[
  {
    "path": ".containerignore",
    "content": "*\n!dist\n"
  },
  {
    "path": ".github/ISSUE_TEMPLATE/blank_issue.md",
    "content": "---\nname: Blank Issue\nabout: Create a blank issue.\n---\n"
  },
  {
    "path": ".github/ISSUE_TEMPLATE/bug.yaml",
    "content": "name: \"\\U0001F41E Bug Report\"\ndescription: \"Create a bug report for Acton.\"\nlabels: [\"bug\"]\nbody:\n  - type: markdown\n    attributes:\n      value: |\n        A bug is when something works differently than it is expected to.\n        ## Remember to search before filing a new report\n        Please search for this bug in the issue tracker, and use a bug report title that would have made your bug report turn up in the search results for your search query.\n  - type: input\n    id: version\n    attributes:\n      label: Acton Version\n      description: \"The output of `acton version`\"\n      placeholder: \"0.16.3\"\n    validations:\n      required: true\n  - type: textarea\n    id: repro\n    attributes:\n      label: Steps to Reproduce and Observed Behavior\n      description: What exactly can someone else do, in order to observe the problem that you observed? Include the output and all error messages.\n    validations:\n      required: true\n  - type: textarea\n    id: expected\n    attributes:\n      label: Expected Behavior\n      description: What did you expect to happen instead?\n    validations:\n      required: true\n"
  },
  {
    "path": ".github/ISSUE_TEMPLATE/config.yml",
    "content": "blank_issues_enabled: true\ncontact_links:\n  - name: 🗣 Ask a Question, Discuss\n    url: https://github.com/actonlang/acton/discussions\n    about: Please ask and answer questions about Acton using GitHub discussions.\n"
  },
  {
    "path": ".github/ISSUE_TEMPLATE/feature.yaml",
    "content": "name: \"\\U0001F680 Feature / Enhancement Request\"\ndescription: \"Suggest a new idea / feature enhancement for Acton.\"\nlabels: [\"enhancement\"]\nbody:\n  - type: markdown\n    attributes:\n      value: |\n        A feature is when you would like to add new functionality or change current functionality / behavior.\n        ## Remember to search before filing a new report\n        Please search for this feature request in the issue tracker, and use a feature request title that would have made your feature request turn up in the search results for your search query.\n  - type: textarea\n    id: repro\n    attributes:\n      label: Proposal\n      description: Provide a clear and concise description of what you want\n    validations:\n      required: true\n  - type: textarea\n    id: expected\n    attributes:\n      label: Motivation\n      description: Explain the problem that your proposal is attempting to address\n    validations:\n      required: true\n  - type: textarea\n    id: actual\n    attributes:\n      label: Alternatives\n      description: What other solutions have you tried or considered?\n    validations:\n      required: true\n"
  },
  {
    "path": ".github/ISSUE_TEMPLATE/ice.yaml",
    "content": "name: \"\\U0001F4A5 Internal Compiler Error\"\ndescription: \"Create a report for an Internal Compiler Error (ICE) in acton.\"\nlabels: [\"bug\", \"Compiler\"]\nbody:\n  - type: markdown\n    attributes:\n      value: |\n        We're sorry to hear you encountered an Internal Compiler Error and thank you for reporting it!\n\n        If possible, try to provide a minimal reproduction case.\n  - type: input\n    id: version\n    attributes:\n      label: Acton Version\n      description: \"The output of `acton version`\"\n      placeholder: \"0.16.3\"\n    validations:\n      required: true\n  - type: textarea\n    id: repro\n    attributes:\n      label: Reproduction code\n      description: What exactly can someone else do, in order to trigger the ICE?\n      placeholder: If possible, try to provide a minimal reproduction case.\n    validations:\n      required: true\n  - type: textarea\n    id: expected\n    attributes:\n      label: Error output\n      description: Include the full output from compiling using `acton`\n      placeholder: |\n        $ ../dist/acton counter_adder.act\n        /home/user/acton/dist/modules/test/counter_adder.c: In function ‘test$counter_adder$$Counter$count$local’:\n        /home/user/acton/dist/modules/test/counter_adder.c:224:9: error: conversion to non-scalar type requested\n          224 |         return (($R)__self__->i);\n              |         ^~~~~~\n        ERROR: internal compiler error: compilation of generated C code failed\n        NOTE: this is likely a bug in acton, please report this at:\n        NOTE: https://github.com/actonlang/acton/issues/new?template=ice.md\n        NOTE: acton 0.5.2.20210904.7.7.37\n        $\n    validations:\n      required: true\n"
  },
  {
    "path": ".github/dependabot.yml",
    "content": "# https://docs.github.com/github/administering-a-repository/configuration-options-for-dependency-updates\nversion: 2\nupdates:\n  - package-ecosystem: \"github-actions\"\n    directory: \"/\" # Location of package manifests\n    schedule:\n      interval: \"weekly\"\n"
  },
  {
    "path": ".github/workflows/claude.yml",
    "content": "name: Claude Code\n\non:\n  issue_comment:\n    types: [created]\n  pull_request_review_comment:\n    types: [created]\n  issues:\n    types: [opened, assigned]\n  pull_request_review:\n    types: [submitted]\n\njobs:\n  claude:\n    if: |\n      (github.event_name == 'issue_comment' && contains(github.event.comment.body, '@claude')) ||\n      (github.event_name == 'pull_request_review_comment' && contains(github.event.comment.body, '@claude')) ||\n      (github.event_name == 'pull_request_review' && contains(github.event.review.body, '@claude')) ||\n      (github.event_name == 'issues' && (contains(github.event.issue.body, '@claude') || contains(github.event.issue.title, '@claude')))\n    runs-on: ubuntu-latest\n    permissions:\n      contents: read\n      pull-requests: read\n      issues: read\n      id-token: write\n    steps:\n      - name: Checkout repository\n        uses: actions/checkout@v6\n        with:\n          fetch-depth: 1\n\n      - name: Run Claude Code\n        id: claude\n        uses: anthropics/claude-code-action@beta\n        with:\n          anthropic_api_key: ${{ secrets.ANTHROPIC_API_KEY }}\n\n"
  },
  {
    "path": ".github/workflows/code-agent.yml",
    "content": "name: Code Agent\n\npermissions:\n  contents: write\n  pull-requests: write\n  issues: write\n\non:\n  issues:\n    types: [opened]\n  issue_comment:\n    types: [created]\n  pull_request_review_comment:\n    types: [created]\n\njobs:\n  code-agent:\n    runs-on: ubuntu-latest\n    if: ${{ github.event.sender.type != 'Bot' }}\n    steps:\n      - uses: potproject/code-agent@main\n        with:\n          github-token: ${{ secrets.GITHUB_TOKEN }}\n\n          # [Claude Code Settings]\n          anthropic-api-key: ${{ secrets.ANTHROPIC_API_KEY }}\n\n          # [Optional Claude Code Settings]\n          # anthropic-base-url: \"https://api.anthropic.com\"\n          # anthropic-model: \"claude-3-7-sonnet-20250219\"\n          # anthropic-small-fast-model: \"claude-3-5-haiku-20241022\"\n          # claude-code-use-bedrock: \"1\"\n          # anthropic-bedrock-base-url: \"https://bedrock.us-east-1.amazonaws.com\"\n          # aws-access-key-id: ${{ secrets.AWS_ACCESS_KEY_ID }}\n          # aws-secret-access-key: ${{ secrets.AWS_SECRET_ACCESS_KEY }}\n          # aws-region: \"us-east-1\"\n          # disable-prompt-caching: \"1\"\n\n          # [Codex Settings]\n          openai-api-key: ${{ secrets.OPENAI_API_KEY }}\n\n          # [Optional Codex Settings]\n          # openai-base-url: \"https://api.openai.com\"\n"
  },
  {
    "path": ".github/workflows/create-release.yml",
    "content": "name: Create Release Branch\n\non:\n  workflow_dispatch:\n    inputs:\n      release_type:\n        description: 'Release Type'\n        required: true\n        type: choice\n        options:\n          - major\n          - minor\n          - patch\n        default: 'patch'\n\njobs:\n  create-release-branch:\n    runs-on: ubuntu-latest\n    steps:\n      - name: Checkout code\n        uses: actions/checkout@v6\n        with:\n          ssh-key: ${{ secrets.ACTONBOT_DEPLOY_KEY }}\n          fetch-depth: 0\n\n      - name: Set up Git user\n        run: |\n          git config user.name \"Acton Bot\"\n          git config user.email apt@acton-lang.org\n\n      - name: Get current version\n        id: current_version\n        run: |\n          VERSION=$(grep \"^VERSION=\" version.mk | cut -d= -f2)\n          echo \"Current version: $VERSION\"\n          echo \"version=$VERSION\" >> $GITHUB_OUTPUT\n\n          # Split version\n          MAJOR=$(echo $VERSION | cut -d. -f1)\n          MINOR=$(echo $VERSION | cut -d. -f2)\n          PATCH=$(echo $VERSION | cut -d. -f3)\n\n          echo \"major=$MAJOR\" >> $GITHUB_OUTPUT\n          echo \"minor=$MINOR\" >> $GITHUB_OUTPUT\n          echo \"patch=$PATCH\" >> $GITHUB_OUTPUT\n\n      - name: Calculate new version\n        id: new_version\n        run: |\n          MAJOR=${{ steps.current_version.outputs.major }}\n          MINOR=${{ steps.current_version.outputs.minor }}\n          PATCH=${{ steps.current_version.outputs.patch }}\n\n          if [[ \"${{ github.event.inputs.release_type }}\" == \"major\" ]]; then\n            MAJOR=$((MAJOR + 1))\n            MINOR=0\n            PATCH=0\n          elif [[ \"${{ github.event.inputs.release_type }}\" == \"minor\" ]]; then\n            MINOR=$((MINOR + 1))\n            PATCH=0\n          else # patch\n            PATCH=$((PATCH + 1))\n          fi\n\n          NEW_VERSION=\"${MAJOR}.${MINOR}.${PATCH}\"\n          echo \"New version: $NEW_VERSION\"\n          echo \"version=$NEW_VERSION\" >> $GITHUB_OUTPUT\n\n      - name: Update version in version.mk\n        run: |\n          NEW_VERSION=${{ steps.new_version.outputs.version }}\n          sed -i \"s/^VERSION=.*/VERSION=${NEW_VERSION}/\" version.mk\n\n      - name: Update CHANGELOG.md\n        run: |\n          NEW_VERSION=${{ steps.new_version.outputs.version }}\n          TODAY=$(date +%Y-%m-%d)\n\n          # Replace [Unreleased] with the new version\n          sed -i \"s/## \\[Unreleased\\]/## [${NEW_VERSION}] - ${TODAY}/\" CHANGELOG.md\n\n      - name: Create and push release branch\n        run: |\n          NEW_VERSION=${{ steps.new_version.outputs.version }}\n          BRANCH_NAME=\"release-v${NEW_VERSION}\"\n\n          git checkout -b $BRANCH_NAME\n          git add version.mk CHANGELOG.md\n          git commit -m \"Release version ${NEW_VERSION}\"\n          git push origin $BRANCH_NAME\n\n          echo \"::notice::Created release branch $BRANCH_NAME with version $NEW_VERSION\"\n\n      - name: Create pull request\n        env:\n          GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}\n        run: |\n          NEW_VERSION=${{ steps.new_version.outputs.version }}\n          BRANCH_NAME=\"release-v${NEW_VERSION}\"\n\n          gh pr create \\\n            --title \"Release v${NEW_VERSION}\" \\\n            --base main \\\n            --head $BRANCH_NAME \\\n            --body \"This PR updates the version to ${NEW_VERSION} and prepares the CHANGELOG.md for release.\"\n"
  },
  {
    "path": ".github/workflows/release.yml",
    "content": "name: Add git tag for release\n\non:\n  pull_request:\n    types:\n      - closed\n\njobs:\n  if_merged:\n    # name should be e.g. release-v1.2.3\n    if: ${{ startsWith(github.head_ref, 'release-v') && github.event.pull_request.merged == true }}\n    runs-on: ubuntu-latest\n    steps:\n      - run: |\n          echo The PR was merged\n      - name: \"Check out repository code\"\n        uses: actions/checkout@v6\n        with:\n          ssh-key: ${{ secrets.ACTONBOT_DEPLOY_KEY }}\n      - name: \"Get the version\"\n        id: get_version\n        run: echo \"version=$(grep VERSION= version.mk | cut -d = -f 2)\" >> $GITHUB_OUTPUT\n      - name: \"Add version tag and push\"\n        run: |\n          git config user.name \"Apt Bot\"\n          git config user.email apt@acton-lang.org\n          git tag v${{steps.get_version.outputs.version}}\n          git push origin v${{steps.get_version.outputs.version}}\n"
  },
  {
    "path": ".github/workflows/test-app.yml",
    "content": "\non:\n  workflow_call:\n    inputs:\n      repo_url:\n        required: true\n        type: string\n      arch:\n        required: false\n        type: string\n        default: \"amd64\"\n\njobs:\n  test-app:\n    runs-on: ubuntu-24.04${{ inputs.arch == 'arm64' && '-arm' || '' }}\n    steps:\n      - name: \"Install gdb\"\n        run: |\n          sudo apt update\n          sudo apt install -y gdb\n      - name: \"Download .deb files\"\n        uses: actions/download-artifact@v8\n        with:\n          name: acton-debs-${{ inputs.arch }}\n      - name: \"Install acton from .deb\"\n        run: |\n          sudo apt install -y ./deb/acton_*.deb\n          acton version\n      - name: \"Clone app repo\"\n        uses: actions/checkout@v6\n        with:\n          repository: ${{ inputs.repo_url }}\n          path: app\n      - name: \"Compile acton program\"\n        run: |\n          cd app\n          acton build\n          acton test\n          acton test perf\n"
  },
  {
    "path": ".github/workflows/test.yml",
    "content": "name: Build, Test & Release\n\n# Build, Test & Release (BTR) run for:\n# - pushes to the main branch\n# - new tags are pushed\n# - for pull requests\n#\n# Releases are tagged with vX.Y.Z. We determine if we are building for a release\n# or not by looking if the tag name starts with 'v'.\n#\n# To release:\n# - create new branch using name: release-vX.Y.Z\n# - update version in version.mk\n# - update CHANGELOG.md, second entry must equal version in version.mk\n#   - first entry is assumed to be \"Unreleased\"\n# - push a tag like vX.Y.Z which is equal to version in version.mk\n#\n\non:\n  pull_request:\n  push:\n    branches:\n      - main\n    tags:\n      - v*\n  schedule:\n    # Schedule to run daily\n    - cron: '4 0 * * *'\n\nenv:\n  ZIG_DOWNLOAD_BASE_URL: https://github.com/actonlang/zigballs/raw/main\n\n# NOTE: Jobs for version tagged releases just pattern match on any tag starting\n# with 'v'. That's probably a version tag, but could be something else. Is there\n# a better way to match?\n\njobs:\n  build-version:\n    runs-on: ubuntu-latest\n    outputs:\n      build_time: ${{ steps.setver.outputs.build_time }}\n    steps:\n      - name: \"Set consistent build time\"\n        id: setver\n        run: echo \"build_time=$(date -u '+%Y%m%d.%-H.%-M')\" >> \"$GITHUB_OUTPUT\"\n\n  matrix_maker_macos:\n    runs-on: ubuntu-latest\n    outputs:\n      matrix: ${{ steps.setmatrix.outputs.matrix }}\n    steps:\n      - name: \"Set Matrix for PR or push\"\n        # Keep PR matrix minimal; extra entries increase cache pressure and slow PR workflows.\n        if: github.event_name != 'schedule'\n        id: setmatrix_pr\n        run: |\n          MATRIX_JSON='{\\\"include\\\":[{\\\"os\\\":\\\"macos\\\",\\\"version\\\":\\\"15\\\",\\\"arch\\\":\\\"aarch64\\\",\\\"cache\\\":true},{\\\"os\\\":\\\"macos\\\",\\\"version\\\":\\\"15\\\",\\\"arch\\\":\\\"x86_64\\\",\\\"cache\\\":true},{\\\"os\\\":\\\"macos\\\",\\\"version\\\":\\\"26\\\",\\\"arch\\\":\\\"aarch64\\\",\\\"cache\\\":true}]}'\n          echo \"matrix=$MATRIX_JSON\" >> $GITHUB_OUTPUT\n\n      - name: \"Set Matrix for nightly run\"\n        if: github.event_name == 'schedule'\n        id: setmatrix_cron\n        run: |\n          MATRIX_JSON='{\\\"include\\\":[{\\\"os\\\":\\\"macos\\\",\\\"version\\\":\\\"15\\\",\\\"arch\\\":\\\"aarch64\\\",\\\"cache\\\":true},{\\\"os\\\":\\\"macos\\\",\\\"version\\\":\\\"15\\\",\\\"arch\\\":\\\"x86_64\\\",\\\"cache\\\":true},{\\\"os\\\":\\\"macos\\\",\\\"version\\\":\\\"26\\\",\\\"arch\\\":\\\"aarch64\\\",\\\"cache\\\":true}]}'\n          echo \"matrix=$MATRIX_JSON\" >> $GITHUB_OUTPUT\n\n      - name: \"Set final matrix output\"\n        id: setmatrix\n        run: |\n          if [ \"${{ github.event_name }}\" == \"schedule\" ]; then\n            echo \"matrix=${{ steps.setmatrix_cron.outputs.matrix }}\" >> $GITHUB_OUTPUT\n          else\n            echo \"matrix=${{ steps.setmatrix_pr.outputs.matrix }}\" >> $GITHUB_OUTPUT\n          fi\n\n      - name: \"Debug: Print matrix JSON\"\n        run: |\n          echo \"Matrix JSON:\"\n          echo '${{ toJson(fromJson(steps.setmatrix.outputs.matrix)) }}'\n          echo \"Event name: ${{ github.event_name }}\"\n\n  test-macos:\n    needs: [build-version, matrix_maker_macos]\n    strategy:\n      fail-fast: false\n      matrix: ${{ fromJson(needs.matrix_maker_macos.outputs.matrix) }}\n    runs-on: ${{ (matrix.version == '15' && matrix.arch == 'x86_64') && 'macos-15-intel' || format('{0}-{1}', matrix.os, matrix.version) }}\n    env:\n      BUILD_TIME: ${{ needs.build-version.outputs.build_time }}\n    steps:\n      - name: \"Show env\"\n        run: env\n      - name: \"Set BUILD_RELEASE when we are building for a version tag\"\n        run: |\n          echo \"BUILD_RELEASE=1\" >> $GITHUB_ENV\n        if: startsWith(github.ref, 'refs/tags/v')\n      - name: \"Enable dumping core files\"\n        run: |\n          sudo sysctl kern.corefile=core.%P\n          ulimit -c unlimited\n      - name: \"Check out repository code\"\n        uses: actions/checkout@v6\n      - name: \"Cache stuff\"\n        if: matrix.cache == true\n        uses: actions/cache@v5\n        with:\n          path: |\n            ~/.stack\n          key: test-${{ matrix.os }}-${{ matrix.version }}-${{ matrix.arch }}-${{ hashFiles('compiler/stack.yaml', 'compiler/stack.yaml.lock', 'Makefile', 'compiler/tools/*.sh') }}\n      - name: \"Cache Acton\"\n        if: matrix.cache == true\n        uses: actions/cache@v5\n        with:\n          path: |\n            ~/.cache/acton/\n          key: test-${{ matrix.os }}-${{ matrix.version }}-${{ matrix.arch }}-acton\n      - name: \"Install build prerequisites\"\n        run: brew install haskell-stack\n      - name: \"Build Acton\"\n        run: |\n          make -j2 -C ${{ github.workspace }} BUILD_RELEASE=${{ env.BUILD_RELEASE }} BUILD_TIME=${BUILD_TIME}\n      - name: \"Build a release\"\n        run: make -C ${{ github.workspace }} release BUILD_TIME=${BUILD_TIME}\n      - name: \"Upload artifact\"\n        uses: actions/upload-artifact@v7\n        with:\n          name: acton-${{ matrix.os }}-${{ matrix.version }}-${{ matrix.arch }}\n          path: ${{ github.workspace }}/acton-*\n          if-no-files-found: error\n      - name: \"Run tests\"\n        env:\n          # Package manager uses token to make authenticated requests to GitHub REST API, avoiding rate limits\n          GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}\n        run: |\n          ulimit -c unlimited\n          make -C ${{ github.workspace }} test\n          make -C ${{ github.workspace }} online-tests\n      - name: \"Upload whole test dir as artifact on test failure\"\n        if: failure()\n        uses: actions/upload-artifact@v7\n        with:\n          name: test-debug-${{ matrix.os }}-${{ matrix.version }}-${{ matrix.arch }}-${{ github.run_id }}.zip\n          path: |\n            ${{ github.workspace }}/test\n\n\n  matrix_maker_linux:\n    runs-on: ubuntu-latest\n    outputs:\n      matrix: ${{ steps.setmatrix.outputs.matrix }}\n    steps:\n      - name: \"Set Matrix for PR or push\"\n        # Keep PR matrix minimal; extra entries increase cache pressure and slow PR workflows.\n        if: github.event_name != 'schedule'\n        id: setmatrix_pr\n        run: |\n          MATRIX_JSON='{\\\"include\\\":[{\\\"os\\\":\\\"debian\\\",\\\"version\\\":\\\"11\\\",\\\"arch\\\":\\\"x86_64\\\",\\\"cache\\\":true},{\\\"os\\\":\\\"ubuntu\\\",\\\"version\\\":\\\"24.04\\\",\\\"arch\\\":\\\"arm64v8\\\",\\\"cache\\\":true}]}'\n          echo \"matrix=$MATRIX_JSON\" >> $GITHUB_OUTPUT\n\n      - name: \"Set Matrix for nightly run\"\n        if: github.event_name == 'schedule'\n        id: setmatrix_cron\n        run: |\n          MATRIX_JSON='{\\\"include\\\":[{\\\"os\\\":\\\"debian\\\",\\\"version\\\":\\\"11\\\",\\\"arch\\\":\\\"x86_64\\\",\\\"cache\\\":true},{\\\"os\\\":\\\"debian\\\",\\\"version\\\":\\\"12\\\",\\\"arch\\\":\\\"x86_64\\\",\\\"cache\\\":false},{\\\"os\\\":\\\"debian\\\",\\\"version\\\":\\\"13\\\",\\\"arch\\\":\\\"x86_64\\\",\\\"cache\\\":false},{\\\"os\\\":\\\"ubuntu\\\",\\\"version\\\":\\\"22.04\\\",\\\"arch\\\":\\\"x86_64\\\",\\\"cache\\\":false},{\\\"os\\\":\\\"ubuntu\\\",\\\"version\\\":\\\"24.04\\\",\\\"arch\\\":\\\"x86_64\\\",\\\"cache\\\":false},{\\\"os\\\":\\\"ubuntu\\\",\\\"version\\\":\\\"24.04\\\",\\\"arch\\\":\\\"arm64v8\\\",\\\"cache\\\":true}]}'\n          echo \"matrix=$MATRIX_JSON\" >> $GITHUB_OUTPUT\n\n      - name: \"Set final matrix output\"\n        id: setmatrix\n        run: |\n          if [ \"${{ github.event_name }}\" == \"schedule\" ]; then\n            echo \"matrix=${{ steps.setmatrix_cron.outputs.matrix }}\" >> $GITHUB_OUTPUT\n          else\n            echo \"matrix=${{ steps.setmatrix_pr.outputs.matrix }}\" >> $GITHUB_OUTPUT\n          fi\n\n      - name: \"Debug: Print matrix JSON\"\n        run: |\n          echo \"Matrix JSON:\"\n          echo '${{ toJson(fromJson(steps.setmatrix.outputs.matrix)) }}'\n          echo \"Event name: ${{ github.event_name }}\"\n\n  test-linux:\n    needs: [build-version, matrix_maker_linux]\n    strategy:\n      fail-fast: false\n      matrix: ${{ fromJson(needs.matrix_maker_linux.outputs.matrix) }}\n    runs-on: ubuntu-24.04${{ matrix.arch == 'arm64v8' && '-arm' || '' }}\n    container:\n      image: ${{ matrix.os }}:${{ matrix.version }}\n    env:\n      LANG: en_US.UTF-8\n      LC_ALL: en_US.UTF-8\n      BUILD_TIME: ${{ needs.build-version.outputs.build_time }}\n    steps:\n      - name: \"Show platform and environment\"\n        run: |\n          uname -a\n          env\n          cat /proc/cpuinfo\n      - name: \"Set BUILD_RELEASE when we are building for a version tag\"\n        if: startsWith(github.ref, 'refs/tags/v')\n        run: |\n          echo \"BUILD_RELEASE=1\" >> $GITHUB_ENV\n      - name: \"Check out repository code\"\n        uses: actions/checkout@v6\n      - name: \"Cache stuff\"\n        if: matrix.cache == true\n        uses: actions/cache@v5\n        with:\n          path: |\n            ~/.stack\n          key: test-${{ matrix.os }}-${{ matrix.version }}-${{ matrix.arch }}-${{ hashFiles('compiler/stack.yaml', 'compiler/stack.yaml.lock', 'Makefile', 'compiler/tools/*.sh') }}\n      - name: \"chown our home dir to avoid stack complaining\"\n        run: chown -R root:root /github/home\n      - name: \"Install build prerequisites\"\n        run: |\n          export DEBIAN_FRONTEND=noninteractive\n          apt-get update\n          apt-get install -qy bzip2 curl g++ haskell-stack libgmp-dev libncurses-dev make procps zlib1g-dev\n          apt-get install -qy gdb\n      - name: \"locale en_US.UTF-8\"\n        run: |\n          apt-get install -qy locales\n          locale-gen en_US.UTF-8\n          echo \"locales locales/default_environment_locale select en_US.UTF-8\" | debconf-set-selections\n          echo \"locales locales/locales_to_be_generated multiselect en_US.UTF-8 UTF-8\" | debconf-set-selections\n          rm \"/etc/locale.gen\"\n          dpkg-reconfigure --frontend noninteractive locales\n      - name: \"Install newer stack\"\n        run: |\n          STACK_VERSION=3.9.3\n          ARCH=\"$(uname -m)\"\n          case \"${ARCH}\" in\n            x86_64) STACK_ARCH=\"x86_64\" ;;\n            aarch64|arm64) STACK_ARCH=\"aarch64\" ;;\n            *) echo \"Unsupported arch: ${ARCH}\" >&2; exit 1 ;;\n          esac\n          STACK_TAR=\"stack-${STACK_VERSION}-linux-${STACK_ARCH}.tar.gz\"\n          STACK_URL=\"https://github.com/commercialhaskell/stack/releases/download/v${STACK_VERSION}/${STACK_TAR}\"\n          mkdir -p \"${HOME}/.local/bin\"\n          curl -fsSL \"${STACK_URL}\" -o /tmp/stack.tgz\n          tar -xzf /tmp/stack.tgz -C /tmp\n          install -m 0755 \"/tmp/stack-${STACK_VERSION}-linux-${STACK_ARCH}/stack\" \"${HOME}/.local/bin/stack\"\n          echo \"${HOME}/.local/bin\" >> \"$GITHUB_PATH\"\n          \"${HOME}/.local/bin/stack\" --version\n      - name: \"Use container glibc target for source build\"\n        run: |\n          GLIBC_VERSION=\"$(getconf GNU_LIBC_VERSION | awk '{print $2}')\"\n          echo \"ACTON_ZIG_GLIBC_VERSION=${GLIBC_VERSION}\" >> \"$GITHUB_ENV\"\n          echo \"Using Zig glibc target ${GLIBC_VERSION}\"\n      - name: \"Build Acton\"\n        run: |\n          make -j2 -C ${GITHUB_WORKSPACE} BUILD_RELEASE=${{ env.BUILD_RELEASE }} BUILD_TIME=${BUILD_TIME}\n      - name: \"Build a release\"\n        run: make -C ${GITHUB_WORKSPACE} release BUILD_TIME=${BUILD_TIME}\n      - name: \"Upload artifact\"\n        uses: actions/upload-artifact@v7\n        with:\n          name: acton-${{ matrix.os }}-${{ matrix.version }}-${{ matrix.arch }}\n          path: ${{ github.workspace }}/acton-*\n          if-no-files-found: error\n      - name: \"Run tests\"\n        run: |\n          ulimit -c unlimited\n          make -C ${GITHUB_WORKSPACE} test\n          make -C ${GITHUB_WORKSPACE} online-tests\n      - name: \"Upload whole test dir as artifact on test failure\"\n        if: failure()\n        uses: actions/upload-artifact@v7\n        with:\n          name: test-debug-${{ matrix.os }}-${{ matrix.version }}-${{ matrix.arch }}-${{ github.run_id }}.zip\n          path: |\n            ${{ github.workspace }}/test\n\n\n  build-debs:\n    needs: build-version\n    strategy:\n      fail-fast: false\n      matrix:\n        arch: [amd64, arm64]\n    runs-on: ${{ matrix.arch == 'amd64' && 'ubuntu-24.04' || 'ubuntu-24.04-arm' }}\n    container:\n      image: debian:11\n    env:\n      LANG: en_US.UTF-8\n      LC_ALL: en_US.UTF-8\n      BUILD_TIME: ${{ needs.build-version.outputs.build_time }}\n      HOME: /tmp/acton-gh-home\n      STACK_ROOT: /tmp/acton-gh-home/.stack\n    steps:\n      - name: \"Show platform and environment\"\n        run: |\n          env\n          ldd --version | head -n1\n          cat /proc/cpuinfo\n          uname -a\n      - name: \"Set BUILD_RELEASE when we are building for a version tag\"\n        run: |\n          echo \"BUILD_RELEASE=1\" >> $GITHUB_ENV\n        if: startsWith(github.ref, 'refs/tags/v')\n      - name: \"Install build prerequisites\"\n        run: |\n          apt-get update\n          apt-get install -qy bzip2 curl g++ haskell-stack libgmp-dev libncurses-dev make procps zlib1g-dev\n          apt-get install -qy bash-completion build-essential debhelper devscripts\n      - name: \"Prepare stack directories\"\n        run: |\n          mkdir -p \"${HOME}/.local/bin\" \"${STACK_ROOT}\"\n      - name: \"Check out repository code\"\n        uses: actions/checkout@v6\n      - name: \"Cache stuff\"\n        uses: actions/cache@v5\n        with:\n          path: |\n            ${{ env.STACK_ROOT }}\n          key: build-debs-${{ matrix.arch }}-${{ hashFiles('compiler/stack.yaml', 'compiler/stack.yaml.lock', 'Makefile', 'compiler/tools/*.sh', 'debian/control') }}\n      - name: \"locale en_US.UTF-8\"\n        run: |\n          apt-get install -qy locales\n          locale-gen en_US.UTF-8\n          echo \"locales locales/default_environment_locale select en_US.UTF-8\" | debconf-set-selections\n          echo \"locales locales/locales_to_be_generated multiselect en_US.UTF-8 UTF-8\" | debconf-set-selections\n          rm \"/etc/locale.gen\"\n          dpkg-reconfigure --frontend noninteractive locales\n      - name: \"Install newer stack\"\n        run: |\n          STACK_VERSION=3.9.3\n          ARCH=\"$(uname -m)\"\n          case \"${ARCH}\" in\n            x86_64) STACK_ARCH=\"x86_64\" ;;\n            aarch64|arm64) STACK_ARCH=\"aarch64\" ;;\n            *) echo \"Unsupported arch: ${ARCH}\" >&2; exit 1 ;;\n          esac\n          STACK_TAR=\"stack-${STACK_VERSION}-linux-${STACK_ARCH}.tar.gz\"\n          STACK_URL=\"https://github.com/commercialhaskell/stack/releases/download/v${STACK_VERSION}/${STACK_TAR}\"\n          curl -fsSL \"${STACK_URL}\" -o /tmp/stack.tgz\n          tar -xzf /tmp/stack.tgz -C /tmp\n          install -m 0755 \"/tmp/stack-${STACK_VERSION}-linux-${STACK_ARCH}/stack\" \"${HOME}/.local/bin/stack\"\n          echo \"${HOME}/.local/bin\" >> \"$GITHUB_PATH\"\n          \"${HOME}/.local/bin/stack\" --version\n      - name: \"Build Debian packages\"\n        shell: bash\n        run: |\n          set -euo pipefail\n          make -C \"${GITHUB_WORKSPACE}\" debs BUILD_RELEASE=${{ env.BUILD_RELEASE }} BUILD_TIME=${BUILD_TIME}\n      - name: \"Show packaged Acton linkage\"\n        shell: bash\n        run: |\n          set -euo pipefail\n          make -C \"${GITHUB_WORKSPACE}\" ldd\n          deb=\"$(ls \"${GITHUB_WORKSPACE}\"/../acton_*.deb | head -n1)\"\n          dpkg-deb -I \"$deb\"\n          tmp=\"$(mktemp -d)\"\n          dpkg-deb -x \"$deb\" \"$tmp\"\n          bins=\"$tmp/usr/lib/acton/bin/acton\"\n          bins=\"$bins $tmp/usr/lib/acton/bin/lsp-server-acton\"\n          bins=\"$bins $tmp/usr/lib/acton/bin/actondb\"\n          make -C \"${GITHUB_WORKSPACE}\" ldd ACTON_LINKAGE_BINS=\"$bins\"\n      - name: \"Compute variables\"\n        id: vars\n        run: |\n          echo \"debdir=$(realpath ${GITHUB_WORKSPACE}/../deb)\" >> $GITHUB_OUTPUT\n          echo \"artifact_dir=$(dirname ${{ github.workspace }})\" >> $GITHUB_OUTPUT\n      - name: \"Move deb files into place for easy artifact extraction\"\n        run: |\n          mkdir -p ${{ steps.vars.outputs.debdir }}\n          ls ${{ steps.vars.outputs.debdir }}/../\n          mv ${{ steps.vars.outputs.debdir }}/../acton_* ${{ steps.vars.outputs.debdir }}/\n      - name: \"Upload artifact\"\n        uses: actions/upload-artifact@v7\n        with:\n          name: acton-debs-${{ matrix.arch }}\n          # Using a wildcard and then deb here to force the entire directory to\n          # be part of resulting artifact.\n          path: ${{ steps.vars.outputs.artifact_dir }}/*deb/\n          if-no-files-found: error\n\n\n  run-macos:\n    needs: test-macos\n    strategy:\n      fail-fast: false\n      matrix:\n        os: [macos-15, macos-15-intel, macos-26]\n    runs-on: ${{ matrix.os }}\n    steps:\n      - name: \"Machine info\"\n        run: |\n          uname -a\n          system_profiler SPHardwareDataType\n      - name: \"Download artifacts for Macos arm64, built on macos-15\"\n        if: ${{ matrix.os == 'macos-15' || matrix.os == 'macos-26' }}\n        uses: actions/download-artifact@v8\n        with:\n          name: acton-macos-15-aarch64\n      - name: \"Download artifacts for Macos x86_64, built on macos-15\"\n        if: ${{ matrix.os == 'macos-15-intel' }}\n        uses: actions/download-artifact@v8\n        with:\n          name: acton-macos-15-x86_64\n      - name: \"Extract acton\"\n        run: |\n          tar Jxf $(ls acton-macos-*.tar.xz | tail -n1)\n      - name: \"Compile acton program\"\n        run: |\n          export PATH=$(pwd)/acton/bin:$PATH\n          acton version\n          echo '#!/usr/bin/env runacton'   > acton-test.act\n          echo 'actor main(env):'          >> acton-test.act\n          echo '    print(\"Hello, world\")' >> acton-test.act\n          echo '    env.exit(0)'           >> acton-test.act\n          chmod a+x acton-test.act\n          ./acton-test.act\n          ./acton-test.act | grep \"Hello, world\"\n          acton build acton-test.act\n          ./acton-test\n          ./acton-test | grep \"Hello, world\"\n\n\n  run-linux:\n    needs: build-debs\n    strategy:\n      fail-fast: false\n      matrix:\n        include:\n          - os: \"debian\"\n            version: \"11\"\n            arch: \"amd64\"\n          - os: \"debian\"\n            version: \"12\"\n            arch: \"amd64\"\n          - os: \"ubuntu\"\n            version: \"20.04\"\n            arch: \"amd64\"\n          - os: \"ubuntu\"\n            version: \"22.04\"\n            arch: \"amd64\"\n          - os: \"ubuntu\"\n            version: \"24.04\"\n            arch: \"amd64\"\n          - os: \"ubuntu\"\n            version: \"24.04\"\n            arch: \"arm64\"\n          - os: \"ubuntu\"\n            version: \"24.04\"\n            arch: \"amd64\"\n            target: \"x86_64-linux-musl\"\n          - os: \"ubuntu\"\n            version: \"24.04\"\n            arch: \"arm64\"\n            target: \"aarch64-linux-musl\"\n    env:\n      # This makes it possible for the GitHub Action itself to run using an\n      # older version of node, which is the only possibility to get it running\n      # on Ubuntu 18.04 (in the matrix above)\n      ACTIONS_RUNNER_FORCE_ACTIONS_NODE_VERSION: node16\n      ACTIONS_ALLOW_USE_UNSECURE_NODE_VERSION: true\n    runs-on: ${{ matrix.arch == 'amd64' && 'ubuntu-latest' || 'ubuntu-24.04-arm' }}\n    container:\n      image: ${{ matrix.os }}:${{ matrix.version }}\n      options: --privileged --ulimit core=-1 --security-opt seccomp=unconfined\n    steps:\n      - name: \"Show platform and environment\"\n        run: |\n          env\n          cat /proc/cpuinfo\n      - name: \"Download .deb files\"\n        uses: actions/download-artifact@v8\n        with:\n          name: acton-debs-${{ matrix.arch }}\n      - name: \"Install acton from .deb\"\n        run: |\n          apt update\n          apt install -y ./deb/acton_*.deb\n          acton version\n      - name: \"Enable dumping core files to /tmp/core...\"\n        run: |\n          apt install -qy procps\n          cat /proc/sys/kernel/core_pattern\n          sysctl kernel.core_pattern='/tmp/core.%h.%e.%t' || true\n          cat /proc/sys/kernel/core_pattern\n          ulimit -c unlimited\n      - name: \"Compile acton program\"\n        run: |\n          echo '#!/usr/bin/env runacton'   > acton-test.act\n          echo 'actor main(env):'          >> acton-test.act\n          echo '    print(\"Hello, world\")' >> acton-test.act\n          echo '    env.exit(0)'           >> acton-test.act\n          chmod a+x acton-test.act\n          ./acton-test.act\n          ./acton-test.act | grep \"Hello, world\"\n          acton build ${{ matrix.target && format('--target {0}', matrix.target) || '' }} acton-test.act\n          ./acton-test\n          ./acton-test | grep \"Hello, world\"\n      - name: \"ls core\"\n        if: failure()\n        run: |\n          pwd\n          ls\n          find /tmp\n          mv /tmp/core* .\n      - name: \"Upload core file & binaries as artifacts on test failure\"\n        if: failure()\n        uses: actions/upload-artifact@v7\n        with:\n          name: coredumps-${{ matrix.os }}-${{ matrix.version }}-${{ github.run_id }}.zip\n          path: |\n            ${{ github.workspace }}/core*\n\n  perf-vs-main:\n    needs: build-debs\n    # Use our own runner to get more deterministic results\n    runs-on: [self-hosted, linux, X64]\n    steps:\n      - name: \"Check out repository code\"\n        uses: actions/checkout@v6\n      - name: \"Remove any currently install Acton to ensure clean slate\"\n        run: |\n          sudo apt-get purge -qy acton\n      - name: \"Install Acton from APT tip repo\"\n        run: |\n          wget -q -O - https://apt.acton-lang.io/acton.gpg | sudo apt-key add -\n          echo \"deb http://aptip.acton-lang.io/ tip main\" | sudo tee /etc/apt/sources.list.d/acton.list\n          sudo apt-get update\n          sudo apt-get install -qy acton\n          acton version\n      - name: \"Run perf tests and record\"\n        run: |\n          acton version\n          cd test/stdlib_tests\n          acton test perf --record\n          cd ../perf\n          acton test perf --record\n      - name: \"Download .deb files\"\n        uses: actions/download-artifact@v8\n        with:\n          name: acton-debs-amd64\n      - name: \"Install acton from .deb\"\n        run: |\n          sudo dpkg -i ./deb/acton_*.deb\n          acton version\n      - name: \"Run perf tests to compare\"\n        run: |\n          cd test/stdlib_tests\n          rm -rf out\n          acton test perf\n          cd ../perf\n          rm -rf out\n          acton test perf\n\n  test-app-sorespo:\n    strategy:\n      fail-fast: false\n      matrix:\n        arch: [amd64, arm64]\n    needs: build-debs\n    uses: \"./.github/workflows/test-app.yml\"\n    with:\n      repo_url: \"orchestron-orchestrator/sorespo\"\n      arch: ${{ matrix.arch }}\n\n  test-app-orchestron:\n    needs: build-debs\n    uses: \"./.github/workflows/test-app.yml\"\n    with:\n      repo_url: \"orchestron-orchestrator/orchestron\"\n\n  test-app-netcli:\n    needs: build-debs\n    uses: \"./.github/workflows/test-app.yml\"\n    with:\n      repo_url: \"orchestron-orchestrator/netcli\"\n\n  test-app-netclics:\n    needs: build-debs\n    uses: \"./.github/workflows/test-app.yml\"\n    with:\n      repo_url: \"orchestron-orchestrator/netclics\"\n\n  test-app-snappy:\n    needs: build-debs\n    uses: \"./.github/workflows/test-app.yml\"\n    with:\n      repo_url: \"actonlang/acton-snappy\"\n\n  test-app-yang:\n    needs: build-debs\n    uses: \"./.github/workflows/test-app.yml\"\n    with:\n      repo_url: \"orchestron-orchestrator/acton-yang\"\n\n  test-app-actmf:\n    needs: build-debs\n    uses: \"./.github/workflows/test-app.yml\"\n    with:\n      repo_url: \"orchestron-orchestrator/actmf\"\n\n  test-app-ncurl:\n    needs: build-debs\n    uses: \"./.github/workflows/test-app.yml\"\n    with:\n      repo_url: \"orchestron-orchestrator/ncurl\"\n\n  test-app-gnmi:\n    needs: build-debs\n    uses: \"./.github/workflows/test-app.yml\"\n    with:\n      repo_url: \"orchestron-orchestrator/acton-gnmi\"\n\n  test-app-actxcrypt:\n    needs: build-debs\n    uses: \"./.github/workflows/test-app.yml\"\n    with:\n      repo_url: \"orchestron-orchestrator/actxcrypt\"\n\n  test-app-orchino:\n    needs: build-debs\n    uses: \"./.github/workflows/test-app.yml\"\n    with:\n      repo_url: \"orchestron-orchestrator/orchino\"\n\n  test-app-lmdb:\n    needs: build-debs\n    uses: \"./.github/workflows/test-app.yml\"\n    with:\n      repo_url: \"orchestron-orchestrator/acton-lmdb\"\n\n  test-app-zlib:\n    needs: build-debs\n    uses: \"./.github/workflows/test-app.yml\"\n    with:\n      repo_url: \"actonlang/acton-zlib\"\n\n  test-app-http2:\n    needs: build-debs\n    uses: \"./.github/workflows/test-app.yml\"\n    with:\n      repo_url: \"actonlang/acton-http2\"\n\n  build-container-image:\n    needs: [test-macos, test-linux, build-debs]\n    runs-on: ubuntu-latest\n    permissions:\n      contents: read\n      packages: write\n    steps:\n      - name: \"Check out repository code\"\n        uses: actions/checkout@v6\n      - name: \"Download deb artifacts\"\n        uses: actions/download-artifact@v8\n        with:\n          pattern: acton-debs-*\n          merge-multiple: true\n      - name: \"Prepare debs for container build\"\n        run: |\n          set -euo pipefail\n          deb_amd64=$(ls deb/acton_*amd64.deb | head -n1)\n          deb_arm64=$(ls deb/acton_*arm64.deb | head -n1)\n          echo \"Using debs: $deb_amd64 and $deb_arm64\"\n\n          version=$(basename \"$deb_amd64\")\n          version=${version#acton_}\n          version=${version%_amd64.deb}\n          echo \"AMD64_DEB=$deb_amd64\" >> \"$GITHUB_ENV\"\n          echo \"ARM64_DEB=$deb_arm64\" >> \"$GITHUB_ENV\"\n          echo \"VERSION_FROM_DEB=$version\" >> \"$GITHUB_ENV\"\n      - name: \"Determine container tag & push intent\"\n        id: container_meta\n        env:\n          GHCR_OWNER: ${{ github.repository_owner }}\n        run: |\n          ref=\"${GITHUB_REF}\"\n          owner=\"${GHCR_OWNER:-actonlang}\"\n          version=\"${VERSION_FROM_DEB:-unknown}\"\n          push=false\n          alias_tag=\"\"\n          if [[ \"$ref\" == refs/tags/v* ]]; then\n            push=true\n          elif [[ \"$ref\" == refs/heads/main ]]; then\n            push=true\n            alias_tag=\"tip\"\n          fi\n          echo \"version_tag=$version\" >> \"$GITHUB_OUTPUT\"\n          echo \"push=$push\" >> \"$GITHUB_OUTPUT\"\n          echo \"owner=$owner\" >> \"$GITHUB_OUTPUT\"\n          echo \"alias_tag=$alias_tag\" >> \"$GITHUB_OUTPUT\"\n      - name: \"Set up QEMU\"\n        uses: docker/setup-qemu-action@v4\n      - name: \"Set up Docker Buildx\"\n        uses: docker/setup-buildx-action@v4\n      - name: \"Log in to GHCR\"\n        if: steps.container_meta.outputs.push == 'true'\n        uses: docker/login-action@v4\n        with:\n          registry: ghcr.io\n          username: ${{ github.actor }}\n          password: ${{ secrets.GITHUB_TOKEN }}\n      - name: \"Build container image\"\n        run: |\n          set -euo pipefail\n          version=\"${{ steps.container_meta.outputs.version_tag }}\"\n          owner=\"${{ steps.container_meta.outputs.owner }}\"\n          alias_tag=\"${{ steps.container_meta.outputs.alias_tag }}\"\n          image_base=\"ghcr.io/${owner}/acton\"\n          image_version=\"${image_base}:${version}\"\n          image_latest=\"${image_base}:latest\"\n          push=\"${{ steps.container_meta.outputs.push }}\"\n\n          if [[ \"$push\" == \"true\" ]]; then\n            platforms=\"linux/amd64,linux/arm64\"\n          else\n            platforms=\"linux/amd64\"\n          fi\n\n          build_flags=(--file Containerfile.deb --label \"org.opencontainers.image.version=${version}\" --provenance=false --sbom=false --platform \"$platforms\")\n\n          if [[ \"$push\" == \"true\" ]]; then\n            docker buildx build \"${build_flags[@]}\" --tag \"$image_version\" --push .\n            if [[ -n \"$alias_tag\" ]]; then\n              docker buildx imagetools create --tag \"${image_base}:${alias_tag}\" \"$image_version\"\n            fi\n            if [[ \"${{ github.ref }}\" == refs/tags/v* ]]; then\n              docker buildx imagetools create --tag \"$image_latest\" \"$image_version\"\n            fi\n          else\n            docker buildx build \"${build_flags[@]}\" --tag \"$image_version\" --load .\n          fi\n\n  # If we are on the main branch, we'll create or update a pre-release called\n  # 'tip' which holds the latest build output from the main branch!  We upload\n  # artifacts twice, first with the version number held in the filename and a\n  # second time after being renamed to remove the version number in the\n  # filename, thus providing a stable URL for downloading the tip tar balls.\n  pre-release-tip:\n    # Only run on the main branch\n    if: github.ref == 'refs/heads/main'\n    runs-on: ubuntu-latest\n    needs: [test-macos, test-linux, build-debs, build-container-image]\n    steps:\n      - name: \"Delete current tip release & tag\"\n        uses: dev-drprasad/delete-tag-and-release@v1.1\n        with:\n          delete_release: true\n          tag_name: tip\n        env:\n          GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}\n      - name: \"Check out repository code\"\n        uses: actions/checkout@v6\n      - name: \"Download artifacts for Macos aarch64, built on macos-15\"\n        uses: actions/download-artifact@v8\n        with:\n          name: acton-macos-15-aarch64\n      - name: \"Download artifacts for Macos x86_64, built on macos-15\"\n        uses: actions/download-artifact@v8\n        with:\n          name: acton-macos-15-x86_64\n      - name: \"Download artifacts for Linux x86_64, built on Debian:11\"\n        uses: actions/download-artifact@v8\n        with:\n          name: acton-debian-11-x86_64\n      - name: \"Download artifacts for Linux arm64, built on Ubuntu:24.04\"\n        uses: actions/download-artifact@v8\n        with:\n          name: acton-ubuntu-24.04-arm64v8\n      - name: \"Download artifacts for Debian Linux on amd64 (x86_64) & arm64 (aarch64)\"\n        uses: actions/download-artifact@v8\n        with:\n          pattern: acton-debs-*\n          merge-multiple: true\n      - name: \"List downloaded artifacts\"\n        run: |\n          ls\n          ls deb\n      - name: \"Workaround for changelog extractor that looks for number versions in headlines, which won't work for 'Unreleased'\"\n        run: sed -i -e 's/^## Unreleased/## [999.9] Unreleased\\nThis is an unreleased snapshot built from the main branch. Like a nightly but more up to date./' CHANGELOG.md\n      - name: \"Extract release notes\"\n        id: extract-release-notes\n        uses: ffurrer2/extract-release-notes@v3\n      - name: \"(re-)create 'tip' release notes and upload artifacts as assets\"\n        uses: ncipollo/release-action@v1\n        with:\n          allowUpdates: true\n          artifacts: \"acton*.tar*,deb/*deb\"\n          body: ${{ steps.extract-release-notes.outputs.release_notes }}\n          draft: false\n          prerelease: true\n          name: \"tip\"\n          tag: \"tip\"\n          token: ${{ secrets.GITHUB_TOKEN }}\n          replacesArtifacts: true\n      - name: \"Remove version number from macos aarch64 tar ball\"\n        run: mv $(ls acton-macos-aarch64*.tar.xz | tail -n1) acton-macos-aarch64-tip.tar.xz\n      - name: \"Remove version number from macos x86_64 tar ball\"\n        run: mv $(ls acton-macos-x86_64*.tar.xz | tail -n1) acton-macos-x86_64-tip.tar.xz\n      - name: \"Remove version number from linux x86_64 tar ball\"\n        run: mv $(ls acton-linux-x86_64*.tar.xz | tail -n1) acton-linux-x86_64-tip.tar.xz\n      - name: \"Remove version number from linux aarch64 tar ball\"\n        run: mv $(ls acton-linux-aarch64*.tar.xz | tail -n1) acton-linux-aarch64-tip.tar.xz\n      - name: \"Remove version number from debian amd64 package\"\n        run: mv $(ls deb/acton_*amd64.deb | tail -n1) deb/acton_tip_amd64.deb\n      - name: \"Remove version number from debian arm64 package\"\n        run: mv $(ls deb/acton_*arm64.deb | tail -n1) deb/acton_tip_arm64.deb\n      - name: \"List files for debug\"\n        run: |\n          ls\n          ls deb\n      - name: \"Upload artifacts without version number for stable links\"\n        uses: ncipollo/release-action@v1\n        with:\n          allowUpdates: true\n          artifacts: \"acton*.tar*,deb/acton_*.deb\"\n          body: ${{ steps.extract-release-notes.outputs.release_notes }}\n          draft: false\n          prerelease: true\n          name: \"tip\"\n          tag: \"tip\"\n          token: ${{ secrets.GITHUB_TOKEN }}\n          replacesArtifacts: true\n\n\n  # Release job, only run for version tagged releases.\n  release:\n    if: startsWith(github.ref, 'refs/tags/v')\n    runs-on: ubuntu-latest\n    needs: [test-macos, test-linux, build-debs, build-container-image]\n    steps:\n      - name: \"Check out repository code\"\n        uses: actions/checkout@v6\n      - name: \"Download artifacts for Macos aarch64, built on macos-15\"\n        uses: actions/download-artifact@v8\n        with:\n          name: acton-macos-15-aarch64\n      - name: \"Download artifacts for Macos x86_64, built on macos-15\"\n        uses: actions/download-artifact@v8\n        with:\n          name: acton-macos-15-x86_64\n      - name: \"Download artifacts for Linux x86_64, built on Debian:11\"\n        uses: actions/download-artifact@v8\n        with:\n          name: acton-debian-11-x86_64\n      - name: \"Download artifacts for Linux arm64, built on Ubuntu:24.04\"\n        uses: actions/download-artifact@v8\n        with:\n          name: acton-ubuntu-24.04-arm64v8\n      - name: \"Download artifacts for Debian Linux\"\n        uses: actions/download-artifact@v8\n        with:\n          pattern: acton-debs-*\n          merge-multiple: true\n      - name: \"List downloaded artifacts\"\n        run: ls\n      - name: \"Extract release notes\"\n        id: extract-release-notes\n        uses: ffurrer2/extract-release-notes@v3\n      - name: \"Create release\"\n        uses: ncipollo/release-action@v1\n        with:\n          allowUpdates: true\n          artifacts: \"acton*.tar*,deb/*deb\"\n          body: ${{ steps.extract-release-notes.outputs.release_notes }}\n          draft: false\n          token: ${{ secrets.GITHUB_TOKEN }}\n          replacesArtifacts: true\n\n\n  # Update apt repo\n  update-apt-repo:\n    if: startsWith(github.ref, 'refs/tags/v')\n    runs-on: ubuntu-latest\n    container:\n      image: debian:experimental\n    needs: [test-macos, test-linux, build-debs]\n    steps:\n      - name: Install build prerequisites\n        run: |\n          apt-get update\n          apt-get install -qy -t experimental reprepro\n          apt-get install -qy git gnupg\n      - name: Import GPG key\n        id: import_gpg\n        uses: crazy-max/ghaction-import-gpg@v7\n        with:\n          gpg_private_key: ${{ secrets.APT_GPG_PRIVATE_KEY }}\n      - name: Check out code of apt.acton-lang.io repo\n        uses: actions/checkout@v6\n        with:\n          repository: actonlang/apt.acton-lang.io\n          path: apt\n          ssh-key: ${{ secrets.APT_DEPLOY_KEY }}\n      - name: \"Download artifacts for Debian Linux\"\n        uses: actions/download-artifact@v8\n        with:\n          path: .\n          pattern: acton-debs-*\n          merge-multiple: true\n      - name: \"Get the version\"\n        id: get_version\n        run: |\n          echo \"version=$(ls ../deb/*amd64.changes | sed -e 's/.*acton_//' -e 's/_amd64.*//')\" >> $GITHUB_OUTPUT\n      - name: \"Include new deb in Apt repository\"\n        run: |\n          cd apt\n          for changes_file in ../deb/*.changes; do\n            reprepro include stable \"$changes_file\"\n          done\n      - name: \"Push updates to git repository for apt.acton-lang.io\"\n        run: |\n          cd apt\n          git config user.name \"Apt Bot\"\n          git config user.email apt@acton-lang.org\n          git add .\n          git status\n          git diff\n          git commit -a -m \"Add Acton v${{steps.get_version.outputs.version}}\"\n          git push\n\n  # Update apt tip repo\n  update-apt-tip-repo:\n    # Only run on the main branch\n    if: github.ref == 'refs/heads/main'\n    runs-on: ubuntu-latest\n    container:\n      image: debian:experimental\n    permissions:\n      contents: write\n    needs: [test-macos, test-linux, build-debs]\n    steps:\n      - name: Install build prerequisites\n        run: |\n          apt-get update\n          apt-get install -qy -t experimental reprepro\n          apt-get install -qy git gnupg\n      - name: Check out code of aptip.acton-lang.io repo\n        uses: actions/checkout@v6\n        with:\n          repository: actonlang/aptip.acton-lang.io\n          path: apt\n          ssh-key: ${{ secrets.APT_TIP_DEPLOY_KEY }}\n      - name: \"Download artifacts for Debian Linux\"\n        uses: actions/download-artifact@v8\n        with:\n          path: .\n          pattern: acton-debs-*\n          merge-multiple: true\n      - name: \"Get the version\"\n        id: get_version\n        run: |\n          echo \"VERSION=$(ls deb/*amd64.changes | sed -e 's/.*acton_//' -e 's/_amd64.*//')\" >> $GITHUB_ENV\n          echo \"version=$(ls deb/*amd64.changes | sed -e 's/.*acton_//' -e 's/_amd64.*//')\" >> $GITHUB_OUTPUT\n      - name: \"Move .deb files in place\"\n        run: |\n          cd apt\n          mv -v ../deb/* deb/\n      - name: \"Configure git\"\n        run: |\n          cd apt\n          git config user.name \"Apt Bot\"\n          git config user.email apt@acton-lang.org\n      - name: \"Push updates to git repository for aptip.acton-lang.io\"\n        run: |\n          cd apt\n          git add deb/*\n          git status\n          git commit -a -m \"Add Acton tip v${VERSION}\"\n          git push\n\n  # Update our homebrew tap\n  update-homebrew:\n    if: startsWith(github.ref, 'refs/tags/v')\n    runs-on: ubuntu-latest\n    # Depend on all test jobs so we don't update brew repo in case anything fails\n    needs: [test-macos, test-linux, build-debs]\n    steps:\n      - name: \"Check out code of main acton repo\"\n        uses: actions/checkout@v6\n      - name: \"Get the version from version.mk\"\n        id: get_version\n        run: |\n          cat version.mk\n          # Set both as environment variable for current job and as output for other steps\n          VERSION=$(grep -o '[0-9]\\+\\.[0-9]\\+\\.[0-9]\\+' version.mk)\n          echo \"Found version: $VERSION\"\n          echo \"VERSION=$VERSION\" >> $GITHUB_ENV\n          echo \"version=$VERSION\" >> $GITHUB_OUTPUT\n      - name: \"Download release tarball\"\n        run: wget https://github.com/actonlang/acton/archive/refs/tags/v${VERSION}.tar.gz\n      - name: \"Calculate SHA256 checksum\"\n        run: sha256sum v${VERSION}.tar.gz\n      - id: shasum\n        run: |\n          CHECKSUM=$(sha256sum v${VERSION}.tar.gz | cut -d' ' -f1)\n          echo \"sum=$CHECKSUM\" >> $GITHUB_OUTPUT\n          echo \"Checksum: $CHECKSUM\"\n      - name: \"Check out code of our brew repo\"\n        uses: actions/checkout@v6\n        with:\n          repository: actonlang/homebrew-acton\n          path: homebrew-acton\n      - name: \"Update formula in homebrew-acton from acton repo\"\n        run: |\n          cp homebrew/Formula/acton.rb homebrew-acton/Formula/acton.rb\n      - name: \"Update brew formula for acton with new version\"\n        run: |\n          sed -i -e 's,^  url.*,  url \"https://github.com/actonlang/acton/archive/refs/tags/v'${VERSION}'.tar.gz\",' -e 's/^  sha256.*/  sha256 \"'${{ steps.shasum.outputs.sum }}'\"/' homebrew-acton/Formula/acton.rb\n          echo \"Updated formula to version ${VERSION} with checksum ${{ steps.shasum.outputs.sum }}\"\n          cat homebrew-acton/Formula/acton.rb | grep -A 1 \"^ *url\"\n      - name: \"Create Pull Request\"\n        uses: peter-evans/create-pull-request@v8\n        with:\n          path: homebrew-acton\n          token: ${{ secrets.ACTBOT_PAT }}\n          branch: acton-v${{ env.VERSION }}\n          title: \"acton v${{ env.VERSION }}\"\n          body: |\n            Automatic update triggered by release on actonlang/acton.\n          committer: Acton Bot <actbot@acton-lang.org>\n          commit-message: \"acton v${{ env.VERSION }}\"\n          signoff: false\n"
  },
  {
    "path": ".github/workflows/trigger-web-update.yml",
    "content": "name: Trigger rebuild of Acton Web page\n\n# When there are changes to files under docs/acton-guide on main branch,\n# trigger the workflow to rebuild the Acton web page\non:\n  push:\n    branches:\n      - main\n    paths:\n      - 'docs/acton-guide/**'\n\njobs:\n  trigger_web_rebuild:\n    runs-on: ubuntu-latest\n\n    steps:\n      - name: \"Trigger build of www.acton-lang.org\"\n        uses: benc-uk/workflow-dispatch@v1\n        with:\n          repo: actonlang/www.acton-lang.org\n          token: ${{ secrets.ACTBOT_PAT }}\n          workflow: main.yml\n          ref: main\n      - name: \"Trigger build of acton.guide\"\n        uses: benc-uk/workflow-dispatch@v1\n        with:\n          repo: actonlang/acton.guide\n          token: ${{ secrets.ACTBOT_PAT }}\n          workflow: main.yml\n          ref: main\n"
  },
  {
    "path": ".github/workflows/update-ask-acton-vector-store.yml",
    "content": "name: Update Ask Acton vector store\n\non:\n  push:\n    branches:\n      - main\n    paths:\n      - 'docs/acton-guide/**'\n  workflow_dispatch:\n\nconcurrency:\n  group: ask-acton-vector-store\n  cancel-in-progress: true\n\njobs:\n  update_vector_store:\n    runs-on: ubuntu-latest\n    permissions:\n      contents: read\n\n    steps:\n      - name: Check out Acton\n        uses: actions/checkout@v6\n\n      - name: Check out Ask Acton indexer\n        uses: actions/checkout@v6\n        with:\n          repository: actonlang/ask-acton\n          path: ask-acton\n          token: ${{ secrets.ACTBOT_PAT }}\n\n      - name: Set up Node.js\n        uses: actions/setup-node@v6\n        with:\n          node-version: '22'\n          cache: npm\n          cache-dependency-path: ask-acton/package-lock.json\n\n      - name: Install Ask Acton dependencies\n        working-directory: ask-acton\n        run: npm ci\n\n      - name: Update vector store\n        working-directory: ask-acton\n        env:\n          OPENAI_API_KEY: ${{ secrets.ASK_ACTON_OPENAI_API_KEY || secrets.OPENAI_API_KEY }}\n          OPENAI_VECTOR_STORE_ID: ${{ secrets.ASK_ACTON_VECTOR_STORE_ID || secrets.OPENAI_VECTOR_STORE_ID }}\n          DOCS_DIR: ${{ github.workspace }}/docs/acton-guide/src\n          DOCS_REVISION: ${{ github.sha }}\n          INDEX_REPLACE_SOURCE: 'true'\n        run: npm run index:docs\n"
  },
  {
    "path": ".github/workflows/webex-notifications.yml",
    "content": "name: Webex Notifications\n\non:\n  pull_request:\n    types: [closed]\n    branches: [main]\n\njobs:\n  notify-webex:\n    runs-on: ubuntu-latest\n    if: github.event.pull_request.merged == true\n\n    steps:\n    - name: Prepare notification message\n      id: message\n      env:\n        PR_NUMBER: ${{ github.event.pull_request.number }}\n        PR_URL: ${{ github.event.pull_request.html_url }}\n        PR_TITLE: ${{ github.event.pull_request.title }}\n        PR_BODY: ${{ github.event.pull_request.body }}\n      run: |\n        MESSAGE=\"### PR [#${PR_NUMBER}](${PR_URL}) merged: ${PR_TITLE}\"\n\n        if [ -n \"$PR_BODY\" ]; then\n          #MESSAGE=\"${MESSAGE}\"$'\\n'$'\\n''```'\n          # TODO: does this contain an extra newline?\n          MESSAGE=\"${MESSAGE}\"$'\\n'\"${PR_BODY}\"\n          #MESSAGE=\"${MESSAGE}\"$'\\n''```'\n        fi\n\n        echo \"message<<EOF\" >> $GITHUB_OUTPUT\n        echo \"$MESSAGE\" >> $GITHUB_OUTPUT\n        echo \"EOF\" >> $GITHUB_OUTPUT\n\n    - name: Send Webex notification\n      env:\n        WEBEX_TOKEN: ${{ secrets.WEBEX_TOKEN }}\n        WEBEX_ROOM_ID: ${{ secrets.WEBEX_ROOM_ID }}\n      run: |\n        set -euo pipefail\n\n        # Write the prepared message to a file verbatim to avoid shell quoting issues\n        cat > message.txt <<'__WEBEX_MSG__'\n        ${{ steps.message.outputs.message }}\n        __WEBEX_MSG__\n\n        # Build JSON payload safely; jq will handle JSON escaping\n        JSON_PAYLOAD=$(jq -n \\\n          --arg roomId \"$WEBEX_ROOM_ID\" \\\n          --rawfile markdown message.txt \\\n          '{roomId: $roomId, markdown: $markdown}')\n\n        # Send message to Webex room using direct API call\n        RESPONSE=$(curl -sS -X POST \"https://webexapis.com/v1/messages\" \\\n          -H \"Authorization: Bearer $WEBEX_TOKEN\" \\\n          -H \"Content-Type: application/json\" \\\n          -d \"$JSON_PAYLOAD\" \\\n          -w \"\\n%{http_code}\")\n\n        HTTP_CODE=$(echo \"$RESPONSE\" | tail -n1)\n        BODY=$(echo \"$RESPONSE\" | head -n-1)\n\n        if [ \"$HTTP_CODE\" -ne 200 ]; then\n          echo \"::error::Failed to send Webex notification. HTTP code: $HTTP_CODE\"\n          echo \"Response: $BODY\"\n          exit 1\n        else\n          echo \"✅ Webex notification sent successfully!\"\n        fi\n"
  },
  {
    "path": ".gitignore",
    "content": "**/.ccls-cache/*\n**/.zig-cache/*\n\n*~\n*.o\n*.a\n**/.DS_Store\n**/.stack-work\n**/*.dSYM\n**/*.hi\n**/*.o\n**/a.out\n**/build.zig*\n**/core\n**/build-cache\n**/zig-cache\n**/.acton.compile.lock\n**/.acton.lock\n**/.build/\n**/*.swp\n**/*.ty\n\nbackend/actondb\nbackend/failure_detector/db_messages_test\nbackend/test/actor_ring_tests_local\nbackend/test/actor_ring_tests_remote\nbackend/test/db_unit_tests\nbackend/test/queue_unit_tests\nbackend/test/skiplist_test\nbackend/test/test_client\n\nbase/build-cache\nbase/out\n\nbuilder/builder\nbuilder/build_runner.zig\nbuilder/zig-cache\n\ncompiler/package.yaml\ncompiler/acton/acton.cabal\ncompiler/acton/package.yaml\ncompiler/lib/package.yaml\ncompiler/lsp-server/package.yaml\ncompiler/lsp-server/lsp-server-acton.cabal\ntest/package.yaml\n\ndebian/.debhelper\ndebian/acton/\ndebian/acton.substvars\ndebian/debhelper-build-stamp\ndebian/changelog\ndebian/files\n\ndeps/*\ndeps-download\n\ndist/*\n\nbuilder/deps/*\n\nexamples/*\n!examples/*.*\n!examples/*/\nexamples/**\n!examples/**/*.*\n!examples/**/*/\n\ntest/*\n!test/*.*\ntest/*.log\n!test/*/\ntest/**\n!test/Makefile\n!test/**/*.*\ntest/**/*.log\n!test/**/*/\n!test/**/snapshots/\n!test/**/snapshots/**/\n!test/**/snapshots/**/*\ntest/**/snapshots/output/**\n\nsnapshots/output/**\n\n# tests organized as acton projects; ignore all but source\ntest/*/*/out/**\ncompiler/acton/test/project/*/out\n"
  },
  {
    "path": ".gitmodules",
    "content": "[submodule \"test/Unity\"]\n\tpath = test/Unity\n\turl = https://github.com/ThrowTheSwitch/Unity.git\n"
  },
  {
    "path": "AGENTS.md",
    "content": "Acton compiler notes:\n\n- `acton build --no-threads` controls whether the produced Acton binary uses\n  threads in Acton RTS. It does not disable threads in the Acton compiler\n  process itself, so compilation still happens concurrently. This flag is only\n  to be used for compatibility with platforms that do no have thread support,\n  for example cross-compiling for Windows, we build without threads.\n"
  },
  {
    "path": "CHANGELOG.md",
    "content": "# Changelog\n\n## Unreleased\n\n### Compiler & Build\n- Add concurrent top-level type checking for total statements, allowing the\n  compiler to check independent top-level definitions in parallel while keeping\n  source-order semantics for non-total statements. [#2773, #2782]\n  - Verbose and timing builds now report inferred signatures for non-total\n    statements, making it easier to add explicit signatures and unlock more\n    concurrent checking.\n  - Type errors from independent total statements are collected into multiple\n    diagnostics instead of stopping at the first failing statement.\n  - Use a fixed worker pool with bounded lookahead, improving memory behavior\n    and performance for modules with many independent top-level definitions.\n- Parse modules in parallel by splitting top-level statement chunks across\n  parser workers, reducing parser latency for large source files while\n  preserving source-order results. [#2787]\n  - `--parse-serial` keeps the whole-file parser available for debugging and\n    fallback comparisons.\n  - Module-suite validation now uses a set-based duplicate check, avoiding\n    quadratic validation time in large projects.\n- Report parser progress percentages during builds, giving useful feedback for\n  very large files before type checking starts. [#2784]\n- Preserve each module's import context in cached module interfaces, so builds,\n  `acton sig`, documentation, and completion can reuse cached interfaces without\n  losing imported class and protocol information. [#2779]\n- Speed up compiler environment lookups and scans in large modules by indexing\n  active names, separating closed imports and finalized top-level names from\n  live local bindings, and deduplicating reserved names with a hash index while\n  preserving source-order semantics. [#2789, #2796, #2797]\n\n### Packages & Distribution\n- Change x86_64 Linux builds from statically linked GNU libc to dynamically\n  linked GNU libc while keeping other libraries statically linked. [#2774,\n  #2781]\n  - The x86_64 Linux release job and Debian package builds run on Debian 11 to\n    provide a glibc 2.31 floor.\n  - Nightly CI still covers Debian 11, 12, and 13 on x86_64.\n  - CI now validates the dynamic library set and maximum required GLIBC version\n    for `acton`, `lsp-server-acton`, and `actondb`.\n- Vendor the `diagnose` compiler diagnostic library from upstream after\n  `diagnose` removed its stale `text <=2.0` dependency, so compiler builds can\n  use the resolver's `text` package instead of pinning `text-2.0` just for\n  diagnostics. [#2783]\n\n### Documentation\n- Document when and how to use the Acton container image, including\n  copy-pastable Docker commands for checking the compiler version and building\n  the current project. [#2767]\n\n### Testing & CI\n- Add a dedicated type-checking benchmark driver that reports parse,\n  environment, kind-checking, and type-checking timings, with optional RTS\n  allocation and GC statistics for compiler performance work. [#2794]\n- Add a generated class-heavy type-checking fixture to exercise concurrent\n  type-checking scheduler performance on large recursive class structures. [#2777]\n\n## [0.27.0] - 2026-05-08\n\n### Added\n- Add precise content-hash based build output reuse throughout the compiler\n  pipeline for optimal compilation [#2447, #2497, #2581, #2674]\n  - Acton now decides whether previous typechecking results, generated build\n    outputs, and downstream work are still valid from source and dependency\n    content instead of relying on file modification times\n  - Cached module interfaces record source hashes, module-level public and\n    implementation hashes, and per-name source / public / implementation hashes\n  - Per-name dependency hashes let the compiler track exactly which names a\n    declaration depends on, so unrelated edits do not force whole modules or\n    downstream dependents to be rebuilt\n  - Public type-signature changes rerun front passes for affected downstream\n    modules; implementation-only changes can refresh implementation hashes and\n    rerun back passes / code generation without forcing unrelated typechecking\n  - When hashes match, cached build output is reused directly instead of\n    reparsing, re-typechecking, or regenerating work that is already fresh\n- Add concurrent module compilation across the build graph. [#2524, #2527]\n  - The compiler schedules modules as soon as their dependencies are ready,\n    allowing independent parts of a project to typecheck in parallel\n  - Front passes and back passes are separated, so dependent modules can start\n    once an interface is available while normalization, C generation, and other\n    back-end work continue in parallel\n  - Ready modules are prioritized by critical path so large dependency branches\n    do not leave available workers idle\n  - This keeps project builds, watch mode, and LSP feedback responsive while\n    still producing the same deterministic build outputs\n- Add VS Code editor support through the Acton language server. [#2487, #2753]\n  - The VS Code extension can now show Acton syntax and type errors inline,\n    using the same parser and typechecker as `acton build`\n  - Completion suggests attribute names, function and method argument names,\n    and other relevant source-level names\n  - Hover shows Acton information for names under the cursor\n  - Editor state is kept in memory for fast lookups, so completion and\n    diagnostics stay responsive while typechecking continues\n- Add `acton doc` command for generating documentation [#2274, #2284, #2292,\n  #2293, #2295]\n  - Supports multiple output formats (text, markdown, HTML)\n  - Default is to open browser into HTML docs when window environment is\n    available, in terminal we fall back to colored text output. Use `acton doc\n    -t` to force text / terminal output.\n  - Plain `acton doc` will show module index in browser - for terminal output, a\n    source file must be given, like `acton doc src/foo.act -t`\n  - Text output is colored for output to TTY (terminal), piping output falls\n    back to plain ASCII output. Also honors `NO_COLOR` env var\n  - HTML supports:\n    - colorized output of types etc\n    - inter-module links to type definitions\n    - explanatory tooltips for generic types\n- Add optional chaining and forced unwrapping for optional values [#2672, #2726]\n  - `person?.residence?.name` returns `None` when any step is `None`\n  - `person!.residence!.name` raises `ValueError` when a required step is\n    unexpectedly `None`\n  - Both forms support attribute access and method calls via `?.` / `!.`, plus\n    indexing and slicing via `?[...]` / `![...]`\n- Add `acton sig` to inspect inferred type signatures using the same\n  project-aware module and dependency resolution as `acton build`. [#2746]\n  - Useful when an error says `foo.bar` does not have attribute `X`, since\n    `acton sig foo.bar` resolves names like the compiler does: first as `bar`\n    in module `foo`, then as module `foo.bar`\n- Add docstring support throughout compiler and AST [#2282]\n  - Parse docstrings in AST declarations [#2269, #2270, #2271, #2565, #2736]\n  - Unescape docstrings in NameInfo\n  - Allow module docstrings before imports\n- Add short options support for argparse module [#2289]\n- Add global command-line options support to actonc [#2291]\n- Add new Hashable protocol and hash() builtin function [#2255]\n  - Replace __hash__ method with new composable hashing approach\n  - Types implement `.hash(self, hasher)` method to update a stateful hasher object\n  - The hasher accumulates state from multiple fields: `self.x.hash(h); self.y.hash(h)`\n  - Use the `hash()` function to get hash values: `h = hash(my_object)`\n  - All built-in types implement Hashable protocol\n  - Uses fast wyhash algorithm via Zig implementation\n- Parser / Syntax errors are now prettier [#2306, #2307, #2309]\n  - Replace basic error rendering with elegant unicode style using Diagnose library\n  - Better structured error reporting using Megaparsec's ADT typed error system\n- Improve error messages for type variable name violations\n  - Clear hints explaining that single uppercase letters are reserved for type variables\n  - Show cases possibilities of new parser error diagnostics\n  - Plain ASCII example (in terminal is even prettier):\n```\n[error Parse error]: Invalid name (reserved for type variables)\n\n     +--> test/syntaxerrors/err41.act@1:7-1:8\n     |\n   1 | class Z(value):\n     :       ^\n     :       `- invalid name 'Z'\n     :\n     | Hint: Single upper case character (optionally followed by digits) are reserved for type variables. Use a longer name.\n-----+\n```\n- Improve string interpolation parsing [#2321]\n  - String parsing has been rewritten from scratch\n  - String interpolation now works by default in all string literals (no f-prefix required)\n    - Both `\"hello {name}\"` and `f\"hello {name}\"` support interpolation\n  - The change to interpolate normal strings is backwards **incompatible**, any\n    strings containing curly braces now need to be escaped or be converted to\n    raw strings, i.e. \"{\" -> \"{{\" or r\"{\"\n  - Backwards compatibility for classic `%` operator style is currently\n    maintained, i.e. NO interpolation is performed for `s = \"hello %s, here is\n    {}\" % name`, so curly braces are treated literaly\n    - NOTE: %-operator style formatting will be deprecated in the future\n  - Parser support nested interpolation strings (thought the necessary rewrites\n  - Properly handle escape sequences in interpolated strings\n  - Support complex expressions in interpolations including slices (`{arr[1:3]}`)\n  - Better error messages for malformed format specifications and many other cases\n```\nERROR: [error Syntax error]: Empty format specifier after ':'\n     ╭──▶ test@1:27-1:27\n     │\n   1 │ f\"Unbalanced format {name:}:10}\"\n     •                            \n     •                           ╰╸ Empty format specifier after ':'\n─────╯\n```\n- Let `repr()` and `type()` accept optional values [#2373]\n  - `repr(None)` returns `\"None\"` and `type(None)` returns `\"None\"`\n  - More convenient than needing wrapper functions for optional values\n- Add webex PR merge notification [#2372]\n- Recognize projects by `Build.act` & `build.act.json` [#2358]\n  - Accept `Build.act` (new ideal), `build.act.json` (common), or `Acton.toml` (existing)\n  - Check for `src/` directory presence for robustness\n- Allow any expression after `after` [#2342]\n  - Previously limited to local functions, now supports method calls, actor methods, etc.\n  - `after 1.5: obj.method()` and `after 0.1: remote_actor.action()` are now valid\n- Add `utils/update-changelog.sh` script to update this file (`CHANGELOG.md`) using Claude - it's a good prompt!\n- Allow logging of optional values [#2382]\n  - Change logging data parameter type from `dict[str, value]` to `dict[str, ?value]`\n  - Enables structured logging with None values like `{\"user\": None, \"count\": 42}`\n- Add `acton build FILE` for file-oriented builds through the main CLI. [#2471,\n  #2592]\n- Add `acton build --watch` for fast edit/build feedback loops. [#2571]\n  - Watch mode performs an initial project build and then keeps running,\n    rebuilding automatically when source files change\n  - Ordinary `.act` file edits use the incremental compiler scheduler, so\n    unchanged modules, dependencies, and back-end work can be reused instead of\n    rebuilding the whole project\n  - Adding or removing source files, or changing `Build.act`, triggers project\n    rediscovery so the build graph stays aligned with the project layout and\n    dependency configuration\n  - New edits supersede older in-flight work, which keeps the compiler\n    responsive while a user is actively typing\n  - Single-file watch is also supported with `acton build FILE --watch` or\n    `acton FILE --watch`\n  - `acton test --watch` uses the same machinery and reruns affected test\n    modules after successful rebuilds\n- Add `acton spec` commands for inspecting and updating `Build.act` as JSON.\n  [#2534]\n- Expand `acton pkg` package management [#2534, #2554, #2586, #2596]\n  - `acton pkg update` downloads the package index\n  - `acton pkg search` searches the local package index\n  - `acton pkg add` can add packages by package name, archive URL, or GitHub\n    repository URL\n  - `acton pkg upgrade` updates dependencies with stored repository metadata\n  - `acton zig-pkg add/remove` manages Zig package dependencies in `Build.act`\n- Add project fingerprints to `Build.act` [#2634, #2681]\n  - Fingerprints identify project lineage and are validated against the project\n    name\n  - This makes accidental project renames and dependency identity conflicts\n    easier to detect\n- Add local dependency overrides with `--dep NAME=PATH`. [#2555]\n- Add release mode aliases [#2708, #2761]\n  - `--release` and `--optimize=release` select `ReleaseFast`\n  - `--release=safe`, `--release=small`, and `--release=fast` select\n    `ReleaseSafe`, `ReleaseSmall`, and `ReleaseFast`\n- Add `--jobs`, `--tty`, `--no-progress`, and `--timing` controls to the main\n  `acton` CLI. [#2478, #2526, #2628]\n- Add `--parse-ast` for compiler debugging. [#2541]\n- Add JSON output for `acton test` and `acton test list`. [#2598]\n- Add a content-hash based result cache for `acton test`. [#2651]\n  - Test results can be reused when the tested module, its dependencies, and\n    expected snapshot data have not changed\n  - This makes repeated test runs much faster while still invalidating cached\n    results when relevant source or dependency content changes\n  - Use `acton test --no-cache` to bypass the cache and force selected tests to\n    rerun\n- Add `acton test --show-log` to always print captured test logs. [#2408]\n- Add `acton test --accept` as an alias for accepting snapshot / golden\n  output. [#2584]\n- Add `acton test stress` mode for repeated concurrent test execution.\n  [#2683, #2691, #2692, #2694]\n  - `--stress-workers` controls the worker count\n  - Stress output shows mixed outcomes and phase coverage while running\n- Add test capability tags with `testing.require()` and `acton test --tag`.\n  [#2655]\n- Add `--min-time`, `--max-time`, `--min-iter`, and `--max-iter` controls for\n  test runs. [#2467, #2408]\n- Add `u1`, `u8`, `i8`, and builtin `i64` support. [#2532, #2519]\n- Add `list.count()` method. [#2521]\n- Add JSON encoding / decoding for list values at the document root. [#2508]\n- Add `xml.Node.encode(pretty=True)` for pretty XML output. [#2512]\n- Add URI `quote()` and `unquote()` helpers. [#2719]\n- Add HTTPS server and TLS listener support. [#2576]\n- Add an Acton LLDB plugin for debugging Acton programs. [#2520]\n  - Adds `acton bt`, `acton locals`, `acton demangle`, and `acton break`\n    commands inside LLDB\n  - Shows filtered, Acton-demangled backtraces with argument values instead of\n    forcing users to read raw generated C symbol names\n  - Prints locals with Acton names and value summaries, including strings,\n    boxed values, objects, actors, classes, and generic value slots\n  - Supports Acton source breakpoints like `acton break src/main.act:42`\n- Add container image builds for Acton Debian packages. [#1404]\n- Add `PROFILE` build option to the Makefile. [#2664]\n- `re.match()` now accepts an optional `start_pos` to begin scanning at an\n  offset. [#2569]\n\n### Changed\n- Move total build graph construction, dependency builds, and generated\n  build.zig / build.zig.zon dependency wiring into the compiler. [#2550,\n  #2551]\n- Use f-strings throughout standard library [#2297, #2290]\n- Improve process environment handling [#2298]\n  - Inherit PATH when custom environment is provided\n- Enhance ecosystem lift process with additional documentation [#2272, #2288]\n- Extend QuickType with effect output for better comprehension translation [#2267]\n- Improve acton.rts.sleep platform coverage [#2303]\n- Switch to use new hash() function instead of __hash__ [#2255]\n- Remove __hash__ special method in favor of hash() builtin [#2304]\n- Rename `docs/acton-by-example` to `docs/acton-guide` [#2313]\n- Adopt Zig optimization levels in Acton [#2362]\n  - Replace `--dev` flag with `--optimize` accepting: Debug, ReleaseSafe, ReleaseSmall, ReleaseFast\n  - Change default from ReleaseFast to Debug (matching Zig's default)\n  - `--dev` maps to Debug for backward compatibility, new `--release` maps to ReleaseFast\n- Simplify command-line parser structure [#2367]\n- Remove deprecated `--dev` option [#2366]\n- Revamp `actonc` debug / verbose mode [#2354]\n- Avoid writing `.ty` files in Types.reconstruct [#2357]\n- Remove unused sysLib & projLib fields from compiler Paths [#2385]\n  - Cleanup remnants from pre-Zig build system migration\n- Simplify Webex PR merge notification & handle escapes [#2376, #2384, #2507]\n  - Improve message formatting and environment variable handling\n- Retire the Acton-written CLI and make the Haskell compiler package provide\n  the `acton` executable directly. [#2607]\n  - `acton`, package management, testing, LSP, and compiler scheduling now use\n    shared compiler code\n  - The old `actonc` implementation has been renamed to the `acton` compiler\n    package\n- Require `Build.act` for projects and require `name` and `fingerprint` in\n  root project build files. [#2643, #2644]\n- Stabilize public interface hashes, include qualified free names in name\n  hashing, and preserve full source locations in cached interfaces. [#2578,\n  #2747, #2752]\n- Validate cached `.ty` files with source metadata and treat version, compiler,\n  and dependency mismatches as recoverable stale cache entries. [#2440, #2717,\n  #2718]\n- Defer full parsing until after project discovery. [#2742]\n- Pass explicit module selections into generated Zig builds so dependency builds\n  only build the modules selected by the compiler. [#2666]\n- Use canonical dependency roots in generated `build.zig.zon` files and isolate\n  transitive Zig dependency names. [#2690, #2696]\n- Upgrade the bundled Zig toolchain to 0.15.2. [#2590, #2594]\n- Use architecture-based default CPU settings for Zig targets. [#2574]\n- Rename `--ignore-compiler` to `--ignore-compiler-version` and make compiler\n  version / mtime mismatches explicit stale-cache checks. [#2568, #2573,\n  #2608, #2609]\n- Move generated C line directives behind `--dbg-no-lines`. [#2518]\n- Enable larger parallel GHC nurseries for compiler builds. [#2522]\n- Use HashMaps for imported type environments. [#2517]\n- Update the `acton new` project template. [#2589]\n- Track build cache growth with periodic checks. [#2475]\n- Make snapshot testing use `snapshots/expected` and `snapshots/output`\n  directories instead of the older golden layout. [#2620]\n- Make `acton test --name` regex based. [#2616]\n- Store discovered test metadata in `.ty` headers so test discovery can reuse\n  cached interfaces. [#2636]\n- Show cached test failures by default while keeping cached successes hidden.\n  [#2557]\n- Align test progress with build progress, use project-qualified module names\n  in progress output, and adapt progress width/timer fields to terminal width.\n  [#2618, #2619, #2628, #2665, #2667, #2682, #2731]\n- Use the provided `logging.Handler` in HTTP server actors. [#2698]\n- Set empty XML node `text` and `tail` values to `None`. [#2509]\n- Make `file.mkdir()` and `file.rmdir()` idempotent. [#2477]\n- Use `mkdtemp` semantics for temporary directory creation. [#2693]\n- Prebuild one-byte ASCII strings to reduce allocation churn. [#2705]\n- Use common dependency builds to avoid redundant rebuilds and guard root-pin\n  warnings behind `--quiet`. [#2649, #2653]\n\n### Removed\n- Remove numpy support from the compiler, parser, stdlib, and tests. [#2413]\n- Remove the old explicit stub compilation mode. [#2414]\n- Remove the old Acton-written `acton.act` CLI implementation after moving CLI\n  functionality into the compiler package. [#2607]\n\n### Fixed\n- Fix string 'in' operator for substrings found at position 0 [#2280]\n- Fix unintended dependency on complete scope when scanning __init__ for attributes [#2285]\n- Ensure lambda-bound variables are in scope when comprehensions are translated [#2267]\n- Default print diff for testing.assertEqual failure [#2260]\n- Fix VERSION substitution in Homebrew PR creation [#2266]\n- Fix escaped braces in strings at position 0 [#2370]\n  - Escaped braces `{{` and `}}` at start of strings were incorrectly parsed as interpolation\n  - Now correctly converts `\"{{a}}\"` to `\"{a}\"` and handles mixed cases like `\"{{hello}} {world}\"`\n- Fix actor constructor alias resolution [#2365]\n  - Aliased actors from imports (`from worker import Worker`) now correctly generate module-prefixed constructors\n  - Fixes issues with builtin actors like `StringDecoder` and explicit aliased imports\n- Fix `.endswith()` for strings shorter than needle [#2348]\n  - Prevent out-of-bounds memory access when haystack is shorter than needle\n- Fix `acton version` command structure [#2363]\n- Avoid superfluous rebuilds for actonc [#2349]\n- Replace `$FORMAT` macro with C function [#2327]\n- Fix \"2320\" error [#2323]\n- Fix Hashable protocol implementation [#2255]\n  - Correct zig bytes definition\n  - Fix issues with bytes containing NUL character\n- Fix solver handling of generic tuples, top-level constraint solving,\n  skolemized type variables, scoped constraints, optional bounds, and coerced\n  index targets. [#2319, #2332, #2339, #2438, #2564, #2570, #2587, #2603,\n  #2624, #2661, #2675]\n- Accept four or five quotes at the end of triple-quoted strings. [#2388]\n- Improve `str.__repr__()` to escape braces correctly and handle quoted\n  strings. [#2386]\n- Fix unclosed string parser diagnostics. [#2486]\n- Escape generated C identifiers that became keywords in C23. [#2480]\n- Fix Unicode handling in regular expressions. [#2540, #2553]\n- Fix parsing, inference, and code generation for negative integer literals,\n  including the most negative `i64` value. [#2492, #2543]\n- Infer `bigint` for integer literals outside the `i64` range. [#2519]\n- Fix `argparse` defaults for list arguments and preserve rest arguments after\n  `--`. [#2473, #2580]\n- Fix boolean singleton use and `None` checks in arbitrary boolean contexts.\n  [#2485, #2491]\n- Fix `bytes.startswith()` end-bound checks. [#2410]\n- Fix `bytes.split()` and `bytearray.split()` for empty separator edge cases.\n  [#2453]\n- Fix tuple printing when tuple values contain `None`. [#2430]\n- Implement `__repr__()` for exceptions. [#2421]\n- Fix printing lists that contain optional elements. [#2613]\n- Fix violations of the UTF-8 invariant when creating strings. [#2455]\n- Fix UTF-8 character / byte offset handling in string partitioning. [#2676]\n- Fix `process.pid()` after the process has exited. [#2405]\n- Fix process and build output handling for paths containing spaces. [#2516]\n- Fix UTF-8 handling in accepted golden test output. [#2593]\n- Fix JSON encoding of fixed-size integer values. [#2530]\n- Fix XML parse errors to use `XmlParseError` instead of generic runtime\n  errors. [#2420]\n- Fix XML special character escaping, CDATA decoding, UTF-8 handling, and\n  prefixed attribute decoding. [#2422, #2433]\n- Fix HTTP response callbacks to pass headers and treat header defaults\n  case-insensitively. [#2448]\n- Validate malformed HTTP requests and responses instead of accepting invalid\n  input or crashing during decode. [#2454, #2457]\n- Fix `is not None` lowering and optional narrowing through comprehension head\n  expressions. [#2412, #2402, #2720]\n- Fix sequential flow analysis around `$RAISE`. [#2401]\n- Fix `while ... else` handling and reevaluate effectful loop conditions each\n  iteration. [#2464, #2466]\n- Fix `and` / `or` expressions when unboxing is involved. [#2465]\n- Fix type casts to unboxable values during code generation. [#2479]\n- Fix conversion of dot selections with partially aliased import chains. [#2700]\n- Fix term substitution when the substitution range and domain overlap. [#2701]\n- Fix lambda lifting and CPS edge cases around converted closure types and\n  nested control flow. [#2709, #2735, #2737]\n- Fix class attribute initialization checks and improve diagnostics for\n  uninitialized attributes. [#2391]\n- Fix class-level and cyclic protocol witness handling. [#2484, #2488, #2556]\n- Fix class instance handling of type-parameter witnesses and prevent static\n  methods from being invoked on instances. [#2623]\n- Fix conversion of `Self` in protocol methods after moving protocol conversion\n  before constraint solving. [#2632]\n- Fix optional equality and optional-chain type inference edge cases. [#2716,\n  #2672, #2726]\n- Fix private imported names leaking through interfaces. [#2567, #2752]\n- Fix actor `self` checks and discovered actor test wrappers. [#2514, #2535]\n- Fix malformed module top-level statements by restricting modules to\n  declarations, imports, and assignments. [#2728]\n- Fix generated name collisions by prefixing generated names with the top-level\n  name. [#2729]\n- Fix stale transitive dependencies after import renames. [#2727]\n- Fix transitive imports for cached modules. [#2677]\n- Fix missing dependency name hashes by treating them as stale cache entries.\n  [#2637]\n- Fix dependency cache invalidation when a path from `--syspath` changes.\n  [#2510]\n- Fix dependency override handling for declared dependencies. [#2555]\n- Validate local `--dep` paths as Acton project roots. [#2638]\n- Rework dependency downloads and honor `http_proxy`. [#2640]\n- Fetch transitive remote dependencies reachable through path dependencies\n  before project discovery. [#2668]\n- Fix stale implementation refreshes when an interface hash is missing. [#2674]\n- Fix orphaned module artifacts after modules are removed. [#2633]\n- Preserve normal and test root stubs and prune orphaned binary executables.\n  [#2265, #2505, #2538]\n- Fix relative / absolute path handling for build files and build.zig.zon\n  syspath entries. [#2493, #2495]\n- Skip Zig builds for dependency projects when only Acton interface artifacts\n  are needed. [#2496]\n- Fix `Build.act` null handling and unused dependency builds. [#2539, #2557]\n- Force recompilation when an alternate output directory is selected. [#2513]\n- Fix `acton --parse` output. [#2536]\n- Fix `acton build` handling after Zig toolchain upgrades. [#2595]\n- Improve error handling for compiler back passes. [#2597]\n- Fix LSP stdout framing corruption. [#2629]\n- Fix RTS message waiting so actors are not missed between waiting states and\n  message delivery. [#2689]\n- Clean up libuv file requests to avoid stale request state. [#2695]\n- Work around macOS 26.4 command-line tools breaking Zig and set\n  `DEVELOPER_DIR=/dev/null` for actondb on macOS. [#2715, #2756]\n- Restore the Zig dist target. [#2745]\n- Delete an accidental root-level copy of `Types.hs`. [#2739]\n\n### Documentation\n- Add ecosystem lift process documentation\n- Add Hashable protocol documentation to Acton Guide. [#2310]\n- Add actor `self`, collection comprehension, and guide organization updates.\n  [#2314, #2315, #2316, #2318]\n- Add Acton developer guide covering repository layout, build flow, compiler\n  passes, runtime, and testing internals. [#2566]\n- Reshape the Acton Guide around task-oriented language, project, testing, and\n  stdlib documentation. [#2734, #2740, #2750]\n- Document optional chaining and forced unwrapping. [#2722, #2732]\n- Document class initialization rules and improved uninitialized attribute\n  diagnostics. [#2391]\n- Document project fingerprints and the `Build.act` project format. [#2634,\n  #2644]\n- Document incremental compilation and content hashing. [#2610]\n- Document RTS backtrace debugging arguments. [#2615]\n- Explain constraint errors with rendered signatures. [#2751]\n- Clarify Acton lock ownership responsibilities. [#2678]\n- Update Ask Acton vector store data when the guide changes. [#2748]\n\n### Testing / CI\n- Support test discovery of actors [#2337]\n  - Recognize test actors without needing wrapper functions\n  - Compiler generates wrappers automatically for discovered test actors\n  - Remove old test types (sync/async/env test functions)\n- Update macOS CI to include macos-15 x86_64/aarch64 and macos-26 arm64, and\n  drop macos-14 to keep the PR matrix small. [#2511, #2583]\n- Test run MUSL executables on Linux [#2355]\n- Test http2, netclics, zlib, netcli applications [#2338, #2331, #2324]\n- Add self name check for actors [#2317]\n- Add more parser / syntax error test cases [#2308]\n- Stop testing Debian 10 [#2352]\n- Drop Debian 11 from test-linux CI matrix [#2588]\n  - this means we do not test / support Debian 11 as a OS dist for developing Acton itself\n  - Debian 11 is still a valid run time target for Acton programs\n    - run-linux still covers compiling & running Acton programs on Debian 11\n- Support multiple files for compiler testing framework [#2363]\n  - Accumulate environment from modules to support imports\n- Add compiler pass golden tests for parse, kind, type, normalize, deactorize,\n  CPS, lambda lift, boxing, header generation, C generation, and signatures.\n  [#2548]\n- Add incremental rebuild regression tests with stable sanitized hash output.\n  [#2503, #2506, #2581, #2631]\n- Add snapshot testing coverage and cache validation for expected snapshot\n  metadata. [#2639, #2679]\n- Add stress testing fixtures with racy and crashing FFI examples. [#2683]\n- Add TLS stdlib tests and an HTTPS server test fixture. [#2572, #2576]\n- Add ecosystem and ACTMF application tests. [#2641, #2548]\n- Add more ecosystem applications to CI coverage. [#2641]\n- Add Linux container image builds from Debian packages. [#1404]\n- Build Debian packages on Ubuntu 22.04 and fix stack usage in build-debs.\n  [#2647, #2652]\n- Allow Telemetrify failures while macOS 26 support settles. [#2585]\n- Drop the shared Acton cache from CI. [#2605]\n- Drop Telemetrify from CI. [#2749]\n- Add build.zig generated-file gitignores. [#2656]\n- Close golden files after reading them during tests. [#2617]\n- Update GitHub Actions dependencies including checkout, cache,\n  upload/download-artifact, create-pull-request, Docker build actions, and\n  release-note extraction actions. [#2415, #2429, #2498, #2499, #2537,\n  #2544, #2558, #2559, #2560, #2561, #2669, #2670, #2684, #2685, #2686,\n  #2687, #2591, #2754, #2755]\n\n\n## [0.26.0] - 2025-06-02\n\n### Added\n- Add list, set, and dict comprehensions [#2258]\n- Add CLAUDE.md files for AI assistant guidance [#2262]\n  - Component-specific development guides\n  - Code style guidelines and best practices\n- Add Claude PR Assistant GitHub Actions workflow [#2261]\n\n### Changed\n- Expand numpy test suite [#2259]\n- Update install docs to remove architecture restrictions for APT repository [#2253]\n\n### Fixed\n- Fix cosmetic race condition in actor waiting queue operations [#2254]\n  - Ensure atomic setting of waitsfor link when entering waiting state\n- Fix handling of NotImplemented extension annotations [#2256]\n  - Keep annotations until CodeGen for proper constructor generation\n\n### Documentation\n- Document changelog update process before releases\n- Remove arch=amd64 restriction from APT repository documentation\n\n## [0.25.0] - 2025-04-23\n\n### Added\n- Acton Vim plugin for syntax highlighting & indent, see\n  https://github.com/actonlang/vim-acton\n- Add `crypto.hash.md5` module for MD5 hashing\n  - supports incremental updates and one-shot\n- Add `bytes.from_hex()` & `bytes.hex()` for hex encoding/decoding of bytes\n- Add `.str_ms()` to `time.Duration`\n- Add `max_def` and `min_def` functions that require a default argument\n  - Unlike max() & min(), these functions require a default value that is\n    returned when the input iterable is empty\n    - `max_def([1, 2, 3], -1)` returns 3\n    - `max_def([], -1)` returns -1\n- Add `re.split()` function to split strings based on regular expressions\n  - `re.split(\" +\", \"a  b   c\")` returns `[\"a\", \"b\", \"c\"]`\n- Add support for golden testing in the `testing` module\n  - Test functions can return a `str` to be compared against stored golden values\n  - `acton test` will show actual vs expected golden value\n  - Golden values are stored in `test/golden/MODULE/TEST_NAME`\n  - Update expected values with `--golden-update`\n- Unmangle actor class names in logging\n- Add `--no-threads` option to compile single-threaded applications\n- Set minimum thread stack size to 8MB to avoid stack overflows\n- Add better documentation for integer types in the guide\n- Add `__name__` variable containing current module name\n- Add `complex.from_real_imag()` function to create complex numbers\n- Add support for complex numbers as dictionary keys\n- Add proper implementation of the Logical protocol for integers\n- Add URI parsing module for handling HTTP URLs and other URIs\n- Add `--list-imports` option to actonc to show imported modules\n- Add a ConsoleSink to the logging module\n- Capture log messages in tests for easier troubleshooting\n- Add diff module for comparing strings\n  - Support for unified diff format with customizable context headers and colors\n- Add GitHub Action to create new releases automatically\n- Add support for ALPN (Application-Layer Protocol Negotiation) in TLS\n\n### Changed\n- Dict & Mapping methods `get` and `pop` now return `None` when key is not\n  found, instead of throwing KeyError\n  - Use new `get_def` & `pop_def` for explicit default values\n- Automatic backtrace printing on crashes disabled on non-Linux platforms\n  - LLDB on MacOS often hangs, so automatic backtrace printing is disabled\n- Make module paths in type error messages clickable for easier navigation\n- Improve `RunProcess` handling to properly await EOF for stdout/stderr\n- Disable garbage collection during package upgrade operations to improve performance\n- Silence build lock messages for dependency builds to reduce output noise\n- Use development mode (`--dev`) to build dependencies in test command\n- Don't store protocol witnesses in class attributes, push further into methods instead\n- Upgrade tlsuv library to v0.33.4 for improved TLS support\n- Enhance package dependency handling with support for transitive dependencies\n- Use a global dependencies directory in `~/.cache` for better dependency management\n- Improve testing output with deduplication of stdout/stderr messages\n- Colorize error messages for better readability\n- Reintroduce `--tempdir` option to actonc for manual control of temporary files\n- Allow integers to overflow for fixed-size integer types (i16, i32, i64, etc.)\n- Use diff for golden testing when outputs don't match\n- Rename common.mk to version.mk to better reflect its purpose\n- Make del operator idempotent for lists and dictionaries\n\n### Fixed\n- Fix type conversion between `u16` and `int`\n- Fix XML default namespace parsing\n- Fix error handling in process actor\n  - Process signals are now ignored if process has exited\n  - Better error handling around stdin/stdout/stderr operations\n- Fix volatile variables in try-except blocks to avoid compiler optimization\n  issues impacting control flow\n- Fix string format in `time.DateTime`'s RFC1123 format (month was off by one)\n- Improve error messages with better source location information\n  - Added location details for \"Missing constraint\" errors\n  - Added location details for \"missing tuple component\" errors\n  - Better error reporting when class method's first parameter doesn't match Self type\n- Fix dictionary iteration in relation context\n- Fix constructor functions for bounded integer types\n- Fix CPS transformation for nested lambdas with preprocessing requirements\n- Fix handling of main project local dependency overrides\n- Fix `zip()` function implementation\n- Fix left shift operator (`<<`) for integers\n- Fix XML encoding to properly handle UTF-8\n- Fix TCP connection close to properly mark socket as invalid\n- Fix hash function to avoid signed overflow undefined behavior\n- Fix depth subtyping for builtin collections (list, dict, set)\n- Fix discovery of root actor based on name\n- Fix `acton test --name` to correctly filter tests by name\n- Fix string allocation in `B_str` to properly account for byte length\n- Fix package upgrade correctness\n- Fix handling of XML comments during parsing\n- Fix main project dependencies in build.zig.zon\n- Fix polarity improvement handling in type solver\n- Fix exception handling in iterate-relation context\n- Fix `free()` behavior (now a no-op in GC environment)\n- Fix race condition in actor waiting queue operations\n- Optimize f-string parsing for better performance\n\n### Testing / CI\n- Add macos-aarch64 tip release build\n- Stop testing on Ubuntu 18.04\n- Install gdb in test-app environment for better crash analysis\n- Separate caches for Acton build and Stack/GHC in CI to avoid cache thrashing\n- Add caching for Linux ARM64 builds to improve CI speed\n- Ensure uniqueness of test artifact names to prevent collisions\n- Add support for Linux on ARM64 (aarch64) in CI\n- Add test of respnet (a real-world Acton application) to CI\n- Add testing on Ubuntu 24.04 for ARM64\n- Use artifact upload/download v4 for better performance\n- Add tests for all compiler passes\n- Await cache cleaning to avoid race conditions\n\n\n## [0.24.1] (2024-11-09)\n\n## Added\n- It is now possible to compare actors with `if a is b`\n  - This is a stop gap measure.\n  - Equality comparison requires the `Eq` protocol and this awaits the planned\n    actor / class unification work\n\n## Changed\n- Change `TCPListenConnection` callback `on_error(c, error: str)` to\n  `on_listen(c, error: ?str)`. Previously, the `on_error()` callback was called\n  if there was an error establishing the listening connection. It is now also\n  called in the positive case, when we have successfully established the\n  listening connection. If the `error` argument is `None`, all went well whereas\n  if it is set, there was an error.\n\n## Fixed\n- Dependencies are now idempotently fetched, i.e. if we first look if we already\n  have the configured hash locally and use that. We only fetch it if we don't\n  have a dependency locally.\n  - Previously, `acton build` would effectively require an Internet connection,\n    which is now fixed. Like now, you can do `acton fetch` in a repo to fetch\n    all dependencies locally and from there on you can work in \"airplane mode\".\n- Dependency hash mismatch is now correctly checked and treated as an error.\n\n### Testing / CI / Build\n- TCP tests have been rewritten to use the new `TCPListenConnection` `on_listen`\n  callback to properly sequence the test so we first establish the server and\n  then start the client. This removes a racy condition which lead to flaky test\n  failures.\n- Stopped testing on MacOS 12, which is EoL.\n\n\n## [0.24.0] (2024-11-05)\n\nActon now supports package dependencies and has a package manager to work with\nthese, fetching and building them. There are new docs at https://acton.guide\nIt's now possible to write Acton low level code in Zig, in addition to C.\n\n## Added\n- New docs: https://acton.guide\n  - Starting point was the Acton-by-Example and it's been improved from there\n    with new content and updates of existing pages\n  - New top level structure making it easier to navigate\n  - Includes a guide on how to integrate a C library\n- Package management!\n  - Acton now supports adding dependencies on other packages, either in a local\n    path or to be downloaded from the Internet.\n  - New commands, `acton pkg add` etc to manage dependencies, see\n    https://acton.guide for more\n  - This largely relies on the Zig package manager and the Zig build system\n  - It is also possible to add a Zig package dependency in an Acton project in\n    order to enable the integration with Zig / C / C++ libraries\n- Lots of improvements around the build system\n  - Upgrade to Zig v0.13\n  - Avoid anonymousDependency which is deprecated in newer Zig versions\n  - Materialize build.zig on disk, to allow customization, like adding\n    dependencies\n  - Send deps as zig CLI arguments instead of hacking builder imports\n  - Remove old extra headers, now included in Zig 0.13\n- Add `any()` and `all()` - does what it sounds like\n  - These were previously removed due to a bug but are now brought back\n- `json.encode()` now has a `pretty` option to enable pretty printing\n- `file.ReadFile()` & `file.WriteFile()` now support taking an advisory lock on\n  Linux and MacOS\n- `acton` now takes a project lock before compiling to avoid races\n- Revamped zig build caching, separating the local and global cache\n  - Only the local one is automatically periodically cleaned\n- Add support for writing Acton modules in Zig\n  - It is now possible to write functions in Zig, thus making the entire Zig\n    ecosystem potentially reachable with ease\n- Add new `base64` module to stdlib\n  - It is built on the Zig stdlib `base64` functions\n- Allow naming overlap in hierarchical modules\n  - It is now possible to have a module `foo` (src/foo.act) and a `foo.bar`\n    (src/foo/bar.act), which would previously conflict and yield a compilation\n    error.\n- Improved source location error messages\n- Upgraded to Haskell GHC 9.6.6\n\n## Changed\n- Add `remote_close` callback to TCPConnection / TCPListenConnection &\n  TLSconnection\n- Use `OSError` instead of `RuntimeError` for general exceptions in the `file`\n  module functions and classes\n- `argparse` `--help` now shows help for the most specific cmd\n- Remove worked thread CPU affinity to get compile speedup\n  - This is primarily as a workaround for slow Zig builds. For `acton build` we\n    run the acton compiler `actonc` and eventually `zig build`. Zig gets the\n    number of parallel worker threads to run by inspecting its affinity. When\n    started by Acton, it inherits the affinity of the worker thread that started\n    it.\n  - CPU affinity is probably a win for server workloads, so this is a\n    regression, but for desktop apps, it likely workb setter not pinning to CPU\n    cores\n    \n## Fixed\n- Fixed scope extension to handle accessing variables in else defined in try\n- Fixed CPS'ed __init__ so we can correctly instantiate actors in class init\n- Fixed passing function with mut effect to actor\n  - The actor seal leak detection would incorrectly trigger. We need a better\n    detector, until then the check is removed.\n- Fix returning fixed size integer\n  - The recent unboxing code misbehaved in some situations when trying to return\n    a fixed size integer from a function\n- Fix assert(Not)Equal\n  - Now actually works for None values, would previously only compare the values\n    if they were not-None\n- Fix qualified name checking, so we can properly detect method invocation via\n  class name even for imported classes\n  - This was an issue when importing a module and trying to call a @staticmethod\n    on a class\n\n## Testing / CI / Build\n- Stopped building the vendored libraries we ship, they are now shipped as\n  source and compiled on demand\n- Force hermetic build on MacOS\n  - Avoids pulling in system libraries\n- Simplify actondb build\n- Add dependabot config for updating GitHub Actions workflows\n- Add test on macos-15\n- Test other Acton apps in main Acton repo CI\n\n\n## [0.23.0] (2024-08-13)\n\n## Added\n- More unboxing of fixed size integers\n  - Function local variables are unboxed\n  - Passing fixed size integers as arguments between functions is also unboxed\n  - This adds an extra pass to the compiler to handle boxing and unboxing\n  - For some programs, the code is now pretty much optimal\n    - For example, the C code generated from `test/perf/src/dct.act` looks\n      pretty much as one would write it by hand and thus runs at about the\n      \"speed of C\". It does 0 mallocs and runs about 20x faster than before\n      unboxing (depending a bit on computer).\n  - class and actor attributes are still boxed\n    - This is likely the most important future work around unboxing since\n      individual mallocs for class & actor attributes typically account for a\n      the lion's share of GC pressure\n    - It is challenging around generics though\n- New `Set.update()` method to add items to a set from an iterable, such as a\n  list or another set\n- Added `--module` argument to `acton test` to select module to test\n  - For example, `acton test --module foo` to only run tests in module foo\n- Improved printing of test results for test modules that crashed\n  - The error is now printed for each individual test in the test module\n- Added `list.index(val, start=0, stop: ?int)` to get the first index of an\n  element in a list. It can be constrained through the start and stop\n  parameters.\n\n## Changed\n- `re.match()` now returns `Match` object where the group is `list[?str]`. It\n  used to be `list[str]` but it is possible to have groups that do not match on\n  anything and so `?str` is the correct type. This applies both for named groups\n  and normal numbered groups.\n  - For example, consider `foo((123)|bar)` which matches either `foo123` or\n    `foobar`. The inner `(123)` group is ORed and so it will have no match for\n    `foobar`, thus we get the result `m.group = [\"foobar\", \"bar\", None]`\n- `set.pop()` now throws `ValueError` for an empty set\n\n## Fixed\n- Fixed tuple type inference\n  - Tuples with named fields can now be properly type inferred\n- `acton test perf` now limits concurrency to 1 to get better results\n- Fix `str.strip()` on empty strings, it would previously return `\\n` but now\n  returns an empty string as it should\n- Fixes crash in `re.match()` for groups with no matches, which previously\n  resulted in `SEGFAULT`\n  - For example, consider `foo((123)|bar)` which matches either `foo123` or\n    `foobar`. The inner `(123)` group is ORed and so it will have no match for\n    `foobar`, thus we get the result `m.group = [\"foobar\", \"bar\", None]`\n    - This would previously crash but we now properly check the result values\n- Fix str slicing when range is 0 length which would previously `SIGILL`\n  - For example, for `a = \"foobar\"` if we would try to access `a[23:]`, there is\n    no character 23 and so the length of the slice is 0 which would trigger a\n    `SIGILL` when compiled in `--dev` mode (which comes with lots of extra\n    UBsan)\n- Fix dict corruption issue when deleting items #1805\n- `set.pop()` now does not crash for an empty list (it threw NULL before)\n- Fix decoding of buffered test output\n\n### Testing / CI\n- Added performance test to CI\n  - This runs on a dedicated computer, a laptop in Kristian's rack at home\n  - Runs `acton test perf` in `test/perf` which currently only includes the\n    `dct` program\n    - Simply add more test programs to the `test/perf` project to have them run\n  - The testing procedure is as follow:\n    - The CI test checks out the tests from the feature branch, so it will\n      always be the latest version of the test itself\n    - The latest tip release from acton main branch is installed and used to\n      compile the `test/perf` project\n    - `acton test perf --record` is used to run the test and record the result,\n      which will act as the baseline\n    - The acton release from the local feature branch is then installed (fetched\n      as artifact from the `build-debs` job)\n    - `acton test perf` is now run, which will run with the latest version and\n      compare the results against the baseline\n    - We do not currently inspect the results to give a pass / fail score,\n      they're just printed in the CI output for a human to look at\n    - Natural variance seems to hover around +-5%, which feels OK\n- Revamp PR testing to run on small set of platforms and run a nightly scheduled\n  test job that includes all platforms that were previously in the PR jobs\n  - This was triggered by the number of platforms reaching a higher number which\n    in turn has led to more cached data and as the GitHub Actions runner cache\n    is limited to 10GB, we hit the limit and got churn which meant that there\n    were always slow jobs. By reducing the number of PR jobs, they can continue\n    to run cached whereas the nightly jobs can run without a cache.\n- Stop CI testing on MacOS 11 as it has been deprecated by Github\n- Start CI testing on Ubuntu 24.04\n- Stop CI testing on Ubuntu 23.04 and 23.10 as they are EoL\n- Temporary fix of building Acton by using our own mirror for the Zig tar ball.\n  We are using a particular nightly v0.12.0 build that is no longer available\n  for download from ziglang.org and so we now mirror it ourselves. This affects\n  both builds in CI and local builds.\n- Fix GitHub Actions to run on Ubuntu 18.04\n  - The artifact download action uses Node.JS to run and as GitHub has imposed\n    constraints and new defaults, this has been magically updated to use a newer\n    version of Node.JS than before. The newer Node version is compiled using\n    glibc 2.28 and that's too new for Ubuntu 18.04, so the end result is that\n    you basically can't use the common GitHub Actions with Ubuntu 18.04 or\n    similar older distros. What a weird way to treat your CI users by GitHub!?\n    Anyhow, we work around this by explicitly enabling the use of the old Node\n    again.\n- Add caching for test-external-projects of C object files & archives\n\n\n## [0.22.0] (2024-04-14)\nSupport for Windows and continued improvements for `acton test`! Internally the\nbiggest change is the removal of link time redirection of malloc, which opens up\nfor more flexible memory management.\n\n### Added\n- Acton programs now run on Windows!\n  - It is now possible to compile Acton programs for Windows, both x86_64 and\n    aarch64, although since Acton itself (compiler etc) is not available on\n    Windows, only cross-compilation from MacOS or Linux is possible.\n  - Use `acton --target aarch64-windows-gnu examples/helloworld.act` to produce\n    `examples/helloworld.exe` which can be run on Windows\n  - Acton applications compiled for Windows are single threaded\n  - termios related terminal settings, is not supported on Windows\n- Acton RTS now supports actor cleanup through GC finalization\n  - Define a `action def __cleanup__():` action on your actor and it will be run\n    when the actor is about to be garbage collected\n- `acton build` now builds dependencies in `deps/` before building the main\n  project\n- `acton test` now excludes the time spent in GC from test times\n  - This is probably somewhat approximate and not super accurate, in particular\n    for tests with very short test durations\n- `acton test perf` is now expanded and support all kinds of tests (previously\n  only unit tests were supported)\n  - some memory usage is printed alongside timing information\n  - GC is run explicitly during perf test to get better memory usage stats but\n    it also slows things down a bit, in particular for very short duration tests\n- `acton test perf --record` can save a performance snapshot to disk\n  - Subsequent invocations of `acton test perf` will back the data from disk and\n    display a comparison with percentage diff\n- AbE: testing documentation is much improved!\n- `acton --only-build` performs only the low level build from .C source,\n  skipping compilation of .act files. This can be used if you want to modify the\n  C source by hand and still leverage the low level builder to perform the build.\n- `file.FS.cwd()` to get current working directory\n- `file.join_path()` to join path components\n- Link time redirection of malloc & friends is now removed. All malloc calls are\n  instead explicit, either directly to `GC_MALLOC` or via `acton_malloc` which\n  is our own malloc function which is runtime reconfigurable. While there is no\n  usage of malloc directly from our code, it is now possible to do manual\n  memory management mixed with GC managed memory.\n  - As before, module constants are placed in the regular heap, so that the GC\n    does not have to scan it.\n  - Many string formatting functions have been reshaped since `asprintf` does an\n    implicit malloc, which we must either free or avoid. As a result, we now\n    copy less data around, which speeds things up.\n- `process.Process` now takes an optional timeout argument to stop the process\n- New `process.RunProcess` that waits for a process to exit and then reports to\n  a callback with the buffered output from stdout / stderr\n  - This can provide a simpler interface than `process.Process` if you just want\n    to wait for the process to finish running before starting to parse its\n    output as you'll get a single invokation and the full output rather than\n    receive it piecemeal\n- Add `.unix_s()` `.unix_ms()` `.unix_us()` `.unix_ns()` to `time.Instant`\n  - To get a Unix timestamp (seconds since 1970-01-01 00:00:00), as seconds,\n    milliseconds, microseconds or nanoseconds respectively\n- `env.is_tty()` to check if stdout is a TTY\n- `acton.rts.start_gc_performance_measurement()` to start a GC perf measurement\n- `acton.rts.get_gc_time()` to get the GC timings\n- `env.is_tty()` to check if stdout is a TTY\n- `env.set_stdin(canonical: bool, echo: bool)` to set stdin options\n  - `canonical` is the default mode which is line buffered where the OS /\n    terminal offers line editing capabilities and we only receive the input ones\n    carriage return is hit\n  - setting `env.set_stdin(canonical=False)` turns stdin into non-canonical mode\n    where each character as entered is immediately forwarded to the stdin\n    callback so we can react to it, great for interactive applications!\n  - `echo` enables (the default) or disables echoing of characters\n- `term` improvements:\n  - More grey shades\n  - `term.clear` && `term.top` to clear and move cursor to top\n- `http.Client.close()` to explicitly close a connection\n- Single threaded RTS mode, only used by Windows for now\n\n### Changed\n- The work dir and environment arguments of `process.Process` have been moved to\n  the end as they are optional, making it possible to invoke with fewer args\n- Tests run by `acton test` are now compiled with `--dev` and thus have C\n  asserts enabled, similarly the test.hs that drives the test in the Acton repo\n  now compile with `--dev` to get C asserts\n- `acton test` now runs test for at least 50ms\n- `acton test perf` now runs test for at least 1s\n- Rename `--only-act` to `--skip-build`\n- Acton build cache now uses up to 15GB instead of 5GB\n\n### Removed\n- `actonc` no longer supports `--no-zigbuild` / `--zigbuild` (it's now the\n  default/only choice). It hasn't been tested in quite some time now and the zig\n  build system works well enough that there is basically no reason to keep the\n  old system around.\n- `actonc` no longer accepts `--cc` since we now always build using the zig\n  build system which implies the clang version that Zig ships.\n- `actonc` no longer supports explicit `--stub` compilation, use `--auto-stub`\n\n### Fixed\n- `key` argument in `KeyError(key)` is now of type `value`, not `list[None]`\n  which it was previously incorrect inferred as\n- `file.WriteFile.write()` now truncates file to avoid leftover tail of old\n  content\n- `time.Stopwatch().reset()` now works\n- Test crashes are now handled\n  - If the test program (e.g. `._test_foo`) crashes from an assert or similar,\n    the top test runner now captures this and reflects it in the output\n- Correct dependency path computation in builder\n- Makefile now more idempotent to avoid building when nothing has changed\n\n### Testing / CI\n- Test on MacOS 14 on Apple M1 / arm64 / aarch64\n- Many tests are now repeatedly 100 times to give some idea of stability\n\n\n## [0.21.0] (2024-03-13)\n\n### Added\n- `acton test` testing has been revamped, now doing multiple test iterations\n  - each test will be run for at least 1ms, for many smaller unit tests this\n    means the test case run hundreds of times\n  - all the internals have been rewritten to handle multiple tests results from\n    a test\n  - running multiple test iterations gives better performance measurement but\n    can also show flakiness in tests\n- `acton test list` will list all the test names in a project\n- `acton test --name foo --name bar` will filter to only run tests named `foo`\n  and `bar` in a project\n- AbE: explain testing with `acton test`\n- New methods to interact with environment variables [#1723]\n  - `getenv` & `getenvb` to read an environment variable\n  - `setenv` & `setenvb` to set an environment variable\n  - `unsetenv` & `unsetenvb` to set an environment variable\n  - The first set of functions work with strings and attempt to automatically\n    detect the encoding, although utf-8 is the only supported encoding by Acton\n    right now.\n  - The functions ending with `b` work with bytes data which can be used for\n    explicit control over encoding.\n- `env.stdin_install` now supports both `str` and `bytes` [#1723]\n  - It was orignally built to work with `str` which meant it decoded data from\n    stdin automatically. This assumed utf-8 encoding.\n  - `env.stdin_install` was then changed so the callback would get `bytes`,\n    which is technically more correct (it could just be bytes!) but leaves it to\n    the application programmer to decode data.\n  - A new interface now offers the best of both worlds:\n    - `env.stdin_install(on_stdin, encoding, on_stdin_bytes)`\n    - by specifying `env.stdin_install(on_stdin=my_cb)`, `my_cb` will be called\n      and get `str` input. The encoding is detected by reading the `LANG`\n      environment variable or defaults to `utf-8`. It is possible to explicitly\n      specify the encoding with the `encoding` argument.\n    - Use `env.stdin_install(on_stdin_bytes=my_cb)` to instead receive bytes\n- Acton now always compiles everything from source\n  - Previously, pre-compiled binary libraries were shipped for the native\n    target, so on x86_64-linux, there was a libActon.a compiled for x86_64-linux\n  - Now we just ship the source code of Acton base etc and perform the full C\n    compilation when we actually run actonc\n  - The first invokations of `acton build` is slow, taking up to a few minutes,\n    but as all results are cached, subsequent invokations run in fractions of a\n    second.\n  - `~/.cache/acton` is used to store the cache and it is wiped if it reaches\n    5GB after which it will be automatically re-populated when the next `acton\n    build` is called\n- Low level compiler support for dependencies\n  - Place Acton project dependencies in the `deps/` folder and the compiler will\n    automatically find them to allow inclusion of Acton modules from other Acton\n    projects\n  - This implements the low level internal support for finding modules in other\n    projects and correctly linking together the final output\n  - There is NO support for managing the dependency download itself or even\n    compiling the dependency\n- `SIGABRT` is now automatically handled by the crash handler for automatic\n  backtrace printing or interactive debugging, just like we already manage\n  `SIGILL` and `SIGSEGV`\n  - This simplifies debugging of Acton itself after catastrophic crashes\n- `file` module now has methods to interact with file system, like listing\n  files, making directories, stating files, removing files and walking directory\n  trees.\n- `file.FS.exepath()` returns the path to the current executable\n- `acton` now finds `actonc` by looking at its own location rather than assuming\n  `actonc` is on the path\n- Add `--only-act` to only perform Acton compilation and skip C compilation\n\n### Changed\n- `acton test` will compile test functions in dev mode to get asserts\n- The `dev` and `rel` folders have been removed, e.g. `out/rel/bin` -> `out/bin`\n- Printing of compiler pass debug output from individual files, like `acton\n  src/foo.act --types` will now only print output from the specified name and\n  not dependencies\n  - Previously, dependent modules, like if `src/foo.act` imports `bar`, we would\n    also print the types debug output for the `bar` module\n  - Printing of compiler pass debug output requires recompiling the module and\n    thus shortcutting the up-to-date check. By not printing output for included\n    modules, the included modules do not need to be recompiled thus speeding up\n    the whole compilation.\n- Always link in libprotobuf-c to allow modules to use protobuf tech\n- Improved argparse parsing by doing a descent first parsing of options and into\n  sub-commands with positional argument parsing happening as a second pass\n  [#1714]\n\n### Fixed\n- `acton new foo` now creates a new project `foo`\n- Fixed handling of failing tests in `acton test` [#1709]\n- Fixed required since self is now parsed as a kwd param [#1715]\n- Upgrade GC\n  - Now ignoring `free()`. This was also previously the case but this was lost\n    when we upstreamed the new build.zig for bdwgc. It is now back, which is\n    required for handling the \"edge\", like where syscall / libc calls do malloc\n    and then free. uv_fs_scandir is an example of such, which was recently added\n    and triggered a bug.\n  - Incremental collection has been fixed on Linux so that it should work,\n    although it is not supported by the Acton RTS. Incremental collection is\n    likely much slower for most programs but with better responsiveness. It\n    could potentially be better for very large heaps as well as overhead of\n    virtual dirty bit now only hits from a very small heap. It remains to be\n    seen.\n- `testing.test_runner` has been fixed with regards to scheduling, now we\n  actually wait for a test kind to be completed before proceeding to the next.\n  Previously for async tests we would spawn all tests immediately and then\n  proceed to next test category, so we would oversubscribe the tests runners\n  giving worse performance.\n- Various fixes to test output, like count of tess was wrong\n- numpy now compiles and runs. There are new tests cases!\n\n### Testing / CI\n- Tests, like of builtins etc, now run with `--dev` so we get assertions\n\n\n## [0.20.1] (2024-02-22)\n\n### Fixed\n- Install `acton` frontend in Debian package\n\n## [0.20.0] (2024-02-22)\n\n### Added\n- New `acton` CLI which takes over as the main acton program, it should be\n  called instead of `actonc`, for example `acton build` [#1645]\n  - it calls into `actonc` for doing most of the work and is currently mostly\n    just a thin wrapper\n  - over time, more functionality will be placed in the `acton` frontend\n- New `acton test` command which build and runs all test in a project [#1645]\n- The compiler now does automatic test discovery\n  - Simply doing `import testing` and functions with a name starting with\n    `_test` will be identified as a test and run by `acton test`. The functions\n    are sorted into categories based on their type signature.\n- Run-time reconfigurable `malloc`\n  - It is now possible to reconfigure which malloc to use during runtime\n  - All external libraries (libuv for example) are now configured to use a\n    particular malloc\n  - Libraries that did not support a custom alloc have now been extended with\n    support for custom malloc.\n- Module constants are placed in non-GC heap\n  - Using the reconfigurable malloc, we now make use of the \"real\" malloc (the\n    one libc provides) during startup of RTS and up past module init. This means\n    all module constants will be placed on the normal heap and not the GC heap.\n  - The GC is mark & sweep which means it slows down considerably when there is\n    a large live heap.\n  - This makes is a viable option to place large amounts of data as module\n    constants instead of run time state to speed up programs.\n- Fixed size integers arithmetic and comparisons are now unboxed\n  - For math heavy programs, this can produce a 4x improvement\n  - A lot of witnesses are now unnecessary and thus removed, reducing GC pressure\n- `testing` module has gotten a face lift with much better asserts\n  - The assert exceptions now include and print the values\n  - Formatting happens in `__str__` so performance of exceptions is unchanged\n- New `snappy` module in stdlib [#1655]\n  - Snappy is a fast compression library\n  - Snappy is written in C++ which implied some changes to build.zig and actonc\n- It is now possible to print a .ty file by doing: `acton foo.ty`\n- Improved size & performance of dictionaries\n  - An empty dictionary is now completely empty\n  - For low number of elements, the dictionary is actually a list with linear\n    searching\n  - For 5 elements and up, the dict starts to use a hashtable\n- `KeyError` & `IndexError` now include key  / index so it's easier to\n  understand what went wrong\n\n### Changed\n- The Debian package of Acton now depends on libc 2.27 [#1645]\n  - Previously depended on the glibc installed on the the build machine (2.36)\n    since it was expanded from `${shlibs:Depends}`\n- Now using Zig 0.12.0-dev.2236\n  - the build system has changed somewhat so all build.zig files are updated\n- DB backend is now optional, include with `acton build --db`\n- Using newer version of tlsuv library\n- RTS main thread now runs special actors, currently just `Env`\n  - This enables us to install signal handlers from `Env` since this must be\n    done from a programs main thread.\n\n### Fixed\n- `dict` changed internally to allow storing of `None`\n- Support `None` in JSON\n  - Based on the improved support of dicts\n- `lstrip`, `rstrip` & `setdefault` now work properly\n- Fix effect of `json.encode()` and `json.decode()` [#1654]\n  - They are pure!\n- Fix `testing.test_runner` when there are 0 tests to run [#]\n- Add tests of client & server in `http` module\n- `argparse` module now supports nested command parsing\n- `argparse` module now supports `--` for literal interpretation of positional\n  arguments\n- Fix compilation of projects that used TLS\n  - We had missed linking in all necessary mbedtls libraries\n\n\n## [0.19.2] (2024-01-15)\n\n### Added\n- `argparse` now supports optional positional arguments\n  - like so: `p.add_arg(\"foo\", \"Foo thing\", required=False, nargs=\"?\")`\n- `print()` now takes multiple new input arguments:\n  - `print(*vals, sep=\" \", end=\"\", stderr=False, flush=False)`\n  - `sep` is the separation character between values, default \" \"\n  - `end` is the line ending character, default \"\\n\"\n  - Output is written to stdout per default, set `stderr=True` to write to\n    stderr instead\n  - set `flush=True` to flush the output\n- new `--rts-bt-debug` flag that launches interactive debugger (`gdb`) on\n  SIGSEGV / SIGILL\n\n### Changed\n- `print()` now formats to a temporary buffer before printing to reduce\n  interleaving multiple outputs\n- `printn()` has been removed in preference of using `print(foo, end=\"\")`\n\n### Fixed\n- `KeyError` now includes the key as part of the error message\n  - e.g. `KeyError: getitem: key not in dictionary, key: foobar`\n  - The string formatting of the error message including the key only happens\n    when the str representation of the exception is necessary, so it does not\n    incur a performance penalty in normal scenarios\n  - The key for which the lookup was attempted is stored in the `key` attribute\n- Homebrew Formula now somewhat decoupled from Stack version [#1627]\n  - Idiomatic Homebrew Formulas use system-ghc, i.e. a GHC version installed by\n    Homebrew itself and not from Stack. Since we specify a Stack LTS resolver,\n    which is a coupled to a particular version of GHC, there is room for a\n    version mismatch.\n  - The latest occurrence of which was GHC 9.4.8 in Homebrew vs Stack LTS 21.13\n    with GHC 9.4.7. A rather silly small mismatch but that nonetheless breaks\n    the Homebrew build. This is particularly annoying because it happens only\n    after we've made a release, so the feedback is too late and thus a\n    correction version must be released to fix the version mismatch (we've\n    upgraded to LTS 21.25 with GHC 9.4.8 to align on Homebrew).\n  - Now `skip-ghc-check` is used to skip the GHC version check to allow some\n    minor mismatch to happen. We must still ensure that at least the major\n    version of GHC is aligned, like GHC 9.4.\n    \n    \n## [0.19.1] (2024-01-08)\n\n### Fixed\n- Upgraded Stack to 21.25 / GHC 9.4.8\n  - This should hopefully fix the Homebrew build\n\n\n## [0.19.0] (2024-01-08)\n\n### Added\n- Much improved argument \"rows\" support [#1609] [#1617], including:\n  - positional & keywords arguments\n  - default argument values\n- `up`, `down`, `left` & `right` in `term` module now accept `n` arg [#1619]\n  - can move multiple steps in given direction\n\n### Changed\n- for `http.Client` the following positional arguments are now keyword args:\n  - `schema`: defaults to `https`\n  - `port`: defaults to `80` for schema `http` and `443` for `https`\n  - `tls_verify`: default `True`\n  - `connect_timeout`: default `10.0`\n\n### Fixed\n- Remove superfluous explicit arguments, now using default values [#1615] [#1618]\n- Now possible to print `None` [#1609]\n\n### Testing / CI\n- Now testing Telemetrify in GitHub Action workflow as part of CI testing\n  - Telemetrify is the largest known application written using Acton, so we add\n    testing of it to the Acton repo to avoid accidental breakage\n  - Telemetrify main branch is already tested with the latest release of Acton\n  - now, new changes in acton are also verified against the telemetrify repo\n  - we test against the `acton-next` branch in the telemetrify repo\n    - this enables us to make breaking changes in the Acton repo, realize the\n      break, then write a fix adapting the telemetrify code to the new Acton\n      change and push this to the `acton-next` branch after which the PR on the\n      Acton repo can be retried\n\n\n## [0.18.5] (2023-12-12)\n\n### Testing / CI\n- Fix build of APT repo\n\n\n## [0.18.4] (2023-12-12)\n\n### Fixed\n- Add constraint forcing type of self parameter [#1598]\n- Let solver use upper bound of type variable when reducing protocol constraints\n- Remove subclass constraint on isinstance parameters\n- Type error message improvements [#1522] [#1589] [#1596]\n- Fix `actonc --debug` [#1591]\n  - Now also printing zig output\n  - `--verbose` has been removed\n\n### Testing / CI\n- Stop testing on MacOS 11 [#1600]\n  - Homebrew has dropped support for MacOS 11 so the CI job had to build stuff\n    from source making it super slow and fragile, thus dropping it.\n\n\n## [0.18.3] (2023-11-21)\n\n### Added\n- `type()` function that provides the type of something as a string [#1587]\n  - Can be really useful as development tool to get inferred types or similar\n  - It should not be used for metaprogramming or similar\n  - This will likely be removed in the future when there is a better way of\n    debugging types, like a language server\n    \n### Fixed\n- Only print truly unhandled exception [#1586]\n  - \"Unhandled\" Exceptions are no longer printed in actor methods called by\n    another actor that awaits the return value\n  - It used to be that when an actor B raised an exception in a method called by\n    actor A, presuming no try/except handling at all, an `Unhandled exception`\n    message would be printed in both actor A and B.\n  - Now we inspect waiting actors and in case there are any, the exception will\n    be considered \"handled\" in the actor method that raised the exception\n- Cleanup old cruft from Makefile [#]\n- Now using zig v0.12.0-dev.1536\n  - Improved CPU feature detection for Apple silicon\n  - Some smaller zig build system changes, but it seems to be stabilizing as\n    there are now docs!\n- Acton now builds on Apple Silicon MacOS [#1582]\n  - It used to not understand the CPU features and thus MbedTLS would fail to\n    compile\n  - With zig v0.12.0, the correct CPU features are recognized\n- Fix int rounding [#1577]\n- Improve DNS error handling in net.TCPConnection [#1573]\n  - Ignore DNS resolution errors if we're already in connected state\n  - Given happy eyeball support, we could get a A record and establish a working\n    IPv4 connection while IPv6 would give an error and be retried continuously,\n    which is completely pointless when IPv4 is already established.\n- Type error now separate error from identifier with `:` [#1583]\n\n### Testing / CI\n- Now also testing build / test and running on Ubuntu 23.10\n- There are now golden tests for the compilers type errors [#1571]\n\n\n## [0.18.2] (2023-10-31)\n\nA real fix this time to the Debian APT repo.\n\n\n## [0.18.1] (2023-10-31)\n\nA small fix for Debian builds.\n\n### Fixed\n- Align Debian package building on bookworm / 12\n\n\n## [0.18.0] (2023-10-30)\n\n### Added\n- Exceptions now have a `__str__()` method used to print the exception\n  - useful for exception types where we want to be able to include dynamic data\n  - string formatting of dynamic log messages is expensive, so we don't want to\n    incur that cost for exceptions that are thrown but never printed\n  - add extra attributes and print them in `__str__()` in your custom exceptions\n- Add `testing` module [#1524] [#1552]\n  - Supports four categories of tests:\n    - unit tests: `proc() -> None`, think pure functions\n    - synchronous actor tests, involves actors\n    - asynchronous actor tests\n    - env tests\n- Improvement to type error messages [#1554] [#1556] [#1559]\n- Add `term` module\n  - a couple of small helpers for doing colored text and similar in terminals\n- Add `random.choice()` & `random.choice()` [#1541]\n- Add `printn()` is like print but prints without an ending newline\n  - also flushes output immediately, useful to print progress style output\n  - this is temporary and will be removed once default argument handling is\n    properly implemented\n- Add `math.pi = 3.141592653589793` [#1539]\n- `acton.rts.enable_gc()` & `acton.rts.disable_gc()`\n  - there are situations in which it can be useful to turn off the GC, such as\n    during certain test scenarios\n- `acton.rts.get_mem_usage()` returns memory usage [#]\n  - approximate output due to how the GC works\n- Add `uri` module [#1560]\n  - Features a `parse_http()` function to parse a HTTP URL into its parts\n\n### Changed\n- Reverted to global single threaded malloc [#1547]\n  - There have been some reports of errors that could potentially be related to\n    per-thread malloc or DNS lookups. In caution, the per-thread malloc has been\n    disabled and will be brought back in a safe way once we've been able to test\n    it much more thoroughly.\n- Integer division by zero now results in exception `ZeroDivisionError`\n  - for `float`, `inf` is returned [#1530]\n    - this is aligned with IEEE & languages like C, Zig, Rust, Swift, Julia\n    - Python raises an exception on float divide by zero\n- Haskell Stack updated to LTS 21.13 using GHC 9.4 [#1517]\n  - Some tests show actonc running ~25% faster\n    - Presumably thanks to more optimizations in ghc\n  - C++ seemingly pulled in as a dependency for building Acton itself :(\n    - Would be nice to use zig c++ but alas, that does not work\n- `actonc` now always built statically on Linux\n  - Previously it was only built statically in release mode\n  - It does emit some errors / warnings around using dlopen but those are\n    harmless and can be ignored in our case\n- commands in `argparse` now expect `proc()` rather than `pure()`\n- JSON encode/decode are now free functions [#1536]\n  - the JSON encode and decode functions were implemented as methods on an actor\n    due to an earlier actonc bug\n  - bug is fixed, so `encode()` and `decode()` are now moved to free functions\n    in the `json` module\n  - the old `Json` actor remains and simply wraps the free functions\n\n### Fixed\n- Fix error handling in `net.TCPConnection` for single family use [#1546]\n  - original error handling presumed a dual stack socket and so would wait for\n    both IPv4 and IPv6 to report an error before propagating the error to the\n    caller\n  - now if only a single address family is used, errors are immediately sent to\n    the caller\n- Fix error handling in `net.TCPConnection` for dual stack use [#1527]\n  - while the original design focused on this use case, there was a bug\n- Honor `--root`\n  - the automatic detection of root actors based on the name `main` would\n    previously override a manually provided one\n- Fix time difference calculation when underflowing\n- Fix add / sub duration & comparison for `time.Instant` [#1545]\n- Fix premature conversion of input to close converter [#1553]\n\n### Testing / CI\n- Now building .debs on Debian 12 / bookworm\n- Avoid DNS lookups in test [#1551]\n  - We have a likely bug around DNS lookups that hits on MacOS. Work around by\n    using \"127.0.0.1\" rather than \"localhost\" in tests.\n\n\n## [0.17.0] (2023-09-25)\n\nActon now has exceptions, how exceptional!\n\n### Added\n- Add support for exceptions! [#1463]\n  - The syntactic support for exceptions has existed for a long time but the\n    underlying run time support was not implemented. It now is!\n    - It used to be that exceptions would exit the whole application without any\n      means of catching an exception.\n  - Unhandled exceptions are now printed to stderr [#1481]\n    - Do note however that unhandled exceptions will not exit the program nor\n      even the actors encountering an exception. It will abort the execution of\n      the current method and nothing else.\n- New `http` module [#1485]\n  - `http.Client` is a HTTP client that supports unencrypted HTTP on port 80 and\n    HTTPS using TLS on port 443\n  - `http.Listener` / `http.Server` is a HTTP server component that currently\n    only supports unencrypted HTTP (due to lack of a `net.TLSListener`)\n  - Supports chunked transfer-encoding [#1510]\n- New `logging` module [#1483]\n  - Provides logging functionality in an actor centric world\n- New `argparse` module [#1499]\n  - Command line argument parsing!\n- `net.TCPConnection`: A new TCP client connection actor [#1398]\n  - Support DNS lookups so the input address can be a name rather than an IP\n    address\n    - It is still possible to connect using an IP address\n  - Supports Happy Eyeballs (RFC6555) which uses both IPv4 and IPv6\n    simultaneously to connect using the fastest transport\n    - Happy Eyeballs is only used for hostnames. If an IP address is provided,\n      we connect directly to it.\n- `net.TLSConnection`: A new TLS client connection actor [#1470]\n  - A simple TLS client connection actor. It supports disabling TLS certificate\n    verification for testing purposes.\n  - Using the MbedTLS library and tlsuv under the hood.\n- `net.is_ipv4(address: str) -> bool` tells you if something is an IPv4 address\n- `net.is_ipv6(address: str) -> bool` tells you if something is an IPv6 address\n- AbE: Documented capability based security [#1267]\n- The class name of exception errors is now printed on exception [#1423]\n- `actonc build --cpedantic` now works, it was previously only supported for\n  single files [#1438]\n- It is now possible to have mutually recursive definitions between function\n  defs, classes and actors [#1433] [#1435]\n- RTS now uses a per thread malloc implementation [#1456]\n  - `malloc` is part of libgc which has two flavours, a global malloc with a\n    lock and a per thread allocator\n  - During the restructuring to use Zigs build system, the compilation option to\n    use the per thread allocator was lost. It is now back!\n  - For parallel workloads across multiple RTS worker threads, there is a clear\n    bottleneck around malloc... not very surprisingly ;)\n- RTS readyQ and per actor message queue has been optimized [#1456]\n  - There is now a tail pointer which significantly speeds up insertions\n  - The fields have been slightly reorganized to allow the most important fields\n    early so it can be fetched in one cacheline\n  - Before, having many concurrent actors with many outstanding messages would\n    scale poorly, on an AMD 5950X running the pairs benchmark:\n    - before:\n      -    1 actor pair & 1   token: ~4M continuations per second\n      -   10 actor pair & 1   token: ~650K continuations per second\n      - 1000 actor pair & 1   token: ~280K continuations per second\n      - 1000 actor pair & 500 token: ~280K continuations per second\n    - after readyQ tail optimization:\n      -    1 actor pair & 1   token: ~3.8M continuations per second\n      - 1000 actor pair & 1   token: ~3.6M continuations per second\n      - 1000 actor pair & 500 token: ~700K continuations per second\n    - after msg queue tail optimization:\n      -    1 actor pair & 1   token: ~3.8M continuations per second\n      - 1000 actor pair & 1   token: ~3.6M continuations per second\n      - 1000 actor pair & 500 token: ~3.6M continuations per second\n  - This is an artificial benchmark where there is extremely little real work\n    done, so continuation switching becomes the dominant load. Thus, the\n    bottleneck becomes the global readyQ. Using more than 1 worker thread only\n    leads to lock contention and so the benchmarks are for 1 worker thread.\n    - Since the actor message queue is per actor, it is possible that multiple\n      worker threads could work faster but in practice they step on each others\n      toes enough around the global readyQ that it is slower overall.\n\n### Changed\n- `net.TCPIPConnection` is removed and replaced by `net.TCPConnection`\n  - Originally opted to add `net.TCPConnection` now and phase out\n    `net.TCPIPConnection` later but as there is already a breaking change with\n    the change of Auth -> Cap so all user code related to networking (and other\n    things) need to be changed, we might as well change from\n    `net.TCPIPConnection` to `net.TCPConnection`\n- `DNS` actor is replaced with lookup functions [#1406]\n  - The `DNS` actor is removed, the `lookup_a` & `lookup_aaaa` methods it has\n    are now free functions in the `net` module, i.e. simply call `net.lookup_a`\n  - It was originally an actonc shortcoming that lead to the design with a `DNS`\n    actor - it was intentional, so this is more of a cleanup\n- Renamed authentication concept to \"capabilities\" [#1402] [#1407]\n  - In order to better reflect the mental model and intuition we want to instill\n    in users of Acton, Auth objects are renamed to Cap\n    - With a reference to a capability, we can use that capability. This aligns\n      with the existing security model for the internal actor domain where an\n      actor must hold a reference to another actor in order to call its method.\n    - We want to extend that mental model for all external things in the world\n      as well.\n  - All `*Auth` objects now have a `Cap` suffix\n  - All `auth` args are renamed to `cap`\n- `SysCap` is a new capability for functions related to Acton RTS System\n  internals [#1388]\n  - `SysCap` is available from `env.syscap`\n  - `SysCap` is separate from the normal capability hierarchy where `WorldCap`\n    is the root\n    - This is to promote the aspiration to restrict access to RTS internal\n    - While `WorldCap` shouldn't be passed around frivolously either,\n      capabilities should restricted and delegated, it is still fairly normal to\n      pass `WorldCap` while the vast majority of programs should not even need\n      `SysCap`\n- The `msg` of exceptions is now optional [#1422]\n\n### Fixed\n- Fix control flow bug for `continue` in `for` loop [#1265]\n- Fix control flow bug for `return` in `while loop` [#1194]\n- Fix comparison of optional types [#1186] [#1506]\n- Fix necessary casts for bool checks on tuple field [#1500] [#1504]\n- Throw exceptions for unimplemented builtins [#1010]\n  - Previously printed to stderr and did `exit(1)`\n  - Now throws a `NotImplemetedError` instead!\n- Failed dict key lookups now throw `KeyError` [#1499]\n  - Previously incorrectly raised `IndexError`\n- Document use of `--sigs` in Acton-by-Example [#1405]\n- Fix up-to-date check for stub compilation [#1399]\n- Improve support for alternate output in actonc [#1395]\n  - When alternate output is enabled, like `actonc --types`, now uses quiet\n    mode, thus suppressing various progress messages which interferred with the\n    alternate output\n  - Avoid errors when compiling files without a root actor\n- Clean up old generated output files [#1411]\n  - When the source files is moved or removed, also remove the corresponding\n    output files\n- Fix return value of int hashable [#1415]\n- Fix module import check [#1420]\n- Avoid segfault when exception `error_message` is not set [#1422]\n- Bump Zig version to v0.11.0 [#1421]\n- Fix `reversed([])` which would `SIGILL` in dev mode [#1455]\n- Fix `reversed([1,2,3])` which now returns reversed result [#1455]\n  - Previous code did the reversal but returned the original value :P\n- Fix `i64` comparisons like eq/ne/etc [#1459]\n  - Would just return the wrong results, like `i64(0) == i64(0)` would not\n    return `True`. Now works as they should!\n- Fix list add with empty list input, like `[1]+[]` [#1461]\n  - Used to segfault, now works as intended\n\n### Testing / CI\n- Stop testing on Ubuntu 22.10 since it is End of Support\n\n\n## [0.16.0] (2023-07-03)\n\nPrimarily addition of simplified TCP reconnection, related fixes and functionality.\n\n### Added\n- Add `.close()` and `.reconnect()` on TCP client actor [#1383]\n  - It is now possible to explicitly close or reconnect a TCP client\n- Add RTS Monitor actor in `acton.rts.Monitor()` [#1383]\n  - The RTS Monitor actor starts a worker monitor per worker thread, each pinned\n    to a particular worker thread. By doing so, it can retrieve information from\n    each worker thread in safe manner, honoring the RTS design.\n  - Currently just supporting getting handles from I/O subsystem.\n- Add `env.nr_threads` [#1383]\n- Add `set_actor_affinity(wthread_id)` [#1383]\n\n### Changed\n- Include DNS query hostname in `on_error` cb [#1382]\n  - Simplifies retrying a query since we otherwise do not have a persistent\n    tracking object per query\n\n### Fixed\n- Fix `--rts-debug` [#1383]\n  - Has been broken since new builder but is now fixed\n- Fix off-by-one in worker thread wake up [#1383]\n  - Waking all threads would not consider all threads as there was an off-by-one\n    error.\n  - No known problems in the field from this, it was only noticed in development\n    using --rts-wthreads=1\n    - The RTS uses at least 4 workers per default\n- Use relative source file path in logs [#1383] [#1391]\n  - `__FILE__`, set by the C compiler, is used to include source file path in\n    log messages\n  - Zig uses absolute paths to all files\n  - now using `-ffile-prefix-map` to make path relative\n  - project dir name also included, for example `base/rts/rts.c`, to make it\n    easier to understand from which project a file comes from\n- Assignment in multiple branches [#1390] [#1392]\n  - Only assigning in multiple branches (not before branches) would lead to\n    redefining shadowing variable of outer scope in low level generated C code\n  - Info guiding joined assignment has been fixed\n\n### Testing / CI\n- Verify we cannot instantiate WorldAuth\n\n\n## [0.15.3] (2023-06-27)\n\n### Added\n- `actonc --cache CACHEDIR` can be used to specify the build cache directory\n\n### Fixed\n- static compilation with Musl libc is now possible on Linux [#1372]\n  - adjusted to adjtimex\n- hashing for `int` now supports values outside of `i64` [#1348] [#1367]\n- fix `__pow__` to avoid compiler optimization bug [#1371]\n- bump Zig version [#1374]\n  - avoids \"File not Found\" error\n- text color in SVG in docs now follow font color [#1365]\n- fix hooking of thread creation to inject signal handler wrapper for stop the\n  world [#812]\n- corrected arguments passed to `on_error` callback of `net.DNS` related lookup\n  functions [#812]\n  - .act file specified 2 arguments to the `on_error` callback while the .ext.c\n    file only sent a single argument\n\n### Testing / CI\n- cross-compilation is now tested in CI in all jobs for these targets:\n  - `aarch64-macos-none`\n  - `x86_64-macos-none`\n  - `x86_64-linux-gnu.2.27`\n  - `x86_64-linux-musl`\n- CI uses `--cache` to place build cache in `~/.cache/acton/test-build-cache`,\n  which is in turn cached in CI\n  - the cross-compilation testing meant testing went from ~1 minute to ~3, with\n    caching it remains at around ~1 minute\n\n\n## [0.15.2] (2023-06-16)\n\nElevate Acton's build capabilities by completing the adoption of the Zig build\nsystem. Everything, including external library dependencies, builtins, RTS,\nstdlib and backend, is now built using build.zig files. A hierarchy of zig\nmodules are formed, which allow building the entirety of the Acton system with a\nsingle zig build, which is what actonc calls internally. This enables complete\ncontrol over all aspects of the low level compilation.\n\nThe most striking feature unlocked is likely cross-compilation:\n\n  $ actonc --quiet helloworld.act \n  $ file helloworld\n  helloworld: ELF 64-bit LSB executable, x86-64, version 1 (SYSV), dynamically linked, interpreter /lib64/ld-linux-x86-64.so.2, for GNU/Linux 2.0.0, with debug_info, not stripped\n  $ actonc --quiet helloworld.act --target x86_64-macos-none\n  $ file helloworld\n  helloworld: Mach-O 64-bit x86_64 executable, flags:<NOUNDEFS|DYLDLINK|TWOLEVEL|PIE>\n\nLibraries for the local platform are still prebuilt and included in the Acton\ndistribution, hich are used when using the default target, i.e. targetting the\nlocal machine. For any customization to the target, everything will be built\nfrom source.\n\n### Fixed\n- revamped low level build, now potentially rebuilding entire Acton system from\n  source code\n  - allows cross-compilation and similar advanced features\n  - use `--target` for cross-compilation, e.g. `--target aarch64-macos-none` to\n    target an Apple M1 computer\n  - for Acton projects, there is now a `build-cache` directory that caches all\n    built output and speeds things up tremendously\n- `json` module now correctly encodes and decodes floats [#1345] [#1349]\n- zig build of all external library dependencies\n  - gives us much better control over how libraries are compiled\n  - much much faster! autoconfig is really slow!\n    - e.g. building protobuf-c takes a few seconds on a 2015 MBP while with\n      autoconf, it spends > 1 minute trying to figure out capabilities of the\n      C++ compiler, despite the C++ parts of libprotobuf-c not being enabled!\n    - the debian test job now often build Acton in less than 3 minutes, macos-13\n      often run in ~4 minutes - a real improvement!\n  - libargp [#1336]\n  - libbsdnt [#1337]\n  - libgc [#1344]\n  - libnetstring [#1325]\n  - libpcre2 [#1331]\n  - libprotobuf-c [#1341]\n  - libutf8proc [#1332]\n  - libuuid [#1340]\n  - libuv [#1334]\n  - libxml2 [#1333]\n  - libyyjson [#1323]\n  - remove libbsd & libmd as dependency [#1329]\n    - only use was of arc4random in numpy, which is now rand using()\n- backend is now built using zig [#1346]\n- use curl instead of git clone to fetch dependencies [#1343]\n  - much faster and reduced disk usage\n\n### Testing / CI\n- caching has been vastly improved in CI\n  - based on the new zig build system, we utilize zigs excellent caching\n    capability by using a single zig cache for the entire build of Acton. In CI,\n    we cache the zig-cache directory, so we don't actually have to recompile\n    files at all. Some CI runs now take less than 2 minutes to build Acton!\n  - we should be able to  trust Zigs caching to do the right thing, if files are\n    modified it will notice!\n- testing of the Homebrew Formula has been removed [#1338]\n  - since some time, this test job has been intermittently failing, or rather\n    only intermittently passing as most of the time it fails\n  - to avoid lots of errors in CI, the job has been removed\n  - the failures are likely coming from some change in brew behavior\n  - we use a fairly hacked up and not supported workflow\n  - several attempts to fix it have been unsuccessful and we're unable to spend\n    more time on it right not\n- removed test of compiling Acton on Ubuntu 20.04 due to problems with stack\n  - note how executables built by actonc are still compatible with Ubuntu 20.04\n\n\n## [0.15.1] (2023-06-02)\n\nA better strategy for constraint solver results in vastly lower constraint\nsolving times and thus reduced overall compilation times. Large improvements in\ncode generation resulting in less memory allocations and thus a much lower load\non the GC, yielding much better runtime performance.\n\nThe internal compilation of generation C code has been revamped, now more\nstructured and simplified in many ways, internally making use of the Zig build\nsystem which in turn unleashes a lot of benefits.\n\n### Changed\n- release builds now use `-O3` and dev builds use `-Og` [#1270]\n- Collection overloading has been removed [#1316]\n  - It was previously possible to overload collections like dict / Mapping\n  - {} now always means the builtin dict\n\n### Fixed\n- Faster constraint solver through new strategy [#1316]\n  - Evaluates vastly fewer possibilities\n  - One application used to take over 10 mins for constraint solving which now\n    runs in roughly 10 seconds - woohoo\n- New second stage compilation of generated C code [#1249] [#1304]\n  - new `builder` performs \"second stage\" compilation of the C code that\n    `actonc` generates into object files, archives and executable binaries\n  - Built on Zig's Build System, gaining all that it offers\n  - Very good caching, dependency detection, up-to-date checking and concurrency\n  - Custom compilation to make `builder` itself portable\n  - Compilation can now be more clearly separated in two steps:\n    - step 1: `actonc` compiles `.act` to `.c` & `.h`\n    - step 2: `builder` compiles `.c` & `.h` to `.o` & `.a` & executables\n  - Up-to-date checking in actonc adjusted to only compare `.act` with `.c` &\n    `.h` output\n  - `builder` does a fantastic job of following dependencies (looking at\n    `#include` statements etc) to figure out when things need to be recompiled\n  - All of this is internal, `actonc` calls `builder` under the hood, much like\n    it earlier called `cc` under the hood\n  - `--no-zigbuild` can be used to force old compilation method\n    - `--no-zigbuild` will be removed in the future\n- Much faster build of Acton itself using prebuilt libActonDeps [#1279] [#1282]\n  - Uses a checksum of git refs of all lib that constitutes libActonDeps\n    - If any dep lib is updated to use new version, libActonDeps will be rebuilt\n  - Uploaded to github.com/actonlang/libactondeps and downloaded on demand from\n    normal Makefile, thus used for local builds and in CI\n  - Falls back to local compilation if prebuilt version is not available\n- builtins, RTS & stlib now organized as an Acton project called `base` [#1309]\n  - More streamlined towards imagined design of how project dependencies will\n    work in the future, meaning less special kludges\n  - Cleans up include paths and similar, avoiding potential naming conflicts\n- builtin code is now generated [#1256] [#1260]\n  - `__builtin__.c` and `__builtin__.h` are now generated from `__builtin__.ty`\n    at build time, whereas they were earlier checked in to git, having once been\n    generated but heavily modified by hand\n  - given complexity of these files, it is difficult to keep the files up to\n    date when there are changes to the `CodeGen` pass in `actonc`\n  - `actonc` CodeGen pass is now infused with some of the bespoke customizations\n    done for builtins, other customizations have been removed to streamline the\n    whole thing or inserted into .ext.c file to use the \"standard way of\n    customization\" (what an oxymoron)\n- Better performance through code generation improvements [#1263] [#1274]\n  - Code generation has been improved, primarily to avoid unnecessary\n    allocations, thus reducing pressure on GC, leading to improved performance\n  - One application that ran in > 12 minutes now run in < 2 minutes\n- `xml` module now correctly parses default namespace [#1262]\n- address `xml` bugs with more null checks [#126]\n- Switched to a nightly version of zig [#1264]\n  - pre-release version of zig v0.11\n  - we still pin to this particular zig version which goes through the Acton CI\n    testing so there is relatively low risk of this silently breaking something\n- Document `after` and encourage not using `sleep` [#1269]\n- `actonc` now transparently passes through zig output [#1277]\n  - treats subprocess output as bytestring instead of trying to decode it\n  - we only pass it through anyway, there is no analysis done on it\n  - avoids errors seen when not using UTF-8 locale, like when `LANG` is unset\n    (effectively defaulting to `C`)\n- Remove bunch of old code, irrelevant tests, old gen env scripts ect [#1278]\n- `math` module switched from stub style to .ext.c style [#1309]\n- Add missing MacOS headers [#1309]\n- Remove note on segfault in AbE that's no longer valid [#1303]\n\n### Testing / CI\n- Added macos-13 as test target in CI [#1258]\n- New CI job to build libactondeps and upload to \"cache\" repository [#1283] [#1284]\n  - Also using cached for CI builds (as well as local)\n  - MacOS CI builds 12 -> 6 minutes, Linux ~8 -> 4 minutes\n    - brew-macos is still slow, but we get quicker feedback of failures looking\n      at test-macos & test-linux jobs\n- Fixed Homebrew build by applying workaround\n  - Broke due to upstream changes and is still broken with default suggested\n    config in `brew new-tap`\n\n\n## [0.15.0] (2023-04-26)\n\n### Added\n- `actonc` is now statically linked in the Acton APT repo packages [#1148]\n  - enables development using Acton on Ubuntu 18.04, Debian 10 and distributions\n    of similar age\n  - static linking only works when the build platform is a slightly older Linux,\n    it works on Debian 11 which we are using, while on a newer Debian (testing\n    as of December 2022) the compilation fails\n  - our static compilation is conditioned on `STATIC_ACTONC=true`, which is set\n    in our `build-debs` CI job which builds the .deb packages used in the Acton\n    APT repo\n  - local compilation still defaults to a dynamically linked `actonc`\n- Parallel GC marking, speeding up mark phase significantly on computers with\n  many cores [#]\n  - Up to 16 parallel threads are used for marking\n- Add `sorted()` function [#1211]\n  - Uses timsort, which is the same sorting algorithm used by Python and Java's\n    Arrays.sort()\n- Add `re` module for regular expression matching [#1208]\n  - Offers `match()` function to match on text,\n    - Unanchored pattern matching, unlike the Python equivalent which is\n      anchored at the start per default (seems highly unintuitive)\n- Completely revamped `time` module [#1188]\n  - The high level interface is now oriented based on the two common usage\n    patterns of measuring elapsed time or telling the current date and time.\n  - `Stopwatch` measure elapsed time\n  - `time.now()` now returns a DateTime object, which is a higher level object\n- New fixed width integers: i16, i32, i64, u16, u32, u64 [#1202] [#1202] [#1203]\n- Backend queue subscriptions now done in bulk [#1127]\n  - An actor mailbox is mapped to a queue in the backend\n  - For every actor creation, the RTS would create and subscribe to the\n    corresponding queue.\n  - There's a new interface for queue subscriptions where individual queues are\n    grouped together into queue groups, so the RTS only needs to subscribe to a\n    group once\n- New acton projects are now git initialized [#1185]\n  - Using `actonc new foo` to create a new Acton project, we now check if git is\n    available and if so, initialize the repository. Also include a `.gitignore`\n- Allow overriding number of worker threads [#1199]\n  - It's been possible to set but we always used a minimum of 4, so even setting\n    threads to 2 you would end up with 4. It can be really useful for debugging\n    to run on a single WT, so honoring this is useful.\n- Add list methods `clear`, `extend` & `pop` [#1206]\n- New `--rts-no-bt` option to disable automatic backtrace printing [#1226]\n  - Automatic backtrace printing is nice for the normal case where one might run\n    a program and do not have core dumps enabled\n  - However, when doing actual debugging, one usually enables core dumps and\n    analysis it using a debugger interactively, in which case it's only annoying\n    to get a couple of screenfuls of backtrace in the terminal on every\n    iteration\n- Laid foundation for exception handling [#1228]\n  - Handles exceptions for CPS converted code\n  - Proc style functions do not currently handle exceptions properly\n  - Not fully enabled just yet, as it requires some more work\n- `int` literals between 0 and 256 are now statically allocated [#1235]\n  - Python uses the same trick for -5 to 255 for speedup for commonly used\n    integers\n  - Acton literal negative integers are really not negative integers but an\n    expression of \"minus\" and the integer 5 so we cannot currently do the same\n    trick for common negative values, like -1 etc\n- lists can now shrink to reduce memory usage [#1237]\n  - When list length goes below half, the list will be reallocated and copied\n    over to a new memory area\n\n### Changed\n- bash completion for `actonc` now completes `.act` files [#1246]\n- `TCPIPListener` interface has changed for callback registration [#1181]\n  - The `on_receive` and `on_error` handler for individual client connections\n    (`TCPListenConnection`) are now registered after instantiation of each\n    `TCPListenConnection` actor by calling `cb_install()`.\n    - This is most appropriately done in the on_accept callback.\n  - Unlike the old pattern, where we provided these callbacks up front to the\n    `TCPIPListener` actor, having them registered per client connection\n    naturally opens up to having different handlers per client.\n\n### Fixed\n- Fix `@property` handling & inference [#1207]\n- Fix bug in dict `__eq__`, so equality check now works [#1144]\n- `min()` & `max()` now work as they should [#1150]\n- `isinstance` now works correctly [#1124]\n- Fix compilation with return in nested branches [#1162]\n- Signal interrupts are now properly handled in acton.rts.sleep() [#1172]\n  - Previously, a signal would interrupt the sleep and it would simply not sleep\n    long enough. Now, if interrupted, the sleep is called with the remaining\n    time until the full duration has passed.\n- Fix worker thread indexes in WTS rtsmon interface [#1176]\n- `bool([])` now correctly returns False [#1193]\n- Correct `hex`, `bin` and `ascii` functions [#1196]\n- `actonc docs --signs` now works [#1197]\n- Correct pid is now reported in rtsmon [#1177]\n- Atomic mallocs are now used where possible to speed up GC [#1225]\n  - The GC does not need to scan the value of a `str` or `bytearray`, so they\n    are now atomically allocated which means the GC will skip scanning them\n- Document more list operations [#1136]\n- Explain named tuples [#1192]\n- Improved some parser errors [#1198]\n- Now using zig v0.10.1 [#1174]\n- Update to LTS 18.28 [#1141]\n- Internal name mangling has been changed [#1160]\n- builtins has been reorganized [#1169]\n- New `make clean-all` target to clean move stuff [#1210]\n\n### Testing / CI\n- Add Ubuntu 18.04 as test platform in CI [#1149]\n  - It's not possible to build Acton on Ubuntu 18.04\n  - As actonc is now statically built, the version built on Debian now also runs\n    on Ubuntu 18.04!\n- Test all available operations on lists [#1137]\n- Test all available operations on dicts [#1140]\n- Concurrent builds disabled on MacOS due to intermittent failures [#1145]\n- web page rebuild now triggered on changes to docs/acton-by-example [#1216]\n- Deb package now also gets a deterministic name [#1217] [#1219] [#1220]\n  - Makes it much easier to install the pre-built tip packages for testing / CI\n    etc on other repos\n\n\n## [0.14.2] (2022-11-27)\n\n### Fixed\n- Improve `actonc` performance [#1119]\n  - The constraint solver can have a massive performance impact on the\n    compilation process, in particular if it has a very large amount of\n    solutions to evaluate.\n  - The number of alternative solutions had too little weight during constraint\n    sorting which would result in a very large amount of potential solutions to\n    evaluate. An example program took 31 minutes to compile, which after the fix\n    compiles in milliseconds.\n  - For a 100 constraints, with the wrong strategy we might need to evaluate\n    5^100 solutions (heat death of universe etc) whereas if we do things\n    correctly we can solve all constraints in perhaps 100*3 tries. Exponential\n    is exponential.\n- Fixed size `i64` integer type is now instantiable [#1118]\n- Improved str to int conversion [#1115]\n- Corrected str `.split` and `.splitlines()`\n- Correct DB server & client comm loop select handling [#1111]\n  - Ignores EBADF and have ensured this design is correct with regards to timing\n    of invalid fds.\n- Drop explicit `gcc` dependency for Debian package [#1110]\n  - Haskell GHC still depends on it though, so it still gets installed.\n- Use slightly newer bsdgc / libgc version [#1112]\n  - Slight build simplification as we've upstreamed some modifications.\n\n\n## [0.14.1] (2022-11-14)\n\n### Added\n- `actonc --cc` to specify which C compiler to use to compile a module and\n  binary executables [#1103]\n  - Note that the Acton system is still compiled by `zig cc`. On Linux we are\n    targeting GNU libc 2.28, which might affect compilation of individual\n    modules or executables.\n\n### Fixed\n- `float.__ge__` is now working correctly [#1105]\n- Removed incremental operations from integers [#1106]\n- Improved `int` to `str` conversion [#1107]\n\n\n## [0.14.0] (2022-11-10)\nActon RTS now does garbage collection!\n\n### Added\n- The Acton RTS now does garbage collection [#1091]\n  - Using libgc a.k.a the Boehm-Demers-Weiser garbage collector\n  - The GC stops the world to perform garbage collection during which all Acton\n    RTS worker threads are paused. It is likely this will be visible as pauses\n    of the whole system.\n  - Performance appears to be largely on par with and without GC but this is\n    based on small artificial programs.\n  - It is possible to disable the GC at run time by setting the environment\n    variable `export GC_DONT_GC=1` before starting the Acton application\n    - This will be removed in the future when the GC has been field proven.\n  - Long term is to implement an Acton specific GC that can, for example, avoid\n    stop the world events by doing collection per actor. This is quite far into\n    the future. Until then, this will have to do!\n\n\n## [0.13.1] (2022-11-10)\n\n### Changed\n- Allow `_` as a dummy variable name [#1020] [#1061]\n  - `_` can be used in an assignment to effectively throw away a result\n  - Unlike using a variable like `dummy`, `_` acts as a wildcard from a type\n    perspective, so that we can do `_ = 3` and `_ = \"a\"`, while if we attempt to\n    use another dummy variable name we will get a type error as we try to assign\n    it values with different types\n- `__self__` has been renamed to `self` [#1056]\n  - it is a reference to the own actor and holds the \"external\" view, i.e. it\n    can be passed to another actor as a reference to the local actor\n\n### Fixed\n- Correct DB client comm thread to avoid potential deadlock [#1088]\n  - Incorrect handling of error return status from select meant we could attempt\n    to read on fds that had no data and thus the comm thread would deadlock.\n  - Now we do proper error handling, always continuing for another spin &\n    attempt at select in case we get an error back.\n  - The (under development) garbage collector (GC) uses signals to instruct\n    threads to pause for stop the world events and thus we end up interrupting\n    the select loop a lot more frequently than before, thus surfacing this bug.\n- Correct DB client comm thread to avoid busy waiting [#1089]\n  - On Linux, using `select()` with a timeout, if the select is interrupted the\n    timeout value will be modified to reflect the time not slept. Thus the next\n    select in our comm thread loop would sleep for a shorter period of time.\n    Depending on the timing of the interrupt, the sleep might be shortened to\n    effectively form a busy wait.\n  - The (under development) garbage collector (GC) uses signals to instruct\n    threads to pause for stop the world events and thus we end up interrupting\n    the select loop a lot more frequently than before, thus surfacing this bug.\n  - Fixed by always resetting the timeout value in the loop.\n- Make RTS DB clients stick to one partition [#1087]\n  - Make sure RTS (a DB client) does not hop between different DB server\n    partitions even if they learn about disjoint gossip views.\n  - Prevents incorrect operation when DB servers are not aware of each other but\n    are \"joined\" by a RTS that see all the servers.\n  - This scenario is most easily reproduced by starting DB servers without\n    specifying a seed, and so the DB servers won't see each other, and then let\n    a RTS connect to the DB servers, which then sees a view of all 3 servers.\n    - This is now rejected as invalid.\n  - Using vector clocks to determine and reject invalid views. Very elegant =)\n- Correct `time.monotonic()` [#1097]\n  - It returned a wildly incorrect results as the nanoseconds part was not\n    properly added up with seconds.\n- Include argp-standalone library in libActonDeps [#1058]\n  - No more external dependencies!\n  - argp is available as part of the system on GNU/Linux but on MacOS we have\n    relied on the argp-standalone package installed via brew. We now prefer to\n    use our own on both Linux and MacOS.\n- Acton system is now compiled with `-Werror` to improve code quality [#1060]\n  - There are some exceptions to this but the overall goal is to be essentially\n    free of compilation warnings\n- Fix bug in truediv for `int` [#1076]\n- Fix bad codegen of classname argument to `isinstance()` [#1055]\n- Correct effect declaration to `mut` for some builtin protocols [#1053]\n- Method decorators like `@staticmethod` now work [#1054]\n- Added lost constraints inferred on target expressions [#1050]\n- Avoid undefined behavior in builtin object hash [#1065]\n- Clean up library include paths etc [#1068] [#1077] [#1080] [#1092]\n  - Made possible by including all of our external dependencies in libActonDeps\n\n### Testing / CI\n- Add back testing on Ubuntu 20.04 [#1093]\n  - libxml2 requires a newer automake (1.16.3) than is available on Ubuntu 20.04\n  - We fix this by hacking the configure.ac file to require the version\n    available on Ubuntu 20.04 (1.16.1)\n\n\n## [0.13.0] (2022-11-04)\nNew \"deactorizer\", which unlocks proper async / sync actor method calls.\n\n### Added\n- Added new \"deactorizer\" pass in compiler [#374]\n  - No real user visible change, like no change in syntax, but we now properly\n    compile programs with regards to async / sync calling behavior of methods.\n  - Briefly, an actor method called from the local method is called directly.\n    This effect is called \"proc\". Remote actor methods are normally called\n    asynchronously and these are called \"action\". If we assign the return value\n    of an action, we are locking for a synchronous behavior which is achieved by\n    an await. These semantics are now correctly implemented.\n  - In particular, passing methods as arguments, a method might not know whether\n    it is passed an action or proc and thus needs to handle this in a generic\n    way. This is particularly tricky as we don't want to to any run time\n    inspection of arguments and thus need to have it all figured out at compile\n    time.\n  - Many many many other things are fixed through the merge of the new\n    deactorizer. There are improvements and fixes to various passes in the\n    compiler. This has been in the works for almost a year.\n- Added `--auto-stub` to `actonc` [#1047]\n  - Enables automatic detection of stub mode compilation\n- Extended actor argument pruning analysis to honour `NotImplemented` [#524]\n  - Pruning analysis prunes away arguments that are not used under the lifetime\n    of an actor, e.g. an argument only used for actor body initialization code.\n    Pruned arguments are not persisted.\n  - Pruning analysis does not cover C code, so when one or more methods are\n    implemented in C and defined as `NotImplemented` in the Acton module, we\n    cannot reliably determine what arguments are used or unused.\n  - The safe choice is to assume all arguments are used, which is what we are\n    now doing.\n  - This removes a bunch of `_force_persistance` methods in stdlib.\n\n### Changed\n- Default is now to not automatically detect stub mode [#1047]\n  - Use `--auto-stub` to enable automatic stub mode detection\n\n### Fixed\n- Now using zig v0.10.0, which was recently released [#1029]\n  - Previously using a nightly build of v0.10\n- Correct arithmetic operations using hexadecimal literals [#1027]\n- Build actondb using zig with -target [#1003]\n\n\n## [0.12.0] (2022-10-27)\nEdvin's second birthday, only 10 minor releases behind Acton ;)\n\n### Added\n- Zig is now used as the C compiler for Acton [#972]\n  - Many parts of Acton, like the run time system, builtins and parts of the\n    standard library are written in C\n  - actonc compiles Acton programs into C which are then compiled into binary\n    executables using a C compiler\n  - zig is now used for both of these use cases\n  - zig is bundled with Acton so that we know what version of zig we get, which\n    is the same across Linux and MacOS\n- Acton programs on Linux are now backwards compatible to GNU libc v2.28\n  - Previously, acton programs would be built for the GNU libc version on the\n    compiling computer, making it impossible to run on older distributions\n  - Now compatible with for example Ubuntu 20.04 LTS & Debian 10\n  - This is made possible by zigs incredible cross-compilation functionality,\n    which isn't just about targetting other OS, CPUs but also older libc\n    versions\n  - v2.28 appears to be the oldest version we can practically target without\n    code changes, even earlier versions fail compilation\n  - We could reduce backwards compatible, for example by targetting glibc 2.31,\n    if we find things that we would like access to, i.e. don't regard glibc 2.28\n    compatibility as a hard promise\n- Added `--always-build` to actonc [#988]\n  - Used in test suite so that we always force compilation in order to ensure\n    valid test results\n- `actonc` argument parsing now done using sub-parsers, allowing greater freedom\n  in constructing more complex commands [#976]\n- All external library dependencies are combined in one .a archive [#849]\n  - Decouples library dependency in builtins, RTS & stdlib from actonc compiler\n    arguments\n- All external library dependencies are now built from source [#984]\n  - Allows us to compile them with zig, thus power to select target libc\n- Add `xml` module [#835]\n  - Offers simple `encode()` and `decode()` operations\n  - Based on libxml2\n- The `int` type now supports arbitrary precision [#146]\n  - Add some big numbers!\n  - The previous implementation of `int` was as a signed 64 bit integer, this is\n    now available as the `i64` type in Acton, although its use is currently\n    quite limited.\n  - Longer term, fixed size integers like `i64` or `u64` (for an unsigned) are\n    available and can be chosen for high performance use cases. Developers\n    familiar with this level of coding are likely able to make an informed\n    choice about what integer type to choose. Using `int` for the arbitrary\n    precision type is the safer choice which will make most users happy.\n  - Using BSDNT library, which is a reasonably fast C implementation of\n    arbitrary precision types and arithmetic operations. It is not as fast as\n    MPL but has a more liberal license.\n\n### Fixed\n- Fixed seed arg parsing in actondb [#900]\n- Avoid crash during TCP client resume\n- DB now using logging rather fprintf(stderr, ...)\n- Reduce unprovoked CPS & 'rtail' bugs [#949]\n- Update docs for --root & `runacton` [#950]\n- `file.ReadFile` can now read arbitrarily large files [#955]\n- RTS does proper error handling of DB interaction [#957]\n  - This is a huge improvement!!!\n  - The run time system now properly reads the return code from all DB query\n    operations and acts appropriately. For example, lacking a quorum, the RTS\n    will continuously retry an operation until quorum can be reached.\n  - For some failures a larger chunk of operations needs to be retried, i.e. we\n    can't just wrap up a small function in a retry loop but need a larger retry\n    loop around a group of operations.\n  - DB API now returns a minority status which the RTS can and does react on\n    - Typical example is with 3 DB nodes and a commit goes through on 2, i.e.\n      with a quorum and is thus considered a success, however the 3rd node\n      rejected it because of a schema mismatch. The RTS can now be notified\n      through the minority status and attempt to repair the schema.\n      - A typical example of schema repairs necessary are for the queues, which\n        are dynamic. Every actor gets a queue in the database, so when new\n        actors are created, new queues also need to be created and if a\n        particular DB server is not up when the queue is created, it will be\n        missing and needs to be repaired later on.\n      - We should have proper sync up between DB servers, so that they query\n        each other and converge on the latest state. Until then, repair\n        initiated from RTS is our way of fixing it.\n- Notify gossip view to clients (RTS) from agreement round leader [#951]\n  - For example, in this scenario:\n    - db1 is started\n    - RTS is started & connected to db1 but unable to progress due to no quorum\n    - db2 is connected, gossips with db1 and we now have quorum\n    - RTS continues to be stalled as it is never notified about db2 and thus\n      unable to reach a quorum\n- Avoid MacOS quarantine shenanigans that kills actonc [#971]\n  - MacOS has some quarantine concept, so like if a file is downloaded from the\n    Internet, it is marked as quarantine and the user is asked \"Are you sure you\n    want to run this\" after which the quarantine flag, which is stored as a file\n    system extended attribute, is cleared.\n  - Somehow we trigger this quarantine, presumably by that we overwrite, through\n    cp, a binary executable that macos has run and this triggers it to set the\n    quarantine flag. The effect is that whenever we execute actonc, MacOS kills\n    -9 it, which is obviously rather annoying.\n  - By copying to a temporary file and then moving it in place, we avoid MacOS\n    setting the quarantine flag. We already did this, though for other reasons,\n    for actondb, so in a way this is a unification for the files in bin/\n\n### Testing / CI\n- Simplify and clean up RTS DB test orchestrator [#941] [#973]\n- Stop testing on Ubuntu 20.04\n  - It's not possible to compile libxml2 on a stock Ubuntu 20.04 as a newer\n    version of automake is required than is shipped\n  - We mainly want to uphold run time compatibility with Ubuntu 20.04, like it\n    should be possible to run Acton applications but utilizing Ubuntu 20.04 as a\n    development platform for Acton is not a high priority target, thus dropping\n    it is quite fine.\n- Revamp Increase timeout\n- Avoid kill -9 on macos [#969]\n  - MacOS quarantine functionality thinks we are doing something fishy and kill\n    -9 our process\n  - Worked around by doing cp & mv instead of just a cp\n\n\n## [0.11.7] (2022-10-03)\nMany important fixes for RTS/DB and the language in general!\n\n### Added\n- Bash completion is now part of the Debian packages & brew formula\n\n### Changed\n- actondb now uses a default value for gossip port of RPC port +1 [#913]\n  - The gossip protocol only propagates the RPC port & parts of the\n    implementation has a hard-coded assumption that the gossip port has a +1\n    offset\n  - In order to avoid configuration errors, the default gossip port is now RPC\n    port + 1 and if another gossip port is explicitly configured, an error log\n    message is emitted on startup.\n  - While this is marked as a change, it could really be considered a fix as any\n    other configuration of the system was invalid anyway.\n\n### Fixed\n- Fixed include path for M1 \n  - /opt/homebrew/include added to header include path [#892]\n  - Actually fixes builds on M1!\n  - This has \"worked\" because the only M2 where Acton was tested also had header\n    files in /usr/local/include but on a fresh install it errored out.\n- Fix up-to-date check in compiler for imported modules from stdlib [#890]\n- Fix seed arg parsing in actondb that lead to \"Illegal instruction\" error\n- Fix nested dicts definitions [#869]\n  - Now possible to directly define nested dicts\n- Avoid inconsistent view between RTS & DB in certain situations [#788]\n  - If an RTS node was stopped & quickly rejoins or if a transient partition\n    happens and the gossip round does not complete before the partition heals.\n  - We now wait for gossip round to complete.\n  - This ensures that local actor placement doesn't fail during such events.\n- Fix handling of missed timer events [#907]\n  - Circumstances such as suspending the Acton RTS or resuming a system from the\n    database could lead to negative timeout, i.e. sleep for less than 0 seconds.\n  - The libuv timeout argument is an uint64 and feeding in a negative signed\n    integer results in a value like 18446744073709550271, which roughly meant\n    sleeping for 584 million years, i.e. effectively blocking the RTS timerQ.\n  - It's now fixed by treating negative timeouts as 0, so we immediately wake up\n    to handle the event, however late we might be.\n- Timer events now wake up WT threads after system resumption [#907]\n  - Worker Threads (WT) are created in `NoExist` state and should transition\n    into `Idle` once initiated, however that was missing leading to a deadlock.\n  - This was masked as in most cases, a WT and will transition into `Working`\n    once they've carried out some work and then back into `Idle`\n  - `wake_wt` function, which is called to wake up a WT after a timer event is\n    triggered, wakes up threads that are currently in `Idle` state, if they are\n    in `NoExist`, it will do nothing.\n  - If there is no work, such as the case after system resumption from the DB,\n    WTs will stay in the `NoExist` state and then `wake_wt` will do nothing, so\n    the system is blocked.\n  - WT now properly transition into `Idle`.\n- Only communicate with live DB nodes from RTS DB client [#910] [#916]\n  - When the RTS communicates with the DB nodes, we've broadcast messages to all\n    servers we know about. If they are down, they've had their socket fd set to\n    0 to signal that the server is down. However, fd=0 is not invalid, it is\n    stdin, so we ended up sending data to stdin creating lots of garbage output\n    on the terminal.\n  - fd -1 is used to signal an invalid fd, which prevents similar mistakes.\n  - The DB node status is inspected and messages are only sent to live servers.\n- Avoid segfault on resuming TCP listener & TCP listener connection [#922]\n  - Invalidate fds on actor resumption [#917]\n- Remove remaining ending new lines from RTS log messages [#926]\n- Remove ending new lines from DB log messages [#932]\n\n### Testing / CI\n- Rewritten RTS / DB tests [#925] [#929]\n  - More robust event handling, directly reacting when something happens, for\n    example if a DB server segfaults or we see unexpected output we can abort\n    the test\n  - Now has much better combined output of DB & app output for simple\n    correlation during failures\n  - Test orchestrator now written in Acton (previously Python), at least async\n    IO callback style is better supported to directly react to events...\n\n\n## [0.11.6] (2022-09-20)\n\n### Fixed\n- Homebrew Formula now includes util-linux for Linux\n  - required for <uuid/uuid.h>\n\n\n## [0.11.5] (2022-09-20)\n\n### Fixed\n- Homebrew Formula test [#882]\n- Homebrew Formula now pins GHC dependency to version 8.10 [#885]\n  - This is aligned with the stack resolver version we're currently using\n- actondb is now statically linked with protobuf-c [#887]\n  - Found in brew linkage testing, which should now pass\n\n\n## [0.11.4] (2022-09-19)\n\n### Testing / CI\n- Minor correction to Homebrew release automation\n  - This is silly...\n\n\n## [0.11.3] (2022-09-19)\n\n### Testing / CI\n- Minor correction to Homebrew release automation\n\n\n## [0.11.2] (2022-09-19)\n\nThere are additions but they're so minor you get 'em for free in a patch\nrelease! ;)\n\n### Added\n- Add runacton wrapper to run .act files using shebang [#238]\n  - Write an Acton program in a .act file and add shebang line at top:\n    - `#!/usr/bin/env runacton`\n  - ... and then run the .act file. It will be seamlessly compiled and executed!\n    Magic *whosh*\n\n### Testing / CI\n- Homebrew Formula moved to actonlang/acton repo [#868]\n  - Building a brew bottle is now part of regular CI testing\n  - Ensures that our Homebrew Formula is correct with regards to dependencies\n    etc, which has previously been a long standing issue\n  - mirrored to actonlang/homebrew-acton when we release\n- Retry DB test jobs [#853]\n  - No longer have to manually re-run CI jobs on failures\n  - Retry just the DB test itself, which takes a few seconds instead of\n    rerunning entire CI job which takes minutes\n- New automatic release process\n  - Removes adding git tag as manual step\n  - Now push branch `release-vX.Y.Z` updating `common.mk` & version in\n    `CHANGELOG.md`, once this PR is merged, a new workflow adds the git tag\n    which in turn triggers the release build\n\n\n## [0.11.1] (2022-09-14)\n\n### Testing / CI\n- Fix APT repo job\n\n\n## [0.11.0] (2022-09-14)\n\n### Added\n- Apple M1 / M2 CPUs are now supported [#823]\n  - aarch64 calling conventions are different for variadic vs fixed functions\n    and this is a problem when we alias a fixed function as a variadic function,\n    which is exactly what we did in a number of places in the stdlib where we\n    manually write C code\n  - Now fixed by calling $function2, $function3 etc for 2 vs 3 args\n- `actonc new foobar` will create a new project called foobar according to the\n  standard project directory layout\n- Completely rewritten IO system & RTS workers [#698]\n  - libuv is now used for all IO operations instead of our own home grown IO\n    subsystem.\n  - Rather than a single thread dedicated to IO, all RTS worker threads now also\n    perform IO work. IO actors are pinned to a particular worker thread on\n    initialization.\n- New `net` module [#733]\n  - replaces `env.connect()` & `env.listen()`\n  - adds DNS lookup functions\n- New `process` module [#752] [#796] [#797] [#798] [#799] [#800] [#801] [#804]\n  [#808]\n  - runs sub-processes\n- New `file` module which allows reading and writing files [#806]\n  - Replaces `env.openR` & `env.openW`\n- New `json` module to encode and decode Acton data to JSON document (strings)\n  [#829]\n  - built on yyjson C library, which is a very fast (3.5GB/s) JSON library\n- Do token based authentication\n  - Capability based authentication has previously been based around access to\n    the env actor, which was initially fed into the system as an argument to the\n    root actor\n  - We wanted to modularize the code of the env actor and so instead we've opted\n    to use a token based authentication scheme\n  - A WorldAuth token is passed to the root actor, accessible as `env.auth`\n  - Tokens are organized in a hierarchy, e.g.\n    - WorldAuth > NetAuth > TCPAuth > TCPConnectAuth\n  - Performing actions always require most specific auth token\n    - This is to encourage users NOT to pass around the WorldAuth token but make\n      it more specific\n  - For example creating `net.TCPIPConnection` requires a `TCPConnectAuth` token\n- actonc now outputs some information about what it is doing per default [#840]\n  - Previous quieter output can be achieved with `--quiet`\n  - `--timing` includes extra timing information on how long compiler passes and\n    other operations take\n  - all `--verbose` output now under `--debug`\n- actonc now takes a lock on a project when compiling, which ensures that two\n  invokations of actonc to build the same project do not step on each others\n  toes [#760]\n  - lock is implemented using flock(), so even if actonc dies and lock file\n    stays in place, it is not considered locked (flock only keeps lock while\n    process that acquired lock is running)\n  - Our own stdlib is built concurrently with development and release profile,\n    which can now be run \"concurrently\", i.e. we do not have to ensure\n    serialization of these two builds from the Makefile and since all other\n    targets are run concurrenctly this simplifies the Makefile quite a bit,\n    however since there is a lock there won't be an actual concurrent build\n- actonc now automatically sets the root actor to `main`, if a program contains\n  such an actor. This means `--root` argument is mostly superfluous now [#726]\n- actonc --root argument now takes a qualified name, like <module>.<actor>\n  [#628]\n  - this is required to build an executable in a project with:\n    `actonc build --root test.main`\n- RTS has improved logging, including timestamps, log levels etc. Also supports\n  file output [#584]\n  - Log output is sent to stderr\n  - RTS worker thread id is included so it is now easier to follow what a\n    particular thread is doing.\n  - stderr output has millisecond time resolution\n  - file output (--rts-log-path) has nanosecond precision\n  - Using pretty, short relative paths\n- ActonDB has improved logging, including timestamps, log levels etc and\n  supports file output [#588]\n  - supports logging to file with --log-file\n  - similar implementation as RTS (based on same log.c library but modified)\n- actonc automatically detects stub mode compilation based on presence of .c\n  file [#601] [#624]\n- actonc supports new .ext.c style definition of C functions where individual\n  functions in an .act file can be externally defined in the .ext.c file by\n  using `NotImplemented` as the function body [#706]\n- actonc is now aware of development / release profile [#599] [#612]\n  - output placed in correct location, i.e. out/rel or out/dev\n- actonc now supports custom compilation of modules via Makefile [#602]\n  - if a module is to be stub compiled (i.e. there is a .act file with a\n    corresponding .c file) then if there is also a Makefile in the project root,\n    actonc will run make for the corresponding target, e.g. `make out/rel/foo.o`\n- actonc now has concept of commands [#608]\n  - like `actonc build` which will build an Acton project\n- stdlib is now compiled from actonc as a Acton project [#599]\n- `__builtin__.act` has been moved from stdlib to `builtin/ty`, which is also an\n  Acton project [#623]\n  - `__builtin__.act` really is special, like it's an implicit dependency for\n    everything else, and trying to add extra logic to get it to build first when\n    building the stdlib project doesn't make sense; it's now special rules in\n    the Acton Makefile\n- Improve DB schema creation messages [#586]\n  - Messages contained \"test\", which is misleading. The DB server creates the\n    schemas, i.e. the schema is hard-coded. This is per design and a\n    simplification (no need for schema management RPCs) as the DB and RTS are\n    tightly coupled anyway.\n- ActonDB will now gossip RTS node membership, forming the foundation for doing\n  distributed computing\n- ActonDB monitor membership information now contains all nodes [#645]\n- RTS mon now has a membership view [#645]\n- `bytes` type added [#655]\n- Library dependencies are now included in the Acton distribution [#698]\n- Added `__repr__` method to class value & subclasses [#685]\n- Added Ord instances for lists & dicts [#719]\n\n### Changed\n- `after` now takes a float argument [#846]\n  - Allows sub-second delays\n- IO subsystem has been replaced with libuv\n- `env.connect()`, `env.listen()` has been replaced with `net` module, i.e.\n  `net.TCPIPConnection` and `net.TCPListener`\n- file access via `env` has been replaced with the `file` module\n- RTS log output is now sent to stderr rather than stdout\n- `actonc dump foo.ty` now takes the filename of the `.ty` file to dump as a\n  positional argument rather than the old way of using an option (`actonc dump\n  --file foo.ty`)\n\n### Fixed\n- Avoid segfault in actondb due to uninitialized mon fds [#627] [#633]\n- Exceptions during build of executables no longer deletes produced .ty files [#629]\n- Fixed DB server & client issues leading to segfaults [#559]\n  - Pass skiplist keys by reference\n  - Fix duplicate nonces in msg_callbacks skiplist\n  - Extend lock protection over msg_callbacks\n- DB client no longer asserts & exits on perror [#574]\n  - Now handles more errors rather than bailing out\n- Properly initialize fd_data entries [#571]\n  - Sometimes a slot wasn't properly initialized, which would lead to incorrect\n    behavior\n- RTS now cleans up and closes fd on EOF [#570]\n- RTS fd array is now 1024 slots long [#570]\n  - Used to be 100, which means we can address up to 100 fds. Default fd limit\n    on most Linuxes is 1024, so we align on that. The proper fix is to have a\n    dynamic structure for fd or set it to the same value as the limit (but\n    that's bad for large values).\n- RTS uses sigaction instead of signal, which should tighten up some edge cases\n  [#587]\n- Do not print log message on new connection in RTS / env [#607]\n- Correct Debian package dependencies [#625]\n  - We used the wrong dependencies, shared libraries, when we should have the\n    development libraries available, since we are not a \"normal\" application but\n    a compiler, so when we in turn build programs we want to link them as\n    statically as possible (sort of, not including libc but most other things)\n  - Now installing the .deb file will pull in all the correct dependencies on\n    Debian 11 / bullseye and Ubuntu 20.04\n- Correct handling of plain and raw bytes / string literals [#655] [#657]\n- UTF-8 encoding is now enforced for source files\n- All library dependencies are now included in the Acton [#693]\n  - For example libuv, libutf8proc, libbsd (on Linux)\n  - No longer partially linking some modules like math & numpy\n  - We used to partially link in e.g. libbsd into math\n    - numpy imports math so importing both math and numpy means we got duplicate\n      symbols\n    - This was likely a faulty design in the first place as it lead to symbol\n      collisions\n  - Now all library dependencies are part of the Acton distribution and are\n    linked in with the final application at actonc build time\n  - Files are stored as e.g. dist/lib/libuv_a.a. The _a suffix is to ensure we\n    get the statically compiled library and do not link with a shared .so\n    library if one happens to be present on the system.\n- C lib guide rewritten for new .ext.c style [#766][#766]\n- Custom make file invocations are now more idempotent [#845]\n  - Avoid copying .h files which forces make to rebuild targets\n    \n\n### Testing / CI\n- Tasty (Haskell test library & runner) is now used for testing actonc. Most\n  tests have been migrated from test/Makefile to compiler/test.hs [#631]\n  - Tasty offers different style testing; unit, golden, property etc, with\n    flexible runners that can execute tests in paralell. Has nice, compact and\n    colorized output in the terminal and can output to richer formats as well as\n    run benchmarking tests.\n  - There are now timeouts for all tests run by Tasty\n- TCP servers stress test for opening & closing fds in RTS [#570]\n- actonc build of projects have some test cases [#623] [#625]\n- Now testing on MacOS 12 [#527]\n- Stopped testing on MacOS 10 []\n- Now testing on Ubuntu 20.04, 22.04 & 22.10 [#700]\n- New test jobs for running actonc and its output on a clean machine [#]\n  - This installs acton from a .deb file on Linux and from artifact .zip file on\n    Mac\n  - Ensure that we have all dependencies declared correctly and that we ship all\n    necessary files\n  - Running on same platforms as normal test, i.e.:\n    - MacOS 11 & 12\n    - Debian 11\n    - Ubuntu 20.04, 22.04 & 22.10\n\n\n## [0.10.0] (2022-02-25)\n\n### Added\n- actors now have a `__resume__` function that is called by the RTS just after\n  actors have been deserialized from the database [#517]\n  - This is effectively a generic hook point that can be used by certain actor\n    implementations to run code when being resumed from the database\n- ListenSocket supports resumption [#529]\n  - We cannot restore the previous state of a listening socket since that fd and\n    all its associated resources in the kernel etc are gone.\n  - The next best thing we can do is tell the application, through the error\n    callback, that there is an error with the listen socket and it is then up to\n    the application to retry, effectively attempting to listen again\n- Connection now supports resumption [#546]\n  - Similar to ListenSocket, so that upon resumption we invoke the registered\n    error handler so that the application can reconnect\n  - Unlike ListenSocket, the error callback must first be registered through\n    `on_receive` on the `Connection`\n  - What's neat is that any application that attempts to handle reconnects will\n    also automatically have code for dealing with Acton based actor migration\n    and recovery!!!\n- `actonc` now takes `--tempdir` option to write intermediate output (generated\n  C) to instead of randomly generated directory, which also means the specified\n  directory is kept and not deleted on exit [#516]\n  - in the generated directory, there is a `build.sh` file that contains the\n    same commands that `actonc` would use to produce the final binary output\n    from the source files\n\n### Changed\n- `on_receipt` is now called `on_receive` on `Connection` [#522]\n- `on_connection` is now called `on_connect` on `env.listen` [#535]\n- The error callbacks of Connection & ListenSocket now receive the Connection or\n  ListenSocket as an argument so that it is easy to identify which instance the\n  error pertains too [#547]\n- The main program thread is no longer named `main` [#528]\n  - The thread name is reported in various tools like top and ps or when there\n    is no thread name, the process name is used\n  - The process name is more unique than the main thread name (always \"main\"),\n    so we prefer to use the process name\n\n### Fixed\n- Initialize `pthread_getspecific` to `NULL` value [#529]\n  - Avoids segfault, in particular on MacOS\n- `on_connect` callback is now always handed a connection argument [#538]\n  - Every since we split out the error handler this was really the case but the\n    function signature indicated that it was maybe a Connection and so all\n    application code had to be written defensively, checking if the argument was\n    None\n  - It will never be None and the signature now matches that so application code\n    can be written more cleanly\n- Fix TCP client connection on Linux with epoll [#542]\n  - Ever since we started supporting epoll natively on Linux, rather than the\n    libkqueue shim layer, we have had this regression where TCP client\n    connections do not work\n  - We registered the same fd with different filters in epoll which resulted in\n    an error. It's now fixed by first clearing older flags before\n    re-registering the fd.\n- ActonDB and DDB libraries are now compiled with debug flags [#529]\n  - Unlike other parts of RTS that are compiled with debug flags when `actonc\n    --dev` is used, we don't have the same possibility of conditional\n    compilation here, so meanwhile the DDB things will now always include debug\n    flags\n\n\n### Testing / CI\n- Correct DB test so that the return value is actually inspected [#518]\n- Generated files now come with newline [#521]\n- Work around current issues with serialization of uninitialized values [#518]\n- Remove old RTS DDB test [#530]\n\n\n## [0.9.1] (2022-02-17)\n\n### Fixed\n- Fix ActonDB monitor interface initialization [#514]\n  - God knows how this ever worked, but it mostly did on Linux. Mac OS X really\n    exposed the errors together with the RTS not halting on DDB errors, which we\n    should address through [#431]\n- Serialize all manually constructed actors [#512]\n  - A new convenience function makes it easier to serialize all manually\n    constructed actors to the DB and it is used in various places so that all\n    currently known actors are serialized\n  - The better fix for most of these actors is probably to have CPS converted\n    init functions instead but that's some more code to write which is\n    cumbersome for manually defined actors\n\n\n## [0.9.0] (2022-02-15)\n\n### Added\n- Add DB client library statistics [#473]\n  - We keep count, sum of time and timing buckets per operation type\n  - `actonmon` exposes these metrics over the prometheus HTTP endpoint\n- RTS mon interface now uses netstrings as line encoding [#494]\n  - Much more robust than the previous implementation which relied on luck\n  - netstrings are very simple and can be implemented in a few lines of C or\n    Python, so we are still considerably simpler than protobuf or similar\n- Add mon interface to ActonDB [#499]\n  - We only expose membership information\n  - Gives us a nice programmatic interface to query the DB for membership info,\n    so we can determine whether our DB cluster has converged or not\n- Acton RTS now handles `SIGINT` and `SIGTERM` [#509]\n  - RTS will gracefully shutdown upon receiving either `SIGINT` or `SIGTERM`\n  - If a second `SIGINT` or `SIGTERM` is received while the RTS is gracefully\n    shutting down, it will instead exit immediately\n- Add `ListenSocket` actor [#506]\n  - `env.listen()` now returns a `ListenSocket`, previously it did not return\n    anything, which meant that we never got a \"handle\" on the socket itself so\n    we couldn't for example stop listening on a port.\n  - Also means we have a more natural place to add logic for what should happen\n    on actor resumption.\n\n### Changed\n- `env.listen()` now takes a on_error callback function [#504]\n  - Previously the on_connect callback would be invoked with a `None` argument\n    on error, which meant it wasn't really an \"on connect\" handler\n  - Now we get separate callbacks so each can be implemented much cleaner\n- Enough DDB servers must be specified for configured replication factor [#474]\n  - With a replication factor of 3, `--rts-ddb-host` must be specified at least\n    3 times to point to 3 DB servers\n  - A previous short term fix [#427] assumed all DDB servers were running on the\n    same host, typically localhost for testing\n  - We now let the user figure it out instead, allowing true multi-node operation\n  - Long term fix is still to properly implement gossip protocol\n\n### Fixed\n- Fix segfault caused by misaligned uuid.h / libuuid on MacOS [#488]\n  - used `uuid.h` from system and uuid lib from util-linux package\n- Fix actor instantiation in env.c [#481]\n  - We failed to create the DB queue on actor instantiation which would lead to\n    errors on later enqueues [#472]\n  - [#186] changed the way actors are initiated and code generated by actonc\n    uses the new correct way whereas the builtin actors like Env, Connection etc\n    defined in `env.c` are manually implemented and still used to old way\n  - All actors in `env.c` now use the new correct way!\n- Fix epoll detection of disconnect [#469]\n  - In addition to listening for `EPOLLHUP` we must detect `EPOLLRDHUP`\n- Do not rewrite argv for `--rts-ddb-host` option arguments [#476]\n- Fix `--opt=arg` style parsing of argument [#479]\n  - Argument value was `t=arg` rather than `arg` due to misplaced parentheses\n- Do single line logging [#475]\n  - Previously had tasks where first a partial log line would be printed, to be\n    completed when the task finished. This looks nice in an interactive terminal\n    but if anything else logs meanwhile, the output becomes garbled.\n- Cleaned up bootstrap removing `ancestor0` [#481]\n- Speed up RTS startup when using the database [#493]\n  - A `select()` timeout meant we would always pause for 3 seconds\n  - We now avoid the timeout entirely by having a \"wakeup pipe\" that we can prod\n    to wake up the comms thread in the RTS\n  - For small programs, like most of our tests, we can now startup 3 DB nodes\n    and run the program in 30ms or so whereas previously it would take just over\n    3 seconds. 100x improvement!\n\n### Testing / CI\n- CI jobs now depend on all \"previous jobs\" which prevents inconsistencies [#478]\n  - There are jobs, like the update-apt-repo job, which depend on previously\n    jobs, like test-linux.\n  - While the test job for Linux could succeed and thus allow the\n    update-apt-repo job to proceed, text-macos could fail, meaning the overall\n    pipeline status is failed, yet enough has passed to now run the\n    update-apt-repo job. Uploading a new version there but not a similar one for\n    Mac OS X causes inconsistencies.\n- DB test script (`test_db.py`) now uses Python unittest style rather than\n  homegrown functions [#501]\n  - Makes it easier and more robust to handle setUp & tearDown\n- Ensure app is killed during tearDown as to ensure cleanup [#502]\n- The test for RTS with DB now has a new test where the test app uses TCP for\n  control and exposing information which should make it much faster and more\n  robust than relying on stdout parsing.\n  - However, it does not currently support testing DB resumption / recovery as\n    our TCP listen sockets do not support resumption\n\n\n## [0.8.0] (2022-01-14)\n\n### Added\n- New RTS mon logging option [#464]\n  - This new option makes it possible to write the RTS monitor statistics to a\n    log file specified with `--rts-mon-log-path`\n  - The first stats snapshot is taken just at startup of the application after\n    which subsequent stats snapshots are taken at the specified periodicity. A\n    snapshot is always taken just before shutdown.\n  - The periodicity is specified by `--rts-mon-log-period` in units of seconds\n    and the default value is 30\n- New RTS mon output option [#464]\n  - It is possible to output the RTS monitor statistics just before the exit of\n    program by specifying `--rts-mon-on-exit`\n  - The RTS monitor statics are printed to stdout.\n- Threads now have names, making it easier to debug [#457]\n  - \"main\", \"IO\", \"Mon Socket\" and \"Worker X\" are the currently used names\n- Show RTS options and arguments with `--rts-help` [#465]\n\n### Changed\n- stdout is now line buffered [#464]\n- `--rts-mon` has been renamed to `--rts-mon-socket-path`\n  - Since there are now multiple output options for the RTS monitor statistics\n    we use a more specific name\n\n### Fixed\n- Avoid slow RTS performance when using DDB & the DDB server is too fast [#453]\n  - If the DB server responded quickly enough, the client library would enter a\n    pthread_cond_timedwait to wait for the response but it had already arrived\n    leading to always hitting the timeout [#449]\n  - The effect was that the Acton program would run very slowly as each\n    continuation would take one DDB communication timeout to process, which is\n    set to 10 seconds\n  - The DDB client library has been improved to check for the response within\n    the mutex lock to avoid this situation\n  - RTS in DDB mode is now fast!\n- Acton RTS now shuts down \"gracefully\" [#460]\n  - `env.exit()` previously called `exit()` in C, immediately shutting down the\n    application & RTS\n  - Any currently running continuation (in another worker thread) would be\n    abrubtly killed\n  - This has been improved so that the RTS will let worker threads complete any\n    currently executing continuation and commit that work before exiting the\n    application\n- Only do CPU affinity when there are as many worker threads as CPU cores [#447]\n  - `--rts-wthreads` can be used to specify the number of worker threads and if\n    that number does not align with the number of CPU cores in the machine, we\n    will not do CPU pinning\n  - Previously, the worker threads that overlapped with available CPU cores\n    would be pinned whereas the rest would go unpinned.\n- Corrected worker thread count message [#446]\n  - Previously, the log message (when using `--rts-verbose`) that shows the\n    number of worker threads used when there are few available CPU cores would\n    show the incorrect number (`0`) [#445]:\n    - `**RTS** Detected 2 CPUs: Using 0 worker threads, due to low CPU count. No CPU affinity used.`\n  - RTS was actually using more worker threads but the log message was wrong and\n    has now been corrected.\n- Corrected actual number of worker threads [#457]\n  - While we computed the correct number of worker threads to use, when creating\n    the threads we completely failed to use that computed value and instead\n    unconditionally spawned as many worker threads as there are CPU cores.\n  - There was also an off-by-one error on the number of worker threads.\n  - This has all been corrected so the correct number of worker threads is now\n    created and there is a test case to prove it.\n\n\n## [0.7.4] (2022-01-06)\n\n### Fixed\n- env actor is serialized to database backend during bootstrap [#430]\n  - Actor serialization (\"snapshotting\") to the database usually happens when a\n    continuation (roughly an actor method) has been run\n  - The env actor might never run, which meant it might not have been\n    serialized to the DB, so when resuming an Acton application from the\n    database, the env actor could be missing leading to a segfault [#408]\n- RTS now connects to all DB nodes to enable replication factor >1 [#427]\n  - This is a short term fix [#409]\n  - Longer term, the client DB gossip protocol will be enhanced to deal with\n    this properly [#432]\n  - Tests now using 3 DB nodes\n- Fix DB Membership signaling on DB server crash [#429]\n- The RTS with DDB test is now using 3 DB nodes and replication factor 3 [#434]\n- Avoid some C errors so we compile on Ubuntu [#428]\n\n\n## [0.7.3] (2022-01-03)\n\n### Fixed\n- Fix segfaults in RTS argument parsing [#420]\n  - Missing argument to option would previously lead to segfault, which is now\n    fixed [#419]\n  - Passing option arguments with =, like `--rts-wthreads=8` now works\n- Various fixes to C lib wrapping document [#418]\n- Renamed minienv to env [#417]\n  - Only internal change, does not influence what a user of Acton sees\n- Now testing RTS using DDB in CI [#425]\n\n\n## [0.7.2] (2021-12-15)\n\n### Added\n- Homebrew formula revamped to support Apple M1 [homebrew-acton#28]\n  - Formula now uses brew installed (\"system\") ghc instead of stack installed\n    GHC, which is more idiomatic Homebrew\n  - Mac on M1 users, simply do: `brew install actonlang/acton/acton`\n    - Acton will be automatically built from source!\n  - No pre-built binary packages (\"bottles\") as our build environment, which is\n    using GitHub Action runners, cannot build those\n- `actonc` compiler profiles fully implemented [#403]\n  - previously, `--dev` only used to enable RTS debug\n  - now, all libraries are compiled twice, for dev and rel, and packaged up into\n    libActon_dev and libActon_rel archives\n  - dev mode is compiled with debug symbols (`-g`)\n  - release mode is using optimized code (`-O3`)\n  - final program binary is also compiled with the same flags\n\n### Fixed\n- The RTS mode using the distributed backend for storing program state is now\n  working [#407]\n\n\n## [0.7.1] (2021-11-23)\n\nThere are currently known regressions:\n- using RTS together with the distributed backend database is not working\n\n### Fixed\n- `actonc` now explicitly using `-no-pie` on Linux [#390]\n  - this aligns with how we already build our object files, shipped in\n    libActon.a etc\n\n\n## [0.7.0] (2021-11-23)\n\nThere are currently known regressions:\n- using RTS together with the distributed backend database is not working\n\n### Added\n- Basic support for Apple M1 silicon [#383]\n  - Mostly about keeping track of Homebrew paths, since it uses `/opt/homebrew`\n    on Apple silicon vs `/usr/local` on Intel CPUs\n  - Not thoroughly tested, but Acton compiles and `actonc` appears to produce\n    working programs\n- *Acton by Example* book [#370] [#371] [#375]\n  - https://www.acton-lang.org/learn/acton-by-example/\n  - far from complete, but a decent start\n  - using mdBook format\n  - using svgbob plugin to draw pretty SVG art using ASCII art\n  - source in `docs/acton-by-example`\n    - source deliberately kept close (same git repo) to Acton itself, so we can\n      easily update docs as we update other things\n- The number of worker threads is made configurable [#365]\n  - Run an acton program with `--rts-wthreads X`\n  - As before, number of worker threads defaults to number of logical CPU cores\n    (threads)\n- RTS statistics and monitoring functionality [#353]\n  - Each worker thread keeps some statistics, like:\n    - number of sleeps\n    - number of continuations executed\n    - time spent executing continuation, counted in bucket less than:\n      - 100ns, 1us, 10us, 100us, 1ms, 10ms, 100ms, 1s, 10s, 100s, +Inf\n    - bookkeeping overhead, like taking internal locks, enqueueing messages etc,\n      also counted in buckets\n  - `utils/actonmon` is a simple utility to connect to monitor socket, fetch\n    statistics and display them\n    - can display in fancy table using `--rich` (using Python rich module)\n    - defaults to simple no-frills output that have no extra dependencies\n    - `--prom` will expose a http server exposing metrics to be consumed by\n      Prometheus in the OpenMetrics exposition format\n      - can then be displayed in Grafana or similar\n- There are now two compilation \"profiles\"; development & release [#345]\n  - `--dev` implies debug symbols are included and RTS debugging is enabled,\n    which was previously enabled with `--rts-debug`\n  - release mode is the default and does not include debug symbols nor RTS\n    debugging\n- `actonc --numeric-version` shows a numeric version number [#346]\n  - a stable interface to simply display the actonc version number\n  - unlike `--version` which stretches across multiple lines and includes the\n    versions of cc, the haskell stack used to build actonc etc\n- Debian packages are now added as assets to GitHub releases [#369]\n  - .deb have always been available as GH Action job artifact\n  - For release versions, the .deb was available via the Acton apt repo\n  - Now easily possible to grab historic versions as well as pre-release .deb,\n    i.e. from main branch by downloading .deb from GitHub release page\n\n### Changed\n- Acton compiler now built using Haskell LTS 18.12 [#335]\n- `--rts-debug` option replaced `--dev` [#345]\n- GitHub Actions now run for PRs and for main branch and tags [#385]\n  - Would previously run both for PRs and for push to a branch, resulting in\n    duplicate runs\n\n### Fixed\n- Significantly improve performance by reducing RTS worker thread wake ups [#360]\n  - Best case scenarios is on the scale of 10x performance with drastically\n    reduced syscall overhead\n- Fix lib path on Mac OS X on x86_64 [#384]\n  - Now includes `/usr/local/lib` in library search path\n  - This was previously included through some default mechanism but it is now\n    explicit\n- Make build more idempotent [#333]\n- Fix GNU sed check in Makefile [#344]\n- Add `#pragma once` to `numpy.h` [#331]\n- Avoid regenerating protobuf generated files [#382]\n  - Since the generated files are checked into git, we really do not want to\n    regenerate them, thus the Make target has been turned into a NOP\n- Fix GitHub Action caching issue by adding version cache key [#339]\n- Simplify GitHub issue template for bug report [#367]\n\n\n## [0.6.4] (2021-09-29)\n\nThere are currently known regressions:\n- using RTS together with the distributed backend database is not working\n\n### Fixed\n- `break` & `continue` now works in `for` loops that are CPS fragmented [#325]\n  - Using `break` would previously not work in a `for` loop if the loop was\n    broken into multiple continuations during the CPS transform. For example,\n    this happens when a call to another actor is made in the `for` loop.\n- An installed `actonc` can now find `__builtin__.h` [#327]\n  - A previous restructuring of files in order to improve the Makefile and build\n    organization led to us having to use weirdly long and relative include\n    paths. This ultimately led to run time failures of actonc. Since some of\n    these files need to be built both when building actonc itself as well as\n    when using actonc, the paths must remain the same in source and release\n    output. They did not after [#286], which has now been reverted.\n\n\n## [0.6.3] (2021-09-28)\n\nThere are currently known regressions:\n- using RTS together with the distributed backend database is not working\n\n### Added\n- Acton now has a apt repository - `apt.acton-lang.io` [#320]\n  - Version tagged releases are automatically uploaded.\n\n### Changed\n- `actonc` now uses `cc` rather than `gcc` [#303]\n- Acton project makefiles now use `$(CC)` rather than hardcoding `cc` [#303]\n- Acton is now built and tested on debian:bullseye (11, current stable) [#313]\n\n### Fixed\n- Debian packages now depend on non-dev libraries for utf8proc & protobuf [#315]\n- Makefile restructuring [#304] [#307]\n  - backend and compiler Makefiles have now been folded into the top level\n    Makefile.\n  - DAG is more complete and more things can run correctly in parallel.\n  - stack / ghc build now uses 4 parallel threads, for some speedup (55 seconds\n    -> 35 seconds on an AMD 5950X). Higher parallelism did not improve things\n    much further.\n  - Avoid declaring actonc as a PHONY target, which causes constant rebuilds,\n    not it actually has proper dependencies defined so make can understand when\n    there is nothing to do.\n- Debian packages now reflect tip version number [#307] [#308]\n  - Previously debian packages had the \"base version\", like 0.6.2, even when\n    built as a pre-release build. `actonc --version` in the package would still\n    correctly identify like e.g. `0.6.2.20210924.16.58.23`\n  - Now the .deb file also contains the complete build info, like\n    `acton_0.6.2.20210924.16.58.23_amd64.deb`\n\n\n## [0.6.2] (2021-09-23)\n\n### Added\n- Linuxbrew build [homebrew-acton#7]\n  - Acton can now be installed via Linuxbrew (Homebrew on Linux)\n\n### Fixed\n- Constraint grouping to also consider free environment types variables [#277]\n  - Previously, this bug in the constraint solver meant that `actonc` could hang\n    when compiling certain programs.\n- Added missing CPS case to fix return value [#279]\n  - Would previously lead to an internal compiler error where the generated C\n    code would not compile.\n- Fix RTS bug that could lead to segmentation fault [#285]\n  - The integrity of a linked list was not preserved during a certain operation\n    which would lead to a segmentation fault.\n  - The error typically occurred during high load situations.\n- Continuation environment now includes all variables [#288]\n  - Previously, after the CPS step, the generated continuation was lacking its\n    environment which meant some variables were inaccessible.\n- The numpy module is now working again [#293]\n  - It was broken during a code restructuring and has now been restored.\n  - The entire public interface is now contained in numpy.h (not spread over\n    multiple .h files as before).\n  - numpy.o is partially linked to hide any library dependencies.\n  - The same model of not leaking module internals will be used for other\n    modules in the future.\n\n\n## [0.6.1] (2021-09-19)\n\n### Added\n- Debian packaging [#60]\n  - There is now a .deb produced and uploaded as part of the artifacts for each\n    release on GitHub.\n\n### Changed\n- RTS now uses a minimum of 4 worker threads [#263]\n  - The default is to use as many worker threads as there are CPUs and set CPU\n    affinity to map worker threads to CPUs in a 1:1 fashion.\n  - The first core is used to run the eventloop that processes I/O and the rest\n    runs the main loop that executes actors.\n  - On machines with a low CPU count this can be catastrophic. The extreme\n    example being a single CPU machine, which consequently will have 0 worker\n    threads executing actors. It will only run the eventloop that processes I/O\n    and thus is unable to actually run an Acton program.\n  - Even on a 2 CPU machine, which would lead to a single worker thread\n    executing actors, this can be quite bad.\n  - We now run a minimum of 4 worker threads, 1 for the I/O eventloop and 3\n    actor processing threads, to get around these problems.\n\n\n## [0.6.0] (2021-09-17)\n\nDespite a regression in the RTS's distributed mode of operationa, v0.6.0 is\nreleased as improvements in other areas make it the best version of Acton to\ndate.\n\n### Added\n- Acton project concept [#140]\n  - An Acton project is a standardized structure for how to organize an Acton\n    project:\n    - At the root is an `Acton.toml` file. It is currently empty but its\n      location denotes the project root.\n    - `src/` is the directory in which source files are stored, imports are\n      relative to this directory, i.e. `import foo` will import `src/foo.act`\n      - imports will also search the system path as before for the stdlib modules\n    - `out/` is the output directory in which generated type file (`.ty`) and\n      object / library files are written as well as binaries\n      - `out/bin` is where executables end up (`actonc --root foo bar.act` will\n        produce an executable)\n      - `out/types` is where types files go\n      - `out/lib` is where object / library files go\n  - We used to write compiled output of modules to the system path. To install\n    acton on a system, outside of a users home directory, we can no longer write\n    to the system path since it is owned by root. Further, we don't want to\n    write to a common system path as different users code could collide.\n  - Now only the builtins and stdlib modules are in the system path. Other\n    compiled output, like type files and object files, are written to the\n    project directory.\n  - It is still possible to compile individual `.act` files as executabes\n    (`--root ROOT`), in which case `actonc` will create a temporary directory\n    for intermediate output and write the final file in the same directory as\n    the `.act` file. This is to preserve the current behavior when \"using acton\n    as a scripting language\".\n  - Overall, the idea is to cater to both:\n    - Acton as a scripting language\n      - Often a single source file - minimal \"project overhead\" wanted\n    - Acton for large projects\n      - Many modules, perhaps producing multiple executables\n      - Good project structure necessary to manage it all\n- There is now an RTS debug mode [#189]\n  - With `actonc --rts-debug`, an Acton program can be compiled with debug\n    functionality included.\n  - When a debug enabled Acton program is run with `my-program --rts-debug`,\n- Argument to configure the replication factor used with the distributed backend\n  database [#204]\n  - Default is 3, as that is the lowest value that makes sense for a quorum.\n  - Read and write quorum is derived from the replication factor / 2 + 1\n    - Thus, with replication=3, read/write quorum is 2\n- Connecting to multiple database backend servers for redundancy [#206]\n  - `--rts-ddb-host` can be specified multiple times to connect to multiple\n    backend servers\n  - Thus, an RTS compute node can survive a database server going down.\n  - The port number can be specified per host by appending it colon separated\n    from the hostname, like `--rts-ddb-host localhost:32001`\n- Monotonic time function have been added [#152]\n  - `time.monotonic()` returning a float.\n  - `time.monotonic_ns()` returning nanoseconds as an integer.\n\n### Changed\n- RTS now uses epoll on Linux [#243]\n  - Was previously written for kqueue, which runs natively on MacOS X.\n  - On Linux, a shim, libkqueue, was used to map kqueue calls to epoll.\n  - To reduce risk of error and potentially squeeze out more performance, epoll\n    is a better choice.\n  - Dependency on libkqueue has been removed, which makes it easier to compile\n    Acton on more platforms.\n- `time` module has been aligned with its Python counterpart [#152] [#197]\n  - `time.time()` function now returns a float.\n  - New function `time.time_ns()` returns time in nanoseconds as an integer.\n  - `RuntimeError` is raised on an error, just like Python\n- `actonc --version` now includes verbose output [#212]\n  - Previously it was required to run `actonc --version --verbose` to see CC\n    information etc. This is now included in the default output of `actonc\n    --version` and `--verbose` no longer influences the output.\n\n### Fixed\n- `actonc --version` no longer requires a \"dummy\" argument [#212]\n- Fix actor creation and initialization in the RTS [#186]\n  - Previously, actor creation and initialization was indeterministic and given\n    certain conditions, messages or even actors could be lost, leading to\n    system malfunction. One way in which this showed was how certain programs\n    would just hang even when they should exit.\n  - RTS has been entirely reworked in regards to actor creation and now follows\n    the overall language model, which makes things simpler and more robust.\n\n\n## [0.5.3] (2021-09-13)\n\n### Added\n- It is now possible to install Acton on Mac OS X via Homebrew\n  - `brew install actonlang/acton/acton`\n- Warnings are now generally treated as errors when compiling Acton [#153]\n  - Many warnings have been fixed.\n  - There are some exceptions added for some warnings.\n    - With time these should be reduced.\n- Bug triage and prioritization document [#165]\n  - see `docs/triage.md`\n\n### Fixed\n- Fix internal instantiations of tuples to use `$NEWTUPLE` [#173]\n  - For example functions like `divmod` that returns a tuple was using an\n    incorrect macro.\n- `divmod` now returns correct results. (#))\n  - It would previously return wildly incorrect results (integer wraparound\n    style) and could lead to segfaults due to incorrect tuple creation\n- Greater than or equal (`>=`) now works for integers [#161]\n  - It was broken and actually did an equal match.\n- Fix header inclusion for numpy use of arc4random functions [#155]\n- Situations where `actonc` was unable to unify atoms and ints or infer type\n  conversion have now been fixed. [#183]\n- Fix variable being out of scope in a function [#174]\n\n\n## [0.5.2] (2021-08-25)\n\n### Fixed\n- It is now possible to raise exceptions [#133] [#137]\n  - Previously a naming misalignment between the Acton compiler code generation\n    and the builtins of the RTS led to an Internal Compiler Error.\n  - BaseException is now also used instead of Exception, as it should.\n- Distributed RTS mode has been fixed with regards to actor bootstrap that\n  previously lead to duplicate actors [#121]\n- An actor method (callback) can now be passed as an argument to another actor\n  method [#129]\n  - This could previously lead to a segmentation fault during certain\n    situations.\n- Avoid cleaning away `modules/math.h` [#136]\n  - This was due to an outdated Makefile cleaning target\n- Type inferencing now works for all dicts [#139]\n  - Previously worked for some, for example a dict of strings but not for a dict\n    of ints.\n- The modules `acton.rts`, `math` and `random` now work correctly [#127]\n  - The type signature filed was missing but is now correctly built.\n  - There are test cases for these modules but the tests were not run in CI\n- More tests are now run in CI [#128]\n  - Due to a directory restructuring and assumptions (mother of all evil), some\n    tests were previously not run. While working locally on a developers\n    computer things worked due to manually compiled files. We failed to detect\n    these missing type signature files in CI since the tests were not run\n    automatically.\n- Type inference is now order independent [#142]\n  - There were previously situations in which the type inferencer was unable to\n    do its job based on the layout / order of the code.\n- `print(foo())` now correctly prints the return value of foo() rather than a\n  message reference (due to asynchronous evaluation) [#142]\n\n\n## [0.5.1] (2021-08-24)\n\n### Fixed\n- v0.5.0 was released with an incorrect version number and would identify itself\n  as version v0.4.2\n\n\n## [0.5.0] (2021-08-23)\n\n### Added\n- The distributed database backend is enabled in the RTS [#45]\n  - this was previously a build time flag\n  - it is now run time configuration via `--rts-ddb-host` and `--rts-ddb-port`\n  - see `examples/count` for a demo and instructions\n- RTS now has a `--rts-verbose` argument to make it more chatty [#45]\n- General evaluation of expressions in a boolean context [#107]\n  - explicit boolean expressions were already supported and working\n  - however, in Python any expression can be evaluated in a boolean context\n    which was not properly supported... and it now is!\n  - this could be considered a bug fix, like it should go under \"Fixed\" but it\n    is big enough of a thing to warrant being here... almost like new\n    functionality, although we probably did intend to support this all along\n- Description of development workflow, see `docs/development_workflow.md` [#73]\n- A short guide on how to wrap C libraries for use in Acton, see\n  `docs/wrapping_c_libraries.md` [#84]\n- `time.time()` function [#83]\n  - returns the current system time in nanoseconds as an integer\n  - `time` is a new module\n- `random.randint()` function [#113]\n  - `random` is a new module\n- `acton.rts.sleep()` function [#95]\n  - from a user perspective acts just like Pythons `time.sleep()`\n  - it uses `usleep` in C which means it actually sleeps the RTS thread\n    executing the actor\n    - this is typically a bad thing - we just want to sleep an actor, not the\n      RTS thread\n    - there are however use cases, like when implementing benchmarking or\n      similar.\n    - this is why it is under `acton.rts` and not in `time`\n  - `acton.rts` is a new module\n\n### Changed\n- Refactored Makefile structure to complete DAG [#77]\n  - use a single top level Makefile rather than recursive Makefiles\n  - only matters if you are doing development on Acton itself\n  - backend, being enough of a standalone piece, still has its own Makefile\n- `actonc --hgen` and `actonc --cgen` now outputs only code [#82]\n  - easier to pipe directly to a file\n  - compilation command not included, now available with `actonc --ccmd`\n- `actonc` argument `--path` is now called `--syspath` [#93]\n  - it is the system path and was already referred to as `syspath` internally\n- The build output, when building Acton itself, is now placed in `dist` [#88]\n  - makes it considerably easier to produce a release by tarring up its content\n  - release size has been reduced to almost half by avoiding unnecessary files\n  - the top level directories, like `modules` is now a source directory and no\n    longer \"the working directory of `actonc`\"\n- Source code of several modules have been moved from separate subdirs, like\n  `math` and `time`, into `modules/`. Less top level clutter! [#99]\n\n### Fixed\n- Improved dependency declaration for backend [#77]\n  - Only matters if you are building Acton yourself and making changes to the\n    backend database\n\n\n## [0.4.2] (2021-08-05)\n\n### Added\n- `tip` releases are now available at stable URLs: [#70]\n  - https://github.com/actonlang/acton/releases/download/tip/acton-darwin-x86_64.tar.bz2\n  - https://github.com/actonlang/acton/releases/download/tip/acton-linux-x86_64.tar.bz2\n\n### Fixed\n- Versioned releases now use correct version number, like `0.4.1` rather than\n  the version style used for `tip` releases which include the date & time, like\n  `0.4.1.2021.08.05.12.15.37` [#69]\n- tip release tar balls now reflect the full tip version in the filename [#71]\n  - like `acton-linux-x86_64-0.4.1.20210805.13.46.55.tar.bz2`\n  - previously, it would just be `acton-linux-x86_64-0.4.1.tar.bz2`, making it\n    difficult to differentiate against the proper 0.4.1 or other nightlies\n\n\n## [0.4.1] (2021-08-05)\n\n### Added\n- `--version --verbose` will print verbose version information [#41]\n- Internal compiler errors include information about the C compiler (cc) [#41]\n- Acton is now made available as GitHub Releases [#53]\n  - pre-built binary releases! Users no longer need to compile Acton themselves\n  - available from [Releases page](https://github.com/actonlang/acton/releases)\n  - versioned releases, like this v0.4.1, are available\n  - latest build from `main` branch is available as `tip`\n\n### Fixed\n- Integer subtraction has been fixed [#48]\n  - wrong order of operators would previously return wildly incorrect results\n\n\n## [0.4.0] (2021-07-23)\n\n### Added\n- Linux compatibility! [#1] [#14] [#15]\n  - it is now possible to compile the Acton compiler (actonc), the backend and\n    the RTS on Linux\n  - actonc can now compile Acton programs on Linux\n  - Linux on x86_64 is tested, no other architectures\n  - libkqueue is used on Linux as a compatibility shim between kqueue calls and\n    epoll\n    - Acton was initially developed on OS X and the RTS therefore uses kqueue\n      and not epoll / aio(uring)\n- More test cases, in particular the ones for which we have GitHub issues [#21]\n- CI runs on Linux too [#15]\n  - acton is built and tested on both Linux and OS X\n  - all tests are the same across both platforms\n- `actonc` has got a `--version` argument\n\n### Changed\n- Now uses Haskell lts-17.14 instead of lts-13.0 [#2]\n\n### Removed\n- The project repository has been cleaned up overall\n\n### Fixed\n- `actonc` now detects and reports internal compiler errors [#28]\n  - happens when gcc fails to compile the C code that actonc generates\n- A bunch of compiler surprises have been made less surprising\n  - see git log for details ;)\n\n\n## [0.3.0] (2021-04-14)\n\n### Added\n- Acton is now public and published at its new [home on\n  Github](https://github.com/actonlang/acton/)\n- Added basic (working) build instructions\n- A basic test suite with a few tests, including some of the examples being\n  reused for testing\n- GitHub Actions is used as CI to build and test Acton\n  - Mac OS X / Darwin is the only platform used for testing Acton\n\n### Changed\n- distributed database backend is disabled in builds per default\n  - while working, it is too rough around the edges to be enabled per default\n  - in particular, it needs to be made run time configurable\n\n\n## 0.2.0 (a long long time ago, like 2019)\n\nThis is a sort of fictitious release that roughly maps to the prehistoric era\nbefore recorded time. There was a git log but no real version keeping.\n\n0.2.0 was the first ever version of the \"new compiler\". It wasn't 0.1 because in\nan earlier prehistoric era, another system existed which could be called the\nfirst incarnation of Acton. It was more of a proof of concept based on Python as\na runtime and with a hacked up Cassandra database as a backend store. Since\nthen, this second incarnation has been in focus and 0.2.0 was its first version.\n\n\n[#1]: https://github.com/actonlang/acton/pull/1\n[#2]: https://github.com/actonlang/acton/pull/2\n[#7]: https://github.com/actonlang/acton/pull/7\n[#14]: https://github.com/actonlang/acton/pull/14\n[#15]: https://github.com/actonlang/acton/pull/15\n[#21]: https://github.com/actonlang/acton/pull/21\n[#28]: https://github.com/actonlang/acton/pull/28\n[#14]: https://github.com/actonlang/acton/pull/14\n[#15]: https://github.com/actonlang/acton/pull/15\n[#21]: https://github.com/actonlang/acton/pull/21\n[#28]: https://github.com/actonlang/acton/pull/28\n[#41]: https://github.com/actonlang/acton/pull/41\n[#45]: https://github.com/actonlang/acton/pull/45\n[#48]: https://github.com/actonlang/acton/pull/48\n[#53]: https://github.com/actonlang/acton/pull/53\n[#60]: https://github.com/actonlang/acton/pull/60\n[#69]: https://github.com/actonlang/acton/pull/69\n[#70]: https://github.com/actonlang/acton/pull/70\n[#71]: https://github.com/actonlang/acton/pull/71\n[#73]: https://github.com/actonlang/acton/pull/73\n[#77]: https://github.com/actonlang/acton/pull/77\n[#82]: https://github.com/actonlang/acton/pull/82\n[#83]: https://github.com/actonlang/acton/pull/83\n[#84]: https://github.com/actonlang/acton/pull/84\n[#88]: https://github.com/actonlang/acton/pull/88\n[#93]: https://github.com/actonlang/acton/pull/93\n[#95]: https://github.com/actonlang/acton/pull/95\n[#99]: https://github.com/actonlang/acton/pull/99\n[#107]: https://github.com/actonlang/acton/pull/107\n[#113]: https://github.com/actonlang/acton/pull/113\n[#121]: https://github.com/actonlang/acton/pull/121\n[#127]: https://github.com/actonlang/acton/pull/127\n[#128]: https://github.com/actonlang/acton/pull/128\n[#129]: https://github.com/actonlang/acton/pull/129\n[#133]: https://github.com/actonlang/acton/pull/133\n[#136]: https://github.com/actonlang/acton/pull/136\n[#137]: https://github.com/actonlang/acton/pull/137\n[#139]: https://github.com/actonlang/acton/pull/139\n[#140]: https://github.com/actonlang/acton/pull/140\n[#142]: https://github.com/actonlang/acton/pull/142\n[#146]: https://github.com/actonlang/acton/issues/146\n[#152]: https://github.com/actonlang/acton/pull/152\n[#153]: https://github.com/actonlang/acton/pull/153\n[#155]: https://github.com/actonlang/acton/pull/155\n[#161]: https://github.com/actonlang/acton/pull/161\n[#165]: https://github.com/actonlang/acton/pull/165\n[#173]: https://github.com/actonlang/acton/pull/173\n[#174]: https://github.com/actonlang/acton/pull/174\n[#183]: https://github.com/actonlang/acton/pull/183\n[#186]: https://github.com/actonlang/acton/pull/186\n[#189]: https://github.com/actonlang/acton/pull/189\n[#197]: https://github.com/actonlang/acton/pull/197\n[#204]: https://github.com/actonlang/acton/pull/204\n[#206]: https://github.com/actonlang/acton/pull/206\n[#212]: https://github.com/actonlang/acton/pull/212\n[#238]: https://github.com/actonlang/acton/issues/238\n[#243]: https://github.com/actonlang/acton/pull/243\n[#263]: https://github.com/actonlang/acton/pull/264\n[#277]: https://github.com/actonlang/acton/pull/277\n[#279]: https://github.com/actonlang/acton/pull/279\n[#285]: https://github.com/actonlang/acton/pull/285\n[#286]: https://github.com/actonlang/acton/pull/286\n[#288]: https://github.com/actonlang/acton/pull/288\n[#293]: https://github.com/actonlang/acton/pull/293\n[#303]: https://github.com/actonlang/acton/pull/303\n[#304]: https://github.com/actonlang/acton/pull/304\n[#307]: https://github.com/actonlang/acton/pull/307\n[#308]: https://github.com/actonlang/acton/pull/308\n[#313]: https://github.com/actonlang/acton/pull/313\n[#315]: https://github.com/actonlang/acton/pull/315\n[#320]: https://github.com/actonlang/acton/pull/320\n[#325]: https://github.com/actonlang/acton/pull/325\n[#327]: https://github.com/actonlang/acton/pull/327\n[#331]: https://github.com/actonlang/acton/pull/331\n[#333]: https://github.com/actonlang/acton/pull/333\n[#335]: https://github.com/actonlang/acton/pull/335\n[#339]: https://github.com/actonlang/acton/pull/339\n[#344]: https://github.com/actonlang/acton/pull/344\n[#345]: https://github.com/actonlang/acton/pull/345\n[#346]: https://github.com/actonlang/acton/pull/346\n[#353]: https://github.com/actonlang/acton/pull/353\n[#360]: https://github.com/actonlang/acton/pull/360\n[#365]: https://github.com/actonlang/acton/pull/365\n[#367]: https://github.com/actonlang/acton/pull/367\n[#369]: https://github.com/actonlang/acton/pull/369\n[#370]: https://github.com/actonlang/acton/pull/370\n[#371]: https://github.com/actonlang/acton/pull/371\n[#374]: https://github.com/actonlang/acton/issues/374\n[#375]: https://github.com/actonlang/acton/pull/375\n[#382]: https://github.com/actonlang/acton/pull/382\n[#383]: https://github.com/actonlang/acton/pull/383\n[#384]: https://github.com/actonlang/acton/pull/384\n[#385]: https://github.com/actonlang/acton/pull/385\n[#390]: https://github.com/actonlang/acton/pull/390\n[#403]: https://github.com/actonlang/acton/pull/403\n[#407]: https://github.com/actonlang/acton/pull/407\n[#408]: https://github.com/actonlang/acton/issues/408\n[#409]: https://github.com/actonlang/acton/issues/409\n[#417]: https://github.com/actonlang/acton/pull/417\n[#418]: https://github.com/actonlang/acton/pull/418\n[#419]: https://github.com/actonlang/acton/issues/419\n[#420]: https://github.com/actonlang/acton/pull/420\n[#425]: https://github.com/actonlang/acton/pull/425\n[#427]: https://github.com/actonlang/acton/pull/427\n[#428]: https://github.com/actonlang/acton/pull/428\n[#429]: https://github.com/actonlang/acton/pull/429\n[#430]: https://github.com/actonlang/acton/pull/430\n[#431]: https://github.com/actonlang/acton/issues/431\n[#432]: https://github.com/actonlang/acton/issues/432\n[#434]: https://github.com/actonlang/acton/pull/434\n[#445]: https://github.com/actonlang/acton/issues/445\n[#446]: https://github.com/actonlang/acton/pull/446\n[#447]: https://github.com/actonlang/acton/pull/447\n[#449]: https://github.com/actonlang/acton/issues/449\n[#453]: https://github.com/actonlang/acton/pull/453\n[#457]: https://github.com/actonlang/acton/pull/457\n[#460]: https://github.com/actonlang/acton/pull/460\n[#464]: https://github.com/actonlang/acton/pull/464\n[#465]: https://github.com/actonlang/acton/pull/465\n[#469]: https://github.com/actonlang/acton/pull/469\n[#472]: https://github.com/actonlang/acton/issues/472\n[#473]: https://github.com/actonlang/acton/pull/473\n[#474]: https://github.com/actonlang/acton/pull/474\n[#475]: https://github.com/actonlang/acton/pull/475\n[#476]: https://github.com/actonlang/acton/pull/476\n[#478]: https://github.com/actonlang/acton/pull/478\n[#479]: https://github.com/actonlang/acton/pull/479\n[#481]: https://github.com/actonlang/acton/pull/481\n[#488]: https://github.com/actonlang/acton/pull/488\n[#493]: https://github.com/actonlang/acton/pull/493\n[#494]: https://github.com/actonlang/acton/pull/494\n[#499]: https://github.com/actonlang/acton/pull/499\n[#501]: https://github.com/actonlang/acton/pull/501\n[#502]: https://github.com/actonlang/acton/pull/502\n[#504]: https://github.com/actonlang/acton/pull/504\n[#506]: https://github.com/actonlang/acton/pull/506\n[#509]: https://github.com/actonlang/acton/pull/509\n[#512]: https://github.com/actonlang/acton/pull/512\n[#514]: https://github.com/actonlang/acton/pull/514\n[#516]: https://github.com/actonlang/acton/pull/516\n[#517]: https://github.com/actonlang/acton/pull/517\n[#518]: https://github.com/actonlang/acton/pull/518\n[#521]: https://github.com/actonlang/acton/pull/521\n[#522]: https://github.com/actonlang/acton/pull/522\n[#524]: https://github.com/actonlang/acton/issues/524\n[#527]: https://github.com/actonlang/acton/issues/527\n[#528]: https://github.com/actonlang/acton/pull/528\n[#529]: https://github.com/actonlang/acton/pull/529\n[#530]: https://github.com/actonlang/acton/pull/530\n[#535]: https://github.com/actonlang/acton/pull/535\n[#538]: https://github.com/actonlang/acton/pull/538\n[#542]: https://github.com/actonlang/acton/pull/542\n[#546]: https://github.com/actonlang/acton/pull/546\n[#547]: https://github.com/actonlang/acton/issues/547\n[#559]: https://github.com/actonlang/acton/pull/559\n[#570]: https://github.com/actonlang/acton/pull/570\n[#571]: https://github.com/actonlang/acton/pull/571\n[#574]: https://github.com/actonlang/acton/pull/574\n[#584]: https://github.com/actonlang/acton/pull/584\n[#586]: https://github.com/actonlang/acton/pull/586\n[#587]: https://github.com/actonlang/acton/pull/587\n[#588]: https://github.com/actonlang/acton/pull/588\n[#599]: https://github.com/actonlang/acton/pull/599\n[#601]: https://github.com/actonlang/acton/pull/601\n[#602]: https://github.com/actonlang/acton/pull/602\n[#607]: https://github.com/actonlang/acton/pull/607\n[#608]: https://github.com/actonlang/acton/pull/608\n[#612]: https://github.com/actonlang/acton/pull/612\n[#623]: https://github.com/actonlang/acton/pull/623\n[#624]: https://github.com/actonlang/acton/pull/624\n[#625]: https://github.com/actonlang/acton/pull/625\n[#627]: https://github.com/actonlang/acton/issues/627\n[#628]: https://github.com/actonlang/acton/pull/628\n[#629]: https://github.com/actonlang/acton/pull/629\n[#631]: https://github.com/actonlang/acton/pull/631\n[#633]: https://github.com/actonlang/acton/pull/633\n[#645]: https://github.com/actonlang/acton/pull/645\n[#655]: https://github.com/actonlang/acton/pull/655\n[#685]: https://github.com/actonlang/acton/pull/685\n[#693]: https://github.com/actonlang/acton/pull/693\n[#698]: https://github.com/actonlang/acton/pull/698\n[#700]: https://github.com/actonlang/acton/pull/700\n[#706]: https://github.com/actonlang/acton/pull/706\n[#719]: https://github.com/actonlang/acton/pull/719\n[#726]: https://github.com/actonlang/acton/pull/726\n[#733]: https://github.com/actonlang/acton/pull/733\n[#752]: https://github.com/actonlang/acton/pull/752\n[#760]: https://github.com/actonlang/acton/pull/760\n[#788]: https://github.com/actonlang/acton/issues/788\n[#806]: https://github.com/actonlang/acton/pull/806\n[#808]: https://github.com/actonlang/acton/pull/808\n[#823]: https://github.com/actonlang/acton/pull/823\n[#829]: https://github.com/actonlang/acton/pull/829\n[#835]: https://github.com/actonlang/acton/issues/835\n[#840]: https://github.com/actonlang/acton/pull/840\n[#845]: https://github.com/actonlang/acton/pull/845\n[#846]: https://github.com/actonlang/acton/pull/846\n[#849]: https://github.com/actonlang/acton/issues/849\n[#853]: https://github.com/actonlang/acton/issues/853\n[#868]: https://github.com/actonlang/acton/pull/868\n[#869]: https://github.com/actonlang/acton/issues/869\n[#882]: https://github.com/actonlang/acton/issues/882\n[#885]: https://github.com/actonlang/acton/issues/885\n[#887]: https://github.com/actonlang/acton/issues/887\n[#890]: https://github.com/actonlang/acton/issues/890\n[#892]: https://github.com/actonlang/acton/pull/892\n[#900]: https://github.com/actonlang/acton/pull/900\n[#907]: https://github.com/actonlang/acton/issues/907\n[#910]: https://github.com/actonlang/acton/pull/910\n[#913]: https://github.com/actonlang/acton/issues/913\n[#916]: https://github.com/actonlang/acton/pull/916\n[#917]: https://github.com/actonlang/acton/pull/917\n[#922]: https://github.com/actonlang/acton/pull/922\n[#926]: https://github.com/actonlang/acton/issues/926\n[#925]: https://github.com/actonlang/acton/pull/925\n[#929]: https://github.com/actonlang/acton/pull/929\n[#932]: https://github.com/actonlang/acton/pull/932\n[#941]: https://github.com/actonlang/acton/issues/941\n[#949]: https://github.com/actonlang/acton/pull/949\n[#950]: https://github.com/actonlang/acton/pull/950\n[#951]: https://github.com/actonlang/acton/issues/951\n[#955]: https://github.com/actonlang/acton/pull/955\n[#957]: https://github.com/actonlang/acton/pull/957\n[#969]: https://github.com/actonlang/acton/issues/969\n[#971]: https://github.com/actonlang/acton/pull/971\n[#972]: https://github.com/actonlang/acton/issues/972\n[#976]: https://github.com/actonlang/acton/pull/976\n[#984]: https://github.com/actonlang/acton/pull/984\n[#988]: https://github.com/actonlang/acton/pull/988\n[#1003]: https://github.com/actonlang/acton/issues/1003\n[#1020]: https://github.com/actonlang/acton/pull/1020\n[#1027]: https://github.com/actonlang/acton/issues/1027\n[#1029]: https://github.com/actonlang/acton/issues/1029\n[#1047]: https://github.com/actonlang/acton/issues/1047\n[#1050]: https://github.com/actonlang/acton/issues/1050\n[#1053]: https://github.com/actonlang/acton/pull/1053\n[#1054]: https://github.com/actonlang/acton/pull/1054\n[#1055]: https://github.com/actonlang/acton/pull/1055\n[#1056]: https://github.com/actonlang/acton/pull/1056\n[#1058]: https://github.com/actonlang/acton/pull/1058\n[#1060]: https://github.com/actonlang/acton/pull/1060\n[#1065]: https://github.com/actonlang/acton/pull/1065\n[#1068]: https://github.com/actonlang/acton/pull/1068\n[#1076]: https://github.com/actonlang/acton/pull/1076\n[#1087]: https://github.com/actonlang/acton/pull/1087\n[#1088]: https://github.com/actonlang/acton/pull/1088\n[#1089]: https://github.com/actonlang/acton/pull/1089\n[#1091]: https://github.com/actonlang/acton/issues/1091\n[#1093]: https://github.com/actonlang/acton/pull/1093\n[#1097]: https://github.com/actonlang/acton/pull/1097\n[#2253]: https://github.com/actonlang/acton/pull/2253\n[#2254]: https://github.com/actonlang/acton/pull/2254\n[#2256]: https://github.com/actonlang/acton/pull/2256\n[#2257]: https://github.com/actonlang/acton/pull/2257\n[#2258]: https://github.com/actonlang/acton/pull/2258\n[#2259]: https://github.com/actonlang/acton/pull/2259\n[#2261]: https://github.com/actonlang/acton/pull/2261\n[#2262]: https://github.com/actonlang/acton/pull/2262\n\n[#41]: https://github.com/actonlang/acton/pull/41\n[#45]: https://github.com/actonlang/acton/pull/45\n[#48]: https://github.com/actonlang/acton/pull/48\n[#53]: https://github.com/actonlang/acton/pull/53\n[#60]: https://github.com/actonlang/acton/pull/60\n[#69]: https://github.com/actonlang/acton/pull/69\n[#126]: https://github.com/actonlang/acton/pull/126\n[#657]: https://github.com/actonlang/acton/pull/657\n[#766]: https://github.com/actonlang/acton/pull/766\n[#796]: https://github.com/actonlang/acton/pull/796\n[#797]: https://github.com/actonlang/acton/pull/797\n[#798]: https://github.com/actonlang/acton/pull/798\n[#799]: https://github.com/actonlang/acton/pull/799\n[#800]: https://github.com/actonlang/acton/pull/800\n[#801]: https://github.com/actonlang/acton/pull/801\n[#804]: https://github.com/actonlang/acton/pull/804\n[#812]: https://github.com/actonlang/acton/pull/812\n[#973]: https://github.com/actonlang/acton/pull/973\n[#1010]: https://github.com/actonlang/acton/pull/1010\n[#1061]: https://github.com/actonlang/acton/pull/1061\n[#1077]: https://github.com/actonlang/acton/pull/1077\n[#1080]: https://github.com/actonlang/acton/pull/1080\n[#1092]: https://github.com/actonlang/acton/pull/1092\n[#1103]: https://github.com/actonlang/acton/pull/1103\n[#1105]: https://github.com/actonlang/acton/pull/1105\n[#1106]: https://github.com/actonlang/acton/pull/1106\n[#1107]: https://github.com/actonlang/acton/pull/1107\n[#1110]: https://github.com/actonlang/acton/pull/1110\n[#1111]: https://github.com/actonlang/acton/pull/1111\n[#1112]: https://github.com/actonlang/acton/pull/1112\n[#1115]: https://github.com/actonlang/acton/pull/1115\n[#1118]: https://github.com/actonlang/acton/pull/1118\n[#1119]: https://github.com/actonlang/acton/pull/1119\n[#1124]: https://github.com/actonlang/acton/pull/1124\n[#1127]: https://github.com/actonlang/acton/pull/1127\n[#1136]: https://github.com/actonlang/acton/pull/1136\n[#1137]: https://github.com/actonlang/acton/pull/1137\n[#1140]: https://github.com/actonlang/acton/pull/1140\n[#1141]: https://github.com/actonlang/acton/pull/1141\n[#1144]: https://github.com/actonlang/acton/pull/1144\n[#1145]: https://github.com/actonlang/acton/pull/1145\n[#1148]: https://github.com/actonlang/acton/pull/1148\n[#1149]: https://github.com/actonlang/acton/pull/1149\n[#1150]: https://github.com/actonlang/acton/pull/1150\n[#1160]: https://github.com/actonlang/acton/pull/1160\n[#1162]: https://github.com/actonlang/acton/pull/1162\n[#1169]: https://github.com/actonlang/acton/pull/1169\n[#1172]: https://github.com/actonlang/acton/pull/1172\n[#1174]: https://github.com/actonlang/acton/pull/1174\n[#1176]: https://github.com/actonlang/acton/pull/1176\n[#1177]: https://github.com/actonlang/acton/pull/1177\n[#1181]: https://github.com/actonlang/acton/pull/1181\n[#1185]: https://github.com/actonlang/acton/pull/1185\n[#1186]: https://github.com/actonlang/acton/pull/1186\n[#1188]: https://github.com/actonlang/acton/pull/1188\n[#1192]: https://github.com/actonlang/acton/pull/1192\n[#1193]: https://github.com/actonlang/acton/pull/1193\n[#1194]: https://github.com/actonlang/acton/pull/1194\n[#1196]: https://github.com/actonlang/acton/pull/1196\n[#1197]: https://github.com/actonlang/acton/pull/1197\n[#1198]: https://github.com/actonlang/acton/pull/1198\n[#1199]: https://github.com/actonlang/acton/pull/1199\n[#1202]: https://github.com/actonlang/acton/pull/1202\n[#1203]: https://github.com/actonlang/acton/pull/1203\n[#1206]: https://github.com/actonlang/acton/pull/1206\n[#1207]: https://github.com/actonlang/acton/pull/1207\n[#1208]: https://github.com/actonlang/acton/pull/1208\n[#1210]: https://github.com/actonlang/acton/pull/1210\n[#1211]: https://github.com/actonlang/acton/pull/1211\n[#1216]: https://github.com/actonlang/acton/pull/1216\n[#1217]: https://github.com/actonlang/acton/pull/1217\n[#1219]: https://github.com/actonlang/acton/pull/1219\n[#1220]: https://github.com/actonlang/acton/pull/1220\n[#1225]: https://github.com/actonlang/acton/pull/1225\n[#1226]: https://github.com/actonlang/acton/pull/1226\n[#1228]: https://github.com/actonlang/acton/pull/1228\n[#1235]: https://github.com/actonlang/acton/pull/1235\n[#1237]: https://github.com/actonlang/acton/pull/1237\n[#1246]: https://github.com/actonlang/acton/pull/1246\n[#1249]: https://github.com/actonlang/acton/pull/1249\n[#1256]: https://github.com/actonlang/acton/pull/1256\n[#1258]: https://github.com/actonlang/acton/pull/1258\n[#1260]: https://github.com/actonlang/acton/pull/1260\n[#1262]: https://github.com/actonlang/acton/pull/1262\n[#1263]: https://github.com/actonlang/acton/pull/1263\n[#1264]: https://github.com/actonlang/acton/pull/1264\n[#1265]: https://github.com/actonlang/acton/pull/1265\n[#1267]: https://github.com/actonlang/acton/pull/1267\n[#1269]: https://github.com/actonlang/acton/pull/1269\n[#1270]: https://github.com/actonlang/acton/pull/1270\n[#1274]: https://github.com/actonlang/acton/pull/1274\n[#1277]: https://github.com/actonlang/acton/pull/1277\n[#1278]: https://github.com/actonlang/acton/pull/1278\n[#1279]: https://github.com/actonlang/acton/pull/1279\n[#1282]: https://github.com/actonlang/acton/pull/1282\n[#1283]: https://github.com/actonlang/acton/pull/1283\n[#1284]: https://github.com/actonlang/acton/pull/1284\n[#1303]: https://github.com/actonlang/acton/pull/1303\n[#1304]: https://github.com/actonlang/acton/pull/1304\n[#1309]: https://github.com/actonlang/acton/pull/1309\n[#1316]: https://github.com/actonlang/acton/pull/1316\n[#1323]: https://github.com/actonlang/acton/pull/1323\n[#1325]: https://github.com/actonlang/acton/pull/1325\n[#1329]: https://github.com/actonlang/acton/pull/1329\n[#1331]: https://github.com/actonlang/acton/pull/1331\n[#1332]: https://github.com/actonlang/acton/pull/1332\n[#1333]: https://github.com/actonlang/acton/pull/1333\n[#1334]: https://github.com/actonlang/acton/pull/1334\n[#1336]: https://github.com/actonlang/acton/pull/1336\n[#1337]: https://github.com/actonlang/acton/pull/1337\n[#1338]: https://github.com/actonlang/acton/pull/1338\n[#1340]: https://github.com/actonlang/acton/pull/1340\n[#1341]: https://github.com/actonlang/acton/pull/1341\n[#1343]: https://github.com/actonlang/acton/pull/1343\n[#1344]: https://github.com/actonlang/acton/pull/1344\n[#1345]: https://github.com/actonlang/acton/pull/1345\n[#1346]: https://github.com/actonlang/acton/pull/1346\n[#1348]: https://github.com/actonlang/acton/pull/1348\n[#1349]: https://github.com/actonlang/acton/pull/1349\n[#1365]: https://github.com/actonlang/acton/pull/1365\n[#1367]: https://github.com/actonlang/acton/pull/1367\n[#1371]: https://github.com/actonlang/acton/pull/1371\n[#1372]: https://github.com/actonlang/acton/pull/1372\n[#1374]: https://github.com/actonlang/acton/pull/1374\n[#1382]: https://github.com/actonlang/acton/pull/1382\n[#1383]: https://github.com/actonlang/acton/pull/1383\n[#1388]: https://github.com/actonlang/acton/pull/1388\n[#1390]: https://github.com/actonlang/acton/pull/1390\n[#1391]: https://github.com/actonlang/acton/pull/1391\n[#1392]: https://github.com/actonlang/acton/pull/1392\n[#1395]: https://github.com/actonlang/acton/pull/1395\n[#1398]: https://github.com/actonlang/acton/pull/1398\n[#1399]: https://github.com/actonlang/acton/pull/1399\n[#1402]: https://github.com/actonlang/acton/pull/1402\n[#1404]: https://github.com/actonlang/acton/pull/1404\n[#1405]: https://github.com/actonlang/acton/pull/1405\n[#1406]: https://github.com/actonlang/acton/pull/1406\n[#1407]: https://github.com/actonlang/acton/pull/1407\n[#1411]: https://github.com/actonlang/acton/pull/1411\n[#1415]: https://github.com/actonlang/acton/pull/1415\n[#1420]: https://github.com/actonlang/acton/pull/1420\n[#1421]: https://github.com/actonlang/acton/pull/1421\n[#1422]: https://github.com/actonlang/acton/pull/1422\n[#1423]: https://github.com/actonlang/acton/pull/1423\n[#1433]: https://github.com/actonlang/acton/pull/1433\n[#1435]: https://github.com/actonlang/acton/pull/1435\n[#1438]: https://github.com/actonlang/acton/pull/1438\n[#1455]: https://github.com/actonlang/acton/pull/1455\n[#1456]: https://github.com/actonlang/acton/pull/1456\n[#1459]: https://github.com/actonlang/acton/pull/1459\n[#1461]: https://github.com/actonlang/acton/pull/1461\n[#1463]: https://github.com/actonlang/acton/pull/1463\n[#1470]: https://github.com/actonlang/acton/pull/1470\n[#1481]: https://github.com/actonlang/acton/pull/1481\n[#1483]: https://github.com/actonlang/acton/pull/1483\n[#1485]: https://github.com/actonlang/acton/pull/1485\n[#1499]: https://github.com/actonlang/acton/pull/1499\n[#1500]: https://github.com/actonlang/acton/pull/1500\n[#1504]: https://github.com/actonlang/acton/pull/1504\n[#1506]: https://github.com/actonlang/acton/pull/1506\n[#1510]: https://github.com/actonlang/acton/pull/1510\n[#1517]: https://github.com/actonlang/acton/pull/1517\n[#1522]: https://github.com/actonlang/acton/pull/1522\n[#1524]: https://github.com/actonlang/acton/pull/1524\n[#1527]: https://github.com/actonlang/acton/pull/1527\n[#1530]: https://github.com/actonlang/acton/pull/1530\n[#1536]: https://github.com/actonlang/acton/pull/1536\n[#1539]: https://github.com/actonlang/acton/pull/1539\n[#1541]: https://github.com/actonlang/acton/pull/1541\n[#1545]: https://github.com/actonlang/acton/pull/1545\n[#1546]: https://github.com/actonlang/acton/pull/1546\n[#1547]: https://github.com/actonlang/acton/pull/1547\n[#1551]: https://github.com/actonlang/acton/pull/1551\n[#1552]: https://github.com/actonlang/acton/pull/1552\n[#1553]: https://github.com/actonlang/acton/pull/1553\n[#1554]: https://github.com/actonlang/acton/pull/1554\n[#1556]: https://github.com/actonlang/acton/pull/1556\n[#1559]: https://github.com/actonlang/acton/pull/1559\n[#1560]: https://github.com/actonlang/acton/pull/1560\n[#1571]: https://github.com/actonlang/acton/pull/1571\n[#1573]: https://github.com/actonlang/acton/pull/1573\n[#1577]: https://github.com/actonlang/acton/pull/1577\n[#1582]: https://github.com/actonlang/acton/pull/1582\n[#1583]: https://github.com/actonlang/acton/pull/1583\n[#1586]: https://github.com/actonlang/acton/pull/1586\n[#1587]: https://github.com/actonlang/acton/pull/1587\n[#1589]: https://github.com/actonlang/acton/pull/1589\n[#1591]: https://github.com/actonlang/acton/pull/1591\n[#1596]: https://github.com/actonlang/acton/pull/1596\n[#1598]: https://github.com/actonlang/acton/pull/1598\n[#1600]: https://github.com/actonlang/acton/pull/1600\n[#1609]: https://github.com/actonlang/acton/pull/1609\n[#1615]: https://github.com/actonlang/acton/pull/1615\n[#1617]: https://github.com/actonlang/acton/pull/1617\n[#1618]: https://github.com/actonlang/acton/pull/1618\n[#1619]: https://github.com/actonlang/acton/pull/1619\n[#1627]: https://github.com/actonlang/acton/pull/1627\n[#1645]: https://github.com/actonlang/acton/pull/1645\n[#1654]: https://github.com/actonlang/acton/pull/1654\n[#1655]: https://github.com/actonlang/acton/pull/1655\n[#1709]: https://github.com/actonlang/acton/pull/1709\n[#1714]: https://github.com/actonlang/acton/pull/1714\n[#1715]: https://github.com/actonlang/acton/pull/1715\n[#1723]: https://github.com/actonlang/acton/pull/1723\n[#1805]: https://github.com/actonlang/acton/pull/1805\n[#2255]: https://github.com/actonlang/acton/pull/2255\n[#2260]: https://github.com/actonlang/acton/pull/2260\n[#2266]: https://github.com/actonlang/acton/pull/2266\n[#2267]: https://github.com/actonlang/acton/pull/2267\n[#2280]: https://github.com/actonlang/acton/pull/2280\n[#2282]: https://github.com/actonlang/acton/pull/2282\n[#2285]: https://github.com/actonlang/acton/pull/2285\n[#2289]: https://github.com/actonlang/acton/pull/2289\n[#2291]: https://github.com/actonlang/acton/pull/2291\n[#2298]: https://github.com/actonlang/acton/pull/2298\n[#2303]: https://github.com/actonlang/acton/pull/2303\n[#2304]: https://github.com/actonlang/acton/pull/2304\n[#2308]: https://github.com/actonlang/acton/pull/2308\n[#2310]: https://github.com/actonlang/acton/pull/2310\n[#2313]: https://github.com/actonlang/acton/pull/2313\n[#2317]: https://github.com/actonlang/acton/pull/2317\n[#2321]: https://github.com/actonlang/acton/pull/2321\n[#2323]: https://github.com/actonlang/acton/pull/2323\n[#2327]: https://github.com/actonlang/acton/pull/2327\n[#2337]: https://github.com/actonlang/acton/pull/2337\n[#2342]: https://github.com/actonlang/acton/pull/2342\n[#2348]: https://github.com/actonlang/acton/pull/2348\n[#2349]: https://github.com/actonlang/acton/pull/2349\n[#2352]: https://github.com/actonlang/acton/pull/2352\n[#2354]: https://github.com/actonlang/acton/pull/2354\n[#2355]: https://github.com/actonlang/acton/pull/2355\n[#2357]: https://github.com/actonlang/acton/pull/2357\n[#2358]: https://github.com/actonlang/acton/pull/2358\n[#2362]: https://github.com/actonlang/acton/pull/2362\n[#2363]: https://github.com/actonlang/acton/pull/2363\n[#2365]: https://github.com/actonlang/acton/pull/2365\n[#2366]: https://github.com/actonlang/acton/pull/2366\n[#2367]: https://github.com/actonlang/acton/pull/2367\n[#2370]: https://github.com/actonlang/acton/pull/2370\n[#2372]: https://github.com/actonlang/acton/pull/2372\n[#2373]: https://github.com/actonlang/acton/pull/2373\n[#2382]: https://github.com/actonlang/acton/pull/2382\n[#2385]: https://github.com/actonlang/acton/pull/2385\n[#2386]: https://github.com/actonlang/acton/pull/2386\n[#2388]: https://github.com/actonlang/acton/pull/2388\n[#2391]: https://github.com/actonlang/acton/pull/2391\n[#2401]: https://github.com/actonlang/acton/pull/2401\n[#2405]: https://github.com/actonlang/acton/pull/2405\n[#2408]: https://github.com/actonlang/acton/pull/2408\n[#2410]: https://github.com/actonlang/acton/pull/2410\n[#2413]: https://github.com/actonlang/acton/pull/2413\n[#2414]: https://github.com/actonlang/acton/pull/2414\n[#2420]: https://github.com/actonlang/acton/pull/2420\n[#2421]: https://github.com/actonlang/acton/pull/2421\n[#2430]: https://github.com/actonlang/acton/pull/2430\n[#2448]: https://github.com/actonlang/acton/pull/2448\n[#2453]: https://github.com/actonlang/acton/pull/2453\n[#2455]: https://github.com/actonlang/acton/pull/2455\n[#2465]: https://github.com/actonlang/acton/pull/2465\n[#2475]: https://github.com/actonlang/acton/pull/2475\n[#2477]: https://github.com/actonlang/acton/pull/2477\n[#2479]: https://github.com/actonlang/acton/pull/2479\n[#2480]: https://github.com/actonlang/acton/pull/2480\n[#2486]: https://github.com/actonlang/acton/pull/2486\n[#2496]: https://github.com/actonlang/acton/pull/2496\n[#2508]: https://github.com/actonlang/acton/pull/2508\n[#2509]: https://github.com/actonlang/acton/pull/2509\n[#2510]: https://github.com/actonlang/acton/pull/2510\n[#2512]: https://github.com/actonlang/acton/pull/2512\n[#2513]: https://github.com/actonlang/acton/pull/2513\n[#2516]: https://github.com/actonlang/acton/pull/2516\n[#2517]: https://github.com/actonlang/acton/pull/2517\n[#2518]: https://github.com/actonlang/acton/pull/2518\n[#2519]: https://github.com/actonlang/acton/pull/2519\n[#2520]: https://github.com/actonlang/acton/pull/2520\n[#2521]: https://github.com/actonlang/acton/pull/2521\n[#2522]: https://github.com/actonlang/acton/pull/2522\n[#2530]: https://github.com/actonlang/acton/pull/2530\n[#2534]: https://github.com/actonlang/acton/pull/2534\n[#2536]: https://github.com/actonlang/acton/pull/2536\n[#2541]: https://github.com/actonlang/acton/pull/2541\n[#2548]: https://github.com/actonlang/acton/pull/2548\n[#2555]: https://github.com/actonlang/acton/pull/2555\n[#2557]: https://github.com/actonlang/acton/pull/2557\n[#2566]: https://github.com/actonlang/acton/pull/2566\n[#2569]: https://github.com/actonlang/acton/pull/2569\n[#2571]: https://github.com/actonlang/acton/pull/2571\n[#2574]: https://github.com/actonlang/acton/pull/2574\n[#2576]: https://github.com/actonlang/acton/pull/2576\n[#2584]: https://github.com/actonlang/acton/pull/2584\n[#2585]: https://github.com/actonlang/acton/pull/2585\n[#2588]: https://github.com/actonlang/acton/pull/2588\n[#2589]: https://github.com/actonlang/acton/pull/2589\n[#2593]: https://github.com/actonlang/acton/pull/2593\n[#2595]: https://github.com/actonlang/acton/pull/2595\n[#2597]: https://github.com/actonlang/acton/pull/2597\n[#2598]: https://github.com/actonlang/acton/pull/2598\n[#2605]: https://github.com/actonlang/acton/pull/2605\n[#2607]: https://github.com/actonlang/acton/pull/2607\n[#2610]: https://github.com/actonlang/acton/pull/2610\n[#2613]: https://github.com/actonlang/acton/pull/2613\n[#2615]: https://github.com/actonlang/acton/pull/2615\n[#2616]: https://github.com/actonlang/acton/pull/2616\n[#2617]: https://github.com/actonlang/acton/pull/2617\n[#2620]: https://github.com/actonlang/acton/pull/2620\n[#2623]: https://github.com/actonlang/acton/pull/2623\n[#2629]: https://github.com/actonlang/acton/pull/2629\n[#2632]: https://github.com/actonlang/acton/pull/2632\n[#2633]: https://github.com/actonlang/acton/pull/2633\n[#2636]: https://github.com/actonlang/acton/pull/2636\n[#2637]: https://github.com/actonlang/acton/pull/2637\n[#2638]: https://github.com/actonlang/acton/pull/2638\n[#2640]: https://github.com/actonlang/acton/pull/2640\n[#2641]: https://github.com/actonlang/acton/pull/2641\n[#2651]: https://github.com/actonlang/acton/pull/2651\n[#2655]: https://github.com/actonlang/acton/pull/2655\n[#2656]: https://github.com/actonlang/acton/pull/2656\n[#2664]: https://github.com/actonlang/acton/pull/2664\n[#2666]: https://github.com/actonlang/acton/pull/2666\n[#2668]: https://github.com/actonlang/acton/pull/2668\n[#2674]: https://github.com/actonlang/acton/pull/2674\n[#2676]: https://github.com/actonlang/acton/pull/2676\n[#2677]: https://github.com/actonlang/acton/pull/2677\n[#2678]: https://github.com/actonlang/acton/pull/2678\n[#2683]: https://github.com/actonlang/acton/pull/2683\n[#2689]: https://github.com/actonlang/acton/pull/2689\n[#2693]: https://github.com/actonlang/acton/pull/2693\n[#2695]: https://github.com/actonlang/acton/pull/2695\n[#2698]: https://github.com/actonlang/acton/pull/2698\n[#2700]: https://github.com/actonlang/acton/pull/2700\n[#2701]: https://github.com/actonlang/acton/pull/2701\n[#2705]: https://github.com/actonlang/acton/pull/2705\n[#2719]: https://github.com/actonlang/acton/pull/2719\n[#2727]: https://github.com/actonlang/acton/pull/2727\n[#2728]: https://github.com/actonlang/acton/pull/2728\n[#2729]: https://github.com/actonlang/acton/pull/2729\n[#2739]: https://github.com/actonlang/acton/pull/2739\n[#2742]: https://github.com/actonlang/acton/pull/2742\n[#2745]: https://github.com/actonlang/acton/pull/2745\n[#2746]: https://github.com/actonlang/acton/pull/2746\n[#2748]: https://github.com/actonlang/acton/pull/2748\n[#2749]: https://github.com/actonlang/acton/pull/2749\n[#2751]: https://github.com/actonlang/acton/pull/2751\n[#2761]: https://github.com/actonlang/acton/pull/2761\n[#2767]: https://github.com/actonlang/acton/pull/2767\n[#2773]: https://github.com/actonlang/acton/pull/2773\n[#2774]: https://github.com/actonlang/acton/pull/2774\n[#2777]: https://github.com/actonlang/acton/pull/2777\n[#2779]: https://github.com/actonlang/acton/pull/2779\n[#2781]: https://github.com/actonlang/acton/pull/2781\n[#2782]: https://github.com/actonlang/acton/pull/2782\n[#2783]: https://github.com/actonlang/acton/pull/2783\n[#2784]: https://github.com/actonlang/acton/pull/2784\n[#2787]: https://github.com/actonlang/acton/pull/2787\n[#2789]: https://github.com/actonlang/acton/pull/2789\n[#2794]: https://github.com/actonlang/acton/pull/2794\n[#2796]: https://github.com/actonlang/acton/pull/2796\n[#2797]: https://github.com/actonlang/acton/pull/2797\n\n\n[0.3.0]: https://github.com/actonlang/acton/releases/tag/v0.3.0\n[0.4.0]: https://github.com/actonlang/acton/compare/v0.3.0...v0.4.0\n[0.4.1]: https://github.com/actonlang/acton/compare/v0.4.0...v0.4.1\n[0.4.2]: https://github.com/actonlang/acton/compare/v0.4.1...v0.4.2\n[0.5.0]: https://github.com/actonlang/acton/compare/v0.4.2...v0.5.0\n[0.5.1]: https://github.com/actonlang/acton/compare/v0.5.0...v0.5.1\n[0.5.2]: https://github.com/actonlang/acton/compare/v0.5.1...v0.5.2\n[0.5.3]: https://github.com/actonlang/acton/compare/v0.5.2...v0.5.3\n[0.6.0]: https://github.com/actonlang/acton/compare/v0.5.3...v0.6.0\n[0.6.1]: https://github.com/actonlang/acton/compare/v0.6.0...v0.6.1\n[0.6.2]: https://github.com/actonlang/acton/compare/v0.6.1...v0.6.2\n[0.6.3]: https://github.com/actonlang/acton/compare/v0.6.2...v0.6.3\n[0.6.4]: https://github.com/actonlang/acton/compare/v0.6.3...v0.6.4\n[0.7.0]: https://github.com/actonlang/acton/compare/v0.6.4...v0.7.0\n[0.7.1]: https://github.com/actonlang/acton/compare/v0.7.0...v0.7.1\n[0.7.2]: https://github.com/actonlang/acton/compare/v0.7.1...v0.7.2\n[0.7.3]: https://github.com/actonlang/acton/compare/v0.7.2...v0.7.3\n[0.7.4]: https://github.com/actonlang/acton/compare/v0.7.3...v0.7.4\n[0.8.0]: https://github.com/actonlang/acton/compare/v0.7.4...v0.8.0\n[0.9.0]: https://github.com/actonlang/acton/compare/v0.8.0...v0.9.0\n[0.9.1]: https://github.com/actonlang/acton/compare/v0.9.0...v0.9.1\n[0.10.0]: https://github.com/actonlang/acton/compare/v0.9.1...v0.10.0\n[0.11.0]: https://github.com/actonlang/acton/compare/v0.10.0...v0.11.0\n[0.11.1]: https://github.com/actonlang/acton/compare/v0.11.0...v0.11.1\n[0.11.2]: https://github.com/actonlang/acton/compare/v0.11.1...v0.11.2\n[0.11.3]: https://github.com/actonlang/acton/compare/v0.11.2...v0.11.3\n[0.11.4]: https://github.com/actonlang/acton/compare/v0.11.3...v0.11.4\n[0.11.5]: https://github.com/actonlang/acton/compare/v0.11.4...v0.11.5\n[0.11.6]: https://github.com/actonlang/acton/compare/v0.11.5...v0.11.6\n[0.11.7]: https://github.com/actonlang/acton/compare/v0.11.6...v0.11.7\n[0.12.0]: https://github.com/actonlang/acton/compare/v0.11.7...v0.12.0\n[0.13.0]: https://github.com/actonlang/acton/compare/v0.12.0...v0.13.0\n[0.13.1]: https://github.com/actonlang/acton/compare/v0.13.0...v0.13.1\n[0.14.0]: https://github.com/actonlang/acton/compare/v0.13.1...v0.14.0\n[0.15.0]: https://github.com/actonlang/acton/compare/v0.14.0...v0.15.0\n[0.16.0]: https://github.com/actonlang/acton/compare/v0.15.0...v0.16.0\n[0.16.1]: https://github.com/actonlang/acton/compare/v0.16.0...v0.16.1\n[0.16.2]: https://github.com/actonlang/acton/compare/v0.16.1...v0.16.2\n[0.16.3]: https://github.com/actonlang/acton/compare/v0.16.2...v0.16.3\n[0.16.4]: https://github.com/actonlang/acton/compare/v0.16.3...v0.16.4\n[0.16.5]: https://github.com/actonlang/acton/compare/v0.16.4...v0.16.5\n[0.16.6]: https://github.com/actonlang/acton/compare/v0.16.5...v0.16.6\n[0.16.7]: https://github.com/actonlang/acton/compare/v0.16.6...v0.16.7\n[0.16.8]: https://github.com/actonlang/acton/compare/v0.16.7...v0.16.8\n[0.16.9]: https://github.com/actonlang/acton/compare/v0.16.8...v0.16.9\n[0.16.10]: https://github.com/actonlang/acton/compare/v0.16.9...v0.16.10\n[0.16.11]: https://github.com/actonlang/acton/compare/v0.16.10...v0.16.11\n[0.16.12]: https://github.com/actonlang/acton/compare/v0.16.11...v0.16.12\n[0.16.13]: https://github.com/actonlang/acton/compare/v0.16.12...v0.16.13\n[0.17.0]: https://github.com/actonlang/acton/compare/v0.16.13...v0.17.0\n[0.17.1]: https://github.com/actonlang/acton/compare/v0.17.0...v0.17.1\n[0.17.2]: https://github.com/actonlang/acton/compare/v0.17.1...v0.17.2\n[0.17.3]: https://github.com/actonlang/acton/compare/v0.17.2...v0.17.3\n[0.17.4]: https://github.com/actonlang/acton/compare/v0.17.3...v0.17.4\n[0.17.5]: https://github.com/actonlang/acton/compare/v0.17.4...v0.17.5\n[0.17.6]: https://github.com/actonlang/acton/compare/v0.17.5...v0.17.6\n[0.17.7]: https://github.com/actonlang/acton/compare/v0.17.6...v0.17.7\n[0.17.8]: https://github.com/actonlang/acton/compare/v0.17.7...v0.17.8\n[0.17.9]: https://github.com/actonlang/acton/compare/v0.17.8...v0.17.9\n[0.17.10]: https://github.com/actonlang/acton/compare/v0.17.9...v0.17.10\n[0.17.11]: https://github.com/actonlang/acton/compare/v0.17.10...v0.17.11\n[0.17.12]: https://github.com/actonlang/acton/compare/v0.17.11...v0.17.12\n[0.18.0]: https://github.com/actonlang/acton/compare/v0.17.12...v0.18.0\n[0.18.1]: https://github.com/actonlang/acton/compare/v0.18.0...v0.18.1\n[0.18.2]: https://github.com/actonlang/acton/compare/v0.18.1...v0.18.2\n[0.19.0]: https://github.com/actonlang/acton/compare/v0.18.2...v0.19.0\n[0.19.1]: https://github.com/actonlang/acton/compare/v0.19.0...v0.19.1\n[0.19.2]: https://github.com/actonlang/acton/compare/v0.19.1...v0.19.2\n[0.19.3]: https://github.com/actonlang/acton/compare/v0.19.2...v0.19.3\n[0.19.4]: https://github.com/actonlang/acton/compare/v0.19.3...v0.19.4\n[0.19.5]: https://github.com/actonlang/acton/compare/v0.19.4...v0.19.5\n[0.20.0]: https://github.com/actonlang/acton/compare/v0.19.5...v0.20.0\n[0.20.1]: https://github.com/actonlang/acton/compare/v0.20.0...v0.20.1\n[0.20.2]: https://github.com/actonlang/acton/compare/v0.20.1...v0.20.2\n[0.20.3]: https://github.com/actonlang/acton/compare/v0.20.2...v0.20.3\n[0.20.4]: https://github.com/actonlang/acton/compare/v0.20.3...v0.20.4\n[0.20.5]: https://github.com/actonlang/acton/compare/v0.20.4...v0.20.5\n[0.20.6]: https://github.com/actonlang/acton/compare/v0.20.5...v0.20.6\n[0.20.7]: https://github.com/actonlang/acton/compare/v0.20.6...v0.20.7\n[0.20.8]: https://github.com/actonlang/acton/compare/v0.20.7...v0.20.8\n[0.20.9]: https://github.com/actonlang/acton/compare/v0.20.8...v0.20.9\n[0.20.10]: https://github.com/actonlang/acton/compare/v0.20.9...v0.20.10\n[0.20.11]: https://github.com/actonlang/acton/compare/v0.20.10...v0.20.11\n[0.20.12]: https://github.com/actonlang/acton/compare/v0.20.11...v0.20.12\n[0.20.13]: https://github.com/actonlang/acton/compare/v0.20.12...v0.20.13\n[0.20.14]: https://github.com/actonlang/acton/compare/v0.20.13...v0.20.14\n[0.20.15]: https://github.com/actonlang/acton/compare/v0.20.14...v0.20.15\n[0.20.16]: https://github.com/actonlang/acton/compare/v0.20.15...v0.20.16\n[0.20.17]: https://github.com/actonlang/acton/compare/v0.20.16...v0.20.17\n[0.20.18]: https://github.com/actonlang/acton/compare/v0.20.17...v0.20.18\n[0.20.19]: https://github.com/actonlang/acton/compare/v0.20.18...v0.20.19\n[0.20.20]: https://github.com/actonlang/acton/compare/v0.20.19...v0.20.20\n[0.20.21]: https://github.com/actonlang/acton/compare/v0.20.20...v0.20.21\n[0.20.22]: https://github.com/actonlang/acton/compare/v0.20.21...v0.20.22\n[0.20.23]: https://github.com/actonlang/acton/compare/v0.20.22...v0.20.23\n[0.20.24]: https://github.com/actonlang/acton/compare/v0.20.23...v0.20.24\n[0.20.25]: https://github.com/actonlang/acton/compare/v0.20.24...v0.20.25\n[0.20.26]: https://github.com/actonlang/acton/compare/v0.20.25...v0.20.26\n[0.20.27]: https://github.com/actonlang/acton/compare/v0.20.26...v0.20.27\n[0.20.28]: https://github.com/actonlang/acton/compare/v0.20.27...v0.20.28\n[0.20.29]: https://github.com/actonlang/acton/compare/v0.20.28...v0.20.29\n[0.20.30]: https://github.com/actonlang/acton/compare/v0.20.29...v0.20.30\n[0.20.31]: https://github.com/actonlang/acton/compare/v0.20.30...v0.20.31\n[0.20.32]: https://github.com/actonlang/acton/compare/v0.20.31...v0.20.32\n[0.20.33]: https://github.com/actonlang/acton/compare/v0.20.32...v0.20.33\n[0.20.34]: https://github.com/actonlang/acton/compare/v0.20.33...v0.20.34\n[0.21.0]: https://github.com/actonlang/acton/compare/v0.20.34...v0.21.0\n[0.21.1]: https://github.com/actonlang/acton/compare/v0.21.0...v0.21.1\n[0.21.2]: https://github.com/actonlang/acton/compare/v0.21.1...v0.21.2\n[0.21.3]: https://github.com/actonlang/acton/compare/v0.21.2...v0.21.3\n[0.22.0]: https://github.com/actonlang/acton/compare/v0.21.3...v0.22.0\n[0.23.0]: https://github.com/actonlang/acton/compare/v0.22.0...v0.23.0\n[0.23.1]: https://github.com/actonlang/acton/compare/v0.23.0...v0.23.1\n[0.23.2]: https://github.com/actonlang/acton/compare/v0.23.1...v0.23.2\n[0.23.3]: https://github.com/actonlang/acton/compare/v0.23.2...v0.23.3\n[0.23.4]: https://github.com/actonlang/acton/compare/v0.23.3...v0.23.4\n[0.23.5]: https://github.com/actonlang/acton/compare/v0.23.4...v0.23.5\n[0.23.6]: https://github.com/actonlang/acton/compare/v0.23.5...v0.23.6\n[0.23.7]: https://github.com/actonlang/acton/compare/v0.23.6...v0.23.7\n[0.23.8]: https://github.com/actonlang/acton/compare/v0.23.7...v0.23.8\n[0.23.9]: https://github.com/actonlang/acton/compare/v0.23.8...v0.23.9\n[0.23.10]: https://github.com/actonlang/acton/compare/v0.23.9...v0.23.10\n[0.23.11]: https://github.com/actonlang/acton/compare/v0.23.10...v0.23.11\n[0.23.12]: https://github.com/actonlang/acton/compare/v0.23.11...v0.23.12\n[0.23.13]: https://github.com/actonlang/acton/compare/v0.23.12...v0.23.13\n[0.23.14]: https://github.com/actonlang/acton/compare/v0.23.13...v0.23.14\n[0.23.15]: https://github.com/actonlang/acton/compare/v0.23.14...v0.23.15\n[0.23.16]: https://github.com/actonlang/acton/compare/v0.23.15...v0.23.16\n[0.23.17]: https://github.com/actonlang/acton/compare/v0.23.16...v0.23.17\n[0.23.18]: https://github.com/actonlang/acton/compare/v0.23.17...v0.23.18\n[0.23.19]: https://github.com/actonlang/acton/compare/v0.23.18...v0.23.19\n[0.23.20]: https://github.com/actonlang/acton/compare/v0.23.19...v0.23.20\n[0.23.21]: https://github.com/actonlang/acton/compare/v0.23.20...v0.23.21\n[0.24.0]: https://github.com/actonlang/acton/compare/v0.23.21...v0.24.0\n[0.24.1]: https://github.com/actonlang/acton/compare/v0.24.0...v0.24.1\n[0.25.0]: https://github.com/actonlang/acton/compare/v0.24.1...v0.25.0\n[0.26.0]: https://github.com/actonlang/acton/compare/v0.25.0...v0.26.0\n[0.27.0]: https://github.com/actonlang/acton/compare/v0.26.0...v0.27.0\n\n[homebrew-acton#7]: https://github.com/actonlang/homebrew-acton/pull/7\n[homebrew-acton#28]: https://github.com/actonlang/homebrew-acton/pull/28\n"
  },
  {
    "path": "CLAUDE.md",
    "content": "# Acton Programming Language - Development Guide\n\nActon is an actor-based programming language with distributed computing capabilities. This guide helps AI assistants understand the codebase structure and development practices.\n\n## Quick Start\n\n### Essential Build Commands\n```bash\nmake                           # Build everything\nmake dist/bin/acton           # Build only the compiler (faster when working on compiler)\nmake test                     # Run all tests\nmake test-compiler            # Run compiler tests only\ndist/bin/acton build          # Build an Acton project\ndist/bin/acton test           # Test an Acton project\n```\n\n### Key Binaries\n- `dist/bin/acton` - The Acton compiler and CLI (project management, testing)\n- `dist/bin/actonc` - Compatibility symlink to `acton`\n\n## Repository Overview\n\n```\nacton/\n├── compiler/          # Haskell-based compiler → [See compiler/CLAUDE.md]\n├── base/             # Standard library & RTS → [See base/CLAUDE.md]\n├── backend/          # Distributed runtime → [See backend/CLAUDE.md]\n├── ecolift/          # Ecosystem lift process → [See ecolift/CLAUDE.md]\n├── test/             # Test suites\n├── docs/             # Documentation (mdBook)\n└── build.zig         # Main build configuration\n```\n\n## Component-Specific Guides\n\nFor detailed information about each component, see:\n- **[compiler/CLAUDE.md](compiler/CLAUDE.md)** - Haskell compiler architecture, compilation pipeline\n- **[base/CLAUDE.md](base/CLAUDE.md)** - Standard library modules, RTS, builtins\n- **[backend/CLAUDE.md](backend/CLAUDE.md)** - Distributed database, actor persistence\n- **[ecolift/CLAUDE.md](ecolift/CLAUDE.md)** - Ecosystem lift process for external repositories\n\n## Language Concepts\n\n### Actor Model\n- Actors are concurrent entities with private state\n- Communication via asynchronous message passing\n- No shared memory between actors\n- Actors can be distributed across nodes\n\n### Type System\n- Static typing with type inference\n- Python-inspired syntax\n- Support for generics\n- Protocol-based polymorphism (similar to interfaces)\n\n## Code Style Guidelines\n\n### Acton Code\n```acton\n# Variables and functions: snake_case\ndef calculate_sum(values: list[int]) -> int:\n    return sum(values)\n\n# Classes and types: PascalCase\nclass DataProcessor:\n    def process(self, data: str) -> None:\n        pass\n\n# Actors: PascalCase\nactor WorkerActor:\n    def handle_request(self, req: Request) -> None:\n        pass\n```\n\n### Haskell Code (Compiler)\n```haskell\n-- Functions: camelCase\nparseExpression :: Parser Expression\n\n-- Types: PascalCase\ndata AstNode = Literal Int | Variable String\n\n-- Explicit type signatures always\n-- 2-space indentation for some functions\n-- \"Whiteboard layout\" for other functions where very deep indent is used to lay out expressions almost like one would when writing beautiful math expressions on a whiteboard\n```\n\n### C Code (RTS/Backend)\n```c\n// Functions: snake_case with module prefix\nint rts_actor_create(rts_actor_t *actor);\n\n// Macros/Constants: UPPER_CASE\n#define MAX_ACTORS 1024\n\n// Structs: snake_case with _t suffix\ntypedef struct actor_state_t {\n    // ...\n} actor_state_t;\n```\n\n## Testing Philosophy\n\n1. **Comprehensive Coverage**: Every feature should have tests\n2. **Snapshot Tests**: For compiler error messages and output\n3. **Performance Tests**: Track performance regressions\n4. **Integration Tests**: Test distributed features\n\n## Common Development Tasks\n\n### Adding a New Builtin Type\n1. Implement C code in `base/builtin/`\n2. Add Acton interface in `base/src/__builtin__.act`\n3. Update compiler type system if needed\n4. Add tests in `test/builtins_auto/`\n\n### Adding a Standard Library Module\n1. Create `.act` file in `base/src/`\n2. Add C extension in `.ext.c` if needed\n3. Update `base/Build.act`\n4. Add module tests\n\n### Modifying the Compiler\n1. Work in `compiler/lib/src/Acton/`\n2. Run `make dist/bin/acton` for quick rebuilds\n3. Add test cases in `compiler/acton/test/`\n4. Update snapshot files if error messages change\n\n## Build System\n\n- Uses Zig build system (`build.zig` files)\n- Integrates Haskell (Stack), C, and Acton compilation\n- Supports cross-compilation\n- Package management via `Build.act` files\n\n## Important Files\n\n- `Makefile` - Top-level build orchestration\n- `build.zig` - Main Zig build configuration\n- `compiler/stack.yaml` - Haskell dependencies\n- `*/Build.act` - Acton package configurations\n\n## Debugging Tips\n\n1. **Compiler Issues**: Enable verbose output with `--debug`\n2. **Runtime Issues**: Use `ACTON_LOG_LEVEL=debug`\n3. **Actor Issues**: Monitor with `actonmon` utility\n4. **Memory Issues**: Built-in GC statistics available\n\n## Contributing Guidelines\n\n1. Follow existing code style in each language\n2. Add tests for new features\n3. Update documentation as needed\n4. Ensure `make test` passes before submitting changes\n5. Keep commits focused and well-described\n\nFor detailed development workflow and release procedures, see [docs/dev.md](docs/dev.md)\n\n## Git Commit Guidelines\n\nWhen making commits:\n- Do not include AI assistant attribution (no \"Generated with Claude\", co-authored-by or similar)\n- Write commit messages as if you wrote the code yourself\n- Focus on what the change does, not how it was created\n- Try hard to use short summary messages (< 50 chars)\n- **NEVER use `git add -A` or `git add .`** - always add files deliberately\n- Be careful not to add generated files (like `package.yaml` which are generated from `.in` templates)\n\n## Release Process\n\n### Creating a New Release\n\n1. **Create release branch**: Use format `release-vX.Y.Z` (note the `v` prefix!)\n   ```bash\n   git checkout -b release-v0.26.0\n   ```\n\n2. **Update version files**:\n   - `version.mk` - Update VERSION (this controls the version for the entire project)\n   - Note: Do NOT manually edit `package.yaml` files - they are generated from `package.yaml.in` templates\n\n3. **Update CHANGELOG.md**:\n   - Add new version section with **today's date** (format: YYYY-MM-DD)\n   - Organize changes under: Added, Changed, Fixed, Documentation, Testing/CI\n   - Add PR links for all referenced PRs at the bottom\n   - Add version comparison link\n\n4. **Create and merge PR**:\n   ```bash\n   git push -u origin release-vX.Y.Z\n   gh pr create --title \"Release vX.Y.Z\"\n   ```\n\n5. **After PR merge**:\n   - Create and push tag: `git tag vX.Y.Z && git push origin vX.Y.Z`\n   - GitHub Actions will automatically create the release\n   - Update Homebrew formula if needed\n\n### Important Release Notes\n- Always use `release-v` prefix for release branches (not just `release-`)\n- Always use today's date in the changelog (not a future or past date)\n- The changelog update process is documented in `docs/dev.md`\n"
  },
  {
    "path": "CONTRIBUTING.md",
    "content": "# Contributing to Acton\n\nHi and thanks for your interest in contributing to Acton! It is possible to\ncontribute in many ways and all contributions are appreciated!\n\n# Questions\n\nUse [GitHub discussions](https://github.com/actonlang/acton/discussions) to ask\nquestions. Search existing questions to avoid duplicates.\n\n# Bug reporting and feature requests\n\nFound a bug? Have an idea for a possible improvement? Open an [issue on Github](https://github.com/actonlang/acton/issues/new)!\n\nPlease search existing issues to avoid creating duplicate issues. Try and write\na good concise subject. Include all relevant information in the issue\ndescription.\n\n# Submitting code\n\nCode contributions are generally welcome. Submit your code as a pull request\n(PR) on the [GitHub project](https://github.com/actonlang/acton).\n\nBefore writing too much code, please open an issue to ensure that your intended\nchanges or fixes are aligned with the overall direction of the project. This can\nsave everyone's time :)\n"
  },
  {
    "path": "Containerfile",
    "content": "FROM debian:13\nMAINTAINER Kristian Larsson <kristian@spritelink.net>\n\nCOPY dist/ /usr/lib/acton/\n\nRUN cd /usr/bin \\\n && ln -sf ../lib/acton/bin/acton \\\n && ln -sf ../lib/acton/bin/actonc \\\n && ln -sf ../lib/acton/bin/actondb \\\n && ln -sf ../lib/acton/bin/runacton\n\nENTRYPOINT [\"/usr/bin/acton\"]\n"
  },
  {
    "path": "Containerfile.deb",
    "content": "FROM debian:13\nMAINTAINER Kristian Larsson <kristian@spritelink.net>\n\nARG TARGETARCH\nCOPY deb/acton_*${TARGETARCH}.deb /tmp/acton.deb\n\nRUN apt-get update \\\n && apt-get install -y --no-install-recommends /tmp/acton.deb \\\n && rm /tmp/acton.deb \\\n && apt-get clean \\\n && rm -rf /var/lib/apt/lists/*\n\nENTRYPOINT [\"/usr/bin/acton\"]\n"
  },
  {
    "path": "LICENSE",
    "content": "Copyright (C) 2019-2021 Data Ductus AB\nCopyright (C) 2019-2021 Deutsche Telekom AG\n\nRedistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:\n\n1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.\n\n2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.\n\n3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission.\n\nTHIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS \"AS IS\" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n"
  },
  {
    "path": "Makefile",
    "content": "include version.mk\nTD := $(CURDIR)\nCHANGELOG_VERSION=$(shell grep '^\\#\\# \\[[0-9]' CHANGELOG.md | sed 's/\\#\\# \\[\\([^]]\\{1,\\}\\)].*/\\1/' | head -n1)\nGIT_VERSION_TAG=$(shell git tag --points-at HEAD 2>/dev/null | grep \"v[0-9]\" | sed -e 's/^v//')\n\nifdef HOME\nZIG_LOCAL_CACHE_DIR ?= $(HOME)/.cache/acton/zig-local-cache\nZIG_GLOBAL_CACHE_DIR ?= $(HOME)/.cache/acton/zig-global-cache\nelse\n# TODO: Windows?\nZIG_LOCAL_CACHE_DIR ?= $(TD)/zig-cache\nZIG_GLOBAL_CACHE_DIR ?= $(TD)/zig-global-cache\nendif\nexport ZIG_LOCAL_CACHE_DIR\nexport ZIG_GLOBAL_CACHE_DIR\n\nACTON=$(TD)/dist/bin/acton\nACTONC=dist/bin/actonc\nZIG_VERSION:=0.15.2\nZIG=$(TD)/dist/zig/zig\nCURL:=curl --fail --location --retry 5 --retry-delay 2 --retry-max-time 120 --retry-all-errors --retry-connrefused\nAR=$(ZIG) ar\nCC=$(ZIG) cc\nCXX=$(ZIG) c++\nexport CC\nexport CXX\nACTON_STACK_CC=$(TD)/compiler/tools/zig-cc.sh\nACTON_STACK_CXX=$(TD)/compiler/tools/zig-cxx.sh\nACTON_STACK_NEEDS_ZIG=\nACTON_ZIG_TARGET=\nSTACK=unset CC && unset CXX && unset CFLAGS && unset CPPFLAGS && unset LDFLAGS && unset ACTON_REAL_LD && stack\n\n# Determine which xargs we have. BSD xargs does not have --no-run-if-empty,\n# rather, it is the default behavior so the argument is superfluous. We check if\n# we are using GNU xargs by trying to run xargs --version and grep for 'GNU', if\n# that returns 0 we are on GNU and will use 'xargs --no-run-if-empty', otherwise\n# we are on BSD and will use 'xargs' straight up.\nXARGS_CHECK := $(shell xargs --version 2>&1 | grep GNU >/dev/null 2>&1; echo $$?)\nifeq ($(XARGS_CHECK),0)\n\tXARGS := xargs --no-run-if-empty\nelse\n\tXARGS := xargs\nendif\n\n# This is the version we will stamp into acton\nBUILD_TIME=$(shell date \"+%Y%m%d.%-H.%-M.%-S\")\nifdef BUILD_RELEASE\nexport VERSION_INFO?=$(VERSION)\nexport DEB_DIST=stable\nexport CONTAINER_TAG?=$(VERSION)\nelse\nexport VERSION_INFO?=$(VERSION).$(BUILD_TIME)\nexport DEB_DIST=tip\nexport CONTAINER_TAG?=tip\nendif\n\nifdef CPEDANTIC\nCPEDANTIC=--cpedantic\nendif\n\nPROFILE ?= 0\nACTON_STACK_BUILD_OPTS := $(STACK_OPTS)\nifeq ($(PROFILE),1)\nACTON_STACK_BUILD_OPTS += --profile --library-profiling --executable-profiling\nACTC_GHC_OPTS += -fprof-auto -fprof-cafs\nendif\n\n# rewrite arm64 to aarch64\nifeq ($(shell uname -m),arm64)\nARCH:=aarch64\nelse\nARCH:=$(shell uname -m)\nendif\n\n# -- Apple Mac OS X ------------------------------------------------------------\nifeq ($(shell uname -s),Darwin)\nOS:=macos\nendif\n\n# -- Linux ---------------------------------------------------------------------\nifeq ($(shell uname -s),Linux)\nOS:=linux\nACTON_ZIG_GLIBC_VERSION ?= 2.31\nexport ACTON_ZIG_GLIBC_VERSION\nACTON_STACK_NEEDS_ZIG=1\nSTACK=CC=\"$(ACTON_STACK_CC)\" CXX=\"$(ACTON_STACK_CXX)\" CFLAGS= CPPFLAGS= LDFLAGS= ACTON_REAL_LD=\"$(ACTON_STACK_CC)\" stack --with-gcc=\"$(ACTON_STACK_CC)\"\nifeq ($(shell uname -m),x86_64)\nACTON_ZIG_TARGET := x86_64-linux-gnu.$(ACTON_ZIG_GLIBC_VERSION)\nelse ifeq ($(shell uname -m),aarch64)\nACTON_ZIG_TARGET := aarch64-linux-gnu.$(ACTON_ZIG_GLIBC_VERSION)\nelse\n$(error \"Unsupported architecture for Linux?\" $(shell uname -m))\nendif\nACTONC_TARGET := --target $(ACTON_ZIG_TARGET)\nendif # -- END: Linux ----------------------------------------------------------\n\n.PHONY: all\nall: version-check\n\t$(MAKE) $(DIST_ZIG)\n\t$(MAKE) distribution\n\n.PHONY: help\nhelp:\n\t@echo \"Available make targets:\"\n\t@echo \"  all     - build everything\"\n\t@echo \"  test    - run the test suite\"\n\t@echo \"  make PROFILE=1 dist/bin/acton - build profiled acton binary\"\n\t@echo \"\"\n\t@echo \"  clean   - /normal/ clean repo\"\n\t@echo \"  clean-all - thorough cleaning\"\n\t@echo \"  clean-downloads - remove downloaded deps, normally never needed?\"\n\n\n.PHONY: version-check\nversion-check:\nifneq ($(VERSION), $(CHANGELOG_VERSION))\n\t$(error Version in version.mk ($(VERSION)) differs from last version in CHANGELOG.md ($(CHANGELOG_VERSION)))\nendif\nifneq ($(GIT_VERSION_TAG),) # if we are on a git tag..\nifneq ($(VERSION),$(GIT_VERSION_TAG)) # ..ensure the git tag is same as version in version.mk\n\t$(error Current git tag ($(GIT_VERSION_TAG)) differs from version in version.mk ($(VERSION)))\nendif\nendif\n\nBUILTIN_HFILES=$(wildcard base/builtin/*.h)\n\nDIST_BINS=$(ACTONC) dist/bin/actondb dist/bin/runacton dist/bin/lsp-server-acton\nDIST_ZIG=dist/zig\nifeq ($(ACTON_STACK_NEEDS_ZIG),1)\nACTON_STACK_PREREQS=$(DIST_ZIG)\nelse\nACTON_STACK_PREREQS=\nendif\n\n.PHONY: test-backend\ntest-backend: $(BACKEND_TESTS)\n\t@echo DISABLED TEST: backend/failure_detector/db_messages_test\n\t./backend/test/actor_ring_tests_local\n\t./backend/test/actor_ring_tests_remote\n\t./backend/test/db_unit_tests\n\t@echo DISABLED test: ./backend/test/queue_unit_tests\n\t./backend/test/skiplist_test\n\n# /compiler ----------------------------------------------\nACTONC_HS=$(wildcard compiler/lib/src/*.hs compiler/lib/src/*/*.hs compiler/acton/*.hs compiler/acton/*/*.hs)\nACTONLSP_HS=$(wildcard compiler/lsp-server/*.hs)\ndist/bin/acton: compiler/lib/package.yaml.in compiler/acton/package.yaml.in compiler/lsp-server/package.yaml.in compiler/stack.yaml $(ACTONC_HS) $(ACTONLSP_HS) version.mk dist/builder $(ACTON_STACK_PREREQS)\n\tmkdir -p dist/bin\n\trm -f dist/bin/actonc\n\tcd compiler && sed 's,^version: BUILD_VERSION,version: \"$(VERSION)\",' < lib/package.yaml.in > lib/package.yaml\n\tcd compiler && $(STACK) build acton lsp-server-acton $(ACTON_STACK_BUILD_OPTS) --ghc-options='-j4 $(ACTC_GHC_OPTS)' --dry-run 2>&1 | grep \"Nothing to build\" || \\\n\t\t(sed 's,^version: BUILD_VERSION,version: \"$(VERSION_INFO)\",' < acton/package.yaml.in > acton/package.yaml \\\n\t\t&& sed 's,^version: BUILD_VERSION,version: \"$(VERSION_INFO)\",' < lsp-server/package.yaml.in > lsp-server/package.yaml \\\n\t\t&& unset CC && unset CXX && unset CFLAGS && unset CPPFLAGS && unset LDFLAGS && unset ACTON_REAL_LD && stack setup \\\n\t\t&& $(STACK) build acton lsp-server-acton $(ACTON_STACK_BUILD_OPTS) --ghc-options='-j4 $(ACTC_GHC_OPTS)')\n\tcd compiler && $(STACK) --local-bin-path=../dist/bin install acton lsp-server-acton $(ACTON_STACK_BUILD_OPTS) --ghc-options='-j4 $(ACTC_GHC_OPTS)'\n\t# Keep actonc as a symlink for compatibility\n\tln -sf acton dist/bin/actonc\n\ndist/bin/actonc: dist/bin/acton\n\t@mkdir -p $(dir $@)\n\tln -sf acton $@\n\ndist/bin/lsp-server-acton: dist/bin/acton\n\t@true\n\n.PHONY: clean-compiler\nclean-compiler:\n\tcd compiler && stack clean >/dev/null 2>&1 || true\n\trm -f dist/bin/acton dist/bin/actonc compiler/package.yaml compiler/acton.cabal \\\n\t\tcompiler/acton/package.yaml compiler/acton/acton.cabal \\\n\t\tcompiler/lib/*.cabal compiler/acton/*.cabal compiler/lsp-server/*.cabal\n\nACTON_LINKAGE_BINS ?= dist/bin/acton dist/bin/lsp-server-acton dist/bin/actondb\nACTON_ALLOWED_NEEDED_RE ?= ^(libc\\.so\\.6|libm\\.so\\.6|libdl\\.so\\.2|libpthread\\.so\\.0|librt\\.so\\.1|libutil\\.so\\.1|ld-linux-x86-64\\.so\\.2|ld-linux-aarch64\\.so\\.1)$$\n.PHONY: ldd\nldd: $(ACTON_LINKAGE_BINS)\nifeq ($(OS),linux)\n\t@for bin in $(ACTON_LINKAGE_BINS); do \\\n\t\techo \"== $$bin ==\"; \\\n\t\tldd \"$$bin\"; \\\n\t\tif command -v readelf >/dev/null 2>&1; then \\\n\t\t\tunexpected_needed=$$(readelf -d \"$$bin\" | sed -n 's/.*Shared library: \\[\\(.*\\)\\].*/\\1/p' | grep -Ev '$(ACTON_ALLOWED_NEEDED_RE)' || true); \\\n\t\t\tif [ -n \"$$unexpected_needed\" ]; then \\\n\t\t\t\techo \"unexpected dynamic libraries:\" >&2; \\\n\t\t\t\techo \"$$unexpected_needed\" >&2; \\\n\t\t\t\texit 1; \\\n\t\t\tfi; \\\n\t\t\tmax_glibc=$$(readelf --version-info \"$$bin\" | grep -o 'GLIBC_[0-9][.0-9]*' | sed 's/GLIBC_//' | sort -Vu | tail -n 1); \\\n\t\t\tif [ -n \"$$max_glibc\" ]; then \\\n\t\t\t\techo \"max GLIBC version required: $$max_glibc\"; \\\n\t\t\t\tif [ \"$$(printf '%s\\n%s\\n' \"$$max_glibc\" \"$(ACTON_ZIG_GLIBC_VERSION)\" | sort -V | tail -n 1)\" != \"$(ACTON_ZIG_GLIBC_VERSION)\" ]; then \\\n\t\t\t\t\techo \"ERROR: $$bin requires GLIBC $$max_glibc, newer than target $(ACTON_ZIG_GLIBC_VERSION)\" >&2; \\\n\t\t\t\t\texit 1; \\\n\t\t\t\tfi; \\\n\t\t\tfi; \\\n\t\tfi; \\\n\tdone\nelse\n\t@echo \"ldd target is only meaningful on Linux\"\nendif\n\n# /deps --------------------------------------------------\nDEPS += dist/deps/mbedtls\nDEPS += dist/deps/libargp\nDEPS += dist/deps/libbsdnt\nDEPS += dist/deps/libgc\nDEPS += dist/deps/libnetstring\nDEPS += dist/deps/pcre2\nDEPS += dist/deps/libprotobuf_c\nDEPS += dist/deps/tlsuv\nDEPS += dist/deps/libutf8proc\nDEPS += dist/deps/libuuid\nDEPS += dist/deps/libuv\nDEPS += dist/deps/libxml2\nDEPS += dist/deps/libyyjson\nDEPS += dist/deps/libsnappy_c\n\n.PHONE: clean-downloads\nclean-downloads:\n\trm -rf deps-download\n\n\n# /deps/libargp --------------------------------------------\nLIBARGP_REF=137154fb257055beb11f3283021d8eccc3c4f470\ndeps-download/$(LIBARGP_REF).tar.gz:\n\tmkdir -p deps-download\n\t$(CURL) -o $@ https://github.com/actonlang/argp-standalone/archive/$(LIBARGP_REF).tar.gz\n\ndist/deps/libargp: deps-download/$(LIBARGP_REF).tar.gz\n\tmkdir -p \"$@\"\n\tcd \"$@\" && tar zx --strip-components=1 -f \"$(TD)/$<\"\n\trm -rf \"$@/testsuite\"\n\ttouch \"$(TD)/$@\"\n\n# /deps/libbsdnt --------------------------------------------\nLIBBSDNT_REF=cf7db3414867b8b4a5561bc9aa94a8050d0225c4\ndeps-download/$(LIBBSDNT_REF).tar.gz:\n\tmkdir -p deps-download\n\t$(CURL) -o $@ https://github.com/actonlang/bsdnt/archive/$(LIBBSDNT_REF).tar.gz\n\ndist/deps/libbsdnt: deps-download/$(LIBBSDNT_REF).tar.gz\n\tmkdir -p \"$@\"\n\tcd \"$@\" && tar zx --strip-components=1 -f \"$(TD)/$<\"\n\ttouch \"$(TD)/$@\"\n\n# /deps/libgc --------------------------------------------\nLIBGC_REF=5ef334ab8f9ef9e23d6b9c99fbd2b621bd52789b\ndeps-download/$(LIBGC_REF).tar.gz:\n\tmkdir -p deps-download\n\t$(CURL) -o $@ https://github.com/actonlang/bdwgc/archive/$(LIBGC_REF).tar.gz\n\ndist/deps/libgc: deps-download/$(LIBGC_REF).tar.gz\n\tmkdir -p \"$@\"\n\tcd \"$@\" && tar zx --strip-components=1 -f \"$(TD)/$<\"\n\trm -rf \"$@/tests\" \"$@/tools\"\n\ttouch \"$(TD)/$@\"\n\n# /deps/libmbedtls --------------------------------------------\nLIBMBEDTLS_REF=c7d83538d3d359b05a9331bb2c9217977b5856ac\ndeps-download/$(LIBMBEDTLS_REF).tar.gz:\n\tmkdir -p deps-download\n\t$(CURL) -o $@ https://github.com/actonlang/mbedtls/archive/$(LIBMBEDTLS_REF).tar.gz\n\ndist/deps/mbedtls: deps-download/$(LIBMBEDTLS_REF).tar.gz\n\tmkdir -p \"$@\"\n\tcd \"$@\" && tar zx --strip-components=1 -f \"$(TD)/$<\"\n\ttouch \"$(TD)/$@\"\n\n# /deps/libprotobuf_c --------------------------------------------\nLIBPROTOBUF_C_REF=faa19a6f6ca393fea01077fb37011a949bc6a3ee\ndeps-download/$(LIBPROTOBUF_C_REF).tar.gz:\n\tmkdir -p deps-download\n\t$(CURL) -o $@ https://github.com/actonlang/protobuf-c/archive/$(LIBPROTOBUF_C_REF).tar.gz\n\ndist/deps/libprotobuf_c: deps-download/$(LIBPROTOBUF_C_REF).tar.gz\n\tmkdir -p \"$@\"\n\tcd \"$@\" && tar zx --strip-components=1 -f \"$(TD)/$<\"\n\ttouch \"$(TD)/$@\"\n\n# /deps/tlsuv ---------------------------------------------\nTLSUV_REF=5af699b033776ec6a21b32c90e7aa7bf08c9929f\ndeps-download/$(TLSUV_REF).tar.gz:\n\tmkdir -p deps-download\n\t$(CURL) -o $@ https://github.com/actonlang/tlsuv/archive/$(TLSUV_REF).tar.gz\n\ndist/deps/tlsuv: deps-download/$(TLSUV_REF).tar.gz dist/deps/libuv dist/deps/mbedtls\n\tmkdir -p \"$@\"\n\tcd \"$@\" && tar zx --strip-components=1 -f \"$(TD)/$<\"\n\ttouch \"$(TD)/$@\"\n\n# /deps/libutf8proc --------------------------------------\nLIBUTF8PROC_REF=a78677e855f0a282e79da6164db4ce1cf0789237\ndeps-download/$(LIBUTF8PROC_REF).tar.gz:\n\tmkdir -p deps-download\n\t$(CURL) -o $@ https://github.com/actonlang/utf8proc/archive/$(LIBUTF8PROC_REF).tar.gz\n\ndist/deps/libutf8proc: deps-download/$(LIBUTF8PROC_REF).tar.gz\n\tmkdir -p \"$@\"\n\tcd \"$@\" && tar zx --strip-components=1 -f \"$(TD)/$<\"\n\ttouch \"$(TD)/$@\"\n\n# /deps/libuuid ------------------------------------------\ndist/deps/libuuid: deps/libuuid\n\tmkdir -p \"$(TD)/$@\"\n\tcp -a \"$</\"* \"$(TD)/$@\"\n\n# /deps/libuv --------------------------------------------\nLIBUV_REF=d760a3f23511ebe7b1935fe1429147d4fca27bb4\ndeps-download/$(LIBUV_REF).tar.gz:\n\tmkdir -p deps-download\n\t$(CURL) -o $@ https://github.com/actonlang/libuv/archive/$(LIBUV_REF).tar.gz\n\ndist/deps/libuv: deps-download/$(LIBUV_REF).tar.gz\n\tmkdir -p \"$@\"\n\tcd \"$@\" && tar zx --strip-components=1 -f \"$(TD)/$<\" \"libuv-$(LIBUV_REF)/build.zig\" \"libuv-$(LIBUV_REF)/include\" \"libuv-$(LIBUV_REF)/src\"\n\ttouch \"$(TD)/$@\"\n\n# /deps/libxml2 ------------------------------------------\nLIBXML2_REF=358ca4e6e34dd2b386aab1fdeb74a641c54940a0\ndeps-download/$(LIBXML2_REF).tar.gz:\n\tmkdir -p deps-download\n\t$(CURL) -o $@ https://github.com/actonlang/libxml2/archive/$(LIBXML2_REF).tar.gz\n\ndist/deps/libxml2: deps-download/$(LIBXML2_REF).tar.gz\n\tmkdir -p \"$@\"\n\tcd \"$@\" && tar zx --strip-components=1 -f \"$(TD)/$<\"\n\trm -rf \"$@/doc\" \"$@/example\" \"$@/fuzz\" \"$@/os400\" \"$@/python\" $@/test*\n\ttouch \"$(TD)/$@\"\n\n# /deps/pcre2 --------------------------------------------\nLIBPCRE2_REF=b82656c5b28658ce1d75489a1b67ba0de5f531ec\ndeps-download/$(LIBPCRE2_REF).tar.gz:\n\tmkdir -p deps-download\n\t$(CURL) -o $@ https://github.com/actonlang/pcre2/archive/$(LIBPCRE2_REF).tar.gz\n\ndist/deps/pcre2: deps-download/$(LIBPCRE2_REF).tar.gz\n\tmkdir -p \"$@\"\n\tcd \"$@\" && tar zx --strip-components=1 -f \"$(TD)/$<\"\n\ttouch \"$(TD)/$@\"\n\n# /deps/libsnappy_c --------------------------------------------\nLIBSNAPPY_C_REF=9d77a3136e271b709eeac4b1db2d27c281b330b2\ndeps-download/$(LIBSNAPPY_C_REF).tar.gz:\n\tmkdir -p deps-download\n\t$(CURL) -o $@ https://github.com/actonlang/snappy/archive/$(LIBSNAPPY_C_REF).tar.gz\n\ndist/deps/libsnappy_c: deps-download/$(LIBSNAPPY_C_REF).tar.gz\n\tmkdir -p \"$@\"\n\tcd \"$@\" && tar zx --strip-components=1 -f \"$(TD)/$<\"\n\ttouch \"$(TD)/$@\"\n\ndist/deps/libnetstring: deps/libnetstring $(DIST_ZIG)\n\tmkdir -p \"$(TD)/$@\"\n\tcp -a \"$</\"* \"$(TD)/$@\"\n\ndist/deps/libyyjson: deps/libyyjson $(DIST_ZIG)\n\tmkdir -p \"$(TD)/$@\"\n\tcp -a \"$</\"* \"$(TD)/$@\"\n\n# top level targets\n.PHONY: test test-builtins test-compiler test-db test-examples test-lang test-regressions test-rts test-stdlib online-tests\ntest: dist/bin/acton\n\tcd compiler && stack test libacton acton:test_acton acton:incremental\n\t$(MAKE) test-stdlib\n\t$(MAKE) -C backend test\n\t$(MAKE) test-rts-db\n\ntest-builtins:\n\tcd compiler && stack test acton --ta '-p \"Builtins\"'\n\ntest-compiler:\n\tcd compiler && stack test libacton\n\tcd compiler && stack test acton --ta '-p \"compiler\"'\n\ntest-compiler-accept:\n\tcd compiler && stack test acton --test-arguments \"--golden-start --golden-reset\"\n\ntest-cross-compile:\n\tcd compiler && stack test acton --ta '-p \"cross-compilation\"'\n\ntest-incremental: dist/bin/actonc\n\tcd compiler && stack test acton:incremental\n\n.PHONY: test-incremental-accept\ntest-incremental-accept: dist/bin/actonc\n\tcd compiler && stack test acton:incremental --ta \"--accept\"\n\n.PHONY: test-rebuild test-rebuild-accept\ntest-rebuild: test-incremental\n\ntest-rebuild-accept: test-incremental-accept\n\ntest-syntaxerrors:\n\tcd compiler && stack test acton --ta '-p \"syntax errors\"'\n\ntest-syntaxerrors-accept:\n\tcd compiler/acton && stack runghc -- test.hs -p \"syntax errors\" --accept\n\ntest-typeerrors:\n\tcd compiler && stack test acton --ta '-p \"type errors\"'\n\ntest-typeerrors-accept:\n\tcd compiler && stack test acton:test_acton --ta '-p \"type errors\" --accept'\n\ntest-db:\n\tcd compiler && stack test acton --ta '-p \"DB\"'\n\ntest-examples:\n\tcd compiler && stack test acton --ta '-p \"Examples\"'\n\ntest-lang:\n\tcd compiler && stack test acton --ta '-p \"Core language\"'\n\ntest-regressions:\n\tcd compiler && stack test acton --ta '-p \"Regression\"'\n\ntest-rts:\n\tcd compiler && stack test acton --ta '-p \"RTS\"'\n\ntest-rts-db:\n\t$(MAKE) -C test\n\ntest-stdlib: dist/bin/acton\n\tcd compiler && stack test acton --ta '-p \"stdlib\"'\n\t$(MAKE) -C test tls-test-server\n\tcd test/stdlib_tests && \"$(ACTON)\" test\n\nonline-tests: dist/bin/actonc\n\tcd compiler && stack test acton:test_acton_online\n\n\n.PHONY: clean clean-all clean-base\nclean: clean-distribution clean-base\n\nclean-all: clean clean-compiler\n\trm -rf $(ZIG_LOCAL_CACHE_DIR)\n\nclean-base:\n\trm -rf base/out\n\n# == DIST ==\n#\n\nBACKEND_FILES = backend/Build.act backend/build.zig backend/build.zig.zon $(wildcard backend/*.c backend/*.h backend/failure_detector/*.c backend/failure_detector/*.h)\nDIST_BACKEND_FILES = $(addprefix dist/,$(BACKEND_FILES)) dist/backend/deps dist/bin/actondb\ndist/backend%: backend/%\n\tmkdir -p \"$(dir $@)\"\n\tcp -a \"$<\" \"$@\"\n\n.PHONY: dist/base\ndist/base: base base/.build base/__root.zig base/acton.zig base/build.zig base/build.zig.zon base/acton.zig dist/bin/actonc $(DEPS) dist/backend/Build.act\n\tmkdir -p \"$@\" \"$@/.build\" \"$@/out\"\n\tcp -a base/__root.zig base/Build.act base/acton.zig base/build.zig base/build.zig.zon base/builtin base/rts base/src dist/base/\n\tcd dist/base && ../bin/actonc build --skip-build && rm -rf .build\n\n# This does a little hack, first copying and then moving the file in place. This\n# is to avoid an error if the executable is currently running. cp tries to open\n# the file and modify it, which the Linux kernel (and perhaps others?) will\n# prevent if the file to be modified is an executable program that is currently\n# running.  We work around it by moving / renaming the file in place instead!\nifeq ($(OS),macos)\n# Workaround for macOS 26.4 CLI tools breaking Zig: point DEVELOPER_DIR to\n# /dev/null to prevent Zig from trying to use them and instead falling back to\n# its own implementation.\n# See https://codeberg.org/ziglang/zig/issues/31658.\ndist/bin/actondb: export DEVELOPER_DIR := $(or $(DEVELOPER_DIR),/dev/null)\nendif\ndist/bin/actondb: $(DIST_ZIG) $(DEPS)\n\t@mkdir -p $(dir $@)\n\tcd dist/backend && \"$(ZIG)\" build -Donly_actondb $(if $(ACTON_ZIG_TARGET),-Dtarget=$(ACTON_ZIG_TARGET)) --prefix \"$(TD)/dist\"\n\ndist/bin/runacton: bin/runacton\n\t@mkdir -p $(dir $@)\n\tcp $< $@.tmp\n\tmv $@.tmp $@\n\ndist/builder: builder/build.zig builder/build.zig.zon\n\t@mkdir -p \"$@\"\n\tcp -a $^ \"$@/\"\n\ndist/deps/%: deps/% $(DEPS)\n\t@mkdir -p \"$(dir $@)\"\n\tcp -a \"$<\" \"$@\"\n\ndist/completion/acton.bash-completion: completion/acton.bash-completion\n\tmkdir -p \"$(dir $@)\"\n\tcp \"$<\" \"$@\"\n\nZIG_TARBALL=zig-$(ARCH)-$(OS)-$(ZIG_VERSION).tar.xz\nZIG_DOWNLOAD_BASE_URL ?=\nifeq ($(strip $(ZIG_DOWNLOAD_BASE_URL)),)\nifeq ($(findstring -dev,$(ZIG_VERSION)),-dev)\nZIG_DOWNLOAD_URL ?= https://ziglang.org/builds/$(ZIG_TARBALL)\nelse\nZIG_DOWNLOAD_URL ?= https://ziglang.org/download/$(ZIG_VERSION)/$(ZIG_TARBALL)\nendif\nelse\nZIG_DOWNLOAD_URL ?= $(patsubst %/,%,$(ZIG_DOWNLOAD_BASE_URL))/$(ZIG_TARBALL)\nendif\n\ndist/zig: deps-download/$(ZIG_TARBALL)\n\tmkdir -p \"$@\"\n\tcd \"$@\" && tar Jx --strip-components=1 -f \"../../$^\"\n\trm -rf \"$@/doc\"\n\tcp -a deps/zig-extras/* \"$@\"\n\n\n# By default Zig downloads come from ziglang.org. CI can set\n# ZIG_DOWNLOAD_BASE_URL=https://github.com/actonlang/zigballs/raw/main\n# to fetch the same tarball filename from our mirror.\ndeps-download/$(ZIG_TARBALL):\n\tmkdir -p deps-download\n\t$(CURL) -o $@ \"$(ZIG_DOWNLOAD_URL)\"\n\n.PHONY: distribution1 distribution clean-distribution\ndistribution1: dist/base $(DIST_BACKEND_FILES) dist/builder $(DIST_BINS) $(DIST_ZIG)\n\t$(MAKE) $(DEPS)\n\ndistribution: distribution1 dist/lldb/acton.py\n\nclean-distribution:\n\trm -rf dist\n\n# == release ==\n# This is where we take our distribution and turn it into a release tar ball\nGNU_TAR := $(shell sed --version 2>&1 | grep GNU >/dev/null 2>&1; echo $$?)\nifeq ($(GNU_TAR),0)\nTAR_TRANSFORM_OPT=--transform 's,^dist,acton,'\nelse\nTAR_TRANSFORM_OPT=-s ,^dist,acton,\nendif\n\n# Do grep to only get a version number. If there's an error, we get an empty\n# string which is better than getting the error message itself.\nACTONC_VERSION=$(shell $(ACTONC) --numeric-version 2>/dev/null | grep -E \"^[0-9.]+$$\")\n.PHONY: acton-$(OS)-$(ARCH)-$(ACTONC_VERSION).tar.xz\nacton-$(OS)-$(ARCH)-$(ACTONC_VERSION).tar.xz:\n\ttar cv $(TAR_TRANSFORM_OPT) --exclude .gitignore dist | xz -z -0 --threads=0 > \"$@\"\n\n.PHONY: release\nrelease: distribution\n\t$(MAKE) acton-$(OS)-$(ARCH)-$(ACTONC_VERSION).tar.xz\n\n# This target is used by the debian packaging\n.PHONY: install\ninstall:\n\tmkdir -p \"$(DESTDIR)/usr/bin\" \"$(DESTDIR)/usr/lib/acton\"\n\tcp -a dist/. \"$(DESTDIR)/usr/lib/acton/\"\n\tcd \"$(DESTDIR)/usr/bin\" && ln -s ../lib/acton/bin/acton\n\tcd \"$(DESTDIR)/usr/bin\" && ln -s ../lib/acton/bin/acton actonc\n\tcd \"$(DESTDIR)/usr/bin\" && ln -s ../lib/acton/bin/actondb\n\tcd \"$(DESTDIR)/usr/bin\" && ln -s ../lib/acton/bin/runacton\n\tcd \"$(DESTDIR)/usr/bin\" && ln -s ../lib/acton/bin/lsp-server-acton\n\ndist/lldb/acton.py: utils/lldb/acton.py\n\t@mkdir -p dist/lldb\n\tcp -a $< $@\n\n.PHONY: debian/changelog\ndebian/changelog: debian/changelog.in CHANGELOG.md\n\tcat $< | sed -e 's/VERSION/$(VERSION_INFO)/' -e 's/DEB_DIST/$(DEB_DIST)/' > $@\n\n.PHONY: debs\ndebs: debian/changelog\n\tdebuild --preserve-envvar VERSION_INFO --preserve-envvar PATH --preserve-envvar STACK_ROOT --preserve-envvar ZIG_DOWNLOAD_BASE_URL --preserve-envvar ACTON_ZIG_GLIBC_VERSION -i -us -uc -nc -b\n\n.PHONY: container-image image image-deb push-image\ncontainer-image: all\n\tpodman build -f Containerfile -t acton:$(CONTAINER_TAG) --volume $(TD):/src:ro .\n\nimage: container-image\n\n# Build container from locally built .deb (useful to mirror CI build path)\nimage-deb: debs\n\tpodman build -f Containerfile.deb -t acton:$(CONTAINER_TAG) --build-arg TARGETARCH=$(ARCH) --volume $(TD):/src:ro .\n\npush-image:\n\t@echo \"Pushing container image to GitHub Container Registry\"\n\tpodman tag acton:$(CONTAINER_TAG) ghcr.io/actonlang/acton:$(CONTAINER_TAG)\n\tpodman push ghcr.io/actonlang/acton:$(CONTAINER_TAG)\n"
  },
  {
    "path": "README.md",
    "content": "# The Acton programming language\n[![Test](https://github.com/actonlang/acton/actions/workflows/test.yml/badge.svg)](https://github.com/actonlang/acton/actions/workflows/test.yml)\n\nActon is a general purpose programming language, designed to be useful for a\nwide range of applications, from desktop applications to embedded and\ndistributed systems. In a first approximation Acton can be described as a\nseamless addition of a powerful new construct to an existing language: Acton\nadds *actors* to *Python*.\n\nActon is a compiled language, offering the speed of C but with a considerably\nsimpler programming model. There is no explicit memory management, instead\nrelying on garbage collection.\n\nActon is statically typed with an expressive type language and type inference.\nType inference means you don't have to explicitly declare types of every\nvariable but that the compiler will *infer* the type and performs its checks\naccordingly. We can have the benefits of type safety without the extra overhead\ninvolved in declaring types.\n\nThe Acton Run Time System (RTS) offers a distributed mode of operation allowing\nmultiple computers to participate in running one logical Acton system. Actors\ncan migrate between compute nodes for load sharing purposes and similar. The RTS\noffers exactly once delivery guarantees. Through checkpointing of actor states\nto a distributed database, the failure of individual compute nodes can be\nrecovered by restoring actor state. Your system can run forever!\n\nNOTE: Acton is in an experimental phase and although much of the syntax has been\nworked out, there may be changes.\n\n\n# Getting started with Acton\n\n## Install Acton\n\nCheck out the [installation guide](https://www.acton-lang.org/install) for more details.\n\n### Debian / Ubuntu\n```sh\nsudo install -m 0755 -d /etc/apt/keyrings\nsudo wget -q -O /etc/apt/keyrings/acton.asc https://apt.acton-lang.io/acton.gpg\nsudo chmod a+r /etc/apt/keyrings/acton.asc\necho \"deb [signed-by=/etc/apt/keyrings/acton.asc arch=amd64] http://apt.acton-lang.io/ stable main\" | sudo tee -a /etc/apt/sources.list.d/acton.list\nsudo apt-get update\nsudo apt-get install -qy acton\n```\n\n### Mac OS X\n```sh\nbrew install actonlang/acton/acton\n```\n\n### Container image\n\nUse the container image to try Acton without installing it locally, or to run\nActon builds in CI:\n\n```sh\ndocker run --rm ghcr.io/actonlang/acton:latest version\ndocker run --rm -v \"$PWD\":/work -w /work ghcr.io/actonlang/acton:latest build\n```\n\nFor day-to-day development, the native APT and Homebrew packages are usually\nmore convenient. For CI, pin a version tag instead of using `latest`.\n\n## Writing and compiling your first Acton program\n\nEdit the program source file, let's call it `helloworld.act`, and enter the\nfollowing code:\n\n``` Acton\nactor main(env):\n    print(\"Hello, world!\")\n    env.exit(0)\n```\n\nCompile the program and run it:\n\n```\n$ acton helloworld.act\n$ ./helloworld\nHello, world!\n```\n\n## And then...?\nCheck out our [learning resources](https://www.acton-lang.org/learn).\n\n\n# Building Acton from source\nSee [building Acton from source](https://www.acton-lang.org/install/from-source).\n\n# Developing Acton\nSee [dev info](docs/dev.md).\n\n# Contributions\n\nFor information about contributing to Acton, see [CONTRIBUTING.md](CONTRIBUTING.md).\n\n## Thanks to all the people who already contributed!\n\n<a href=\"https://github.com/actonlang/acton/graphs/contributors\">\n  <img src=\"https://contributors-img.web.app/image?repo=actonlang/acton\" />\n</a>\n"
  },
  {
    "path": "backend/.gitignore",
    "content": ""
  },
  {
    "path": "backend/Build.act",
    "content": "name = \"actondb\"\nfingerprint = 0xb1be0c7ca3b92d45\n"
  },
  {
    "path": "backend/CLAUDE.md",
    "content": "# Acton Backend - Distributed Runtime & Database\n\nThe backend provides distributed computing capabilities, actor persistence, and fault tolerance for Acton applications.\n\n## Quick Reference\n\n### Directory Structure\n```\nbackend/\n├── actondb.c            # Main database implementation\n├── db.c/h               # Core database operations\n├── txns.c/h             # Transaction management\n├── queue.c/h            # Message queue implementation\n├── hash_ring.c/h        # Consistent hashing for distribution\n├── comm.c/h             # Network communication\n├── failure_detector/    # Node failure detection\n├── build.zig            # Build configuration\n└── test/                # Backend tests\n```\n\n### Build & Test\n```bash\n# Build backend (part of main build)\nmake\n\n# Run backend tests\nmake test-backend\n\n# Build standalone\ncd backend && zig build\n```\n\n## Core Components\n\n### ActonDB (`actondb.c`, `db.c/h`)\n\nActonDB is the distributed database that provides:\n- Actor state persistence\n- Transactional updates\n- Replication across nodes\n- Automatic failover\n\n#### Key Features\n- Write-ahead logging\n- Snapshot isolation\n- Multi-version concurrency control\n- Consistent hashing for data distribution\n\n#### API Overview\n```c\n// Initialize database\nint actondb_init(const char *data_dir);\n\n// Actor state operations\nint actondb_put(actor_id_t actor, void *state, size_t size);\nint actondb_get(actor_id_t actor, void **state, size_t *size);\nint actondb_delete(actor_id_t actor);\n\n// Transaction support\ntxn_t *actondb_txn_begin();\nint actondb_txn_commit(txn_t *txn);\nint actondb_txn_abort(txn_t *txn);\n```\n\n### Transaction System (`txns.c/h`, `txn_state.c/h`)\n\n#### Transaction Lifecycle\n```\nBEGIN → ACTIVE → PREPARING → PREPARED → COMMITTING → COMMITTED\n                     ↓                        ↓\n                  ABORTING ← ← ← ← ← ← ← ABORTED\n```\n\n#### Implementation Details\n- Two-phase commit protocol\n- Distributed transaction coordination\n- Conflict detection and resolution\n- Deadlock prevention\n\n### Message Queue System (`queue.c/h`, `queue_callback.c/h`)\n\n#### Queue Types\n1. **Actor Queues** - Per-actor message queues\n2. **System Queues** - Internal system messages\n3. **Remote Queues** - Inter-node communication\n\n#### Features\n- Lock-free implementation where possible\n- Priority message handling\n- Flow control\n- Back-pressure mechanisms\n\n### Distribution (`hash_ring.c/h`)\n\n#### Consistent Hashing\n- Maps actors to nodes\n- Handles node additions/removals\n- Minimizes data movement\n- Virtual nodes for balance\n\n#### Ring Operations\n```c\n// Add/remove nodes\nhash_ring_add_node(ring, node_id, weight);\nhash_ring_remove_node(ring, node_id);\n\n// Find node for actor\nnode_id_t hash_ring_find_node(ring, actor_id);\n\n// Get replica nodes\nhash_ring_get_replicas(ring, actor_id, replicas, count);\n```\n\n### Communication Layer (`comm.c/h`)\n\n#### Network Protocol\n- Custom binary protocol\n- Message framing\n- Compression support\n- Encryption ready\n\n#### Message Types\n```c\ntypedef enum {\n    MSG_ACTOR_CALL,\n    MSG_ACTOR_CAST,\n    MSG_STATE_SYNC,\n    MSG_HEARTBEAT,\n    MSG_NODE_JOIN,\n    MSG_NODE_LEAVE\n} message_type_t;\n```\n\n### Failure Detection (`failure_detector/`)\n\n#### Components\n- **fd.c/h** - Main failure detector\n- **cells.c/h** - Distributed state cells\n- **vector_clock.c/h** - Logical time tracking\n\n#### Detection Algorithm\n- Adaptive timeout based on network conditions\n- Gossip protocol for state dissemination\n- Vector clocks for causality tracking\n- Split-brain prevention\n\n## Working with the Backend\n\n### Adding New Database Operations\n\n1. **Define Operation** in `db.h`:\n```c\nint actondb_new_operation(/* parameters */);\n```\n\n2. **Implement** in `db.c`:\n```c\nint actondb_new_operation(/* parameters */) {\n    // Validate inputs\n    // Begin transaction if needed\n    // Perform operation\n    // Handle errors\n    // Return result\n}\n```\n\n3. **Add Tests** in `test/db_unit_tests.c`\n\n### Implementing New Message Types\n\n1. **Define Message** in `comm.h`:\n```c\ntypedef struct {\n    message_header_t header;\n    // Custom fields\n} my_message_t;\n```\n\n2. **Add Handler** in `comm.c`:\n```c\nstatic void handle_my_message(connection_t *conn, \n                              my_message_t *msg) {\n    // Process message\n    // Send response if needed\n}\n```\n\n3. **Register Handler**:\n```c\nmessage_handlers[MSG_MY_TYPE] = handle_my_message;\n```\n\n### Transaction Implementation\n\n```c\n// Example transactional operation\nint perform_atomic_update(actor_id_t actor1, actor_id_t actor2) {\n    txn_t *txn = actondb_txn_begin();\n    if (!txn) return -1;\n    \n    // Read states\n    void *state1, *state2;\n    if (txn_get(txn, actor1, &state1) < 0) goto abort;\n    if (txn_get(txn, actor2, &state2) < 0) goto abort;\n    \n    // Modify states\n    modify_state(state1);\n    modify_state(state2);\n    \n    // Write back\n    if (txn_put(txn, actor1, state1) < 0) goto abort;\n    if (txn_put(txn, actor2, state2) < 0) goto abort;\n    \n    // Commit\n    return actondb_txn_commit(txn);\n    \nabort:\n    actondb_txn_abort(txn);\n    return -1;\n}\n```\n\n## Performance Optimization\n\n### Database Performance\n- Use batch operations when possible\n- Minimize transaction scope\n- Leverage indexes appropriately\n- Monitor lock contention\n\n### Network Performance\n- Batch messages when possible\n- Use compression for large payloads\n- Connection pooling\n- Async I/O throughout\n\n### Memory Management\n- Pool allocators for hot paths\n- Minimize allocations in critical sections\n- Use stack allocation where appropriate\n- Profile memory usage regularly\n\n## Debugging & Monitoring\n\n### Logging\n```c\n// Log levels\nLOG_ERROR(\"Failed to connect: %s\", error_msg);\nLOG_WARN(\"Retry attempt %d\", retry_count);\nLOG_INFO(\"Node %s joined\", node_id);\nLOG_DEBUG(\"Message received: %d bytes\", size);\n```\n\n### Metrics\n- Transaction throughput\n- Message queue depths\n- Network latency\n- Node health status\n\n### Debug Tools\n```bash\n# Enable debug logging\nexport ACTON_LOG_LEVEL=debug\n\n# Trace messages\nexport ACTON_TRACE_MESSAGES=1\n\n# Database diagnostics\nactondb-debug --stats\n```\n\n## Testing Strategy\n\n### Unit Tests\n- Test individual components\n- Mock external dependencies\n- Focus on edge cases\n\n### Integration Tests\n- Multi-node scenarios\n- Failure injection\n- Performance benchmarks\n\n### Stress Tests\n- High message rates\n- Large state sizes\n- Network partitions\n- Node failures\n\n## Security Considerations\n\n1. **Authentication**\n   - Node-to-node authentication\n   - Message signing\n   - Certificate management\n\n2. **Encryption**\n   - TLS for network communication\n   - At-rest encryption for database\n\n3. **Access Control**\n   - Actor-level permissions\n   - Operation authorization\n\n## Common Issues & Solutions\n\n### Issue: High Message Latency\n- Check network conditions\n- Verify queue depths\n- Look for lock contention\n- Consider batching\n\n### Issue: Transaction Conflicts\n- Reduce transaction scope\n- Add retry logic\n- Consider optimistic locking\n- Review access patterns\n\n### Issue: Memory Growth\n- Check for queue buildup\n- Verify state cleanup\n- Look for memory leaks\n- Monitor GC activity\n\n## Future Considerations\n\nThe backend is designed to support:\n- Geographic distribution\n- Multi-datacenter deployment\n- Elastic scaling\n- Advanced replication strategies"
  },
  {
    "path": "backend/actondb.c",
    "content": "/*\n * Copyright (C) 2019-2021 Deutsche Telekom AG\n *\n * Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:\n *\n * 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.\n *\n * 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.\n *\n * 3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission.\n *\n * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS \"AS IS\" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n */\n\n/*\n * server.c\n *\n *      Author: aagapi\n */\n\n// ActonDB Server:\n\n#include \"db.h\"\n#include \"queue_callback.h\"\n#include \"failure_detector/db_queries.h\"\n#include \"failure_detector/fd.h\"\n#include \"comm.h\"\n#include \"fastrand.h\"\n#include \"log.h\"\n#include \"netstring.h\"\n#include \"yyjson.h\"\n\n#include <stdio.h>\n#include <unistd.h>\n#include <stdlib.h>\n#include <string.h>\n#include <netdb.h>\n#include <sys/types.h>\n#include <sys/socket.h>\n#include <netinet/in.h>\n#include <arpa/inet.h>\n#include <sys/time.h>\n#include <sys/select.h>\n#include <fcntl.h>\n#include <errno.h>\n#include <argp.h>\n#include <string.h>\n#include <limits.h>\n#include <signal.h>\n\n#define LOGPFX \"#ActDB# \"\n\npid_t pid;\n\n#define SERVER_BUFSIZE 128 * 1024 // (1024 * 1024)\n#define PRINT_BUFSIZE 128 * 1024\n\n#define UPDATE_LC_ON_GOSSIP\n#define DO_HIERARCHICAL_CONNECT 0\n\nchar in_buf[SERVER_BUFSIZE];\nchar out_buf[SERVER_BUFSIZE];\n\nint no_state_cols = 2;                  // 1;   // 4;\nint no_state_primary_keys = 1;\nint min_state_clustering_keys = 1;      // 0;   // 1;\nint no_state_index_keys = 0;            // 1;\n\nint no_queue_cols = 1;                  // 2;\n\n#define ACTORS_TABLE    (WORD)0\n#define MSGS_TABLE      (WORD)1\n#define MSG_QUEUE       (WORD)2\n\n//WORD state_table_key = (WORD) 0;\n//WORD queue_table_key = (WORD) 1;\n\n\nvoid error(char *msg) {\n  log_error(msg);\n}\n\n#define SERVER_VERBOSITY 1\n\n#define DEFAULT_DATA_PORT 32000\n#define DEFAULT_GOSSIP_PORT 32001\n\n#define RANDOM_NONCES\nint64_t requests = 0;\n\nint64_t _get_nonce(unsigned int * fastrandstate)\n{\n#ifdef RANDOM_NONCES\n    unsigned int randno1, randno2;\n    int64_t randlong;\n    FASTRAND(fastrandstate, randno1);\n    FASTRAND(fastrandstate, randno2);\n    return ((int64_t) randno1 << 32) | ((int64_t) randno2 & 0xFFFFFFFFL);\n#else\n    return ++requests;\n#endif\n}\n\n#define PROPOSAL_STATUS_NON_EXISTING 0\n#define PROPOSAL_STATUS_ACTIVE 1\n#define PROPOSAL_STATUS_ACCEPTED 2\n#define PROPOSAL_STATUS_AMMENDED 3\n#define PROPOSAL_STATUS_REJECTED 4\n\n#define AGREED_PEERS 0\n#define LOCAL_PEERS 1\n#define CONNECTED_PEERS 2\n#define CONNECTED_CLIENTS 3\n\ntypedef struct membership\n{\n    skiplist_t * connected_peers;\n    skiplist_t * local_peers;\n    skiplist_t * agreed_peers;\n    skiplist_t * stable_peers;\n    skiplist_t * connected_clients;\n    skiplist_t * connected_client_sockets;\n\n    vector_clock * view_id;\n\n    int my_id;\n\n    skiplist_t * outstanding_proposal;\n    skiplist_t * outstanding_proposal_clients;\n    int64_t outstanding_proposal_nonce;\n    vector_clock * outstanding_view_id;\n    int outstanding_proposal_acks;\n    short proposal_status;\n    skiplist_t * merged_responses;\n    skiplist_t * merged_client_responses;\n} membership;\n\nint add_remote_server_to_list(remote_server * rs, skiplist_t * peer_list, unsigned int * seedptr);\nint add_client_to_membership(struct sockaddr_in addr, int sockfd, char *hostname, int portno, skiplist_t * clients, unsigned int * seedptr);\nint propose_local_membership(membership * m, vector_clock * my_vc, membership_agreement_msg ** amr, int64_t nonce, unsigned int * fastrandstate);\n\nmembership * get_membership(int my_id)\n{\n    membership * m = (membership *) malloc(sizeof(membership));\n\n    m->connected_peers = create_skiplist(&sockaddr_cmp);\n    m->local_peers = create_skiplist(&sockaddr_cmp);\n    m->agreed_peers = create_skiplist(&sockaddr_cmp);\n    m->stable_peers = create_skiplist(&sockaddr_cmp);\n    m->connected_clients = create_skiplist(&sockaddr_cmp);\n    m->view_id = NULL;\n    m->my_id = my_id;\n\n    m->outstanding_proposal = create_skiplist(&sockaddr_cmp);\n    m->outstanding_proposal_clients = create_skiplist(&sockaddr_cmp);\n    m->outstanding_view_id = NULL;\n    m->outstanding_proposal_acks = 0;\n    m->outstanding_proposal_nonce = -1;\n    m->proposal_status = PROPOSAL_STATUS_NON_EXISTING;\n    m->merged_responses = create_skiplist(&sockaddr_cmp);\n    m->merged_client_responses = create_skiplist(&sockaddr_cmp);\n\n    return m;\n}\n\nvoid free_membership(membership * m)\n{\n    skiplist_free(m->connected_peers);\n    skiplist_free(m->local_peers);\n    skiplist_free(m->agreed_peers);\n    skiplist_free(m->stable_peers);\n    skiplist_free(m->connected_clients);\n\n    if(m->view_id != NULL)\n        free_vc(m->view_id);\n\n    if(m->outstanding_proposal != NULL)\n        skiplist_free(m->outstanding_proposal);\n\n    if(m->outstanding_proposal_clients != NULL)\n        skiplist_free(m->outstanding_proposal_clients);\n\n    if(m->outstanding_view_id != NULL)\n        free_vc(m->outstanding_view_id);\n\n    if(m->merged_responses != NULL)\n        skiplist_free(m->merged_responses);\n\n    if(m->merged_client_responses != NULL)\n        skiplist_free(m->merged_client_responses);\n\n    free(m);\n}\n\ntypedef struct client_descriptor\n{\n    struct sockaddr_in addr;\n    int sockfd;\n    char id[256];\n} client_descriptor;\n\nclient_descriptor * get_client_descriptor(struct sockaddr_in addr, int sockfd, char *hostname, int portno)\n{\n    client_descriptor * cd = (client_descriptor *) malloc(sizeof(struct client_descriptor));\n    memcpy(&(cd->addr), &addr, sizeof(struct sockaddr_in));\n    cd->sockfd = sockfd;\n    snprintf((char *) &cd->id, 256, \"%s:%d\", hostname, portno);\n    return cd;\n}\n\nvoid free_client_descriptor(client_descriptor * cd)\n{\n    free(cd);\n}\n\nint add_client_to_membership(struct sockaddr_in addr, int sockfd, char *hostname, int portno, skiplist_t * clients, unsigned int * seedptr)\n{\n    client_descriptor * cd = get_client_descriptor(addr, sockfd, hostname, portno);\n\n    if(skiplist_search(clients, &(cd->addr)) != NULL)\n    {\n        log_info(\"Client address %s:%d was already added to membership!\", hostname, portno);\n        free_client_descriptor(cd);\n        return -1;\n    }\n\n    int status = skiplist_insert(clients, &(cd->addr), cd, seedptr);\n\n    if(status != 0)\n    {\n        log_error(\"Error adding client address %s:%d to membership!\", hostname, portno);\n        free_client_descriptor(cd);\n        return -2;\n    }\n\n    return 0;\n}\n\nclient_descriptor * lookup_client_by_fd(int fd, skiplist_t * clients)\n{\n    for(snode_t * crt = HEAD(clients); crt!=NULL; crt = NEXT(crt))\n    {\n        client_descriptor * crt_cd = (client_descriptor *) crt->value;\n        if(crt_cd->sockfd == fd)\n            return crt_cd;\n    }\n    return NULL;\n}\n\nint create_state_schema(db_t * db, unsigned int * fastrandstate)\n{\n    int primary_key_idx = 0;\n    int clustering_key_idxs[2];\n    clustering_key_idxs[0]=1;\n    clustering_key_idxs[1]=2;\n    int index_key_idx=3;\n\n    int * col_types = NULL;\n\n    db_schema_t* db_schema = db_create_schema(col_types, no_state_cols + 1, &primary_key_idx, no_state_primary_keys, clustering_key_idxs, min_state_clustering_keys, &index_key_idx, no_state_index_keys);\n\n    assert(db_schema != NULL && \"Schema creation failed\");\n\n    // Create table:\n\n    int ret = db_create_table(ACTORS_TABLE, db_schema, db, fastrandstate);\n\n    log_info(\"%s - %s (%d)\", \"Create ACTORS_TABLE\", ret==0?\"OK\":\"FAILED\", ret);\n\n    ret = db_create_table(MSGS_TABLE, db_schema, db, fastrandstate);\n\n    log_info(\"%s - %s (%d)\", \"Create MSGS_TABLE\", ret==0?\"OK\":\"FAILED\", ret);\n\n    return ret;\n}\n\nint create_queue_schema(db_t * db, unsigned int * fastrandstate)\n{\n    int * col_types = (int *) malloc((no_queue_cols + 1) * sizeof(int));\n    col_types[0] = DB_TYPE_INT64;\n\n    col_types[no_queue_cols] = DB_TYPE_BLOB; // Include blob\n\n    int ret = create_queue_table(MSG_QUEUE, no_queue_cols + 1, col_types, db,  fastrandstate);\n\n    log_info(\"%s - %s (%d)\", \"Create MSG_QUEUE table\", ret==0?\"OK\":\"FAILED\", ret);\n\n    return ret;\n}\n\n\n\ndb_schema_t * get_schema(db_t * db, WORD table_key)\n{\n    snode_t * node = skiplist_search(db->tables, table_key);\n\n    if(node == NULL)\n        return NULL;\n\n    db_table_t * table = (db_table_t *) (node->value);\n\n    return table->schema;\n}\n\n// Write message handlers:\n\nint get_ack_packet(int status, write_query * q,\n                    void ** snd_buf, unsigned * snd_msg_len, vector_clock * vc)\n{\n    ack_message * ack = init_ack_message(get_cell_address(q->cell), status, q->txnid, q->nonce);\n\n#if (VERBOSE_RPC > 0)\n    char print_buff[1024];\n    to_string_ack_message(ack, (char *) print_buff);\n    log_info(\"Sending ack message: %s\", print_buff);\n#endif\n\n    int ret = serialize_ack_message(ack, snd_buf, snd_msg_len, vc);\n\n    free_ack_message(ack);\n\n    return ret;\n}\n\nint get_gossip_ack_packet(int status, gossip_listen_message * q,\n                    void ** snd_buf, unsigned * snd_msg_len, vector_clock * vc)\n{\n    ack_message * ack = init_ack_message(NULL, status, NULL, q->nonce);\n\n#if (VERBOSE_RPC > 0)\n    char print_buff[1024];\n    to_string_ack_message(ack, (char *) print_buff);\n    log_info(\"Sending ack message: %s\", print_buff);\n#endif\n\n    int ret = serialize_ack_message(ack, snd_buf, snd_msg_len, vc);\n\n    free_ack_message(ack);\n\n    return ret;\n}\n\nint handle_write_query(write_query * wq, db_t * db, unsigned int * fastrandstate)\n{\n    int total_cols = wq->cell->no_keys + wq->cell->no_columns;\n    int total_cols_plus_blob = total_cols + ((wq->cell->last_blob_size > 0)?(1):(0));\n\n    db_schema_t * schema = get_schema(db, (WORD) wq->cell->table_key);\n\n    int no_clustering_keys = wq->cell->no_keys - schema->no_primary_keys;\n\n    switch(wq->msg_type)\n    {\n        case RPC_TYPE_WRITE:\n        {\n            assert(wq->cell->no_columns > 0 || (wq->cell->last_blob != NULL && wq->cell->last_blob_size > 0));\n\n            WORD * column_values = (WORD *) malloc(total_cols_plus_blob * sizeof(WORD));\n\n            int j = 0;\n            for(;j<wq->cell->no_keys;j++)\n                column_values[j] = (WORD) wq->cell->keys[j];\n            for(;j<total_cols;j++)\n                column_values[j] = (WORD) wq->cell->columns[j-wq->cell->no_keys];\n\n            if(wq->cell->last_blob_size > 0)\n            {\n                assert(total_cols_plus_blob == total_cols + 1);\n                column_values[total_cols] = malloc(wq->cell->last_blob_size);\n                memcpy(column_values[total_cols], wq->cell->last_blob, wq->cell->last_blob_size);\n            }\n\n\n            if(wq->txnid == NULL) // Write out of txn\n                return db_insert_transactional(column_values, total_cols_plus_blob, no_clustering_keys, wq->cell->last_blob_size, wq->cell->version, (WORD) wq->cell->table_key, db, fastrandstate);\n            else // Write in txn\n                return db_insert_in_txn(column_values, total_cols_plus_blob, schema->no_primary_keys, no_clustering_keys, wq->cell->last_blob_size, (WORD) wq->cell->table_key, wq->txnid, db, fastrandstate);\n        }\n        case RPC_TYPE_DELETE:\n        {\n            if(wq->txnid == NULL) // Delete out of txn\n            {\n                if(wq->cell->no_keys == schema->no_primary_keys)\n                    return db_delete_row_transactional((WORD *) wq->cell->keys, wq->cell->version, (WORD) wq->cell->table_key, db, fastrandstate);\n                else\n                    assert(0); // db_delete_cell not implemented yet\n            }\n            else\n            {\n                if(wq->cell->no_keys == schema->no_primary_keys)\n                    return db_delete_row_in_txn((WORD *) wq->cell->keys, wq->cell->no_keys, (WORD) wq->cell->table_key, wq->txnid, db, fastrandstate);\n                else\n                    return db_delete_cell_in_txn((WORD *) wq->cell->keys, schema->no_primary_keys, no_clustering_keys, (WORD) wq->cell->table_key, wq->txnid, db, fastrandstate);\n                // TO DO: To support db_delete_by_index_in_txn (in RPCs and backend)\n            }\n        }\n    }\n\n    return 1;\n}\n\nvector_clock * get_empty_vc()\n{\n    return init_vc(0, NULL, NULL, 0);\n}\n\nvector_clock * get_local_vc(int my_id)\n{\n    int node_ids[] = {my_id};\n    int64_t counters[] = {0};\n    return init_vc(1, node_ids, counters, 0);\n}\n\n// Read (regular and range) message handlers:\n\nint count_cells(db_row_t* result, int * max_depth)\n{\n    if(result == NULL)\n        return 0;\n\n    if(result->cells == NULL || result->cells->no_items == 0)\n        return 1;\n\n    *max_depth = *max_depth + 1;\n\n    int no_cells = 0;\n    for(snode_t * crt_cell = HEAD(result->cells); crt_cell != NULL; crt_cell = NEXT(crt_cell))\n    {\n        db_row_t * child = (db_row_t*) crt_cell->value;\n        no_cells += count_cells(child, max_depth);\n    }\n\n    return no_cells;\n}\n\ncell * serialize_cells(db_row_t* result, cell * cells, int64_t table_key, int64_t * key_path, int depth, int no_schema_keys)\n{\n    if(result == NULL)\n        return cells;\n\n    key_path[depth-1] = (int64_t) result->key;\n\n    if(result->cells == NULL || result->cells->no_items == 0)\n    {\n        assert(result->no_columns > 0);\n        assert(depth >= no_schema_keys);\n\n        if(result->last_blob_size <= 0)\n            copy_cell(cells, table_key,\n                    key_path, depth,\n                    (int64_t *) result->column_array, result->no_columns,\n                    NULL, 0,\n                    result->version);\n        else\n            copy_cell(cells, table_key,\n                    key_path, depth,\n                    (int64_t *) result->column_array, result->no_columns - 1,\n                    result->column_array[result->no_columns - 1], result->last_blob_size,\n                    result->version);\n\n        return cells + 1;\n    }\n\n//  log_debug(\"serialize_cells:\");\n//  print_long_row(result);\n\n    cell * cells_ptr = cells;\n    for(snode_t * crt_cell = HEAD(result->cells); crt_cell != NULL; crt_cell = NEXT(crt_cell))\n    {\n        db_row_t * child = (db_row_t*) crt_cell->value;\n        cells_ptr = serialize_cells(child, cells_ptr, table_key, key_path, depth+1, no_schema_keys);\n    }\n\n    return cells_ptr;\n}\n\nint get_read_response_packet(db_row_t* result, read_query * q, db_schema_t * schema, void ** snd_buf, unsigned * snd_msg_len, vector_clock * vc)\n{\n    range_read_response_message * m = NULL;\n\n    if(result == NULL)\n    {\n        m = init_range_read_response_message(NULL, 0, q->txnid, q->nonce);\n    }\n    else if(result->cells == NULL || result->cells->no_items == 0)\n    // Return a single cell read result\n    {\n        assert(result->no_columns > 0);\n        assert(result->no_columns >= schema->min_no_cols);\n        assert(q->cell_address->keys[q->cell_address->no_keys - 1] == (int64_t) result->key);\n\n        cell * c = NULL;\n        if(result->last_blob_size <= 0)\n        {\n            c = init_cell(q->cell_address->table_key,\n                            (int64_t *) &result->key, 1, // Result cell always points to last (inner-most) key of the query\n                            (int64_t *) result->column_array, result->no_columns,\n                            NULL, 0,\n                            result->version);\n        }\n        else\n        {\n            c = init_cell(q->cell_address->table_key,\n                            (int64_t *) &result->key, 1, // Result cell always points to last (inner-most) key of the query\n                            (int64_t *) result->column_array, result->no_columns - 1,\n                            result->column_array[result->no_columns - 1], result->last_blob_size,\n                            result->version);\n        }\n\n        m = init_range_read_response_message(c, 1, q->txnid, q->nonce);\n    }\n    else\n    // Return a multi-cell read result; traverse db_row downwards and get all child cells recursively:\n    {\n        int schema_keys = schema->no_primary_keys + schema->min_no_clustering_keys; // We only use this schema data for sanity checking of read back results\n//      int no_keys = schema_keys - q->cell_address->no_keys + 1;\n\n        int max_depth = 1;\n\n        int no_results = count_cells(result, &max_depth);\n\n        cell * cells = malloc(no_results * sizeof(cell));\n\n        int64_t * key_path = (int64_t *) malloc(max_depth * sizeof(int64_t));\n\n        cell * last_cell_ptr = serialize_cells(result, cells, q->cell_address->table_key, key_path, 1, schema_keys); // no_keys\n\n        assert(last_cell_ptr - cells == no_results);\n\n        m = init_range_read_response_message(cells, no_results, q->txnid, q->nonce);\n    }\n\n#if (VERBOSE_RPC > 0)\n    char print_buff[PRINT_BUFSIZE];\n    to_string_range_read_response_message(m, (char *) print_buff);\n    log_info(\"Sending range read response message: %s\", print_buff);\n#endif\n\n    int ret = serialize_range_read_response_message(m, snd_buf, snd_msg_len, vc);\n\n    free_range_read_response_message(m);\n\n    return ret;\n}\n\ndb_row_t* handle_read_query(read_query * q, db_schema_t ** schema, db_t * db, unsigned int * fastrandstate)\n{\n    int i=0;\n\n    *schema = get_schema(db, (WORD) q->cell_address->table_key);\n    int no_clustering_keys = q->cell_address->no_keys - (*schema)->no_primary_keys;\n\n    if(no_clustering_keys == 0)\n    {\n        return db_search((WORD *) q->cell_address->keys, (WORD) q->cell_address->table_key, db);\n    }\n    else\n    {\n        return db_search_clustering((WORD *) q->cell_address->keys,\n                                    (WORD *) (q->cell_address->keys + (*schema)->no_primary_keys),\n                                    no_clustering_keys, (WORD) q->cell_address->table_key, db);\n    }\n}\n\nremote_server * lookup_client_by_client_socket_addr(struct sockaddr_in * client_socket_addr, skiplist_t * clients)\n{\n    for(snode_t * crt = HEAD(clients); crt!=NULL; crt = NEXT(crt))\n    {\n        remote_server * rs = (remote_server *) crt->value;\n        if(sockaddr_cmp((WORD) client_socket_addr, (WORD) (&(rs->client_socket_addr))) == 0)\n            return rs;\n    }\n    return NULL;\n}\n\nint handle_gossip_listen_message(gossip_listen_message * msg, client_descriptor * cd,\n        membership * m, vector_clock * my_lc, membership_agreement_msg ** amr, unsigned int * fastrandstate)\n{\n    struct sockaddr_in dummy_serveraddr;\n    remote_server * rs = get_remote_server(msg->node_description->hostname, msg->node_description->portno, dummy_serveraddr, cd->addr, DUMMY_FD, 0, 1);\n    rs->status = NODE_LIVE;\n\n    log_info(\"Adding client %s:%d/%d/%d to membership.\", rs->hostname, msg->node_description->portno, msg->node_description->node_id, rs->portno);\n\n    int status = add_remote_server_to_list(rs, m->connected_clients, fastrandstate);\n\n    return propose_local_membership(m, my_lc, amr, msg->nonce, fastrandstate);\n}\n\nint get_range_read_response_packet(snode_t* start_row, snode_t* end_row, int no_results, range_read_query * q,\n                                    db_schema_t * schema, void ** snd_buf, unsigned * snd_msg_len,\n                                    vector_clock * vc)\n{\n    int schema_keys = schema->no_primary_keys + schema->min_no_clustering_keys; // We only use this schema data for sanity checking of read back results\n//  int no_keys = schema_keys - q->start_cell_address->no_keys + 1;\n    range_read_response_message * m = NULL;\n\n    if(no_results == 0)\n    {\n        m = init_range_read_response_message(NULL, 0, q->txnid, q->nonce);\n    }\n    else\n    {\n        assert(start_row != NULL);\n\n        int max_range_depth = 0;\n        int no_cells = 0, i=0;\n        for(snode_t * crt_row = start_row; i<no_results; crt_row = NEXT(crt_row), i++)\n        {\n            db_row_t* result = (db_row_t* ) crt_row->value;\n//          print_long_row(result);\n            int max_depth = 1;\n            no_cells += count_cells(result, &max_depth);\n            max_range_depth = (max_depth > max_range_depth)?max_depth:max_range_depth;\n        }\n\n        cell * cells = malloc(no_cells * sizeof(cell));\n\n        int64_t * key_path = (int64_t *) malloc(max_range_depth * sizeof(int64_t));\n\n        i=0;\n        cell * last_cell_ptr = cells;\n        for(snode_t * crt_row = start_row; i<no_results; crt_row = NEXT(crt_row), i++)\n        {\n            db_row_t* result = (db_row_t* ) crt_row->value;\n            last_cell_ptr = serialize_cells(result, last_cell_ptr, q->start_cell_address->table_key, key_path, 1, schema_keys); // no_keys\n        }\n\n        assert(last_cell_ptr - cells == no_cells);\n\n        m = init_range_read_response_message(cells, no_cells, q->txnid, q->nonce);\n    }\n\n#if (VERBOSE_RPC > 0)\n        char print_buff[PRINT_BUFSIZE];\n        to_string_range_read_response_message(m, (char *) print_buff);\n        log_info(\"Sending range read response message: %s\", print_buff);\n#endif\n\n        int ret = serialize_range_read_response_message(m, snd_buf, snd_msg_len, vc);\n\n        free_range_read_response_message(m);\n\n        return ret;\n}\n\nint handle_range_read_query(range_read_query * q,\n                            snode_t** start_row, snode_t** end_row, db_schema_t ** schema,\n                            db_t * db, unsigned int * fastrandstate)\n{\n    int i=0;\n\n    assert(q->start_cell_address->table_key == q->end_cell_address->table_key);\n    assert(q->start_cell_address->no_keys == q->end_cell_address->no_keys);\n\n    *schema = get_schema(db, (WORD) q->start_cell_address->table_key);\n\n    int no_clustering_keys = q->start_cell_address->no_keys - (*schema)->no_primary_keys;\n\n    if(no_clustering_keys == 0)\n    {\n        return db_range_search((WORD *) q->start_cell_address->keys, (WORD *) q->end_cell_address->keys, start_row, end_row, (WORD) q->start_cell_address->table_key, db);\n    }\n    else\n    {\n        return db_range_search_clustering((WORD *) q->start_cell_address->keys,\n                                        (WORD *) (q->start_cell_address->keys + (*schema)->no_primary_keys),\n                                        (WORD *) (q->end_cell_address->keys + (*schema)->no_primary_keys),\n                                        no_clustering_keys, start_row, end_row, (WORD) q->start_cell_address->table_key, db);\n    }\n}\n\n// Queue message handlers:\n\nint get_queue_ack_packet(int status, queue_query_message * q,\n                    void ** snd_buf, unsigned * snd_msg_len, vector_clock * vc)\n{\n    ack_message * ack = init_ack_message(q->cell_address, status, q->txnid, q->nonce);\n\n#if (VERBOSE_RPC > 0)\n    char print_buff[1024];\n    to_string_ack_message(ack, (char *) print_buff);\n    log_info(\"Sending queue ack message: %s\", print_buff);\n#endif\n\n    int ret = serialize_ack_message(ack, snd_buf, snd_msg_len, vc);\n\n    free_ack_message(ack);\n\n    return ret;\n}\n\nint get_queue_read_response_packet(snode_t* start_row, snode_t* end_row, int no_results,\n                                    int64_t new_read_head, int status, db_schema_t * schema,\n                                    queue_query_message * q,\n                                    void ** snd_buf, unsigned * snd_msg_len, vector_clock * vc)\n{\n    queue_query_message * m = NULL;\n\n    if(no_results == 0)\n    {\n        m = init_read_queue_response(q->cell_address, NULL, 0, q->app_id, q->shard_id, q->consumer_id, q->group_id, new_read_head, (short) status, q->txnid, q->nonce);\n    }\n    else\n    {\n        assert(start_row != NULL);\n\n        cell * cells = malloc(no_results * sizeof(cell));\n\n        int i=0;\n        int64_t prev_id = -1;\n        for(snode_t * crt_row = start_row; i<no_results; crt_row = NEXT(crt_row), i++)\n        {\n            db_row_t* result = (db_row_t* ) crt_row->value;\n            int64_t id = (int64_t) result->key;\n            assert(i==0 || prev_id == (id - 1));\n            prev_id = id;\n            if(result->last_blob_size <= 0)\n                copy_cell(cells+i, q->cell_address->table_key,\n                        (int64_t *) &result->key, 1,\n                        (int64_t *) result->column_array, result->no_columns,\n                        NULL, 0,\n                        result->version);\n            else\n                copy_cell(cells+i, q->cell_address->table_key,\n                        (int64_t *) &result->key, 1,\n                        (int64_t *) result->column_array, result->no_columns - 1,\n                        result->column_array[result->no_columns - 1], result->last_blob_size,\n                        result->version);\n        }\n\n        m = init_read_queue_response(q->cell_address, cells, no_results, q->app_id, q->shard_id, q->consumer_id, q->group_id, new_read_head, (short) status, q->txnid, q->nonce);\n    }\n\n#if (VERBOSE_RPC > 0)\n        char print_buff[1024];\n        to_string_queue_message(m, (char *) print_buff);\n        log_info(\"Sending read queue response message: %s\", print_buff);\n#endif\n\n        int ret = serialize_queue_message(m, snd_buf, snd_msg_len, 0, vc);\n\n        free_queue_message(m);\n\n        return ret;\n}\n\nint handle_create_queue(queue_query_message * q, db_t * db, unsigned int * fastrandstate)\n{\n    if(q->txnid == NULL) // Create queue out of txn\n        return create_queue((WORD) q->cell_address->table_key, (WORD) q->cell_address->keys[0], NULL, 1, db, fastrandstate);\n    else // Create queue in txn\n        return create_queue_in_txn((WORD) q->cell_address->table_key, (WORD) q->cell_address->keys[0], q->txnid, db, fastrandstate);\n}\n\nint handle_delete_queue(queue_query_message * q, db_t * db, unsigned int * fastrandstate)\n{\n    if(q->txnid == NULL)\n        return delete_queue((WORD) q->cell_address->table_key, (WORD) q->cell_address->keys[0], NULL, 1, db, fastrandstate);\n    else\n        return delete_queue_in_txn((WORD) q->cell_address->table_key, (WORD) q->cell_address->keys[0], q->txnid, db, fastrandstate);\n}\n\nint handle_subscribe_queue(queue_query_message * q, int * clientfd, int64_t * prev_read_head, int64_t * prev_consume_head, db_t * db, unsigned int * fastrandstate)\n{\n    if(q->txnid != NULL) // Create queue out of txn\n    {\n        assert(0); // Subscriptions in txns are not supported yet\n        return 1;\n    }\n    else\n        return register_remote_subscribe_queue((WORD) q->consumer_id, (WORD) q->shard_id, (WORD) q->app_id, (WORD) q->cell_address->table_key, (WORD) q->cell_address->keys[0], (WORD) q->group_id,\n                                        clientfd, prev_read_head, prev_consume_head, 1, db, fastrandstate);\n}\n\nint handle_unsubscribe_queue(queue_query_message * q, db_t * db, unsigned int * fastrandstate)\n{\n    if(q->txnid != NULL) // Create queue out of txn\n    {\n        assert(0); // Unsubscriptions in txns are not supported yet\n        return 1;\n    }\n    else\n        return register_remote_unsubscribe_queue((WORD) q->consumer_id, (WORD) q->shard_id, (WORD) q->app_id, (WORD) q->cell_address->table_key, (WORD) q->cell_address->keys[0], (WORD) q->group_id, 1, db);\n}\n\nint handle_enqueue(queue_query_message * q, db_t * db, unsigned int * fastrandstate)\n{\n    assert(q->no_cells > 0 && q->cells != NULL);\n\n    int status = -1;\n\n    for(int i=0;i<q->no_cells;i++)\n    {\n        int total_cols = q->cells[i].no_keys + q->cells[i].no_columns;\n        int total_cols_plus_blob = total_cols + ((q->cells[i].last_blob_size > 0)?(1):(0));\n\n        int64_t * column_values = (int64_t *) malloc(total_cols_plus_blob * sizeof(int64_t));\n\n        int j = 0;\n        for(;j<q->cells[i].no_keys;j++)\n            column_values[j] = q->cells[i].keys[j];\n        for(;j<total_cols;j++)\n            column_values[j] = q->cells[i].columns[j-q->cells[i].no_keys];\n\n        if(q->cells[i].last_blob_size > 0)\n        {\n            assert(total_cols_plus_blob == total_cols + 1);\n            column_values[total_cols] = (int64_t) malloc(q->cells[i].last_blob_size);\n            memcpy((WORD) column_values[total_cols], q->cells[i].last_blob, q->cells[i].last_blob_size);\n        }\n\n        // Below will automatically trigger remote consumer notifications on the queue, either immediately or upon txn commit:\n        if(q->txnid == NULL) // Enqueue out of txn\n            status = enqueue((WORD *) column_values, total_cols_plus_blob, q->cells[i].last_blob_size, (WORD) q->cell_address->table_key, (WORD) q->cell_address->keys[0], 1, db, fastrandstate);\n        else // Enqueue in txn\n            status = enqueue_in_txn((WORD *) column_values, total_cols_plus_blob, q->cells[i].last_blob_size, (WORD) q->cell_address->table_key, (WORD) q->cell_address->keys[0], q->txnid, db, fastrandstate);\n\n        if(status != 0)\n            break;\n    }\n\n    return status;\n}\n\nint handle_read_queue(queue_query_message * q,\n                        int * entries_read, int64_t * new_read_head, vector_clock ** prh_version,\n                        snode_t** start_row, snode_t** end_row, db_schema_t ** schema,\n                        db_t * db, unsigned int * fastrandstate)\n{\n    *schema = get_schema(db, (WORD) q->cell_address->table_key);\n\n    if(q->txnid == NULL) // Read queue out of txn\n        return read_queue((WORD) q->consumer_id, (WORD) q->shard_id, (WORD) q->app_id,\n                            (WORD) q->cell_address->table_key, (WORD) q->cell_address->keys[0], q->queue_index,\n                            entries_read, new_read_head, prh_version,\n                            start_row, end_row, 1, db);\n    else // Read queue in txn\n        return read_queue_in_txn((WORD) q->consumer_id, (WORD) q->shard_id, (WORD) q->app_id,\n                                    (WORD) q->cell_address->table_key, (WORD) q->cell_address->keys[0],\n                                    (int) q->queue_index, entries_read, new_read_head,\n                                    start_row, end_row, q->txnid, db, fastrandstate);\n}\n\nint handle_consume_queue(queue_query_message * q, db_t * db, unsigned int * fastrandstate)\n{\n    if(q->txnid == NULL) // Consume queue out of txn\n        return consume_queue((WORD) q->consumer_id, (WORD) q->shard_id, (WORD) q->app_id,\n                            (WORD) q->cell_address->table_key, (WORD) q->cell_address->keys[0],\n                            q->queue_index, db);\n    else // Consume queue in txn\n        return consume_queue_in_txn((WORD) q->consumer_id, (WORD) q->shard_id, (WORD) q->app_id,\n                                    (WORD) q->cell_address->table_key, (WORD) q->cell_address->keys[0],\n                                    q->queue_index, q->txnid, db, fastrandstate);\n}\n\n// Txn messages handlers:\n\nint get_txn_ack_packet(int status, txn_message * q,\n                    void ** snd_buf, unsigned * snd_msg_len, vector_clock * vc)\n{\n    ack_message * ack = init_ack_message(NULL, status, q->txnid, q->nonce);\n\n#if (VERBOSE_RPC > 0)\n    char print_buff[1024];\n    to_string_ack_message(ack, (char *) print_buff);\n    log_info(\"Sending txn ack message: %s\", print_buff);\n#endif\n\n    int ret = serialize_ack_message(ack, snd_buf, snd_msg_len, vc);\n\n    free_ack_message(ack);\n\n    return ret;\n}\n\n\nint handle_new_txn(txn_message * q, db_t * db, unsigned int * fastrandstate)\n{\n    assert(q->txnid != NULL);\n\n#if (MULTI_THREADED == 1)\n    pthread_mutex_lock(db->txn_state_lock);\n#endif\n\n    txn_state * ts = get_txn_state(q->txnid, db);\n\n    if(ts != NULL)\n    {\n#if (MULTI_THREADED == 1)\n        pthread_mutex_unlock(db->txn_state_lock);\n#endif\n\n        return DUPLICATE_TXN; // txnid already exists on server\n    }\n\n    ts = init_txn_state();\n\n    memcpy(&ts->txnid, q->txnid, sizeof(uuid_t));\n\n    skiplist_insert(db->txn_state, (WORD) ts->txnid, (WORD) ts, fastrandstate);\n\n#if (MULTI_THREADED == 1)\n    pthread_mutex_unlock(db->txn_state_lock);\n#endif\n\n    return 0;\n}\n\nint handle_validate_txn(txn_message * q, db_t * db, unsigned int * fastrandstate)\n{\n    assert(q->txnid != NULL);\n    assert(q->version != NULL);\n\n    return validate_txn(q->txnid, q->version, db);\n}\n\nint handle_commit_txn(txn_message * q, db_t * db, unsigned int * fastrandstate)\n{\n    assert(q->txnid != NULL);\n\n    txn_state * ts = get_txn_state(q->txnid, db);\n\n    // Make sure the txn has the right commit stamp (it c'd be that the current server missed the previous validation packet so the version was not set then):\n\n    if(ts == NULL)\n        return NO_SUCH_TXN; // txnid doesn't exist on server\n\n    set_version(ts, q->version);\n\n    return persist_txn(ts, db, fastrandstate);\n}\n\nint handle_abort_txn(txn_message * q, db_t * db, unsigned int * fastrandstate)\n{\n    assert(q->txnid != NULL);\n\n    return abort_txn(q->txnid, db);\n}\n\n\nint handle_socket_nop(int * childfd, int * status)\n{\n    struct sockaddr_in address;\n    int addrlen;\n    getpeername(*childfd, (struct sockaddr*)&address,\n                (socklen_t*)&addrlen);\n    log_info(\"Host disconnected, ip %s, port %d, status=%d, fd, NOP %d\" ,\n              inet_ntoa(address.sin_addr) , ntohs(address.sin_port), *status, *childfd);\n\n    *status = NODE_DEAD;\n\n    return 0;\n}\n\nint handle_socket_close(int * childfd, int * status)\n{\n    struct sockaddr_in address;\n    int addrlen;\n    getpeername(*childfd, (struct sockaddr*)&address,\n                (socklen_t*)&addrlen);\n    log_info(\"Host disconnected, ip %s, port %d, old_status=%d, closing fd %d\" ,\n              inet_ntoa(address.sin_addr) , ntohs(address.sin_port), *status, *childfd);\n\n    //Close the socket and mark as -1 for reuse:\n    close(*childfd);\n    *childfd = -1;\n\n    *status = NODE_DEAD;\n\n    return 0;\n}\n\nint add_remote_server_to_list(remote_server * rs, skiplist_t * peer_list, unsigned int * seedptr)\n{\n    snode_t * snode = skiplist_search(peer_list, &rs->serveraddr);\n\n    if(snode != NULL)\n    {\n        log_info(\"Server address %s:%d was already added to membership, marking it as live!\", rs->hostname, rs->portno);\n        remote_server * existing_rs = (remote_server *) snode->value;\n        existing_rs->status = NODE_LIVE;\n        // Update client socket address:\n        memcpy(&(existing_rs->client_socket_addr), &(rs->client_socket_addr), sizeof(struct sockaddr_in));\n        return -1;\n    }\n\n    int status = skiplist_insert(peer_list, &rs->serveraddr, rs, seedptr);\n\n    if(status != 0)\n    {\n        log_error(\"Error adding server address %s:%d to membership!\", rs->hostname, rs->portno);\n        assert(0);\n        return -2;\n    }\n\n    return 0;\n}\n\nint add_remote_server_to_membership(remote_server * rs, membership * m, short list, unsigned int * seedptr)\n{\n    switch(list)\n    {\n        case AGREED_PEERS:\n            return add_remote_server_to_list(rs, m->agreed_peers, seedptr);\n        case LOCAL_PEERS:\n            return add_remote_server_to_list(rs, m->local_peers, seedptr);\n        case CONNECTED_PEERS:\n            return add_remote_server_to_list(rs, m->connected_peers, seedptr);\n        case CONNECTED_CLIENTS:\n            return add_remote_server_to_list(rs, m->connected_clients, seedptr);\n    }\n\n    return -1;\n}\n\nint add_peer_to_membership(char *hostname, unsigned short portno, struct sockaddr_in serveraddr, int serverfd, int do_connect, membership * m, short list, remote_server ** rs, unsigned int * seedptr)\n{\n    struct sockaddr_in dummy_serveraddr;\n    *rs = get_remote_server(hostname, portno, serveraddr, dummy_serveraddr, serverfd, do_connect, 0);\n\n    if(rs == NULL)\n    {\n        log_debug(\"ERROR: Failed joining server %s:%d (it looks down)!\", hostname, portno);\n            return 1;\n    }\n\n    int status = add_remote_server_to_membership(*rs, m, list, seedptr);\n\n    if(status != 0)\n    {\n            assert(0);\n            free_remote_server(*rs);\n            *rs = NULL;\n    }\n\n    return status;\n}\n\n\nint handle_client_message(int childfd, int msg_len, db_t * db, membership * m, skiplist_t * clients, unsigned int * fastrandstate, vector_clock * my_lc, int my_id)\n{\n    void * tmp_out_buf = NULL, * q = NULL;\n    unsigned snd_msg_len;\n    short msg_type;\n    short is_gossip_message;\n    db_schema_t * schema;\n    int64_t nonce = -1;\n    membership_agreement_msg * amr = NULL;\n\n    vector_clock * lc_read = NULL;\n    int status = parse_message(in_buf + sizeof(int), msg_len, &q, &msg_type, &is_gossip_message, &nonce, 1, &lc_read);\n\n    if(status != 0)\n    {\n            log_error( \"ERROR decoding client request\");\n            return -1;\n    }\n\n    if(lc_read != NULL)\n    {\n            // If we were multi-threaded, we'd have to protect this snippet:\n\n#if (VERBOSE_RPC > 2)\n        char msg_buf[1024];\n        log_debug(\"SERVER: Received client message with LC %s.\", to_string_vc(lc_read, msg_buf));\n        log_debug(\"SERVER: My LC before update is %s.\", to_string_vc(my_lc, msg_buf));\n#endif\n\n            update_vc(my_lc, lc_read);\n            increment_vc(my_lc, my_id);\n\n            free_vc(lc_read);\n\n#if (VERBOSE_RPC > 2)\n        log_debug(\"SERVER: Updated local LC to %s.\", to_string_vc(my_lc, msg_buf));\n#endif\n    }\n\n    switch(msg_type)\n    {\n            case RPC_TYPE_WRITE:\n            {\n                status = handle_write_query((write_query *) q, db, fastrandstate);\n                if(status != 0)\n                {\n                    log_error(\"handle_write_query returned %d!\", status);\n                    assert(0);\n                }\n                vector_clock * vc = (((write_query *) q)->txnid != NULL)?(copy_vc(my_lc)):(NULL);\n                status = get_ack_packet(status, (write_query *) q, &tmp_out_buf, &snd_msg_len, vc);\n                if(vc != NULL)\n                    free_vc(vc);\n                free_write_query((write_query *) q);\n                break;\n            }\n            case RPC_TYPE_READ:\n            {\n                db_row_t* result = handle_read_query((read_query *) q, &schema, db, fastrandstate);\n                vector_clock * vc = (((read_query *) q)->txnid != NULL)?(copy_vc(my_lc)):(NULL);\n                status = get_read_response_packet(result, (read_query *) q, schema, &tmp_out_buf, &snd_msg_len, vc);\n                if(vc != NULL)\n                    free_vc(vc);\n                free_read_query((read_query *) q);\n                break;\n            }\n            case RPC_TYPE_RANGE_READ:\n            {\n                snode_t * start_row = NULL, * end_row = NULL;\n                vector_clock * vc = (((range_read_query *) q)->txnid != NULL)?(copy_vc(my_lc)):(NULL);\n                int no_results = handle_range_read_query((range_read_query *) q, &start_row, &end_row, &schema, db, fastrandstate);\n                status = get_range_read_response_packet(start_row, end_row, no_results, (range_read_query *) q, schema, &tmp_out_buf, &snd_msg_len, vc);\n                if(vc != NULL)\n                    free_vc(vc);\n                free_range_read_query((range_read_query *) q);\n                break;\n            }\n            case RPC_TYPE_QUEUE:\n            {\n                queue_query_message * qm = (queue_query_message *) q;\n                vector_clock * vc = (qm->txnid != NULL)?(copy_vc(my_lc)):(NULL);\n\n                switch(qm->msg_type)\n                {\n                    case QUERY_TYPE_CREATE_QUEUE:\n                    {\n                        status = handle_create_queue(qm, db, fastrandstate);\n//                      assert(status == 0);\n                        status = get_queue_ack_packet(status, qm, &tmp_out_buf, &snd_msg_len, vc);\n                        break;\n                    }\n                    case QUERY_TYPE_DELETE_QUEUE:\n                    {\n                        status = handle_delete_queue(qm, db, fastrandstate);\n                        assert(status == 0);\n                        status = get_queue_ack_packet(status, qm, &tmp_out_buf, &snd_msg_len, vc);\n                        break;\n                    }\n                    case QUERY_TYPE_SUBSCRIBE_QUEUE:\n                    {\n                        int64_t prev_read_head = -1, prev_consume_head = -1;\n                        status = handle_subscribe_queue(qm, &childfd, &prev_read_head, &prev_consume_head, db, fastrandstate);\n//                      assert(status == 0);\n                        status = get_queue_ack_packet(status, qm, &tmp_out_buf, &snd_msg_len, vc);\n                        break;\n                    }\n                    case QUERY_TYPE_UNSUBSCRIBE_QUEUE:\n                    {\n                        status = handle_unsubscribe_queue(qm, db, fastrandstate);\n                        assert(status == 0);\n                        status = get_queue_ack_packet(status, qm, &tmp_out_buf, &snd_msg_len, vc);\n                        break;\n                    }\n                    case QUERY_TYPE_ADD_QUEUE_TO_GROUP:\n                    {\n                        // This is handled automatically, should not be called explicitly\n                        assert(0);\n                        break;\n                    }\n                    case QUERY_TYPE_ENQUEUE:\n                    {\n                        status = handle_enqueue(qm, db, fastrandstate);\n                        assert(status == 0);\n                        status = get_queue_ack_packet(status, qm, &tmp_out_buf, &snd_msg_len, vc);\n\n                        break;\n                    }\n                    case QUERY_TYPE_READ_QUEUE:\n                    {\n                        int entries_read = 0;\n                        int64_t new_read_head = -1;\n                        vector_clock * prh_version = NULL;\n                        snode_t * start_row = NULL, * end_row = NULL;\n                        db_schema_t * schema = NULL;\n                        status = handle_read_queue(qm, &entries_read, &new_read_head, &prh_version,\n                                                        &start_row, &end_row, &schema, db, fastrandstate);\n                        if(status != QUEUE_STATUS_READ_COMPLETE && status != QUEUE_STATUS_READ_INCOMPLETE && status != DB_ERR_NO_CONSUMER)\n                        {\n                            log_error(\"Unexpected status returned by handle_read_queue(): %d\", status);\n                            assert(0);\n                        }\n                        status = get_queue_read_response_packet(start_row, end_row, entries_read, new_read_head, status, schema, qm, &tmp_out_buf, &snd_msg_len, vc);\n\n                        break;\n                    }\n                    case QUERY_TYPE_CONSUME_QUEUE:\n                    {\n                        status = handle_consume_queue(qm, db, fastrandstate);\n//                      assert(status == (int) qm->queue_index);\n                        status = get_queue_ack_packet(status, qm, &tmp_out_buf, &snd_msg_len, vc);\n                        break;\n                    }\n                    default:\n                    {\n                        assert(0);\n                    }\n                }\n\n                if(vc != NULL)\n                    free_vc(vc);\n                free_queue_message(qm);\n\n                break;\n            }\n            case RPC_TYPE_TXN:\n            {\n                txn_message * tm = (txn_message *) q;\n                assert(tm->txnid != NULL);\n                vector_clock * vc = copy_vc(my_lc);\n\n                switch(tm->type)\n                {\n                    case DB_TXN_BEGIN:\n                    {\n                        status = handle_new_txn(tm, db, fastrandstate);\n                        assert(status == 0 || status == DUPLICATE_TXN);\n                        status = get_txn_ack_packet(status, tm, &tmp_out_buf, &snd_msg_len, vc);\n\n                        break;\n                    }\n                    case DB_TXN_VALIDATION:\n                    {\n                        status = handle_validate_txn(tm, db, fastrandstate);\n                        if(status != VAL_STATUS_COMMIT)\n                            log_warn(\"BACKEND: handle_validate_txn() returned %d\\n\", status);\n                        assert(status == VAL_STATUS_COMMIT || status == VAL_STATUS_ABORT || status == VAL_STATUS_ABORT_SCHEMA || status == NO_SUCH_TXN);\n                        status = get_txn_ack_packet(status, tm, &tmp_out_buf, &snd_msg_len, vc);\n\n                        break;\n                    }\n                    case DB_TXN_COMMIT:\n                    {\n                        status = handle_commit_txn(tm, db, fastrandstate);\n                        if(status != 0)\n                            log_warn(\"BACKEND: handle_commit_txn() returned %d\\n\", status);\n                        status = get_txn_ack_packet(status, tm, &tmp_out_buf, &snd_msg_len, vc);\n\n                        break;\n                    }\n                    case DB_TXN_ABORT:\n                    {\n                        status = handle_abort_txn(tm, db, fastrandstate);\n                        assert(status == 0);\n                        status = get_txn_ack_packet(status, tm, &tmp_out_buf, &snd_msg_len, vc);\n\n                        break;\n                    }\n                }\n\n                if(vc != NULL)\n                    free_vc(vc);\n                free_txn_message(tm);\n\n                break;\n            }\n            case RPC_TYPE_GOSSIP_LISTEN:\n            {\n                client_descriptor * cd = lookup_client_by_fd(childfd, clients);\n                int status = handle_gossip_listen_message((gossip_listen_message *) q, cd, m, copy_vc(my_lc),\n                                                            &amr, fastrandstate);\n\n                assert(get_gossip_ack_packet(status, (gossip_listen_message *) q, &tmp_out_buf, &snd_msg_len, NULL) == 0);\n            free_gossip_listen_msg(q);\n                break;\n            }\n            case RPC_TYPE_ACK:\n            {\n                assert(0); // S'dn't happen currently\n                break;\n            }\n        default:\n        {\n            assert(0);\n        }\n    }\n\n    assert(status == 0);\n\n    int n = write(childfd, tmp_out_buf, snd_msg_len);\n    if (n < 0)\n      log_error(\"ERROR writing to socket\");\n\n    // There might be a view notification to send to client:\n    if(amr != NULL)\n    {\n        assert(serialize_membership_agreement_msg(amr, &tmp_out_buf, &snd_msg_len) == 0);\n        free_membership_agreement(amr);\n        n = write(childfd, tmp_out_buf, snd_msg_len);\n        if (n < 0)\n            log_error(\"ERROR writing to socket\");\n    }\n\n    free(tmp_out_buf);\n\n    return 0;\n}\n\n// Gossip message handling:\n\nint get_join_packet(int status, int rack_id, int dc_id, char * hostname, unsigned short portno, int64_t nonce,\n                    void ** snd_buf, unsigned * snd_msg_len, vector_clock * vc)\n{\n    membership_agreement_msg * jm = get_membership_join_msg(status, rack_id, dc_id, hostname, portno, nonce, vc);\n\n#if (VERBOSE_RPC > 0)\n    char print_buff[1024];\n    to_string_membership_agreement_msg(jm, (char *) print_buff);\n    log_info(\"Sending Join message: %s\", print_buff);\n#endif\n\n    int ret = serialize_membership_agreement_msg(jm, snd_buf, snd_msg_len);\n\n    free_membership_agreement(jm);\n\n    return ret;\n}\n\nint get_agreement_propose_packet(int status, membership_state * membership, int64_t nonce,\n                                    void ** snd_buf, unsigned * snd_msg_len, vector_clock * vc)\n{\n    membership_agreement_msg * amr = get_membership_propose_msg(status, membership, nonce, vc);\n\n#if (VERBOSE_RPC > 0)\n    char print_buff[1024];\n    to_string_membership_agreement_msg(amr, (char *) print_buff);\n    log_info(\"Sending Membership Propose message: %s\", print_buff);\n#endif\n\n    int ret = serialize_membership_agreement_msg(amr, snd_buf, snd_msg_len);\n\n    free_membership_agreement(amr);\n\n    return ret;\n}\n\nint get_agreement_response_packet(int status, membership_state * membership, membership_agreement_msg * am,\n                                    void ** snd_buf, unsigned * snd_msg_len, vector_clock * vc)\n{\n    membership_agreement_msg * amr = get_membership_response_msg(status, membership, am->nonce, copy_vc(vc));\n\n#if (VERBOSE_RPC > 0)\n    char print_buff[1024];\n    to_string_membership_agreement_msg(amr, (char *) print_buff);\n    log_info(\"Sending Membership Response message: %s\", print_buff);\n#endif\n\n    int ret = serialize_membership_agreement_msg(amr, snd_buf, snd_msg_len);\n\n    free_membership_agreement(amr);\n\n    return ret;\n}\n\nint get_agreement_notify_packet(int status, membership_state * membership, membership_agreement_msg * am,\n                                membership_agreement_msg ** amr,    void ** snd_buf, unsigned * snd_msg_len,\n                                vector_clock * vc, vector_clock * prev_vc)\n{\n    *amr = get_membership_notify_msg(status, membership, am->nonce, copy_vc(vc));\n\n#if (VERBOSE_RPC > 0)\n    char print_buff[1024];\n    to_string_membership_agreement_msg(*amr, (char *) print_buff);\n    log_info(\"Sending Membership Notify message: %s\", print_buff);\n#endif\n\n    int ret = serialize_membership_agreement_msg(*amr, snd_buf, snd_msg_len);\n\n    return ret;\n}\n\nint get_agreement_notify_ack_packet(int status, membership_agreement_msg * am,\n                                    void ** snd_buf, unsigned * snd_msg_len, vector_clock * vc)\n{\n    membership_agreement_msg * amr = get_membership_notify_ack_msg(status, am->nonce, copy_vc(vc));\n\n#if (VERBOSE_RPC > 0)\n    char print_buff[1024];\n    to_string_membership_agreement_msg(amr, (char *) print_buff);\n    log_info(\"Sending Membership Notify ACK message: %s\", print_buff);\n#endif\n\n    int ret = serialize_membership_agreement_msg(amr, snd_buf, snd_msg_len);\n\n    free_membership_agreement(amr);\n\n    return ret;\n}\n\nmembership_state * get_membership_state_from_server_list(skiplist_t * servers, skiplist_t * clients, vector_clock * my_lc)\n{\n    if(servers->no_items == 0)\n        return NULL;\n\n    node_description * nds = (node_description *) malloc(servers->no_items * sizeof(node_description));\n    node_description * client_nds = (node_description *) malloc(clients->no_items * sizeof(node_description));\n\n    int i = 0;\n    for(snode_t * crt = HEAD(servers); crt!=NULL; crt = NEXT(crt), i++)\n    {\n        remote_server * rs = (remote_server *) crt->value;\n        copy_node_description(nds+i, rs->status, get_node_id((struct sockaddr *) &(rs->serveraddr)), 0, 0, rs->hostname, rs->portno);\n    }\n\n    int j = 0;\n    for(snode_t * crt = HEAD(clients); crt!=NULL; crt = NEXT(crt), j++)\n    {\n        remote_server * rs = (remote_server *) crt->value;\n        copy_node_description(client_nds+j, rs->status, get_node_id((struct sockaddr *) &(rs->serveraddr)), 0, 0, rs->hostname, rs->portno);\n    }\n\n    return init_membership_state(servers->no_items, nds, clients->no_items, client_nds, my_lc);\n}\n\nint no_live_nodes(skiplist_t * list)\n{\n    int no_nodes = 0;\n\n    for(snode_t * crt = HEAD(list); crt!=NULL; crt = NEXT(crt))\n    {\n        remote_server * rs = (remote_server *) crt->value;\n\n        if(rs->status == NODE_LIVE)\n            no_nodes++;\n    }\n\n    return no_nodes;\n}\n\nint no_live_or_unknown_nodes(skiplist_t * list)\n{\n    int no_nodes = 0;\n\n    for(snode_t * crt = HEAD(list); crt!=NULL; crt = NEXT(crt))\n    {\n        remote_server * rs = (remote_server *) crt->value;\n\n        if(rs->status == NODE_LIVE)\n            no_nodes++;\n    }\n\n    return no_nodes;\n}\n\nint is_min_live_node(int id, skiplist_t * list)\n{\n    if(list->no_items == 0)\n        return -2; // empty list\n\n    int min_id = INT_MAX, id_in_list = 0;\n\n    for(snode_t * crt = HEAD(list); crt!=NULL; crt = NEXT(crt))\n    {\n        remote_server * rs = (remote_server *) crt->value;\n        int node_id = get_node_id((struct sockaddr *) &(rs->serveraddr));\n        if(node_id == id)\n            id_in_list = 1;\n\n        if(rs->status == NODE_LIVE)\n        {\n            min_id = (node_id < min_id)?node_id:min_id;\n        }\n    }\n\n    if(!id_in_list)\n        return -1; // Node not in list\n\n    if(min_id == id)\n        return 1;\n\n    return 0;\n}\n\nint mark_live(membership * m, int sender_id)\n{\n    for(snode_t * crt = HEAD(m->local_peers); crt!=NULL; crt = NEXT(crt))\n    {\n        remote_server * rs = (remote_server *) crt->value;\n\n        int node_id = get_node_id((struct sockaddr *) &(rs->serveraddr));\n        if(node_id == sender_id)\n        {\n            rs->status = NODE_LIVE;\n\n            return 0;\n        }\n    }\n\n    return 1;\n}\n\nint mark_dead(membership * m, int sender_id)\n{\n    for(snode_t * crt = HEAD(m->local_peers); crt!=NULL; crt = NEXT(crt))\n    {\n        remote_server * rs = (remote_server *) crt->value;\n\n        int node_id = get_node_id((struct sockaddr *) &(rs->serveraddr));\n        if(node_id == sender_id)\n        {\n            rs->status = NODE_DEAD;\n\n            return 0;\n        }\n    }\n\n    return 1;\n}\n\nint send_join_message(int rack_id, int dc_id, char * hostname, unsigned short portno, vector_clock * my_vc, remote_server * dest_rs, unsigned int * fastrandstate)\n{\n    void * tmp_out_buf = NULL;\n    unsigned snd_msg_len;\n\n    if(dest_rs->status != NODE_LIVE || dest_rs->sockfd <= 0)\n    {\n#if (VERBOSE_RPC > 0)\n        char msg_buf[1024];\n        log_warn(\"SERVER: Not sending JOIN request to %s, as its status is %d!\", dest_rs->id, dest_rs->status);\n#endif\n\n            return 1;\n    }\n\n    int status = get_join_packet(0, rack_id, dc_id, hostname, portno, _get_nonce(fastrandstate), &tmp_out_buf, &snd_msg_len, copy_vc(my_vc));\n\n    assert(status == 0);\n\n    int n = write(dest_rs->sockfd, tmp_out_buf, snd_msg_len);\n\n    if (n < 0)\n        error(\"ERROR writing to socket\");\n\n    free(tmp_out_buf);\n\n    return 0;\n}\n\n\nint propose_local_membership(membership * m, vector_clock * my_vc, membership_agreement_msg ** amr, int64_t nonce, unsigned int * fastrandstate)\n{\n    void * tmp_out_buf = NULL;\n    unsigned snd_msg_len;\n    int status = 0, skip_proposal = 0;\n    char msg_buf[1024];\n\n    if(no_live_nodes(m->local_peers) <= 1)\n    {\n#if (VERBOSE_RPC > 0)\n        log_warn(\"SERVER: Skipping proposing new view, as no other nodes are live in local membership!\");\n#endif\n        skip_proposal = 1;\n    }\n\n    if(is_min_live_node(m->my_id, m->local_peers) != 1)\n    {\n#if (VERBOSE_RPC > 0)\n        log_info(\"SERVER: Skipping proposing new view, as I am not the min live node!\");\n#endif\n        skip_proposal = 1;\n    }\n\n    if(skip_proposal)\n    {\n        // In this case, there won't be an agreement proposal, but we must still notify the clients of the current local view if\n        // this came from a listen_to_gossip(), for it to learn the client memberships in case we are the only server in the system:\n        if(amr != NULL)\n        {\n            *amr = get_membership_notify_msg(0,\n                                        get_membership_state_from_server_list(skiplist_clone(m->local_peers, fastrandstate),\n                                                                             skiplist_clone(m->connected_clients, fastrandstate),\n                                                                             copy_vc(my_vc)),\n                                        nonce, copy_vc(my_vc));\n#if (VERBOSE_RPC > 0)\n        to_string_membership_agreement_msg(*amr, (char *) msg_buf);\n        log_info(\"Sending Membership Notify message to clients: %s\", msg_buf);\n#endif\n        }\n        return SKIP_PROPOSAL_STATUS;\n    }\n\n    if(m->outstanding_view_id != NULL)\n    {\n#if (VERBOSE_RPC > 0)\n        log_warn(\"SERVER: Proposing new view, aborting already outstanding view proposal %s!\",\n                            to_string_vc(m->outstanding_view_id, msg_buf));\n#endif\n        skiplist_free(m->outstanding_proposal);\n        skiplist_free(m->outstanding_proposal_clients);\n        free_vc(m->outstanding_view_id);\n    }\n\n    m->outstanding_proposal = skiplist_clone(m->local_peers, fastrandstate);\n    m->outstanding_proposal_clients = skiplist_clone(m->connected_clients, fastrandstate);\n    m->outstanding_view_id = copy_vc(my_vc);\n    m->outstanding_proposal_nonce = _get_nonce(fastrandstate);\n    m->proposal_status = PROPOSAL_STATUS_ACTIVE;\n    m->outstanding_proposal_acks = 0;\n    m->merged_responses = skiplist_clone(m->local_peers, fastrandstate); // init merged responses for server list to \"my response\"\n    m->merged_client_responses = skiplist_clone(m->connected_clients, fastrandstate); // init merged responses for client list to \"my response\"\n\n    status = get_agreement_propose_packet(0, get_membership_state_from_server_list(m->outstanding_proposal, m->outstanding_proposal_clients, copy_vc(m->outstanding_view_id)),\n                                                m->outstanding_proposal_nonce, &tmp_out_buf, &snd_msg_len, copy_vc(m->outstanding_view_id));\n\n\n    for(snode_t * crt = HEAD(m->local_peers); crt!=NULL; crt = NEXT(crt))\n    {\n        remote_server * rs = (remote_server *) crt->value;\n\n#if (VERBOSE_RPC > 0)\n        log_info(\"SERVER: propose_local_membership: Evaluating node (%s, %d, %d, %d), my_id = %d..\", rs->id, rs->status, rs->sockfd, get_node_id((struct sockaddr *) &(rs->serveraddr)), m->my_id);\n#endif\n\n        if(rs->status == NODE_LIVE && rs->sockfd > 0 && get_node_id((struct sockaddr *) &(rs->serveraddr)) != m->my_id) // skip myself, and nodes that are \"down\" in membership\n        {\n#if (VERBOSE_RPC > 0)\n            log_info(\"SERVER: Sending proposal!\");\n#endif\n            int n = write(rs->sockfd, tmp_out_buf, snd_msg_len);\n\n            if (n < 0)\n              error(\"ERROR writing to socket\");\n\n            m->outstanding_proposal_acks++;\n        }\n    }\n\n    free(tmp_out_buf);\n\n    return 0;\n}\n\nint merge_membership_agreement_msg_to_list(membership_agreement_msg * ma, skiplist_t * merged_list, membership * m, vector_clock * my_lc, unsigned int * fastrandstate)\n{\n    int memberships_differ = 0;\n    struct sockaddr_in dummy_serveraddr;\n\n    for(int i=0;i<ma->membership->no_nodes;i++)\n    {\n        node_description nd = ma->membership->membership[i];\n\n        remote_server * rs = get_remote_server(nd.hostname, nd.portno, dummy_serveraddr, dummy_serveraddr, DUMMY_FD, 0, 0);\n        rs->status = nd.status;\n\n        snode_t * node = skiplist_search(merged_list, &rs->serveraddr);\n\n        if(node == NULL) // I just learned about this node\n        {\n#if (VERBOSE_RPC > 0)\n            char msg_buf[1024];\n            log_info(\"SERVER: merge_membership_agreement_msg_to_list: Learned about node %s from proposal, status=%d.\", rs->id, rs->status);\n#endif\n\n            int status = connect_remote_server(rs);\n\n            if(status != 0)\n            {\n                rs->status = NODE_DEAD;\n                rs->sockfd = -1;\n                if(nd.status == NODE_LIVE)\n                    memberships_differ = 1;\n            }\n\n            status = add_remote_server_to_list(rs, m->local_peers, fastrandstate);\n            status = add_remote_server_to_list(rs, merged_list, fastrandstate);\n\n            assert(status == 0);\n        }\n        else\n        {\n            free_remote_server(rs);\n\n            remote_server * rs_local = (remote_server *) node->value;\n\n            if(rs_local->status != nd.status) // if proposed server status is different than local one, and proposed clock is newer, use proposed status\n            {\n                int64_t local_counter = get_component_vc(my_lc, nd.node_id);\n                int64_t proposed_counter = get_component_vc(ma->vc, nd.node_id);\n\n                if((proposed_counter > local_counter)\n                        || (proposed_counter == -1 && local_counter == -1)) // -1 is for client (RTS membership entries), which do not participate in the vector_clock version\n                {\n#if (VERBOSE_RPC > 0)\n                    log_info(\"SERVER: merge_membership_agreement_msg_to_list: Updating status of node %s from %d to %d, because local_counter=%\" PRId64 \", proposed_counter=%\" PRId64 \".\", rs->id, rs_local->status, nd.status, local_counter, proposed_counter);\n#endif\n\n                    rs_local->status = nd.status;\n                }\n                else\n                {\n#if (VERBOSE_RPC > 0)\n                    log_info(\"SERVER: merge_membership_agreement_msg_to_list: Requesting membership ammend, because for node %s, local_status=%d, proposed_status=%d, local_counter=%\" PRId64 \", proposed_counter=%\" PRId64 \".\", rs->id, rs_local->status, nd.status, local_counter, proposed_counter);\n#endif\n\n                    memberships_differ = 1;\n                }\n            }\n        }\n    }\n\n    return memberships_differ;\n}\n\nint merge_membership_agreement_msg_to_client_list(membership_agreement_msg * ma, skiplist_t * merged_list, membership * m, vector_clock * my_lc, unsigned int * fastrandstate)\n{\n    int memberships_differ = 0;\n    struct sockaddr_in dummy_serveraddr;\n    int reverse_connect_to_clients = 0;\n\n    for(int i=0;i<ma->membership->no_client_nodes;i++)\n    {\n        node_description nd = ma->membership->client_membership[i];\n\n        remote_server * rs = get_remote_server(nd.hostname, nd.portno, dummy_serveraddr, dummy_serveraddr, DUMMY_FD, 0, 1);\n        rs->status = nd.status;\n\n        snode_t * node = skiplist_search(merged_list, &rs->serveraddr);\n\n        if(node == NULL) // I just learned about this client\n        {\n#if (VERBOSE_RPC > 0)\n            char msg_buf[1024];\n            log_info(\"SERVER: merge_membership_agreement_msg_to_list: Learned about client node %s from proposal, status=%d.\", rs->id, rs->status);\n#endif\n\n            int status = 0;\n            if(reverse_connect_to_clients)\n            {\n                status = connect_remote_server(rs);\n\n                if(status != 0)\n                {\n                    rs->status = NODE_DEAD;\n                    rs->sockfd = -1;\n                    if(nd.status == NODE_LIVE)\n                        memberships_differ = 1;\n                }\n            }\n            else\n            {\n                memberships_differ = 1;\n            }\n\n            status = add_remote_server_to_list(rs, m->connected_clients, fastrandstate);\n            assert(status == 0);\n            status = add_remote_server_to_list(rs, merged_list, fastrandstate);\n            assert(status == 0);\n        }\n        else\n        {\n            free_remote_server(rs);\n\n            remote_server * rs_local = (remote_server *) node->value;\n\n            if(rs_local->status != nd.status) // if proposed server status is different than local one, and proposed clock is newer, use proposed status\n            {\n                int64_t local_counter = get_component_vc(my_lc, nd.node_id);\n                int64_t proposed_counter = get_component_vc(ma->vc, nd.node_id);\n\n                if((proposed_counter > local_counter)\n                    || (proposed_counter == -1 && local_counter == -1)) // -1 is for client (RTS membership entries), which do not participate in the vector_clock version\n                {\n#if (VERBOSE_RPC > 0)\n                    log_info(\"SERVER: merge_membership_agreement_msg_to_list: Updating status of node %s from %d to %d, because local_counter=%\" PRId64 \", proposed_counter=%\" PRId64 \".\", rs->id, rs_local->status, nd.status, local_counter, proposed_counter);\n#endif\n\n                    rs_local->status = nd.status;\n                }\n                else\n                {\n#if (VERBOSE_RPC > 0)\n                    log_info(\"SERVER: merge_membership_agreement_msg_to_list: Requesting membership ammend, because for node %s, local_status=%d, proposed_status=%d, local_counter=%\" PRId64 \", proposed_counter=%\" PRId64 \".\", rs->id, rs_local->status, nd.status, local_counter, proposed_counter);\n#endif\n\n                    memberships_differ = 1;\n                }\n            }\n        }\n    }\n\n    return memberships_differ;\n}\n\nint handle_agreement_propose_message(membership_agreement_msg * ma, membership_state ** merged_membership, membership * m, db_t * db, vector_clock * my_lc, vector_clock * prev_lc, unsigned int * fastrandstate)\n{\n#if (VERBOSE_RPC > 0)\n    char msg_buf[1024];\n    log_info(\"SERVER: Received new view proposal %s!\", to_string_membership_agreement_msg(ma, msg_buf));\n#endif\n\n    if(compare_vc(m->view_id, ma->vc) > 0)\n    {\n#if (VERBOSE_RPC > 0)\n        log_info(\"SERVER: Rejecting proposed view %s because it is older than my installed view %s!\",\n                            to_string_vc(m->view_id, msg_buf), to_string_vc(ma->vc, msg_buf));\n#endif\n\n        *merged_membership = NULL;\n\n        return PROPOSAL_STATUS_REJECTED;\n    }\n\n    // Copy local view to merged list:\n    skiplist_t * merged_list = skiplist_clone(m->local_peers, fastrandstate);\n    skiplist_t * client_merged_list = skiplist_clone(m->connected_clients, fastrandstate);\n\n    // Merge it with proposed view:\n    int memberships_differ = merge_membership_agreement_msg_to_list(ma, merged_list, m, prev_lc, fastrandstate);\n    int client_memberships_differ = merge_membership_agreement_msg_to_client_list(ma, client_merged_list, m, prev_lc, fastrandstate);\n\n    *merged_membership = get_membership_state_from_server_list(merged_list, client_merged_list, my_lc);\n\n    return (memberships_differ | client_memberships_differ)?PROPOSAL_STATUS_AMMENDED:PROPOSAL_STATUS_ACCEPTED;\n}\n\nint handle_agreement_response_message(membership_agreement_msg * ma, membership_state ** merged_membership, membership * m, db_t * db, vector_clock * my_lc, vector_clock * prev_vc, unsigned int * fastrandstate)\n{\n#if (VERBOSE_RPC > 0)\n    char msg_buf[1024];\n    log_info(\"SERVER: Received agreement response message %s, outstanding_proposal_acks=%d!\", to_string_membership_agreement_msg(ma, msg_buf), m->outstanding_proposal_acks);\n#endif\n\n    *merged_membership = NULL;\n\n    if(m->outstanding_view_id == NULL)\n    {\n#if (VERBOSE_RPC > 0)\n        log_warn(\"SERVER: Received Agreement Response message, but no outstanding view proposal is active!\");\n#endif\n        return -2;\n    }\n\n    if(m->outstanding_proposal_nonce != ma->nonce)\n    {\n#if (VERBOSE_RPC > 0)\n        log_warn(\"SERVER: Received Agreement Response message, but nonce (%\" PRId64 \") does not match outstanding view proposal nonce (%\" PRId64 \")!\",\n                            ma->nonce, m->outstanding_proposal_nonce);\n#endif\n        return -1;\n    }\n\n    m->outstanding_proposal_acks--;\n\n    assert(m->outstanding_proposal_acks >=0);\n\n    if(ma->ack_status == PROPOSAL_STATUS_ACCEPTED) // view identical with proposed one\n    {\n            if(m->outstanding_proposal_acks == 0)\n            {\n                if(m->proposal_status == PROPOSAL_STATUS_ACTIVE)\n                    m->proposal_status = PROPOSAL_STATUS_ACCEPTED; // my proposal was accepted\n\n                *merged_membership = get_membership_state_from_server_list(m->merged_responses, m->merged_client_responses, my_lc);\n                assert(*merged_membership != NULL);\n            }\n    }\n    else if(ma->ack_status == PROPOSAL_STATUS_AMMENDED)\n    {\n            int memberships_differ = merge_membership_agreement_msg_to_list(ma, m->merged_responses, m, prev_vc, fastrandstate);\n            int client_memberships_differ = merge_membership_agreement_msg_to_client_list(ma, m->merged_client_responses, m, prev_vc, fastrandstate);\n\n//          assert(memberships_differ);\n\n            if(m->proposal_status != PROPOSAL_STATUS_REJECTED)\n                m->proposal_status = PROPOSAL_STATUS_AMMENDED; // my proposal was ammended\n\n            if(m->proposal_status == PROPOSAL_STATUS_AMMENDED && m->outstanding_proposal_acks == 0)\n            {\n                *merged_membership = get_membership_state_from_server_list(m->merged_responses, m->merged_client_responses, my_lc);\n                assert(*merged_membership != NULL);\n            }\n    }\n    else\n    {\n            assert(ma->ack_status == PROPOSAL_STATUS_REJECTED);\n\n            m->proposal_status = PROPOSAL_STATUS_REJECTED; // my proposal was rejected\n    }\n\n    if((m->proposal_status == PROPOSAL_STATUS_AMMENDED || m->proposal_status == PROPOSAL_STATUS_ACCEPTED) && m->outstanding_proposal_acks == 0)\n        assert(*merged_membership != NULL);\n\n    return m->proposal_status;\n}\n\nint auto_update_group_queue_subscriptions(membership * m, db_t * db, unsigned int * fastrandstate)\n{\n    char msg_buf[4096];\n    log_debug(\"SERVER: Auto-updating actor queue mapping to groups.\");\n\n    // Update queue group membership from gossip state:\n\n    for(snode_t * crt_rts = HEAD(m->connected_clients); crt_rts!=NULL; crt_rts = NEXT(crt_rts))\n    {\n        remote_server * rts = (remote_server *) (crt_rts->value);\n\n        int rts_id = get_node_id((struct sockaddr *) &(rts->serveraddr));\n\n        int update_status = set_bucket_status(db->queue_groups, (WORD) rts_id, rts->status, &get_group_state_key, &get_group_state_live_field);\n\n        if(update_status < 0) // We just learned of this group; add it\n        {\n            log_debug(\"SERVER: auto_update_group_queue_subscriptions: Bucket %d not found, adding it\", rts_id);\n\n            group_state * new_group = get_group((WORD) rts_id);\n\n            add_bucket(db->queue_groups, new_group, &get_group_state_key, &get_group_state_live_field, fastrandstate);\n        }\n    }\n\n    if(db->queue_groups->buckets->no_items < 1) // 2\n    {\n        log_debug(\"SERVER: We only have %d groups in total, nothing to do\", db->queue_groups->buckets->no_items);\n        return 0;\n    }\n\n    // Update cached version of queue group subscriptions for all queues in all DB tables:\n\n    for(snode_t * crt_table = HEAD(db->tables); crt_table!=NULL; crt_table = NEXT(crt_table))\n    {\n        db_table_t * table = (db_table_t *) (crt_table->value);\n\n        for(snode_t * crt_queue = HEAD(table->queues); crt_queue!=NULL; crt_queue = NEXT(crt_queue))\n        {\n            db_row_t * row = (db_row_t *) (crt_queue->value);\n\n            WORD result = get_buckets_for_object(db->queue_groups, (int) row->key, db->queue_group_replication_factor,\n                                        &get_group_state_key, &get_group_state_live_field,\n                                        fastrandstate);\n\n            if(db->queue_group_replication_factor > 1 && row->group_subscriptions != NULL)\n            {\n            \tskiplist_free(row->group_subscriptions);\n            }\n\n            row->group_subscriptions = result;\n\n            if(row->group_subscriptions != NULL)\n            \tcreate_headers_for_group_subscribers(row, db, fastrandstate);\n        }\n    }\n\n    return 0;\n}\n\nint install_agreed_view(membership_agreement_msg * ma, membership * m, vector_clock * my_lc, db_t * db, unsigned int * fastrandstate)\n{\n#if (VERBOSE_RPC > -1)\n    char msg_buf[1024];\n#endif\n\n    if(compare_vc(m->view_id, ma->vc) > 0)\n    {\n#if (VERBOSE_RPC > -1)\n        log_info(\"SERVER: Skipping installing notified view %s because it is older than my installed view %s!\",\n                            to_string_vc(ma->vc, msg_buf), to_string_vc(m->view_id, msg_buf));\n#endif\n\n        return 1;\n    }\n\n    // If servers are already connected in local membership, copy their entries from there into agreed membership. Otherwise create new connections for them:\n\n    skiplist_t * new_membership = create_skiplist(&sockaddr_cmp);\n\n    int local_view_disagrees = 0;\n    struct sockaddr_in dummy_serveraddr;\n\n    for(int i=0;i<ma->membership->no_nodes;i++)\n    {\n        node_description nd = ma->membership->membership[i];\n\n        remote_server * rs = get_remote_server(nd.hostname, nd.portno, dummy_serveraddr, dummy_serveraddr, DUMMY_FD, 0, 0);\n        rs->status = nd.status;\n\n        snode_t * node = skiplist_search(m->local_peers, &rs->serveraddr);\n\n        if(node == NULL) // I just learned about this node\n        {\n            int status = connect_remote_server(rs);\n\n            if(status != 0)\n            {\n                rs->status = NODE_DEAD;\n                rs->sockfd = -1;\n                local_view_disagrees = 1;\n            }\n\n            status = add_remote_server_to_list(rs, m->local_peers, fastrandstate);\n            assert(status == 0);\n\n            status = add_remote_server_to_list(rs, new_membership, fastrandstate);\n            assert(status == 0);\n        }\n        else\n        {\n            free_remote_server(rs);\n\n            remote_server * rs_local = (remote_server *) node->value;\n\n            if(rs_local->status != nd.status) // if proposed server status is different than local one, and proposed clock is newer, use proposed status\n            {\n                int64_t local_counter = get_component_vc(my_lc, nd.node_id);\n                int64_t proposed_counter = get_component_vc(ma->vc, nd.node_id);\n\n                if(proposed_counter > local_counter)\n                {\n                    rs_local->status = nd.status;\n                }\n                else\n                {\n                    local_view_disagrees = 1;\n                }\n            }\n\n            int status = add_remote_server_to_list(rs_local, new_membership, fastrandstate);\n            assert(status == 0);\n        }\n    }\n\n    if(m->agreed_peers != NULL)\n    {\n        skiplist_free(m->agreed_peers);\n    }\n\n    m->agreed_peers = new_membership;\n\n    update_or_replace_vc(&(m->view_id), ma->vc);\n\n    if(db->enable_auto_queue_group_subscriptions)\n    {\n        auto_update_group_queue_subscriptions(m, db, fastrandstate);\n    }\n\n#if (VERBOSE_RPC > -1)\n    log_info(\"SERVER: Installed new agreed view %s, local_view_disagrees=%d\",\n                    to_string_membership_agreement_msg(ma, msg_buf),\n                    local_view_disagrees);\n#endif\n\n    return local_view_disagrees;\n}\n\n\n\nint notify_new_view_to_clients(membership * m, membership_agreement_msg * ma, vector_clock * my_lc)\n{\n    void * tmp_out_buf = NULL, * q = NULL;\n    unsigned snd_msg_len;\n    char msg_buf[1024];\n\n    membership_agreement_msg * amr = NULL;\n\n    membership_state * mstate = get_membership_state_from_server_list(m->local_peers, m->connected_clients, my_lc);\n\n    int status = get_agreement_notify_packet(PROPOSAL_STATUS_ACCEPTED, mstate, ma, &amr, &tmp_out_buf, &snd_msg_len, my_lc, my_lc);\n\n    for(snode_t * crt = HEAD(m->connected_client_sockets); crt!=NULL; crt = NEXT(crt))\n    {\n        client_descriptor * cd = (client_descriptor *) crt->value;\n\n        if(cd->sockfd == 0)\n            continue;\n\n        char client_address2[INET_ADDRSTRLEN];\n        inet_ntop( AF_INET, &(cd->addr).sin_addr, client_address2, sizeof(client_address2));\n        log_info(\"SERVER: Notifying new agreed view %s to client %s:%d, fd=%d\",\n                            to_string_membership_agreement_msg(ma, msg_buf),\n                            client_address2, ntohs(cd->addr.sin_port), cd->sockfd);\n\n        int n = write(cd->sockfd, tmp_out_buf, snd_msg_len);\n\n        if (n < 0)\n            error(\"ERROR writing to socket\");\n    }\n\n    free_membership_agreement(amr);\n\n//  free_membership_state(mstate, 0);\n\n    free(tmp_out_buf);\n\n    return 0;\n}\n\nint handle_agreement_notify_message(membership_agreement_msg * ma, membership * m, db_t * db, vector_clock * my_lc, vector_clock * prev_vc, unsigned int * fastrandstate)\n{\n    int ret = install_agreed_view(ma, m, my_lc, db, fastrandstate);\n    notify_new_view_to_clients(m, ma, my_lc);\n    return ret;\n}\n\nint handle_agreement_notify_ack_message(membership_agreement_msg * ma, membership * m, db_t * db, unsigned int * fastrandstate)\n{\n    return 0;\n}\n\nint parse_gossip_message(void * rcv_buf, size_t rcv_msg_len, membership_agreement_msg ** ma, int64_t * nonce, vector_clock ** vc)\n{\n    int status = deserialize_membership_agreement_msg(rcv_buf, rcv_msg_len, ma);\n\n    if(status == 0)\n    {\n        *nonce = (*ma)->nonce;\n        *vc = (*ma)->vc;\n\n#if (VERBOSE_RPC > 0)\n        char print_buff[PRINT_BUFSIZE];\n        to_string_membership_agreement_msg((*ma), (char *) print_buff);\n        log_info(\"Received gossip message: %s\", print_buff);\n#endif\n    }\n    else\n    {\n        *ma = NULL;\n        *vc = NULL;\n        *nonce = -1;\n    }\n\n    return status;\n}\n\nint handle_join_message(int childfd, int msg_len, membership * m, db_t * db, unsigned int * fastrandstate, vector_clock * my_lc, int old_id, int my_id, remote_server * rs)\n{\n    membership_agreement_msg * ma = NULL;\n    int64_t nonce = -1;\n    vector_clock * lc_read = NULL;\n    int local_membership_changed = 0;\n\n    int status = parse_gossip_message(in_buf + sizeof(int), msg_len, &ma, &nonce, &lc_read);\n\n    if(status != 0)\n    {\n        log_error(\"ERROR decoding server join request\");\n                return -1;\n    }\n\n    if(ma->msg_type != MEMBERSHIP_AGREEMENT_JOIN)\n    {\n        return -1;\n    }\n\n#if (VERBOSE_RPC > 0)\n    char msg_buf[1024];\n    log_info(\"SERVER: Received new join message %s!\", to_string_membership_agreement_msg(ma, msg_buf));\n#endif\n\n    // Update peer socket address to announced one:\n\n    assert(ma->membership->no_nodes == 1);\n\n    node_description nd = ma->membership->membership[0];\n    rs->status = NODE_LIVE;\n\n    status = update_listen_socket(rs, nd.hostname, nd.portno, 0);\n    assert(status == 0);\n\n    // Check if newly joined server already existed in local peers. If so, and if announced address differs, update it:\n\n    snode_t * node = skiplist_search(m->local_peers, &rs->serveraddr);\n\n    if(node != NULL)\n    {\n        remote_server * old_rs_local = (remote_server *) node->value;\n\n        if(strcmp((char *) &(rs->id), (char *) &(old_rs_local->id)) != 0)\n        {\n#if (VERBOSE_RPC > 0)\n            log_info(\"SERVER: Removing old peer entry from local_peers: %s\", old_rs_local->id);\n#endif\n            skiplist_delete(m->local_peers, &rs->serveraddr);\n\n            free_remote_server(old_rs_local);\n        }\n        else // I knew of this peer, and entry is the same. Nothing changes in local membership, except for possibly marking that node as live and updating socketfd, of node was previously dead:\n        {\n            int old_status = old_rs_local->status;\n            int new_joiner_id = get_node_id((struct sockaddr *) &(old_rs_local->serveraddr));\n\n            assert(my_id != new_joiner_id);\n\n            if(old_status == NODE_DEAD || my_id < new_joiner_id)\n            {\n                assert(old_rs_local->sockfd <= 0 || my_id < new_joiner_id);\n\n#if (VERBOSE_RPC > 0)\n                log_info(\"SERVER: Peer %s %s. Updating its sockfd from %d to %d, old_status=%d, and marking node live!\",\n                                                old_rs_local->id, (old_status == NODE_DEAD)?\"came back up\":\"sent join request\",\n                                                old_rs_local->sockfd, rs->sockfd, old_rs_local->status);\n#endif\n\n                old_rs_local->status = NODE_LIVE;\n\n                old_rs_local->sockfd = rs->sockfd;\n            }\n            else\n            {\n                assert(old_rs_local->sockfd > 0);\n\n#if (VERBOSE_RPC > 0)\n                log_debug(\"SERVER: I am already connected to peer %s (status = %d), and my id > his id. NOT updating its sockfd from %d to %d, and closing new socket!\",\n                                        old_rs_local->id, old_rs_local->status, old_rs_local->sockfd, rs->sockfd);\n#endif\n\n//              close(rs->sockfd);\n            }\n\n            return old_rs_local->status != old_status; // We s'd propose new membership if local membership changed\n        }\n    }\n\n    // Add newly joined peer to local_peers:\n\n    status = add_remote_server_to_membership(rs, m, LOCAL_PEERS, fastrandstate);\n\n    assert(status == 0);\n\n    if(ma != NULL)\n            free_membership_agreement(ma);\n\n    return 1;\n}\n\n\nint handle_server_message(int childfd, int msg_len, membership * m, db_t * db, unsigned int * fastrandstate, vector_clock * my_lc, int sender_id)\n{\n    void * tmp_out_buf = NULL;\n    unsigned snd_msg_len;\n    membership_agreement_msg * ma = NULL;\n    int64_t nonce = -1;\n    vector_clock * lc_read = NULL;\n    short output_packet = 1;\n    membership_state * merged_membership = NULL;\n\n    int status = parse_gossip_message(in_buf + sizeof(int), msg_len, &ma, &nonce, &lc_read);\n\n    if(status != 0)\n    {\n        log_error(\"ERROR decoding server gossip message\");\n                return -1;\n    }\n\n    mark_live(m, sender_id);\n\n    vector_clock * prev_vc = copy_vc(my_lc);\n\n#ifdef UPDATE_LC_ON_GOSSIP\n    if(lc_read != NULL)\n    {\n        // If we were multi-threaded, we'd have to protect this snippet:\n\n#if (VERBOSE_RPC > 2)\n        char msg_buf[1024];\n        log_debug(\"SERVER: Received server message with LC %s.\", to_string_vc(lc_read, msg_buf));\n        log_debug(\"SERVER: My LC before update is %s.\", to_string_vc(my_lc, msg_buf));\n#endif\n\n        update_vc(my_lc, lc_read);\n\n#if (VERBOSE_RPC > 2)\n        log_debug(\"SERVER: Updated local LC to %s.\", to_string_vc(my_lc, msg_buf));\n#endif\n\n        increment_vc(my_lc, m->my_id);\n\n#if (VERBOSE_RPC > 2)\n        log_debug(\"SERVER: Incremented local LC to %s.\", to_string_vc(my_lc, msg_buf));\n#endif\n    }\n#endif\n\n    switch(ma->msg_type)\n    {\n        case MEMBERSHIP_AGREEMENT_PROPOSE:\n        {\n            status = handle_agreement_propose_message(ma, &merged_membership, m, db, copy_vc(my_lc), prev_vc, fastrandstate);\n//          assert(status == 0);\n            status = get_agreement_response_packet(status, merged_membership, ma, &tmp_out_buf, &snd_msg_len, copy_vc(my_lc));\n            break;\n        }\n        case MEMBERSHIP_AGREEMENT_RESPONSE:\n        {\n            status = handle_agreement_response_message(ma, &merged_membership, m, db, copy_vc(my_lc), prev_vc, fastrandstate);\n\n            if(status < 0)\n            {\n                output_packet = 0;\n            }\n            else if(m->proposal_status == PROPOSAL_STATUS_REJECTED)\n            {\n                // NOP\n            }\n            else if(m->outstanding_proposal_acks == 0)\n            {\n                assert(merged_membership != NULL);\n\n                if(m->proposal_status == PROPOSAL_STATUS_ACCEPTED)\n                {\n                    membership_agreement_msg * amr = NULL;\n\n                    status = get_agreement_notify_packet(PROPOSAL_STATUS_ACCEPTED, merged_membership, ma, &amr, &tmp_out_buf, &snd_msg_len, copy_vc(my_lc), prev_vc);\n\n                    int local_view_disagrees = install_agreed_view(amr, m, copy_vc(my_lc), db, fastrandstate);\n\n                    notify_new_view_to_clients(m, amr, copy_vc(my_lc));\n\n                    free_membership_agreement(amr);\n\n                    //  if(local_view_disagrees)\n                    //  {\n                    //      propose_local_membership(m, copy_vc(my_lc), fastrandstate);\n                    //      output_packet = 0;\n                    //  }\n                    //\n                }\n                else if(m->proposal_status == PROPOSAL_STATUS_AMMENDED) // re-propose merged membership from previous round\n                {\n                    m->outstanding_proposal = skiplist_clone(m->merged_responses, fastrandstate);\n                    m->outstanding_proposal_clients = skiplist_clone(m->merged_client_responses, fastrandstate);\n                    m->outstanding_view_id = copy_vc(my_lc);\n                    m->outstanding_proposal_nonce = _get_nonce(fastrandstate);\n                    m->proposal_status = PROPOSAL_STATUS_ACTIVE;\n                    m->outstanding_proposal_acks = 0;\n\n                    status = get_agreement_propose_packet(0, get_membership_state_from_server_list(m->outstanding_proposal, m->outstanding_proposal_clients, copy_vc(m->outstanding_view_id)),\n                                                                m->outstanding_proposal_nonce, &tmp_out_buf, &snd_msg_len, copy_vc(m->outstanding_view_id));\n                }\n            }\n            else\n            {\n                output_packet = 0;\n            }\n            break;\n        }\n        case MEMBERSHIP_AGREEMENT_NOTIFY:\n        {\n            int local_view_disagrees = handle_agreement_notify_message(ma, m, db, copy_vc(my_lc), prev_vc, fastrandstate);\n\n//          if(local_view_disagrees)\n//              propose_local_membership(m, copy_vc(my_lc), fastrandstate);\n\n            status = get_agreement_notify_ack_packet(status, ma, &tmp_out_buf, &snd_msg_len, copy_vc(my_lc));\n            break;\n        }\n        case MEMBERSHIP_AGREEMENT_RETRY_LINK:\n        {\n            assert(0);\n            break;\n        }\n        case MEMBERSHIP_AGREEMENT_NOTIFY_ACK:\n        {\n            status = handle_agreement_notify_ack_message(ma, m, db, fastrandstate);\n//          assert(status == 0);\n            output_packet = 0;\n            break;\n        }\n    }\n\n//    assert(status == 0);\n\n    if(output_packet)\n    {\n            if(ma->msg_type == MEMBERSHIP_AGREEMENT_RESPONSE) // multicast notifications\n            {\n                assert(merged_membership != NULL);\n\n            for(snode_t * crt = HEAD(m->merged_responses); crt!=NULL; crt = NEXT(crt))\n            {\n                remote_server * rs = (remote_server *) crt->value;\n\n                if(rs->status == NODE_LIVE && rs->sockfd > 0 && get_node_id((struct sockaddr *) &(rs->serveraddr)) != m->my_id) // skip myself, and nodes that are \"down\" in membership\n                {\n                    int n = write(rs->sockfd, tmp_out_buf, snd_msg_len);\n\n                    if (n < 0)\n                        error(\"ERROR writing to socket\");\n\n                    m->outstanding_proposal_acks++;\n                }\n            }\n            }\n            else // unicast back response\n            {\n            int n = write(childfd, tmp_out_buf, snd_msg_len);\n\n            if (n < 0)\n              error(\"ERROR writing to socket\");\n            }\n\n        free(tmp_out_buf);\n    }\n\n//    if(merged_membership != NULL)\n//          free_membership_state(merged_membership);\n\n    if(ma != NULL)\n            free_membership_agreement(ma);\n\n    return 0;\n}\n\ntypedef struct argp_arguments\n{\n  int verbosity;\n  int portno;\n  int gportno;\n  char ** seeds;\n  unsigned short * seed_ports;\n  int no_seeds;\n  char * local_iface;\n  char *mon_socket_path;\n  char *log_file_path;\n} argp_arguments;\n\nerror_t parse_opt (int key, char *arg, struct argp_state *state)\n{\n    argp_arguments * arguments = (argp_arguments *) state->input;\n    char tmp_buff[10];\n\n    switch (key)\n        {\n        case 'v':\n            arguments->verbosity = 2;\n            break;\n        case 'q':\n            arguments->verbosity = 0;\n            break;\n        case 'p':\n            arguments->portno = atoi(arg);\n            break;\n        case 'm':\n            arguments->gportno = atoi(arg);\n            break;\n        case 's':\n            assert(strnlen(arg, 256) > 1);\n            arguments->no_seeds = 1;\n            for (char * end_ptr = strchr(arg, ','); end_ptr != NULL; end_ptr = strchr(end_ptr + 1, ','), arguments->no_seeds++);\n            arguments->seeds = (char **) malloc(arguments->no_seeds * sizeof(char *));\n            arguments->seed_ports = (unsigned short *) malloc(arguments->no_seeds * sizeof(int));\n            char * start_ptr = arg;\n            char * end_ptr = NULL;\n            int stop = 0;\n            for(int i = 0; !stop; i++) {\n                end_ptr = strchr(start_ptr, ',');\n\n                char * separator_ptr = strchr(start_ptr, ':');\n                assert(separator_ptr != NULL);\n                *separator_ptr = '\\0';\n\n                arguments->seeds[i] = strndup(start_ptr, separator_ptr - start_ptr);\n                arguments->seed_ports[i] = (unsigned short) atoi(separator_ptr + 1);\n\n                if(end_ptr == NULL) {\n                    stop = 1;\n                } else {\n                    *end_ptr = '\\0';\n                    start_ptr = end_ptr + 1;\n                }\n            }\n            break;\n        case 'S':\n            arguments->mon_socket_path = arg;\n            break;\n        case 'i':\n            assert(strnlen(arg, 256) > 1);\n            arguments->local_iface = strndup(arg, 256);\n            break;\n        case 'l':\n            arguments->log_file_path = arg;\n            break;\n        case ARGP_KEY_ARG:\n        case ARGP_KEY_END:\n            //        argp_usage (state);\n            break;\n        default:\n            return ARGP_ERR_UNKNOWN;\n        }\n\n    return 0;\n}\n\n\nconst char* membership_to_json (membership *m) {\n    yyjson_mut_doc *doc = yyjson_mut_doc_new(NULL);\n    yyjson_mut_val *root = yyjson_mut_obj(doc);\n    yyjson_mut_doc_set_root(doc, root);\n\n    yyjson_mut_obj_add_str(doc, root, \"name\", \"membership\");\n\n    yyjson_mut_obj_add_int(doc, root, \"pid\", pid);\n\n    struct timeval tv;\n    struct tm tm;\n    gettimeofday(&tv, NULL);\n    localtime_r(&tv.tv_sec, &tm);\n    char dt[32];    // = \"YYYY-MM-ddTHH:mm:ss.SSS+0000\";\n    strftime(dt, 32, \"%Y-%m-%dT%H:%M:%S.000%z\", &tm);\n    sprintf(dt + 20, \"%03hu%s\", (unsigned short)(tv.tv_usec / 1000), dt + 23);\n\n    yyjson_mut_obj_add_str(doc, root, \"datetime\", dt);\n\n    yyjson_mut_val *j_mbm = yyjson_mut_obj(doc);\n    yyjson_mut_obj_add_val(doc, root, \"membership\", j_mbm);\n    yyjson_mut_obj_add_int(doc, j_mbm, \"my_id\", m->my_id);\n    char view_id[1024];\n    yyjson_mut_obj_add_str(doc, j_mbm, \"view_id\", to_string_vc(m->view_id, view_id));\n\n    yyjson_mut_val *j_nodes = yyjson_mut_obj(doc);\n    yyjson_mut_obj_add_val(doc, root, \"nodes\", j_nodes);\n    for(snode_t * crt = HEAD(m->agreed_peers); crt!=NULL; crt = NEXT(crt)) {\n        remote_server * rs = (remote_server *) crt->value;\n\n        yyjson_mut_val *j_node = yyjson_mut_obj(doc);\n        yyjson_mut_obj_add_val(doc, j_nodes, rs->id, j_node);\n        yyjson_mut_obj_add_str(doc, j_node, \"type\", \"DDB\");\n        yyjson_mut_obj_add_str(doc, j_node, \"hostname\", rs->hostname);\n        yyjson_mut_obj_add_str(doc, j_node, \"status\", RS_status_name[rs->status]);\n    }\n    for(snode_t * crt = HEAD(m->connected_clients); crt!=NULL; crt = NEXT(crt)) {\n        remote_server * rs = (remote_server *) crt->value;\n\n        yyjson_mut_val *j_node = yyjson_mut_obj(doc);\n        yyjson_mut_obj_add_val(doc, j_nodes, rs->id, j_node);\n        yyjson_mut_obj_add_str(doc, j_node, \"type\", \"RTS\");\n        yyjson_mut_obj_add_str(doc, j_node, \"hostname\", rs->hostname);\n        yyjson_mut_obj_add_str(doc, j_node, \"status\", RS_status_name[rs->status]);\n    }\n\n    const char *json = yyjson_mut_write(doc, 0, NULL);\n    yyjson_mut_doc_free(doc);\n    return json;\n}\n\n\nint main(int argc, char **argv) {\n  int parentfd, gparentfd, childfd;\n  int portno, gportno;\n  unsigned int clientlen;\n  struct sockaddr_in serveraddr, gserveraddr, clientaddr;\n  struct hostent *hostp;\n  char *hostaddrp;\n  int optval; /* flag value for setsockopt */\n  int msg_len; /* message byte size */\n  fd_set readfds;\n  struct timeval timeout;\n  timeout.tv_sec = 3;\n  timeout.tv_usec = 0;\n  unsigned int seed;\n  int ret = 0;\n  char msg_buf[1024];\n  int verbosity = SERVER_VERBOSITY;\n  FILE *logf = NULL;\n\n  pid = getpid();\n\n  // Do line buffered output\n  setlinebuf(stdout);\n\n  const char *argp_program_version = \"ddb server 1.0\";\n\n  static struct argp_option options[] =\n  {\n    {\"verbose\",         'v',        0, 0,  \"Produce verbose output\" },\n    {\"quiet\",           'q',        0, 0,  \"Don't produce any output\" },\n    {\"port\",            'p',   \"PORT\", 0,  \"Port for client data requests\" },\n    {\"mon-socket-path\", 'S',   \"PATH\", 0,  \"Path to unix socket to expose mon stats\" },\n    {\"mport\",           'm',  \"MPORT\", 0,  \"Port for server gossip packets\" },\n    {\"seeds\",           's',  \"SEEDS\", 0,  \"Seeds, comma-separated\" },\n    {\"iface\",           'i',  \"IFACE\", 0,  \"Local interface to listen to\" },\n    {\"log-file\",        'l',   \"FILE\", 0,  \"Log file\" },\n    { 0 }\n  };\n\n  static struct argp argp = { options, parse_opt, NULL, \"ddb - standalone server module\" };\n\n  argp_arguments arguments;\n\n  /* Default values. */\n  arguments.verbosity = 1;\n  arguments.portno = DEFAULT_DATA_PORT;\n  arguments.gportno = -1;\n  arguments.local_iface = \"127.0.0.1\";\n  arguments.no_seeds = 0;\n  arguments.mon_socket_path = NULL;\n  arguments.log_file_path = NULL;\n\n  argp_parse (&argp, argc, argv, 0, 0, &arguments);\n\n  if (arguments.log_file_path) {\n      logf = fopen(arguments.log_file_path, \"w\");\n      if (!logf) {\n          log_error(\"Unable to open log file (%s) for writing\", arguments.log_file_path);\n          exit(1);\n      }\n      log_add_fp(logf, LOG_DEBUG); // LOG_TRACE\n      // Turn off log output on stderr\n      log_set_quiet(true);\n  }\n\n  // Ignore SIGPIPE:\n\n  struct sigaction sa;\n  memset(&sa, 0, sizeof(sa));\n\n  sa.sa_handler = SIG_IGN;\n\n  if (sigaction(SIGPIPE, &sa, NULL) == -1)\n  {\n      error(\"sigaction(SIG_IGN SIGPIPE) failed\");\n  }\n\n  portno = arguments.portno;\n  // NOTE: gossip port is expected to be +1 from the RPC port. This is a current\n  //  limitation of the gossip protocol as it doesn't carry information about a\n  //  separate gossip port.\n  if (arguments.gportno > 0) {\n      // TODO: remove this once gossip protocol carries gossip port info\n      if (arguments.gportno != arguments.portno+1)\n          log_warn(\"Using a gossip port other than RPC port + 1 is not a supported configuration\");\n      gportno = arguments.gportno;\n  } else {\n      gportno = arguments.portno+1;\n  }\n  verbosity = arguments.verbosity;\n  log_info(\"Using args: portno=%d, gportno=%d, verbosity=%d, seeds:\", portno, gportno, verbosity);\n\n  for(int i=0;i<arguments.no_seeds;i++)\n  {\n      struct hostent * host = gethostbyname(arguments.seeds[i]);\n      if (host == NULL)\n      {\n          log_error(\"ERROR, no such host %s\", arguments.seeds[i]);\n          return -1;\n      }\n\n      free(arguments.seeds[i]);\n      arguments.seeds[i] = strdup(host->h_name);\n\n      log_info(\"%s:%d\", arguments.seeds[i], arguments.seed_ports[i]);\n  }\n\n  skiplist_t * clients = create_skiplist(&sockaddr_cmp); // List of remote clients\n\n  GET_RANDSEED(&seed, 0); // thread_id\n\n  // Get db pointer:\n  db_t * db = get_db();\n\n  // Create schema:\n  ret = create_state_schema(db, &seed);\n  if (ret == 0) {\n      log_info(\"State schema successfully created\");\n  } else {\n      log_fatal(\"Failed to create state schema\");\n  }\n\n  ret = create_queue_schema(db, &seed);\n  if (ret == 0) {\n      log_info(\"Queue schema successfully created\");\n  } else {\n      log_fatal(\"Failed to create queue schema\");\n  }\n\n  struct hostent * local_iface_hostent = gethostbyname(arguments.local_iface);\n\n  // Set up main data socket:\n\n  parentfd = socket(AF_INET, SOCK_STREAM, 0);\n  if (parentfd < 0)\n    error(\"ERROR opening socket\");\n\n  optval = 1;\n  setsockopt(parentfd, SOL_SOCKET, SO_REUSEADDR, (const void *)&optval , sizeof(int));\n  bzero((char *) &serveraddr, sizeof(serveraddr));\n  serveraddr.sin_family = AF_INET;\n  serveraddr.sin_addr.s_addr = htonl(INADDR_ANY);\n  serveraddr.sin_port = htons((unsigned short) portno);\n\n  // Set up main gossip socket:\n\n  gparentfd = socket(AF_INET, SOCK_STREAM, 0);\n  if (gparentfd < 0)\n    error(\"ERROR opening gossip socket\");\n\n  setsockopt(gparentfd, SOL_SOCKET, SO_REUSEADDR, (const void *)&optval , sizeof(int));\n  bzero((char *) &gserveraddr, sizeof(serveraddr));\n  gserveraddr.sin_family = AF_INET;\n  bcopy(local_iface_hostent->h_addr_list[0], (char *)&(gserveraddr.sin_addr.s_addr), local_iface_hostent->h_length);\n//  gserveraddr.sin_addr.s_addr = htonl(INADDR_ANY);\n  gserveraddr.sin_port = htons((uint16_t) gportno);\n\n  int my_id = get_node_id((struct sockaddr *) &gserveraddr);\n  char * my_address = strdup(inet_ntoa(gserveraddr.sin_addr));\n  unsigned short my_port = (unsigned short) ntohs(gserveraddr.sin_port);\n\n  vector_clock * my_lc = init_local_vc_id(my_id);\n\n  membership * m = get_membership(my_id);\n  m->connected_client_sockets = clients;\n\n  log_info(\"Started [%s:%d, %s:%d], my_lc = %s\", inet_ntoa(serveraddr.sin_addr), ntohs(serveraddr.sin_port), my_address, my_port, to_string_vc(my_lc, msg_buf));\n\n  // Set up monitoring socket\n  int mon_sock=-1, mon_client_sock=-1;\n  struct sockaddr_un mon_addr, mon_client_addr;\n  char mon_rbuf[64];\n  size_t mon_buf_used = 0;\n  if (arguments.mon_socket_path) {\n      if ((mon_sock = socket(AF_UNIX, SOCK_STREAM, 0)) == -1) {\n          log_error(LOGPFX \"ERROR: Unable to create Monitor Socket\");\n          exit(1);\n      }\n\n      mon_addr.sun_family = AF_UNIX;\n      strcpy(mon_addr.sun_path, arguments.mon_socket_path);\n      unlink(mon_addr.sun_path);\n      if (bind(mon_sock, (struct sockaddr *)&mon_addr, sizeof(mon_addr.sun_path) + sizeof(mon_addr.sun_family)) == -1) {\n    log_error(LOGPFX \"ERROR: Unable to bind to Monitor Socket\");\n          exit(1);\n      }\n      if (listen(mon_sock, 5) == -1) {\n          log_error(LOGPFX \"ERROR: Unable to listen on Monitor Socket\");\n          exit(1);\n      }\n  }\n\n  if (bind(parentfd, (struct sockaddr *) &serveraddr, sizeof(serveraddr)) < 0)\n    error(\"ERROR on binding client socket\");\n\n  if (listen(parentfd, 100) < 0) /* allow 100 requests to queue up */\n    error(\"ERROR on listen client socket\");\n\n  if (bind(gparentfd, (struct sockaddr *) &gserveraddr, sizeof(serveraddr)) < 0)\n    error(\"ERROR on binding gossip socket\");\n\n  if (listen(gparentfd, 100) < 0) /* allow 100 requests to queue up */\n    error(\"ERROR on listen gossip socket\");\n\n  // Add myself to local membership:\n\n  remote_server * rsp = NULL;\n  ret = add_peer_to_membership(my_address, my_port, gserveraddr, OWN_FD, 0, m, LOCAL_PEERS, &rsp, &seed);\n\n  // Now add seed servers:\n\n  struct sockaddr_in dummy_serveraddr;\n\n  for(int i=0;i<arguments.no_seeds;i++)\n  {\n      int cmp_res = strncmp(arguments.seeds[i], my_address, 256);\n\n      // Skip connecting to myself:\n      if(cmp_res == 0 && arguments.seed_ports[i] == my_port)\n      {\n          log_debug(\"SERVER: Skipping connecting to seed %s:%d (myself)\", arguments.seeds[i], arguments.seed_ports[i]);\n          continue;\n      }\n\n#if (DO_HIERARCHICAL_CONNECT > 0)\n      // Also skip connecting to seed nodes with IP:port bigger (lexicographycally) than myself (they will connect to me as they come up):\n      if(cmp_res > 0 || ((cmp_res == 0) && (arguments.seed_ports[i] > my_port)) )\n      {\n          log_debug(\"SERVER: Skipping connecting to seed %s:%d (> myself)\", arguments.seeds[i], arguments.seed_ports[i]);\n      }\n      else\n      {\n#endif\n          log_debug(\"SERVER: Connecting to %s:%d..\", arguments.seeds[i], arguments.seed_ports[i]);\n          ret = add_peer_to_membership(arguments.seeds[i], arguments.seed_ports[i], dummy_serveraddr, DUMMY_FD, 1, m, LOCAL_PEERS, &rsp, &seed);\n          if(ret == 0 && rsp->status == NODE_LIVE)\n          {\n              ret = send_join_message(0, 0, my_address, my_port, my_lc, rsp, &seed);\n          }\n#if (DO_HIERARCHICAL_CONNECT > 0)\n      }\n#endif\n  }\n\n  ret = propose_local_membership(m, copy_vc(my_lc), NULL, -1, &seed);\n\n  clientlen = sizeof(clientaddr);\n\n  while(1)\n  {\n        FD_ZERO(&readfds);\n\n        // Add parent sockets to read set:\n\n        FD_SET(parentfd, &readfds);\n        FD_SET(gparentfd, &readfds);\n        int max_fd = (parentfd>gparentfd)?(parentfd):(gparentfd);\n\n        // Add active clients to read set:\n\n        for(snode_t * crt = HEAD(clients); crt!=NULL; crt = NEXT(crt))\n        {\n            client_descriptor * rs = (client_descriptor *) crt->value;\n            if(rs->sockfd > 0)\n            {\n//              log_debug(\"SERVER: Listening to client socket %s..\", rs->id);\n                FD_SET(rs->sockfd, &readfds);\n                max_fd = (rs->sockfd > max_fd)? rs->sockfd : max_fd;\n            }\n            else\n            {\n//              log_debug(\"SERVER: Not listening to disconnected client socket %s..\", rs->id);\n            }\n        }\n\n        // Add active peers to read set:\n\n        for(snode_t * crt = HEAD(m->local_peers); crt!=NULL; crt = NEXT(crt))\n        {\n            remote_server * rs = (remote_server *) crt->value;\n            if(rs->sockfd > 0)\n            {\n                if(verbosity > 3)\n                {\n                    ret = fcntl(rs->sockfd, F_GETFL);\n                    log_debug(\"active peer %s, sockfd=%d, status=%d, flags=%d\", rs->id, rs->sockfd, rs->status, ret);\n                }\n\n//              log_debug(\"SERVER: Listening to peer socket %s..\", rs->id);\n                FD_SET(rs->sockfd, &readfds);\n                max_fd = (rs->sockfd > max_fd)? rs->sockfd : max_fd;\n            }\n            else\n            {\n//              log_debug(\"SERVER: Not listening to disconnected peer socket %s..\", rs->id);\n            }\n        }\n\n        // Add active pre-joined peers to read set:\n\n        for(snode_t * crt = HEAD(m->connected_peers); crt!=NULL; crt = NEXT(crt))\n        {\n            remote_server * rs = (remote_server *) crt->value;\n            if(rs->sockfd > 0 && rs->status == NODE_PREJOINED)\n            {\n                if(verbosity > 3)\n                {\n                    ret = fcntl(rs->sockfd, F_GETFL);\n                    log_debug(\"pre-joined peer %s, sockfd=%d, status=%d, flags=%d\", rs->id, rs->sockfd, rs->status, ret);\n                }\n\n//              log_debug(\"SERVER: Listening to peer socket %s..\", rs->id);\n                FD_SET(rs->sockfd, &readfds);\n                max_fd = (rs->sockfd > max_fd)? rs->sockfd : max_fd;\n            }\n            else\n            {\n//              log_debug(\"SERVER: Not listening to disconnected peer socket %s..\", rs->id);\n            }\n        }\n\n        // Monitor socket\n        if (mon_sock > 0) {\n            FD_SET(mon_sock, &readfds);\n            max_fd = (mon_sock > max_fd)? mon_sock : max_fd;\n        }\n        if (mon_client_sock > 0) {\n            FD_SET(mon_client_sock, &readfds);\n            max_fd = (mon_client_sock > max_fd)? mon_client_sock : max_fd;\n        }\n\n        int status = select(max_fd + 1, &readfds, NULL, NULL, NULL); // &timeout\n\n        if (status < 0)\n        {\n            if ((errno != EINTR) && (errno != EBADF))\n            {\n                log_error(\"select error, errno: %d\", errno);\n                assert(0); // EINVAL, ENOMEM\n            }\n            continue;\n        }\n\n        if(verbosity > 3)\n            log_debug(\"select returned %d/%d!\", status, errno);\n\n        // Monitor socket\n        if (mon_sock > 0 && FD_ISSET(mon_sock, &readfds)) {\n            if (mon_client_sock == -1) {\n                socklen_t t = sizeof(mon_client_sock);\n                if ((mon_client_sock = accept(mon_sock, (struct sockaddr *)&mon_client_addr, &t)) == -1) {\n                    perror(\"accept\");\n                    exit(1);\n                }\n            }\n        }\n\n        // Monitor socket client requests\n        if (mon_client_sock > 0 && FD_ISSET(mon_client_sock, &readfds)) {\n            char *buf_base, *str;\n            size_t len;\n            ssize_t bytes_read = recv(mon_client_sock, &mon_rbuf[mon_buf_used], sizeof(mon_rbuf) - mon_buf_used, 0);\n            if (bytes_read <= 0) {\n                close(mon_client_sock);\n                mon_client_sock = -1;\n            } else {\n                mon_buf_used += bytes_read;\n\n                buf_base = mon_rbuf;\n                while (1) {\n                    if (mon_buf_used == 0)\n                        break;\n                    int r = netstring_read(&buf_base, &mon_buf_used, &str, &len);\n                    if (r != 0) {\n                        log_error(LOGPFX \"Mon socket: Error reading netstring: %d\", r);\n                        break;\n                    }\n\n                    if (memcmp(str, \"membership\", len) == 0) {\n                        const char *json = membership_to_json(m);\n                        char *send_buf = malloc(strlen(json)+14); // maximum digits for length is 9 (999999999) + : + ; + \\0\n                        sprintf(send_buf, \"%lu:%s,\", strlen(json), json);\n                        int send_res = send(mon_client_sock, send_buf, strlen(send_buf), 0);\n                        free((void *)json);\n                        free((void *)send_buf);\n                        if (send_res < 0) {\n                            break;\n                        }\n                    }\n                }\n\n                if (buf_base > mon_rbuf && mon_buf_used > 0)\n                    memmove(mon_rbuf, buf_base, mon_buf_used);\n            }\n        }\n\n        // Check if there's a new connection attempt from a client:\n\n        if(FD_ISSET(parentfd, &readfds))\n        {\n              childfd = accept(parentfd, (struct sockaddr *) &clientaddr, &clientlen);\n              if (childfd < 0)\n                error(\"ERROR on accept\");\n\n#ifdef MACOS\n              int option_set = 1;\n              if (setsockopt (childfd, SOL_SOCKET, SO_NOSIGPIPE, &option_set, sizeof (option_set)) < 0) {\n                  error(\"setsockopt(SO_NOSIGPIPE)\");\n              }\n#endif\n\n              hostp = gethostbyaddr((const char *)&clientaddr.sin_addr.s_addr,\n                          sizeof(clientaddr.sin_addr.s_addr), AF_INET);\n              if (hostp == NULL)\n                error(\"ERROR on gethostbyaddr\");\n              hostaddrp = strdup(inet_ntoa(clientaddr.sin_addr));\n              if (hostaddrp == NULL)\n                error(\"ERROR on inet_ntoa\");\n\n              log_info(\"SERVER: accepted connection from client: %s (%s:%d)\", hostp->h_name, hostaddrp, ntohs(clientaddr.sin_port));\n\n              ret = add_client_to_membership(clientaddr, childfd, hostaddrp, ntohs(clientaddr.sin_port), clients, &seed); // hostp->h_name\n\n//            assert(ret == 0);\n        }\n\n        // Check if there's a new connection attempt from a peer server:\n\n        if(FD_ISSET(gparentfd, &readfds))\n        {\n              childfd = accept(gparentfd, (struct sockaddr *) &clientaddr, &clientlen);\n              if (childfd < 0)\n                error(\"ERROR on accept\");\n\n#ifdef MACOS\n              int option_set = 1;\n              if (setsockopt (childfd, SOL_SOCKET, SO_NOSIGPIPE, &option_set, sizeof (option_set)) < 0) {\n                  error(\"setsockopt(SO_NOSIGPIPE)\");\n              }\n#endif\n\n              hostp = gethostbyaddr((const char *)&clientaddr.sin_addr.s_addr,\n                          sizeof(clientaddr.sin_addr.s_addr), AF_INET);\n              if (hostp == NULL)\n                error(\"ERROR on gethostbyaddr\");\n              hostaddrp = strdup(inet_ntoa(clientaddr.sin_addr));\n              if (hostaddrp == NULL)\n                error(\"ERROR on inet_ntoa\");\n\n              log_info(\"SERVER: accepted connection from peer: %s (%s:%d), sockfd=%d\", hostp->h_name, hostaddrp, ntohs(clientaddr.sin_port), childfd);\n\n              ret = add_peer_to_membership(hostaddrp, ntohs(clientaddr.sin_port), clientaddr, childfd, 0, m, CONNECTED_PEERS, &rsp, &seed); // hostp->h_name\n              rsp->status = NODE_PREJOINED;\n\n//            assert(ret == 0);\n\n              continue;\n        }\n\n        // Check if there are messages from existing clients:\n\n        for(snode_t * crt = HEAD(clients); crt!=NULL; crt = NEXT(crt))\n        {\n            client_descriptor * cd = (client_descriptor *) crt->value;\n            if(cd->sockfd > 0 && FD_ISSET(cd->sockfd , &readfds))\n            // Received a msg from this client:\n            {\n                if(read_full_packet(&(cd->sockfd), (char *) in_buf, SERVER_BUFSIZE, &msg_len, &ret, &handle_socket_close))\n                {\n                    if(ret == NODE_DEAD)\n                    {\n                        remote_server * rs = lookup_client_by_client_socket_addr(&(cd->addr), m->connected_clients);\n                        if(rs != NULL)\n                        {\n                            rs->status = NODE_DEAD;\n                            log_debug(\"Client %s, sockfd=%d, status=%d went dead, proposing new membership..\", rs->id, rs->sockfd, rs->status);\n                            propose_local_membership(m, copy_vc(my_lc), NULL, -1, &seed);\n                        }\n                    }\n                    continue;\n                }\n\n                if(handle_client_message(cd->sockfd, msg_len, db, m, clients, &seed, my_lc, my_id))\n                        continue;\n            }\n        }\n\n        // Check if there are messages from peer servers:\n\n        for(snode_t * crt = HEAD(m->local_peers); crt!=NULL; crt = NEXT(crt))\n        {\n            remote_server * rs = (remote_server *) crt->value;\n\n            if(rs->sockfd > 0 && FD_ISSET(rs->sockfd , &readfds))\n            // Received a msg from this server:\n            {\n                log_trace(\"active peer %s, sockfd=%d, status=%d is ready for reading\", rs->id, rs->sockfd, rs->status);\n\n                ret = read_full_packet(&(rs->sockfd), (char *) in_buf, SERVER_BUFSIZE, &msg_len, &(rs->status), &handle_socket_close);\n\n                if(rs->status == NODE_DEAD || rs->sockfd <= 0) // If peer closed socket, propose it removed from agreed membership\n                {\n                    propose_local_membership(m, copy_vc(my_lc), NULL, -1, &seed);\n                    continue;\n                }\n\n                int sender_id = get_node_id((struct sockaddr *) &(rs->serveraddr));\n                if(handle_server_message(rs->sockfd, msg_len, m, db, &seed, my_lc, sender_id))\n                        continue;\n            }\n        }\n\n        // Check if there are messages from pre-joined peer servers:\n\n        for(snode_t * crt = HEAD(m->connected_peers); crt!=NULL; crt = NEXT(crt))\n        {\n            remote_server * rs = (remote_server *) crt->value;\n\n            if(rs->status == NODE_PREJOINED && rs->sockfd > 0 && FD_ISSET(rs->sockfd , &readfds))\n            // Received a msg from this server:\n            {\n                log_trace(\"pre-joined peer %s, sockfd=%d, status=%d is ready for reading\", rs->id, rs->sockfd, rs->status);\n\n                ret = read_full_packet(&(rs->sockfd), (char *) in_buf, SERVER_BUFSIZE, &msg_len, &(rs->status), &handle_socket_nop);\n\n                // TO DO: If peer closed socket before it sent join packet (rs->status == NODE_DEAD || rs->sockfd <= 0), also remove it from connected list to save some space\n\n                if(ret)\n                    continue;\n\n                int sender_id = get_node_id((struct sockaddr *) &(rs->serveraddr));\n                if((ret=handle_join_message(rs->sockfd, msg_len, m, db, &seed, my_lc, sender_id, my_id, rs)) < 0)\n                {\n                    if(handle_server_message(rs->sockfd, msg_len, m, db, &seed, my_lc, sender_id))\n                        continue;\n                }\n\n\n                if(ret > 0) // local membership changed\n                {\n                    if(verbosity > 0)\n                        log_debug(\"Membership changed after %s/%d/%d joined, proposing new membership\", rs->id, rs->sockfd, rs->status);\n\n                    propose_local_membership(m, copy_vc(my_lc), NULL, -1, &seed);\n                }\n                else\n                {\n                    if(verbosity > 0)\n                        log_debug(\"Membership did not change after %s/%d/%d joined, NOT proposing new membership\", rs->id, rs->sockfd, rs->status);\n                }\n            }\n        }\n  }\n\n  // Close sockets to clients and peers:\n\n    for(snode_t * crt = HEAD(clients); crt!=NULL; crt = NEXT(crt))\n    {\n        client_descriptor * rs = (client_descriptor *) crt->value;\n        if(rs->sockfd > 0)\n        {\n            close(rs->sockfd);\n        }\n    }\n\n    for(snode_t * crt = HEAD(m->local_peers); crt!=NULL; crt = NEXT(crt))\n    {\n        remote_server * rs = (remote_server *) crt->value;\n        if(rs->sockfd > 0)\n        {\n            close(rs->sockfd);\n        }\n    }\n\n    if (logf) {\n        fclose(logf);\n    }\n}\n"
  },
  {
    "path": "backend/client_api.c",
    "content": "/*\n * Copyright (C) 2019-2021 Deutsche Telekom AG\n *\n * Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:\n *\n * 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.\n *\n * 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.\n *\n * 3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission.\n *\n * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS \"AS IS\" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n */\n\n/*\n * client_api.c\n *\n *      Author: aagapi\n */\n\n#include \"client_api.h\"\n#include \"hash_ring.h\"\n#include \"log.h\"\n\n#define GC_THREADS 1\n#include \"gc.h\"\n\nstruct dbc_stat dbc_stats;\n\nvoid zeroize_dbc_ops_stats(struct dbc_ops_stat *ops_stat, const char *name) {\n    ops_stat->name = name;\n    ops_stat->called = 0;\n    ops_stat->completed = 0;\n    ops_stat->success = 0;\n    ops_stat->error = 0;\n    ops_stat->no_quorum = 0;\n    ops_stat->time_sum = 0;\n    ops_stat->time_100ns = 0;\n    ops_stat->time_1us = 0;\n    ops_stat->time_10us = 0;\n    ops_stat->time_100us = 0;\n    ops_stat->time_1ms = 0;\n    ops_stat->time_10ms = 0;\n    ops_stat->time_100ms = 0;\n    ops_stat->time_1s = 0;\n    ops_stat->time_10s = 0;\n    ops_stat->time_100s = 0;\n    ops_stat->time_inf = 0;\n}\n\nvoid init_dbc_stats() {\n\n#define X(ops_name) \\\n    dbc_stats.ops_name = malloc(sizeof(struct dbc_ops_stat)); \\\n    zeroize_dbc_ops_stats(dbc_stats.ops_name, #ops_name);\nLIST_OF_DBC_OPS\n#undef X\n\n}\n\nvoid stat_start(struct dbc_ops_stat *ops_stat, struct timespec *ts_start) {\n    ops_stat->called++;\n\n    clock_gettime(CLOCK_MONOTONIC, ts_start);\n}\n\nvoid stat_stop(struct dbc_ops_stat *ops_stat, struct timespec *ts_start, int status) {\n    ops_stat->completed++;\n\n    struct timespec ts_stop;\n    clock_gettime(CLOCK_MONOTONIC, &ts_stop);\n    long long int diff = (ts_stop.tv_sec * 1000000000 + ts_stop.tv_nsec) - ((long long int)ts_start->tv_sec * 1000000000 + (long long int)ts_start->tv_nsec);\n\n    if      (diff < 100)              { ops_stat->time_100ns++; }\n    else if (diff < 1   * 1000)       { ops_stat->time_1us++; }\n    else if (diff < 10  * 1000)       { ops_stat->time_10us++; }\n    else if (diff < 100 * 1000)       { ops_stat->time_100us++; }\n    else if (diff < 1   * 1000000)    { ops_stat->time_1ms++; }\n    else if (diff < 10  * 1000000)    { ops_stat->time_10ms++; }\n    else if (diff < 100 * 1000000)    { ops_stat->time_100ms++; }\n    else if (diff < 1   * 1000000000) { ops_stat->time_1s++; }\n    else if (diff < (long long int)10  * 1000000000) { ops_stat->time_10s++; }\n    else if (diff < (long long int)100 * 1000000000) { ops_stat->time_100s++; }\n    else                              { ops_stat->time_inf++; }\n\n    if (status == 0) {\n        ops_stat->success++;\n    } else if (status == NO_QUORUM_ERR) {\n        ops_stat->error++;\n        ops_stat->no_quorum++;\n    } else if (status < 0) {\n        ops_stat->error++;\n    } else {\n        log_error(\"Unknown ops status %d\", status);\n        assert(0);\n    }\n}\n\nint64_t requests=0;\n\nint queue_callback_cmp(WORD e1, WORD e2)\n{\n    queue_callback_args * a1 = (queue_callback_args *) e1;\n    queue_callback_args * a2 = (queue_callback_args *) e2;\n\n    if(a1->consumer_id != a2->consumer_id)\n        return (int64_t) a1->consumer_id - (int64_t) a2->consumer_id;\n\n    if(a1->queue_id != a2->queue_id)\n        return (int64_t) a1->queue_id - (int64_t) a2->queue_id;\n\n    if(a1->table_key != a2->table_key)\n        return (int64_t) a1->table_key - (int64_t) a2->table_key;\n\n    if(a1->shard_id != a2->shard_id)\n        return (int64_t) a1->shard_id - (int64_t) a2->shard_id;\n\n    if(a1->app_id != a2->app_id)\n        return (int64_t) a1->app_id - (int64_t) a2->app_id;\n\n    return 0;\n}\n\nint queue_group_callback_cmp(WORD e1, WORD e2)\n{\n    queue_callback_args * a1 = (queue_callback_args *) e1;\n    queue_callback_args * a2 = (queue_callback_args *) e2;\n\n    if(a1->consumer_id != a2->consumer_id)\n        return (int64_t) a1->consumer_id - (int64_t) a2->consumer_id;\n\n    if(a1->group_id != a2->group_id)\n        return (int64_t) a1->group_id - (int64_t) a2->group_id;\n\n    if(a1->shard_id != a2->shard_id)\n        return (int64_t) a1->shard_id - (int64_t) a2->shard_id;\n\n    if(a1->app_id != a2->app_id)\n        return (int64_t) a1->app_id - (int64_t) a2->app_id;\n\n    return 0;\n}\n\n// Remote DB API:\n\nvoid * comm_thread_loop(void * args);\n\nremote_db_t * get_remote_db(int replication_factor, int rack_id, int dc_id, char * hostname, unsigned short local_rts_id,\n                            int no_seeds, char ** seed_hosts, int * seed_ports, unsigned int * seedptr)\n{\n    remote_db_t * db = (remote_db_t *) malloc(sizeof(remote_db_t) + 5 * sizeof(pthread_mutex_t) + sizeof(pthread_cond_t));\n    memset(db, 0, sizeof(remote_db_t) + 5 * sizeof(pthread_mutex_t) + sizeof(pthread_cond_t));\n\n    db->servers = create_skiplist(&sockaddr_cmp);\n    db->rtses = create_skiplist(&sockaddr_cmp);\n    db->actors = create_skiplist_long();\n    db->_rts_ring = get_hash_ring();\n    db->txn_state = create_skiplist_uuid();\n    db->queue_subscriptions = create_skiplist(&queue_callback_cmp);\n    db->group_queue_subscriptions = create_skiplist(&queue_group_callback_cmp);\n    db->msg_callbacks = create_skiplist_long();\n    db->subscribe_lock = (pthread_mutex_t*) ((char*) db + sizeof(remote_db_t));\n    pthread_mutex_init(db->subscribe_lock, NULL);\n    db->msg_callbacks_lock = (pthread_mutex_t*) ((char*) db + sizeof(remote_db_t) + sizeof(pthread_mutex_t));\n    pthread_mutex_init(db->msg_callbacks_lock, NULL);\n    db->lc_lock = (pthread_mutex_t*) ((char*) db + sizeof(remote_db_t) + 2 * sizeof(pthread_mutex_t));\n    pthread_mutex_init(db->lc_lock, NULL);\n    db->txn_state_lock = (pthread_mutex_t*) ((char*) db + sizeof(remote_db_t) + 3 * sizeof(pthread_mutex_t));\n    pthread_mutex_init(db->txn_state_lock, NULL);\n    db->gossip_lock = (pthread_mutex_t*) ((char*) db + sizeof(remote_db_t) + 4 * sizeof(pthread_mutex_t));\n    pthread_mutex_init(db->gossip_lock, NULL);\n    db->gossip_signal = (pthread_cond_t*) ((char*) db + sizeof(remote_db_t) + 5 * sizeof(pthread_mutex_t));\n    pthread_cond_init(db->gossip_signal, NULL);\n\n    db->replication_factor = replication_factor;\n    db->quorum_size = (int) (replication_factor / 2) + 1;\n    db->rpc_timeout = 10;\n\n    db->actor_replication_factor = 1;\n\n    db->stop_comm = 0;\n    int r = pipe(db->wakeup_pipe);\n\n#ifdef ACTON_THREADS\n    assert(pthread_create(&(db->comm_thread), NULL, comm_thread_loop, db) == 0);\n#else\n    assert(1==0 && \"DB client API not supported in single-threaded mode!\");\n#endif\n\n    db->my_lc = init_empty_vc();\n    db->current_view_id = NULL;\n\n    for(int i=0; i<no_seeds; i++)\n        add_server_to_membership(seed_hosts[i], seed_ports[i], NODE_LIVE, db, seedptr);\n\n    int status = listen_to_gossip(NODE_LIVE, rack_id, dc_id, hostname, local_rts_id, db);\n\n    return db;\n}\n\nint handle_socket_close(int * childfd)\n{\n    struct sockaddr_in address;\n    int addrlen;\n    getpeername(*childfd , (struct sockaddr*)&address,\n                (socklen_t*)&addrlen);\n    log_info(\"Host disconnected , ip %s , port %d \" ,\n          inet_ntoa(address.sin_addr) , ntohs(address.sin_port));\n\n    //Close the socket and mark as -1 in list for reuse\n    close(*childfd);\n    *childfd = -1;\n\n    return 0;\n}\n\nint install_gossiped_view(membership_agreement_msg * ma, remote_db_t * db, unsigned int * fastrandstate)\n{\n    char msg_buf[4096], msg_buf2[1024];\n\n    pthread_mutex_lock(db->gossip_lock);\n\n    if(db->current_view_id != NULL && (compare_vc(db->current_view_id, ma->vc) == VC_INCOMPARABLE ||\n                                        compare_vc(db->current_view_id, ma->vc) == VC_DISJOINT))\n    {\n#if (VERBOSE_RPC > -1)\n        log_debug(\"CLIENT: Skipping installing notified view %s because it is incomparable to my installed view %s (client is remaining sticky to previous partition)!\",\n                            to_string_vc(ma->vc, msg_buf), to_string_vc(db->current_view_id, msg_buf2));\n#endif\n\n        pthread_mutex_unlock(db->gossip_lock);\n\n        return 1;\n    }\n\n    if(db->current_view_id != NULL && compare_vc(db->current_view_id, ma->vc) > 0)\n    {\n#if (VERBOSE_RPC > -1)\n        log_debug(\"CLIENT: Skipping installing notified view %s because it is older than my installed view %s!\",\n                            to_string_vc(ma->vc, msg_buf), to_string_vc(db->current_view_id, msg_buf2));\n#endif\n\n        pthread_mutex_unlock(db->gossip_lock);\n\n        return 1;\n    }\n\n    // The local RTS might transiently be marked dead in the gossip message, or might be missing from the view altogether,\n    // in which case we should wait for the gossip to settle before installing local view.\n    // This can happen for instance if a node quickly crashes and rejoins, or if a transient partition happens\n    // and the gossip agreement round does not complete before the partition heals\n    // This leads to issue https://github.com/actonlang/acton/issues/788\n    int found_local = 0;\n    for(int i=0;i<ma->membership->no_client_nodes;i++)\n    {\n        node_description nd = ma->membership->client_membership[i];\n        if(get_node_id((struct sockaddr *) &(nd.address)) == db->local_rts_id)\n        {\n            found_local = 1;\n            if(nd.status != NODE_LIVE)\n            {\n#if (VERBOSE_RPC > -1)\n                log_debug(\"CLIENT: Skipping installing notified view %s because it transiently marks local RTS as dead.\",\n                            to_string_vc(ma->vc, msg_buf));\n#endif\n\n                pthread_mutex_unlock(db->gossip_lock);\n\n                return 1;\n            }\n        }\n    }\n\n    if(found_local == 0)\n    {\n#if (VERBOSE_RPC > -1)\n        log_debug(\"CLIENT: Skipping installing notified view %s because it transiently lacks knowledge of local RTS.\",\n                            to_string_vc(ma->vc, msg_buf));\n#endif\n\n        pthread_mutex_unlock(db->gossip_lock);\n\n        return 1;\n    }\n\n    // Add DB servers we have recently found about to client's server membership:\n    for(int i=0;i<ma->membership->no_nodes;i++)\n    {\n        node_description nd = ma->membership->membership[i];\n\n        add_server_to_membership(nd.hostname, nd.portno - 1, nd.status, db, fastrandstate);\n    }\n\n    // Add RTSs we have recently found about to client's RTS membership:\n    for(int i=0;i<ma->membership->no_client_nodes;i++)\n    {\n        node_description nd = ma->membership->client_membership[i];\n\n        add_rts_to_membership(nd.rack_id, nd.dc_id, nd.hostname, nd.portno, nd.status, db->rtses, db->_rts_ring, fastrandstate);\n    }\n\n    // Update actor placement:\n    update_actor_placement(db);\n\n    update_or_replace_vc(&(db->current_view_id), ma->vc);\n\n    pthread_mutex_unlock(db->gossip_lock);\n\n#if (VERBOSE_RPC > -1)\n    log_debug(\"CLIENT: Installed new agreed view %s\", to_string_membership_agreement_msg(ma, msg_buf));\n#endif\n\n    log_debug(\"CLIENT: RTS membership: %s\", to_string_rts_membership(db, msg_buf));\n\n    return 0;\n}\n\nvoid comm_wake_up(remote_db_t *db) {\n    // Write dummy data that wakes up the comms thread\n    int r = write(db->wakeup_pipe[1], \"!\", 1);\n}\n\nvoid * comm_thread_loop(void * args)\n{\n    remote_db_t * db = (remote_db_t *) args;\n    struct timeval timeout;\n    char in_buf[BUFSIZE];\n    int msg_len = -1;\n    int announced_msg_len = -1;\n    int read_buf_offset = 0;\n\n    while(!db->stop_comm)\n    {\n        timeout.tv_sec = 3;\n        timeout.tv_usec = 0;\n        FD_ZERO(&(db->readfds));\n        FD_SET(db->wakeup_pipe[0], &(db->readfds));\n        int max_fd = db->wakeup_pipe[0];\n\n        for(snode_t * crt = HEAD(db->servers); crt!=NULL; crt = NEXT(crt))\n        {\n            remote_server * rs = (remote_server *) crt->value;\n            if(rs->sockfd > 0)\n            {\n//              log_info(\"Listening to server socket %s..\", rs->id);\n                FD_SET(rs->sockfd, &(db->readfds));\n                max_fd = (rs->sockfd > max_fd)? rs->sockfd : max_fd;\n            }\n            else\n            {\n//              log_info(\"Not listening to disconnected server socket %s..\", rs->id);\n            }\n        }\n\n        int status = select(max_fd + 1 , &(db->readfds) , NULL , NULL , &timeout);\n\n        if (status < 0)\n        {\n            if (errno != EINTR && errno != EBADF)\n            {\n                log_error(\"select error, errno: %d\", errno);\n                assert(0); // EINVAL, ENOMEM\n            }\n            continue;\n        }\n\n        if (FD_ISSET(db->wakeup_pipe[0], &(db->readfds))) {\n            char dummy;\n            int r = read(db->wakeup_pipe[0], &dummy, 1); // Consume dummy data\n        }\n\n        for(snode_t * crt = HEAD(db->servers); crt!=NULL; crt = NEXT(crt))\n        {\n            remote_server * rs = (remote_server *) crt->value;\n            if(rs->sockfd > 0 && FD_ISSET(rs->sockfd , &(db->readfds)))\n            // Received a msg from this server:\n            {\n                int skip_parsing = 0;\n\n                while(1) // Loop until reading complete packet:\n                {\n                    assert(read_buf_offset < BUFSIZE - sizeof(int));\n\n                    if(read_buf_offset == 0)\n                    {\n                        // Read msg len header from packet:\n\n                        bzero(in_buf, BUFSIZE);\n                        msg_len = -1;\n\n                        int size_len = read(rs->sockfd, in_buf, sizeof(int));\n\n                        if (size_len < 0)\n                        {\n                            continue;\n                        }\n                        else if (size_len == 0)\n                        {\n                            handle_socket_close(&(rs->sockfd));\n                            skip_parsing = 1;\n                            break;\n                        }\n\n                        announced_msg_len = *((int *)in_buf);\n\n                        *((int *)in_buf) = 0; // 0 back buffer\n\n                        read_buf_offset = 0;\n                    }\n\n                    if(announced_msg_len <= 0)\n                    {\n                        read_buf_offset = 0;\n                        continue;\n                    }\n\n                    msg_len = read(rs->sockfd, in_buf + sizeof(int) + read_buf_offset, announced_msg_len - read_buf_offset);\n\n#if CLIENT_VERBOSITY > 1\n                    log_info(\"announced_msg_len=%d, msg_len=%d, read_buf_offset=%d\", announced_msg_len, msg_len, read_buf_offset);\n#endif\n\n                    if (msg_len < 0)\n                    {\n                        log_error(\"ERROR reading from socket\");\n                        continue;\n                    }\n                    else if(msg_len == 0) // client closed socket\n                    {\n                        handle_socket_close(&(rs->sockfd));\n                        skip_parsing = 1;\n                        break;\n                    }\n                    else if(msg_len < announced_msg_len - read_buf_offset)\n                    {\n                        read_buf_offset += msg_len;\n                        continue; // Continue reading socket until full packet length\n                    }\n\n                    break;\n                }\n\n                if(skip_parsing)\n                    continue;\n\n                if(announced_msg_len != msg_len)\n                {\n                    log_info(\"2: announced_msg_len=%d, msg_len=%d, read_buf_offset=%d\", announced_msg_len, msg_len, read_buf_offset);\n                    assert(0);\n                }\n\n                read_buf_offset = 0; // Reset\n\n#if CLIENT_VERBOSITY > 1\n                log_info(\"client received %d / %d bytes\", announced_msg_len, msg_len);\n#endif\n\n                void * tmp_out_buf = NULL, * q = NULL;\n                short msg_type;\n                short is_gossip_message;\n                db_schema_t * schema;\n                int64_t nonce = -1;\n\n                vector_clock * lc_read = NULL;\n                int status = parse_message(in_buf + sizeof(int), msg_len, &q, &msg_type, &is_gossip_message, &nonce, 0, &lc_read);\n\n                if(status != 0)\n                {\n                        log_error(\"ERROR decoding server response!\");\n                        continue;\n                        assert(0);\n                }\n\n                if(lc_read != NULL)\n                {\n                        update_lc_protected(db, lc_read);\n                        free_vc(lc_read);\n                }\n\n                if(nonce > 0) // A server reply\n                {\n                        status = add_reply_to_nonce(q, msg_type, nonce, db);\n                }\n                else if (msg_type == RPC_TYPE_QUEUE) // A queue notification\n                {\n                        // Notify local subscriber if found:\n\n                        queue_query_message * qqm = (queue_query_message *) q;\n\n                        assert(qqm->msg_type == QUERY_TYPE_QUEUE_NOTIFICATION);\n\n                        WORD notif_table_key = (WORD) qqm->cell_address->table_key;\n                        WORD notif_queue_id = (WORD) qqm->cell_address->keys[0];\n\n                        queue_callback * qc = get_queue_client_callback((WORD) qqm->consumer_id, (WORD) qqm->shard_id, (WORD) qqm->app_id, (WORD) qqm->group_id,\n                                                                        notif_table_key, notif_queue_id,\n                                                                        1, db);\n\n                        if(qc == NULL)\n                        {\n                        log_error(\"CLIENT: No local subscriber subscriber %\" PRId64 \"/%\" PRId64 \"/%\" PRId64 \" exists for queue %\" PRId64 \"/%\" PRId64 \"!\",\n                                                                        (int64_t) qqm->consumer_id, (int64_t) qqm->shard_id, (int64_t) qqm->app_id,\n                                                                        (int64_t) notif_table_key, (int64_t) notif_queue_id);\n                        continue;\n                        }\n\n                    queue_callback_args * qca = get_queue_callback_args(notif_table_key, notif_queue_id, (WORD) qqm->app_id, (WORD) qqm->shard_id, (WORD) qqm->consumer_id, (WORD) qqm->group_id, QUEUE_NOTIF_ENQUEUED);\n#if (CLIENT_VERBOSITY > 0)\n                    log_info(\"CLIENT: Attempting to notify local subscriber %\" PRId64 \" (%p/%p/%p/%p)\", (int64_t) qqm->consumer_id, qc, qc->lock, qc->signal, qc->callback);\n#endif\n\n                    status = pthread_mutex_lock(qc->lock);\n\n#if (CLIENT_LOCK_VERBOSITY > 0)\n                    log_info(\"CLIENT: Locked consumer lock of %\" PRId64 \" (%p/%p), status=%d\", (int64_t) qqm->consumer_id, qc, qc->lock, status);\n#endif\n\n                    pthread_cond_signal(qc->signal);\n                    qc->callback(qca);\n                    status = pthread_mutex_unlock(qc->lock);\n                    assert(status == 0);\n\n#if (CLIENT_LOCK_VERBOSITY > 0)\n                    log_info(\"CLIENT: Unlocked consumer lock of %\" PRId64 \" (%p/%p), status=%d\", (int64_t) qqm->consumer_id, qc, qc->lock, status);\n#endif\n\n#if (CLIENT_VERBOSITY > 0)\n                    log_info(\"CLIENT: Notified local subscriber %\" PRId64 \" (%p/%p/%p/%p)\", (int64_t) qqm->consumer_id, qc, qc->lock, qc->signal, qc->callback);\n#endif\n                }\n                else // a gossip notification\n                {\n                    assert(is_gossip_message && msg_type == MEMBERSHIP_AGREEMENT_NOTIFY);\n\n                    membership_agreement_msg * ma = (membership_agreement_msg *) q;\n\n                    assert(ma->msg_type == MEMBERSHIP_AGREEMENT_NOTIFY);\n\n                    install_gossiped_view(ma, db, &(db->fastrandstate));\n\n                    free_membership_agreement(ma);\n                }\n\n//              assert(status > 0);\n            }\n        }\n    }\n\n    return NULL;\n}\n\nint add_server_to_membership(char *hostname, int portno, int status, remote_db_t * db, unsigned int * seedptr)\n{\n    struct sockaddr_in dummy_serveraddr;\n\n    remote_server * rs = get_remote_server(hostname, portno, dummy_serveraddr, dummy_serveraddr, DUMMY_FD, 0, 0);\n    rs->status = status;\n\n    if(rs == NULL)\n    {\n        log_error(\"ERROR: Failed joining server %s:%d (DNS/network problem?)!\", hostname, portno);\n        return 1;\n    }\n\n    snode_t * prev_entry = skiplist_search(db->servers, &rs->serveraddr);\n\n    if(prev_entry != NULL)\n    {\n        log_info(\"Server address %s:%d already in membership!\", hostname, portno);\n        remote_server * prev_rems = (remote_server *) prev_entry->value;\n        if(rs->status == NODE_LIVE && (prev_rems->status == NODE_DEAD || prev_rems->sockfd <= 0))\n        {\n            // Delete previous entry, reconnect to node and update socket descriptor if we've been disconnected in the mean time:\n            log_info(\"Reconnecting to server %s:%d\", hostname, portno);\n            skiplist_delete(db->servers, &rs->serveraddr);\n        }\n        else\n        {\n            prev_rems->status = rs->status;\n            free_remote_server(rs);\n            return -1;\n        }\n    }\n\n    free_remote_server(rs);\n\n    rs = get_remote_server(hostname, portno, dummy_serveraddr, dummy_serveraddr, DUMMY_FD, 1, 0);\n\n    if((skiplist_insert(db->servers, &rs->serveraddr, rs, seedptr)) != 0)\n    {\n        log_error(\"ERROR: Error adding server address %s:%d to membership!\", hostname, portno);\n        free_remote_server(rs);\n        return -2;\n    }\n\n    if(rs->status == NODE_DEAD)\n    {\n        log_error(\"ERROR: Failed joining server %s:%d (it looks down)!\", hostname, portno);\n        return 1;\n    }\n    comm_wake_up(db);\n\n    return 0;\n}\n\nrts_descriptor * get_rts_descriptor(int rack_id, int dc_id, char *hostname, int local_rts_id, int status)\n{\n    rts_descriptor * rts_d = (rts_descriptor *) malloc(sizeof(struct rts_descriptor));\n\n    snprintf((char *) &rts_d->id, 262, \"%s/%d\", hostname, local_rts_id);\n\n    rts_d->rack_id = rack_id;\n    rts_d->dc_id = dc_id;\n    rts_d->local_rts_id = local_rts_id;\n    rts_d->status = status;\n\n    struct hostent * host = gethostbyname(hostname);\n    if (host == NULL)\n    {\n        log_error(\"ERROR, no such host %s\", hostname);\n        free_rts_descriptor(rts_d);\n        return NULL;\n    }\n\n    bzero((void *) &rts_d->addr, sizeof(struct sockaddr_in));\n    rts_d->addr.sin_family = AF_INET;\n    bcopy((char *) host->h_addr_list[0], (char *)&(rts_d->addr.sin_addr.s_addr), host->h_length);\n    rts_d->addr.sin_port = htons(local_rts_id);\n\n    rts_d->hostname = strndup(hostname, strnlen(hostname, 256) + 1);\n\n//  free(host);\n\n    return rts_d;\n}\n\nvoid free_rts_descriptor(WORD rts_d)\n{\n    free(rts_d);\n}\n\nWORD get_rts_key(WORD rts)\n{\n    return (WORD) ((rts_descriptor *) rts)->_local_rts_index;\n}\n\nWORD get_rts_live_field(WORD rts)\n{\n    return (WORD) &(((rts_descriptor *) rts)->status);\n}\n\nint add_rts_to_membership(int rack_id, int dc_id, char *hostname, int local_rts_id, int node_status,\n                            skiplist_t * rtss, hash_ring * _rts_ring,\n                            unsigned int * seedptr)\n{\n    rts_descriptor * rts_d = get_rts_descriptor(rack_id, dc_id, hostname, local_rts_id, node_status);\n\n    snode_t * prev_entry = skiplist_search(rtss, &(rts_d->addr));\n    if(prev_entry != NULL)\n    {\n        log_debug(\"RTS address %s:%d already in membership, updating status and metadata!\", hostname, local_rts_id);\n        rts_descriptor * prev_descriptor = (rts_descriptor *) prev_entry->value;\n        prev_descriptor->status = rts_d->status;\n        prev_descriptor->rack_id = rts_d->rack_id;\n        prev_descriptor->dc_id = rts_d->dc_id;\n        free_rts_descriptor(rts_d);\n        return -1;\n    }\n    rts_d->_local_rts_index = get_node_id((struct sockaddr *) &(rts_d->addr)); // rtss->no_items;\n\n    int status = skiplist_insert(rtss, &(rts_d->addr), rts_d, seedptr);\n\n    if(status != 0)\n    {\n        log_debug(\"ERROR: Error adding RTS %s:%d to membership!\", hostname, local_rts_id);\n        free_rts_descriptor(rts_d);\n        return -2;\n    }\n\n    // Update RTS consistent hashing ring used for actor placement:\n\n    status = add_bucket(_rts_ring, (WORD) rts_d, &get_rts_key, &get_rts_live_field, seedptr);\n\n    assert(status == 0);\n\n    log_debug(\"Added RTS %s:%d - %d to membership!\", hostname, local_rts_id, rts_d->_local_rts_index);\n\n    return 0;\n}\n\nchar * to_string_rts_membership(remote_db_t * db, char * msg_buff)\n{\n    char * crt_ptr = msg_buff;\n    sprintf(crt_ptr, \"RTS_membership(\");\n    crt_ptr += strlen(crt_ptr);\n\n    for(snode_t * crt = HEAD(db->rtses); crt!=NULL; crt = NEXT(crt))\n    {\n        rts_descriptor * nd = (rts_descriptor *) crt->value;\n        sprintf(crt_ptr, \"RTS(status=%d, rack_id=%d, dc_id=%d, hostname=%s, rts_id=%d, local_index=%d)\", nd->status, nd->rack_id, nd->dc_id,\n                            (nd->hostname != NULL)?(nd->hostname):\"NULL\",\n                            nd->local_rts_id, nd->_local_rts_index);\n        crt_ptr += strlen(crt_ptr);\n        sprintf(crt_ptr, \", \");\n        crt_ptr += 2;\n    }\n\n    sprintf(crt_ptr, \")\");\n\n    return msg_buff;\n}\n\n\nactor_descriptor * get_actor_descriptor(long actor_id, rts_descriptor * host_rts, int is_local, int status)\n{\n    actor_descriptor * a = (actor_descriptor *) malloc(sizeof(struct actor_descriptor));\n    a->actor_id = actor_id;\n    a->host_rts = host_rts;\n    a->is_local = is_local;\n    a->status = status;\n    return a;\n}\n\nvoid free_actor_descriptor(actor_descriptor * a)\n{\n    free(a);\n}\n\nskiplist_t * get_rtses_for_actor(long actor_id, remote_db_t * db)\n{\n    if(db->_rts_ring->live_buckets == 0)\n        return NULL;\n\n    if(db->actor_replication_factor == 1)\n    {\n        skiplist_t * result = create_skiplist_long();\n        rts_descriptor * rts_d = (rts_descriptor *) get_buckets_for_object(db->_rts_ring, (int) actor_id, 1,\n                                                                            &get_rts_key, &get_rts_live_field, &(db->fastrandstate));\n        skiplist_insert(result, (WORD) rts_d->_local_rts_index, rts_d, &(db->fastrandstate));\n        return result;\n    }\n\n    return get_buckets_for_object(db->_rts_ring, (int) actor_id, db->actor_replication_factor,\n                                    &get_rts_key, &get_rts_live_field, &(db->fastrandstate));\n}\n\nrts_descriptor * get_first_rts_for_actor(long actor_id, remote_db_t * db)\n{\n    if(db->_rts_ring->live_buckets == 0)\n        return NULL;\n\n    return (rts_descriptor *) get_buckets_for_object(db->_rts_ring, (int) actor_id, 1,\n            &get_rts_key, &get_rts_live_field, &(db->fastrandstate));\n}\n\nskiplist_t * get_local_actors(remote_db_t * db)\n{\n    skiplist_t * result = create_skiplist_long();\n    int status = 0;\n\n    for(snode_t * crt = HEAD(db->actors); crt!=NULL; crt = NEXT(crt))\n    {\n        actor_descriptor * a = (actor_descriptor *) crt->value;\n        if(a->is_local)\n        {\n            status = skiplist_insert(result, (WORD) a->actor_id, a, &(db->fastrandstate));\n\n            assert(status == 0);\n        }\n    }\n\n    return result;\n}\n\nskiplist_t * get_remote_actors(remote_db_t * db)\n{\n    skiplist_t * result = create_skiplist_long();\n    int status = 0;\n\n    for(snode_t * crt = HEAD(db->actors); crt!=NULL; crt = NEXT(crt))\n    {\n        actor_descriptor * a = (actor_descriptor *) crt->value;\n        if(!a->is_local)\n        {\n            status = skiplist_insert(result, (WORD) a->actor_id, a, &(db->fastrandstate));\n\n            assert(status == 0);\n        }\n    }\n\n    return result;\n}\n\nint is_actor_local(long actor_id, remote_db_t * db)\n{\n    int host_id = -1;\n\n    if(db->actor_replication_factor == 1)\n    {\n        rts_descriptor * host_rts = get_first_rts_for_actor(actor_id, db);\n\n        assert(host_rts != NULL);\n\n        host_id = get_node_id((struct sockaddr *) &(host_rts->addr));\n\n        return (host_id == db->local_rts_id);\n    }\n    else\n    {\n        skiplist_t * rtses = get_rtses_for_actor(actor_id, db);\n        for(snode_t * crt = HEAD(rtses); crt!=NULL; crt = NEXT(crt))\n        {\n            rts_descriptor * rts_d = (rts_descriptor *) crt->value;\n            host_id = get_node_id((struct sockaddr *) &(rts_d->addr));\n            if(host_id == db->local_rts_id)\n                return 1;\n        }\n        return 0;\n    }\n}\n\nint update_actor_placement(remote_db_t * db)\n{\n    char msg_buf[4096];\n\n    log_debug(\"CLIENT: Updating actor placement. Previous actor membership: %s\", to_string_actor_membership(db, msg_buf));\n\n    int host_id = -1;\n    for(snode_t * crt = HEAD(db->actors); crt!=NULL; crt = NEXT(crt))\n    {\n        actor_descriptor * a = (actor_descriptor *) crt->value;\n\n        if(db->actor_replication_factor == 1)\n        {\n            rts_descriptor * first_rts = get_first_rts_for_actor(a->actor_id, db);\n\n            assert(first_rts != NULL);\n\n            a->host_rts = first_rts;\n\n            a->is_local = (first_rts->_local_rts_index == db->local_rts_id);\n        }\n        else\n        {\n            skiplist_t * rtses = get_rtses_for_actor(a->actor_id, db);\n            int replica_no = 0;\n            a->is_local = 0;\n            for(snode_t * crt = HEAD(rtses); crt!=NULL; crt = NEXT(crt))\n            {\n                rts_descriptor * rts_d = (rts_descriptor *) crt->value;\n                host_id = get_node_id((struct sockaddr *) &(rts_d->addr));\n                if(host_id == db->local_rts_id)\n                    a->is_local = 1;\n                if(replica_no == 0)\n                {\n                    a->host_rts = rts_d;\n                }\n                replica_no++;\n            }\n        }\n    }\n\n    log_debug(\"CLIENT: Actor membership: %s\", to_string_actor_membership(db, msg_buf));\n\n    return 0;\n}\n\nint add_actor_to_membership(long actor_id, remote_db_t * db)\n{\n    char msg_buf[4096];\n\n    log_debug(\"Adding actor %ld to membership!\", actor_id);\n\n    actor_descriptor * a = get_actor_descriptor(actor_id, NULL, 1, ACTOR_STATUS_RUNNING);\n\n    snode_t * prev_entry = skiplist_search(db->actors, (WORD) a->actor_id);\n    if(prev_entry != NULL)\n    {\n        log_debug(\"Actor %ld was already added to membership, skipping.\\n\", a->actor_id);\n        return -1;\n    }\n\n    int status = skiplist_insert(db->actors, (WORD) a->actor_id, a, &(db->fastrandstate));\n\n    if(status != 0)\n    {\n        log_debug(\"ERROR: Error adding actor %ld to membership!\\n\", a->actor_id);\n        free_actor_descriptor(a);\n        return -2;\n    }\n\n    a->host_rts = get_first_rts_for_actor(actor_id, db);\n\n    if(a->host_rts != NULL)\n    {\n        int host_id = get_node_id((struct sockaddr *) &(a->host_rts->addr));\n        a->is_local = (host_id == db->local_rts_id);\n    }\n    else // RTS node has not installed a gossiped view yet, consider actors local until it does\n    {\n            a->is_local = 1;\n    }\n\n    log_debug(\"Added actor %ld to membership!\", a->actor_id);\n\n    log_debug(\"CLIENT: Actor membership: %s\", to_string_actor_membership(db, msg_buf));\n\n    return 0;\n}\n\nchar * to_string_actor_membership(remote_db_t * db, char * msg_buff)\n{\n    char * crt_ptr = msg_buff;\n    sprintf(crt_ptr, \"actor_membership(\");\n    crt_ptr += strlen(crt_ptr);\n\n    for(snode_t * crt = HEAD(db->actors); crt!=NULL; crt = NEXT(crt))\n    {\n        actor_descriptor * a = (actor_descriptor *) crt->value;\n        sprintf(crt_ptr, \"Actor(actor_id=%ld, rts=%s:%d, rts_index=%d, rack_id=%d, dc_id=%d, status=%d)\",\n                        a->actor_id,\n                        (a->host_rts != NULL && a->host_rts->hostname != NULL)?(a->host_rts->hostname):\"local\",\n                        (a->host_rts != NULL)?a->host_rts->local_rts_id:-1,\n                        (a->host_rts != NULL)?a->host_rts->_local_rts_index:-1,\n                        (a->host_rts != NULL)?a->host_rts->rack_id:-1,\n                        (a->host_rts != NULL)?a->host_rts->dc_id:-1,\n                        a->status);\n        crt_ptr += strlen(crt_ptr);\n        sprintf(crt_ptr, \", \");\n        crt_ptr += 2;\n    }\n\n    sprintf(crt_ptr, \")\");\n\n    return msg_buff;\n}\n\n\n\nmsg_callback * add_msg_callback(int64_t nonce, void (*callback)(void *), remote_db_t * db)\n{\n    pthread_mutex_lock(db->msg_callbacks_lock);\n\n    snode_t * node = skiplist_search(db->msg_callbacks, (WORD) nonce);\n\n    assert(node != NULL);\n    assert(node->value == (WORD) 1);\n\n    msg_callback * mc = get_msg_callback(nonce, NULL, callback, db->replication_factor);\n\n    skiplist_insert(db->msg_callbacks, (WORD) nonce, mc, &(db->fastrandstate));\n\n    snode_t * node2 = skiplist_search(db->msg_callbacks, (WORD) nonce);\n\n    assert(node2->value == mc);\n\n    pthread_mutex_unlock(db->msg_callbacks_lock);\n\n    return mc;\n}\n\nint add_reply_to_nonce(void * reply, short reply_type, int64_t nonce, remote_db_t * db)\n{\n    int ret = 0;\n\n    pthread_mutex_lock(db->msg_callbacks_lock);\n\n    snode_t * node = skiplist_search(db->msg_callbacks, (WORD) nonce);\n\n    if(node == NULL || node->value == (WORD) 1)\n    {\n        pthread_mutex_unlock(db->msg_callbacks_lock);\n\n//      log_info(\"Nonce %\" PRId64 \" not found!\", nonce);\n\n        return -1;\n    }\n\n    msg_callback * mc = (msg_callback *) node->value;\n\n    int no_replies = add_reply_to_msg_callback(reply, reply_type, mc);\n\n    if(no_replies < 0)\n    {\n        pthread_mutex_unlock(db->msg_callbacks_lock);\n        return no_replies;\n    }\n\n    // Signal consumer if a quorum of replies have arrived:\n    if(no_replies >= db->quorum_size)\n    {\n        ret = pthread_mutex_lock(mc->lock);\n        pthread_cond_signal(mc->signal);\n        if((mc->callback) != NULL)\n        {\n//          log_debug(\"mc = %p, mc->callback = %p, calling..\", mc, mc->callback);\n            (mc->callback)(NULL);\n        }\n        ret = pthread_mutex_unlock(mc->lock);\n    }\n\n    pthread_mutex_unlock(db->msg_callbacks_lock);\n\n    return no_replies;\n}\n\nint delete_msg_callback(int64_t nonce, remote_db_t * db)\n{\n    pthread_mutex_lock(db->msg_callbacks_lock);\n\n    snode_t * node = skiplist_search(db->msg_callbacks, (WORD) nonce);\n\n    if(node == NULL)\n    {\n        pthread_mutex_unlock(db->msg_callbacks_lock);\n\n        return 1;\n    }\n\n    msg_callback * mc = (msg_callback *) node->value;\n\n    skiplist_delete(db->msg_callbacks, (WORD) nonce);\n\n    free_msg_callback(mc);\n\n    pthread_mutex_unlock(db->msg_callbacks_lock);\n\n    return 0;\n}\n\nint64_t _get_nonce(remote_db_t * db)\n{\n#ifdef RANDOM_NONCES\n    unsigned int randno1, randno2;\n    int64_t randlong;\n    FASTRAND(&(db->fastrandstate), randno1);\n    FASTRAND(&(db->fastrandstate), randno2);\n    return ((int64_t) randno1 << 32) | ((int64_t) randno2 & 0xFFFFFFFFL);\n#else\n    return ++requests;\n#endif\n}\n\nint64_t get_nonce(remote_db_t * db)\n{\n    int64_t nonce = -1;\n    snode_t * node = (snode_t *) 1;\n\n    while(node != NULL)\n    {\n        nonce = _get_nonce(db);\n        pthread_mutex_lock(db->msg_callbacks_lock);\n        node = skiplist_search(db->msg_callbacks, (WORD) nonce);\n        if(node == NULL)\n        {\n            skiplist_insert(db->msg_callbacks, (WORD) nonce, (WORD) 1, &(db->fastrandstate));\n        }\n        pthread_mutex_unlock(db->msg_callbacks_lock);\n    }\n\n    return nonce;\n}\n\nvector_clock * get_and_increment_lc(remote_db_t * db, int node_id)\n{\n    pthread_mutex_lock(db->lc_lock);\n\n    vector_clock * vc = copy_vc(db->my_lc);\n\n    increment_vc(db->my_lc, node_id);\n\n    pthread_mutex_unlock(db->lc_lock);\n\n    return vc;\n}\n\nvector_clock * get_lc(remote_db_t * db)\n{\n    return copy_vc(db->my_lc);\n}\n\nint update_lc_protected(remote_db_t * db, vector_clock * vc_in)\n{\n    pthread_mutex_lock(db->lc_lock);\n\n    int ret = update_vc(db->my_lc, vc_in);\n\n    pthread_mutex_unlock(db->lc_lock);\n\n    return ret;\n}\n\nint close_remote_db(remote_db_t * db)\n{\n    db->stop_comm = 1;\n#ifdef ACTON_THREADS\n    pthread_join(db->comm_thread, NULL);\n#endif\n\n    for(snode_t * crt = HEAD(db->servers); crt!=NULL; crt = NEXT(crt))\n    {\n        remote_server * rs = (remote_server *) crt->value;\n        close(rs->sockfd);\n    }\n\n    return free_remote_db(db);\n}\n\nint free_remote_db(remote_db_t * db)\n{\n    skiplist_free_val(db->servers, &free_remote_server_ptr);\n    skiplist_free(db->txn_state);\n    skiplist_free(db->queue_subscriptions);\n    skiplist_free(db->group_queue_subscriptions);\n    free_hash_ring(db->_rts_ring, NULL);\n    skiplist_free_val(db->rtses, &free_rts_descriptor);\n    skiplist_free(db->actors);\n    free(db);\n    free_vc(db->my_lc);\n    return 0;\n}\n\n// Comm fctns:\n\n/*\n * error - wrapper for perror\n */\nvoid error(char *msg) {\n    perror(msg);\n}\n\nint send_packet(void * buf, unsigned len, int sockfd)\n{\n    assert(sockfd != 0);\n    int n = write(sockfd, buf, len);\n    if (n < 0)\n    {\n        error(\"ERROR writing to socket\");\n    }\n    else\n    {\n#if CLIENT_VERBOSITY > 2\n        log_info(\"Wrote %d bytes to socket\", n);\n#endif\n    }\n\n    return 0;\n}\n\nint send_packet_wait_reply(void * out_buf, unsigned out_len, int sockfd, void * in_buf, unsigned in_buf_size, int * in_len)\n{\n    int ret = send_packet(out_buf, out_len, sockfd);\n\n    if(ret != 0)\n        return ret;\n\n    bzero(in_buf, in_buf_size);\n    *in_len = -1;\n    while(*in_len < 0)\n    {\n        *in_len = read(sockfd, in_buf, BUFSIZE);\n        if (*in_len < 0)\n            error(\"ERROR reading from socket\");\n        else\n        {\n#if CLIENT_VERBOSITY > 2\n            log_info(\"Read %d bytes from socket\", *in_len);\n#endif\n        }\n    }\n\n    return 0;\n}\n\nint wait_on_msg_callback(msg_callback * mc, remote_db_t * db)\n{\n    if(mc == NULL)\n    {\n        assert(0);\n\n        return NO_SUCH_MSG_CALLBACK;\n    }\n\n    // Wait for signal from comm thread. It will come when 'db->quorum_size' replies have arrived on that nonce:\n\n    int ret = pthread_mutex_lock(mc->lock);\n\n    if(mc->no_replies >= db->quorum_size)\n    // Enough replies arrived already\n    {\n        pthread_mutex_unlock(mc->lock);\n        return 0;\n    }\n\n    struct timespec ts;\n    clock_gettime(CLOCK_REALTIME, &ts);\n    ts.tv_sec += db->rpc_timeout;\n    ret = pthread_cond_timedwait(mc->signal, mc->lock, &ts);\n\n    pthread_mutex_unlock(mc->lock);\n\n    if(ret != 0 && ret != ETIMEDOUT)\n    {\n        log_info(\"pthread_cond_timedwait returned %d/%d\", ret, errno);\n        assert(0);\n    }\n\n    return 0;\n}\n\nint send_packet_wait_replies_async(void * out_buf, unsigned out_len, int64_t nonce, msg_callback ** mc, remote_db_t * db)\n{\n    int ret = 0;\n    *mc = add_msg_callback(nonce, NULL, db);\n    assert (*mc != NULL);\n    assert (*mc != (WORD) 1);\n\n    for(snode_t * server_node = HEAD(db->servers); server_node!=NULL; server_node=NEXT(server_node))\n    {\n        remote_server * rs = (remote_server *) server_node->value;\n        if (rs->status != NODE_LIVE || rs->sockfd <= 0)\n            continue;\n#if SYNC_SOCKET > 0\n        pthread_mutex_lock(rs->sockfd_lock);\n#endif\n        ret = send_packet(out_buf, out_len, rs->sockfd);\n#if SYNC_SOCKET > 0\n        pthread_mutex_unlock(rs->sockfd_lock);\n#endif\n        if(ret != 0)\n        {\n            assert(0);\n#if CLIENT_VERBOSITY > 0\n            log_error(\"Server %s seems down.\", rs->id);\n#endif\n        }\n    }\n\n    return 0;\n}\n\nint send_packet_wait_replies_sync(void * out_buf, unsigned out_len, int64_t nonce, msg_callback ** mc, remote_db_t * db)\n{\n    int ret = send_packet_wait_replies_async(out_buf, out_len, nonce, mc, db);\n\n    if(ret != 0)\n        return ret;\n\n    // Wait for signal from comm thread. It will come when 'db->quorum_size' replies have arrived on that nonce:\n    return wait_on_msg_callback(*mc, db);\n}\n\n\n// Write ops:\n\nint remote_insert_in_txn(WORD * column_values, int no_cols, int no_primary_keys, int no_clustering_keys, WORD blob, size_t blob_size,\n                        WORD table_key, int * minority_status, uuid_t * txnid, remote_db_t * db)\n{\n    struct timespec ts_start;\n    stat_start(dbc_stats.remote_insert_in_txn, &ts_start);\n\n    unsigned len = 0;\n    void * tmp_out_buf = NULL;\n    *minority_status = 0;\n\n#if (DEBUG_BLOBS > 0)\n    size_t print_size = 256 + no_cols * sizeof(long) + blob_size;\n    char * printbuf = (char *) malloc(print_size);\n    char * crt_ptr = printbuf;\n    sprintf(crt_ptr, \"cols={\");\n    crt_ptr += strlen(crt_ptr);\n    for(int i=0;i<no_cols;i++)\n    {\n        sprintf(crt_ptr, \"%ld, \", (long) column_values[i]);\n        crt_ptr += strlen(crt_ptr);\n    }\n    sprintf(crt_ptr, \"}, blob(%d)={\", blob_size);\n    crt_ptr += strlen(crt_ptr);\n    if(blob_size > 0)\n    {\n        for(int i=0;i<blob_size / sizeof(long);i++)\n        {\n            sprintf(crt_ptr, \"%lu \", *((long *)blob + i));\n            crt_ptr += strlen(crt_ptr);\n        }\n    }\n    sprintf(crt_ptr, \"}\");\n    crt_ptr += strlen(crt_ptr);\n    log_info(\"remote_insert_in_txn: %s\", printbuf);\n    free(printbuf);\n#endif\n\n    write_query * wq = build_insert_in_txn(column_values, no_cols, no_primary_keys, no_clustering_keys, blob, blob_size, table_key, txnid, get_nonce(db));\n    int success = serialize_write_query(wq, (void **) &tmp_out_buf, &len, 1, NULL);\n\n    if(db->servers->no_items < db->quorum_size)\n    {\n        log_error(\"Not enough servers configured for quorum (%d/%d servers configured)\", db->servers->no_items, db->replication_factor);\n        stat_stop(dbc_stats.remote_insert_in_txn, &ts_start, NO_QUORUM_ERR);\n        return NO_QUORUM_ERR;\n    }\n    remote_server * rs = (remote_server *) (HEAD(db->servers))->value;\n\n#if CLIENT_VERBOSITY > 0\n    char print_buff[1024];\n    to_string_write_query(wq, (char *) print_buff);\n    log_info(\"Sending write query to server %s: %s\", rs->id, print_buff);\n#endif\n\n    // Send packet to server and wait for reply:\n\n    msg_callback * mc = NULL;\n    success = send_packet_wait_replies_sync(tmp_out_buf, len, wq->nonce, &mc, db);\n    assert(success == 0);\n    free_write_query(wq);\n\n    if(mc->no_replies < db->quorum_size)\n    {\n        log_error(\"No quorum (%d/%d replies received)\", mc->no_replies, db->replication_factor);\n        delete_msg_callback(mc->nonce, db);\n        stat_stop(dbc_stats.remote_insert_in_txn, &ts_start, NO_QUORUM_ERR);\n        return NO_QUORUM_ERR;\n    }\n\n    int ok_status = 0;\n\n    for(int i=0;i<mc->no_replies;i++)\n    {\n        ack_message * ack = (ack_message *) mc->replies[i];\n        if(ack->status == 0)\n            ok_status++;\n        else\n            *minority_status = ack->status;\n\n#if CLIENT_VERBOSITY > 0\n        to_string_ack_message(ack, (char *) print_buff);\n        log_info(\"Got back response from server %s: %s\", rs->id, print_buff);\n#endif\n    }\n\n    if(ok_status < db->quorum_size)\n    {\n        log_error(\"No valid quorum (%d/%d valid replies received, minority_status=%d)\", ok_status, db->replication_factor, *minority_status);\n        delete_msg_callback(mc->nonce, db);\n        stat_stop(dbc_stats.remote_insert_in_txn, &ts_start, NO_QUORUM_ERR);\n        return NO_QUORUM_ERR;\n    }\n\n    delete_msg_callback(mc->nonce, db);\n\n    stat_stop(dbc_stats.remote_insert_in_txn, &ts_start, 0);\n    return 0;\n}\n\nint remote_update_in_txn(int * col_idxs, int no_cols, WORD * column_values, WORD blob, size_t blob_size, WORD table_key, int * minority_status, uuid_t * txnid, remote_db_t * db)\n{\n    assert (0); // Not supported\n    return 0;\n}\n\nint remote_delete_row_in_txn(WORD * column_values, int no_primary_keys, WORD table_key,\n                            int * minority_status, uuid_t * txnid, remote_db_t * db)\n{\n    struct timespec ts_start;\n    stat_start(dbc_stats.remote_delete_row_in_txn, &ts_start);\n    *minority_status = 0;\n\n    unsigned len = 0;\n    write_query * wq = build_delete_row_in_txn(column_values, no_primary_keys, table_key, txnid, get_nonce(db));\n    void * tmp_out_buf = NULL;\n    int success = serialize_write_query(wq, (void **) &tmp_out_buf, &len, 1, NULL);\n\n    if(db->servers->no_items < db->quorum_size)\n    {\n        log_error(\"No quorum (%d/%d servers alive)\", db->servers->no_items, db->replication_factor);\n        stat_stop(dbc_stats.remote_delete_row_in_txn, &ts_start, NO_QUORUM_ERR);\n        return NO_QUORUM_ERR;\n    }\n    remote_server * rs = (remote_server *) (HEAD(db->servers))->value;\n\n#if CLIENT_VERBOSITY > 0\n    char print_buff[1024];\n    to_string_write_query(wq, (char *) print_buff);\n    log_info(\"Sending delete row query to server %s: %s\", rs->id, print_buff);\n#endif\n\n    // Send packet to server and wait for reply:\n\n    msg_callback * mc = NULL;\n    success = send_packet_wait_replies_sync(tmp_out_buf, len, wq->nonce, &mc, db);\n    assert(success == 0);\n    free_write_query(wq);\n\n    if(mc->no_replies < db->quorum_size)\n    {\n        log_error(\"No quorum (%d/%d replies received)\", mc->no_replies, db->replication_factor);\n        delete_msg_callback(mc->nonce, db);\n        stat_stop(dbc_stats.remote_delete_row_in_txn, &ts_start, NO_QUORUM_ERR);\n        return NO_QUORUM_ERR;\n    }\n\n    int ok_status = 0;\n\n    for(int i=0;i<mc->no_replies;i++)\n    {\n        assert(mc->reply_types[i] == RPC_TYPE_ACK);\n        ack_message * ack = (ack_message *) mc->replies[i];\n        if(ack->status == 0)\n            ok_status++;\n        else\n            *minority_status = ack->status;\n\n#if CLIENT_VERBOSITY > 0\n        to_string_ack_message(ack, (char *) print_buff);\n        log_info(\"Got back response from server %s: %s\", rs->id, print_buff);\n#endif\n    }\n\n    if(ok_status < db->quorum_size)\n    {\n        log_error(\"No valid quorum (%d/%d valid replies received, minority_status=%d)\", ok_status, db->replication_factor, *minority_status);\n        delete_msg_callback(mc->nonce, db);\n        stat_stop(dbc_stats.remote_delete_row_in_txn, &ts_start, NO_QUORUM_ERR);\n        return NO_QUORUM_ERR;\n    }\n\n    delete_msg_callback(mc->nonce, db);\n\n    stat_stop(dbc_stats.remote_delete_row_in_txn, &ts_start, 0);\n    return 0;\n}\n\nint remote_delete_cell_in_txn(WORD * column_values, int no_primary_keys, int no_clustering_keys, WORD table_key,\n                                int * minority_status, uuid_t * txnid, remote_db_t * db)\n{\n    struct timespec ts_start;\n    stat_start(dbc_stats.remote_delete_cell_in_txn, &ts_start);\n    *minority_status = 0;\n\n    unsigned len = 0;\n    write_query * wq = build_delete_cell_in_txn(column_values, no_primary_keys, no_clustering_keys, table_key, txnid, get_nonce(db));\n    void * tmp_out_buf = NULL;\n    int success = serialize_write_query(wq, (void **) &tmp_out_buf, &len, 1, NULL);\n\n    if(db->servers->no_items < db->quorum_size)\n    {\n        log_error(\"No quorum (%d/%d servers alive)\", db->servers->no_items, db->replication_factor);\n        stat_stop(dbc_stats.remote_delete_cell_in_txn, &ts_start, NO_QUORUM_ERR);\n        return NO_QUORUM_ERR;\n    }\n    remote_server * rs = (remote_server *) (HEAD(db->servers))->value;\n\n#if CLIENT_VERBOSITY > 0\n    char print_buff[1024];\n    to_string_write_query(wq, (char *) print_buff);\n    log_info(\"Sending delete cell query to server %s: %s\", rs->id, print_buff);\n#endif\n\n    // Send packet to server and wait for reply:\n\n    msg_callback * mc = NULL;\n    success = send_packet_wait_replies_sync(tmp_out_buf, len, wq->nonce, &mc, db);\n    assert(success == 0);\n    free_write_query(wq);\n\n    if(mc->no_replies < db->quorum_size)\n    {\n        log_error(\"No quorum (%d/%d replies received)\", mc->no_replies, db->replication_factor);\n        delete_msg_callback(mc->nonce, db);\n        stat_stop(dbc_stats.remote_delete_cell_in_txn, &ts_start, NO_QUORUM_ERR);\n        return NO_QUORUM_ERR;\n    }\n\n    int ok_status = 0;\n\n    for(int i=0;i<mc->no_replies;i++)\n    {\n        assert(mc->reply_types[i] == RPC_TYPE_ACK);\n        ack_message * ack = (ack_message *) mc->replies[i];\n        if(ack->status == 0)\n            ok_status++;\n        else\n            *minority_status = ack->status;\n\n#if CLIENT_VERBOSITY > 0\n        to_string_ack_message(ack, (char *) print_buff);\n        log_info(\"Got back response from server %s: %s\", rs->id, print_buff);\n#endif\n    }\n\n    if(ok_status < db->quorum_size)\n    {\n        log_error(\"No valid quorum (%d/%d valid replies received, minority_status=%d)\", ok_status, db->replication_factor, *minority_status);\n        delete_msg_callback(mc->nonce, db);\n        stat_stop(dbc_stats.remote_delete_cell_in_txn, &ts_start, NO_QUORUM_ERR);\n        return NO_QUORUM_ERR;\n    }\n\n    delete_msg_callback(mc->nonce, db);\n\n    stat_stop(dbc_stats.remote_delete_cell_in_txn, &ts_start, 0);\n    return 0;\n}\n\nint remote_delete_by_index_in_txn(WORD index_key, int idx_idx, WORD table_key, int * minority_status, uuid_t * txnid, remote_db_t * db)\n{\n    assert (0); // Not supported\n    return 0;\n}\n\n\n// Read ops:\n\nint get_db_rows_forest_from_read_response(range_read_response_message * response, snode_t** start_row, snode_t** end_row, remote_db_t * db)\n// If a DB query returned multiple cells, accumulate them all in a forest of trees rooted at\n// elements of the returned list start_row->end_row. Return the number of roots found. For forests with a single root\n// (which e.g. results from non-range queries will be), a list with a single element (located at start_row==end_row) will be returned:\n{\n    if(response->no_cells == 0) // No results\n    {\n        *start_row = NULL;\n        *end_row = NULL;\n        return 0;\n    }\n\n    skiplist_t * roots = create_skiplist_long();\n\n    db_row_t* result = create_db_row_schemaless2((WORD *) response->cells[0].keys, response->cells[0].no_keys,\n            (WORD *) response->cells[0].columns, response->cells[0].no_columns,\n            response->cells[0].last_blob, response->cells[0].last_blob_size, &(db->fastrandstate));\n\n    for(int i=0;i<response->no_cells;i++) // We have a deeper result than 1\n    {\n        db_row_t* root_cell = NULL;\n        snode_t * root_cell_node = skiplist_search(roots, (WORD) response->cells[i].keys[0]);\n\n        if(root_cell_node == NULL)\n        {\n//          log_info(\"Creating new root cell for cell %d (%\" PRId64 \")\", i, response->cells[i].keys[0]);\n\n            root_cell = create_db_row_schemaless2((WORD *) response->cells[i].keys, response->cells[i].no_keys,\n                    (WORD *) response->cells[i].columns, response->cells[i].no_columns,\n                    response->cells[i].last_blob, response->cells[i].last_blob_size, &(db->fastrandstate));\n            skiplist_insert(roots, (WORD) response->cells[i].keys[0], (WORD) root_cell, &(db->fastrandstate));\n            continue;\n        }\n        else\n        {\n            root_cell = (db_row_t *) (root_cell_node->value);\n        }\n\n        db_row_t * cell = root_cell, * new_cell = NULL;\n        for(int j=1;j<response->cells[i].no_keys;j++, cell = new_cell)\n        {\n            snode_t * new_cell_node = skiplist_search(cell->cells, (WORD) response->cells[i].keys[j]);\n\n            if(new_cell_node == NULL)\n            {\n                new_cell = create_db_row_schemaless2((WORD *) response->cells[i].keys + j, response->cells[i].no_keys - j,\n                        (WORD *) response->cells[i].columns, response->cells[i].no_columns,\n                        response->cells[i].last_blob, response->cells[i].last_blob_size, &(db->fastrandstate));\n\n//              log_info(\"Inserting cell %d (%\" PRId64 \") into tree at level %d\", i, response->cells[i].keys[j], j);\n\n                skiplist_insert(cell->cells, (WORD) response->cells[i].keys[j], (WORD) new_cell, &(db->fastrandstate));\n\n                break;\n            }\n            else\n            {\n                new_cell = (db_row_t *) (new_cell_node->value);\n\n                assert(j < response->cells[i].no_keys - 1); // there s'dn't be 2 cells returned with the exact same keypath\n            }\n        }\n    }\n\n    int no_roots = 1;\n    *start_row = HEAD(roots);\n    for(*end_row=*start_row;NEXT(*end_row) != NULL;*end_row=NEXT(*end_row), no_roots++);\n\n    assert(roots->no_items == no_roots);\n//  assert(roots->no_items == *end_row - *start_row + 1);\n\n    return roots->no_items;\n}\n\ndb_row_t* get_db_rows_tree_from_read_response(range_read_response_message * response, remote_db_t * db)\n// If a DB query returned multiple cells, accumulate them all in a single tree rooted at \"result\"\n// (assumes this is a non-range query, i.e. all cells will have a common parent on the key path):\n{\n    if(response->no_cells == 0) // No results\n        return NULL;\n\n    db_row_t* result = create_db_row_schemaless2((WORD *) response->cells[0].keys, response->cells[0].no_keys,\n            (WORD *) response->cells[0].columns, response->cells[0].no_columns,\n            response->cells[0].last_blob, response->cells[0].last_blob_size, &(db->fastrandstate));\n\n    for(int i=1;i<response->no_cells;i++) // We have a deeper result than 1\n    {\n        db_row_t * cell = result, * new_cell = NULL;\n\n        assert(response->cells[i].keys[0] == (int64_t) result->key);\n\n        for(int j=1;j<response->cells[i].no_keys;j++, cell = new_cell)\n        {\n            snode_t * new_cell_node = skiplist_search(cell->cells, (WORD) response->cells[i].keys[j]);\n\n            if(new_cell_node == NULL)\n            {\n                new_cell = create_db_row_schemaless2((WORD *) response->cells[i].keys + j, response->cells[i].no_keys - j,\n                        (WORD *) response->cells[i].columns, response->cells[i].no_columns,\n                        response->cells[i].last_blob, response->cells[i].last_blob_size, &(db->fastrandstate));\n\n//              log_info(\"Inserting cell %d (%\" PRId64 \") into tree at level %d\", i, response->cells[i].keys[j], j);\n\n                skiplist_insert(cell->cells, (WORD) response->cells[i].keys[j], (WORD) new_cell, &(db->fastrandstate));\n\n                break;\n            }\n            else\n            {\n                new_cell = (db_row_t *) (new_cell_node->value);\n\n                assert(j < response->cells[i].no_keys - 1); // there s'dn't be 2 cells returned with the exact same keypath\n            }\n        }\n    }\n\n//  print_long_row(result);\n\n    return result;\n}\n\nint remote_search_in_txn(WORD* primary_keys, int no_primary_keys, db_row_t** result_row, WORD table_key,\n                        int * minority_status, uuid_t * txnid, remote_db_t * db)\n{\n    struct timespec ts_start;\n    stat_start(dbc_stats.remote_search_in_txn, &ts_start);\n\n    unsigned len = 0;\n    void * tmp_out_buf = NULL;\n    *result_row = NULL;\n    *minority_status = 0;\n\n    read_query * q = build_search_in_txn(primary_keys, no_primary_keys, table_key, txnid, get_nonce(db));\n    int success = serialize_read_query(q, (void **) &tmp_out_buf, &len, NULL);\n\n    if(db->servers->no_items < db->quorum_size)\n    {\n        log_error(\"No quorum (%d/%d servers alive)\", db->servers->no_items, db->replication_factor);\n        stat_stop(dbc_stats.remote_search_in_txn, &ts_start, NO_QUORUM_ERR);\n        return NO_QUORUM_ERR;\n    }\n    remote_server * rs = (remote_server *) (HEAD(db->servers))->value;\n\n#if CLIENT_VERBOSITY > 0\n    char print_buff[1024];\n    to_string_read_query(q, (char *) print_buff);\n    log_info(\"Sending read row query to server %s: %s\", rs->id, print_buff);\n#endif\n\n    // Send packet to server and wait for reply:\n\n    msg_callback * mc = NULL;\n    success = send_packet_wait_replies_sync(tmp_out_buf, len, q->nonce, &mc, db);\n    assert(success == 0);\n    free_read_query(q);\n\n    if(mc->no_replies < db->quorum_size)\n    {\n        log_error(\"No quorum (%d/%d replies received)\", mc->no_replies, db->replication_factor);\n        delete_msg_callback(mc->nonce, db);\n        stat_stop(dbc_stats.remote_search_in_txn, &ts_start, NO_QUORUM_ERR);\n        return NO_QUORUM_ERR;\n    }\n\n    range_read_response_message * response = NULL;\n    int ok_status = 0;\n\n    for(int i=0;i<mc->no_replies;i++)\n    {\n        assert(mc->reply_types[i] == RPC_TYPE_RANGE_READ_RESPONSE);\n        range_read_response_message * candidate_response = (range_read_response_message *) mc->replies[i];\n\n#if CLIENT_VERBOSITY > 0\n        to_string_range_read_response_message(candidate_response, (char *) print_buff);\n        log_info(\"Got back response from server %s: %s\", rs->id, print_buff);\n#endif\n\n        if(candidate_response->no_cells >= 0)\n        {\n            ok_status++;\n            if(response == NULL)\n                response = candidate_response;\n        }\n        else\n        {\n            *minority_status = candidate_response->no_cells;\n        }\n    }\n\n    if(ok_status < db->quorum_size)\n    {\n        log_error(\"No valid quorum (%d/%d valid replies received, minority_status=%d)\", ok_status, db->replication_factor, *minority_status);\n        delete_msg_callback(mc->nonce, db);\n        stat_stop(dbc_stats.remote_search_in_txn, &ts_start, NO_QUORUM_ERR);\n        return NO_QUORUM_ERR;\n    }\n\n    // If result returned multiple cells, accumulate them all in a single tree rooted at \"result\":\n    *result_row = get_db_rows_tree_from_read_response(response, db);\n\n    delete_msg_callback(mc->nonce, db);\n\n    stat_stop(dbc_stats.remote_search_in_txn, &ts_start, 0);\n    return 0;\n}\n\n\nint remote_search_clustering_in_txn(WORD* primary_keys, int no_primary_keys, WORD* clustering_keys, int no_clustering_keys,\n                                            db_row_t** result_row, WORD table_key,\n                                            int * minority_status, uuid_t * txnid, remote_db_t * db)\n{\n    struct timespec ts_start;\n    stat_start(dbc_stats.remote_search_clustering_in_txn, &ts_start);\n\n    unsigned len = 0;\n    void * tmp_out_buf = NULL;\n    *result_row = NULL;\n    *minority_status = 0;\n\n    read_query * q = build_search_clustering_in_txn(primary_keys, no_primary_keys, clustering_keys, no_clustering_keys, table_key, txnid, get_nonce(db));\n    int success = serialize_read_query(q, (void **) &tmp_out_buf, &len, NULL);\n\n    if(db->servers->no_items < db->quorum_size)\n    {\n        log_error(\"No quorum (%d/%d servers alive)\", db->servers->no_items, db->replication_factor);\n        stat_stop(dbc_stats.remote_search_clustering_in_txn, &ts_start, NO_QUORUM_ERR);\n        return NO_QUORUM_ERR;\n    }\n    remote_server * rs = (remote_server *) (HEAD(db->servers))->value;\n\n#if CLIENT_VERBOSITY > 0\n    char print_buff[1024];\n    to_string_read_query(q, (char *) print_buff);\n    log_info(\"Sending read cell query to server %s: %s\", rs->id, print_buff);\n#endif\n\n    // Send packet to server and wait for reply:\n\n    msg_callback * mc = NULL;\n    success = send_packet_wait_replies_sync(tmp_out_buf, len, q->nonce, &mc, db);\n    assert(success == 0);\n    free_read_query(q);\n\n    if(mc->no_replies < db->quorum_size)\n    {\n        log_error(\"No quorum (%d/%d replies received)\", mc->no_replies, db->replication_factor);\n        delete_msg_callback(mc->nonce, db);\n        stat_stop(dbc_stats.remote_search_clustering_in_txn, &ts_start, NO_QUORUM_ERR);\n        return NO_QUORUM_ERR;\n    }\n\n    range_read_response_message * response = NULL;\n    int ok_status = 0;\n\n    for(int i=0;i<mc->no_replies;i++)\n    {\n        assert(mc->reply_types[i] == RPC_TYPE_RANGE_READ_RESPONSE);\n        range_read_response_message * candidate_response = (range_read_response_message *) mc->replies[i];\n\n#if CLIENT_VERBOSITY > 0\n        to_string_range_read_response_message(candidate_response, (char *) print_buff);\n        log_info(\"Got back response from server %s: %s\", rs->id, print_buff);\n#endif\n\n        if(candidate_response->no_cells >= 0)\n        {\n            ok_status++;\n            if(response == NULL)\n                response = candidate_response;\n        }\n        else\n        {\n            *minority_status = candidate_response->no_cells;\n        }\n    }\n\n    if(ok_status < db->quorum_size)\n    {\n        log_error(\"No valid quorum (%d/%d valid replies received, minority_status=%d)\", ok_status, db->replication_factor, *minority_status);\n        delete_msg_callback(mc->nonce, db);\n        stat_stop(dbc_stats.remote_search_clustering_in_txn, &ts_start, NO_QUORUM_ERR);\n        return NO_QUORUM_ERR;\n    }\n\n    // If result returned multiple cells, accumulate them all in a single tree rooted at \"result\":\n    *result_row = get_db_rows_tree_from_read_response(response, db);\n\n    delete_msg_callback(mc->nonce, db);\n\n    stat_stop(dbc_stats.remote_search_clustering_in_txn, &ts_start, 0);\n    return 0;\n}\n\nint remote_search_columns_in_txn(WORD* primary_keys, int no_primary_keys, WORD* clustering_keys, int no_clustering_keys,\n                                    WORD* col_keys, int no_columns, db_row_t** result_row, WORD table_key,\n                                    int * minority_status, uuid_t * txnid, remote_db_t * db)\n{\n    assert (0); // Not supported\n    return 0;\n}\n\nint remote_search_index_in_txn(WORD index_key, int idx_idx, db_row_t** result_row, WORD table_key, int * minority_status, uuid_t * txnid, remote_db_t * db)\n{\n    assert (0); // Not supported; TO DO\n    return 0;\n}\n\n\nint remote_range_search_in_txn(WORD* start_primary_keys, WORD* end_primary_keys, int no_primary_keys,\n                            snode_t** start_row, snode_t** end_row,\n                            WORD table_key, int * no_items, int * minority_status, uuid_t * txnid, remote_db_t * db)\n{\n    struct timespec ts_start;\n    stat_start(dbc_stats.remote_range_search_in_txn, &ts_start);\n\n    unsigned len = 0;\n    void * tmp_out_buf = NULL;\n    *no_items = 0;\n    *minority_status = 0;\n\n    range_read_query * q = build_range_search_in_txn(start_primary_keys, end_primary_keys, no_primary_keys, table_key, txnid, get_nonce(db));\n    int success = serialize_range_read_query(q, (void **) &tmp_out_buf, &len, NULL);\n\n    if(db->servers->no_items < db->quorum_size)\n    {\n        log_error(\"No quorum (%d/%d servers alive)\", db->servers->no_items, db->replication_factor);\n        stat_stop(dbc_stats.remote_range_search_in_txn, &ts_start, NO_QUORUM_ERR);\n        return NO_QUORUM_ERR;\n    }\n    remote_server * rs = (remote_server *) (HEAD(db->servers))->value;\n\n#if CLIENT_VERBOSITY > 0\n    char print_buff[1024];\n    to_string_range_read_query(q, (char *) print_buff);\n    log_info(\"Sending range read row query to server %s: %s\", rs->id, print_buff);\n#endif\n\n    // Send packet to server and wait for reply:\n\n    msg_callback * mc = NULL;\n    success = send_packet_wait_replies_sync(tmp_out_buf, len, q->nonce, &mc, db);\n    assert(success == 0);\n    free_range_read_query(q);\n\n    if(mc->no_replies < db->quorum_size)\n    {\n        log_error(\"No quorum (%d/%d replies received)\", mc->no_replies, db->replication_factor);\n        delete_msg_callback(mc->nonce, db);\n        stat_stop(dbc_stats.remote_range_search_in_txn, &ts_start, NO_QUORUM_ERR);\n        return NO_QUORUM_ERR;\n    }\n\n    range_read_response_message * response;\n    int ok_status = 0;\n\n    for(int i=0;i<mc->no_replies;i++)\n    {\n        assert(mc->reply_types[i] == RPC_TYPE_RANGE_READ_RESPONSE);\n        range_read_response_message * candidate_response = (range_read_response_message *) mc->replies[i];\n\n#if CLIENT_VERBOSITY > 0\n        to_string_range_read_response_message(candidate_response, (char *) print_buff);\n        log_info(\"Got back response from server %s: %s\", rs->id, print_buff);\n#endif\n\n        if(candidate_response->no_cells >= 0)\n        {\n            ok_status++;\n            if(response == NULL)\n                response = candidate_response;\n        }\n        else\n        {\n            *minority_status = candidate_response->no_cells;\n        }\n    }\n\n    if(ok_status < db->quorum_size)\n    {\n        log_error(\"No valid quorum (%d/%d valid replies received, minority_status=%d)\", ok_status, db->replication_factor, *minority_status);\n        delete_msg_callback(mc->nonce, db);\n        stat_stop(dbc_stats.remote_range_search_in_txn, &ts_start, NO_QUORUM_ERR);\n        return NO_QUORUM_ERR;\n    }\n\n    // If result returned multiple cells, accumulate them all in a forest of db_rows rooted at elements of list start_row->end_row:\n    *no_items = get_db_rows_forest_from_read_response(response, start_row, end_row, db);\n\n    delete_msg_callback(mc->nonce, db);\n\n    stat_stop(dbc_stats.remote_range_search_in_txn, &ts_start, 0);\n    return 0;\n}\n\nint remote_range_search_clustering_in_txn(WORD* primary_keys, int no_primary_keys,\n                                     WORD* start_clustering_keys, WORD* end_clustering_keys, int no_clustering_keys,\n                                     snode_t** start_row, snode_t** end_row,\n                                     WORD table_key, int * no_items, int * minority_status,\n                                     uuid_t * txnid, remote_db_t * db)\n{\n    struct timespec ts_start;\n    stat_start(dbc_stats.remote_range_search_clustering_in_txn, &ts_start);\n\n    unsigned len = 0;\n    void * tmp_out_buf = NULL;\n    *no_items = 0;\n    *minority_status = 0;\n\n    range_read_query * q = build_range_search_clustering_in_txn(primary_keys, no_primary_keys,\n                                                            start_clustering_keys, end_clustering_keys, no_clustering_keys,\n                                                            table_key, txnid, get_nonce(db));\n    int success = serialize_range_read_query(q, (void **) &tmp_out_buf, &len, NULL);\n\n    if(db->servers->no_items < db->quorum_size)\n    {\n        log_error(\"No quorum (%d/%d servers alive)\", db->servers->no_items, db->replication_factor);\n        stat_stop(dbc_stats.remote_range_search_clustering_in_txn, &ts_start, NO_QUORUM_ERR);\n        return NO_QUORUM_ERR;\n    }\n    remote_server * rs = (remote_server *) (HEAD(db->servers))->value;\n\n#if CLIENT_VERBOSITY > 0\n    char print_buff[1024];\n    to_string_range_read_query(q, (char *) print_buff);\n    log_info(\"Sending range read cell query to server %s: %s\", rs->id, print_buff);\n#endif\n\n    // Send packet to server and wait for reply:\n\n    msg_callback * mc = NULL;\n    success = send_packet_wait_replies_sync(tmp_out_buf, len, q->nonce, &mc, db);\n    assert(success == 0);\n    free_range_read_query(q);\n\n    if(mc->no_replies < db->quorum_size)\n    {\n        log_error(\"No quorum (%d/%d replies received)\", mc->no_replies, db->replication_factor);\n        delete_msg_callback(mc->nonce, db);\n        stat_stop(dbc_stats.remote_range_search_clustering_in_txn, &ts_start, NO_QUORUM_ERR);\n        return NO_QUORUM_ERR;\n    }\n\n    range_read_response_message * response = NULL;\n    int ok_status = 0;\n\n    for(int i=0;i<mc->no_replies;i++)\n    {\n        assert(mc->reply_types[i] == RPC_TYPE_RANGE_READ_RESPONSE);\n        range_read_response_message * candidate_response = (range_read_response_message *) mc->replies[i];\n\n#if CLIENT_VERBOSITY > 0\n        to_string_range_read_response_message(candidate_response, (char *) print_buff);\n        log_info(\"Got back response from server %s: %s\", rs->id, print_buff);\n#endif\n\n        if(candidate_response->no_cells >= 0)\n        {\n            ok_status++;\n            if(response == NULL)\n                response = candidate_response;\n        }\n        else\n        {\n            *minority_status = candidate_response->no_cells;\n        }\n    }\n\n    if(ok_status < db->quorum_size)\n    {\n        log_error(\"No valid quorum (%d/%d valid replies received, minority_status=%d)\", ok_status, db->replication_factor, *minority_status);\n        delete_msg_callback(mc->nonce, db);\n        stat_stop(dbc_stats.remote_range_search_clustering_in_txn, &ts_start, NO_QUORUM_ERR);\n        return NO_QUORUM_ERR;\n    }\n\n    // If result returned multiple cells, accumulate them all in a forest of db_rows rooted at elements of list start_row->end_row:\n    *no_items = get_db_rows_forest_from_read_response(response, start_row, end_row, db);\n\n    delete_msg_callback(mc->nonce, db);\n\n    stat_stop(dbc_stats.remote_range_search_clustering_in_txn, &ts_start, 0);\n    return 0;\n}\n\nint remote_range_search_index_in_txn(int idx_idx, WORD start_idx_key, WORD end_idx_key,\n                                snode_t** start_row, snode_t** end_row,\n                                WORD table_key, int * no_items, int * minority_status,\n                                uuid_t * txnid, remote_db_t * db)\n{\n    assert (0); // Not supported; TO DO\n    return 0;\n}\n\nint remote_read_full_table_in_txn(snode_t** start_row, snode_t** end_row, WORD table_key, int * no_items, int * minority_status,\n                                uuid_t * txnid, remote_db_t * db)\n{\n    struct timespec ts_start;\n    stat_start(dbc_stats.remote_read_full_table_in_txn, &ts_start);\n\n    unsigned len = 0;\n    void * tmp_out_buf = NULL;\n    *no_items = 0;\n    *minority_status = 0;\n\n    range_read_query * q = build_wildcard_range_search_in_txn(table_key, txnid, get_nonce(db));\n    int success = serialize_range_read_query(q, (void **) &tmp_out_buf, &len, NULL);\n\n    if(db->servers->no_items < db->quorum_size)\n    {\n        log_error(\"No quorum (%d/%d servers alive)\", db->servers->no_items, db->replication_factor);\n        stat_stop(dbc_stats.remote_read_full_table_in_txn, &ts_start, NO_QUORUM_ERR);\n        return NO_QUORUM_ERR;\n    }\n    remote_server * rs = (remote_server *) (HEAD(db->servers))->value;\n\n#if CLIENT_VERBOSITY > 0\n    char print_buff[1024];\n    to_string_range_read_query(q, (char *) print_buff);\n    log_info(\"Sending full table read query to server %s: %s\", rs->id, print_buff);\n#endif\n\n    // Send packet to server and wait for reply:\n\n    msg_callback * mc = NULL;\n    success = send_packet_wait_replies_sync(tmp_out_buf, len, q->nonce, &mc, db);\n    assert(success == 0);\n    free_range_read_query(q);\n\n    if(mc->no_replies < db->quorum_size)\n    {\n        log_error(\"No quorum (%d/%d replies received)\", mc->no_replies, db->replication_factor);\n        delete_msg_callback(mc->nonce, db);\n        stat_stop(dbc_stats.remote_read_full_table_in_txn, &ts_start, NO_QUORUM_ERR);\n        return NO_QUORUM_ERR;\n    }\n\n    range_read_response_message * response = NULL;\n    int ok_status = 0;\n\n    for(int i=0;i<mc->no_replies;i++)\n    {\n        assert(mc->reply_types[i] == RPC_TYPE_RANGE_READ_RESPONSE);\n        range_read_response_message * candidate_response = (range_read_response_message *) mc->replies[i];\n\n#if CLIENT_VERBOSITY > 2\n        to_string_range_read_response_message(candidate_response, (char *) print_buff);\n        log_info(\"Got back response from server: %s\", print_buff);\n#endif\n\n        if(candidate_response->no_cells >= 0)\n        {\n            ok_status++;\n            if(response == NULL)\n                response = candidate_response;\n        }\n        else\n        {\n            *minority_status = candidate_response->no_cells;\n        }\n    }\n\n    if(ok_status < db->quorum_size)\n    {\n        log_error(\"No valid quorum (%d/%d valid replies received, minority_status=%d)\", ok_status, db->replication_factor, *minority_status);\n        delete_msg_callback(mc->nonce, db);\n        stat_stop(dbc_stats.remote_read_full_table_in_txn, &ts_start, NO_QUORUM_ERR);\n        return NO_QUORUM_ERR;\n    }\n\n    // If result returned multiple cells, accumulate them all in a forest of db_rows rooted at elements of list start_row->end_row:\n    *no_items = get_db_rows_forest_from_read_response(response, start_row, end_row, db);\n\n    delete_msg_callback(mc->nonce, db);\n\n#if DEBUG_BLOBS > 0\n    log_info(\"remote_read_full_table_in_txn: Returning %\" PRId64 \" [%d rows]:\", (int64_t) table_key, result);\n\n    for(snode_t * node = *start_row; node!=NULL; node=NEXT(node))\n        print_long_row((db_row_t*) node->value);\n#endif\n\n    stat_stop(dbc_stats.remote_read_full_table_in_txn, &ts_start, 0);\n    return 0;\n}\n\nvoid remote_print_long_table(WORD table_key, remote_db_t * db)\n{\n    snode_t* start_row = NULL, * end_row = NULL;\n    int no_items = 0, minority_status = 0;\n    int ret = remote_read_full_table_in_txn(&start_row, &end_row, table_key, &no_items, &minority_status, NULL, db);\n\n    log_info(\"DB_TABLE: %\" PRId64 \" [%d rows]\", (int64_t) table_key, no_items);\n\n    if(ret == 0 && no_items > 0)\n    {\n        for(snode_t * node = start_row; node!=NULL; node=NEXT(node))\n            print_long_row((db_row_t*) node->value);\n    }\n}\n\n\n// Queue ops:\n\n/*\n *\n * Note on status returns of queue operations:\n *\n * If there is a quorum of valid replies from servers, we return the appropriate non-err status.\n * In the case of a queue read for instance, this is QUEUE_STATUS_READ_INCOMPLETE or QUEUE_STATUS_READ_COMPLETE.\n * In addition, if there also were non-valid replies received (and there was still a quorum),\n * we also set the err status of the minority error response in the 'minority_status' variable to advise\n * the client that some schemas on a minority of nodes might need repairs.\n * If there is no quorum of *valid* replies, but there was a quorum of received replies\n * (e.g. we received schema mismatch errors), we return NO_QUORUM_ERR and set the minority status\n * with the received error status.\n * If there was no quorum of replies at all (not enough servers responded), we return NO_QUORUM_ERR and fill\n * in no minority_status (the client will not be able to recreate schemas anyway until there is a quorum).\n * As a result, in all cases when the client receives NO_QUORUM_ERR, he has to retry the operation.\n * In addition, if minority_status is set to a schema mismatch flavor of error, he can attempt schema correction after this,\n * whether or not he also needs to re-try the operation (if the operation succeeded, this will still help to install correct schemas on\n * the minority nodes).\n *\n */\n\n\nint remote_create_queue_in_txn(WORD table_key, WORD queue_id, int * minority_status, uuid_t * txnid, remote_db_t * db)\n{\n    struct timespec ts_start;\n    stat_start(dbc_stats.remote_create_queue_in_txn, &ts_start);\n\n    unsigned len = 0;\n    void * tmp_out_buf = NULL;\n    *minority_status = 0;\n\n    queue_query_message * q = build_create_queue_in_txn(table_key, queue_id, txnid, get_nonce(db));\n    int success = serialize_queue_message(q, (void **) &tmp_out_buf, &len, 1, NULL);\n\n    if(db->servers->no_items < db->quorum_size)\n    {\n        log_error(\"No quorum (%d/%d servers alive)\", db->servers->no_items, db->replication_factor);\n        stat_stop(dbc_stats.remote_create_queue_in_txn, &ts_start, NO_QUORUM_ERR);\n        return NO_QUORUM_ERR;\n    }\n    remote_server * rs = (remote_server *) (HEAD(db->servers))->value;\n\n#if CLIENT_VERBOSITY > 0\n    char print_buff[1024];\n    to_string_queue_message(q, (char *) print_buff);\n    log_info(\"Sending queue message to server %s: %s\", rs->id, print_buff);\n#endif\n\n    // Send packet to server and wait for reply:\n\n    msg_callback * mc = NULL;\n    success = send_packet_wait_replies_sync(tmp_out_buf, len, q->nonce, &mc, db);\n    assert(success == 0);\n    free_queue_message(q);\n\n    if(mc->no_replies < db->quorum_size)\n    {\n        log_error(\"No quorum (%d/%d replies received)\", mc->no_replies, db->replication_factor);\n        delete_msg_callback(mc->nonce, db);\n        stat_stop(dbc_stats.remote_create_queue_in_txn, &ts_start, NO_QUORUM_ERR);\n        return NO_QUORUM_ERR;\n    }\n\n    int ok_status = 0;\n\n    for(int i=0;i<mc->no_replies;i++)\n    {\n        assert(mc->reply_types[i] == RPC_TYPE_ACK);\n        ack_message * ack = (ack_message *) mc->replies[i];\n        if(ack->status == 0 || ack->status == DB_ERR_DUPLICATE_QUEUE)\n            ok_status++;\n        else\n            *minority_status = ack->status;\n\n#if CLIENT_VERBOSITY > 0\n        to_string_ack_message(ack, (char *) print_buff);\n        log_info(\"Got back response from server %s: %s\", rs->id, print_buff);\n#endif\n    }\n\n    if(ok_status < db->quorum_size)\n    {\n        log_error(\"No valid quorum (%d/%d valid replies received, minority_status=%d)\", ok_status, db->replication_factor, *minority_status);\n        delete_msg_callback(mc->nonce, db);\n        stat_stop(dbc_stats.remote_create_queue_in_txn, &ts_start, NO_QUORUM_ERR);\n        return NO_QUORUM_ERR;\n    }\n\n    delete_msg_callback(mc->nonce, db);\n\n    stat_stop(dbc_stats.remote_create_queue_in_txn, &ts_start, 0);\n    return 0;\n}\n\nint remote_delete_queue_in_txn(WORD table_key, WORD queue_id, int * minority_status, uuid_t * txnid, remote_db_t * db)\n{\n    struct timespec ts_start;\n    stat_start(dbc_stats.remote_delete_queue_in_txn, &ts_start);\n\n    unsigned len = 0;\n    void * tmp_out_buf = NULL;\n    *minority_status = 0;\n\n    queue_query_message * q = build_delete_queue_in_txn(table_key, queue_id, txnid, get_nonce(db));\n    int success = serialize_queue_message(q, (void **) &tmp_out_buf, &len, 1, NULL);\n\n    if(db->servers->no_items < db->quorum_size)\n    {\n        log_error(\"No quorum (%d/%d servers alive)\", db->servers->no_items, db->replication_factor);\n        stat_stop(dbc_stats.remote_delete_queue_in_txn, &ts_start, NO_QUORUM_ERR);\n        return NO_QUORUM_ERR;\n    }\n    remote_server * rs = (remote_server *) (HEAD(db->servers))->value;\n\n#if CLIENT_VERBOSITY > 0\n    char print_buff[1024];\n    to_string_queue_message(q, (char *) print_buff);\n    log_info(\"Sending queue message to server %s: %s\", rs->id, print_buff);\n#endif\n\n    // Send packet to server and wait for reply:\n\n    msg_callback * mc = NULL;\n    success = send_packet_wait_replies_sync(tmp_out_buf, len, q->nonce, &mc, db);\n    assert(success == 0);\n    free_queue_message(q);\n\n    if(mc->no_replies < db->quorum_size)\n    {\n        log_error(\"No quorum (%d/%d replies received)\", mc->no_replies, db->replication_factor);\n        delete_msg_callback(mc->nonce, db);\n        stat_stop(dbc_stats.remote_delete_queue_in_txn, &ts_start, NO_QUORUM_ERR);\n        return NO_QUORUM_ERR;\n    }\n\n    int ok_status = 0;\n\n    for(int i=0;i<mc->no_replies;i++)\n    {\n        assert(mc->reply_types[i] == RPC_TYPE_ACK);\n        ack_message * ack = (ack_message *) mc->replies[i];\n        if(ack->status == 0)\n            ok_status++;\n        else\n            *minority_status = ack->status;\n\n#if CLIENT_VERBOSITY > 0\n        to_string_ack_message(ack, (char *) print_buff);\n        log_info(\"Got back response from server %s: %s\", rs->id, print_buff);\n#endif\n    }\n\n    if(ok_status < db->quorum_size)\n    {\n        log_error(\"No valid quorum (%d/%d valid replies received, minority_status=%d)\", ok_status, db->replication_factor, *minority_status);\n        delete_msg_callback(mc->nonce, db);\n        stat_stop(dbc_stats.remote_delete_queue_in_txn, &ts_start, NO_QUORUM_ERR);\n        return NO_QUORUM_ERR;\n    }\n\n    delete_msg_callback(mc->nonce, db);\n\n    stat_stop(dbc_stats.remote_delete_queue_in_txn, &ts_start, 0);\n    return 0;\n}\n\nint remote_enqueue_in_txn(WORD * column_values, int no_cols, WORD blob, size_t blob_size, WORD table_key, WORD queue_id,\n                            int * minority_status, uuid_t * txnid, remote_db_t * db)\n{\n    struct timespec ts_start;\n    stat_start(dbc_stats.remote_enqueue_in_txn, &ts_start);\n\n    unsigned len = 0;\n    void * tmp_out_buf = NULL;\n    *minority_status = 0;\n\n    queue_query_message * q = build_enqueue_in_txn(column_values, no_cols, blob, blob_size, table_key, queue_id, txnid, get_nonce(db));\n    int success = serialize_queue_message(q, (void **) &tmp_out_buf, &len, 1, NULL);\n\n    if(db->servers->no_items < db->quorum_size)\n    {\n        log_error(\"No quorum (%d/%d servers alive)\", db->servers->no_items, db->replication_factor);\n        stat_stop(dbc_stats.remote_enqueue_in_txn, &ts_start, NO_QUORUM_ERR);\n        return NO_QUORUM_ERR;\n    }\n    remote_server * rs = (remote_server *) (HEAD(db->servers))->value;\n\n#if CLIENT_VERBOSITY > 0\n    char print_buff[1024];\n    to_string_queue_message(q, (char *) print_buff);\n    log_info(\"Sending queue message to server %s: %s\", rs->id, print_buff);\n#endif\n\n    // Send packet to server and wait for reply:\n\n    msg_callback * mc = NULL;\n    success = send_packet_wait_replies_sync(tmp_out_buf, len, q->nonce, &mc, db);\n    assert(success == 0);\n    free_queue_message(q);\n\n    if(mc->no_replies < db->quorum_size)\n    {\n        log_error(\"No quorum (%d/%d replies received)\", mc->no_replies, db->replication_factor);\n        delete_msg_callback(mc->nonce, db);\n        stat_stop(dbc_stats.remote_enqueue_in_txn, &ts_start, NO_QUORUM_ERR);\n        return NO_QUORUM_ERR;\n    }\n\n    int ok_status = 0;\n\n    for(int i=0;i<mc->no_replies;i++)\n    {\n        assert(mc->reply_types[i] == RPC_TYPE_ACK);\n        ack_message * ack = (ack_message *) mc->replies[i];\n        if(ack->status == 0)\n            ok_status++;\n        else\n            *minority_status = ack->status;\n\n#if CLIENT_VERBOSITY > 0\n        to_string_ack_message(ack, (char *) print_buff);\n        log_info(\"Got back response from server %s: %s\", rs->id, print_buff);\n#endif\n    }\n\n    if(ok_status < db->quorum_size)\n    {\n        log_error(\"No valid quorum (%d/%d valid replies received, minority_status=%d)\", ok_status, db->replication_factor, *minority_status);\n        delete_msg_callback(mc->nonce, db);\n        stat_stop(dbc_stats.remote_enqueue_in_txn, &ts_start, NO_QUORUM_ERR);\n        return NO_QUORUM_ERR;\n    }\n\n    delete_msg_callback(mc->nonce, db);\n\n    stat_stop(dbc_stats.remote_enqueue_in_txn, &ts_start, 0);\n    return 0;\n}\n\nint remote_read_queue_in_txn(WORD consumer_id, WORD shard_id, WORD app_id, WORD table_key, WORD queue_id,\n        int max_entries, int * entries_read, int64_t * new_read_head,\n        snode_t** start_row, snode_t** end_row, int * minority_status, uuid_t * txnid,\n        remote_db_t * db)\n{\n    struct timespec ts_start;\n    stat_start(dbc_stats.remote_read_queue_in_txn, &ts_start);\n\n    unsigned len = 0;\n    void * tmp_out_buf = NULL;\n    *minority_status = 0;\n\n    queue_query_message * q = build_read_queue_in_txn(consumer_id, shard_id, app_id, table_key, queue_id, max_entries, txnid, get_nonce(db));\n    int success = serialize_queue_message(q, (void **) &tmp_out_buf, &len, 1, NULL);\n\n    if(db->servers->no_items < db->quorum_size)\n    {\n        log_error(\"No quorum (%d/%d servers alive)\", db->servers->no_items, db->replication_factor);\n        stat_stop(dbc_stats.remote_read_queue_in_txn, &ts_start, NO_QUORUM_ERR);\n        return NO_QUORUM_ERR;\n    }\n    remote_server * rs = (remote_server *) (HEAD(db->servers))->value;\n\n#if CLIENT_VERBOSITY > 0\n    char print_buff[1024];\n    to_string_queue_message(q, (char *) print_buff);\n    log_info(\"Sending queue message to server %s: %s\", rs->id, print_buff);\n#endif\n\n    // Send packet to server and wait for reply:\n\n    msg_callback * mc = NULL;\n    success = send_packet_wait_replies_sync(tmp_out_buf, len, q->nonce, &mc, db);\n    assert(success == 0);\n    free_queue_message(q);\n\n    if(mc->no_replies < db->quorum_size)\n    {\n        log_error(\"No quorum (%d/%d replies received)\", mc->no_replies, db->replication_factor);\n        delete_msg_callback(mc->nonce, db);\n        stat_stop(dbc_stats.remote_read_queue_in_txn, &ts_start, NO_QUORUM_ERR);\n        return NO_QUORUM_ERR;\n    }\n\n    queue_query_message * candidate_response = NULL, * response = NULL;\n    int valid_responses = 0;\n    for(int i=0;i<mc->no_replies;i++)\n    {\n        assert(mc->reply_types[i] == RPC_TYPE_QUEUE);\n        candidate_response = (queue_query_message *) mc->replies[i];\n        assert(candidate_response->msg_type == QUERY_TYPE_READ_QUEUE_RESPONSE);\n#if CLIENT_VERBOSITY > 0\n        to_string_queue_message(candidate_response, (char *) print_buff);\n        log_info(\"Got back response: %s\", print_buff);\n#endif\n        if(candidate_response->status < 0)\n        {\n            *minority_status = candidate_response->status;\n        }\n        else\n        {\n             // To determine whether the read was complete or incomplete, we use the status from the server reply\n             // with the highest queue_index (since it will contain the latest persisted enqueues):\n\n            if(response == NULL || candidate_response->queue_index > response->queue_index)\n                response = candidate_response;\n            valid_responses++;\n        }\n    }\n\n    if(valid_responses < db->quorum_size)\n    {\n        log_error(\"No valid quorum (%d/%d valid replies received, minority_status=%d)\", valid_responses, db->replication_factor, *minority_status);\n        delete_msg_callback(mc->nonce, db);\n        stat_stop(dbc_stats.remote_read_queue_in_txn, &ts_start, NO_QUORUM_ERR);\n        return NO_QUORUM_ERR;\n    }\n\n    // Parse queue read response message to row list:\n\n    skiplist_t * rows = create_skiplist_long();\n    for(int i=0;i<response->no_cells;i++)\n    {\n            db_row_t * row = create_db_row_schemaless2((WORD *) response->cells[i].keys, response->cells[i].no_keys,\n                                                        (WORD *) response->cells[i].columns, response->cells[i].no_columns,\n                                                    response->cells[i].last_blob, response->cells[i].last_blob_size,\n                                                    &(db->fastrandstate)); // Note that cell versions are only kept on the server, we don't return them to the client\n            skiplist_insert(rows, (WORD) response->cells[i].keys[0], (WORD) row, &(db->fastrandstate));\n    }\n\n    *start_row = HEAD(rows);\n\n    if((*start_row) != NULL)\n    {\n            for(*end_row = *start_row;NEXT(*end_row) != NULL;*end_row = NEXT(*end_row));\n    }\n\n    *entries_read = response->no_cells;\n    *new_read_head = response->queue_index;\n\n    delete_msg_callback(mc->nonce, db);\n\n    stat_stop(dbc_stats.remote_read_queue_in_txn, &ts_start, 0);\n    return response->status;\n}\n\nint remote_consume_queue_in_txn(WORD consumer_id, WORD shard_id, WORD app_id, WORD table_key, WORD queue_id,\n                                int64_t new_consume_head, int * minority_status, uuid_t * txnid, remote_db_t * db)\n{\n    struct timespec ts_start;\n    stat_start(dbc_stats.remote_consume_queue_in_txn, &ts_start);\n\n    unsigned len = 0;\n    void * tmp_out_buf = NULL;\n    *minority_status = 0;\n\n    queue_query_message * q = build_consume_queue_in_txn(consumer_id, shard_id, app_id, table_key, queue_id, new_consume_head, txnid, get_nonce(db));\n    int success = serialize_queue_message(q, (void **) &tmp_out_buf, &len, 1, NULL);\n\n    if(db->servers->no_items < db->quorum_size)\n    {\n        log_error(\"No quorum (%d/%d servers alive)\", db->servers->no_items, db->replication_factor);\n        stat_stop(dbc_stats.remote_consume_queue_in_txn, &ts_start, NO_QUORUM_ERR);\n        return NO_QUORUM_ERR;\n    }\n    remote_server * rs = (remote_server *) (HEAD(db->servers))->value;\n\n#if CLIENT_VERBOSITY > 0\n    char print_buff[1024];\n    to_string_queue_message(q, (char *) print_buff);\n    log_info(\"Sending queue message to server %s: %s\", rs->id, print_buff);\n#endif\n\n    // Send packet to server and wait for reply:\n\n    msg_callback * mc = NULL;\n    success = send_packet_wait_replies_sync(tmp_out_buf, len, q->nonce, &mc, db);\n    assert(success == 0);\n    free_queue_message(q);\n\n    if(mc->no_replies < db->quorum_size)\n    {\n        log_error(\"No quorum (%d/%d replies received)\", mc->no_replies, db->replication_factor);\n        delete_msg_callback(mc->nonce, db);\n        stat_stop(dbc_stats.remote_consume_queue_in_txn, &ts_start, NO_QUORUM_ERR);\n        return NO_QUORUM_ERR;\n    }\n\n    int ok_status = 0;\n\n    for(int i=0;i<mc->no_replies;i++)\n    {\n        if(mc->reply_types[i] != RPC_TYPE_ACK)\n        {\n            log_error(\"Received unexpected reply type: %d\", mc->reply_types[i]);\n            assert(0);\n        }\n        ack_message * ack = (ack_message *) mc->replies[i];\n        if(ack->status == 0)\n            ok_status++;\n        else\n            *minority_status = ack->status;\n\n#if CLIENT_VERBOSITY > 0\n        to_string_ack_message(ack, (char *) print_buff);\n        log_info(\"Got back response from server %s: %s\", rs->id, print_buff);\n#endif\n    }\n\n    if(ok_status < db->quorum_size)\n    {\n        log_error(\"No valid quorum (%d/%d valid replies received, minority_status=%d)\", ok_status, db->replication_factor, *minority_status);\n        delete_msg_callback(mc->nonce, db);\n        stat_stop(dbc_stats.remote_consume_queue_in_txn, &ts_start, NO_QUORUM_ERR);\n        return NO_QUORUM_ERR;\n    }\n\n    delete_msg_callback(mc->nonce, db);\n\n    stat_stop(dbc_stats.remote_consume_queue_in_txn, &ts_start, 0);\n    return 0;\n}\n\nint _remote_subscribe_queue(WORD consumer_id, WORD shard_id, WORD app_id, WORD table_key, WORD queue_id, WORD group_id,\n                        queue_callback * callback, int64_t * prev_read_head, int64_t * prev_consume_head,\n                        int * minority_status, remote_db_t * db)\n{\n    struct timespec ts_start;\n    stat_start(dbc_stats.remote_subscribe_queue, &ts_start);\n\n    unsigned len = 0;\n    void * tmp_out_buf = NULL;\n\n    queue_query_message * q = NULL;\n    if((int) group_id == -1)\n    {\n        q = build_subscribe_queue_in_txn(consumer_id, shard_id, app_id, table_key, queue_id, NULL, get_nonce(db)); // txnid\n    }\n    else\n    {\n        q = build_subscribe_group_in_txn(consumer_id, shard_id, app_id, group_id, NULL, get_nonce(db));\n    }\n\n    *minority_status = 0;\n\n    int success = serialize_queue_message(q, (void **) &tmp_out_buf, &len, 1, NULL);\n\n    if(db->servers->no_items < db->quorum_size)\n    {\n        log_error(\"No quorum (%d/%d servers alive)\", db->servers->no_items, db->replication_factor);\n        stat_stop(dbc_stats.remote_subscribe_queue, &ts_start, NO_QUORUM_ERR);\n        return NO_QUORUM_ERR;\n    }\n    remote_server * rs = (remote_server *) (HEAD(db->servers))->value;\n\n#if CLIENT_VERBOSITY > 0\n    char print_buff[1024];\n    to_string_queue_message(q, (char *) print_buff);\n    log_info(\"Sending queue message to server %s: %s\", rs->id, print_buff);\n#endif\n\n    // Send packet to server and wait for reply:\n\n    msg_callback * mc = NULL;\n    success = send_packet_wait_replies_sync(tmp_out_buf, len, q->nonce, &mc, db);\n    assert(success == 0);\n    free_queue_message(q);\n\n    if(mc->no_replies < db->quorum_size)\n    {\n        log_error(\"No quorum (%d/%d replies received)\", mc->no_replies, db->replication_factor);\n        delete_msg_callback(mc->nonce, db);\n        stat_stop(dbc_stats.remote_subscribe_queue, &ts_start, NO_QUORUM_ERR);\n        return NO_QUORUM_ERR;\n    }\n\n    int ok_status = 0, subscription_exists = 0;\n    for(int i=0;i<mc->no_replies;i++)\n    {\n        assert(mc->reply_types[i] == RPC_TYPE_ACK);\n        ack_message * ack = (ack_message *) mc->replies[i];\n        if(ack->status == 0 || ack->status == DB_ERR_DUPLICATE_CONSUMER)\n        {\n            ok_status++;\n            if(ack->status == DB_ERR_DUPLICATE_CONSUMER)\n                subscription_exists = 1;\n        }\n        else\n        {\n            *minority_status = ack->status;\n        }\n\n#if CLIENT_VERBOSITY > 0\n        to_string_ack_message(ack, (char *) print_buff);\n        log_info(\"Got back response from server %s: %s\", rs->id, print_buff);\n#endif\n    }\n\n    if(ok_status < db->quorum_size)\n    {\n        log_error(\"No valid quorum (%d/%d valid replies received, minority_status=%d)\", ok_status, db->replication_factor, *minority_status);\n        delete_msg_callback(mc->nonce, db);\n        stat_stop(dbc_stats.remote_subscribe_queue, &ts_start, NO_QUORUM_ERR);\n        return NO_QUORUM_ERR;\n    }\n\n    delete_msg_callback(mc->nonce, db);\n\n    // Add local subscription on client:\n\n    int local_ret = -1;\n\n    if((int) group_id == -1)\n    {\n        local_ret = subscribe_queue_client(consumer_id, shard_id, app_id, table_key, queue_id, callback, 1, db);\n    }\n    else\n    {\n        local_ret = subscribe_to_group(consumer_id, shard_id, app_id, group_id, callback, 1, db);\n    }\n\n    stat_stop(dbc_stats.remote_subscribe_queue, &ts_start, 0);\n\n    return (subscription_exists || local_ret == CLIENT_ERR_SUBSCRIPTION_EXISTS)?CLIENT_ERR_SUBSCRIPTION_EXISTS:0;\n}\n\nint _remote_unsubscribe_queue(WORD consumer_id, WORD shard_id, WORD app_id, WORD table_key, WORD queue_id, WORD group_id,\n                            int * minority_status, remote_db_t * db)\n{\n    struct timespec ts_start;\n    stat_start(dbc_stats.remote_unsubscribe_queue, &ts_start);\n\n    unsigned len = 0;\n    void * tmp_out_buf = NULL;\n\n    queue_query_message * q = NULL;\n    if((int) group_id == -1)\n    {\n        q = build_unsubscribe_queue_in_txn(consumer_id, shard_id, app_id, table_key, queue_id, NULL, get_nonce(db)); // txnid\n    }\n    else\n    {\n        q = build_unsubscribe_group_in_txn(consumer_id, shard_id, app_id, group_id, NULL, get_nonce(db));\n    }\n\n    *minority_status = 0;\n\n    int success = serialize_queue_message(q, (void **) &tmp_out_buf, &len, 1, NULL);\n\n    if(db->servers->no_items < db->quorum_size)\n    {\n        log_error(\"No quorum (%d/%d servers alive)\", db->servers->no_items, db->replication_factor);\n        stat_stop(dbc_stats.remote_unsubscribe_queue, &ts_start, NO_QUORUM_ERR);\n        return NO_QUORUM_ERR;\n    }\n    remote_server * rs = (remote_server *) (HEAD(db->servers))->value;\n\n#if CLIENT_VERBOSITY > 0\n    char print_buff[1024];\n    to_string_queue_message(q, (char *) print_buff);\n    log_info(\"Sending queue message to server %s: %s\", rs->id, print_buff);\n#endif\n\n    // Send packet to server and wait for reply:\n\n    msg_callback * mc = NULL;\n    success = send_packet_wait_replies_sync(tmp_out_buf, len, q->nonce, &mc, db);\n    assert(success == 0);\n    free_queue_message(q);\n\n    if(mc->no_replies < db->quorum_size)\n    {\n        log_error(\"No quorum (%d/%d replies received)\", mc->no_replies, db->replication_factor);\n        delete_msg_callback(mc->nonce, db);\n        stat_stop(dbc_stats.remote_unsubscribe_queue, &ts_start, NO_QUORUM_ERR);\n        return NO_QUORUM_ERR;\n    }\n\n    int ok_status = 0, subscription_missing = 0;\n    for(int i=0;i<mc->no_replies;i++)\n    {\n        assert(mc->reply_types[i] == RPC_TYPE_ACK);\n        ack_message * ack = (ack_message *) mc->replies[i];\n        if(ack->status == 0 || ack->status == DB_ERR_NO_CONSUMER)\n        {\n            ok_status++;\n            if(ack->status == DB_ERR_NO_CONSUMER)\n                subscription_missing = 1;\n        }\n        else\n        {\n            *minority_status = ack->status;\n        }\n\n#if CLIENT_VERBOSITY > 0\n        to_string_ack_message(ack, (char *) print_buff);\n        log_info(\"Got back response from server %s: %s\", rs->id, print_buff);\n#endif\n    }\n\n    if(ok_status < db->quorum_size)\n    {\n        log_error(\"No valid quorum (%d/%d valid replies received, minority_status=%d)\", ok_status, db->replication_factor, *minority_status);\n        delete_msg_callback(mc->nonce, db);\n        stat_stop(dbc_stats.remote_unsubscribe_queue, &ts_start, NO_QUORUM_ERR);\n        return NO_QUORUM_ERR;\n    }\n\n    delete_msg_callback(mc->nonce, db);\n\n    // Remove local subscription from client:\n    int status = -1;\n    if((int) group_id == -1)\n    {\n            status = unsubscribe_queue_client(consumer_id, shard_id, app_id, table_key, queue_id, 1, db);\n    }\n    else\n    {\n            status = unsubscribe_from_group(consumer_id, shard_id, app_id, group_id, 1, db);\n    }\n\n    int local_ret = unsubscribe_queue_client(consumer_id, shard_id, app_id, table_key, queue_id, 1, db);\n    stat_stop(dbc_stats.remote_unsubscribe_queue, &ts_start, 0);\n\n    return (subscription_missing || local_ret == CLIENT_ERR_NO_SUBSCRIPTION_EXISTS)?CLIENT_ERR_NO_SUBSCRIPTION_EXISTS:0;\n}\n\nint remote_subscribe_queue_in_txn(WORD consumer_id, WORD shard_id, WORD app_id, WORD table_key, WORD queue_id,\n                        queue_callback * callback, int64_t * prev_read_head, int64_t * prev_consume_head,\n                        int * minority_status, uuid_t * txnid, remote_db_t * db)\n{\n    assert (0); // Not supported\n    return 0;\n}\n\nint remote_unsubscribe_queue_in_txn(WORD consumer_id, WORD shard_id, WORD app_id, WORD table_key, WORD queue_id,\n                                    int * minority_status, uuid_t * txnid, remote_db_t * db)\n{\n    assert (0); // Not supported\n    return 0;\n}\n\nint remote_subscribe_queue(WORD consumer_id, WORD shard_id, WORD app_id, WORD table_key, WORD queue_id,\n                        queue_callback * callback, int64_t * prev_read_head, int64_t * prev_consume_head,\n                        int * minority_status, remote_db_t * db)\n{\n    return _remote_subscribe_queue(consumer_id, shard_id, app_id, table_key, queue_id, (WORD) -1,\n                                    callback, prev_read_head, prev_consume_head, minority_status, db);\n}\n\nint remote_unsubscribe_queue(WORD consumer_id, WORD shard_id, WORD app_id, WORD table_key, WORD queue_id,\n                            int * minority_status, remote_db_t * db)\n{\n    return _remote_unsubscribe_queue(consumer_id, shard_id, app_id, table_key, queue_id, (WORD) -1, minority_status, db);\n}\n\nint remote_subscribe_group(WORD consumer_id, WORD shard_id, WORD app_id, WORD group_id,\n                        queue_callback * callback, int * minority_status, remote_db_t * db)\n{\n\tlog_debug(\"remote_subscribe_group(consumer_id = %d, group_id = %d)\", (int) consumer_id, (int) group_id);\n    return _remote_subscribe_queue(consumer_id, shard_id, app_id, (WORD) -1, (WORD) -1, group_id,\n                                    callback, NULL, NULL, minority_status, db);\n}\n\nint remote_unsubscribe_group(WORD consumer_id, WORD shard_id, WORD app_id, WORD group_id, int * minority_status, remote_db_t * db)\n{\n    return _remote_unsubscribe_queue(consumer_id, shard_id, app_id, (WORD) -1, (WORD) -1, group_id, minority_status, db);\n}\n\nint remote_add_queue_to_group(WORD table_key, WORD queue_id, WORD group_id, short use_lock, remote_db_t * db)\n{\n    struct timespec ts_start;\n    stat_start(dbc_stats.remote_subscribe_queue, &ts_start);\n\n    unsigned len = 0;\n    void * tmp_out_buf = NULL;\n\n    queue_query_message * q = build_add_queue_to_group_in_txn(table_key, queue_id, group_id, NULL, get_nonce(db));\n\n    int success = serialize_queue_message(q, (void **) &tmp_out_buf, &len, 1, NULL);\n\n    if(db->servers->no_items < db->quorum_size)\n    {\n        log_error(\"No quorum (%d/%d servers alive)\", db->servers->no_items, db->replication_factor);\n        stat_stop(dbc_stats.remote_subscribe_queue, &ts_start, NO_QUORUM_ERR);\n        return NO_QUORUM_ERR;\n    }\n    remote_server * rs = (remote_server *) (HEAD(db->servers))->value;\n\n#if CLIENT_VERBOSITY > 0\n    char print_buff[1024];\n    to_string_queue_message(q, (char *) print_buff);\n    log_debug(\"Sending queue message to server %s: %s\", rs->id, print_buff);\n#endif\n\n    // Send packet to server and wait for reply:\n\n    msg_callback * mc = NULL;\n    success = send_packet_wait_replies_sync(tmp_out_buf, len, q->nonce, &mc, db);\n    assert(success == 0);\n    free_queue_message(q);\n\n    if(mc->no_replies < db->quorum_size)\n    {\n        log_error(\"No quorum (%d/%d replies received)\", mc->no_replies, db->replication_factor);\n        delete_msg_callback(mc->nonce, db);\n        stat_stop(dbc_stats.remote_subscribe_queue, &ts_start, NO_QUORUM_ERR);\n        return NO_QUORUM_ERR;\n    }\n\n    for(int i=0;i<mc->no_replies;i++)\n    {\n        assert(mc->reply_types[i] == RPC_TYPE_ACK);\n        ack_message * ack = (ack_message *) mc->replies[i];\n        if(ack->status == CLIENT_ERR_SUBSCRIPTION_EXISTS)\n        {\n                delete_msg_callback(mc->nonce, db);\n                stat_stop(dbc_stats.remote_subscribe_queue, &ts_start, SUBSCRIPTION_EXISTS);\n                // TODO: align return value to use client API codes rather than server API?\n                return CLIENT_ERR_SUBSCRIPTION_EXISTS;\n        }\n\n#if CLIENT_VERBOSITY > 0\n        to_string_ack_message(ack, (char *) print_buff);\n        log_debug(\"Got back response from server %s: %s\", rs->id, print_buff);\n#endif\n    }\n\n    delete_msg_callback(mc->nonce, db);\n\n    stat_stop(dbc_stats.remote_subscribe_queue, &ts_start, 0);\n\n    return 0;\n}\n\nint remote_remove_queue_from_group(WORD table_key, WORD queue_id, WORD group_id, short use_lock, remote_db_t * db)\n{\n    struct timespec ts_start;\n    stat_start(dbc_stats.remote_subscribe_queue, &ts_start);\n\n    unsigned len = 0;\n    void * tmp_out_buf = NULL;\n\n    queue_query_message * q = build_remove_queue_from_group_in_txn(table_key, queue_id, group_id, NULL, get_nonce(db));\n\n    int success = serialize_queue_message(q, (void **) &tmp_out_buf, &len, 1, NULL);\n\n    if(db->servers->no_items < db->quorum_size)\n    {\n        log_error(\"No quorum (%d/%d servers alive)\", db->servers->no_items, db->replication_factor);\n        stat_stop(dbc_stats.remote_subscribe_queue, &ts_start, NO_QUORUM_ERR);\n        return NO_QUORUM_ERR;\n    }\n    remote_server * rs = (remote_server *) (HEAD(db->servers))->value;\n\n#if CLIENT_VERBOSITY > 0\n    char print_buff[1024];\n    to_string_queue_message(q, (char *) print_buff);\n    log_debug(\"Sending queue message to server %s: %s\", rs->id, print_buff);\n#endif\n\n    // Send packet to server and wait for reply:\n\n    msg_callback * mc = NULL;\n    success = send_packet_wait_replies_sync(tmp_out_buf, len, q->nonce, &mc, db);\n    assert(success == 0);\n    free_queue_message(q);\n\n    if(mc->no_replies < db->quorum_size)\n    {\n        log_error(\"No quorum (%d/%d replies received)\", mc->no_replies, db->replication_factor);\n        delete_msg_callback(mc->nonce, db);\n        stat_stop(dbc_stats.remote_subscribe_queue, &ts_start, NO_QUORUM_ERR);\n        return NO_QUORUM_ERR;\n    }\n\n    for(int i=0;i<mc->no_replies;i++)\n    {\n        assert(mc->reply_types[i] == RPC_TYPE_ACK);\n        ack_message * ack = (ack_message *) mc->replies[i];\n        if(ack->status == CLIENT_ERR_SUBSCRIPTION_EXISTS)\n        {\n                delete_msg_callback(mc->nonce, db);\n                stat_stop(dbc_stats.remote_subscribe_queue, &ts_start, SUBSCRIPTION_EXISTS);\n                // TODO: align return value to use client API codes rather than server API?\n                return CLIENT_ERR_SUBSCRIPTION_EXISTS;\n        }\n\n#if CLIENT_VERBOSITY > 0\n        to_string_ack_message(ack, (char *) print_buff);\n        log_debug(\"Got back response from server %s: %s\", rs->id, print_buff);\n#endif\n    }\n\n    delete_msg_callback(mc->nonce, db);\n\n    stat_stop(dbc_stats.remote_subscribe_queue, &ts_start, 0);\n\n    return 0;\n}\n\n\n// Subscription handling client-side:\n\nqueue_callback * get_queue_client_callback(WORD consumer_id, WORD shard_id, WORD app_id, WORD group_id, WORD table_key, WORD queue_id, short use_lock, remote_db_t * db)\n{\n    queue_callback_args * qca = get_queue_callback_args(table_key, queue_id,\n                                                       app_id, shard_id, consumer_id,\n                                                       group_id, QUEUE_NOTIF_ENQUEUED);\n    if(use_lock)\n        pthread_mutex_lock(db->subscribe_lock);\n\n    snode_t * subscription_node = NULL;\n\n    if((int) group_id != -1)\n    {\n        subscription_node = skiplist_search(db->group_queue_subscriptions, (WORD) qca);\n    }\n    else\n    {\n        subscription_node = skiplist_search(db->queue_subscriptions, (WORD) qca);\n    }\n\n    if(use_lock)\n        pthread_mutex_unlock(db->subscribe_lock);\n\n    return (subscription_node != NULL)? ((queue_callback *) (subscription_node->value)):NULL;\n}\n\nint subscribe_queue_client(WORD consumer_id, WORD shard_id, WORD app_id, WORD table_key, WORD queue_id,\n                    queue_callback * callback, short use_lock, remote_db_t * db)\n{\n    struct timespec ts_start;\n    stat_start(dbc_stats.subscribe_queue_client, &ts_start);\n\n    queue_callback_args * qca = get_queue_callback_args(table_key, queue_id, app_id, shard_id, consumer_id, (WORD) -1, QUEUE_NOTIF_ENQUEUED);\n\n    if(use_lock)\n        pthread_mutex_lock(db->subscribe_lock);\n\n    snode_t * subscription_node = skiplist_search(db->queue_subscriptions, (WORD) qca);\n\n    if(subscription_node != NULL)\n    {\n        if(use_lock)\n            pthread_mutex_unlock(db->subscribe_lock);\n\n        stat_stop(dbc_stats.subscribe_queue_client, &ts_start, SUBSCRIPTION_EXISTS);\n        return CLIENT_ERR_SUBSCRIPTION_EXISTS; // Subscription already exists\n    }\n\n    int status = skiplist_insert(db->queue_subscriptions, (WORD) qca, (WORD) callback, &(db->fastrandstate));\n\n    if(use_lock)\n        pthread_mutex_unlock(db->subscribe_lock);\n\n    assert(status == 0);\n\n#if (VERBOSITY > 0)\n    log_info(\"CLIENT: Subscriber %\" PRId64 \"/%\" PRId64 \"/%\" PRId64 \" subscribed queue %\" PRId64 \"/%\" PRId64 \" with callback %p\",\n                    (int64_t) app_id, (int64_t) shard_id, (int64_t) consumer_id,\n                    (int64_t) table_key, (int64_t) queue_id, cs->callback);\n#endif\n\n    stat_stop(dbc_stats.subscribe_queue_client, &ts_start, 0);\n    return status;\n}\n\nint unsubscribe_queue_client(WORD consumer_id, WORD shard_id, WORD app_id, WORD table_key, WORD queue_id,\n                        short use_lock, remote_db_t * db)\n{\n    struct timespec ts_start;\n    stat_start(dbc_stats.unsubscribe_queue_client, &ts_start);\n\n    queue_callback_args * qca = get_queue_callback_args(table_key, queue_id, app_id, shard_id, consumer_id, (WORD) -1, QUEUE_NOTIF_ENQUEUED);\n\n    if(use_lock)\n        pthread_mutex_lock(db->subscribe_lock);\n\n    queue_callback * callback = skiplist_delete(db->queue_subscriptions, (WORD) qca);\n\n    if(use_lock)\n        pthread_mutex_unlock(db->subscribe_lock);\n\n    assert(callback != NULL);\n\n    free_queue_callback(callback);\n\n#if (VERBOSITY > 0)\n    log_info(\"CLIENT: Subscriber %\" PRId64 \"/%\" PRId64 \"/%\" PRId64 \" unsubscribed queue %\" PRId64 \"/%\" PRId64 \" with callback %p\",\n                    (int64_t) app_id, (int64_t) shard_id, (int64_t) consumer_id,\n                    (int64_t) table_key, (int64_t) queue_id, cs->callback);\n#endif\n\n    stat_stop(dbc_stats.unsubscribe_queue_client, &ts_start, 0);\n    return (callback != NULL)?0:CLIENT_ERR_NO_SUBSCRIPTION_EXISTS;\n}\n\nint subscribe_to_group(WORD consumer_id, WORD shard_id, WORD app_id, WORD group_id,\n                            queue_callback * callback, short use_lock, remote_db_t * db)\n{\n    struct timespec ts_start;\n    stat_start(dbc_stats.subscribe_queue_client, &ts_start);\n\n    queue_callback_args * qca = get_queue_callback_args((WORD) -1, (WORD) -1, app_id, shard_id, consumer_id, group_id, GROUP_NOTIF_ENQUEUED);\n\n    if(use_lock)\n        pthread_mutex_lock(db->subscribe_lock);\n\n    snode_t * subscription_node = skiplist_search(db->group_queue_subscriptions, (WORD) qca);\n\n    if(subscription_node != NULL)\n    {\n        if(use_lock)\n            pthread_mutex_unlock(db->subscribe_lock);\n\n        stat_stop(dbc_stats.subscribe_queue_client, &ts_start, SUBSCRIPTION_EXISTS);\n        return CLIENT_ERR_SUBSCRIPTION_EXISTS; // Subscription already exists\n    }\n\n    int status = skiplist_insert(db->group_queue_subscriptions, (WORD) qca, (WORD) callback, &(db->fastrandstate));\n\n    if(use_lock)\n        pthread_mutex_unlock(db->subscribe_lock);\n\n    assert(status == 0);\n\n#if (VERBOSITY > 0)\n    log_debug(\"CLIENT: Subscriber %\" PRId64 \"/%\" PRId64 \"/%\" PRId64 \" subscribed group %\" PRId64 \" with callback %p\",\n                    (int64_t) app_id, (int64_t) shard_id, (int64_t) consumer_id,\n                    (int64_t) group_id, cs->callback);\n#endif\n\n    stat_stop(dbc_stats.subscribe_queue_client, &ts_start, 0);\n    return status;\n}\n\nint unsubscribe_from_group(WORD consumer_id, WORD shard_id, WORD app_id, WORD group_id,\n                            short use_lock, remote_db_t * db)\n{\n    struct timespec ts_start;\n    stat_start(dbc_stats.unsubscribe_queue_client, &ts_start);\n\n    queue_callback_args * qca = get_queue_callback_args((WORD) -1, (WORD) -1, app_id, shard_id, consumer_id, group_id, QUEUE_NOTIF_ENQUEUED);\n\n    if(use_lock)\n        pthread_mutex_lock(db->subscribe_lock);\n\n    queue_callback * callback = skiplist_delete(db->group_queue_subscriptions, (WORD) qca);\n\n    if(use_lock)\n        pthread_mutex_unlock(db->subscribe_lock);\n\n    assert(callback != NULL);\n\n    free_queue_callback(callback);\n\n#if (VERBOSITY > 0)\n        log_info(\"CLIENT: Subscriber %\" PRId64 \"/%\" PRId64 \"/%\" PRId64 \" unsubscribed group %\" PRId64 \" with callback %p\",\n                    (int64_t) app_id, (int64_t) shard_id, (int64_t) consumer_id,\n                    (int64_t) group_id, cs->callback);\n#endif\n\n    stat_stop(dbc_stats.unsubscribe_queue_client, &ts_start, 0);\n    return (callback != NULL)?0:CLIENT_ERR_NO_SUBSCRIPTION_EXISTS;\n}\n\n\n\n// Txn mgmt:\n\nuuid_t * remote_new_txn(remote_db_t * db)\n{\n    uuid_t * txnid = NULL;\n    unsigned len = 0;\n    void * tmp_out_buf = NULL;\n    int status = -2;\n\n    if(db->servers->no_items < db->quorum_size)\n    {\n        log_error(\"No quorum (%d/%d servers alive)\", db->servers->no_items, db->replication_factor);\n        return NULL;\n    }\n    remote_server * rs = (remote_server *) (HEAD(db->servers))->value;\n\n    while(status == -2) // txnid already exists on server\n    {\n        txnid = new_client_txn(db, &(db->fastrandstate));\n        txn_message * q = build_new_txn(txnid, get_nonce(db));\n        int success = serialize_txn_message(q, (void **) &tmp_out_buf, &len, 1, NULL);\n\n#if CLIENT_VERBOSITY > 0\n        char print_buff[1024];\n        to_string_txn_message(q, (char *) print_buff);\n        log_info(\"Sending new txn to server %s: %s\", rs->id, print_buff);\n#endif\n\n        // Send packet to server and wait for reply:\n\n        msg_callback * mc = NULL;\n        success = send_packet_wait_replies_sync(tmp_out_buf, len, q->nonce, &mc, db);\n        assert(success == 0);\n        free_txn_message(q);\n\n        if(mc->no_replies < db->quorum_size)\n        {\n            log_error(\"No quorum (%d/%d replies received)\", mc->no_replies, db->replication_factor);\n            delete_msg_callback(mc->nonce, db);\n            return NULL;\n        }\n\n        int ok_status = 0, err_status = 0;\n\n        for(int i=0;i<mc->no_replies;i++)\n        {\n            assert(mc->reply_types[i] == RPC_TYPE_ACK);\n            ack_message * ack = (ack_message *) mc->replies[i];\n            if(ack->status == 0)\n                ok_status++;\n            else\n                err_status = ack->status;\n\n#if CLIENT_VERBOSITY > 0\n            to_string_ack_message(ack, (char *) print_buff);\n            log_info(\"Got back response from server %s: %s\", rs->id, print_buff);\n#endif\n        }\n\n        // TO DO: Update my_lc from each ACK reply received from servers:\n\n        if(ok_status >= db->quorum_size)\n            err_status = 0;\n\n        delete_msg_callback(mc->nonce, db);\n\n        status = err_status;\n    }\n\n    assert(status == 0);\n\n    return txnid;\n}\n\nint _remote_validate_txn(uuid_t * txnid, vector_clock * version, remote_server * rs_in, int * minority_status, remote_db_t * db)\n{\n    unsigned len = 0;\n    void * tmp_out_buf = NULL;\n    *minority_status = 0;\n\n    txn_message * q = build_validate_txn(txnid, version, get_nonce(db));\n    int success = serialize_txn_message(q, (void **) &tmp_out_buf, &len, 1, version);\n\n    if(db->servers->no_items < db->quorum_size)\n    {\n        log_error(\"No quorum (%d/%d servers alive)\", db->servers->no_items, db->replication_factor);\n        return NO_QUORUM_ERR;\n    }\n    remote_server * rs = (rs_in != NULL)?(rs_in):((remote_server *) (HEAD(db->servers))->value);\n\n#if CLIENT_VERBOSITY > 0\n    char print_buff[1024];\n    to_string_txn_message(q, (char *) print_buff);\n    log_info(\"Sending validate txn: %s\", print_buff);\n#endif\n\n    // Send packet to server and wait for reply:\n\n    msg_callback * mc = NULL;\n    success = send_packet_wait_replies_sync(tmp_out_buf, len, q->nonce, &mc, db);\n    assert(success == 0);\n    free_txn_message(q);\n\n    if(mc->no_replies < db->quorum_size)\n    {\n        log_error(\"No quorum (%d/%d replies received)\", mc->no_replies, db->replication_factor);\n        delete_msg_callback(mc->nonce, db);\n        return NO_QUORUM_ERR;\n    }\n\n    int ok_status = 0, abort_status = 0;\n\n    for(int i=0;i<mc->no_replies;i++)\n    {\n        assert(mc->reply_types[i] == RPC_TYPE_ACK);\n        ack_message * ack = (ack_message *) mc->replies[i];\n        if(ack->status == VAL_STATUS_COMMIT)\n            ok_status++;\n        else if(ack->status == VAL_STATUS_ABORT)\n            abort_status++;\n        else if(ack->status == VAL_STATUS_ABORT_SCHEMA)\n            *minority_status = ack->status;\n\n#if CLIENT_VERBOSITY > 0\n        to_string_ack_message(ack, (char *) print_buff);\n        log_info(\"Got back response from server %s: %s\", rs->id, print_buff);\n#endif\n    }\n\n    if(ok_status < db->quorum_size)\n    {\n        log_error(\"No valid quorum (%d/%d valid replies received (%d aborts), minority_status=%d)\", ok_status, db->replication_factor, abort_status, *minority_status);\n        delete_msg_callback(mc->nonce, db);\n        return VAL_STATUS_ABORT;\n    }\n\n    delete_msg_callback(mc->nonce, db);\n\n    return VAL_STATUS_COMMIT;\n}\n\nint remote_validate_txn(uuid_t * txnid, int * minority_status, remote_db_t * db)\n{\n    struct timespec ts_start;\n    stat_start(dbc_stats.remote_validate_txn, &ts_start);\n\n    vector_clock * version = get_lc(db);\n\n    int ret = _remote_validate_txn(txnid, get_lc(db), NULL, minority_status, db);\n\n    free_vc(version);\n\n    stat_stop(dbc_stats.remote_validate_txn, &ts_start, 0);\n    return ret;\n}\n\nint _remote_abort_txn(uuid_t * txnid, remote_server * rs_in, remote_db_t * db)\n{\n    struct timespec ts_start;\n    stat_start(dbc_stats.remote_abort_txn, &ts_start);\n\n    unsigned len = 0;\n    void * tmp_out_buf = NULL;\n\n    txn_message * q = build_abort_txn(txnid, get_nonce(db));\n    int success = serialize_txn_message(q, (void **) &tmp_out_buf, &len, 1, NULL);\n\n    if(db->servers->no_items < db->quorum_size)\n    {\n        log_error(\"No quorum (%d/%d servers alive)\", db->servers->no_items, db->replication_factor);\n        stat_stop(dbc_stats.remote_abort_txn, &ts_start, NO_QUORUM_ERR);\n        return NO_QUORUM_ERR;\n    }\n    remote_server * rs = (rs_in != NULL)?(rs_in):((remote_server *) (HEAD(db->servers))->value);\n\n#if CLIENT_VERBOSITY > 0\n    char print_buff[1024];\n    to_string_txn_message(q, (char *) print_buff);\n    log_info(\"Sending abort txn: %s\", print_buff);\n#endif\n\n    // Send packet to server and wait for reply:\n\n    msg_callback * mc = NULL;\n    success = send_packet_wait_replies_sync(tmp_out_buf, len, q->nonce, &mc, db);\n    assert(success == 0);\n    free_txn_message(q);\n\n    if(mc->no_replies < db->quorum_size)\n    {\n        log_error(\"No quorum (%d/%d replies received)\", mc->no_replies, db->replication_factor);\n        delete_msg_callback(mc->nonce, db);\n        stat_stop(dbc_stats.remote_abort_txn, &ts_start, NO_QUORUM_ERR);\n        return NO_QUORUM_ERR;\n    }\n\n    int ok_status = 0, err_status = 0;\n\n    for(int i=0;i<mc->no_replies;i++)\n    {\n        assert(mc->reply_types[i] == RPC_TYPE_ACK);\n        ack_message * ack = (ack_message *) mc->replies[i];\n        if(ack->status == 0)\n            ok_status++;\n        else\n            err_status = ack->status;\n\n#if CLIENT_VERBOSITY > 0\n        to_string_ack_message(ack, (char *) print_buff);\n        log_info(\"Got back response from server %s: %s\", rs->id, print_buff);\n#endif\n    }\n\n    if(ok_status >= db->quorum_size)\n        err_status = 0;\n\n    delete_msg_callback(mc->nonce, db);\n\n    stat_stop(dbc_stats.remote_abort_txn, &ts_start, 0);\n    return err_status;\n}\n\nint remote_abort_txn(uuid_t * txnid, remote_db_t * db)\n{\n    return _remote_abort_txn(txnid, NULL, db);\n}\n\nint _remote_persist_txn(uuid_t * txnid, vector_clock * version, remote_server * rs_in, int * minority_status, remote_db_t * db)\n{\n    unsigned len = 0;\n    void * tmp_out_buf = NULL;\n\n    txn_message * q = build_commit_txn(txnid, version, get_nonce(db));\n    int success = serialize_txn_message(q, (void **) &tmp_out_buf, &len, 1, version);\n    *minority_status = 0;\n\n    if(db->servers->no_items < db->quorum_size)\n    {\n        log_error(\"No quorum (%d/%d servers alive)\", db->servers->no_items, db->replication_factor);\n        return NO_QUORUM_ERR;\n    }\n    remote_server * rs = (rs_in != NULL)?(rs_in):((remote_server *) (HEAD(db->servers))->value);\n\n#if CLIENT_VERBOSITY > 0\n    char print_buff[1024];\n    to_string_txn_message(q, (char *) print_buff);\n    log_info(\"Sending commit txn: %s\", print_buff);\n#endif\n\n    // Send packet to server and wait for reply:\n\n    msg_callback * mc = NULL;\n    success = send_packet_wait_replies_sync(tmp_out_buf, len, q->nonce, &mc, db);\n    assert(success == 0);\n    free_txn_message(q);\n\n    if(mc->no_replies < db->quorum_size)\n    {\n        log_error(\"No quorum (%d/%d replies received)\", mc->no_replies, db->replication_factor);\n        delete_msg_callback(mc->nonce, db);\n        return NO_QUORUM_ERR;\n    }\n\n    int ok_status = 0;\n\n    for(int i=0;i<mc->no_replies;i++)\n    {\n        if(mc->reply_types[i] != RPC_TYPE_ACK)\n        {\n            log_error(\"Received unexpected reply type: %d\", mc->reply_types[i]);\n            assert(0);\n        }\n        ack_message * ack = (ack_message *) mc->replies[i];\n        if(ack->status == 0)\n            ok_status++;\n        else\n            *minority_status = ack->status;\n\n#if CLIENT_VERBOSITY > 0\n        to_string_ack_message(ack, (char *) print_buff);\n        log_info(\"Got back response from server %s: %s\", rs->id, print_buff);\n#endif\n    }\n\n    if(ok_status < db->quorum_size)\n    {\n        log_error(\"No valid quorum (%d/%d valid replies received), minority_status = %d\", ok_status, db->replication_factor, *minority_status);\n        delete_msg_callback(mc->nonce, db);\n        return NO_QUORUM_ERR;\n    }\n\n    delete_msg_callback(mc->nonce, db);\n\n    return 0;\n}\n\nint remote_commit_txn(uuid_t * txnid, int * minority_status, remote_db_t * db)\n{\n    struct timespec ts_start;\n    stat_start(dbc_stats.remote_commit_txn, &ts_start);\n\n    unsigned len = 0;\n    void * tmp_out_buf = NULL;\n\n#if (CLIENT_VERBOSITY > 0)\n    char uuid_str[37];\n    uuid_unparse_lower(*txnid, uuid_str);\n#endif\n#if (CLIENT_VERBOSITY > 1)\n    log_info(\"CLIENT: Attempting to validate txn %s\", uuid_str);\n#endif\n\n    if(db->servers->no_items < db->quorum_size)\n    {\n        log_error(\"No quorum (%d/%d servers alive)\", db->servers->no_items, db->replication_factor);\n        stat_stop(dbc_stats.remote_commit_txn, &ts_start, NO_QUORUM_ERR);\n        return NO_QUORUM_ERR;\n    }\n    remote_server * rs = (remote_server *) (HEAD(db->servers))->value;\n\n    vector_clock * commit_stamp = get_lc(db);\n\n    int val_res = _remote_validate_txn(txnid, commit_stamp, rs, minority_status, db);\n\n#if (CLIENT_VERBOSITY > 0)\n    log_info(\"CLIENT: validate txn %s from server %s returned %d, minority_status %d\", uuid_str, rs->id, val_res, *minority_status);\n#endif\n\n    switch(val_res)\n    {\n        case VAL_STATUS_COMMIT:\n        {\n            int persist_status = NO_SUCH_TXN, minority_status_persist, retry = 0;\n            while(persist_status != 0)\n            {\n                persist_status = _remote_persist_txn(txnid, commit_stamp, rs, &minority_status_persist, db);\n#if (CLIENT_VERBOSITY > 0)\n                log_info(\"CLIENT: persist txn %s from server %s returned %d, minority_status %d\", uuid_str, rs->id, persist_status, minority_status_persist);\n#endif\n                if(retry==1)\n                    sleep(1);\n                retry=1;\n            }\n            int res = close_client_txn(*txnid, db); // Clear local cached txn state on client\n\n#if (CLIENT_VERBOSITY > 1)\n            log_info(\"CLIENT: close txn %s returned %d\", uuid_str, res);\n#endif\n            break;\n        }\n        case VAL_STATUS_ABORT:\n        case VAL_STATUS_ABORT_SCHEMA:\n        {\n            int res = _remote_abort_txn(txnid, rs, db);\n\n#if (CLIENT_VERBOSITY > 0)\n            log_info(\"CLIENT: abort txn %s from server %s returned %d\", uuid_str, rs->id, res);\n#endif\n            res = close_client_txn(*txnid, db); // Clear local cached txn state on client\n\n#if (CLIENT_VERBOSITY > 1)\n            log_info(\"CLIENT: close txn %s returned %d\", uuid_str, res);\n#endif\n\n            break;\n        }\n        case NO_QUORUM_ERR:\n        {\n            log_error(\"Validation round achieved no quorum\");\n            free_vc(commit_stamp);\n            stat_stop(dbc_stats.remote_commit_txn, &ts_start, NO_QUORUM_ERR);\n            return NO_QUORUM_ERR;\n        }\n        default:\n        {\n            assert(0);\n        }\n    }\n\n    free_vc(commit_stamp);\n\n    stat_stop(dbc_stats.remote_commit_txn, &ts_start, 0);\n    return val_res;\n}\n\n// Txn state handling client-side:\n\ntxn_state * get_client_txn_state(uuid_t txnid, remote_db_t * db)\n{\n    snode_t * txn_node = (snode_t *) skiplist_search(db->txn_state, (WORD) txnid);\n\n#if (CLIENT_VERBOSITY > 0)\n    char uuid_str[37];\n    uuid_unparse_lower(txnid, uuid_str);\n    log_info(\"CLIENT: get_client_txn_state(%s): skiplist_search() returned: %p / %p\", uuid_str, txn_node, (txn_node != NULL)? (txn_state *) txn_node->value : NULL);\n#endif\n\n    return (txn_node != NULL)? (txn_state *) txn_node->value : NULL;\n}\n\nuuid_t * new_client_txn(remote_db_t * db, unsigned int * seedptr)\n{\n    txn_state * ts = NULL, * previous = NULL;\n\n    pthread_mutex_lock(db->txn_state_lock);\n\n    while(ts == NULL)\n    {\n        ts = init_txn_state();\n        previous = get_client_txn_state(ts->txnid, db);\n        if(previous != NULL)\n        {\n            free_txn_state(ts);\n            ts = NULL;\n        }\n    }\n\n    skiplist_insert(db->txn_state, (WORD) (ts->txnid), (WORD) ts, seedptr);\n\n    pthread_mutex_unlock(db->txn_state_lock);\n\n    return &(ts->txnid);\n}\n\nint close_client_txn(uuid_t txnid, remote_db_t * db)\n{\n    struct timespec ts_start;\n    stat_start(dbc_stats.close_client_txn, &ts_start);\n\n    pthread_mutex_lock(db->txn_state_lock);\n\n    txn_state * ts = get_client_txn_state(txnid, db);\n    if(ts == NULL) { // No such txn\n        pthread_mutex_unlock(db->txn_state_lock);\n        stat_stop(dbc_stats.close_client_txn, &ts_start, NO_SUCH_TXN);\n        return NO_SUCH_TXN;\n    }\n\n    skiplist_delete(db->txn_state, (WORD) txnid);\n    free_txn_state(ts);\n    pthread_mutex_unlock(db->txn_state_lock);\n\n    stat_stop(dbc_stats.close_client_txn, &ts_start, 0);\n    return 0;\n}\n\n// Msg callback handling:\n\nmsg_callback * get_msg_callback(int64_t nonce, WORD client_id, void (*callback)(void *), int replication_factor)\n{\n    msg_callback * mc = (msg_callback *) malloc(sizeof(msg_callback) +\n                            2 * sizeof(pthread_mutex_t) + sizeof(pthread_cond_t) +\n                            replication_factor * (sizeof(void *) + sizeof(short) ));\n    mc->client_id = client_id;\n    mc->nonce = nonce;\n    mc->lock = (pthread_mutex_t *) ((char *)mc + sizeof(msg_callback));\n    mc->signal = (pthread_cond_t *) ((char *)mc + sizeof(msg_callback) + sizeof(pthread_mutex_t));\n    pthread_mutex_init(mc->lock, NULL);\n    pthread_cond_init(mc->signal, NULL);\n    mc->callback = callback;\n\n    mc->no_replies = 0;\n    mc->no_valid_replies = 0;\n    mc->reply_lock = (pthread_mutex_t *) ((char *)mc + sizeof(msg_callback) + sizeof(pthread_mutex_t) + sizeof(pthread_cond_t));\n    pthread_mutex_init(mc->reply_lock, NULL);\n//  mc->replies = (void **) ((char *)mc + sizeof(msg_callback) + 2 * sizeof(pthread_mutex_t) + sizeof(pthread_cond_t));\n//  mc->reply_types = (short *) ((char *)mc + sizeof(msg_callback) + 2 * sizeof(pthread_mutex_t) + sizeof(pthread_cond_t) + replication_factor * sizeof(void *));\n\n    mc->replies = (void **) malloc(replication_factor*sizeof(void *));\n    mc->reply_types = (short *) malloc(replication_factor*sizeof(short));\n\n    return mc;\n}\n\nint add_reply_to_msg_callback(void * reply, short reply_type, msg_callback * mc)\n{\n    int no_replies = 0;\n    int ret = pthread_mutex_lock(mc->reply_lock);\n\n    mc->replies[mc->no_replies] = reply;\n    mc->reply_types[mc->no_replies] = reply_type;\n    mc->no_replies++;\n\n    int status = 0, invalid_reply = 0;\n    if(reply_type == RPC_TYPE_ACK)\n        status = ((ack_message *) reply)->status;\n    else if(reply_type == RPC_TYPE_QUEUE)\n        status = ((queue_query_message *) reply)->status;\n\n    if(status < 0 &&\n       status != DB_ERR_DUPLICATE_QUEUE &&\n       status != DB_ERR_DUPLICATE_CONSUMER) // valid statuses\n    {\n#if (CLIENT_VERBOSITY > 0)\n        log_debug(\"Received invalid ack with status %d\", status);\n#endif\n        invalid_reply=1;\n    }\n\n    if(!invalid_reply)\n        mc->no_valid_replies++;\n\n    no_replies = mc->no_valid_replies;\n\n    ret = pthread_mutex_unlock(mc->reply_lock);\n\n    return no_replies;\n}\n\nvoid free_msg_callback(msg_callback * mc)\n{\n    free(mc->replies);\n    free(mc->reply_types);\n    free(mc);\n}\n\n// Gossip listener:\n\n#define DEBUG_GOSSIP_CALLBACK 0\n\ngossip_callback_args * get_gossip_callback_args(membership_state * membership, int status)\n{\n    gossip_callback_args * qca = (gossip_callback_args *) malloc(sizeof(gossip_callback_args));\n    qca->membership = membership;\n    qca->status = status;\n    return qca;\n}\n\nvoid free_gossip_callback_args(gossip_callback_args * qca)\n{\n    free(qca);\n}\n\ngossip_callback * get_gossip_callback(void (*callback)(gossip_callback_args *))\n{\n    gossip_callback * qc = (gossip_callback *) malloc(sizeof(gossip_callback) + sizeof(pthread_mutex_t) + sizeof(pthread_cond_t));\n    qc->lock = (pthread_mutex_t *) ((char *)qc + sizeof(gossip_callback));\n    qc->signal = (pthread_cond_t *) ((char *)qc + sizeof(gossip_callback) + sizeof(pthread_mutex_t));\n    pthread_mutex_init(qc->lock, NULL);\n    pthread_cond_init(qc->signal, NULL);\n    qc->callback = callback;\n    return qc;\n}\n\nint wait_on_gossip_callback(gossip_callback * qc)\n{\n    int ret = pthread_mutex_lock(qc->lock);\n\n#if DEBUG_GOSSIP_CALLBACK > 0\n    log_info(\"Locked gossip lock %p/%p\", qc, qc->lock);\n#endif\n\n    struct timespec ts;\n    clock_gettime(CLOCK_REALTIME, &ts);\n    ts.tv_sec += 3;\n    ret = pthread_cond_timedwait(qc->signal, qc->lock, &ts);\n\n    pthread_mutex_unlock(qc->lock);\n\n#if DEBUG_GOSSIP_CALLBACK > 0\n    log_info(\"Unlocked gossip lock %p/%p\", qc, qc->lock);\n#endif\n\n    return ret;\n}\n\nvoid free_gossip_callback(gossip_callback * qc)\n{\n    free(qc);\n}\n\nint listen_to_gossip(int status, int rack_id, int dc_id, char * hostname, unsigned short local_rts_id, remote_db_t * db)\n{\n    unsigned len = 0;\n    void * tmp_out_buf = NULL;\n\n    node_description * nd = init_node_description(status, -1, rack_id, dc_id, hostname, local_rts_id);\n    nd->node_id = get_node_id((struct sockaddr *) &(nd->address));\n    db->local_rts_id = nd->node_id;\n\n    gossip_listen_message * q = build_gossip_listen_msg(nd, get_nonce(db));\n\n    int success = serialize_gossip_listen_msg(q, (void **) &tmp_out_buf, &len);\n\n    if(db->servers->no_items < 1)\n    {\n        log_error(\"At least 1 server must be configured for the client to subscribe to gossip (%d servers configured)\", db->servers->no_items);\n        return NO_QUORUM_ERR;\n    }\n    remote_server * rs = (remote_server *) (HEAD(db->servers))->value;\n\n#if CLIENT_VERBOSITY > 0\n    char print_buff[1024];\n    to_string_gossip_listen_msg(q, (char *) print_buff);\n    log_info(\"Sending gossip listen message to server %s: %s\", rs->id, print_buff);\n#endif\n\n    // Send packet to server and wait for reply:\n\n    msg_callback * mc = NULL;\n    success = send_packet_wait_replies_sync(tmp_out_buf, len, q->nonce, &mc, db);\n    assert(success == 0);\n    free_gossip_listen_msg(q);\n\n    if(mc->no_replies < db->quorum_size)\n    {\n        log_error(\"No quorum (%d/%d replies received)\", mc->no_replies, db->replication_factor);\n        delete_msg_callback(mc->nonce, db);\n        return NO_QUORUM_ERR;\n    }\n\n    for(int i=0;i<mc->no_replies;i++)\n    {\n        assert(mc->reply_types[i] == RPC_TYPE_ACK);\n        ack_message * ack = (ack_message *) mc->replies[i];\n        if(ack->status == CLIENT_ERR_SUBSCRIPTION_EXISTS)\n        {\n                delete_msg_callback(mc->nonce, db);\n                return CLIENT_ERR_SUBSCRIPTION_EXISTS;\n        }\n\n#if CLIENT_VERBOSITY > 0\n        to_string_ack_message(ack, (char *) print_buff);\n        log_info(\"Got back response from server %s: %s\", rs->id, print_buff);\n#endif\n    }\n\n    delete_msg_callback(mc->nonce, db);\n\n    return 0;\n}\n\n\n\n\n\n\n"
  },
  {
    "path": "backend/client_api.h",
    "content": "/*\n * Copyright (C) 2019-2021 Deutsche Telekom AG\n *\n * Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:\n *\n * 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.\n *\n * 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.\n *\n * 3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission.\n *\n * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS \"AS IS\" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n */\n\n/*\n * client_api.h\n *\n *      Author: aagapi\n */\n\n#ifndef BACKEND_CLIENT_API_H_\n#define BACKEND_CLIENT_API_H_\n\n#include \"db.h\"\n#include \"queue_callback.h\"\n#include \"failure_detector/db_queries.h\"\n#include \"failure_detector/fd.h\"\n#include \"fastrand.h\"\n#include \"comm.h\"\n\n#include <stdio.h>\n#include <stdlib.h>\n#include <unistd.h>\n#include <uuid/uuid.h>\n#include <errno.h>\n\n#define RANDOM_NONCES\n\n#define CLIENT_VERBOSITY 0\n#define CLIENT_LOCK_VERBOSITY 0\n#define SYNC_SOCKET 1\n\n#define NO_QUORUM_ERR -1\n#define NO_SUCH_MSG_CALLBACK -2\n#define NO_SUCH_TXN -3\n#define SUBSCRIPTION_EXISTS -4\n#define NO_SUBSCRIPTION_EXISTS -5\n\n#define DEBUG_BLOBS 0\n\n/*\n * Statistics per type of DB operation\n *\n * When a DB operation is called through the client API, we immediately\n * increment the \"called\" counter. When an operation ends successfully we\n * increment the success counter or if it fails, we increment the error counter.\n * This way, we can see the number of outstanding requests through\n * called-(success+error). no_quorum is a specific error type, and such errors\n * are counted both using the generic \"error\" counter as well as the more\n * specific no_quorum counter. The timing of each operation is recorded in the\n * time_ buckets, forming a histogram.\n */\nstruct dbc_ops_stat {\n    const char *name;\n    unsigned long long called;     // Number of calls of this op, incremented on start\n    unsigned long long completed;  // Number of completed, incremented on completion\n    // Currently outstanding / in-flight ops is the diff between called - completed\n    unsigned long long success;    // Number of successful calls of this op\n    unsigned long long error;      // Number of failed calls of this op, includes all errors\n    // success + error = completed\n    unsigned long long no_quorum;  // Number of failed calls with NO_QUORUM_ERR\n    unsigned long long time_sum;   // nanoseconds spent waiting for op to complete\n    unsigned long long time_100ns; // bucket for <100ns\n    unsigned long long time_1us;   // bucket for <1us\n    unsigned long long time_10us;  // bucket for <10us\n    unsigned long long time_100us; // bucket for <100us\n    unsigned long long time_1ms;   // bucket for <1ms\n    unsigned long long time_10ms;  // bucket for <10ms\n    unsigned long long time_100ms; // bucket for <100ms\n    unsigned long long time_1s;    // bucket for <1s\n    unsigned long long time_10s;   // bucket for <10s\n    unsigned long long time_100s;  // bucket for <100s\n    unsigned long long time_inf;   // bucket for <+Inf\n};\n\n// List of operation types\n#define LIST_OF_DBC_OPS \\\n    X(remote_insert_in_txn) \\\n    X(remote_update_in_txn) \\\n    X(remote_delete_row_in_txn) \\\n    X(remote_delete_cell_in_txn) \\\n    X(remote_delete_by_index_in_txn) \\\n    X(remote_search_in_txn) \\\n    X(remote_search_clustering_in_txn) \\\n    X(remote_search_columns_in_txn) \\\n    X(remote_search_index_in_txn) \\\n    X(remote_range_search_in_txn) \\\n    X(remote_range_search_clustering_in_txn) \\\n    X(remote_range_search_index_in_txn) \\\n    X(remote_read_full_table_in_txn) \\\n    X(remote_create_queue_in_txn) \\\n    X(remote_delete_queue_in_txn) \\\n    X(remote_enqueue_in_txn) \\\n    X(remote_read_queue_in_txn) \\\n    X(remote_consume_queue_in_txn) \\\n    X(remote_subscribe_queue) \\\n    X(remote_unsubscribe_queue) \\\n    X(remote_subscribe_queue_in_txn) \\\n    X(remote_unsubscribe_queue_in_txn) \\\n    X(subscribe_queue_client) \\\n    X(unsubscribe_queue_client) \\\n    X(remote_validate_txn) \\\n    X(remote_abort_txn) \\\n    X(remote_commit_txn) \\\n    X(close_client_txn)\n\n// DB client statistics per operation type\nstruct dbc_stat {\n    // Generate the DB client stats structure, based on the list of operations\n#define X(ops_name) \\\n    struct dbc_ops_stat *ops_name;\nLIST_OF_DBC_OPS\n#undef X\n};\n\nvoid init_dbc_stats();\n\n// Remote DB API:\n\ntypedef struct msg_callback\n{\n    void (*callback)(void *);\n    WORD client_id;\n    int64_t nonce;\n    pthread_mutex_t * lock;\n    pthread_cond_t * signal;\n\n    pthread_mutex_t * reply_lock;\n    void ** replies;\n    short * reply_types;\n    short no_replies;\n    short no_valid_replies;\n} msg_callback;\n\nmsg_callback * get_msg_callback(int64_t nonce, WORD client_id, void (*callback)(void *), int replication_factor);\nint add_reply_to_msg_callback(void * reply, short reply_type, msg_callback * mc);\nvoid free_msg_callback(msg_callback * mc);\n\ntypedef struct remote_db {\n    int db_id;\n    skiplist_t * servers; // List of remote database servers\n    skiplist_t * rtses; // List of connected rts-es\n    skiplist_t * actors; // List of actors to be deployed in the system\n\n    skiplist_t * txn_state; // Client cache of txn state\n    skiplist_t * queue_subscriptions; // Client queue subscriptions\n    skiplist_t * group_queue_subscriptions; // Group client queue subscriptions\n    skiplist_t * msg_callbacks; // Client msg callbacks\n    pthread_mutex_t* subscribe_lock;\n    pthread_mutex_t* msg_callbacks_lock;\n    pthread_mutex_t* txn_state_lock;\n\n    int replication_factor;\n    int quorum_size;\n    int rpc_timeout;\n    int actor_replication_factor;\n\n    pthread_t comm_thread;\n    short stop_comm;\n    fd_set readfds;\n    int wakeup_pipe[2];\n\n    int64_t requests;\n    unsigned int fastrandstate;\n\n    pthread_mutex_t* lc_lock;\n    vector_clock * my_lc;\n\n    vector_clock * current_view_id;\n    pthread_mutex_t * gossip_lock;\n    pthread_cond_t * gossip_signal;\n\n    hash_ring * _rts_ring; // Consistent hashing ring for actor-to-rts placement\n    int local_rts_id;\n} remote_db_t;\n\ntypedef struct gossip_callback_args\n{\n    membership_state * membership;\n    int status;\n} gossip_callback_args;\n\ntypedef struct gossip_callback\n{\n    void (*callback)(gossip_callback_args *);\n    pthread_mutex_t * lock;\n    pthread_cond_t * signal;\n} gossip_callback;\n\nremote_db_t * get_remote_db(int replication_factor, int rack_id, int dc_id, char * hostname, unsigned short local_rts_id,\n                            int no_seeds, char ** seed_hosts, int * seed_ports, unsigned int * seedptr);\nint add_server_to_membership(char *hostname, int portno, int status, remote_db_t * db, unsigned int * seedptr);\nmsg_callback * add_msg_callback(int64_t nonce, void (*callback)(void *), remote_db_t * db);\nint delete_msg_callback(int64_t nonce, remote_db_t * db);\nint wait_on_msg_callback(msg_callback * mc, remote_db_t * db);\nint add_reply_to_nonce(void * reply, short reply_type, int64_t nonce, remote_db_t * db);\nint64_t get_nonce(remote_db_t * db);\nvector_clock * get_lc(remote_db_t * db);\nvector_clock * get_and_increment_lc(remote_db_t * db, int node_id);\nint update_lc_protected(remote_db_t * db, vector_clock * vc_in);\nint free_remote_db(remote_db_t * db);\nint close_remote_db(remote_db_t * db);\nint sockaddr_cmp(WORD a1, WORD a2);\nint queue_callback_cmp(WORD e1, WORD e2);\n\n// Write ops:\n\nint remote_insert_in_txn(WORD * column_values, int no_cols, int no_primary_keys, int no_clustering_keys,\n                        WORD blob, size_t blob_size, WORD table_key, int * minority_status,\n                        uuid_t * txnid, remote_db_t * db);\nint remote_update_in_txn(int * col_idxs, int no_cols, WORD * column_values, WORD blob, size_t blob_size,\n                        WORD table_key, int * minority_status, uuid_t * txnid, remote_db_t * db);\nint remote_delete_row_in_txn(WORD * column_values, int no_primary_keys, WORD table_key, int * minority_status,\n                                uuid_t * txnid, remote_db_t * db);\nint remote_delete_cell_in_txn(WORD * column_values, int no_primary_keys, int no_clustering_keys,\n                               WORD table_key, int * minority_status, uuid_t * txnid, remote_db_t * db);\nint remote_delete_by_index_in_txn(WORD index_key, int idx_idx, WORD table_key, int * minority_status, uuid_t * txnid, remote_db_t * db);\n\n// Read ops:\n\nint remote_search_in_txn(WORD* primary_keys, int no_primary_keys, db_row_t** result_row, WORD table_key,\n                        int * minority_status, uuid_t * txnid, remote_db_t * db);\nint remote_search_clustering_in_txn(WORD* primary_keys, int no_primary_keys, WORD* clustering_keys, int no_clustering_keys,\n                                    db_row_t** result_row, WORD table_key, int * minority_status, uuid_t * txnid, remote_db_t * db);\nint remote_search_columns_in_txn(WORD* primary_keys, int no_primary_keys, WORD* clustering_keys, int no_clustering_keys,\n                                    WORD* col_keys, int no_columns, db_row_t** result_row, WORD table_key,\n                                    int * minority_status, uuid_t * txnid, remote_db_t * db);\nint remote_search_index_in_txn(WORD index_key, int idx_idx, db_row_t** result_row, WORD table_key,\n                                int * minority_status, uuid_t * txnid, remote_db_t * db);\nint remote_range_search_in_txn(WORD* start_primary_keys, WORD* end_primary_keys, int no_primary_keys,\n                            snode_t** start_row, snode_t** end_row,\n                            WORD table_key, int * no_items, int * minority_status, uuid_t * txnid, remote_db_t * db);\nint remote_range_search_clustering_in_txn(WORD* primary_keys, int no_primary_keys,\n                                     WORD* start_clustering_keys, WORD* end_clustering_keys, int no_clustering_keys,\n                                     snode_t** start_row, snode_t** end_row,\n                                     WORD table_key, int * no_items, int * minority_status, uuid_t * txnid, remote_db_t * db);\nint remote_range_search_index_in_txn(int idx_idx, WORD start_idx_key, WORD end_idx_key,\n                                    snode_t** start_row, snode_t** end_row,\n                                    WORD table_key, int * no_items, int * minority_status, uuid_t * txnid, remote_db_t * db);\nint remote_read_full_table_in_txn(snode_t** start_row, snode_t** end_row, WORD table_key,\n                                    int * no_items, int * minority_status, uuid_t * txnid, remote_db_t * db);\nvoid remote_print_long_table(WORD table_key, remote_db_t * db);\n\n// Queue ops:\n\nint remote_create_queue_in_txn(WORD table_key, WORD queue_id, int * minority_status, uuid_t * txnid, remote_db_t * db);\nint remote_delete_queue_in_txn(WORD table_key, WORD queue_id, int * minority_status, uuid_t * txnid, remote_db_t * db);\nint remote_enqueue_in_txn(WORD * column_values, int no_cols, WORD blob, size_t blob_size, WORD table_key,\n                        WORD queue_id, int * minority_status, uuid_t * txnid, remote_db_t * db);\nint remote_read_queue_in_txn(WORD consumer_id, WORD shard_id, WORD app_id, WORD table_key, WORD queue_id,\n        int max_entries, int * entries_read, int64_t * new_read_head,\n        snode_t** start_row, snode_t** end_row, int * minority_status, uuid_t * txnid,\n        remote_db_t * db);\nint remote_consume_queue_in_txn(WORD consumer_id, WORD shard_id, WORD app_id, WORD table_key, WORD queue_id,\n                    int64_t new_consume_head, int * minority_status, uuid_t * txnid, remote_db_t * db);\nint remote_subscribe_queue(WORD consumer_id, WORD shard_id, WORD app_id, WORD table_key, WORD queue_id,\n                        queue_callback * callback, int64_t * prev_read_head, int64_t * prev_consume_head,\n                        int * minority_status, remote_db_t * db);\nint remote_unsubscribe_queue(WORD consumer_id, WORD shard_id, WORD app_id, WORD table_key, WORD queue_id,\n                        int * minority_status, remote_db_t * db);\nint remote_subscribe_queue_in_txn(WORD consumer_id, WORD shard_id, WORD app_id, WORD table_key, WORD queue_id,\n                        queue_callback * callback, int64_t * prev_read_head, int64_t * prev_consume_head,\n                        int * minority_status, uuid_t * txnid, remote_db_t * db);\nint remote_unsubscribe_queue_in_txn(WORD consumer_id, WORD shard_id, WORD app_id, WORD table_key, WORD queue_id,\n                        int * minority_status, uuid_t * txnid, remote_db_t * db);\nint remote_subscribe_group(WORD consumer_id, WORD shard_id, WORD app_id, WORD group_id,\n                        queue_callback * callback, int * minority_status, remote_db_t * db);\nint remote_unsubscribe_group(WORD consumer_id, WORD shard_id, WORD app_id, WORD group_id,\n                        int * minority_status, remote_db_t * db);\n\n// Subscription handling client-side:\n\nqueue_callback * get_queue_client_callback(WORD consumer_id, WORD shard_id, WORD app_id, WORD group_id, WORD table_key, WORD queue_id,\n                    short use_lock, remote_db_t * db);\nint subscribe_queue_client(WORD consumer_id, WORD shard_id, WORD app_id, WORD table_key, WORD queue_id,\n                    queue_callback * callback, short use_lock, remote_db_t * db);\nint unsubscribe_queue_client(WORD consumer_id, WORD shard_id, WORD app_id, WORD table_key, WORD queue_id,\n                        short use_lock, remote_db_t * db);\nint remote_add_queue_to_group(WORD table_key, WORD queue_id, WORD group_id, short use_lock, remote_db_t * db);\nint remote_remove_queue_from_group(WORD table_key, WORD queue_id, WORD group_id, short use_lock, remote_db_t * db);\nint subscribe_to_group(WORD consumer_id, WORD shard_id, WORD app_id, WORD group_id,\n                            queue_callback * callback, short use_lock, remote_db_t * db);\nint unsubscribe_from_group(WORD consumer_id, WORD shard_id, WORD app_id, WORD group_id,\n                            short use_lock, remote_db_t * db);\n\n\n// Txn mgmt:\n\nuuid_t * remote_new_txn(remote_db_t * db);\nint remote_validate_txn(uuid_t * txnid, int * minority_status, remote_db_t * db);\nint remote_abort_txn(uuid_t * txnid, remote_db_t * db);\nint remote_commit_txn(uuid_t * txnid, int * minority_status, remote_db_t * db);\n\n// Txn state handling client-side:\n\ntxn_state * get_client_txn_state(uuid_t txnid, remote_db_t * db);\nuuid_t * new_client_txn(remote_db_t * db, unsigned int * seedptr);\nint close_client_txn(uuid_t txnid, remote_db_t * db);\n\n// Gossip listener:\n\ngossip_callback_args * get_gossip_callback_args(membership_state * ms, int status);\nvoid free_gossip_callback_args(gossip_callback_args * qca);\ngossip_callback * get_gossip_callback(void (*callback)(gossip_callback_args *));\nint wait_on_gossip_callback(gossip_callback *);\nvoid free_gossip_callback(gossip_callback * qc);\nint listen_to_gossip(int status, int rack_id, int dc_id, char * hostname, unsigned short local_rts_id, remote_db_t * db);\n\n// RTS mgmt:\n\ntypedef struct rts_descriptor\n{\n    char id[262];\n    int rack_id;\n    int dc_id;\n    char * hostname;\n    unsigned short local_rts_id;\n    unsigned int _local_rts_index;\n    struct sockaddr_in addr;\n    int status;\n} rts_descriptor;\n\nrts_descriptor * get_rts_descriptor(int rack_id, int dc_id, char *hostname, int local_rts_id, int status);\nvoid free_rts_descriptor(WORD rts_d);\nWORD get_rts_key(WORD);\nWORD get_rts_live_field(WORD);\nint add_rts_to_membership(int rack_id, int dc_id, char *hostname, int local_rts_id, int node_status, skiplist_t * rtss, hash_ring * _rts_ring, unsigned int * seedptr);\nchar * to_string_rts_membership(remote_db_t * db, char * msg_buff);\n\n// Actor mgmt:\n\n#define ACTOR_STATUS_RUNNING 0\n#define ACTOR_STATUS_MIGRATING 1\n#define ACTOR_STATUS_STOPPED 2\nstatic const char *Actor_status_name[] = {\"running\", \"migrating\", \"stopped\"};\n\n\ntypedef struct actor_descriptor\n{\n    long actor_id;\n    rts_descriptor * host_rts;\n    int is_local;\n    int status;\n} actor_descriptor;\n\nactor_descriptor * get_actor_descriptor(long actor_id, rts_descriptor * host_rts, int is_local, int status);\nvoid free_actor_descriptor(actor_descriptor * a);\nint add_actor_to_membership(long actor_id, remote_db_t * db);\nint update_actor_placement(remote_db_t * db);\nint is_actor_local(long actor_id, remote_db_t * db);\nskiplist_t * get_rtses_for_actor(long actor_id, remote_db_t * db);\nrts_descriptor * get_first_rts_for_actor(long actor_id, remote_db_t * db);\nskiplist_t * get_local_actors(remote_db_t * db);\nskiplist_t * get_remote_actors(remote_db_t * db);\nchar * to_string_actor_membership(remote_db_t * db, char * msg_buff);\n\n#endif /* BACKEND_CLIENT_API_H_ */\n"
  },
  {
    "path": "backend/comm.c",
    "content": "/*\n * Copyright (C) 2019-2021 Deutsche Telekom AG\n *\n * Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:\n *\n * 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.\n *\n * 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.\n *\n * 3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission.\n *\n * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS \"AS IS\" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n */\n\n/*\n * comm.c\n *\n *      Author: aagapi\n */\n\n#include \"comm.h\"\n#include \"log.h\"\n#include <stdio.h>\n#include <stdlib.h>\n#include <unistd.h>\n\nint parse_message_v1(void * rcv_buf, size_t rcv_msg_len, void ** out_msg, short * out_msg_type, int64_t * nonce, short is_server)\n{\n    write_query * wq;\n    read_query * rq;\n    range_read_query * rrq;\n    queue_query_message * qq;\n    ack_message * am;\n    txn_message * tm;\n\n    range_read_response_message * rrr;\n\n#if (VERBOSE_RPC > 0)\n    char print_buff[BUFSIZE];\n#endif\n    int status = 0;\n\n    if(is_server) // RPCs received by server\n    {\n        status = deserialize_write_query(rcv_buf, rcv_msg_len, &wq);\n        if(status == 0)\n        {\n#if (VERBOSE_RPC > 0)\n            to_string_write_query(wq, (char *) print_buff);\n            log_debug(\"Received write query: %s\", print_buff);\n#endif\n            *out_msg = (void *) wq;\n            *out_msg_type = RPC_TYPE_WRITE;\n            *nonce = wq->nonce;\n            return 0;\n        }\n\n        status = deserialize_read_query(rcv_buf, rcv_msg_len, &rq);\n        if(status == 0)\n        {\n#if (VERBOSE_RPC > 0)\n            to_string_read_query(rq, (char *) print_buff);\n            log_debug(\"Received read query: %s\", print_buff);\n#endif\n            *out_msg = (void *) rq;\n            *out_msg_type = RPC_TYPE_READ;\n            *nonce = rq->nonce;\n            return 0;\n        }\n\n        status = deserialize_range_read_query(rcv_buf, rcv_msg_len, &rrq);\n        if(status == 0)\n        {\n#if (VERBOSE_RPC > 0)\n            to_string_range_read_query(rrq, (char *) print_buff);\n            log_debug(\"Received range read query: %s\", print_buff);\n#endif\n            *out_msg = (void *) rrq;\n            *out_msg_type = RPC_TYPE_RANGE_READ;\n            *nonce = rrq->nonce;\n            return 0;\n        }\n\n        status = deserialize_txn_message(rcv_buf, rcv_msg_len, &tm);\n        if(status == 0)\n        {\n#if (VERBOSE_RPC > 0)\n            to_string_txn_message(tm, (char *) print_buff);\n            log_debug(\"Received txn message: %s\", print_buff);\n#endif\n            *out_msg = (void *) tm;\n            *out_msg_type = RPC_TYPE_TXN;\n            *nonce = tm->nonce;\n            return 0;\n        }\n\n        status = deserialize_queue_message(rcv_buf, rcv_msg_len, &qq);\n        if(status == 0)\n        {\n#if (VERBOSE_RPC > 0)\n            to_string_queue_message(qq, (char *) print_buff);\n            log_debug(\"Received queue query: %s\", print_buff);\n#endif\n            *out_msg = (void *) qq;\n            *out_msg_type = RPC_TYPE_QUEUE;\n            *nonce = qq->nonce;\n            return 0;\n        }\n\n        status = deserialize_ack_message(rcv_buf, rcv_msg_len, &am);\n        if(status == 0)\n        {\n#if (VERBOSE_RPC > 0)\n            to_string_ack_message(am, (char *) print_buff);\n            log_debug(\"Received ack message: %s\", print_buff);\n#endif\n            *out_msg = (void *) am;\n            *out_msg_type = RPC_TYPE_ACK;\n            *nonce = am->nonce;\n\n            return 0;\n        }\n    }\n    else // RPCs received by client\n    {\n        status = deserialize_ack_message(rcv_buf, rcv_msg_len, &am);\n        if(status == 0)\n        {\n#if (VERBOSE_RPC > 0)\n            to_string_ack_message(am, (char *) print_buff);\n            log_debug(\"Received ack message: %s\", print_buff);\n#endif\n            *out_msg = (void *) am;\n            *out_msg_type = RPC_TYPE_ACK;\n            *nonce = am->nonce;\n\n            return 0;\n        }\n\n        status = deserialize_write_query(rcv_buf, rcv_msg_len, &wq);\n        if(status == 0)\n        {\n#if (VERBOSE_RPC > 0)\n            to_string_write_query(wq, (char *) print_buff);\n            log_debug(\"Received write query: %s\", print_buff);\n#endif\n            *out_msg = (void *) wq;\n            *out_msg_type = RPC_TYPE_READ_RESPONSE;\n            *nonce = wq->nonce;\n\n            return 0;\n        }\n\n        status = deserialize_range_read_response_message(rcv_buf, rcv_msg_len, &rrr);\n        if(status == 0)\n        {\n#if (VERBOSE_RPC > 0)\n            to_string_range_read_response_message(rrr, (char *) print_buff);\n            log_debug(\"Received range read response: %s\", print_buff);\n#endif\n            *out_msg = (void *) rrr;\n            *out_msg_type = RPC_TYPE_RANGE_READ_RESPONSE;\n            *nonce = rrr->nonce;\n\n            return 0;\n        }\n\n        status = deserialize_queue_message(rcv_buf, rcv_msg_len, &qq);\n        if(status == 0)\n        {\n#if (VERBOSE_RPC > 0)\n            to_string_queue_message(qq, (char *) print_buff);\n            log_debug(\"Received queue read response: %s\", print_buff);\n#endif\n            *out_msg = (void *) qq;\n            *out_msg_type = RPC_TYPE_QUEUE;\n            *nonce = qq->nonce;\n\n            return 0;\n        }\n    }\n\n    *out_msg = NULL;\n    *out_msg_type = -1;\n    *nonce = -1;\n\n    return 1;\n}\n\nint parse_message(void * rcv_buf, size_t rcv_msg_len, void ** out_msg, short * out_msg_type, short * is_gossip_message, int64_t * nonce, short is_server, vector_clock ** vc)\n{\n    read_query * rq;\n    range_read_query * rrq;\n    queue_query_message * qq;\n    ack_message * am;\n    txn_message * tm;\n\n    range_read_response_message * rrr;\n\n#if (VERBOSE_RPC > 0)\n    char print_buff[BUFSIZE];\n#endif\n    int status = 0;\n\n    if(is_server) // RPCs received by server\n    {\n        status = deserialize_server_message(rcv_buf, rcv_msg_len, out_msg, out_msg_type, vc);\n\n        if(status == 0)\n        {\n            switch(*out_msg_type)\n            {\n                case RPC_TYPE_WRITE:\n                {\n                    write_query * wq = (write_query *) *(out_msg);\n#if (VERBOSE_RPC > 0)\n                    to_string_write_query(wq, (char *) print_buff);\n                    log_debug(\"Received write query: %s\", print_buff);\n#endif\n                    *nonce = wq->nonce;\n                    return 0;\n                }\n                case RPC_TYPE_READ:\n                {\n                    read_query * wq = (read_query *) *(out_msg);\n#if (VERBOSE_RPC > 0)\n                    to_string_read_query(wq, (char *) print_buff);\n                    log_debug(\"Received read query: %s\", print_buff);\n#endif\n                    *nonce = wq->nonce;\n                    return 0;\n                }\n                case RPC_TYPE_RANGE_READ:\n                {\n                    range_read_query * wq = (range_read_query *) *(out_msg);\n#if (VERBOSE_RPC > 0)\n                    to_string_range_read_query(wq, (char *) print_buff);\n                    log_debug(\"Received range read query: %s\", print_buff);\n#endif\n                    *nonce = wq->nonce;\n                    return 0;\n                }\n                case RPC_TYPE_QUEUE:\n                {\n                    queue_query_message * wq = (queue_query_message *) *(out_msg);\n#if (VERBOSE_RPC > 0)\n                    to_string_queue_message(wq, (char *) print_buff);\n                    log_debug(\"Received queue message: %s\", print_buff);\n#endif\n                    *nonce = wq->nonce;\n                    return 0;\n                }\n                case RPC_TYPE_TXN:\n                {\n                    txn_message * wq = (txn_message *) *(out_msg);\n#if (VERBOSE_RPC > 0)\n                    to_string_txn_message(wq, (char *) print_buff);\n                    log_debug(\"Received txn message: %s\", print_buff);\n#endif\n                    *nonce = wq->nonce;\n                    return 0;\n                }\n                case RPC_TYPE_GOSSIP_LISTEN:\n                {\n                    gossip_listen_message * wq = (gossip_listen_message *) *(out_msg);\n#if (VERBOSE_RPC > 0)\n                    to_string_gossip_listen_msg(wq, (char *) print_buff);\n                    log_debug(\"Received gossip listen message: %s\", print_buff);\n#endif\n                    *nonce = wq->nonce;\n                    return 0;\n                }\n                default:\n                {\n                    assert(0);\n                }\n            }\n        }\n    }\n    else // RPCs received by client\n    {\n        status = deserialize_client_message(rcv_buf, rcv_msg_len, out_msg, out_msg_type, is_gossip_message, vc);\n\n        if(status == 0)\n        {\n            if(*is_gossip_message)\n            {\n                return 0;\n            }\n\n            switch(*out_msg_type)\n            {\n                case RPC_TYPE_ACK:\n                {\n                    ack_message * wq = (ack_message *) *(out_msg);\n    #if (VERBOSE_RPC > 0)\n                    to_string_ack_message(wq, (char *) print_buff);\n                    log_debug(\"Received ack message: %s\", print_buff);\n    #endif\n                    *nonce = wq->nonce;\n                    return 0;\n                }\n                case RPC_TYPE_WRITE:\n                {\n                    write_query * wq = (write_query *) *(out_msg);\n#if (VERBOSE_RPC > 0)\n                    to_string_write_query(wq, (char *) print_buff);\n                    log_debug(\"Received write query: %s\", print_buff);\n#endif\n                    *nonce = wq->nonce;\n                    return 0;\n                }\n                case RPC_TYPE_RANGE_READ_RESPONSE:\n                {\n                    range_read_response_message * wq = (range_read_response_message *) *(out_msg);\n#if (VERBOSE_RPC > 0)\n                    to_string_range_read_response_message(wq, (char *) print_buff);\n                    log_debug(\"Received range read response message: %s\", print_buff);\n#endif\n                    *nonce = wq->nonce;\n                    return 0;\n                }\n                case RPC_TYPE_QUEUE:\n                {\n                    queue_query_message * wq = (queue_query_message *) *(out_msg);\n#if (VERBOSE_RPC > 0)\n                    to_string_queue_message(wq, (char *) print_buff);\n                    log_debug(\"Received queue message: %s\", print_buff);\n#endif\n                    *nonce = wq->nonce;\n                    return 0;\n                }\n                case RPC_TYPE_TXN:\n                {\n                    txn_message * wq = (txn_message *) *(out_msg);\n#if (VERBOSE_RPC > 0)\n                    to_string_txn_message(wq, (char *) print_buff);\n                    log_debug(\"Received txn message: %s\", print_buff);\n#endif\n                    *nonce = wq->nonce;\n                    return 0;\n                }\n                default:\n                {\n                    assert(0);\n                }\n            }\n        }\n    }\n\n    *out_msg = NULL;\n    *out_msg_type = -1;\n    *nonce = -1;\n\n    return 1;\n}\n\nint read_full_packet(int * sockfd, char * inbuf, size_t inbuf_size, int * msg_len, int * statusp, int (*handle_socket_close)(int * sockfd, int * status))\n{\n    int announced_msg_len = -1;\n    int read_buf_offset = 0;\n    int status = 0;\n\n    while(1) // Loop until reading complete packet:\n    {\n        assert(read_buf_offset < inbuf_size - sizeof(int));\n\n        if(read_buf_offset == 0)\n        {\n            // Read msg len header from packet:\n\n            bzero(inbuf, inbuf_size);\n            *msg_len = -1;\n\n            int size_len = read(*sockfd, inbuf, sizeof(int));\n\n            if (size_len < 0)\n            {\n                log_error(\"ERROR reading from socket\");\n                continue;\n            }\n            else if (size_len == 0)\n            {\n                handle_socket_close(sockfd, statusp);\n                status = 1;\n                break;\n            }\n\n            announced_msg_len = *((int *)inbuf);\n\n            *((int *)inbuf) = 0; // 0 back buffer\n\n            read_buf_offset = 0;\n        }\n\n        if(announced_msg_len <= 0)\n        {\n            read_buf_offset = 0;\n            continue;\n        }\n\n        *msg_len = read(*sockfd, inbuf + sizeof(int) + read_buf_offset, announced_msg_len - read_buf_offset);\n\n#if COMM_VERBOSITY > 2\n        log_debug(\"announced_msg_len=%d, msg_len=%d, read_buf_offset=%d\", announced_msg_len, *msg_len, read_buf_offset);\n#endif\n\n        if (*msg_len < 0)\n        {\n                log_error(\"ERROR reading from socket\");\n            continue;\n        }\n        else if(*msg_len == 0) // client closed socket\n        {\n            handle_socket_close(sockfd, statusp);\n            status = 1;\n            break;\n        }\n        else if(*msg_len < announced_msg_len - read_buf_offset)\n        {\n            read_buf_offset += *msg_len;\n            continue; // Continue reading socket until full packet length\n        }\n\n        break;\n    }\n\n    assert(status != 0 || announced_msg_len == *msg_len);\n\n//    read_buf_offset = 0; // Reset\n\n#if COMM_VERBOSITY > 2\n    log_debug(\"server received %d / %d bytes\", announced_msg_len, *msg_len);\n#endif\n\n    return status;\n}\n\nint sockaddr_cmp(WORD a1, WORD a2)\n{\n    struct sockaddr * x = (struct sockaddr *) a1;\n    struct sockaddr * y = (struct sockaddr *) a2;\n\n#define CMP(a, b) if (a != b) return a - b\n\n    CMP(x->sa_family, y->sa_family);\n\n    if (x->sa_family == AF_UNIX) {\n        struct sockaddr_un *xun = (void*)x, *yun = (void*)y;\n        int r = strcmp(xun->sun_path, yun->sun_path);\n        if (r != 0)\n            return r;\n    } else if (x->sa_family == AF_INET) {\n        struct sockaddr_in *xin = (void*)x, *yin = (void*)y;\n        CMP(ntohl(xin->sin_addr.s_addr), ntohl(yin->sin_addr.s_addr));\n        CMP(ntohs(xin->sin_port), ntohs(yin->sin_port));\n    } else if (x->sa_family == AF_INET6) {\n        struct sockaddr_in6 *xin6 = (void*)x, *yin6 = (void*)y;\n        int r = memcmp(xin6->sin6_addr.s6_addr, yin6->sin6_addr.s6_addr, sizeof(xin6->sin6_addr.s6_addr));\n        if (r != 0)\n            return r;\n        CMP(ntohs(xin6->sin6_port), ntohs(yin6->sin6_port));\n        CMP(xin6->sin6_flowinfo, yin6->sin6_flowinfo);\n        CMP(xin6->sin6_scope_id, yin6->sin6_scope_id);\n    } else {\n        assert(!\"unknown sa_family\");\n    }\n\n#undef CMP\n    return 0;\n}\n\n// Remote server struct fctns:\n\nremote_server * get_remote_server(char *hostname, unsigned short portno,\n        struct sockaddr_in serveraddr, struct sockaddr_in client_socket_addr,\n        int serverfd, int do_connect, int is_rts)\n{\n    remote_server * rs = (remote_server *) malloc(sizeof(remote_server));\n    bzero(rs, sizeof(remote_server));\n    rs->status = NODE_DEAD;\n    assert(serverfd != NULL_FD);\n    memcpy(&(rs->client_socket_addr), &client_socket_addr, sizeof(struct sockaddr_in));\n\n    if(serverfd > 0 || serverfd == OWN_FD) // For own node, use provided serveraddr and mark as live\n    {\n            memcpy(&(rs->serveraddr), &serveraddr, sizeof(struct sockaddr_in));\n            rs->sockfd = serverfd;\n            rs->server = gethostbyname(hostname);\n            assert(rs->server != NULL);\n            rs->status = NODE_LIVE;\n    }\n    else\n    {\n            rs->server = gethostbyname(hostname);\n        if (rs->server == NULL)\n        {\n            log_error(\"ERROR, no such host %s\", hostname);\n            free_remote_server(rs);\n            return NULL;\n        }\n\n        bzero((void *) &rs->serveraddr, sizeof(struct sockaddr_in));\n        rs->serveraddr.sin_family = AF_INET;\n        bcopy((char *)rs->server->h_addr_list[0], (char *)&(rs->serveraddr.sin_addr.s_addr), rs->server->h_length);\n        rs->serveraddr.sin_port = htons(portno);\n\n        if(do_connect)\n        {\n            rs->status = NODE_LIVE;\n\n                rs->sockfd = socket(AF_INET, SOCK_STREAM, 0);\n            if (rs->sockfd < 0)\n            {\n                log_error(\"ERROR opening socket!\");\n                free_remote_server(rs);\n                return NULL;\n            }\n\n                int connect_success = -1;\n                for(int connect_retries = 0; connect_success != 0 && connect_retries < MAX_CONNECT_RETRIES; connect_retries++)\n                {\n                    connect_success = connect(rs->sockfd, (struct sockaddr *) &rs->serveraddr, sizeof(struct sockaddr_in));\n                    if(connect_success != 0)\n                        sleep(1);\n                }\n            if (connect_success != 0)\n            {\n                log_error(\"get_remote_server: ERROR connecting to %s:%d\", hostname, portno);\n                rs->status = NODE_DEAD;\n                rs->sockfd = -1;\n            }\n        }\n    }\n\n    rs->sockfd_lock = (pthread_mutex_t*) malloc (sizeof(pthread_mutex_t));\n    pthread_mutex_init(rs->sockfd_lock, NULL);\n\n    snprintf((char *) &rs->id, 262, \"%s%s%d\", hostname, is_rts?\"/\":\":\", portno);\n\n    strncpy((char *) &(rs->hostname), hostname, strnlen(hostname, 256) + 1);\n    rs->portno = portno;\n\n    return rs;\n}\n\nint update_listen_socket(remote_server * rs, char *hostname, unsigned short portno, int do_connect)\n{\n    struct hostent * old_hostent = rs->server;\n\n    rs->server = gethostbyname(hostname);\n    if (rs->server == NULL)\n    {\n        log_error(\"ERROR, no such host %s\", hostname);\n        rs->server = old_hostent;\n        return -1;\n    }\n\n    bzero((void *) &rs->serveraddr, sizeof(struct sockaddr_in));\n    rs->serveraddr.sin_family = AF_INET;\n    bcopy((char *)rs->server->h_addr_list[0], (char *)&(rs->serveraddr.sin_addr.s_addr), rs->server->h_length);\n    rs->serveraddr.sin_port = htons(portno);\n\n    if(do_connect)\n    {\n        int old_sockfd = rs->sockfd;\n        rs->sockfd = socket(AF_INET, SOCK_STREAM, 0);\n        if (rs->sockfd < 0)\n        {\n            log_error(\"update_listen_socket: ERROR opening socket!\");\n            rs->sockfd = old_sockfd;\n            return -2;\n        }\n\n        int connect_success = -1;\n        for(int connect_retries = 0; connect_success != 0 && connect_retries < MAX_CONNECT_RETRIES; connect_retries++)\n        {\n            connect_success = connect(rs->sockfd, (struct sockaddr *) &rs->serveraddr, sizeof(struct sockaddr_in));\n            if(connect_success != 0)\n                sleep(2);\n        }\n        if(connect_success != 0)\n        {\n            log_error(\"update_listen_socket: ERROR connecting to %s:%d\", hostname, portno);\n            rs->status = NODE_DEAD;\n            rs->sockfd = -1;\n        }\n        else\n        {\n            log_debug(\"SERVER: Updated listen socket of %s/%s:%d (%s:%d) from %d to %d\", rs->id, rs->hostname, rs->portno, hostname, portno, old_sockfd, rs->sockfd);\n        }\n    }\n\n    log_debug(\"SERVER: Updating listen socket of %s/%s:%d (%d) to %s:%d\", rs->id, rs->hostname, rs->portno, rs->sockfd, hostname, portno);\n\n    snprintf((char *) &rs->id, 262, \"%s:%d\", hostname, portno);\n\n    strncpy((char *) &(rs->hostname), hostname, strnlen(hostname, 256) + 1);\n\n    rs->portno = portno;\n\n    return 0;\n}\n\nint connect_remote_server(remote_server * rs)\n{\n    if(rs->sockfd > 0)\n    {\n        log_error(\"connect_remote_server: Skipping connect, server %s:%d already connected!\", rs->hostname, rs->portno);\n        return 0;\n    }\n\n    rs->sockfd = socket(AF_INET, SOCK_STREAM, 0);\n\n    if (rs->sockfd < 0)\n    {\n        log_error(\"connect_remote_server: ERROR opening socket!\");\n        return -1;\n    }\n\n    int connect_success = -1;\n    for(int connect_retries = 0; connect_success != 0 && connect_retries < MAX_CONNECT_RETRIES; connect_retries++)\n    {\n        connect_success = connect(rs->sockfd, (struct sockaddr *) &rs->serveraddr, sizeof(struct sockaddr_in));\n        if(connect_success != 0)\n            sleep(2);\n    }\n\n    if(connect_success != 0)\n    {\n        log_error(\"connect_remote_server: ERROR connecting to %s:%d\", rs->hostname, rs->portno);\n        rs->status = NODE_DEAD;\n        rs->sockfd = -1;\n    }\n\n    return connect_success;\n}\n\nvoid free_remote_server(remote_server * rs)\n{\n    free(rs->sockfd_lock);\n    free(rs);\n}\n\nvoid free_remote_server_ptr(WORD ptr)\n{\n    free_remote_server((remote_server *) ptr);\n}\n\n\n"
  },
  {
    "path": "backend/comm.h",
    "content": "/*\n * comm.h\n *\n *      Author: aagapi\n */\n\n#ifndef BACKEND_COMM_H_\n#define BACKEND_COMM_H_\n\n#include \"failure_detector/db_queries.h\"\n#include <netinet/in.h>\n#include <sys/socket.h>\n#include <sys/types.h>\n#include <sys/un.h>\n#include <arpa/inet.h>\n#include <string.h>\n#include <sys/time.h>\n#include <sys/select.h>\n#include <netdb.h>\n\n#define VERBOSE_RPC 0\n#define COMM_VERBOSITY 2\n\n#define BUFSIZE 128 * 1024\n#define MAX_CONNECT_RETRIES 5\n\n#define NODE_LIVE 0\n#define NODE_DEAD 1\n#define NODE_PREJOINED 2\n\n#define NULL_FD -1\n#define OWN_FD -2\n#define DUMMY_FD -3\n\nstatic const char *RS_status_name[] = {\"live\", \"dead\", \"unknown\", \"prejoined\"};\n\n// Comm loop fctns:\n\nint parse_message(void * rcv_buf, size_t rcv_msg_len, void ** out_msg, short * out_msg_type, short * is_gossip_message, int64_t * nonce, short is_server, vector_clock ** vc);\nint read_full_packet(int * sockfd, char * inbuf, size_t inbuf_size, int * msg_len, int * statusp, int (*handle_socket_close)(int * sockfd, int * status));\nint sockaddr_cmp(WORD a1, WORD a2);\n\n// Remote server mgmt fctns:\n\ntypedef struct remote_server\n{\n    char hostname[256];\n    unsigned short portno;\n    int sockfd;\n    pthread_mutex_t* sockfd_lock;\n    struct sockaddr_in serveraddr;\n    struct sockaddr_in client_socket_addr;\n    struct hostent *server;\n    char id[262];\n    int status;\n    char in_buf[BUFSIZE];\n} remote_server;\n\nremote_server * get_remote_server(char *hostname, unsigned short portno, struct sockaddr_in serveraddr, struct sockaddr_in client_socket_addr, int serverfd, int do_connect, int is_rts);\nint update_listen_socket(remote_server * rs, char *hostname, unsigned short portno, int do_connect);\nint connect_remote_server(remote_server * rs);\nvoid free_remote_server(remote_server * rs);\nvoid free_remote_server_ptr(WORD ptr);\n\n\n#endif /* BACKEND_COMM_H_ */\n"
  },
  {
    "path": "backend/common.h",
    "content": "/*\n * Copyright (C) 2019-2021 Deutsche Telekom AG\n *\n * Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:\n *\n * 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.\n *\n * 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.\n *\n * 3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission.\n *\n * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS \"AS IS\" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n */\n\n/*\n * common.h\n *      Author: aagapi\n */\n\n#ifndef BACKEND_COMMON_H_\n#define BACKEND_COMMON_H_\n\n\ntypedef void *WORD;\n\n#define DB_TYPE_CHAR 0\n#define DB_TYPE_INT16 1\n#define DB_TYPE_INT32 2\n#define DB_TYPE_INT64 3\n#define DB_TYPE_FLOAT32 4\n#define DB_TYPE_FLOAT64 5\n#define DB_TYPE_BLOB 6\n\n#define VERBOSE_BACKEND 0\n\n#include <stdlib.h>\n#include <pthread.h>\n#include <unistd.h>\n#include <inttypes.h>\n#include <string.h>\n#include <assert.h>\n\n#endif /* BACKEND_COMMON_H_ */\n"
  },
  {
    "path": "backend/consumer_state.h",
    "content": "/*\n * Copyright (C) 2019-2021 Deutsche Telekom AG\n *\n * Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:\n *\n * 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.\n *\n * 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.\n *\n * 3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission.\n *\n * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS \"AS IS\" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n */\n\n/*\n * consumer_state.h\n *\n *      Author: aagapi\n */\n\n#ifndef BACKEND_CONSUMER_STATE_H_\n#define BACKEND_CONSUMER_STATE_H_\n\n#include \"common.h\"\n#include \"failure_detector/vector_clock.h\"\n\ntypedef struct group_state group_state;\n\ntypedef struct group_queue_consumer_state {\n    int64_t private_read_head;\n    int64_t private_consume_head;\n\n    vector_clock * prh_version;\n    vector_clock * pch_version;\n\n    group_state * gs;\n} group_queue_consumer_state;\n\ntypedef struct consumer_state {\n    WORD consumer_id;\n    WORD shard_id;\n    WORD app_id;\n    WORD group_id;\n\n    int64_t private_read_head;\n    int64_t private_consume_head;\n\n    vector_clock * prh_version;\n    vector_clock * pch_version;\n\n    short notified;\n\n    queue_callback* callback; // For local subscribers\n    int * sockfd; // For remote subscribers\n} consumer_state;\n\n#endif /* BACKEND_CONSUMER_STATE_H_ */\n"
  },
  {
    "path": "backend/db.c",
    "content": "/*\n * Copyright (C) 2019-2021 Deutsche Telekom AG\n *\n * Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:\n *\n * 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.\n *\n * 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.\n *\n * 3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission.\n *\n * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS \"AS IS\" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n */\n\n/*\n * db.c\n *\n *      Author: aagapi\n */\n\n#include <stdlib.h>\n#include <stdio.h>\n#include <limits.h>\n#include <string.h>\n#include <assert.h>\n\n#include \"db.h\"\n#include \"queue_groups.h\"\n#include \"skiplist.h\"\n#include \"log.h\"\n\n// DB API:\n\ndb_row_t * create_empty_row(WORD key)\n{\n    db_cell_t * row = (db_cell_t *) malloc(sizeof(db_cell_t));\n\n    memset(row, 0, sizeof(db_cell_t));\n\n    row->key = key;\n\n    row->cells = NULL;\n\n    row->column_array = NULL;\n\n    row->no_columns=0;\n\n    row->last_blob_size = 0;\n\n    row->version = NULL;\n\n    row->_next = NULL;\n\n    row->no_entries = 0;\n\n    return row;\n}\n\n\ndb_row_t * create_db_row_schemaless(WORD * column_values, int * primary_key_idxs, int no_primary_keys,\n                                    int * clustering_key_idxs, int no_clustering_keys, int no_schema_clustering_keys,\n                                    int no_cols, size_t last_blob_size, unsigned int * fastrandstate)\n{\n    assert(no_primary_keys == 1);\n    assert(no_clustering_keys >= no_schema_clustering_keys);\n\n    db_cell_t * row = create_empty_row(column_values[primary_key_idxs[0]]);\n\n    // Several clustering keys mean several levels of depth (a la super columns):\n\n    db_cell_t * crt_cell = row, * new_cell = NULL;\n\n    for(int i=0; i<no_clustering_keys; i++, crt_cell = new_cell)\n    {\n        crt_cell->cells = create_skiplist_long();\n\n        int col_index = (i<no_schema_clustering_keys)?(clustering_key_idxs[i]):(i);\n\n        new_cell = create_empty_row(column_values[col_index]);\n\n        if(i == no_clustering_keys - 1)\n        {\n            new_cell->no_columns = no_cols - no_primary_keys - no_clustering_keys;\n            new_cell->last_blob_size = last_blob_size;\n            new_cell->column_array = (WORD *) malloc(new_cell->no_columns * sizeof(WORD));\n            int j=0;\n            for(;j<new_cell->no_columns - 1;j++)\n            {\n                new_cell->column_array[j] = column_values[no_primary_keys + no_clustering_keys + j];\n            }\n\n            if(last_blob_size <= 0) // last column is value\n            {\n                new_cell->column_array[j] = column_values[no_primary_keys + no_clustering_keys + j];\n            }\n            else // last column is blob\n            {\n                new_cell->column_array[j] = malloc(last_blob_size);\n                memcpy(new_cell->column_array[j], column_values[no_primary_keys + no_clustering_keys + j], last_blob_size);\n            }\n        }\n\n        skiplist_insert(crt_cell->cells, column_values[col_index], (WORD) new_cell, fastrandstate);\n    }\n\n    return row;\n}\n\n// Assumes key indexes are in order (partition keys, followed by clustering keys, followed by columns). Also assumes a single partition key:\ndb_row_t * create_db_row_schemaless2(WORD * keys, int no_keys, WORD * cols, int no_cols, WORD last_blob, size_t last_blob_size, unsigned int * fastrandstate)\n{\n    db_cell_t * row = create_empty_row(keys[0]);\n\n    db_cell_t * crt_cell = row, * new_cell = NULL;\n    for(int i=1; i<no_keys; i++, crt_cell = new_cell)\n    {\n        crt_cell->cells = create_skiplist_long();\n\n        new_cell = create_empty_row(keys[i]);\n\n        skiplist_insert(crt_cell->cells, keys[i], (WORD) new_cell, fastrandstate);\n    }\n\n    assert(crt_cell != NULL && crt_cell->cells == NULL);\n\n    assert(last_blob == NULL || last_blob_size > 0);\n\n    int total_cols = no_cols + ((last_blob != NULL)?1:0);\n\n    crt_cell->no_columns = total_cols;\n    crt_cell->column_array = (WORD *) malloc(total_cols * sizeof(WORD));\n    int j=0;\n    for(;j<no_cols;j++)\n    {\n        crt_cell->column_array[j] = cols[j];\n    }\n\n    crt_cell->last_blob_size = last_blob_size;\n\n    if(last_blob != NULL)\n    {\n        assert(total_cols == no_cols + 1);\n\n        crt_cell->column_array[no_cols] = malloc(last_blob_size);\n        memcpy(crt_cell->column_array[no_cols], last_blob, last_blob_size);\n    }\n\n    return row;\n}\n\ndb_row_t * create_db_row_sf(WORD * column_values, db_schema_t * schema, int no_clustering_keys, int no_cols, size_t last_blob_size, unsigned int * fastrandstate)\n{\n    return create_db_row_schemaless(column_values, schema->primary_key_idxs, schema->no_primary_keys,\n                                        schema->clustering_key_idxs, no_clustering_keys, schema->min_no_clustering_keys,\n                                        no_cols, last_blob_size, fastrandstate);\n}\n\nvoid free_db_cell(db_row_t * row, db_t * db)\n{\n    if(row->cells != NULL)\n    {\n        for(snode_t * cell=HEAD(row->cells);cell!=NULL;cell=NEXT(cell))\n            if(cell->value != NULL)\n                free_db_cell(cell->value, db);\n\n        skiplist_free(row->cells);\n    }\n\n    if(row->column_array != NULL)\n    {\n        if(row->last_blob_size > 0 && row->no_columns > 0 && row->column_array[row->no_columns - 1] != NULL)\n        {\n            free(row->column_array[row->no_columns - 1]);\n        }\n\n        free(row->column_array);\n    }\n\n    if(row->group_subscriptions != NULL && db->queue_group_replication_factor > 1)\n    {\n        skiplist_free(row->group_subscriptions);\n    }\n\n    free(row);\n}\n\nvoid free_db_row(db_row_t * row, db_schema_t * schema, db_t * db)\n{\n    free_db_cell(row, db);\n}\n\ndb_t * get_db()\n{\n#if (MULTI_THREADED == 1)\n    db_t * db = (db_t *) malloc(sizeof(db_t) + sizeof(pthread_mutex_t));\n#else\n    db_t * db = (db_t *) malloc(sizeof(db_t));\n# endif\n\n    db->tables = create_skiplist_long();\n    db->txn_state = create_skiplist_uuid();\n    db->queue_groups = get_hash_ring();\n    db->queue_group_replication_factor = 1;\n    db->enable_auto_queue_group_subscriptions = ENABLE_AUTO_QUEUE_GROUP_SUBSCRIPTIONS;\n\n#if (MULTI_THREADED == 1)\n    db->txn_state_lock = (pthread_mutex_t*) ((char*) db + sizeof(db_t));\n    pthread_mutex_init(db->txn_state_lock, NULL);\n# endif\n\n    return db;\n}\n\nint db_delete_db(db_t * db)\n{\n    skiplist_free(db->tables);\n    skiplist_free(db->txn_state);\n    free_hash_ring(db->queue_groups, free_group_state);\n    free(db);\n    return 0;\n}\n\nint db_dump_db(db_t * db)\n{\n    assert(0 && \"DB dump not implemented yet\");\n\n    return 0;\n}\n\n// Deep copy constructor (to allow caller to free his structs):\ndb_schema_t* db_create_schema(int * col_types, int no_cols, int * primary_key_idxs, int no_primary_keys, int * clustering_key_idxs, int no_clustering_keys, int * index_key_idxs, int no_index_keys)\n{\n    assert(no_cols > 0 && \"Schema must have at least 1 column\");\n    assert(no_primary_keys > 0 && \"Schema must have at least 1 primary key\");\n    assert(no_primary_keys <= no_cols && \"Schema must have less primary keys than columns\");\n    assert(no_primary_keys == 1 && \"Schemas don't currently support compound primary keys\");\n    assert(primary_key_idxs[0] < no_cols && \"Primary key index out of bounds\");\n\n    db_schema_t * schema = (db_schema_t *) malloc(sizeof(db_schema_t));\n\n    schema->min_no_cols = no_cols;\n    schema->col_types = NULL;\n\n    if(col_types != NULL)\n    {\n        schema->col_types = (int *) malloc(no_cols * sizeof(int));\n        for(int i=0;i<no_cols;i++)\n            schema->col_types[i] = col_types[i];\n    }\n\n    schema->primary_key_idxs = (int *) malloc(no_primary_keys * sizeof(int));\n    schema->no_primary_keys = no_primary_keys;\n    for(int i=0;i<no_primary_keys;i++)\n        schema->primary_key_idxs[i] = primary_key_idxs[i];\n\n    schema->min_no_clustering_keys = no_clustering_keys;\n    if(no_clustering_keys > 0)\n    {\n        schema->clustering_key_idxs = (int *) malloc(no_clustering_keys * sizeof(int));\n        for(int i=0;i<no_clustering_keys;i++)\n            schema->clustering_key_idxs[i] = clustering_key_idxs[i];\n    }\n\n    schema->no_index_keys = no_index_keys;\n    if(no_index_keys > 0)\n    {\n        schema->index_key_idxs = (int *) malloc(no_index_keys * sizeof(int));\n        for(int i=0;i<no_index_keys;i++)\n            schema->index_key_idxs[i] = index_key_idxs[i];\n    }\n\n    return schema;\n}\n\nvoid free_schema(db_schema_t * schema)\n{\n    if(schema == NULL)\n        return;\n\n    if(schema->col_types != NULL)\n        free(schema->col_types);\n    if(schema->primary_key_idxs != NULL)\n        free(schema->primary_key_idxs);\n    if(schema->clustering_key_idxs != NULL)\n        free(schema->clustering_key_idxs);\n    if(schema->index_key_idxs != NULL)\n        free(schema->index_key_idxs);\n    free(schema);\n}\n\nint db_create_table(WORD table_key, db_schema_t* schema, db_t * db, unsigned int * fastrandstate)\n{\n    db_table_t * table = (db_table_t *) malloc(sizeof(db_table_t));\n\n    table->table_key = table_key;\n\n    // Deep copy of schema (to allow caller to free his copy):\n\n    table->schema = db_create_schema(schema->col_types, schema->min_no_cols, schema->primary_key_idxs, schema->no_primary_keys, schema->clustering_key_idxs, schema->min_no_clustering_keys, schema->index_key_idxs, schema->no_index_keys);\n\n    table->rows = create_skiplist_long();\n\n    table->row_tombstones = create_skiplist_long();\n\n    if(schema->no_index_keys > 0)\n        table->indexes = (skiplist_t **) malloc(schema->no_index_keys * sizeof(skiplist_t *));\n\n    for(int i=0;i<schema->no_index_keys;i++)\n        table->indexes[i] = create_skiplist_long();\n\n    table->queues = create_skiplist_long();\n\n    table->lock = (pthread_mutex_t*) malloc(sizeof(pthread_mutex_t));\n    pthread_mutex_init(table->lock, NULL);\n\n    return skiplist_insert(db->tables, table_key, (WORD) table, fastrandstate);\n}\n\nint db_create_index(int new_index, WORD table_key, db_t * db, unsigned int * fastrandstate)\n{\n    assert(0 && \"Index creation post schema creation not supported yet\");\n\n    return 0;\n}\n\nint db_delete_table(WORD table_key, db_t * db)\n{\n    db_table_t * table = (db_table_t *) skiplist_delete(db->tables, table_key);\n\n    if(table != NULL)\n    {\n        skiplist_free(table->rows);\n        for(int i=0;i<table->schema->no_index_keys;i++)\n            skiplist_free(table->indexes[i]);\n        if(table->schema->no_index_keys > 0)\n            free(table->indexes);\n        free_schema(table->schema);\n        skiplist_free(table->queues);\n        free(table);\n    }\n\n    return table != NULL;\n}\n\n\n// Table API:\n\nint table_insert(WORD * column_values, int no_cols, int no_clustering_keys, size_t last_blob_size, vector_clock * version, db_table_t * table, unsigned int * fastrandstate)\n{\n    db_schema_t * schema = table->schema;\n\n    assert(schema->no_primary_keys == 1 && \"Compound primary keys unsupported for now\");\n\n    if(no_clustering_keys < schema->min_no_clustering_keys)\n    {\n        log_error(\"SERVER: Row insert must contain at least %d schema clustering keys, only has %d keys\", schema->min_no_clustering_keys, no_clustering_keys);\n        assert(0);\n    }\n\n    assert(no_cols > (schema->no_primary_keys + no_clustering_keys) && \"Insert must contain at least 1 non-key column or blob\");\n\n    db_row_t * row = NULL;\n    snode_t * row_node = skiplist_search(table->rows, column_values[schema->primary_key_idxs[0]]);\n\n    if(row_node == NULL)\n    {\n        row = create_db_row_sf(column_values, schema, no_clustering_keys, no_cols, last_blob_size, fastrandstate);\n        row->version = (version != NULL)? copy_vc(version) : NULL;\n        skiplist_insert(table->rows, column_values[schema->primary_key_idxs[0]], (WORD) row, fastrandstate);\n    }\n    else\n    {\n        row = (db_row_t *) row_node->value;\n\n        db_row_t * cell = row, * new_cell = NULL;\n\n        for(int i=0;i<no_clustering_keys;i++, cell = new_cell)\n        {\n            int col_index = (i < schema->min_no_clustering_keys)?(schema->clustering_key_idxs[i]):(i);\n\n            snode_t * new_cell_node = skiplist_search(cell->cells, column_values[col_index]);\n\n            if(new_cell_node == NULL)\n            {\n                new_cell = create_empty_row(column_values[col_index]);\n\n                if(i < no_clustering_keys - 1)\n                {\n                    new_cell->cells = create_skiplist_long();\n                }\n\n                skiplist_insert(cell->cells, column_values[col_index], (WORD) new_cell, fastrandstate);\n            }\n            else\n            {\n                new_cell = (db_row_t *) (new_cell_node->value);\n            }\n        }\n\n        // Populate columns and set version for newly created cell:\n\n        assert(cell != NULL && cell->cells == NULL);\n\n        cell->no_columns = no_cols - schema->no_primary_keys - no_clustering_keys;\n        cell->last_blob_size = last_blob_size;\n        cell->column_array = (WORD *) malloc(cell->no_columns * sizeof(WORD));\n        int j=0;\n        for(;j<cell->no_columns - 1;j++)\n        {\n            cell->column_array[j] = column_values[schema->no_primary_keys + no_clustering_keys + j];\n        }\n\n        if(last_blob_size <= 0) // last column is value\n        {\n            cell->column_array[j] = column_values[schema->no_primary_keys + no_clustering_keys + j];\n        }\n        else // last column is blob\n        {\n            cell->column_array[j] = malloc(last_blob_size);;\n\n            memcpy(cell->column_array[j], column_values[schema->no_primary_keys + no_clustering_keys + j], last_blob_size);\n        }\n\n        if(version != NULL)\n            update_or_replace_vc(&(cell->version), version);\n    }\n\n    for(int i=0;i<schema->no_index_keys;i++)\n    {\n        if(schema->index_key_idxs[i] < no_cols)\n            skiplist_insert(table->indexes[i], column_values[schema->index_key_idxs[i]], (WORD) row, fastrandstate);\n    }\n\n    return 0;\n}\n\n\nint table_update(WORD * column_values, int no_cols, int no_clustering_keys, size_t last_blob_size, int * col_idxs, vector_clock * version, db_table_t * table)\n{\n    db_schema_t * schema = table->schema;\n\n    assert(schema->no_primary_keys == 1 && \"Compound primary keys unsupported for now\");\n\n    assert(no_clustering_keys >= schema->min_no_clustering_keys);\n\n    assert(no_cols > schema->no_primary_keys + no_clustering_keys && \"Empty update\");\n\n    assert(col_idxs[0] == schema->primary_key_idxs[0] && \"Update must contain primary key as first element\");\n\n    for(int i=0;i<schema->min_no_clustering_keys;i++)\n    {\n        assert(col_idxs[i+1] == schema->clustering_key_idxs[i] && \"Update must contain all minimal clustering keys in the right order, right after primary key\");\n    }\n\n    db_row_t * row = NULL;\n    snode_t * row_node = skiplist_search(table->rows, column_values[schema->primary_key_idxs[0]]);\n\n    if(row_node == NULL)\n        return -1;\n\n    row = (db_row_t *) row_node->value;\n\n    for(int i=0;i<no_clustering_keys;i++)\n    {\n        row_node = skiplist_search(row->cells, column_values[schema->clustering_key_idxs[i]]);\n\n        if(row_node == NULL)\n            return -1;\n\n        row = (db_row_t *) (row_node->value);\n    }\n\n    int i=schema->no_primary_keys + no_clustering_keys;\n    for(;i<no_cols - 1;i++)\n    {\n        row->column_array[col_idxs[i] - schema->no_primary_keys - no_clustering_keys] = column_values[i];\n    }\n\n    if(last_blob_size <= 0) // last column is value\n    {\n        row->column_array[col_idxs[i] - schema->no_primary_keys - no_clustering_keys] = column_values[i];\n    }\n    else // last column is blob\n    {\n        row->column_array[col_idxs[i] - schema->no_primary_keys - no_clustering_keys] = malloc(last_blob_size);\n\n        memcpy(row->column_array[col_idxs[i] - schema->no_primary_keys - no_clustering_keys], column_values[i], last_blob_size);\n    }\n\n    if(version != NULL)\n        update_or_replace_vc(&(row->version), version);\n\n    return 0;\n}\n\ndb_row_t* table_search(WORD* primary_keys, db_table_t * table)\n{\n    db_schema_t * schema = table->schema;\n\n    assert(schema->no_primary_keys == 1 && \"Compound primary keys unsupported for now\");\n\n    snode_t * row_node = skiplist_search(table->rows, primary_keys[0]);\n\n    if(row_node == NULL)\n        return NULL;\n\n    db_row_t* row = (db_row_t *) row_node->value;\n\n    return row;\n}\n\nint table_range_search(WORD* start_primary_keys, WORD* end_primary_keys, snode_t** start_row, snode_t** end_row, db_table_t * table)\n{\n    db_schema_t * schema = table->schema;\n    int no_results = 0;\n\n    assert(schema->no_primary_keys == 1 && \"Compound primary keys unsupported for now\");\n\n    if(start_primary_keys == NULL)\n        assert(end_primary_keys == NULL);\n\n    if(start_primary_keys == NULL || (start_primary_keys[0] == (WORD)LONG_MIN && end_primary_keys[0] == (WORD)(LONG_MAX - 1)))\n    {\n//      assert(end_primary_keys == NULL);\n        *start_row = HEAD(table->rows);\n        if(table->rows->no_items > 0 && (*start_row) != NULL)\n            for(*end_row=*start_row; NEXT(*end_row) != NULL; *end_row = NEXT(*end_row));\n\n        return table->rows->no_items;\n    }\n\n    *start_row = skiplist_search_higher(table->rows, start_primary_keys[0]);\n\n    if(*start_row == NULL)\n    {\n        *end_row = NULL;\n        return 0;\n    }\n\n    for(*end_row = *start_row; NEXT(*end_row) != NULL && (int64_t) (*end_row)->key < (int64_t) end_primary_keys[0]; *end_row=NEXT(*end_row), no_results++);\n\n    return no_results+1;\n}\n\nint table_verify_row_range_version(WORD* start_primary_keys, WORD* end_primary_keys, int no_primary_keys,\n                                        int64_t * range_result_keys, vector_clock ** range_result_versions, int no_range_results, db_table_t * table)\n{\n    int i = 0;\n\n    assert(no_primary_keys == 1 && \"Compound primary keys unsupported for now\");\n\n    snode_t * start_row = skiplist_search_higher(table->rows, start_primary_keys[0]);\n\n    for(snode_t * cell_row_node = start_row; cell_row_node != NULL && (int64_t) cell_row_node->key < (int64_t) end_primary_keys[0]; cell_row_node=NEXT(cell_row_node), i++)\n    {\n        db_row_t* cell_row = (db_row_t *) cell_row_node->value;\n\n        // Some keys were removed from the backend since the range query happened:\n        if(i>(no_range_results - 1))\n            return 1;\n\n        if((int64_t) cell_row->key != range_result_keys[i])\n            return 1;\n\n        int cmp = compare_vc(cell_row->version, range_result_versions[i]);\n        if(cmp != 0)\n            return cmp;\n    }\n\n    // Some extra keys were added to the backend since the range query happened:\n    if(i<no_range_results)\n        return 1;\n\n    return 0;\n}\n\nint table_range_search_copy(WORD* start_primary_keys, WORD* end_primary_keys, db_row_t** rows, db_table_t * table)\n{\n    db_schema_t * schema = table->schema;\n    int no_results = 0;\n\n    assert(schema->no_primary_keys == 1 && \"Compound primary keys unsupported for now\");\n\n    return skiplist_get_range(table->rows, start_primary_keys[0], end_primary_keys[0], (WORD**) rows, &no_results);\n}\n\ndb_row_t* table_search_clustering(WORD* primary_keys, WORD* clustering_keys, int no_clustering_keys, db_table_t * table)\n{\n    db_schema_t * schema = table->schema;\n\n    assert(no_clustering_keys > 0 && \"No clustering keys given\");\n\n//  assert(no_clustering_keys <= schema->min_no_clustering_keys && \"Too many clustering keys given\");\n\n    db_row_t* row = table_search(primary_keys, table);\n\n    if(row == NULL)\n#if (VERBOSE_BACKEND > 0)\n        log_error(\"Row not found by primary key %\" PRId64 \"!\", (int64_t) primary_keys[0]);\n#endif\n        return NULL;\n\n    for(int i=0;i<no_clustering_keys;i++)\n    {\n        snode_t * row_node = skiplist_search(row->cells, clustering_keys[i]);\n\n        if(row_node != NULL)\n        {\n            row = (db_row_t *) row_node->value;\n        }\n        else\n        {\n#if (VERBOSE_BACKEND > 0)\n            log_error(\"Row not found by clustering key %d / %\" PRId64 \"!\", i, (int64_t) clustering_keys[i]);\n#endif\n\n            return NULL;\n        }\n    }\n\n    return row;\n}\n\nint table_verify_cell_version(WORD* primary_keys, int no_primary_keys, WORD* clustering_keys, int no_clustering_keys, vector_clock * version, db_table_t * table)\n{\n    assert(no_primary_keys == 1);\n\n    snode_t * row_node = skiplist_search(table->rows, primary_keys[0]);\n\n    if(row_node == NULL)\n        return DB_ERR_NO_QUEUE;\n\n    db_row_t* row = (db_row_t *) row_node->value;\n\n    for(int i=0;i<no_clustering_keys;i++)\n    {\n        snode_t * row_node = skiplist_search(row->cells, clustering_keys[i]);\n\n        if(row_node == NULL)\n            return DB_ERR_NO_QUEUE;\n\n        row = (db_row_t *) row_node->value;\n    }\n\n    return compare_vc(version, row->version);\n}\n\nint table_range_search_clustering(WORD* primary_keys, WORD* start_clustering_keys, WORD* end_clustering_keys, int no_clustering_keys, snode_t** start_row, snode_t** end_row, db_table_t * table)\n{\n    db_schema_t * schema = table->schema;\n\n    assert(no_clustering_keys > 0 && \"No clustering keys given\");\n\n//  assert(no_clustering_keys <= schema->min_no_clustering_keys && \"Too many clustering keys given\");\n\n    db_row_t* row = table_search(primary_keys, table);\n\n    if(row == NULL)\n        return 0;\n\n    for(int i=0;i<no_clustering_keys-1;i++)\n    {\n        assert(start_clustering_keys[i] == end_clustering_keys[i] && \"For first N-1 clustering keys, start key must be equal to end key\");\n\n        snode_t * row_node = skiplist_search(row->cells, start_clustering_keys[i]);\n\n        if(row_node != NULL)\n        {\n            row = (db_row_t *) row_node->value;\n        }\n        else\n        {\n            return -1;\n        }\n    }\n\n    *start_row = skiplist_search_higher(row->cells, start_clustering_keys[no_clustering_keys-1]);\n\n    if(*start_row == NULL)\n    {\n        *end_row = NULL;\n        return 0;\n    }\n\n    int no_results = 0;\n    for(*end_row = *start_row; NEXT(*end_row) != NULL && (int64_t) (*end_row)->key < (int64_t) end_clustering_keys[no_clustering_keys-1]; *end_row=NEXT(*end_row), no_results++);\n\n    return no_results+1;\n}\n\nvoid print_long_db(db_t * db)\n{\n    log_info(\"DB: [%d tables]\", db->tables->no_items);\n\n    for(snode_t * node = HEAD(db->tables);node!=NULL;node=NEXT(node))\n        print_long_table((db_table_t *) node->value);\n}\n\nvoid print_long_table(db_table_t * table)\n{\n    log_info(\"DB_TABLE: %\" PRId64 \" [%d rows]\", (int64_t) table->table_key, table->rows->no_items);\n\n    for(snode_t * node = HEAD(table->rows);node!=NULL;node=NEXT(node))\n        print_long_row((db_row_t*) node->value);\n}\n\nvoid print_long_row(db_row_t* row)\n{\n    char to_string[MAX_PRINT_BUFF];\n    int len = 0;\n\n    long_row_to_string(row, (char *) to_string, &len, (char *) to_string);\n\n    log_info(\"DB_ROW [%d cells]: %s\", (row->cells != NULL)?(row->cells->no_items):(0), to_string);\n}\n\nvoid long_row_to_string(db_row_t* row, char * to_string, int * len, char * orig_offset)\n{\n    #define PRINT_BLOBS 1\n    #define PRINT_BLOBS_AS_LONG 1\n\n    sprintf(to_string, \"{ %\" PRId64 \", \", (int64_t) row->key);\n\n    if(row->cells != NULL)\n    {\n        assert(row->no_columns == 0);\n\n        for(snode_t* node = HEAD(row->cells); node != NULL; node = NEXT(node))\n        {\n            if(to_string + strlen(to_string) - orig_offset > MAX_PRINT_BUFF - 10)\n            {\n                sprintf(to_string + strlen(to_string), \"..\");\n                break;\n            }\n\n            db_row_t * subrow = (db_row_t *) node->value;\n            long_row_to_string(subrow, to_string + strlen(to_string), len, orig_offset);\n        }\n    }\n\n    if(row->no_columns > 0)\n    {\n        sprintf(to_string + strlen(to_string), \"[ \");\n        for(int i=0; i<row->no_columns; i++)\n        {\n            if(to_string + strlen(to_string) - orig_offset > MAX_PRINT_BUFF - 10)\n            {\n                sprintf(to_string + strlen(to_string), \"..\");\n                break;\n            }\n\n#if (PRINT_BLOBS > 0)\n            if(i<(row->no_columns - 1) || row->last_blob_size <= 0)\n            {\n                sprintf(to_string + strlen(to_string), \"%\" PRId64 \", \", (int64_t) row->column_array[i]);\n            }\n            else\n            {\n#if (PRINT_BLOBS_AS_LONG > 0)\n                for(int bi=0;bi < row->last_blob_size / sizeof(long);bi++)\n                    sprintf(to_string + strlen(to_string), \"%lu \",  *((unsigned long *) row->column_array[i] + bi));\n#else\n                sprintf(to_string + strlen(to_string), \"%s, \", (char *) row->column_array[i]);\n#endif\n            }\n\n#else\n            sprintf(to_string + strlen(to_string), \"%\" PRId64 \", \", (int64_t) row->column_array[i]);\n#endif\n        }\n        sprintf(to_string + strlen(to_string), \" ]\");\n    }\n\n    sprintf(to_string + strlen(to_string), \"}, \");\n\n    *len = strlen(to_string);\n}\n\nint table_verify_cell_range_version(WORD* primary_keys, int no_primary_keys, WORD* start_clustering_keys, WORD* end_clustering_keys, int no_clustering_keys,\n                                        int64_t * range_result_keys, vector_clock ** range_result_versions, int no_range_results, db_table_t * table)\n{\n    assert(no_primary_keys == 1);\n\n    snode_t * row_node = skiplist_search(table->rows, primary_keys[0]);\n\n    if(row_node == NULL)\n        return -1;\n\n    db_row_t* row = (db_row_t *) row_node->value;\n\n    for(int i=0;i<no_clustering_keys-1;i++)\n    {\n        assert(start_clustering_keys[i] == end_clustering_keys[i] && \"For first N-1 clustering keys, start key must be equal to end key\");\n\n        snode_t * row_node = skiplist_search(row->cells, start_clustering_keys[i]);\n\n        if(row_node == NULL)\n            return -1;\n\n        db_row_t* row = (db_row_t *) row_node->value;\n    }\n\n    snode_t * start_row = skiplist_search_higher(row->cells, start_clustering_keys[no_clustering_keys-1]);\n    int i = 0;\n\n    for(snode_t * cell_row_node = start_row; cell_row_node != NULL && (int64_t) cell_row_node->key < (int64_t) end_clustering_keys[no_clustering_keys-1]; cell_row_node=NEXT(cell_row_node), i++)\n    {\n        db_row_t* cell_row = (db_row_t *) cell_row_node->value;\n\n        // Some keys were removed from the backend since the range query happened:\n        if(i>(no_range_results - 1))\n            return 1;\n\n        if((int64_t) cell_row->key != range_result_keys[i])\n            return 1;\n\n        int cmp = compare_vc(cell_row->version, range_result_versions[i]);\n        if(cmp != 0)\n            return cmp;\n    }\n\n    // Some extra keys were added to the backend since the range query happened:\n    if(i<no_range_results)\n        return 1;\n\n    return 0;\n}\n\n\nWORD* table_search_columns(WORD* primary_keys, WORD* clustering_keys, int no_clustering_keys, int* column_idxs, int no_columns, db_table_t * table)\n{\n    db_schema_t * schema = table->schema;\n\n    assert(no_columns > 0 && \"No column indexes given\");\n    assert(no_clustering_keys >= schema->min_no_clustering_keys && \"Not enough clustering keys given\");\n\n    db_row_t* row = table_search_clustering(primary_keys, clustering_keys, no_clustering_keys, table);\n\n    if(row == NULL)\n        return NULL;\n\n    assert(row->column_array != NULL && row->no_columns > 0);\n\n    WORD* results = (WORD*) malloc(no_columns * sizeof(WORD));\n\n    for(int i=0;i<no_columns;i++)\n    {\n        assert(column_idxs[i] <= row->no_columns + schema->no_primary_keys + no_clustering_keys && \"Column index doesn't exist in backend (DB corrupted?)\");\n\n        if(column_idxs[i] < schema->no_primary_keys)\n            results[i] = primary_keys[column_idxs[i]];\n        else if(column_idxs[i] < schema->no_primary_keys + no_clustering_keys)\n            results[i] = clustering_keys[column_idxs[i] - schema->no_primary_keys];\n        else\n            results[i] = row->column_array[column_idxs[i] - schema->no_primary_keys - no_clustering_keys];\n    }\n\n    return results;\n}\n\ndb_row_t* table_search_index(WORD index_key, int idx_idx, db_table_t * table)\n{\n    db_schema_t * schema = table->schema;\n\n    assert(idx_idx <= schema->no_index_keys == 1 && \"Index index out of range\");\n\n    snode_t * row_node = skiplist_search(table->indexes[idx_idx], index_key);\n\n    if(row_node != NULL)\n    {\n        return (db_row_t *) (row_node->value);\n    }\n    else\n    {\n        return NULL;\n    }\n}\n\nint table_verify_index_version(WORD index_key, int idx_idx, vector_clock * version, db_table_t * table)\n{\n    db_schema_t * schema = table->schema;\n\n    assert(idx_idx <= schema->no_index_keys == 1 && \"Index index out of range\");\n\n    snode_t * row_node = skiplist_search(table->indexes[idx_idx], index_key);\n\n    if(row_node == NULL)\n        return 1;\n\n    return compare_vc(version, ((db_row_t *) (row_node->value))->version);\n}\n\nint table_range_search_index(int idx_idx, WORD start_idx_key, WORD end_idx_key, snode_t** start_row, snode_t** end_row, db_table_t * table)\n{\n    db_schema_t * schema = table->schema;\n    int no_results = 0;\n\n    assert(idx_idx <= schema->no_index_keys == 1 && \"Index index out of range\");\n\n    *start_row = skiplist_search_higher(table->indexes[idx_idx], start_idx_key);\n\n    for(*end_row = *start_row; (*end_row != NULL) && ((int64_t) (*end_row)->key < (int64_t) end_idx_key); *end_row=NEXT(*end_row), no_results++);\n\n    return no_results+1;\n}\n\nint table_verify_index_range_version(int idx_idx, WORD start_idx_key, WORD end_idx_key,\n                                        int64_t * range_result_keys, vector_clock ** range_result_versions, int no_range_results, db_table_t * table)\n{\n    db_schema_t * schema = table->schema;\n    int i = 0;\n\n    assert(idx_idx <= schema->no_index_keys == 1 && \"Index index out of range\");\n\n    snode_t * start_row = skiplist_search_higher(table->indexes[idx_idx], start_idx_key);\n\n    for(snode_t * cell_row_node = start_row; cell_row_node != NULL && (int64_t) cell_row_node->key < (int64_t) end_idx_key; cell_row_node=NEXT(cell_row_node), i++)\n    {\n        db_row_t* cell_row = (db_row_t *) cell_row_node->value;\n\n        // Some keys were removed from the backend since the range query happened:\n        if(i>(no_range_results - 1))\n            return 1;\n\n        if((int64_t) cell_row->key != range_result_keys[i])\n            return 1;\n\n        int cmp = compare_vc(cell_row->version, range_result_versions[i]);\n        if(cmp != 0)\n            return cmp;\n    }\n\n    // Some extra keys were added to the backend since the range query happened:\n    if(i<no_range_results)\n        return 1;\n\n    return 0;\n}\n\nint table_delete_row(WORD* primary_keys, vector_clock * version, db_table_t * table, db_t * db, unsigned int * fastrandstate)\n{\n    db_row_t* row = (db_row_t *) (skiplist_delete(table->rows, primary_keys[0]));\n\n    snode_t * exists = skiplist_search(table->row_tombstones, primary_keys[0]);\n\n    if(exists != NULL)\n        skiplist_insert(table->row_tombstones, primary_keys[0], (version != NULL)? copy_vc(version) : NULL, fastrandstate);\n\n    if(row != NULL)\n    {\n        free_db_row(row, table->schema, db);\n    }\n    else\n    {\n        log_warn(\"table_delete_row(): Row with pk %\" PRId64 \" doesn't exist!\", (int64_t) primary_keys[0]);\n    }\n\n    return row == NULL;\n}\n\nint table_delete_by_index(WORD index_key, int idx_idx, db_table_t * table)\n{\n    db_schema_t * schema = table->schema;\n\n    assert(idx_idx <= schema->no_index_keys == 1 && \"Index index out of range\");\n\n    db_row_t* row = (db_row_t *) (skiplist_delete(table->indexes[idx_idx], index_key));\n\n    // TO DO: Re-enable this after enhancing indexes:\n\n//  if(row != NULL)\n//      free_db_row(row, table->schema);\n\n    return row == NULL;\n}\n\n\n// DB API:\n\nint db_insert_transactional(WORD * column_values, int no_cols, int no_clustering_keys, size_t last_blob_size, vector_clock * version, WORD table_key, db_t * db, unsigned int * fastrandstate)\n{\n#if (VERBOSE_BACKEND > 0)\n    log_info(\"BACKEND: db_insert_transactional: Attempting to insert %d total columns into backend:\", min_no_cols);\n    for(int i=0;i<min_no_cols;i++)\n        log_info(\"column_values[%d] = %\" PRId64 \"\", i, (int64_t) column_values[i]);\n#endif\n\n    snode_t * node = skiplist_search(db->tables, table_key);\n\n    if(node == NULL)\n        return -1;\n\n    db_table_t * table = (db_table_t *) (node->value);\n\n    return table_insert(column_values, no_cols, no_clustering_keys, last_blob_size, version, table, fastrandstate);\n}\n\nint db_insert(WORD * column_values, int no_cols, int no_clustering_keys, size_t last_blob_size, WORD table_key, db_t * db, unsigned int * fastrandstate)\n{\n    return db_insert_transactional(column_values, no_cols, no_clustering_keys, last_blob_size, NULL, table_key, db, fastrandstate);\n}\n\nint db_update_transactional(WORD * column_values, int no_cols, int no_clustering_keys, size_t last_blob_size, int * col_idxs, vector_clock * version, WORD table_key, db_t * db)\n{\n    snode_t * node = skiplist_search(db->tables, table_key);\n\n    if(node == NULL)\n        return -1;\n\n    db_table_t * table = (db_table_t *) (node->value);\n\n    return table_update(column_values, no_cols, no_clustering_keys, last_blob_size, col_idxs, version, table);\n}\n\nint db_update(WORD * column_values, int no_cols, int no_clustering_keys, size_t last_blob_size, int * col_idxs, WORD table_key, db_t * db)\n{\n    return db_update_transactional(column_values, no_cols, no_clustering_keys, last_blob_size, col_idxs, NULL, table_key, db);\n}\n\ndb_row_t* db_search(WORD* primary_keys, WORD table_key, db_t * db)\n{\n    snode_t * node = skiplist_search(db->tables, table_key);\n\n    if(node == NULL)\n        return NULL;\n\n    db_table_t * table = (db_table_t *) (node->value);\n\n    return table_search(primary_keys, table);\n}\n\nint db_range_search(WORD* start_primary_keys, WORD* end_primary_keys, snode_t** start_row, snode_t** end_row, WORD table_key, db_t * db)\n{\n    snode_t * node = skiplist_search(db->tables, table_key);\n\n    if(node == NULL)\n        return -1;\n\n    db_table_t * table = (db_table_t *) (node->value);\n\n    return table_range_search(start_primary_keys, end_primary_keys, start_row, end_row, table);\n}\n\nint db_verify_row_range_version(WORD* start_primary_keys, WORD* end_primary_keys, int no_primary_keys, WORD table_key,\n                                    int64_t * range_result_keys, vector_clock ** range_result_versions, int no_range_results, db_t * db)\n{\n    snode_t * node = skiplist_search(db->tables, table_key);\n\n    if(node == NULL)\n        return -1;\n\n    db_table_t * table = (db_table_t *) (node->value);\n\n    return table_verify_row_range_version(start_primary_keys, end_primary_keys, no_primary_keys,\n            range_result_keys, range_result_versions, no_range_results, table);\n}\n\nint db_range_search_copy(WORD* start_primary_keys, WORD* end_primary_keys, db_row_t** rows, WORD table_key, db_t * db)\n{\n    snode_t * node = skiplist_search(db->tables, table_key);\n\n    if(node == NULL)\n        return -1;\n\n    db_table_t * table = (db_table_t *) (node->value);\n\n    return table_range_search_copy(start_primary_keys, end_primary_keys, rows, table);\n}\n\ndb_row_t* db_search_clustering(WORD* primary_keys, WORD* clustering_keys, int no_clustering_keys, WORD table_key, db_t * db)\n{\n    snode_t * node = skiplist_search(db->tables, table_key);\n\n    if(node == NULL)\n        return NULL;\n\n    db_table_t * table = (db_table_t *) (node->value);\n\n    return table_search_clustering(primary_keys, clustering_keys, no_clustering_keys, table);\n}\n\nint db_verify_cell_version(WORD* primary_keys, int no_primary_keys, WORD* clustering_keys, int no_clustering_keys, WORD table_key, vector_clock * version, db_t * db)\n{\n    snode_t * node = skiplist_search(db->tables, table_key);\n\n    if(node == NULL)\n        return DB_ERR_NO_TABLE;\n\n    db_table_t * table = (db_table_t *) (node->value);\n\n    return table_verify_cell_version(primary_keys, no_primary_keys, clustering_keys, no_clustering_keys, version, table);\n}\n\nint db_range_search_clustering(WORD* primary_keys, WORD* start_clustering_keys, WORD* end_clustering_keys, int no_clustering_keys, snode_t** start_row, snode_t** end_row, WORD table_key, db_t * db)\n{\n    snode_t * node = skiplist_search(db->tables, table_key);\n\n    if(node == NULL)\n        return -1;\n\n    db_table_t * table = (db_table_t *) (node->value);\n\n    return table_range_search_clustering(primary_keys, start_clustering_keys, end_clustering_keys, no_clustering_keys, start_row, end_row, table);\n}\n\nint db_verify_cell_range_version(WORD* primary_keys, int no_primary_keys, WORD* start_clustering_keys, WORD* end_clustering_keys, int no_clustering_keys, WORD table_key,\n                                    int64_t * range_result_keys, vector_clock ** range_result_versions, int no_range_results, db_t * db)\n{\n    snode_t * node = skiplist_search(db->tables, table_key);\n\n    if(node == NULL)\n        return -1;\n\n    db_table_t * table = (db_table_t *) (node->value);\n\n    return table_verify_cell_range_version(primary_keys, no_primary_keys, start_clustering_keys, end_clustering_keys, no_clustering_keys, range_result_keys, range_result_versions, no_range_results, table);\n}\n\n\nWORD* db_search_columns(WORD* primary_keys, WORD* clustering_keys, int no_clustering_keys, int* column_idxs, int no_columns, WORD table_key, db_t * db)\n{\n    snode_t * node = skiplist_search(db->tables, table_key);\n\n    if(node == NULL)\n        return NULL;\n\n    db_table_t * table = (db_table_t *) (node->value);\n\n    return table_search_columns(primary_keys, clustering_keys, no_clustering_keys, column_idxs, no_columns, table);\n}\n\ndb_row_t* db_search_index(WORD index_key, int idx_idx, WORD table_key, db_t * db)\n{\n    snode_t * node = skiplist_search(db->tables, table_key);\n\n    if(node == NULL)\n        return NULL;\n\n    db_table_t * table = (db_table_t *) (node->value);\n\n    return table_search_index(index_key, idx_idx, table);\n}\n\nint db_verify_index_version(WORD index_key, int idx_idx, WORD table_key, vector_clock * version, db_t * db)\n{\n    snode_t * node = skiplist_search(db->tables, table_key);\n\n    if(node == NULL)\n        return -2;\n\n    db_table_t * table = (db_table_t *) (node->value);\n\n    return table_verify_index_version(index_key, idx_idx, version, table);\n}\n\nint db_range_search_index(int idx_idx, WORD start_idx_key, WORD end_idx_key, snode_t** start_row, snode_t** end_row, WORD table_key, db_t * db)\n{\n    snode_t * node = skiplist_search(db->tables, table_key);\n\n    if(node == NULL)\n        return -1;\n\n    db_table_t * table = (db_table_t *) (node->value);\n\n    return table_range_search_index(idx_idx, start_idx_key, end_idx_key, start_row, end_row, table);\n}\n\nint db_verify_index_range_version(int idx_idx, WORD start_idx_key, WORD end_idx_key,\n                                    int64_t * range_result_keys, vector_clock ** range_result_versions, int no_range_results, WORD table_key, db_t * db)\n{\n    snode_t * node = skiplist_search(db->tables, table_key);\n\n    if(node == NULL)\n        return -1;\n\n    db_table_t * table = (db_table_t *) (node->value);\n\n    return table_verify_index_range_version(idx_idx, start_idx_key, end_idx_key, range_result_keys, range_result_versions, no_range_results, table);\n}\n\nint db_delete_row_transactional(WORD* primary_keys, vector_clock * version, WORD table_key, db_t * db, unsigned int * fastrandstate)\n{\n    snode_t * node = skiplist_search(db->tables, table_key);\n\n    if(node == NULL)\n    {\n        log_warn(\"db_delete_row(): Table with pk %\" PRId64 \" doesn't exist!\", (int64_t) table_key);\n        return -1;\n    }\n\n    db_table_t * table = (db_table_t *) (node->value);\n\n    return table_delete_row(primary_keys, version, table, db, fastrandstate);\n}\n\nint db_delete_row(WORD* primary_keys, WORD table_key, db_t * db, unsigned int * fastrandstate)\n{\n    return db_delete_row_transactional(primary_keys, NULL, table_key, db, fastrandstate);\n}\n\nint db_delete_by_index(WORD index_key, int idx_idx, WORD table_key, db_t * db)\n{\n    snode_t * node = skiplist_search(db->tables, table_key);\n\n    if(node == NULL)\n        return -1;\n\n    db_table_t * table = (db_table_t *) (node->value);\n\n    return table_delete_by_index(index_key, idx_idx, table);\n}\n"
  },
  {
    "path": "backend/db.h",
    "content": "/*\n * Copyright (C) 2019-2021 Deutsche Telekom AG\n *\n * Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:\n *\n * 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.\n *\n * 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.\n *\n * 3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission.\n *\n * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS \"AS IS\" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n */\n\n/*\n * db.h\n *      Author: aagapi\n */\n\n#ifndef BACKEND_DB_H_\n#define BACKEND_DB_H_\n\n#include \"common.h\"\n#include \"skiplist.h\"\n#include \"fastrand.h\"\n#include \"failure_detector/vector_clock.h\"\n#include \"hash_ring.h\"\n\n// High level API:\n\n// Query types:\n\n#define QUERY_TYPE_UPDATE 0\n#define QUERY_TYPE_DELETE 1\n#define QUERY_TYPE_READ_COLS 2\n#define QUERY_TYPE_READ_CELL 3\n#define QUERY_TYPE_READ_CELL_RANGE 4\n#define QUERY_TYPE_READ_ROW 5\n#define QUERY_TYPE_READ_ROW_RANGE 6\n#define QUERY_TYPE_READ_INDEX 7\n#define QUERY_TYPE_READ_INDEX_RANGE 8\n\n#define QUERY_TYPE_ENQUEUE 9\n#define QUERY_TYPE_READ_QUEUE 10\n#define QUERY_TYPE_CONSUME_QUEUE 11\n#define QUERY_TYPE_CREATE_QUEUE 12\n#define QUERY_TYPE_DELETE_QUEUE 13\n#define QUERY_TYPE_SUBSCRIBE_QUEUE 14\n#define QUERY_TYPE_UNSUBSCRIBE_QUEUE 15\n\n#define QUERY_TYPE_READ_QUEUE_RESPONSE 16\n#define QUERY_TYPE_QUEUE_NOTIFICATION 17\n\n#define QUERY_TYPE_ADD_QUEUE_TO_GROUP 18\n#define QUERY_TYPE_REMOVE_QUEUE_FROM_GROUP 19\n\n// Return statuses:\n\n#define DB_ERR_NO_TABLE -1\n#define DB_ERR_NO_QUEUE -2\n#define DB_ERR_NO_CONSUMER -3\n#define DB_ERR_QUEUE_COMPLETE -4\n#define DB_ERR_QUEUE_HEAD_INVALID -5\n#define DB_ERR_DUPLICATE_QUEUE -6\n#define DB_ERR_DUPLICATE_CONSUMER -7\n#define VAL_STATUS_ABORT_SCHEMA -8\n\n#define QUEUE_STATUS_READ_INCOMPLETE 0\n#define QUEUE_STATUS_READ_COMPLETE 1\n\n#define QUEUE_NOTIF_ENQUEUED 0\n#define QUEUE_NOTIF_DELETED 1\n\n#define VERBOSE_BACKEND 0\n\n#define MAX_PRINT_BUFF 128 * 1024\n\n#define MULTI_THREADED 0\n\n#define ENABLE_AUTO_QUEUE_GROUP_SUBSCRIPTIONS 1\n\ntypedef struct db_schema {\n    int * col_types;\n    int min_no_cols;\n\n    int * primary_key_idxs;\n    int no_primary_keys;\n\n    int * clustering_key_idxs;\n    int min_no_clustering_keys;\n\n    int * index_key_idxs;\n    int no_index_keys;\n} db_schema_t;\n\ntypedef struct db_table {\n    WORD table_key;\n    db_schema_t * schema;\n    skiplist_t * rows;\n    skiplist_t ** indexes;\n\n    skiplist_t * queues;\n    skiplist_t * row_tombstones;\n\n    pthread_mutex_t* lock;\n} db_table_t;\n\n// Cells:\n\ntypedef struct db_cell {\n    WORD key;\n    skiplist_t * cells;\n    WORD * column_array;\n    int no_columns;\n    int last_blob_size;\n\n    // Queue metadata:\n    skiplist_t * consumer_state;\n    WORD group_subscriptions; // This field is either a group_state * or a skiplist_t * of group_states (if db->queue_group_replication_factor > 1)\n    int64_t no_entries;\n    pthread_mutex_t* enqueue_lock;\n    pthread_mutex_t* read_lock;\n    pthread_mutex_t* subscribe_lock;\n\n    vector_clock * version;\n\n    struct db_cell_t * _next;\n} db_cell_t;\n\ntypedef db_cell_t db_row_t;\n\ntypedef struct db {\n    skiplist_t * tables;\n    skiplist_t * txn_state;\n\n    hash_ring * queue_groups;\n    int queue_group_replication_factor;\n    int enable_auto_queue_group_subscriptions;\n#if (MULTI_THREADED == 1)\n    pthread_mutex_t* txn_state_lock;\n#endif\n} db_t;\n\n// DB high level API:\n\n// DB, schema and table manipulation:\n\ndb_t * get_db();\nint db_delete_db(db_t * db);\nint db_dump_db(db_t * db);\n\ndb_schema_t* db_create_schema(int * col_types, int no_cols, int * primary_key_idxs, int no_primary_keys, int * clustering_key_idxs, int no_clustering_keys, int * index_key_idxs, int no_index_keys);\nvoid free_schema(db_schema_t * schema);\nint db_create_table(WORD table_key, db_schema_t* schema, db_t * db, unsigned int * fastrandstate);\nint db_create_index(int new_index, WORD table_key, db_t * db, unsigned int * fastrandstate);\nint db_delete_table(WORD table_key, db_t * db);\n\n// DB queries:\n\nint db_insert(WORD * column_values, int no_cols, int no_clustering_keys, size_t last_blob_size, WORD table_key, db_t * db, unsigned int * fastrandstate);\nint db_insert_transactional(WORD * column_values, int no_cols, int no_clustering_keys, size_t last_blob_size, vector_clock * version, WORD table_key, db_t * db, unsigned int * fastrandstate);\nint db_update(WORD * column_values, int no_cols, int no_clustering_keys, size_t last_blob_size, int * col_idxs, WORD table_key, db_t * db);\nint db_update_transactional(WORD * column_values, int no_cols, int no_clustering_keys, size_t last_blob_size, int * col_idxs, vector_clock * version, WORD table_key, db_t * db);\ndb_row_t* db_search(WORD* primary_keys, WORD table_key, db_t * db);\nint db_range_search(WORD* start_primary_keys, WORD* end_primary_keys, snode_t** start_row, snode_t** end_row, WORD table_key, db_t * db);\nint db_range_search_copy(WORD* start_primary_keys, WORD* end_primary_keys, db_row_t** rows, WORD table_key, db_t * db);\ndb_row_t* db_search_clustering(WORD* primary_keys, WORD* clustering_keys, int no_clustering_keys, WORD table_key, db_t * db);\nint db_range_search_clustering(WORD* primary_keys, WORD* start_clustering_keys, WORD* end_clustering_keys, int no_clustering_keys, snode_t** start_row, snode_t** end_row, WORD table_key, db_t * db);\nWORD* db_search_columns(WORD* primary_keys, WORD* clustering_keys, int no_clustering_keys, int* column_idxs, int no_columns, WORD table_key, db_t * db);\ndb_row_t* db_search_index(WORD index_key, int idx_idx, WORD table_key, db_t * db);\nint db_range_search_index(int idx_idx, WORD start_idx_key, WORD end_idx_key, snode_t** start_row, snode_t** end_row, WORD table_key, db_t * db);\nint db_delete_row(WORD* primary_keys, WORD table_key, db_t * db, unsigned int * fastrandstate);\nint db_delete_row_transactional(WORD* primary_keys, vector_clock * version, WORD table_key, db_t * db, unsigned int * fastrandstate);\n// TO DO: int db_delete_cell(WORD* keys, int no_primary_keys, int no_clustering_keys, WORD table_key, db_t * db);\nint db_delete_by_index(WORD index_key, int idx_idx, WORD table_key, db_t * db);\nint db_verify_cell_version(WORD* primary_keys, int no_primary_keys, WORD* clustering_keys, int no_clustering_keys, WORD table_key, vector_clock * version, db_t * db);\nint db_verify_row_range_version(WORD* start_primary_keys, WORD* end_primary_keys, int no_primary_keys, WORD table_key,\n                                    int64_t * range_result_keys, vector_clock ** range_result_versions, int no_range_results, db_t * db);\nint db_verify_cell_range_version(WORD* primary_keys, int no_primary_keys, WORD* start_clustering_keys, WORD* end_clustering_keys, int no_clustering_keys, WORD table_key,\n                                    int64_t * range_result_keys, vector_clock ** range_result_versions, int no_range_results, db_t * db);\nint db_verify_index_version(WORD index_key, int idx_idx, WORD table_key, vector_clock * version, db_t * db);\nint db_verify_index_range_version(int idx_idx, WORD start_idx_key, WORD end_idx_key,\n                                    int64_t * range_result_keys, vector_clock ** range_result_versions, int no_range_results, WORD table_key, db_t * db);\n\n// Lower level API:\n\ndb_row_t * create_db_row_schemaless(WORD * column_values, int * primary_key_idxs, int no_primary_keys,\n                                    int * clustering_key_idxs, int no_clustering_keys, int no_schema_clustering_keys,\n                                    int no_cols, size_t last_blob_size, unsigned int * fastrandstate);\n// Assumes key indexes are in order (rartition keys, followed by clustering keys, followed by columns). Also assumes a single partition key\ndb_row_t * create_db_row_schemaless2(WORD * keys, int no_keys, WORD * cols, int no_cols, WORD last_blob, size_t last_blob_size, unsigned int * fastrandstate);\nvoid free_db_row(db_row_t * row, db_schema_t * schema, db_t * db);\nvoid long_row_to_string(db_row_t* row, char * to_string, int * len, char * orig_offset);\nvoid print_long_db(db_t * db);\nvoid print_long_table(db_table_t * table);\nvoid print_long_row(db_row_t* row);\n\nint table_insert(WORD * column_values, int no_cols, int no_clustering_keys, size_t last_blob_size, vector_clock * version, db_table_t * table, unsigned int * fastrandstate);\nint table_update(WORD * column_values, int no_cols, int no_clustering_keys, size_t last_blob_size, int * col_idxs, vector_clock * version, db_table_t * table);\ndb_row_t* table_search(WORD* primary_keys, db_table_t * table);\nint table_range_search(WORD* start_primary_keys, WORD* end_primary_keys, snode_t** start_row, snode_t** end_row, db_table_t * table);\nint table_range_search_copy(WORD* start_primary_keys, WORD* end_primary_keys, db_row_t** rows, db_table_t * table);\ndb_row_t* table_search_clustering(WORD* primary_keys, WORD* clustering_keys, int no_clustering_keys, db_table_t * table);\nint table_range_search_clustering(WORD* primary_keys, WORD* start_clustering_keys, WORD* end_clustering_keys, int no_clustering_keys, snode_t** start_row, snode_t** end_row, db_table_t * table);\nWORD* table_search_columns(WORD* primary_keys, WORD* clustering_keys, int no_clustering_keys, int* column_idxs, int no_columns, db_table_t * table);\ndb_row_t* table_search_index(WORD index_key, int idx_idx, db_table_t * table);\nint table_range_search_index(int idx_idx, WORD start_idx_key, WORD end_idx_key, snode_t** start_row, snode_t** end_row, db_table_t * table);\nint table_delete_row(WORD* primary_keys, vector_clock * version, db_table_t * table, db_t * db, unsigned int * fastrandstate);\nint table_delete_by_index(WORD index_key, int idx_idx, db_table_t * table);\nint table_verify_cell_version(WORD* primary_keys, int no_primary_keys, WORD* clustering_keys, int no_clustering_keys, vector_clock * version, db_table_t * table);\nint table_verify_row_range_version(WORD* start_primary_keys, WORD* end_primary_keys, int no_primary_keys,\n                                        int64_t * range_result_keys, vector_clock ** range_result_versions, int no_range_results, db_table_t * table);\nint table_verify_cell_range_version(WORD* primary_keys, int no_primary_keys, WORD* start_clustering_keys, WORD* end_clustering_keys, int no_clustering_keys,\n                                        int64_t * range_result_keys, vector_clock ** range_result_versions, int no_range_results, db_table_t * table);\nint table_verify_index_version(WORD index_key, int idx_idx, vector_clock * version, db_table_t * table);\nint table_verify_index_range_version(int idx_idx, WORD start_idx_key, WORD end_idx_key,\n                                        int64_t * range_result_keys, vector_clock ** range_result_versions, int no_range_results, db_table_t * table);\n#endif /* BACKEND_DB_H_ */\n"
  },
  {
    "path": "backend/db_client_api.h",
    "content": "/*\n * db_client_api.h\n *\n *      Author: aagapi\n */\n\n#ifndef BACKEND_DB_CLIENT_API_H_\n#define BACKEND_DB_CLIENT_API_H_\n\n\n\n\n\n#endif /* BACKEND_DB_CLIENT_API_H_ */\n"
  },
  {
    "path": "backend/failure_detector/cells.c",
    "content": "/*\n * Copyright (C) 2019-2021 Deutsche Telekom AG\n *\n * Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:\n *\n * 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.\n *\n * 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.\n *\n * 3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission.\n *\n * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS \"AS IS\" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n */\n\n/*\n * cells.c\n *\n *      Author: aagapi\n */\n\n#include \"cells.h\"\n#include \"../log.h\"\n\n#include <stdlib.h>\n#include <stdio.h>\n#include <string.h>\n#include <limits.h>\n#include <assert.h>\n\n// Vector Clock serialization:\n\nint serialize_vc(vector_clock * vc, void ** buf, unsigned * len)\n{\n    VectorClockMessage msg = VECTOR_CLOCK_MESSAGE__INIT;\n    init_vc_msg(&msg, vc);\n\n    *len = vector_clock_message__get_packed_size (&msg);\n    *buf = malloc (*len);\n    vector_clock_message__pack (&msg, *buf);\n\n    free_vc_msg(&msg);\n\n    return 0;\n}\n\nint deserialize_vc(void * buf, unsigned msg_len, vector_clock ** vc)\n{\n      VectorClockMessage * msg = vector_clock_message__unpack (NULL, msg_len, buf);\n\n      if (msg == NULL)\n      { // Something failed\n        log_error(\"error unpacking vector_clock message\");\n        return 1;\n      }\n\n      assert(msg->n_ids == msg->n_counters);\n\n      *vc = init_vc_from_msg(msg);\n\n      vector_clock_message__free_unpacked(msg, NULL);\n\n      return 0;\n}\n\n\n// Cell Address:\n\ncell_address * init_cell_address(int64_t table_key, int64_t * keys, int no_keys)\n{\n    cell_address * ca = (cell_address *) malloc(sizeof(cell_address));\n    ca->table_key = table_key;\n    ca->keys = keys;\n    ca->no_keys = no_keys;\n\n    return ca;\n}\n\ncell_address * init_cell_address_copy(int64_t table_key, int64_t * keys, int no_keys)\n{\n    cell_address * ca = (cell_address *) malloc(sizeof(cell_address));\n    ca->table_key = table_key;\n    ca->no_keys = no_keys;\n    ca->keys = (int64_t *) malloc(no_keys * sizeof(int64_t));\n    for(int i=0;i<no_keys;i++)\n        ca->keys[i] = keys[i];\n\n    return ca;\n}\n\ncell_address * init_cell_address_copy2(int64_t table_key, int64_t * primary_keys, int no_primary_keys, int64_t * clustering_keys, int no_clustering_keys)\n{\n    int i = 0;\n    cell_address * c = (cell_address *) malloc(sizeof(cell_address));\n    c->table_key = (int64_t) table_key;\n    c->no_keys = no_primary_keys + no_clustering_keys;\n\n    assert(c->no_keys > 0);\n\n    c->keys = (int64_t *) malloc(c->no_keys * sizeof(int64_t));\n    for(;i<no_primary_keys;i++)\n        c->keys[i] = (int64_t) primary_keys[i];\n\n    for(;i<c->no_keys;i++)\n        c->keys[i] = (int64_t) clustering_keys[i-no_primary_keys];\n\n    return c;\n}\n\ncell_address * init_cell_address_single_key_copy(int64_t table_key, int64_t key)\n{\n    cell_address * ca = (cell_address *) malloc(sizeof(cell_address));\n    ca->table_key = table_key;\n    ca->no_keys = 1;\n    ca->keys = (int64_t *) malloc(sizeof(int64_t));\n    ca->keys[0] = key;\n\n    return ca;\n}\n\nint copy_cell_address(cell_address * ca, int64_t table_key, int64_t * keys, int no_keys)\n{\n    ca->table_key = table_key;\n    ca->keys = keys;\n    ca->no_keys = no_keys;\n\n    return 0;\n}\n\n\nvoid free_cell_address(cell_address * ca)\n{\n    free(ca->keys);\n    free(ca);\n}\n\nvoid init_cell_address_msg(CellAddressMessage * msg, cell_address * ca)\n{\n    msg->table_key = ca->table_key;\n    msg->n_keys = ca->no_keys;\n    msg->keys = (int64_t *) malloc(ca->no_keys * sizeof(int64_t));\n    for(int i=0;i<ca->no_keys;i++)\n        msg->keys[i] = ca->keys[i];\n}\n\ncell_address * init_cell_address_from_msg(CellAddressMessage * msg)\n{\n    return init_cell_address_copy(msg->table_key, msg->keys, msg->n_keys);\n}\n\nvoid free_cell_address_msg(CellAddressMessage * msg)\n{\n    free(msg->keys);\n}\n\nint serialize_cell_address(cell_address * ca, void ** buf, unsigned * len)\n{\n    CellAddressMessage msg = CELL_ADDRESS_MESSAGE__INIT;\n    init_cell_address_msg(&msg, ca);\n\n    *len = cell_address_message__get_packed_size (&msg);\n    *buf = malloc (*len);\n    cell_address_message__pack (&msg, *buf);\n\n    free_cell_address_msg(&msg);\n\n    return 0;\n}\n\nint deserialize_cell_address(void * buf, unsigned msg_len, cell_address ** ca)\n{\n    CellAddressMessage * msg = cell_address_message__unpack (NULL, msg_len, buf);\n\n    if (msg == NULL)\n    {\n        log_error(\"error unpacking cell_address message\");\n        return 1;\n    }\n\n    *ca = init_cell_address_from_msg(msg);\n\n    cell_address_message__free_unpacked(msg, NULL);\n\n    return 0;\n}\n\nint equals_cell_address(cell_address * ca1, cell_address * ca2)\n{\n    if((ca1 != NULL && ca2 == NULL) || (ca1 == NULL && ca2 != NULL))\n        return 0;\n\n    if(ca1->table_key != ca2->table_key || ca1->no_keys != ca2->no_keys)\n        return 0;\n\n    for(int i=0;i<ca1->no_keys;i++)\n        if(ca1->keys[i] != ca2->keys[i])\n            return 0;\n\n    return 1;\n}\n\nchar * to_string_cell_address(cell_address * ca, char * msg_buff)\n{\n    char * crt_ptr = msg_buff;\n\n    sprintf(crt_ptr, \"CellAddress(table_key=%\" PRId64 \", keys={\", ca->table_key);\n    crt_ptr += strlen(crt_ptr);\n\n    for(int i=0;i<ca->no_keys;i++)\n    {\n        sprintf(crt_ptr, \"%\" PRId64 \", \",  ca->keys[i]);\n        crt_ptr += strlen(crt_ptr);\n    }\n\n    sprintf(crt_ptr, \"})\");\n\n    return msg_buff;\n}\n\n// Cell:\n\ncell * init_cell(int64_t table_key, int64_t * keys, int no_keys, int64_t * columns, int no_columns, WORD last_blob, size_t last_blob_size, vector_clock * version)\n{\n    cell * ca = (cell *) malloc(sizeof(cell));\n    ca->table_key = table_key;\n    ca->keys = keys;\n    ca->columns = columns;\n    ca->no_keys = no_keys;\n    ca->no_columns = no_columns;\n    ca->last_blob = last_blob;\n    ca->last_blob_size = last_blob_size;\n    ca->version = version;\n\n    return ca;\n}\n\nvoid copy_cell(cell * ca, int64_t table_key, int64_t * keys, int no_keys, int64_t * columns, int no_columns, WORD last_blob, size_t last_blob_size, vector_clock * version)\n{\n    ca->table_key = table_key;\n\n    ca->no_keys = no_keys;\n    ca->keys = (int64_t *) malloc(no_keys * sizeof(int64_t));\n    for(int i=0;i<no_keys;i++)\n        ca->keys[i] = keys[i];\n\n    assert(last_blob == NULL || last_blob_size > 0);\n\n    ca->no_columns = no_columns;\n    ca->columns = (int64_t *) malloc(no_columns * sizeof(int64_t));\n    for(int i=0;i<no_columns;i++)\n        ca->columns[i] = columns[i];\n\n    ca->last_blob_size = last_blob_size;\n    if(last_blob != NULL)\n    {\n        ca->last_blob = malloc(last_blob_size);\n        memcpy(ca->last_blob, last_blob, last_blob_size);\n    }\n    else\n    {\n        ca->last_blob = NULL;\n    }\n\n    if(version != NULL)\n        ca->version = copy_vc(version);\n    else\n        ca->version = NULL;\n}\n\ncell * init_cell_copy(int64_t table_key, int64_t * keys, int no_keys, int64_t * columns, int no_columns, WORD last_blob, size_t last_blob_size, vector_clock * version)\n{\n    cell * ca = (cell *) malloc(sizeof(cell));\n    copy_cell(ca, table_key, keys, no_keys, columns, no_columns, last_blob, last_blob_size, version);\n    return ca;\n}\n\ncell_address * get_cell_address(cell * c)\n{\n    return init_cell_address_copy(c->table_key, c->keys, c->no_keys);\n}\n\nvoid free_cell_ptrs(cell * ca)\n{\n    if(ca->keys != NULL)\n        free(ca->keys);\n\n    if(ca->columns != NULL)\n    {\n        free(ca->columns);\n    }\n\n    if(ca->last_blob != NULL)\n    {\n        assert(ca->last_blob_size > 0);\n        free(ca->last_blob);\n    }\n\n    free_vc(ca->version);\n}\n\nvoid free_cell(cell * ca)\n{\n    free_cell_ptrs(ca);\n    free(ca);\n}\n\nvoid init_cell_msg(VersionedCellMessage * msg, cell * ca, VectorClockMessage * vc_msg)\n{\n    msg->table_key = ca->table_key;\n    msg->n_keys = ca->no_keys;\n    msg->keys = (int64_t *) malloc(ca->no_keys * sizeof(int64_t));\n    for(int i=0;i<ca->no_keys;i++)\n        msg->keys[i] = ca->keys[i];\n\n    msg->n_columns = ca->no_columns;\n    if(ca->no_columns > 0)\n        msg->columns = (int64_t *) malloc(ca->no_columns * sizeof(int64_t));\n    for(int i=0;i<ca->no_columns;i++)\n        msg->columns[i] = ca->columns[i];\n\n    if(ca->last_blob != NULL)\n    {\n        assert(ca->last_blob_size > 0);\n        msg->blob.len = ca->last_blob_size;\n        msg->blob.data = malloc(ca->last_blob_size);\n        memcpy(msg->blob.data, ca->last_blob, ca->last_blob_size);\n    }\n    else\n    {\n        msg->blob.data = NULL;\n        msg->blob.len = 0;\n    }\n\n    if(ca->version != NULL)\n    {\n        init_vc_msg(vc_msg, ca->version);\n        msg->version = vc_msg;\n    }\n    else\n    {\n//      msg->version = NULL;\n    }\n}\n\ncell * copy_cell_from_msg(cell * c, VersionedCellMessage * msg)\n{\n    copy_cell(c, msg->table_key, msg->keys, msg->n_keys, msg->columns, msg->n_columns, msg->blob.data, msg->blob.len, (msg->version != NULL)?(init_vc_from_msg(msg->version)):(NULL));\n    return c;\n}\n\ncell * init_cell_from_msg(VersionedCellMessage * msg)\n{\n    if(msg == NULL)\n        return NULL;\n\n    vector_clock * vc = NULL;\n    if(msg->version != NULL)\n        vc = init_vc_from_msg(msg->version);\n    cell * c = init_cell_copy(msg->table_key, msg->keys, msg->n_keys, msg->columns, msg->n_columns, msg->blob.data, msg->blob.len, vc);\n\n    return c;\n}\n\nvoid free_cell_msg(VersionedCellMessage * msg)\n{\n    if(msg->keys != NULL)\n        free(msg->keys);\n    if(msg->columns != NULL)\n        free(msg->columns);\n    if(msg->blob.data != NULL && msg->blob.len > 0)\n        free(msg->blob.data);\n    if(msg->version != NULL)\n        free_vc_msg(msg->version);\n}\n\nint serialize_cell(cell * ca, void ** buf, unsigned * len)\n{\n    VersionedCellMessage msg = VERSIONED_CELL_MESSAGE__INIT;\n    VectorClockMessage vc_msg = VECTOR_CLOCK_MESSAGE__INIT;\n\n    init_cell_msg(&msg, ca, &vc_msg);\n\n    *len = versioned_cell_message__get_packed_size (&msg);\n    *buf = malloc (*len);\n    versioned_cell_message__pack (&msg, *buf);\n\n    free_cell_msg(&msg);\n\n    return 0;\n}\n\nint deserialize_cell(void * buf, unsigned msg_len, cell ** ca)\n{\n    VersionedCellMessage * msg = versioned_cell_message__unpack (NULL, msg_len, buf);\n\n    if (msg == NULL)\n    {\n        log_error(\"error unpacking cell message\");\n        return 1;\n    }\n\n    *ca = init_cell_from_msg(msg);\n\n    versioned_cell_message__free_unpacked(msg, NULL);\n\n    return 0;\n}\n\nint equals_cell(cell * ca1, cell * ca2)\n{\n    if(ca1 == NULL && ca2 == NULL)\n        return 1;\n\n    if(ca1 != NULL && ca2 == NULL)\n        return 0;\n\n    if(ca1 == NULL && ca2 != NULL)\n        return 0;\n\n    if(ca1->table_key != ca2->table_key || ca1->no_keys != ca2->no_keys)\n        return 0;\n\n    for(int i=0;i<ca1->no_keys;i++)\n        if(ca1->keys[i] != ca2->keys[i])\n            return 0;\n\n    for(int i=0;i<ca1->no_columns;i++)\n        if(ca1->columns[i] != ca2->columns[i])\n            return 0;\n\n    if(ca1->last_blob_size != ca2->last_blob_size)\n        return 0;\n    if(ca1->last_blob_size > 0)\n    {\n        assert(ca1->last_blob != NULL && ca2->last_blob != NULL);\n\n        if(memcmp(ca1->last_blob, ca2->last_blob, ca1->last_blob_size) != 0)\n            return 0;\n    }\n\n    if(compare_vc(ca1->version, ca2->version))\n        return 0;\n\n    return 1;\n}\n\nchar * to_string_cell(cell * ca, char * msg_buff)\n{\n    char * crt_ptr = msg_buff;\n\n    sprintf(crt_ptr, \"Cell(table_key=%\" PRId64 \", keys={\", ca->table_key);\n    crt_ptr += strlen(crt_ptr);\n\n    for(int i=0;i<ca->no_keys;i++)\n    {\n        sprintf(crt_ptr, \"%\" PRId64 \", \", ca->keys[i]);\n        crt_ptr += strlen(crt_ptr);\n    }\n\n    sprintf(crt_ptr, \"}, columns={\");\n    crt_ptr += strlen(crt_ptr);\n\n    for(int i=0;i<ca->no_columns;i++)\n    {\n        sprintf(crt_ptr, \"%\" PRId64 \", \", ca->columns[i]);\n        crt_ptr += strlen(crt_ptr);\n    }\n\n    sprintf(crt_ptr, \"}, version=\");\n    crt_ptr += strlen(crt_ptr);\n\n    if(ca->version != NULL)\n    {\n        to_string_vc(ca->version, crt_ptr);\n        crt_ptr += strlen(crt_ptr);\n    }\n\n    sprintf(crt_ptr, \")\");\n\n    return msg_buff;\n}\n\n\n"
  },
  {
    "path": "backend/failure_detector/cells.h",
    "content": "/*\n * cells.h\n *\n *      Author: aagapi\n */\n\n#ifndef BACKEND_FAILURE_DETECTOR_CELLS_H_\n#define BACKEND_FAILURE_DETECTOR_CELLS_H_\n\n#include \"db_messages.pb-c.h\"\n#include \"vector_clock.h\"\n\ntypedef void * WORD;\n\ntypedef struct cell_address\n{\n    int64_t table_key;\n    int64_t * keys;\n    int no_keys;\n} cell_address;\n\ncell_address * init_cell_address(int64_t table_key, int64_t * keys, int no_keys);\ncell_address * init_cell_address_copy(int64_t table_key, int64_t * keys, int no_keys);\ncell_address * init_cell_address_copy2(int64_t table_key, int64_t * primary_keys, int no_primary_keys, int64_t * clustering_keys, int no_clustering_keys);\ncell_address * init_cell_address_single_key_copy(int64_t table_key, int64_t key);\nint copy_cell_address(cell_address * ca, int64_t table_key, int64_t * keys, int no_keys);\nvoid free_cell_address(cell_address * ca);\nvoid init_cell_address_msg(CellAddressMessage * msg, cell_address * ca);\ncell_address * init_cell_address_from_msg(CellAddressMessage * msg);\nvoid free_cell_address_msg(CellAddressMessage * msg);\nint serialize_cell_address(cell_address * ca, void ** buf, unsigned * len);\nint deserialize_cell_address(void * buf, unsigned msg_len, cell_address ** ca);\nint equals_cell_address(cell_address * ca1, cell_address * ca2);\nchar * to_string_cell_address(cell_address * ca, char * msg_buff);\n\ntypedef struct cell\n{\n    int64_t table_key;\n    int64_t * keys;\n    int no_keys;\n    int64_t * columns;\n    int no_columns;\n    WORD last_blob;\n    size_t last_blob_size;\n    vector_clock * version;\n} cell;\n\ncell * init_cell(int64_t table_key, int64_t * keys, int no_keys, int64_t * columns, int no_columns, WORD last_blob, size_t last_blob_size, vector_clock * version);\ncell * init_cell_copy(int64_t table_key, int64_t * keys, int no_keys, int64_t * columns, int no_columns, WORD last_blob, size_t last_blob_size, vector_clock * version);\nvoid copy_cell(cell * ca, int64_t table_key, int64_t * keys, int no_keys, int64_t * columns, int no_columns, WORD last_blob, size_t last_blob_size, vector_clock * version);\ncell_address * get_cell_address(cell * c);\ncell * init_cell_from_msg(VersionedCellMessage * msg);\ncell * copy_cell_from_msg(cell * c, VersionedCellMessage * msg);\nvoid free_cell(cell * ca);\nvoid free_cell_ptrs(cell * ca);\nvoid init_cell_msg(VersionedCellMessage * msg, cell * ca, VectorClockMessage * vc_msg);\nvoid free_cell_msg(VersionedCellMessage * msg);\nint serialize_cell(cell * ca, void ** buf, unsigned * len);\nint deserialize_cell(void * buf, unsigned msg_len, cell ** ca);\nint equals_cell(cell * ca1, cell * ca2);\nchar * to_string_cell(cell * ca, char * msg_buff);\n\nint serialize_vc(vector_clock * vc, void ** buf, unsigned * len);\nint deserialize_vc(void * buf, unsigned msg_len, vector_clock ** vc);\n\n#endif /* BACKEND_FAILURE_DETECTOR_CELLS_H_ */\n"
  },
  {
    "path": "backend/failure_detector/db_messages.pb-c.c",
    "content": "/*\n * Copyright (C) 2019-2021 Deutsche Telekom AG\n *\n * Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:\n *\n * 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.\n *\n * 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.\n *\n * 3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission.\n *\n * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS \"AS IS\" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n */\n\n/* Generated by the protocol buffer compiler.  DO NOT EDIT! */\n/* Generated from: backend/failure_detector/db_messages.proto */\n\n/* Do not generate deprecated warnings for self */\n#ifndef PROTOBUF_C__NO_DEPRECATED\n#define PROTOBUF_C__NO_DEPRECATED\n#endif\n\n#include \"db_messages.pb-c.h\"\nvoid   node_state_message__init\n                     (NodeStateMessage         *message)\n{\n  static const NodeStateMessage init_value = NODE_STATE_MESSAGE__INIT;\n  *message = init_value;\n}\nsize_t node_state_message__get_packed_size\n                     (const NodeStateMessage *message)\n{\n  assert(message->base.descriptor == &node_state_message__descriptor);\n  return protobuf_c_message_get_packed_size ((const ProtobufCMessage*)(message));\n}\nsize_t node_state_message__pack\n                     (const NodeStateMessage *message,\n                      uint8_t       *out)\n{\n  assert(message->base.descriptor == &node_state_message__descriptor);\n  return protobuf_c_message_pack ((const ProtobufCMessage*)message, out);\n}\nsize_t node_state_message__pack_to_buffer\n                     (const NodeStateMessage *message,\n                      ProtobufCBuffer *buffer)\n{\n  assert(message->base.descriptor == &node_state_message__descriptor);\n  return protobuf_c_message_pack_to_buffer ((const ProtobufCMessage*)message, buffer);\n}\nNodeStateMessage *\n       node_state_message__unpack\n                     (ProtobufCAllocator  *allocator,\n                      size_t               len,\n                      const uint8_t       *data)\n{\n  return (NodeStateMessage *)\n     protobuf_c_message_unpack (&node_state_message__descriptor,\n                                allocator, len, data);\n}\nvoid   node_state_message__free_unpacked\n                     (NodeStateMessage *message,\n                      ProtobufCAllocator *allocator)\n{\n  if(!message)\n    return;\n  assert(message->base.descriptor == &node_state_message__descriptor);\n  protobuf_c_message_free_unpacked ((ProtobufCMessage*)message, allocator);\n}\nvoid   vector_clock_message__init\n                     (VectorClockMessage         *message)\n{\n  static const VectorClockMessage init_value = VECTOR_CLOCK_MESSAGE__INIT;\n  *message = init_value;\n}\nsize_t vector_clock_message__get_packed_size\n                     (const VectorClockMessage *message)\n{\n  assert(message->base.descriptor == &vector_clock_message__descriptor);\n  return protobuf_c_message_get_packed_size ((const ProtobufCMessage*)(message));\n}\nsize_t vector_clock_message__pack\n                     (const VectorClockMessage *message,\n                      uint8_t       *out)\n{\n  assert(message->base.descriptor == &vector_clock_message__descriptor);\n  return protobuf_c_message_pack ((const ProtobufCMessage*)message, out);\n}\nsize_t vector_clock_message__pack_to_buffer\n                     (const VectorClockMessage *message,\n                      ProtobufCBuffer *buffer)\n{\n  assert(message->base.descriptor == &vector_clock_message__descriptor);\n  return protobuf_c_message_pack_to_buffer ((const ProtobufCMessage*)message, buffer);\n}\nVectorClockMessage *\n       vector_clock_message__unpack\n                     (ProtobufCAllocator  *allocator,\n                      size_t               len,\n                      const uint8_t       *data)\n{\n  return (VectorClockMessage *)\n     protobuf_c_message_unpack (&vector_clock_message__descriptor,\n                                allocator, len, data);\n}\nvoid   vector_clock_message__free_unpacked\n                     (VectorClockMessage *message,\n                      ProtobufCAllocator *allocator)\n{\n  if(!message)\n    return;\n  assert(message->base.descriptor == &vector_clock_message__descriptor);\n  protobuf_c_message_free_unpacked ((ProtobufCMessage*)message, allocator);\n}\nvoid   gossip_message__init\n                     (GossipMessage         *message)\n{\n  static const GossipMessage init_value = GOSSIP_MESSAGE__INIT;\n  *message = init_value;\n}\nsize_t gossip_message__get_packed_size\n                     (const GossipMessage *message)\n{\n  assert(message->base.descriptor == &gossip_message__descriptor);\n  return protobuf_c_message_get_packed_size ((const ProtobufCMessage*)(message));\n}\nsize_t gossip_message__pack\n                     (const GossipMessage *message,\n                      uint8_t       *out)\n{\n  assert(message->base.descriptor == &gossip_message__descriptor);\n  return protobuf_c_message_pack ((const ProtobufCMessage*)message, out);\n}\nsize_t gossip_message__pack_to_buffer\n                     (const GossipMessage *message,\n                      ProtobufCBuffer *buffer)\n{\n  assert(message->base.descriptor == &gossip_message__descriptor);\n  return protobuf_c_message_pack_to_buffer ((const ProtobufCMessage*)message, buffer);\n}\nGossipMessage *\n       gossip_message__unpack\n                     (ProtobufCAllocator  *allocator,\n                      size_t               len,\n                      const uint8_t       *data)\n{\n  return (GossipMessage *)\n     protobuf_c_message_unpack (&gossip_message__descriptor,\n                                allocator, len, data);\n}\nvoid   gossip_message__free_unpacked\n                     (GossipMessage *message,\n                      ProtobufCAllocator *allocator)\n{\n  if(!message)\n    return;\n  assert(message->base.descriptor == &gossip_message__descriptor);\n  protobuf_c_message_free_unpacked ((ProtobufCMessage*)message, allocator);\n}\nvoid   gossip_listen_message__init\n                     (GossipListenMessage         *message)\n{\n  static const GossipListenMessage init_value = GOSSIP_LISTEN_MESSAGE__INIT;\n  *message = init_value;\n}\nsize_t gossip_listen_message__get_packed_size\n                     (const GossipListenMessage *message)\n{\n  assert(message->base.descriptor == &gossip_listen_message__descriptor);\n  return protobuf_c_message_get_packed_size ((const ProtobufCMessage*)(message));\n}\nsize_t gossip_listen_message__pack\n                     (const GossipListenMessage *message,\n                      uint8_t       *out)\n{\n  assert(message->base.descriptor == &gossip_listen_message__descriptor);\n  return protobuf_c_message_pack ((const ProtobufCMessage*)message, out);\n}\nsize_t gossip_listen_message__pack_to_buffer\n                     (const GossipListenMessage *message,\n                      ProtobufCBuffer *buffer)\n{\n  assert(message->base.descriptor == &gossip_listen_message__descriptor);\n  return protobuf_c_message_pack_to_buffer ((const ProtobufCMessage*)message, buffer);\n}\nGossipListenMessage *\n       gossip_listen_message__unpack\n                     (ProtobufCAllocator  *allocator,\n                      size_t               len,\n                      const uint8_t       *data)\n{\n  return (GossipListenMessage *)\n     protobuf_c_message_unpack (&gossip_listen_message__descriptor,\n                                allocator, len, data);\n}\nvoid   gossip_listen_message__free_unpacked\n                     (GossipListenMessage *message,\n                      ProtobufCAllocator *allocator)\n{\n  if(!message)\n    return;\n  assert(message->base.descriptor == &gossip_listen_message__descriptor);\n  protobuf_c_message_free_unpacked ((ProtobufCMessage*)message, allocator);\n}\nvoid   membership_view_message__init\n                     (MembershipViewMessage         *message)\n{\n  static const MembershipViewMessage init_value = MEMBERSHIP_VIEW_MESSAGE__INIT;\n  *message = init_value;\n}\nsize_t membership_view_message__get_packed_size\n                     (const MembershipViewMessage *message)\n{\n  assert(message->base.descriptor == &membership_view_message__descriptor);\n  return protobuf_c_message_get_packed_size ((const ProtobufCMessage*)(message));\n}\nsize_t membership_view_message__pack\n                     (const MembershipViewMessage *message,\n                      uint8_t       *out)\n{\n  assert(message->base.descriptor == &membership_view_message__descriptor);\n  return protobuf_c_message_pack ((const ProtobufCMessage*)message, out);\n}\nsize_t membership_view_message__pack_to_buffer\n                     (const MembershipViewMessage *message,\n                      ProtobufCBuffer *buffer)\n{\n  assert(message->base.descriptor == &membership_view_message__descriptor);\n  return protobuf_c_message_pack_to_buffer ((const ProtobufCMessage*)message, buffer);\n}\nMembershipViewMessage *\n       membership_view_message__unpack\n                     (ProtobufCAllocator  *allocator,\n                      size_t               len,\n                      const uint8_t       *data)\n{\n  return (MembershipViewMessage *)\n     protobuf_c_message_unpack (&membership_view_message__descriptor,\n                                allocator, len, data);\n}\nvoid   membership_view_message__free_unpacked\n                     (MembershipViewMessage *message,\n                      ProtobufCAllocator *allocator)\n{\n  if(!message)\n    return;\n  assert(message->base.descriptor == &membership_view_message__descriptor);\n  protobuf_c_message_free_unpacked ((ProtobufCMessage*)message, allocator);\n}\nvoid   membership_agreement_message__init\n                     (MembershipAgreementMessage         *message)\n{\n  static const MembershipAgreementMessage init_value = MEMBERSHIP_AGREEMENT_MESSAGE__INIT;\n  *message = init_value;\n}\nsize_t membership_agreement_message__get_packed_size\n                     (const MembershipAgreementMessage *message)\n{\n  assert(message->base.descriptor == &membership_agreement_message__descriptor);\n  return protobuf_c_message_get_packed_size ((const ProtobufCMessage*)(message));\n}\nsize_t membership_agreement_message__pack\n                     (const MembershipAgreementMessage *message,\n                      uint8_t       *out)\n{\n  assert(message->base.descriptor == &membership_agreement_message__descriptor);\n  return protobuf_c_message_pack ((const ProtobufCMessage*)message, out);\n}\nsize_t membership_agreement_message__pack_to_buffer\n                     (const MembershipAgreementMessage *message,\n                      ProtobufCBuffer *buffer)\n{\n  assert(message->base.descriptor == &membership_agreement_message__descriptor);\n  return protobuf_c_message_pack_to_buffer ((const ProtobufCMessage*)message, buffer);\n}\nMembershipAgreementMessage *\n       membership_agreement_message__unpack\n                     (ProtobufCAllocator  *allocator,\n                      size_t               len,\n                      const uint8_t       *data)\n{\n  return (MembershipAgreementMessage *)\n     protobuf_c_message_unpack (&membership_agreement_message__descriptor,\n                                allocator, len, data);\n}\nvoid   membership_agreement_message__free_unpacked\n                     (MembershipAgreementMessage *message,\n                      ProtobufCAllocator *allocator)\n{\n  if(!message)\n    return;\n  assert(message->base.descriptor == &membership_agreement_message__descriptor);\n  protobuf_c_message_free_unpacked ((ProtobufCMessage*)message, allocator);\n}\nvoid   cell_address_message__init\n                     (CellAddressMessage         *message)\n{\n  static const CellAddressMessage init_value = CELL_ADDRESS_MESSAGE__INIT;\n  *message = init_value;\n}\nsize_t cell_address_message__get_packed_size\n                     (const CellAddressMessage *message)\n{\n  assert(message->base.descriptor == &cell_address_message__descriptor);\n  return protobuf_c_message_get_packed_size ((const ProtobufCMessage*)(message));\n}\nsize_t cell_address_message__pack\n                     (const CellAddressMessage *message,\n                      uint8_t       *out)\n{\n  assert(message->base.descriptor == &cell_address_message__descriptor);\n  return protobuf_c_message_pack ((const ProtobufCMessage*)message, out);\n}\nsize_t cell_address_message__pack_to_buffer\n                     (const CellAddressMessage *message,\n                      ProtobufCBuffer *buffer)\n{\n  assert(message->base.descriptor == &cell_address_message__descriptor);\n  return protobuf_c_message_pack_to_buffer ((const ProtobufCMessage*)message, buffer);\n}\nCellAddressMessage *\n       cell_address_message__unpack\n                     (ProtobufCAllocator  *allocator,\n                      size_t               len,\n                      const uint8_t       *data)\n{\n  return (CellAddressMessage *)\n     protobuf_c_message_unpack (&cell_address_message__descriptor,\n                                allocator, len, data);\n}\nvoid   cell_address_message__free_unpacked\n                     (CellAddressMessage *message,\n                      ProtobufCAllocator *allocator)\n{\n  if(!message)\n    return;\n  assert(message->base.descriptor == &cell_address_message__descriptor);\n  protobuf_c_message_free_unpacked ((ProtobufCMessage*)message, allocator);\n}\nvoid   cell_message__init\n                     (CellMessage         *message)\n{\n  static const CellMessage init_value = CELL_MESSAGE__INIT;\n  *message = init_value;\n}\nsize_t cell_message__get_packed_size\n                     (const CellMessage *message)\n{\n  assert(message->base.descriptor == &cell_message__descriptor);\n  return protobuf_c_message_get_packed_size ((const ProtobufCMessage*)(message));\n}\nsize_t cell_message__pack\n                     (const CellMessage *message,\n                      uint8_t       *out)\n{\n  assert(message->base.descriptor == &cell_message__descriptor);\n  return protobuf_c_message_pack ((const ProtobufCMessage*)message, out);\n}\nsize_t cell_message__pack_to_buffer\n                     (const CellMessage *message,\n                      ProtobufCBuffer *buffer)\n{\n  assert(message->base.descriptor == &cell_message__descriptor);\n  return protobuf_c_message_pack_to_buffer ((const ProtobufCMessage*)message, buffer);\n}\nCellMessage *\n       cell_message__unpack\n                     (ProtobufCAllocator  *allocator,\n                      size_t               len,\n                      const uint8_t       *data)\n{\n  return (CellMessage *)\n     protobuf_c_message_unpack (&cell_message__descriptor,\n                                allocator, len, data);\n}\nvoid   cell_message__free_unpacked\n                     (CellMessage *message,\n                      ProtobufCAllocator *allocator)\n{\n  if(!message)\n    return;\n  assert(message->base.descriptor == &cell_message__descriptor);\n  protobuf_c_message_free_unpacked ((ProtobufCMessage*)message, allocator);\n}\nvoid   versioned_cell_message__init\n                     (VersionedCellMessage         *message)\n{\n  static const VersionedCellMessage init_value = VERSIONED_CELL_MESSAGE__INIT;\n  *message = init_value;\n}\nsize_t versioned_cell_message__get_packed_size\n                     (const VersionedCellMessage *message)\n{\n  assert(message->base.descriptor == &versioned_cell_message__descriptor);\n  return protobuf_c_message_get_packed_size ((const ProtobufCMessage*)(message));\n}\nsize_t versioned_cell_message__pack\n                     (const VersionedCellMessage *message,\n                      uint8_t       *out)\n{\n  assert(message->base.descriptor == &versioned_cell_message__descriptor);\n  return protobuf_c_message_pack ((const ProtobufCMessage*)message, out);\n}\nsize_t versioned_cell_message__pack_to_buffer\n                     (const VersionedCellMessage *message,\n                      ProtobufCBuffer *buffer)\n{\n  assert(message->base.descriptor == &versioned_cell_message__descriptor);\n  return protobuf_c_message_pack_to_buffer ((const ProtobufCMessage*)message, buffer);\n}\nVersionedCellMessage *\n       versioned_cell_message__unpack\n                     (ProtobufCAllocator  *allocator,\n                      size_t               len,\n                      const uint8_t       *data)\n{\n  return (VersionedCellMessage *)\n     protobuf_c_message_unpack (&versioned_cell_message__descriptor,\n                                allocator, len, data);\n}\nvoid   versioned_cell_message__free_unpacked\n                     (VersionedCellMessage *message,\n                      ProtobufCAllocator *allocator)\n{\n  if(!message)\n    return;\n  assert(message->base.descriptor == &versioned_cell_message__descriptor);\n  protobuf_c_message_free_unpacked ((ProtobufCMessage*)message, allocator);\n}\nvoid   server_message__init\n                     (ServerMessage         *message)\n{\n  static const ServerMessage init_value = SERVER_MESSAGE__INIT;\n  *message = init_value;\n}\nsize_t server_message__get_packed_size\n                     (const ServerMessage *message)\n{\n  assert(message->base.descriptor == &server_message__descriptor);\n  return protobuf_c_message_get_packed_size ((const ProtobufCMessage*)(message));\n}\nsize_t server_message__pack\n                     (const ServerMessage *message,\n                      uint8_t       *out)\n{\n  assert(message->base.descriptor == &server_message__descriptor);\n  return protobuf_c_message_pack ((const ProtobufCMessage*)message, out);\n}\nsize_t server_message__pack_to_buffer\n                     (const ServerMessage *message,\n                      ProtobufCBuffer *buffer)\n{\n  assert(message->base.descriptor == &server_message__descriptor);\n  return protobuf_c_message_pack_to_buffer ((const ProtobufCMessage*)message, buffer);\n}\nServerMessage *\n       server_message__unpack\n                     (ProtobufCAllocator  *allocator,\n                      size_t               len,\n                      const uint8_t       *data)\n{\n  return (ServerMessage *)\n     protobuf_c_message_unpack (&server_message__descriptor,\n                                allocator, len, data);\n}\nvoid   server_message__free_unpacked\n                     (ServerMessage *message,\n                      ProtobufCAllocator *allocator)\n{\n  if(!message)\n    return;\n  assert(message->base.descriptor == &server_message__descriptor);\n  protobuf_c_message_free_unpacked ((ProtobufCMessage*)message, allocator);\n}\nvoid   client_message__init\n                     (ClientMessage         *message)\n{\n  static const ClientMessage init_value = CLIENT_MESSAGE__INIT;\n  *message = init_value;\n}\nsize_t client_message__get_packed_size\n                     (const ClientMessage *message)\n{\n  assert(message->base.descriptor == &client_message__descriptor);\n  return protobuf_c_message_get_packed_size ((const ProtobufCMessage*)(message));\n}\nsize_t client_message__pack\n                     (const ClientMessage *message,\n                      uint8_t       *out)\n{\n  assert(message->base.descriptor == &client_message__descriptor);\n  return protobuf_c_message_pack ((const ProtobufCMessage*)message, out);\n}\nsize_t client_message__pack_to_buffer\n                     (const ClientMessage *message,\n                      ProtobufCBuffer *buffer)\n{\n  assert(message->base.descriptor == &client_message__descriptor);\n  return protobuf_c_message_pack_to_buffer ((const ProtobufCMessage*)message, buffer);\n}\nClientMessage *\n       client_message__unpack\n                     (ProtobufCAllocator  *allocator,\n                      size_t               len,\n                      const uint8_t       *data)\n{\n  return (ClientMessage *)\n     protobuf_c_message_unpack (&client_message__descriptor,\n                                allocator, len, data);\n}\nvoid   client_message__free_unpacked\n                     (ClientMessage *message,\n                      ProtobufCAllocator *allocator)\n{\n  if(!message)\n    return;\n  assert(message->base.descriptor == &client_message__descriptor);\n  protobuf_c_message_free_unpacked ((ProtobufCMessage*)message, allocator);\n}\nvoid   write_query_message__init\n                     (WriteQueryMessage         *message)\n{\n  static const WriteQueryMessage init_value = WRITE_QUERY_MESSAGE__INIT;\n  *message = init_value;\n}\nsize_t write_query_message__get_packed_size\n                     (const WriteQueryMessage *message)\n{\n  assert(message->base.descriptor == &write_query_message__descriptor);\n  return protobuf_c_message_get_packed_size ((const ProtobufCMessage*)(message));\n}\nsize_t write_query_message__pack\n                     (const WriteQueryMessage *message,\n                      uint8_t       *out)\n{\n  assert(message->base.descriptor == &write_query_message__descriptor);\n  return protobuf_c_message_pack ((const ProtobufCMessage*)message, out);\n}\nsize_t write_query_message__pack_to_buffer\n                     (const WriteQueryMessage *message,\n                      ProtobufCBuffer *buffer)\n{\n  assert(message->base.descriptor == &write_query_message__descriptor);\n  return protobuf_c_message_pack_to_buffer ((const ProtobufCMessage*)message, buffer);\n}\nWriteQueryMessage *\n       write_query_message__unpack\n                     (ProtobufCAllocator  *allocator,\n                      size_t               len,\n                      const uint8_t       *data)\n{\n  return (WriteQueryMessage *)\n     protobuf_c_message_unpack (&write_query_message__descriptor,\n                                allocator, len, data);\n}\nvoid   write_query_message__free_unpacked\n                     (WriteQueryMessage *message,\n                      ProtobufCAllocator *allocator)\n{\n  if(!message)\n    return;\n  assert(message->base.descriptor == &write_query_message__descriptor);\n  protobuf_c_message_free_unpacked ((ProtobufCMessage*)message, allocator);\n}\nvoid   read_query_message__init\n                     (ReadQueryMessage         *message)\n{\n  static const ReadQueryMessage init_value = READ_QUERY_MESSAGE__INIT;\n  *message = init_value;\n}\nsize_t read_query_message__get_packed_size\n                     (const ReadQueryMessage *message)\n{\n  assert(message->base.descriptor == &read_query_message__descriptor);\n  return protobuf_c_message_get_packed_size ((const ProtobufCMessage*)(message));\n}\nsize_t read_query_message__pack\n                     (const ReadQueryMessage *message,\n                      uint8_t       *out)\n{\n  assert(message->base.descriptor == &read_query_message__descriptor);\n  return protobuf_c_message_pack ((const ProtobufCMessage*)message, out);\n}\nsize_t read_query_message__pack_to_buffer\n                     (const ReadQueryMessage *message,\n                      ProtobufCBuffer *buffer)\n{\n  assert(message->base.descriptor == &read_query_message__descriptor);\n  return protobuf_c_message_pack_to_buffer ((const ProtobufCMessage*)message, buffer);\n}\nReadQueryMessage *\n       read_query_message__unpack\n                     (ProtobufCAllocator  *allocator,\n                      size_t               len,\n                      const uint8_t       *data)\n{\n  return (ReadQueryMessage *)\n     protobuf_c_message_unpack (&read_query_message__descriptor,\n                                allocator, len, data);\n}\nvoid   read_query_message__free_unpacked\n                     (ReadQueryMessage *message,\n                      ProtobufCAllocator *allocator)\n{\n  if(!message)\n    return;\n  assert(message->base.descriptor == &read_query_message__descriptor);\n  protobuf_c_message_free_unpacked ((ProtobufCMessage*)message, allocator);\n}\nvoid   ack_message__init\n                     (AckMessage         *message)\n{\n  static const AckMessage init_value = ACK_MESSAGE__INIT;\n  *message = init_value;\n}\nsize_t ack_message__get_packed_size\n                     (const AckMessage *message)\n{\n  assert(message->base.descriptor == &ack_message__descriptor);\n  return protobuf_c_message_get_packed_size ((const ProtobufCMessage*)(message));\n}\nsize_t ack_message__pack\n                     (const AckMessage *message,\n                      uint8_t       *out)\n{\n  assert(message->base.descriptor == &ack_message__descriptor);\n  return protobuf_c_message_pack ((const ProtobufCMessage*)message, out);\n}\nsize_t ack_message__pack_to_buffer\n                     (const AckMessage *message,\n                      ProtobufCBuffer *buffer)\n{\n  assert(message->base.descriptor == &ack_message__descriptor);\n  return protobuf_c_message_pack_to_buffer ((const ProtobufCMessage*)message, buffer);\n}\nAckMessage *\n       ack_message__unpack\n                     (ProtobufCAllocator  *allocator,\n                      size_t               len,\n                      const uint8_t       *data)\n{\n  return (AckMessage *)\n     protobuf_c_message_unpack (&ack_message__descriptor,\n                                allocator, len, data);\n}\nvoid   ack_message__free_unpacked\n                     (AckMessage *message,\n                      ProtobufCAllocator *allocator)\n{\n  if(!message)\n    return;\n  assert(message->base.descriptor == &ack_message__descriptor);\n  protobuf_c_message_free_unpacked ((ProtobufCMessage*)message, allocator);\n}\nvoid   range_read_query_message__init\n                     (RangeReadQueryMessage         *message)\n{\n  static const RangeReadQueryMessage init_value = RANGE_READ_QUERY_MESSAGE__INIT;\n  *message = init_value;\n}\nsize_t range_read_query_message__get_packed_size\n                     (const RangeReadQueryMessage *message)\n{\n  assert(message->base.descriptor == &range_read_query_message__descriptor);\n  return protobuf_c_message_get_packed_size ((const ProtobufCMessage*)(message));\n}\nsize_t range_read_query_message__pack\n                     (const RangeReadQueryMessage *message,\n                      uint8_t       *out)\n{\n  assert(message->base.descriptor == &range_read_query_message__descriptor);\n  return protobuf_c_message_pack ((const ProtobufCMessage*)message, out);\n}\nsize_t range_read_query_message__pack_to_buffer\n                     (const RangeReadQueryMessage *message,\n                      ProtobufCBuffer *buffer)\n{\n  assert(message->base.descriptor == &range_read_query_message__descriptor);\n  return protobuf_c_message_pack_to_buffer ((const ProtobufCMessage*)message, buffer);\n}\nRangeReadQueryMessage *\n       range_read_query_message__unpack\n                     (ProtobufCAllocator  *allocator,\n                      size_t               len,\n                      const uint8_t       *data)\n{\n  return (RangeReadQueryMessage *)\n     protobuf_c_message_unpack (&range_read_query_message__descriptor,\n                                allocator, len, data);\n}\nvoid   range_read_query_message__free_unpacked\n                     (RangeReadQueryMessage *message,\n                      ProtobufCAllocator *allocator)\n{\n  if(!message)\n    return;\n  assert(message->base.descriptor == &range_read_query_message__descriptor);\n  protobuf_c_message_free_unpacked ((ProtobufCMessage*)message, allocator);\n}\nvoid   range_read_response_message__init\n                     (RangeReadResponseMessage         *message)\n{\n  static const RangeReadResponseMessage init_value = RANGE_READ_RESPONSE_MESSAGE__INIT;\n  *message = init_value;\n}\nsize_t range_read_response_message__get_packed_size\n                     (const RangeReadResponseMessage *message)\n{\n  assert(message->base.descriptor == &range_read_response_message__descriptor);\n  return protobuf_c_message_get_packed_size ((const ProtobufCMessage*)(message));\n}\nsize_t range_read_response_message__pack\n                     (const RangeReadResponseMessage *message,\n                      uint8_t       *out)\n{\n  assert(message->base.descriptor == &range_read_response_message__descriptor);\n  return protobuf_c_message_pack ((const ProtobufCMessage*)message, out);\n}\nsize_t range_read_response_message__pack_to_buffer\n                     (const RangeReadResponseMessage *message,\n                      ProtobufCBuffer *buffer)\n{\n  assert(message->base.descriptor == &range_read_response_message__descriptor);\n  return protobuf_c_message_pack_to_buffer ((const ProtobufCMessage*)message, buffer);\n}\nRangeReadResponseMessage *\n       range_read_response_message__unpack\n                     (ProtobufCAllocator  *allocator,\n                      size_t               len,\n                      const uint8_t       *data)\n{\n  return (RangeReadResponseMessage *)\n     protobuf_c_message_unpack (&range_read_response_message__descriptor,\n                                allocator, len, data);\n}\nvoid   range_read_response_message__free_unpacked\n                     (RangeReadResponseMessage *message,\n                      ProtobufCAllocator *allocator)\n{\n  if(!message)\n    return;\n  assert(message->base.descriptor == &range_read_response_message__descriptor);\n  protobuf_c_message_free_unpacked ((ProtobufCMessage*)message, allocator);\n}\nvoid   txn_message__init\n                     (TxnMessage         *message)\n{\n  static const TxnMessage init_value = TXN_MESSAGE__INIT;\n  *message = init_value;\n}\nsize_t txn_message__get_packed_size\n                     (const TxnMessage *message)\n{\n  assert(message->base.descriptor == &txn_message__descriptor);\n  return protobuf_c_message_get_packed_size ((const ProtobufCMessage*)(message));\n}\nsize_t txn_message__pack\n                     (const TxnMessage *message,\n                      uint8_t       *out)\n{\n  assert(message->base.descriptor == &txn_message__descriptor);\n  return protobuf_c_message_pack ((const ProtobufCMessage*)message, out);\n}\nsize_t txn_message__pack_to_buffer\n                     (const TxnMessage *message,\n                      ProtobufCBuffer *buffer)\n{\n  assert(message->base.descriptor == &txn_message__descriptor);\n  return protobuf_c_message_pack_to_buffer ((const ProtobufCMessage*)message, buffer);\n}\nTxnMessage *\n       txn_message__unpack\n                     (ProtobufCAllocator  *allocator,\n                      size_t               len,\n                      const uint8_t       *data)\n{\n  return (TxnMessage *)\n     protobuf_c_message_unpack (&txn_message__descriptor,\n                                allocator, len, data);\n}\nvoid   txn_message__free_unpacked\n                     (TxnMessage *message,\n                      ProtobufCAllocator *allocator)\n{\n  if(!message)\n    return;\n  assert(message->base.descriptor == &txn_message__descriptor);\n  protobuf_c_message_free_unpacked ((ProtobufCMessage*)message, allocator);\n}\nvoid   queue_query_message__init\n                     (QueueQueryMessage         *message)\n{\n  static const QueueQueryMessage init_value = QUEUE_QUERY_MESSAGE__INIT;\n  *message = init_value;\n}\nsize_t queue_query_message__get_packed_size\n                     (const QueueQueryMessage *message)\n{\n  assert(message->base.descriptor == &queue_query_message__descriptor);\n  return protobuf_c_message_get_packed_size ((const ProtobufCMessage*)(message));\n}\nsize_t queue_query_message__pack\n                     (const QueueQueryMessage *message,\n                      uint8_t       *out)\n{\n  assert(message->base.descriptor == &queue_query_message__descriptor);\n  return protobuf_c_message_pack ((const ProtobufCMessage*)message, out);\n}\nsize_t queue_query_message__pack_to_buffer\n                     (const QueueQueryMessage *message,\n                      ProtobufCBuffer *buffer)\n{\n  assert(message->base.descriptor == &queue_query_message__descriptor);\n  return protobuf_c_message_pack_to_buffer ((const ProtobufCMessage*)message, buffer);\n}\nQueueQueryMessage *\n       queue_query_message__unpack\n                     (ProtobufCAllocator  *allocator,\n                      size_t               len,\n                      const uint8_t       *data)\n{\n  return (QueueQueryMessage *)\n     protobuf_c_message_unpack (&queue_query_message__descriptor,\n                                allocator, len, data);\n}\nvoid   queue_query_message__free_unpacked\n                     (QueueQueryMessage *message,\n                      ProtobufCAllocator *allocator)\n{\n  if(!message)\n    return;\n  assert(message->base.descriptor == &queue_query_message__descriptor);\n  protobuf_c_message_free_unpacked ((ProtobufCMessage*)message, allocator);\n}\nvoid   consumer_id__init\n                     (ConsumerID         *message)\n{\n  static const ConsumerID init_value = CONSUMER_ID__INIT;\n  *message = init_value;\n}\nsize_t consumer_id__get_packed_size\n                     (const ConsumerID *message)\n{\n  assert(message->base.descriptor == &consumer_id__descriptor);\n  return protobuf_c_message_get_packed_size ((const ProtobufCMessage*)(message));\n}\nsize_t consumer_id__pack\n                     (const ConsumerID *message,\n                      uint8_t       *out)\n{\n  assert(message->base.descriptor == &consumer_id__descriptor);\n  return protobuf_c_message_pack ((const ProtobufCMessage*)message, out);\n}\nsize_t consumer_id__pack_to_buffer\n                     (const ConsumerID *message,\n                      ProtobufCBuffer *buffer)\n{\n  assert(message->base.descriptor == &consumer_id__descriptor);\n  return protobuf_c_message_pack_to_buffer ((const ProtobufCMessage*)message, buffer);\n}\nConsumerID *\n       consumer_id__unpack\n                     (ProtobufCAllocator  *allocator,\n                      size_t               len,\n                      const uint8_t       *data)\n{\n  return (ConsumerID *)\n     protobuf_c_message_unpack (&consumer_id__descriptor,\n                                allocator, len, data);\n}\nvoid   consumer_id__free_unpacked\n                     (ConsumerID *message,\n                      ProtobufCAllocator *allocator)\n{\n  if(!message)\n    return;\n  assert(message->base.descriptor == &consumer_id__descriptor);\n  protobuf_c_message_free_unpacked ((ProtobufCMessage*)message, allocator);\n}\nvoid   create_queue_message__init\n                     (CreateQueueMessage         *message)\n{\n  static const CreateQueueMessage init_value = CREATE_QUEUE_MESSAGE__INIT;\n  *message = init_value;\n}\nsize_t create_queue_message__get_packed_size\n                     (const CreateQueueMessage *message)\n{\n  assert(message->base.descriptor == &create_queue_message__descriptor);\n  return protobuf_c_message_get_packed_size ((const ProtobufCMessage*)(message));\n}\nsize_t create_queue_message__pack\n                     (const CreateQueueMessage *message,\n                      uint8_t       *out)\n{\n  assert(message->base.descriptor == &create_queue_message__descriptor);\n  return protobuf_c_message_pack ((const ProtobufCMessage*)message, out);\n}\nsize_t create_queue_message__pack_to_buffer\n                     (const CreateQueueMessage *message,\n                      ProtobufCBuffer *buffer)\n{\n  assert(message->base.descriptor == &create_queue_message__descriptor);\n  return protobuf_c_message_pack_to_buffer ((const ProtobufCMessage*)message, buffer);\n}\nCreateQueueMessage *\n       create_queue_message__unpack\n                     (ProtobufCAllocator  *allocator,\n                      size_t               len,\n                      const uint8_t       *data)\n{\n  return (CreateQueueMessage *)\n     protobuf_c_message_unpack (&create_queue_message__descriptor,\n                                allocator, len, data);\n}\nvoid   create_queue_message__free_unpacked\n                     (CreateQueueMessage *message,\n                      ProtobufCAllocator *allocator)\n{\n  if(!message)\n    return;\n  assert(message->base.descriptor == &create_queue_message__descriptor);\n  protobuf_c_message_free_unpacked ((ProtobufCMessage*)message, allocator);\n}\nvoid   delete_queue_message__init\n                     (DeleteQueueMessage         *message)\n{\n  static const DeleteQueueMessage init_value = DELETE_QUEUE_MESSAGE__INIT;\n  *message = init_value;\n}\nsize_t delete_queue_message__get_packed_size\n                     (const DeleteQueueMessage *message)\n{\n  assert(message->base.descriptor == &delete_queue_message__descriptor);\n  return protobuf_c_message_get_packed_size ((const ProtobufCMessage*)(message));\n}\nsize_t delete_queue_message__pack\n                     (const DeleteQueueMessage *message,\n                      uint8_t       *out)\n{\n  assert(message->base.descriptor == &delete_queue_message__descriptor);\n  return protobuf_c_message_pack ((const ProtobufCMessage*)message, out);\n}\nsize_t delete_queue_message__pack_to_buffer\n                     (const DeleteQueueMessage *message,\n                      ProtobufCBuffer *buffer)\n{\n  assert(message->base.descriptor == &delete_queue_message__descriptor);\n  return protobuf_c_message_pack_to_buffer ((const ProtobufCMessage*)message, buffer);\n}\nDeleteQueueMessage *\n       delete_queue_message__unpack\n                     (ProtobufCAllocator  *allocator,\n                      size_t               len,\n                      const uint8_t       *data)\n{\n  return (DeleteQueueMessage *)\n     protobuf_c_message_unpack (&delete_queue_message__descriptor,\n                                allocator, len, data);\n}\nvoid   delete_queue_message__free_unpacked\n                     (DeleteQueueMessage *message,\n                      ProtobufCAllocator *allocator)\n{\n  if(!message)\n    return;\n  assert(message->base.descriptor == &delete_queue_message__descriptor);\n  protobuf_c_message_free_unpacked ((ProtobufCMessage*)message, allocator);\n}\nvoid   subscribe_queue_message__init\n                     (SubscribeQueueMessage         *message)\n{\n  static const SubscribeQueueMessage init_value = SUBSCRIBE_QUEUE_MESSAGE__INIT;\n  *message = init_value;\n}\nsize_t subscribe_queue_message__get_packed_size\n                     (const SubscribeQueueMessage *message)\n{\n  assert(message->base.descriptor == &subscribe_queue_message__descriptor);\n  return protobuf_c_message_get_packed_size ((const ProtobufCMessage*)(message));\n}\nsize_t subscribe_queue_message__pack\n                     (const SubscribeQueueMessage *message,\n                      uint8_t       *out)\n{\n  assert(message->base.descriptor == &subscribe_queue_message__descriptor);\n  return protobuf_c_message_pack ((const ProtobufCMessage*)message, out);\n}\nsize_t subscribe_queue_message__pack_to_buffer\n                     (const SubscribeQueueMessage *message,\n                      ProtobufCBuffer *buffer)\n{\n  assert(message->base.descriptor == &subscribe_queue_message__descriptor);\n  return protobuf_c_message_pack_to_buffer ((const ProtobufCMessage*)message, buffer);\n}\nSubscribeQueueMessage *\n       subscribe_queue_message__unpack\n                     (ProtobufCAllocator  *allocator,\n                      size_t               len,\n                      const uint8_t       *data)\n{\n  return (SubscribeQueueMessage *)\n     protobuf_c_message_unpack (&subscribe_queue_message__descriptor,\n                                allocator, len, data);\n}\nvoid   subscribe_queue_message__free_unpacked\n                     (SubscribeQueueMessage *message,\n                      ProtobufCAllocator *allocator)\n{\n  if(!message)\n    return;\n  assert(message->base.descriptor == &subscribe_queue_message__descriptor);\n  protobuf_c_message_free_unpacked ((ProtobufCMessage*)message, allocator);\n}\nvoid   unsubscribe_queue_message__init\n                     (UnsubscribeQueueMessage         *message)\n{\n  static const UnsubscribeQueueMessage init_value = UNSUBSCRIBE_QUEUE_MESSAGE__INIT;\n  *message = init_value;\n}\nsize_t unsubscribe_queue_message__get_packed_size\n                     (const UnsubscribeQueueMessage *message)\n{\n  assert(message->base.descriptor == &unsubscribe_queue_message__descriptor);\n  return protobuf_c_message_get_packed_size ((const ProtobufCMessage*)(message));\n}\nsize_t unsubscribe_queue_message__pack\n                     (const UnsubscribeQueueMessage *message,\n                      uint8_t       *out)\n{\n  assert(message->base.descriptor == &unsubscribe_queue_message__descriptor);\n  return protobuf_c_message_pack ((const ProtobufCMessage*)message, out);\n}\nsize_t unsubscribe_queue_message__pack_to_buffer\n                     (const UnsubscribeQueueMessage *message,\n                      ProtobufCBuffer *buffer)\n{\n  assert(message->base.descriptor == &unsubscribe_queue_message__descriptor);\n  return protobuf_c_message_pack_to_buffer ((const ProtobufCMessage*)message, buffer);\n}\nUnsubscribeQueueMessage *\n       unsubscribe_queue_message__unpack\n                     (ProtobufCAllocator  *allocator,\n                      size_t               len,\n                      const uint8_t       *data)\n{\n  return (UnsubscribeQueueMessage *)\n     protobuf_c_message_unpack (&unsubscribe_queue_message__descriptor,\n                                allocator, len, data);\n}\nvoid   unsubscribe_queue_message__free_unpacked\n                     (UnsubscribeQueueMessage *message,\n                      ProtobufCAllocator *allocator)\n{\n  if(!message)\n    return;\n  assert(message->base.descriptor == &unsubscribe_queue_message__descriptor);\n  protobuf_c_message_free_unpacked ((ProtobufCMessage*)message, allocator);\n}\nvoid   enqueue_message__init\n                     (EnqueueMessage         *message)\n{\n  static const EnqueueMessage init_value = ENQUEUE_MESSAGE__INIT;\n  *message = init_value;\n}\nsize_t enqueue_message__get_packed_size\n                     (const EnqueueMessage *message)\n{\n  assert(message->base.descriptor == &enqueue_message__descriptor);\n  return protobuf_c_message_get_packed_size ((const ProtobufCMessage*)(message));\n}\nsize_t enqueue_message__pack\n                     (const EnqueueMessage *message,\n                      uint8_t       *out)\n{\n  assert(message->base.descriptor == &enqueue_message__descriptor);\n  return protobuf_c_message_pack ((const ProtobufCMessage*)message, out);\n}\nsize_t enqueue_message__pack_to_buffer\n                     (const EnqueueMessage *message,\n                      ProtobufCBuffer *buffer)\n{\n  assert(message->base.descriptor == &enqueue_message__descriptor);\n  return protobuf_c_message_pack_to_buffer ((const ProtobufCMessage*)message, buffer);\n}\nEnqueueMessage *\n       enqueue_message__unpack\n                     (ProtobufCAllocator  *allocator,\n                      size_t               len,\n                      const uint8_t       *data)\n{\n  return (EnqueueMessage *)\n     protobuf_c_message_unpack (&enqueue_message__descriptor,\n                                allocator, len, data);\n}\nvoid   enqueue_message__free_unpacked\n                     (EnqueueMessage *message,\n                      ProtobufCAllocator *allocator)\n{\n  if(!message)\n    return;\n  assert(message->base.descriptor == &enqueue_message__descriptor);\n  protobuf_c_message_free_unpacked ((ProtobufCMessage*)message, allocator);\n}\nvoid   enqueue_response_message__init\n                     (EnqueueResponseMessage         *message)\n{\n  static const EnqueueResponseMessage init_value = ENQUEUE_RESPONSE_MESSAGE__INIT;\n  *message = init_value;\n}\nsize_t enqueue_response_message__get_packed_size\n                     (const EnqueueResponseMessage *message)\n{\n  assert(message->base.descriptor == &enqueue_response_message__descriptor);\n  return protobuf_c_message_get_packed_size ((const ProtobufCMessage*)(message));\n}\nsize_t enqueue_response_message__pack\n                     (const EnqueueResponseMessage *message,\n                      uint8_t       *out)\n{\n  assert(message->base.descriptor == &enqueue_response_message__descriptor);\n  return protobuf_c_message_pack ((const ProtobufCMessage*)message, out);\n}\nsize_t enqueue_response_message__pack_to_buffer\n                     (const EnqueueResponseMessage *message,\n                      ProtobufCBuffer *buffer)\n{\n  assert(message->base.descriptor == &enqueue_response_message__descriptor);\n  return protobuf_c_message_pack_to_buffer ((const ProtobufCMessage*)message, buffer);\n}\nEnqueueResponseMessage *\n       enqueue_response_message__unpack\n                     (ProtobufCAllocator  *allocator,\n                      size_t               len,\n                      const uint8_t       *data)\n{\n  return (EnqueueResponseMessage *)\n     protobuf_c_message_unpack (&enqueue_response_message__descriptor,\n                                allocator, len, data);\n}\nvoid   enqueue_response_message__free_unpacked\n                     (EnqueueResponseMessage *message,\n                      ProtobufCAllocator *allocator)\n{\n  if(!message)\n    return;\n  assert(message->base.descriptor == &enqueue_response_message__descriptor);\n  protobuf_c_message_free_unpacked ((ProtobufCMessage*)message, allocator);\n}\nvoid   read_queue_message__init\n                     (ReadQueueMessage         *message)\n{\n  static const ReadQueueMessage init_value = READ_QUEUE_MESSAGE__INIT;\n  *message = init_value;\n}\nsize_t read_queue_message__get_packed_size\n                     (const ReadQueueMessage *message)\n{\n  assert(message->base.descriptor == &read_queue_message__descriptor);\n  return protobuf_c_message_get_packed_size ((const ProtobufCMessage*)(message));\n}\nsize_t read_queue_message__pack\n                     (const ReadQueueMessage *message,\n                      uint8_t       *out)\n{\n  assert(message->base.descriptor == &read_queue_message__descriptor);\n  return protobuf_c_message_pack ((const ProtobufCMessage*)message, out);\n}\nsize_t read_queue_message__pack_to_buffer\n                     (const ReadQueueMessage *message,\n                      ProtobufCBuffer *buffer)\n{\n  assert(message->base.descriptor == &read_queue_message__descriptor);\n  return protobuf_c_message_pack_to_buffer ((const ProtobufCMessage*)message, buffer);\n}\nReadQueueMessage *\n       read_queue_message__unpack\n                     (ProtobufCAllocator  *allocator,\n                      size_t               len,\n                      const uint8_t       *data)\n{\n  return (ReadQueueMessage *)\n     protobuf_c_message_unpack (&read_queue_message__descriptor,\n                                allocator, len, data);\n}\nvoid   read_queue_message__free_unpacked\n                     (ReadQueueMessage *message,\n                      ProtobufCAllocator *allocator)\n{\n  if(!message)\n    return;\n  assert(message->base.descriptor == &read_queue_message__descriptor);\n  protobuf_c_message_free_unpacked ((ProtobufCMessage*)message, allocator);\n}\nvoid   read_queue_response_message__init\n                     (ReadQueueResponseMessage         *message)\n{\n  static const ReadQueueResponseMessage init_value = READ_QUEUE_RESPONSE_MESSAGE__INIT;\n  *message = init_value;\n}\nsize_t read_queue_response_message__get_packed_size\n                     (const ReadQueueResponseMessage *message)\n{\n  assert(message->base.descriptor == &read_queue_response_message__descriptor);\n  return protobuf_c_message_get_packed_size ((const ProtobufCMessage*)(message));\n}\nsize_t read_queue_response_message__pack\n                     (const ReadQueueResponseMessage *message,\n                      uint8_t       *out)\n{\n  assert(message->base.descriptor == &read_queue_response_message__descriptor);\n  return protobuf_c_message_pack ((const ProtobufCMessage*)message, out);\n}\nsize_t read_queue_response_message__pack_to_buffer\n                     (const ReadQueueResponseMessage *message,\n                      ProtobufCBuffer *buffer)\n{\n  assert(message->base.descriptor == &read_queue_response_message__descriptor);\n  return protobuf_c_message_pack_to_buffer ((const ProtobufCMessage*)message, buffer);\n}\nReadQueueResponseMessage *\n       read_queue_response_message__unpack\n                     (ProtobufCAllocator  *allocator,\n                      size_t               len,\n                      const uint8_t       *data)\n{\n  return (ReadQueueResponseMessage *)\n     protobuf_c_message_unpack (&read_queue_response_message__descriptor,\n                                allocator, len, data);\n}\nvoid   read_queue_response_message__free_unpacked\n                     (ReadQueueResponseMessage *message,\n                      ProtobufCAllocator *allocator)\n{\n  if(!message)\n    return;\n  assert(message->base.descriptor == &read_queue_response_message__descriptor);\n  protobuf_c_message_free_unpacked ((ProtobufCMessage*)message, allocator);\n}\nvoid   consume_queue_message__init\n                     (ConsumeQueueMessage         *message)\n{\n  static const ConsumeQueueMessage init_value = CONSUME_QUEUE_MESSAGE__INIT;\n  *message = init_value;\n}\nsize_t consume_queue_message__get_packed_size\n                     (const ConsumeQueueMessage *message)\n{\n  assert(message->base.descriptor == &consume_queue_message__descriptor);\n  return protobuf_c_message_get_packed_size ((const ProtobufCMessage*)(message));\n}\nsize_t consume_queue_message__pack\n                     (const ConsumeQueueMessage *message,\n                      uint8_t       *out)\n{\n  assert(message->base.descriptor == &consume_queue_message__descriptor);\n  return protobuf_c_message_pack ((const ProtobufCMessage*)message, out);\n}\nsize_t consume_queue_message__pack_to_buffer\n                     (const ConsumeQueueMessage *message,\n                      ProtobufCBuffer *buffer)\n{\n  assert(message->base.descriptor == &consume_queue_message__descriptor);\n  return protobuf_c_message_pack_to_buffer ((const ProtobufCMessage*)message, buffer);\n}\nConsumeQueueMessage *\n       consume_queue_message__unpack\n                     (ProtobufCAllocator  *allocator,\n                      size_t               len,\n                      const uint8_t       *data)\n{\n  return (ConsumeQueueMessage *)\n     protobuf_c_message_unpack (&consume_queue_message__descriptor,\n                                allocator, len, data);\n}\nvoid   consume_queue_message__free_unpacked\n                     (ConsumeQueueMessage *message,\n                      ProtobufCAllocator *allocator)\n{\n  if(!message)\n    return;\n  assert(message->base.descriptor == &consume_queue_message__descriptor);\n  protobuf_c_message_free_unpacked ((ProtobufCMessage*)message, allocator);\n}\nvoid   consume_queue_response_message__init\n                     (ConsumeQueueResponseMessage         *message)\n{\n  static const ConsumeQueueResponseMessage init_value = CONSUME_QUEUE_RESPONSE_MESSAGE__INIT;\n  *message = init_value;\n}\nsize_t consume_queue_response_message__get_packed_size\n                     (const ConsumeQueueResponseMessage *message)\n{\n  assert(message->base.descriptor == &consume_queue_response_message__descriptor);\n  return protobuf_c_message_get_packed_size ((const ProtobufCMessage*)(message));\n}\nsize_t consume_queue_response_message__pack\n                     (const ConsumeQueueResponseMessage *message,\n                      uint8_t       *out)\n{\n  assert(message->base.descriptor == &consume_queue_response_message__descriptor);\n  return protobuf_c_message_pack ((const ProtobufCMessage*)message, out);\n}\nsize_t consume_queue_response_message__pack_to_buffer\n                     (const ConsumeQueueResponseMessage *message,\n                      ProtobufCBuffer *buffer)\n{\n  assert(message->base.descriptor == &consume_queue_response_message__descriptor);\n  return protobuf_c_message_pack_to_buffer ((const ProtobufCMessage*)message, buffer);\n}\nConsumeQueueResponseMessage *\n       consume_queue_response_message__unpack\n                     (ProtobufCAllocator  *allocator,\n                      size_t               len,\n                      const uint8_t       *data)\n{\n  return (ConsumeQueueResponseMessage *)\n     protobuf_c_message_unpack (&consume_queue_response_message__descriptor,\n                                allocator, len, data);\n}\nvoid   consume_queue_response_message__free_unpacked\n                     (ConsumeQueueResponseMessage *message,\n                      ProtobufCAllocator *allocator)\n{\n  if(!message)\n    return;\n  assert(message->base.descriptor == &consume_queue_response_message__descriptor);\n  protobuf_c_message_free_unpacked ((ProtobufCMessage*)message, allocator);\n}\nstatic const ProtobufCFieldDescriptor node_state_message__field_descriptors[6] =\n{\n  {\n    \"status\",\n    1,\n    PROTOBUF_C_LABEL_REQUIRED,\n    PROTOBUF_C_TYPE_INT32,\n    0,   /* quantifier_offset */\n    offsetof(NodeStateMessage, status),\n    NULL,\n    NULL,\n    0,             /* flags */\n    0,NULL,NULL    /* reserved1,reserved2, etc */\n  },\n  {\n    \"node_id\",\n    2,\n    PROTOBUF_C_LABEL_REQUIRED,\n    PROTOBUF_C_TYPE_INT32,\n    0,   /* quantifier_offset */\n    offsetof(NodeStateMessage, node_id),\n    NULL,\n    NULL,\n    0,             /* flags */\n    0,NULL,NULL    /* reserved1,reserved2, etc */\n  },\n  {\n    \"hostname\",\n    3,\n    PROTOBUF_C_LABEL_REQUIRED,\n    PROTOBUF_C_TYPE_BYTES,\n    0,   /* quantifier_offset */\n    offsetof(NodeStateMessage, hostname),\n    NULL,\n    NULL,\n    0,             /* flags */\n    0,NULL,NULL    /* reserved1,reserved2, etc */\n  },\n  {\n    \"port\",\n    4,\n    PROTOBUF_C_LABEL_REQUIRED,\n    PROTOBUF_C_TYPE_INT32,\n    0,   /* quantifier_offset */\n    offsetof(NodeStateMessage, port),\n    NULL,\n    NULL,\n    0,             /* flags */\n    0,NULL,NULL    /* reserved1,reserved2, etc */\n  },\n  {\n    \"rack_id\",\n    5,\n    PROTOBUF_C_LABEL_REQUIRED,\n    PROTOBUF_C_TYPE_INT32,\n    0,   /* quantifier_offset */\n    offsetof(NodeStateMessage, rack_id),\n    NULL,\n    NULL,\n    0,             /* flags */\n    0,NULL,NULL    /* reserved1,reserved2, etc */\n  },\n  {\n    \"dc_id\",\n    6,\n    PROTOBUF_C_LABEL_REQUIRED,\n    PROTOBUF_C_TYPE_INT32,\n    0,   /* quantifier_offset */\n    offsetof(NodeStateMessage, dc_id),\n    NULL,\n    NULL,\n    0,             /* flags */\n    0,NULL,NULL    /* reserved1,reserved2, etc */\n  },\n};\nstatic const unsigned node_state_message__field_indices_by_name[] = {\n  5,   /* field[5] = dc_id */\n  2,   /* field[2] = hostname */\n  1,   /* field[1] = node_id */\n  3,   /* field[3] = port */\n  4,   /* field[4] = rack_id */\n  0,   /* field[0] = status */\n};\nstatic const ProtobufCIntRange node_state_message__number_ranges[1 + 1] =\n{\n  { 1, 0 },\n  { 0, 6 }\n};\nconst ProtobufCMessageDescriptor node_state_message__descriptor =\n{\n  PROTOBUF_C__MESSAGE_DESCRIPTOR_MAGIC,\n  \"NodeStateMessage\",\n  \"NodeStateMessage\",\n  \"NodeStateMessage\",\n  \"\",\n  sizeof(NodeStateMessage),\n  6,\n  node_state_message__field_descriptors,\n  node_state_message__field_indices_by_name,\n  1,  node_state_message__number_ranges,\n  (ProtobufCMessageInit) node_state_message__init,\n  NULL,NULL,NULL    /* reserved[123] */\n};\nstatic const ProtobufCFieldDescriptor vector_clock_message__field_descriptors[2] =\n{\n  {\n    \"ids\",\n    1,\n    PROTOBUF_C_LABEL_REPEATED,\n    PROTOBUF_C_TYPE_INT32,\n    offsetof(VectorClockMessage, n_ids),\n    offsetof(VectorClockMessage, ids),\n    NULL,\n    NULL,\n    0,             /* flags */\n    0,NULL,NULL    /* reserved1,reserved2, etc */\n  },\n  {\n    \"counters\",\n    2,\n    PROTOBUF_C_LABEL_REPEATED,\n    PROTOBUF_C_TYPE_INT64,\n    offsetof(VectorClockMessage, n_counters),\n    offsetof(VectorClockMessage, counters),\n    NULL,\n    NULL,\n    0,             /* flags */\n    0,NULL,NULL    /* reserved1,reserved2, etc */\n  },\n};\nstatic const unsigned vector_clock_message__field_indices_by_name[] = {\n  1,   /* field[1] = counters */\n  0,   /* field[0] = ids */\n};\nstatic const ProtobufCIntRange vector_clock_message__number_ranges[1 + 1] =\n{\n  { 1, 0 },\n  { 0, 2 }\n};\nconst ProtobufCMessageDescriptor vector_clock_message__descriptor =\n{\n  PROTOBUF_C__MESSAGE_DESCRIPTOR_MAGIC,\n  \"VectorClockMessage\",\n  \"VectorClockMessage\",\n  \"VectorClockMessage\",\n  \"\",\n  sizeof(VectorClockMessage),\n  2,\n  vector_clock_message__field_descriptors,\n  vector_clock_message__field_indices_by_name,\n  1,  vector_clock_message__number_ranges,\n  (ProtobufCMessageInit) vector_clock_message__init,\n  NULL,NULL,NULL    /* reserved[123] */\n};\nstatic const ProtobufCFieldDescriptor gossip_message__field_descriptors[2] =\n{\n  {\n    \"node_state\",\n    1,\n    PROTOBUF_C_LABEL_REQUIRED,\n    PROTOBUF_C_TYPE_MESSAGE,\n    0,   /* quantifier_offset */\n    offsetof(GossipMessage, node_state),\n    &node_state_message__descriptor,\n    NULL,\n    0,             /* flags */\n    0,NULL,NULL    /* reserved1,reserved2, etc */\n  },\n  {\n    \"vc\",\n    2,\n    PROTOBUF_C_LABEL_REQUIRED,\n    PROTOBUF_C_TYPE_MESSAGE,\n    0,   /* quantifier_offset */\n    offsetof(GossipMessage, vc),\n    &vector_clock_message__descriptor,\n    NULL,\n    0,             /* flags */\n    0,NULL,NULL    /* reserved1,reserved2, etc */\n  },\n};\nstatic const unsigned gossip_message__field_indices_by_name[] = {\n  0,   /* field[0] = node_state */\n  1,   /* field[1] = vc */\n};\nstatic const ProtobufCIntRange gossip_message__number_ranges[1 + 1] =\n{\n  { 1, 0 },\n  { 0, 2 }\n};\nconst ProtobufCMessageDescriptor gossip_message__descriptor =\n{\n  PROTOBUF_C__MESSAGE_DESCRIPTOR_MAGIC,\n  \"GossipMessage\",\n  \"GossipMessage\",\n  \"GossipMessage\",\n  \"\",\n  sizeof(GossipMessage),\n  2,\n  gossip_message__field_descriptors,\n  gossip_message__field_indices_by_name,\n  1,  gossip_message__number_ranges,\n  (ProtobufCMessageInit) gossip_message__init,\n  NULL,NULL,NULL    /* reserved[123] */\n};\nstatic const ProtobufCFieldDescriptor gossip_listen_message__field_descriptors[2] =\n{\n  {\n    \"node_state\",\n    1,\n    PROTOBUF_C_LABEL_REQUIRED,\n    PROTOBUF_C_TYPE_MESSAGE,\n    0,   /* quantifier_offset */\n    offsetof(GossipListenMessage, node_state),\n    &node_state_message__descriptor,\n    NULL,\n    0,             /* flags */\n    0,NULL,NULL    /* reserved1,reserved2, etc */\n  },\n  {\n    \"nonce\",\n    2,\n    PROTOBUF_C_LABEL_REQUIRED,\n    PROTOBUF_C_TYPE_INT64,\n    0,   /* quantifier_offset */\n    offsetof(GossipListenMessage, nonce),\n    NULL,\n    NULL,\n    0,             /* flags */\n    0,NULL,NULL    /* reserved1,reserved2, etc */\n  },\n};\nstatic const unsigned gossip_listen_message__field_indices_by_name[] = {\n  0,   /* field[0] = node_state */\n  1,   /* field[1] = nonce */\n};\nstatic const ProtobufCIntRange gossip_listen_message__number_ranges[1 + 1] =\n{\n  { 1, 0 },\n  { 0, 2 }\n};\nconst ProtobufCMessageDescriptor gossip_listen_message__descriptor =\n{\n  PROTOBUF_C__MESSAGE_DESCRIPTOR_MAGIC,\n  \"GossipListenMessage\",\n  \"GossipListenMessage\",\n  \"GossipListenMessage\",\n  \"\",\n  sizeof(GossipListenMessage),\n  2,\n  gossip_listen_message__field_descriptors,\n  gossip_listen_message__field_indices_by_name,\n  1,  gossip_listen_message__number_ranges,\n  (ProtobufCMessageInit) gossip_listen_message__init,\n  NULL,NULL,NULL    /* reserved[123] */\n};\nstatic const ProtobufCFieldDescriptor membership_view_message__field_descriptors[3] =\n{\n  {\n    \"membership\",\n    1,\n    PROTOBUF_C_LABEL_REPEATED,\n    PROTOBUF_C_TYPE_MESSAGE,\n    offsetof(MembershipViewMessage, n_membership),\n    offsetof(MembershipViewMessage, membership),\n    &node_state_message__descriptor,\n    NULL,\n    0,             /* flags */\n    0,NULL,NULL    /* reserved1,reserved2, etc */\n  },\n  {\n    \"client_membership\",\n    2,\n    PROTOBUF_C_LABEL_REPEATED,\n    PROTOBUF_C_TYPE_MESSAGE,\n    offsetof(MembershipViewMessage, n_client_membership),\n    offsetof(MembershipViewMessage, client_membership),\n    &node_state_message__descriptor,\n    NULL,\n    0,             /* flags */\n    0,NULL,NULL    /* reserved1,reserved2, etc */\n  },\n  {\n    \"view_id\",\n    3,\n    PROTOBUF_C_LABEL_REQUIRED,\n    PROTOBUF_C_TYPE_MESSAGE,\n    0,   /* quantifier_offset */\n    offsetof(MembershipViewMessage, view_id),\n    &vector_clock_message__descriptor,\n    NULL,\n    0,             /* flags */\n    0,NULL,NULL    /* reserved1,reserved2, etc */\n  },\n};\nstatic const unsigned membership_view_message__field_indices_by_name[] = {\n  1,   /* field[1] = client_membership */\n  0,   /* field[0] = membership */\n  2,   /* field[2] = view_id */\n};\nstatic const ProtobufCIntRange membership_view_message__number_ranges[1 + 1] =\n{\n  { 1, 0 },\n  { 0, 3 }\n};\nconst ProtobufCMessageDescriptor membership_view_message__descriptor =\n{\n  PROTOBUF_C__MESSAGE_DESCRIPTOR_MAGIC,\n  \"MembershipViewMessage\",\n  \"MembershipViewMessage\",\n  \"MembershipViewMessage\",\n  \"\",\n  sizeof(MembershipViewMessage),\n  3,\n  membership_view_message__field_descriptors,\n  membership_view_message__field_indices_by_name,\n  1,  membership_view_message__number_ranges,\n  (ProtobufCMessageInit) membership_view_message__init,\n  NULL,NULL,NULL    /* reserved[123] */\n};\nstatic const ProtobufCFieldDescriptor membership_agreement_message__field_descriptors[5] =\n{\n  {\n    \"msg_type\",\n    1,\n    PROTOBUF_C_LABEL_REQUIRED,\n    PROTOBUF_C_TYPE_INT32,\n    0,   /* quantifier_offset */\n    offsetof(MembershipAgreementMessage, msg_type),\n    NULL,\n    NULL,\n    0,             /* flags */\n    0,NULL,NULL    /* reserved1,reserved2, etc */\n  },\n  {\n    \"ack_status\",\n    2,\n    PROTOBUF_C_LABEL_REQUIRED,\n    PROTOBUF_C_TYPE_INT32,\n    0,   /* quantifier_offset */\n    offsetof(MembershipAgreementMessage, ack_status),\n    NULL,\n    NULL,\n    0,             /* flags */\n    0,NULL,NULL    /* reserved1,reserved2, etc */\n  },\n  {\n    \"view\",\n    3,\n    PROTOBUF_C_LABEL_OPTIONAL,\n    PROTOBUF_C_TYPE_MESSAGE,\n    0,   /* quantifier_offset */\n    offsetof(MembershipAgreementMessage, view),\n    &membership_view_message__descriptor,\n    NULL,\n    0,             /* flags */\n    0,NULL,NULL    /* reserved1,reserved2, etc */\n  },\n  {\n    \"nonce\",\n    4,\n    PROTOBUF_C_LABEL_REQUIRED,\n    PROTOBUF_C_TYPE_INT64,\n    0,   /* quantifier_offset */\n    offsetof(MembershipAgreementMessage, nonce),\n    NULL,\n    NULL,\n    0,             /* flags */\n    0,NULL,NULL    /* reserved1,reserved2, etc */\n  },\n  {\n    \"vc\",\n    5,\n    PROTOBUF_C_LABEL_REQUIRED,\n    PROTOBUF_C_TYPE_MESSAGE,\n    0,   /* quantifier_offset */\n    offsetof(MembershipAgreementMessage, vc),\n    &vector_clock_message__descriptor,\n    NULL,\n    0,             /* flags */\n    0,NULL,NULL    /* reserved1,reserved2, etc */\n  },\n};\nstatic const unsigned membership_agreement_message__field_indices_by_name[] = {\n  1,   /* field[1] = ack_status */\n  0,   /* field[0] = msg_type */\n  3,   /* field[3] = nonce */\n  4,   /* field[4] = vc */\n  2,   /* field[2] = view */\n};\nstatic const ProtobufCIntRange membership_agreement_message__number_ranges[1 + 1] =\n{\n  { 1, 0 },\n  { 0, 5 }\n};\nconst ProtobufCMessageDescriptor membership_agreement_message__descriptor =\n{\n  PROTOBUF_C__MESSAGE_DESCRIPTOR_MAGIC,\n  \"MembershipAgreementMessage\",\n  \"MembershipAgreementMessage\",\n  \"MembershipAgreementMessage\",\n  \"\",\n  sizeof(MembershipAgreementMessage),\n  5,\n  membership_agreement_message__field_descriptors,\n  membership_agreement_message__field_indices_by_name,\n  1,  membership_agreement_message__number_ranges,\n  (ProtobufCMessageInit) membership_agreement_message__init,\n  NULL,NULL,NULL    /* reserved[123] */\n};\nstatic const ProtobufCFieldDescriptor cell_address_message__field_descriptors[2] =\n{\n  {\n    \"table_key\",\n    1,\n    PROTOBUF_C_LABEL_REQUIRED,\n    PROTOBUF_C_TYPE_INT64,\n    0,   /* quantifier_offset */\n    offsetof(CellAddressMessage, table_key),\n    NULL,\n    NULL,\n    0,             /* flags */\n    0,NULL,NULL    /* reserved1,reserved2, etc */\n  },\n  {\n    \"keys\",\n    2,\n    PROTOBUF_C_LABEL_REPEATED,\n    PROTOBUF_C_TYPE_INT64,\n    offsetof(CellAddressMessage, n_keys),\n    offsetof(CellAddressMessage, keys),\n    NULL,\n    NULL,\n    0,             /* flags */\n    0,NULL,NULL    /* reserved1,reserved2, etc */\n  },\n};\nstatic const unsigned cell_address_message__field_indices_by_name[] = {\n  1,   /* field[1] = keys */\n  0,   /* field[0] = table_key */\n};\nstatic const ProtobufCIntRange cell_address_message__number_ranges[1 + 1] =\n{\n  { 1, 0 },\n  { 0, 2 }\n};\nconst ProtobufCMessageDescriptor cell_address_message__descriptor =\n{\n  PROTOBUF_C__MESSAGE_DESCRIPTOR_MAGIC,\n  \"CellAddressMessage\",\n  \"CellAddressMessage\",\n  \"CellAddressMessage\",\n  \"\",\n  sizeof(CellAddressMessage),\n  2,\n  cell_address_message__field_descriptors,\n  cell_address_message__field_indices_by_name,\n  1,  cell_address_message__number_ranges,\n  (ProtobufCMessageInit) cell_address_message__init,\n  NULL,NULL,NULL    /* reserved[123] */\n};\nstatic const ProtobufCFieldDescriptor cell_message__field_descriptors[3] =\n{\n  {\n    \"table_key\",\n    1,\n    PROTOBUF_C_LABEL_REQUIRED,\n    PROTOBUF_C_TYPE_INT64,\n    0,   /* quantifier_offset */\n    offsetof(CellMessage, table_key),\n    NULL,\n    NULL,\n    0,             /* flags */\n    0,NULL,NULL    /* reserved1,reserved2, etc */\n  },\n  {\n    \"keys\",\n    2,\n    PROTOBUF_C_LABEL_REPEATED,\n    PROTOBUF_C_TYPE_INT64,\n    offsetof(CellMessage, n_keys),\n    offsetof(CellMessage, keys),\n    NULL,\n    NULL,\n    0,             /* flags */\n    0,NULL,NULL    /* reserved1,reserved2, etc */\n  },\n  {\n    \"columns\",\n    3,\n    PROTOBUF_C_LABEL_REPEATED,\n    PROTOBUF_C_TYPE_INT64,\n    offsetof(CellMessage, n_columns),\n    offsetof(CellMessage, columns),\n    NULL,\n    NULL,\n    0,             /* flags */\n    0,NULL,NULL    /* reserved1,reserved2, etc */\n  },\n};\nstatic const unsigned cell_message__field_indices_by_name[] = {\n  2,   /* field[2] = columns */\n  1,   /* field[1] = keys */\n  0,   /* field[0] = table_key */\n};\nstatic const ProtobufCIntRange cell_message__number_ranges[1 + 1] =\n{\n  { 1, 0 },\n  { 0, 3 }\n};\nconst ProtobufCMessageDescriptor cell_message__descriptor =\n{\n  PROTOBUF_C__MESSAGE_DESCRIPTOR_MAGIC,\n  \"CellMessage\",\n  \"CellMessage\",\n  \"CellMessage\",\n  \"\",\n  sizeof(CellMessage),\n  3,\n  cell_message__field_descriptors,\n  cell_message__field_indices_by_name,\n  1,  cell_message__number_ranges,\n  (ProtobufCMessageInit) cell_message__init,\n  NULL,NULL,NULL    /* reserved[123] */\n};\nstatic const ProtobufCFieldDescriptor versioned_cell_message__field_descriptors[5] =\n{\n  {\n    \"table_key\",\n    1,\n    PROTOBUF_C_LABEL_REQUIRED,\n    PROTOBUF_C_TYPE_INT64,\n    0,   /* quantifier_offset */\n    offsetof(VersionedCellMessage, table_key),\n    NULL,\n    NULL,\n    0,             /* flags */\n    0,NULL,NULL    /* reserved1,reserved2, etc */\n  },\n  {\n    \"keys\",\n    2,\n    PROTOBUF_C_LABEL_REPEATED,\n    PROTOBUF_C_TYPE_INT64,\n    offsetof(VersionedCellMessage, n_keys),\n    offsetof(VersionedCellMessage, keys),\n    NULL,\n    NULL,\n    0,             /* flags */\n    0,NULL,NULL    /* reserved1,reserved2, etc */\n  },\n  {\n    \"columns\",\n    3,\n    PROTOBUF_C_LABEL_REPEATED,\n    PROTOBUF_C_TYPE_INT64,\n    offsetof(VersionedCellMessage, n_columns),\n    offsetof(VersionedCellMessage, columns),\n    NULL,\n    NULL,\n    0,             /* flags */\n    0,NULL,NULL    /* reserved1,reserved2, etc */\n  },\n  {\n    \"blob\",\n    4,\n    PROTOBUF_C_LABEL_REQUIRED,\n    PROTOBUF_C_TYPE_BYTES,\n    0,   /* quantifier_offset */\n    offsetof(VersionedCellMessage, blob),\n    NULL,\n    NULL,\n    0,             /* flags */\n    0,NULL,NULL    /* reserved1,reserved2, etc */\n  },\n  {\n    \"version\",\n    5,\n    PROTOBUF_C_LABEL_OPTIONAL,\n    PROTOBUF_C_TYPE_MESSAGE,\n    0,   /* quantifier_offset */\n    offsetof(VersionedCellMessage, version),\n    &vector_clock_message__descriptor,\n    NULL,\n    0,             /* flags */\n    0,NULL,NULL    /* reserved1,reserved2, etc */\n  },\n};\nstatic const unsigned versioned_cell_message__field_indices_by_name[] = {\n  3,   /* field[3] = blob */\n  2,   /* field[2] = columns */\n  1,   /* field[1] = keys */\n  0,   /* field[0] = table_key */\n  4,   /* field[4] = version */\n};\nstatic const ProtobufCIntRange versioned_cell_message__number_ranges[1 + 1] =\n{\n  { 1, 0 },\n  { 0, 5 }\n};\nconst ProtobufCMessageDescriptor versioned_cell_message__descriptor =\n{\n  PROTOBUF_C__MESSAGE_DESCRIPTOR_MAGIC,\n  \"VersionedCellMessage\",\n  \"VersionedCellMessage\",\n  \"VersionedCellMessage\",\n  \"\",\n  sizeof(VersionedCellMessage),\n  5,\n  versioned_cell_message__field_descriptors,\n  versioned_cell_message__field_indices_by_name,\n  1,  versioned_cell_message__number_ranges,\n  (ProtobufCMessageInit) versioned_cell_message__init,\n  NULL,NULL,NULL    /* reserved[123] */\n};\nstatic const ProtobufCFieldDescriptor server_message__field_descriptors[8] =\n{\n  {\n    \"mtype\",\n    1,\n    PROTOBUF_C_LABEL_REQUIRED,\n    PROTOBUF_C_TYPE_INT32,\n    0,   /* quantifier_offset */\n    offsetof(ServerMessage, mtype),\n    NULL,\n    NULL,\n    0,             /* flags */\n    0,NULL,NULL    /* reserved1,reserved2, etc */\n  },\n  {\n    \"wm\",\n    2,\n    PROTOBUF_C_LABEL_OPTIONAL,\n    PROTOBUF_C_TYPE_MESSAGE,\n    0,   /* quantifier_offset */\n    offsetof(ServerMessage, wm),\n    &write_query_message__descriptor,\n    NULL,\n    0,             /* flags */\n    0,NULL,NULL    /* reserved1,reserved2, etc */\n  },\n  {\n    \"rm\",\n    3,\n    PROTOBUF_C_LABEL_OPTIONAL,\n    PROTOBUF_C_TYPE_MESSAGE,\n    0,   /* quantifier_offset */\n    offsetof(ServerMessage, rm),\n    &read_query_message__descriptor,\n    NULL,\n    0,             /* flags */\n    0,NULL,NULL    /* reserved1,reserved2, etc */\n  },\n  {\n    \"rrm\",\n    4,\n    PROTOBUF_C_LABEL_OPTIONAL,\n    PROTOBUF_C_TYPE_MESSAGE,\n    0,   /* quantifier_offset */\n    offsetof(ServerMessage, rrm),\n    &range_read_query_message__descriptor,\n    NULL,\n    0,             /* flags */\n    0,NULL,NULL    /* reserved1,reserved2, etc */\n  },\n  {\n    \"qm\",\n    5,\n    PROTOBUF_C_LABEL_OPTIONAL,\n    PROTOBUF_C_TYPE_MESSAGE,\n    0,   /* quantifier_offset */\n    offsetof(ServerMessage, qm),\n    &queue_query_message__descriptor,\n    NULL,\n    0,             /* flags */\n    0,NULL,NULL    /* reserved1,reserved2, etc */\n  },\n  {\n    \"tm\",\n    6,\n    PROTOBUF_C_LABEL_OPTIONAL,\n    PROTOBUF_C_TYPE_MESSAGE,\n    0,   /* quantifier_offset */\n    offsetof(ServerMessage, tm),\n    &txn_message__descriptor,\n    NULL,\n    0,             /* flags */\n    0,NULL,NULL    /* reserved1,reserved2, etc */\n  },\n  {\n    \"gl\",\n    7,\n    PROTOBUF_C_LABEL_OPTIONAL,\n    PROTOBUF_C_TYPE_MESSAGE,\n    0,   /* quantifier_offset */\n    offsetof(ServerMessage, gl),\n    &gossip_listen_message__descriptor,\n    NULL,\n    0,             /* flags */\n    0,NULL,NULL    /* reserved1,reserved2, etc */\n  },\n  {\n    \"vc\",\n    8,\n    PROTOBUF_C_LABEL_OPTIONAL,\n    PROTOBUF_C_TYPE_MESSAGE,\n    0,   /* quantifier_offset */\n    offsetof(ServerMessage, vc),\n    &vector_clock_message__descriptor,\n    NULL,\n    0,             /* flags */\n    0,NULL,NULL    /* reserved1,reserved2, etc */\n  },\n};\nstatic const unsigned server_message__field_indices_by_name[] = {\n  6,   /* field[6] = gl */\n  0,   /* field[0] = mtype */\n  4,   /* field[4] = qm */\n  2,   /* field[2] = rm */\n  3,   /* field[3] = rrm */\n  5,   /* field[5] = tm */\n  7,   /* field[7] = vc */\n  1,   /* field[1] = wm */\n};\nstatic const ProtobufCIntRange server_message__number_ranges[1 + 1] =\n{\n  { 1, 0 },\n  { 0, 8 }\n};\nconst ProtobufCMessageDescriptor server_message__descriptor =\n{\n  PROTOBUF_C__MESSAGE_DESCRIPTOR_MAGIC,\n  \"ServerMessage\",\n  \"ServerMessage\",\n  \"ServerMessage\",\n  \"\",\n  sizeof(ServerMessage),\n  8,\n  server_message__field_descriptors,\n  server_message__field_indices_by_name,\n  1,  server_message__number_ranges,\n  (ProtobufCMessageInit) server_message__init,\n  NULL,NULL,NULL    /* reserved[123] */\n};\nstatic const ProtobufCFieldDescriptor client_message__field_descriptors[7] =\n{\n  {\n    \"mtype\",\n    1,\n    PROTOBUF_C_LABEL_REQUIRED,\n    PROTOBUF_C_TYPE_INT32,\n    0,   /* quantifier_offset */\n    offsetof(ClientMessage, mtype),\n    NULL,\n    NULL,\n    0,             /* flags */\n    0,NULL,NULL    /* reserved1,reserved2, etc */\n  },\n  {\n    \"am\",\n    2,\n    PROTOBUF_C_LABEL_OPTIONAL,\n    PROTOBUF_C_TYPE_MESSAGE,\n    0,   /* quantifier_offset */\n    offsetof(ClientMessage, am),\n    &ack_message__descriptor,\n    NULL,\n    0,             /* flags */\n    0,NULL,NULL    /* reserved1,reserved2, etc */\n  },\n  {\n    \"wm\",\n    3,\n    PROTOBUF_C_LABEL_OPTIONAL,\n    PROTOBUF_C_TYPE_MESSAGE,\n    0,   /* quantifier_offset */\n    offsetof(ClientMessage, wm),\n    &write_query_message__descriptor,\n    NULL,\n    0,             /* flags */\n    0,NULL,NULL    /* reserved1,reserved2, etc */\n  },\n  {\n    \"rrrm\",\n    4,\n    PROTOBUF_C_LABEL_OPTIONAL,\n    PROTOBUF_C_TYPE_MESSAGE,\n    0,   /* quantifier_offset */\n    offsetof(ClientMessage, rrrm),\n    &range_read_response_message__descriptor,\n    NULL,\n    0,             /* flags */\n    0,NULL,NULL    /* reserved1,reserved2, etc */\n  },\n  {\n    \"qm\",\n    5,\n    PROTOBUF_C_LABEL_OPTIONAL,\n    PROTOBUF_C_TYPE_MESSAGE,\n    0,   /* quantifier_offset */\n    offsetof(ClientMessage, qm),\n    &queue_query_message__descriptor,\n    NULL,\n    0,             /* flags */\n    0,NULL,NULL    /* reserved1,reserved2, etc */\n  },\n  {\n    \"tm\",\n    6,\n    PROTOBUF_C_LABEL_OPTIONAL,\n    PROTOBUF_C_TYPE_MESSAGE,\n    0,   /* quantifier_offset */\n    offsetof(ClientMessage, tm),\n    &txn_message__descriptor,\n    NULL,\n    0,             /* flags */\n    0,NULL,NULL    /* reserved1,reserved2, etc */\n  },\n  {\n    \"vc\",\n    7,\n    PROTOBUF_C_LABEL_OPTIONAL,\n    PROTOBUF_C_TYPE_MESSAGE,\n    0,   /* quantifier_offset */\n    offsetof(ClientMessage, vc),\n    &vector_clock_message__descriptor,\n    NULL,\n    0,             /* flags */\n    0,NULL,NULL    /* reserved1,reserved2, etc */\n  },\n};\nstatic const unsigned client_message__field_indices_by_name[] = {\n  1,   /* field[1] = am */\n  0,   /* field[0] = mtype */\n  4,   /* field[4] = qm */\n  3,   /* field[3] = rrrm */\n  5,   /* field[5] = tm */\n  6,   /* field[6] = vc */\n  2,   /* field[2] = wm */\n};\nstatic const ProtobufCIntRange client_message__number_ranges[1 + 1] =\n{\n  { 1, 0 },\n  { 0, 7 }\n};\nconst ProtobufCMessageDescriptor client_message__descriptor =\n{\n  PROTOBUF_C__MESSAGE_DESCRIPTOR_MAGIC,\n  \"ClientMessage\",\n  \"ClientMessage\",\n  \"ClientMessage\",\n  \"\",\n  sizeof(ClientMessage),\n  7,\n  client_message__field_descriptors,\n  client_message__field_indices_by_name,\n  1,  client_message__number_ranges,\n  (ProtobufCMessageInit) client_message__init,\n  NULL,NULL,NULL    /* reserved[123] */\n};\nstatic const ProtobufCFieldDescriptor write_query_message__field_descriptors[5] =\n{\n  {\n    \"cell\",\n    1,\n    PROTOBUF_C_LABEL_OPTIONAL,\n    PROTOBUF_C_TYPE_MESSAGE,\n    0,   /* quantifier_offset */\n    offsetof(WriteQueryMessage, cell),\n    &versioned_cell_message__descriptor,\n    NULL,\n    0,             /* flags */\n    0,NULL,NULL    /* reserved1,reserved2, etc */\n  },\n  {\n    \"txnid\",\n    2,\n    PROTOBUF_C_LABEL_REQUIRED,\n    PROTOBUF_C_TYPE_BYTES,\n    0,   /* quantifier_offset */\n    offsetof(WriteQueryMessage, txnid),\n    NULL,\n    NULL,\n    0,             /* flags */\n    0,NULL,NULL    /* reserved1,reserved2, etc */\n  },\n  {\n    \"nonce\",\n    3,\n    PROTOBUF_C_LABEL_REQUIRED,\n    PROTOBUF_C_TYPE_INT64,\n    0,   /* quantifier_offset */\n    offsetof(WriteQueryMessage, nonce),\n    NULL,\n    NULL,\n    0,             /* flags */\n    0,NULL,NULL    /* reserved1,reserved2, etc */\n  },\n  {\n    \"msg_type\",\n    4,\n    PROTOBUF_C_LABEL_REQUIRED,\n    PROTOBUF_C_TYPE_INT32,\n    0,   /* quantifier_offset */\n    offsetof(WriteQueryMessage, msg_type),\n    NULL,\n    NULL,\n    0,             /* flags */\n    0,NULL,NULL    /* reserved1,reserved2, etc */\n  },\n  {\n    \"mtype\",\n    5,\n    PROTOBUF_C_LABEL_REQUIRED,\n    PROTOBUF_C_TYPE_INT32,\n    0,   /* quantifier_offset */\n    offsetof(WriteQueryMessage, mtype),\n    NULL,\n    NULL,\n    0,             /* flags */\n    0,NULL,NULL    /* reserved1,reserved2, etc */\n  },\n};\nstatic const unsigned write_query_message__field_indices_by_name[] = {\n  0,   /* field[0] = cell */\n  3,   /* field[3] = msg_type */\n  4,   /* field[4] = mtype */\n  2,   /* field[2] = nonce */\n  1,   /* field[1] = txnid */\n};\nstatic const ProtobufCIntRange write_query_message__number_ranges[1 + 1] =\n{\n  { 1, 0 },\n  { 0, 5 }\n};\nconst ProtobufCMessageDescriptor write_query_message__descriptor =\n{\n  PROTOBUF_C__MESSAGE_DESCRIPTOR_MAGIC,\n  \"WriteQueryMessage\",\n  \"WriteQueryMessage\",\n  \"WriteQueryMessage\",\n  \"\",\n  sizeof(WriteQueryMessage),\n  5,\n  write_query_message__field_descriptors,\n  write_query_message__field_indices_by_name,\n  1,  write_query_message__number_ranges,\n  (ProtobufCMessageInit) write_query_message__init,\n  NULL,NULL,NULL    /* reserved[123] */\n};\nstatic const ProtobufCFieldDescriptor read_query_message__field_descriptors[4] =\n{\n  {\n    \"cell_address\",\n    1,\n    PROTOBUF_C_LABEL_REQUIRED,\n    PROTOBUF_C_TYPE_MESSAGE,\n    0,   /* quantifier_offset */\n    offsetof(ReadQueryMessage, cell_address),\n    &cell_address_message__descriptor,\n    NULL,\n    0,             /* flags */\n    0,NULL,NULL    /* reserved1,reserved2, etc */\n  },\n  {\n    \"txnid\",\n    2,\n    PROTOBUF_C_LABEL_REQUIRED,\n    PROTOBUF_C_TYPE_BYTES,\n    0,   /* quantifier_offset */\n    offsetof(ReadQueryMessage, txnid),\n    NULL,\n    NULL,\n    0,             /* flags */\n    0,NULL,NULL    /* reserved1,reserved2, etc */\n  },\n  {\n    \"nonce\",\n    3,\n    PROTOBUF_C_LABEL_REQUIRED,\n    PROTOBUF_C_TYPE_INT64,\n    0,   /* quantifier_offset */\n    offsetof(ReadQueryMessage, nonce),\n    NULL,\n    NULL,\n    0,             /* flags */\n    0,NULL,NULL    /* reserved1,reserved2, etc */\n  },\n  {\n    \"mtype\",\n    4,\n    PROTOBUF_C_LABEL_REQUIRED,\n    PROTOBUF_C_TYPE_INT32,\n    0,   /* quantifier_offset */\n    offsetof(ReadQueryMessage, mtype),\n    NULL,\n    NULL,\n    0,             /* flags */\n    0,NULL,NULL    /* reserved1,reserved2, etc */\n  },\n};\nstatic const unsigned read_query_message__field_indices_by_name[] = {\n  0,   /* field[0] = cell_address */\n  3,   /* field[3] = mtype */\n  2,   /* field[2] = nonce */\n  1,   /* field[1] = txnid */\n};\nstatic const ProtobufCIntRange read_query_message__number_ranges[1 + 1] =\n{\n  { 1, 0 },\n  { 0, 4 }\n};\nconst ProtobufCMessageDescriptor read_query_message__descriptor =\n{\n  PROTOBUF_C__MESSAGE_DESCRIPTOR_MAGIC,\n  \"ReadQueryMessage\",\n  \"ReadQueryMessage\",\n  \"ReadQueryMessage\",\n  \"\",\n  sizeof(ReadQueryMessage),\n  4,\n  read_query_message__field_descriptors,\n  read_query_message__field_indices_by_name,\n  1,  read_query_message__number_ranges,\n  (ProtobufCMessageInit) read_query_message__init,\n  NULL,NULL,NULL    /* reserved[123] */\n};\nstatic const ProtobufCFieldDescriptor ack_message__field_descriptors[5] =\n{\n  {\n    \"cell_address\",\n    1,\n    PROTOBUF_C_LABEL_OPTIONAL,\n    PROTOBUF_C_TYPE_MESSAGE,\n    0,   /* quantifier_offset */\n    offsetof(AckMessage, cell_address),\n    &cell_address_message__descriptor,\n    NULL,\n    0,             /* flags */\n    0,NULL,NULL    /* reserved1,reserved2, etc */\n  },\n  {\n    \"status\",\n    2,\n    PROTOBUF_C_LABEL_REQUIRED,\n    PROTOBUF_C_TYPE_INT32,\n    0,   /* quantifier_offset */\n    offsetof(AckMessage, status),\n    NULL,\n    NULL,\n    0,             /* flags */\n    0,NULL,NULL    /* reserved1,reserved2, etc */\n  },\n  {\n    \"txnid\",\n    3,\n    PROTOBUF_C_LABEL_REQUIRED,\n    PROTOBUF_C_TYPE_BYTES,\n    0,   /* quantifier_offset */\n    offsetof(AckMessage, txnid),\n    NULL,\n    NULL,\n    0,             /* flags */\n    0,NULL,NULL    /* reserved1,reserved2, etc */\n  },\n  {\n    \"nonce\",\n    4,\n    PROTOBUF_C_LABEL_REQUIRED,\n    PROTOBUF_C_TYPE_INT64,\n    0,   /* quantifier_offset */\n    offsetof(AckMessage, nonce),\n    NULL,\n    NULL,\n    0,             /* flags */\n    0,NULL,NULL    /* reserved1,reserved2, etc */\n  },\n  {\n    \"mtype\",\n    5,\n    PROTOBUF_C_LABEL_REQUIRED,\n    PROTOBUF_C_TYPE_INT32,\n    0,   /* quantifier_offset */\n    offsetof(AckMessage, mtype),\n    NULL,\n    NULL,\n    0,             /* flags */\n    0,NULL,NULL    /* reserved1,reserved2, etc */\n  },\n};\nstatic const unsigned ack_message__field_indices_by_name[] = {\n  0,   /* field[0] = cell_address */\n  4,   /* field[4] = mtype */\n  3,   /* field[3] = nonce */\n  1,   /* field[1] = status */\n  2,   /* field[2] = txnid */\n};\nstatic const ProtobufCIntRange ack_message__number_ranges[1 + 1] =\n{\n  { 1, 0 },\n  { 0, 5 }\n};\nconst ProtobufCMessageDescriptor ack_message__descriptor =\n{\n  PROTOBUF_C__MESSAGE_DESCRIPTOR_MAGIC,\n  \"AckMessage\",\n  \"AckMessage\",\n  \"AckMessage\",\n  \"\",\n  sizeof(AckMessage),\n  5,\n  ack_message__field_descriptors,\n  ack_message__field_indices_by_name,\n  1,  ack_message__number_ranges,\n  (ProtobufCMessageInit) ack_message__init,\n  NULL,NULL,NULL    /* reserved[123] */\n};\nstatic const ProtobufCFieldDescriptor range_read_query_message__field_descriptors[5] =\n{\n  {\n    \"start_cell_address\",\n    1,\n    PROTOBUF_C_LABEL_REQUIRED,\n    PROTOBUF_C_TYPE_MESSAGE,\n    0,   /* quantifier_offset */\n    offsetof(RangeReadQueryMessage, start_cell_address),\n    &cell_address_message__descriptor,\n    NULL,\n    0,             /* flags */\n    0,NULL,NULL    /* reserved1,reserved2, etc */\n  },\n  {\n    \"end_cell_address\",\n    2,\n    PROTOBUF_C_LABEL_REQUIRED,\n    PROTOBUF_C_TYPE_MESSAGE,\n    0,   /* quantifier_offset */\n    offsetof(RangeReadQueryMessage, end_cell_address),\n    &cell_address_message__descriptor,\n    NULL,\n    0,             /* flags */\n    0,NULL,NULL    /* reserved1,reserved2, etc */\n  },\n  {\n    \"txnid\",\n    3,\n    PROTOBUF_C_LABEL_REQUIRED,\n    PROTOBUF_C_TYPE_BYTES,\n    0,   /* quantifier_offset */\n    offsetof(RangeReadQueryMessage, txnid),\n    NULL,\n    NULL,\n    0,             /* flags */\n    0,NULL,NULL    /* reserved1,reserved2, etc */\n  },\n  {\n    \"nonce\",\n    4,\n    PROTOBUF_C_LABEL_REQUIRED,\n    PROTOBUF_C_TYPE_INT64,\n    0,   /* quantifier_offset */\n    offsetof(RangeReadQueryMessage, nonce),\n    NULL,\n    NULL,\n    0,             /* flags */\n    0,NULL,NULL    /* reserved1,reserved2, etc */\n  },\n  {\n    \"mtype\",\n    5,\n    PROTOBUF_C_LABEL_REQUIRED,\n    PROTOBUF_C_TYPE_INT32,\n    0,   /* quantifier_offset */\n    offsetof(RangeReadQueryMessage, mtype),\n    NULL,\n    NULL,\n    0,             /* flags */\n    0,NULL,NULL    /* reserved1,reserved2, etc */\n  },\n};\nstatic const unsigned range_read_query_message__field_indices_by_name[] = {\n  1,   /* field[1] = end_cell_address */\n  4,   /* field[4] = mtype */\n  3,   /* field[3] = nonce */\n  0,   /* field[0] = start_cell_address */\n  2,   /* field[2] = txnid */\n};\nstatic const ProtobufCIntRange range_read_query_message__number_ranges[1 + 1] =\n{\n  { 1, 0 },\n  { 0, 5 }\n};\nconst ProtobufCMessageDescriptor range_read_query_message__descriptor =\n{\n  PROTOBUF_C__MESSAGE_DESCRIPTOR_MAGIC,\n  \"RangeReadQueryMessage\",\n  \"RangeReadQueryMessage\",\n  \"RangeReadQueryMessage\",\n  \"\",\n  sizeof(RangeReadQueryMessage),\n  5,\n  range_read_query_message__field_descriptors,\n  range_read_query_message__field_indices_by_name,\n  1,  range_read_query_message__number_ranges,\n  (ProtobufCMessageInit) range_read_query_message__init,\n  NULL,NULL,NULL    /* reserved[123] */\n};\nstatic const ProtobufCFieldDescriptor range_read_response_message__field_descriptors[4] =\n{\n  {\n    \"cells\",\n    1,\n    PROTOBUF_C_LABEL_REPEATED,\n    PROTOBUF_C_TYPE_MESSAGE,\n    offsetof(RangeReadResponseMessage, n_cells),\n    offsetof(RangeReadResponseMessage, cells),\n    &versioned_cell_message__descriptor,\n    NULL,\n    0,             /* flags */\n    0,NULL,NULL    /* reserved1,reserved2, etc */\n  },\n  {\n    \"txnid\",\n    2,\n    PROTOBUF_C_LABEL_REQUIRED,\n    PROTOBUF_C_TYPE_BYTES,\n    0,   /* quantifier_offset */\n    offsetof(RangeReadResponseMessage, txnid),\n    NULL,\n    NULL,\n    0,             /* flags */\n    0,NULL,NULL    /* reserved1,reserved2, etc */\n  },\n  {\n    \"nonce\",\n    3,\n    PROTOBUF_C_LABEL_REQUIRED,\n    PROTOBUF_C_TYPE_INT64,\n    0,   /* quantifier_offset */\n    offsetof(RangeReadResponseMessage, nonce),\n    NULL,\n    NULL,\n    0,             /* flags */\n    0,NULL,NULL    /* reserved1,reserved2, etc */\n  },\n  {\n    \"mtype\",\n    4,\n    PROTOBUF_C_LABEL_REQUIRED,\n    PROTOBUF_C_TYPE_INT32,\n    0,   /* quantifier_offset */\n    offsetof(RangeReadResponseMessage, mtype),\n    NULL,\n    NULL,\n    0,             /* flags */\n    0,NULL,NULL    /* reserved1,reserved2, etc */\n  },\n};\nstatic const unsigned range_read_response_message__field_indices_by_name[] = {\n  0,   /* field[0] = cells */\n  3,   /* field[3] = mtype */\n  2,   /* field[2] = nonce */\n  1,   /* field[1] = txnid */\n};\nstatic const ProtobufCIntRange range_read_response_message__number_ranges[1 + 1] =\n{\n  { 1, 0 },\n  { 0, 4 }\n};\nconst ProtobufCMessageDescriptor range_read_response_message__descriptor =\n{\n  PROTOBUF_C__MESSAGE_DESCRIPTOR_MAGIC,\n  \"RangeReadResponseMessage\",\n  \"RangeReadResponseMessage\",\n  \"RangeReadResponseMessage\",\n  \"\",\n  sizeof(RangeReadResponseMessage),\n  4,\n  range_read_response_message__field_descriptors,\n  range_read_response_message__field_indices_by_name,\n  1,  range_read_response_message__number_ranges,\n  (ProtobufCMessageInit) range_read_response_message__init,\n  NULL,NULL,NULL    /* reserved[123] */\n};\nstatic const ProtobufCFieldDescriptor txn_message__field_descriptors[9] =\n{\n  {\n    \"type\",\n    1,\n    PROTOBUF_C_LABEL_REQUIRED,\n    PROTOBUF_C_TYPE_INT32,\n    0,   /* quantifier_offset */\n    offsetof(TxnMessage, type),\n    NULL,\n    NULL,\n    0,             /* flags */\n    0,NULL,NULL    /* reserved1,reserved2, etc */\n  },\n  {\n    \"own_read_set\",\n    2,\n    PROTOBUF_C_LABEL_REPEATED,\n    PROTOBUF_C_TYPE_MESSAGE,\n    offsetof(TxnMessage, n_own_read_set),\n    offsetof(TxnMessage, own_read_set),\n    &versioned_cell_message__descriptor,\n    NULL,\n    0,             /* flags */\n    0,NULL,NULL    /* reserved1,reserved2, etc */\n  },\n  {\n    \"own_write_set\",\n    3,\n    PROTOBUF_C_LABEL_REPEATED,\n    PROTOBUF_C_TYPE_MESSAGE,\n    offsetof(TxnMessage, n_own_write_set),\n    offsetof(TxnMessage, own_write_set),\n    &versioned_cell_message__descriptor,\n    NULL,\n    0,             /* flags */\n    0,NULL,NULL    /* reserved1,reserved2, etc */\n  },\n  {\n    \"complete_read_set\",\n    4,\n    PROTOBUF_C_LABEL_REPEATED,\n    PROTOBUF_C_TYPE_MESSAGE,\n    offsetof(TxnMessage, n_complete_read_set),\n    offsetof(TxnMessage, complete_read_set),\n    &versioned_cell_message__descriptor,\n    NULL,\n    0,             /* flags */\n    0,NULL,NULL    /* reserved1,reserved2, etc */\n  },\n  {\n    \"complete_write_set\",\n    5,\n    PROTOBUF_C_LABEL_REPEATED,\n    PROTOBUF_C_TYPE_MESSAGE,\n    offsetof(TxnMessage, n_complete_write_set),\n    offsetof(TxnMessage, complete_write_set),\n    &versioned_cell_message__descriptor,\n    NULL,\n    0,             /* flags */\n    0,NULL,NULL    /* reserved1,reserved2, etc */\n  },\n  {\n    \"txnid\",\n    6,\n    PROTOBUF_C_LABEL_REQUIRED,\n    PROTOBUF_C_TYPE_BYTES,\n    0,   /* quantifier_offset */\n    offsetof(TxnMessage, txnid),\n    NULL,\n    NULL,\n    0,             /* flags */\n    0,NULL,NULL    /* reserved1,reserved2, etc */\n  },\n  {\n    \"nonce\",\n    7,\n    PROTOBUF_C_LABEL_REQUIRED,\n    PROTOBUF_C_TYPE_INT64,\n    0,   /* quantifier_offset */\n    offsetof(TxnMessage, nonce),\n    NULL,\n    NULL,\n    0,             /* flags */\n    0,NULL,NULL    /* reserved1,reserved2, etc */\n  },\n  {\n    \"version\",\n    8,\n    PROTOBUF_C_LABEL_OPTIONAL,\n    PROTOBUF_C_TYPE_MESSAGE,\n    0,   /* quantifier_offset */\n    offsetof(TxnMessage, version),\n    &vector_clock_message__descriptor,\n    NULL,\n    0,             /* flags */\n    0,NULL,NULL    /* reserved1,reserved2, etc */\n  },\n  {\n    \"mtype\",\n    9,\n    PROTOBUF_C_LABEL_REQUIRED,\n    PROTOBUF_C_TYPE_INT32,\n    0,   /* quantifier_offset */\n    offsetof(TxnMessage, mtype),\n    NULL,\n    NULL,\n    0,             /* flags */\n    0,NULL,NULL    /* reserved1,reserved2, etc */\n  },\n};\nstatic const unsigned txn_message__field_indices_by_name[] = {\n  3,   /* field[3] = complete_read_set */\n  4,   /* field[4] = complete_write_set */\n  8,   /* field[8] = mtype */\n  6,   /* field[6] = nonce */\n  1,   /* field[1] = own_read_set */\n  2,   /* field[2] = own_write_set */\n  5,   /* field[5] = txnid */\n  0,   /* field[0] = type */\n  7,   /* field[7] = version */\n};\nstatic const ProtobufCIntRange txn_message__number_ranges[1 + 1] =\n{\n  { 1, 0 },\n  { 0, 9 }\n};\nconst ProtobufCMessageDescriptor txn_message__descriptor =\n{\n  PROTOBUF_C__MESSAGE_DESCRIPTOR_MAGIC,\n  \"TxnMessage\",\n  \"TxnMessage\",\n  \"TxnMessage\",\n  \"\",\n  sizeof(TxnMessage),\n  9,\n  txn_message__field_descriptors,\n  txn_message__field_indices_by_name,\n  1,  txn_message__number_ranges,\n  (ProtobufCMessageInit) txn_message__init,\n  NULL,NULL,NULL    /* reserved[123] */\n};\nstatic const ProtobufCFieldDescriptor queue_query_message__field_descriptors[12] =\n{\n  {\n    \"queue_address\",\n    1,\n    PROTOBUF_C_LABEL_REQUIRED,\n    PROTOBUF_C_TYPE_MESSAGE,\n    0,   /* quantifier_offset */\n    offsetof(QueueQueryMessage, queue_address),\n    &cell_address_message__descriptor,\n    NULL,\n    0,             /* flags */\n    0,NULL,NULL    /* reserved1,reserved2, etc */\n  },\n  {\n    \"msg_type\",\n    2,\n    PROTOBUF_C_LABEL_REQUIRED,\n    PROTOBUF_C_TYPE_INT32,\n    0,   /* quantifier_offset */\n    offsetof(QueueQueryMessage, msg_type),\n    NULL,\n    NULL,\n    0,             /* flags */\n    0,NULL,NULL    /* reserved1,reserved2, etc */\n  },\n  {\n    \"app_id\",\n    3,\n    PROTOBUF_C_LABEL_REQUIRED,\n    PROTOBUF_C_TYPE_INT32,\n    0,   /* quantifier_offset */\n    offsetof(QueueQueryMessage, app_id),\n    NULL,\n    NULL,\n    0,             /* flags */\n    0,NULL,NULL    /* reserved1,reserved2, etc */\n  },\n  {\n    \"shard_id\",\n    4,\n    PROTOBUF_C_LABEL_REQUIRED,\n    PROTOBUF_C_TYPE_INT32,\n    0,   /* quantifier_offset */\n    offsetof(QueueQueryMessage, shard_id),\n    NULL,\n    NULL,\n    0,             /* flags */\n    0,NULL,NULL    /* reserved1,reserved2, etc */\n  },\n  {\n    \"consumer_id\",\n    5,\n    PROTOBUF_C_LABEL_REQUIRED,\n    PROTOBUF_C_TYPE_INT32,\n    0,   /* quantifier_offset */\n    offsetof(QueueQueryMessage, consumer_id),\n    NULL,\n    NULL,\n    0,             /* flags */\n    0,NULL,NULL    /* reserved1,reserved2, etc */\n  },\n  {\n    \"group_id\",\n    6,\n    PROTOBUF_C_LABEL_REQUIRED,\n    PROTOBUF_C_TYPE_INT32,\n    0,   /* quantifier_offset */\n    offsetof(QueueQueryMessage, group_id),\n    NULL,\n    NULL,\n    0,             /* flags */\n    0,NULL,NULL    /* reserved1,reserved2, etc */\n  },\n  {\n    \"queue_index\",\n    7,\n    PROTOBUF_C_LABEL_REQUIRED,\n    PROTOBUF_C_TYPE_INT32,\n    0,   /* quantifier_offset */\n    offsetof(QueueQueryMessage, queue_index),\n    NULL,\n    NULL,\n    0,             /* flags */\n    0,NULL,NULL    /* reserved1,reserved2, etc */\n  },\n  {\n    \"status\",\n    8,\n    PROTOBUF_C_LABEL_REQUIRED,\n    PROTOBUF_C_TYPE_INT32,\n    0,   /* quantifier_offset */\n    offsetof(QueueQueryMessage, status),\n    NULL,\n    NULL,\n    0,             /* flags */\n    0,NULL,NULL    /* reserved1,reserved2, etc */\n  },\n  {\n    \"cells\",\n    9,\n    PROTOBUF_C_LABEL_REPEATED,\n    PROTOBUF_C_TYPE_MESSAGE,\n    offsetof(QueueQueryMessage, n_cells),\n    offsetof(QueueQueryMessage, cells),\n    &versioned_cell_message__descriptor,\n    NULL,\n    0,             /* flags */\n    0,NULL,NULL    /* reserved1,reserved2, etc */\n  },\n  {\n    \"txnid\",\n    10,\n    PROTOBUF_C_LABEL_REQUIRED,\n    PROTOBUF_C_TYPE_BYTES,\n    0,   /* quantifier_offset */\n    offsetof(QueueQueryMessage, txnid),\n    NULL,\n    NULL,\n    0,             /* flags */\n    0,NULL,NULL    /* reserved1,reserved2, etc */\n  },\n  {\n    \"nonce\",\n    11,\n    PROTOBUF_C_LABEL_REQUIRED,\n    PROTOBUF_C_TYPE_INT64,\n    0,   /* quantifier_offset */\n    offsetof(QueueQueryMessage, nonce),\n    NULL,\n    NULL,\n    0,             /* flags */\n    0,NULL,NULL    /* reserved1,reserved2, etc */\n  },\n  {\n    \"mtype\",\n    12,\n    PROTOBUF_C_LABEL_REQUIRED,\n    PROTOBUF_C_TYPE_INT32,\n    0,   /* quantifier_offset */\n    offsetof(QueueQueryMessage, mtype),\n    NULL,\n    NULL,\n    0,             /* flags */\n    0,NULL,NULL    /* reserved1,reserved2, etc */\n  },\n};\nstatic const unsigned queue_query_message__field_indices_by_name[] = {\n  2,   /* field[2] = app_id */\n  8,   /* field[8] = cells */\n  4,   /* field[4] = consumer_id */\n  5,   /* field[5] = group_id */\n  1,   /* field[1] = msg_type */\n  11,   /* field[11] = mtype */\n  10,   /* field[10] = nonce */\n  0,   /* field[0] = queue_address */\n  6,   /* field[6] = queue_index */\n  3,   /* field[3] = shard_id */\n  7,   /* field[7] = status */\n  9,   /* field[9] = txnid */\n};\nstatic const ProtobufCIntRange queue_query_message__number_ranges[1 + 1] =\n{\n  { 1, 0 },\n  { 0, 12 }\n};\nconst ProtobufCMessageDescriptor queue_query_message__descriptor =\n{\n  PROTOBUF_C__MESSAGE_DESCRIPTOR_MAGIC,\n  \"QueueQueryMessage\",\n  \"QueueQueryMessage\",\n  \"QueueQueryMessage\",\n  \"\",\n  sizeof(QueueQueryMessage),\n  12,\n  queue_query_message__field_descriptors,\n  queue_query_message__field_indices_by_name,\n  1,  queue_query_message__number_ranges,\n  (ProtobufCMessageInit) queue_query_message__init,\n  NULL,NULL,NULL    /* reserved[123] */\n};\nstatic const ProtobufCFieldDescriptor consumer_id__field_descriptors[3] =\n{\n  {\n    \"app_id\",\n    1,\n    PROTOBUF_C_LABEL_REQUIRED,\n    PROTOBUF_C_TYPE_INT32,\n    0,   /* quantifier_offset */\n    offsetof(ConsumerID, app_id),\n    NULL,\n    NULL,\n    0,             /* flags */\n    0,NULL,NULL    /* reserved1,reserved2, etc */\n  },\n  {\n    \"shard_id\",\n    2,\n    PROTOBUF_C_LABEL_REQUIRED,\n    PROTOBUF_C_TYPE_INT32,\n    0,   /* quantifier_offset */\n    offsetof(ConsumerID, shard_id),\n    NULL,\n    NULL,\n    0,             /* flags */\n    0,NULL,NULL    /* reserved1,reserved2, etc */\n  },\n  {\n    \"consumer_id\",\n    3,\n    PROTOBUF_C_LABEL_REQUIRED,\n    PROTOBUF_C_TYPE_INT32,\n    0,   /* quantifier_offset */\n    offsetof(ConsumerID, consumer_id),\n    NULL,\n    NULL,\n    0,             /* flags */\n    0,NULL,NULL    /* reserved1,reserved2, etc */\n  },\n};\nstatic const unsigned consumer_id__field_indices_by_name[] = {\n  0,   /* field[0] = app_id */\n  2,   /* field[2] = consumer_id */\n  1,   /* field[1] = shard_id */\n};\nstatic const ProtobufCIntRange consumer_id__number_ranges[1 + 1] =\n{\n  { 1, 0 },\n  { 0, 3 }\n};\nconst ProtobufCMessageDescriptor consumer_id__descriptor =\n{\n  PROTOBUF_C__MESSAGE_DESCRIPTOR_MAGIC,\n  \"ConsumerID\",\n  \"ConsumerID\",\n  \"ConsumerID\",\n  \"\",\n  sizeof(ConsumerID),\n  3,\n  consumer_id__field_descriptors,\n  consumer_id__field_indices_by_name,\n  1,  consumer_id__number_ranges,\n  (ProtobufCMessageInit) consumer_id__init,\n  NULL,NULL,NULL    /* reserved[123] */\n};\nstatic const ProtobufCFieldDescriptor create_queue_message__field_descriptors[3] =\n{\n  {\n    \"queue_address\",\n    1,\n    PROTOBUF_C_LABEL_REQUIRED,\n    PROTOBUF_C_TYPE_MESSAGE,\n    0,   /* quantifier_offset */\n    offsetof(CreateQueueMessage, queue_address),\n    &cell_address_message__descriptor,\n    NULL,\n    0,             /* flags */\n    0,NULL,NULL    /* reserved1,reserved2, etc */\n  },\n  {\n    \"txnid\",\n    2,\n    PROTOBUF_C_LABEL_REQUIRED,\n    PROTOBUF_C_TYPE_BYTES,\n    0,   /* quantifier_offset */\n    offsetof(CreateQueueMessage, txnid),\n    NULL,\n    NULL,\n    0,             /* flags */\n    0,NULL,NULL    /* reserved1,reserved2, etc */\n  },\n  {\n    \"nonce\",\n    3,\n    PROTOBUF_C_LABEL_REQUIRED,\n    PROTOBUF_C_TYPE_INT64,\n    0,   /* quantifier_offset */\n    offsetof(CreateQueueMessage, nonce),\n    NULL,\n    NULL,\n    0,             /* flags */\n    0,NULL,NULL    /* reserved1,reserved2, etc */\n  },\n};\nstatic const unsigned create_queue_message__field_indices_by_name[] = {\n  2,   /* field[2] = nonce */\n  0,   /* field[0] = queue_address */\n  1,   /* field[1] = txnid */\n};\nstatic const ProtobufCIntRange create_queue_message__number_ranges[1 + 1] =\n{\n  { 1, 0 },\n  { 0, 3 }\n};\nconst ProtobufCMessageDescriptor create_queue_message__descriptor =\n{\n  PROTOBUF_C__MESSAGE_DESCRIPTOR_MAGIC,\n  \"CreateQueueMessage\",\n  \"CreateQueueMessage\",\n  \"CreateQueueMessage\",\n  \"\",\n  sizeof(CreateQueueMessage),\n  3,\n  create_queue_message__field_descriptors,\n  create_queue_message__field_indices_by_name,\n  1,  create_queue_message__number_ranges,\n  (ProtobufCMessageInit) create_queue_message__init,\n  NULL,NULL,NULL    /* reserved[123] */\n};\nstatic const ProtobufCFieldDescriptor delete_queue_message__field_descriptors[3] =\n{\n  {\n    \"queue_address\",\n    1,\n    PROTOBUF_C_LABEL_REQUIRED,\n    PROTOBUF_C_TYPE_MESSAGE,\n    0,   /* quantifier_offset */\n    offsetof(DeleteQueueMessage, queue_address),\n    &cell_address_message__descriptor,\n    NULL,\n    0,             /* flags */\n    0,NULL,NULL    /* reserved1,reserved2, etc */\n  },\n  {\n    \"txnid\",\n    2,\n    PROTOBUF_C_LABEL_REQUIRED,\n    PROTOBUF_C_TYPE_BYTES,\n    0,   /* quantifier_offset */\n    offsetof(DeleteQueueMessage, txnid),\n    NULL,\n    NULL,\n    0,             /* flags */\n    0,NULL,NULL    /* reserved1,reserved2, etc */\n  },\n  {\n    \"nonce\",\n    3,\n    PROTOBUF_C_LABEL_REQUIRED,\n    PROTOBUF_C_TYPE_INT64,\n    0,   /* quantifier_offset */\n    offsetof(DeleteQueueMessage, nonce),\n    NULL,\n    NULL,\n    0,             /* flags */\n    0,NULL,NULL    /* reserved1,reserved2, etc */\n  },\n};\nstatic const unsigned delete_queue_message__field_indices_by_name[] = {\n  2,   /* field[2] = nonce */\n  0,   /* field[0] = queue_address */\n  1,   /* field[1] = txnid */\n};\nstatic const ProtobufCIntRange delete_queue_message__number_ranges[1 + 1] =\n{\n  { 1, 0 },\n  { 0, 3 }\n};\nconst ProtobufCMessageDescriptor delete_queue_message__descriptor =\n{\n  PROTOBUF_C__MESSAGE_DESCRIPTOR_MAGIC,\n  \"DeleteQueueMessage\",\n  \"DeleteQueueMessage\",\n  \"DeleteQueueMessage\",\n  \"\",\n  sizeof(DeleteQueueMessage),\n  3,\n  delete_queue_message__field_descriptors,\n  delete_queue_message__field_indices_by_name,\n  1,  delete_queue_message__number_ranges,\n  (ProtobufCMessageInit) delete_queue_message__init,\n  NULL,NULL,NULL    /* reserved[123] */\n};\nstatic const ProtobufCFieldDescriptor subscribe_queue_message__field_descriptors[4] =\n{\n  {\n    \"queue_address\",\n    1,\n    PROTOBUF_C_LABEL_REQUIRED,\n    PROTOBUF_C_TYPE_MESSAGE,\n    0,   /* quantifier_offset */\n    offsetof(SubscribeQueueMessage, queue_address),\n    &cell_address_message__descriptor,\n    NULL,\n    0,             /* flags */\n    0,NULL,NULL    /* reserved1,reserved2, etc */\n  },\n  {\n    \"consumer_id\",\n    2,\n    PROTOBUF_C_LABEL_REQUIRED,\n    PROTOBUF_C_TYPE_MESSAGE,\n    0,   /* quantifier_offset */\n    offsetof(SubscribeQueueMessage, consumer_id),\n    &consumer_id__descriptor,\n    NULL,\n    0,             /* flags */\n    0,NULL,NULL    /* reserved1,reserved2, etc */\n  },\n  {\n    \"txnid\",\n    3,\n    PROTOBUF_C_LABEL_REQUIRED,\n    PROTOBUF_C_TYPE_BYTES,\n    0,   /* quantifier_offset */\n    offsetof(SubscribeQueueMessage, txnid),\n    NULL,\n    NULL,\n    0,             /* flags */\n    0,NULL,NULL    /* reserved1,reserved2, etc */\n  },\n  {\n    \"nonce\",\n    4,\n    PROTOBUF_C_LABEL_REQUIRED,\n    PROTOBUF_C_TYPE_INT64,\n    0,   /* quantifier_offset */\n    offsetof(SubscribeQueueMessage, nonce),\n    NULL,\n    NULL,\n    0,             /* flags */\n    0,NULL,NULL    /* reserved1,reserved2, etc */\n  },\n};\nstatic const unsigned subscribe_queue_message__field_indices_by_name[] = {\n  1,   /* field[1] = consumer_id */\n  3,   /* field[3] = nonce */\n  0,   /* field[0] = queue_address */\n  2,   /* field[2] = txnid */\n};\nstatic const ProtobufCIntRange subscribe_queue_message__number_ranges[1 + 1] =\n{\n  { 1, 0 },\n  { 0, 4 }\n};\nconst ProtobufCMessageDescriptor subscribe_queue_message__descriptor =\n{\n  PROTOBUF_C__MESSAGE_DESCRIPTOR_MAGIC,\n  \"SubscribeQueueMessage\",\n  \"SubscribeQueueMessage\",\n  \"SubscribeQueueMessage\",\n  \"\",\n  sizeof(SubscribeQueueMessage),\n  4,\n  subscribe_queue_message__field_descriptors,\n  subscribe_queue_message__field_indices_by_name,\n  1,  subscribe_queue_message__number_ranges,\n  (ProtobufCMessageInit) subscribe_queue_message__init,\n  NULL,NULL,NULL    /* reserved[123] */\n};\nstatic const ProtobufCFieldDescriptor unsubscribe_queue_message__field_descriptors[4] =\n{\n  {\n    \"queue_address\",\n    1,\n    PROTOBUF_C_LABEL_REQUIRED,\n    PROTOBUF_C_TYPE_MESSAGE,\n    0,   /* quantifier_offset */\n    offsetof(UnsubscribeQueueMessage, queue_address),\n    &cell_address_message__descriptor,\n    NULL,\n    0,             /* flags */\n    0,NULL,NULL    /* reserved1,reserved2, etc */\n  },\n  {\n    \"consumer_id\",\n    2,\n    PROTOBUF_C_LABEL_REQUIRED,\n    PROTOBUF_C_TYPE_MESSAGE,\n    0,   /* quantifier_offset */\n    offsetof(UnsubscribeQueueMessage, consumer_id),\n    &consumer_id__descriptor,\n    NULL,\n    0,             /* flags */\n    0,NULL,NULL    /* reserved1,reserved2, etc */\n  },\n  {\n    \"txnid\",\n    3,\n    PROTOBUF_C_LABEL_REQUIRED,\n    PROTOBUF_C_TYPE_BYTES,\n    0,   /* quantifier_offset */\n    offsetof(UnsubscribeQueueMessage, txnid),\n    NULL,\n    NULL,\n    0,             /* flags */\n    0,NULL,NULL    /* reserved1,reserved2, etc */\n  },\n  {\n    \"nonce\",\n    4,\n    PROTOBUF_C_LABEL_REQUIRED,\n    PROTOBUF_C_TYPE_INT64,\n    0,   /* quantifier_offset */\n    offsetof(UnsubscribeQueueMessage, nonce),\n    NULL,\n    NULL,\n    0,             /* flags */\n    0,NULL,NULL    /* reserved1,reserved2, etc */\n  },\n};\nstatic const unsigned unsubscribe_queue_message__field_indices_by_name[] = {\n  1,   /* field[1] = consumer_id */\n  3,   /* field[3] = nonce */\n  0,   /* field[0] = queue_address */\n  2,   /* field[2] = txnid */\n};\nstatic const ProtobufCIntRange unsubscribe_queue_message__number_ranges[1 + 1] =\n{\n  { 1, 0 },\n  { 0, 4 }\n};\nconst ProtobufCMessageDescriptor unsubscribe_queue_message__descriptor =\n{\n  PROTOBUF_C__MESSAGE_DESCRIPTOR_MAGIC,\n  \"UnsubscribeQueueMessage\",\n  \"UnsubscribeQueueMessage\",\n  \"UnsubscribeQueueMessage\",\n  \"\",\n  sizeof(UnsubscribeQueueMessage),\n  4,\n  unsubscribe_queue_message__field_descriptors,\n  unsubscribe_queue_message__field_indices_by_name,\n  1,  unsubscribe_queue_message__number_ranges,\n  (ProtobufCMessageInit) unsubscribe_queue_message__init,\n  NULL,NULL,NULL    /* reserved[123] */\n};\nstatic const ProtobufCFieldDescriptor enqueue_message__field_descriptors[3] =\n{\n  {\n    \"cells\",\n    1,\n    PROTOBUF_C_LABEL_REPEATED,\n    PROTOBUF_C_TYPE_MESSAGE,\n    offsetof(EnqueueMessage, n_cells),\n    offsetof(EnqueueMessage, cells),\n    &versioned_cell_message__descriptor,\n    NULL,\n    0,             /* flags */\n    0,NULL,NULL    /* reserved1,reserved2, etc */\n  },\n  {\n    \"txnid\",\n    2,\n    PROTOBUF_C_LABEL_REQUIRED,\n    PROTOBUF_C_TYPE_BYTES,\n    0,   /* quantifier_offset */\n    offsetof(EnqueueMessage, txnid),\n    NULL,\n    NULL,\n    0,             /* flags */\n    0,NULL,NULL    /* reserved1,reserved2, etc */\n  },\n  {\n    \"nonce\",\n    3,\n    PROTOBUF_C_LABEL_REQUIRED,\n    PROTOBUF_C_TYPE_INT64,\n    0,   /* quantifier_offset */\n    offsetof(EnqueueMessage, nonce),\n    NULL,\n    NULL,\n    0,             /* flags */\n    0,NULL,NULL    /* reserved1,reserved2, etc */\n  },\n};\nstatic const unsigned enqueue_message__field_indices_by_name[] = {\n  0,   /* field[0] = cells */\n  2,   /* field[2] = nonce */\n  1,   /* field[1] = txnid */\n};\nstatic const ProtobufCIntRange enqueue_message__number_ranges[1 + 1] =\n{\n  { 1, 0 },\n  { 0, 3 }\n};\nconst ProtobufCMessageDescriptor enqueue_message__descriptor =\n{\n  PROTOBUF_C__MESSAGE_DESCRIPTOR_MAGIC,\n  \"EnqueueMessage\",\n  \"EnqueueMessage\",\n  \"EnqueueMessage\",\n  \"\",\n  sizeof(EnqueueMessage),\n  3,\n  enqueue_message__field_descriptors,\n  enqueue_message__field_indices_by_name,\n  1,  enqueue_message__number_ranges,\n  (ProtobufCMessageInit) enqueue_message__init,\n  NULL,NULL,NULL    /* reserved[123] */\n};\nstatic const ProtobufCFieldDescriptor enqueue_response_message__field_descriptors[4] =\n{\n  {\n    \"queue_address\",\n    1,\n    PROTOBUF_C_LABEL_REQUIRED,\n    PROTOBUF_C_TYPE_MESSAGE,\n    0,   /* quantifier_offset */\n    offsetof(EnqueueResponseMessage, queue_address),\n    &cell_address_message__descriptor,\n    NULL,\n    0,             /* flags */\n    0,NULL,NULL    /* reserved1,reserved2, etc */\n  },\n  {\n    \"last_item_id\",\n    2,\n    PROTOBUF_C_LABEL_REQUIRED,\n    PROTOBUF_C_TYPE_INT64,\n    0,   /* quantifier_offset */\n    offsetof(EnqueueResponseMessage, last_item_id),\n    NULL,\n    NULL,\n    0,             /* flags */\n    0,NULL,NULL    /* reserved1,reserved2, etc */\n  },\n  {\n    \"txnid\",\n    3,\n    PROTOBUF_C_LABEL_REQUIRED,\n    PROTOBUF_C_TYPE_BYTES,\n    0,   /* quantifier_offset */\n    offsetof(EnqueueResponseMessage, txnid),\n    NULL,\n    NULL,\n    0,             /* flags */\n    0,NULL,NULL    /* reserved1,reserved2, etc */\n  },\n  {\n    \"nonce\",\n    4,\n    PROTOBUF_C_LABEL_REQUIRED,\n    PROTOBUF_C_TYPE_INT64,\n    0,   /* quantifier_offset */\n    offsetof(EnqueueResponseMessage, nonce),\n    NULL,\n    NULL,\n    0,             /* flags */\n    0,NULL,NULL    /* reserved1,reserved2, etc */\n  },\n};\nstatic const unsigned enqueue_response_message__field_indices_by_name[] = {\n  1,   /* field[1] = last_item_id */\n  3,   /* field[3] = nonce */\n  0,   /* field[0] = queue_address */\n  2,   /* field[2] = txnid */\n};\nstatic const ProtobufCIntRange enqueue_response_message__number_ranges[1 + 1] =\n{\n  { 1, 0 },\n  { 0, 4 }\n};\nconst ProtobufCMessageDescriptor enqueue_response_message__descriptor =\n{\n  PROTOBUF_C__MESSAGE_DESCRIPTOR_MAGIC,\n  \"EnqueueResponseMessage\",\n  \"EnqueueResponseMessage\",\n  \"EnqueueResponseMessage\",\n  \"\",\n  sizeof(EnqueueResponseMessage),\n  4,\n  enqueue_response_message__field_descriptors,\n  enqueue_response_message__field_indices_by_name,\n  1,  enqueue_response_message__number_ranges,\n  (ProtobufCMessageInit) enqueue_response_message__init,\n  NULL,NULL,NULL    /* reserved[123] */\n};\nstatic const ProtobufCFieldDescriptor read_queue_message__field_descriptors[5] =\n{\n  {\n    \"queue_address\",\n    1,\n    PROTOBUF_C_LABEL_REQUIRED,\n    PROTOBUF_C_TYPE_MESSAGE,\n    0,   /* quantifier_offset */\n    offsetof(ReadQueueMessage, queue_address),\n    &cell_address_message__descriptor,\n    NULL,\n    0,             /* flags */\n    0,NULL,NULL    /* reserved1,reserved2, etc */\n  },\n  {\n    \"consumer_id\",\n    2,\n    PROTOBUF_C_LABEL_REQUIRED,\n    PROTOBUF_C_TYPE_MESSAGE,\n    0,   /* quantifier_offset */\n    offsetof(ReadQueueMessage, consumer_id),\n    &consumer_id__descriptor,\n    NULL,\n    0,             /* flags */\n    0,NULL,NULL    /* reserved1,reserved2, etc */\n  },\n  {\n    \"max_items\",\n    3,\n    PROTOBUF_C_LABEL_REQUIRED,\n    PROTOBUF_C_TYPE_INT64,\n    0,   /* quantifier_offset */\n    offsetof(ReadQueueMessage, max_items),\n    NULL,\n    NULL,\n    0,             /* flags */\n    0,NULL,NULL    /* reserved1,reserved2, etc */\n  },\n  {\n    \"txnid\",\n    4,\n    PROTOBUF_C_LABEL_REQUIRED,\n    PROTOBUF_C_TYPE_BYTES,\n    0,   /* quantifier_offset */\n    offsetof(ReadQueueMessage, txnid),\n    NULL,\n    NULL,\n    0,             /* flags */\n    0,NULL,NULL    /* reserved1,reserved2, etc */\n  },\n  {\n    \"nonce\",\n    5,\n    PROTOBUF_C_LABEL_REQUIRED,\n    PROTOBUF_C_TYPE_INT64,\n    0,   /* quantifier_offset */\n    offsetof(ReadQueueMessage, nonce),\n    NULL,\n    NULL,\n    0,             /* flags */\n    0,NULL,NULL    /* reserved1,reserved2, etc */\n  },\n};\nstatic const unsigned read_queue_message__field_indices_by_name[] = {\n  1,   /* field[1] = consumer_id */\n  2,   /* field[2] = max_items */\n  4,   /* field[4] = nonce */\n  0,   /* field[0] = queue_address */\n  3,   /* field[3] = txnid */\n};\nstatic const ProtobufCIntRange read_queue_message__number_ranges[1 + 1] =\n{\n  { 1, 0 },\n  { 0, 5 }\n};\nconst ProtobufCMessageDescriptor read_queue_message__descriptor =\n{\n  PROTOBUF_C__MESSAGE_DESCRIPTOR_MAGIC,\n  \"ReadQueueMessage\",\n  \"ReadQueueMessage\",\n  \"ReadQueueMessage\",\n  \"\",\n  sizeof(ReadQueueMessage),\n  5,\n  read_queue_message__field_descriptors,\n  read_queue_message__field_indices_by_name,\n  1,  read_queue_message__number_ranges,\n  (ProtobufCMessageInit) read_queue_message__init,\n  NULL,NULL,NULL    /* reserved[123] */\n};\nstatic const ProtobufCFieldDescriptor read_queue_response_message__field_descriptors[4] =\n{\n  {\n    \"queue_entries\",\n    1,\n    PROTOBUF_C_LABEL_REPEATED,\n    PROTOBUF_C_TYPE_MESSAGE,\n    offsetof(ReadQueueResponseMessage, n_queue_entries),\n    offsetof(ReadQueueResponseMessage, queue_entries),\n    &versioned_cell_message__descriptor,\n    NULL,\n    0,             /* flags */\n    0,NULL,NULL    /* reserved1,reserved2, etc */\n  },\n  {\n    \"consumer_id\",\n    2,\n    PROTOBUF_C_LABEL_REQUIRED,\n    PROTOBUF_C_TYPE_MESSAGE,\n    0,   /* quantifier_offset */\n    offsetof(ReadQueueResponseMessage, consumer_id),\n    &consumer_id__descriptor,\n    NULL,\n    0,             /* flags */\n    0,NULL,NULL    /* reserved1,reserved2, etc */\n  },\n  {\n    \"txnid\",\n    3,\n    PROTOBUF_C_LABEL_REQUIRED,\n    PROTOBUF_C_TYPE_BYTES,\n    0,   /* quantifier_offset */\n    offsetof(ReadQueueResponseMessage, txnid),\n    NULL,\n    NULL,\n    0,             /* flags */\n    0,NULL,NULL    /* reserved1,reserved2, etc */\n  },\n  {\n    \"nonce\",\n    4,\n    PROTOBUF_C_LABEL_REQUIRED,\n    PROTOBUF_C_TYPE_INT64,\n    0,   /* quantifier_offset */\n    offsetof(ReadQueueResponseMessage, nonce),\n    NULL,\n    NULL,\n    0,             /* flags */\n    0,NULL,NULL    /* reserved1,reserved2, etc */\n  },\n};\nstatic const unsigned read_queue_response_message__field_indices_by_name[] = {\n  1,   /* field[1] = consumer_id */\n  3,   /* field[3] = nonce */\n  0,   /* field[0] = queue_entries */\n  2,   /* field[2] = txnid */\n};\nstatic const ProtobufCIntRange read_queue_response_message__number_ranges[1 + 1] =\n{\n  { 1, 0 },\n  { 0, 4 }\n};\nconst ProtobufCMessageDescriptor read_queue_response_message__descriptor =\n{\n  PROTOBUF_C__MESSAGE_DESCRIPTOR_MAGIC,\n  \"ReadQueueResponseMessage\",\n  \"ReadQueueResponseMessage\",\n  \"ReadQueueResponseMessage\",\n  \"\",\n  sizeof(ReadQueueResponseMessage),\n  4,\n  read_queue_response_message__field_descriptors,\n  read_queue_response_message__field_indices_by_name,\n  1,  read_queue_response_message__number_ranges,\n  (ProtobufCMessageInit) read_queue_response_message__init,\n  NULL,NULL,NULL    /* reserved[123] */\n};\nstatic const ProtobufCFieldDescriptor consume_queue_message__field_descriptors[5] =\n{\n  {\n    \"queue_address\",\n    1,\n    PROTOBUF_C_LABEL_REQUIRED,\n    PROTOBUF_C_TYPE_MESSAGE,\n    0,   /* quantifier_offset */\n    offsetof(ConsumeQueueMessage, queue_address),\n    &cell_address_message__descriptor,\n    NULL,\n    0,             /* flags */\n    0,NULL,NULL    /* reserved1,reserved2, etc */\n  },\n  {\n    \"consumer_id\",\n    2,\n    PROTOBUF_C_LABEL_REQUIRED,\n    PROTOBUF_C_TYPE_MESSAGE,\n    0,   /* quantifier_offset */\n    offsetof(ConsumeQueueMessage, consumer_id),\n    &consumer_id__descriptor,\n    NULL,\n    0,             /* flags */\n    0,NULL,NULL    /* reserved1,reserved2, etc */\n  },\n  {\n    \"new_consume_head\",\n    3,\n    PROTOBUF_C_LABEL_REQUIRED,\n    PROTOBUF_C_TYPE_INT64,\n    0,   /* quantifier_offset */\n    offsetof(ConsumeQueueMessage, new_consume_head),\n    NULL,\n    NULL,\n    0,             /* flags */\n    0,NULL,NULL    /* reserved1,reserved2, etc */\n  },\n  {\n    \"txnid\",\n    4,\n    PROTOBUF_C_LABEL_REQUIRED,\n    PROTOBUF_C_TYPE_BYTES,\n    0,   /* quantifier_offset */\n    offsetof(ConsumeQueueMessage, txnid),\n    NULL,\n    NULL,\n    0,             /* flags */\n    0,NULL,NULL    /* reserved1,reserved2, etc */\n  },\n  {\n    \"nonce\",\n    5,\n    PROTOBUF_C_LABEL_REQUIRED,\n    PROTOBUF_C_TYPE_INT64,\n    0,   /* quantifier_offset */\n    offsetof(ConsumeQueueMessage, nonce),\n    NULL,\n    NULL,\n    0,             /* flags */\n    0,NULL,NULL    /* reserved1,reserved2, etc */\n  },\n};\nstatic const unsigned consume_queue_message__field_indices_by_name[] = {\n  1,   /* field[1] = consumer_id */\n  2,   /* field[2] = new_consume_head */\n  4,   /* field[4] = nonce */\n  0,   /* field[0] = queue_address */\n  3,   /* field[3] = txnid */\n};\nstatic const ProtobufCIntRange consume_queue_message__number_ranges[1 + 1] =\n{\n  { 1, 0 },\n  { 0, 5 }\n};\nconst ProtobufCMessageDescriptor consume_queue_message__descriptor =\n{\n  PROTOBUF_C__MESSAGE_DESCRIPTOR_MAGIC,\n  \"ConsumeQueueMessage\",\n  \"ConsumeQueueMessage\",\n  \"ConsumeQueueMessage\",\n  \"\",\n  sizeof(ConsumeQueueMessage),\n  5,\n  consume_queue_message__field_descriptors,\n  consume_queue_message__field_indices_by_name,\n  1,  consume_queue_message__number_ranges,\n  (ProtobufCMessageInit) consume_queue_message__init,\n  NULL,NULL,NULL    /* reserved[123] */\n};\nstatic const ProtobufCFieldDescriptor consume_queue_response_message__field_descriptors[6] =\n{\n  {\n    \"queue_address\",\n    1,\n    PROTOBUF_C_LABEL_REQUIRED,\n    PROTOBUF_C_TYPE_MESSAGE,\n    0,   /* quantifier_offset */\n    offsetof(ConsumeQueueResponseMessage, queue_address),\n    &cell_address_message__descriptor,\n    NULL,\n    0,             /* flags */\n    0,NULL,NULL    /* reserved1,reserved2, etc */\n  },\n  {\n    \"consumer_id\",\n    2,\n    PROTOBUF_C_LABEL_REQUIRED,\n    PROTOBUF_C_TYPE_MESSAGE,\n    0,   /* quantifier_offset */\n    offsetof(ConsumeQueueResponseMessage, consumer_id),\n    &consumer_id__descriptor,\n    NULL,\n    0,             /* flags */\n    0,NULL,NULL    /* reserved1,reserved2, etc */\n  },\n  {\n    \"status\",\n    3,\n    PROTOBUF_C_LABEL_REQUIRED,\n    PROTOBUF_C_TYPE_INT32,\n    0,   /* quantifier_offset */\n    offsetof(ConsumeQueueResponseMessage, status),\n    NULL,\n    NULL,\n    0,             /* flags */\n    0,NULL,NULL    /* reserved1,reserved2, etc */\n  },\n  {\n    \"new_consume_head\",\n    4,\n    PROTOBUF_C_LABEL_REQUIRED,\n    PROTOBUF_C_TYPE_INT64,\n    0,   /* quantifier_offset */\n    offsetof(ConsumeQueueResponseMessage, new_consume_head),\n    NULL,\n    NULL,\n    0,             /* flags */\n    0,NULL,NULL    /* reserved1,reserved2, etc */\n  },\n  {\n    \"txnid\",\n    5,\n    PROTOBUF_C_LABEL_REQUIRED,\n    PROTOBUF_C_TYPE_BYTES,\n    0,   /* quantifier_offset */\n    offsetof(ConsumeQueueResponseMessage, txnid),\n    NULL,\n    NULL,\n    0,             /* flags */\n    0,NULL,NULL    /* reserved1,reserved2, etc */\n  },\n  {\n    \"nonce\",\n    6,\n    PROTOBUF_C_LABEL_REQUIRED,\n    PROTOBUF_C_TYPE_INT64,\n    0,   /* quantifier_offset */\n    offsetof(ConsumeQueueResponseMessage, nonce),\n    NULL,\n    NULL,\n    0,             /* flags */\n    0,NULL,NULL    /* reserved1,reserved2, etc */\n  },\n};\nstatic const unsigned consume_queue_response_message__field_indices_by_name[] = {\n  1,   /* field[1] = consumer_id */\n  3,   /* field[3] = new_consume_head */\n  5,   /* field[5] = nonce */\n  0,   /* field[0] = queue_address */\n  2,   /* field[2] = status */\n  4,   /* field[4] = txnid */\n};\nstatic const ProtobufCIntRange consume_queue_response_message__number_ranges[1 + 1] =\n{\n  { 1, 0 },\n  { 0, 6 }\n};\nconst ProtobufCMessageDescriptor consume_queue_response_message__descriptor =\n{\n  PROTOBUF_C__MESSAGE_DESCRIPTOR_MAGIC,\n  \"ConsumeQueueResponseMessage\",\n  \"ConsumeQueueResponseMessage\",\n  \"ConsumeQueueResponseMessage\",\n  \"\",\n  sizeof(ConsumeQueueResponseMessage),\n  6,\n  consume_queue_response_message__field_descriptors,\n  consume_queue_response_message__field_indices_by_name,\n  1,  consume_queue_response_message__number_ranges,\n  (ProtobufCMessageInit) consume_queue_response_message__init,\n  NULL,NULL,NULL    /* reserved[123] */\n};\n"
  },
  {
    "path": "backend/failure_detector/db_messages.pb-c.h",
    "content": "/*\n * Copyright (C) 2019-2021 Deutsche Telekom AG\n *\n * Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:\n *\n * 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.\n *\n * 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.\n *\n * 3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission.\n *\n * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS \"AS IS\" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n */\n\n/* Generated by the protocol buffer compiler.  DO NOT EDIT! */\n/* Generated from: backend/failure_detector/db_messages.proto */\n\n#ifndef PROTOBUF_C_backend_2ffailure_5fdetector_2fdb_5fmessages_2eproto__INCLUDED\n#define PROTOBUF_C_backend_2ffailure_5fdetector_2fdb_5fmessages_2eproto__INCLUDED\n\n#include <protobuf-c/protobuf-c.h>\n\nPROTOBUF_C__BEGIN_DECLS\n\n#if PROTOBUF_C_VERSION_NUMBER < 1000000\n# error This file was generated by a newer version of protoc-c which is incompatible with your libprotobuf-c headers. Please update your headers.\n#elif 1004000 < PROTOBUF_C_MIN_COMPILER_VERSION\n# error This file was generated by an older version of protoc-c which is incompatible with your libprotobuf-c headers. Please regenerate this file with a newer version of protoc-c.\n#endif\n\n\ntypedef struct NodeStateMessage NodeStateMessage;\ntypedef struct VectorClockMessage VectorClockMessage;\ntypedef struct GossipMessage GossipMessage;\ntypedef struct GossipListenMessage GossipListenMessage;\ntypedef struct MembershipViewMessage MembershipViewMessage;\ntypedef struct MembershipAgreementMessage MembershipAgreementMessage;\ntypedef struct CellAddressMessage CellAddressMessage;\ntypedef struct CellMessage CellMessage;\ntypedef struct VersionedCellMessage VersionedCellMessage;\ntypedef struct ServerMessage ServerMessage;\ntypedef struct ClientMessage ClientMessage;\ntypedef struct WriteQueryMessage WriteQueryMessage;\ntypedef struct ReadQueryMessage ReadQueryMessage;\ntypedef struct AckMessage AckMessage;\ntypedef struct RangeReadQueryMessage RangeReadQueryMessage;\ntypedef struct RangeReadResponseMessage RangeReadResponseMessage;\ntypedef struct TxnMessage TxnMessage;\ntypedef struct QueueQueryMessage QueueQueryMessage;\ntypedef struct ConsumerID ConsumerID;\ntypedef struct CreateQueueMessage CreateQueueMessage;\ntypedef struct DeleteQueueMessage DeleteQueueMessage;\ntypedef struct SubscribeQueueMessage SubscribeQueueMessage;\ntypedef struct UnsubscribeQueueMessage UnsubscribeQueueMessage;\ntypedef struct EnqueueMessage EnqueueMessage;\ntypedef struct EnqueueResponseMessage EnqueueResponseMessage;\ntypedef struct ReadQueueMessage ReadQueueMessage;\ntypedef struct ReadQueueResponseMessage ReadQueueResponseMessage;\ntypedef struct ConsumeQueueMessage ConsumeQueueMessage;\ntypedef struct ConsumeQueueResponseMessage ConsumeQueueResponseMessage;\n\n\n/* --- enums --- */\n\n\n/* --- messages --- */\n\nstruct  NodeStateMessage\n{\n  ProtobufCMessage base;\n  /*\n   * 0 - dead, 1 - ready, 2 - alive but not ready\n   */\n  int32_t status;\n  int32_t node_id;\n  ProtobufCBinaryData hostname;\n  int32_t port;\n  int32_t rack_id;\n  int32_t dc_id;\n};\n#define NODE_STATE_MESSAGE__INIT \\\n { PROTOBUF_C_MESSAGE_INIT (&node_state_message__descriptor) \\\n    , 0, 0, {0,NULL}, 0, 0, 0 }\n\n\nstruct  VectorClockMessage\n{\n  ProtobufCMessage base;\n  size_t n_ids;\n  int32_t *ids;\n  size_t n_counters;\n  int64_t *counters;\n};\n#define VECTOR_CLOCK_MESSAGE__INIT \\\n { PROTOBUF_C_MESSAGE_INIT (&vector_clock_message__descriptor) \\\n    , 0,NULL, 0,NULL }\n\n\nstruct  GossipMessage\n{\n  ProtobufCMessage base;\n  NodeStateMessage *node_state;\n  VectorClockMessage *vc;\n};\n#define GOSSIP_MESSAGE__INIT \\\n { PROTOBUF_C_MESSAGE_INIT (&gossip_message__descriptor) \\\n    , NULL, NULL }\n\n\nstruct  GossipListenMessage\n{\n  ProtobufCMessage base;\n  NodeStateMessage *node_state;\n  int64_t nonce;\n};\n#define GOSSIP_LISTEN_MESSAGE__INIT \\\n { PROTOBUF_C_MESSAGE_INIT (&gossip_listen_message__descriptor) \\\n    , NULL, 0 }\n\n\nstruct  MembershipViewMessage\n{\n  ProtobufCMessage base;\n  size_t n_membership;\n  NodeStateMessage **membership;\n  size_t n_client_membership;\n  NodeStateMessage **client_membership;\n  VectorClockMessage *view_id;\n};\n#define MEMBERSHIP_VIEW_MESSAGE__INIT \\\n { PROTOBUF_C_MESSAGE_INIT (&membership_view_message__descriptor) \\\n    , 0,NULL, 0,NULL, NULL }\n\n\nstruct  MembershipAgreementMessage\n{\n  ProtobufCMessage base;\n  /*\n   * 0 - PROPOSE, 1 - RESPONSE, 2 - NOTIFY, 3 - RETRY_LINK, 4 - NOTIFY_ACK\n   */\n  int32_t msg_type;\n  /*\n   * 0 - ACK, 1 - NACK, 2 - UNINIT\n   */\n  int32_t ack_status;\n  MembershipViewMessage *view;\n  int64_t nonce;\n  VectorClockMessage *vc;\n};\n#define MEMBERSHIP_AGREEMENT_MESSAGE__INIT \\\n { PROTOBUF_C_MESSAGE_INIT (&membership_agreement_message__descriptor) \\\n    , 0, 0, NULL, 0, NULL }\n\n\nstruct  CellAddressMessage\n{\n  ProtobufCMessage base;\n  int64_t table_key;\n  size_t n_keys;\n  int64_t *keys;\n};\n#define CELL_ADDRESS_MESSAGE__INIT \\\n { PROTOBUF_C_MESSAGE_INIT (&cell_address_message__descriptor) \\\n    , 0, 0,NULL }\n\n\nstruct  CellMessage\n{\n  ProtobufCMessage base;\n  int64_t table_key;\n  size_t n_keys;\n  int64_t *keys;\n  size_t n_columns;\n  int64_t *columns;\n};\n#define CELL_MESSAGE__INIT \\\n { PROTOBUF_C_MESSAGE_INIT (&cell_message__descriptor) \\\n    , 0, 0,NULL, 0,NULL }\n\n\nstruct  VersionedCellMessage\n{\n  ProtobufCMessage base;\n  int64_t table_key;\n  size_t n_keys;\n  int64_t *keys;\n  size_t n_columns;\n  int64_t *columns;\n  ProtobufCBinaryData blob;\n  /*\n   *    optional int64 version_no=6;\n   */\n  VectorClockMessage *version;\n};\n#define VERSIONED_CELL_MESSAGE__INIT \\\n { PROTOBUF_C_MESSAGE_INIT (&versioned_cell_message__descriptor) \\\n    , 0, 0,NULL, 0,NULL, {0,NULL}, NULL }\n\n\nstruct  ServerMessage\n{\n  ProtobufCMessage base;\n  /*\n   * {RPC_TYPE_WRITE, RPC_TYPE_READ, RPC_TYPE_RANGE_READ, RPC_TYPE_QUEUE, RPC_TYPE_TXN, RPC_TYPE_GOSSIP_LISTEN}\n   */\n  int32_t mtype;\n  WriteQueryMessage *wm;\n  ReadQueryMessage *rm;\n  RangeReadQueryMessage *rrm;\n  QueueQueryMessage *qm;\n  TxnMessage *tm;\n  GossipListenMessage *gl;\n  VectorClockMessage *vc;\n};\n#define SERVER_MESSAGE__INIT \\\n { PROTOBUF_C_MESSAGE_INIT (&server_message__descriptor) \\\n    , 0, NULL, NULL, NULL, NULL, NULL, NULL, NULL }\n\n\nstruct  ClientMessage\n{\n  ProtobufCMessage base;\n  /*\n   * {RPC_TYPE_ACK, RPC_TYPE_WRITE, RPC_TYPE_RANGE_READ_RESPONSE, RPC_TYPE_QUEUE, RPC_TYPE_TXN}\n   */\n  int32_t mtype;\n  AckMessage *am;\n  WriteQueryMessage *wm;\n  RangeReadResponseMessage *rrrm;\n  QueueQueryMessage *qm;\n  TxnMessage *tm;\n  VectorClockMessage *vc;\n};\n#define CLIENT_MESSAGE__INIT \\\n { PROTOBUF_C_MESSAGE_INIT (&client_message__descriptor) \\\n    , 0, NULL, NULL, NULL, NULL, NULL, NULL }\n\n\nstruct  WriteQueryMessage\n{\n  ProtobufCMessage base;\n  /*\n   * CellMessage\n   */\n  VersionedCellMessage *cell;\n  ProtobufCBinaryData txnid;\n  int64_t nonce;\n  /*\n   * {RPC_TYPE_WRITE, RPC_TYPE_DELETE}\n   */\n  int32_t msg_type;\n  int32_t mtype;\n};\n#define WRITE_QUERY_MESSAGE__INIT \\\n { PROTOBUF_C_MESSAGE_INIT (&write_query_message__descriptor) \\\n    , NULL, {0,NULL}, 0, 0, 0 }\n\n\nstruct  ReadQueryMessage\n{\n  ProtobufCMessage base;\n  CellAddressMessage *cell_address;\n  ProtobufCBinaryData txnid;\n  int64_t nonce;\n  int32_t mtype;\n};\n#define READ_QUERY_MESSAGE__INIT \\\n { PROTOBUF_C_MESSAGE_INIT (&read_query_message__descriptor) \\\n    , NULL, {0,NULL}, 0, 0 }\n\n\nstruct  AckMessage\n{\n  ProtobufCMessage base;\n  CellAddressMessage *cell_address;\n  /*\n   * 0 - ACK, 1 - NACK\n   */\n  int32_t status;\n  ProtobufCBinaryData txnid;\n  int64_t nonce;\n  int32_t mtype;\n};\n#define ACK_MESSAGE__INIT \\\n { PROTOBUF_C_MESSAGE_INIT (&ack_message__descriptor) \\\n    , NULL, 0, {0,NULL}, 0, 0 }\n\n\nstruct  RangeReadQueryMessage\n{\n  ProtobufCMessage base;\n  CellAddressMessage *start_cell_address;\n  CellAddressMessage *end_cell_address;\n  ProtobufCBinaryData txnid;\n  int64_t nonce;\n  int32_t mtype;\n};\n#define RANGE_READ_QUERY_MESSAGE__INIT \\\n { PROTOBUF_C_MESSAGE_INIT (&range_read_query_message__descriptor) \\\n    , NULL, NULL, {0,NULL}, 0, 0 }\n\n\nstruct  RangeReadResponseMessage\n{\n  ProtobufCMessage base;\n  size_t n_cells;\n  VersionedCellMessage **cells;\n  ProtobufCBinaryData txnid;\n  int64_t nonce;\n  int32_t mtype;\n};\n#define RANGE_READ_RESPONSE_MESSAGE__INIT \\\n { PROTOBUF_C_MESSAGE_INIT (&range_read_response_message__descriptor) \\\n    , 0,NULL, {0,NULL}, 0, 0 }\n\n\nstruct  TxnMessage\n{\n  ProtobufCMessage base;\n  /*\n   * BEGIN=0, VALIDATION=1, COMMIT=2, ABORT=3\n   */\n  int32_t type;\n  size_t n_own_read_set;\n  VersionedCellMessage **own_read_set;\n  size_t n_own_write_set;\n  VersionedCellMessage **own_write_set;\n  size_t n_complete_read_set;\n  VersionedCellMessage **complete_read_set;\n  size_t n_complete_write_set;\n  VersionedCellMessage **complete_write_set;\n  ProtobufCBinaryData txnid;\n  int64_t nonce;\n  VectorClockMessage *version;\n  int32_t mtype;\n};\n#define TXN_MESSAGE__INIT \\\n { PROTOBUF_C_MESSAGE_INIT (&txn_message__descriptor) \\\n    , 0, 0,NULL, 0,NULL, 0,NULL, 0,NULL, {0,NULL}, 0, NULL, 0 }\n\n\nstruct  QueueQueryMessage\n{\n  ProtobufCMessage base;\n  CellAddressMessage *queue_address;\n  /*\n   * QUERY_TYPE_{CREATE_QUEUE, DELETE_QUEUE, SUBSCRIBE_QUEUE, UNSUBSCRIBE_QUEUE, ENQUEUE, READ_QUEUE, CONSUME_QUEUE, READ_QUEUE_RESPONSE, NOTIFICATION}\n   */\n  int32_t msg_type;\n  int32_t app_id;\n  int32_t shard_id;\n  int32_t consumer_id;\n  int32_t group_id;\n  int32_t queue_index;\n  int32_t status;\n  size_t n_cells;\n  VersionedCellMessage **cells;\n  ProtobufCBinaryData txnid;\n  int64_t nonce;\n  int32_t mtype;\n};\n#define QUEUE_QUERY_MESSAGE__INIT \\\n { PROTOBUF_C_MESSAGE_INIT (&queue_query_message__descriptor) \\\n    , NULL, 0, 0, 0, 0, 0, 0, 0, 0,NULL, {0,NULL}, 0, 0 }\n\n\nstruct  ConsumerID\n{\n  ProtobufCMessage base;\n  int32_t app_id;\n  int32_t shard_id;\n  int32_t consumer_id;\n};\n#define CONSUMER_ID__INIT \\\n { PROTOBUF_C_MESSAGE_INIT (&consumer_id__descriptor) \\\n    , 0, 0, 0 }\n\n\nstruct  CreateQueueMessage\n{\n  ProtobufCMessage base;\n  CellAddressMessage *queue_address;\n  ProtobufCBinaryData txnid;\n  int64_t nonce;\n};\n#define CREATE_QUEUE_MESSAGE__INIT \\\n { PROTOBUF_C_MESSAGE_INIT (&create_queue_message__descriptor) \\\n    , NULL, {0,NULL}, 0 }\n\n\nstruct  DeleteQueueMessage\n{\n  ProtobufCMessage base;\n  CellAddressMessage *queue_address;\n  ProtobufCBinaryData txnid;\n  int64_t nonce;\n};\n#define DELETE_QUEUE_MESSAGE__INIT \\\n { PROTOBUF_C_MESSAGE_INIT (&delete_queue_message__descriptor) \\\n    , NULL, {0,NULL}, 0 }\n\n\nstruct  SubscribeQueueMessage\n{\n  ProtobufCMessage base;\n  CellAddressMessage *queue_address;\n  ConsumerID *consumer_id;\n  ProtobufCBinaryData txnid;\n  int64_t nonce;\n};\n#define SUBSCRIBE_QUEUE_MESSAGE__INIT \\\n { PROTOBUF_C_MESSAGE_INIT (&subscribe_queue_message__descriptor) \\\n    , NULL, NULL, {0,NULL}, 0 }\n\n\nstruct  UnsubscribeQueueMessage\n{\n  ProtobufCMessage base;\n  CellAddressMessage *queue_address;\n  ConsumerID *consumer_id;\n  ProtobufCBinaryData txnid;\n  int64_t nonce;\n};\n#define UNSUBSCRIBE_QUEUE_MESSAGE__INIT \\\n { PROTOBUF_C_MESSAGE_INIT (&unsubscribe_queue_message__descriptor) \\\n    , NULL, NULL, {0,NULL}, 0 }\n\n\nstruct  EnqueueMessage\n{\n  ProtobufCMessage base;\n  /*\n   * CellMessage\n   */\n  size_t n_cells;\n  VersionedCellMessage **cells;\n  ProtobufCBinaryData txnid;\n  int64_t nonce;\n};\n#define ENQUEUE_MESSAGE__INIT \\\n { PROTOBUF_C_MESSAGE_INIT (&enqueue_message__descriptor) \\\n    , 0,NULL, {0,NULL}, 0 }\n\n\nstruct  EnqueueResponseMessage\n{\n  ProtobufCMessage base;\n  CellAddressMessage *queue_address;\n  int64_t last_item_id;\n  ProtobufCBinaryData txnid;\n  int64_t nonce;\n};\n#define ENQUEUE_RESPONSE_MESSAGE__INIT \\\n { PROTOBUF_C_MESSAGE_INIT (&enqueue_response_message__descriptor) \\\n    , NULL, 0, {0,NULL}, 0 }\n\n\nstruct  ReadQueueMessage\n{\n  ProtobufCMessage base;\n  CellAddressMessage *queue_address;\n  ConsumerID *consumer_id;\n  int64_t max_items;\n  ProtobufCBinaryData txnid;\n  int64_t nonce;\n};\n#define READ_QUEUE_MESSAGE__INIT \\\n { PROTOBUF_C_MESSAGE_INIT (&read_queue_message__descriptor) \\\n    , NULL, NULL, 0, {0,NULL}, 0 }\n\n\nstruct  ReadQueueResponseMessage\n{\n  ProtobufCMessage base;\n  size_t n_queue_entries;\n  VersionedCellMessage **queue_entries;\n  ConsumerID *consumer_id;\n  ProtobufCBinaryData txnid;\n  int64_t nonce;\n};\n#define READ_QUEUE_RESPONSE_MESSAGE__INIT \\\n { PROTOBUF_C_MESSAGE_INIT (&read_queue_response_message__descriptor) \\\n    , 0,NULL, NULL, {0,NULL}, 0 }\n\n\nstruct  ConsumeQueueMessage\n{\n  ProtobufCMessage base;\n  CellAddressMessage *queue_address;\n  ConsumerID *consumer_id;\n  int64_t new_consume_head;\n  ProtobufCBinaryData txnid;\n  int64_t nonce;\n};\n#define CONSUME_QUEUE_MESSAGE__INIT \\\n { PROTOBUF_C_MESSAGE_INIT (&consume_queue_message__descriptor) \\\n    , NULL, NULL, 0, {0,NULL}, 0 }\n\n\nstruct  ConsumeQueueResponseMessage\n{\n  ProtobufCMessage base;\n  CellAddressMessage *queue_address;\n  ConsumerID *consumer_id;\n  /*\n   * 0 - ACK, 1 - NACK\n   */\n  int32_t status;\n  int64_t new_consume_head;\n  ProtobufCBinaryData txnid;\n  int64_t nonce;\n};\n#define CONSUME_QUEUE_RESPONSE_MESSAGE__INIT \\\n { PROTOBUF_C_MESSAGE_INIT (&consume_queue_response_message__descriptor) \\\n    , NULL, NULL, 0, 0, {0,NULL}, 0 }\n\n\n/* NodeStateMessage methods */\nvoid   node_state_message__init\n                     (NodeStateMessage         *message);\nsize_t node_state_message__get_packed_size\n                     (const NodeStateMessage   *message);\nsize_t node_state_message__pack\n                     (const NodeStateMessage   *message,\n                      uint8_t             *out);\nsize_t node_state_message__pack_to_buffer\n                     (const NodeStateMessage   *message,\n                      ProtobufCBuffer     *buffer);\nNodeStateMessage *\n       node_state_message__unpack\n                     (ProtobufCAllocator  *allocator,\n                      size_t               len,\n                      const uint8_t       *data);\nvoid   node_state_message__free_unpacked\n                     (NodeStateMessage *message,\n                      ProtobufCAllocator *allocator);\n/* VectorClockMessage methods */\nvoid   vector_clock_message__init\n                     (VectorClockMessage         *message);\nsize_t vector_clock_message__get_packed_size\n                     (const VectorClockMessage   *message);\nsize_t vector_clock_message__pack\n                     (const VectorClockMessage   *message,\n                      uint8_t             *out);\nsize_t vector_clock_message__pack_to_buffer\n                     (const VectorClockMessage   *message,\n                      ProtobufCBuffer     *buffer);\nVectorClockMessage *\n       vector_clock_message__unpack\n                     (ProtobufCAllocator  *allocator,\n                      size_t               len,\n                      const uint8_t       *data);\nvoid   vector_clock_message__free_unpacked\n                     (VectorClockMessage *message,\n                      ProtobufCAllocator *allocator);\n/* GossipMessage methods */\nvoid   gossip_message__init\n                     (GossipMessage         *message);\nsize_t gossip_message__get_packed_size\n                     (const GossipMessage   *message);\nsize_t gossip_message__pack\n                     (const GossipMessage   *message,\n                      uint8_t             *out);\nsize_t gossip_message__pack_to_buffer\n                     (const GossipMessage   *message,\n                      ProtobufCBuffer     *buffer);\nGossipMessage *\n       gossip_message__unpack\n                     (ProtobufCAllocator  *allocator,\n                      size_t               len,\n                      const uint8_t       *data);\nvoid   gossip_message__free_unpacked\n                     (GossipMessage *message,\n                      ProtobufCAllocator *allocator);\n/* GossipListenMessage methods */\nvoid   gossip_listen_message__init\n                     (GossipListenMessage         *message);\nsize_t gossip_listen_message__get_packed_size\n                     (const GossipListenMessage   *message);\nsize_t gossip_listen_message__pack\n                     (const GossipListenMessage   *message,\n                      uint8_t             *out);\nsize_t gossip_listen_message__pack_to_buffer\n                     (const GossipListenMessage   *message,\n                      ProtobufCBuffer     *buffer);\nGossipListenMessage *\n       gossip_listen_message__unpack\n                     (ProtobufCAllocator  *allocator,\n                      size_t               len,\n                      const uint8_t       *data);\nvoid   gossip_listen_message__free_unpacked\n                     (GossipListenMessage *message,\n                      ProtobufCAllocator *allocator);\n/* MembershipViewMessage methods */\nvoid   membership_view_message__init\n                     (MembershipViewMessage         *message);\nsize_t membership_view_message__get_packed_size\n                     (const MembershipViewMessage   *message);\nsize_t membership_view_message__pack\n                     (const MembershipViewMessage   *message,\n                      uint8_t             *out);\nsize_t membership_view_message__pack_to_buffer\n                     (const MembershipViewMessage   *message,\n                      ProtobufCBuffer     *buffer);\nMembershipViewMessage *\n       membership_view_message__unpack\n                     (ProtobufCAllocator  *allocator,\n                      size_t               len,\n                      const uint8_t       *data);\nvoid   membership_view_message__free_unpacked\n                     (MembershipViewMessage *message,\n                      ProtobufCAllocator *allocator);\n/* MembershipAgreementMessage methods */\nvoid   membership_agreement_message__init\n                     (MembershipAgreementMessage         *message);\nsize_t membership_agreement_message__get_packed_size\n                     (const MembershipAgreementMessage   *message);\nsize_t membership_agreement_message__pack\n                     (const MembershipAgreementMessage   *message,\n                      uint8_t             *out);\nsize_t membership_agreement_message__pack_to_buffer\n                     (const MembershipAgreementMessage   *message,\n                      ProtobufCBuffer     *buffer);\nMembershipAgreementMessage *\n       membership_agreement_message__unpack\n                     (ProtobufCAllocator  *allocator,\n                      size_t               len,\n                      const uint8_t       *data);\nvoid   membership_agreement_message__free_unpacked\n                     (MembershipAgreementMessage *message,\n                      ProtobufCAllocator *allocator);\n/* CellAddressMessage methods */\nvoid   cell_address_message__init\n                     (CellAddressMessage         *message);\nsize_t cell_address_message__get_packed_size\n                     (const CellAddressMessage   *message);\nsize_t cell_address_message__pack\n                     (const CellAddressMessage   *message,\n                      uint8_t             *out);\nsize_t cell_address_message__pack_to_buffer\n                     (const CellAddressMessage   *message,\n                      ProtobufCBuffer     *buffer);\nCellAddressMessage *\n       cell_address_message__unpack\n                     (ProtobufCAllocator  *allocator,\n                      size_t               len,\n                      const uint8_t       *data);\nvoid   cell_address_message__free_unpacked\n                     (CellAddressMessage *message,\n                      ProtobufCAllocator *allocator);\n/* CellMessage methods */\nvoid   cell_message__init\n                     (CellMessage         *message);\nsize_t cell_message__get_packed_size\n                     (const CellMessage   *message);\nsize_t cell_message__pack\n                     (const CellMessage   *message,\n                      uint8_t             *out);\nsize_t cell_message__pack_to_buffer\n                     (const CellMessage   *message,\n                      ProtobufCBuffer     *buffer);\nCellMessage *\n       cell_message__unpack\n                     (ProtobufCAllocator  *allocator,\n                      size_t               len,\n                      const uint8_t       *data);\nvoid   cell_message__free_unpacked\n                     (CellMessage *message,\n                      ProtobufCAllocator *allocator);\n/* VersionedCellMessage methods */\nvoid   versioned_cell_message__init\n                     (VersionedCellMessage         *message);\nsize_t versioned_cell_message__get_packed_size\n                     (const VersionedCellMessage   *message);\nsize_t versioned_cell_message__pack\n                     (const VersionedCellMessage   *message,\n                      uint8_t             *out);\nsize_t versioned_cell_message__pack_to_buffer\n                     (const VersionedCellMessage   *message,\n                      ProtobufCBuffer     *buffer);\nVersionedCellMessage *\n       versioned_cell_message__unpack\n                     (ProtobufCAllocator  *allocator,\n                      size_t               len,\n                      const uint8_t       *data);\nvoid   versioned_cell_message__free_unpacked\n                     (VersionedCellMessage *message,\n                      ProtobufCAllocator *allocator);\n/* ServerMessage methods */\nvoid   server_message__init\n                     (ServerMessage         *message);\nsize_t server_message__get_packed_size\n                     (const ServerMessage   *message);\nsize_t server_message__pack\n                     (const ServerMessage   *message,\n                      uint8_t             *out);\nsize_t server_message__pack_to_buffer\n                     (const ServerMessage   *message,\n                      ProtobufCBuffer     *buffer);\nServerMessage *\n       server_message__unpack\n                     (ProtobufCAllocator  *allocator,\n                      size_t               len,\n                      const uint8_t       *data);\nvoid   server_message__free_unpacked\n                     (ServerMessage *message,\n                      ProtobufCAllocator *allocator);\n/* ClientMessage methods */\nvoid   client_message__init\n                     (ClientMessage         *message);\nsize_t client_message__get_packed_size\n                     (const ClientMessage   *message);\nsize_t client_message__pack\n                     (const ClientMessage   *message,\n                      uint8_t             *out);\nsize_t client_message__pack_to_buffer\n                     (const ClientMessage   *message,\n                      ProtobufCBuffer     *buffer);\nClientMessage *\n       client_message__unpack\n                     (ProtobufCAllocator  *allocator,\n                      size_t               len,\n                      const uint8_t       *data);\nvoid   client_message__free_unpacked\n                     (ClientMessage *message,\n                      ProtobufCAllocator *allocator);\n/* WriteQueryMessage methods */\nvoid   write_query_message__init\n                     (WriteQueryMessage         *message);\nsize_t write_query_message__get_packed_size\n                     (const WriteQueryMessage   *message);\nsize_t write_query_message__pack\n                     (const WriteQueryMessage   *message,\n                      uint8_t             *out);\nsize_t write_query_message__pack_to_buffer\n                     (const WriteQueryMessage   *message,\n                      ProtobufCBuffer     *buffer);\nWriteQueryMessage *\n       write_query_message__unpack\n                     (ProtobufCAllocator  *allocator,\n                      size_t               len,\n                      const uint8_t       *data);\nvoid   write_query_message__free_unpacked\n                     (WriteQueryMessage *message,\n                      ProtobufCAllocator *allocator);\n/* ReadQueryMessage methods */\nvoid   read_query_message__init\n                     (ReadQueryMessage         *message);\nsize_t read_query_message__get_packed_size\n                     (const ReadQueryMessage   *message);\nsize_t read_query_message__pack\n                     (const ReadQueryMessage   *message,\n                      uint8_t             *out);\nsize_t read_query_message__pack_to_buffer\n                     (const ReadQueryMessage   *message,\n                      ProtobufCBuffer     *buffer);\nReadQueryMessage *\n       read_query_message__unpack\n                     (ProtobufCAllocator  *allocator,\n                      size_t               len,\n                      const uint8_t       *data);\nvoid   read_query_message__free_unpacked\n                     (ReadQueryMessage *message,\n                      ProtobufCAllocator *allocator);\n/* AckMessage methods */\nvoid   ack_message__init\n                     (AckMessage         *message);\nsize_t ack_message__get_packed_size\n                     (const AckMessage   *message);\nsize_t ack_message__pack\n                     (const AckMessage   *message,\n                      uint8_t             *out);\nsize_t ack_message__pack_to_buffer\n                     (const AckMessage   *message,\n                      ProtobufCBuffer     *buffer);\nAckMessage *\n       ack_message__unpack\n                     (ProtobufCAllocator  *allocator,\n                      size_t               len,\n                      const uint8_t       *data);\nvoid   ack_message__free_unpacked\n                     (AckMessage *message,\n                      ProtobufCAllocator *allocator);\n/* RangeReadQueryMessage methods */\nvoid   range_read_query_message__init\n                     (RangeReadQueryMessage         *message);\nsize_t range_read_query_message__get_packed_size\n                     (const RangeReadQueryMessage   *message);\nsize_t range_read_query_message__pack\n                     (const RangeReadQueryMessage   *message,\n                      uint8_t             *out);\nsize_t range_read_query_message__pack_to_buffer\n                     (const RangeReadQueryMessage   *message,\n                      ProtobufCBuffer     *buffer);\nRangeReadQueryMessage *\n       range_read_query_message__unpack\n                     (ProtobufCAllocator  *allocator,\n                      size_t               len,\n                      const uint8_t       *data);\nvoid   range_read_query_message__free_unpacked\n                     (RangeReadQueryMessage *message,\n                      ProtobufCAllocator *allocator);\n/* RangeReadResponseMessage methods */\nvoid   range_read_response_message__init\n                     (RangeReadResponseMessage         *message);\nsize_t range_read_response_message__get_packed_size\n                     (const RangeReadResponseMessage   *message);\nsize_t range_read_response_message__pack\n                     (const RangeReadResponseMessage   *message,\n                      uint8_t             *out);\nsize_t range_read_response_message__pack_to_buffer\n                     (const RangeReadResponseMessage   *message,\n                      ProtobufCBuffer     *buffer);\nRangeReadResponseMessage *\n       range_read_response_message__unpack\n                     (ProtobufCAllocator  *allocator,\n                      size_t               len,\n                      const uint8_t       *data);\nvoid   range_read_response_message__free_unpacked\n                     (RangeReadResponseMessage *message,\n                      ProtobufCAllocator *allocator);\n/* TxnMessage methods */\nvoid   txn_message__init\n                     (TxnMessage         *message);\nsize_t txn_message__get_packed_size\n                     (const TxnMessage   *message);\nsize_t txn_message__pack\n                     (const TxnMessage   *message,\n                      uint8_t             *out);\nsize_t txn_message__pack_to_buffer\n                     (const TxnMessage   *message,\n                      ProtobufCBuffer     *buffer);\nTxnMessage *\n       txn_message__unpack\n                     (ProtobufCAllocator  *allocator,\n                      size_t               len,\n                      const uint8_t       *data);\nvoid   txn_message__free_unpacked\n                     (TxnMessage *message,\n                      ProtobufCAllocator *allocator);\n/* QueueQueryMessage methods */\nvoid   queue_query_message__init\n                     (QueueQueryMessage         *message);\nsize_t queue_query_message__get_packed_size\n                     (const QueueQueryMessage   *message);\nsize_t queue_query_message__pack\n                     (const QueueQueryMessage   *message,\n                      uint8_t             *out);\nsize_t queue_query_message__pack_to_buffer\n                     (const QueueQueryMessage   *message,\n                      ProtobufCBuffer     *buffer);\nQueueQueryMessage *\n       queue_query_message__unpack\n                     (ProtobufCAllocator  *allocator,\n                      size_t               len,\n                      const uint8_t       *data);\nvoid   queue_query_message__free_unpacked\n                     (QueueQueryMessage *message,\n                      ProtobufCAllocator *allocator);\n/* ConsumerID methods */\nvoid   consumer_id__init\n                     (ConsumerID         *message);\nsize_t consumer_id__get_packed_size\n                     (const ConsumerID   *message);\nsize_t consumer_id__pack\n                     (const ConsumerID   *message,\n                      uint8_t             *out);\nsize_t consumer_id__pack_to_buffer\n                     (const ConsumerID   *message,\n                      ProtobufCBuffer     *buffer);\nConsumerID *\n       consumer_id__unpack\n                     (ProtobufCAllocator  *allocator,\n                      size_t               len,\n                      const uint8_t       *data);\nvoid   consumer_id__free_unpacked\n                     (ConsumerID *message,\n                      ProtobufCAllocator *allocator);\n/* CreateQueueMessage methods */\nvoid   create_queue_message__init\n                     (CreateQueueMessage         *message);\nsize_t create_queue_message__get_packed_size\n                     (const CreateQueueMessage   *message);\nsize_t create_queue_message__pack\n                     (const CreateQueueMessage   *message,\n                      uint8_t             *out);\nsize_t create_queue_message__pack_to_buffer\n                     (const CreateQueueMessage   *message,\n                      ProtobufCBuffer     *buffer);\nCreateQueueMessage *\n       create_queue_message__unpack\n                     (ProtobufCAllocator  *allocator,\n                      size_t               len,\n                      const uint8_t       *data);\nvoid   create_queue_message__free_unpacked\n                     (CreateQueueMessage *message,\n                      ProtobufCAllocator *allocator);\n/* DeleteQueueMessage methods */\nvoid   delete_queue_message__init\n                     (DeleteQueueMessage         *message);\nsize_t delete_queue_message__get_packed_size\n                     (const DeleteQueueMessage   *message);\nsize_t delete_queue_message__pack\n                     (const DeleteQueueMessage   *message,\n                      uint8_t             *out);\nsize_t delete_queue_message__pack_to_buffer\n                     (const DeleteQueueMessage   *message,\n                      ProtobufCBuffer     *buffer);\nDeleteQueueMessage *\n       delete_queue_message__unpack\n                     (ProtobufCAllocator  *allocator,\n                      size_t               len,\n                      const uint8_t       *data);\nvoid   delete_queue_message__free_unpacked\n                     (DeleteQueueMessage *message,\n                      ProtobufCAllocator *allocator);\n/* SubscribeQueueMessage methods */\nvoid   subscribe_queue_message__init\n                     (SubscribeQueueMessage         *message);\nsize_t subscribe_queue_message__get_packed_size\n                     (const SubscribeQueueMessage   *message);\nsize_t subscribe_queue_message__pack\n                     (const SubscribeQueueMessage   *message,\n                      uint8_t             *out);\nsize_t subscribe_queue_message__pack_to_buffer\n                     (const SubscribeQueueMessage   *message,\n                      ProtobufCBuffer     *buffer);\nSubscribeQueueMessage *\n       subscribe_queue_message__unpack\n                     (ProtobufCAllocator  *allocator,\n                      size_t               len,\n                      const uint8_t       *data);\nvoid   subscribe_queue_message__free_unpacked\n                     (SubscribeQueueMessage *message,\n                      ProtobufCAllocator *allocator);\n/* UnsubscribeQueueMessage methods */\nvoid   unsubscribe_queue_message__init\n                     (UnsubscribeQueueMessage         *message);\nsize_t unsubscribe_queue_message__get_packed_size\n                     (const UnsubscribeQueueMessage   *message);\nsize_t unsubscribe_queue_message__pack\n                     (const UnsubscribeQueueMessage   *message,\n                      uint8_t             *out);\nsize_t unsubscribe_queue_message__pack_to_buffer\n                     (const UnsubscribeQueueMessage   *message,\n                      ProtobufCBuffer     *buffer);\nUnsubscribeQueueMessage *\n       unsubscribe_queue_message__unpack\n                     (ProtobufCAllocator  *allocator,\n                      size_t               len,\n                      const uint8_t       *data);\nvoid   unsubscribe_queue_message__free_unpacked\n                     (UnsubscribeQueueMessage *message,\n                      ProtobufCAllocator *allocator);\n/* EnqueueMessage methods */\nvoid   enqueue_message__init\n                     (EnqueueMessage         *message);\nsize_t enqueue_message__get_packed_size\n                     (const EnqueueMessage   *message);\nsize_t enqueue_message__pack\n                     (const EnqueueMessage   *message,\n                      uint8_t             *out);\nsize_t enqueue_message__pack_to_buffer\n                     (const EnqueueMessage   *message,\n                      ProtobufCBuffer     *buffer);\nEnqueueMessage *\n       enqueue_message__unpack\n                     (ProtobufCAllocator  *allocator,\n                      size_t               len,\n                      const uint8_t       *data);\nvoid   enqueue_message__free_unpacked\n                     (EnqueueMessage *message,\n                      ProtobufCAllocator *allocator);\n/* EnqueueResponseMessage methods */\nvoid   enqueue_response_message__init\n                     (EnqueueResponseMessage         *message);\nsize_t enqueue_response_message__get_packed_size\n                     (const EnqueueResponseMessage   *message);\nsize_t enqueue_response_message__pack\n                     (const EnqueueResponseMessage   *message,\n                      uint8_t             *out);\nsize_t enqueue_response_message__pack_to_buffer\n                     (const EnqueueResponseMessage   *message,\n                      ProtobufCBuffer     *buffer);\nEnqueueResponseMessage *\n       enqueue_response_message__unpack\n                     (ProtobufCAllocator  *allocator,\n                      size_t               len,\n                      const uint8_t       *data);\nvoid   enqueue_response_message__free_unpacked\n                     (EnqueueResponseMessage *message,\n                      ProtobufCAllocator *allocator);\n/* ReadQueueMessage methods */\nvoid   read_queue_message__init\n                     (ReadQueueMessage         *message);\nsize_t read_queue_message__get_packed_size\n                     (const ReadQueueMessage   *message);\nsize_t read_queue_message__pack\n                     (const ReadQueueMessage   *message,\n                      uint8_t             *out);\nsize_t read_queue_message__pack_to_buffer\n                     (const ReadQueueMessage   *message,\n                      ProtobufCBuffer     *buffer);\nReadQueueMessage *\n       read_queue_message__unpack\n                     (ProtobufCAllocator  *allocator,\n                      size_t               len,\n                      const uint8_t       *data);\nvoid   read_queue_message__free_unpacked\n                     (ReadQueueMessage *message,\n                      ProtobufCAllocator *allocator);\n/* ReadQueueResponseMessage methods */\nvoid   read_queue_response_message__init\n                     (ReadQueueResponseMessage         *message);\nsize_t read_queue_response_message__get_packed_size\n                     (const ReadQueueResponseMessage   *message);\nsize_t read_queue_response_message__pack\n                     (const ReadQueueResponseMessage   *message,\n                      uint8_t             *out);\nsize_t read_queue_response_message__pack_to_buffer\n                     (const ReadQueueResponseMessage   *message,\n                      ProtobufCBuffer     *buffer);\nReadQueueResponseMessage *\n       read_queue_response_message__unpack\n                     (ProtobufCAllocator  *allocator,\n                      size_t               len,\n                      const uint8_t       *data);\nvoid   read_queue_response_message__free_unpacked\n                     (ReadQueueResponseMessage *message,\n                      ProtobufCAllocator *allocator);\n/* ConsumeQueueMessage methods */\nvoid   consume_queue_message__init\n                     (ConsumeQueueMessage         *message);\nsize_t consume_queue_message__get_packed_size\n                     (const ConsumeQueueMessage   *message);\nsize_t consume_queue_message__pack\n                     (const ConsumeQueueMessage   *message,\n                      uint8_t             *out);\nsize_t consume_queue_message__pack_to_buffer\n                     (const ConsumeQueueMessage   *message,\n                      ProtobufCBuffer     *buffer);\nConsumeQueueMessage *\n       consume_queue_message__unpack\n                     (ProtobufCAllocator  *allocator,\n                      size_t               len,\n                      const uint8_t       *data);\nvoid   consume_queue_message__free_unpacked\n                     (ConsumeQueueMessage *message,\n                      ProtobufCAllocator *allocator);\n/* ConsumeQueueResponseMessage methods */\nvoid   consume_queue_response_message__init\n                     (ConsumeQueueResponseMessage         *message);\nsize_t consume_queue_response_message__get_packed_size\n                     (const ConsumeQueueResponseMessage   *message);\nsize_t consume_queue_response_message__pack\n                     (const ConsumeQueueResponseMessage   *message,\n                      uint8_t             *out);\nsize_t consume_queue_response_message__pack_to_buffer\n                     (const ConsumeQueueResponseMessage   *message,\n                      ProtobufCBuffer     *buffer);\nConsumeQueueResponseMessage *\n       consume_queue_response_message__unpack\n                     (ProtobufCAllocator  *allocator,\n                      size_t               len,\n                      const uint8_t       *data);\nvoid   consume_queue_response_message__free_unpacked\n                     (ConsumeQueueResponseMessage *message,\n                      ProtobufCAllocator *allocator);\n/* --- per-message closures --- */\n\ntypedef void (*NodeStateMessage_Closure)\n                 (const NodeStateMessage *message,\n                  void *closure_data);\ntypedef void (*VectorClockMessage_Closure)\n                 (const VectorClockMessage *message,\n                  void *closure_data);\ntypedef void (*GossipMessage_Closure)\n                 (const GossipMessage *message,\n                  void *closure_data);\ntypedef void (*GossipListenMessage_Closure)\n                 (const GossipListenMessage *message,\n                  void *closure_data);\ntypedef void (*MembershipViewMessage_Closure)\n                 (const MembershipViewMessage *message,\n                  void *closure_data);\ntypedef void (*MembershipAgreementMessage_Closure)\n                 (const MembershipAgreementMessage *message,\n                  void *closure_data);\ntypedef void (*CellAddressMessage_Closure)\n                 (const CellAddressMessage *message,\n                  void *closure_data);\ntypedef void (*CellMessage_Closure)\n                 (const CellMessage *message,\n                  void *closure_data);\ntypedef void (*VersionedCellMessage_Closure)\n                 (const VersionedCellMessage *message,\n                  void *closure_data);\ntypedef void (*ServerMessage_Closure)\n                 (const ServerMessage *message,\n                  void *closure_data);\ntypedef void (*ClientMessage_Closure)\n                 (const ClientMessage *message,\n                  void *closure_data);\ntypedef void (*WriteQueryMessage_Closure)\n                 (const WriteQueryMessage *message,\n                  void *closure_data);\ntypedef void (*ReadQueryMessage_Closure)\n                 (const ReadQueryMessage *message,\n                  void *closure_data);\ntypedef void (*AckMessage_Closure)\n                 (const AckMessage *message,\n                  void *closure_data);\ntypedef void (*RangeReadQueryMessage_Closure)\n                 (const RangeReadQueryMessage *message,\n                  void *closure_data);\ntypedef void (*RangeReadResponseMessage_Closure)\n                 (const RangeReadResponseMessage *message,\n                  void *closure_data);\ntypedef void (*TxnMessage_Closure)\n                 (const TxnMessage *message,\n                  void *closure_data);\ntypedef void (*QueueQueryMessage_Closure)\n                 (const QueueQueryMessage *message,\n                  void *closure_data);\ntypedef void (*ConsumerID_Closure)\n                 (const ConsumerID *message,\n                  void *closure_data);\ntypedef void (*CreateQueueMessage_Closure)\n                 (const CreateQueueMessage *message,\n                  void *closure_data);\ntypedef void (*DeleteQueueMessage_Closure)\n                 (const DeleteQueueMessage *message,\n                  void *closure_data);\ntypedef void (*SubscribeQueueMessage_Closure)\n                 (const SubscribeQueueMessage *message,\n                  void *closure_data);\ntypedef void (*UnsubscribeQueueMessage_Closure)\n                 (const UnsubscribeQueueMessage *message,\n                  void *closure_data);\ntypedef void (*EnqueueMessage_Closure)\n                 (const EnqueueMessage *message,\n                  void *closure_data);\ntypedef void (*EnqueueResponseMessage_Closure)\n                 (const EnqueueResponseMessage *message,\n                  void *closure_data);\ntypedef void (*ReadQueueMessage_Closure)\n                 (const ReadQueueMessage *message,\n                  void *closure_data);\ntypedef void (*ReadQueueResponseMessage_Closure)\n                 (const ReadQueueResponseMessage *message,\n                  void *closure_data);\ntypedef void (*ConsumeQueueMessage_Closure)\n                 (const ConsumeQueueMessage *message,\n                  void *closure_data);\ntypedef void (*ConsumeQueueResponseMessage_Closure)\n                 (const ConsumeQueueResponseMessage *message,\n                  void *closure_data);\n\n/* --- services --- */\n\n\n/* --- descriptors --- */\n\nextern const ProtobufCMessageDescriptor node_state_message__descriptor;\nextern const ProtobufCMessageDescriptor vector_clock_message__descriptor;\nextern const ProtobufCMessageDescriptor gossip_message__descriptor;\nextern const ProtobufCMessageDescriptor gossip_listen_message__descriptor;\nextern const ProtobufCMessageDescriptor membership_view_message__descriptor;\nextern const ProtobufCMessageDescriptor membership_agreement_message__descriptor;\nextern const ProtobufCMessageDescriptor cell_address_message__descriptor;\nextern const ProtobufCMessageDescriptor cell_message__descriptor;\nextern const ProtobufCMessageDescriptor versioned_cell_message__descriptor;\nextern const ProtobufCMessageDescriptor server_message__descriptor;\nextern const ProtobufCMessageDescriptor client_message__descriptor;\nextern const ProtobufCMessageDescriptor write_query_message__descriptor;\nextern const ProtobufCMessageDescriptor read_query_message__descriptor;\nextern const ProtobufCMessageDescriptor ack_message__descriptor;\nextern const ProtobufCMessageDescriptor range_read_query_message__descriptor;\nextern const ProtobufCMessageDescriptor range_read_response_message__descriptor;\nextern const ProtobufCMessageDescriptor txn_message__descriptor;\nextern const ProtobufCMessageDescriptor queue_query_message__descriptor;\nextern const ProtobufCMessageDescriptor consumer_id__descriptor;\nextern const ProtobufCMessageDescriptor create_queue_message__descriptor;\nextern const ProtobufCMessageDescriptor delete_queue_message__descriptor;\nextern const ProtobufCMessageDescriptor subscribe_queue_message__descriptor;\nextern const ProtobufCMessageDescriptor unsubscribe_queue_message__descriptor;\nextern const ProtobufCMessageDescriptor enqueue_message__descriptor;\nextern const ProtobufCMessageDescriptor enqueue_response_message__descriptor;\nextern const ProtobufCMessageDescriptor read_queue_message__descriptor;\nextern const ProtobufCMessageDescriptor read_queue_response_message__descriptor;\nextern const ProtobufCMessageDescriptor consume_queue_message__descriptor;\nextern const ProtobufCMessageDescriptor consume_queue_response_message__descriptor;\n\nPROTOBUF_C__END_DECLS\n\n\n#endif  /* PROTOBUF_C_backend_2ffailure_5fdetector_2fdb_5fmessages_2eproto__INCLUDED */\n"
  },
  {
    "path": "backend/failure_detector/db_messages.proto",
    "content": "/*\n * Copyright (C) 2019-2021 Deutsche Telekom AG\n *\n * Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:\n *\n * 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.\n *\n * 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.\n *\n * 3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission.\n *\n * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS \"AS IS\" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n */\n\nsyntax = \"proto2\";\n\n// Membership protocol:\n\nmessage NodeStateMessage {\n    required int32 status=1;    // 0 - dead, 1 - ready, 2 - alive but not ready\n    required int32 node_id=2;\n    required bytes hostname=3;\n    required int32 port=4;\n    required int32 rack_id=5;\n    required int32 dc_id=6;\n}\n\nmessage VectorClockMessage {\n    repeated int32 ids=1; \n    repeated int64 counters=2; \n}\n\nmessage GossipMessage {\n    required NodeStateMessage node_state=1;\n    required VectorClockMessage vc=2;\n}\n\nmessage GossipListenMessage {\n    required NodeStateMessage node_state=1;\n    required int64 nonce=2;\n}\n\nmessage MembershipViewMessage {\n    repeated NodeStateMessage membership=1; \n    repeated NodeStateMessage client_membership=2; \n    required VectorClockMessage view_id=3;\n}\n\nmessage MembershipAgreementMessage {\n    required int32 msg_type=1;      // 0 - PROPOSE, 1 - RESPONSE, 2 - NOTIFY, 3 - RETRY_LINK, 4 - NOTIFY_ACK\n    required int32 ack_status=2;        // 0 - ACK, 1 - NACK, 2 - UNINIT\n    optional MembershipViewMessage view=3; \n    required int64 nonce=4;\n    required VectorClockMessage vc=5;\n}\n\n// DB cells and Queue entries:\n\nmessage CellAddressMessage {\n    required int64 table_key=1;\n    repeated int64 keys=2;\n}\n\nmessage CellMessage {\n    required int64 table_key=1;\n    repeated int64 keys=2;\n    repeated int64 columns=3;\n}\n\nmessage VersionedCellMessage {\n    required int64 table_key=1;\n    repeated int64 keys=2;\n    repeated int64 columns=3;\n    required bytes blob=4;\n    \n    optional VectorClockMessage version=5;\n//  optional int64 version_no=6;\n}\n\n// DB queries:\n\nmessage ServerMessage {\n    required int32 mtype=1; // {RPC_TYPE_WRITE, RPC_TYPE_READ, RPC_TYPE_RANGE_READ, RPC_TYPE_QUEUE, RPC_TYPE_TXN, RPC_TYPE_GOSSIP_LISTEN}\n    \n    optional WriteQueryMessage wm=2;\n    optional ReadQueryMessage rm=3;\n    optional RangeReadQueryMessage rrm=4;\n    optional QueueQueryMessage qm=5;\n    optional TxnMessage tm=6;\n    optional GossipListenMessage gl=7;\n    \n    optional VectorClockMessage vc=8;\n}\n\nmessage ClientMessage {\n    required int32 mtype=1; // {RPC_TYPE_ACK, RPC_TYPE_WRITE, RPC_TYPE_RANGE_READ_RESPONSE, RPC_TYPE_QUEUE, RPC_TYPE_TXN}\n    \n    optional AckMessage am=2;\n    optional WriteQueryMessage wm=3;\n    optional RangeReadResponseMessage rrrm=4;\n    optional QueueQueryMessage qm=5;\n    optional TxnMessage tm=6;\n\n    optional VectorClockMessage vc=7;\n}\n\nmessage WriteQueryMessage {\n    optional VersionedCellMessage cell=1; // CellMessage\n    required bytes txnid=2;\n    required int64 nonce=3;\n    \n    required int32 msg_type=4; // {RPC_TYPE_WRITE, RPC_TYPE_DELETE}\n    \n    required int32 mtype=5;\n}\n\nmessage ReadQueryMessage {\n    required CellAddressMessage cell_address=1;\n    required bytes txnid=2;\n    required int64 nonce=3;\n    \n    required int32 mtype=4;\n}\n\nmessage AckMessage {\n    optional CellAddressMessage cell_address=1;\n    required int32 status=2; // 0 - ACK, 1 - NACK\n    required bytes txnid=3;\n    required int64 nonce=4;\n    \n    required int32 mtype=5;\n}\n\nmessage RangeReadQueryMessage {\n    required CellAddressMessage start_cell_address=1;\n    required CellAddressMessage end_cell_address=2;\n    required bytes txnid=3;\n    required int64 nonce=4;\n    \n    required int32 mtype=5;\n}\n\nmessage RangeReadResponseMessage {\n    repeated VersionedCellMessage cells=1;\n    required bytes txnid=2;\n    required int64 nonce=3;\n    \n    required int32 mtype=4;\n}\n\n\n// Txn messages:\n\nmessage TxnMessage {\n    required int32 type=1; // BEGIN=0, VALIDATION=1, COMMIT=2, ABORT=3\n    repeated VersionedCellMessage own_read_set=2;\n    repeated VersionedCellMessage own_write_set=3;\n    repeated VersionedCellMessage complete_read_set=4;\n    repeated VersionedCellMessage complete_write_set=5;\n    required bytes txnid=6;\n    required int64 nonce=7;\n    \n    optional VectorClockMessage version=8;\n    \n    required int32 mtype=9;\n}\n\n// Queue messages:\n\nmessage QueueQueryMessage {\n    required CellAddressMessage queue_address=1;\n    \n    required int32 msg_type=2; // QUERY_TYPE_{CREATE_QUEUE, DELETE_QUEUE, SUBSCRIBE_QUEUE, UNSUBSCRIBE_QUEUE, ENQUEUE, READ_QUEUE, CONSUME_QUEUE, READ_QUEUE_RESPONSE, NOTIFICATION}\n\n    required int32 app_id=3;\n    required int32 shard_id=4;\n    required int32 consumer_id=5;\n    required int32 group_id=6;\n\n    required int32 queue_index=7;\n\n    required int32 status=8;\n    \n    repeated VersionedCellMessage cells=9;\n\n    required bytes txnid=10;\n    required int64 nonce=11;\n    \n    required int32 mtype=12;\n}\n\n\n// Below message types are obsolete:\n\nmessage ConsumerID {\n    required int32 app_id=1;\n    required int32 shard_id=2;\n    required int32 consumer_id=3;\n}\n\nmessage CreateQueueMessage {\n    required CellAddressMessage queue_address=1;\n    required bytes txnid=2;\n    required int64 nonce=3;\n}\n\nmessage DeleteQueueMessage {\n    required CellAddressMessage queue_address=1;\n    required bytes txnid=2;\n    required int64 nonce=3;\n}\n\nmessage SubscribeQueueMessage {\n    required CellAddressMessage queue_address=1;\n    required ConsumerID consumer_id=2;\n    required bytes txnid=3;\n    required int64 nonce=4;\n}\n\nmessage UnsubscribeQueueMessage {\n    required CellAddressMessage queue_address=1;\n    required ConsumerID consumer_id=2;\n    required bytes txnid=3;\n    required int64 nonce=4;\n}\n\nmessage EnqueueMessage {\n    repeated VersionedCellMessage cells=1; // CellMessage\n    required bytes txnid=2;\n    required int64 nonce=3;\n}\n\nmessage EnqueueResponseMessage {\n    required CellAddressMessage queue_address=1;\n    required int64 last_item_id=2;  \n    required bytes txnid=3;\n    required int64 nonce=4;\n}\n\nmessage ReadQueueMessage {\n    required CellAddressMessage queue_address=1;\n    required ConsumerID consumer_id=2;\n    required int64 max_items=3;\n    required bytes txnid=4;\n    required int64 nonce=5;\n}\n\nmessage ReadQueueResponseMessage {\n    repeated VersionedCellMessage queue_entries=1;\n    required ConsumerID consumer_id=2;\n    required bytes txnid=3;\n    required int64 nonce=4;\n}\n\nmessage ConsumeQueueMessage {\n    required CellAddressMessage queue_address=1;\n    required ConsumerID consumer_id=2;\n    required int64 new_consume_head=3;\n    required bytes txnid=4;\n    required int64 nonce=5;\n}\n\nmessage ConsumeQueueResponseMessage {\n    required CellAddressMessage queue_address=1;\n    required ConsumerID consumer_id=2;\n    required int32 status=3; // 0 - ACK, 1 - NACK\n    required int64 new_consume_head=4;\n    required bytes txnid=5;\n    required int64 nonce=6;\n}\n\n"
  },
  {
    "path": "backend/failure_detector/db_messages_test.c",
    "content": "/*\n * Copyright (C) 2019-2021 Deutsche Telekom AG\n *\n * Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:\n *\n * 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.\n *\n * 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.\n *\n * 3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission.\n *\n * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS \"AS IS\" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n */\n\n/*\n * db_messages_test.c\n *\n *      Author: aagapi\n */\n\n#include \"vector_clock.h\"\n#include \"fd.h\"\n#include \"cells.h\"\n#include \"db_queries.h\"\n#include <stdio.h>\n#include <stdlib.h>\n#include <assert.h>\n#include <uuid/uuid.h>\n#include <string.h>\n\n#define MAX_MSG_SIZE_VC 1024\n\nint write_msg_to_file (unsigned char *buff, unsigned len, FILE * fp)\n{\n    unsigned written = fwrite(buff, len, 1, fp);\n\n//  printf(\"Wrote %d / %d bytes to file\\n\", written * len, len);\n\n    return (written == 1)? 0 : -1;\n}\n\nint read_msg_from_file (unsigned max_length, unsigned char *buff, FILE * fp)\n{\n  unsigned cur_len = 0;\n  unsigned nread;\n\n  while ((nread=fread(buff + cur_len, 1, max_length - cur_len, fp)) != 0)\n  {\n    printf(\"Read %d bytes\\n\", nread);\n    cur_len += nread;\n    if (cur_len == max_length)\n    {\n      fprintf(stderr, \"max message length exceeded\\n\");\n      return -1;\n    }\n  }\n  return cur_len;\n}\n\nvoid write_read_from_file(void * buf_w, unsigned len_w, unsigned char *buf_r, unsigned * len_r)\n{\n    // Serialize it to file:\n\n    FILE * fptr_w = fopen(\"/tmp/vc.test\",\"wb\");\n    int success = write_msg_to_file(buf_w, len_w, fptr_w);\n    assert(success == 0);\n    fclose(fptr_w);\n\n    // Read it back:\n\n    FILE * fptr_r = fopen(\"/tmp/vc.test\",\"rb\");\n\n    *len_r = read_msg_from_file(MAX_MSG_SIZE_VC, buf_r, fptr_r);\n\n    if(*len_r != len_w)\n    {\n        printf(\"len_r=%d != len_w=%d\\n\", *len_r, len_w);\n        assert(0);\n    }\n    fclose(fptr_r);\n}\n\n\nint main (int argc, const char * argv[])\n{\n    FILE *fptr_w = NULL, * fptr_r = NULL;\n    void * buf_w;\n    unsigned len_w;\n    unsigned char buf_r[MAX_MSG_SIZE_VC];\n//  void * buf_r = malloc(MAX_MSG_SIZE_VC);\n    unsigned len_r;\n    char err_msg[1024], err_msg2[1024];\n\n    // Generate a dummy VC message:\n\n    int node_ids[] = {0,1};\n    int64_t counters[] = {0,0};\n\n    vector_clock * vc = init_vc(2, node_ids, counters, 1), * vc_r = NULL;\n    add_component_vc(vc, 2, 0);\n    increment_vc(vc, 0);\n    increment_vc(vc, 0);\n    increment_vc(vc, 1);\n    increment_vc(vc, 2);\n    increment_vc(vc, 2);\n    serialize_vc(vc, &buf_w, &len_w);\n    write_read_from_file(buf_w, len_w, buf_r, &len_r);\n    deserialize_vc(buf_r, len_r, &vc_r);\n    printf(\"VC message: %s\\n\", to_string_vc(vc, err_msg));\n    if(compare_vc(vc, vc_r) != 0)\n    {\n        printf(\"VC read mismatch (%s)!\\n\", to_string_vc(vc_r, err_msg));\n        assert(0);\n    }\n\n    // Generate dummy GS message:\n\n    gossip_state * gs = init_gossip_state(0, 0, 0, 0, \"localhost\", 32000, vc), * gs_r = NULL;\n    serialize_gs(gs, &buf_w, &len_w);\n    write_read_from_file(buf_w, len_w, buf_r, &len_r);\n    deserialize_gs(buf_r, len_r, &gs_r);\n\n    printf(\"GossipState message: %s\\n\", to_string_gs(gs, err_msg));\n    if(!equals_gs(gs, gs_r))\n    {\n        printf(\"GS read mismatch (%s)!\\n\", to_string_gs(gs_r, err_msg));\n        assert(0);\n    }\n\n    // Generate dummy Membership State message:\n\n    node_description * nds = (node_description *) malloc(3 * sizeof(node_description));\n    copy_node_description(&nds[0], 0, 0, 0, 0, \"localhost\", 32000);\n    copy_node_description(&nds[1], 0, 1, 0, 0, \"localhost\", 32001);\n    copy_node_description(&nds[2], 1, 2, 0, 0, \"localhost\", 32002);\n\n    node_description * client_nds = (node_description *) malloc(1 * sizeof(node_description));\n    copy_node_description(&client_nds[0], 0, 0, 0, 0, \"localhost\", 22000);\n\n    membership_state * ms = init_membership_state(3, nds, 1, client_nds, vc), * ms_r = NULL;\n    serialize_membership_state(ms, &buf_w, &len_w);\n    write_read_from_file(buf_w, len_w, buf_r, &len_r);\n    deserialize_membership_state(buf_r, len_r, &ms_r);\n\n    printf(\"MembershipState message: %s\\n\", to_string_membership_state(ms, err_msg));\n    if(!equals_membership_state(ms, ms_r))\n    {\n        printf(\"MembershipState read mismatch (%s)!\\n\", to_string_membership_state(ms_r, err_msg));\n        assert(0);\n    }\n\n    // Generate dummy Membership Agreement message:\n\n    membership_agreement_msg * ma = init_membership_agreement_msg(MEMBERSHIP_AGREEMENT_PROPOSE, 0, ms, 0, vc), * ma_r = NULL;\n    serialize_membership_agreement_msg(ma, &buf_w, &len_w);\n    write_read_from_file(buf_w, len_w, buf_r, &len_r);\n    unsigned msg_len = ((unsigned *) buf_r)[0];\n    deserialize_membership_agreement_msg(buf_r + sizeof(int), msg_len, &ma_r);\n\n    printf(\"MembershipAgreement message: %s\\n\", to_string_membership_agreement_msg(ma, err_msg));\n    if(!equals_membership_agreement_msg(ma, ma_r))\n    {\n        printf(\"MembershipAgreement read mismatch (%s)!\\n\", to_string_membership_agreement_msg(ma_r, err_msg));\n        assert(0);\n    }\n\n    // Generate a dummy Cell and CellAddress:\n\n    int64_t key = 1, end_key = 3;\n    int64_t column = 1, end_column = 5;\n    uuid_t txnid;\n    uuid_generate(txnid);\n\n    int no_cells = 2;\n    cell * cll = (cell *) malloc(no_cells * sizeof(cell));\n    for(int i=0;i<no_cells;i++)\n        copy_cell(cll + i, 0, (i==0)?(&key) : (&end_key), 1, (i==0)?(&column) : (&end_column), 1, NULL, 0, vc);\n    cell_address * cell_address = init_cell_address(0, &key, 1), * end_cell_address = init_cell_address(0, &end_key, 1);\n\n    // Generate dummy Write Query:\n\n    short mtype = -1;\n    write_query * wquery = init_write_query(cll, RPC_TYPE_WRITE, &txnid, 3), * wquery_r = NULL;\n    serialize_write_query(wquery, &buf_w, &len_w, 1, vc);\n    write_read_from_file(buf_w, len_w, buf_r, &len_r);\n    assert(((int *) buf_r)[0] == len_r - sizeof(int));\n    deserialize_server_message(((int *) buf_r + 1), len_r - sizeof(int), (void *) &wquery_r, &mtype, &vc_r);\n    assert(mtype == RPC_TYPE_WRITE);\n\n    printf(\"Write query: %s (%s)\\n\", to_string_write_query(wquery, err_msg), to_string_vc(vc_r, err_msg2));\n    if(!equals_write_query(wquery, wquery_r))\n    {\n        printf(\"Write query read mismatch (%s)!\\n\", to_string_write_query(wquery_r, err_msg));\n        assert(0);\n    }\n    if(compare_vc(vc, vc_r) != 0)\n    {\n        printf(\"VC read mismatch (%s)!\\n\", to_string_vc(vc_r, err_msg));\n        assert(0);\n    }\n\n\n    // Generate dummy Read Query:\n\n    read_query * rquery = init_read_query(cell_address, &txnid, 3), * rquery_r = NULL;\n    serialize_read_query(rquery, &buf_w, &len_w, vc);\n    write_read_from_file(buf_w, len_w, buf_r, &len_r);\n    deserialize_server_message(((int *) buf_r + 1), len_r - sizeof(int), (void *) &rquery_r, &mtype, &vc_r);\n    assert(mtype == RPC_TYPE_READ);\n\n    printf(\"Read query: %s (%s)\\n\", to_string_read_query(rquery, err_msg), to_string_vc(vc_r, err_msg2));\n    if(!equals_read_query(rquery, rquery_r))\n    {\n        printf(\"Read query read mismatch (%s)!\\n\", to_string_read_query(rquery_r, err_msg));\n        assert(0);\n    }\n    if(compare_vc(vc, vc_r) != 0)\n    {\n        printf(\"VC read mismatch (%s)!\\n\", to_string_vc(vc_r, err_msg));\n        assert(0);\n    }\n\n    // Ack Message:\n\n    ack_message * am = init_ack_message(cell_address, 1, &txnid, 3), * am_r = NULL;\n    serialize_ack_message(am, &buf_w, &len_w, vc);\n    write_read_from_file(buf_w, len_w, buf_r, &len_r);\n    deserialize_client_message(((int *) buf_r + 1), len_r - sizeof(int), (void *) &am_r, &mtype, &vc_r);\n    assert(mtype == RPC_TYPE_ACK);\n\n    printf(\"Ack message: %s (%s)\\n\", to_string_ack_message(am, err_msg), to_string_vc(vc_r, err_msg2));\n    if(!equals_ack_message(am, am_r))\n    {\n        printf(\"Ack message read mismatch (%s)!\\n\", to_string_ack_message(am_r, err_msg));\n        assert(0);\n    }\n    if(compare_vc(vc, vc_r) != 0)\n    {\n        printf(\"VC read mismatch (%s)!\\n\", to_string_vc(vc_r, err_msg));\n        assert(0);\n    }\n\n    // Range read query:\n\n    range_read_query * rrq = init_range_read_query(cell_address, end_cell_address, &txnid, 3), * rrq_r = NULL;\n    serialize_range_read_query(rrq, &buf_w, &len_w, vc);\n    write_read_from_file(buf_w, len_w, buf_r, &len_r);\n    deserialize_server_message(((int *) buf_r + 1), len_r - sizeof(int), (void *) &rrq_r, &mtype, &vc_r);\n    assert(mtype == RPC_TYPE_RANGE_READ);\n\n    printf(\"Range Read Query: %s (%s)\\n\", to_string_range_read_query(rrq, err_msg), to_string_vc(vc_r, err_msg2));\n    if(!equals_range_read_query(rrq, rrq_r))\n    {\n        printf(\"Range Read Query read mismatch (%s)!\\n\", to_string_range_read_query(rrq_r, err_msg));\n        assert(0);\n    }\n    if(compare_vc(vc, vc_r) != 0)\n    {\n        printf(\"VC read mismatch (%s)!\\n\", to_string_vc(vc_r, err_msg));\n        assert(0);\n    }\n\n    // Range read response:\n\n    range_read_response_message * rrm = init_range_read_response_message(cll, no_cells, &txnid, 3), * rrm_r = NULL;\n    serialize_range_read_response_message(rrm, &buf_w, &len_w, vc);\n    write_read_from_file(buf_w, len_w, buf_r, &len_r);\n    deserialize_client_message(((int *) buf_r + 1), len_r - sizeof(int), (void *) &rrm_r, &mtype, &vc_r);\n    assert(mtype == RPC_TYPE_RANGE_READ_RESPONSE);\n\n    printf(\"Range Read Response: %s (%s)\\n\", to_string_range_read_response_message(rrm, err_msg), to_string_vc(vc_r, err_msg2));\n    if(!equals_range_read_response_message(rrm, rrm_r))\n    {\n        printf(\"Range Read Response read mismatch (%s)!\\n\", to_string_range_read_response_message(rrm_r, err_msg));\n        assert(0);\n    }\n    if(compare_vc(vc, vc_r) != 0)\n    {\n        printf(\"VC read mismatch (%s)!\\n\", to_string_vc(vc_r, err_msg));\n        assert(0);\n    }\n\n    // Create queue message:\n\n    queue_query_message * cq = init_create_queue_message(cell_address, &txnid, 3), * cq_r = NULL;\n    serialize_queue_message(cq, &buf_w, &len_w, 1, vc);\n    write_read_from_file(buf_w, len_w, buf_r, &len_r);\n    deserialize_server_message(((int *) buf_r + 1), len_r - sizeof(int), (void *) &cq_r, &mtype, &vc_r);\n    assert(mtype == RPC_TYPE_QUEUE);\n\n    printf(\"Create Queue: %s (%s)\\n\", to_string_queue_message(cq, err_msg), to_string_vc(vc_r, err_msg2));\n    if(!equals_queue_message(cq, cq_r))\n    {\n        printf(\"Create Queue read mismatch (%s)!\\n\", to_string_queue_message(cq_r, err_msg));\n        assert(0);\n    }\n    if(compare_vc(vc, vc_r) != 0)\n    {\n        printf(\"VC read mismatch (%s)!\\n\", to_string_vc(vc_r, err_msg));\n        assert(0);\n    }\n\n    // Delete queue message:\n\n    cq = init_delete_queue_message(cell_address, &txnid, 3);\n    serialize_queue_message(cq, &buf_w, &len_w, 1, vc);\n    write_read_from_file(buf_w, len_w, buf_r, &len_r);\n    deserialize_server_message(((int *) buf_r + 1), len_r - sizeof(int), (void *) &cq_r, &mtype, &vc_r);\n    assert(mtype == RPC_TYPE_QUEUE);\n\n    printf(\"Delete Queue: %s (%s)\\n\", to_string_queue_message(cq, err_msg), to_string_vc(vc_r, err_msg2));\n    if(!equals_queue_message(cq, cq_r))\n    {\n        printf(\"Delete Queue read mismatch (%s)!\\n\", to_string_queue_message(cq_r, err_msg));\n        assert(0);\n    }\n    if(compare_vc(vc, vc_r) != 0)\n    {\n        printf(\"VC read mismatch (%s)!\\n\", to_string_vc(vc_r, err_msg));\n        assert(0);\n    }\n\n    // Subscribe queue message:\n\n    cq = init_subscribe_queue_message(cell_address, 1, 2, 3, &txnid, 3);\n    serialize_queue_message(cq, &buf_w, &len_w, 1, vc);\n    write_read_from_file(buf_w, len_w, buf_r, &len_r);\n    deserialize_server_message(((int *) buf_r + 1), len_r - sizeof(int), (void *) &cq_r, &mtype, &vc_r);\n    assert(mtype == RPC_TYPE_QUEUE);\n\n    printf(\"Subscribe Queue: %s (%s)\\n\", to_string_queue_message(cq, err_msg), to_string_vc(vc_r, err_msg2));\n    if(!equals_queue_message(cq, cq_r))\n    {\n        printf(\"Subscribe Queue read mismatch (%s)!\\n\", to_string_queue_message(cq_r, err_msg));\n        assert(0);\n    }\n    if(compare_vc(vc, vc_r) != 0)\n    {\n        printf(\"VC read mismatch (%s)!\\n\", to_string_vc(vc_r, err_msg));\n        assert(0);\n    }\n\n    // Unsubscribe queue message:\n\n    cq = init_unsubscribe_queue_message(cell_address, 1, 2, 3, &txnid, 3);\n    serialize_queue_message(cq, &buf_w, &len_w, 1, vc);\n    write_read_from_file(buf_w, len_w, buf_r, &len_r);\n    deserialize_server_message(((int *) buf_r + 1), len_r - sizeof(int), (void *) &cq_r, &mtype, &vc_r);\n    assert(mtype == RPC_TYPE_QUEUE);\n\n    printf(\"Unsubscribe Queue: %s (%s)\\n\", to_string_queue_message(cq, err_msg), to_string_vc(vc_r, err_msg2));\n    if(!equals_queue_message(cq, cq_r))\n    {\n        printf(\"Unsubscribe Queue read mismatch (%s)!\\n\", to_string_queue_message(cq_r, err_msg));\n        assert(0);\n    }\n    if(compare_vc(vc, vc_r) != 0)\n    {\n        printf(\"VC read mismatch (%s)!\\n\", to_string_vc(vc_r, err_msg));\n        assert(0);\n    }\n\n    // Enqueue message:\n\n    cq = init_enqueue_message(cell_address, cll, no_cells, &txnid, 3);\n    serialize_queue_message(cq, &buf_w, &len_w, 1, vc);\n    write_read_from_file(buf_w, len_w, buf_r, &len_r);\n    deserialize_server_message(((int *) buf_r + 1), len_r - sizeof(int), (void *) &cq_r, &mtype, &vc_r);\n    assert(mtype == RPC_TYPE_QUEUE);\n\n    printf(\"Enqueue: %s (%s)\\n\", to_string_queue_message(cq, err_msg), to_string_vc(vc_r, err_msg2));\n    if(!equals_queue_message(cq, cq_r))\n    {\n        printf(\"Enqueue read mismatch (%s)!\\n\", to_string_queue_message(cq_r, err_msg));\n        assert(0);\n    }\n    if(compare_vc(vc, vc_r) != 0)\n    {\n        printf(\"VC read mismatch (%s)!\\n\", to_string_vc(vc_r, err_msg));\n        assert(0);\n    }\n\n    // Read queue message:\n\n    cq = init_read_queue_message(cell_address, 1, 2, 3, 2, &txnid, 3);\n    serialize_queue_message(cq, &buf_w, &len_w, 1, vc);\n    write_read_from_file(buf_w, len_w, buf_r, &len_r);\n    deserialize_server_message(((int *) buf_r + 1), len_r - sizeof(int), (void *) &cq_r, &mtype, &vc_r);\n    assert(mtype == RPC_TYPE_QUEUE);\n\n    printf(\"Read Queue: %s (%s)\\n\", to_string_queue_message(cq, err_msg), to_string_vc(vc_r, err_msg2));\n    if(!equals_queue_message(cq, cq_r))\n    {\n        printf(\"Read Queue read mismatch (%s)!\\n\", to_string_queue_message(cq_r, err_msg));\n        assert(0);\n    }\n    if(compare_vc(vc, vc_r) != 0)\n    {\n        printf(\"VC read mismatch (%s)!\\n\", to_string_vc(vc_r, err_msg));\n        assert(0);\n    }\n\n    // Consume queue message:\n\n    cq = init_consume_queue_message(cell_address, 1, 2, 3, 1, &txnid, 3);\n    serialize_queue_message(cq, &buf_w, &len_w, 1, vc);\n    write_read_from_file(buf_w, len_w, buf_r, &len_r);\n    deserialize_server_message(((int *) buf_r + 1), len_r - sizeof(int), (void *) &cq_r, &mtype, &vc_r);\n    assert(mtype == RPC_TYPE_QUEUE);\n\n    printf(\"Consume Queue: %s (%s)\\n\", to_string_queue_message(cq, err_msg), to_string_vc(vc_r, err_msg2));\n    if(!equals_queue_message(cq, cq_r))\n    {\n        printf(\"Consume Queue read mismatch (%s)!\\n\", to_string_queue_message(cq_r, err_msg));\n        assert(0);\n    }\n    if(compare_vc(vc, vc_r) != 0)\n    {\n        printf(\"VC read mismatch (%s)!\\n\", to_string_vc(vc_r, err_msg));\n        assert(0);\n    }\n\n    // Read queue response message:\n\n    cq = init_read_queue_response(cell_address, cll, no_cells, 1, 2, 3, 1, 2, 1, &txnid, 3);\n    serialize_queue_message(cq, &buf_w, &len_w, 0, vc);\n    write_read_from_file(buf_w, len_w, buf_r, &len_r);\n    deserialize_client_message(((int *) buf_r + 1), len_r - sizeof(int), (void *) &cq_r, &mtype, &vc_r);\n    assert(mtype == RPC_TYPE_QUEUE);\n\n    printf(\"Read Queue Response: %s (%s)\\n\", to_string_queue_message(cq, err_msg), to_string_vc(vc_r, err_msg2));\n    if(!equals_queue_message(cq, cq_r))\n    {\n        printf(\"Read Queue Response read mismatch (%s)!\\n\", to_string_queue_message(cq_r, err_msg));\n        assert(0);\n    }\n    if(compare_vc(vc, vc_r) != 0)\n    {\n        printf(\"VC read mismatch (%s)!\\n\", to_string_vc(vc_r, err_msg));\n        assert(0);\n    }\n\n    // Txn message:\n\n    txn_message * tm = init_txn_message(DB_TXN_VALIDATION,\n                                    cll, 2,\n                                    cll, 2,\n                                    cll, 2,\n                                    cll, 2,\n                                    &txnid, vc, 3), * tm_r = NULL;\n    serialize_txn_message(tm, &buf_w, &len_w, 1, vc);\n    write_read_from_file(buf_w, len_w, buf_r, &len_r);\n    deserialize_server_message(((int *) buf_r + 1), len_r - sizeof(int), (void *) &tm_r, &mtype, &vc_r);\n    assert(mtype == RPC_TYPE_TXN);\n\n    printf(\"Txn Message: %s (%s)\\n\", to_string_txn_message(tm, err_msg), to_string_vc(vc_r, err_msg2));\n    if(!equals_txn_message(tm, tm_r))\n    {\n        printf(\"Txn Message read mismatch (%s)!\\n\", to_string_txn_message(tm_r, err_msg));\n        assert(0);\n    }\n    if(compare_vc(vc, vc_r) != 0)\n    {\n        printf(\"VC read mismatch (%s)!\\n\", to_string_vc(vc_r, err_msg));\n        assert(0);\n    }\n}\n\n\n\n\n\n"
  },
  {
    "path": "backend/failure_detector/db_queries.c",
    "content": "/*\n * Copyright (C) 2019-2021 Deutsche Telekom AG\n *\n * Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:\n *\n * 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.\n *\n * 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.\n *\n * 3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission.\n *\n * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS \"AS IS\" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n */\n\n/*\n * db_queries.c\n *\n *      Author: aagapi\n */\n\n#include \"db_queries.h\"\n#include \"db_messages.pb-c.h\"\n#include \"../log.h\"\n\n#include <stdlib.h>\n#include <stdio.h>\n#include <string.h>\n#include <limits.h>\n#include <assert.h>\n\nvoid free_server_msg(ServerMessage * m);\nvoid free_client_msg(ClientMessage * m);\n\n// Write Query:\n\nwrite_query * init_write_query(cell * cell, int msg_type, uuid_t * txnid, int64_t nonce)\n{\n    write_query * ca = (write_query *) malloc(sizeof(write_query));\n    ca->cell = cell;\n    ca->msg_type = msg_type;\n    ca->txnid = txnid;\n    ca->nonce = nonce;\n    return ca;\n}\n\nwrite_query * init_write_query_copy(cell * cell, int msg_type, uuid_t * txnid, int64_t nonce)\n{\n    write_query * ca = (write_query *) malloc(sizeof(write_query));\n    ca->cell = (cell != NULL)?(init_cell_copy(cell->table_key, cell->keys, cell->no_keys, cell->columns, cell->no_columns, cell->last_blob, cell->last_blob_size, cell->version)):(NULL);\n    ca->msg_type = msg_type;\n    if(txnid != NULL)\n    {\n        ca->txnid = malloc(sizeof(uuid_t));\n        memcpy(ca->txnid, txnid, sizeof(uuid_t));\n    }\n    else\n    {\n        ca->txnid = NULL;\n    }\n    ca->nonce = nonce;\n    return ca;\n}\n\nwrite_query * build_insert_in_txn(WORD * column_values, int no_cols, int no_primary_keys, int no_clustering_keys, WORD blob, size_t blob_size, WORD table_key, uuid_t * txnid, int64_t nonce)\n{\n    int no_keys = no_primary_keys + no_clustering_keys;\n    assert(no_cols > no_keys || (blob != NULL && blob_size > 0));\n    cell * c = init_cell((int64_t) table_key, (int64_t *) column_values, no_keys, ((int64_t *) column_values + no_keys), no_cols - no_keys, blob, blob_size, NULL);\n    return init_write_query_copy(c, RPC_TYPE_WRITE, txnid, nonce);\n}\n\nwrite_query * build_delete_row_in_txn(WORD* primary_keys, int no_primary_keys, WORD table_key, uuid_t * txnid, int64_t nonce)\n{\n    cell * c = init_cell((int64_t) table_key, (int64_t *) primary_keys, no_primary_keys, NULL, 0, NULL, 0, NULL);\n    return init_write_query_copy(c, RPC_TYPE_DELETE, txnid, nonce);\n}\n\nwrite_query * build_delete_cell_in_txn(WORD* keys, int no_primary_keys, int no_clustering_keys, WORD table_key, uuid_t * txnid, int64_t nonce)\n{\n    cell * c = init_cell((int64_t) table_key, (int64_t *) keys, no_primary_keys + no_clustering_keys, NULL, 0, NULL, 0, NULL);\n    return init_write_query_copy(c, RPC_TYPE_DELETE, txnid, nonce);\n}\n\nwrite_query * build_delete_by_index_in_txn(WORD index_key, int idx_idx, WORD table_key, uuid_t * txnid, int64_t nonce)\n{\n    assert (0); // Not supported\n    return 0;\n}\n\nwrite_query * build_update_in_txn(int * col_idxs, int no_cols, WORD * column_values, WORD blob, size_t blob_size, WORD table_key, uuid_t * txnid, int64_t nonce)\n{\n    assert (0); // Not supported\n    return 0;\n}\n\nvoid free_write_query(write_query * ca)\n{\n    free_cell(ca->cell);\n    free(ca);\n}\n\nvoid init_write_query_msg(WriteQueryMessage * msg, write_query * ca, VersionedCellMessage * vcell_msg)\n{\n    if(ca->txnid != NULL)\n    {\n        msg->txnid.len = sizeof(uuid_t);\n        msg->txnid.data = malloc(sizeof(uuid_t));\n        memcpy(msg->txnid.data, ca->txnid, sizeof(uuid_t));\n    }\n    else\n    {\n        msg->txnid.data = NULL;\n        msg->txnid.len = 0;\n    }\n    msg->nonce = ca->nonce;\n    msg->cell = vcell_msg;\n    msg->msg_type = ca->msg_type;\n}\n\nwrite_query * init_write_query_from_msg(WriteQueryMessage * msg)\n{\n    cell * cell = init_cell_from_msg(msg->cell);\n    write_query * c = init_write_query_copy(cell, msg->msg_type, (uuid_t *) msg->txnid.data, msg->nonce);\n    return c;\n}\n\nvoid free_write_query_msg(WriteQueryMessage * msg)\n{\n//  if(msg->txnid.data != NULL)\n//      free(msg->txnid.data);\n    if(msg->cell != NULL)\n        free_cell_msg(msg->cell);\n}\n\nint serialize_write_query(write_query * ca, void ** buf, unsigned * len, short for_server, vector_clock * vc)\n{\n    WriteQueryMessage msg = WRITE_QUERY_MESSAGE__INIT;\n    VersionedCellMessage vcell_msg = VERSIONED_CELL_MESSAGE__INIT;\n    VectorClockMessage vc_msg = VECTOR_CLOCK_MESSAGE__INIT;\n\n    if(ca->cell != NULL)\n        init_cell_msg(&vcell_msg, ca->cell, &vc_msg);\n    init_write_query_msg(&msg, ca, (ca->cell != NULL)?(&vcell_msg):(NULL));\n    msg.mtype = RPC_TYPE_WRITE;\n\n    if(for_server)\n    {\n        ServerMessage sm = SERVER_MESSAGE__INIT;\n        sm.mtype = RPC_TYPE_WRITE;\n        sm.wm = &msg;\n        sm.rm = NULL;\n        sm.rrm = NULL;\n        sm.qm = NULL;\n        sm.tm = NULL;\n        sm.gl = NULL;\n\n        if(vc != NULL)\n        {\n            VectorClockMessage lc_msg = VECTOR_CLOCK_MESSAGE__INIT;\n            init_vc_msg(&lc_msg, vc);\n            sm.vc = &lc_msg;\n        }\n        else\n        {\n            sm.vc = NULL;\n        }\n\n        *len = server_message__get_packed_size (&sm);\n        *len = (*len) + sizeof(int);\n        *buf = malloc (*len);\n        memset(*buf, 0 , *len);\n        *((int *)(*buf)) = (*len) - sizeof(int);\n        server_message__pack (&sm, (void *) ((int *)(*buf) + 1));\n\n        free_server_msg(&sm);\n    }\n    else\n    {\n        ClientMessage cm = CLIENT_MESSAGE__INIT;\n        cm.mtype = RPC_TYPE_WRITE;\n        cm.am = NULL;\n        cm.wm = &msg;\n        cm.rrrm = NULL;\n        cm.qm = NULL;\n        cm.tm = NULL;\n\n        if(vc != NULL)\n        {\n            VectorClockMessage lc_msg = VECTOR_CLOCK_MESSAGE__INIT;\n            init_vc_msg(&lc_msg, vc);\n            cm.vc = &lc_msg;\n        }\n        else\n        {\n            cm.vc = NULL;\n        }\n\n        *len = client_message__get_packed_size (&cm);\n        *len = (*len) + sizeof(int);\n        *buf = malloc (*len);\n        memset(*buf, 0 , *len);\n        *((int *)(*buf)) = (*len) - sizeof(int);\n        client_message__pack (&cm, (void *) ((int *)(*buf) + 1));\n\n        free_client_msg(&cm);\n    }\n\n    return 0;\n}\n\nint deserialize_write_query(void * buf, unsigned msg_len, write_query ** ca)\n{\n    WriteQueryMessage * msg = write_query_message__unpack (NULL, msg_len, buf);\n\n    if (msg == NULL) {\n        log_error(\"Error unpacking write query message, msg is NULL\");\n        return 1;\n    } else if (msg->mtype != RPC_TYPE_WRITE) {\n        log_error(\"Error unpacking write query message, msg->mtype is not RPC_TYPE_WRITE: %d\", msg->mtype);\n        return 1;\n    }\n\n    *ca = init_write_query_from_msg(msg);\n\n    write_query_message__free_unpacked(msg, NULL);\n\n    return 0;\n}\n\nchar * to_string_write_query(write_query * ca, char * msg_buff)\n{\n    char * crt_ptr = msg_buff;\n    char uuid_str[37];\n    if(ca->txnid != NULL)\n        uuid_unparse_lower(*(ca->txnid), uuid_str);\n    else\n        uuid_str[0]='\\0';\n\n    sprintf(crt_ptr, \"%s(txnid=%s, nonce=%\" PRId64 \", cell=\", (ca->msg_type == RPC_TYPE_WRITE)?(\"WriteQuery\"):(\"DeleteQuery\"), uuid_str, ca->nonce);\n    crt_ptr += strlen(crt_ptr);\n\n    if(ca->cell != NULL)\n    {\n        to_string_cell(ca->cell, crt_ptr);\n        crt_ptr += strlen(crt_ptr);\n    }\n\n    sprintf(crt_ptr, \")\");\n\n    return msg_buff;\n}\n\nint equals_write_query(write_query * ca1, write_query * ca2)\n{\n    if(ca1->nonce != ca2->nonce || ca1->msg_type != ca2->msg_type || !equals_cell(ca1->cell, ca2->cell))\n        return 0;\n\n    if(ca1->txnid != NULL && ca2->txnid && uuid_compare(*(ca1->txnid), *(ca2->txnid)))\n        return 0;\n\n    return 1;\n}\n\n\n// Read Query:\n\nread_query * init_read_query(cell_address * cell_address, uuid_t * txnid, int64_t nonce)\n{\n    read_query * ca = (read_query *) malloc(sizeof(read_query));\n    ca->cell_address = cell_address;\n    ca->txnid = txnid;\n    ca->nonce = nonce;\n    return ca;\n}\n\nread_query * init_read_query_copy(cell_address * cell_address, uuid_t * txnid, int64_t nonce)\n{\n    read_query * ca = (read_query *) malloc(sizeof(read_query));\n    ca->cell_address = init_cell_address_copy(cell_address->table_key, cell_address->keys, cell_address->no_keys);\n    if(txnid != NULL)\n    {\n        ca->txnid = malloc(sizeof(uuid_t));\n        memcpy(ca->txnid, txnid, sizeof(uuid_t));\n    }\n    else\n    {\n        ca->txnid = NULL;\n    }\n    ca->nonce = nonce;\n    return ca;\n}\n\nread_query * build_search_in_txn(WORD* primary_keys, int no_primary_keys, WORD table_key, uuid_t * txnid, int64_t nonce)\n{\n    cell_address * c = init_cell_address_copy((int64_t) table_key, (int64_t *) primary_keys, no_primary_keys);\n\n    return init_read_query_copy(c, txnid, nonce);\n}\n\nread_query * build_search_clustering_in_txn(WORD* primary_keys, int no_primary_keys, WORD* clustering_keys, int no_clustering_keys, WORD table_key, uuid_t * txnid, int64_t nonce)\n{\n    cell_address * c = init_cell_address_copy2((int64_t) table_key, (int64_t *) primary_keys, no_primary_keys, (int64_t *) clustering_keys, no_clustering_keys);\n\n    return init_read_query_copy(c, txnid, nonce);\n}\n\nread_query * build_search_columns_in_txn(WORD* primary_keys, int no_primary_keys, WORD* clustering_keys, int no_clustering_keys, WORD* col_keys, int no_columns, WORD table_key, uuid_t * txnid, int64_t nonce)\n{\n    assert(0); // Not supported\n    return NULL;\n}\n\nread_query * build_search_index_in_txn(WORD index_key, int idx_idx, WORD table_key, uuid_t * txnid, int64_t nonce)\n{\n    assert(0); // Not supported\n    return NULL;\n}\n\n\nvoid free_read_query(read_query * ca)\n{\n    free_cell_address(ca->cell_address);\n    free(ca);\n}\n\nvoid init_read_query_msg(ReadQueryMessage * msg, read_query * ca, CellAddressMessage * cell_address_msg)\n{\n    if(ca->txnid != NULL)\n    {\n        msg->txnid.len = sizeof(uuid_t);\n        msg->txnid.data = malloc(sizeof(uuid_t));\n        memcpy(msg->txnid.data, ca->txnid, sizeof(uuid_t));\n    }\n    else\n    {\n        msg->txnid.data = NULL;\n        msg->txnid.len = 0;\n    }\n    msg->nonce = ca->nonce;\n    msg->cell_address = cell_address_msg;\n}\n\nread_query * init_read_query_from_msg(ReadQueryMessage * msg)\n{\n    cell_address * cell_address = init_cell_address_from_msg(msg->cell_address);\n    read_query * c = init_read_query_copy(cell_address, (uuid_t *) msg->txnid.data, msg->nonce);\n    return c;\n}\n\nvoid free_read_query_msg(ReadQueryMessage * msg)\n{\n    free_cell_address_msg(msg->cell_address);\n//  if(msg->txnid.data != NULL)\n//      free(msg->txnid.data);\n}\n\nint serialize_read_query(read_query * ca, void ** buf, unsigned * len, vector_clock * vc)\n{\n    ReadQueryMessage msg = READ_QUERY_MESSAGE__INIT;\n    CellAddressMessage cell_address_msg = CELL_ADDRESS_MESSAGE__INIT;\n\n    init_cell_address_msg(&cell_address_msg, ca->cell_address);\n    init_read_query_msg(&msg, ca, &cell_address_msg);\n    msg.mtype = RPC_TYPE_READ;\n\n    ServerMessage sm = SERVER_MESSAGE__INIT;\n    sm.mtype = RPC_TYPE_READ;\n    sm.wm = NULL;\n    sm.rm = &msg;\n    sm.rrm = NULL;\n    sm.qm = NULL;\n    sm.tm = NULL;\n    sm.gl = NULL;\n\n    if(vc != NULL)\n    {\n        VectorClockMessage lc_msg = VECTOR_CLOCK_MESSAGE__INIT;\n        init_vc_msg(&lc_msg, vc);\n        sm.vc = &lc_msg;\n    }\n    else\n    {\n        sm.vc = NULL;\n    }\n\n    *len = server_message__get_packed_size (&sm);\n    *len = (*len) + sizeof(int);\n    *buf = malloc (*len);\n    memset(*buf, 0 , *len);\n    *((int *)(*buf)) = (*len) - sizeof(int);\n    server_message__pack (&sm, (void *) ((int *)(*buf) + 1));\n\n    free_server_msg(&sm);\n\n    return 0;\n}\n\nint deserialize_read_query(void * buf, unsigned msg_len, read_query ** ca)\n{\n    ReadQueryMessage * msg = read_query_message__unpack (NULL, msg_len, buf);\n\n    if (msg == NULL) {\n        log_error(\"Error unpacking read query message, msg is NULL\");\n        return 1;\n    } else if (msg->mtype != RPC_TYPE_READ) {\n        log_error(\"Error unpacking read query message, msg->mtype is not RPC_TYPE_READ: %d\", msg->mtype);\n        return 1;\n    }\n\n    *ca = init_read_query_from_msg(msg);\n\n    read_query_message__free_unpacked(msg, NULL);\n\n    return 0;\n}\n\nchar * to_string_read_query(read_query * ca, char * msg_buff)\n{\n    char * crt_ptr = msg_buff;\n    char uuid_str[37];\n    if(ca->txnid != NULL)\n        uuid_unparse_lower(*(ca->txnid), uuid_str);\n    else\n        uuid_str[0]='\\0';\n\n    sprintf(crt_ptr, \"ReadQuery(txnid=%s, nonce=%\" PRId64 \", \", uuid_str, ca->nonce);\n    crt_ptr += strlen(crt_ptr);\n\n    to_string_cell_address(ca->cell_address, crt_ptr);\n    crt_ptr += strlen(crt_ptr);\n\n    sprintf(crt_ptr, \")\");\n\n    return msg_buff;\n}\n\nint equals_read_query(read_query * ca1, read_query * ca2)\n{\n    if(ca1->nonce != ca2->nonce || !equals_cell_address(ca1->cell_address, ca2->cell_address))\n        return 0;\n\n    if(ca1->txnid != NULL && ca2->txnid && uuid_compare(*(ca1->txnid), *(ca2->txnid)))\n        return 0;\n\n    return 1;\n}\n\n// Range read query:\n\nrange_read_query * build_range_search_in_txn(WORD* start_primary_keys, WORD* end_primary_keys, int no_primary_keys, WORD table_key, uuid_t * txnid, int64_t nonce)\n{\n    cell_address * start_c = init_cell_address_copy((int64_t) table_key, (int64_t *) start_primary_keys, no_primary_keys);\n    cell_address * end_c = init_cell_address_copy((int64_t) table_key, (int64_t *) end_primary_keys, no_primary_keys);\n\n    return init_range_read_query_copy(start_c, end_c, txnid, nonce);\n}\n\nrange_read_query * build_range_search_clustering_in_txn(WORD* primary_keys, int no_primary_keys, WORD* start_clustering_keys, WORD* end_clustering_keys, int no_clustering_keys, WORD table_key, uuid_t * txnid, int64_t nonce)\n{\n    cell_address * start_c = init_cell_address_copy2((int64_t) table_key, (int64_t *) primary_keys, no_primary_keys, (int64_t *) start_clustering_keys, no_clustering_keys);\n    cell_address * end_c = init_cell_address_copy2((int64_t) table_key, (int64_t *) primary_keys, no_primary_keys, (int64_t *) end_clustering_keys, no_clustering_keys);\n\n    return init_range_read_query_copy(start_c, end_c, txnid, nonce);\n}\n\nrange_read_query * build_range_search_index_in_txn(int idx_idx, WORD start_idx_key, WORD end_idx_key, WORD table_key, uuid_t * txnid, int64_t nonce)\n{\n    assert(0); // Not supported\n    return NULL;\n}\n\nrange_read_query * build_wildcard_range_search_in_txn(WORD table_key, uuid_t * txnid, int64_t nonce)\n{\n    int64_t min_key = LONG_MIN;\n    int64_t max_key = LONG_MAX - 1;\n\n    cell_address * start_c = init_cell_address_copy((int64_t) table_key, &min_key, 1);\n    cell_address * end_c = init_cell_address_copy((int64_t) table_key, &max_key, 1);\n\n    return init_range_read_query_copy(start_c, end_c, txnid, nonce);\n}\n\nrange_read_query * init_range_read_query(cell_address * start_cell_address, cell_address * end_cell_address, uuid_t * txnid, int64_t nonce)\n{\n    range_read_query * ca = (range_read_query *) malloc(sizeof(range_read_query));\n    ca->start_cell_address = start_cell_address;\n    ca->end_cell_address = end_cell_address;\n    ca->txnid = txnid;\n    ca->nonce = nonce;\n    return ca;\n}\n\nvoid free_range_read_query(range_read_query * ca)\n{\n    free_cell_address(ca->start_cell_address);\n    free_cell_address(ca->end_cell_address);\n    free(ca);\n}\n\nrange_read_query * init_range_read_query_copy(cell_address * start_cell_address, cell_address * end_cell_address, uuid_t * txnid, int64_t nonce)\n{\n    range_read_query * ca = (range_read_query *) malloc(sizeof(range_read_query));\n    ca->start_cell_address = init_cell_address_copy(start_cell_address->table_key, start_cell_address->keys, start_cell_address->no_keys);\n    ca->end_cell_address = init_cell_address_copy(end_cell_address->table_key, end_cell_address->keys, end_cell_address->no_keys);\n    if(txnid != NULL)\n    {\n        ca->txnid = malloc(sizeof(uuid_t));\n        memcpy(ca->txnid, txnid, sizeof(uuid_t));\n    }\n    else\n    {\n        ca->txnid = NULL;\n    }\n    ca->nonce = nonce;\n    return ca;\n}\n\nvoid init_range_read_query_msg(RangeReadQueryMessage * msg, range_read_query * ca, CellAddressMessage * start_cell_address_msg, CellAddressMessage * end_cell_address_msg)\n{\n    if(ca->txnid != NULL)\n    {\n        msg->txnid.len = sizeof(uuid_t);\n        msg->txnid.data = malloc(sizeof(uuid_t));\n        memcpy(msg->txnid.data, ca->txnid, sizeof(uuid_t));\n    }\n    else\n    {\n        msg->txnid.data = NULL;\n        msg->txnid.len = 0;\n    }\n    msg->nonce = ca->nonce;\n    msg->start_cell_address = start_cell_address_msg;\n    msg->end_cell_address = end_cell_address_msg;\n}\n\nrange_read_query * init_range_read_query_from_msg(RangeReadQueryMessage * msg)\n{\n    cell_address * start_cell_address = init_cell_address_from_msg(msg->start_cell_address);\n    cell_address * end_cell_address = init_cell_address_from_msg(msg->end_cell_address);\n    range_read_query * c = init_range_read_query_copy(start_cell_address, end_cell_address, (uuid_t *) msg->txnid.data, msg->nonce);\n    return c;\n}\n\nvoid free_range_read_query_msg(RangeReadQueryMessage * msg)\n{\n    free_cell_address_msg(msg->start_cell_address);\n    free_cell_address_msg(msg->end_cell_address);\n//  if(msg->txnid.data != NULL)\n//      free(msg->txnid.data);\n}\n\nint serialize_range_read_query(range_read_query * ca, void ** buf, unsigned * len, vector_clock * vc)\n{\n    RangeReadQueryMessage msg = RANGE_READ_QUERY_MESSAGE__INIT;\n    CellAddressMessage start_cell_address_msg = CELL_ADDRESS_MESSAGE__INIT;\n    CellAddressMessage end_cell_address_msg = CELL_ADDRESS_MESSAGE__INIT;\n\n    init_cell_address_msg(&start_cell_address_msg, ca->start_cell_address);\n    init_cell_address_msg(&end_cell_address_msg, ca->end_cell_address);\n    init_range_read_query_msg(&msg, ca, &start_cell_address_msg, &end_cell_address_msg);\n    msg.mtype = RPC_TYPE_RANGE_READ;\n\n    ServerMessage sm = SERVER_MESSAGE__INIT;\n    sm.mtype = RPC_TYPE_RANGE_READ;\n    sm.wm = NULL;\n    sm.rm = NULL;\n    sm.rrm = &msg;\n    sm.qm = NULL;\n    sm.tm = NULL;\n    sm.gl = NULL;\n\n    if(vc != NULL)\n    {\n        VectorClockMessage lc_msg = VECTOR_CLOCK_MESSAGE__INIT;\n        init_vc_msg(&lc_msg, vc);\n        sm.vc = &lc_msg;\n    }\n    else\n    {\n        sm.vc = NULL;\n    }\n\n    *len = server_message__get_packed_size (&sm);\n    *len = (*len) + sizeof(int);\n    *buf = malloc (*len);\n    memset(*buf, 0 , *len);\n    *((int *)(*buf)) = (*len) - sizeof(int);\n    server_message__pack (&sm, (void *) ((int *)(*buf) + 1));\n\n    free_server_msg(&sm);\n\n    return 0;\n}\n\nint deserialize_range_read_query(void * buf, unsigned msg_len, range_read_query ** ca)\n{\n    RangeReadQueryMessage * msg = range_read_query_message__unpack (NULL, msg_len, buf);\n\n    if (msg == NULL) {\n        log_error(\"Error unpacking range read query message, msg is NULL\");\n    } else if (msg->mtype != RPC_TYPE_RANGE_READ) {\n        log_error(\"Error unpacking range read query message, msg->mtype is not RPC_TYPE_RANGE_READ: %d\", msg->mtype);\n        return 1;\n    }\n\n    *ca = init_range_read_query_from_msg(msg);\n\n    range_read_query_message__free_unpacked(msg, NULL);\n\n    return 0;\n}\n\nchar * to_string_range_read_query(range_read_query * ca, char * msg_buff)\n{\n    char * crt_ptr = msg_buff;\n    char uuid_str[37];\n    if(ca->txnid != NULL)\n        uuid_unparse_lower(*(ca->txnid), uuid_str);\n    else\n        uuid_str[0]='\\0';\n\n    sprintf(crt_ptr, \"RangeReadQuery(txnid=%s, nonce=%\" PRId64 \", start_key=\", uuid_str, ca->nonce);\n    crt_ptr += strlen(crt_ptr);\n\n    to_string_cell_address(ca->start_cell_address, crt_ptr);\n    crt_ptr += strlen(crt_ptr);\n\n    sprintf(crt_ptr, \", end_key=\");\n    crt_ptr += strlen(crt_ptr);\n\n    to_string_cell_address(ca->end_cell_address, crt_ptr);\n    crt_ptr += strlen(crt_ptr);\n\n    sprintf(crt_ptr, \")\");\n\n    return msg_buff;\n}\n\nint equals_range_read_query(range_read_query * ca1, range_read_query * ca2)\n{\n    if(ca1->nonce != ca2->nonce ||\n        !equals_cell_address(ca1->start_cell_address, ca2->start_cell_address) ||\n        !equals_cell_address(ca1->end_cell_address, ca2->end_cell_address))\n        return 0;\n\n    if(ca1->txnid != NULL && ca2->txnid && uuid_compare(*(ca1->txnid), *(ca2->txnid)))\n        return 0;\n\n    return 1;\n}\n\n\n// Ack Message:\n\nack_message * init_ack_message(cell_address * cell_address, int status, uuid_t * txnid, int64_t nonce)\n{\n    ack_message * ca = (ack_message *) malloc(sizeof(ack_message));\n    ca->cell_address = cell_address;\n    ca->status = status;\n    ca->txnid = txnid;\n    ca->nonce = nonce;\n    return ca;\n}\n\nack_message * init_ack_message_copy(cell_address * cell_address, int status, uuid_t * txnid, int64_t nonce)\n{\n    ack_message * ca = (ack_message *) malloc(sizeof(ack_message));\n    ca->cell_address = (cell_address != NULL)?(init_cell_address_copy(cell_address->table_key, cell_address->keys, cell_address->no_keys)):(NULL);\n    ca->status = status;\n    if(txnid != NULL)\n    {\n        ca->txnid = malloc(sizeof(uuid_t));\n        memcpy(ca->txnid, txnid, sizeof(uuid_t));\n    }\n    else\n    {\n        ca->txnid = NULL;\n    }\n    ca->nonce = nonce;\n    return ca;\n}\n\nvoid free_ack_message(ack_message * ca)\n{\n    if(ca->cell_address != NULL)\n        free_cell_address(ca->cell_address);\n    free(ca);\n}\n\nvoid init_ack_message_msg(AckMessage * msg, ack_message * ca, CellAddressMessage * cell_address_msg)\n{\n    msg->status = ca->status;\n    if(ca->txnid != NULL)\n    {\n        msg->txnid.len = sizeof(uuid_t);\n        msg->txnid.data = malloc(sizeof(uuid_t));\n        memcpy(msg->txnid.data, ca->txnid, sizeof(uuid_t));\n    }\n    else\n    {\n        msg->txnid.data = NULL;\n        msg->txnid.len = 0;\n    }\n    msg->nonce = ca->nonce;\n    msg->cell_address = cell_address_msg;\n}\n\nack_message * init_ack_message_from_msg(AckMessage * msg)\n{\n    cell_address * cell_address = (msg->cell_address != NULL)?(init_cell_address_from_msg(msg->cell_address)):(NULL);\n    ack_message * c = init_ack_message_copy(cell_address, msg->status, (uuid_t *) msg->txnid.data, msg->nonce);\n    return c;\n}\n\nvoid free_ack_message_msg(AckMessage * msg)\n{\n    if(msg->cell_address != NULL)\n        free_cell_address_msg(msg->cell_address);\n//  if(msg->txnid.data != NULL)\n//      free(msg->txnid.data);\n}\n\nint serialize_ack_message(ack_message * ca, void ** buf, unsigned * len, vector_clock * vc)\n{\n    AckMessage msg = ACK_MESSAGE__INIT;\n    CellAddressMessage cell_address_msg = CELL_ADDRESS_MESSAGE__INIT;\n\n    if(ca->cell_address != NULL)\n        init_cell_address_msg(&cell_address_msg, ca->cell_address);\n    init_ack_message_msg(&msg, ca, (ca->cell_address != NULL)?(&cell_address_msg):(NULL));\n    msg.mtype = RPC_TYPE_ACK;\n\n    ClientMessage cm = CLIENT_MESSAGE__INIT;\n    cm.mtype = RPC_TYPE_ACK;\n    cm.am = &msg;\n    cm.wm = NULL;\n    cm.rrrm = NULL;\n    cm.qm = NULL;\n    cm.tm = NULL;\n\n    if(vc != NULL)\n    {\n        VectorClockMessage lc_msg = VECTOR_CLOCK_MESSAGE__INIT;\n        init_vc_msg(&lc_msg, vc);\n        cm.vc = &lc_msg;\n    }\n    else\n    {\n        cm.vc = NULL;\n    }\n\n    *len = client_message__get_packed_size (&cm);\n    *len = (*len) + sizeof(int);\n    *buf = malloc (*len);\n    memset(*buf, 0 , *len);\n    *((int *)(*buf)) = (*len) - sizeof(int);\n    client_message__pack (&cm, (void *) ((int *)(*buf) + 1));\n\n    free_client_msg(&cm);\n\n    return 0;\n}\n\nint deserialize_ack_message(void * buf, unsigned msg_len, ack_message ** ca)\n{\n    AckMessage * msg = ack_message__unpack (NULL, msg_len, buf);\n    char print_buff[100];\n\n    if (msg == NULL) {\n        log_error(\"Error unpacking ack query message, msg is NULL\");\n        return 1;\n    } else if (msg->mtype != RPC_TYPE_ACK) {\n        log_error(\"Error unpacking ack query message, msg->mtype is not RPC_TYPE_ACK: %d\", msg->mtype);\n        return 1;\n    }\n\n    *ca = init_ack_message_from_msg(msg);\n\n//  to_string_ack_message(*ca, (char *) print_buff);\n//  log_debug(\"Received ACK message: %s\", print_buff);\n\n    ack_message__free_unpacked(msg, NULL);\n\n    return 0;\n}\n\nchar * to_string_ack_message(ack_message * ca, char * msg_buff)\n{\n    char * crt_ptr = msg_buff;\n    char uuid_str[37];\n    if(ca->txnid != NULL)\n        uuid_unparse_lower(*(ca->txnid), uuid_str);\n    else\n        uuid_str[0]='\\0';\n\n    sprintf(crt_ptr, \"AckMessage(status=%d, txnid=%s, nonce=%\" PRId64 \", \", ca->status, uuid_str, ca->nonce);\n    crt_ptr += strlen(crt_ptr);\n\n    if(ca->cell_address != NULL)\n    {\n        to_string_cell_address(ca->cell_address, crt_ptr);\n        crt_ptr += strlen(crt_ptr);\n    }\n\n    sprintf(crt_ptr, \")\");\n\n    return msg_buff;\n}\n\nint equals_ack_message(ack_message * ca1, ack_message * ca2)\n{\n    if(ca1->nonce != ca2->nonce || ca1->status != ca2->status ||\n        !equals_cell_address(ca1->cell_address, ca2->cell_address))\n        return 0;\n\n    if(ca1->txnid != NULL && ca2->txnid && uuid_compare(*(ca1->txnid), *(ca2->txnid)))\n        return 0;\n\n    return 1;\n}\n\n// Range read response:\n\nrange_read_response_message * init_range_read_response_message(cell * cells, int no_cells, uuid_t * txnid, int64_t nonce)\n{\n    range_read_response_message * ca = (range_read_response_message *) malloc(sizeof(range_read_response_message));\n    ca->cells = cells;\n    ca->no_cells = no_cells;\n    ca->txnid = txnid;\n    ca->nonce = nonce;\n    return ca;\n}\n\nrange_read_response_message * init_range_read_response_message_copy(cell * cells, int no_cells, uuid_t * txnid, int64_t nonce)\n{\n    range_read_response_message * ca = (range_read_response_message *) malloc(sizeof(range_read_response_message));\n    ca->no_cells = no_cells;\n    ca->cells = (cell *) malloc(no_cells * sizeof(cell));\n    for(int i=0;i<no_cells;i++)\n    {\n        copy_cell(ca->cells + i, cells[i].table_key, cells[i].keys, cells[i].no_keys, cells[i].columns, cells[i].no_columns, cells[i].last_blob, cells[i].last_blob_size, cells[i].version);\n    }\n    if(txnid != NULL)\n    {\n        ca->txnid = malloc(sizeof(uuid_t));\n        memcpy(ca->txnid, txnid, sizeof(uuid_t));\n    }\n    else\n    {\n        ca->txnid = NULL;\n    }\n    ca->nonce = nonce;\n    return ca;\n}\n\nvoid init_range_read_response_message_msg(RangeReadResponseMessage * msg, range_read_response_message * ca)\n{\n    if(ca->txnid != NULL)\n    {\n        msg->txnid.len = sizeof(uuid_t);\n        msg->txnid.data = malloc(sizeof(uuid_t));\n        memcpy(msg->txnid.data, ca->txnid, sizeof(uuid_t));\n    }\n    else\n    {\n        msg->txnid.data = NULL;\n        msg->txnid.len = 0;\n    }\n    msg->nonce = ca->nonce;\n    msg->n_cells = ca->no_cells;\n\n    msg->cells = (VersionedCellMessage **) malloc(msg->n_cells * sizeof (VersionedCellMessage*));\n    VectorClockMessage ** vcs = (VectorClockMessage **) malloc(msg->n_cells * sizeof (VectorClockMessage*));\n\n    for(int i=0;i<ca->no_cells;i++)\n    {\n        msg->cells[i] = malloc (sizeof (VersionedCellMessage));\n        versioned_cell_message__init(msg->cells[i]);\n        vcs[i] = malloc (sizeof (VectorClockMessage));\n        vector_clock_message__init(vcs[i]);\n        init_cell_msg(msg->cells[i], ca->cells+i, vcs[i]);\n    }\n\n    free(vcs);\n}\n\nrange_read_response_message * init_range_read_response_message_from_msg(RangeReadResponseMessage * msg)\n{\n    cell * cells = (cell *) malloc(msg->n_cells * sizeof(cell));\n    for(int i=0;i<msg->n_cells;i++)\n        copy_cell_from_msg(cells + i, msg->cells[i]);\n\n    range_read_response_message * c = init_range_read_response_message_copy(cells, msg->n_cells, (uuid_t *) msg->txnid.data, msg->nonce);\n    return c;\n}\n\nvoid free_range_read_response_message_msg(RangeReadResponseMessage * msg)\n{\n    for(int i=0;i<msg->n_cells;i++)\n        free_cell_msg(msg->cells[i]);\n\n    if(msg->cells != NULL)\n        free(msg->cells);\n\n//  if(msg->txnid.data != NULL)\n//      free(msg->txnid.data);\n}\n\nvoid free_range_read_response_message(range_read_response_message * ca)\n{\n    for(int i=0;i<ca->no_cells;i++)\n        free_cell_ptrs(ca->cells + i);\n\n    if(ca->cells != NULL)\n        free(ca->cells);\n\n    free(ca);\n}\n\nint serialize_range_read_response_message(range_read_response_message * ca, void ** buf, unsigned * len, vector_clock * vc)\n{\n    RangeReadResponseMessage msg = RANGE_READ_RESPONSE_MESSAGE__INIT;\n\n    init_range_read_response_message_msg(&msg, ca);\n    msg.mtype = RPC_TYPE_RANGE_READ_RESPONSE;\n\n    ClientMessage cm = CLIENT_MESSAGE__INIT;\n    cm.mtype = RPC_TYPE_RANGE_READ_RESPONSE;\n    cm.am = NULL;\n    cm.wm = NULL;\n    cm.rrrm = &msg;\n    cm.qm = NULL;\n    cm.tm = NULL;\n\n    if(vc != NULL)\n    {\n        VectorClockMessage lc_msg = VECTOR_CLOCK_MESSAGE__INIT;\n        init_vc_msg(&lc_msg, vc);\n        cm.vc = &lc_msg;\n    }\n    else\n    {\n        cm.vc = NULL;\n    }\n\n    *len = client_message__get_packed_size (&cm);\n    *len = (*len) + sizeof(int);\n    *buf = malloc (*len);\n    memset(*buf, 0 , *len);\n    *((int *)(*buf)) = (*len) - sizeof(int);\n    client_message__pack (&cm, (void *) ((int *)(*buf) + 1));\n\n    free_client_msg(&cm);\n\n    return 0;\n}\n\nint deserialize_range_read_response_message(void * buf, unsigned msg_len, range_read_response_message ** ca)\n{\n    RangeReadResponseMessage * msg = range_read_response_message__unpack (NULL, msg_len, buf);\n\n    if (msg == NULL) {\n        log_error(\"Error unpacking range read response message, msg is NULL\");\n        return 1;\n    } else if (msg->mtype != RPC_TYPE_RANGE_READ_RESPONSE) {\n        log_error(\"Error unpacking range read response message, msg->mtype is not RPC_TYPE_RANGE_READ_RESPONSE: %d\", msg->mtype);\n        return 1;\n    }\n\n    *ca = init_range_read_response_message_from_msg(msg);\n\n    range_read_response_message__free_unpacked(msg, NULL);\n\n    return 0;\n}\n\n\nchar * to_string_range_read_response_message(range_read_response_message * ca, char * msg_buff)\n{\n    char * crt_ptr = msg_buff;\n    char uuid_str[37];\n    if(ca->txnid != NULL)\n        uuid_unparse_lower(*(ca->txnid), uuid_str);\n    else\n        uuid_str[0]='\\0';\n\n    sprintf(crt_ptr, \"RangeReadResponseMessage(txnid=%s, nonce=%\" PRId64 \"\", uuid_str, ca->nonce);\n    crt_ptr += strlen(crt_ptr);\n\n    sprintf(crt_ptr, \", cells={\");\n    crt_ptr += strlen(crt_ptr);\n    for(int i=0;i<ca->no_cells;i++)\n    {\n        if(crt_ptr - msg_buff > MAX_PRINT_BUFF - 10)\n        {\n            sprintf(crt_ptr, \"..\");\n            crt_ptr += strlen(crt_ptr);\n            break;\n        }\n\n        to_string_cell(ca->cells+i, crt_ptr);\n        crt_ptr += strlen(crt_ptr);\n        sprintf(crt_ptr, \", \");\n        crt_ptr += strlen(crt_ptr);\n    }\n\n    sprintf(crt_ptr, \"} )\");\n\n    return msg_buff;\n}\n\nint equals_range_read_response_message(range_read_response_message * ca1, range_read_response_message * ca2)\n{\n    if(ca1->nonce != ca2->nonce || ca1->no_cells != ca2->no_cells)\n        return 0;\n\n    if(ca1->txnid != NULL && ca2->txnid && uuid_compare(*(ca1->txnid), *(ca2->txnid)))\n        return 0;\n\n    for(int i=0;i<ca1->no_cells;i++)\n        if(!equals_cell(ca1->cells+i, ca2->cells+i))\n            return 0;\n\n    return 1;\n}\n\n\n// Queue query (and response) messages:\n\nqueue_query_message * init_query_message_basic(cell_address * cell_address, uuid_t * txnid, int64_t nonce)\n{\n    queue_query_message * ca = (queue_query_message *) malloc(sizeof(queue_query_message));\n    ca->cells = NULL;\n    ca->no_cells = 0;\n    ca->cell_address = cell_address;\n    ca->queue_index = -1;\n    ca->app_id = -1;\n    ca->shard_id = -1;\n    ca->consumer_id = -1;\n    ca->group_id = -1;\n    ca->status = -1;\n    if(txnid != NULL)\n    {\n        ca->txnid = malloc(sizeof(uuid_t));\n        memcpy(ca->txnid, txnid, sizeof(uuid_t));\n    }\n    else\n    {\n        ca->txnid = NULL;\n    }\n    ca->nonce = nonce;\n    return ca;\n}\n\nqueue_query_message * build_enqueue_in_txn(WORD * column_values, int no_cols, WORD blob, size_t blob_size, WORD table_key, WORD queue_id, uuid_t * txnid, int64_t nonce)\n{\n    cell_address * c = init_cell_address_single_key_copy((int64_t) table_key, (int64_t) queue_id);\n    cell * entry = init_cell_copy((int64_t) table_key, (int64_t *) column_values, 0, (int64_t *) column_values, no_cols, blob, blob_size, NULL);\n\n    return init_enqueue_message(c, entry, 1, txnid, nonce);\n}\n\nqueue_query_message * build_read_queue_in_txn(WORD consumer_id, WORD shard_id, WORD app_id, WORD table_key, WORD queue_id,\n                                                int max_entries, uuid_t * txnid, int64_t nonce)\n{\n    cell_address * c = init_cell_address_single_key_copy((int64_t) table_key, (int64_t) queue_id);\n    return init_read_queue_message(c, (int64_t) app_id, (int64_t) shard_id, (int64_t) consumer_id, (int64_t) max_entries, txnid, nonce);\n\n}\n\nqueue_query_message * build_consume_queue_in_txn(WORD consumer_id, WORD shard_id, WORD app_id, WORD table_key, WORD queue_id,\n                                                    int64_t new_consume_head, uuid_t * txnid, int64_t nonce)\n{\n    cell_address * c = init_cell_address_single_key_copy((int64_t) table_key, (int64_t) queue_id);\n    return init_consume_queue_message(c, (int64_t) app_id, (int64_t) shard_id, (int64_t) consumer_id, new_consume_head, txnid, nonce);\n}\n\nqueue_query_message * build_create_queue_in_txn(WORD table_key, WORD queue_id, uuid_t * txnid, int64_t nonce)\n{\n    cell_address * c = init_cell_address_single_key_copy((int64_t) table_key, (int64_t) queue_id);\n    return init_create_queue_message(c, txnid, nonce);\n}\n\nqueue_query_message * build_delete_queue_in_txn(WORD table_key, WORD queue_id, uuid_t * txnid, int64_t nonce)\n{\n    cell_address * c = init_cell_address_single_key_copy((int64_t) table_key, (int64_t) queue_id);\n    return init_delete_queue_message(c, txnid, nonce);\n}\n\nqueue_query_message * build_subscribe_queue_in_txn(WORD consumer_id, WORD shard_id, WORD app_id, WORD table_key, WORD queue_id, uuid_t * txnid, int64_t nonce)\n{\n    cell_address * c = init_cell_address_single_key_copy((int64_t) table_key, (int64_t) queue_id);\n    return init_subscribe_queue_message(c, (int64_t) app_id, (int64_t) shard_id, (int64_t) consumer_id, -1, txnid, nonce);\n}\n\nqueue_query_message * build_unsubscribe_queue_in_txn(WORD consumer_id, WORD shard_id, WORD app_id, WORD table_key, WORD queue_id, uuid_t * txnid, int64_t nonce)\n{\n    cell_address * c = init_cell_address_single_key_copy((int64_t) table_key, (int64_t) queue_id);\n    return init_unsubscribe_queue_message(c, (int64_t) app_id, (int64_t) shard_id, (int64_t) consumer_id, -1, txnid, nonce);\n}\n\nqueue_query_message * build_subscribe_group_in_txn(WORD consumer_id, WORD shard_id, WORD app_id, WORD group_id, uuid_t * txnid, int64_t nonce)\n{\n    cell_address * c = init_cell_address_single_key_copy((int64_t) -1, (int64_t) -1);\n    return init_subscribe_queue_message(c, (int64_t) app_id, (int64_t) shard_id, (int64_t) consumer_id, (int64_t) group_id, txnid, nonce);\n}\n\nqueue_query_message * build_unsubscribe_group_in_txn(WORD consumer_id, WORD shard_id, WORD app_id, WORD group_id, uuid_t * txnid, int64_t nonce)\n{\n    cell_address * c = init_cell_address_single_key_copy((int64_t) -1, (int64_t) -1);\n    return init_unsubscribe_queue_message(c, (int64_t) app_id, (int64_t) shard_id, (int64_t) consumer_id, (int64_t) group_id, txnid, nonce);\n}\n\nqueue_query_message * build_add_queue_to_group_in_txn(WORD table_key, WORD queue_id, WORD group_id, uuid_t * txnid, int64_t nonce)\n{\n    cell_address * c = init_cell_address_single_key_copy((int64_t) table_key, (int64_t) queue_id);\n    return init_add_queue_to_group_message(c, (int64_t) group_id, txnid, nonce);\n}\n\nqueue_query_message * build_remove_queue_from_group_in_txn(WORD table_key, WORD queue_id, WORD group_id, uuid_t * txnid, int64_t nonce)\n{\n    cell_address * c = init_cell_address_single_key_copy((int64_t) table_key, (int64_t) queue_id);\n    return init_remove_queue_from_group_message(c, (int64_t) group_id, txnid, nonce);\n}\n\n\nqueue_query_message * init_create_queue_message(cell_address * cell_address, uuid_t * txnid, int64_t nonce)\n{\n    queue_query_message * ca = init_query_message_basic(cell_address, txnid, nonce);\n    ca->msg_type = QUERY_TYPE_CREATE_QUEUE;\n    return ca;\n}\n\nqueue_query_message * init_delete_queue_message(cell_address * cell_address, uuid_t * txnid, int64_t nonce)\n{\n    queue_query_message * ca = init_query_message_basic(cell_address, txnid, nonce);\n    ca->msg_type = QUERY_TYPE_DELETE_QUEUE;\n    return ca;\n}\n\nqueue_query_message * init_subscribe_queue_message(cell_address * cell_address, int app_id, int shard_id, int consumer_id, int group_id, uuid_t * txnid, int64_t nonce)\n{\n    queue_query_message * ca = init_query_message_basic(cell_address, txnid, nonce);\n    ca->msg_type = QUERY_TYPE_SUBSCRIBE_QUEUE;\n    ca->app_id = app_id;\n    ca->shard_id = shard_id;\n    ca->consumer_id = consumer_id;\n    ca->group_id = group_id;\n    return ca;\n}\n\nqueue_query_message * init_unsubscribe_queue_message(cell_address * cell_address, int app_id, int shard_id, int consumer_id, int group_id, uuid_t * txnid, int64_t nonce)\n{\n    queue_query_message * ca = init_query_message_basic(cell_address, txnid, nonce);\n    ca->msg_type = QUERY_TYPE_UNSUBSCRIBE_QUEUE;\n    ca->app_id = app_id;\n    ca->shard_id = shard_id;\n    ca->consumer_id = consumer_id;\n    ca->group_id = group_id;\n    return ca;\n}\n\nqueue_query_message * init_add_queue_to_group_message(cell_address * cell_address, int group_id, uuid_t * txnid, int64_t nonce)\n{\n    queue_query_message * ca = init_query_message_basic(cell_address, txnid, nonce);\n    ca->msg_type = QUERY_TYPE_ADD_QUEUE_TO_GROUP;\n    ca->group_id = group_id;\n    return ca;\n}\n\nqueue_query_message * init_remove_queue_from_group_message(cell_address * cell_address, int group_id, uuid_t * txnid, int64_t nonce)\n{\n    queue_query_message * ca = init_query_message_basic(cell_address, txnid, nonce);\n    ca->msg_type = QUERY_TYPE_REMOVE_QUEUE_FROM_GROUP;\n    ca->group_id = group_id;\n    return ca;\n}\n\nqueue_query_message * init_enqueue_message(cell_address * cell_address, cell * cells, int no_cells, uuid_t * txnid, int64_t nonce)\n{\n    queue_query_message * ca = init_query_message_basic(cell_address, txnid, nonce);\n    ca->msg_type = QUERY_TYPE_ENQUEUE;\n    ca->cells = cells;\n    ca->no_cells = no_cells;\n    return ca;\n}\n\nqueue_query_message * init_read_queue_message(cell_address * cell_address, int app_id, int shard_id, int consumer_id, int64_t max_entries, uuid_t * txnid, int64_t nonce)\n{\n    queue_query_message * ca = init_query_message_basic(cell_address, txnid, nonce);\n    ca->msg_type = QUERY_TYPE_READ_QUEUE;\n    ca->queue_index = max_entries;\n    ca->app_id = app_id;\n    ca->shard_id = shard_id;\n    ca->consumer_id = consumer_id;\n    ca->group_id = -1;\n    return ca;\n}\n\nqueue_query_message * init_consume_queue_message(cell_address * cell_address, int app_id, int shard_id, int consumer_id, int64_t new_consume_head, uuid_t * txnid, int64_t nonce)\n{\n    queue_query_message * ca = init_query_message_basic(cell_address, txnid, nonce);\n    ca->msg_type = QUERY_TYPE_CONSUME_QUEUE;\n    ca->queue_index = new_consume_head;\n    ca->app_id = app_id;\n    ca->shard_id = shard_id;\n    ca->consumer_id = consumer_id;\n    ca->group_id = -1;\n    return ca;\n}\n\nqueue_query_message * init_read_queue_response(cell_address * cell_address, cell * cells, int no_cells, int app_id, int shard_id, int consumer_id, int group_id, int64_t new_read_head, short status, uuid_t * txnid, int64_t nonce)\n{\n    queue_query_message * ca = init_query_message_basic(cell_address, txnid, nonce);\n    ca->msg_type = QUERY_TYPE_READ_QUEUE_RESPONSE;\n    ca->queue_index = new_read_head;\n    ca->app_id = app_id;\n    ca->shard_id = shard_id;\n    ca->consumer_id = consumer_id;\n    ca->group_id = group_id;\n    ca->cells = cells;\n    ca->no_cells = no_cells;\n    ca->status = status;\n    return ca;\n\n}\n\nqueue_query_message * init_queue_notification(cell_address * cell_address, cell * cells, int no_cells, int app_id, int shard_id, int consumer_id, int group_id, int64_t new_no_entries, short status, uuid_t * txnid, int64_t nonce)\n{\n    queue_query_message * ca = init_query_message_basic(cell_address, txnid, nonce);\n    ca->msg_type = QUERY_TYPE_QUEUE_NOTIFICATION;\n    ca->queue_index = new_no_entries;\n    ca->app_id = app_id;\n    ca->shard_id = shard_id;\n    ca->consumer_id = consumer_id;\n    ca->group_id = group_id;\n    ca->cells = cells;\n    ca->no_cells = no_cells;\n    ca->status = status;\n    return ca;\n\n}\n\nvoid free_queue_message(queue_query_message * ca)\n{\n    for(int i=0;i<ca->no_cells;i++)\n        free_cell_ptrs(ca->cells + i);\n\n    if(ca->cells != NULL)\n        free(ca->cells);\n\n    free(ca);\n}\n\nvoid init_queue_message_msg(QueueQueryMessage * msg, queue_query_message * ca, CellAddressMessage * cell_address_msg)\n{\n    VectorClockMessage ** vcs = NULL;\n\n    msg->msg_type = ca->msg_type;\n    if(ca->txnid != NULL)\n    {\n        msg->txnid.len = sizeof(uuid_t);\n        msg->txnid.data = malloc(sizeof(uuid_t));\n        memcpy(msg->txnid.data, ca->txnid, sizeof(uuid_t));\n    }\n    else\n    {\n        msg->txnid.data = NULL;\n        msg->txnid.len = 0;\n    }\n    msg->nonce = ca->nonce;\n    msg->n_cells = ca->no_cells;\n\n    msg->queue_address = cell_address_msg;\n\n    msg->app_id = ca->app_id;\n    msg->shard_id = ca->shard_id;\n    msg->consumer_id = ca->consumer_id;\n    msg->group_id = ca->group_id;\n    msg->queue_index = ca->queue_index;\n    msg->status = ca->status;\n\n    if(ca->no_cells > 0)\n    {\n        msg->cells = (VersionedCellMessage **) malloc(msg->n_cells * sizeof (VersionedCellMessage*));\n        vcs = (VectorClockMessage **) malloc(msg->n_cells * sizeof (VectorClockMessage*));\n\n        for(int i=0;i<ca->no_cells;i++)\n        {\n            msg->cells[i] = malloc (sizeof (VersionedCellMessage));\n            versioned_cell_message__init(msg->cells[i]);\n            vcs[i] = malloc (sizeof (VectorClockMessage));\n            vector_clock_message__init(vcs[i]);\n            init_cell_msg(msg->cells[i], ca->cells+i, vcs[i]);\n        }\n\n        free(vcs);\n    }\n}\n\nqueue_query_message * init_queue_message_from_msg(QueueQueryMessage * msg)\n{\n    cell * cells = NULL;\n    cell_address * cell_address = init_cell_address_from_msg(msg->queue_address);\n\n    switch(msg->msg_type)\n    {\n        case QUERY_TYPE_CREATE_QUEUE:\n        {\n            return init_create_queue_message(cell_address, (uuid_t *) msg->txnid.data, msg->nonce);\n        }\n        case QUERY_TYPE_DELETE_QUEUE:\n        {\n            return init_delete_queue_message(cell_address, (uuid_t *) msg->txnid.data, msg->nonce);\n        }\n        case QUERY_TYPE_SUBSCRIBE_QUEUE:\n        {\n            return init_subscribe_queue_message(cell_address, msg->app_id, msg->shard_id, msg->consumer_id, msg->group_id, (uuid_t *) msg->txnid.data, msg->nonce);\n        }\n        case QUERY_TYPE_UNSUBSCRIBE_QUEUE:\n        {\n            return init_unsubscribe_queue_message(cell_address, msg->app_id, msg->shard_id, msg->consumer_id, msg->group_id, (uuid_t *) msg->txnid.data, msg->nonce);\n        }\n        case QUERY_TYPE_ADD_QUEUE_TO_GROUP:\n        {\n            return init_add_queue_to_group_message(cell_address, msg->group_id, (uuid_t *) msg->txnid.data, msg->nonce);\n        }\n        case QUERY_TYPE_REMOVE_QUEUE_FROM_GROUP:\n        {\n            return init_remove_queue_from_group_message(cell_address, msg->group_id, (uuid_t *) msg->txnid.data, msg->nonce);\n        }\n        case QUERY_TYPE_ENQUEUE:\n        {\n            if(msg->n_cells > 0)\n            {\n                cells = (cell *) malloc(msg->n_cells * sizeof(cell));\n                for(int i=0;i<msg->n_cells;i++)\n                    copy_cell_from_msg(cells + i, msg->cells[i]);\n            }\n\n            return init_enqueue_message(cell_address, cells, msg->n_cells, (uuid_t *) msg->txnid.data, msg->nonce);\n        }\n        case QUERY_TYPE_READ_QUEUE:\n        {\n            return init_read_queue_message(cell_address, msg->app_id, msg->shard_id, msg->consumer_id, msg->queue_index, (uuid_t *) msg->txnid.data, msg->nonce);\n        }\n        case QUERY_TYPE_CONSUME_QUEUE:\n        {\n            return init_consume_queue_message(cell_address, msg->app_id, msg->shard_id, msg->consumer_id, msg->queue_index, (uuid_t *) msg->txnid.data, msg->nonce);\n        }\n        case QUERY_TYPE_READ_QUEUE_RESPONSE:\n        {\n            if(msg->n_cells > 0)\n            {\n                cells = (cell *) malloc(msg->n_cells * sizeof(cell));\n                for(int i=0;i<msg->n_cells;i++)\n                    copy_cell_from_msg(cells + i, msg->cells[i]);\n            }\n\n            return init_read_queue_response(cell_address, cells, msg->n_cells, msg->app_id, msg->shard_id, msg->consumer_id, msg->group_id, msg->queue_index, msg->status, (uuid_t *) msg->txnid.data, msg->nonce);\n        }\n        case QUERY_TYPE_QUEUE_NOTIFICATION:\n        {\n            return init_queue_notification(cell_address, NULL, 0, msg->app_id, msg->shard_id, msg->consumer_id, msg->group_id, msg->queue_index, msg->status, (uuid_t *) msg->txnid.data, msg->nonce);\n        }\n        default:\n        {\n            assert(0);\n        }\n    }\n\n    return NULL;\n}\n\nvoid free_queue_message_msg(QueueQueryMessage * msg)\n{\n//  if(msg->txnid.data != NULL)\n//      free(msg->txnid.data);\n\n    for(int i=0;i<msg->n_cells;i++)\n        free_cell_msg(msg->cells[i]);\n\n    if(msg->cells != NULL)\n        free(msg->cells);\n}\n\n\nint serialize_queue_message(queue_query_message * ca, void ** buf, unsigned * len, short for_server, vector_clock * vc)\n{\n    QueueQueryMessage msg = QUEUE_QUERY_MESSAGE__INIT;\n    CellAddressMessage cell_address_msg = CELL_ADDRESS_MESSAGE__INIT;\n\n    init_cell_address_msg(&cell_address_msg, ca->cell_address);\n    init_queue_message_msg(&msg, ca, &cell_address_msg);\n    msg.mtype = RPC_TYPE_QUEUE;\n\n    if(for_server)\n    {\n        ServerMessage sm = SERVER_MESSAGE__INIT;\n        sm.mtype = RPC_TYPE_QUEUE;\n        sm.wm = NULL;\n        sm.rm = NULL;\n        sm.rrm = NULL;\n        sm.qm = &msg;\n        sm.tm = NULL;\n        sm.gl = NULL;\n\n        if(vc != NULL)\n        {\n            VectorClockMessage lc_msg = VECTOR_CLOCK_MESSAGE__INIT;\n            init_vc_msg(&lc_msg, vc);\n            sm.vc = &lc_msg;\n        }\n        else\n        {\n            sm.vc = NULL;\n        }\n\n        *len = server_message__get_packed_size (&sm);\n        *len = (*len) + sizeof(int);\n        *buf = malloc (*len);\n        memset(*buf, 0 , *len);\n        *((int *)(*buf)) = (*len) - sizeof(int);\n        server_message__pack (&sm, (void *) ((int *)(*buf) + 1));\n\n        free_server_msg(&sm);\n    }\n    else\n    {\n        ClientMessage cm = CLIENT_MESSAGE__INIT;\n        cm.mtype = RPC_TYPE_QUEUE;\n        cm.am = NULL;\n        cm.wm = NULL;\n        cm.rrrm = NULL;\n        cm.qm = &msg;\n        cm.tm = NULL;\n\n        if(vc != NULL)\n        {\n            VectorClockMessage lc_msg = VECTOR_CLOCK_MESSAGE__INIT;\n            init_vc_msg(&lc_msg, vc);\n            cm.vc = &lc_msg;\n        }\n        else\n        {\n            cm.vc = NULL;\n        }\n\n        *len = client_message__get_packed_size (&cm);\n        *len = (*len) + sizeof(int);\n        *buf = malloc (*len);\n        memset(*buf, 0 , *len);\n        *((int *)(*buf)) = (*len) - sizeof(int);\n        client_message__pack (&cm, (void *) ((int *)(*buf) + 1));\n\n        free_client_msg(&cm);\n    }\n\n    return 0;\n\n}\n\nint deserialize_queue_message(void * buf, unsigned msg_len, queue_query_message ** ca)\n{\n    QueueQueryMessage * msg = queue_query_message__unpack (NULL, msg_len, buf);\n\n    if (msg == NULL) {\n        log_error(\"Error unpacking queue query message, msg is NULL\");\n        return 1;\n    } else if (msg->mtype != RPC_TYPE_QUEUE) {\n        log_error(\"Error unpacking queue query message, msg->mtype is not RPC_TYPE_QUEUE: %d\", msg->mtype);\n        return 1;\n    }\n\n    *ca = init_queue_message_from_msg(msg);\n\n    queue_query_message__free_unpacked(msg, NULL);\n\n    return 0;\n}\n\nchar * to_string_queue_message(queue_query_message * ca, char * msg_buff)\n{\n    char * crt_ptr = msg_buff;\n    char uuid_str[37];\n    if(ca->txnid != NULL)\n        uuid_unparse_lower(*(ca->txnid), uuid_str);\n    else\n        uuid_str[0]='\\0';\n\n    switch(ca->msg_type)\n    {\n        case QUERY_TYPE_CREATE_QUEUE:\n        {\n            sprintf(crt_ptr, \"CreateQueue(txnid=%s, nonce=%\" PRId64 \", \", uuid_str, ca->nonce);\n            break;\n        }\n        case QUERY_TYPE_DELETE_QUEUE:\n        {\n            sprintf(crt_ptr, \"DeleteQueue(txnid=%s, nonce=%\" PRId64 \", \", uuid_str, ca->nonce);\n            break;\n        }\n        case QUERY_TYPE_SUBSCRIBE_QUEUE:\n        {\n            sprintf(crt_ptr, \"SubscribeQueue(txnid=%s, nonce=%\" PRId64 \", app_id=%d, shard_id=%d, consumer_id=%d, \", uuid_str, ca->nonce, ca->app_id, ca->shard_id, ca->consumer_id);\n            break;\n        }\n        case QUERY_TYPE_UNSUBSCRIBE_QUEUE:\n        {\n            sprintf(crt_ptr, \"UnsubscribeQueue(txnid=%s, nonce=%\" PRId64 \", app_id=%d, shard_id=%d, consumer_id=%d, \", uuid_str, ca->nonce, ca->app_id, ca->shard_id, ca->consumer_id);\n            break;\n        }\n        case QUERY_TYPE_ADD_QUEUE_TO_GROUP:\n        {\n            sprintf(crt_ptr, \"AddQueueToGroup(txnid=%s, nonce=%\" PRId64 \", table_key=%\" PRId64 \", queue_id=%\" PRId64 \", group_id=%d, \", uuid_str, ca->nonce, ca->cell_address->table_key, ca->cell_address->keys[0], ca->group_id);\n            break;\n        }\n        case QUERY_TYPE_REMOVE_QUEUE_FROM_GROUP:\n        {\n            sprintf(crt_ptr, \"RemoveQueueFromGroup(txnid=%s, nonce=%\" PRId64 \", table_key=%\" PRId64 \", queue_id=%\" PRId64 \", group_id=%d, \", uuid_str, ca->nonce, ca->cell_address->table_key, ca->cell_address->keys[0], ca->group_id);\n            break;\n        }\n        case QUERY_TYPE_ENQUEUE:\n        {\n            sprintf(crt_ptr, \"Enqueue(txnid=%s, nonce=%\" PRId64 \", no_entries=%d, \", uuid_str, ca->nonce, ca->no_cells);\n            break;\n        }\n        case QUERY_TYPE_READ_QUEUE:\n        {\n            sprintf(crt_ptr, \"ReadQueue(txnid=%s, nonce=%\" PRId64 \", app_id=%d, shard_id=%d, consumer_id=%d, max_items=%\" PRId64 \", \", uuid_str, ca->nonce, ca->app_id, ca->shard_id, ca->consumer_id, ca->queue_index);\n            break;\n        }\n        case QUERY_TYPE_CONSUME_QUEUE:\n        {\n            sprintf(crt_ptr, \"ConsumeQueue(txnid=%s, nonce=%\" PRId64 \", app_id=%d, shard_id=%d, consumer_id=%d, new_consume_head=%\" PRId64 \", \", uuid_str, ca->nonce, ca->app_id, ca->shard_id, ca->consumer_id, ca->queue_index);\n            break;\n        }\n        case QUERY_TYPE_READ_QUEUE_RESPONSE:\n        {\n            sprintf(crt_ptr, \"ReadQueueResponse(txnid=%s, nonce=%\" PRId64 \", app_id=%d, shard_id=%d, consumer_id=%d, no_entries=%d, new_read_head=%\" PRId64 \", status=%d, \", uuid_str, ca->nonce, ca->app_id, ca->shard_id, ca->consumer_id, ca->no_cells, ca->queue_index, ca->status);\n            break;\n        }\n    }\n    crt_ptr += strlen(crt_ptr);\n\n    to_string_cell_address(ca->cell_address, crt_ptr);\n    crt_ptr += strlen(crt_ptr);\n\n    if(ca->no_cells > 0)\n    {\n        sprintf(crt_ptr, \", cells={\");\n        crt_ptr += strlen(crt_ptr);\n        for(int i=0;i<ca->no_cells;i++)\n        {\n            if(crt_ptr - msg_buff > MAX_PRINT_BUFF - 5)\n            {\n                sprintf(crt_ptr, \"..\");\n                crt_ptr += strlen(crt_ptr);\n                break;\n            }\n\n            to_string_cell(ca->cells+i, crt_ptr);\n            crt_ptr += strlen(crt_ptr);\n            sprintf(crt_ptr, \", \");\n            crt_ptr += strlen(crt_ptr);\n        }\n\n        sprintf(crt_ptr, \"} )\");\n        crt_ptr += strlen(crt_ptr);\n    }\n\n    sprintf(crt_ptr, \")\");\n\n    return msg_buff;\n}\n\nint equals_queue_message(queue_query_message * ca1, queue_query_message * ca2)\n{\n    if(ca1->nonce != ca2->nonce ||\n        ca1->msg_type != ca2->msg_type || ca1->queue_index != ca2->queue_index ||\n        ca1->no_cells != ca2->no_cells || !equals_cell_address(ca1->cell_address, ca2->cell_address))\n        return 0;\n\n    if(ca1->txnid != NULL && ca2->txnid && uuid_compare(*(ca1->txnid), *(ca2->txnid)))\n        return 0;\n\n    return 1;\n}\n\n// Txn Message:\n\ntxn_message * build_new_txn(uuid_t * txnid, int64_t nonce)\n{\n    return init_txn_message_copy(DB_TXN_BEGIN,\n            NULL, 0, // own_read_set, no_own_read_set,\n            NULL, 0, // own_write_set, no_own_write_set,\n            NULL, 0, // complete_read_set, no_complete_read_set,\n            NULL, 0, // complete_write_set, no_complete_write_set,\n            txnid, NULL, nonce);\n}\n\ntxn_message * build_validate_txn(uuid_t * txnid, vector_clock * version, int64_t nonce)\n{\n    // In the current implementation, the server mirrors the txn's complete read and write sets, so there is no reason to re-send them from client:\n\n    return init_txn_message_copy(DB_TXN_VALIDATION,\n            NULL, 0, // own_read_set, no_own_read_set,\n            NULL, 0, // own_write_set, no_own_write_set,\n            NULL, 0, // complete_read_set, no_complete_read_set,\n            NULL, 0, // complete_write_set, no_complete_write_set,\n            txnid, version, nonce);\n}\n\ntxn_message * build_commit_txn(uuid_t * txnid, vector_clock * version, int64_t nonce)\n{\n    // In the current implementation, the server mirrors the txn's complete read and write sets, so there is no reason to re-send them from client:\n\n    return init_txn_message_copy(DB_TXN_COMMIT,\n            NULL, 0, // own_read_set, no_own_read_set,\n            NULL, 0, // own_write_set, no_own_write_set,\n            NULL, 0, // complete_read_set, no_complete_read_set,\n            NULL, 0, // complete_write_set, no_complete_write_set,\n            txnid, version, nonce);\n}\n\ntxn_message * build_abort_txn(uuid_t * txnid, int64_t nonce)\n{\n    return init_txn_message_copy(DB_TXN_ABORT,\n            NULL, 0, // own_read_set, no_own_read_set,\n            NULL, 0, // own_write_set, no_own_write_set,\n            NULL, 0, // complete_read_set, no_complete_read_set,\n            NULL, 0, // complete_write_set, no_complete_write_set,\n            txnid, NULL, nonce);\n}\n\ntxn_message * init_txn_message(int type,\n        cell * own_read_set, int no_own_read_set,\n        cell * own_write_set, int no_own_write_set,\n        cell * complete_read_set, int no_complete_read_set,\n        cell * complete_write_set, int no_complete_write_set,\n        uuid_t * txnid, vector_clock * version, int64_t nonce)\n{\n    txn_message * ca = (txn_message *) malloc(sizeof(txn_message));\n    ca->type = type;\n    ca->own_read_set = own_read_set;\n    ca->no_own_read_set = no_own_read_set;\n    ca->own_write_set = own_write_set;\n    ca->no_own_write_set = no_own_write_set;\n    ca->complete_read_set = complete_read_set;\n    ca->no_complete_read_set = no_complete_read_set;\n    ca->complete_write_set = complete_write_set;\n    ca->no_complete_write_set = no_complete_write_set;\n    ca->txnid = txnid;\n    ca->version = version;\n    ca->nonce = nonce;\n    return ca;\n}\n\ntxn_message * init_txn_message_copy(int type,\n        cell * own_read_set, int no_own_read_set,\n        cell * own_write_set, int no_own_write_set,\n        cell * complete_read_set, int no_complete_read_set,\n        cell * complete_write_set, int no_complete_write_set,\n        uuid_t * txnid, vector_clock * version, int64_t nonce)\n{\n    txn_message * ca = (txn_message *) malloc(sizeof(txn_message));\n\n    ca->type = type;\n    if(txnid != NULL)\n    {\n        ca->txnid = malloc(sizeof(uuid_t));\n        memcpy(ca->txnid, txnid, sizeof(uuid_t));\n    }\n    else\n    {\n        ca->txnid = NULL;\n    }\n\n    ca->version = (version != NULL)?copy_vc(version):NULL;\n    ca->nonce = nonce;\n    ca->no_own_read_set = no_own_read_set;\n    ca->no_own_write_set = no_own_write_set;\n    ca->no_complete_read_set = no_complete_read_set;\n    ca->no_complete_write_set = no_complete_write_set;\n\n    ca->own_read_set = (cell *) malloc (no_own_read_set * sizeof(cell));\n    for(int i=0;i<no_own_read_set;i++)\n        ca->own_read_set[i] = own_read_set[i];\n\n    ca->own_write_set = (cell *) malloc (no_own_write_set * sizeof(cell));\n    for(int i=0;i<no_own_write_set;i++)\n        ca->own_write_set[i] = own_write_set[i];\n\n    ca->complete_read_set = (cell *) malloc (no_complete_read_set * sizeof(cell));\n    for(int i=0;i<no_complete_read_set;i++)\n        ca->complete_read_set[i] = complete_read_set[i];\n\n    ca->complete_write_set = (cell *) malloc (no_complete_write_set * sizeof(cell));\n    for(int i=0;i<no_complete_write_set;i++)\n        ca->complete_write_set[i] = complete_write_set[i];\n\n    return ca;\n}\n\nvoid free_txn_message(txn_message * ca)\n{\n    for(int i=0;i<ca->no_own_read_set;i++)\n        free_cell_ptrs(ca->own_read_set+i);\n    free(ca->own_read_set);\n\n    for(int i=0;i<ca->no_own_write_set;i++)\n        free_cell_ptrs(ca->own_write_set+i);\n    free(ca->own_write_set);\n\n    for(int i=0;i<ca->no_complete_read_set;i++)\n        free_cell_ptrs(ca->complete_read_set+i);\n    free(ca->complete_read_set);\n\n    for(int i=0;i<ca->no_complete_write_set;i++)\n        free_cell_ptrs(ca->complete_write_set+i);\n    free(ca->complete_write_set);\n\n    if(ca->version != NULL)\n        free_vc(ca->version);\n\n    free(ca);\n}\n\nvoid init_txn_message_msg(TxnMessage * msg, txn_message * ca, VectorClockMessage * vc_msg)\n{\n    msg->n_own_read_set = ca->no_own_read_set;\n    msg->n_own_write_set = ca->no_own_write_set;\n    msg->n_complete_read_set = ca->no_complete_read_set;\n    msg->n_complete_write_set = ca->no_complete_write_set;\n\n    VersionedCellMessage **own_read_set = (VersionedCellMessage **) malloc(msg->n_own_read_set * sizeof (VersionedCellMessage*));\n    VectorClockMessage ** vc_msgs_own_read_set = (VectorClockMessage **) malloc(msg->n_own_read_set * sizeof (VectorClockMessage*));\n\n    for(int i = 0; i < msg->n_own_read_set; i++)\n    {\n        own_read_set[i] = malloc (sizeof (VersionedCellMessage));\n        versioned_cell_message__init(own_read_set[i]);\n        vc_msgs_own_read_set[i] = malloc (sizeof (VectorClockMessage));\n        vector_clock_message__init(vc_msgs_own_read_set[i]);\n        init_cell_msg(own_read_set[i], ca->own_read_set+i, vc_msgs_own_read_set[i]);\n    }\n    free(vc_msgs_own_read_set);\n\n    VersionedCellMessage **own_write_set = (VersionedCellMessage **) malloc(msg->n_own_write_set * sizeof (VersionedCellMessage*));\n    VectorClockMessage ** vc_msgs_own_write_set = (VectorClockMessage **) malloc(msg->n_own_write_set * sizeof (VectorClockMessage*));\n\n    for(int i = 0; i < msg->n_own_write_set; i++)\n    {\n        own_write_set[i] = malloc (sizeof (VersionedCellMessage));\n        versioned_cell_message__init(own_write_set[i]);\n        vc_msgs_own_write_set[i] = malloc (sizeof (VectorClockMessage));\n        vector_clock_message__init(vc_msgs_own_write_set[i]);\n        init_cell_msg(own_write_set[i], ca->own_write_set+i, vc_msgs_own_write_set[i]);\n    }\n    free(vc_msgs_own_write_set);\n\n    VersionedCellMessage **complete_read_set = (VersionedCellMessage **) malloc(msg->n_complete_read_set * sizeof (VersionedCellMessage*));\n    VectorClockMessage ** vc_msgs_complete_read_set = (VectorClockMessage **) malloc(msg->n_complete_read_set * sizeof (VectorClockMessage*));\n\n    for(int i = 0; i < msg->n_complete_read_set; i++)\n    {\n        complete_read_set[i] = malloc (sizeof (VersionedCellMessage));\n        versioned_cell_message__init(complete_read_set[i]);\n        vc_msgs_complete_read_set[i] = malloc (sizeof (VectorClockMessage));\n        vector_clock_message__init(vc_msgs_complete_read_set[i]);\n        init_cell_msg(complete_read_set[i], ca->complete_read_set+i, vc_msgs_complete_read_set[i]);\n    }\n    free(vc_msgs_complete_read_set);\n\n    VersionedCellMessage **complete_write_set = (VersionedCellMessage **) malloc(msg->n_complete_write_set * sizeof (VersionedCellMessage*));\n    VectorClockMessage ** vc_msgs_complete_write_set = (VectorClockMessage **) malloc(msg->n_complete_write_set * sizeof (VectorClockMessage*));\n\n    for(int i = 0; i < msg->n_complete_write_set; i++)\n    {\n        complete_write_set[i] = malloc (sizeof (VersionedCellMessage));\n        versioned_cell_message__init(complete_write_set[i]);\n        vc_msgs_complete_write_set[i] = malloc (sizeof (VectorClockMessage));\n        vector_clock_message__init(vc_msgs_complete_write_set[i]);\n        init_cell_msg(complete_write_set[i], ca->complete_write_set+i, vc_msgs_complete_write_set[i]);\n    }\n    free(vc_msgs_complete_write_set);\n\n    msg->own_read_set = own_read_set;\n    msg->own_write_set = own_write_set;\n    msg->complete_read_set = complete_read_set;\n    msg->complete_write_set = complete_write_set;\n    msg->type = ca->type;\n    if(ca->txnid != NULL)\n    {\n        msg->txnid.len = sizeof(uuid_t);\n        msg->txnid.data = malloc(sizeof(uuid_t));\n        memcpy(msg->txnid.data, ca->txnid, sizeof(uuid_t));\n    }\n    else\n    {\n        msg->txnid.data = NULL;\n        msg->txnid.len = 0;\n    }\n    if(ca->version != NULL)\n    {\n        init_vc_msg(vc_msg, ca->version);\n\n//      msg->has_version = 1;\n        msg->version = vc_msg;\n    }\n    else\n    {\n//      msg->has_version = 0;\n    }\n\n    msg->nonce = ca->nonce;\n}\n\ntxn_message * init_txn_message_from_msg(TxnMessage * msg)\n{\n    cell * own_read_set = (cell *) malloc(msg->n_own_read_set * sizeof(cell));\n    cell * own_write_set = (cell *) malloc(msg->n_own_write_set * sizeof(cell));\n    cell * complete_read_set = (cell *) malloc(msg->n_complete_read_set * sizeof(cell));\n    cell * complete_write_set = (cell *) malloc(msg->n_complete_write_set * sizeof(cell));\n\n    for(int i=0;i<msg->n_own_read_set;i++)\n        copy_cell_from_msg(own_read_set+i, msg->own_read_set[i]);\n    for(int i=0;i<msg->n_own_write_set;i++)\n        copy_cell_from_msg(own_write_set+i, msg->own_write_set[i]);\n    for(int i=0;i<msg->n_complete_read_set;i++)\n        copy_cell_from_msg(complete_read_set+i, msg->complete_read_set[i]);\n    for(int i=0;i<msg->n_complete_write_set;i++)\n        copy_cell_from_msg(complete_write_set+i, msg->complete_write_set[i]);\n\n    txn_message * c = init_txn_message_copy(msg->type,\n            own_read_set, msg->n_own_read_set,\n            own_write_set, msg->n_own_write_set,\n            complete_read_set, msg->n_complete_read_set,\n            complete_write_set, msg->n_complete_write_set,\n            (uuid_t *) msg->txnid.data, (msg->version != NULL)?init_vc_from_msg(msg->version):NULL, msg->nonce); // msg->has_version\n\n    return c;\n}\n\nvoid free_txn_message_msg(TxnMessage * msg)\n{\n    for(int i=0;i<msg->n_own_read_set;i++)\n        free_cell_msg(msg->own_read_set[i]);\n    free(msg->own_read_set);\n\n    for(int i=0;i<msg->n_own_write_set;i++)\n        free_cell_msg(msg->own_write_set[i]);\n    free(msg->own_write_set);\n\n    for(int i=0;i<msg->n_complete_read_set;i++)\n        free_cell_msg(msg->complete_read_set[i]);\n    free(msg->complete_read_set);\n\n    for(int i=0;i<msg->n_complete_write_set;i++)\n        free_cell_msg(msg->complete_write_set[i]);\n    free(msg->complete_write_set);\n\n    if(msg->version != NULL) // msg->has_version\n        free_vc_msg(msg->version);\n}\n\nint serialize_txn_message(txn_message * ca, void ** buf, unsigned * len, short for_server, vector_clock * vc)\n{\n    TxnMessage msg = TXN_MESSAGE__INIT;\n    VectorClockMessage vc_msg = VECTOR_CLOCK_MESSAGE__INIT;\n\n    init_txn_message_msg(&msg, ca, &vc_msg);\n    msg.mtype = RPC_TYPE_TXN;\n\n    if(for_server)\n    {\n        ServerMessage sm = SERVER_MESSAGE__INIT;\n        sm.mtype = RPC_TYPE_TXN;\n        sm.wm = NULL;\n        sm.rm = NULL;\n        sm.rrm = NULL;\n        sm.qm = NULL;\n        sm.tm = &msg;\n        sm.gl = NULL;\n\n        if(vc != NULL)\n        {\n            VectorClockMessage lc_msg = VECTOR_CLOCK_MESSAGE__INIT;\n            init_vc_msg(&lc_msg, vc);\n            sm.vc = &lc_msg;\n        }\n        else\n        {\n            sm.vc = NULL;\n        }\n\n        *len = server_message__get_packed_size (&sm);\n        *len = (*len) + sizeof(int);\n        *buf = malloc (*len);\n        memset(*buf, 0 , *len);\n        *((int *)(*buf)) = (*len) - sizeof(int);\n        server_message__pack (&sm, (void *) ((int *)(*buf) + 1));\n\n        free_server_msg(&sm);\n    }\n    else\n    {\n        ClientMessage cm = CLIENT_MESSAGE__INIT;\n        cm.mtype = RPC_TYPE_TXN;\n        cm.am = NULL;\n        cm.wm = NULL;\n        cm.rrrm = NULL;\n        cm.qm = NULL;\n        cm.tm = &msg;\n\n        if(vc != NULL)\n        {\n            VectorClockMessage lc_msg = VECTOR_CLOCK_MESSAGE__INIT;\n            init_vc_msg(&lc_msg, vc);\n            cm.vc = &lc_msg;\n        }\n        else\n        {\n            cm.vc = NULL;\n        }\n\n        *len = client_message__get_packed_size (&cm);\n        *len = (*len) + sizeof(int);\n        *buf = malloc (*len);\n        memset(*buf, 0 , *len);\n        *((int *)(*buf)) = (*len) - sizeof(int);\n        client_message__pack (&cm, (void *) ((int *)(*buf) + 1));\n\n        free_client_msg(&cm);\n    }\n\n    return 0;\n}\n\nint deserialize_txn_message(void * buf, unsigned msg_len, txn_message ** ca)\n{\n    TxnMessage * msg = txn_message__unpack (NULL, msg_len, buf);\n\n    if (msg == NULL) {\n        log_error(\"Error unpacking txn query message, msg is NULL\");\n        return 1;\n    } else if (msg->mtype != RPC_TYPE_TXN) {\n        log_error(\"Error unpacking txn query message, msg->mtype is not RPC_TYPE_TXN: %d\", msg->mtype);\n        return 1;\n    }\n\n    *ca = init_txn_message_from_msg(msg);\n\n    txn_message__free_unpacked(msg, NULL);\n\n    return 0;\n}\n\nchar * to_string_txn_message(txn_message * ca, char * msg_buff)\n{\n    char * crt_ptr = msg_buff;\n    char uuid_str[37];\n    if(ca->txnid != NULL)\n        uuid_unparse_lower(*(ca->txnid), uuid_str);\n    else\n        uuid_str[0]='\\0';\n\n    sprintf(crt_ptr, \"TxnMessage(type=%d, txnid=%s, nonce=%\" PRId64 \"\", ca->type, uuid_str, ca->nonce);\n    crt_ptr += strlen(crt_ptr);\n\n    sprintf(crt_ptr, \", own_read_set={\");\n    crt_ptr += strlen(crt_ptr);\n    for(int i=0;i<ca->no_own_read_set;i++)\n    {\n        to_string_cell(ca->own_read_set+i, crt_ptr);\n        crt_ptr += strlen(crt_ptr);\n        sprintf(crt_ptr, \", \");\n        crt_ptr += strlen(crt_ptr);\n    }\n\n    sprintf(crt_ptr, \"}, own_write_set={\");\n    crt_ptr += strlen(crt_ptr);\n    for(int i=0;i<ca->no_own_write_set;i++)\n    {\n        to_string_cell(ca->own_write_set+i, crt_ptr);\n        crt_ptr += strlen(crt_ptr);\n        sprintf(crt_ptr, \", \");\n        crt_ptr += strlen(crt_ptr);\n    }\n\n    sprintf(crt_ptr, \"}, complete_read_set={\");\n    crt_ptr += strlen(crt_ptr);\n    for(int i=0;i<ca->no_complete_read_set;i++)\n    {\n        to_string_cell(ca->complete_read_set+i, crt_ptr);\n        crt_ptr += strlen(crt_ptr);\n        sprintf(crt_ptr, \", \");\n        crt_ptr += strlen(crt_ptr);\n    }\n\n    sprintf(crt_ptr, \"}, complete_write_set={\");\n    crt_ptr += strlen(crt_ptr);\n    for(int i=0;i<ca->no_complete_write_set;i++)\n    {\n        to_string_cell(ca->complete_write_set+i, crt_ptr);\n        crt_ptr += strlen(crt_ptr);\n        sprintf(crt_ptr, \"}, \");\n        crt_ptr += strlen(crt_ptr);\n    }\n\n    sprintf(crt_ptr, \"}, version=\");\n    crt_ptr += strlen(crt_ptr);\n\n    if(ca->version != NULL)\n    {\n        to_string_vc(ca->version, crt_ptr);\n        crt_ptr += strlen(crt_ptr);\n    }\n\n    sprintf(crt_ptr, \")\");\n\n    return msg_buff;\n}\n\nint equals_txn_message(txn_message * ca1, txn_message * ca2)\n{\n    if(ca1->nonce != ca2->nonce || ca1->type != ca2->type ||\n        ca1->no_own_read_set != ca2->no_own_read_set ||\n        ca1->no_own_write_set != ca2->no_own_write_set ||\n        ca1->no_complete_read_set != ca2->no_complete_read_set ||\n        ca1->no_complete_write_set != ca2->no_complete_write_set)\n        return 0;\n\n    if(ca1->txnid != NULL && ca2->txnid && uuid_compare(*(ca1->txnid), *(ca2->txnid)))\n        return 0;\n\n    if(compare_vc(ca1->version, ca2->version))\n        return 0;\n\n    for(int i=0;i<ca1->no_own_read_set;i++)\n        if(!equals_cell(ca1->own_read_set+i, ca2->own_read_set+i))\n            return 0;\n\n    for(int i=0;i<ca1->no_own_write_set;i++)\n        if(!equals_cell(ca1->own_write_set+i, ca2->own_write_set+i))\n            return 0;\n\n    for(int i=0;i<ca1->no_complete_read_set;i++)\n        if(!equals_cell(ca1->complete_read_set+i, ca2->complete_read_set+i))\n            return 0;\n\n    for(int i=0;i<ca1->no_complete_write_set;i++)\n        if(!equals_cell(ca1->complete_write_set+i, ca2->complete_write_set+i))\n            return 0;\n\n    return 1;\n}\n\n\ngossip_listen_message * build_gossip_listen_msg(node_description * nd, int64_t nonce)\n{\n    gossip_listen_message * gs = (gossip_listen_message *) malloc(sizeof(gossip_listen_message));\n    gs->node_description = nd;\n    gs->nonce = nonce;\n    return gs;\n}\n\nvoid free_gossip_listen_msg(gossip_listen_message * gs)\n{\n    free_node_description(gs->node_description);\n    free(gs);\n}\n\nvoid free_gossip_listen_message_msg(GossipListenMessage * msg)\n{\n}\n\nint serialize_gossip_listen_msg(gossip_listen_message * gs, void ** buf, unsigned * len)\n{\n    GossipListenMessage msg = GOSSIP_LISTEN_MESSAGE__INIT;\n\n    NodeStateMessage ns_msg = NODE_STATE_MESSAGE__INIT;\n    init_ns_msg_from_description(&ns_msg, gs->node_description);\n\n    msg.node_state = &ns_msg;\n    msg.nonce = gs->nonce;\n\n    ServerMessage sm = SERVER_MESSAGE__INIT;\n    sm.mtype = RPC_TYPE_GOSSIP_LISTEN;\n    sm.wm = NULL;\n    sm.rm = NULL;\n    sm.rrm = NULL;\n    sm.qm = NULL;\n    sm.tm = NULL;\n    sm.gl = &msg;\n    sm.vc = NULL;\n\n    *len = server_message__get_packed_size (&sm);\n    *len = (*len) + sizeof(int);\n    *buf = malloc (*len);\n    memset(*buf, 0 , *len);\n    *((int *)(*buf)) = (*len) - sizeof(int);\n    server_message__pack (&sm, (void *) ((int *)(*buf) + 1));\n\n    free_server_msg(&sm);\n\n    return 0;\n}\n\nint deserialize_gossip_listen_msg(void * buf, unsigned msg_len, gossip_listen_message ** gl)\n{\n    GossipListenMessage * msg = gossip_listen_message__unpack(NULL, msg_len, buf);\n\n    if (msg == NULL) {\n        log_error(\"Error unpacking gossip_state message, msg is NULL\");\n        return 1;\n    }\n\n    node_description * nd = init_node_description(msg->node_state->status, msg->node_state->node_id, msg->node_state->rack_id, msg->node_state->dc_id, (char *) msg->node_state->hostname.data, msg->node_state->port);\n\n    *gl = build_gossip_listen_msg(nd, msg->nonce);\n\n     return 0;\n}\n\nint equals_gossip_listen_msg(gossip_listen_message * gs1, gossip_listen_message * gs2)\n{\n    return equals_node_description(gs1->node_description, gs2->node_description) &&\n            gs1->node_description->status == gs2->node_description->status &&\n            gs1->nonce == gs2->nonce;\n}\n\nchar * to_string_gossip_listen_msg(gossip_listen_message * gs, char * msg_buff)\n{\n    sprintf(msg_buff, \"GossipListenMessage(node_description=\");\n    to_string_node_description(gs->node_description, msg_buff + strlen(msg_buff));\n    sprintf(msg_buff, \", nonce=%\" PRId64 \")\", gs->nonce);\n    return msg_buff;\n}\n\n\nvoid free_server_msg(ServerMessage * sm)\n{\n    switch(sm->mtype)\n    {\n        case RPC_TYPE_WRITE:\n        {\n            assert(sm->wm != NULL);\n            free_write_query_msg(sm->wm);\n            break;\n        }\n        case RPC_TYPE_READ:\n        {\n            assert(sm->rm != NULL);\n            free_read_query_msg(sm->rm);\n            break;\n        }\n        case RPC_TYPE_RANGE_READ:\n        {\n            assert(sm->rrm != NULL);\n            free_range_read_query_msg(sm->rrm);\n            break;\n        }\n        case RPC_TYPE_QUEUE:\n        {\n            assert(sm->qm != NULL);\n            free_queue_message_msg(sm->qm);\n            break;\n        }\n        case RPC_TYPE_TXN:\n        {\n            assert(sm->tm != NULL);\n            free_txn_message_msg(sm->tm);\n            break;\n        }\n        case RPC_TYPE_GOSSIP_LISTEN:\n        {\n            assert(sm->gl != NULL);\n            free_gossip_listen_message_msg(sm->gl);\n            break;\n        }\n        default:\n        {\n            log_fatal(\"Wrong server message type %d\", sm->mtype);\n        }\n    }\n\n    if(sm->vc != NULL)\n        free_vc_msg(sm->vc);\n}\n\nint deserialize_server_message(void * buf, unsigned msg_len, void ** dest_buf, short * mtype, vector_clock ** vc)\n{\n    ServerMessage * sm = server_message__unpack (NULL, msg_len, buf);\n\n    if (sm == NULL)\n    {\n        *mtype = -1;\n        log_error(\"Error unpacking server message, msg is NULL\");\n        return 1;\n    }\n\n    switch(sm->mtype)\n    {\n        case RPC_TYPE_WRITE:\n        {\n            assert(sm->wm != NULL);\n            *dest_buf = (write_query *) init_write_query_from_msg(sm->wm);\n            break;\n        }\n        case RPC_TYPE_READ:\n        {\n            assert(sm->rm != NULL);\n            *dest_buf = (read_query *) init_read_query_from_msg(sm->rm);\n            break;\n        }\n        case RPC_TYPE_RANGE_READ:\n        {\n            assert(sm->rrm != NULL);\n            *dest_buf = (range_read_query *) init_range_read_query_from_msg(sm->rrm);\n            break;\n        }\n        case RPC_TYPE_QUEUE:\n        {\n            assert(sm->qm != NULL);\n            *dest_buf = (queue_query_message *) init_queue_message_from_msg(sm->qm);\n            break;\n        }\n        case RPC_TYPE_TXN:\n        {\n            assert(sm->tm != NULL);\n            *dest_buf = (txn_message *) init_txn_message_from_msg(sm->tm);\n            break;\n        }\n        case RPC_TYPE_GOSSIP_LISTEN:\n        {\n            assert(sm->gl != NULL);\n            node_description * nd = init_node_description(sm->gl->node_state->status, sm->gl->node_state->node_id, sm->gl->node_state->rack_id, sm->gl->node_state->dc_id, (char *) sm->gl->node_state->hostname.data, sm->gl->node_state->port);\n            *dest_buf = (gossip_listen_message *) build_gossip_listen_msg(nd, sm->gl->nonce);\n            break;\n        }\n        default:\n        {\n            log_fatal(\"Wrong server message type %d\", sm->mtype);\n            return 1;\n        }\n    }\n\n    *mtype = sm->mtype;\n\n    *vc = (sm->vc != NULL)?(init_vc_from_msg(sm->vc)):(NULL);\n\n    //printf(\"Deserialized message of type %d\\n\", sm->mtype);\n\n    server_message__free_unpacked(sm, NULL);\n\n    return 0;\n}\n\nvoid free_client_msg(ClientMessage * cm)\n{\n    switch(cm->mtype)\n    {\n        case RPC_TYPE_ACK:\n        {\n            assert(cm->am != NULL);\n            free_ack_message_msg(cm->am);\n            break;\n        }\n        case RPC_TYPE_WRITE:\n        {\n            assert(cm->wm != NULL);\n            free_write_query_msg(cm->wm);\n            break;\n        }\n        case RPC_TYPE_RANGE_READ_RESPONSE:\n        {\n            assert(cm->rrrm != NULL);\n            free_range_read_response_message_msg(cm->rrrm);\n            break;\n        }\n        case RPC_TYPE_QUEUE:\n        {\n            assert(cm->qm != NULL);\n            free_queue_message_msg(cm->qm);\n            break;\n        }\n        case RPC_TYPE_TXN:\n        {\n            assert(cm->tm != NULL);\n            free_txn_message_msg(cm->tm);\n            break;\n        }\n        default:\n        {\n            log_fatal(\"Wrong client message type %d\", cm->mtype);\n        }\n    }\n\n    if(cm->vc != NULL)\n        free_vc_msg(cm->vc);\n}\n\nint deserialize_client_message(void * buf, unsigned msg_len, void ** dest_buf, short * mtype, short * is_gossip_message, vector_clock ** vc)\n{\n    ClientMessage * cm = client_message__unpack (NULL, msg_len, buf);\n    *is_gossip_message = 0;\n\n    if (cm == NULL)\n    {\n        log_error(\"Error unpacking client message, msg is NULL\");\n\n        // This might be a gossiped membership notification:\n\n        membership_agreement_msg * ma = NULL;\n\n        int status = deserialize_membership_agreement_msg(buf, msg_len, &ma); //  + sizeof(int)\n\n        if(status == 0)\n        {\n// #if (VERBOSE_RPC > 0)\n            char print_buff[1024];\n            to_string_membership_agreement_msg(ma, (char *) print_buff);\n            log_debug(\"Received gossip message: %s\", print_buff);\n// #endif\n\n            switch(ma->msg_type)\n            {\n                case MEMBERSHIP_AGREEMENT_NOTIFY:\n                {\n                    *is_gossip_message = 1;\n                    *mtype = ma->msg_type;\n                    *dest_buf = ma;\n                    break;\n                }\n                default:\n                {\n                    log_fatal(\"Wrong gossip message type %d\", ma->msg_type);\n                }\n            }\n\n            return 0;\n        }\n        else\n        {\n            log_error(\"Error unpacking gossip message\");\n            return 1;\n        }\n    }\n\n    switch(cm->mtype)\n    {\n        case RPC_TYPE_ACK:\n        {\n            assert(cm->am != NULL);\n            *dest_buf = init_ack_message_from_msg(cm->am);\n            break;\n        }\n        case RPC_TYPE_WRITE:\n        {\n            assert(cm->wm != NULL);\n            *dest_buf = init_write_query_from_msg(cm->wm);\n            break;\n        }\n        case RPC_TYPE_RANGE_READ_RESPONSE:\n        {\n            assert(cm->rrrm != NULL);\n            *dest_buf = init_range_read_response_message_from_msg(cm->rrrm);\n            break;\n        }\n        case RPC_TYPE_QUEUE:\n        {\n            assert(cm->qm != NULL);\n            *dest_buf = init_queue_message_from_msg(cm->qm);\n            break;\n        }\n        case RPC_TYPE_TXN:\n        {\n            assert(cm->tm != NULL);\n            *dest_buf = init_txn_message_from_msg(cm->tm);\n            break;\n        }\n        default:\n        {\n            log_fatal(\"Wrong client message type %d\", cm->mtype);\n            return 1;\n        }\n    }\n\n    *mtype = cm->mtype;\n\n    *vc = (cm->vc != NULL)?(init_vc_from_msg(cm->vc)):(NULL);\n\n    client_message__free_unpacked(cm, NULL);\n\n    return 0;\n}\n\n\n\n\n\n"
  },
  {
    "path": "backend/failure_detector/db_queries.h",
    "content": "/*\n * Copyright (C) 2019-2021 Deutsche Telekom AG\n *\n * Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:\n *\n * 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.\n *\n * 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.\n *\n * 3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission.\n *\n * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS \"AS IS\" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n */\n\n/*\n * db_queries.h\n *\n *      Author: aagapi\n */\n\n#ifndef BACKEND_FAILURE_DETECTOR_DB_QUERIES_H_\n#define BACKEND_FAILURE_DETECTOR_DB_QUERIES_H_\n\n#include \"cells.h\"\n#include \"../db.h\"\n#include \"../txns.h\"\n#include \"fd.h\"\n#include <uuid/uuid.h>\n\n#define RPC_TYPE_WRITE 0\n#define RPC_TYPE_DELETE 1\n#define RPC_TYPE_READ 2\n#define RPC_TYPE_RANGE_READ 3\n#define RPC_TYPE_ACK 4\n#define RPC_TYPE_READ_RESPONSE 5\n#define RPC_TYPE_RANGE_READ_RESPONSE 6\n#define RPC_TYPE_QUEUE 7\n#define RPC_TYPE_TXN 8\n#define RPC_TYPE_GOSSIP 9\n#define RPC_TYPE_GOSSIP_LISTEN 10\n\n#define DB_TXN_BEGIN 0\n#define DB_TXN_VALIDATION 1\n#define DB_TXN_COMMIT 2\n#define DB_TXN_ABORT 3\n\n#define DB_ACK 0\n#define DB_NACK 1\n\n#define CLIENT_ERR_SUBSCRIPTION_EXISTS 1\n#define CLIENT_ERR_NO_SUBSCRIPTION_EXISTS 2\n\nint deserialize_server_message(void * buf, unsigned msg_len, void ** sm, short * mtype, vector_clock ** vc);\nint deserialize_client_message(void * buf, unsigned msg_len, void ** cm, short * mtype, short * is_gossip_message, vector_clock ** vc);\n\ntypedef struct write_query\n{\n    cell * cell;\n    int msg_type; // {RPC_TYPE_WRITE, RPC_TYPE_DELETE}\n    uuid_t * txnid;\n    int64_t nonce;\n} write_query;\n\ntypedef write_query read_response_message;\n\nwrite_query * build_insert_in_txn(WORD * column_values, int no_cols, int no_primary_keys, int no_clustering_keys, WORD blob, size_t blob_size, WORD table_key, uuid_t * txnid, int64_t nonce);\nwrite_query * build_delete_row_in_txn(WORD* primary_keys, int no_primary_keys, WORD table_key, uuid_t * txnid, int64_t nonce);\nwrite_query * build_delete_cell_in_txn(WORD* keys, int no_primary_keys, int no_clustering_keys, WORD table_key, uuid_t * txnid, int64_t nonce);\nwrite_query * build_delete_by_index_in_txn(WORD index_key, int idx_idx, WORD table_key, uuid_t * txnid, int64_t nonce);\nwrite_query * build_update_in_txn(int * col_idxs, int no_cols, WORD * column_values, WORD blob, size_t blob_size, WORD table_key, uuid_t * txnid, int64_t nonce);\n\nwrite_query * init_write_query(cell * cell, int msg_type, uuid_t * txnid, int64_t nonce);\nwrite_query * init_write_query_copy(cell * cell, int msg_type, uuid_t * txnid, int64_t nonce);\nvoid free_write_query(write_query * ca);\nint serialize_write_query(write_query * ca, void ** buf, unsigned * len, short for_server, vector_clock * vc);\nint deserialize_write_query(void * buf, unsigned msg_len, write_query ** ca);\nchar * to_string_write_query(write_query * ca, char * msg_buff);\nint equals_write_query(write_query * ca1, write_query * ca2);\n\ntypedef struct read_query\n{\n    cell_address * cell_address;\n    uuid_t * txnid;\n    int64_t nonce;\n} read_query;\n\nread_query * build_search_in_txn(WORD* primary_keys, int no_primary_keys, WORD table_key, uuid_t * txnid, int64_t nonce);\nread_query * build_search_clustering_in_txn(WORD* primary_keys, int no_primary_keys, WORD* clustering_keys, int no_clustering_keys, WORD table_key, uuid_t * txnid, int64_t nonce);\nread_query * build_search_columns_in_txn(WORD* primary_keys, int no_primary_keys, WORD* clustering_keys, int no_clustering_keys, WORD* col_keys, int no_columns, WORD table_key, uuid_t * txnid, int64_t nonce);\nread_query * build_search_index_in_txn(WORD index_key, int idx_idx, WORD table_key, uuid_t * txnid, int64_t nonce);\n\nread_query * init_read_query(cell_address * cell_address, uuid_t * txnid, int64_t nonce);\nread_query * init_read_query_copy(cell_address * cell_address, uuid_t * txnid, int64_t nonce);\nvoid free_read_query(read_query * ca);\nint serialize_read_query(read_query * ca, void ** buf, unsigned * len, vector_clock * vc);\nint deserialize_read_query(void * buf, unsigned msg_len, read_query ** ca);\nchar * to_string_read_query(read_query * ca, char * msg_buff);\nint equals_read_query(read_query * ca1, read_query * ca2);\n\n\ntypedef struct ack_message\n{\n    cell_address * cell_address;\n    int status;\n    uuid_t * txnid;\n    int64_t nonce;\n} ack_message;\n\nack_message * init_ack_message(cell_address * cell_address, int status, uuid_t * txnid, int64_t nonce);\nvoid free_ack_message(ack_message * ca);\nint serialize_ack_message(ack_message * ca, void ** buf, unsigned * len, vector_clock * vc);\nint deserialize_ack_message(void * buf, unsigned msg_len, ack_message ** ca);\nchar * to_string_ack_message(ack_message * ca, char * msg_buff);\nint equals_ack_message(ack_message * ca1, ack_message * ca2);\n\n\ntypedef struct range_read_query\n{\n    cell_address * start_cell_address;\n    cell_address * end_cell_address;\n    uuid_t * txnid;\n    int64_t nonce;\n} range_read_query;\n\nrange_read_query * build_range_search_in_txn(WORD* start_primary_keys, WORD* end_primary_keys, int no_primary_keys, WORD table_key, uuid_t * txnid, int64_t nonce);\nrange_read_query * build_range_search_clustering_in_txn(WORD* primary_keys, int no_primary_keys, WORD* start_clustering_keys, WORD* end_clustering_keys, int no_clustering_keys, WORD table_key, uuid_t * txnid, int64_t nonce);\nrange_read_query * build_range_search_index_in_txn(int idx_idx, WORD start_idx_key, WORD end_idx_key, WORD table_key, uuid_t * txnid, int64_t nonce);\nrange_read_query * build_wildcard_range_search_in_txn(WORD table_key, uuid_t * txnid, int64_t nonce);\n\nrange_read_query * init_range_read_query(cell_address * start_cell_address, cell_address * end_cell_address, uuid_t * txnid, int64_t nonce);\nrange_read_query * init_range_read_query_copy(cell_address * start_cell_address, cell_address * end_cell_address, uuid_t * txnid, int64_t nonce);\nvoid free_range_read_query(range_read_query * ca);\nint serialize_range_read_query(range_read_query * ca, void ** buf, unsigned * len, vector_clock * vc);\nint deserialize_range_read_query(void * buf, unsigned msg_len, range_read_query ** ca);\nchar * to_string_range_read_query(range_read_query * ca, char * msg_buff);\nint equals_range_read_query(range_read_query * ca1, range_read_query * ca2);\n\n\ntypedef struct range_read_response_message\n{\n    cell * cells;\n    int no_cells;\n    uuid_t * txnid;\n    int64_t nonce;\n} range_read_response_message;\n\nrange_read_response_message * init_range_read_response_message(cell * cells, int no_cells, uuid_t * txnid, int64_t nonce);\nvoid free_range_read_response_message(range_read_response_message * ca);\nint serialize_range_read_response_message(range_read_response_message * ca, void ** buf, unsigned * len, vector_clock * vc);\nint deserialize_range_read_response_message(void * buf, unsigned msg_len, range_read_response_message ** ca);\nchar * to_string_range_read_response_message(range_read_response_message * ca, char * msg_buff);\nint equals_range_read_response_message(range_read_response_message * ca1, range_read_response_message * ca2);\n\n\ntypedef struct queue_query_message\n{\n    cell_address * cell_address; // queue address\n    short msg_type; // {CREATE, DELETE, SUBSCRIBE, UNSUBSCRIBE, ENQUEUE, READ_QUEUE, CONSUME_QUEUE, READ_QUEUE_RESPONSE}\n\n    int app_id;\n    int shard_id;\n    int consumer_id;\n    int group_id;\n\n    // For ENQUEUE and READ_QUEUE_RESPONSE:\n\n    cell * cells;\n    int no_cells;\n\n    // For READ_QUEUE (== max_entries) and CONSUME_QUEUE (== new_consume_head):\n\n    int64_t queue_index;\n\n\n    // For RESPONSE type messages:\n\n    short status;\n\n    uuid_t * txnid;\n    int64_t nonce;\n} queue_query_message;\n\nqueue_query_message * build_create_queue_in_txn(WORD table_key, WORD queue_id, uuid_t * txnid, int64_t nonce);\nqueue_query_message * build_delete_queue_in_txn(WORD table_key, WORD queue_id, uuid_t * txnid, int64_t nonce);\nqueue_query_message * build_enqueue_in_txn(WORD * column_values, int no_cols, WORD blob, size_t blob_size, WORD table_key, WORD queue_id, uuid_t * txnid, int64_t nonce);\nqueue_query_message * build_read_queue_in_txn(WORD consumer_id, WORD shard_id, WORD app_id, WORD table_key, WORD queue_id,\n                                                int max_entries, uuid_t * txnid, int64_t nonce);\nqueue_query_message * build_consume_queue_in_txn(WORD consumer_id, WORD shard_id, WORD app_id, WORD table_key, WORD queue_id,\n                                                    int64_t new_consume_head, uuid_t * txnid, int64_t nonce);\nqueue_query_message * build_subscribe_queue_in_txn(WORD consumer_id, WORD shard_id, WORD app_id, WORD table_key, WORD queue_id, uuid_t * txnid, int64_t nonce);\nqueue_query_message * build_unsubscribe_queue_in_txn(WORD consumer_id, WORD shard_id, WORD app_id, WORD table_key, WORD queue_id, uuid_t * txnid, int64_t nonce);\nqueue_query_message * build_subscribe_group_in_txn(WORD consumer_id, WORD shard_id, WORD app_id, WORD group_id, uuid_t * txnid, int64_t nonce);\nqueue_query_message * build_unsubscribe_group_in_txn(WORD consumer_id, WORD shard_id, WORD app_id, WORD group_id, uuid_t * txnid, int64_t nonce);\nqueue_query_message * build_add_queue_to_group_in_txn(WORD table_key, WORD queue_id, WORD group_id, uuid_t * txnid, int64_t nonce);\nqueue_query_message * build_remove_queue_from_group_in_txn(WORD table_key, WORD queue_id, WORD group_id, uuid_t * txnid, int64_t nonce);\n\nqueue_query_message * init_create_queue_message(cell_address * cell_address, uuid_t * txnid, int64_t nonce);\nqueue_query_message * init_delete_queue_message(cell_address * cell_address, uuid_t * txnid, int64_t nonce);\nqueue_query_message * init_subscribe_queue_message(cell_address * cell_address, int app_id, int shard_id, int consumer_id, int group_id, uuid_t * txnid, int64_t nonce);\nqueue_query_message * init_unsubscribe_queue_message(cell_address * cell_address, int app_id, int shard_id, int consumer_id, int group_id, uuid_t * txnid, int64_t nonce);\nqueue_query_message * init_add_queue_to_group_message(cell_address * cell_address, int group_id, uuid_t * txnid, int64_t nonce);\nqueue_query_message * init_remove_queue_from_group_message(cell_address * cell_address, int group_id, uuid_t * txnid, int64_t nonce);\nqueue_query_message * init_enqueue_message(cell_address * cell_address, cell * cells, int no_cells, uuid_t * txnid, int64_t nonce);\nqueue_query_message * init_read_queue_message(cell_address * cell_address, int app_id, int shard_id, int consumer_id, int64_t max_entries, uuid_t * txnid, int64_t nonce);\nqueue_query_message * init_consume_queue_message(cell_address * cell_address, int app_id, int shard_id, int consumer_id, int64_t new_consume_head, uuid_t * txnid, int64_t nonce);\nqueue_query_message * init_read_queue_response(cell_address * cell_address, cell * cells, int no_cells, int app_id, int shard_id, int consumer_id, int group_id, int64_t new_read_head, short status, uuid_t * txnid, int64_t nonce);\nqueue_query_message * init_queue_notification(cell_address * cell_address, cell * cells, int no_cells, int app_id, int shard_id, int consumer_id, int group_id, int64_t new_no_entries, short status, uuid_t * txnid, int64_t nonce);\nvoid free_queue_message(queue_query_message * ca);\nint serialize_queue_message(queue_query_message * ca, void ** buf, unsigned * len, short for_server, vector_clock * vc);\nint deserialize_queue_message(void * buf, unsigned msg_len, queue_query_message ** ca);\nchar * to_string_queue_message(queue_query_message * ca, char * msg_buff);\nint equals_queue_message(queue_query_message * ca1, queue_query_message * ca2);\n\ntypedef struct txn_message\n{\n    int type;\n    cell * own_read_set;\n    int no_own_read_set;\n    cell * own_write_set;\n    int no_own_write_set;\n    cell * complete_read_set;\n    int no_complete_read_set;\n    cell * complete_write_set;\n    int no_complete_write_set;\n    uuid_t * txnid;\n    vector_clock * version;\n    int64_t nonce;\n} txn_message;\n\ntxn_message * build_new_txn(uuid_t * txnid, int64_t nonce);\ntxn_message * build_validate_txn(uuid_t * txnid, vector_clock * version, int64_t nonce);\ntxn_message * build_abort_txn(uuid_t * txnid, int64_t nonce);\ntxn_message * build_commit_txn(uuid_t * txnid, vector_clock * version, int64_t nonce);\n\ntxn_message * init_txn_message(int type,\n                                cell * own_read_set, int no_own_read_set,\n                                cell * own_write_set, int no_own_write_set,\n                                cell * complete_read_set, int no_complete_read_set,\n                                cell * complete_write_set, int no_complete_write_set,\n                                uuid_t * txnid, vector_clock * version, int64_t nonce);\ntxn_message * init_txn_message_copy(int type,\n        cell * own_read_set, int no_own_read_set,\n        cell * own_write_set, int no_own_write_set,\n        cell * complete_read_set, int no_complete_read_set,\n        cell * complete_write_set, int no_complete_write_set,\n        uuid_t * txnid, vector_clock * version, int64_t nonce);\nvoid free_txn_message(txn_message * ca);\nint serialize_txn_message(txn_message * ca, void ** buf, unsigned * len, short for_server, vector_clock * vc);\nint deserialize_txn_message(void * buf, unsigned msg_len, txn_message ** ca);\nchar * to_string_txn_message(txn_message * ca, char * msg_buff);\nint equals_txn_message(txn_message * ca1, txn_message * ca2);\n\ntypedef struct gossip_listen_message\n{\n    node_description * node_description;\n    int64_t nonce;\n} gossip_listen_message;\n\ngossip_listen_message * build_gossip_listen_msg(node_description * nd, int64_t nonce);\nvoid free_gossip_listen_msg(gossip_listen_message * gs);\nint serialize_gossip_listen_msg(gossip_listen_message * gs, void ** buf, unsigned * len);\nint deserialize_gossip_listen_msg(void * buf, unsigned msg_len, gossip_listen_message ** gl);\nint equals_gossip_listen_msg(gossip_listen_message * gs1, gossip_listen_message * gs2);\nchar * to_string_gossip_listen_msg(gossip_listen_message * gs, char * msg_buff);\n\n#endif /* BACKEND_FAILURE_DETECTOR_DB_QUERIES_H_ */\n"
  },
  {
    "path": "backend/failure_detector/fd.c",
    "content": "/*\n * Copyright (C) 2019-2021 Deutsche Telekom AG\n *\n * Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:\n *\n * 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.\n *\n * 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.\n *\n * 3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission.\n *\n * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS \"AS IS\" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n */\n\n/*\n * fd.c\n * Author: aagapi\n */\n\n#include \"fd.h\"\n#include \"db_messages.pb-c.h\"\n#include \"../log.h\"\n\n#include <stdio.h>\n#include <stdlib.h>\n#include <string.h>\n#include <netdb.h>\n#include <sys/types.h>\n#include <sys/socket.h>\n#include <netinet/in.h>\n#include <arpa/inet.h>\n\n/* Node description: */\n\nvoid init_ns_msg_from_description(NodeStateMessage * ns_msg, node_description * nd)\n{\n    ns_msg->status = nd->status;\n    ns_msg->node_id = nd->node_id;\n    ns_msg->rack_id = nd->rack_id;\n    ns_msg->dc_id = nd->dc_id;\n    ns_msg->port = nd->portno;\n\n    assert(nd->hostname != NULL);\n\n    ns_msg->hostname.len = strnlen(nd->hostname, 256) + 1;\n    ns_msg->hostname.data = malloc(ns_msg->hostname.len);\n    memcpy(ns_msg->hostname.data, nd->hostname, ns_msg->hostname.len);\n}\n\nint copy_node_description(node_description * nd, int status, int node_id, int rack_id, int dc_id, char * hostname, unsigned short portno)\n{\n    nd->status = status;\n    nd->node_id = node_id;\n    nd->rack_id = rack_id;\n    nd->dc_id = dc_id;\n    nd->portno = portno;\n\n    bzero((void *) &nd->address, sizeof(struct sockaddr_in));\n    nd->hostname = NULL;\n\n    if(hostname != NULL)\n    {\n        struct hostent * host = gethostbyname(hostname);\n        if (host == NULL)\n        {\n            log_error(\"ERROR, no such host %s\", hostname);\n            assert(0);\n            return -1;\n        }\n\n        nd->address.sin_family = AF_INET;\n        bcopy((char *)host->h_addr, (char *)&(nd->address.sin_addr.s_addr), host->h_length);\n        nd->address.sin_port = htons(portno);\n\n        nd->hostname = strndup(hostname, strnlen(hostname, 256) + 1);\n    }\n\n    return 0;\n}\n\nnode_description * init_node_description(int status, int node_id, int rack_id, int dc_id, char * hostname, unsigned short portno)\n{\n    node_description * nd = (node_description *) malloc(sizeof(node_description));\n\n    copy_node_description(nd, status, node_id, rack_id, dc_id, hostname, portno);\n\n    return nd;\n}\n\nvoid free_node_description(node_description * nd)\n{\n    if(nd->hostname != NULL)\n        free(nd->hostname);\n    free(nd);\n}\n\nint equals_node_description(node_description * nd1, node_description * nd2)\n{\n    return nd1->node_id == nd2->node_id && nd1->rack_id == nd2->rack_id && nd1->dc_id == nd2->dc_id;\n}\n\nchar * to_string_node_description(node_description * nd, char * msg_buff)\n{\n    sprintf(msg_buff, \"Node(status=%d, node_id=%d, rack_id=%d, dc_id=%d, hostname=%s, port=%d)\", nd->status, nd->node_id, nd->rack_id, nd->dc_id, (nd->hostname != NULL)?(nd->hostname):\"NULL\", nd->portno);\n    return msg_buff;\n}\n\n\n/* Gossip state: */\n\ngossip_state * init_gossip_state(int status, int node_id, int rack_id, int dc_id, char * hostname, unsigned short portno, vector_clock * vc)\n{\n    gossip_state * gs = (gossip_state *) malloc(sizeof(struct gossip_state));\n    bzero(gs, sizeof(struct gossip_state));\n    copy_node_description(&(gs->nd), status, node_id, rack_id, dc_id, hostname, portno);\n    gs->vc = (vc != NULL)?vc:init_vc(0, NULL, NULL, 0);\n\n    return gs;\n}\n\nvoid free_gossip_state(gossip_state * gs)\n{\n    free_vc(gs->vc);\n    free(gs);\n}\n\nvoid free_gossip_msg(GossipMessage * msg)\n{\n    free_vc_msg(msg->vc);\n}\n\nvoid init_ns_msg(NodeStateMessage * ns_msg, gossip_state * gs)\n{\n    init_ns_msg_from_description(ns_msg, &(gs->nd));\n}\n\nint serialize_gs(gossip_state * gs, void ** buf, unsigned * len)\n{\n    GossipMessage msg = GOSSIP_MESSAGE__INIT;\n\n    VectorClockMessage vc_msg = VECTOR_CLOCK_MESSAGE__INIT;\n    init_vc_msg(&vc_msg, gs->vc);\n\n    NodeStateMessage ns_msg = NODE_STATE_MESSAGE__INIT;\n    init_ns_msg(&ns_msg, gs);\n\n    msg.vc = &vc_msg;\n    msg.node_state = &ns_msg;\n\n    *len = gossip_message__get_packed_size (&msg);\n    *buf = malloc (*len);\n    gossip_message__pack (&msg, *buf);\n\n    free_gossip_msg(&msg);\n\n    return 0;\n}\n\nint deserialize_gs(void * buf, unsigned msg_len, gossip_state ** gs)\n{\n      GossipMessage * msg = gossip_message__unpack(NULL, msg_len, buf);\n\n      if (msg == NULL)\n      { // Something failed\n        log_error(\"error unpacking gossip_state message\");\n        return 1;\n      }\n\n      vector_clock * vc = init_vc_from_msg(msg->vc);\n\n      *gs = init_gossip_state(msg->node_state->status, msg->node_state->node_id, msg->node_state->rack_id, msg->node_state->dc_id, (char *) msg->node_state->hostname.data, msg->node_state->port, vc);\n\n      return 0;\n}\n\nint equals_gs(gossip_state * gs1, gossip_state * gs2)\n{\n    return equals_node_description(&(gs1->nd), &(gs2->nd)) &&\n            gs1->nd.status == gs2->nd.status &&\n            compare_vc(gs1->vc, gs2->vc) == 0;\n}\n\nchar * to_string_gs(gossip_state * gs, char * msg_buff)\n{\n    sprintf(msg_buff, \"GS(node_description=\");\n    to_string_node_description(&(gs->nd), msg_buff + strlen(msg_buff));\n    sprintf(msg_buff, \", vc=\");\n    to_string_vc(gs->vc, msg_buff + strlen(msg_buff));\n    sprintf(msg_buff + strlen(msg_buff), \")\");\n\n    return msg_buff;\n}\n\n/* Membership: */\n\nmembership_state * init_membership_state(int no_nodes, node_description * membership, int no_client_nodes, node_description * client_membership, vector_clock * view_id)\n{\n    membership_state * ms = (membership_state *) malloc(sizeof(membership_state));\n    ms->no_nodes = no_nodes;\n    ms->membership = membership;\n    ms->no_client_nodes = no_client_nodes;\n    ms->client_membership = client_membership;\n    ms->view_id = view_id;\n    return ms;\n}\n\nmembership_state * clone_membership(membership_state * m)\n{\n    membership_state * ms = (membership_state *) malloc(sizeof(membership_state));\n    ms->no_nodes = m->no_nodes;\n    ms->membership = (node_description *) malloc(m->no_nodes * sizeof(node_description));\n    for(int i=0;i<m->no_nodes;i++)\n        copy_node_description(ms->membership + i, m->membership[i].status, m->membership[i].node_id, m->membership[i].rack_id, m->membership[i].dc_id, m->membership[i].hostname, m->membership[i].portno);\n\n    ms->no_client_nodes = m->no_client_nodes;\n    ms->client_membership = (node_description *) malloc(m->no_client_nodes * sizeof(node_description));\n    for(int i=0;i<m->no_client_nodes;i++)\n        copy_node_description(ms->client_membership + i, m->client_membership[i].status, m->client_membership[i].node_id, m->client_membership[i].rack_id, m->client_membership[i].dc_id, m->client_membership[i].hostname, m->client_membership[i].portno);\n\n    ms->view_id = (m->view_id != NULL)?(copy_vc(m->view_id)):(NULL);\n\n    return ms;\n}\n\nvoid free_membership_state(membership_state * ms, int do_free_vc)\n{\n    free(ms->membership);\n    free(ms->client_membership);\n    if(do_free_vc)\n        free_vc(ms->view_id);\n    free(ms);\n}\n\nvoid free_membership_msg(MembershipViewMessage * msg)\n{\n    free_vc_msg(msg->view_id);\n\n    for(int i=0;i<msg->n_membership;i++)\n        free(msg->membership[i]);\n\n    free(msg->membership);\n\n    for(int i=0;i<msg->n_client_membership;i++)\n        free(msg->client_membership[i]);\n\n    free(msg->client_membership);\n}\n\nvoid init_membership_msg(MembershipViewMessage * msg, membership_state * m, VectorClockMessage * view_id_msg)\n{\n    NodeStateMessage **membership_v = (NodeStateMessage **) malloc (m->no_nodes * sizeof (NodeStateMessage*));\n    NodeStateMessage **client_membership_v = NULL;\n    if(m->no_client_nodes > 0)\n        client_membership_v = (NodeStateMessage **) malloc (m->no_client_nodes * sizeof (NodeStateMessage*));\n\n    for(int i = 0; i < m->no_nodes; i++)\n    {\n        membership_v[i] = malloc (sizeof (NodeStateMessage));\n        node_state_message__init(membership_v[i]);\n        init_ns_msg_from_description(membership_v[i], m->membership+i);\n    }\n    msg->n_membership = m->no_nodes;\n    msg->membership = membership_v;\n\n    for(int i = 0; i < m->no_client_nodes; i++)\n    {\n        client_membership_v[i] = malloc (sizeof (NodeStateMessage));\n        node_state_message__init(client_membership_v[i]);\n        init_ns_msg_from_description(client_membership_v[i], m->client_membership+i);\n    }\n    msg->n_client_membership = m->no_client_nodes;\n    msg->client_membership = client_membership_v;\n\n    msg->view_id = view_id_msg;\n}\n\nint serialize_membership_state(membership_state * m, void ** buf, unsigned * len)\n{\n    MembershipViewMessage msg = MEMBERSHIP_VIEW_MESSAGE__INIT;\n    VectorClockMessage view_id_msg = VECTOR_CLOCK_MESSAGE__INIT;\n    init_vc_msg(&view_id_msg, m->view_id);\n\n    init_membership_msg(&msg, m, &view_id_msg);\n\n    *len = membership_view_message__get_packed_size (&msg);\n    *buf = malloc (*len);\n    membership_view_message__pack (&msg, *buf);\n\n    free_membership_msg(&msg);\n\n    return 0;\n\n}\n\nmembership_state * init_membership_from_msg(MembershipViewMessage * msg)\n{\n    vector_clock * view_id = init_vc_from_msg(msg->view_id);\n\n    node_description * membership = (node_description *) malloc(msg->n_membership * sizeof(node_description));\n    for(int i=0;i<msg->n_membership;i++)\n        copy_node_description(membership+i, msg->membership[i]->status, msg->membership[i]->node_id, msg->membership[i]->rack_id, msg->membership[i]->dc_id,\n                                (char *) msg->membership[i]->hostname.data, (unsigned short) msg->membership[i]->port);\n\n    node_description * client_membership = NULL;\n    if(msg->n_client_membership > 0)\n    {\n        client_membership = (node_description *) malloc(msg->n_client_membership * sizeof(node_description));\n        for(int i=0;i<msg->n_client_membership;i++)\n            copy_node_description(client_membership+i, msg->client_membership[i]->status, msg->client_membership[i]->node_id, msg->client_membership[i]->rack_id, msg->client_membership[i]->dc_id,\n                                    (char *) msg->client_membership[i]->hostname.data, (unsigned short) msg->client_membership[i]->port);\n    }\n\n    return init_membership_state(msg->n_membership, membership, msg->n_client_membership, client_membership, view_id);\n}\n\nint deserialize_membership_state(void * buf, unsigned msg_len, membership_state ** ms)\n{\n    MembershipViewMessage * msg = membership_view_message__unpack(NULL, msg_len, buf);\n\n    if (msg == NULL)\n    {\n        log_error(\"error unpacking membership view message\");\n        return 1;\n    }\n\n    *ms = init_membership_from_msg(msg);\n\n    return 0;\n}\n\nint equals_membership_state(membership_state * gs1, membership_state * gs2)\n{\n    if(gs1->no_nodes != gs2->no_nodes)\n        return 0;\n\n    for(int i=0;i<gs1->no_nodes;i++)\n        if(!equals_node_description(gs1->membership + i, gs2->membership + i))\n            return 0;\n\n    if(gs1->no_client_nodes != gs2->no_client_nodes)\n        return 0;\n\n    for(int i=0;i<gs1->no_client_nodes;i++)\n        if(!equals_node_description(gs1->client_membership + i, gs2->client_membership + i))\n            return 0;\n\n    return 1;\n}\n\nchar * to_string_membership_state(membership_state * gs, char * msg_buff)\n{\n    char * crt_ptr = msg_buff;\n    sprintf(crt_ptr, \"Membership(\");\n    crt_ptr += strlen(crt_ptr);\n\n    for(int i=0;i<gs->no_nodes;i++)\n    {\n        to_string_node_description(gs->membership+i, crt_ptr);\n        crt_ptr += strlen(crt_ptr);\n        sprintf(crt_ptr, \", \");\n        crt_ptr += 2;\n    }\n\n    sprintf(crt_ptr, \"), Client Membership(\");\n    crt_ptr += strlen(\"), Client Membership(\");\n\n    for(int i=0;i<gs->no_client_nodes;i++)\n    {\n        to_string_node_description(gs->client_membership+i, crt_ptr);\n        crt_ptr += strlen(crt_ptr);\n        sprintf(crt_ptr, \", \");\n        crt_ptr += 2;\n    }\n\n    return msg_buff;\n}\n\n\n/* Membership agreement messages: */\n\nmembership_agreement_msg * init_membership_agreement_msg(int msg_type, int ack_status, membership_state * membership, int64_t nonce, vector_clock * vc)\n{\n    membership_agreement_msg * ma = (membership_agreement_msg *) malloc(sizeof(membership_agreement_msg));\n    ma->msg_type = msg_type;\n    ma->ack_status = ack_status;\n    ma->membership = membership;\n    ma->nonce = nonce;\n    ma->vc = vc;\n    return ma;\n}\n\nmembership_agreement_msg * get_membership_propose_msg(int ack_status, membership_state * membership, int64_t nonce, vector_clock * vc)\n{\n    return init_membership_agreement_msg(MEMBERSHIP_AGREEMENT_PROPOSE, ack_status, membership, nonce, vc);\n}\n\nmembership_agreement_msg * get_membership_response_msg(int ack_status, membership_state * membership, int64_t nonce, vector_clock * vc)\n{\n    return init_membership_agreement_msg(MEMBERSHIP_AGREEMENT_RESPONSE, ack_status, membership, nonce, vc);\n}\n\nmembership_agreement_msg * get_membership_notify_msg(int ack_status, membership_state * membership, int64_t nonce, vector_clock * vc)\n{\n    return init_membership_agreement_msg(MEMBERSHIP_AGREEMENT_NOTIFY, ack_status, membership, nonce, vc);\n}\n\nmembership_agreement_msg * get_membership_notify_ack_msg(int ack_status, int64_t nonce, vector_clock * vc)\n{\n    return init_membership_agreement_msg(MEMBERSHIP_AGREEMENT_NOTIFY_ACK, ack_status, NULL, nonce, vc);\n}\n\nmembership_agreement_msg * get_membership_join_msg(int status, int rack_id, int dc_id, char * hostname, unsigned short portno, int64_t nonce, vector_clock * vc)\n{\n    node_description * nd = init_node_description(status, -1, rack_id, dc_id, hostname, portno);\n\n    nd->node_id = get_node_id((struct sockaddr *) &(nd->address));\n\n    membership_state * membership = init_membership_state(1, nd, 0, NULL, copy_vc(vc));\n\n    return init_membership_agreement_msg(MEMBERSHIP_AGREEMENT_JOIN, status, membership, nonce, vc);\n}\n\nvoid free_membership_agreement(membership_agreement_msg * ma)\n{\n    if(ma->membership != NULL)\n        free_membership_state(ma->membership, 1);\n    if(ma->vc != NULL)\n        free_vc(ma->vc);\n    free(ma);\n}\n\nvoid free_membership_agreement_msg(MembershipAgreementMessage * msg)\n{\n    if(msg->vc != NULL)\n        free_vc_msg(msg->vc);\n\n    if(msg->view != NULL)\n        free_membership_msg(msg->view);\n}\n\nint serialize_membership_agreement_msg(membership_agreement_msg * ma, void ** buf, unsigned * len)\n{\n    MembershipAgreementMessage msg = MEMBERSHIP_AGREEMENT_MESSAGE__INIT;\n\n    VectorClockMessage vc_msg = VECTOR_CLOCK_MESSAGE__INIT;\n    init_vc_msg(&vc_msg, ma->vc);\n    msg.vc = &vc_msg;\n\n    if(ma->membership != NULL)\n    {\n        MembershipViewMessage mview_msg = MEMBERSHIP_VIEW_MESSAGE__INIT;\n        VectorClockMessage view_id_msg = VECTOR_CLOCK_MESSAGE__INIT;\n        init_vc_msg(&view_id_msg, ma->membership->view_id);\n        init_membership_msg(&mview_msg, ma->membership, &view_id_msg);\n        msg.view = &mview_msg;\n    }\n    else\n    {\n        msg.view = NULL;\n    }\n\n    msg.msg_type = ma->msg_type;\n    msg.ack_status = ma->ack_status;\n    msg.nonce = ma->nonce;\n\n    *len = membership_agreement_message__get_packed_size (&msg);\n    *len = (*len) + sizeof(int);\n    *buf = malloc (*len);\n    memset(*buf, 0 , *len);\n    *((int *)(*buf)) = (*len) - sizeof(int);\n    membership_agreement_message__pack (&msg, (void *) ((int *)(*buf) + 1));\n    free_membership_agreement_msg(&msg);\n\n    return 0;\n}\n\nint deserialize_membership_agreement_msg(void * buf, unsigned msg_len, membership_agreement_msg ** ma)\n{\n    MembershipAgreementMessage * msg = membership_agreement_message__unpack(NULL, msg_len, buf);\n\n    if (msg == NULL)\n    {\n        log_error(\"error unpacking membership agreement message\");\n        return 1;\n    }\n\n    vector_clock * vc = init_vc_from_msg(msg->vc);\n    membership_state * membership = (msg->view != NULL)?(init_membership_from_msg(msg->view)):(NULL);\n\n    *ma = init_membership_agreement_msg(msg->msg_type, msg->ack_status, membership, msg->nonce, vc);\n\n    return 0;\n}\n\nint equals_membership_agreement_msg(membership_agreement_msg * ma1, membership_agreement_msg * ma2)\n{\n    if(ma1->nonce != ma2->nonce || ma1->msg_type != ma2->msg_type || ma1->ack_status != ma2->ack_status)\n        return 0;\n\n    if((ma1->membership != NULL && ma2->membership == NULL) ||\n        (ma1->membership == NULL && ma2->membership != NULL) ||\n        !equals_membership_state(ma1->membership, ma2->membership))\n        return 0;\n\n    if(compare_vc(ma1->vc, ma2->vc) != 0)\n        return 0;\n\n    return 1;\n}\n\nchar * to_string_membership_agreement_msg(membership_agreement_msg * ma, char * msg_buff)\n{\n    char * crt_ptr = msg_buff;\n    sprintf(crt_ptr, \"Membership_agreement_msg(type=%d, ack_status=%d, nonce=%\" PRId64 \", \", ma->msg_type, ma->ack_status, ma->nonce);\n    crt_ptr += strlen(crt_ptr);\n\n    if(ma->membership != NULL)\n    {\n        to_string_membership_state(ma->membership, crt_ptr);\n        crt_ptr += strlen(crt_ptr);\n        sprintf(crt_ptr, \", \");\n        crt_ptr += 2;\n    }\n\n    if(ma->vc != NULL)\n    {\n        to_string_vc(ma->vc, crt_ptr);\n        crt_ptr += strlen(crt_ptr);\n    }\n    sprintf(crt_ptr, \")\");\n\n    return msg_buff;\n}\n\n\n\n"
  },
  {
    "path": "backend/failure_detector/fd.h",
    "content": "/*\n * fd.h\n *\n * Author: aagapi\n */\n\n#ifndef BACKEND_FAILURE_DETECTOR_FD_H_\n#define BACKEND_FAILURE_DETECTOR_FD_H_\n\n#include \"vector_clock.h\"\n\n#define MAX_MSG_SIZE_GS (MAX_MSG_SIZE_VC + 16)\n\n#define SKIP_PROPOSAL_STATUS 10\n\n/* Node description: */\n\ntypedef struct node_description\n{\n    int status;\n    int node_id;\n    int rack_id;\n    int dc_id;\n\n    char * hostname;\n    unsigned short portno;\n    struct sockaddr_in address;\n} node_description;\n\nnode_description * init_node_description(int status, int node_id, int rack_id, int dc_idm, char * hostname, unsigned short portno);\nint copy_node_description(node_description * nd, int status, int node_id, int rack_id, int dc_id, char * hostname, unsigned short portno);\nvoid free_node_description(node_description * vc);\nint equals_node_description(node_description * nd1, node_description * nd2);\nchar * to_string_node_description(node_description * nd, char * msg_buff);\nvoid init_ns_msg_from_description(NodeStateMessage * ns_msg, node_description * nd);\n\n/* Gossip state: */\n\ntypedef struct gossip_state\n{\n    node_description nd;\n    vector_clock * vc;\n} gossip_state;\n\ngossip_state * init_gossip_state(int status, int node_id, int rack_id, int dc_id, char * hostname, unsigned short portno, vector_clock * vc);\nvoid free_gossip_state(gossip_state * vc);\nint serialize_gs(gossip_state * gs, void ** buf, unsigned * len);\nint deserialize_gs(void * buf, unsigned msg_len, gossip_state ** gs);\nint equals_gs(gossip_state * gs1, gossip_state * gs2);\nchar * to_string_gs(gossip_state * gs, char * msg_buff);\n\n/* Membership view: */\n\ntypedef struct membership_state\n{\n    int no_nodes;\n    node_description * membership;\n    int no_client_nodes;\n    node_description * client_membership;\n    vector_clock * view_id;\n} membership_state;\n\nmembership_state * init_membership_state(int no_nodes, node_description * membership, int no_client_nodes, node_description * client_membership, vector_clock * view_id);\nvoid free_membership_state(membership_state * ms, int do_free_vc);\nint serialize_membership_state(membership_state * gs, void ** buf, unsigned * len);\nint deserialize_membership_state(void * buf, unsigned msg_len, membership_state ** gs);\nint equals_membership_state(membership_state * gs1, membership_state * gs2);\nchar * to_string_membership_state(membership_state * gs, char * msg_buff);\n\n/* Membership agreement messages: */\n\n#define MEMBERSHIP_AGREEMENT_PROPOSE 0\n#define MEMBERSHIP_AGREEMENT_RESPONSE 1\n#define MEMBERSHIP_AGREEMENT_NOTIFY 2\n#define MEMBERSHIP_AGREEMENT_RETRY_LINK 3\n#define MEMBERSHIP_AGREEMENT_NOTIFY_ACK 4\n#define MEMBERSHIP_AGREEMENT_JOIN 5\n\n#define ACK 0\n#define NACK 1\n#define UNINIT 2\n\ntypedef struct membership_agreement_msg\n{\n    int msg_type;\n    int ack_status;\n    membership_state * membership;\n    int64_t nonce;\n    vector_clock * vc;\n} membership_agreement_msg;\n\nmembership_agreement_msg * get_membership_propose_msg(int ack_status, membership_state * membership, int64_t nonce, vector_clock * vc);\nmembership_agreement_msg * get_membership_response_msg(int ack_status, membership_state * membership, int64_t nonce, vector_clock * vc);\nmembership_agreement_msg * get_membership_notify_msg(int ack_status, membership_state * membership, int64_t nonce, vector_clock * vc);\nmembership_agreement_msg * get_membership_notify_ack_msg(int ack_status, int64_t nonce, vector_clock * vc);\nmembership_agreement_msg * get_membership_join_msg(int status, int rack_id, int dc_id, char * hostname, unsigned short portno, int64_t nonce, vector_clock * vc);\nmembership_agreement_msg * init_membership_agreement_msg(int msg_type, int ack_status, membership_state * membership, int64_t nonce, vector_clock * vc);\nvoid free_membership_agreement(membership_agreement_msg * ma);\nvoid free_membership_agreement_msg(MembershipAgreementMessage * msg);\nint serialize_membership_agreement_msg(membership_agreement_msg * gs, void ** buf, unsigned * len);\nint deserialize_membership_agreement_msg(void * buf, unsigned msg_len, membership_agreement_msg ** ma);\nint equals_membership_agreement_msg(membership_agreement_msg * ma1, membership_agreement_msg * ma2);\nchar * to_string_membership_agreement_msg(membership_agreement_msg * gs, char * msg_buff);\n\n#endif /* BACKEND_FAILURE_DETECTOR_FD_H_ */\n"
  },
  {
    "path": "backend/failure_detector/txns.h",
    "content": "/*\n * txns.h\n *      Author: aagapi\n */\n\n#ifndef BACKEND_FAILURE_DETECTOR_TXNS_H_\n#define BACKEND_FAILURE_DETECTOR_TXNS_H_\n\ntypedef struct txn_message\n{\n    int64_t txnid;\n\n} txn_message;\n\n\n\n#endif /* BACKEND_FAILURE_DETECTOR_TXNS_H_ */\n"
  },
  {
    "path": "backend/failure_detector/vector_clock.c",
    "content": "/*\n * Copyright (C) 2019-2021 Deutsche Telekom AG\n *\n * Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:\n *\n * 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.\n *\n * 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.\n *\n * 3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission.\n *\n * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS \"AS IS\" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n */\n\n/*\n * vector_clock.c\n *\n *  Author: aagapi\n */\n\n#include \"vector_clock.h\"\n#include \"db_messages.pb-c.h\"\n#include <stdio.h>\n#include <stdlib.h>\n#include <string.h>\n\n// #include \"cfuhash.h\"\n\nint increment_vc(vector_clock * vc, int node_id)\n{\n    // Binary search node_id:\n    int found_idx = -1, exact_match = 0;\n    BINARY_SEARCH_NODEID(vc, node_id, found_idx, exact_match);\n\n    if(!exact_match)\n        return -1;\n\n    vc->node_ids[found_idx].counter++;\n\n    return 0;\n}\n\n// Returns:\n//      -2 of vc1 and vc2 are incomparable\n//      -1 if vc1 < vc2\n//      0 if vc1 == vc2\n//      1 if vc1 > vc2\n\nint compare_vc(vector_clock * vc1, vector_clock * vc2)\n{\n    if(vc1 == NULL && vc2 == NULL)\n        return 0;\n\n    if(vc1 == NULL || vc2 == NULL)\n        return VC_INCOMPARABLE;\n\n    if(vc1->no_nodes != vc2->no_nodes)\n        return VC_INCOMPARABLE;\n\n    int first_bigger = 0, second_bigger = 0;\n\n    for(int i=0;i<vc1->no_nodes;i++)\n    {\n        if(vc1->node_ids[i].node_id != vc2->node_ids[i].node_id)\n            return VC_INCOMPARABLE;\n\n        if(vc1->node_ids[i].counter > vc2->node_ids[i].counter)\n            first_bigger = 1;\n        else if(vc1->node_ids[i].counter < vc2->node_ids[i].counter)\n            second_bigger = 1;\n    }\n\n    if(first_bigger && second_bigger)\n        return VC_DISJOINT;\n    else if(first_bigger)\n        return 1;\n    else if(second_bigger)\n        return -1;\n    else\n        return 0;\n}\n\nint update_vc(vector_clock * vc_dest, vector_clock * vc_src)\n{\n    int dest_idx = 0;\n    int status = 0;\n\n    for(int i=0;i<vc_src->no_nodes;i++)\n    {\n        dest_idx = 0;\n\n        while(vc_dest->node_ids[dest_idx].node_id < vc_src->node_ids[i].node_id && dest_idx < vc_dest->no_nodes)\n            dest_idx++;\n\n        if(dest_idx < vc_dest->no_nodes && vc_dest->node_ids[dest_idx].node_id == vc_src->node_ids[i].node_id) // We have found the i'th component. Update it to the maximum of the 2 vectors:\n        {\n            if(vc_src->node_ids[i].counter > vc_dest->node_ids[dest_idx].counter)\n                vc_dest->node_ids[dest_idx].counter = vc_src->node_ids[i].counter;\n        }\n        else     // Source vector has a component that dest vector doesn't. Add that component to the dest vector:\n        {\n            status = add_component_vc(vc_dest, vc_src->node_ids[i].node_id, vc_src->node_ids[i].counter);\n            assert(status == 0);\n        }\n    }\n\n    return 0;\n}\n\nint update_or_replace_vc(vector_clock ** vc_dest, vector_clock * vc_src)\n{\n    int alloc_new_vc = (*vc_dest == NULL || (*vc_dest)->no_nodes != vc_src->no_nodes);\n\n    if(!alloc_new_vc)\n    {\n        for(int n=0;n<vc_src->no_nodes;n++)\n        {\n            if((*vc_dest)->node_ids[n].node_id != vc_src->node_ids[n].node_id)\n            {\n                alloc_new_vc = 1;\n                break;\n            }\n            else\n            {\n                (*vc_dest)->node_ids[n].counter = vc_src->node_ids[n].counter;\n            }\n        }\n    }\n\n    if(alloc_new_vc)\n    {\n        if(*vc_dest != NULL)\n            free_vc(*vc_dest);\n        (*vc_dest) = copy_vc(vc_src);\n    }\n\n    return 0;\n}\n\nint add_component_vc(vector_clock * vc, int node_id, int initial_counter)\n{\n    // Binary search node_id:\n    int found_idx = 0, exact_match = 0;\n    BINARY_SEARCH_NODEID(vc, node_id, found_idx, exact_match);\n\n    if(exact_match)\n        return -1; // Component already existed\n\n    if(vc->no_nodes == vc->capacity)\n        grow_vc(vc);\n\n    // Insert component in its location and shift rest to keep vector sorted\n    // Note that this is a rare operation:\n\n    for(int idx = vc->no_nodes;idx>found_idx+1;idx--)\n        vc->node_ids[idx] = vc->node_ids[idx-1];\n\n    vc->node_ids[found_idx+1].node_id = node_id;\n    vc->node_ids[found_idx+1].counter = (initial_counter > 0)?initial_counter:0;\n\n    vc->no_nodes++;\n\n    return 0;\n}\n\nint64_t get_component_vc(vector_clock * vc, int node_id)\n{\n    // Binary search node_id:\n    int found_idx = 0, exact_match = 0;\n    BINARY_SEARCH_NODEID(vc, node_id, found_idx, exact_match);\n\n    if(exact_match)\n        return vc->node_ids[found_idx].counter;\n    else\n        return -1;\n}\n\n// S'd never call this in principle:\n\nint remove_component_vc(vector_clock * vc, int node_id)\n{\n    // Binary search node_id:\n    int found_idx = -1, exact_match = 0;\n    BINARY_SEARCH_NODEID(vc, node_id, found_idx, exact_match);\n\n    if(!exact_match)\n        return -1; // Component doesn't exist\n\n    // Remove component and shift the rest:\n\n    for(int idx = found_idx; idx < vc->no_nodes ;idx++)\n        vc->node_ids[idx] = vc->node_ids[idx+1];\n\n    vc->no_nodes--;\n\n    return 0;\n}\n\nint cmpfunc (const void * a, const void * b) {\n   return (((struct versioned_id *)a)->node_id - ((struct versioned_id *)b)->node_id);\n}\n\nvector_clock * init_vc(int init_no_nodes, int * node_ids, int64_t * counters, int sort_node_ids)\n{\n    vector_clock * vc = (vector_clock *) malloc(sizeof(struct vector_clock));\n    memset(vc, 0, sizeof(struct vector_clock));\n\n    vc->no_nodes = (init_no_nodes > 0)? init_no_nodes:0;\n\n    vc->capacity = (int)(((init_no_nodes > DEFAULT_SIZE)?init_no_nodes:DEFAULT_SIZE) * GROWTH_RATE);\n\n//  printf(\"Alloc-ing vc of capacity %d for no_nodes = %d\\n\", vc->capacity, vc->no_nodes);\n\n    vc->node_ids =  (versioned_id *) malloc (vc->capacity * sizeof(struct versioned_id));\n    memset(vc->node_ids, 0, vc->capacity * sizeof(struct versioned_id));\n\n    for(int i=0;i<vc->no_nodes;i++)\n    {\n        vc->node_ids[i].node_id = (node_ids != NULL)? node_ids[i]:0;\n        vc->node_ids[i].counter = (counters != NULL)?counters[i]:0;\n    }\n\n    if(sort_node_ids) // Only call with sort_node_ids true if input node_ids not already sorted\n    {\n        qsort(vc->node_ids, vc->no_nodes, sizeof(struct versioned_id), cmpfunc);\n    }\n\n    return vc;\n}\n\nint get_node_id(struct sockaddr * x)\n{\n    #define LSB 16\n\n    assert(x->sa_family == AF_INET || x->sa_family == AF_INET6); // AF_UNIX?\n\n    if (x->sa_family == AF_INET)\n    {\n        struct sockaddr_in *xin = (struct sockaddr_in *)x;\n\n        return (ntohl(xin->sin_addr.s_addr) << LSB) | (ntohs(xin->sin_port));\n    }\n    else if (x->sa_family == AF_INET6)\n    {\n        struct sockaddr_in6 *xin6 = (struct sockaddr_in6 *)x;\n\n        uint32_t * addr = (uint32_t *) xin6->sin6_addr.s6_addr;\n\n        return (ntohl(addr[1]) << LSB) | (ntohs(xin6->sin6_port)); // use least significant host bits of the host portion of a IPV6 address\n    }\n\n    return 0;\n}\n\nvector_clock * init_empty_vc()\n{\n    return init_vc(0, NULL, NULL, 0);\n}\n\nvector_clock * init_local_vc_id(int local_id)\n{\n    int64_t counter = 0;\n\n    return init_vc(1, &local_id, &counter, 0);\n}\n\nvector_clock * init_local_vc(struct sockaddr * x)\n{\n    assert(x != NULL);\n\n    return init_local_vc_id(get_node_id(x));\n}\n\nvector_clock * copy_vc(vector_clock * vc1)\n{\n    vector_clock * vc = (vector_clock *) malloc(sizeof(struct vector_clock));\n\n    vc->no_nodes = vc1->no_nodes;\n\n    vc->capacity = vc1->capacity;\n\n    vc->node_ids =  (versioned_id *) malloc (vc->capacity * sizeof(struct versioned_id));\n\n    for(int i=0;i<vc->no_nodes;i++)\n    {\n        vc->node_ids[i].node_id = vc1->node_ids[i].node_id;\n        vc->node_ids[i].counter = vc1->node_ids[i].counter;\n    }\n\n    return vc;\n}\n\nvector_clock * init_vc_from_msg(VectorClockMessage * msg)\n{\n    vector_clock * vc = init_vc(msg->n_ids, NULL, NULL, 0);\n\n    for (int i = 0; i < vc->no_nodes; i++)\n    {\n        vc->node_ids[i].node_id = msg->ids[i];\n        vc->node_ids[i].counter = msg->counters[i];\n    }\n\n    return vc;\n}\n\nint grow_vc(vector_clock * vc)\n{\n    vc->capacity = (int)(vc->no_nodes * GROWTH_RATE);\n\n    versioned_id * new_vector = (versioned_id *) malloc (vc->capacity * sizeof (struct versioned_id));\n\n    memcpy(new_vector, vc->node_ids, vc->no_nodes * sizeof (struct versioned_id));\n\n    free(vc->node_ids);\n\n    vc->node_ids = new_vector;\n\n    return 0;\n}\n\nvoid free_vc(vector_clock * vc)\n{\n    if(vc == NULL)\n        return;\n\n    if(vc->node_ids != NULL)\n        free(vc->node_ids);\n    free(vc);\n}\n\nvoid init_vc_msg(VectorClockMessage * msg_ptr, vector_clock * vc)\n{\n     msg_ptr->n_ids = vc->no_nodes;\n     msg_ptr->ids = (int32_t *) malloc (msg_ptr->n_ids * sizeof(int32_t));\n     msg_ptr->n_counters = vc->no_nodes;\n     msg_ptr->counters = (int64_t *) malloc (msg_ptr->n_counters * sizeof(int64_t));\n     for (int i = 0; i < msg_ptr->n_ids; i++)\n     {\n         (msg_ptr->ids)[i] = vc->node_ids[i].node_id;\n         (msg_ptr->counters)[i] = vc->node_ids[i].counter;\n     }\n}\n\nvoid free_vc_msg(VectorClockMessage * msg)\n{\n    free(msg->ids);\n    free(msg->counters);\n}\n\nchar * to_string_vc(vector_clock * vc, char * msg_buff)\n{\n    char * crt_ptr = msg_buff;\n\n    if(vc == NULL)\n    {\n        sprintf(crt_ptr, \"VC(NULL)\");\n        return msg_buff;\n    }\n\n    sprintf(crt_ptr, \"VC(\");\n    crt_ptr += strlen(crt_ptr);\n\n    for(int i=0;i<vc->no_nodes;i++)\n    {\n        sprintf(crt_ptr, \"%s%d:%\" PRId64, i>0?\", \":\"\", vc->node_ids[i].node_id, vc->node_ids[i].counter);\n        crt_ptr += strlen(crt_ptr);\n    }\n\n    sprintf(crt_ptr, \")\");\n\n    return msg_buff;\n}\n\n\n\n"
  },
  {
    "path": "backend/failure_detector/vector_clock.h",
    "content": "/*\n * vector_clock.h\n *\n * Author: aagapi\n */\n\n#ifndef BACKEND_FAILURE_DETECTOR_VECTOR_CLOCK_H_\n#define BACKEND_FAILURE_DETECTOR_VECTOR_CLOCK_H_\n\n#define DEFAULT_SIZE 8\n#define GROWTH_RATE 2.0\n\n#define VC_INCOMPARABLE -2\n#define VC_DISJOINT -3\n\n#include \"db_messages.pb-c.h\"\n#include <sys/socket.h>\n#include <netinet/in.h>\n#include <netinet/ip.h>\n#include <inttypes.h>\n\n// Sets in found_idx index of node_id (if found), or first smallest index (if not found):\n#define BINARY_SEARCH_NODEID(vc, node_id, found_idx, exact_match)                       \\\n       (exact_match) = 0;                                                           \\\n       (found_idx) = -1;                                                                \\\n       int first = 0, last = (vc)->no_nodes - 1;                                    \\\n       int middle = (first+last)/2;                                                     \\\n       for(;first <= last; middle = (first + last)/2)                               \\\n       {                                                                            \\\n           if((vc)->node_ids[middle].node_id == (node_id))                          \\\n           {                                                                        \\\n               (found_idx) = middle;                                                \\\n               (exact_match) = 1;                                                   \\\n               break;                                                               \\\n           }                                                                        \\\n           else if((vc)->node_ids[middle].node_id < (node_id))                      \\\n           {                                                                        \\\n               (found_idx) = middle;                                                \\\n               first = middle + 1;                                                  \\\n           }                                                                        \\\n           else                                                                         \\\n               last = middle - 1;                                                   \\\n       }                                                                            \\\n\ntypedef struct versioned_id\n{\n    int node_id;\n    int64_t counter;\n} versioned_id;\n\ntypedef struct vector_clock\n{\n    int no_nodes;\n    int capacity;\n    versioned_id * node_ids;\n} vector_clock;\n\nint increment_vc(vector_clock * vc, int node_id);\n\nint compare_vc(vector_clock * vc1, vector_clock * vc2);\n\nint update_vc(vector_clock * vc_dest, vector_clock * vc_src);\n\nint update_or_replace_vc(vector_clock ** vc_dest, vector_clock * vc_src);\n\nint add_component_vc(vector_clock * vc, int node_id, int initial_counter);\n\nint64_t get_component_vc(vector_clock * vc, int node_id);\n\nint remove_component_vc(vector_clock * vc, int node_id);\n\nvector_clock * init_vc(int init_no_nodes, int * node_ids, int64_t * counters, int sort_node_ids);\n\nvector_clock * init_empty_vc();\n\nvector_clock * init_local_vc_id(int local_id);\n\nvector_clock * init_local_vc(struct sockaddr * x);\n\nvector_clock * copy_vc(vector_clock * vc1);\n\nvector_clock * init_vc_from_msg(VectorClockMessage * msg);\n\nvoid init_vc_msg(VectorClockMessage * msg_ptr, vector_clock * vc);\n\nvoid free_vc_msg(VectorClockMessage * msg);\n\nvoid free_vc(vector_clock * vc);\n\nint grow_vc(vector_clock * vc);\n\n// int serialize_vc(vector_clock * vc, void ** buf, unsigned * len);\n\n// int deserialize_vc(void * buf, unsigned msg_len, vector_clock ** vc);\n\nchar * to_string_vc(vector_clock * vc, char * msg_buff);\n\nint get_node_id(struct sockaddr * x);\n\n#endif /* BACKEND_FAILURE_DETECTOR_VECTOR_CLOCK_H_ */\n"
  },
  {
    "path": "backend/fastrand.h",
    "content": "\n#include <time.h>\n\n#ifndef FASTRAND_H_\n#define FASTRAND_H_\n\n#if( defined _POSIX_THREADS && _POSIX_TIMERS >= 0 && _POSIX_MONOTONIC_CLOCK >= 0 )\n#define GET_RANDSEED(seedptr, rand)                                                                             \\\n{                                                                                                           \\\n  struct timespec tp;                                                                                       \\\n  clock_gettime( CLOCK_MONOTONIC_RAW, &tp );                                                                \\\n  *(seedptr) = (unsigned int) ((tp.tv_nsec & 0xFFFFFFFF00000000) + (tp.tv_nsec & 0x00000000FFFFFFFF) + rand) ; \\\n}\n#else\n#define GET_RANDSEED(seedptr, rand)                                                                             \\\n{                                                                                                           \\\n  int64_t now = time(NULL);                                                                                         \\\n  *(seedptr) = (unsigned int) ((now & 0xFFFFFFFF00000000) + (now & 0x00000000FFFFFFFF) + rand) ; \\\n}\n#endif\n\n\n#define FASTRAND(seedptr, value)                \\\n{   *seedptr = (214013*(*seedptr)+2531011); \\\n    value = ((*seedptr)>>16)&0x7FFF;            \\\n}\n\nstatic unsigned int g_seed;\n\ninline static void fast_srand(int seed)\n{\n    g_seed = seed;\n}\n\ninline static int fastrand()\n{\n    g_seed = (214013*g_seed+2531011);\n\n    return (g_seed>>16)&0x7FFF;\n}\n\n\n#endif /* FASTRAND_H_ */\n"
  },
  {
    "path": "backend/hash_ring.c",
    "content": "/*\n * Copyright (C) 2019-2021 Deutsche Telekom AG\n *\n * Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:\n *\n * 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.\n *\n * 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.\n *\n * 3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission.\n *\n * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS \"AS IS\" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n */\n\n/*\n * hash_ring.c\n *  - Thread safe consistent hashing API\n *      Author: aagapi\n */\n\n#include \"hash_ring.h\"\n#include \"hashes.h\"\n\nhash_ring * get_hash_ring()\n{\n    hash_ring * ring = (hash_ring *) malloc(sizeof(hash_ring) + sizeof(pthread_mutex_t));\n    memset(ring, 0, sizeof(hash_ring) + sizeof(pthread_mutex_t));\n    ring->buckets = create_skiplist_long();\n    ring->live_buckets = 0;\n    ring->lock = (pthread_mutex_t*) ((char*) ring + sizeof(hash_ring));\n    pthread_mutex_init(ring->lock, NULL);\n    return ring;\n}\n\nvoid free_hash_ring(hash_ring * ring, void (*free_val)(WORD))\n{\n    if(free_val == NULL)\n    {\n        skiplist_free(ring->buckets);\n    }\n    else\n    {\n        skiplist_free_val(ring->buckets, free_val);\n    }\n    free(ring);\n}\n\nint add_bucket(hash_ring * ring, WORD bucket, void* (*get_key)(void *), void* (*get_live_field)(void *), unsigned int * fastrandstate)\n{\n    pthread_mutex_lock(ring->lock);\n\n    uint32_t id_hash = hash32((uint32_t) get_key(bucket));\n\n    if(skiplist_search(ring->buckets, (WORD) id_hash) != NULL)\n    {\n        pthread_mutex_unlock(ring->lock);\n        return -1;\n    }\n\n    if(*((int *) get_live_field(bucket)) == BUCKET_LIVE)\n        ring->live_buckets++;\n\n    int status = skiplist_insert(ring->buckets, (WORD) id_hash, bucket, fastrandstate);\n\n    pthread_mutex_unlock(ring->lock);\n\n    return status;\n}\n\nsnode_t * lookup_bucket(hash_ring * ring, WORD bucket_id)\n{\n    WORD id_hash = (WORD) hash32((uint32_t) bucket_id);\n    return skiplist_search(ring->buckets, id_hash);\n}\n\nint get_bucket_status(hash_ring * ring, WORD bucket, void* (*get_key)(void *), void* (*get_live_field)(void *))\n{\n    snode_t * node = NULL;\n    pthread_mutex_lock(ring->lock);\n\n    uint32_t id_hash = hash32((uint32_t) get_key(bucket));\n\n    node = skiplist_search(ring->buckets, (WORD) id_hash);\n\n    if(node == NULL)\n    {\n        pthread_mutex_unlock(ring->lock);\n        return -1;\n    }\n\n    int status = *((int *) get_live_field(node->value));\n\n    pthread_mutex_unlock(ring->lock);\n\n    return status;\n}\n\nint set_bucket_status(hash_ring * ring, WORD bucket, int status, void* (*get_key)(void *), void* (*get_live_field)(void *))\n{\n    snode_t * node = NULL;\n    pthread_mutex_lock(ring->lock);\n\n    uint32_t id_hash = hash32((uint32_t) bucket); // hash32((uint32_t) get_key(bucket));\n\n    node = skiplist_search(ring->buckets, (WORD) id_hash);\n\n    if(node == NULL)\n    {\n        pthread_mutex_unlock(ring->lock);\n        return -1;\n    }\n\n    if(*((int *) get_live_field(node->value)) != status)\n    {\n        if(status == BUCKET_LIVE)\n            ring->live_buckets++;\n        else\n            ring->live_buckets--;\n    }\n\n    *((int *) get_live_field(node->value)) = status;\n\n    pthread_mutex_unlock(ring->lock);\n\n    return 0;\n}\n\nint mark_bucket_dead(hash_ring * ring, WORD bucket, void* (*get_key)(void *), void* (*get_live_field)(void *))\n{\n    return set_bucket_status(ring, bucket, BUCKET_DEAD, get_key, get_live_field);\n}\n\nint mark_bucket_live(hash_ring * ring, WORD bucket, void* (*get_key)(void *), void* (*get_live_field)(void *))\n{\n    return set_bucket_status(ring, bucket, BUCKET_LIVE, get_key, get_live_field);\n}\n\nWORD get_buckets_for_object(hash_ring * ring, int object_id, int replication_factor,\n                            void* (*get_key)(void *), void* (*get_live_field)(void *),\n                            unsigned int * fastrandstate)\n{\n    pthread_mutex_lock(ring->lock);\n\n    skiplist_t * result = (replication_factor > 1)?create_skiplist_long():NULL;\n    int status = 0;\n\n    int replicas = (replication_factor < ring->live_buckets)?replication_factor:ring->live_buckets;\n\n    if(replicas == 0)\n    {\n        pthread_mutex_unlock(ring->lock);\n\n        return NULL;\n    }\n\n    snode_t * snode = skiplist_search_higher(ring->buckets, (WORD) hash32((uint32_t) object_id));\n\n    while(result == NULL || result->no_items < replicas)\n    {\n        if(snode == NULL)\n        {\n            // Wrap back to the beginning of the ring:\n            snode = HEAD(ring->buckets);\n        }\n\n        if(*((int *) get_live_field(snode->value)) == BUCKET_LIVE)\n        {\n            if(replication_factor > 1)\n            {\n                status = skiplist_insert(result, (WORD) get_key(snode->value), snode->value, fastrandstate);\n                assert(status == 0);\n            }\n\n            pthread_mutex_unlock(ring->lock);\n\n            return (WORD) snode->value;\n        }\n\n        snode = NEXT(snode);\n    }\n\n    pthread_mutex_unlock(ring->lock);\n\n    return (WORD) result;\n}\n\n"
  },
  {
    "path": "backend/hash_ring.h",
    "content": "/*\n * Copyright (C) 2019-2021 Deutsche Telekom AG\n *\n * Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:\n *\n * 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.\n *\n * 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.\n *\n * 3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission.\n *\n * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS \"AS IS\" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n */\n\n/*\n * hash_ring.h\n *  - Thread safe consistent hashing API\n *      Author: aagapi\n */\n\n#ifndef BACKEND_HASH_RING_H_\n#define BACKEND_HASH_RING_H_\n\n#include \"common.h\"\n#include \"skiplist.h\"\n\n#define BUCKET_LIVE 0\n#define BUCKET_DEAD 1\n\ntypedef struct hash_ring\n{\n    skiplist_t * buckets;\n    int live_buckets;\n    pthread_mutex_t * lock;\n} hash_ring;\n\nhash_ring * get_hash_ring();\nvoid free_hash_ring(hash_ring * ring, void (*free_val)(WORD));\nint add_bucket(hash_ring * ring, WORD bucket, void * (*get_key)(void *), void * (*get_live_field)(void *), unsigned int * fastrandstate);\nsnode_t * lookup_bucket(hash_ring * ring, WORD bucket_id);\nint get_bucket_status(hash_ring * ring, WORD bucket, void * (*get_key)(void *), void * (*get_live_field)(void *));\nint set_bucket_status(hash_ring * ring, WORD bucket, int status, void * (*get_key)(void *), void * (*get_live_field)(void *));\nint mark_bucket_dead(hash_ring * ring, WORD bucket, void * (*get_key)(void *), void * (*get_live_field)(void *));\nint mark_bucket_live(hash_ring * ring, WORD bucket, void * (*get_key)(void *), void * (*get_live_field)(void *));\nWORD get_buckets_for_object(hash_ring * ring, int object_id, int replication_factor,\n                            void * (*get_key)(void *), void * (*get_live_field)(void *),\n                            unsigned int * fastrandstate);\n\n#endif /* BACKEND_HASH_RING_H_ */\n"
  },
  {
    "path": "backend/hashes.h",
    "content": "/*\n * Copyright (C) 2019-2021 Deutsche Telekom AG\n *\n * Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:\n *\n * 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.\n *\n * 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.\n *\n * 3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission.\n *\n * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS \"AS IS\" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n */\n\n#ifndef BACKEND_HASHES_H_\n#define BACKEND_HASHES_H_\n\nuint32_t hash32(uint32_t x)\n// Collision free, each input bit affects each output bit with ~50% probability\n{\n    x = ((x >> 16) ^ x) * 0x45d9f3b;\n    x = ((x >> 16) ^ x) * 0x45d9f3b;\n    x = (x >> 16) ^ x;\n    return x;\n}\n\n#endif /* BACKEND_HASHES_H_ */\n"
  },
  {
    "path": "backend/log.c",
    "content": "/*\n * Copyright (c) 2020 rxi\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to\n * deal in the Software without restriction, including without limitation the\n * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or\n * sell copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING\n * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS\n * IN THE SOFTWARE.\n */\n\n#include \"log.h\"\n\n#define MAX_CALLBACKS 32\n\ntypedef struct {\n  log_LogFn fn;\n  void *udata;\n  int level;\n} Callback;\n\nstatic struct {\n  void *udata;\n  log_LockFn lock;\n  int level;\n  bool quiet;\n  Callback callbacks[MAX_CALLBACKS];\n} L;\n\n\nstatic const char *level_strings[] = {\n  \"TRACE\", \"DEBUG\", \"INFO\", \"WARN\", \"ERROR\", \"FATAL\"\n};\n\n#ifdef LOG_USE_COLOR\nstatic const char *level_colors[] = {\n  \"\\x1b[94m\", \"\\x1b[36m\", \"\\x1b[32m\", \"\\x1b[33m\", \"\\x1b[31m\", \"\\x1b[35m\"\n};\n#endif\n\n\nstatic void stdout_callback(log_Event *ev) {\n  char buf[16];\n  buf[strftime(buf, sizeof(buf), \"%H:%M:%S\", ev->date)] = '\\0';\n#ifdef LOG_USE_COLOR\n  fprintf(\n    ev->udata, \"%s.%06lu %s%-5s\\x1b[0m \\x1b[90m%-20s:%5d:\\x1b[0m \",\n    buf, ev->ts.tv_nsec/1000, level_colors[ev->level], level_strings[ev->level],\n    ev->file, ev->line);\n#else\n  fprintf(\n    ev->udata, \"%s.%06lu %-5s %-20s:%5d: \",\n    buf, ev->ts.tv_nsec/1000, level_strings[ev->level], ev->file, ev->line);\n#endif\n  vfprintf(ev->udata, ev->fmt, ev->ap);\n  fprintf(ev->udata, \"\\n\");\n  fflush(ev->udata);\n}\n\n\nstatic void file_callback(log_Event *ev) {\n  char buf[64];\n  buf[strftime(buf, sizeof(buf), \"%Y-%m-%d %H:%M:%S\", ev->date)] = '\\0';\n  fprintf(\n    ev->udata, \"%s.%09lu %-5s %-20s:%5d: \",\n    buf, ev->ts.tv_nsec, level_strings[ev->level], ev->file, ev->line);\n  vfprintf(ev->udata, ev->fmt, ev->ap);\n  fprintf(ev->udata, \"\\n\");\n  fflush(ev->udata);\n}\n\n\nstatic void lock(void)   {\n  if (L.lock) { L.lock(true, L.udata); }\n}\n\n\nstatic void unlock(void) {\n  if (L.lock) { L.lock(false, L.udata); }\n}\n\n\nconst char* log_level_string(int level) {\n  return level_strings[level];\n}\n\n\nvoid log_set_lock(log_LockFn fn, void *udata) {\n  L.lock = fn;\n  L.udata = udata;\n}\n\n\nvoid log_set_level(int level) {\n  L.level = level;\n}\n\n\nvoid log_set_quiet(bool enable) {\n  L.quiet = enable;\n}\n\n\nint log_add_callback(log_LogFn fn, void *udata, int level) {\n  for (int i = 0; i < MAX_CALLBACKS; i++) {\n    if (!L.callbacks[i].fn) {\n      L.callbacks[i] = (Callback) { fn, udata, level };\n      return 0;\n    }\n  }\n  return -1;\n}\n\n\nint log_add_fp(FILE *fp, int level) {\n  return log_add_callback(file_callback, fp, level);\n}\n\n\nstatic void init_event(log_Event *ev, void *udata) {\n  if (!ev->date) {\n    clock_gettime(CLOCK_REALTIME, &ev->ts);\n    ev->date = localtime(&ev->ts.tv_sec);\n  }\n  ev->udata = udata;\n}\n\n\nvoid log_log(int level, const char *file, int line, const char *fmt, ...) {\n  log_Event ev = {\n    .fmt   = fmt,\n    .file  = file,\n    .line  = line,\n    .level = level,\n  };\n\n  lock();\n\n  if (!L.quiet && level >= L.level) {\n    init_event(&ev, stderr);\n    va_start(ev.ap, fmt);\n    stdout_callback(&ev);\n    va_end(ev.ap);\n  }\n\n  for (int i = 0; i < MAX_CALLBACKS && L.callbacks[i].fn; i++) {\n    Callback *cb = &L.callbacks[i];\n    if (level >= cb->level) {\n      init_event(&ev, cb->udata);\n      va_start(ev.ap, fmt);\n      cb->fn(&ev);\n      va_end(ev.ap);\n    }\n  }\n\n  unlock();\n}\n"
  },
  {
    "path": "backend/log.h",
    "content": "/**\n * Copyright (c) 2020 rxi\n *\n * This library is free software; you can redistribute it and/or modify it\n * under the terms of the MIT license. See `log.c` for details.\n */\n\n#ifndef LOG_H\n#define LOG_H\n\n#include <stdio.h>\n#include <stdarg.h>\n#include <stdbool.h>\n#include <time.h>\n\n#define LOG_VERSION \"0.1.0\"\n\ntypedef struct {\n  va_list ap;\n  const char *fmt;\n  const char *file;\n  struct timespec ts;\n  struct tm *date;\n  void *udata;\n  int line;\n  int level;\n} log_Event;\n\ntypedef void (*log_LogFn)(log_Event *ev);\ntypedef void (*log_LockFn)(bool lock, void *udata);\n\nenum { LOG_TRACE, LOG_DEBUG, LOG_INFO, LOG_WARN, LOG_ERROR, LOG_FATAL };\n\n#define log_trace(...) log_log(LOG_TRACE, __FILE__, __LINE__, __VA_ARGS__)\n#define log_debug(...) log_log(LOG_DEBUG, __FILE__, __LINE__, __VA_ARGS__)\n#define log_info(...)  log_log(LOG_INFO,  __FILE__, __LINE__, __VA_ARGS__)\n#define log_warn(...)  log_log(LOG_WARN,  __FILE__, __LINE__, __VA_ARGS__)\n#define log_error(...) log_log(LOG_ERROR, __FILE__, __LINE__, __VA_ARGS__)\n#define log_fatal(...) log_log(LOG_FATAL, __FILE__, __LINE__, __VA_ARGS__)\n\nconst char* log_level_string(int level);\nvoid log_set_lock(log_LockFn fn, void *udata);\nvoid log_set_level(int level);\nvoid log_set_quiet(bool enable);\nint log_add_callback(log_LogFn fn, void *udata, int level);\nint log_add_fp(FILE *fp, int level);\n\nvoid log_log(int level, const char *file, int line, const char *fmt, ...);\n\n#endif\n"
  },
  {
    "path": "backend/queue.c",
    "content": "/*\n * Copyright (C) 2019-2021 Deutsche Telekom AG\n *\n * Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:\n *\n * 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.\n *\n * 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.\n *\n * 3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission.\n *\n * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS \"AS IS\" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n */\n\n/*\n * queue.c\n *\n *      Author: aagapi\n */\n\n#include \"queue.h\"\n#include \"log.h\"\n#include \"failure_detector/cells.h\"\n#include \"failure_detector/db_queries.h\"\n\n#include <limits.h>\n#include <assert.h>\n#include <stdlib.h>\n#include <stdio.h>\n\n#define MIN(x, y) (((x)<(y))?(x):(y))\n#define MAX(x, y) (((x)>(y))?(x):(y))\n\n#define VERBOSITY 1\n#define LOCK_VERBOSITY 0\n\ndb_table_t * get_table_by_key(WORD table_key, db_t * db)\n{\n    snode_t * node = skiplist_search(db->tables, table_key);\n    if(node == NULL)\n        return NULL;\n\n    return (db_table_t *) (node->value);\n}\n\nint create_queue_table(WORD table_id, int no_cols, int * col_types, db_t * db, unsigned int * fastrandstate) {\n    int primary_key_idx = 0; // queue_id\n    int clustering_key_idx = 1; // entry_id\n    int total_cols = no_cols+2;\n\n    int * total_col_types = (int *) malloc(total_cols * sizeof(int));\n\n    for(int i=0;i<total_cols;i++)\n        total_col_types[i] = ((i<2)?(DB_TYPE_INT64):(col_types[i-2]));\n\n    db_schema_t* db_schema = db_create_schema(total_col_types, total_cols,\n                                            &primary_key_idx, 1,\n                                            &clustering_key_idx, 1,\n                                            NULL, 0);\n\n    assert(db_schema != NULL && \"Schema creation failed\");\n\n    // Create queue table:\n\n    int ret = db_create_table(table_id, db_schema, db, fastrandstate);\n\n#if (VERBOSITY > 0)\n    log_info(\"Queue table %\" PRId64 \" created\", (int64_t) table_id);\n#endif\n\n    return ret;\n}\n\n// Functions for handling remote notifications:\n\nint get_queue_notification_packet(WORD table_key, WORD queue_id, WORD app_id, WORD shard_id, WORD consumer_id, WORD group_id,\n                                    int64_t new_no_entries, int status,\n                                    void ** snd_buf, unsigned * snd_msg_len)\n{\n    cell_address ca;\n\n    copy_cell_address(&ca, (int64_t) table_key, (int64_t *) &queue_id, 1);\n\n    queue_query_message * m = init_queue_notification(&ca, NULL, 0, (int) app_id, (int) shard_id, (int) consumer_id, (int) group_id, new_no_entries, status, NULL, -1);\n\n#if (VERBOSE_RPC > 0)\n    char print_buff[1024];\n    to_string_queue_message(m, (char *) print_buff);\n    log_debug(\"Sending queue notification message: %s\", print_buff);\n#endif\n\n    int ret = serialize_queue_message(m, snd_buf, snd_msg_len, 0, NULL);\n\n    assert(ret == 0);\n\n    free_queue_message(m);\n\n    return ret;\n}\n\nint notify_remote_queue_subscribers(WORD table_key, WORD queue_id, db_t * db)\n{\n    db_table_t * table = get_table_by_key(table_key, db);\n    int status = 0;\n\n    if(table == NULL)\n        return DB_ERR_NO_TABLE; // Table doesn't exist\n\n    snode_t * node = skiplist_search(table->rows, queue_id);\n    if(node == NULL)\n        return DB_ERR_NO_QUEUE; // Queue doesn't exist\n\n    db_row_t * db_row = (db_row_t *) (node->value);\n\n    // Notify remote subscribers if they haven't been notified:\n\n    for(snode_t * cell=HEAD(db_row->consumer_state);cell!=NULL;cell=NEXT(cell))\n    {\n        if(cell->value != NULL)\n        {\n            consumer_state * cs = (consumer_state *) (cell->value);\n\n            if(cs->callback != NULL || cs->notified > 0) // Skip local subscribers or ones that have already been notified:\n                continue;\n\n            assert(cs->sockfd != NULL);\n\n            if(*(cs->sockfd) == 0)\n            {\n#if (VERBOSITY > 0)\n                log_debug(\"SERVER: Skipping notifying disconnected subscriber %\" PRId64 \"\", (int64_t) cs->consumer_id);\n                continue;\n#endif\n            }\n\n            void * snd_buf = NULL;\n            unsigned snd_msg_len = -1;\n            status = get_queue_notification_packet(table_key, queue_id, cs->app_id, cs->shard_id,\n                                                        cs->consumer_id, cs->group_id,\n                                                        db_row->no_entries, 0,\n                                                        &snd_buf, &snd_msg_len);\n            assert(status == 0);\n\n            int n = write(*(cs->sockfd), snd_buf, snd_msg_len);\n            if (n < 0)\n            {\n                    log_error(\"ERROR writing notification to socket!\");\n                    continue;\n            }\n\n            free(snd_buf);\n\n            cs->notified=1;\n\n#if (VERBOSITY > 0)\n            log_debug(\"SERVER: Notified remote subscriber %\" PRId64 \"\", (int64_t) cs->consumer_id);\n#endif\n        }\n    }\n\n    return status;\n}\n\nvoid notify_subscriber(consumer_state * cs, WORD table_key, WORD queue_id, db_row_t * db_row)\n{\n    int status = 0, ret = 0;\n\n    if(cs->group_id >= 0) // Skip group subscribers (these will be notified via their group)\n    {\n// #if (VERBOSITY > 0)\n//        log_debug(\"BACKEND: Skipping notifying group subscriber %\" PRId64 \" for queue %d because it will be notified via group notifications\", (int64_t) cs->consumer_id, (int) queue_id);\n// #endif\n        return;\n    }\n\n    if(cs->notified > 0) // Skip already notified subscribers (whether local or remote)\n    {\n// #if (VERBOSITY > 0)\n//        log_debug(\"BACKEND: Skipping notifying subscriber %\" PRId64 \" for queue %d because it was already notified\", (int64_t) cs->consumer_id);\n// #endif\n        return;\n    }\n\n    if(cs->callback != NULL) // Local subscriber\n    {\n        assert(cs->sockfd == NULL);\n\n        queue_callback_args * qca = get_queue_callback_args(table_key, queue_id, cs->app_id, cs->shard_id, cs->consumer_id, cs->group_id, QUEUE_NOTIF_ENQUEUED);\n\n#if (VERBOSITY > 0)\n        log_debug(\"BACKEND: Attempting to notify local subscriber %\" PRId64 \" (%p/%p/%p/%p)\", (int64_t) qca->consumer_id, cs->callback, cs->callback->lock, cs->callback->signal, cs->callback->callback);\n#endif\n\n        ret = pthread_mutex_lock(cs->callback->lock);\n\n#if (LOCK_VERBOSITY > 0)\n        log_debug(\"BACKEND: Locked consumer lock of %\" PRId64 \" (%p/%p), status=%d\", (int64_t) qca->consumer_id, cs->callback, cs->callback->lock, ret);\n#endif\n\n        pthread_cond_signal(cs->callback->signal);\n        cs->callback->callback(qca);\n        ret = pthread_mutex_unlock(cs->callback->lock);\n\n#if (LOCK_VERBOSITY > 0)\n        log_debug(\"BACKEND: Unlocked consumer lock of %\" PRId64 \" (%p/%p), status=%d\", (int64_t) qca->consumer_id, cs->callback, cs->callback->lock, ret);\n#endif\n    }\n    else // remote subscriber\n    {\n        assert(cs->sockfd != NULL);\n\n        if(*(cs->sockfd) == 0)\n        {\n#if (VERBOSITY > 0)\n            log_debug(\"SERVER: Skipping notifying disconnected remote subscriber %\" PRId64 \"\", (int64_t) cs->consumer_id);\n#endif\n            return;\n        }\n\n        void * snd_buf = NULL;\n        unsigned snd_msg_len = -1;\n        status = get_queue_notification_packet(table_key, queue_id,\n                                                cs->app_id, cs->shard_id, cs->consumer_id, cs->group_id,\n                                                db_row->no_entries, 0,\n                                                &snd_buf, &snd_msg_len);\n        assert(status == 0);\n\n        int n = write(*(cs->sockfd), snd_buf, snd_msg_len);\n        if (n < 0)\n        {\n              fprintf(stderr, \"ERROR writing notification to socket!\\n\");\n              return;\n        }\n\n        free(snd_buf);\n    }\n\n    cs->notified=1;\n\n#if (VERBOSITY > 0)\n    log_debug(\"BACKEND: Notified %s subscriber %\" PRId64 \"\", (cs->callback != NULL)?\"local\":\"remote\", (int64_t) cs->consumer_id);\n#endif\n}\n\nvoid notify_subscribers(skiplist_t * subscriber_list, WORD table_key, WORD queue_id, db_row_t * db_row)\n{\n    for(snode_t * cell=HEAD(subscriber_list);cell!=NULL;cell=NEXT(cell))\n    {\n        if(cell->value != NULL)\n        {\n            consumer_state * cs = (consumer_state *) (cell->value);\n\n            notify_subscriber(cs, table_key, queue_id, db_row);\n        }\n    }\n}\n\nint enqueue(WORD * column_values, int no_cols, size_t last_blob_size, WORD table_key, WORD queue_id, short use_lock, db_t * db, unsigned int * fastrandstate)\n{\n    db_table_t * table = get_table_by_key(table_key, db);\n    int ret = 0;\n\n    if(table == NULL)\n        return DB_ERR_NO_TABLE; // Table doesn't exist\n\n    snode_t * node = skiplist_search(table->rows, queue_id);\n    if(node == NULL)\n        return DB_ERR_NO_QUEUE; // Queue doesn't exist\n\n    db_row_t * db_row = (db_row_t *) (node->value);\n\n    if(use_lock)\n    {\n        pthread_mutex_lock(db_row->enqueue_lock);\n    }\n\n    int64_t entry_id = db_row->no_entries;\n    db_row->no_entries++;\n\n    if(use_lock)\n    {\n        pthread_mutex_unlock(db_row->enqueue_lock);\n    }\n\n    // Add queue_id as partition key and entry_id as clustering key:\n\n    WORD * queue_column_values = (WORD *) malloc((no_cols + 2) * sizeof(WORD));\n    queue_column_values[0]=queue_id;\n    queue_column_values[1]=(WORD) entry_id;\n    for(int64_t i=2;i<no_cols + 2;i++)\n        queue_column_values[i]=column_values[i-2];\n\n    int status = table_insert(queue_column_values, no_cols+2, 1, last_blob_size, NULL, table, fastrandstate);\n\n#if (VERBOSITY > 0)\n    log_debug(\"BACKEND: Inserted queue entry %\" PRId64 \" in queue %\" PRId64 \"/%\" PRId64 \", status=%d\", entry_id, (int64_t) table_key, (int64_t) queue_id, status);\n#endif\n\n    // Notify individual queue subscribers if they haven't been notified:\n\n    notify_subscribers(db_row->consumer_state, table_key, queue_id, db_row);\n\n    // Similarly notify all group subscribers:\n\n    if(db_row->group_subscriptions != NULL)\n    {\n        if(db->queue_group_replication_factor > 1)\n        {\n            for(snode_t * cell=HEAD((skiplist_t *) db_row->group_subscriptions);cell!=NULL;cell=NEXT(cell))\n            {\n                group_state * gs = (group_state *) (cell->value);\n\n                notify_subscribers(gs->consumers, table_key, queue_id, db_row);\n            }\n        }\n        else\n        {\n            notify_subscribers(((group_state *) db_row->group_subscriptions)->consumers, table_key, queue_id, db_row);\n\n#if (VERBOSITY > 0)\n            log_debug(\"BACKEND: Notified group subscribers from group %d (%d subscribers)\",\n                            (int) ((group_state *) db_row->group_subscriptions)->group_id,\n                            ((group_state *) db_row->group_subscriptions)->consumers->no_items);\n#endif\n        }\n    }\n\n    return status;\n}\n\nint lookup_consumer_state_in_group(WORD queue_id, WORD consumer_id, db_row_t * db_row,\n                                    consumer_state ** cs, db_t * db)\n{\n    if(db_row->group_subscriptions == NULL) // Queue's group is already cached by 'auto_update_group_queue_subscriptions()', no need to call 'get_buckets_for_object()' again\n    {\n        log_debug(\"SERVER: lookup_consumer_state_in_group(%d), found no group state!\", (int) queue_id);\n\n        *cs = NULL;\n\n        return DB_ERR_NO_GROUP;\n    }\n\n    if(db->queue_group_replication_factor == 1)\n    {\n        group_state * gs = (group_state *) db_row->group_subscriptions;\n\n        log_debug(\"SERVER: lookup_consumer_state_in_group(%d, %d), found group state: group_id = %d, status = %d, consumers = %d\",\n                (int) queue_id, (int) consumer_id, ((gs != NULL)?((int) gs->group_id):(-1)),\n                ((gs != NULL)?((int) gs->status):(-1)),\n                ((gs != NULL)?((int) gs->consumers->no_items):(-1)));\n\n        return lookup_listener_in_group(gs, consumer_id, queue_id, cs);\n    }\n    else\n    {\n        skiplist_t * gss = (skiplist_t *) db_row->group_subscriptions;\n\n        for(snode_t * cell=HEAD(gss);cell!=NULL;cell=NEXT(cell))\n        {\n            if(cell->value != NULL)\n            {\n                group_state * gs = (group_state *) cell->value;\n\n                int ret = lookup_listener_in_group(gs, consumer_id, queue_id, cs);\n\n                if(ret == 0)\n                {\n                    log_debug(\"SERVER: lookup_consumer_state_in_group(%d), found group state: group_id = %d, status = %d, consumers = %d\",\n                            (int) queue_id, ((gs != NULL)?((int) gs->group_id):(-1)),\n                            ((gs != NULL)?((int) gs->status):(-1)),\n                            ((gs != NULL)?((int) gs->consumers->no_items):(-1)));\n\n                    return 0;\n                }\n            }\n        }\n\n        return DB_ERR_NO_CONSUMER;\n    }\n}\n\nint lookup_consumer_state_in_row_or_group(WORD queue_id, WORD consumer_id, db_row_t * db_row,\n                                           consumer_state ** cs, consumer_state ** group_cs, db_t * db)\n{\n\t*cs = NULL;\n\t*group_cs = NULL;\n\n\tsnode_t * consumer_node = skiplist_search(db_row->consumer_state, consumer_id);\n\tif(consumer_node == NULL)\n\t\treturn DB_ERR_NO_CONSUMER;\n\n\t*cs = (consumer_state *) (consumer_node->value);\n\n\tlookup_consumer_state_in_group(queue_id, consumer_id, db_row, group_cs, db);\n\n\treturn 0;\n}\n\nvoid sanity_check_consumer_read_heads(int64_t old_read_head, int64_t old_consume_head, int64_t new_read_head)\n{\n    assert(old_read_head <= new_read_head);\n\n    assert(old_consume_head <= new_read_head);\n}\n\nvoid sanity_check_consumer_consume_heads(int64_t old_read_head, int64_t old_consume_head, int64_t new_consume_head)\n{\n    assert(old_read_head >= new_consume_head);\n\n    assert(old_consume_head <= new_consume_head);\n\n}\n\nint is_consumer_notified(consumer_state * cs, consumer_state * gqcs)\n{\n\treturn (gqcs != NULL)?(gqcs->notified):(cs->notified);\n}\n\nvoid set_consumer_notified(consumer_state * cs, consumer_state * gqcs, int value)\n{\n    if(gqcs != NULL)\n    \tgqcs->notified=value;\n\n    cs->notified=value;\n}\n\nint set_private_read_head(WORD consumer_id, WORD shard_id, WORD app_id, WORD table_key, WORD queue_id,\n                            int64_t new_read_head, vector_clock * version, short use_lock, db_t * db)\n{\n    db_table_t * table = get_table_by_key(table_key, db);\n    if(table == NULL)\n        return DB_ERR_NO_TABLE; // Table doesn't exist\n    snode_t * node = skiplist_search(table->rows, queue_id);\n    if(node == NULL)\n        return DB_ERR_NO_QUEUE; // Queue doesn't exist\n\n    db_row_t * db_row = (db_row_t *) (node->value);\n\n    int64_t no_entries = db_row->no_entries;\n\n    consumer_state * cs = NULL, * gqcs = NULL;\n\n    int ret = lookup_consumer_state_in_row_or_group(queue_id, consumer_id, db_row, &cs, &gqcs, db);\n\n    if(ret != 0)\n        return ret; // Consumer or group doesn't exist\n\n    assert (cs != NULL || gqcs != NULL);\n\n    if(use_lock)\n    {\n        pthread_mutex_lock(db_row->read_lock);\n    }\n\n    assert(new_read_head <= no_entries - 1);\n\n    assert(version != NULL);\n\n    int64_t old_read_head = READ_HEAD(cs), old_consume_head = CONSUME_HEAD(cs);\n\n    sanity_check_consumer_read_heads(old_read_head, old_consume_head, new_read_head);\n\n    cs->private_read_head = new_read_head;\n\n    update_or_replace_vc(&(cs->prh_version), version);\n\n    if(use_lock)\n    {\n        pthread_mutex_unlock(db_row->read_lock);\n    }\n\n    return 0;\n}\n\nint set_private_consume_head(WORD consumer_id, WORD shard_id, WORD app_id, WORD table_key, WORD queue_id,\n                            int64_t new_consume_head, vector_clock * version, db_t * db)\n{\n    db_table_t * table = get_table_by_key(table_key, db);\n    if(table == NULL)\n        return DB_ERR_NO_TABLE; // Table doesn't exist\n    snode_t * node = skiplist_search(table->rows, queue_id);\n    if(node == NULL)\n        return DB_ERR_NO_QUEUE; // Queue doesn't exist\n\n    db_row_t * db_row = (db_row_t *) (node->value);\n\n    int64_t no_entries = db_row->no_entries;\n\n    consumer_state * cs = NULL, * gqcs = NULL;\n\n    int ret = lookup_consumer_state_in_row_or_group(queue_id, consumer_id, db_row, &cs, &gqcs, db);\n\n    if(ret != 0)\n        return ret; // Consumer or group doesn't exist\n\n    assert (cs != NULL || gqcs != NULL);\n\n    assert(new_consume_head <= no_entries - 1);\n\n    assert(version != NULL);\n\n    int64_t old_read_head = READ_HEAD(cs), old_consume_head = CONSUME_HEAD(cs);\n\n    sanity_check_consumer_consume_heads(old_read_head, old_consume_head, new_consume_head);\n\n    if(old_consume_head <= new_consume_head)\n    {\n    \tcs->private_consume_head = new_consume_head;\n    \tupdate_or_replace_vc(&(cs->pch_version), version);\n    }\n\n    return 0;\n}\n\nint read_queue(WORD consumer_id, WORD shard_id, WORD app_id, WORD table_key, WORD queue_id,\n        int max_entries, int * entries_read, int64_t * new_read_head, vector_clock ** prh_version,\n        snode_t** start_row, snode_t** end_row, short use_lock,\n        db_t * db)\n{\n    db_table_t * table = get_table_by_key(table_key, db);\n    *entries_read=0;\n\n    if(table == NULL)\n        return DB_ERR_NO_TABLE; // Table doesn't exist\n\n    snode_t * node = skiplist_search(table->rows, queue_id);\n    if(node == NULL)\n        return DB_ERR_NO_QUEUE; // Queue doesn't exist\n\n    db_row_t * db_row = (db_row_t *) (node->value);\n\n    int64_t no_entries = db_row->no_entries;\n\n    consumer_state * cs = NULL, * gqcs = NULL;\n\n    int ret = lookup_consumer_state_in_row_or_group(queue_id, consumer_id, db_row, &cs, &gqcs, db);\n\n    if(ret != 0)\n        return ret; // Consumer or group doesn't exist\n\n    assert (cs != NULL || gqcs != NULL);\n\n    if(use_lock)\n    {\n        pthread_mutex_lock(db_row->read_lock);\n    }\n\n    if(cs->private_read_head > no_entries - 1)\n    {\n        log_debug(\"BACKEND: ERROR Subscriber %\" PRId64 \" trying to read from queue %\" PRId64 \" , prev_read_head=%\" PRId64 \", no_entries=%\" PRId64 \"\",\n                        (int64_t) cs->consumer_id, queue_id, cs->private_read_head, no_entries);\n\n        assert(0);\n    }\n\n    int64_t old_read_head = READ_HEAD(cs);\n\n    vector_clock * old_prh_vsn = READ_HEAD_VERSION(cs);\n\n    *prh_version = (old_prh_vsn != NULL)? copy_vc(old_prh_vsn) : NULL;\n\n    if(old_read_head == no_entries - 1)\n    {\n        if(use_lock)\n        {\n            pthread_mutex_unlock(db_row->read_lock);\n        }\n\n        *new_read_head = old_read_head;\n        return QUEUE_STATUS_READ_COMPLETE; // Nothing to read\n    }\n\n    *new_read_head = MIN(old_read_head + max_entries, no_entries - 1);\n    int64_t start_index = old_read_head + 1;\n\n    cs->private_read_head = *new_read_head;\n\n    if(use_lock)\n    {\n        pthread_mutex_unlock(db_row->read_lock);\n    }\n\n    int64_t no_results = (int64_t) table_range_search_clustering((WORD *) &queue_id,\n                                        (WORD*) &start_index, (WORD*) new_read_head, 1,\n                                        start_row, end_row, table);\n\n    assert(no_results == (*new_read_head - start_index + 1));\n\n#if (VERBOSITY > 0)\n    log_debug(\"BACKEND: Subscriber %\" PRId64 \" read %\" PRId64 \" queue entries from queue %\" PRId64 \", new_read_head=%\" PRId64 \"\",\n                    (int64_t) cs->consumer_id, no_results, queue_id, cs->private_read_head);\n#endif\n\n    *entries_read = (int) no_results;\n\n    ret = ((*new_read_head) == (no_entries - 1))? QUEUE_STATUS_READ_COMPLETE : QUEUE_STATUS_READ_INCOMPLETE;\n\n    if(ret == QUEUE_STATUS_READ_COMPLETE)\n    {\n    \tset_consumer_notified(cs, gqcs, 0);\n    }\n\n    return ret;\n}\n\nint peek_queue(WORD consumer_id, WORD shard_id, WORD app_id, WORD table_key, WORD queue_id,\n        int max_entries, int64_t offset, int * entries_read, int64_t * new_read_head, vector_clock ** prh_version,\n        snode_t** start_row, snode_t** end_row, db_t * db)\n{\n    db_table_t * table = get_table_by_key(table_key, db);\n    *entries_read=0;\n\n    if(table == NULL)\n        return DB_ERR_NO_TABLE; // Table doesn't exist\n\n    snode_t * node = skiplist_search(table->rows, queue_id);\n    if(node == NULL)\n        return DB_ERR_NO_QUEUE; // Queue doesn't exist\n\n    db_row_t * db_row = (db_row_t *) (node->value);\n\n    int64_t no_entries = db_row->no_entries;\n\n    consumer_state * cs = NULL, * gqcs = NULL;\n\n    int ret = lookup_consumer_state_in_row_or_group(queue_id, consumer_id, db_row, &cs, &gqcs, db);\n\n    if(ret != 0)\n        return ret; // Consumer or group doesn't exist\n\n    assert (cs != NULL || gqcs != NULL);\n\n    int64_t old_read_head = READ_HEAD(cs);\n\n    vector_clock * old_prh_vsn = READ_HEAD_VERSION(cs);\n\n    int64_t start_offset = (offset >= 0)?offset:old_read_head;\n    assert(start_offset <= no_entries - 1);\n\n    *prh_version = (old_prh_vsn != NULL)? copy_vc(old_prh_vsn) : NULL;\n\n    if(start_offset == no_entries - 1)\n    {\n        *new_read_head = start_offset;\n        return QUEUE_STATUS_READ_COMPLETE; // Nothing to read\n    }\n\n    *new_read_head = MIN(start_offset + max_entries, no_entries - 1);\n    int64_t start_index = start_offset + 1;\n\n    int64_t no_results = (int64_t) table_range_search_clustering((WORD *) &queue_id,\n                                        (WORD*) &start_index, (WORD*) new_read_head, 1,\n                                        start_row, end_row, table);\n\n    assert(no_results == (*new_read_head - start_index + 1));\n\n#if (VERBOSITY > 0)\n    log_debug(\"BACKEND: Subscriber %\" PRId64 \" peeked %\" PRId64 \" / %\" PRId64 \" queue entries, new_read_head=%\" PRId64 \", private_read_head=%\" PRId64 \"\",\n                    (int64_t) cs->consumer_id, no_results, no_entries, *new_read_head, old_read_head);\n#endif\n\n    *entries_read = (int) no_results;\n\n    ret = ((*new_read_head) == (no_entries - 1))? QUEUE_STATUS_READ_COMPLETE : QUEUE_STATUS_READ_INCOMPLETE;\n\n    return ret;\n}\n\nint replay_queue(WORD consumer_id, WORD shard_id, WORD app_id, WORD table_key, WORD queue_id,\n        int64_t replay_offset, int max_entries,\n        int * entries_read, int64_t * new_replay_offset,\n        snode_t** start_row, snode_t** end_row,\n        db_t * db)\n{\n    db_table_t * table = get_table_by_key(table_key, db);\n    *entries_read=0;\n\n    if(table == NULL)\n        return DB_ERR_NO_TABLE; // Table doesn't exist\n\n    snode_t * node = skiplist_search(table->rows, queue_id);\n    if(node == NULL)\n        return DB_ERR_NO_QUEUE; // Queue doesn't exist\n\n    db_row_t * db_row = (db_row_t *) (node->value);\n\n    int64_t no_entries = db_row->no_entries;\n\n    consumer_state * cs = NULL, * gqcs = NULL;\n\n    int ret = lookup_consumer_state_in_row_or_group(queue_id, consumer_id, db_row, &cs, &gqcs, db);\n\n    if(ret != 0)\n        return ret; // Consumer or group doesn't exist\n\n    assert (cs != NULL || gqcs != NULL);\n\n//  set_consumer_notified(cs, gqcs, 0); // Replays don't count as notification consumptions\n\n    int64_t old_read_head = READ_HEAD(cs), old_consume_head = CONSUME_HEAD(cs);\n\n    assert(old_read_head <= no_entries - 1);\n    assert(old_consume_head + replay_offset <= old_read_head);\n\n    if(old_consume_head + replay_offset == old_read_head)\n    {\n        return QUEUE_STATUS_READ_COMPLETE; // // Nothing to replay\n    }\n\n    *new_replay_offset = MIN(old_consume_head + replay_offset + max_entries, old_read_head);\n    int64_t start_index = old_consume_head + replay_offset;\n\n    int64_t no_results = (int64_t) table_range_search_clustering((WORD *) &queue_id,\n                                        (WORD*) &start_index, (WORD*) new_replay_offset, 1,\n                                        start_row, end_row, table);\n    *entries_read = (int) no_results;\n\n    if(no_results != (*new_replay_offset) - start_index)\n    {\n        log_debug(\"table_range_search_clustering(%\" PRId64 \"-%\" PRId64 \") returned %\" PRId64 \" entries!\", start_index, *new_replay_offset, no_results);\n        print_long_db(db);\n        assert(0);\n    }\n\n#if (VERBOSITY > 0)\n    log_debug(\"BACKEND: Subscriber %\" PRId64 \" replayed %\" PRId64 \" queue entries, new_replay_offset=%\" PRId64 \"\",\n                    (int64_t) cs->consumer_id, no_results, *new_replay_offset);\n#endif\n\n    ret = ((*new_replay_offset) == old_read_head)? QUEUE_STATUS_READ_COMPLETE : QUEUE_STATUS_READ_INCOMPLETE;\n\n    return ret;\n}\n\nint consume_queue(WORD consumer_id, WORD shard_id, WORD app_id, WORD table_key, WORD queue_id,\n        int64_t new_consume_head, db_t * db)\n{\n    db_table_t * table = get_table_by_key(table_key, db);\n\n    if(table == NULL)\n        return DB_ERR_NO_TABLE; // Table doesn't exist\n\n    snode_t * node = skiplist_search(table->rows, queue_id);\n    if(node == NULL)\n        return DB_ERR_NO_QUEUE; // Queue doesn't exist\n\n    db_row_t * db_row = (db_row_t *) (node->value);\n\n    consumer_state * cs = NULL, * gqcs = NULL;\n\n    int ret = lookup_consumer_state_in_row_or_group(queue_id, consumer_id, db_row, &cs, &gqcs, db);\n\n    if(ret != 0)\n        return ret; // Consumer or group doesn't exist\n\n    assert (cs != NULL || gqcs != NULL);\n\n    int64_t old_read_head = READ_HEAD(cs), old_consume_head = CONSUME_HEAD(cs);\n\n    set_consumer_notified(cs, gqcs, 0);\n\n    assert(old_consume_head <= old_read_head);\n\n    if(new_consume_head > old_read_head)\n    {\n        return DB_ERR_QUEUE_HEAD_INVALID; // // Invalid consume\n    }\n\n    if(new_consume_head == old_consume_head)\n    {\n        return DB_ERR_QUEUE_COMPLETE; // // Nothing to consume\n    }\n\n    cs->private_consume_head = new_consume_head;\n\n#if (VERBOSITY > 0)\n    log_debug(\"BACKEND: Subscriber %\" PRId64 \" consumed entries, new_consume_head=%\" PRId64 \", read_head=%\" PRId64 \"\",\n                    (int64_t) cs->consumer_id, new_consume_head, old_read_head);\n#endif\n\n    return (int) new_consume_head;\n}\n\n\nint __subscribe_queue(WORD consumer_id, WORD shard_id, WORD app_id, db_row_t * db_row, WORD group_id,\n                    queue_callback * callback, int * sockfd, int64_t * prev_read_head, int64_t * prev_consume_head,\n                    short use_lock, db_t * db, unsigned int * fastrandstate)\n{\n    if(use_lock)\n        pthread_mutex_lock(db_row->subscribe_lock);\n\n    *prev_read_head = -1;\n    *prev_consume_head = -1;\n\n    snode_t * consumer_node = skiplist_search(db_row->consumer_state, consumer_id);\n    if(consumer_node != NULL)\n    {\n        consumer_state * found_cs = (consumer_state *) (consumer_node->value);\n\n        log_debug(\"BACKEND: ERR: Found consumer state %\" PRId64 \" when searching for consumer_id %\" PRId64 \"!\", (int64_t) found_cs->consumer_id, (int64_t) consumer_id);\n\n        *prev_read_head = found_cs->private_read_head;\n        *prev_consume_head = found_cs->private_consume_head;\n\n        if(use_lock)\n            pthread_mutex_unlock(db_row->subscribe_lock);\n\n        return DB_ERR_DUPLICATE_CONSUMER; // Consumer already exists!\n    }\n\n    consumer_state * cs = get_consumer_state(consumer_id, shard_id, app_id, group_id, callback, sockfd, 0);\n\n    int ret = skiplist_insert(db_row->consumer_state, consumer_id, cs, fastrandstate);\n\n    if(use_lock)\n        pthread_mutex_unlock(db_row->subscribe_lock);\n\n#if (VERBOSITY > 0)\n    log_debug(\"BACKEND: Subscriber %\" PRId64 \"/%\" PRId64 \"/%\" PRId64 \"/%\" PRId64 \" subscribed queue %\" PRId64 \" with callback %p\",\n                    (int64_t) cs->app_id, (int64_t) cs->shard_id, (int64_t) cs->consumer_id, (int64_t) cs->group_id,\n                    (int64_t) db_row->key, cs->callback);\n#endif\n\n    return ret;\n}\n\n\nint _subscribe_queue(WORD consumer_id, WORD shard_id, WORD app_id, WORD table_key, WORD queue_id, WORD group_id,\n                    queue_callback * callback, int * sockfd, int64_t * prev_read_head, int64_t * prev_consume_head,\n                    short use_lock, db_t * db, unsigned int * fastrandstate)\n{\n    db_table_t * table = get_table_by_key(table_key, db);\n\n    if(table == NULL)\n        return DB_ERR_NO_TABLE; // Table doesn't exist\n\n    snode_t * node = skiplist_search(table->rows, queue_id);\n    if(node == NULL)\n        return DB_ERR_NO_QUEUE; // Queue doesn't exist\n\n    db_row_t * db_row = (db_row_t *) (node->value);\n\n    int ret = __subscribe_queue(consumer_id, shard_id, app_id, db_row, group_id,\n            callback, sockfd, prev_read_head, prev_consume_head,\n            use_lock, db, fastrandstate);\n\n    return ret;\n}\n\nint _subscribe_group(WORD consumer_id, WORD shard_id, WORD app_id, WORD group_id,\n                    queue_callback * callback, int * sockfd,\n                    short use_lock, db_t * db, unsigned int * fastrandstate)\n{\n    group_state * found_group = NULL;\n    snode_t * group_node = lookup_bucket(db->queue_groups, group_id);\n    int ret = 0;\n    if(group_node == NULL) // Group doesn't exist\n    {\n        found_group = get_group((WORD) group_id);\n\n        ret = add_listener_to_group(found_group, consumer_id, shard_id, app_id,\n                               callback, sockfd, fastrandstate);\n\n        log_debug(\"BACKEND: Bucket %d not found, adding it as %p\", group_id, found_group);\n\n        add_bucket(db->queue_groups, found_group, &get_group_state_key, &get_group_state_live_field, fastrandstate);\n    }\n    else\n    {\n        found_group = (group_state *) (group_node->value);\n\n        ret = add_listener_to_group(found_group,\n                                consumer_id, shard_id, app_id,\n                                callback,\n                                sockfd,\n                                fastrandstate);\n        if(ret == DB_ERR_DUPLICATE_CONSUMER)\n        {\n            log_debug(\"BACKEND: Warning: Found previously existing consumer state in queue group %p, group_id = %\" PRId64 \" when searching for consumer_id %\" PRId64 \"!\", found_group, (int64_t) group_id, (int64_t) consumer_id);\n        }\n    }\n\n#if (VERBOSITY > 0)\n    log_debug(\"BACKEND: Subscriber %\" PRId64 \"/%\" PRId64 \"/%\" PRId64 \" subscribed to group %p, group_id=%\" PRId64 \" with callback %p, fd %d, group now has %d consumers\",\n                    (int64_t) app_id, (int64_t) shard_id, (int64_t) consumer_id, found_group, (int64_t) group_id, callback, *sockfd, found_group->consumers->no_items);\n#endif\n\n    return ret;\n}\n\nint _unsubscribe_group(WORD consumer_id, WORD group_id, db_t * db)\n{\n    snode_t * group_node = lookup_bucket(db->queue_groups, group_id);\n    if(group_node == NULL)\n        return DB_ERR_NO_GROUP; // Group doesn't exist\n\n    group_state * found_group = (group_state *) (group_node->value);\n\n    int ret = remove_listener_from_group(found_group, consumer_id);\n\n    if(ret == DB_ERR_NO_CONSUMER)\n    {\n        log_debug(\"BACKEND: Warning: Found no previously existing consumer state in queue group %\" PRId64 \" when attempting to remove consumer_id %\" PRId64 \"!\", (int64_t) group_id, (int64_t) consumer_id);\n    }\n\n#if (VERBOSITY > 0)\n    log_debug(\"BACKEND: Subscriber %\" PRId64 \" unsubscribed from group %\" PRId64 \"\", (int64_t) consumer_id, (int64_t) group_id);\n#endif\n\n    return ret;\n}\n\n\nint subscribe_queue(WORD consumer_id, WORD shard_id, WORD app_id, WORD table_key, WORD queue_id,\n                    queue_callback * callback, int64_t * prev_read_head, int64_t * prev_consume_head,\n                    short use_lock, db_t * db, unsigned int * fastrandstate)\n{\n    assert(callback != NULL);\n\n    return _subscribe_queue(consumer_id, shard_id, app_id, table_key, queue_id, (WORD) -1,\n            callback, NULL, prev_read_head, prev_consume_head,\n            use_lock, db, fastrandstate);\n}\n\nint register_remote_subscribe_queue(WORD consumer_id, WORD shard_id, WORD app_id, WORD table_key, WORD queue_id, WORD group_id,\n                    int * sockfd, int64_t * prev_read_head, int64_t * prev_consume_head,\n                    short use_lock, db_t * db, unsigned int * fastrandstate)\n{\n    assert(sockfd != NULL);\n\n#if (VERBOSITY > 0)\n    log_debug(\"BACKEND: register_remote_subscribe_queue %\" PRId64 \"/%\" PRId64 \"/%\" PRId64 \" for group_id %\" PRId64 \", queue_id %\" PRId64 \"/%\" PRId64 \"\",\n                    (int64_t) app_id, (int64_t) shard_id, (int64_t) consumer_id, (int64_t) group_id,\n                    (int64_t) table_key, (int64_t) queue_id);\n#endif\n\n    if((int) group_id == -1)\n    {\n        return _subscribe_queue(consumer_id, shard_id, app_id, table_key, queue_id, group_id,\n                NULL, sockfd, prev_read_head, prev_consume_head,\n                use_lock, db, fastrandstate);\n    }\n    else\n    {\n        return _subscribe_group(consumer_id, shard_id, app_id, group_id,\n                    NULL, sockfd, use_lock, db, fastrandstate);\n    }\n}\n\n\nint _unsubscribe_queue(WORD consumer_id, WORD shard_id, WORD app_id, WORD table_key, WORD queue_id, WORD group_id,\n                        short use_lock, db_t * db)\n{\n    db_table_t * table = get_table_by_key(table_key, db);\n\n    if(table == NULL)\n        return DB_ERR_NO_TABLE; // Table doesn't exist\n\n    snode_t * node = skiplist_search(table->rows, queue_id);\n    if(node == NULL)\n        return DB_ERR_NO_QUEUE; // Queue doesn't exist\n\n    db_row_t * db_row = (db_row_t *) (node->value);\n\n    if(use_lock)\n        pthread_mutex_lock(db_row->subscribe_lock);\n\n    snode_t * consumer_node = skiplist_delete(db_row->consumer_state, consumer_id);\n\n    if(use_lock)\n        pthread_mutex_unlock(db_row->subscribe_lock);\n\n    if(node == NULL)\n        return DB_ERR_NO_CONSUMER; // Consumer didn't exist\n\n#if (VERBOSITY > 0)\n    log_debug(\"BACKEND: Subscriber %\" PRId64 \"/%\" PRId64 \"/%\" PRId64 \"/%\" PRId64 \" unsubscribed queue %\" PRId64 \"/%\" PRId64 \"\",\n                    (int64_t) app_id, (int64_t) shard_id, (int64_t) consumer_id, (int64_t) group_id,\n                    (int64_t) table_key, (int64_t) queue_id);\n#endif\n\n    return 0;\n}\n\nint unsubscribe_queue(WORD consumer_id, WORD shard_id, WORD app_id, WORD table_key, WORD queue_id, WORD group_id,\n                        short use_lock, db_t * db)\n{\n    return _unsubscribe_queue(consumer_id, shard_id, app_id, table_key, queue_id, group_id, use_lock, db);\n}\n\nint register_remote_unsubscribe_queue(WORD consumer_id, WORD shard_id, WORD app_id, WORD table_key, WORD queue_id, WORD group_id,\n                                        short use_lock, db_t * db)\n{\n    if((int) group_id == -1)\n    {\n        return _unsubscribe_queue(consumer_id, shard_id, app_id, table_key, queue_id, group_id, use_lock, db);\n    }\n    else\n    {\n        return _unsubscribe_group(consumer_id, group_id, db);\n    }\n}\n\nvoid _create_headers_for_group_subscribers(group_state * gs, db_row_t * row, db_t * db, unsigned int * fastrandstate)\n{\n\tint64_t prev_read_head, prev_consume_head;\n\n\tif(gs == NULL)\n\t\treturn;\n\n    for(snode_t * crt_consumer = HEAD(gs->consumers); crt_consumer!=NULL; crt_consumer = NEXT(crt_consumer))\n    {\n    \tconsumer_state * cs = (consumer_state *) crt_consumer->value;\n\n    \t__subscribe_queue(cs->consumer_id, cs->shard_id, cs->app_id, row, gs->group_id,\n    \t            NULL, NULL, &prev_read_head, &prev_consume_head,\n    \t            1, db, fastrandstate);\n    }\n}\n\nvoid create_headers_for_group_subscribers(db_row_t * db_row, db_t * db, unsigned int * fastrandstate)\n{\n\tif(db_row->group_subscriptions == NULL)\n\t\treturn;\n\n    if(db->queue_group_replication_factor == 1)\n    {\n        group_state * gs = (group_state *) db_row->group_subscriptions;\n\n        _create_headers_for_group_subscribers(gs, db_row, db, fastrandstate);\n\n\t    log_debug(\"SERVER: Updated queue group bucket for queue %d, group_pointer=%p, group_id = %d, status = %d, consumers = %d\",\n\t    \t\t(int) db_row->key, gs,\n\t\t\t\t((gs != NULL)?((int) gs->group_id):(-1)),\n\t\t\t\t((gs != NULL)?((int) gs->status):(-1)),\n\t\t\t\t((gs != NULL)?((int) gs->consumers->no_items):(-1)));\n    }\n    else\n    {\n    \tskiplist_t * groups = (skiplist_t *) db_row->group_subscriptions;\n\n    \tfor(snode_t * crt_group = HEAD(groups); crt_group!=NULL; crt_group = NEXT(crt_group))\n    \t{\n    \t\tgroup_state * gs = (group_state *) crt_group->value;\n\n    \t\t_create_headers_for_group_subscribers(gs, db_row, db, fastrandstate);\n\n    \t    log_debug(\"SERVER: Updated queue group bucket for queue %d, group_pointer=%p, group_id = %d, status = %d, consumers = %d\",\n    \t    \t\t(int) db_row->key, gs,\n    \t\t\t\t((gs != NULL)?((int) gs->group_id):(-1)),\n    \t\t\t\t((gs != NULL)?((int) gs->status):(-1)),\n    \t\t\t\t((gs != NULL)?((int) gs->consumers->no_items):(-1)));\n    \t}\n    }\n}\n\nint create_queue(WORD table_key, WORD queue_id, vector_clock * version, short use_lock, db_t * db, unsigned int * fastrandstate)\n{\n    db_table_t * table = get_table_by_key(table_key, db);\n\n    if(table == NULL)\n        return DB_ERR_NO_TABLE; // Table doesn't exist\n\n    if(use_lock)\n        pthread_mutex_lock(table->lock);\n\n    snode_t * node = skiplist_search(table->rows, queue_id);\n    if(node != NULL)\n    {\n        if(use_lock)\n            pthread_mutex_unlock(table->lock);\n\n        return DB_ERR_DUPLICATE_QUEUE; // Queue already exists!\n    }\n\n    db_schema_t* schema = table->schema;\n\n    // Create sentinel queue entry:\n\n    WORD * queue_column_values = (WORD *) malloc(3 * sizeof(WORD)); // schema->no_cols\n    queue_column_values[0]=queue_id;\n    queue_column_values[1]=(WORD) - 2;\n    queue_column_values[2]=0;\n\n    int status = table_insert(queue_column_values, 3, 1, 0, NULL, table, fastrandstate); // version? // schema->no_cols\n\n    if(status)\n    {\n        if(use_lock)\n            pthread_mutex_unlock(table->lock);\n\n        return status;\n    }\n\n    // Get queue row:\n\n    snode_t * qr_node = skiplist_search(table->rows, queue_id);\n    if(qr_node == NULL)\n    {\n        if(use_lock)\n            pthread_mutex_unlock(table->lock);\n\n        return DB_ERR_NO_QUEUE; // Queue creation error\n    }\n\n    db_row_t * db_row = (db_row_t *) (qr_node->value);\n\n    db_row->consumer_state = create_skiplist_long();\n\n    if(!db_row->consumer_state)\n    {\n        if(use_lock)\n            pthread_mutex_unlock(table->lock);\n\n        return DB_ERR_NO_QUEUE; // Queue creation error\n    }\n\n    db_row->enqueue_lock = (pthread_mutex_t*) malloc(sizeof(pthread_mutex_t));\n    pthread_mutex_init(db_row->enqueue_lock, NULL);\n    db_row->read_lock = (pthread_mutex_t*) malloc(sizeof(pthread_mutex_t));\n    pthread_mutex_init(db_row->read_lock, NULL);\n    db_row->subscribe_lock = (pthread_mutex_t*) malloc(sizeof(pthread_mutex_t));\n    pthread_mutex_init(db_row->subscribe_lock, NULL);\n\n    db_row->group_subscriptions = get_buckets_for_object(db->queue_groups, (int) db_row->key, db->queue_group_replication_factor,\n                                                            &get_group_state_key, &get_group_state_live_field,\n                                                            fastrandstate);\n\n    if(db_row->group_subscriptions != NULL)\n    \tcreate_headers_for_group_subscribers(db_row, db, fastrandstate);\n\n    if(version != NULL)\n        update_or_replace_vc(&(db_row->version), version);\n\n    skiplist_insert(table->queues, queue_id, (WORD) db_row, fastrandstate);\n\n    if(use_lock)\n        pthread_mutex_unlock(table->lock);\n\n#if (VERBOSITY > 0)\n    log_debug(\"BACKEND: Queue %\" PRId64 \"/%\" PRId64 \" created\", (int64_t) table_key, (int64_t) queue_id);\n#endif\n\n    return 0;\n}\n\nint delete_queue(WORD table_key, WORD queue_id, vector_clock * version, short use_lock, db_t * db, unsigned int * fastrandstate)\n{\n    db_table_t * table = get_table_by_key(table_key, db);\n    int ret = 0;\n\n    if(table == NULL)\n        return DB_ERR_NO_TABLE; // Table doesn't exist\n\n    snode_t * node = skiplist_search(table->rows, queue_id);\n    if(node == NULL)\n        return DB_ERR_NO_QUEUE; // Queue doesn't exist\n\n    db_row_t * db_row = (db_row_t *) (node->value);\n\n    if(use_lock)\n        pthread_mutex_lock(table->lock);\n\n    // Remove pointer to queue DB row from queue cache table:\n\n    skiplist_delete(table->queues, queue_id);\n\n    // Notify consumers of queue deletion:\n\n    for(snode_t * cell=HEAD(db_row->consumer_state);cell!=NULL;cell=NEXT(cell))\n    {\n        if(cell->value != NULL)\n        {\n            consumer_state * cs = (consumer_state *) (cell->value);\n\n            if(cs->callback == NULL || cs->notified > 0)\n                continue;\n\n            queue_callback_args * qca = get_queue_callback_args(table_key, queue_id, cs->app_id, cs->shard_id, cs->consumer_id, cs->group_id, QUEUE_NOTIF_DELETED);\n\n#if (VERBOSITY > 0)\n            log_debug(\"BACKEND: Attempting to notify subscriber %\" PRId64 \" (%p/%p/%p/%p)\", (int64_t) qca->consumer_id, cs->callback, cs->callback->lock, cs->callback->signal, cs->callback->callback);\n#endif\n\n            ret = pthread_mutex_lock(cs->callback->lock);\n\n#if (VERBOSITY > 0)\n            log_debug(\"BACKEND: Locked consumer lock of %\" PRId64 \" (%p/%p), status=%d\", (int64_t) qca->consumer_id, cs->callback, cs->callback->lock, ret);\n#endif\n\n            pthread_cond_signal(cs->callback->signal);\n            cs->callback->callback(qca);\n            ret = pthread_mutex_unlock(cs->callback->lock);\n\n#if (VERBOSITY > 0)\n            log_debug(\"BACKEND: Unlocked consumer lock of %\" PRId64 \" (%p/%p), status=%d\", (int64_t) qca->consumer_id, cs->callback, cs->callback->lock, ret);\n#endif\n\n//          cs->notified=1;\n\n#if (VERBOSITY > 0)\n            log_debug(\"BACKEND: Notified subscriber %\" PRId64 \" (%p/%p/%p/%p)\", (int64_t) qca->consumer_id, cs->callback, cs->callback->lock, cs->callback->signal, cs->callback->callback);\n#endif\n\n        }\n    }\n\n    skiplist_free_val(db_row->consumer_state, free_consumer_state_sl);\n\n    ret = table_delete_row((WORD*) &(queue_id), version, table, db, fastrandstate);\n\n    if(use_lock)\n        pthread_mutex_unlock(table->lock);\n\n#if (VERBOSITY > 0)\n    log_debug(\"BACKEND: Queue %\" PRId64 \"/%\" PRId64 \" deleted\", (int64_t) table_key, (int64_t) queue_id);\n#endif\n\n    return ret;\n}\n\nconsumer_state * get_consumer_state(WORD consumer_id, WORD shard_id, WORD app_id, WORD group_id, queue_callback* callback, int * sockfd,\n                                    int is_group_subscription)\n{\n    consumer_state * cs = (consumer_state *) malloc(sizeof(consumer_state));\n    cs->consumer_id = consumer_id;\n    cs->shard_id = shard_id;\n    cs->app_id = app_id;\n    cs->group_id = group_id;\n    cs->private_read_head = -1;\n    cs->private_consume_head = -1;\n    cs->callback = callback;\n    cs->sockfd = sockfd;\n    cs->notified=0;\n    cs->prh_version=NULL;\n    cs->pch_version=NULL;\n\n    return cs;\n}\n\nvoid free_consumer_state(consumer_state * cs)\n{\n    if(cs->prh_version != NULL)\n        free_vc(cs->prh_version);\n\n    if(cs->pch_version != NULL)\n        free_vc(cs->pch_version);\n\n    if(cs->callback != NULL)\n        free_queue_callback(cs->callback);\n\n    free(cs);\n}\n\nvoid free_consumer_state_sl(void * cs)\n{\n    free_consumer_state((consumer_state *) cs);\n}\n\nint add_consumer_state_to_group(WORD queue_id, consumer_state * cs, group_state *gs, unsigned int * fastrandstate)\n{\n    snode_t * consumer_node = skiplist_search(gs->consumers, queue_id);\n    if(consumer_node != NULL)\n    {\n        return 1;\n    }\n\n    return skiplist_insert(gs->consumers, queue_id, cs, fastrandstate);\n}\n\nint get_consumer_state_from_group(WORD queue_id, group_state * gs, consumer_state ** cs)\n{\n    snode_t * consumer_node = skiplist_search(gs->consumers, queue_id);\n    if(consumer_node != NULL)\n    {\n        *cs = (consumer_state *) (consumer_node->value);\n        return 0;\n    }\n    return 1;\n}\n\nint pop_consumer_state_from_group(WORD queue_id, group_state * gs, consumer_state ** cs)\n{\n    *cs = (consumer_state *) skiplist_delete(gs->consumers, queue_id);\n    if(*cs != NULL)\n    {\n        return 0;\n    }\n    return 1;\n}\n\n\nvoid free_queue_table_state(WORD queue_table_state)\n{\n    skiplist_free(queue_table_state);\n}\n\n\n\n\n\n\n\n\n"
  },
  {
    "path": "backend/queue.h",
    "content": "/*\n * Copyright (C) 2019-2021 Deutsche Telekom AG\n *\n * Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:\n *\n * 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.\n *\n * 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.\n *\n * 3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission.\n *\n * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS \"AS IS\" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n */\n\n/*\n * queue.h\n *\n *      Author: aagapi\n */\n\n#ifndef BACKEND_QUEUE_H_\n#define BACKEND_QUEUE_H_\n\n#include \"db.h\"\n#include \"queue_callback.h\"\n#include \"consumer_state.h\"\n#include \"queue_groups.h\"\n\n#define DB_ERR_NO_TABLE -1\n#define DB_ERR_NO_QUEUE -2\n#define DB_ERR_NO_CONSUMER -3\n#define DB_ERR_QUEUE_COMPLETE -4\n#define DB_ERR_QUEUE_HEAD_INVALID -5\n#define DB_ERR_DUPLICATE_QUEUE -6\n#define DB_ERR_DUPLICATE_CONSUMER -7\n#define DB_ERR_NO_GROUP -8\n\n#define QUEUE_STATUS_READ_INCOMPLETE 0\n#define QUEUE_STATUS_READ_COMPLETE 1\n\n#define QUEUE_NOTIF_ENQUEUED 0\n#define QUEUE_NOTIF_DELETED 1\n#define GROUP_NOTIF_ENQUEUED 2\n\n#define READ_HEAD(cs) (cs->private_read_head)\n#define CONSUME_HEAD(cs) (cs->private_consume_head)\n#define READ_HEAD_VERSION(cs) (cs->prh_version)\n#define CONSUME_HEAD_VERSION(cs) (cs->pch_version)\n\nint enqueue(WORD * column_values, int no_cols, size_t last_blob_size, WORD table_key, WORD queue_id, short use_lock, db_t * db, unsigned int * fastrandstate);\nint read_queue(WORD consumer_id, WORD shard_id, WORD app_id, WORD table_key, WORD queue_id,\n        int max_entries, int * entries_read, int64_t * new_read_head, vector_clock ** prh_version,\n        snode_t** start_row, snode_t** end_row, short use_lock,\n        db_t * db);\nint peek_queue(WORD consumer_id, WORD shard_id, WORD app_id, WORD table_key, WORD queue_id,\n        int max_entries, int64_t offset, int * entries_read, int64_t * new_read_head, vector_clock ** prh_version,\n        snode_t** start_row, snode_t** end_row, db_t * db);\nint replay_queue(WORD consumer_id, WORD shard_id, WORD app_id, WORD table_key, WORD queue_id,\n        int64_t replay_offset, int max_entries,\n        int * entries_read, int64_t * new_replay_offset,\n        snode_t** start_row, snode_t** end_row,\n        db_t * db);\nint consume_queue(WORD consumer_id, WORD shard_id, WORD app_id, WORD table_key, WORD queue_id,\n                    int64_t new_consume_head, db_t * db);\nint subscribe_queue(WORD consumer_id, WORD shard_id, WORD app_id, WORD table_key, WORD queue_id,\n                        queue_callback * callback, int64_t * prev_read_head, int64_t * prev_consume_head,\n                        short use_lock, db_t * db, unsigned int * fastrandstate);\nint __subscribe_queue(WORD consumer_id, WORD shard_id, WORD app_id, db_row_t * db_row, WORD group_id,\n                    queue_callback * callback, int * sockfd, int64_t * prev_read_head, int64_t * prev_consume_head,\n                    short use_lock, db_t * db, unsigned int * fastrandstate);\nint register_remote_subscribe_queue(WORD consumer_id, WORD shard_id, WORD app_id, WORD table_key, WORD queue_id, WORD group_id,\n                    int * sockfd, int64_t * prev_read_head, int64_t * prev_consume_head,\n                    short use_lock, db_t * db, unsigned int * fastrandstate);\nint register_remote_unsubscribe_queue(WORD consumer_id, WORD shard_id, WORD app_id, WORD table_key, WORD queue_id, WORD group_id,\n                                        short use_lock, db_t * db);\nint unsubscribe_queue(WORD consumer_id, WORD shard_id, WORD app_id, WORD table_key, WORD queue_id, WORD group_id,\n                        short use_lock, db_t * db);\nvoid create_headers_for_group_subscribers(db_row_t * db_row, db_t * db, unsigned int * fastrandstate);\nint create_queue(WORD table_key, WORD queue_id, vector_clock * version, short use_lock,\n                    db_t * db, unsigned int * fastrandstate);\nint delete_queue(WORD table_key, WORD queue_id, vector_clock * version, short use_lock, db_t * db, unsigned int * fastrandstate);\nint create_queue_table(WORD table_id, int no_cols, int * col_types,\n                        db_t * db, unsigned int * fastrandstate);\nint set_private_read_head(WORD consumer_id, WORD shard_id, WORD app_id, WORD table_key, WORD queue_id,\n                            int64_t new_read_head, vector_clock * version, short use_lock, db_t * db);\nint set_private_consume_head(WORD consumer_id, WORD shard_id, WORD app_id, WORD table_key, WORD queue_id,\n                            int64_t new_consume_head, vector_clock * version, db_t * db);\n\nconsumer_state * get_consumer_state(WORD consumer_id, WORD shard_id, WORD app_id, WORD group_id, queue_callback* callback, int * sockfd, int is_group_subscription);\nvoid free_consumer_state(consumer_state * cs);\nvoid free_consumer_state_sl(void * cs);\n\nint add_consumer_state_to_group(WORD queue_id, consumer_state * cs, group_state *gs, unsigned int * fastrandstate);\nint get_consumer_state_from_group(WORD queue_id, group_state * gs, consumer_state ** cs);\nint pop_consumer_state_from_group(WORD queue_id, group_state * gs, consumer_state ** cs);\n\nvoid free_queue_table_state(WORD queue_table_state);\n\n#endif /* BACKEND_QUEUE_H_ */\n"
  },
  {
    "path": "backend/queue_callback.c",
    "content": "/*\n * Copyright (C) 2019-2021 Deutsche Telekom AG\n *\n * Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:\n *\n * 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.\n *\n * 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.\n *\n * 3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission.\n *\n * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS \"AS IS\" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n */\n\n/*\n * queue_callback.c\n *      Author: aagapi\n */\n\n#include \"queue_callback.h\"\n\nqueue_callback_args * get_queue_callback_args(WORD table_key, WORD queue_id, WORD app_id, WORD shard_id, WORD consumer_id, WORD group_id, int status)\n{\n    queue_callback_args * qca = (queue_callback_args *) malloc(sizeof(queue_callback_args));\n    qca->table_key = table_key;\n    qca->queue_id = queue_id;\n\n    qca->app_id = app_id;\n    qca->shard_id = shard_id;\n    qca->consumer_id = consumer_id;\n\n    qca->group_id = group_id;\n\n    qca->status = status;\n\n    return qca;\n}\n\nvoid free_queue_callback_args(queue_callback_args * qca)\n{\n    free(qca);\n}\n\nqueue_callback * get_queue_callback(void (*callback)(queue_callback_args *))\n{\n    queue_callback * qc = (queue_callback *) malloc(sizeof(queue_callback) + sizeof(pthread_mutex_t) + sizeof(pthread_cond_t));\n    qc->lock = (pthread_mutex_t *) ((char *)qc + sizeof(queue_callback));\n    qc->signal = (pthread_cond_t *) ((char *)qc + sizeof(queue_callback) + sizeof(pthread_mutex_t));\n    pthread_mutex_init(qc->lock, NULL);\n    pthread_cond_init(qc->signal, NULL);\n    qc->callback = callback;\n    return qc;\n}\n\nint wait_on_queue_callback(queue_callback * qc)\n{\n    int ret = pthread_mutex_lock(qc->lock);\n\n#if DEBUG_QUEUE_CALLBACK > 0\n    printf(\"Locked consumer lock %p/%p\\n\", qc, qc->lock);\n#endif\n\n    struct timespec ts;\n    clock_gettime(CLOCK_REALTIME, &ts);\n    ts.tv_sec += 3;\n    ret = pthread_cond_timedwait(qc->signal, qc->lock, &ts);\n\n    pthread_mutex_unlock(qc->lock);\n\n#if DEBUG_QUEUE_CALLBACK > 0\n    printf(\"Unlocked consumer lock %p/%p\\n\", qc, qc->lock);\n#endif\n\n    return ret;\n}\n\nvoid free_queue_callback(queue_callback * qc)\n{\n    free(qc);\n}\n\n\n"
  },
  {
    "path": "backend/queue_callback.h",
    "content": "/*\n * Copyright (C) 2019-2021 Deutsche Telekom AG\n *\n * Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:\n *\n * 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.\n *\n * 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.\n *\n * 3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission.\n *\n * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS \"AS IS\" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n */\n\n/*\n * queue_callback.h\n *      Author: aagapi\n */\n\n#ifndef BACKEND_QUEUE_CALLBACK_H_\n#define BACKEND_QUEUE_CALLBACK_H_\n\n#include \"common.h\"\n\ntypedef struct queue_callback_args\n{\n    WORD table_key;\n    WORD queue_id;\n\n    WORD consumer_id;\n    WORD shard_id;\n    WORD app_id;\n\n    WORD group_id;\n\n    int status;\n} queue_callback_args;\n\ntypedef struct queue_callback\n{\n    void (*callback)(queue_callback_args *);\n    pthread_mutex_t * lock;\n    pthread_cond_t * signal;\n} queue_callback;\n\n#define DEBUG_QUEUE_CALLBACK 0\n\nqueue_callback_args * get_queue_callback_args(WORD table_key, WORD queue_id, WORD app_id, WORD shard_id, WORD consumer_id, WORD group_id, int status);\nvoid free_queue_callback_args(queue_callback_args * qca);\nqueue_callback * get_queue_callback(void (*callback)(queue_callback_args *));\nint wait_on_queue_callback(queue_callback *);\nvoid free_queue_callback(queue_callback * qc);\n\n#endif /* BACKEND_QUEUE_CALLBACK_H_ */\n"
  },
  {
    "path": "backend/queue_groups.c",
    "content": "/*\n * Copyright (C) 2019-2021 Deutsche Telekom AG\n *\n * Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:\n *\n * 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.\n *\n * 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.\n *\n * 3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission.\n *\n * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS \"AS IS\" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n */\n\n/*\n * queue_groups.c\n *      Author: aagapi\n */\n\n#include \"queue_groups.h\"\n\n// Queue group management fctns:\n\ngroup_state * get_group(WORD group_id)\n{\n    group_state * group = (group_state *) malloc(sizeof(group_state) + sizeof(pthread_mutex_t));\n    group->group_id = group_id;\n    group->consumers = create_skiplist_long();\n    group->queue_tables = create_skiplist_long();\n    group->status = GROUP_STATUS_ACTIVE;\n    group->group_lock = (pthread_mutex_t*) ((char*) group + sizeof(group_state));\n    pthread_mutex_init(group->group_lock, NULL);\n    return group;\n}\n\nvoid free_group_state(WORD gs)\n{\n    delete_group((group_state *) gs);\n}\n\nWORD get_group_state_key(WORD rs)\n{\n    return ((group_state *) rs)->group_id;\n}\nWORD get_group_state_live_field(WORD rs)\n{\n    return (WORD) (&(((group_state *) rs)->status));\n}\n\nint clear_group(group_state * group)\n{\n    skiplist_free_val(group->consumers, free_group_state);\n    group->consumers = create_skiplist_long();\n\n    skiplist_free_val(group->queue_tables, free_queue_table_state);\n    group->queue_tables = create_skiplist_long();\n\n    return 0;\n}\n\nint delete_group(group_state * group)\n{\n    skiplist_free_val(group->consumers, free_group_state);\n    skiplist_free_val(group->queue_tables, free_queue_table_state);\n    free(group);\n    return 0;\n}\n\nvoid activate_group(group_state * group)\n{\n    group->status = GROUP_STATUS_ACTIVE;\n}\n\nvoid deactivate_group(group_state * group)\n{\n    group->status = GROUP_STATUS_INACTIVE;\n}\n\nint add_queue_to_group(group_state * group, WORD table_key, WORD queue_id, unsigned int * fastrandstate)\n{\n    skiplist_t * queue_list = NULL;\n    pthread_mutex_lock(group->group_lock);\n    snode_t * table_list = skiplist_search(group->queue_tables, table_key);\n    if(table_list != NULL)\n    {\n        skiplist_t * queue_list = (skiplist_t *) (table_list->value);\n    }\n    else\n    {\n        queue_list = create_skiplist_long();\n        skiplist_insert(group->queue_tables, table_key, queue_list, fastrandstate);\n    }\n    skiplist_insert(queue_list, queue_id, queue_id, fastrandstate);\n    pthread_mutex_unlock(group->group_lock);\n    return 0;\n}\n\nint remove_queue_from_group(group_state * group, WORD table_key, WORD queue_id)\n{\n    pthread_mutex_lock(group->group_lock);\n    snode_t * table_list = skiplist_search(group->queue_tables, table_key);\n    if(table_list == NULL)\n    {\n        pthread_mutex_unlock(group->group_lock);\n        return DB_ERR_NO_TABLE;\n    }\n    skiplist_t * queue_list = (skiplist_t *) (table_list->value);\n    if(queue_list != NULL)\n    {\n        snode_t * queue_entry = skiplist_delete(queue_list, queue_id);\n        pthread_mutex_unlock(group->group_lock);\n        if(queue_entry == NULL)\n            return DB_ERR_NO_QUEUE;\n    }\n    else\n    {\n        pthread_mutex_unlock(group->group_lock);\n        return DB_ERR_NO_QUEUE;\n    }\n    return 0;\n}\n\nint is_queue_in_group(group_state * group, WORD table_key, WORD queue_id)\n{\n    pthread_mutex_lock(group->group_lock);\n    snode_t * table_list = skiplist_search(group->queue_tables, table_key);\n    if(table_list == NULL)\n    {\n        pthread_mutex_unlock(group->group_lock);\n        return 0;\n    }\n    skiplist_t * queue_list = (skiplist_t *) (table_list->value);\n    if(queue_list != NULL)\n    {\n        snode_t * queue_entry = skiplist_search(queue_list, queue_id);\n        pthread_mutex_unlock(group->group_lock);\n        if(queue_entry == NULL)\n            return 0;\n    }\n    else\n    {\n        pthread_mutex_unlock(group->group_lock);\n    }\n    return 1;\n}\n\nint add_listener_to_group(group_state * group,\n                        WORD consumer_id, WORD shard_id, WORD app_id,\n                        queue_callback * callback,\n                        int * sockfd,\n                        unsigned int * fastrandstate)\n{\n    consumer_state * cs = get_consumer_state(consumer_id, shard_id, app_id, group->group_id, callback, sockfd, 1);\n\n    pthread_mutex_lock(group->group_lock);\n\n    snode_t * consumer_node = skiplist_search(group->consumers, consumer_id);\n\n    int ret = 0;\n    if(consumer_node != NULL)\n    {\n        ret = DB_ERR_DUPLICATE_CONSUMER; // We allow the consumer to update his previously existing callback and meta-data, but advise him that he has done so\n    }\n\n    skiplist_insert(group->consumers, consumer_id, cs, fastrandstate);\n\n    pthread_mutex_unlock(group->group_lock);\n\n    return ret;\n}\n\nint remove_listener_from_group(group_state * group, WORD consumer_id)\n{\n    pthread_mutex_lock(group->group_lock);\n\n    snode_t * consumer_node = skiplist_delete(group->consumers, consumer_id);\n\n    pthread_mutex_unlock(group->group_lock);\n\n    if(consumer_node == NULL)\n        return DB_ERR_NO_CONSUMER; // Consumer didn't exist\n    return 0;\n}\n\nint lookup_listener_in_group(group_state * group, WORD consumer_id, WORD queue_id, consumer_state ** cs)\n{\n    pthread_mutex_lock(group->group_lock);\n\n    snode_t * consumer_node = skiplist_search(group->consumers, consumer_id);\n\n    pthread_mutex_unlock(group->group_lock);\n\n    if(consumer_node == NULL)\n    {\n        *cs = NULL;\n\n        return DB_ERR_NO_CONSUMER; // Consumer didn't exist\n    }\n\n    *cs = (consumer_state *) consumer_node->value;\n\n    return 0;\n}\n\n\n\n"
  },
  {
    "path": "backend/queue_groups.h",
    "content": "/*\n * Copyright (C) 2019-2021 Deutsche Telekom AG\n *\n * Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:\n *\n * 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.\n *\n * 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.\n *\n * 3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission.\n *\n * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS \"AS IS\" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n */\n\n/*\n * queue_groups.h\n *      Author: aagapi\n */\n\n#ifndef BACKEND_QUEUE_GROUPS_H_\n#define BACKEND_QUEUE_GROUPS_H_\n\n#include \"common.h\"\n#include \"queue_callback.h\"\n#include \"queue.h\"\n#include \"skiplist.h\"\n\n#define GROUP_STATUS_ACTIVE 0\n#define GROUP_STATUS_INACTIVE 1\n\ntypedef struct group_state {\n    WORD group_id;\n    skiplist_t * queue_tables;\n    skiplist_t * consumers;\n    pthread_mutex_t* group_lock;\n    int status;\n} group_state;\n\ntypedef struct consumer_state consumer_state;\n\n// Queue group management fctns:\n\ngroup_state * get_group(WORD group_id);\nint delete_group(group_state * group);\nint clear_group(group_state * group);\nvoid activate_group(group_state * group);\nvoid deactivate_group(group_state * group);\nint add_queue_to_group(group_state * group, WORD table_key, WORD queue_id, unsigned int * fastrandstate);\nint remove_queue_from_group(group_state * group, WORD table_key, WORD queue_id);\nint add_listener_to_group(group_state * group,\n                        WORD consumer_id, WORD shard_id, WORD app_id,\n                        queue_callback * callback,\n                        int * sockfd,\n                        unsigned int * fastrandstate);\nint lookup_listener_in_group(group_state * group, WORD consumer_id, WORD queue_id, consumer_state ** cs);\nint remove_listener_from_group(group_state * group, WORD consumer_id);\nint is_queue_in_group(group_state * group, WORD table_key, WORD queue_id);\nvoid free_group_state(WORD gs);\nWORD get_group_state_key(WORD rs);\nWORD get_group_state_live_field(WORD rs);\n\n#endif /* BACKEND_QUEUE_GROUPS_H_ */\n"
  },
  {
    "path": "backend/skiplist.c",
    "content": "/*\n * Copyright (C) 2019-2021 Deutsche Telekom AG\n *\n * Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:\n *\n * 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.\n *\n * 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.\n *\n * 3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission.\n *\n * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS \"AS IS\" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n */\n\n/*\n * skiplist.c\n *\n */\n\n#include <stdlib.h>\n#include <stdio.h>\n#include <limits.h>\n#include <assert.h>\n#include <uuid/uuid.h>\n#include <inttypes.h>\n\n#include \"skiplist.h\"\n#include \"log.h\"\n#include \"fastrand.h\"\n\nint long_cmp(WORD e1, WORD e2) {\n    return (int) ((int64_t) e1 - (int64_t) e2);\n}\n\nint uuid_cmp(WORD e1, WORD e2)\n{\n    return uuid_compare(e1, e2);\n}\n\nskiplist_t *create_skiplist_long() {\n    return create_skiplist(NULL);\n}\n\nskiplist_t *create_skiplist_uuid() {\n    return create_skiplist(&uuid_cmp);\n}\n\nskiplist_t *create_skiplist(int (*cmp)(WORD, WORD)) {\n    skiplist_t * list = (skiplist_t *) malloc(sizeof(skiplist_t));\n\n    return skiplist_init(list, cmp);\n}\n\nskiplist_t *skiplist_init(skiplist_t *list, int (*cmp)(WORD, WORD)) {\n    snode_t *header = (snode_t *) malloc(sizeof(struct snode));\n    list->header = header;\n    header->key = (WORD) LONG_MAX;\n    header->forward = (snode_t **) malloc(sizeof(snode_t*) * (SKIPLIST_MAX_LEVEL));\n    for (int i = 0; i < SKIPLIST_MAX_LEVEL; i++) {\n        header->forward[i] = NULL; // list->header;\n    }\n\n    list->level = 0;\n\n    list->no_items=0;\n\n    list->cmp = (cmp != NULL)?(cmp):(&long_cmp);\n\n    return list;\n}\n\nstatic int rand_level(unsigned int * seedptr) {\n    unsigned int randno;\n\n    FASTRAND(seedptr, randno);\n\n    return randno % SKIPLIST_MAX_LEVEL;\n}\n\nint skiplist_insert(skiplist_t *list, WORD key, WORD value, unsigned int * seedptr) {\n    snode_t *update[SKIPLIST_MAX_LEVEL];\n    snode_t *x = list->header;\n    int i = list->level, level;\n    for (; i >= 0; i--) {\n        while (x->forward[i] != NULL && (list->cmp(x->forward[i]->key, key) < 0))\n            x = x->forward[i];\n//      log_debug(\"Item %\" PRId64 \" will update node %\" PRId64 \" at level %d\", key, x->key, i);\n            update[i] = x;\n    }\n\n    if (x->forward[0] != NULL && list->cmp(key, x->forward[0]->key) == 0) {\n        x->forward[0]->value = value;\n        return 0;\n    } else {\n        level = rand_level(seedptr);\n//      log_debug(\"Item %\" PRId64 \", picking level %d\", key, level);\n        if (level > list->level) {\n            for (i = list->level + 1; i <= level; i++) {\n                update[i] = list->header;\n            }\n            list->level = level;\n        }\n\n        x = (snode_t *) malloc(sizeof(snode_t));\n        x->key = key;\n        x->value = value;\n        x->forward = (snode_t **) malloc(sizeof(snode_t*) * (level+1));\n        for (i = 0; i <= level; i++) {\n//              log_debug(\"Item %\" PRId64 \" chaining myself after node %\" PRId64 \" at level %d\", key, update[i]->key, i);\n            x->forward[i] = update[i]->forward[i];\n            update[i]->forward[i] = x;\n        }\n\n        list->no_items++;\n    }\n    return 0;\n}\n\nskiplist_t * skiplist_clone(skiplist_t * list, unsigned int * seedptr)\n{\n    skiplist_t * dst_list = create_skiplist(list->cmp);\n\n    for(snode_t * crt = HEAD(list); crt!=NULL; crt = NEXT(crt))\n    {\n        skiplist_insert(dst_list, crt->key, crt->value, seedptr);\n    }\n\n    return dst_list;\n}\n\nsnode_t *skiplist_search(skiplist_t *list, WORD key) {\n    snode_t *x = list->header;\n    for (int i = list->level; i >= 0; i--) {\n        while (x->forward[i] != NULL && (list->cmp(x->forward[i]->key, key) <= 0) )\n            x = x->forward[i];\n    }\n\n    if (x != NULL && ((int64_t) x->key) != LONG_MAX && list->cmp(key, x->key) == 0) {\n        return x;\n    } else {\n        return NULL;\n    }\n\n    return NULL;\n}\n\nsnode_t *skiplist_search_higher(skiplist_t *list, WORD key) {\n    snode_t *x = list->header;\n    for (int i = list->level; i >= 0; i--) {\n        while (x->forward[i] != NULL && (list->cmp(x->forward[i]->key, key) < 0))\n            x = x->forward[i];\n    }\n\n    if(x != NULL)\n            return x->forward[0];\n    else\n            assert(0);\n\n    return NULL;\n}\n\nint skiplist_get_range(skiplist_t *list, WORD start_key, WORD end_key, WORD** result, int *no_nodes)\n{\n    snode_t * start_node = NULL;\n    int i=0;\n\n    start_node = skiplist_search_higher(list, start_key);\n\n    if(start_node != NULL)\n    {\n        *result = NULL;\n        *no_nodes = 0;\n        return -1;\n    }\n\n    *no_nodes=1;\n\n    for(snode_t * x = start_node;list->cmp(x->forward[0]->key, end_key) < 0;x = x->forward[0])\n        (*no_nodes)++;\n\n    *result = (WORD*) malloc(*no_nodes*sizeof(WORD));\n\n    for(snode_t * x = start_node;list->cmp(x->forward[0]->key, end_key) < 0;x = x->forward[0])\n        (*result)[i++] = x->value;\n\n    return 0;\n}\n\n\nsnode_t *skiplist_search_lower(skiplist_t *list, WORD key) {\n    snode_t *x = list->header;\n    for (int i = list->level; i >= 0; i--) {\n        while (x->forward[i] != NULL && (list->cmp(x->forward[i]->key, key) <= 0))\n            x = x->forward[i];\n    }\n\n    return x;\n}\n\n\nstatic void skiplist_node_free(snode_t *x) {\n    if (x) {\n        free(x->forward);\n        free(x);\n    }\n}\n\nWORD skiplist_delete(skiplist_t *list, WORD key) {\n    WORD value = NULL;\n\n    snode_t *update[SKIPLIST_MAX_LEVEL];\n    snode_t *x = list->header;\n    for (int i = list->level; i >= 0; i--) {\n        while (x->forward[i] != NULL && (list->cmp(x->forward[i]->key, key) < 0))\n            x = x->forward[i];\n            update[i] = x;\n    }\n\n    if(x->forward[0] != NULL)\n            x = x->forward[0];\n\n    if (list->cmp(x->key, key) == 0) {\n        for (int i = 0; i <= list->level; i++) {\n            if (update[i]->forward[i] != x)\n                break;\n            update[i]->forward[i] = x->forward[i];\n        }\n\n        value = x->value;\n\n        skiplist_node_free(x);\n\n        while (list->level > 0 && list->header->forward[list->level] == NULL)\n            list->level--;\n\n        list->no_items--;\n    }\n    return value;\n}\n\nvoid skiplist_free(skiplist_t *list)\n{\n    snode_t *current_node = list->header->forward[0];\n    while(current_node != NULL) {\n        snode_t *next_node = current_node->forward[0];\n        free(current_node->forward);\n        free(current_node);\n        current_node = next_node;\n    }\n\n    free(list->header->forward);\n    free(list->header);\n\n    free(list);\n}\n\nvoid skiplist_free_val(skiplist_t *list, void (*free_val)(WORD))\n{\n    snode_t *current_node = list->header->forward[0];\n    while(current_node != NULL) {\n        snode_t *next_node = current_node->forward[0];\n        free(current_node->forward);\n        free_val(current_node->value);\n        free(current_node);\n        current_node = next_node;\n    }\n\n    free(list->header->forward);\n    free(list->header);\n\n    free(list);\n}\n\nvoid skiplist_dump(skiplist_t *list) {\n    snode_t *x = list->header;\n    while (x && x->forward[0] != NULL) {\n        log_trace(\"%\" PRId64 \"[%\" PRId64 \"]->\", (int64_t) x->forward[0]->key, (int64_t) x->forward[0]->value);\n        x = x->forward[0];\n    }\n    log_trace(\"NIL\");\n}\n\n\n\n"
  },
  {
    "path": "backend/skiplist.h",
    "content": "/*\n * skiplist.h\n *\n */\n\n#ifndef BACKEND_SKIPLIST_H_\n#define BACKEND_SKIPLIST_H_\n\ntypedef void *WORD;\n\n#define SKIPLIST_MAX_LEVEL 6\n\n#define HEAD(skiplist) ((skiplist)->header->forward[0])\n#define NEXT(snode) ((snode)->forward[0])\n\ntypedef struct snode {\n    WORD key;\n    WORD value;\n    struct snode **forward;\n} snode_t;\n\ntypedef struct skiplist {\n    int level;\n    struct snode *header;\n    int no_items;\n\n    int (*cmp)(WORD, WORD);\n} skiplist_t;\n\nskiplist_t * create_skiplist_long();\nskiplist_t *create_skiplist_uuid();\nskiplist_t * create_skiplist(int (*cmp)(WORD, WORD));\nskiplist_t * skiplist_init(skiplist_t *list, int (*cmp)(WORD, WORD));\nskiplist_t * skiplist_clone(skiplist_t * list, unsigned int * seedptr);\nint skiplist_insert(skiplist_t *list, WORD key, WORD value, unsigned int * seedptr);\nsnode_t * skiplist_search(skiplist_t *list, WORD key);\nsnode_t *skiplist_search_higher(skiplist_t *list, WORD key);\nsnode_t *skiplist_search_lower(skiplist_t *list, WORD key);\nint skiplist_get_range(skiplist_t *list, WORD start_key, WORD end_key, WORD** result, int *no_nodes);\nstatic void skiplist_node_free(snode_t *x);\nWORD skiplist_delete(skiplist_t *list, WORD key);\nvoid skiplist_free(skiplist_t *list);\nvoid skiplist_free_val(skiplist_t *list, void (*free_val)(WORD));\nvoid skiplist_dump(skiplist_t *list);\n\n\n#endif /* BACKEND_SKIPLIST_H_ */\n"
  },
  {
    "path": "backend/test/actor_ring_tests_local.c",
    "content": "/*\n * Copyright (C) 2019-2021 Deutsche Telekom AG\n *\n * Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:\n *\n * 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.\n *\n * 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.\n *\n * 3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission.\n *\n * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS \"AS IS\" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n */\n\n#include <stdio.h>\n#include <stdlib.h>\n#include <pthread.h>\n#include <assert.h>\n#include <pthread.h>\n#include <unistd.h>\n#include <string.h>\n#include <time.h>\n\n#include \"txns.h\"\n\n#define COLLECTION_ID_0 0\n#define COLLECTION_ID_1 1\n#define COLLECTION_ID_2 2 // local counter variable as int\n#define COLLECTION_ID_3 3 // local counter variable as char blob\n\nint no_actors = 2;\nint no_items = 10;\n\nint min_no_state_cols = 3;\nint no_state_primary_keys = 1;\nint min_state_clustering_keys = 1;\nint no_state_index_keys = 1;\n\nint no_queue_cols = 3;\n\nWORD state_table_key = (WORD) 0;\nWORD queue_table_key = (WORD) 1;\n\nint rand_sleep = 1;\n\nint debug = 1;\nint debug_lock = 0;\n\n\ntypedef struct actor_collection_item {\n    int actor_id;\n    int collection_id;\n    int item_id;\n    int item_value;\n} actor_collection_item_t;\n\ntypedef struct actor_queue_item {\n    int sender_id;\n    int item_value;\n} actor_queue_item_t;\n\ntypedef struct actor_args\n{\n    db_t * db;\n    WORD state_table_key;\n    WORD queue_table_key;\n    WORD queue_id;\n    int no_enqueues;\n\n    WORD consumer_id;\n    WORD shard_id;\n    WORD app_id;\n\n    skiplist_t * rcv_counters;\n    skiplist_t * snd_counters;\n    int64_t total_rcv;\n    int64_t total_snd;\n\n    int successful_enqueues;\n    int successful_dequeues;\n    int successful_consumes;\n    int successful_replays;\n\n    int64_t read_head;\n    int64_t read_head_after_replay;\n\n    queue_callback * qc;\n\n    vector_clock * vc;\n\n    int status;\n} actor_args;\n\n// Create schema:\n\nint create_state_schema(db_t * db, unsigned int * fastrandstate)\n{\n    int primary_key_idx = 0;\n    int clustering_key_idxs[2];\n    clustering_key_idxs[0]=1;\n    clustering_key_idxs[1]=2;\n    int index_key_idx=3;\n\n    //  Col types are not enforced:\n\n    int * col_types = NULL;\n\n    /*\n    int * col_types = (int *) malloc(no_state_cols * sizeof(int));\n\n    for(int i=0;i<no_state_cols;i++)\n        col_types[i] = DB_TYPE_INT32;\n     */\n\n    db_schema_t* db_schema = db_create_schema(col_types, min_no_state_cols, &primary_key_idx, no_state_primary_keys, clustering_key_idxs, min_state_clustering_keys, &index_key_idx, no_state_index_keys);\n\n    assert(db_schema != NULL && \"Schema creation failed\");\n\n    // Create table:\n\n    int ret = db_create_table((WORD) 0, db_schema, db, fastrandstate);\n\n    printf(\"Test %s - %s (%d)\\n\", \"create_state_table\", ret==0?\"OK\":\"FAILED\", ret);\n\n    return ret;\n}\n\nint create_queue_schema(db_t * db, unsigned int * fastrandstate)\n{\n    assert(no_queue_cols == 3);\n\n    // Note: Col types are not enforced in the schema-less model. You still need to provide a \"col_types\" array of size \"no_columns\" at table creation time (currently):\n\n    int * col_types = (int *) malloc(no_queue_cols * sizeof(int));\n    col_types[0] = DB_TYPE_INT64;\n    col_types[1] = DB_TYPE_INT32;\n    col_types[2] = DB_TYPE_BLOB;\n\n    int ret = create_queue_table(queue_table_key, no_queue_cols, col_types, db, fastrandstate);\n    printf(\"Test %s - %s (%d)\\n\", \"create_queue_table\", ret==0?\"OK\":\"FAILED\", ret);\n\n    // Create input queues for all actors:\n\n    for(int64_t queue_id=0;queue_id<no_actors;queue_id++)\n    {\n        ret = create_queue(queue_table_key, (WORD) queue_id, NULL, 1, db, fastrandstate);\n        printf(\"Test %s - %s (%d)\\n\", \"create_queue\", ret==0?\"OK\":\"FAILED\", ret);\n    }\n\n    return ret;\n}\n\n\nvoid consumer_callback(queue_callback_args * qca)\n{\n    printf(\"Consumer %\" PRId64 \"/%\" PRId64 \"/%\" PRId64 \" received notification for queue %\" PRId64 \"/%\" PRId64 \", status %d\\n\",\n            (int64_t) qca->app_id, (int64_t) qca->shard_id, (int64_t) qca->consumer_id,\n            (int64_t) qca->table_key, (int64_t) qca->queue_id,\n            qca->status);\n}\n\nint read_queue_while_not_empty(actor_args * ca, int * entries_read, snode_t ** start_row, snode_t ** end_row)\n{\n    int read_status = QUEUE_STATUS_READ_INCOMPLETE;\n    vector_clock * prh_version;\n\n    while(read_status != QUEUE_STATUS_READ_COMPLETE)\n    {\n        read_status = read_queue(ca->consumer_id, ca->shard_id, ca->app_id,\n                        ca->queue_table_key, ca->queue_id,\n                        2, entries_read, &ca->read_head, &prh_version,\n                        start_row, end_row, 1, ca->db);\n\n        increment_vc(ca->vc, (int) ca->consumer_id);\n\n        if(read_status < 0)\n        {\n            printf(\"ERROR: read_queue returned %d\\n\", read_status);\n            return read_status;\n        }\n        else\n        {\n            assert(read_status == QUEUE_STATUS_READ_COMPLETE || read_status == QUEUE_STATUS_READ_INCOMPLETE);\n\n            ca->successful_dequeues += (*entries_read);\n\n            if((*entries_read) > 0)\n            {\n                printf(\"CONSUMER %\" PRId64 \": successful_dequeues=%d, last_entry_id=%\" PRId64 \"\\n\",\n                        (int64_t) ca->consumer_id, ca->successful_dequeues, (int64_t) (*end_row)->key);\n\n                if(((int64_t) (*end_row)->key) != ca->successful_dequeues - 1)\n                    printf(\"Test %s - FAILED (%\" PRId64 \" != %d)\\n\", \"last_entry_id\", (int64_t) (*end_row)->key, ca->successful_dequeues - 1);\n            }\n        }\n    }\n\n    return read_status;\n}\n\nchar digits[10][10] = { \"zero\", \"one\", \"two\", \"three\", \"four\", \"five\", \"six\", \"seven\", \"eight\", \"nine\" };\n\nint checkpoint_local_state(actor_args * ca, uuid_t * txnid, unsigned int * fastrandstate)\n{\n    int ret = 0;\n\n    WORD * column_values = (WORD *) malloc(5 * sizeof(WORD));\n\n    column_values[0] = ca->consumer_id;\n\n    for(snode_t * node = HEAD(ca->rcv_counters);node != NULL;node = NEXT(node))\n    {\n        column_values[1] = (WORD) COLLECTION_ID_0;\n        column_values[2] = node->key;\n        column_values[3] = node->value;\n        char * str_value = ((int) node->value <= 9)?(digits[(int) node->value]):\"NaN\";\n        column_values[4] = str_value; // For backend local API, when there is a blob, place blob pointer as the last col value, and set the corresponding blob_size in the insert call below\n\n        ret = db_insert_in_txn(column_values, 5, no_state_primary_keys, 2,\n                                strnlen((const char *) str_value, 10) + 1, // blob size\n                                ca->state_table_key, txnid, ca->db, fastrandstate);\n\n        assert(ret == 0);\n    }\n\n    for(snode_t * node = HEAD(ca->snd_counters);node != NULL;node = NEXT(node))\n    {\n        column_values[1] = (WORD) COLLECTION_ID_1;\n        column_values[2] = node->key;\n        column_values[3] = node->value;\n        char * str_value = ((int) node->value <= 9)?(digits[(int) node->value]):\"NaN\";\n        column_values[4] = str_value; // For backend local API, when there is a blob, place blob pointer as the last col value, and set the corresponding blob_size in the insert call below\n\n        ret = db_insert_in_txn(column_values, 5, no_state_primary_keys, 2,\n                                strnlen((const char *) str_value, 10) + 1, // blob size\n                                ca->state_table_key, txnid, ca->db, fastrandstate);\n\n        assert(ret == 0);\n    }\n\n    // Checkpoint the standalone counter variable, once in an int column, once in a char blob column:\n\n    column_values[1] = (WORD) COLLECTION_ID_2;\n    column_values[2] = (WORD) ca->total_rcv; // Note that there is no blob here (blob_size == 0 below)\n\n    ret = db_insert_in_txn(column_values, 3, no_state_primary_keys, 1,\n                                0, // blob size\n                                ca->state_table_key, txnid, ca->db, fastrandstate);\n\n    char * str_value = ((int) ca->total_rcv <= 9)?(digits[(int) ca->total_rcv]):\"NaN\";\n\n    column_values[1] = (WORD) COLLECTION_ID_3;\n    column_values[2] = (WORD) str_value; // For backend local API, when there is a blob, place blob pointer as the last col value, and set the corresponding blob_size in the insert call below\n\n    ret = db_insert_in_txn(column_values, 3, no_state_primary_keys, 1,\n                                strnlen((const char *) str_value, 10) + 1, // blob size\n                                ca->state_table_key, txnid, ca->db, fastrandstate);\n\n    free(column_values);\n\n    return 0;\n}\n\n\nint send_seed_msgs(actor_args * ca, int * msgs_sent, unsigned int * fastrandstate)\n{\n    int ret = 0;\n    int64_t dest_id = ((int64_t) ca->consumer_id < no_actors - 1)? ((int64_t) ca->consumer_id + 1) : 0;\n\n    int no_outgoing_counters = 2;\n\n    assert(no_queue_cols == 3);\n\n    *msgs_sent=0;\n\n    WORD * column_values = (WORD *) malloc(no_queue_cols * sizeof(WORD));\n\n    for(int i=0;i<no_outgoing_counters;i++)\n    {\n        column_values[0] = ca->consumer_id;\n        column_values[1] = (WORD) i;\n        char * str_value = (i <= 9)?(digits[i]):\"NaN\";\n        column_values[2] = (WORD) str_value;\n\n        ret = enqueue(column_values, no_queue_cols, strnlen((const char *) str_value, 10) + 1, ca->queue_table_key, (WORD) dest_id, 1, ca->db, fastrandstate);\n\n        assert(ret == 0);\n\n        (*msgs_sent)++;\n\n        skiplist_insert(ca->snd_counters, (WORD) dest_id, (WORD) i, fastrandstate);\n\n        ca->total_snd++;\n    }\n\n    free(column_values);\n\n    return 0;\n}\n\n\nint send_outgoing_msgs(actor_args * ca, int outgoing_counters[], int no_outgoing_counters, int * msgs_sent, uuid_t * txnid, unsigned int * fastrandstate)\n{\n    int ret = 0;\n    int64_t dest_id = ((int64_t) ca->consumer_id < no_actors - 1)? ((int64_t) ca->consumer_id + 1) : 0;\n\n/*\n    if(debug)\n        printf(\"ACTOR %\" PRId64 \": Sending %d msgs to ACTOR %\" PRId64 \".\\n\", (int64_t) ca->consumer_id, no_outgoing_counters, dest_id);\n*/\n\n    assert(no_queue_cols == 3);\n\n    *msgs_sent=0;\n\n    WORD * column_values = (WORD *) malloc(no_queue_cols * sizeof(WORD));\n\n    for(int i=0;i<no_outgoing_counters;i++)\n    {\n        column_values[0] = ca->consumer_id;\n        column_values[1] = (WORD) outgoing_counters[i];\n        char * str_value = (outgoing_counters[i] <= 9)?(digits[outgoing_counters[i]]):\"NaN\";\n        column_values[2] = (WORD) str_value;\n\n        ret = enqueue_in_txn(column_values, no_queue_cols, strnlen((const char *) str_value, 10) + 1, ca->queue_table_key, (WORD) dest_id, txnid, ca->db, fastrandstate);\n\n        assert(ret == 0);\n\n        (*msgs_sent)++;\n    }\n\n    free(column_values);\n\n    return 0;\n}\n\nint process_messages(snode_t * start_row, snode_t * end_row, int entries_read,\n                        int outgoing_counters[], int * no_outgoing_counters,\n                        actor_args * ca, unsigned int * fastrandstate)\n{\n    int ret = 0;\n    int processed = 0;\n    snode_t * crt_row = NULL;\n\n    if(entries_read == 0 || start_row == NULL)\n    {\n        printf(\"ACTOR %\" PRId64 \": No msgs to process!\\n\", (int64_t) ca->consumer_id);\n        return 0;\n    }\n\n    if(debug)\n        printf(\"ACTOR %\" PRId64 \": %d msgs to process.\\n\", (int64_t) ca->consumer_id, entries_read);\n\n    for(crt_row = start_row; processed<entries_read; crt_row = NEXT(crt_row), processed++)\n    {\n        db_row_t * db_row = (db_row_t *) crt_row->value;\n//      print_long_row(db_row);\n\n        int64_t queue_entry_id = (int64_t) db_row->key;\n        assert(db_row->no_columns == 3);\n        int64_t sender_id = (int64_t) db_row->column_array[0];\n        int counter_val = (int) db_row->column_array[1];\n        char * str_value = (char *) db_row->column_array[2];\n\n        printf(\"ACTOR %\" PRId64 \": Read queue entry: (id=%\" PRId64 \", snd=%\" PRId64 \", val=%d, str=%s)\\n\", (int64_t) ca->consumer_id, queue_entry_id, sender_id, counter_val, str_value);\n\n//                  skiplist_search(ca->rcv_counters, COLLECTION_ID_0, (WORD) entries_read);\n\n        skiplist_insert(ca->rcv_counters, (WORD) sender_id, (WORD) counter_val, fastrandstate);\n        ca->total_rcv++;\n\n        counter_val++;\n        outgoing_counters[*no_outgoing_counters] = counter_val;\n        *no_outgoing_counters = (*no_outgoing_counters) + 1;\n\n        int64_t dest_id = ((int64_t) ca->consumer_id < no_actors - 1)? ((int64_t) ca->consumer_id + 1) : 0;\n\n        skiplist_insert(ca->snd_counters, (WORD) dest_id, (WORD) counter_val, fastrandstate);\n        ca->total_snd++;\n\n        assert(processed < entries_read-1 || crt_row == end_row);\n    }\n\n    assert(processed == entries_read);\n\n    return processed;\n}\n\nint produce_effects(uuid_t * txnid, actor_args * ca,\n                    int * msgs_sent, int outgoing_counters[], int no_outgoing_counters,\n                    unsigned int * fastrandstate)\n{\n    // Checkpoint local state in txn:\n\n    int ret = checkpoint_local_state(ca, txnid, fastrandstate);\n\n    assert(ret == 0);\n\n    if(debug)\n        printf(\"ACTOR %\" PRId64 \": Chekpointed local state in txn.\\n\", (int64_t) ca->consumer_id);\n\n    // Send outgoing msgs in txn:\n    ret = send_outgoing_msgs(ca, outgoing_counters, no_outgoing_counters, msgs_sent, txnid, fastrandstate);\n\n    assert(ret == 0);\n\n    if(debug)\n        printf(\"ACTOR %\" PRId64 \": Sent %d outgoing msgs in txn.\\n\", (int64_t) ca->consumer_id, *msgs_sent);\n\n    return 0;\n}\n\nvoid * actor(void * cargs)\n{\n    unsigned int seed, randno;\n    int ret = 0;\n    snode_t * start_row, * end_row;\n    int msgs_sent = 0;\n    int outgoing_counters[100];\n    int no_outgoing_counters = 0;\n\n    actor_args * ca = (actor_args *) cargs;\n\n    queue_callback * qc = ca->qc;\n\n    GET_RANDSEED(&seed, 0); // thread_id\n\n    increment_vc(ca->vc, (int) ca->consumer_id);\n\n    int64_t prev_read_head = -1, prev_consume_head = -1;\n    ret = subscribe_queue(ca->consumer_id, ca->shard_id, ca->app_id, ca->queue_table_key, ca->queue_id, qc,\n                            &prev_read_head, &prev_consume_head, 1, ca->db, &seed);\n    printf(\"Test %s - %s (%d)\\n\", \"subscribe_queue\", ret==0?\"OK\":\"FAILED\", ret);\n    if(ret)\n        return NULL;\n\n    if(debug)\n        printf(\"ACTOR %\" PRId64 \": Subscribed to queue %\" PRId64 \"/%\" PRId64 \" with callback (%p/%p/%p/%p)\\n\", (int64_t) ca->consumer_id, (int64_t) ca->queue_table_key, (int64_t) ca->queue_id, qc, qc->lock, qc->signal, qc->callback);\n\n    increment_vc(ca->vc, (int) ca->consumer_id);\n\n    ca->rcv_counters = create_skiplist_long();\n    ca->snd_counters = create_skiplist_long();\n\n    int entries_read = (int) prev_read_head + 1;\n\n    if((int64_t) ca->consumer_id == 0)\n    {\n        send_seed_msgs(ca, &msgs_sent, &seed);\n        ca->successful_enqueues += msgs_sent;\n        if(debug)\n            printf(\"ACTOR %\" PRId64 \": sent %d seed outgoing msgs.\\n\", (int64_t) ca->consumer_id, msgs_sent);\n    }\n\n    int read_status = read_queue_while_not_empty(ca, &entries_read, &start_row, &end_row);\n    if(read_status < 0)\n    {\n        return (void *) read_status;\n    }\n\n    // Add app-specific message processing work here:\n\n    no_outgoing_counters = 0;\n    ret = process_messages(start_row, end_row, entries_read, outgoing_counters, &no_outgoing_counters, ca, &seed);\n\n    if(entries_read > 0)\n    {\n        int checkpoint_success = 0;\n        while(!checkpoint_success)\n        {\n            uuid_t * txnid = new_txn(ca->db, &seed);\n\n            ret = produce_effects(txnid, ca, &msgs_sent, outgoing_counters, no_outgoing_counters, &seed);\n\n            assert(ret == 0);\n\n            // Consume input queue in same txn:\n\n            ret = consume_queue_in_txn(ca->consumer_id, ca->shard_id, ca->app_id, ca->queue_table_key, ca->queue_id,\n                                        (int64_t) ca->read_head, txnid, ca->db, &seed);\n\n            if(ret < 0 && ret != DB_ERR_QUEUE_COMPLETE)\n                printf(\"ERROR: consume_queue returned %d\\n\", ret);\n\n            if(debug)\n                printf(\"ACTOR %\" PRId64 \": consumed input queue up to %\" PRId64 \" in txn.\\n\", (int64_t) ca->consumer_id, (int64_t) ca->read_head);\n\n            ret = commit_txn(txnid, ca->vc, ca->db, &seed);\n\n            if(debug)\n                printf(\"ACTOR %\" PRId64 \": Commit returned %d.\\n\", (int64_t) ca->consumer_id, ret);\n\n            checkpoint_success = (ret == VAL_STATUS_COMMIT);\n        }\n\n        increment_vc(ca->vc, (int) ca->consumer_id);\n\n        ca->successful_consumes = ca->successful_dequeues;\n        ca->successful_enqueues += msgs_sent;\n\n        printf(\"ACTOR %\" PRId64 \": successful_dequeues=%d, successful_consumes=%d, no_enqueues=%d\\n\",\n                (int64_t) ca->consumer_id, ca->successful_dequeues, ca->successful_consumes, ca->no_enqueues);\n    }\n\n    while(ca->successful_consumes < ca->no_enqueues)\n    {\n        if(debug)\n            printf(\"ACTOR %\" PRId64 \": Blocking for input (successful_consumes=%d, no_enqueues=%d)\\n\", (int64_t) ca->consumer_id, ca->successful_consumes, ca->no_enqueues);\n\n        ret = wait_on_queue_callback(qc);\n\n        if(ret == 0)\n        {\n            if(debug)\n                printf(\"ACTOR %\" PRId64 \": Was signaled, status=%d, reading queue..\\n\", (int64_t) ca->consumer_id, ret);\n        }\n        else\n        {\n            if(debug)\n                printf(\"ACTOR %\" PRId64 \": Wait timed out, status=%d, reading queue..\\n\", (int64_t) ca->consumer_id, ret);\n        }\n\n        // Received queue notification, reading:\n\n        read_status = read_queue_while_not_empty(ca, &entries_read, &start_row, &end_row);\n        if(read_status < 0)\n        {\n            return (void *) read_status;\n        }\n\n        // Add app-specific message processing work here:\n\n        no_outgoing_counters = 0;\n        ret = process_messages(start_row, end_row, entries_read, outgoing_counters, &no_outgoing_counters, ca, &seed);\n\n        if(entries_read > 0)\n        {\n            int checkpoint_success = 0;\n            while(!checkpoint_success)\n            {\n                uuid_t * txnid = new_txn(ca->db, &seed);\n\n                ret = produce_effects(txnid, ca, &msgs_sent, outgoing_counters, no_outgoing_counters, &seed);\n\n                // Consume input queue in same txn:\n\n                ret = consume_queue_in_txn(ca->consumer_id, ca->shard_id, ca->app_id, ca->queue_table_key, ca->queue_id,\n                                            (int64_t) ca->read_head, txnid, ca->db, &seed);\n\n                if(ret < 0 && ret != DB_ERR_QUEUE_COMPLETE)\n                    printf(\"ERROR: consume_queue returned %d\\n\", ret);\n\n                if(debug)\n                    printf(\"ACTOR %\" PRId64 \": consumed input queue up to %\" PRId64 \" in txn.\\n\", (int64_t) ca->consumer_id, (int64_t) ca->read_head);\n\n                ret = commit_txn(txnid, ca->vc, ca->db, &seed);\n\n                if(debug)\n                    printf(\"ACTOR %\" PRId64 \": Commit returned %d.\\n\", (int64_t) ca->consumer_id, ret);\n\n                checkpoint_success = (ret == VAL_STATUS_COMMIT);\n            }\n\n            increment_vc(ca->vc, (int) ca->consumer_id);\n\n            ca->successful_consumes = ca->successful_dequeues;\n            ca->successful_enqueues += msgs_sent;\n\n            printf(\"ACTOR %\" PRId64 \": successful_dequeues=%d, successful_consumes=%d, successful_enqueues=%d, private_read_head=%\" PRId64 \", no_enqueues=%d\\n\",\n                    (int64_t) ca->consumer_id, ca->successful_dequeues, ca->successful_consumes, ca->successful_enqueues, ca->read_head, ca->no_enqueues);\n\n//          print_long_db(ca->db);\n        }\n\n        if(rand_sleep)\n        {\n            FASTRAND(&seed, randno);\n            sleep((randno % 10) * 0.2);\n        }\n    }\n\n    ret = unsubscribe_queue(ca->consumer_id, ca->shard_id, ca->app_id, ca->queue_table_key, ca->queue_id, 1, ca->db);\n    printf(\"Test %s - %s (%d)\\n\", \"unsubscribe_queue\", ret==0?\"OK\":\"FAILED\", ret);\n\n    free_queue_callback(qc);\n\n    return (void *) ret;\n}\n\nint main(int argc, char **argv) {\n    unsigned int seed;\n    int ret = 0;\n\n    if (argc != 3) {\n       fprintf(stderr,\"usage: %s <no_actors> <no_enqueues>\\n\", argv[0]);\n       exit(0);\n    }\n\n    no_actors = atoi(argv[1]);\n    no_items = atoi(argv[2]);\n\n    GET_RANDSEED(&seed, 0); // thread_id\n\n    // Get db pointer:\n\n    db_t * db = get_db();\n\n    // Create state table:\n\n    ret = create_state_schema(db, &seed);\n\n    // Create queue table:\n\n    ret = create_queue_schema(db, &seed);\n\n    // Create and run producer and consumer threads (also test subscribe / unsubscribe):\n\n    pthread_t actor_ts[50];\n    actor_args cargs[50];\n    int node_ids[50];\n    memset(&node_ids, 0, 50*sizeof(int));\n    int64_t counters[50];\n    memset(&counters, 0, 50*sizeof(int64_t));\n\n    for(int i=0;i<no_actors;i++)\n    {\n        node_ids[i] = i;\n    }\n\n    for(int i=0;i<no_actors;i++)\n    {\n        memset(&(cargs[i]), 0, sizeof(actor_args));\n        cargs[i].db = db;\n        cargs[i].app_id = (WORD) 0;\n        cargs[i].shard_id = (WORD) 0;\n        cargs[i].consumer_id = (WORD) node_ids[i];\n        cargs[i].state_table_key = state_table_key;\n        cargs[i].queue_table_key = queue_table_key;\n        cargs[i].queue_id = cargs[i].consumer_id;\n        cargs[i].no_enqueues = no_items;\n        cargs[i].vc = init_vc(no_actors, (int *) node_ids, (int64_t *) counters, 0);\n        cargs[i].qc = get_queue_callback(consumer_callback);\n\n        ret = pthread_create(actor_ts+i, NULL, actor, &(cargs[i]));\n        printf(\"Test %s (%d) - %s (%d)\\n\", \"create_actor_thread\", i, ret==0?\"OK\":\"FAILED\", ret);\n        if(ret)\n            return -1;\n    }\n\n    for(int i=0;i<no_actors;i++)\n    {\n        ret = pthread_join(actor_ts[i], NULL);\n        printf(\"Test %s (%d) - %s (%d)\\n\", \"join_actor_thread\", i, ret==0?\"OK\":\"FAILED\", ret);\n        if(ret)\n            return -2;\n    }\n\n    for(int i=0;i<no_actors;i++)\n    {\n        int num_enqueues = cargs[i].no_enqueues+((i==0)?2:0);\n\n        // Test enqueues:\n        printf(\"Test %s (%d) - %s (%d)\\n\", \"enqueue\", i, (cargs[i].successful_enqueues>=num_enqueues && cargs[i].successful_enqueues<=num_enqueues+1)?\"OK\":\"FAILED\", ret);\n\n        // Test dequeues:\n        printf(\"Test %s (%d) - %s (%d)\\n\", \"dequeue\", i, cargs[i].successful_dequeues==cargs[i].successful_enqueues-((i==0)?2:0)?\"OK\":\"FAILED\", ret);\n\n        // Test read head sanity:\n        printf(\"Test %s (%d) - %s (%d)\\n\", \"read_head\", i, ((int) cargs[i].read_head)==(cargs[i].successful_dequeues - 1)?\"OK\":\"FAILED\", ret);\n\n        // Test consumes:\n        printf(\"Test %s (%d) - %s (%d)\\n\", \"consume\", i, cargs[i].successful_consumes==cargs[i].successful_dequeues?\"OK\":\"FAILED\", ret);\n    }\n\n    print_long_db(db);\n\n    return 0;\n}\n\n\n\n\n"
  },
  {
    "path": "backend/test/actor_ring_tests_remote.c",
    "content": "/*\n * Copyright (C) 2019-2021 Deutsche Telekom AG\n *\n * Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:\n *\n * 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.\n *\n * 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.\n *\n * 3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission.\n *\n * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS \"AS IS\" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n */\n\n#include <stdio.h>\n#include <stdlib.h>\n#include <pthread.h>\n#include <assert.h>\n#include <pthread.h>\n#include <unistd.h>\n#include <string.h>\n#include <time.h>\n\n// #include \"txns.h\"\n\n#include <sys/types.h>\n#include <sys/socket.h>\n#include <netinet/in.h>\n#include <netdb.h>\n#include <uuid/uuid.h>\n\n#include \"client_api.h\"\n#include \"fastrand.h\"\n\n\n#define COLLECTION_ID_0 0 // rcv_counters map\n#define COLLECTION_ID_1 1 // snd_counters map\n#define COLLECTION_ID_2 2 // local counter variable as int\n#define COLLECTION_ID_3 3 // local counter variable as char blob\n\nint no_actors = 2;\nint no_items = 20;\n\nint min_no_state_cols = 3;\nint no_state_primary_keys = 1;\nint min_state_clustering_keys = 1;\nint no_state_index_keys = 1;\n\nint no_queue_cols = 2;\n\nWORD state_table_key = (WORD) 0;\nWORD queue_table_key = (WORD) 1;\n\nint rand_sleep = 1;\n\nint debug = 1;\nint debug_lock = 0;\n\ntypedef struct actor_collection_item {\n    int actor_id;\n    int collection_id;\n    int item_id;\n    int item_value;\n} actor_collection_item_t;\n\ntypedef struct actor_queue_item {\n    int sender_id;\n    int item_value;\n} actor_queue_item_t;\n\ntypedef struct actor_args\n{\n    remote_db_t * db;\n    WORD state_table_key;\n    WORD queue_table_key;\n    WORD queue_id;\n    int no_enqueues;\n\n    WORD consumer_id;\n    WORD shard_id;\n    WORD app_id;\n\n    skiplist_t * rcv_counters;\n    skiplist_t * snd_counters;\n    int64_t total_rcv;\n    int64_t total_snd;\n\n    int successful_enqueues;\n    int successful_dequeues;\n    int successful_consumes;\n    int successful_replays;\n\n    int64_t read_head;\n    int64_t read_head_after_replay;\n\n    queue_callback * qc;\n\n    db_schema_t * schema;\n\n    int status;\n} actor_args;\n\n// Create schema:\n\ndb_schema_t* create_state_schema()\n{\n    int primary_key_idx = 0;\n    int clustering_key_idxs[2];\n    clustering_key_idxs[0]=1;\n    clustering_key_idxs[1]=2;\n    int index_key_idx=3;\n\n    int * col_types = NULL;\n\n    //  Col types are not enforced:\n    /*\n    col_types = (int *) malloc((no_state_cols+1) * sizeof(int));\n\n    for(int i=0;i<no_state_cols;i++)\n        col_types[i] = DB_TYPE_INT32;\n\n    col_types[no_state_cols] = DB_TYPE_BLOB; // Include blob\n    */\n\n    db_schema_t* db_schema = db_create_schema(col_types, min_no_state_cols, &primary_key_idx, no_state_primary_keys, clustering_key_idxs, min_state_clustering_keys, &index_key_idx, no_state_index_keys);\n\n    assert(db_schema != NULL && \"Schema creation failed\");\n\n    return db_schema;\n}\n\nint create_queue_schema(remote_db_t * db, unsigned int * fastrandstate)\n{\n    assert(no_queue_cols == 2);\n    int minority_status = 0;\n\n    // Create input queues for all actors:\n\n    int ret = 0;\n\n    for(int64_t queue_id=0;queue_id<no_actors;queue_id++)\n    {\n        ret = remote_create_queue_in_txn(queue_table_key, (WORD) queue_id, &minority_status, NULL, db);\n        printf(\"Test %s - %s (%d)\\n\", \"create_queue\", ret==0?\"OK\":\"FAILED\", ret);\n    }\n\n    return ret;\n}\n\n\nvoid consumer_callback(queue_callback_args * qca)\n{\n    printf(\"Consumer %\" PRId64 \"/%\" PRId64 \"/%\" PRId64 \" received notification for queue %\" PRId64 \"/%\" PRId64 \", status %d\\n\",\n            (int64_t) qca->app_id, (int64_t) qca->shard_id, (int64_t) qca->consumer_id,\n            (int64_t) qca->table_key, (int64_t) qca->queue_id,\n            qca->status);\n}\n\nint read_queue_while_not_empty(actor_args * ca, int * entries_read, snode_t ** start_row, snode_t ** end_row)\n{\n    int read_status = QUEUE_STATUS_READ_INCOMPLETE, minority_status = 0;\n\n    while(read_status != QUEUE_STATUS_READ_COMPLETE)\n    {\n        read_status = remote_read_queue_in_txn(ca->consumer_id, ca->shard_id, ca->app_id,\n                        ca->queue_table_key, ca->queue_id,\n                        2, entries_read, &ca->read_head,\n                        start_row, end_row, &minority_status, NULL, ca->db);\n\n        if(read_status < 0)\n        {\n            printf(\"ERROR: read_queue returned %d\\n\", read_status);\n            return read_status;\n        }\n        else\n        {\n            assert(read_status == QUEUE_STATUS_READ_COMPLETE || read_status == QUEUE_STATUS_READ_INCOMPLETE);\n\n            ca->successful_dequeues += (*entries_read);\n\n            if((*entries_read) > 0)\n            {\n                printf(\"CONSUMER %\" PRId64 \": successful_dequeues=%d, last_entry_id=%\" PRId64 \"\\n\",\n                        (int64_t) ca->consumer_id, ca->successful_dequeues, (int64_t) (*end_row)->key);\n\n                if(((int64_t) (*end_row)->key) != ca->successful_dequeues - 1)\n                    printf(\"Test %s - FAILED (%\" PRId64 \" != %d)\\n\", \"last_entry_id\", (int64_t) (*end_row)->key, ca->successful_dequeues - 1);\n            }\n        }\n    }\n\n    return read_status;\n}\n\nchar digits[10][10] = { \"zero\", \"one\", \"two\", \"three\", \"four\", \"five\", \"six\", \"seven\", \"eight\", \"nine\" };\n\nint checkpoint_local_state(actor_args * ca, uuid_t * txnid, unsigned int * fastrandstate)\n{\n    int ret = 0, minority_status = 0;\n\n    WORD * column_values = (WORD *) malloc(4 * sizeof(WORD));\n\n    column_values[0] = ca->consumer_id;\n\n    // Checkpoint the 2 maps:\n\n    for(snode_t * node = HEAD(ca->rcv_counters); node != NULL;node = NEXT(node))\n    {\n        column_values[1] = (WORD) COLLECTION_ID_0;\n        column_values[2] = node->key;\n        column_values[3] = node->value;\n        char * str_value = ((int) node->value <= 9)?(digits[(int) node->value]):\"NaN\";\n\n        ret = remote_insert_in_txn(column_values, 4, no_state_primary_keys, 2,\n                                    (WORD) str_value, strnlen((const char *) str_value, 10) + 1,\n                                    ca->state_table_key, &minority_status, txnid, ca->db);\n\n        assert(ret == 0);\n    }\n\n    for(snode_t * node = HEAD(ca->snd_counters);node != NULL;node = NEXT(node))\n    {\n        column_values[1] = (WORD) COLLECTION_ID_1;\n        column_values[2] = node->key;\n        column_values[3] = node->value;\n        char * str_value = ((int) node->value <= 9)?(digits[(int) node->value]):\"NaN\";\n\n        ret = remote_insert_in_txn(column_values, 4, no_state_primary_keys, 2,\n                                    (WORD) str_value, strnlen((const char *) str_value, 10) + 1,\n                                    ca->state_table_key, &minority_status, txnid, ca->db);\n\n        assert(ret == 0);\n    }\n\n    // Checkpoint the standalone counter variable, once in an int column, once in a char blob column:\n\n    column_values[1] = (WORD) COLLECTION_ID_2;\n    column_values[2] = (WORD) ca->total_rcv;\n\n    ret = remote_insert_in_txn(column_values, 3, no_state_primary_keys, 1,\n                                NULL, 0,\n                                ca->state_table_key, &minority_status, txnid, ca->db);\n\n    char * str_value = ((int) ca->total_rcv <= 9)?(digits[(int) ca->total_rcv]):\"NaN\";\n\n    column_values[1] = (WORD) COLLECTION_ID_3;\n\n    ret = remote_insert_in_txn(column_values, 2, no_state_primary_keys, 1,\n                                (WORD) str_value, strnlen((const char *) str_value, 10) + 1,\n                                ca->state_table_key, &minority_status, txnid, ca->db);\n\n    free(column_values);\n\n    return 0;\n}\n\n\nint send_seed_msgs(actor_args * ca, int * msgs_sent, unsigned int * fastrandstate)\n{\n    int ret = 0;\n    int64_t dest_id = ((int64_t) ca->consumer_id < no_actors - 1)? ((int64_t) ca->consumer_id + 1) : 0;\n\n    int no_outgoing_counters = 2;\n\n    *msgs_sent=0;\n\n    assert(no_queue_cols == 2);\n\n    WORD * column_values = (WORD *) malloc(no_queue_cols * sizeof(WORD));\n    int minority_status = 0;\n\n    for(int i=0;i<no_outgoing_counters;i++)\n    {\n        column_values[0] = ca->consumer_id;\n        column_values[1] = (WORD) i;\n        char * str_value = (i <= 9)?(digits[i]):\"NaN\";\n\n        ret = remote_enqueue_in_txn(column_values, no_queue_cols, (WORD) str_value, strnlen((const char *) str_value, 10) + 1, ca->queue_table_key, (WORD) dest_id, &minority_status, NULL, ca->db);\n\n        assert(ret == 0);\n\n        (*msgs_sent)++;\n\n        skiplist_insert(ca->snd_counters, (WORD) dest_id, (WORD) i, fastrandstate);\n\n        ca->total_snd++;\n    }\n\n    free(column_values);\n\n    return 0;\n}\n\n\nint send_outgoing_msgs(actor_args * ca, int outgoing_counters[], int no_outgoing_counters, int * msgs_sent, uuid_t * txnid, unsigned int * fastrandstate)\n{\n    int ret = 0;\n    int64_t dest_id = ((int64_t) ca->consumer_id < no_actors - 1)? ((int64_t) ca->consumer_id + 1) : 0;\n\n/*\n    if(debug)\n        printf(\"ACTOR %\" PRId64 \": Sending %d msgs to ACTOR %\" PRId64 \".\\n\", (int64_t) ca->consumer_id, no_outgoing_counters, dest_id);\n*/\n\n    assert(no_queue_cols == 2);\n\n    *msgs_sent=0;\n\n    WORD * column_values = (WORD *) malloc(no_queue_cols * sizeof(WORD));\n    int minority_status = 0;\n\n    for(int i=0;i<no_outgoing_counters;i++)\n    {\n        column_values[0] = ca->consumer_id;\n        column_values[1] = (WORD) outgoing_counters[i];\n        char * str_value = (outgoing_counters[i] <= 9)?(digits[outgoing_counters[i]]):\"NaN\";\n\n        ret = remote_enqueue_in_txn(column_values, no_queue_cols, (WORD) str_value, strnlen((const char *) str_value, 10) + 1, ca->queue_table_key, (WORD) dest_id, &minority_status, txnid, ca->db);\n\n        assert(ret == 0);\n\n        (*msgs_sent)++;\n    }\n\n    free(column_values);\n\n    return 0;\n}\n\nint process_messages(snode_t * start_row, snode_t * end_row, int entries_read,\n                        int outgoing_counters[], int * no_outgoing_counters,\n                        actor_args * ca, unsigned int * fastrandstate)\n{\n    int ret = 0;\n    int processed = 0;\n    snode_t * crt_row = NULL;\n\n    if(entries_read == 0 || start_row == NULL)\n    {\n        printf(\"ACTOR %\" PRId64 \": No msgs to process!\\n\", (int64_t) ca->consumer_id);\n        return 0;\n    }\n\n    if(debug)\n        printf(\"ACTOR %\" PRId64 \": %d msgs to process.\\n\", (int64_t) ca->consumer_id, entries_read);\n\n    for(crt_row = start_row; processed<entries_read; crt_row = NEXT(crt_row), processed++)\n    {\n        db_row_t * db_row = (db_row_t *) crt_row->value;\n//      print_long_row(db_row);\n\n        int64_t queue_entry_id = (int64_t) db_row->key;\n        assert(db_row->no_columns == 3);\n        int64_t sender_id = (int64_t) db_row->column_array[0];\n        int counter_val = (int) db_row->column_array[1];\n        char * str_value = (char *) db_row->column_array[2];\n\n        printf(\"ACTOR %\" PRId64 \": Read queue entry: (id=%\" PRId64 \", snd=%\" PRId64 \", val=%d, str=%s)\\n\", (int64_t) ca->consumer_id, queue_entry_id, sender_id, counter_val, str_value);\n\n//                  skiplist_search(ca->rcv_counters, COLLECTION_ID_0, (WORD) entries_read);\n\n        skiplist_insert(ca->rcv_counters, (WORD) sender_id, (WORD) counter_val, fastrandstate);\n        ca->total_rcv++;\n\n        counter_val++;\n        outgoing_counters[*no_outgoing_counters] = counter_val;\n        *no_outgoing_counters = (*no_outgoing_counters) + 1;\n\n        int64_t dest_id = ((int64_t) ca->consumer_id < no_actors - 1)? ((int64_t) ca->consumer_id + 1) : 0;\n\n        skiplist_insert(ca->snd_counters, (WORD) dest_id, (WORD) counter_val, fastrandstate);\n        ca->total_snd++;\n\n        assert(processed < entries_read-1 || crt_row == end_row);\n    }\n\n    assert(processed == entries_read);\n\n    return processed;\n}\n\nint produce_effects(uuid_t * txnid, actor_args * ca,\n                    int * msgs_sent, int outgoing_counters[], int no_outgoing_counters,\n                    unsigned int * fastrandstate)\n{\n    // Checkpoint local state in txn:\n\n    int ret = checkpoint_local_state(ca, txnid, fastrandstate);\n\n    assert(ret == 0);\n\n    if(debug)\n        printf(\"ACTOR %\" PRId64 \": Chekpointed local state in txn.\\n\", (int64_t) ca->consumer_id);\n\n    // Send outgoing msgs in txn:\n    ret = send_outgoing_msgs(ca, outgoing_counters, no_outgoing_counters, msgs_sent, txnid, fastrandstate);\n\n    assert(ret == 0);\n\n    if(debug)\n        printf(\"ACTOR %\" PRId64 \": Sent %d outgoing msgs in txn.\\n\", (int64_t) ca->consumer_id, *msgs_sent);\n\n    return 0;\n}\n\nvoid * actor(void * cargs)\n{\n    unsigned int seed, randno;\n    int ret = 0, minority_status = 0;\n    snode_t * start_row, * end_row;\n    int msgs_sent = 0;\n    int outgoing_counters[100];\n    int no_outgoing_counters = 0;\n\n    actor_args * ca = (actor_args *) cargs;\n\n    queue_callback * qc = ca->qc;\n\n    GET_RANDSEED(&seed, 0); // thread_id\n\n    int64_t prev_read_head = -1, prev_consume_head = -1;\n    int minority_status = 0;\n    ret = remote_subscribe_queue(ca->consumer_id, ca->shard_id, ca->app_id, ca->queue_table_key, ca->queue_id, qc,\n                            &prev_read_head, &prev_consume_head, &minority_status, ca->db);\n    printf(\"Test %s - %s (%d)\\n\", \"subscribe_queue\", ret==0?\"OK\":\"FAILED\", ret);\n    if(ret)\n        return NULL;\n\n    if(debug)\n        printf(\"ACTOR %\" PRId64 \": Subscribed to queue %\" PRId64 \"/%\" PRId64 \" with callback (%p/%p/%p/%p)\\n\", (int64_t) ca->consumer_id, (int64_t) ca->queue_table_key, (int64_t) ca->queue_id, qc, qc->lock, qc->signal, qc->callback);\n\n    ca->rcv_counters = create_skiplist_long();\n    ca->snd_counters = create_skiplist_long();\n\n    int entries_read = (int) prev_read_head + 1;\n\n    if((int64_t) ca->consumer_id == 0)\n    {\n        ret = send_seed_msgs(ca, &msgs_sent, &seed);\n        ca->successful_enqueues += msgs_sent;\n        if(debug)\n            printf(\"ACTOR %\" PRId64 \": sent %d seed outgoing msgs (status = %d).\\n\", (int64_t) ca->consumer_id, msgs_sent, ret);\n//      remote_print_long_table(state_table_key, ca->db);\n//      remote_print_long_table(queue_table_key, ca->db);\n    }\n\n    int read_status = read_queue_while_not_empty(ca, &entries_read, &start_row, &end_row);\n    if(read_status < 0)\n    {\n        return (void *) read_status;\n    }\n\n    // Add app-specific message processing work here:\n\n    no_outgoing_counters = 0;\n    ret = process_messages(start_row, end_row, entries_read, outgoing_counters, &no_outgoing_counters, ca, &seed);\n    int minority_status = 0;\n\n    if(entries_read > 0)\n    {\n        int checkpoint_success = 0;\n        while(!checkpoint_success)\n        {\n            uuid_t * txnid = remote_new_txn(ca->db);\n\n            ret = produce_effects(txnid, ca, &msgs_sent, outgoing_counters, no_outgoing_counters, &seed);\n\n            assert(ret == 0);\n\n            // Consume input queue in same txn:\n\n            ret = remote_consume_queue_in_txn(ca->consumer_id, ca->shard_id, ca->app_id, ca->queue_table_key, ca->queue_id,\n                                        (int64_t) ca->read_head, &minority_status, txnid, ca->db);\n\n            if(ret < 0 && ret != DB_ERR_QUEUE_COMPLETE)\n                printf(\"ERROR: consume_queue returned %d\\n\", ret);\n\n            if(debug)\n                printf(\"ACTOR %\" PRId64 \": consumed input queue up to %\" PRId64 \" in txn.\\n\", (int64_t) ca->consumer_id, (int64_t) ca->read_head);\n\n            ret = remote_commit_txn(txnid, &minority_status, ca->db);\n\n            if(debug)\n                printf(\"ACTOR %\" PRId64 \": Commit returned %d.\\n\", (int64_t) ca->consumer_id, ret);\n\n            checkpoint_success = (ret == VAL_STATUS_COMMIT);\n        }\n\n//      remote_print_long_table(state_table_key, ca->db);\n//      remote_print_long_table(queue_table_key, ca->db);\n\n        ca->successful_consumes = ca->successful_dequeues;\n        ca->successful_enqueues += msgs_sent;\n\n        printf(\"ACTOR %\" PRId64 \": successful_dequeues=%d, successful_consumes=%d, no_enqueues=%d\\n\",\n                (int64_t) ca->consumer_id, ca->successful_dequeues, ca->successful_consumes, ca->no_enqueues);\n    }\n\n    while(ca->successful_consumes < ca->no_enqueues)\n    {\n        if(debug)\n            printf(\"ACTOR %\" PRId64 \": Blocking for input (successful_consumes=%d, no_enqueues=%d)\\n\", (int64_t) ca->consumer_id, ca->successful_consumes, ca->no_enqueues);\n\n        ret = wait_on_queue_callback(qc);\n\n        if(ret == 0)\n        {\n            if(debug)\n                printf(\"ACTOR %\" PRId64 \": Was signaled, status=%d, reading queue..\\n\", (int64_t) ca->consumer_id, ret);\n        }\n        else\n        {\n            if(debug)\n                printf(\"ACTOR %\" PRId64 \": Wait timed out, status=%d, reading queue..\\n\", (int64_t) ca->consumer_id, ret);\n        }\n\n        // Received queue notification, reading:\n\n        read_status = read_queue_while_not_empty(ca, &entries_read, &start_row, &end_row);\n        if(read_status < 0)\n        {\n            return (void *) read_status;\n        }\n\n        no_outgoing_counters = 0;\n        ret = process_messages(start_row, end_row, entries_read, outgoing_counters, &no_outgoing_counters, ca, &seed);\n\n        if(entries_read > 0)\n        {\n            int checkpoint_success = 0;\n            while(!checkpoint_success)\n            {\n                uuid_t * txnid = remote_new_txn(ca->db);\n\n                ret = produce_effects(txnid, ca, &msgs_sent, outgoing_counters, no_outgoing_counters, &seed);\n\n                // Consume input queue in same txn:\n\n                ret = remote_consume_queue_in_txn(ca->consumer_id, ca->shard_id, ca->app_id, ca->queue_table_key, ca->queue_id,\n                                            (int64_t) ca->read_head, &minority_status, txnid, ca->db);\n\n                if(ret < 0 && ret != DB_ERR_QUEUE_COMPLETE)\n                    printf(\"ERROR: consume_queue returned %d\\n\", ret);\n\n                if(debug)\n                    printf(\"ACTOR %\" PRId64 \": consumed input queue up to %\" PRId64 \" in txn.\\n\", (int64_t) ca->consumer_id, (int64_t) ca->read_head);\n\n                ret = remote_commit_txn(txnid, ca->db);\n\n                if(debug)\n                    printf(\"ACTOR %\" PRId64 \": Commit returned %d.\\n\", (int64_t) ca->consumer_id, ret);\n\n                checkpoint_success = (ret == VAL_STATUS_COMMIT);\n            }\n\n//          remote_print_long_table(state_table_key, ca->db);\n//          remote_print_long_table(queue_table_key, ca->db);\n\n            ca->successful_consumes = ca->successful_dequeues;\n            ca->successful_enqueues += msgs_sent;\n\n            printf(\"ACTOR %\" PRId64 \": successful_dequeues=%d, successful_consumes=%d, successful_enqueues=%d, private_read_head=%\" PRId64 \", no_enqueues=%d\\n\",\n                    (int64_t) ca->consumer_id, ca->successful_dequeues, ca->successful_consumes, ca->successful_enqueues, ca->read_head, ca->no_enqueues);\n\n//          print_long_db(ca->db);\n        }\n\n        if(rand_sleep)\n        {\n            FASTRAND(&seed, randno);\n            sleep((randno % 10) * 0.2);\n        }\n    }\n\n    ret = remote_unsubscribe_queue(ca->consumer_id, ca->shard_id, ca->app_id, ca->queue_table_key, ca->queue_id, &minority_status, ca->db);\n    printf(\"Test %s - %s (%d)\\n\", \"unsubscribe_queue\", ret==0?\"OK\":\"FAILED\", ret);\n\n//  free_queue_callback(qc);\n\n    return (void *) ret;\n}\n\nint main(int argc, char **argv) {\n    char *hostname;\n    int portno;\n    unsigned int seed;\n    int ret = 0;\n\n    GET_RANDSEED(&seed, 0); // thread_id\n\n    // Get db pointer:\n\n    /* check command line arguments */\n    if (argc != 5) {\n       fprintf(stderr,\"usage: %s <hostname> <port> <no_actors> <no_enqueues>\\n\", argv[0]);\n       exit(0);\n    }\n    hostname = argv[1];\n    portno = atoi(argv[2]);\n    no_actors = atoi(argv[3]);\n    no_items = atoi(argv[4]);\n\n    remote_db_t * db = get_remote_db(1);\n\n    add_server_to_membership(hostname, portno, db, &seed);\n//    add_server_to_membership(hostname, portno+1, db, &seed);\n//    add_server_to_membership(hostname, portno+2, db, &seed);\n\n    // Create state table:\n\n    db_schema_t* schema = create_state_schema();\n\n    // Create queue table:\n\n    ret = create_queue_schema(db, &seed);\n\n    // Create and run producer and consumer threads (also test subscribe / unsubscribe):\n\n    pthread_t actor_ts[50];\n    actor_args cargs[50];\n    int node_ids[50];\n    memset(&node_ids, 0, 50*sizeof(int));\n    int64_t counters[50];\n    memset(&counters, 0, 50*sizeof(int64_t));\n\n    for(int i=0;i<no_actors;i++)\n    {\n        node_ids[i] = i;\n    }\n\n    for(int i=0;i<no_actors;i++)\n    {\n        memset(&(cargs[i]), 0, sizeof(actor_args));\n        cargs[i].db = db;\n        cargs[i].app_id = (WORD) 0;\n        cargs[i].shard_id = (WORD) 0;\n        cargs[i].consumer_id = (WORD) node_ids[i];\n        cargs[i].state_table_key = state_table_key;\n        cargs[i].queue_table_key = queue_table_key;\n        cargs[i].queue_id = cargs[i].consumer_id;\n        cargs[i].no_enqueues = no_items;\n        cargs[i].qc = get_queue_callback(consumer_callback);\n        cargs[i].schema = schema;\n\n        ret = pthread_create(actor_ts+i, NULL, actor, &(cargs[i]));\n        printf(\"Test %s (%d) - %s (%d)\\n\", \"create_actor_thread\", i, ret==0?\"OK\":\"FAILED\", ret);\n        if(ret)\n            return -1;\n    }\n\n    for(int i=0;i<no_actors;i++)\n    {\n        ret = pthread_join(actor_ts[i], NULL);\n        printf(\"Test %s (%d) - %s (%d)\\n\", \"join_actor_thread\", i, ret==0?\"OK\":\"FAILED\", ret);\n        if(ret)\n            return -2;\n    }\n\n    for(int i=0;i<no_actors;i++)\n    {\n        int num_enqueues = cargs[i].no_enqueues+((i==0)?2:0);\n\n        // Test enqueues:\n        printf(\"Test %s (%d) - %s (%d)\\n\", \"enqueue\", i, (cargs[i].successful_enqueues>=num_enqueues && cargs[i].successful_enqueues<=num_enqueues+1)?\"OK\":\"FAILED\", ret);\n\n        // Test dequeues:\n        printf(\"Test %s (%d) - %s (%d)\\n\", \"dequeue\", i, cargs[i].successful_dequeues==cargs[i].successful_enqueues-((i==0)?2:0)?\"OK\":\"FAILED\", ret);\n\n        // Test read head sanity:\n        printf(\"Test %s (%d) - %s (%d)\\n\", \"read_head\", i, ((int) cargs[i].read_head)==(cargs[i].successful_dequeues - 1)?\"OK\":\"FAILED\", ret);\n\n        // Test consumes:\n        printf(\"Test %s (%d) - %s (%d)\\n\", \"consume\", i, cargs[i].successful_consumes==cargs[i].successful_dequeues?\"OK\":\"FAILED\", ret);\n    }\n\n    remote_print_long_table(state_table_key, db);\n    remote_print_long_table(queue_table_key, db);\n\n    return 0;\n}\n\n\n\n"
  },
  {
    "path": "backend/test/db_unit_tests.c",
    "content": "/*\n * Copyright (C) 2019-2021 Deutsche Telekom AG\n *\n * Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:\n *\n * 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.\n *\n * 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.\n *\n * 3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission.\n *\n * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS \"AS IS\" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n */\n\n#include <stdio.h>\n#include <stdlib.h>\n#include <pthread.h>\n#include <assert.h>\n\n#include \"db.h\"\n\ntypedef struct actor_collection_item {\n    int actor_id;\n    int collection_id;\n    int item_id;\n    int item_value;\n} actor_collection_item_t;\n\nint no_cols = 4;\nint no_primary_keys = 1;\nint no_clustering_keys = 2;\nint no_index_keys = 1;\n\nint no_actors = 2;\nint no_collections = 2;\nint no_items = 2;\n\n// Create schema:\n\nint create_schema(db_t * db, unsigned int * fastrandstate) {\n    int primary_key_idx = 0;\n    int clustering_key_idxs[2];\n    clustering_key_idxs[0]=1;\n    clustering_key_idxs[1]=2;\n    int index_key_idx=3;\n\n    int * col_types = (int *) malloc(no_cols * sizeof(int));\n\n    for(int i=0;i<no_cols;i++)\n        col_types[i] = DB_TYPE_INT32;\n\n    db_schema_t* db_schema = db_create_schema(col_types, no_cols, &primary_key_idx, no_primary_keys, clustering_key_idxs, no_clustering_keys, &index_key_idx, no_index_keys);\n\n    assert(db_schema != NULL && \"Schema creation failed\");\n\n    // Create table:\n\n    return db_create_table((WORD) 0, db_schema, db, fastrandstate);;\n}\n\n// Populate DB (also db_insert test):\n\nint populate_db(db_t * db, unsigned int * fastrandstate) {\n    for(int64_t aid=0;aid<no_actors;aid++)\n    {\n        for(int64_t cid=0;cid<no_collections;cid++)\n        {\n            for(int64_t iid=0;iid<no_items;iid++)\n            {\n                WORD * column_values = (WORD *) malloc(no_cols * sizeof(WORD));\n\n                column_values[0] = (WORD) aid;\n                column_values[1] = (WORD) cid;\n                column_values[2] = (WORD) iid;\n                column_values[3] = (WORD) iid + 1;\n\n                if(db_insert(column_values, no_cols, no_clustering_keys, 0, (WORD) 0, db, fastrandstate) != 0)\n                    return -1;\n            }\n        }\n    }\n\n    return 0;\n}\n\n// Read by (PK, CK1, CK2, Column):\n\nint test_search_column(db_t * db) {\n    int ret = 0;\n    int column_idxs[no_cols];\n    for(int i=0;i<no_cols;i++)\n        column_idxs[i]=i;\n\n    for(int64_t aid=0;aid<no_actors;aid++)\n    {\n        for(int64_t cid=0;cid<no_collections;cid++)\n        {\n            for(int64_t iid=0;iid<no_items;iid++)\n            {\n                WORD * column_values = (WORD *) malloc(no_cols * sizeof(WORD));\n\n                column_values[0] = (WORD) aid;\n                column_values[1] = (WORD) cid;\n                column_values[2] = (WORD) iid;\n                column_values[3] = (WORD) iid + 1;\n\n                WORD* col_values = db_search_columns(&column_values[0], &column_values[1], 2, (int*) column_idxs, no_cols, (WORD) 0, db);\n\n                for(int i=0;i<no_cols;i++)\n                {\n                    if(col_values[i] != column_values[i])\n                    {\n                        printf(\"Read back mismatched column %d on row (%\" PRId64 \", %\" PRId64 \", %\" PRId64 \", %\" PRId64 \"). Read back: (%\" PRId64 \", %\" PRId64 \", %\" PRId64 \", %\" PRId64 \")!\\n\",\n                                i, (int64_t) column_values[0], (int64_t) column_values[1], (int64_t) column_values[2], (int64_t) column_values[3],\n                                (int64_t) col_values[0], (int64_t) col_values[1], (int64_t) col_values[2], (int64_t) col_values[3]);\n                        ret = -1;\n                    }\n                }\n            }\n        }\n    }\n\n    return ret;\n}\n\n\n// Read by (PK):\n\nint test_search_pk(db_t * db)\n{\n    for(int64_t aid=0;aid<no_actors;aid++)\n    {\n        db_row_t* row = db_search((WORD *) &aid, (WORD) 0, db);\n\n        if((int64_t) row->key != aid)\n        {\n            printf(\"Read back mismatched pk %\" PRId64 \" ( != %\" PRId64 \")!\\n\", (int64_t) row->key, aid);\n            return -1;\n        }\n    }\n\n    return 0;\n}\n\n// Read by (PK, CK1):\n\nint test_search_pk_ck1(db_t * db)\n{\n    for(int64_t aid=0;aid<no_actors;aid++)\n    {\n        for(int64_t cid=0;cid<no_collections;cid++)\n        {\n            db_row_t* row = db_search_clustering((WORD *) &aid, (WORD *) &cid, 1, (WORD) 0, db);\n\n            if((int64_t) row->key != cid)\n            {\n                printf(\"Read back mismatched ck1 %\" PRId64 \" ( != %\" PRId64 \") in cell (%\" PRId64 \", %\" PRId64 \")!\\n\", (int64_t) row->key, cid, aid, cid);\n                return -1;\n            }\n        }\n    }\n\n    return 0;\n}\n\n// Read by (PK, CK1, CK2):\n\nint test_search_pk_ck1_ck2(db_t * db)\n{\n    for(int64_t aid=0;aid<no_actors;aid++)\n    {\n        for(int64_t cid=0;cid<no_collections;cid++)\n        {\n            for(int64_t iid=0;iid<no_items;iid++)\n            {\n                WORD * cks = (WORD *) malloc(2 * sizeof(WORD));\n                cks[0] = (WORD) cid;\n                cks[1] = (WORD) iid;\n\n                db_row_t* row = db_search_clustering((WORD *) &aid, cks, 2, (WORD) 0, db);\n\n                if((int64_t) row->key != iid)\n                {\n                    printf(\"Read back mismatched ck2 %\" PRId64 \" ( != %\" PRId64 \") in cell (%\" PRId64 \", %\" PRId64 \", %\" PRId64 \")!\\n\", (int64_t) row->key, iid, aid, cid, iid);\n                    return -1;\n                }\n            }\n        }\n    }\n\n    return 0;\n}\n\n// Read by secondary index:\n\nint test_search_index(db_t * db)\n{\n    // TO DO: fix\n\n    for(int64_t iid=0;iid<no_items;iid++)\n    {\n        db_row_t* row = db_search_index((WORD) (iid + 1), 0, (WORD) 0, db);\n\n        if(row == NULL)\n        {\n            printf(\"Read back mismatched row for secondary key %\" PRId64 \"!\\n\", iid + 1);\n            return -1;\n        }\n    }\n\n    return 0;\n}\n\n// Update by (PK, CK1, CK2, Column):\n\nint test_update(db_t * db)\n{\n    int ret = 0;\n    int column_idxs[no_cols];\n    for(int i=0;i<no_cols;i++)\n        column_idxs[i]=i;\n\n    for(int64_t aid=0;aid<no_actors;aid++)\n    {\n        for(int64_t cid=0;cid<no_collections;cid++)\n        {\n            for(int64_t iid=0;iid<no_items;iid++)\n            {\n                WORD * column_values = (WORD *) malloc(no_cols * sizeof(WORD));\n\n                column_values[0] = (WORD) aid;\n                column_values[1] = (WORD) cid;\n                column_values[2] = (WORD) iid;\n                column_values[3] = (WORD) iid + 2;\n\n                if(db_update(column_values, no_cols, 2, 0, column_idxs, (WORD) 0, db) != 0)\n                    return -2;\n\n                WORD* col_values = db_search_columns(&column_values[0], &column_values[1], 2, (int*) column_idxs, no_cols, (WORD) 0, db);\n\n                for(int i=0;i<no_cols;i++)\n                {\n                    if(col_values[i] != column_values[i])\n                    {\n                        printf(\"Read back mismatched column %d on row (%\" PRId64 \", %\" PRId64 \", %\" PRId64 \", %\" PRId64 \"). Read back: (%\" PRId64 \", %\" PRId64 \", %\" PRId64 \", %\" PRId64 \")!\\n\",\n                                i, (int64_t) column_values[0], (int64_t) column_values[1], (int64_t) column_values[2], (int64_t) column_values[3],\n                                (int64_t) col_values[0], (int64_t) col_values[1], (int64_t) col_values[2], (int64_t) col_values[3]);\n                        ret = -1;\n                    }\n                }\n            }\n        }\n    }\n\n    return ret;\n}\n\n// Delete by (PK):\n\nint test_delete_pk(db_t * db, unsigned int * fastrandstate)\n{\n    for(int64_t aid=0;aid<no_actors;aid++)\n    {\n        if(db_delete_row((WORD *) &aid, (WORD) 0, db, fastrandstate) != 0)\n        {\n            printf(\"Delete failed for pk %\" PRId64 \"!\\n\", aid);\n            return -1;\n        }\n\n        db_row_t* row = db_search((WORD *) &aid, (WORD) 0, db);\n\n        if(row != NULL)\n        {\n            printf(\"Delete failed for pk %\" PRId64 \" - did not delete row (return row key %\" PRId64 \")!\\n\", aid, (int64_t) row->key);\n            return -1;\n        }\n    }\n\n    return 0;\n}\n\n// Delete by (PK, CK1):\n\nint test_delete_pk_ck1(db_t * db)\n{\n    // TO DO:\n\n    return 0;\n}\n\n// Delete by (PK, CK1, CK2):\n\nint test_delete_pk_ck1_ck2(db_t * db)\n{\n    // TO DO:\n\n    return 0;\n}\n\n// Delete by (PK, CK1, CK2, Column):\n\nint test_delete_col(db_t * db)\n{\n    // TO DO:\n\n    return 0;\n}\n\n// Delete by secondary index:\nint test_delete_index(db_t * db)\n{\n    for(int64_t iid=0;iid<no_items;iid++)\n    {\n        if(db_delete_by_index((WORD) (iid + 1), 0, (WORD) 0, db) != 0)\n        {\n            printf(\"Delete failed for secondary key value %\" PRId64 \"!\\n\", iid + 1);\n            return -1;\n        }\n\n        db_row_t* row = db_search_index((WORD) (iid + 1), 0, (WORD) 0, db);\n\n        if(row != NULL)\n        {\n            printf(\"Delete failed for secondary key value %\" PRId64 \" - did not delete row (return row key %\" PRId64 \")!\\n\", iid + 1, (int64_t) row->key);\n            return -1;\n        }\n    }\n\n    return 0;\n}\n\n// Range search by PK:\n\nint test_range_search_pk(db_t * db)\n{\n    // TO DO: Improve (check returned keys):\n\n    int64_t start_key = 0;\n    int64_t end_key = no_actors - 1;\n    snode_t* start_row = NULL, * end_row = NULL;\n\n    return (db_range_search((WORD*) &start_key, (WORD*) &end_key, &start_row, &end_row, (WORD) 0, db) == no_actors);\n}\n\nint test_range_search_pk_copy(db_t * db)\n{\n    // TO DO: Improve (check returned keys):\n\n    int64_t start_key = 0;\n    int64_t end_key = no_actors - 1;\n    db_row_t* rows = NULL;\n\n    return (db_range_search_copy((WORD*) &start_key, (WORD*) &end_key, &rows, (WORD) 0, db) == no_actors);\n}\n\n// Range search by (PK, CK1):\n\nint test_range_search_pk_ck1(db_t * db)\n{\n    // TO DO: Improve (check returned keys):\n\n    int64_t pk = 0;\n    int64_t start_key = 0;\n    int64_t end_key = no_collections - 1;\n    snode_t* start_row = NULL, * end_row = NULL;\n\n    int no_entries = db_range_search_clustering((WORD*) &pk,(WORD*) &start_key, (WORD*) &end_key, 1, &start_row, &end_row, (WORD) 0, db);\n\n    if(no_entries != no_collections)\n    {\n        printf(\"ERROR: db_range_search_clustering(%\" PRId64 \", %\" PRId64 \"-%\" PRId64 \") returned %d entries!\\n\", pk, start_key, end_key, no_entries);\n        print_long_db(db);\n        assert(0);\n        return 1;\n    }\n\n    return 0;\n}\n\n// Range search by (PK, CK1, CK2):\n\nint test_range_search_pk_ck1_ck2(db_t * db)\n{\n    // TO DO: Improve (check returned keys):\n\n    int64_t pk = 0;\n    int64_t start_keys[2];\n    start_keys[0] = 0;\n    start_keys[1] = 0;\n\n    int64_t end_keys[2];\n    end_keys[0] = 0;\n    end_keys[1] = no_items - 1;\n\n    snode_t* start_row = NULL, * end_row = NULL;\n\n    int no_entries = db_range_search_clustering((WORD*) &pk,(WORD*) start_keys, (WORD*) end_keys, 2, &start_row, &end_row, (WORD) 0, db);\n\n    if(no_entries != no_items)\n    {\n        printf(\"ERROR: db_range_search_clustering(%\" PRId64 \", %\" PRId64 \", %\" PRId64 \"-%\" PRId64 \") returned %d entries!\\n\", pk, start_keys[0], end_keys[0], end_keys[1], no_entries);\n        print_long_db(db);\n        assert(0);\n        return 1;\n    }\n\n    return 0;\n}\n\n// Range search by secondary index:\n\nint test_range_search_index(db_t * db)\n{\n    // TO DO: Improve (check returned keys):\n\n    int64_t start_key = 1;\n    int64_t end_key = no_items;\n    snode_t* start_row = NULL, * end_row = NULL;\n\n    return (db_range_search_index(0, (WORD) start_key, (WORD) end_key, &start_row, &end_row, (WORD) 0, db) == (no_items - 1));\n}\n\n\nint main(int argc, char **argv) {\n    unsigned int seed;\n    int ret = 0;\n\n    GET_RANDSEED(&seed, 0); // thread_id\n\n    // Get db pointer:\n\n    db_t * db = get_db();\n\n    // Create schema:\n\n    ret = create_schema(db, &seed);\n    printf(\"Test %s - %s\\n\", \"create_schema\", ret==0?\"OK\":\"FAILED\");\n\n    // Populate DB:\n\n    ret = populate_db(db, &seed);\n    printf(\"Test %s - %s\\n\", \"populate_db\", ret==0?\"OK\":\"FAILED\");\n\n    // Read by (PK):\n\n    ret = test_search_pk(db);\n    printf(\"Test %s - %s\\n\", \"test_search_pk\", ret==0?\"OK\":\"FAILED\");\n\n    // Read by (PK, CK1):\n\n    ret = test_search_pk_ck1(db);\n    printf(\"Test %s - %s\\n\", \"test_search_pk_ck1\", ret==0?\"OK\":\"FAILED\");\n\n    // Read by (PK, CK1, CK2):\n\n    ret = test_search_pk_ck1_ck2(db);\n    printf(\"Test %s - %s\\n\", \"test_search_pk_ck1_ck2\", ret==0?\"OK\":\"FAILED\");\n\n    // Read by (PK, CK1, CK2, Column):\n    ret = test_search_column(db);\n    printf(\"Test %s - %s\\n\", \"test_search_column\", ret==0?\"OK\":\"FAILED\");\n\n    // Read by secondary index:\n\n    ret = test_search_index(db);\n    printf(\"Test %s - %s\\n\", \"test_search_index\", ret==0?\"OK\":\"FAILED\");\n\n    // Update by (PK, CK1, CK2, Column):\n\n    ret = test_update(db);\n    printf(\"Test %s - %s\\n\", \"test_update\", ret==0?\"OK\":\"FAILED\");\n\n\n    // Delete by (PK, CK1, CK2, Column):\n\n    ret = test_delete_col(db);\n    printf(\"Test %s - %s\\n\", \"test_delete_col\", ret==0?\"OK\":\"FAILED\");\n\n    // Delete by (PK, CK1, CK2):\n\n    ret = test_delete_pk_ck1_ck2(db);\n    printf(\"Test %s - %s\\n\", \"test_delete_pk_ck1_ck2\", ret==0?\"OK\":\"FAILED\");\n\n    // Delete by (PK, CK1):\n\n    ret = test_delete_pk_ck1(db);\n    printf(\"Test %s - %s\\n\", \"test_delete_pk_ck1\", ret==0?\"OK\":\"FAILED\");\n\n    // Delete by (PK):\n\n    ret = test_delete_pk(db, &seed);\n    printf(\"Test %s - %s\\n\", \"test_delete_pk\", ret==0?\"OK\":\"FAILED\");\n\n    ret = populate_db(db, &seed);\n    printf(\"Test %s - %s\\n\", \"repopulate_db\", ret==0?\"OK\":\"FAILED\");\n\n    // Delete by secondary index:\n\n//  ret = test_delete_index(db);\n//  printf(\"Test %s - %s\\n\", \"\", ret==0?\"OK\":\"FAILED\");\n\n//  ret = populate_db(db, &seed);\n\n    // Range search by PK:\n\n    ret = test_range_search_pk(db);\n    printf(\"Test %s - %s\\n\", \"test_delete_index\", ret==0?\"OK\":\"FAILED\");\n\n    // Range search by PK (copy):\n\n    ret = test_range_search_pk_copy(db);\n    printf(\"Test %s - %s\\n\", \"test_range_search_pk_copy\", ret==0?\"OK\":\"FAILED\");\n\n    // Range search by (PK, CK1):\n\n    ret = test_range_search_pk_ck1(db);\n    printf(\"Test %s - %s\\n\", \"test_range_search_pk_ck1\", ret==0?\"OK\":\"FAILED\");\n\n    // Range search by (PK, CK1, CK2):\n\n    ret = test_range_search_pk_ck1_ck2(db);\n    printf(\"Test %s - %s\\n\", \"test_range_search_pk_ck1_ck2\", ret==0?\"OK\":\"FAILED\");\n\n    // Range search by secondary index:\n\n    ret = test_range_search_index(db);\n    printf(\"Test %s - %s\\n\", \"test_range_search_index\", ret==0?\"OK\":\"FAILED\");\n\n    return 0;\n}\n\n\n\n\n"
  },
  {
    "path": "backend/test/queue_unit_tests.c",
    "content": "/*\n * Copyright (C) 2019-2021 Deutsche Telekom AG\n *\n * Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:\n *\n * 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.\n *\n * 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.\n *\n * 3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission.\n *\n * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS \"AS IS\" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n */\n\n#include <stdio.h>\n#include <stdlib.h>\n#include <pthread.h>\n#include <assert.h>\n#include <pthread.h>\n#include <unistd.h>\n#include <string.h>\n#include <time.h>\n\n#include \"queue.h\"\n\nint no_cols = 2;\nint no_items = 10;\nWORD table_key = (WORD) 0;\nWORD queue_id = (WORD) 0;\n\ntypedef struct actor_collection_item {\n    int item_id;\n    int item_value;\n} actor_collection_item_t;\n\ntypedef struct producer_args\n{\n    db_t * db;\n    WORD table_key;\n    WORD queue_id;\n    int no_enqueues;\n\n    int successful_enqueues;\n    int status;\n} producer_args;\n\ntypedef struct consumer_args\n{\n    db_t * db;\n    WORD table_key;\n    WORD queue_id;\n    int no_enqueues;\n\n    WORD consumer_id;\n    WORD shard_id;\n    WORD app_id;\n\n    int successful_dequeues;\n    int successful_consumes;\n    int successful_replays;\n\n    int64_t read_head;\n    int64_t read_head_after_replay;\n\n    int status;\n} consumer_args;\n\n\n// Enqueue test:\n\nint do_enqueues(db_t * db, WORD table_id, WORD queue_id, int no_enqueues, int rand_sleep, int * successful_enqueues, unsigned int * fastrandstate) {\n    unsigned int randno;\n\n    for(int64_t iid=0;iid<no_enqueues;iid++)\n    {\n        WORD * column_values = (WORD *) malloc(no_cols * sizeof(WORD));\n\n        column_values[0] = (WORD) iid;\n        column_values[1] = (WORD) iid + 1;\n\n        int ret = enqueue(column_values, no_cols, 0, table_id, queue_id, 1, db, fastrandstate);\n        if(ret != 0)\n            return ret;\n\n        (*successful_enqueues)++;\n\n        if(rand_sleep)\n        {\n            FASTRAND(fastrandstate, randno);\n            sleep((randno % 10) * 0.2);\n        }\n    }\n\n    return 0;\n}\n\nvoid * producer(void * pargs)\n{\n    unsigned int seed;\n    int ret = 0;\n\n    producer_args * pa = (producer_args *) pargs;\n\n    GET_RANDSEED(&seed, 0); // thread_id\n\n    ret = do_enqueues(pa->db, pa->table_key, pa->queue_id, pa->no_enqueues, 1, &(pa->successful_enqueues), &seed);\n\n    pa->status = ret;\n\n    return (void *) pa->status;\n}\n\nvoid consumer_callback(queue_callback_args * qca)\n{\n    printf(\"Consumer %\" PRId64 \"/%\" PRId64 \"/%\" PRId64 \" received notification for queue %\" PRId64 \"/%\" PRId64 \", status %d\\n\",\n            (int64_t) qca->app_id, (int64_t) qca->shard_id, (int64_t) qca->consumer_id,\n            (int64_t) qca->table_key, (int64_t) qca->queue_id,\n            qca->status);\n}\n\nint read_queue_while_not_empty(consumer_args * ca, int * entries_read)\n{\n    snode_t * start_row, * end_row;\n    int read_status = QUEUE_STATUS_READ_INCOMPLETE;\n    vector_clock * prh_version;\n\n    while(read_status != QUEUE_STATUS_READ_COMPLETE)\n    {\n        read_status = read_queue(ca->consumer_id, ca->shard_id, ca->app_id,\n                        ca->table_key, ca->queue_id,\n                        2, entries_read, &ca->read_head, &prh_version,\n                        &start_row, &end_row, 1, ca->db);\n\n        if(read_status < 0)\n        {\n            printf(\"ERROR: read_queue returned %d\\n\", read_status);\n            return read_status;\n        }\n        else\n        {\n            assert(read_status == QUEUE_STATUS_READ_COMPLETE || read_status == QUEUE_STATUS_READ_INCOMPLETE);\n\n            ca->successful_dequeues += (*entries_read);\n\n            if((*entries_read) > 0)\n            {\n                printf(\"CONSUMER %\" PRId64 \": successful_dequeues=%d, last_entry_id=%\" PRId64 \"\\n\",\n                        (int64_t) ca->consumer_id, ca->successful_dequeues, (int64_t) end_row->key);\n\n                if(((int64_t) end_row->key) != ca->successful_dequeues - 1)\n                    printf(\"Test %s - FAILED (%\" PRId64 \" != %d)\\n\", \"last_entry_id\", (int64_t) end_row->key, ca->successful_dequeues - 1);\n            }\n        }\n    }\n\n    return read_status;\n}\n\nvoid * consumer(void * cargs)\n{\n    unsigned int seed;\n    int ret = 0;\n    snode_t * start_row, * end_row;\n\n    consumer_args * ca = (consumer_args *) cargs;\n\n    pthread_cond_t signal = PTHREAD_COND_INITIALIZER;\n    pthread_mutex_t lock = PTHREAD_MUTEX_INITIALIZER;\n\n    GET_RANDSEED(&seed, 0); // thread_id\n\n    queue_callback qc;\n    qc.lock = &lock;\n    qc.signal = &signal;\n    qc.callback = consumer_callback;\n\n    int64_t prev_read_head = -1, prev_consume_head = -1;\n    ret = subscribe_queue(ca->consumer_id, ca->shard_id, ca->app_id, ca->table_key, ca->queue_id, &qc,\n                            &prev_read_head, &prev_consume_head, 1, ca->db, &seed);\n    printf(\"Test %s - %s (%d)\\n\", \"subscribe_queue\", ret==0?\"OK\":\"FAILED\", ret);\n    if(ret)\n        return NULL;\n\n    int entries_read = (int) prev_read_head + 1;\n\n    int read_status = read_queue_while_not_empty(ca, &entries_read);\n    if(read_status < 0)\n    {\n        return (void *) read_status;\n    }\n\n    // Add app-specific message processing work here\n\n    ret = consume_queue(ca->consumer_id, ca->shard_id, ca->app_id,\n                        ca->table_key, ca->queue_id,\n                        (int64_t) ca->read_head, ca->db);\n\n    if(ret < 0 && ret != DB_ERR_QUEUE_COMPLETE)\n        printf(\"ERROR: consume_queue returned %d\\n\", ret);\n    else\n        ca->successful_consumes = ca->successful_dequeues;\n\n    printf(\"CONSUMER %\" PRId64 \": successful_dequeues=%d, successful_consumes=%d\\n\",\n            (int64_t) ca->consumer_id, ca->successful_dequeues, ca->successful_consumes);\n\n    while(ca->successful_consumes < ca->no_enqueues)\n    {\n        pthread_mutex_lock(&lock);\n        struct timespec ts;\n        clock_gettime(CLOCK_REALTIME, &ts);\n        ts.tv_sec += 3;\n        pthread_cond_timedwait(&signal, &lock, &ts);\n        // Received queue notification, reading:\n\n        read_status = read_queue_while_not_empty(ca, &entries_read);\n        if(read_status < 0)\n        {\n            return (void *) read_status;\n        }\n\n        // Add app-specific message processing work here\n\n        ret = consume_queue(ca->consumer_id, ca->shard_id, ca->app_id,\n                            ca->table_key, ca->queue_id,\n                            (int64_t) ca->read_head, ca->db);\n\n        if(ret < 0 && ret != DB_ERR_QUEUE_COMPLETE)\n            printf(\"ERROR: consume_queue returned %d\\n\", ret);\n        else\n            ca->successful_consumes = ca->successful_dequeues;\n\n        printf(\"CONSUMER %\" PRId64 \": successful_dequeues=%d, successful_consumes=%d\\n\",\n                (int64_t) ca->consumer_id, ca->successful_dequeues, ca->successful_consumes);\n\n        pthread_mutex_unlock(&lock);\n    }\n\n    ret = unsubscribe_queue(ca->consumer_id, ca->shard_id, ca->app_id, ca->table_key, ca->queue_id, 1, ca->db);\n    printf(\"Test %s - %s (%d)\\n\", \"unsubscribe_queue\", ret==0?\"OK\":\"FAILED\", ret);\n\n    return (void *) ret;\n}\n\nvoid * consumer_replay(void * cargs)\n{\n    unsigned int seed;\n    int ret = 0;\n    snode_t * start_row, * end_row;\n\n    consumer_args * ca = (consumer_args *) cargs;\n\n    pthread_cond_t signal = PTHREAD_COND_INITIALIZER;\n    pthread_mutex_t lock = PTHREAD_MUTEX_INITIALIZER;\n\n    GET_RANDSEED(&seed, 0); // thread_id\n\n    queue_callback qc;\n    qc.lock = &lock;\n    qc.signal = &signal;\n    qc.callback = consumer_callback;\n\n    int64_t prev_read_head = -1, prev_consume_head = -1;\n    ret = subscribe_queue(ca->consumer_id, ca->shard_id, ca->app_id, ca->table_key, ca->queue_id, &qc,\n                            &prev_read_head, &prev_consume_head, 1, ca->db, &seed);\n\n    int entries_read = (int) prev_read_head + 1;\n\n    int read_status = read_queue_while_not_empty(ca, &entries_read);\n    if(read_status < 0)\n    {\n        return (void *) read_status;\n    }\n\n    while(ca->successful_dequeues < ca->no_enqueues)\n    {\n        pthread_mutex_lock(&lock);\n        struct timespec ts;\n        clock_gettime(CLOCK_REALTIME, &ts);\n        ts.tv_sec += 3;\n        pthread_cond_timedwait(&signal, &lock, &ts);\n\n        // Received queue notification, reading:\n\n        read_status = read_queue_while_not_empty(ca, &entries_read);\n        if(read_status < 0)\n        {\n            return (void *) read_status;\n        }\n\n        pthread_mutex_unlock(&lock);\n    }\n\n    ret = replay_queue(ca->consumer_id, ca->shard_id, ca->app_id,\n            ca->table_key, ca->queue_id,\n            0, ca->successful_dequeues,\n            &ca->successful_replays, &ca->read_head_after_replay,\n            &start_row, &end_row, ca->db);\n\n    assert(ret == QUEUE_STATUS_READ_COMPLETE);\n\n    ret = unsubscribe_queue(ca->consumer_id, ca->shard_id, ca->app_id, ca->table_key, ca->queue_id, 1, ca->db);\n    printf(\"Test %s - %s (%d)\\n\", \"unsubscribe_queue\", ret==0?\"OK\":\"FAILED\", ret);\n\n    return (void *) ret;\n}\n\n\nint main(int argc, char **argv) {\n    unsigned int seed;\n    int ret = 0;\n\n    GET_RANDSEED(&seed, 0); // thread_id\n\n    // Get db pointer:\n\n    db_t * db = get_db();\n\n    // Create queue table:\n\n    int * col_types = (int *) malloc(no_cols * sizeof(int));\n    for(int i=0;i<no_cols;i++)\n        col_types[i] = DB_TYPE_INT64;\n\n    ret = create_queue_table(table_key, no_cols, col_types, db,  &seed);\n    printf(\"Test %s - %s (%d)\\n\", \"create_queue_table\", ret==0?\"OK\":\"FAILED\", ret);\n\n    // Create queue:\n\n    ret = create_queue(table_key, queue_id, NULL, 1, db, &seed);\n    printf(\"Test %s - %s (%d)\\n\", \"create_queue\", ret==0?\"OK\":\"FAILED\", ret);\n\n    // Create and run producer and consumer threads (also test subscribe / unsubscribe):\n\n    pthread_t producer_t, consumer_t, consumer2_t;\n\n    producer_args pargs;\n    memset(&pargs, 0, sizeof(producer_args));\n    pargs.db = db;\n    pargs.table_key = table_key;\n    pargs.queue_id = queue_id;\n    pargs.no_enqueues = no_items;\n\n    consumer_args cargs;\n    memset(&cargs, 0, sizeof(consumer_args));\n    cargs.db = db;\n    cargs.table_key = table_key;\n    cargs.queue_id = queue_id;\n    cargs.no_enqueues = no_items;\n    cargs.app_id = (WORD) 0;\n    cargs.shard_id = (WORD) 0;\n    cargs.consumer_id = (WORD) 0;\n\n    consumer_args cargs_replay;\n    memset(&cargs_replay, 0, sizeof(consumer_args));\n    cargs_replay.db = db;\n    cargs_replay.table_key = table_key;\n    cargs_replay.queue_id = queue_id;\n    cargs_replay.no_enqueues = no_items;\n    cargs_replay.app_id = (WORD) 0;\n    cargs_replay.shard_id = (WORD) 0;\n    cargs_replay.consumer_id = (WORD) 1;\n\n    ret = pthread_create(&producer_t, NULL, producer, &pargs);\n    printf(\"Test %s - %s (%d)\\n\", \"create_producer_thread\", ret==0?\"OK\":\"FAILED\", ret);\n    if(ret)\n        return -1;\n\n    ret = pthread_create(&consumer_t, NULL, consumer, &cargs);\n    printf(\"Test %s - %s (%d)\\n\", \"create_consumer_thread\", ret==0?\"OK\":\"FAILED\", ret);\n    if(ret)\n        return -1;\n\n    ret = pthread_create(&consumer2_t, NULL, consumer_replay, &cargs_replay);\n    printf(\"Test %s - %s (%d)\\n\", \"create_consumer_replay_thread\", ret==0?\"OK\":\"FAILED\", ret);\n    if(ret)\n        return -1;\n\n    ret = pthread_join(producer_t, NULL);\n    printf(\"Test %s - %s (%d)\\n\", \"join_producer_thread\", ret==0?\"OK\":\"FAILED\", ret);\n    if(ret)\n        return -2;\n\n    ret = pthread_join(consumer_t, NULL);\n    printf(\"Test %s - %s (%d)\\n\", \"join_consumer_thread\", ret==0?\"OK\":\"FAILED\", ret);\n    if(ret)\n        return -2;\n\n    ret = pthread_join(consumer2_t, NULL);\n    printf(\"Test %s - %s (%d)\\n\", \"join_consumer_replay_thread\", ret==0?\"OK\":\"FAILED\", ret);\n    if(ret)\n        return -2;\n\n    // Test enqueues:\n    printf(\"Test %s - %s (%d)\\n\", \"enqueue\", pargs.successful_enqueues==pargs.no_enqueues?\"OK\":\"FAILED\", ret);\n\n    // Test dequeues:\n    printf(\"Test %s - %s (%d)\\n\", \"dequeue\", cargs.successful_dequeues==cargs.no_enqueues?\"OK\":\"FAILED\", ret);\n\n    // Test read head sanity:\n    printf(\"Test %s - %s (%d)\\n\", \"read_head\", ((int) cargs.read_head)==(cargs.no_enqueues - 1)?\"OK\":\"FAILED\", ret);\n\n    // Test consumes:\n    printf(\"Test %s - %s (%d)\\n\", \"consume\", cargs.successful_consumes==cargs.no_enqueues?\"OK\":\"FAILED\", ret);\n\n\n    // Test dequeues on C2:\n    printf(\"Test %s - %s (%d)\\n\", \"dequeue\", cargs_replay.successful_dequeues==cargs_replay.no_enqueues?\"OK\":\"FAILED\", ret);\n\n    // Test read head sanity on C2:\n    printf(\"Test %s - %s (%d)\\n\", \"read_head\", ((int) cargs_replay.read_head)==(cargs_replay.no_enqueues - 1)?\"OK\":\"FAILED\", ret);\n\n    // Test replays on C2:\n    printf(\"Test %s - %s (%d)\\n\", \"replay\", cargs_replay.successful_replays==cargs_replay.no_enqueues?\"OK\":\"FAILED\", ret);\n\n    // Test read head sanity after replay on C2:\n    printf(\"Test %s - %s (%d)\\n\", \"read_head_replay\", ((int) cargs_replay.read_head_after_replay)==(cargs_replay.no_enqueues - 1)?\"OK\":\"FAILED\", ret);\n\n    // Test delete queue:\n\n    ret = delete_queue(table_key, queue_id, NULL, 1, db, &seed);\n    printf(\"Test %s - %s (%d)\\n\", \"delete_queue\", ret==0?\"OK\":\"FAILED\", ret);\n\n    return 0;\n}\n\n\n\n\n"
  },
  {
    "path": "backend/test/skiplist_test.c",
    "content": "/*\n * Copyright (C) 2019-2021 Deutsche Telekom AG\n *\n * Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:\n *\n * 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.\n *\n * 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.\n *\n * 3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission.\n *\n * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS \"AS IS\" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n */\n\n/*\n * skiplist_test.c\n *\n */\n\n#include \"skiplist.h\"\n#include <stdio.h>\n\nint main() {\n    int arr[] = { 1, 3, 3, 6, 9, 9, 2, 11, 11, 1, 4, 4 }, i;\n    skiplist_t * list;\n    unsigned int randno;\n\n    list = create_skiplist_long();\n\n    printf(\"Insert:--------------------\\n\");\n    for (i = 0; i < sizeof(arr) / sizeof(arr[0]); i++) {\n        skiplist_insert(list, (WORD) arr[i], (WORD) arr[i], &randno);\n        skiplist_dump(list);\n    }\n//    skiplist_dump(list);\n\n    printf(\"Search:--------------------\\n\");\n    int keys[] = { 3, 4, 7, 10, 111 };\n\n    for (i = 0; i < sizeof(keys) / sizeof(keys[0]); i++) {\n        snode_t *x = skiplist_search(list, (WORD) keys[i]);\n        if (x) {\n            printf(\"key = %d, value = %d\\n\", keys[i], (int) x->value);\n        } else {\n            printf(\"key = %d, not found\\n\", keys[i]);\n        }\n    }\n\n    printf(\"Search:--------------------\\n\");\n    skiplist_delete(list, (WORD) 3);\n    skiplist_dump(list);\n    skiplist_delete(list, (WORD) 9);\n    skiplist_dump(list);\n    skiplist_delete(list, (WORD) 11);\n    skiplist_dump(list);\n    skiplist_delete(list, (WORD) 11);\n    skiplist_dump(list);\n    skiplist_delete(list, (WORD) 11);\n    skiplist_dump(list);\n    skiplist_delete(list, (WORD) 1);\n    skiplist_dump(list);\n    skiplist_delete(list, (WORD) 6);\n    skiplist_dump(list);\n    skiplist_delete(list, (WORD) 2);\n    skiplist_dump(list);\n    skiplist_delete(list, (WORD) 4);\n    skiplist_dump(list);\n    skiplist_free(list);\n\n    return 0;\n}\n\n\n\n"
  },
  {
    "path": "backend/test/test_client.c",
    "content": "/*\n * Copyright (C) 2019-2021 Deutsche Telekom AG\n *\n * Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:\n *\n * 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.\n *\n * 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.\n *\n * 3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission.\n *\n * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS \"AS IS\" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n */\n\n/*\n * client.c\n *\n *      Author: aagapi\n */\n\n\n\n#include <stdio.h>\n#include <stdlib.h>\n#include <string.h>\n#include <unistd.h>\n#include <sys/types.h>\n#include <sys/socket.h>\n#include <netinet/in.h>\n#include <netdb.h>\n#include <uuid/uuid.h>\n\n#include \"client_api.h\"\n#include \"fastrand.h\"\n\ntypedef struct actor_collection_item {\n    int actor_id;\n    int collection_id;\n    int item_id;\n    int item_value;\n} actor_collection_item_t;\n\nint no_cols = 4;\nint no_primary_keys = 1;\nint no_clustering_keys = 2;\nint no_index_keys = 1;\n\nint no_queue_cols = 2;\nint no_enqueues = 5;\n\nint no_actors = 2;\nint no_collections = 2;\nint no_items = 2;\n\nint minority_status = 0;\n\n\ndb_schema_t * create_schema() {\n    int primary_key_idx = 0;\n    int clustering_key_idxs[2];\n    clustering_key_idxs[0]=1;\n    clustering_key_idxs[1]=2;\n    int index_key_idx=3;\n\n    int * col_types = (int *) malloc(no_cols * sizeof(int));\n\n    for(int i=0;i<no_cols;i++)\n        col_types[i] = DB_TYPE_INT32;\n\n    db_schema_t* db_schema = db_create_schema(col_types, no_cols, &primary_key_idx, no_primary_keys, clustering_key_idxs, no_clustering_keys, &index_key_idx, no_index_keys);\n\n    assert(db_schema != NULL && \"Schema creation failed\");\n\n    return db_schema;\n}\n\n// Tests:\n\nint populate_db(db_schema_t * schema, remote_db_t * db, uuid_t * txnid, unsigned int * fastrandstate)\n{\n    printf(\"TEST: populate_db\\n\");\n\n    WORD * column_values = (WORD *) malloc(no_cols * sizeof(WORD));\n\n    for(int64_t aid=0;aid<no_actors;aid++)\n    {\n        for(int64_t cid=0;cid<no_collections;cid++)\n        {\n            for(int64_t iid=0;iid<no_items;iid++)\n            {\n                column_values[0] = (WORD) aid;\n                column_values[1] = (WORD) cid;\n                column_values[2] = (WORD) iid;\n                column_values[3] = (WORD) iid + 1;\n\n                if(remote_insert_in_txn(column_values, no_cols, schema->no_primary_keys, schema->min_no_clustering_keys, NULL, 0, (WORD) 0, &minority_status, txnid, db) != 0)\n                    return -1;\n            }\n        }\n    }\n\n    return 0;\n}\n\nint delete_test(db_schema_t * schema, remote_db_t * db, uuid_t * txnid, unsigned int * fastrandstate)\n// Deletes row for last actor\n{\n    printf(\"TEST: delete_test\\n\");\n\n    WORD row_key = (WORD) no_actors - 1;\n    return remote_delete_row_in_txn(&row_key, schema->no_primary_keys, (WORD) 0, &minority_status, txnid, db);\n}\n\nint delete_all(db_schema_t * schema, remote_db_t * db, uuid_t * txnid, unsigned int * fastrandstate)\n// Deletes row for last actor\n{\n    printf(\"TEST: delete_test\\n\");\n\n    int ret = 0;\n    for(int64_t aid = 0; aid<no_actors; aid++)\n        ret |= remote_delete_row_in_txn((WORD *) &aid, schema->no_primary_keys, (WORD) 0, &minority_status, txnid, db);\n\n    return ret;\n}\n\nint test_search_pk(db_schema_t * schema, remote_db_t * db, uuid_t * txnid, unsigned int * fastrandstate)\n{\n    printf(\"TEST: test_search_pk\\n\");\n\n    char print_buff[1024];\n\n    for(int64_t aid=0;aid<no_actors;aid++)\n    {\n        db_row_t * row = NULL;\n        remote_search_in_txn((WORD *) &aid, schema->no_primary_keys, &row, (WORD) 0, &minority_status, txnid, db);\n\n        if(txnid != NULL && row == NULL)\n            continue;\n\n        print_long_row(row);\n\n        if(row == NULL)\n        {\n            printf(\"Read back wrong NULL row for cell (%\" PRId64 \")!\\n\", aid);\n            return -1;\n        }\n\n        if((int64_t) row->key != aid)\n        {\n            printf(\"Read back mismatched pk %\" PRId64 \" ( != %\" PRId64 \") in cell!\\n\", (int64_t) row->key, aid);\n            return -1;\n        }\n    }\n\n    return 0;\n}\n\nint test_search_pk_ck1(db_schema_t * schema, remote_db_t * db, uuid_t * txnid, unsigned int * fastrandstate)\n{\n    printf(\"TEST: test_search_pk_ck1\\n\");\n\n    char print_buff[1024];\n\n    for(int64_t aid=0;aid<no_actors;aid++)\n    {\n        for(int64_t cid=0;cid<no_collections;cid++)\n        {\n            db_row_t * row = NULL;\n\n            remote_search_clustering_in_txn((WORD *) &aid, schema->no_primary_keys, (WORD *) &cid, 1, &row, (WORD) 0, &minority_status, txnid, db);\n\n            if(txnid != NULL && row == NULL)\n                continue;\n\n            print_long_row(row);\n\n            if(row == NULL)\n            {\n                printf(\"Read back wrong NULL row for cell (%\" PRId64 \", %\" PRId64 \")!\\n\", aid, cid);\n                return -1;\n            }\n\n            if((int64_t) row->key != cid)\n            {\n                printf(\"Read back mismatched ck1 %\" PRId64 \" ( != %\" PRId64 \") in cell (%\" PRId64 \", %\" PRId64 \")!\\n\", (int64_t) row->key, cid, aid, cid);\n                return -1;\n            }\n        }\n    }\n\n    return 0;\n}\n\nint test_search_pk_ck1_ck2(db_schema_t * schema, remote_db_t * db, uuid_t * txnid, unsigned int * fastrandstate)\n{\n    printf(\"TEST: test_search_pk_ck1_ck2\\n\");\n\n    char print_buff[1024];\n    WORD * cks = (WORD *) malloc(2 * sizeof(WORD));\n\n    for(int64_t aid=0;aid<no_actors;aid++)\n    {\n        for(int64_t cid=0;cid<no_collections;cid++)\n        {\n            for(int64_t iid=0;iid<no_items;iid++)\n            {\n                cks[0] = (WORD) cid;\n                cks[1] = (WORD) iid;\n\n                db_row_t * row = NULL;\n\n                remote_search_clustering_in_txn((WORD *) &aid, schema->no_primary_keys, cks, 2, &row, (WORD) 0, &minority_status, txnid, db);\n\n                if(txnid != NULL && row == NULL)\n                    continue;\n\n                print_long_row(row);\n\n                if((int64_t) row->key != iid)\n                {\n                    printf(\"Read back mismatched ck1 %\" PRId64 \" ( != %\" PRId64 \") in cell (%\" PRId64 \", %\" PRId64 \", %\" PRId64 \")!\\n\", (int64_t) row->key, iid, aid, cid, iid);\n                    return -1;\n                }\n            }\n        }\n    }\n\n    return 0;\n}\n\n// Queue tests:\n\nvoid consumer_callback(queue_callback_args * qca)\n{\n    printf(\"Consumer %\" PRId64 \"/%\" PRId64 \"/%\" PRId64 \" received notification for queue %\" PRId64 \"/%\" PRId64 \", status %d\\n\",\n            (int64_t) qca->app_id, (int64_t) qca->shard_id, (int64_t) qca->consumer_id,\n            (int64_t) qca->table_key, (int64_t) qca->queue_id,\n            qca->status);\n}\n\n\nint test_create_queue(remote_db_t * db, uuid_t * txnid)\n// Creates 2 queues\n{\n    printf(\"TEST: create_queue\\n\");\n\n    int ret = remote_create_queue_in_txn((WORD) 1, (WORD) 1, &minority_status, txnid, db);\n    ret |= remote_create_queue_in_txn((WORD) 1, (WORD) 2, &minority_status, txnid, db);\n\n    return ret;\n}\n\nint test_delete_queue(remote_db_t * db, uuid_t * txnid)\n{\n    printf(\"TEST: delete_queue\\n\");\n\n    int ret = remote_delete_queue_in_txn((WORD) 1, (WORD) 1, &minority_status, txnid, db);\n    ret |= remote_delete_queue_in_txn((WORD) 1, (WORD) 2, &minority_status, txnid, db);\n\n    return ret;\n}\n\nint test_subscribe_queue(remote_db_t * db, WORD consumer_id, WORD queue_id)\n{\n    printf(\"TEST: subscribe_queue\\n\");\n    int64_t prev_read_head = -1, prev_consume_head = -1;\n    queue_callback * qc = get_queue_callback(consumer_callback);\n\n    return remote_subscribe_queue(consumer_id, (WORD) 1, (WORD) 2, (WORD) 1, queue_id, qc, &prev_read_head, &prev_consume_head, &minority_status, db); // &txnid\n}\n\nint test_unsubscribe_queue(remote_db_t * db, WORD consumer_id, WORD queue_id)\n{\n    printf(\"TEST: unsubscribe_queue\\n\");\n    return remote_unsubscribe_queue(consumer_id, (WORD) 1, (WORD) 2, (WORD) 1, queue_id, &minority_status, db); // &txnid\n}\n\nint test_enqueue(remote_db_t * db, WORD queue_id, uuid_t * txnid)\n{\n    printf(\"TEST: enqueue\\n\");\n\n    WORD * column_values = (WORD *) malloc(no_queue_cols * sizeof(WORD));\n\n    for(int64_t i=0;i<no_enqueues;i++)\n    {\n        column_values[0] = (WORD) i;\n        column_values[1] = (WORD) i + 1;\n\n        if(remote_enqueue_in_txn(column_values, no_queue_cols, NULL, 0, (WORD) 1, queue_id, &minority_status, txnid, db) != 0)\n            return -1;\n    }\n\n    return 0;\n}\n\nint test_read_queue(remote_db_t * db, WORD consumer_id, WORD queue_id, uuid_t * txnid)\n{\n    printf(\"TEST: read_queue\\n\");\n    int max_entries = no_enqueues;\n    int entries_read;\n    int64_t new_read_head;\n    snode_t* start_row, * end_row;\n    int ret = remote_read_queue_in_txn(consumer_id, (WORD) 1, (WORD) 2, (WORD) 1, queue_id,\n                                    max_entries, &entries_read, &new_read_head,\n                                    &start_row, &end_row, &minority_status, txnid, db);\n\n    assert(ret == QUEUE_STATUS_READ_COMPLETE);\n    assert(entries_read == no_enqueues);\n    assert(new_read_head == no_enqueues - 1);\n    assert(end_row->key - start_row->key == (entries_read - 1));\n\n    return ret;\n}\n\nint test_consume_queue(remote_db_t * db, WORD consumer_id, WORD queue_id, uuid_t * txnid)\n{\n    printf(\"TEST: consume_queue\\n\");\n    return remote_consume_queue_in_txn(consumer_id, (WORD) 1, (WORD) 2, (WORD) 1, queue_id, no_enqueues - 1, &minority_status, txnid, db); // &txnid\n}\n\nint test_txn(remote_db_t * db, db_schema_t * schema, unsigned * fastrandstate)\n{\n    printf(\"TEST: txn\\n\");\n\n    int node_ids[] = {0,1};\n    int64_t counters[] = {0,0};\n\n    vector_clock * vc = init_vc(2, node_ids, counters, 0), * vc_r = NULL;\n    add_component_vc(vc, 2, 0);\n    increment_vc(vc, 0);\n    increment_vc(vc, 0);\n    increment_vc(vc, 1);\n    increment_vc(vc, 2);\n    increment_vc(vc, 2);\n\n    update_vc(db->my_lc, vc);\n\n    uuid_t * txnid = remote_new_txn(db);\n\n    assert(txnid != NULL);\n\n    int status = populate_db(schema, db, txnid, fastrandstate);\n    printf(\"Test %s - %s (%d)\\n\", \"populate_db_txn\", status==0?\"OK\":\"FAILED\", status);\n\n    status = test_search_pk_ck1_ck2(schema, db, txnid, fastrandstate);\n    printf(\"Test %s - %s (%d)\\n\", \"test_search_pk_ck1_ck2_txn\", status==0?\"OK\":\"FAILED\", status);\n\n    status = test_search_pk_ck1(schema, db, txnid, fastrandstate);\n    printf(\"Test %s - %s (%d)\\n\", \"test_search_pk_ck1_txn\", status==0?\"OK\":\"FAILED\", status);\n\n    status = test_search_pk(schema, db, txnid, fastrandstate);\n    printf(\"Test %s - %s (%d)\\n\", \"test_search_pk_txn\", status==0?\"OK\":\"FAILED\", status);\n\n    status = test_enqueue(db, (WORD) 2, txnid);\n    printf(\"Test %s - %s (%d)\\n\", \"enqueue_txn\", status==0?\"OK\":\"FAILED\", status);\n\n    status = test_subscribe_queue(db, (WORD) 1, (WORD) 1);\n    printf(\"Test %s - %s (%d)\\n\", \"subscribe_queue_txn\", status==0?\"OK\":\"FAILED\", status);\n\n    status = test_read_queue(db, (WORD) 1, (WORD) 1, txnid);\n    printf(\"Test %s - %s (%d)\\n\", \"read_queue_txn\", status==QUEUE_STATUS_READ_COMPLETE?\"OK\":\"FAILED\", status);\n\n    status = test_consume_queue(db, (WORD) 1, (WORD) 1, txnid);\n    printf(\"Test %s - %s (%d)\\n\", \"consume_queue_txn\", status==0?\"OK\":\"FAILED\", status);\n\n    status = remote_commit_txn(txnid, db);\n    printf(\"Test %s - %s (%d)\\n\", \"commit_txn\", status==0?\"OK\":\"FAILED\", status);\n\n    return 0;\n}\n\nint main(int argc, char **argv) {\n    int portno, n, status;\n    char *hostname;\n    unsigned int seed;\n\n    GET_RANDSEED(&seed, 0); // thread_id\n\n    /* check command line arguments */\n    if (argc != 3) {\n       fprintf(stderr,\"usage: %s <hostname> <port>\\n\", argv[0]);\n       exit(0);\n    }\n    hostname = argv[1];\n    portno = atoi(argv[2]);\n\n    remote_db_t * db = get_remote_db(3);\n\n    add_server_to_membership(hostname, portno, db, &seed);\n    add_server_to_membership(hostname, portno+1, db, &seed);\n    add_server_to_membership(hostname, portno+2, db, &seed);\n\n    db_schema_t * schema = create_schema();\n\n    status = populate_db(schema, db, NULL, &seed);\n    printf(\"Test %s - %s (%d)\\n\", \"populate_db\", status==0?\"OK\":\"FAILED\", status);\n\n    status = test_search_pk_ck1_ck2(schema, db, NULL, &seed);\n    printf(\"Test %s - %s (%d)\\n\", \"test_search_pk_ck1_ck2\", status==0?\"OK\":\"FAILED\", status);\n\n    status = test_search_pk_ck1(schema, db, NULL, &seed);\n    printf(\"Test %s - %s (%d)\\n\", \"test_search_pk_ck1\", status==0?\"OK\":\"FAILED\", status);\n\n    status = test_search_pk(schema, db, NULL, &seed);\n    printf(\"Test %s - %s (%d)\\n\", \"test_search_pk\", status==0?\"OK\":\"FAILED\", status);\n\n    remote_print_long_table((WORD) 0, db);\n\n    status = delete_all(schema, db, NULL, &seed);\n    printf(\"Test %s - %s (%d)\\n\", \"delete_all\", status==0?\"OK\":\"FAILED\", status);\n\n    status = test_create_queue(db, NULL);\n    printf(\"Test %s - %s (%d)\\n\", \"create_queue\", status==0?\"OK\":\"FAILED\", status);\n\n    status = test_subscribe_queue(db, (WORD) 0, (WORD) 1);\n    printf(\"Test %s - %s (%d)\\n\", \"subscribe_queue\", status==0?\"OK\":\"FAILED\", status);\n\n    status = test_enqueue(db, (WORD) 1, NULL);\n    printf(\"Test %s - %s (%d)\\n\", \"enqueue\", status==0?\"OK\":\"FAILED\", status);\n\n    status = test_read_queue(db, (WORD) 0, (WORD) 1, NULL);\n    printf(\"Test %s - %s (%d)\\n\", \"read_queue\", status==QUEUE_STATUS_READ_COMPLETE?\"OK\":\"FAILED\", status);\n\n    status = test_consume_queue(db, (WORD) 0, (WORD) 1, NULL);\n    printf(\"Test %s - %s (%d)\\n\", \"consume_queue\", status==(no_enqueues - 1)?\"OK\":\"FAILED\", status);\n\n    status = test_unsubscribe_queue(db, (WORD) 0, (WORD) 1);\n    printf(\"Test %s - %s (%d)\\n\", \"unsubscribe_queue\", status==0?\"OK\":\"FAILED\", status);\n\n    remote_print_long_table((WORD) 0, db);\n    remote_print_long_table((WORD) 1, db);\n\n    status = test_txn(db, schema, &seed);\n    printf(\"Test %s - %s (%d)\\n\", \"txn\", status==0?\"OK\":\"FAILED\", status);\n\n    remote_print_long_table((WORD) 0, db);\n    remote_print_long_table((WORD) 1, db);\n\n    status = test_delete_queue(db, NULL);\n    printf(\"Test %s - %s (%d)\\n\", \"delete_queue\", status==0?\"OK\":\"FAILED\", status);\n\n    status = close_remote_db(db);\n    printf(\"Test %s - %s (%d)\\n\", \"close_remote_db\", status==0?\"OK\":\"FAILED\", status);\n\n    return 0;\n}\n\n\n"
  },
  {
    "path": "backend/txn_state.c",
    "content": "/*\n * Copyright (C) 2019-2021 Deutsche Telekom AG\n *\n * Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:\n *\n * 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.\n *\n * 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.\n *\n * 3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission.\n *\n * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS \"AS IS\" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n */\n\n/*\n * txn_state.c\n */\n\n#include <stdlib.h>\n#include <uuid/uuid.h>\n#include <string.h>\n#include <assert.h>\n\n#include \"txn_state.h\"\n\nint txn_write_cmp(WORD e1, WORD e2)\n{\n    txn_write * tr1 = (txn_write *) e1;\n    txn_write * tr2 = (txn_write *) e2;\n\n    if(tr1->table_key != tr2->table_key)\n        return (int) ((int64_t) tr1->table_key - (int64_t) tr2->table_key);\n\n    if(tr1->query_type < QUERY_TYPE_ENQUEUE) // Regular ops ordering:\n    {\n        // Newer writes always overwrite older writes to the same objects in the same txn (even between updates/deletes to same object):\n\n        int no_key_cols1 = tr1->no_primary_keys + tr1->no_clustering_keys;\n        int no_key_cols2 = tr2->no_primary_keys + tr2->no_clustering_keys;\n\n        if(no_key_cols1 != no_key_cols2)\n            return no_key_cols1 - no_key_cols2;\n        for(int i=0;i<no_key_cols1;i++)\n        {\n            if(tr1->column_values[i] != tr2->column_values[i])\n                return (int) (int64_t) tr1->column_values[i] - (int64_t) tr2->column_values[i];\n        }\n    }\n    else // Queue ops ordering:\n    {\n        if(tr1->query_type != tr2->query_type)\n            return tr1->query_type - tr2->query_type;\n\n        // For queue reads and consumes, the last version of private read/consume head is kept in write set:\n        if(tr1->query_type == QUERY_TYPE_READ_QUEUE || tr1->query_type == QUERY_TYPE_CONSUME_QUEUE)\n        {\n            if(tr1->queue_id != tr2->queue_id)\n                return (int) ((int64_t) tr1->queue_id - (int64_t) tr2->queue_id);\n            if(tr1->app_id != tr2->app_id)\n                return (int) ((int64_t) tr1->app_id - (int64_t) tr2->app_id);\n            if(tr1->shard_id != tr2->shard_id)\n                return (int) ((int64_t) tr1->shard_id - (int64_t) tr2->shard_id);\n            if(tr1->consumer_id != tr2->consumer_id)\n                return (int) ((int64_t) tr1->consumer_id - (int64_t) tr2->consumer_id);\n        }\n        // All enqueues, queue creates, deletes, subscribes and unsubscribes are accumulated in the write set, in the local order they were issued in the txn:\n        else if(tr1->query_type == QUERY_TYPE_ENQUEUE ||\n                tr1->query_type == QUERY_TYPE_CREATE_QUEUE ||\n                tr1->query_type == QUERY_TYPE_SUBSCRIBE_QUEUE ||\n                tr1->query_type == QUERY_TYPE_UNSUBSCRIBE_QUEUE)\n        {\n            if(tr1->local_order != tr2->local_order)\n                return (int) ((int64_t) tr1->local_order - (int64_t) tr2->local_order);\n        }\n    }\n\n    return 0;\n}\n\nint txn_read_cmp(WORD e1, WORD e2)\n{\n    txn_read * tr1 = (txn_read *) e1;\n    txn_read * tr2 = (txn_read *) e2;\n\n    // Same read operations (individual or range, queried by various clustering levels) return the same object versions while the txn is open:\n\n    if(tr1->query_type != tr2->query_type)\n        return tr1->query_type - tr2->query_type;\n\n    if(tr1->table_key != tr2->table_key)\n        return (int) ((int64_t) tr1->table_key - (int64_t) tr2->table_key);\n\n    if(tr1->query_type == QUERY_TYPE_READ_INDEX || tr1->query_type == QUERY_TYPE_READ_INDEX_RANGE)\n    {\n        if(tr1->idx_idx != tr2->idx_idx)\n            return tr1->idx_idx - tr2->idx_idx;\n    }\n\n    if(tr1->no_primary_keys != tr2->no_primary_keys)\n        return tr1->no_primary_keys - tr2->no_primary_keys;\n    for(int i=0;i<tr1->no_primary_keys;i++)\n    {\n        if(tr1->start_primary_keys[i] != tr2->start_primary_keys[i])\n            return tr1->start_primary_keys[i] - tr2->start_primary_keys[i];\n    }\n\n    if(tr1->query_type == QUERY_TYPE_READ_ROW_RANGE || tr1->query_type == QUERY_TYPE_READ_INDEX_RANGE)\n    {\n        for(int i=0;i<tr1->no_primary_keys;i++)\n        {\n            if(tr1->end_primary_keys[i] != tr2->end_primary_keys[i])\n                return tr1->end_primary_keys[i] - tr2->end_primary_keys[i];\n        }\n    }\n\n    if(tr1->query_type != QUERY_TYPE_READ_ROW && tr1->query_type != QUERY_TYPE_READ_ROW_RANGE)\n    {\n        if(tr1->no_clustering_keys != tr2->no_clustering_keys)\n            return tr1->no_clustering_keys - tr2->no_clustering_keys;\n        for(int i=0;i<tr1->no_clustering_keys;i++)\n        {\n            if(tr1->start_clustering_keys[i] != tr2->start_clustering_keys[i])\n                return tr1->start_clustering_keys[i] - tr2->start_clustering_keys[i];\n        }\n\n        if(tr1->query_type == QUERY_TYPE_READ_CELL_RANGE)\n        {\n            for(int i=0;i<tr1->no_clustering_keys;i++)\n            {\n                if(tr1->end_clustering_keys[i] != tr2->end_clustering_keys[i])\n                    return tr1->end_clustering_keys[i] - tr2->end_clustering_keys[i];\n            }\n        }\n    }\n\n    if(tr1->query_type == QUERY_TYPE_READ_COLS)\n    {\n        if(tr1->no_col_keys != tr2->no_col_keys)\n            return tr1->no_col_keys - tr2->no_col_keys;\n        for(int i=0;i<tr1->no_col_keys;i++)\n        {\n            if(tr1->col_keys[i] != tr2->col_keys[i])\n                return tr1->col_keys[i] - tr2->col_keys[i];\n        }\n    }\n\n    return 0;\n}\n\ntxn_state * init_txn_state()\n{\n    txn_state * ts = (txn_state *) malloc(sizeof(txn_state));\n    uuid_generate(ts->txnid);\n    ts->read_set = create_skiplist(&txn_read_cmp);\n    ts->write_set = create_skiplist(&txn_write_cmp);\n    ts->state = TXN_STATUS_ACTIVE;\n    ts->version = NULL;\n\n    return ts;\n}\n\nvoid set_version(txn_state * ts, vector_clock * vc)\n{\n    if(ts->version == NULL)\n        ts->version = copy_vc(vc);\n    else\n        update_or_replace_vc(&(ts->version), vc);\n}\n\nvoid free_txn_state(txn_state * ts)\n{\n    skiplist_free(ts->read_set);\n    skiplist_free(ts->write_set);\n    free(ts);\n}\n\ntxn_write * get_txn_write(short query_type, WORD * column_values, int no_cols, int no_primary_keys, int no_clustering_keys, size_t blob_size, WORD table_key, int64_t local_order)\n{\n    txn_write * tw = (txn_write *) malloc(sizeof(txn_write) + no_cols*sizeof(WORD));\n    memset(tw, 0, sizeof(txn_write) + no_cols*sizeof(WORD));\n\n    tw->table_key = table_key;\n    tw->no_cols = no_cols;\n    tw->no_primary_keys = no_primary_keys;\n    tw->no_clustering_keys = no_clustering_keys;\n    tw->blob_size = blob_size;\n    tw->column_values = (WORD *) ((char *) tw + sizeof(txn_write));\n    for(int i=0;i<tw->no_cols;i++)\n        tw->column_values[i] = column_values[i];\n\n    tw->query_type = query_type;\n    tw->local_order = local_order;\n\n    return tw;\n}\n\ntxn_write * get_dummy_txn_write(short query_type, WORD * primary_keys, int no_primary_keys, WORD * clustering_keys, int no_clustering_keys, WORD table_key, int64_t local_order)\n{\n    int no_cols = no_primary_keys + no_clustering_keys;\n    txn_write * tw = (txn_write *) malloc(sizeof(txn_write) + no_cols*sizeof(WORD));\n    memset(tw, 0, sizeof(txn_write) + no_cols*sizeof(WORD));\n\n    tw->table_key = table_key;\n    tw->no_cols = no_cols;\n    tw->blob_size = 0;\n    tw->no_primary_keys = no_primary_keys;\n    tw->no_clustering_keys = no_clustering_keys;\n    tw->column_values = (WORD *) ((char *) tw + sizeof(txn_write));\n    int i=0;\n    for(;i<tw->no_primary_keys;i++)\n        tw->column_values[i] = primary_keys[i];\n    for(;i<tw->no_cols;i++)\n        tw->column_values[i] = primary_keys[i-no_primary_keys];\n\n    tw->query_type = query_type;\n    tw->local_order = local_order;\n\n    return tw;\n}\n\ntxn_write * get_txn_queue_op(short query_type, WORD * column_values, int no_cols, size_t blob_size, WORD table_key,\n                    WORD queue_id, WORD consumer_id, WORD shard_id, WORD app_id,\n                    int64_t new_read_head, vector_clock * prh_version, int64_t new_consume_head, int64_t local_order)\n{\n    assert(query_type >= QUERY_TYPE_ENQUEUE && query_type <= QUERY_TYPE_UNSUBSCRIBE_QUEUE);\n\n    txn_write * tw = get_txn_write(query_type, column_values, no_cols, 0, 0, blob_size, table_key, local_order);\n\n    tw->queue_id = queue_id;\n\n    if(query_type == QUERY_TYPE_READ_QUEUE || query_type == QUERY_TYPE_CONSUME_QUEUE ||\n        query_type == QUERY_TYPE_SUBSCRIBE_QUEUE || query_type == QUERY_TYPE_UNSUBSCRIBE_QUEUE)\n    {\n        tw->consumer_id = consumer_id;\n        tw->shard_id = shard_id;\n        tw->app_id = app_id;\n    }\n    else\n    {\n        assert(consumer_id == NULL && shard_id == NULL && app_id == NULL);\n    }\n\n    if(query_type == QUERY_TYPE_READ_QUEUE)\n    {\n        tw->new_read_head = new_read_head;\n        tw->prh_version = prh_version;\n    }\n    else\n    {\n        assert(new_read_head == -1);\n    }\n\n    if(query_type == QUERY_TYPE_CONSUME_QUEUE)\n    {\n        tw->new_consume_head = new_consume_head;\n    }\n    else\n    {\n        assert(new_consume_head == -1);\n    }\n\n    return tw;\n}\n\nvoid free_txn_write(txn_write * tw)\n{\n    free(tw);\n}\n\ntxn_read * get_txn_read(short query_type,\n                        WORD* start_primary_keys, WORD* end_primary_keys, int no_primary_keys,\n                        WORD* start_clustering_keys, WORD* end_clustering_keys, int no_clustering_keys,\n                        WORD* col_keys, int no_col_keys,\n                        int idx_idx,\n                        vector_clock * result_version,\n                        int64_t * range_result_keys, vector_clock ** range_result_versions, int no_range_results,\n                        WORD table_key, int64_t local_order)\n{\n    int total_col_count = no_primary_keys + no_clustering_keys;\n    if(query_type == QUERY_TYPE_READ_ROW_RANGE)\n        total_col_count += no_primary_keys;\n    if(query_type == QUERY_TYPE_READ_CELL_RANGE)\n        total_col_count += no_clustering_keys;\n    if(query_type == QUERY_TYPE_READ_COLS)\n        total_col_count += no_col_keys;\n\n    txn_read * tr = (txn_read *) malloc(sizeof(txn_read) + total_col_count * sizeof(WORD));\n    memset(tr, 0, sizeof(txn_read) + total_col_count * sizeof(WORD));\n\n    tr->table_key = table_key;\n    tr->query_type = query_type;\n    tr->local_order = local_order;\n\n    int offset = sizeof(txn_write);\n    tr->no_primary_keys = no_primary_keys;\n    tr->start_clustering_keys = (WORD *) ((char *) tr + offset);\n    for(int i=0;i<tr->no_primary_keys;i++)\n        tr->start_primary_keys[i] = start_primary_keys[i];\n    offset += tr->no_primary_keys * sizeof(WORD);\n\n    if(query_type == QUERY_TYPE_READ_ROW_RANGE)\n    {\n        tr->end_clustering_keys = (WORD *) ((char *) tr + offset);\n        for(int i=0;i<tr->no_primary_keys;i++)\n            tr->end_clustering_keys[i] = end_clustering_keys[i];\n        offset += tr->no_primary_keys * sizeof(WORD);\n    }\n\n    if(query_type != QUERY_TYPE_READ_ROW && query_type != QUERY_TYPE_READ_ROW_RANGE)\n    {\n        tr->start_clustering_keys = (WORD *) ((char *) tr + offset);\n        for(int i=0;i<tr->no_clustering_keys;i++)\n            tr->start_clustering_keys[i] = start_clustering_keys[i];\n        offset += tr->no_clustering_keys * sizeof(WORD);\n    }\n\n    if(query_type == QUERY_TYPE_READ_CELL_RANGE)\n    {\n        tr->end_clustering_keys = (WORD *) ((char *) tr + offset);\n        for(int i=0;i<tr->no_clustering_keys;i++)\n            tr->end_clustering_keys[i] = end_clustering_keys[i];\n        offset += tr->no_clustering_keys * sizeof(WORD);\n    }\n\n    if(query_type == QUERY_TYPE_READ_COLS)\n    {\n        tr->col_keys = (WORD *) ((char *) tr + offset);\n        for(int i=0;i<tr->no_col_keys;i++)\n            tr->col_keys[i] = col_keys[i];\n        offset += tr->no_col_keys * sizeof(WORD);\n    }\n\n    if(query_type == QUERY_TYPE_READ_INDEX || query_type == QUERY_TYPE_READ_INDEX_RANGE)\n        assert(idx_idx != -1);\n\n    tr->idx_idx = idx_idx;\n\n    tr->result_version = result_version;\n    tr->range_result_keys = range_result_keys;\n    tr->range_result_versions = range_result_versions;\n    tr->no_range_results = no_range_results;\n\n    return tr;\n}\n\nvoid free_txn_read(txn_read * tr)\n{\n    if(tr->result_version != NULL)\n        free_vc(tr->result_version);\n\n    if(tr->range_result_keys && tr->no_range_results > 0)\n    {\n        free(tr->range_result_keys);\n        for(int i=0;i<tr->no_range_results;i++)\n            free_vc(tr->range_result_versions[i]);\n        free(tr->range_result_versions);\n    }\n\n    free(tr);\n}\n\nint add_write_to_txn(short query_type, WORD * column_values, int no_cols, int no_primary_keys, int no_clustering_keys, size_t blob_size, WORD table_key, txn_state * ts, unsigned int * fastrandstate)\n{\n    assert((query_type == QUERY_TYPE_UPDATE) || (query_type == QUERY_TYPE_DELETE));\n    txn_write * tw = get_txn_write(query_type, column_values, no_cols, no_primary_keys, no_clustering_keys, blob_size, table_key, (int64_t) ts->write_set->no_items);\n\n    // Note that this will overwrite previous values written for the variable in the same txn (last write wins):\n\n    snode_t * prev_tw_node = skiplist_search(ts->write_set, (WORD) tw);\n    txn_write * prev_tw = (prev_tw_node != NULL)?prev_tw_node->value : NULL;\n\n    int ret = skiplist_insert(ts->write_set, (WORD) tw, (WORD) tw, fastrandstate);\n\n    if(prev_tw != NULL)\n        free_txn_write(prev_tw);\n\n    return ret;\n}\n\nint add_row_read_to_txn(WORD* primary_keys, int no_primary_keys,\n                        WORD table_key, db_row_t* result,\n                        txn_state * ts, unsigned int * fastrandstate)\n{\n    txn_read * tr = get_txn_read(QUERY_TYPE_READ_ROW, primary_keys, NULL, no_primary_keys, NULL, NULL, 0, NULL, 0, -1, copy_vc(result->version), NULL, NULL, 0, table_key, (int64_t) ts->read_set->no_items);\n\n    // Note that this will overwrite previous values read for the variable in the same txn (last read wins):\n\n    snode_t * prev_tr_node = skiplist_search(ts->read_set, (WORD) tr);\n    txn_read * prev_tr = (prev_tr_node != NULL)?prev_tr_node->value : NULL;\n\n    int ret = skiplist_insert(ts->read_set, (WORD) tr, (WORD) tr, fastrandstate);\n\n    if(prev_tr != NULL)\n        free_txn_read(prev_tr);\n\n    return ret;\n}\n\nint add_row_range_read_to_txn(WORD* start_primary_keys, WORD* end_primary_keys, int no_primary_keys, WORD table_key,\n                                snode_t* start_row, snode_t* end_row, int no_results,\n                                txn_state * ts, unsigned int * fastrandstate)\n{\n    int64_t * range_result_keys = (int64_t *) malloc(no_results * sizeof(int64_t));\n    vector_clock ** range_result_versions = (vector_clock **) malloc(no_results * sizeof(vector_clock *));;\n    int i=0;\n\n    for(snode_t* crt_row = start_row;crt_row != end_row;crt_row=NEXT(crt_row), i++)\n    {\n        db_row_t * row = (db_row_t *) crt_row->value;\n        range_result_keys[i] = (int64_t) row->key;\n        range_result_versions[i] = (row->version != NULL)? copy_vc(row->version) : NULL;\n    }\n\n    txn_read * tr = get_txn_read(QUERY_TYPE_READ_ROW_RANGE, start_primary_keys, end_primary_keys, no_primary_keys, NULL, NULL, 0, NULL, 0, -1, NULL, range_result_keys, range_result_versions, no_results, table_key, (int64_t) ts->read_set->no_items);\n    snode_t * prev_tr_node = skiplist_search(ts->read_set, (WORD) tr);\n    txn_read * prev_tr = (prev_tr_node != NULL)?prev_tr_node->value : NULL;\n\n    int ret = skiplist_insert(ts->read_set, (WORD) tr, (WORD) tr, fastrandstate); // Note that this will overwrite previous values read for the variable in the same txn (last read wins)\n    if(prev_tr != NULL)\n        free_txn_read(prev_tr);\n\n    return ret;\n}\n\nint add_cell_read_to_txn(WORD* primary_keys, int no_primary_keys, WORD* clustering_keys, int no_clustering_keys,\n                                WORD table_key, db_row_t* result,\n                                txn_state * ts, unsigned int * fastrandstate)\n{\n    txn_read * tr = get_txn_read(QUERY_TYPE_READ_CELL, primary_keys, NULL, no_primary_keys, clustering_keys, NULL, no_clustering_keys, NULL, 0, -1, copy_vc(result->version), NULL, NULL, 0, table_key, (int64_t) ts->read_set->no_items);\n    snode_t * prev_tr_node = skiplist_search(ts->read_set, (WORD) tr);\n    txn_read * prev_tr = (prev_tr_node != NULL)?prev_tr_node->value : NULL;\n\n    int ret = skiplist_insert(ts->read_set, (WORD) tr, (WORD) tr, fastrandstate); // Note that this will overwrite previous values read for the variable in the same txn (last read wins)\n    if(prev_tr != NULL)\n        free_txn_read(prev_tr);\n\n    return ret;\n}\n\nint add_cell_range_read_to_txn(WORD* primary_keys, int no_primary_keys, WORD* start_clustering_keys,\n                                WORD* end_clustering_keys, int no_clustering_keys,\n                                WORD table_key,\n                                snode_t* start_row, snode_t* end_row, int no_results,\n                                txn_state * ts, unsigned int * fastrandstate)\n{\n    int64_t * range_result_keys = (int64_t *) malloc(no_results * sizeof(int64_t));\n    vector_clock ** range_result_versions = (vector_clock **) malloc(no_results * sizeof(vector_clock *));;\n    int i=0;\n\n    for(snode_t* crt_row = start_row;crt_row != end_row;crt_row=NEXT(crt_row), i++)\n    {\n        db_row_t * row = (db_row_t *) crt_row->value;\n        range_result_keys[i] = (int64_t) row->key;\n        range_result_versions[i] = (row->version != NULL)? copy_vc(row->version) : NULL;\n    }\n\n    txn_read * tr = get_txn_read(QUERY_TYPE_READ_CELL_RANGE, primary_keys, NULL, no_primary_keys,\n                                start_clustering_keys, end_clustering_keys, no_clustering_keys,\n                                NULL, 0, -1, NULL,\n                                range_result_keys, range_result_versions, no_results,\n                                table_key, (int64_t) ts->read_set->no_items);\n\n    snode_t * prev_tr_node = skiplist_search(ts->read_set, (WORD) tr);\n    txn_read * prev_tr = (prev_tr_node != NULL)?prev_tr_node->value : NULL;\n\n    int ret = skiplist_insert(ts->read_set, (WORD) tr, (WORD) tr, fastrandstate); // Note that this will overwrite previous values read for the variable in the same txn (last read wins)\n    if(prev_tr != NULL)\n        free_txn_read(prev_tr);\n\n    return ret;\n}\n\nint add_col_read_to_txn(WORD* primary_keys, int no_primary_keys, WORD* clustering_keys, int no_clustering_keys,\n                                WORD* col_keys, int no_columns,\n                                WORD table_key, db_row_t* result,\n                                txn_state * ts, unsigned int * fastrandstate)\n{\n    txn_read * tr = get_txn_read(QUERY_TYPE_READ_COLS, primary_keys, NULL, no_primary_keys, clustering_keys, NULL, no_clustering_keys, col_keys, no_columns, -1, copy_vc(result->version), NULL, NULL, 0, table_key, (int64_t) ts->read_set->no_items);\n    snode_t * prev_tr_node = skiplist_search(ts->read_set, (WORD) tr);\n    txn_read * prev_tr = (prev_tr_node != NULL)?prev_tr_node->value : NULL;\n\n    int ret = skiplist_insert(ts->read_set, (WORD) tr, (WORD) tr, fastrandstate); // Note that this will overwrite previous values read for the variable in the same txn (last read wins)\n    if(prev_tr != NULL)\n        free_txn_read(prev_tr);\n\n    return ret;\n}\n\nint add_index_read_to_txn(WORD* index_key, int idx_idx, WORD table_key, db_row_t* result, txn_state * ts, unsigned int * fastrandstate)\n{\n    txn_read * tr = get_txn_read(QUERY_TYPE_READ_INDEX, index_key, NULL, 1, NULL, NULL, 0, NULL, 0, idx_idx, copy_vc(result->version), NULL, NULL, 0, table_key, (int64_t) ts->read_set->no_items);\n    snode_t * prev_tr_node = skiplist_search(ts->read_set, (WORD) tr);\n    txn_read * prev_tr = (prev_tr_node != NULL)?prev_tr_node->value : NULL;\n\n    int ret = skiplist_insert(ts->read_set, (WORD) tr, (WORD) tr, fastrandstate); // Note that this will overwrite previous values read for the variable in the same txn (last read wins)\n    if(prev_tr != NULL)\n        free_txn_read(prev_tr);\n\n    return ret;\n}\n\nint add_index_range_read_to_txn(int idx_idx, WORD* start_idx_key, WORD* end_idx_key, snode_t* start_row, snode_t* end_row, int no_results, WORD table_key, txn_state * ts, unsigned int * fastrandstate)\n{\n    int64_t * range_result_keys = (int64_t *) malloc(no_results * sizeof(int64_t));\n    vector_clock ** range_result_versions = (vector_clock **) malloc(no_results * sizeof(vector_clock *));;\n    int i=0;\n\n    for(snode_t* crt_row = start_row;crt_row != end_row;crt_row=NEXT(crt_row), i++)\n    {\n        db_row_t * row = (db_row_t *) crt_row->value;\n        range_result_keys[i] = (int64_t) row->key;\n        range_result_versions[i] = (row->version != NULL)? copy_vc(row->version) : NULL;\n    }\n\n    txn_read * tr = get_txn_read(QUERY_TYPE_READ_INDEX_RANGE, start_idx_key, end_idx_key, 1, NULL, NULL, 0, NULL, 0, idx_idx, NULL, range_result_keys, range_result_versions, no_results, table_key, (int64_t) ts->read_set->no_items);\n    snode_t * prev_tr_node = skiplist_search(ts->read_set, (WORD) tr);\n    txn_read * prev_tr = (prev_tr_node != NULL)?prev_tr_node->value : NULL;\n\n    int ret = skiplist_insert(ts->read_set, (WORD) tr, (WORD) tr, fastrandstate); // Note that this will overwrite previous values read for the variable in the same txn (last read wins)\n    if(prev_tr != NULL)\n        free_txn_read(prev_tr);\n\n    return ret;\n}\n\n// Queue ops:\n\nint add_enqueue_to_txn(WORD * column_values, int no_cols, size_t blob_size, WORD table_key, WORD queue_id, txn_state * ts, unsigned int * fastrandstate)\n{\n    txn_write * tw = get_txn_queue_op(QUERY_TYPE_ENQUEUE, column_values, no_cols, blob_size, table_key, queue_id,\n                        NULL, NULL, NULL, -1, NULL, -1, (int64_t) ts->write_set->no_items);\n\n     // Multiple enqueues in the same txn accumulate in write set (indexed by local_order = ts->write_set->no_items):\n    return skiplist_insert(ts->write_set, (WORD) tw, (WORD) tw, fastrandstate);\n}\n\nint add_read_queue_to_txn(WORD consumer_id, WORD shard_id, WORD app_id, WORD table_key, WORD queue_id,\n                        int64_t new_read_head, vector_clock * prh_version, txn_state * ts, unsigned int * fastrandstate)\n{\n    txn_write * tw = get_txn_queue_op(QUERY_TYPE_READ_QUEUE, NULL, 0, 0, table_key, queue_id,\n                                consumer_id, shard_id, app_id, new_read_head, prh_version, -1,\n                                (int64_t) ts->write_set->no_items);\n\n    // Keep only latest private_read_head when doing multiple queue reads in the same txn:\n    snode_t * prev_tw_node = skiplist_search(ts->write_set, (WORD) tw);\n    txn_write * prev_tw = (prev_tw_node != NULL)?prev_tw_node->value : NULL;\n\n    int ret = skiplist_insert(ts->write_set, (WORD) tw, (WORD) tw, fastrandstate); // TO DO: Handle multiple queue reads in the same txn\n\n    if(prev_tw != NULL)\n        free_txn_write(prev_tw);\n\n    return ret;\n}\n\nint add_consume_queue_to_txn(WORD consumer_id, WORD shard_id, WORD app_id, WORD table_key, WORD queue_id,\n                    int64_t new_consume_head, txn_state * ts, unsigned int * fastrandstate)\n{\n    txn_write * tw = get_txn_queue_op(QUERY_TYPE_CONSUME_QUEUE, NULL, 0, 0, table_key, queue_id,\n                                consumer_id, shard_id, app_id, -1, NULL, new_consume_head,\n                                (int64_t) ts->write_set->no_items);\n    // Keep only latest private_consume_head when doing multiple queue consumes in the same txn:\n    snode_t * prev_tw_node = skiplist_search(ts->write_set, (WORD) tw);\n    txn_write * prev_tw = (prev_tw_node != NULL)?prev_tw_node->value : NULL;\n\n    int ret = skiplist_insert(ts->write_set, (WORD) tw, (WORD) tw, fastrandstate); // TO DO: Handle multiple queue reads in the same txn\n    if(prev_tw != NULL)\n        free_txn_write(prev_tw);\n\n    return ret;\n}\n\nint add_create_queue_to_txn(WORD table_key, WORD queue_id, txn_state * ts, unsigned int * fastrandstate)\n{\n    txn_write * tw = get_txn_queue_op(QUERY_TYPE_CREATE_QUEUE, NULL, 0, 0, table_key, queue_id,\n                                            NULL, NULL, NULL, -1, NULL, -1, (int64_t) ts->write_set->no_items);\n\n     // Multiple \"create queue\"-s in the same txn accumulate in write set (indexed by local_order = ts->write_set->no_items):\n    return skiplist_insert(ts->write_set, (WORD) tw, (WORD) tw, fastrandstate); // TO DO: Handle multiple enqueues in the same txn\n}\n\nint add_delete_queue_to_txn(WORD table_key, WORD queue_id, txn_state * ts, unsigned int * fastrandstate)\n{\n    txn_write * tw = get_txn_queue_op(QUERY_TYPE_DELETE_QUEUE, NULL, 0, 0, table_key, queue_id,\n                                            NULL, NULL, NULL, -1, NULL, -1, (int64_t) ts->write_set->no_items);\n\n     // Multiple \"delete queue\"-s in the same txn accumulate in write set (indexed by local_order = ts->write_set->no_items):\n    return skiplist_insert(ts->write_set, (WORD) tw, (WORD) tw, fastrandstate); // TO DO: Handle multiple enqueues in the same txn\n}\n\nint add_subscribe_queue_to_txn(WORD consumer_id, WORD shard_id, WORD app_id, WORD table_key, WORD queue_id,\n                        queue_callback * callback, int64_t * prev_read_head, int64_t * prev_consume_head,\n                        txn_state * ts, unsigned int * fastrandstate)\n{\n    assert (0); // Not implemented\n    return 0;\n}\n\nint add_unsubscribe_queue_to_txn(WORD consumer_id, WORD shard_id, WORD app_id, WORD table_key, WORD queue_id,\n                        txn_state * ts)\n{\n    assert (0); // Not implemented\n    return 0;\n}\n\n"
  },
  {
    "path": "backend/txn_state.h",
    "content": "/*\n * txn_state.h\n */\n\n#ifndef BACKEND_TXN_STATE_H_\n#define BACKEND_TXN_STATE_H_\n\n#include <uuid/uuid.h>\n#include \"db.h\"\n#include \"queue_callback.h\"\n\n#define TXN_STATUS_ACTIVE 0\n#define TXN_STATUS_VALIDATED 1\n// #define TXN_STATUS_COMMITTED 2\n// #define TXN_STATUS_ABORTED 3\n\n\ntypedef struct txn_write\n{\n    short query_type;\n    WORD table_key;\n\n    WORD * column_values;\n    int no_cols;\n    int no_primary_keys;\n    int no_clustering_keys;\n    size_t blob_size;\n\n    // For queue ops:\n\n    WORD queue_id;\n    WORD consumer_id;\n    WORD shard_id;\n    WORD app_id;\n\n    int64_t new_read_head;  // read_queue (out)\n    int64_t new_consume_head; // consume_queue (in)\n\n    vector_clock * prh_version;\n//  vector_clock * pch_version;\n\n    int64_t local_order;\n} txn_write;\n\ntypedef struct txn_read\n{\n    WORD table_key;\n\n    WORD* start_primary_keys;\n    WORD* end_primary_keys;\n    int no_primary_keys;\n\n    WORD* start_clustering_keys;\n    WORD* end_clustering_keys;\n    int no_clustering_keys;\n\n    WORD* col_keys;\n    int no_col_keys;\n\n    // For idx queries:\n\n    int idx_idx;\n\n    short query_type;\n\n    // For non-range queries:\n\n    vector_clock * result_version;\n\n    // For range queries:\n\n    int64_t * range_result_keys;\n    vector_clock ** range_result_versions;\n    int no_range_results;\n\n    snode_t* start_row;\n    snode_t* end_row;\n\n    int64_t local_order;\n} txn_read;\n\ntypedef struct txn_state\n{\n    uuid_t txnid;\n    skiplist_t * read_set;\n    skiplist_t * write_set;\n    short state;\n\n    vector_clock * version;\n} txn_state;\n\nint txn_write_cmp(WORD e1, WORD e2);\nint txn_read_cmp(WORD e1, WORD e2);\n\ntxn_state * init_txn_state();\nvoid free_txn_state(txn_state * ts);\nvoid set_version(txn_state * ts, vector_clock * vc);\n\ntxn_write * get_txn_write(short query_type, WORD * column_values, int no_cols, int no_primary_keys, int no_clustering_keys, size_t blob_size, WORD table_key, int64_t local_order);\ntxn_write * get_dummy_txn_write(short query_type, WORD * primary_keys, int no_primary_keys, WORD * clustering_keys, int no_clustering_keys, WORD table_key, int64_t local_order);\nvoid free_txn_write(txn_write * tw);\ntxn_read * get_txn_read(short query_type,\n                        WORD* start_primary_keys, WORD* end_primary_keys, int no_primary_keys,\n                        WORD* start_clustering_keys, WORD* end_clustering_keys, int no_clustering_keys,\n                        WORD* col_keys, int no_col_keys,\n                        int idx_idx,\n                        vector_clock * result_version,\n                        int64_t * range_result_keys, vector_clock ** range_result_versions, int no_range_results,\n                        WORD table_key, int64_t local_order);\nvoid free_txn_read(txn_read * tr);\n\n// Txn ops mgmt API:\n\nint add_write_to_txn(short query_type, WORD * column_values, int no_cols, int no_primary_keys, int no_clustering_keys, size_t blob_size,\n                    WORD table_key, txn_state * ts, unsigned int * fastrandstate);\nint add_row_read_to_txn(WORD* primary_keys, int no_primary_keys,\n                        WORD table_key, db_row_t* result,\n                        txn_state * ts, unsigned int * fastrandstate);\nint add_row_range_read_to_txn(WORD* start_primary_keys, WORD* end_primary_keys, int no_primary_keys, WORD table_key,\n                                snode_t* start_row, snode_t* end_row, int no_results,\n                                txn_state * ts, unsigned int * fastrandstate);\nint add_cell_read_to_txn(WORD* primary_keys, int no_primary_keys, WORD* clustering_keys, int no_clustering_keys,\n                                WORD table_key, db_row_t* result,\n                                txn_state * ts, unsigned int * fastrandstate);\nint add_cell_range_read_to_txn(WORD* primary_keys, int no_primary_keys, WORD* start_clustering_keys,\n                                WORD* end_clustering_keys, int no_clustering_keys,\n                                WORD table_key,\n                                snode_t* start_row, snode_t* end_row, int no_results,\n                                txn_state * ts, unsigned int * fastrandstate);\nint add_col_read_to_txn(WORD* primary_keys, int no_primary_keys, WORD* clustering_keys, int no_clustering_keys,\n                                WORD* col_keys, int no_columns,\n                                WORD table_key, db_row_t* result,\n                                txn_state * ts, unsigned int * fastrandstate);\nint add_index_read_to_txn(WORD* index_key, int idx_idx, WORD table_key, db_row_t* result, txn_state * ts, unsigned int * fastrandstate);\nint add_index_range_read_to_txn(int idx_idx, WORD* start_idx_key, WORD* end_idx_key, snode_t* start_row, snode_t* end_row, int no_results, WORD table_key, txn_state * ts, unsigned int * fastrandstate);\n\n// Queue ops:\n\nint add_enqueue_to_txn(WORD * column_values, int no_cols, size_t blob_size, WORD table_key, WORD queue_id, txn_state * ts, unsigned int * fastrandstate);\nint add_read_queue_to_txn(WORD consumer_id, WORD shard_id, WORD app_id, WORD table_key, WORD queue_id,\n                            int64_t new_read_head, vector_clock * prh_version, txn_state * ts, unsigned int * fastrandstate);\nint add_consume_queue_to_txn(WORD consumer_id, WORD shard_id, WORD app_id, WORD table_key, WORD queue_id,\n                    int64_t new_consume_head, txn_state * ts, unsigned int * fastrandstate);\nint add_create_queue_to_txn(WORD table_key, WORD queue_id, txn_state * ts, unsigned int * fastrandstate);\nint add_delete_queue_to_txn(WORD table_key, WORD queue_id, txn_state * ts, unsigned int * fastrandstate);\nint add_subscribe_queue_to_txn(WORD consumer_id, WORD shard_id, WORD app_id, WORD table_key, WORD queue_id,\n                        queue_callback * callback, int64_t * prev_read_head, int64_t * prev_consume_head,\n                        txn_state * ts, unsigned int * fastrandstate);\nint add_unsubscribe_queue_to_txn(WORD consumer_id, WORD shard_id, WORD app_id, WORD table_key, WORD queue_id, txn_state * ts);\n\n#endif /* BACKEND_TXN_STATE_H_ */\n"
  },
  {
    "path": "backend/txns.c",
    "content": "/*\n * Copyright (C) 2019-2021 Deutsche Telekom AG\n *\n * Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:\n *\n * 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.\n *\n * 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.\n *\n * 3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission.\n *\n * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS \"AS IS\" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n */\n\n/*\n * txns.c\n *\n *      Author: aagapi\n */\n\n#include \"txns.h\"\n#include \"log.h\"\n\n#include <stdio.h>\n\n#define VERBOSE_TXNS 1\n#define VERBOSE_TXNS_PERSIST 0\n\n// DB queries:\n\ntxn_state * get_txn_state(uuid_t * txnid, db_t * db)\n{\n    snode_t * txn_node = (snode_t *) skiplist_search(db->txn_state, (WORD) (*txnid));\n\n    return (txn_node != NULL)? (txn_state *) txn_node->value : NULL;\n}\n\nuuid_t * new_txn(db_t * db, unsigned int * seedptr)\n{\n    txn_state * ts = NULL, * previous = NULL;\n\n#if (MULTI_THREADED == 1)\n    pthread_mutex_lock(db->txn_state_lock);\n#endif\n\n    while(ts == NULL)\n    {\n        ts = init_txn_state();\n        previous = get_txn_state(&(ts->txnid), db);\n        if(previous != NULL)\n        {\n            free_txn_state(ts);\n            ts = NULL;\n        }\n    }\n\n    skiplist_insert(db->txn_state, (WORD) ts->txnid, (WORD) ts, seedptr);\n\n#if (MULTI_THREADED == 1)\n    pthread_mutex_unlock(db->txn_state_lock);\n#endif\n\n    return &(ts->txnid);\n}\n\nint close_txn_state(txn_state * ts, db_t * db)\n{\n#if (MULTI_THREADED == 1)\n    pthread_mutex_lock(db->txn_state_lock);\n#endif\n\n    skiplist_delete(db->txn_state, ts->txnid);\n    free_txn_state(ts);\n\n#if (MULTI_THREADED == 1)\n    pthread_mutex_unlock(db->txn_state_lock);\n#endif\n\n    return 0;\n}\n\nint close_txn(uuid_t * txnid, db_t * db)\n{\n    txn_state * ts = get_txn_state(txnid, db);\n    if(ts == NULL)\n        return NO_SUCH_TXN; // No such txn\n\n    return close_txn_state(ts, db);\n}\n\nint key_path_overlaps(txn_read * tr, txn_write * tw)\n{\n    // Writes must be at least as specific as reads:\n    assert(tr->no_primary_keys + tr->no_clustering_keys <= tw->no_primary_keys + tw->no_clustering_keys);\n\n    int is_exact_read_query = (tr->query_type == QUERY_TYPE_READ_COLS || tr->query_type == QUERY_TYPE_READ_CELL || tr->query_type == QUERY_TYPE_READ_ROW);\n\n    if(tr->query_type == QUERY_TYPE_READ_INDEX)\n    {\n        if((int64_t) tw->column_values[tr->idx_idx] == (int64_t) tr->start_primary_keys[0])\n            return 1;\n        return 0;\n    }\n\n    if(tr->query_type == QUERY_TYPE_READ_INDEX_RANGE)\n    {\n        if((int64_t) tw->column_values[tr->idx_idx] <= (int64_t) tr->start_primary_keys[0] && (int64_t) tw->column_values[tr->idx_idx] >= (int64_t) tr->end_primary_keys[0])\n            return 1;\n        return 0;\n    }\n\n    for(int i=0;i<tr->no_primary_keys;i++)\n    {\n        if(is_exact_read_query && tr->start_primary_keys[i] != tw->column_values[i])\n            return 0;\n        if(!is_exact_read_query &&\n            ((int64_t) tr->start_primary_keys[i] > (int64_t) tw->column_values[i] ||\n            (int64_t) tr->end_primary_keys[i] < (int64_t) tw->column_values[i]))\n                return 0;\n    }\n    for(int i=0;i<tr->no_clustering_keys;i++)\n    {\n        if(is_exact_read_query && tr->start_clustering_keys[i] != tw->column_values[tw->no_primary_keys + i])\n            return 0;\n        if(!is_exact_read_query &&\n            ((int64_t) tr->start_clustering_keys[i] > (int64_t) tw->column_values[tw->no_primary_keys + i] ||\n            (int64_t) tr->end_clustering_keys[i] < (int64_t) tw->column_values[tw->no_primary_keys + i]))\n                return 0;\n    }\n\n    return 1;\n}\n\n// Check if txn read op tr is invalidated by write op tw:\nint rw_conflict(txn_read * tr, txn_write * tw, int check_exact_match)\n{\n    if(check_exact_match && tr->table_key != tw->table_key)\n        return 0;\n\n    // Check for RW conflicts only on regular data (all conflicts on queues are WW):\n\n    if(tr->query_type >= QUERY_TYPE_READ_COLS && tr->query_type <= QUERY_TYPE_READ_INDEX_RANGE &&\n        (tw->query_type == QUERY_TYPE_UPDATE || tw->query_type == QUERY_TYPE_DELETE) )\n    {\n        switch(tr->query_type)\n        {\n            case QUERY_TYPE_READ_COLS:\n            case QUERY_TYPE_READ_CELL:\n            case QUERY_TYPE_READ_CELL_RANGE:\n            case QUERY_TYPE_READ_ROW:\n            case QUERY_TYPE_READ_ROW_RANGE:\n            case QUERY_TYPE_READ_INDEX:\n            case QUERY_TYPE_READ_INDEX_RANGE:\n            {\n                if(check_exact_match && key_path_overlaps(tr, tw)) //  && compare_vc(tr->version, vector_clock * vc2)\n                    return 1;\n            }\n        }\n    }\n\n    return 0;\n}\n\n// Check if queue op tw1 is invalidated by queue op tw2:\nint queue_op_conflict(txn_write * tw1, txn_write * tw2)\n{\n    // Subscribes and unsubscribes are not currently supported in txns\n\n    assert(tw1->query_type != QUERY_TYPE_SUBSCRIBE_QUEUE && tw1->query_type != QUERY_TYPE_UNSUBSCRIBE_QUEUE);\n    assert(tw2->query_type != QUERY_TYPE_SUBSCRIBE_QUEUE && tw2->query_type != QUERY_TYPE_UNSUBSCRIBE_QUEUE);\n\n    // Queue ops only conflict if they are on the same table and queue:\n\n    if(tw1->table_key != tw2->table_key || tw1->queue_id != tw2->queue_id)\n        return 0;\n\n    // CREATE_QUEUE and DELETE_QUEUE conflict with everything:\n\n    if(tw1->query_type == QUERY_TYPE_CREATE_QUEUE || tw1->query_type == QUERY_TYPE_DELETE_QUEUE ||\n       tw2->query_type == QUERY_TYPE_CREATE_QUEUE || tw2->query_type == QUERY_TYPE_DELETE_QUEUE)\n        return 1;\n\n    // Only ENQUEUE/ENQUEUE (by any producers), as well as READ_QUEUE / READ_QUEUE and\n    // CONSUME_QUEUE / CONSUME_QUEUE *by the same consumer* are valid conflicts:\n\n    if(tw1->query_type != tw2->query_type)\n        return 0;\n\n    if(tw1->query_type == QUERY_TYPE_ENQUEUE)\n        return 1;\n\n    if((tw1->query_type == QUERY_TYPE_READ_QUEUE || tw1->query_type == QUERY_TYPE_CONSUME_QUEUE) &&\n            tw1->consumer_id == tw2->consumer_id &&\n            tw1->shard_id == tw2->shard_id &&\n            tw1->app_id == tw2->app_id)\n        return 1;\n\n    return 0;\n}\n\n// Check if txn write op tw1 is invalidated by write op tw2:\nint ww_conflict(txn_write * tw1, txn_write * tw2)\n{\n    short is_regular_op1 = (tw1->query_type == QUERY_TYPE_UPDATE || tw1->query_type == QUERY_TYPE_DELETE);\n    short is_regular_op2 = (tw2->query_type == QUERY_TYPE_UPDATE || tw2->query_type == QUERY_TYPE_DELETE);\n\n    if((is_regular_op1 && !is_regular_op2) || (!is_regular_op1&&is_regular_op2))\n        return 0;\n\n    if(is_regular_op1)\n        return (txn_write_cmp((WORD) tw1, (WORD) tw2) == 0);\n    else\n        return queue_op_conflict(tw1, tw2);\n}\n\nint is_read_invalidated(txn_read * tr, txn_state * rts, db_t * db)\n{\n    // Check for conflicts with backend DB:\n\n    switch(tr->query_type)\n    {\n        case QUERY_TYPE_READ_COLS:\n        case QUERY_TYPE_READ_CELL:\n        {\n            return db_verify_cell_version(tr->start_primary_keys, tr->no_primary_keys, tr->start_clustering_keys, tr->no_clustering_keys, tr->table_key, tr->result_version, db);\n        }\n        case QUERY_TYPE_READ_ROW:\n        {\n            return db_verify_cell_version(tr->start_primary_keys, tr->no_primary_keys, NULL, 0, tr->table_key, tr->result_version, db);\n        }\n        case QUERY_TYPE_READ_INDEX:\n        {\n            return db_verify_index_version(tr->start_primary_keys, tr->idx_idx, tr->table_key, tr->result_version, db);\n        }\n        case QUERY_TYPE_READ_CELL_RANGE:\n        {\n            return db_verify_cell_range_version(tr->start_primary_keys, tr->no_primary_keys,\n                                                tr->start_clustering_keys, tr->end_clustering_keys, tr->no_clustering_keys, tr->table_key,\n                                                tr->range_result_keys, tr->range_result_versions, tr->no_range_results, db);\n        }\n        case QUERY_TYPE_READ_ROW_RANGE:\n        {\n            return db_verify_row_range_version(tr->start_primary_keys, tr->end_primary_keys, tr->no_primary_keys, tr->table_key,\n                                                tr->range_result_keys, tr->range_result_versions, tr->no_range_results, db);\n        }\n        case QUERY_TYPE_READ_INDEX_RANGE:\n        {\n            return db_verify_index_range_version(tr->idx_idx, tr->start_primary_keys, tr->end_primary_keys,\n                                                tr->range_result_keys, tr->range_result_versions, tr->no_range_results, tr->table_key, db);\n        }\n    }\n\n    // Check for conflicts with the other txn write sets:\n\n    // If exact (non-range) read, and not a secondary index query, create dummy write op on the same key path, to look it up in other txn's write set:\n\n    int is_exact_query = (tr->query_type == QUERY_TYPE_READ_COLS || tr->query_type == QUERY_TYPE_READ_CELL || tr->query_type == QUERY_TYPE_READ_ROW);\n    txn_write * dummy_tw_update = is_exact_query? get_dummy_txn_write(QUERY_TYPE_UPDATE, tr->start_primary_keys, tr->no_primary_keys, tr->start_clustering_keys, tr->no_clustering_keys, tr->table_key, 0) : NULL;\n\n#if (MULTI_THREADED == 1)\n    pthread_mutex_lock(db->txn_state_lock);\n#endif\n\n    for(snode_t * node=HEAD(db->txn_state); node!=NULL; node=NEXT(node))\n    {\n        assert(node->value != NULL);\n\n        txn_state * ts = (txn_state *) node->value;\n\n        if(ts->state != TXN_STATUS_VALIDATED || uuid_compare(rts->txnid, ts->txnid) == 0)\n            continue;\n\n        if(is_exact_query)\n        {\n            snode_t * write_op_n = skiplist_search(ts->write_set, (WORD) dummy_tw_update);\n\n            if(write_op_n != NULL)\n            {\n                assert(write_op_n->value != NULL);\n\n                txn_write * tw = (txn_write *) write_op_n->value;\n\n                if(rw_conflict(tr, tw, 0))\n                {\n#if (VERBOSE_TXNS > 0)\n                        log_debug(\"Invalidating txn due to rw conflict\");\n#endif\n\n#if (MULTI_THREADED == 1)\n                        pthread_mutex_unlock(db->txn_state_lock);\n#endif\n\n                        return 1;\n                }\n            }\n        }\n        else\n        // For range or index queries, we need to iterate the other txn write sets to see if any writes conflict with our reads:\n        {\n            for(snode_t * write_op_n=HEAD(ts->write_set); write_op_n!=NULL; write_op_n=NEXT(write_op_n))\n            {\n                assert(write_op_n->value != NULL);\n\n                txn_write * tw = (txn_write *) write_op_n->value;\n\n                if(rw_conflict(tr, tw, 1) && ts->state == TXN_STATUS_VALIDATED)\n                {\n#if (MULTI_THREADED == 1)\n                        pthread_mutex_unlock(db->txn_state_lock);\n#endif\n                    return 1;\n                }\n            }\n        }\n    }\n\n#if (MULTI_THREADED == 1)\n    pthread_mutex_unlock(db->txn_state_lock);\n#endif\n\n    return 0;\n}\n\nint is_write_invalidated(txn_write * tw, txn_state * rts, int * schema_status, db_t * db)\n{\n    // Check for invalidated queue reads / creation / deletion ops with backend DB:\n\n    *schema_status = 0;\n    switch(tw->query_type)\n    {\n        case QUERY_TYPE_READ_QUEUE:\n        {\n            int status = db_verify_cell_version(&tw->queue_id, 1, NULL, 0, tw->table_key, tw->prh_version, db);\n            if(status == DB_ERR_NO_TABLE || status == DB_ERR_NO_QUEUE)\n            {\n#if (VERBOSE_TXNS > 0)\n                log_debug(\"read_queue(%ld) invalidating txn\", tw->queue_id);\n#endif\n                *schema_status = 1;\n            }\n            return (status != 0);\n        }\n        case QUERY_TYPE_CREATE_QUEUE:\n        {\n            return (db_search(&tw->queue_id, tw->table_key, db) != NULL);\n        }\n        case QUERY_TYPE_DELETE_QUEUE:\n        case QUERY_TYPE_UNSUBSCRIBE_QUEUE:\n        {\n            return (db_search(&tw->queue_id, tw->table_key, db) == NULL);\n        }\n        case QUERY_TYPE_ENQUEUE:\n        case QUERY_TYPE_CONSUME_QUEUE:\n        case QUERY_TYPE_SUBSCRIBE_QUEUE:\n        {\n            if(db_search(&tw->queue_id, tw->table_key, db) == NULL)\n            {\n#if (VERBOSE_TXNS > 0)\n                log_debug(\"Query type %d (%ld) invalidating txn\", tw->query_type, tw->queue_id);\n#endif\n                *schema_status = 1;\n                return 1;\n            }\n            return 0;\n        }\n    }\n\n    // Check for WW conflicts with other txns' write sets:\n\n#if (MULTI_THREADED == 1)\n    pthread_mutex_lock(db->txn_state_lock);\n#endif\n\n    for(snode_t * node=HEAD(db->txn_state); node!=NULL; node=NEXT(node))\n    {\n        assert(node->value != NULL);\n\n        txn_state * ts = (txn_state *) node->value;\n\n        if(ts->state != TXN_STATUS_VALIDATED || uuid_compare(rts->txnid, ts->txnid) == 0)\n            continue;\n\n        if(tw->query_type == QUERY_TYPE_UPDATE || tw->query_type == QUERY_TYPE_DELETE)\n        // Regular ops\n        {\n            snode_t * write_op_n = skiplist_search(ts->write_set, (WORD) tw);\n\n            if(write_op_n != NULL)\n            {\n                assert(write_op_n->value != NULL);\n\n                txn_write * tw2 = (txn_write *) write_op_n->value;\n\n//              if(ww_conflict(tw, tw2, 0))\n//              {\n#if (VERBOSE_TXNS > 0)\n                    char uuid_str1[37], uuid_str2[37];\n                    uuid_unparse_lower(rts->txnid, uuid_str1);\n                    uuid_unparse_lower(ts->txnid, uuid_str2);\n\n                    log_debug(\"Invalidating txn due to ww conflict on table=%\" PRId64 \"/%\" PRId64 \", write_type=%d/%d, key=%\" PRId64 \"/%\" PRId64 \", txn=%s/%s\",\n                                (int64_t) tw->table_key, (int64_t) tw2->table_key,\n                                tw->query_type, tw2->query_type,\n                                ((int64_t *) tw->column_values)[0], ((int64_t *) tw2->column_values)[0],\n                                uuid_str2, uuid_str1);\n#endif\n\n#if (MULTI_THREADED == 1)\n                    pthread_mutex_unlock(db->txn_state_lock);\n#endif\n\n                    return 1;\n//              }\n            }\n        }\n        else\n        // Queue ops:\n        {\n            for(snode_t * write_op_n=HEAD(ts->write_set); write_op_n!=NULL; write_op_n=NEXT(write_op_n))\n            {\n                assert(write_op_n->value != NULL);\n\n                txn_write * tw2 = (txn_write *) write_op_n->value;\n\n                // No conflict between regular ops and queue ops:\n\n                if(tw->query_type == QUERY_TYPE_UPDATE || tw->query_type == QUERY_TYPE_DELETE)\n                    continue;\n\n                if(queue_op_conflict(tw, tw2))\n\n                {\n#if (MULTI_THREADED == 1)\n                    pthread_mutex_unlock(db->txn_state_lock);\n#endif\n                    return 1;\n                }\n            }\n        }\n    }\n\n#if (MULTI_THREADED == 1)\n    pthread_mutex_unlock(db->txn_state_lock);\n#endif\n\n    return 0;\n}\n\n\nint validate_txn(uuid_t * txnid, vector_clock * version, db_t * db)\n{\n    txn_state * ts = get_txn_state(txnid, db);\n    int schema_status = 0;\n    if(ts == NULL)\n        return NO_SUCH_TXN; // No such txn\n\n    assert(ts->state == TXN_STATUS_ACTIVE);\n\n    // Txn now gets a new version stamp:\n\n    set_version(ts, version);\n\n    for(snode_t * read_op_n=HEAD(ts->read_set); read_op_n!=NULL; read_op_n=NEXT(read_op_n))\n    {\n        if(read_op_n->value != NULL)\n        {\n            txn_read * tr = (txn_read *) read_op_n->value;\n\n            if(is_read_invalidated(tr, ts, db))\n            {\n                return VAL_STATUS_ABORT;\n            }\n        }\n    }\n\n    for(snode_t * write_op_n=HEAD(ts->write_set); write_op_n!=NULL; write_op_n=NEXT(write_op_n))\n    {\n        if(write_op_n->value != NULL)\n        {\n            txn_write * tw = (txn_write *) write_op_n->value;\n\n            if(is_write_invalidated(tw, ts, &schema_status, db))\n            {\n                return (schema_status == 0)?VAL_STATUS_ABORT:VAL_STATUS_ABORT_SCHEMA;\n            }\n        }\n    }\n\n    ts->state = TXN_STATUS_VALIDATED;\n\n    return VAL_STATUS_COMMIT;\n}\n\nint persist_write(txn_write * tw, vector_clock * version, db_t * db, unsigned int * fastrandstate)\n{\n    switch(tw->query_type)\n    {\n        case QUERY_TYPE_UPDATE:\n        {\n            // Note: This also updates or creates the version of the updated / created cell:\n\n            return db_insert_transactional(tw->column_values, tw->no_cols, tw->no_clustering_keys, tw->blob_size, version, tw->table_key, db, fastrandstate);\n        }\n        case QUERY_TYPE_DELETE:\n        {\n            // Update row tombstone version for handling shadow range reads and reads by incomplete partition / clustering key path?\n\n            return db_delete_row_transactional(tw->column_values, version, tw->table_key, db, fastrandstate); // TO DO: use tw->no_primary_keys and tw->no_clustering_keys\n        }\n        case QUERY_TYPE_ENQUEUE:\n        {\n            return enqueue(tw->column_values, tw->no_cols, tw->blob_size, tw->table_key, tw->queue_id, 1, db, fastrandstate);\n        }\n        case QUERY_TYPE_READ_QUEUE:\n        {\n            // Note: This also updates queue private read head version:\n\n            return set_private_read_head(tw->consumer_id, tw->shard_id, tw->app_id, tw->table_key, tw->queue_id, tw->new_read_head, version, 1, db);\n        }\n        case QUERY_TYPE_CONSUME_QUEUE:\n        {\n            return set_private_consume_head(tw->consumer_id, tw->shard_id, tw->app_id, tw->table_key, tw->queue_id, tw->new_consume_head, version, db);\n        }\n        case QUERY_TYPE_CREATE_QUEUE:\n        {\n            return create_queue(tw->table_key, tw->queue_id, version, 1, db, fastrandstate);\n        }\n        case QUERY_TYPE_DELETE_QUEUE:\n        {\n            // Note: This also updates queue tombstone version (if queue was not already deleted by a different txn, in which case earliest deletion timestamp is kept):\n\n            return delete_queue(tw->table_key, tw->queue_id, version, 1, db, fastrandstate);\n        }\n        default:\n        {\n            assert(0);\n        }\n    }\n\n    return 0;\n}\n\nint persist_txn(txn_state * ts, db_t * db, unsigned int * fastrandstate)\n{\n    int res = 0;\n\n    // Txn needs to have received a commit version by this point:\n    assert(ts->version != NULL);\n\n#if (VERBOSE_TXNS_PERSIST > 0)\n        char uuid_str[37];\n        uuid_unparse_lower(ts->txnid, uuid_str);\n        log_debug(\"BACKEND: Txn %s has %d writes\", uuid_str, ts->write_set->no_items);\n#endif\n\n    for(snode_t * write_op_n=HEAD(ts->write_set); write_op_n!=NULL; write_op_n=NEXT(write_op_n))\n    {\n        if(write_op_n->value != NULL)\n        {\n            txn_write * tw = (txn_write *) write_op_n->value;\n\n#if (VERBOSE_TXNS_PERSIST > 0)\n            log_debug(\"BACKEND: Txn %s attempting to persist write of type %d\", uuid_str, tw->query_type);\n#endif\n\n            res = persist_write(tw, ts->version, db, fastrandstate);\n\n#if (VERBOSE_TXNS_PERSIST > 0)\n            log_debug(\"BACKEND: Txn %s successfully persisted write of type %d\", uuid_str, tw->query_type);\n#endif\n\n            if(res != 0)\n                log_debug(\"BACKEND: persist_write for txn, of type %d returned %d\", tw->query_type, res);\n        }\n    }\n\n    close_txn_state(ts, db);\n\n    return res;\n}\n\nint abort_txn(uuid_t * txnid, db_t * db)\n{\n    return close_txn(txnid, db);\n}\n\nint commit_txn(uuid_t * txnid, vector_clock * version, db_t * db, unsigned int * fastrandstate)\n{\n    txn_state * ts = get_txn_state(txnid, db);\n    if(ts == NULL)\n        return NO_SUCH_TXN; // No such txn\n\n#if (VERBOSE_TXNS > 0)\n    char uuid_str[37];\n    uuid_unparse_lower(*txnid, uuid_str);\n#endif\n#if (VERBOSE_TXNS > 1)\n    log_debug(\"BACKEND: Attempting to validate txn %s\", uuid_str);\n#endif\n\n    int res = validate_txn(txnid, version, db);\n\n#if (VERBOSE_TXNS > 1)\n    log_debug(\"BACKEND: validate txn %s returned %d\", uuid_str, res);\n#endif\n\n    if(res == VAL_STATUS_COMMIT)\n    {\n        res = persist_txn(ts, db, fastrandstate);\n\n#if (VERBOSE_TXNS > 0)\n        log_debug(\"BACKEND: persist txn %s returned %d\", uuid_str, res);\n#endif\n    }\n    else if(res == VAL_STATUS_ABORT || res == VAL_STATUS_ABORT_SCHEMA)\n    {\n        res = abort_txn(txnid, db);\n\n#if (VERBOSE_TXNS > 0)\n        log_debug(\"BACKEND: abort txn %s returned %d\", uuid_str, res);\n#endif\n    }\n    else\n    {\n        assert(0);\n    }\n\n    return res;\n}\n\n\nint db_insert_in_txn(WORD * column_values, int no_cols, int no_primary_keys, int no_clustering_keys, size_t blob_size, WORD table_key, uuid_t * txnid, db_t * db, unsigned int * fastrandstate)\n{\n    txn_state * ts = get_txn_state(txnid, db);\n    if(ts == NULL)\n        return NO_SUCH_TXN; // No such txn\n\n    return add_write_to_txn(QUERY_TYPE_UPDATE, column_values, no_cols, no_primary_keys, no_clustering_keys, blob_size, table_key, ts, fastrandstate);\n}\n\ndb_row_t* db_search_in_txn(WORD* primary_keys, int no_primary_keys, WORD table_key, uuid_t * txnid, db_t * db, unsigned int * fastrandstate)\n{\n    txn_state * ts = get_txn_state(txnid, db);\n    if(ts == NULL)\n        return NULL; // No such txn\n\n    db_row_t* result = db_search(primary_keys, table_key, db);\n\n    // Note that if result == NULL (no such row), we still add that query to the txn read set (to allow txn to be invalidated by \"shadow writes\")\n\n    int ret = add_row_read_to_txn(primary_keys, no_primary_keys, table_key, result, ts, fastrandstate);\n\n    assert(ret == 0);\n\n    return result;\n}\n\nint db_range_search_in_txn(WORD* start_primary_keys, WORD* end_primary_keys, int no_primary_keys,\n                            snode_t** start_row, snode_t** end_row,\n                            WORD table_key, uuid_t * txnid, db_t * db, unsigned int * fastrandstate)\n{\n    txn_state * ts = get_txn_state(txnid, db);\n    if(ts == NULL)\n        return NO_SUCH_TXN; // No such txn\n\n    int no_rows = db_range_search(start_primary_keys, end_primary_keys, start_row, end_row, table_key, db);\n\n    // Note that if no_rows == 0 (no rows read), we still add that query to the txn read set (to allow txn to be invalidated by \"shadow writes\")\n\n    return add_row_range_read_to_txn(start_primary_keys, end_primary_keys, no_primary_keys, table_key, *start_row, *end_row, no_rows, ts, fastrandstate);\n}\n\n\ndb_row_t* db_search_clustering_in_txn(WORD* primary_keys, int no_primary_keys, WORD* clustering_keys, int no_clustering_keys, WORD table_key, uuid_t * txnid, db_t * db, unsigned int * fastrandstate)\n{\n    txn_state * ts = get_txn_state(txnid, db);\n    if(ts == NULL)\n        return NULL; // No such txn\n\n    db_row_t* result = db_search_clustering(primary_keys, clustering_keys, no_clustering_keys, table_key, db);\n\n    // Note that if result == NULL (no such row), we still add that query to the txn read set (to allow txn to be invalidated by \"shadow writes\")\n\n    int ret = add_cell_read_to_txn(primary_keys, no_primary_keys, clustering_keys, no_clustering_keys, table_key, result, ts, fastrandstate);\n\n    assert(ret == 0);\n\n    return result;\n}\n\nint db_range_search_clustering_in_txn(WORD* primary_keys, int no_primary_keys, WORD* start_clustering_keys, WORD* end_clustering_keys, int no_clustering_keys, snode_t** start_row, snode_t** end_row, WORD table_key, uuid_t * txnid, db_t * db, unsigned int * fastrandstate)\n{\n    txn_state * ts = get_txn_state(txnid, db);\n    if(ts == NULL)\n        return NO_SUCH_TXN; // No such txn\n\n    // Note that if ret == 0 (no rows read), we still add that query to the txn read set (to allow txn to be invalidated by \"shadow writes\")\n\n    int no_results = db_range_search_clustering(primary_keys, start_clustering_keys, end_clustering_keys, no_clustering_keys, start_row, end_row, table_key, db);\n\n    return add_cell_range_read_to_txn(primary_keys, no_primary_keys, start_clustering_keys,\n                                        end_clustering_keys, no_clustering_keys, table_key,\n                                        *start_row, *end_row, no_results, ts, fastrandstate);\n}\n\n// WORD* db_search_columns_in_txn(WORD* primary_keys, int no_primary_keys, WORD* clustering_keys, int* column_idxs, int no_columns, WORD table_key, uuid_t * txnid, db_t * db, unsigned int * fastrandstate)\ndb_row_t* db_search_columns_in_txn(WORD* primary_keys, int no_primary_keys, WORD* clustering_keys, int no_clustering_keys, WORD* col_keys, int no_columns, WORD table_key, uuid_t * txnid, db_t * db, unsigned int * fastrandstate)\n{\n    assert (0); // This won't work until db_search_columns is refactored as per below:\n    return 0;\n\n/*\n    txn_state * ts = get_txn_state(txnid, db);\n    if(ts == NULL)\n        return NO_SUCH_TXN; // No such txn\n\n//  db_search_columns(primary_keys, clustering_keys, int* column_idxs, no_columns, table_key, db_t * db);\n\n    db_row_t* result = db_search_columns_result(primary_keys, clustering_keys, col_keys, no_columns, table_key, db);\n\n    return add_col_read_to_txn(primary_keys, no_primary_keys, clustering_keys, no_clustering_keys,\n                                col_keys, no_columns, table_key, result, ts, fastrandstate);\n*/\n}\n\ndb_row_t* db_search_index_in_txn(WORD index_key, int idx_idx, WORD table_key, uuid_t * txnid, db_t * db, unsigned int * fastrandstate)\n{\n    txn_state * ts = get_txn_state(txnid, db);\n    if(ts == NULL)\n        return NULL; // No such txn\n\n    db_row_t* result = db_search_index(index_key, idx_idx, table_key, db);\n\n    int ret = add_index_read_to_txn(&index_key, idx_idx, table_key, result, ts, fastrandstate);\n\n    assert(ret == 0);\n\n    return result;\n}\n\nint db_range_search_index_in_txn(int idx_idx, WORD start_idx_key, WORD end_idx_key, snode_t** start_row, snode_t** end_row, WORD table_key, uuid_t * txnid, db_t * db, unsigned int * fastrandstate)\n{\n    txn_state * ts = get_txn_state(txnid, db);\n    if(ts == NULL)\n        return NO_SUCH_TXN; // No such txn\n\n    int no_results = db_range_search_index(idx_idx, start_idx_key, end_idx_key, start_row, end_row, table_key, db);\n\n    return add_index_range_read_to_txn(idx_idx, &start_idx_key, &end_idx_key, *start_row, *end_row, no_results, table_key, ts, fastrandstate);\n}\n\nint db_delete_row_in_txn(WORD* primary_keys, int no_primary_keys, WORD table_key, uuid_t * txnid, db_t * db, unsigned int * fastrandstate)\n{\n    txn_state * ts = get_txn_state(txnid, db);\n    if(ts == NULL)\n        return NO_SUCH_TXN; // No such txn\n\n    return add_write_to_txn(QUERY_TYPE_DELETE, primary_keys, no_primary_keys, no_primary_keys, 0, 0, table_key, ts, fastrandstate);\n}\n\nint db_delete_cell_in_txn(WORD* keys, int no_primary_keys, int no_clustering_keys, WORD table_key, uuid_t * txnid, db_t * db, unsigned int * fastrandstate)\n{\n    txn_state * ts = get_txn_state(txnid, db);\n    if(ts == NULL)\n        return NO_SUCH_TXN; // No such txn\n\n    return add_write_to_txn(QUERY_TYPE_DELETE, keys, no_primary_keys+no_clustering_keys, no_primary_keys, no_clustering_keys, 0, table_key, ts, fastrandstate);\n}\n\nint db_delete_by_index_in_txn(WORD index_key, int idx_idx, WORD table_key, uuid_t * txnid, db_t * db, unsigned int * fastrandstate)\n{\n    assert (0); // Not supported yet\n    return 0;\n}\n\nint db_update_in_txn(int * col_idxs, int no_cols, size_t blob_size, WORD * column_values, WORD table_key, uuid_t * txnid, db_t * db, unsigned int * fastrandstate)\n{\n    assert (0); // Not supported in new schema-less model\n    return 0;\n}\n\n// Queue ops:\n\nint enqueue_in_txn(WORD * column_values, int no_cols, size_t blob_size, WORD table_key, WORD queue_id, uuid_t * txnid, db_t * db, unsigned int * fastrandstate)\n{\n    txn_state * ts = get_txn_state(txnid, db);\n    if(ts == NULL)\n        return NO_SUCH_TXN; // No such txn\n\n    return add_enqueue_to_txn(column_values, no_cols, blob_size, table_key, queue_id, ts, fastrandstate);\n}\n\nint read_queue_in_txn(WORD consumer_id, WORD shard_id, WORD app_id, WORD table_key, WORD queue_id,\n        int max_entries, int * entries_read, int64_t * new_read_head,\n        snode_t** start_row, snode_t** end_row, uuid_t * txnid,\n        db_t * db, unsigned int * fastrandstate)\n{\n    txn_state * ts = get_txn_state(txnid, db);\n    if(ts == NULL)\n        return NO_SUCH_TXN; // No such txn\n\n    int64_t prev_read_head = -1;\n\n    // Lookup previously existing read head in this txn's read set:\n\n    for(snode_t * write_op_n=HEAD(ts->write_set); write_op_n!=NULL; write_op_n=NEXT(write_op_n))\n    {\n        if(write_op_n->value != NULL)\n        {\n            txn_write * tw = (txn_write *) write_op_n->value;\n\n            if(tw->query_type == QUERY_TYPE_READ_QUEUE && tw->table_key == table_key &&\n                tw->queue_id == queue_id && tw->consumer_id == consumer_id &&\n                tw->shard_id == shard_id && tw->app_id == app_id)\n            {\n                prev_read_head = tw->new_read_head;\n                break;\n            }\n        }\n    }\n\n    vector_clock * prh_version = NULL;\n\n    int status = peek_queue(consumer_id, shard_id, app_id, table_key, queue_id,\n            max_entries, prev_read_head, entries_read, new_read_head, &prh_version,\n            start_row, end_row, db);\n\n    int ret = add_read_queue_to_txn(consumer_id, shard_id, app_id, table_key, queue_id,\n                                    *new_read_head, prh_version, ts, fastrandstate);\n\n    return (ret==0)?(status):(ret);\n}\n\nint consume_queue_in_txn(WORD consumer_id, WORD shard_id, WORD app_id, WORD table_key, WORD queue_id,\n                    int64_t new_consume_head, uuid_t * txnid, db_t * db, unsigned int * fastrandstate)\n{\n    txn_state * ts = get_txn_state(txnid, db);\n    if(ts == NULL)\n        return NO_SUCH_TXN; // No such txn\n\n    return add_consume_queue_to_txn(consumer_id, shard_id, app_id, table_key, queue_id,\n            new_consume_head, ts, fastrandstate);\n}\n\nint subscribe_queue_in_txn(WORD consumer_id, WORD shard_id, WORD app_id, WORD table_key, WORD queue_id,\n                        queue_callback * callback, int64_t * prev_read_head, int64_t * prev_consume_head,\n                        uuid_t * txnid, db_t * db, unsigned int * fastrandstate)\n{\n    assert (0); // Not implemented\n    return 0;\n}\n\nint unsubscribe_queue_in_txn(WORD consumer_id, WORD shard_id, WORD app_id, WORD table_key, WORD queue_id,\n                                uuid_t * txnid, db_t * db, unsigned int * fastrandstate)\n{\n    assert (0); // Not implemented\n    return 0;\n}\n\nint create_queue_in_txn(WORD table_key, WORD queue_id, uuid_t * txnid, db_t * db, unsigned int * fastrandstate)\n{\n    txn_state * ts = get_txn_state(txnid, db);\n    if(ts == NULL)\n        return NO_SUCH_TXN; // No such txn\n\n    return add_create_queue_to_txn(table_key, queue_id, ts, fastrandstate);\n}\n\nint delete_queue_in_txn(WORD table_key, WORD queue_id, uuid_t * txnid, db_t * db, unsigned int * fastrandstate)\n{\n    txn_state * ts = get_txn_state(txnid, db);\n    if(ts == NULL)\n        return NO_SUCH_TXN; // No such txn\n\n    return add_delete_queue_to_txn(table_key, queue_id, ts, fastrandstate);\n}\n"
  },
  {
    "path": "backend/txns.h",
    "content": "/*\n * txns.h\n *\n *      Author: aagapi\n */\n\n#ifndef BACKEND_TXNS_H_\n#define BACKEND_TXNS_H_\n\n#include \"txn_state.h\"\n#include \"queue.h\"\n\n#define VAL_STATUS_COMMIT 0\n#define VAL_STATUS_ABORT 1\n\n#define DUPLICATE_TXN -2\n#define NO_SUCH_TXN -3\n\n\n// DB queries:\n\ntxn_state * get_txn_state(uuid_t * txnid, db_t * db);\nuuid_t * new_txn(db_t * db, unsigned int * seedptr);\nint close_txn(uuid_t * txnid, db_t * db);\nint close_txn_state(txn_state * ts, db_t * db);\nint validate_txn(uuid_t * txnid, vector_clock * version, db_t * db);\nint abort_txn(uuid_t * txnid, db_t * db);\nint commit_txn(uuid_t * txnid, vector_clock * version, db_t * db, unsigned int * fastrandstate);\n\nint db_insert_in_txn(WORD * column_values, int no_cols, int no_primary_keys, int no_clustering_keys, size_t blob_size, WORD table_key, uuid_t * txnid, db_t * db, unsigned int * fastrandstate);\n\ndb_row_t* db_search_in_txn(WORD* primary_keys, int no_primary_keys, WORD table_key, uuid_t * txnid, db_t * db, unsigned int * fastrandstate);\n\ndb_row_t* db_search_clustering_in_txn(WORD* primary_keys, int no_primary_keys, WORD* clustering_keys, int no_clustering_keys, WORD table_key,\n                                        uuid_t * txnid, db_t * db, unsigned int * fastrandstate);\ndb_row_t* db_search_columns_in_txn(WORD* primary_keys, int no_primary_keys, WORD* clustering_keys, int no_clustering_keys,\n                                    WORD* col_keys, int no_columns, WORD table_key,\n                                    uuid_t * txnid, db_t * db, unsigned int * fastrandstate);\ndb_row_t* db_search_index_in_txn(WORD index_key, int idx_idx, WORD table_key, uuid_t * txnid, db_t * db, unsigned int * fastrandstate);\n\nint db_range_search_in_txn(WORD* start_primary_keys, WORD* end_primary_keys, int no_primary_keys,\n                            snode_t** start_row, snode_t** end_row,\n                            WORD table_key, uuid_t * txnid, db_t * db, unsigned int * fastrandstate);\nint db_range_search_clustering_in_txn(WORD* primary_keys, int no_primary_keys,\n                                     WORD* start_clustering_keys, WORD* end_clustering_keys, int no_clustering_keys,\n                                     snode_t** start_row, snode_t** end_row,\n                                     WORD table_key, uuid_t * txnid, db_t * db, unsigned int * fastrandstate);\nint db_range_search_index_in_txn(int idx_idx, WORD start_idx_key, WORD end_idx_key,\n                                snode_t** start_row, snode_t** end_row,\n                                WORD table_key, uuid_t * txnid, db_t * db, unsigned int * fastrandstate);\n\nint db_delete_row_in_txn(WORD* primary_keys, int no_primary_keys, WORD table_key, uuid_t * txnid, db_t * db, unsigned int * fastrandstate);\nint db_delete_cell_in_txn(WORD* keys, int no_primary_keys, int no_clustering_keys, WORD table_key, uuid_t * txnid, db_t * db, unsigned int * fastrandstate);\nint db_delete_by_index_in_txn(WORD index_key, int idx_idx, WORD table_key, uuid_t * txnid, db_t * db, unsigned int * fastrandstate);\nint db_update_in_txn(int * col_idxs, int no_cols, size_t blob_size, WORD * column_values, WORD table_key, uuid_t * txnid, db_t * db, unsigned int * fastrandstate);\n\n// Queue ops:\n\nint enqueue_in_txn(WORD * column_values, int no_cols, size_t blob_size, WORD table_key, WORD queue_id, uuid_t * txnid, db_t * db, unsigned int * fastrandstate);\nint read_queue_in_txn(WORD consumer_id, WORD shard_id, WORD app_id, WORD table_key, WORD queue_id,\n        int max_entries, int * entries_read, int64_t * new_read_head,\n        snode_t** start_row, snode_t** end_row, uuid_t * txnid,\n        db_t * db, unsigned int * fastrandstate);\nint consume_queue_in_txn(WORD consumer_id, WORD shard_id, WORD app_id, WORD table_key, WORD queue_id,\n                    int64_t new_consume_head, uuid_t * txnid, db_t * db, unsigned int * fastrandstate);\nint subscribe_queue_in_txn(WORD consumer_id, WORD shard_id, WORD app_id, WORD table_key, WORD queue_id,\n                        queue_callback * callback, int64_t * prev_read_head, int64_t * prev_consume_head,\n                        uuid_t * txnid, db_t * db, unsigned int * fastrandstate);\nint unsubscribe_queue_in_txn(WORD consumer_id, WORD shard_id, WORD app_id, WORD table_key, WORD queue_id,\n                                uuid_t * txnid, db_t * db, unsigned int * fastrandstate);\nint create_queue_in_txn(WORD table_key, WORD queue_id, uuid_t * txnid, db_t * db, unsigned int * fastrandstate);\nint delete_queue_in_txn(WORD table_key, WORD queue_id, uuid_t * txnid, db_t * db, unsigned int * fastrandstate);\n\n// Lower level API:\n\nint persist_write(txn_write * tw, vector_clock * version, db_t * db, unsigned int * fastrandstate);\nint persist_txn(txn_state * ts, db_t * db, unsigned int * fastrandstate);\n\n#endif /* BACKEND_TXNS_H_ */\n"
  },
  {
    "path": "base/.gitignore",
    "content": ""
  },
  {
    "path": "base/Build.act",
    "content": "name = \"base\"\nfingerprint = 0xc0b4fe61c0b4fe61\n\ndependencies = {\n    \"actondb\": (\n        path=\"../backend/\"\n    )\n}\n\nzig_dependencies = {\n    \"libbsdnt\": (\n        path=\"../deps/libbsdnt/\"\n    ),\n    \"libgc\": (\n        path=\"../deps/libgc/\"\n    ),\n    \"libmbedtls\": (\n        path=\"../deps/mbedtls/\"\n    ),\n    \"libnetstring\": (\n        path=\"../deps/libnetstring/\"\n    ),\n    \"libpcre2\": (\n        path=\"../deps/pcre2/\"\n    ),\n    \"libprotobuf_c\": (\n        path=\"../deps/libprotobuf_c/\"\n    ),\n    \"libsnappy\": (\n        path=\"../deps/libsnappy_c/\"\n    ),\n    \"libtlsuv\": (\n        path=\"../deps/tlsuv/\"\n    ),\n    \"libutf8proc\": (\n        path=\"../deps/libutf8proc/\"\n    ),\n    \"libuuid\": (\n        path=\"../deps/libuuid/\"\n    ),\n    \"libuv\": (\n        path=\"../deps/libuv/\"\n    ),\n    \"libxml2\": (\n        path=\"../deps/libxml2/\"\n    ),\n    \"libyyjson\": (\n        path=\"../deps/libyyjson/\"\n    )\n}\n"
  },
  {
    "path": "base/CLAUDE.md",
    "content": "# Acton Base - Standard Library & Runtime System\n\nThe base directory contains the Acton standard library and runtime system (RTS), providing core functionality for all Acton programs.\n\n## Quick Reference\n\n### Directory Structure\n```\nbase/\n├── src/                  # Standard library modules (Acton)\n├── builtin/             # Builtin types implementation (C)\n├── rts/                 # Runtime system (C/Zig)\n├── stdlib/              # Additional stdlib components\n├── build.zig            # Build configuration\n└── Build.act          # Package definition\n```\n\n### Build Commands\n```bash\n# Build base (included in main build)\nmake\n\n# Run stdlib tests\nmake test-stdlib\n\n# Build specific module\ncd base && zig build\n```\n\n## Standard Library Modules (`src/`)\n\n### Core Modules\n\n#### `__builtin__.act`\n- Fundamental types and functions\n- Imported implicitly in all modules\n- Interfaces to C builtins\n\n#### `file.act` / `file.ext.c`\n- File I/O operations\n- Path manipulation\n- Directory operations\n\n#### `net.act` / `net.ext.c`\n- TCP/UDP networking\n- DNS resolution\n- Socket operations\n\n#### `process.act` / `process.ext.c`\n- Process spawning\n- Environment variables\n- Signal handling\n\n#### `time.act` / `time.ext.c`\n- Time operations\n- Sleep/delay functions\n- Time formatting\n\n### Data Processing\n\n#### `json.act` / `json.ext.c`\n- JSON parsing and generation\n- Type-safe JSON handling\n\n#### `xml.act` / `xml.ext.c`\n- XML parsing\n- DOM manipulation\n\n#### `base64.act` / `base64.ext.c`\n- Base64 encoding/decoding\n\n### Advanced Modules\n\n#### `http.act`\n- HTTP client/server\n- Request/response handling\n- WebSocket support\n\n#### `re.act` / `re.ext.c`\n- Regular expressions\n- Pattern matching\n- String substitution\n\n#### `numpy.act` / `numpy.c`\n- Numerical arrays\n- Mathematical operations\n- Compatible subset of NumPy\n\n## Builtin Types (`builtin/`)\n\n### Type Implementation Pattern\nEach builtin type typically has:\n```c\n// type_name.h - Header with struct definition\ntypedef struct {\n    // ... internal representation\n} ActonType;\n\n// type_name.c - Implementation\n// - Constructor functions\n// - Method implementations\n// - Protocol implementations\n// - Memory management\n```\n\n### Core Types\n\n#### Numeric Types\n- `int.c/h` - Arbitrary precision integers\n- `float.c/h` - 64-bit floating point\n- `complex.c/h` - Complex numbers\n- `i16.c/h`, `i32.c/h`, `i64.c/h` - Fixed-size integers\n- `u16.c/h`, `u32.c/h`, `u64.c/h` - Unsigned integers\n\n#### Collections\n- `list.c/h` - Dynamic arrays\n- `dict.c/h` - Hash maps\n- `set.c/h` - Hash sets\n- `tuple.c/h` - Immutable sequences\n\n#### Text and Binary\n- `str.c/h` - Unicode strings\n- `bytes.c/h` - Binary data\n\n### Memory Management\nAll builtin types follow Acton's memory model:\n- Reference counting with cycle detection\n- Automatic memory management\n- C integration points\n\n## Runtime System (`rts/`)\n\n### Core Components\n\n#### `rts.c/h`\n- Main runtime initialization\n- Actor system setup\n- Scheduler initialization\n\n#### `q.c/h`\n- Actor message queues\n- Lock-free implementations\n- Message routing\n\n#### `io.c/h`\n- Async I/O with libuv\n- File descriptors\n- Network operations\n\n#### `gc.zig`\n- Garbage collector\n- Reference counting\n- Cycle detection\n\n### Actor Runtime\n- Lightweight actors\n- Message passing\n- Scheduling\n- Distribution support\n\n## Adding Standard Library Modules\n\n### 1. Pure Acton Module\n```acton\n# src/mymodule.act\ndef my_function(x: int) -> int:\n    return x * 2\n\nclass MyClass:\n    def method(self) -> str:\n        return \"hello\"\n```\n\n### 2. Module with C Extension\n```acton\n# src/mymodule.act\n# C functions are declared as external\ndef native_function(x: int) -> int:\n    NotImplemented\n```\n\n```c\n// src/mymodule.ext.c\n#include <acton.h>\n\nB_int native_function(B_int x) {\n    return intFromInt(asInt(x) * 2);\n}\n```\n\n### 3. Update Configuration\n```toml\n# base/Build.act\n[dependencies]\nmymodule = { path = \"src/mymodule.act\" }\n```\n\n## Working with Builtins\n\n### Adding Methods to Builtin Types\n\n1. **Declare in Acton** (`__builtin__.act`):\n```acton\nextension list[T]:\n    def my_new_method(self) -> T:\n        NotImplemented\n```\n\n2. **Implement in C** (`list.c`):\n```c\nB_value list_my_new_method(B_list self) {\n    // Implementation\n    return result;\n}\n```\n\n3. **Register Method** (`list.c`):\n```c\nstatic struct method_entry list_methods[] = {\n    {\"my_new_method\", (void*)list_my_new_method},\n    // ...\n};\n```\n\n### Memory Management in C Extensions\n\n```c\n// Allocate Acton object\nB_str result = (B_str)GC_MALLOC(sizeof(struct B_str));\nresult->_class = &str_class;\n\n// Reference counting\nINCREF(obj);  // Increase reference\nDECREF(obj);  // Decrease reference\n\n// Conversion helpers\nint64_t val = asInt(acton_int);\nB_int result = intFromInt(val);\n```\n\n## Testing\n\n### Unit Tests\n- Place in `test/stdlib_auto/`\n- Naming: `test_module.act`\n- Auto-discovered by test runner\n\n### C Extension Tests\n- Test through Acton interface\n- Use `testing` module assertions\n- Verify memory management\n\n### Performance Tests\n- Use `test/perf/` for benchmarks\n- Compare against Python/C baselines\n- Track regression\n\n## Common Patterns\n\n### Async Operations\n```c\n// In .ext.c file\nvoid async_operation(B_actor self, B_callback cb) {\n    // Start async work\n    uv_work_t *req = malloc(sizeof(uv_work_t));\n    req->data = cb;\n    \n    uv_queue_work(uv_default_loop(), req, \n                  do_work, after_work);\n}\n```\n\n### Error Handling\n```c\n// Throw Acton exception from C\nif (error_condition) {\n    B_raise(B_ValueError, \"Error message\");\n    return NULL;\n}\n```\n\n### Protocol Implementation\n```c\n// Implement protocol for type\nstatic B_bool str_eq(B_str self, B_value other) {\n    if (other->_class != &str_class) \n        return B_False;\n    return strcmp(self->data, ((B_str)other)->data) == 0 \n           ? B_True : B_False;\n}\n```\n\n## Performance Guidelines\n\n1. **String Operations**\n   - Use views when possible\n   - Avoid unnecessary copies\n   - Cache length calculations\n\n2. **Collections**\n   - Preallocate when size known\n   - Use appropriate data structure\n   - Consider memory locality\n\n3. **I/O Operations**\n   - Always async in actors\n   - Buffer when appropriate\n   - Use libuv efficiently\n\n## Debugging\n\n### Print Debugging\n```c\n// In C extensions\nfprintf(stderr, \"Debug: value=%ld\\n\", asInt(val));\n\n// Force flush\nfflush(stderr);\n```\n\n### GDB\n```bash\n# Run with GDB\ngdb ./program\n(gdb) break function_name\n(gdb) run\n```\n\n### Memory Debugging\n- Use Valgrind for leaks\n- Enable GC debugging\n- Check reference counts\n\n## Integration Notes\n\n- Standard library available to all Acton programs\n- Modules lazy-loaded on import\n- C extensions loaded dynamically\n- Type information preserved at runtime"
  },
  {
    "path": "base/__root.zig",
    "content": "const std = @import(\"std\");\n\nconst acton = @import(\"acton.zig\");\nconst gc = @import(\"rts/gc.zig\");\n\nexport fn base64Q_encode(data: *acton.bytes) callconv(.c) *acton.bytes {\n    const alloc = gc.allocator();\n    const encoder = std.base64.standard.Encoder;\n    // For possible Unicode input, bytes and chars may not be 1:1\n    const data_len: usize = @intCast(data.nbytes);\n    const out_len = encoder.calcSize(data_len);\n    const buffer = alloc.alloc(u8, out_len) catch @panic(\"OOM\");\n    const data_slice = data.str[0..data_len];\n    const encoded = encoder.encode(buffer, data_slice);\n\n    const res = alloc.create(acton.bytes) catch @panic(\"OOM\");\n    res.* = .{\n        .class = data.class,\n        .nbytes = @intCast(out_len),\n        .str = @as([*:0]const u8, @ptrCast(encoded.ptr))\n    };\n    return res;\n}\n\nexport fn base64Q_decode(data: *acton.bytes) callconv(.c) *acton.bytes {\n    const alloc = gc.allocator();\n    const decoder = std.base64.standard.Decoder;\n    // Convert null-terminated string to slice for decoder\n    const data_len: usize = @intCast(data.nbytes);\n    const data_slice = data.str[0..data_len];\n    // And then compute the exact number of bytes we need to decode, without padding\n    const out_len = decoder.calcSizeForSlice(data_slice) catch {\n        acton.raise_ValueError(\"Invalid base64 input data\");\n        unreachable; // raise above does longjmp so this is unreachable\n    };\n    const buffer = alloc.alloc(u8, out_len) catch @panic(\"OOM\");\n    decoder.decode(buffer, data_slice) catch unreachable;\n\n    const res = alloc.create(acton.bytes) catch @panic(\"OOM\");\n    res.* = .{\n        .class = data.class,\n        .nbytes = @intCast(out_len),\n        .str = @as([*:0]const u8, @ptrCast(buffer.ptr))\n    };\n    return res;\n}\n\nexport fn zig_crypto_hash_md5_init() callconv(.c) *std.crypto.hash.Md5 {\n    const alloc = gc.allocator();\n    const hasher_ptr = alloc.create(std.crypto.hash.Md5) catch {\n        unreachable(\"OOM while allocating Md5 hasher\");\n    };\n    hasher_ptr.* = std.crypto.hash.Md5.init(.{});\n\n    return hasher_ptr;\n}\n\nexport fn zig_crypto_hash_md5_update(hasher: *std.crypto.hash.Md5, data: *acton.bytes) callconv(.c) void {\n    const len: usize = @intCast(data.nbytes); // destination type from context\n    const slice = data.str[0..len];\n    hasher.update(slice);\n}\n\nexport fn zig_crypto_hash_md5_finalize(hasher: *std.crypto.hash.Md5, output: *acton.bytes) callconv(.c) void {\n    const digest_len = 16;\n    const out_slice: *[16]u8 = @as([*]u8, @ptrCast(@constCast(output.str)))[0..digest_len];\n    hasher.final(out_slice);\n}\n\nexport fn zig_hash_wyhash_init(seed: u64) callconv(.c) *std.hash.Wyhash {\n    const alloc = gc.allocator();\n    const hasher_ptr = alloc.create(std.hash.Wyhash) catch {\n        acton.raise_MemoryError(\"OOM while allocating Wyhash hasher\");\n        unreachable; // raise above does longjmp so this is unreachable\n    };\n    hasher_ptr.* = std.hash.Wyhash.init(seed);\n\n    return hasher_ptr;\n}\n\nexport fn zig_hash_wyhash_update(hasher: *std.hash.Wyhash, data: *acton.bytes) callconv(.c) void {\n    const len: usize = @intCast(data.nbytes); // destination type from context\n    const slice = data.str[0..len];\n    hasher.update(slice);\n}\n\nexport fn zig_hash_wyhash_final(hasher: *std.hash.Wyhash) callconv(.c) u64 {\n    return hasher.final();\n}\n\nexport fn zig_hash_wyhash_hash(seed: u64, data: *acton.bytes) callconv(.c) u64 {\n    const len: usize = @intCast(data.nbytes); // destination type from context\n    const slice = data.str[0..len];\n    return std.hash.Wyhash.hash(seed, slice);\n}\n"
  },
  {
    "path": "base/acton.zig",
    "content": "const std = @import(\"std\");\nconst expect = std.testing.expect;\nconst c_acton = @cImport({\n    @cInclude(\"builtin/builtin.h\");\n});\nconst gc = @import(\"rts/gc.zig\");\n\n// B_bytes\npub const bytes = extern struct {\n    class: usize,\n    nbytes: i32,              // length of str in bytes\n    str: [*]const u8            // str is UTF-8 encoded.\n};\n\n// B_NoneType\npub const none = extern struct {\n    class: usize,\n};\n\n// B_str\npub const str = extern struct {\n    class: usize,\n    nbytes: i32,              // length of str in bytes\n    nchars: i32,              // length of str in Unicode chars\n    str: [*:0]const u8            // str is UTF-8 encoded.\n};\n\n// B_ValueError\npub const ValueError = extern struct {\n    class: *c_acton.B_ValueErrorG_class,\n    error_message: c_acton.B_str,\n};\n\n// This is the equivalent of the expanded macro in C:\n//   $NEW(B_ValueError,to$str(message))\npub fn new_ValueError(message: []const u8) *c_acton.B_ValueError {\n    const alloc = gc.allocator();\n\n    const error_ptr = alloc.create(ValueError) catch @panic(\"OOM\");\n    const c_error_message = @constCast(message.ptr);\n    const error_message_ptr = c_acton.to_str_noc(c_error_message);\n    error_ptr.* = .{ .class = @ptrCast(&c_acton.B_ValueErrorG_methods), .error_message = null };\n    if (error_ptr.class.__init__) |init_fn| {\n        _ = init_fn(@ptrCast(error_ptr), error_message_ptr);\n    }\n    return @ptrCast(error_ptr);\n}\n\n// This is the equivalent of the function call in C:\n//   $RAISE((B_BaseException)$NEW(B_ValueError,to$str(message)))\npub fn raise_ValueError(message: []const u8) void {\n    const error_ptr = new_ValueError(message);\n    // @ptrCast is used to cast the pointer to the correct type expected by the C function\n    c_acton.@\"$RAISE\"(@ptrCast(error_ptr));\n    // RAISE does not return, it does a longjmp, so this code is unreachable\n    unreachable;\n}\n\n// B_MemoryError\npub const MemoryError = extern struct {\n    class: *c_acton.B_MemoryErrorG_class,\n    error_message: c_acton.B_str,\n};\n\n// This is the equivalent of the expanded macro in C:\n//  $NEW(B_MemoryError,to$str(message))\npub fn new_MemoryError(message: []const u8) *c_acton.B_MemoryError {\n    const alloc = gc.allocator();\n\n    const error_ptr = alloc.create(MemoryError) catch @panic(\"OOM\");\n    const c_error_message = @constCast(message.ptr);\n    const error_message_ptr = c_acton.to_str_noc(c_error_message);\n    error_ptr.* = .{ .class = @ptrCast(&c_acton.B_MemoryErrorG_methods), .error_message = null };\n    if (error_ptr.class.__init__) |init_fn| {\n        _ = init_fn(@ptrCast(error_ptr), error_message_ptr);\n    }\n    return @ptrCast(error_ptr);\n}\n\n// This is the equivalent of the function call in C:\n//   $RAISE((B_BaseException)$NEW(B_MemoryError,to$str(message)))\npub fn raise_MemoryError(message: []const u8) void {\n    const error_ptr = new_MemoryError(message);\n    // @ptrCast is used to cast the pointer to the correct type expected by the C function\n    c_acton.@\"$RAISE\"(@ptrCast(error_ptr));\n    // RAISE does not return, it does a longjmp, so this code is unreachable\n    unreachable;\n}\n\ntest \"str struct\" {\n    // Check that our struct is the same size as the C struct, by using @typeInfo\n    // B_str is a pointer to a C struct, so we need to \"dereference\" the pointer\n    // type to get to the struct type, then check the size of the nbytes field\n    switch (@typeInfo(c_acton.B_str)) {\n        .Pointer => |info| switch (info.size) {\n            .C => switch (@typeInfo(info.child)) {\n                .Struct => |child_info| {\n                    inline for (child_info.fields) |field| {\n                        //std.debug.print(\"struct B_str field: {s} size: {d}\\n\", .{field.name, @sizeOf(field.type)});\n                        if (std.mem.eql(u8, field.name, \"nbytes\")) {\n                            try expect(@sizeOf(field.type) == 4);\n                        }\n                        if (std.mem.eql(u8, field.name, \"nchars\")) {\n                            try expect(@sizeOf(field.type) == 4);\n                        }\n                    }\n                },\n                else => {\n                    @compileError(\"Unhandled type: {s}\" ++ @typeName(info.child));\n                }\n            },\n            else => {\n                @compileError(\"Unhandled type:\");\n            }\n        },\n        else =>\n            std.debug.print(\"unexpected type\\n\", .{}),\n    }\n    try expect(@sizeOf(str) == 24); // 8 + 4 + 4 + 8\n//    std.debug.print(\"size of str: {d}\\n\", .{ @sizeOf(str) });\n//    std.debug.print(\"size of B_str: {d}\\n\", .{ @sizeOf(B_str) });\n//    std.debug.print(\"size of imported c_acton.B_str: {d}\\n\", .{ @sizeOf(c_acton.B_str.*) });\n    //try expect(@sizeOf(c_acton.B_str) == 8);\n    //try expect(@sizeOf(str) == @sizeOf(c_acton.B_str));\n}\n"
  },
  {
    "path": "base/builtin/Iterator.c",
    "content": "/*\n * Copyright (C) 2019-2021 Data Ductus AB\n *\n * Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:\n *\n * 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.\n *\n * 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.\n *\n * 3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission.\n *\n * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS \"AS IS\" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n */\n\nB_Iterator B_IterableD_IteratorD___iter__(B_IterableD_Iterator wit, B_Iterator self) {\n    return self;\n}\n \n$WORD $next(B_Iterator it) {\n    return it->$class->__next__(it);\n}\n"
  },
  {
    "path": "base/builtin/Iterator.h",
    "content": "\n$WORD $next(B_Iterator);\n"
  },
  {
    "path": "base/builtin/atom.c",
    "content": "/*\n * Copyright (C) 2019-2021 Data Ductus AB\n *\n * Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:\n *\n * 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.\n *\n * 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.\n *\n * 3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission.\n *\n * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS \"AS IS\" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n */\n\nstruct B_atomG_class B_atomG_methods = {\n    \"B_atom\",\n    UNASSIGNED,\n    ($SuperG_class)&B_valueG_methods\n};\n"
  },
  {
    "path": "base/builtin/atom.h",
    "content": "extern struct B_atomG_class B_atomG_methods;\n\n\n"
  },
  {
    "path": "base/builtin/bigint.c",
    "content": "/*\n * Copyright (C) 2019-2021 Data Ductus AB\n *\n * Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:\n *\n * 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.\n *\n * 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.\n *\n * 3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission.\n *\n * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS \"AS IS\" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n */\n\n#define GC_THREADS 1\n#include \"gc.h\"\n\n// General methods ///////////////////////////////////////////////////////////////////////\n\nint set_str(zz_ptr a, unsigned char *str, B_int intbase);\n\nB_bigint malloc_bigint() {\n    B_bigint res = acton_malloc(sizeof(struct B_bigint));\n    res->$class = &B_bigintG_methods;\n    res->val.n = acton_malloc_atomic(sizeof(unsigned long));\n    res->val.size = 0;\n    res->val.alloc = 1;\n    return res;\n}\n\nvoid zz_malloc_fit(zz_ptr res, len_t m) {\n    res->n = acton_malloc_atomic(sizeof(unsigned long) * m);\n    res->size = 0;\n    res->alloc = m;\n}\n\nB_bigint B_IntegralD_bigintD___lshift__(B_IntegralD_bigint wit,  B_bigint a, B_int b);\n\nB_bigint B_bigintG_new(B_atom a, B_int base) {\n    if (base) {\n        if ($ISINSTANCE0(a,B_str)) {\n            B_bigint res = malloc_bigint();\n            res->$class = &B_bigintG_methods;\n            set_str(&res->val, ((B_str)a)->str, base);\n            return res;\n        } else {\n            char errmsg[1024];\n            snprintf(errmsg, sizeof(errmsg), \"integer type constructor: base argument is only allowed when converting from a str\");\n            $RAISE($NEW(B_BaseException,to$str(errmsg)));\n        }\n    }\n    if ($ISINSTANCE0(a,B_bigint)) return (B_bigint)a;\n    if ($ISINSTANCE0(a,B_int)) {\n        return toB_bigint(((B_int)a)->val);\n    }\n    if ($ISINSTANCE0(a,B_i32)) {\n        return toB_bigint((long)((B_i32)a)->val);\n    }\n    if ($ISINSTANCE0(a,B_i16)) {\n        return toB_bigint((long)((B_i16)a)->val);\n    }\n    if ($ISINSTANCE0(a,B_i8)) {\n        return toB_bigint((long)((B_i8)a)->val);\n    }\n    if ($ISINSTANCE0(a,B_u64)) {\n        unsigned long v = ((B_u64)a)->val;\n        if (v==0) \n            return toB_bigint(0L);\n        else {\n            B_bigint res = malloc_bigint();\n            res->val.size=1;\n            res->val.n[0] = v;\n            return res;\n        }\n    }\n    if ($ISINSTANCE0(a,B_u32)) {\n        unsigned int v = ((B_u32)a)->val;\n        if (v==0) \n            return toB_bigint(0L);\n        else {\n            B_bigint res = malloc_bigint();\n            res->val.size=1;\n            res->val.n[0] = (unsigned long)v;\n            return res;\n        }\n    }\n    if ($ISINSTANCE0(a,B_u16)) {\n        unsigned short v = ((B_u16)a)->val;\n        if (v==0) \n            return toB_bigint(0L);\n        else {\n            B_bigint res = malloc_bigint();\n            res->val.size=1;\n            res->val.n[0] = (unsigned long)v;\n            return res;\n        }\n    }\n    if ($ISINSTANCE0(a,B_u8)) {\n        unsigned char v = ((B_u8)a)->val;\n        if (v==0) \n            return toB_bigint(0L);\n        else {\n            B_bigint res = malloc_bigint();\n            res->val.size=1;\n            res->val.n[0] = (unsigned long)v;\n            return res;\n        }\n    }\n    if ($ISINSTANCE0(a,B_u1)) {\n        unsigned char v = ((B_u8)a)->val;\n        if (v==0) \n            return toB_bigint(0L);\n        else {\n            B_bigint res = malloc_bigint();\n            res->val.size=1;\n            res->val.n[0] = (unsigned long)v;\n            return res;\n        }\n    }\n    if ($ISINSTANCE0(a,B_float)) {\n        double aval = ((B_float)a)->val;\n        int e;\n        double m = frexp(aval,&e);\n        if (e>52) {\n            B_bigint c = toB_bigint((long)(m*4503599627370496.0)); // (1<< 52); \n            B_int d = toB_int(e-52);\n            return  B_IntegralD_bigintD___lshift__(NULL,c,d);\n        } else {\n            long al = (long)aval;\n            B_bigint res = toB_bigint(al);\n            return res;\n        }\n    }\n    if ($ISINSTANCE0(a,B_bool)) return toB_bigint(((B_bool)a)->val);\n    if ($ISINSTANCE0(a,B_str)) {\n        B_bigint res = malloc_bigint();\n        res->$class = &B_bigintG_methods;\n        set_str(&res->val, ((B_str)a)->str, base);\n        return res;\n    }\n    fprintf(stderr,\"internal error: B_bigintG_new: argument not of atomic type\\n\");\n    exit(-1);\n}\n\nB_NoneType B_bigintD___init__(B_bigint self, B_atom a, B_int base){\n    self->val = B_bigintG_new(a,base)->val;\n    return B_None;\n}\n\nvoid B_bigintD___serialize__(B_bigint self,$Serial$state state) {\n    B_bigint prevkey = (B_bigint)B_dictD_get(state->done,(B_Hashable)B_HashableD_WORDG_witness,self,NULL);\n    if (prevkey) {\n        long pk = fromB_bigint(prevkey);\n        $val_serialize(-INT_ID,&pk,state);\n        return;\n    }\n    B_dictD_setitem(state->done,(B_Hashable)B_HashableD_WORDG_witness,self,toB_bigint(state->row_no));\n    int blobsize = 1 + labs(self->val.size);\n    $ROW row = $add_header(INT_ID,blobsize,state);\n    row->blob[0] = ($WORD)self->val.size;\n    memcpy(&row->blob[1],self->val.n,labs(self->val.size)*sizeof(long));\n}\n\nB_bigint B_bigintD___deserialize__(B_bigint res,$Serial$state state) {\n    $ROW this = state->row;\n    state->row = this->next;\n    state->row_no++;\n    if (this->class_id < 0) {\n        return (B_bigint)B_dictD_get(state->done,(B_Hashable)B_HashableD_intG_witness,toB_bigint((long)this->blob[0]),NULL);\n    } else {\n        if (!res)\n            res = malloc_bigint();\n        res->val.size = (long)this->blob[0];\n        res->val.alloc = labs(res->val.size);\n        res->val.n = acton_malloc(res->val.alloc*sizeof(long));\n        memcpy(res->val.n,&this->blob[1],res->val.alloc*sizeof(long));\n        B_dictD_setitem(state->done,(B_Hashable)B_HashableD_intG_witness,toB_bigint(state->row_no-1),res);\n        res->$class = &B_bigintG_methods;\n        return res;\n    }\n}\n\nB_bool B_bigintD___bool__(B_bigint n) {\n    return toB_bool(zz_cmpi(&n->val,0));\n}\n\nB_str B_bigintD___str__(B_bigint n) {\n    return to_str_noc(get_str(&n->val));\n}\n\nB_str B_bigintD___repr__(B_bigint n) {\n    return to_str_noc(get_str(&n->val));\n}\n\n/*\nB_bigint zz$toB_bigint(zz_ptr n) {\n    B_bigint res = malloc_bigint();\n    res->$class = &B_bigintG_methods;\n    res->val.n = n->n;\n    res->val.size = n->size;\n    res->val.alloc = n->alloc;\n    return res;\n}\n*/\n\n// B_IntegralD_bigint /////////////////////////////////////////////////////////////////////////\n\n \nB_bigint B_IntegralD_bigintD___add__(B_IntegralD_bigint wit,  B_bigint a, B_bigint b) {\n    B_bigint res = malloc_bigint();\n    zz_add(&res->val,&a->val,&b->val);\n    return res;\n}\n\nB_bigint B_IntegralD_bigintD___zero__(B_IntegralD_bigint wit) {\n    return toB_bigint(0);\n}\n\nB_complex B_IntegralD_bigintD___complex__(B_IntegralD_bigint wit, B_bigint a) {\n    $RAISE((B_BaseException)$NEW(B_NotImplementedError, to$str(\"Number.__complex__ not implemented for int\")));\n    return NULL; // This is just to silence compiler warning, above RAISE will longjmp from here anyway\n}\n\nB_bigint B_IntegralD_bigintD___fromatom__(B_IntegralD_bigint wit, B_atom a) {\n    return B_bigintG_new(a,NULL);\n}\n\nB_bigint B_IntegralD_bigintD___mul__(B_IntegralD_bigint wit,  B_bigint a, B_bigint b) {\n    B_bigint res = malloc_bigint();\n    zz_mul(&res->val,&a->val,&b->val);\n    return res;\n}  \n  \nB_bigint B_IntegralD_bigintD___pow__(B_IntegralD_bigint wit, B_bigint a, B_bigint b) {\n    zz_ptr val_b = &b->val;\n    if (zz_cmpi(val_b,0) < 0) {\n        char errmsg[1024];\n        snprintf(errmsg, sizeof(errmsg), \"int.__pow__(): negative exponent: %s\", get_str(val_b));\n        $RAISE((B_BaseException)$NEW(B_ValueError,to$str(errmsg)));\n    }\n    if (zz_cmpi(val_b,LONG_MAX) > 0) {\n        char errmsg[1024];\n        snprintf(errmsg, sizeof(errmsg), \"int.__pow__(): exponent out of range (>LONG_MAX):  %s\", get_str(val_b));\n        $RAISE((B_BaseException)$NEW(B_ValueError,to$str(errmsg)));\n    }\n    B_bigint res = malloc_bigint();\n    if (val_b->size == 0)\n         zz_seti(&res->val, 1);\n     else     \n         zz_powi(&res->val,&a->val,val_b->n[0]); // __pow__ should have an int64 exponent in the Acton protocol\n    return res;\n}\n\nB_bigint B_IntegralD_bigintD___neg__(B_IntegralD_bigint wit,  B_bigint a) {\n    B_bigint res = malloc_bigint();\n    zz_neg(&res->val,&a->val);\n    return res;\n}\n\nB_bigint B_IntegralD_bigintD___pos__(B_IntegralD_bigint wit,  B_bigint a) {\n    return a;\n}\n\n$WORD B_IntegralD_bigintD_real(B_IntegralD_bigint wit, B_bigint a, B_Real wit2) {\n    $RAISE((B_BaseException)$NEW(B_NotImplementedError,to$str(\"Number.__real__ not implemented for int\")));\n    return NULL; // This is just to silence compiler warning, above RAISE will longjmp from here anyway\n}\n\n$WORD B_IntegralD_bigintD_imag(B_IntegralD_bigint wit, B_bigint a, B_Real wit2) {\n    $RAISE((B_BaseException)$NEW(B_NotImplementedError,to$str(\"Number.__imag__ not implemented for int\")));\n    return NULL; // This is just to silence compiler warning, above RAISE will longjmp from here anyway\n}\n\n$WORD B_IntegralD_bigintD___abs__(B_IntegralD_bigint wit, B_bigint a, B_Real wit2) {\n    B_bigint res = malloc_bigint();\n    zz_set(&res->val,&a->val);\n    res->val.size = labs(a->val.size);\n    return wit2->$class->__fromatom__(wit2,(B_atom)res);\n}\n\nB_bigint B_IntegralD_bigintD_conjugate(B_IntegralD_bigint wit,  B_bigint a) {\n    return a;\n}\n\nB_float B_IntegralD_bigintD___float__ (B_IntegralD_bigint wit, B_bigint n) {\n    return B_floatG_new((B_atom)n);\n}\n\n$WORD B_IntegralD_bigintD___trunc__ (B_IntegralD_bigint wit, B_bigint n, B_Integral wit2) {\n    return wit2->$class->__fromatom__(wit2,(B_atom)n);\n}\n  \n$WORD B_IntegralD_bigintD___floor__ (B_IntegralD_bigint wit, B_bigint n, B_Integral wit2) {\n    return wit2->$class->__fromatom__(wit2,(B_atom)n);\n}\n  \n$WORD B_IntegralD_bigintD___ceil__ (B_IntegralD_bigint wit, B_bigint n, B_Integral wit2) {\n    return wit2->$class->__fromatom__(wit2,(B_atom)n);\n}\n\nB_bigint B_IntegralD_bigintD___floordiv__(B_IntegralD_bigint wit, B_bigint a, B_bigint b);\n\nB_bigint B_IntegralD_bigintD___round__ (B_IntegralD_bigint wit, B_bigint n, B_int p) {\n    zz_struct nval = n->val;\n    if (nval.size < 0) { \n        B_bigint n1 = malloc_bigint();\n        zz_neg(&n1->val,&nval);\n        B_bigint res = B_IntegralD_bigintD___round__(wit,n1,p);\n        zz_neg(&res->val,&res->val);\n        return res;\n    }\n    long pval = fromB_int(p);\n    if (pval>=0)\n        return n;\n    B_bigint p10 = B_IntegralD_bigintD___pow__(NULL,toB_bigint(10), B_IntegralD_bigintD___neg__(NULL,toB_bigint(p->val)));\n    B_bigint p10half = B_IntegralD_bigintD___floordiv__(NULL, p10,toB_bigint(2));\n    B_bigint n1 = B_IntegralD_bigintD___floordiv__(NULL,B_IntegralD_bigintD___add__(NULL,n,p10half),p10);\n    return B_IntegralD_bigintD___mul__(NULL,n1,p10);\n}\n  \n$WORD B_IntegralD_bigintD_numerator (B_IntegralD_bigint wit, B_bigint n, B_Integral wit2) {\n    return wit2->$class->__fromatom__(wit2,(B_atom)n);\n}\n  \n$WORD B_IntegralD_bigintD_denominator (B_IntegralD_bigint wit, B_bigint n, B_Integral wit2) {\n    B_bigint res = toB_bigint(1L);\n    return wit2->$class->__fromatom__(wit2,(B_atom)res);\n}\n  \nB_int B_IntegralD_bigintD___int__ (B_IntegralD_bigint wit, B_bigint n) {\n    unsigned long k = n->val.n[0];\n    long sz = n->val.size;\n    if (labs(sz) > 1 || (sz==1 && k > 0x7ffffffffffffffful) || sz == -1 && k > 0x8000000000000000ul) {\n        char errmsg[1024];\n        snprintf(errmsg, sizeof(errmsg), \"bigint.__int__: value %s out of range for type int\",get_str(&n->val));\n        $RAISE((B_BaseException)$NEW(B_ValueError,to$str(errmsg)));\n    }\n    return toB_int(k*sz);\n}\n\nB_int B_IntegralD_bigintD___index__ (B_IntegralD_bigint wit, B_bigint n) {\n    unsigned long k = n->val.n[0];\n    long sz = n->val.size;\n    if (labs(sz) > 1 || (sz==1 && k > 0x7ffffffffffffffful) || sz == -1 && k > 0x8000000000000000ul) {\n        char errmsg[1024];\n        snprintf(errmsg, sizeof(errmsg), \"bigint.__index__: value %s out of range for type int\",get_str(&n->val));\n        $RAISE((B_BaseException)$NEW(B_ValueError,to$str(errmsg)));\n    }\n    return toB_int(k*sz);\n}\n\nB_tuple B_IntegralD_bigintD___divmod__(B_IntegralD_bigint wit, B_bigint a, B_bigint b) {\n    if (b->val.size == 0){\n        char errmsg[1024];\n        snprintf(errmsg, sizeof(errmsg), \"integer divmod: divisor is zero\");\n        $RAISE((B_BaseException)$NEW(B_ZeroDivisionError,to$str(errmsg)));\n    }\n    B_bigint q = malloc_bigint();\n    B_bigint r = malloc_bigint();\n    zz_divrem(&q->val,&r->val,&a->val,&b->val);\n    return $NEWTUPLE(2, q, r);\n}\n\nB_bigint B_IntegralD_bigintD___floordiv__(B_IntegralD_bigint wit, B_bigint a, B_bigint b) {\n    if (b->val.size == 0){\n        char errmsg[1024];\n        snprintf(errmsg, sizeof(errmsg), \"integer floordiv: divisor is zero\");\n        $RAISE((B_BaseException)$NEW(B_ZeroDivisionError,to$str(errmsg)));\n    }\n     B_bigint res = malloc_bigint();\n    zz_div(&res->val,&a->val,&b->val);\n    return res;\n}\n\nB_bigint B_IntegralD_bigintD___mod__(B_IntegralD_bigint wit, B_bigint a, B_bigint b) {\n    B_tuple t = B_IntegralD_bigintD___divmod__(wit,a,b);\n    return t->components[1];\n}\n\nB_bigint B_IntegralD_bigintD___lshift__(B_IntegralD_bigint wit,  B_bigint a, B_int b) {\n    zz_struct aval = a->val;\n    long ma = aval.size;\n    long bval = fromB_int(b);\n    if (ma==0 || bval==0)\n        return a;\n    if (bval<0) {\n        char errmsg[1024];\n        snprintf(errmsg, sizeof(errmsg), \"bigint.__lshift__: negative shift count: %ld\", bval);\n        $RAISE((B_BaseException)$NEW(B_ValueError,to$str(errmsg)));\n    }\n    long shw = bval/64;\n    long shb = bval%64;\n    long mres = labs(ma) + shw + (shb > 0);\n    B_bigint res = malloc_bigint();\n    zz_ptr rval = &res->val;\n    zz_malloc_fit(rval,mres);\n    word_t ci = nn_shl(rval->n, aval.n, labs(ma), shb);\n    rval->n[labs(ma)] = ci;\n    if (shw>0) {\n        for (int i = labs(ma)-1+(shb>0); i >= 0; i--)\n            rval->n[i+shw] = rval->n[i];\n        for (int i = 0; i < shw; i++)\n            rval->n[i] = 0;\n    }\n    mres = mres - (rval->n[mres-1]==0);\n    mres = ma<0? -mres:mres;\n    rval->size = mres;\n    return res; \n}\n\nB_bigint B_IntegralD_bigintD___rshift__(B_IntegralD_bigint wit,  B_bigint a, B_int b) {\n    zz_struct aval = a->val;\n    long ma = aval.size;\n    long bval = fromB_int(b);\n    if (ma==0 || bval==0)\n        return a;\n    if (bval<0)  {\n        char errmsg[1024];\n        snprintf(errmsg, sizeof(errmsg), \"bigint.__rshift__: negative shift count: %ld\", bval);\n        $RAISE((B_BaseException)$NEW(B_ValueError,to$str(errmsg)));\n    }\n    B_bigint res = malloc_bigint();\n    zz_ptr rval = &res->val;\n    long shw = bval/64;\n    long shb = bval%64;\n    long mres = labs(ma) - shw;\n    zz_malloc_fit(rval,mres);\n    unsigned long tmp[mres];\n    for (int i = 0; i < mres; i++)\n        tmp[i] = aval.n[i+shw];\n    word_t ci = nn_shr(rval->n, tmp, mres, shb);\n    mres = mres - (rval->n[mres-1]==0);\n    mres = ma<0?-mres:mres;\n    res->val.size = mres;\n    return res; \n}\n \nB_bigint B_IntegralD_bigintD___invert__(B_IntegralD_bigint wit,  B_bigint a) {\n    B_bigint res0 = malloc_bigint();\n    B_bigint res = malloc_bigint();\n    B_bigint one = toB_bigint(1);\n    zz_neg(&res0->val,&a->val);\n    zz_sub(&res->val,&res0->val,&one->val);\n    return res;\n}\n\n\n// LogicalB_bigint  ////////////////////////////////////////////////////////////////////////////////////////\n\n// Converts src (which must be non-zero), to two's complement form, stored in dst.\n// src and dst may be the same address.\nvoid twocompl(unsigned long *dst, unsigned long *src, long len) {\n    unsigned long carry = 1;\n    for (int i = 0; i < len; i++) {\n        unsigned long t = src[i] ^ ULONG_MAX;\n        if (t < ULONG_MAX || carry == 0) {\n            dst[i] = t + carry;\n            carry = 0;\n        } else {\n            dst[i] = 0;\n        }\n    }\n}\n\nB_bigint B_LogicalD_IntegralD_bigintD___and__(B_LogicalD_IntegralD_bigint wit,  B_bigint a, B_bigint b) {\n    long aneg = a->val.size < 0;\n    long bneg = b->val.size < 0;\n    long asize = labs(a->val.size);\n    long bsize = labs(b->val.size);\n    if (bsize==0) return toB_bigint(0);\n    if (asize==0) return toB_bigint(0);\n    unsigned long  *a1, *b1;\n    if (aneg) {\n        a1 = acton_malloc(asize*sizeof(long));\n        twocompl(a1, a->val.n, asize);\n    } else\n        a1 = a->val.n;\n    if (bneg) {\n        b1 = acton_malloc(bsize*sizeof(long));\n        twocompl(b1, b->val.n, bsize);\n    } else\n        b1 = b->val.n;\n    long rneg = aneg & bneg;\n    if (asize < bsize) {\n        unsigned long *t = a1; a1 = b1; b1 = t;\n        long tsize = asize; asize = bsize; bsize = tsize;\n        long tneg = aneg; aneg = bneg; bneg = tneg;\n    }\n    B_bigint res = malloc_bigint();\n    // if both are positive, rsize = bsize\n    // if one is positive, use that size\n    // if both are negative, rsize = asize\n    zz_malloc_fit(&res->val,bneg ? asize : bsize);\n    res->val.size = 0;\n    if (bneg) {\n        for (int i = asize-1; i >= bsize; i--) {\n            res->val.n[i] = a1[i];\n            if (res->val.size == 0 && res->val.n[i] != 0L)\n                res->val.size = i+1;\n        }\n    }\n    for (int i = bsize-1; i >= 0; i--) {\n        res->val.n[i] = a1[i] & b1[i];\n        if (res->val.size == 0 && res->val.n[i] != 0L)\n            res->val.size = i+1;\n    }\n    if (rneg) {\n        twocompl(res->val.n, res->val.n, res->val.size);\n        res->val.size = -res->val.size;\n    }\n    return res;\n}     \n\n                                                 \nB_bigint B_LogicalD_IntegralD_bigintD___or__(B_LogicalD_IntegralD_bigint wit,  B_bigint a, B_bigint b) {\n    long aneg = a->val.size < 0;\n    long bneg = b->val.size < 0;\n    long asize = labs(a->val.size);\n    long bsize = labs(b->val.size);\n    if (bsize==0) return a;\n    if (asize==0) return b;\n    unsigned long  *a1, *b1;\n    if (aneg) {\n        a1 = acton_malloc(asize*sizeof(long));\n        twocompl(a1, a->val.n, asize);\n    } else\n        a1 = a->val.n;\n    if (bneg) {\n        b1 = acton_malloc(bsize*sizeof(long));\n        twocompl(b1, b->val.n, bsize);\n    } else\n        b1 = b->val.n;\n    long rneg = aneg | bneg;\n    if (asize < bsize) {\n        unsigned long *t = a1; a1 = b1; b1 = t;\n        long tsize = asize; asize = bsize; bsize = tsize;\n        long tneg = aneg; aneg = bneg; bneg = tneg;\n    }\n    B_bigint res = malloc_bigint();\n    zz_malloc_fit(&res->val,bneg ? bsize : asize);\n    res->val.size = 0;\n    if (!bneg) {\n        for (int i = asize-1; i >= bsize; i--) {\n            res->val.n[i] = a1[i];\n            if (res->val.size == 0 && res->val.n[i] != 0L)\n                res->val.size = i+1;\n        }\n    }\n    for (int i = bsize-1; i >= 0; i--) {\n        res->val.n[i] = a1[i] | b1[i];\n        if (res->val.size == 0 && res->val.n[i] != 0L)\n            res->val.size = i+1;\n    }\n    if (rneg) {\n        twocompl(res->val.n, res->val.n, res->val.size);\n        res->val.size = -res->val.size;\n    }\n    return res;\n}     \n\n\nB_bigint B_LogicalD_IntegralD_bigintD___xor__(B_LogicalD_IntegralD_bigint wit,  B_bigint a, B_bigint b) {\n    long aneg = a->val.size < 0;\n    long bneg = b->val.size < 0;\n    long asize = labs(a->val.size);\n    long bsize = labs(b->val.size);\n    if (bsize==0) return a;\n    if (asize==0) return b;\n    unsigned long  *a1, *b1;\n    if (aneg) {\n        a1 = acton_malloc(asize*sizeof(long));\n        twocompl(a1, a->val.n, asize);\n    } else\n        a1 = a->val.n;\n    if (bneg) {\n        b1 = acton_malloc(bsize*sizeof(long));\n        twocompl(b1, b->val.n, bsize);\n    } else\n        b1 = b->val.n;\n    long rneg = aneg ^ bneg;\n    if (asize < bsize) {\n        unsigned long *t = a1; a1 = b1; b1 = t;\n        long tsize = asize; asize = bsize; bsize = tsize;\n        long tneg = aneg; aneg = bneg; bneg = tneg;\n    }\n    B_bigint res = malloc_bigint();\n    zz_malloc_fit(&res->val,asize);\n    res->val.size = 0;\n    for (int i = asize-1; i >= bsize; i--) {\n        res->val.n[i] = bneg ? (~a1[i]) : a1[i];\n        if (res->val.size == 0 && res->val.n[i] != 0L)\n            res->val.size = i+1;\n     }\n    for (int i = bsize-1; i >= 0; i--) {\n        res->val.n[i] = a1[i] ^ b1[i];\n        if (res->val.size == 0 && res->val.n[i] != 0L)\n            res->val.size = i+1;\n    }\n    if (rneg) {\n        twocompl(res->val.n, res->val.n, res->val.size);\n        res->val.size = -res->val.size;\n    }\n    return res;\n}     \n \n// B_MinusD_IntegralD_bigint  ////////////////////////////////////////////////////////////////////////////////////////\n\nB_bigint B_MinusD_IntegralD_bigintD___sub__(B_MinusD_IntegralD_bigint wit,  B_bigint a, B_bigint b) {\n    B_bigint res = malloc_bigint();\n    zz_sub(&res->val,&a->val,&b->val);\n    return res;\n}\n\n\n// B_DivD_bigint  ////////////////////////////////////////////////////////////////////////////////////////\n\nB_float B_DivD_bigintD___truediv__ (B_DivD_bigint wit, B_bigint a, B_bigint b) {\n    if (zz_equal(&b->val, &toB_bigint(0)->val))\n        $RAISE((B_BaseException)$NEW(B_ZeroDivisionError, to$str(\"division by zero\")));\n    zz_ptr aval = &a->val;\n    zz_ptr bval = &b->val;\n    B_bigint ared = malloc_bigint();\n    B_bigint bred = malloc_bigint();\n    B_bigint q = malloc_bigint();\n    B_bigint r = malloc_bigint();\n    B_bigint g = malloc_bigint();\n    zz_gcd(&g->val,aval,bval);\n    zz_div(&ared->val,aval,&g->val);\n    zz_div(&bred->val,bval,&g->val);\n    zz_divrem(&q->val,&r->val,&ared->val,&bred->val);\n    return to$float(B_floatG_new((B_atom)q)->val +  B_floatG_new((B_atom)r)->val/ B_floatG_new((B_atom)bred)->val);\n}\n\n// B_OrdD_bigint  ////////////////////////////////////////////////////////////////////////////////////////\n\nB_bool B_OrdD_bigintD___eq__ (B_OrdD_bigint wit, B_bigint a, B_bigint b) {\n    return toB_bool(zz_equal(&a->val,&b->val));\n}\n\nB_bool B_OrdD_bigintD___ne__ (B_OrdD_bigint wit, B_bigint a, B_bigint b) {\n    return toB_bool(1-zz_equal(&a->val,&b->val));\n}\n\nB_bool B_OrdD_bigintD___lt__ (B_OrdD_bigint wit, B_bigint a, B_bigint b) {\n    return toB_bool(zz_cmp(&a->val,&b->val) < 0);\n}\n\nB_bool B_OrdD_bigintD___le__ (B_OrdD_bigint wit, B_bigint a, B_bigint b) {\n    return toB_bool(zz_cmp(&a->val,&b->val) <= 0);\n}\n\nB_bool B_OrdD_bigintD___gt__ (B_OrdD_bigint wit, B_bigint a, B_bigint b) {\n    return toB_bool(zz_cmp(&a->val,&b->val) > 0);\n}\n\nB_bool B_OrdD_bigintD___ge__ (B_OrdD_bigint wit, B_bigint a, B_bigint b) {\n    return toB_bool(zz_cmp(&a->val,&b->val) >= 0);\n}\n\n// B_HashableD_bigint ///////////////////////////////////////////////////////////////////////////////////////////////////////\n\nB_bool B_HashableD_bigintD___eq__(B_HashableD_bigint wit, B_bigint a, B_bigint b) {\n    return toB_bool(zz_equal(&a->val,&b->val));\n}\n\nB_bool B_HashableD_bigintD___ne__(B_HashableD_bigint wit, B_bigint a, B_bigint b) {\n    return toB_bool(1-zz_equal(&a->val,&b->val));\n}\n\nB_NoneType B_HashableD_bigintD_hash(B_HashableD_bigint wit, B_bigint a, B_hasher h) {\n    long sz = a->val.size;\n    unsigned long data;\n    if (sz==0)\n        data = 0UL;\n    else\n        data = (long)a->val.n[0];\n    zig_hash_wyhash_update(h->_hasher,to$bytesD_len((char *)&data,8));\n    return B_None;\n}\n\nlong fromB_bigint(B_bigint n) { \n    long sz = n->val.size;\n    if (sz==0) return 0;\n    unsigned long res = n->val.n[0];\n    if (res > LONG_MAX || labs(sz) > 1) {\n        fprintf(stderr,\"internal error: overflow in converting int to bounded int\\n\");\n        exit(1);\n    }\n    return sz<0 ? -res : res;\n}\n            \nB_bigint toB_bigint(long n) {\n    if (n >= 0 && n < 256)\n        return &B_bigint_strs[n];\n    else {\n        B_bigint res = malloc_bigint();\n        res->val.n[0] = n > 0 ? n : (n == LONG_MIN ? 9223372036854775808UL : -n);\n        res->val.size = n < 0 ? -1 : n > 0;\n        return res;\n    }\n}\n\nB_bigint toB_bigint2(char *str) {\n    B_bigint res = malloc_bigint();\n    res->$class = &B_bigintG_methods;\n    set_str(&res->val, (unsigned char *)str, NULL);\n    return res;\n}\n\n\n// Conversion to strings /////////////////////////////////////////////////////////////////////////////\n\n// These four constants must be changed for a 32 bit machine\nint WORDSIZE = 64;\nint POW10INWORD = 18; // Largest power of 10 that fits in a signed long \nunsigned char POWINWORD[37] = {0,0,62,39,31,27,24,22,20,19,18,18,17,17,16,16,15,15,15,14,14,14,14,13,13,13,13,13,13,12,12,12,12,12,12,12,12};\n//POWINWORD[b] is largest power of b that fits in a signed word\ndouble CCCC = 9.805415291306852e-2;  // log2(WORDSIZE) - log2 (POW10INWORD) - log2 (log2(10))\n\n// n is a valid digit in base b iff digvalue[n] < b.\nunsigned char digvalue[256] = {\n    99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99,\n    99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99,\n    99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99,\n     0,  1,  2,  3,  4,  5,  6,  7,  8,  9, 99, 99, 99, 99, 99, 99,\n    99, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24,\n    25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 99, 99, 99, 99, 99,\n    99, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24,\n    25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 99, 99, 99, 99, 99,\n    99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99,\n    99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99,\n    99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99,\n    99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99,\n    99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99,\n    99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99,\n    99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99,\n    99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99,\n};\n\n\nint get_str0(bool ishead, zz_ptr n, zz_ptr dens[], int d, unsigned char *res, int pos) {\n    if (d >= 0) {\n        zz_ptr hi = acton_malloc(sizeof(zz_struct));\n        zz_ptr lo = acton_malloc(sizeof(zz_struct));\n        zz_init_fit(hi,dens[d]->size);\n        zz_init_fit(lo,dens[d]->size);\n        zz_divrem(hi, lo, n, dens[d]);\n        if (hi->size==0 && ishead) {\n            return get_str0(ishead, lo, dens, d-1, res, pos);\n        } else {\n            int newpos = get_str0(ishead, hi, dens, d-1, res, pos);\n            return get_str0(false, lo, dens, d-1, res, newpos);\n        }\n    } else {\n        char buf[POW10INWORD + 1];\n        sprintf(buf, \"%lu\", (unsigned long)n->n[0]);\n        int len = strlen(buf);\n        if (ishead) {\n            memcpy(&res[pos], buf, len);\n            return pos + len;\n        } else {\n            memcpy(&res[pos + POW10INWORD - len], buf, len);\n            return pos + POW10INWORD;\n        }\n    }\n}\n\n\nchar * get_str(zz_ptr nval) {\n    if (nval->size == 0)\n        return \"0\";\n    long nlen = BSDNT_ABS(nval->size);\n    zz_ptr npos = acton_malloc(sizeof(zz_struct));\n    zz_init_fit(npos,nlen);\n    nn_copy(npos->n, nval->n, nlen);\n    npos->size = nlen;\n    int is_neg_n = nval->size < 0;\n    int d;\n    zz_ptr *dens;\n    if (nlen == 1) {\n        d = 0;\n        dens = NULL;\n    } else {\n        d = ceil(log2((double)nlen) + CCCC);  //number of squarings\n        dens = acton_malloc(d * sizeof(zz_ptr));\n        dens[0] = acton_malloc(sizeof(zz_struct));\n        zz_init_fit(dens[0], 1);\n        zz_seti(dens[0], 10); \n        zz_powi(dens[0], dens[0], POW10INWORD);\n        for (int i=1; i < d; i++) {\n            dens[i] = acton_malloc(sizeof(zz_struct));\n            zz_init_fit(dens[i], 2 * dens[i-1]->size);\n            zz_mul(dens[i], dens[i-1], dens[i-1]);\n        }\n    }\n    // strlen is for most n one more than necessary; this is a precaution for values of n where\n    // the double value ... in ceil(...) is very close to an integer. So we often waste one byte.\n    int strlen = ceil(log10((float)npos->n[nlen - 1]) + (nlen - 1) * WORD_BITS * log10(2) + is_neg_n) + 2;\n    char *res = acton_malloc_atomic(strlen);\n    memset(res,'0', strlen);\n    int pos = 0;\n    if (is_neg_n) {\n        res[0] = '-';\n        pos++;\n    }\n    int newpos = get_str0(true, npos, dens, d-1, (unsigned char *)res, pos);\n    res[newpos] = '\\0';\n    return res;\n}\n\n\nint set_str0(zz_ptr a, unsigned char *nstr, unsigned char base, int parts) {\n    // assert(parts > 0);\n    if (parts == 1) {\n        unsigned long val = 0;\n        int i = 0;\n        while (i < POWINWORD[base])\n            val = val * base + digvalue[nstr[i++]];\n        zz_seti(a, val);\n        return POWINWORD[base];\n    } else {\n        int hi = parts/2;\n        int lo = parts - hi;\n        zz_ptr hires = acton_malloc(sizeof(zz_struct));\n        zz_ptr lores = acton_malloc(sizeof(zz_struct));\n        zz_init(hires);\n        zz_init(lores);\n        int hidigs = set_str0(hires, nstr, base, hi);\n        int lodigs = set_str0(lores, &nstr[hi * POWINWORD[base]], base, lo);\n        zz_seti(a, base);\n        zz_powi(a, a, POWINWORD[base] * lo);\n        zz_mul(a, a, hires);\n        zz_add(a, a, lores);\n        return hidigs + lodigs;\n    }\n}\n\n\nint set_str(zz_ptr a, unsigned char *nstr, B_int intbase) {\n    int pre = 0;\n    int sgn = 1;\n    while(isspace(nstr[pre])) pre++;   // should leading spaces be allowed?\n    if(nstr[pre]=='+')\n        pre++;\n    else if (nstr[pre]=='-') {\n        sgn = -1;\n        pre++;\n    }\n    int len = 0;\n    int pre_len = pre;\n    unsigned char basefromstr = 0;\n    if (nstr[pre]=='0') {\n        pre++; \n        if (nstr[pre]=='x' || nstr[pre]=='X') {\n            basefromstr = 16; pre++; pre_len += 2;\n        } else if (nstr[pre]=='o' || nstr[pre]=='O') {\n            basefromstr = 8; pre++; pre_len += 2;\n        } else if (nstr[pre]=='b' || nstr[pre]=='B') {\n            basefromstr = 2; pre++; pre_len += 2;\n        } else\n            len++;\n    }\n    unsigned char basefrompar = 0;\n    if (!intbase)\n        basefrompar = 0;\n    else {\n        long baseval = fromB_int(intbase);\n        if (baseval < 2 || baseval > 36) {\n            char errmsg[1024];\n            snprintf(errmsg, sizeof(errmsg), \"integer type constructor: base parameter %ld is out of range (must be between 2 and 36, inclusive)\", baseval);\n            $RAISE((B_BaseException)$NEW(B_ValueError,to$str(errmsg)));\n        } else\n            basefrompar = (unsigned char)baseval;\n    }\n    unsigned char base;\n    if (basefrompar==0) \n        base = basefromstr ? basefromstr : 10;\n    else if (basefromstr==0) \n        base = basefrompar;\n    else if (basefromstr != basefrompar) {\n        char errmsg[1024];\n        snprintf(errmsg, sizeof(errmsg), \"integer type constructor: base specified in str (%d) is in conflict with base in parameter base (%d)\", basefromstr, basefrompar);\n        $RAISE((B_BaseException)$NEW(B_ValueError,to$str(errmsg)));\n    } else\n        base = basefromstr; // which is equal to basefrompar\n    while (digvalue[nstr[pre]] < base) {\n        len++;\n        pre++;\n    }\n    if (len == 0 || nstr[pre] != 0) {\n        char errmsg[1024];\n        snprintf(errmsg, sizeof(errmsg), \"integer type constructor: string \\\"%s\\\" cannot be interpreted as an int in base %d\", nstr,base);\n        $RAISE((B_BaseException)$NEW(B_ValueError,to$str(errmsg)));\n    }\n    nstr += pre_len;\n    \n    int parts = len / POWINWORD[base];\n    int offset =  len % POWINWORD[base];\n    \n    if (offset == 0) {\n        return set_str0(a, nstr, base, parts);\n        a->size *= sgn;\n    } else {\n        unsigned long headval = 0;\n        int partdigits = 0;\n        int i = 0;\n        while (i < offset)\n            headval = headval * base + digvalue[nstr[i++]];\n        if (parts > 0) {\n            zz_ptr res0 = acton_malloc(sizeof(zz_struct));\n            zz_init(res0);\n            partdigits = set_str0(res0, &nstr[offset], base, parts);\n            zz_seti(a, base);\n            zz_powi(a, a, POWINWORD[base] * parts);\n            zz_muli(a, a, headval);\n            zz_add(a, a, res0);\n        } else {\n            zz_seti(a, headval);\n        }\n        a->size *= sgn;\n        return pre; // we shouldn't return chars consumed since we throw exception if whole string not consumed.\n    } \n}\n\n\n// gcd functions from BSDNT //////////////////////////////////\nB_bigint $gcd(B_bigint a, B_bigint b) {\n    B_bigint res = malloc_bigint();\n    zz_gcd(&res->val, &a->val, &b->val);\n    return res;\n}\n\nB_tuple $xgcd(B_bigint a, B_bigint b) {\n    B_bigint d = malloc_bigint();\n    B_bigint s = malloc_bigint();\n    B_bigint t = malloc_bigint();\n    zz_xgcd(&d->val, &s->val, &t->val, &a->val, &b->val);\n    return $NEWTUPLE(3, d, s, t);\n}\n    \nunsigned long B_bigint_longs[256] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9,\n                                   10, 11, 12, 13, 14, 15, 16, 17, 18, 19,\n                                   20, 21, 22, 23, 24, 25, 26, 27, 28, 29,\n                                   30, 31, 32, 33, 34, 35, 36, 37, 38, 39,\n                                   40, 41, 42, 43, 44, 45, 46, 47, 48, 49,\n                                   50, 51, 52, 53, 54, 55, 56, 57, 58, 59,\n                                   60, 61, 62, 63, 64, 65, 66, 67, 68, 69,\n                                   70, 71, 72, 73, 74, 75, 76, 77, 78, 79,\n                                   80, 81, 82, 83, 84, 85, 86, 87, 88, 89,\n                                   90, 91, 92, 93, 94, 95, 96, 97, 98, 99,\n                                   100, 101, 102, 103, 104, 105, 106, 107, 108, 109,\n                                   110, 111, 112, 113, 114, 115, 116, 117, 118, 119,\n                                   120, 121, 122, 123, 124, 125, 126, 127, 128, 129,\n                                   130, 131, 132, 133, 134, 135, 136, 137, 138, 139,\n                                   140, 141, 142, 143, 144, 145, 146, 147, 148, 149,\n                                   150, 151, 152, 153, 154, 155, 156, 157, 158, 159,\n                                   160, 161, 162, 163, 164, 165, 166, 167, 168, 169,\n                                   170, 171, 172, 173, 174, 175, 176, 177, 178, 179,\n                                   180, 181, 182, 183, 184, 185, 186, 187, 188, 189,\n                                   190, 191, 192, 193, 194, 195, 196, 197, 198, 199,\n                                   200, 201, 202, 203, 204, 205, 206, 207, 208, 209,\n                                   210, 211, 212, 213, 214, 215, 216, 217, 218, 219,\n                                   220, 221, 222, 223, 224, 225, 226, 227, 228, 229,\n                                   230, 231, 232, 233, 234, 235, 236, 237, 238, 239,\n                                   240, 241, 242, 243, 244, 245, 246, 247, 248, 249,\n                                   250, 251, 252, 253, 254, 255 };\n\n                           \nstruct B_bigint B_bigint_strs[256] =\n                        {{&B_bigintG_methods, B_bigint_longs, 0, 1},\n                         {&B_bigintG_methods, B_bigint_longs+1, 1, 1},\n                         {&B_bigintG_methods, B_bigint_longs+2, 1, 1},\n                         {&B_bigintG_methods, B_bigint_longs+3, 1, 1},\n                         {&B_bigintG_methods, B_bigint_longs+4, 1, 1},\n                         {&B_bigintG_methods, B_bigint_longs+5, 1, 1},\n                         {&B_bigintG_methods, B_bigint_longs+6, 1, 1},\n                         {&B_bigintG_methods, B_bigint_longs+7, 1, 1},\n                         {&B_bigintG_methods, B_bigint_longs+8, 1, 1},\n                         {&B_bigintG_methods, B_bigint_longs+9, 1, 1},\n                         {&B_bigintG_methods, B_bigint_longs+10, 1, 1},\n                         {&B_bigintG_methods, B_bigint_longs+11, 1, 1},\n                         {&B_bigintG_methods, B_bigint_longs+12, 1, 1},\n                         {&B_bigintG_methods, B_bigint_longs+13, 1, 1},\n                         {&B_bigintG_methods, B_bigint_longs+14, 1, 1},\n                         {&B_bigintG_methods, B_bigint_longs+15, 1, 1},\n                         {&B_bigintG_methods, B_bigint_longs+16, 1, 1},\n                         {&B_bigintG_methods, B_bigint_longs+17, 1, 1},\n                         {&B_bigintG_methods, B_bigint_longs+18, 1, 1},\n                         {&B_bigintG_methods, B_bigint_longs+19, 1, 1},\n                         {&B_bigintG_methods, B_bigint_longs+20, 1, 1},\n                         {&B_bigintG_methods, B_bigint_longs+21, 1, 1},\n                         {&B_bigintG_methods, B_bigint_longs+22, 1, 1},\n                         {&B_bigintG_methods, B_bigint_longs+23, 1, 1},\n                         {&B_bigintG_methods, B_bigint_longs+24, 1, 1},\n                         {&B_bigintG_methods, B_bigint_longs+25, 1, 1},\n                         {&B_bigintG_methods, B_bigint_longs+26, 1, 1},\n                         {&B_bigintG_methods, B_bigint_longs+27, 1, 1},\n                         {&B_bigintG_methods, B_bigint_longs+28, 1, 1},\n                         {&B_bigintG_methods, B_bigint_longs+29, 1, 1},\n                         {&B_bigintG_methods, B_bigint_longs+30, 1, 1},\n                         {&B_bigintG_methods, B_bigint_longs+31, 1, 1},\n                         {&B_bigintG_methods, B_bigint_longs+32, 1, 1},\n                         {&B_bigintG_methods, B_bigint_longs+33, 1, 1},\n                         {&B_bigintG_methods, B_bigint_longs+34, 1, 1},\n                         {&B_bigintG_methods, B_bigint_longs+35, 1, 1},\n                         {&B_bigintG_methods, B_bigint_longs+36, 1, 1},\n                         {&B_bigintG_methods, B_bigint_longs+37, 1, 1},\n                         {&B_bigintG_methods, B_bigint_longs+38, 1, 1},\n                         {&B_bigintG_methods, B_bigint_longs+39, 1, 1},\n                         {&B_bigintG_methods, B_bigint_longs+40, 1, 1},\n                         {&B_bigintG_methods, B_bigint_longs+41, 1, 1},\n                         {&B_bigintG_methods, B_bigint_longs+42, 1, 1},\n                         {&B_bigintG_methods, B_bigint_longs+43, 1, 1},\n                         {&B_bigintG_methods, B_bigint_longs+44, 1, 1},\n                         {&B_bigintG_methods, B_bigint_longs+45, 1, 1},\n                         {&B_bigintG_methods, B_bigint_longs+46, 1, 1},\n                         {&B_bigintG_methods, B_bigint_longs+47, 1, 1},\n                         {&B_bigintG_methods, B_bigint_longs+48, 1, 1},\n                         {&B_bigintG_methods, B_bigint_longs+49, 1, 1},\n                         {&B_bigintG_methods, B_bigint_longs+50, 1, 1},\n                         {&B_bigintG_methods, B_bigint_longs+51, 1, 1},\n                         {&B_bigintG_methods, B_bigint_longs+52, 1, 1},\n                         {&B_bigintG_methods, B_bigint_longs+53, 1, 1},\n                         {&B_bigintG_methods, B_bigint_longs+54, 1, 1},\n                         {&B_bigintG_methods, B_bigint_longs+55, 1, 1},\n                         {&B_bigintG_methods, B_bigint_longs+56, 1, 1},\n                         {&B_bigintG_methods, B_bigint_longs+57, 1, 1},\n                         {&B_bigintG_methods, B_bigint_longs+58, 1, 1},\n                         {&B_bigintG_methods, B_bigint_longs+59, 1, 1},\n                         {&B_bigintG_methods, B_bigint_longs+60, 1, 1},\n                         {&B_bigintG_methods, B_bigint_longs+61, 1, 1},\n                         {&B_bigintG_methods, B_bigint_longs+62, 1, 1},\n                         {&B_bigintG_methods, B_bigint_longs+63, 1, 1},\n                         {&B_bigintG_methods, B_bigint_longs+64, 1, 1},\n                         {&B_bigintG_methods, B_bigint_longs+65, 1, 1},\n                         {&B_bigintG_methods, B_bigint_longs+66, 1, 1},\n                         {&B_bigintG_methods, B_bigint_longs+67, 1, 1},\n                         {&B_bigintG_methods, B_bigint_longs+68, 1, 1},\n                         {&B_bigintG_methods, B_bigint_longs+69, 1, 1},\n                         {&B_bigintG_methods, B_bigint_longs+70, 1, 1},\n                         {&B_bigintG_methods, B_bigint_longs+71, 1, 1},\n                         {&B_bigintG_methods, B_bigint_longs+72, 1, 1},\n                         {&B_bigintG_methods, B_bigint_longs+73, 1, 1},\n                         {&B_bigintG_methods, B_bigint_longs+74, 1, 1},\n                         {&B_bigintG_methods, B_bigint_longs+75, 1, 1},\n                         {&B_bigintG_methods, B_bigint_longs+76, 1, 1},\n                         {&B_bigintG_methods, B_bigint_longs+77, 1, 1},\n                         {&B_bigintG_methods, B_bigint_longs+78, 1, 1},\n                         {&B_bigintG_methods, B_bigint_longs+79, 1, 1},\n                         {&B_bigintG_methods, B_bigint_longs+80, 1, 1},\n                         {&B_bigintG_methods, B_bigint_longs+81, 1, 1},\n                         {&B_bigintG_methods, B_bigint_longs+82, 1, 1},\n                         {&B_bigintG_methods, B_bigint_longs+83, 1, 1},\n                         {&B_bigintG_methods, B_bigint_longs+84, 1, 1},\n                         {&B_bigintG_methods, B_bigint_longs+85, 1, 1},\n                         {&B_bigintG_methods, B_bigint_longs+86, 1, 1},\n                         {&B_bigintG_methods, B_bigint_longs+87, 1, 1},\n                         {&B_bigintG_methods, B_bigint_longs+88, 1, 1},\n                         {&B_bigintG_methods, B_bigint_longs+89, 1, 1},\n                         {&B_bigintG_methods, B_bigint_longs+90, 1, 1},\n                         {&B_bigintG_methods, B_bigint_longs+91, 1, 1},\n                         {&B_bigintG_methods, B_bigint_longs+92, 1, 1},\n                         {&B_bigintG_methods, B_bigint_longs+93, 1, 1},\n                         {&B_bigintG_methods, B_bigint_longs+94, 1, 1},\n                         {&B_bigintG_methods, B_bigint_longs+95, 1, 1},\n                         {&B_bigintG_methods, B_bigint_longs+96, 1, 1},\n                         {&B_bigintG_methods, B_bigint_longs+97, 1, 1},\n                         {&B_bigintG_methods, B_bigint_longs+98, 1, 1},\n                         {&B_bigintG_methods, B_bigint_longs+99, 1, 1},\n                         {&B_bigintG_methods, B_bigint_longs+100, 1, 1},\n                         {&B_bigintG_methods, B_bigint_longs+101, 1, 1},\n                         {&B_bigintG_methods, B_bigint_longs+102, 1, 1},\n                         {&B_bigintG_methods, B_bigint_longs+103, 1, 1},\n                         {&B_bigintG_methods, B_bigint_longs+104, 1, 1},\n                         {&B_bigintG_methods, B_bigint_longs+105, 1, 1},\n                         {&B_bigintG_methods, B_bigint_longs+106, 1, 1},\n                         {&B_bigintG_methods, B_bigint_longs+107, 1, 1},\n                         {&B_bigintG_methods, B_bigint_longs+108, 1, 1},\n                         {&B_bigintG_methods, B_bigint_longs+109, 1, 1},\n                         {&B_bigintG_methods, B_bigint_longs+110, 1, 1},\n                         {&B_bigintG_methods, B_bigint_longs+111, 1, 1},\n                         {&B_bigintG_methods, B_bigint_longs+112, 1, 1},\n                         {&B_bigintG_methods, B_bigint_longs+113, 1, 1},\n                         {&B_bigintG_methods, B_bigint_longs+114, 1, 1},\n                         {&B_bigintG_methods, B_bigint_longs+115, 1, 1},\n                         {&B_bigintG_methods, B_bigint_longs+116, 1, 1},\n                         {&B_bigintG_methods, B_bigint_longs+117, 1, 1},\n                         {&B_bigintG_methods, B_bigint_longs+118, 1, 1},\n                         {&B_bigintG_methods, B_bigint_longs+119, 1, 1},\n                         {&B_bigintG_methods, B_bigint_longs+120, 1, 1},\n                         {&B_bigintG_methods, B_bigint_longs+121, 1, 1},\n                         {&B_bigintG_methods, B_bigint_longs+122, 1, 1},\n                         {&B_bigintG_methods, B_bigint_longs+123, 1, 1},\n                         {&B_bigintG_methods, B_bigint_longs+124, 1, 1},\n                         {&B_bigintG_methods, B_bigint_longs+125, 1, 1},\n                         {&B_bigintG_methods, B_bigint_longs+126, 1, 1},\n                         {&B_bigintG_methods, B_bigint_longs+127, 1, 1},\n                         {&B_bigintG_methods, B_bigint_longs+128, 1, 1},\n                         {&B_bigintG_methods, B_bigint_longs+129, 1, 1},\n                         {&B_bigintG_methods, B_bigint_longs+130, 1, 1},\n                         {&B_bigintG_methods, B_bigint_longs+131, 1, 1},\n                         {&B_bigintG_methods, B_bigint_longs+132, 1, 1},\n                         {&B_bigintG_methods, B_bigint_longs+133, 1, 1},\n                         {&B_bigintG_methods, B_bigint_longs+134, 1, 1},\n                         {&B_bigintG_methods, B_bigint_longs+135, 1, 1},\n                         {&B_bigintG_methods, B_bigint_longs+136, 1, 1},\n                         {&B_bigintG_methods, B_bigint_longs+137, 1, 1},\n                         {&B_bigintG_methods, B_bigint_longs+138, 1, 1},\n                         {&B_bigintG_methods, B_bigint_longs+139, 1, 1},\n                         {&B_bigintG_methods, B_bigint_longs+140, 1, 1},\n                         {&B_bigintG_methods, B_bigint_longs+141, 1, 1},\n                         {&B_bigintG_methods, B_bigint_longs+142, 1, 1},\n                         {&B_bigintG_methods, B_bigint_longs+143, 1, 1},\n                         {&B_bigintG_methods, B_bigint_longs+144, 1, 1},\n                         {&B_bigintG_methods, B_bigint_longs+145, 1, 1},\n                         {&B_bigintG_methods, B_bigint_longs+146, 1, 1},\n                         {&B_bigintG_methods, B_bigint_longs+147, 1, 1},\n                         {&B_bigintG_methods, B_bigint_longs+148, 1, 1},\n                         {&B_bigintG_methods, B_bigint_longs+149, 1, 1},\n                         {&B_bigintG_methods, B_bigint_longs+150, 1, 1},\n                         {&B_bigintG_methods, B_bigint_longs+151, 1, 1},\n                         {&B_bigintG_methods, B_bigint_longs+152, 1, 1},\n                         {&B_bigintG_methods, B_bigint_longs+153, 1, 1},\n                         {&B_bigintG_methods, B_bigint_longs+154, 1, 1},\n                         {&B_bigintG_methods, B_bigint_longs+155, 1, 1},\n                         {&B_bigintG_methods, B_bigint_longs+156, 1, 1},\n                         {&B_bigintG_methods, B_bigint_longs+157, 1, 1},\n                         {&B_bigintG_methods, B_bigint_longs+158, 1, 1},\n                         {&B_bigintG_methods, B_bigint_longs+159, 1, 1},\n                         {&B_bigintG_methods, B_bigint_longs+160, 1, 1},\n                         {&B_bigintG_methods, B_bigint_longs+161, 1, 1},\n                         {&B_bigintG_methods, B_bigint_longs+162, 1, 1},\n                         {&B_bigintG_methods, B_bigint_longs+163, 1, 1},\n                         {&B_bigintG_methods, B_bigint_longs+164, 1, 1},\n                         {&B_bigintG_methods, B_bigint_longs+165, 1, 1},\n                         {&B_bigintG_methods, B_bigint_longs+166, 1, 1},\n                         {&B_bigintG_methods, B_bigint_longs+167, 1, 1},\n                         {&B_bigintG_methods, B_bigint_longs+168, 1, 1},\n                         {&B_bigintG_methods, B_bigint_longs+169, 1, 1},\n                         {&B_bigintG_methods, B_bigint_longs+170, 1, 1},\n                         {&B_bigintG_methods, B_bigint_longs+171, 1, 1},\n                         {&B_bigintG_methods, B_bigint_longs+172, 1, 1},\n                         {&B_bigintG_methods, B_bigint_longs+173, 1, 1},\n                         {&B_bigintG_methods, B_bigint_longs+174, 1, 1},\n                         {&B_bigintG_methods, B_bigint_longs+175, 1, 1},\n                         {&B_bigintG_methods, B_bigint_longs+176, 1, 1},\n                         {&B_bigintG_methods, B_bigint_longs+177, 1, 1},\n                         {&B_bigintG_methods, B_bigint_longs+178, 1, 1},\n                         {&B_bigintG_methods, B_bigint_longs+179, 1, 1},\n                         {&B_bigintG_methods, B_bigint_longs+180, 1, 1},\n                         {&B_bigintG_methods, B_bigint_longs+181, 1, 1},\n                         {&B_bigintG_methods, B_bigint_longs+182, 1, 1},\n                         {&B_bigintG_methods, B_bigint_longs+183, 1, 1},\n                         {&B_bigintG_methods, B_bigint_longs+184, 1, 1},\n                         {&B_bigintG_methods, B_bigint_longs+185, 1, 1},\n                         {&B_bigintG_methods, B_bigint_longs+186, 1, 1},\n                         {&B_bigintG_methods, B_bigint_longs+187, 1, 1},\n                         {&B_bigintG_methods, B_bigint_longs+188, 1, 1},\n                         {&B_bigintG_methods, B_bigint_longs+189, 1, 1},\n                         {&B_bigintG_methods, B_bigint_longs+190, 1, 1},\n                         {&B_bigintG_methods, B_bigint_longs+191, 1, 1},\n                         {&B_bigintG_methods, B_bigint_longs+192, 1, 1},\n                         {&B_bigintG_methods, B_bigint_longs+193, 1, 1},\n                         {&B_bigintG_methods, B_bigint_longs+194, 1, 1},\n                         {&B_bigintG_methods, B_bigint_longs+195, 1, 1},\n                         {&B_bigintG_methods, B_bigint_longs+196, 1, 1},\n                         {&B_bigintG_methods, B_bigint_longs+197, 1, 1},\n                         {&B_bigintG_methods, B_bigint_longs+198, 1, 1},\n                         {&B_bigintG_methods, B_bigint_longs+199, 1, 1},\n                         {&B_bigintG_methods, B_bigint_longs+200, 1, 1},\n                         {&B_bigintG_methods, B_bigint_longs+201, 1, 1},\n                         {&B_bigintG_methods, B_bigint_longs+202, 1, 1},\n                         {&B_bigintG_methods, B_bigint_longs+203, 1, 1},\n                         {&B_bigintG_methods, B_bigint_longs+204, 1, 1},\n                         {&B_bigintG_methods, B_bigint_longs+205, 1, 1},\n                         {&B_bigintG_methods, B_bigint_longs+206, 1, 1},\n                         {&B_bigintG_methods, B_bigint_longs+207, 1, 1},\n                         {&B_bigintG_methods, B_bigint_longs+208, 1, 1},\n                         {&B_bigintG_methods, B_bigint_longs+209, 1, 1},\n                         {&B_bigintG_methods, B_bigint_longs+210, 1, 1},\n                         {&B_bigintG_methods, B_bigint_longs+211, 1, 1},\n                         {&B_bigintG_methods, B_bigint_longs+212, 1, 1},\n                         {&B_bigintG_methods, B_bigint_longs+213, 1, 1},\n                         {&B_bigintG_methods, B_bigint_longs+214, 1, 1},\n                         {&B_bigintG_methods, B_bigint_longs+215, 1, 1},\n                         {&B_bigintG_methods, B_bigint_longs+216, 1, 1},\n                         {&B_bigintG_methods, B_bigint_longs+217, 1, 1},\n                         {&B_bigintG_methods, B_bigint_longs+218, 1, 1},\n                         {&B_bigintG_methods, B_bigint_longs+219, 1, 1},\n                         {&B_bigintG_methods, B_bigint_longs+220, 1, 1},\n                         {&B_bigintG_methods, B_bigint_longs+221, 1, 1},\n                         {&B_bigintG_methods, B_bigint_longs+222, 1, 1},\n                         {&B_bigintG_methods, B_bigint_longs+223, 1, 1},\n                         {&B_bigintG_methods, B_bigint_longs+224, 1, 1},\n                         {&B_bigintG_methods, B_bigint_longs+225, 1, 1},\n                         {&B_bigintG_methods, B_bigint_longs+226, 1, 1},\n                         {&B_bigintG_methods, B_bigint_longs+227, 1, 1},\n                         {&B_bigintG_methods, B_bigint_longs+228, 1, 1},\n                         {&B_bigintG_methods, B_bigint_longs+229, 1, 1},\n                         {&B_bigintG_methods, B_bigint_longs+230, 1, 1},\n                         {&B_bigintG_methods, B_bigint_longs+231, 1, 1},\n                         {&B_bigintG_methods, B_bigint_longs+232, 1, 1},\n                         {&B_bigintG_methods, B_bigint_longs+233, 1, 1},\n                         {&B_bigintG_methods, B_bigint_longs+234, 1, 1},\n                         {&B_bigintG_methods, B_bigint_longs+235, 1, 1},\n                         {&B_bigintG_methods, B_bigint_longs+236, 1, 1},\n                         {&B_bigintG_methods, B_bigint_longs+237, 1, 1},\n                         {&B_bigintG_methods, B_bigint_longs+238, 1, 1},\n                         {&B_bigintG_methods, B_bigint_longs+239, 1, 1},\n                         {&B_bigintG_methods, B_bigint_longs+240, 1, 1},\n                         {&B_bigintG_methods, B_bigint_longs+241, 1, 1},\n                         {&B_bigintG_methods, B_bigint_longs+242, 1, 1},\n                         {&B_bigintG_methods, B_bigint_longs+243, 1, 1},\n                         {&B_bigintG_methods, B_bigint_longs+244, 1, 1},\n                         {&B_bigintG_methods, B_bigint_longs+245, 1, 1},\n                         {&B_bigintG_methods, B_bigint_longs+246, 1, 1},\n                         {&B_bigintG_methods, B_bigint_longs+247, 1, 1},\n                         {&B_bigintG_methods, B_bigint_longs+248, 1, 1},\n                         {&B_bigintG_methods, B_bigint_longs+249, 1, 1},\n                         {&B_bigintG_methods, B_bigint_longs+250, 1, 1},\n                         {&B_bigintG_methods, B_bigint_longs+251, 1, 1},\n                         {&B_bigintG_methods, B_bigint_longs+252, 1, 1},\n                         {&B_bigintG_methods, B_bigint_longs+253, 1, 1},\n                         {&B_bigintG_methods, B_bigint_longs+254, 1, 1},\n                         {&B_bigintG_methods, B_bigint_longs+255, 1, 1}};\n"
  },
  {
    "path": "base/builtin/bigint.h",
    "content": "#include <bsdnt/zz.h>\n\nstruct B_bigint {\n    struct B_bigintG_class *$class;\n    zz_struct val;\n};\n\n// B_int zz$to$int(zz_ptr val);\n\nlong fromB_bigint(B_bigint n);\nB_bigint toB_bigint(long n);\nB_bigint toB_bigint2(char *str);\n\nchar *get_str(zz_ptr n);\n\nB_bigint B_bigintG_new(B_atom a, B_int base);\n\nB_bigint $gcd(B_bigint, B_bigint);\nB_tuple $xgcd(B_bigint, B_bigint);\n\nextern struct B_bigint B_bigint_strs[256];\n\n\n#define ORD_B_bigint__eq__(a,b)  (zz_equal(&a->val,&b->val))\n#define ORD_B_bigint__ne__(a,b)  (1-zz_equal(&a->val,&b->val))\n#define ORD_B_bigint__lt__(a,b)  (zz_cmp(&a->val,&b->val) < 0)\n#define ORD_B_bigint__le__(a,b)  (zz_cmp(&a->val,&b->val) <= 0)\n#define ORD_B_bigint__gt__(a,b)  (zz_cmp(&a->val,&b->val) > 0)\n#define ORD_B_bigint__ge__(a,b)  (zz_cmp(&a->val,&b->val) >= 0)\n\n"
  },
  {
    "path": "base/builtin/bool.c",
    "content": "/*\n * Copyright (C) 2019-2021 Data Ductus AB\n *\n * Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:\n *\n * 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.\n *\n * 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.\n *\n * 3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission.\n *\n * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS \"AS IS\" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n */\n\n\n\n// Serialization ///////////////////////////////////////////////////////////////////////\n\nB_NoneType B_boolD___init__(B_bool self, B_value s){\n    self->val = (s->$class->__bool__(s))->val;\n    return B_None;\n}\n\nB_bool B_boolD___bool__(B_bool self) {\n    return self;\n}\n\nB_str B_boolD___str__(B_bool self) {\n    if (self->val)\n        return to$str(\"True\");\n    else\n        return to$str(\"False\");\n}\n\nB_str B_boolD___repr__(B_bool self) {\n    if (self->val)\n        return to$str(\"True\");\n    else\n        return to$str(\"False\");\n}\n\nvoid B_boolD___serialize__(B_bool self, $Serial$state state) {\n    $val_serialize(BOOL_ID,&self->val,state);\n}\n\nB_bool B_boolD___deserialize__(B_bool self, $Serial$state state) {\n    return toB_bool((long)$val_deserialize(state));\n}\n\nB_bool B_boolG_new(B_value s) {\n    return $NEW(B_bool, s);\n}\n\nB_bool toB_bool(long b) {\n    return b ? B_True : B_False;\n}\n    \nlong fromB_bool(B_bool b) {\n    return b->val;\n}\n\nstruct B_bool $t = {&B_boolG_methods,1L};\nstruct B_bool $f = {&B_boolG_methods,0L};\n\nB_bool B_True = &$t;\nB_bool B_False = &$f;\n\n\nB_bool $default__bool__(B_value self) {\n    return B_True;\n}\n\n// B_HashableD_bool ///////////////////////////////////////////////////////////////////////////////////////////////////////\n\nB_bool B_HashableD_boolD___eq__(B_HashableD_bool wit, B_bool a, B_bool b) {\n    return toB_bool(a->val == b->val);\n}\n\nB_bool B_HashableD_boolD___ne__(B_HashableD_bool wit, B_bool a, B_bool b) {\n    return toB_bool(a->val != b->val);\n}\n\nB_NoneType B_HashableD_boolD_hash(B_HashableD_bool wit, B_bool a, B_hasher h) {\n    zig_hash_wyhash_update(h->_hasher, to$bytesD_len((char *)&(a->val), 8));\n    return B_None;\n}\n"
  },
  {
    "path": "base/builtin/bool.h",
    "content": "struct B_bool {\n  struct B_boolG_class *$class;\n  long val;\n};\n\nB_bool toB_bool(long b);\nlong fromB_bool(B_bool b);\n\nextern B_bool B_True, B_False;\n\nB_bool $default__bool__(B_value);\n"
  },
  {
    "path": "base/builtin/box.c",
    "content": "/*\n * Copyright (C) 2019-2021 Data Ductus AB\n *\n * Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:\n *\n * 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.\n *\n * 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.\n *\n * 3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission.\n *\n * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS \"AS IS\" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n */\n\nB_NoneType $BoxD___init__($Box self, $WORD val) {\n    self->val = val;\n    return B_None;\n}\n\nB_bool $BoxD___bool__($Box self) {\n    B_value it = (B_value)self->val;\n    return it->$class->__bool__(it);\n}\n\nB_str $BoxD___str__($Box self) {\n    B_value it = (B_value)self->val;\n    return it->$class->__str__(it);\n}\n\nB_str $BoxD___repr__($Box self) {\n    B_value it = (B_value)self->val;\n    return it->$class->__repr__(it);\n}\n\nvoid $BoxD___serialize__ ($Box self, $Serial$state state) {\n    $step_serialize(self->val, state);\n}\n\n$Box $BoxD___deserialize__ ($Box self, $Serial$state state) {\n    if (!self) {\n        if (!state) {\n            self = acton_malloc(sizeof(struct $Box));\n            self->$class = &$BoxG_methods;\n            return self;\n        }\n        self = $DNEW($Box, state);\n    }\n    self->val = $step_deserialize(state);\n    return self;\n}\n\n$Box $BoxG_new($WORD G_1) {\n    $Box $tmp = acton_malloc(sizeof(struct $Box));\n    $tmp->$class = &$BoxG_methods;\n    $BoxG_methods.__init__($tmp, G_1);\n    return $tmp;\n}\n\nstruct $BoxG_class $BoxG_methods = {\n    .$GCINFO            = \"$Box\",\n    .$superclass        = ($SuperG_class)&B_ExceptionG_methods,\n    .__init__           = $BoxD___init__,\n    .__bool__           = $BoxD___bool__,\n    .__str__            = $BoxD___str__,\n    .__repr__           = $BoxD___repr__,\n    .__serialize__      = $BoxD___serialize__,\n    .__deserialize__    = $BoxD___deserialize__\n};\n"
  },
  {
    "path": "base/builtin/box.h",
    "content": "struct $Box;\n\ntypedef struct $Box *$Box;\n\nstruct $Box {\n    struct $BoxG_class *$class;\n    $WORD val;\n};\n\nstruct $BoxG_class {\n    char *$GCINFO;\n    int $class_id;\n    $SuperG_class $superclass;\n    B_NoneType (*__init__) ($Box, $WORD);\n    void (*__serialize__) ($Box, $Serial$state);\n    $Box (*__deserialize__) ($Box, $Serial$state);\n    B_bool (*__bool__) ($Box);\n    B_str (*__str__) ($Box);\n    B_str (*__repr__) ($Box);\n};\n\n$Box $BoxG_new($WORD);\n\nextern struct $BoxG_class $BoxG_methods;\n"
  },
  {
    "path": "base/builtin/builtin.c",
    "content": "/*\n * Copyright (C) 2019-2021 Data Ductus AB\n *\n * Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:\n *\n * 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.\n *\n * 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.\n *\n * 3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission.\n *\n * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS \"AS IS\" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n */\n\n#ifdef __linux__\n#ifndef _GNU_SOURCE\n#define _GNU_SOURCE 1\n#endif\n#endif\n\n#include \"builtin.h\"\n\n#include \"common.c\"\n#include \"class_hierarchy.c\"\n#include \"none.c\"\n#include \"box.c\"\n// #include \"atom.c\"\n#include \"int.c\"\n#include \"i32.c\"\n#include \"i16.c\"\n#include \"i8.c\"\n#include \"u64.c\"\n#include \"u32.c\"\n#include \"u16.c\"\n#include \"u8.c\"\n#include \"u1.c\"\n#include \"bigint.c\"\n#include \"float.c\"\n#include \"bool.c\"\n#include \"complex.c\"\n#include \"Iterator.c\"\n#include \"slice.c\"\n//#include \"hash.c\"\n#include \"timsort.c\"\n#include \"list.c\"\n#include \"dict.c\"\n#include \"str.c\"\n#include \"set.c\"\n#include \"tuple.c\"\n#include \"range.c\"\n#include \"exceptions.c\"\n#include \"serialize.c\"\n#include \"registration.c\"\n#include \"function.c\"\n#include \"builtin_functions.c\"\n#include \"env.c\"\n#include \"staticWitnesses.c\"\n#include \"utils.c\"\n#include \"hasher.c\"\n"
  },
  {
    "path": "base/builtin/builtin.h",
    "content": "#pragma once\n#ifdef __linux__\n#ifndef _GNU_SOURCE\n#define _GNU_SOURCE 1\n#endif\n#endif\n\n#include <stdlib.h>\n#include <stddef.h>\n#include <stdio.h>\n#include <stdbool.h>\n#include <string.h>\n#include <math.h>\n#include <ctype.h>\n#include <stdatomic.h>\n\n#include \"../rts/common.h\"\n#include \"common.h\"\n\nstruct B_NoneType;\ntypedef struct B_NoneType *B_NoneType;\n\nstruct B_tuple;\ntypedef struct B_tuple *B_tuple;\n\nstruct $Serial$state;\ntypedef struct $Serial$state *$Serial$state;\n\nstruct $SuperG_class;\ntypedef struct $SuperG_class *$SuperG_class;\n\nstruct $Super;\ntypedef struct $Super *$Super;\n\nstruct $SerializableG_class;\ntypedef struct $SerializableG_class *$SerializableG_class;\n\nstruct $Serializable;\ntypedef struct $Serializable  *$Serializable;\n\n// The following declarations moved here from function.h\n\nstruct $proc;\nstruct $action;\nstruct $mut;\nstruct $pure;\nstruct $Cont;\n\ntypedef struct $proc *$proc;\ntypedef struct $action *$action;\ntypedef struct $mut *$mut;\ntypedef struct $pure *$pure;\ntypedef struct $Cont *$Cont;\n\nenum $RTAG { $RDONE, $RFAIL, $RCONT, $RWAIT };\ntypedef enum $RTAG $RTAG;\n\nstruct $R {\n    $RTAG tag;\n    $Cont cont;\n    $WORD value;\n};\ntypedef struct $R $R;\n\n#define $R_CONT(cont, arg)      ($R){$RCONT, (cont), ($WORD)(arg)}\n#define $R_DONE(value)          ($R){$RDONE, NULL,   (value)}\n#define $R_FAIL(value)          ($R){$RFAIL, NULL,   (value)}\n#define $R_WAIT(cont, value)    ($R){$RWAIT, (cont), (value)}\n\n/////////////////////////////////////////////////////////\n\n// And the following from rts.h /////////////////////////\n\nstruct $Actor;\nstruct $Catcher;\ntypedef struct $Actor *$Actor;\ntypedef struct $Catcher *$Catcher;\n\n#define $Lock                   volatile atomic_flag\n\n///////////////////////////////////////////////////////////\n\n#include \"../out/types/__builtin__.h\"\n#include \"class_hierarchy.h\"\n#include \"serialize.h\"\n#include \"registration.h\"\n#include \"exceptions.h\"\n#include \"Iterator.h\"\n#include \"complx.h\"\n#include \"box.h\"\n#include \"none.h\"\n#include \"slice.h\"\n#include \"float.h\"\n#include \"bool.h\"\n#include \"list.h\"\n#include \"dict.h\"\n#include \"str.h\"\n#include \"set.h\"\n#include \"tuple.h\"\n//#include \"hash.h\"\n#include \"int.h\"\n#include \"i32.h\"\n#include \"i16.h\"\n#include \"i8.h\"\n#include \"u64.h\"\n#include \"u32.h\"\n#include \"u16.h\"\n#include \"u8.h\"\n#include \"u1.h\"\n#include \"bigint.h\"\n#include \"range.h\"\n#include \"function.h\"\n#include \"builtin_functions.h\"\n#include \"env.h\"\n#include \"staticWitnesses.h\"\n#include \"utils.h\"\n#include \"hasher.h\"\n\n"
  },
  {
    "path": "base/builtin/builtin_functions.c",
    "content": "/*\n * Copyright (C) 2019-2021 Data Ductus AB\n *\n * Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:\n *\n * 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.\n *\n * 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.\n *\n * 3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission.\n *\n * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS \"AS IS\" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n */\n\n#include <stdarg.h>\n\n// print //////////////////////////////////////////////////////////////////////////////\n\nstatic $WORD mkstr($WORD w) {\n    B_value w1 = (B_value)w;\n    return w1->$class->__str__(w);\n}\n/*\nB_NoneType B_print(int size, ...) {\n    va_list args;\n    va_start(args,size);\n    if (size > 0) {\n        B_value elem = va_arg(args,B_value);\n        fputs((const char*)elem->$class->__str__(elem)->str,stdout);\n     }\n    for (int i=1; i<size; i++) {\n         putchar(' ');\n         B_value elem = va_arg(args,B_value);\n         fputs((const char*)elem->$class->__str__(elem)->str,stdout);\n     }\n     putchar('\\n');\n     va_end(args);\n     return B_None;\n}\n*/\n\nB_str __str__(B_value x) {\n    if (x == B_None)\n        return to$str(\"None\");\n    else\n        return x->$class->__str__(x);\n}\n\nB_NoneType B_print(B_tuple t, B_str sep_arg, B_str end_arg, B_bool stderr_arg, B_bool flush_arg) {\n    FILE *outfd = stdout;\n    if (stderr_arg && stderr_arg->val) {\n        outfd = stderr;\n    }\n    B_str sep = to$str(\" \");\n    if (sep_arg)\n        sep = sep_arg;\n    B_str end = to$str(\"\\n\");\n    if (end_arg)\n        end = end_arg;\n\n    // Write to temporary buffer first, making us much less prone to interleaved\n    // output from multiple threads. It costs a malloc and some copies but print\n    // should not be used in performance critical code.\n    int tlen = 0;\n    for (int i=0; i<t->size; i++) {\n        B_value elem = (B_value)t->components[i];\n        tlen += __str__(elem)->nbytes + sep->nbytes;\n    }\n    tlen += end->nbytes;\n    char *s = acton_malloc(tlen+1);\n    int pos = 0;\n    for (int i=0; i<t->size; i++) {\n        if (i > 0) {\n            memcpy(s+pos, sep->str, sep->nbytes);\n            pos += sep->nbytes;\n        }\n        B_value elem = (B_value)t->components[i];\n        memcpy(s+pos, __str__(elem)->str, __str__(elem)->nbytes);\n        pos += __str__(elem)->nbytes;\n    }\n    memcpy(s+pos, end->str, end->nbytes);\n    pos += end->nbytes;\n    s[pos] = '\\0';\n    fputs(s, outfd);\n\n    if (flush_arg && flush_arg->val)\n        fflush(outfd);\n    return B_None;\n}\n\n// enumerate //////////////////////////////////////////////////////////////////////////\n\nvoid B_IteratorD_enumerate_init(B_IteratorD_enumerate self, B_Iterator it, B_int n) {\n    self->it = it;\n    self->nxt = fromB_int(n);\n}\n\nB_bool B_IteratorD_enumerate_bool(B_IteratorD_enumerate self) {\n    return B_True;\n}\n\nB_str B_IteratorD_enumerate_str(B_IteratorD_enumerate self) {\n    return $FORMAT(\"<enumerate iterator object at %p>\", self);\n}\n\nvoid B_IteratorD_enumerate_serialize(B_IteratorD_enumerate self,$Serial$state state) {\n    $step_serialize(self->it,state);\n    $step_serialize(toB_int(self->nxt),state);\n}\n\nB_IteratorD_enumerate B_IteratorD_enumerate$_deserialize(B_IteratorD_enumerate res,$Serial$state state) {\n    if (!res)\n        res = $DNEW(B_IteratorD_enumerate,state);\n    res->it = $step_deserialize(state);\n    res->nxt = fromB_int((B_int)$step_deserialize(state));\n    return res;\n}\n\n$WORD B_IteratorD_enumerate_next(B_IteratorD_enumerate it) {\n    $WORD w = it->it->$class->__next__(it->it);\n    return $NEWTUPLE(2,toB_int(it->nxt++),w);\n}\n\nstruct B_IteratorD_enumerateG_class B_IteratorD_enumerateG_methods = {\"B_IteratorD_enumerate\",UNASSIGNED,($SuperG_class)&B_IteratorG_methods,B_IteratorD_enumerate_init,\n                                                                B_IteratorD_enumerate_serialize, B_IteratorD_enumerate$_deserialize, \n                                                                B_IteratorD_enumerate_bool,B_IteratorD_enumerate_str,B_IteratorD_enumerate_str, B_IteratorD_enumerate_next};\n\n\nB_IteratorD_enumerate B_IteratorD_enumerateG_new(B_Iterator it, B_int n) {\n    return $NEW(B_IteratorD_enumerate, it, n);\n}\n\nB_Iterator B_enumerate(B_Iterable wit, $WORD iter, B_int start) {\n    B_Iterator it = wit->$class->__iter__(wit,iter);\n    if (!start)\n        start = toB_int(0);\n    return (B_Iterator)B_IteratorD_enumerateG_new(it,start); \n}\n\n// filter ////////////////////////////////////////////////////////////////////////////////\n\nvoid B_IteratorD_filter_init(B_IteratorD_filter self, B_Iterator it,  $pure f) {\n    self->it = it;\n    self->f = f;\n}\n\nB_bool B_IteratorD_filter_bool(B_IteratorD_filter self) {\n    return B_True;\n}\n\nB_str B_IteratorD_filter_str(B_IteratorD_filter self) {\n    return $FORMAT(\"<filter iterator object at %p>\", self);\n}\n\nvoid B_IteratorD_filter_serialize(B_IteratorD_filter self,$Serial$state state) {\n    $step_serialize(self->it,state);\n}\n\nB_IteratorD_filter B_IteratorD_filter$_deserialize(B_IteratorD_filter res, $Serial$state state) {\n    if (!res)\n        res = $DNEW(B_IteratorD_filter,state);\n    res->it = $step_deserialize(state);\n    return res;\n}\n\n$WORD B_IteratorD_filter_next(B_IteratorD_filter it) {\n    $WORD w;\n    do\n        w = it->it->$class->__next__(it->it);\n    while (!fromB_bool(it->f->$class->__eval__(it->f, w)));\n    return w;\n}\n\nstruct B_IteratorD_filterG_class B_IteratorD_filterG_methods = {\"B_IteratorD_filter\",UNASSIGNED,($SuperG_class)&B_IteratorG_methods,B_IteratorD_filter_init,\n                                                          B_IteratorD_filter_serialize, B_IteratorD_filter$_deserialize, \n                                                          B_IteratorD_filter_bool,B_IteratorD_filter_str,B_IteratorD_filter_str, B_IteratorD_filter_next};\n\nB_IteratorD_filter B_IteratorD_filterG_new(B_Iterator it, $pure f) {\n    return $NEW(B_IteratorD_filter, it, f);\n}\n\nB_Iterator B_filter(B_Iterable wit, $pure f, $WORD iter) {\n    B_Iterator it = wit->$class->__iter__(wit,iter);\n    return (B_Iterator)B_IteratorD_filterG_new(it,f);\n}\n\n// map ////////////////////////////////////////////////////////////////////////////////\n\nvoid B_IteratorD_map_init(B_IteratorD_map self, B_Iterator it, $pure f) {\n    self->it = it;\n    self->f = f;\n}\n\nB_bool B_IteratorD_map_bool(B_IteratorD_map self) {\n    return B_True;\n}\n\nB_str B_IteratorD_map_str(B_IteratorD_map self) {\n    return $FORMAT(\"<map iterator object at %p>\", self);\n}\n\nvoid B_IteratorD_map_serialize(B_IteratorD_map self,$Serial$state state) {\n    $step_serialize(self->it,state);\n}\n\nB_IteratorD_map B_IteratorD_map$_deserialize(B_IteratorD_map res, $Serial$state state) {\n    if (!res)\n        res = $DNEW(B_IteratorD_map,state);\n    res->it = $step_deserialize(state);\n    return res;\n}\n\n$WORD B_IteratorD_map_next(B_IteratorD_map it) {\n    $WORD w = it->it->$class->__next__(it->it);\n    return it->f->$class->__eval__(it->f, w);\n}\n\nstruct B_IteratorD_mapG_class B_IteratorD_mapG_methods = {\"B_IteratorD_map\",UNASSIGNED,($SuperG_class)&B_IteratorG_methods,B_IteratorD_map_init,\n                                                    B_IteratorD_map_serialize, B_IteratorD_map$_deserialize,  \n                                                    B_IteratorD_map_bool,B_IteratorD_map_str,B_IteratorD_map_str, B_IteratorD_map_next};\n\nB_IteratorD_map B_IteratorD_mapG_new(B_Iterator it, $pure f) {\n    return $NEW(B_IteratorD_map, it, f);\n}\n\nB_Iterator B_map(B_Iterable wit, $pure f, $WORD iter) {\n    B_Iterator it = wit->$class->__iter__(wit,iter);\n    return (B_Iterator)B_IteratorD_mapG_new(it,f);\n}\n\n\n// max, min ///////////////////////////////////////////////////////////////////////////////////\n\n$WORD B_max(B_Ord wit, B_Iterable wit2, $WORD iter, $WORD dflt) {\n    $WORD res = dflt;\n    B_Iterator it = wit2->$class->__iter__(wit2,iter);  \n    while(1) {\n        if ($PUSH()) {\n            $WORD nxt = it->$class->__next__(it);\n            if (!res || fromB_bool(wit->$class->__lt__(wit,res,nxt)))\n                res = nxt;\n            $DROP();\n        } else {\n            B_BaseException ex = $POP();\n            if ($ISINSTANCE0(ex, B_StopIteration))\n                break;\n           else\n               $RAISE(ex);\n        }\n    }\n\n    // If no value was found in the iterable\n    if (!res) {\n        if (dflt) {\n            return dflt; // Return the provided default value\n        } else {\n            $RAISE(((B_BaseException)B_ValueErrorG_new($FORMAT(\"max() arg is an empty sequence\"))));\n        }\n    }\n\n    return res;\n}\n\n$WORD B_max_def(B_Ord wit, B_Iterable wit2, $WORD iter, $WORD dflt) {\n    $WORD res = dflt;\n    B_Iterator it = wit2->$class->__iter__(wit2,iter);\n    while(1) {\n        if ($PUSH()) {\n            $WORD nxt = it->$class->__next__(it);\n            if (fromB_bool(wit->$class->__lt__(wit,res,nxt)))\n                res = nxt;\n            $DROP();\n        } else {\n            B_BaseException ex = $POP();\n            if ($ISINSTANCE0(ex, B_StopIteration))\n                break;\n           else\n               $RAISE(ex);\n        }\n    }\n    return res;\n}\n\n$WORD B_min(B_Ord wit, B_Iterable wit2, $WORD iter, $WORD dflt) {\n    $WORD res = NULL;\n    B_Iterator it = wit2->$class->__iter__(wit2,iter);  \n    while(1) {\n        if ($PUSH()) {\n            $WORD nxt = it->$class->__next__(it);\n            if (!res || fromB_bool(wit->$class->__gt__(wit,res,nxt)))\n                res = nxt;\n            $DROP();\n        } else {\n            B_BaseException ex = $POP();\n            if ($ISINSTANCE0(ex, B_StopIteration))\n                break;\n            else\n                $RAISE(ex);\n        }\n    }\n\n    // If no value was found in the iterable\n    if (!res) {\n        if (dflt) {\n            return dflt; // Return the provided default value\n        } else {\n            $RAISE((B_BaseException)B_ValueErrorG_new($FORMAT(\"min() arg is an empty sequence\")));\n        }\n    }\n\n    return res;\n}\n\n$WORD B_min_def(B_Ord wit, B_Iterable wit2, $WORD iter, $WORD dflt) {\n    $WORD res = dflt;\n    B_Iterator it = wit2->$class->__iter__(wit2,iter);  \n    while(1) {\n        if ($PUSH()) {\n            $WORD nxt = it->$class->__next__(it);\n            if (fromB_bool(wit->$class->__gt__(wit,res,nxt)))\n                res = nxt;\n            $DROP();\n        } else {\n            B_BaseException ex = $POP();\n            if ($ISINSTANCE0(ex, B_StopIteration))\n                break;\n            else\n                $RAISE(ex);\n        }\n    }\n    return res;\n}\n\nB_list B_sorted(B_Ord wit, B_Iterable wit2, $WORD iter) {\n    B_CollectionD_SequenceD_list w = B_CollectionD_SequenceD_listG_witness;\n    B_list res = w->$class->__fromiter__(w, wit2, iter);\n    B_tim_sort(wit, res->data, res->length);\n    return res;\n}\n\n// sum /////////////////////////////////////////////////////////////////////////////////\n\n$WORD B_sum(B_Plus wit, B_Iterable wit2, $WORD iter, $WORD start) {\n    B_Iterator it = wit2->$class->__iter__(wit2,iter);  \n    $WORD res = start;\n    if (start == NULL) {\n        res = wit->$class->__zero__(wit);\n    }\n\n    $WORD nxt;\n    while(1) {\n        if ($PUSH()) {\n            nxt = it->$class->__next__(it);\n            res = wit->$class->__add__(wit,res,nxt);\n            $DROP();\n        } else {\n            B_BaseException ex = $POP();\n            if ($ISINSTANCE0(ex, B_StopIteration))\n                break;\n            else\n                $RAISE(ex);\n        }\n    }\n    return res;\n}\n\n// zip ////////////////////////////////////////////////////////////////////////////////\n\nvoid B_IteratorD_zip_init(B_IteratorD_zip self, B_Iterator it1, B_Iterator it2) {\n    self->it1 = it1;\n    self->it2 = it2;\n}\n\nB_bool B_IteratorD_zip_bool(B_IteratorD_zip self) {\n    return B_True;\n}\n\nB_str B_IteratorD_zip_str(B_IteratorD_zip self) {\n    return $FORMAT(\"<zip iterator object at %p>\", self);\n}\n\nvoid B_IteratorD_zip_serialize(B_IteratorD_zip self,$Serial$state state) {\n    $step_serialize(self->it1,state);\n    $step_serialize(self->it2,state);\n}\n\nB_IteratorD_zip B_IteratorD_zip$_deserialize(B_IteratorD_zip res, $Serial$state state) {\n    if (!res)\n        res = $DNEW(B_IteratorD_zip,state);\n    res->it1 = $step_deserialize(state);\n    res->it2 = $step_deserialize(state);\n    return res;\n}\n\n$WORD B_IteratorD_zip_next(B_IteratorD_zip it) {\n    $WORD w1 = it->it1->$class->__next__(it->it1);\n    $WORD w2 = it->it2->$class->__next__(it->it2);\n    return $NEWTUPLE(2,w1,w2);\n}\n\nstruct B_IteratorD_zipG_class B_IteratorD_zipG_methods = {\" B_IteratorD_zip\",UNASSIGNED,($SuperG_class)&B_IteratorG_methods,B_IteratorD_zip_init,\n                                                    B_IteratorD_zip_serialize, B_IteratorD_zip$_deserialize, \n                                                    B_IteratorD_zip_bool,B_IteratorD_zip_str,B_IteratorD_zip_str, B_IteratorD_zip_next};\n\nB_IteratorD_zip B_IteratorD_zipG_new(B_Iterator iter1, B_Iterator iter2) {\n    return $NEW(B_IteratorD_zip, iter1, iter2);\n}\n\n// Note dubious pairings of witnesses and WORDs. This fixes #2140 without breaking any test.\nB_Iterator B_zip (B_Iterable wit1, B_Iterable wit2, $WORD iter1, $WORD iter2) {\n    B_Iterator it1 = wit2->$class->__iter__(wit2,iter1);\n    B_Iterator it2 = wit1->$class->__iter__(wit1,iter2);\n    return (B_Iterator)B_IteratorD_zipG_new(it1,it2);\n}\n\n// EqOpt //////////////////////////////////////////////////////\n\nextern struct $EqOptG_class $EqOptG_methods;\n\nvoid $EqOptD___init__($EqOpt wit, B_Eq W_Eq$A) {\n    wit->W_Eq$A = W_Eq$A;\n}\n\nB_bool $EqOptD_bool($EqOpt self) {\n    return B_True;\n}\n\nB_str $EqOptD_str($EqOpt self) {\n    return $FORMAT(\"<EqOpt witness at %p>\", self);\n}\n\nvoid $EqOptD_serialize($EqOpt self,$Serial$state state) {\n    $step_serialize(self->W_Eq$A,state);\n}\n\n$EqOpt $EqOptD_deserialize($EqOpt res, $Serial$state state) {\n    if (!res)\n        res = $DNEW($EqOpt,state);\n    res->W_Eq$A = $step_deserialize(state);\n    return res;\n}\n\nB_bool $EqOptD___eq__($EqOpt wit, $WORD a, $WORD b) {\n    if (a && b) {\n        return wit->W_Eq$A->$class->__eq__(wit->W_Eq$A, a, b);\n    }\n    return (!a && !b) ? B_True : B_False;\n}\n\nB_bool $EqOptD___ne__($EqOpt wit, $WORD a, $WORD b) {\n    if (a && b)\n        return wit->W_Eq$A->$class->__ne__(wit->W_Eq$A, a, b);\n    return (!a && !b) ? B_False : B_True;\n}\n\nstruct $EqOptG_class $EqOptG_methods = {\"$EqOpt\", UNASSIGNED, NULL, $EqOptD___init__, $EqOptD_serialize, $EqOptD_deserialize, \n                                         $EqOptD_bool, $EqOptD_str, $EqOptD_str, $EqOptD___eq__, $EqOptD___ne__};\n\n\n$EqOpt $EqOptG_new(B_Eq W_Eq$A) {\n    return $NEW($EqOpt, W_Eq$A);\n}\n\n\n// IdentityActor //////////////////////////////////////////////////////\n\nextern struct $IdentityActorG_class $IdentityActorG_methods;\n\nvoid $IdentityActorD___init__($IdentityActor wit) { }\n\nB_bool $IdentityActorD_bool($IdentityActor self) {\n    return B_True;\n}\n\nB_str $IdentityActorD_str($IdentityActor self) {\n    return $FORMAT(\"<IdentityActor witness at %p>\", self);\n}\n\nvoid $IdentityActorD_serialize($IdentityActor self,$Serial$state state) { }\n\n$IdentityActor $IdentityActorD_deserialize($IdentityActor res, $Serial$state state) {\n    if (!res)\n        res = $DNEW($IdentityActor,state);\n    return res;\n}\n\nB_bool $IdentityActorD___is__($IdentityActor wit, $WORD a, $WORD b) {\n    return (a == b) ? B_True : B_False;\n}\n\nB_bool $IdentityActorD___isnot__($IdentityActor wit, $WORD a, $WORD b) {\n    return (a == b) ? B_False : B_True;\n}\n\nstruct $IdentityActorG_class $IdentityActorG_methods = {\"$IdentityActor\", UNASSIGNED, NULL, $IdentityActorD___init__, $IdentityActorD_serialize, $IdentityActorD_deserialize, \n                                         $IdentityActorD_bool, $IdentityActorD_str, $IdentityActorD_str, $IdentityActorD___is__, $IdentityActorD___isnot__};\n\n\n$IdentityActor $IdentityActorG_new() {\n    return $NEW($IdentityActor);\n}\n\n\n// Various small functions //////////////////////////////////////////////////////////////\n\n// Code generated by acton\n/*\n$WORD B_abs (B_Number W_149, B_Real W_148, $WORD x) {\n    return W_149->$class->__abs__(W_149, x, W_148);\n}\n\nB_bool B_all (B_Iterable W_164, $WORD it) {\n    B_Iterator nB_iter = W_164->$class->__iter__(W_164, it);\n    $WORD n$1val = nB_iter->$class->__next__(nB_iter);\n    while ($ISNOTNONE(n$1val)) {\n        B_value x = (B_value)n$1val;\n        if (!x->$class->__bool__(x)->val) {\n            return (B_bool)B_False;\n        }\n        n$1val = nB_iter->$class->__next__(nB_iter);\n    }\n    return (B_bool)B_True;\n}\nB_bool B_any (B_Iterable W_179, $WORD it) {\n    B_Iterator n$2iter = W_179->$class->__iter__(W_179, it);\n    $WORD n$3val = n$2iter->$class->__next__(n$2iter);\n    while ($ISNOTNONE(n$3val)) {\n        B_value x = (B_value)n$3val;\n        if (x->$class->__bool__(x)->val) {\n            return (B_bool)B_True;\n        }\n        n$3val = n$2iter->$class->__next__(n$2iter);\n    }\n    return (B_bool)B_False;\n}\n\nB_tuple B_divmod (B_Integral W_225, $WORD a, $WORD b) {\n    return W_225->$class->__divmod__(W_225, a, b);\n}\nB_Iterator B_iter (B_Iterable W_278, $WORD x) {\n    return W_278->$class->__iter__(W_278, x);\n}\nB_int B_len (B_Collection W_301, $WORD x) {\n    return W_301->$class->__len__(W_301, x);\n}\n\n$WORD B_pow (B_Number W_344, $WORD a, $WORD b) {\n    return W_344->$class->__pow__(W_344, a, b);\n}\n\nB_str B_repr(B_value x) {\n    return x->$class->__repr__(x);\n}\n\nB_Iterator B_reversed (B_Sequence W_369, $WORD seq) {\n    return W_369->$class->__reversed__(W_369, seq);\n}\n$WORD B_round (B_Real W_395, $WORD x, B_int n) {\n    return W_395->$class->__round__(W_395, x, n);\n}\n*/\n\n$WORD $ASSERT(B_bool test, B_str msg) {\n    if (!test->val) {\n        $RAISE((B_BaseException)$NEW(B_AssertionError,msg));\n        return NULL; // to avoid compiler warning\n    }\n    return B_None;\n}\n"
  },
  {
    "path": "base/builtin/builtin_functions.h",
    "content": "#pragma once\n// #include \"function.h\"\n\n \n// enumerate ////////////////////////////////////////////////////////////\n\nstruct B_IteratorD_enumerate;\ntypedef struct B_IteratorD_enumerate *B_IteratorD_enumerate;\n\nstruct B_IteratorD_enumerateG_class {\n  char *$GCINFO;\n  int $class_id;\n  $SuperG_class $superclass;\n  void (*__init__)(B_IteratorD_enumerate, B_Iterator,B_int);\n  void (*__serialize__)(B_IteratorD_enumerate,$Serial$state);\n  B_IteratorD_enumerate (*__deserialize__)(B_IteratorD_enumerate,$Serial$state);\n  B_bool (*__bool__)(B_IteratorD_enumerate);\n  B_str (*__str__)(B_IteratorD_enumerate);\n  B_str (*__repr__)(B_IteratorD_enumerate);\n  $WORD(*__next__)(B_IteratorD_enumerate);\n};\n\nstruct B_IteratorD_enumerate {\n  struct B_IteratorD_enumerateG_class *$class;\n  B_Iterator it;\n  int nxt;\n};\n\nextern struct B_IteratorD_enumerateG_class B_IteratorD_enumerateG_methods;\nB_IteratorD_enumerate B_IteratorD_enumerateG_new(B_Iterator,B_int);\n\n\n// filter ////////////////////////////////////////////////////////////\n\nB_Iterator B_filter (B_Iterable, $pure, $WORD);\n\nstruct B_IteratorD_filter;\ntypedef struct B_IteratorD_filter *B_IteratorD_filter;\n\nstruct B_IteratorD_filterG_class {\n  char *$GCINFO;\n  int $class_id;\n  $SuperG_class $superclass;\n  void (*__init__)(B_IteratorD_filter, B_Iterator, $pure);\n  void (*__serialize__)(B_IteratorD_filter,$Serial$state);\n  B_IteratorD_filter (*__deserialize__)(B_IteratorD_filter,$Serial$state);\n  B_bool (*__bool__)(B_IteratorD_filter);\n  B_str (*__str__)(B_IteratorD_filter);\n  B_str (*__repr__)(B_IteratorD_filter);\n  $WORD(*__next__)(B_IteratorD_filter);\n};\n\nstruct B_IteratorD_filter {\n  struct B_IteratorD_filterG_class *$class;\n  B_Iterator it;\n  $pure f;\n};\n\nextern struct B_IteratorD_filterG_class B_IteratorD_filterG_methods;\nB_IteratorD_filter B_IteratorD_filterG_new(B_Iterator, $pure);\n\n// map ////////////////////////////////////////////////////////////\n\nB_Iterator B_map (B_Iterable, $pure, $WORD);\n\nstruct B_IteratorD_map;\ntypedef struct B_IteratorD_map *B_IteratorD_map;\n\nstruct B_IteratorD_mapG_class {\n  char *$GCINFO;\n  int $class_id;\n  $SuperG_class $superclass;\n  void (*__init__)(B_IteratorD_map, B_Iterator, $pure);\n  void (*__serialize__)(B_IteratorD_map,$Serial$state);\n  B_IteratorD_map (*__deserialize__)(B_IteratorD_map,$Serial$state);\n  B_bool (*__bool__)(B_IteratorD_map);\n  B_str (*__str__)(B_IteratorD_map);\n  B_str (*__repr__)(B_IteratorD_map);\n  $WORD(*__next__)(B_IteratorD_map);\n};\n\nstruct B_IteratorD_map {\n  struct B_IteratorD_mapG_class *$class;\n  B_Iterator it;\n  $pure f;\n};\n\nextern struct B_IteratorD_mapG_class B_IteratorD_mapG_methods;\nB_IteratorD_map B_IteratorD_mapG_new(B_Iterator, $pure);\n\n// zip ////////////////////////////////////////////////////////////\n\nstruct B_IteratorD_zip;\ntypedef struct B_IteratorD_zip *B_IteratorD_zip;\n\nstruct B_IteratorD_zipG_class {\n  char *$GCINFO;\n  int $class_id;\n  $SuperG_class $superclass;\n  void (*__init__)(B_IteratorD_zip, B_Iterator, B_Iterator);\n  void (*__serialize__)(B_IteratorD_zip,$Serial$state);\n  B_IteratorD_zip (*__deserialize__)(B_IteratorD_zip,$Serial$state);\n  B_bool (*__bool__)(B_IteratorD_zip);\n  B_str (*__str__)(B_IteratorD_zip);\n  B_str (*__repr__)(B_IteratorD_zip);\n  $WORD(*__next__)(B_IteratorD_zip);\n};\n\nstruct B_IteratorD_zip {\n  struct B_IteratorD_zipG_class *$class;\n  B_Iterator it1;\n  B_Iterator it2;\n};\n\nextern struct B_IteratorD_zipG_class B_IteratorD_zipG_methods;\nB_IteratorD_zip B_IteratorD_zipG_new(B_Iterator, B_Iterator);\n\nB_Iterator B_zip(B_Iterable wit1, B_Iterable wit2, $WORD iter1, $WORD iter2);\n\n\n// EqOpt //////////////////////////////////////////////////////\n\nstruct $EqOpt;\ntypedef struct $EqOpt *$EqOpt;\n\nstruct $EqOptG_class {\n    char *$GCINFO;\n    int $class_id;\n    $SuperG_class $superclass;\n    void (*__init__)($EqOpt, B_Eq);\n    void (*__serialize__)($EqOpt,$Serial$state);\n    $EqOpt (*__deserialize__)($EqOpt,$Serial$state);\n    B_bool (*__bool__)($EqOpt);\n    B_str (*__str__)($EqOpt);\n    B_str (*__repr__)($EqOpt);\n    B_bool (*__eq__)($EqOpt, $WORD, $WORD);\n    B_bool (*__ne__)($EqOpt, $WORD, $WORD);\n};\n\nstruct $EqOpt {\n    struct $EqOptG_class *$class;\n    B_Eq W_Eq$A;\n};\n\n$EqOpt $EqOptG_new(B_Eq);\n\n\n// IdentityActor //////////////////////////////////////////////////////\n\nstruct $IdentityActor;\ntypedef struct $IdentityActor *$IdentityActor;\n\nstruct $IdentityActorG_class {\n    char *$GCINFO;\n    int $class_id;\n    $SuperG_class $superclass;\n    void (*__init__)($IdentityActor);\n    void (*__serialize__)($IdentityActor,$Serial$state);\n    $IdentityActor (*__deserialize__)($IdentityActor,$Serial$state);\n    B_bool (*__bool__)($IdentityActor);\n    B_str (*__str__)($IdentityActor);\n    B_str (*__repr__)($IdentityActor);\n    B_bool (*__is__)($IdentityActor, $WORD, $WORD);\n    B_bool (*__isnot__)($IdentityActor, $WORD, $WORD);\n};\n\nstruct $IdentityActor {\n    struct $IdentityActorG_class *$class;\n};\n\n$IdentityActor $IdentityActorG_new();\n\n\n// Various small functions //////////////////////////////////////////////////////////\n\n$WORD B_min(B_Ord wit, B_Iterable wit2, $WORD iter, $WORD deflt);\n$WORD B_max(B_Ord wit, B_Iterable wit2, $WORD iter, $WORD deflt);\n$WORD B_min_def(B_Ord wit, B_Iterable wit2, $WORD iter, $WORD deflt);\n$WORD B_max_def(B_Ord wit, B_Iterable wit2, $WORD iter, $WORD deflt);\n\n// Signatures generated by acton \n\n/*\n$WORD B_abs (B_Real, B_Number, $WORD);\nB_bool B_all (B_Iterable, $WORD);\nB_bool B_any (B_Iterable, $WORD);\nB_tuple B_divmod (B_Integral, $WORD, $WORD);\nB_u64 B_hash (B_Hashable, $WORD);\nB_Iterator B_iter (B_Iterable, $WORD);\nB_int B_len (B_Collection, $WORD);\n$WORD $next (B_Iterator);\n$WORD B_pow (B_Number, $WORD, $WORD);\nB_str B_repr(B_value);\nB_Iterator B_reversed (B_Sequence, $WORD);\n$WORD B_round (B_Real, $WORD, B_int);\n$WORD B_sum(B_Plus, B_Iterable, $WORD, $WORD);\n*/\n\n$WORD $ASSERT(B_bool, B_str);\n"
  },
  {
    "path": "base/builtin/class_hierarchy.c",
    "content": "/*\n * Copyright (C) 2019-2021 Data Ductus AB\n *\n * Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:\n *\n * 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.\n *\n * 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.\n *\n * 3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission.\n *\n * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS \"AS IS\" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n */\n\n$Serializable $SerializableG_new() {\n    return $NEW($Serializable);\n}\n\nB_NoneType $SerializableD___init__ ($Serializable self) {\n    return B_None;\n}\n/*\nB_value B_valueG_new() {\n    return $NEW(B_value);\n}\n\nB_NoneType B_valueD___init__ (B_value self) {\n    return B_None;\n}\n\nB_object B_objectG_new() {\n    return $NEW(B_object);\n}\n\nB_NoneType B_objectD___init__ (B_object self) {\n    return B_None;\n}\n*/\nB_str B_valueD___str__(B_value self) {\n    return $FORMAT(\"<%s object at %p>\", unmangle_name(self->$class->$GCINFO), self);\n}\n\nB_str B_valueD___repr__(B_value self) {\n    return $FORMAT(\"<%s object at %p>\", unmangle_name(self->$class->$GCINFO), self);\n}\n\nB_str B_objectD___str__(B_object self) {\n    return $FORMAT(\"<%s object at %p>\", unmangle_name(self->$class->$GCINFO), self);\n}\n\nB_bool B_valueD___bool__(B_value self) {\n    return B_True;\n}\nB_bool B_objectD___bool__(B_object self) {\n    return B_True;\n}\n\nstruct $SerializableG_class $SerializableG_methods = {\"$Serializable\",UNASSIGNED,NULL, $SerializableD___init__,NULL,NULL};\n\n//struct B_valueG_class B_valueG_methods = {\"B_value\",UNASSIGNED,($SuperG_class)&$SerializableG_methods,B_valueD___init__,NULL,NULL, B_valueD___bool__,B_valueD___str__,B_valueD___str__};\n\n//struct B_objectG_class B_objectG_methods = {\"B_object\",UNASSIGNED,($SuperG_class)&B_valueG_methods,B_objectD___init__,NULL,NULL,B_objectD___bool__,B_objectD___str__,B_objectD___str__};\n"
  },
  {
    "path": "base/builtin/class_hierarchy.h",
    "content": "// Super //////////////////////////////////////////////////////////////\n\n// This is only used for typing the $superclass field in classes.\n\n\nstruct $SuperG_class {\n    char *$GCINFO;\n    int $class_id;\n    $SuperG_class $superclass;\n};\n\nstruct $Super {\n    $SuperG_class $class;\n};\n\n/*\ntypedef struct $InitializableG_class *$InitializableG_class;\n\ntypedef struct $Initializable  *$Initializable;\n\nstruct $InitializableG_class {\n    char *$GCINFO;\n    int $class_id;\n    $SuperG_class $superclass;                   // = NULL\n    B_NoneType (*__init__)($Initializable);\n};\n\nstruct $Initializable {\n    struct $InitializableG_class *$class;\n};\n\nextern struct $InitializableG_class $InitializableG_methods;\n$Initializable $InitializableG_new();\n*/\n\n// Serializable //////////////////////////////////////////////////////\n\nstruct $SerializableG_class {\n    char *$GCINFO;\n    int $class_id;\n    $SuperG_class $superclass;                   // = InitializableG_methods\n    B_NoneType (*__init__)($Serializable);\n    void (*__serialize__)($Serializable, $Serial$state);\n    $Serializable (*__deserialize__)($Serializable, $Serial$state);\n};\n\nstruct $Serializable {\n    struct $SerializableG_class *$class;\n};\n\nextern struct $SerializableG_class $SerializableG_methods;\n$Serializable $SerializableG_new();\n  \n"
  },
  {
    "path": "base/builtin/common.c",
    "content": "/*\n * Copyright (C) 2019-2021 Data Ductus AB\n *\n * Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:\n *\n * 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.\n *\n * 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.\n *\n * 3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission.\n *\n * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS \"AS IS\" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n */\n\nvoid $default__init__($WORD s) {\n    return;\n}\n\n/*\nvoid B_printobj(char *mess,$WORD obj) {\n    B_value obj1 = (B_value)obj;\n    printf(\"%s %s\\n\",mess,obj1->$class->__str__(obj1)->str);\n}\n*/\n\nchar *unmangle_name(char *input) {\n    // Check for NULL input\n    if (input == NULL) {\n        return NULL;\n    }\n    char *output = GC_malloc(strlen(input) + 1);\n    // Check for allocation failure\n    if (output == NULL) {\n        return NULL;\n    }\n\n    // Check if string starts with \"B_\"\n    if (strncmp(input, \"B_\", 2) == 0) {\n        // Copy string without \"B_\"\n        strcpy(output, input + 2);\n    } else {\n        // Copy string as is\n        strcpy(output, input);\n    }\n    // Handle \"Q_\" mangling for nested modules\n    char *pos;\n    while ((pos = strstr(output, \"Q_\")) != NULL) {\n        *pos = '.';\n        memmove(pos + 1, pos + 2, strlen(pos + 2) + 1);\n    }\n\n    return output;\n}\n"
  },
  {
    "path": "base/builtin/common.h",
    "content": "\ntypedef void *$WORD;\n#define B_None ($WORD)0\n\n#define $long long\n#define $int64 int64_t\n\nvoid $default__init__($WORD);\n\n\n// void B_printobj(char *mess,$WORD obj);\n\n\n#define $NEW($T, ...)       ({ $T $t = acton_malloc(sizeof(struct $T)); \\\n                               $t->$class = &$T ## G_methods; \\\n                               $t->$class->__init__($t, ##__VA_ARGS__); \\\n                               $t; })\n\n#define $NEWCC($X, $c, ...) ({ $X $x = acton_malloc(sizeof(struct $X)); \\\n                               $x->$class = &$X ## G_methods; \\\n                               $x->$class->__init__($x, ##__VA_ARGS__, $CONSTCONT($x,$c)); })\n\n#define $DNEW($T, $state)   ({ $T $t = acton_malloc(sizeof(struct $T)); \\\n                               $t->$class = &$T ## G_methods;                                     \\\n                               B_dictD_setitem($state->done,(B_Hashable)B_HashableD_intG_witness,toB_bigint($state->row_no-1),$t); \\\n                               $t; })\n\n#define $AND(T, a, b)       ({ T $a = (a); ($a && ((B_value)$a)->$class->__bool__((B_value)$a)->val) ? (b) : $a; })\n\n#define $OR(T, a, b)        ({ T $a = (a); ($a && ((B_value)$a)->$class->__bool__((B_value)$a)->val) ? $a : (b); })\n\n#define $NOT(T, a)          ({ T $a = (a); ($a && ((B_value)$a)->$class->__bool__((B_value)$a)->val) ? B_False : B_True; })\n\n#define $ISINSTANCE($x,$T)  ({ \\\n                               /* If object is NULL (None), return False */ \\\n                               ($x) == B_None ? B_False : ({ \\\n                                 $SuperG_class $c = (($Super)$x)->$class; \\\n                                 while($c && $c != ($SuperG_class)&$T ## G_methods) $c = $c->$superclass; \\\n                                 toB_bool($c != 0); \\\n                               }); \\\n                             })\n\n#define $ISINSTANCE0($x,$T)  ({ \\\n                               /* If object is NULL (None), return 0 (False) */ \\\n                               ($x) == B_None ? 0 : ({ \\\n                                 $SuperG_class $c = (($Super)$x)->$class; \\\n                                 while($c && $c != ($SuperG_class)&$T ## G_methods) $c = $c->$superclass; \\\n                                 $c != 0; \\\n                               }); \\\n                             })\n\n#define $ISNOTNONE(x)       ((x) != B_None ? B_True : B_False)\n\n#define $ISNOTNONE0(x)      ((x) != B_None)\n\n#define $ISNONE(x)          ((x) != B_None ? B_False : B_True)\n\n#define $ISNONE0(x)         ((x) == B_None)\n\n#define $SKIPRES(cont)      (cont)\n\n#define RAISE($T, ...)      $RAISE((B_BaseException)$NEW($T, ##__VA_ARGS__))\n\n// $FORMAT is now a C function in str.c\n\nchar *unmangle_name(char *input);\n"
  },
  {
    "path": "base/builtin/complex.c",
    "content": "/*\n * Copyright (C) 2019-2021 Data Ductus AB\n *\n * Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:\n *\n * 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.\n *\n * 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.\n *\n * 3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission.\n *\n * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS \"AS IS\" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n */\n\nB_complex toB_complex(complex double c) {\n    B_complex res = acton_malloc(sizeof(struct B_complex));\n    res->$class = &B_complexG_methods;\n    res->val = c;\n    return res;\n}\n\nB_complex B_complexG_new(B_Number wit, $WORD c) {\n    return $NEW(B_complex,wit,c);\n}\n\nB_complex B_complexD_from_real_imag (B_Real wit1, B_Real wit2, $WORD real, $WORD imag) {\n    double re = wit1->$class->__float__(wit1, real)->val;\n    double im = wit2->$class->__float__(wit2, imag)->val;\n    return toB_complex(re + im * _Complex_I);\n}\n\nB_NoneType B_complexD___init__(B_complex self, B_Number wit, $WORD c){\n    self->val = wit->$class->__complx__(wit,c)->val;\n    return B_None;\n}\n\nvoid B_complexD___serialize__(B_complex c,$Serial$state state) {\n    $ROW row = $add_header(COMPLEX_ID,2,state);\n    double re = creal(c->val);\n    double im = cimag(c->val);\n    memcpy(row->blob,&re,sizeof(double));\n    memcpy(row->blob+1,&im,sizeof(double));\n}\n\nB_complex B_complexD___deserialize__(B_complex self, $Serial$state state) {\n    $ROW this = state->row;\n    state->row =this->next;\n    state->row_no++;\n    double re, im;\n    memcpy(&re,this->blob,sizeof(double));\n    memcpy(&im,this->blob+1,sizeof(double));\n    return toB_complex(re + im * _Complex_I);\n}\n\nB_bool B_complexD___bool__(B_complex n) {\n    return toB_bool(n->val != 0.0);\n}\n\nB_str B_complexD___str__(B_complex c) {\n    return $FORMAT(\"%f + %f*I\", creal(c->val), cimag(c->val));\n}\n  \nB_str B_complexD___repr__(B_complex c) {\n    return $FORMAT(\"%f + %f*I\", creal(c->val), cimag(c->val));\n}\n  \n// B_NumberD_complex  ////////////////////////////////////////////////////////////////////////////////////////\n\nB_complex B_NumberD_complexD___add__(B_NumberD_complex wit, B_complex a, B_complex b) {\n    return toB_complex(a->val + b->val);\n}  \n\nB_complex B_NumberD_complexD___zero__(B_NumberD_complex wit) {\n    return toB_complex(0.0);\n}\n\nB_complex B_NumberD_complexD___complex__ (B_NumberD_complex wit, B_complex c) {\n    return c;\n}\n\nB_complex B_NumberD_complexD___mul__ (B_NumberD_complex wit, B_complex a, B_complex b){\n    return toB_complex(a->val * b->val);\n}\n\nB_complex B_NumberD_complexD___fromatom__(B_NumberD_complex wit, B_atom a) {\n    $RAISE((B_BaseException)$NEW(B_NotImplementedError,to$str(\"__fromatom__ not implemented for complex\")));\n    return B_None;\n}\n\nB_complex B_NumberD_complexD___pow__ (B_NumberD_complex wit, B_complex a, B_complex b) {\n    return toB_complex(cpow(a->val,b->val));\n}\n\nB_complex B_NumberD_complexD___neg__ (B_NumberD_complex wit, B_complex c){\n    return toB_complex(-c->val);\n}\n\nB_complex B_NumberD_complexD___pos__ (B_NumberD_complex wit, B_complex c) {\n    return c;\n}\n\n$WORD B_NumberD_complexD_real (B_NumberD_complex wit, B_complex c, B_Real wit2) {\n    return wit2->$class->__fromatom__(wit2,(B_atom)to$float(creal(c->val)));\n}\n\n$WORD B_NumberD_complexD_imag (B_NumberD_complex wit, B_complex c, B_Real wit2) {\n    return wit2->$class->__fromatom__(wit2,(B_atom)to$float(cimag(c->val)));\n}\n\n$WORD B_NumberD_complexD___abs__ (B_NumberD_complex wit, B_complex c, B_Real wit2) {\n    return wit2->$class->__fromatom__(wit2,(B_atom)to$float(cabs(c->val)));\n}\n\nB_complex B_NumberD_complexD_conjugate (B_NumberD_complex wit, B_complex c) {\n    return toB_complex(conj(c->val));\n}\n\n// B_DivD_complex /////////////////////////////////////////////////////////////////////////////////////////\n\nB_complex B_DivD_complexD___truediv__ (B_DivD_complex wit, B_complex a, B_complex b) {\n    if (b->val == 0.0) {\n        RAISE(B_ZeroDivisionError, to_str_noc(\"complex truediv: divisor is zero\"));\n    }\n    return toB_complex(a->val/b->val);\n}\n\n// B_MinusD_NumberD_complex  ////////////////////////////////////////////////////////////////////////////////////////\n\nB_complex B_MinusD_NumberD_complexD___sub__(B_MinusD_NumberD_complex wit, B_complex a, B_complex b) {\n    return toB_complex(a->val - b->val);\n}  \n// B_EqD_complex  ////////////////////////////////////////////////////////////////////////////////////////\n\nB_bool B_EqD_complexD___eq__ (B_EqD_complex wit, B_complex a, B_complex b) {\n    return toB_bool(creal(a->val) == creal(b->val) && cimag(a->val) == cimag(b->val));\n}\n\nB_bool B_EqD_complexD___ne__ (B_EqD_complex wit, B_complex a, B_complex b) {\n    return toB_bool(!fromB_bool(B_EqD_complexD___eq__(wit,a,b)));\n}\n\n\n// B_HashableD_complex  ////////////////////////////////////////////////////////////////////////////////////////\n\nB_bool B_HashableD_complexD___eq__(B_HashableD_complex wit, B_complex a, B_complex b) {\n    return toB_bool(creal(a->val) == creal(b->val) && cimag(a->val) == cimag(b->val));\n}\n\nB_bool B_HashableD_complexD___ne__(B_HashableD_complex wit, B_complex a, B_complex b) {\n    return toB_bool(!fromB_bool(B_HashableD_complexD___eq__(wit,a,b)));\n}\n\nB_NoneType B_HashableD_complexD_hash(B_HashableD_complex wit, B_complex a, B_hasher h) {\n    zig_hash_wyhash_update(h->_hasher, to$bytesD_len((char *)&(a->val), 16));\n    return B_None;\n}\n\n// init methods ////////////////////////////////////////////////////////////////////////////////////////////////\n/*\nB_NoneType B_NumberD_complex_init (B_NumberD_complex wit) {\n    wit-> W_Minus = (B_Minus)$NEW(B_MinusD_NumberD_complex,(B_Number)wit);\n    return B_None;\n}\n\nB_NoneType B_MinusD_NumberD_complex_init(B_MinusD_NumberD_complex wit, B_Number W_Number) {\n    wit->W_Number =  W_Number;\n    return B_None;\n}\n\nB_NoneType B_EqD_complex_init(B_EqD_complex wit) {\n    return B_None;\n}\n\nB_NoneType B_DivD_complex_init(B_DivD_complex wit) {\n    return B_None;\n}\n\nB_NoneType B_HashableD_complex_init(B_HashableD_complex wit) {\n    return B_None;\n}\n\nB_NumberD_complex B_NumberD_complexG_new() {\n    return $NEW(B_NumberD_complex);\n}\n\nB_MinusD_NumberD_complex B_MinusD_NumberD_complexG_new(B_Number wit) {\n    return $NEW(B_MinusD_NumberD_complex,wit);\n}\n  \nB_EqD_complex B_EqD_complexG_new() {\n    return $NEW(B_EqD_complex);\n}\n\nB_HashableD_complex B_HashableD_complexG_new() {\n    return $NEW(B_HashableD_complex);\n}\n\n\nstruct B_NumberD_complex B_NumberD_complex_instance;\nstruct B_MinusD_NumberD_complex B_MinusD_NumberD_complex_instance;\nstruct B_EqD_complex B_EqD_complex_instance;\nstruct B_HashableD_complex B_HashableD_complex_instance;\n\nstruct B_NumberD_complexG_class B_NumberD_complexG_methods = {\n    \"B_NumberD_complex\",\n    UNASSIGNED,\n    ($SuperG_class)&B_NumberG_methods,\n    B_NumberD_complex_init,\n    B_NumberD_complexD___serialize__,\n    B_NumberD_complexD___deserialize__,\n    (B_bool (*)(B_NumberD_complex))$default__bool__,\n    (B_str (*)(B_NumberD_complex))$default__str__,\n    (B_str (*)(B_NumberD_complex))$default__str__,\n    B_NumberD_complexD___add__,\n    (B_complex (*)(B_NumberD_complex, B_complex, B_complex))B_PlusD___iadd__,\n    B_NumberD_complexD___mul__,\n    (B_complex (*)(B_NumberD_complex, B_complex, B_complex))B_TimesD___imul__,\n    NULL,        // fromatom\n    B_NumberD_complexD___complx__,\n    B_NumberD_complexD___pow__,\n    (B_complex (*)(B_NumberD_complex, B_complex, B_complex))B_NumberD___ipow__,\n    B_NumberD_complexD___neg__,\n    B_NumberD_complexD___pos__,\n    B_NumberD_complex$real,\n    B_NumberD_complex$imag,\n    B_NumberD_complexD___abs__,\n    B_NumberD_complex$conjugate\n};\nstruct B_NumberD_complex B_NumberD_complex_instance = {&B_NumberD_complexG_methods, (B_Minus)&B_MinusD_NumberD_complex_instance};\nB_NumberD_complex B_NumberD_complexG_witness = &B_NumberD_complex_instance;\n\nstruct B_DivD_complexG_class B_DivD_complexG_methods = {\n    \"B_DivD_complex\",\n    UNASSIGNED,\n    ($SuperG_class)&B_DivG_methods,\n    B_DivD_complex_init,\n    B_DivD_complexD___serialize__,\n    B_DivD_complexD___deserialize__,\n    (B_bool (*)(B_DivD_complex))$default__bool__,\n    (B_str (*)(B_DivD_complex))$default__str__,\n    (B_str (*)(B_DivD_complex))$default__str__,\n    B_DivD_complexD___truediv__,\n    (B_complex (*)(B_DivD_complex, B_complex, B_complex))B_DivD___itruediv__,\n};\n\nstruct B_DivD_complex B_DivD_complex_instance = {&B_DivD_complexG_methods};\nB_DivD_complex B_DivD_complexG_witness = &B_DivD_complex_instance;\n\nstruct B_MinusD_NumberD_complexG_class B_MinusD_NumberD_complexG_methods = {\n    \"B_MinusD_NumberD_complex\",\n    UNASSIGNED,\n    ($SuperG_class)&B_MinusG_methods,\n    B_MinusD_NumberD_complex_init,\n    B_MinusD_NumberD_complexD___serialize__,\n    B_MinusD_NumberD_complexD___deserialize__,\n    (B_bool (*)(B_MinusD_NumberD_complex))$default__bool__,\n    (B_str (*)(B_MinusD_NumberD_complex))$default__str__,\n    (B_str (*)(B_MinusD_NumberD_complex))$default__str__,\n    B_MinusD_NumberD_complexD___sub__,\n    (B_complex (*)(B_MinusD_NumberD_complex, B_complex, B_complex))B_MinusD___isub__\n};\nstruct B_MinusD_NumberD_complex B_MinusD_NumberD_complex_instance = {&B_MinusD_NumberD_complexG_methods, (B_Number)&B_NumberD_complex_instance};\nB_MinusD_NumberD_complex B_MinusD_NumberD_complexG_witness = &B_MinusD_NumberD_complex_instance;\n\nstruct B_EqD_complexG_class B_EqD_complexG_methods = {\n    \"B_EqD_complex\",\n    UNASSIGNED,\n    ($SuperG_class)&B_EqG_methods,\n    B_EqD_complex_init,\n    B_EqD_complexD___serialize__,\n    B_EqD_complexD___deserialize__,\n    (B_bool (*)(B_EqD_complex))$default__bool__,\n    (B_str (*)(B_EqD_complex))$default__str__,\n    (B_str (*)(B_EqD_complex))$default__str__,\n    B_EqD_complexD___eq__,\n    B_EqD_complexD___ne__\n};\nstruct B_EqD_complex B_EqD_complex_instance = {&B_EqD_complexG_methods};\nB_EqD_complex B_EqD_complexG_witness = &B_EqD_complex_instance;\n\nstruct B_HashableD_complexG_class B_HashableD_complexG_methods = {\n    \"B_HashableD_complex\",\n    UNASSIGNED,\n    ($SuperG_class)&B_HashableG_methods,\n    B_HashableD_complex_init,\n    B_HashableD_complexD___serialize__,\n    B_HashableD_complexD___deserialize__,\n    (B_bool (*)(B_HashableD_complex))$default__bool__,\n    (B_str (*)(B_HashableD_complex))$default__str__,\n    (B_str (*)(B_HashableD_complex))$default__str__,\n    B_HashableD_complexD___eq__,\n    B_HashableD_complexD___ne__\n};\nstruct B_HashableD_complex B_HashableD_complex_instance = {&B_HashableD_complexG_methods};\nB_HashableD_complex B_HashableD_complexG_witness = &B_HashableD_complex_instance;\n*/\n"
  },
  {
    "path": "base/builtin/complx.h",
    "content": "/*\n * This file is deliberately named complx.h to avoid collisions under gcc or\n * clang. Details are murky, is it with the standard complex.h? (Path should be\n * different, no?) Björn should know the details..\n */\n#include <complex.h>\n\nstruct B_complex {\n    struct B_complexG_class *$class;\n    complex double val;\n};\n\nB_complex toB_complex(complex double c);\n\n"
  },
  {
    "path": "base/builtin/csiphash.c",
    "content": "/* **************************************************************************\n <MIT License>\n Copyright (c) 2013  Marek Majkowski <marek@popcount.org>\n\n Permission is hereby granted, free of charge, to any person obtaining a copy\n of this software and associated documentation files (the \"Software\"), to deal\n in the Software without restriction, including without limitation the rights\n to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n copies of the Software, and to permit persons to whom the Software is\n furnished to do so, subject to the following conditions:\n\n The above copyright notice and this permission notice shall be included in\n all copies or substantial portions of the Software.\n\n THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n THE SOFTWARE.\n </MIT License>\n\n Original location:\n    https://github.com/majek/csiphash/\n\n Solution inspired by code from:\n    Samuel Neves (supercop/crypto_auth/siphash24/little)\n    djb (supercop/crypto_auth/siphash24/little2)\n    Jean-Philippe Aumasson (https://131002.net/siphash/siphash24.c)\n\n Modified for Python by Christian Heimes:\n    - C89 / MSVC compatibility\n    - _rotl64() on Windows\n    - letoh64() fallback\n*/\n\n#include <stdint.h>\n\n/* byte swap little endian to host endian\n * Endian conversion not only ensures that the hash function returns the same\n * value on all platforms. It is also required to for a good dispersion of\n * the hash values' least significant bits.\n */\n#if PY_LITTLE_ENDIAN\n#  define _le64toh(x) ((uint64_t)(x))\n#elif defined(__APPLE__)\n#  define _le64toh(x) OSSwapLittleToHostInt64(x)\n#elif defined(HAVE_LETOH64)\n#  define _le64toh(x) le64toh(x)\n#else\n#  define _le64toh(x) (((uint64_t)(x) << 56) | \\\n                      (((uint64_t)(x) << 40) & 0xff000000000000ULL) | \\\n                      (((uint64_t)(x) << 24) & 0xff0000000000ULL) | \\\n                      (((uint64_t)(x) << 8)  & 0xff00000000ULL) | \\\n                      (((uint64_t)(x) >> 8)  & 0xff000000ULL) | \\\n                      (((uint64_t)(x) >> 24) & 0xff0000ULL) | \\\n                      (((uint64_t)(x) >> 40) & 0xff00ULL) | \\\n                      ((uint64_t)(x)  >> 56))\n#endif\n\n\n#ifdef _MSC_VER\n#  define ROTATE(x, b)  _rotl64(x, b)\n#else\n#  define ROTATE(x, b) (uint64_t)( ((x) << (b)) | ( (x) >> (64 - (b))) )\n#endif\n\n#define HALF_ROUND(a,b,c,d,s,t)         \\\n    a += b; c += d;             \\\n    b = ROTATE(b, s) ^ a;           \\\n    d = ROTATE(d, t) ^ c;           \\\n    a = ROTATE(a, 32);\n\n#define DOUBLE_ROUND(v0,v1,v2,v3)       \\\n    HALF_ROUND(v0,v1,v2,v3,13,16);      \\\n    HALF_ROUND(v2,v1,v0,v3,17,21);      \\\n    HALF_ROUND(v0,v1,v2,v3,13,16);      \\\n    HALF_ROUND(v2,v1,v0,v3,17,21);\n\n\nstatic uint64_t\nsiphash24(uint64_t k0, uint64_t k1, const void *src, ssize_t src_sz) {\n    uint64_t b = (uint64_t)src_sz << 56;\n    const uint8_t *in = (uint8_t*)src;\n\n    uint64_t v0 = k0 ^ 0x736f6d6570736575ULL;\n    uint64_t v1 = k1 ^ 0x646f72616e646f6dULL;\n    uint64_t v2 = k0 ^ 0x6c7967656e657261ULL;\n    uint64_t v3 = k1 ^ 0x7465646279746573ULL;\n\n    uint64_t t;\n    uint8_t *pt;\n\n    while (src_sz >= 8) {\n        uint64_t mi;\n        memcpy(&mi, in, sizeof(mi));\n        mi = _le64toh(mi);\n        in += sizeof(mi);\n        src_sz -= sizeof(mi);\n        v3 ^= mi;\n        DOUBLE_ROUND(v0,v1,v2,v3);\n        v0 ^= mi;\n    }\n\n    t = 0;\n    pt = (uint8_t *)&t;\n    switch (src_sz) {\n        case 7: pt[6] = in[6]; /* fall through */\n        case 6: pt[5] = in[5]; /* fall through */\n        case 5: pt[4] = in[4]; /* fall through */\n        case 4: memcpy(pt, in, sizeof(uint32_t)); break;\n        case 3: pt[2] = in[2]; /* fall through */\n        case 2: pt[1] = in[1]; /* fall through */\n        case 1: pt[0] = in[0]; /* fall through */\n    }\n    b |= _le64toh(t);\n\n    v3 ^= b;\n    DOUBLE_ROUND(v0,v1,v2,v3);\n    v0 ^= b;\n    v2 ^= 0xff;\n    DOUBLE_ROUND(v0,v1,v2,v3);\n    DOUBLE_ROUND(v0,v1,v2,v3);\n\n    /* modified */\n    t = (v0 ^ v1) ^ (v2 ^ v3);\n    return t;\n}\n"
  },
  {
    "path": "base/builtin/dict.c",
    "content": "/*\n * Copyright (C) 2019-2021 Data Ductus AB\n *\n * Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:\n *\n * 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.\n *\n * 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.\n *\n * 3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission.\n *\n * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS \"AS IS\" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n */\n// types //////////////////////////////////////////////////////////////////////////////////////\n\ntypedef struct $entry_struct {\n    long hash;\n    $WORD key;\n    $WORD value;  // deleted entry has value DELETED\n} *$entry_t;\n\nstruct $table_struct {\n    char *$GCINFO;\n    long tb_size;        // size of dk_indices array; must be power of 2\n    long tb_usable;      // nr of unused entries in tb_entries (deleted entries are counted as used)\n    long tb_nentries;    // nr of used entries in tb_entries\n    int  tb_indices[];   // array of indices\n    // after this follows tb_entries array;\n};\n\n#define DELETED (($WORD)1)\n#define INIT_SIZE 4\n#define DKIX_EMPTY (-1)\n#define DKIX_DUMMY (-2)  /* Used internally */\n#define TB_ENTRIES(tb)                                          \\\n    (($entry_t)(&((int*)((tb)->tb_indices))[(tb)->tb_size]))\n\n#define PERTURB_SHIFT 5\n\n// Internal routines //////////////////////////////////////////////////////////////////\n\n/*\n  Internal routine used by dictresize() to build a hashtable of entries.\n%*/\nstatic void build_indices(B_Hashable hashwit, $table oldtable, $table newtable, $entry_t ep, long n) {\n    long mask = newtable->tb_size - 1;\n    for (int ix = 0; ix < n; ix++, ep++) {\n        uint64_t hash;\n        if (oldtable->tb_size > INIT_SIZE)\n            hash = ep->hash;\n        else {\n            hash = fromB_u64(B_hash(hashwit, ep->key));\n            ep->hash = hash;\n        }\n        unsigned long i = (unsigned long)hash & mask;\n        for (unsigned long perturb = hash; newtable->tb_indices[i] != DKIX_EMPTY;) {\n            perturb >>= PERTURB_SHIFT;\n            i = mask & (i*5 + perturb + 1);\n        }\n        newtable->tb_indices[i] = ix;\n    }\n}\n\n/*\n  Restructure the table by allocating a new table and reinserting all\n  items again.  When entries have been deleted, the new table may\n  actually be smaller than the old one.\n*/\n\nstatic int dictresize(B_Hashable hashwit, B_dict d) {\n    $table oldtable = d->table;\n    long numelements = d->numelements;\n    long newsize, minsize = 3*numelements;\n    $entry_t oldentries, newentries;\n    for (newsize = INIT_SIZE; newsize < minsize; newsize <<= 1);\n    /* Allocate a new table. */\n    $table newtable =  acton_malloc(sizeof(char*) + 3*sizeof(long) + newsize*sizeof(int) + (2*newsize/3)*sizeof(struct $entry_struct));\n    newtable->tb_size = newsize;\n    newtable->tb_usable = 2*newsize/3-numelements;\n    newtable->tb_nentries = numelements;\n    memset(&(newtable->tb_indices[0]), 0xff, newsize*sizeof(int));\n    newentries = TB_ENTRIES(newtable);\n    if (numelements > 0) {\n        oldentries = TB_ENTRIES(oldtable);\n        if (oldtable->tb_nentries == numelements) {\n            memcpy(newentries, oldentries, numelements*sizeof(struct $entry_struct));\n        }\n        else {\n            $entry_t ep = oldentries;\n            for (int i = 0; i < numelements; i++) {\n                while (ep->value == DELETED) ep++;\n                newentries[i] = *ep++;\n            }\n        }\n        if (newsize > INIT_SIZE)\n            build_indices(hashwit, oldtable, newtable, newentries, numelements);\n    }\n    // for (int i=0; i < newsize; i++) printf(\"%d -> %d\\n\",i,newtable->tb_indices[i]);\n    // for (int i=0; i < newtable->tb_nentries; i++){\n    //   $entry_t e = newentries + i;\n        // printf(\"%ld     %lu\\n\", e->hash, ((B_int)e->key)->val.n[0])\n        \n    d->table = newtable;\n    return 0;\n}\n\n\n// Search index of hash table from offset of entry table\n// Only called when the dict is a hashtable (i.e. table->tb_size > INIT_SIZE)\nstatic int $lookdict_index($table table, uint64_t hash, int index) {\n    unsigned long mask =  (table->tb_size)-1;\n    unsigned long perturb = hash;\n    unsigned long i = (unsigned long)hash & mask;\n\n    for (;;) {\n        int ix = table->tb_indices[i];\n        if (ix == index) {\n            return i;\n        }\n        if (ix == DKIX_EMPTY) {\n            return DKIX_EMPTY;\n        }\n        perturb >>= PERTURB_SHIFT;\n        i = mask & (i*5 + perturb + 1);\n    }\n    // unreachable\n}\n\n// Returns index into compact array where hash/key is found\n// (and returns corresponding value in *res)\n// or DKIX_EMPTY if no such entry exists\nint $lookdict(B_dict dict, B_Hashable hashwit, uint64_t hash, $WORD key, $WORD *res) {\n    $table table = dict->table;\n    if (!table) {\n        *res = NULL;\n        //printf(\"no table\\n\");\n        return DKIX_EMPTY;\n    }\n    if (table->tb_size == INIT_SIZE) {\n        // Ignore hash and do linear search\n        for (int ix = 0; ix < (int)table->tb_nentries; ix++) {\n            $entry_t entry = &TB_ENTRIES(table)[ix];\n            if (entry->value != DELETED && (entry->key == key || (hashwit->$class->__eq__(hashwit,key,entry->key)->val))) {\n                // found an entry with the same or equal key\n                *res = entry->value; \n                return ix;\n            }\n        }\n        //printf(\"failed linear search\\n\");\n        return DKIX_EMPTY;\n    } else {\n        unsigned long mask = (table->tb_size)-1, i = (unsigned long)hash & mask, perturb = hash;\n        int ix;\n        for(;;) {\n            ix = table->tb_indices[i];\n            // printf(\"ix = %d\\n\",ix);\n            if (ix == DKIX_EMPTY) {\n                // Unused slot\n                *res = NULL;\n                // printf(\"found unused slot\\n\");\n                return ix;\n            }\n            if (ix >= 0) {\n                $entry_t entry = &TB_ENTRIES(table)[ix];\n                if (entry->value != DELETED && (entry->key == key || (entry->hash == hash && hashwit->$class->__eq__(hashwit,key,entry->key)->val))) {\n                    // found an entry with the same or equal key\n                    *res = entry->value;\n                    return ix;\n                }\n                // collision; probe another location\n            }\n            perturb >>= PERTURB_SHIFT;\n            i = (i*5 + perturb + 1) & mask;\n            // printf(\"collision; perturb is %ld, hash is %ld, mask is %ld, next probe is %ld\\n\", perturb,  hash, mask, i);\n        }\n        // this should be unreachable\n    }\n}\n\n//  Internal function to find slot in index array for an item from its hash\n//  when it is known that the key is not present in the dict.\n  \nstatic long find_empty_slot($table table, uint64_t hash) {\n    if (table->tb_size==INIT_SIZE)\n        return table->tb_nentries;\n    const unsigned long mask = table->tb_size-1;\n    unsigned long i = (unsigned long)hash & mask;\n    int ix = table->tb_indices[i];\n    for (unsigned long perturb = hash; ix >= 0;) {\n        perturb >>= PERTURB_SHIFT;\n        i = (i*5 + perturb + 1) & mask;\n        ix = table->tb_indices[i];\n    }\n    return i;\n}\n\nstatic void insertdict(B_dict dict, B_Hashable hashwit, uint64_t hash, $WORD key, $WORD value) {\n    $WORD old_value;\n    $table table;\n    $entry_t ep;\n    if (!dict->table || dict->table->tb_usable <= 0)\n        dictresize(hashwit,dict);\n    if (dict->table->tb_size == 2*INIT_SIZE)\n         hash = fromB_u64(B_hash(hashwit, key));\n    int ix = $lookdict(dict,hashwit,hash,key,&old_value);\n    if (ix == DKIX_EMPTY) {\n        table = dict->table;\n        long newpos = find_empty_slot(table,hash);\n        ep = &TB_ENTRIES(table)[table->tb_nentries];\n        table->tb_indices[newpos] = table->tb_nentries;\n        ep->key = key;\n        ep->hash = hash;\n        ep->value = value;\n        table->tb_usable--;\n        table->tb_nentries++;\n        dict->numelements++;\n        return;\n    }\n    if (old_value != value)  //eq ??\n        TB_ENTRIES(dict->table)[ix].value = value;\n    return;\n}\n\n// General methods /////////////////////////////////////////////////////////////////////////\n\nB_dict B_dictG_new(B_Hashable hashwit, B_Iterable wit, $WORD iterable) {\n    return $NEW(B_dict,hashwit, wit, iterable);\n}\n\nB_NoneType B_dictD___init__(B_dict dict, B_Hashable hashwit, B_Iterable wit, $WORD iterable) {\n    dict->numelements = 0;\n    dict->table = NULL;\n    if (wit && iterable) {\n        B_Iterator it = wit->$class->__iter__(wit,iterable);\n        while(1) {\n            if ($PUSH()) {\n                B_tuple nxt = (B_tuple)it->$class->__next__(it);\n                B_dictD_setitem(dict,hashwit,nxt->components[0],nxt->components[1]);\n                $DROP();\n            } else {\n                B_BaseException ex = $POP();\n                if ($ISINSTANCE0(ex, B_StopIteration))\n                    break;\n                else\n                    $RAISE(ex);\n            }\n        }\n    }\n    return B_None;\n}\n\nB_bool B_dictD___bool__(B_dict self) {\n    return toB_bool(self->numelements>0);\n}\n\nB_str B_dictD___str__(B_dict self) {\n    B_list s2 = B_listD_new(self->numelements);\n    B_IteratorD_dict_items iter = $NEW(B_IteratorD_dict_items,self);\n    B_tuple item;\n    B_SequenceD_list wit = B_SequenceD_listG_witness;\n    for (int i=0; i<self->numelements; i++) {\n        item = (B_tuple)iter->$class->__next__(iter);\n        B_value key = ((B_value)item->components[0]);\n        B_value value = ((B_value)item->components[1]);\n        B_str keystr = key->$class->__repr__(key);\n        B_str valuestr = value ? value->$class->__repr__(value) : to$str(\"None\");\n        B_str elem = acton_malloc(sizeof(struct B_str));\n        elem->$class = &B_strG_methods;\n        elem->nbytes = keystr->nbytes+valuestr->nbytes+1;\n        elem->nchars = keystr->nchars+valuestr->nchars+1;\n        elem->str = acton_malloc(elem->nbytes+1);\n        memcpy(elem->str,keystr->str,keystr->nbytes);\n        elem->str[keystr->nbytes] = ':';\n        memcpy(&elem->str[keystr->nbytes+1],valuestr->str,valuestr->nbytes);\n        elem->str[elem->nbytes] = '\\0';    \n        wit->$class->append(wit,s2,elem);\n    }\n    return B_strD_join_par('{',s2,'}');\n}\n\nB_str B_dictD___repr__(B_dict self) {\n    return B_dictD___str__(self);\n}\n\nvoid B_dictD___serialize__(B_dict self,$Serial$state state) {\n    B_int prevkey = (B_int)B_dictD_get(state->done,(B_Hashable)B_HashableD_WORDG_witness,self,NULL);\n    if (prevkey) {\n        long pk = fromB_int(prevkey);\n        $val_serialize(-DICT_ID,&pk,state);\n        return;\n    }\n    B_dictD_setitem(state->done,(B_Hashable)B_HashableD_WORDG_witness,self,toB_int(state->row_no));\n    int blobsize = 4 + (self->table->tb_size + 1) * sizeof(int)/sizeof($WORD);\n    $ROW row = $add_header(DICT_ID,blobsize,state);\n    row->blob[0] = ($WORD)self->numelements;\n    row->blob[1] = ($WORD)self->table->tb_size;\n    row->blob[2] = ($WORD)self->table->tb_usable;\n    row->blob[3] = ($WORD)self->table->tb_nentries;\n    memcpy(&row->blob[4],self->table->tb_indices,self->table->tb_size*sizeof(int));\n    for (int i=0; i<self->table->tb_nentries; i++) {\n        $entry_t entry = &TB_ENTRIES(self->table)[i];\n        $step_serialize(toB_u64(entry->hash),state);\n        $step_serialize(entry->key,state);\n        $step_serialize(entry->value,state);\n    }\n}\n\nB_dict B_dictD___deserialize__(B_dict res, $Serial$state state) {\n    $ROW this = state->row;\n    state->row = this->next;\n    state->row_no++;\n    if (this->class_id < 0) {\n        return B_dictD_get(state->done,(B_Hashable)B_HashableD_intG_witness,toB_int((long)this->blob[0]),NULL);\n    } else {\n        if (!res)\n            res = acton_malloc(sizeof(struct B_dict));\n        B_dictD_setitem(state->done,(B_Hashable)B_HashableD_intG_witness,toB_int(state->row_no-1),res);\n        res->$class = &B_dictG_methods;\n        res->numelements = (long)this->blob[0];\n        long tb_size = (long)this->blob[1];\n        res->table = acton_malloc(sizeof(char*) + 3*sizeof(long) + tb_size*sizeof(int) + (2*tb_size/3)*sizeof(struct $entry_struct));\n        res->table->tb_size = tb_size;\n        res->table->tb_usable = (long)this->blob[2];\n        res->table->tb_nentries = (long)this->blob[3];\n        memcpy(res->table->tb_indices,&this->blob[4],tb_size*sizeof(int));\n        for (int i=0; i<res->table->tb_nentries; i++) {\n            $entry_t entry = &TB_ENTRIES(res->table)[i];\n            entry->hash = fromB_u64((B_u64)$step_deserialize(state));\n            entry->key =  $step_deserialize(state);\n            entry->value = $step_deserialize(state);\n        }\n        return res;\n    }\n}\n\n// B_OrdD_dict ////////////////////////////////////////////////////////////////////////\n\nB_bool B_dictrel(bool directfalse,B_OrdD_dict w, B_dict a, B_dict b) {\n    if (directfalse) {\n        return B_False;\n    };\n    if (a->numelements == 0)\n        return B_True;\n    B_Hashable wH = w->W_HashableD_AD_OrdD_dict;\n    B_Eq wB = w->W_EqD_BD_OrdD_dict;\n    B_MappingD_dict m = B_MappingD_dictG_new(wH);\n    B_Iterator it = m->$class->keys(m,a);\n    $WORD x,resa,resb;\n    if ($PUSH()) {\n        while(1) {\n            x = it->$class->__next__(it);\n            long h = 0;\n            if (a->table->tb_size > INIT_SIZE)\n                h = fromB_u64(B_hash(wH, x));\n            int ixa = $lookdict(a, wH, h, x, &resa);\n            int ixb = $lookdict(b, wH, h, x ,&resb);\n            if (ixb<0 || wB->$class->__ne__(wB,resa,resb)->val) {\n                $DROP();\n                return B_False;\n            }\n        }\n        $DROP();\n    } else {\n        B_BaseException ex = $POP();\n        if (! $ISINSTANCE0(ex, B_StopIteration))\n           $RAISE(ex);\n    }\n    return B_True;\n}\n\nB_bool B_OrdD_dictD___eq__ (B_OrdD_dict w, B_dict a, B_dict b) {\n    return B_dictrel(a->numelements != b->numelements,w,a,b);\n}\n\nB_bool B_OrdD_dictD___ne__ (B_OrdD_dict w, B_dict a, B_dict b) {\n    return toB_bool(!(w->$class->__eq__(w,a,b)->val));\n}\n\nB_bool B_OrdD_dictD___lt__ (B_OrdD_dict w, B_dict a, B_dict b) {\n    return B_dictrel(a->numelements >= b->numelements,w,a,b);\n}\n\nB_bool B_OrdD_dictD___le__ (B_OrdD_dict w, B_dict a, B_dict b) {\n    return B_dictrel(a->numelements > b->numelements,w,a,b);\n}\n\nB_bool B_OrdD_dictD___gt__ (B_OrdD_dict w, B_dict a, B_dict b) {\n    return toB_bool(!(w->$class->__lt__(w,b,a)->val));\n}\n\nB_bool B_OrdD_dictD___ge__ (B_OrdD_dict w, B_dict a, B_dict b) {\n    return toB_bool(!(w->$class->__le__(w,b,a)->val));\n}\n\n// B_MappingD_dict ///////////////////////////////////////////////////////////////\n\n// First, define Iterator class for keys  //////////////////////////////////////////////////////////////////////////////\n \nstatic $WORD B_IteratorD_dictD_next(B_IteratorD_dict self) {\n    if (!self->src->table)\n        $RAISE ((B_BaseException)$NEW(B_StopIteration, to$str(\"dict keys iterator terminated\")));\n    int i = self->nxt;\n    $table table = self->src->table;\n    int n = table->tb_nentries;\n    while (i < n) {\n        $entry_t entry =  &TB_ENTRIES(table)[i];\n        if (entry->value != DELETED) {\n            self->nxt = i+1;\n            return entry->key;\n        }\n        i++;\n    }\n    $RAISE ((B_BaseException)$NEW(B_StopIteration, to$str(\"dict keys iterator terminated\")));\n    return NULL;\n}\n\nB_IteratorD_dict B_IteratorD_dictG_new(B_dict dict) {\n    return $NEW(B_IteratorD_dict, dict);\n}\n \nvoid B_IteratorD_dictD_init(B_IteratorD_dict self, B_dict dict) {\n    self->src = dict;\n    self->nxt = 0;\n}\n\n\nB_bool B_IteratorD_dictD_bool(B_IteratorD_dict self) {\n    return B_True;\n}\n\nB_str B_IteratorD_dictD_str(B_IteratorD_dict self) {\n    return $FORMAT(\"<dict keys iterator object at %p>\", self);\n}\n\nvoid B_IteratorD_dictD_serialize(B_IteratorD_dict self, $Serial$state state) {\n    $step_serialize(self->src,state);\n    $step_serialize(toB_int(self->nxt),state);\n}\n\n\nB_IteratorD_dict B_IteratorD_dict__deserialize(B_IteratorD_dict res, $Serial$state state) {\n    if (!res)\n        res = $DNEW( B_IteratorD_dict,state);\n    res->src = (B_dict)$step_deserialize(state);\n    res->nxt = fromB_int((B_int)$step_deserialize(state));\n    return res;\n}\n\n\nstruct B_IteratorD_dictG_class B_IteratorD_dictG_methods = {\"B_IteratorD_dict\",UNASSIGNED,($SuperG_class)&B_IteratorG_methods, B_IteratorD_dictD_init,\n                                                      B_IteratorD_dictD_serialize, B_IteratorD_dict__deserialize, B_IteratorD_dictD_bool,B_IteratorD_dictD_str,B_IteratorD_dictD_str, B_IteratorD_dictD_next};\n\n\nB_Iterator B_MappingD_dictD___iter__ (B_MappingD_dict wit, B_dict dict) {\n    return (B_Iterator)$NEW(B_IteratorD_dict,dict);\n}\n\nB_dict B_MappingD_dictD___fromiter__ (B_MappingD_dict wit, B_Iterable wit2, $WORD iter) {\n    return B_dictG_new(wit->W_HashableD_AD_MappingD_dict, wit2, iter);\n    /*\n    B_Iterator it = wit2->$class->__iter__(wit2,iter);\n    B_Hashable hashwit = wit->W_HashableD_AD_MappingD_dict;\n    B_dict dict = $NEW(B_dict,hashwit,NULL,NULL);\n    B_tuple nxt;\n    while((nxt = (B_tuple)it->$class->__next__(it))) {\n        B_dictD_setitem(dict,hashwit,nxt->components[0],nxt->components[1]);\n    }\n    return dict;\n    */\n}\n\nB_int B_MappingD_dictD___len__ (B_MappingD_dict wit, B_dict dict) {\n    return toB_int(dict->numelements);\n}\n  \nB_bool B_MappingD_dictD___contains__ (B_MappingD_dict wit, B_dict dict, $WORD key) {\n    if (dict->numelements == 0)\n        return B_False;\n    B_Hashable hashwit = wit->W_HashableD_AD_MappingD_dict;\n    $WORD res;\n    long h = 0;\n    if (dict->table->tb_size > INIT_SIZE)\n        h = fromB_u64(B_hash(hashwit, key));\n    return toB_bool($lookdict(dict,hashwit,h,key,&res) >= 0);\n}\n\nB_bool B_MappingD_dictD___containsnot__ (B_MappingD_dict wit, B_dict dict, $WORD key) {\n    return toB_bool(!B_MappingD_dictD___contains__(wit, dict, key)->val);\n}\n\n$WORD B_MappingD_dictD_get (B_MappingD_dict wit, B_dict dict, $WORD key) {\n    if (!dict->table)\n        return B_None;\n    uint64_t hash = 0;\n    B_Hashable hashwit = wit->W_HashableD_AD_MappingD_dict;\n    if (dict->table->tb_size > INIT_SIZE)\n        hash = fromB_u64(B_hash(hashwit, key));\n    $WORD res;\n    int ix = $lookdict(dict,hashwit,hash,key,&res);\n    if (ix < 0)\n        return B_None;\n    else\n        return res;\n}\n\n$WORD B_MappingD_dictD_get_def (B_MappingD_dict wit, B_dict dict, $WORD key, $WORD deflt) {\n    if (!dict->table)\n        return deflt;\n    uint64_t hash = 0;\n    B_Hashable hashwit = wit->W_HashableD_AD_MappingD_dict;\n    if (dict->table->tb_size > INIT_SIZE) \n        hash = fromB_u64(B_hash(hashwit, key));\n    $WORD res;\n    int ix = $lookdict(dict,hashwit,hash,key,&res);\n    if (ix < 0) \n        return deflt;\n    else\n        return res;\n}\n\n$WORD B_MappingD_dictD_pop(B_MappingD_dict wit, B_dict dict, $WORD key) {\n    if (dict->numelements == 0)\n        return B_None;\n    $table table = dict->table;\n    uint64_t hash = 0;\n    B_Hashable hashwit = wit->W_HashableD_AD_MappingD_dict;\n    if (table->tb_size > INIT_SIZE) {\n        hash = fromB_u64(B_hash(hashwit, key));\n    }\n    $WORD res;\n    int ix = $lookdict(dict,hashwit,hash,key,&res);\n    if (ix < 0)\n        return B_None;\n    else {\n        $entry_t entry = &TB_ENTRIES(table)[ix];\n        int i = $lookdict_index(table,hash,ix);\n        table->tb_indices[i] = DKIX_DUMMY;\n        res = entry->value;\n        entry->value = DELETED;\n        dict->numelements--;\n        if (10*dict->numelements < dict->table->tb_size)\n            dictresize(hashwit,dict);\n        return res;\n    }\n}\n\n$WORD B_MappingD_dictD_pop_def(B_MappingD_dict wit, B_dict dict, $WORD key, $WORD deflt) {\n    if (dict->numelements == 0)\n        return deflt;\n    $table table = dict->table;\n    uint64_t hash = 0;\n    B_Hashable hashwit = wit->W_HashableD_AD_MappingD_dict;\n    if (table->tb_size > INIT_SIZE) {\n        hash = fromB_u64(B_hash(hashwit, key));\n    }\n    $WORD res;\n    int ix = $lookdict(dict,hashwit,hash,key,&res);\n    if (ix < 0)\n        return deflt;\n    else {\n        $entry_t entry = &TB_ENTRIES(table)[ix];\n        int i = $lookdict_index(table,hash,ix);\n        table->tb_indices[i] = DKIX_DUMMY;\n        res = entry->value;\n        entry->value = DELETED;\n        dict->numelements--;\n        if (10*dict->numelements < dict->table->tb_size)\n            dictresize(hashwit,dict);\n        return res;\n    }\n}\n\nB_Iterator B_MappingD_dictD_keys (B_MappingD_dict wit, B_dict dict) {\n    return (B_Iterator)$NEW(B_IteratorD_dict,dict);\n}\n\n// Iterator classes for values and items\n\n// values iterator\n\nstatic $WORD B_IteratorD_dict_values_next(B_IteratorD_dict_values self) {\n    int i = self->nxt;\n    $table table = self->src->table;\n    if(!table)\n        $RAISE ((B_BaseException)$NEW(B_StopIteration, to$str(\"dict values iterator terminated\")));\n    int n = table->tb_nentries;\n    while (i < n) {\n        $entry_t entry =  &TB_ENTRIES(table)[i];\n        if (entry->value != DELETED) {\n            self->nxt = i+1;\n            return entry->value;\n        }\n        i++;\n    }\n    $RAISE ((B_BaseException)$NEW(B_StopIteration, to$str(\"dict values iterator terminated\")));\n    return NULL; // to avoid compiler warning\n}\n \nB_IteratorD_dict_values B_IteratorD_dict_valuesG_new(B_dict dict) {\n    return $NEW(B_IteratorD_dict_values, dict);\n}\n \nvoid B_IteratorD_dict_values_init(B_IteratorD_dict_values self, B_dict dict) {\n    self->src = dict;\n    self->nxt = 0;\n}\n\n\nB_bool B_IteratorD_dict_values_bool(B_IteratorD_dict_values self) {\n    return B_True;\n}\n\nB_str B_IteratorD_dict_values_str(B_IteratorD_dict_values self) {\n    return $FORMAT(\"<dict values iterator object at %p>\", self);\n}\n\nvoid B_IteratorD_dict_values_serialize(B_IteratorD_dict_values self, $Serial$state state) {\n    $step_serialize(self->src,state);\n    $step_serialize(toB_int(self->nxt),state);\n}\n\nB_IteratorD_dict_values B_IteratorD_dict_values_deserialize(B_IteratorD_dict_values res, $Serial$state state) {\n    if (!res)\n        res = $DNEW(B_IteratorD_dict_values,state);\n    res->src = (B_dict)$step_deserialize(state);\n    res->nxt = fromB_int((B_int)$step_deserialize(state));\n    return res;\n}\n\nstruct B_IteratorD_dict_valuesG_class B_IteratorD_dict_valuesG_methods = {\"B_IteratorD_dict_values\",UNASSIGNED,($SuperG_class)&B_IteratorG_methods, B_IteratorD_dict_values_init,\n                                                                    B_IteratorD_dict_values_serialize, B_IteratorD_dict_values_deserialize, B_IteratorD_dict_values_bool, B_IteratorD_dict_values_str,B_IteratorD_dict_values_str,\n                                                                    B_IteratorD_dict_values_next};\n\n// items iterator\n\nstatic $WORD B_IteratorD_dict_items_next(B_IteratorD_dict_items self) {\n    int i = self->nxt;\n    $table table = self->src->table;\n    if(!table)\n        $RAISE ((B_BaseException)$NEW(B_StopIteration, to$str(\"dict items iterator terminated\")));\n    int n = table->tb_nentries;\n    while (i < n) {\n        $entry_t entry =  &TB_ENTRIES(table)[i];\n        if (entry->value != DELETED) {\n            self->nxt = i+1;\n            return $NEWTUPLE(2,entry->key,entry->value);\n        }\n        i++;\n    }\n    $RAISE ((B_BaseException)$NEW(B_StopIteration, to$str(\"dict items iterator terminated\")));\n    return NULL; // to avoid compiler warning\n}\n \nB_IteratorD_dict_items B_IteratorD_dict_itemsG_new(B_dict dict) {\n    return $NEW(B_IteratorD_dict_items, dict);\n}\n \nvoid B_IteratorD_dict_items_init(B_IteratorD_dict_items self, B_dict dict) {\n    self->src = dict;\n    self->nxt = 0;\n}\n\n\nB_bool B_IteratorD_dict_items_bool(B_IteratorD_dict_items self) {\n    return B_True;\n}\n\nB_str B_IteratorD_dict_items_str(B_IteratorD_dict_items self) {\n    return $FORMAT(\"<dict items iterator object at %p>\", self);\n}\n\nvoid B_IteratorD_dict_items_serialize(B_IteratorD_dict_items self, $Serial$state state) {\n    $step_serialize(self->src,state);\n    $step_serialize(toB_int(self->nxt),state);\n}\n\nB_IteratorD_dict_items B_IteratorD_dict_items_deserialize(B_IteratorD_dict_items res, $Serial$state state) {\n    if (!res)\n        res = $DNEW(B_IteratorD_dict_items,state);\n    res->src = (B_dict)$step_deserialize(state);\n    res->nxt = fromB_int((B_int)$step_deserialize(state));\n    return res;\n}\n\n\n\nstruct B_IteratorD_dict_itemsG_class B_IteratorD_dict_itemsG_methods = {\"B_IteratorD_dict_items\",UNASSIGNED,($SuperG_class)&B_IteratorG_methods, B_IteratorD_dict_items_init,\n                                                                  B_IteratorD_dict_items_serialize, B_IteratorD_dict_items_deserialize,B_IteratorD_dict_items_bool, B_IteratorD_dict_items_str, B_IteratorD_dict_items_str, B_IteratorD_dict_items_next};\n\n\nB_Iterator B_MappingD_dictD_values (B_MappingD_dict wit, B_dict dict) {\n    return (B_Iterator)$NEW(B_IteratorD_dict_values, dict);\n}\n\nB_Iterator B_MappingD_dictD_items (B_MappingD_dict wit, B_dict dict) {\n    return (B_Iterator)$NEW(B_IteratorD_dict_items, dict);\n}\n\nB_NoneType B_MappingD_dictD_update (B_MappingD_dict wit, B_dict dict, B_Iterable wit2, $WORD other) {\n    B_Hashable hashwit = wit->W_HashableD_AD_MappingD_dict;\n    B_Iterator it = wit2->$class->__iter__(wit2,other);\n    while(1) {\n        if ($PUSH()) {\n            B_tuple item = it->$class->__next__(it);\n            B_dictD_setitem(dict,hashwit,item->components[0],item->components[1]);\n            $DROP();\n        } else {\n            B_BaseException ex = $POP();\n            if ($ISINSTANCE0(ex, B_StopIteration))\n                break;\n           else\n               $RAISE(ex);\n        }\n    }\n    return B_None;\n}\n\nB_tuple B_MappingD_dictD_popitem (B_MappingD_dict wit, B_dict dict) {\n    if (dict->numelements == 0)  {\n        return NULL;\n    }\n    B_Hashable hashwit = wit->W_HashableD_AD_MappingD_dict;\n    $table table = dict->table;\n    int ix = table->tb_nentries-1;\n    while (ix >= 0) {\n        $entry_t entry =  &TB_ENTRIES(table)[ix];\n        if (entry->value != DELETED) {\n            if (table->tb_size > INIT_SIZE) {\n                uint64_t hash = fromB_u64(B_hash(hashwit, entry->key));\n                int i = $lookdict_index(table,hash,ix);\n                table->tb_indices[i] = DKIX_DUMMY;\n            }\n            dict->numelements--;\n            table->tb_nentries = ix;\n            return $NEWTUPLE(2,entry->key,entry->value);\n        }\n        ix--;\n    }\n    return NULL;\n}\n\n$WORD B_MappingD_dictD_setdefault (B_MappingD_dict wit, B_dict dict, $WORD key, $WORD deflt) {\n    if (!deflt) deflt = B_None;\n    B_Hashable hashwit = wit->W_HashableD_AD_MappingD_dict;\n    uint64_t hash = fromB_u64(B_hash(hashwit, key));\n    $WORD value;\n    int ix = $lookdict(dict,hashwit,hash,key,&value);\n    if (ix >= 0)\n        return value;\n    insertdict(dict, hashwit, hash, key, deflt);\n    return deflt;\n}\n \n\n// B_IndexedD_MappingD_dict ///////////////////////////////////////////////////////////////////////\n\n$WORD B_IndexedD_MappingD_dictD___getitem__(B_IndexedD_MappingD_dict wit, B_dict dict, $WORD key) {\n    if(dict->numelements == 0)\n        $RAISE((B_BaseException)$NEW(B_KeyError, key, to$str(\"getitem: empty dictionary\")));\n    B_Hashable hashwit = ((B_MappingD_dict)wit->W_Mapping)->W_HashableD_AD_MappingD_dict;\n    uint64_t hash = 0;\n    if (dict->table->tb_size > INIT_SIZE) {\n        hash = fromB_u64(B_hash(hashwit, key));\n    }\n    $WORD res;\n    int ix = $lookdict(dict,hashwit,hash,key,&res);\n    if (ix < 0)  {\n        $RAISE((B_BaseException)$NEW(B_KeyError, key, to$str(\"getitem: key not in dictionary\")));\n    }      \n    return res;\n}\n\nB_NoneType B_IndexedD_MappingD_dictD___setitem__ (B_IndexedD_MappingD_dict wit, B_dict dict, $WORD key, $WORD value) {\n    B_Hashable hashwit = ((B_MappingD_dict)wit->W_Mapping)->W_HashableD_AD_MappingD_dict;\n    uint64_t hash = 0;\n    if (dict->table && dict->table->tb_size > INIT_SIZE) {\n        hash = fromB_u64(B_hash(hashwit, key));\n    }\n    insertdict(dict, hashwit, hash, key, value);     \n    return B_None;\n}\n\nB_NoneType B_IndexedD_MappingD_dictD___delitem__ (B_IndexedD_MappingD_dict wit, B_dict dict, $WORD key) {\n    if (dict->numelements == 0)  {\n        return B_None;\n    }\n    $table table = dict->table;\n    uint64_t hash = 0;\n    B_Hashable hashwit = ((B_MappingD_dict)wit->W_Mapping)->W_HashableD_AD_MappingD_dict;\n    if (dict->table->tb_size > INIT_SIZE) {\n        hash = fromB_u64(B_hash(hashwit, key));\n    }\n    $WORD res;\n    int ix = $lookdict(dict,hashwit,hash,key,&res);\n    //printf(\"ix = %d\\n\",ix);\n    if (ix < 0)  { // No such key\n        return B_None;\n    }      \n    $entry_t entry = &TB_ENTRIES(table)[ix];\n    int i = $lookdict_index(table,hash,ix);\n    table->tb_indices[i] = DKIX_DUMMY;\n    res = entry->value;\n    //if (res == DELETED) {\n    //    $RAISE((B_BaseException)$NEW(B_KeyError, key, to$str(\"delitem: key already deleted\")));\n    //}\n    entry->value = DELETED;\n    dict->numelements--;\n    if (10*dict->numelements < dict->table->tb_size) \n        dictresize(hashwit,dict);\n    return B_None;\n}\n\nvoid B_dictD_setitem(B_dict dict, B_Hashable hashwit, $WORD key, $WORD value) {\n    uint64_t hash = 0;\n    if (dict->table && dict->table->tb_size > INIT_SIZE) {\n        hash = fromB_u64(B_hash(hashwit, key));\n    }\n    insertdict(dict, hashwit, hash, key, value);     \n}\n\n$WORD B_dictD_get(B_dict dict, B_Hashable hashwit, $WORD key, $WORD deflt) {\n    if (dict->numelements == 0)\n        return deflt;\n    uint64_t hash = 0;\n    if (dict->table->tb_size > INIT_SIZE) {\n        hash = fromB_u64(B_hash(hashwit, key));\n    }\n    $WORD res;\n    int ix = $lookdict(dict,hashwit,hash,key,&res);\n    if (ix < 0) \n        return deflt;\n    else\n        return res;\n}\n\n$WORD B_dictD_pop(B_dict dict, B_Hashable hashwit, $WORD key, $WORD deflt) {\n    if (dict->numelements == 0)\n        return deflt;\n    $table table = dict->table;\n    uint64_t hash = 0;\n    if (table->tb_size > INIT_SIZE) {\n        hash = fromB_u64(B_hash(hashwit, key));\n    }\n    $WORD res;\n    int ix = $lookdict(dict,hashwit,hash,key,&res);\n    if (ix < 0) \n        return deflt;\n    else {\n        $entry_t entry = &TB_ENTRIES(table)[ix];\n        int i = $lookdict_index(table,hash,ix);\n        table->tb_indices[i] = DKIX_DUMMY;\n        res = entry->value;\n        entry->value = DELETED;\n        dict->numelements--;\n        if (10*dict->numelements < dict->table->tb_size) \n        dictresize(hashwit,dict);\n        return res;\n    }\n}\n\n/*\nB_dict B_dictD_copy(B_dict dict, B_Hashable hashwit) {\n    B_Iterable w = (B_Iterable)B_MappingD_dictG_witness;\n    return B_dictG_new(hashwit, w, dict);\n}\n\nB_NoneType B_dictD_clear(B_dict dict, B_Hashable hashwit) {\n    $table table = NULL;\n    dict->numelements = 0;\n    return B_None;\n}\n*/\n"
  },
  {
    "path": "base/builtin/dict.h",
    "content": "typedef struct $table_struct *$table;\n\nstruct B_dict {\n    struct B_dictG_class *$class;\n    long numelements;               // nr of elements in dictionary\n    $table table;                   // the hashtable\n};\n\n// Iterators over dicts ///////////////////////////////////////////////////////\n\n// keys iterator\n\ntypedef struct B_IteratorD_dict *B_IteratorD_dict;\n\nstruct B_IteratorD_dictG_class {\n    char *$GCINFO;\n    int $class_id;\n    $SuperG_class $superclass;\n    void (*__init__)(B_IteratorD_dict, B_dict);\n    void (*__serialize__)(B_IteratorD_dict,$Serial$state);\n    B_IteratorD_dict (*__deserialize__)(B_IteratorD_dict,$Serial$state);\n    B_bool (*__bool__)(B_IteratorD_dict);\n    B_str (*__str__)(B_IteratorD_dict);\n    B_str (*__repr__)(B_IteratorD_dict);\n    $WORD(*__next__)(B_IteratorD_dict);\n};\n\nstruct B_IteratorD_dict {\n    struct B_IteratorD_dictG_class *$class;\n    B_dict src;\n    int nxt;\n};\n\nextern struct B_IteratorD_dictG_class  B_IteratorD_dictG_methods;\nB_IteratorD_dict B_IteratorD_dictG_new(B_dict);\n\n// values iterator\n\ntypedef struct B_IteratorD_dict_values *B_IteratorD_dict_values;\n\nstruct B_IteratorD_dict_valuesG_class {\n    char *$GCINFO;\n    int $class_id;\n    $SuperG_class $superclass;\n    void (*__init__)(B_IteratorD_dict_values, B_dict);\n    void (*__serialize__)(B_IteratorD_dict_values,$Serial$state);\n    B_IteratorD_dict_values (*__deserialize__)(B_IteratorD_dict_values,$Serial$state);\n    B_bool (*__bool__)(B_IteratorD_dict_values);\n    B_str (*__str__)(B_IteratorD_dict_values);\n    B_str (*__repr__)(B_IteratorD_dict_values);\n    $WORD(*__next__)(B_IteratorD_dict_values);\n};\n\nstruct B_IteratorD_dict_values {\n    struct B_IteratorD_dict_valuesG_class *$class;\n    B_dict src;\n    int nxt;\n};\n\nextern struct B_IteratorD_dict_valuesG_class  B_IteratorD_dict_valuesG_methods;\nB_IteratorD_dict_values B_IteratorD_dict_valuesG_new(B_dict);\n\n// items iterator\n\ntypedef struct B_IteratorD_dict_items *B_IteratorD_dict_items;\n\nstruct B_IteratorD_dict_itemsG_class {\n    char *$GCINFO;\n    int $class_id;\n    $SuperG_class $superclass;\n    void (*__init__)(B_IteratorD_dict_items, B_dict);\n    void (*__serialize__)(B_IteratorD_dict_items,$Serial$state);\n    B_IteratorD_dict_items (*__deserialize__)(B_IteratorD_dict_items,$Serial$state);\n    B_bool (*__bool__)(B_IteratorD_dict_items);\n    B_str (*__str__)(B_IteratorD_dict_items);\n    B_str (*__repr__)(B_IteratorD_dict_items);\n    $WORD(*__next__)(B_IteratorD_dict_items);\n};\n\nstruct B_IteratorD_dict_items {\n    struct B_IteratorD_dict_itemsG_class *$class;\n    B_dict src;\n    int nxt;\n};\n\nextern struct B_IteratorD_dict_itemsG_class  B_IteratorD_dict_itemsG_methods;\nB_IteratorD_dict_items B_IteratorD_dict_itemsG_new(B_dict);\n\n\n// Convenience methods used for (de)serialization\nvoid B_dictD_setitem(B_dict dict, B_Hashable hashwit, $WORD key, $WORD value);\n$WORD B_dictD_get(B_dict dict, B_Hashable hashwit, $WORD key, $WORD deflt);\n"
  },
  {
    "path": "base/builtin/env.c",
    "content": "/*\n * Copyright (C) 2019-2021 Data Ductus AB\n *\n * Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:\n *\n * 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.\n *\n * 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.\n *\n * 3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission.\n *\n * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS \"AS IS\" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n */\n\n#ifdef __linux__\n#ifndef _GNU_SOURCE\n#define _GNU_SOURCE 1\n#endif\n#endif\n\n#define GC_THREADS 1\n#include <gc.h>\n\n#if defined(_WIN32) || defined(_WIN64)\n#else\n#include <termios.h>\n#endif\n#include <unistd.h>\n#include <uv.h>\n\n#include \"env.h\"\n\n#include \"../rts/io.h\"\n#include \"../rts/log.h\"\n\nextern char rts_exit;\nextern int return_val;\n\n\n// Env /////////////////////////////////////////////////////////////////////////\n\n$R B_EnvD_stdout_writeG_local (B_Env self, $Cont c$cont, B_str s) {\n    printf(\"%s\", s->str);\n    return $R_CONT(c$cont, B_None);\n}\n\n$R B_EnvD_set_stdinG_local (B_Env self, $Cont c$cont, B_bool canonical, B_bool echo) {\n#if defined(_WIN32) || defined(_WIN64)\n#else\n    struct termios attr;\n    tcgetattr(STDIN_FILENO, &attr);\n\n    if (canonical != NULL) {\n        if (fromB_bool(canonical) == true) {\n            attr.c_lflag |= ICANON; // Set ICANON flag\n        } else {\n            attr.c_lflag &= ~ICANON; // Remove ICANON flag\n        }\n    }\n\n    if (echo != NULL) {\n        if (fromB_bool(echo) == true) {\n            attr.c_lflag |= ECHO;\n        } else {\n            attr.c_lflag &= ~ECHO;\n        }\n    }\n\n    tcsetattr(STDIN_FILENO, TCSANOW, &attr);\n#endif\n    return $R_CONT(c$cont, B_None);\n}\n\nvoid read_stdin(uv_stream_t *stream, ssize_t nread, const uv_buf_t *buf) {\n    if (nread < 0){\n        if (nread == UV_EOF) {\n            uv_close((uv_handle_t *)stream, NULL);\n        }\n    } else if (nread > 0) {\n        if (stream->data) {\n            $action cb = stream->data;\n            cb->$class->__asyn__(cb, to$bytesD_len(buf->base, nread));\n        }\n    }\n}\n\n$R B_EnvD__on_stdin_bytesG_local (B_Env self, $Cont c$cont, $action cb) {\n    // This should be the only call in env that does IO stuff, so it is safe to\n    // pin affinity here (and not earlier)..\n    pin_actor_affinity();\n    uv_tty_t *tty = acton_malloc(sizeof(uv_tty_t));\n    uv_tty_init(get_uv_loop(), tty, STDIN_FILENO, 1);\n    tty->data = cb;\n    uv_read_start((uv_stream_t*)tty, alloc_buffer, read_stdin);\n    return $R_CONT(c$cont, B_None);\n}\n\n$R B_EnvD_exitG_local (B_Env self, $Cont c$cont, B_int n) {\n    return_val = fromB_int(n);\n    rts_shutdown();\n    return $R_CONT(c$cont, B_None);\n}\n\n\nB_Env B_EnvG_newactor(B_WorldCap wc, B_SysCap sc, B_list args) {\n    B_Env $tmp = $NEWACTOR(B_Env);\n    $tmp->cap = wc;\n    $tmp->args = args;\n    $tmp->syscap = sc;\n    $tmp->auth = $tmp->cap;\n    $tmp->argv = $tmp->args;\n    $tmp->$affinity = 0; // hard-coded to special worker on the main thread\n    serialize_state_shortcut(($Actor)$tmp);\n    return $tmp;\n}\n\n\nB_SysCap B_SysCapG_new() {\n    B_SysCap $tmp = acton_malloc(sizeof(struct B_SysCap));\n    $tmp->$class = &B_SysCapG_methods;\n    //   B_SysCapG_methods.__init__($tmp);\n    return $tmp;\n}\n\nB_NoneType B_SysCapD___init__ (B_SysCap self) {\n    return B_None;\n}\n\n\nB_WorldCap B_WorldCapG_new() {\n    B_WorldCap $tmp = acton_malloc(sizeof(struct B_WorldCap));\n    $tmp->$class = &B_WorldCapG_methods;\n    //   B_WorldCapG_methods.__init__($tmp);\n    return $tmp;\n}\n\nB_NoneType B_WorldCapD___init__ (B_WorldCap self) {\n    return B_None;\n}\n\n"
  },
  {
    "path": "base/builtin/env.h",
    "content": "#pragma once\n\nB_Env B_EnvG_newactor (B_WorldCap, B_SysCap, B_list);\n\nB_SysCap B_SysCapG_new();\nB_NoneType B_SysCapD___init__ (B_SysCap self);\n\nB_WorldCap B_WorldCapG_new();\nB_NoneType B_WorldCapD___init__ (B_WorldCap self);\n"
  },
  {
    "path": "base/builtin/exceptions.c",
    "content": "/*\n * Copyright (C) 2019-2021 Data Ductus AB\n *\n * Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:\n *\n * 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.\n *\n * 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.\n *\n * 3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission.\n *\n * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS \"AS IS\" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n */\n\nvoid B_BaseExceptionD___serialize__ (B_BaseException, $Serial$state);\nB_bool B_valueD___bool__ (B_value);\nB_str B_valueD___str__ (B_value);\nB_str B_valueD___repr__ (B_value);\n\n\nB_NoneType $SEQD___init__ ($SEQ self) {\n    self->error_message = NULL;\n    return B_None;\n}\n$SEQ $SEQD___deserialize__ ($SEQ self, $Serial$state state) {\n    if (!self) {\n        if (!state) {\n            self = acton_malloc(sizeof(struct $SEQ));\n            self->$class = &$SEQG_methods;\n            return self;\n        }\n        self = $DNEW($SEQ, state);\n    }\n    self->error_message = $step_deserialize(state);\n    return self;\n}\n$SEQ $SEQG_new() {\n    $SEQ $tmp = acton_malloc(sizeof(struct $SEQ));\n    $tmp->$class = &$SEQG_methods;\n    $SEQG_methods.__init__($tmp);\n    return $tmp;\n}\nstruct $SEQG_class $SEQG_methods = {\n    .$GCINFO            = \"$SEQ\",\n    .$superclass        = ($SuperG_class)&B_ExceptionG_methods,\n    .__init__           = $SEQD___init__,\n    .__bool__           = (B_bool (*) ($SEQ))B_valueD___bool__,\n    .__str__            = (B_str (*) ($SEQ))B_valueD___str__,\n    .__repr__           = (B_str (*) ($SEQ))B_valueD___repr__,\n    .__serialize__      = (void (*) ($SEQ, $Serial$state))B_BaseExceptionD___serialize__,\n    .__deserialize__    = $SEQD___deserialize__\n};\n\n\n$BRK $BRKD___deserialize__ ($BRK self, $Serial$state state) {\n    if (!self) {\n        if (!state) {\n            self = acton_malloc(sizeof(struct $BRK));\n            self->$class = &$BRKG_methods;\n            return self;\n        }\n        self = $DNEW($BRK, state);\n    }\n    self->error_message = NULL;\n    return self;\n}\n$BRK $BRKG_new() {\n    $BRK $tmp = acton_malloc(sizeof(struct $BRK));\n    $tmp->$class = &$BRKG_methods;\n    $BRKG_methods.__init__($tmp);\n    return $tmp;\n}\nstruct $BRKG_class $BRKG_methods = {\n    .$GCINFO            = \"$BRK\",\n    .$superclass        = ($SuperG_class)&B_ExceptionG_methods,\n    .__init__           = (B_NoneType (*) ($BRK))$SEQD___init__,\n    .__bool__           = (B_bool (*) ($BRK))B_valueD___bool__,\n    .__str__            = (B_str (*) ($BRK))B_valueD___str__,\n    .__repr__           = (B_str (*) ($BRK))B_valueD___repr__,\n    .__serialize__      = (void (*) ($BRK, $Serial$state))B_BaseExceptionD___serialize__,\n    .__deserialize__    = $BRKD___deserialize__\n};\n\n\n$CNT $CNTD___deserialize__ ($CNT self, $Serial$state state) {\n    if (!self) {\n        if (!state) {\n            self = acton_malloc(sizeof(struct $CNT));\n            self->$class = &$CNTG_methods;\n            return self;\n        }\n        self = $DNEW($CNT, state);\n    }\n    self->error_message = $step_deserialize(state);\n    return self;\n}\n$CNT $CNTG_new() {\n    $CNT $tmp = acton_malloc(sizeof(struct $CNT));\n    $tmp->$class = &$CNTG_methods;\n    $CNTG_methods.__init__($tmp);\n    return $tmp;\n}\nstruct $CNTG_class $CNTG_methods = {\n    .$GCINFO            = \"$CNT\",\n    .$superclass        = ($SuperG_class)&B_ExceptionG_methods,\n    .__init__           = (B_NoneType (*) ($CNT))$SEQD___init__,\n    .__bool__           = (B_bool (*) ($CNT))B_valueD___bool__,\n    .__str__            = (B_str (*) ($CNT))B_valueD___str__,\n    .__repr__           = (B_str (*) ($CNT))B_valueD___repr__,\n    .__serialize__      = (void (*) ($CNT, $Serial$state))B_BaseExceptionD___serialize__,\n    .__deserialize__    = $CNTD___deserialize__\n};\n\n\nB_NoneType $RETD___init__ ($RET self, B_value val) {\n    self->error_message = NULL;\n    self->val = val;\n    return B_None;\n}\nvoid $RETD___serialize__ ($RET self, $Serial$state state) {\n    $step_serialize(self->val, state);\n}\n$RET $RETD___deserialize__ ($RET self, $Serial$state state) {\n    if (!self) {\n        if (!state) {\n            self = acton_malloc(sizeof(struct $RET));\n            self->$class = &$RETG_methods;\n            return self;\n        }\n        self = $DNEW($RET, state);\n    }\n    self->error_message = $step_deserialize(state);\n    self->val = $step_deserialize(state);\n    return self;\n}\n$RET $RETG_new(B_value G_1) {\n    $RET $tmp = acton_malloc(sizeof(struct $RET));\n    $tmp->$class = &$RETG_methods;\n    $RETG_methods.__init__($tmp, G_1);\n    return $tmp;\n}\nstruct $RETG_class $RETG_methods = {\n    .$GCINFO            = \"$RET\",\n    .$superclass        = ($SuperG_class)&B_ExceptionG_methods,\n    .__init__           = $RETD___init__,\n    .__bool__           = (B_bool (*) ($RET))B_valueD___bool__,\n    .__str__            = (B_str (*) ($RET))B_valueD___str__,\n    .__repr__           = (B_str (*) ($RET))B_valueD___repr__,\n    .__serialize__      = $RETD___serialize__,\n    .__deserialize__    = $RETD___deserialize__\n};\n\n\n$WORD $raiseValueError(B_str msg) {\n    $RAISE((B_BaseException)$NEW(B_ValueError,msg));\n    return ($WORD)0;\n}\n"
  },
  {
    "path": "base/builtin/exceptions.h",
    "content": "#include <setjmp.h>\n\nstruct JumpBuf;\ntypedef struct JumpBuf *JumpBuf;\nstruct JumpBuf {\n    jmp_buf buf;\n    B_BaseException xval;\n    JumpBuf prev;\n};\n\nvoid $RAISE(B_BaseException e);\nJumpBuf $PUSH_BUF();\nvoid $DROP();\nB_BaseException $POP();\n#define $PUSH()             (!setjmp($PUSH_BUF()->buf))\n\n \n/*\n  Exceptions hierarchy in Python 3.8 according to\n\n  https://docs.python.org/3/library/exceptions.html\n\n  BaseException\n  +-- SystemExit\n  +-- KeyboardInterrupt\n  +-- GeneratorExit\n  +-- Exception\n  +-- StopIteration\n  +-- StopAsyncIteration\n  +-- ArithmeticError\n  |    +-- FloatingPointError              ***\n  |    +-- OverflowError\n  |    +-- ZeroDivisionError\n  +-- AssertionError\n  +-- AttributeError\n  +-- BufferError                          ***\n  +-- EOFError\n  +-- ImportError                          ***\n  |    +-- ModuleNotFoundError             ***\n  +-- LookupError           \n  |    +-- IndexError\n  |    +-- KeyError\n  +-- MemoryError\n  +-- NameError                            ***\n  |    +-- UnboundLocalError               ***\n  +-- OSError\n  |    +-- BlockingIOError\n  |    +-- ChildProcessError\n  |    +-- ConnectionError\n  |    |    +-- BrokenPipeError\n  |    |    +-- ConnectionAbortedError\n  |    |    +-- ConnectionRefusedError\n  |    |    +-- ConnectionResetError\n  |    +-- FileExistsError\n  |    +-- FileNotFoundError\n  |    +-- InterruptedError\n  |    +-- IsADirectoryError\n  |    +-- NotADirectoryError\n  |    +-- PermissionError\n  |    +-- ProcessLookupError\n  |    +-- TimeoutError\n  +-- ReferenceError                       ***\n  +-- RuntimeError\n  |    +-- NotImplementedError\n  |    +-- RecursionError\n  +-- SyntaxError                          ***\n  |    +-- IndentationError\n  |         +-- TabError\n  +-- SystemError\n  +-- TypeError                            ***\n  +-- ValueError\n  |    +-- UnicodeError\n  |         +-- UnicodeDecodeError\n  |         +-- UnicodeEncodeError\n  |         +-- UnicodeTranslateError\n  +-- Warning\n  +-- DeprecationWarning\n  +-- PendingDeprecationWarning\n  +-- RuntimeWarning\n  +-- SyntaxWarning\n  +-- UserWarning\n  +-- FutureWarning\n  +-- ImportWarning\n  +-- UnicodeWarning\n  +-- BytesWarning\n  +-- ResourceWarning\n\n  Plus the (hidden) primitive exceptions that implement control flow in the presence of finalizers:\n\n  +-- $SEQ\n  +-- $BRK\n  +-- $CNT\n  +-- $RET\n \n*/\n\nstruct $SEQ;\nstruct $BRK;\nstruct $CNT;\nstruct $RET;\n\ntypedef struct $SEQ *$SEQ;\ntypedef struct $BRK *$BRK;\ntypedef struct $CNT *$CNT;\ntypedef struct $RET *$RET;\n\nstruct $SEQG_class {\n    char *$GCINFO;\n    int $class_id;\n    $SuperG_class $superclass;\n    B_NoneType (*__init__) ($SEQ);\n    void (*__serialize__) ($SEQ, $Serial$state);\n    $SEQ (*__deserialize__) ($SEQ, $Serial$state);\n    B_bool (*__bool__) ($SEQ);\n    B_str (*__str__) ($SEQ);\n    B_str (*__repr__) ($SEQ);\n};\nstruct $SEQ {\n    struct $SEQG_class *$class;\n    B_str error_message;\n};\nstruct $BRKG_class {\n    char *$GCINFO;\n    int $class_id;\n    $SuperG_class $superclass;\n    B_NoneType (*__init__) ($BRK);\n    void (*__serialize__) ($BRK, $Serial$state);\n    $BRK (*__deserialize__) ($BRK, $Serial$state);\n    B_bool (*__bool__) ($BRK);\n    B_str (*__str__) ($BRK);\n    B_str (*__repr__) ($BRK);\n};\nstruct $BRK {\n    struct $BRKG_class *$class;\n    B_str error_message;\n};\nstruct $CNTG_class {\n    char *$GCINFO;\n    int $class_id;\n    $SuperG_class $superclass;\n    B_NoneType (*__init__) ($CNT);\n    void (*__serialize__) ($CNT, $Serial$state);\n    $CNT (*__deserialize__) ($CNT, $Serial$state);\n    B_bool (*__bool__) ($CNT);\n    B_str (*__str__) ($CNT);\n    B_str (*__repr__) ($CNT);\n};\nstruct $CNT {\n    struct $CNTG_class *$class;\n    B_str error_message;\n};\nstruct $RETG_class {\n    char *$GCINFO;\n    int $class_id;\n    $SuperG_class $superclass;\n    B_NoneType (*__init__) ($RET, B_value);\n    void (*__serialize__) ($RET, $Serial$state);\n    $RET (*__deserialize__) ($RET, $Serial$state);\n    B_bool (*__bool__) ($RET);\n    B_str (*__str__) ($RET);\n    B_str (*__repr__) ($RET);\n};\nstruct $RET {\n    struct $RETG_class *$class;\n    B_str error_message;\n    B_value val;\n};\n\nextern struct $SEQG_class $SEQG_methods;\nextern struct $BRKG_class $BRKG_methods;\nextern struct $CNTG_class $CNTG_methods;\nextern struct $RETG_class $RETG_methods;\n\n$SEQ $SEQG_new();\n$BRK $BRKG_new();\n$CNT $CNTG_new();\n$RET $RETG_new(B_value);\n\n$WORD $raiseValueError(B_str str);\n    \n"
  },
  {
    "path": "base/builtin/float.c",
    "content": "/*\n * Copyright (C) 2019-2021 Data Ductus AB\n *\n * Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:\n *\n * 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.\n *\n * 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.\n *\n * 3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission.\n *\n * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS \"AS IS\" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n */\n\n#include <math.h>\n\n// General methods ///////////////////////////////////////////////////////////////////////\n\nB_float B_floatG_new(B_atom a) {\n    if ($ISINSTANCE0(a,B_int)) return to$float((double)((B_int)a)->val);\n    if ($ISINSTANCE0(a,B_i32)) return to$float((double)((B_i32)a)->val);\n    if ($ISINSTANCE0(a,B_i16)) return to$float((double)((B_i16)a)->val);\n    if ($ISINSTANCE0(a,B_u64)) return to$float((double)((B_u64)a)->val);\n    if ($ISINSTANCE0(a,B_u32)) return to$float((double)((B_u32)a)->val);\n    if ($ISINSTANCE0(a,B_u16)) return to$float((double)((B_u16)a)->val);\n    if ($ISINSTANCE0(a,B_bigint)) {\n        zz_struct aval = ((B_bigint)a)->val;\n        if (aval.size == 0)\n            return to$float(0.0);\n        if (labs(aval.size) > 16)\n            $RAISE((B_BaseException)$NEW(B_ValueError,to$str(\"float(): int value too big for type float\")));\n        double pow = 1.0;  \n        double res = 0.0;\n        for (int i = 0; i<(labs(aval.size)); i++) {\n            res += aval.n[i] * pow;\n            pow *= 18446744073709551616.0; // literal is 2^64\n        }\n        return to$float(aval.size<0 ? -res : res);\n    }\n    if ($ISINSTANCE0(a,B_float)) return (B_float)a;\n    if ($ISINSTANCE0(a,B_bool)) return to$float((double)((B_bool)a)->val);\n    if ($ISINSTANCE0(a,B_str)) {\n        double x;\n        int c;\n        sscanf((char *)((B_str)a)->str,\"%lf%n\",&x,&c);\n        if (c==((B_str)a)->nbytes)\n            return to$float(x);\n        else\n            $RAISE((B_BaseException)$NEW(B_ValueError,to$str(\"float_fromatom(): invalid str literal for type float\")));\n    }\n    fprintf(stderr,\"internal error: float_fromatom: argument not of atomic type\");\n    exit(-1);\n\n}\n\nB_NoneType B_floatD___init__(B_float self, B_atom a){\n    self->val = B_floatG_new(a)->val;\n    return B_None;\n}\n\nvoid B_floatD___serialize__(B_float self, $Serial$state state) {\n    $val_serialize(FLOAT_ID,&self->val,state);\n}\n\nB_float B_floatD___deserialize__(B_float self, $Serial$state state) {\n    $WORD w = $val_deserialize(state);\n    double x;\n    memcpy(&x,&w,sizeof($WORD));\n    return to$float(x);\n}\n\nB_bool B_floatD___bool__(B_float x) {\n    return toB_bool(x->val != 0.0);\n}\n\nB_str B_floatD___str__(B_float x) {\n    return $FORMAT(\"%g\", x->val);\n}\n\nB_str B_floatD___repr__(B_float x) {\n    return $FORMAT(\"%g\", x->val);\n}\n\nB_float to$float(double x) {\n    B_float res = acton_malloc(sizeof(struct B_float));\n    res->$class = &B_floatG_methods;\n    res->val = x;\n    return res;\n}\n\nB_float toB_float(double x) {\n    B_float res = acton_malloc(sizeof(struct B_float));\n    res->$class = &B_floatG_methods;\n    res->val = x;\n    return res;\n}\n\ndouble fromB_float(B_float x) {\n    return x->val;\n}\n\n\n// B_RealFloatD_float /////////////////////////////////////////////////////////////////////////\n\nB_float B_RealFloatD_floatD___add__(B_RealFloatD_float wit,  B_float a, B_float b) {\n    return to$float(fromB_float(a) + fromB_float(b));\n}  \n\nB_float B_RealFloatD_floatD___zero__(B_RealFloatD_float wit) {\n    return to$float(0.0);\n}\n\nB_float B_RealFloatD_floatD___fromatom__(B_RealFloatD_float wit, B_atom a) {\n    return B_floatG_new(a);\n}\n\nB_complex B_RealFloatD_floatD___complex__(B_RealFloatD_float wit, B_float a) {\n    return toB_complex(a->val);\n}\n\nB_float B_RealFloatD_floatD___mul__(B_RealFloatD_float wit,  B_float a, B_float b) {\n    return to$float(fromB_float(a) * fromB_float(b));\n}  \n\nB_float B_RealFloatD_floatD___pow__(B_RealFloatD_float wit,  B_float a, B_float b) {\n    return to$float(exp(fromB_float(b) * log(fromB_float(a))));\n}\n\nB_float B_RealFloatD_floatD___neg__(B_RealFloatD_float wit, B_float a) {\n    return to$float(-fromB_float(a));\n}\n\nB_float B_RealFloatD_floatD___pos__(B_RealFloatD_float wit, B_float a) {\n    return a;\n}\n\n$WORD B_RealFloatD_floatD_real(B_RealFloatD_float wit, B_float a, B_Real wit2) {\n    return wit2->$class->__fromatom__(wit2,(B_atom)a);\n}\n\n$WORD B_RealFloatD_floatD_imag(B_RealFloatD_float wit, B_float a, B_Real wit2) {\n    return wit2->$class->__fromatom__(wit2,(B_atom)to$float(0.0));\n}\n\n$WORD B_RealFloatD_floatD___abs__(B_RealFloatD_float wit, B_float a, B_Real wit2) {\n    return wit2->$class->__fromatom__(wit2,(B_atom)to$float(fabs(fromB_float(a))));\n}\n\nB_float B_RealFloatD_floatD_conjugate(B_RealFloatD_float wit, B_float a) {\n    return a;\n}\nB_float B_RealFloatD_floatD___float__ (B_RealFloatD_float wit, B_float x) {\n    return x;\n}\n\n$WORD B_RealFloatD_floatD___trunc__ (B_RealFloatD_float wit, B_float x, B_Integral wit2) {\n    return wit2->$class->__fromatom__(wit2,(B_atom)toB_int((long)trunc(fromB_float(x))));\n}\n  \n$WORD B_RealFloatD_floatD___floor__ (B_RealFloatD_float wit, B_float x, B_Integral wit2) {\n    return wit2->$class->__fromatom__(wit2,(B_atom)toB_int((long)floor(fromB_float(x))));\n}\n  \n$WORD B_RealFloatD_floatD___ceil__ (B_RealFloatD_float wit, B_float x, B_Integral wit2) {\n    return wit2->$class->__fromatom__(wit2,(B_atom)toB_int((long)ceil(fromB_float(x))));\n}\n  \nB_float B_RealFloatD_floatD___round__ (B_RealFloatD_float wit, B_float x, B_int p) {\n    double pval = p==NULL ? 0.0 : (double)fromB_int(p);\n    double p10 = pow(10.0,pval);\n    return to$float(round(x->val * p10)/p10);\n}\n     \n// B_MinusD_RealFloatD_float  ////////////////////////////////////////////////////////////////////////////////////////\n\n \nB_float B_MinusD_RealFloatD_floatD___sub__(B_MinusD_RealFloatD_float wit,  B_float a, B_float b) {\n    return to$float(fromB_float(a) - fromB_float(b));\n}  \n\n// B_DivD_float  ////////////////////////////////////////////////////////////////////////////////////////\n\nB_float B_DivD_floatD___truediv__(B_DivD_float wit, B_float a, B_float b) {\n    return to$float(fromB_float(a) / fromB_float(b));\n}  \n\n// B_OrdD_float  ////////////////////////////////////////////////////////////////////////////////////////\n\nB_bool B_OrdD_floatD___eq__ (B_OrdD_float wit, B_float a, B_float b) {\n    return toB_bool(a->val == b->val);\n}\n\nB_bool B_OrdD_floatD___ne__ (B_OrdD_float wit, B_float a, B_float b) {\n    return toB_bool(a->val != b->val);\n}\n\nB_bool B_OrdD_floatD___lt__ (B_OrdD_float wit, B_float a, B_float b) {\n    return toB_bool(a->val < b->val);\n}\n\nB_bool B_OrdD_floatD___le__ (B_OrdD_float wit, B_float a, B_float b) {\n    return toB_bool(a->val <= b->val);\n}\n\nB_bool B_OrdD_floatD___gt__ (B_OrdD_float wit, B_float a, B_float b) {\n    return toB_bool(a->val > b->val);\n}\n\nB_bool B_OrdD_floatD___ge__ (B_OrdD_float wit, B_float a, B_float b) {\n    return toB_bool(a->val >= b->val);\n}\n\n\n// B_HashableD_float ///////////////////////////////////////////////////////////////////////////////////////////////////////\n\nB_bool B_HashableD_floatD___eq__(B_HashableD_float wit, B_float a, B_float b) {\n    return toB_bool(a->val == b->val);\n}\n\nB_bool B_HashableD_floatD___neq__(B_HashableD_float wit, B_float a, B_float b) {\n    return toB_bool(a->val != b->val);\n}\n\nB_NoneType B_HashableD_floatD_hash(B_HashableD_float wit, B_float a, B_hasher h) {\n    zig_hash_wyhash_update(h->_hasher, to$bytesD_len((char *)&(a->val), 8));\n    return B_None;\n}\n"
  },
  {
    "path": "base/builtin/float.h",
    "content": "\nstruct B_float {\n    struct B_floatG_class *$class;\n    double val;\n};\n\n// #define B_RealD_floatG_new(...) B_RealFloatG_new(__VA_ARGS__)\n// #define B_RealD_float B_RealFloat\n\nB_float to$float(double x); // Dare not remove this; possibly used in compiler...?\n\nB_float toB_float(double x);\ndouble fromB_float(B_float x);\n\nB_float B_floatG_new(B_atom a);\n\n#define float_DIV(x,y)           (x/y)\n#define float_pow(x,y)           (pow(x,y))\n"
  },
  {
    "path": "base/builtin/function.c",
    "content": "/*\n * Copyright (C) 2019-2021 Data Ductus AB\n *\n * Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:\n *\n * 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.\n *\n * 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.\n *\n * 3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission.\n *\n * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS \"AS IS\" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n */\n\n////////////////////////////////////////////////////////////////////////////////////////\n\nB_bool $procD___bool__($proc self) {\n  return B_True;\n}\nB_str $procD___str__($proc self) {\n  return $FORMAT(\"<proc closure at %p>\", self);\n}\n\nB_bool $actionD___bool__($action self) {\n  return B_True;\n}\nB_str $actionD___str__($action self) {\n  return $FORMAT(\"<action closure at %p>\", self);\n}\n\nB_bool $mutD___bool__($mut self) {\n  return B_True;\n}\nB_str $mutD___str__($mut self) {\n  return $FORMAT(\"<mut closure at %p>\", self);\n}\n\nB_bool $pureD___bool__($pure self) {\n  return B_True;\n}\nB_str $pureD___str__($pure self) {\n  return $FORMAT(\"<pure closure at %p>\", self);\n}\n\nvoid $ContD___init__($Cont $this) {\n    // Empty\n}\nB_bool $ContD___bool__($Cont self) {\n  return B_True;\n}\nB_str $ContD___str__($Cont self) {\n  return $FORMAT(\"<$Cont closure at %p>\", self);\n}\nvoid $ContD___serialize__($Cont self, $Serial$state state) {\n    // Empty\n}\n$Cont $ContD___deserialize__($Cont self, $Serial$state state) {\n    return $DNEW($Cont,state);\n}\n\nstruct $ContG_class $ContG_methods = {\n    \"$Cont\",\n    UNASSIGNED,\n    NULL,\n    $ContD___init__,\n    $ContD___serialize__,\n    $ContD___deserialize__,\n    $ContD___bool__,\n    $ContD___str__,\n    $ContD___str__,\n    NULL                /* __call__ */\n};\nstruct $procG_class $procG_methods = {\n    \"$proc\",\n    UNASSIGNED,\n    NULL,\n    NULL,               /* __init__ */\n    NULL,               /* __serialize__ */\n    NULL,               /* __deserialize__ */\n    $procD___bool__,\n    $procD___str__,\n    $procD___str__,\n    NULL,               /* __call__ */\n    NULL                /* __exec__ */\n};\nstruct $actionG_class $actionG_methods = {\n    \"$action\",\n    UNASSIGNED,\n    NULL,\n    NULL,               /* __init__ */\n    NULL,               /* __serialize__ */\n    NULL,               /* __deserialize__ */\n    $actionD___bool__,\n    $actionD___str__,\n    $actionD___str__,\n    NULL,               /* __call__ */\n    NULL,               /* __exec__ */\n    NULL                /* __asyn__ */\n};\nstruct $mutG_class $mutG_methods = {\n    \"$mut\",\n    UNASSIGNED,\n    NULL,\n    NULL,               /* __init__ */\n    NULL,               /* __serialize__ */\n    NULL,               /* __deserialize__ */\n    $mutD___bool__,\n    $mutD___str__,\n    $mutD___str__,\n    NULL,               /* __call__ */\n    NULL,               /* __exec__ */\n    NULL                /* __eval__ */\n};\nstruct $pureG_class $pureG_methods = {\n    \"$pure\",\n    UNASSIGNED,\n    NULL,\n    NULL,               /* __init__ */\n    NULL,               /* __serialize__ */\n    NULL,               /* __deserialize__ */\n    $pureD___bool__,\n    $pureD___str__,\n    $pureD___str__,\n    NULL,               /* __call__ */\n    NULL,               /* __exec__ */\n    NULL                /* __eval__ */\n};\n"
  },
  {
    "path": "base/builtin/function.h",
    "content": "#pragma once\n\nstruct $ContG_class {\n    char *$GCINFO;\n    int $class_id;\n    $SuperG_class $superclass;\n    void (*__init__)($Cont);\n    void (*__serialize__)($Cont, $Serial$state);\n    $Cont (*__deserialize__)($Cont, $Serial$state);\n    B_bool (*__bool__)($Cont);\n    B_str (*__str__)($Cont);\n    B_str (*__repr__)($Cont);\n    $R (*__call__)($Cont, $WORD);\n};\nstruct $Cont {\n    struct $ContG_class *$class;\n};\nextern struct $ContG_class $ContG_methods;\n\nvoid $ContD___init__($Cont);\nB_bool $ContD___bool__($Cont);\nB_str $ContD___str__($Cont);\nvoid $ContD___serialize__($Cont, $Serial$state);\n$Cont $ContD___deserialize__($Cont, $Serial$state);\n\n\nstruct $procG_class {\n    char *$GCINFO;\n    int $class_id;\n    $SuperG_class $superclass;\n    void (*__init__)($proc);\n    void (*__serialize__)($proc, $Serial$state);\n    $proc (*__deserialize__)($proc, $Serial$state);\n    B_bool (*__bool__)($proc);\n    B_str (*__str__)($proc);\n    B_str (*__repr__)($proc);\n    $R (*__call__)($proc, $Cont, $WORD);\n    $R (*__exec__)($proc, $Cont, $WORD);\n};\nstruct $proc {\n    struct $procG_class *$class;\n};\nextern struct $procG_class $procG_methods;\n\n\nstruct $actionG_class {\n    char *$GCINFO;\n    int $class_id;\n    $SuperG_class $superclass;\n    void (*__init__)($action);\n    void (*__serialize__)($action, $Serial$state);\n    $action (*__deserialize__)($action, $Serial$state);\n    B_bool (*__bool__)($action);\n    B_str (*__str__)($action);\n    B_str (*__repr__)($action);\n    $R (*__call__)($action, $Cont, $WORD);\n    $R (*__exec__)($action, $Cont, $WORD);\n    B_Msg (*__asyn__)($action, $WORD);\n};\nstruct $action {\n    struct $actionG_class *$class;\n};\nextern struct $actionG_class $actionG_methods;\n\n\nstruct $mutG_class {\n    char *$GCINFO;\n    int $class_id;\n    $SuperG_class $superclass;\n    void (*__init__)($mut);\n    void (*__serialize__)($mut, $Serial$state);\n    $mut (*__deserialize__)($mut, $Serial$state);\n    B_bool (*__bool__)($mut);\n    B_str (*__str__)($mut);\n    B_str (*__repr__)($mut);\n    $R (*__call__)($mut, $Cont, $WORD);\n    $R (*__exec__)($mut, $Cont, $WORD);\n    $WORD (*__eval__)($mut, $WORD);\n};\nstruct $mut {\n    struct $mutG_class *$class;\n};\nextern struct $mutG_class $mutG_methods;\n\n\nstruct $pureG_class {\n    char *$GCINFO;\n    int $class_id;\n    $SuperG_class $superclass;\n    void (*__init__)($pure);\n    void (*__serialize__)($pure, $Serial$state);\n    $pure (*__deserialize__)($pure, $Serial$state);\n    B_bool (*__bool__)($pure);\n    B_str (*__str__)($pure);\n    B_str (*__repr__)($pure);\n    $R (*__call__)($pure, $Cont, $WORD);\n    $R (*__exec__)($pure, $Cont, $WORD);\n    $WORD (*__eval__)($pure, $WORD);\n};\nstruct $pure {\n    struct $pureG_class *$class;\n};\nextern struct $pureG_class $pureG_methods;\n\n\n//////////////////////////////////////////////////////////////////////////////////\nstruct $action2;\ntypedef struct $action2 *$action2;\nstruct $action2G_class {\n    char *$GCINFO;\n    int $class_id;\n    $SuperG_class $superclass;\n    void (*__init__)($action2);\n    void (*__serialize__)($action2, $Serial$state);\n    $action2 (*__deserialize__)($action2, $Serial$state);\n    B_bool (*__bool__)($action2);\n    B_str (*__str__)($action2);\n    B_str (*__repr__)($action2);\n    $R (*__call__)($action2, $Cont, $WORD, $WORD);\n    $R (*__exec__)($action2, $Cont, $WORD, $WORD);\n    B_Msg (*__asyn__)($action2, $WORD, $WORD);\n};\nstruct $action2 {\n    struct $action2G_class *$class;\n};\n\nstruct $action3;\ntypedef struct $action3 *$action3;\nstruct $action3G_class {\n    char *$GCINFO;\n    int $class_id;\n    $SuperG_class $superclass;\n    void (*__init__)($action3);\n    void (*__serialize__)($action3, $Serial$state);\n    $action3 (*__deserialize__)($action3, $Serial$state);\n    B_bool (*__bool__)($action3);\n    B_str (*__str__)($action3);\n    B_str (*__repr__)($action3);\n    $R (*__call__)($action3, $Cont, $WORD, $WORD, $WORD);\n    $R (*__exec__)($action3, $WORD, $WORD, $WORD);\n    B_Msg (*__asyn__)($action3, $WORD, $WORD, $WORD);\n};\nstruct $action3 {\n    struct $action3G_class *$class;\n};\n"
  },
  {
    "path": "base/builtin/hasher.c",
    "content": "B_NoneType B_hasherD___init__ (B_hasher self, B_u64 seed) {\n    self->_hasher = zig_hash_wyhash_init(seed ? fromB_u64(seed) : 0);\n    return B_None;\n}\n\nB_NoneType B_hasherD_update (B_hasher self, B_bytes data) {\n    zig_hash_wyhash_update(self->_hasher, data);\n    return B_None;\n}\n\nB_u64 B_hasherD_finalize (B_hasher self) {\n    uint64_t h = zig_hash_wyhash_final(self->_hasher);\n    B_u64 result = toB_u64(h);\n    return result;\n}\n\nB_bool B_hasherD___bool__(B_hasher h) {\n    return B_True;\n}\n\nB_str B_hasherD___str__(B_hasher self) {\n    return $FORMAT(\"<hasher object at %p>\", self);\n}\n\nB_str B_hasherD___repr__(B_hasher self) {\n    return $FORMAT(\"<hasher object at %p>\",self);\n}\n\nB_hasher B_hasherG_new(B_u64 seed) {\n    return $NEW(B_hasher, seed);\n}\n \nvoid B_hasherD___serialize__(B_hasher self, $Serial$state state) {\n    // TODO\n}\n\nB_hasher B_hasherD___deserialize__(B_hasher self, $Serial$state state) {\n    // TODO\n    return B_hasherG_new(toB_u64(0));\n}\n\n"
  },
  {
    "path": "base/builtin/hasher.h",
    "content": "struct B_hasher;\ntypedef struct B_hasher *B_hasher;\n\n/*\nstruct B_hasherG_class {\n    char *$GCINFO;\n    int $class_id;\n    $SuperG_class $superclass;\n    B_NoneType (*__init__) (B_hasher, u64);\n    void (*__serialize__) (B_hasher, $Serial$state);\n    B_hasher (*__deserialize__) (B_hasher, $Serial$state);\n    B_bool (*__bool__) (B_hasher);\n    B_str (*__str__) (B_hasher);\n    B_str (*__repr__) (B_hasher);\n    B_NoneType (*update) (B_hasher, B_bytes);\n    B_u64 (*finalize) (B_hasher);\n};\n*/\n\nstruct B_hasher {\n    struct B_hasherG_class *$class;\n    void  *_hasher;\n};\n\nextern struct B_hasherG_class B_hasherG_methods;\nB_hasher B_hasherG_new(B_u64);\n\nvoid *zig_hash_wyhash_init(uint64_t seed);\nvoid zig_hash_wyhash_update(void *hasher, B_bytes data);\nuint64_t zig_hash_wyhash_final(void *hasher);\n\nuint64_t zig_hash_wyhash_hash(uint64_t seed, B_bytes data);\n\n"
  },
  {
    "path": "base/builtin/i16.c",
    "content": "/*\n * Copyright (C) 2019-2021 Data Ductus AB\n *\n * Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:\n *\n * 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.\n *\n * 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.\n *\n * 3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission.\n *\n * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS \"AS IS\" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n */\n\n// Auxiliary //////////////////////////////////////////////////////////////////////////////\n\n// only called with e>=0.\nshort i16_pow(short a, short e) {\n    if (e == 0) return 1;\n    if (e == 1) return a;\n    if (e%2 == 0) return i16_pow(a*a,e/2);\n    return a * i16_pow(a*a,e/2);\n}\n\n// General methods ///////////////////////////////////////////////////////////////////////\n\nB_i16 B_i16G_new(B_atom a, B_int base) {\n    B_bigint b = B_bigintG_new(a, base);\n    unsigned long n = b->val.n[0];\n    long sz = b->val.size;\n    if (labs(sz) > 1 || (sz==1 && n > 0x7ffful) || sz == -1 && n > 0x8000ul) {\n        char errmsg[1024];\n        snprintf(errmsg, sizeof(errmsg), \"i16(): value %s out of range for type i16\",get_str(&b->val));\n        $RAISE((B_BaseException)$NEW(B_ValueError,to$str(errmsg)));\n    }\n    return toB_i16((short)(n*sz));\n}\n\nB_NoneType B_i16D___init__(B_i16 self, B_atom a, B_int base){\n    self->val = B_i16G_new(a,base)->val;\n    return B_None;\n}\n\nvoid B_i16D___serialize__(B_i16 n, $Serial$state state) {\n    $val_serialize(I16_ID,&n->val,state);\n}\n\nB_i16 B_i16D___deserialize__(B_i16 n, $Serial$state state) {\n    return toB_i16((short)(uintptr_t)$val_deserialize(state));\n}\n\nB_bool B_i16D___bool__(B_i16 n) {\n    return toB_bool(n->val != 0);\n}\n\nB_str B_i16D___str__(B_i16 n) {\n    return $FORMAT(\"%hd\", n->val);\n}\n\nB_str B_i16D___repr__(B_i16 n) {\n    return $FORMAT(\"%hd\", n->val);\n}\n\nB_i16 toB_i16(short i) {\n    B_i16 res = acton_malloc(sizeof(struct B_i16));\n    res->$class = &B_i16G_methods;\n    res->val = i;\n    return res;\n}\n\nshort fromB_i16(B_i16 w) {\n    return w->val;\n}\n\n                  \n\n// B_IntegralD_i16 /////////////////////////////////////////////////////////////////////////\n\n \nB_i16 B_IntegralD_i16D___add__(B_IntegralD_i16 wit,  B_i16 a, B_i16 b) {\n    return toB_i16(a->val + b->val);\n}  \n\nB_i16 B_IntegralD_i16D___zero__(B_IntegralD_i16 wit) {\n    return toB_i16(0);\n}\n\nB_complex B_IntegralD_i16D___complex__(B_IntegralD_i16 wit, B_i16 a) {\n    return toB_complex((double)a->val);\n}\n\nB_i16 B_IntegralD_i16D___fromatom__(B_IntegralD_i16 wit, B_atom a) {\n    return B_i16G_new(a,NULL);\n}\n\nB_i16 B_IntegralD_i16D___mul__(B_IntegralD_i16 wit,  B_i16 a, B_i16 b) {\n    return toB_i16(a->val * b->val);\n}  \n  \nB_i16 B_IntegralD_i16D___pow__(B_IntegralD_i16 wit,  B_i16 a, B_i16 b) {\n    if ( b->val < 0) {\n        // raise VALUEERROR;\n        return NULL;\n    }\n    return toB_i16(i16_pow(a->val,b->val));\n}\n\nB_i16 B_IntegralD_i16D___neg__(B_IntegralD_i16 wit,  B_i16 a) {\n    return toB_i16(-a->val);\n}\n\nB_i16 B_IntegralD_i16D___pos__(B_IntegralD_i16 wit,  B_i16 a) {\n    return a;\n}\n\n$WORD B_IntegralD_i16D_real(B_IntegralD_i16 wit, B_i16 a, B_Real wit2) {\n    return wit2->$class->__fromatom__(wit2,(B_atom)a);\n}\n\n$WORD B_IntegralD_i16D_imag(B_IntegralD_i16 wit, B_i16 a, B_Real wit2) {\n    return wit2->$class->__fromatom__(wit2,(B_atom)toB_i16(0L));\n}\n\n$WORD B_IntegralD_i16D___abs__(B_IntegralD_i16 wit, B_i16 a, B_Real wit2) {\n    return wit2->$class->__fromatom__(wit2,(B_atom)toB_i16(labs(a->val)));\n}\n\nB_i16 B_IntegralD_i16D_conjugate(B_IntegralD_i16 wit,  B_i16 a) {\n    return a;\n}\n\nB_float B_IntegralD_i16D___float__ (B_IntegralD_i16 wit, B_i16 n) {\n    return to$float((double)n->val);\n}\n\n$WORD B_IntegralD_i16D___trunc__ (B_IntegralD_i16 wit, B_i16 n, B_Integral wit2) {\n    return wit2->$class->__fromatom__(wit2,(B_atom)n);\n}\n  \n$WORD B_IntegralD_i16D___floor__ (B_IntegralD_i16 wit, B_i16 n, B_Integral wit2) {\n    return wit2->$class->__fromatom__(wit2,(B_atom)n);\n}\n  \n$WORD B_IntegralD_i16D___ceil__ (B_IntegralD_i16 wit, B_i16 n, B_Integral wit2) {\n    return wit2->$class->__fromatom__(wit2,(B_atom)n);\n}\n  \nB_i16 B_IntegralD_i16D___round__ (B_IntegralD_i16 wit, B_i16 n, B_int p) {\n    short nval = n->val;\n    if (nval<0)\n        return toB_i16(-B_IntegralD_i16D___round__(wit,toB_i16(-nval),p)->val);\n    short pval = p==NULL ? 0 : fromB_int(p);\n    if (pval>=0)\n        return n;\n    short p10 = i16_pow(10,-pval);\n    short res = nval/p10;\n    if (nval%p10 * 2 > p10)\n        res++; \n    return toB_i16 (res * p10);\n}\n  \n$WORD B_IntegralD_i16D_numerator (B_IntegralD_i16 wit, B_i16 n, B_Integral wit2) {\n    return wit2->$class->__fromatom__(wit2,(B_atom)n);\n}\n  \n$WORD B_IntegralD_i16D_denominator (B_IntegralD_i16 wit, B_i16 n, B_Integral wit2) {\n    return wit2->$class->__fromatom__(wit2,(B_atom)toB_i16(1L));\n}\n  \nB_int B_IntegralD_i16D___int__ (B_IntegralD_i16 wit, B_i16 n) {\n    return B_intG_new((B_atom)n,NULL);\n}\n\nB_int B_IntegralD_i16D___index__(B_IntegralD_i16 wit, B_i16 n) {\n    return B_intG_new((B_atom)n,NULL);\n}\n\nB_tuple B_IntegralD_i16D___divmod__(B_IntegralD_i16 wit, B_i16 a, B_i16 b) {\n    if (b->val == 0)\n        $RAISE((B_BaseException)$NEW(B_ZeroDivisionError, to$str(\"division by zero\")));\n    short n = a->val;\n    short d = b->val;\n    return $NEWTUPLE(2, toB_i16(n/d), toB_i16(n%d));\n}\n\nB_i16 B_IntegralD_i16D___floordiv__(B_IntegralD_i16 wit, B_i16 a, B_i16 b) {\n    if (b->val == 0)\n        $RAISE((B_BaseException)$NEW(B_ZeroDivisionError, to$str(\"division by zero\")));\n    return toB_i16(a->val / b->val);\n}\n\nB_i16 B_IntegralD_i16D___mod__(B_IntegralD_i16 wit, B_i16 a, B_i16 b) {\n    return toB_i16(a->val % b->val);\n}\n\nB_i16 B_IntegralD_i16D___lshift__(B_IntegralD_i16 wit,  B_i16 a, B_int b) {\n    return toB_i16(a->val << fromB_int(b));\n}\n\nB_i16 B_IntegralD_i16D___rshift__(B_IntegralD_i16 wit,  B_i16 a, B_int b) {\n    return toB_i16(a->val >> fromB_int(b));\n}\n \nB_i16 B_IntegralD_i16D___invert__(B_IntegralD_i16 wit,  B_i16 a) {\n    return toB_i16(~a->val);\n}\n\n\n// B_LogicalD_IntegralD_i16  ////////////////////////////////////////////////////////////////////////////////////////\n\nB_i16 B_LogicalD_IntegralD_i16D___and__(B_LogicalD_IntegralD_i16 wit,  B_i16 a, B_i16 b) {\n    return toB_i16(a->val & b->val);\n}\n                                                 \nB_i16 B_LogicalD_IntegralD_i16D___or__(B_LogicalD_IntegralD_i16 wit,  B_i16 a, B_i16 b) {\n    return toB_i16(a->val | b->val);\n}\n                                                 \nB_i16 B_LogicalD_IntegralD_i16D___xor__(B_LogicalD_IntegralD_i16 wit,  B_i16 a, B_i16 b) {\n    return toB_i16(a->val ^ b->val);\n}  \n \n// B_MinusD_IntegralD_i16  ////////////////////////////////////////////////////////////////////////////////////////\n\n \nB_i16 B_MinusD_IntegralD_i16D___sub__(B_MinusD_IntegralD_i16 wit,  B_i16 a, B_i16 b) {\n    return toB_i16(a->val - b->val);\n}  \n\n// B_DivD_i16  ////////////////////////////////////////////////////////////////////////////////////////\n\n \nB_float B_DivD_i16D___truediv__ (B_DivD_i16 wit, B_i16 a, B_i16 b) {\n    if (b->val == 0)\n        $RAISE((B_BaseException)$NEW(B_ZeroDivisionError, to$str(\"division by zero\")));\n    return to$float((double)a->val/(double)b->val);\n}\n\n// B_OrdD_i16  ////////////////////////////////////////////////////////////////////////////////////////\n\nB_bool B_OrdD_i16D___eq__ (B_OrdD_i16 wit, B_i16 a, B_i16 b) {\n    return toB_bool(a->val == b->val);\n}\n\nB_bool B_OrdD_i16D___ne__ (B_OrdD_i16 wit, B_i16 a, B_i16 b) {\n    return toB_bool(a->val != b->val);\n}\n\nB_bool B_OrdD_i16D___lt__ (B_OrdD_i16 wit, B_i16 a, B_i16 b) {\n    return toB_bool(a->val < b->val);\n}\n\nB_bool B_OrdD_i16D___le__ (B_OrdD_i16 wit, B_i16 a, B_i16 b) {\n    return toB_bool(a->val <= b->val);\n}\n\nB_bool B_OrdD_i16D___gt__ (B_OrdD_i16 wit, B_i16 a, B_i16 b) {\n    return toB_bool(a->val > b->val);\n}\n\nB_bool B_OrdD_i16D___ge__ (B_OrdD_i16 wit, B_i16 a, B_i16 b) {\n    return toB_bool(a->val >= b->val);\n}\n\n// B_HashableD_i16 ///////////////////////////////////////////////////////////////////////////////////////////////////////\n\nB_bool B_HashableD_i16D___eq__(B_HashableD_i16 wit, B_i16 a, B_i16 b) {\n    return toB_bool(a->val == b->val);\n}\n\nB_bool B_HashableD_i16D___ne__(B_HashableD_i16 wit, B_i16 a, B_i16 b) {\n    return toB_bool(a->val != b->val);\n}\n\nB_NoneType B_HashableD_i16D_hash(B_HashableD_i16 wit, B_i16 a, B_hasher h) {\n    zig_hash_wyhash_update(h->_hasher, to$bytesD_len((char *)&(a->val), 2));\n    return B_None;\n}\n"
  },
  {
    "path": "base/builtin/i16.h",
    "content": "struct B_i16 {\n    struct B_i16G_class *$class;\n    short val;\n};\n\n \nB_i16 toB_i16(short n);\nshort fromB_i16(B_i16 n);\n\nB_i16 B_i16G_new(B_atom a, B_int base);\n \n#define i16_DIV(a,b)       ( {if (b==0) $RAISE((B_BaseException)$NEW(B_ZeroDivisionError,to$str(\"i16 truediv: division by zero\"))); (double)a/(double)b;} )\n#define i16_FLOORDIV(a,b)  ( {if (b==0) $RAISE((B_BaseException)$NEW(B_ZeroDivisionError,to$str(\"i16 floordiv: division by zero\")));  a/b;} )\n#define i16_MOD(a,b)       ( {if (b==0) $RAISE((B_BaseException)$NEW(B_ZeroDivisionError,to$str(\"i16 mod: division by zero\"))); a%b;} )\n\nshort i16_pow(short a, short b);\n"
  },
  {
    "path": "base/builtin/i32.c",
    "content": "/*\n * Copyright (C) 2019-2021 Data Ductus AB\n *\n * Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:\n *\n * 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.\n *\n * 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.\n *\n * 3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission.\n *\n * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS \"AS IS\" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n */\n\n// Auxiliary //////////////////////////////////////////////////////////////////////////////\n\n// only called with e>=0.\nint i32_pow(int a, int e) {\n    if (e == 0) return 1;\n    if (e == 1) return a;\n    if (e%2 == 0) return i32_pow(a*a,e/2);\n    return a * i32_pow(a*a,e/2);\n}\n\n// General methods ///////////////////////////////////////////////////////////////////////\n\nB_i32 B_i32G_new(B_atom a, B_int base) {\n    B_bigint b = B_bigintG_new(a, base);\n    unsigned long n = b->val.n[0];\n    long sz = b->val.size;\n    if (labs(sz) > 1 || (sz==1 && n > 0x7ffffffful) || sz == -1 && n > 0x80000000ul) {\n        char errmsg[1024];\n        snprintf(errmsg, sizeof(errmsg), \"i32(): value %s out of range for type i32\",get_str(&b->val));\n        $RAISE((B_BaseException)$NEW(B_ValueError,to$str(errmsg)));\n    }\n    return toB_i32((int)(n*sz));\n}\n\n\nB_NoneType B_i32D___init__(B_i32 self, B_atom a, B_int base){\n    self->val = B_i32G_new(a,base)->val;\n    return B_None;\n}\n\nvoid B_i32D___serialize__(B_i32 n, $Serial$state state) {\n    $val_serialize(I32_ID,&n->val,state);\n}\n\nB_i32 B_i32D___deserialize__(B_i32 n, $Serial$state state) {\n    return toB_i32((int)(uintptr_t)$val_deserialize(state));\n}\n\nB_bool B_i32D___bool__(B_i32 n) {\n    return toB_bool(n->val != 0);\n}\n\nB_str B_i32D___str__(B_i32 n) {\n    return $FORMAT(\"%d\", n->val);\n}\n\nB_str B_i32D___repr__(B_i32 n) {\n    return $FORMAT(\"%d\", n->val);\n}\n\nB_i32 toB_i32(int i) {\n    B_i32 res = acton_malloc(sizeof(struct B_i32));\n    res->$class = &B_i32G_methods;\n    res->val = i;\n    return res;\n}\n\nint fromB_i32(B_i32 w) {\n    return w->val;\n}\n\n                  \n\n// B_IntegralD_i32 /////////////////////////////////////////////////////////////////////////\n\n \nB_i32 B_IntegralD_i32D___add__(B_IntegralD_i32 wit,  B_i32 a, B_i32 b) {\n    return toB_i32(a->val + b->val);\n}  \n\nB_i32 B_IntegralD_i32D___zero__(B_IntegralD_i32 wit) {\n    return toB_i32(0);\n}\n\nB_complex B_IntegralD_i32D___complex__(B_IntegralD_i32 wit, B_i32 a) {\n    return toB_complex((double)a->val);\n}\n\nB_i32 B_IntegralD_i32D___fromatom__(B_IntegralD_i32 wit, B_atom a) {\n    return B_i32G_new(a,NULL);\n}\n\nB_i32 B_IntegralD_i32D___mul__(B_IntegralD_i32 wit,  B_i32 a, B_i32 b) {\n    return toB_i32(a->val * b->val);\n}  \n  \nB_i32 B_IntegralD_i32D___pow__(B_IntegralD_i32 wit,  B_i32 a, B_i32 b) {\n    if ( b->val < 0) {\n        // raise VALUEERROR;\n        return NULL;\n    }\n    return toB_i32(i32_pow(a->val,b->val));\n}\n\nB_i32 B_IntegralD_i32D___neg__(B_IntegralD_i32 wit,  B_i32 a) {\n    return toB_i32(-a->val);\n}\n\nB_i32 B_IntegralD_i32D___pos__(B_IntegralD_i32 wit,  B_i32 a) {\n    return a;\n}\n\n$WORD B_IntegralD_i32D_real(B_IntegralD_i32 wit, B_i32 a, B_Real wit2) {\n    return wit2->$class->__fromatom__(wit2,(B_atom)a);\n}\n\n$WORD B_IntegralD_i32D_imag(B_IntegralD_i32 wit, B_i32 a, B_Real wit2) {\n    return wit2->$class->__fromatom__(wit2,(B_atom)toB_i32(0L));\n}\n\n$WORD B_IntegralD_i32D___abs__(B_IntegralD_i32 wit, B_i32 a, B_Real wit2) {\n    return wit2->$class->__fromatom__(wit2,(B_atom)toB_i32(labs(a->val)));\n}\n\nB_i32 B_IntegralD_i32D_conjugate(B_IntegralD_i32 wit,  B_i32 a) {\n    return a;\n}\n\nB_float B_IntegralD_i32D___float__ (B_IntegralD_i32 wit, B_i32 n) {\n    return to$float((double)n->val);\n}\n\n$WORD B_IntegralD_i32D___trunc__ (B_IntegralD_i32 wit, B_i32 n, B_Integral wit2) {\n    return wit2->$class->__fromatom__(wit2,(B_atom)n);\n}\n  \n$WORD B_IntegralD_i32D___floor__ (B_IntegralD_i32 wit, B_i32 n, B_Integral wit2) {\n    return wit2->$class->__fromatom__(wit2,(B_atom)n);\n}\n  \n$WORD B_IntegralD_i32D___ceil__ (B_IntegralD_i32 wit, B_i32 n, B_Integral wit2) {\n    return wit2->$class->__fromatom__(wit2,(B_atom)n);\n}\n  \nB_i32 B_IntegralD_i32D___round__ (B_IntegralD_i32 wit, B_i32 n, B_int p) {\n    int nval = n->val;\n    if (nval<0)\n        return toB_i32(-B_IntegralD_i32D___round__(wit,toB_i32(-nval),p)->val);\n    int pval = p==NULL ? 0 : fromB_int(p);\n    if (pval>=0)\n        return n;\n    int p10 = i32_pow(10,-pval);\n    int res = nval/p10;\n    if (nval%p10 * 2 > p10)\n        res++; \n    return toB_i32 (res * p10);\n}\n  \n$WORD B_IntegralD_i32D_numerator (B_IntegralD_i32 wit, B_i32 n, B_Integral wit2) {\n    return wit2->$class->__fromatom__(wit2,(B_atom)n);\n}\n  \n$WORD B_IntegralD_i32D_denominator (B_IntegralD_i32 wit, B_i32 n, B_Integral wit2) {\n    return wit2->$class->__fromatom__(wit2,(B_atom)toB_i32(1L));\n}\n  \nB_int B_IntegralD_i32D___int__ (B_IntegralD_i32 wit, B_i32 n) {\n    return B_intG_new((B_atom)n,NULL);\n}\n\nB_int B_IntegralD_i32D___index__(B_IntegralD_i32 wit, B_i32 n) {\n    return B_intG_new((B_atom)n,NULL);\n}\n\nB_tuple B_IntegralD_i32D___divmod__(B_IntegralD_i32 wit, B_i32 a, B_i32 b) {\n    int n = a->val;\n    int d = b->val;\n    return $NEWTUPLE(2, toB_i32(n/d), toB_i32(n%d));\n}\n\nB_i32 B_IntegralD_i32D___floordiv__(B_IntegralD_i32 wit, B_i32 a, B_i32 b) {\n    if (b->val == 0)\n        $RAISE((B_BaseException)$NEW(B_ZeroDivisionError, to$str(\"division by zero\")));\n    return toB_i32(a->val / b->val);\n}\n\nB_i32 B_IntegralD_i32D___mod__(B_IntegralD_i32 wit, B_i32 a, B_i32 b) {\n    return toB_i32(a->val % b->val);\n}\n\nB_i32 B_IntegralD_i32D___lshift__(B_IntegralD_i32 wit,  B_i32 a, B_int b) {\n    return toB_i32(a->val << fromB_int(b));\n}\n\nB_i32 B_IntegralD_i32D___rshift__(B_IntegralD_i32 wit,  B_i32 a, B_int b) {\n    return toB_i32(a->val >> fromB_int(b));\n}\n \nB_i32 B_IntegralD_i32D___invert__(B_IntegralD_i32 wit,  B_i32 a) {\n    return toB_i32(~a->val);\n}\n\n\n// B_LogicalD_IntegralD_i32  ////////////////////////////////////////////////////////////////////////////////////////\n\nB_i32 B_LogicalD_IntegralD_i32D___and__(B_LogicalD_IntegralD_i32 wit,  B_i32 a, B_i32 b) {\n    return toB_i32(a->val & b->val);\n}\n                                                 \nB_i32 B_LogicalD_IntegralD_i32D___or__(B_LogicalD_IntegralD_i32 wit,  B_i32 a, B_i32 b) {\n    return toB_i32(a->val | b->val);\n}\n                                                 \nB_i32 B_LogicalD_IntegralD_i32D___xor__(B_LogicalD_IntegralD_i32 wit,  B_i32 a, B_i32 b) {\n    return toB_i32(a->val ^ b->val);\n}  \n \n// B_MinusD_IntegralD_i32  ////////////////////////////////////////////////////////////////////////////////////////\n\n \nB_i32 B_MinusD_IntegralD_i32D___sub__(B_MinusD_IntegralD_i32 wit,  B_i32 a, B_i32 b) {\n    return toB_i32(a->val - b->val);\n}  \n\n// B_DivD_i32  ////////////////////////////////////////////////////////////////////////////////////////\n\n \nB_float B_DivD_i32D___truediv__ (B_DivD_i32 wit, B_i32 a, B_i32 b) {\n    if (b->val == 0)\n        $RAISE((B_BaseException)$NEW(B_ZeroDivisionError, to$str(\"division by zero\")));\n    return to$float((double)a->val/(double)b->val);\n}\n\n// B_OrdD_i32  ////////////////////////////////////////////////////////////////////////////////////////\n\nB_bool B_OrdD_i32D___eq__ (B_OrdD_i32 wit, B_i32 a, B_i32 b) {\n    return toB_bool(a->val == b->val);\n}\n\nB_bool B_OrdD_i32D___ne__ (B_OrdD_i32 wit, B_i32 a, B_i32 b) {\n    return toB_bool(a->val != b->val);\n}\n\nB_bool B_OrdD_i32D___lt__ (B_OrdD_i32 wit, B_i32 a, B_i32 b) {\n    return toB_bool(a->val < b->val);\n}\n\nB_bool B_OrdD_i32D___le__ (B_OrdD_i32 wit, B_i32 a, B_i32 b) {\n    return toB_bool(a->val <= b->val);\n}\n\nB_bool B_OrdD_i32D___gt__ (B_OrdD_i32 wit, B_i32 a, B_i32 b) {\n    return toB_bool(a->val > b->val);\n}\n\nB_bool B_OrdD_i32D___ge__ (B_OrdD_i32 wit, B_i32 a, B_i32 b) {\n    return toB_bool(a->val >= b->val);\n}\n\n// B_HashableD_i32 ///////////////////////////////////////////////////////////////////////////////////////////////////////\n\nB_bool B_HashableD_i32D___eq__(B_HashableD_i32 wit, B_i32 a, B_i32 b) {\n    return toB_bool(a->val == b->val);\n}\n\nB_bool B_HashableD_i32D___ne__(B_HashableD_i32 wit, B_i32 a, B_i32 b) {\n    return toB_bool(a->val != b->val);\n}\n\nB_NoneType B_HashableD_i32D_hash(B_HashableD_i32 wit, B_i32 a, B_hasher h) {\n    zig_hash_wyhash_update(h->_hasher, to$bytesD_len((char *)&(a->val), 4));\n    return B_None;\n}\n"
  },
  {
    "path": "base/builtin/i32.h",
    "content": "struct B_i32 {\n    struct B_i32G_class *$class;\n    int val;\n};\n\n \nB_i32 toB_i32(int n);\nint fromB_i32(B_i32 n);\n\nB_i32 B_i32G_new(B_atom a, B_int base);\n\n#define i32_DIV(a,b)       ( {if (b==0) $RAISE((B_BaseException)$NEW(B_ZeroDivisionError,to$str(\"i32 truediv: division by zero\"))); (double)a/(double)b;} )\n#define i32_FLOORDIV(a,b)  ( {if (b==0) $RAISE((B_BaseException)$NEW(B_ZeroDivisionError,to$str(\"i32 floordiv: division by zero\")));  a/b;} )\n#define i32_MOD(a,b)       ( {if (b==0) $RAISE((B_BaseException)$NEW(B_ZeroDivisionError,to$str(\"i32 mod: division by zero\"))); a%b;} )\n\nint i32_pow(int a, int b);\n"
  },
  {
    "path": "base/builtin/i8.c",
    "content": "/*\n * Copyright (C) 2019-2021 Data Ductus AB\n *\n * Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:\n *\n * 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.\n *\n * 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.\n *\n * 3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission.\n *\n * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS \"AS IS\" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n */\n\n// Auxiliary //////////////////////////////////////////////////////////////////////////////\n\n// only called with e>=0.\nint8_t i8_pow(int8_t a, int8_t e) {\n    if (e == 0) return 1;\n    if (e == 1) return a;\n    if (e%2 == 0) return i8_pow(a*a,e/2);\n    return a * i8_pow(a*a,e/2);\n}\n\n// General methods ///////////////////////////////////////////////////////////////////////\n\nB_i8 B_i8G_new(B_atom a, B_int base) {\n    B_bigint b = B_bigintG_new(a, base);\n    unsigned long n = b->val.n[0];\n    long sz = b->val.size;\n    if (labs(sz) > 1 || (sz==1 && n > SCHAR_MAX) || sz == -1 && n > labs(SCHAR_MIN)) {\n        char errmsg[1024];\n        snprintf(errmsg, sizeof(errmsg), \"i8(): value %s out of range for type i8\",get_str(&b->val));\n        $RAISE((B_BaseException)$NEW(B_ValueError,to$str(errmsg)));\n    }\n    return toB_i8(n);\n}\n\nB_NoneType B_i8D___init__(B_i8 self, B_atom a, B_int base){\n    self->val = B_i8G_new(a,base)->val;\n    return B_None;\n}\n\nvoid B_i8D___serialize__(B_i8 n, $Serial$state state) {\n    $val_serialize(I8_ID,&n->val,state);\n}\n\nB_i8 B_i8D___deserialize__(B_i8 n, $Serial$state state) {\n    return toB_i8((int8_t)$val_deserialize(state));\n}\n\nB_bool B_i8D___bool__(B_i8 n) {\n    return toB_bool(n->val != 0);\n}\n\nB_str B_i8D___str__(B_i8 n) {\n    return $FORMAT(\"%d\", n->val);\n}\n\nB_str B_i8D___repr__(B_i8 n) {\n    return $FORMAT(\"%d\", n->val);\n}\n\nB_i8 toB_i8(int8_t i) {\n    B_i8 res = acton_malloc(sizeof(struct B_i8));\n    res->$class = &B_i8G_methods;\n    res->val = i;\n    return res;\n}\n\nint8_t fromB_i8(B_i8 w) {\n    return w->val;\n}\n\n                  \n\n// B_IntegralD_i8 /////////////////////////////////////////////////////////////////////////\n\n \nB_i8 B_IntegralD_i8D___add__(B_IntegralD_i8 wit,  B_i8 a, B_i8 b) {\n    return toB_i8(a->val + b->val);\n}  \n\nB_i8 B_IntegralD_i8D___zero__(B_IntegralD_i8 wit) {\n    return toB_i8(0);\n}\n\nB_complex B_IntegralD_i8D___complex__(B_IntegralD_i8 wit, B_i8 a) {\n    return toB_complex((double)a->val);\n}\n\nB_i8 B_IntegralD_i8D___fromatom__(B_IntegralD_i8 wit, B_atom a) {\n    return B_i8G_new(a,NULL);\n}\n\nB_i8 B_IntegralD_i8D___mul__(B_IntegralD_i8 wit,  B_i8 a, B_i8 b) {\n    return toB_i8(a->val * b->val);\n}  \n  \nB_i8 B_IntegralD_i8D___pow__(B_IntegralD_i8 wit,  B_i8 a, B_i8 b) {\n    if ( b->val < 0) {\n        // raise VALUEERROR;\n        return NULL;\n    }\n    return toB_i8(i8_pow(a->val,b->val));\n}\n\nB_i8 B_IntegralD_i8D___neg__(B_IntegralD_i8 wit,  B_i8 a) {\n    return toB_i8(-a->val);\n}\n\nB_i8 B_IntegralD_i8D___pos__(B_IntegralD_i8 wit,  B_i8 a) {\n    return a;\n}\n\n$WORD B_IntegralD_i8D_real(B_IntegralD_i8 wit, B_i8 a, B_Real wit2) {\n    return wit2->$class->__fromatom__(wit2,(B_atom)a);\n}\n\n$WORD B_IntegralD_i8D_imag(B_IntegralD_i8 wit, B_i8 a, B_Real wit2) {\n    return wit2->$class->__fromatom__(wit2,(B_atom)toB_i8(0L));\n}\n\n$WORD B_IntegralD_i8D___abs__(B_IntegralD_i8 wit, B_i8 a, B_Real wit2) {\n    return wit2->$class->__fromatom__(wit2,(B_atom)toB_i8(labs(a->val)));\n}\n\nB_i8 B_IntegralD_i8D_conjugate(B_IntegralD_i8 wit,  B_i8 a) {\n    return a;\n}\n\nB_float B_IntegralD_i8D___float__ (B_IntegralD_i8 wit, B_i8 n) {\n    return to$float((double)n->val);\n}\n\n$WORD B_IntegralD_i8D___trunc__ (B_IntegralD_i8 wit, B_i8 n, B_Integral wit2) {\n    return wit2->$class->__fromatom__(wit2,(B_atom)n);\n}\n  \n$WORD B_IntegralD_i8D___floor__ (B_IntegralD_i8 wit, B_i8 n, B_Integral wit2) {\n    return wit2->$class->__fromatom__(wit2,(B_atom)n);\n}\n  \n$WORD B_IntegralD_i8D___ceil__ (B_IntegralD_i8 wit, B_i8 n, B_Integral wit2) {\n    return wit2->$class->__fromatom__(wit2,(B_atom)n);\n}\n  \nB_i8 B_IntegralD_i8D___round__ (B_IntegralD_i8 wit, B_i8 n, B_int p) {\n    int8_t nval = n->val;\n    if (nval<0)\n        return toB_i8(-B_IntegralD_i8D___round__(wit,toB_i8(-nval),p)->val);\n    long pval = p==NULL ? 0 : fromB_int(p);\n    if (pval>=0)\n        return n;\n    int8_t p10 = i8_pow(10,-pval);\n    int8_t res = nval/p10;\n    if (nval%p10 * 2 > p10)\n        res++; \n    return toB_i8 (res * p10);\n}\n  \n$WORD B_IntegralD_i8D_numerator (B_IntegralD_i8 wit, B_i8 n, B_Integral wit2) {\n    return wit2->$class->__fromatom__(wit2,(B_atom)n);\n}\n  \n$WORD B_IntegralD_i8D_denominator (B_IntegralD_i8 wit, B_i8 n, B_Integral wit2) {\n    return wit2->$class->__fromatom__(wit2,(B_atom)toB_i8(1L));\n}\n  \nB_int B_IntegralD_i8D___int__ (B_IntegralD_i8 wit, B_i8 n) {\n    return B_intG_new((B_atom)n,NULL);\n}\n\nB_int B_IntegralD_i8D___index__(B_IntegralD_i8 wit, B_i8 n) {\n    return B_intG_new((B_atom)n,NULL);\n}\n\nB_tuple B_IntegralD_i8D___divmod__(B_IntegralD_i8 wit, B_i8 a, B_i8 b) {\n    if (b->val == 0)\n        $RAISE((B_BaseException)$NEW(B_ZeroDivisionError, to$str(\"division by zero\")));\n    int8_t n = a->val;\n    int8_t d = b->val;\n    return $NEWTUPLE(2, toB_i8(n/d), toB_i8(n%d));\n}\n\nB_i8 B_IntegralD_i8D___floordiv__(B_IntegralD_i8 wit, B_i8 a, B_i8 b) {\n    if (b->val == 0)\n        $RAISE((B_BaseException)$NEW(B_ZeroDivisionError, to$str(\"division by zero\")));\n    return toB_i8(a->val / b->val);\n}\n\nB_i8 B_IntegralD_i8D___mod__(B_IntegralD_i8 wit, B_i8 a, B_i8 b) {\n    return toB_i8(a->val % b->val);\n}\n\nB_i8 B_IntegralD_i8D___lshift__(B_IntegralD_i8 wit,  B_i8 a, B_int b) {\n    return toB_i8(a->val << fromB_int(b));\n}\n\nB_i8 B_IntegralD_i8D___rshift__(B_IntegralD_i8 wit,  B_i8 a, B_int b) {\n    return toB_i8(a->val >> fromB_int(b));\n}\n \nB_i8 B_IntegralD_i8D___invert__(B_IntegralD_i8 wit,  B_i8 a) {\n    return toB_i8(~a->val);\n}\n\n\n// B_LogicalD_IntegralD_i8  ////////////////////////////////////////////////////////////////////////////////////////\n\nB_i8 B_LogicalD_IntegralD_i8D___and__(B_LogicalD_IntegralD_i8 wit,  B_i8 a, B_i8 b) {\n    return toB_i8(a->val & b->val);\n}\n                                                 \nB_i8 B_LogicalD_IntegralD_i8D___or__(B_LogicalD_IntegralD_i8 wit,  B_i8 a, B_i8 b) {\n    return toB_i8(a->val | b->val);\n}\n                                                 \nB_i8 B_LogicalD_IntegralD_i8D___xor__(B_LogicalD_IntegralD_i8 wit,  B_i8 a, B_i8 b) {\n    return toB_i8(a->val ^ b->val);\n}  \n \n// B_MinusD_IntegralD_i8  ////////////////////////////////////////////////////////////////////////////////////////\n\n \nB_i8 B_MinusD_IntegralD_i8D___sub__(B_MinusD_IntegralD_i8 wit,  B_i8 a, B_i8 b) {\n    return toB_i8(a->val - b->val);\n}  \n\n// B_DivD_i8  ////////////////////////////////////////////////////////////////////////////////////////\n\n \nB_float B_DivD_i8D___truediv__ (B_DivD_i8 wit, B_i8 a, B_i8 b) {\n    if (b->val == 0)\n        $RAISE((B_BaseException)$NEW(B_ZeroDivisionError, to$str(\"division by zero\")));\n    return to$float((double)a->val/(double)b->val);\n}\n\n// B_OrdD_i8  ////////////////////////////////////////////////////////////////////////////////////////\n\nB_bool B_OrdD_i8D___eq__ (B_OrdD_i8 wit, B_i8 a, B_i8 b) {\n    return toB_bool(a->val == b->val);\n}\n\nB_bool B_OrdD_i8D___ne__ (B_OrdD_i8 wit, B_i8 a, B_i8 b) {\n    return toB_bool(a->val != b->val);\n}\n\nB_bool B_OrdD_i8D___lt__ (B_OrdD_i8 wit, B_i8 a, B_i8 b) {\n    return toB_bool(a->val < b->val);\n}\n\nB_bool B_OrdD_i8D___le__ (B_OrdD_i8 wit, B_i8 a, B_i8 b) {\n    return toB_bool(a->val <= b->val);\n}\n\nB_bool B_OrdD_i8D___gt__ (B_OrdD_i8 wit, B_i8 a, B_i8 b) {\n    return toB_bool(a->val > b->val);\n}\n\nB_bool B_OrdD_i8D___ge__ (B_OrdD_i8 wit, B_i8 a, B_i8 b) {\n    return toB_bool(a->val >= b->val);\n}\n\n// B_HashableD_i8 ///////////////////////////////////////////////////////////////////////////////////////////////////////\n\nB_bool B_HashableD_i8D___eq__(B_HashableD_i8 wit, B_i8 a, B_i8 b) {\n    return toB_bool(a->val == b->val);\n}\n\nB_bool B_HashableD_i8D___ne__(B_HashableD_i8 wit, B_i8 a, B_i8 b) {\n    return toB_bool(a->val != b->val);\n}\n\nB_NoneType B_HashableD_i8D_hash(B_HashableD_i8 wit, B_i8 a, B_hasher h) {\n    zig_hash_wyhash_update(h->_hasher, to$bytesD_len((char *)&(a->val),1));\n    return B_None;\n}\n"
  },
  {
    "path": "base/builtin/i8.h",
    "content": "struct B_i8 {\n    struct B_i8G_class *$class;\n    int8_t val;\n};\n\n \nB_i8 toB_i8(int8_t n);\nint8_t fromB_i8(B_i8 n);\n\nB_i8 B_i8G_new(B_atom a, B_int base);\n \n#define i8_DIV(a,b)       ( {if (b==0) $RAISE((B_BaseException)$NEW(B_ZeroDivisionError,to$str(\"i8 truediv: division by zero\"))); (double)a/(double)b;} )\n#define i8_FLOORDIV(a,b)  ( {if (b==0) $RAISE((B_BaseException)$NEW(B_ZeroDivisionError,to$str(\"i8 floordiv: division by zero\")));  a/b;} )\n#define i8_MOD(a,b)       ( {if (b==0) $RAISE((B_BaseException)$NEW(B_ZeroDivisionError,to$str(\"i8 mod: division by zero\"))); a%b;} )\n\nint8_t i8_pow(int8_t a, int8_t b);\n"
  },
  {
    "path": "base/builtin/int.c",
    "content": "/*\n * Copyright (C) 2019-2021 Data Ductus AB\n *\n * Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:\n *\n * 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.\n *\n * 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.\n *\n * 3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission.\n *\n * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS \"AS IS\" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n */\n\n// Auxiliary //////////////////////////////////////////////////////////////////////////////\n\n// only called with e>=0.\nlong int_pow(long a, long e) {\n    if (e == 0) return 1;\n    if (e == 1) return a;\n    if (e%2 == 0) return int_pow(a*a,e/2);\n    return a * int_pow(a*a,e/2);\n}\n\n// General methods ///////////////////////////////////////////////////////////////////////\n\nB_int B_intG_new(B_atom a, B_int base) {\n    B_bigint b = B_bigintG_new(a, base);\n    unsigned long n = b->val.n[0];\n    long sz = b->val.size;\n    if (labs(sz) > 1 || (sz==1 && n > 0x7ffffffffffffffful) || sz == -1 && n > 0x8000000000000000ul) {\n        char errmsg[1024];\n        snprintf(errmsg, sizeof(errmsg), \"int(): value %s out of range for type int\",get_str(&b->val));\n        $RAISE((B_BaseException)$NEW(B_ValueError,to$str(errmsg)));\n    }\n    return toB_int(n*sz);\n}\n \nB_NoneType B_intD___init__(B_int self, B_atom a, B_int base){\n    self->val = B_intG_new(a,base)->val;\n    return B_None;\n}\n\nvoid B_intD___serialize__(B_int n, $Serial$state state) {\n    $val_serialize(INT_ID,&n->val,state);\n}\n\nB_int B_intD___deserialize__(B_int n, $Serial$state state) {\n    return toB_int((long)$val_deserialize(state));\n}\n\nB_bool B_intD___bool__(B_int n) {\n    return toB_bool(n->val != 0);\n}\n\nB_str B_intD___str__(B_int n) {\n    return $FORMAT(\"%lld\", n->val);\n}\n\nB_str B_intD___repr__(B_int n) {\n    return $FORMAT(\"%lld\", n->val);\n}\n\nB_int toB_int(int64_t i) {\n    B_int res = acton_malloc(sizeof(struct B_int));\n    res->$class = &B_intG_methods;\n    res->val = i;\n    return res;\n}\n\nB_int to$int(int64_t n) {\n    return toB_int(n);\n}\n\nint64_t fromB_int(B_int w) {\n    return w->val;\n}\n\n                  \n\n// B_IntegralD_int /////////////////////////////////////////////////////////////////////////\n\n \nB_int B_IntegralD_intD___add__(B_IntegralD_int wit,  B_int a, B_int b) {\n    return toB_int(a->val + b->val);\n}\n\nB_int B_IntegralD_intD___zero__(B_IntegralD_int wit) {\n    return toB_int(0);\n}\n\nB_complex B_IntegralD_intD___complex__(B_IntegralD_int wit, B_int a) {\n    return toB_complex((double)a->val);\n}\n\nB_int B_IntegralD_intD___fromatom__(B_IntegralD_int wit, B_atom a) {\n    return B_intG_new(a,NULL);\n}\n\nB_int B_IntegralD_intD___mul__(B_IntegralD_int wit,  B_int a, B_int b) {\n    return toB_int(a->val * b->val);\n}  \n  \nB_int B_IntegralD_intD___pow__(B_IntegralD_int wit,  B_int a, B_int b) {\n    if ( b->val < 0) {\n        // raise VALUEERROR;\n        return NULL;\n    }\n    return toB_int(int_pow(a->val,b->val));\n}\n\nB_int B_IntegralD_intD___neg__(B_IntegralD_int wit,  B_int a) {\n    return toB_int(-a->val);\n}\n\nB_int B_IntegralD_intD___pos__(B_IntegralD_int wit,  B_int a) {\n    return a;\n}\n\n$WORD B_IntegralD_intD_real(B_IntegralD_int wit, B_int a, B_Real wit2) {\n    return wit2->$class->__fromatom__(wit2,(B_atom)a);\n}\n\n$WORD B_IntegralD_intD_imag(B_IntegralD_int wit, B_int a, B_Real wit2) {\n    return wit2->$class->__fromatom__(wit2,(B_atom)toB_int(0L));\n}\n\n$WORD B_IntegralD_intD___abs__(B_IntegralD_int wit, B_int a, B_Real wit2) {\n    return wit2->$class->__fromatom__(wit2,(B_atom)toB_int(labs(a->val)));\n}\n\nB_int B_IntegralD_intD_conjugate(B_IntegralD_int wit,  B_int a) {\n    return a;\n}\n\nB_float B_IntegralD_intD___float__ (B_IntegralD_int wit, B_int n) {\n    return to$float((double)n->val);\n}\n\n$WORD B_IntegralD_intD___trunc__ (B_IntegralD_int wit, B_int n, B_Integral wit2) {\n    return wit2->$class->__fromatom__(wit2,(B_atom)n);\n}\n  \n$WORD B_IntegralD_intD___floor__ (B_IntegralD_int wit, B_int n, B_Integral wit2) {\n    return wit2->$class->__fromatom__(wit2,(B_atom)n);\n}\n  \n$WORD B_IntegralD_intD___ceil__ (B_IntegralD_int wit, B_int n, B_Integral wit2) {\n    return wit2->$class->__fromatom__(wit2,(B_atom)n);\n}\n  \nB_int B_IntegralD_intD___round__ (B_IntegralD_int wit, B_int n, B_int p) {\n    long nval = n->val;\n    if (nval<0)\n        return toB_int(-B_IntegralD_intD___round__(wit,toB_int(-nval),p)->val);\n    long pval = p==NULL ? 0 : fromB_int(p);\n    if (pval>=0)\n        return n;\n    long p10 = int_pow(10,-pval);\n    long res = nval/p10;\n    if (nval%p10 * 2 > p10)\n        res++; \n    return toB_int (res * p10);\n}\n  \n$WORD B_IntegralD_intD_numerator (B_IntegralD_int wit, B_int n, B_Integral wit2) {\n    return wit2->$class->__fromatom__(wit2,(B_atom)n);\n}\n  \n$WORD B_IntegralD_intD_denominator (B_IntegralD_int wit, B_int n, B_Integral wit2) {\n    return wit2->$class->__fromatom__(wit2,(B_atom)toB_int(1L));\n}\n  \nB_int B_IntegralD_intD___int__ (B_IntegralD_int wit, B_int n) {\n    return B_intG_new((B_atom)n,NULL);\n}\n\nB_int B_IntegralD_intD___index__(B_IntegralD_int wit, B_int n) {\n    return B_intG_new((B_atom)n,NULL);\n}\n\nB_tuple B_IntegralD_intD___divmod__(B_IntegralD_int wit, B_int a, B_int b) {\n    long n = a->val;\n    long d = b->val;\n    return $NEWTUPLE(2, toB_int(n/d), toB_int(n%d));\n}\n\nB_int B_IntegralD_intD___floordiv__(B_IntegralD_int wit, B_int a, B_int b) {\n    if (b->val == 0)\n        $RAISE((B_BaseException)$NEW(B_ZeroDivisionError, to$str(\"division by zero\")));\n    return toB_int(a->val / b->val);\n}\n\nB_int B_IntegralD_intD___mod__(B_IntegralD_int wit, B_int a, B_int b) {\n    return toB_int(a->val % b->val);\n}\n\nB_int B_IntegralD_intD___lshift__(B_IntegralD_int wit,  B_int a, B_int b) {\n    return toB_int(a->val << fromB_int(b));\n}\n\nB_int B_IntegralD_intD___rshift__(B_IntegralD_int wit,  B_int a, B_int b) {\n    return toB_int(a->val >> fromB_int(b));\n}\n \nB_int B_IntegralD_intD___invert__(B_IntegralD_int wit,  B_int a) {\n    return toB_int(~a->val);\n}\n\n\n// B_LogicalD_IntegralD_int  ////////////////////////////////////////////////////////////////////////////////////////\n\nB_int B_LogicalD_IntegralD_intD___and__(B_LogicalD_IntegralD_int wit,  B_int a, B_int b) {\n    return toB_int(a->val & b->val);\n}\n                                                 \nB_int B_LogicalD_IntegralD_intD___or__(B_LogicalD_IntegralD_int wit,  B_int a, B_int b) {\n    return toB_int(a->val | b->val);\n}\n                                                 \nB_int B_LogicalD_IntegralD_intD___xor__(B_LogicalD_IntegralD_int wit,  B_int a, B_int b) {\n    return toB_int(a->val ^ b->val);\n}  \n \n// B_MinusD_IntegralD_int  ////////////////////////////////////////////////////////////////////////////////////////\n\n \nB_int B_MinusD_IntegralD_intD___sub__(B_MinusD_IntegralD_int wit,  B_int a, B_int b) {\n    return toB_int(a->val - b->val);\n}  \n\n// B_DivD_int  ////////////////////////////////////////////////////////////////////////////////////////\n\n \nB_float B_DivD_intD___truediv__ (B_DivD_int wit, B_int a, B_int b) {\n    if (b->val == 0)\n        $RAISE((B_BaseException)$NEW(B_ZeroDivisionError, to$str(\"division by zero\")));\n    return to$float((double)a->val/(double)b->val);\n}\n\n// B_OrdD_int  ////////////////////////////////////////////////////////////////////////////////////////\n\nB_bool B_OrdD_intD___eq__ (B_OrdD_int wit, B_int a, B_int b) {\n    return toB_bool(a->val == b->val);\n}\n\nB_bool B_OrdD_intD___ne__ (B_OrdD_int wit, B_int a, B_int b) {\n    return toB_bool(a->val != b->val);\n}\n\nB_bool B_OrdD_intD___lt__ (B_OrdD_int wit, B_int a, B_int b) {\n    return toB_bool(a->val < b->val);\n}\n\nB_bool B_OrdD_intD___le__ (B_OrdD_int wit, B_int a, B_int b) {\n    return toB_bool(a->val <= b->val);\n}\n\nB_bool B_OrdD_intD___gt__ (B_OrdD_int wit, B_int a, B_int b) {\n    return toB_bool(a->val > b->val);\n}\n\nB_bool B_OrdD_intD___ge__ (B_OrdD_int wit, B_int a, B_int b) {\n    return toB_bool(a->val >= b->val);\n}\n\n// B_HashableD_int ///////////////////////////////////////////////////////////////////////////////////////////////////////\n\nB_bool B_HashableD_intD___eq__(B_HashableD_int wit, B_int a, B_int b) {\n    return toB_bool(a->val == b->val);\n}\n\nB_bool B_HashableD_intD___ne__(B_HashableD_int wit, B_int a, B_int b) {\n    return toB_bool(a->val != b->val);\n}\n\nB_NoneType B_HashableD_intD_hash(B_HashableD_int wit, B_int a, B_hasher h) {\n    zig_hash_wyhash_update(h->_hasher,to$bytesD_len((char *)&(a->val),8));\n    return B_None;\n}\n"
  },
  {
    "path": "base/builtin/int.h",
    "content": "struct B_int {\n    struct B_intG_class *$class;\n    int64_t val;\n};\n\n \nB_int toB_int(int64_t n);\nB_int to$int(int64_t n);\nint64_t fromB_int(B_int n);\n\nB_int B_intG_new(B_atom a, B_int base);\n\n// only called with e>=0.\nlong int_pow(long a, long e); // used also for ndarrays\n\n#define int_DIV(a,b)       ( {if (b==0) $RAISE((B_BaseException)$NEW(B_ZeroDivisionError,to$str(\"int truediv: division by zero\"))); (double)a/(double)b;} )\n#define int_FLOORDIV(a,b)  ( {if (b==0) $RAISE((B_BaseException)$NEW(B_ZeroDivisionError,to$str(\"int floordiv: division by zero\")));  a/b;} )\n#define int_MOD(a,b)       ( {if (b==0) $RAISE((B_BaseException)$NEW(B_ZeroDivisionError,to$str(\"int mod: division by zero\"))); a%b;} )\n"
  },
  {
    "path": "base/builtin/list.c",
    "content": "/*\n * Copyright (C) 2019-2021 Data Ductus AB\n *\n * Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:\n *\n * 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.\n *\n * 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.\n *\n * 3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission.\n *\n * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS \"AS IS\" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n */\n\n// Auxiliary functions /////////////////////////////////////////////////////////////////////////////////////////////////////\n \n// For now, expansion doubles capacity. \nstatic void expand(B_list lst, int n) {\n    if (lst->capacity >= lst->length + n)\n        return;\n    int newcapacity = lst->capacity==0 ? 1 : lst->capacity;\n    while (newcapacity < lst->length+n)\n        newcapacity <<= 1;\n    $WORD* newptr = lst->data==NULL\n        ? acton_malloc(newcapacity*sizeof($WORD))\n        : acton_realloc(lst->data,newcapacity*sizeof($WORD));\n    if (newptr == NULL) {\n        $RAISE((B_BaseException)$NEW(B_MemoryError,to$str(\"memory allocation failed\")));\n    }\n    lst->data = newptr;\n    lst->capacity = newcapacity;\n}\n\nstatic void shrink(B_list lst) {\n    if (lst->capacity > 20 && 2*lst->length < lst->capacity) {\n        int newcapacity = lst->length;\n        $WORD old = lst->data;\n        lst->data = acton_malloc(newcapacity * sizeof($WORD));\n        lst->capacity = newcapacity;\n        assert(old != NULL);\n        memcpy(lst->data, old, newcapacity * sizeof($WORD));\n    }\n}\n            \n\nB_list B_listD_new(int capacity) {\n    if (capacity < 0) {\n        fprintf(stderr,\"Internal error list_new: negative capacity\");\n        exit(-1);\n    } \n    B_list lst = acton_malloc(sizeof(struct B_list));\n    if (lst == NULL) {\n        $RAISE((B_BaseException)$NEW(B_MemoryError,to$str(\"memory allocation failed\")));\n    }\n    if (capacity>0) {\n        lst->data = acton_malloc(capacity*sizeof($WORD));\n        if (lst->data == NULL) {\n            $RAISE((B_BaseException)$NEW(B_MemoryError,to$str(\"memory allocation failed\")));\n        }\n    } else {\n        lst->data = NULL;\n    }\n    lst->length = 0;\n    lst->capacity = capacity;\n    lst->$class = &B_listG_methods; \n    return lst;\n}\n\n// General methods ///////////////////////////////////////\n\nB_list B_listG_new(B_Iterable wit, $WORD iterable) {\n    return $NEW(B_list, wit, iterable);\n}\n\nB_NoneType B_listD___init__(B_list lst, B_Iterable wit, $WORD iterable) {\n    lst->length = 0;\n    lst->capacity = 0;\n    lst->data = NULL;\n    if (!iterable || !wit) {\n        return B_None;\n    }\n    $WORD w;\n    B_Iterator it = wit->$class->__iter__(wit,iterable);\n    B_SequenceD_list wit2 = B_SequenceD_listG_new();\n    while(1) {\n        if ($PUSH()) {\n            $WORD e = it->$class->__next__(it);\n            wit2->$class->append(wit2, lst, e);\n            $DROP();\n        } else {\n            B_BaseException ex = $POP();\n            if ($ISINSTANCE0(ex, B_StopIteration))\n                break;\n           else\n               $RAISE(ex);\n        }\n    }\n    return B_None;\n}\n  \nB_bool B_listD___bool__(B_list self) {\n    return toB_bool(self->length>0);\n}\n\nB_str B_listD___str__(B_list self) {\n    B_list s2 = B_listD_new(self->length);\n    B_SequenceD_list wit2 = B_SequenceD_listG_new();\n    for (int i=0; i< self->length; i++) {\n        B_value elem = (B_value)self->data[i];\n        if (elem == B_None) {\n            wit2->$class->append(wit2, s2, to$str(\"None\"));\n        } else {\n            wit2->$class->append(wit2, s2, elem->$class->__repr__(elem));\n        }\n    }\n    return B_strD_join_par('[',s2,']');\n}\n\nB_str B_listD___repr__(B_list self) {\n    return B_listD___str__(self);\n}\n\nvoid B_listD___serialize__(B_list self,$Serial$state state) {\n    B_int prevkey = (B_int)B_dictD_get(state->done,(B_Hashable)B_HashableD_WORDG_witness,self,NULL);\n    if (prevkey) {\n        long pk = fromB_int(prevkey);\n        $val_serialize(-LIST_ID,&pk,state);\n        return;\n    }\n    B_dictD_setitem(state->done,(B_Hashable)B_HashableD_WORDG_witness,self,toB_int(state->row_no));\n    long len = (long)self->length;\n    $val_serialize(LIST_ID,&len,state);\n    for (int i=0; i<self->length; i++) {\n        $step_serialize(self->data[i],state);\n    }\n}\n \nB_list B_listD___deserialize__(B_list res, $Serial$state state) {\n    $ROW this = state->row;\n    state->row = this->next;\n    state->row_no++;\n    if (this->class_id < 0) {\n        return (B_list)B_dictD_get(state->done,(B_Hashable)B_HashableD_intG_witness,toB_int((long)this->blob[0]),NULL);\n    } else {\n        if (!res)\n            res = B_listD_new((int)(long)this->blob[0]);\n        B_dictD_setitem(state->done,(B_Hashable)B_HashableD_intG_witness,toB_int(state->row_no-1),res);\n        res->length = res->capacity;\n        for (int i = 0; i < res->length; i++) \n            res->data[i] = $step_deserialize(state);\n        return res;\n    }\n}\n\nB_list B_listD_copy(B_list lst) {\n    int len = lst->length;\n    B_list res = B_listD_new(len);\n    res->length = len;\n    if (len > 0)\n        memcpy(res->data, lst->data, len*sizeof($WORD));\n    return res;\n}\n\nB_NoneType B_listD_clear(B_list lst) {\n    lst->data = NULL;\n    lst->capacity = 0;\n    lst->length = 0;\n    return B_None;\n}\n\nB_NoneType B_listD_extend(B_list lst, B_list other) {\n    if (other->length == 0)\n        return B_None;\n    expand(lst, other->length);\n    memcpy(lst->data + lst->length, other->data, other->length * sizeof($WORD));\n    lst->length += other->length;\n    return B_None;\n}\n\n$WORD B_listD_pop(B_list lst, B_int i) {\n    long ix;\n    int len =lst->length;\n    if (!i)\n        ix = len-1;\n    else\n        ix = fromB_int(i);\n    long ix0 = ix < 0 ? len + ix : ix;\n    if (ix0 < 0 || ix0 >= len) {\n        $RAISE((B_BaseException)$NEW(B_IndexError, toB_int(ix0), to$str(\"pop: index outside list\")));\n    }\n    $WORD res = lst->data[ix0];\n    memmove(lst->data + ix0,\n            lst->data + (ix0 + 1),\n            (len-(ix0+1))*sizeof($WORD));\n    lst->data[len-1] = NULL;\n    lst->length--;\n    shrink(lst);\n    return res;\n}\n\nB_int B_listD_index(B_list self, B_Eq W_EqD_B, $WORD val, B_int start, B_int stop) {\n    int strt = 0;\n    if (start)\n        strt = fromB_int(start);\n    if (strt < 0)\n        $RAISE((B_BaseException)$NEW(B_ValueError, to$str(\"start position must be >= 0\")));\n    if (strt > self->length)\n        $RAISE((B_BaseException)$NEW(B_ValueError, to$str(\"start position must not exceed list length\")));\n    int stp = self->length;\n    if (stop) {\n        stp = fromB_int(stop);\n        if (stp <= strt)\n            $RAISE((B_BaseException)$NEW(B_ValueError, to$str(\"stop position must be higher than start position\")));\n    }\n    if (stp > self->length)\n        stp = self->length;\n    for (int i=strt; i < stp; i++) {\n        B_value elem = (B_value)self->data[i];\n        B_bool eq = W_EqD_B->$class->__eq__(W_EqD_B, val, elem);\n        if (eq->val)\n            return toB_int(i);\n    }\n    $RAISE((B_BaseException)$NEW(B_KeyError, val, to$str(\"element is not in list\")));\n    return NULL; //to prevent compiler warning\n}\n\nB_int B_listD_count(B_list self, B_Eq W_EqD_B, $WORD val) {\n    int count = 0;\n    for (int i = 0; i < self->length; i++) {\n        B_value elem = (B_value)self->data[i];\n        B_bool eq = W_EqD_B->$class->__eq__(W_EqD_B, val, elem);\n        if (eq->val)\n            count++;\n    }\n    return to$int(count);\n}\n\n\n\n// B_OrdD_list ////////////////////////////////////////////////////////\n\nB_bool B_OrdD_listD___eq__ (B_OrdD_list w, B_list a, B_list b) {\n    if (a->length != b->length) return B_False;                                \n    B_Ord w2 = w->W_OrdD_AD_OrdD_list;\n    for (int i = 0; i<a->length; i++) {\n        if ((w2->$class->__ne__(w2,a->data[i],b->data[i]))->val) return B_False;\n    }\n    return B_True;\n}\n\nB_bool B_OrdD_listD___ne__ (B_OrdD_list w, B_list a, B_list b) {\n    return toB_bool(!(w->$class->__eq__(w,a,b)->val));\n}\n\nB_bool B_OrdD_listD___lt__ (B_OrdD_list w, B_list a, B_list b) {\n    int minl = a->length<b->length ? a->length : b->length;\n    B_Ord wA = w->W_OrdD_AD_OrdD_list;\n    int i=0;\n    while (i<minl && wA->$class->__eq__(wA,a->data[i],b->data[i])) i++;\n    if (i==a->length)\n        return toB_bool(i<b->length);\n    if (i==b->length)\n        return B_False;\n    return  wA->$class->__lt__(wA,a->data[i],b->data[i]);\n}\n\nB_bool B_OrdD_listD___le__ (B_OrdD_list w, B_list a, B_list b) {\n    int minl = a->length<b->length ? a->length : b->length;\n    B_Ord wA = w->W_OrdD_AD_OrdD_list;\n    int i=0;\n    while (i<minl && wA->$class->__eq__(wA,a->data[i],b->data[i])) i++;\n    if (i==a->length)\n        return toB_bool(i<=b->length);\n    if (i==b->length)\n        return B_False;\n    return  wA->$class->__lt__(wA,a->data[i],b->data[i]);\n}\n\nB_bool B_OrdD_listD___gt__ (B_OrdD_list w, B_list a, B_list b) {\n    return  B_OrdD_listD___lt__ (w,b,a);\n}\n\nB_bool B_OrdD_listD___ge__ (B_OrdD_list w, B_list a, B_list b) {\n    return  B_OrdD_listD___le__ (w,b,a);\n}\n\n\n//  B_TimesD_SequenceD_list /////////////////////////////////////////////////////////\n\n \nB_list B_TimesD_SequenceD_listD___add__ (B_TimesD_SequenceD_list wit, B_list lst, B_list other) {\n    int lstlen = lst->length;\n    int otherlen = other->length;\n    int reslen = lstlen + otherlen;\n    B_list res = B_listD_new(reslen);\n    if (lstlen > 0)\n        memcpy(res->data,lst->data,lstlen*sizeof($WORD));\n    if (otherlen > 0)\n        memcpy(res->data+lstlen,other->data,otherlen*sizeof($WORD));\n    res->length = reslen;\n    return res;\n}\n\nB_list B_TimesD_SequenceD_listD___zero__ (B_TimesD_SequenceD_list wit) {\n    return B_listD_new(0);\n}\n\nB_list B_TimesD_SequenceD_listD___mul__ (B_TimesD_SequenceD_list wit, B_list lst, B_int n) {\n    int lstlen = lst->length;\n    long n64 =  fromB_int(n);\n    if (lstlen == 0 || n64 <= 0)\n        return B_listD_new(0);\n    else {\n        B_list res = B_listD_new(lstlen * n64);\n        for (int i=0; i<n64; i++)\n            memcpy(res->data + i*lstlen, lst->data, lstlen * sizeof($WORD));\n        res->length = lstlen * n64;\n        return res;\n    }\n}\n\n//  B_CollectionD_SequenceD_list ///////////////////////////////////////////////////////\n\n// first define the Iterator instance ///\n\n\nstatic $WORD B_IteratorD_listD_next(B_IteratorD_list self) {\n    if (self->nxt >= self->src->length)\n        $RAISE ((B_BaseException)$NEW(B_StopIteration, to$str(\"list iterator terminated\")));\n    return self->src->data[self->nxt++];\n}\n\nB_IteratorD_list B_IteratorD_listG_new(B_list lst) {\n    return $NEW(B_IteratorD_list, lst);\n}\n\nvoid B_IteratorD_listD_init(B_IteratorD_list self, B_list lst) {\n    self->src = lst;\n    self->nxt = 0;\n}\n\nB_bool B_IteratorD_listD_bool(B_IteratorD_list self) {\n    return B_True;\n}\n\nB_str B_IteratorD_listD_str(B_IteratorD_list self) {\n    return $FORMAT(\"<list iterator object at %p>\", self);\n}\n\nvoid B_IteratorD_listD_serialize(B_IteratorD_list self,$Serial$state state) {\n    $step_serialize(self->src,state);\n    $step_serialize(toB_int(self->nxt),state);\n}\n\nB_IteratorD_list B_IteratorD_list$_deserialize(B_IteratorD_list res, $Serial$state state) {\n    if(!res)\n        res = $DNEW(B_IteratorD_list,state);\n    res->src = (B_list)$step_deserialize(state);\n    res->nxt = fromB_int((B_int)$step_deserialize(state));\n    return res;\n}\n\nstruct B_IteratorD_listG_class B_IteratorD_listG_methods = {\"B_IteratorD_list\",UNASSIGNED,($SuperG_class)&B_IteratorG_methods, B_IteratorD_listD_init,\n                                                      B_IteratorD_listD_serialize, B_IteratorD_list$_deserialize,B_IteratorD_listD_bool,B_IteratorD_listD_str,B_IteratorD_listD_str,B_IteratorD_listD_next};\n\n// Now, we can define the protocol methods\n\nB_Iterator B_CollectionD_SequenceD_listD___iter__(B_CollectionD_SequenceD_list wit, B_list lst) {\n    return (B_Iterator)$NEW(B_IteratorD_list,lst);\n}\n\nB_list B_CollectionD_SequenceD_listD___fromiter__ (B_CollectionD_SequenceD_list wit, B_Iterable wit2, $WORD iter) {\n    return B_listG_new(wit2, iter);\n    /*\n    B_list res = B_listD_new(4);\n    B_SequenceD_list wit3 = B_SequenceD_listG_new();\n    B_Iterator it = wit2->$class->__iter__(wit2,iter);\n    $WORD nxt;\n    while ((nxt = it->$class->__next__(it))) {\n        wit3->$class->append(wit3, res, nxt);\n    }\n    return res;\n    */\n}\n\nB_int B_CollectionD_SequenceD_listD___len__(B_CollectionD_SequenceD_list wit, B_list self) {\n    return toB_int(self->length);\n}\n\n//  B_SequenceD_list //////////////////////////////////////////////////////////////////\n \n$WORD $listD_U__getitem__(B_list lst, int64_t n) {\n    int len = lst->length;\n    int ix0 = n < 0 ? len + n : n;\n    if (ix0 < 0 || ix0 >= len) {\n        $RAISE((B_BaseException)$NEW(B_IndexError, toB_int(ix0), to$str(\"getitem: index outside list\")));\n    }\n    return lst->data[ix0];\n}\n\n$WORD B_SequenceD_listD___getitem__(B_SequenceD_list wit, B_list lst, B_int n) {\n    return  $listD_U__getitem__(lst, fromB_int(n));\n}\n\nB_NoneType listD_U__setitem__(B_list lst, int64_t n, $WORD val) {\n    int len = lst->length;\n    int ix0 = n < 0 ? len + n : n;\n    if (ix0 < 0 || ix0 >= len) {\n        $RAISE((B_BaseException)$NEW(B_IndexError, toB_int(ix0), to$str(\"setitem: index outside list\")));\n    }\n    lst->data[ix0] = val;\n    return B_None;\n}\n\nB_NoneType B_SequenceD_listD___setitem__(B_SequenceD_list wit, B_list lst, B_int n, $WORD val) {\n    return  listD_U__setitem__(lst, fromB_int(n), val);\n}\n\nB_NoneType B_SequenceD_listD___delitem__(B_SequenceD_list wit, B_list lst, B_int n) {\n    int len = lst->length;\n    int64_t ix = fromB_int(n);\n    int ix0 = ix < 0 ? len + ix : ix;\n    if(ix0 < 0 || ix0 >= len) {\n        return B_None;\n    }\n    memmove(lst->data + ix0,\n            lst->data + (ix0 + 1),\n            (len-(ix0+1))*sizeof($WORD));\n    lst->data[lst->length-1] = NULL;\n    lst->length--;\n    shrink(lst);\n    return B_None;\n}\n\nB_NoneType B_SequenceD_listD_append(B_SequenceD_list wit, B_list lst, $WORD elem);\n\n\nB_list B_SequenceD_listD___getslice__(B_SequenceD_list wit, B_list lst, B_slice slc) {\n    int len = lst->length;\n    int64_t start, stop, step, slen;\n    normalize_slice(slc, len, &slen, &start, &stop, &step);\n    // slice notation has been eliminated and default values applied.\n    // slen is now the length of the slice\n    B_list rlst = B_listD_new(slen);\n    int64_t t = start;\n    for (int i=0; i<slen; i++) {\n        B_SequenceD_listD_append(NULL, rlst, lst->data[t]);\n        t += step;\n    }\n    return rlst;\n}\n \nB_NoneType B_SequenceD_listD___setslice__(B_SequenceD_list wit, B_list lst, B_Iterable wit2, B_slice slc, $WORD iter) {\n    int len = lst->length;\n    B_list other = B_listD_new(0);    \n    B_SequenceD_list wit3 = B_SequenceD_listG_new();\n    B_Iterator it = wit2->$class->__iter__(wit2,iter);\n    while(1) {\n        if ($PUSH()) {\n            $WORD w = it->$class->__next__(it);\n            wit3->$class->append(wit3, other, w);\n            $DROP();\n        } else {\n            B_BaseException ex = $POP();\n            if ($ISINSTANCE0(ex, B_StopIteration))\n                break;\n           else\n               $RAISE(ex);\n        }\n    }\n    int olen = other->length; \n    int64_t start, stop, step, slen;\n    normalize_slice(slc, len, &slen, &start, &stop, &step);\n    if (step != 1 && olen != slen) {\n        $RAISE((B_BaseException)$NEW(B_ValueError,to$str(\"setslice: illegal slice\")));\n    }\n    int copy = olen <= slen ? olen : slen;\n    int t = start;\n    for (int i= 0; i<copy; i++) {\n        lst->data[t] = other->data[i];\n        t += step;\n    }\n    if (olen == slen)\n        return B_None;\n    // now we know that step=1\n    if (olen < slen) {\n        memmove(lst->data + start + copy,\n                lst->data + start + slen,\n                (len-(start+slen))*sizeof($WORD));\n        lst->length-=slen-olen;\n        return B_None;\n    } else {\n        expand(lst,olen-slen);\n        int rest = len - (start+copy);\n        int incr = olen - slen;\n        memmove(lst->data + start + copy + incr,\n                lst->data + start + copy,\n                rest*sizeof($WORD));\n        for (int i = copy; i < olen; i++)\n            lst->data[start+i] = other->data[i];\n        lst->length += incr;\n    }\n    return B_None;\n}\n\nB_NoneType B_SequenceD_listD___delslice__(B_SequenceD_list wit, B_list lst, B_slice slc) {\n    int len = lst->length;\n    int64_t start, stop, step, slen;\n    normalize_slice(slc, len, &slen, &start, &stop, &step);\n    if (slen==0) return B_None;\n    $WORD *p = lst->data + start;\n    for (int i=0; i<slen-1; i++) {\n        memmove(p,p+i+1,(step-1)*sizeof($WORD));\n        p+=step-1;\n    }\n    memmove(p,p+slen,(len-1-(start+step*(slen-1)))*sizeof($WORD));\n    lst->length-=slen;\n    return B_None;\n}  \n\nB_NoneType B_SequenceD_listD_reverse(B_SequenceD_list wit, B_list lst) {\n    int len = lst->length;\n    for (int i = 0; i < len/2; i++) {\n        $WORD tmp = lst->data[i];\n        lst->data[i] = lst->data[len-1-i];\n        lst->data[len-1-i] = tmp;\n    }\n    return B_None;\n}\n\nB_Iterator B_SequenceD_listD___reversed__(B_SequenceD_list wit, B_list lst) {\n    B_list copy = B_listD_copy(lst);\n    B_SequenceD_listD_reverse(wit, copy);\n    return B_CollectionD_SequenceD_listD___iter__((B_CollectionD_SequenceD_list)wit->W_Collection, copy);\n}\n\nB_NoneType B_SequenceD_listD_insert(B_SequenceD_list wit, B_list lst, B_int n, $WORD elem) {\n    int len = lst->length;\n    long ix = fromB_int(n);\n    expand(lst,1);\n    long ix0 = ix < 0 ? (len+ix < 0 ? 0 : len+ix) : (ix < len ? ix : len);\n    memmove(lst->data + (ix0 + 1),\n            lst->data + ix0 ,\n            (len - ix0) * sizeof($WORD));\n    lst->data[ix0] = elem;\n    lst->length++;\n    return B_None;\n}\n\nB_NoneType B_SequenceD_listD_append(B_SequenceD_list wit, B_list lst, $WORD elem) {\n    expand(lst,1);\n    lst->data[lst->length++] = elem;\n    return B_None;\n}\n\n\n// B_ContainerD_list ///////////////////////////////////////////////////////////////////\n\nB_bool B_ContainerD_listD___contains__(B_ContainerD_list wit, B_list lst, $WORD elem) {\n    long res = 0;\n    B_Eq w = wit->W_EqD_AD_ContainerD_list;\n    for (int i=0; i < lst->length; i++) {\n        if (fromB_bool(w->$class->__eq__(w,elem,lst->data[i]))) {\n            res = 1;\n            break;\n        }\n    }\n\n    return toB_bool(res);\n}\n                 \nB_bool B_ContainerD_listD___containsnot__(B_ContainerD_list wit, B_list lst, $WORD elem) {\n    return toB_bool(!B_ContainerD_listD___contains__(wit,lst,elem)->val);\n}\n\n// Witnesses used in code generation\n// The initialization code that registers method tables in a list indexed by classid uses list append;\n// so we need to initialize the below method table here, even if it is done in B___init__.\n\nstruct B_SequenceD_listG_class B_SequenceD_listG_methods = {\n    \"B_SequenceD_list\", \n    UNASSIGNED,\n    ($SuperG_class)&B_SequenceG_methods,\n    NULL, //B_SequenceD_listD___init__,\n    NULL, //B_SequenceD_listD___serialize__,\n    NULL, //B_SequenceD_listD___deserialize__,\n    (B_bool (*)(B_SequenceD_list))$default__bool__,\n    (B_str (*)(B_SequenceD_list))$default__str__,\n    (B_str (*)(B_SequenceD_list))$default__str__,\n    B_SequenceD_listD___getitem__,\n    B_SequenceD_listD___setitem__,\n    B_SequenceD_listD___delitem__,\n    B_SequenceD_listD___getslice__,\n    B_SequenceD_listD___setslice__,\n    B_SequenceD_listD___delslice__,\n    B_SequenceD_listD___reversed__,\n    B_SequenceD_listD_insert,\n    B_SequenceD_listD_append,\n    B_SequenceD_listD_reverse\n};\n\n/*\nstruct B_TimesD_SequenceD_list B_TimesD_SequenceD_list_instance;\nstruct B_SequenceD_list B_SequenceD_list_instance;\n\nstruct B_CollectionD_SequenceD_list B_CollectionD_SequenceD_list_instance = {\n    &B_CollectionD_SequenceD_listG_methods,\n    (B_Sequence)&B_SequenceD_list_instance\n};\n\nB_CollectionD_SequenceD_list B_CollectionD_SequenceD_listG_witness = &B_CollectionD_SequenceD_list_instance;\n\nstruct B_SequenceD_list B_SequenceD_list_instance = { \n    &B_SequenceD_listG_methods,\n    (B_Eq)&B_OrdD_intG_methods,\n    (B_Collection)&B_CollectionD_SequenceD_list_instance,\n    (B_Times)&B_TimesD_SequenceD_list_instance\n};\n\nB_SequenceD_list B_SequenceD_listG_witness = &B_SequenceD_list_instance;\n\nstruct B_TimesD_SequenceD_list B_TimesD_SequenceD_list_instance = {\n    &B_TimesD_SequenceD_listG_methods,\n    (B_Sequence)&B_SequenceD_list_instance\n};\nB_TimesD_SequenceD_list B_TimesD_SequenceD_listG_witness = &B_TimesD_SequenceD_list_instance;\n*/\n"
  },
  {
    "path": "base/builtin/list.h",
    "content": " \nstruct B_list {\n  struct B_listG_class *$class;\n  $WORD *data;\n  int length;\n  int capacity;\n};\n/*\nextern struct B_SequenceD_list *B_SequenceD_listG_witness;\nextern struct B_CollectionD_SequenceD_list *B_CollectionD_SequenceD_listG_witness;\n*/\n\n// Iterators over lists ///////////////////////////////////////////////////////\n\ntypedef struct B_IteratorD_list *B_IteratorD_list; ;\n\nstruct B_IteratorD_listG_class {\n  char *$GCINFO;\n  int $class_id;\n  $SuperG_class $superclass;\n  void (*__init__)(B_IteratorD_list, B_list);\n  void (*__serialize__)(B_IteratorD_list,$Serial$state);\n  B_IteratorD_list (*__deserialize__)(B_IteratorD_list,$Serial$state);\n  B_bool (*__bool__)(B_IteratorD_list);\n  B_str (*__str__)(B_IteratorD_list);\n  B_str (*__repr__)(B_IteratorD_list);\n  $WORD(*__next__)(B_IteratorD_list);\n};\n\nstruct B_IteratorD_list {\n  struct B_IteratorD_listG_class *$class;\n  B_list src;\n  int nxt;\n};\n\nextern struct  B_IteratorD_listG_class  B_IteratorD_listG_methods;\nB_IteratorD_list B_IteratorD_listG_new(B_list);\n\n//convenience functions used at various places.\nB_list B_listD_new(int capacity);\nB_list B_listD_copy(B_list lst);\n\n$WORD $listD_U__getitem__(B_list lst, int64_t n);\nB_NoneType listD_U__setitem__(B_list lst, int64_t n, $WORD val);\n"
  },
  {
    "path": "base/builtin/none.c",
    "content": "/*\n * Copyright (C) 2019-2021 Data Ductus AB\n *\n * Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:\n *\n * 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.\n *\n * 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.\n *\n * 3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission.\n *\n * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS \"AS IS\" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n */\n\nB_NoneType B_NoneTypeG_new() {\n  return $NEW(B_NoneType);\n}\n\n\nvoid B_NoneTypeD__serialize__(B_NoneType self, $Serial$state state) {\n  $add_header(NONE_ID,0,state);\n}\n\nB_NoneType B_NoneTypeD__deserialize__(B_NoneType self, $Serial$state state) {\n  state->row = state->row->next;\n  state->row_no++;\n  return NULL;\n}\n\nB_bool B_NoneTypeD__bool__(B_NoneType self) {\n  return B_False;\n}\n\nB_str B_NoneTypeD__str__(B_NoneType self) {\n  return to$str(\"None\");\n}\n\nstruct B_NoneTypeG_class B_NoneTypeG_methods = {\"B_NoneType\",UNASSIGNED,($SuperG_class)&B_valueG_methods,(void (*)(B_NoneType))$default__init__,\n                                            B_NoneTypeD__serialize__,  B_NoneTypeD__deserialize__, B_NoneTypeD__bool__, B_NoneTypeD__str__, B_NoneTypeD__str__};\n"
  },
  {
    "path": "base/builtin/none.h",
    "content": "struct B_NoneTypeG_class {\n    char *$GCINFO;\n    int $class_id;\n    $SuperG_class $superclass;\n    void (*__init__)(B_NoneType);\n    void (*__serialize__)(B_NoneType,$Serial$state);\n    B_NoneType (*__deserialize__)(B_NoneType,$Serial$state);\n    B_bool (*__bool__)(B_NoneType);\n    B_str (*__str__)(B_NoneType);\n    B_str (*__repr__)(B_NoneType);\n};\n\nstruct B_NoneType {\n    struct B_NoneTypeG_class *$class;\n};\n\nextern struct B_NoneTypeG_class B_NoneTypeG_methods;\nB_NoneType B_NoneTypeG_new();\n"
  },
  {
    "path": "base/builtin/range.c",
    "content": "/*\n * Copyright (C) 2019-2021 Data Ductus AB\n *\n * Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:\n *\n * 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.\n *\n * 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.\n *\n * 3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission.\n *\n * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS \"AS IS\" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n */\n\nB_range B_rangeG_new(B_int start, B_int stop, B_int step) {\n    return $NEW(B_range, start, stop, step);\n}\n\n\nB_NoneType B_rangeD___init__(B_range self, B_int start, B_int stop, B_int step) {\n    int64_t ustart, ustop, ustep, stp;\n    if (stop) {\n        ustart = start->val;\n        ustop = stop->val;\n    } else {\n        ustart = 0;\n        ustop = start->val;\n    }\n    if (step) {\n        stp = step->val;\n        if (stp == 0) {\n            $RAISE((B_BaseException)$NEW(B_ValueError, to$str(\"range() step size must not be zero\")));\n        } else {\n            ustep = stp;\n        }\n    } else {\n        ustep = 1;\n    }\n    stp = self->step = ustep;\n    int64_t r = ustop - ustart;\n    self->nxt = ustart - stp;\n    self->remaining = r/stp + (r%stp != 0);\n    return B_None;\n}\n\n/*\nB_bool B_rangeD___bool__(B_range self) {\n    return toB_bool ((self->step > 0 && self->stop > self->start) ||\n                    (self->start > self->stop));\n}\n\nB_str B_rangeD___str__(B_range self) {\n    return $FORMAT(\"range(%ld,%ld,%ld)\", self->start, self->stop, self->step);\n}\n\nB_str B_rangeD___repr__(B_range self) {\n    return $FORMAT(\"range(%ld,%ld,%ld)\", self->start, self->stop, self->step);\n}\n\nvoid B_rangeD___serialize__(B_range self, $Serial$state state) {\n    $ROW row = $add_header(RANGE_ID,3,state);\n    row->blob[0] = ($WORD)self->start;\n    row->blob[1] = ($WORD)self->stop;\n    row->blob[2] = ($WORD)self->step;\n}\n\nB_range B_rangeD___deserialize__(B_range self, $Serial$state state) {\n    $ROW this = state->row;\n    state->row = this->next;\n    state->row_no++;\n    B_range res = acton_malloc(sizeof(struct B_range));\n    res->$class = &B_rangeG_methods;\n    res->start = (int64_t)this->blob[0];\n    res->stop = (int64_t)this->blob[1];\n    res->step = (int64_t)this->blob[2];\n    return res;\n}\n*/\nint64_t rangeD_U__next__(B_range self) {\n    if (self->remaining-- <= 0)\n        $RAISE ((B_BaseException)$NEW(B_StopIteration, to$str(\"range iterator terminated\")));\n    return self->nxt += self->step;\n}\n\nB_int B_rangeD___next__(B_range self) {\n    return toB_int(rangeD_U__next__(self));\n}\n/*\nvoid B_IteratorD_rangeD_init(B_IteratorD_range self, B_range rng) {\n    int64_t stp = self->step = rng->step;\n    int64_t r = rng->stop - rng->start;\n    self->nxt = rng->start - stp;\n    self->remaining = r/stp + (r%stp != 0);\n    self->box = rng->box;\n}                                    \n*/\n\n\nB_bool B_rangeD___bool__(B_range self) {\n    return B_True;\n}\n\nB_str B_rangeD___repr__(B_range self) {\n    return $FORMAT(\"<range object at %p>\", self);\n}\n\nB_str B_rangeD___str__(B_range self) {\n    return $FORMAT(\"<range object at %p>\", self);\n}\n\nvoid B_rangeD___serialize__(B_range self, $Serial$state state) {\n    $step_serialize(toB_int(self->nxt),state);\n    $step_serialize(toB_int(self->step),state);\n    $step_serialize(toB_int(self->remaining),state);\n}\n\nB_range B_rangeD___deserialize__(B_range self, $Serial$state state) {\n    B_range res = $DNEW(B_range,state);\n    res->nxt = fromB_int((B_int)$step_deserialize(state));\n    res->step = fromB_int((B_int)$step_deserialize(state));\n    res->remaining = fromB_int((B_int)$step_deserialize(state));\n    return res;\n}\n/*\nstruct B_IteratorD_rangeG_class B_IteratorD_rangeG_methods = {\n    \"B_IteratorD_range\",\n    UNASSIGNED,\n    ($SuperG_class)&B_IteratorG_methods,\n    B_IteratorD_rangeD_init,\n    B_IteratorD_rangeD_serialize,\n    B_IteratorD_range$_deserialize,\n    B_IteratorD_rangeD_bool,\n    B_IteratorD_rangeD_str,\n    B_IteratorD_rangeD_str,\n    B_IteratorD_rangeD_next\n};\n\nB_Iterator B_IterableD_rangeD___iter__ (B_IterableD_range wit, B_range rng) {\n    return (B_Iterator)$NEW(B_IteratorD_range,rng);\n}\n*/\n"
  },
  {
    "path": "base/builtin/range.h",
    "content": "\nstruct B_range {\n    struct B_rangeG_class *$class;\n    int64_t nxt;\n    int64_t step;\n    int64_t remaining;\n};\n\nint64_t $rangeD_U__next__(B_range);\n"
  },
  {
    "path": "base/builtin/registration.c",
    "content": "/*\n * Copyright (C) 2019-2021 Data Ductus AB\n *\n * Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:\n *\n * 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.\n *\n * 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.\n *\n * 3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission.\n *\n * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS \"AS IS\" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n */\n\n// classid generation and retrieval ////////////////////////////////////////////////////////\n\n/* \n * Note that this does not attempt to be thread-safe. \n * We need to sort out how initialization is to be done.\n */\n\nB_list G_methods;  //key is classid; values are method tables\n\n\nvoid $register_force(int classid, $WORD meths) {\n  // we require that G_methods is big enough to index it at classid. See register_builtin below.\n  G_methods->data[classid] = meths;\n  (($SerializableG_class)meths)->$class_id = classid;\n}\n    \nvoid $register($WORD meths) {\n    B_SequenceD_list wit = B_SequenceD_listG_witness;    \n    wit->$class->append(wit,G_methods,meths);\n    (($SerializableG_class)meths)->$class_id = G_methods->length-1;\n    //printf(\"$register class %s at index %d\\n\", (($SerializableG_class)meths)->$GCINFO, G_methods->length-1);\n}\n\n\n/*\n * We do not register rts classid's here, since we want to be able to serialize without including all of rts.o with its  \n * special main and handling of $ROOT. Doing so would complicate testing of builtin types significantly.\n */\nvoid $register_builtin() {\n  G_methods = B_listD_new(2*PREASSIGNED); //preallocate space for PREASSIGNED user classes before doubling needed\n  memset(G_methods->data,0,PREASSIGNED*sizeof($WORD)); // initiate PREASSIGNED first slots to NULL;\n  G_methods->length = PREASSIGNED;\n  $register_force(NONE_ID,&B_NoneTypeG_methods);\n  // $register_force(ATOM_ID,&B_atomG_methods);\n  $register_force(INT_ID,&B_intG_methods);\n  $register_force(FLOAT_ID,&B_floatG_methods);\n  //  $register_force(COMPLEX_ID,&B_complexG_methods);\n  $register_force(BOOL_ID,&B_boolG_methods);\n  $register_force(STR_ID,&B_strG_methods);\n  $register_force(LIST_ID,&B_listG_methods);\n  $register_force(DICT_ID,&B_dictG_methods);\n  $register_force(SET_ID,&B_setG_methods);\n  $register_force(RANGE_ID,&B_rangeG_methods);\n  $register_force(TUPLE_ID,&B_tupleG_methods);\n  $register_force(BYTEARRAY_ID,&B_bytearrayG_methods);\n  $register_force(STRITERATOR_ID,&B_IteratorB_strG_methods);\n  $register_force(LISTITERATOR_ID,&B_IteratorD_listG_methods);\n  $register_force(DICTITERATOR_ID,&B_IteratorD_dictG_methods);\n  $register_force(VALUESITERATOR_ID,&B_IteratorD_dict_valuesG_methods);\n  $register_force(ITEMSITERATOR_ID,&B_IteratorD_dict_itemsG_methods);\n  $register_force(SETITERATOR_ID,&B_IteratorD_setG_methods);\n  // $register_force(RANGEITERATOR_ID,&B_IteratorD_rangeG_methods);\n  $register_force(ENUMERATEITERATOR_ID,&B_IteratorD_enumerateG_methods);\n  // $register_force(FILTERITERATOR_ID,&B_IteratorD_filterG_methods);\n  // $register_force(MAPITERATOR_ID,&B_IteratorD_mapG_methods);\n  $register_force(ZIPITERATOR_ID,&B_IteratorD_zipG_methods);\n  $register_force(BASEEXCEPTION_ID,&B_BaseExceptionG_methods);\n  $register_force(SYSTEMEXIT_ID,&B_SystemExitG_methods);\n  $register_force(KEYBOARDINTERRUPT_ID,&B_KeyboardInterruptG_methods);\n  $register_force(EXCEPTION_ID,&B_ExceptionG_methods);\n  $register_force(ASSERTIONERROR_ID,&B_AssertionErrorG_methods);\n  $register_force(LOOKUPERROR_ID,&B_LookupErrorG_methods);\n  $register_force(INDEXERROR_ID,&B_IndexErrorG_methods);\n  $register_force(KEYERROR_ID,&B_KeyErrorG_methods);\n  $register_force(MEMORYERROR_ID,&B_MemoryErrorG_methods);\n  $register_force(OSERROR_ID,&B_OSErrorG_methods);\n  $register_force(RUNTIMEERROR_ID,&B_RuntimeErrorG_methods);\n  $register_force(NOTIMPLEMENTEDERROR_ID,&B_NotImplementedErrorG_methods);\n  $register_force(VALUEERROR_ID,&B_ValueErrorG_methods);\n  //  $register_builtin_protocols();\n  $register_force(SEQ_ID,&$SEQG_methods);\n  $register_force(BRK_ID,&$BRKG_methods);\n  $register_force(CNT_ID,&$CNTG_methods);\n  $register_force(RET_ID,&$RETG_methods);\n  $register_force(I8_ID,&B_i8G_methods);\n  $register_force(I16_ID,&B_i16G_methods);\n  $register_force(I32_ID,&B_i32G_methods);\n  $register_force(I64_ID,&B_intG_methods);\n  $register_force(U1_ID,&B_u1G_methods);\n  $register_force(U8_ID,&B_u8G_methods);\n  $register_force(U16_ID,&B_u16G_methods);\n  $register_force(U32_ID,&B_u32G_methods);\n  $register_force(U64_ID,&B_u64G_methods);\n}\n\n\nB_bool issubtype(int sub_id, int ancestor_id) {\n  if (sub_id == ancestor_id)\n    return B_True;\n  $SuperG_class c =  ($SuperG_class)$GET_METHODS(sub_id)->$superclass;\n  while(c)\n    if(c->$class_id == ancestor_id)\n      return B_True;\n    else\n      c = c->$superclass;\n  return B_False;\n}\n"
  },
  {
    "path": "base/builtin/registration.h",
    "content": "/* \n * During initialization of an Acton program we need to establish a one-to-one mapping between method tables and non-negative integers. \n * The latter are called class id's and for each object being serialized, its class id is stored together with serialization of its\n * local state. During deserialization, the class id is used to find the object's method table and hence its __deserialize__ method.\n * Builtin classes and classes in the runtime system have predefined class id's, mainly to ease debugging (e.g. to make reading\n * hexdumps of serialized files slightly less painful).\n * \n * This mechanism requires that the mapping between method tables and integers is the same in the serializing and the \n * deserializing system. This will be the case if they do registration for the same classes in the same order, typically \n * by being the same piece of software.\n */\n\n#define UNASSIGNED -1\n#define NONE_ID 0\n#define ATOM_ID 1\n#define INT_ID 2\n#define FLOAT_ID 3\n#define COMPLEX_ID 4\n#define BOOL_ID 5\n#define STR_ID 6\n#define LIST_ID 7\n#define DICT_ID 8\n#define SET_ID 9\n#define RANGE_ID 10\n#define TUPLE_ID 11\n#define BYTEARRAY_ID 12\n#define ITEM_ID 13\n#define MSG_ID 14\n#define ACTOR_ID 15\n#define CATCHER_ID 16\n#define SLICE_ID 17   // Adding SLICE_ID by using a gap in the numbering...\n#define CONT_ID 18\n#define DONE_ID 19\n#define CONSTCONT_ID 20\n#define STRITERATOR_ID 21\n#define LISTITERATOR_ID 22\n#define DICTITERATOR_ID 23\n#define VALUESITERATOR_ID 24\n#define ITEMSITERATOR_ID 25\n#define SETITERATOR_ID 26\n#define RANGEITERATOR_ID 27\n#define ENUMERATEITERATOR_ID 28\n#define FILTERITERATOR_ID 29\n#define MAPITERATOR_ID 30\n#define ZIPITERATOR_ID 31\n\n#define BASEEXCEPTION_ID                        32\n#define     SYSTEMEXIT_ID                       33\n#define     KEYBOARDINTERRUPT_ID                34\n#define     EXCEPTION_ID                        35\n#define         ASSERTIONERROR_ID               36\n#define         LOOKUPERROR_ID                  37\n#define             INDEXERROR_ID               38\n#define             KEYERROR_ID                 39\n#define         MEMORYERROR_ID                  40\n#define         OSERROR_ID                      41\n#define         RUNTIMEERROR_ID                 42\n#define             NOTIMPLEMENTEDERROR_ID      43\n#define         VALUEERROR_ID                   44\n\n#define PROC_ID 45\n#define ACTION_ID 46\n#define MUT_ID 47\n#define PURE_ID 48\n\n#define SEQ_ID 49\n#define BRK_ID 50\n#define CNT_ID 51\n#define RET_ID 52\n\n#define I8_ID 53\n#define I16_ID 54\n#define I32_ID 55\n#define I64_ID 56\n#define U1_ID 57\n#define U8_ID 58\n#define U16_ID 59\n#define U32_ID 60\n#define U64_ID 61\n\n#define PREASSIGNED 62\n\n\n/* \n * Register the builtin classes (those with the above class id's except MSG_ID  -- CONSTCONT_ID). \n * This must be the first registration call, since it also initializes the data structures containing the mapping. \n * This call does *not* register the rts class id's MSG_ID  -- CONSTCONT_ID, which must be registered by \n * a call to register_rts in rts.h. \n */\n\nvoid $register_builtin();\n\n/* \n * Register a user defined class by supplying the address to its method table. A fresh class id is generated and \n * the internal mapping extended. Each class whose objects may be serialized must be registered.\n */\nvoid $register($WORD meths);\n\n/*\n * Registering a class with predetermined class id. To be used for builtin and rts classes only.\n * \n */\nvoid $register_force(int classid, $WORD meths);\n\n#define $GET_CLASSID(meths)  ((meths)->$class_id)\n\n#define $GET_METHODS(classid)  (($SerializableG_class)G_methods->data[classid])\n\n// list of method tables indexed by class_id. Only accessed via GET_METHODS above\n\nextern B_list G_methods;\n\nB_bool issubtype(int sub_id, int ancestor_id); \n"
  },
  {
    "path": "base/builtin/serialize.c",
    "content": "/*\n * Copyright (C) 2019-2021 Data Ductus AB\n *\n * Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:\n *\n * 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.\n *\n * 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.\n *\n * 3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission.\n *\n * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS \"AS IS\" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n */\n\n#define BUF_SIZE 8192\n\n// Queue implementation //////////////////////////////////////////////////////////////////\n\nvoid $enqueue($Serial$state state, $ROW elem) {\n    if (state->row)\n        state->row->next = elem;\n    else\n        state->fst = elem;\n    state->row = elem;\n}\nvoid $enqueue2(struct $ROWLISTHEADER *header, $ROW elem) {\n    if (header->last)\n        header->last->next = elem;\n    else\n        header->fst = elem;\n    header->last = elem;\n}\n \n// Hashable$WORD methods //////////////////////////////////////////////////\n\nvoid B_HashableD_WORDD___serialize__(B_HashableD_WORD self, $Serial$state state) {\n}\n\nB_HashableD_WORD B_HashableD_WORDD___deserialize__(B_HashableD_WORD self, $Serial$state state) {\n    B_HashableD_WORD res = $DNEW(B_HashableD_WORD,state);\n    return res;\n}\n\nB_bool B_HashableD_WORD_eq(B_HashableD_WORD wit, $WORD a, $WORD b) {\n    return toB_bool(a==b);\n}\n\nB_bool B_HashableD_WORD_ne(B_HashableD_WORD wit, $WORD a, $WORD b) {\n    return  toB_bool(a != b);\n}\n\nB_NoneType B_HashableD_WORD_hash(B_HashableD_WORD wit, $WORD a, B_hasher h) {\n    zig_hash_wyhash_update(h->_hasher, to$bytesD_len((char *)&a, 8));\n    return B_None;\n}\n\nstruct B_HashableD_WORDG_class B_HashableD_WORDG_methods = {\n    \"B_HashableD_WORD\",\n    UNASSIGNED,\n    ($SuperG_class)&B_HashableG_methods,\n    (void (*)(B_HashableD_WORD))$default__init__,\n    B_HashableD_WORDD___serialize__,\n    B_HashableD_WORDD___deserialize__,\n    (B_bool (*)(B_HashableD_WORD))$default__bool__,\n    (B_str (*)(B_HashableD_WORD))$default__str__,\n    (B_str (*)(B_HashableD_WORD))$default__str__,\n    B_HashableD_WORD_eq,\n    B_HashableD_WORD_ne,\n    B_HashableD_WORD_hash\n};\nstruct B_HashableD_WORD B_HashableD_WORD_instance = {&B_HashableD_WORDG_methods};\nstruct B_HashableD_WORD *B_HashableD_WORDG_witness = &B_HashableD_WORD_instance;\n\n\n// small-step functions for (de)serializing the next object /////////////////////////////////////////////////\n\n$ROW $add_header(int class_id, int blob_size, $Serial$state state) {\n    $ROW res = acton_malloc(2 * sizeof(int) + (1+blob_size)*sizeof($WORD));\n    res->class_id = class_id;\n    state->row_no++;\n    res->blob_size = blob_size;\n    res->next = NULL;\n    $enqueue(state,res);\n    return res;\n}\n\nvoid $step_serialize($WORD self, $Serial$state state) {\n    if (self) {\n        int class_id = $GET_CLASSID((($Serializable)self)->$class);\n        if (class_id > ITEM_ID) { // not one of the Acton builtin datatypes, which have hand-crafted serializations\n            if (state->globmap) {\n                long key = (long)state->globmap(self);\n                if (key < 0) {\n                    $val_serialize(-class_id,&key,state);\n                    return;\n                }\n            }\n            B_int prevkey = (B_int)B_dictD_get(state->done,(B_Hashable)B_HashableD_WORDG_witness,self,NULL);\n            if (prevkey) {\n                $val_serialize(-class_id,&prevkey->val,state);\n            } else {\n                B_dictD_setitem(state->done,(B_Hashable)B_HashableD_WORDG_witness,self,toB_int(state->row_no));\n                $add_header(class_id,0,state);\n                (($Serializable)self)->$class->__serialize__(self,state);\n            }\n        } else \n            (($Serializable)self)->$class->__serialize__(self,state);\n    } else\n        $add_header(NONE_ID,0,state);\n}\n\n$WORD $step_deserialize($Serial$state state) {\n    if (abs(state->row->class_id) > ITEM_ID) {\n        $ROW this = state->row;\n        state->row = this->next;\n        state->row_no++;\n        if (this->class_id < 0) {\n            long key = (long)this->blob[0];\n            if (key < 0)\n                return state->globmap(($WORD)key);\n            else\n                return B_dictD_get(state->done,(B_Hashable)B_HashableD_intG_witness,toB_int(key),NULL);\n        } else\n            return $GET_METHODS(this->class_id)->__deserialize__(NULL, state);\n    } else\n        return $GET_METHODS(abs(state->row->class_id))->__deserialize__(NULL, state);\n}\n\n\n\nvoid $val_serialize(int class_id, $WORD val,$Serial$state state) {\n    $ROW row = $add_header(class_id,1,state);\n    memcpy(row->blob,val,sizeof($WORD));\n}\n\n$WORD $val_deserialize($Serial$state state) {\n    $WORD res;\n    memcpy(&res,(state->row)->blob,sizeof($WORD));\n    state->row = state->row->next;\n    state->row_no++;\n    return res;\n}\n\n// Serialization methods ///////////////////////////////////////////////////////////////////////////////\n\nvoid $write_serialized($ROW row, char *file) {\n    char buf[BUF_SIZE];\n    char *p = buf;\n    char *bufend = buf + BUF_SIZE;\n    FILE *fileptr = fopen(file,\"wb\");\n    int chunk_size;\n    char *start;\n    while(row) {\n        chunk_size = 2*sizeof(int);\n        start = (char*)row;\n        if (p+chunk_size > bufend) {\n            int fits = bufend - p;\n            memcpy(p,start,fits);\n            fwrite(buf,1,sizeof(buf),fileptr); // TODO:  handle file write error\n            p = buf;\n            chunk_size -= fits;\n            start += fits;\n        }\n        memcpy(p,start,chunk_size);\n        p+=chunk_size;\n    \n        chunk_size = (row->blob_size)*sizeof($WORD);\n        start =  (char*)row->blob;\n        while (p+chunk_size > bufend) {\n            int fits = bufend - p;\n            memcpy(p,start,fits);\n            fwrite(buf,1,sizeof(buf),fileptr); // TODO:  handle file write error\n            p = buf;\n            chunk_size -= fits;\n            start += fits;\n        }\n        memcpy(p,start,chunk_size);\n        p+=chunk_size;\n    \n        row = row->next;\n    }\n    fwrite(buf,1,p-buf,fileptr); // TODO:  handle file write error\n    fclose(fileptr);\n}\n \n$ROW $serialize($Serializable s, $WORD (*globmap)($WORD)) {\n    $Serial$state state = acton_malloc(sizeof(struct $Serial$state));\n    state->done = $NEW(B_dict,(B_Hashable)B_HashableD_WORDG_witness,NULL,NULL);\n    state->globmap = globmap;\n    state->row_no=0;\n    state->row = NULL;\n    state->fst = NULL;\n    $step_serialize(s,state);\n    return state->fst;\n}\n\n$ROW $glob_serialize($Serializable self, $WORD (*globmap)($WORD)) {\n    $Serial$state state = acton_malloc(sizeof(struct $Serial$state));\n    state->done = $NEW(B_dict,(B_Hashable)B_HashableD_WORDG_witness,NULL,NULL);\n    state->globmap = globmap;\n    state->row_no=0;\n    state->row = NULL;\n    state->fst = NULL;\n    $add_header(self->$class->$class_id,0,state);\n    self->$class->__serialize__(self,state);\n    return state->fst;\n}\n\nvoid $serialize_file($Serializable s, char *file) {\n    $write_serialized($serialize(s,NULL),file);\n}\n\n$Serializable $deserialize($ROW row, $WORD (*globmap)($WORD)) {\n    $Serial$state state = acton_malloc(sizeof(struct $Serial$state));\n    state->done = $NEW(B_dict,(B_Hashable)B_HashableD_intG_witness,NULL,NULL);\n    state->globmap = globmap;\n    state->row_no=0;\n    state->row = row;\n    state->fst = NULL;\n    return $step_deserialize(state);\n}\n\n$Serializable $glob_deserialize($Serializable self, $ROW row, $WORD (*globmap)($WORD)) {\n    $Serial$state state = acton_malloc(sizeof(struct $Serial$state));\n    state->done = $NEW(B_dict,(B_Hashable)B_HashableD_intG_witness,NULL,NULL);\n    state->globmap = globmap;\n    state->row_no=1;\n    state->row = row->next;\n    state->fst = NULL;\n    return self->$class->__deserialize__(self,state);\n}\n\n$ROW $read_serialized(char *file) {\n    char buf[BUF_SIZE];\n    char *p = buf;\n    char *bufend;\n    FILE *fileptr = fopen(file,\"rb\");\n    int chunk_size;\n    char *start;\n    struct $ROWLISTHEADER header;\n    header.fst = NULL;\n    header.last = NULL;\n    bufend = buf + fread(buf,1,sizeof(buf),fileptr);\n    while(p < bufend || !feof(fileptr)) {\n        int init[2];//4\n        chunk_size = 2*sizeof(int); \n        start = (char*)init;\n        if (p + chunk_size > bufend) {\n            int fits = bufend - p;\n            memcpy(start,p,fits);\n            bufend = buf + fread(buf,1,sizeof(buf),fileptr); // TODO:  handle file write error\n            p = buf;\n            chunk_size -= fits;\n            start += fits;\n        }\n        memcpy(start,p,chunk_size);\n        p+=chunk_size;\n        $ROW row = acton_malloc(2*sizeof(int) + (init[1]+1) * sizeof($WORD));\n        memcpy(row,init,2*sizeof(int));//4\n        row->next = NULL;\n        chunk_size =  (init[1]) * sizeof($WORD);\n        start = (char*)row->blob;\n        while (p + chunk_size > bufend) {\n            int fits = bufend - p;\n            memcpy(start,p,fits);\n            bufend = buf + fread(buf,1,sizeof(buf),fileptr); // TODO:  handle file write error\n            p = buf;\n            chunk_size -= fits;\n            start += fits;\n        }\n        memcpy(start,p,chunk_size);\n        p+=chunk_size;\n        $enqueue2(&header,row);\n    }\n    return header.fst;\n}\n       \n$Serializable $deserialize_file(char *file) {\n    return $deserialize($read_serialized(file), NULL);\n}\n"
  },
  {
    "path": "base/builtin/serialize.h",
    "content": "\n\n// Types for serialization ////////////////////////////////////////////////////////////////////////////\n\n\n// The serialization of an Acton object/value is a linked list of $ROW:s.\n\n\ntypedef struct $ROW *$ROW;\n\nstruct $ROW {\n    $ROW next;\n    int class_id;\n    int blob_size;\n    $WORD blob[];\n};\n\nstruct $ROWLISTHEADER {\n    $ROW fst;\n    $ROW last;\n};\n\n//typedef struct $Serial$state *$Serial$state;\n\nstruct $Serial$state {\n    char *$GCINFO;\n    B_dict done;\n    $WORD (*globmap)($WORD);\n    long row_no;\n    $ROW row;\n    $ROW fst; //not used in deserialization\n};\n\n// small-step helpers for defining serializations //////////////////////////////////////////////////\n\nvoid $step_serialize($WORD self, $Serial$state state);\n$WORD $step_deserialize($Serial$state state);\n\nvoid $val_serialize(int class_id, $WORD val, $Serial$state state);\n$WORD $val_deserialize($Serial$state state);\n\n$ROW $add_header(int class_id, int blob_size, $Serial$state state);\n\n// top-level functions for serialization of an object ////////////////////////////////////////////////\n\nlong $total_rowsize($ROW);\n\n$ROW $serialize($Serializable s, $WORD (*globmap)($WORD));\n$ROW $glob_serialize($Serializable s, $WORD (*globmap)($WORD));\nvoid $write_serialized($ROW row, char *file);\n// $serialize_file just calls the above two functions\nvoid $serialize_file($Serializable s, char *file);\n\n$Serializable $deserialize($ROW row, $WORD (*globmap)($WORD));\n$Serializable $glob_deserialize($Serializable s, $ROW row, $WORD (*globmap)($WORD));\n$ROW $read_serialized(char *file);\n// $deserialize_file just calls the above two functions\n$Serializable $deserialize_file(char *file);\n\n// B_HashableD_WORD (for pointers) ////////////////////////////////////////////////////////////////////////\n\n// B_HashableD_WORDG_witness is needed to create the MappingB_dict witness necessary for serialization.\n\ntypedef struct B_HashableD_WORD *B_HashableD_WORD;\n\nstruct B_HashableD_WORDG_class {\n    char *$GCINFO;\n    int $class_id;\n    $SuperG_class superclass;\n    void (*__init__)(B_HashableD_WORD);\n    void (*__serialize__)(B_HashableD_WORD,$Serial$state);\n    B_HashableD_WORD (*__deserialize__)(B_HashableD_WORD,$Serial$state);\n    B_bool (*__bool__)(B_HashableD_WORD);\n    B_str (*__str__)(B_HashableD_WORD);\n    B_str (*__repr__)(B_HashableD_WORD);\n    B_bool (*__eq__)(B_HashableD_WORD, $WORD, $WORD);\n    B_bool (*__ne__)(B_HashableD_WORD, $WORD, $WORD);\n    B_NoneType (* hash)(B_HashableD_WORD, $WORD, B_hasher);\n};\n\nstruct B_HashableD_WORD {\n    struct B_HashableD_WORDG_class *$class;\n};\n\nextern struct B_HashableD_WORDG_class B_HashableD_WORDG_methods;\nB_HashableD_WORD B_HashableD_WORDG_new();\nextern struct B_HashableD_WORD *B_HashableD_WORDG_witness;\n"
  },
  {
    "path": "base/builtin/set.c",
    "content": "/*\n * Copyright (C) 2019-2021 Data Ductus AB\n *\n * Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:\n *\n * 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.\n *\n * 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.\n *\n * 3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission.\n *\n * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS \"AS IS\" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n */\n\n \n#define DISCARD_NOTFOUND 0\n#define DISCARD_FOUND 1\n#define PERTURB_SHIFT 5\n#define MIN_SIZE 8\n\nstatic $WORD _dummy;\n#define dummy (&_dummy)\n\n\n// Auxiliary functions ///////////////////////////////////////////////////////////////////////////////\n\nstatic void B_set_insert_clean(B_setentry *table, long mask, $WORD *key, long hash) {\n    B_setentry *entry;\n    long perturb = hash;\n    long i = hash & mask;\n    long j;\n\n    while (1) {\n        entry = &table[i];\n        if (entry->key == NULL)\n            goto found_null;\n        \n        perturb >>= PERTURB_SHIFT;\n        i = (i * 5 + 1 + perturb) & mask;\n    }\n found_null:\n    entry->key = key;\n    entry->hash = hash;\n}\n\nstatic int B_set_table_resize(B_set so, int minsize) {\n    B_setentry *oldtable, *newtable, *entry;\n    long oldmask = so->mask;\n    long newmask;\n\n    /* Find the smallest table size > minsize. */\n    long newsize = MIN_SIZE;\n    while (newsize <= (long)minsize) {\n        newsize <<= 1; // The largest possible value is PY_SSIZE_T_MAX + 1.\n    }\n    /* Get space for a new table. */\n    oldtable = so->table;\n\n    newtable = acton_malloc(sizeof(B_setentry) * newsize);\n    if (newtable == NULL) {\n        return -1;\n    }\n\n    /* Make the B_set empty, using the new table. */\n    memset(newtable, 0, sizeof(B_setentry) * newsize);\n    so->mask = newsize - 1;\n    so->table = newtable;\n\n    /* Copy the data over; \n       dummy entries aren't copied over, of course */\n    newmask = (long)so->mask;\n    if (so->fill == so->numelements) {\n        for (entry = oldtable; entry <= oldtable + oldmask; entry++) {\n            if (entry->key != NULL) {\n                B_set_insert_clean(newtable, newmask, entry->key, entry->hash);\n            }\n        }\n    } else {\n        so->fill = so->numelements;\n        for (entry = oldtable; entry <= oldtable + oldmask; entry++) {\n            if (entry->key != NULL && entry->key != dummy) {\n                B_set_insert_clean(newtable, newmask, entry->key, entry->hash);\n            }\n        }\n    }\n\n    acton_free(oldtable);\n    return 0;\n}\n\nstatic B_setentry *B_set_lookkey(B_set set, B_Hashable hashwit, $WORD key, long hash) {\n    B_setentry *entry;\n    long perturb;\n    long mask = set->mask;\n    long i = hash & mask;\n\n    entry = &set->table[i];\n    if (entry->key == NULL)\n        return entry;\n\n    perturb = hash;\n\n    while (1) {\n        if (entry->hash == hash) {\n            $WORD *startkey = entry->key;\n            // startkey cannot be a dummy because the dummy hash field is -1 \n            // assert(startkey != dummy);\n            if (startkey == key || hashwit->$class->__eq__(hashwit,startkey,key)) \n                return entry;\n        }\n        perturb >>= PERTURB_SHIFT;\n        i = (i * 5 + 1 + perturb) & mask;\n\n        entry = &set->table[i];\n        if (entry->key == NULL)\n            return entry;\n    }\n}\n\nstatic int B_set_contains_entry(B_set set,  B_Hashable hashwit, $WORD elem, long hash) {\n    return B_set_lookkey(set, hashwit, elem, hash)->key != NULL;\n}\n\nvoid B_set_add_entry(B_set set, B_Hashable hashwit, $WORD key, long hash) {\n    B_setentry *freeslot;\n    B_setentry *entry;\n    long perturb;\n    long mask;\n    long i;  \n    mask = set->mask;\n    i = hash & mask;\n\n    entry = &set->table[i];\n    if (entry->key == NULL)\n        goto found_unused;\n\n    freeslot = NULL;\n    perturb = hash;\n\n    while (1) {\n        if (entry->hash == hash) {\n            $WORD startkey = entry->key;\n            // startkey cannot be a dummy because the dummy hash field is -1 \n            if (startkey == key || hashwit->$class->__eq__(hashwit,startkey,key))\n                goto found_active;\n        }\n        else if (entry->hash == -1)\n            freeslot = entry;\n\n        perturb >>= PERTURB_SHIFT;\n        i = (i * 5 + 1 + perturb) & mask;\n\n        entry = &set->table[i];\n        if (entry->key == NULL)\n            goto found_unused_or_dummy;\n    }\n\n found_unused_or_dummy:\n    if (freeslot == NULL)\n        goto found_unused;\n    set->numelements++;\n    freeslot->key = key;\n    freeslot->hash = hash;\n    return;\n\n found_unused:\n    set->fill++;\n    set->numelements++;\n    entry->key = key;\n    entry->hash = hash;\n    if ((size_t)set->fill*5 < mask*3)\n        return;\n    B_set_table_resize(set, set->numelements>50000 ? set->numelements*2 : set->numelements*4);\n    return;\n\n found_active:\n    return;\n}\n\n\nB_set B_set_copy(B_set set, B_Hashable hashwit) {\n    B_set res = acton_malloc(sizeof(struct B_set));\n    memcpy(res,set,sizeof(struct B_set));\n    res->table = acton_malloc((set->mask+1)*sizeof(B_setentry));\n    memcpy(res->table,set->table,(set->mask+1)*sizeof(B_setentry));\n    return res;\n}\n\nstatic int B_set_discard_entry(B_set set, B_Hashable hashwit, $WORD elem, long hash) {\n    B_setentry *entry = B_set_lookkey(set,hashwit,elem, hash);\n    if (entry->key != NULL) {\n        entry->key = dummy;\n        entry->hash = -1;\n        set->numelements--;\n        return DISCARD_FOUND;\n    } else\n        return DISCARD_NOTFOUND;\n}\n\n// General methods ///////////////////////////////////////////////////////////////////////////////////\n\nB_set B_setG_new(B_Hashable hashwit, B_Iterable wit, $WORD iterable) {\n    return $NEW(B_set, hashwit, wit, iterable);\n}\n\nB_NoneType B_setD___init__(B_set set, B_Hashable hashwit, B_Iterable wit, $WORD iterable) {\n    set->numelements = 0;\n    set->fill = 0;\n    set->mask = MIN_SIZE-1;\n    set->finger = 0;\n    set->table = acton_malloc(MIN_SIZE*sizeof(B_setentry));\n    memset(set->table,0,MIN_SIZE*sizeof(B_setentry));\n    if (wit && iterable) {\n        B_Iterator it = wit->$class->__iter__(wit,iterable);\n        while(1) {\n            if ($PUSH()) {\n                $WORD nxt = it->$class->__next__(it);\n                B_set_add_entry(set,hashwit,nxt,fromB_u64(B_hash(hashwit, nxt)));\n                $DROP();\n            } else {\n                B_BaseException ex = $POP();\n                if ($ISINSTANCE0(ex, B_StopIteration))\n                    break;\n                else\n                    $RAISE(ex);\n            }\n        }\n    }\n    return B_None;\n}\n\nB_bool B_setD___bool__(B_set self) {\n    return toB_bool(self->numelements>0);\n}\n\nB_str B_setD___str__(B_set self) {\n    B_list s2 = B_listD_new(self->numelements);\n    B_SequenceD_list wit = B_SequenceD_listG_witness;\n    B_IteratorD_set iter = $NEW(B_IteratorD_set,self);\n    B_value elem;\n    for (int i=0; i<self->numelements; i++) {\n        elem = (B_value)iter->$class->__next__(iter);\n        wit->$class->append(wit,s2,elem->$class->__repr__(elem));\n    }\n    return B_strD_join_par('{',s2,'}');\n}\n\nB_str B_setD___repr__(B_set self) {\n    return B_setD___str__(self);\n}\n\nvoid B_setD___serialize__(B_set self, $Serial$state state) {\n    B_int prevkey = (B_int)B_dictD_get(state->done,(B_Hashable)B_HashableD_WORDG_witness,self,NULL);\n    if (prevkey) {\n        long pk = fromB_int(prevkey);\n        $val_serialize(-SET_ID,&pk,state);\n        return;\n    }\n    B_dictD_setitem(state->done,(B_Hashable)B_HashableD_WORDG_witness,self,toB_int(state->row_no));\n    $ROW row = $add_header(SET_ID,4,state);\n    row->blob[0] = ($WORD)self->numelements;\n    row->blob[1] = ($WORD)self->fill;\n    row->blob[2] = ($WORD)self->mask;\n    row->blob[3] = ($WORD)self->finger;\n    for (long i=0; i<=self->mask; i++) {\n        B_setentry *entry = &self->table[i];\n        $step_serialize(toB_int(entry->hash),state);\n        $step_serialize(entry->key,state);\n    }\n}\n \nB_set B_setD___deserialize__ (B_set res, $Serial$state state) {\n    $ROW this = state->row;\n    state->row = this->next;\n    state->row_no++;\n    if (this->class_id < 0) {\n        return B_dictD_get(state->done,(B_Hashable)B_HashableD_intG_witness,toB_int((long)this->blob[0]),NULL);\n    } else {\n        if (!res)\n            res = acton_malloc(sizeof(struct B_set));\n        B_dictD_setitem(state->done,(B_Hashable)B_HashableD_intG_witness,toB_int(state->row_no-1),res);\n        res->$class = &B_setG_methods;\n        res->numelements = (long)this->blob[0];\n        res->fill = (long)this->blob[1];\n        res->mask = (long)this->blob[2];\n        res->finger = (long)this->blob[3];\n        res->table = acton_malloc((res->mask+1)*sizeof(B_setentry));\n        memset(res->table,0,(res->mask+1)*sizeof(B_setentry));\n        for (int i=0; i<=res->mask;i++) {\n            B_setentry *entry = &res->table[i];\n            entry->hash = fromB_int((B_int)$step_deserialize(state));\n            entry->key = $step_deserialize(state);\n            if (entry->hash==-1)\n                entry->key = dummy;\n        }\n        return res;\n    }\n}\n\n\n// B_Set\n\n// Iterable ///////////////////////////////////////////////////////////////////////////////////////  Leif \n\nstatic $WORD B_IteratorD_set_next_entry(B_IteratorD_set self) {\n    B_setentry *table = self->src->table;\n    long n = self->src->mask;\n    long i = self->nxt;\n    while (i <= n) {\n        B_setentry *entry = &table[i];\n        if (entry->key != NULL && entry->key != dummy) {\n            self->nxt = i+1;\n            return entry;\n        }\n        i++;\n    }\n    $RAISE ((B_BaseException)$NEW(B_StopIteration, to$str(\"set iterator terminated\")));\n    return NULL; //to avoid compiler warning\n}\n\nstatic B_Iterator B_set_iter_entry(B_set set) {\n    B_IteratorD_set iter =  acton_malloc(sizeof(struct B_IteratorD_set));\n    struct B_IteratorD_setG_class *methods = acton_malloc(sizeof(struct B_IteratorD_setG_class));\n    iter->$class = methods;\n    methods->__next__ =  B_IteratorD_set_next_entry;\n    iter->src = set;\n    iter->nxt = 0;\n    return (B_Iterator)iter;\n}\n                                            \nstatic $WORD B_IteratorD_set_next(B_IteratorD_set self) {\n    $WORD res;\n    if((res = B_IteratorD_set_next_entry(self))) {\n        return ((B_setentry*)res)->key;\n    } \n    return NULL;\n}\n\nB_IteratorD_set B_IteratorD_setG_new(B_set s) {\n    return $NEW(B_IteratorD_set, s);\n}\n\nvoid B_IteratorD_set_init(B_IteratorD_set self, B_set set) {\n    self->src = set;\n    self->nxt = 0;\n}\n\nB_bool B_IteratorD_set_bool(B_IteratorD_set self) {\n    return B_True;\n}\n\nB_str B_IteratorD_set_str(B_IteratorD_set self) {\n    return $FORMAT(\"<set keys iterator object at %p>\", self);\n}\n\nvoid B_IteratorD_set_serialize(B_IteratorD_set self, $Serial$state state) {\n    $step_serialize(self->src,state);\n    $step_serialize(toB_int(self->nxt),state);\n}\n\nB_IteratorD_set B_IteratorD_setD__deserialize(B_IteratorD_set res, $Serial$state state) {\n    if (!res)\n        res = $DNEW(B_IteratorD_set,state);\n    res->src = (B_set)$step_deserialize(state);\n    res->nxt = fromB_int((B_int)$step_deserialize(state));\n    return res;\n}\n\nstruct B_IteratorD_setG_class B_IteratorD_setG_methods = {\"B_IteratorD_set\",UNASSIGNED,($SuperG_class)&B_IteratorG_methods, B_IteratorD_set_init,\n                                                    B_IteratorD_set_serialize, B_IteratorD_setD__deserialize,B_IteratorD_set_bool,B_IteratorD_set_str,B_IteratorD_set_str, B_IteratorD_set_next};\n\n\nB_Iterator B_SetD_setD___iter__ (B_SetD_set wit, B_set set) {\n    return (B_Iterator)$NEW(B_IteratorD_set,set);\n}\n\nB_NoneType B_SetD_setD_add (B_SetD_set wit, B_set set, $WORD elem) {\n    B_Hashable hashwit = wit->W_HashableD_AD_SetD_set;\n    B_set_add_entry(set,hashwit,elem,fromB_u64(B_hash(hashwit, elem)));\n    return B_None;\n}\n\nB_set B_SetD_setD___fromiter__(B_SetD_set wit, B_Iterable wit2, $WORD iter) {\n    return B_setG_new(wit->W_HashableD_AD_SetD_set, wit2, iter);\n    /*\n    B_Iterator it = wit2->$class->__iter__(wit2,iter);\n    B_set res = $NEW(B_set,hashwit,NULL,NULL);\n    res->numelements = 0;\n    res->fill = 0;\n    res->mask = MIN_SIZE-1;\n    res->finger = 0;\n    res->table = acton_malloc(MIN_SIZE*sizeof(B_setentry));\n    memset(res->table,0,MIN_SIZE*sizeof(B_setentry));\n    $WORD nxt;\n    while((nxt = it->$class->__next__(it))) {\n        B_set_add_entry(res,hashwit,nxt,fromB_u64(B_hash(hashwit, nxt)));\n    }\n    return res;\n    */\n}\n\nB_int B_SetD_setD___len__ (B_SetD_set wit, B_set set) {\n    return toB_int(set->numelements);\n}\n\nB_bool B_SetD_setD___contains__ (B_SetD_set wit, B_set set, $WORD val) {\n    B_Hashable hashwit = wit->W_HashableD_AD_SetD_set;\n    return toB_bool(B_set_contains_entry(set,hashwit,val,fromB_u64(B_hash(hashwit, val))));\n}\n\nB_bool B_SetD_setD___containsnot__ (B_SetD_set wit, B_set set, $WORD v) {\n    return  toB_bool(!B_SetD_setD___contains__(wit,set,v)->val);\n}\n\nB_bool B_SetD_setD_isdisjoint (B_SetD_set wit, B_set set, B_set other) {\n    B_Hashable hashwit = wit->W_HashableD_AD_SetD_set;\n    if (set == other) \n        return toB_bool(set->numelements == 0);\n    if (other->numelements > set->numelements)\n        return B_SetD_setD_isdisjoint(wit,other,set);\n    B_Iterator iter = B_set_iter_entry(other);\n    $WORD w;\n    long res = 1;\n    while((w = $next(iter))){\n        if(B_set_contains_entry(set, hashwit,((B_setentry*)w)->key, ((B_setentry*)w)->hash)) {\n            res = 0;\n            break;\n        }\n    }\n    return toB_bool(res);\n}\n\n// TODO: ideally this could be defined in .act file instead of C since we just\n// need to call the .add() method, but that doesn't currently seem to work\nB_NoneType B_SetD_setD_update (B_SetD_set wit, B_set set, B_Iterable otherwit, $WORD other) {\n    B_Hashable hashwit = wit->W_HashableD_AD_SetD_set;\n    if (set == other)\n        return B_None;\n    B_Iterator it = otherwit->$class->__iter__(otherwit, other);\n    while(1) {\n        if ($PUSH()) {\n            $WORD e = it->$class->__next__(it);\n            B_set_add_entry(set, hashwit, e, fromB_u64(B_hash(hashwit, e)));\n            $DROP();\n        } else {\n            B_BaseException ex = $POP();\n            if ($ISINSTANCE0(ex, B_StopIteration))\n                break;\n           else\n               $RAISE(ex);\n        }\n    }\n    return B_None;\n}\n\nB_NoneType B_SetD_setD_discard (B_SetD_set wit, B_set set, $WORD elem) {\n    B_Hashable hashwit = wit->W_HashableD_AD_SetD_set;\n    B_set_discard_entry(set,hashwit,elem,fromB_u64(B_hash(hashwit, elem)));\n    return B_None;\n}\n\n$WORD B_SetD_setD_pop (B_SetD_set wit, B_set set) {\n    if (set->numelements == 0)\n        $RAISE((B_BaseException)$NEW(B_ValueError, to$str(\"pop from an empty set\")));\n\n    $WORD res;\n    // Make sure the search finger is in bounds \n    B_setentry *entry = set->table + (set->finger & set->mask);\n    B_setentry *limit = set->table + set->mask;\n\n    while (entry->key == NULL || entry->key==dummy) {\n        entry++;\n        if (entry > limit)\n            entry = set->table;\n    }\n    res = entry->key;\n    entry->key = dummy;\n    entry->hash = -1;\n    set->numelements--;\n    set->finger = entry - set->table + 1;   // next place to start \n    return res;\n}\n\n\n// B_Ord\n\nB_bool B_OrdD_SetD_setD___eq__ (B_OrdD_SetD_set wit, B_set set, B_set other) {\n    B_Hashable hashwit = ((B_SetD_set)wit->W_Set)->W_HashableD_AD_SetD_set;\n    if (set == other) \n        return B_True;\n    if (set->numelements != other->numelements)\n        return B_False;\n    B_Iterator iter = B_set_iter_entry(other);\n    long n = 0;\n    while(n < set->numelements) {\n        $WORD w = $next(iter);\n        if(!B_set_contains_entry(set, hashwit, ((B_setentry*)w)->key, ((B_setentry*)w)->hash))\n            return B_False;\n        n++;\n    }\n    return B_True;\n}\n  \nB_bool B_OrdD_SetD_setD___ne__ (B_OrdD_SetD_set wit, B_set set, B_set other) {\n    return toB_bool(!B_OrdD_SetD_setD___eq__ (wit,set,other)->val);\n}\n  \nB_bool B_OrdD_SetD_setD___gt__ (B_OrdD_SetD_set wit, B_set set, B_set other) {\n    B_Hashable hashwit = ((B_SetD_set)wit->W_Set)->W_HashableD_AD_SetD_set;\n    if (set == other) \n        return B_False;    \n    if (set->numelements <= other->numelements)\n        return B_False;\n    B_Iterator iter = B_set_iter_entry(other);\n    long n = 0;\n    while(n < other->numelements) {\n        $WORD w = $next(iter);\n        if(!B_set_contains_entry(set, hashwit, ((B_setentry*)w)->key, ((B_setentry*)w)->hash))\n            return B_False;\n        n++;\n    }\n    return B_True;\n}\n  \nB_bool B_OrdD_SetD_setD___ge__ (B_OrdD_SetD_set wit, B_set set, B_set other) {\n    B_Hashable hashwit = ((B_SetD_set)wit->W_Set)->W_HashableD_AD_SetD_set;\n    if (set == other) \n        return B_False;    \n    if (set->numelements < other->numelements)\n        return B_False;\n    B_Iterator iter = B_set_iter_entry(other);\n    long n = 0;\n    while(n < other->numelements) {\n        $WORD w = $next(iter);\n        if(!B_set_contains_entry(set, hashwit, ((B_setentry*)w)->key, ((B_setentry*)w)->hash))\n            return B_False;\n        n++;\n    }\n    return B_True;\n}\n\nB_bool B_OrdD_SetD_setD___lt__ (B_OrdD_SetD_set wit, B_set set, B_set other) {\n    return B_OrdD_SetD_setD___gt__(wit, other, set);\n}\n  \nB_bool B_OrdD_SetD_setD___le__ (B_OrdD_SetD_set wit, B_set set, B_set other) {\n    return  B_OrdD_SetD_setD___ge__(wit, other, set);\n}\n  \n// B_Minus\n\n \nB_set B_MinusD_SetD_setD___sub__ (B_MinusD_SetD_set wit, B_set set, B_set other) {\n    B_Hashable hashwit = ((B_SetD_set)wit->W_Set)->W_HashableD_AD_SetD_set;\n    B_set res = B_set_copy(set,hashwit);\n    B_Iterator iter = B_set_iter_entry(other);\n    long n = 0;\n    while(n < other->numelements) {\n        $WORD w = $next(iter);\n        $WORD key = ((B_setentry*)w)->key;\n        long hash = ((B_setentry*)w)->hash;\n        B_set_discard_entry(res,hashwit,key,hash);\n        n++;\n    }\n    return res;\n}\n\n// B_Logical\n\n \nB_set B_LogicalD_SetD_setD___and__(B_LogicalD_SetD_set wit, B_set set, B_set other) {\n    B_Hashable hashwit = ((B_SetD_set)wit->W_Set)->W_HashableD_AD_SetD_set;\n    if (other->numelements > set->numelements)\n        return  B_LogicalD_SetD_setD___and__(wit,other,set);\n    B_set res = $NEW(B_set,hashwit,NULL,NULL);\n    B_Iterator iter = B_set_iter_entry(set);\n    long n = 0;\n    while(n < set->numelements) {\n        $WORD w = $next(iter);\n        $WORD key = ((B_setentry*)w)->key;\n        long hash = ((B_setentry*)w)->hash;\n        if (B_set_contains_entry(other,hashwit,key,hash))\n            B_set_add_entry(res,hashwit,key,hash);\n        n++;\n    }\n    return res;\n}\n\nB_set B_LogicalD_SetD_setD___or__ (B_LogicalD_SetD_set wit, B_set set, B_set other) {\n    B_Hashable hashwit = ((B_SetD_set)wit->W_Set)->W_HashableD_AD_SetD_set;\n    if (other->numelements > set->numelements)\n        return B_LogicalD_SetD_setD___or__ (wit,other,set);\n    B_set res = B_set_copy(set, hashwit);\n    B_Iterator iter = B_set_iter_entry(other);\n    long n = 0;\n    while(n < other->numelements) {\n        $WORD w = $next(iter);\n        $WORD key = ((B_setentry*)w)->key;\n        long hash = ((B_setentry*)w)->hash;\n        B_set_add_entry(res,hashwit,key,hash);\n        n++;\n    }\n    return res;\n}\n\nB_set B_LogicalD_SetD_setD___xor__(B_LogicalD_SetD_set wit, B_set set, B_set other) {\n    B_Hashable hashwit = ((B_SetD_set)wit->W_Set)->W_HashableD_AD_SetD_set;\n    B_set res = B_set_copy(set, hashwit);\n    B_Iterator iter = B_set_iter_entry(other);\n    long n = 0;\n    while(n < other->numelements) {\n        $WORD w = $next(iter);\n        $WORD key = ((B_setentry*)w)->key;\n        long hash = ((B_setentry*)w)->hash;\n        if(!B_set_discard_entry(res,hashwit,key,hash))\n            B_set_add_entry(res,hashwit,key,hash);\n        n++;\n    }\n    return res;\n}\n\n#undef dummy\n"
  },
  {
    "path": "base/builtin/set.h",
    "content": "\ntypedef struct {\n    $WORD key;\n    long hash;    \n} B_setentry;\n\nstruct B_set {\n    struct B_setG_class *$class;\n    long numelements;    // nr of elements in B_set\n    long fill;           // numelements + #dummy entries\n    long mask;\n    long finger;                       // Search finger for pop() \n    B_setentry *table;                  // the hashtable\n};\n\n\n// Iterators over sets ///////////////////////////////////////////////////////\n\ntypedef struct B_IteratorD_set *B_IteratorD_set; ;\n\nstruct B_IteratorD_setG_class {\n    char *$GCINFO;\n    int $class_id;\n    $SuperG_class $superclass;\n    void (*__init__)(B_IteratorD_set, B_set);\n    void (*__serialize__)(B_IteratorD_set, $Serial$state);\n    B_IteratorD_set (*__deserialize__)(B_IteratorD_set, $Serial$state);\n    B_bool (*__bool__)(B_IteratorD_set);\n    B_str (*__str__)(B_IteratorD_set);\n    B_str (*__repr__)(B_IteratorD_set);\n    $WORD(*__next__)(B_IteratorD_set);\n};\n\nstruct B_IteratorD_set {\n    struct B_IteratorD_setG_class *$class;\n    B_set src;\n    int nxt;\n};\n\nextern struct  B_IteratorD_setG_class  B_IteratorD_setG_methods;\nB_IteratorD_set B_IteratorD_setG_new(B_set);\n\nvoid B_set_add_entry(B_set set, B_Hashable hashwit, $WORD key, long hash);\n"
  },
  {
    "path": "base/builtin/slice.c",
    "content": "/*\n * Copyright (C) 2019-2021 Data Ductus AB\n *\n * Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:\n *\n * 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.\n *\n * 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.\n *\n * 3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission.\n *\n * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS \"AS IS\" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n */\n\n\n/* Normalize slice notation, so that\n   - if step == 0, VALUEERROR is raised\n\n   - Otherwise, \n   - on input, len must be the # of elements in the sequence being sliced\n   - on output \n      - 0 <= *start <= len is the starting position\n      - 0 <= *stop <= len is the ending position (*non-inclusive*!)\n      - *step is the step size (which may be negative)\n      - *slen is the # of elements in the slice. \n*/\n\nvoid normalize_slice(B_slice slc, int64_t len, int64_t *slen, int64_t *start, int64_t *stop, int64_t *step) {\n    if (slc->step == NULL)\n        *step = 1;\n    else\n        *step = *slc->step;\n    if (*step == 0) {\n        $RAISE((B_BaseException)$NEW(B_ValueError,to$str(\"step size 0 in slice\")));\n    }\n    if (slc->start == NULL)\n        *start = *step > 0 ? 0 : len-1;\n    else {\n        *start = *slc->start;\n        *start = *start >=0 ? (*start < len  ? *start : len-1 + (*step > 0))\n            : (*start > -len ? len+*start : 0);\n    }\n    if (slc->stop == NULL)\n        *stop = *step > 0 ? len : -1;\n    else {\n        *stop = *slc->stop;\n        *stop = *stop >= 0 ? (*stop < len  ? *stop : len-1 + (*step > 0)) \n            : (*stop > -len ? len+*stop : 0);\n    }\n  \n    if ((*step > 0 && *start >= *stop) || (*step < 0 && *start <= *stop))\n        *slen = 0;\n    else\n        *slen = (*stop-*start)/ *step + ((*stop-*start)%*step != 0);\n}\n\nB_slice B_sliceG_new(B_int start, B_int stop, B_int step) {\n    return $NEW(B_slice,start,stop,step);\n}\n\nB_NoneType B_sliceD___init__(B_slice s, B_int start, B_int stop, B_int step) {\n    if (start) {\n        s->start = acton_malloc(sizeof(int64_t));\n        *s->start = fromB_int(start);\n    } else\n        s->start = NULL;\n    if (stop) {\n        s->stop = acton_malloc(sizeof(int64_t));\n        *s->stop = fromB_int(stop);\n    } else\n        s->stop = NULL;\n    if (step) {\n        s->step = acton_malloc(sizeof(int64_t));\n        *s->step = fromB_int(step);\n    } else\n        s->step = NULL;\n    return B_None;\n}\n\nvoid B_sliceD___serialize__ (B_slice self, $Serial$state state) {\n    $ROW row = $add_header(SLICE_ID,3,state);\n    row->blob[0] = ($WORD)*self->start;\n    row->blob[1] = ($WORD)*self->stop;\n    row->blob[2] = ($WORD)*self->step;\n}\nB_slice B_sliceD___deserialize__ (B_slice self, $Serial$state state) {\n    $ROW this = state->row;\n    state->row = this->next;\n    state->row_no++;\n    B_slice res = acton_malloc(sizeof(struct B_slice));\n    res->$class = &B_sliceG_methods;\n    res->start = acton_malloc(sizeof(long));\n    res->stop = acton_malloc(sizeof(long));\n    res->step = acton_malloc(sizeof(long));\n    *res->start = (long)this->blob[0];\n    *res->stop = (long)this->blob[1];\n    *res->step = (long)this->blob[2];\n    return res;\n}\n\nB_bool B_sliceD___bool__(B_slice s) {\n    return B_True;\n}\n\nB_str B_sliceD___str__(B_slice s) {\n    return $FORMAT(\"Slice [%ld:%ld:%ld]\", *s->start, *s->stop, *s->step);\n}\n\nB_str B_sliceD___repr__(B_slice s) {\n    return B_sliceD___str__(s);\n}\n"
  },
  {
    "path": "base/builtin/slice.h",
    "content": "\nstruct B_slice {\n  struct B_sliceG_class *$class;\n  int64_t *start;\n  int64_t *stop;\n  int64_t *step;\n};\n\nvoid normalize_slice(B_slice slc, int64_t len, int64_t *slen, int64_t *start, int64_t *stop, int64_t *step);\n"
  },
  {
    "path": "base/builtin/staticWitnesses.c",
    "content": "struct B_HashableD_bytes B_HashableD_bytesG_instance;\nstruct B_TimesD_bytes B_TimesD_bytesG_instance;\nstruct B_ContainerD_bytes B_ContainerD_bytesG_instance;\nstruct B_SliceableD_bytes B_SliceableD_bytesG_instance;\nstruct B_OrdD_bytes B_OrdD_bytesG_instance;\nstruct B_ContainerD_bytearray B_ContainerD_bytearrayG_instance;\nstruct B_TimesD_SequenceD_bytearray B_TimesD_SequenceD_bytearrayG_instance;\nstruct B_CollectionD_SequenceD_bytearray B_CollectionD_SequenceD_bytearrayG_instance;\nstruct B_SequenceD_bytearray B_SequenceD_bytearrayG_instance;\nstruct B_OrdD_bytearray B_OrdD_bytearrayG_instance;\nstruct B_HashableD_str B_HashableD_strG_instance;\nstruct B_TimesD_str B_TimesD_strG_instance;\nstruct B_SliceableD_str B_SliceableD_strG_instance;\nstruct B_ContainerD_str B_ContainerD_strG_instance;\nstruct B_OrdD_str B_OrdD_strG_instance;\n// struct B_IterableD_range B_IterableD_rangeG_instance;\nstruct B_IterableD_Iterator B_IterableD_IteratorG_instance;\nstruct B_SetD_set B_SetD_setG_instance;\nstruct B_OrdD_dict B_OrdD_dictG_instance;\nstruct B_MappingD_dict B_MappingD_dictG_instance;\nstruct B_OrdD_list B_OrdD_listG_instance;\nstruct B_ContainerD_list B_ContainerD_listG_instance;\nstruct B_TimesD_SequenceD_list B_TimesD_SequenceD_listG_instance;\nstruct B_CollectionD_SequenceD_list B_CollectionD_SequenceD_listG_instance;\nstruct B_SequenceD_list B_SequenceD_listG_instance;\nstruct B_SequenceD_list B_SequenceD_listG_instance;\nstruct B_HashableD_complex B_HashableD_complexG_instance;\nstruct B_EqD_complex B_EqD_complexG_instance;\nstruct B_DivD_complex B_DivD_complexG_instance;\nstruct B_MinusD_NumberD_complex B_MinusD_NumberD_complexG_instance;\nstruct B_NumberD_complex B_NumberD_complexG_instance;\nstruct B_HashableD_float B_HashableD_floatG_instance;\nstruct B_OrdD_float B_OrdD_floatG_instance;\nstruct B_DivD_float B_DivD_floatG_instance;\nstruct B_MinusD_RealFloatD_float B_MinusD_RealFloatD_floatG_instance;\nstruct B_RealFloatD_float B_RealFloatD_floatG_instance;\nstruct B_HashableD_u1 B_HashableD_u1G_instance;\nstruct B_OrdD_u1 B_OrdD_u1G_instance;\nstruct B_DivD_u1 B_DivD_u1G_instance;\nstruct B_LogicalD_IntegralD_u1 B_LogicalD_IntegralD_u1G_instance;\nstruct B_MinusD_IntegralD_u1 B_MinusD_IntegralD_u1G_instance;\nstruct B_IntegralD_u1 B_IntegralD_u1G_instance;\nstruct B_HashableD_u8 B_HashableD_u8G_instance;\nstruct B_OrdD_u8 B_OrdD_u8G_instance;\nstruct B_DivD_u8 B_DivD_u8G_instance;\nstruct B_LogicalD_IntegralD_u8 B_LogicalD_IntegralD_u8G_instance;\nstruct B_MinusD_IntegralD_u8 B_MinusD_IntegralD_u8G_instance;\nstruct B_IntegralD_u8 B_IntegralD_u8G_instance;\nstruct B_HashableD_u16 B_HashableD_u16G_instance;\nstruct B_OrdD_u16 B_OrdD_u16G_instance;\nstruct B_DivD_u16 B_DivD_u16G_instance;\nstruct B_LogicalD_IntegralD_u16 B_LogicalD_IntegralD_u16G_instance;\nstruct B_MinusD_IntegralD_u16 B_MinusD_IntegralD_u16G_instance;\nstruct B_IntegralD_u16 B_IntegralD_u16G_instance;\nstruct B_HashableD_u32 B_HashableD_u32G_instance;\nstruct B_OrdD_u32 B_OrdD_u32G_instance;\nstruct B_DivD_u32 B_DivD_u32G_instance;\nstruct B_LogicalD_IntegralD_u32 B_LogicalD_IntegralD_u32G_instance;\nstruct B_MinusD_IntegralD_u32 B_MinusD_IntegralD_u32G_instance;\nstruct B_IntegralD_u32 B_IntegralD_u32G_instance;\nstruct B_HashableD_u64 B_HashableD_u64G_instance;\nstruct B_OrdD_u64 B_OrdD_u64G_instance;\nstruct B_DivD_u64 B_DivD_u64G_instance;\nstruct B_LogicalD_IntegralD_u64 B_LogicalD_IntegralD_u64G_instance;\nstruct B_MinusD_IntegralD_u64 B_MinusD_IntegralD_u64G_instance;\nstruct B_IntegralD_u64 B_IntegralD_u64G_instance;\nstruct B_HashableD_i8 B_HashableD_i8G_instance;\nstruct B_OrdD_i8 B_OrdD_i8G_instance;\nstruct B_DivD_i8 B_DivD_i8G_instance;\nstruct B_LogicalD_IntegralD_i8 B_LogicalD_IntegralD_i8G_instance;\nstruct B_MinusD_IntegralD_i8 B_MinusD_IntegralD_i8G_instance;\nstruct B_IntegralD_i8 B_IntegralD_i8G_instance;\nstruct B_HashableD_i16 B_HashableD_i16G_instance;\nstruct B_OrdD_i16 B_OrdD_i16G_instance;\nstruct B_DivD_i16 B_DivD_i16G_instance;\nstruct B_LogicalD_IntegralD_i16 B_LogicalD_IntegralD_i16G_instance;\nstruct B_MinusD_IntegralD_i16 B_MinusD_IntegralD_i16G_instance;\nstruct B_IntegralD_i16 B_IntegralD_i16G_instance;\nstruct B_HashableD_i32 B_HashableD_i32G_instance;\nstruct B_OrdD_i32 B_OrdD_i32G_instance;\nstruct B_DivD_i32 B_DivD_i32G_instance;\nstruct B_LogicalD_IntegralD_i32 B_LogicalD_IntegralD_i32G_instance;\nstruct B_MinusD_IntegralD_i32 B_MinusD_IntegralD_i32G_instance;\nstruct B_IntegralD_i32 B_IntegralD_i32G_instance;\nstruct B_HashableD_int B_HashableD_intG_instance;\nstruct B_OrdD_int B_OrdD_intG_instance;\nstruct B_DivD_int B_DivD_intG_instance;\nstruct B_LogicalD_IntegralD_int B_LogicalD_IntegralD_intG_instance;\nstruct B_MinusD_IntegralD_int B_MinusD_IntegralD_intG_instance;\nstruct B_IntegralD_int B_IntegralD_intG_instance;\nstruct B_HashableD_bigint B_HashableD_bigintG_instance;\nstruct B_OrdD_bigint B_OrdD_bigintG_instance;\nstruct B_DivD_bigint B_DivD_bigintG_instance;\nstruct B_LogicalD_IntegralD_bigint B_LogicalD_IntegralD_bigintG_instance;\nstruct B_MinusD_IntegralD_bigint B_MinusD_IntegralD_bigintG_instance;\nstruct B_IntegralD_bigint B_IntegralD_bigintG_instance;\nstruct B_HashableD_bool B_HashableD_boolG_instance;\nstruct B_HashableD_bytes B_HashableD_bytesG_instance = {&B_HashableD_bytesG_methods};\nstruct B_TimesD_bytes B_TimesD_bytesG_instance = {&B_TimesD_bytesG_methods};\nstruct B_ContainerD_bytes B_ContainerD_bytesG_instance = {&B_ContainerD_bytesG_methods};\nstruct B_SliceableD_bytes B_SliceableD_bytesG_instance = {&B_SliceableD_bytesG_methods};\nstruct B_OrdD_bytes B_OrdD_bytesG_instance = {&B_OrdD_bytesG_methods};\nstruct B_ContainerD_bytearray B_ContainerD_bytearrayG_instance = {&B_ContainerD_bytearrayG_methods};\nstruct B_TimesD_SequenceD_bytearray B_TimesD_SequenceD_bytearrayG_instance = {&B_TimesD_SequenceD_bytearrayG_methods, (B_Sequence)&B_SequenceD_bytearrayG_instance};\nstruct B_CollectionD_SequenceD_bytearray B_CollectionD_SequenceD_bytearrayG_instance = {&B_CollectionD_SequenceD_bytearrayG_methods, (B_Sequence)&B_SequenceD_bytearrayG_instance};\nstruct  B_SequenceD_bytearray B_SequenceD_bytearrayG_instance = {&B_SequenceD_bytearrayG_methods, (B_Eq)&B_OrdD_bigintG_methods, (B_Collection)&B_CollectionD_SequenceD_bytearrayG_instance, (B_Times)&B_TimesD_SequenceD_bytearrayG_instance};\nstruct B_OrdD_bytearray B_OrdD_bytearrayG_instance = {&B_OrdD_bytearrayG_methods};\nstruct B_HashableD_str B_HashableD_strG_instance = {&B_HashableD_strG_methods};\nstruct B_TimesD_str B_TimesD_strG_instance = {&B_TimesD_strG_methods};\nstruct B_SliceableD_str B_SliceableD_strG_instance = {&B_SliceableD_strG_methods};\nstruct B_ContainerD_str B_ContainerD_strG_instance = {&B_ContainerD_strG_methods};\nstruct B_OrdD_str B_OrdD_strG_instance = {&B_OrdD_strG_methods};\n//struct B_IterableD_range B_IterableD_rangeG_instance = {&B_IterableD_rangeG_methods};\nstruct B_IterableD_Iterator B_IterableD_IteratorG_instance = {&B_IterableD_IteratorG_methods};\nstruct B_SetD_set B_SetD_setG_instance = {&B_SetD_setG_methods};\nstruct B_OrdD_dict B_OrdD_dictG_instance = {&B_OrdD_dictG_methods};\nstruct B_MappingD_dict B_MappingD_dictG_instance = {&B_MappingD_dictG_methods};\nstruct B_OrdD_list B_OrdD_listG_instance = {&B_OrdD_listG_methods};\nstruct B_ContainerD_list B_ContainerD_listG_instance = {&B_ContainerD_listG_methods};\nstruct B_TimesD_SequenceD_list B_TimesD_SequenceD_listG_instance = {&B_TimesD_SequenceD_listG_methods, (B_Sequence)&B_SequenceD_listG_instance};\nstruct B_CollectionD_SequenceD_list B_CollectionD_SequenceD_listG_instance = {&B_CollectionD_SequenceD_listG_methods, (B_Sequence)&B_SequenceD_listG_instance};\nstruct B_SequenceD_list B_SequenceD_listG_instance = {&B_SequenceD_listG_methods, (B_Eq)&B_OrdD_bigintG_methods, (B_Collection)&B_CollectionD_SequenceD_listG_instance, (B_Times)&B_TimesD_SequenceD_listG_instance};\nstruct B_HashableD_complex B_HashableD_complexG_instance = {&B_HashableD_complexG_methods};\nstruct B_EqD_complex B_EqD_complexG_instance = {&B_EqD_complexG_methods};\nstruct B_DivD_complex B_DivD_complexG_instance = {&B_DivD_complexG_methods};\n\nstruct B_MinusD_NumberD_complex B_MinusD_NumberD_complexG_instance = {&B_MinusD_NumberD_complexG_methods, (B_Number)&B_NumberD_complexG_instance};\nstruct B_NumberD_complex B_NumberD_complexG_instance = {&B_NumberD_complexG_methods, (B_Minus)&B_MinusD_NumberD_complexG_instance};\nstruct B_HashableD_float B_HashableD_floatG_instance = {&B_HashableD_floatG_methods};\nstruct B_OrdD_float B_OrdD_floatG_instance = {&B_OrdD_floatG_methods};\nstruct B_DivD_float B_DivD_floatG_instance = {&B_DivD_floatG_methods};\nstruct B_MinusD_RealFloatD_float B_MinusD_RealFloatD_floatG_instance = {&B_MinusD_RealFloatD_floatG_methods, (B_Number)&B_RealFloatD_floatG_instance};\nstruct B_RealFloatD_float B_RealFloatD_floatG_instance = {&B_RealFloatD_floatG_methods, (B_Minus)&B_MinusD_RealFloatD_floatG_instance};\nstruct B_HashableD_u1 B_HashableD_u1G_instance = {&B_HashableD_u1G_methods};\nstruct B_OrdD_u1 B_OrdD_u1G_instance = {&B_OrdD_u1G_methods};\nstruct B_DivD_u1 B_DivD_u1G_instance = {&B_DivD_u1G_methods};\nstruct B_LogicalD_IntegralD_u1 B_LogicalD_IntegralD_u1G_instance = {&B_LogicalD_IntegralD_u1G_methods, (B_Integral)&B_IntegralD_u1G_instance};\nstruct B_MinusD_IntegralD_u1 B_MinusD_IntegralD_u1G_instance = {&B_MinusD_IntegralD_u1G_methods, (B_Number)&B_IntegralD_u1G_instance};\nstruct B_IntegralD_u1 B_IntegralD_u1G_instance = {&B_IntegralD_u1G_methods, (B_Minus)&B_MinusD_IntegralD_u1G_instance, (B_Logical)&B_LogicalD_IntegralD_u1G_instance};\n\nstruct B_HashableD_u8 B_HashableD_u8G_instance = {&B_HashableD_u8G_methods};\nstruct B_OrdD_u8 B_OrdD_u8G_instance = {&B_OrdD_u8G_methods};\nstruct B_DivD_u8 B_DivD_u8G_instance = {&B_DivD_u8G_methods};\nstruct B_LogicalD_IntegralD_u8 B_LogicalD_IntegralD_u8G_instance = {&B_LogicalD_IntegralD_u8G_methods, (B_Integral)&B_IntegralD_u8G_instance};\nstruct B_MinusD_IntegralD_u8 B_MinusD_IntegralD_u8G_instance = {&B_MinusD_IntegralD_u8G_methods, (B_Number)&B_IntegralD_u8G_instance};\nstruct B_IntegralD_u8 B_IntegralD_u8G_instance = {&B_IntegralD_u8G_methods, (B_Minus)&B_MinusD_IntegralD_u8G_instance, (B_Logical)&B_LogicalD_IntegralD_u8G_instance};\nstruct B_HashableD_u16 B_HashableD_u16G_instance = {&B_HashableD_u16G_methods};\nstruct B_OrdD_u16 B_OrdD_u16G_instance = {&B_OrdD_u16G_methods};\nstruct B_DivD_u16 B_DivD_u16G_instance = {&B_DivD_u16G_methods};\nstruct B_LogicalD_IntegralD_u16 B_LogicalD_IntegralD_u16G_instance = {&B_LogicalD_IntegralD_u16G_methods, (B_Integral)&B_IntegralD_u16G_instance};\nstruct B_MinusD_IntegralD_u16 B_MinusD_IntegralD_u16G_instance = {&B_MinusD_IntegralD_u16G_methods, (B_Number)&B_IntegralD_u16G_instance};\nstruct B_IntegralD_u16 B_IntegralD_u16G_instance = {&B_IntegralD_u16G_methods, (B_Minus)&B_MinusD_IntegralD_u16G_instance, (B_Logical)&B_LogicalD_IntegralD_u16G_instance};\nstruct B_HashableD_u32 B_HashableD_u32G_instance = {&B_HashableD_u32G_methods};\nstruct B_OrdD_u32 B_OrdD_u32G_instance = {&B_OrdD_u32G_methods};\nstruct B_DivD_u32 B_DivD_u32G_instance = {&B_DivD_u32G_methods};\nstruct B_LogicalD_IntegralD_u32 B_LogicalD_IntegralD_u32G_instance = {&B_LogicalD_IntegralD_u32G_methods, (B_Integral)&B_IntegralD_u32G_instance};\nstruct B_MinusD_IntegralD_u32 B_MinusD_IntegralD_u32G_instance = {&B_MinusD_IntegralD_u32G_methods, (B_Number)&B_IntegralD_u32G_instance};\nstruct B_IntegralD_u32 B_IntegralD_u32G_instance = {&B_IntegralD_u32G_methods, (B_Minus)&B_MinusD_IntegralD_u32G_instance, (B_Logical)&B_LogicalD_IntegralD_u32G_instance};\nstruct B_HashableD_u64 B_HashableD_u64G_instance = {&B_HashableD_u64G_methods};\nstruct B_OrdD_u64 B_OrdD_u64G_instance = {&B_OrdD_u64G_methods};\nstruct B_DivD_u64 B_DivD_u64G_instance = {&B_DivD_u64G_methods};\nstruct B_LogicalD_IntegralD_u64 B_LogicalD_IntegralD_u64G_instance = {&B_LogicalD_IntegralD_u64G_methods, (B_Integral)&B_IntegralD_u64G_instance};\nstruct B_MinusD_IntegralD_u64 B_MinusD_IntegralD_u64G_instance = {&B_MinusD_IntegralD_u64G_methods, (B_Number)&B_IntegralD_u64G_instance};\nstruct B_IntegralD_u64 B_IntegralD_u64G_instance = {&B_IntegralD_u64G_methods, (B_Minus)&B_MinusD_IntegralD_u64G_instance, (B_Logical)&B_LogicalD_IntegralD_u64G_instance};\nstruct B_HashableD_i8 B_HashableD_i8G_instance = {&B_HashableD_i8G_methods};\nstruct B_OrdD_i8 B_OrdD_i8G_instance = {&B_OrdD_i8G_methods};\nstruct B_DivD_i8 B_DivD_i8G_instance = {&B_DivD_i8G_methods};\nstruct B_LogicalD_IntegralD_i8 B_LogicalD_IntegralD_i8G_instance = {&B_LogicalD_IntegralD_i8G_methods, (B_Integral)&B_IntegralD_i8G_instance};\nstruct B_MinusD_IntegralD_i8 B_MinusD_IntegralD_i8G_instance = {&B_MinusD_IntegralD_i8G_methods, (B_Number)&B_IntegralD_i8G_instance};\nstruct B_IntegralD_i8 B_IntegralD_i8G_instance = {&B_IntegralD_i8G_methods, (B_Minus)&B_MinusD_IntegralD_i8G_instance, (B_Logical)&B_LogicalD_IntegralD_i8G_instance};\nstruct B_HashableD_i16 B_HashableD_i16G_instance = {&B_HashableD_i16G_methods};\nstruct B_OrdD_i16 B_OrdD_i16G_instance = {&B_OrdD_i16G_methods};\nstruct B_DivD_i16 B_DivD_i16G_instance = {&B_DivD_i16G_methods};\nstruct B_LogicalD_IntegralD_i16 B_LogicalD_IntegralD_i16G_instance = {&B_LogicalD_IntegralD_i16G_methods, (B_Integral)&B_IntegralD_i16G_instance};\nstruct B_MinusD_IntegralD_i16 B_MinusD_IntegralD_i16G_instance = {&B_MinusD_IntegralD_i16G_methods, (B_Number)&B_IntegralD_i16G_instance};\nstruct B_IntegralD_i16 B_IntegralD_i16G_instance = {&B_IntegralD_i16G_methods, (B_Minus)&B_MinusD_IntegralD_i16G_instance, (B_Logical)&B_LogicalD_IntegralD_i16G_instance};\nstruct B_HashableD_i32 B_HashableD_i32G_instance = {&B_HashableD_i32G_methods};\nstruct B_OrdD_i32 B_OrdD_i32G_instance = {&B_OrdD_i32G_methods};\nstruct B_DivD_i32 B_DivD_i32G_instance = {&B_DivD_i32G_methods};\nstruct B_LogicalD_IntegralD_i32 B_LogicalD_IntegralD_i32G_instance = {&B_LogicalD_IntegralD_i32G_methods, (B_Integral)&B_IntegralD_i32G_instance};\nstruct B_MinusD_IntegralD_i32 B_MinusD_IntegralD_i32G_instance = {&B_MinusD_IntegralD_i32G_methods, (B_Number)&B_IntegralD_i32G_instance};\nstruct B_IntegralD_i32 B_IntegralD_i32G_instance = {&B_IntegralD_i32G_methods, (B_Minus)&B_MinusD_IntegralD_i32G_instance, (B_Logical)&B_LogicalD_IntegralD_i32G_instance};\nstruct B_HashableD_int B_HashableD_intG_instance = {&B_HashableD_intG_methods};\nstruct B_OrdD_int B_OrdD_intG_instance = {&B_OrdD_intG_methods};\nstruct B_DivD_int B_DivD_intG_instance = {&B_DivD_intG_methods};\nstruct B_LogicalD_IntegralD_int B_LogicalD_IntegralD_intG_instance = {&B_LogicalD_IntegralD_intG_methods, (B_Integral)&B_IntegralD_intG_instance};\nstruct B_MinusD_IntegralD_int B_MinusD_IntegralD_intG_instance = {&B_MinusD_IntegralD_intG_methods, (B_Number)&B_IntegralD_intG_instance};\nstruct B_IntegralD_int B_IntegralD_intG_instance = {&B_IntegralD_intG_methods, (B_Minus)&B_MinusD_IntegralD_intG_instance, (B_Logical)&B_LogicalD_IntegralD_intG_instance};\nstruct B_HashableD_bigint B_HashableD_bigintG_instance = {&B_HashableD_bigintG_methods};\nstruct B_OrdD_bigint B_OrdD_bigintG_instance = {&B_OrdD_bigintG_methods};\nstruct B_DivD_bigint B_DivD_bigintG_instance = {&B_DivD_bigintG_methods};\nstruct B_LogicalD_IntegralD_bigint B_LogicalD_IntegralD_bigintG_instance = {&B_LogicalD_IntegralD_bigintG_methods, (B_Integral)&B_IntegralD_bigintG_instance};\nstruct B_MinusD_IntegralD_bigint B_MinusD_IntegralD_bigintG_instance = {&B_MinusD_IntegralD_bigintG_methods, (B_Number)&B_IntegralD_bigintG_instance};\nstruct B_IntegralD_bigint B_IntegralD_bigintG_instance = {&B_IntegralD_bigintG_methods, (B_Minus)&B_MinusD_IntegralD_bigintG_instance, (B_Logical)&B_LogicalD_IntegralD_bigintG_instance};\nstruct B_HashableD_bool  B_HashableD_boolG_instance = {&B_HashableD_boolG_methods};\n\n\nB_HashableD_bytes B_HashableD_bytesG_witness = &B_HashableD_bytesG_instance;\nB_TimesD_bytes B_TimesD_bytesG_witness = &B_TimesD_bytesG_instance;\nB_ContainerD_bytes B_ContainerD_bytesG_witness = &B_ContainerD_bytesG_instance;\nB_SliceableD_bytes B_SliceableD_bytesG_witness = &B_SliceableD_bytesG_instance;\nB_OrdD_bytes B_OrdD_bytesG_witness = &B_OrdD_bytesG_instance;\nB_ContainerD_bytearray B_ContainerD_bytearrayG_witness = &B_ContainerD_bytearrayG_instance;\nB_TimesD_SequenceD_bytearray B_TimesD_SequenceD_bytearrayG_witness = &B_TimesD_SequenceD_bytearrayG_instance;\nB_CollectionD_SequenceD_bytearray B_CollectionD_SequenceD_bytearrayG_witness = &B_CollectionD_SequenceD_bytearrayG_instance;\nB_SequenceD_bytearray B_SequenceD_bytearrayG_witness = &B_SequenceD_bytearrayG_instance;\nB_OrdD_bytearray B_OrdD_bytearrayG_witness = &B_OrdD_bytearrayG_instance;\nB_HashableD_str B_HashableD_strG_witness = &B_HashableD_strG_instance;\nB_TimesD_str B_TimesD_strG_witness = &B_TimesD_strG_instance;\nB_SliceableD_str B_SliceableD_strG_witness = &B_SliceableD_strG_instance;\nB_ContainerD_str B_ContainerD_strG_witness = &B_ContainerD_strG_instance;\nB_OrdD_str B_OrdD_strG_witness = &B_OrdD_strG_instance;\n//B_IterableD_range B_IterableD_rangeG_witness = &B_IterableD_rangeG_instance;\nB_IterableD_Iterator B_IterableD_IteratorG_witness = &B_IterableD_IteratorG_instance;\n//B_MinusD_SetD_set B_MinusD_SetD_setG_witness = &B_MinusD_SetD_setG_instance;\n//B_LogicalD_SetD_set B_LogicalD_SetD_setG_witness = &B_LogicalD_SetD_setG_instance;\n//B_OrdD_SetD_set B_OrdD_SetD_setG_witness = &B_OrdD_SetD_setG_instance;\nB_SetD_set B_SetD_setG_witness = &B_SetD_setG_instance;\nB_OrdD_dict B_OrdD_dictG_witness = &B_OrdD_dictG_instance;\n//B_IndexedD_MappingD_dict B_IndexedD_MappingD_dictG_witness = &B_IndexedD_MappingD_dictG_instance;\nB_MappingD_dict B_MappingD_dictG_witness = &B_MappingD_dictG_instance;\nB_OrdD_list B_OrdD_listG_witness = &B_OrdD_listG_instance;\nB_ContainerD_list B_ContainerD_listG_witness = &B_ContainerD_listG_instance;\nB_TimesD_SequenceD_list B_TimesD_SequenceD_listG_witness = &B_TimesD_SequenceD_listG_instance;\nB_CollectionD_SequenceD_list B_CollectionD_SequenceD_listG_witness = &B_CollectionD_SequenceD_listG_instance;\nB_SequenceD_list B_SequenceD_listG_witness = &B_SequenceD_listG_instance;\nB_HashableD_complex B_HashableD_complexG_witness = &B_HashableD_complexG_instance;\nB_EqD_complex B_EqD_complexG_witness = &B_EqD_complexG_instance;\nB_DivD_complex B_DivD_complexG_witness = &B_DivD_complexG_instance;\nB_MinusD_NumberD_complex B_MinusD_NumberD_complexG_witness = &B_MinusD_NumberD_complexG_instance;\nB_NumberD_complex B_NumberD_complexG_witness = &B_NumberD_complexG_instance;\nB_HashableD_float B_HashableD_floatG_witness = &B_HashableD_floatG_instance;\nB_OrdD_float B_OrdD_floatG_witness = &B_OrdD_floatG_instance;\nB_DivD_float B_DivD_floatG_witness = &B_DivD_floatG_instance;\nB_MinusD_RealFloatD_float B_MinusD_RealFloatD_floatG_witness = &B_MinusD_RealFloatD_floatG_instance;\nB_RealFloatD_float B_RealFloatD_floatG_witness = &B_RealFloatD_floatG_instance;\nB_HashableD_u1 B_HashableD_u1G_witness = &B_HashableD_u1G_instance;\nB_OrdD_u1 B_OrdD_u1G_witness = &B_OrdD_u1G_instance;\nB_DivD_u1 B_DivD_u1G_witness = &B_DivD_u1G_instance;\nB_LogicalD_IntegralD_u1 B_LogicalD_IntegralD_u1G_witness = &B_LogicalD_IntegralD_u1G_instance;\nB_MinusD_IntegralD_u1 B_MinusD_IntegralD_u1G_witness = &B_MinusD_IntegralD_u1G_instance;\nB_IntegralD_u1 B_IntegralD_u1G_witness = &B_IntegralD_u1G_instance;\nB_HashableD_u8 B_HashableD_u8G_witness = &B_HashableD_u8G_instance;\nB_OrdD_u8 B_OrdD_u8G_witness = &B_OrdD_u8G_instance;\nB_DivD_u8 B_DivD_u8G_witness = &B_DivD_u8G_instance;\nB_LogicalD_IntegralD_u8 B_LogicalD_IntegralD_u8G_witness = &B_LogicalD_IntegralD_u8G_instance;\nB_MinusD_IntegralD_u8 B_MinusD_IntegralD_u8G_witness = &B_MinusD_IntegralD_u8G_instance;\nB_IntegralD_u8 B_IntegralD_u8G_witness = &B_IntegralD_u8G_instance;\nB_HashableD_u16 B_HashableD_u16G_witness = &B_HashableD_u16G_instance;\nB_OrdD_u16 B_OrdD_u16G_witness = &B_OrdD_u16G_instance;\nB_DivD_u16 B_DivD_u16G_witness = &B_DivD_u16G_instance;\nB_LogicalD_IntegralD_u16 B_LogicalD_IntegralD_u16G_witness = &B_LogicalD_IntegralD_u16G_instance;\nB_MinusD_IntegralD_u16 B_MinusD_IntegralD_u16G_witness = &B_MinusD_IntegralD_u16G_instance;\nB_IntegralD_u16 B_IntegralD_u16G_witness = &B_IntegralD_u16G_instance;\nB_HashableD_u32 B_HashableD_u32G_witness = &B_HashableD_u32G_instance;\nB_OrdD_u32 B_OrdD_u32G_witness = &B_OrdD_u32G_instance;\nB_DivD_u32 B_DivD_u32G_witness = &B_DivD_u32G_instance;\nB_LogicalD_IntegralD_u32 B_LogicalD_IntegralD_u32G_witness = &B_LogicalD_IntegralD_u32G_instance;\nB_MinusD_IntegralD_u32 B_MinusD_IntegralD_u32G_witness = &B_MinusD_IntegralD_u32G_instance;\nB_IntegralD_u32 B_IntegralD_u32G_witness = &B_IntegralD_u32G_instance;\nB_HashableD_u64 B_HashableD_u64G_witness = &B_HashableD_u64G_instance;\nB_OrdD_u64 B_OrdD_u64G_witness = &B_OrdD_u64G_instance;\nB_DivD_u64 B_DivD_u64G_witness = &B_DivD_u64G_instance;\nB_LogicalD_IntegralD_u64 B_LogicalD_IntegralD_u64G_witness = &B_LogicalD_IntegralD_u64G_instance;\nB_MinusD_IntegralD_u64 B_MinusD_IntegralD_u64G_witness = &B_MinusD_IntegralD_u64G_instance;\nB_IntegralD_u64 B_IntegralD_u64G_witness = &B_IntegralD_u64G_instance;\nB_HashableD_i16 B_HashableD_i16G_witness = &B_HashableD_i16G_instance;\nB_OrdD_i16 B_OrdD_i16G_witness = &B_OrdD_i16G_instance;\nB_DivD_i16 B_DivD_i16G_witness = &B_DivD_i16G_instance;\nB_LogicalD_IntegralD_i16 B_LogicalD_IntegralD_i16G_witness = &B_LogicalD_IntegralD_i16G_instance;\nB_MinusD_IntegralD_i16 B_MinusD_IntegralD_i16G_witness = &B_MinusD_IntegralD_i16G_instance;\nB_IntegralD_i16 B_IntegralD_i16G_witness = &B_IntegralD_i16G_instance;\nB_HashableD_i32 B_HashableD_i32G_witness = &B_HashableD_i32G_instance;\nB_OrdD_i32 B_OrdD_i32G_witness = &B_OrdD_i32G_instance;\nB_DivD_i32 B_DivD_i32G_witness = &B_DivD_i32G_instance;\nB_LogicalD_IntegralD_i32 B_LogicalD_IntegralD_i32G_witness = &B_LogicalD_IntegralD_i32G_instance;\nB_MinusD_IntegralD_i32 B_MinusD_IntegralD_i32G_witness = &B_MinusD_IntegralD_i32G_instance;\nB_IntegralD_i32 B_IntegralD_i32G_witness = &B_IntegralD_i32G_instance;\nB_HashableD_i8 B_HashableD_i8G_witness = &B_HashableD_i8G_instance;\nB_OrdD_i8 B_OrdD_i8G_witness = &B_OrdD_i8G_instance;\nB_DivD_i8 B_DivD_i8G_witness = &B_DivD_i8G_instance;\nB_LogicalD_IntegralD_i8 B_LogicalD_IntegralD_i8G_witness = &B_LogicalD_IntegralD_i8G_instance;\nB_MinusD_IntegralD_i8 B_MinusD_IntegralD_i8G_witness = &B_MinusD_IntegralD_i8G_instance;\nB_IntegralD_i8 B_IntegralD_i8G_witness = &B_IntegralD_i8G_instance;\nB_HashableD_int B_HashableD_intG_witness = &B_HashableD_intG_instance;\nB_OrdD_int B_OrdD_intG_witness = &B_OrdD_intG_instance;\nB_DivD_int B_DivD_intG_witness = &B_DivD_intG_instance;\nB_LogicalD_IntegralD_int B_LogicalD_IntegralD_intG_witness = &B_LogicalD_IntegralD_intG_instance;\nB_MinusD_IntegralD_int B_MinusD_IntegralD_intG_witness = &B_MinusD_IntegralD_intG_instance;\nB_IntegralD_int B_IntegralD_intG_witness = &B_IntegralD_intG_instance;\nB_HashableD_bigint B_HashableD_bigintG_witness = &B_HashableD_bigintG_instance;\nB_OrdD_bigint B_OrdD_bigintG_witness = &B_OrdD_bigintG_instance;\nB_DivD_bigint B_DivD_bigintG_witness = &B_DivD_bigintG_instance;\nB_LogicalD_IntegralD_bigint B_LogicalD_IntegralD_bigintG_witness = &B_LogicalD_IntegralD_bigintG_instance;\nB_MinusD_IntegralD_bigint B_MinusD_IntegralD_bigintG_witness = &B_MinusD_IntegralD_bigintG_instance;\nB_IntegralD_bigint B_IntegralD_bigintG_witness = &B_IntegralD_bigintG_instance;\nB_HashableD_bool B_HashableD_boolG_witness = &B_HashableD_boolG_instance;\n\nstruct B_OrdD_list B_OrdD_listD_bytesG_instance = {&B_OrdD_listG_methods, (B_Ord)&B_OrdD_bytesG_instance};\nB_OrdD_list B_OrdD_listD_bytesG_witness = &B_OrdD_listD_bytesG_instance;\n\nstruct B_IndexedD_MappingD_dict B_IndexedD_MappingD_dictD_strG_instance;\nstruct B_IndexedD_MappingD_dict B_IndexedD_MappingD_dictD_intG_instance;\nstruct B_MappingD_dict B_MappingD_dictD_strG_instance = {&B_MappingD_dictG_methods, (B_Eq)&B_HashableD_strG_instance, (B_Eq)&B_HashableD_strG_instance,\n                                                         (B_Indexed)&B_IndexedD_MappingD_dictD_strG_instance, (B_Hashable)&B_HashableD_strG_instance};\nstruct B_MappingD_dict B_MappingD_dictD_intG_instance = {&B_MappingD_dictG_methods, (B_Eq)&B_HashableD_intG_instance, (B_Eq)&B_HashableD_intG_instance,\n                                                         (B_Indexed)&B_IndexedD_MappingD_dictD_intG_instance, (B_Hashable)&B_HashableD_intG_instance};\n\nstruct B_IndexedD_MappingD_dict B_IndexedD_MappingD_dictD_strG_instance =  {&B_IndexedD_MappingD_dictG_methods, (B_Eq)&B_HashableD_strG_instance, (B_Eq)&B_HashableD_strG_instance,\n                                                         (B_Mapping)&B_MappingD_dictD_strG_instance, (B_Hashable)&B_HashableD_strG_instance};\nstruct B_IndexedD_MappingD_dict B_IndexedD_MappingD_dictD_intG_instance =  {&B_IndexedD_MappingD_dictG_methods, (B_Eq)&B_HashableD_intG_instance, (B_Eq)&B_HashableD_intG_instance,\n                                                         (B_Mapping)&B_MappingD_dictD_intG_instance, (B_Hashable)&B_HashableD_intG_instance};\n\nB_MappingD_dict B_MappingD_dictD_strG_witness = &B_MappingD_dictD_strG_instance;\nB_MappingD_dict B_MappingD_dictD_intG_witness = &B_MappingD_dictD_intG_instance;\n"
  },
  {
    "path": "base/builtin/staticWitnesses.h",
    "content": "extern B_HashableD_bytes B_HashableD_bytesG_witness;\nextern B_TimesD_bytes B_TimesD_bytesG_witness;\nextern B_ContainerD_bytes B_ContainerD_bytesG_witness;\nextern B_SliceableD_bytes B_SliceableD_bytesG_witness;\nextern B_OrdD_bytes B_OrdD_bytesG_witness;\nextern B_ContainerD_bytearray B_ContainerD_bytearrayG_witness;\nextern B_TimesD_SequenceD_bytearray B_TimesD_SequenceD_bytearrayG_witness;\nextern B_CollectionD_SequenceD_bytearray B_CollectionD_SequenceD_bytearrayG_witness;\nextern B_SequenceD_bytearray B_SequenceD_bytearrayG_witness;\nextern B_OrdD_bytearray B_OrdD_bytearrayG_witness;\nextern B_HashableD_str B_HashableD_strG_witness;\nextern B_TimesD_str B_TimesD_strG_witness;\nextern B_SliceableD_str B_SliceableD_strG_witness;\nextern B_ContainerD_str B_ContainerD_strG_witness;\nextern B_OrdD_str B_OrdD_strG_witness;\n// extern B_IterableD_range B_IterableD_rangeG_witness;\nextern B_IterableD_Iterator B_IterableD_IteratorG_witness;\nextern B_MinusD_SetD_set B_MinusD_SetD_setG_witness;\nextern B_LogicalD_SetD_set B_LogicalD_SetD_setG_witness;\nextern B_OrdD_SetD_set B_OrdD_SetD_setG_witness;\nextern B_SetD_set B_SetD_setG_witness;\nextern B_OrdD_dict B_OrdD_dictG_witness;\nextern B_IndexedD_MappingD_dict B_IndexedD_MappingD_dictG_witness;\nextern B_MappingD_dict B_MappingD_dictG_witness;\nextern B_OrdD_list B_OrdD_listG_witness;\nextern B_ContainerD_list B_ContainerD_listG_witness;\nextern B_TimesD_SequenceD_list B_TimesD_SequenceD_listG_witness;\nextern B_CollectionD_SequenceD_list B_CollectionD_SequenceD_listG_witness;\nextern B_SequenceD_list B_SequenceD_listG_witness;\nextern B_HashableD_complex B_HashableD_complexG_witness;\nextern B_EqD_complex B_EqD_complexG_witness;\nextern B_DivD_complex B_DivD_complexG_witness;\nextern B_MinusD_NumberD_complex B_MinusD_NumberD_complexG_witness;\nextern B_NumberD_complex B_NumberD_complexG_witness;\nextern B_HashableD_float B_HashableD_floatG_witness;\nextern B_OrdD_float B_OrdD_floatG_witness;\nextern B_DivD_float B_DivD_floatG_witness;\nextern B_MinusD_RealFloatD_float B_MinusD_RealFloatD_floatG_witness;\nextern B_RealFloatD_float B_RealFloatD_floatG_witness;\nextern B_HashableD_u1 B_HashableD_u1G_witness;\nextern B_OrdD_u1 B_OrdD_u1G_witness;\nextern B_DivD_u1 B_DivD_u1G_witness;\nextern B_LogicalD_IntegralD_u1 B_LogicalD_IntegralD_u1G_witness;\nextern B_MinusD_IntegralD_u1 B_MinusD_IntegralD_u1G_witness;\nextern B_IntegralD_u1 B_IntegralD_u1G_witness;\nextern B_HashableD_u8 B_HashableD_u8G_witness;\nextern B_OrdD_u8 B_OrdD_u8G_witness;\nextern B_DivD_u8 B_DivD_u8G_witness;\nextern B_LogicalD_IntegralD_u8 B_LogicalD_IntegralD_u8G_witness;\nextern B_MinusD_IntegralD_u8 B_MinusD_IntegralD_u8G_witness;\nextern B_IntegralD_u8 B_IntegralD_u8G_witness;\nextern B_HashableD_u16 B_HashableD_u16G_witness;\nextern B_OrdD_u16 B_OrdD_u16G_witness;\nextern B_DivD_u16 B_DivD_u16G_witness;\nextern B_LogicalD_IntegralD_u16 B_LogicalD_IntegralD_u16G_witness;\nextern B_MinusD_IntegralD_u16 B_MinusD_IntegralD_u16G_witness;\nextern B_IntegralD_u16 B_IntegralD_u16G_witness;\nextern B_HashableD_u32 B_HashableD_u32G_witness;\nextern B_OrdD_u32 B_OrdD_u32G_witness;\nextern B_DivD_u32 B_DivD_u32G_witness;\nextern B_LogicalD_IntegralD_u32 B_LogicalD_IntegralD_u32G_witness;\nextern B_MinusD_IntegralD_u32 B_MinusD_IntegralD_u32G_witness;\nextern B_IntegralD_u32 B_IntegralD_u32G_witness;\nextern B_HashableD_u64 B_HashableD_u64G_witness;\nextern B_OrdD_u64 B_OrdD_u64G_witness;\nextern B_DivD_u64 B_DivD_u64G_witness;\nextern B_LogicalD_IntegralD_u64 B_LogicalD_IntegralD_u64G_witness;\nextern B_MinusD_IntegralD_u64 B_MinusD_IntegralD_u64G_witness;\nextern B_IntegralD_u64 B_IntegralD_u64G_witness;\nextern B_HashableD_i16 B_HashableD_i16G_witness;\nextern B_OrdD_i16 B_OrdD_i16G_witness;\nextern B_DivD_i16 B_DivD_i16G_witness;\nextern B_LogicalD_IntegralD_i16 B_LogicalD_IntegralD_i16G_witness;\nextern B_MinusD_IntegralD_i16 B_MinusD_IntegralD_i16G_witness;\nextern B_IntegralD_i16 B_IntegralD_i16G_witness;\nextern B_HashableD_i32 B_HashableD_i32G_witness;\nextern B_OrdD_i32 B_OrdD_i32G_witness;\nextern B_DivD_i32 B_DivD_i32G_witness;\nextern B_LogicalD_IntegralD_i32 B_LogicalD_IntegralD_i32G_witness;\nextern B_MinusD_IntegralD_i32 B_MinusD_IntegralD_i32G_witness;\nextern B_IntegralD_i32 B_IntegralD_i32G_witness;\nextern B_HashableD_i8 B_HashableD_i8G_witness;\nextern B_OrdD_i8 B_OrdD_i8G_witness;\nextern B_DivD_i8 B_DivD_i8G_witness;\nextern B_LogicalD_IntegralD_i8 B_LogicalD_IntegralD_i8G_witness;\nextern B_MinusD_IntegralD_i8 B_MinusD_IntegralD_i8G_witness;\nextern B_IntegralD_i8 B_IntegralD_i8G_witness;\nextern B_HashableD_int B_HashableD_intG_witness;\nextern B_OrdD_int B_OrdD_intG_witness;\nextern B_DivD_int B_DivD_intG_witness;\nextern B_LogicalD_IntegralD_int B_LogicalD_IntegralD_intG_witness;\nextern B_MinusD_IntegralD_int B_MinusD_IntegralD_intG_witness;\nextern B_IntegralD_int B_IntegralD_intG_witness;\nextern B_HashableD_bigint B_HashableD_bigintG_witness;\nextern B_OrdD_bigint B_OrdD_bigintG_witness;\nextern B_DivD_bigint B_DivD_bigintG_witness;\nextern B_LogicalD_IntegralD_bigint B_LogicalD_IntegralD_bigintG_witness;\nextern B_MinusD_IntegralD_bigint B_MinusD_IntegralD_bigintG_witness;\nextern B_IntegralD_bigint B_IntegralD_bigintG_witness;\nextern B_HashableD_bool B_HashableD_boolG_witness;\n\nextern B_OrdD_list  B_OrdD_listD_bytesG_witness;\nextern B_MappingD_dict B_MappingD_dictD_strG_witness;\nextern B_MappingD_dict B_MappingD_dictD_intG_witness;\nextern B_MappingD_dict B_MappingD_dictD_bigintG_witness;\n \n#define $SequenceD_listG_witness B_SequenceD_listG_witness\n#define $CollectionD_listG_witness B_CollectionD_SequenceD_listG_witness\n"
  },
  {
    "path": "base/builtin/str.c",
    "content": "/*\n * Copyright (C) 2019-2021 Data Ductus AB\n *\n * Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:\n *\n * 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.\n *\n * 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.\n *\n * 3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission.\n *\n * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS \"AS IS\" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n */\n\n#include <stdlib.h>\n#include <string.h>\n#include <stdio.h>\n#include <limits.h>\n#include <ctype.h>\n\n#include <strings.h>\n\n#define GC_THREADS 1\n#include \"gc.h\"\n\n#include \"utf8proc.h\"\n\n// Auxiliaries, some used for both str and bytearray implementations ////////////////////////////////////////////////////////\n\nstatic unsigned char nul = 0;\n\nstatic struct B_str null_struct = {&B_strG_methods,0,0,&nul};\n\nstatic B_str null_str = &null_struct;\n\n// Prebuilt immutable one-byte ASCII strings used by indexing and iteration.\n#define ASCII_CHAR_TABLE_SIZE 128\nstatic unsigned char ascii_char_data[ASCII_CHAR_TABLE_SIZE][2] = {\n    [1] = {1, 0},\n    [2] = {2, 0},\n    [3] = {3, 0},\n    [4] = {4, 0},\n    [5] = {5, 0},\n    [6] = {6, 0},\n    [7] = {7, 0},\n    [8] = {8, 0},\n    [9] = {9, 0},\n    [10] = {10, 0},\n    [11] = {11, 0},\n    [12] = {12, 0},\n    [13] = {13, 0},\n    [14] = {14, 0},\n    [15] = {15, 0},\n    [16] = {16, 0},\n    [17] = {17, 0},\n    [18] = {18, 0},\n    [19] = {19, 0},\n    [20] = {20, 0},\n    [21] = {21, 0},\n    [22] = {22, 0},\n    [23] = {23, 0},\n    [24] = {24, 0},\n    [25] = {25, 0},\n    [26] = {26, 0},\n    [27] = {27, 0},\n    [28] = {28, 0},\n    [29] = {29, 0},\n    [30] = {30, 0},\n    [31] = {31, 0},\n    [32] = {32, 0},\n    [33] = {33, 0},\n    [34] = {34, 0},\n    [35] = {35, 0},\n    [36] = {36, 0},\n    [37] = {37, 0},\n    [38] = {38, 0},\n    [39] = {39, 0},\n    [40] = {40, 0},\n    [41] = {41, 0},\n    [42] = {42, 0},\n    [43] = {43, 0},\n    [44] = {44, 0},\n    [45] = {45, 0},\n    [46] = {46, 0},\n    [47] = {47, 0},\n    [48] = {48, 0},\n    [49] = {49, 0},\n    [50] = {50, 0},\n    [51] = {51, 0},\n    [52] = {52, 0},\n    [53] = {53, 0},\n    [54] = {54, 0},\n    [55] = {55, 0},\n    [56] = {56, 0},\n    [57] = {57, 0},\n    [58] = {58, 0},\n    [59] = {59, 0},\n    [60] = {60, 0},\n    [61] = {61, 0},\n    [62] = {62, 0},\n    [63] = {63, 0},\n    [64] = {64, 0},\n    [65] = {65, 0},\n    [66] = {66, 0},\n    [67] = {67, 0},\n    [68] = {68, 0},\n    [69] = {69, 0},\n    [70] = {70, 0},\n    [71] = {71, 0},\n    [72] = {72, 0},\n    [73] = {73, 0},\n    [74] = {74, 0},\n    [75] = {75, 0},\n    [76] = {76, 0},\n    [77] = {77, 0},\n    [78] = {78, 0},\n    [79] = {79, 0},\n    [80] = {80, 0},\n    [81] = {81, 0},\n    [82] = {82, 0},\n    [83] = {83, 0},\n    [84] = {84, 0},\n    [85] = {85, 0},\n    [86] = {86, 0},\n    [87] = {87, 0},\n    [88] = {88, 0},\n    [89] = {89, 0},\n    [90] = {90, 0},\n    [91] = {91, 0},\n    [92] = {92, 0},\n    [93] = {93, 0},\n    [94] = {94, 0},\n    [95] = {95, 0},\n    [96] = {96, 0},\n    [97] = {97, 0},\n    [98] = {98, 0},\n    [99] = {99, 0},\n    [100] = {100, 0},\n    [101] = {101, 0},\n    [102] = {102, 0},\n    [103] = {103, 0},\n    [104] = {104, 0},\n    [105] = {105, 0},\n    [106] = {106, 0},\n    [107] = {107, 0},\n    [108] = {108, 0},\n    [109] = {109, 0},\n    [110] = {110, 0},\n    [111] = {111, 0},\n    [112] = {112, 0},\n    [113] = {113, 0},\n    [114] = {114, 0},\n    [115] = {115, 0},\n    [116] = {116, 0},\n    [117] = {117, 0},\n    [118] = {118, 0},\n    [119] = {119, 0},\n    [120] = {120, 0},\n    [121] = {121, 0},\n    [122] = {122, 0},\n    [123] = {123, 0},\n    [124] = {124, 0},\n    [125] = {125, 0},\n    [126] = {126, 0},\n    [127] = {127, 0}\n};\nstatic struct B_str ascii_char_strs[ASCII_CHAR_TABLE_SIZE] = {\n    [1] = {&B_strG_methods, 1, 1, ascii_char_data[1]},\n    [2] = {&B_strG_methods, 1, 1, ascii_char_data[2]},\n    [3] = {&B_strG_methods, 1, 1, ascii_char_data[3]},\n    [4] = {&B_strG_methods, 1, 1, ascii_char_data[4]},\n    [5] = {&B_strG_methods, 1, 1, ascii_char_data[5]},\n    [6] = {&B_strG_methods, 1, 1, ascii_char_data[6]},\n    [7] = {&B_strG_methods, 1, 1, ascii_char_data[7]},\n    [8] = {&B_strG_methods, 1, 1, ascii_char_data[8]},\n    [9] = {&B_strG_methods, 1, 1, ascii_char_data[9]},\n    [10] = {&B_strG_methods, 1, 1, ascii_char_data[10]},\n    [11] = {&B_strG_methods, 1, 1, ascii_char_data[11]},\n    [12] = {&B_strG_methods, 1, 1, ascii_char_data[12]},\n    [13] = {&B_strG_methods, 1, 1, ascii_char_data[13]},\n    [14] = {&B_strG_methods, 1, 1, ascii_char_data[14]},\n    [15] = {&B_strG_methods, 1, 1, ascii_char_data[15]},\n    [16] = {&B_strG_methods, 1, 1, ascii_char_data[16]},\n    [17] = {&B_strG_methods, 1, 1, ascii_char_data[17]},\n    [18] = {&B_strG_methods, 1, 1, ascii_char_data[18]},\n    [19] = {&B_strG_methods, 1, 1, ascii_char_data[19]},\n    [20] = {&B_strG_methods, 1, 1, ascii_char_data[20]},\n    [21] = {&B_strG_methods, 1, 1, ascii_char_data[21]},\n    [22] = {&B_strG_methods, 1, 1, ascii_char_data[22]},\n    [23] = {&B_strG_methods, 1, 1, ascii_char_data[23]},\n    [24] = {&B_strG_methods, 1, 1, ascii_char_data[24]},\n    [25] = {&B_strG_methods, 1, 1, ascii_char_data[25]},\n    [26] = {&B_strG_methods, 1, 1, ascii_char_data[26]},\n    [27] = {&B_strG_methods, 1, 1, ascii_char_data[27]},\n    [28] = {&B_strG_methods, 1, 1, ascii_char_data[28]},\n    [29] = {&B_strG_methods, 1, 1, ascii_char_data[29]},\n    [30] = {&B_strG_methods, 1, 1, ascii_char_data[30]},\n    [31] = {&B_strG_methods, 1, 1, ascii_char_data[31]},\n    [32] = {&B_strG_methods, 1, 1, ascii_char_data[32]},\n    [33] = {&B_strG_methods, 1, 1, ascii_char_data[33]},\n    [34] = {&B_strG_methods, 1, 1, ascii_char_data[34]},\n    [35] = {&B_strG_methods, 1, 1, ascii_char_data[35]},\n    [36] = {&B_strG_methods, 1, 1, ascii_char_data[36]},\n    [37] = {&B_strG_methods, 1, 1, ascii_char_data[37]},\n    [38] = {&B_strG_methods, 1, 1, ascii_char_data[38]},\n    [39] = {&B_strG_methods, 1, 1, ascii_char_data[39]},\n    [40] = {&B_strG_methods, 1, 1, ascii_char_data[40]},\n    [41] = {&B_strG_methods, 1, 1, ascii_char_data[41]},\n    [42] = {&B_strG_methods, 1, 1, ascii_char_data[42]},\n    [43] = {&B_strG_methods, 1, 1, ascii_char_data[43]},\n    [44] = {&B_strG_methods, 1, 1, ascii_char_data[44]},\n    [45] = {&B_strG_methods, 1, 1, ascii_char_data[45]},\n    [46] = {&B_strG_methods, 1, 1, ascii_char_data[46]},\n    [47] = {&B_strG_methods, 1, 1, ascii_char_data[47]},\n    [48] = {&B_strG_methods, 1, 1, ascii_char_data[48]},\n    [49] = {&B_strG_methods, 1, 1, ascii_char_data[49]},\n    [50] = {&B_strG_methods, 1, 1, ascii_char_data[50]},\n    [51] = {&B_strG_methods, 1, 1, ascii_char_data[51]},\n    [52] = {&B_strG_methods, 1, 1, ascii_char_data[52]},\n    [53] = {&B_strG_methods, 1, 1, ascii_char_data[53]},\n    [54] = {&B_strG_methods, 1, 1, ascii_char_data[54]},\n    [55] = {&B_strG_methods, 1, 1, ascii_char_data[55]},\n    [56] = {&B_strG_methods, 1, 1, ascii_char_data[56]},\n    [57] = {&B_strG_methods, 1, 1, ascii_char_data[57]},\n    [58] = {&B_strG_methods, 1, 1, ascii_char_data[58]},\n    [59] = {&B_strG_methods, 1, 1, ascii_char_data[59]},\n    [60] = {&B_strG_methods, 1, 1, ascii_char_data[60]},\n    [61] = {&B_strG_methods, 1, 1, ascii_char_data[61]},\n    [62] = {&B_strG_methods, 1, 1, ascii_char_data[62]},\n    [63] = {&B_strG_methods, 1, 1, ascii_char_data[63]},\n    [64] = {&B_strG_methods, 1, 1, ascii_char_data[64]},\n    [65] = {&B_strG_methods, 1, 1, ascii_char_data[65]},\n    [66] = {&B_strG_methods, 1, 1, ascii_char_data[66]},\n    [67] = {&B_strG_methods, 1, 1, ascii_char_data[67]},\n    [68] = {&B_strG_methods, 1, 1, ascii_char_data[68]},\n    [69] = {&B_strG_methods, 1, 1, ascii_char_data[69]},\n    [70] = {&B_strG_methods, 1, 1, ascii_char_data[70]},\n    [71] = {&B_strG_methods, 1, 1, ascii_char_data[71]},\n    [72] = {&B_strG_methods, 1, 1, ascii_char_data[72]},\n    [73] = {&B_strG_methods, 1, 1, ascii_char_data[73]},\n    [74] = {&B_strG_methods, 1, 1, ascii_char_data[74]},\n    [75] = {&B_strG_methods, 1, 1, ascii_char_data[75]},\n    [76] = {&B_strG_methods, 1, 1, ascii_char_data[76]},\n    [77] = {&B_strG_methods, 1, 1, ascii_char_data[77]},\n    [78] = {&B_strG_methods, 1, 1, ascii_char_data[78]},\n    [79] = {&B_strG_methods, 1, 1, ascii_char_data[79]},\n    [80] = {&B_strG_methods, 1, 1, ascii_char_data[80]},\n    [81] = {&B_strG_methods, 1, 1, ascii_char_data[81]},\n    [82] = {&B_strG_methods, 1, 1, ascii_char_data[82]},\n    [83] = {&B_strG_methods, 1, 1, ascii_char_data[83]},\n    [84] = {&B_strG_methods, 1, 1, ascii_char_data[84]},\n    [85] = {&B_strG_methods, 1, 1, ascii_char_data[85]},\n    [86] = {&B_strG_methods, 1, 1, ascii_char_data[86]},\n    [87] = {&B_strG_methods, 1, 1, ascii_char_data[87]},\n    [88] = {&B_strG_methods, 1, 1, ascii_char_data[88]},\n    [89] = {&B_strG_methods, 1, 1, ascii_char_data[89]},\n    [90] = {&B_strG_methods, 1, 1, ascii_char_data[90]},\n    [91] = {&B_strG_methods, 1, 1, ascii_char_data[91]},\n    [92] = {&B_strG_methods, 1, 1, ascii_char_data[92]},\n    [93] = {&B_strG_methods, 1, 1, ascii_char_data[93]},\n    [94] = {&B_strG_methods, 1, 1, ascii_char_data[94]},\n    [95] = {&B_strG_methods, 1, 1, ascii_char_data[95]},\n    [96] = {&B_strG_methods, 1, 1, ascii_char_data[96]},\n    [97] = {&B_strG_methods, 1, 1, ascii_char_data[97]},\n    [98] = {&B_strG_methods, 1, 1, ascii_char_data[98]},\n    [99] = {&B_strG_methods, 1, 1, ascii_char_data[99]},\n    [100] = {&B_strG_methods, 1, 1, ascii_char_data[100]},\n    [101] = {&B_strG_methods, 1, 1, ascii_char_data[101]},\n    [102] = {&B_strG_methods, 1, 1, ascii_char_data[102]},\n    [103] = {&B_strG_methods, 1, 1, ascii_char_data[103]},\n    [104] = {&B_strG_methods, 1, 1, ascii_char_data[104]},\n    [105] = {&B_strG_methods, 1, 1, ascii_char_data[105]},\n    [106] = {&B_strG_methods, 1, 1, ascii_char_data[106]},\n    [107] = {&B_strG_methods, 1, 1, ascii_char_data[107]},\n    [108] = {&B_strG_methods, 1, 1, ascii_char_data[108]},\n    [109] = {&B_strG_methods, 1, 1, ascii_char_data[109]},\n    [110] = {&B_strG_methods, 1, 1, ascii_char_data[110]},\n    [111] = {&B_strG_methods, 1, 1, ascii_char_data[111]},\n    [112] = {&B_strG_methods, 1, 1, ascii_char_data[112]},\n    [113] = {&B_strG_methods, 1, 1, ascii_char_data[113]},\n    [114] = {&B_strG_methods, 1, 1, ascii_char_data[114]},\n    [115] = {&B_strG_methods, 1, 1, ascii_char_data[115]},\n    [116] = {&B_strG_methods, 1, 1, ascii_char_data[116]},\n    [117] = {&B_strG_methods, 1, 1, ascii_char_data[117]},\n    [118] = {&B_strG_methods, 1, 1, ascii_char_data[118]},\n    [119] = {&B_strG_methods, 1, 1, ascii_char_data[119]},\n    [120] = {&B_strG_methods, 1, 1, ascii_char_data[120]},\n    [121] = {&B_strG_methods, 1, 1, ascii_char_data[121]},\n    [122] = {&B_strG_methods, 1, 1, ascii_char_data[122]},\n    [123] = {&B_strG_methods, 1, 1, ascii_char_data[123]},\n    [124] = {&B_strG_methods, 1, 1, ascii_char_data[124]},\n    [125] = {&B_strG_methods, 1, 1, ascii_char_data[125]},\n    [126] = {&B_strG_methods, 1, 1, ascii_char_data[126]},\n    [127] = {&B_strG_methods, 1, 1, ascii_char_data[127]}\n};\nstatic B_str space_str = &ascii_char_strs[(unsigned char)' '];\n\nstatic struct B_str whitespace_struct = {&B_strG_methods,6,6,(unsigned char *)\" \\t\\n\\r\\x0b\\x0c\"};\n\nstatic B_str whitespace_str = &whitespace_struct;\n\nstatic struct B_bytes null_bytes_struct = {&B_bytesG_methods,0,&nul};\n\nstatic B_bytes null_bytes = &null_bytes_struct;\n\nstatic struct B_bytes space_bytes_struct = {&B_bytesG_methods,1,(unsigned char *)\" \"};\n\nstatic B_bytes space_bytes = &space_bytes_struct;\n\nstatic struct B_bytes whitespace_bytes_struct = {&B_bytesG_methods,6,(unsigned char *)\" \\t\\n\\r\\x0b\\x0c\"};\n\nstatic B_bytes whitespace_bytes = &whitespace_bytes_struct;\n\n// We avoid returning the bytearray singleton from bytearray methods, this is\n// just used internally as a default value for the fill character.\nstatic struct B_bytearray space_bytearray_struct = {&B_bytearrayG_methods,1,(unsigned char *)\" \",1};\n\nstatic B_bytearray space_bytearray = &space_bytearray_struct;\n\nstatic struct B_bytearray whitespace_bytearray_struct = {&B_bytearrayG_methods,6,(unsigned char *)\" \\t\\n\\r\\x0b\\x0c\",6};\n\nstatic B_bytearray whitespace_bytearray = &whitespace_bytearray_struct;\n\n#define NEW_UNFILLED_STR(nm,nchrs,nbtes)        \\\n    assert(nbtes >= nchrs);                     \\\n    nm = acton_malloc(sizeof(struct B_str));           \\\n    (nm)->$class = &B_strG_methods;               \\\n    (nm)->nchars = nchrs;                       \\\n    (nm)->nbytes = nbtes;                       \\\n    (nm)->str = acton_malloc_atomic(nbtes + 1);       \\\n    (nm)->str[nbtes] = 0\n\n#define NEW_UNFILLED_BYTEARRAY(nm,nbtes)        \\\n    nm = acton_malloc(sizeof(struct B_bytearray));     \\\n    (nm)->$class = &B_bytearrayG_methods;         \\\n    (nm)->nbytes = nbtes;                       \\\n    (nm)->capacity = nbtes;                     \\\n    (nm)->str = acton_malloc_atomic(nbtes + 1);       \\\n    (nm)->str[nbtes] = 0\n\n#define NEW_UNFILLED_BYTES(nm,nbtes)            \\\n    nm = acton_malloc(sizeof(struct B_bytes));         \\\n    (nm)->$class = &B_bytesG_methods;             \\\n    (nm)->nbytes = nbtes;                       \\\n    (nm)->str = acton_malloc_atomic(nbtes + 1);              \\\n    (nm)->str[nbtes] = 0\n\n// Conversion to and from C strings\n\nB_str to$str(char *str) {\n    B_str res;\n    int nbytes = 0;\n    int nchars = 0;\n    bool isascii = true;\n    unsigned char *p = (unsigned char*)str;\n    while (*p != 0) {\n        if (*p >= 0x80) {\n            isascii = false;\n            break;\n        }\n        p++;\n    }\n    if (isascii) {\n        nbytes = p - (unsigned char*)str;\n        if (nbytes == 0)\n            return null_str;\n        if (nbytes == 1 && str[0] > 0 && (unsigned char)str[0] < ASCII_CHAR_TABLE_SIZE)\n            return &ascii_char_strs[(unsigned char)str[0]];\n        NEW_UNFILLED_STR(res, nbytes, nbytes);\n        memcpy(res->str, str, nbytes);\n        return res;\n    }\n    p = (unsigned char*)str;\n    int cp, cpnbytes;\n    while(1) {\n        if (*p == '\\0') {\n            NEW_UNFILLED_STR(res,nchars, nbytes);\n            memcpy(res->str,str,nbytes);\n            return res;\n        }\n        cpnbytes = utf8proc_iterate(p,-1,&cp);\n        if (cpnbytes < 0) {\n            $RAISE((B_BaseException)$NEW(B_ValueError,to$str(\"to$str: Unicode decode error\")));\n            return NULL;\n        }\n        nbytes += cpnbytes;\n        nchars++;\n        p += cpnbytes;\n    }\n}\n\n// No-copy version\nB_str to_str_noc(char *str) {\n    B_str res = acton_malloc(sizeof(struct B_str));\n    res->$class = &B_strG_methods;\n    res->nbytes = strlen(str);\n    res->nchars = res->nbytes;\n    res->str = (unsigned char*)str;\n\n    bool isascii = true;\n    unsigned char *p = (unsigned char*)str;\n    while (*p != 0) {\n        if (*p >= 0x80) {\n            isascii = false;\n            break;\n        }\n        p++;\n    }\n    p = (unsigned char*)str;\n    int cp, cpnbytes;\n    if (!isascii) {\n        res->nchars = 0;\n        while (1) {\n            if (*p == '\\0')\n                break;\n            cpnbytes = utf8proc_iterate(p, -1, &cp);\n            if (cpnbytes < 0) {\n                $RAISE((B_BaseException)$NEW(B_ValueError,to$str(\"to_str_noc: Unicode decode error\")));\n                return NULL;\n            }\n            p += cpnbytes;\n            res->nchars++;\n        }\n    }\n    return res;\n}\n\nunsigned char *fromB_str(B_str str) {\n    return str->str;\n}\n\n// #bytes in UTF-8 to represent codepoint cp\nstatic int byte_length(unsigned int cp) {\n    if (cp < 0x80)\n        return 1;\n    else if (cp < 0x800)\n        return 2;\n    else if (cp < 0x10000)\n        return 3;\n    else\n        return 4;\n}\n\n// #bytes in UTF-8 for char starting with byte c\nstatic int byte_length2(unsigned char c) {\n    if (c < 0x80)\n        return 1;\n    else if (c < 0xe0)\n        return 2;\n    else if (c < 0xf0)\n        return 3;\n    else\n        return 4;\n}\n\ntypedef int (*transform)(int codepoint);\n\n// Mapping a codepoint transform over an entire string\n// For the moment only used for str_upper and str_lower;\n// maybe not worthwhile to keep.\nstatic B_str str_transform(B_str s, transform f) {\n    if (s->nchars == 0) {\n        return null_str;\n    }\n    int cp, cpu, cplen, cpulen;\n    unsigned char *p = s->str;\n    unsigned char buffer[4*s->nchars];\n    unsigned char *up = buffer;\n    for (int i=0; i < s->nchars; i++) {\n        cplen = utf8proc_iterate(p,-1,&cp);\n        cpu = f(cp);\n        cpulen = utf8proc_encode_char(cpu,up);\n        p+=cplen;\n        up += cpulen;\n    }\n    int nbytes = (int)(up-buffer);\n    B_str res;\n    NEW_UNFILLED_STR(res,s->nchars,nbytes);\n    memcpy(res->str,buffer,nbytes);\n    return res;\n}\n\n// Find char position in text from byte position.\n// Assume that i is first byte of a char in text.\nstatic int char_no(B_str text,int i) {\n    if (text->nbytes == text->nchars) // ASCII string\n        return i;\n    int res = 0;\n    int k=0;\n    unsigned char *t = text->str;\n    while (k<i) {\n        k += byte_length2(t[k]);\n        res++;\n    }\n    return res;\n}\n\nstatic unsigned char *skip_chars(unsigned char* start, int n, int isascii) {\n    unsigned char *res = start;\n    if (isascii)\n        return start+n;\n    if (n >= 0) {\n        for (int i=0; i<n; i++)\n            res += byte_length2(*res);\n    } else {\n        for (int i= 0; i<-n; i++) {\n            res--;\n            while (*res >> 6 == 2) res--;\n        }\n    }\n    return res;\n}\n\n\n// Find byte position in text from char position.\n// Assume i is a valid char index in text\nstatic int byte_no(B_str text, int i) {\n    int res = 0;\n    unsigned char *t = text->str;\n    for (int k=0; k<i; k++) {\n        int n = byte_length2(*t);\n        res += n;\n        t += n;\n    }\n    return res;\n}\n\n// Handles negative indices in getitem etc (slice notation)\nstatic int get_index(int i, int nchars) {\n    if (i >= 0) {\n        if (i<nchars)\n            return i;\n    } else {\n        if (i >= -nchars)\n            return nchars+i;\n    }\n    $RAISE((B_BaseException)$NEW(B_IndexError, toB_int(i), to$str(\"index outside str\")));\n    return 0;\n}\n\n\n// Eliminates slice notation in find, index, count and other methods\n// with optional start and end and adds defaults for omitted parameters.\n\nstatic int fix_start_end(int nchars, B_int *start, B_int *end) {\n    if (*start==NULL) {\n        *start = acton_malloc(sizeof(struct B_int));\n        *start = toB_int(0);\n    } else {\n        int st = fromB_int(*start);\n        if (st > nchars) {\n            return -1;\n        }\n        if (st < 0) \n            st += nchars+1;\n        st = st < 0 ? 0 : st;\n        *start = toB_int(st);\n    }\n    if (*end==NULL) {\n        *end = acton_malloc(sizeof(struct B_int));\n        *end = toB_int(nchars);\n    } else {\n        int en = fromB_int(*end);\n        if (en > nchars)   \n            en = nchars;      \n        else if (en < 0) \n            en += nchars+1;     \n        en = en < 0 ? 0 : en;    \n        \n        *end = toB_int(en);\n    }\n    return 0;\n}\n\n// Builds a new one-char string starting at p.\nstatic B_str mk_char(unsigned char *p) {\n    unsigned char c = *p;\n    if (c > 0 && c < ASCII_CHAR_TABLE_SIZE)\n        return &ascii_char_strs[c];\n\n    B_str res;\n    NEW_UNFILLED_STR(res,1,byte_length2(*p));\n    for (int i=0; i<res->nbytes; i++)\n        res->str[i] = p[i];\n    return res;\n}\n\nint equal_bytes(unsigned char *p, unsigned char *q, int len) {\n    int i;\n    for (i=0; i<len; i++) {\n        if (p[i] != q[i]) break;\n    }\n    return i==len;\n}\n\nstatic int isspace_codepoint(int codepoint) {\n    int cat = utf8proc_get_property(codepoint)->category;\n    int bidi = utf8proc_get_property(codepoint)->bidi_class;\n    return (cat == UTF8PROC_CATEGORY_ZS || (bidi >= UTF8PROC_BIDI_CLASS_B && bidi <= UTF8PROC_BIDI_CLASS_WS));\n}\n\nstatic int islinebreak_codepoint(int codepoint) {\n    // category not useful; all the seven codepoints we handle are in category Other, control.\n    return (codepoint <= 0x0a && codepoint <= 0x0d) ||\n        (codepoint >= 0x1c && codepoint <= 0x1e);\n    // For now we ignore the three codepoints below which are counted as linebreaks by\n    // Python's splitlines for strings.\n    //  || codepoint == 0x85 || codepoint == 0x2028 ||codepoint == 0x2029;\n\n}\n\n// The Boyer-Moore-Horspool algorithm for searching for pattern in text.\n// For very short patterns, this should be replaced by brute force.\n// Returns byte position in text where first occurrence of pattern starts,\n// or -1 if it does not occur.\n// Start search from the left end of text.\nint bmh( unsigned char *text, unsigned char *pattern, int tbytes, int pbytes) {\n    if (pbytes>tbytes) return -1;\n    int skip[256];\n    for (int i=0; i<256; i++) skip[i] = pbytes;\n    for (int i=0; i<pbytes-1; i++)\n        skip[(int)pattern[i]] = pbytes-i-1;\n    int k = pbytes-1;\n    int i, j;\n    while (k<tbytes) {\n        j = pbytes-1;\n        i = k;\n        while (j >=0 && text[i] == pattern[j]) {\n            j--; i--;\n        }\n        if (j==-1) return i+1;\n        k += skip[(int)text[k]];\n    }\n    return -1;\n}\n\n// Start search from the right end of text.\nstatic int rbmh( unsigned char *text, unsigned char *pattern, int tbytes, int pbytes) {\n    if (pbytes>tbytes) return -1;\n    int skip[256];\n    for (int i=0; i<256; i++) skip[i] = pbytes;\n    for (int i=pbytes-1; i>0; i--)\n        skip[(int)pattern[i]] = i;\n    int k = tbytes - pbytes;\n    int i, j;\n    while (k >= 0) {\n        j = 0;\n        i = k;\n        while (j < pbytes && text[i] == pattern[j]) {\n            j++; i++;\n        }\n        if (j==pbytes) return i-pbytes;\n        k -= skip[(int)text[k]];\n    }\n    return -1;\n}\n\nstruct byte_counts {\n    int printable, squotes, dquotes, escaped, non_printable, non_ascii, braces;\n};\n\n\nstruct byte_counts byte_count(unsigned char *s, int len) {\n   struct byte_counts res = {0,0,0,0,0,0,0};\n    unsigned char c;\n    for (int i=0; i<len; i++) {\n        c = s[i];\n        if (c=='\\\\' || c=='\\n' || c=='\\t' || c=='\\r')\n            res.escaped++;\n        else if (c < 32 || c == 127)\n            res.non_printable++;\n        else if (c=='\\'')\n            res.squotes++;\n        else if (c=='\"')\n            res.dquotes++;\n        else if (c=='{' || c=='}')\n            res.braces++;\n        else if (c<127)\n            res.printable++;\n        else\n            res.non_ascii++;\n    }\n    return res;\n}\n\nvoid escape_str(unsigned char *out, unsigned char *in, int outlen, int inlen, int max_esc, bool esc_squote, bool esc_dquote, bool esc_braces, bool esc_triple_dquote) {\n    unsigned char *hexdigits = (unsigned char *)\"0123456789abcdef\";\n    unsigned char *p = out;\n    for (int i=0; i<inlen; i++) {\n        unsigned char c = in[i];\n\n        // Handle \"\"\" sequences if requested\n        if (esc_triple_dquote && i + 2 < inlen && c == '\"' && in[i+1] == '\"' && in[i+2] == '\"') {\n            // Escape all three quotes: \"\"\" -> \\\"\\\"\\\"\n            *p = '\\\\'; p++;\n            *p = '\"'; p++;\n            *p = '\\\\'; p++;\n            *p = '\"'; p++;\n            *p = '\\\\'; p++;\n            *p = '\"'; p++;\n            i += 2;  // Skip the other two quotes\n            continue;\n        }\n\n        if ((c < 32 && c != '\\t' && c != '\\r' && c != '\\n') || ( c > 126 && c <= max_esc)) {\n            *p = '\\\\'; p++;\n            *p = 'x'; p++;\n            *p = hexdigits[c >> 4]; p++;\n            *p = hexdigits[c & 0xf]; p++;\n        } else {\n            switch (c) {\n            case '\\\\':\n                *p = '\\\\'; p++;\n                *p = '\\\\'; p++;\n                break;\n            case '\\'':\n                if (esc_squote) {\n                    *p = '\\\\'; p++;\n                }\n                *p = '\\''; p++;\n                break;\n            case '\"':\n                if (esc_dquote) {\n                    *p = '\\\\'; p++;\n                }\n                *p = '\"'; p++;\n                break;\n            case '{':\n                if (esc_braces) {\n                    *p = '{'; p++;\n                }\n                *p = '{'; p++;\n                break;\n            case '}':\n                if (esc_braces) {\n                    *p = '}'; p++;\n                }\n                *p = '}'; p++;\n                break;\n            case '\\t':\n                *p = '\\\\'; p++;\n                *p = 't'; p++;\n                break;\n            case '\\n':\n                *p = '\\\\'; p++;\n                *p = 'n'; p++;\n                break;\n            case '\\r':\n                *p = '\\\\'; p++;\n                *p = 'r'; p++;\n                break;\n            default:\n                *p = c; p++;\n            }\n        }\n    }\n}\n\n\n\n// General methods //////////////////////////////////////////////////////////////\n\nB_str B_strG_new(B_value s) {\n    return $NEW(B_str, s);\n}\n\nB_NoneType B_strD___init__(B_str self, B_value s) {\n    // If s is None (C NULL) we use the \"None\" string.\n    if (s == NULL) {\n        self->nchars = 4;\n        self->nbytes = 4;\n        self->str = (unsigned char *)\"None\";\n        return B_None;\n    }\n    B_str res = s->$class->__str__(s);\n    self->nchars = res->nchars;\n    self->nbytes = res->nbytes;\n    self->str = res->str;\n    return B_None;\n}\n\nB_bool B_strD___bool__(B_str s) {\n    return toB_bool(s->nchars > 0);\n};\n\nB_str B_strD___str__(B_str s) {\n    return s;\n}\n\n\nB_str B_strD___repr__(B_str s) {\n    struct byte_counts bs = byte_count(s->str, s->nbytes);\n    // We aim to produce a simple, readable representation of the string\n    // - Default to single quotes unless string contains single quotes\n    // - Use double quotes if string contains single quotes\n    // - Use triple quotes (\"\"\") if both quote types are present\n    // - If \"\"\" appears in the content, escape it as \\\"\\\"\\\"\n\n    bool use_triple_quotes = (bs.dquotes > 0 && bs.squotes > 0); // Use triple quotes if both types are present\n    bool use_double_quotes = false;  // Default to single quotes\n\n    if (use_triple_quotes) {\n        // Always use \"\"\" for triple quotes\n        use_double_quotes = true;\n    } else {\n        // Simple case: use single quotes unless string contains single quotes\n        use_double_quotes = (bs.squotes > 0);\n    }\n\n    int quotes_per_side = use_triple_quotes ? 3 : 1;\n    int quote_bytes = quotes_per_side * 2;\n\n    // Count how many \"\"\" sequences need escaping (only relevant if using \"\"\" delimiters)\n    int escape_triple_bytes = 0;\n    if (use_triple_quotes) {\n        unsigned char *p = s->str;\n        int remaining = s->nbytes;\n        int pos;\n        while ((pos = bmh(p, (unsigned char*)\"\\\"\\\"\\\"\", remaining, 3)) >= 0) {\n            escape_triple_bytes += 3;  // Each quote needs a backslash: \"\"\" -> \\\"\\\"\\\"\n            p += pos + 3;\n            remaining = s->nbytes - (p - s->str);\n        }\n    }\n\n    int newbytes = quote_bytes + bs.escaped + 3*bs.non_printable + bs.braces + escape_triple_bytes;\n\n    B_str res;\n    NEW_UNFILLED_STR(res, s->nchars + newbytes, s->nbytes + newbytes);\n\n    char quote_char = use_double_quotes ? '\"' : '\\'';\n\n    // Add opening quotes\n    for (int i = 0; i < quotes_per_side; i++)\n        res->str[i] = quote_char;\n\n    escape_str(res->str + quotes_per_side, s->str, res->nbytes - quote_bytes, s->nbytes, 127, false, false, true, use_triple_quotes);\n\n    // Add closing quotes\n    for (int i = 0; i < quotes_per_side; i++)\n        res->str[res->nbytes - quotes_per_side + i] = quote_char;\n\n    return res;\n}\n\nvoid B_strD___serialize__(B_str str,$Serial$state state) {\n    int nWords = str->nbytes/sizeof($WORD) + 1;         // # $WORDS needed to store str->str, including terminating 0.\n    $ROW row = $add_header(STR_ID,2+nWords,state);\n    long nbytes = (int)str->nbytes;                    // We could pack nbytes and nchars in one $WORD,\n    memcpy(row->blob,&nbytes,sizeof($WORD));            // but we should think of a better, general approach.\n    long nchars = (int)str->nchars;\n    memcpy(row->blob+1,&nchars,sizeof($WORD));\n    memcpy(row->blob+2,str->str,nbytes+1);\n}\n\nB_str B_strD___deserialize__(B_str self, $Serial$state state) {\n    $ROW this = state->row;\n    state->row =this->next;\n    state->row_no++;\n    B_str res = acton_malloc(sizeof(struct B_str));\n    long nbytes;\n    memcpy(&nbytes,this->blob,sizeof($WORD));\n    res->$class = &B_strG_methods;\n    res->nbytes = (int)nbytes;\n    long nchars;\n    memcpy(&nchars,this->blob+1,sizeof($WORD));\n    res->nchars = (int)nchars;\n    res->str = acton_malloc_atomic(nbytes+1);\n    memcpy(res->str,this->blob+2,nbytes+1);\n    return res;\n}\n\n\n// str-specific methods ////////////////////////////////////////////////////////\n\nB_str B_strD_capitalize(B_str s) {\n    if (s->nchars==0) {\n        return null_str;\n    }\n    int cp, cpu, cplen, cpulen;\n    unsigned char *p = s->str;\n    unsigned char buffer[4*s->nchars];\n    unsigned char *up = buffer;\n    for (int i=0; i < s->nchars; i++) {\n        cplen = utf8proc_iterate(p,-1,&cp);\n        cpu = i==0? utf8proc_totitle(cp) : utf8proc_tolower(cp);\n        cpulen = utf8proc_encode_char(cpu,up);\n        p+=cplen;\n        up += cpulen;\n    }\n    long nbytes = (long)(up-buffer);\n    B_str res;\n    NEW_UNFILLED_STR(res,s->nchars,nbytes);\n    memcpy(res->str,buffer,nbytes);\n    return res;\n}\n\nB_str B_strD_center(B_str s, B_int width, B_str fill) {\n    int wval = fromB_int(width);\n    if (!fill)\n        fill = space_str;\n    if (fill->nchars != 1) {\n        $RAISE((B_BaseException)$NEW(B_ValueError,to$str(\"center: fill string not single char\")));\n    }\n    if (wval <= s->nchars) {\n        return s;\n    }\n    int pad = (wval-s->nchars);\n    int padleft = pad/2; // Below we make use of the fact padright >= padleft.\n    int padright = pad-padleft;\n    int fillbytes = fill->nbytes;\n    int sbytes = s->nbytes;\n    B_str res;\n    NEW_UNFILLED_STR(res, wval,sbytes+pad*fillbytes);\n    unsigned char *c = fill->str;\n    unsigned char *p = res->str;\n    p += padleft*fillbytes+sbytes;\n    for (int i = 0; i<padright; i++) {\n        for (int j = 0; j < fillbytes; j++)\n            p[j] = c[j];\n        p += fillbytes;\n    }\n    p -= padright*fillbytes;\n    memcpy(res->str,p,padleft*fillbytes);\n    p -= sbytes;\n    memcpy(p,s->str,sbytes);\n    return res;\n}\n\n\nB_int B_strD_count(B_str s, B_str sub, B_int start, B_int end) {\n    int isascii = s->nchars == s->nbytes;\n    B_int st = start;\n    B_int en = end;\n    if (fix_start_end(s->nchars,&st,&en) < 0) return toB_int(0);\n    unsigned char *p = skip_chars(s->str,fromB_int(st),isascii);\n    unsigned char *q = skip_chars(p,fromB_int(en)-fromB_int(st),isascii);\n    int res = 0;\n    int n = bmh(p,sub->str,q-p,sub->nbytes);\n    while (n>=0) {\n        res++;\n        p += n + (sub->nbytes>0 ? sub->nbytes : 1);\n        n = bmh(p,sub->str,q-p,sub->nbytes);\n    }\n    return toB_int(res);\n}\n\nB_bytes B_strD_encode(B_str s) {\n    B_bytes res;\n    NEW_UNFILLED_BYTES(res,s->nbytes);\n    memcpy(res->str,s->str,s->nbytes);\n    return res;\n}\n\nB_bool B_strD_endswith(B_str s, B_str sub, B_int start, B_int end) {\n    B_int st = start;\n    B_int en = end;\n    if (fix_start_end(s->nchars,&st,&en) < 0) return B_False;\n    if (en->val-st->val < sub->nbytes) return B_False;\n    int isascii = s->nchars==s->nbytes;\n    unsigned char *p = skip_chars(s->str + s->nbytes,fromB_int(en) - s->nchars,isascii) - sub->nbytes;\n    unsigned char *q = sub->str;\n    for (int i=0; i<sub->nbytes; i++) {\n        if (*p == 0 || *p++ != *q++) {\n            return B_False;\n        }\n    }\n    return B_True;\n}\n\nB_str B_strD_expandtabs(B_str s, B_int tabsize){\n    if (s->nchars == 0) {\n        return null_str;\n    }\n    int tabsz = tabsize?fromB_int(tabsize):8;\n    int pos = 0;\n    int expanded = 0;\n    tabsz = tabsz <= 0 ? 1 : tabsz;\n    unsigned char buffer[tabsz * s->nchars];\n    unsigned char *p = s->str;\n    unsigned char *q = buffer;\n    for (int i=0; i<s->nchars; i++) {\n        if (*p == '\\t') {\n            int n = tabsz - pos % tabsz;\n            for (int j=0; j < n; j++) {\n                *q++ = ' ';\n            }\n            p++;\n            expanded += n-1;\n            pos+=n;\n        } else if (*p=='\\n' || *p == '\\r') {\n            *q++ = *p++;\n            pos = 0;\n        } else {\n            for (int j=0; j< byte_length2(*p); j++) {\n                *q++ = *p++;\n                pos++;\n            }\n        }\n    }\n    B_str res;\n    NEW_UNFILLED_STR(res,s->nchars+expanded,s->nbytes+expanded);\n    memcpy(res->str,buffer,s->nbytes+expanded);\n    return res;\n}\n\nB_int B_strD_find(B_str s, B_str sub, B_int start, B_int end) {\n    int isascii = s->nchars == s->nbytes;\n    B_int st = start;\n    B_int en = end;\n    if (fix_start_end(s->nchars,&st,&en) < 0) return toB_int(-1);\n    unsigned char *p = skip_chars(s->str,fromB_int(st),isascii);\n    unsigned char *q = skip_chars(p,fromB_int(en)-fromB_int(st),isascii);\n    int n = bmh(p,sub->str,q-p,sub->nbytes);\n    if (n<0) return toB_int(-1);\n    return toB_int(char_no(s,n+p-s->str));\n}\n\nB_int B_strD_index(B_str s, B_str sub, B_int start, B_int end) {\n    B_int n = B_strD_find(s,sub,start,end);\n    if (fromB_int(n)<0) {\n        $RAISE((B_BaseException)$NEW(B_ValueError,to$str(\"index: substring not found\")));\n    }\n    return n;\n}\n\nB_bool B_strD_isalnum(B_str s) {\n    unsigned char *p = s->str;\n    int codepoint;\n    int nbytes;\n    if (s->nchars == 0)\n        return B_False;\n    for (int i=0; i < s->nchars; i++) {\n        nbytes = utf8proc_iterate(p,-1,&codepoint);\n        utf8proc_category_t cat = utf8proc_category(codepoint);\n        if ((cat <  UTF8PROC_CATEGORY_LU || cat >  UTF8PROC_CATEGORY_LO) && cat != UTF8PROC_CATEGORY_ND)\n            return B_False;\n        p += nbytes;\n    }\n    return B_True;\n}\n\nB_bool B_strD_isalpha(B_str s) {\n    unsigned char *p = s->str;\n    int codepoint;\n    int nbytes;\n    if (s->nchars == 0)\n        return B_False;\n    for (int i=0; i < s->nchars; i++) {\n        nbytes = utf8proc_iterate(p,-1,&codepoint);\n        utf8proc_category_t cat = utf8proc_category(codepoint);\n        if (cat <  UTF8PROC_CATEGORY_LU || cat >  UTF8PROC_CATEGORY_LO)\n            return B_False;\n        p += nbytes;\n    }\n    return B_True;\n}\n\nB_bool B_strD_isascii(B_str s) {\n    unsigned char *p = s->str;\n    for (int i=0; i < s->nbytes; i++) {\n        if (*p > 127)\n            return B_False;\n        p++;\n    }\n    return B_True;\n}\n\nB_bool B_strD_isdecimal(B_str s) {\n    unsigned char *p = s->str;\n    int codepoint;\n    int nbytes;\n    if (s->nchars == 0)\n        return B_False;\n    for (int i=0; i < s->nchars; i++) {\n        nbytes = utf8proc_iterate(p,-1,&codepoint);\n        utf8proc_category_t cat = utf8proc_category(codepoint);\n        if (cat != UTF8PROC_CATEGORY_ND)\n            return B_False;\n        p += nbytes;\n    }\n    return B_True;\n}\n\nB_bool B_strD_islower(B_str s) {\n    unsigned char *p = s->str;\n    int codepoint;\n    int nbytes;\n    int has_cased = 0;\n    if (s->nchars == 0)\n        return B_False;\n    for (int i=0; i < s->nchars; i++) {\n        nbytes = utf8proc_iterate(p,-1,&codepoint);\n        utf8proc_category_t cat = utf8proc_category(codepoint);\n        if (cat == UTF8PROC_CATEGORY_LT|| cat == UTF8PROC_CATEGORY_LU)\n            return B_False;\n        if (cat == UTF8PROC_CATEGORY_LL)\n            has_cased = 1;\n        p += nbytes;\n    }\n    return toB_bool(has_cased);\n}\n\nB_bool B_strD_isprintable(B_str s) {\n    unsigned char *p = s->str;\n    int codepoint;\n    int nbytes;\n    if (s->nchars == 0)\n        return B_False;\n    for (int i=0; i < s->nchars; i++) {\n        nbytes = utf8proc_iterate(p,-1,&codepoint);\n        utf8proc_category_t cat = utf8proc_category(codepoint);\n        if (cat >= UTF8PROC_CATEGORY_ZS && codepoint != 0x20)\n            return B_False;\n        p += nbytes;\n    }\n    return B_True;\n}\n\nB_bool B_strD_isspace(B_str s) {\n    unsigned char *p = s->str;\n    int codepoint;\n    int nbytes;\n    if (s->nchars == 0)\n        return B_False;\n    for (int i=0; i < s->nchars; i++) {\n        nbytes = utf8proc_iterate(p,-1,&codepoint);\n        if (!isspace_codepoint(codepoint))\n            return B_False;\n        p += nbytes;\n    }\n    return B_True;\n}\n\nB_bool B_strD_istitle(B_str s) {\n    unsigned char *p = s->str;\n    int codepoint;\n    int nbytes;\n    int hascased = 0;\n    int incasedrun = 0;\n    if (s->nchars == 0)\n        return B_False;\n    for (int i=0; i < s->nchars; i++) {\n        nbytes = utf8proc_iterate(p,-1,&codepoint);\n        utf8proc_category_t cat = utf8proc_category(codepoint);\n        if (cat == UTF8PROC_CATEGORY_LU || cat == UTF8PROC_CATEGORY_LT ) {\n            hascased = 1;\n            if (incasedrun)\n                return B_False;\n            incasedrun = 1;\n        } else if (cat == UTF8PROC_CATEGORY_LL) {\n            hascased = 1;\n            if (!incasedrun)\n                return B_False;\n        } else\n            incasedrun = 0;\n        p += nbytes;\n    }\n    return toB_bool(hascased);\n}\n\nB_bool B_strD_isupper(B_str s) {\n    unsigned char *p = s->str;\n    int codepoint;\n    int nbytes;\n    int hascased = 0;\n    if (s->nchars == 0)\n        return B_False;\n    for (int i=0; i < s->nchars; i++) {\n        nbytes = utf8proc_iterate(p,-1,&codepoint);\n        utf8proc_category_t cat = utf8proc_category(codepoint);\n        if (cat == UTF8PROC_CATEGORY_LL)\n            return B_False;\n        if (cat == UTF8PROC_CATEGORY_LU || cat == UTF8PROC_CATEGORY_LT)\n            hascased = 1;\n        p += nbytes;\n    }\n    return toB_bool(hascased);\n}\n\nB_str B_strD_join(B_str s, B_Iterable wit, $WORD iter) {\n    int totchars = 0;\n    int totbytes = 0;\n    B_CollectionD_SequenceD_list wit2 = B_CollectionD_SequenceD_listG_witness;\n    B_list lst = wit2->$class->__fromiter__(wit2,wit,iter);\n    B_str nxt;\n    int len = lst->length;\n    for (int i=0; i<len; i++) {\n        nxt = (B_str)lst->data[i];\n        totchars += nxt->nchars;\n        totbytes += nxt->nbytes;\n    }\n    if (len > 1) {\n        totchars += (len-1) * s->nchars;\n        totbytes += (len-1) * s->nbytes;\n    }\n    B_str res;\n    NEW_UNFILLED_STR(res,totchars,totbytes);\n    if (len > 0) {\n        nxt = (B_str)lst->data[0];\n        unsigned char *p = res->str;\n        memcpy(p,nxt->str,nxt->nbytes);\n        p += nxt->nbytes;\n        for (int i=1; i<len; i++) {\n            nxt = (B_str)lst->data[i];\n            memcpy(p,s->str,s->nbytes);\n            p += s->nbytes;\n            memcpy(p,nxt->str,nxt->nbytes);\n            p += nxt->nbytes;\n        }\n    }\n    return res;\n}\n\nB_str B_strD_ljust(B_str s, B_int width, B_str fill) {\n    if (!fill) fill = space_str;\n    if (fill->nchars != 1) {\n        $RAISE((B_BaseException)$NEW(B_ValueError,to$str(\"ljust: fill str not single char\")));\n    }\n    int wval = fromB_int(width);\n    if (wval <= s->nchars) {\n        return s;\n    }\n    int pad = (wval-s->nchars);\n    B_str res;\n    NEW_UNFILLED_STR(res,wval, s->nbytes+pad*fill->nbytes);\n    unsigned char *c = fill->str;\n    unsigned char *p = res->str + s->nbytes;\n    for (int i = 0; i<pad; i++) {\n        for (int j = 0; j < fill->nbytes; j++)\n            *p++ = c[j];\n    }\n    memcpy(res->str,s->str,s->nbytes);\n    return res;\n}\n\nB_str B_strD_lower(B_str s) {\n    return str_transform(s,utf8proc_tolower);\n}\n\n\nB_str B_strD_lstrip(B_str s, B_str cs) {\n    if (s->nchars == 0) return s;\n    if (cs==NULL) cs = whitespace_str;\n    unsigned char *p = s->str;\n    int i, k;\n    for (i = 0; i < s->nchars; i++) {\n        unsigned char *q = cs->str;\n        for (k = 0; k < cs->nchars; k++) {\n            if (equal_bytes(p,q,byte_length2(*q)))\n                break;\n            else\n                q +=  byte_length2(*q);\n        }\n        if (k == cs->nchars) break;\n        p +=  byte_length2(*p);\n    }\n    B_str res;\n    NEW_UNFILLED_STR(res,s->nchars-i,s->str+s->nbytes-p);\n    memcpy(res->str,p,res->nbytes);\n    return res;\n}\n\nB_tuple B_strD_partition(B_str s, B_str sep) {\n    int n = fromB_int(B_strD_find(s,sep,NULL,NULL));\n    if (n<0) {\n        return $NEWTUPLE(3,s,null_str,null_str);\n    } else {\n        int isascii = s->nchars == s->nbytes;\n        int nb = (int)(skip_chars(s->str,n,isascii)-s->str);\n        B_str ls;\n        NEW_UNFILLED_STR(ls,n,nb);\n        memcpy(ls->str,s->str,nb);\n        B_str rs;\n        int nbr = s->nbytes - sep->nbytes - nb;\n        NEW_UNFILLED_STR(rs,s->nchars-n-sep->nchars,nbr);\n        memcpy(rs->str,s->str+nb+sep->nbytes,nbr);\n        return $NEWTUPLE(3,ls,sep,rs);\n    }\n}\n\nB_str B_strD_replace(B_str s, B_str old, B_str new, B_int count) {\n    if (count==NULL)\n        count = toB_int(INT_MAX);\n    int c = fromB_int(B_strD_count(s,old,NULL,NULL));\n    int c0 = fromB_int(count) < c ? fromB_int(count) : c;\n    if (c0==0){\n        return s;\n    }\n    int nbytes = s->nbytes + c0*(new->nbytes-old->nbytes);\n    int nchars = s->nchars+c0*(new->nchars-old->nchars);\n    B_str res;\n    NEW_UNFILLED_STR(res,nchars,nbytes);\n    unsigned char *p = s->str;\n    unsigned char *q = res->str;\n    unsigned char *pold = old->str;\n    unsigned char *pnew = new->str;\n    int plen = s->nbytes;\n    int n;\n    for (int i=0; i<c0; i++) {\n        n = i>0 && old->nbytes==0 ? 1 : bmh(p,pold,plen,old->nbytes);\n        if (n>0) {\n            memcpy(q,p,n);\n            p+=n; q+=n;\n        }\n        memcpy(q,pnew,new->nbytes);\n        p += old->nbytes;\n        q += new->nbytes;\n        plen -= n+old->nbytes;\n    }\n    if (plen>0)\n        memcpy(q,p,plen);\n    return res;\n}\n\n\nB_int B_strD_rfind(B_str s, B_str sub, B_int start, B_int end) {\n    int isascii = s->nchars == s->nbytes;\n    B_int st = start;\n    B_int en = end;\n    if (fix_start_end(s->nchars,&st,&en) < 0) return toB_int(-1);\n    unsigned char *p = skip_chars(s->str,fromB_int(st),isascii);\n    unsigned char *q = skip_chars(p,fromB_int(en)-fromB_int(st),isascii);\n    int n = rbmh(p,sub->str,q-p,sub->nbytes);\n    if (n<0) return toB_int(-1);\n    return toB_int(char_no(s,n+p-s->str));\n}\n\n\nB_int B_strD_rindex(B_str s, B_str sub, B_int start, B_int end) {\n    B_int n = B_strD_rfind(s,sub,start,end);\n    if (fromB_int(n)<0) {\n        $RAISE((B_BaseException)$NEW(B_ValueError,to$str(\"rindex: substring not found\")));\n    };\n    return n;\n}\n\nB_str B_strD_rjust(B_str s, B_int width, B_str fill) {\n    if (!fill) fill = space_str;\n    if (fill->nchars != 1) {\n        $RAISE((B_BaseException)$NEW(B_ValueError,to$str(\"rjust: fill string not single char\")));\n    }\n    int wval = fromB_int(width);\n    if (wval <= s->nchars) {\n        return s;\n    }\n    int pad = (wval-s->nchars);\n    B_str res;\n    NEW_UNFILLED_STR(res,wval,s->nbytes+pad*fill->nbytes);\n    unsigned char *c = fill->str;\n    unsigned char *p = res->str;\n    for (int i = 0; i<pad; i++) {\n        for (int j = 0; j < fill->nbytes; j++)\n            *p++ = c[j];\n    }\n    memcpy(p,s->str,s->nbytes);\n    return res;\n}\n\nB_tuple B_strD_rpartition(B_str s, B_str sep) {\n    int n = fromB_int(B_strD_rfind(s,sep,NULL,NULL));\n    if (n<0) {\n        return $NEWTUPLE(3,null_str,null_str,s);\n    } else {\n        int isascii = s->nchars == s->nbytes;\n        int nb = (int)(skip_chars(s->str,n,isascii)-s->str);\n        B_str ls;\n        NEW_UNFILLED_STR(ls,n,nb);\n        memcpy(ls->str,s->str,nb);\n        int nbr = s->nbytes - sep->nbytes - nb;\n        B_str rs;\n        NEW_UNFILLED_STR(rs,s->nchars-n-sep->nchars,nbr);\n        memcpy(rs->str,s->str+nb+sep->nbytes,nbr);\n        return  $NEWTUPLE(3,ls,sep,rs);\n    }\n}\n\n\nB_list B_strD_split(B_str s, B_str sep, B_int maxsplit) {\n    B_list res = $NEW(B_list,NULL,NULL);\n    B_SequenceD_list wit = B_SequenceD_listG_witness;\n    if (maxsplit == NULL || fromB_int(maxsplit) < 0) maxsplit = toB_int(INT_MAX); \n    int remaining = s->nchars;\n    if (sep == NULL) {\n        unsigned char *p = s->str;\n        int nbytes, codepoint, wordlength;\n        if (remaining==0) {\n            return res;\n        }\n        wordlength = 0;\n        int inword = 0;\n        unsigned char *q;\n        while (remaining > 0) {\n            nbytes = utf8proc_iterate(p,-1,&codepoint);\n            if (!isspace_codepoint(codepoint)) {\n                if (!inword) {\n                    inword = 1;\n                    q = p;\n                    wordlength = 1;\n                    if (res->length == fromB_int(maxsplit))\n                        break; // we have now removed leading whitespace in remainder\n                } else\n                    wordlength++;\n            } else {\n                if (inword) {\n                    inword = 0;\n                    B_str word;\n                    NEW_UNFILLED_STR(word,wordlength,p-q);\n                    memcpy(word->str,q,p-q);\n                    wit->$class->append(wit,res,word);\n                    wordlength = 0;\n                }\n            }\n            remaining--;\n            p += nbytes;\n        }\n        // this if statement should be simplified; almost code duplication.\n        if (remaining == 0) {\n            if (inword) {\n                B_str word;\n                NEW_UNFILLED_STR(word,wordlength,p-q);\n                memcpy(word->str,q,p-q);\n                wit->$class->append(wit,res,word);\n            }\n        } else {\n            B_str word;\n            p = s->str+s->nbytes;\n            NEW_UNFILLED_STR(word,remaining,p-q);\n            memcpy(word->str,q,p-q);\n            wit->$class->append(wit,res,word);\n        }\n        // $WORD w = list_getitem(res,0);\n        return res;\n    } else { // separator given\n        if (sep->nchars==0) {\n            $RAISE((B_BaseException)$NEW(B_ValueError,to$str(\"split: separator is empty string\")));\n        }\n        if (remaining==0) { // for some unfathomable reason, this is the behaviour of the Python method\n            wit->$class->append(wit,res,null_str);\n            return res;\n        }\n        B_str ls, rs, ssep;\n        rs = s;\n        // Note: This builds many intermediate rs strings...\n        while (rs->nchars>0 && res->length < fromB_int(maxsplit)) {\n            B_tuple t = B_strD_partition(rs,sep);\n            ssep = (B_str)t->components[1];\n            rs =  (B_str)t->components[2];\n            wit->$class->append(wit,res,(B_str)t->components[0]);\n        }\n        if (ssep->nchars>0)\n            wit->$class->append(wit,res,rs);\n        return res;\n    }\n}\n\nB_list B_strD_splitlines(B_str s, B_bool keepends) {\n    B_SequenceD_list wit = B_SequenceD_listG_witness;\n    if (!keepends)\n        keepends = B_False;\n    B_list res = $NEW(B_list,NULL,NULL);\n    unsigned char *p = s->str;\n    unsigned char *q = p;\n    int nbytes, codepoint, linelength;\n    if (s->nbytes==0) {\n        return res;\n    }\n    linelength = 0;\n    while (p < s->str + s->nbytes) {\n        nbytes = utf8proc_iterate(p,-1,&codepoint);\n        utf8proc_category_t cat = utf8proc_category(codepoint);\n        if (!islinebreak_codepoint(codepoint)) {\n            linelength++;\n            p += nbytes;\n        } else {\n            // all the codepoints we count as linebreaks are ascii bytes, i.e. nbytes = 1.\n            B_str line;\n            int winend = *p=='\\r' && *(p+1)=='\\n';\n            int size = p-q + (keepends->val ? 1 + winend : 0);\n            NEW_UNFILLED_STR(line,linelength + (keepends->val ? 1 + winend : 0),size);\n            memcpy(line->str,q,size);\n            p += 1 + winend;\n            q = p;\n            wit->$class->append(wit,res,line);\n            linelength = 0;\n        }\n    }\n    if (q < p) {\n        B_str line;\n        NEW_UNFILLED_STR(line,linelength,p-q);\n        memcpy(line->str,q,p-q);\n        wit->$class->append(wit,res,line);\n    }\n    return res;\n}\n\nB_str B_strD_rstrip(B_str s, B_str cs) {\n    if (s->nchars == 0) return s;\n    if (cs==NULL) cs = whitespace_str;\n    unsigned char *p = s->str + s->nbytes;\n    int i, k;\n    for (i = 0; i < s->nchars; i++) {\n        unsigned char *q = cs->str;\n        p = skip_chars(p,-1,0);\n        for (k = 0; k < cs->nchars; k++) {\n            if (equal_bytes(p,q,byte_length2(*q)))\n                break;\n            else\n                q += byte_length2(*q);\n        }\n        if (k == cs->nchars) break;\n    }\n    p = skip_chars(p,1,0);\n    B_str res;\n    NEW_UNFILLED_STR(res,s->nchars-i,p-s->str);\n    memcpy(res->str,s->str,res->nbytes);\n    return res;\n}\n\nB_bool B_strD_startswith(B_str s, B_str sub, B_int start, B_int end) {\n    B_int st = start;\n    B_int en = end;\n    if (fix_start_end(s->nchars,&st,&en) < 0) return B_False;\n    int isascii = s->nchars==s->nbytes;\n    unsigned char *p = skip_chars(s->str,fromB_int(st),isascii);\n    unsigned char *q = sub->str;\n    for (int i=0; i<sub->nbytes; i++) {\n        if (*p == 0 || *p++ != *q++) {\n            return B_False;\n        }\n    }\n    return B_True;\n}\n\n\nB_str B_strD_strip(B_str s, B_str cs) {\n    return B_strD_lstrip(B_strD_rstrip(s,cs),cs);\n}\n\nB_str B_strD_upper(B_str s) {\n    return str_transform(s,utf8proc_toupper);\n}\n\nB_str B_strD_zfill(B_str s, B_int width) {\n    int wval = fromB_int(width);\n    int fill = wval - s->nchars;\n    if (fill < 0)\n        return s;\n    B_str res;\n    NEW_UNFILLED_STR(res,wval,s->nbytes+fill);\n    unsigned char *p = s->str;\n    unsigned char *q = res->str;\n    int hassign = (*p=='+' | *p=='-');\n    if (hassign) {\n        *q = *p;\n        q++;\n    }\n    for (int i=0; i < fill; i++)\n        *q++ = '0';\n    memcpy(res->str+hassign+fill,s->str+hassign,s->nbytes-hassign);\n    return res;\n}\n\n\n\n// Protocol methods; string implementations /////////////////////////////////////////////////////////////////////////////\n/*\n   Note: We make str instances for Indexed and Sliceable even though these protocols\n   include mutating methods.\n*/\n\n// B_Ord ///////////////////////////////////////////////////////////////////////////////////////////////\n\n\n// TODO: We should consider how to normalize strings before comparisons\n\n\n// The comparisons below do lexicographic byte-wise comparisons.\n// Thus they do not in general reflect locale-dependent order conventions.\n\nB_bool B_OrdD_strD___eq__ (B_OrdD_str wit, B_str a, B_str b) {\n    return toB_bool(strcmp((char *)a->str,(char *)b->str) == 0);\n}\n\nB_bool B_OrdD_strD___ne__ (B_OrdD_str wit, B_str a, B_str b) {\n    return toB_bool(strcmp((char *)a->str,(char *)b->str) != 0);\n}\n\nB_bool B_OrdD_strD___lt__ (B_OrdD_str wit, B_str a, B_str b) {\n    return toB_bool(strcmp((char *)a->str,(char *)b->str) < 0);\n}\n\nB_bool B_OrdD_strD___le__ (B_OrdD_str wit, B_str a, B_str b) {\n    return toB_bool(strcmp((char *)a->str,(char *)b->str) <= 0);\n}\n\nB_bool B_OrdD_strD___gt__ (B_OrdD_str wit, B_str a, B_str b) {\n    return toB_bool(strcmp((char *)a->str,(char *)b->str) > 0);\n}\n\nB_bool B_OrdD_strD___ge__ (B_OrdD_str wit, B_str a, B_str b) {\n    return toB_bool(strcmp((char *)a->str,(char *)b->str) >= 0);\n}\n\n// B_Hashable ///////////////////////////////////////////////////////////////////////////////////\n\nB_bool B_HashableD_strD___eq__ (B_HashableD_str wit, B_str a, B_str b) {\n    return toB_bool(strcmp((char *)a->str,(char *)b->str) == 0);\n}\n\nB_bool B_HashableD_strD___ne__ (B_HashableD_str wit, B_str a, B_str b) {\n    return toB_bool(strcmp((char *)a->str,(char *)b->str) != 0);\n}\n\nB_NoneType B_HashableD_strD_hash(B_HashableD_str wit, B_str a, B_hasher h) {\n    zig_hash_wyhash_update(h->_hasher,to$bytes((char *)a->str));\n    return B_None;\n}\n// B_Times /////////////////////////////////////////////////////////////////////////////////////////////\n\nB_str B_TimesD_strD___add__ (B_TimesD_str wit, B_str s, B_str t) {\n    B_str res;\n    NEW_UNFILLED_STR(res,s->nchars + t->nchars,s->nbytes + t->nbytes);\n    memcpy(res->str,s->str,s->nbytes);\n    memcpy(res->str+s->nbytes,t->str,t->nbytes);\n    return res;\n}\n\nB_str B_TimesD_strD___zero__ (B_TimesD_str wit) {\n    return null_str;\n}\n\nB_str B_TimesD_strD___mul__ (B_TimesD_str wit, B_str a, B_int n) {\n    int nval = fromB_int(n);\n    if (nval <= 0)\n        return null_str;\n    else {\n        B_str res;\n        NEW_UNFILLED_STR(res,a->nchars * nval, a->nbytes * nval);\n        for (int i=0; i<nval; i++)\n            memcpy(res->str + i*a->nbytes,a->str,a->nbytes);\n        return res;\n    }\n}\n\n// Collection ///////////////////////////////////////////////////////////////////////////////////////\n\n\nB_str B_ContainerD_strD___fromiter__ (B_ContainerD_str wit, B_Iterable wit2, $WORD iter) {\n    return B_strD_join(null_str,wit2,iter);\n}\n\nB_int B_ContainerD_strD___len__ (B_ContainerD_str wit, B_str s){\n    return  toB_int(s->nchars);\n}\n\n// B_Container ///////////////////////////////////////////////////////////////////////////\n\n\nB_bool B_ContainerD_strD___contains__ (B_ContainerD_str wit, B_str s, B_str sub) {\n    return toB_bool(bmh(s->str,sub->str,s->nbytes,sub->nbytes) >= 0);\n}\n\nB_bool B_ContainerD_strD___containsnot__ (B_ContainerD_str wit, B_str s, B_str sub) {\n    return toB_bool(!B_ContainerD_strD___contains__(wit, s, sub)->val);\n}\n\n// Iterable ///////////////////////////////////////////////////////////////////////////\n\n// first define Iterator class\n\nB_IteratorB_str B_IteratorB_strG_new(B_str str) {\n    return $NEW(B_IteratorB_str, str);\n}\n\nB_NoneType B_IteratorB_strD_init(B_IteratorB_str self, B_str str) {\n    self->src = str;\n    self->nxt = 0;\n    return B_None;\n}\n\nvoid B_IteratorB_strD_serialize(B_IteratorB_str self,$Serial$state state) {\n    $step_serialize(self->src,state);\n    $step_serialize(toB_int(self->nxt),state);\n}\n\n\nB_IteratorB_str B_IteratorB_str$_deserialize(B_IteratorB_str res, $Serial$state state) {\n    if (!res)\n        res = $DNEW(B_IteratorB_str,state);\n    res->src = (B_str)$step_deserialize(state);\n    res->nxt = fromB_int((B_int)$step_deserialize(state));\n    return res;\n}\n\nB_bool B_IteratorB_strD_bool(B_IteratorB_str self) {\n    return B_True;\n}\n\nB_str B_IteratorB_strD_str(B_IteratorB_str self) {\n    return $FORMAT(\"<str iterator object at %p>\", self);\n}\n\n// this is next function for forward iteration\nstatic B_str B_IteratorB_strD_next(B_IteratorB_str self) {\n    unsigned char *p = &self->src->str[self->nxt];\n    if (*p != 0) {\n        self->nxt +=byte_length2(*p);\n        return mk_char(p);\n    }\n    $RAISE ((B_BaseException)$NEW(B_StopIteration, to$str(\"str iterator terminated\")));\n    return NULL; // to avoid compiler warning\n}\n\n\nstruct B_IteratorB_strG_class B_IteratorB_strG_methods = {\"B_IteratorB_str\",UNASSIGNED,($SuperG_class)&B_IteratorG_methods, B_IteratorB_strD_init,\n                                                    B_IteratorB_strD_serialize, B_IteratorB_str$_deserialize,\n                                                    B_IteratorB_strD_bool, B_IteratorB_strD_str, B_IteratorB_strD_str, B_IteratorB_strD_next};\n\n// now, define __iter__\n\nB_Iterator B_ContainerD_strD___iter__ (B_ContainerD_str wit, B_str s) {\n    return (B_Iterator)$NEW(B_IteratorB_str,s);\n}\n\n\n// Indexed ///////////////////////////////////////////////////////////////////////////\n\nB_str B_SliceableD_strD___getitem__ (B_SliceableD_str wit, B_str s, B_int i) {\n    unsigned char *p = s->str;\n    int ix = get_index(fromB_int(i),s->nchars);\n    p = skip_chars(p,ix,s->nchars == s->nbytes);\n    return mk_char(p);\n}\n\nB_NoneType B_SliceableD_strD___setitem__ (B_SliceableD_str wit, B_str str, B_int i, B_str val) {\n    $RAISE((B_BaseException)$NEW(B_NotImplementedError,to$str(\"call to mutating method setitem on string\")));\n    return B_None;\n}\n\nB_NoneType B_SliceableD_strD___delitem__ (B_SliceableD_str wit, B_str str, B_int i) {\n    $RAISE((B_BaseException)$NEW(B_NotImplementedError,to$str(\"call to mutating method delitem on string\")));\n    return B_None;\n}\n\n// Sliceable //////////////////////////////////////////////////////////////////////////////////////\n\nB_str B_SliceableD_strD___getslice__ (B_SliceableD_str wit, B_str s, B_slice slc) {\n    int isascii = s->nchars == s->nbytes;\n    int nchars = s->nchars;\n    int nbytes = 0;\n    int64_t start, stop, step, slen;\n    normalize_slice(slc, nchars, &slen, &start, &stop, &step);\n    if (slen == 0) {\n        return null_str;\n    }\n    if (slen == 1) {\n        return mk_char(skip_chars(s->str, start, isascii));\n    }\n    //slice notation have been eliminated and default values applied.\n    unsigned char buffer[4*slen]; // very conservative buffer size.\n    unsigned char *p = buffer;\n    unsigned char *t = skip_chars(s->str, start, isascii);\n    for (int i=0; i<slen; i++) {\n        int bytes = byte_length2(*t);\n        for (int k=0; k<bytes; k++) {\n            p[nbytes] = *t;\n            t++; nbytes++;\n        }\n        t = skip_chars(t,step-1,isascii);\n    }\n    B_str res;\n    NEW_UNFILLED_STR(res,slen,nbytes);\n    if (nbytes > 0)\n        memcpy(res->str,buffer,nbytes);\n    return res;\n}\n\nB_NoneType B_SliceableD_strD___setslice__ (B_SliceableD_str wit, B_str str, B_Iterable wit2, B_slice slc, $WORD iter) {\n    $RAISE((B_BaseException)$NEW(B_NotImplementedError,to$str(\"call to mutating method setslice on string\")));\n    return B_None;\n}\n\nB_NoneType B_SliceableD_strD___delslice__ (B_SliceableD_str wit, B_str str, B_slice slc) {\n    $RAISE((B_BaseException)$NEW(B_NotImplementedError,to$str(\"call to mutating method delslice on string\")));\n    return B_None;\n}\n\n// End of str implementation ////////////////////////////////////////////////////\n\n// bytearray implementation //////////////////////////////////////////////////////////////////////////////\n\n// Conversion to and from C strings\n\nB_bytearray toB_bytearray(char *str) {\n    B_bytearray res;\n    int len = strlen(str);\n    NEW_UNFILLED_BYTEARRAY(res,len);\n    memcpy(res->str,str,len);\n    return res;\n}\n\n\nB_bytearray to$bytearrayD_len(char *str, int len) {\n    B_bytearray res;\n    NEW_UNFILLED_BYTEARRAY(res, len);\n    memcpy(res->str, str, len);\n    return res;\n}\n\nB_bytearray actBytearrayFromCString(char *str) {\n    B_bytearray res;\n    int len = strlen(str);\n    NEW_UNFILLED_BYTEARRAY(res,len);\n    memcpy(res->str,str,len);\n    return res;\n}\n\nB_bytearray actBytearrayFromCStringNoCopy(char *str) {\n    B_bytearray res = acton_malloc(sizeof(struct B_bytearray));\n    res->$class = &B_bytearrayG_methods;\n    res->nbytes = strlen(str);\n    res->str = (unsigned char*)str;\n    return res;\n}\n\nB_bytearray actBytearrayFromCStringLength(char *str, int len) {\n    B_bytearray res;\n    NEW_UNFILLED_BYTEARRAY(res, len);\n    memcpy(res->str, str, len);\n    return res;\n}\n\nB_bytearray actBytearrayFromCStringLengthNoCopy(char *str, int length) {\n    B_bytearray res = acton_malloc(sizeof(struct B_bytearray));\n    res->$class = &B_bytearrayG_methods;\n    res->nbytes = length;\n    res->str = (unsigned char*)str;\n    return res;\n}\n\nunsigned char *fromB_bytearray(B_bytearray b) {\n    return b->str;\n}\n\n// Auxiliaries\n\nstatic void expand_bytearray(B_bytearray b,int n) {\n    if (b->capacity >= b->nbytes + n)\n        return;\n    int newcapacity = b->capacity==0 ? 1 : b->capacity;\n    while (newcapacity < b->nbytes+n)\n        newcapacity <<= 1;\n    unsigned char *newstr = b->str==NULL\n        ? acton_malloc_atomic(newcapacity+1)\n        : acton_realloc(b->str,newcapacity+1);\n    if (newstr == NULL) {\n        $RAISE((B_BaseException)$NEW(B_MemoryError,to$str(\"memory allocation failed\")));\n    }\n    b->str = newstr;\n    b->capacity = newcapacity;\n}\n\nstatic B_bytearray B_bytearrayD_copy(B_bytearray s) {\n    B_bytearray res;\n    NEW_UNFILLED_BYTEARRAY(res,s->nbytes);\n    res->nbytes = s->nbytes;\n    memcpy(res->str,s->str,s->nbytes);\n    return res;\n}\n\n\n// General methods\n\nB_bytearray B_bytearrayG_new(B_bytes b) {\n    return $NEW(B_bytearray, b);\n}\n\nB_NoneType B_bytearrayD___init__(B_bytearray self, B_bytes b) {\n    int len = b->nbytes;\n    self->nbytes = len;\n    self->capacity = len;\n    self->str = acton_malloc_atomic(len+1);\n    memcpy(self->str,b->str,len+1);\n    return B_None;\n}\n\nB_bool B_bytearrayD___bool__(B_bytearray s) {\n    return toB_bool(s->nbytes > 0);\n};\n\nB_str B_bytearrayD___str__(B_bytearray s) {\n    struct byte_counts bs = byte_count(s->str, s->nbytes);\n    bool use_single_quotes = !(bs.dquotes==0 && bs.squotes>0);\n    int escaped_quotes = use_single_quotes ? bs.dquotes : bs.squotes;\n    int newbytes = 14+bs.escaped+3*bs.non_printable+escaped_quotes+3*bs.non_ascii;\n    B_str res;\n    int nbytes = s->nbytes+newbytes;\n    NEW_UNFILLED_STR(res,nbytes,nbytes);\n    escape_str(res->str+12,s->str,res->nbytes-12,s->nbytes,255,!use_single_quotes,use_single_quotes,false,false);\n    if (use_single_quotes) {\n        res->str[11] = '\\'';\n        res->str[res->nbytes-2] = '\\'';\n    } else {\n        res->str[11] = '\"';\n        res->str[res->nbytes-2] = '\"';\n    }\n    memcpy(res->str, \"bytearray(b\",11);\n    res->str[res->nbytes-1] = ')';\n    return res;\n}\n\nB_str B_bytearrayD___repr__(B_bytearray s) {\n    return B_bytearrayD___str__(s);\n}\n\nvoid B_bytearrayD___serialize__(B_bytearray str,$Serial$state state) {\n    int nWords = str->nbytes/sizeof($WORD) + 1;         // # $WORDS needed to store str->str, including terminating 0.\n    $ROW row = $add_header(BYTEARRAY_ID,1+nWords,state);\n    long nbytes = (long)str->nbytes;\n    memcpy(row->blob,&nbytes,sizeof($WORD));\n    memcpy(row->blob+1,str->str,nbytes+1);\n}\n\nB_bytearray B_bytearrayD___deserialize__(B_bytearray res, $Serial$state state) {\n    $ROW this = state->row;\n    state->row =this->next;\n    state->row_no++;\n    if(!res)\n        res = acton_malloc(sizeof(struct B_bytearray));\n    long nbytes;\n    memcpy(&nbytes,this->blob,sizeof($WORD));\n    res->$class = &B_bytearrayG_methods;\n    res->nbytes = (long)nbytes;\n    res->str = acton_malloc_atomic(nbytes+1);\n    memcpy(res->str,this->blob+1,nbytes+1);\n    return res;\n}\n\n// bytearray methods\n\nB_bytearray B_bytearrayD_capitalize(B_bytearray s) {\n    if (s->nbytes==0) {\n        return toB_bytearray(\"\");\n    }\n    B_bytearray res;\n    NEW_UNFILLED_BYTEARRAY(res,s->nbytes);\n    res->str[0] = toupper(s->str[0]);\n    for (int i=1; i<s->nbytes; i++)\n        res->str[i] = tolower(s->str[i]);\n    return res;\n}\n\nB_bytearray B_bytearrayD_center(B_bytearray s, B_int width, B_bytearray fill) {\n    if (!fill) fill = space_bytearray;\n    if (fill->nbytes != 1) {\n        $RAISE((B_BaseException)$NEW(B_ValueError,to$str(\"center: fill bytearray not single char\")));\n    }\n    int wval = fromB_int(width);\n    if (wval <= s->nbytes) {\n        return B_bytearrayD_copy(s);\n    }\n    int pad = (wval-s->nbytes);\n    int padleft = pad/2;\n    int padright = pad-padleft;\n    int sbytes = s->nbytes;\n    B_bytearray res;\n    NEW_UNFILLED_BYTEARRAY(res, wval);\n    unsigned char c = fill->str[0];\n    unsigned char *p = res->str;\n    p += padleft+sbytes;\n    for (int i = 0; i<padright; i++) {\n        p[i] = c;\n    }\n    memcpy(res->str,p,padleft);\n    p -= sbytes;\n    memcpy(p,s->str,sbytes);\n    return res;\n}\n\nB_int B_bytearrayD_count(B_bytearray s, B_bytearray sub, B_int start, B_int end) {\n    B_int st = start;\n    B_int en = end;\n    if (fix_start_end(s->nbytes,&st,&en) < 0) return toB_int(0);\n    int stval = fromB_int(st);\n    int enval = fromB_int(en);\n    unsigned char *p = &s->str[stval];\n    unsigned char *q = &p[enval-stval];\n    int res = 0;\n    int n = bmh(p,sub->str,q-p,sub->nbytes);\n    while (n>=0) {\n        res++;\n        p += n + (sub->nbytes>0 ? sub->nbytes : 1);\n        n = bmh(p,sub->str,q-p,sub->nbytes);\n    }\n    return toB_int(res);\n}\n\nB_str B_bytearrayD_decode(B_bytearray s) {\n    return to$str((char*)s->str);\n}\n\nB_bool B_bytearrayD_endswith(B_bytearray s, B_bytearray sub, B_int start, B_int end) {\n    B_int st = start;\n    B_int en = end;\n    if (fix_start_end(s->nbytes,&st,&en) < 0) return B_False;\n    int enval = fromB_int(en);\n    unsigned char *p = &s->str[enval-sub->nbytes];\n    unsigned char *q = sub->str;\n    for (int i=0; i<sub->nbytes; i++) {\n        if (*p == 0 || *p++ != *q++) {\n            return B_False;\n        }\n    }\n    return B_True;\n}\n\nB_bytearray B_bytearrayD_expandtabs(B_bytearray s, B_int tabsz){\n    if (s->nbytes == 0) {\n        return toB_bytearray(\"\");\n    }\n    int pos = 0;\n    int expanded = 0;\n    int tabsize = fromB_int(tabsz);\n    tabsize = tabsize <= 0 ? 1 : tabsize;\n    unsigned char buffer[tabsize * s->nbytes];\n    unsigned char *p = s->str;\n    unsigned char *q = buffer;\n    for (int i=0; i<s->nbytes; i++) {\n        if (*p == '\\t') {\n            int n = tabsize - pos % tabsize;\n            for (int j=0; j < n; j++) {\n                *q++ = ' ';\n            }\n            p++;\n            expanded += n-1;\n            pos+=n;\n        } else if (*p=='\\n' || *p == '\\r') {\n            *q++ = *p++;\n            pos = 0;\n        } else {\n            for (int j=0; j< byte_length2(*p); j++) {\n                *q++ = *p++;\n                pos++;\n            }\n        }\n    }\n    B_bytearray res;\n    NEW_UNFILLED_BYTEARRAY(res,s->nbytes+expanded);\n    memcpy(res->str,buffer,s->nbytes+expanded);\n    return res;\n}\n\nB_int B_bytearrayD_find(B_bytearray s, B_bytearray sub, B_int start, B_int end) {\n    B_int st = start;\n    B_int en = end;\n    if (fix_start_end(s->nbytes,&st,&en) < 0) return toB_int(-1);\n    unsigned char *p = &s->str[fromB_int(st)];\n    unsigned char *q = &s->str[fromB_int(en)];\n    int n = bmh(p,sub->str,q-p,sub->nbytes);\n    if (n<0) return toB_int(-1);\n    return toB_int(n+p-s->str);\n}\n\nB_bytearray B_bytearrayD_from_hex(B_str s) {\n    // Each byte is represented by 2 hex chars\n    int strlen = s->nbytes;  // Changed from len to nbytes\n    if (strlen % 2 != 0) {\n        $RAISE((B_BaseException)$NEW(B_ValueError,to$str(\"from_hex: hex string must have even length\")));\n    }\n\n    int bytelen = strlen / 2;\n    char *result = acton_malloc_atomic(bytelen);\n\n    for (int i = 0; i < strlen; i += 2) {\n        char high = s->str[i];\n        char low = s->str[i + 1];\n\n        // Convert hex chars to values 0-15\n        int high_val, low_val;\n\n        // Handle high nibble\n        if (high >= '0' && high <= '9')\n            high_val = high - '0';\n        else if (high >= 'a' && high <= 'f')\n            high_val = high - 'a' + 10;\n        else if (high >= 'A' && high <= 'F')\n            high_val = high - 'A' + 10;\n        else {\n            $RAISE((B_BaseException)$NEW(B_ValueError,to$str(\"from_hex: invalid hex character\")));\n        }\n\n        // Handle low nibble\n        if (low >= '0' && low <= '9')\n            low_val = low - '0';\n        else if (low >= 'a' && low <= 'f')\n            low_val = low - 'a' + 10;\n        else if (low >= 'A' && low <= 'F')\n            low_val = low - 'A' + 10;\n        else {\n            $RAISE((B_BaseException)$NEW(B_ValueError,to$str(\"from_hex: invalid hex character\")));\n        }\n\n        // Combine into byte\n        result[i/2] = (high_val << 4) | low_val;\n    }\n\n    return actBytearrayFromCStringLengthNoCopy(result, bytelen);\n}\n\nB_str B_bytearrayD_hex(B_bytearray s) {\n    // Each byte becomes 2 hex chars, so output length is 2 * number of bytes\n    int len = s->nbytes * 2;\n    char *result = acton_malloc_atomic(len);\n\n    // Hex digit lookup table\n    const char hex_digits[] = \"0123456789abcdef\";\n\n    // Convert each byte to two hex digits\n    for (int i = 0; i < s->nbytes; i++) {\n        unsigned char byte = s->str[i];\n        result[i*2] = hex_digits[byte >> 4];     // High nibble\n        result[i*2 + 1] = hex_digits[byte & 0xf]; // Low nibble\n    }\n\n    // Convert to Acton string without copying\n    return to_str_noc(result);\n}\n\n\nB_int B_bytearrayD_index(B_bytearray s, B_bytearray sub, B_int start, B_int end) {\n    B_int n = B_bytearrayD_find(s,sub,start,end);\n    if (fromB_int(n)<0) {\n        $RAISE((B_BaseException)$NEW(B_ValueError,to$str(\"index: substring not found\")));\n    }\n    return n;\n}\n\nB_bool B_bytearrayD_isalnum(B_bytearray s) {\n    if (s->nbytes==0)\n        return B_False;\n    for (int i=0; i<s->nbytes; i++) {\n        unsigned char c = s->str[i];\n        if (c < '0' || c > 'z' || (c > '9' && c < 'A') || (c > 'Z' && c < 'a'))\n            return B_False;\n    }\n    return B_True;\n}\n\nB_bool B_bytearrayD_isalpha(B_bytearray s) {\n    if (s->nbytes==0)\n        return B_False;\n    for (int i=0; i<s->nbytes; i++) {\n        unsigned char c = s->str[i];\n        if (c < 'A' || c > 'z' || (c > 'Z' && c < 'a'))\n            return B_False;\n    }\n    return B_True;\n}\n\nB_bool B_bytearrayD_isascii(B_bytearray s) {\n    for (int i=0; i<s->nbytes; i++) {\n        unsigned char c = s->str[i];\n        if (c > 0x7f)\n            return B_False;\n    }\n    return B_True;\n}\n\nB_bool B_bytearrayD_isdigit(B_bytearray s) {\n    if (s->nbytes==0)\n        return B_False;\n    for (int i=0; i<s->nbytes; i++) {\n        unsigned char c = s->str[i];\n        if (c<'0' || c > '9')\n            return B_False;\n    }\n    return B_True;\n}\n\n\nB_bool B_bytearrayD_islower(B_bytearray s) {\n    int has_lower = 0;\n    for (int i=0; i < s->nbytes; i++) {\n        unsigned char c = s->str[i];\n        if (c >= 'A' && c <= 'Z')\n            return B_False;\n        if (c >= 'a' && c <= 'z')\n            has_lower = 1;\n    }\n    return toB_bool(has_lower);\n}\n\nB_bool B_bytearrayD_isspace(B_bytearray s) {\n    if (s->nbytes==0)\n        return B_False;\n    for (int i=0; i<s->nbytes; i++) {\n        unsigned char c = s->str[i];\n        if (c !=' ' && c != '\\t' && c != '\\n' && c != '\\r' && c != '\\x0b' && c != '\\f')\n            return B_False;\n    }\n    return B_True;\n}\n\nB_bool B_bytearrayD_istitle(B_bytearray s) {\n    if (s->nbytes==0)\n        return B_False;\n    int incasedrun = 0;\n    for (int i=0; i < s->nbytes; i++) {\n        unsigned char c = s->str[i];\n        if (c >='A' && c <= 'Z') {\n            if (incasedrun)\n                return B_False;\n            incasedrun = 1;\n        } else if (c >='a' && c <= 'z') {\n            if (!incasedrun)\n                return B_False;\n        } else\n            incasedrun = 0;\n    }\n    return B_True;\n}\n\nB_bool B_bytearrayD_isupper(B_bytearray s) {\n    int has_upper = 0;\n    for (int i=0; i < s->nbytes; i++) {\n        unsigned char c = s->str[i];\n        if (c >= 'a' && c <= 'z')\n            return B_False;\n        if (c >= 'a' && c <= 'z')\n            has_upper = 1;\n    }\n    return toB_bool(has_upper);\n}\n\nB_bytearray B_bytearrayD_join(B_bytearray s, B_Iterable wit, $WORD iter) {\n    int totbytes = 0;\n    B_CollectionD_SequenceD_list wit2 = B_CollectionD_SequenceD_listG_witness;\n    B_list lst = wit2->$class->__fromiter__(wit2,wit,iter);\n    B_bytearray nxt;\n    int len = lst->length;\n    for (int i=0; i<len; i++) {\n        nxt = (B_bytearray)lst->data[i];\n        totbytes += nxt->nbytes;\n    }\n    if (len > 1) {\n        totbytes += (len-1) * s->nbytes;\n    }\n    B_bytearray res;\n    NEW_UNFILLED_BYTEARRAY(res,totbytes);\n    if (len > 0) {\n        nxt = (B_bytearray)lst->data[0];\n        unsigned char *p = res->str;\n        memcpy(p,nxt->str,nxt->nbytes);\n        p += nxt->nbytes;\n        for (int i=1; i<len; i++) {\n            nxt = (B_bytearray)lst->data[i];\n            memcpy(p,s->str,s->nbytes);\n            p += s->nbytes;\n            memcpy(p,nxt->str,nxt->nbytes);\n            p += nxt->nbytes;\n        }\n    }\n    return res;\n}\n\nB_bytearray B_bytearrayD_ljust(B_bytearray s, B_int width, B_bytearray fill) {\n    if (!fill)\n        fill = space_bytearray;\n    int wval = fromB_int(width);\n    if (fill->nbytes != 1) {\n        $RAISE((B_BaseException)$NEW(B_ValueError,to$str(\"bytearray ljust: fill array not single char\")));\n    }\n    if (wval <= s->nbytes) {\n        return B_bytearrayD_copy(s);\n    }\n    B_bytearray res;\n    NEW_UNFILLED_BYTEARRAY(res,wval);\n    memcpy(res->str,s->str,s->nbytes);\n    unsigned char c = fill->str[0];\n    for (int i = s->nbytes; i<wval; i++) {\n        res->str[i] = c;\n    }\n    return res;\n}\n\nB_bytearray B_bytearrayD_lower(B_bytearray s) {\n    B_bytearray res;\n    NEW_UNFILLED_BYTEARRAY(res,s->nbytes);\n    for (int i=0; i< s->nbytes; i++)\n        res->str[i] = tolower(res->str[i]);\n    return res;\n}\n\nB_bytearray B_bytearrayD_lstrip(B_bytearray s, B_bytearray cs) {\n    if (!cs)\n        cs = whitespace_bytearray;\n    int nstrip = 0;\n    for (int i=0; i<s->nbytes; i++) {\n        unsigned char c = s->str[i];\n        int found = 0;\n        for (int j=0; j<cs->nbytes; j++)\n            if (c == cs->str[j]) {\n                found = 1;\n                break;\n            }\n        if (!found)\n            break;\n        nstrip++;\n    }\n    B_bytearray res;\n    NEW_UNFILLED_BYTEARRAY(res,s->nbytes-nstrip);\n    memcpy(res->str,s->str+nstrip,res->nbytes);\n    return res;\n}\n\n\nB_tuple B_bytearrayD_partition(B_bytearray s, B_bytearray sep) {\n    int n = fromB_int(B_bytearrayD_find(s,sep,NULL,NULL));\n    if (n<0) {\n        return $NEWTUPLE(3,s,toB_bytearray(\"\"),toB_bytearray(\"\"));\n    } else {\n        int nb = bmh(s->str,sep->str,s->nbytes,sep->nbytes);\n        B_bytearray ls;\n        NEW_UNFILLED_BYTEARRAY(ls,nb);\n        memcpy(ls->str,s->str,nb);\n        B_bytearray rs;\n        int nbr = s->nbytes - sep->nbytes - nb;\n        NEW_UNFILLED_BYTEARRAY(rs,nbr);\n        memcpy(rs->str,s->str+nb+sep->nbytes,nbr);\n        return $NEWTUPLE(3,ls,sep,rs);\n    }\n}\n\n\nB_bytearray B_bytearrayD_replace(B_bytearray s, B_bytearray old, B_bytearray new, B_int count) {\n    if (count==NULL)\n        count = toB_int(INT_MAX);\n    int c = fromB_int(B_bytearrayD_count(s,old,NULL,NULL));\n    int c0 = fromB_int(count) < c ? fromB_int(count) : c;\n    if (c0==0){\n        return B_bytearrayD_copy(s);\n    }\n    int nbytes = s->nbytes + c0*(new->nbytes-old->nbytes);\n    B_bytearray res;\n    NEW_UNFILLED_BYTEARRAY(res,nbytes);\n    unsigned char *p = s->str;\n    unsigned char *q = res->str;\n    unsigned char *pold = old->str;\n    unsigned char *pnew = new->str;\n    int plen = s->nbytes;\n    int n;\n    for (int i=0; i<c0; i++) {\n        n = i>0 && old->nbytes==0 ? 1 : bmh(p,pold,plen,old->nbytes);\n        if (n>0) {\n            memcpy(q,p,n);\n            p+=n; q+=n;\n        }\n        memcpy(q,pnew,new->nbytes);\n        p += old->nbytes;\n        q += new->nbytes;\n        plen -= n+old->nbytes;\n    }\n    if (plen>0)\n        memcpy(q,p,plen);\n    return res;\n}\n\n\nB_int B_bytearrayD_rfind(B_bytearray s, B_bytearray sub, B_int start, B_int end) {\n    B_int st = start;\n    B_int en = end;\n    if (fix_start_end(s->nbytes,&st,&en) < 0) return toB_int(-1);\n    unsigned char *p = &s->str[fromB_int(st)];\n    unsigned char *q = &s->str[fromB_int(en)];\n    int n = rbmh(p,sub->str,q-p,sub->nbytes);\n    if (n<0) return toB_int(-1);\n    return toB_int(n+p-s->str);\n}\n\n\nB_int B_bytearrayD_rindex(B_bytearray s, B_bytearray sub, B_int start, B_int end) {\n    B_int n = B_bytearrayD_rfind(s,sub,start,end);\n    if (fromB_int(n)<0) {\n        $RAISE((B_BaseException)$NEW(B_ValueError,to$str(\"rindex for bytearray: substring not found\")));\n    };\n    return n;\n}\n\nB_bytearray B_bytearrayD_rjust(B_bytearray s, B_int width, B_bytearray fill) {\n    if (!fill)\n        fill = space_bytearray;\n    int wval = fromB_int(width);\n    if (fill->nbytes != 1) {\n        $RAISE((B_BaseException)$NEW(B_ValueError,to$str(\"rjust: fill string not single char\")));\n    }\n    if (wval <= s->nbytes) {\n        return B_bytearrayD_copy(s);\n    }\n    int pad = (wval-s->nbytes);\n    B_bytearray res;\n    NEW_UNFILLED_BYTEARRAY(res,wval);\n    unsigned char c = fill->str[0];\n    for (int i = 0; i<pad; i++) {\n        res->str[i] = c;\n    }\n    memcpy(&res->str[pad],s->str,s->nbytes);\n    return res;\n}\n\nB_tuple B_bytearrayD_rpartition(B_bytearray s, B_bytearray sep) {\n    int n = fromB_int(B_bytearrayD_rfind(s,sep,NULL,NULL));\n    if (n<0) {\n        return $NEWTUPLE(3,toB_bytearray(\"\"),toB_bytearray(\"\"),s);\n    } else {\n        int nb = rbmh(s->str,sep->str,s->nbytes,sep->nbytes);\n        B_bytearray ls;\n        NEW_UNFILLED_BYTEARRAY(ls,nb);\n        memcpy(ls->str,s->str,nb);\n        int nbr = s->nbytes - sep->nbytes - nb;\n        B_bytearray rs;\n        NEW_UNFILLED_BYTEARRAY(rs,nbr);\n        memcpy(rs->str,s->str+nb+sep->nbytes,nbr);\n        return  $NEWTUPLE(3,ls,sep,rs);\n    }\n}\n\nB_bytearray B_bytearrayD_rstrip(B_bytearray s, B_bytearray cs) {\n    if (!cs)\n        cs = whitespace_bytearray;\n    int nstrip = 0;\n    for (int i=s->nbytes-1; i>=0; i--) {\n        unsigned char c = s->str[i];\n        int found = 0;\n        for (int j=0; j<cs->nbytes; j++)\n            if (c == cs->str[j]) {\n                found = 1;\n                break;\n            }\n        if (!found)\n            break;\n        nstrip++;\n    }\n    B_bytearray res;\n    NEW_UNFILLED_BYTEARRAY(res,s->nbytes-nstrip);\n    memcpy(res->str,s->str,res->nbytes);\n    return res;\n}\n \nB_list B_bytearrayD_split(B_bytearray s, B_bytearray sep, B_int maxsplit) {\n    B_list res = $NEW(B_list,NULL,NULL);\n    B_SequenceD_list wit = B_SequenceD_listG_witness;\n    if (maxsplit == NULL || fromB_int(maxsplit) < 0) maxsplit = toB_int(INT_MAX); \n    if (sep == NULL) {\n        unsigned char *p = s->str;\n        if (s->nbytes==0) {\n            return res;\n        }\n        int inword = 0;\n        unsigned char *q;\n        while (p < s->str + s->nbytes) {\n            if  (*p !=' ' && *p != '\\t' && *p != '\\n' && *p != '\\r' && *p != '\\x0b' && *p != '\\f') {\n                if (!inword) {\n                    inword = 1;\n                    q = p;\n                    if (res->length == fromB_int(maxsplit))\n                        break; // we have now removed leading whitespace in remainder\n                }\n            } else {\n                if (inword) {\n                    inword = 0;\n                    B_bytearray word;\n                    NEW_UNFILLED_BYTEARRAY(word,p-q);\n                    memcpy(word->str,q,p-q);\n                    wit->$class->append(wit,res,word);\n                }\n            }\n            p++;\n        }\n        // this if statement should be simplified; almost code duplication.\n        if (p < s->str + s->nbytes) { // we did not break out of the while loop\n            if (inword) {\n                B_bytearray word;\n                NEW_UNFILLED_BYTEARRAY(word,p-q);\n                memcpy(word->str,q,p-q);\n                 wit->$class->append(wit,res,word);\n            }\n        } else {\n            B_bytearray word;\n            p = s->str+s->nbytes;\n            NEW_UNFILLED_BYTEARRAY(word,p-q);\n            memcpy(word->str,q,p-q);\n             wit->$class->append(wit,res,word);\n        }\n        return res;\n    } else { // separator given\n        if (sep->nbytes==0) {\n            $RAISE((B_BaseException)$NEW(B_ValueError,to$str(\"split for bytearray: separator is empty string\")));\n        }\n        if (s->nbytes==0) { // for some unfathomable reason, this is the behaviour of the Python method\n            wit->$class->append(wit,res,toB_bytearray(\"\"));\n            return res;\n        }\n        B_bytearray ls, rs, ssep;\n        rs = s;\n        // Note: This builds many intermediate rs strings...\n        while (rs->nbytes>0 && res->length < fromB_int(maxsplit)) {\n            B_tuple t = B_bytearrayD_partition(rs,sep);\n            ssep = (B_bytearray)t->components[1];\n            rs =  (B_bytearray)t->components[2];\n             wit->$class->append(wit,res,(B_bytearray)t->components[0]);\n        }\n        if (ssep->nbytes>0)\n            wit->$class->append(wit,res,rs);\n        return res;\n    }\n}\n\nB_list B_bytearrayD_splitlines(B_bytearray s, B_bool keepends) {\n    if (!keepends)\n        keepends = B_False;\n    B_SequenceD_list wit = B_SequenceD_listG_witness;\n    B_list res = $NEW(B_list,NULL,NULL);\n    if (s->nbytes==0) {\n        return res;\n    }\n    int winend;\n    unsigned char *p = s->str;\n    unsigned char *q = p;\n    while (p < s->str + s->nbytes) {\n        if (*p != '\\n' && *p != '\\r') {\n            p++;\n        } else {\n            B_bytearray line;\n            winend = *p=='\\r' && *(p+1)=='\\n';\n            int size = p-q + (keepends->val ? 1 + winend : 0);\n            NEW_UNFILLED_BYTEARRAY(line,size);\n            memcpy(line->str,q,size);\n            p+= 1 + winend;\n            q = p;\n            wit->$class->append(wit,res,line);\n        }\n    }\n    if (q < p) {\n        B_bytearray line;\n        NEW_UNFILLED_BYTEARRAY(line,p-q);\n        memcpy(line->str,q,p-q);\n        wit->$class->append(wit,res,line);\n    }\n    return res;\n}\n\nB_bool B_bytearrayD_startswith(B_bytearray s, B_bytearray sub, B_int start, B_int end) {\n    B_int st = start;\n    B_int en = end;\n    if (fix_start_end(s->nbytes,&st,&en) < 0) return B_False;\n    unsigned char *p = s->str + fromB_int(st);\n    if (sub->nbytes > 0 && p+sub->nbytes > s->str+s->nbytes) return B_False;\n    unsigned char *q = sub->str;\n    for (int i=0; i<sub->nbytes; i++) {\n        if (p >= s->str + fromB_int(en) || *p++ != *q++) {\n            return B_False;\n        }\n    }\n    return B_True;\n}\n\n\nB_bytearray B_bytearrayD_strip(B_bytearray s, B_bytearray cs) {\n    return B_bytearrayD_lstrip(B_bytearrayD_rstrip(s,cs),cs);\n}\n\nB_bytearray B_bytearrayD_upper(B_bytearray s) {\n    B_bytearray res;\n    NEW_UNFILLED_BYTEARRAY(res,s->nbytes);\n    for (int i=0; i< s->nbytes; i++)\n        res->str[i] = toupper(res->str[i]);\n    return res;\n}\n\nB_bytearray B_bytearrayD_zfill(B_bytearray s, B_int width) {\n    int wval = fromB_int(width);\n    int fill = wval - s->nbytes;\n    if (fill < 0)\n        return B_bytearrayD_copy(s);\n    B_bytearray res;\n    NEW_UNFILLED_BYTEARRAY(res,wval);\n    unsigned char *p = s->str;\n    unsigned char *q = res->str;\n    int hassign = (*p=='+' | *p=='-');\n    if (hassign) {\n        *q = *p;\n        q++;\n    }\n    for (int i=0; i < fill; i++)\n        *q++ = '0';\n    memcpy(res->str+hassign+fill,s->str+hassign,s->nbytes-hassign);\n    return res;\n}\n\n\n// Ord\n\n\nB_bool B_OrdD_bytearrayD___eq__ (B_OrdD_bytearray wit, B_bytearray a, B_bytearray b) {\n    return toB_bool(strcmp((char *)a->str,(char *)b->str)==0);\n}\n\nB_bool B_OrdD_bytearrayD___ne__ (B_OrdD_bytearray wit, B_bytearray a, B_bytearray b) {\n    return  toB_bool(strcmp((char *)a->str,(char *)b->str)!=0);\n}\n\nB_bool B_OrdD_bytearrayD___lt__ (B_OrdD_bytearray wit, B_bytearray a, B_bytearray b) {\n    return toB_bool(strcmp((char *)a->str,(char *)b->str)<0);\n}\n\nB_bool B_OrdD_bytearrayD___le__ (B_OrdD_bytearray wit, B_bytearray a, B_bytearray b){\n    return toB_bool(strcmp((char *)a->str,(char *)b->str)<=0);\n}\n\nB_bool B_OrdD_bytearrayD___gt__ (B_OrdD_bytearray wit, B_bytearray a, B_bytearray b){\n    return toB_bool(strcmp((char *)a->str,(char *)b->str)>0);\n}\n\nB_bool B_OrdD_bytearrayD___ge__ (B_OrdD_bytearray wit, B_bytearray a, B_bytearray b){\n    return toB_bool(strcmp((char *)a->str,(char *)b->str)>=0);\n}\n\n// Container\n\n// Iterable\n\nstatic B_int B_IteratorB_bytearrayD_next(B_IteratorB_bytearray self) {\n    if (self->nxt >= self->src->nbytes)\n        $RAISE ((B_BaseException)$NEW(B_StopIteration, to$str(\"bytearray iterator terminated\")));\n    return toB_int(self->src->str[self->nxt++]);\n}\n\nB_NoneType B_IteratorB_bytearrayD_init(B_IteratorB_bytearray self, B_bytearray b) {\n    self->src = b;\n    self->nxt = 0;\n    return B_None;\n}\n\nB_bool B_IteratorB_bytearrayD_bool(B_IteratorB_bytearray self) {\n    return B_True;\n}\n\nB_str B_IteratorB_bytearrayD_str(B_IteratorB_bytearray self) {\n    return $FORMAT(\"<bytearray iterator object at %p>\", self);\n}\n\nvoid B_IteratorB_bytearrayD_serialize(B_IteratorB_bytearray self,$Serial$state state) {\n    $step_serialize(self->src,state);\n    $step_serialize(toB_int(self->nxt),state);\n}\n\nB_IteratorB_bytearray B_IteratorB_bytearray$_deserialize(B_IteratorB_bytearray res, $Serial$state state) {\n    if(!res)\n        res = $DNEW(B_IteratorB_bytearray,state);\n    res->src = (B_bytearray)$step_deserialize(state);\n    res->nxt = fromB_int((B_int)$step_deserialize(state));\n    return res;\n}\n\nstruct B_IteratorB_bytearrayG_class B_IteratorB_bytearrayG_methods = {\n    \"\",\n    UNASSIGNED,\n    ($SuperG_class)&B_IteratorG_methods,\n    B_IteratorB_bytearrayD_init,\n    B_IteratorB_bytearrayD_serialize,\n    B_IteratorB_bytearray$_deserialize,\n    B_IteratorB_bytearrayD_bool,\n    B_IteratorB_bytearrayD_str,\n    B_IteratorB_bytearrayD_str,\n    B_IteratorB_bytearrayD_next\n};\n\nB_Iterator B_ContainerD_bytearrayD___iter__ (B_ContainerD_bytearray wit, B_bytearray str) {\n    return (B_Iterator)$NEW(B_IteratorB_bytearray,str);\n}\n\nB_bytearray B_ContainerD_bytearrayD___fromiter__ (B_ContainerD_bytearray wit, B_Iterable wit2, $WORD iter) {\n    return B_bytearrayD_join(toB_bytearray(\"\"),wit2,iter);\n}\n\nB_int B_ContainerD_bytearrayD___len__ (B_ContainerD_bytearray wit, B_bytearray str) {\n    return  toB_int(str->nbytes);\n}\n\nB_bool B_ContainerD_bytearrayD___contains__(B_ContainerD_bytearray wit, B_bytearray self, B_int n) {\n    long res = 0;\n    for (int i=0; i < self->nbytes; i++) {\n        if (self->str[i] == (unsigned char)fromB_int(n)) {\n            res = 1;\n            break;\n        }\n    }\n    return toB_bool(res);\n}\n\nB_bool B_ContainerD_bytearrayD___containsnot__(B_ContainerD_bytearray wit, B_bytearray self, B_int n) {\n    return  toB_bool(!B_ContainerD_bytearrayD___contains__(wit,self,n)->val);\n}\n\n// Sequence\n\nB_int B_SequenceD_bytearrayD___getitem__ (B_SequenceD_bytearray wit, B_bytearray self, B_int n) {\n    int64_t ix = fromB_int(n);\n    int64_t ix0 = ix < 0 ? self->nbytes + ix : ix;\n    if (ix0<0 || ix0 >= self->nbytes)\n        $RAISE((B_BaseException)$NEW(B_IndexError, toB_int(ix0), to$str(\"getitem: index outside bytearray\")));\n    return toB_int((long)self->str[ix0]);\n}\n\nB_NoneType B_SequenceD_bytearrayD___setitem__ (B_SequenceD_bytearray wit, B_bytearray self, B_int n, B_int v) {\n    int64_t ix = fromB_int(n);\n    int64_t ix0 = ix < 0 ? self->nbytes + ix : ix;\n   long val = fromB_int(v);\n    if (ix0<0 || ix0 >= self->nbytes)\n        $RAISE((B_BaseException)$NEW(B_IndexError, toB_int(ix0), to$str(\"setitem: index outside bytearray\")));\n    if (val<0 || val>255)\n        $RAISE((B_BaseException)$NEW(B_ValueError,to$str(\"setitem for bytearray: value outside [0..255]\")));\n    self->str[ix0] = (unsigned char)val;\n    return B_None;\n}\n\nB_NoneType B_SequenceD_bytearrayD___delitem__ (B_SequenceD_bytearray wit, B_bytearray self, B_int n) {\n    int64_t ix = fromB_int(n);\n    int64_t ix0 = ix < 0 ? self->nbytes + ix : ix;\n    int len = self->nbytes;\n    if (ix0 < 0 || ix0 >= len)\n        $RAISE((B_BaseException)$NEW(B_IndexError, toB_int(ix0), to$str(\"delitem: index outside bytearray\")));\n    memmove(self->str + ix0,self->str + (ix0 + 1),len-(ix0+1));\n    self->nbytes--;\n    return B_None;\n}\n\nB_NoneType B_SequenceD_bytearrayD_insert(B_SequenceD_bytearray wit, B_bytearray self, B_int n, B_int elem) {\n    long ix = fromB_int(n);\n    int len = self->nbytes;\n    expand_bytearray(self,1);\n    int ix0 = ix < 0 ? (len+ix < 0 ? 0 : len+ix) : (ix < len ? ix : len);\n    memmove(self->str + (ix0 + 1),\n            self->str + ix0 ,\n            len - ix0 + 1); // +1 to move also terminating '\\0'\n    self->str[ix0] = (unsigned char)fromB_int(elem) & 0xff;\n    self->nbytes++;\n    return B_None;\n}\n\nB_NoneType B_SequenceD_bytearrayD_append(B_SequenceD_bytearray wit, B_bytearray self, B_int elem) {\n    expand_bytearray(self,1);\n    self->str[self->nbytes++] = (unsigned char)fromB_int(elem) & 0xff;\n    self->str[self->nbytes] = '\\0';\n    return B_None;\n}\n\nB_NoneType B_SequenceD_bytearrayD_reverse(B_SequenceD_bytearray wit, B_bytearray self) {\n    int len = self->nbytes;\n    for (int i = 0; i < len/2; i++) {\n        unsigned char tmp = self->str[i];\n        self->str[i] = self->str[len-1-i];\n        self->str[len-1-i] = tmp;\n    }\n    return B_None;\n}\n\nB_Iterator B_SequenceD_bytearrayD___reversed__(B_SequenceD_bytearray wit, B_bytearray self) {\n    B_bytearray copy = B_bytearrayD_copy(self);\n    B_SequenceD_bytearrayD_reverse(wit,copy);\n    return B_ContainerD_bytearrayD___iter__ (NULL, copy);\n}\n\nB_bytearray B_SequenceD_bytearrayD___getslice__ (B_SequenceD_bytearray wit, B_bytearray self, B_slice slc) {\n    int len = self->nbytes;\n    int64_t start, stop, step, slen;\n    normalize_slice(slc, len, &slen, &start, &stop, &step);\n    B_bytearray res;\n    NEW_UNFILLED_BYTEARRAY(res,slen);\n    long t = start;\n    for (int i=0; i<slen; i++) {\n        B_int w = B_SequenceD_bytearrayD___getitem__(wit, self, toB_int(t));\n        B_SequenceD_bytearrayD___setitem__(wit, res , toB_int(i), w);\n        t += step;\n    }\n    return res;\n}\n\nB_NoneType B_SequenceD_bytearrayD___setslice__ (B_SequenceD_bytearray wit,  B_bytearray self, B_Iterable wit2, B_slice slc, $WORD iter) {\n    B_Iterator it = wit2->$class->__iter__(wit2,iter);\n    int len = self->nbytes;\n    B_bytearray other;\n    NEW_UNFILLED_BYTEARRAY(other,0);\n    $WORD w;\n    while ((w=it->$class->__next__(it)))\n        B_SequenceD_bytearrayD_append(wit, other,(B_int)w);\n    int olen = other->nbytes; \n    int64_t start, stop, step, slen;\n    normalize_slice(slc, len, &slen, &start, &stop, &step);\n    if (step != 1 && olen != slen) {\n        $RAISE((B_BaseException)$NEW(B_ValueError,to$str(\"setslice for bytearray: illegal slice\")));\n    }\n    int copy = olen <= slen ? olen : slen;\n    int t = start;\n    for (int i= 0; i<copy; i++) {\n        self->str[t] = other->str[i];\n        t += step;\n    }\n    if (olen == slen)\n        return B_None;\n    // now we know that step=1\n    if (olen < slen) {\n        memmove(self->str + start + copy,\n                self->str + start + slen,\n                len-(start+slen));\n        self->nbytes-=slen-olen;\n        return B_None;\n    } else {\n        expand_bytearray(self,olen-slen);\n        int rest = len - (start+copy);\n        int incr = olen - slen;\n        memmove(self->str + start + copy + incr,\n                self->str + start + copy,\n                rest);\n        for (int i = copy; i < olen; i++)\n            self->str[start+i] = other->str[i];\n        self->nbytes += incr;\n    }\n    return B_None;\n}\n\nB_NoneType B_SequenceD_bytearrayD___delslice__ (B_SequenceD_bytearray wit,  B_bytearray self, B_slice slc) {\n    int len = self->nbytes;\n    int64_t start, stop, step, slen;\n    normalize_slice(slc, len, &slen, &start, &stop, &step);\n    if (slen==0) return B_None;\n    unsigned char *p = self->str + start;\n    for (int i=0; i<slen-1; i++) {\n        memmove(p,p+i+1,step-1);\n        p+=step-1;\n    }\n    memmove(p,p+slen,len-1-(start+step*(slen-1)));\n    self->nbytes-=slen;\n    self->str[self->nbytes] = '\\0';\n    return B_None;\n}\n\n// Collection\n\n\nB_Iterator B_CollectionD_SequenceD_bytearrayD___iter__ (B_CollectionD_SequenceD_bytearray wit, B_bytearray str) {\n    return (B_Iterator)$NEW(B_IteratorB_bytearray,str);\n}\n\nB_bytearray B_CollectionD_SequenceD_bytearrayD___fromiter__ (B_CollectionD_SequenceD_bytearray wit, B_Iterable wit2, $WORD iter) {\n    return B_bytearrayD_join(toB_bytearray(\"\"),wit2,iter);\n}\n\nB_int B_CollectionD_SequenceD_bytearrayD___len__ (B_CollectionD_SequenceD_bytearray wit, B_bytearray str) {\n    return  toB_int(str->nbytes);\n}\n\n// Times\n\nB_bytearray B_TimesD_SequenceD_bytearrayD___add__ (B_TimesD_SequenceD_bytearray wit, B_bytearray a, B_bytearray b) {\n    B_bytearray res;\n    NEW_UNFILLED_BYTEARRAY(res,a->nbytes+b->nbytes);\n    memcpy(res->str,a->str,a->nbytes);\n    memcpy(res->str+a->nbytes,b->str,b->nbytes);\n    return res;\n}\n\nB_bytearray B_TimesD_SequenceD_bytearrayD___zero__ (B_TimesD_SequenceD_bytearray wit) {\n    return toB_bytearray(\"\");\n}\n\nB_bytearray B_TimesD_SequenceD_bytearrayD___mul__ (B_TimesD_SequenceD_bytearray wit, B_bytearray a, B_int n) {\n    int nval = fromB_int(n);\n    if (nval <= 0)\n        return toB_bytearray(\"\");\n    else {\n        B_bytearray res;\n        NEW_UNFILLED_BYTEARRAY(res, a->nbytes * nval);\n        for (int i=0; i<nval; i++)\n            memcpy(res->str + i*a->nbytes,a->str,a->nbytes);\n        return res;\n    }\n}\n\n// End of bytearray implementation ////////////////////////////////////////////////\n\n\n\n// bytes implementation ///////////////////////////////////////////////////////////\n\n\n// Conversion to and from C strings\n\nB_bytes to$bytes(char *str) {\n    B_bytes res;\n    int len = strlen(str);\n    NEW_UNFILLED_BYTES(res,len);\n    memcpy(res->str,str,len);\n    return res;\n}\n\nB_bytes to$bytesD_len(char *str, int len) {\n    B_bytes res;\n    NEW_UNFILLED_BYTES(res, len);\n    memcpy(res->str, str, len);\n    return res;\n}\n\nB_bytes actBytesFromCString(char *str) {\n    B_bytes res;\n    int len = strlen(str);\n    NEW_UNFILLED_BYTES(res,len);\n    memcpy(res->str,str,len);\n    return res;\n}\n\nB_bytes actBytesFromCStringNoCopy(char *str) {\n    B_bytes res = acton_malloc(sizeof(struct B_bytes));\n    res->$class = &B_bytesG_methods;\n    res->nbytes = strlen(str);\n    res->str =  (unsigned char*)str;\n    return res;\n}\n\nB_bytes actBytesFromCStringLength(char *str, int len) {\n    B_bytes res;\n    NEW_UNFILLED_BYTES(res, len);\n    memcpy(res->str, str, len);\n    return res;\n}\n\nB_bytes actBytesFromCStringLengthNoCopy(char *str, int length) {\n    B_bytes res = acton_malloc(sizeof(struct B_bytes));\n    res->$class = &B_bytesG_methods;\n    res->nbytes = length;\n    res->str =  (unsigned char*)str;\n    return res;\n}\n\nunsigned char *fromB_bytes(B_bytes b) {\n    return b->str;\n}\n\n// Auxiliaries\n\nstatic B_bytes B_bytesD_copy(B_bytes s) {\n    B_bytes res;\n    NEW_UNFILLED_BYTES(res,s->nbytes);\n    res->nbytes = s->nbytes;\n    memcpy(res->str,s->str,s->nbytes);\n    return res;\n}\n\n\n\n// Bytes methods, implementations\n\n// General methods //////////////////////////////////////////////////////////////\n\nB_bytes B_bytesG_new(B_Iterable iter, $WORD wit) {\n    return $NEW(B_bytes, iter, wit);\n}\n\nB_NoneType B_bytesD___init__(B_bytes self, B_Iterable wit, $WORD iter) {\n    B_CollectionD_SequenceD_list wit2 = B_CollectionD_SequenceD_listG_witness;\n    B_list lst = wit2->$class->__fromiter__(wit2,wit,iter);\n    int len = lst->length;\n    self->nbytes = len;\n    self->str = acton_malloc_atomic(len+1);\n    self->str[len] = 0;\n    for (int i=0; i< len; i++) {\n        int n = fromB_int((B_int)lst->data[i]);\n        if (0<=n && n <= 255)\n            self->str[i] = n;\n        else\n            $RAISE((B_BaseException)$NEW(B_ValueError,to$str(\"bytes constructor: element outside [0..255]\")));\n    }\n    return B_None;\n}\n\nB_bool B_bytesD___bool__(B_bytes s) {\n    return toB_bool(s->nbytes > 0);\n};\n\nB_str B_bytesD___str__(B_bytes s) {\n    struct byte_counts bs = byte_count(s->str, s->nbytes);\n    bool use_single_quotes = !(bs.dquotes==0 && bs.squotes>0);\n    int escaped_quotes = use_single_quotes ? bs.dquotes : bs.squotes;\n    int newbytes = 3+bs.escaped+3*bs.non_printable+escaped_quotes+3*bs.non_ascii;\n    B_str res;\n    int nbytes = s->nbytes+newbytes;\n    NEW_UNFILLED_STR(res,nbytes,nbytes);\n    escape_str(res->str+2,s->str,res->nbytes-2,s->nbytes,255,!use_single_quotes,use_single_quotes,false,false);\n    if (use_single_quotes) {\n        res->str[1] = '\\'';\n        res->str[res->nbytes-1] = '\\'';\n    } else {\n        res->str[1] = '\"';\n        res->str[res->nbytes-1] = '\"';\n    }\n    res->str[0] = 'b';\n    return res;\n}\n\nB_str B_bytesD___repr__(B_bytes s) {\n    return  B_bytesD___str__(s);\n}\n\nvoid B_bytesD___serialize__(B_bytes str,$Serial$state state) {\n    int nWords = str->nbytes/sizeof($WORD) + 1;         // # $WORDS needed to store str->str, including terminating 0.\n    $ROW row = $add_header(STR_ID,1+nWords,state);\n    long nbytes = (long)str->nbytes;\n    memcpy(row->blob,&nbytes,sizeof($WORD));\n    memcpy(row->blob+1,str->str,nbytes+1);\n}\n\nB_bytes B_bytesD___deserialize__(B_bytes self, $Serial$state state) {\n    $ROW this = state->row;\n    state->row =this->next;\n    state->row_no++;\n    B_bytes res = acton_malloc(sizeof(struct B_bytes));\n    long nbytes;\n    memcpy(&nbytes,this->blob,sizeof($WORD));\n    res->$class = &B_bytesG_methods;\n    res->nbytes = (long)nbytes;\n    res->str = acton_malloc_atomic(nbytes+1);\n    memcpy(res->str,this->blob+2,nbytes+1);\n    return res;\n}\n\nB_bytes B_bytesD_capitalize(B_bytes s) {\n    if (s->nbytes==0) {\n        return s;\n    }\n    B_bytes res;\n    NEW_UNFILLED_BYTES(res,s->nbytes);\n    res->str[0] = toupper(s->str[0]);\n    for (int i = 1; i < s->nbytes; i++)\n        res->str[i] = tolower(s->str[i]);\n    return res;\n}\n\nB_bytes B_bytesD_center(B_bytes s, B_int width, B_bytes fill) {\n    int wval = fromB_int(width);\n    if (!fill) fill = to$bytes(\" \");\n    if (fill->nbytes != 1) {\n        $RAISE((B_BaseException)$NEW(B_ValueError,to$str(\"center: fill bytes not single char\")));\n    }\n    if (wval <= s->nbytes) {\n        return s;\n    }\n    int pad = (wval-s->nbytes);\n    int padleft = pad/2;\n    int padright = pad-padleft;\n    int sbytes = s->nbytes;\n    B_bytes res;\n    NEW_UNFILLED_BYTES(res, wval);\n    unsigned char c = fill->str[0];\n    unsigned char *p = res->str;\n    p += padleft+sbytes;\n    for (int i = 0; i<padright; i++) {\n        p[i] = c;\n    }\n    memcpy(res->str,p,padleft);\n    p -= sbytes;\n    memcpy(p,s->str,sbytes);\n    return res;\n}\n\nB_int B_bytesD_count(B_bytes s, B_bytes sub, B_int start, B_int end) {\n    B_int st = start;\n    B_int en = end;\n    if (fix_start_end(s->nbytes,&st,&en) < 0) return toB_int(0);\n    int stval = fromB_int(st);\n    unsigned char *p = &s->str[stval];\n    unsigned char *q = &p[fromB_int(en)-stval];\n    int res = 0;\n    int n = bmh(p,sub->str,q-p,sub->nbytes);\n    while (n>=0) {\n        res++;\n        p += n + (sub->nbytes>0 ? sub->nbytes : 1);\n        n = bmh(p,sub->str,q-p,sub->nbytes);\n    }\n    return toB_int(res);\n}\n\nB_str B_bytesD_decode(B_bytes s) {\n    return to$str((char*)s->str);\n}\n\nB_bool B_bytesD_endswith(B_bytes s, B_bytes sub, B_int start, B_int end) {\n    B_int st = start;\n    B_int en = end;\n    if (fix_start_end(s->nbytes,&st,&en) < 0) return B_False;\n    unsigned char *p = &s->str[fromB_int(en)-sub->nbytes];\n    unsigned char *q = sub->str;\n    for (int i=0; i<sub->nbytes; i++) {\n        if (*p == 0 || *p++ != *q++) {\n            return B_False;\n        }\n    }\n    return B_True;\n}\n\nB_bytes B_bytesD_expandtabs(B_bytes s, B_int tabsz){\n    if (s->nbytes == 0) {\n        return null_bytes;\n    }\n    int pos = 0;\n    int expanded = 0;\n    int tabsize = fromB_int(tabsz);\n    tabsize = tabsize <= 0 ? 1 : tabsize;\n    unsigned char buffer[tabsize * s->nbytes];\n    unsigned char *p = s->str;\n    unsigned char *q = buffer;\n    for (int i=0; i<s->nbytes; i++) {\n        if (*p == '\\t') {\n            int n = tabsize - pos % tabsize;\n            for (int j=0; j < n; j++) {\n                *q++ = ' ';\n            }\n            p++;\n            expanded += n-1;\n            pos+=n;\n        } else if (*p=='\\n' || *p == '\\r') {\n            *q++ = *p++;\n            pos = 0;\n        } else {\n            for (int j=0; j< byte_length2(*p); j++) {\n                *q++ = *p++;\n                pos++;\n            }\n        }\n    }\n    B_bytes res;\n    NEW_UNFILLED_BYTES(res,s->nbytes+expanded);\n    memcpy(res->str,buffer,s->nbytes+expanded);\n    return res;\n}\n\nB_int B_bytesD_find(B_bytes s, B_bytes sub, B_int start, B_int end) {\n    B_int st = start;\n    B_int en = end;\n    if (fix_start_end(s->nbytes,&st,&en) < 0) return toB_int(-1);\n    unsigned char *p = &s->str[fromB_int(st)];\n    unsigned char *q = &s->str[fromB_int(en)];\n    int n = bmh(p,sub->str,q-p,sub->nbytes);\n    if (n<0) return toB_int(-1);\n    return toB_int(n+p-s->str);\n}\n\nB_bytes B_bytesD_from_hex(B_str s) {\n    if (s->nbytes == 0)\n        return null_bytes;\n    // Each byte is represented by 2 hex chars\n    int strlen = s->nbytes;  // Changed from len to nbytes\n    if (strlen % 2 != 0) {\n        $RAISE((B_BaseException)$NEW(B_ValueError,to$str(\"from_hex: hex string must have even length\")));\n    }\n\n    int bytelen = strlen / 2;\n    char *result = acton_malloc_atomic(bytelen);\n\n    for (int i = 0; i < strlen; i += 2) {\n        char high = s->str[i];\n        char low = s->str[i + 1];\n\n        // Convert hex chars to values 0-15\n        int high_val, low_val;\n\n        // Handle high nibble\n        if (high >= '0' && high <= '9')\n            high_val = high - '0';\n        else if (high >= 'a' && high <= 'f')\n            high_val = high - 'a' + 10;\n        else if (high >= 'A' && high <= 'F')\n            high_val = high - 'A' + 10;\n        else {\n            $RAISE((B_BaseException)$NEW(B_ValueError,to$str(\"from_hex: invalid hex character\")));\n        }\n\n        // Handle low nibble\n        if (low >= '0' && low <= '9')\n            low_val = low - '0';\n        else if (low >= 'a' && low <= 'f')\n            low_val = low - 'a' + 10;\n        else if (low >= 'A' && low <= 'F')\n            low_val = low - 'A' + 10;\n        else {\n            $RAISE((B_BaseException)$NEW(B_ValueError,to$str(\"from_hex: invalid hex character\")));\n        }\n\n        // Combine into byte\n        result[i/2] = (high_val << 4) | low_val;\n    }\n\n    return actBytesFromCStringLengthNoCopy(result, bytelen);\n}\n\nB_str B_bytesD_hex(B_bytes s) {\n    if (s->nbytes == 0)\n        return null_str;\n    // Each byte becomes 2 hex chars, so output length is 2 * number of bytes\n    int len = s->nbytes * 2;\n    char *result = acton_malloc_atomic(len);\n\n    // Hex digit lookup table\n    const char hex_digits[] = \"0123456789abcdef\";\n\n    // Convert each byte to two hex digits\n    for (int i = 0; i < s->nbytes; i++) {\n        unsigned char byte = s->str[i];\n        result[i*2] = hex_digits[byte >> 4];     // High nibble\n        result[i*2 + 1] = hex_digits[byte & 0xf]; // Low nibble\n    }\n\n    // Convert to Acton string without copying\n    return to_str_noc(result);\n}\n\nB_int B_bytesD_index(B_bytes s, B_bytes sub, B_int start, B_int end) {\n    B_int n = B_bytesD_find(s,sub,start,end);\n    if (fromB_int(n)<0) {\n        $RAISE((B_BaseException)$NEW(B_ValueError,to$str(\"index: substring not found\")));\n    }\n    return n;\n}\n\nB_bool B_bytesD_isalnum(B_bytes s) {\n    if (s->nbytes==0)\n        return B_False;\n    for (int i=0; i<s->nbytes; i++) {\n        unsigned char c = s->str[i];\n        if (c < '0' || c > 'z' || (c > '9' && c < 'A') || (c > 'Z' && c < 'a'))\n            return B_False;\n    }\n    return B_True;\n}\n\nB_bool B_bytesD_isalpha(B_bytes s) {\n    if (s->nbytes==0)\n        return B_False;\n    for (int i=0; i<s->nbytes; i++) {\n        unsigned char c = s->str[i];\n        if (c < 'A' || c > 'z' || (c > 'Z' && c < 'a'))\n            return B_False;\n    }\n    return B_True;\n}\n\nB_bool B_bytesD_isascii(B_bytes s) {\n    for (int i=0; i<s->nbytes; i++) {\n        unsigned char c = s->str[i];\n        if (c > 0x7f)\n            return B_False;\n    }\n    return B_True;\n}\n\nB_bool B_bytesD_isdigit(B_bytes s) {\n    if (s->nbytes==0)\n        return B_False;\n    for (int i=0; i<s->nbytes; i++) {\n        unsigned char c = s->str[i];\n        if (c<'0' || c > '9')\n            return B_False;\n    }\n    return B_True;\n}\n\n\nB_bool B_bytesD_islower(B_bytes s) {\n    int has_lower = 0;\n    for (int i=0; i < s->nbytes; i++) {\n        unsigned char c = s->str[i];\n        if (c >= 'A' && c <= 'Z')\n            return B_False;\n        if (c >= 'a' && c <= 'z')\n            has_lower = 1;\n    }\n    return toB_bool(has_lower);\n}\n\nB_bool B_bytesD_isspace(B_bytes s) {\n    if (s->nbytes==0)\n        return B_False;\n    for (int i=0; i<s->nbytes; i++) {\n        unsigned char c = s->str[i];\n        if (c !=' ' && c != '\\t' && c != '\\n' && c != '\\r' && c != '\\x0b' && c != '\\f')\n            return B_False;\n    }\n    return B_True;\n}\n\nB_bool B_bytesD_istitle(B_bytes s) {\n    if (s->nbytes==0)\n        return B_False;\n    int incasedrun = 0;\n    for (int i=0; i < s->nbytes; i++) {\n        unsigned char c = s->str[i];\n        if (c >='A' && c <= 'Z') {\n            if (incasedrun)\n                return B_False;\n            incasedrun = 1;\n        } else if (c >='a' && c <= 'z') {\n            if (!incasedrun)\n                return B_False;\n        } else\n            incasedrun = 0;\n    }\n    return B_True;\n}\n\nB_bool B_bytesD_isupper(B_bytes s) {\n    int has_upper = 0;\n    for (int i=0; i < s->nbytes; i++) {\n        unsigned char c = s->str[i];\n        if (c >= 'a' && c <= 'z')\n            return B_False;\n        if (c >= 'a' && c <= 'z')\n            has_upper = 1;\n    }\n    return toB_bool(has_upper);\n}\n\nB_bytes B_bytesD_join(B_bytes s, B_Iterable wit, $WORD iter) {\n    int totbytes = 0;\n    B_CollectionD_SequenceD_list wit2 = B_CollectionD_SequenceD_listG_witness;\n    B_list lst = wit2->$class->__fromiter__(wit2,wit,iter);\n    B_bytes nxt;\n    int len = lst->length;\n    for (int i=0; i<len; i++) {\n        nxt = (B_bytes)lst->data[i];\n        totbytes += nxt->nbytes;\n    }\n    if (len > 1) {\n        totbytes += (len-1) * s->nbytes;\n    }\n    B_bytes res;\n    NEW_UNFILLED_BYTES(res,totbytes);\n    if (len > 0) {\n        nxt = (B_bytes)lst->data[0];\n        unsigned char *p = res->str;\n        memcpy(p,nxt->str,nxt->nbytes);\n        p += nxt->nbytes;\n        for (int i=1; i<len; i++) {\n            nxt = (B_bytes)lst->data[i];\n            memcpy(p,s->str,s->nbytes);\n            p += s->nbytes;\n            memcpy(p,nxt->str,nxt->nbytes);\n            p += nxt->nbytes;\n        }\n    }\n    return res;\n}\n\nB_bytes B_bytesD_ljust(B_bytes s, B_int width, B_bytes fill) {\n    if (!fill)\n        fill = space_bytes;\n    int wval = fromB_int(width);\n    if (fill->nbytes != 1) {\n        $RAISE((B_BaseException)$NEW(B_ValueError,to$str(\"bytes ljust: fill array not single char\")));\n    }\n    if (wval <= s->nbytes) {\n        return B_bytesD_copy(s);\n    }\n    B_bytes res;\n    NEW_UNFILLED_BYTES(res,wval);\n    memcpy(res->str,s->str,s->nbytes);\n    unsigned char c = fill->str[0];\n    for (int i = s->nbytes; i<wval; i++) {\n        res->str[i] = c;\n    }\n    return res;\n}\n\nB_bytes B_bytesD_lower(B_bytes s) {\n    B_bytes res;\n    NEW_UNFILLED_BYTES(res,s->nbytes);\n    for (int i=0; i< s->nbytes; i++)\n        res->str[i] = tolower(res->str[i]);\n    return res;\n}\n\nB_bytes B_bytesD_lstrip(B_bytes s, B_bytes cs) {\n    if (!cs)\n        cs = whitespace_bytes;\n    int nstrip = 0;\n    for (int i=0; i<s->nbytes; i++) {\n        unsigned char c = s->str[i];\n        int found = 0;\n        for (int j=0; j<cs->nbytes; j++)\n            if (c == cs->str[j]) {\n                found = 1;\n                break;\n            }\n        if (!found)\n            break;\n        nstrip++;\n    }\n    B_bytes res;\n    NEW_UNFILLED_BYTES(res,s->nbytes-nstrip);\n    memcpy(res->str,s->str+nstrip,res->nbytes);\n    return res;\n}\n\n\nB_tuple B_bytesD_partition(B_bytes s, B_bytes sep) {\n    int n = fromB_int(B_bytesD_find(s,sep,NULL,NULL));\n    if (n<0) {\n        return $NEWTUPLE(3,s,to$bytes(\"\"),to$bytes(\"\"));\n    } else {\n        int nb = bmh(s->str,sep->str,s->nbytes,sep->nbytes);\n        B_bytes ls;\n        NEW_UNFILLED_BYTES(ls,nb);\n        memcpy(ls->str,s->str,nb);\n        B_bytes rs;\n        int nbr = s->nbytes - sep->nbytes - nb;\n        NEW_UNFILLED_BYTES(rs,nbr);\n        memcpy(rs->str,s->str+nb+sep->nbytes,nbr);\n        return $NEWTUPLE(3,ls,sep,rs);\n    }\n}\n\n\nB_bytes B_bytesD_removeprefix(B_bytes s, B_bytes prefix) {\n    int bytes_to_remove;\n    if (prefix->nbytes > s->nbytes || memcmp(s->str,prefix->str,prefix->nbytes))\n        bytes_to_remove = 0;\n    else\n        bytes_to_remove = prefix->nbytes;\n    B_bytes res;\n    int resbytes = s->nbytes - bytes_to_remove;\n    NEW_UNFILLED_BYTES(res,resbytes);\n    memcpy(res->str,s->str+bytes_to_remove,resbytes);\n    return res;\n}\n\nB_bytes B_bytesD_removesuffix(B_bytes s, B_bytes suffix) {\n    int bytes_to_remove;\n    if (suffix->nbytes > s->nbytes || memcmp(s->str+s->nbytes-suffix->nbytes,suffix->str,suffix->nbytes))\n        bytes_to_remove = 0;\n    else\n        bytes_to_remove = suffix->nbytes;\n    B_bytes res;\n    int resbytes = s->nbytes - bytes_to_remove;\n    NEW_UNFILLED_BYTES(res,resbytes);\n    memcpy(res->str,s->str,resbytes);\n    return res;\n}\nB_bytes B_bytesD_replace(B_bytes s, B_bytes old, B_bytes new, B_int count) {\n    if (count==NULL)\n        count = toB_int(INT_MAX);\n    int c = fromB_int(B_bytesD_count(s,old,NULL,NULL));\n    int c0 = fromB_int(count) < c ? fromB_int(count) : c;\n    if (c0==0){\n        return B_bytesD_copy(s);\n    }\n    int nbytes = s->nbytes + c0*(new->nbytes-old->nbytes);\n    B_bytes res;\n    NEW_UNFILLED_BYTES(res,nbytes);\n    unsigned char *p = s->str;\n    unsigned char *q = res->str;\n    unsigned char *pold = old->str;\n    unsigned char *pnew = new->str;\n    int plen = s->nbytes;\n    int n;\n    for (int i=0; i<c0; i++) {\n        n = i>0 && old->nbytes==0 ? 1 : bmh(p,pold,plen,old->nbytes);\n        if (n>0) {\n            memcpy(q,p,n);\n            p+=n; q+=n;\n        }\n        memcpy(q,pnew,new->nbytes);\n        p += old->nbytes;\n        q += new->nbytes;\n        plen -= n+old->nbytes;\n    }\n    if (plen>0)\n        memcpy(q,p,plen);\n    return res;\n}\n\n\nB_int B_bytesD_rfind(B_bytes s, B_bytes sub, B_int start, B_int end) {\n    B_int st = start;\n    B_int en = end;\n    if (fix_start_end(s->nbytes,&st,&en) < 0) return toB_int(-1);\n    unsigned char *p = &s->str[fromB_int(st)];\n    unsigned char *q = &s->str[fromB_int(en)];\n    int n = rbmh(p,sub->str,q-p,sub->nbytes);\n    if (n<0) return toB_int(-1);\n    return toB_int(n+p-s->str);\n}\n\n\nB_int B_bytesD_rindex(B_bytes s, B_bytes sub, B_int start, B_int end) {\n    B_int n = B_bytesD_rfind(s,sub,start,end);\n    if (fromB_int(n)<0) {\n        $RAISE((B_BaseException)$NEW(B_ValueError,to$str(\"rindex for bytes: substring not found\")));\n    };\n    return n;\n}\n\nB_bytes B_bytesD_rjust(B_bytes s, B_int width, B_bytes fill) {\n    if (!fill)\n        fill = space_bytes;\n    if (fill->nbytes != 1) {\n        $RAISE((B_BaseException)$NEW(B_ValueError,to$str(\"rjust: fill string not single char\")));\n    }\n    int wval = fromB_int(width); \n    if (wval <= s->nbytes) {\n        return B_bytesD_copy(s);\n    }\n    int pad = (wval-s->nbytes);\n    B_bytes res;\n    NEW_UNFILLED_BYTES(res,wval);\n    unsigned char c = fill->str[0];\n    for (int i = 0; i<pad; i++) {\n        res->str[i] = c;\n    }\n    memcpy(&res->str[pad],s->str,s->nbytes);\n    return res;\n}\n\nB_tuple B_bytesD_rpartition(B_bytes s, B_bytes sep) {\n    int n = fromB_int(B_bytesD_rfind(s,sep,NULL,NULL));\n    if (n<0) {\n        return $NEWTUPLE(3,to$bytes(\"\"),to$bytes(\"\"),s);\n    } else {\n        int nb = rbmh(s->str,sep->str,s->nbytes,sep->nbytes);\n        B_bytes ls;\n        NEW_UNFILLED_BYTES(ls,nb);\n        memcpy(ls->str,s->str,nb);\n        int nbr = s->nbytes - sep->nbytes - nb;\n        B_bytes rs;\n        NEW_UNFILLED_BYTES(rs,nbr);\n        memcpy(rs->str,s->str+nb+sep->nbytes,nbr);\n        return  $NEWTUPLE(3,ls,sep,rs);\n    }\n}\n\nB_bytes B_bytesD_rstrip(B_bytes s, B_bytes cs) {\n    if (!cs)\n        cs = whitespace_bytes;\n    int nstrip = 0;\n    for (int i=s->nbytes-1; i>=0; i--) {\n        unsigned char c = s->str[i];\n        int found = 0;\n        for (int j=0; j<cs->nbytes; j++)\n            if (c == cs->str[j]) {\n                found = 1;\n                break;\n            }\n        if (!found)\n            break;\n        nstrip++;\n    }\n    B_bytes res;\n    NEW_UNFILLED_BYTES(res,s->nbytes-nstrip);\n    memcpy(res->str,s->str,res->nbytes);\n    return res;\n}\n \nB_list B_bytesD_split(B_bytes s, B_bytes sep, B_int maxsplit) {\n    B_list res = $NEW(B_list,NULL,NULL);\n    B_SequenceD_list wit = B_SequenceD_listG_witness;\n    if (maxsplit == NULL || fromB_int(maxsplit) < 0) maxsplit = toB_int(INT_MAX); \n    if (sep == NULL) {\n        unsigned char *p = s->str;\n        if (s->nbytes==0) {\n            return res;\n        }\n        int inword = 0;\n        unsigned char *q;\n        while (p < s->str + s->nbytes) {\n            if  (*p !=' ' && *p != '\\t' && *p != '\\n' && *p != '\\r' && *p != '\\x0b' && *p != '\\f') {\n                if (!inword) {\n                    inword = 1;\n                    q = p;\n                    if (res->length == fromB_int(maxsplit))\n                        break; // we have now removed leading whitespace in remainder\n                }\n            } else {\n                if (inword) {\n                    inword = 0;\n                    B_bytes word;\n                    NEW_UNFILLED_BYTES(word,p-q);\n                    memcpy(word->str,q,p-q);\n                    wit->$class->append(wit,res,word);\n                }\n            }\n            p++;\n        }\n        // this if statement should be simplified; almost code duplication.\n        if (p < s->str + s->nbytes) { // we did not break out of the while loop\n            if (inword) {\n                B_bytes word;\n                NEW_UNFILLED_BYTES(word,p-q);\n                memcpy(word->str,q,p-q);\n                wit->$class->append(wit,res,word);\n            }\n        } else {\n            B_bytes word;\n            p = s->str+s->nbytes;\n            NEW_UNFILLED_BYTES(word,p-q);\n            memcpy(word->str,q,p-q);\n           wit->$class->append(wit,res,word);\n        }\n        return res;\n    } else { // separator given\n        if (sep->nbytes==0) {\n            $RAISE((B_BaseException)$NEW(B_ValueError,to$str(\"split for bytes: separator is empty string\")));\n        }\n        if (s->nbytes==0) { // for some unfathomable reason, this is the behaviour of the Python method\n            wit->$class->append(wit,res,null_bytes);\n            return res;\n        }\n        B_bytes ls, rs, ssep;\n        rs = s;\n        // Note: This builds many intermediate rs strings...\n        while (rs->nbytes>0 && res->length < fromB_int(maxsplit)) {\n            B_tuple t = B_bytesD_partition(rs,sep);\n            ssep = (B_bytes)t->components[1];\n            rs =  (B_bytes)t->components[2];\n            wit->$class->append(wit,res,(B_bytes)t->components[0]);\n        }\n        if (ssep->nbytes>0)\n            wit->$class->append(wit,res,rs);\n        return res;\n    }\n}\n\nB_list B_bytesD_splitlines(B_bytes s, B_bool keepends) {\n    if (!keepends)\n        keepends = B_False;\n    B_list res = $NEW(B_list,NULL,NULL);\n    B_SequenceD_list wit = B_SequenceD_listG_witness;\n    if (s->nbytes==0) {\n        return res;\n    }\n    int winend;\n    unsigned char *p = s->str;\n    unsigned char *q = p;\n    while (p < s->str + s->nbytes) {\n        if (*p != '\\n' && *p != '\\r') {\n            p++;\n        } else {\n            B_bytes line;\n            winend = *p=='\\r' && *(p+1)=='\\n';\n            int size = p-q + (keepends->val ? 1 + winend : 0);\n            NEW_UNFILLED_BYTES(line,size);\n            memcpy(line->str,q,size);\n            p+= 1 + winend;\n            q = p;\n            wit->$class->append(wit,res,line);\n        }\n    }\n    if (q < p) {\n        B_bytes line;\n        NEW_UNFILLED_BYTES(line,p-q);\n        memcpy(line->str,q,p-q);\n        wit->$class->append(wit,res,line);\n    }\n    return res;\n}\n\nB_bool B_bytesD_startswith(B_bytes s, B_bytes sub, B_int start, B_int end) {\n    B_int st = start;\n    B_int en = end;\n    if (fix_start_end(s->nbytes,&st,&en) < 0) return B_False;\n    unsigned char *p = s->str + fromB_int(st);\n    if (sub->nbytes > 0 && p+sub->nbytes > s->str+s->nbytes) return B_False;\n    unsigned char *q = sub->str;\n    for (int i=0; i<sub->nbytes; i++) {\n        if (p >= s->str + fromB_int(en) || *p++ != *q++) {\n            return B_False;\n        }\n    }\n    return B_True;\n}\n\n\nB_bytes B_bytesD_strip(B_bytes s, B_bytes cs) {\n    return B_bytesD_lstrip(B_bytesD_rstrip(s,cs),cs);\n}\n\nB_bytes B_bytesD_upper(B_bytes s) {\n    B_bytes res;\n    NEW_UNFILLED_BYTES(res,s->nbytes);\n    for (int i=0; i< s->nbytes; i++)\n        res->str[i] = toupper(res->str[i]);\n\n    return res;\n}\n\nB_bytes B_bytesD_zfill(B_bytes s, B_int width) {\n    int wval = fromB_int(width);\n    int fill = wval - s->nbytes;\n    if (fill < 0)\n        return B_bytesD_copy(s);\n    B_bytes res;\n    NEW_UNFILLED_BYTES(res,wval);\n    unsigned char *p = s->str;\n    unsigned char *q = res->str;\n    int hassign = (*p=='+' | *p=='-');\n    if (hassign) {\n        *q = *p;\n        q++;\n    }\n    for (int i=0; i < fill; i++)\n        *q++ = '0';\n    memcpy(res->str+hassign+fill,s->str+hassign,s->nbytes-hassign);\n    return res;\n}\n\n// protocol methods ///////////////////////////////////////////////////\n\n// Ord\n\n\nB_bool B_OrdD_bytesD___eq__ (B_OrdD_bytes wit, B_bytes a, B_bytes b) {\n    if (a->nbytes != b->nbytes)\n        return B_False;\n    for (int i=0; i < a->nbytes; i++)\n        if (a->str[i] != b->str[i])\n            return B_False;\n    return B_True;\n}\n\nB_bool B_OrdD_bytesD___ne__ (B_OrdD_bytes wit, B_bytes a, B_bytes b) {\n    return  toB_bool(!B_OrdD_bytesD___eq__(wit,a,b)->val);\n}\n\nB_bool B_OrdD_bytesD___lt__ (B_OrdD_bytes wit, B_bytes a, B_bytes b) {\n    int minl = a->nbytes<b->nbytes ? a->nbytes : b->nbytes;\n    int i=0;\n    while (i<minl && a->str[i]==b->str[i]) i++;\n    if (i==a->nbytes)\n        return toB_bool(i<b->nbytes);\n    if (i==b->nbytes)\n        return B_False;\n    return toB_bool(a->str[i]<b->str[i]);\n}\n\nB_bool B_OrdD_bytesD___le__ (B_OrdD_bytes wit, B_bytes a, B_bytes b){\n    return toB_bool(!B_OrdD_bytesD___lt__(wit,b,a)->val);\n}\n\nB_bool B_OrdD_bytesD___gt__ (B_OrdD_bytes wit, B_bytes a, B_bytes b){\n    return B_OrdD_bytesD___lt__(wit,b,a);\n}\n\nB_bool B_OrdD_bytesD___ge__ (B_OrdD_bytes wit, B_bytes a, B_bytes b){\n    return toB_bool(!B_OrdD_bytesD___lt__(wit,a,b)->val);\n}\n\n// Container\n\n// Iterable ///////////////////////////////////////////////////////////////////////////\n\nB_IteratorB_bytes B_IteratorB_bytesG_new(B_bytes str) {\n    return $NEW(B_IteratorB_bytes, str);\n}\n\nB_NoneType B_IteratorB_bytesD_init(B_IteratorB_bytes self, B_bytes str) {\n    self->src = str;\n    self->nxt = 0;\n    return B_None;\n}\n\nvoid B_IteratorB_bytesD_serialize(B_IteratorB_bytes self,$Serial$state state) {\n    $step_serialize(self->src,state);\n    $step_serialize(toB_int(self->nxt),state);\n}\n\n\nB_IteratorB_bytes B_IteratorB_bytes$_deserialize(B_IteratorB_bytes res, $Serial$state state) {\n    if (!res)\n        res = $DNEW(B_IteratorB_bytes,state);\n    res->src = (B_bytes)$step_deserialize(state);\n    res->nxt = fromB_int((B_int)$step_deserialize(state));\n    return res;\n}\n\nB_bool B_IteratorB_bytesD_bool(B_IteratorB_bytes self) {\n    return B_True;\n}\n\nB_str B_IteratorB_bytesD_str(B_IteratorB_bytes self) {\n    return $FORMAT(\"<bytes iterator object at %p>\", self);\n}\n\n// this is next function for forward iteration\nstatic B_int B_IteratorB_bytesD_next(B_IteratorB_bytes self) {\n    if (self->nxt >= self->src->nbytes)\n        $RAISE ((B_BaseException)$NEW(B_StopIteration, to$str(\"bytes iterator terminated\")));\n    return toB_int(self->src->str[self->nxt++]);\n}\n\nstruct B_IteratorB_bytesG_class B_IteratorB_bytesG_methods = {\"B_IteratorB_bytes\",UNASSIGNED,($SuperG_class)&B_IteratorG_methods, B_IteratorB_bytesD_init,\n                                                        B_IteratorB_bytesD_serialize, B_IteratorB_bytes$_deserialize,\n                                                        B_IteratorB_bytesD_bool, B_IteratorB_bytesD_str,  B_IteratorB_bytesD_str, B_IteratorB_bytesD_next};\n\nB_Iterator B_ContainerD_bytesD___iter__ (B_ContainerD_bytes wit, B_bytes str) {\n    return (B_Iterator)$NEW(B_IteratorB_bytes,str);\n}\n\nB_bytes B_ContainerD_bytesD___fromiter__ (B_ContainerD_bytes wit, B_Iterable wit2, $WORD iter) {\n    return B_bytesD_join(to$bytes(\"\"),wit2,iter);\n}\n\nB_int B_ContainerD_bytesD___len__ (B_ContainerD_bytes wit, B_bytes str) {\n    return toB_int(str->nbytes);\n}\n\nB_bool B_ContainerD_bytesD___contains__ (B_ContainerD_bytes wit, B_bytes str, B_int n) {\n    long res = 0;\n    for (int i=0; i < str->nbytes; i++) {\n        if (str->str[i] == (unsigned char)fromB_int(n)) {\n            res = 1;\n            break;\n        }\n    }\n    return toB_bool(res);\n}\n\nB_bool B_ContainerD_bytesD___containsnot__ (B_ContainerD_bytes wit, B_bytes str, B_int n) {\n    return toB_bool(!B_ContainerD_bytesD___contains__(wit, str, n)->val);\n}\n\n// Sliceable\n\nB_int B_SliceableD_bytesD___getitem__ (B_SliceableD_bytes wit, B_bytes str, B_int n) {\n    long ix = fromB_int(n);\n    long ix0 = ix < 0 ? str->nbytes + ix : ix;\n    if (ix0<0 || ix0 >= str->nbytes)\n        $RAISE((B_BaseException)$NEW(B_IndexError, toB_int(ix0), to$str(\"getitem: index outside bytesarray\")));\n    return toB_int((long)str->str[ix0]);\n}\n\nB_NoneType B_SliceableD_bytesD___setitem__ (B_SliceableD_bytes wit, B_bytes str, B_int i, B_int val) {\n    $RAISE((B_BaseException)$NEW(B_NotImplementedError,to$str(\"call to mutating method setitem on bytes\")));\n    return B_None;\n}\n\nB_NoneType B_SliceableD_bytesD___delitem__ (B_SliceableD_bytes wit, B_bytes str, B_int i) {\n    $RAISE((B_BaseException)$NEW(B_NotImplementedError,to$str(\"call to mutating method delitem on bytes\")));\n    return B_None;\n}\n\nB_bytes B_SliceableD_bytesD___getslice__ (B_SliceableD_bytes wit, B_bytes str, B_slice slc) {\n    int64_t start, stop, step, slen;\n    normalize_slice(slc, str->nbytes, &slen, &start, &stop, &step);\n    //slice notation has been eliminated and default values applied\n    B_bytes res;\n    NEW_UNFILLED_BYTES(res,slen);\n    int t = start;\n    for (int i=0; i<slen; i++) {\n        res->str[i] = str->str[t];\n        t += step;\n    }\n    return res;\n}\n\nB_NoneType B_SliceableD_bytesD___setslice__ (B_SliceableD_bytes wit, B_bytes str, B_Iterable wit2, B_slice slc, $WORD iter) {\n    $RAISE((B_BaseException)$NEW(B_NotImplementedError,to$str(\"call to mutating method setslice on bytes\")));\n    return B_None;\n}\n\nB_NoneType B_SliceableD_bytesD___delslice__ (B_SliceableD_bytes wit, B_bytes str, B_slice slc) {\n    $RAISE((B_BaseException)$NEW(B_NotImplementedError,to$str(\"call to mutating method delslice on bytes\")));\n    return B_None;\n}\n\n// Times\n\n\nB_bytes B_TimesD_bytesD___add__ (B_TimesD_bytes wit, B_bytes s, B_bytes t) {\n    B_bytes res;\n    NEW_UNFILLED_BYTES(res,s->nbytes + t->nbytes);\n    memcpy(res->str,s->str,s->nbytes);\n    memcpy(res->str+s->nbytes,t->str,t->nbytes);\n    return res;\n}\n\nB_bytes B_TimesD_bytesD___zero__ (B_TimesD_bytes wit) {\n    return to$bytes(\"\");\n}\n\nB_bytes B_TimesD_bytesD___mul__ (B_TimesD_bytes wit, B_bytes a, B_int n) {\n    int nval = fromB_int(n);\n    if (nval <= 0)\n        return to$bytes(\"\");\n    else {\n        B_bytes res;\n        NEW_UNFILLED_BYTES(res, a->nbytes * nval);\n        for (int i=0; i<nval; i++)\n            memcpy(res->str + i*a->nbytes,a->str,a->nbytes);\n        return res;\n    }\n}\n\n// Hashable\n\n\nB_bool B_HashableD_bytesD___eq__ (B_HashableD_bytes wit, B_bytes a, B_bytes b) {\n    if (a->nbytes != b->nbytes)\n        return B_False;\n    for (int i=0; i < a->nbytes; i++)\n        if (a->str[i] != b->str[i])\n            return B_False;\n    return B_True;\n}\n\nB_bool B_HashableD_bytesD___ne__ (B_HashableD_bytes wit, B_bytes a, B_bytes b) {\n    return  toB_bool(!B_HashableD_bytesD___eq__(wit,a,b)->val);\n}\n\nB_NoneType B_HashableD_bytesD_hash(B_HashableD_bytes wit, B_bytes a, B_hasher h) {\n    zig_hash_wyhash_update(h->_hasher, a);\n    return B_None;\n}\n\n// Builtin functions involving strings /////////////////////////////////////////////\n\nB_str B_ascii(B_value v) {\n    B_str s  = v->$class->__str__(v);\n    struct byte_counts bs = byte_count(s->str, s->nbytes);\n    //    printf(\"%d %d %d %d %d %d\\n\",bs.escaped,bs.squotes,bs.dquotes,bs.printable,bs.non_printable,bs.non_ascii);\n    bool use_single_quotes = !(bs.dquotes==0 && bs.squotes>0);\n    int escaped_quotes = use_single_quotes ? bs.dquotes : bs.squotes;\n    int newbytes = 2+bs.escaped+3*bs.non_printable+escaped_quotes+3*bs.non_ascii;\n    B_str res;\n    NEW_UNFILLED_STR(res,s->nchars+newbytes,s->nbytes+newbytes);\n    escape_str(res->str+1,s->str,res->nbytes-1,s->nbytes,255,!use_single_quotes,use_single_quotes,false,false);\n    if (use_single_quotes) {\n        res->str[0] = '\\'';\n        res->str[res->nbytes-1] = '\\'';\n    } else {\n        res->str[0] = '\"';\n        res->str[res->nbytes-1] = '\"';\n    }\n    return res;\n}\n\nB_str B_bin(B_Integral wit, $WORD n) {\n    long v = fromB_int(wit->$class->__int__(wit,n));\n    int sign = v<0;\n    int nbits = 1;\n    unsigned long u = labs(v);\n    if (u & 0xffffffff00000000) {\n        u >>= 32; nbits += 32;\n    }\n    if (u & 0x00000000ffff0000) {\n        u >>= 16; nbits += 16;\n    }\n    if (u & 0x000000000000ff00) {\n        u >>= 8; nbits += 8;\n    }\n    if (u & 0x00000000000000f0) {\n        u >>= 4; nbits += 4;\n    }\n    if (u & 0x000000000000000c) {\n        u >>= 2; nbits += 2;\n    }\n    if (u & 0x0000000000000002) {\n        u >>= 1; nbits += 1;\n    }\n    B_str res;\n    int nbytes = sign+2+nbits;\n    NEW_UNFILLED_STR(res,nbytes,nbytes);\n    unsigned char *p = res->str;\n    if (sign) {\n        *p = '-'; p++;\n    }\n    *p = '0'; p++;\n    *p = 'b'; p++;\n    u = labs(v);\n    for (int i = nbits-1; i>=0; i--) {\n        *p = u & (1L << i) ? '1' : '0'; p++;\n    }\n    return res;\n}\n\nB_str B_chr(B_Integral wit, $WORD n) {\n    long v = fromB_int(wit->$class->__int__(wit,n));\n    if (v >=  0x110000)\n        $RAISE((B_BaseException)$NEW(B_ValueError,to$str(\"chr: argument is not a valid Unicode code point\")));\n    if (v > 0 && v < ASCII_CHAR_TABLE_SIZE)\n        return &ascii_char_strs[v];\n    unsigned char code[4];\n    int nbytes = utf8proc_encode_char((int)v,(unsigned char*)&code);\n    if (nbytes==0)\n        $RAISE((B_BaseException)$NEW(B_ValueError,to$str(\"chr: argument is not a valid Unicode code point\")));\n    B_str res;\n    NEW_UNFILLED_STR(res,1,nbytes);\n    for (int i=0; i<nbytes; i++)\n        res->str[i] = code[i];\n    return res;\n}\n\nB_str B_hex(B_Integral wit, $WORD n) {\n    unsigned char *hexdigits = (unsigned char *)\"0123456789abcdef\";\n    long v =  fromB_int(wit->$class->__int__(wit,n));\n    int sign = v<0;\n    int nhexs = 1;\n    unsigned long u = labs(v);\n    if (u & 0xffffffff00000000) {\n        u >>= 32; nhexs += 8;\n    }\n    if (u & 0x00000000ffff0000) {\n        u >>= 16; nhexs += 4;\n    }\n    if (u & 0x000000000000ff00) {\n        u >>= 8; nhexs += 2;\n    }\n    if (u & 0x00000000000000f0) {\n        u >>= 4; nhexs += 1;\n    }\n    B_str res;\n    int nbytes = sign+2+nhexs;\n    NEW_UNFILLED_STR(res,nbytes,nbytes);\n    unsigned char *p = res->str;\n    if (sign) {\n        *p = '-'; p++;\n    }\n    *p = '0'; p++;\n    *p = 'x'; p++;\n    u = labs(v);\n    for (int i = nhexs-1; i>=0; i--) {\n        *p = hexdigits[(u>>(4*i)) & 0xf]; p++;\n    }\n    return res;\n}\n\nint64_t B_U_6ord(B_str c) {\n    if(c->nchars != 1)\n        $RAISE((B_BaseException)$NEW(B_ValueError,to$str(\"ord: argument is not a single Unicode char\")));\n    int cp;\n    int cpnbytes = utf8proc_iterate(c->str,-1,&cp);\n    if (cpnbytes < 0)\n        $RAISE((B_BaseException)$NEW(B_ValueError,to$str(\"ord: argument is not a single Unicode char\")));\n    return (int64_t)cp;\n}\n\n// Auxiliary function used in __str__ for collections ////////////////////////////\n\nB_str B_strD_join_par(char lpar, B_list elems, char rpar) {\n    char *s = \", \";\n    int len = elems->length;\n    int totchars = 2;  //parens\n    int totbytes = 2;\n    B_str nxt;\n    for (int i=0; i<len; i++) {\n        nxt = (B_str)elems->data[i];\n        totchars += nxt->nchars;\n        totbytes += nxt->nbytes;\n    }\n    if (len > 1) {\n        totchars += (len-1) * 2; // 2 is length of \", \"\n        totbytes += (len-1) * 2;\n    }\n    B_str res;\n    NEW_UNFILLED_STR(res,totchars,totbytes);\n    res->str[0] = lpar;\n    res->str[totbytes-1] = rpar;\n    if (len > 0) {\n        unsigned char *p = res->str+1;\n        nxt = elems->data[0];\n        memcpy(p,nxt->str,nxt->nbytes);\n        p += nxt->nbytes;\n        for (int i=1; i<len; i++) {\n            nxt = (B_str)elems->data[i];\n            memcpy(p,s,2);\n            p += 2;\n            memcpy(p,nxt->str,nxt->nbytes);\n            p += nxt->nbytes;\n        }\n    }\n    return res;\n}\n\nB_str $default__str__(B_value self) {\n    return $FORMAT(\"<%s object at %p>\", self->$class->$GCINFO, self);\n}\n\n\n\n// Static witnesses\n\n\n/*\nstruct B_OrdD_strG_class  B_OrdD_strG_methods = {\n    \"B_OrdD_str\",\n    UNASSIGNED,\n    ($SuperG_class)&B_OrdG_methods,\n    (B_NoneType (*)(B_OrdD_str))$default__init__,\n    B_OrdD_strD___serialize__,\n    B_OrdD_strD___deserialize__,\n    (B_bool (*)(B_OrdD_str))$default__bool__,\n    (B_str (*)(B_OrdD_str))$default__str__,\n    (B_str (*)(B_OrdD_str))$default__str__,\n    B_OrdD_strD___eq__,\n    B_OrdD_strD___ne__,\n    B_OrdD_strD___lt__,\n    B_OrdD_strD___le__,\n    B_OrdD_strD___gt__,\n    B_OrdD_strD___ge__\n};\n\nstruct B_OrdD_str B_OrdD_str_instance = {&B_OrdD_strG_methods};\nB_OrdD_str B_OrdD_strG_witness = &B_OrdD_str_instance;\n\nstruct B_ContainerD_strG_class  B_ContainerD_strG_methods = {\n    \"B_ContainerD_str\",\n    UNASSIGNED,\n    ($SuperG_class)&B_ContainerG_methods,\n    (B_NoneType (*)(B_ContainerD_str))$default__init__,\n    B_ContainerD_strD___serialize__,\n    B_ContainerD_strD___deserialize__,\n    (B_bool (*)(B_ContainerD_str))$default__bool__,\n    (B_str (*)(B_ContainerD_str))$default__str__,\n    (B_str (*)(B_ContainerD_str))$default__str__,\n    B_ContainerD_strD___iter__,\n    NULL,\n    B_ContainerD_strD___len__,\n    B_ContainerD_strD___contains__,\n    B_ContainerD_strD___containsnot__\n};\n\nstruct B_ContainerD_str B_ContainerD_str_instance = {&B_ContainerD_strG_methods};\nB_ContainerD_str B_ContainerD_strG_witness = &B_ContainerD_str_instance;\n\n\nstruct B_SliceableD_strG_class  B_SliceableD_strG_methods = {\n    \"B_SliceableD_str\",\n    UNASSIGNED,\n    ($SuperG_class)&B_SliceableG_methods,\n    (B_NoneType (*)(B_SliceableD_str))$default__init__,\n    B_SliceableD_strD___serialize__,\n    B_SliceableD_strD___deserialize__,\n    (B_bool (*)(B_SliceableD_str))$default__bool__,\n    (B_str (*)(B_SliceableD_str))$default__str__,\n    (B_str (*)(B_SliceableD_str))$default__str__,\n    B_SliceableD_strD___getitem__,\n    B_SliceableD_strD___setitem__,\n    B_SliceableD_strD___delitem__,\n    B_SliceableD_strD___getslice__,\n    B_SliceableD_strD___setslice__,\n    B_SliceableD_strD___delslice__\n};\n\nstruct B_SliceableD_str B_SliceableD_str_instance = {&B_SliceableD_strG_methods};\nB_SliceableD_str B_SliceableD_strG_witness = &B_SliceableD_str_instance;\n\nstruct B_TimesD_strG_class  B_TimesD_strG_methods = {\n    \"B_TimesD_str\",\n    UNASSIGNED,\n    ($SuperG_class)&B_TimesG_methods,\n    (B_NoneType (*)(B_TimesD_str))$default__init__,\n    B_TimesD_strD___serialize__,\n    B_TimesD_strD___deserialize__,\n    (B_bool (*)(B_TimesD_str))$default__bool__,\n    (B_str (*)(B_TimesD_str))$default__str__,\n    (B_str (*)(B_TimesD_str))$default__str__,\n    B_TimesD_strD___add__,\n    (B_str (*)(B_TimesD_str, B_str, B_str))B_PlusD___iadd__,\n    B_TimesD_strD___mul__,\n    (B_str (*)(B_TimesD_str, B_str, B_int))B_TimesD___imul__,\n\n};\n\nstruct B_TimesD_str B_TimesD_str_instance = {&B_TimesD_strG_methods};\nB_TimesD_str B_TimesD_strG_witness = &B_TimesD_str_instance;\n\nstruct B_HashableD_strG_class  B_HashableD_strG_methods = {\n    \"B_HashableD_str\",\n    UNASSIGNED,\n    ($SuperG_class)&B_HashableG_methods,\n    (B_NoneType (*)(B_HashableD_str))$default__init__,\n    B_HashableD_strD___serialize__,\n    B_HashableD_strD___deserialize__,\n    (B_bool (*)(B_HashableD_str))$default__bool__,\n    (B_str (*)(B_HashableD_str))$default__str__,\n    (B_str (*)(B_HashableD_str))$default__str__,\n    B_HashableD_strD___eq__,\n    B_HashableD_strD___ne__\n};\n\nstruct B_HashableD_str B_HashableD_str_instance = {&B_HashableD_strG_methods};\nB_HashableD_str B_HashableD_strG_witness = &B_HashableD_str_instance;\n\nstruct B_SequenceD_bytearray  B_SequenceD_bytearray_instance;\nstruct B_CollectionD_SequenceD_bytearray B_CollectionD_SequenceD_bytearray_instance;\nstruct B_TimesD_SequenceD_bytearray B_TimesD_SequenceD_bytearray_instance;\n\n\nstruct B_OrdD_bytearrayG_class  B_OrdD_bytearrayG_methods = {\n    \"B_OrdD_bytearray\",\n    UNASSIGNED,\n    ($SuperG_class)&B_OrdG_methods,\n    (B_NoneType (*)(B_OrdD_bytearray))$default__init__,\n    B_OrdD_bytearrayD___serialize__,\n    B_OrdD_bytearrayD___deserialize__,\n    (B_bool (*)(B_OrdD_bytearray))$default__bool__,\n    (B_str (*)(B_OrdD_bytearray))$default__str__,\n    (B_str (*)(B_OrdD_bytearray))$default__str__,\n    B_OrdD_bytearrayD___eq__, B_OrdD_bytearrayD___ne__,\n    B_OrdD_bytearrayD___lt__, B_OrdD_bytearrayD___le__,\n    B_OrdD_bytearrayD___gt__, B_OrdD_bytearrayD___ge__\n};\n\nstruct B_OrdD_bytearray B_OrdD_bytearray_instance = {&B_OrdD_bytearrayG_methods};\nB_OrdD_bytearray B_OrdD_bytearrayG_witness = &B_OrdD_bytearray_instance;\n\nstruct B_SequenceD_bytearrayG_class B_SequenceD_bytearrayG_methods = {\n    \"B_SequenceD_bytearray\",\n    UNASSIGNED,\n    ($SuperG_class)&B_SequenceG_methods,\n    (B_NoneType (*)(B_SequenceD_bytearray))$default__init__,\n    B_SequenceD_bytearrayD___serialize__,\n    B_SequenceD_bytearrayD___deserialize__,\n    (B_bool (*)(B_SequenceD_bytearray))$default__bool__,\n    (B_str (*)(B_SequenceD_bytearray))$default__str__,\n    (B_str (*)(B_SequenceD_bytearray))$default__str__,\n    B_SequenceD_bytearrayD___getitem__,\n    B_SequenceD_bytearrayD___setitem__,\n    B_SequenceD_bytearrayD___delitem__,\n    B_SequenceD_bytearrayD___getslice__,\n    B_SequenceD_bytearrayD___setslice__,\n    B_SequenceD_bytearrayD___delslice__,\n    B_SequenceD_bytearrayD___reversed__,\n    B_SequenceD_bytearray$insert,\n    B_SequenceD_bytearray$append,\n    B_SequenceD_bytearray$reverse\n};\n\nstruct B_SequenceD_bytearray B_SequenceD_bytearray_instance = {\n    &B_SequenceD_bytearrayG_methods,\n    (B_Eq)&B_OrdD_intG_methods,\n    (B_Collection)&B_CollectionD_SequenceD_bytearray_instance,\n    (B_Times)&B_TimesD_SequenceD_bytearray_instance\n};\nB_SequenceD_bytearray B_SequenceD_bytearrayG_witness = &B_SequenceD_bytearray_instance;\n\nstruct B_CollectionD_SequenceD_bytearrayG_class B_CollectionD_SequenceD_bytearrayG_methods = {\n    \"B_CollectionD_SequenceD_bytearray\",\n    UNASSIGNED,\n    ($SuperG_class)&B_CollectionG_methods,\n    B_CollectionD_SequenceD_bytearrayD___init__,\n    B_CollectionD_SequenceD_bytearrayD___serialize__,\n    B_CollectionD_SequenceD_bytearrayD___deserialize__,\n    (B_bool (*)(B_CollectionD_SequenceD_bytearray))$default__bool__,\n    (B_str (*)(B_CollectionD_SequenceD_bytearray))$default__str__,\n    (B_str (*)(B_CollectionD_SequenceD_bytearray))$default__str__,\n    B_CollectionD_SequenceD_bytearrayD___iter__,\n    B_CollectionD_SequenceD_bytearrayD___fromiter__,\n    B_CollectionD_SequenceD_bytearrayD___len__\n};\n\nstruct B_CollectionD_SequenceD_bytearray B_CollectionD_SequenceD_bytearray_instance = {&B_CollectionD_SequenceD_bytearrayG_methods,(B_Sequence)&B_SequenceD_bytearray_instance};\nB_CollectionD_SequenceD_bytearray B_CollectionD_SequenceD_bytearrayG_witness = &B_CollectionD_SequenceD_bytearray_instance;\n\nstruct B_TimesD_SequenceD_bytearrayG_class  B_TimesD_SequenceD_bytearrayG_methods = {\n    \"B_TimesD_SequenceD_bytearray\",\n    UNASSIGNED,\n    ($SuperG_class)&B_TimesG_methods,\n    B_TimesD_SequenceD_bytearrayD___init__,\n    B_TimesD_SequenceD_bytearrayD___serialize__,\n    B_TimesD_SequenceD_bytearrayD___deserialize__,\n    (B_bool (*)(B_TimesD_SequenceD_bytearray))$default__bool__,\n    (B_str (*)(B_TimesD_SequenceD_bytearray))$default__str__,\n    (B_str (*)(B_TimesD_SequenceD_bytearray))$default__str__,\n    B_TimesD_SequenceD_bytearrayD___add__,\n    (B_bytearray (*)(B_TimesD_SequenceD_bytearray, B_bytearray, B_bytearray))B_PlusD___iadd__,\n    B_TimesD_SequenceD_bytearrayD___mul__,\n    (B_bytearray (*)(B_TimesD_SequenceD_bytearray, B_bytearray, B_int))B_TimesD___imul__,\n};\n\nstruct B_TimesD_SequenceD_bytearray B_TimesD_SequenceD_bytearray_instance = {&B_TimesD_SequenceD_bytearrayG_methods};\nB_TimesD_SequenceD_bytearray B_TimesD_SequenceD_bytearrayG_witness = &B_TimesD_SequenceD_bytearray_instance;\n\nstruct B_ContainerD_bytearrayG_class B_ContainerD_bytearrayG_methods = {\n    \"B_ContainerD_bytearray\",\n    UNASSIGNED,\n    ($SuperG_class)&B_ContainerG_methods,\n    B_ContainerD_bytearrayD___init__,\n    B_ContainerD_bytearrayD___serialize__,\n    B_ContainerD_bytearrayD___deserialize__,\n    (B_bool (*)(B_ContainerD_bytearray))$default__bool__,\n    (B_str (*)(B_ContainerD_bytearray))$default__str__,\n    (B_str (*)(B_ContainerD_bytearray))$default__str__,\n    B_ContainerD_bytearrayD___iter__,\n    B_ContainerD_bytearrayD___fromiter__,\n    B_ContainerD_bytearrayD___len__,\n    B_ContainerD_bytearrayD___contains__,\n    B_ContainerD_bytearrayD___containsnot__\n};\n\nstruct B_ContainerD_bytearray B_ContainerD_bytearray_instance = {&B_ContainerD_bytearrayG_methods};\nB_ContainerD_bytearray B_ContainerD_bytearrayG_witness = &B_ContainerD_bytearray_instance;\n\n\n\nstruct B_OrdD_bytesG_class  B_OrdD_bytesG_methods = {\n    \"B_OrdD_bytes\",\n    UNASSIGNED,\n    ($SuperG_class)&B_OrdG_methods,\n    (B_NoneType (*)(B_OrdD_bytes))$default__init__,\n    B_OrdD_bytesD___serialize__,\n    B_OrdD_bytesD___deserialize__,\n    (B_bool (*)(B_OrdD_bytes))$default__bool__,\n    (B_str (*)(B_OrdD_bytes))$default__str__,\n    (B_str (*)(B_OrdD_bytes))$default__str__,\n    B_OrdD_bytesD___eq__,\n    B_OrdD_bytesD___ne__,\n    B_OrdD_bytesD___lt__,\n    B_OrdD_bytesD___le__,\n    B_OrdD_bytesD___gt__,\n    B_OrdD_bytesD___ge__\n};\n\nstruct B_OrdD_bytes B_OrdD_bytes_instance = {&B_OrdD_bytesG_methods};\nB_OrdD_bytes B_OrdD_bytesG_witness = &B_OrdD_bytes_instance;\n\nstruct B_ContainerD_bytesG_class  B_ContainerD_bytesG_methods = {\n    \"B_ContainerD_bytes\",\n    UNASSIGNED,\n    ($SuperG_class)&B_ContainerG_methods,\n    B_ContainerD_bytesD___init__,\n    B_ContainerD_bytesD___serialize__,\n    B_ContainerD_bytesD___deserialize__,\n    (B_bool (*)(B_ContainerD_bytes))$default__bool__,\n    (B_str (*)(B_ContainerD_bytes))$default__str__,\n    (B_str (*)(B_ContainerD_bytes))$default__str__,\n    B_ContainerD_bytesD___iter__,\n    NULL,\n    B_ContainerD_bytesD___len__,\n    B_ContainerD_bytesD___contains__,\n    B_ContainerD_bytesD___containsnot__\n};\n\nstruct B_ContainerD_bytes B_ContainerD_bytes_instance = {&B_ContainerD_bytesG_methods};\nB_ContainerD_bytes B_ContainerD_bytesG_witness = &B_ContainerD_bytes_instance;\n\n\nstruct B_SliceableD_bytesG_class  B_SliceableD_bytesG_methods = {\n    \"B_SliceableD_bytes\",\n    UNASSIGNED,\n    ($SuperG_class)&B_SliceableG_methods,\n    (B_NoneType (*)(B_SliceableD_bytes))$default__init__,\n    B_SliceableD_bytesD___serialize__,\n    B_SliceableD_bytesD___deserialize__,\n    (B_bool (*)(B_SliceableD_bytes))$default__bool__,\n    (B_str (*)(B_SliceableD_bytes))$default__str__,\n    (B_str (*)(B_SliceableD_bytes))$default__str__,\n    B_SliceableD_bytesD___getitem__,\n    B_SliceableD_bytesD___setitem__,\n    B_SliceableD_bytesD___delitem__,\n    B_SliceableD_bytesD___getslice__,\n    B_SliceableD_bytesD___setslice__,\n    B_SliceableD_bytesD___delslice__\n};\n\nstruct B_SliceableD_bytes B_SliceableD_bytes_instance = {&B_SliceableD_bytesG_methods};\nB_SliceableD_bytes B_SliceableD_bytesG_witness = &B_SliceableD_bytes_instance;\n\nstruct B_TimesD_bytesG_class  B_TimesD_bytesG_methods = {\n    \"B_TimesD_bytes\",\n    UNASSIGNED,\n    ($SuperG_class)&B_TimesG_methods,\n    (B_NoneType (*)(B_TimesD_bytes))$default__init__,\n    B_TimesD_bytesD___serialize__,\n    B_TimesD_bytesD___deserialize__,\n    (B_bool (*)(B_TimesD_bytes))$default__bool__,\n    (B_str (*)(B_TimesD_bytes))$default__str__,\n    (B_str (*)(B_TimesD_bytes))$default__str__,\n    B_TimesD_bytesD___add__,\n    (B_bytes (*)(B_TimesD_bytes, B_bytes, B_bytes))B_PlusD___iadd__,\n    B_TimesD_bytesD___mul__,\n    (B_bytes (*)(B_TimesD_bytes, B_bytes, B_int))B_TimesD___imul__,\n\n};\n\nstruct B_TimesD_bytes B_TimesD_bytes_instance = {&B_TimesD_bytesG_methods};\nB_TimesD_bytes B_TimesD_bytesG_witness = &B_TimesD_bytes_instance;\n\nstruct B_HashableD_bytesG_class  B_HashableD_bytesG_methods = {\n    \"B_HashableD_bytes\",\n    UNASSIGNED,\n    ($SuperG_class)&B_HashableG_methods,\n    (B_NoneType (*)(B_HashableD_bytes))$default__init__,\n    B_HashableD_bytesD___serialize__,\n    B_HashableD_bytesD___deserialize__,\n    (B_bool (*)(B_HashableD_bytes))$default__bool__,\n    (B_str (*)(B_HashableD_bytes))$default__str__,\n    (B_str (*)(B_HashableD_bytes))$default__str__,\n    B_HashableD_bytesD___eq__,\n    B_HashableD_bytesD___ne__\n};\n\nstruct B_HashableD_bytes B_HashableD_bytes_instance = {&B_HashableD_bytesG_methods};\nB_HashableD_bytes B_HashableD_bytesG_witness = &B_HashableD_bytes_instance;\n\n*/\n\nB_str $FORMAT(const char *format, ...) {\n    va_list args;\n    va_start(args, format);\n\n    va_list args_copy;\n    va_copy(args_copy, args);\n    int size = vsnprintf(NULL, 0, format, args_copy);\n    va_end(args_copy);\n\n    if (size < 0) {\n        va_end(args);\n        RAISE(B_ValueError, to_str_noc(\"Invalid format string\"));\n    }\n\n    char *buffer = (char *)acton_malloc_atomic(size + 1);\n    if (buffer == NULL) {\n        va_end(args);\n        RAISE(B_MemoryError, to_str_noc(\"Failed to allocate memory for formatted string\"));\n    }\n\n    vsnprintf(buffer, size + 1, format, args);\n    va_end(args);\n\n    return to_str_noc(buffer);\n}\n"
  },
  {
    "path": "base/builtin/str.h",
    "content": "struct B_strG_class;\n\nstruct B_str {\n    struct B_strG_class *$class;\n    int nbytes;              // length of str in bytes\n    int nchars;              // length of str in Unicode chars\n    unsigned char *str;      // str is UTF-8 encoded.\n};\n\n// Constructor; str must be a null-terminated, correctly UTF-8-encoded string.\n// The constructor checks this and returns a B_str value.\nB_str to$str(char *str);  //Dare not remove this\n\nB_str toB_str(char *str);\n\nB_str to_str_noc(char *str);\n\n// Destructor; recover the internal string.\nunsigned char *fromB_str(B_str str);\n\nB_str $FORMAT(const char *format, ...);\n\n// Iterators over str's ///////////////////////////////////////////////////////\n\ntypedef struct B_IteratorB_str *B_IteratorB_str; ;\n\nstruct B_IteratorB_strG_class {\n    char *$GCINFO;\n    int $class_id;\n    $SuperG_class $superclass;\n    B_NoneType (*__init__)(B_IteratorB_str, B_str);\n    void (*__serialize__)(B_IteratorB_str,$Serial$state);\n    B_IteratorB_str (*__deserialize__)(B_IteratorB_str,$Serial$state);\n    B_bool (*__bool__)(B_IteratorB_str);\n    B_str (*__str__)(B_IteratorB_str);\n    B_str (*__repr__)(B_IteratorB_str);\n    B_str (*__next__)(B_IteratorB_str);\n};\n\nstruct B_IteratorB_str {\n    struct B_IteratorB_strG_class *$class;\n    B_str src;\n    int nxt;\n};\n\nextern struct  B_IteratorB_strG_class  B_IteratorB_strG_methods;\nB_IteratorB_str B_IteratorB_strG_new(B_str);\n\n// bytearray /////////////////////////////////////////////////////////////////////////////////////\n\n\n\nstruct B_bytearray {\n    struct B_bytearrayG_class *$class;\n    int nbytes;\n    unsigned char *str;\n    int capacity;\n};\n\n \nB_bytearray toB_bytearray(char *str); \nunsigned char *fromB_bytearray(B_bytearray b);\n\n// Iterators over bytearrays ///////////////////////////////////////////////////////\n\ntypedef struct B_IteratorB_bytearray *B_IteratorB_bytearray; ;\n\nstruct B_IteratorB_bytearrayG_class {\n    char *$GCINFO;\n    int $class_id;\n    $SuperG_class $superclass;\n    B_NoneType (*__init__)(B_IteratorB_bytearray, B_bytearray);\n    void (*__serialize__)(B_IteratorB_bytearray,$Serial$state);\n    B_IteratorB_bytearray (*__deserialize__)(B_IteratorB_bytearray,$Serial$state);\n    B_bool (*__bool__)(B_IteratorB_bytearray);\n    B_str (*__str__)(B_IteratorB_bytearray);\n    B_str (*__repr__)(B_IteratorB_bytearray);\n    B_int (*__next__)(B_IteratorB_bytearray);\n};\n\nstruct B_IteratorB_bytearray {\n    struct B_IteratorB_bytearrayG_class *$class;\n    B_bytearray src;\n    int nxt;\n};\n\nextern struct  B_IteratorB_bytearrayG_class  B_IteratorB_bytearrayG_methods;\nB_IteratorB_bytearray B_IteratorB_bytearrayG_new(B_bytearray);\n\n// bytes /////////////////////////////////////////////////////////////////////////////////////\n\n\nstruct B_bytes {\n    struct B_bytesG_class *$class;\n    int nbytes;\n    unsigned char *str;\n};\n\nB_bytes to$bytes(char *str);\nB_bytes to$bytesD_len(char *str, int len);\nB_bytes actBytesFromCString(char *str);\nB_bytes actBytesFromCStringNoCopy(char *str);\nB_bytes actBytesFromCStringLength(char *str, int len);\nB_bytes actBytesFromCStringLengthNoCopy(char *str, int length);\nunsigned char *fromB_bytes(B_bytes b);\n\n\n// Iterators over bytes ///////////////////////////////////////////////////////\n\n\ntypedef struct B_IteratorB_bytes *B_IteratorB_bytes; ;\n\nstruct B_IteratorB_bytesG_class {\n    char *$GCINFO;\n    int $class_id;\n    $SuperG_class $superclass;\n    B_NoneType (*__init__)(B_IteratorB_bytes, B_bytes);\n    void (*__serialize__)(B_IteratorB_bytes,$Serial$state);\n    B_IteratorB_bytes (*__deserialize__)(B_IteratorB_bytes,$Serial$state);\n    B_bool (*__bool__)(B_IteratorB_bytes);\n    B_str (*__str__)(B_IteratorB_bytes);\n    B_str (*__repr__)(B_IteratorB_bytes);\n    B_int (*__next__)(B_IteratorB_bytes);\n};\n\nstruct B_IteratorB_bytes {\n    struct B_IteratorB_bytesG_class *$class;\n    B_bytes src;\n    int nxt;\n};\n\nextern struct  B_IteratorB_bytesG_class  B_IteratorB_bytesG_methods;\nB_IteratorB_bytes B_IteratorB_bytesG_new(B_bytes);\n\n// Internal auxiliary function /////////////////////////////////////////////\n\n// used in defining __str__ method for collection types (list, dict, set)\nB_str B_strD_join_par(char lpar,B_list elems, char rpar);\n\nB_str $default__str__(B_value);\n"
  },
  {
    "path": "base/builtin/timsort.c",
    "content": "#define SORT_NAME B\n\n#define SORT_TYPE $WORD\n\n/* An implementation of simplified Timsort (no galloping).\n\n * Slightly modified from https://github.com/GNOME/libxml2/blob/master/timsort.h#L531\n * (STR_COMP is modified and takes an extra witness parameter. Consequently several methods from the main function downwards\n * need take this parameter.\n * \n * The following is the comment in the libxml2 file.\n *\n * Taken from https://github.com/swenson/sort\n * Revision: 05fd77bfec049ce8b7c408c4d3dd2d51ee061a15\n * Removed all code unrelated to Timsort and made minor adjustments for\n * cross-platform compatibility.\n */\n\n/*\n * The MIT License (MIT)\n *\n * Copyright (c) 2010-2017 Christopher Swenson.\n * Copyright (c) 2012 Vojtech Fried.\n * Copyright (c) 2012 Google Inc. All Rights Reserved.\n *\n * Permission is hereby granted, free of charge, to any person obtaining a\n * copy of this software and associated documentation files (the \"Software\"),\n * to deal in the Software without restriction, including without limitation\n * the rights to use, copy, modify, merge, publish, distribute, sublicense,\n * and/or sell copies of the Software, and to permit persons to whom the\n * Software is furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING\n * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER\n * DEALINGS IN THE SOFTWARE.\n */\n\n// #include <stdlib.h>\n// #include <stdio.h>\n// #include <string.h>\n// #ifdef HAVE_STDINT_H\n// #include <stdint.h>\n// #elif defined(_WIN32)\n// typedef unsigned __int64 uint64_t;\n// #endif\n\n#ifndef SORT_NAME\n#error \"Must declare SORT_NAME\"\n#endif\n\n#ifndef SORT_TYPE\n#error \"Must declare SORT_TYPE\"\n#endif\n\n#ifndef SORT_CMP\n#define SORT_CMP(w, x, y)  (w->$class->__lt__(w, x, y)->val ? -1 : (w->$class->__eq__(w, x, y)->val ? 0 : 1))     //((x) < (y) ? -1 : ((x) == (y) ? 0 : 1))\n#endif\n\n#ifndef TIM_SORT_STACK_SIZE\n#define TIM_SORT_STACK_SIZE 128\n#endif\n\n#define SORT_SWAP(x,y) {SORT_TYPE __SORT_SWAP_t = (x); (x) = (y); (y) = __SORT_SWAP_t;}\n\n\n/* Common, type-agnostic functions and constants that we don't want to declare twice. */\n#ifndef SORT_COMMON_H\n#define SORT_COMMON_H\n\n#ifndef MAX\n#define MAX(x,y) (((x) > (y) ? (x) : (y)))\n#endif\n\n#ifndef MIN\n#define MIN(x,y) (((x) < (y) ? (x) : (y)))\n#endif\n\nstatic int compute_minrun(const uint64_t);\n\n#ifndef CLZ\n#if defined(__GNUC__) && ((__GNUC__ == 3 && __GNUC_MINOR__ >= 4) || (__GNUC__ > 3))\n#define CLZ __builtin_clzll\n#else\n\nstatic int clzll(uint64_t);\n\n/* adapted from Hacker's Delight */\nstatic int clzll(uint64_t x) {\n  int n;\n\n  if (x == 0) {\n    return 64;\n  }\n\n  n = 0;\n\n  if (x <= 0x00000000FFFFFFFFL) {\n    n = n + 32;\n    x = x << 32;\n  }\n\n  if (x <= 0x0000FFFFFFFFFFFFL) {\n    n = n + 16;\n    x = x << 16;\n  }\n\n  if (x <= 0x00FFFFFFFFFFFFFFL) {\n    n = n + 8;\n    x = x << 8;\n  }\n\n  if (x <= 0x0FFFFFFFFFFFFFFFL) {\n    n = n + 4;\n    x = x << 4;\n  }\n\n  if (x <= 0x3FFFFFFFFFFFFFFFL) {\n    n = n + 2;\n    x = x << 2;\n  }\n\n  if (x <= 0x7FFFFFFFFFFFFFFFL) {\n    n = n + 1;\n  }\n\n  return n;\n}\n\n#define CLZ clzll\n#endif\n#endif\n\nstatic __inline int compute_minrun(const uint64_t size) {\n  const int top_bit = 64 - CLZ(size);\n  const int shift = MAX(top_bit, 6) - 6;\n  const int minrun = size >> shift;\n  const uint64_t mask = (1ULL << shift) - 1;\n\n  if (mask & size) {\n    return minrun + 1;\n  }\n\n  return minrun;\n}\n\n#endif /* SORT_COMMON_H */\n\n#define SORT_CONCAT(x, y) x ## _ ## y\n#define SORT_MAKE_STR1(x, y) SORT_CONCAT(x,y)\n#define SORT_MAKE_STR(x) SORT_MAKE_STR1(SORT_NAME,x)\n\n#define BINARY_INSERTION_FIND          SORT_MAKE_STR(binary_insertion_find)\n#define BINARY_INSERTION_SORT_START    SORT_MAKE_STR(binary_insertion_sort_start)\n#define BINARY_INSERTION_SORT          SORT_MAKE_STR(binary_insertion_sort)\n#define REVERSE_ELEMENTS               SORT_MAKE_STR(reverse_elements)\n#define COUNT_RUN                      SORT_MAKE_STR(count_run)\n#define CHECK_INVARIANT                SORT_MAKE_STR(check_invariant)\n#define TIM_SORT                       SORT_MAKE_STR(tim_sort)\n#define TIM_SORT_RESIZE                SORT_MAKE_STR(tim_sort_resize)\n#define TIM_SORT_MERGE                 SORT_MAKE_STR(tim_sort_merge)\n#define TIM_SORT_COLLAPSE              SORT_MAKE_STR(tim_sort_collapse)\n\n#ifndef MAX\n#define MAX(x,y) (((x) > (y) ? (x) : (y)))\n#endif\n#ifndef MIN\n#define MIN(x,y) (((x) < (y) ? (x) : (y)))\n#endif\n\ntypedef struct {\n  size_t start;\n  size_t length;\n} TIM_SORT_RUN_T;\n\n\nvoid BINARY_INSERTION_SORT(B_Ord w, SORT_TYPE *dst, const size_t size);\nvoid TIM_SORT(B_Ord w, SORT_TYPE *dst, const size_t size);\n\n\n/* Function used to do a binary search for binary insertion sort */\nstatic __inline size_t BINARY_INSERTION_FIND(B_Ord w, SORT_TYPE *dst, const SORT_TYPE x,\n    const size_t size) {\n  size_t l, c, r;\n  SORT_TYPE cx;\n  l = 0;\n  r = size - 1;\n  c = r >> 1;\n\n  /* check for out of bounds at the beginning. */\n  if (SORT_CMP(w, x, dst[0]) < 0) {\n    return 0;\n  } else if (SORT_CMP(w, x, dst[r]) > 0) {\n    return r;\n  }\n\n  cx = dst[c];\n\n  while (1) {\n      const int val = SORT_CMP(w, x, cx);\n    if (val < 0) {\n      if (c - l <= 1) {\n        return c;\n      }\n\n      r = c;\n    } else { /* allow = for stability. The binary search favors the right. */\n      if (r - c <= 1) {\n        return c + 1;\n      }\n\n      l = c;\n    }\n\n    c = l + ((r - l) >> 1);\n    cx = dst[c];\n  }\n}\n\n/* Binary insertion sort, but knowing that the first \"start\" entries are sorted.  Used in timsort. */\nstatic void BINARY_INSERTION_SORT_START(B_Ord w, SORT_TYPE *dst, const size_t start, const size_t size) {\n  size_t i;\n\n  for (i = start; i < size; i++) {\n    size_t j;\n    SORT_TYPE x;\n    size_t location;\n\n    /* If this entry is already correct, just move along */\n    if (SORT_CMP(w, dst[i - 1], dst[i]) <= 0) {\n      continue;\n    }\n\n    /* Else we need to find the right place, shift everything over, and squeeze in */\n    x = dst[i];\n    location = BINARY_INSERTION_FIND(w, dst, x, i);\n    for (j = i - 1; j >= location; j--) {\n      dst[j + 1] = dst[j];\n\n      if (j == 0) { /* check edge case because j is unsigned */\n        break;\n      }\n    }\n\n    dst[location] = x;\n  }\n}\n\n/* Binary insertion sort */\nvoid BINARY_INSERTION_SORT(B_Ord w, SORT_TYPE *dst, const size_t size) {\n  /* don't bother sorting an array of size <= 1 */\n  if (size <= 1) {\n    return;\n  }\n\n  BINARY_INSERTION_SORT_START(w, dst, 1, size);\n}\n\n/* timsort implementation, based on timsort.txt */\n\nstatic __inline void REVERSE_ELEMENTS(SORT_TYPE *dst, size_t start, size_t end) {\n  while (1) {\n    if (start >= end) {\n      return;\n    }\n\n    SORT_SWAP(dst[start], dst[end]);\n    start++;\n    end--;\n  }\n}\n\nstatic size_t COUNT_RUN(B_Ord w, SORT_TYPE *dst, const size_t start, const size_t size) {\n  size_t curr;\n\n  if (size - start == 1) {\n    return 1;\n  }\n\n  if (start >= size - 2) {\n      if (SORT_CMP(w, dst[size - 2], dst[size - 1]) > 0) {\n      SORT_SWAP(dst[size - 2], dst[size - 1]);\n    }\n\n    return 2;\n  }\n\n  curr = start + 2;\n\n  if (SORT_CMP(w, dst[start], dst[start + 1]) <= 0) {\n    /* increasing run */\n    while (1) {\n      if (curr == size - 1) {\n        break;\n      }\n\n      if (SORT_CMP(w, dst[curr - 1], dst[curr]) > 0) {\n        break;\n      }\n\n      curr++;\n    }\n\n    return curr - start;\n  } else {\n    /* decreasing run */\n    while (1) {\n      if (curr == size - 1) {\n        break;\n      }\n\n      if (SORT_CMP(w, dst[curr - 1], dst[curr]) <= 0) {\n        break;\n      }\n\n      curr++;\n    }\n\n    /* reverse in-place */\n    REVERSE_ELEMENTS(dst, start, curr - 1);\n    return curr - start;\n  }\n}\n\nstatic int CHECK_INVARIANT(TIM_SORT_RUN_T *stack, const int stack_curr) {\n  size_t A, B, C;\n\n  if (stack_curr < 2) {\n    return 1;\n  }\n\n  if (stack_curr == 2) {\n    const size_t A1 = stack[stack_curr - 2].length;\n    const size_t B1 = stack[stack_curr - 1].length;\n\n    if (A1 <= B1) {\n      return 0;\n    }\n\n    return 1;\n  }\n\n  A = stack[stack_curr - 3].length;\n  B = stack[stack_curr - 2].length;\n  C = stack[stack_curr - 1].length;\n\n  if ((A <= B + C) || (B <= C)) {\n    return 0;\n  }\n\n  return 1;\n}\n\ntypedef struct {\n  size_t alloc;\n  SORT_TYPE *storage;\n} TEMP_STORAGE_T;\n\nstatic void TIM_SORT_RESIZE(TEMP_STORAGE_T *store, const size_t new_size) {\n  if (store->alloc < new_size) {\n    SORT_TYPE *tempstore = (SORT_TYPE *)acton_realloc(store->storage, new_size * sizeof(SORT_TYPE));\n\n    if (tempstore == NULL) {\n      fprintf(stderr, \"Error allocating temporary storage for tim sort: need %lu bytes\",\n              (unsigned long)(sizeof(SORT_TYPE) * new_size));\n      exit(1);\n    }\n\n    store->storage = tempstore;\n    store->alloc = new_size;\n  }\n}\n\nstatic void TIM_SORT_MERGE(B_Ord w, SORT_TYPE *dst, const TIM_SORT_RUN_T *stack, const int stack_curr,\n                           TEMP_STORAGE_T *store) {\n  const size_t A = stack[stack_curr - 2].length;\n  const size_t B = stack[stack_curr - 1].length;\n  const size_t curr = stack[stack_curr - 2].start;\n  SORT_TYPE *storage;\n  size_t i, j, k;\n  TIM_SORT_RESIZE(store, MIN(A, B));\n  storage = store->storage;\n\n  /* left merge */\n  if (A < B) {\n    memcpy(storage, &dst[curr], A * sizeof(SORT_TYPE));\n    i = 0;\n    j = curr + A;\n\n    for (k = curr; k < curr + A + B; k++) {\n      if ((i < A) && (j < curr + A + B)) {\n          if (SORT_CMP(w, storage[i], dst[j]) <= 0) {\n          dst[k] = storage[i++];\n        } else {\n          dst[k] = dst[j++];\n        }\n      } else if (i < A) {\n        dst[k] = storage[i++];\n      } else {\n        break;\n      }\n    }\n  } else {\n    /* right merge */\n    memcpy(storage, &dst[curr + A], B * sizeof(SORT_TYPE));\n    i = B;\n    j = curr + A;\n    k = curr + A + B;\n\n    while (k > curr) {\n      k--;\n      if ((i > 0) && (j > curr)) {\n          if (SORT_CMP(w, dst[j - 1], storage[i - 1]) > 0) {\n          dst[k] = dst[--j];\n        } else {\n          dst[k] = storage[--i];\n        }\n      } else if (i > 0) {\n        dst[k] = storage[--i];\n      } else {\n        break;\n      }\n    }\n  }\n}\n\nstatic int TIM_SORT_COLLAPSE(B_Ord w, SORT_TYPE *dst, TIM_SORT_RUN_T *stack, int stack_curr,\n                             TEMP_STORAGE_T *store, const size_t size) {\n  while (1) {\n    size_t A, B, C, D;\n    int ABC, BCD, CD;\n\n    /* if the stack only has one thing on it, we are done with the collapse */\n    if (stack_curr <= 1) {\n      break;\n    }\n\n    /* if this is the last merge, just do it */\n    if ((stack_curr == 2) && (stack[0].length + stack[1].length == size)) {\n        TIM_SORT_MERGE(w, dst, stack, stack_curr, store);\n      stack[0].length += stack[1].length;\n      stack_curr--;\n      break;\n    }\n    /* check if the invariant is off for a stack of 2 elements */\n    else if ((stack_curr == 2) && (stack[0].length <= stack[1].length)) {\n        TIM_SORT_MERGE(w, dst, stack, stack_curr, store);\n      stack[0].length += stack[1].length;\n      stack_curr--;\n      break;\n    } else if (stack_curr == 2) {\n      break;\n    }\n\n    B = stack[stack_curr - 3].length;\n    C = stack[stack_curr - 2].length;\n    D = stack[stack_curr - 1].length;\n\n    if (stack_curr >= 4) {\n      A = stack[stack_curr - 4].length;\n      ABC = (A <= B + C);\n    } else {\n      ABC = 0;\n    }\n\n    BCD = (B <= C + D) || ABC;\n    CD = (C <= D);\n\n    /* Both invariants are good */\n    if (!BCD && !CD) {\n      break;\n    }\n\n    /* left merge */\n    if (BCD && !CD) {\n        TIM_SORT_MERGE(w, dst, stack, stack_curr - 1, store);\n      stack[stack_curr - 3].length += stack[stack_curr - 2].length;\n      stack[stack_curr - 2] = stack[stack_curr - 1];\n      stack_curr--;\n    } else {\n      /* right merge */\n        TIM_SORT_MERGE(w, dst, stack, stack_curr, store);\n      stack[stack_curr - 2].length += stack[stack_curr - 1].length;\n      stack_curr--;\n    }\n  }\n\n  return stack_curr;\n}\n\nstatic __inline int PUSH_NEXT(B_Ord w,\n                              SORT_TYPE *dst,\n                              const size_t size,\n                              TEMP_STORAGE_T *store,\n                              const size_t minrun,\n                              TIM_SORT_RUN_T *run_stack,\n                              size_t *stack_curr,\n                              size_t *curr) {\n    size_t len = COUNT_RUN(w, dst, *curr, size);\n  size_t run = minrun;\n\n  if (run > size - *curr) {\n    run = size - *curr;\n  }\n\n  if (run > len) {\n      BINARY_INSERTION_SORT_START(w, &dst[*curr], len, run);\n    len = run;\n  }\n\n  run_stack[*stack_curr].start = *curr;\n  run_stack[*stack_curr].length = len;\n  (*stack_curr)++;\n  *curr += len;\n\n  if (*curr == size) {\n    /* finish up */\n    while (*stack_curr > 1) {\n        TIM_SORT_MERGE(w, dst, run_stack, *stack_curr, store);\n      run_stack[*stack_curr - 2].length += run_stack[*stack_curr - 1].length;\n      (*stack_curr)--;\n    }\n\n    if (store->storage != NULL) {\n      acton_free(store->storage);\n      store->storage = NULL;\n    }\n\n    return 0;\n  }\n\n  return 1;\n}\n\nvoid TIM_SORT(B_Ord w, SORT_TYPE *dst, const size_t size) {\n  size_t minrun;\n  TEMP_STORAGE_T _store, *store;\n  TIM_SORT_RUN_T run_stack[TIM_SORT_STACK_SIZE];\n  size_t stack_curr = 0;\n  size_t curr = 0;\n\n  /* don't bother sorting an array of size 1 */\n  if (size <= 1) {\n    return;\n  }\n\n  if (size < 64) {\n      BINARY_INSERTION_SORT(w, dst, size);\n    return;\n  }\n\n  /* compute the minimum run length */\n  minrun = compute_minrun(size);\n  /* temporary storage for merges */\n  store = &_store;\n  store->alloc = 0;\n  store->storage = NULL;\n\n  if (!PUSH_NEXT(w, dst, size, store, minrun, run_stack, &stack_curr, &curr)) {\n    return;\n  }\n\n  if (!PUSH_NEXT(w, dst, size, store, minrun, run_stack, &stack_curr, &curr)) {\n    return;\n  }\n\n  if (!PUSH_NEXT(w, dst, size, store, minrun, run_stack, &stack_curr, &curr)) {\n    return;\n  }\n\n  while (1) {\n    if (!CHECK_INVARIANT(run_stack, stack_curr)) {\n        stack_curr = TIM_SORT_COLLAPSE(w, dst, run_stack, stack_curr, store, size);\n      continue;\n    }\n\n    if (!PUSH_NEXT(w, dst, size, store, minrun, run_stack, &stack_curr, &curr)) {\n      return;\n    }\n  }\n}\n\n#undef SORT_CONCAT\n#undef SORT_MAKE_STR1\n#undef SORT_MAKE_STR\n#undef SORT_NAME\n#undef SORT_TYPE\n#undef SORT_CMP\n#undef TEMP_STORAGE_T\n#undef TIM_SORT_RUN_T\n#undef PUSH_NEXT\n#undef SORT_SWAP\n#undef SORT_CONCAT\n#undef SORT_MAKE_STR1\n#undef SORT_MAKE_STR\n#undef BINARY_INSERTION_FIND\n#undef BINARY_INSERTION_SORT_START\n#undef BINARY_INSERTION_SORT\n#undef REVERSE_ELEMENTS\n#undef COUNT_RUN\n#undef TIM_SORT\n#undef TIM_SORT_RESIZE\n#undef TIM_SORT_COLLAPSE\n#undef TIM_SORT_RUN_T\n#undef TEMP_STORAGE_T\n"
  },
  {
    "path": "base/builtin/tuple.c",
    "content": "/*\n * Copyright (C) 2019-2021 Data Ductus AB\n *\n * Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:\n *\n * 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.\n *\n * 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.\n *\n * 3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission.\n *\n * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS \"AS IS\" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n */\n\n#include <stdarg.h>\n\nB_NoneType B_tupleD___init__(B_tuple self,int size ,...) {\n    va_list args;\n    va_start(args,size);\n    self->size = size;\n    self->components = acton_malloc(size*sizeof($WORD));\n    for (int i=0; i<size; i++)\n        self->components[i] = va_arg(args,$WORD);\n    va_end(args);\n    return B_None;\n}\n\nB_bool B_tupleD___bool__(B_tuple self) {\n    return toB_bool(self->size>0);\n}\n\nB_str B_tupleD___str__(B_tuple self) {\n    B_list s2 = B_listD_new(self->size);\n    B_SequenceD_list wit = B_SequenceD_listG_witness;\n    for (int i=0; i< self->size; i++) {\n        B_value elem = (B_value)self->components[i];\n        if (elem == NULL) {\n            wit->$class->append(wit,s2,to$str(\"None\"));\n        } else {\n            wit->$class->append(wit,s2,elem->$class->__repr__(elem));\n        }\n    }\n    return B_strD_join_par('(',s2,')');\n}\n\n\nvoid B_tupleD___serialize__(B_tuple self, $Serial$state state) {\n    B_int prevkey = (B_int)B_dictD_get(state->done,(B_Hashable)B_HashableD_WORDG_witness,self,NULL);\n    if (prevkey) {\n        $val_serialize(-TUPLE_ID,&prevkey->val,state);\n        return;\n    }\n    B_dictD_setitem(state->done,(B_Hashable)B_HashableD_WORDG_witness,self,toB_int(state->row_no));\n    long len = (long)self->size;\n    $val_serialize(TUPLE_ID,&len,state);\n    for (int i=0; i<self->size; i++) {\n        $step_serialize(self->components[i],state);\n    }\n}\n\nB_tuple B_tupleD___deserialize__(B_tuple self, $Serial$state state) {\n    $ROW this = state->row;\n    state->row = this->next;\n    state->row_no++;\n    if (this->class_id < 0) {\n        return (B_tuple)B_dictD_get(state->done,(B_Hashable)B_HashableD_intG_witness,toB_int((long)this->blob[0]),NULL);\n    } else {\n        int len = (int)(long)this->blob[0];\n        B_tuple res = acton_malloc(sizeof(struct B_tuple));\n        B_dictD_setitem(state->done,(B_Hashable)B_HashableD_intG_witness,toB_int(state->row_no-1),res);\n        res->components = acton_malloc(len * sizeof($WORD));\n        res->$class = &B_tupleG_methods;\n        res->size = len;\n        for (int i = 0; i < len; i++) \n            res->components[i] = $step_deserialize(state);\n        return res;\n    }\n}\n\nstruct B_tupleG_class B_tupleG_methods = {\n    \"tuple\",\n    UNASSIGNED,\n    ($SuperG_class)&B_valueG_methods,\n    B_tupleD___init__,\n    B_tupleD___serialize__,\n    B_tupleD___deserialize__,\n    B_tupleD___bool__,\n    B_tupleD___str__,\n    B_tupleD___str__\n};\n// Iterators over tuples ///////////////////////////////////////////////////////\n\nstatic $WORD B_IteratorD_tupleD_next(B_IteratorD_tuple self) {\n    return self->nxt >= self->src->size ? NULL : self->src->components[self->nxt++];\n}\n\nB_NoneType B_IteratorD_tupleD_init(B_IteratorD_tuple self, B_tuple lst) {\n    self->src = lst;\n    self->nxt = 0;\n    return B_None;\n}\n\nB_bool B_IteratorD_tupleD_bool(B_IteratorD_tuple self) {\n    return B_True;\n}\n\nB_str B_IteratorD_tupleD_str(B_IteratorD_tuple self) {\n    return $FORMAT(\"<tuple iterator object at %p>\", self);\n}\nvoid B_IteratorD_tupleD_serialize(B_IteratorD_tuple self,$Serial$state state) {\n    $step_serialize(self->src,state);\n    $step_serialize(toB_int(self->nxt),state);\n}\n\nB_IteratorD_tuple B_IteratorD_tuple$_deserialize(B_IteratorD_tuple res, $Serial$state state) {\n    if (!res)\n        res = $DNEW(B_IteratorD_tuple,state);\n    res->src = $step_deserialize(state);\n    res->nxt = fromB_int((B_int)$step_deserialize(state));\n    return res;\n}\n\nstruct B_IteratorD_tupleG_class B_IteratorD_tupleG_methods = {\"B_IteratorD_tuple\",UNASSIGNED,($SuperG_class)&B_IteratorG_methods,B_IteratorD_tupleD_init,\n                                                        B_IteratorD_tupleD_serialize,B_IteratorD_tuple$_deserialize,B_IteratorD_tupleD_bool,B_IteratorD_tupleD_str,B_IteratorD_tupleD_str,B_IteratorD_tupleD_next};\n\n\n// Iterable ///////////////////////////////////////////////////////////////\n\nB_Iterator B_IterableD_tupleD___iter__(B_IterableD_tuple wit, B_tuple self) {\n    return (B_Iterator)$NEW(B_IteratorD_tuple,self);\n}\n\nB_NoneType B_IterableD_tupleD___init__(B_IterableD_tuple self) {\n    return B_None;\n}\n\nvoid B_IterableD_tupleD___serialize__(B_IterableD_tuple self, $Serial$state state) {\n}\n\nB_IterableD_tuple B_IterableD_tupleD___deserialize__(B_IterableD_tuple self, $Serial$state state) {\n    B_IterableD_tuple res = $DNEW(B_IterableD_tuple,state);\n    return res;\n}\nstruct B_IterableD_tupleG_class B_IterableD_tupleG_methods = {\n    \"B_IterableD_tuple\",\n    UNASSIGNED,\n    ($SuperG_class)&B_IterableG_methods,\n    B_IterableD_tupleD___init__,\n    B_IterableD_tupleD___serialize__,\n    B_IterableD_tupleD___deserialize__,\n    (B_bool (*)(B_IterableD_tuple))$default__bool__,\n    (B_str (*)(B_IterableD_tuple))$default__str__,\n    (B_str (*)(B_IterableD_tuple))$default__str__,\n    B_IterableD_tupleD___iter__\n};\n//struct B_IterableD_tuple B_IterableD_tuple$instance = {&B_IterableD_tupleG_methods};\n//struct B_IterableD_tuple *B_IterableD_tupleG_witness = &B_IterableD_tuple$instance;\n\n// Sliceable ///////////////////////////////////////////////////////////////\n\nvoid B_SliceableD_tupleD___serialize__(B_SliceableD_tuple self, $Serial$state state) {\n}\n\nB_SliceableD_tuple B_SliceableD_tupleD___deserialize__(B_SliceableD_tuple self, $Serial$state state) {\n    B_SliceableD_tuple res = $DNEW(B_SliceableD_tuple,state);\n    return res;\n}\n\nB_NoneType B_SliceableD_tupleD___init__ (B_SliceableD_tuple wit) {\n    return B_None;\n}\n\n$WORD B_SliceableD_tupleD___getitem__ (B_SliceableD_tuple wit, B_tuple self, B_int n) {\n    int size = self->size;\n    int ix = fromB_int(n);\n    int ix0 = ix < 0 ? size + ix : ix;\n    if (ix0 < 0 || ix0 >= size) {\n        $RAISE((B_BaseException)$NEW(B_IndexError, toB_int(ix0), to$str(\"tuple.getitem: index outside tuple\")));\n    }\n    return self->components[ix0];\n}\n\n\nB_NoneType B_SliceableD_tupleD___setitem__ (B_SliceableD_tuple wit, B_tuple self, B_int ix, $WORD elem) {\n    $RAISE((B_BaseException)$NEW(B_NotImplementedError,to$str(\"call to mutating method setitem on tuple\")));\n    return B_None;\n}\n\nB_NoneType B_SliceableD_tupleD___delitem__ (B_SliceableD_tuple wit, B_tuple self, B_int ix) {\n    $RAISE((B_BaseException)$NEW(B_NotImplementedError,to$str(\"call to mutating method delitem on tuple\")));\n    return B_None;\n}\n  \n\nB_tuple B_SliceableD_tupleD___getslice__ (B_SliceableD_tuple wit, B_tuple self, B_slice slc) {\n    int size = self->size;\n    int64_t start, stop, step, slen;\n    normalize_slice(slc, size, &slen, &start, &stop, &step);\n    //slice notation have been eliminated and default values applied.\n    // slen now is the length of the slice\n    B_tuple res = acton_malloc(sizeof(struct B_tuple));\n    res->$class = self->$class;\n    res->size = slen;\n    res->components = acton_malloc(slen * sizeof($WORD));\n    int t = start;\n    for (int i=0; i<slen; i++) {\n        res->components[i] = self->components[t];\n        t += step;\n    }\n    return res;\n}\n\nB_NoneType B_SliceableD_tupleD___setslice__ (B_SliceableD_tuple wit, B_tuple self, B_Iterable wit2, B_slice slc, $WORD iter) {\n    $RAISE((B_BaseException)$NEW(B_NotImplementedError,to$str(\"call to mutating method setslice on tuple\")));\n    return B_None;\n}\n\nB_NoneType B_SliceableD_tupleD___delslice__ (B_SliceableD_tuple wit, B_tuple self, B_slice slc) {\n    $RAISE((B_BaseException)$NEW(B_NotImplementedError,to$str(\"call to mutating method delslice on tuple\")));\n    return B_None;\n}\n\nstruct B_SliceableD_tupleG_class B_SliceableD_tupleG_methods = {\n    \"B_SliceableD_tuple\",\n    UNASSIGNED,\n    ($SuperG_class)&B_SliceableG_methods,\n    B_SliceableD_tupleD___init__,\n    B_SliceableD_tupleD___serialize__,\n    B_SliceableD_tupleD___deserialize__,\n    (B_bool (*)(B_SliceableD_tuple))$default__bool__,\n    (B_str (*)(B_SliceableD_tuple))$default__str__,\n    (B_str (*)(B_SliceableD_tuple))$default__str__,\n    B_SliceableD_tupleD___getitem__,\n    B_SliceableD_tupleD___setitem__,\n    B_SliceableD_tupleD___delitem__,\n    B_SliceableD_tupleD___getslice__,\n    B_SliceableD_tupleD___setslice__,\n    B_SliceableD_tupleD___delslice__\n};\n\n// Hashable ///////////////////////////////////////////////////////////////\n\nB_NoneType B_HashableD_tupleD___init__ (B_HashableD_tuple wit, int n, B_Hashable *comps) {\n    wit->W_HashableB_tuple$size = n;\n    wit->W_Hashable = comps;\n    return B_None;\n}\n\nvoid B_HashableD_tupleD___serialize__(B_HashableD_tuple self, $Serial$state state) {\n    $step_serialize(toB_int(self->W_HashableB_tuple$size), state);\n    // we need to serialize the array of Hashables!!\n}\n\nB_HashableD_tuple B_HashableD_tupleD___deserialize__(B_HashableD_tuple self, $Serial$state state) {\n    B_HashableD_tuple res = $DNEW(B_HashableD_tuple,state);\n    res->W_HashableB_tuple$size = fromB_int($step_deserialize(state));\n    res->W_Hashable = NULL; // We do not get hash functions for the tuple!\n    return res;\n}\n\nB_bool B_HashableD_tupleD___eq__ (B_HashableD_tuple wit, B_tuple tup1, B_tuple tup2) {\n    //type-checking guarantees that sizes are equal\n    for (int i=0; i<tup1->size; i++)\n        if (!wit->W_Hashable[i]->$class->__eq__(wit->W_Hashable[i],tup1->components[i],tup2->components[i]))\n            return B_False;\n    return B_True;\n}\n\nB_bool B_HashableD_tupleD___ne__ (B_HashableD_tuple wit, B_tuple tup1, B_tuple tup2) {\n    return toB_bool(!fromB_bool(B_HashableD_tupleD___eq__(wit,tup1,tup2)));\n}\n    \n  \n// B_int B_HashableD_tupleD___hash__ (B_HashableD_tuple wit, B_tuple tup) {\n//    return toB_int(B_tupleD_hash(wit,tup));\n// }\n\nstruct B_HashableD_tupleG_class B_HashableD_tupleG_methods = {\n    \"B_HashableD_tuple\",\n    UNASSIGNED,\n    ($SuperG_class)&B_HashableG_methods,\n    B_HashableD_tupleD___init__,\n    B_HashableD_tupleD___serialize__,\n    B_HashableD_tupleD___deserialize__,\n    (B_bool (*)(B_HashableD_tuple))$default__bool__,\n    (B_str (*)(B_HashableD_tuple))$default__str__,\n    (B_str (*)(B_HashableD_tuple))$default__str__,\n    B_HashableD_tupleD___eq__,\n    B_HashableD_tupleD___ne__\n};\n"
  },
  {
    "path": "base/builtin/tuple.h",
    "content": "struct B_tupleG_class {\n    char *$GCINFO;\n    int $class_id;\n    $SuperG_class $superclass;\n    B_NoneType (*__init__)(B_tuple,int,...);\n    void (*__serialize__)(B_tuple,$Serial$state); \n    B_tuple (*__deserialize__)(B_tuple,$Serial$state);\n    B_bool (*__bool__)(B_tuple);\n    B_str (*__str__)(B_tuple);\n    B_str (*__repr__)(B_tuple);\n};\n\nstruct B_tuple {\n    struct B_tupleG_class *$class;\n    int size;\n    $WORD *components;\n};\n\nextern struct B_tupleG_class B_tupleG_methods;\nB_tuple B_tupleG_new(int,...);\n\n#define $NEWTUPLE(B_len, ...)  ({ B_tuple $t = acton_malloc(sizeof(struct B_tuple)+B_len*sizeof($WORD)); \\\n            $t->$class = &B_tupleG_methods;                               \\\n            $t->$class->__init__($t, B_len, __VA_ARGS__);                \\\n            $t; })\n\n#define $NEWTUPLE0  ({ B_tuple $t = acton_malloc(sizeof(struct B_tuple));       \\\n            $t->$class = &B_tupleG_methods;                               \\\n            $t->$class->__init__($t,0);                                  \\\n            $t; })\n\n\n\n// struct definitions for tuple protocol instances are not in __builtin__.h\n// (They cannot be expressed in __builtin__.act for lack of syntax)\n\nstruct B_IterableD_tuple;\ntypedef struct B_IterableD_tuple *B_IterableD_tuple;\n\nstruct B_IterableD_tupleG_class;\ntypedef struct B_IterableD_tupleG_class *B_IterableD_tupleG_class;\n\nstruct B_SliceableD_tuple;\ntypedef struct B_SliceableD_tuple *B_SliceableD_tuple;\n\nstruct B_SliceableD_tupleG_class;\ntypedef struct B_SliceableD_tupleG_class *B_SliceableD_tupleG_class;\n\nstruct B_HashableD_tuple;\ntypedef struct B_HashableD_tuple *B_HashableD_tuple;\n\nstruct B_HashableD_tupleG_class;\ntypedef struct B_HashableD_tupleG_class *B_HashableD_tupleG_class;\n\n// B_IterableD_tuple ////////////////////////////////////////////////////////////\n\nstruct B_IterableD_tuple {\n    B_IterableD_tupleG_class $class;\n};\n\nstruct B_IterableD_tupleG_class {\n    char *$GCINFO;\n    int $class_id;\n    $SuperG_class $superclass;\n    B_NoneType (*__init__)(B_IterableD_tuple);\n    void (*__serialize__)(B_IterableD_tuple,$Serial$state);\n    B_IterableD_tuple (*__deserialize__)(B_IterableD_tuple,$Serial$state);\n    B_bool (*__bool__)(B_IterableD_tuple);\n    B_str (*__str__)(B_IterableD_tuple);\n    B_str (*__repr__)(B_IterableD_tuple);\n    B_Iterator (*__iter__)(B_IterableD_tuple, B_tuple);\n};\n\nB_NoneType B_IterableD_tupleD___init__ (B_IterableD_tuple);\nvoid B_IterableD_tupleD___serialize__(B_IterableD_tuple, $Serial$state);\nB_IterableD_tuple B_IterableD_tupleD___deserialize__(B_IterableD_tuple, $Serial$state);\nB_Iterator B_IterableD_tupleD___iter__ (B_IterableD_tuple, B_tuple);\n\nextern struct B_IterableD_tupleG_class B_IterableD_tupleG_methods;\nB_IterableD_tuple B_IterableD_tupleG_new();\n\n// B_SliceableD_tuple ////////////////////////////////////////////////////////////\n\n// all methods except getitem and getslice will raise NotImplementedError\n\nstruct B_SliceableD_tuple {\n    B_SliceableD_tupleG_class $class;\n};\n\nstruct B_SliceableD_tupleG_class {\n    char *$GCINFO;\n    int $class_id;\n    $SuperG_class $superclass;\n    B_NoneType (*__init__)(B_SliceableD_tuple);\n    void (*__serialize__)(B_SliceableD_tuple,$Serial$state);\n    B_SliceableD_tuple (*__deserialize__)(B_SliceableD_tuple,$Serial$state);\n    B_bool (*__bool__)(B_SliceableD_tuple);\n    B_str (*__str__)(B_SliceableD_tuple);\n    B_str (*__repr__)(B_SliceableD_tuple);\n    $WORD (*__getitem__)(B_SliceableD_tuple, B_tuple, B_int);\n    B_NoneType (*__setitem__)(B_SliceableD_tuple, B_tuple, B_int, $WORD);\n    B_NoneType (*__delitem__)(B_SliceableD_tuple, B_tuple, B_int);\n    B_tuple (*__getslice__)(B_SliceableD_tuple, B_tuple, B_slice);\n    B_NoneType (*__setslice__)(B_SliceableD_tuple, B_tuple, B_Iterable, B_slice, $WORD);\n    B_NoneType (*__delslice__)(B_SliceableD_tuple, B_tuple, B_slice);\n};\n\nB_NoneType B_SliceableD_tupleD___init__ (B_SliceableD_tuple);\nvoid B_SliceableD_tupleD___serialize__(B_SliceableD_tuple, $Serial$state);\nB_SliceableD_tuple B_SliceableD_tupleD___deserialize__(B_SliceableD_tuple, $Serial$state);\n$WORD B_SliceableD_tupleD___getitem__ (B_SliceableD_tuple, B_tuple, B_int);\nB_NoneType B_SliceableD_tupleD___setitem__ (B_SliceableD_tuple, B_tuple, B_int, $WORD);\nB_NoneType B_SliceableD_tupleD___delitem__ (B_SliceableD_tuple, B_tuple, B_int);\nB_tuple B_SliceableD_tupleD___getslice__ (B_SliceableD_tuple, B_tuple, B_slice);\nB_NoneType B_SliceableD_tupleD___setslice__ (B_SliceableD_tuple, B_tuple, B_Iterable, B_slice, $WORD);\nB_NoneType B_SliceableD_tupleD___delslice__ (B_SliceableD_tuple, B_tuple, B_slice);\n\nextern struct B_SliceableD_tupleG_class B_SliceableD_tupleG_methods;\nB_SliceableD_tuple B_SliceableD_tupleG_new();\n\n// B_HashableD_tuple ////////////////////////////////////////////////////////////\n\nstruct B_HashableD_tuple {\n    B_HashableD_tupleG_class $class;\n    int W_HashableB_tuple$size;\n    B_Hashable *W_Hashable;\n};\n\nstruct B_HashableD_tupleG_class {\n    char *$GCINFO;\n    int $class_id;\n    $SuperG_class $superclass;\n    B_NoneType (*__init__)(B_HashableD_tuple,int,B_Hashable*);\n    void (*__serialize__)(B_HashableD_tuple,$Serial$state);\n    B_HashableD_tuple (*__deserialize__)(B_HashableD_tuple,$Serial$state);\n    B_bool (*__bool__)(B_HashableD_tuple);\n    B_str (*__str__)(B_HashableD_tuple);\n    B_str (*__repr__)(B_HashableD_tuple);\n    B_bool (*__eq__)(B_HashableD_tuple, B_tuple, B_tuple);\n    B_bool (*__ne__)(B_HashableD_tuple, B_tuple, B_tuple);\n    B_NoneType (*hash) (B_HashableD_tuple, B_tuple, B_hasher);\n};\n  \nB_NoneType B_HashableD_tupleD___init__ (B_HashableD_tuple,int,B_Hashable*);\nvoid B_HashableD_tupleD___serialize__(B_HashableD_tuple, $Serial$state);\nB_HashableD_tuple B_HashableD_tupleD___deserialize__(B_HashableD_tuple, $Serial$state);\nB_bool B_HashableD_tupleD___eq__ (B_HashableD_tuple, B_tuple, B_tuple);\nB_bool B_HashableD_tupleD___ne__ (B_HashableD_tuple, B_tuple, B_tuple);\nB_NoneType B_HashableD_tupleD_hash (B_HashableD_tuple, B_tuple, B_hasher);\n\nextern struct B_HashableD_tupleG_class B_HashableD_tupleG_methods;\nB_HashableD_tuple B_HashableD_tupleG_new();\n\nextern struct B_IterableD_tupleG_class B_IterableD_tupleG_methods;\nB_IterableD_tuple B_IterableD_tupleG_new();\nextern struct B_SliceableD_tupleG_class B_SliceableD_tupleG_methods;\nB_SliceableD_tuple B_SliceableD_tupleG_new();\nextern struct B_HashableD_tupleG_class B_HashableD_tupleG_methods;\nB_HashableD_tuple B_HashableD_tupleG_new();\n\nextern struct B_HashableD_tuple *B_HashableD_tuple_new(int,B_Hashable*);\n\n// Iterators over tuples ///////////////////////////////////////////////////////\n\ntypedef struct B_IteratorD_tuple *B_IteratorD_tuple;\n\nstruct B_IteratorD_tupleG_class {\n    char *$GCINFO;\n    int $class_id;\n    $SuperG_class $superclass;\n    B_NoneType (*__init__)(B_IteratorD_tuple, B_tuple);\n    void (*__serialize__)(B_IteratorD_tuple,$Serial$state);\n    B_IteratorD_tuple (*__deserialize__)(B_IteratorD_tuple,$Serial$state);\n    B_bool (*__bool__)(B_IteratorD_tuple);\n    B_str (*__str__)(B_IteratorD_tuple);\n    B_str (*__repr__)(B_IteratorD_tuple);\n    $WORD(*__next__)(B_IteratorD_tuple);\n};\n\nstruct B_IteratorD_tuple {\n    struct B_IteratorD_tupleG_class *$class;\n    B_tuple src;\n    int nxt;\n};\n\nextern struct B_IteratorD_tupleG_class B_IteratorD_tupleG_methods;\nB_IteratorD_tuple B_IteratorD_tupleG_new(B_tuple);\n"
  },
  {
    "path": "base/builtin/u1.c",
    "content": "/*\n * Copyright (C) 2019-2021 Data Ductus AB\n *\n * Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:\n *\n * 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.\n *\n * 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.\n *\n * 3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission.\n *\n * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS \"AS IS\" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n */\n\n// Auxiliary //////////////////////////////////////////////////////////////////////////////\n\n// only called with e>=0.\nuint8_t u1_pow(uint8_t a, uint8_t e) {\n    if (e == 0) return 1;\n    return a;\n}\n\n// General methods ///////////////////////////////////////////////////////////////////////\n\nB_u1 B_u1G_new(B_atom a, B_int base) {\n    B_bigint b = B_bigintG_new(a, base);\n    long sz = b->val.size;\n    if (sz == 0) return toB_u1(0);\n    unsigned long n = b->val.n[0];\n    if (sz != 1 || n > 1) {\n        char errmsg[1024];\n        snprintf(errmsg, sizeof(errmsg), \"u1(): value %s out of range for type u1\",get_str(&b->val));\n        $RAISE((B_BaseException)$NEW(B_ValueError,to$str(errmsg)));\n    }\n    return toB_u1(n);\n}\n\nB_NoneType B_u1D___init__(B_u1 self, B_atom a, B_int base){\n    self->val = B_u1G_new(a,base)->val;\n    return B_None;\n}\n\nvoid B_u1D___serialize__(B_u1 n, $Serial$state state) {\n    $val_serialize(U1_ID,&n->val,state);\n}\n\nB_u1 B_u1D___deserialize__(B_u1 n, $Serial$state state) {\n    return toB_u1((uint8_t)$val_deserialize(state));\n}\n\nB_bool B_u1D___bool__(B_u1 n) {\n    return toB_bool(n->val);\n}\n\nB_str B_u1D___str__(B_u1 n) {\n    return $FORMAT(\"%d\", n->val);\n}\n\nB_str B_u1D___repr__(B_u1 n) {\n    return $FORMAT(\"%d\", n->val);\n}\n\nB_u1 toB_u1(uint8_t i) {\n    B_u1 res = acton_malloc(sizeof(struct B_u1));\n    res->$class = &B_u1G_methods;\n    res->val = i;\n    return res;\n}\n\nuint8_t fromB_u1(B_u1 w) {\n    return w->val;\n}\n\n                  \n\n// B_IntegralD_u1 /////////////////////////////////////////////////////////////////////////\n\n \nB_u1 B_IntegralD_u1D___add__(B_IntegralD_u1 wit,  B_u1 a, B_u1 b) {\n    return toB_u1((a->val + b->val)%2);\n}  \n\nB_u1 B_IntegralD_u1D___zero__(B_IntegralD_u1 wit) {\n    return toB_u1(0);\n}\n\nB_complex B_IntegralD_u1D___complex__(B_IntegralD_u1 wit, B_u1 a) {\n    return toB_complex((double)a->val);\n}\n\nB_u1 B_IntegralD_u1D___fromatom__(B_IntegralD_u1 wit, B_atom a) {\n    return B_u1G_new(a,NULL);\n}\n\nB_u1 B_IntegralD_u1D___mul__(B_IntegralD_u1 wit,  B_u1 a, B_u1 b) {\n    return toB_u1((a->val * b->val));\n}  \n  \nB_u1 B_IntegralD_u1D___pow__(B_IntegralD_u1 wit,  B_u1 a, B_u1 b) {\n    return toB_u1(u1_pow(a->val,b->val));\n}\n\nB_u1 B_IntegralD_u1D___neg__(B_IntegralD_u1 wit,  B_u1 a) {\n    if (a->val > 0L)\n        $RAISE((B_BaseException)$NEW(B_ValueError,to$str(\"u1.neg: cannot negate non-zero value in u1\")));\n    return a;\n}\n\nB_u1 B_IntegralD_u1D___pos__(B_IntegralD_u1 wit,  B_u1 a) {\n    return a;\n}\n\n$WORD B_IntegralD_u1D_real(B_IntegralD_u1 wit, B_u1 a, B_Real wit2) {\n    return wit2->$class->__fromatom__(wit2,(B_atom)a);\n}\n\n$WORD B_IntegralD_u1D_imag(B_IntegralD_u1 wit, B_u1 a, B_Real wit2) {\n    return wit2->$class->__fromatom__(wit2,(B_atom)toB_u1(0));\n}\n\n$WORD B_IntegralD_u1D___abs__(B_IntegralD_u1 wit, B_u1 a, B_Real wit2) {\n    return wit2->$class->__fromatom__(wit2,(B_atom)a);\n}\n\nB_u1 B_IntegralD_u1D_conjugate(B_IntegralD_u1 wit,  B_u1 a) {\n    return a;\n}\n\nB_float B_IntegralD_u1D___float__ (B_IntegralD_u1 wit, B_u1 n) {\n    return to$float((double)n->val);\n}\n\n$WORD B_IntegralD_u1D___trunc__ (B_IntegralD_u1 wit, B_u1 n, B_Integral wit2) {\n    return wit2->$class->__fromatom__(wit2,(B_atom)n);\n}\n  \n$WORD B_IntegralD_u1D___floor__ (B_IntegralD_u1 wit, B_u1 n, B_Integral wit2) {\n    return wit2->$class->__fromatom__(wit2,(B_atom)n);\n}\n  \n$WORD B_IntegralD_u1D___ceil__ (B_IntegralD_u1 wit, B_u1 n, B_Integral wit2) {\n    return wit2->$class->__fromatom__(wit2,(B_atom)n);\n}\n  \nB_u1 B_IntegralD_u1D___round__ (B_IntegralD_u1 wit, B_u1 n, B_int p) {\n    uint8_t nval = n->val;\n    long pval = p==NULL ? 0 : fromB_int(p);\n    if (pval>=0)\n        return n;\n    uint8_t p10 = u1_pow(10,-pval);\n    uint8_t res = nval/p10;\n    if (nval%p10 * 2 > p10)\n        res++; \n    return toB_u1 (res * p10); // is this what we want?\n}\n  \n$WORD B_IntegralD_u1D_numerator (B_IntegralD_u1 wit, B_u1 n, B_Integral wit2) {\n    return wit2->$class->__fromatom__(wit2,(B_atom)n);\n}\n  \n$WORD B_IntegralD_u1D_denominator (B_IntegralD_u1 wit, B_u1 n, B_Integral wit2) {\n    return wit2->$class->__fromatom__(wit2,(B_atom)toB_u1(1L));\n}\n  \nB_int B_IntegralD_u1D___int__ (B_IntegralD_u1 wit, B_u1 n) {\n    return B_intG_new((B_atom)n,NULL);\n}\n\nB_int B_IntegralD_u1D___index__(B_IntegralD_u1 wit, B_u1 n) {\n    return B_intG_new((B_atom)n,NULL);\n}\n\nB_tuple B_IntegralD_u1D___divmod__(B_IntegralD_u1 wit, B_u1 a, B_u1 b) {\n    int n = a->val;\n    int d = b->val;\n    return $NEWTUPLE(2, toB_u1(n/d), toB_u1(n%d));\n}\n\nB_u1 B_IntegralD_u1D___floordiv__(B_IntegralD_u1 wit, B_u1 a, B_u1 b) {\n    if (b->val == 0)\n        $RAISE((B_BaseException)$NEW(B_ZeroDivisionError, to$str(\"division by zero\")));\n    return toB_u1(a->val / b->val);\n}\n\nB_u1 B_IntegralD_u1D___mod__(B_IntegralD_u1 wit, B_u1 a, B_u1 b) {\n    return toB_u1(a->val % b->val);\n}\n\nB_u1 B_IntegralD_u1D___lshift__(B_IntegralD_u1 wit,  B_u1 a, B_int b) {\n    return toB_u1(a->val << fromB_int(b));\n}\n\nB_u1 B_IntegralD_u1D___rshift__(B_IntegralD_u1 wit,  B_u1 a, B_int b) {\n    return toB_u1(a->val >> fromB_int(b));\n}\n \nB_u1 B_IntegralD_u1D___invert__(B_IntegralD_u1 wit,  B_u1 a) {\n    return toB_u1(~a->val);\n}\n\n\n// B_LogicalD_IntegralD_u1  ////////////////////////////////////////////////////////////////////////////////////////\n\nB_u1 B_LogicalD_IntegralD_u1D___and__(B_LogicalD_IntegralD_u1 wit,  B_u1 a, B_u1 b) {\n    return toB_u1(a->val & b->val);\n}\n                                                 \nB_u1 B_LogicalD_IntegralD_u1D___or__(B_LogicalD_IntegralD_u1 wit,  B_u1 a, B_u1 b) {\n    return toB_u1(a->val | b->val);\n}\n                                                 \nB_u1 B_LogicalD_IntegralD_u1D___xor__(B_LogicalD_IntegralD_u1 wit,  B_u1 a, B_u1 b) {\n    return toB_u1(a->val ^ b->val);\n}  \n \n// B_MinusD_IntegralD_u1  ////////////////////////////////////////////////////////////////////////////////////////\n\n \nB_u1 B_MinusD_IntegralD_u1D___sub__(B_MinusD_IntegralD_u1 wit,  B_u1 a, B_u1 b) {\n    return toB_u1(a->val - b->val);\n}  \n\n// B_DivD_u1  ////////////////////////////////////////////////////////////////////////////////////////\n\n \nB_float B_DivD_u1D___truediv__ (B_DivD_u1 wit, B_u1 a, B_u1 b) {\n    if (b->val == 0)\n        $RAISE((B_BaseException)$NEW(B_ZeroDivisionError, to$str(\"division by zero\")));\n    return to$float((double)a->val/(double)b->val);\n}\n\n// B_OrdD_u1  ////////////////////////////////////////////////////////////////////////////////////////\n\nB_bool B_OrdD_u1D___eq__ (B_OrdD_u1 wit, B_u1 a, B_u1 b) {\n    return toB_bool(a->val == b->val);\n}\n\nB_bool B_OrdD_u1D___ne__ (B_OrdD_u1 wit, B_u1 a, B_u1 b) {\n    return toB_bool(a->val != b->val);\n}\n\nB_bool B_OrdD_u1D___lt__ (B_OrdD_u1 wit, B_u1 a, B_u1 b) {\n    return toB_bool(a->val < b->val);\n}\n\nB_bool B_OrdD_u1D___le__ (B_OrdD_u1 wit, B_u1 a, B_u1 b) {\n    return toB_bool(a->val <= b->val);\n}\n\nB_bool B_OrdD_u1D___gt__ (B_OrdD_u1 wit, B_u1 a, B_u1 b) {\n    return toB_bool(a->val > b->val);\n}\n\nB_bool B_OrdD_u1D___ge__ (B_OrdD_u1 wit, B_u1 a, B_u1 b) {\n    return toB_bool(a->val >= b->val);\n}\n\n// B_HashableD_u1 ///////////////////////////////////////////////////////////////////////////////////////////////////////\n\nB_bool B_HashableD_u1D___eq__(B_HashableD_u1 wit, B_u1 a, B_u1 b) {\n    return toB_bool(a->val == b->val);\n}\n\nB_bool B_HashableD_u1D___ne__(B_HashableD_u1 wit, B_u1 a, B_u1 b) {\n    return toB_bool(a->val != b->val);\n}\n\nB_NoneType B_HashableD_u1D_hash(B_HashableD_u1 wit, B_u1 a, B_hasher h) {\n    zig_hash_wyhash_update(h->_hasher, to$bytesD_len((char *)&(a->val),1));\n    return B_None;\n}\n"
  },
  {
    "path": "base/builtin/u1.h",
    "content": "struct B_u1 {\n    struct B_u1G_class *$class;\n    uint8_t val;\n};\n\nB_u1 toB_u1(uint8_t n);\nuint8_t fromB_u1(B_u1 n);\n\nB_u1 B_u1G_new(B_atom a, B_int base);\n\n#define u1_DIV(a,b)       ( {if (b==0) $RAISE((B_BaseException)$NEW(B_ZeroDivisionError,to$str(\"u1 truediv: division by zero\"))); (double)a;} )\n#define u1_FLOORDIV(a,b)  ( {if (b==0) $RAISE((B_BaseException)$NEW(B_ZeroDivisionError,to$str(\"u1 floordiv: division by zero\")));  a;} )\n#define u1_MOD(a,b)       ( {if (b==0) $RAISE((B_BaseException)$NEW(B_ZeroDivisionError,to$str(\"u1 mod: division by zero\"))); a;} )\n\nuint8_t u1_pow(uint8_t a, uint8_t b);\n"
  },
  {
    "path": "base/builtin/u16.c",
    "content": "/*\n * Copyright (C) 2019-2021 Data Ductus AB\n *\n * Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:\n *\n * 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.\n *\n * 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.\n *\n * 3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission.\n *\n * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS \"AS IS\" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n */\n\n// Auxiliary //////////////////////////////////////////////////////////////////////////////\n\n// only called with e>=0.\nunsigned short u16_pow(unsigned short a, unsigned short e) {\n    if (e == 0) return 1;\n    if (e == 1) return a;\n    if (e%2 == 0) return u16_pow(a*a,e/2);\n    return a * u16_pow(a*a,e/2);\n}\n\n// General methods ///////////////////////////////////////////////////////////////////////\n\nB_u16 B_u16G_new(B_atom a, B_int base) {\n    B_bigint b = B_bigintG_new(a, base);\n    long sz = b->val.size;\n    if (sz==0) return toB_u16(0);\n    unsigned long n = b->val.n[0];\n    if (sz != 1 || n > 0xfffful) {\n        char errmsg[1024];\n        snprintf(errmsg, sizeof(errmsg), \"u16(): value %s out of range for type u16\",get_str(&b->val));\n        $RAISE((B_BaseException)$NEW(B_ValueError,to$str(errmsg)));\n    }\nreturn toB_u16((unsigned short)n);\n}\n\nB_NoneType B_u16D___init__(B_u16 self, B_atom a, B_int base){\n    self->val = B_u16G_new(a,base)->val;\n    return B_None;\n}\n\nvoid B_u16D___serialize__(B_u16 n, $Serial$state state) {\n    $val_serialize(U16_ID,&n->val,state);\n}\n\nB_u16 B_u16D___deserialize__(B_u16 n, $Serial$state state) {\n    return toB_u16((uint16_t)$val_deserialize(state));\n}\n\nB_bool B_u16D___bool__(B_u16 n) {\n    return toB_bool(n->val != 0);\n}\n\nB_str B_u16D___str__(B_u16 n) {\n    return $FORMAT(\"%hu\", n->val);\n}\n\nB_str B_u16D___repr__(B_u16 n) {\n    return $FORMAT(\"%hu\", n->val);\n}\n\nB_u16 toB_u16(unsigned short i) {\n    B_u16 res = acton_malloc(sizeof(struct B_u16));\n    res->$class = &B_u16G_methods;\n    res->val = i;\n    return res;\n}\n\nunsigned short fromB_u16(B_u16 w) {\n    return w->val;\n}\n\n                  \n\n// B_IntegralD_u16 /////////////////////////////////////////////////////////////////////////\n\n \nB_u16 B_IntegralD_u16D___add__(B_IntegralD_u16 wit,  B_u16 a, B_u16 b) {\n    return toB_u16(a->val + b->val);\n}  \n\nB_u16 B_IntegralD_u16D___zero__(B_IntegralD_u16 wit) {\n    return toB_u16(0);\n}\n\nB_complex B_IntegralD_u16D___complex__(B_IntegralD_u16 wit, B_u16 a) {\n    return toB_complex((double)a->val);\n}\n\nB_u16 B_IntegralD_u16D___fromatom__(B_IntegralD_u16 wit, B_atom a) {\n    return B_u16G_new(a,NULL);\n}\n\nB_u16 B_IntegralD_u16D___mul__(B_IntegralD_u16 wit,  B_u16 a, B_u16 b) {\n    return toB_u16(a->val * b->val);\n}  \n  \nB_u16 B_IntegralD_u16D___pow__(B_IntegralD_u16 wit,  B_u16 a, B_u16 b) {\n    return toB_u16(u16_pow(a->val,b->val));\n}\n\nB_u16 B_IntegralD_u16D___neg__(B_IntegralD_u16 wit,  B_u16 a) {\n    if (a->val > 0L)\n        $RAISE((B_BaseException)$NEW(B_ValueError,to$str(\"u16.neg: cannot negate non-zero value in u16\")));\n    return a;\n}\n\nB_u16 B_IntegralD_u16D___pos__(B_IntegralD_u16 wit,  B_u16 a) {\n    return a;\n}\n\n$WORD B_IntegralD_u16D_real(B_IntegralD_u16 wit, B_u16 a, B_Real wit2) {\n    return wit2->$class->__fromatom__(wit2,(B_atom)a);\n}\n\n$WORD B_IntegralD_u16D_imag(B_IntegralD_u16 wit, B_u16 a, B_Real wit2) {\n    return wit2->$class->__fromatom__(wit2,(B_atom)toB_u16(0L));\n}\n\n$WORD B_IntegralD_u16D___abs__(B_IntegralD_u16 wit, B_u16 a, B_Real wit2) {\n    return wit2->$class->__fromatom__(wit2,(B_atom)a);\n}\n\nB_u16 B_IntegralD_u16D_conjugate(B_IntegralD_u16 wit,  B_u16 a) {\n    return a;\n}\n\nB_float B_IntegralD_u16D___float__ (B_IntegralD_u16 wit, B_u16 n) {\n    return to$float((double)n->val);\n}\n\n$WORD B_IntegralD_u16D___trunc__ (B_IntegralD_u16 wit, B_u16 n, B_Integral wit2) {\n    return wit2->$class->__fromatom__(wit2,(B_atom)n);\n}\n  \n$WORD B_IntegralD_u16D___floor__ (B_IntegralD_u16 wit, B_u16 n, B_Integral wit2) {\n    return wit2->$class->__fromatom__(wit2,(B_atom)n);\n}\n  \n$WORD B_IntegralD_u16D___ceil__ (B_IntegralD_u16 wit, B_u16 n, B_Integral wit2) {\n    return wit2->$class->__fromatom__(wit2,(B_atom)n);\n}\n  \nB_u16 B_IntegralD_u16D___round__ (B_IntegralD_u16 wit, B_u16 n, B_int p) {\n    unsigned short nval = n->val;\n    short pval = p==NULL ? 0 : fromB_int(p);\n    if (pval>=0)\n        return n;\n    unsigned short p10 = u16_pow(10,-pval);\n    unsigned short res = nval/p10;\n    if (nval%p10 * 2 > p10)\n        res++; \n    return toB_u16 (res * p10);\n}\n  \n$WORD B_IntegralD_u16D_numerator (B_IntegralD_u16 wit, B_u16 n, B_Integral wit2) {\n    return wit2->$class->__fromatom__(wit2,(B_atom)n);\n}\n  \n$WORD B_IntegralD_u16D_denominator (B_IntegralD_u16 wit, B_u16 n, B_Integral wit2) {\n    return wit2->$class->__fromatom__(wit2,(B_atom)toB_u16(1L));\n}\n  \nB_int B_IntegralD_u16D___int__ (B_IntegralD_u16 wit, B_u16 n) {\n    return B_intG_new((B_atom)n,NULL);\n}\n\nB_int B_IntegralD_u16D___index__(B_IntegralD_u16 wit, B_u16 n) {\n    return B_intG_new((B_atom)n,NULL);\n}\n\nB_tuple B_IntegralD_u16D___divmod__(B_IntegralD_u16 wit, B_u16 a, B_u16 b) {\n    int n = a->val;\n    int d = b->val;\n    return $NEWTUPLE(2, toB_u16(n/d), toB_u16(n%d));\n}\n\nB_u16 B_IntegralD_u16D___floordiv__(B_IntegralD_u16 wit, B_u16 a, B_u16 b) {\n    if (b->val == 0)\n        $RAISE((B_BaseException)$NEW(B_ZeroDivisionError, to$str(\"division by zero\")));\n    return toB_u16(a->val / b->val);\n}\n\nB_u16 B_IntegralD_u16D___mod__(B_IntegralD_u16 wit, B_u16 a, B_u16 b) {\n    return toB_u16(a->val % b->val);\n}\n\nB_u16 B_IntegralD_u16D___lshift__(B_IntegralD_u16 wit,  B_u16 a, B_int b) {\n    return toB_u16(a->val << fromB_int(b));\n}\n\nB_u16 B_IntegralD_u16D___rshift__(B_IntegralD_u16 wit,  B_u16 a, B_int b) {\n    return toB_u16(a->val >> fromB_int(b));\n}\n \nB_u16 B_IntegralD_u16D___invert__(B_IntegralD_u16 wit,  B_u16 a) {\n    return toB_u16(~a->val);\n}\n\n\n// B_LogicalD_IntegralD_u16  ////////////////////////////////////////////////////////////////////////////////////////\n\nB_u16 B_LogicalD_IntegralD_u16D___and__(B_LogicalD_IntegralD_u16 wit,  B_u16 a, B_u16 b) {\n    return toB_u16(a->val & b->val);\n}\n                                                 \nB_u16 B_LogicalD_IntegralD_u16D___or__(B_LogicalD_IntegralD_u16 wit,  B_u16 a, B_u16 b) {\n    return toB_u16(a->val | b->val);\n}\n                                                 \nB_u16 B_LogicalD_IntegralD_u16D___xor__(B_LogicalD_IntegralD_u16 wit,  B_u16 a, B_u16 b) {\n    return toB_u16(a->val ^ b->val);\n}  \n \n// B_MinusD_IntegralD_u16  ////////////////////////////////////////////////////////////////////////////////////////\n\n \nB_u16 B_MinusD_IntegralD_u16D___sub__(B_MinusD_IntegralD_u16 wit,  B_u16 a, B_u16 b) {\n    return toB_u16(a->val - b->val);\n}  \n\n// B_DivD_u16  ////////////////////////////////////////////////////////////////////////////////////////\n\n \nB_float B_DivD_u16D___truediv__ (B_DivD_u16 wit, B_u16 a, B_u16 b) {\n    if (b->val == 0)\n        $RAISE((B_BaseException)$NEW(B_ZeroDivisionError, to$str(\"division by zero\")));\n    return to$float((double)a->val/(double)b->val);\n}\n\n// B_OrdD_u16  ////////////////////////////////////////////////////////////////////////////////////////\n\nB_bool B_OrdD_u16D___eq__ (B_OrdD_u16 wit, B_u16 a, B_u16 b) {\n    return toB_bool(a->val == b->val);\n}\n\nB_bool B_OrdD_u16D___ne__ (B_OrdD_u16 wit, B_u16 a, B_u16 b) {\n    return toB_bool(a->val != b->val);\n}\n\nB_bool B_OrdD_u16D___lt__ (B_OrdD_u16 wit, B_u16 a, B_u16 b) {\n    return toB_bool(a->val < b->val);\n}\n\nB_bool B_OrdD_u16D___le__ (B_OrdD_u16 wit, B_u16 a, B_u16 b) {\n    return toB_bool(a->val <= b->val);\n}\n\nB_bool B_OrdD_u16D___gt__ (B_OrdD_u16 wit, B_u16 a, B_u16 b) {\n    return toB_bool(a->val > b->val);\n}\n\nB_bool B_OrdD_u16D___ge__ (B_OrdD_u16 wit, B_u16 a, B_u16 b) {\n    return toB_bool(a->val >= b->val);\n}\n\n// B_HashableD_u16 ///////////////////////////////////////////////////////////////////////////////////////////////////////\n\nB_bool B_HashableD_u16D___eq__(B_HashableD_u16 wit, B_u16 a, B_u16 b) {\n    return toB_bool(a->val == b->val);\n}\n\nB_bool B_HashableD_u16D___ne__(B_HashableD_u16 wit, B_u16 a, B_u16 b) {\n    return toB_bool(a->val != b->val);\n}\n\nB_NoneType B_HashableD_u16D_hash(B_HashableD_u16 wit, B_u16 a, B_hasher h) {\n    zig_hash_wyhash_update(h->_hasher, to$bytesD_len((char *)&(a->val),2));\n    return B_None;\n}\n"
  },
  {
    "path": "base/builtin/u16.h",
    "content": "struct B_u16 {\n    struct B_u16G_class *$class;\n    unsigned short val;\n};\n\nB_u16 toB_u16(unsigned short n);\nunsigned short fromB_u16(B_u16 n);\n\nB_u16 B_u16G_new(B_atom a, B_int base);\n\n#define u16_DIV(a,b)       ( {if (b==0) $RAISE((B_BaseException)$NEW(B_ZeroDivisionError,to$str(\"u16 truediv: division by zero\"))); (double)a/(double)b;} )\n#define u16_FLOORDIV(a,b)  ( {if (b==0) $RAISE((B_BaseException)$NEW(B_ZeroDivisionError,to$str(\"u16 floordiv: division by zero\")));  a/b;} )\n#define u16_MOD(a,b)       ( {if (b==0) $RAISE((B_BaseException)$NEW(B_ZeroDivisionError,to$str(\"u16 mod: division by zero\"))); a%b;} )\n\nunsigned short u16_pow(unsigned short a, unsigned short b);\n"
  },
  {
    "path": "base/builtin/u32.c",
    "content": "/*\n * Copyright (C) 2019-2021 Data Ductus AB\n *\n * Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:\n *\n * 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.\n *\n * 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.\n *\n * 3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission.\n *\n * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS \"AS IS\" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n */\n\n// Auxiliary //////////////////////////////////////////////////////////////////////////////\n\n// only called with e>=0.\nunsigned int u32_pow(unsigned int a, unsigned int e) {\n    if (e == 0) return 1;\n    if (e == 1) return a;\n    if (e%2 == 0) return u32_pow(a*a,e/2);\n    return a * u32_pow(a*a,e/2);\n}\n\n// General methods ///////////////////////////////////////////////////////////////////////\n\nB_u32 B_u32G_new(B_atom a, B_int base) {\n    B_bigint b = B_bigintG_new(a, base);\n    long sz = b->val.size;\n    if (sz==0) return toB_u32(0);\n    unsigned long n = b->val.n[0];\n    if ((sz != 1 || n > 0xfffffffful)) {\n        char errmsg[1024];\n        snprintf(errmsg, sizeof(errmsg), \"u32(): value %s out of range for type u32\",get_str(&b->val));\n        $RAISE((B_BaseException)$NEW(B_ValueError,to$str(errmsg)));\n    } \n    return toB_u32((unsigned int)n);\n}\n\nB_NoneType B_u32D___init__(B_u32 self, B_atom a, B_int base){\n    self->val = B_u32G_new(a,base)->val;\n    return B_None;\n}\n\nvoid B_u32D___serialize__(B_u32 n, $Serial$state state) {\n    $val_serialize(U32_ID,&n->val,state);\n}\n\nB_u32 B_u32D___deserialize__(B_u32 n, $Serial$state state) {\n    return toB_u32((int)(uintptr_t)$val_deserialize(state));\n}\n\nB_bool B_u32D___bool__(B_u32 n) {\n    return toB_bool(n->val != 0);\n}\n\nB_str B_u32D___str__(B_u32 n) {\n    return $FORMAT(\"%u\", n->val);\n}\n\nB_str B_u32D___repr__(B_u32 n) {\n    return $FORMAT(\"%u\", n->val);\n}\n\nB_u32 toB_u32(unsigned int i) {\n    B_u32 res = acton_malloc(sizeof(struct B_u32));\n    res->$class = &B_u32G_methods;\n    res->val = i;\n    return res;\n}\n\nunsigned int fromB_u32(B_u32 w) {\n    return w->val;\n}\n\n                  \n\n// B_IntegralD_u32 /////////////////////////////////////////////////////////////////////////\n\n \nB_u32 B_IntegralD_u32D___add__(B_IntegralD_u32 wit,  B_u32 a, B_u32 b) {\n    return toB_u32(a->val + b->val);\n}  \n\nB_u32 B_IntegralD_u32D___zero__(B_IntegralD_u32 wit) {\n    return toB_u32(0);\n}\n\nB_complex B_IntegralD_u32D___complex__(B_IntegralD_u32 wit, B_u32 a) {\n    return toB_complex((double)a->val);\n}\n\nB_u32 B_IntegralD_u32D___fromatom__(B_IntegralD_u32 wit, B_atom a) {\n    return B_u32G_new(a,NULL);\n}\n\nB_u32 B_IntegralD_u32D___mul__(B_IntegralD_u32 wit,  B_u32 a, B_u32 b) {\n    return toB_u32(a->val * b->val);\n}  \n  \nB_u32 B_IntegralD_u32D___pow__(B_IntegralD_u32 wit,  B_u32 a, B_u32 b) {\n    return toB_u32(u32_pow(a->val,b->val));\n}\n\nB_u32 B_IntegralD_u32D___neg__(B_IntegralD_u32 wit,  B_u32 a) {\n    if (a->val > 0L)\n        $RAISE((B_BaseException)$NEW(B_ValueError,to$str(\"u32.neg: cannot negate non-zero value in u32\")));\n    return a;\n}\n\nB_u32 B_IntegralD_u32D___pos__(B_IntegralD_u32 wit,  B_u32 a) {\n    return a;\n}\n\n$WORD B_IntegralD_u32D_real(B_IntegralD_u32 wit, B_u32 a, B_Real wit2) {\n    return wit2->$class->__fromatom__(wit2,(B_atom)a);\n}\n\n$WORD B_IntegralD_u32D_imag(B_IntegralD_u32 wit, B_u32 a, B_Real wit2) {\n    return wit2->$class->__fromatom__(wit2,(B_atom)toB_u32(0L));\n}\n\n$WORD B_IntegralD_u32D___abs__(B_IntegralD_u32 wit, B_u32 a, B_Real wit2) {\n    return wit2->$class->__fromatom__(wit2,(B_atom)a);\n}\n\nB_u32 B_IntegralD_u32D_conjugate(B_IntegralD_u32 wit,  B_u32 a) {\n    return a;\n}\n\nB_float B_IntegralD_u32D___float__ (B_IntegralD_u32 wit, B_u32 n) {\n    return to$float((double)n->val);\n}\n\n$WORD B_IntegralD_u32D___trunc__ (B_IntegralD_u32 wit, B_u32 n, B_Integral wit2) {\n    return wit2->$class->__fromatom__(wit2,(B_atom)n);\n}\n  \n$WORD B_IntegralD_u32D___floor__ (B_IntegralD_u32 wit, B_u32 n, B_Integral wit2) {\n    return wit2->$class->__fromatom__(wit2,(B_atom)n);\n}\n  \n$WORD B_IntegralD_u32D___ceil__ (B_IntegralD_u32 wit, B_u32 n, B_Integral wit2) {\n    return wit2->$class->__fromatom__(wit2,(B_atom)n);\n}\n  \nB_u32 B_IntegralD_u32D___round__ (B_IntegralD_u32 wit, B_u32 n, B_int p) {\n    unsigned int nval = n->val;\n    int pval = p==NULL ? 0 : fromB_int(p);\n    if (pval>=0)\n        return n;\n    unsigned int p10 = u32_pow(10,-pval);\n    unsigned int res = nval/p10;\n    if (nval%p10 * 2 > p10)\n        res++; \n    return toB_u32 (res * p10);\n}\n  \n$WORD B_IntegralD_u32D_numerator (B_IntegralD_u32 wit, B_u32 n, B_Integral wit2) {\n    return wit2->$class->__fromatom__(wit2,(B_atom)n);\n}\n  \n$WORD B_IntegralD_u32D_denominator (B_IntegralD_u32 wit, B_u32 n, B_Integral wit2) {\n    return wit2->$class->__fromatom__(wit2,(B_atom)toB_u32(1L));\n}\n  \nB_int B_IntegralD_u32D___int__ (B_IntegralD_u32 wit, B_u32 n) {\n    return B_intG_new((B_atom)n,NULL);\n}\n\nB_int B_IntegralD_u32D___index__(B_IntegralD_u32 wit, B_u32 n) {\n    return B_intG_new((B_atom)n,NULL);\n}\n\nB_tuple B_IntegralD_u32D___divmod__(B_IntegralD_u32 wit, B_u32 a, B_u32 b) {\n    int n = a->val;\n    int d = b->val;\n    return $NEWTUPLE(2, toB_u32(n/d), toB_u32(n%d));\n}\n\nB_u32 B_IntegralD_u32D___floordiv__(B_IntegralD_u32 wit, B_u32 a, B_u32 b) {\n    if (b->val == 0)\n        $RAISE((B_BaseException)$NEW(B_ZeroDivisionError, to$str(\"division by zero\")));\n    return toB_u32(a->val / b->val);\n}\n\nB_u32 B_IntegralD_u32D___mod__(B_IntegralD_u32 wit, B_u32 a, B_u32 b) {\n    return toB_u32(a->val % b->val);\n}\n\nB_u32 B_IntegralD_u32D___lshift__(B_IntegralD_u32 wit,  B_u32 a, B_int b) {\n    return toB_u32(a->val << fromB_int(b));\n}\n\nB_u32 B_IntegralD_u32D___rshift__(B_IntegralD_u32 wit,  B_u32 a, B_int b) {\n    return toB_u32(a->val >> fromB_int(b));\n}\n \nB_u32 B_IntegralD_u32D___invert__(B_IntegralD_u32 wit,  B_u32 a) {\n    return toB_u32(~a->val);\n}\n\n\n// B_LogicalD_IntegralD_u32  ////////////////////////////////////////////////////////////////////////////////////////\n\nB_u32 B_LogicalD_IntegralD_u32D___and__(B_LogicalD_IntegralD_u32 wit,  B_u32 a, B_u32 b) {\n    return toB_u32(a->val & b->val);\n}\n                                                 \nB_u32 B_LogicalD_IntegralD_u32D___or__(B_LogicalD_IntegralD_u32 wit,  B_u32 a, B_u32 b) {\n    return toB_u32(a->val | b->val);\n}\n                                                 \nB_u32 B_LogicalD_IntegralD_u32D___xor__(B_LogicalD_IntegralD_u32 wit,  B_u32 a, B_u32 b) {\n    return toB_u32(a->val ^ b->val);\n}  \n \n// B_MinusD_IntegralD_u32  ////////////////////////////////////////////////////////////////////////////////////////\n\n \nB_u32 B_MinusD_IntegralD_u32D___sub__(B_MinusD_IntegralD_u32 wit,  B_u32 a, B_u32 b) {\n    return toB_u32(a->val - b->val);\n}  \n\n// B_DivD_u32  ////////////////////////////////////////////////////////////////////////////////////////\n\n \nB_float B_DivD_u32D___truediv__ (B_DivD_u32 wit, B_u32 a, B_u32 b) {\n    if (b->val == 0)\n        $RAISE((B_BaseException)$NEW(B_ZeroDivisionError, to$str(\"division by zero\")));\n    return to$float((double)a->val/(double)b->val);\n}\n\n// B_OrdD_u32  ////////////////////////////////////////////////////////////////////////////////////////\n\nB_bool B_OrdD_u32D___eq__ (B_OrdD_u32 wit, B_u32 a, B_u32 b) {\n    return toB_bool(a->val == b->val);\n}\n\nB_bool B_OrdD_u32D___ne__ (B_OrdD_u32 wit, B_u32 a, B_u32 b) {\n    return toB_bool(a->val != b->val);\n}\n\nB_bool B_OrdD_u32D___lt__ (B_OrdD_u32 wit, B_u32 a, B_u32 b) {\n    return toB_bool(a->val < b->val);\n}\n\nB_bool B_OrdD_u32D___le__ (B_OrdD_u32 wit, B_u32 a, B_u32 b) {\n    return toB_bool(a->val <= b->val);\n}\n\nB_bool B_OrdD_u32D___gt__ (B_OrdD_u32 wit, B_u32 a, B_u32 b) {\n    return toB_bool(a->val > b->val);\n}\n\nB_bool B_OrdD_u32D___ge__ (B_OrdD_u32 wit, B_u32 a, B_u32 b) {\n    return toB_bool(a->val >= b->val);\n}\n\n// B_HashableD_u32 ///////////////////////////////////////////////////////////////////////////////////////////////////////\n\nB_bool B_HashableD_u32D___eq__(B_HashableD_u32 wit, B_u32 a, B_u32 b) {\n    return toB_bool(a->val == b->val);\n}\n\nB_bool B_HashableD_u32D___ne__(B_HashableD_u32 wit, B_u32 a, B_u32 b) {\n    return toB_bool(a->val != b->val);\n}\n\nB_NoneType B_HashableD_u32D_hash(B_HashableD_u32 wit, B_u32 a, B_hasher h) {\n    zig_hash_wyhash_update(h->_hasher, to$bytesD_len((char *)&(a->val), 4));\n    return B_None;\n}\n"
  },
  {
    "path": "base/builtin/u32.h",
    "content": "struct B_u32 {\n    struct B_u32G_class *$class;\n    unsigned int val;\n};\n\nB_u32 toB_u32(unsigned int n);\nunsigned int fromB_u32(B_u32 n);\n\nB_u32 B_u32G_new(B_atom a, B_int base);\n\n#define u32_DIV(a,b)       ( {if (b==0) $RAISE((B_BaseException)$NEW(B_ZeroDivisionError,to$str(\"u32 truediv: division by zero\"))); (double)a/(double)b;} )\n#define u32_FLOORDIV(a,b)  ( {if (b==0) $RAISE((B_BaseException)$NEW(B_ZeroDivisionError,to$str(\"u32 floordiv: division by zero\")));  a/b;} )\n#define u32_MOD(a,b)       ( {if (b==0) $RAISE((B_BaseException)$NEW(B_ZeroDivisionError,to$str(\"u32 mod: division by zero\"))); a%b;} )\n\nunsigned int u32_pow(unsigned int a, unsigned int b);\n"
  },
  {
    "path": "base/builtin/u64.c",
    "content": "/*\n * Copyright (C) 2019-2021 Data Ductus AB\n *\n * Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:\n *\n * 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.\n *\n * 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.\n *\n * 3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission.\n *\n * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS \"AS IS\" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n */\n\n// Auxiliary //////////////////////////////////////////////////////////////////////////////\n\n// only called with e>=0.\nuint64_t u64_pow(uint64_t a, uint64_t e) {\n    if (e == 0) return 1;\n    if (e == 1) return a;\n    if (e%2 == 0) return u64_pow(a*a,e/2);\n    return a * u64_pow(a*a,e/2);\n}\n\n// General methods ///////////////////////////////////////////////////////////////////////\n\nB_u64 B_u64G_new(B_atom a, B_int base) {\n    B_bigint b = B_bigintG_new(a, base);\n    long sz = b->val.size;\n    if (sz==0) return toB_u64(0);\n    uint64_t n = b->val.n[0];\n    if (sz != 1) {\n        char errmsg[1024];\n        snprintf(errmsg, sizeof(errmsg), \"u64(): value %s out of range for type u64\",get_str(&b->val));\n        $RAISE((B_BaseException)$NEW(B_ValueError,to$str(errmsg)));\n    }\n    return toB_u64(n);\n}\n \nB_NoneType B_u64D___init__(B_u64 self, B_atom a, B_int base){\n    self->val = B_u64G_new(a,base)->val;\n    return B_None;\n}\n\nvoid B_u64D___serialize__(B_u64 n, $Serial$state state) {\n    $val_serialize(U64_ID,&n->val,state);\n}\n\nB_u64 B_u64D___deserialize__(B_u64 n, $Serial$state state) {\n    return toB_u64((long)$val_deserialize(state));\n}\n\nB_bool B_u64D___bool__(B_u64 n) {\n    return toB_bool(n->val != 0);\n}\n\nB_str B_u64D___str__(B_u64 n) {\n    return $FORMAT(\"%llu\", n->val);\n}\n\nB_str B_u64D___repr__(B_u64 n) {\n    return $FORMAT(\"%llu\", n->val);\n}\n\nB_u64 toB_u64(uint64_t i) {\n    B_u64 res = acton_malloc(sizeof(struct B_u64));\n    res->$class = &B_u64G_methods;\n    res->val = i;\n    return res;\n}\n\nuint64_t fromB_u64(B_u64 w) {\n    return w->val;\n}\n\n                  \n\n// B_IntegralD_u64 /////////////////////////////////////////////////////////////////////////\n\n \nB_u64 B_IntegralD_u64D___add__(B_IntegralD_u64 wit,  B_u64 a, B_u64 b) {\n    return toB_u64(a->val + b->val);\n}  \n\nB_u64 B_IntegralD_u64D___zero__(B_IntegralD_u64 wit) {\n    return toB_u64(0);\n}\n\nB_complex B_IntegralD_u64D___complex__(B_IntegralD_u64 wit, B_u64 a) {\n    return toB_complex((double)a->val);\n}\n\nB_u64 B_IntegralD_u64D___fromatom__(B_IntegralD_u64 wit, B_atom a) {\n    return B_u64G_new(a,NULL);\n}\n\nB_u64 B_IntegralD_u64D___mul__(B_IntegralD_u64 wit,  B_u64 a, B_u64 b) {\n    return toB_u64(a->val * b->val);\n}  \n  \nB_u64 B_IntegralD_u64D___pow__(B_IntegralD_u64 wit,  B_u64 a, B_u64 b) {\n    return toB_u64(u64_pow(a->val,b->val));\n}\n\nB_u64 B_IntegralD_u64D___neg__(B_IntegralD_u64 wit,  B_u64 a) {\n    if (a->val > 0L)\n        $RAISE((B_BaseException)$NEW(B_ValueError,to$str(\"u64.neg: cannot negate non-zero value in u64\")));\n    return a;\n}\n\nB_u64 B_IntegralD_u64D___pos__(B_IntegralD_u64 wit,  B_u64 a) {\n    return a;\n}\n\n$WORD B_IntegralD_u64D_real(B_IntegralD_u64 wit, B_u64 a, B_Real wit2) {\n    return wit2->$class->__fromatom__(wit2,(B_atom)a);\n}\n\n$WORD B_IntegralD_u64D_imag(B_IntegralD_u64 wit, B_u64 a, B_Real wit2) {\n    return wit2->$class->__fromatom__(wit2,(B_atom)toB_u64(0L));\n}\n\n$WORD B_IntegralD_u64D___abs__(B_IntegralD_u64 wit, B_u64 a, B_Real wit2) {\n    return wit2->$class->__fromatom__(wit2,(B_atom)a);\n}\n\nB_u64 B_IntegralD_u64D_conjugate(B_IntegralD_u64 wit,  B_u64 a) {\n    return a;\n}\n\nB_float B_IntegralD_u64D___float__ (B_IntegralD_u64 wit, B_u64 n) {\n    return to$float((double)n->val);\n}\n\n$WORD B_IntegralD_u64D___trunc__ (B_IntegralD_u64 wit, B_u64 n, B_Integral wit2) {\n    return wit2->$class->__fromatom__(wit2,(B_atom)n);\n}\n  \n$WORD B_IntegralD_u64D___floor__ (B_IntegralD_u64 wit, B_u64 n, B_Integral wit2) {\n    return wit2->$class->__fromatom__(wit2,(B_atom)n);\n}\n  \n$WORD B_IntegralD_u64D___ceil__ (B_IntegralD_u64 wit, B_u64 n, B_Integral wit2) {\n    return wit2->$class->__fromatom__(wit2,(B_atom)n);\n}\n  \nB_u64 B_IntegralD_u64D___round__ (B_IntegralD_u64 wit, B_u64 n, B_int p) {\n    uint64_t nval = n->val;\n    long pval = p==NULL ? 0 : fromB_int(p);\n    if (pval>=0)\n        return n;\n    uint64_t p10 = u64_pow(10,-pval);\n    uint64_t res = nval/p10;\n    if (nval%p10 * 2 > p10)\n        res++; \n    return toB_u64 (res * p10);\n}\n  \n$WORD B_IntegralD_u64D_numerator (B_IntegralD_u64 wit, B_u64 n, B_Integral wit2) {\n    return wit2->$class->__fromatom__(wit2,(B_atom)n);\n}\n  \n$WORD B_IntegralD_u64D_denominator (B_IntegralD_u64 wit, B_u64 n, B_Integral wit2) {\n    return wit2->$class->__fromatom__(wit2,(B_atom)toB_u64(1L));\n}\n  \nB_int B_IntegralD_u64D___int__ (B_IntegralD_u64 wit, B_u64 n) {\n    if (n->val > 0x7ffffffffffffffful)\n        $RAISE((B_BaseException)$NEW(B_ZeroDivisionError, to$str(\"u64 value too large to be converted to int\")));\n    return toB_int(n->val);\n}\n\nB_int B_IntegralD_u64D___index__(B_IntegralD_u64 wit, B_u64 n) {\n    if (n->val > 0x7ffffffffffffffful)\n        $RAISE((B_BaseException)$NEW(B_ZeroDivisionError, to$str(\"u64 value too large to be converted to int\")));\n    return toB_int(n->val);\n}\n\nB_tuple B_IntegralD_u64D___divmod__(B_IntegralD_u64 wit, B_u64 a, B_u64 b) {\n    int n = a->val;\n    int d = b->val;\n    return $NEWTUPLE(2, toB_u64(n/d), toB_u64(n%d));\n}\n\nB_u64 B_IntegralD_u64D___floordiv__(B_IntegralD_u64 wit, B_u64 a, B_u64 b) {\n    if (b->val == 0)\n        $RAISE((B_BaseException)$NEW(B_ZeroDivisionError, to$str(\"division by zero\")));\n    return toB_u64(a->val / b->val);\n}\n\nB_u64 B_IntegralD_u64D___mod__(B_IntegralD_u64 wit, B_u64 a, B_u64 b) {\n    return toB_u64(a->val % b->val);\n}\n\nB_u64 B_IntegralD_u64D___lshift__(B_IntegralD_u64 wit,  B_u64 a, B_int b) {\n    return toB_u64(a->val << fromB_int(b));\n}\n\nB_u64 B_IntegralD_u64D___rshift__(B_IntegralD_u64 wit,  B_u64 a, B_int b) {\n    return toB_u64(a->val >> fromB_int(b));\n}\n \nB_u64 B_IntegralD_u64D___invert__(B_IntegralD_u64 wit,  B_u64 a) {\n    return toB_u64(~a->val);\n}\n\n\n// B_LogicalD_IntegralD_u64  ////////////////////////////////////////////////////////////////////////////////////////\n\nB_u64 B_LogicalD_IntegralD_u64D___and__(B_LogicalD_IntegralD_u64 wit,  B_u64 a, B_u64 b) {\n    return toB_u64(a->val & b->val);\n}\n                                                 \nB_u64 B_LogicalD_IntegralD_u64D___or__(B_LogicalD_IntegralD_u64 wit,  B_u64 a, B_u64 b) {\n    return toB_u64(a->val | b->val);\n}\n                                                 \nB_u64 B_LogicalD_IntegralD_u64D___xor__(B_LogicalD_IntegralD_u64 wit,  B_u64 a, B_u64 b) {\n    return toB_u64(a->val ^ b->val);\n}  \n \n// B_MinusD_IntegralD_u64  ////////////////////////////////////////////////////////////////////////////////////////\n\n \nB_u64 B_MinusD_IntegralD_u64D___sub__(B_MinusD_IntegralD_u64 wit,  B_u64 a, B_u64 b) {\n    return toB_u64(a->val - b->val);\n}  \n\n// B_DivD_u64  ////////////////////////////////////////////////////////////////////////////////////////\n\n \nB_float B_DivD_u64D___truediv__ (B_DivD_u64 wit, B_u64 a, B_u64 b) {\n    if (b->val == 0)\n        $RAISE((B_BaseException)$NEW(B_ZeroDivisionError, to$str(\"division by zero\")));\n    return to$float((double)a->val/(double)b->val);\n}\n\n// B_OrdD_u64  ////////////////////////////////////////////////////////////////////////////////////////\n\nB_bool B_OrdD_u64D___eq__ (B_OrdD_u64 wit, B_u64 a, B_u64 b) {\n    return toB_bool(a->val == b->val);\n}\n\nB_bool B_OrdD_u64D___ne__ (B_OrdD_u64 wit, B_u64 a, B_u64 b) {\n    return toB_bool(a->val != b->val);\n}\n\nB_bool B_OrdD_u64D___lt__ (B_OrdD_u64 wit, B_u64 a, B_u64 b) {\n    return toB_bool(a->val < b->val);\n}\n\nB_bool B_OrdD_u64D___le__ (B_OrdD_u64 wit, B_u64 a, B_u64 b) {\n    return toB_bool(a->val <= b->val);\n}\n\nB_bool B_OrdD_u64D___gt__ (B_OrdD_u64 wit, B_u64 a, B_u64 b) {\n    return toB_bool(a->val > b->val);\n}\n\nB_bool B_OrdD_u64D___ge__ (B_OrdD_u64 wit, B_u64 a, B_u64 b) {\n    return toB_bool(a->val >= b->val);\n}\n\n// B_HashableD_u64 ///////////////////////////////////////////////////////////////////////////////////////////////////////\n\nB_bool B_HashableD_u64D___eq__(B_HashableD_u64 wit, B_u64 a, B_u64 b) {\n    return toB_bool(a->val == b->val);\n}\n\nB_bool B_HashableD_u64D___ne__(B_HashableD_u64 wit, B_u64 a, B_u64 b) {\n    return toB_bool(a->val != b->val);\n}\n\nB_NoneType B_HashableD_u64D_hash(B_HashableD_u64 wit, B_u64 a, B_hasher h) {\n    zig_hash_wyhash_update(h->_hasher, to$bytesD_len((char *)&(a->val), 8));\n    return B_None;\n}\n"
  },
  {
    "path": "base/builtin/u64.h",
    "content": "struct B_u64 {\n    struct B_u64G_class *$class;\n    uint64_t val;\n};\n\nB_u64 toB_u64(uint64_t n);\nuint64_t fromB_u64(B_u64 n);\n\nB_u64 B_u64G_new(B_atom a, B_int base);\n\n#define u64_DIV(a,b)       ( {if (b==0) $RAISE((B_BaseException)$NEW(B_ZeroDivisionError,to$str(\"u64 truediv: division by zero\"))); (double)a/(double)b;} )\n#define u64_FLOORDIV(a,b)  ( {if (b==0) $RAISE((B_BaseException)$NEW(B_ZeroDivisionError,to$str(\"u64 floordiv: division by zero\")));  a/b;} )\n#define u64_MOD(a,b)       ( {if (b==0) $RAISE((B_BaseException)$NEW(B_ZeroDivisionError,to$str(\"u64 mod: division by zero\"))); a%b;} )\n\nuint64_t u64_pow(uint64_t a, uint64_t b);\n"
  },
  {
    "path": "base/builtin/u8.c",
    "content": "/*\n * Copyright (C) 2019-2021 Data Ductus AB\n *\n * Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:\n *\n * 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.\n *\n * 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.\n *\n * 3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission.\n *\n * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS \"AS IS\" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n */\n\n// Auxiliary //////////////////////////////////////////////////////////////////////////////\n\n// only called with e>=0.\nuint8_t u8_pow(uint8_t a, uint8_t e) {\n    if (e == 0) return 1;\n    if (e == 1) return a;\n    if (e%2 == 0) return u8_pow(a*a,e/2);\n    return a * u8_pow(a*a,e/2);\n}\n\n// General methods ///////////////////////////////////////////////////////////////////////\n\nB_u8 B_u8G_new(B_atom a, B_int base) {\n    B_bigint b = B_bigintG_new(a, base);\n    long sz = b->val.size;\n    if (sz == 0) return toB_u8(0);\n    unsigned long n = b->val.n[0];\n    if (sz != 1 || n > UCHAR_MAX) {\n        char errmsg[1024];\n        snprintf(errmsg, sizeof(errmsg), \"u8(): value %s out of range for type u8\",get_str(&b->val));\n        $RAISE((B_BaseException)$NEW(B_ValueError,to$str(errmsg)));\n    }\n    return toB_u8(n);\n}\n\nB_NoneType B_u8D___init__(B_u8 self, B_atom a, B_int base){\n    self->val = B_u8G_new(a,base)->val;\n    return B_None;\n}\n\nvoid B_u8D___serialize__(B_u8 n, $Serial$state state) {\n    $val_serialize(U8_ID,&n->val,state);\n}\n\nB_u8 B_u8D___deserialize__(B_u8 n, $Serial$state state) {\n    return toB_u8((uint8_t)$val_deserialize(state));\n}\n\nB_bool B_u8D___bool__(B_u8 n) {\n    return toB_bool(n->val != 0);\n}\n\nB_str B_u8D___str__(B_u8 n) {\n    return $FORMAT(\"%u\", n->val);\n}\n\nB_str B_u8D___repr__(B_u8 n) {\n    return $FORMAT(\"%u\", n->val);\n}\n\nB_u8 toB_u8(uint8_t i) {\n    B_u8 res = acton_malloc(sizeof(struct B_u8));\n    res->$class = &B_u8G_methods;\n    res->val = i;\n    return res;\n}\n\nuint8_t fromB_u8(B_u8 w) {\n    return w->val;\n}\n\n                  \n\n// B_IntegralD_u8 /////////////////////////////////////////////////////////////////////////\n\n \nB_u8 B_IntegralD_u8D___add__(B_IntegralD_u8 wit,  B_u8 a, B_u8 b) {\n    return toB_u8(a->val + b->val);\n}  \n\nB_u8 B_IntegralD_u8D___zero__(B_IntegralD_u8 wit) {\n    return toB_u8(0);\n}\n\nB_complex B_IntegralD_u8D___complex__(B_IntegralD_u8 wit, B_u8 a) {\n    return toB_complex((double)a->val);\n}\n\nB_u8 B_IntegralD_u8D___fromatom__(B_IntegralD_u8 wit, B_atom a) {\n    return B_u8G_new(a,NULL);\n}\n\nB_u8 B_IntegralD_u8D___mul__(B_IntegralD_u8 wit,  B_u8 a, B_u8 b) {\n    return toB_u8(a->val * b->val);\n}  \n  \nB_u8 B_IntegralD_u8D___pow__(B_IntegralD_u8 wit,  B_u8 a, B_u8 b) {\n    return toB_u8(u8_pow(a->val,b->val));\n}\n\nB_u8 B_IntegralD_u8D___neg__(B_IntegralD_u8 wit,  B_u8 a) {\n    if (a->val > 0L)\n        $RAISE((B_BaseException)$NEW(B_ValueError,to$str(\"u8.neg: cannot negate non-zero value in u8\")));\n    return a;\n}\n\nB_u8 B_IntegralD_u8D___pos__(B_IntegralD_u8 wit,  B_u8 a) {\n    return a;\n}\n\n$WORD B_IntegralD_u8D_real(B_IntegralD_u8 wit, B_u8 a, B_Real wit2) {\n    return wit2->$class->__fromatom__(wit2,(B_atom)a);\n}\n\n$WORD B_IntegralD_u8D_imag(B_IntegralD_u8 wit, B_u8 a, B_Real wit2) {\n    return wit2->$class->__fromatom__(wit2,(B_atom)toB_u8(0L));\n}\n\n$WORD B_IntegralD_u8D___abs__(B_IntegralD_u8 wit, B_u8 a, B_Real wit2) {\n    return wit2->$class->__fromatom__(wit2,(B_atom)a);\n}\n\nB_u8 B_IntegralD_u8D_conjugate(B_IntegralD_u8 wit,  B_u8 a) {\n    return a;\n}\n\nB_float B_IntegralD_u8D___float__ (B_IntegralD_u8 wit, B_u8 n) {\n    return to$float((double)n->val);\n}\n\n$WORD B_IntegralD_u8D___trunc__ (B_IntegralD_u8 wit, B_u8 n, B_Integral wit2) {\n    return wit2->$class->__fromatom__(wit2,(B_atom)n);\n}\n  \n$WORD B_IntegralD_u8D___floor__ (B_IntegralD_u8 wit, B_u8 n, B_Integral wit2) {\n    return wit2->$class->__fromatom__(wit2,(B_atom)n);\n}\n  \n$WORD B_IntegralD_u8D___ceil__ (B_IntegralD_u8 wit, B_u8 n, B_Integral wit2) {\n    return wit2->$class->__fromatom__(wit2,(B_atom)n);\n}\n  \nB_u8 B_IntegralD_u8D___round__ (B_IntegralD_u8 wit, B_u8 n, B_int p) {\n    uint8_t nval = n->val;\n    long pval = p==NULL ? 0 : fromB_int(p);\n    if (pval>=0)\n        return n;\n    uint8_t p10 = u8_pow(10,-pval);\n    uint8_t res = nval/p10;\n    if (nval%p10 * 2 > p10)\n        res++; \n    return toB_u8 (res * p10);\n}\n  \n$WORD B_IntegralD_u8D_numerator (B_IntegralD_u8 wit, B_u8 n, B_Integral wit2) {\n    return wit2->$class->__fromatom__(wit2,(B_atom)n);\n}\n  \n$WORD B_IntegralD_u8D_denominator (B_IntegralD_u8 wit, B_u8 n, B_Integral wit2) {\n    return wit2->$class->__fromatom__(wit2,(B_atom)toB_u8(1L));\n}\n  \nB_int B_IntegralD_u8D___int__ (B_IntegralD_u8 wit, B_u8 n) {\n    return B_intG_new((B_atom)n,NULL);\n}\n\nB_int B_IntegralD_u8D___index__(B_IntegralD_u8 wit, B_u8 n) {\n    return B_intG_new((B_atom)n,NULL);\n}\n\nB_tuple B_IntegralD_u8D___divmod__(B_IntegralD_u8 wit, B_u8 a, B_u8 b) {\n    int n = a->val;\n    int d = b->val;\n    return $NEWTUPLE(2, toB_u8(n/d), toB_u8(n%d));\n}\n\nB_u8 B_IntegralD_u8D___floordiv__(B_IntegralD_u8 wit, B_u8 a, B_u8 b) {\n    if (b->val == 0)\n        $RAISE((B_BaseException)$NEW(B_ZeroDivisionError, to$str(\"division by zero\")));\n    return toB_u8(a->val / b->val);\n}\n\nB_u8 B_IntegralD_u8D___mod__(B_IntegralD_u8 wit, B_u8 a, B_u8 b) {\n    return toB_u8(a->val % b->val);\n}\n\nB_u8 B_IntegralD_u8D___lshift__(B_IntegralD_u8 wit,  B_u8 a, B_int b) {\n    return toB_u8(a->val << fromB_int(b));\n}\n\nB_u8 B_IntegralD_u8D___rshift__(B_IntegralD_u8 wit,  B_u8 a, B_int b) {\n    return toB_u8(a->val >> fromB_int(b));\n}\n \nB_u8 B_IntegralD_u8D___invert__(B_IntegralD_u8 wit,  B_u8 a) {\n    return toB_u8(~a->val);\n}\n\n\n// B_LogicalD_IntegralD_u8  ////////////////////////////////////////////////////////////////////////////////////////\n\nB_u8 B_LogicalD_IntegralD_u8D___and__(B_LogicalD_IntegralD_u8 wit,  B_u8 a, B_u8 b) {\n    return toB_u8(a->val & b->val);\n}\n                                                 \nB_u8 B_LogicalD_IntegralD_u8D___or__(B_LogicalD_IntegralD_u8 wit,  B_u8 a, B_u8 b) {\n    return toB_u8(a->val | b->val);\n}\n                                                 \nB_u8 B_LogicalD_IntegralD_u8D___xor__(B_LogicalD_IntegralD_u8 wit,  B_u8 a, B_u8 b) {\n    return toB_u8(a->val ^ b->val);\n}  \n \n// B_MinusD_IntegralD_u8  ////////////////////////////////////////////////////////////////////////////////////////\n\n \nB_u8 B_MinusD_IntegralD_u8D___sub__(B_MinusD_IntegralD_u8 wit,  B_u8 a, B_u8 b) {\n    return toB_u8(a->val - b->val);\n}  \n\n// B_DivD_u8  ////////////////////////////////////////////////////////////////////////////////////////\n\n \nB_float B_DivD_u8D___truediv__ (B_DivD_u8 wit, B_u8 a, B_u8 b) {\n    if (b->val == 0)\n        $RAISE((B_BaseException)$NEW(B_ZeroDivisionError, to$str(\"division by zero\")));\n    return to$float((double)a->val/(double)b->val);\n}\n\n// B_OrdD_u8  ////////////////////////////////////////////////////////////////////////////////////////\n\nB_bool B_OrdD_u8D___eq__ (B_OrdD_u8 wit, B_u8 a, B_u8 b) {\n    return toB_bool(a->val == b->val);\n}\n\nB_bool B_OrdD_u8D___ne__ (B_OrdD_u8 wit, B_u8 a, B_u8 b) {\n    return toB_bool(a->val != b->val);\n}\n\nB_bool B_OrdD_u8D___lt__ (B_OrdD_u8 wit, B_u8 a, B_u8 b) {\n    return toB_bool(a->val < b->val);\n}\n\nB_bool B_OrdD_u8D___le__ (B_OrdD_u8 wit, B_u8 a, B_u8 b) {\n    return toB_bool(a->val <= b->val);\n}\n\nB_bool B_OrdD_u8D___gt__ (B_OrdD_u8 wit, B_u8 a, B_u8 b) {\n    return toB_bool(a->val > b->val);\n}\n\nB_bool B_OrdD_u8D___ge__ (B_OrdD_u8 wit, B_u8 a, B_u8 b) {\n    return toB_bool(a->val >= b->val);\n}\n\n// B_HashableD_u8 ///////////////////////////////////////////////////////////////////////////////////////////////////////\n\nB_bool B_HashableD_u8D___eq__(B_HashableD_u8 wit, B_u8 a, B_u8 b) {\n    return toB_bool(a->val == b->val);\n}\n\nB_bool B_HashableD_u8D___ne__(B_HashableD_u8 wit, B_u8 a, B_u8 b) {\n    return toB_bool(a->val != b->val);\n}\n\nB_NoneType B_HashableD_u8D_hash(B_HashableD_u8 wit, B_u8 a, B_hasher h) {\n    zig_hash_wyhash_update(h->_hasher, to$bytesD_len((char *)&(a->val),1));\n    return B_None;\n}\n"
  },
  {
    "path": "base/builtin/u8.h",
    "content": "struct B_u8 {\n    struct B_u8G_class *$class;\n    uint8_t val;\n};\n\nB_u8 toB_u8(uint8_t n);\nuint8_t fromB_u8(B_u8 n);\n\nB_u8 B_u8G_new(B_atom a, B_int base);\n\n#define u8_DIV(a,b)       ( {if (b==0) $RAISE((B_BaseException)$NEW(B_ZeroDivisionError,to$str(\"u8 truediv: division by zero\"))); (double)a/(double)b;} )\n#define u8_FLOORDIV(a,b)  ( {if (b==0) $RAISE((B_BaseException)$NEW(B_ZeroDivisionError,to$str(\"u8 floordiv: division by zero\")));  a/b;} )\n#define u8_MOD(a,b)       ( {if (b==0) $RAISE((B_BaseException)$NEW(B_ZeroDivisionError,to$str(\"u8 mod: division by zero\"))); a%b;} )\n\nuint8_t u8_pow(uint8_t a, uint8_t b);\n"
  },
  {
    "path": "base/builtin/utils.c",
    "content": "B_list B_mk_list(int len, ...) {\n    B_list res = B_listD_new(len);\n    res->length = len;\n    va_list args;\n    va_start(args, len);\n    for (int i = 0; i < len; i++)\n        res->data[i] = va_arg(args, $WORD);\n    return res;\n}\n\nB_set B_mk_set(int len, B_Hashable w,...) {\n    B_set res = B_setG_new(w, NULL, NULL);\n    va_list args;\n    va_start(args, w);\n    for (int i=0; i < len; i++) {\n        $WORD elem = va_arg(args, $WORD);\n        B_set_add_entry(res,w,elem,fromB_u64(B_hash(w, elem)));\n    }\n    return res;\n}\n\nB_dict B_mk_dict(int len, B_Hashable w,...) {\n    B_dict res =  acton_malloc(sizeof(struct B_dict));\n    res->$class = &B_dictG_methods;\n    res->numelements = 0;\n    res->table = NULL;\n    va_list args;\n    va_start(args, w);\n    for (int i=0; i < len; i++) {\n        B_tuple t =  va_arg(args, B_tuple);\n        B_dictD_setitem(res, w, t->components[0], t->components[1]);\n    }\n    return res;\n}\n"
  },
  {
    "path": "base/builtin/utils.h",
    "content": "B_list B_mk_list(int len,...);\n\nB_dict B_mk_dict(int len, B_Hashable w,...);\n\nB_set B_mk_set(int len, B_Hashable w,...);\n"
  },
  {
    "path": "base/rts/common.c",
    "content": "#include <stdlib.h>\n#include <errno.h>\n\n#ifdef __linux__\n#include <dlfcn.h>\n#endif\n\n#include <mbedtls/platform.h>\n#define LIBXML_STATIC\n#include <libxml/xmlmemory.h>\n#include <tlsuv/tlsuv.h>\n\n#include \"rts/common.h\"\n\n#if defined(_WIN32) || defined(_WIN64)\n\n#include <math.h>\n\n// strndup() is not available on Windows\nchar *strndup( const char *s1, size_t n)\n{\n    char *copy= (char*)malloc( n+1 );\n    memcpy( copy, s1, n );\n    copy[n] = 0;\n    return copy;\n};\n#endif\n\ntypedef struct {\n    acton_malloc_func malloc;\n    acton_malloc_func malloc_atomic;\n    acton_realloc_func realloc;\n    acton_calloc_func calloc;\n    acton_free_func free;\n    acton_strdup_func strdup;\n    acton_strndup_func strndup;\n} acton__allocator_t;\n\nstatic acton__allocator_t acton__allocator = {\n    malloc,\n    malloc,\n    realloc,\n    calloc,\n    free,\n    strdup,\n    strndup\n};\n\nvoid acton_noop_free(void *ptr) {\n}\n\nvoid *GC_calloc(size_t count, size_t size) {\n    return GC_malloc(count*size);\n}\n\nvoid acton_init_alloc() {\n    // UV & TLSUV are used for IO, which is always done on the GC-heap. We don't\n    // have any constants related to UV, so we can always use the GC\n\n    uv_replace_allocator(GC_malloc,\n                         GC_realloc,\n                         GC_calloc,\n                         acton_noop_free);\n\n    tlsuv_set_allocator(GC_malloc,\n                            GC_realloc,\n                            GC_calloc,\n                            acton_noop_free);\n}\n\nint acton_replace_allocator(acton_malloc_func malloc_func,\n                            acton_malloc_func malloc_atomic_func,\n                            acton_realloc_func realloc_func,\n                            acton_calloc_func calloc_func,\n                            acton_free_func free_func,\n                            acton_strdup_func strdup_func,\n                            acton_strndup_func strndup_func) {\n    if (malloc_func == NULL || malloc_atomic_func == NULL ||\n        realloc_func == NULL || calloc_func == NULL ||\n        free_func == NULL || strdup_func == NULL ||\n        strndup_func == NULL\n        ) {\n        return -1;\n    }\n\n    acton__allocator.malloc = malloc_func;\n    acton__allocator.malloc_atomic = malloc_atomic_func;\n    acton__allocator.realloc = realloc_func;\n    acton__allocator.calloc = calloc_func;\n    acton__allocator.free = free_func;\n    acton__allocator.strdup = strdup_func;\n    acton__allocator.strndup = strndup_func;\n\n    bsdnt_replace_allocator(acton__allocator.malloc,\n                            acton__allocator.realloc,\n                            acton__allocator.free);\n\n    xmlMemSetup(acton__allocator.free,\n                acton__allocator.malloc,\n                acton__allocator.realloc,\n                acton__allocator.strdup);\n\n    mbedtls_platform_set_calloc_free(acton__allocator.calloc,\n                                     acton_noop_free);\n\n    return 0;\n}\n\nvoid* acton_malloc(size_t size) {\n    return acton__allocator.calloc(1, size);\n}\n\nvoid* acton_malloc_atomic(size_t size) {\n    return acton__allocator.malloc_atomic(size);\n}\n\nvoid* acton_realloc(void* ptr, size_t size) {\n    return acton__allocator.realloc(ptr, size);\n}\n\n\nvoid* acton_calloc(size_t count, size_t size) {\n    return acton__allocator.calloc(count, size);\n}\n\nvoid acton_free(void* ptr) {\n    int saved_errno;\n\n    /* The system allocator the assumption that errno is not modified but custom\n     * allocators may not be so careful.\n     */\n    saved_errno = errno;\n    acton__allocator.free(ptr);\n    errno = saved_errno;\n}\n\nchar *acton_strdup(const char *s) {\n    return acton__allocator.strdup(s);\n}\n\nchar *acton_strndup(const char *s, size_t n) {\n    return acton__allocator.strndup(s, n);\n}\n\n\nvoid* acton_gc_malloc(size_t size) {\n    return GC_malloc(size);\n}\n\nvoid* acton_gc_malloc_atomic(size_t size) {\n    return GC_malloc_atomic(size);\n}\n\nvoid* acton_gc_realloc(void* ptr, size_t size) {\n    return GC_realloc(ptr, size);\n}\n\nvoid* acton_gc_calloc(size_t count, size_t size) {\n    return GC_calloc(count, size);\n}\n\nvoid acton_gc_free(void* ptr) {\n    return GC_free(ptr);\n}\n\nchar *acton_gc_strdup(const char *s) {\n    return GC_strdup(s);\n}\n\nchar *acton_gc_strndup(const char *s, size_t n) {\n    return GC_strndup(s, n);\n}\n"
  },
  {
    "path": "base/rts/common.h",
    "content": "#pragma once\n#include <stddef.h>\n#include <stdlib.h>\n\n#define GC_THREADS 1\n#ifdef _WIN32\n#include <winsock2.h>\n#endif\n#include <gc.h>\n\ntypedef void *(*acton_malloc_func)(size_t size);\ntypedef void *(*acton_malloc_func)(size_t size);\ntypedef void *(*acton_realloc_func)(void* ptr, size_t size);\ntypedef void *(*acton_calloc_func)(size_t count, size_t size);\ntypedef void (*acton_free_func)(void* ptr);\ntypedef char *(*acton_strdup_func)(const char* s);\ntypedef char *(*acton_strndup_func)(const char* s, size_t n);\n\nvoid acton_init_malloc();\n\nint acton_replace_allocator(acton_malloc_func malloc_func,\n                            acton_malloc_func malloc_atomic_func,\n                            acton_realloc_func realloc_func,\n                            acton_calloc_func calloc_func,\n                            acton_free_func free_func,\n                            acton_strdup_func strdup_func,\n                            acton_strndup_func strndup_func);\n\n\nvoid *acton_malloc(size_t size);\nvoid *acton_malloc_atomic(size_t size);\nvoid *acton_realloc(void* ptr, size_t size);\nvoid *acton_calloc(size_t count, size_t size);\nvoid acton_free(void* ptr);\nchar *acton_strdup(const char *s);\nchar *acton_strndup(const char *s, size_t n);\n\nvoid *acton_gc_malloc(size_t size);\nvoid *acton_gc_malloc_atomic(size_t size);\nvoid *acton_gc_realloc(void* ptr, size_t size);\nvoid *acton_gc_calloc(size_t count, size_t size);\nvoid acton_gc_free(void* ptr);\nchar *acton_gc_strdup(const char *s);\nchar *acton_gc_strndup(const char *s, size_t n);\n"
  },
  {
    "path": "base/rts/gc.zig",
    "content": "const std = @import(\"std\");\nconst assert = std.debug.assert;\nconst testing = std.testing;\nconst mem = std.mem;\nconst Allocator = std.mem.Allocator;\n\nconst gc = @cImport({\n    @cInclude(\"gc.h\");\n});\n\n/// Returns the Allocator used for APIs in Zig\npub fn allocator() Allocator {\n    // Initialize libgc\n    if (gc.GC_is_init_called() == 0) {\n        gc.GC_init();\n    }\n\n    return Allocator{\n        .ptr = undefined,\n        .vtable = &gc_allocator_vtable,\n    };\n}\n\n/// Enable or disable interior pointers.\n/// If used, this must be called before the first allocator() call.\npub fn setAllInteriorPointers(enable_interior_pointers: bool) void {\n    gc.GC_set_all_interior_pointers(@intFromBool(enable_interior_pointers));\n}\n\n/// Returns the current heap size of used memory.\npub fn getHeapSize() u64 {\n    return gc.GC_get_heap_size();\n}\n\n/// Disable garbage collection.\npub fn disable() void {\n    gc.GC_disable();\n}\n\n/// Enables garbage collection. GC is enabled by default so this is\n/// only useful if you called disable earlier.\npub fn enable() void {\n    gc.GC_enable();\n}\n\n// Performs a full, stop-the-world garbage collection. With leak detection\n// enabled this will output any leaks as well.\npub fn collect() void {\n    gc.GC_gcollect();\n}\n\n/// Perform some garbage collection. Returns zero when work is done.\npub fn collectLittle() u8 {\n    return @as(u8, @intCast(gc.GC_collect_a_little()));\n}\n\n/// Enables leak-finding mode. See the libgc docs for more details.\npub fn setFindLeak(v: bool) void {\n    return gc.GC_set_find_leak(@intFromBool(v));\n}\n\n// TODO(mitchellh): there are so many more functions to add here\n// from gc.h, just add em as they're useful.\n\n/// GcAllocator is an implementation of std.mem.Allocator that uses\n/// libgc under the covers. This means that all memory allocated with\n/// this allocated doesn't need to be explicitly freed (but can be).\n///\n/// The GC is a singleton that is globally shared. Multiple GcAllocators\n/// do not allocate separate pages of memory; they share the same underlying\n/// pages.\n///\n// NOTE(mitchellh): this is basically just a copy of the standard CAllocator\n// since libgc has a malloc/free-style interface. There are very slight differences\n// due to API differences but overall the same.\npub const GcAllocator = struct {\n    fn alloc(\n        _: *anyopaque,\n        len: usize,\n        alignment: mem.Alignment,\n        return_address: usize,\n    ) ?[*]u8 {\n        _ = return_address;\n        assert(len > 0);\n        return alignedAlloc(len, alignment);\n    }\n\n    fn resize(\n        _: *anyopaque,\n        buf: []u8,\n        alignment: mem.Alignment,\n        new_len: usize,\n        return_address: usize,\n    ) bool {\n        _ = alignment;\n        _ = return_address;\n        if (new_len <= buf.len) {\n            return true;\n        }\n\n        const full_len = alignedAllocSize(buf.ptr);\n        if (new_len <= full_len) {\n            return true;\n        }\n\n        return false;\n    }\n\n    fn free(\n        _: *anyopaque,\n        buf: []u8,\n        alignment: mem.Alignment,\n        return_address: usize,\n    ) void {\n        _ = alignment;\n        _ = return_address;\n        alignedFree(buf.ptr);\n    }\n\n    fn getHeader(ptr: [*]u8) *[*]u8 {\n        return @as(*[*]u8, @ptrFromInt(@intFromPtr(ptr) - @sizeOf(usize)));\n    }\n\n    fn alignedAlloc(len: usize, alignment: mem.Alignment) ?[*]u8 {\n        const alignment_bytes = alignment.toByteUnits();\n\n        // Thin wrapper around regular malloc, overallocate to account for\n        // alignment padding and store the orignal malloc()'ed pointer before\n        // the aligned address.\n        const unaligned_ptr = @as([*]u8, @ptrCast(gc.GC_malloc(len + alignment_bytes - 1 + @sizeOf(usize)) orelse return null));\n        const unaligned_addr = @intFromPtr(unaligned_ptr);\n        const aligned_addr = mem.alignForward(usize, unaligned_addr + @sizeOf(usize), alignment_bytes);\n        const aligned_ptr = unaligned_ptr + (aligned_addr - unaligned_addr);\n        getHeader(aligned_ptr).* = unaligned_ptr;\n\n        return aligned_ptr;\n    }\n\n    fn alignedFree(ptr: [*]u8) void {\n        const unaligned_ptr = getHeader(ptr).*;\n        gc.GC_free(unaligned_ptr);\n    }\n\n    fn alignedAllocSize(ptr: [*]u8) usize {\n        const unaligned_ptr = getHeader(ptr).*;\n        const delta = @intFromPtr(ptr) - @intFromPtr(unaligned_ptr);\n        return gc.GC_size(unaligned_ptr) - delta;\n    }\n\n    fn remap(\n        _: *anyopaque,\n        _: []u8,\n        _: mem.Alignment,\n        _: usize,\n        _: usize,\n    ) ?[*]u8 {\n        return null;\n    }\n};\n\nconst gc_allocator_vtable = Allocator.VTable{\n    .alloc = GcAllocator.alloc,\n    .resize = GcAllocator.resize,\n    .remap = GcAllocator.remap,\n    .free = GcAllocator.free,\n};\n\ntest \"GcAllocator\" {\n    const alloc = allocator();\n\n    try std.heap.testAllocator(alloc);\n    try std.heap.testAllocatorAligned(alloc);\n    try std.heap.testAllocatorLargeAlignment(alloc);\n    try std.heap.testAllocatorAlignedShrink(alloc);\n}\n\ntest \"heap size\" {\n    // No garbage so should be 0\n    try testing.expect(collectLittle() == 0);\n\n    // Force a collection should work\n    collect();\n\n    try testing.expect(getHeapSize() > 0);\n}\n"
  },
  {
    "path": "base/rts/io.c",
    "content": "#ifdef ACTON_THREADS\n#define GC_THREADS 1\n#endif\n#include <gc.h>\n\n#include \"io.h\"\n\n#include <uv.h>\n#include <unistd.h>\n\n#include \"log.h\"\n#include \"log.h\"\n\nextern char rts_exit;\n\nuv_loop_t *get_uv_loop() {\n    WorkerCtx wctx = GET_WCTX();\n    return (uv_loop_t *)wctx->uv_loop;\n}\n\nvoid alloc_buffer(uv_handle_t *handle, size_t size, uv_buf_t *buf) {\n    *buf = uv_buf_init((char*) acton_malloc_atomic(size), size);\n}\n"
  },
  {
    "path": "base/rts/io.h",
    "content": "#pragma once\n\n#ifdef __linux__\n#ifndef _GNU_SOURCE\n#define _GNU_SOURCE 1\n#endif\n#endif\n\n#define GC_THREADS 1\n#include <gc.h>\n\n#include <uv.h>\n\n#ifdef __gnu_linux__\n    #define IS_GNU_LINUX\n#elif  __APPLE__ && __MACH__\n    #define IS_MACOS\n#endif\n\nextern uv_loop_t *aux_uv_loop;\nuv_loop_t *get_uv_loop();\n\nvoid alloc_buffer(uv_handle_t *handle, size_t size, uv_buf_t *buf);\n"
  },
  {
    "path": "base/rts/log.c",
    "content": "/*\n * Copyright (c) 2020 rxi\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to\n * deal in the Software without restriction, including without limitation the\n * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or\n * sell copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING\n * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS\n * IN THE SOFTWARE.\n */\n\n#ifdef ACTON_THREADS\n#include <pthread.h>\n#endif\n\n#include <uv.h>\n#include \"log.h\"\n\n#define MAX_CALLBACKS 32\n#ifdef ACTON_THREADS\nstatic pthread_mutex_t l_mutex;\n#endif\n\ntypedef struct {\n  log_LogFn fn;\n  void *udata;\n  int level;\n} Callback;\n\nstatic struct {\n  void *udata;\n  int level;\n  bool quiet;\n  Callback callbacks[MAX_CALLBACKS];\n} L;\n\n\nstatic const char *level_strings[] = {\n  \"TRACE\", \"DEBUG\", \"INFO\", \"WARN\", \"ERROR\", \"FATAL\"\n};\n\n#ifdef LOG_USE_COLOR\nstatic const char *level_colors[] = {\n  \"\\x1b[94m\", \"\\x1b[36m\", \"\\x1b[32m\", \"\\x1b[33m\", \"\\x1b[31m\", \"\\x1b[35m\"\n};\n#endif\n\n\nstatic void stdout_callback(log_Event *ev) {\n  // Get a short thread name\n  char tname[16] = \"\";\n#ifdef ACTON_THREADS\n  pthread_getname_np(pthread_self(), tname, 16);\n#endif\n  if (strncmp(tname, \"IO\", 6) == 0) {\n  } else if (strncmp(tname, \"Worker\", 6) == 0) {\n    strncpy(tname, &tname[7], 4);\n  } else {\n    // main thread, ignore the name\n    strcpy(tname, \"\");\n  }\n\n  char buf[16];\n  buf[strftime(buf, sizeof(buf), \"%H:%M:%S\", ev->date)] = '\\0';\n#ifdef LOG_USE_COLOR\n  fprintf(\n    ev->udata, \"%s.%06lu %s%-5s\\x1b[0m \\x1b[90m%-20s:%5d:\\x1b[0m RTS %2s: \",\n    buf, ev->ts.tv_nsec/1000, level_colors[ev->level], level_strings[ev->level],\n    ev->file, ev->line, tname);\n#else\n  fprintf(\n    ev->udata, \"%s.%06lu %-5s %-20s:%5d: RTS %2s: \",\n    buf, ev->ts.tv_nsec/1000, level_strings[ev->level], ev->file, ev->line, tname);\n#endif\n  vfprintf(ev->udata, ev->fmt, ev->ap);\n  fprintf(ev->udata, \"\\n\");\n  fflush(ev->udata);\n}\n\n\nstatic void file_callback(log_Event *ev) {\n  // Get a short thread name\n  char tname[16];\n#ifdef ACTON_THREADS\n  pthread_getname_np(pthread_self(), tname, 16);\n#endif\n  if (strncmp(tname, \"IO\", 6) == 0) {\n  } else if (strncmp(tname, \"Worker\", 6) == 0) {\n    strncpy(tname, &tname[7], 4);\n  } else {\n    // main thread, ignore the name\n    strcpy(tname, \"\");\n  }\n\n  char buf[64];\n  buf[strftime(buf, sizeof(buf), \"%Y-%m-%d %H:%M:%S\", ev->date)] = '\\0';\n  fprintf(\n    ev->udata, \"%s.%09lu %-5s %-20s:%5d: RTS %2s: \",\n    buf, ev->ts.tv_nsec, level_strings[ev->level], ev->file, ev->line, tname);\n  vfprintf(ev->udata, ev->fmt, ev->ap);\n  fprintf(ev->udata, \"\\n\");\n  fflush(ev->udata);\n}\n\n\nstatic void lock(void)   {\n#ifdef ACTON_THREADS\n  pthread_mutex_lock(&l_mutex);\n#endif\n}\n\n\nstatic void unlock(void) {\n#ifdef ACTON_THREADS\n  pthread_mutex_unlock(&l_mutex);\n#endif\n}\n\n\nconst char* log_level_string(int level) {\n  return level_strings[level];\n}\n\nint log_get_level() {\n  return L.level;\n}\n\nvoid log_set_level(int level) {\n  L.level = level;\n}\n\n\nvoid log_set_quiet(bool enable) {\n  L.quiet = enable;\n}\n\n\nint log_add_callback(log_LogFn fn, void *udata, int level) {\n  for (int i = 0; i < MAX_CALLBACKS; i++) {\n    if (!L.callbacks[i].fn) {\n      L.callbacks[i] = (Callback) { fn, udata, level };\n      return 0;\n    }\n  }\n  return -1;\n}\n\n\nint log_add_fp(FILE *fp, int level) {\n  return log_add_callback(file_callback, fp, level);\n}\n\n\nstatic void init_event(log_Event *ev, void *udata) {\n  if (!ev->date) {\n    uv_clock_gettime(UV_CLOCK_REALTIME, &ev->ts);\n    ev->date = localtime(&ev->ts.tv_sec);\n  }\n  ev->udata = udata;\n}\n\n\nvoid log_log(int level, const char *file, int line, const char *fmt, ...) {\n  log_Event ev = {\n    .fmt   = fmt,\n    .file  = file,\n    .line  = line,\n    .level = level,\n  };\n\n  lock();\n\n  if (!L.quiet && level >= L.level) {\n    init_event(&ev, stderr);\n    va_start(ev.ap, fmt);\n    stdout_callback(&ev);\n    va_end(ev.ap);\n  }\n\n  for (int i = 0; i < MAX_CALLBACKS && L.callbacks[i].fn; i++) {\n    Callback *cb = &L.callbacks[i];\n    if (level >= cb->level) {\n      init_event(&ev, cb->udata);\n      va_start(ev.ap, fmt);\n      cb->fn(&ev);\n      va_end(ev.ap);\n    }\n  }\n\n  unlock();\n}\n"
  },
  {
    "path": "base/rts/log.h",
    "content": "/**\n * Copyright (c) 2020 rxi\n *\n * This library is free software; you can redistribute it and/or modify it\n * under the terms of the MIT license. See `log.c` for details.\n */\n\n#ifndef LOG_H\n#define LOG_H\n\n#ifdef __linux__\n#ifndef _GNU_SOURCE\n#define _GNU_SOURCE 1\n#endif\n#endif\n\n#include <stdio.h>\n#include <stdarg.h>\n#include <stdbool.h>\n#include <time.h>\n\n#include \"../rts/rts.h\"\n\n#define LOG_VERSION \"0.1.0\"\n\ntypedef struct {\n  va_list ap;\n  const char *fmt;\n  const char *file;\n  struct timespec ts;\n  struct tm *date;\n  void *udata;\n  int line;\n  int level;\n} log_Event;\n\ntypedef void (*log_LogFn)(log_Event *ev);\ntypedef void (*log_LockFn)(bool lock, void *udata);\n\nenum { LOG_TRACE, LOG_DEBUG, LOG_INFO, LOG_WARN, LOG_ERROR, LOG_FATAL };\n\n#define log_trace(...) log_log(LOG_TRACE, __FILE__, __LINE__, __VA_ARGS__)\n#define log_debug(...) log_log(LOG_DEBUG, __FILE__, __LINE__, __VA_ARGS__)\n#define log_info(...)  log_log(LOG_INFO,  __FILE__, __LINE__, __VA_ARGS__)\n#define log_warn(...)  log_log(LOG_WARN,  __FILE__, __LINE__, __VA_ARGS__)\n#define log_error(...) log_log(LOG_ERROR, __FILE__, __LINE__, __VA_ARGS__)\n#define log_fatal(...) log_log(LOG_FATAL, __FILE__, __LINE__, __VA_ARGS__)\n\nconst char* log_level_string(int level);\nint log_get_level();\nvoid log_set_level(int level);\nvoid log_set_quiet(bool enable);\nint log_add_callback(log_LogFn fn, void *udata, int level);\nint log_add_fp(FILE *fp, int level);\n\nvoid log_log(int level, const char *file, int line, const char *fmt, ...);\n\n#endif\n"
  },
  {
    "path": "base/rts/netstring.c",
    "content": "/* Streaming API for netstrings. */\n\n#include <stdio.h>\n#include <string.h>\n#include <stdlib.h>\n#include <ctype.h>\n#include \"netstring.h\"\n\n/* Reads a netstring from a `buffer` of length `buffer_length`. Writes\n   to `netstring_start` a pointer to the beginning of the string in\n   the buffer, and to `netstring_length` the length of the\n   string. Does not allocate any memory. If it reads successfully,\n   then it returns 0. If there is an error, then the return value will\n   be negative. The error values are:\n\n   NETSTRING_ERROR_TOO_LONG      More than 999999999 bytes in a field\n   NETSTRING_ERROR_NO_COLON      No colon was found after the number\n   NETSTRING_ERROR_TOO_SHORT     Number of bytes greater than buffer length\n   NETSTRING_ERROR_NO_COMMA      No comma was found at the end\n   NETSTRING_ERROR_LEADING_ZERO  Leading zeros are not allowed\n   NETSTRING_ERROR_NO_LENGTH     Length not given at start of netstring\n\n   If you're sending messages with more than 999999999 bytes -- about\n   2 GB -- then you probably should not be doing so in the form of a\n   single netstring. This restriction is in place partially to protect\n   from malicious or erroneous input, and partly to be compatible with\n   D. J. Bernstein's reference implementation.\n\n   Example:\n      if (netstring_read(&buf, &buflen, &str, &len) < 0) failed();\n */\nint netstring_read(char **pbuffer, size_t *pbuffer_length,\n                   char **netstring_start, size_t *netstring_length) {\n  int i;\n  size_t len = 0;\n  char *buffer = *pbuffer;\n  size_t buffer_length = *pbuffer_length;\n\n  /* Write default values for outputs */\n  *netstring_start = NULL; *netstring_length = 0;\n\n  /* Make sure buffer is big enough. Minimum size is 3. */\n  if (buffer_length < 3) return NETSTRING_ERROR_TOO_SHORT;\n\n  /* No leading zeros allowed! */\n  if (buffer[0] == '0' && isdigit(buffer[1]))\n    return NETSTRING_ERROR_LEADING_ZERO;\n\n  /* The netstring must start with a number */\n  if (!isdigit(buffer[0])) return NETSTRING_ERROR_NO_LENGTH;\n\n  /* Read the number of bytes */\n  for (i = 0; i < buffer_length && isdigit(buffer[i]); i++) {\n    /* Error if more than 9 digits */\n    if (i >= 9) return NETSTRING_ERROR_TOO_LONG;\n    /* Accumulate each digit, assuming ASCII. */\n    len = len*10 + (buffer[i] - '0');\n  }\n\n  /* Check buffer length once and for all. Specifically, we make sure\n     that the buffer is longer than the number we've read, the length\n     of the string itself, and the colon and comma. */\n  if (i + len + 1 >= buffer_length) return NETSTRING_ERROR_TOO_SHORT;\n\n  /* Read the colon */\n  if (buffer[i++] != ':') return NETSTRING_ERROR_NO_COLON;\n  \n  /* Test for the trailing comma */\n  if (buffer[i + len] != ',') return NETSTRING_ERROR_NO_COMMA;\n\n  /* Set the return values */\n  *netstring_start = &buffer[i];\n  *netstring_length = len;\n  *pbuffer = *netstring_start + len + 1;\n  *pbuffer_length = buffer_length - (i + len + 1);\n\n  return 0;\n}\n\n/* Retrieves the size of the concatenated netstrings */\nint netstring_list_size(char *buffer, size_t size, size_t *ptotal) {\n  char  *str, *base = buffer;\n  size_t len,  remaining = size;\n  int rc;\n\n  while( remaining>0 && (rc=netstring_read(&base, &remaining, &str, &len))==0 ){\n  }\n\n  if( rc==NETSTRING_ERROR_NO_LENGTH || rc==NETSTRING_ERROR_TOO_SHORT ) rc = 0;\n  *ptotal = size - remaining;\n  return rc;\n}\n\n/* Retrieves the number of concatenated netstrings */\nint netstring_list_count(char *buffer, size_t size, int *pcount) {\n  char  *str, *base = buffer;\n  size_t len,  remaining = size;\n  int rc, count = 0;\n\n  while( remaining>0 && (rc=netstring_read(&base, &remaining, &str, &len))==0 ){\n    count++;\n  }\n\n  if( rc==NETSTRING_ERROR_NO_LENGTH || rc==NETSTRING_ERROR_TOO_SHORT ) rc = 0;\n  *pcount = count;\n  return rc;\n}\n\n/* count the number of digits (base 10) in a positive integer */\nint numdigits(size_t len) {\n  int n = 1;\n  if ( len >= 100000000 ) { n += 8; len /= 100000000; }\n  if ( len >= 10000     ) { n += 4; len /= 10000; }\n  if ( len >= 100       ) { n += 2; len /= 100; }\n  if ( len >= 10        ) { n += 1; }\n  return n;\n}\n\n/* Return the length, in ASCII characters, of a netstring containing\n   `data_length` bytes. */\nsize_t netstring_buffer_size(size_t data_length) {\n  return (size_t)numdigits(data_length) + data_length + 2;\n}\n\n/* Allocate and create a netstring containing the first `len` bytes of\n   `data`. This must be manually freed by the client. If `len` is 0\n   then no data will be read from `data`, and it may be NULL.\n   Returns the netstring size not including the null terminator */\nsize_t netstring_add_ex(char **netstring, char *data, size_t len) {\n  size_t num_len, size_prev=0, size_next;\n  char *ptr;\n\n  if (netstring == 0 || (len > 0 && data == 0)) return 0;\n\n  num_len = numdigits(len);\n  size_next = num_len + len + 2;\n\n  if (*netstring == 0) {\n    ptr = acton_malloc(size_next + 1);\n    if (ptr == 0) return 0;\n    *netstring = ptr;\n  } else {\n    size_prev = strlen(*netstring);\n    ptr = acton_realloc(*netstring, size_prev + size_next + 1);\n    if (ptr == 0) return 0;\n    *netstring = ptr;\n    ptr += size_prev;\n  }\n\n  if (len == 0) {\n    strcpy(ptr, \"0:,\");\n  } else {\n    sprintf(ptr, \"%lu:\", (unsigned long)len);\n    ptr += num_len + 1;\n    memcpy(ptr, data, len);\n    ptr += len; *ptr = ',';\n    ptr++; *ptr = 0;\n  }\n  return size_prev + size_next;\n}\n\nsize_t netstring_add(char **netstring, char *data) {\n  return netstring_add_ex(netstring, data, strlen(data));\n}\n"
  },
  {
    "path": "base/rts/netstring.h",
    "content": "#ifndef __NETSTRING_STREAM_H\n#define __NETSTRING_STREAM_H\n\n#include <string.h>\n\nsize_t netstring_add(char **netstring, char *data);\nsize_t netstring_add_ex(char **netstring, char *data, size_t len);\n\nint netstring_read(char **buffer_start, size_t *buffer_length,\n                   char **netstring_start, size_t *netstring_length);\n\nsize_t netstring_buffer_size(size_t data_length);\n\nint netstring_list_size(char *buffer, size_t size, size_t *ptotal);\nint netstring_list_count(char *buffer, size_t size, int *pcount);\n\n/* Errors that can occur during netstring parsing */\n#define NETSTRING_ERROR_TOO_LONG     -1\n#define NETSTRING_ERROR_NO_COLON     -2\n#define NETSTRING_ERROR_TOO_SHORT    -3\n#define NETSTRING_ERROR_NO_COMMA     -4\n#define NETSTRING_ERROR_LEADING_ZERO -5\n#define NETSTRING_ERROR_NO_LENGTH    -6\n\n#endif\n"
  },
  {
    "path": "base/rts/q.c",
    "content": "#include \"rts.h\"\n#include \"q.h\"\n\nstatic inline void spinlock_lock($Lock *f) {\n    while (atomic_flag_test_and_set(f) == true) {\n        // spin until we could set the flag\n    }\n}\nstatic inline void spinlock_unlock($Lock *f) {\n    atomic_flag_clear(f);\n}\n\n#if defined MPMC && MPMC == 3\nint ENQ_ready($Actor a) {\n    // TODO: atomics!\n}\n#elif defined MPMC && MPMC == 2\nint ENQ_ready($Actor a) {\n    int i = a->$affinity;\n    assert(a != NULL && a->$waitsfor == NULL);\n    spinlock_lock(&rqs[i].lock);\n    if (rqs[i].tail) {\n        rqs[i].tail->$next = a;\n        rqs[i].tail = a;\n    } else {\n        rqs[i].head = a;\n        rqs[i].tail = a;\n    }\n    a->$next = NULL;\n    rqs[i].count++;\n    spinlock_unlock(&rqs[i].lock);\n    // If we enqueue to someone who is not us, immediately wake them up...\n    WorkerCtx wctx = GET_WCTX();\n    if (wctx != NULL) {\n        long our_wtid = wctx->id;\n        if (our_wtid != i)\n            wake_wt(i);\n    }\n    return i;\n}\n#else\nint ENQ_ready($Actor a) {\n    int i = a->$affinity;\n    spinlock_lock(&rqs[i].lock);\n    if (rqs[i].head) {\n        $Actor x = rqs[i].head;\n        while (x->$next)\n            x = x->$next;\n        x->$next = a;\n    } else {\n        rqs[i].head = a;\n    }\n    a->$next = NULL;\n    spinlock_unlock(&rqs[i].lock);\n    // If we enqueue to someone who is not us, immediately wake them up...\n    WorkerCtx wctx = GET_WCTX();\n    if (wctx != NULL) {\n        long our_wtid = wctx->id;\n        if (our_wtid != i)\n            wake_wt(i);\n    }\n    return i;\n}\n#endif\n\n// Atomically enqueue actor \"a\" onto the right ready-queue, either a thread\n// local one or the \"default\" shared one.\n\n// Atomically dequeue and return the first actor from a ready-queue, first\n// dequeueing from the thread specific queue and second from the global shared\n// readyQ or return NULL if no work is found.\n#if defined MPMC && MPMC == 3\n$Actor _DEQ_ready(int idx) {\n    // TODO: atomics!\n}\n#elif defined MPMC && MPMC == 2\n$Actor _DEQ_ready(int idx) {\n    $Actor res = NULL;\n    if (rqs[idx].head == NULL) {\n        return res;\n    }\n\n    spinlock_lock(&rqs[idx].lock);\n    res = rqs[idx].head;\n    if (res) {\n        rqs[idx].head = res->$next;\n        res->$next = NULL;\n        if (rqs[idx].head == NULL) {\n            rqs[idx].tail = NULL;\n        }\n        assert(res->$waitsfor == NULL);\n    } else {\n        rqs[idx].tail = NULL;\n    }\n    rqs[idx].count--;\n    spinlock_unlock(&rqs[idx].lock);\n    return res;\n}\n#else\n// First version\n$Actor _DEQ_ready(int idx) {\n    $Actor res = NULL;\n    if (rqs[idx].head == NULL)\n        return res;\n\n    spinlock_lock(&rqs[idx].lock);\n    res = rqs[idx].head;\n    if (res) {\n        rqs[idx].head = res->$next;\n        res->$next = NULL;\n    }\n    spinlock_unlock(&rqs[idx].lock);\n    return res;\n}\n#endif\n\n$Actor DEQ_ready(int idx) {\n    assert(idx >= 0 && idx < 256);\n    $Actor res = _DEQ_ready(idx);\n    if (res)\n        return res;\n\n    // Unless we are running without threads, worker thread 0 (our main thread)\n    // is special and does not pick up work from the shared queue. It only\n    // serves special actors scheduled on it.\n    if (idx == 0)\n        return NULL;\n\n    res = _DEQ_ready(SHARED_RQ);\n    return res;\n}\n\n\n#if MSGQ == 2\n// Atomically enqueue message \"m\" onto the queue of actor \"a\",\n// return true if the queue was previously empty.\nbool ENQ_msg(B_Msg m, $Actor a) {\n    bool did_enq = true;\n    spinlock_lock(&a->B_Msg_lock);\n    m->$next = NULL;\n    if (a->B_Msg_tail) {\n        a->B_Msg_tail->$next = m;\n        a->B_Msg_tail = m;\n        did_enq = false;\n    } else {\n        a->B_Msg = m;\n        a->B_Msg_tail = m;\n    }\n    spinlock_unlock(&a->B_Msg_lock);\n    return did_enq;\n}\n\n// Atomically dequeue the first message from the queue of actor \"a\",\n// return true if the queue still holds messages.\nbool DEQ_msg($Actor a) {\n    bool has_more = false;\n    spinlock_lock(&a->B_Msg_lock);\n    B_Msg x = a->B_Msg;\n    if (x) {\n        a->B_Msg = x->$next;\n        x->$next = NULL;\n        if (a->B_Msg == NULL) {\n            a->B_Msg_tail = NULL;\n        }\n        has_more = a->B_Msg != NULL;\n    } else {\n        a->B_Msg_tail = NULL;\n    }\n    spinlock_unlock(&a->B_Msg_lock);\n    return has_more;\n}\n#else // MSGQ == 1\n// Atomically enqueue message \"m\" onto the queue of actor \"a\",\n// return true if the queue was previously empty.\nbool ENQ_msg(B_Msg m, $Actor a) {\n    bool did_enq = true;\n    spinlock_lock(&a->B_Msg_lock);\n    m->$next = NULL;\n    if (a->B_Msg) {\n        B_Msg x = a->B_Msg;\n        while (x->$next)\n            x = x->$next;\n        x->$next = m;\n        did_enq = false;\n    } else {\n        a->B_Msg = m;\n    }\n    spinlock_unlock(&a->B_Msg_lock);\n    return did_enq;\n}\n\n// Atomically dequeue the first message from the queue of actor \"a\",\n// return true if the queue still holds messages.\nbool DEQ_msg($Actor a) {\n    bool has_more = false;\n    spinlock_lock(&a->B_Msg_lock);\n    if (a->B_Msg) {\n        B_Msg x = a->B_Msg;\n        a->B_Msg = x->$next;\n        x->$next = NULL;\n        has_more = a->B_Msg != NULL;\n    }\n    spinlock_unlock(&a->B_Msg_lock);\n    return has_more;\n}\n#endif // MSGQ\n"
  },
  {
    "path": "base/rts/q.h",
    "content": "#pragma once\n\n#define MPMC 2\n\n#include \"rts.h\"\n\n\n#if defined MPMC && MPMC == 3\n// TODO: do atomics!\nstruct mpmcq {\n    $Actor  head;\n    $Actor tail;\n    unsigned long long count;\n    $Lock lock;\n};\n#else\nstruct mpmcq {\n    $Actor head;\n    $Actor tail;\n    unsigned long long count;\n    $Lock lock;\n};\n#endif\n\nextern struct mpmcq rqs[NUM_RQS];\n"
  },
  {
    "path": "base/rts/rts.c",
    "content": "/*\n * Copyright (C) 2019-2021 Data Ductus AB\n *\n * Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:\n *\n * 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.\n *\n * 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.\n *\n * 3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission.\n *\n * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS \"AS IS\" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n */\n\n#ifdef __linux__\n#ifndef _GNU_SOURCE\n#define _GNU_SOURCE 1\n#endif\n#endif\n\n#ifdef ACTON_THREADS\n#define GC_THREADS 1\n#endif\n#include <gc.h>\n\n#if defined(_WIN32) || defined(_WIN64)\n#else\n#include <termios.h>\n#endif\n#include <unistd.h>\n#ifdef ACTON_THREADS\n#include <pthread.h>\n#endif\n#include <stdio.h>\n#include <stdarg.h>\n#ifdef ACTON_DB\n#include <uuid/uuid.h>\n#endif\n#include <signal.h>\n\n#include <time.h>\n#include <stdlib.h>\n\n// Windows\n#ifdef _WIN32\n#else\n#include <sys/un.h>\n#include <sys/time.h>\n#include <sys/wait.h>\n#endif\n#ifdef __linux__\n#include <sys/prctl.h>\n#endif\n\n#include \"common.h\"\n#include \"common.c\"\n\n#include \"yyjson.h\"\n#include \"rts.h\"\n\n#include <uv.h>\n\n#include \"q.c\"\n\n#include \"io.c\"\n\n#include \"log.c\"\n#include \"netstring.h\"\n#include \"../builtin/env.h\"\n#include \"../builtin/function.h\"\n\n#ifdef ACTON_DB\n#include \"../backend/client_api.h\"\n#include \"../backend/fastrand.h\"\nextern struct dbc_stat dbc_stats;\n#endif\n\n#ifndef _WIN32\nstruct sigaction sa_abrt, sa_ill, sa_int, sa_pipe, sa_segv, sa_term;\n#endif\n\nchar rts_verbose = 0;\nchar rts_debug = 0;\nlong num_wthreads = -1;\n\nchar rts_exit = 0;\nint return_val = 0;\n\nchar *appname = NULL;\npid_t pid;\n\nuv_loop_t *aux_uv_loop = NULL;\nuv_loop_t *uv_loops[MAX_WTHREADS];\nuv_async_t stop_ev[MAX_WTHREADS];\nuv_async_t wake_ev[MAX_WTHREADS];\nuv_check_t work_ev[MAX_WTHREADS];\nWorkerCtx wctxs[MAX_WTHREADS];\nuv_timer_t *timer_ev;\n\nchar *mon_log_path = NULL;\nint mon_log_period = 30;\nchar *mon_socket_path = NULL;\n\n\nstruct wt_stat wt_stats[MAX_WTHREADS];\n\n// Conveys current thread status, like what is it doing?\nenum WT_State {WT_NoExist = 0, WT_Working = 1, WT_Idle = 2, WT_Sleeping = 3};\nstatic const char *WT_State_name[] = {\"poof\", \"work\", \"idle\", \"sleep\"};\n\n/*\n * Custom printf macros for printing verbose and debug information\n * RTS Debug Printf   = rtsd_printf\n */\n#ifdef DEV\n#define rtsd_printf(...) if (rts_debug) log_debug(__VA_ARGS__)\n#else\n#define rtsd_printf(...)\n#endif\n\n\n#if defined(IS_MACOS)\n#include <sys/types.h>\n#include <sys/sysctl.h>\n#include <mach/mach_init.h>\n#include <mach/thread_policy.h>\n\n#define SYSCTL_CORE_COUNT   \"machdep.cpu.core_count\"\n\ntypedef struct cpu_set {\n  uint32_t    count;\n} cpu_set_t;\n\nstatic inline void\nCPU_ZERO(cpu_set_t *cs) { cs->count = 0; }\n\nstatic inline void\nCPU_SET(int num, cpu_set_t *cs) { cs->count |= (1 << num); }\n\nstatic inline int\nCPU_ISSET(int num, cpu_set_t *cs) { return (cs->count & (1 << num)); }\n\nint sched_getaffinity(pid_t pid, size_t cpu_size, cpu_set_t *cpu_set)\n{\n    int32_t core_count = 0;\n    size_t  len = sizeof(core_count);\n    int ret = sysctlbyname(SYSCTL_CORE_COUNT, &core_count, &len, 0, 0);\n    if (ret) {\n        fprintf(stderr, \"error getting the core count %d\\n\", ret);\n        return -1;\n    }\n    cpu_set->count = 0;\n    for (int i = 0; i < core_count; i++) {\n        cpu_set->count |= (1 << i);\n    }\n\n    return 0;\n}\n\nkern_return_t thread_policy_set(\n                    thread_t thread,\n                    thread_policy_flavor_t flavor,\n                    thread_policy_t policy_info,\n                    mach_msg_type_number_t count);\n\nint pthread_setaffinity_np(pthread_t thread, size_t cpu_size, cpu_set_t *cpu_set) {\n    int core = 0;\n    for (core = 0; core < 8 * cpu_size; core++) {\n        if (CPU_ISSET(core, cpu_set))\n            break;\n    }\n    thread_affinity_policy_data_t policy = { core };\n\n    thread_port_t mach_thread = pthread_mach_thread_np(thread);\n    thread_policy_set(mach_thread, THREAD_AFFINITY_POLICY, (thread_policy_t)&policy, 1);\n\n    return 0;\n}\n#endif\n\nextern void $ROOTINIT();\nextern $Actor $ROOT();\n\nstruct mpmcq rqs[NUM_RQS];\n\n$Actor root_actor = NULL;\nB_Env env_actor = NULL;\n\nB_Msg timerQ = NULL;\n$Lock timerQ_lock;\n\nint64_t next_key = -10;\n$Lock next_key_lock;\n\nint64_t timer_consume_hd = 0;       // Lacks protection, although spinlocks wouldn't help concurrent increments. Must fix in db!\n\ntime_t current_time() {\n    uv_timespec64_t now;\n    if (uv_clock_gettime(UV_CLOCK_REALTIME, &now) != 0) {\n        log_error(\"uv_clock_gettime() failed\");\n        return 0;\n    }\n    return now.tv_sec * 1000000 + now.tv_nsec / 1000;\n}\n\n#ifdef ACTON_THREADS\npthread_key_t self_key;\npthread_key_t pkey_wctx;\n\npthread_mutex_t rts_exit_lock = PTHREAD_MUTEX_INITIALIZER;\npthread_cond_t rts_exit_signal = PTHREAD_COND_INITIALIZER;\n\n#define NUM_THREADS num_wthreads+1\n\nvoid pin_actor_affinity() {\n    $Actor a = ($Actor)pthread_getspecific(self_key);\n    WorkerCtx wctx = (WorkerCtx)pthread_getspecific(pkey_wctx);\n    long i = wctx->id;\n    log_debug(\"Pinning affinity for %s actor %ld to current WT %d\", a->$class->$GCINFO, a->$globkey, i);\n    a->$affinity = i;\n}\n\nvoid set_actor_affinity(int wthread_id) {\n    $Actor a = ($Actor)pthread_getspecific(self_key);\n    log_debug(\"Setting affinity for %s actor %ld to WT %d\", a->$class->$GCINFO, a->$globkey, wthread_id);\n    a->$affinity = wthread_id;\n}\n#else // ACTON_THREADS\n$Actor self_actor;\n\n#define NUM_THREADS 1\n\nvoid pin_actor_affinity() { }\nvoid set_actor_affinity(int wthread_id) { }\n#endif // ACTON_THREADS\n\nvoid wake_wt(int wtid) {\n    // We are sometimes optimistically called, i.e. the caller sometimes does\n    // not really know whether there is new work or not. We check and if there\n    // is not, then there is no need to wake anyone up.\n    if (!rqs[wtid].head)\n        return;\n\n#ifdef ACTON_THREADS\n    // wake up corresponding worker threads....\n    if (wtid == SHARED_RQ) {\n        for (int i = 1; i <= num_wthreads; i++) {\n            if (wt_stats[i].state == WT_Idle) {\n                uv_async_send(&wake_ev[i]);\n                return;\n            }\n        }\n    } else {\n        // thread specific queue\n        uv_async_send(&wake_ev[wtid]);\n    }\n#else\n    uv_async_send(&wake_ev[wtid]);\n#endif\n\n}\n\nvoid reset_timeout() {\n    // Wake up timerQ thread\n    uv_async_send(&wake_ev[0]);\n}\nint64_t get_next_key() {\n    spinlock_lock(&next_key_lock);\n    int64_t res = --next_key;\n    spinlock_unlock(&next_key_lock);\n    return res;\n}\n\n#define ACTORS_TABLE    ($WORD)0\n#define MSGS_TABLE      ($WORD)1\n#define MSG_QUEUE       ($WORD)2\n\n#define TIMER_QUEUE     0           // Special key in table MSG_QUEUE\n\n#ifdef ACTON_DB\nremote_db_t * db = NULL;\n#endif\n\n\n#if defined(_WIN32) || defined(_WIN64)\n// TODO: termios support in windows?\n#else\nstruct termios old_stdin_attr;\n#endif\n\n////////////////////////////////////////////////////////////////////////////////////////\n\n/* \n\nThe strangeness of the next 30 lines are caused by the unfortunate presence of Msg in __builtin__.act.\n\n-- This generates a stub of B_MsgD___init__ with wrong parameters, and its presence in the method table, so we define it here, but never use it.\n-- The out-commented version is how __init__ should really be defined\n-- The B_msgG_newXX function now inlines the proper __init__; it has to be renamed because of a generated and improper B_msgG_new.\n\n*/\n\nB_NoneType B_MsgD___init__ (B_Msg G_1p) {\n    // Must (and will) never be called!\n    return B_None;\n}\n\n/*\nvoid B_MsgD___init__(B_Msg m, $Actor to, $Cont cont, time_t baseline, $WORD value) {\n    m->$next = NULL;\n    m->$to = to;\n    m->$cont = cont;\n    m->$waiting = NULL;\n    m->$baseline = baseline;\n    m->value = value;\n    atomic_flag_clear(&m->$wait_lock);\n    m->$globkey = get_next_key();\n}\n*/\n\nB_Msg B_MsgG_newXX( $Actor to, $Cont cont, time_t baseline, $WORD value) {\n    B_Msg m = GC_malloc(sizeof(struct B_Msg));\n    m->$class = &B_MsgG_methods;\n    m->$next = NULL;\n    m->$to = to;\n    m->$cont = cont;\n    m->$waiting = NULL;\n    m->$baseline = baseline;\n    m->value = value;\n    atomic_flag_clear(&m->$wait_lock);\n    m->$globkey = get_next_key();\n    return m;\n}\n\n\n////////////////////////////////////////////////////////////////////////\n\nB_bool B_MsgD___bool__(B_Msg self) {\n  return B_True;\n}\n\nB_str B_MsgD___str__(B_Msg self) {\n  return $FORMAT(\"<B_Msg object at %p>\", self);\n}\n\nB_str B_MsgD___repr__(B_Msg self) {\n  return B_MsgD___str__(self);\n}\n\nvoid B_MsgD___serialize__(B_Msg self, $Serial$state state) {\n    $step_serialize(self->$to,state);\n    $step_serialize(self->$cont,state);\n    $val_serialize(ITEM_ID,&self->$baseline,state);\n    $step_serialize(self->value,state);\n}\n\n\nB_Msg B_MsgD___deserialize__(B_Msg res, $Serial$state state) {\n    if (!res) {\n        if (!state) {\n            res = GC_malloc(sizeof (struct B_Msg));\n            res->$class = &B_MsgG_methods;\n            return res;\n        }\n        res = $DNEW(B_Msg,state);\n    }\n    res->$next = NULL;\n    res->$to = $step_deserialize(state);\n    res->$cont = $step_deserialize(state);\n    res->$waiting = NULL;\n    res->$baseline = (time_t)$val_deserialize(state);\n    res->value = $step_deserialize(state);\n    atomic_flag_clear(&res->$wait_lock);\n    return res;\n}\n\n////////////////////////////////////////////////////////////////////////////////////////\n\nvoid $ActorD___init__($Actor a) {\n    a->$next = NULL;\n    a->B_Msg = NULL;\n    a->$outgoing = NULL;\n    a->$waitsfor = NULL;\n    a->$consume_hd = 0;\n    a->$catcher = NULL;\n    atomic_flag_clear(&a->B_Msg_lock);\n    a->$globkey = get_next_key();\n    a->$affinity = SHARED_RQ;\n    rtsd_printf(\"# New Actor %ld at %p of class %s\", a->$globkey, a, a->$class->$GCINFO);\n}\n\nB_bool $ActorD___bool__($Actor self) {\n  return B_True;\n}\n\nB_str $ActorD___str__($Actor self) {\n  return $FORMAT(\"<$Actor %ld %s at %p>\", self->$globkey, self->$class->$GCINFO, self);\n}\n\nB_NoneType $ActorD___resume__($Actor self) {\n  return B_None;\n}\n\nB_NoneType $ActorD___cleanup__($Actor self) {\n  return B_None;\n}\n\nvoid $ActorD___serialize__($Actor self, $Serial$state state) {\n    $step_serialize(self->$waitsfor,state);\n    $val_serialize(ITEM_ID,&self->$consume_hd,state);\n    $step_serialize(self->$catcher,state);\n}\n\n$Actor $ActorD___deserialize__($Actor res, $Serial$state state) {\n    if (!res) {\n        if (!state) {\n            res = GC_malloc(sizeof(struct $Actor));\n            res->$class = &$ActorG_methods;\n            return res;\n        }\n        res = $DNEW($Actor, state);\n    }\n    res->$next = NULL;\n    res->B_Msg = NULL;\n    res->$outgoing = NULL;\n    res->$waitsfor = $step_deserialize(state);\n    res->$consume_hd = (long)$val_deserialize(state);\n    res->$catcher = $step_deserialize(state);\n    atomic_flag_clear(&res->B_Msg_lock);\n    if (res->$affinity > 0)\n        res->$affinity = SHARED_RQ;\n    return res;\n}\n\n////////////////////////////////////////////////////////////////////////////////////////\n\nvoid $CatcherD___init__($Catcher c, $Cont cont) {\n    c->$next = NULL;\n    c->$cont = cont;\n    c->xval = NULL;\n}\n\nB_bool $CatcherD___bool__($Catcher self) {\n  return B_True;\n}\n\nB_str $CatcherD___str__($Catcher self) {\n  return $FORMAT(\"<$Catcher object at %p>\", self);\n}\n\nvoid $CatcherD___serialize__($Catcher self, $Serial$state state) {\n    $step_serialize(self->$next,state);\n    $step_serialize(self->$cont,state);\n    $step_serialize(self->xval,state);\n}\n\n$Catcher $CatcherD___deserialize__($Catcher self, $Serial$state state) {\n    $Catcher res = $DNEW($Catcher,state);\n    res->$next = $step_deserialize(state);\n    res->$cont = $step_deserialize(state);\n    res->xval = $step_deserialize(state);\n    return res;\n}\n///////////////////////////////////////////////////////////////////////////////////////\n\nvoid $ConstContD___init__($ConstCont $this, $WORD val, $Cont cont) {\n    $this->val = val;\n    $this->cont = cont;\n}\n\nB_bool $ConstContD___bool__($ConstCont self) {\n  return B_True;\n}\n\nB_str $ConstContD___str__($ConstCont self) {\n  return $FORMAT(\"<$ConstCont object at %p>\", self);\n}\n\nvoid $ConstContD___serialize__($ConstCont self, $Serial$state state) {\n    $step_serialize(self->val,state);\n    $step_serialize(self->cont,state);\n}\n\n$ConstCont $ConstContD___deserialize__($ConstCont self, $Serial$state state) {\n    $ConstCont res = $DNEW($ConstCont,state);\n    res->val = $step_deserialize(state);\n    res->cont = $step_deserialize(state);\n    return res;\n}\n\n$R $ConstContD___call__($ConstCont $this, $WORD _ignore) {\n    $Cont cont = $this->cont;\n    return cont->$class->__call__(cont, $this->val);\n}\n\n$Cont $CONSTCONT($WORD val, $Cont cont){\n    $ConstCont obj = GC_malloc(sizeof(struct $ConstCont));\n    obj->$class = &$ConstContG_methods;\n    $ConstContG_methods.__init__(obj, val, cont);\n    return ($Cont)obj;\n}\n\n////////////////////////////////////////////////////////////////////////////////////////\n\n/*\nstruct B_MsgG_class B_MsgG_methods = {\n    MSG_HEADER,\n    UNASSIGNED,\n    NULL,\n    NULL,\n    B_MsgD___serialize__,\n    B_MsgD___deserialize__,\n    B_MsgD___bool__,\n    B_MsgD___str__,\n    B_MsgD___str__\n};\n*/\n\nstruct $ActorG_class $ActorG_methods = {\n    ACTOR_HEADER,\n    UNASSIGNED,\n    NULL,\n    $ActorD___init__,\n    $ActorD___serialize__,\n    $ActorD___deserialize__,\n    $ActorD___bool__,\n    $ActorD___str__,\n    $ActorD___str__,\n    $ActorD___resume__,\n    $ActorD___cleanup__\n};\n\nstruct $CatcherG_class $CatcherG_methods = {\n    CATCHER_HEADER,\n    UNASSIGNED,\n    NULL,\n    $CatcherD___init__,\n    $CatcherD___serialize__,\n    $CatcherD___deserialize__,\n    $CatcherD___bool__,\n    $CatcherD___str__,\n    $CatcherD___str__\n};\n\nstruct $ConstContG_class $ConstContG_methods = {\n    \"$ConstCont\",\n    UNASSIGNED,\n    NULL,\n    $ConstContD___init__,\n    $ConstContD___serialize__,\n    $ConstContD___deserialize__,\n    $ConstContD___bool__,\n    $ConstContD___str__,\n    $ConstContD___str__,\n    $ConstContD___call__\n};\n\n////////////////////////////////////////////////////////////////////////////////////////\n\n\n#define MARK_RESULT         NULL\n#define MARK_EXCEPTION      ($Cont)1\n\n#define EXCEPTIONAL(m)      (m->$cont == MARK_EXCEPTION)\n#define FROZEN(m)           (m->$cont == MARK_RESULT || EXCEPTIONAL(m))\n\n// Atomically add actor \"a\" to the waiting list of messasge \"m\" if it is not frozen (and return true),\n// else immediately return false.\nbool ADD_waiting($Actor a, B_Msg m) {\n    bool did_add = false;\n\n    assert(m != NULL);\n\n    spinlock_lock(&m->$wait_lock);\n    if (!FROZEN(m)) {\n        a->$next = m->$waiting;\n        m->$waiting = a;\n        a->$waitsfor = m;\n        did_add = true;\n    }\n    spinlock_unlock(&m->$wait_lock);\n    return did_add;\n}\n\n// Atomically freeze message \"m\" using \"mark\", and return its list of waiting actors.\n$Actor FREEZE_waiting(B_Msg m, $Cont mark) {\n    spinlock_lock(&m->$wait_lock);\n    m->$cont = mark;\n    $Actor res = m->$waiting;\n    m->$waiting = NULL;\n    spinlock_unlock(&m->$wait_lock);\n    return res;\n}\n\n// Atomically enqueue timed message \"m\" onto the global timer-queue, at position\n// given by \"m->baseline\".\nbool ENQ_timed(B_Msg m) {\n    time_t m_baseline = m->$baseline;\n    bool new_head = false;\n    spinlock_lock(&timerQ_lock);\n    B_Msg x = timerQ;\n    if (x && x->$baseline <= m_baseline) {\n        B_Msg next = x->$next;\n        while (next && next->$baseline <= m_baseline) {\n            x = next;\n            next = x->$next;\n        }\n        x->$next = m;\n        m->$next = next;\n    } else {\n        timerQ = m;\n        m->$next = x;\n        new_head = true;\n    }\n    spinlock_unlock(&timerQ_lock);\n    return new_head;\n}\n\n// Atomically dequeue and return the first message from the global timer-queue if \n// its baseline is less or equal to \"now\", else return NULL.\nB_Msg DEQ_timed(time_t now) {\n    spinlock_lock(&timerQ_lock);\n    B_Msg res = timerQ;\n    if (res) {\n        if (res->$baseline <= now) {\n            timerQ = res->$next;\n            res->$next = NULL;\n        } else {\n            res = NULL;\n        }\n    }\n    spinlock_unlock(&timerQ_lock);\n    return res;\n}\n\n////////////////////////////////////////////////////////////////////////////////////////\nchar *RTAG_name($RTAG tag) {\n    switch (tag) {\n        case $RDONE: return \"RDONE\"; break;\n        case $RFAIL: return \"RFAIL\"; break;\n        case $RCONT: return \"RCONT\"; break;\n        case $RWAIT: return \"RWAIT\"; break;\n    }\n}\n////////////////////////////////////////////////////////////////////////////////////////\n$R $DoneD___call__($Cont $this, $WORD val) {\n    return $R_DONE(val);\n}\n\nB_bool $DoneD___bool__($Cont self) {\n  return B_True;\n}\n\nB_str $DoneD___str__($Cont self) {\n  return $FORMAT(\"<$Done object at %p>\", self);\n}\n\nvoid $Done__serialize__($Cont self, $Serial$state state) {\n  return;\n}\n\n$Cont $Done__deserialize__($Cont self, $Serial$state state) {\n  $Cont res = $DNEW($Cont,state);\n  res->$class = &$DoneG_methods;\n  return res;\n}\n\nstruct $ContG_class $DoneG_methods = {\n    \"$Done\",\n    UNASSIGNED,\n    NULL,\n    $ContD___init__,\n    $Done__serialize__,\n    $Done__deserialize__,\n    $DoneD___bool__,\n    $DoneD___str__,\n    $DoneD___str__,\n    $DoneD___call__\n};\nstruct $Cont $Done$instance = {\n    &$DoneG_methods\n};\n////////////////////////////////////////////////////////////////////////////////////////\n$R $FailD___call__($Cont $this, $WORD ex) {\n    return $R_FAIL(ex);\n}\n\nB_bool $FailD___bool__($Cont self) {\n  return B_True;\n}\n\nB_str $FailD___str__($Cont self) {\n  return $FORMAT(\"<$Fail object at %p>\", self);\n}\n\nvoid $Fail__serialize__($Cont self, $Serial$state state) {\n  return;\n}\n\n$Cont $Fail__deserialize__($Cont self, $Serial$state state) {\n  $Cont res = $DNEW($Cont,state);\n  res->$class = &$FailG_methods;\n  return res;\n}\n\nstruct $ContG_class $FailG_methods = {\n    \"$Fail\",\n    UNASSIGNED,\n    NULL,\n    $ContD___init__,\n    $Fail__serialize__,\n    $Fail__deserialize__,\n    $FailD___bool__,\n    $FailD___str__,\n    $FailD___str__,\n    $FailD___call__\n};\nstruct $Cont $Fail$instance = {\n    &$FailG_methods\n};\n////////////////////////////////////////////////////////////////////////////////////////\n$R $InitRootD___call__ ($Cont $this, $WORD val) {\n    typedef $R(*ROOT__init__t)($Actor, $Cont, B_Env);    // Assumed type of the ROOT actor's __init__ method\n    return ((ROOT__init__t)root_actor->$class->__init__)(root_actor, ($Cont)val, env_actor);\n}\n\nstruct $ContG_class $InitRootG_methods = {\n    \"$InitRoot\",\n    UNASSIGNED,\n    NULL,\n    $ContD___init__,\n    $ContD___serialize__,\n    $ContD___deserialize__,\n    $ContD___bool__,\n    $ContD___str__,\n    $ContD___str__,\n    $InitRootD___call__\n};\nstruct $Cont $InitRoot$cont = {\n    &$InitRootG_methods\n};\n////////////////////////////////////////////////////////////////////////////////////////\n\n#ifdef ACTON_DB\nvoid dummy_callback(queue_callback_args * qca) { }\nvoid queue_group_message_callback(queue_callback_args * qca) {\n//    rtsd_printf(\"   # There are messages in actor queues for group %d, subscriber %d, status %d\\n\", (int) qca->group_id, (int) qca->consumer_id, qca->status);\n}\n\nvoid create_db_queue(long key) {\n    int minority_status = 0;\n    while(!rts_exit) {\n        int ret = remote_create_queue_in_txn(MSG_QUEUE, ($WORD)key, &minority_status, NULL, db);\n        rtsd_printf(\"#### Create queue %ld returns %d\", key, ret);\n        if(ret == NO_QUORUM_ERR) {\n            sleep(3);\n            continue;\n        }\n        if(ret == 0 || ret == CLIENT_ERR_SUBSCRIPTION_EXISTS)\n            break;\n    }\n}\n\nvoid init_db_queue(long key) {\n    if (db)\n        create_db_queue(key);\n}\n\nvoid register_actor(long key) {\n    if (db) {\n        int status = add_actor_to_membership(key, db);\n        assert(status == 0);\n    }\n}\n#endif\n\nvoid PUSH_outgoing($Actor self, B_Msg m) {\n    m->$next = self->$outgoing;\n    self->$outgoing = m;\n}\n\nvoid PUSH_catcher($Actor a, $Catcher c) {\n    c->$next = a->$catcher;\n    a->$catcher = c;\n}\n\n$Catcher POP_catcher($Actor a) {\n    $Catcher c = a->$catcher;\n    if (c) {\n        a->$catcher = c->$next;\n        c->$next = NULL;\n    }\n    return c;\n}\n\nB_Msg $ASYNC($Actor to, $Cont cont) {\n    $Actor self = GET_SELF();\n    time_t baseline = 0;\n    B_Msg m = B_MsgG_newXX(to, cont, baseline, &$Done$instance);\n    if (self) {                                         // $ASYNC called by actor code\n        m->$baseline = self->B_Msg->$baseline;\n        PUSH_outgoing(self, m);\n    } else {                                            // $ASYNC called by the event loop\n        m->$baseline = current_time();\n        if (ENQ_msg(m, to)) {\n           int wtid = ENQ_ready(to);\n           wake_wt(wtid);\n        }\n    }\n    return m;\n}\n\nB_Msg $AFTER(B_float sec, $Cont cont) {\n    $Actor self = GET_SELF();\n    rtsd_printf(\"# AFTER by %ld\", self->$globkey);\n    time_t baseline = self->B_Msg->$baseline + sec->val * 1000000;\n    B_Msg m = B_MsgG_newXX(self, cont, baseline, &$Done$instance);\n    PUSH_outgoing(self, m);\n    return m;\n}\n\n$R $AWAIT($Cont cont, B_Msg m) {\n    return $R_WAIT(cont, m);\n}\n\n$R $PUSH_C($Cont cont) {\n    $Actor self = GET_SELF();\n    $Catcher c = $NEW($Catcher, cont);\n    PUSH_catcher(self, c);\n    return $R_CONT(cont, B_True);                   // True indicates the \"try\" branch\n}\n\nB_BaseException $POP_C() {\n    $Actor self = GET_SELF();\n    $Catcher c = POP_catcher(self);\n    B_BaseException ex = c->xval;\n    return ex;\n}\n\nvoid $DROP_C() {\n    $Actor self = GET_SELF();\n    POP_catcher(self);\n}\n\nJumpBuf $PUSH_BUF() {\n    WorkerCtx wctx = GET_WCTX();\n    assert(wctx != NULL);\n    JumpBuf current = wctx->jump_top;\n    JumpBuf new = (JumpBuf)GC_malloc(sizeof(struct JumpBuf));\n    new->prev = current;\n    wctx->jump_top = new;\n    return new;\n}\n\nB_BaseException $POP() {\n    WorkerCtx wctx = GET_WCTX();\n    assert(wctx != NULL);\n    JumpBuf current = wctx->jump_top;\n    assert(current != NULL);\n    //    assert(current->prev != NULL);\n    wctx->jump_top = current->prev;\n    return current->xval;\n}\n\nvoid $DROP() {\n    WorkerCtx wctx = GET_WCTX();\n    assert(wctx != NULL);\n    JumpBuf current = wctx->jump_top;\n    assert(current != NULL);\n    //   (current->prev != NULL);\n    wctx->jump_top = current->prev;\n}\n\nvoid $RAISE(B_BaseException e) {\n    WorkerCtx wctx = GET_WCTX();\n    JumpBuf jump = wctx->jump_top;\n    jump->xval = e;\n    longjmp(jump->buf, 1);\n}\n\n#ifdef ACTON_DB\nvoid create_all_actor_queues() {\n    for(snode_t * node = HEAD(db->actors); node!=NULL; node=NEXT(node)) {\n        create_db_queue((long) node->key);\n    }\n}\n\nint handle_status_and_schema_mismatch(int ret, int minority_status, long key)\n{\n    // If schema on any of the DB servers needs updating (based on minority_status), do that.\n    // If there was a quorum of healthy servers, we can go on after this, the operation succeeded.\n    // If schema was missing on a majority of servers, we'll in addition get NO_QUORUM_ERR, and\n    // we also need to retry the operation.\n    int queues_created = 0;\n    switch(minority_status) {\n        case DB_ERR_NO_QUEUE:\n        case DB_ERR_NO_CONSUMER:\n        case VAL_STATUS_ABORT_SCHEMA: {\n            // Schema errs:\n//            create_all_actor_queues();\n            create_db_queue(key);\n            queues_created = 1;\n            break;\n        }\n        case QUEUE_STATUS_READ_INCOMPLETE:\n        case QUEUE_STATUS_READ_COMPLETE:\n        case DB_ERR_DUPLICATE_CONSUMER:\n        case DB_ERR_QUEUE_COMPLETE:\n        case DB_ERR_DUPLICATE_QUEUE: {\n            // These are OK:\n            break;\n        }\n        default: { // DB_ERR_QUEUE_HEAD_INVALID, DB_ERR_NO_TABLE\n            assert(0);\n        }\n    }\n\n    if(ret == VAL_STATUS_ABORT_SCHEMA && !queues_created) {\n//        create_all_actor_queues();\n        create_db_queue(key);\n    }\n\n    if(ret == NO_QUORUM_ERR) {\n        sleep(3);\n        return 1;\n    }\n\n    return 0;\n}\n#endif\n\nvoid reverse_outgoing_queue($Actor self) {\n    B_Msg prev = NULL;\n    B_Msg m = self->$outgoing;\n    while (m) {\n        B_Msg next = m->$next;\n        m->$next = prev;\n        prev = m;\n        m = next;\n    }\n    self->$outgoing = prev;\n}\n\n#ifdef ACTON_DB\n// Send all buffered messages of the sender to global DB queues in a single txn, and retry it until success\n// Leaves no side effects in local queues if txns need to abort\n// Assumes the actor's outgoing queue has already been reversed in FIFO order\nvoid FLUSH_outgoing_db($Actor self, uuid_t *txnid) {\n    rtsd_printf(\"#### FLUSH_outgoing messages from %ld to DB queues\", self->$globkey);\n    B_Msg m = self->$outgoing;\n    while (m) {\n        long dest = (m->$baseline == self->B_Msg->$baseline)? m->$to->$globkey : 0;\n        int ret = 0, minority_status = 0;\n        while(!rts_exit) {\n            ret = remote_enqueue_in_txn(($WORD*)&m->$globkey, 1, NULL, 0, MSG_QUEUE, (WORD)dest, &minority_status, txnid, db);\n            if (dest) {\n                    rtsd_printf(\"   # enqueue msg %ld to queue %ld returns %d, minority_status=%d\", m->$globkey, dest, ret, minority_status);\n            } else {\n                    rtsd_printf(\"   # enqueue msg %ld to TIMER_QUEUE returns %d, minority_status=%d\", m->$globkey, ret, minority_status);\n            }\n            if(!handle_status_and_schema_mismatch(ret, minority_status, dest))\n                break;\n        }\n        m = m->$next;\n    }\n}\n#endif\n\n// Actually send all buffered messages of the sender, using internal queues only\n// Assumes the actor's outgoing queue has already been reversed in FIFO order\nvoid FLUSH_outgoing_local($Actor self) {\n    rtsd_printf(\"#### FLUSH_outgoing messages from %ld to RTS-internal queues\", self->$globkey);\n    B_Msg m = self->$outgoing;\n    self->$outgoing = NULL;\n    while (m) {\n        B_Msg next = m->$next;\n        m->$next = NULL;\n        long dest;\n        if (m->$baseline == self->B_Msg->$baseline) {\n            $Actor to = m->$to;\n            if (ENQ_msg(m, to)) {\n                ENQ_ready(to);\n            }\n            dest = to->$globkey;\n        } else {\n            if (ENQ_timed(m))\n                reset_timeout();\n            dest = 0;\n        }\n        m = next;\n    }\n}\n\ntime_t next_timeout() {\n    return timerQ ? timerQ->$baseline : 0;\n}\n\nvoid handle_timeout() {\n    time_t now = current_time();\n    B_Msg m = DEQ_timed(now);\n    if (m) {\n        rtsd_printf(\"## Dequeued timed msg with baseline %ld (now is %ld)\", m->$baseline, now);\n        if (ENQ_msg(m, m->$to)) {\n            int wtid = ENQ_ready(m->$to);\n            wake_wt(wtid);\n        }\n#ifdef ACTON_DB\n        if (db) {\n                int success = 0;\n                while(!success && !rts_exit)\n                {\n                uuid_t *txnid = remote_new_txn(db);\n                if(txnid == NULL)\n                    continue;\n                timer_consume_hd++;\n\n                long key = TIMER_QUEUE;\n                snode_t *m_start, *m_end;\n                int entries_read = 0, minority_status = 0;\n                int64_t read_head = -1;\n\n                int ret0 = remote_read_queue_in_txn(($WORD)db->local_rts_id, 0, 0, MSG_QUEUE, ($WORD)key, 1, &entries_read, &read_head, &m_start, &m_end, &minority_status, NULL, db);\n                rtsd_printf(\"   # dummy read msg from TIMER_QUEUE returns %d, entries read: %d\", ret0, entries_read);\n                if(handle_status_and_schema_mismatch(ret0, minority_status, key))\n                    continue;\n\n                int ret1 = remote_consume_queue_in_txn(($WORD)db->local_rts_id, 0, 0, MSG_QUEUE, ($WORD)key, read_head, &minority_status, txnid, db);\n                rtsd_printf(\"   # consume msg %ld from TIMER_QUEUE returns %d\", m->$globkey, ret1);\n                if(handle_status_and_schema_mismatch(ret1, minority_status, key))\n                    continue;\n\n                int ret2 = remote_enqueue_in_txn(($WORD*)&m->$globkey, 1, NULL, 0, MSG_QUEUE, (WORD)m->$to->$globkey, &minority_status, txnid, db);\n                rtsd_printf(\"   # (timed) enqueue msg %ld to queue %ld returns %d\", m->$globkey, m->$to->$globkey, ret2);\n                if(handle_status_and_schema_mismatch(ret2, minority_status, key))\n                    continue;\n\n                int ret3 = remote_commit_txn(txnid, &minority_status, db);\n                rtsd_printf(\"############## Commit returned %d, minority_status %d\", ret3, minority_status);\n                if(handle_status_and_schema_mismatch(ret3, minority_status, key))\n                    continue;\n                if(ret3 == VAL_STATUS_COMMIT)\n                    success = 1;\n                }\n        }\n#endif\n    }\n}\n\n////////////////////////////////////////////////////////////////////////////////////////\n\nB_dict globdict = NULL;\n\n$WORD try_globdict($WORD w) {\n    long key = (long)w;\n    $WORD obj = B_dictD_get(globdict, (B_Hashable)B_HashableD_intG_witness, toB_int(key), NULL);\n    return obj;\n}\n\n#ifdef ACTON_DB\nlong read_queued_msg(long key, int64_t *read_head) {\n    snode_t *m_start, *m_end;\n    int entries_read = 0, minority_status = 0, ret = 0;\n    \n    while(!rts_exit) {\n        ret = remote_read_queue_in_txn(($WORD)db->local_rts_id, 0, 0, MSG_QUEUE, ($WORD)key,\n                                           1, &entries_read, read_head, &m_start, &m_end, &minority_status, NULL, db);\n        rtsd_printf(\"   # read msg from queue %ld returns %d, entries read: %d, minority_status: %d\", key, ret, entries_read, minority_status);\n        if(!handle_status_and_schema_mismatch(ret, minority_status, key))\n            break;\n    }\n\n    if (!entries_read)\n        return 0;\n    db_row_t *r = (db_row_t*)m_start->value;\n    rtsd_printf(\"# r %p, key: %ld, cells: %p, columns: %p, no_cols: %d, blobsize: %d\", r, (long)r->key, r->cells, r->column_array, r->no_columns, r->last_blob_size);\n    return (long)r->column_array[0];\n}\n#endif\n\ntypedef struct BlobHd {           // C.f. $ROW\n    int class_id;\n    int blob_size;\n} BlobHd;\n\n$ROW extract_row($WORD *blob, size_t blob_size) {\n    int words_left = blob_size / sizeof($WORD);\n    if (words_left == 0)\n        return NULL;\n    BlobHd* head = (BlobHd*)blob;\n    $ROW fst = GC_malloc(sizeof(struct $ROW) + head->blob_size*sizeof($WORD));\n    $ROW row = fst;\n    while (!rts_exit) {\n        long size = 1 + head->blob_size;\n        memcpy(&row->class_id, blob, size*sizeof($WORD));\n        blob += size;\n        words_left -= size;\n        if (words_left == 0)\n            break;\n        head = (BlobHd*)blob;\n        row->next = GC_malloc(sizeof(struct $ROW) + head->blob_size*sizeof($WORD));\n        row = row->next;\n    };\n    row->next = NULL;\n    return fst;\n}\n\nvoid print_rows($ROW row) {\n    int n = 0;\n    while (row) {\n        char b[1024];\n        int len = 0;\n        for (int i = 0; i < row->blob_size; i++)\n            len += sprintf(b+len, \"%ld \", (long)row->blob[i]);\n        sprintf(b+len, \".\");\n\n        rtsd_printf(\"--- %2d: class_id %6d, blob_size: %3d, blob: %s\", n, row->class_id, row->blob_size, b);\n        n++;\n        row = row->next;\n    }\n}\n\nvoid print_msg(B_Msg m) {\n    rtsd_printf(\"==== Message %p\", m);\n    rtsd_printf(\"     next: %p\", m->$next);\n    rtsd_printf(\"     to: %p\", m->$to);\n    rtsd_printf(\"     cont: %p\", m->$cont);\n    rtsd_printf(\"     waiting: %p\", m->$waiting);\n    rtsd_printf(\"     baseline: %ld\", m->$baseline);\n    rtsd_printf(\"     value: %p\", m->value);\n    rtsd_printf(\"     globkey: %ld\", m->$globkey);\n}\n\nvoid print_actor($Actor a) {\n    rtsd_printf(\"==== Actor %p\", a);\n    rtsd_printf(\"     next: %p\", a->$next);\n    rtsd_printf(\"     msg: %p\", a->B_Msg);\n    rtsd_printf(\"     outgoing: %p\", a->$outgoing);\n    rtsd_printf(\"     waitsfor: %p\", a->$waitsfor);\n    rtsd_printf(\"     consume_hd: %ld\", (long)a->$consume_hd);\n    rtsd_printf(\"     catcher: %p\", a->$catcher);\n    rtsd_printf(\"     globkey: %ld\", a->$globkey);\n}\n\n#ifdef ACTON_DB\nvoid deserialize_system(snode_t *actors_start) {\n    rtsd_printf(\"Deserializing system\");\n    queue_callback * gqc = get_queue_callback(queue_group_message_callback);\n    int ret = 0,  minority_status = 0, no_items = 0;\n    rtsd_printf(\"### remote_subscribe_group(consumer_id = %d, group_id = %d)\\n\", (int) db->local_rts_id, (int) db->local_rts_id);\n    while(!rts_exit) {\n        ret = remote_subscribe_group((WORD) db->local_rts_id, NULL, NULL, (WORD) db->local_rts_id, gqc, &minority_status, db);\n        if(!handle_status_and_schema_mismatch(ret, minority_status, 0))\n            break;\n    }\n    snode_t *msgs_start, *msgs_end;\n    while(!rts_exit) {\n        ret = remote_read_full_table_in_txn(&msgs_start, &msgs_end, MSGS_TABLE, &no_items, &minority_status, NULL, db);\n        if(!handle_status_and_schema_mismatch(ret, minority_status, 0))\n            break;\n    }\n    \n    globdict = $NEW(B_dict,(B_Hashable)B_HashableD_intG_witness,NULL,NULL);\n\n    long min_key = 0;\n\n    rtsd_printf(\"#### Msg allocation:\");\n    for(snode_t * node = msgs_start; node!=NULL; node=NEXT(node)) {\n        db_row_t* r = (db_row_t*) node->value;\n        rtsd_printf(\"# r %p, key: %ld, cells: %p, columns: %p, no_cols: %d, blobsize: %d\", r, (long)r->key, r->cells, r->column_array, r->no_columns, r->last_blob_size);\n        long key = (long)r->key;\n        if (r->cells) {\n            db_row_t* r2 = (HEAD(r->cells))->value;\n            rtsd_printf(\"# r2 %p, key: %ld, cells: %p, columns: %p, no_cols: %d, blobsize: %d\", r2, (long)r2->key, r2->cells, r2->column_array, r2->no_columns, r2->last_blob_size);\n            BlobHd *head = (BlobHd*)r2->column_array[0];\n            B_Msg msg = (B_Msg)$GET_METHODS(head->class_id)->__deserialize__(NULL, NULL);\n            msg->$globkey = key;\n            B_dictD_setitem(globdict, (B_Hashable)B_HashableD_intG_witness, to$int(key), msg);\n            rtsd_printf(\"# Allocated Msg %p = %ld of class %s = %d\", msg, msg->$globkey, msg->$class->$GCINFO, msg->$class->$class_id);\n            if (key < min_key)\n                min_key = key;\n        }\n    }\n    rtsd_printf(\"#### Actor allocation:\");\n    for(snode_t * node = actors_start; node!=NULL; node=NEXT(node)) {\n        db_row_t* r = (db_row_t*) node->value;\n        rtsd_printf(\"# r %p, key: %ld, cells: %p, columns: %p, no_cols: %d, blobsize: %d\", r, (long)r->key, r->cells, r->column_array, r->no_columns, r->last_blob_size);\n        long key = (long)r->key;\n        if (r->cells) {\n            db_row_t* r2 = (HEAD(r->cells))->value;\n            rtsd_printf(\"# r2 %p, key: %ld, cells: %p, columns: %p, no_cols: %d, blobsize: %d\", r2, (long)r2->key, r2->cells, r2->column_array, r2->no_columns, r2->last_blob_size);\n            BlobHd *head = (BlobHd*)r2->column_array[0];\n            $Actor act = ($Actor)$GET_METHODS(head->class_id)->__deserialize__(NULL, NULL);\n            act->$globkey = key;\n            B_dictD_setitem(globdict, (B_Hashable)B_HashableD_intG_witness, to$int(key), act);\n            rtsd_printf(\"# Allocated Actor %p = %ld of class %s = %d\", act, act->$globkey, act->$class->$GCINFO, act->$class->$class_id);\n            if (key < min_key)\n                min_key = key;\n        }\n        register_actor(key);\n    }\n    next_key = min_key;\n\n    rtsd_printf(\"#### Msg contents:\");\n    for(snode_t * node = msgs_start; node!=NULL; node=NEXT(node)) {\n        db_row_t* r = (db_row_t*) node->value;\n        long key = (long)r->key;\n        if (r->cells) {\n            db_row_t* r2 = (HEAD(r->cells))->value;\n            $WORD *blob = ($WORD*)r2->column_array[0];\n            int blob_size = r2->last_blob_size;\n            $ROW row = extract_row(blob, blob_size);\n            B_Msg msg = (B_Msg)B_dictD_get(globdict, (B_Hashable)B_HashableD_intG_witness, to$int(key), NULL);\n            rtsd_printf(\"####### Deserializing msg %p = %ld of class %s = %d\", msg, msg->$globkey, msg->$class->$GCINFO, msg->$class->$class_id);\n            print_rows(row);\n            $glob_deserialize(($Serializable)msg, row, try_globdict);\n            print_msg(msg);\n        }\n    }\n\n    rtsd_printf(\"#### Actor contents:\");\n    for(snode_t * node = actors_start; node!=NULL; node=NEXT(node)) {\n        db_row_t* r = (db_row_t*) node->value;\n        long key = (long)r->key;\n        if (r->cells) {\n            db_row_t* r2 = (HEAD(r->cells))->value;\n            $WORD *blob = ($WORD*)r2->column_array[0];\n            int blob_size = r2->last_blob_size;\n            $ROW row = extract_row(blob, blob_size);\n            $Actor act = ($Actor)B_dictD_get(globdict, (B_Hashable)B_HashableD_intG_witness, to$int(key), NULL);\n            rtsd_printf(\"####### Deserializing actor %p = %ld of class %s = %d\", act, act->$globkey, act->$class->$GCINFO, act->$class->$class_id);\n            print_rows(row);\n            $glob_deserialize(($Serializable)act, row, try_globdict);\n\n            B_Msg m = act->$waitsfor;\n            if (m && !FROZEN(m)) {\n                ADD_waiting(act, m);\n                rtsd_printf(\"# Adding Actor %ld to wait for Msg %ld\", act->$globkey, m->$globkey);\n            }\n            else {\n                act->$waitsfor = NULL;\n            }\n\n            rtsd_printf(\"#### Reading msgs queue %ld contents:\", key);\n            int64_t prev_read_head = -1; //, prev_consume_head = -1;\n            int ret = 0, minority_status = 0;\n            while (!rts_exit) {\n                    long msg_key = read_queued_msg(key, &prev_read_head);\n                if (!msg_key)\n                    break;\n                m = B_dictD_get(globdict, (B_Hashable)B_HashableD_intG_witness, to$int(msg_key), NULL);\n                rtsd_printf(\"# Adding Msg %ld to Actor %ld\", m->$globkey, act->$globkey);\n                ENQ_msg(m, act);\n            }\n            if (act->B_Msg && !act->$waitsfor) {\n                ENQ_ready(act);\n                rtsd_printf(\"# Adding Actor %ld to the readyQ\", act->$globkey);\n            }\n            print_actor(act);\n        }\n    }\n\n    rtsd_printf(\"#### Actor resume:\");\n    for(snode_t * node = actors_start; node!=NULL; node=NEXT(node)) {\n        db_row_t* r = (db_row_t*) node->value;\n        long key = (long)r->key;\n        $Actor act = ($Actor)B_dictD_get(globdict, (B_Hashable)B_HashableD_intG_witness, to$int(key), NULL);\n        rtsd_printf(\"####### Resuming actor %p = %ld of class %s = %d\", act, act->$globkey, act->$class->$GCINFO, act->$class->$class_id);\n        act->$class->__resume__(act);\n    }\n\n    rtsd_printf(\"#### Reading timer queue contents:\");\n    time_t now = current_time();\n    int64_t prev_read_head = -1;\n    while(!rts_exit) {\n        long msg_key = read_queued_msg(TIMER_QUEUE, &prev_read_head);\n        if (!msg_key)\n            break;\n        B_Msg m = B_dictD_get(globdict, (B_Hashable)B_HashableD_intG_witness, to$int(msg_key), NULL);\n        if (m->$baseline < now)\n            m->$baseline = now;\n        rtsd_printf(\"# Adding Msg %ld to the timerQ\", m->$globkey);\n        ENQ_timed(m);\n    }\n\n    /*\n     * Actor IDs (-11 & -12) here chosen by fair dice roll... Haha, kidding.\n     * These values are aligned with the IDs allocated by get_next_key() when\n     * called in the BOOTSTRAP() function. The ID allocator next_key starts at\n     * -10, so -11 is the first key handed out and with the env actor is created\n     * first, it will get -11. Similarly for the root actor, which is assigned\n     * ID -12 (via the $NEWROOT call embedded in the external function $ROOT).\n     * These values must be kept in sync with next_key and the structure in\n     * the BOOTSTRAP() function!\n     */\n    env_actor  = (B_Env)B_dictD_get(globdict, (B_Hashable)B_HashableD_intG_witness, to$int(-11), NULL);\n    root_actor = ($Actor)B_dictD_get(globdict, (B_Hashable)B_HashableD_intG_witness, to$int(-12), NULL);\n    globdict = NULL;\n    rtsd_printf(\"System deserialized\");\n}\n#endif\n\n$WORD try_globkey($WORD obj) {\n    $SerializableG_class c = (($Serializable)obj)->$class;\n    if (c->$class_id == MSG_ID) {\n        long key = ((B_Msg)obj)->$globkey;\n        return ($WORD)key;\n    } else if (c->$class_id == ACTOR_ID || c->$superclass && c->$superclass->$class_id == ACTOR_ID) {\n        long key = (($Actor)obj)->$globkey;\n        return ($WORD)key;\n    }\n    return 0;\n}\n\nlong $total_rowsize($ROW r) {           // In words\n    long size = 0;\n    while (r) {\n        size += 1 + r->blob_size;       // Two ints == one $WORD\n        r = r->next;\n    }\n    return size;\n}\n\n#ifdef ACTON_DB\nvoid insert_row(long key, size_t total, $ROW row, $WORD table, uuid_t *txnid) {\n    $WORD column[2] = {($WORD)key, 0};\n    $WORD blob[total];\n    $WORD *p = blob;\n    int row_no = 0;\n    while (row) {\n        //printf(\"   # row %d: class %d, blob_size %d\\n\", row_no, row->class_id, row->blob_size);\n        long size = 1 + row->blob_size;\n        memcpy(p, &row->class_id, size*sizeof($WORD));\n        row_no++;\n        p += size;\n        row = row->next;\n    }\n    BlobHd *end = (BlobHd*)p;\n\n    char b[1024];\n    int len = 0;\n    for (int i = 0; i < total; i++)\n        len += sprintf(b+len, \"%lu \", (unsigned long)blob[i]);\n    sprintf(b+len, \".\");\n    rtsd_printf(\"## Built blob, size: %ld, blob: %s\", total, b);\n\n    //printf(\"\\n## Sanity check extract row:\\n\");\n    //$ROW row1 = extract_row(blob, total*sizeof($WORD));\n    //print_rows(row1);\n    int ret = 0, minority_status = 0;\n    while(!rts_exit) {\n        ret = remote_insert_in_txn(column, 2, 1, 1, blob, total*sizeof($WORD), table, &minority_status, txnid, db);\n        rtsd_printf(\"   # insert to table %ld, row %ld, returns %d\", (long)table, key, ret);\n        if(!handle_status_and_schema_mismatch(ret, minority_status, 0))\n            break;\n    }\n}\n\nvoid serialize_msg(B_Msg m, uuid_t *txnid) {\n    rtsd_printf(\"#### Serializing Msg %ld\", m->$globkey);\n    $ROW row = $glob_serialize(($Serializable)m, try_globkey);\n    print_rows(row);\n    insert_row(m->$globkey, $total_rowsize(row), row, MSGS_TABLE, txnid);\n}\n\nvoid serialize_actor($Actor a, uuid_t *txnid) {\n    rtsd_printf(\"#### Serializing Actor %ld\", a->$globkey);\n    $ROW row = $glob_serialize(($Serializable)a, try_globkey);\n    print_rows(row);\n    insert_row(a->$globkey, $total_rowsize(row), row, ACTORS_TABLE, txnid);\n\n    B_Msg out = a->$outgoing;\n    while (out) {\n        serialize_msg(out, txnid);\n        out = out->$next;\n    }\n}\n#endif\n\nvoid serialize_state_shortcut($Actor a) {\n#ifdef ACTON_DB\n    if (db) {\n            int success = 0, ret = 0, minority_status = 0;\n            while(!success && !rts_exit) {\n            uuid_t * txnid = remote_new_txn(db);\n            if(txnid == NULL)\n                continue;\n            serialize_actor(a, txnid);\n            ret = remote_commit_txn(txnid, &minority_status, db);\n            rtsd_printf(\"############## Commit returned %d, minority_status %d\", ret, minority_status);\n            if(handle_status_and_schema_mismatch(ret, minority_status, a->$globkey))\n                continue;\n            if(ret == VAL_STATUS_COMMIT)\n                success = 1;\n            }\n    }\n#endif\n}\n\nvoid BOOTSTRAP(int argc, char *argv[]) {\n    B_list args = B_listG_new(NULL,NULL);\n    B_SequenceD_list wit = B_SequenceD_listG_witness;\n    for (int i=0; i< argc; i++)\n        wit->$class->append(wit,args,to$str(argv[i]));\n\n    env_actor = B_EnvG_newactor(B_WorldCapG_new(), B_SysCapG_new(), args);\n    env_actor->nr_wthreads = toB_int(num_wthreads);\n\n    root_actor = $ROOT();                           // Assumed to return $NEWACTOR(X) for the selected root actor X\n    time_t now = current_time();\n    B_Msg m = B_MsgG_newXX(root_actor, &$InitRoot$cont, now, &$Done$instance);\n#ifdef ACTON_DB\n    if (db) {\n            int ret = 0, minority_status = 0;\n            while(!rts_exit) {\n                ret = remote_enqueue_in_txn(($WORD*)&m->$globkey, 1, NULL, 0, MSG_QUEUE, (WORD)root_actor->$globkey, &minority_status, NULL, db);\n                rtsd_printf(\"   # enqueue bootstrap msg %ld to root actor queue %ld returns %d, minority_status %d\", m->$globkey, root_actor->$globkey, ret, minority_status);\n                if(!handle_status_and_schema_mismatch(ret, minority_status, root_actor->$globkey))\n                    break;\n            }\n    }\n#endif\n    if (ENQ_msg(m, root_actor)) {\n        ENQ_ready(root_actor);\n    }\n\n}\n\nvoid save_actor_state($Actor current, B_Msg m) {\n#ifdef ACTON_DB\n            if (db) {\n                int success = 0;\n                reverse_outgoing_queue(current);\n                while(!success && !rts_exit) {\n                    uuid_t * txnid = remote_new_txn(db);\n                    if(txnid == NULL)\n                        continue;\n                    current->$consume_hd++;\n                    serialize_actor(current, txnid);\n                    FLUSH_outgoing_db(current, txnid);\n                    serialize_msg(current->B_Msg, txnid);\n\n                    long key = current->$globkey;\n                    snode_t *m_start, *m_end;\n                    int entries_read = 0, minority_status = 0;\n                    int64_t read_head = -1;\n\n                    int ret0 = remote_read_queue_in_txn(($WORD) db->local_rts_id, 0, 0, MSG_QUEUE, ($WORD)key, 1, &entries_read, &read_head, &m_start, &m_end, &minority_status, NULL, db);\n                    rtsd_printf(\"   # dummy read msg from queue %ld returns %d, entries read: %d\", key, ret0, entries_read);\n                    if(handle_status_and_schema_mismatch(ret0, minority_status, key))\n                        continue;\n\n                    int ret1 = remote_consume_queue_in_txn(($WORD) db->local_rts_id, 0, 0, MSG_QUEUE, ($WORD)key, read_head, &minority_status, txnid, db);\n                    rtsd_printf(\"   # consume msg %ld from queue %ld returns %d\", m->$globkey, key, ret1);\n                    if(handle_status_and_schema_mismatch(ret1, minority_status, key))\n                        continue;\n\n                    int ret2 = remote_commit_txn(txnid, &minority_status, db);\n                    rtsd_printf(\"############## Commit returned %d, minority_status %d\", ret2, minority_status);\n                    if(handle_status_and_schema_mismatch(ret2, minority_status, key))\n                        continue;\n                    if(ret2 == VAL_STATUS_COMMIT)\n                        success = 1;\n                }\n                FLUSH_outgoing_local(current);\n            } else {\n#endif\n                reverse_outgoing_queue(current);\n                FLUSH_outgoing_local(current);\n#ifdef ACTON_DB\n            }\n#endif\n}\n\n////////////////////////////////////////////////////////////////////////////////////////\n\nvoid main_stop_cb(uv_async_t *ev) {\n    uv_stop(uv_loops[0]);\n}\n\n\nvoid arm_timer_ev();\nvoid main_wake_cb(uv_async_t *ev) {\n    // Wäjky-päjky\n    arm_timer_ev();\n}\n\nvoid main_timer_cb(uv_timer_t *ev) {\n    handle_timeout();\n    arm_timer_ev();\n}\n\nvoid arm_timer_ev() {\n    time_t next_time = next_timeout();\n    if (next_time) {\n        time_t now = current_time();\n        long long int offset = (next_time - now) / 1000; // offset in milliseconds\n        // Negative offset means we missed to trigger in time. Set timeout to 0\n        // to directly run on next uv cycle.\n        if (offset < 0)\n            offset = 0;\n        int r = uv_timer_start(timer_ev, main_timer_cb, offset, 0);\n        if (r != 0) {\n            char errmsg[1024] = \"Unable to set timer: \";\n            uv_strerror_r(r, errmsg + strlen(errmsg), sizeof(errmsg)-strlen(errmsg));\n            log_fatal(errmsg);\n        }\n    } else {\n        int r = uv_timer_stop(timer_ev);\n        if (r != 0) {\n            char errmsg[1024] = \"Unable to stop timer: \";\n            uv_strerror_r(r, errmsg + strlen(errmsg), sizeof(errmsg)-strlen(errmsg));\n            log_fatal(errmsg);\n        }\n    }\n}\n\nvoid wt_stop_cb(uv_async_t *ev) {\n    WorkerCtx wctx = GET_WCTX();\n    uv_stop((uv_loop_t *)wctx->uv_loop);\n}\n\nvoid wt_wake_cb(uv_async_t *ev) {\n    // We just wake up the uv loop here if it is blocked waiting for IO, real\n    // work is run later when wt_work_cb is called as part of the \"check\" phase.\n}\n\nvoid wt_work_cb(uv_check_t *ev) {\n    WorkerCtx wctx = (WorkerCtx)ev->data;\n    assert(wctx->id >= 0 && wctx->id < 256);\n\n    uv_timespec64_t ts_start, ts1, ts2, ts3;\n    long long int runtime = 0;\n\n    uv_clock_gettime(UV_CLOCK_MONOTONIC, &ts_start);\n    while (true) {\n        if (rts_exit) {\n            return;\n        }\n        volatile $Actor current = DEQ_ready(wctx->id);\n        if (!current)\n            return;\n\n        wake_wt(SHARED_RQ);\n\n        SET_SELF(current);\n        volatile B_Msg m = current->B_Msg;\n        $Cont cont = m->$cont;\n        $WORD val = m->value;\n\n        uv_clock_gettime(UV_CLOCK_MONOTONIC, &ts1);\n        wt_stats[wctx->id].state = WT_Working;\n\n        $R r;\n        if (wctx->jump0 || $PUSH()) {                         // Normal path\n            if (!wctx->jump0) {\n                wctx->jump0 = wctx->jump_top;\n            }\n            rtsd_printf(\"## Running actor %ld : %s\", current->$globkey, current->$class->$GCINFO);\n            r = cont->$class->__call__(cont, val);\n\n            uv_clock_gettime(UV_CLOCK_MONOTONIC, &ts2);\n            long long int diff = (ts2.tv_sec * 1000000000 + ts2.tv_nsec) - (ts1.tv_sec * 1000000000 + ts1.tv_nsec);\n\n            wt_stats[wctx->id].conts_count++;\n            wt_stats[wctx->id].conts_sum += diff;\n\n            if      (diff < 100)              { wt_stats[wctx->id].conts_100ns++; }\n            else if (diff < 1   * 1000)       { wt_stats[wctx->id].conts_1us++; }\n            else if (diff < 10  * 1000)       { wt_stats[wctx->id].conts_10us++; }\n            else if (diff < 100 * 1000)       { wt_stats[wctx->id].conts_100us++; }\n            else if (diff < 1   * 1000000)    { wt_stats[wctx->id].conts_1ms++; }\n            else if (diff < 10  * 1000000)    { wt_stats[wctx->id].conts_10ms++; }\n            else if (diff < 100 * 1000000)    { wt_stats[wctx->id].conts_100ms++; }\n            else if (diff < 1   * 1000000000) { wt_stats[wctx->id].conts_1s++; }\n            else if (diff < (long long int)10  * 1000000000) { wt_stats[wctx->id].conts_10s++; }\n            else if (diff < (long long int)100 * 1000000000) { wt_stats[wctx->id].conts_100s++; }\n            else                              { wt_stats[wctx->id].conts_inf++; }\n        } else {                                        // Exceptional path\n            assert(wctx->jump0 != NULL);\n            assert(wctx->jump0->xval != NULL);\n            B_BaseException ex = wctx->jump0->xval;\n            rtsd_printf(\"## (%d) Actor %ld : %s longjmp exception: %s\", wctx->id, current->$globkey, current->$class->$GCINFO, ex->$class->$GCINFO);\n            r = $R_FAIL(ex);\n        }\n\n        switch (r.tag) {\n        case $RDONE: {\n            save_actor_state(current, m);\n            m->value = r.value;                             // m->value holds the message result,\n            $Actor b = FREEZE_waiting(m, MARK_RESULT);      // so mark this and stop further m->waiting additions\n            while (b) {\n                b->B_Msg->value = r.value;\n                b->$waitsfor = NULL;\n                $Actor c = b->$next;\n                ENQ_ready(b);\n                rtsd_printf(\"## Waking up actor %ld : %s\", b->$globkey, b->$class->$GCINFO);\n                b = c;\n            }\n            rtsd_printf(\"## DONE actor %ld : %s\", current->$globkey, current->$class->$GCINFO);\n            if (DEQ_msg(current)) {\n                ENQ_ready(current);\n            }\n            break;\n        }\n        case $RCONT: {\n            m->$cont = r.cont;\n            m->value = r.value;\n            rtsd_printf(\"## CONT actor %ld : %s\", current->$globkey, current->$class->$GCINFO);\n            ENQ_ready(current);\n            break;\n        }\n        case $RFAIL: {\n            $Catcher c = current->$catcher;\n            if (c) {                            // Normal exception handling\n                c->xval = (B_BaseException)r.value;\n                m->$cont = c->$cont;\n                m->value = B_False;             // False signals the exceptional branch\n                rtsd_printf(\"## FAIL/handle actor %ld : %s\", current->$globkey, current->$class->$GCINFO);\n                ENQ_ready(current);\n            } else {                            // An unhandled exception\n                save_actor_state(current, m);\n                B_BaseException ex = (B_BaseException)r.value;\n                m->value = r.value;                                 // m->value holds the raised exception,\n                $Actor b = FREEZE_waiting(m, MARK_EXCEPTION);       // so mark this and stop further m->waiting additions\n                // If any other actor is waiting for our result / exception,\n                // then we consider the exception handled and we can avoid\n                // printing the exception both in the originating actor and in\n                // the waiting actor. Thus we only print Unhandled exception in\n                // the originating actor when there is no one waiting for us.\n                if (!b)\n                    fprintf(stderr, \"Unhandled exception in actor: %s[%ld]:\\n  %s\\n\", unmangle_name(current->$class->$GCINFO), current->$globkey, fromB_str(ex->$class->__str__(ex)));\n                while (b) {\n                    b->B_Msg->$cont = &$Fail$instance;\n                    b->B_Msg->value = r.value;\n                    b->$waitsfor = NULL;\n                    $Actor c = b->$next;\n                    ENQ_ready(b);\n                    rtsd_printf(\"## Propagating exception to actor %ld : %s\", b->$globkey, b->$class->$GCINFO);\n                    b = c;\n                }\n                if (DEQ_msg(current)) {\n                    ENQ_ready(current);\n                }\n                rtsd_printf(\"## Done handling failed actor %ld : %s\", current->$globkey, current->$class->$GCINFO);\n            }\n            break;\n        }\n        case $RWAIT: {\n#ifdef ACTON_DB\n            if (db) {\n                int success = 0, ret = 0, minority_status = 0;\n                reverse_outgoing_queue(current);\n                while(!success && !rts_exit) {\n                    uuid_t * txnid = remote_new_txn(db);\n                    if(txnid == NULL)\n                        continue;\n                    serialize_actor(current, txnid);\n                    FLUSH_outgoing_db(current, txnid);\n                    serialize_msg(current->B_Msg, txnid);\n                    ret = remote_commit_txn(txnid, &minority_status, db);\n                    rtsd_printf(\"############## Commit returned %d, minority_status %d\", ret, minority_status);\n                    if(handle_status_and_schema_mismatch(ret, minority_status, current->$globkey))\n                        continue;\n                    if(ret == VAL_STATUS_COMMIT)\n                        success = 1;\n                }\n            } else {\n#endif\n                reverse_outgoing_queue(current);\n#ifdef ACTON_DB\n            }\n#endif\n            m->$cont = r.cont;\n            B_Msg x = (B_Msg)r.value;\n            assert(x != NULL);\n\n            bool added_waiting = ADD_waiting(current, x);\n            FLUSH_outgoing_local(current);\n\n            if (added_waiting) {      // x->cont is a proper $Cont: x is still being processed so current was added to x->waiting\n                rtsd_printf(\"## AWAIT actor %ld : %s\", current->$globkey, current->$class->$GCINFO);\n            } else if (EXCEPTIONAL(x)) {        // x->cont == MARK_EXCEPTION: x->value holds the raised exception, current is not in x->waiting\n                rtsd_printf(\"## AWAIT/fail actor %ld : %s\", current->$globkey, current->$class->$GCINFO);\n                m->$cont = &$Fail$instance;\n                m->value = x->value;\n                ENQ_ready(current);\n            } else {                            // x->cont == MARK_RESULT: x->value holds the final response, current is not in x->waiting\n                rtsd_printf(\"## AWAIT/wakeup actor %ld : %s\", current->$globkey, current->$class->$GCINFO);\n                m->value = x->value;\n                ENQ_ready(current);\n            }\n            break;\n        }\n        }\n        SET_SELF(NULL);\n\n        uv_clock_gettime(UV_CLOCK_MONOTONIC, &ts3);\n        long long int diff = (ts3.tv_sec * 1000000000 + ts3.tv_nsec) - (ts2.tv_sec * 1000000000 + ts2.tv_nsec);\n        wt_stats[wctx->id].bkeep_count++;\n        wt_stats[wctx->id].bkeep_sum += diff;\n\n        if      (diff < 100)              { wt_stats[wctx->id].bkeep_100ns++; }\n        else if (diff < 1   * 1000)       { wt_stats[wctx->id].bkeep_1us++; }\n        else if (diff < 10  * 1000)       { wt_stats[wctx->id].bkeep_10us++; }\n        else if (diff < 100 * 1000)       { wt_stats[wctx->id].bkeep_100us++; }\n        else if (diff < 1   * 1000000)    { wt_stats[wctx->id].bkeep_1ms++; }\n        else if (diff < 10  * 1000000)    { wt_stats[wctx->id].bkeep_10ms++; }\n        else if (diff < 100 * 1000000)    { wt_stats[wctx->id].bkeep_100ms++; }\n        else if (diff < 1   * 1000000000) { wt_stats[wctx->id].bkeep_1s++; }\n        else if (diff < (long long int)10  * 1000000000) { wt_stats[wctx->id].bkeep_10s++; }\n        else if (diff < (long long int)100 * 1000000000) { wt_stats[wctx->id].bkeep_100s++; }\n        else                              { wt_stats[wctx->id].bkeep_inf++; }\n\n        wt_stats[wctx->id].state = WT_Idle;\n\n        runtime = (ts3.tv_sec * 1000000000 + ts3.tv_nsec) - (ts_start.tv_sec * 1000000000 + ts_start.tv_nsec);\n        // run for max 20ms before yielding to IO\n        // NOTE: since we are not preemptive, a single long continuation can\n        // exceed this cap\n        if (runtime > 20*1000000)\n            break;\n    }\n\n    // if there's more work, wake up ourselves again to process more but\n    // interleave with some IO\n    uv_async_send(&wake_ev[wctx->id]);\n}\n\nvoid *main_loop(void *idx) {\n    WorkerCtx wctx = (WorkerCtx)GC_malloc(sizeof(struct WorkerCtx));\n    wctxs[(long)idx] = wctx;\n    wctx->id = (long)idx;\n    wctx->uv_loop = uv_loops[wctx->id];\n    wctx->jump_top = NULL;\n    wctx->jump0 = NULL;\n#ifdef ACTON_THREADS\n    pthread_setspecific(pkey_wctx, (void *)wctx);\n#endif\n\n    char tname[11]; // Enough for \"Worker XXX\\0\"\n    snprintf(tname, sizeof(tname), \"Worker %ld\", wctx->id);\n#ifdef ACTON_THREADS\n#if defined(IS_MACOS)\n    pthread_setname_np(tname);\n#else\n    pthread_setname_np(pthread_self(), tname);\n#endif\n#endif\n\n    uv_check_init(wctx->uv_loop, &work_ev[wctx->id]);\n    work_ev[wctx->id].data = wctx;\n    uv_check_start(&work_ev[wctx->id], (uv_check_cb)wt_work_cb);\n\n    wt_stats[wctx->id].state = WT_Idle;\n    int r = uv_run(wctx->uv_loop, UV_RUN_DEFAULT);\n    wt_stats[wctx->id].state = WT_NoExist;\n    rtsd_printf(\"Exiting...\");\n    return NULL;\n}\n\n////////////////////////////////////////////////////////////////////////////////////////\n\nvoid $register_rts () {\n  $register_force(MSG_ID,&B_MsgG_methods);\n  $register_force(ACTOR_ID,&$ActorG_methods);\n  $register_force(CATCHER_ID,&$CatcherG_methods);\n  $register_force(PROC_ID,&$procG_methods);\n  $register_force(ACTION_ID,&$actionG_methods);\n  $register_force(MUT_ID,&$mutG_methods);\n  $register_force(PURE_ID,&$pureG_methods);\n  $register_force(CONT_ID,&$ContG_methods);\n  $register_force(DONE_ID,&$DoneG_methods);\n  $register_force(CONSTCONT_ID,&$ConstContG_methods);\n  $register(&$DoneG_methods);\n  $register(&$InitRootG_methods);\n  $register(&B_EnvG_methods);\n}\n \n////////////////////////////////////////////////////////////////////////////////////////\n\n#ifdef ACTON_DB\nvoid dbc_ops_stats_to_json(yyjson_mut_doc *doc, yyjson_mut_val *j_mpoint, struct dbc_ops_stat *ops_stat) {\n    yyjson_mut_val *j_ops_stat = yyjson_mut_obj(doc);\n    yyjson_mut_obj_add_val(doc, j_mpoint, ops_stat->name, j_ops_stat);\n\n    yyjson_mut_obj_add_int(doc, j_ops_stat, \"called\",     ops_stat->called);\n    yyjson_mut_obj_add_int(doc, j_ops_stat, \"completed\",  ops_stat->completed);\n    yyjson_mut_obj_add_int(doc, j_ops_stat, \"success\",    ops_stat->success);\n    yyjson_mut_obj_add_int(doc, j_ops_stat, \"error\",      ops_stat->error);\n    yyjson_mut_obj_add_int(doc, j_ops_stat, \"no_quorum\",  ops_stat->no_quorum);\n    yyjson_mut_obj_add_int(doc, j_ops_stat, \"time_sum\",   ops_stat->time_sum);\n    yyjson_mut_obj_add_int(doc, j_ops_stat, \"time_100ns\", ops_stat->time_100ns);\n    yyjson_mut_obj_add_int(doc, j_ops_stat, \"time_1us\",   ops_stat->time_1us);\n    yyjson_mut_obj_add_int(doc, j_ops_stat, \"time_10us\",  ops_stat->time_10us);\n    yyjson_mut_obj_add_int(doc, j_ops_stat, \"time_100us\", ops_stat->time_100us);\n    yyjson_mut_obj_add_int(doc, j_ops_stat, \"time_1ms\",   ops_stat->time_1ms);\n    yyjson_mut_obj_add_int(doc, j_ops_stat, \"time_10ms\",  ops_stat->time_10ms);\n    yyjson_mut_obj_add_int(doc, j_ops_stat, \"time_100ms\", ops_stat->time_100ms);\n    yyjson_mut_obj_add_int(doc, j_ops_stat, \"time_1s\",    ops_stat->time_1s);\n    yyjson_mut_obj_add_int(doc, j_ops_stat, \"time_10s\",   ops_stat->time_10s);\n    yyjson_mut_obj_add_int(doc, j_ops_stat, \"time_100s\",  ops_stat->time_100s);\n    yyjson_mut_obj_add_int(doc, j_ops_stat, \"time_inf\",   ops_stat->time_inf);\n\n}\n#endif\n\n\nconst char* stats_to_json () {\n    yyjson_mut_doc *doc = yyjson_mut_doc_new(NULL);\n    yyjson_mut_val *root = yyjson_mut_obj(doc);\n    yyjson_mut_doc_set_root(doc, root);\n\n    yyjson_mut_obj_add_str(doc, root, \"name\", appname);\n\n    yyjson_mut_obj_add_int(doc, root, \"pid\", pid);\n\n    uv_timespec64_t ts;\n    if (uv_clock_gettime(UV_CLOCK_REALTIME, &ts) != 0) {\n        log_fatal(\"Unable to get precise time\");\n        return NULL;\n    }\n    struct tm tm;\n#ifdef _WIN32\n    errno_t result = localtime_s(&tm, &ts.tv_sec);\n    if (result != 0) {\n        char errmsg[1024] = \"Error getting time: \";\n        uv_strerror_r(errno, errmsg + strlen(errmsg), sizeof(errmsg) - strlen(errmsg));\n        log_warn(\"%s\", errmsg);\n        return NULL;\n    }\n#else\n    localtime_r(&ts.tv_sec, &tm);\n#endif\n    char dt[32];    // = \"YYYY-MM-ddTHH:mm:ss.SSS+0000\";\n    strftime(dt, 32, \"%Y-%m-%dT%H:%M:%S.000%z\", &tm);\n    sprintf(dt + 20, \"%03hu%s\", (unsigned short)(ts.tv_nsec / 1000000), dt + 23);\n\n    yyjson_mut_obj_add_str(doc, root, \"datetime\", dt);\n\n    // Worker threads\n    yyjson_mut_val *j_stat = yyjson_mut_obj(doc);\n    yyjson_mut_obj_add_val(doc, root, \"wt\", j_stat);\n    for (unsigned int i = 1; i < NUM_THREADS; i++) {\n        yyjson_mut_val *j_wt = yyjson_mut_obj(doc);\n        yyjson_mut_obj_add_val(doc, j_stat, wt_stats[i].key, j_wt);\n        yyjson_mut_obj_add_str(doc, j_wt, \"state\",       WT_State_name[wt_stats[i].state]);\n        yyjson_mut_obj_add_int(doc, j_wt, \"sleeps\",      wt_stats[i].sleeps);\n        yyjson_mut_obj_add_int(doc, j_wt, \"qlen\",        rqs[i].count);\n        yyjson_mut_obj_add_int(doc, j_wt, \"conts_count\", wt_stats[i].conts_count);\n        yyjson_mut_obj_add_int(doc, j_wt, \"conts_sum\",   wt_stats[i].conts_sum);\n        yyjson_mut_obj_add_int(doc, j_wt, \"conts_100ns\", wt_stats[i].conts_100ns);\n        yyjson_mut_obj_add_int(doc, j_wt, \"conts_1us\",   wt_stats[i].conts_1us);\n        yyjson_mut_obj_add_int(doc, j_wt, \"conts_10us\",  wt_stats[i].conts_10us);\n        yyjson_mut_obj_add_int(doc, j_wt, \"conts_100us\", wt_stats[i].conts_100us);\n        yyjson_mut_obj_add_int(doc, j_wt, \"conts_1ms\",   wt_stats[i].conts_1ms);\n        yyjson_mut_obj_add_int(doc, j_wt, \"conts_10ms\",  wt_stats[i].conts_10ms);\n        yyjson_mut_obj_add_int(doc, j_wt, \"conts_100ms\", wt_stats[i].conts_100ms);\n        yyjson_mut_obj_add_int(doc, j_wt, \"conts_1s\",    wt_stats[i].conts_1s);\n        yyjson_mut_obj_add_int(doc, j_wt, \"conts_10s\",   wt_stats[i].conts_10s);\n        yyjson_mut_obj_add_int(doc, j_wt, \"conts_100s\",  wt_stats[i].conts_100s);\n        yyjson_mut_obj_add_int(doc, j_wt, \"conts_inf\",   wt_stats[i].conts_inf);\n        yyjson_mut_obj_add_int(doc, j_wt, \"bkeep_count\", wt_stats[i].bkeep_count);\n        yyjson_mut_obj_add_int(doc, j_wt, \"bkeep_sum\",   wt_stats[i].bkeep_sum);\n        yyjson_mut_obj_add_int(doc, j_wt, \"bkeep_100ns\", wt_stats[i].bkeep_100ns);\n        yyjson_mut_obj_add_int(doc, j_wt, \"bkeep_1us\",   wt_stats[i].bkeep_1us);\n        yyjson_mut_obj_add_int(doc, j_wt, \"bkeep_10us\",  wt_stats[i].bkeep_10us);\n        yyjson_mut_obj_add_int(doc, j_wt, \"bkeep_100us\", wt_stats[i].bkeep_100us);\n        yyjson_mut_obj_add_int(doc, j_wt, \"bkeep_1ms\",   wt_stats[i].bkeep_1ms);\n        yyjson_mut_obj_add_int(doc, j_wt, \"bkeep_10ms\",  wt_stats[i].bkeep_10ms);\n        yyjson_mut_obj_add_int(doc, j_wt, \"bkeep_100ms\", wt_stats[i].bkeep_100ms);\n        yyjson_mut_obj_add_int(doc, j_wt, \"bkeep_1s\",    wt_stats[i].bkeep_1s);\n        yyjson_mut_obj_add_int(doc, j_wt, \"bkeep_10s\",   wt_stats[i].bkeep_10s);\n        yyjson_mut_obj_add_int(doc, j_wt, \"bkeep_100s\",  wt_stats[i].bkeep_100s);\n        yyjson_mut_obj_add_int(doc, j_wt, \"bkeep_inf\",   wt_stats[i].bkeep_inf);\n    }\n\n    // Database\n    yyjson_mut_val *j_dbc = yyjson_mut_obj(doc);\n    yyjson_mut_obj_add_val(doc, root, \"db_client\", j_dbc);\n\n#ifdef ACTON_DB\n#define X(ops_name) \\\n    dbc_ops_stats_to_json(doc, j_dbc, dbc_stats.ops_name);\nLIST_OF_DBC_OPS\n#undef X\n#endif\n\n    const char *json = yyjson_mut_write(doc, 0, NULL);\n    yyjson_mut_doc_free(doc);\n    return json;\n}\n\n#ifdef ACTON_DB\nconst char* db_membership_to_json () {\n    yyjson_mut_doc *doc = yyjson_mut_doc_new(NULL);\n    yyjson_mut_val *root = yyjson_mut_obj(doc);\n    yyjson_mut_doc_set_root(doc, root);\n\n    yyjson_mut_obj_add_str(doc, root, \"name\", appname);\n\n    yyjson_mut_obj_add_int(doc, root, \"pid\", pid);\n\n    uv_timespec64_t ts;\n    if (uv_clock_gettime(UV_CLOCK_REALTIME, &ts) != 0) {\n        log_fatal(\"Unable to get precise time\");\n        return NULL;\n    }\n    struct tm tm;\n    localtime_r(&ts.tv_sec, &tm);\n    char dt[32];    // = \"YYYY-MM-ddTHH:mm:ss.SSS+0000\";\n    strftime(dt, 32, \"%Y-%m-%dT%H:%M:%S.000%z\", &tm);\n    sprintf(dt + 20, \"%03hu%s\", (unsigned short)(ts.tv_nsec / 1000000), dt + 23);\n\n    yyjson_mut_obj_add_str(doc, root, \"datetime\", dt);\n\n    // Actual topology\n    yyjson_mut_val *j_nodes = yyjson_mut_obj(doc);\n    yyjson_mut_obj_add_val(doc, root, \"nodes\", j_nodes);\n    for (snode_t * crt = HEAD(db->servers); crt!=NULL; crt = NEXT(crt)) {\n        remote_server * rs = (remote_server *) crt->value;\n\n        yyjson_mut_val *j_node = yyjson_mut_obj(doc);\n        yyjson_mut_obj_add_val(doc, j_nodes, rs->id, j_node);\n        yyjson_mut_obj_add_str(doc, j_node, \"type\", \"DDB\");\n        yyjson_mut_obj_add_str(doc, j_node, \"hostname\", rs->hostname);\n        yyjson_mut_obj_add_str(doc, j_node, \"status\", RS_status_name[rs->status]);\n    }\n    for (snode_t * crt = HEAD(db->rtses); crt!=NULL; crt = NEXT(crt)) {\n        rts_descriptor * nd = (rts_descriptor *) crt->value;\n\n        yyjson_mut_val *j_node = yyjson_mut_obj(doc);\n        yyjson_mut_obj_add_val(doc, j_nodes, nd->id, j_node);\n        yyjson_mut_obj_add_str(doc, j_node, \"type\", \"RTS\");\n        yyjson_mut_obj_add_str(doc, j_node, \"hostname\", nd->hostname);\n        yyjson_mut_obj_add_str(doc, j_node, \"status\", RS_status_name[nd->status]);\n        yyjson_mut_obj_add_int(doc, j_node, \"local_rts_id\", nd->local_rts_id);\n        yyjson_mut_obj_add_int(doc, j_node, \"dc_id\", nd->dc_id);\n        yyjson_mut_obj_add_int(doc, j_node, \"rack_id\", nd->rack_id);\n    }\n\n    const char *json = yyjson_mut_write(doc, 0, NULL);\n    yyjson_mut_doc_free(doc);\n    return json;\n}\n#endif\n\nconst char* actors_to_json () {\n    yyjson_mut_doc *doc = yyjson_mut_doc_new(NULL);\n    yyjson_mut_val *root = yyjson_mut_obj(doc);\n    yyjson_mut_doc_set_root(doc, root);\n\n    yyjson_mut_obj_add_str(doc, root, \"name\", appname);\n\n    yyjson_mut_obj_add_int(doc, root, \"pid\", pid);\n\n    uv_timespec64_t ts;\n    if (uv_clock_gettime(UV_CLOCK_REALTIME, &ts) != 0) {\n        log_fatal(\"Unable to get precise time\");\n        return NULL;\n    }\n    struct tm tm;\n#ifdef _WIN32\n    errno_t result = localtime_s(&tm, &ts.tv_sec);\n    if (result != 0) {\n        char errmsg[1024] = \"Error getting time: \";\n        uv_strerror_r(errno, errmsg + strlen(errmsg), sizeof(errmsg) - strlen(errmsg));\n        log_warn(\"%s\", errmsg);\n        return NULL;\n    }\n#else\n    localtime_r(&ts.tv_sec, &tm);\n#endif\n    char dt[32];    // = \"YYYY-MM-ddTHH:mm:ss.SSS+0000\";\n    strftime(dt, 32, \"%Y-%m-%dT%H:%M:%S.000%z\", &tm);\n    sprintf(dt + 20, \"%03hu%s\", (unsigned short)(ts.tv_nsec / 1000000), dt + 23);\n\n    yyjson_mut_obj_add_str(doc, root, \"datetime\", dt);\n\n    // Actual topology\n    yyjson_mut_val *j_actors = yyjson_mut_obj(doc);\n    yyjson_mut_obj_add_val(doc, root, \"actors\", j_actors);\n#ifdef ACTON_DB\n    // TODO: implement similar option but local only\n    for(snode_t * crt = HEAD(db->actors); crt!=NULL; crt = NEXT(crt))\n    {\n        actor_descriptor * a = (actor_descriptor *) crt->value;\n\n        char a_id_str[21]; // up to length of unsigned long long\n        snprintf(a_id_str, 21, \"%lld\", (unsigned long long)a->actor_id);\n        yyjson_mut_val *act_id = yyjson_mut_strcpy(doc, a_id_str);\n\n        yyjson_mut_val *j_a = yyjson_mut_obj(doc);\n        yyjson_mut_obj_put(j_actors, act_id, j_a);\n        yyjson_mut_obj_add_str(doc, j_a, \"rts\", a->host_rts->id);\n        yyjson_mut_obj_add_str(doc, j_a, \"local\", a->is_local?\"yes\":\"no\");\n        yyjson_mut_obj_add_str(doc, j_a, \"status\", Actor_status_name[a->status]);\n    }\n#endif\n\n    const char *json = yyjson_mut_write(doc, 0, NULL);\n    yyjson_mut_doc_free(doc);\n    return json;\n}\n\n#ifdef ACTON_THREADS\nvoid *$mon_log_loop(void *period) {\n    log_info(\"Starting monitor log, with %ld second(s) period, to: %s\", (long)period, mon_log_path);\n\n#if defined(IS_MACOS)\n    pthread_setname_np(\"Monitor Log\");\n#else\n    pthread_setname_np(pthread_self(), \"Monitor Log\");\n#endif\n\n    FILE *f;\n    f = fopen(mon_log_path, \"w\");\n    if (!f) {\n        fprintf(stderr, \"ERROR: Unable to open RTS monitor log file (%s) for writing\\n\", mon_log_path);\n        exit(1);\n    }\n\n    while (1) {\n        const char *json = stats_to_json();\n        fputs(json, f);\n        fputs(\"\\n\", f);\n        if (rts_exit > 0) {\n            log_info(\"Shutting down RTS Monitor log thread.\");\n            break;\n        }\n\n        pthread_mutex_lock(&rts_exit_lock);\n        struct timespec ts;\n        clock_gettime(CLOCK_REALTIME, &ts);\n        ts.tv_sec += (long)period;\n        pthread_cond_timedwait(&rts_exit_signal, &rts_exit_lock, &ts);\n        pthread_mutex_unlock(&rts_exit_lock);\n    }\n    fclose(f);\n    return NULL;\n}\n\n\nvoid *$mon_socket_loop() {\n    log_info(\"Starting monitor socket listen on %s\", mon_socket_path);\n\n#if defined(IS_MACOS)\n    pthread_setname_np(\"Monitor Socket\");\n#else\n    pthread_setname_np(pthread_self(), \"Monitor Socket\");\n#endif\n\n#ifdef _WIN32\n    // TODO: implement on windows!?\n#else\n    int s, client_sock, len;\n    struct sockaddr_un local, remote;\n    char q[100];\n\n    if ((s = socket(AF_UNIX, SOCK_STREAM, 0)) == -1) {\n        fprintf(stderr, \"ERROR: Unable to create Monitor Socket\\n\");\n        exit(1);\n    }\n\n    local.sun_family = AF_UNIX;\n    strcpy(local.sun_path, mon_socket_path);\n    unlink(local.sun_path);\n    len = sizeof(local.sun_path) + sizeof(local.sun_family);\n    if (bind(s, (struct sockaddr *)&local, len) == -1) {\n        fprintf(stderr, \"ERROR: Unable to bind to Monitor Socket\\n\");\n        exit(1);\n    }\n\n    if (listen(s, 5) == -1) {\n        fprintf(stderr, \"ERROR: Unable to listen on Monitor Socket\\n\");\n        exit(1);\n    }\n\n    while (1) {\n        socklen_t t = sizeof(remote);\n        if ((client_sock = accept(s, (struct sockaddr *)&remote, &t)) == -1) {\n            perror(\"accept\");\n            exit(1);\n        }\n\n        int n;\n        char rbuf[64], *buf_base, *str;\n        ssize_t bytes_read;\n        size_t buf_used = 0, len;\n        while (1) {\n            bytes_read = recv(client_sock, &rbuf[buf_used], sizeof(rbuf) - buf_used, 0);\n            if (bytes_read <= 0)\n                break;\n            buf_used += bytes_read;\n\n            buf_base = rbuf;\n            while (1) {\n                if (buf_used == 0)\n                    break;\n                int r = netstring_read(&buf_base, &buf_used, &str, &len);\n                if (r != 0) {\n                    log_info(\"Mon socket: Error reading netstring: %d\", r);\n                    break;\n                }\n\n                if (memcmp(str, \"actors\", len) == 0) {\n                    const char *json = actors_to_json();\n                    char *send_buf = GC_malloc(strlen(json)+14); // 14 = maximum digits for length is 9 (999999999) + : + ; + \\0\n                    sprintf(send_buf, \"%lu:%s,\", strlen(json), json);\n                    int send_res = send(client_sock, send_buf, strlen(send_buf), 0);\n                    //free((void *)json);\n                    //free((void *)send_buf);\n                    if (send_res < 0) {\n                        log_info(\"Mon socket: Error sending\");\n                        break;\n                    }\n                }\n\n#ifdef ACTON_DB\n                if (memcmp(str, \"membership\", len) == 0) {\n                    const char *json = db_membership_to_json();\n                    char *send_buf = GC_malloc(strlen(json)+14); // 14 = maximum digits for length is 9 (999999999) + : + ; + \\0\n                    sprintf(send_buf, \"%lu:%s,\", strlen(json), json);\n                    int send_res = send(client_sock, send_buf, strlen(send_buf), 0);\n                    //free((void *)json);\n                    //free((void *)send_buf);\n                    if (send_res < 0) {\n                        log_info(\"Mon socket: Error sending\");\n                        break;\n                    }\n                }\n#endif\n\n                if (memcmp(str, \"WTS\", len) == 0) {\n                    const char *json = stats_to_json();\n                    char *send_buf = GC_malloc(strlen(json)+14); // 14 = maximum digits for length is 9 (999999999) + : + ; + \\0\n                    sprintf(send_buf, \"%lu:%s,\", strlen(json), json);\n                    int send_res = send(client_sock, send_buf, strlen(send_buf), 0);\n                    //free((void *)json);\n                    //free((void *)send_buf);\n                    if (send_res < 0) {\n                        log_info(\"Mon socket: Error sending\");\n                        break;\n                    }\n                }\n            }\n\n            if (buf_base > rbuf && buf_used > 0)\n                memmove(rbuf, buf_base, buf_used);\n        }\n\n        close(client_sock);\n    }\n    return NULL;\n#endif\n}\n#endif\n\nvoid rts_shutdown() {\n#if defined(_WIN32) || defined(_WIN64)\n#else\n    tcsetattr(STDIN_FILENO, TCSANOW, &old_stdin_attr);\n#endif\n\n    rts_exit = 1;\n    // 0 = main thread, rest is wthreads, thus +1\n    for (int i = 0; i < NUM_THREADS; i++) {\n        uv_async_send(&stop_ev[i]);\n    }\n}\n\n\n#ifndef _WIN32\nvoid print_trace() {\n    char pid_buf[30];\n    sprintf(pid_buf, \"%d\", getpid());\n    char name_buf[512];\n    name_buf[readlink(\"/proc/self/exe\", name_buf, 511)]=0;\n#ifdef __linux__\n    prctl(PR_SET_PTRACER, PR_SET_PTRACER_ANY, 0, 0, 0);\n#endif\n#ifdef __linux__\n    int child_pid = fork();\n    if (!child_pid) {\n        dup2(2, 1); // redirect output to stderr\n        execlp(\"lldb\", \"lldb\", \"-p\", pid_buf, \"--batch\", \"-o\", \"thread backtrace all\", \"-o\", \"exit\", \"--one-line-on-crash\", \"exit\", name_buf, NULL);\n        execlp(\"gdb\", \"gdb\", \"--quiet\", \"--batch\", \"-n\", \"-ex\", \"set confirm off\", \"-ex\", \"set pagination off\", \"-ex\", \"set debuginfod enabled off\", \"-ex\", \"thread\", \"-ex\", \"thread apply all backtrace full\", name_buf, pid_buf, NULL);\n        fprintf(stderr, \"Unable to get detailed backtrace using lldb or gdb\\n\");\n        exit(0); /* If lldb/gdb failed to start */\n    } else {\n        waitpid(child_pid, NULL, 0);\n    }\n#else\n    fprintf(stderr, \"Unable to get detailed backtrace on this platform\\n\");\n    exit(0); /* If lldb/gdb failed to start */\n#endif\n}\n\nvoid launch_debugger(int signum) {\n    fprintf(stderr, \"\\nERROR: This is the automatic debug launcher for %s\\n\", appname);\n    if (signum == SIGILL)\n        fprintf(stderr, \"\\nERROR: illegal instruction\\n\");\n    if (signum == SIGSEGV)\n        fprintf(stderr, \"\\nERROR: segmentation fault\\n\");\n    fprintf(stderr, \"Starting interactive debugger...\\n\");\n    char pid_buf[30];\n    sprintf(pid_buf, \"%d\", getpid());\n    char name_buf[512];\n    name_buf[readlink(\"/proc/self/exe\", name_buf, 511)]=0;\n#ifdef __linux__\n    prctl(PR_SET_PTRACER, PR_SET_PTRACER_ANY, 0, 0, 0);\n#endif\n    int child_pid = fork();\n    if (!child_pid) {\n        char findthread[40] = \"thread find \";\n        sprintf(findthread + strlen(findthread), \"%p\", (void *)pthread_self());\n        execlp(\"gdb\", \"gdb\", \"--quiet\", \"-n\", \"-ex\", \"set confirm off\", \"-ex\", findthread, name_buf, pid_buf, NULL);\n        fprintf(stderr, \"Unable to get detailed backtrace using lldb or gdb\");\n        exit(0); /* If lldb/gdb failed to start */\n    } else {\n        waitpid(child_pid, NULL, 0);\n        exit(0);\n    }\n}\n\nvoid crash_handler(int signum) {\n    fprintf(stderr, \"\\nERROR: This is the automatic crash handler for %s\\n\", appname);\n    if (signum == SIGILL)\n        fprintf(stderr, \"ERROR: illegal instruction\\n\");\n    if (signum == SIGSEGV)\n        fprintf(stderr, \"ERROR: segmentation fault\\n\");\n    fprintf(stderr, \"NOTE: this is likely a bug in acton, please report this at:\\n\");\n    fprintf(stderr, \"NOTE: https://github.com/actonlang/acton/issues/new\\n\");\n    fprintf(stderr, \"NOTE: include the backtrace printed below between -- 8< -- lines\\n\");\n\n    fprintf(stderr, \"\\n-- 8< --------- BACKTRACE --------------------\\n\");\n    print_trace();\n    fprintf(stderr, \"\\n-- 8< --------- END BACKTRACE ----------------\\n\");\n\n    if (signum == SIGILL)\n        fprintf(stderr, \"\\nERROR: illegal instruction\\n\");\n    if (signum == SIGSEGV)\n        fprintf(stderr, \"\\nERROR: segmentation fault\\n\");\n    fprintf(stderr, \"NOTE: this is likely a bug in acton, please report this at:\\n\");\n    fprintf(stderr, \"NOTE: https://github.com/actonlang/acton/issues/new\\n\");\n    fprintf(stderr, \"NOTE: include the backtrace printed above between -- 8< -- lines\\n\");\n\n    // Restore / uninstall signal handlers for SIGILL & SIGSEGV\n    sa_ill.sa_handler = NULL;\n    if (sigaction(SIGILL, &sa_ill, NULL) == -1) {\n        log_fatal(\"Failed to install signal handler for SIGILL: %s\", strerror(errno));\n        exit(1);\n    }\n    sa_segv.sa_handler = NULL;\n    if (sigaction(SIGSEGV, &sa_segv, NULL) == -1) {\n        log_fatal(\"Failed to install signal handler for SIGSEGV: %s\", strerror(errno));\n        exit(1);\n    }\n    // Kill ourselves with original signal sent to us\n    kill(getpid(), signum);\n}\n\nvoid sigint_handler(int signum) {\n    if (rts_exit == 0) {\n        log_info(\"Received SIGINT, shutting down gracefully...\");\n        rts_shutdown();\n    } else {\n        log_info(\"Received SIGINT during graceful shutdown, exiting immediately\");\n        exit(return_val);\n    }\n}\n\nvoid sigterm_handler(int signum) {\n    if (rts_exit == 0) {\n        log_info(\"Received SIGTERM, shutting down gracefully...\");\n        rts_shutdown();\n    } else {\n        log_info(\"Received SIGTERM during graceful shutdown, exiting immediately\");\n        exit(return_val);\n    }\n}\n#endif\n\nvoid check_uv_fatal(int status, char msg[]) {\n    if (status == 0)\n        return;\n\n    char errmsg[1024];\n    snprintf(errmsg, sizeof(errmsg), \"%s\", msg);\n    uv_strerror_r(status, errmsg+strlen(errmsg), sizeof(errmsg)-strlen(errmsg));\n    log_fatal(errmsg);\n    exit(1);\n}\n\n\nstruct option {\n    const char *name;\n    const char *arg_name;\n    int         val;\n    const char *desc;\n};\n\n\nvoid print_help(struct option *opt) {\n    printf(\"The Acton RTS reads and consumes the following options and arguments. All\\n\" \\\n           \"other parameters are passed verbatim to the Acton application. Option\\n\" \\\n           \"arguments can be passed either with --rts-option=ARG or --rts-option ARG\\n\\n\");\n    while (opt->name) {\n        char optarg[64];\n\n        sprintf(optarg, \"%s%s%s\", opt->name, opt->arg_name?\"=\":\"\", opt->arg_name?opt->arg_name:\"\");\n        printf(\"  --%-30s  %s\\n\", optarg, opt->desc);\n        opt++;\n    }\n    printf(\"\\n\");\n    exit(0);\n}\n\nvoid DaveNull () {}\n\nint main(int argc, char **argv) {\n    // Init garbage collector and suppress warnings\n    GC_INIT();\n    GC_set_warn_proc(DaveNull);\n    acton_init_alloc();\n    acton_replace_allocator(GC_malloc, GC_malloc_atomic, GC_realloc, GC_calloc, acton_noop_free, GC_strdup, GC_strndup);\n    int ddb_no_host = 0;\n    char **ddb_host = NULL;\n    char *rts_host = \"localhost\";\n    int ddb_port = 32000;\n    int ddb_replication = 3;\n    int rts_node_id = -1;\n    int rts_rack_id = -1;\n    int rts_dc_id = -1;\n    int new_argc = argc;\n    int cpu_pin;\n    uv_cpu_info_t* cpu_infos;\n    int num_cores;\n    if (uv_cpu_info(&cpu_infos, &num_cores) != 0) {\n        log_fatal(\"Unable to get CPU info\");\n        exit(1);\n    }\n    bool mon_on_exit = false;\n    bool auto_backtrace = true;\n    bool interactive_backtrace = false;\n    char *log_path = NULL;\n    FILE *logf = NULL;\n    bool log_stderr = false;\n\n    appname = argv[0];\n    pid = getpid();\n\n#ifndef _WIN32\n    // Do line buffered output\n    setlinebuf(stdout);\n\n    // Signal handling\n    sigfillset(&sa_abrt.sa_mask);\n    sigfillset(&sa_ill.sa_mask);\n    sigfillset(&sa_int.sa_mask);\n    sigfillset(&sa_pipe.sa_mask);\n    sigfillset(&sa_segv.sa_mask);\n    sigfillset(&sa_term.sa_mask);\n    sa_abrt.sa_flags = SA_RESTART;\n    sa_ill.sa_flags = SA_RESTART;\n    sa_int.sa_flags = SA_RESTART;\n    sa_pipe.sa_flags = SA_RESTART;\n    sa_segv.sa_flags = SA_RESTART;\n    sa_term.sa_flags = SA_RESTART;\n\n    // Ignore SIGPIPE, like we get if the other end talking to us on the Monitor\n    // socket (which is a Unix domain socket) goes away.\n    sa_pipe.sa_handler = SIG_IGN;\n    // Handle signals\n    sa_int.sa_handler = &sigint_handler;\n    sa_term.sa_handler = &sigterm_handler;\n\n    if (sigaction(SIGPIPE, &sa_pipe, NULL) == -1) {\n        log_fatal(\"Failed to install signal handler for SIGPIPE: %s\", strerror(errno));\n        exit(1);\n    }\n    if (sigaction(SIGINT, &sa_int, NULL) == -1) {\n        log_fatal(\"Failed to install signal handler for SIGINT: %s\", strerror(errno));\n        exit(1);\n    }\n    if (sigaction(SIGTERM, &sa_term, NULL) == -1) {\n        log_fatal(\"Failed to install signal handler for SIGTERM: %s\", strerror(errno));\n        exit(1);\n    }\n#endif\n\n#ifdef ACTON_THREADS\n    pthread_key_create(&self_key, NULL);\n    pthread_setspecific(self_key, NULL);\n    pthread_key_create(&pkey_wctx, NULL);\n#else\n    self_actor = NULL;\n#endif\n\n    log_set_quiet(true);\n    /*\n     * A note on argument parsing: The RTS has its own command line arguments,\n     * all prefixed with --rts-, which we need to parse out. The remainder of\n     * the arguments should be passed on to the Acton program, thus we need to\n     * fiddle with argv. To avoid modifying argv in place, we create a new argc\n     * and argv which we bootstrap the Acton program with. The special -- means\n     * to stop scanning for options, and any argument following it will be\n     * passed verbatim.\n     * For example (note the duplicate --rts-verbose)\n     *   Command line    : ./app foo --rts-verbose --bar --rts-verbose\n     *   Application sees: [./app, foo, --bar]\n     * Using -- to pass verbatim arguments:\n     *   Command line    : ./app foo --rts-verbose --bar -- --rts-verbose\n     *   Application sees: [./app, foo, --bar, --, --rts-verbose]\n     *\n     * We support both styles of providing an option argument, e.g.:\n     *    ./app --rts-wthreads 8\n     *    ./app --rts-wthreads=8\n     * Optional arguments aren't supported, an option either takes a required\n     * argument or it does not.\n     */\n    static struct option long_options[] = {\n        {\"rts-bt-dbg\", NULL, 'x', \"Interactively debug on SIGILL / SIGSEGV\"},\n        {\"rts-debug\", NULL, 'd', \"RTS debug, requires program to be compiled with --optimize Debug\"},\n        {\"rts-ddb-host\", \"HOST\", 'h', \"DDB hostname\"},\n        {\"rts-ddb-port\", \"PORT\", 'p', \"DDB port [32000]\"},\n        {\"rts-ddb-replication\", \"FACTOR\", 'r', \"DDB replication factor [3]\"},\n        {\"rts-node-id\", \"ID\", 'i', \"RTS node ID\"},\n        {\"rts-rack-id\", \"RACK\", 'R', \"RTS rack ID\"},\n        {\"rts-dc-id\", \"DATACENTER\", 'D', \"RTS datacenter ID\"},\n        {\"rts-host\", \"RTSHOST\", 'N', \"RTS hostname\"},\n        {\"rts-help\", NULL, 'H', \"Show this help\"},\n        {\"rts-mon-log-path\", \"PATH\", 'l', \"Path to RTS mon stats log\"},\n        {\"rts-mon-log-period\", \"PERIOD\", 'k', \"Periodicity of writing RTS mon stats log entry\"},\n        {\"rts-mon-on-exit\", NULL, 'E', \"Print RTS mon stats to stdout on exit\"},\n        {\"rts-mon-socket-path\", \"PATH\", 'm', \"Path to unix socket to expose RTS mon stats\"},\n        {\"rts-no-bt\", NULL, 'B', \"Disable automatic backtrace\"},\n        {\"rts-log-path\", \"PATH\", 'L', \"Path to RTS log\"},\n        {\"rts-log-stderr\", NULL, 's', \"Log to stderr in addition to log file\"},\n        {\"rts-verbose\", NULL, 'v', \"Enable verbose RTS output\"},\n        {\"rts-wthreads\", \"COUNT\", 'w', \"Number of worker threads [#CPU cores]\"},\n        {NULL, 0, 0}\n    };\n    // length of long_options array\n    #define OPTLEN (sizeof(long_options) / sizeof(long_options[0]) - 1)\n\n    int ch = 0;\n    // where we map current (i) argc position into new_argc\n    int new_argc_dst = 0;\n    // stop scanning once we've seen '--', passing the rest verbatim\n    int opt_scan = 1;\n    char **new_argv = acton_malloc((argc+1) * sizeof *new_argv);\n    char *optarg = NULL;\n    for (int i = 0; i < argc; i++) {\n        ch = 0;\n        optarg = NULL;\n        if (strcmp(argv[i], \"--\") == 0) opt_scan = 0;\n        if (opt_scan) {\n            for (int j=0; j<OPTLEN; j++) {\n                if (strlen(argv[i]) > 2\n                    && strncmp(argv[i]+2, long_options[j].name, strlen(long_options[j].name)) == 0) {\n                    // argv[i] matches one of our options!\n                    ch = long_options[j].val;\n                    new_argc--;\n                    if (long_options[j].arg_name) {\n                        if (strlen(argv[i]) > 2+strlen(long_options[j].name)\n                            && argv[i][2+strlen(long_options[j].name)] == '=') {\n                            // option argument is in --opt=arg style, so dig out\n                            optarg = (char *)argv[i]+(2+strlen(long_options[j].name)+1);\n                        } else {\n                            // argument has to be next in argv\n                            if (i+1 == argc) { // check we are not at end\n                                fprintf(stderr, \"ERROR: --%s requires an argument.\\n\", long_options[j].name);\n                                exit(1);\n                            }\n                            i++;\n                            optarg = argv[i];\n                            new_argc--;\n                        }\n                    }\n                    break;\n                }\n            }\n        }\n        if (!ch) { // Didn't identify one of our options, so pass through\n            new_argv[new_argc_dst++] = argv[i];\n            continue;\n        }\n\n        switch (ch) {\n            case 'B':\n                auto_backtrace = false;\n                break;\n            case 'd':\n                #ifndef DEV\n                fprintf(stderr, \"ERROR: RTS debug not supported.\\n\");\n                fprintf(stderr, \"HINT: Recompile this program using: acton --optimize Debug ...\\n\");\n                exit(1);\n                #endif\n                log_set_quiet(false);\n                if (log_get_level() > LOG_DEBUG)\n                    log_set_level(LOG_DEBUG);\n                rts_debug = 1;\n                // Enabling rts debug implies verbose RTS output too\n                rts_verbose = 10;\n                break;\n            case 'E':\n                mon_on_exit = true;\n                break;\n            case 'H':\n                print_help(long_options);\n                break;\n            case 'h':\n                ddb_host = acton_realloc(ddb_host, ++ddb_no_host * sizeof *ddb_host);\n                ddb_host[ddb_no_host-1] = optarg;\n                break;\n            case 'k':\n                mon_log_period = atoi(optarg);\n                break;\n            case 'L':\n                log_path = optarg;\n                break;\n            case 'l':\n                mon_log_path = optarg;\n                break;\n            case 'm':\n                mon_socket_path = optarg;\n                break;\n            case 'p':\n                ddb_port = atoi(optarg);\n                break;\n            case 'r':\n                ddb_replication = atoi(optarg);\n                break;\n            case 'i':\n                rts_node_id = atoi(optarg);\n                break;\n            case 'R':\n                rts_rack_id = atoi(optarg);\n                break;\n            case 'D':\n                rts_dc_id = atoi(optarg);\n                break;\n            case 'N':\n                rts_host = acton_strdup(optarg);\n                break;\n            case 's':\n                log_stderr = true;\n                break;\n            case 'v':\n                if (log_get_level() > LOG_INFO)\n                    log_set_level(LOG_INFO);\n                rts_verbose = 1;\n                break;\n            case 'w':\n                num_wthreads = atoi(optarg);\n                break;\n            case 'x':\n                interactive_backtrace = true;\n                break;\n        }\n    }\n    new_argv[new_argc] = NULL;\n\n#ifndef _WIN32\n    if (interactive_backtrace) {\n        sa_abrt.sa_handler = &launch_debugger;\n        sa_ill.sa_handler = &launch_debugger;\n        sa_segv.sa_handler = &launch_debugger;\n    } else {\n        sa_abrt.sa_handler = &crash_handler;\n        sa_ill.sa_handler = &crash_handler;\n        sa_segv.sa_handler = &crash_handler;\n    }\n#endif\n\n    if (auto_backtrace) {\n#ifndef _WIN32\n        if (sigaction(SIGABRT, &sa_abrt, NULL) == -1) {\n            log_fatal(\"Failed to install signal handler for SIGABRT: %s\", strerror(errno));\n            exit(1);\n        }\n        if (sigaction(SIGILL, &sa_ill, NULL) == -1) {\n            log_fatal(\"Failed to install signal handler for SIGILL: %s\", strerror(errno));\n            exit(1);\n        }\n        if (sigaction(SIGSEGV, &sa_segv, NULL) == -1) {\n            log_fatal(\"Failed to install signal handler for SIGSEGV: %s\", strerror(errno));\n            exit(1);\n        }\n#endif\n    }\n\n    if (log_path)\n        log_set_quiet(true);\n    if (rts_verbose || log_stderr)\n        log_set_quiet(false);\n\n    if (log_path) {\n        logf = fopen(log_path, \"w\");\n        if (!logf) {\n            fprintf(stderr, \"ERROR: Unable to open RTS log file (%s) for writing\\n\", log_path);\n            exit(1);\n        }\n        log_add_fp(logf, LOG_TRACE);\n    }\n\n#ifdef ACTON_THREADS\n    if (num_wthreads > MAX_WTHREADS) {\n        fprintf(stderr, \"ERROR: Maximum of %d worker threads supported.\\n\", MAX_WTHREADS);\n        fprintf(stderr, \"HINT: Run this program with fewer worker threads: %s --rts-wthreads %d\\n\", argv[0], MAX_WTHREADS);\n        exit(1);\n    }\n    // Determine number of worker threads, normally 1:1 per CPU thread / core\n    // For low core count systems we do a minimum of 4 worker threads\n    if (num_wthreads == -1 && num_cores < 4) { // auto, few CPU cores, so use 4 worker threads\n        num_wthreads = 4;\n        cpu_pin = 0;\n        log_info(\"Detected %ld CPUs: Using %ld worker threads, due to low CPU count. No CPU affinity used.\", num_cores, num_wthreads);\n    } else if (num_wthreads == -1) { // auto, many CPU cores, use 1 worker thread per CPU core\n        num_wthreads = num_cores;\n        cpu_pin = 1;\n        log_info(\"Detected %ld CPUs: Using %ld worker threads for 1:1 mapping with CPU affinity set.\", num_cores, num_wthreads);\n    } else {\n        cpu_pin = 0;\n        log_info(\"Detected %ld CPUs: Using %ld worker threads (manually set). No CPU affinity used.\", num_cores, num_wthreads);\n    }\n#else\n    log_info(\"Running without threads, main thread will perform all work\");\n    if (num_wthreads != -1) {\n        fprintf(stderr, \"ERROR: Threads disabled, provided --rts-wthreads argument has no effect.\\n\");\n        fprintf(stderr, \"HINT: You cannot compile with --no-threads and use --rts-wthreads at run time.\\n\");\n        exit(1);\n    }\n    num_wthreads = 0;\n#endif\n    // Zeroize statistics\n    for (int i=0; i < MAX_WTHREADS; i++) {\n        wt_stats[i].idx = i;\n        sprintf(wt_stats[i].key, \"%d\", i);\n        wt_stats[i].state = 0;\n        wt_stats[i].sleeps = 0;\n\n        wt_stats[i].conts_count = 0;\n        wt_stats[i].conts_sum = 0;\n        wt_stats[i].conts_100ns = 0;\n        wt_stats[i].conts_1us = 0;\n        wt_stats[i].conts_10us = 0;\n        wt_stats[i].conts_100us = 0;\n        wt_stats[i].conts_1ms = 0;\n        wt_stats[i].conts_10ms = 0;\n        wt_stats[i].conts_100ms = 0;\n        wt_stats[i].conts_1s = 0;\n        wt_stats[i].conts_10s = 0;\n        wt_stats[i].conts_100s = 0;\n        wt_stats[i].conts_inf = 0;\n\n        wt_stats[i].bkeep_count = 0;\n        wt_stats[i].bkeep_sum = 0;\n        wt_stats[i].bkeep_100ns = 0;\n        wt_stats[i].bkeep_1us = 0;\n        wt_stats[i].bkeep_10us = 0;\n        wt_stats[i].bkeep_100us = 0;\n        wt_stats[i].bkeep_1ms = 0;\n        wt_stats[i].bkeep_10ms = 0;\n        wt_stats[i].bkeep_100ms = 0;\n        wt_stats[i].bkeep_1s = 0;\n        wt_stats[i].bkeep_10s = 0;\n        wt_stats[i].bkeep_100s = 0;\n        wt_stats[i].bkeep_inf = 0;\n    }\n#ifdef ACTON_DB\n    init_dbc_stats();\n#endif\n    wctxs[0] = NULL;\n\n    for (int i=0; i <= num_wthreads; i++) {\n        uv_loop_t *loop = GC_malloc(sizeof(uv_loop_t));\n        check_uv_fatal(uv_loop_init(loop), \"Error initializing libuv loop: \");\n        uv_loops[i] = loop;\n\n        if (i == 0) {\n            check_uv_fatal(uv_async_init(uv_loops[i], &stop_ev[i], main_stop_cb), \"Error initializing libuv stop event: \");\n            check_uv_fatal(uv_async_init(uv_loops[i], &wake_ev[i], main_wake_cb), \"Error initializing libuv wake event: \");\n            check_uv_fatal(uv_async_send(&wake_ev[i]), \"Error sending initial work event: \");\n        } else {\n            check_uv_fatal(uv_async_init(uv_loops[i], &stop_ev[i], wt_stop_cb), \"Error initializing libuv stop event: \");\n            check_uv_fatal(uv_async_init(uv_loops[i], &wake_ev[i], wt_wake_cb), \"Error initializing libuv wake event: \");\n            check_uv_fatal(uv_async_send(&wake_ev[i]), \"Error sending initial work event: \");\n        }\n    }\n    aux_uv_loop = uv_loops[0];\n\n    for (int i=0; i < NUM_RQS; i++) {\n        rqs[i].head = NULL;\n        rqs[i].tail = NULL;\n        rqs[i].count = 0;\n    }\n\n#if defined(_WIN32) || defined(_WIN64)\n#else\n    tcgetattr(STDIN_FILENO, &old_stdin_attr);\n#endif\n\n    // RTS startup and module is static stuff, in particular module constants\n    // which are created during module init are static and do not need to be\n    // scanned. We therefore use the real_malloc (not GC_malloc) so that it is\n    // not traced by the GC, thus saving loads of work scanning this memory\n    // over and over.\n    acton_replace_allocator(malloc, malloc, realloc, calloc, acton_noop_free, strdup, strndup);\n    $register_builtin();\n    B___init__();\n    $register_rts();\n\n    WorkerCtx wctx = (WorkerCtx)GC_malloc(sizeof(struct WorkerCtx));\n    wctxs[0] = wctx;\n    wctx->id = 0;\n    wctx->uv_loop = uv_loops[wctx->id];\n    wctx->jump_top = NULL;\n    wctx->jump0 = NULL;\n#ifdef ACTON_THREADS\n    pthread_setspecific(pkey_wctx, (void *)wctx);\n#endif\n\n    $ROOTINIT();\n    acton_replace_allocator(GC_malloc, GC_malloc_atomic, GC_realloc, GC_calloc, acton_noop_free, GC_strdup, GC_strndup);\n\n    unsigned int seed;\n    if (ddb_host) {\n#ifdef ACTON_DB\n        GET_RANDSEED(&seed, 0);\n        log_info(\"Starting distributed RTS node, host=%s, node_id=%d, rack_id=%d, datacenter_id=%d\", rts_host, rts_node_id, rts_rack_id, rts_dc_id);\n        log_info(\"Using distributed database backend replication factor of %d\", ddb_replication);\n        char ** seed_hosts = (char **) malloc(ddb_no_host * sizeof(char *));\n        int * seed_ports = (int *) malloc(ddb_no_host * sizeof(int));\n\n        for (int i=0; i<ddb_no_host; i++) {\n            seed_hosts[i] = acton_strdup(ddb_host[i]);\n            seed_ports[i] = ddb_port;\n            char *colon = strchr(seed_hosts[i], ':');\n            if (colon) {\n                *colon = '\\0';\n                seed_ports[i] = atoi(colon + 1);\n            }\n            log_info(\"Using distributed database backend (DDB): %s:%d\", seed_hosts[i], seed_ports[i]);\n        }\n        db = get_remote_db(ddb_replication, rts_rack_id, rts_dc_id, rts_host, rts_node_id, ddb_no_host, seed_hosts, seed_ports, &seed);\n        free(seed_hosts);\n        free(seed_ports);\n#else\n        fprintf(stderr, \"ERROR: DB support disabled, unable to use provided DB backend host.\\n\");\n        fprintf(stderr, \"HINT: Enable DB backend: acton --db\\n\");\n        exit(1);\n#endif\n    }\n\n#ifdef ACTON_DB\n    if (db) {\n        snode_t* start_row = NULL, * end_row = NULL;\n        log_info(\"Checking for existing actor state in DDB.\");\n        int ret = 0,  minority_status = 0, no_items = 0;\n        while(!rts_exit) {\n            ret = remote_read_full_table_in_txn(&start_row, &end_row, ACTORS_TABLE, &no_items, &minority_status, NULL, db);\n            if(!handle_status_and_schema_mismatch(ret, minority_status, 0))\n                break;\n        }\n        if (no_items > 0) {\n            log_info(\"Found %d existing actors; Restoring actor state from DDB.\", no_items);\n            deserialize_system(start_row);\n            log_info(\"Actor state restored from DDB.\");\n        } else {\n            log_info(\"No previous state in DDB; Initializing database...\\n\");\n            queue_callback * gqc = get_queue_callback(queue_group_message_callback);\n            rtsd_printf(\"### initializing remote_subscribe_group(consumer_id = %d, group_id = %d)\\n\", (int) db->local_rts_id, (int) db->local_rts_id);\n            while(!rts_exit) {\n                ret = remote_subscribe_group((WORD) db->local_rts_id, NULL, NULL, (WORD) db->local_rts_id, gqc, &minority_status, db);\n                if(!handle_status_and_schema_mismatch(ret, minority_status, 0)) {\n                    break;\n                }\n            }\n            int indices[] = {0};\n            db_schema_t* db_schema = db_create_schema(NULL, 1, indices, 1, indices, 0, indices, 0);\n            create_db_queue(TIMER_QUEUE);\n            timer_consume_hd = 0;\n            BOOTSTRAP(new_argc, new_argv);\n            log_info(\"Database intialization complete.\");\n        }\n    } else {\n#endif\n        BOOTSTRAP(new_argc, new_argv);\n#ifdef ACTON_DB\n    }\n#endif\n\n#ifdef ACTON_THREADS\n    cpu_set_t cpu_set;\n\n    size_t primary_thread_stack_size;\n    size_t target_thread_stack_size;\n#if defined(IS_MACOS)\n    primary_thread_stack_size = pthread_get_stacksize_np(pthread_self());\n#else\n    pthread_attr_t attr;\n    pthread_getattr_np(pthread_self(), &attr);\n    pthread_attr_getstacksize(&attr, &primary_thread_stack_size);\n    pthread_attr_destroy(&attr);\n#endif\n    target_thread_stack_size = REQUIRED_STACK_SIZE > primary_thread_stack_size ? (size_t)REQUIRED_STACK_SIZE : primary_thread_stack_size;\n\n    if (primary_thread_stack_size < target_thread_stack_size)\n        log_warn(\"Current primary thread stack size: %u, required thread stack size: %u\", primary_thread_stack_size, target_thread_stack_size);\n\n    pthread_attr_t ss_attr;\n    size_t secondary_thread_stack_size = 0;\n    pthread_attr_init(&ss_attr);\n    pthread_attr_getstacksize(&ss_attr, &secondary_thread_stack_size);\n    if (secondary_thread_stack_size < target_thread_stack_size)\n    {\n        log_debug(\"Secondary thread stack size: %d, required thread stack size: %d\", secondary_thread_stack_size, target_thread_stack_size);\n        int err = pthread_attr_setstacksize(&ss_attr, target_thread_stack_size);\n        if (err)\n            log_error(\"pthread_attr_setstacksize failed: %s\", strerror(err));\n    }\n\n    // RTS Monitor Log\n    pthread_t mon_log_thread;\n    if (mon_log_path) {\n        pthread_create(&mon_log_thread, &ss_attr, $mon_log_loop, (void *)(intptr_t)mon_log_period);\n        if (cpu_pin) {\n            CPU_ZERO(&cpu_set);\n            CPU_SET(0, &cpu_set);\n            pthread_setaffinity_np(mon_log_thread, sizeof(cpu_set), &cpu_set);\n        }\n    }\n\n    // RTS Monitor Socket\n    pthread_t mon_socket_thread;\n    if (mon_socket_path) {\n        pthread_create(&mon_socket_thread, &ss_attr, $mon_socket_loop, NULL);\n        if (cpu_pin) {\n            CPU_ZERO(&cpu_set);\n            CPU_SET(0, &cpu_set);\n            pthread_setaffinity_np(mon_socket_thread, sizeof(cpu_set), &cpu_set);\n        }\n    }\n\n    // Start worker threads\n    pthread_t threads[MAX_WTHREADS];\n    // Worker threads run through 0..num_wthreads where 0 is the main thread,\n    // thus we need to start 1..num_wthreads. Only need to keep track of\n    // branches we start.\n    for (int idx = 1; idx <= num_wthreads; idx++) {\n        pthread_create(&threads[idx-1], &ss_attr, main_loop, (void*)(intptr_t)idx);\n        // Index start at 1 and we pin wthreads to CPU 1...n\n        // We use CPU 0 for misc threads, like IO / mon etc\n        if (cpu_pin) {\n            CPU_ZERO(&cpu_set);\n            CPU_SET(idx, &cpu_set);\n            //pthread_setaffinity_np(threads[idx-1], sizeof(cpu_set), &cpu_set);\n        }\n    }\n\n    pthread_attr_destroy(&ss_attr);\n#endif\n\n\n    uv_check_init(aux_uv_loop, &work_ev[wctx->id]);\n    work_ev[wctx->id].data = wctx;\n    uv_check_start(&work_ev[wctx->id], (uv_check_cb)wt_work_cb);\n\n    // Run the timer queue and keep track of other periodic tasks\n    timer_ev = GC_malloc(sizeof(uv_timer_t));\n    uv_timer_init(aux_uv_loop, timer_ev);\n    uv_timer_start(timer_ev, main_timer_cb, 0, 0);\n\n#ifdef ACTON_THREADS\n    // Set affinity for main thread\n    if (cpu_pin) {\n        CPU_ZERO(&cpu_set);\n        CPU_SET(0, &cpu_set);\n        pthread_setaffinity_np(pthread_self(), sizeof(cpu_set), &cpu_set);\n    }\n#endif\n\n    // Run the uv loop for the main thread\n    wt_stats[0].state = WT_Idle;\n    int r = uv_run(aux_uv_loop, UV_RUN_DEFAULT);\n    wt_stats[0].state = WT_NoExist;\n\n    // -- SHUTDOWN --\n\n#ifdef ACTON_THREADS\n    // Join threads\n    for (int idx = 1; idx <= num_wthreads; idx++) {\n        pthread_join(threads[idx-1], NULL);\n    }\n\n    pthread_mutex_lock(&rts_exit_lock);\n    pthread_cond_broadcast(&rts_exit_signal);\n    pthread_mutex_unlock(&rts_exit_lock);\n\n    if (mon_log_path) {\n        pthread_join(mon_log_thread, NULL);\n    }\n\n    if (mon_on_exit) {\n        const char *stats_json = stats_to_json();\n        printf(\"%s\\n\", stats_json);\n    }\n#endif\n\n    if (logf) {\n        fclose(logf);\n    }\n\n    return return_val;\n}\n"
  },
  {
    "path": "base/rts/rts.h",
    "content": "#pragma once\n\n#include <stdio.h>\n#include <stdlib.h>\n#include <stdint.h>\n#include <stdbool.h>\n#include <time.h>\n#ifdef ACTON_THREADS\n#include <pthread.h>\n#endif\n#include <setjmp.h>\n\n#include <uv.h>\n\n#ifdef __gnu_linux__\n    #define IS_GNU_LINUX\n#elif  __APPLE__ && __MACH__\n    #define IS_MACOS\n#endif\n\n#include \"common.h\"\n#include \"../builtin/builtin.h\"\n\n#define MSGQ 2\n#ifdef ACTON_THREADS\n#define MAX_WTHREADS 256\n#define NUM_RQS (MAX_WTHREADS+1)\n// The shared RQ is the top-most readyQ\n#define SHARED_RQ (NUM_RQS-1)\n#else\n#define MAX_WTHREADS 1\n#define NUM_RQS 1\n#define SHARED_RQ 0\n#endif\n\n#define REQUIRED_STACK_SIZE 8*1024*1024\n\n#include \"q.h\"\n\nextern long num_wthreads;\nstruct wt_stat {\n    unsigned int idx;          // worker thread index\n    char key[10];              // thread index as string for convenience\n    unsigned int state;        // current thread state\n    unsigned long long sleeps; // number of times thread slept\n\n    // Executing actor continuations is the primary work of the RTS, we measure\n    // the execution time of each and count to buckets to get a rough idea of\n    // how long it takes\n    unsigned long long conts_count; // number of executed continuations\n    unsigned long long conts_sum;   // nanoseconds spent running continuations\n    unsigned long long conts_100ns; // bucket for <100ns\n    unsigned long long conts_1us;   // bucket for <1us\n    unsigned long long conts_10us;  // bucket for <10us\n    unsigned long long conts_100us; // bucket for <100us\n    unsigned long long conts_1ms;   // bucket for <1ms\n    unsigned long long conts_10ms;  // bucket for <10ms\n    unsigned long long conts_100ms; // bucket for <100ms\n    unsigned long long conts_1s;     // bucket for <1s\n    unsigned long long conts_10s;    // bucket for <10s\n    unsigned long long conts_100s;   // bucket for <100s\n    unsigned long long conts_inf;   // bucket for <+Inf\n    // Bookkeeping is all the other work we do not directly related to running\n    // actor continuations, like taking locks, committing information, talking\n    // to the database etc\n    unsigned long long bkeep_count; // number of bookkeeping rounds\n    unsigned long long bkeep_sum;   // nanoseconds spent bookkeeping\n    unsigned long long bkeep_100ns; // bucket for <100ns\n    unsigned long long bkeep_1us;   // bucket for <1us\n    unsigned long long bkeep_10us;  // bucket for <10us\n    unsigned long long bkeep_100us; // bucket for <100us\n    unsigned long long bkeep_1ms;   // bucket for <1ms\n    unsigned long long bkeep_10ms;  // bucket for <10ms\n    unsigned long long bkeep_100ms; // bucket for <100ms\n    unsigned long long bkeep_1s;     // bucket for <1s\n    unsigned long long bkeep_10s;    // bucket for <10s\n    unsigned long long bkeep_100s;   // bucket for <100s\n    unsigned long long bkeep_inf;   // bucket for <+Inf\n    // Avoid cache trashing by aligning on cache line size (64!?)\n    char padding[56];\n};\nextern struct wt_stat wt_stats[MAX_WTHREADS];\n\nstruct B_Msg;\nstruct $ConstCont;\n\n#ifdef ACTON_THREADS\nextern pthread_key_t pkey_wctx;\nextern pthread_key_t pkey_uv_loop;\n\nextern pthread_key_t self_key;\nextern pthread_mutex_t sleep_lock;\nextern pthread_cond_t work_to_do;\n\n#define GET_WCTX() (WorkerCtx)pthread_getspecific(pkey_wctx)\n#else\n#define GET_WCTX() wctxs[0]\n#endif\n\nextern $Actor self_actor;\n\ntypedef struct B_Msg *B_Msg;\ntypedef struct $ConstCont *$ConstCont;\n\nextern struct B_MsgG_class B_MsgG_methods;\nextern struct $ActorG_class $ActorG_methods;\nextern struct $CatcherG_class $CatcherG_methods;\nextern struct $ContG_class $DoneG_methods;\nextern struct $ContG_class $FailG_methods;\nextern struct $ConstContG_class $ConstContG_methods;\n\n#define MSG_HEADER              \"Msg\"\n#define ACTOR_HEADER            \"Actor\"\n#define CATCHER_HEADER          \"Catcher\"\n#define CLOS_HEADER             \"Clos\"\n\n/*       Defined in builtin/__builtin__.h with wrong type for __init__\nstruct B_MsgG_class {\n    char *$GCINFO;\n    int $class_id;\n    $SuperG_class $superclass;\n    void (*__init__)(B_Msg, $Actor, $Cont, time_t, $WORD);\n    void (*__serialize__)(B_Msg, $Serial$state);\n    B_Msg (*__deserialize__)(B_Msg, $Serial$state);\n    B_bool (*__bool__)(B_Msg);\n    B_str (*__str__)(B_Msg);\n    B_str (*__repr__)(B_Msg);\n};\n*/\nstruct B_Msg {\n    struct B_MsgG_class *$class;\n    B_Msg $next;\n    $Actor $to;\n    $Cont $cont;\n    $Actor $waiting;\n    time_t $baseline;\n    $Lock $wait_lock;\n    $WORD value;\n    $long $globkey;\n};\n\nstruct $ActorG_class {\n    char *$GCINFO;\n    int $class_id;\n    $SuperG_class $superclass;\n    void (*__init__)($Actor);\n    void (*__serialize__)($Actor, $Serial$state);\n    $Actor (*__deserialize__)($Actor, $Serial$state);\n    B_bool (*__bool__)($Actor);\n    B_str (*__str__)($Actor);\n    B_str (*__repr__)($Actor);\n    B_NoneType (*__resume__)($Actor);\n    B_NoneType (*__cleanup__)($Actor);\n};\nstruct $Actor {\n    struct $ActorG_class *$class;\n    $Actor $next;\n    B_Msg B_Msg;\n    B_Msg B_Msg_tail;\n    $Lock B_Msg_lock;\n    $int64 $affinity;\n    B_Msg $outgoing;\n    B_Msg $waitsfor;\n    $int64 $consume_hd;\n    $Catcher $catcher;\n    $long $globkey;\n};\n\nstruct $CatcherG_class {\n    char *$GCINFO;\n    int $class_id;\n    $SuperG_class $superclass;\n    void (*__init__)($Catcher, $Cont);\n    void (*__serialize__)($Catcher, $Serial$state);\n    $Catcher (*__deserialize__)($Catcher, $Serial$state);\n    B_bool (*__bool__)($Catcher);\n    B_str (*__str__)($Catcher);\n    B_str (*__repr__)($Catcher);\n};\nstruct $Catcher {\n    struct $CatcherG_class *$class;\n    $Catcher $next;\n    $Cont $cont;\n    B_BaseException xval;\n};\n\n\nstruct $ConstContG_class {\n    char *$GCINFO;\n    int $class_id;\n    $SuperG_class $superclass;\n    void (*__init__)($ConstCont, $WORD, $Cont);\n    void (*__serialize__)($ConstCont, $Serial$state);\n    $ConstCont (*__deserialize__)($ConstCont, $Serial$state);\n    B_bool (*__bool__)($ConstCont);\n    B_str (*__str__)($ConstCont);\n    B_str (*__repr__)($ConstCont);\n    $R (*__call__)($ConstCont, $WORD);\n};\nstruct $ConstCont {\n    struct $ConstContG_class *$class;\n    $WORD val;\n    $Cont cont;\n};\n$Cont $CONSTCONT($WORD, $Cont);\n\nB_Msg $ASYNC($Actor, $Cont);\nB_Msg $AFTER(B_float, $Cont);\n$R $AWAIT($Cont, B_Msg);\n\nvoid init_db_queue(long);\nvoid register_actor(long key);\nvoid serialize_state_shortcut($Actor);\n\n#ifdef ACTON_DB\n#define INIT_DB_QUEUE(key) init_db_queue(key)\n#define REGISTER_ACTOR(key) register_actor(key)\n#else\n#define INIT_DB_QUEUE(key)\n#define REGISTER_ACTOR(key)\n#endif\n\n#define $NEWACTOR($T)       ({ $T $t = GC_malloc(sizeof(struct $T)); \\\n                               $t->$class = &$T ## G_methods; \\\n                               $ActorG_methods.__init__(($Actor)$t); \\\n                               $t->$affinity = SHARED_RQ; \\\n                               INIT_DB_QUEUE($t->$globkey); \\\n                               REGISTER_ACTOR($t->$globkey); \\\n                               $t; })\n\n#define $InstallFinalizer(act, fn) GC_register_finalizer(act, fn, NULL, NULL, NULL)\n\n#ifdef ACTON_THREADS\n#define GET_SELF() ($Actor)pthread_getspecific(self_key)\n#define SET_SELF(a) pthread_setspecific(self_key, (void *)a)\n#define GET_WTID() (int)pthread_getspecific(pkey_wtid);\n#else\n#define GET_SELF() self_actor\n#define SET_SELF(a) self_actor = a\n#define GET_WTID() 0\n#endif\n\n$R $PUSH_C($Cont);\nB_BaseException $POP_C();\nvoid $DROP_C();\n#define $PUSHF_C $PUSH_C\n#define $RAISE_C $RAISE\n\n/*\nstruct JumpBuf;\ntypedef struct JumpBuf *JumpBuf;\nstruct JumpBuf {\n    jmp_buf buf;\n    B_BaseException xval;\n    JumpBuf prev;\n};\n*/\n\nstruct WorkerCtx;\ntypedef struct WorkerCtx *WorkerCtx;\nstruct WorkerCtx {\n    long id;\n    uv_loop_t *uv_loop;\n    volatile JumpBuf jump_top;\n    volatile JumpBuf jump0;\n};\nextern WorkerCtx wctxs[MAX_WTHREADS];\n\nJumpBuf $PUSH_BUF();\nB_BaseException $POP();\nvoid $DROP();\nvoid $RAISE(B_BaseException e);\n#define $PUSH()             (!setjmp($PUSH_BUF()->buf))\n#define $PUSHF $PUSH\n\nextern pid_t pid;\nextern B_Msg timerQ;\n\nvoid wake_wt(int wtid);\n\ntime_t current_time();\ntime_t next_timeout();\nvoid handle_timeout();\nvoid rts_shutdown();\n\nvoid pin_actor_affinity();\nvoid set_actor_affinity(int wthread_id);\n\n//typedef B_int B_Env;\n\nvoid $Actor$serialize($Actor, B_NoneType);\nvoid $Actor$deserialize($Actor, B_NoneType);\nB_NoneType $ActorD___cleanup__($Actor);\n\nB_bool B_MsgD___bool__(B_Msg self); \nB_str B_MsgD___str__(B_Msg self);\nB_str B_MsgD___repr__(B_Msg self); \nvoid B_MsgD___serialize__(B_Msg self, $Serial$state state);\nB_Msg B_MsgD___deserialize__(B_Msg res, $Serial$state state);\n\n\n$ROW $serialize_rts();\nvoid $deserialize_rts($ROW);\n\n\nvoid $register_rts();\n"
  },
  {
    "path": "base/src/__builtin__.act",
    "content": "# Copyright (C) 2019-2021 Data Ductus AB\n#\n# Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:\n#\n# 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.\n#\n# 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.\n#\n# 3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission.\n#\n# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS \"AS IS\" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n#\n\n## Built-in types ##################################################################################\n\nclass value:\n    __init__ : () -> None\n    def __bool__(self) -> bool:\n        NotImplemented\n    def __str__(self) -> str:\n        NotImplemented\n    def __repr__(self) -> str:\n        NotImplemented\n\nclass object (value):\n    pass\n\nclass atom (value):\n    pass\n\nclass int (atom):\n    def __init__(self, val: atom, base: ?int) -> None:\n        NotImplemented\n\nclass i32 (atom):\n    def __init__(self, val: atom, base: ?int) -> None:\n        NotImplemented\n\nclass i16 (atom):\n    def __init__(self, val: atom, base: ?int) -> None:\n        NotImplemented\n\nclass i8 (atom):\n    def __init__(self, val: atom, base: ?int) -> None:\n        NotImplemented\n\nclass u64 (atom):\n    def __init__(self, val: atom, base: ?int) -> None:\n        NotImplemented\n\nclass u32 (atom):\n    def __init__(self, val: atom, base: ?int) -> None:\n        NotImplemented\n\nclass u16 (atom):\n    def __init__(self, val: atom, base: ?int) -> None:\n        NotImplemented\n\nclass u8 (atom):\n    def __init__(self, val: atom, base: ?int) -> None:\n        NotImplemented\n\nclass u1 (atom):\n    def __init__(self, val: atom, base: ?int) -> None:\n        NotImplemented\n\nclass bigint (atom):\n    def __init__(self, val: atom, base: ?int) -> None:\n        NotImplemented\n\nclass float (atom):\n    def __init__(self, val: atom) -> None:\n        NotImplemented\n\nclass bool (atom):\n    def __init__(self, val: value) -> None:\n        NotImplemented\n\nclass slice(value):\n    def __init__(self, start: ?int, stop: ?int, step: ?int) -> None:\n        NotImplemented\n\nclass list[A] (object):\n    def __init__(self, val: ?Iterable[A]) -> None:\n        NotImplemented\n    def clear(self) -> None:\n        NotImplemented\n    def copy(self) -> list[A]:\n        NotImplemented\n    def extend(self, other: list[A]) -> None:\n        NotImplemented\n    def pop(self, n :?int) -> A:\n        NotImplemented\n    # TODO: improve this, to like A(Eq) or something\n    # generic type B should really just be A(Eq), but I don't think we can say\n    # that A is a generic type without constraints in one place and then adds\n    # constraints in another, so using B is a bit of a workaround.\n    def index[B(Eq)](self, val: B, start: int=0, stop: ?int) -> int:\n        \"\"\"Return the index of the first occurrence of val in the list\n\n        The optional arguments start and stop are interpreted as in slice\n        notation and will limit the search to the slice of the list from start\n        to stop.\n\n        Raises KeyError if val is not in the searched list / slice.\n        \"\"\"\n        NotImplemented\n    def count[B(Eq)](self, val: B) -> int:\n        NotImplemented\n\nclass Iterator[A] (object):\n    __next__     : () -> A\n    \n\nprotocol Iterable[A]:\n    __iter__     : () -> Iterator[A]\n\nclass range(Iterator[int]):\n    \"\"\"Return an object that produces a sequence of integers from start\n    (inclusive) to stop (exclusive) in step sizes as specified by the step\n    argument, which is 1 per default. It is possible to call with just a single\n    argument like `range(j)` where `j` is then interpreted to be the stop\n    argument with an implicit default start of 0.\n\n    - `range(0, 3, 1)` produces [0, 1, 2]\n    - `range(0, 3)` produces [0, 1, 2]\n    - `range(3)` produces [0, 1, 2]\n    \"\"\"\n    def __init__(self, start: int, stop: ?int, step: int=1) -> None:\n        NotImplemented\n    def __next__(self)->int:\n        NotImplemented\n\nclass str (atom):\n    def __init__     (self, val: ?value) -> None:\n        NotImplemented\n    def capitalize   (self) -> str:\n        NotImplemented\n    def center       (self, width: int, fillchar: ?str) -> str:\n        NotImplemented\n    def count        (self, sub: str, start: ?int, end: ?int) -> int:\n        NotImplemented\n    def encode       (self) -> bytes:\n        NotImplemented\n    def endswith     (self, suffix: str, start: ?int, end: ?int) -> bool:\n        NotImplemented\n    def expandtabs   (self, tabsize: ?int) -> str:\n        NotImplemented\n    def find         (self, sub: str, start: ?int, end: ?int) -> int:\n        NotImplemented\n    def index        (self, sub: str, start: ?int, end: ?int) -> int:\n        NotImplemented\n    def isalnum      (self) -> bool:\n        NotImplemented\n    def isalpha      (self) -> bool:\n        NotImplemented\n    def isascii      (self) -> bool:\n        NotImplemented\n    def isdecimal    (self) -> bool:\n        NotImplemented\n    def islower      (self) -> bool:\n        NotImplemented\n    def isprintable  (self) -> bool:\n        NotImplemented\n    def isspace      (self) -> bool:\n        NotImplemented\n    def istitle      (self) -> bool:\n        NotImplemented\n    def isupper      (self) -> bool:\n        NotImplemented\n    def join         (self, iterable: Iterable[str]) -> str:\n        NotImplemented\n    def ljust        (self, width: int, fillchar: ?str) -> str:\n        NotImplemented\n    def lower        (self) -> str:\n        NotImplemented\n    def lstrip       (self, chars: ?str) -> str:\n        NotImplemented\n    def partition    (self, sep: str) -> (str,str,str):\n        NotImplemented\n    def replace      (self, old: str, new: str, count: ?int) -> str:\n        NotImplemented\n    def rfind        (self, sub: str, start: ?int, end: ?int) -> int:\n        NotImplemented\n    def rindex       (self, sub: str, start: ?int, end: ?int) -> int:\n        NotImplemented\n    def rjust        (self, width: int, fillchar: ?str) -> str:\n        NotImplemented\n    def rpartition   (self, sep: str) -> (str,str,str):\n        NotImplemented\n    def rstrip       (self, chars: ?str) -> str:\n        NotImplemented\n    def split        (self, sep: str, maxsplit: ?int) -> list[str]:\n        NotImplemented\n    def splitlines   (self, keepends: ?bool) -> list[str]:\n        NotImplemented\n    def startswith   (self, prefix: str, start: ?int, end: ?int) -> bool:\n        NotImplemented\n    def strip        (self, chars: ?str) -> str:\n        NotImplemented\n    def upper        (self) -> str:\n        NotImplemented\n    def zfill        (self, width: int) -> str:\n        NotImplemented\n\nclass bytes (value):\n    def __init__     (self, iterable: Iterable[int]) -> None:\n        NotImplemented\n    def capitalize   (self) -> bytes:\n        NotImplemented\n    def center       (self, width: int, fillchar: ?bytes) -> bytes:\n        NotImplemented\n    def count        (self, sub: bytes, start: ?int, end: ?int) -> int:\n        NotImplemented\n    def decode       (self) -> str:\n        NotImplemented\n    def endswith     (self, suffix: bytes, start: ?int, end: ?int) -> bool:\n        NotImplemented\n    def expandtabs   (self, tabsize: ?int) -> bytes:\n        NotImplemented\n    def find         (self, sub: bytes, start: ?int, end: ?int) -> int:\n        NotImplemented\n    @staticmethod\n    def from_hex     (s: str) -> bytes:\n        NotImplemented\n    def hex          (self) -> str:\n        NotImplemented\n    def index        (self, sub: bytes, start: ?int, end: ?int) -> int:\n        NotImplemented\n    def isalnum      (self) -> bool:\n        NotImplemented\n    def isalpha      (self) -> bool:\n        NotImplemented\n    def isascii      (self) -> bool:\n        NotImplemented\n    def isdigit      (self) -> bool:\n        NotImplemented\n    def islower      (self) -> bool:\n        NotImplemented\n    def isspace      (self) -> bool:\n        NotImplemented\n    def istitle      (self) -> bool:\n        NotImplemented\n    def isupper      (self) -> bool:\n        NotImplemented\n    def join         (self, iterable: Iterable[bytes]) -> bytes:\n        NotImplemented\n    def ljust        (self, width: int, fillchar: ?bytes) -> bytes:\n        NotImplemented\n    def lower        (self) -> bytes:\n        NotImplemented\n    def lstrip       (self, chars: ?bytes) -> bytes:\n        NotImplemented\n    def partition    (self, sep: bytes) -> (bytes,bytes,bytes):\n        NotImplemented\n    def replace      (self, old: bytes, new: bytes, count: ?int) -> bytes:\n        NotImplemented\n    def rfind        (self, sub: bytes, start: ?int, end: ?int) -> int:\n        NotImplemented\n    def rindex       (self, sub: bytes, start: ?int, end: ?int) -> int:\n        NotImplemented\n    def rjust        (self, width: int, fillchar: ?bytes) -> bytes:\n        NotImplemented\n    def rpartition   (self, sep: bytes) -> (bytes,bytes,bytes):\n        NotImplemented\n    def rstrip       (self, chars: ?bytes) -> bytes:\n        NotImplemented\n    def split        (self, sep: bytes, maxsplit: ?int) -> list[bytes]:\n        NotImplemented\n    def splitlines   (self, keepends: ?bool) -> list[bytes]:\n        NotImplemented\n    def startswith   (self, prefix: bytes, start: ?int, end: ?int) -> bool:\n        NotImplemented\n    def strip        (self, chars: ?bytes) -> bytes:\n        NotImplemented\n    def upper        (self) -> bytes:\n        NotImplemented\n    def zfill        (self, width: int) -> bytes:\n        NotImplemented\n\nclass bytearray (object):\n    def __init__     (self, val: bytes) -> None:\n        NotImplemented\n    def capitalize   (self) -> bytearray:\n        NotImplemented\n    def center       (self, width: int, fillchar: ?bytearray) -> bytearray:\n        NotImplemented\n    def count        (self, sub: bytearray, start: ?int, end: ?int) -> int:\n        NotImplemented\n    def decode       (self) -> str:\n        NotImplemented\n    def endswith     (self, suffix: bytearray, start: ?int, end: ?int) -> bool:\n        NotImplemented\n    def expandtabs   (self, tabsize: ?int) -> bytearray:\n        NotImplemented\n    def find         (self, sub: bytearray, start: ?int, end: ?int) -> int:\n        NotImplemented\n    @staticmethod\n    def from_hex     (s: str) -> bytearray:\n        NotImplemented\n    def hex          (self) -> str:\n        NotImplemented\n    def index        (self, sub: bytearray, start: ?int, end: ?int) -> int:\n        NotImplemented\n    def isalnum      (self) -> bool:\n        NotImplemented\n    def isalpha      (self) -> bool:\n        NotImplemented\n    def isascii      (self) -> bool:\n        NotImplemented\n    def isdigit      (self) -> bool:\n        NotImplemented\n    def islower      (self) -> bool:\n        NotImplemented\n    def isspace      (self) -> bool:\n        NotImplemented\n    def istitle      (self) -> bool:\n        NotImplemented\n    def isupper      (self) -> bool:\n        NotImplemented\n    def join         (self, iterable: Iterable[bytearray]) -> bytearray:\n        NotImplemented\n    def ljust        (self, width: int, fillchar: ?bytearray) -> bytearray:\n        NotImplemented\n    def lower        (self) -> bytearray:\n        NotImplemented\n    def lstrip       (self, chars: ?bytearray) -> bytearray:\n        NotImplemented\n    def partition    (self, sep: bytearray) -> (bytearray,bytearray,bytearray):\n        NotImplemented\n    def replace      (self, old: bytearray, new: bytearray, count: ?int) -> bytearray:\n        NotImplemented\n    def rfind        (self, sub: bytearray, start: ?int, end: ?int) -> int:\n        NotImplemented\n    def rindex       (self, sub: bytearray, start: ?int, end: ?int) -> int:\n        NotImplemented\n    def rjust        (self, width: int, fillchar: ?bytearray) -> bytearray:\n        NotImplemented\n    def rpartition   (self, sep: bytearray) -> (bytearray,bytearray,bytearray):\n        NotImplemented\n    def rstrip       (self, chars: ?bytearray) -> bytearray:\n        NotImplemented\n    def split        (self, sep: bytearray, maxsplit: ?int) -> list[bytearray]:\n        NotImplemented\n    def splitlines   (self, keepends: ?bool) -> list[bytearray]:\n        NotImplemented\n    def startswith   (self, prefix: bytearray, start: ?int, end: ?int) -> bool:\n        NotImplemented\n    def strip        (self, chars: ?bytearray) -> bytearray:\n        NotImplemented\n    def upper        (self) -> bytearray:\n        NotImplemented\n    def zfill        (self, width: int) -> bytearray:\n        NotImplemented\n\nclass Msg[A] (value):\n    NotImplemented\n\n## Exceptions ##################################################################################\n\n# All exceptions should have a human readable error in the error_message field.\n# It is generally set by the constructor for each exception class that inherits\n# from BaseException to something appropriate for that particular exception. It\n# is also a common convention to accept a message as an argument to the\n# constructor, which can be used to override the default message.\nclass BaseException (value):\n    error_message: str\n    def __init__(self, msg: ?str) -> None:\n        self.error_message = msg if msg is not None else \"\"\n\n    def __str__(self):\n        return f\"{self._name()}: {self.error_message}\"\n\n    def __repr__(self):\n        return \"{self._name()}({self.error_message.__repr__()})\"\n\n    def _name(self) -> str:\n        NotImplemented\n\nclass SystemExit (BaseException):\n    pass\n\nclass KeyboardInterrupt (BaseException):\n    pass\n\nclass Exception (BaseException):\n    pass\n\nclass StopIteration (Exception):\n    pass\n\nclass AssertionError (Exception):\n    pass\n\nclass LookupError (Exception):\n    pass\n\nclass IndexError (LookupError):\n    def __init__(self, index: int, msg: ?str=None):\n        self.index = index\n        self.error_message = msg if msg is not None else \"List index out of range\"\n\n    def __str__(self):\n        return f\"{self._name()}: {self.error_message}, index: {self.index}\"\n\n    def __repr__(self):\n        return \"{self._name()}({self.index}, {self.error_message.__repr__()})\"\n\nclass KeyError(LookupError):\n    def __init__(self, key: value, msg: ?str=None):\n        self.key = key\n        self.error_message = msg if msg is not None else \"Key not found\"\n\n    def __str__(self):\n        return f\"{self._name()}: {self.error_message}, key: {str(self.key)}\"\n\n    def __repr__(self):\n        return '{self._name()}({self.key.__repr__()}, {self.error_message.__repr__()})'\n\nclass MemoryError (Exception):\n    pass\n\nclass OSError (Exception):\n    pass\n\nclass FileNotFoundError (OSError):\n    def __init__(self, filename: str):\n        self.error_message = \"\"\n        self.filename = filename\n\n    def __str__(self):\n        return f\"{self._name()}: No such file or directory: '{self.filename}'\"\n\n    def __repr__(self):\n        return '{self._name()}({self.filename.__repr__()})'\n\nclass RuntimeError (Exception):\n    pass\n\nclass NotImplementedError (RuntimeError):\n    pass\n\nclass ValueError (Exception):\n    pass\n\nclass ArithmeticError (Exception):\n    pass\n\nclass ZeroDivisionError (ArithmeticError):\n    pass\n\n\n## General protocols ###############################################################################\n\nprotocol Identity:\n    @staticmethod\n    __is__        : (Self,Self) -> bool\n    @staticmethod\n    __isnot__     : (Self,Self) -> bool\n\nprotocol Eq:\n    @staticmethod\n    __eq__       : (Self,Self) -> bool\n    @staticmethod\n    __ne__       : (Self,Self) -> bool\n    def __ne__(a,b):\n        return not (a == b)\n\nprotocol Ord (Eq):\n    @staticmethod\n    __lt__       : (Self,Self) -> bool\n    @staticmethod\n    __le__       : (Self,Self) -> bool\n    @staticmethod\n    __gt__       : (Self,Self) -> bool\n    @staticmethod\n    __ge__       : (Self,Self) -> bool\n\n    def __le__(a,b):\n        return a < b or a == b\n    def __gt__(a,b):\n        return b < a\n    def __ge__(a,b):\n        return b <= a\n\nprotocol Logical:\n    @staticmethod\n    __and__     : (Self,Self) -> Self\n    @staticmethod\n    __or__      : (Self,Self) -> Self\n    @staticmethod\n    __xor__     : (Self,Self) -> Self\n\n    @staticmethod\n    __iand__    : (Self,Self) -> Self\n    @staticmethod\n    __ior__     : (Self,Self) -> Self\n    @staticmethod\n    __ixor__    : (Self,Self) -> Self\n\n    def __iand__(a,b):\n        return a & b\n    def __ior__(a,b):\n        return a | b\n    def __ixor__(a,b):\n        return a ^ b\n\nprotocol Plus:\n    @staticmethod\n    __add__      : (Self,Self) -> Self\n    @staticmethod\n    __iadd__     : (Self,Self) -> Self\n    @staticmethod\n    __zero__     : () -> Self\n\n    def __iadd__(a,b):\n        return a + b\n\nprotocol Minus:\n    @staticmethod\n    __sub__      : (Self,Self) -> Self\n    @staticmethod\n    __isub__     : (Self,Self) -> Self\n\n    def __isub__(a,b):\n        return a - b\n\nprotocol Times[A] (Plus):\n    @staticmethod\n    __mul__      : (Self,A) -> Self\n    @staticmethod\n    __imul__     : (Self,A) -> Self\n\n    def __imul__(a,b):\n        return a * b\n\nprotocol Div[A]:\n    @staticmethod\n    __truediv__  : (Self,Self) -> A\n    @staticmethod\n    __itruediv__ : (Self,Self) -> A\n\n    def __itruediv__(a,b):\n        return a / b\n\nclass hasher(object):\n    def __init__(self, seed : u64 = 0) -> None:\n        NotImplemented \n\n    def update(self, b : bytes) -> None:\n        NotImplemented  \n\n    def finalize(self) -> u64:\n        NotImplemented  \n\nprotocol Hashable (Eq):\n    hash : (hasher) -> None\n    \nclass complex (value):\n    def __init__(self, val: Number) -> None:\n        NotImplemented\n\n    @staticmethod\n    def from_real_imag(real: Real, imag: Real) -> complex:\n        NotImplemented\n\nclass dict[A(Hashable),B] (object):\n    def __init__(self, iterable: ?Iterable[(A,B)]) -> None:\n        NotImplemented\n# Code generation for calls to copy and clear becomes wrong, so we omit them for now\n#    def clear(self) -> None:\n#        NotImplemented\n#    def copy(self) -> dict[A,B]:\n#        NotImplemented\n\nclass set[A(Hashable)] (object):\n    def __init__(self, iterable: ?Iterable[A]) -> None:\n        NotImplemented\n\n## Number protocols ################################################################################\n\n#   Plus\n#    |\n#    |\n#   Times           Minus\n#    |               |\n#    |               |\n#   Number <----------\n#    |\n#    |\n#   Real\n#    |\n#    |\n#   Rational        Logical\n#    |               |\n#    |               |\n#   Integral <--------\n\nprotocol Number (Times[Self],Minus):\n    @staticmethod\n    __fromatom__ : (atom) -> Self\n\n    __complex__  : () -> complex\n\n    @staticmethod\n    __pow__      : (Self,Self) -> Self\n\n    @staticmethod\n    __ipow__     : (Self,Self) -> Self\n\n    def __ipow__(a,b):\n        return a ** b\n\n    __neg__      : () -> Self\n    __pos__      : () -> Self\n\n    real         : () -> Real\n    imag         : () -> Real\n    __abs__      : () -> Real  # What about arg?\n\n    conjugate    : () -> Self\n\nprotocol Real (Number):\n    __float__    : () -> float\n\n    __trunc__    : () -> Integral\n    __floor__    : () -> Integral\n    __ceil__     : () -> Integral\n\n    __round__    : (?int) -> Self\n\nprotocol RealFloat (Real):\n    pass\n\nprotocol Rational (Real):\n    numerator    : () -> Integral\n    denominator  : () -> Integral\n\nprotocol Integral (Rational,Logical):\n    __int__      : () -> int\n    __index__    : () -> int\n\n    @staticmethod\n    __divmod__   : (Self,Self) -> (Self,Self)\n    @staticmethod\n    __floordiv__ : (Self,Self) -> Self\n    @staticmethod\n    __mod__      : (Self,Self) -> Self\n\n    @staticmethod\n    __ifloordiv__ : (Self,Self) -> Self\n    @staticmethod\n    __imod__     : (Self,Self) -> Self\n\n    @staticmethod\n    __lshift__   : (Self,int) -> Self\n    @staticmethod\n    __rshift__   : (Self,int) -> Self\n\n    @staticmethod\n    __ilshift__  : (Self,int) -> Self\n    @staticmethod\n    __irshift__  : (Self,int) -> Self\n\n    def __ifloordiv__(a,b):\n        return a // b\n    def __imod__(a,b):\n        return a % b\n    def __ilshift__(a,b):\n        return a << b\n    def __irshift__(a,b):\n        return a >> b\n\n    __invert__   : () -> Self\n\n## Number protocol extensions ######################################################################\n\n#extension bool (Eq): pass\nextension bool (Hashable):\n    NotImplemented\n\nextension int (Integral):\n    NotImplemented\nextension int (Div[float]):\n    NotImplemented\nextension int (Ord):\n    NotImplemented\nextension int (Hashable):\n    NotImplemented\n\nextension i32 (Integral):\n    NotImplemented\nextension i32 (Div[float]):\n    NotImplemented\nextension i32 (Ord):\n    NotImplemented\nextension i32 (Hashable):\n    NotImplemented\n\nextension i16 (Integral):\n    NotImplemented\nextension i16 (Div[float]):\n    NotImplemented\nextension i16 (Ord):\n    NotImplemented\nextension i16 (Hashable):\n    NotImplemented\n\n\nextension i8 (Integral):\n    NotImplemented\nextension i8 (Div[float]):\n    NotImplemented\nextension i8 (Ord):\n    NotImplemented\nextension i8 (Hashable):\n    NotImplemented\n\nextension u64 (Integral):\n    NotImplemented\nextension u64 (Div[float]):\n    NotImplemented\nextension u64 (Ord):\n    NotImplemented\nextension u64 (Hashable):\n    NotImplemented\n\nextension u32 (Integral):\n    NotImplemented\nextension u32 (Div[float]):\n    NotImplemented\nextension u32 (Ord):\n    NotImplemented\nextension u32 (Hashable):\n    NotImplemented\n\nextension u16 (Integral):\n    NotImplemented\nextension u16 (Div[float]):\n    NotImplemented\nextension u16 (Ord):\n    NotImplemented\nextension u16 (Hashable):\n    NotImplemented\n\nextension u8 (Integral):\n    NotImplemented\nextension u8 (Div[float]):\n    NotImplemented\nextension u8 (Ord):\n    NotImplemented\nextension u8 (Hashable):\n    NotImplemented\n\nextension u1 (Integral):\n    NotImplemented\nextension u1 (Div[float]):\n    NotImplemented\nextension u1 (Ord):\n    NotImplemented\nextension u1 (Hashable):\n    NotImplemented\n\nextension bigint (Integral):\n    NotImplemented\nextension bigint (Div[float]):\n    NotImplemented\nextension bigint (Ord):\n    NotImplemented\nextension bigint (Hashable):\n    NotImplemented\n\nextension float (RealFloat):\n    NotImplemented\nextension float (Div[float]):\n    NotImplemented\nextension float (Ord):\n    NotImplemented\nextension float (Hashable):\n    NotImplemented\n\nextension complex (Number):\n    NotImplemented\nextension complex (Div[complex]):\n    NotImplemented\nextension complex (Eq):\n    NotImplemented\nextension complex (Hashable):\n    NotImplemented\n\n## Collection protocols ############################################################################\n\nprotocol Indexed[A (Eq),B]:\n    __getitem__  : (A) -> B\n    __setitem__  : mut(A,B) -> None\n    __delitem__  : mut(A) -> None\n\nprotocol Sliceable[A] (Indexed[int,A]):\n    __getslice__ : (slice) -> Self\n    __setslice__ : mut(slice,Iterable[A]) -> None\n    __delslice__ : mut(slice) -> None\n\nprotocol Collection[A] (Iterable[A]):\n    @staticmethod\n    __fromiter__ : (Iterable[A]) -> Self\n    __len__      : () -> int\n\nprotocol Container[A(Eq)] (Collection[A]):\n    __contains__    : (A) -> bool\n    __containsnot__ : (A) -> bool\n\n\n\n#   Indexed         Iterable        Plus\n#    |               |               |\n#    |               |               |\n#   Sliceable       Collection      Times\n#    |               |               |\n#    |               |               |\n#   Sequence <-------- <--------------\n\nprotocol Sequence[A] (Sliceable[A], Collection[A], Times[int]):\n    __reversed__ : () -> Iterator[A]\n    insert      : mut(int,A) -> None\n    append      : mut(A) -> None\n    reverse     : mut() -> None\n\n\n\n#   Iterable\n#    |\n#    |\n#   Collection\n#    |\n#    |\n#   Container       Indexed\n#    |               |\n#    |               |\n#   Mapping <---------\n\nprotocol Mapping[A(Eq),B] (Container[A], Indexed[A,B]):\n    get         : (A) -> ?B\n    get_def     : (A,B) -> B\n    pop         : mut(A) -> ?B\n    pop_def     : mut(A,B) -> B\n    keys        : () -> Iterator[A]\n    values      : () -> Iterator[B]\n    items       : () -> Iterator[(A,B)]\n    update      : mut(Iterable[(A,B)]) -> None\n    popitem     : () -> (A,B)\n    setdefault  : mut(A,B) -> ?B\n\n\n\n#   Iterable\n#    |\n#    |\n#   Collection      Eq\n#    |               |\n#    |               |\n#   Container       Ord             Logical         Minus\n#    |               |               |               |\n#    |               |               |               |\n#   Set <------------- <-------------- <--------------\n\nprotocol Set[A (Eq)] (Container[A], Ord, Logical, Minus):\n    @staticmethod\n    isdisjoint  : (Self,Self) -> bool\n    add         : mut(A) -> None\n    discard     : mut(A) -> None\n    pop         : mut() -> A\n    update      : mut(Iterable[A]) -> None\n\n\n## Collection protocol extensions ########################################\n\nextension list[A] (Sequence[A]):\n    NotImplemented\nextension list[A(Eq)] (Container[A]):\n    NotImplemented\nextension list[A(Ord)] (Ord):\n    NotImplemented\n\nextension dict[A(Hashable),B] (Mapping[A,B]):\n    NotImplemented\nextension dict[A(Hashable),B(Eq)] (Ord):\n    NotImplemented\n\nextension set[A(Hashable)] (Set[A]):\n    NotImplemented\n\nextension Iterator[A](Iterable[A]):\n    NotImplemented\n\n# extension range[A](Iterable[A]):\n#     NotImplemented\n\nextension str (Ord):\n    NotImplemented\nextension str (Container[str]):\n    NotImplemented\nextension str (Sliceable[str]):\n    NotImplemented\nextension str (Times[int]):\n    NotImplemented\nextension str (Hashable):\n    NotImplemented\n\nextension bytearray (Ord):\n    NotImplemented\nextension bytearray (Sequence[int]):\n    NotImplemented\nextension bytearray (Container[int]):\n    NotImplemented\n\nextension bytes (Ord):\n    NotImplemented\nextension bytes (Sliceable[int]):\n    NotImplemented\nextension bytes (Container[int]):\n    NotImplemented\nextension bytes (Times[int]):\n    NotImplemented\nextension bytes (Hashable):\n    NotImplemented\n\n## Builtin functions #####################################################\n\ndef abs(x : Number) -> Real:\n    return x.__abs__()\n\ndef all[A(value)](it: Iterable[A]) -> bool:\n    for x in it:\n        if bool(x) == False:\n            return False\n    return True\n\ndef any[A(value)](it: Iterable[A]) -> bool:\n    for x in it:\n        if bool(x) == True:\n            return True\n    return False\n\ndef ascii(x : value) -> str:\n    NotImplemented\n\ndef bin(x: Integral) -> str:\n    NotImplemented\n\ndef chr(i: Integral) -> str:\n    NotImplemented\n\ndef divmod [A(Integral)] (a : A, b : A) -> (A, A): \n    return Integral.__divmod__(a,b)\n\ndef enumerate(iterable: Iterable[A], start: ?int) -> Iterator[(int,A)]:\n    NotImplemented\n\ndef filter (function: ?((A) -> B), iterable: Iterable[A]) -> Iterator[A]:\n    NotImplemented\n\ndef hash(x: Hashable) -> u64:\n    h = hasher()\n    x.hash(h)\n    return h.finalize()\n\ndef seed_hash(seed: u64, x: Hashable) -> u64:\n    h = hasher(seed)\n    x.hash(h)\n    return h.finalize()\n\ndef hex(i: Integral) -> str:\n    NotImplemented\n\ndef iter(x : Iterable[A]) -> Iterator[A]:\n    return x.__iter__()\n\ndef len(x : Collection[A]) -> int:\n    return x.__len__()\n\ndef map(function: (A) -> B, iterable: Iterable[A]) -> Iterator[B]:\n    NotImplemented\n\ndef max [A(Ord)] (iter: Iterable[A], dflt: ?A) -> A:\n    NotImplemented\n\ndef min [A(Ord)] (iter: Iterable[A], dflt: ?A) -> A:\n    NotImplemented\n\ndef max_def [A(Ord)] (iter: Iterable[A], dflt: A) -> A:\n    NotImplemented\n\ndef min_def [A(Ord)] (iter: Iterable[A], dflt: A) -> A:\n    NotImplemented\n\ndef next(x : Iterator[A]) -> A:\n    return x.__next__()\n\ndef ord(c: str) -> int:\n    NotImplemented\n\ndef pow [A(Number)] (a : A, b : A) -> A:\n    return Number.__pow__(a,b)\n\ndef print(*args, sep: str=\" \", end: str=\"\\n\", err: bool=False, flush: bool=False) -> None:\n    \"\"\"Prints values\n\n    Values are printed per default to stdout, but can be printed to stderr by\n    setting err=True. Multiple values are separated by the sep argument, a\n    space per default. Each invocation will per default add a new line character\n    at the end, which can be overridden through the end argument. Output can be\n    flushed by setting flush=True.\n\n    It is not possible to write to arbitrary file descriptors. Use the file IO\n    functionality to write to files.\n    \"\"\"\n    NotImplemented\n\ndef repr(x: ?value):\n    if x is not None:\n        return x.__repr__()\n    return \"None\"\n\ndef reversed[A](seq : Sequence[A]) -> Iterator[A]:\n    return seq.__reversed__()\n\ndef round [A(Real)] (x : A, n : ?int) -> A:\n    return x.__round__(n)\n\ndef sorted [A(Ord)] (iter: Iterable[A]) -> list[A]:\n    NotImplemented\n\ndef sum [A(Plus)] (iter: Iterable[A], start: ?A) -> A:\n    NotImplemented\n\ndef zip (a: Iterable[A], b: Iterable[B]) -> Iterator[(A,B)]:\n    NotImplemented\n\ndef gcd(a : bigint, b :bigint) -> bigint:\n    NotImplemented\n\ndef xgcd(a : bigint, b : bigint) -> (bigint, bigint, bigint):\n    NotImplemented\n\ndef type(a: ?value) -> str:\n    \"\"\"Get the name of the type of something as a string\n\n    Do not use this for meta-programming. Use isinstance().\n\n    This is only meant for development use as an alternative to letting acton\n    print inferred types and similar. It will be removed in a future version\n    when there are better ways to debug types.\n    \"\"\"\n    NotImplemented\n\ndef actorid() -> str:\n    NotImplemented\n\nactor StringDecoder(cb_out: action(str) -> None, encoding: ?str=\"utf-8\", on_error: ?action(str, bytes) -> None):\n    \"\"\"Bytes to string decoder\n\n    Decodes bytes to string using the provided encoding. If no encoding is given\n    UTF-8 is used. The decoder is stateful in order to buffer incomplete multi-\n    byte characters.\n    \"\"\"\n    MAX_UNICODE_CHAR_SIZE: int = 4\n    var buf: bytes = b\"\"\n\n    if encoding is not None:\n        if encoding.lower() != \"utf-8\":\n            raise ValueError(\"Only utf-8 encoding is supported\")\n\n    def decode(input: bytes) -> None:\n        buf += input\n        # Attempt to decode all of buf. If it fails we are likely in the middle\n        # of a multi-byte character so we try again by removing the last bytes\n        # iteratively until we succeed. UTF-8 has up to 4 bytes per character.\n        for i in range(len(buf), len(buf)-MAX_UNICODE_CHAR_SIZE, -1):\n            try:\n                s = buf[:i].decode()\n                buf = buf[i:]\n                cb_out(s)\n                return\n            except ValueError:\n                pass\n        if on_error is not None:\n            on_error(\"Invalid UTF-8\", buf)\n        else:\n            raise ValueError(f\"Invalid UTF-8: {str(buf)}\")\n\n## Environment ################################################\n\nclass WorldCap():\n    \"\"\"WorldCap has the capability to access the entire world outside of Acton.\n    It is the root of the capability hierarchy.\n\n    In an actor world, access to actors (like being able to call their methods)\n    requires a reference to the relevant actor. Anyone with a reference can\n    access the actor in question. It is not possible to forge a reference.\n\n    In Acton, things outside the actor world are represented as actors with the\n    associated capabilities. For example, with a reference to the TCPConnectCap\n    actor, we have the capability of using a POSIX socket to connect to a remote\n    host over the network. TCPConnectCap is part of a capability hierarchy,\n    starting with the generic WorldCap and becoming further and further refined:\n\n      WorldCap > NetCap > TCPCap > TCPConnectCap\n\n    There are other more refined Caps that each have a a subset of the\n    capabilities of the world.\n\n    Capability based privilege restriction prevent some deeply nested part of a\n    program, perhaps in a dependency to a dependency, to perform operations\n    unknown to the application author. Access to capabilities must be explicitly\n    handed out and a program can only perform operations based on the\n    capabilities it has access to.\n    \"\"\"\n    pass\n\nclass SysCap():\n    \"\"\"SysCap has the capability to access the internals of the Acton RTS system\n    \"\"\"\n    pass\n\nactor Env (wc: WorldCap, sc: SysCap, args: list[str]):\n    cap = wc\n    auth = wc\n    syscap = sc\n    argv = args\n    nr_wthreads: int = 0\n\n    action def getenv(name: str) -> ?str:\n        \"\"\"Get the value of an environment variable\"\"\"\n        res = getenvb(name.encode())\n        if res is not None:\n            return res.decode()\n        return None\n\n    action def getenvb(name: bytes) -> ?bytes:\n        \"\"\"Get the value of an environment variable\"\"\"\n        NotImplemented\n\n    action def setenv(n: str, v: str) -> None:\n        \"\"\"Set the value of an environment variable\"\"\"\n        setenvb(n.encode(), v.encode())\n\n    action def setenvb(n: bytes, v: bytes) -> None:\n        \"\"\"Set the value of an environment variable\"\"\"\n        NotImplemented\n\n    action def unsetenv(n: str) -> None:\n        \"\"\"Unset an environment variable\"\"\"\n        unsetenvb(n.encode())\n\n    action def unsetenvb(n: bytes) -> None:\n        \"\"\"Unset an environment variable\"\"\"\n        NotImplemented\n\n    action def stdout_write(s: str) -> None:\n        NotImplemented\n\n    action def stdin_install(on_stdin: ?action(str) -> None, encoding: ?str=None, on_error: ?action(str, bytes) -> None, on_stdin_bytes: ?action(bytes) -> None) -> None:\n        if on_stdin is None and on_stdin_bytes is None:\n            raise ValueError(\"At least one of on_stdin or on_stdin_bytes must be set\")\n        elif on_stdin_bytes is not None:\n            if encoding is not None:\n                raise ValueError(\"encoding must not be set when on_stdin_bytes is set, it is only used for decoding stdin bytes to string\")\n            if on_error is not None:\n                raise ValueError(\"on_error must not be set when on_stdin_bytes is set, it is only used for decoding error when decoding stdin bytes to string\")\n            _on_stdin_bytes(on_stdin_bytes)\n        elif on_stdin is not None:\n            if encoding is None:\n                # If no encoding is given, attempt to discover the encoding used\n                # Default to utf-8 if we're unable to discover the encoding\n                encoding = \"utf-8\"\n                # Read encoding from the LANG environment variable\n                lang_env = getenv(\"LANG\")\n                if lang_env is not None:\n                    try:\n                        encoding = lang_env.split(\".\")[1].lower()\n                    except:\n                        pass\n            # If stdin is attached to a terminal, attempt to discover the\n            # encoding used by the terminal by inspecting the LANG environment\n            # variable.\n            sd = StringDecoder(on_stdin, encoding, on_error)\n            _on_stdin_bytes(sd.decode)\n\n    action def set_stdin(canonical: ?bool, echo: ?bool) -> None:\n        NotImplemented\n\n    action def is_tty() -> bool:\n        NotImplemented\n\n    action def _on_stdin_bytes(cb: action(bytes) -> None) -> None:\n        NotImplemented\n\n    action def exit(n: int):\n        NotImplemented\n"
  },
  {
    "path": "base/src/__builtin__.ext.c",
    "content": "#include \"rts/rts.c\"\n\nvoid B___ext_init__() {\n\n    B_HashableD_bigintG_methods.__eq__ = (B_bool (*)(B_HashableD_bigint, B_bigint, B_bigint))B_OrdD_bigintD___eq__;\n    B_HashableD_intG_methods.__eq__ = (B_bool (*)(B_HashableD_int, B_int, B_int))B_OrdD_intD___eq__;\n    B_HashableD_i32G_methods.__eq__ = (B_bool (*)(B_HashableD_i32, B_i32, B_i32))B_OrdD_i32D___eq__;\n    B_HashableD_i16G_methods.__eq__ = (B_bool (*)(B_HashableD_i16, B_i16, B_i16))B_OrdD_i16D___eq__;\n    B_HashableD_u64G_methods.__eq__ = (B_bool (*)(B_HashableD_u64, B_u64, B_u64))B_OrdD_u64D___eq__;\n    B_HashableD_u32G_methods.__eq__ = (B_bool (*)(B_HashableD_u32, B_u32, B_u32))B_OrdD_u32D___eq__;\n    B_HashableD_u16G_methods.__eq__ = (B_bool (*)(B_HashableD_u16, B_u16, B_u16))B_OrdD_u16D___eq__;\n    B_HashableD_floatG_methods.__eq__ = (B_bool (*)(B_HashableD_float, B_float, B_float))B_OrdD_floatD___eq__;\n    B_HashableD_strG_methods.__eq__ = (B_bool (*)(B_HashableD_str, B_str, B_str))B_OrdD_strD___eq__;\n    B_HashableD_bytesG_methods.__eq__ = (B_bool (*)(B_HashableD_bytes, B_bytes, B_bytes))B_OrdD_bytesD___eq__;\n    B_HashableD_complexG_methods.__eq__ = (B_bool (*)(B_HashableD_complex, B_complex, B_complex))B_HashableD_complexD___eq__;\n\n    B_ContainerD_listG_methods.__len__ = (B_int (*)(B_ContainerD_list, B_list))B_CollectionD_SequenceD_listD___len__;\n    B_ContainerD_listG_methods.__fromiter__ = (B_list (*)(B_ContainerD_list, B_Iterable, $WORD))B_CollectionD_SequenceD_listD___fromiter__;\n    B_ContainerD_listG_methods.__iter__ = (B_Iterator (*)(B_ContainerD_list, B_list))B_CollectionD_SequenceD_listD___iter__;\n}\n\nB_str B_BaseExceptionD__name (B_BaseException self) {\n    return to$str(unmangle_name(self->$class->$GCINFO));\n}\n\nB_str B_type(B_value a) {\n    if (a)\n        return to$str(unmangle_name(a->$class->$GCINFO));\n    return to$str(\"None\");\n}\n\n$R B_EnvD_getenvbG_local (B_Env self, $Cont C_cont, B_bytes name) {\n    // uv_os_getenv is not threadsafe but our Env actor forces serial execution\n\n    // Try to use a small fixed size buffer\n    size_t len = 256;\n    char smallval[256];\n    char *value = smallval;\n\n    const char* env_var = (char*)fromB_bytes(name);\n\n    // First, query the required buffer size by passing NULL as the buffer\n    int r = uv_os_getenv(env_var, value, &len);\n    if (r == UV_ENOENT) {\n        // The environment variable does not exist\n        return $R_CONT(C_cont, B_None);\n    } else if (r == UV_ENOBUFS) {\n        // Allocate the buffer and actually get the environment variable value\n        value = (char*)acton_malloc(len);\n        r = uv_os_getenv(env_var, value, &len);\n    }\n    if (r < 0) {\n        $RAISE((B_BaseException)B_RuntimeErrorG_new($FORMAT(\"Failed to read the environment variable %s: %s\", env_var, uv_strerror(r))));\n    }\n    return $R_CONT(C_cont, to$bytes(value));\n}\n\n$R B_EnvD_setenvbG_local (B_Env self, $Cont C_cont, B_bytes name, B_bytes value) {\n    const char* env_var = fromB_bytes(name);\n    const char* env_val = fromB_bytes(value);\n    int r = uv_os_setenv(env_var, env_val);\n    if (r < 0) {\n        $RAISE((B_BaseException)B_RuntimeErrorG_new($FORMAT(\"Failed to set the environment variable %s: %s\", env_var, uv_strerror(r))));\n    }\n    return $R_CONT(C_cont, B_None);\n}\n\n$R B_EnvD_unsetenvbG_local (B_Env self, $Cont C_cont, B_bytes name) {\n    const char* env_var = fromB_bytes(name);\n    int r = uv_os_unsetenv(env_var);\n    if (r < 0) {\n        $RAISE((B_BaseException)B_RuntimeErrorG_new($FORMAT(\"Failed to unset the environment variable %s: %s\", env_var, uv_strerror(r))));\n    }\n    return $R_CONT(C_cont, B_None);\n}\n\n// action def is_tty() -> bool:\n$R B_EnvD_is_ttyG_local (B_Env self, $Cont C_cont) {\n    return $R_CONT(C_cont, toB_bool(isatty(1)));\n}\n\nB_str B_actorid() {\n    $Actor a = GET_SELF();\n    return $FORMAT(\"%ld\", a->$globkey);\n}\n"
  },
  {
    "path": "base/src/acton/rts.act",
    "content": "def gc(cap: SysCap) -> None:\n    \"\"\"Collect garbage\n\n    Jedi level. This is not the function you are looking for.\n    \"\"\"\n    NotImplemented\n\ndef enable_gc(cap: SysCap) -> None:\n    \"\"\"Enable the garbage collector\n\n    Jedi level. This is not the function you are looking for.\n    \"\"\"\n    NotImplemented\n\ndef disable_gc(cap: SysCap) -> None:\n    \"\"\"Disable the garbage collector\n\n    Jedi level. This is not the function you are looking for.\n    \"\"\"\n    NotImplemented\n\n\ndef start_gc_performance_measurement(cap: SysCap) -> None:\n    \"\"\"Start performance measurement of the garbage collector\n\n    Jedi level. This is not the function you are looking for.\n    \"\"\"\n    NotImplemented\n\ndef get_gc_time(cap: SysCap) -> (total: u64, mark: u64, sweep: u64):\n    \"\"\"Get GC time in milliseconds\"\"\"\n    NotImplemented\n\ndef get_mem_usage(cap: SysCap) -> u64:\n    \"\"\"Get memory usage in number of bytes\n\n    Gets the approximate current memory usage by this program. This is not the\n    same as the heap size (which is the amount of memory allocated to us from\n    the OS).\n    Computed by taking the heap size and subtracting unmapped bytes and free\n    bytes as the GC thinks of it. It's approximate because the GC gives us an\n    approximate value, usually on the order of ~10KB. Thus, it is hard to\n    precisely measure small usage of memory whereas for applications consuming\n    hundreds of KB or megabytes of memory, the precision is quite enough.\n    \"\"\"\n    NotImplemented\n\ndef get_gc_total_bytes(cap: SysCap) -> u64:\n    \"\"\"Get total number of bytes allocated on the GC heap\n    \"\"\"\n    NotImplemented\n\ndef get_gc_bytes_since_gc(cap: SysCap) -> u64:\n    \"\"\"Get number of bytes allocated on the GC heap since last GC\n    \"\"\"\n    NotImplemented\n\ndef get_rss(cap: SysCap) -> u64:\n    \"\"\"Get Resident Set Size in number of bytes\n\n    The Resident Set Size (RSS) is the amount of memory occupied by the process\n    in RAM. It includes the heap, the stack, and the code segment. It does not\n    include memory that is swapped out to disk. It is the amount of memory that\n    the process is actually using in RAM.\n    \"\"\"\n    NotImplemented\n\n# sleep is sort of dangerous - it will actually put the RTS thread executing the\n# actor calling this function to sleep. This could be seen as ultrabad, like we\n# would want to just pause execution of one actor and let the RTS thread process\n# other actors meanwhile. There would be room for such a function, however, the\n# acton.rts.sleep() is deliberately putting the RTS thread to sleep. This is a\n# simple way of simulating heavy work without actually doing the heavy work, so\n# in a benchmark we can pretend some actors are doing relatively heavy work, yet\n# our CPU usage will be lower, so this is like laptop airplane mode friendly\n# (consumes less battery).\ndef sleep(cap: SysCap, duration: float) -> None:\n    \"\"\"Put RTS worker thread to sleep\"\"\"\n    NotImplemented\n\ndef rss(cap: SysCap) -> int:\n    \"\"\"Get Resident Set Size\"\"\"\n    NotImplemented\n\ndef _io_handles(cap: SysCap) -> dict[u64, (typ: str, act: u64)]:\n    \"\"\"Return all I/O handles and their type for the current worker thread\"\"\"\n    NotImplemented\n\ndef rts_stats(cap: SysCap) -> dict[u64, (state: str, sleeps: u64, conts_count: u64, conts_sum: u64, conts_100ns: u64, conts_1us: u64, conts_10us: u64, conts_100us: u64, conts_1ms: u64, conts_10ms: u64, conts_100ms: u64, conts_1s: u64, conts_10s: u64, conts_100s: u64, conts_inf: u64, bkeep_count: u64, bkeep_sum: u64, bkeep_100ns: u64, bkeep_1us: u64, bkeep_10us: u64, bkeep_100us: u64, bkeep_1ms: u64, bkeep_10ms: u64, bkeep_100ms: u64, bkeep_1s: u64, bkeep_10s: u64, bkeep_100s: u64, bkeep_inf: u64)]:\n    \"\"\"Return all I/O handles and their type for the current worker thread\"\"\"\n    NotImplemented\n\nactor WThreadMonitor(env: Env, arg_wthread_id: int):\n    wthread_id = arg_wthread_id\n\n    def io_handles():\n        return _io_handles(env.syscap)\n\n    proc def _init():\n        \"\"\"Implementation internal\"\"\"\n        NotImplemented\n    _init()\n\nactor Monitor(env: Env):\n    tms: dict[int, WThreadMonitor] = {}\n\n    for wthread_id in range(1, env.nr_wthreads+1):\n        tm = WThreadMonitor(env, wthread_id)\n        tms[wthread_id] = tm\n\n    def io_handles():\n        res = {}\n        for wthread_id, tm in tms.items():\n            res[wthread_id] = tm.io_handles()\n        return res\n\n"
  },
  {
    "path": "base/src/acton/rts.ext.c",
    "content": "#define GC_THREADS 1\n#include <gc.h>\n\n#include <time.h>\n#include <uv.h>\n\n#include \"rts/io.h\"\n#include \"rts/log.h\"\n\nvoid actonQ_rtsQ___ext_init__() {\n    // NOP\n}\n\nB_NoneType actonQ_rtsQ_gc (B_SysCap cap) {\n    GC_gcollect_and_unmap();\n    return B_None;\n}\n\nB_NoneType actonQ_rtsQ_enable_gc (B_SysCap cap) {\n    GC_enable();\n    return B_None;\n}\n\nB_NoneType actonQ_rtsQ_disable_gc (B_SysCap cap) {\n    GC_disable();\n    return B_None;\n}\n\n// def start_gc_performance_measurement(cap: SysCap) -> None:\nB_NoneType actonQ_rtsQ_start_gc_performance_measurement (B_SysCap cap) {\n    GC_start_performance_measurement();\n    return B_None;\n}\n\n// def get_gc_time(cap: SysCap) -> (total: u64, mark: u64, sweep: u64):\nB_tuple actonQ_rtsQ_get_gc_time (B_SysCap cap) {\n    unsigned long total = GC_get_full_gc_total_time();\n    unsigned long mark = GC_get_stopped_mark_total_time();\n    unsigned long sweep = total - mark;\n\n    B_tuple res = $NEWTUPLE(3,\n                            toB_u64(total),\n                            toB_u64(mark),\n                            toB_u64(sweep)\n                            );\n    return res;\n}\n\nB_u64 actonQ_rtsQ_get_heap_size (B_SysCap cap) {\n    return toB_u64(GC_get_heap_size());\n}\n\nuint64_t actonQ_rtsQ_U_get_mem_usage (B_SysCap cap) {\n    return GC_get_heap_size() - GC_get_free_bytes();\n}\n\n// def get_gc_total_bytes(cap: SysCap) -> u64:\nuint64_t actonQ_rtsQ_U_1get_gc_total_bytes (B_SysCap cap) {\n    return GC_get_total_bytes();\n}\n\n//def get_gc_bytes_since_gc(cap: SysCap) -> u64:\nuint64_t actonQ_rtsQ_U_2get_gc_bytes_since_gc (B_SysCap cap) {\n    return GC_get_bytes_since_gc();\n}\n\n// def get_rss(cap: SysCap) -> u64:\nuint64_t actonQ_rtsQ_U_3get_rss (B_SysCap cap) {\n    uint64_t rsm;\n    int r = uv_resident_set_memory(&rsm);\n    return rsm;\n}\n\nint64_t actonQ_rtsQ_U_6rss (B_SysCap cap) {\n    int64_t rsm;\n    int r = uv_resident_set_memory(&rsm);\n    return rsm;\n}\n\nB_NoneType actonQ_rtsQ_U_4sleep (B_SysCap cap, double sleep_time) {\n    double st = sleep_time;\n    struct timespec ts;\n    ts.tv_sec = (int)st;\n    ts.tv_nsec = (st - (float)ts.tv_sec)*1e9;\n\n    // Handle overflow of nanoseconds into seconds\n    if (ts.tv_nsec >= 1e9) {\n        ts.tv_sec += 1;\n        ts.tv_nsec -= 1e9;\n    }\n\n    // Use high precision nanosleep where available, otherwise fall back to uv_sleep.\n#if defined(__linux__) || defined(__APPLE__)\n    // Unlike usleep, nanosleep() tolerates signal interrupts and will write the\n    // remaining time (that it didn't sleep) into the third argument. We spin\n    // until it completes successfully.\n    while (nanosleep(&ts, &ts) != 0) {\n        // Continue sleeping with remaining time\n    }\n#else\n    // For other platforms, fall back to uv_sleep (millisecond granularity)\n    uv_sleep((uint64_t)ts.tv_sec * 1000 + ts.tv_nsec / 1000000);\n#endif\n    return B_None;\n}\n\nstruct actonQ_rtsQ_io_handles_walk_res {\n    B_dict d;\n    B_Hashable wit;\n};\n\nvoid actonQ_rtsQ_io_handles_walk_cb (uv_handle_t *handle, void *arg) {\n    struct actonQ_rtsQ_io_handles_walk_res *walk_res = (struct actonQ_rtsQ_io_handles_walk_res *)arg;\n    B_tuple val;\n    if (uv_handle_get_type(handle) == UV_TCP) {\n        $Actor hactor = handle->data;\n        val = (B_tuple)$NEWTUPLE(2,\n                                to$str((char *)uv_handle_type_name(uv_handle_get_type(handle))),\n                                toB_u64((unsigned long)hactor)\n                                );\n    } else {\n        val = (B_tuple)$NEWTUPLE(2,\n                                to$str((char *)uv_handle_type_name(uv_handle_get_type(handle))),\n                                toB_u64(0) // TODO: should be None type instead, right?\n                                );\n    }\n\n    B_dictD_setitem(walk_res->d, walk_res->wit, toB_u64((long)handle), val);\n}\n\nB_dict actonQ_rtsQ__io_handles (B_SysCap cap) {\n    B_Hashable wit = (B_Hashable)B_HashableD_u64G_witness;\n    B_dict d = $NEW(B_dict, wit, NULL, NULL);\n\n    struct actonQ_rtsQ_io_handles_walk_res walk_res;\n    walk_res.wit = wit;\n    walk_res.d = d;\n    uv_walk(get_uv_loop(), actonQ_rtsQ_io_handles_walk_cb, (void *)&walk_res);\n\n    return d;\n}\n\nB_dict actonQ_rtsQ_rts_stats (B_SysCap cap) {\n    B_Hashable wit = (B_Hashable)B_HashableD_u64G_witness;\n    B_dict d = $NEW(B_dict, wit, NULL, NULL);\n    for (int i; i <= num_wthreads; i++) {\n        B_tuple stats = $NEWTUPLE(28,\n                            to$str(\"TODO\"), // state\n                            toB_u64(wt_stats[i].sleeps),\n                            toB_u64(wt_stats[i].conts_count),\n                            toB_u64(wt_stats[i].conts_sum),\n                            toB_u64(wt_stats[i].conts_100ns),\n                            toB_u64(wt_stats[i].conts_1us),\n                            toB_u64(wt_stats[i].conts_10us),\n                            toB_u64(wt_stats[i].conts_100us),\n                            toB_u64(wt_stats[i].conts_1ms),\n                            toB_u64(wt_stats[i].conts_10ms),\n                            toB_u64(wt_stats[i].conts_100ms),\n                            toB_u64(wt_stats[i].conts_1s),\n                            toB_u64(wt_stats[i].conts_10s),\n                            toB_u64(wt_stats[i].conts_100s),\n                            toB_u64(wt_stats[i].conts_inf),\n                            toB_u64(wt_stats[i].bkeep_count),\n                            toB_u64(wt_stats[i].bkeep_sum),\n                            toB_u64(wt_stats[i].bkeep_100ns),\n                            toB_u64(wt_stats[i].bkeep_1us),\n                            toB_u64(wt_stats[i].bkeep_10us),\n                            toB_u64(wt_stats[i].bkeep_100us),\n                            toB_u64(wt_stats[i].bkeep_1ms),\n                            toB_u64(wt_stats[i].bkeep_10ms),\n                            toB_u64(wt_stats[i].bkeep_100ms),\n                            toB_u64(wt_stats[i].bkeep_1s),\n                            toB_u64(wt_stats[i].bkeep_10s),\n                            toB_u64(wt_stats[i].bkeep_100s),\n                            toB_u64(wt_stats[i].bkeep_inf)\n                            );\n        B_dictD_setitem(d, wit, toB_u64(i), stats);\n    }\n    return d;\n}\n\n$R actonQ_rtsQ_WThreadMonitorD__initG_local (actonQ_rtsQ_WThreadMonitor self, $Cont C_cont) {\n    set_actor_affinity(fromB_int(self->wthread_id));\n    return $R_CONT(C_cont, B_None);\n}\n"
  },
  {
    "path": "base/src/argparse.act",
    "content": "\"\"\"Command line argument parsing\n\nThe argparse module provides command-line argument parsing for Acton applications.\nIt supports options (flags), positional arguments, sub-commands, and automatic\nhelp generation.\n\n## Basic Usage\n\n```acton\nimport argparse\n\nactor main(env):\n    def _parse_args():\n        p = argparse.Parser()\n        p.add_option(\"lines\", \"int\", default=10, help=\"Number of lines\", short=\"n\")\n        p.add_bool(\"follow\", \"Follow file changes\", short=\"f\")\n        p.add_arg(\"file\", \"File to tail\")\n        return p.parse(env.argv)\n\n    try:\n        args = _parse_args()\n\n        num_lines = args.get_int(\"lines\")\n        follow = args.get_bool(\"follow\")\n        filename = args.get_str(\"file\")\n\n        print(\"Tailing\", num_lines, \"lines from\", filename)\n        if follow:\n            print(\"Following file changes...\")\n\n    except argparse.PrintUsage as exc:\n        print(exc.error_message)\n        env.exit(0)\n    except argparse.ArgumentError as exc:\n        print(exc.error_message, err=True)\n        env.exit(1)\n```\n\nThe typical idiom is to define a `_parse_args()` function that sets up the parser\nand returns the parsed arguments, then wrap the main logic in a try/except block\nto handle help requests and argument errors gracefully.\n\n## Positional arguments\n\nPositional arguments must appear in a specific order and as plain values, i.e.\nno leading `-` or `--`:\n\n```acton\np.add_arg(\"file\", \"File to tail\")                    # required\np.add_arg(\"backup\", \"Backup file\", required=False)   # optional\np.add_arg(\"files\", \"Files to tail\", nargs=\"+\")       # one or more\n\n# Usage: tail log.txt\n# Usage: tail log.txt backup.log\n# Usage: tail app.log error.log debug.log\n```\n\n## Boolean flags\n\nBoolean flags are options that do not take a value. If present, they are `True`,\notherwise they are `False`:\n\n```acton\np.add_bool(\"follow\", \"Follow file changes\", short=\"f\")\np.add_bool(\"quiet\", \"Suppress headers\", short=\"q\")\n\nargs = p.parse([\"tail\", \"-f\", \"-q\", \"app.log\"])\nfollow = args.get_bool(\"follow\")   # True\nquiet = args.get_bool(\"quiet\")     # True\n\n# Usage: tail -f app.log\n# Usage: tail --follow --quiet app.log\n# Usage: tail -fq app.log  (grouped)\n```\n\n\n## Options with values\n\nOptions can take values of different types:\n\n```acton\n# Integer option\np.add_option(\"lines\", \"int\", default=10, help=\"Number of lines\", short=\"n\")\nnum_lines = args.get_int(\"lines\")\n\n# String option\np.add_option(\"format\", \"str\", default=\"plain\", help=\"Output format\")\nfmt = args.get_str(\"format\")\n\n# String list option\np.add_option(\"exclude\", \"strlist\", nargs=\"+\", help=\"Patterns to exclude\")\npatterns = args.get_strlist(\"exclude\")\n\n# Usage: tail -n 20 --format json --exclude \"ERROR\" \"DEBUG\" app.log\n```\n\n## Short options\n\nShort options are single character aliases prefixed with a single dash:\n\n```acton\np.add_option(\"lines\", \"int\", default=10, help=\"Number of lines\", short=\"n\")\np.add_bool(\"follow\", \"Follow file changes\", short=\"f\")\n\n# These are equivalent:\n# --lines 20 --follow\n# -n 20 -f\n# -n20 -f      (inline value)\n# -fn 20       (grouped boolean + option)\n```\n\n### Grouping rules\n- Boolean flags can be grouped: `-fq` = `-f -q`\n- Options with values: `-n 20` or `-n20` (inline)\n- Short options must be alphanumeric (a-z, A-Z, 0-9)\n- Each short option must be unique\n\n## Sub-commands\n\nSub-commands enable hierarchical CLIs like `git add` or `docker run`:\n\n```acton\ndef cmd_head(args):\n    lines = args.get_int(\"lines\")\n    print(\"Head mode:\", lines, \"lines\")\n\ndef cmd_tail(args):\n    lines = args.get_int(\"lines\")\n    follow = args.get_bool(\"follow\")\n    print(\"Tail mode:\", lines, \"lines, follow:\", follow)\n\np = argparse.Parser()\np.add_bool(\"verbose\", \"Verbose output\", short=\"v\")\n\nhead_cmd = p.add_cmd(\"head\", \"Show first lines\", cmd_head)\nhead_cmd.add_option(\"lines\", \"int\", default=10, short=\"n\")\n\ntail_cmd = p.add_cmd(\"tail\", \"Show last lines\", cmd_tail)\ntail_cmd.add_option(\"lines\", \"int\", default=10, short=\"n\")\ntail_cmd.add_bool(\"follow\", \"Follow changes\", short=\"f\")\n\n# Usage: viewer -v tail -n 20 -f app.log\n```\n\n## Command handlers and execution\n\nAfter parsing, execute the command handler if one was specified:\n\n```acton\nargs = parser.parse(env.argv)\ncmd = args.cmd\nif cmd is not None:\n    cmd(args)  # Execute the command function\nelse:\n    # No sub-command, default behavior\n    filename = args.get_str(\"file\")\n    print(\"Processing\", filename, \"with default settings\")\n```\n\n## Help generation\n\nHelp is automatically generated and displayed with `--help`:\n\n```\nUsage: tail [-n LINES] [-f] FILE\n\nPositional arguments:\n  FILE               File to tail\n\nOptions:\n  -n, --lines LINES  Number of lines\n  -f, --follow       Follow file changes\n  --help             show this help message\n```\n\n## Error handling\n\nThe parser raises specific exceptions for different error conditions:\n\n- `ArgumentError`: Invalid arguments, missing values, unknown options\n- `PrintUsage`: Help requested (catch and print, then exit)\n\nAlways wrap parsing in try/except to handle these gracefully.\n\"\"\"\n\n# TODO: mutually exclusive argument groups\n# TODO: argument metavar\n# TODO: required options (oxymoronic)?\n# TODO: bash completion\n#\n\n# Parsing Algorithm: Three-Phase Approach\n#\n# Phase 1 - Option Recognition and Collection:\n# Parser processes argv sequentially, identifying known long options (--option) and\n# short options (-x). For grouped short options (-abc), recognized options are processed\n# immediately while unknown options are reconstructed and added to 'rest'. Sub-commands\n# are detected and registered but parsing continues. All unrecognized arguments go to 'rest'.\n#\n# Phase 2 - Sub-command Processing (recursive):\n# If a sub-command was identified, its parser receives the 'rest' arguments and repeats\n# Phase 1 with its own option definitions. This happens recursively for nested sub-commands,\n# with each level processing its known options and passing unknowns down the chain.\n#\n# Phase 3 - Positional Argument Matching:\n# After all option processing, remaining arguments are matched to positional argument\n# definitions. Inner-most parsers (deepest sub-commands) process positional arguments\n# first, enabling optional positional arguments at higher levels while still consuming\n# required positional arguments in sub-commands.\n#\n# Grouped Short Options (-abc):\n# Recognized options are processed immediately, unknown options are reconstructed as\n# separate arguments for 'rest' (e.g., -a known, -bc unknown -> -bc goes to rest).\n# This enables mixed groups where some options belong to the main parser and others\n# to sub-command parsers.\n\nclass ArgumentError(Exception):\n    pass\n\nclass PrintUsage(ArgumentError):\n    pass\n\n\nclass Args(object):\n    cmd_parser: ?Parser\n    options: dict[str, (type: str, value: value)]\n    cmd: ?proc(Args) -> None\n\n    def __init__(self):\n        self.cmd_parser = None\n        self.options = {}\n        self.cmd = None\n\n    def get_bool(self, name: str) -> bool:\n        try:\n            opt = self.options[name]\n            if opt.type != \"bool\":\n                raise ValueError(f\"Option {name} is not a bool\")\n            val = opt.value\n            if isinstance(val, bool):\n                return val\n            raise ValueError(f\"Option value {str(val)} is not a bool\")\n        except KeyError:\n            raise ArgumentError(f\"Option '{name}' not found\")\n\n    def get_int(self, name: str) -> int:\n        try:\n            opt = self.options[name]\n            if opt.type != \"int\":\n                raise ValueError(f\"Option '{name}' is not a int\")\n            val = opt.value\n            if isinstance(val, int):\n                return val\n            raise ValueError(f\"Option value '{str(val)}' is not a int\")\n        except KeyError:\n            raise ArgumentError(f\"Option '{name}' not found\")\n\n    def get_str(self, name: str) -> str:\n        try:\n            opt = self.options[name]\n            if opt.type != \"str\":\n                raise ValueError(f\"Option '{name}' is not a str\")\n            val = opt.value\n            if isinstance(val, str):\n                return val\n            raise ValueError(f\"Option value '{str(val)}' is not a str\")\n        except KeyError:\n            raise ArgumentError(f\"Option '{name}' not found\")\n\n    def get_strlist(self, name: str) -> list[str]:\n        try:\n            opt = self.options[name]\n            if opt.type != \"strlist\":\n                raise ValueError(f\"Option '{name}' is not a list[str]\")\n            val = opt.value\n            if isinstance(val, list):\n                return val\n            raise ValueError(f\"Option value '{str(val)}' is not a list[str]\")\n        except KeyError:\n            raise ArgumentError(f\"Option '{name}' not found\")\n\n\nclass Parser(object):\n    cmd: str\n    opts: dict[str, (name: str, type: str, nargs: str, default: ?value, help: str, short: ?str)]\n    short_opts: dict[str, str]  # short -> long name mapping\n    args: list[(name: str, help: str, required: bool, nargs: str, left: int)]\n    cmds: dict[str, (help: str, parser: Parser, fn: proc(Args) -> None)]\n    prog: str\n\n    def __init__(self, cmd=\"\"):\n        self.cmd = cmd\n        self.opts = {}\n        self.short_opts = {}\n        self.args = []\n        self.cmds = {}\n        self.prog = \"\"\n\n    def add_bool(self, name: str, help: str, short: ?str=None):\n        if short is not None:\n            if len(short) != 1:\n                raise ArgumentError(\"Short option must be exactly one character\")\n            if not short.isalnum():\n                raise ArgumentError(\"Short option must be alphanumeric\")\n            if short in self.short_opts:\n                raise ArgumentError(f\"Short option '{short}' already exists\")\n            self.short_opts[short] = name\n\n        self.opts[name] = (name=name, type=\"bool\", nargs=\"?\", default=False, help=help, short=short)\n\n    def add_option(self, name: str, type: str, nargs: str=\"?\", default: ?value=None, help=\"\", short: ?str=None):\n        if name in self.opts:\n            raise ArgumentError(f\"Option '{name}' already exists\")\n        if type not in {\"int\", \"str\", \"strlist\"}:\n            raise ArgumentError(f\"Invalid option type '{type}'\")\n\n        if short is not None:\n            if len(short) != 1:\n                raise ArgumentError(\"Short option must be exactly one character\")\n            if not short.isalnum():\n                raise ArgumentError(\"Short option must be alphanumeric\")\n            if short in self.short_opts:\n                raise ArgumentError(f\"Short option '{short}' already exists\")\n            self.short_opts[short] = name\n\n        self.opts[name] = (name=name, type=type, nargs=nargs, default=default, help=help, short=short)\n\n    def add_arg(self, name: str, help: str=\"\", required: bool=True, nargs: str=\"?\"):\n        if nargs == \"+\" or nargs == \"*\":\n            for arg in self.args:\n                if arg.nargs == \"+\" or arg.nargs == \"*\":\n                    raise ArgumentError(\"Only one positional argument with multiple values allowed\")\n        self.args.append((name=name, help=help, required=required, nargs=nargs, left=1))\n\n    def add_cmd(self, name: str, help: str=\"\", fn: proc(Args) -> None):\n        p = Parser(name)\n        self.cmds[name] = (help=help, parser=p, fn=fn)\n        return p\n\n    def print_usage(self):\n        print(self.get_usage())\n\n    def get_usage(self):\n        usage_text = \"\"\n        short_opts = \"\"\n        for name in sorted(self.opts.keys()):\n            opt = self.opts[name]\n            short_opt = opt.short\n            if opt.type == \"bool\":\n                if short_opt is not None:\n                    short_opts += f\" [-{short_opt}]\"\n                else:\n                    short_opts += f\" [--{name}]\"\n            else:\n                if short_opt is not None:\n                    short_opts += f\" [-{short_opt} {name.upper()}]\"\n                else:\n                    short_opts += f\" [--{name} {name.upper()}]\"\n        for arg in self.args:\n            n = arg.name\n            if n is not None:\n                if arg.nargs == \"?\":\n                    if arg.required:\n                        short_opts += f\" {n.upper()}\"\n                    else:\n                        short_opts += f\" [{n.upper()}]\"\n                elif arg.nargs == \"+\":\n                    short_opts += f\" {n.upper()} [{n.upper()} ...]\"\n        if len(self.cmds) > 0:\n            short_opts += \" COMMAND\"\n        usage_text += f\"Usage: {self.prog}{short_opts}\\n\"\n\n        if len(self.cmds) > 0:\n            usage_text += \"\\nCommands:\\n\"\n            for name in sorted(self.cmds.keys()):\n                usage_text += f\"  {name:<14} {self.cmds[name].help}\\n\"\n        if len(self.args) > 0:\n            usage_text += \"\\nPositional arguments:\\n\"\n            for arg in self.args:\n                n = arg.name\n                if n is not None:\n                    usage_text += f\"  {n.upper():<14} {arg.help}\\n\"\n        if len(self.opts) > 0:\n            usage_text += \"\\nOptions:\\n\"\n            for name in sorted(self.opts.keys()):\n                opt = self.opts[name]\n                opt_help = f\"--{name}\"\n                short_opt = opt.short\n                if short_opt is not None:\n                    opt_help = f\"-{short_opt}, {opt_help}\"\n                if opt.type != \"bool\":\n                    opt_help += f\" {name.upper()}\"\n                usage_text += f\"  {opt_help:<14} {opt.help}\\n\"\n        return usage_text\n\n    def parse(self, argv: list[str]) -> Args:\n        return self._parse(argv)\n\n    def _parse(self, argin: list[str], res_args: ?Args=None) -> Args:\n        injected_help = False\n        if \"help\" not in self.opts:\n            injected_help = True\n            self.add_bool(\"help\", \"show this help message\")\n\n        if res_args is None: # top level call\n            self.prog = argin[0]\n            args_to_parse = argin[1:]\n        else: # recursively called\n            args_to_parse = argin\n        args, rest = self._parse_and_consume(args_to_parse, res_args, prog=self.prog)\n        cmd_parser = args.cmd_parser\n\n        if injected_help and args.get_bool(\"help\"):\n            if cmd_parser is not None:\n                raise PrintUsage(cmd_parser.get_usage())\n            raise PrintUsage(self.get_usage())\n\n        for arg in self.args:\n            if arg.required and arg.name not in args.options:\n                raise ArgumentError(f\"Missing positional argument: {arg.name}\")\n\n        return args\n\n    def _parse_and_consume(self, argv: list[str], res_args: ?Args, prog=\"\") -> (Args, list[str]):\n        self.prog = prog\n        #print(self, \"_parse_and_consume, argv:\", argv, \"res_args:\", res_args)\n        rest: list[str] = []\n        cmd_parser = None\n        if res_args is not None:\n            res = res_args\n        else:\n            res = Args()\n        # Insert default values\n        for akey, aspec in self.opts.items():\n            defval = aspec.default\n            if defval is not None:\n                res.options[akey] = (\"type\"=aspec.type, \"value\"=defval)\n        for arg in self.args:\n            if not arg.required:\n                if arg.nargs == \"+\":\n                    res.options[arg.name] = (\"type\"=\"strlist\", \"value\"=[])\n\n        skip = 0\n        for i in range(len(argv)):\n            p = i + skip\n            if p >= len(argv):\n                break\n            arg = argv[p]\n            start = 0\n            end = len(arg)\n            if arg == '--':\n                rest.extend(argv[p+1:])\n                break\n            elif arg.startswith('--'):\n                start = 2\n                val_in_arg = False\n                if arg.find('=') != -1:\n                    val_in_arg = True\n                    end = arg.find('=')\n                akey = arg[start:end]\n\n                if akey in self.opts:\n                    aspec = self.opts[akey]\n                    val = False\n                    if aspec.type != \"bool\": # all other types take a value\n                        if val_in_arg:\n                            val = arg[end+1:]\n                        else:\n                            try:\n                                val = argv[p+1]\n                            except IndexError:\n                                raise ArgumentError(f\"Missing value to option {arg}\")\n                            skip += 1\n\n                    if aspec.type == \"bool\":\n                        res.options[akey] = (\"type\"=\"bool\", \"value\"=True)\n                    elif aspec.type == \"int\":\n                        try:\n                            res.options[akey] = (\"type\"=\"int\", \"value\"=int(val))\n                        except ValueError:\n                            raise ArgumentError(f\"Option {akey} requires an integer value\")\n                    elif aspec.type == \"str\":\n                        res.options[akey] = (\"type\"=\"str\", \"value\"=val)\n                    elif aspec.type == \"strlist\":\n                        newval = []\n                        if akey in res.options:\n                            curlist = res.options[akey].value\n                            if isinstance(curlist, list):\n                                newval = curlist\n                        newval.append(val)\n                        res.options[akey] = (\"type\"=\"strlist\", \"value\"=newval)\n                else:\n                    #raise ArgumentError(f\"Unknown option {arg}\")\n                    rest.append(arg)\n            elif arg.startswith('-') and len(arg) > 1:\n                # Handle short options (-x or -xyz for grouped bools only)\n                short_chars = arg[1:]  # Remove leading dash\n\n                # Check if this is a single non-bool option with inline value\n                if len(short_chars) > 1:\n                    first_char = short_chars[0]\n                    if first_char in self.short_opts:\n                        first_spec = self.opts[self.short_opts[first_char]]\n                        if first_spec.type != \"bool\":\n                            # Single non-bool option with inline value: -ofile.txt\n                            akey = self.short_opts[first_char]\n                            val = short_chars[1:]  # Rest is the value\n\n                            if first_spec.type == \"int\":\n                                try:\n                                    res.options[akey] = (\"type\"=\"int\", \"value\"=int(val))\n                                except ValueError:\n                                    raise ArgumentError(f\"Option -{first_char} requires an integer value\")\n                            elif first_spec.type == \"str\":\n                                res.options[akey] = (\"type\"=\"str\", \"value\"=val)\n                            elif first_spec.type == \"strlist\":\n                                newval = []\n                                if akey in res.options:\n                                    curlist = res.options[akey].value\n                                    if isinstance(curlist, list):\n                                        newval = curlist\n                                newval.append(val)\n                                res.options[akey] = (\"type\"=\"strlist\", \"value\"=newval)\n                            continue  # Skip to next argument\n\n                # Process as grouped boolean options or single option\n                unknown_chars = []\n                processed_any = False\n\n                for j in range(len(short_chars)):\n                    short_char = short_chars[j]\n\n                    if short_char in self.short_opts:\n                        akey = self.short_opts[short_char]\n                        aspec = self.opts[akey]\n\n                        if aspec.type == \"bool\":\n                            res.options[akey] = (\"type\"=\"bool\", \"value\"=True)\n                            processed_any = True\n                        else:\n                            # Non-bool short option in group context\n                            if j != len(short_chars) - 1:\n                                raise ArgumentError(f\"Non-boolean option -{short_char} cannot be grouped (must be last or use separate argument)\")\n\n                            # Single non-bool option, value comes from next arg\n                            val = \"\"\n                            try:\n                                val = argv[p+1]\n                                skip += 1\n                            except IndexError:\n                                raise ArgumentError(f\"Missing value to option -{short_char}\")\n\n                            if aspec.type == \"int\":\n                                try:\n                                    res.options[akey] = (\"type\"=\"int\", \"value\"=int(val))\n                                except ValueError:\n                                    raise ArgumentError(f\"Option -{short_char} requires an integer value\")\n                            elif aspec.type == \"str\":\n                                res.options[akey] = (\"type\"=\"str\", \"value\"=val)\n                            elif aspec.type == \"strlist\":\n                                newval = []\n                                if akey in res.options:\n                                    curlist = res.options[akey].value\n                                    if isinstance(curlist, list):\n                                        newval = curlist\n                                newval.append(val)\n                                res.options[akey] = (\"type\"=\"strlist\", \"value\"=newval)\n                            processed_any = True\n                            break  # Exit loop after processing value\n                    else:\n                        # Unknown short option, collect for later\n                        unknown_chars.append(short_char)\n\n                # If we have unknown chars, add them to rest as separate arguments\n                if len(unknown_chars) > 0:\n                    if len(unknown_chars) == 1:\n                        rest.append(\"-\" + unknown_chars[0])\n                    else:\n                        rest.append(\"-\" + \"\".join(unknown_chars))\n\n                # If no known options were processed and we have unknowns,\n                # it means the entire arg was unknown\n                if not processed_any and len(unknown_chars) > 0:\n                    # We already added the reconstructed unknown args above\n                    pass\n            else:\n                if arg in self.cmds:\n                    # We found a sub-command, store which one but continue\n                    # parsing the rest of the options. Make sure not to set\n                    # pass rest of args to subparser for command\n                    if cmd_parser is None:\n                        cmd = self.cmds[arg]\n                        res.cmd = cmd.fn\n                        res.cmd_parser = cmd.parser\n                        cmd_parser = cmd.parser\n                    else:\n                        rest.append(arg)\n\n                else:\n                    rest.append(arg)\n\n        # Run sub-command parser\n        if cmd_parser is not None:\n            #print(self, \": cmd found, invoking cmd parser with\", rest)\n            res, posargs = cmd_parser._parse_and_consume(rest, res, prog=self.prog + \" \" + cmd_parser.cmd)\n            #print(self, \": cmd parser done, res:\", res, \"posargs:\", posargs, \"res.cmd:\", res.cmd)\n        else:\n            posargs = rest\n        rest = []\n\n        #print(self, \"Do second loop for optional posargs on rest:\", posargs)\n        for i in range(len(posargs)):\n            arg = posargs[i]\n            if len(self.args) == 0:\n                rest.append(arg)\n            else:\n                posarg = self.args[0]\n                if posarg.nargs == \"?\":\n                    res.options[posarg.name] = (\"type\"=\"str\", \"value\"=arg)\n                    self.args.pop(0)\n                elif posarg.nargs == \"+\":\n                    newval = []\n                    if posarg.name in res.options:\n                        curlist = res.options[posarg.name].value\n                        if isinstance(curlist, list):\n                            newval = curlist\n                    newval.append(arg)\n                    res.options[posarg.name] = (\"type\"=\"strlist\", \"value\"=newval)\n                    remaining_posargs = len(self.args) - 1\n                    if len(posargs)-(i+1) == remaining_posargs:\n                        self.args.pop(0)\n\n        return res, rest\n"
  },
  {
    "path": "base/src/base64.act",
    "content": "def encode(data: bytes) -> bytes:\n    NotImplemented\n\ndef decode(data: bytes) -> bytes:\n    NotImplemented\n"
  },
  {
    "path": "base/src/base64.ext.c",
    "content": "void base64Q___ext_init__() {}\n"
  },
  {
    "path": "base/src/buildy.act",
    "content": "\"\"\"Buildy stuff\n\nOur projects have a built.act and it collides with this module if it would be\ncalled just 'build', so it's buildy for buildy stuff.\n\"\"\"\n\nimport file\nimport json\nimport re\n\nclass BuildSpecError(ValueError):\n    pass\n\ndef zig_safe_name(name: str) -> str:\n    m = re.match(r\"^[a-zA-Z][a-zA-Z0-9_]*$\", name)\n    if m is None:\n        raise BuildSpecError(f\"Invalid dependency name '{name}', must start with a letter and only contain letters, numbers and underscores\")\n    return name\n\n\nclass BuildSpec(object):\n    \"\"\"Build configuration, the content of Build.act\n\n    - name is the project name\n    - description is a human-readable project description (optional)\n    - dependencies are dependencies on other Acton projects\n    - zig_dependencies are dependencies on Zig projects, which could in turn be\n      Zig, C or C++ libraries that get linked in with the project\n    - fingerprint identifies the project lineage\n    \"\"\"\n    name: str\n    description: ?str\n    dependencies: dict[str, PkgDependency]\n    zig_dependencies: dict[str, ZigDependency]\n    # Acton-managed package fingerprint (string, e.g. \"0x1234abcd...\")\n    fingerprint: str\n\n    def __init__(self, name: str, fingerprint: str, description: ?str=None, dependencies: dict[str, PkgDependency]={}, zig_dependencies: dict[str, ZigDependency]={}):\n        self.name = name\n        self.fingerprint = fingerprint\n        self.description = description\n        self.dependencies = dependencies\n        self.zig_dependencies = zig_dependencies\n\n    @staticmethod\n    def from_json(data: str):\n        jd = json.decode(data)\n        name = \"\"\n        has_name = False\n        description = None\n        new_dependencies = {}\n        new_zig_dependencies = {}\n        fingerprint = \"\"\n        has_fingerprint = False\n        if isinstance(jd, dict):\n            for key, value in jd.items():\n                if isinstance(key, str):\n                    if key == \"name\":\n                        if value is None:\n                            has_name = False\n                        elif isinstance(value, str):\n                            name = value\n                            has_name = True\n                        else:\n                            raise ValueError(\"Invalid build spec JSON, name should be a string\")\n                    elif key == \"description\":\n                        if value is None:\n                            description = None\n                        elif isinstance(value, str):\n                            description = value\n                        else:\n                            raise ValueError(\"Invalid build spec JSON, description should be a string\")\n                    elif key == \"dependencies\":\n                        if value is None:\n                            new_dependencies = {}\n                        elif isinstance(value, dict):\n                            for dep_name, dep_attrs in value.items():\n                                if isinstance(dep_name, str) and isinstance(dep_attrs, dict):\n                                    dep = PkgDependency.from_json(dep_name, dep_attrs)\n                                    new_dependencies[dep_name] = dep\n                                else:\n                                    raise ValueError(\"Invalid build spec JSON, dependencies should be a dict\")\n                        else:\n                            raise ValueError(\"Invalid build spec JSON, dependencies should be a dict\")\n                    elif key == \"zig_dependencies\":\n                        if value is None:\n                            new_zig_dependencies = {}\n                        elif isinstance(value, dict):\n                            for dep_name, dep_attrs in value.items():\n                                if isinstance(dep_name, str) and isinstance(dep_attrs, dict):\n                                    dep = ZigDependency.from_json(dep_name, dep_attrs)\n                                    new_zig_dependencies[dep_name] = dep\n                                else:\n                                    raise ValueError(\"Invalid build spec JSON, zig_dependencies should be a dict\")\n                        else:\n                            raise ValueError(\"Invalid build spec JSON, zig_dependencies should be a dict\")\n                    elif key == \"fingerprint\":\n                        if value is None:\n                            has_fingerprint = False\n                        elif isinstance(value, str):\n                            fingerprint = value\n                            has_fingerprint = True\n                        else:\n                            raise ValueError(\"Invalid build spec JSON, fingerprint should be a string like 0xdeadbeef...\")\n                    else:\n                        raise ValueError(f\"Invalid build spec JSON, unknown key '{key}'\")\n                else:\n                    raise ValueError(\"Invalid build spec JSON, non-string key found in top level dict\")\n\n            if not has_name:\n                raise ValueError(\"Invalid build spec JSON, name is required\")\n            if not has_fingerprint:\n                raise ValueError(\"Invalid build spec JSON, fingerprint is required\")\n            return BuildSpec(name, fingerprint, description, new_dependencies, new_zig_dependencies)\n        raise ValueError(\"Invalid build spec JSON, top level should be a dict\")\n\n    def to_json(self) -> str:\n        res_deps = {}\n        res_zigdeps = {}\n        for dep_name, dep in self.dependencies.items():\n            res_deps[dep_name] = dep.to_json()\n        for dep_name, dep in self.zig_dependencies.items():\n            res_zigdeps[dep_name] = dep.to_json()\n        res = {\n            \"name\": self.name,\n            \"fingerprint\": self.fingerprint,\n            \"dependencies\": res_deps,\n            \"zig_dependencies\": res_zigdeps,\n        }\n        description = self.description\n        if description is not None:\n            res[\"description\"] = description\n        return json.encode(res, pretty=True)\n\ndef extract_fingerprint(zon_text: str) -> ?str:\n    for line in zon_text.split(\"\\n\"):\n        sline = line.strip()\n        if sline.startswith(\".fingerprint\"):\n            parts = sline.split(\"=\", 1)\n            if len(parts) == 2:\n                value = parts[1].strip().rstrip(\",\")\n                if re.match(r\"^0x[0-9a-fA-F]+$\", value) is not None and value != \"0xacedf00dacedf00d\":\n                    return value\n    return None\n\nclass Dependency(object):\n    name: str\n    url: ?str\n    hash: ?str\n    path: ?str\n    repo_url: ?str\n    repo_ref: ?str\n\nclass PkgDependency(Dependency):\n\n    def __init__(self, name: str, url: ?str, hash: ?str, path: ?str, repo_url: ?str, repo_ref: ?str):\n        if path is not None and url is not None:\n            raise ValueError(f\"Dependency '{name}' has both path and url set. Set only path or url. You can override path for a dep, e.g.: acton build --dep {name}={path}\")\n        self.name = zig_safe_name(name)\n        self.url = url\n        self.hash = hash\n        self.path = path\n        self.repo_url = repo_url\n        self.repo_ref = repo_ref\n\n    @staticmethod\n    def from_json(dep_name, data: dict[str, str]):\n        dep_url = None\n        dep_hash = None\n        dep_path = None\n        dep_repo_url = None\n        dep_repo_ref = None\n        for key, value in data.items():\n            if key == \"url\":\n                data_url = data[\"url\"]\n                if isinstance(data_url, str):\n                    dep_url = data_url\n            elif key == \"hash\":\n                data_hash = data[\"hash\"]\n                if isinstance(data_hash, str):\n                    dep_hash = data_hash\n            elif key == \"path\":\n                data_path = data[\"path\"]\n                if isinstance(data_path, str):\n                    dep_path = data_path\n            elif key == \"repo_url\":\n                data_repo_url = data[\"repo_url\"]\n                if isinstance(data_repo_url, str):\n                    dep_repo_url = data_repo_url\n            elif key == \"repo_ref\":\n                data_repo_ref = data[\"repo_ref\"]\n                if isinstance(data_repo_ref, str):\n                    dep_repo_ref = data_repo_ref\n            else:\n                raise ValueError(f\"Invalid build spec JSON, unknown key '{key}' in dependency '{dep_name}'\")\n        return PkgDependency(dep_name, dep_url, dep_hash, dep_path, dep_repo_url, dep_repo_ref)\n\n    def to_json(self) -> dict[str, str]:\n        res = {}\n        repo_url = self.repo_url\n        if repo_url is not None:\n            res[\"repo_url\"] = repo_url\n        repo_ref = self.repo_ref\n        if repo_ref is not None:\n            res[\"repo_ref\"] = repo_ref\n        url = self.url\n        if url is not None:\n            res[\"url\"] = url\n        hash = self.hash\n        if hash is not None:\n            res[\"hash\"] = hash\n        path = self.path\n        if path is not None:\n            res[\"path\"] = path\n        return res\n\n    def to_zon(self, deps_path) -> str:\n        path = \"\"\n        self_path = self.path\n        if self_path is not None:\n            path = self_path\n        else:\n            dep_hash = self.hash\n            if dep_hash is not None:\n                path = file.join_path([deps_path, f\"{self.name}-{dep_hash}\"])\n            else:\n                raise ValueError(f\"Invalid build spec JSON, dependency '{self.name}' has no path or hash\")\n        return \"\"\"        .%s = .{{\n            .path = \"%s\"\n        }},\n\"\"\" % (\n            self.name,\n            path\n        )\n\n\nclass ZigDependency(Dependency):\n    options: dict[str, str]\n    artifacts: list[str]\n\n    def __init__(self, name: str, url: ?str, hash: ?str, path: ?str, options: dict[str, str], artifacts: list[str]):\n        self.name = zig_safe_name(name)\n        self.url = url\n        self.hash = hash\n        self.path = path\n        self.repo_url = None\n        self.repo_ref = None\n        self.options = options\n        self.artifacts = artifacts\n\n    @staticmethod\n    def from_json(dep_name, data: dict[str, str]):\n        dep_url: ?str = None\n        dep_hash: ?str = None\n        dep_path: ?str = None\n        dep_options: dict[str, str] = {}\n        dep_artifacts: list[str] = []\n\n        for key, value in data.items():\n            if key == \"url\":\n                data_url = value\n                if isinstance(data_url, str):\n                    dep_url = data_url\n            elif key == \"hash\":\n                data_hash = value\n                if isinstance(data_hash, str):\n                    dep_hash = data_hash\n            elif key == \"path\":\n                data_path = value\n                if isinstance(data_path, str):\n                    dep_path = data_path\n            elif key == \"options\":\n                data_options = value\n                if isinstance(data_options, dict):\n                    dep_options = data_options\n            elif key == \"artifacts\":\n                data_artifacts = value\n                if isinstance(data_artifacts, list):\n                    dep_artifacts = data_artifacts\n            else:\n                raise ValueError(f\"Invalid build spec JSON, unknown key '{key}' in dependency '{dep_name}'\")\n        return ZigDependency(dep_name, dep_url, dep_hash, dep_path, dep_options, dep_artifacts)\n\n    def to_json(self) -> dict[str, value]:\n        res = {}\n\n        url = self.url\n        if url is not None:\n            res[\"url\"] = url\n\n        hash = self.hash\n        if hash is not None:\n            res[\"hash\"] = hash\n\n        path = self.path\n        if path is not None:\n            res[\"path\"] = path\n\n        options = self.options\n        if len(options) > 0:\n            res[\"options\"] = options\n\n        artifacts = self.artifacts\n        if len(artifacts) > 0:\n            res[\"artifacts\"] = artifacts\n\n        return res\n\n    def to_zon(self) -> str:\n        url = self.url\n        hash = self.hash\n        self_path = self.path\n        if self_path is not None:\n            return \"\"\"        .%s = .{{\n                .path = \"%s\",\n            }},\n    \"\"\" % (self.name, self_path)\n\n        return \"\"\"        .%s = .{{\n            .url = \"%s\",\n            .hash = \"%s\",\n        }},\n\"\"\" % (\n            self.name,\n            url if url is not None else \"\",\n            hash if hash is not None else \"\",\n        )\n\ndef gen_buildzig(template: str, build_config: BuildSpec) -> str:\n    deps_defs = \"\"\n    liblink_lines = \"\"\n    exelink_lines = \"\"\n\n    for dep in build_config.dependencies.values():\n        deps_defs += \"    const actdep_\" + dep.name + \" = b.dependency(\\\"\" + dep.name + \"\\\", .{{\\n\"\n        deps_defs += \"        .target = target,\\n\"\n        deps_defs += \"        .optimize = optimize,\\n\"\n        deps_defs += \"    }});\\n\"\n        liblink_lines += \"    libActonProject.linkLibrary(actdep_\" + dep.name + \".artifact(\\\"ActonProject\\\"));\\n\"\n        exelink_lines += \"            executable.linkLibrary(actdep_\" + dep.name + \".artifact(\\\"ActonProject\\\"));\\n\"\n\n    for dep_name, dep in build_config.zig_dependencies.items():\n        if len(dep.artifacts) > 0:\n            deps_defs += \"    const dep_\" + dep.name + \" = b.dependency(\\\"\" + dep.name + \"\\\", .{{\\n\"\n            deps_defs += \"        .target = target,\\n\"\n            deps_defs += \"        .optimize = optimize,\\n\"\n            for key, value in dep.options.items():\n                deps_defs += \"        .\" + key + \" = \" + value + \",\\n\"\n            deps_defs += \"    }});\\n\"\n            for artifact in dep.artifacts:\n                liblink_lines += \"    libActonProject.linkLibrary(dep_\" + dep.name + \".artifact(\\\"\" + artifact + \"\\\"));\\n\"\n                exelink_lines += \"            executable.linkLibrary(dep_\" + dep.name + \".artifact(\\\"\" + artifact + \"\\\"));\\n\"\n\n    res = [\n        \"// AUTOMATICALLY GENERATED BY ACTON BUILD SYSTEM\",\n        \"// DO NOT EDIT, CHANGES WILL BE OVERWRITTEN!!!!!\",\n        \"\",\n    ]\n    for line in template.split(\"\\n\"):\n        res.append(line)\n        sline = line.strip()\n        if sline == \"// Dependencies from Build.act\":\n            res.append(deps_defs)\n        if sline == \"// lib: link with dependencies / get headers from Build.act\":\n            res.append(liblink_lines)\n        if sline == \"// exe: link with dependencies / get headers from Build.act\":\n            res.append(exelink_lines)\n\n    return \"\\n\".join(res)\n\ndef gen_buildzigzon(template: str, build_config: BuildSpec, relative_syspath: str, deps_path: str) -> str:\n    deps = \"\"\n    for dep_name, dep in build_config.dependencies.items():\n        deps += dep.to_zon(deps_path)\n    for dep_name, dep in build_config.zig_dependencies.items():\n        deps += dep.to_zon()\n\n    res = [\n        \"// AUTOMATICALLY GENERATED BY ACTON BUILD SYSTEM\",\n        \"// DO NOT EDIT, CHANGES WILL BE OVERWRITTEN!!!!!\",\n        \"\",\n    ]\n    for line in template.split(\"\\n\"):\n        line = line.replace(r\"{{syspath}}\", relative_syspath)\n        if \"{{fingerprint}}\" in line:\n            line = line.replace(r\"{{fingerprint}}\", str(build_config.fingerprint))\n        res.append(line)\n        sline = line.strip()\n        if sline == \"// Dependencies from Build.act\":\n            res.append(deps)\n\n    return \"\\n\".join(res)\n"
  },
  {
    "path": "base/src/crypto/hash/md5.act",
    "content": "class Hasher(object):\n    _hasher: u64\n    def __init__(self):\n        \"\"\"Initialize a new MD5 hashing context\n        \"\"\"\n        self._hasher = 0\n        self._init()\n\n    def _init(self):\n        \"\"\"C function to reach out to Zig code\"\"\"\n        NotImplemented\n\n    def update(self, data: bytes) -> None:\n        \"\"\"Update the hasher state with the given chunk of data\"\"\"\n        NotImplemented\n\n    def finalize(self) -> bytes:\n        \"\"\"Finalize the hash and return the 16-byte MD5 digest as bytes\n        After final() is called, this instance should not be used again.\n        \"\"\"\n        NotImplemented\n\ndef hash(data: bytes) -> bytes:\n    \"\"\"Compute and return the MD5 digest of the given data\"\"\"\n    m = Hasher()\n    m.update(data)\n    return m.finalize()\n"
  },
  {
    "path": "base/src/crypto/hash/md5.ext.c",
    "content": "void cryptoQ_hashQ_md5Q___ext_init__() {}\n\nvoid *zig_crypto_hash_md5_init();\nvoid *zig_crypto_hash_md5_update(void *hasher, B_bytes data);\nvoid *zig_crypto_hash_md5_finalize(void *hasher, B_bytes output);\n\nB_NoneType cryptoQ_hashQ_md5Q_HasherD__init (cryptoQ_hashQ_md5Q_Hasher self) {\n    self->_hasher = zig_crypto_hash_md5_init();\n    return B_None;\n}\nB_NoneType cryptoQ_hashQ_md5Q_HasherD_update (cryptoQ_hashQ_md5Q_Hasher self, B_bytes data) {\n    zig_crypto_hash_md5_update(self->_hasher, data);\n    return B_None;\n}\nB_bytes cryptoQ_hashQ_md5Q_HasherD_finalize (cryptoQ_hashQ_md5Q_Hasher self) {\n    B_bytes output = to$bytes(\"1234567890abcdef\");\n    zig_crypto_hash_md5_finalize(self->_hasher, output);\n    return output;\n}\n"
  },
  {
    "path": "base/src/diff.act",
    "content": "import term\n\n# Implementation of Myers-inspired diff algorithm, which is efficient and produces\n# good results for typical text file differences.\n# This algorithm uses a divide-and-conquer approach with features from Myers and\n# Patience diff algorithms to identify changes between two sequences.\n# The algorithm focuses on finding common sequences and anchors to produce\n# minimal, readable diffs.\n# Myers algorithm is documented at: http://blog.robertelder.org/diff-algorithm/\n\ndef myers_diff(e: list[str], f: list[str], i: int = 0, j: int = 0) -> list[Op]:\n    \"\"\"\n    Myers-inspired diff algorithm implementation - finds the minimal edit script between two sequences.\n\n    This algorithm combines elements of Myers diff and Patience diff to efficiently find\n    differences between sequences. It uses a divide-and-conquer approach that:\n    1. Quickly identifies common prefixes and suffixes\n    2. Finds matching sections in the middle (\"middle snake\")\n    3. Uses unique lines as anchors to align content\n    4. Handles special cases efficiently (empty sequences, single elements)\n\n    The implementation creates Keep/Insert/Delete operations directly, compatible with the\n    unified diff format.\n\n    Args:\n        e: First sequence (old)\n        f: Second sequence (new)\n        i: Starting position in first sequence (used in recursion)\n        j: Starting position in second sequence (used in recursion)\n\n    Returns:\n        List of diff operations (Keep, Insert, Delete) representing the minimal edit script\n    \"\"\"\n    # Handle edge cases first\n    if len(e) == 0:\n        # All lines in f were inserted\n        result = []\n        for n in range(0, len(f)):\n            result.append(Insert(f[n], j + n))\n        return result\n\n    if len(f) == 0:\n        # All lines in e were deleted\n        result = []\n        for n in range(0, len(e)):\n            result.append(Delete(e[n], i + n))\n        return result\n\n    # Find the longest common prefix\n    prefix_len = 0\n    while prefix_len < len(e) and prefix_len < len(f) and e[prefix_len] == f[prefix_len]:\n        prefix_len += 1\n\n    # Generate Keep operations for the common prefix\n    prefix_ops = []\n    for n in range(0, prefix_len):\n        prefix_ops.append(Keep(e[n], i + n, j + n))\n\n    # Find the longest common suffix\n    suffix_len = 0\n    while suffix_len < len(e) - prefix_len and suffix_len < len(f) - prefix_len and e[len(e) - 1 - suffix_len] == f[len(f) - 1 - suffix_len]:\n        suffix_len += 1\n\n    # Generate Keep operations for the common suffix\n    suffix_ops = []\n    for n in range(0, suffix_len):\n        old_idx = len(e) - suffix_len + n\n        new_idx = len(f) - suffix_len + n\n        suffix_ops.append(Keep(e[old_idx], i + old_idx, j + new_idx))\n\n    # If we have a common prefix or suffix, recursively diff the middle part\n    if prefix_len > 0 or suffix_len > 0:\n        middle_ops = myers_diff(\n            e[prefix_len:len(e)-suffix_len],\n            f[prefix_len:len(f)-suffix_len],\n            i + prefix_len,\n            j + prefix_len\n        )\n        return prefix_ops + middle_ops + suffix_ops\n\n    # If e is just one element and f has multiple elements, delete e and insert all of f\n    if len(e) == 1 and len(f) > 1:\n        result = [Delete(e[0], i)]\n        for n in range(0, len(f)):\n            result.append(Insert(f[n], j + n))\n        return result\n\n    # If f is just one element and e has multiple elements, delete all of e and insert f\n    if len(f) == 1 and len(e) > 1:\n        result = []\n        for n in range(0, len(e)):\n            result.append(Delete(e[n], i + n))\n        result.append(Insert(f[0], j))\n        return result\n\n    # If both have just one element, compare them\n    if len(e) == 1 and len(f) == 1:\n        if e[0] == f[0]:\n            return [Keep(e[0], i, j)]\n        else:\n            return [Delete(e[0], i), Insert(f[0], j)]\n\n    # Divide and conquer: find the middle snake\n    middle = len(e) // 2\n\n    # Find best matching line in f for the middle of e\n    best_match_pos = -1\n    best_match_len = -1\n\n    for pos in range(0, len(f)):\n        match_len = 0\n        while middle + match_len < len(e) and pos + match_len < len(f) and e[middle + match_len] == f[pos + match_len]:\n            match_len += 1\n\n        if match_len > best_match_len:\n            best_match_len = match_len\n            best_match_pos = pos\n\n    if best_match_len > 0:\n        # Generate Keep operations for the matching segment\n        match_ops = []\n        for n in range(0, best_match_len):\n            match_ops.append(Keep(e[middle + n], i + middle + n, j + best_match_pos + n))\n\n        # Recursively diff the segments before and after the match\n        before_ops = myers_diff(e[0:middle], f[0:best_match_pos], i, j)\n        after_ops = myers_diff(\n            e[middle+best_match_len:],\n            f[best_match_pos+best_match_len:],\n            i + middle + best_match_len,\n            j + best_match_pos + best_match_len\n        )\n\n        return before_ops + match_ops + after_ops\n\n    # No good match in the middle, use Patience diff approach\n    # Try to identify unique lines and align around them\n    unique_lines_e = {}\n    for idx, line in enumerate(e):\n        if line not in unique_lines_e:\n            unique_lines_e[line] = []\n        unique_lines_e[line].append(idx)\n\n    unique_lines_f = {}\n    for idx, line in enumerate(f):\n        if line not in unique_lines_f:\n            unique_lines_f[line] = []\n        unique_lines_f[line].append(idx)\n\n    # Find lines that appear exactly once in both sequences\n    anchors: list[(int, int)] = []\n\n    for line, e_indices in unique_lines_e.items():\n        if len(e_indices) == 1 and line in unique_lines_f and len(unique_lines_f[line]) == 1:\n            e_idx = e_indices[0]\n            f_idx = unique_lines_f[line][0]\n            anchors.append((e_idx, f_idx))\n\n    # Sort anchors by position in e\n    # We'll do a simple bubble sort that uses a temporary variable for the swap\n    sorted_anchors = list(anchors)  # Make a copy\n    for i in range(len(sorted_anchors)):\n        for j in range(len(sorted_anchors) - i - 1):\n            if sorted_anchors[j].0 > sorted_anchors[j+1].0:\n                # Swap using a temporary variable\n                temp = sorted_anchors[j]\n                sorted_anchors[j] = sorted_anchors[j+1]\n                sorted_anchors[j+1] = temp\n\n    # Extract sorted indices\n    sorted_e_indices = []\n    sorted_f_indices = []\n    for anchor in sorted_anchors:\n        sorted_e_indices.append(anchor.0)\n        sorted_f_indices.append(anchor.1)\n\n    if len(sorted_e_indices) > 0:\n        # We found unique matching lines, use them as anchors\n        result = []\n\n        # Initialize with starting positions\n        last_e = 0\n        last_f = 0\n\n        for idx in range(len(sorted_e_indices)):\n            e_idx = sorted_e_indices[idx]\n            f_idx = sorted_f_indices[idx]\n\n            # Recursively diff the segment before this anchor\n            if e_idx > last_e or f_idx > last_f:\n                before_ops = myers_diff(e[last_e:e_idx], f[last_f:f_idx], i + last_e, j + last_f)\n                result.extend(before_ops)\n\n            # Add the anchor line as a Keep operation\n            result.append(Keep(e[e_idx], i + e_idx, j + f_idx))\n\n            # Update last positions\n            last_e = e_idx + 1\n            last_f = f_idx + 1\n\n        # Process the last segment after the last anchor\n        if last_e < len(e) or last_f < len(f):\n            after_ops = myers_diff(e[last_e:], f[last_f:], i + last_e, j + last_f)\n            result.extend(after_ops)\n\n        return result\n\n    # Fall back to simple edit script if no anchors found\n    result = []\n    for n in range(0, len(e)):\n        result.append(Delete(e[n], i + n))\n    for n in range(0, len(f)):\n        result.append(Insert(f[n], j + n))\n    return result\n\n# Base operation class\nclass Op:\n    def __init__(self):\n        pass\n\n    def format_with_color(self) -> str:\n        return \"\"\n\nclass Gap(Op):\n    def __init__(self):\n        pass\n\n    def __str__(self) -> str:\n        return \"...\"\n\n    def format_with_color(self) -> str:\n        return term.grey20 + \"...\" + term.normal\n\n# Keep operation class (for context lines)\nclass Keep(Op):\n    content: str\n    index_old: int\n    index_new: int\n\n    def __init__(self, content: str, index_old: int, index_new: int):\n        self.content = content\n        self.index_old = index_old\n        self.index_new = index_new\n\n    def __str__(self) -> str:\n        return f\" {self.content}\"\n\n    def format_with_color(self) -> str:\n        return term.grey20 + str(self) + term.normal\n\n# Delete operation class\nclass Delete(Op):\n    content: str\n    index_old: int\n\n    def __init__(self, content: str, index_old: int):\n        self.content = content\n        self.index_old = index_old\n\n    def __str__(self) -> str:\n        return f\"-{self.content}\"\n\n    def format_with_color(self) -> str:\n        return term.red + str(self) + term.normal\n\n# Insert operation class\nclass Insert(Op):\n    content: str\n    index_new: int\n\n    def __init__(self, content: str, index_new: int):\n        self.content = content\n        self.index_new = index_new\n\n    def __str__(self) -> str:\n        return f\"+{self.content}\"\n\n    def format_with_color(self) -> str:\n        return term.green + str(self) + term.normal\n\ndef filter_operations_with_context(operations: list[Op], context_lines: int) -> list[Op]:\n    \"\"\"\n    Filter operations to only include changes and their surrounding context.\n\n    Args:\n        operations: List of diff operations\n        context_lines: Number of unchanged lines to include around each change\n\n    Returns:\n        Filtered list of operations with only changes and their context\n    \"\"\"\n    if context_lines < 0:\n        # Show all context\n        return operations\n\n    # Find the indices of operations with changes (deletes and inserts)\n    change_indices = []\n    for i in range(len(operations)):\n        if isinstance(operations[i], Delete) or isinstance(operations[i], Insert):\n            change_indices.append(i)\n\n    # If no changes, return empty list\n    if len(change_indices) == 0:\n        return []\n\n    # Determine which lines should be included\n    include_line = [False] * len(operations)\n\n    # Mark lines within context_lines of any change\n    for i in range(len(operations)):\n        for change_idx in change_indices:\n            if abs(i - change_idx) <= context_lines:\n                include_line[i] = True\n                break\n\n    # Create filtered list\n    filtered_ops = []\n\n    # Add operations with Gap markers for gaps\n    in_chunk = False\n    for i in range(len(operations)):\n        if include_line[i]:\n            # If starting a new chunk after a gap, add a marker line\n            if not in_chunk and i > 0 and len(filtered_ops) > 0:\n                filtered_ops.append(Gap())\n\n            filtered_ops.append(operations[i])\n            in_chunk = True\n        else:\n            in_chunk = False\n\n    return filtered_ops\n\ndef generate_chunk_header(chunk_ops: list[Op]) -> str:\n    \"\"\"\n    Generate a unified diff chunk header showing line numbers.\n\n    Format: @@ -<old_start>,<old_count> +<new_start>,<new_count> @@\n\n    Args:\n        chunk_ops: List of operations for this chunk\n\n    Returns:\n        Chunk header string in unified diff format\n    \"\"\"\n    # Find line numbers for old and new files\n    old_start = -1\n    old_count = 0\n    new_start = -1\n    new_count = 0\n\n    for op in chunk_ops:\n        if isinstance(op, Gap):\n            continue\n\n        if isinstance(op, Keep):\n            # Line exists in both files\n            if old_start == -1:\n                old_start = op.index_old\n            if new_start == -1:\n                new_start = op.index_new\n            old_count += 1\n            new_count += 1\n        elif isinstance(op, Delete):\n            # Line only exists in old file\n            if old_start == -1:\n                old_start = op.index_old\n            old_count += 1\n        elif isinstance(op, Insert):\n            # Line only exists in new file\n            if new_start == -1:\n                new_start = op.index_new\n            new_count += 1\n\n    # Default to 1 if no valid index found (shouldn't happen)\n    if old_start == -1:\n        old_start = 0\n    if new_start == -1:\n        new_start = 0\n\n    # Line numbers in display are 1-based\n    return f\"@@ -{old_start+1},{old_count} +{new_start+1},{new_count} @@\"\n\ndef find_chunks(operations: list[Op]) -> list[list[Op]]:\n    \"\"\"\n    Split operations into chunks, using Gap operations as dividers.\n\n    Args:\n        operations: List of diff operations, potentially including Gap markers\n\n    Returns:\n        List of operation chunks, where each chunk is a list of operations\n    \"\"\"\n    chunks = []\n    current_chunk = []\n\n    for op in operations:\n        if isinstance(op, Gap):\n            # End the current chunk if it has operations\n            if len(current_chunk) > 0:\n                chunks.append(current_chunk)\n                current_chunk = []\n        else:\n            # Add to the current chunk\n            current_chunk.append(op)\n\n    # Add the last chunk if it exists\n    if len(current_chunk) > 0:\n        chunks.append(current_chunk)\n\n    return chunks\n\ndef diff(old_text: str, new_text: str, color=False, context_lines=3) -> str:\n    \"\"\" Generate a unified diff between two text strings\n\n    Uses the Myers diff algorithm.\n\n    Args:\n        old_text: Original text content\n        new_text: New text content\n        color: Whether to add terminal color codes to the output (default False)\n        context_lines: Number of unchanged lines to show around each change\n                       (default 3 lines), use -1 for showing all lines\n\n    Returns:\n        Empty string if texts are identical, otherwise returns a unified diff.\n        If context_lines is specified, only shows that many unchanged lines around changes.\n    \"\"\"\n    if old_text == new_text:\n        return \"\"\n\n    old_lines = old_text.splitlines(True)\n    new_lines = new_text.splitlines(True)\n\n    # Handle case where last line doesn't have newline\n    if len(old_lines) > 0 and old_text[-1] != '\\n':\n        old_lines[-1] = old_lines[-1] + '\\n'\n    if len(new_lines) > 0 and new_text[-1] != '\\n':\n        new_lines[-1] = new_lines[-1] + '\\n'\n\n    operations = myers_diff(old_lines, new_lines)\n\n    if context_lines >= 0:\n        operations = filter_operations_with_context(operations, context_lines)\n\n    if len(operations) == 0:\n        return \"\"\n\n    result = []\n\n    # Skip headers only when context_lines=-1 (showing full file)\n    # We're going to simplify our approach here\n    skip_headers = context_lines < 0\n\n    for chunk in find_chunks(operations):\n        if not skip_headers:\n            # Generate and add chunk header\n            header = generate_chunk_header(chunk)\n            if color:\n                result.append(term.grey20 + header + \"\\n\" + term.normal)\n            else:\n                result.append(header + \"\\n\")\n\n        # Add the operations for this chunk\n        for op in chunk:\n            if color:\n                result.append(op.format_with_color())\n            else:\n                result.append(str(op))\n\n    return \"\".join(result).rstrip()\n"
  },
  {
    "path": "base/src/file.act",
    "content": "class FileCap():\n    def __init__(self, cap: WorldCap):\n        pass\n\nclass ReadFileCap():\n    def __init__(self, cap: FileCap):\n        pass\n\nclass WriteFileCap():\n    def __init__(self, cap: FileCap):\n        pass\n\ndef get_relative_path(target_path: str, from_path: str) -> str:\n    \"\"\"\n    Compute the relative path from one absolute path to another.\n\n    Args:\n        target_path: The absolute path we want to reach\n        from_path: The absolute path we're starting from\n\n    Returns:\n        A relative path that will reach target_path from from_path\n\n    Raises:\n        ValueError: If either path is not absolute (doesn't start with '/')\n    \"\"\"\n    # Validate inputs are absolute paths\n    if not target_path.startswith('/') or not from_path.startswith('/'):\n        raise ValueError(\"Both paths must be absolute (start with '/')\")\n\n    # Split paths into components and remove empty strings\n    target_parts = []\n    for p in target_path.split('/'):\n        if p:\n            target_parts.append(p)\n\n    from_parts = []\n    for p in from_path.split('/'):\n        if p:\n            from_parts.append(p)\n\n    # Find common prefix\n    common_length = 0\n    for t, f in zip(target_parts, from_parts):\n        if t != f:\n            break\n        common_length += 1\n\n    # Build the relative path\n    # First go up as many levels as needed\n    up_levels = len(from_parts) - common_length\n    up_path = []\n    for _ in range(up_levels):\n        up_path.append('..')\n\n    # Then add the path to the target\n    down_path = []\n    for i in range(common_length, len(target_parts)):\n        down_path.append(target_parts[i])\n\n    # Combine the parts\n    relative_parts = []\n    relative_parts.extend(up_path)\n    relative_parts.extend(down_path)\n\n    # Handle special case where paths are identical\n    if not relative_parts:\n        return '.'\n\n    # Join with forward slashes\n    return '/'.join(relative_parts)\n\n\ndef resolve_relative_path(start_dir: str, rel_path: str) -> str:\n    \"\"\"\n    Resolve a relative path against a working directory to get an absolute path.\n\n    Args:\n        start_dir: Start directory (must be absolute)\n        rel_path: Relative path to resolve\n\n    Returns:\n        The resulting absolute path\n\n    Raises:\n        ValueError: If start_dir is not absolute or if rel_path is absolute\n    \"\"\"\n    if not start_dir.startswith('/'):\n        raise ValueError(\"Working directory must be absolute (start with '/')\")\n    if rel_path.startswith('/'):\n        # Relative path is already absolute\n        return rel_path\n\n    # Handle empty or current directory case\n    if not rel_path or rel_path == '.':\n        return start_dir\n\n    # Split both paths into components\n    sd_parts = []\n    for p in start_dir.split('/'):\n        if p:\n            sd_parts.append(p)\n\n    rel_parts = []\n    for p in rel_path.split('/'):\n        if p != '.':\n            rel_parts.append(p)\n\n    # Start with the working directory components\n    result_parts = []\n    result_parts.extend(sd_parts)\n\n    # Process each component of the relative path\n    for part in rel_parts:\n        if part == '..':\n            if not result_parts:\n                raise ValueError(\"Relative path goes above root directory\")\n            result_parts.pop()\n        else:\n            result_parts.append(part)\n\n    # Construct the final path\n    if not result_parts:\n        return '/'\n    return '/' + '/'.join(result_parts)\n\n\n\nclass FileStat(value):\n    name: str\n    dev: u64\n    mode: u64\n    nlink: u64\n    uid: u64\n    gid: u64\n    rdev: u64\n    ino: u64\n    size: u64\n    blksize: u64\n    blocks: u64\n    flags: u64\n    gen: u64\n    atime: float\n    mtime: float\n    ctime: float\n    birthtime: float\n\n    def __init__(self, name: str, dev: u64, mode: u64, nlink: u64, uid: u64, gid: u64, rdev: u64, ino: u64, size: u64, blksize: u64, blocks: u64, flags: u64, gen: u64, atime: float, mtime: float, ctime: float, birthtime: float):\n        self.name = name\n        self.dev = dev\n        self.mode = mode\n        self.nlink = nlink\n        self.uid = uid\n        self.gid = gid\n        self.rdev = rdev\n        self.ino = ino\n        self.size = size\n        self.blksize = blksize\n        self.blocks = blocks\n        self.flags = flags\n        self.gen = gen\n        self.atime = atime\n        self.mtime = mtime\n        self.ctime = ctime\n        self.birthtime = birthtime\n\n    def is_dir(self) -> bool:\n        \"\"\"Return True if the file is a directory\"\"\"\n        NotImplemented\n\n    def is_file(self) -> bool:\n        \"\"\"Return True if the file is a regular file\"\"\"\n        NotImplemented\n\n    def is_symlink(self) -> bool:\n        \"\"\"Return True if the file is a symbolic link\"\"\"\n        NotImplemented\n\n    def is_block_device(self) -> bool:\n        \"\"\"Return True if the file is a block device\"\"\"\n        NotImplemented\n\n    def is_char_device(self) -> bool:\n        \"\"\"Return True if the file is a character device\"\"\"\n        NotImplemented\n\n    def is_fifo(self) -> bool:\n        \"\"\"Return True if the file is a FIFO\"\"\"\n        NotImplemented\n\n    def is_socket(self) -> bool:\n        \"\"\"Return True if the file is a socket\"\"\"\n        NotImplemented\n\nextension FileStat (Eq):\n    def __eq__(self, other) -> bool:\n        return self.name == other.name and self.dev == other.dev and self.mode == other.mode and self.nlink == other.nlink and self.uid == other.uid and self.gid == other.gid and self.rdev == other.rdev and self.ino == other.ino and self.size == other.size and self.blksize == other.blksize and self.blocks == other.blocks and self.flags == other.flags and self.gen == other.gen and self.atime == other.atime and self.mtime == other.mtime and self.ctime == other.ctime and self.birthtime == other.birthtime\n\ndef join_path(parts: list[str], sep: ?str=None) -> str:\n    \"\"\"Join two paths\"\"\"\n    # TODO: support more than just / as separator based on platform\n    psep = \"/\"\n    if sep is not None:\n        psep = sep\n    return psep.join(parts)\n\n# TODO: refactor into a read-only version and one for writing!?\nactor FS(cap: FileCap):\n    \"\"\"File system operations \"\"\"\n\n    proc def _pin_affinity() -> None:\n        NotImplemented\n    _pin_affinity()\n\n    action def copyfile(src: str, dst: str) -> None:\n        \"\"\"Copy a file\"\"\"\n        NotImplemented\n\n    action def copytree(src: str, dst: str) -> None:\n        \"\"\"Copy a directory tree\"\"\"\n        for entry in listdir(src):\n            s = lstat(join_path([src, entry]))\n            if s.is_dir():\n                mkdir(join_path([dst, entry]))\n                copytree(join_path([src, entry]), join_path([dst, entry]))\n            else:\n                copyfile(join_path([src, entry]), join_path([dst, entry]))\n\n    action def cwd() -> str:\n        \"\"\"Get the current working directory\"\"\"\n        NotImplemented\n\n    action def exepath() -> str:\n        \"\"\"Get the path to the executable\"\"\"\n        NotImplemented\n\n    action def homedir() -> str:\n        \"\"\"Get the home directory\"\"\"\n        NotImplemented\n\n    action def mkdir(filename: str):\n        \"\"\"Make a directory\"\"\"\n        NotImplemented\n\n    action def mktmpdir(prefix: str=\"\") -> str:\n        \"\"\"Make a temporary directory\"\"\"\n        NotImplemented\n\n    action def listdir(path: str) -> list[str]:\n        \"\"\"List directory contents\"\"\"\n        NotImplemented\n\n    action def lstat(filename: str) -> FileStat:\n        \"\"\"Get file status without following symlinks\"\"\"\n        NotImplemented\n\n    action def remove(filename: str) -> None:\n        \"\"\"Remove a file\"\"\"\n        NotImplemented\n\n    action def rmdir(dirname: str) -> None:\n        \"\"\"Remove a directory\"\"\"\n        NotImplemented\n\n    action def rmtree(d: str) -> None:\n        \"\"\"Recursively remove a directory tree\"\"\"\n        try:\n            for entry in listdir(d):\n                try:\n                    s = lstat(d + \"/\" + entry)\n                    if s.is_dir():\n                        rmtree(d + \"/\" + entry)\n                        rmdir(d + \"/\" + entry)\n                    else:\n                        remove(d + \"/\" + entry)\n                except OSError:\n                    # probably a symlink or permission denied\n                    pass\n        except OSError:\n            # dir doesn't exist\n            pass\n\n    action def tmpdir() -> str:\n        \"\"\"Get temporary directory\"\"\"\n        NotImplemented\n\n    action def stat(filename: str) -> FileStat:\n        \"\"\"Get file status\"\"\"\n        NotImplemented\n\n    action def walk(d: str, follow_symlinks: bool=False) -> list[FileStat]:\n        \"\"\"Recursively walk a directory tree\"\"\"\n        # TODO: this should be a generator\n        res = []\n        try:\n            for entry in listdir(d):\n                try:\n                    if follow_symlinks:\n                        s = stat(d + \"/\" + entry)\n                    else:\n                        s = lstat(d + \"/\" + entry)\n                    res.append(s)\n                    if s.is_dir():\n                        res.extend(walk(d + \"/\" + entry))\n                except OSError:\n                    # probably a symlink or permission denied\n                    pass\n        except OSError:\n            # dir doesn't exist\n            pass\n        return res\n\n\nactor ReadFile(cap: ReadFileCap, filename: str, lock=False):\n    \"\"\"Read a file\n    \"\"\"\n    var _fd = -1\n\n    proc def _open_file():\n        \"\"\"C magic\"\"\"\n        NotImplemented\n\n    proc def _lock_file():\n        NotImplemented\n\n    _open_file()\n    if lock:\n        _lock_file()\n\n    action def read() -> bytes:\n        \"\"\"Read content of file\"\"\"\n        NotImplemented\n\n    action def close() -> None:\n        \"\"\"Close file\"\"\"\n        NotImplemented\n\n\nactor WriteFile(cap: WriteFileCap, filename: str, lock=False):\n    \"\"\"Write a file\n    \"\"\"\n    var _fd = -1\n\n    proc def _open_file():\n        \"\"\"C magic\"\"\"\n        NotImplemented\n\n    proc def _lock_file():\n        NotImplemented\n\n    _open_file()\n    if lock:\n        _lock_file()\n\n    action def write(data: bytes) -> None:\n        \"\"\"Write data to file\"\"\"\n        NotImplemented\n\n    action def close() -> None:\n        \"\"\"Close file\"\"\"\n        NotImplemented\n"
  },
  {
    "path": "base/src/file.ext.c",
    "content": "#define GC_THREADS 1\n#include \"gc.h\"\n\n#include <stdio.h>\n#include <string.h>\n#include <sys/file.h>\n\n#include <uv.h>\n#include \"../rts/io.h\"\n#include \"../rts/log.h\"\n#include \"../out/types/file.h\"\n\n\nvoid fileQ___ext_init__() {\n\n}\n\n$R fileQ_FSD__pin_affinityG_local (fileQ_FS self, $Cont c$cont) {\n    pin_actor_affinity();\n    return $R_CONT(c$cont, B_None);\n}\n\n// def is_dir(self) -> bool:\nB_bool fileQ_FileStatD_is_dir (fileQ_FileStat self) {\n    return toB_bool(S_ISDIR(fromB_u64(self->mode)));\n}\n\n// def is_file(self) -> bool:\nB_bool fileQ_FileStatD_is_file (fileQ_FileStat self) {\n    return toB_bool(S_ISREG(fromB_u64(self->mode)));\n}\n\n// def is_symlink(self) -> bool:\nB_bool fileQ_FileStatD_is_symlink (fileQ_FileStat self) {\n#if defined(_WIN32) || defined(_WIN64)\n    // TODO: do better\n    return B_False;\n#else\n    return toB_bool(S_ISLNK(fromB_u64(self->mode)));\n#endif\n}\n\n// def is_block_device(self) -> bool:\nB_bool fileQ_FileStatD_is_block_device (fileQ_FileStat self) {\n    return toB_bool(S_ISBLK(fromB_u64(self->mode)));\n}\n\n// def is_char_device(self) -> bool:\nB_bool fileQ_FileStatD_is_char_device (fileQ_FileStat self) {\n    return toB_bool(S_ISCHR(fromB_u64(self->mode)));\n}\n\n// def is_fifo(self) -> bool:\nB_bool fileQ_FileStatD_is_fifo (fileQ_FileStat self) {\n#if defined(_WIN32) || defined(_WIN64)\n    // TODO: do better\n    return B_False;\n#else\n    return toB_bool(S_ISFIFO(fromB_u64(self->mode)));\n#endif\n}\n\n// def is_socket(self) -> bool:\nB_bool fileQ_FileStatD_is_socket (fileQ_FileStat self) {\n#if defined(_WIN32) || defined(_WIN64)\n    // TODO: do better\n    return B_False;\n#else\n    return toB_bool(S_ISSOCK(fromB_u64(self->mode)));\n#endif\n}\n\n// action def copyfile(src: str, dst: str) -> None:\n$R fileQ_FSD_copyfileG_local (fileQ_FS self, $Cont C_cont, B_str src, B_str dst) {\n    uv_fs_t *req = (uv_fs_t *)acton_malloc(sizeof(uv_fs_t));\n    int r = uv_fs_copyfile(get_uv_loop(), req, (char *)fromB_str(src), (char *)fromB_str(dst), 0, NULL);\n    if (r < 0) {\n        char errmsg[1024] = \"Error copying file: \";\n        uv_strerror_r(r, errmsg + strlen(errmsg), sizeof(errmsg)-strlen(errmsg));\n        uv_fs_req_cleanup(req);\n        log_warn(errmsg);\n        $RAISE(((B_BaseException)B_OSErrorG_new(to$str(errmsg))));\n    }\n    uv_fs_req_cleanup(req);\n    return $R_CONT(C_cont, B_None);\n}\n\n// action def cwd() -> str:\n$R fileQ_FSD_cwdG_local (fileQ_FS self, $Cont C_cont) {\n    char cwd[1024];\n    size_t size = sizeof(cwd);\n    int r = uv_cwd(cwd, &size);\n    if (r < 0) {\n        char errmsg[1024] = \"Error getting cwd: \";\n        uv_strerror_r(r, errmsg + strlen(errmsg), sizeof(errmsg)-strlen(errmsg));\n        log_warn(errmsg);\n        $RAISE(((B_BaseException)B_OSErrorG_new(to$str(errmsg))));\n    }\n    return $R_CONT(C_cont, to$str(cwd));\n}\n\n// action def exepath() -> str:\n$R fileQ_FSD_exepathG_local (fileQ_FS self, $Cont C_cont) {\n    char exepath[1024];\n    size_t size = sizeof(exepath);\n    int r = uv_exepath(exepath, &size);\n    if (r < 0) {\n        char errmsg[1024] = \"Error getting exepath: \";\n        uv_strerror_r(r, errmsg + strlen(errmsg), sizeof(errmsg)-strlen(errmsg));\n        log_warn(errmsg);\n        $RAISE(((B_BaseException)B_OSErrorG_new(to$str(errmsg))));\n    }\n    return $R_CONT(C_cont, to$str(exepath));\n}\n\n// action def homedir() -> str:\n$R fileQ_FSD_homedirG_local (fileQ_FS self, $Cont C_cont) {\n    char homedir[1024];\n    size_t size = sizeof(homedir);\n    int r = uv_os_homedir(homedir, &size);\n    if (r < 0) {\n        char errmsg[1024] = \"Error getting homedir: \";\n        uv_strerror_r(r, errmsg + strlen(errmsg), sizeof(errmsg)-strlen(errmsg));\n        log_warn(errmsg);\n        $RAISE(((B_BaseException)B_OSErrorG_new(to$str(errmsg))));\n    }\n    return $R_CONT(C_cont, to$str(homedir));\n}\n\n// action def mkdir(filename: str):\n$R fileQ_FSD_mkdirG_local (fileQ_FS self, $Cont C_cont, B_str filename) {\n    uv_fs_t *req = (uv_fs_t *)acton_malloc(sizeof(uv_fs_t));\n    int r = uv_fs_mkdir(get_uv_loop(), req, (char *)fromB_str(filename), 0777, NULL);\n    if (r < 0 && r != UV_EEXIST) {\n        char errmsg[1024] = \"Error creating directory: \";\n        uv_strerror_r(r, errmsg + strlen(errmsg), sizeof(errmsg)-strlen(errmsg));\n        uv_fs_req_cleanup(req);\n        log_warn(errmsg);\n        $RAISE(((B_BaseException)B_OSErrorG_new(to$str(errmsg))));\n    }\n    uv_fs_req_cleanup(req);\n    return $R_CONT(C_cont, B_None);\n}\n\n// action def mktmpdir(prefix: str=\"\"):\n$R fileQ_FSD_mktmpdirG_local (fileQ_FS self, $Cont C_cont, B_str prefix) {\n    uv_fs_t *req = (uv_fs_t *)acton_malloc(sizeof(uv_fs_t));\n    size_t size = 128;\n    char *tmpdir;\n    int r;\n\n    while (1) {\n        tmpdir = (char *)acton_malloc(size);\n        size_t requested = size;\n        r = uv_os_tmpdir(tmpdir, &requested);\n        if (r == UV_ENOBUFS) {\n            size = requested;\n            continue;\n        }\n        if (r < 0) {\n            char errmsg[1024] = \"Error getting temporary directory: \";\n            uv_strerror_r(r, errmsg + strlen(errmsg), sizeof(errmsg)-strlen(errmsg));\n            log_warn(errmsg);\n            $RAISE(((B_BaseException)B_OSErrorG_new(to$str(errmsg))));\n        }\n        break;\n    }\n\n    const char *cprefix = prefix == B_None ? \"\" : (const char *)fromB_str(prefix);\n    size_t template_size = strlen(tmpdir) + 1 + strlen(cprefix) + 6 + 1;\n    char *tpl = (char *)acton_malloc(template_size);\n    snprintf(tpl, template_size, \"%s/%sXXXXXX\", tmpdir, cprefix);\n\n    r = uv_fs_mkdtemp(get_uv_loop(), req, tpl, NULL);\n    if (r < 0) {\n        char errmsg[1024] = \"Error creating temporary directory: \";\n        uv_strerror_r(r, errmsg + strlen(errmsg), sizeof(errmsg)-strlen(errmsg));\n        uv_fs_req_cleanup(req);\n        log_warn(errmsg);\n        $RAISE(((B_BaseException)B_OSErrorG_new(to$str(errmsg))));\n    }\n\n    // libuv stores the resolved path in req->path, not in the template buffer.\n    B_str path = to$str(req->path);\n    uv_fs_req_cleanup(req);\n    return $R_CONT(C_cont, path);\n}\n\n// action def listdir(path: str) -> list[str]:\n$R fileQ_FSD_listdirG_local (fileQ_FS self, $Cont C_cont, B_str path) {\n    B_SequenceD_list wit = B_SequenceD_listG_witness;\n    uv_fs_t *req = (uv_fs_t *)acton_malloc(sizeof(uv_fs_t));\n    B_list res = B_listD_new(0);\n    res->length = 0;\n    int r = uv_fs_scandir(get_uv_loop(), req, (char *)fromB_str(path), 0, NULL);\n    if (r < 0) {\n        char errmsg[1024] = \"Error listing directory: \";\n        uv_strerror_r(r, errmsg + strlen(errmsg), sizeof(errmsg)-strlen(errmsg));\n        uv_fs_req_cleanup(req);\n        log_warn(errmsg);\n        $RAISE(((B_BaseException)B_OSErrorG_new(to$str(errmsg))));\n    }\n    uv_dirent_t ent;\n    while (uv_fs_scandir_next(req, &ent) != UV_EOF) {\n        wit->$class->append(wit, res, to$str(ent.name));\n    }\n    uv_fs_req_cleanup(req);\n    return $R_CONT(C_cont, res);\n}\n\n// action def lstat(filename: str) -> FileStat:\n$R fileQ_FSD_lstatG_local (fileQ_FS self, $Cont C_cont, B_str filename) {\n    uv_fs_t *req = (uv_fs_t *)acton_malloc(sizeof(uv_fs_t));\n    int r = uv_fs_lstat(get_uv_loop(), req, (char *)fromB_str(filename), NULL);\n    if (r < 0) {\n        char errmsg[1024] = \"Error getting file stat: \";\n        uv_strerror_r(r, errmsg + strlen(errmsg), sizeof(errmsg)-strlen(errmsg));\n        uv_fs_req_cleanup(req);\n        log_warn(errmsg);\n        $RAISE((B_BaseException)B_OSErrorG_new(to$str(errmsg)));\n    }\n    uv_stat_t *stat = (uv_stat_t *)req->ptr;\n    fileQ_FileStat res = fileQ_FileStatG_new(filename,\n                                             toB_u64(stat->st_dev),\n                                             toB_u64(stat->st_mode),\n                                             toB_u64(stat->st_nlink),\n                                             toB_u64(stat->st_uid),\n                                             toB_u64(stat->st_gid),\n                                             toB_u64(stat->st_rdev),\n                                             toB_u64(stat->st_ino),\n                                             toB_u64(stat->st_size),\n                                             toB_u64(stat->st_blksize),\n                                             toB_u64(stat->st_blocks),\n                                             toB_u64(stat->st_flags),\n                                             toB_u64(stat->st_gen),\n                                             toB_float(stat->st_atim.tv_sec + stat->st_atim.tv_nsec / 1e9),\n                                             toB_float(stat->st_mtim.tv_sec + stat->st_mtim.tv_nsec / 1e9),\n                                             toB_float(stat->st_ctim.tv_sec + stat->st_ctim.tv_nsec / 1e9),\n                                             toB_float(stat->st_birthtim.tv_sec + stat->st_birthtim.tv_nsec / 1e9)\n                                             );\n    uv_fs_req_cleanup(req);\n    return $R_CONT(C_cont, res);\n}\n\n// action def rmdir(dirname: str) -> None:\n$R fileQ_FSD_rmdirG_local (fileQ_FS self, $Cont C_cont, B_str dirname) {\n    uv_fs_t *req = (uv_fs_t *)acton_malloc(sizeof(uv_fs_t));\n    int r = uv_fs_rmdir(get_uv_loop(), req, (char *)fromB_str(dirname), NULL);\n    if (r < 0 && r != UV_ENOENT) {\n        char errmsg[1024] = \"Error removing directory: \";\n        uv_strerror_r(r, errmsg + strlen(errmsg), sizeof(errmsg)-strlen(errmsg));\n        uv_fs_req_cleanup(req);\n        log_warn(errmsg);\n        $RAISE(((B_BaseException)B_OSErrorG_new(to$str(errmsg))));\n    }\n    uv_fs_req_cleanup(req);\n    return $R_CONT(C_cont, B_None);\n}\n\n// action def remove(filename: str) -> None:\n$R fileQ_FSD_removeG_local (fileQ_FS self, $Cont C_cont, B_str filename) {\n    uv_fs_t *req = (uv_fs_t *)acton_malloc(sizeof(uv_fs_t));\n    int r = uv_fs_unlink(get_uv_loop(), req, (char *)fromB_str(filename), NULL);\n    if (r < 0) {\n        char errmsg[1024] = \"Error removing file: \";\n        uv_strerror_r(r, errmsg + strlen(errmsg), sizeof(errmsg)-strlen(errmsg));\n        uv_fs_req_cleanup(req);\n        log_warn(errmsg);\n        $RAISE(((B_BaseException)B_OSErrorG_new(to$str(errmsg))));\n    }\n    uv_fs_req_cleanup(req);\n    return $R_CONT(C_cont, B_None);\n}\n\n// action def stat(filename: str) -> FileStat:\n$R fileQ_FSD_statG_local (fileQ_FS self, $Cont C_cont, B_str filename) {\n    uv_fs_t *req = (uv_fs_t *)acton_malloc(sizeof(uv_fs_t));\n    int r = uv_fs_stat(get_uv_loop(), req, (char *)fromB_str(filename), NULL);\n    if (r == UV_ENOENT) {\n        uv_fs_req_cleanup(req);\n        $RAISE(((B_BaseException)B_FileNotFoundErrorG_new(filename)));\n    } else if (r < 0) {\n        char errmsg[1024] = \"Error getting file stat: \";\n        uv_strerror_r(r, errmsg + strlen(errmsg), sizeof(errmsg)-strlen(errmsg));\n        uv_fs_req_cleanup(req);\n        log_warn(errmsg);\n        $RAISE(((B_BaseException)B_OSErrorG_new(to$str(errmsg))));\n    }\n    uv_stat_t *stat = (uv_stat_t *)req->ptr;\n    fileQ_FileStat res = fileQ_FileStatG_new(filename,\n                                             toB_u64(stat->st_dev),\n                                             toB_u64(stat->st_mode),\n                                             toB_u64(stat->st_nlink),\n                                             toB_u64(stat->st_uid),\n                                             toB_u64(stat->st_gid),\n                                             toB_u64(stat->st_rdev),\n                                             toB_u64(stat->st_ino),\n                                             toB_u64(stat->st_size),\n                                             toB_u64(stat->st_blksize),\n                                             toB_u64(stat->st_blocks),\n                                             toB_u64(stat->st_flags),\n                                             toB_u64(stat->st_gen),\n                                             toB_float(stat->st_atim.tv_sec + stat->st_atim.tv_nsec / 1e9),\n                                             toB_float(stat->st_mtim.tv_sec + stat->st_mtim.tv_nsec / 1e9),\n                                             toB_float(stat->st_ctim.tv_sec + stat->st_ctim.tv_nsec / 1e9),\n                                             toB_float(stat->st_birthtim.tv_sec + stat->st_birthtim.tv_nsec / 1e9)\n                                             );\n    uv_fs_req_cleanup(req);\n    return $R_CONT(C_cont, res);\n}\n\n$R fileQ_FSD_tmpdirG_local (fileQ_FS self, $Cont C_cont) {\n    size_t size = 128;\n    int r;\n\n    while (1) {\n        char *buffer = (char *)acton_malloc(size);\n        size_t requested = size;\n        r = uv_os_tmpdir(buffer, &requested);\n        if (r == UV_ENOBUFS) {\n            size = requested;\n            continue;\n        }\n        if (r < 0) {\n            char errmsg[1024] = \"Error getting temporary directory: \";\n            uv_strerror_r(r, errmsg + strlen(errmsg), sizeof(errmsg)-strlen(errmsg));\n            log_warn(errmsg);\n            $RAISE(((B_BaseException)B_OSErrorG_new(to$str(errmsg))));\n        }\n        return $R_CONT(C_cont, to$str(buffer));\n    }\n}\n\n$R fileQ_ReadFileD__open_fileG_local (fileQ_ReadFile self, $Cont c$cont) {\n    pin_actor_affinity();\n    uv_fs_t *req = (uv_fs_t *)acton_malloc(sizeof(uv_fs_t));\n    int r = uv_fs_open(get_uv_loop(), req, (char *)fromB_str(self->filename), UV_FS_O_RDONLY, 0, NULL);\n    if (r == UV_ENOENT) {\n        uv_fs_req_cleanup(req);\n        $RAISE(((B_BaseException)B_FileNotFoundErrorG_new(self->filename)));\n    } else if (r < 0) {\n        char errmsg[1024] = \"Error opening file for reading: \";\n        uv_strerror_r(r, errmsg + strlen(errmsg), sizeof(errmsg)-strlen(errmsg));\n        uv_fs_req_cleanup(req);\n        log_warn(errmsg);\n        $RAISE(((B_BaseException)B_OSErrorG_new(to$str(errmsg))));\n\n    }\n    self->_fd = toB_int(r);\n    uv_fs_req_cleanup(req);\n    return $R_CONT(c$cont, B_None);\n}\n\n$R fileQ_ReadFileD__lock_fileG_local (fileQ_ReadFile self, $Cont c$cont) {\n#if defined(_WIN32) || defined(_WIN64)\n    assert(0 && \"fileQ_ReadFileD__lock_fileG_local not implemented on Windows\");\n#else\n    int r = flock(fromB_int(self->_fd), LOCK_EX + LOCK_NB);\n    if (r < 0) {\n        char errmsg[1024] = \"Error locking file: \";\n        uv_strerror_r(r, errmsg + strlen(errmsg), sizeof(errmsg)-strlen(errmsg));\n        log_warn(errmsg);\n        $RAISE(((B_BaseException)B_OSErrorG_new(to$str(errmsg))));\n    }\n#endif\n    return $R_CONT(c$cont, B_None);\n}\n\n$R fileQ_ReadFileD_closeG_local (fileQ_ReadFile self, $Cont c$cont) {\n    uv_fs_t *req = (uv_fs_t *)acton_malloc(sizeof(uv_fs_t));\n    int r = uv_fs_close(get_uv_loop(), req, (uv_file)fromB_int(self->_fd), NULL);\n    if (r < 0) {\n        char errmsg[1024] = \"Error closing file: \";\n        uv_strerror_r(r, errmsg + strlen(errmsg), sizeof(errmsg)-strlen(errmsg));\n        uv_fs_req_cleanup(req);\n        log_warn(errmsg);\n        $RAISE(((B_BaseException)B_OSErrorG_new(to$str(errmsg))));\n    }\n    uv_fs_req_cleanup(req);\n    return $R_CONT(c$cont, B_None);\n}\n\n$R fileQ_ReadFileD_readG_local (fileQ_ReadFile self, $Cont c$cont) {\n    B_SequenceD_list wit = B_SequenceD_listG_witness;\n    uv_fs_t *req = (uv_fs_t *)acton_malloc(sizeof(uv_fs_t));\n    char buf[1024] = {0};\n    uv_buf_t iovec = uv_buf_init(buf, sizeof(buf));\n    int r = uv_fs_read(get_uv_loop(), req, (uv_file)fromB_int(self->_fd), &iovec, 1, -1, NULL);\n    B_list res = B_listD_new(0);\n    res->length = 0;\n    while (r > 0) {\n        wit->$class->append(wit, res, to$bytesD_len(buf,r));\n        uv_fs_req_cleanup(req);\n        iovec = uv_buf_init(buf, sizeof(buf));\n        r = uv_fs_read(get_uv_loop(), req, (uv_file)fromB_int(self->_fd), &iovec, 1, -1, NULL);\n    }\n    if (r < 0) {\n        char errmsg[1024] = \"Error reading from file: \";\n        uv_strerror_r(r, errmsg + strlen(errmsg), sizeof(errmsg)-strlen(errmsg));\n        uv_fs_req_cleanup(req);\n        log_warn(errmsg);\n        $RAISE(((B_BaseException)B_OSErrorG_new(to$str(errmsg))));\n    }\n    uv_fs_req_cleanup(req);\n    B_bytes nullb = to$bytes(\"\");\n    B_Iterable wit2 = ((B_Iterable)((B_Collection)B_SequenceD_listG_new()->W_Collection));\n    return $R_CONT(c$cont, nullb->$class->join(nullb,wit2,res));\n}\n\n\n$R fileQ_WriteFileD__open_fileG_local (fileQ_WriteFile self, $Cont c$cont) {\n    pin_actor_affinity();\n    uv_fs_t *req = (uv_fs_t *)acton_malloc(sizeof(uv_fs_t));\n    int r = uv_fs_open(get_uv_loop(), req, (char *)fromB_str(self->filename),  UV_FS_O_RDWR | UV_FS_O_CREAT | UV_FS_O_TRUNC, S_IWUSR|S_IRUSR|S_IRGRP|S_IROTH, NULL);\n    if (r < 0) {\n        char errmsg[1024] = \"Error opening file for writing: \";\n        uv_strerror_r(r, errmsg + strlen(errmsg), sizeof(errmsg)-strlen(errmsg));\n        uv_fs_req_cleanup(req);\n        log_warn(errmsg);\n        $RAISE(((B_BaseException)B_OSErrorG_new(to$str(errmsg))));\n\n    }\n    self->_fd = toB_int(r);\n    uv_fs_req_cleanup(req);\n    return $R_CONT(c$cont, B_None);\n}\n\n$R fileQ_WriteFileD__lock_fileG_local (fileQ_WriteFile self, $Cont c$cont) {\n#if defined(_WIN32) || defined(_WIN64)\n    assert(0 && \"fileQ_ReadFileD__lock_fileG_local not implemented on Windows\");\n#else\n    int r = flock(fromB_int(self->_fd), LOCK_EX + LOCK_NB);\n    if (r < 0) {\n        char errmsg[1024] = \"Error locking file: \";\n        uv_strerror_r(r, errmsg + strlen(errmsg), sizeof(errmsg)-strlen(errmsg));\n        log_warn(errmsg);\n        $RAISE(((B_BaseException)B_OSErrorG_new(to$str(errmsg))));\n    }\n#endif\n    return $R_CONT(c$cont, B_None);\n}\n\n\n$R fileQ_WriteFileD_closeG_local (fileQ_WriteFile self, $Cont c$cont) {\n    uv_fs_t *req = (uv_fs_t *)acton_malloc(sizeof(uv_fs_t));\n    int r = uv_fs_close(get_uv_loop(), req, (uv_file)fromB_int(self->_fd), NULL);\n    if (r < 0) {\n        char errmsg[1024] = \"Error closing file: \";\n        uv_strerror_r(r, errmsg + strlen(errmsg), sizeof(errmsg)-strlen(errmsg));\n        uv_fs_req_cleanup(req);\n        log_warn(errmsg);\n        $RAISE(((B_BaseException)B_OSErrorG_new(to$str(errmsg))));\n    }\n    uv_fs_req_cleanup(req);\n    return $R_CONT(c$cont, B_None);\n}\n\n$R fileQ_WriteFileD_writeG_local (fileQ_WriteFile self, $Cont c$cont, B_bytes data) {\n    uv_fs_t *req = (uv_fs_t *)acton_malloc(sizeof(uv_fs_t));\n    uv_buf_t buf = uv_buf_init((char *)data->str, data->nbytes);\n\n    int r = uv_fs_write(get_uv_loop(), req, (uv_file)fromB_int(self->_fd), &buf, 1, 0, NULL);\n    if (r < 0) {\n        char errmsg[1024] = \"Error writing to file: \";\n        uv_strerror_r(r, errmsg + strlen(errmsg), sizeof(errmsg)-strlen(errmsg));\n        uv_fs_req_cleanup(req);\n        log_warn(errmsg);\n        $RAISE(((B_BaseException)B_OSErrorG_new(to$str(errmsg))));\n\n    }\n    uv_fs_req_cleanup(req);\n    return $R_CONT(c$cont, B_None);\n}\n"
  },
  {
    "path": "base/src/fs.act",
    "content": "\ndef path_separator() -> str:\n    \"\"\"Get the path separator for the current platform.\"\"\"\n    # TODO: Implement this function\n    return \"/\"\n\n# The local platform's path separator\nsep: str = path_separator()\n\ndef join_path(parts: list[str], path_separator: ?str=None) -> str:\n    \"\"\"Join path components together\"\"\"\n    psep = path_separator if path_separator is not None else sep\n    return psep.join(parts)\n\ndef glob(pattern: str, path: str, path_separator: ?str=None) -> bool:\n    r\"\"\"Match a glob pattern against a file path.\n\n    Supports the following glob features:\n    - '*': Matches any sequence of characters within a single path segment\n    - '**': Matches any sequence of characters across multiple path segments\n    - '?': Matches any single character\n    - '[abc]': Matches any character in the set (a, b, or c)\n    - '[a-z]': Matches any character in the range (a through z)\n    - '[^abc]': Matches any character NOT in the set (negated character class)\n    - Escaping special characters with backslash\n    - '{a,b,c}': Matches any of the comma-separated terms\n\n    Args:\n        pattern: The glob pattern to match against\n        path: The file path to match\n        path_separator: The path separator character to use. Defaults to fs.sep.\n\n    Returns:\n        True if the path matches the pattern, False otherwise\n    \"\"\"\n    separator = path_separator if path_separator is not None else sep\n    return _glob_recursive(pattern, 0, path, 0, separator)\n\ndef _glob_recursive(pattern: str, p_idx: int, path: str, s_idx: int, separator: str) -> bool:\n    \"\"\"\n    Recursive helper function for pattern matching.\n\n    Args:\n        pattern: The glob pattern to match against\n        p_idx: Current index in the pattern\n        path: The file path to match\n        s_idx: Current index in the path\n        separator: The path separator character\n\n    Returns:\n        True if the remainder of the path matches the remainder of the pattern\n    \"\"\"\n    # Base case: if we've reached the end of the pattern\n    if p_idx == len(pattern):\n        # Match if we've also reached the end of the path\n        return s_idx == len(path)\n\n    # Handle escaping with backslash\n    if p_idx < len(pattern) - 1 and pattern[p_idx] == '\\\\':\n        # Match the escaped character literally\n        if s_idx < len(path) and pattern[p_idx + 1] == path[s_idx]:\n            return _glob_recursive(pattern, p_idx + 2, path, s_idx + 1, separator)\n        return False\n\n    # Handle ** wildcard (matches across multiple path segments)\n    if p_idx + 1 < len(pattern) and pattern[p_idx:p_idx+2] == '**':\n        # Check if the next character after ** is a path separator\n        if p_idx + 2 < len(pattern) and pattern[p_idx + 2] == separator:\n            # Handle **/ pattern - match any number of directories\n            next_idx = p_idx + 3  # Skip past **/\n\n            # Try to match the rest of the pattern at every position in the path\n            for i in range(s_idx, len(path) + 1):\n                if _glob_recursive(pattern, next_idx, path, i, separator):\n                    return True\n\n            return False\n        else:\n            # Treat ** as * if not followed by separator\n            # Skip both * characters and match any sequence\n            return (_glob_recursive(pattern, p_idx + 2, path, s_idx, separator) or\n                    (s_idx < len(path) and _glob_recursive(pattern, p_idx, path, s_idx + 1, separator)))\n\n    # Handle * wildcard (matches any sequence within a path segment)\n    if pattern[p_idx] == '*':\n        # Find the next path separator in both pattern and path\n        next_sep_pattern = pattern.find(separator, p_idx + 1)\n        if next_sep_pattern == -1:\n            next_sep_pattern = len(pattern)\n\n        next_sep_path = path.find(separator, s_idx)\n        if next_sep_path == -1:\n            next_sep_path = len(path)\n\n        # Try to match the rest of the pattern with the rest of the path\n        # but don't cross path separators\n        return (_glob_recursive(pattern, p_idx + 1, path, s_idx, separator) or\n                (s_idx < len(path) and s_idx < next_sep_path and _glob_recursive(pattern, p_idx, path, s_idx + 1, separator)))\n\n    # Handle ? wildcard (matches any single character)\n    if pattern[p_idx] == '?':\n        return s_idx < len(path) and _glob_recursive(pattern, p_idx + 1, path, s_idx + 1, separator)\n\n    # Handle character class [...]\n    if pattern[p_idx] == '[' and p_idx < len(pattern) - 1:\n        # Find the closing bracket\n        close_idx = pattern.find(']', p_idx + 1)\n        if close_idx == -1:\n            # If no closing bracket, treat [ as a literal character\n            return s_idx < len(path) and pattern[p_idx] == path[s_idx] and _glob_recursive(pattern, p_idx + 1, path, s_idx + 1, separator)\n\n        # If we're at the end of the path, no match\n        if s_idx >= len(path):\n            return False\n\n        # Extract the character class content\n        char_class = pattern[p_idx + 1:close_idx]\n\n        # Check if it's a negated class\n        negated = char_class.startswith('!') or char_class.startswith('^')\n        if negated:\n            char_class = char_class[1:]\n\n        # Check if the character matches the class\n        match_found = False\n\n        # Handle character ranges like a-z\n        i = 0\n        while i < len(char_class):\n            if i + 2 < len(char_class) and char_class[i + 1] == '-':\n                # It's a range\n                if char_class[i] <= path[s_idx] and path[s_idx] <= char_class[i + 2]:\n                    match_found = True\n                    break\n                i += 3\n            else:\n                # It's a single character\n                if char_class[i] == path[s_idx]:\n                    match_found = True\n                    break\n                i += 1\n\n        # If negated, invert the result\n        if negated:\n            match_found = not match_found\n\n        # If the character matched the class, continue matching\n        if match_found:\n            return _glob_recursive(pattern, close_idx + 1, path, s_idx + 1, separator)\n\n        return False\n\n    # Handle brace expansion {a,b,c}\n    if pattern[p_idx] == r'{' and p_idx < len(pattern) - 1:\n        close_idx = pattern.find(r'}', p_idx + 1)\n        if close_idx == -1:\n            # If no closing brace, treat { as a literal character\n            return s_idx < len(path) and pattern[p_idx] == path[s_idx] and _glob_recursive(pattern, p_idx + 1, path, s_idx + 1, separator)\n\n        # Extract the options\n        options = pattern[p_idx + 1:close_idx].split(',')\n\n        # Try to match each option with the remainder of the pattern\n        for option in options:\n            # Create a new pattern with this option replacing the brace expression\n            new_pattern = pattern[:p_idx] + option + pattern[close_idx + 1:]\n            if _glob_recursive(new_pattern, 0, path, 0, separator):\n                return True\n\n        return False\n\n    # Default case: literal character match\n    return (s_idx < len(path) and\n            pattern[p_idx] == path[s_idx] and\n            _glob_recursive(pattern, p_idx + 1, path, s_idx + 1, separator))\n"
  },
  {
    "path": "base/src/hash/wyhash.act",
    "content": "class Hasher(object):\n    _hasher: u64\n    def __init__(self, seed: u64 = 0):\n        \"\"\"Initialize a new MD5 hashing context\n        \"\"\"\n        self._hasher = 0  # type: u64\n        self._init(seed)\n\n    def _init(self, seed: u64) -> None:\n        \"\"\"C function to reach out to Zig code\"\"\"\n        NotImplemented\n\n    def update(self, data: bytes) -> None:\n        \"\"\"Update the hasher state with the given chunk of data\"\"\"\n        NotImplemented\n\n    def finalize(self) -> u64:\n        \"\"\"Finalize and return the hash\n        \"\"\"\n        NotImplemented\n\ndef hash(seed: u64, data: bytes) -> u64:\n    \"\"\"Compute and return the Wyash digest of the given data\"\"\"\n    NotImplemented\n"
  },
  {
    "path": "base/src/hash/wyhash.ext.c",
    "content": "void hashQ_wyhashQ___ext_init__() {}\n\nvoid *zig_hash_wyhash_init(uint64_t seed);\nvoid zig_hash_wyhash_update(void *hasher, B_bytes data);\nuint64_t zig_hash_wyhash_final(void *hasher);\nuint64_t zig_hash_wyhash_hash(uint64_t seed, B_bytes data);\n\nB_NoneType hashQ_wyhashQ_HasherD__init (hashQ_wyhashQ_Hasher self, B_u64 seed) {\n    self->_hasher = zig_hash_wyhash_init(fromB_u64(seed));\n    return B_None;\n}\n\nB_NoneType hashQ_wyhashQ_HasherD_update (hashQ_wyhashQ_Hasher self, B_bytes data) {\n    zig_hash_wyhash_update(self->_hasher, data);\n    return B_None;\n}\n\nB_u64 hashQ_wyhashQ_HasherD_finalize (hashQ_wyhashQ_Hasher self) {\n    uint64_t h = zig_hash_wyhash_final(self->_hasher);\n    B_u64 result = toB_u64(h);\n    return result;\n}\n\nuint64_t hashQ_wyhashQ_U_1hash (uint64_t seed, B_bytes data) {\n    uint64_t result = zig_hash_wyhash_hash(seed, data);\n    return result;\n}\n"
  },
  {
    "path": "base/src/http.act",
    "content": "import acton.rts\nimport json\nimport logging\nimport net\nimport time\n\nresponses : dict[int,bytes] = {\n    100: b\"Continue\",\n    101: b\"Switching Protocols\",\n    102: b\"Processing\",\n    103: b\"Early Hints\",\n    200: b\"OK\",\n    201: b\"Created\",\n    202: b\"Accepted\",\n    203: b\"Non-Authoritative Information\",\n    204: b\"No Content\",\n    205: b\"Reset Content\",\n    206: b\"Partial Content\",\n    207: b\"Multi-Status\",\n    208: b\"Already Reported\",\n    226: b\"IM Used\",\n    300: b\"Multiple Choices\",\n    301: b\"Moved Permanently\",\n    302: b\"Found\",\n    303: b\"See Other\",\n    304: b\"Not Modified\",\n    305: b\"Use Proxy\",\n    306: b\"(Unused)\",\n    307: b\"Temporary Redirect\",\n    308: b\"Permanent Redirect\",\n    400: b\"Bad Request\",\n    401: b\"Unauthorized\",\n    402: b\"Payment Required\",\n    403: b\"Forbidden\",\n    404: b\"Not Found\",\n    405: b\"Method Not Allowed\",\n    406: b\"Not Acceptable\",\n    407: b\"Proxy Authentication Required\",\n    408: b\"Request Timeout\",\n    409: b\"Conflict\",\n    410: b\"Gone\",\n    411: b\"Length Required\",\n    412: b\"Precondition Failed\",\n    413: b\"Content Too Large\",\n    414: b\"URI Too Long\",\n    415: b\"Unsupported Media Type\",\n    416: b\"Range Not Satisfiable\",\n    417: b\"Expectation Failed\",\n    418: b\"(Unused)\",\n    421: b\"Misdirected Request\",\n    422: b\"Unprocessable Content\",\n    423: b\"Locked\",\n    424: b\"Failed Dependency\",\n    425: b\"Too Early\",\n    426: b\"Upgrade Required\",\n    428: b\"Precondition Required\",\n    429: b\"Too Many Requests\",\n    431: b\"Request Header Fields Too Large\",\n    451: b\"Unavailable For Legal Reasons\",\n    500: b\"Internal Server Error\",\n    501: b\"Not Implemented\",\n    502: b\"Bad Gateway\",\n    503: b\"Service Unavailable\",\n    504: b\"Gateway Timeout\",\n    505: b\"HTTP Version Not Supported\",\n    506: b\"Variant Also Negotiates\",\n    507: b\"Insufficient Storage\",\n    508: b\"Loop Detected\",\n    510: b\"Not Extended (OBSOLETED)\",\n    511: b\"Network Authentication Required\"\n}\n\n\ndef build_request(host: str, method: bytes, path: bytes, version: bytes, headers: dict[str, str], body: bytes) -> bytes:\n    r = [ method + b\" \" + path + b\" HTTP/\" + version ]\n    lheaders: dict[str, str] = {}\n    for k in headers:\n        lheaders[k.lower()] = k\n\n    if \"host\" not in lheaders:\n        headers[\"Host\"] = host\n    if \"user-agent\" not in lheaders:\n        headers[\"User-Agent\"] = \"Acton HTTP Client\"\n    if \"accept\" not in lheaders:\n        headers[\"Accept\"] = \"*/*\"\n#    if \"accept-encoding\" not in lheaders:\n#        headers[\"Accept-Encoding\"] = \"gzip, deflate\"\n    if \"connection\" not in lheaders:\n        headers[\"Connection\"] = \"keep-alive\"\n    if \"content-length\" not in lheaders:\n        headers[\"Content-Length\"] = str(len(body))\n\n    for k, v in headers.items():\n        r.append(k.encode() + b\": \" + v.encode())\n\n    r.append(b\"\\r\\n\")\n    res = b\"\\r\\n\".join(r)\n    if len(body) > 0:\n        res += body\n    return res\n\n\ndef build_response(version: bytes, status: int, headers: dict[str, str], body: str):\n    b = body.encode()\n    # TODO: Add Connection?\n    status_line: bytes = b\"HTTP/\" + version + b\" \" + str(status).encode()\n    if status in responses:\n        status_line += b\" \" + responses[status]\n\n    r = [ status_line ]\n    header_keys = [k.lower() for k in headers.keys()]\n    if \"server\" not in header_keys:\n        headers[\"Server\"] = \"Acton HTTP Server\"\n    if \"content-type\" not in header_keys:\n        headers[\"Content-Type\"] = \"text/html; charset=utf-8\"\n    if \"date\" not in header_keys:\n        headers[\"Date\"] = time.now().str_rfc1123()\n\n    for k, v in headers.items():\n        if k.lower() == \"content-length\":\n            # Disregard content-length, we'll compute it from body length\n            continue\n        r.append(k.encode() + b\": \" + v.encode())\n\n    r.append(b\"Content-Length: \" + str(len(b)).encode())\n    r.append(b\"\\r\\n\")\n    res = b\"\\r\\n\".join(r)\n    if len(b) > 0:\n       res += b\n\n    return res\n\n\nclass Message(object):\n    def __init__(self, start_line: bytes, headers: dict[str, str], body: bytes):\n        self.start_line = start_line\n        self.headers = headers\n        self.body = body\n\n\nclass Request(object):\n    @property\n    method: str\n    @property\n    path: str\n    @property\n    version: bytes\n    @property\n    headers: dict[str, str]\n    @property\n    body: bytes\n\n    def __init__(self, method: str, path: str, version: bytes, headers: dict[str, str], body: bytes):\n        self.method = method\n        self.path = path\n        self.version = version\n        self.headers = headers\n        self.body = body\n\n    def __str__(self):\n        return f\"<http.Request {self.method} {self.path} {str(self.version)} {self.headers.__str__()} {str(self.body)}>\"\n\nextension Request(Eq):\n    def __eq__(self, other):\n        return self.method == other.method and self.path == other.path and self.version == other.version and self.headers == other.headers and self.body == other.body\n\n\nclass Response(object):\n    @property\n    version: bytes\n    @property\n    status: int\n    @property\n    headers: dict[str, str]\n    @property\n    body: bytes\n\n    def __init__(self, version: bytes, status: int, headers: dict[str, str], body: bytes) -> None:\n        self.version = version\n        self.status = status\n        self.headers = headers\n        self.body = body\n\n    def __str__(self) -> str:\n        return f\"<http.Response {self.status}>\"\n\n    def decode_json(self):\n        return json.decode(self.body.decode())\n\nextension Response(Eq):\n    def __eq__(self, other):\n        return self.version == other.version and self.status == other.status and self.headers == other.headers and self.body == other.body\n\n\ndef parse_message(i: bytes, log: logging.Logger) -> (?Message, bytes):\n    rs = i.split(b\"\\r\\n\\r\\n\", 1)\n    if len(rs) == 1:\n        return None, i\n    else:\n        header_lines = rs[0].split(b\"\\r\\n\", None)\n        start_line = header_lines[0].rstrip(b\"\\r\\n\")\n\n        headers : dict[str, str] = {}\n        for hline in header_lines[1:]:\n            hv = hline.split(b\":\", 1)\n            if len(hv) == 1:\n                # TODO: silently ignore or explicitly throw error or something?\n                pass\n            else:\n                try:\n                    hname = hv[0].decode().strip(\" \").lower()\n                    headers[hname] = hv[1].decode().strip(\" \")\n                except ValueError:\n                    log.debug(\"Invalid header\")\n                    return None, i\n\n        # TODO: why do we have to init body & rest here? seems we segfault otherwise...\n        body = b\"\"\n        rest = b\"\"\n        if \"content-length\" in headers:\n            clen = int(headers[\"content-length\"].strip(\" \"))\n            log.trace(f\"Got content-length in headers, expecting {clen} bytes\", None)\n            if len(rs[1]) >= clen:\n                body = rs[1][:clen]\n                rest = rs[1][clen:]\n                log.trace(\"Enough data to reach content-length!\", None)\n                msg = Message(start_line, headers, body)\n                return msg, rest\n            else:\n                log.trace(\"Not enough data to reach content-length\", None)\n                return None, i\n        elif \"transfer-encoding\" in headers:\n            tenc = set(headers[\"transfer-encoding\"].strip(\" \").split(\",\", None))\n            if \"chunked\" in tenc:\n                log.trace(\"Got chunked transfer-encoding\", None)\n                reached_end = False\n                rest = rs[1]\n                log.trace(f\"Rest: {str(rest)}\", None)\n                body = b\"\"\n                while not reached_end:\n                    maybe_chunk = rest.split(b\"\\r\\n\", 1)\n                    if len(maybe_chunk) == 1:\n                        log.trace(\"No chunk header found\", None)\n                        return None, i\n                    elif len(maybe_chunk) == 2:\n                        chunk_header = maybe_chunk[0].strip(b\"\\r\\n\")\n                        if chunk_header == b\"\":\n                            log.trace(\"Empty chunk header\", None)\n                            return None, i\n                        try:\n                            chunk_header_str = chunk_header.decode()\n                        except ValueError:\n                            log.debug(\"Invalid chunk header\")\n                            return None, i\n                        else:\n                            rest = maybe_chunk[1]\n                            log.trace(f\"Chunk header: {chunk_header[:20]}\", None)\n                            try:\n                                clen = int(chunk_header_str, 16)\n                                log.trace(f\"Chunk length: {clen}\", None)\n                            except ValueError:\n                                log.trace(\"Chunk header not a length\", None)\n                            else:\n                                if len(rest) >= clen:\n                                    gap = rest[clen-10:clen+10]\n                                    chunk = rest[:clen]\n                                    log.trace(f\"Read chunk: {str(chunk)}\", None)\n                                    rest = rest[clen:]\n                                    if len(rest) < 2 and rest[0:2] != b\"\\r\\n\":\n                                        log.trace(\"Could not find chunk end marker\", None)\n                                        return None, i\n                                    rest = rest[2:]\n                                    #log.trace(\"Enough data to reach end of chunk\", None)\n                                    chunk_preview = str(chunk[-5:])\n                                    rest_preview = str(rest[:5])\n                                    log.trace(f\"Enough data to reach end of chunk, chunk gap: {chunk_preview}|{rest_preview}\", None)\n                                    body += chunk\n                                    if clen == 0:\n                                        reached_end = True\n                                        msg = Message(start_line, headers, body)\n                                        log.trace(\"Reached end of chunked message\", None)\n                                        return msg, rest\n                                else:\n                                    log.trace(\"Not enough data to reach end of chunk\", None)\n                                    return None, i\n\n                    else:\n                        # TODO: InternalError?\n                        raise ValueError(\"Unreachable\")\n        else:\n            body = b\"\"\n            rest = rs[1]\n            msg = Message(start_line, headers, body)\n            return msg, rest\n        return None, i\n\n\ndef parse_request(i: bytes, log: logging.Logger) -> (?Request, bytes):\n    msg, rest = parse_message(i, log)\n    if msg is not None:\n        slparts = msg.start_line.split(b\" \", None)\n        if len(slparts) != 3:\n            # HTTP request must have exactly 3 parts: METHOD PATH HTTP/VERSION\n            return None, b\"\"\n        try:\n            method = slparts[0].decode()\n            path = slparts[1].decode()\n        except ValueError:\n            log.debug(\"Invalid method/path\")\n            return None, b\"\"\n        else:\n            verparts = slparts[2].split(b\"/\", 1)\n            if len(verparts) != 2:\n                # invalid request\n                # TODO: actually HTTP 0.9 might only have 2 parts, but we don't support that\n                return None, b\"\"\n            version = verparts[1]\n            if version != b\"1.1\" and version != b\"1.0\":\n                return None, b\"\"\n            req = Request(method, path, version, msg.headers, msg.body)\n            return req, rest\n    return None, i\n\ndef parse_response(i: bytes, log: logging.Logger) -> (?Response, bytes):\n    msg, rest = parse_message(i, log)\n    if msg is not None:\n        slparts = msg.start_line.split(b\" \", None)\n        if len(slparts) < 2:\n            # HTTP response must have at least 2 parts: HTTP/VERSION STATUS_CODE [REASON_PHRASE]\n            return None, b\"\"\n        verparts = slparts[0].split(b\"/\", 1)\n        if len(verparts) != 2:\n            # invalid request\n            # TODO: actually HTTP 0.9 might only have 2 parts, but we don't support that\n            return None, b\"\"\n        version = verparts[1]\n        if version != b\"1.1\" and version != b\"1.0\":\n            log.trace(\"Invalid HTTP version\", None)\n            return None, b\"\"\n\n        try:\n            status = int(slparts[1].decode())\n        except ValueError:\n            log.debug(\"Invalid status\")\n            return None, b\"\"\n        else:\n            resp = Response(version, status, msg.headers, msg.body)\n            return resp, b\"\"\n    return None, i\n\n\nactor Server(conn: net.TCPListenConnection, on_accept: action(Server) -> None, log_handler: ?logging.Handler):\n    \"\"\"Server serves a single client connection\"\"\"\n    _log = logging.Logger(log_handler)\n    var on_request_cb: ?action(Server, Request, action(int, dict[str, str], str) -> None) -> None = None\n    var on_error_cb: ?action(Server, str) -> None = None\n    var version: ?bytes = None\n    var buf = b\"\"\n    var close_connection: bool = True\n    var query_count: u64 = 0\n    var response_count: u64 = 0\n    var outstanding_requests: dict[u64, Response] = {}\n\n    def cb_install(new_on_request: action(Server, Request, action(int, dict[str, str], str) -> None) -> None, new_on_error: action(Server, str) -> None):\n        on_request_cb = new_on_request\n        on_error_cb = new_on_error\n        if buf != b\"\":\n            req, buf = parse_request(buf, _log)\n\n    def on_conn_receive(conn_obj, data: bytes) -> None:\n        # TODO: do we really need a buf?\n        if on_request_cb is None:\n            buf += data\n            return None\n        else:\n            if buf != b\"\":\n                data = buf + data\n\n        req, buf = parse_request(data, _log)\n        if req is not None:\n            if version is None:\n                version = req.version\n            elif version is not None and version != req.version:\n                _log.debug(\"Version mismatch\", None)\n                conn.close()\n\n            if version is not None and version == b\"1.0\":\n                if \"connection\" in req.headers:\n                    if req.headers[\"connection\"] == \"close\":\n                        _log.debug(\"HTTP 1.0 with connection: close, closing connection...\", None)\n                        close_connection = True\n                    else:\n                        _log.debug(\"HTTP 1.0 with connection header, not closing connection...\", None)\n                        _log.trace(\"connection header\", {\"connection\": req.headers[\"connection\"]})\n                else:\n                    close_connection = True\n            elif version is not None and version == b\"1.1\":\n                if \"connection\" in req.headers and req.headers[\"connection\"] == \"close\":\n                    _log.debug(\"HTTP 1.1, closing connection...\", None)\n                    close_connection = True\n                else:\n                    close_connection = False\n\n            query_count += 1\n            def respond(status_code: int, headers: dict[str, str], body: str):\n                _log.trace(\"Going to respond with query id\", {\"query_count\": query_count})\n                if query_count == response_count + 1:\n                    # In order, send response immediately\n                    _log.trace(\"Sending response immediately\", None)\n                    send_response(status_code, headers, body)\n                    response_count += 1\n                else:\n                    # Buffer up response\n                    _log.trace(\"Buffering response\", None)\n                    # TODO: actually implement buffering?\n                    #outstanding_requests[query_count] = Response(\"GABBA\", version, status_code, headers, body.encode())\n\n            if on_request_cb is not None:\n                response = on_request_cb(self, req, respond)\n                if response is not None:\n                    _log.trace(\"Sending response immediately\", None)\n                else:\n                    _log.trace(\"Async response\", None)\n            else:\n                _log.notice(\"No on_request callback set\", None)\n\n    def on_conn_error(conn, error):\n        # TODO: the conn should really be in here, but type error!?\n        _log.trace(f\"There was an error: {str(error)} from: {str(\"\")}\", None)\n\n    def close():\n        conn.close()\n\n    def send_response(status_code: int, headers: dict[str, str], data: str):\n        if version is not None:\n            res = build_response(version, status_code, headers, data)\n            conn.write(res)\n\n        if close_connection:\n            conn.close()\n\n\nactor TLSServer(conn: net.TLSListenConnection, on_accept: action(TLSServer) -> None, log_handler: ?logging.Handler):\n    \"\"\"Server serves a single TLS client connection\"\"\"\n    _log = logging.Logger(log_handler)\n    var on_request_cb: ?action(TLSServer, Request, action(int, dict[str, str], str) -> None) -> None = None\n    var on_error_cb: ?action(TLSServer, str) -> None = None\n    var version: ?bytes = None\n    var buf = b\"\"\n    var close_connection: bool = True\n    var query_count: u64 = 0\n    var response_count: u64 = 0\n    var outstanding_requests: dict[u64, Response] = {}\n\n    def cb_install(new_on_request: action(TLSServer, Request, action(int, dict[str, str], str) -> None) -> None, new_on_error: action(TLSServer, str) -> None):\n        on_request_cb = new_on_request\n        on_error_cb = new_on_error\n        if buf != b\"\":\n            req, buf = parse_request(buf, _log)\n\n    def on_conn_receive(conn_obj, data: bytes) -> None:\n        # TODO: do we really need a buf?\n        if on_request_cb is None:\n            buf += data\n            return None\n        else:\n            if buf != b\"\":\n                data = buf + data\n\n        req, buf = parse_request(data, _log)\n        if req is not None:\n            if version is None:\n                version = req.version\n            elif version is not None and version != req.version:\n                _log.debug(\"Version mismatch\", None)\n                conn.close()\n\n            if version is not None and version == b\"1.0\":\n                if \"connection\" in req.headers:\n                    if req.headers[\"connection\"] == \"close\":\n                        _log.debug(\"HTTP 1.0 with connection: close, closing connection...\", None)\n                        close_connection = True\n                    else:\n                        _log.debug(\"HTTP 1.0 with connection header, not closing connection...\", None)\n                        _log.trace(\"connection header\", {\"connection\": req.headers[\"connection\"]})\n                else:\n                    close_connection = True\n            elif version is not None and version == b\"1.1\":\n                if \"connection\" in req.headers and req.headers[\"connection\"] == \"close\":\n                    _log.debug(\"HTTP 1.1, closing connection...\", None)\n                    close_connection = True\n                else:\n                    close_connection = False\n\n            query_count += 1\n            def respond(status_code: int, headers: dict[str, str], body: str):\n                _log.trace(\"Going to respond with query id\", {\"query_count\": query_count})\n                if query_count == response_count + 1:\n                    # In order, send response immediately\n                    _log.trace(\"Sending response immediately\", None)\n                    send_response(status_code, headers, body)\n                    response_count += 1\n                else:\n                    # Buffer up response\n                    _log.trace(\"Buffering response\", None)\n                    # TODO: actually implement buffering?\n                    #outstanding_requests[query_count] = Response(\"GABBA\", version, status_code, headers, body.encode())\n\n            if on_request_cb is not None:\n                response = on_request_cb(self, req, respond)\n                if response is not None:\n                    _log.trace(\"Sending response immediately\", None)\n                else:\n                    _log.trace(\"Async response\", None)\n            else:\n                _log.notice(\"No on_request callback set\", None)\n\n    def on_conn_error(conn, error):\n        # TODO: the conn should really be in here, but type error!?\n        _log.trace(f\"There was an error: {str(error)} from: {str(\"\")}\", None)\n\n    def close():\n        conn.close()\n\n    def send_response(status_code: int, headers: dict[str, str], data: str):\n        if version is not None:\n            res = build_response(version, status_code, headers, data)\n            conn.write(res)\n\n        if close_connection:\n            conn.close()\n\n\n# TODO: change port to u16, when u16 has a sub-type relationship to int\n# TODO: the on_listen_error default should be some action that just automatically retries with a backoff\n# TODO: add restart method to restart the listener\nactor Listener(cap: net.TCPListenCap, address: str, port: int, on_accept: action(Server) -> None, on_listen_error: ?action(net.TCPListener, str) -> None = None, log_handler: ?logging.Handler = None):\n    \"\"\"HTTP Server Listener\"\"\"\n    _log = logging.Logger(log_handler)\n    var bufs = []\n\n    def on_conn_listen(listener, error):\n        if error is not None:\n            _log.notice(\"There was an error with the listener socket\", {\"error\": error})\n            if on_listen_error is not None:\n                on_listen_error(listener, error)\n\n    def on_listener_accept(conn):\n        s = Server(conn, on_accept, log_handler)\n        await async on_accept(s)\n        await async conn.cb_install(s.on_conn_receive, s.on_conn_error, None)\n\n    var _listener = net.TCPListener(cap, address, port, on_conn_listen, on_listener_accept)\n\n\n# TODO: change port to u16, when u16 has a sub-type relationship to int\n# TODO: the on_listen_error default should be some action that just automatically retries with a backoff\n# TODO: add restart method to restart the listener\nactor TLSListener(cap: net.TCPListenCap, address: str, port: int, cert_pem: bytes, key_pem: bytes, on_accept: action(TLSServer) -> None, on_listen_error: ?action(net.TLSListener, str) -> None = None, log_handler: ?logging.Handler = None):\n    \"\"\"HTTPS Server Listener\"\"\"\n    _log = logging.Logger(log_handler)\n    var bufs = []\n\n    def on_conn_listen(listener, error):\n        if error is not None:\n            _log.notice(\"There was an error with the listener socket\", {\"error\": error})\n            if on_listen_error is not None:\n                on_listen_error(listener, error)\n\n    def on_listener_accept(conn):\n        s = TLSServer(conn, on_accept, log_handler)\n        await async on_accept(s)\n        await async conn.cb_install(s.on_conn_receive, s.on_conn_error, None)\n\n    var _listener = net.TLSListener(cap, address, port, cert_pem, key_pem, on_conn_listen, on_listener_accept)\n\n\n# TODO: change port to u16, when u16 has a sub-type relationship to int\nactor Client(cap: net.TCPConnectCap, address: str, on_connect: action(Client) -> None, on_error: action(Client, str) -> None, scheme: str=\"https\", port: ?int=None, tls_verify: bool=True, log_handler: ?logging.Handler):\n    \"\"\"HTTP(S) Client\n\n    scheme is either 'http' or 'https', the default is 'https'\n    port is optional, if not provided, it will be inferred from the scheme where http=80 and https=443\n    \"\"\"\n    _log = logging.Logger(log_handler)\n    var _on_response: list[(bytes, action(Client, Response) -> None)] = []\n    var version: ?bytes = None\n    var buf = b\"\"\n    var close_connection: bool = True\n    var tcp_conn: ?net.TCPConnection = None\n    var tls_conn: ?net.TLSConnection = None\n\n    def _connect():\n        if scheme == \"http\":\n            _log.verbose(\"Using http scheme and port 80\", None)\n            tcp_port = port if port is not None else 80\n            tcp_conn = net.TCPConnection(cap, address, tcp_port, _on_tcp_connect, _on_tcp_receive, _on_tcp_error, None, connect_timeout=10.0)\n        elif scheme == \"https\":\n            _log.verbose(\"Using https scheme and port 443\", None)\n            tls_port = port if port is not None else 443\n            tls_conn = net.TLSConnection(cap, address, tls_port, _on_tls_connect, _on_tls_receive, _on_tls_error, None, tls_verify)\n        else:\n            raise ValueError(f\"Only http and https schemes are supported. Unsupported scheme: {scheme}\")\n\n    def _on_conn_connect():\n        # If there are outstanding requests, it probably means we were\n        for r in _on_response:\n            _conn_write(r.0)\n        await async on_connect(self)\n\n    def _on_tcp_connect(conn: net.TCPConnection) -> None:\n        _on_conn_connect()\n\n    def _on_tls_connect(conn: net.TLSConnection) -> None:\n        _on_conn_connect()\n\n    def _on_tcp_receive(conn: net.TCPConnection, data: bytes) -> None:\n        _on_con_receive(data)\n\n    def _on_tls_receive(conn: net.TLSConnection, data: bytes) -> None:\n        _on_con_receive(data)\n\n    def _on_con_receive(data: bytes) -> None:\n        buf += data\n        _log.debug(\"Received data\", {\"bytes\": len(data)})\n        #_log.trace(\"Received data\", {\"data\": data})\n\n        while True:\n            r, buf = parse_response(buf, _log)\n            if r is not None:\n                if \"connection\" in r.headers and r.headers[\"connection\"] == \"close\":\n                    close_connection = True\n                    _conn_close()\n                    _log.debug(\"Closing TCP connection due to header: Connection: close\", None)\n                    _connect()\n                if len(_on_response) == 0:\n                    _log.notice(\"Data received with no on_response callback set\", None)\n                    break\n                outreq = _on_response[0]\n                del _on_response[0]\n                cb = outreq.1\n\n                await async cb(self, r)\n            else:\n                break\n\n    def _on_tcp_error(conn: net.TCPConnection, error: str) -> None:\n        _on_con_error(error)\n\n    def _on_tls_error(conn: net.TLSConnection, error: str) -> None:\n        _on_con_error(error)\n\n    def _on_con_error(error: str) -> None:\n        on_error(self, error)\n\n    def _conn_close() -> None:\n        if tcp_conn is not None:\n            def _noop(c):\n                pass\n            tcp_conn.close(_noop)\n        elif tls_conn is not None:\n            def _noop(c):\n                pass\n            tls_conn.close(_noop)\n\n    def _conn_write(data: bytes) -> None:\n        _log.trace(\"Sending data\", {\"data\": data})\n        if tcp_conn is not None:\n            tcp_conn.write(data)\n        elif tls_conn is not None:\n            tls_conn.write(data)\n\n    def close():\n        _conn_close()\n\n    # HTTP methods\n    def get(path: str, on_response: action(Client, Response) -> None, headers: dict[str, str] = {}):\n        req = build_request(address, b\"GET\", path.encode(), b\"1.1\", headers, b\"\")\n        _log.debug(\"Sending request\", {\"method\": \"GET\", \"path\": path})\n        _on_response.append((req, on_response))\n        _conn_write(req)\n\n    def head(path: str, on_response: action(Client, Response) -> None, headers: dict[str, str] = {}):\n        req = build_request(address, b\"HEAD\", path.encode(), b\"1.1\", headers, b\"\")\n        _log.debug(\"Sending request\", {\"method\": \"HEAD\", \"path\": path})\n        _on_response.append((req, on_response))\n        _conn_write(req)\n\n    def post(path: str, body: bytes, on_response: action(Client, Response) -> None, headers: dict[str, str] = {}):\n        if \"Content-Type\" not in headers:\n            headers[\"Content-Type\"] = \"application/x-www-form-urlencoded\"\n        req = build_request(address, b\"POST\", path.encode(), b\"1.1\", headers, body)\n        _log.debug(\"Sending request\", {\"method\": \"POST\", \"path\": path})\n        _on_response.append((req, on_response))\n        _conn_write(req)\n\n    def put(path: str, body: bytes, on_response: action(Client, Response) -> None, headers: dict[str, str] = {}):\n        req = build_request(address, b\"PUT\", path.encode(), b\"1.1\", headers, body)\n        _log.debug(\"Sending request\", {\"method\": \"PUT\", \"path\": path})\n        _on_response.append((req, on_response))\n        _conn_write(req)\n\n    def delete(path: str, on_response: action(Client, Response) -> None, headers: dict[str, str] = {}):\n        req = build_request(address, b\"DELETE\", path.encode(), b\"1.1\", headers, b\"\")\n        _log.debug(\"Sending request\", {\"method\": \"DELETE\", \"path\": path})\n        _on_response.append((req, on_response))\n        _conn_write(req)\n\n    _connect()\n"
  },
  {
    "path": "base/src/json.act",
    "content": "actor Json():\n    \"\"\"JSON actor for distributed async processing\n\n    This actor can be used to process JSON data in a asynchronous distributed\n    fashion. The `encode` and `decode` methods are identical to the free\n    `encode` and `decode` functions in this module but by being wrapped in an\n    actor, they can be:\n    - called asynchronously\n    - the Json actor can be run by a different worker\n    Thus, by using one or multiple Json actors, the work of encoding or decoding\n    JSON can be distributed across multiple actors / workers / CPUs.\n    \"\"\"\n    action def decode(data: str) -> dict[str, ?value]:\n        return decode(data)\n\n    action def decode_list(data: str) -> list[?value]:\n        return decode_list(data)\n\n    action def encode(data: dict[str, ?value]) -> str:\n        return encode(data)\n\n    action def encode_list(data: list[?value], pretty=False) -> str:\n        return encode_list(data, pretty)\n\n\ndef decode(data: str) -> dict[str, ?value]:\n    \"\"\"Decode a JSON string into a dictionary of values\n    \"\"\"\n    NotImplemented\n\ndef decode_list(data: str) -> list[?value]:\n    \"\"\"Decode a JSON string (containing an array) into a list of values\n    \"\"\"\n    NotImplemented\n\ndef encode(data: dict[str, ?value], pretty=False) -> str:\n    \"\"\"Encode a dictionary into a JSON string\n    \"\"\"\n    NotImplemented\n\ndef encode_list(data: list[?value], pretty=False) -> str:\n    \"\"\"Encode a list into a JSON array string\n    \"\"\"\n    NotImplemented\n"
  },
  {
    "path": "base/src/json.ext.c",
    "content": "\n#include \"../rts/io.h\"\n#include \"../rts/log.h\"\n#include \"yyjson.h\"\n\nstatic void *my_malloc(void *ctx, size_t size) {\n    return acton_malloc(size);\n}\n\nstatic void *my_realloc(void *ctx, void *ptr, size_t size) {\n    return acton_realloc(ptr, size);\n}\n\nstatic void my_free(void *ctx, void *ptr) {\n    acton_free(ptr);\n}\n\n\nyyjson_alc acton_alc;\n\nvoid jsonQ___ext_init__() {\n    acton_alc.malloc = my_malloc;\n    acton_alc.realloc = my_realloc;\n    acton_alc.free = my_free;\n}\n\nvoid jsonQ_encode_list_into(yyjson_mut_doc *doc, yyjson_mut_val *node, B_list data);\nvoid jsonQ_encode_dict(yyjson_mut_doc *doc, yyjson_mut_val *node, B_dict data) {\n    B_IteratorD_dict_items iter = $NEW(B_IteratorD_dict_items, data);\n    B_tuple item;\n\n    for (int i=0; i < data->numelements; i++) {\n        item = (B_tuple)iter->$class->__next__(iter);\n        char *key = (char *)fromB_str((B_str)item->components[0]);\n        B_value v = item->components[1];\n        if (v) {\n            switch (v->$class->$class_id) {\n                case INT_ID:;\n                    yyjson_mut_obj_add_int(doc, node, key, fromB_int((B_int)v));\n                    break;\n                case FLOAT_ID:;\n                    yyjson_mut_obj_add_real(doc, node, key, fromB_float((B_float)v));\n                    break;\n                case BOOL_ID:;\n                    yyjson_mut_obj_add_bool(doc, node, key, fromB_bool((B_bool)v));\n                    break;\n                case STR_ID:;\n                    yyjson_mut_obj_add_str(doc, node, key,  (char *)fromB_str((B_str)v));\n                    break;\n                case LIST_ID:;\n                    yyjson_mut_val *l = yyjson_mut_arr(doc);\n                    yyjson_mut_obj_add_val(doc, node, key, l);\n                    jsonQ_encode_list_into(doc, l, (B_list)v);\n                    break;\n                case DICT_ID:;\n                    yyjson_mut_val *d = yyjson_mut_obj(doc);\n                    yyjson_mut_obj_add_val(doc, node, key, d);\n                    jsonQ_encode_dict(doc, d, (B_dict)v);\n                    break;\n                case I8_ID:;\n                    yyjson_mut_obj_add_int(doc, node, key, ((B_i8)v)->val);\n                    break;\n                case I16_ID:;\n                    yyjson_mut_obj_add_int(doc, node, key, ((B_i16)v)->val);\n                    break;\n                case I32_ID:;\n                    yyjson_mut_obj_add_int(doc, node, key, ((B_i32)v)->val);\n                    break;\n                case I64_ID:;\n                    yyjson_mut_obj_add_int(doc, node, key, ((B_int)v)->val);\n                    break;\n                case U1_ID:;\n                    yyjson_mut_obj_add_uint(doc, node, key, ((B_u1)v)->val);\n                    break;\n                case U8_ID:;\n                    yyjson_mut_obj_add_uint(doc, node, key, ((B_u8)v)->val);\n                    break;\n                case U16_ID:;\n                    yyjson_mut_obj_add_uint(doc, node, key, ((B_u16)v)->val);\n                    break;\n                case U32_ID:;\n                    yyjson_mut_obj_add_uint(doc, node, key, ((B_u32)v)->val);\n                    break;\n                case U64_ID:;\n                    yyjson_mut_obj_add_uint(doc, node, key, ((B_u64)v)->val);\n                    break;\n                default:;\n                    // TODO: hmm, at least handle all builtin types? and that's it,\n                    // maybe? like we really shouldn't accept user-defined types\n                    // here, just throw an exception? or when we have unions, just\n                    // accept union of the types we support\n                    $RAISE(((B_BaseException)B_ValueErrorG_new($FORMAT(\"jsonQ_encode_dict: for key %s unknown type: %s\", key, v->$class->$GCINFO))));\n            }\n        } else {\n            yyjson_mut_obj_add_null(doc, node, key);\n        }\n    }\n}\n\nvoid jsonQ_encode_list_into(yyjson_mut_doc *doc, yyjson_mut_val *node, B_list data) {\n    for (int i = 0; i < data->length; i++) {\n        B_value v = data->data[i];\n        if (v) {\n            switch (v->$class->$class_id) {\n                case INT_ID:;\n                    yyjson_mut_arr_add_int(doc, node, fromB_int((B_int)v));\n                    break;\n                case FLOAT_ID:;\n                    yyjson_mut_arr_add_real(doc, node, fromB_float((B_float)v));\n                    break;\n                case BOOL_ID:;\n                    yyjson_mut_arr_add_bool(doc, node, fromB_bool((B_bool)v));\n                    break;\n                case STR_ID:;\n                    yyjson_mut_arr_add_str(doc, node,  (char *)fromB_str((B_str)v));\n                    break;\n                case LIST_ID:;\n                    yyjson_mut_val *l = yyjson_mut_arr_add_arr(doc, node);\n                    if (l) {\n                        jsonQ_encode_list_into(doc, l, (B_list)v);\n                    } else {\n                        // TODO: raise exception\n                    }\n                    break;\n                case DICT_ID:;\n                    yyjson_mut_val *d = yyjson_mut_arr_add_obj(doc, node);\n                    if (d) {\n                        jsonQ_encode_dict(doc, d, (B_dict)v);\n                    } else {\n                        // TODO: raise exception\n                    }\n                    break;\n                case I8_ID:;\n                    yyjson_mut_arr_add_int(doc, node, ((B_i8)v)->val);\n                    break;\n                case I16_ID:;\n                    yyjson_mut_arr_add_int(doc, node, ((B_i16)v)->val);\n                    break;\n                case I32_ID:;\n                    yyjson_mut_arr_add_int(doc, node, ((B_i32)v)->val);\n                    break;\n                case I64_ID:;\n                    yyjson_mut_arr_add_int(doc, node, ((B_int)v)->val);\n                    break;\n                case U1_ID:;\n                    yyjson_mut_arr_add_uint(doc, node, ((B_u1)v)->val);\n                    break;\n                case U8_ID:;\n                    yyjson_mut_arr_add_uint(doc, node, ((B_u8)v)->val);\n                    break;\n                case U16_ID:;\n                    yyjson_mut_arr_add_uint(doc, node, ((B_u16)v)->val);\n                    break;\n                case U32_ID:;\n                    yyjson_mut_arr_add_uint(doc, node, ((B_u32)v)->val);\n                    break;\n                case U64_ID:;\n                    yyjson_mut_arr_add_uint(doc, node, ((B_u64)v)->val);\n                    break;\n                default:;\n                    // TODO: hmm, at least handle all builtin types? and that's it,\n                    // maybe? like we really shouldn't accept user-defined types\n                    // here, just throw an exception? or when we have unions, just\n                    // accept union of the types we support\n                    $RAISE(((B_BaseException)B_ValueErrorG_new($FORMAT(\"jsonQ_encode_list: unknown type: %s\", v->$class->$GCINFO))));\n            }\n        } else {\n            yyjson_mut_arr_add_null(doc, node);\n        }\n    }\n}\n\nB_list jsonQ_decode_arr(yyjson_val *);\n\nB_dict jsonQ_decode_obj(yyjson_val *obj) {\n\n    B_Hashable wit = (B_Hashable)B_HashableD_strG_witness;\n    B_dict res = $NEW(B_dict, wit, NULL, NULL);\n    yyjson_obj_iter iter;\n    yyjson_obj_iter_init(obj, &iter);\n    yyjson_val *key, *val;\n    while ((key = yyjson_obj_iter_next(&iter))) {\n        val = yyjson_obj_iter_get_val(key);\n\n        switch (yyjson_get_type(val)) {\n            case YYJSON_TYPE_NONE:;\n                break;\n            case YYJSON_TYPE_NULL:;\n                B_dictD_setitem(res, wit, to$str(yyjson_get_str(key)), B_None);\n                break;\n            case YYJSON_TYPE_BOOL:;\n                B_dictD_setitem(res, wit, to$str(yyjson_get_str(key)), toB_bool(yyjson_get_bool(val)));\n                break;\n            case YYJSON_TYPE_NUM:;\n                switch (yyjson_get_subtype(val)) {\n                    case YYJSON_SUBTYPE_UINT:;\n                        B_dictD_setitem(res, wit, to$str(yyjson_get_str(key)), toB_int(yyjson_get_int(val)));\n                        break;\n                    case YYJSON_SUBTYPE_SINT:;\n                        B_dictD_setitem(res, wit, to$str(yyjson_get_str(key)), toB_int(yyjson_get_int(val)));\n                        break;\n                    case YYJSON_SUBTYPE_REAL:;\n                        B_dictD_setitem(res, wit, to$str(yyjson_get_str(key)), to$float(yyjson_get_real(val)));\n                        break;\n                }\n                break;\n            case YYJSON_TYPE_STR:;\n                B_dictD_setitem(res, wit, to$str(yyjson_get_str(key)), to$str(yyjson_get_str(val)));\n                break;\n            case YYJSON_TYPE_ARR:;\n                B_list l = jsonQ_decode_arr(val);\n                B_dictD_setitem(res, wit, to$str(yyjson_get_str(key)), l);\n                break;\n            case YYJSON_TYPE_OBJ:;\n                B_dict d = jsonQ_decode_obj(val);\n                B_dictD_setitem(res, wit, to$str(yyjson_get_str(key)), d);\n                break;\n            default:;\n                // unreachable\n                $RAISE(((B_BaseException)B_ValueErrorG_new($FORMAT(\"jsonQ_encode_list: unknown type: %d\", yyjson_get_type(val)))));\n        }\n    }\n    return res;\n}\n\nB_list jsonQ_decode_arr(yyjson_val *arr) {\n    B_SequenceD_list wit = B_SequenceD_listG_witness;\n    B_list res = B_listG_new(NULL, NULL);\n    yyjson_val *val;\n    yyjson_arr_iter iter;\n    yyjson_arr_iter_init(arr, &iter);\n    while ((val = yyjson_arr_iter_next(&iter))) {\n        switch (yyjson_get_type(val)) {\n            case YYJSON_TYPE_NONE:\n                break;\n            case YYJSON_TYPE_NULL:;\n                wit->$class->append(wit, res, B_None);\n                break;\n            case YYJSON_TYPE_BOOL:;\n                wit->$class->append(wit, res, toB_bool(yyjson_get_bool(val)));\n                break;\n            case YYJSON_TYPE_NUM:;\n                switch (yyjson_get_subtype(val)) {\n                    case YYJSON_SUBTYPE_UINT:;\n                        wit->$class->append(wit, res, toB_int(yyjson_get_int(val)));\n                        break;\n                    case YYJSON_SUBTYPE_SINT:;\n                        wit->$class->append(wit, res, toB_int(yyjson_get_int(val)));\n                        break;\n                    case YYJSON_SUBTYPE_REAL:;\n                        wit->$class->append(wit, res, to$float(yyjson_get_real(val)));\n                        break;\n                }\n                break;\n            case YYJSON_TYPE_STR:;\n                wit->$class->append(wit, res, to$str(yyjson_get_str(val)));\n                break;\n            case YYJSON_TYPE_ARR:;\n                B_list l = jsonQ_decode_arr(val);\n                wit->$class->append(wit, res, l);\n                break;\n            case YYJSON_TYPE_OBJ:;\n                B_dict d = jsonQ_decode_obj(val);\n                wit->$class->append(wit, res, d);\n                break;\n            default:;\n                // TODO: just handle all types?\n                $RAISE(((B_BaseException)B_ValueErrorG_new($FORMAT(\"jsonQ_decode_arr: unknown type: %d\", yyjson_get_type(val)))));\n        }\n    }\n    return res;\n}\n\nB_dict jsonQ_decode (B_str data) {\n    // Read JSON and get root\n    yyjson_read_err err;\n    yyjson_doc *doc = yyjson_read_opts(fromB_str(data), strlen(fromB_str(data)), 0, &acton_alc, &err);\n    yyjson_val *root = yyjson_doc_get_root(doc);\n\n    B_dict res = $NEW(B_dict,(B_Hashable)B_HashableD_strG_witness,NULL,NULL);\n    // Iterate over the root object\n    if (doc) {\n        yyjson_val *obj = yyjson_doc_get_root(doc);\n        res = jsonQ_decode_obj(obj);\n    } else {\n        char errmsg[1024];\n        snprintf(errmsg, sizeof(errmsg), \"JSON parsing error: %s (%u) at position %ld\", err.msg, err.code, err.pos);\n        $RAISE((B_BaseException)$NEW(B_ValueError, to$str(errmsg)));\n    }\n\n    yyjson_doc_free(doc);\n    return res;\n}\n\nB_list jsonQ_decode_list (B_str data) {\n    // Read JSON and get root\n    yyjson_read_err err;\n    yyjson_doc *doc = yyjson_read_opts(fromB_str(data), strlen(fromB_str(data)), 0, &acton_alc, &err);\n    if (!doc) {\n        char errmsg[1024];\n        snprintf(errmsg, sizeof(errmsg), \"JSON parsing error: %s (%u) at position %ld\", err.msg, err.code, err.pos);\n        $RAISE((B_BaseException)$NEW(B_ValueError, to$str(errmsg)));\n    }\n\n    yyjson_val *root = yyjson_doc_get_root(doc);\n    if (yyjson_get_type(root) != YYJSON_TYPE_ARR) {\n        yyjson_doc_free(doc);\n        $RAISE(((B_BaseException)B_ValueErrorG_new(to$str(\"JSON root is not an array\"))));\n    }\n\n    B_list res = jsonQ_decode_arr(root);\n    yyjson_doc_free(doc);\n    return res;\n}\n\nB_str jsonQ_encode (B_dict data, B_bool pretty) {\n    if (pretty == NULL)\n        pretty = B_False;\n\n    // Create JSON document\n    yyjson_mut_doc *doc = yyjson_mut_doc_new(&acton_alc);\n    yyjson_mut_val *root = yyjson_mut_obj(doc);\n    yyjson_mut_doc_set_root(doc, root);\n\n    jsonQ_encode_dict(doc, root, data);\n\n    yyjson_write_err err;\n    int flags = 0;\n    if (pretty == B_True)\n        flags += YYJSON_WRITE_PRETTY;\n\n    char *json = yyjson_mut_write_opts(doc, flags, &acton_alc, NULL, &err);\n    //yyjson_doc_free(doc);\n    return to$str(json);\n}\n\nB_str jsonQ_encode_list (B_list data, B_bool pretty) {\n    if (pretty == NULL)\n        pretty = B_False;\n\n    // Create JSON document\n    yyjson_mut_doc *doc = yyjson_mut_doc_new(&acton_alc);\n    yyjson_mut_val *root = yyjson_mut_arr(doc);\n    yyjson_mut_doc_set_root(doc, root);\n\n    jsonQ_encode_list_into(doc, root, data);\n\n    yyjson_write_err err;\n    int flags = 0;\n    if (pretty == B_True)\n        flags += YYJSON_WRITE_PRETTY;\n\n    char *json = yyjson_mut_write_opts(doc, flags, &acton_alc, NULL, &err);\n    //yyjson_doc_free(doc);\n    return to$str(json);\n}\n"
  },
  {
    "path": "base/src/logging.act",
    "content": "r\"\"\"Advanced actor based logging\n\nThere are three main components to the logging system:\n- Loggers: each actor that wants to emit logs creates its own Logger object\n- Handlers: the Logger object sends log messages to an Handler actor\n- Sinks: Handlers sends log messages to a Sink actor for final output\n\nTogether, these components form a chain of actors that can be used to propagate,\nfilter, transform and output log messages.\n\nThe Logger object is the main interface for emitting log messages. Each actor\nthat wants to emit log messages needs to create at least one Logger object. The\nLogger forwards messages to a log Handler. It provides convenience methods for\neach log level, e.g. `.info(msg, data)` or `.error(msg, data)`. Each of these\nmethods takes a log message and an optional data dictionary for structured data,\nkeyed by strings. It is also possible to only log structured data. Not all\ndestination Sinks support structured data, in which case the structured data is\nflattened into a string representation.\n\nThe Handler receives log messages from Loggers. It can forward the messages to\na parent handler, making it possible to build a hierarchy of Handlers. At the\ntop of the hierarchy is the root Handler, which does not have a parent Handler.\nFor output, the Handler can also send the log messages to one or more Sinks.\nEach Handler has an associated output log level and only log messages of that\nlevel or higher importance will be propagated. By using a single log Handler for\na group of related actors, the log level can be controlled for all actors in the\ngroup with a single setting.\n\nSinks receives log messages from Handlers and are responsible for finally\noutputting the log messages. For example, the StdoutSink writes log messages to\nthe stdout while FileSink can write log messages to a file.\n\nHere's an illustrative example of Logger, Handler and Sink hierarchy:\n\n                                     .------------.\n                               .---->| SyslogSink |\n           .---------.         |     '------------'\n           | Handler |---------+\n           '---------'         |     .------------.\n              ^  ^             '---->| FileSink   |\n              |  |                   '------------'\n              |  '----------.\n              |             |\n           .---------.    .---------.   .------------.\n           | Handler |    | Handler |-->| StdoutSink |\n           '---------'    '---------'   '------------'\n              ^^^           ^^^  ^^^\n              |||           |||  ||'----------.\n              |||           |||  |'----------.|\n              |||           |||  '----------.||\n              |||           |||             |||\n        .----------.    .----------.    .----------.\n        | Actor w/ |.   | Actor w/ |.   | Actor w/ |.\n        | Logger   ||.  | Logger   ||.  | Logger   ||.\n        '----------'||  '----------'||  '----------'||\n         '----------'|   '----------'|   '----------'|\n          '----------'    '----------'    '----------'\n\nFor a simple application and in fact many large programs too, a single root\nHandler and a Sink or two is enough.\n\nLog Messages include the originating actor class and actor id. The Logger can be\ngiven a name, which can be useful if there is a human friendly name to the actor\ninstance like \"HTTP Worker 3\". The path taken by the message through the Handler\nhierarchy is recorded and is also included in the outputted form.\n\n         .------------------------------- date\n         |                  .------------ time\n         |                  |  .--------- timezone offset\n         |                  |  |     .--- level\n         |                  |  |     |\nvvvvvvvvvv vvvvvvvvvvvvvvvvvv vv vvvvv\n2023-09-11T22:23:39.185147227+02 DEBUG  MyApp>http>HTTP Worker 3: my_app.http.server[-17]: Received query - {'method': 'GET', 'path': '/foo'}\n                                        ^^^^^^^^^^^^^^^^^^^^^^^^  ^^^^^^^^^^^^^^^^^^ ^^^   ^^^^^^^^^^^^^^   ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n                                        |                         |                  |     |                |\n                      handler path -----'                         |                  |     |                |\n                       actor class -------------------------------'                  |     |                |\n                          actor id --------------------------------------------------'     |                |\n                       log message --------------------------------------------------------'                |\n                   structured data -------------------------------------------------------------------------'\n\"\"\"\n\nimport file\nimport time\n\n# Log levels\nUNSET, OFF, EMERGENCY, ALERT, CRITICAL, ERR, WARNING, INFO, NOTICE, DEBUG, VERBOSE, TRACE, ALL : int\nUNSET     = -2\nOFF       = -1\nEMERGENCY = 0\nALERT     = 1\nCRITICAL  = 2\n# TODO: 'ERROR' name conflicts on Windows as it is some macro on C-level\nERR       = 3\nWARNING   = 4\nINFO      = 5\nNOTICE    = 6\nDEBUG     = 7\nVERBOSE   = 8\nTRACE     = 9\nALL       = 999\n\nlvl_names = {\n    EMERGENCY : 'EMERG',\n    ALERT     : 'ALERT',\n    CRITICAL  : 'CRIT',\n    ERR       : 'ERROR',\n    WARNING   : 'WARN',\n    INFO      : 'INFO',\n    NOTICE    : 'NOTICE',\n    DEBUG     : 'DEBUG',\n    VERBOSE   : 'VERB',\n    TRACE     : 'TRACE',\n}\n\nclass Message():\n    \"\"\"A log message\n    \"\"\"\n    ts: time.DateTime\n    level: int\n    actor_class: str\n    actor_id: int\n    name: ?str\n    path: list[str]\n    msg: ?str\n    data: ?dict[str, ?value]\n\n    def __init__(self, level: int, path: list[str], name: ?str, msg: ?str, data: ?dict[str, ?value]):\n        self.ts = time.now()\n        self.level = level\n        self.name = name\n        self.path = path\n        self.msg = msg\n        self.data = data\n        self.actor_class = \"\"\n        self.actor_id = 0\n        self.actor_class = self._get_actor_class()\n        self.actor_id = self._get_actor_id()\n\n    def _get_actor_class(self) -> str:\n        NotImplemented\n\n    def _get_actor_id(self) -> int:\n        NotImplemented\n\n\nclass Formatter:\n    def __init__(self):\n        pass\n\n    def format(self, m: Message) -> ?str:\n        raise NotImplementedError(\"\")\n\n\nclass DefaultFormatter(Formatter):\n    def format(self, m: Message) -> ?str:\n        lvl_name = lvl_names[m.level]\n        msg = m.msg\n        data = m.data\n        if msg is None and data is None:\n            return\n        str_path = '>'.join(m.path)\n        text = f\"{str(m.ts)} {lvl_name:<7}\"\n        if len(str_path) > 0:\n            text += str_path + \": \"\n        text += f\"{m.actor_class}[{str(m.actor_id)}]: \"\n        if msg is not None:\n            text += msg\n        return text\n\n\nclass Sink(object):\n    \"\"\"A log sink\n    \"\"\"\n    formatter: Formatter\n\n    def __init__(self):\n        self.formatter = DefaultFormatter()\n\n    def set_formatter(self, formatter: Formatter):\n        self.formatter = formatter\n\n    proc def handle(self, m: Message):\n        raise NotImplementedError(\"\")\n\n\nclass StdoutSink(Sink):\n    \"\"\"Log sink that writes to stdout\n    \"\"\"\n    def handle(self, m: Message):\n        text = self.formatter.format(m)\n        if text is not None:\n            data = m.data\n            if data is not None:\n                text += \" - \" + str(data)\n            print(text)\n\nclass ConsoleSink(Sink):\n    \"\"\"Log sink that writes to the console, i.e. stderr\n    \"\"\"\n    def handle(self, m: Message):\n        text = self.formatter.format(m)\n        if text is not None:\n            data = m.data\n            if data is not None:\n                text += \" - \" + str(data)\n            print(text, err=True)\n\n# Untested and doesn't work yet?\n# TODO: implement this!\n#class FileSink(Sink):\n#    filename: str\n#    fh: file.WriteFile\n#\n#    def __init__(self, cap: file.WriteFileCap, filename: str):\n#        self.formatter = DefaultFormatter()\n#        self.filename = filename\n#        self.f = file.WriteFile(cap, filename)\n#\n#    def handle(self, m: Message):\n#        text = self.formatter.format(m)\n#        self.fh.write(text.encode())\n\n\nactor Handler(name: ?str):\n    var parent_handler: ?Handler = None\n    var sinks: list[Sink] = []\n    var output_level: int = ALL\n\n    def add_sink(sink: Sink):\n        sinks.append(sink)\n\n    def handle(m: Message):\n        if m.level <= output_level:\n            if name is not None:\n                m.path.insert(0, name)\n            if parent_handler is not None:\n                parent_handler.handle(m)\n            for sink in sinks:\n                sink.handle(m)\n\n    def set_handler(h: Handler):\n        parent_handler = h\n\n    def set_output_level(level: int):\n        output_level = level\n\n    def get_level() -> int:\n        return output_level\n\n\nclass Logger(object):\n    \"\"\"A logger\"\"\"\n    name: ?str\n    handler: ?Handler\n    output_level: int\n    last_check: time.Stopwatch\n\n    # TODO: Default name to actor type and ID\n    def __init__(self, handler: ?Handler):\n        self.name = None\n        self.handler = handler\n        self.output_level = UNSET\n        # TODO: enable, but it currently crashes?\n#        if handler is not None:\n#            self.output_level = handler.get_level()\n        self.last_check = time.Stopwatch()\n\n    def _set_level(self, level: int):\n        self.output_level = level\n\n    def log(self, level, msg, data: ?dict[str, ?value]):\n        handler = self.handler\n        if handler is not None:\n            path = []\n            n = self.name\n            if n is not None:\n                path = [n]\n            m = Message(level, path, self.name, msg, data)\n            # TODO: remove async here. It is an async call, but removing it leads to invalid AWAIT call, see\n            if self.output_level == UNSET or self.last_check.elapsed().to_float() > 0.1:\n                # TODO: do this async with a callback instead to avoid blocking\n                self.output_level = handler.get_level()\n                self.last_check = time.Stopwatch()\n            if level <= self.output_level:\n                async handler.handle(m)\n\n    def emergency(self, msg: ?str, data: ?dict[str, ?value]):\n        self.log(EMERGENCY, msg, data)\n\n    def alert(self, msg: ?str, data: ?dict[str, ?value]):\n        self.log(ALERT, msg, data)\n\n    def critical(self, msg: ?str, data: ?dict[str, ?value]):\n        self.log(CRITICAL, msg, data)\n\n    def error(self, msg: ?str, data: ?dict[str, ?value]):\n        self.log(ERR, msg, data)\n\n    def warning(self, msg: ?str, data: ?dict[str, ?value]):\n        self.log(WARNING, msg, data)\n\n    def info(self, msg: ?str, data: ?dict[str, ?value]):\n        self.log(INFO, msg, data)\n\n    def notice(self, msg: ?str, data: ?dict[str, ?value]):\n        self.log(NOTICE, msg, data)\n\n    def debug(self, msg: ?str, data: ?dict[str, ?value]):\n        self.log(DEBUG, msg, data)\n\n    def verbose(self, msg: ?str, data: ?dict[str, ?value]):\n        self.log(VERBOSE, msg, data)\n\n    def trace(self, msg: ?str, data: ?dict[str, ?value]):\n        self.log(TRACE, msg, data)\n"
  },
  {
    "path": "base/src/logging.ext.c",
    "content": "\nvoid loggingQ___ext_init__() {}\n\nB_int loggingQ_MessageD__get_actor_id (loggingQ_Message self) {\n    $Actor actor_self = GET_SELF();\n    return toB_int(actor_self->$globkey);\n}\n\nB_str loggingQ_MessageD__get_actor_class (loggingQ_Message self) {\n    $Actor actor_self = GET_SELF();\n    return to$str(unmangle_name(actor_self->$class->$GCINFO));\n}\n"
  },
  {
    "path": "base/src/math.act",
    "content": "# Copyright (C) 2019-2021 Data Ductus AB\n#\n# Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:\n#\n# 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.\n#\n# 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.\n#\n# 3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission.\n#\n# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS \"AS IS\" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n#\n\npi = 3.141592653589793\n\nprotocol RealFuns:\n    @staticmethod\n    sqrt       : (Self) -> Self\n    @staticmethod\n    exp        : (Self) -> Self\n    @staticmethod\n    log        : (Self) -> Self\n    @staticmethod\n    sin        : (Self) -> Self\n    @staticmethod\n    cos        : (Self) -> Self\n    @staticmethod\n    tan        : (Self) -> Self\n    @staticmethod\n    asin       : (Self) -> Self\n    @staticmethod\n    acos       : (Self) -> Self\n    @staticmethod\n    atan       : (Self) -> Self\n    @staticmethod\n    sinh       : (Self) -> Self\n    @staticmethod\n    cosh       : (Self) -> Self\n    @staticmethod\n    tanh       : (Self) -> Self\n    @staticmethod\n    asinh       : (Self) -> Self\n    @staticmethod\n    acosh       : (Self) -> Self\n    @staticmethod\n    atanh       : (Self) -> Self\n\nextension float (RealFuns):\n    NotImplemented\n\ndef sqrt(x: float):\n   return RealFuns.sqrt(x)\ndef exp(x: float):\n   return RealFuns.exp(x)\ndef log(x: float):\n   return RealFuns.log(x)\ndef sin(x: float):\n   return RealFuns.sin(x)\ndef cos(x: float):\n   return RealFuns.cos(x)\ndef tan(x: float):\n   return RealFuns.tan(x)\ndef asin(x: float):\n   return RealFuns.asin(x)\ndef acos(x: float):\n   return RealFuns.acos(x)\ndef atan(x: float):\n   return RealFuns.atan(x)\ndef sinh(x: float):\n   return RealFuns.sinh(x)\ndef cosh(x: float):\n   return RealFuns.cosh(x)\ndef tanh(x: float):\n   return RealFuns.tanh(x)\ndef asinh(x: float):\n   return RealFuns.asinh(x)\ndef acosh(x: float):\n   return RealFuns.acosh(x)\ndef atanh(x: float):\n   return RealFuns.atanh(x)\n"
  },
  {
    "path": "base/src/math.ext.c",
    "content": "B_float mathQ_RealFunsD_floatD_sqrt(mathQ_RealFunsD_float wit, B_float x) {\n  return to$float(sqrt(x->val));\n}\nB_float mathQ_RealFunsD_floatD_exp(mathQ_RealFunsD_float wit, B_float x) {\n  return to$float(exp(x->val));\n}\nB_float mathQ_RealFunsD_floatD_log(mathQ_RealFunsD_float wit, B_float x) {\n  return to$float(log(x->val));\n}\nB_float mathQ_RealFunsD_floatD_sin(mathQ_RealFunsD_float wit, B_float x) {\n  return to$float(sin(x->val));\n}\nB_float mathQ_RealFunsD_floatD_cos(mathQ_RealFunsD_float wit, B_float x) {\n  return to$float(cos(x->val));\n}\nB_float mathQ_RealFunsD_floatD_tan(mathQ_RealFunsD_float wit, B_float x) {\n  return to$float(tan(x->val));\n}\nB_float mathQ_RealFunsD_floatD_asin(mathQ_RealFunsD_float wit, B_float x) {\n  return to$float(asin(x->val));\n}\nB_float mathQ_RealFunsD_floatD_acos(mathQ_RealFunsD_float wit, B_float x) {\n  return to$float(acos(x->val));\n}\nB_float mathQ_RealFunsD_floatD_atan(mathQ_RealFunsD_float wit, B_float x) {\n  return to$float(atan(x->val));\n}\nB_float mathQ_RealFunsD_floatD_sinh(mathQ_RealFunsD_float wit, B_float x) {\n  return to$float(sinh(x->val));\n}\nB_float mathQ_RealFunsD_floatD_cosh(mathQ_RealFunsD_float wit, B_float x) {\n  return to$float(cosh(x->val));\n}\nB_float mathQ_RealFunsD_floatD_tanh(mathQ_RealFunsD_float wit, B_float x) {\n  return to$float(tanh(x->val));\n}\nB_float mathQ_RealFunsD_floatD_asinh(mathQ_RealFunsD_float wit, B_float x) {\n  return to$float(asinh(x->val));\n}\nB_float mathQ_RealFunsD_floatD_acosh(mathQ_RealFunsD_float wit, B_float x) {\n  return to$float(acosh(x->val));\n}\nB_float mathQ_RealFunsD_floatD_atanh(mathQ_RealFunsD_float wit, B_float x) {\n  return to$float(atanh(x->val));\n}\n\nvoid mathQ___ext_init__() {\n    //NOP\n};\n"
  },
  {
    "path": "base/src/net.act",
    "content": "\"\"\"Network IO\n\"\"\"\n\nclass NetCap():\n    \"\"\"Capability to access network\"\"\"\n    def __init__(self, cap: WorldCap):\n        pass\n\nclass DNSCap():\n    \"\"\"Capability to perform DNS queries\"\"\"\n    def __init__(self, cap: NetCap):\n        pass\n\nclass TCPCap():\n    \"\"\"Capability to connect or listen with TCP\"\"\"\n    def __init__(self, cap: NetCap):\n        pass\n\nclass TCPConnectCap():\n    \"\"\"Capability to connect using TCP to a remote host\"\"\"\n    def __init__(self, cap: TCPCap):\n        pass\n\nclass TCPListenCap():\n    \"\"\"Capability to listen with TCP\"\"\"\n    def __init__(self, cap: TCPCap):\n        pass\n\nclass _TCPListenConnectCap():\n    \"\"\"Internal use only\"\"\"\n    pass\n\ndef is_ipv4(address: str) -> bool:\n    NotImplemented\n\ndef is_ipv6(address: str) -> bool:\n    NotImplemented\n\ndef _lookup_a(name: str, on_resolve: action(list[str]) -> None, on_error: action(str, str) -> None) -> None:\n    \"\"\"Perform DNS lookup for name of record type A\n    \"\"\"\n    NotImplemented\n\ndef _lookup_aaaa(name: str, on_resolve: action(list[str]) -> None, on_error: action(str, str) -> None) -> None:\n    \"\"\"Perform DNS lookup for name of record type AAAA\n    \"\"\"\n    NotImplemented\n\n\ndef lookup_a(cap: DNSCap, name: str, on_resolve: action(list[str]) -> None, on_error: action(str, str) -> None) -> None:\n    \"\"\"Perform DNS lookup for name of record type A\n    \"\"\"\n    _lookup_a(name, on_resolve, on_error)\n\ndef lookup_aaaa(cap: DNSCap, name: str, on_resolve: action(list[str]) -> None, on_error: action(str, str) -> None) -> None:\n    \"\"\"Perform DNS lookup for name of record type AAAA\n    \"\"\"\n    _lookup_aaaa(name, on_resolve, on_error)\n\n\nactor TCPConnection(cap: TCPConnectCap, address: str, port: int, on_connect: action(TCPConnection) -> None, on_receive: action(TCPConnection, bytes) -> None, on_error: action(TCPConnection, str) -> None, on_remote_close: ?action(TCPConnection) -> None, connect_timeout: float=10.0):\n    \"\"\"TCP IP Connection\"\"\"\n    var _a_res: list[str] = []\n    var _aaaa_res: list[str] = []\n    var _sock = -1\n    var _sock4 = -1\n    var _sock4_state = 0\n    var _sock4_error = \"\"\n    var _sock6 = -1\n    var _sock6_state = 0\n    var _sock6_error = \"\"\n\n    STATE_NONE = 0\n    STATE_RESOLVING  = 1 # Resolving DNS\n    STATE_CONNECTING = 2 # Got DNS response or input was IP address so now doing TCP connect\n    STATE_CONNECTED  = 3 # TCP Connected\n    STATE_CLOSED     = 4 # TCP Connection disconnected / closed (it might never have been connected)\n    var _state = STATE_NONE\n\n    var _connections = 0\n    var _consecutive_connect_errors = 0\n    var _bytes_in: u64 = 0\n    var _bytes_out: u64 = 0\n\n    proc def _pin_affinity() -> None:\n        NotImplemented\n    _pin_affinity()\n\n    # TODO: we should not just connect to the first IPv4 and first IPv6 result\n    # but rather arrange them in order of preference and try them in that order,\n    # more details in Happy Eye Balls v2 https://tools.ietf.org/html/rfc8305\n\n    # DNS A\n    def _on_dns_a_resolve(result):\n        _a_res = result\n        _sock4_state = STATE_CONNECTING\n        _state = STATE_CONNECTING\n        _connect4(result[0])\n\n    def _on_dns_a_error(name, msg):\n        if _state == STATE_RESOLVING:\n            after 0.1: _lookup_a(address, _on_dns_a_resolve, _on_dns_a_error)\n\n    # DNS AAAA\n    def _on_dns_aaaa_resolve(result):\n        _aaaa_res = result\n        _sock6_state = STATE_CONNECTING\n        _state = STATE_CONNECTING\n        _connect6(result[0])\n\n    def _on_dns_aaaa_error(name, msg):\n        if _state == STATE_RESOLVING:\n            after 0.1: _lookup_aaaa(address, _on_dns_aaaa_resolve, _on_dns_aaaa_error)\n\n    action def _on_tcp_error(sockfamily: int, err: int, errmsg: str):\n        if sockfamily == 4:\n            if _sock6_state == STATE_NONE: # IPv4 only connection\n                _consecutive_connect_errors += 1\n                on_error(self, errmsg)\n            else: # dual stack connection\n                # wait for other socket to connect or fail\n                if _sock6_error != \"\":\n                    _consecutive_connect_errors += 1\n                    on_error(self, errmsg + \"  IPv6 error: \" + _sock6_error)\n            _sock4_error = errmsg\n        elif sockfamily == 6:\n            if _sock4_state == STATE_NONE: # IPv6 only connection\n                _consecutive_connect_errors += 1\n                on_error(self, errmsg)\n            else: # dual stack connection\n                # wait for other socket to connect or fail\n                if _sock4_error != \"\":\n                    _consecutive_connect_errors += 1\n                    on_error(self, errmsg + \"  IPv4 error: \" + _sock4_error)\n            _sock6_error = errmsg\n\n    # TCP connect over IPv4\n    proc def _connect4(ip_address: str):\n        NotImplemented\n\n    # TCP connect over IPv6\n    proc def _connect6(ip_address: str):\n        NotImplemented\n\n    action def _on_connect4():\n        _sock4_state = STATE_CONNECTED\n        _sock4_error = \"\"\n        if _sock6_state == STATE_CONNECTED:\n            # If IPv6 is already connected, we (IPv4) lost, so close our socket\n            # TODO: close IPv4 socket\n            return\n        _on_connect(_sock4)\n\n    action def _on_connect6():\n        _sock6_state = STATE_CONNECTED\n        _sock6_error = \"\"\n        if _sock4_state == STATE_CONNECTED:\n            # If IPv4 is already connected, we (IPv6) lost, so close our socket\n            # TODO: close IPv6 socket\n            return\n        _on_connect(_sock6)\n\n    # Handle on_connect event\n    proc def _on_connect(sock: int):\n        if _state == STATE_CONNECTING:\n            _state = STATE_CONNECTED\n            _sock = sock\n            _read_start()\n            _connections += 1\n            _consecutive_connect_errors = 0\n            on_connect(self)\n        elif _state == STATE_CONNECTED:\n            # It is normal to get multiple on_connect events since we are doing\n            # Happy Eyeballs and letting IPv4 race against IPv6, however, those\n            # should be cancelled out in the _on_connect[46] functions above.\n            pass\n        else:\n            # We don't expect to establish a connection in any other state\n            # TODO: use RTS log instead\n            print(\"Unexpected state\", _state)\n\n    proc def _read_start():\n        NotImplemented\n\n    action def write(data: bytes) -> None:\n        \"\"\"Write data to remote\"\"\"\n        NotImplemented\n\n    action def close(on_close: action(TCPConnection) -> None) -> None:\n        \"\"\"Close the connection\"\"\"\n        NotImplemented\n\n    def _connect_timeout():\n        if _state == STATE_CONNECTING:\n            _state = STATE_CLOSED\n            _consecutive_connect_errors += 1\n            def _on_close(c):\n                on_error(self, \"Connection attempt failed due to timeout\")\n            close(_on_close)\n\n    def reconnect():\n        close(_connect)\n\n    def _connect(c):\n        # TODO: would be nice to cancel connect_timeout when connection succeeds\n        after connect_timeout: _connect_timeout()\n        if is_ipv4(address):\n            _sock4_state = STATE_CONNECTING\n            _state = STATE_CONNECTING\n            _connect4(address)\n        elif is_ipv6(address):\n            _sock6_state = STATE_CONNECTING\n            _state = STATE_CONNECTING\n            _connect6(address)\n        else:\n            _state = STATE_RESOLVING\n            _lookup_aaaa(address, _on_dns_aaaa_resolve, _on_dns_aaaa_error)\n            # TODO: delay this by a few milliseconds to give IPv6 a slight preference\n            _lookup_a(address, _on_dns_a_resolve, _on_dns_a_error)\n\n    mut def __resume__() -> None:\n        NotImplemented\n\n    action def ip_version() -> ?int:\n        NotImplemented\n\n    action def local_address() -> str:\n        NotImplemented\n\n    action def remote_address() -> str:\n        NotImplemented\n\n    action def metrics():\n        return (connections=_connections,\n                consecutive_connect_errors=_consecutive_connect_errors,\n                bytes_in=_bytes_in,\n                bytes_out=_bytes_out)\n\n    _connect(self)\n\n\nactor TCPListenConnection(cap: _TCPListenConnectCap, server_client: int):\n    \"\"\"TCP Listener Connection\"\"\"\n    var client: int = -1\n    var on_receive: ?action(TCPListenConnection, bytes) -> None = None\n    var on_error: ?action(TCPListenConnection, str) -> None = None\n    var on_remote_close: ?action(TCPListenConnection) -> None = None\n    var _initialized = False\n\n    proc def _read_start():\n        \"\"\"Implementation internal\"\"\"\n        NotImplemented\n\n    action def cb_install(new_on_receive: action(TCPListenConnection, bytes) -> None, new_on_error: action(TCPListenConnection, str) -> None, new_on_remote_close: ?action(TCPListenConnection) -> None) -> None:\n        \"\"\"Install callback handlers\"\"\"\n        on_receive = new_on_receive\n        on_error = new_on_error\n        on_remote_close = new_on_remote_close\n        if not _initialized:\n            _read_start()\n            _initialized = True\n\n    action def close() -> None:\n        \"\"\"Close connection\"\"\"\n        NotImplemented\n\n    action def write(data: bytes) -> None:\n        \"\"\"Write data to remote\"\"\"\n        NotImplemented\n\n    mut def __resume__() -> None:\n        NotImplemented\n\n    proc def _init() -> None:\n        \"\"\"Implementation internal\"\"\"\n        NotImplemented\n    _init()\n\nactor TCPListener(cap: TCPListenCap, address: str, port: int, on_listen: action(TCPListener, ?str) -> None, on_accept: action(TCPListenConnection) -> None):\n    \"\"\"TCP Listener\"\"\"\n    _stream = -1\n    def create_tcp_listen_connection(cap: _TCPListenConnectCap, client: int):\n        \"\"\"Implementation internal\"\"\"\n        c = TCPListenConnection(cap, client)\n        on_accept(c)\n\n    mut def __resume__() -> None:\n        NotImplemented\n\n    proc def _init():\n        \"\"\"Implementation internal\"\"\"\n        NotImplemented\n    _init()\n\nactor TLSListenConnection(cap: _TCPListenConnectCap, server_stream: int):\n    \"\"\"TLS Listener Connection\"\"\"\n    var _stream = -1\n    var on_receive: ?action(TLSListenConnection, bytes) -> None = None\n    var on_error: ?action(TLSListenConnection, str) -> None = None\n    var on_remote_close: ?action(TLSListenConnection) -> None = None\n    var _initialized = False\n\n    proc def _read_start():\n        \"\"\"Implementation internal\"\"\"\n        NotImplemented\n\n    action def cb_install(new_on_receive: action(TLSListenConnection, bytes) -> None, new_on_error: action(TLSListenConnection, str) -> None, new_on_remote_close: ?action(TLSListenConnection) -> None) -> None:\n        \"\"\"Install callback handlers\"\"\"\n        on_receive = new_on_receive\n        on_error = new_on_error\n        on_remote_close = new_on_remote_close\n        if not _initialized:\n            _read_start()\n            _initialized = True\n\n    action def close() -> None:\n        \"\"\"Close connection\"\"\"\n        NotImplemented\n\n    action def write(data: bytes) -> None:\n        \"\"\"Write data to remote\"\"\"\n        NotImplemented\n\n    mut def __resume__() -> None:\n        NotImplemented\n\n    proc def _init() -> None:\n        \"\"\"Implementation internal\"\"\"\n        NotImplemented\n    _init()\n\nactor TLSListener(cap: TCPListenCap, address: str, port: int, cert_pem: bytes, key_pem: bytes, on_listen: action(TLSListener, ?str) -> None, on_accept: action(TLSListenConnection) -> None):\n    \"\"\"TLS Listener\"\"\"\n    _stream = -1\n    _tls_ctx = -1\n    def create_tls_listen_connection(cap: _TCPListenConnectCap, stream: int):\n        \"\"\"Implementation internal\"\"\"\n        c = TLSListenConnection(cap, stream)\n        on_accept(c)\n\n    mut def __resume__() -> None:\n        NotImplemented\n\n    proc def _init():\n        \"\"\"Implementation internal\"\"\"\n        NotImplemented\n    _init()\n\nactor TLSConnection(cap: TCPConnectCap, address: str, port: int, on_connect: action(TLSConnection) -> None, on_receive: action(TLSConnection, bytes) -> None, on_error: action(TLSConnection, str) -> None, on_remote_close: ?action(TLSConnection) -> None, verify_tls: bool=True, protocols: list[str]=[]):\n    # TODO: support hostname/CN mismatch, good when connecting with IP address?\n    # TODO: do DNS lookup in Acton\n    # TODO: support ALPN\n    # TODO: support SNI\n    # TODO: support client certificates\n    # TODO: implement state machine\n    # TODO: support timeout\n    # TODO: do Happy Eyeballs\n    var _stream = -1\n\n    var _on_close: ?action(TLSConnection) -> None = None\n\n    var _connections = 0\n    var _consecutive_connect_errors = 0\n    var _bytes_in: u64 = 0\n    var _bytes_out: u64 = 0\n\n    proc def _pin_affinity() -> None:\n        NotImplemented\n    _pin_affinity()\n\n    action def _on_tls_connect():\n        _connections += 1\n        on_connect(self)\n\n    action def _on_tls_error(sockfamily: int, err: int, errmsg: str):\n        on_error(self, errmsg)\n\n    action def close(on_close: action(TLSConnection) -> None) -> None:\n        \"\"\"Close the connection\"\"\"\n        NotImplemented\n\n    action def write(data: bytes) -> None:\n        \"\"\"Write data to remote\"\"\"\n        NotImplemented\n\n    def reconnect():\n        close(_connect)\n\n    proc def _connect_tls():\n        NotImplemented\n\n    proc def _connect(c):\n        _connect_tls()\n    _connect(self)\n"
  },
  {
    "path": "base/src/net.ext.c",
    "content": "#define GC_THREADS 1\n#ifdef _WIN32\n#include <winsock2.h>\n#endif\n#include <gc.h>\n\n#include <stdint.h>\n#include <tlsuv/tlsuv.h>\n#include <uv.h>\n#include <errno.h>\n#include <stdio.h>\n#include <string.h>\n#ifndef _WIN32\n#include <unistd.h>\n#endif\n#include \"../rts/io.h\"\n#include \"../rts/log.h\"\n\nvoid netQ___ext_init__() {\n    // NOP\n}\n\n\nB_bool netQ_is_ipv4 (B_str address) {\n    struct sockaddr_in sa;\n    if (inet_pton(AF_INET, (const char *)fromB_str(address), &(sa.sin_addr)) == 0) {\n        return B_False;\n    } else {\n        return B_True;\n    }\n}\n\nB_bool netQ_is_ipv6 (B_str address) {\n    struct sockaddr_in6 sa;\n    if (inet_pton(AF_INET6, (const char *)fromB_str(address), &(sa.sin6_addr)) == 0) {\n        return B_False;\n    } else {\n        return B_True;\n    }\n}\n\nstruct dns_cb_data {\n    struct addrinfo *hints;\n    char* hostname;\n    $action on_resolve;\n    $action2 on_error;\n};\n\nstatic void _lookup_a__on_resolve (uv_getaddrinfo_t *req, int status, struct addrinfo *dns_res) {\n    struct dns_cb_data *cb_data = req->data;\n    B_list $res = B_listG_new(NULL, NULL);\n\n    if (status != 0) {\n        char errmsg[1024] = \"DNS lookup error: \";\n        uv_strerror_r(status, errmsg + strlen(errmsg), sizeof(errmsg)-strlen(errmsg));\n        $action2 f = ($action2)cb_data->on_error;\n        f->$class->__asyn__(f, to$str(cb_data->hostname), to$str(errmsg));\n\n        // No free with GC, but maybe one day we do this explicitly?\n        //uv_freeaddrinfo(dns_res);\n        //free(cb_data->hints);\n        //free(cb_data);\n        //free(req);\n        return;\n    }\n\n    struct addrinfo *rp;\n    char addr[17] = {'\\0'};\n    for (rp = dns_res; rp != NULL; rp = rp->ai_next) {\n        uv_ip4_name((struct sockaddr_in*) rp->ai_addr, addr, 16);\n        B_SequenceD_listG_witness->$class->append(B_SequenceD_listG_witness, $res, to$str(addr));\n    }\n\n    $action f = ($action)cb_data->on_resolve;\n    f->$class->__asyn__(f, $res);\n\n    // No free with GC, but maybe one day we do this explicitly?\n    //uv_freeaddrinfo(dns_res);\n    //free(cb_data->hints);\n    //free(cb_data);\n    //free(req);\n}\n\nB_NoneType netQ__lookup_a (B_str name, $action on_resolve, $action on_error) {\n    struct addrinfo *hints = (struct addrinfo *)acton_malloc(sizeof(struct addrinfo));\n    hints->ai_family = PF_INET;\n    hints->ai_socktype = SOCK_STREAM;\n    hints->ai_protocol = IPPROTO_TCP;\n    hints->ai_flags = 0;\n\n    struct dns_cb_data *cb_data = (struct dns_cb_data *)acton_malloc(sizeof(struct dns_cb_data));\n    cb_data->hints = hints;\n    cb_data->hostname = (char *)fromB_str(name);\n    cb_data->on_resolve = on_resolve;\n    cb_data->on_error = ($action2) on_error;\n\n    uv_getaddrinfo_t *req = (uv_getaddrinfo_t*)acton_malloc(sizeof(uv_getaddrinfo_t));\n    req->data = cb_data;\n\n    int r = uv_getaddrinfo(get_uv_loop(), req, _lookup_a__on_resolve, (const char *)fromB_str(name), NULL, hints);\n    if (r != 0) {\n        char errmsg[1024] = \"Unable to run DNS query: \";\n        uv_strerror_r(r, errmsg + strlen(errmsg), sizeof(errmsg)-strlen(errmsg));\n        log_warn(errmsg);\n        $action2 f = ($action2)cb_data->on_error;\n        f->$class->__asyn__(f, name, to$str(errmsg));\n        // NOTE: free() here if do manual memory management in I/O one day\n        return B_None;\n    }\n\n    return B_None;\n}\n\nstatic void _lookup_aaaa__on_resolve (uv_getaddrinfo_t *req, int status, struct addrinfo *dns_res) {\n    struct dns_cb_data *cb_data = req->data;\n    B_list $res = B_listG_new(NULL, NULL);\n\n    if (status != 0) {\n        char errmsg[1024] = \"DNS lookup error: \";\n        uv_strerror_r(status, errmsg + strlen(errmsg), sizeof(errmsg)-strlen(errmsg));\n        $action2 f = ($action2)cb_data->on_error;\n        f->$class->__asyn__(f, to$str(cb_data->hostname), to$str(errmsg));\n\n        // No free with GC, but maybe one day we do this explicitly?\n        //uv_freeaddrinfo(dns_res);\n        //free(cb_data->hints);\n        //free(cb_data);\n        //free(req);\n        return;\n    }\n\n    struct addrinfo *rp;\n    char addr[40] = {'\\0'};\n    for (rp = dns_res; rp != NULL; rp = rp->ai_next) {\n        uv_ip6_name((struct sockaddr_in6*)rp->ai_addr, addr, 39);\n        B_SequenceD_listG_witness->$class->append(B_SequenceD_listG_witness, $res, to$str(addr));\n    }\n\n    $action f = ($action)cb_data->on_resolve;\n    f->$class->__asyn__(f, $res);\n\n    // No free with GC, but maybe one day we do this explicitly?\n    //uv_freeaddrinfo(dns_res);\n    //free(cb_data->hints);\n    //free(cb_data);\n    //free(req);\n}\n\nB_NoneType netQ__lookup_aaaa (B_str name, $action on_resolve, $action on_error) {\n    struct addrinfo *hints = (struct addrinfo *)acton_malloc(sizeof(struct addrinfo));\n    hints->ai_family = PF_INET6;\n    hints->ai_socktype = SOCK_STREAM;\n    hints->ai_protocol = IPPROTO_TCP;\n    hints->ai_flags = 0;\n\n    struct dns_cb_data *cb_data = (struct dns_cb_data *)acton_malloc(sizeof(struct dns_cb_data));\n    cb_data->hints = hints;\n    cb_data->hostname = (char *)fromB_str(name);\n    cb_data->on_resolve = on_resolve;\n    cb_data->on_error = ($action2)on_error;\n\n    uv_getaddrinfo_t *req = (uv_getaddrinfo_t*)acton_malloc(sizeof(uv_getaddrinfo_t));\n    req->data = cb_data;\n\n    int r = uv_getaddrinfo(get_uv_loop(), req, _lookup_aaaa__on_resolve, (const char *)fromB_str(name), NULL, hints);\n    if (r != 0) {\n        char errmsg[1024] = \"Unable to run DNS query: \";\n        uv_strerror_r(r, errmsg + strlen(errmsg), sizeof(errmsg)-strlen(errmsg));\n        log_warn(errmsg);\n        $action2 f = ($action2)cb_data->on_error;\n        f->$class->__asyn__(f, name, to$str(errmsg));\n        // NOTE: free() here if do manual memory management in I/O one day\n        return B_None;\n    }\n\n    return B_None;\n}\n\nvoid netQ_TCPConnection__on_receive(uv_stream_t *stream, ssize_t nread, const uv_buf_t *buf) {\n    if (nread < 0){\n        if (nread == UV_EOF) {\n            netQ_TCPConnection self = stream->data;\n            if ((intptr_t)stream != -1)\n                uv_close((uv_handle_t *)stream, NULL);\n            self->_sock = toB_int(-1);\n            self->_sock4 = toB_int(-1);\n            self->_sock6 = toB_int(-1);\n            if (self->on_remote_close) {\n                $action f = ($action)self->on_remote_close;\n                f->$class->__asyn__(f, self);\n            }\n        }\n    } else if (nread > 0) {\n        if (stream->data) {\n            netQ_TCPConnection self = stream->data;\n            $action2 f = ($action2)self->on_receive;\n            f->$class->__asyn__(f, self, to$bytesD_len(buf->base, nread));\n            self->_bytes_in->val += nread;\n        }\n    }\n}\n\n\n$R netQ_TCPConnectionD__pin_affinityG_local (netQ_TCPConnection self, $Cont c$cont) {\n    pin_actor_affinity();\n    return $R_CONT(c$cont, B_None);\n}\n\nvoid on_connect4(uv_connect_t *connect_req, int status) {\n    netQ_TCPConnection self = (netQ_TCPConnection)connect_req->data;\n\n    if (status != 0) {\n        char errmsg[1024] = \"Error in TCP connect over IPv4: \";\n        uv_strerror_r(status, errmsg + strlen(errmsg), sizeof(errmsg)-strlen(errmsg));\n        log_warn(errmsg);\n        self->$class->_on_tcp_error(self, toB_int(4), toB_int(status), to$str(errmsg));\n        return;\n    }\n    self->$class->_on_connect4(self);\n}\n\nvoid on_connect6(uv_connect_t *connect_req, int status) {\n    netQ_TCPConnection self = (netQ_TCPConnection)connect_req->data;\n\n    if (status != 0) {\n        char errmsg[1024] = \"Error in TCP connect over IPv6: \";\n        uv_strerror_r(status, errmsg + strlen(errmsg), sizeof(errmsg)-strlen(errmsg));\n        log_warn(errmsg);\n        self->$class->_on_tcp_error(self, toB_int(6), toB_int(status), to$str(errmsg));\n        return;\n    }\n    self->$class->_on_connect6(self);\n}\n\n$R netQ_TCPConnectionD__connect4G_local (netQ_TCPConnection self, $Cont c$cont, B_str ip_address) {\n    log_debug(\"TCP connecting over IPv4 to %s\", fromB_str(ip_address));\n    uv_tcp_t* socket = (uv_tcp_t*)acton_malloc(sizeof(uv_tcp_t));\n    uv_tcp_init(get_uv_loop(), socket);\n    self->_sock4 = toB_int((int64_t)(intptr_t)socket);\n\n    uv_connect_t* connect_req = (uv_connect_t*)acton_malloc(sizeof(uv_connect_t));\n    connect_req->data = (void *)self;\n\n    struct sockaddr_in dest;\n    uv_ip4_addr((const char *)fromB_str(ip_address), fromB_int(self->port), &dest);\n\n    uv_tcp_connect(connect_req, socket, (const struct sockaddr*)&dest, on_connect4);\n\n    return $R_CONT(c$cont, B_None);\n}\n\n$R netQ_TCPConnectionD__connect6G_local (netQ_TCPConnection self, $Cont c$cont, B_str ip_address) {\n    log_debug(\"TCP connecting over IPv6 to %s\", fromB_str(ip_address));\n    uv_tcp_t* socket = (uv_tcp_t*)acton_malloc(sizeof(uv_tcp_t));\n    uv_tcp_init(get_uv_loop(), socket);\n    self->_sock6 = toB_int((int64_t)(intptr_t)socket);\n\n    uv_connect_t* connect_req = (uv_connect_t*)acton_malloc(sizeof(uv_connect_t));\n    connect_req->data = (void *)self;\n\n    struct sockaddr_in6 dest;\n    uv_ip6_addr((const char *)fromB_str(ip_address), fromB_int(self->port), &dest);\n\n    uv_tcp_connect(connect_req, socket, (const struct sockaddr*)&dest, on_connect6);\n\n    return $R_CONT(c$cont, B_None);\n}\n\n$R netQ_TCPConnectionD__read_startG_local (netQ_TCPConnection self, $Cont c$cont) {\n    uv_tcp_t* socket = (uv_tcp_t *)fromB_int(self->_sock);\n    socket->data = self;\n    int r = uv_read_start((uv_stream_t *)socket, alloc_buffer, netQ_TCPConnection__on_receive);\n    if (r < 0) {\n        char errmsg[1024] = \"Failed to start reading from TCP client socket: \";\n        uv_strerror_r(r, errmsg + strlen(errmsg), sizeof(errmsg)-strlen(errmsg));\n        log_warn(errmsg);\n        $action2 f = ($action2)self->on_error;\n        f->$class->__asyn__(f, self, to$str(errmsg));\n        return $R_CONT(c$cont, B_None);\n    }\n\n    return $R_CONT(c$cont, B_None);\n}\n\n$R netQ_TCPConnectionD_writeG_local (netQ_TCPConnection self, $Cont c$cont, B_bytes data) {\n    uv_stream_t *stream = (uv_stream_t *)fromB_int(self->_sock);\n    // fd == -1 means invalid FD and can happen after __resume__\n    if ((intptr_t)stream == -1)\n        return $R_CONT(c$cont, B_None);\n\n    uv_write_t *req = (uv_write_t *)acton_malloc(sizeof(uv_write_t));\n    uv_buf_t buf = uv_buf_init((char *)data->str, data->nbytes);\n    int r = uv_write(req, stream, &buf, 1, NULL);\n    if (r < 0) {\n        char errmsg[1024] = \"Failed to write to TCP socket: \";\n        uv_strerror_r(r, errmsg + strlen(errmsg), sizeof(errmsg)-strlen(errmsg));\n        log_warn(errmsg);\n        $action2 f = ($action2)self->on_error;\n        f->$class->__asyn__(f, self, to$str(errmsg));\n    }\n    self->_bytes_out->val += data->nbytes;\n    return $R_CONT(c$cont, B_None);\n}\n\nB_NoneType netQ_TCPConnectionD___resume__ (netQ_TCPConnection self) {\n    self->_sock = toB_int(-1);\n    self->_sock4 = toB_int(-1);\n    self->_sock6 = toB_int(-1);\n    $action2 f = ($action2)self->on_error;\n    f->$class->__asyn__(f, self, to$str(\"resume\"));\n    return B_None;\n}\n\nstruct close_cb_data {\n    netQ_TCPConnection self;\n    $action on_close;\n};\n\nstatic void after_shutdown(uv_shutdown_t* req, int status) {\n    log_debug(\"TCP Shutdown complete, closing handle\");\n    if (status < 0)\n        log_warn(\"Error in TCP shutdown: %s\", uv_strerror(status));\n    uv_close((uv_handle_t*)req->handle, NULL);\n    struct close_cb_data *cb_data = (struct close_cb_data *)req->data;\n    $action on_close = ($action)cb_data->on_close;\n    on_close->$class->__asyn__(on_close, cb_data->self);\n}\n\n$R netQ_TCPConnectionD_closeG_local (netQ_TCPConnection self, $Cont c$cont, $action on_close) {\n    uv_stream_t *stream = (uv_stream_t *)fromB_int(self->_sock);\n    // fd == -1 means invalid FD and can happen after __resume__\n    if ((intptr_t)stream == -1) {\n        on_close->$class->__asyn__(on_close, self);\n        return $R_CONT(c$cont, B_None);\n    }\n\n    log_debug(\"Closing TCP connection\");\n    struct close_cb_data *cb_data = (struct close_cb_data *)acton_malloc(sizeof(struct close_cb_data));\n    cb_data->self = self;\n    cb_data->on_close = on_close;\n    uv_shutdown_t *req = (uv_shutdown_t *)acton_malloc(sizeof(uv_shutdown_t));\n    req->data = (void *)cb_data;\n    int r = uv_shutdown(req, stream, after_shutdown);\n    self->_sock = toB_int(-1);\n    self->_sock4 = toB_int(-1);\n    self->_sock6 = toB_int(-1);\n    if (r < 0) {\n        // TODO: we could probably ignore most or all of these errors as the\n        // purpose is to shutdown our side of the connection and many of these\n        // errors are about \"not connected\" or \"already closed\", turning this\n        // into a NOP\n        char errmsg[1024] = \"Failed to shutdown TCP client socket: \";\n        uv_strerror_r(r, errmsg + strlen(errmsg), sizeof(errmsg)-strlen(errmsg));\n        log_warn(errmsg);\n        on_close->$class->__asyn__(on_close, self);\n        // TODO: we should always call uv_close() here\n        return $R_CONT(c$cont, B_None);\n    }\n    return $R_CONT(c$cont, B_None);\n}\n\n$R netQ_TCPConnectionD_ip_versionG_local (netQ_TCPConnection self, $Cont c$cont) {\n    struct sockaddr_storage peername;\n    int namelen = sizeof(peername);\n    if (uv_tcp_getpeername((const uv_tcp_t *)fromB_int(self->_sock), (struct sockaddr*)&peername, &namelen) == 0) {\n        if (peername.ss_family == AF_INET) {\n            return $R_CONT(c$cont, toB_int(4));\n        } else if (peername.ss_family == AF_INET6) {\n            return $R_CONT(c$cont, toB_int(6));\n        } else {\n            log_error(\"Unhandled AFI\");\n        }\n    } else {\n        log_error(\"Failed to get peer name from handle %d\", fromB_int(self->_sock));\n    }\n    return $R_CONT(c$cont, B_None);\n}\n\n$R netQ_TCPConnectionD_local_addressG_local (netQ_TCPConnection self, $Cont c$cont) {\n    struct sockaddr_storage sockname;\n    int namelen = sizeof(sockname);\n    char addr[INET6_ADDRSTRLEN] = { '\\0' };\n    if (uv_tcp_getsockname((const uv_tcp_t *)fromB_int(self->_sock), (struct sockaddr*)&sockname, &namelen) == 0) {\n        if (sockname.ss_family == AF_INET) {\n            uv_ip4_name((struct sockaddr_in*)&sockname, addr, sizeof(addr));\n        } else if (sockname.ss_family == AF_INET6) {\n            uv_ip6_name((struct sockaddr_in6*)&sockname, addr, sizeof(addr));\n        } else {\n            log_error(\"Unhandled AFI\");\n        }\n    } else {\n        log_error(\"Failed to get sock name from handle %d\", fromB_int(self->_sock));\n    }\n    return $R_CONT(c$cont, to$str(addr));\n}\n\n$R netQ_TCPConnectionD_remote_addressG_local (netQ_TCPConnection self, $Cont c$cont) {\n    struct sockaddr_storage peername;\n    int namelen = sizeof(peername);\n    char addr[INET6_ADDRSTRLEN] = { '\\0' };\n    if (uv_tcp_getpeername((const uv_tcp_t *)fromB_int(self->_sock), (struct sockaddr*)&peername, &namelen) == 0) {\n        if (peername.ss_family == AF_INET) {\n            uv_ip4_name((struct sockaddr_in*)&peername, addr, sizeof(addr));\n        } else if (peername.ss_family == AF_INET6) {\n            uv_ip6_name((struct sockaddr_in6*)&peername, addr, sizeof(addr));\n        } else {\n            log_error(\"Unhandled AFI\");\n        }\n    } else {\n        log_error(\"Failed to get peer name from handle %d\", fromB_int(self->_sock));\n    }\n    return $R_CONT(c$cont, to$str(addr));\n}\n\n\nvoid on_new_connection(uv_stream_t *server, int status) {\n    netQ_TCPListener self = (netQ_TCPListener)server->data;\n\n    if (status != 0) {\n        char errmsg[1024] = \"Error on new TCP client connection: \";\n        uv_strerror_r(status, errmsg + strlen(errmsg), sizeof(errmsg)-strlen(errmsg));\n        log_warn(errmsg);\n        $action2 f = ($action2)self->on_listen;\n        f->$class->__asyn__(f, self, to$str(errmsg));\n        // NOTE: free() here if do manual memory management in I/O one day\n        return;\n    }\n\n    uv_tcp_t *client = (uv_tcp_t*)acton_malloc(sizeof(uv_tcp_t));\n    uv_tcp_init(get_uv_loop(), client);\n    int r = uv_accept(server, (uv_stream_t *)client);\n    if (r != 0) {\n        char errmsg[1024] = \"Error in accepting TCP client connection: \";\n        uv_strerror_r(r, errmsg + strlen(errmsg), sizeof(errmsg)-strlen(errmsg));\n        log_warn(errmsg);\n        $action2 f = ($action2)self->on_listen;\n        f->$class->__asyn__(f, self, to$str(errmsg));\n        // NOTE: free() here if do manual memory management in I/O one day\n        return;\n    }\n\n    self->$class->create_tcp_listen_connection(self, B_None, toB_int((int64_t)(intptr_t)client));\n    // NOTE: free() here if do manual memory management in I/O one day\n}\n\n\n$R netQ_TCPListenerD__initG_local (netQ_TCPListener self, $Cont c$cont) {\n    pin_actor_affinity();\n\n    uv_tcp_t *server = (uv_tcp_t *)acton_malloc(sizeof(uv_tcp_t));\n    uv_tcp_init(get_uv_loop(), server);\n    server->data = (void *)self;\n    int r;\n    struct sockaddr_in addr4;\n    struct sockaddr_in6 addr6;\n    if (inet_pton(AF_INET, (const char *)fromB_str(self->address), &(addr4.sin_addr)) == 1) {\n        r = uv_ip4_addr((const char *)fromB_str(self->address), fromB_int(self->port), &addr4);\n    } else if (inet_pton(AF_INET6, (const char *)fromB_str(self->address), &(addr6.sin6_addr)) == 1) {\n        r = uv_ip6_addr((const char *)fromB_str(self->address), fromB_int(self->port), &addr6);\n    } else {\n        B_str errmsg = $FORMAT(\"Address is not an IPv4 or IPv6 address: %s\", fromB_str(self->address));\n        log_warn((const char *)fromB_str(errmsg));\n        $action2 f = ($action2)self->on_listen;\n        f->$class->__asyn__(f, self, errmsg);\n        // NOTE: free() here if do manual memory management in I/O one day\n        return $R_CONT(c$cont, B_None);\n    }\n    if (r != 0) {\n        char errmsg[1024] = \"Unable to parse address: \";\n        uv_strerror_r(r, errmsg + strlen(errmsg), sizeof(errmsg)-strlen(errmsg));\n        log_warn(errmsg);\n        $action2 f = ($action2)self->on_listen;\n        f->$class->__asyn__(f, self, to$str(errmsg));\n        // NOTE: free() here if do manual memory management in I/O one day\n        return $R_CONT(c$cont, B_None);\n    }\n\n    if (inet_pton(AF_INET, (const char *)fromB_str(self->address), &(addr4.sin_addr)) == 1) {\n        r = uv_tcp_bind(server, (const struct sockaddr *)&addr4, 0);\n    } else if (inet_pton(AF_INET6, (const char *)fromB_str(self->address), &(addr6.sin6_addr)) == 1) {\n        r = uv_tcp_bind(server, (const struct sockaddr *)&addr6, 0);\n    }\n    if (r != 0) {\n        char errmsg[1024] = \"Error in TCP bind: \";\n        uv_strerror_r(r, errmsg + strlen(errmsg), sizeof(errmsg)-strlen(errmsg));\n        log_warn(errmsg);\n        $action2 f = ($action2)self->on_listen;\n        f->$class->__asyn__(f, self, to$str(errmsg));\n        // NOTE: free() here if do manual memory management in I/O one day\n        return $R_CONT(c$cont, B_None);\n    }\n\n    r = uv_listen((uv_stream_t *)server, 1024, on_new_connection);\n    if (r != 0) {\n        char errmsg[1024] = \"Error in TCP listen: \";\n        uv_strerror_r(r, errmsg + strlen(errmsg), sizeof(errmsg)-strlen(errmsg));\n        log_warn(errmsg);\n        $action2 f = ($action2)self->on_listen;\n        f->$class->__asyn__(f, self, to$str(errmsg));\n        // NOTE: free() here if do manual memory management in I/O one day\n        return $R_CONT(c$cont, B_None);\n    }\n\n    $action2 f = ($action2)self->on_listen;\n    f->$class->__asyn__(f, self, B_None);\n    return $R_CONT(c$cont, B_None);\n}\n\nB_NoneType netQ_TCPListenerD___resume__ (netQ_TCPListener self) {\n    self->_stream = toB_int(-1);\n    $action2 f = ($action2)self->on_listen;\n    f->$class->__asyn__(f, self, to$str(\"resume\"));\n    return B_None;\n}\n\n$R netQ_TCPListenConnectionD__initG_local (netQ_TCPListenConnection self, $Cont c$cont) {\n    pin_actor_affinity();\n\n    uv_stream_t *client = (uv_stream_t *)fromB_int(self->server_client);\n    uv_os_fd_t fd;\n    uv_fileno((uv_handle_t *)client, &fd);\n    uv_tcp_t* client_handle = (uv_tcp_t*)acton_malloc(sizeof(uv_tcp_t));\n    uv_tcp_init(get_uv_loop(), client_handle);\n    uv_tcp_open(client_handle, (uv_os_sock_t)fd);\n    self->client = toB_int((int64_t)(intptr_t)client_handle);\n\n    return $R_CONT(c$cont, B_None);\n}\n\nvoid netQ_TCPListenConnection__on_receive(uv_stream_t *stream, ssize_t nread, const uv_buf_t *buf) {\n    if (nread < 0){\n        if (nread == UV_EOF) {\n            netQ_TCPListenConnection self = stream->data;\n            if ((intptr_t)stream != -1)\n                uv_close((uv_handle_t *)stream, NULL);\n            self->client = toB_int(-1);\n            if (self->on_remote_close) {\n                $action f = ($action)self->on_remote_close;\n                f->$class->__asyn__(f, self);\n            }\n        }\n    } else if (nread > 0) {\n        if (stream->data) {\n            netQ_TCPListenConnection self = stream->data;\n            $action2 f = ($action2)self->on_receive;\n            f->$class->__asyn__(f, self, to$bytesD_len(buf->base, nread));\n        }\n    }\n\n    // No free with GC, but maybe one day we do this explicitly?\n    //if (buf->base)\n    //    free(buf->base);\n}\n\n$R netQ_TCPListenConnectionD__read_startG_local (netQ_TCPListenConnection self, $Cont c$cont) {\n    uv_stream_t *client = (uv_stream_t *)fromB_int(self->client);\n    client->data = self;\n    int r = uv_read_start(client, alloc_buffer, netQ_TCPListenConnection__on_receive);\n    if (r < 0) {\n        char errmsg[1024] = \"Failed to start reading from TCP socket: \";\n        uv_strerror_r(r, errmsg + strlen(errmsg), sizeof(errmsg)-strlen(errmsg));\n        log_warn(errmsg);\n        $action2 f = ($action2)self->on_error;\n        f->$class->__asyn__(f, self, to$str(errmsg));\n        return $R_CONT(c$cont, B_None);\n    }\n\n    return $R_CONT(c$cont, B_None);\n}\n\n$R netQ_TCPListenConnectionD_writeG_local (netQ_TCPListenConnection self, $Cont c$cont, B_bytes data) {\n    uv_stream_t *stream = (uv_stream_t *)fromB_int(self->client);\n    // fd == -1 means invalid FD and can happen after __resume__\n    if ((intptr_t)stream == -1)\n        return $R_CONT(c$cont, B_None);\n\n    uv_write_t *req = (uv_write_t *)acton_malloc(sizeof(uv_write_t));\n    uv_buf_t buf = uv_buf_init((char *)data->str, data->nbytes);\n    int r = uv_write(req, stream, &buf, 1, NULL);\n    if (r < 0) {\n        char errmsg[1024] = \"Failed to write to TCP socket: \";\n        uv_strerror_r(r, errmsg + strlen(errmsg), sizeof(errmsg)-strlen(errmsg));\n        log_warn(errmsg);\n        $action2 f = ($action2)self->on_error;\n        f->$class->__asyn__(f, self, to$str(errmsg));\n    }\n    return $R_CONT(c$cont, B_None);\n}\n\n$R netQ_TCPListenConnectionD_closeG_local (netQ_TCPListenConnection self, $Cont c$cont) {\n    log_debug(\"Closing TCP connection, affinity=%d\", self->$affinity);\n    uv_stream_t *client = (uv_stream_t *)fromB_int(self->client);\n    // fd == -1 means invalid FD and can happen after __resume__ or if the socket was closed\n    if ((intptr_t)client == -1)\n        return $R_CONT(c$cont, B_None);\n\n    // TODO: shouldn't we call uv_shutdown() first? uv_read_stop() is not needed I think\n    uv_read_stop(client);\n    if (uv_is_closing((uv_handle_t *)client) == 0) {\n        uv_close((uv_handle_t *)client, NULL);\n    }\n    self->client = toB_int(-1);\n    return $R_CONT(c$cont, B_None);\n}\n\nB_NoneType netQ_TCPListenConnectionD___resume__ (netQ_TCPListenConnection self) {\n    self->server_client = toB_int(-1);\n    self->client = toB_int(-1);\n    return B_None;\n}\n\nstruct tls_listener_conn {\n    netQ_TLSListener listener;\n    tlsuv_stream_t *stream;\n};\n\nstatic void tls_listener_on_close(uv_handle_t *stream) {\n    log_debug(\"TLS listener handle closed, stream: %p  stream->data: %p\", stream, stream->data);\n}\n\nstatic void tls_listener_close_stream(tlsuv_stream_t *stream) {\n    tlsuv_stream_close(stream, tls_listener_on_close);\n}\n\nstatic void tls_listener_on_connect(uv_connect_t *creq, int status) {\n    struct tls_listener_conn *conn = (struct tls_listener_conn *)creq->data;\n    netQ_TLSListener listener = conn->listener;\n    tlsuv_stream_t *stream = conn->stream;\n\n    if (status != 0) {\n        char errmsg[1024] = \"TLS handshake failed: \";\n        uv_strerror_r(status, errmsg + strlen(errmsg), sizeof(errmsg)-strlen(errmsg));\n        log_warn(errmsg);\n        $action2 f = ($action2)listener->on_listen;\n        f->$class->__asyn__(f, listener, to$str(errmsg));\n        tls_listener_close_stream(stream);\n        return;\n    }\n\n    listener->$class->create_tls_listen_connection(listener, B_None, toB_int((int64_t)(intptr_t)stream));\n}\n\nstatic void tls_listener_on_receive(uv_stream_t *stream, ssize_t nread, const uv_buf_t *buf) {\n    netQ_TLSListenConnection self = ((tlsuv_stream_t *)stream)->data;\n    if (nread > 0) {\n        if (stream->data) {\n            $action2 f = ($action2)self->on_receive;\n            B_bytes data = to$bytesD_len(buf->base, nread);\n            f->$class->__asyn__(f, self, data);\n        }\n    } else if (nread == UV_EOF) {\n        log_debug(\"TLS listen connection closed %p\", stream);\n        tls_listener_close_stream((tlsuv_stream_t *)stream);\n        self->_stream = toB_int(-1);\n        if (self->on_remote_close) {\n            $action f = ($action)self->on_remote_close;\n            f->$class->__asyn__(f, self);\n        }\n    } else if (nread < 0) {\n        log_debug(\"TLS listen read error %ld: %s\", nread, uv_strerror((int)nread));\n        tls_listener_close_stream((tlsuv_stream_t *)stream);\n        if (stream->data) {\n            self->_stream = toB_int(-1);\n        }\n    }\n}\n\nstatic void tls_listener_write_cb(uv_write_t *wreq, int status) {\n    if (status < 0) {\n        char errmsg[1024] = \"Failed to write to TLS listen socket: \";\n        uv_strerror_r(status, errmsg + strlen(errmsg), sizeof(errmsg)-strlen(errmsg));\n        log_warn(errmsg);\n        netQ_TLSListenConnection self = (netQ_TLSListenConnection)wreq->data;\n        $action2 on_error = ($action2)self->on_error;\n        on_error->$class->__asyn__(on_error, self, to$str(errmsg));\n        tls_listener_close_stream((tlsuv_stream_t *)wreq->handle);\n    }\n}\n\nstatic void on_new_tls_connection(uv_stream_t *server, int status) {\n    netQ_TLSListener self = (netQ_TLSListener)server->data;\n\n    if (status != 0) {\n        char errmsg[1024] = \"Error on new TLS client connection: \";\n        uv_strerror_r(status, errmsg + strlen(errmsg), sizeof(errmsg)-strlen(errmsg));\n        log_warn(errmsg);\n        $action2 f = ($action2)self->on_listen;\n        f->$class->__asyn__(f, self, to$str(errmsg));\n        return;\n    }\n\n    uv_tcp_t *client = (uv_tcp_t *)acton_malloc(sizeof(uv_tcp_t));\n    uv_tcp_init(get_uv_loop(), client);\n    int r = uv_accept(server, (uv_stream_t *)client);\n    if (r != 0) {\n        char errmsg[1024] = \"Error in accepting TLS client connection: \";\n        uv_strerror_r(r, errmsg + strlen(errmsg), sizeof(errmsg)-strlen(errmsg));\n        log_warn(errmsg);\n        $action2 f = ($action2)self->on_listen;\n        f->$class->__asyn__(f, self, to$str(errmsg));\n        return;\n    }\n\n    uv_os_fd_t fd;\n    r = uv_fileno((uv_handle_t *)client, &fd);\n    if (r != 0) {\n        char errmsg[1024] = \"Error getting TLS client socket fd: \";\n        uv_strerror_r(r, errmsg + strlen(errmsg), sizeof(errmsg)-strlen(errmsg));\n        log_warn(errmsg);\n        $action2 f = ($action2)self->on_listen;\n        f->$class->__asyn__(f, self, to$str(errmsg));\n        return;\n    }\n\n#ifdef _WIN32\n    // NOTE: Windows socket duplication path is untested.\n    SOCKET orig_sock = (SOCKET)fd;\n    WSAPROTOCOL_INFOA dup_info;\n    if (WSADuplicateSocket(orig_sock, GetCurrentProcessId(), &dup_info) != 0) {\n        char errmsg[1024] = \"Error duplicating TLS client socket: \";\n        snprintf(errmsg + strlen(errmsg), sizeof(errmsg) - strlen(errmsg), \"WSA error %d\", WSAGetLastError());\n        log_warn(errmsg);\n        $action2 f = ($action2)self->on_listen;\n        f->$class->__asyn__(f, self, to$str(errmsg));\n        uv_close((uv_handle_t *)client, NULL);\n        return;\n    }\n    SOCKET dup_sock = WSASocket(FROM_PROTOCOL_INFO, FROM_PROTOCOL_INFO, FROM_PROTOCOL_INFO,\n                                &dup_info, 0, WSA_FLAG_OVERLAPPED);\n    uv_close((uv_handle_t *)client, NULL);\n    if (dup_sock == INVALID_SOCKET) {\n        char errmsg[1024] = \"Error duplicating TLS client socket: \";\n        snprintf(errmsg + strlen(errmsg), sizeof(errmsg) - strlen(errmsg), \"WSA error %d\", WSAGetLastError());\n        log_warn(errmsg);\n        $action2 f = ($action2)self->on_listen;\n        f->$class->__asyn__(f, self, to$str(errmsg));\n        return;\n    }\n    uv_os_sock_t sock = (uv_os_sock_t)dup_sock;\n#else\n    int dup_fd = dup((int)fd);\n    uv_close((uv_handle_t *)client, NULL);\n    if (dup_fd < 0) {\n        char errmsg[1024] = \"Error duplicating TLS client socket: \";\n        snprintf(errmsg + strlen(errmsg), sizeof(errmsg) - strlen(errmsg), \"%s\", strerror(errno));\n        log_warn(errmsg);\n        $action2 f = ($action2)self->on_listen;\n        f->$class->__asyn__(f, self, to$str(errmsg));\n        return;\n    }\n    uv_os_sock_t sock = (uv_os_sock_t)dup_fd;\n#endif\n\n    tls_context *tls = (tls_context *)fromB_int(self->_tls_ctx);\n    tlsuv_stream_t *stream = (tlsuv_stream_t *)acton_malloc(sizeof(tlsuv_stream_t));\n    tlsuv_stream_init(get_uv_loop(), stream, tls);\n    tlsuv_stream_set_server(stream, 1);\n    stream->authmode = 0;\n\n    struct tls_listener_conn *conn = (struct tls_listener_conn *)acton_malloc(sizeof(*conn));\n    conn->listener = self;\n    conn->stream = stream;\n\n    uv_connect_t *connect_req = (uv_connect_t *)acton_calloc(1, sizeof(uv_connect_t));\n    connect_req->data = conn;\n\n    r = tlsuv_stream_open(connect_req, stream, sock, tls_listener_on_connect);\n    if (r != 0) {\n        char errmsg[1024] = \"Failed to start TLS handshake: \";\n        uv_strerror_r(r, errmsg + strlen(errmsg), sizeof(errmsg)-strlen(errmsg));\n        log_warn(errmsg);\n        $action2 f = ($action2)self->on_listen;\n        f->$class->__asyn__(f, self, to$str(errmsg));\n        tls_listener_close_stream(stream);\n        return;\n    }\n}\n\n$R netQ_TLSListenerD__initG_local (netQ_TLSListener self, $Cont c$cont) {\n    pin_actor_affinity();\n\n    tls_context *tls = default_tls_context(NULL, 0);\n    if (tls == NULL) {\n        $action2 f = ($action2)self->on_listen;\n        f->$class->__asyn__(f, self, to$str(\"Failed to initialize TLS context\"));\n        return $R_CONT(c$cont, B_None);\n    }\n\n    tlsuv_private_key_t key = NULL;\n    tlsuv_certificate_t cert = NULL;\n    int rc = tls->load_key(&key, (const char *)self->key_pem->str, self->key_pem->nbytes);\n    if (rc != 0) {\n        const char *err = tls->strerror(rc);\n        B_str errmsg = $FORMAT(\"Failed to load TLS key: %s\", err);\n        log_warn((const char *)fromB_str(errmsg));\n        $action2 f = ($action2)self->on_listen;\n        f->$class->__asyn__(f, self, errmsg);\n        return $R_CONT(c$cont, B_None);\n    }\n\n    rc = tls->load_cert(&cert, (const char *)self->cert_pem->str, self->cert_pem->nbytes);\n    if (rc != 0) {\n        const char *err = tls->strerror(rc);\n        B_str errmsg = $FORMAT(\"Failed to load TLS cert: %s\", err);\n        log_warn((const char *)fromB_str(errmsg));\n        $action2 f = ($action2)self->on_listen;\n        f->$class->__asyn__(f, self, errmsg);\n        return $R_CONT(c$cont, B_None);\n    }\n\n    rc = tls->set_own_cert(tls, key, cert);\n    if (rc != 0) {\n        $action2 f = ($action2)self->on_listen;\n        f->$class->__asyn__(f, self, to$str(\"Failed to set TLS certificate\"));\n        return $R_CONT(c$cont, B_None);\n    }\n\n    self->_tls_ctx = toB_int((int64_t)(intptr_t)tls);\n\n    uv_tcp_t *server = (uv_tcp_t *)acton_malloc(sizeof(uv_tcp_t));\n    uv_tcp_init(get_uv_loop(), server);\n    server->data = (void *)self;\n    int r;\n    struct sockaddr_in addr4;\n    struct sockaddr_in6 addr6;\n    if (inet_pton(AF_INET, (const char *)fromB_str(self->address), &(addr4.sin_addr)) == 1) {\n        r = uv_ip4_addr((const char *)fromB_str(self->address), fromB_int(self->port), &addr4);\n    } else if (inet_pton(AF_INET6, (const char *)fromB_str(self->address), &(addr6.sin6_addr)) == 1) {\n        r = uv_ip6_addr((const char *)fromB_str(self->address), fromB_int(self->port), &addr6);\n    } else {\n        B_str errmsg = $FORMAT(\"Address is not an IPv4 or IPv6 address: %s\", fromB_str(self->address));\n        log_warn((const char *)fromB_str(errmsg));\n        $action2 f = ($action2)self->on_listen;\n        f->$class->__asyn__(f, self, errmsg);\n        return $R_CONT(c$cont, B_None);\n    }\n    if (r != 0) {\n        char errmsg[1024] = \"Unable to parse address: \";\n        uv_strerror_r(r, errmsg + strlen(errmsg), sizeof(errmsg)-strlen(errmsg));\n        log_warn(errmsg);\n        $action2 f = ($action2)self->on_listen;\n        f->$class->__asyn__(f, self, to$str(errmsg));\n        return $R_CONT(c$cont, B_None);\n    }\n\n    if (inet_pton(AF_INET, (const char *)fromB_str(self->address), &(addr4.sin_addr)) == 1) {\n        r = uv_tcp_bind(server, (const struct sockaddr *)&addr4, 0);\n    } else if (inet_pton(AF_INET6, (const char *)fromB_str(self->address), &(addr6.sin6_addr)) == 1) {\n        r = uv_tcp_bind(server, (const struct sockaddr *)&addr6, 0);\n    }\n    if (r != 0) {\n        char errmsg[1024] = \"Error in TLS bind: \";\n        uv_strerror_r(r, errmsg + strlen(errmsg), sizeof(errmsg)-strlen(errmsg));\n        log_warn(errmsg);\n        $action2 f = ($action2)self->on_listen;\n        f->$class->__asyn__(f, self, to$str(errmsg));\n        return $R_CONT(c$cont, B_None);\n    }\n\n    r = uv_listen((uv_stream_t *)server, 1024, on_new_tls_connection);\n    if (r != 0) {\n        char errmsg[1024] = \"Error in TLS listen: \";\n        uv_strerror_r(r, errmsg + strlen(errmsg), sizeof(errmsg)-strlen(errmsg));\n        log_warn(errmsg);\n        $action2 f = ($action2)self->on_listen;\n        f->$class->__asyn__(f, self, to$str(errmsg));\n        return $R_CONT(c$cont, B_None);\n    }\n\n    self->_stream = toB_int((int64_t)(intptr_t)server);\n    $action2 f = ($action2)self->on_listen;\n    f->$class->__asyn__(f, self, B_None);\n    return $R_CONT(c$cont, B_None);\n}\n\nB_NoneType netQ_TLSListenerD___resume__ (netQ_TLSListener self) {\n    self->_stream = toB_int(-1);\n    self->_tls_ctx = toB_int(-1);\n    $action2 f = ($action2)self->on_listen;\n    f->$class->__asyn__(f, self, to$str(\"resume\"));\n    return B_None;\n}\n\n$R netQ_TLSListenConnectionD__initG_local (netQ_TLSListenConnection self, $Cont c$cont) {\n    pin_actor_affinity();\n\n    tlsuv_stream_t *stream = (tlsuv_stream_t *)fromB_int(self->server_stream);\n    stream->data = self;\n    self->_stream = toB_int((int64_t)(intptr_t)stream);\n\n    return $R_CONT(c$cont, B_None);\n}\n\n$R netQ_TLSListenConnectionD__read_startG_local (netQ_TLSListenConnection self, $Cont c$cont) {\n    tlsuv_stream_t *stream = (tlsuv_stream_t *)fromB_int(self->_stream);\n    if ((intptr_t)stream == -1)\n        return $R_CONT(c$cont, B_None);\n\n    int r = tlsuv_stream_read_start(stream, alloc_buffer, tls_listener_on_receive);\n    if (r < 0) {\n        char errmsg[1024] = \"Failed to start reading from TLS listen socket: \";\n        uv_strerror_r(r, errmsg + strlen(errmsg), sizeof(errmsg)-strlen(errmsg));\n        log_warn(errmsg);\n        $action2 f = ($action2)self->on_error;\n        f->$class->__asyn__(f, self, to$str(errmsg));\n        return $R_CONT(c$cont, B_None);\n    }\n\n    return $R_CONT(c$cont, B_None);\n}\n\n$R netQ_TLSListenConnectionD_writeG_local (netQ_TLSListenConnection self, $Cont c$cont, B_bytes data) {\n    tlsuv_stream_t *stream = (tlsuv_stream_t *)fromB_int(self->_stream);\n    if ((intptr_t)stream == -1)\n        return $R_CONT(c$cont, B_None);\n\n    uv_write_t *wreq = (uv_write_t *)acton_malloc(sizeof(uv_write_t));\n    wreq->data = self;\n    uv_buf_t buf = uv_buf_init((char *)data->str, data->nbytes);\n    int r = tlsuv_stream_write(wreq, stream, &buf, tls_listener_write_cb);\n    if (r < 0) {\n        char errmsg[1024] = \"Failed to write to TLS listen socket: \";\n        uv_strerror_r(r, errmsg + strlen(errmsg), sizeof(errmsg)-strlen(errmsg));\n        log_warn(errmsg);\n        $action2 f = ($action2)self->on_error;\n        f->$class->__asyn__(f, self, to$str(errmsg));\n    }\n    return $R_CONT(c$cont, B_None);\n}\n\n$R netQ_TLSListenConnectionD_closeG_local (netQ_TLSListenConnection self, $Cont c$cont) {\n    tlsuv_stream_t *stream = (tlsuv_stream_t *)fromB_int(self->_stream);\n    if ((intptr_t)stream == -1)\n        return $R_CONT(c$cont, B_None);\n\n    tls_listener_close_stream(stream);\n    self->_stream = toB_int(-1);\n    return $R_CONT(c$cont, B_None);\n}\n\nB_NoneType netQ_TLSListenConnectionD___resume__ (netQ_TLSListenConnection self) {\n    self->server_stream = toB_int(-1);\n    self->_stream = toB_int(-1);\n    return B_None;\n}\n\n//netQ_DNSCap netQ_TCPConnectionD__dnscap (netQ_TCPConnection self) {\n//    netQ_DNSCap c = netQ_DNSCapG_new(void);\n//    return c;\n//}\n\nstatic void tls_on_close(uv_handle_t* stream) {\n    log_debug(\"TLS handle closed, stream: %p  stream->data: %p\", stream, stream->data);\n}\n\nstatic void tls_close(tlsuv_stream_t *stream) {\n    log_debug(\"Closing TLS stream: %p  stream->data: %p\", stream, stream->data);\n    netQ_TLSConnection self = (netQ_TLSConnection)stream->data;\n    $action on_close = self->_on_close;\n    if (on_close)\n        on_close->$class->__asyn__(on_close, self);\n    tlsuv_stream_close(stream, tls_on_close);\n    self->_stream = toB_int(-1);\n}\n\nvoid tls_on_receive(uv_stream_t *stream, ssize_t nread, const uv_buf_t* buf) {\n    netQ_TLSConnection self = ((tlsuv_stream_t *)stream)->data;\n    if (nread > 0) {\n        if (stream->data) {\n            $action2 f = ($action2)self->on_receive;\n            B_bytes data = to$bytesD_len(buf->base, nread);\n            f->$class->__asyn__(f, self, data);\n            self->_bytes_in->val += nread;\n        }\n    } else if (nread == UV_EOF) {\n        log_debug(\"TLS connection closed %p\", stream);\n        tls_close((tlsuv_stream_t *)stream);\n        if (self->on_remote_close) {\n            $action f = ($action)self->on_remote_close;\n            f->$class->__asyn__(f, self);\n        }\n    }\n    else if (nread < 0) {\n        log_debug(\"TLS read error %ld: %s\", nread, uv_strerror((int) nread));\n        tls_close((tlsuv_stream_t *)stream);\n    }\n}\n\nvoid tls_write_cb(uv_write_t *wreq, int status) {\n    if (status < 0) {\n        log_debug(\"TLS write error %d: %s\", status, uv_strerror(status));\n        char errmsg[1024] = \"Failed to write to TLS TCP socket: \";\n        uv_strerror_r(status, errmsg + strlen(errmsg), sizeof(errmsg)-strlen(errmsg));\n        log_debug(errmsg);\n        netQ_TLSConnection self = (netQ_TLSConnection)wreq->data;\n        $action2 on_error = ($action2)self->on_error;\n        on_error->$class->__asyn__(on_error, self, to$str(errmsg));\n        tls_close((tlsuv_stream_t *)wreq->handle);\n    }\n}\n\n$R netQ_TLSConnectionD_closeG_local (netQ_TLSConnection self, $Cont c$cont, $action on_close) {\n    uv_stream_t *stream = (uv_stream_t *)fromB_int(self->_stream);\n    // fd == -1 means invalid FD and can happen after __resume__\n    if ((intptr_t)stream == -1)\n        return $R_CONT(c$cont, B_None);\n\n    self->_on_close = on_close;\n\n    log_debug(\"Closing TLS TCP connection\");\n    tls_close((tlsuv_stream_t *)stream);\n    // TODO: implement on_error? but tlsuv_stream_close always returns 0 and in\n    // the on_close callback the ->data is already NULL so how to find our actor\n    // and real callback?\n    return $R_CONT(c$cont, B_None);\n}\n\n$R netQ_TLSConnectionD_writeG_local (netQ_TLSConnection self, $Cont c$cont, B_bytes data) {\n    tlsuv_stream_t *stream = (tlsuv_stream_t *)fromB_int(self->_stream);\n    // fd == -1 means invalid FD and can happen after __resume__\n    if ((intptr_t)stream == -1)\n        return $R_CONT(c$cont, B_None);\n\n    uv_write_t *wreq = (uv_write_t *)acton_malloc(sizeof(uv_write_t));\n    wreq->data = self;\n    uv_buf_t buf = uv_buf_init((char *)data->str, data->nbytes);\n    int r = tlsuv_stream_write(wreq, stream, &buf, tls_write_cb);\n    if (r < 0) {\n        char errmsg[1024] = \"Failed to write to TLS TCP socket: \";\n        uv_strerror_r(r, errmsg + strlen(errmsg), sizeof(errmsg)-strlen(errmsg));\n        log_debug(errmsg);\n        $action2 f = ($action2)self->on_error;\n        f->$class->__asyn__(f, self, to$str(errmsg));\n    }\n    self->_bytes_out->val += data->nbytes;\n    return $R_CONT(c$cont, B_None);\n}\n\n\nstatic void tls_on_connect(uv_connect_t *creq, int status) {\n    netQ_TLSConnection self = (netQ_TLSConnection)creq->data;\n    if (status != 0) {\n        char errmsg[1024] = \"Error in TLS TCP connect: \";\n        uv_strerror_r(status, errmsg + strlen(errmsg), sizeof(errmsg)-strlen(errmsg));\n        log_debug(errmsg);\n        tls_close((tlsuv_stream_t *)creq->handle);\n        self->$class->_on_tls_error(self, toB_int(-1), toB_int(status), to$str(errmsg));\n        return;\n    }\n\n    tlsuv_stream_t *stream = (tlsuv_stream_t *) creq->handle;\n    tlsuv_stream_read_start(stream, alloc_buffer, tls_on_receive);\n\n    self->$class->_on_tls_connect(self);\n}\n\nvoid tlsuv_logger(int level, const char *file, unsigned int line, const char *msg) {\n    // Map tlsuv log levels to our RTS log levels\n    int log_level;\n    if (level == 0) {        // NONE, used to say \"we don't want logs\"\n        // not actually used for any log messages, so this should be unreachable\n        return;\n    } else if (level == 1) { // ERR\n        log_level = LOG_ERROR;\n    } else if (level == 2) { // WARN\n        log_level = LOG_WARN;\n    } else if (level == 3) { // INFO\n        log_level = LOG_INFO;\n    } else if (level == 4) { // DEBG\n        log_level = LOG_DEBUG;\n    } else if (level == 5) { // VERB\n        log_level = LOG_DEBUG;\n    } else if (level == 6) { // TRACE\n        log_level = LOG_TRACE;\n    }\n\n    log_log(log_level, file, line, msg);\n}\n\n$R netQ_TLSConnectionD__connect_tlsG_local (netQ_TLSConnection self, $Cont c$cont) {\n    uv_connect_t* connect_req = (uv_connect_t*)acton_calloc(1, sizeof(uv_connect_t));\n    connect_req->data = (void *)self;\n\n    //tlsuv_set_debug(5, tlsuv_logger);\n    tlsuv_stream_t *stream = (tlsuv_stream_t *)acton_malloc(sizeof(tlsuv_stream_t));\n    tlsuv_stream_init(get_uv_loop(), stream, NULL);\n\n    // Default is to verify TLS certificate. Should we disable verification?\n    if (fromB_bool(self->verify_tls) == false) {\n        log_debug(\"TLS certificate verification disabled\");\n        stream->authmode = 0; // 0=none, 2=require (mbedtls specific)\n    }\n\n    // TODO: take ALPN as input to TLSConnection actor\n    //const char *alpn[] = { \"http/1.1\" };\n    int num_protocols = self->protocols->length;\n\n    if (num_protocols > 0) {\n        const char **protocols = (const char **)acton_calloc(num_protocols, sizeof(char*));\n\n        for(int i = 0; i < num_protocols; ++i) {\n            protocols[i] = (const char *)fromB_str(self->protocols->data[i]);\n        }\n        tlsuv_stream_set_protocols(stream, num_protocols, protocols);\n    }\n    //tlsuv_stream_set_protocols(stream, 1, alpn);\n    // No ALPN for now.\n    // TODO: take SNI as input to TLSConnection actor\n    stream->data = (void *)self;\n\n    tlsuv_stream_connect(connect_req, stream, (const char *)fromB_str(self->address), fromB_int(self->port), tls_on_connect);\n    self->_stream = toB_int((int64_t)(intptr_t)stream);\n\n    return $R_CONT(c$cont, B_None);\n}\n\n$R netQ_TLSConnectionD__pin_affinityG_local (netQ_TLSConnection self, $Cont c$cont) {\n    pin_actor_affinity();\n    return $R_CONT(c$cont, B_None);\n}\n"
  },
  {
    "path": "base/src/process.act",
    "content": "\"\"\"Constructs for spawning and interacting with sub-processes\n\"\"\"\n\n\ndef _get_env_path() -> ?str:\n    \"\"\"Get the PATH environment variable\"\"\"\n    NotImplemented\n\nclass ProcessCap():\n    \"\"\"Capability to start processes\"\"\"\n    def __init__(self, cap: WorldCap):\n        pass\n\nactor Process(cap: ProcessCap,\n              cmd: list[str],\n              on_stdout: action(Process, ?bytes) -> None,\n              on_stderr: action(Process, ?bytes) -> None,\n              on_exit: action(Process, int, int) -> None,\n              on_error: action(Process, str) -> None,\n              workdir: ?str=None,\n              env: ?dict[str, str]=None,\n              timeout: ?float=None):\n    \"\"\"A process\n    - cap: capability to start processes\n    - cmd: the command to run\n    - on_stdout: stdout callback actor method\n    - on_stderr: stderr callback actor method\n    - on_exit: exit callback\n      - process\n      - exit code\n      - signal that caused program to exit\n    - on_error: error callback\n    - workdir: working directory, use None for current directory\n    - env: environment for process, use None to inherit current environment\n      When a new env is provided and it does not have PATH set, PATH is\n      inherited from the current env. The PATH variable in the new env,\n      regardless if the new env is inherited or provided, is used to find the\n      executable specified by cmd (unless cmd is a path).\n    - timeout: time in seconds before process is stopped\n    \"\"\"\n    _p = 0\n    var new_env = env\n\n    action def aid() -> int:\n        \"\"\"Actor ID of process actor\n\n        Workaround for lack of working repr on actors.\n        \"\"\"\n        NotImplemented\n\n    proc def _create_process():\n        \"\"\"Do the C magic to actually create a process and talk to it\n        \"\"\"\n        NotImplemented\n\n    action def done_writing() -> None:\n        \"\"\"Close stdin of process\n\n        Closing stdin allows cat to terminate\n        \"\"\"\n        NotImplemented\n\n    action def pid() -> ?int:\n        \"\"\"Get PID of process or None if the process is not running\n        \"\"\"\n        NotImplemented\n\n    action def signal(signal: int) -> None:\n        \"\"\"Send signal to process\n\n        Sends the provided signal to the process.\n        \"\"\"\n        NotImplemented\n\n    action def write(data: bytes) -> None:\n        \"\"\"Write data to stdin of process\n        \"\"\"\n        NotImplemented\n\n    action def kill():\n        \"\"\"Abrubtly kill process by sending SIGKILL\n        \"\"\"\n        signal(9)\n\n    action def terminate():\n        \"\"\"Stop process by sending SIGTERM\n        \"\"\"\n        signal(15)\n\n    def stop():\n        \"\"\"Stop process\n\n        Attempts to stop process using normal means, which means SIGTERM on a\n        Unix system. After 1 second, SIGKILL is sent to ensure the process is\n        stopped.\n        \"\"\"\n        terminate()\n        after 1.0: kill()\n\n    # Handle PATH inheritance for custom environments\n    # When PATH is not explicitly set in the provided environment, inherit it\n    # from the current environment (if set in the current environment).\n    if env is not None and \"PATH\" not in env:\n        parent_path = _get_env_path()\n        if parent_path is not None:\n            new = dict(env.items())\n            new[\"PATH\"] = parent_path\n            new_env = new\n\n    _create_process()\n\n    if timeout is not None:\n        after timeout: stop()\n\n\nactor RunProcess(cap: ProcessCap,\n                 cmd: list[str],\n                 on_exit: action(Process, int, int, bytes, bytes) -> None,\n                 on_error: action(Process, str) -> None,\n                 workdir: ?str,\n                 env: ?dict[str, str],\n                 timeout: ?float=None):\n    \"\"\"Run a process and wait for it to finish\n    \"\"\"\n    var out_buf = b\"\"\n    var err_buf = b\"\"\n    var _out_done = False\n    var _err_done = False\n    var _exited = False\n    var _exit_code = 0\n    var _signal = 0\n    var _process: ?Process = None\n\n\n    def _on_stdout(p: Process, data: ?bytes):\n        if data is not None:\n            out_buf += data\n        else:\n            _out_done = True\n            _check_done()\n\n    def _on_stderr(p: Process, data: ?bytes):\n        if data is not None:\n            err_buf += data\n        else:\n            _err_done = True\n            _check_done()\n\n    def _on_exit(p: Process, exit_code: int, signal: int):\n        _exited = True\n        _exit_code = exit_code\n        _signal = signal\n        _check_done()\n\n    def _check_done():\n        if _process is not None:\n            if _out_done and _err_done and _exited:\n                on_exit(_process, _exit_code, _signal, out_buf, err_buf)\n\n    _p = Process(cap, cmd, _on_stdout, _on_stderr, _on_exit, on_error, workdir, env, timeout)\n    _process = _p\n\n    def signal(sig: int):\n        \"\"\"Send signal to process\"\"\"\n        _p.signal(sig)\n\n    def kill():\n        \"\"\"Abrubtly kill process by sending SIGKILL\n        \"\"\"\n        _p.kill()\n\n    def terminate():\n        \"\"\"Stop process by sending SIGTERM\n        \"\"\"\n        _p.terminate()\n\n    def stop():\n        \"\"\"Stop process\n\n        Attempts to stop process using normal means, which means SIGTERM on a\n        Unix system. After kill_after seconds (defaults to 1), SIGKILL is sent\n        to ensure the process is stopped.\n        \"\"\"\n        _p.stop()\n"
  },
  {
    "path": "base/src/process.ext.c",
    "content": "#include \"rts/common.h\"\n\n#include <uv.h>\n#include \"../rts/io.h\"\n#include \"../rts/log.h\"\n\nvoid processQ___ext_init__() {\n    // NOP\n}\n\nstruct process_data {\n    processQ_Process process;\n    $action on_stdout;\n    $action on_stderr;\n    $action on_exit;\n    uv_pipe_t stdin_pipe;\n    uv_pipe_t stdout_pipe;\n    uv_pipe_t stderr_pipe;\n};\n\nvoid exit_handler(uv_process_t *req, int64_t exit_status, int term_signal) {\n    struct process_data *process_data = req->data;\n    uv_handle_t *stdin_handle = (uv_handle_t *)&process_data->stdin_pipe;\n    // Ensure stdin is closed properly. stdin might be closed already from\n    // done_writing, so check if it's closing first\n    if (uv_is_closing(stdin_handle) == 0)\n        uv_close(stdin_handle, NULL);\n\n    // Close the process handle\n    uv_close((uv_handle_t *)req, NULL);\n\n    process_data->process->_p = toB_int(0);\n\n    // Trigger the on_exit callback\n    $action3 f = ($action3)process_data->on_exit;\n    f->$class->__asyn__(f, process_data->process, toB_int(exit_status), toB_int(term_signal));\n}\n\nvoid read_stderr(uv_stream_t *stream, ssize_t nread, const uv_buf_t *buf) {\n    struct process_data *process_data = (struct process_data *)stream->data;\n    processQ_Process self = process_data->process;\n    $action2 f = ($action2)process_data->on_stderr;\n\n    if (nread < 0) {\n        if (nread == UV_EOF) {\n            uv_close((uv_handle_t *)stream, NULL);\n            f->$class->__asyn__(f, self, B_None);\n        } else {\n            // Log and handle read error\n            log_warn(\"Error reading from stderr\");\n        }\n    } else if (nread > 0) {\n        if (stream->data) {\n            f->$class->__asyn__(f, self, to$bytesD_len(buf->base, nread));\n        }\n    }\n}\n\nvoid read_stdout(uv_stream_t *stream, ssize_t nread, const uv_buf_t *buf) {\n    struct process_data *process_data = (struct process_data *)stream->data;\n    processQ_Process self = process_data->process;\n    $action2 f = ($action2)process_data->on_stdout;\n\n    if (nread < 0) {\n        if (nread == UV_EOF) {\n            uv_close((uv_handle_t *)stream, NULL);\n            f->$class->__asyn__(f, self, B_None);\n        } else {\n            // Log and handle read error\n            log_warn(\"Error reading from stdout\");\n        }\n    } else if (nread > 0) {\n        if (stream->data) {\n            f->$class->__asyn__(f, self, to$bytesD_len(buf->base, nread));\n        }\n    }\n}\n\n$R processQ_ProcessD_aidG_local(processQ_Process self, $Cont c$cont) {\n    return $R_CONT(c$cont, toB_int(self->$globkey));\n}\n\n$R processQ_ProcessD__create_processG_local(processQ_Process self, $Cont c$cont) {\n    pin_actor_affinity();\n    struct process_data *process_data = acton_calloc(1, sizeof(struct process_data));\n    process_data->process = self;\n    process_data->on_stdout = self->on_stdout;\n    process_data->on_stderr = self->on_stderr;\n    process_data->on_exit = self->on_exit;\n\n    uv_process_options_t *options = acton_calloc(1, sizeof(uv_process_options_t));\n\n    uv_process_t *req = acton_calloc(1, sizeof(uv_process_t));\n    self->_p = toB_int((long)req);\n\n    req->data = process_data;\n\n    char **args = (char **)acton_malloc((self->cmd->length + 1) * sizeof(char *));\n\n    for (int i = 0; i < self->cmd->length; i++) {\n        args[i] = (char *)fromB_str(self->cmd->data[i]);\n    }\n    args[self->cmd->length] = NULL;\n\n    if (self->workdir != B_None) {\n        options->cwd = fromB_str(self->workdir);\n    }\n\n    if (self->new_env == B_None) {\n        options->env = NULL;\n    } else {\n        char **env = (char **)acton_calloc((self->new_env->numelements + 1), sizeof(char *));\n        B_IteratorD_dict_items iter = $NEW(B_IteratorD_dict_items, self->new_env);\n        B_tuple item;\n\n        for (int i = 0; i < self->new_env->numelements; i++) {\n            item = (B_tuple)iter->$class->__next__(iter);\n            char *key = fromB_str((B_str)item->components[0]);\n            char *value = fromB_str((B_str)item->components[1]);\n            size_t env_size = strlen(key) + strlen(value) + 2;\n            char *env_var = acton_malloc(env_size);\n            snprintf(env_var, env_size, \"%s=%s\", key, value);\n            env[i] = env_var;\n        }\n        env[self->new_env->numelements] = NULL;\n        options->env = env;\n    }\n\n    uv_pipe_init(get_uv_loop(), &process_data->stdin_pipe, 0);\n    uv_pipe_init(get_uv_loop(), &process_data->stdout_pipe, 0);\n    process_data->stdout_pipe.data = process_data;\n    uv_pipe_init(get_uv_loop(), &process_data->stderr_pipe, 0);\n    process_data->stderr_pipe.data = process_data;\n\n    uv_stdio_container_t process_stdio[3];\n    options->stdio = process_stdio;\n\n    process_stdio[0].flags = UV_CREATE_PIPE | UV_READABLE_PIPE;\n    process_stdio[0].data.stream = (uv_stream_t *)&(process_data->stdin_pipe);\n\n    process_stdio[1].flags = UV_CREATE_PIPE | UV_WRITABLE_PIPE;\n    process_stdio[1].data.stream = (uv_stream_t *)&(process_data->stdout_pipe);\n\n    process_stdio[2].flags = UV_CREATE_PIPE | UV_WRITABLE_PIPE;\n    process_stdio[2].data.stream = (uv_stream_t *)&(process_data->stderr_pipe);\n\n    options->stdio_count = 3;\n\n    options->exit_cb = exit_handler;\n    options->file = args[0];\n    options->args = args;\n\n    int r = uv_spawn(get_uv_loop(), req, options);\n    if (r != 0) {\n        char errmsg[1024] = \"Failed to spawn process: \";\n        uv_strerror_r(r, errmsg + strlen(errmsg), sizeof(errmsg) - strlen(errmsg));\n        log_warn(errmsg);\n        $action2 f = ($action2)self->on_error;\n        f->$class->__asyn__(f, process_data->process, to$str(errmsg));\n        return $R_CONT(c$cont, B_None);\n    }\n    // TODO: do we need to do some magic to read any data produced before this\n    // callback is installed?\n\n    uv_read_start((uv_stream_t *)&process_data->stdout_pipe, alloc_buffer, read_stdout);\n    uv_read_start((uv_stream_t *)&process_data->stderr_pipe, alloc_buffer, read_stderr);\n\n    return $R_CONT(c$cont, B_None);\n}\n\nvoid close_cb(uv_handle_t *handle) {\n    // TODO: clean something up?\n}\n\n$R processQ_ProcessD_done_writingG_local(processQ_Process self, $Cont c$cont) {\n    uv_process_t *p = (uv_process_t *)fromB_int(self->_p);\n    struct process_data *process_data = (struct process_data *)p->data;\n    uv_handle_t *stdin_handle = (uv_handle_t *)&process_data->stdin_pipe;\n    // Ensure stdin is closed properly. stdin might be closed already from\n    // exit_handler, so check if it's closing first\n    if (uv_is_closing(stdin_handle) == 0)\n        uv_close(stdin_handle, close_cb);\n    return $R_CONT(c$cont, B_None);\n}\n\n$R processQ_ProcessD_pidG_local(processQ_Process self, $Cont c$cont) {\n    uv_process_t *p = (uv_process_t *)fromB_int(self->_p);\n    if (p == 0) {\n        log_warn(\"Process has exited, ignoring PID request\");\n        return $R_CONT(c$cont, B_None);\n    }\n    return $R_CONT(c$cont, (B_atom)toB_int(p->pid));\n}\n\n$R processQ_ProcessD_signalG_local(processQ_Process self, $Cont c$cont, B_int signal) {\n    uv_process_t *p = (uv_process_t *)fromB_int(self->_p);\n    if (p == 0) {\n        log_warn(\"Process has exited, ignoring signal request\");\n        return $R_CONT(c$cont, B_None);\n    }\n    uv_process_kill(p, fromB_int(signal));\n    return $R_CONT(c$cont, B_None);\n}\n\n$R processQ_ProcessD_writeG_local(processQ_Process self, $Cont c$cont, B_bytes data) {\n    uv_process_t *p = (uv_process_t *)fromB_int(self->_p);\n    if (p == 0) {\n        log_warn(\"Process has exited, ignoring write request\");\n        return $R_CONT(c$cont, B_None);\n    }\n\n    uv_write_t *req = (uv_write_t *)acton_malloc(sizeof(uv_write_t));\n    uv_buf_t buf = uv_buf_init(data->str, data->nbytes);\n\n    struct process_data *process_data = (struct process_data *)p->data;\n    uv_stream_t *stdin_handle = (uv_stream_t *)&process_data->stdin_pipe;\n\n    int r = uv_write(req, stdin_handle, &buf, 1, NULL);\n    if (r != 0) {\n        char errmsg[1024] = \"Error writing to stdin of process: \";\n        uv_strerror_r(r, errmsg + strlen(errmsg), sizeof(errmsg) - strlen(errmsg));\n        log_warn(errmsg);\n    }\n\n    return $R_CONT(c$cont, B_None);\n}\n\nB_str processQ__get_env_path() {\n    size_t path_size = 1024;  // Initial buffer size\n    char *path_buf = acton_malloc(path_size);\n\n    int r = uv_os_getenv(\"PATH\", path_buf, &path_size);\n    if (r == UV_ENOBUFS) {\n        // Buffer too small, reallocate with required size\n        acton_free(path_buf);\n        path_buf = acton_malloc(path_size);\n        r = uv_os_getenv(\"PATH\", path_buf, &path_size);\n    }\n\n    if (r != 0) {\n        // If PATH is not set or other error occurred, return None\n        acton_free(path_buf);\n        return (B_str)B_None;\n    }\n\n    B_str result = to$str(path_buf);\n    acton_free(path_buf);\n    return result;\n}\n"
  },
  {
    "path": "base/src/qcheck.act",
    "content": "from random import *\n\ndef qcheck_int_1(name: str, prop: (int) -> bool, verbose = False)->int:\n    print(\"Testing\",name)\n    i: int = 1\n    while i <= 100:\n        m = i*i\n        a = randint(-m,m)\n        if not prop(a):\n            print(\"   \",name,\"failed after\",i,\"tests:\\n\",a,\"\\n\")\n            return 1\n        else:\n            if verbose:\n                print(\"   Argument =\",a,\"; passed\")\n        i += 1\n    print(\"   OK,\",name,\"passed 100 tests\\n\")\n    return 0\n\ndef qcheck_int_2(name: str, prop: (int, int) -> bool, verbose = False)->int:\n    print(\"Testing\",name)\n    i: int = 1\n    while i <= 100:\n        m = i*i\n        a = randint(-m,m)\n        b = randint(-m,m)\n        if not prop(a,b):\n            print(\"   \",name,\"failed after\",i,\"tests:\\n\",a,\"\\n\",b)\n            return 1\n        else:\n            if verbose:\n                print(\"   Argument 1 =\",a,\" argument 2 =\",b,\"; passed\")\n        i += 1\n    print(\"   OK,\",name,\"passed 100 tests\\n\")\n    return 0\n\ndef qcheck_bigint_1(name: str, prop: (bigint) -> bool, verbose = False)->int:\n    print(\"Testing\",name)\n    i= 1\n    while i <= 100:\n        m = 2+i//2\n        a = rand_bigint(m)\n        if not prop(a):\n            print(\"   \",name,\"failed after\",i,\"tests:\\n\",a)\n            return 1\n        else:\n            if verbose:\n                print(\"   Argument =\",a,\"; passed\")\n        i += 1\n    print(\"   OK,\",name,\"passed 100 tests\\n\")\n    return 0\n\ndef qcheck_bigint_2(name: str, prop: (bigint, bigint) -> bool, verbose = False)->int:\n    print(\"Testing\",name)\n    i= 1\n    while i <= 100:\n        a = rand_bigint(randint(2,i+2))\n        b = rand_bigint(randint(2,i+2))\n        if not prop(a,b):\n            print(\"   \",name,\"failed after\",i,\"tests:\\n\",a,\"\\n\",b)\n            return 1\n        else:\n            if verbose:\n                print(\"   Argument 1 =\",a,\" argument 2 =\",b,\"; passed\")\n        i += 1\n    print(\"   OK,\",name,\"passed 100 tests\\n\")\n    return 0\n\ndef qcheck_bigint_int(name: str, prop: (bigint, int) -> bool, verbose = False)->int:\n    print(\"Testing\",name)\n    i= 1\n    while i <= 100:\n        a = rand_bigint(randint(2,i+2))\n        b = randint(-i*i,i*i)\n        if not prop(a,b):\n            print(\"   \",name,\"failed after\",i,\"tests:\\n\",a,\"\\n\",b)\n            return 1\n        else:\n            if verbose:\n                print(\"   Argument 1 =\",a,\" argument 2 =\",b,\"; passed\")\n        i += 1\n    print(\"   OK,\",name,\"passed 100 tests\\n\")\n    return 0\n\n    \ndef qcheck_0(name: str, prop: () -> bool)->int:\n    print(\"Testing\",name)\n    if prop ():\n        print(\"   OK,\",name,\"passed\\n\")\n        return 0\n    else:\n        print(\"   \",name,\"failed\")\n        return 1\n        \ndef qcheck_list_2(name: str, prop: (list[int], list[int]) -> bool, verbose = False)->int:\n    print(\"Testing\",name)\n    i = 1\n    while i <= 100:\n        a = rand_list(i)\n        b = rand_list(i)\n        if not prop(a,b):\n            print(\"   *************\",name,\"FAILED AFTER\",i,\"TESTS:*************\\n\",a,\"\\n\",b)\n            return 1\n        else:\n            if verbose:\n                print(\"   Argument 1 =\",a,\" argument 2 =\",b,\"; passed\")\n        i += 1\n    print(\"   OK,\",name,\"passed 100 tests\\n\")\n    return 0\n"
  },
  {
    "path": "base/src/random.act",
    "content": "# TODO: randint should not be pure!!! but what should it be?\ndef randint(min: int, max: int) -> int:\n    NotImplemented\n\ndef randstr(length: int) -> str:\n    char_set = list(\"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789\")\n    res = \"\"\n    for i in range(length):\n        res += choice(char_set)\n    return res\n\ndef choice[T](sequence: Sequence[T]) -> T:\n    \"\"\"\n    Return a random element from the non-empty sequence.\n\n    :param sequence: List or sequence to choose from.\n    :return: A random element from the sequence.\n    \"\"\"\n    if len(sequence) == 0:\n        raise ValueError('Cannot choose from an empty sequence')\n\n    index = randint(0, len(sequence))\n    return sequence[index]\n\n\ndef sample[T](population: list[T], k: int) -> list[T]:\n    \"\"\"\n    Chooses k unique random elements from a population sequence.\n\n    :param population: List from which to sample.\n    :param k: Number of unique elements to pick.\n    :return: A new list containing elements from the population while maintaining the original sequence order.\n    \"\"\"\n    if not (0 <= k and k <= len(population)):\n        raise ValueError(\"Sample larger than population or is negative\")\n\n    result = []\n    indices = list(range(len(population)))\n    for _ in range(k):\n        idx_to_pop = choice(indices)\n        idx = 0\n        for i in range(len(indices)):\n            if indices[i] == idx_to_pop:\n                idx = i\n                break\n        indices.pop(idx)\n        result.append(population[idx_to_pop])\n    return result\n\n\ndef rand_bigint(size):\n    \"\"\"\n    Returns a randomly chosen integer (positive, zero or negative)\n    \n    :param size: Maximal number of decimal digits (must be positive)\n    \"\"\"\n    if (size <= 0):\n        raise ValueError('decimal length of int must be positive')\n    digits = [choice([\"\",\"-\"])]\n    for i in range(size):\n        digits.append(choice([\"0\",\"1\",\"2\",\"3\",\"4\",\"5\",\"6\",\"7\",\"8\",\"9\"]))\n    return bigint(\"\".join(digits))\n\ndef rand_list(size)->list[int]:\n    \"\"\"\n    Returns a randomly chosen list of integers.\n    \n    :param size: Maximal number of elements and maximal size of list elements (must be positive)\n    \"\"\"\n    if (size <= 0):\n        raise ValueError('decimal length of int must be positive')\n    res = []\n    for i in range(randint(0,size)):\n        res.append(randint(-size, size))\n    return res\n"
  },
  {
    "path": "base/src/random.ext.c",
    "content": "#include <stdlib.h>\n\nvoid randomQ___ext_init__() {\n    // seed the random number generator with nanoseconds since the epoch and our\n    // PID\n    uv_timespec64_t ts;\n    uv_clock_gettime(UV_CLOCK_MONOTONIC, &ts);\n    srand(ts.tv_nsec ^ pid);\n}\n\n// NOTE: the standard srand / rand functions are not thread safe, but what does\n// that really mean in this context? While we could use thread safe functions\n// for deterministic random numbers (based on the seed), we won't guarantee\n// deterministic scheduling of actors on our RTS threads and so there still\n// would not be a guarantee for thread safe random numbers. Also, having to call\n// srand to seed reflects the C implementation, which we're not keen on doing -\n// rather we want it Pythonic - you should be able to get a random number with a\n// single call to random.randint(1, 3). So instead we just seed on startup with\n// the time, which is prolly good enough for now. In a future, we could cook up\n// something better.\n\nlong randlong (long min, long max) {\n    // ensure we have a valid range where min is smaller than max\n    if (min > max) {\n        $RAISE(((B_BaseException)B_ValueErrorG_new(to$str(\"min value must be smaller than max\"))));\n    }\n    // upper end of the range we want when \"based to 0\"\n    long range = max - min;\n    // chop off all values that would cause skew, leaving only things within the\n    // range that maps up to a multiple of the specified range\n    long end = RAND_MAX / range;\n    // new end\n    end *= range;\n    // run rand() until we get a value below end\n    long r;\n    // spin getting new values until we find one in range\n    while ((r = rand()) >= end);\n    // normalize back to the requested range\n    return min + r%range;\n}\n\nint64_t randomQ_U_randint(int64_t min, int64_t max) {\n    return randlong(min,max);\n}\n\n"
  },
  {
    "path": "base/src/re.act",
    "content": "\n#class Pattern():\n#    pass\n#\n#class Or(Pattern):\n#    def __init__(self, p: list[Pattern]):\n#        self.p = p\n#\n#    def __str__(self):\n#        res = \"(\"\n#        l = len(self.p)\n#        for i in range(l):\n#            res += str(self.p[i])\n#            if i < l-1:\n#                res += \"|\"\n#        res += \")\"\n#        return res\n#\n#class Text(Pattern):\n#    \"\"\"Literal text\n#    \"\"\"\n#    def __init__(self, t: str):\n#        self.text = t\n#        # TODO: complete patterns for escaping re patterns\n#        self.re_text = t.replace(\".\", r\"\\.\", None).replace(\"?\", r\"\\?\", None)\n#\n#    def __str__(self):\n#        return self.re_text\n\n\nclass Match:\n    def __init__(self, pattern: str, string: str, start_pos: int, end_pos: int, group: list[?str], named_group: dict[str, ?str]) -> None:\n        self.pattern = pattern\n        self.string = string\n        self.start_pos = start_pos\n        self.end_pos = end_pos\n        self.group = group\n        self.named = named_group\n\n# TODO: add _compile function to compile a pattern to a regex, and use it in\n# _match function to avoid recompiling the pattern each time\n\ndef _match(pattern: str, string: str, start_pos: int) -> ?Match:\n    NotImplemented\n\ndef match(pattern: str, string: str, start_pos: int=0) -> ?Match:\n    \"\"\"Scan through string looking for a match to the pattern, returning\n    a match object, or None if no match was found. start_pos sets the\n    index to begin scanning at.\n    \"\"\"\n    return _match(pattern, string, start_pos)\n\ndef matches(pattern: str, string: str) -> list[Match]:\n    \"\"\"Find all non-overlapping matches in string\n    \"\"\"\n    # TODO: implement as a generator instead\n    res = []\n    pos = 0\n    str_len = len(string)\n    while True:\n        if pos >= str_len:\n            break\n        m = _match(pattern, string, pos)\n        if m is None:\n            break\n        if m is not None:\n            res.append(m)\n            if m.end_pos == pos:\n                # Zero-width match: move forward one character if possible\n                if pos < str_len:\n                    pos += 1\n                else:\n                    # At the very end, just break\n                    break\n            else:\n                pos = m.end_pos\n    return res\n\ndef split(pattern: str, subject: str, max_split: int=0) -> list[str]:\n    if pattern == \"\":\n        raise ValueError(\"empty pattern\")\n\n    result = []\n    splits_done = 0\n    pos = 0\n    str_len = len(subject)\n\n    while True:\n        if max_split != 0 and splits_done >= max_split:\n            # Reached maximum number of splits\n            break\n\n        m = _match(pattern, subject, pos)\n        if m is not None:\n            # Append substring before match (normal match)\n            if m.end_pos > pos:\n                result.append(subject[pos:m.start_pos])\n                if len(m.group) > 1:\n                    for g in m.group[1:]:\n                        result.append(g if g is not None else \"\")\n                pos = m.end_pos\n                splits_done += 1\n            else:\n                # Zero-width match\n                if pos == 0:\n                    # At the start: append empty substring to indicate a split at the start\n                    result.append(subject[pos:m.start_pos])\n                else:\n                    # Not at the start: do not append empty substring\n                    # If there are capturing groups, append them (if any)\n                    if len(m.group) > 1:\n                        for g in m.group[1:]:\n                            result.append(g if g is not None else \"\")\n\n                # After handling zero-width match, break to avoid infinite loops\n                break\n        else:\n            # No match found\n            break\n\n    # Append remainder\n    result.append(subject[pos:])\n    return result\n"
  },
  {
    "path": "base/src/re.ext.c",
    "content": "#define PCRE2_CODE_UNIT_WIDTH 8\n\n#include <pcre2.h>\n\nstatic void *pcre2_malloc(size_t size, void *data) {\n    (void)data;\n    return acton_malloc(size);\n}\n\nstatic void pcre2_free(void *ptr, void *data) {}\n\npcre2_compile_context *compile_context;\npcre2_general_context *general_context;\n\nvoid reQ___ext_init__() {\n    general_context = pcre2_general_context_create(pcre2_malloc, pcre2_free, NULL);\n    if (general_context == NULL) {\n        // Handle error\n        assert(0);\n    }\n    compile_context = pcre2_compile_context_create(general_context);\n}\n\n\n// TODO: use u64 instead of int for arg_start_pos\nreQ_Match reQ_U__match (B_str arg_pattern, B_str arg_text, int64_t arg_start_pos) {\n    B_Hashable hwit = (B_Hashable)B_HashableD_strG_witness;\n    B_SequenceD_list swit = B_SequenceD_listG_witness;\n    B_list groups = B_listG_new(NULL, NULL);\n    B_dict named_groups = $NEW(B_dict, hwit, NULL, NULL);\n\n    PCRE2_SPTR pattern = (PCRE2_SPTR)fromB_str(arg_pattern);\n    PCRE2_SPTR text = (PCRE2_SPTR)fromB_str(arg_text);\n    size_t text_length = strlen((char *)text);\n    // TODO: use u64 instead of int to eradicate possibility of < 0\n\n    // Validate start_pos\n    long start_offset = arg_start_pos;\n    if (start_offset < 0) {\n        $RAISE(((B_BaseException)B_ValueErrorG_new(to_str_noc(\"PCRE2 matching failed: negative start_pos\"))));\n    }\n    if ((size_t)start_offset > text_length) {\n        $RAISE(((B_BaseException)B_ValueErrorG_new(to_str_noc(\"start position is greater than string length\"))));\n    }\n\n    int errornumber;\n    PCRE2_SIZE erroroffset;\n    pcre2_code *re = pcre2_compile(\n        pattern,\n        PCRE2_ZERO_TERMINATED,\n        PCRE2_UTF,\n        &errornumber,\n        &erroroffset,\n        compile_context\n    );\n\n    if (re == NULL) {\n        PCRE2_UCHAR buffer[256];\n        pcre2_get_error_message(errornumber, buffer, sizeof(buffer));\n        char errmsg[1024] = \"regex compilation failed at offset \";\n        snprintf(errmsg + strlen(errmsg), sizeof(errmsg) - strlen(errmsg), \"%d: %s\", (int)erroroffset, buffer);\n        $RAISE(((B_BaseException)B_ValueErrorG_new(to$str(errmsg))));\n    }\n\n    pcre2_match_data *match_data = pcre2_match_data_create_from_pattern(re, NULL);\n    int rc = pcre2_match(\n        re,\n        text,\n        text_length,\n        (PCRE2_SIZE)start_offset,\n        0,\n        match_data,\n        NULL\n    );\n\n    if (rc < 0) {\n        pcre2_match_data_free(match_data);\n        pcre2_code_free(re);\n\n        if (rc == PCRE2_ERROR_NOMATCH) {\n            return B_None;\n        } else {\n            // Some other error\n            char errmsg[256];\n            snprintf(errmsg, sizeof(errmsg), \"PCRE2 matching error: %d\", rc);\n            $RAISE(((B_BaseException)B_RuntimeErrorG_new(to$str(errmsg))));\n        }\n    }\n\n    PCRE2_SIZE *ovector = pcre2_get_ovector_pointer(match_data);\n    if (rc == 0) {\n        pcre2_match_data_free(match_data);\n        pcre2_code_free(re);\n        $RAISE(((B_BaseException)B_RuntimeErrorG_new(to_str_noc(\"ovector was not big enough for all captured substrings\"))));\n    }\n\n    // Extract all unnamed groups\n    // group 0 is the entire match, group 1... are subgroups\n    for (int i = 0; i < rc; i++) {\n        PCRE2_SIZE ss_start = ovector[2*i];\n        PCRE2_SIZE ss_end = ovector[2*i+1];\n        if (ss_start == PCRE2_UNSET || ss_end == PCRE2_UNSET) {\n            swit->$class->append(swit, groups, B_None);\n        } else {\n            size_t substring_length = ss_end - ss_start;\n            char *substring = acton_malloc_atomic(substring_length + 1);\n            memcpy(substring, text + ss_start, substring_length);\n            substring[substring_length] = '\\0';\n            swit->$class->append(swit, groups, to_str_noc(substring));\n        }\n    }\n\n    // Named groups\n    int namecount;\n    pcre2_pattern_info(re, PCRE2_INFO_NAMECOUNT, &namecount);\n\n    if (namecount > 0) {\n        PCRE2_SPTR name_table;\n        int name_entry_size;\n        pcre2_pattern_info(re, PCRE2_INFO_NAMETABLE, &name_table);\n        pcre2_pattern_info(re, PCRE2_INFO_NAMEENTRYSIZE, &name_entry_size);\n\n        PCRE2_SPTR tabptr = name_table;\n        for (int i = 0; i < namecount; i++) {\n            int n = (tabptr[0] << 8) | tabptr[1]; // group number for this name\n            // The name itself starts at tabptr+2 and has length (name_entry_size-2)\n            int namelen = name_entry_size - 2;\n            char *group_name = acton_malloc_atomic(namelen + 1);\n            memcpy(group_name, tabptr+2, namelen);\n            group_name[namelen] = '\\0';\n\n            PCRE2_SIZE ss_start = ovector[2*n];\n            PCRE2_SIZE ss_end = ovector[2*n+1];\n            if (ss_start == PCRE2_UNSET || ss_end == PCRE2_UNSET) {\n                B_dictD_setitem(named_groups, hwit, to_str_noc(group_name), B_None);\n            } else {\n                size_t substring_length = ss_end - ss_start;\n                char *substring = acton_malloc_atomic(substring_length + 1);\n                memcpy(substring, text + ss_start, substring_length);\n                substring[substring_length] = '\\0';\n                B_dictD_setitem(named_groups, hwit, to_str_noc(group_name), to_str_noc(substring));\n            }\n\n            tabptr += name_entry_size;\n        }\n    }\n\n    // Entire match offsets\n    PCRE2_SIZE match_start = ovector[0];\n    PCRE2_SIZE match_end = ovector[1];\n\n    pcre2_match_data_free(match_data);\n    pcre2_code_free(re);\n\n    return reQ_MatchG_new(arg_pattern, arg_text, toB_int(match_start), toB_int(match_end), groups, named_groups);\n}\n"
  },
  {
    "path": "base/src/snappy.act",
    "content": "def compress(data: bytes) -> bytes:\n    \"\"\"Compress data using Snappy\n    \"\"\"\n    NotImplemented\n\ndef decompress(data: bytes) -> bytes:\n    \"\"\"Decompress Snappy data\n    \"\"\"\n    NotImplemented\n"
  },
  {
    "path": "base/src/snappy.ext.c",
    "content": "\n#include \"../rts/io.h\"\n#include \"../rts/log.h\"\n#include <snappy-c.h>\n\nvoid snappyQ___ext_init__() {\n    // NOP\n}\n\nB_bytes snappyQ_compress (B_bytes data) {\n    char *input;\n    char *compressed;\n    size_t input_len;\n    size_t compressed_len;\n    snappy_status status;\n    B_bytes ret;\n\n    input = (char*)fromB_bytes(data);\n    input_len = (size_t)data->nbytes;\n\n    compressed_len = snappy_max_compressed_length(input_len);\n    compressed = acton_malloc(compressed_len);\n    status = snappy_compress(input, input_len, compressed, &compressed_len);\n\n    if (SNAPPY_OK == status) {\n        ret = to$bytesD_len(compressed, (int)compressed_len);\n    }\n    else {\n        char *errmsg = SNAPPY_INVALID_INPUT == status ? \"Invalid input\" : \"Buffer too small\";\n        $RAISE((B_BaseException)$NEW(B_ValueError, to$str(errmsg)));\n    }\n\n    return ret;\n}\n\nB_bytes snappyQ_decompress (B_bytes data) {\n    char *input;\n    char *uncompressed;\n    size_t input_len;\n    size_t uncompressed_len;\n    snappy_status status;\n    B_bytes ret;\n\n    input = (char*)fromB_bytes(data);\n    input_len = (size_t)data->nbytes;\n\n    status = snappy_uncompressed_length(input, input_len, &uncompressed_len);\n\n    if (SNAPPY_OK != status) {\n\tchar *errmsg = (SNAPPY_INVALID_INPUT == status) ? \"Invalid input\" : \"Buffer too small\";\n        $RAISE((B_BaseException)$NEW(B_ValueError, to$str(errmsg)));\n    }\n\n    uncompressed = acton_malloc(uncompressed_len);\n    snappy_uncompress(input, input_len, uncompressed, &uncompressed_len);\n\n    if (SNAPPY_OK == status) {\n\tret = to$bytesD_len(uncompressed, (int)uncompressed_len);\n    }\n    else {\n\tchar *errmsg = SNAPPY_INVALID_INPUT == status ? \"Invalid input\" : \"Buffer too small\";\n        $RAISE((B_BaseException)$NEW(B_ValueError, to$str(errmsg)));\n    }\n\n    return ret;\n}\n"
  },
  {
    "path": "base/src/term.act",
    "content": "\n\nnormal = \"\\x1b[0m\"\n\nbold = \"\\x1b[1m\"\nunderline = \"\\x1b[4m\"\nblink = \"\\x1b[5m\"\nreverse = \"\\x1b[7m\"\n\n# colors\nred = \"\\x1b[31m\"\ngreen = \"\\x1b[32m\"\nyellow = \"\\x1b[33m\"\nblue = \"\\x1b[34m\"\nmagenta = \"\\x1b[35m\"\ncyan = \"\\x1b[36m\"\nwhite = \"\\x1b[37m\"\n\ngrey1 = \"\\x1b[38;5;232m\"\ngrey2 = \"\\x1b[38;5;233m\"\ngrey3 = \"\\x1b[38;5;234m\"\ngrey4 = \"\\x1b[38;5;235m\"\ngrey5 = \"\\x1b[38;5;236m\"\ngrey6 = \"\\x1b[38;5;237m\"\ngrey7 = \"\\x1b[38;5;238m\"\ngrey8 = \"\\x1b[38;5;239m\"\ngrey9 = \"\\x1b[38;5;240m\"\ngrey10 = \"\\x1b[38;5;241m\"\ngrey11 = \"\\x1b[38;5;242m\"\ngrey12 = \"\\x1b[38;5;243m\"\ngrey13 = \"\\x1b[38;5;244m\"\ngrey14 = \"\\x1b[38;5;245m\"\ngrey15 = \"\\x1b[38;5;246m\"\ngrey16 = \"\\x1b[38;5;247m\"\ngrey17 = \"\\x1b[38;5;248m\"\ngrey18 = \"\\x1b[38;5;249m\"\ngrey19 = \"\\x1b[38;5;250m\"\ngrey20 = \"\\x1b[38;5;251m\"\ngrey21 = \"\\x1b[38;5;252m\"\ngrey22 = \"\\x1b[38;5;253m\"\ngrey23 = \"\\x1b[38;5;254m\"\ngrey24 = \"\\x1b[38;5;255m\"\n\n# background colors\nbg_red = \"\\x1b[41m\"\nbg_green = \"\\x1b[42m\"\nbg_yellow = \"\\x1b[43m\"\nbg_blue = \"\\x1b[44m\"\nbg_magenta = \"\\x1b[45m\"\nbg_cyan = \"\\x1b[46m\"\nbg_white = \"\\x1b[47m\"\n\nclear = \"\\x1b[0J\"\ntop = \"\\x1b[H\"\n\ndef up(n=1):\n    \"\"\"Move cursor up n lines.\n    \"\"\"\n    if n < 0:\n        raise ValueError(\"n must be >= 0\")\n    res = \"\"\n    for i in range(n):\n        res += \"\\x1b[A\"\n    return res\n\ndef down(n=1):\n    \"\"\"Move cursor down n lines.\n    \"\"\"\n    if n < 0:\n        raise ValueError(\"n must be >= 0\")\n    res = \"\"\n    for i in range(n):\n        res += \"\\x1b[B\"\n    return res\n\ndef right(n=1):\n    \"\"\"Move cursor right n columns.\n    \"\"\"\n    if n < 0:\n        raise ValueError(\"n must be >= 0\")\n    res = \"\"\n    for i in range(n):\n        res += \"\\x1b[C\"\n    return res\n\ndef left(n=1):\n    \"\"\"Move cursor left n columns.\n    \"\"\"\n    if n < 0:\n        raise ValueError(\"n must be >= 0\")\n    res = \"\"\n    for i in range(n):\n        res += \"\\x1b[D\"\n    return res\n\nclearline = \"\\x1b[0G\\x1b[2K\"\n"
  },
  {
    "path": "base/src/testing.act",
    "content": "import acton.rts\nimport argparse\nimport diff\nimport file\nimport json\nimport logging\nimport term\nimport time\n\n# -- assert ---------------------------------------------------------------------\n\ndef opt_str[T](s: ?T) -> str:\n    return str(s) if s is not None else \"None\"\n\nclass NotEqualError[T](AssertionError):\n    a: ?T\n    b: ?T\n\n    def __init__(self, a, b, msg: ?str=None, print_vals: bool=True, diff_str: ?str=None):\n        self.a = a\n        self.b = b\n        self.error_message = msg if msg is not None else \"Expected equal values but they are non-equal.\"\n        self.print_vals = print_vals\n        self.diff_str = diff_str\n\n    def __str__(self):\n        msg = f\"{self._name()}: {self.error_message}\"\n        if self.print_vals:\n            msg += f\" A: {self.a}\"\n            msg += f\" B: {self.b}\"\n        ds = self.diff_str\n        if ds is not None:\n            msg += \"\\n\" + ds\n        return msg\n\n    def __repr__(self):\n        return f\"{self._name()}({repr(self.a)}, {repr(self.b)}, {repr(self.error_message)}, {repr(self.print_vals)}, {repr(self.diff_str)})\"\n\nclass EqualError[T](AssertionError):\n    a: ?T\n    b: ?T\n\n    def __init__(self, a, b, msg: ?str=None, print_vals: bool=True):\n        self.a = a\n        self.b = b\n        self.error_message = msg if msg is not None else \"Expected non-equal values but they are equal.\"\n        self.print_vals = print_vals\n\n    def __str__(self):\n        msg = f\"{self._name()}: {self.error_message}\"\n        if self.print_vals:\n            msg += f\" A: {self.a}\"\n            msg += f\" B: {self.b}\"\n        return msg\n\n    def __repr__(self):\n        return f\"{self._name()}({repr(self.a)}, {repr(self.b)}, {repr(self.error_message)}, {repr(self.print_vals)})\"\n\nclass NotTrueError[T](AssertionError):\n    a: ?T\n\n    def __init__(self, a, msg: ?str=None, print_vals: bool=True):\n        self.a = a\n        self.error_message = msg if msg is not None else \"Expected True but got non-True\"\n        self.print_vals = print_vals\n\n    def __str__(self):\n        msg = f\"{self._name()}: {self.error_message}\"\n        if self.print_vals:\n            msg += f\", value: {self.a}\"\n        return msg\n\n    def __repr__(self):\n        return f\"{self._name()}({repr(self.a)}, {repr(self.error_message)}, {repr(self.print_vals)})\"\n\nclass NotFalseError[T](AssertionError):\n    a: ?T\n\n    def __init__(self, a, msg: ?str=None, print_vals: bool=True):\n        self.a = a\n        self.error_message = msg if msg is not None else \"Expected False but got non-False.\"\n        self.print_vals = print_vals\n\n    def __str__(self):\n        msg = f\"{self._name()}: {self.error_message}\"\n        if self.print_vals:\n            msg += f\", value: {self.a}\"\n        return msg\n\n    def __repr__(self):\n        return f\"{self._name()}({repr(self.a)}, {repr(self.error_message)}, {repr(self.print_vals)})\"\n\nclass NotNoneError[T](AssertionError):\n    a: ?T\n\n    def __init__(self, a, msg: ?str=None, print_vals: bool=True):\n        self.a = a\n        self.error_message = msg if msg is not None else \"Expected None but got non-None.\"\n        self.print_vals = print_vals\n\n    def __str__(self):\n        msg = f\"{self._name()}: {self.error_message}\"\n        if self.print_vals:\n            msg += f\", value: {self.a}\"\n        return msg\n\n    def __repr__(self):\n        return f\"{self._name()}({repr(self.a)}, {repr(self.error_message)}, {repr(self.print_vals)})\"\n\nclass NoneError[T](AssertionError):\n    a: ?T\n\n    def __init__(self, a, msg: ?str=None, print_vals: bool=True):\n        self.a = a\n        self.error_message = msg if msg is not None else \"Expected non-None but got None.\"\n        self.print_vals = print_vals\n\n    def __str__(self):\n        msg = f\"{self._name()}: {self.error_message}\"\n        if self.print_vals:\n            a = self.a\n            msg += f\", value: {a}\"\n        return msg\n\n    def __repr__(self):\n        return f\"{self._name()}({repr(self.a)}, {repr(self.error_message)}, {repr(self.print_vals)})\"\n\nclass NotInError[T,U](AssertionError):\n    a: ?T\n    b: ?U\n\n    def __init__(self, a, b, msg: ?str=None, print_vals: bool=True):\n        self.a = a\n        self.b = b\n        self.error_message = msg if msg is not None else \"Expected element not in container\"\n        self.print_vals = print_vals\n\n    def __str__(self):\n        msg = f\"{self._name()}: {self.error_message}\"\n        if self.print_vals:\n            msg += f\", element: {self.a}\"\n            msg += f\", container: {self.b}\"\n        return msg\n\n    def __repr__(self):\n        return f\"{self._name()}({repr(self.a)}, {repr(self.b)}, {repr(self.error_message)}, {repr(self.print_vals)})\"\n\nclass InError[T,U](AssertionError):\n    a: ?T\n    b: ?U\n\n    def __init__(self, a, b, msg: ?str=None, print_vals: bool=True):\n        self.a = a\n        self.b = b\n        self.error_message = msg if msg is not None else \"Expected element in container\"\n        self.print_vals = print_vals\n\n    def __str__(self):\n        msg = f\"{self._name()}: {self.error_message}\"\n        if self.print_vals:\n            msg += f\", element: {self.a}\"\n            msg += f\", container: {self.b}\"\n        return msg\n\n    def __repr__(self):\n        return f\"{self._name()}({repr(self.a)}, {repr(self.b)}, {repr(self.error_message)}, {repr(self.print_vals)})\"\n\nclass NotIsError[T](AssertionError):\n    a: T\n    b: T\n\n    def __init__(self, a, b, msg: ?str=None, print_vals: bool=True):\n        self.a = a\n        self.b = b\n        self.error_message = msg if msg is not None else \"Expected both objects to be the same identity (is)\"\n        self.print_vals = print_vals\n\n    def __str__(self):\n        msg = f\"{self._name()}: {self.error_message}\"\n        if self.print_vals:\n            msg += f\" A: {str(self.a)}\"\n            msg += f\" B: {str(self.b)}\"\n        return msg\n\n    def __repr__(self):\n        return f\"{self._name()}({repr(self.a)}, {repr(self.b)}, {repr(self.error_message)}, {repr(self.print_vals)})\"\n\nclass IsError[T](AssertionError):\n    a: T\n    b: T\n\n    def __init__(self, a, b, msg: ?str=None, print_vals: bool=True):\n        self.a = a\n        self.b = b\n        self.error_message = msg if msg is not None else \"Expected both objects to be different identities (is not)\"\n        self.print_vals = print_vals\n\n    def __str__(self):\n        msg = f\"{self._name()}: {self.error_message}\"\n        if self.print_vals:\n            msg += f\" A: {str(self.a)}\"\n            msg += f\" B: {str(self.b)}\"\n        return msg\n\n    def __repr__(self):\n        return f\"{self._name()}({repr(self.a)}, {repr(self.b)}, {repr(self.error_message)}, {repr(self.print_vals)})\"\n\nclass NotRaisesError(AssertionError):\n    def __init__(self, msg: ?str=None, print_vals: bool=True):\n        self.error_message = msg if msg is not None else \"Expected exception not raised\"\n        self.print_vals = print_vals\n\n    def __repr__(self):\n        return f\"{self._name()}({repr(self.error_message)}, {repr(self.print_vals)})\"\n\nclass IsInstanceError[T](AssertionError):\n    a: ?T\n    t: str\n\n    def __init__(self, a, t: str, msg: ?str=None, print_vals: bool=True):\n        self.a = a\n        self.t = t\n        self.error_message = msg if msg is not None else \"expected type of specific instance\"\n        self.print_vals = print_vals\n\n    def __repr__(self):\n        return f\"{self._name()}({repr(self.a)}, {repr(self.t)}, {repr(self.error_message)}, {repr(self.print_vals)})\"\n\nclass NotIsInstanceError[T](AssertionError):\n    a: ?T\n    t: str\n\n    def __init__(self, a, t: str, msg: ?str=None, print_vals: bool=True):\n        self.a = a\n        self.t = t\n        self.error_message = msg if msg is not None else \"expected type of specific instance\"\n        self.print_vals = print_vals\n\n    def __repr__(self):\n        return f\"{self._name()}({repr(self.a)}, {repr(self.t)}, {repr(self.error_message)}, {repr(self.print_vals)})\"\n\n\ndef assertEqual[T(Eq)](a: ?T, b: ?T, msg: ?str, print_vals: bool=True, print_diff: bool=True):\n    \"\"\"Assert that two values are equal\n    \"\"\"\n    if ((a is None and b is not None)\n        or (a is not None and b is None)\n        or (a is not None and b is not None and not (a == b))):\n        diff_str = None\n        if print_diff:\n            # We calculate diff here and not in NotEqualError.__str__ because the\n            # \"mut\" effect leaks out of the diff() function, but __str__() must be pure\n            diff_str = f\"{term.normal}{diff.diff(str(a), str(b), color=True)}{term.normal}\"\n        raise NotEqualError(a, b, msg, print_vals, diff_str)\n\ndef assertNotEqual[T(Eq)](a: ?T, b: ?T, msg: ?str, print_vals: bool=True):\n    \"\"\"Assert that two values are not equal\n    \"\"\"\n    if ((a is None and b is None)\n        or (a is not None and b is not None and a == b)):\n        raise EqualError(a, b, msg, print_vals)\n\ndef assertTrue(a, msg: ?str, print_vals: bool=True):\n    \"\"\"Assert that the boolean evaluation of a value is True\n    \"\"\"\n    if not bool(a):\n        raise NotTrueError(a, msg, print_vals)\n\ndef assertFalse(a, msg: ?str, print_vals: bool=True):\n    \"\"\"Assert that the boolean evaluation of a value is False\n    \"\"\"\n    if bool(a):\n        raise NotFalseError(a, msg, print_vals)\n\ndef assertIs[T(Identity)](a: T, b: T, msg: ?str, print_vals: bool=True):\n    \"\"\"Assert that two values are the same identity, i.e. the same object\n    \"\"\"\n    if not (a is b):\n        raise NotIsError(a, b, msg)\n\ndef assertIsNot[T(Identity)](a: T, b: T, msg: ?str, print_vals: bool=True):\n    \"\"\"Assert that two values are not the same identity, i.e. different objects\n    \"\"\"\n    if a is b:\n        raise IsError(a, b, msg)\n\ndef assertNone(a, msg: ?str, print_vals: bool=True):\n    \"\"\"Assert that a value equals None\n    \"\"\"\n    if not (a is None):\n        raise NotNoneError(a, msg, print_vals)\n\ndef assertNotNone(a, msg: ?str, print_vals: bool=True):\n    \"\"\"Assert that a value does not equal None\n    \"\"\"\n    if not (a is not None):\n        raise NoneError(a, msg, print_vals)\n\ndef assertIn(a, b, msg: ?str, print_vals: bool=True):\n    \"\"\"Assert that a value is in a container\n    \"\"\"\n    if not (a in b):\n        raise NotInError(a, b, msg, print_vals)\n\ndef assertNotIn(a, b, msg: ?str, print_vals: bool=True):\n    \"\"\"Assert that a value is not in a container\n    \"\"\"\n    if a in b:\n        raise InError(a, b, msg, print_vals)\n\ndef error(msg: ?str):\n    \"\"\"Raise a generic test error\"\"\"\n    raise AssertionError(msg if msg is not None else \"Test error\")\n\n# -------------------------------------------------------------------------------\n\ndef eq_opt[T(Eq)](a: ?T, b: ?T) -> bool:\n    return a is not None and b is not None and a == b or a is None and b is None\n\nclass TestLogger(logging.Logger):\n    pass\n\nclass SkipTest(AssertionError):\n    pass\n\nclass AbortTest(Exception):\n    pass\n\nclass SyncT(value):\n    def __init__(self, log_handler: logging.Handler, tags: set[str]):\n        self.log_handler = log_handler\n        self.tags = tags\n\n    def skip(self, reason: ?str=\"Skipped\"):\n        raise SkipTest(reason)\n\n    def require(self, tag: str):\n        if tag not in self.tags:\n            self.skip(f\"Missing required capability '{tag}' (enable with --tag {tag})\")\n\nclass AsyncT(value):\n    def __init__(self, report_result: action(?bool, ?Exception, ?str) -> None, log_handler: logging.Handler, tags: set[str]):\n        self.report_result = report_result\n        self.log_handler = log_handler\n        self.tags = tags\n\n    def success(self, output: ?str=None):\n        self.report_result(True, None, output)\n\n    def failure(self, exception: Exception):\n        self.report_result(False, exception, None)\n\n    def error(self, exception: Exception):\n        self.report_result(None, exception, None)\n\n    def skip(self, reason: ?str=\"Skipped\"):\n        self.report_result(True, SkipTest(reason), None)\n        raise AbortTest(reason)\n\n    def require(self, tag: str):\n        if tag not in self.tags:\n            self.skip(f\"Missing required capability '{tag}' (enable with --tag {tag})\")\n\nclass EnvT(value):\n    def __init__(self, report_result: action(?bool, ?Exception, ?str) -> None, env: Env, log_handler: logging.Handler, tags: set[str]):\n        self.report_result = report_result\n        self.env = env\n        self.log_handler = log_handler\n        self.tags = tags\n\n    def success(self, output: ?str=None):\n        self.report_result(True, None, output)\n\n    def failure(self, exception: Exception):\n        self.report_result(False, exception, None)\n\n    def error(self, exception: Exception):\n        self.report_result(None, exception, None)\n\n    def skip(self, reason: ?str=\"Skipped\"):\n        self.report_result(True, SkipTest(reason), None)\n        raise AbortTest(reason)\n\n    def require(self, tag: str):\n        if tag not in self.tags:\n            self.skip(f\"Missing required capability '{tag}' (enable with --tag {tag})\")\n\n\nclass Test(object):\n    module: str\n    name: str\n    desc: str\n\n    def __init__(self, name: str, desc: str, module):\n        self.name = name\n        self.desc = desc\n        self.module = module\n\n    def display_name(self) -> str:\n        \"\"\"Return a pretty display name for the test\"\"\"\n        n = self.name\n        # Remove _test_ prefix\n        if n.startswith(\"_test_\"):\n            n = n[6:]\n        # Remove _wrapper suffix\n        if n.endswith(\"_wrapper\"):\n            n = n[:-8]\n        return n\n\n    def run(self, report_result: action(?bool, ?Exception, ?str) -> None, env: Env, log_handler: logging.Handler, tags: set[str]):\n        if isinstance(self, UnitTest):\n            self.run_test(report_result, env, log_handler, tags)\n        elif isinstance(self, SimpleSyncTest):\n            self.run_test(report_result, env, log_handler, tags)\n        elif isinstance(self, SyncTest):\n            self.run_test(report_result, env, log_handler, tags)\n        elif isinstance(self, AsyncTest):\n            self.run_test(report_result, env, log_handler, tags)\n        elif isinstance(self, EnvTest):\n            self.run_test(report_result, env, log_handler, tags)\n        else:\n            raise ValueError(\"Test: Invalid test type\")\n\n    def to_json(self):\n        return {\n            \"module\": self.module,\n            \"name\": self.name,\n            \"desc\": self.desc,\n        }\n\n    @staticmethod\n    def from_json(data: dict[str, ?value]):\n        module = data[\"module\"]\n        name = data[\"name\"]\n        desc = data[\"desc\"]\n        if isinstance(module, str) and isinstance(name, str) and isinstance(desc, str):\n            return Test(name, desc, module)\n        raise ValueError(\"Test: Invalid JSON\")\n\ndef safe_hash(h: int) -> int: # TODO: Remove when https://github.com/actonlang/acton/issues/1348 is fixed\n    limit = 2**63-1\n    sign = 1\n    if h < 0:\n        limit = 2**63\n        sign = -1\n        h = -h\n\n    while h > limit:\n        f = h // limit\n        h %= limit\n        h += f\n\n    return sign * h\n\nextension Test(Hashable):\n    def __eq__(self, other: Test) -> bool:\n        return self.module == other.module and self.name == other.name\n\n    def hash(self, h):\n        self.module.hash(h)\n        self.name.hash(h)\n        #h.update(self.module.encode())\n        #h.update(self.name.encode())\n\n#    def __hash__(self) -> int:\n#        #return hash(self.data)\n#        return safe_hash(2*hash(self.module) + 3*hash(self.name))\n\nclass UnitTest(Test):\n    def __init__(self, fn: mut() -> None, name: str, desc: str, module: str):\n        self.fn = fn\n        self.name = name\n        self.desc = desc\n        self.module = module\n\n    def run_test(self, report_result: action(?bool, ?Exception, ?str) -> None, env: Env, log_handler: logging.Handler, tags: set[str]):\n        output = None\n        success = None\n        exception = None\n        try:\n            output = self.fn()\n            success = True\n            exception = None\n        except SkipTest as e:\n            success = True\n            exception = e\n        except AssertionError as e:\n            success = False\n            exception = e\n        except Exception as e:\n            success = None\n            exception = e\n        report_result(success, exception, output)\n\nclass SimpleSyncTest(Test):\n    def __init__(self, fn: proc() -> None, name: str, desc: str, module: str):\n        self.fn = fn\n        self.name = name\n        self.desc = desc\n        self.module = module\n\n    def run_test(self, report_result: action(?bool, ?Exception, ?str) -> None, env: Env, log_handler: logging.Handler, tags: set[str]):\n        output = None\n        success = None\n        exception = None\n        try:\n            output = self.fn()\n            success = True\n            exception = None\n        except SkipTest as e:\n            success = True\n            exception = e\n        except AssertionError as e:\n            success = False\n            exception = e\n        except Exception as e:\n            success = None\n            exception = e\n        report_result(success, exception, output)\n\nclass SyncTest(Test):\n    def __init__(self, fn: proc(SyncT) -> None, name: str, desc: str, module: str):\n        self.fn = fn\n        self.name = name\n        self.desc = desc\n        self.module = module\n\n    def run_test(self, report_result: action(?bool, ?Exception, ?str) -> None, env: Env, log_handler: logging.Handler, tags: set[str]):\n        output = None\n        success = None\n        exception = None\n        try:\n            output = self.fn(SyncT(log_handler, tags))\n            success = True\n            exception = None\n        except SkipTest as e:\n            success = True\n            exception = e\n        except AssertionError as e:\n            success = False\n            exception = e\n        except Exception as e:\n            success = None\n            exception = e\n        report_result(success, exception, output)\n\nclass AsyncTest(Test):\n    def __init__(self, fn: proc(AsyncT) -> None, name: str, desc: str, module: str):\n        self.fn = fn\n        self.name = name\n        self.desc = desc\n        self.module = module\n\n    def run_test(self, report_result: action(?bool, ?Exception, ?str) -> None, env: Env, log_handler: logging.Handler, tags: set[str]):\n        try:\n            self.fn(AsyncT(report_result, log_handler, tags))\n        except AbortTest:\n            pass\n\nclass EnvTest(Test):\n    def __init__(self, fn: proc(EnvT) -> None, name: str, desc: str, module: str):\n        self.fn = fn\n        self.name = name\n        self.desc = desc\n        self.module = module\n\n    def run_test(self, report_result: action(?bool, ?Exception, ?str) -> None, env: Env, log_handler: logging.Handler, tags: set[str]):\n        try:\n            self.fn(EnvT(report_result, env, log_handler, tags))\n        except AbortTest:\n            pass\n\n\nclass TestResult(object):\n    \"\"\"\n    There are three possible outcomes for a test:\n    - success: the test ran to completion with the expected results\n      - for unit tests & synchronous actor tests, it means the function returned\n      - for asynchronous actor & env tests, the report_result callback was called with TestResult(success=True, exception=None)\n    - failure: the test encountered an unexpected value\n      - for unit tests & synchronous actor tests, an AssertionError (or child thereof) was raiesd\n      - for asynchronous actor & env tests, the report_result callback was called with TestResult(success=False, exception=AssertionError)\n    - error: the test was unable to run to completion, encountering some other error in test setup or similar\n      - for unit tests & synchronous actor tests, an Exception (or child thereof) was raised, but not an AssertionError\n      - for asynchronous actor & env tests, the report_result callback was called with TestResult(success=None, exception=AssertionError)\n    \"\"\"\n    success: ?bool\n    skipped: bool\n    skip_reason: ?str\n    exception: ?str\n    output: ?str\n    duration: float\n    mem_usage_delta: int\n    non_gc_mem_usage_delta: int\n\n    def __init__(self,\n                 success: ?bool,\n                 exception: ?str,\n                 output: ?str,\n                 duration: float,\n                 mem_usage_delta: int,\n                 non_gc_mem_usage_delta: int,\n                 skipped: bool=False,\n                 skip_reason: ?str=None):\n        self.success = success\n        self.skipped = skipped\n        self.skip_reason = skip_reason\n        self.exception = exception\n        self.output = output\n        self.duration = duration\n        self.mem_usage_delta = mem_usage_delta\n        self.non_gc_mem_usage_delta = non_gc_mem_usage_delta\n\n    def to_json(self):\n        return {\n            \"success\": self.success,\n            \"skipped\": self.skipped,\n            \"skip_reason\": self.skip_reason,\n            \"exception\": self.exception,\n            \"output\": self.output,\n            \"duration\": self.duration,\n            \"mem_usage_delta\": self.mem_usage_delta,\n            \"non_gc_mem_usage_delta\": self.non_gc_mem_usage_delta,\n        }\n\n    @staticmethod\n    def from_json(data: dict[str, str]) -> TestResult:\n        success = data[\"success\"]\n        skipped = False\n        if \"skipped\" in data:\n            skipped = data[\"skipped\"]\n        skip_reason = None\n        if \"skip_reason\" in data:\n            skip_reason = data[\"skip_reason\"]\n        exception = data[\"exception\"]\n        output = data[\"output\"]\n        duration = data[\"duration\"]\n        mem_usage_delta = data[\"mem_usage_delta\"]\n        non_gc_mem_usage_delta = data[\"non_gc_mem_usage_delta\"]\n        if (isinstance(success, bool)\n            and isinstance(skipped, bool)\n            and (skip_reason is None or isinstance(skip_reason, str))\n            and (exception is None or isinstance(exception, str))\n            and (output is None or isinstance(output, str))\n            and isinstance(duration, float)\n            and isinstance(mem_usage_delta, int)\n            and isinstance(non_gc_mem_usage_delta, int)\n            ):\n            return TestResult(success, exception, output, duration, mem_usage_delta, non_gc_mem_usage_delta, skipped, skip_reason)\n        raise ValueError(\"Invalid TestResult JSON\")\n\n\nclass TestInfo(object):\n    definition: Test\n    complete: bool\n    success: ?bool\n    skipped: bool\n    skip_reason: ?str\n    exception: ?str\n    output: ?str\n    std_out: ?str\n    std_err: ?str\n    flaky_output: bool\n    flaky: bool\n    leaky: bool\n    min_duration: float\n    max_duration: float\n    avg_duration: float\n    total_duration: float\n    test_duration: float\n    num_iterations: int\n    num_skipped: int\n    num_failures: int\n    num_errors: int\n    mem_usage_delta_avg: int\n    non_gc_mem_usage_delta_avg: int\n    non_gc_mem_inc_count: int\n    results: list[TestResult]\n\n    def __init__(self,\n                 definition: Test,\n                 complete: bool=False,\n                 success: ?bool=None,\n                 skipped: bool=False,\n                 skip_reason: ?str=None,\n                 exception: ?str=None,\n                 output: ?str=None,\n                 std_out: ?str=None,\n                 std_err: ?str=None,\n                 flaky: bool=False,\n                 min_duration: float=-1.0,\n                 max_duration: float=-1.0,\n                 avg_duration: float=-1.0,\n                 total_duration: float=0.0,\n                 test_duration: float=0.0,\n                 num_iterations: int=0,\n                 num_skipped: int=0,\n                 num_failures: int=0,\n                 num_errors: int=0,\n                 mem_usage_delta_avg: int=0,\n                 non_gc_mem_usage_delta_avg: int=0,\n                 non_gc_mem_inc_count: int=0,\n                 results: list[TestResult]=[]):\n        self.definition = definition\n        self.complete = complete\n        self.success = success\n        self.skipped = skipped\n        self.skip_reason = skip_reason\n        self.exception = exception\n        self.output = output\n        self.std_out = std_out\n        self.std_err = std_err\n        self.flaky_output = False\n        self.flaky = flaky\n        self.leaky = False\n        self.min_duration = min_duration\n        self.max_duration = max_duration\n        self.avg_duration = avg_duration\n        self.total_duration = total_duration\n        self.test_duration = test_duration\n        self.num_iterations = num_iterations\n        self.num_skipped = num_skipped\n        self.num_failures = num_failures\n        self.num_errors = num_errors\n        self.mem_usage_delta_avg = mem_usage_delta_avg\n        self.non_gc_mem_usage_delta_avg = non_gc_mem_usage_delta_avg\n        self.non_gc_mem_inc_count = non_gc_mem_inc_count\n        self.results = results\n\n    def update(self, complete, result: TestResult, test_duration: float=-1.0):\n        self.complete = complete\n\n        first_result = len(self.results) == 0\n        prev_iterations = self.num_iterations\n        if first_result:\n            # First result\n            self.output = result.output\n            self.exception = result.exception\n            self.skip_reason = result.skip_reason\n\n        self.results.append(result)\n\n        if not eq_opt(self.output, result.output):\n            self.flaky_output = True\n\n        if self.exception is None and result.exception is not None:\n            self.exception = result.exception\n        if self.skip_reason is None and result.skip_reason is not None:\n            self.skip_reason = result.skip_reason\n\n        if test_duration > 0.0:\n            self.test_duration = test_duration\n\n        self.num_iterations = prev_iterations + 1\n        if result.skipped:\n            self.num_skipped += 1\n        elif result.success == False:\n            self.num_failures += 1\n        elif result.success is None:\n            self.num_errors += 1\n\n        if first_result:\n            self.min_duration = result.duration\n            self.max_duration = result.duration\n            self.total_duration = result.duration\n            self.avg_duration = result.duration\n            self.mem_usage_delta_avg = result.mem_usage_delta\n            self.non_gc_mem_usage_delta_avg = result.non_gc_mem_usage_delta\n            self.non_gc_mem_inc_count = 1 if result.non_gc_mem_usage_delta > 0 else 0\n        else:\n            if result.duration < self.min_duration or self.min_duration < 0.0:\n                self.min_duration = result.duration\n            if result.duration > self.max_duration or self.max_duration < 0.0:\n                self.max_duration = result.duration\n            self.total_duration += result.duration\n            self.avg_duration = self.total_duration / float(self.num_iterations)\n            self.mem_usage_delta_avg = ((self.mem_usage_delta_avg * prev_iterations) + result.mem_usage_delta) // self.num_iterations\n            self.non_gc_mem_usage_delta_avg = ((self.non_gc_mem_usage_delta_avg * prev_iterations) + result.non_gc_mem_usage_delta) // self.num_iterations\n            if result.non_gc_mem_usage_delta > 0:\n                self.non_gc_mem_inc_count += 1\n\n        if self.non_gc_mem_inc_count > min_def([1, self.num_iterations // 2],1) and self.non_gc_mem_usage_delta_avg > 0:\n            self.leaky = True\n\n        if self.num_failures > 0:\n            self.success = False\n        elif self.num_errors > 0:\n            self.success = None\n        else:\n            self.success = True\n        self.skipped = self.num_skipped > 0 and self.num_failures == 0 and self.num_errors == 0\n\n        if (self.num_failures == 0 and self.num_errors == 0) or self.num_failures == self.num_iterations or self.num_errors == self.num_iterations:\n            self.flaky = False\n        else:\n            self.flaky = True\n\n    def diff(self, old: ?TestInfo) -> (min_duration: str,\n                                       max_duration: str,\n                                       avg_duration: str,\n                                       mem_usage_delta_avg: str,\n                                       non_gc_mem_usage_delta_avg: str,\n                                       non_gc_mem_inc_count: str):\n        def fmt_diff(new, old, unit=\"\") -> str:\n            if old is not None:\n                diff = float(new) - float(old)\n                pct_diff = diff / float(old) * 100\n                sign = \"+\" if diff > 0 else \"\"\n                color = term.green if diff < 0 else term.red\n                diff_str = f\"{sign}{pct_diff:.2f}\" + \"%\"\n                return f\"{color}{diff_str:<10}{term.normal}\"\n            else:\n                return f\"{'':>10}\"\n\n        #return (min_duration=fmt_diff(self.min_duration, old.min_duration if old is not None else None, \"ms\"))\n        return (\n            fmt_diff(self.min_duration, old.min_duration if old is not None else None, \"ms\"),\n            fmt_diff(self.max_duration, old.max_duration if old is not None else None, \"ms\"),\n            fmt_diff(self.avg_duration, old.avg_duration if old is not None else None, \"ms\"),\n            fmt_diff(self.mem_usage_delta_avg, old.mem_usage_delta_avg if old is not None else None, \"B\"),\n            fmt_diff(self.non_gc_mem_usage_delta_avg, old.non_gc_mem_usage_delta_avg if old is not None else None, \"B\"),\n            fmt_diff(self.non_gc_mem_inc_count, old.non_gc_mem_inc_count if old is not None else None)\n        )\n\n    def to_json(self, include_results: bool=False):\n        test_results = []\n        if include_results:\n            for r in self.results:\n                test_results.append(r.to_json())\n\n        return {\n            \"definition\": self.definition.to_json(),\n            \"complete\": self.complete,\n            \"success\": self.success,\n            \"skipped\": self.skipped,\n            \"skip_reason\": self.skip_reason,\n            \"exception\": self.exception,\n            \"output\": self.output,\n            \"std_out\": self.std_out,\n            \"std_err\": self.std_err,\n            \"flaky\": self.flaky,\n            \"min_duration\": self.min_duration,\n            \"max_duration\": self.max_duration,\n            \"avg_duration\": self.avg_duration,\n            \"total_duration\": self.total_duration,\n            \"test_duration\": self.test_duration,\n            \"num_iterations\": self.num_iterations,\n            \"num_skipped\": self.num_skipped,\n            \"num_failures\": self.num_failures,\n            \"num_errors\": self.num_errors,\n            \"mem_usage_delta_avg\": self.mem_usage_delta_avg,\n            \"non_gc_mem_usage_delta_avg\": self.non_gc_mem_usage_delta_avg,\n            \"non_gc_mem_inc_count\": self.non_gc_mem_inc_count,\n            \"results\": test_results\n        }\n\n    @staticmethod\n    def from_json(json_data: dict[str, ?value]) -> TestInfo:\n        def take_definition(jd: dict[str, ?value]) -> Test:\n            if \"definition\" in jd:\n                test_definition = jd[\"definition\"]\n                if isinstance(test_definition, dict):\n                    return Test.from_json(test_definition)\n            raise ValueError(\"Invalid Test JSON: \" + str(jd))\n        definition: Test = take_definition(json_data)\n        complete = json_data[\"complete\"]\n        suc = json_data[\"success\"]\n        success: ?bool = None\n        if suc is not None and isinstance(suc, bool):\n            success = suc\n        sk = False\n        if \"skipped\" in json_data:\n            sk = json_data[\"skipped\"]\n        skipped = False\n        if isinstance(sk, bool):\n            skipped = sk\n        skip_reason_d = None\n        if \"skip_reason\" in json_data:\n            skip_reason_d = json_data[\"skip_reason\"]\n        skip_reason: ?str = None\n        if skip_reason_d is not None and isinstance(skip_reason_d, str):\n            skip_reason = skip_reason_d\n        exc = json_data[\"exception\"]\n        exception: ?str = None\n        if exc is not None and isinstance(exc, str):\n            exception = exc\n        out = json_data[\"output\"]\n        output: ?str = None\n        if out is not None and isinstance(out, str):\n            output = out\n        std_out_d = json_data[\"std_out\"]\n        std_out: ?str = None\n        if std_out_d is not None and isinstance(std_out_d, str):\n            std_out = std_out_d\n        std_err_d = json_data[\"std_err\"]\n        std_err: ?str = None\n        if std_err_d is not None and isinstance(std_err_d, str):\n            std_err = std_err_d\n        flaky = json_data[\"flaky\"]\n        min_duration = json_data[\"min_duration\"]\n        max_duration = json_data[\"max_duration\"]\n        avg_duration = json_data[\"avg_duration\"]\n        total_duration = json_data[\"total_duration\"]\n        test_duration = json_data[\"test_duration\"]\n        num_iterations = json_data[\"num_iterations\"]\n        num_skipped = 0\n        if \"num_skipped\" in json_data:\n            num_skipped = json_data[\"num_skipped\"]\n        num_failures = json_data[\"num_failures\"]\n        num_errors = json_data[\"num_errors\"]\n        mem_usage_delta_avg = json_data[\"mem_usage_delta_avg\"]\n        non_gc_mem_usage_delta_avg = json_data[\"non_gc_mem_usage_delta_avg\"]\n        non_gc_mem_inc_count = json_data[\"non_gc_mem_inc_count\"]\n        results: list[TestResult] = []\n        # We don't support results in the JSON, since we don't want it for\n        # performance reasons but for very generic JSON serialization support it\n        # would be correct to support it.\n        if (isinstance(complete, bool)\n            and isinstance(flaky, bool)\n            and isinstance(min_duration, float)\n            and isinstance(max_duration, float)\n            and isinstance(avg_duration, float)\n            and isinstance(total_duration, float)\n            and isinstance(test_duration, float)\n            and isinstance(num_iterations, int)\n            and isinstance(num_skipped, int)\n            and isinstance(num_failures, int)\n            and isinstance(num_errors, int)\n            and isinstance(mem_usage_delta_avg, int)\n            and isinstance(non_gc_mem_usage_delta_avg, int)\n            and isinstance(non_gc_mem_inc_count, int)\n            ):\n            return TestInfo(definition,\n                            complete,\n                            success,\n                            skipped,\n                            skip_reason,\n                            exception,\n                            output,\n                            std_out,\n                            std_err,\n                            flaky,\n                            min_duration,\n                            max_duration,\n                            avg_duration,\n                            total_duration,\n                            test_duration,\n                            num_iterations,\n                            num_skipped,\n                            num_failures,\n                            num_errors,\n                            mem_usage_delta_avg,\n                            non_gc_mem_usage_delta_avg,\n                            non_gc_mem_inc_count,\n                            results)\n        else:\n            raise ValueError(\"Invalid TestInfo JSON\")\n\nclass TestRunnerConfig(object):\n    perf_mode: bool\n    stress_mode: bool\n    max_iter: int\n    min_iter: int\n    max_time: float\n    min_time: float\n    stress_workers: int\n    output_enabled: bool\n    tags: set[str]\n\n    def __init__(self, perf_mode: bool, stress_mode: bool, args):\n        def split_tags(tag_args: list[str]) -> set[str]:\n            tags = set()\n            for raw_tags in tag_args:\n                for t in raw_tags.split(\",\"):\n                    tag = t.strip()\n                    if tag != \"\":\n                        tags.add(tag)\n            return tags\n        self.perf_mode = perf_mode\n        self.stress_mode = stress_mode\n        self.output_enabled = False if stress_mode or args.get_bool(\"no_output\") else True\n        self.min_iter = args.get_int(\"min-iter\")\n        raw_max_iter = args.get_int(\"max-iter\")\n        if raw_max_iter <= 0:\n            self.max_iter = 0\n        else:\n            self.max_iter = max([raw_max_iter, self.min_iter])\n        self.min_time = float(args.get_int(\"min-time\")) / 1000.0\n        raw_max_time = args.get_int(\"max-time\")\n        if raw_max_time <= 0:\n            self.max_time = 0.0\n        else:\n            self.max_time = max([float(raw_max_time) / 1000.0, self.min_time])\n        self.stress_workers = max([0, args.get_int(\"stress-workers\")])\n        self.tags = split_tags(args.get_strlist(\"tag\"))\n\nclass TimeoutError(Exception):\n    pass\n\nactor TestExecutor(syscap, config, t: Test, report_complete, report_progress, env, executor_id: int, stress_workers: int, stress_nodrift_workers: int):\n    \"\"\"The actual executor of tests\n    \"\"\"\n    log_handler = logging.Handler()\n    log_handler.add_sink(logging.ConsoleSink())\n    fcap = file.FileCap(env.cap)\n    rfcap = file.ReadFileCap(fcap)\n    fs = file.FS(fcap)\n    var test_sw = time.Stopwatch()\n    var last_report = time.Stopwatch()\n    var progress_report_sw = time.Stopwatch()\n    var test_info = None\n    var iteration = 0\n    var stress_drift_rank = max([0, executor_id - stress_nodrift_workers])\n    var stress_drift_workers = max([1, stress_workers - stress_nodrift_workers])\n    var stress_last_drift_us = 0\n    var stress_total_drift_us = 0\n    var stress_est_iter_ms = 0.0\n    var stress_base_drift_us = 0\n    var stress_worker_drift_us = 0\n    var stress_startup_offset_us = 0\n    var stress_startup_done = False\n    var stress_phase_resolution_us = 0\n    var stress_target_sweep_iters = 16\n    var stress_calib_samples = 0\n    var stress_calib_target_samples = 4\n    var stress_calibrating = config.stress_mode and not config.perf_mode and executor_id >= stress_nodrift_workers\n    var stress_refine_enabled = config.stress_mode and not config.perf_mode and executor_id >= stress_nodrift_workers\n    var stress_refine_next_iter = 0\n    var stress_refine_max_sweep_iters = 0\n\n    def _update_stress_timing_estimate(iter_ms: float):\n        if iter_ms <= 0.0:\n            return\n        if stress_est_iter_ms <= 0.0:\n            stress_est_iter_ms = iter_ms\n        else:\n            stress_est_iter_ms = (stress_est_iter_ms * 0.8) + (iter_ms * 0.2)\n\n    def _set_stress_sweep_iters(target_sweep_iters: int):\n        if stress_est_iter_ms <= 0.0:\n            return\n        stress_target_sweep_iters = max([1, target_sweep_iters])\n        stress_base_drift_us = max([1, int((stress_est_iter_ms * 1000.0) / float(stress_target_sweep_iters))])\n        stress_phase_resolution_us = stress_base_drift_us\n        stress_worker_drift_us = stress_base_drift_us * (stress_drift_rank + 1)\n\n    def _stress_plan_time_s() -> float:\n        if config.max_time > 0.0:\n            return config.max_time\n        if config.min_time > 0.0:\n            return config.min_time\n        return 1.0\n\n    def _stress_round_down_pow2(n: int) -> int:\n        if n <= 1:\n            return 1\n        p = 1\n        while p <= n // 2:\n            p *= 2\n        return p\n\n    def _stress_planned_total_iters() -> int:\n        if stress_est_iter_ms <= 0.0:\n            return 0\n        plan_time_s = _stress_plan_time_s()\n        if plan_time_s <= 0.0:\n            return 0\n        return max([16, int((plan_time_s * 1000.0) / max([0.1, stress_est_iter_ms]))])\n\n    def _stress_refine_cap_iters() -> int:\n        if stress_est_iter_ms <= 0.0:\n            return 0\n        # A 1us phase step is the practical ceiling of the current delay model.\n        est_phase_cap = max([1, int(stress_est_iter_ms * 1000.0)])\n        if config.max_time <= 0.0:\n            return est_phase_cap\n        planned_iters = _stress_planned_total_iters()\n        if planned_iters <= 0:\n            return est_phase_cap\n        planned_cap = max([1, _stress_round_down_pow2(planned_iters)])\n        return max([1, min([est_phase_cap, planned_cap])])\n\n    def _maybe_refine_stress_phase(completed_iterations: int):\n        if not stress_refine_enabled or stress_calibrating:\n            return\n        if stress_base_drift_us <= 1:\n            return\n        if completed_iterations <= 0:\n            return\n        if stress_refine_next_iter <= 0:\n            stress_refine_next_iter = max([1, stress_target_sweep_iters])\n        while completed_iterations >= stress_refine_next_iter and stress_base_drift_us > 1:\n            next_sweep = stress_target_sweep_iters * 2\n            if stress_refine_max_sweep_iters > 0 and next_sweep > stress_refine_max_sweep_iters:\n                next_sweep = stress_refine_max_sweep_iters\n            if next_sweep <= stress_target_sweep_iters:\n                break\n            _set_stress_sweep_iters(next_sweep)\n            stress_refine_next_iter += stress_target_sweep_iters\n\n    def _finalize_stress_calibration():\n        if not stress_calibrating:\n            return\n        if stress_est_iter_ms <= 0.0:\n            return\n        est_total_iters = _stress_planned_total_iters()\n        if est_total_iters >= 512:\n            stress_target_sweep_iters = 256\n        elif est_total_iters >= 128:\n            stress_target_sweep_iters = 64\n        else:\n            stress_target_sweep_iters = 16\n\n        _set_stress_sweep_iters(stress_target_sweep_iters)\n        stress_startup_offset_us = max([0, int((stress_est_iter_ms * 1000.0) * float(stress_drift_rank + 1) / float(stress_drift_workers + 1))])\n        if stress_refine_enabled:\n            stress_refine_next_iter = max([1, stress_target_sweep_iters])\n            stress_refine_max_sweep_iters = max([stress_target_sweep_iters, _stress_refine_cap_iters()])\n        stress_calibrating = False\n\n    def _stress_drift_delay() -> int:\n        if not config.stress_mode or config.perf_mode:\n            return 0\n        if executor_id < stress_nodrift_workers:\n            stress_last_drift_us = 0\n            return 0\n        if stress_calibrating:\n            stress_last_drift_us = 0\n            return 0\n        if not stress_startup_done:\n            if stress_startup_offset_us > 0:\n                acton.rts.sleep(syscap, float(stress_startup_offset_us) / 1000000.0)\n                stress_total_drift_us += stress_startup_offset_us\n            stress_startup_done = True\n        drift_us = stress_worker_drift_us\n        if drift_us <= 0:\n            drift_us = max([1, stress_drift_rank + 1])\n        stress_last_drift_us = drift_us\n        stress_total_drift_us += drift_us\n        acton.rts.sleep(syscap, float(drift_us) / 1000000.0)\n        return drift_us\n\n    def _read_expected(path: str) -> ?str:\n        try:\n            exp_file = file.ReadFile(rfcap, path)\n            try:\n                exp_data = exp_file.read().decode()\n                exp_file.close()\n                return exp_data\n            except:\n                exp_file.close()\n        except:\n            return None\n\n    def get_expected(module: str, test: str) -> ?str:\n        snapshot_path = file.join_path([fs.cwd(), \"snapshots\", \"expected\", module, test])\n        exp_val = _read_expected(snapshot_path)\n        if exp_val is not None:\n            return exp_val\n        # TODO: remove this legacy path once ecosystem is on the new path\n        legacy_path = file.join_path([fs.cwd(), \"test\", \"golden\", module, test])\n        return _read_expected(legacy_path)\n\n    action def _report_result(test: Test, sw, non_gc_mem_usage_before, gc_total_bytes_start, gc_time_start, success: ?bool, exception: ?Exception, val: ?str):\n        full_dur = sw.elapsed().to_float() * 1000.0\n        gc_time_end = acton.rts.get_gc_time(syscap).total\n        gc_dur = float(gc_time_end - gc_time_start)\n        testiter_dur = full_dur - gc_dur\n        gc_total_bytes_end = int(acton.rts.get_gc_total_bytes(syscap))\n        mem_usage_delta = gc_total_bytes_end - gc_total_bytes_start\n        test_dur = test_sw.elapsed().to_float()\n        if config.stress_mode and not config.perf_mode:\n            _update_stress_timing_estimate(testiter_dur)\n            if stress_calibrating:\n                stress_calib_samples += 1\n                if stress_calib_samples >= stress_calib_target_samples:\n                    _finalize_stress_calibration()\n        if config.perf_mode:\n            acton.rts.gc(syscap)\n            acton.rts.gc(syscap)\n        non_gc_mem_usage_after = int(acton.rts.get_rss(syscap) - acton.rts.get_mem_usage(syscap))\n        non_gc_mem_usage_delta = non_gc_mem_usage_after - non_gc_mem_usage_before\n        #print(f\"non-GC memory before: {non_gc_mem_usage_before}  after: {non_gc_mem_usage_after}  delta: {non_gc_mem_usage_delta}\")\n\n        skipped = isinstance(exception, SkipTest)\n        skip_reason = None\n        if skipped:\n            skip_exc = exception\n            if skip_exc is not None:\n                skip_reason = str(skip_exc)\n            success = True\n            exception = None\n\n        completed_iterations = iteration + 1\n        complete = False\n        if skipped:\n            complete = True\n        if config.stress_mode:\n            if config.max_time > 0.0 and test_dur > config.max_time:\n                complete = True\n            if config.max_iter > 0 and completed_iterations >= config.max_iter:\n                complete = True\n        else:\n            if test_dur > config.min_time and completed_iterations > config.min_iter:\n                complete = True\n            if config.max_time > 0 and test_dur > config.max_time:\n                complete = True\n            if config.max_iter > 0 and completed_iterations >= config.max_iter:\n                complete = True\n\n        if test_info is not None:\n            exc = str(exception) if exception is not None else None\n            test_info.update(complete, TestResult(success, exc, val, testiter_dur, mem_usage_delta, non_gc_mem_usage_delta, skipped=skipped, skip_reason=skip_reason), test_dur*1000.0)\n            if config.stress_mode and not config.perf_mode and executor_id >= stress_nodrift_workers:\n                _maybe_refine_stress_phase(test_info.num_iterations)\n        iteration = completed_iterations\n        if last_report.elapsed().to_float() > 0.05 or complete:\n            if test_info is not None and config.output_enabled:\n                print(\"\\n\" + json.encode({\"test_info\": test_info.to_json()}), err=True)\n            last_report.reset()\n        if config.stress_mode and (iteration == 1 or iteration % 32 == 0 or progress_report_sw.elapsed().to_float() > 0.08 or complete):\n            report_progress(executor_id,\n                            iteration,\n                            stress_last_drift_us,\n                            stress_total_drift_us,\n                            stress_est_iter_ms,\n                            stress_phase_resolution_us,\n                            stress_target_sweep_iters,\n                            stress_calibrating)\n            progress_report_sw.reset()\n        if not complete:\n            # Re-schedule the next iteration instead of recursing so stress\n            # workers stop promptly once they cross the time budget.\n            after 0: _run_fn(test)\n        else:\n            report_complete(executor_id, t, test_info)\n\n    def _run_fn(t: Test):\n        _stress_drift_delay()\n        print(\"\\n== Running test, iteration:\", iteration)\n        print(\"\\n== Running test, iteration:\", iteration, err=True)\n        # Run GC to get accurate memory usage\n        if config.perf_mode:\n            acton.rts.gc(syscap)\n            acton.rts.gc(syscap)\n        non_gc_mem_usage_before = int(acton.rts.get_rss(syscap) - acton.rts.get_mem_usage(syscap))\n        gc_total_bytes_start = int(acton.rts.get_gc_total_bytes(syscap))\n        gc_time_start = acton.rts.get_gc_time(syscap).total\n        sw = time.Stopwatch()\n\n        def repres(s: ?bool, e: ?Exception, val: ?str) -> None:\n            # Compare expected snapshot value\n            if val is not None:\n                exp_val = get_expected(t.module, t.display_name())\n                if exp_val is None or exp_val is not None and val != exp_val:\n                    exc = NotEqualError(val, exp_val, f\"Test output does not match expected snapshot value.\", diff_str=f\"{term.normal}{diff.diff(str(exp_val), val, color=True)}\", print_vals=False)\n                    _report_result(t, sw, non_gc_mem_usage_before, gc_total_bytes_start, gc_time_start, False, exc, val)\n                    return\n            _report_result(t, sw, non_gc_mem_usage_before, gc_total_bytes_start, gc_time_start, s, e, val)\n\n        try:\n            t.run(repres, env, log_handler, config.tags)\n        except SkipTest as e:\n            _report_result(t, sw, non_gc_mem_usage_before, gc_total_bytes_start, gc_time_start, True, e, None)\n        except AssertionError as e:\n            _report_result(t, sw, non_gc_mem_usage_before, gc_total_bytes_start, gc_time_start, False, e, None)\n        except Exception as e:\n            _report_result(t, sw, non_gc_mem_usage_before, gc_total_bytes_start, gc_time_start, None, e, None)\n\n    def _run_test():\n        \"\"\"Get the next available test and run it\"\"\"\n        test_sw = time.Stopwatch()\n        test_info = TestInfo(t)\n        _run_fn(t)\n\n    after 0: _run_test()\n\n\nclass ProjectTestResults(object):\n    results: dict[str, dict[str, TestInfo]]\n    last_results: dict[str, dict[str, TestInfo]]\n    sw: time.Stopwatch\n    expected_modules: set[str]\n    printed_lines: int\n    up_to_date: bool\n    perf_mode: bool\n\n    def __init__(self, perf_data: str, perf_mode: bool=False):\n        self.results = {}\n        self.sw = time.Stopwatch()\n        self.expected_modules = set([''])\n        self.printed_lines = 0\n        self.up_to_date = False\n        self.perf_mode = perf_mode\n        self.last_results = {}\n        self.last_results = self.parse_perf_data(perf_data)\n\n    def parse_perf_data(self, perf_data: str) -> dict[str, dict[str, TestInfo]]:\n        \"\"\"Parse performance data from a file\n        \"\"\"\n        try:\n            pd = json.decode(perf_data)\n            res = {}\n            for modname, modres in pd.items():\n                resmodres = {}\n                if isinstance(modname, str) and isinstance(modres, dict):\n                    for tname, tinfo in modres.items():\n                        resmodres[tname] = TestInfo.from_json(tinfo)\n                res[modname] = resmodres\n            return res\n        except:\n            print(\"Failed to parse performance data\")\n            return {}\n\n    def update(self, module_name: str, test_name: str, test_info: TestInfo):\n        \"\"\"Update result for individual test\n        \"\"\"\n        self.up_to_date = False\n        if module_name not in self.results:\n            self.results[module_name] = {}\n        self.results[module_name][test_name] = test_info\n\n    def num_tests(self):\n        cnt = 0\n        for module_name in self.results:\n            cnt += len(self.results[module_name])\n        return cnt\n\n    def skip_show(self):\n        if len(self.expected_modules) > 0 and set(self.results.keys()) != self.expected_modules:\n            return True\n        return False\n\n    def is_test_done(self, modname, name):\n        if modname in self.results and name in self.results[modname]:\n            test_info = self.results[modname][name]\n            return test_info.complete\n        return False\n\n    def is_module_done(self, modname):\n        if modname in self.results:\n            for tname, test_info in self.results[modname].items():\n                if not test_info.complete:\n                    return False\n        return True\n\n    def to_json(self):\n        \"\"\"Return JSON encoded results that can be saved to a file\n        \"\"\"\n        # TODO: rewrite using comprehensions\n        res = {}\n        for modname in self.results:\n            modres = {}\n            for tname, tinfo in self.results[modname].items():\n                modres[tname] = tinfo.to_json()\n            res[modname] = modres\n        return json.encode(res)\n\n    def show(self, show_ongoing: bool=False, show_log: bool=False, perf_mem: bool=True)->?int:\n\n        def format_diff(new, old, unit=\"\"):\n            diff = float(new) - float(old)\n            pct_diff = diff / float(old) * 100\n            sign = \"+\" if diff > 0 else \"\"\n            color = term.green if diff < 0 else term.red\n            diff_str = f\"{sign}{pct_diff:.2f}\" + \"%\"\n            return f\"{color}{diff_str:<10}{term.normal}\"\n\n        def format_timing(module_name, test_name):\n            tinfo = self.results[module_name][test_name]\n\n            min_dur = \"--\"\n            avg_dur = \"--\"\n            max_dur = \"--\"\n            min_dur_diff = \"--\"\n            avg_dur_diff = \"--\"\n            max_dur_diff = \"--\"\n            if tinfo.num_iterations > 0:\n                min_dur = f\"{tinfo.min_duration:6.2f}{term.grey13}ms{term.normal}\"\n                avg_dur = f\"{tinfo.avg_duration:6.2f}{term.grey13}ms{term.normal}\"\n                max_dur = f\"{tinfo.max_duration:6.2f}{term.grey13}ms{term.normal}\"\n                min_dur_diff = \"\"\n                avg_dur_diff = \"\"\n                max_dur_diff = \"\"\n\n                try:\n                    last_tinfo = self.last_results[module_name][test_name]\n                    min_dur_diff = format_diff(tinfo.min_duration, last_tinfo.min_duration)\n                    avg_dur_diff = format_diff(tinfo.avg_duration, last_tinfo.avg_duration)\n                    max_dur_diff = format_diff(tinfo.max_duration, last_tinfo.max_duration)\n                except:\n                    pass\n\n            return f\"{min_dur:>8} {min_dur_diff:>10} {term.grey18}Avg:{term.normal} {avg_dur:>8} {avg_dur_diff:>10} {max_dur:>8} {max_dur_diff:>10}\"\n\n        if self.skip_show() or self.up_to_date:\n            return\n        self.up_to_date = True\n\n        errors = 0\n        failures = 0\n        skipped = 0\n        complete = True\n        if set(self.results.keys()) != self.expected_modules:\n            complete = False\n        for module_name in self.results:\n            for test_name, test_info in self.results[module_name].items():\n                if not test_info.complete:\n                    complete = False\n        if not show_ongoing and not complete:\n            return\n\n        for i in range(self.printed_lines):\n            print(term.clearline + term.up() + term.clearline, end=\"\")\n        self.printed_lines = 0\n        tname_width = 20\n        for modname in self.results:\n            for tname, tinfo in self.results[modname].items():\n                tname_width = max_def([tname_width, len(tinfo.definition.display_name())],0)\n        tname_width += 5\n\n        for module_name in sorted(self.results):\n            if module_name == \"\":\n                print(\"\\nTests\")\n                self.printed_lines += 2\n            elif len(self.results[module_name]) > 0:\n                print(f\"\\nTests - module {module_name}:\")\n                self.printed_lines += 2\n\n            for test_name, tinfo in self.results[module_name].items():\n                last_tinfo = None\n                if module_name in self.last_results and test_name in self.last_results[module_name]:\n                    last_tinfo = self.last_results[module_name][test_name]\n                prefix = \"  {tinfo.definition.display_name()}: \"\n                prefix += \" \" * (tname_width - len(prefix))\n                success = tinfo.success\n                exc = tinfo.exception\n                status = \"\"\n                msg = \"\"\n                run_info = \"\"\n                if tinfo.complete:\n                    if tinfo.skipped:\n                        skipped += 1\n                        msg += term.yellow + \"SKIP\" + term.normal\n                    elif exc is not None:\n                        msg += term.bold + term.red\n                        if tinfo.flaky:\n                            msg += \"FLAKY \"\n                        if tinfo.num_errors > 0:\n                            msg += \"ERR\"\n                            errors += 1\n                            run_info += f\"{tinfo.num_errors} errors\"\n                        if tinfo.num_errors > 0 and tinfo.num_failures > 0:\n                            msg += \"/\"\n                            run_info += \" and \"\n                        if tinfo.num_failures > 0:\n                            msg += \"FAIL\"\n                            failures += 1\n                            run_info += f\"{tinfo.num_failures} failures\"\n                        if tinfo.num_errors > 0 or tinfo.num_failures > 0:\n                            run_info += \" out of \"\n                    else:\n                        msg += term.green + \"OK\" + term.normal\n                    msg += \": \"\n                    if self.perf_mode:\n                        msg += format_timing(module_name, test_name) + \" \"\n                    msg += f\"{tinfo.num_iterations:4d} runs in {tinfo.test_duration:3.3f}ms{term.normal}\"\n                else:\n                    msg = term.yellow + \"**\" + term.normal\n\n                l = prefix + msg\n                print(l)\n                self.printed_lines += 1\n                success_runs = max([0, tinfo.num_iterations - tinfo.num_skipped - tinfo.num_failures - tinfo.num_errors])\n                if tinfo.num_iterations > 1 and (tinfo.num_failures > 0 or tinfo.num_errors > 0 or tinfo.num_skipped > 0):\n                    outcome_parts = []\n                    if success_runs > 0:\n                        outcome_parts.append(f\"{success_runs} ok\")\n                    if tinfo.num_failures > 0:\n                        outcome_parts.append(f\"{tinfo.num_failures} fail\")\n                    if tinfo.num_errors > 0:\n                        outcome_parts.append(f\"{tinfo.num_errors} err\")\n                    if tinfo.num_skipped > 0:\n                        outcome_parts.append(f\"{tinfo.num_skipped} skip\")\n                    if len(outcome_parts) > 0:\n                        print(\"    outcomes: \" + \", \".join(outcome_parts))\n                        self.printed_lines += 1\n                if self.perf_mode and perf_mem:\n                    indent = \" \" * 10\n                    diffs = tinfo.diff(last_tinfo)\n                    print(f\"{indent}Memory usage     : {tinfo.mem_usage_delta_avg // 1024:6d}KB {diffs.mem_usage_delta_avg}\")\n                    print(f\"{indent}non-GC usage     : {tinfo.non_gc_mem_usage_delta_avg // 1024:6d}KB {diffs.non_gc_mem_usage_delta_avg}\")\n                    print(indent + \"non-GC usage > 0 : %d%% (%d out of %d)\" % ((tinfo.non_gc_mem_inc_count * 100 // tinfo.num_iterations) if tinfo.num_iterations > 0 else 0,\n                                                                        tinfo.non_gc_mem_inc_count,\n                                                                        tinfo.num_iterations))\n                    self.printed_lines += 3\n                if tinfo.complete:\n                    if tinfo.skipped and tinfo.skip_reason is not None:\n                        print(f\"{term.yellow}    skipped: {tinfo.skip_reason}{term.normal}\")\n                        self.printed_lines += 1\n                    if exc is not None:\n                        for line in str(exc).splitlines(None):\n                            print(f\"{term.red}    {line}{term.normal}\")\n                            self.printed_lines += 1\n                    # Print std_out/std_err if the test failed\n                    if show_log or tinfo.num_failures > 0 or tinfo.num_errors > 0:\n                        def test_output(msgs: str):\n                            for line in msgs.splitlines():\n                                if not (line.startswith(\"== Running test,\") or line == \"\"):\n                                    return True\n                            return False\n\n                        def dedup(buf: str) -> dict[str, set[int]]:\n                            # Initialize result dictionary\n                            result = {}\n\n                            # Split buffer into individual test iterations\n                            iterations = buf.split(\"== Running test, iteration: \")\n\n                            # Clean up iterations - remove empty entries\n                            cleaned_iterations = []\n                            for it in iterations:\n                                if it.strip():\n                                    cleaned_iterations.append(it.strip())\n\n                            # Process each iteration\n                            for iteration in cleaned_iterations:\n                                # Extract iteration number and content\n                                lines = iteration.split('\\n', 1)\n                                iteration_num = int(lines[0])\n                                content = \"\"\n                                if len(lines) > 1: # might not be any real test output yet!?\n                                    content = lines[1].strip()\n\n                                # Add to result dictionary\n                                if content not in result:\n                                    result[content] = set()\n                                result[content].add(iteration_num)\n\n                            return result\n\n                        std_out = tinfo.std_out\n                        if std_out is not None and test_output(std_out):\n                            print(\"    STDOUT:\")\n                            self.printed_lines += 1\n                            chunks = dedup(std_out.strip())\n                            for chunk, test_runs in chunks.items():\n                                if len(chunks) == 1:\n                                    pass\n                                else:\n                                    print(f\"      == {len(test_runs)} test runs with this output:\")\n                                    self.printed_lines += 1\n                                for line in chunk.splitlines():\n                                    print(\"      \" + line)\n                                    self.printed_lines += 1\n                                print(\"\")\n                                self.printed_lines += 1\n                        std_err = tinfo.std_err\n                        if std_err is not None and test_output(std_err):\n                            print(\"    STDERR:\")\n                            self.printed_lines += 1\n                            chunks = dedup(std_err.strip())\n                            for chunk, test_runs in chunks.items():\n                                if len(chunks) == 1:\n                                    pass\n                                else:\n                                    print(f\"      == {len(test_runs)} test runs with this output:\")\n                                    self.printed_lines += 1\n                                for line in chunk.splitlines():\n                                    print(\"      \" + line)\n                                    self.printed_lines += 1\n                                print(\"\")\n                                self.printed_lines += 1\n\n        print(\"\")\n        if complete:\n            if self.num_tests() == 0:\n                print(\"Nothing to test\")\n                print()\n                return 0\n            elif errors > 0 and failures > 0:\n                print(f\"{term.bold}{term.red}{errors} error and {failures} failure out of {self.num_tests()} tests ({self.sw.elapsed().str_ms()}s){term.normal}\")\n                print()\n                return 2\n            elif errors > 0:\n                print(f\"{term.bold}{term.red}{errors} out of {self.num_tests()} tests errored ({self.sw.elapsed().str_ms()}s){term.normal}\")\n                print()\n                return 2\n            elif failures > 0:\n                print(f\"{term.bold}{term.red}{failures} out of {self.num_tests()} tests failed ({self.sw.elapsed().str_ms()}s){term.normal}\")\n                print()\n                return 1\n            else:\n                if skipped > 0:\n                    print(f\"{term.green}All {self.num_tests()} tests passed, {skipped} skipped ({self.sw.elapsed().str_ms()}s){term.normal}\")\n                else:\n                    print(f\"{term.green}All {self.num_tests()} tests passed ({self.sw.elapsed().str_ms()}s){term.normal}\")\n                print()\n                return 0\n        else:\n            print(\"Running tests...\")\n            print()\n        self.printed_lines += 3\n\n\nactor test_runner(env: Env,\n                  unit_tests: dict[str, UnitTest],\n                  simple_sync_tests: dict[str, SimpleSyncTest],\n                  sync_tests: dict[str, SyncTest],\n                  async_tests: dict[str, AsyncTest],\n                  env_tests: dict[str, EnvTest]):\n    sw = time.Stopwatch()\n    var all_tests = {}\n\n    for name, t in unit_tests.items():\n        all_tests[name] = t\n    for name, t in simple_sync_tests.items():\n        all_tests[name] = t\n    for name, t in sync_tests.items():\n        all_tests[name] = t\n    for name, t in async_tests.items():\n        all_tests[name] = t\n    for name, t in env_tests.items():\n        all_tests[name] = t\n\n    proc def _cmd_list(args):\n        res = {}\n        for test_name, test_def in all_tests.items():\n            test_info = TestInfo(test_def)\n            res[test_name] = test_info.to_json()\n        print(\"\\n\" + json.encode({\"tests\": res}), err=True)\n        env.exit(0)\n\n\n\n    proc def _run_tests(args, perf_mode: bool=False, stress_mode: bool=False):\n        config = TestRunnerConfig(perf_mode, stress_mode, args)\n        if config.perf_mode:\n            acton.rts.start_gc_performance_measurement(env.syscap)\n\n        def _default_stress_workers() -> int:\n            # Stress runs benefit from oversubscription so worker actors must\n            # share RTS worker threads instead of mapping one-to-one.\n            base_workers = max([1, env.nr_wthreads])\n            extra_workers = max([1, base_workers // 2])\n            return base_workers + extra_workers\n\n        def _stress_timeout_slack_s() -> float:\n            if not config.stress_mode or config.perf_mode:\n                return 1.0\n            # Oversubscribed stress runs can take several extra seconds to\n            # drain workers and emit the final aggregate result.\n            return max([5.0, min([10.0, config.min_time * 0.9])])\n\n        test_concurrency = 1\n        stress_nodrift_workers = 0\n        if config.stress_mode and not config.perf_mode:\n            if config.stress_workers > 0:\n                test_concurrency = config.stress_workers\n            else:\n                test_concurrency = _default_stress_workers()\n            stress_nodrift_workers = min([test_concurrency, max([2, (test_concurrency + 3) // 4])])\n        test_timeout = 0.0\n        if config.max_time > 0:\n            test_timeout = max([config.max_time, 2.0]) + _stress_timeout_slack_s()\n\n        test_name = args.get_str(\"name\")\n        if test_name not in all_tests:\n            print(f\"Test not found: {test_name}\")\n            env.exit(1)\n        the_test = all_tests[test_name]\n        workers_complete = set()\n        combined_info = TestInfo(the_test)\n        combined_sw = time.Stopwatch()\n        worker_iterations = {}\n        worker_drift_us = {}\n        worker_drift_total_us = {}\n        worker_est_iter_ms = {}\n        worker_phase_resolution_us = {}\n        worker_target_sweep_iters = {}\n        worker_calibrating = {}\n        stress_phase_cov = {\n            \"bins_total\": 0,\n            \"res_us\": 0,\n            \"seen_count\": 0,\n            \"epoch\": 1\n        }\n        stress_phase_bins_epoch = {}\n        for idx in range(test_concurrency):\n            worker_iterations[idx] = 0\n            worker_drift_us[idx] = 0\n            worker_drift_total_us[idx] = 0\n            worker_est_iter_ms[idx] = 0.0\n            worker_phase_resolution_us[idx] = 0\n            if idx < stress_nodrift_workers:\n                worker_target_sweep_iters[idx] = 0\n                worker_calibrating[idx] = False\n            else:\n                worker_target_sweep_iters[idx] = 16\n                worker_calibrating[idx] = config.stress_mode\n\n        def _total_worker_iterations() -> int:\n            total = 0\n            for idx in range(test_concurrency):\n                total += worker_iterations[idx]\n            return total\n\n        def _stress_workers_json():\n            workers = []\n            for idx in range(test_concurrency):\n                workers.append({\n                    \"id\": idx,\n                    \"iterations\": worker_iterations[idx],\n                    \"drift_us\": worker_drift_us[idx],\n                    \"drift_total_us\": worker_drift_total_us[idx],\n                    \"est_iter_ms\": worker_est_iter_ms[idx],\n                    \"phase_resolution_us\": worker_phase_resolution_us[idx],\n                    \"target_sweep_iters\": worker_target_sweep_iters[idx],\n                    \"calibrating\": worker_calibrating[idx],\n                    \"sync\": idx < stress_nodrift_workers\n                })\n            return workers\n\n        def _stress_est_iteration_ms() -> float:\n            total = 0.0\n            count = 0\n            for idx in range(test_concurrency):\n                est = worker_est_iter_ms[idx]\n                if est > 0.0:\n                    total += est\n                    count += 1\n            if count > 0:\n                return total / float(count)\n            return 0.0\n\n        def _stress_phase_resolution_ms() -> float:\n            worst_us = 0\n            for idx in range(stress_nodrift_workers, test_concurrency):\n                res_us = worker_phase_resolution_us[idx]\n                if res_us > worst_us:\n                    worst_us = res_us\n            if worst_us > 0:\n                return float(worst_us) / 1000.0\n            est_ms = _stress_est_iteration_ms()\n            if est_ms > 0.0:\n                return est_ms / 16.0\n            return 0.0\n\n        def _stress_target_sweep_iters() -> int:\n            target = 0\n            for idx in range(stress_nodrift_workers, test_concurrency):\n                if worker_target_sweep_iters[idx] > target:\n                    target = worker_target_sweep_iters[idx]\n            return target\n\n        def _stress_calibrating_workers() -> int:\n            count = 0\n            for idx in range(stress_nodrift_workers, test_concurrency):\n                if worker_calibrating[idx]:\n                    count += 1\n            return count\n\n        def _update_stress_phase_coverage():\n            if not config.stress_mode or config.perf_mode:\n                return\n            if test_concurrency <= stress_nodrift_workers:\n                return\n            phase_res_ms = _stress_phase_resolution_ms()\n            est_ms = _stress_est_iteration_ms()\n            if phase_res_ms <= 0.0 or est_ms <= 0.0:\n                return\n            phase_res_us = max([1, int(phase_res_ms * 1000.0)])\n            bins_total = _stress_target_sweep_iters()\n            if bins_total <= 0:\n                est_us = max([phase_res_us, int(est_ms * 1000.0)])\n                bins_total = max([1, est_us // phase_res_us])\n            if bins_total != stress_phase_cov[\"bins_total\"] or phase_res_us != stress_phase_cov[\"res_us\"]:\n                stress_phase_cov[\"bins_total\"] = bins_total\n                stress_phase_cov[\"res_us\"] = phase_res_us\n                stress_phase_cov[\"seen_count\"] = 0\n                stress_phase_cov[\"epoch\"] = stress_phase_cov[\"epoch\"] + 1\n            for idx in range(stress_nodrift_workers, test_concurrency):\n                if worker_calibrating[idx]:\n                    continue\n                drift_total = worker_drift_total_us[idx]\n                if drift_total <= 0:\n                    continue\n                bin_idx = (drift_total // phase_res_us) % bins_total\n                current_epoch = stress_phase_cov[\"epoch\"]\n                if bin_idx in stress_phase_bins_epoch and stress_phase_bins_epoch[bin_idx] == current_epoch:\n                    continue\n                stress_phase_bins_epoch[bin_idx] = current_epoch\n                stress_phase_cov[\"seen_count\"] = stress_phase_cov[\"seen_count\"] + 1\n\n        def _stress_payload(info: TestInfo):\n            payload = info.to_json()\n            payload[\"stress_worker_count\"] = test_concurrency\n            payload[\"stress_no_drift_workers\"] = stress_nodrift_workers\n            payload[\"stress_est_iteration_ms\"] = _stress_est_iteration_ms()\n            payload[\"stress_phase_resolution_ms\"] = _stress_phase_resolution_ms()\n            payload[\"stress_target_sweep_iters\"] = _stress_target_sweep_iters()\n            payload[\"stress_calibrating_workers\"] = _stress_calibrating_workers()\n            payload[\"stress_phase_bins_seen\"] = stress_phase_cov[\"seen_count\"]\n            payload[\"stress_phase_bins_total\"] = stress_phase_cov[\"bins_total\"]\n            payload[\"stress_workers\"] = _stress_workers_json()\n            return payload\n\n        def _emit_stress_live():\n            if not config.stress_mode or len(workers_complete) >= test_concurrency:\n                return\n            _update_stress_phase_coverage()\n            payload = _stress_payload(combined_info)\n            total_iterations = _total_worker_iterations()\n            payload[\"complete\"] = False\n            payload[\"success\"] = None\n            payload[\"exception\"] = None\n            payload[\"num_failures\"] = 0\n            payload[\"num_errors\"] = 0\n            payload[\"num_iterations\"] = total_iterations\n            payload[\"test_duration\"] = combined_sw.elapsed().to_float() * 1000.0\n            if total_iterations > 0:\n                print(\"\\n\" + json.encode({\"test_info\": payload}), err=True)\n            after 0.08: _emit_stress_live()\n\n        def _merge_worker_info(worker_info: ?TestInfo):\n            if worker_info is not None:\n                for result in worker_info.results:\n                    combined_info.update(False, result)\n\n        def report_progress(executor_id: int,\n                            iterations: int,\n                            drift_us: int,\n                            drift_total_us: int,\n                            est_iter_ms: float,\n                            phase_resolution_us: int,\n                            target_sweep_iters: int,\n                            calibrating: bool):\n            if executor_id in worker_iterations:\n                if iterations > worker_iterations[executor_id]:\n                    worker_iterations[executor_id] = iterations\n                worker_drift_us[executor_id] = drift_us\n                worker_drift_total_us[executor_id] = max([worker_drift_total_us[executor_id], drift_total_us])\n                worker_est_iter_ms[executor_id] = est_iter_ms\n                worker_phase_resolution_us[executor_id] = phase_resolution_us\n                if target_sweep_iters > 0:\n                    worker_target_sweep_iters[executor_id] = target_sweep_iters\n                worker_calibrating[executor_id] = calibrating\n                _update_stress_phase_coverage()\n\n        def _check_timeout():\n            if test_timeout <= 0.0:\n                return\n            if len(workers_complete) >= test_concurrency:\n                # Report after we hit timeout\n                return\n            time_s = test_timeout * 1000.0\n            if config.stress_mode:\n                if len(combined_info.results) > 0:\n                    combined_info.update(\n                        True,\n                        TestResult(\n                            None,\n                            \"Test timeout\",\n                            None,\n                            time_s,\n                            0,\n                            0),\n                        time_s)\n                    _update_stress_phase_coverage()\n                    payload = _stress_payload(combined_info)\n                    payload[\"complete\"] = True\n                    payload[\"test_duration\"] = time_s\n                    payload[\"num_iterations\"] = max([combined_info.num_iterations, _total_worker_iterations()])\n                    print(\"\\n\" + json.encode({\"test_info\": payload}), err=True)\n                    env.exit(0)\n                timeout_info = TestInfo(\n                    the_test,\n                    complete=True,\n                    success=None,\n                    exception=\"Test timeout\",\n                    min_duration=time_s,\n                    max_duration=time_s,\n                    avg_duration=time_s,\n                    total_duration=time_s,\n                    test_duration=time_s,\n                    num_iterations=max([1, _total_worker_iterations()]),\n                    num_failures=0,\n                    num_errors=1\n                    )\n                _update_stress_phase_coverage()\n                payload = _stress_payload(timeout_info)\n                payload[\"num_iterations\"] = max([timeout_info.num_iterations, _total_worker_iterations()])\n                print(\"\\n\" + json.encode({\"test_info\": payload}), err=True)\n                env.exit(0)\n            test_info = TestInfo(\n                the_test,\n                complete=True,\n                success=None,\n                exception=\"Test timeout\",\n                min_duration=time_s,\n                max_duration=time_s,\n                avg_duration=time_s,\n                total_duration=time_s,\n                test_duration=time_s,\n                num_iterations=1,\n                num_failures=0,\n                num_errors=1\n                )\n            print(\"\\n\" + json.encode({\"test_info\": test_info.to_json()}), err=True)\n            env.exit(0)\n\n        def report_complete(executor_id: int, t, worker_info: ?TestInfo):\n            if executor_id in workers_complete:\n                return\n            workers_complete.add(executor_id)\n            if not config.stress_mode:\n                env.exit(0)\n                return\n            _merge_worker_info(worker_info)\n            if len(workers_complete) >= test_concurrency:\n                combined_info.complete = True\n                combined_info.test_duration = combined_sw.elapsed().to_float() * 1000.0\n                _update_stress_phase_coverage()\n                payload = _stress_payload(combined_info)\n                payload[\"num_iterations\"] = max([combined_info.num_iterations, _total_worker_iterations()])\n                print(\"\\n\" + json.encode({\"test_info\": payload}), err=True)\n                env.exit(0)\n\n        test_executors = []\n        for idx in range(test_concurrency):\n            te = TestExecutor(env.syscap, config, the_test, report_complete, report_progress, env, idx, test_concurrency, stress_nodrift_workers)\n            test_executors.append(te)\n        if config.stress_mode:\n            after 0.08: _emit_stress_live()\n        if test_timeout > 0.0:\n            after test_timeout: _check_timeout()\n\n    proc def _run_perf_tests(args):\n        _run_tests(args, perf_mode=True)\n\n    proc def _run_stress_tests(args):\n        _run_tests(args, stress_mode=True)\n\n    def _parse_args():\n        p = argparse.Parser()\n        p.add_bool(\"json\", \"Output results as JSON\")\n        p.add_bool(\"no_output\", \"No result output\")\n        lp = p.add_cmd(\"list\", \"list tests\", _cmd_list)\n        tp = p.add_cmd(\"test\", \"Run tests\", _run_tests)\n        tp.add_arg(\"name\", \"Name of the test to run\")\n        tp.add_option(\"max-iter\", \"int\", default=10**6, help=\"Maximum number of iterations to run\")\n        tp.add_option(\"min-iter\", \"int\", default=3, help=\"Minumum number of iterations to run\")\n        tp.add_option(\"max-time\", \"int\", default=1000, help=\"Maximum time to run a test in milliseconds (0 = no time limit)\")\n        tp.add_option(\"min-time\", \"int\", default=50, help=\"Minimum time to run a test in milliseconds\")\n        tp.add_option(\"stress-workers\", \"int\", default=0, help=\"Concurrent stress workers to run (0 = auto)\")\n        tp.add_option(\"tag\", \"strlist\", default=[], help=\"Enable test capability tag\")\n        pp = tp.add_cmd(\"perf\", \"Performance benchmark tests\", _run_perf_tests)\n        sp = tp.add_cmd(\"stress\", \"Stress tests by running concurrent workers of the same test\", _run_stress_tests)\n\n        args = p.parse(env.argv)\n        _cmd = args.cmd\n        if _cmd is not None:\n            _cmd(args)\n        else:\n            env.exit(0)\n    try:\n        _parse_args()\n    except argparse.PrintUsage as exc:\n        print(exc.error_message)\n        env.exit(0)\n    except argparse.ArgumentError as exc:\n        print(exc.error_message)\n        env.exit(1)\n"
  },
  {
    "path": "base/src/time.act",
    "content": "\"\"\"Stopwatch, time, dates and calendars\n\nThere are primarily two uses of time\n- measuring elapsed time (e.g. for benchmarking)\n- telling the current date and time (e.g. for logging)\n\nUse a Stopwatch to measure elapsed time, e.g.:\n\n    s = time.Stopwatch()\n    # do something\n    elapsed = s.elapsed()\n    print(\"Elapsed time:\", elapsed.str_us())\n    # Elapsed time: 1.234567 s\n\nCall `now()` to get the current date and time:\n\n    dt = time.now()\n    print(\"Current time:\", dt)\n    # Current time: 2023-03-07T15:33:02.238251863+01\n\n`utcnow()` returns the current date and time in UTC:\n\n    dt = time.utcnow()\n    print(\"UTC time:\", dt)\n    # UTC time: 2023-03-07T14:33:02.238251863Z\n\nInstant and Duration store time using two 64 bit fields for seconds and\nfractional seconds. It amounts to a range of +-292 billion years for Instant and\nan elapsed time of 585 billion years for Duration. The resolution is 1 attosecond.\nIt's a lot of zeros, which is why you might want to use str_us(), str_ms() or\nstr_ns() to get a more humanly readable representation.\n\nInformation about the clock source is kept and used as part of various\noperations to indicate precision and error in resulting values.\n\"\"\"\n\n# TODO: localization?\nMONTHS = [\n    \"January\",\n    \"February\",\n    \"March\",\n    \"April\",\n    \"May\",\n    \"June\",\n    \"July\",\n    \"August\",\n    \"September\",\n    \"October\",\n    \"November\",\n    \"December\"\n]\n\nMNTHS = [\n    \"Jan\",\n    \"Feb\",\n    \"Mar\",\n    \"Apr\",\n    \"May\",\n    \"Jun\",\n    \"Jul\",\n    \"Aug\",\n    \"Sep\",\n    \"Oct\",\n    \"Nov\",\n    \"Dec\"\n]\n\nWEEKDAYS = [\n    \"Sunday\",\n    \"Monday\",\n    \"Tuesday\",\n    \"Wednesday\",\n    \"Thursday\",\n    \"Friday\",\n    \"Saturday\"\n]\n\nWKDAYS = [\n    \"Sun\",\n    \"Mon\",\n    \"Tue\",\n    \"Wed\",\n    \"Thu\",\n    \"Fri\",\n    \"Sat\"\n]\n\ndef _get_incarnation() -> int:\n    \"\"\"Get clock instance ID\n    \"\"\"\n    NotImplemented\n\ndef get_realtime() -> (int, int):\n    \"\"\"clock_gettime for CLOCK_REALTIME\n\n    Returns time represented as seconds and nanoseconds since the Epoch, 1st of\n    January 1970 00:00:00 UTC.\n    \"\"\"\n    NotImplemented\n\ndef get_monotonic() -> (int, int):\n    \"\"\"clock_gettime for CLOCK_MONOTONIC\n\n    Returns time represented as seconds and nanoseconds since an arbitrary start\n    time.\n    \"\"\"\n    NotImplemented\n\n\nclass clock_data:\n    def __init__(self, status: int, offset: int, error: int) -> (status: int, offset: int, error: int):\n        return (status=status, offset=offset, error=error)\n\ndef get_clock_data() -> (status: int, offset: int, error: int):\n    \"\"\"Get clock data\n\n    This uses ntp_adjtime to get the current clock data. The returned tuple\n    contains the synchronization status, the offset and the estimated error in\n    microseconds.\n    \"\"\"\n    NotImplemented\n\n# TODO: use named tuple for return value\ndef localtime(seconds: int) -> (int, int, int, int, int, int, int, int, int, str, int):\n    \"\"\"C localtime() function\n    \"\"\"\n    NotImplemented\n\n# TODO: use named tuple for return value\ndef gmtime(seconds: int) -> (int, int, int, int, int, int, int, int, int):\n    \"\"\"C gmtime() function\n    \"\"\"\n    NotImplemented\n\n\nclass Clock:\n    \"\"\"Clock information\n\n    A clock is a source of time. A Clock object stores information about a\n    clock and additional data about the precision and error of a particular\n    reading from the clock. Every object that represent time, like Instant and\n    DateTime, has a clock attribute which is used to trace where the time came\n    from and if it is comparable to other time.\n\n    There are two types of clocks on most POSIX systems today:\n    - real time clock - `RealtimeClock()`\n    - monotonic clock - `MonotonicClock()`\n\n    It is not possible to compare time between different clock types as they\n    have different starting points. The monotonic clock has an arbitrary\n    starting point whereas the realtime clock starts at Epoch (1970-01-01\n    00:00:00 UTC).\n\n    For an Instant from a monotonic clock, it is only comparable with another\n    Instant from the same monotonic clock. The start time of a monotonic clock\n    is arbitrary which means that not only is it not comparable between two\n    machines, it is also not comparable on the same machines between reboots. In\n    order to determine if we are on the same machine and have not rebooted, we\n    keep track of the clock incarnation which is essentially a unique identifier\n    for the start of a clock. On Linux, this is the boot-id, which is unique per\n    machine and boot. On other platforms we use a random incarnation identifier\n    per start of an Acton node, so time will only be comparable within that\n    running instance of the RTS.\n\n    The local real time clock is typically used to track real world time, which\n    on planet earth practically means Coordinated Universal Time (UTC). Like a\n    wristwatch or any other clock, the local clock needs to be periodically set.\n    The NTP/NTS protocols can be used to synchronize the clock over a network\n    connection. A computer clock without some form of clock synchronization can\n    be wildly incorrect and suffer from discontinuous jumps in time if a system\n    administrator changes the local clock, rendering comparisons of different\n    instants invalid even when they are from the same computer.\n\n    Across multiple computers, as is the case for for distributed Acton systems,\n    there has to be clock synchronization in use for time to be comparable. The\n    precision of comparisons will only be as good as the clock synchronization\n    allows.\n\n    NTP is the most common clock synchronization protocol and it can usually\n    achieve synchronization on the order of milliseconds, even sub-ms on local\n    networks. It largely depends on how good the network is. PTP can achieve\n    sub-microsecond synchronization. It is not possible to compare time from two\n    unsynchronized clocks as we have no idea of their drift from UTC.\n\n    Linux, MacOS and various BSD platforms provides detail information about the\n    real time clock, like if it is synchronized, the estimated error etc. This\n    information is retrieved and kept in a Clock object associated with the\n    retrieved time so that we may track the precision of the final result. The\n    information is provided by the NTP or PTP daemon and is only accurate while\n    that daemon is running. A particularly nasty scenario is when an NTPd has\n    been running, updating the kernel information that the clock is synchronized\n    and with a certain error, but has since stopped, leaving the clock\n    information stale. The kernel has no facility to mark it as stale and thus,\n    we will run under the belief that we get good precision time when in fact we\n    are free running, uncoordinated with UTC. It is ultimately up to the system\n    administrator to ensure that clocks on the system(s) running an Acton system\n    are synchronized, preferrably using NTP or similar.\n    \"\"\"\n    # TODO: turn into constants? but getting acton compiler error\n    @property\n    standard: str\n    # Which time standard this clock provides\n    # \"monotonic\": monotonic clock\n    # \"UTC\": real time (UTC) clock\n    @property\n    incarnation: int\n    @property\n    sync: int\n    @property\n    offset: int\n    @property\n    error: int\n\n    def comparable(self, other: Clock) -> bool:\n        \"\"\"Check if two clocks produce comparable time\n        \"\"\"\n        return False\n\n\nclass RealtimeClock(Clock):\n    \"\"\"Realtime clock\n    \"\"\"\n    def __init__(self, sync: int, offset: int, error: int, standard=\"UTC\"):\n        self.standard = standard\n        self.incarnation = _get_incarnation()\n        self.sync = sync\n        self.offset = offset\n        self.error = error\n\n    def comparable(self, other: Clock) -> bool:\n        \"\"\"Check if two clocks produce comparable time\n        \"\"\"\n        if isinstance(other, RealtimeClock):\n            return self.standard == other.standard and self.sync == other.sync\n        else:\n            return False\n\nclass MonotonicClock(Clock):\n    \"\"\"Monotonic clock\n    \"\"\"\n    def __init__(self, sync: int, offset: int, error: int):\n        self.standard = \"monotonic\"\n        self.incarnation = _get_incarnation()\n        self.sync = sync\n        self.offset = offset\n        self.error = error\n\n    def comparable(self, other: Clock) -> bool:\n        \"\"\"Check if two clocks produce comparable time\n        \"\"\"\n        if isinstance(other, MonotonicClock):\n            return self.incarnation == other.incarnation\n        else:\n            return False\n\nclass Calendar(object):\n    \"\"\"A calendar, like gregorian or julian.\n    \"\"\"\n    pass\n\nclass Timezone:\n    @property\n    name: str\n    @property\n    offset: int\n\n    def __init__(self, name: str, offset: int):\n        self.name = name\n        self.offset = offset\n\n    def str_offset(self) -> str:\n        \"\"\"Return the timezone offset from UTC in ISO8601 style\n        \"\"\"\n        tz_str = \"\"\n        if self.offset == 0:\n            tz_str = \"Z\"\n        else:\n            if self.offset > 0:\n                tz_str = \"+\"\n            else:\n                tz_str = \"-\"\n            tz_str += f\"{self.offset // 3600:02d}\"\n            if self.offset % 3600 > 0:\n                tz_str += f\":{(self.offset % 3600) // 60:02d}\"\n        return tz_str\n\n\nclass DateTime(object):\n    \"\"\"A date and time according to a calendar and time zone.\n    \"\"\"\n    @property\n    calendar: ?Calendar\n    @property\n    timezone: ?Timezone\n    @property\n    clock: ?Clock\n    @property\n    era: ?int\n    @property\n    year: int\n    @property\n    month: int\n    @property\n    day: int\n    @property\n    hour: int\n    @property\n    minute: int\n    @property\n    second: int\n    @property\n    attosecond: int\n    @property\n    weekday: int\n    @property\n    yearday: int\n\n    def __init__(self, calendar: ?Calendar, timezone: ?Timezone, clock: ?Clock,\n                 era: ?int, year: int, month: int, day: int, hour: int,\n                 minute: int, second: int, attosecond: int, weekday: int,\n                 yearday: int):\n        self.calendar = calendar\n        self.timezone = timezone\n        self.clock = clock\n        self.era = era\n        self.year = year\n        self.month = month\n        self.day = day\n        self.hour = hour\n        self.minute = minute\n        self.second = second\n        self.attosecond = attosecond\n        self.weekday = weekday\n        self.yearday = yearday\n\n    def __str__(self):\n        return self.str_iso8601_ns()\n\n    def str_iso8601_ns(self):\n        tz_str = \"\"\n#        if self.timezone is not None:\n#            tz_str = self.timezone.str_short()\n        # TODO: remove this superfluous t variable and use above code, which\n        # currently acton borks out on\n        t = self.timezone\n        if t is not None:\n            tz_str = t.str_offset()\n\n        # Most of the clocks\n        return f\"{self.year:04d}-{self.month:02d}-{self.day:02d}T{self.hour:02d}:{self.minute:02d}:{self.second:02d}.{self.attosecond // 10**9:09d}{tz_str}\"\n\n    @staticmethod\n    def now():\n        cd = get_clock_data()\n        c = RealtimeClock(cd.status, cd.offset, cd.error)\n        s, ns = get_realtime()\n\n        tm = localtime(s)\n        tm_year = tm.0\n        tm_month = tm.1\n        tm_day = tm.2\n        tm_hour = tm.3\n        tm_minute = tm.4\n        tm_second = tm.5\n        tm_wday = tm.6\n        tm_yday = tm.7\n        tm_isdst = tm.8\n\n        attosecond = ns * 10**9\n        return DateTime(None, None, None, None, tm_year, tm_month, tm_day, tm_hour, tm_minute, tm_second, attosecond, tm_wday, tm_yday)\n\n    @staticmethod\n    def utcnow():\n        cd = get_clock_data()\n        c = RealtimeClock(cd.status, cd.offset, cd.error)\n        s, ns = get_realtime()\n\n        tm = gmtime(s)\n        tm_year = tm.0\n        tm_month = tm.1\n        tm_day = tm.2\n        tm_hour = tm.3\n        tm_minute = tm.4\n        tm_second = tm.5\n        tm_wday = tm.6\n        tm_yday = tm.7\n        tm_isdst = tm.8\n\n        attosecond = ns * 10**9\n        return DateTime(None, None, None, None, tm_year, tm_month, tm_day, tm_hour, tm_minute, tm_second, attosecond, tm_wday, tm_yday)\n\n    def str_rfc1123(self):\n        # TODO: heh, lol, actually convert to GMT first\n        # web servers want rfc1123 and it should always be in GMT, but I suppose there are other uses of rfc1123\n        return \"%s, %02d %s %04d %02d:%02d:%02d GMT\" % (\n            WKDAYS[self.weekday], self.day, MNTHS[self.month-1], self.year,\n            self.hour, self.minute, self.second)\n\n    def str_asctime(self):\n        return \"%s %s %2d %02d:%02d:%02d %04d\" % (\n            WEEKDAYS[self.weekday][0:3], MONTHS[self.month][0:3], self.day,\n            self.hour, self.minute, self.second, self.year)\n\n\n\nclass Instant(object):\n    \"\"\"A specific point in time as measured with a monotonically increasing\n    clock. Only useful with ~Duration~ and ~Stopwatch~ to measure elapsed time.\n\n    An Instant does not carry calendar or time zone information.\n\n    Stores time using:\n    - i64 second\n    - u64 attosecond\n    Which gives a range of ±292 billion years with a precision down to\n    atto-second (2^10-18).\n    \"\"\"\n    @property\n    second: int\n    @property\n    attosecond: int\n    @property\n    clock: Clock\n\n    # TODO: compiler bug? why isn't c allowed to be maybe Clock? the effect of\n    # __init__ is that self.clock is always a Clock anyway...\n    #def __init__(self, sec: int, asec: int, c: ?Clock=None):\n    def __init__(self, sec: int, asec: int, c: Clock):\n        self.second = sec\n        self.attosecond = asec\n        self.clock = c\n\n    def __str__(self):\n        return f\"{self.second}.{self.attosecond:018d}\"\n\n    def __repr__(self):\n        return f\"Instant({self.second}, {self.attosecond})\"\n\n    def str_ms(self):\n        \"\"\"Return a string representation of the duration with milliseconds.\n        \"\"\"\n        return f\"{self.second}.{self.attosecond // 10**15:03d}\"\n\n    def str_us(self):\n        \"\"\"Return a string representation of the duration with microseconds.\n        \"\"\"\n        return f\"{self.second}.{self.attosecond // 10**12:06d}\"\n\n    def str_ns(self):\n        \"\"\"Return a string representation of the duration with nanoseconds.\n        \"\"\"\n        return f\"{self.second}.{self.attosecond // 10**9:09d}\"\n\n#    TODO: fix this\n#    def __sub__(self, other: Instant) -> Duration:\n#        if (self.second == other.second and self.attosecond > other.attosecond) or self.second > other.second:\n#            return Duration(self.second - other.second, self.attosecond - other.attosecond)\n#        else:\n#            return Duration(other.second - self.second, other.attosecond - self.attosecond)\n\n    def add(self, duration: Duration) -> Instant:\n        attosecond_sum = self.attosecond + duration.attosecond\n        return Instant(self.second + duration.second + attosecond_sum // 10**18, attosecond_sum % 10**18, self.clock)\n\n    def sub(self, duration: Duration) -> Instant:\n        result_attoseconds = self.attosecond - duration.attosecond\n        result_seconds = self.second - duration.second\n        if result_attoseconds < 0:\n            result_seconds -= 1\n            result_attoseconds += 10**18  # 1 second = 10^18 attoseconds\n        return Instant(result_seconds, result_attoseconds, self.clock)\n\n    def since(self, other: Instant) -> Duration:\n        \"\"\"Return the duration since this instant.\n        \"\"\"\n\n        result_attoseconds = self.attosecond - other.attosecond\n        result_seconds = self.second - other.second\n\n        # Handle underflow\n        if result_attoseconds < 0:\n            result_seconds -= 1\n            result_attoseconds += 10**18  # 1 second = 10^18 attoseconds\n\n        return Duration(result_seconds, result_attoseconds, self.clock)\n\n    def comparable(self, other: Instant) -> bool:\n        return self.clock.comparable(other.clock)\n\n    def unix_s(self) -> int:\n        \"\"\"Return the time in seconds since the Unix epoch\n        \"\"\"\n        return self.second\n\n    def unix_ms(self) -> int:\n        \"\"\"Return the time in milliseconds since the Unix epoch\n        \"\"\"\n        return self.second * 1000 + self.attosecond // 10**15\n\n    def unix_us(self) -> int:\n        \"\"\"Return the time in microseconds since the Unix epoch\n        \"\"\"\n        return self.second * 1000000 + self.attosecond // 10**12\n\n    def unix_ns(self) -> int:\n        \"\"\"Return the time in nanoseconds since the Unix epoch\n        \"\"\"\n        return self.second * 1000000000 + self.attosecond // 10**9\n\nextension Instant(Ord):\n    def __eq__(self, other):\n        return self.second == other.second and self.attosecond == other.attosecond\n\n    def __lt__(self, other):\n        return self.second < other.second or self.second == other.second and self.attosecond < other.attosecond\n\n\n\nclass Duration(object):\n    \"\"\"Duration represents elapsed time\n\n    Stored using seconds and attoseconds.\n    \"\"\"\n    @property\n    second: int\n    @property\n    attosecond: int\n    @property\n    clock: ?Clock\n\n    def __init__(self, sec: int, asec: int, c: Clock):\n        self.second = sec\n        self.attosecond = asec\n        self.clock = c\n\n    def __str__(self):\n        return self.str_human()\n\n    def __repr__(self):\n        return f\"{self.second}.{self.attosecond:018d}\"\n\n    @staticmethod\n    def from_parts(week: int, day: int, hour: int, minute: int, second: int, attosecond: int, c: Clock) -> Duration:\n        return Duration(\n            week * 7 * 24 * 60 * 60\n            + day * 24 * 60 * 60\n            + hour * 60 * 60\n            + minute * 60\n            + second,\n            attosecond, c)\n\n    def str_human(self) -> str:\n        \"\"\"Return a human readable string representation\n\n        Like: 4w 3d 2h 1m 5s 123ms\n\n        Weeks is the biggest unit as it has a fixed size (7 days). Months vary\n        in length so we cannot convert to months without having absolute point\n        in times to compare with. Years are explicitly not used since they are\n        not exact, a year is usually thought of as 365 days but they're actually\n        365.25 (actually actually 365.2422) so it becomes error prone and less\n        precise.\n        \"\"\"\n        weeks = self.second // (7 * 24 * 60 * 60)\n        days = (self.second % (7 * 24 * 60 * 60)) // (24 * 60 * 60)\n        hours = (self.second % (24 * 60 * 60)) // (60 * 60)\n        minutes = (self.second % (60 * 60)) // 60\n        seconds = self.second % 60\n        return f\"{weeks}w {days}d {hours}h {minutes}m {seconds}s {self.attosecond // 10**9}ns\"\n\n    def str_ms(self):\n        \"\"\"Return a string representation of the duration with milliseconds.\n        \"\"\"\n        return f\"{self.second}.{self.attosecond // 10**15:03d}\"\n\n    def str_us(self):\n        \"\"\"Return a string representation of the duration with microseconds.\n        \"\"\"\n        return f\"{self.second}.{self.attosecond // 10**12:06d}\"\n\n    def str_ns(self):\n        \"\"\"Return a string representation of the duration with nanoseconds.\n        \"\"\"\n        return f\"{self.second}.{self.attosecond // 10**9:09d}\"\n\n    def to_float(self) -> float:\n        return float(self.second) + (float(self.attosecond) / 10**18)\n\n\ndef monotonic() -> Instant:\n    \"\"\"Get monotonic time\n    \"\"\"\n    c = MonotonicClock(0, 0, 0)\n    t = get_monotonic()\n    return Instant(t.0, t.1 * 10**9, c)\n\ndef time() -> Instant:\n    \"\"\"Get real clock time\n    \"\"\"\n    cd = get_clock_data()\n    c = RealtimeClock(cd.status, cd.offset, cd.error)\n    t = get_realtime()\n    return Instant(t.0, t.1 * 10**9, c)\n\ndef now() -> DateTime:\n    \"\"\"Get the current date and time in the local timezone\n    \"\"\"\n    t = time()\n\n    tm = localtime(t.second)\n    tm_year = tm.0\n    tm_month = tm.1\n    tm_day = tm.2\n    tm_hour = tm.3\n    tm_minute = tm.4\n    tm_second = tm.5\n    tm_wday = tm.6\n    tm_yday = tm.7\n    tm_isdst = tm.8\n\n    tz = Timezone(tm.9, tm.10)\n    return DateTime(None, tz, None, None, tm_year, tm_month, tm_day, tm_hour, tm_minute, tm_second, t.attosecond, tm_wday, tm_yday)\n\ndef utcnow() -> DateTime:\n    \"\"\"Get the current date and time in UTC\n    \"\"\"\n    t = time()\n\n    tm = gmtime(t.second)\n    tm_year = tm.0\n    tm_month = tm.1\n    tm_day = tm.2\n    tm_hour = tm.3\n    tm_minute = tm.4\n    tm_second = tm.5\n    tm_wday = tm.6\n    tm_yday = tm.7\n    tm_isdst = tm.8\n\n    tz = Timezone(\"UTC\", 0)\n    return DateTime(None, tz, None, None, tm_year, tm_month, tm_day, tm_hour, tm_minute, tm_second, t.attosecond, tm_wday, tm_yday)\n\n\nclass Stopwatch(object):\n    \"\"\"Stopwatch measures elapsed time\n\n    The watch is started when it is created and the elapsed time can be\n    retrieved using the elapsed() method. The watch can be reset using the\n    reset() method.\n\n    The system's monotonic clock is primarily used but a real clock time\n    measurement is also kept as a fallback.\n\n    Normally the monotonic clock is excellent for measuring elapsed time as it\n    has high precision and is not affected by discontinuous jumps in the system\n    time. However, the start time of the monotonic clock is arbitrary and thus\n    is only comparable to itself on the same machine while that machine is\n    running. Rebooting might reset the monotonic time. Actor migrations might\n    mean that the Stopwatch was started on one machine and later migrated to\n    another at which point comparing to the monotonic start time is no longer\n    valid. In this case we fall back to comparing the real time, which is not as\n    precise but is at least theoretically comparable between machines or after\n    reboots.\n\n    > A man with a watch knows what time it is. A man with two watches is never\n    > sure.\n       -- Segal’s Law\n\n    The precision of the real clock is normally high when compared on the same\n    machine (intra-machine). It is affected by reboots, where it relies on a\n    hardware clock to keep the time, and is affected by discontinuous jumps in\n    the system time (e.g., if the system administrator manually changes the\n    clock), but otherwise it is comparable to the monotonic clock. When compared\n    between different machines (inter-machine) it is entirely up to the\n    precision and accuracy of the synchronization solution. NTP usually achieves\n    a level on the order milliseconds while PTP is on the order of microseconds\n    or tens of microseconds. There is no way to capture the monotonic and real\n    clock time at the same time, so there will be a slight offset between them.\n    We capture the monotonic time first, which is what we use for precise\n    measurements. If we need to fall back to using the real clock, the offset to\n    the monotonic clock is negligible compared to other sources of error.\n\n    Each Instant keeps information about the source clock which is used to\n    produce a result with an estimated precision and error.\n\n    Use PrecisionStopwatch if you need guaranteed precision (but which will fail\n    if that precision is unattainable).\n    \"\"\"\n    def __init__(self):\n        self.start_mono = monotonic()\n        self.start_real = time()\n\n    def elapsed(self) -> Duration:\n        \"\"\"Return the elapsed time since start\n        \"\"\"\n        n = monotonic()\n        if n.comparable(self.start_mono):\n            return n.since(self.start_mono)\n        return time().since(self.start_real)\n\n    def reset(self):\n        self.start_mono = monotonic()\n        self.start_real = time()\n\n\nclass PrecisionStopwatch(object):\n    \"\"\"A precision stopwatch to measure elapsed time using the monotonic clock.\n\n    Similar to Stopwatch but if there is no reliable monotonic clock available,\n    such as after actor migration, PrecisionStopwatch will fail rather than\n    produce lower precision measurements like Stopwatch will.\n\n    The monotonic clock has an arbitrary start time and as such only works\n    reliably on the same machine while that machine is running. Rebooting will\n    reset the monotonic time. Actor migrations might mean that the\n    PrecisionStopwatch was started on one machine and later migrated to another\n    at which point comparing to the monotonic start time is no longer valid. In\n    this case we throw an exception since we can not guarantee the precision of\n    the result.\n\n    Use Stopwatch if you want to be able to always compare the elapsed time,\n    such as after actor resumption or migrations between machines, even when\n    that means that the precision is lower.\n    \"\"\"\n    def __init__(self):\n        self.start = monotonic()\n\n    def elapsed(self) -> Duration:\n        \"\"\"Return the elapsed time since start\n        \"\"\"\n        n = monotonic()\n        if not n.comparable(self.start):\n            raise Exception(\"Monotonic clock not comparable\")\n        return n.since(self.start)\n\n    def reset(self):\n        self.start = monotonic()\n"
  },
  {
    "path": "base/src/time.ext.c",
    "content": "#define GC_THREADS 1\n#include <gc.h>\n\n#ifdef _WIN32\n#else\n#include <sys/timex.h>\n#endif\n#include <uv.h>\n\n#include \"../rts/io.h\"\n#include \"../rts/log.h\"\n\nunsigned long time__incarnation = 0;\n// Clock data\nint time__realclock_status = 0;\n#ifdef _WIN32\n#else\nstruct timex time__realclock_tx = {0};\n#endif\n\n// Reduce UUID to 64 bits. Good enough for our purposes.\nunsigned long time__uuid_to_ulong(const char* uuid) {\n    unsigned long result = 0;\n    unsigned long value;\n    int i;\n\n    for (i = 0; i < 16; i++) {\n        if (i == 8 || i == 13 || i == 18 || i == 23) {\n            if (uuid[i] != '-') {\n                return 0;\n            }\n        } else {\n            value = isdigit(uuid[i]) ? uuid[i] - '0' : toupper(uuid[i]) - 'A' + 10;\n            result = (result << 4) | (value & 0xF);\n        }\n    }\n\n    return result;\n}\n\n\nvoid time__get_clock_data_cb(uv_timer_t *ev) {\n#ifdef __linux__\n    time__realclock_status = adjtimex(&time__realclock_tx);\n#elif defined(_WIN32) // Windows\n    // TODO: implement Windows support?\n    time__realclock_status = 0;\n#else\n    time__realclock_status = ntp_adjtime(&time__realclock_tx);\n#endif\n}\n\nvoid timeQ___ext_init__() {\n    // Monotonic clocks have an arbitrary starting point, so we need to keep\n    // track of which \"incarnation\" of the clock we're using, thus\n    // time__incarnation. We really want to track a boot-id, which is unique to\n    // a particular boot of a particular machine. Linux provides this in the\n    // /proc/sys/kernel/random/boot_id file, but that's not available on all\n    // platforms. Our fallback method is to track the \"boot-id\" of an Acton\n    // node, which we effectively accomplish by just setting time__incarnation\n    // to a random value at startup. As we do this once on startup of an Acton\n    // node, it means we will be able to compare the measurements within the\n    // same Acton node and during that node's lifetime. If the node is\n    // restarted, we will get a new ID and will thus not be able to compare. Nor\n    // are we able to compare between Acton nodes, as it should.\n\n    // Using Linux boot-id as incarnation\n    FILE* boot_id = fopen(\"/proc/sys/kernel/random/boot_id\", \"r\");\n    if (boot_id != NULL) {\n        // Read the contents of the file.\n        char buf[64];\n        size_t nread = fread(buf, 1, sizeof(buf), boot_id);\n        if (nread > 0) {\n            // Convert the contents to an integer.\n            time__incarnation = time__uuid_to_ulong(buf);\n            log_debug(\"Using Linux boot-id for clock incarnation id: %lu\", time__incarnation);\n        }\n        fclose(boot_id);\n    }\n\n    // Fallback to random incarnation ID.\n    if (time__incarnation == 0) {\n        // We failed to read the boot ID or don't have one on this platform, so\n        // we just use a random value.\n        time__incarnation = rand();\n        log_debug(\"Using random value for clock incarnation id: %lu\", time__incarnation);\n    }\n\n    // Schedule background work to get clock data. Fetching this data using\n    // ntp_adjtime is considerably slower than a simple clock_gettime call, so\n    // we do it in the background. Once every 10 seconds should be enough.\n    // To get an idea, benching on my machine ntp_adjtime is about 50x slower:\n    //   ntp_adjtime time per call: 586.459146 ns\n    //   ntp_adjtime operations per second: 1705148.614052\n    //   clock_gettime time per call: 17.545191 ns\n    //   clock_gettime operations per second: 56995674.769229\n    // We don't want to slow down our programs like that, getting the time\n    // should be cheap, which is why we do this somewhat elaborate dance.\n    uv_timer_t *time__get_clock_data_ev = acton_malloc(sizeof(uv_timer_t));\n    uv_timer_init(aux_uv_loop, time__get_clock_data_ev);\n    uv_timer_start(time__get_clock_data_ev, time__get_clock_data_cb, 10000, 10000);\n    time__get_clock_data_cb(NULL);\n}\n\nint64_t timeQ_U__get_incarnation () {\n    return time__incarnation;\n}\n\n\nB_tuple timeQ_get_monotonic () {\n    uv_timespec64_t ts;\n    if (uv_clock_gettime(UV_CLOCK_MONOTONIC, &ts) == -1) {\n        char errmsg[1024] = \"Error getting time: \";\n        uv_strerror_r(errno, errmsg + strlen(errmsg), sizeof(errmsg) - strlen(errmsg));\n        log_warn(\"%s\", errmsg);\n        $RAISE(((B_BaseException)B_RuntimeErrorG_new(to$str(errmsg))));\n    }\n    return $NEWTUPLE(2,\n                     toB_int(ts.tv_sec),\n                     toB_int(ts.tv_nsec));\n}\n\nB_tuple timeQ_get_realtime () {\n    uv_timespec64_t ts;\n    if (uv_clock_gettime(UV_CLOCK_REALTIME, &ts) == -1) {\n        char errmsg[1024] = \"Error getting time: \";\n        uv_strerror_r(errno, errmsg + strlen(errmsg), sizeof(errmsg) - strlen(errmsg));\n        log_warn(\"%s\", errmsg);\n        $RAISE(((B_BaseException)B_RuntimeErrorG_new(to$str(errmsg))));\n    }\n    return $NEWTUPLE(2,\n                     toB_int(ts.tv_sec),\n                     toB_int(ts.tv_nsec));\n}\n\n\nB_tuple timeQ_get_clock_data () {\n#ifdef _WIN32\n    return $NEWTUPLE(3,\n                     toB_int(time__realclock_status),\n                     toB_int(0),\n                     toB_int(0));\n#else\n    return $NEWTUPLE(3,\n                     toB_int(time__realclock_status),\n                     toB_int(time__realclock_tx.offset),\n                     toB_int(time__realclock_tx.esterror));\n#endif\n}\n\nB_tuple timeQ_U_1localtime (int64_t seconds) {\n    time_t t = seconds;\n    struct tm tm;\n#ifdef _WIN32\n    errno_t result = localtime_s(&tm, &t);\n    if (result != 0) {\n        char errmsg[1024] = \"Error getting time: \";\n        uv_strerror_r(errno, errmsg + strlen(errmsg), sizeof(errmsg) - strlen(errmsg));\n        log_warn(\"%s\", errmsg);\n        $RAISE(((B_BaseException)B_RuntimeErrorG_new(to$str(errmsg))));\n    }\n    return $NEWTUPLE(11,\n                     toB_int(tm.tm_year + 1900),\n                     toB_int(tm.tm_mon + 1),\n                     toB_int(tm.tm_mday),\n                     toB_int(tm.tm_hour),\n                     toB_int(tm.tm_min),\n                     toB_int(tm.tm_sec),\n                     toB_int(tm.tm_wday),\n                     toB_int(tm.tm_yday),\n                     toB_int(tm.tm_isdst),\n                     to$str(\"\"),\n                     toB_int(0));\n#else\n    localtime_r(&t, &tm);\n    return $NEWTUPLE(11,\n                     toB_int(tm.tm_year + 1900),\n                     toB_int(tm.tm_mon + 1),\n                     toB_int(tm.tm_mday),\n                     toB_int(tm.tm_hour),\n                     toB_int(tm.tm_min),\n                     toB_int(tm.tm_sec),\n                     toB_int(tm.tm_wday),\n                     toB_int(tm.tm_yday),\n                     toB_int(tm.tm_isdst),\n                     to$str(tm.tm_zone),\n                     toB_int(tm.tm_gmtoff));\n#endif\n}\n\nB_tuple timeQ_U_3gmtime (int64_t seconds) {\n    time_t t = seconds;\n    struct tm tm;\n#ifdef _WIN32\n    // TODO: implement this!\n    return $NEWTUPLE(9,\n                     toB_int(0),\n                     toB_int(0),\n                     toB_int(0),\n                     toB_int(0),\n                     toB_int(0),\n                     toB_int(0),\n                     toB_int(0),\n                     toB_int(0),\n                     toB_int(0));\n#else\n    gmtime_r(&t, &tm);\n    return $NEWTUPLE(9,\n                     toB_int(tm.tm_year + 1900),\n                     toB_int(tm.tm_mon + 1),\n                     toB_int(tm.tm_mday),\n                     toB_int(tm.tm_hour),\n                     toB_int(tm.tm_min),\n                     toB_int(tm.tm_sec),\n                     toB_int(tm.tm_wday),\n                     toB_int(tm.tm_yday),\n                     toB_int(tm.tm_isdst));\n#endif\n}\n"
  },
  {
    "path": "base/src/uri.act",
    "content": "\n_UNRESERVED = \"abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789-._~\"\n_HEX_DIGITS = \"0123456789ABCDEF\"\n\n\ndef quote(text: str, safe: str=\"/\") -> str:\n    \"\"\"Percent-encode a string for use in a URI.\n\n    Unreserved characters defined by RFC 3986 are preserved. Characters in\n    the safe set are also preserved when they are ASCII bytes.\n    \"\"\"\n    allowed = set(_UNRESERVED + safe)\n    encoded = text.encode()\n    parts: list[str] = []\n\n    for i in range(len(encoded)):\n        byte = encoded[i]\n        if byte < 128 and chr(byte) in allowed:\n            parts.append(chr(byte))\n        else:\n            parts.append(_quote_byte(byte))\n\n    return \"\".join(parts)\n\n\ndef unquote(text: str) -> str:\n    \"\"\"Decode percent-escaped bytes in a URI string as UTF-8.\"\"\"\n    result = bytearray(b\"\")\n    i = 0\n\n    while i < len(text):\n        if text[i] != \"%\":\n            _append_bytes(result, text[i].encode())\n            i += 1\n            continue\n\n        if i + 2 >= len(text):\n            raise ValueError(\"Incomplete percent escape: {text[i:]}\")\n\n        escape = text[i:i+3]\n        hi = _hex_value(text[i+1])\n        lo = _hex_value(text[i+2])\n        result.append(hi * 16 + lo)\n        i += 3\n\n    try:\n        return result.decode()\n    except ValueError:\n        raise ValueError(\"Invalid UTF-8 in percent-escaped text\")\n\n\ndef _append_bytes(result: bytearray, data: bytes) -> None:\n    for i in range(len(data)):\n        result.append(data[i])\n\n\ndef _quote_byte(byte: int) -> str:\n    return \"%\" + _HEX_DIGITS[byte // 16] + _HEX_DIGITS[byte % 16]\n\n\ndef _hex_value(char: str) -> int:\n    idx = _HEX_DIGITS.find(char.upper())\n    if idx == -1:\n        raise ValueError(\"Invalid percent escape: %%{char}\")\n    return idx\n\n\nclass URI(object):\n    \"\"\"A class representing a Uniform Resource Identifier (URI).\n\n    Implements parsing according to RFC 1630.\n\n    Attributes:\n        scheme (str): The URI scheme (e.g. 'http', 'https', 'file')\n        authority (str | None): The authority component (e.g. 'example.com:8080')\n        host (str | None): The hostname part of the authority\n        port (int | None): The port number if specified\n        path (str | None): The path component\n        query (str | None): The query string if present\n        fragment (str | None): The fragment identifier if present\n    \"\"\"\n    scheme: ?str\n    authority: ?str\n    host: ?str\n    port: ?int\n    path: ?str\n    query: ?str\n    fragment: ?str\n\n    def __init__(self, uri_string: str):\n        \"\"\"Parse a URI string into its components.\n\n        Args:\n            uri_string: The URI string to parse\n\n        Raises:\n            ValueError: If the URI string is invalid\n        \"\"\"\n        # Parse scheme\n        scheme, remainder = parse_schema(uri_string)\n        self.scheme = scheme\n\n        # Parse authority\n        authority, host, port, remainder = parse_authority(remainder)\n        self.authority = authority\n        self.host = host\n        self.port = port\n\n        # Parse path\n        path, remainder = parse_path(remainder)\n        self.path = path\n\n        # Parse query\n        query, remainder = parse_query(remainder)\n        self.query = query\n\n        # Parse fragment\n        self.fragment = parse_fragment(remainder)\n\n    def __str__(self) -> str:\n        \"\"\"Return the canonical string representation of the URI.\"\"\"\n        scheme_sep = \"://\" if self.scheme is not None else \"\"\n        query_sep = \"?\" if self.query is not None else \"\"\n        frag_sep = \"#\" if self.fragment is not None else \"\"\n        return (e_str(self.scheme) +\n                scheme_sep +\n                e_str(self.authority) +\n                e_str(self.path) +\n                query_sep +\n                e_str(self.query) +\n                frag_sep +\n                e_str(self.fragment))\n\n    def __repr__(self) -> str:\n        \"\"\"Return a detailed string representation for debugging.\"\"\"\n        return f\"URI(scheme='{self.scheme}', authority='{self.authority}', host='{self.host}', port={self.port}, path='{self.path}', query='{self.query}', fragment='{self.fragment}')\"\n\n\ndef e_str[T](s: ?T) -> str:\n    return str(s) if s is not None else \"\"\n\ndef opt_str[T](s: ?T) -> str:\n    return str(s) if s is not None else \"None\"\n\ndef is_valid_scheme(scheme: str) -> bool:\n    \"\"\"\n    Validate if a scheme string follows RFC 3986 rules:\n    1. Must begin with a letter\n    2. Can contain letters, digits, plus (+), period (.), or hyphen (-)\n    3. Case-insensitive\n\n    Args:\n        scheme: The scheme string to validate\n\n    Returns:\n        bool: True if scheme is valid, False otherwise\n    \"\"\"\n    if not scheme or not scheme[0].isalpha():\n        return False\n\n    # Check each character is valid\n    valid_chars = set('abcdefghijklmnopqrstuvwxyz'\n                     'ABCDEFGHIJKLMNOPQRSTUVWXYZ'\n                     '0123456789'\n                     '+.-')\n\n    return all(map(lambda c: c in valid_chars, scheme))\n\n\ndef parse_schema(uri: str) -> (?str, str):\n    if \":\" not in uri:\n        return None, uri\n    split_result = uri.split(\":\", 1)\n    if len(split_result) == 1:\n        return None, split_result[0]\n    elif len(split_result) == 2:\n        scheme = split_result[0]\n        remainder = split_result[1]\n        if not remainder.startswith(\"//\"):\n            raise ValueError(\"Invalid separator after scheme\")\n        if not is_valid_scheme(scheme):\n            raise ValueError(\"Invalid scheme\")\n        return scheme, remainder[2:]\n    raise ValueError(\"Invalid URI, unable to parse scheme\")\n\n\ndef parse_authority(uri: str) -> (?str, ?str, ?int, str):\n    \"\"\"Parse authority component, returning authority, host, port, and remainder.\"\"\"\n    if uri == \"\":\n        return None, None, None, \"\"\n\n    # Find end of authority component\n    slash_idx = uri.find(\"/\")\n    question_idx = uri.find(\"?\")\n    hash_idx = uri.find(\"#\")\n\n    # Find the first occurring delimiter\n    end_idx = -1\n    if slash_idx != -1:\n        end_idx = slash_idx\n    if question_idx != -1 and (end_idx == -1 or question_idx < end_idx):\n        end_idx = question_idx\n    if hash_idx != -1 and (end_idx == -1 or hash_idx < end_idx):\n        end_idx = hash_idx\n\n    # Extract authority and remainder\n    if end_idx == -1:\n        authority = uri\n        remainder = \"\"\n    else:\n        authority = uri[:end_idx]\n        remainder = uri[end_idx:]\n\n    if not authority:\n        return None, None, None, remainder\n\n    # Parse host and port\n    if \":\" in authority:\n        host_part = authority.split(\":\", 1)\n        try:\n            port = int(host_part[1])\n            if port < 0 or port > 65535:\n                raise ValueError(f\"Port must be between 0 and 65535: {host_part[1]}\")\n            return authority, host_part[0], port, remainder\n        except ValueError:\n            raise ValueError(f\"Invalid port: {host_part[1]}\")\n    else:\n        return authority, authority, None, remainder\n\ndef parse_path(uri: str) -> (?str, str):\n    \"\"\"Parse path component, returning path and remainder.\"\"\"\n    if not uri:\n        return None, \"\"\n\n    if uri[0] != \"/\":\n        uri = \"/\" + uri\n\n    question_idx = uri.find(\"?\")\n    hash_idx = uri.find(\"#\")\n\n    if question_idx != -1 and (hash_idx == -1 or question_idx < hash_idx):\n        return uri[:question_idx], uri[question_idx:]\n    elif hash_idx != -1:\n        return uri[:hash_idx], uri[hash_idx:]\n    else:\n        return uri, \"\"\n\ndef parse_query(uri: str) -> (?str, str):\n    \"\"\"Parse query component, returning query and remainder.\"\"\"\n    if not uri or uri[0] != \"?\":\n        return None, uri\n\n    hash_idx = uri.find(\"#\")\n    if hash_idx != -1:\n        query = uri[1:hash_idx]\n        return \"\" if not query else query, uri[hash_idx:]\n    else:\n        query = uri[1:]\n        return \"\" if not query else query, \"\"\n\ndef parse_fragment(uri: str) -> ?str:\n    \"\"\"Parse fragment component.\"\"\"\n    if not uri or uri[0] != \"#\":\n        return None\n    return \"\" if len(uri) == 1 else uri[1:]\n"
  },
  {
    "path": "base/src/xml.act",
    "content": "class Node():\n    \"\"\"\nA node is an abstract syntax tree for XML.\n\nIt is similar to Python's xml.etree.ElementTree.Element.\nA node always represent an XML tagged element; so also the children are elements.\nText is represented in the attributes text and tail: in node n,\n - n.text is the string before n's first child;\n - n.tail is the string before n's next sibling.\nSo, to get the text at top level of node n, one must concatenate\nn.text and c.tail for all children of n.\n\"\"\"\n    def __init__(self, tag: str, nsdefs: list[(?str,str)]=[], prefix: ?str=None,\n                 attributes: list[(str, str)]=[], children: list[Node]=[], text: ?str=None, tail: ?str=None):\n        self.tag = tag\n        self.nsdefs = nsdefs\n        self.prefix = prefix\n        self.attributes = attributes\n        self.children = children\n        self.text = text\n        self.tail = tail\n\n    def encode(self, pretty=False) -> str:\n        NotImplemented\n\nclass XmlParseError(ValueError):\n    \"\"\"Exception raised for XML parsing errors\n\n    Attributes:\n        line: The line number where the error occurred (if available)\n        column: The column number where the error occurred (if available)\n    \"\"\"\n    line: ?int\n    column: ?int\n\n    def __init__(self, msg: ?str, line: ?int=None, column: ?int=None):\n        self.error_message = msg if msg is not None else \"\"\n        self.line = line\n        self.column = column\n\n    def __str__(self):\n        context = \"\"\n        if self.line is not None:\n            context += \":{self.line}\"\n        if self.column is not None:\n            context += \":{self.column}\"\n        return \"{self._name()}{context}: {self.error_message}\"\n\n    def __repr__(self):\n        return \"{self._name()}({repr(self.error_message)}, {repr(self.line)}, {repr(self.column)})\"\n\ndef decode(data : str) -> Node:\n    NotImplemented\n\ndef encode(node: Node, pretty=False) -> str:\n    return node.encode(pretty)\n\ndef toplevel_text(node):\n     \"\"\"Returns the toplevel text in node, as if all subelements were replaced by sep\"\"\"\n     sep = ' '\n     chunks = []\n     txt = node.text\n     if txt is not None:\n         chunks.append(txt)\n     for c in node.children:\n         tl = c.tail\n         if tl is not None:\n             chunks.append(tl)\n     return sep.join(chunks)\n\ndef encode_nodes(nodes: list[Node], pretty=False) -> str:\n    sep = \"\\n\" if pretty else \"\"\n    return sep.join([node.encode(pretty) for node in nodes])\n"
  },
  {
    "path": "base/src/xml.ext.c",
    "content": "#define LIBXML_STATIC\n#include <libxml/xmlmemory.h>\n#include <libxml/parser.h>\n\n// TODO: The macro below is from builtin/str.c. We should not duplicate it...\n#define NEW_UNFILLED_STR(nm, nchrs, nbtes)      \\\n    assert(nbtes >= nchrs);                     \\\n    nm = acton_malloc(sizeof(struct B_str));           \\\n    (nm)->$class = &B_strG_methods;               \\\n    (nm)->nchars = nchrs;                       \\\n    (nm)->nbytes = nbtes;                       \\\n    (nm)->str = acton_malloc_atomic((nm)->nbytes + 1);       \\\n    (nm)->str[(nm)->nbytes] = 0\n\n// Helper function to count extra bytes needed for XML escaping\n// Returns the number of extra bytes needed to replace the special character\n// with encoded entity (not total bytes)\n//\nstatic int count_xml_escape_extra(B_str str, int escape_quotes) {\n    int extra = 0;\n    // Note: It's safe to iterate byte-by-byte even for UTF-8 strings because we\n    // only check for ASCII characters (&, <, \"). The codepoints for ASCII\n    // characters are backwards compatible (0x00-0x7F -> 00000000-01111111).\n    // Continuation bytes (2nd, ...) in multi-byte UTF-8 characters always have\n    // the same pattern 10xxxxxx (0x80-0xBF) so no UTF-8 continuation byte can\n    // be mistaken for an ASCII character.\n    for (int i = 0; i < str->nbytes; i++) {\n        switch (str->str[i]) {\n            case '&': extra += 4; break;  // &amp; = 5 bytes instead of 1\n            case '<': extra += 3; break;  // &lt; = 4 bytes instead of 1\n            case '\"':\n                if (escape_quotes) extra += 5;  // &quot; = 6 bytes instead of 1\n                break;\n        }\n    }\n    return extra;\n}\n\n// Helper function to copy string with XML escaping\n// Returns pointer to position after copied data\nstatic unsigned char* copy_with_xml_escape(unsigned char *dst, B_str src, int escape_quotes) {\n    for (int i = 0; i < src->nbytes; i++) {\n        // Note: It's safe to iterate byte-for-byte here because we're only\n        // inserting ASCII and copying (maybe UTF-8 multi-byte) characters as\n        // individual bytes, iterating over the total byte length of B_str\n        switch (src->str[i]) {\n            case '&':\n                memcpy(dst, \"&amp;\", 5);\n                dst += 5;\n                break;\n            case '<':\n                memcpy(dst, \"&lt;\", 4);\n                dst += 4;\n                break;\n            case '\"':\n                if (escape_quotes) {\n                    memcpy(dst, \"&quot;\", 6);\n                    dst += 6;\n                } else {\n                    *dst++ = src->str[i];\n                }\n                break;\n            default:\n                *dst++ = src->str[i];\n                break;\n        }\n    }\n    return dst;\n}\n\n// Helper function to collect text from consecutive TEXT and CDATA nodes\n// Returns the combined string and updates the node pointer to the first non-text node\n// Note: cur_ptr is passed by reference (pointer to pointer) so we can update the caller's pointer\n//       to skip past all consumed text/CDATA nodes\nstatic B_str collect_text_cdata_nodes(xmlNodePtr *cur_ptr) {\n    xmlNodePtr cur = *cur_ptr;\n    if (!cur || (cur->type != XML_TEXT_NODE && cur->type != XML_CDATA_SECTION_NODE)) {\n        return NULL;\n    }\n\n    // Count total length of combined text and CDATA nodes\n    size_t text_len = 0;\n    xmlNodePtr text_start = cur;\n    while (cur && (cur->type == XML_TEXT_NODE || cur->type == XML_CDATA_SECTION_NODE)) {\n        if (cur->content) text_len += strlen((char *)cur->content);\n        cur = cur->next;\n    }\n\n    // Create combined string\n    if (text_len > 0) {\n        char *combined = acton_malloc_atomic(text_len + 1);\n        char *p = combined;\n        xmlNodePtr t = text_start;\n        while (t != cur) {\n            if (t->content) {\n                size_t len = strlen((char *)t->content);\n                memcpy(p, t->content, len);\n                p += len;\n            }\n            t = t->next;\n        }\n        *p = '\\0';\n        B_str result = to_str_noc(combined);\n        *cur_ptr = cur;\n        return result;\n    }\n\n    *cur_ptr = cur;\n    return NULL;\n}\n\nxmlQ_Node $NodePtr2Node(xmlNodePtr node) {\n    B_SequenceD_list wit = B_SequenceD_listG_witness;\n    if (node->type == XML_COMMENT_NODE) {\n        return NULL;\n    }\n    if (node->type != XML_ELEMENT_NODE) {\n        char *errmsg = NULL;\n        RAISE(xmlQ_XmlParseError, $FORMAT(\"Unexpected nodetype %d, content is %s\", node->type, node->content), NULL, NULL);\n    }\n\n    B_list nsdefs = B_listG_new(NULL, NULL);\n    xmlNsPtr nsDef = node->nsDef;\n    while (nsDef) {\n        B_str prefix = NULL;\n        if (nsDef->prefix) prefix = to$str((char *)nsDef->prefix);\n        B_str href = to$str((char *)nsDef->href);\n        wit->$class->append(wit,nsdefs, $NEWTUPLE(2, prefix, href));\n        nsDef=nsDef->next;\n    }\n\n    B_str prefix = NULL;\n    if (node->ns && node->ns->prefix)\n        prefix = to$str((char *)node->ns->prefix);\n\n    B_list attributes = B_listG_new(NULL, NULL);\n    xmlAttrPtr attr = node->properties;\n    while (attr) {\n        B_str attr_name;\n        // libxml2 handles namespace prefixes in two ways:\n        // 1. Defined namespaces: attr->ns is set, attr->name has local name only\n        //    e.g., xmlns:ns=\"http://foo\" ns:op=\"x\" -> attr->ns->prefix=\"ns\", attr->name=\"op\"\n        // 2. Undefined namespaces: attr->ns is NULL, attr->name contains the full prefixed name\n        //    e.g., ns:op=\"x\" (no xmlns:ns) -> attr->ns=NULL, attr->name=\"ns:op\"\n        if (attr->ns && attr->ns->prefix) {\n            // Reconstruct prefixed name for defined namespace\n            attr_name = $FORMAT(\"%s:%s\", attr->ns->prefix, attr->name);\n        } else {\n            // Use name as-is (either unprefixed or undefined prefix already in name)\n            attr_name = to$str((char *)attr->name);\n        }\n        wit->$class->append(wit,attributes, $NEWTUPLE(2, attr_name, to$str((char *)xmlGetProp(node, attr->name))));\n        attr = attr->next;\n    }\n\n    B_list children = B_listG_new(NULL, NULL);\n    xmlNodePtr cur = node->xmlChildrenNode;\n\n    // Collect initial text/CDATA nodes\n    B_str text = collect_text_cdata_nodes(&cur);\n\n    while (cur != NULL) {\n        xmlQ_Node child = $NodePtr2Node(cur);\n        if (child)\n            wit->$class->append(wit,children, child);\n        cur = cur->next;\n    }\n\n    // Collect tail text/CDATA nodes after we have exhausted the child nodes\n    cur = node->next;\n    B_str tail = collect_text_cdata_nodes(&cur);\n    // Update the tree structure to skip consumed tail text/CDATA nodes.\n    // This prevents the parent from seeing these text nodes again during its\n    // child iteration, since tail text of an element is part of the parent's\n    // child list in the XML tree.\n    node->next = cur;\n    return (xmlQ_Node)$NEW(xmlQ_Node, to$str((char *)node->name), nsdefs, prefix, attributes, children, text, tail);\n}\n\nxmlQ_Node xmlQ_decode(B_str data) {\n    // With XML_PARSE_NOERROR we suppress printing error and warning reports to stderr\n    xmlDocPtr doc = xmlReadMemory((char *)data->str, data->nbytes, NULL, NULL, XML_PARSE_NOERROR);\n    if (!doc) {\n        xmlErrorPtr err = xmlGetLastError();\n        B_str errmsg;\n        B_int line = NULL;\n        B_int column = NULL;\n\n        if (err && err->message) {\n            if (err->line > 0) {\n                line = toB_int(err->line);\n            }\n            if (err->int2 > 0) {  // int2 contains the column in libxml2\n                column = toB_int(err->int2);\n            }\n\n            // Strip trailing whitespace from error message if needed\n            int orig_len = strlen(err->message);\n            int len = orig_len;\n            while (len > 0 && isspace((unsigned char)err->message[len-1])) {\n                len--;\n            }\n\n            if (len < orig_len) {\n                // Only copy if we actually stripped something\n                char msg_clean[len + 1];\n                strncpy(msg_clean, err->message, len);\n                msg_clean[len] = '\\0';\n                errmsg = to$str(msg_clean);\n            } else {\n                // Use original message as-is\n                errmsg = to$str(err->message);\n            }\n        } else {\n            errmsg = to$str(\"XML parse error\");\n        }\n        RAISE(xmlQ_XmlParseError, errmsg, line, column);\n    }\n    xmlNodePtr root = xmlDocGetRootElement(doc);\n    xmlQ_Node t = $NodePtr2Node(root);\n    xmlFreeDoc(doc);\n    return t;\n}\n\n\nstatic B_str xmlQ_encode_nsdefs(B_list nsdefs);\nstatic B_str xmlQ_encode_attrs(B_list attrs);\n\n\nB_str xmlQ_node2str(xmlQ_Node node, bool pretty, int depth) {\n    B_str nsdefs = xmlQ_encode_nsdefs(node->nsdefs);\n    B_str attrs = xmlQ_encode_attrs(node->attributes);\n\n    // Is this an empty element (no text, no children), then use self-closing tag\n    bool is_empty = !node->text && node->children->length == 0;\n\n\n    // Encode the child nodes to a single string (pretty-printed)\n    bool has_children = node->children->length > 0;\n    B_str nul = to$str(\"\");\n    B_str children_str;\n\n    if (has_children) {\n        B_list children = B_listD_new(node->children->length);\n        children->length = node->children->length;\n        for (int i = 0; i < node->children->length; i++) {\n            xmlQ_Node ch = (xmlQ_Node)node->children->data[i];\n            children->data[i] = xmlQ_node2str(ch, pretty, depth + 1);\n        }\n\n        if (pretty) {\n            // Join with newlines\n            B_str separator = to$str(\"\\n\");\n            children_str = separator->$class->join(separator, B_SequenceD_listG_witness->W_Collection, children);\n        } else {\n            // Join with empty string\n            children_str = nul->$class->join(nul, B_SequenceD_listG_witness->W_Collection, children);\n        }\n    } else {\n      children_str = nul;\n    }\n\n    // Calculate extra bytes needed for escaping text and tail\n    int text_extra = node->text ? count_xml_escape_extra(node->text, 0) : 0;\n    int tail_extra = node->tail ? count_xml_escape_extra(node->tail, 0) : 0;\n\n    int indent_size = pretty ? depth * 2 : 0;\n\n    // Calculate total size\n    int res_bytes = indent_size +\n                    (is_empty ? 1 : 2) * (node->tag->nbytes + (node->prefix ? node->prefix->nbytes + 1 : 0)) +\n                    nsdefs->nbytes + attrs->nbytes +\n                    (is_empty ? 0 : (node->text ? node->text->nbytes + text_extra : 0)) +\n                    (is_empty ? 0 : (has_children && pretty ? 1 : 0)) + // newline before children\n                    (is_empty ? 0 : children_str->nbytes) +\n                    (is_empty ? 0 : (has_children && pretty ? 1 + indent_size : 0)) + // newline + indent before closing\n                    (node->tail ? node->tail->nbytes + tail_extra : 0) +\n                    (is_empty ? 3 : 5); // self-closing tag - 3 bytes (< / >); open+close tag - 5 bytes (< > < / >)\n\n    int res_chars = indent_size +\n                    (is_empty ? 1 : 2) * (node->tag->nchars + (node->prefix ? node->prefix->nchars + 1 : 0)) +\n                    nsdefs->nchars + attrs->nchars +\n                    (is_empty ? 0 : (node->text ? node->text->nchars + text_extra : 0)) +\n                    (is_empty ? 0 : (has_children && pretty ? 1 : 0)) +\n                    (is_empty ? 0 : children_str->nchars) +\n                    (is_empty ? 0 : (has_children && pretty ? 1 + indent_size : 0)) +\n                    (node->tail ? node->tail->nchars + tail_extra : 0) +\n                    (is_empty ? 3 : 5);\n\n    // Build the result string\n    B_str res;\n    NEW_UNFILLED_STR(res, res_chars, res_bytes);\n    unsigned char *p = res->str;\n\n    // Write initial indentation\n    for (int i = 0; i < indent_size; i++) {\n        *p++ = ' ';\n    }\n\n    // Write opening tag\n    *p++ = '<';\n    if (node->prefix) {\n        memcpy(p, node->prefix->str, node->prefix->nbytes);\n        p += node->prefix->nbytes;\n        *p++ = ':';\n    }\n    memcpy(p, node->tag->str, node->tag->nbytes);\n    p += node->tag->nbytes;\n    memcpy(p, nsdefs->str, nsdefs->nbytes);\n    p += nsdefs->nbytes;\n    memcpy(p, attrs->str, attrs->nbytes);\n    p += attrs->nbytes;\n\n    // Write self-closing tag or children followed by explicit close tag\n    if (is_empty) {\n        *p++ = '/';\n        *p++ = '>';\n    } else {\n        *p++ = '>';\n\n        // Write text content\n        if (node->text) {\n            p = copy_with_xml_escape(p, node->text, 0);\n        }\n\n        if (has_children) {\n            // Write newline after opening tag, write children\n            if (pretty) {\n                *p++ = '\\n';\n            }\n            memcpy(p, children_str->str, children_str->nbytes);\n            p += children_str->nbytes;\n\n            // Write newline and indent before closing tag if needed\n            if (pretty) {\n                *p++ = '\\n';\n                for (int i = 0; i < indent_size; i++) {\n                    *p++ = ' ';\n                }\n            }\n        }\n\n        // Write closing tag\n        *p++ = '<';\n        *p++ = '/';\n        if (node->prefix) {\n            memcpy(p, node->prefix->str, node->prefix->nbytes);\n            p += node->prefix->nbytes;\n            *p++ = ':';\n        }\n        memcpy(p, node->tag->str, node->tag->nbytes);\n        p += node->tag->nbytes;\n        *p++ = '>';\n    }\n\n    // Write tail\n    if (node->tail) {\n        p = copy_with_xml_escape(p, node->tail, 0);\n    }\n\n    return res;\n}\n\nstatic B_str xmlQ_encode_nsdefs(B_list nsdefs) {\n    int res_bytes = 0;\n    int res_chars = 0;\n    for (int i=0; i<nsdefs->length;i++) {\n        B_tuple nsdef = nsdefs->data[i];\n        B_str prefix = (B_str)nsdef->components[0];\n        B_str href = (B_str)nsdef->components[1];\n\n        // Count extra bytes needed for escaping href\n        int href_extra = count_xml_escape_extra(href, 1);\n\n        res_bytes += (prefix ? prefix->nbytes+1 : 0) + href->nbytes + href_extra + 9; // 9 = len(\" xmlns\" + \"=\" + '\"' + '\"')\n        res_chars += (prefix ? prefix->nchars+1 : 0) + href->nchars + href_extra + 9;\n    }\n    B_str res;\n    NEW_UNFILLED_STR(res, res_chars, res_bytes);\n    unsigned char *p = res->str;\n    for (int i=0; i<nsdefs->length; i++) {\n        B_tuple nsdef = nsdefs->data[i];\n        *p++ = ' ';\n        B_str prefix = (B_str)nsdef->components[0];\n        B_str href = (B_str)nsdef->components[1];\n        char * xmlns = \"xmlns\";\n        memcpy(p, xmlns, 5); p += 5;\n        if (prefix) {\n            *p++ = ':';\n            memcpy(p, prefix->str, prefix->nbytes); p += prefix->nbytes;\n        }\n        *p++ = '=';\n        *p++ = '\"';\n        p = copy_with_xml_escape(p, href, 1);\n        *p++ = '\"';\n    }\n    return res;\n}\n\n\nstatic B_str xmlQ_encode_attrs(B_list attrs) {\n    int res_bytes = 0;\n    int res_chars = 0;\n    for (int i=0; i < attrs->length; i++) {\n        B_tuple attr = attrs->data[i];\n        B_str key = (B_str)attr->components[0];\n        B_str value = (B_str)attr->components[1];\n\n        // Count extra bytes needed for escaping\n        int extra_bytes = count_xml_escape_extra(value, 1);\n\n        res_bytes += key->nbytes + value->nbytes + extra_bytes + 4; // 4 = len(\" \" + \"=\" + \"'\" + \"'\")\n        res_chars += key->nchars + value->nchars + extra_bytes + 4;\n    }\n    B_str res;\n    NEW_UNFILLED_STR(res, res_chars, res_bytes);\n\n    unsigned char *p = res->str;\n    for (int i=0; i < attrs->length; i++) {\n        B_tuple attr = attrs->data[i];\n        B_str key = (B_str)attr->components[0];\n        B_str value = (B_str)attr->components[1];\n        *p++ = ' ';\n        memcpy(p, key->str, key->nbytes); p += key->nbytes;\n        *p++ = '=';\n        *p++ = '\"';\n        p = copy_with_xml_escape(p, value, 1);\n        *p++ = '\"';\n    }\n    return res;\n}\n\nB_str xmlQ_NodeD_encode(xmlQ_Node self, B_bool pretty) {\n    // Use the internal function with depth 0 for the root node\n    return xmlQ_node2str(self, pretty ? pretty->val != 0 : false, 0);\n}\n\nvoid xmlQ___ext_init__() {\n    // NOP\n}\n"
  },
  {
    "path": "bin/runacton",
    "content": "#!/bin/sh\n# runacton, through use of a shebang line, allows execution of Acton source\n# files a la \"shell script\" style. Start your .act source code file with:\n#\n#   #!/usr/bin/env runacton\n#\n# And you can execute it directly! Under the hood the .act source file is\n# compiled by acton into a binary which is then executed. The original\n# arguments are passed through.\n\nset -e\n\nif [ $# -lt 1 ]; then\n  echo \"runacton: missing .act file path (runacton is meant to be invoked via shebang)\" >&2\n  exit 2\nfi\n\nscript=\"$1\"\nACTON_RUNACTON=1 acton --quiet \"$script\"\nEXEC=\"${script%.act}\"\nshift\nexec \"$EXEC\" \"$@\"\n"
  },
  {
    "path": "compiler/.gitignore",
    "content": "acton.cabal\n"
  },
  {
    "path": "compiler/CLAUDE.md",
    "content": "# Acton Compiler - Development Guide\n\nThe Acton compiler (`acton`) is written in Haskell and compiled Acton source code into C code that can be compiled and linked with the runtime system.\n\n## Quick Reference\n\n### Build & Test\n```bash\n# Build just the compiler (fastest iteration)\nmake dist/bin/acton\n\n# Run compiler tests\nmake test-compiler\n\n# Run specific test suite\ncd compiler && stack test --test-arguments \"--filter pattern\"\n\n# Build with profiling\ncd compiler && stack build --profile\n```\n\n### Key Directories\n```\ncompiler/\n├── lib/                    # Main compiler library\n│   ├── src/Acton/         # Core compiler modules\n│   └── test/              # Compiler unit tests\n├── acton/                 # Compiler executable\n│   ├── Main.hs           # Entry point\n│   └── test/             # Snapshot tests\n└── lsp-server/           # Language server\n```\n\n## Compilation Pipeline\n\nThe compiler transforms Acton code through multiple stages:\n\n```\nSource Code (.act)\n    ↓ Parser\nAST (Abstract Syntax Tree)\n    ↓ Type Checker\nTyped AST\n    ↓ Normalizer\nNormalized AST\n    ↓ Deactorizer\nDeactorized AST\n    ↓ CPS Transform\nCPS Form\n    ↓ Lambda Lifter\nLifted Form\n    ↓ Boxing\nBoxed Form\n    ↓ Code Generator\nC Code (.c, .h)\n```\n\n## Key Modules\n\n### Core Pipeline (`compiler/lib/src/Acton/`)\n\n#### Parser.hs\n- Megaparsec-based parser\n- Produces AST from source code\n- Handles Python-like syntax with Acton extensions\n- Entry point: `parseModule`\n\n#### Types.hs & TypeEnv.hs\n- Type system definitions\n- Type inference engine\n- Constraint solving\n- Key types: `Type`, `Scheme`, `TyEnv`\n\n#### Normalizer.hs\n- Simplifies AST for easier processing\n- Desugars complex expressions\n- Handles pattern matching expansion\n\n#### Deactorizer.hs\n- Transforms actor methods into regular functions\n- Converts actor state into explicit parameters\n- Handles message passing semantics\n\n#### CPS.hs\n- Continuation-Passing Style transformation\n- Makes control flow explicit\n- Prepares for async operations\n\n#### LambdaLifter.hs\n- Lifts nested functions to top level\n- Closure conversion\n- Prepares for C code generation\n\n#### Boxing.hs\n- Converts between boxed/unboxed representations\n- Handles primitive type optimizations\n\n#### CodeGen.hs\n- Generates C code from final AST\n- Produces `.c` and `.h` files\n- Integrates with runtime system\n\n### Supporting Modules\n\n#### Env.hs\n- Environment management\n- Module system handling\n- Import resolution\n\n#### Diagnostics.hs\n- Error message generation\n- Source location tracking\n- Pretty printing errors\n\n#### QuickType.hs\n- Fast type checking for IDE support\n- Incremental type inference\n\n## Working with the Compiler\n\n### Adding a New Language Feature\n\n1. **Update Parser** (`Parser.hs`)\n   - Add new syntax rules\n   - Update AST types in `Syntax.hs`\n\n2. **Update Type System** (`Types.hs`)\n   - Add type rules for new construct\n   - Update type inference\n\n3. **Update Normalizer** (`Normalizer.hs`)\n   - Add normalization rules\n   - Ensure simplified form\n\n4. **Update Code Generation** (`CodeGen.hs`)\n   - Generate appropriate C code\n   - Link with runtime if needed\n\n5. **Add Tests**\n   - Parser tests in `lib/test/`\n   - Type error tests in `acton/test/typeerrors/`\n   - Snapshot tests for code generation\n\n### Debugging the Compiler\n\n```haskell\n-- Add debug prints in any module\nimport Debug.Trace\n\n-- In your code\ntraceShow (\"Debug info\", someValue) $ restOfExpression\n\n-- Or use the built-in pretty printer\nimport Pretty\ntraceShow (renderDoc $ pp someAst) $ ...\n```\n\n### Testing Documentation Generation\n\nDocumentation generation tests are located in `test/test_doc_printing/`. This directory contains various test files demonstrating different documentation scenarios.\n\nTo test documentation generation:\n```bash\nacton doc src/basics.act\n\n# Whole project\nacton doc\n```\n\n### Error Messages\n\nError messages are crucial for user experience. When adding new errors:\n\n1. Create descriptive error in `Diagnostics.hs`\n2. Add snapshot test in `acton/test/typeerrors/`\n3. Include:\n   - Clear description of the problem\n   - Source location\n   - Suggested fix if possible\n\nExample:\n```haskell\nthrowError $ TypeError loc $ \n  \"Cannot unify types\" <+> pp ty1 <+> \"and\" <+> pp ty2\n```\n\n## Type System Details\n\n### Type Inference\n- Hindley-Milner with extensions\n- Row polymorphism for records\n- Subtyping for actors\n- Protocol constraints\n\n### Special Types\n- `World` - Represents side effects\n- `Msg` - Actor message types\n- `Cap` - Capability types\n- `Ref` - Reference types\n\n## Testing Strategy\n\n### Unit Tests (`lib/test/`)\n- Test individual compiler phases\n- Use sydtest framework\n- Fast, focused tests\n\n### Snapshot Tests (`acton/test/`)\n- Compare compiler output against expected\n- Syntax errors: `syntaxerrors/`\n- Type errors: `typeerrors/`\n- Update with: `--accept` flag\n\n### Integration Tests\n- Full compilation tests in `test/`\n- Ensure generated C code works\n\n## Common Tasks\n\n### Adding a Builtin Function\n1. Add signature in `Builtin.hs`\n2. Add type in builtin environment\n3. Generate C call in `CodeGen.hs`\n\n### Improving Error Messages\n1. Identify error location in type checker\n2. Add case in `Diagnostics.hs`\n3. Create snapshot test\n4. Iterate on message clarity\n\n### Optimizing Compilation\n1. Profile with `stack build --profile`\n2. Run with `+RTS -p`\n3. Check `.prof` file\n4. Focus on hot paths in type checker\n\n## Haskell Style Guide\n\n```haskell\n-- Module header\nmodule Acton.Parser\n  ( parseModule\n  , parseExpression\n  , ParseError\n  ) where\n\n-- Explicit imports\nimport qualified Data.Text as T\nimport Data.Maybe (fromMaybe)\n\n-- Type signatures for all top-level functions\nparseModule :: T.Text -> Either ParseError Module\nparseModule input = ...\n\n-- Use where clauses for clarity\nprocessAst :: Ast -> Result\nprocessAst ast = process initialEnv ast\n  where\n    initialEnv = mkEnv\n    process env node = ...\n\n-- Pattern match explicitly\ncompile :: Source -> Either Error Output\ncompile (Source file content) = do\n  ast <- parse content\n  typed <- typeCheck ast\n  generateCode typed\n```\n\n### Whiteboard Layout Style\n\nThe Acton compiler uses a distinctive \"whiteboard layout\" style in many places, especially in the type system and constraint solving code. This style uses very deep indentation to create mathematical equation-like layouts:\n\n```haskell\n-- Function signatures and implementations aligned far from left margin\ninfTop                                  :: Env -> Suite -> TypeM (TEnv,Suite)\ninfTop env ss                           = do -- Implementation starts at column 41+\n                                             pushFX fxPure tNone\n                                             (cs,te,ss) <- infSuiteEnv env ss\n                                             ss <- msubst ss\n                                             return (te, ss)\n\n-- Pattern matching with deep alignment\ninfEnv env (For l p e b els)\n  | nodup p                             = do -- Guard at column 41\n                                             (cs1,te,t1,p') <- infEnvT env p\n                                             t2 <- newTVar\n                                             return (cs1++cs2, [], result)\n\n-- Where clauses with mathematical alignment\naddTyping env n s t c                   = c {info = addT n (simp env s) t (info c)}\n    where addT n s t (DfltInfo l m mbe ts)\n                                        = DfltInfo l m mbe ((n,s,t):ts)\n                                        -- Continuation aligned for visual clarity\n```\n\n**Key characteristics of whiteboard layout:**\n1. **Deep indentation** (often columns 40-50) for do-blocks and expressions\n2. **Vertical alignment** of related terms for easy visual comparison\n3. **Mathematical appearance** - equations and expressions laid out like on a whiteboard\n4. **Structural emphasis** - the layout highlights the logical structure of complex expressions\n5. **Common in type inference** - especially prevalent in Types.hs, TypeEnv.hs, and constraint solving code\n\nThis style helps when working with complex mathematical algorithms by making the structure visually apparent, similar to how one would write equations on a whiteboard with careful spacing and alignment.\n\n## Acton Compiler Style Guide\n\nThese patterns represent the ideal coding style for the Acton compiler. These principles apply broadly across the entire codebase and should be followed in all contributions:\n\n### 1. **Simplify and Remove Dead Code**\n```haskell\n-- BAD: Keep unused data types, functions, or complex abstractions\ndata CompInfo = CompInfo Expr | CompWithWit Expr Expr  -- Dead code\nnormalize' env x = normalize env x  -- Unnecessary wrapper\n\n-- GOOD: Keep only what's needed\ntype NormM a = State (Int,[(Name,PosPar,Expr)]) a\nnormalize env x = ...  -- Direct implementation\n```\n\n### 2. **Separate Concerns Clearly**\n```haskell\n-- BAD: Mix different responsibilities in one function\nprocessExpr env expr = \n  case expr of\n    Add x y -> let tx = typeOf x\n                   ty = typeOf y\n               in if tx == ty then ... else error ...\n    Mul x y -> ...  -- Similar mixed logic\n\n-- GOOD: Separate type checking from transformation\ntypeCheck env expr = ...  -- Just type checking\ntransform env expr = ...  -- Just transformation\n\n-- Or factor out common patterns\nprocessExpr env expr = transform env (typeCheck env expr)\n```\n\n### 3. **Use Generic Abstractions Over Ad-Hoc Solutions**\n```haskell\n-- BAD: Create specific functions for each use case\nhandleListError :: Error -> String\nhandleDictError :: Error -> String\nhandleSetError :: Error -> String\n\n-- GOOD: One generic function that handles all cases\nhandleError :: Error -> String\nhandleError (TypeError t) = \"Type error: \" ++ show t\nhandleError (SyntaxError s) = \"Syntax error: \" ++ s\n```\n\n### 4. **Consistent Naming and Alignment**\n```haskell\n-- Use consistent variable names across the codebase:\n-- env  - Environment\n-- t    - Type\n-- e    - Expression  \n-- p    - Pattern or Parameter\n-- n    - Name\n-- l    - Location\n-- s    - Statement or String\n-- c    - Constraint or Context\n-- w    - Witness\n-- r    - Result or Row\n\n-- Align related definitions for visual clarity\ntInt              = tCon (TC qnInt [])\ntFloat            = tCon (TC qnFloat [])\ntString           = tCon (TC qnString [])\ntBool             = tCon (TC qnBool [])\n```\n\n### 5. **Factor Out Common Patterns**\n```haskell\n-- BAD: Repeat similar code in multiple places\ninfer env (Add e1 e2) = do\n  (cs1, t1, e1') <- infer env e1\n  (cs2, t2, e2') <- infer env e2\n  t <- newTVar\n  return (cs1 ++ cs2 ++ [Cast t1 t, Cast t2 t], t, Add e1' e2')\n  \ninfer env (Mul e1 e2) = do\n  (cs1, t1, e1') <- infer env e1\n  (cs2, t2, e2') <- infer env e2\n  t <- newTVar\n  return (cs1 ++ cs2 ++ [Cast t1 t, Cast t2 t], t, Mul e1' e2')\n\n-- GOOD: Extract common binary operation pattern\ninferBinOp env op e1 e2 = do\n  (cs1, t1, e1') <- infer env e1\n  (cs2, t2, e2') <- infer env e2\n  t <- newTVar\n  return (cs1 ++ cs2 ++ [Cast t1 t, Cast t2 t], t, op e1' e2')\n```\n\n### 6. **Clear Data Flow with Where Clauses**\n```haskell\n-- Structure where clauses to show data dependencies clearly\nprocessExpr env expr = finalResult\n  where \n    -- 1. Extract/compute base values\n    baseType = typeOf env expr\n    location = loc expr\n    \n    -- 2. Build intermediate results  \n    constraints = gatherConstraints baseType\n    simplified = simplify expr\n    \n    -- 3. Construct final result\n    finalResult = Result simplified constraints location\n    \n-- Each binding depends only on earlier bindings\n-- Clear progression from inputs to outputs\n```\n\n### 7. **Handle Each Case in Its Own Context**\n```haskell\n-- BAD: Share state across unrelated computations\nprocessAll items = do\n  state <- initState\n  mapM (process state) items  -- Shared mutable state\n\n-- GOOD: Each computation gets fresh context\nprocessAll items = mapM processOne items\n  where \n    processOne item = do\n      state <- initState  -- Fresh state for each\n      process state item\n```\n\n### 8. **Prefer Explicit Over Implicit**\n```haskell\n-- BAD: Rely on implicit behavior\nfindThing xs = head xs  -- Crashes on empty list\n\n-- GOOD: Make expectations explicit\nfindThing xs = case xs of\n  []    -> error \"findThing: empty list\"\n  (x:_) -> x\n  \n-- Or better, use Maybe\nfindThing :: [a] -> Maybe a\nfindThing []    = Nothing\nfindThing (x:_) = Just x\n```\n\n### Key Principle: These Patterns Apply Everywhere\n\nThe above patterns aren't specific to any particular feature or module. They represent the ideal coding style throughout:\n- **Parser**: Clean separation of lexing/parsing concerns\n- **Type Checker**: Generic constraint handling, clear error messages\n- **Normalizer**: Simple transformations, no unnecessary complexity\n- **Code Generator**: Explicit mappings, clear output structure\n- **All modules**: Consistent naming, factored patterns, clean data flow\n\nWhen in doubt, look at recent high-quality commits in the repository for examples of how to refactor code to match these ideals.\n\n## AI-Assisted Development Process\n\nWhen working with AI assistants on the Acton compiler, follow this structured approach:\n\n### 1. **Problem Discussion Phase**\n- Thoroughly discuss the problem and solution requirements\n- Identify affected compiler phases\n- Consider edge cases and interactions with existing features\n\n### 2. **Test-Driven Development**\n```haskell\n-- AI writes test cases based on requirements\n-- Human reviews and approves test suite\n-- Example: test/comprehensions/generic_test.act\ndef test_generic_list_comp():\n    result = [x * 2 for x in [1, 2, 3]]\n    testing.assertEqual(result, [2, 4, 6])\n```\n\n### 3. **Implementation Phase**\n- AI implements code to pass tests\n- Iteratively compile and run tests\n- Fix errors until all tests pass\n\n### 4. **Code Review and Cleanup Phase** ⚠️ **CRITICAL**\nAfter getting tests to pass, AI MUST perform a holistic code review:\n\n#### Checklist for AI Code Review:\n- [ ] **Remove dead code** - Delete unused functions, data types, imports\n- [ ] **Simplify complex patterns** - Look for opportunities to factor out common code\n- [ ] **Check naming consistency** - Ensure variables and functions follow conventions\n- [ ] **Verify error handling** - Proper error messages with source locations\n- [ ] **Review data flow** - Ensure clean separation of concerns\n- [ ] **Check integration** - Verify the change fits well with existing code\n- [ ] **Update related code** - Ensure all affected areas are updated\n\n#### Example Cleanup Pattern:\n```haskell\n-- BEFORE: Quick fix to pass tests\naddCompWithWit :: (Name,PosPar,Expr,Expr) -> NormM ()\naddComp :: (Name,PosPar,Expr) -> NormM ()\n-- Two similar functions, ad-hoc solution\n\n-- AFTER: Unified clean design\naddComp :: (Name,PosPar,Expr) -> NormM ()\n-- Single function, witness handled through annotation\n```\n\n### 5. **Final Review Before Commit**\n- Ensure code follows the Acton compiler style guide\n- Verify no regression in existing functionality\n- Check that the solution is elegant and maintainable\n- Confirm error messages are helpful\n\n## Common Pitfalls to Avoid\n\n1. **Tunnel Vision**: Don't focus only on making tests pass\n2. **Ad-hoc Solutions**: Avoid quick fixes that complicate the codebase\n3. **Inconsistent Patterns**: Match existing code style and patterns\n4. **Missing Edge Cases**: Consider all variants (e.g., nested comprehensions)\n5. **Poor Error Messages**: Always include helpful context in errors\n\n## Performance Considerations\n\n1. **Parser Performance**\n   - Use strict Text, not String\n   - Careful with backtracking\n\n2. **Type Checker Performance**\n   - Cache type environments\n   - Minimize constraint solving\n\n3. **Code Generation**\n   - Stream output when possible\n   - Batch C file writes\n\n## Integration with Build System\n\nThe compiler is invoked by:\n- Zig build system for Acton projects\n- CLI tool for user commands\n- Test harness for testing\n\nKey interfaces:\n- Command line arguments\n- JSON output for errors\n- File system conventions\n"
  },
  {
    "path": "compiler/acton/Main.hs",
    "content": "{-# LANGUAGE CPP #-}\n-- Copyright (C) 2019-2021 Data Ductus AB\n--\n-- Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:\n--\n-- 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.\n--\n-- 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.\n--\n-- 3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission.\n--\n-- THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS \"AS IS\" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n--\n\nmodule Main where\n\nimport Prelude hiding (readFile, writeFile)\n\nimport qualified Acton.Parser\nimport qualified Acton.Syntax as A\nimport qualified Acton.NameInfo as I\nimport Text.Megaparsec.Error (ParseErrorBundle)\nimport Acton.Parser (CustomParseError)\nimport qualified Acton.CommandLineParser as C\nimport Acton.Printer ()\nimport qualified Acton.Env\nimport Acton.Env (simp, define, setMod)\nimport qualified Acton.QuickType\nimport qualified Acton.Kinds\nimport qualified Acton.Types\nimport qualified Acton.Solver\nimport qualified Acton.Normalizer\nimport qualified Acton.CPS\nimport qualified Acton.Deactorizer\nimport qualified Acton.LambdaLifter\nimport qualified Acton.Boxing\nimport qualified Acton.CodeGen\nimport qualified Acton.BuildSpec as BuildSpec\nimport qualified Acton.Builtin\nimport qualified Acton.DocPrinter as DocP\nimport qualified Acton.Diagnostics as Diag\nimport qualified Acton.Fingerprint as Fingerprint\nimport qualified Acton.SourceProvider as Source\nimport Acton.Compile\nimport Utils\nimport qualified Pretty\nimport qualified InterfaceFiles\nimport qualified PkgCommands\n\nimport Control.Concurrent.MVar\nimport Control.Exception (throw,catch,finally,IOException,try,SomeException,bracket,bracket_,onException,evaluate)\nimport Control.Exception (bracketOnError)\nimport Control.Concurrent (ThreadId, forkIO, killThread, threadDelay)\nimport Control.Concurrent.Chan (Chan, newChan, writeChan, readChan)\nimport Control.Monad\nimport Data.Bits\nimport Data.Default.Class (def)\nimport Data.List.Split\nimport Data.IORef\nimport Data.Maybe (catMaybes, isJust)\nimport Data.Monoid ((<>))\nimport Data.Word (Word32)\nimport Data.Graph\nimport Data.String.Utils (replace)\nimport Data.Version (showVersion)\nimport Data.Char (toLower)\nimport qualified Data.List\nimport Data.Either (partitionEithers)\nimport qualified Data.Map as M\nimport qualified Data.Set\nimport Data.Time.Clock (UTCTime)\nimport Error.Diagnose\nimport Error.Diagnose.Style (defaultStyle)\nimport qualified Filesystem.Path.CurrentOS as Fsco\nimport GHC.Conc (getNumCapabilities, getNumProcessors, setNumCapabilities, myThreadId, threadCapability)\nimport Prettyprinter (unAnnotate)\nimport Prettyprinter.Render.Text (hPutDoc)\nimport Data.List (isPrefixOf, isSuffixOf, find, partition, foldl', nub, intercalate)\nimport System.Clock\nimport System.Directory\nimport System.Directory.Recursive\nimport System.Environment (lookupEnv)\nimport System.Exit\nimport System.FileLock\nimport System.FilePath ((</>), addTrailingPathSeparator)\nimport System.FilePath.Posix\nimport System.IO hiding (readFile, writeFile)\nimport Text.PrettyPrint (renderStyle, style, Style(..), Mode(PageMode))\nimport Text.Show.Pretty (ppDoc)\nimport System.IO.Temp\nimport System.IO.Unsafe (unsafePerformIO)\nimport System.Info\nimport System.Posix.Files\nimport System.Posix.IO (createPipe, setFdOption, closeFd, FdOption(..))\nimport System.Process hiding (createPipe)\nimport qualified System.FSNotify as FS\nimport qualified System.Environment\nimport qualified System.Exit\nimport qualified Paths_acton\nimport System.Random (randomRIO)\nimport Text.Printf\n\nimport qualified Data.ByteString.Lazy as BL\n\nimport TestRunner\nimport TerminalProgress\nimport TerminalSize\nimport ZigProgress\n\nmain = do\n    hSetBuffering stdout LineBuffering\n    arg <- C.parseCmdLine\n    let gopts = case arg of\n          C.CmdOpt g _ -> g\n          C.CompileOpt _ g _ -> g\n    ensureCapabilities gopts\n    let run = case arg of\n          C.CmdOpt gopts (C.New opts)         -> createProject (C.file opts)\n          C.CmdOpt gopts (C.Build bopts)      ->\n              let opts = C.buildCompile bopts\n                  files = C.buildFiles bopts\n              in if null files\n                 then buildProject gopts opts\n                 else buildFiles gopts opts files\n          C.CmdOpt gopts (C.Install opts)      -> PkgCommands.installCommand gopts opts\n          C.CmdOpt gopts (C.Uninstall opts)    -> PkgCommands.uninstallCommand gopts opts\n          C.CmdOpt gopts (C.Sig opts)          -> sigCommand gopts opts\n          C.CmdOpt gopts (C.Test tcmd)        -> runTests gopts tcmd\n          C.CmdOpt gopts C.Fetch             -> fetchCommand gopts\n          C.CmdOpt gopts C.PkgShow           -> pkgShow gopts\n          C.CmdOpt gopts (C.PkgAdd opts)     -> PkgCommands.pkgAddCommand gopts opts\n          C.CmdOpt gopts (C.PkgRemove opts)  -> PkgCommands.pkgRemoveCommand gopts opts\n          C.CmdOpt gopts (C.PkgUpgrade opts) -> PkgCommands.pkgUpgradeCommand gopts opts\n          C.CmdOpt gopts C.PkgUpdate         -> PkgCommands.pkgUpdateCommand gopts\n          C.CmdOpt gopts (C.PkgSearch opts)  -> PkgCommands.pkgSearchCommand gopts opts\n          C.CmdOpt gopts (C.BuildSpecCmd o)   -> buildSpecCommand o\n          C.CmdOpt gopts (C.Cloud opts)       -> undefined\n          C.CmdOpt gopts (C.Doc opts)         -> printDocs gopts opts\n          C.CmdOpt gopts (C.ZigPkgAdd opts)  -> PkgCommands.zigPkgAddCommand gopts opts\n          C.CmdOpt gopts (C.ZigPkgRemove opts) -> PkgCommands.zigPkgRemoveCommand gopts opts\n          C.CmdOpt gopts C.Version            -> printVersion\n          C.CompileOpt nms gopts opts         -> runFile gopts opts (head nms)\n    run `catch` \\(ProjectError msg) -> printErrorAndExit msg\n\n-- Apply global options to compile options\napplyGlobalOpts :: C.GlobalOptions -> C.CompileOptions -> C.CompileOptions\napplyGlobalOpts gopts opts = opts\n\nrunFile :: C.GlobalOptions -> C.CompileOptions -> FilePath -> IO ()\nrunFile gopts opts fname =\n    case takeExtension fname of\n      \".act\" -> buildFile gopts (applyGlobalOpts gopts opts) fname\n      \".ty\" -> printDocs gopts (C.DocOptions fname (Just C.AsciiFormat) Nothing)\n      _ -> printErrorAndExit (\"Unknown filetype: \" ++ fname)\n\n-- Ensure enough capabilities: honor --jobs if set, otherwise at least 2 or #procs.\nensureCapabilities :: C.GlobalOptions -> IO ()\nensureCapabilities gopts = do\n    caps0 <- getNumCapabilities\n    let req = C.jobs gopts\n    when (req > 0 && caps0 < req) $ setNumCapabilities req\n    when (req == 0 && caps0 < 2) $ do\n      procs <- getNumProcessors\n      setNumCapabilities (max 2 procs)\n\n\n-- Auxiliary functions ---------------------------------------------------------------------------------------\n\noptimizeModeToZig :: C.OptimizeMode -> String\noptimizeModeToZig C.Debug        = \"Debug\"\noptimizeModeToZig C.ReleaseSafe  = \"ReleaseSafe\"\noptimizeModeToZig C.ReleaseSmall = \"ReleaseSmall\"\noptimizeModeToZig C.ReleaseFast  = \"ReleaseFast\"\n\nzig :: Paths -> FilePath\nzig paths = sysPath paths ++ \"/zig/zig\"\n\n\n-- Try to acquire a lock, return Nothing if failed, Just (FileLock, FilePath) if succeeded\ntryLock :: FilePath -> IO (Maybe (FileLock, FilePath))\ntryLock lockPath = do\n    maybeLock <- tryLockFile lockPath Exclusive  -- This will fail immediately if locked\n    case maybeLock of\n        Nothing -> return Nothing  -- Lock failed\n        Just lock -> return $ Just (lock, lockPath)\n\n-- Try locks sequentially until one succeeds or all fail\nfindAvailableScratch :: FilePath -> IO (Maybe (FileLock, FilePath))\nfindAvailableScratch basePath = go [0..31]  -- 32 possible scratch directories\n  where\n    go [] = return Nothing  -- All attempts failed\n    go (x:xs) = do\n        let lockPath = joinPath [basePath, \"scratch\" ++ show x ++ \".lock\"]\n        result <- tryLock lockPath\n        case result of\n            Just lockInfo -> return $ Just lockInfo\n            Nothing -> go xs  -- Try next number\n\nprintErrorAndExit msg = do\n                  errorWithoutStackTrace msg\n                  System.Exit.exitFailure\n\n-- our own readFile & writeFile with hard-coded utf-8 encoding (atomic writes)\nreadFile f = do\n    h <- openFile f ReadMode\n    hSetEncoding h utf8\n    c <- hGetContents h\n    return c\n\nwriteFile :: FilePath -> String -> IO ()\nwriteFile = writeFileUtf8Atomic\n\nignoreIOException :: IOException -> IO ()\nignoreIOException _ = return ()\n\nwriteFileAtomic :: FilePath -> String -> IO ()\nwriteFileAtomic f c = do\n    let dir = takeDirectory f\n    bracketOnError\n      (openTempFile dir \".acton-tmp\")\n      (\\(tmpPath, tmpHandle) -> do\n          hClose tmpHandle `catch` ignoreIOException\n          removeFile tmpPath `catch` ignoreIOException)\n      (\\(tmpPath, tmpHandle) -> do\n          hSetEncoding tmpHandle utf8\n          hPutStr tmpHandle c\n          hClose tmpHandle\n          renameFile tmpPath f `catch` handleRenameError tmpPath)\n  where\n    handleRenameError :: FilePath -> IOException -> IO ()\n    handleRenameError tmpPath _ = do\n        removeFile f `catch` ignoreIOException\n        renameFile tmpPath f\n\n-- | Format a TimeSpec as seconds with millisecond precision.\nfmtTimePrecise :: TimeSpec -> String\nfmtTimePrecise t =\n    printf \"%6.3f s\" secs\n  where\n    secs :: Float\n    secs = (fromIntegral (sec t)) + (fromIntegral (nsec t) / 1000000000)\n\n-- | Format a TimeSpec with second granularity for compact narrow logs.\nfmtTimeCompact :: TimeSpec -> String\nfmtTimeCompact t =\n    if wholeSecs <= 0 && remNanos > 0\n      then \"<1s\"\n      else show roundedSecs ++ \"s\"\n  where\n    wholeSecs = fromIntegral (sec t) :: Integer\n    remNanos = nsec t\n    roundedSecs =\n      wholeSecs + if remNanos >= 500000000 then 1 else 0\n\n-- | Pad a string with trailing spaces for aligned output.\npadRight :: Int -> String -> String\npadRight width s\n    | len >= width' = s\n    | otherwise = s ++ replicate (width' - len) ' '\n  where\n    width' = max 0 width\n    len = length s\n\n-- | Pad a string with leading spaces for aligned output.\npadLeft :: Int -> String -> String\npadLeft width s\n    | len >= width' = s\n    | otherwise = replicate (width' - len) ' ' ++ s\n  where\n    width' = max 0 width\n    len = length s\n\nprogressSpinnerThreshold :: Int\nprogressSpinnerThreshold = 25\n\nprogressPrefixWidth :: Int -> Int\nprogressPrefixWidth cols\n    | cols >= progressSpinnerThreshold = 3\n    | otherwise = 0\n\n-- | Truncate a string on the right with an ellipsis when it does not fit.\nabbreviateRight :: Int -> String -> String\nabbreviateRight width s\n    | width <= 0 = \"\"\n    | length s <= width = s\n    | width <= 3 = take width s\n    | otherwise = take (width - 3) s ++ \"...\"\n\n-- | Compress a module label to preserve the root and as much of the tail as fits.\nfitBuildModuleLabel :: Int -> String -> String\nfitBuildModuleLabel width label\n    | width <= 0 = \"\"\n    | length label <= width = label\n    | width < 10 = termFitPlainLeft width label\n    | otherwise =\n        case break (== '.') label of\n          (root, '.':rest) ->\n            let rootBudget = min (length root) (max 1 (width - 4))\n                tailBudget = max 0 (width - rootBudget - 3)\n            in if tailBudget <= 0\n                 then termFitPlainLeft width label\n                 else take rootBudget root ++ \"...\" ++ termFitPlainLeft tailBudget rest\n          _ -> abbreviateRight width label\n\ntype StatusRenderer = Int -> Maybe String\n\nstaticStatusRenderer :: String -> String -> StatusRenderer\nstaticStatusRenderer full short budget\n    | budget < 10 = Nothing\n    | length full <= budget = Just full\n    | length short <= budget = Just short\n    | otherwise = Just (abbreviateRight budget full)\n\ndata BuildLineLayout = BuildLineLayout\n  { bllText :: String\n  , bllAligned :: Bool\n  , bllLabelCols :: Int\n  , bllHasStatus :: Bool\n  }\n\nemptyBuildLineLayout :: BuildLineLayout\nemptyBuildLineLayout = BuildLineLayout \"\" False 0 False\n\n-- | Fit a build line body to width while preserving module/status columns when possible.\nfitBuildLineLayout :: Int -> Int -> Int -> Bool -> String -> StatusRenderer -> BuildLineLayout\nfitBuildLineLayout width labelWidth statusWidth preserveBlankLabel modLbl renderStatus\n    | width <= 0 = emptyBuildLineLayout\n    | hasLabelColumn =\n        case renderAligned of\n          Just line -> line\n          Nothing ->\n            if null modLbl\n              then fitStatusOnly\n              else BuildLineLayout (fitBuildModuleLabel width modLbl) False (min width labelWidth) False\n    | otherwise = fitStatusOnly\n  where\n    minStatusWidth = 10\n    minLabelWidth = 10\n    hasLabelColumn = preserveBlankLabel || not (null modLbl)\n    renderAligned\n      | width < 2 + minStatusWidth = Nothing\n      | labelCols <= 0 && not (null modLbl) = Nothing\n      | not (null modLbl) && labelCols < min minLabelWidth (length modLbl) = Nothing\n      | statusCols < minStatusWidth = Nothing\n      | otherwise =\n          case renderStatus statusCols of\n            Just status ->\n              let labelText = if null modLbl then \"\" else fitBuildModuleLabel labelCols modLbl\n                  core =\n                    padRight labelCols labelText\n                    ++ \"  \"\n                    ++ padRight statusCols status\n              in Just (BuildLineLayout core True labelCols True)\n            Nothing -> Nothing\n    labelCols = min labelWidth (max 0 (width - 2 - minStatusWidth))\n    statusCols = min statusWidth (max 0 (width - labelCols - 2))\n    fitStatusOnly =\n      case renderStatus (min statusWidth width) of\n        Just status -> BuildLineLayout (termFitPlainRight width status) False 0 True\n        Nothing -> emptyBuildLineLayout\n\n-- | Fit an active build line to the current terminal width.\nfitBuildActiveLineAligned :: Int -> Int -> Int -> String -> StatusRenderer -> String\nfitBuildActiveLineAligned width labelWidth statusWidth modLbl renderStatus =\n    bllText (fitBuildLineLayout width labelWidth statusWidth False modLbl renderStatus)\n\nsafeLiveWidth :: Int -> Int\nsafeLiveWidth width\n    | width <= 0 = 0\n    | width == 1 = 1\n    | otherwise = width - 1\n\n-- Version handling ------------------------------------------------------------------------------------------\n\nprintVersion = putStrLn getVer\n\ngetVer          = showVersion Paths_acton.version\n\nprintIce errMsg = putStrLn(\n                        \"ERROR: internal compiler error: \" ++ errMsg ++\n                        \"\\nNOTE: this is likely a bug in acton, please report this at:\" ++\n                        \"\\nNOTE: https://github.com/actonlang/acton/issues/new?template=ice.yaml\" ++\n                        \"\\nNOTE: acton \" ++ getVer\n                        )\n\n-- Create a project ---------------------------------------------------------------------------------------------\n\n-- | Create a new Acton project skeleton (files, dirs, optional git init).\ncreateProject :: String -> IO ()\ncreateProject name = do\n    curDir <- getCurrentDirectory\n    projDirExists <- doesDirectoryExist name\n    iff (projDirExists) $\n        printErrorAndExit (\"Unable to create project \" ++ name ++ \", directory already exists.\")\n    fp <- generateFingerprint name\n    let projDir = joinPath [curDir, name]\n        srcRoot = joinPath [projDir, \"src\"]\n        buildActPath = joinPath [projDir, \"Build.act\"]\n        buildSpec = BuildSpec.BuildSpec\n          { BuildSpec.specName = name\n          , BuildSpec.specDescription = Nothing\n          , BuildSpec.fingerprint = fp\n          , BuildSpec.dependencies = M.empty\n          , BuildSpec.zig_dependencies = M.empty\n          }\n    createDirectoryIfMissing True srcRoot\n    writeFile buildActPath (BuildSpec.renderBuildAct buildSpec)\n    paths <- findPaths buildActPath defaultCompileOptions\n    writeFile (joinPath [ projDir, \".gitignore\" ]) (\n      \".acton.compile.lock\\n\" ++\n      \".acton.lock\\n\" ++\n      \"build.zig\\n\" ++\n      \"build.zig.zon\\n\" ++\n      \"out\\n\"\n      )\n    writeFile (joinPath [ projDir, \"README.md\" ]) (\n      \"# \" ++ name ++ \"\\n\\n\"\n      ++ \"```sh\\nacton build\\n./out/bin/\" ++ name ++ \"\\n```\\n\"\n      )\n    createDirectoryIfMissing True (srcDir paths)\n    writeFile (joinPath [(srcDir paths), name ++ \".act\"]) \"#\\n#\\n\\nactor main(env):\\n    print(\\\"Hello World!\\\")\\n    env.exit(0)\\n\"\n    putStrLn(\"Created project \" ++ name)\n    putStrLn(\"Next: cd \" ++ name ++ \" && acton build && ./out/bin/\" ++ name)\n    gitAvailable <- isGitAvailable\n    iff (gitAvailable) $ do\n        putStrLn(\"\")\n        setCurrentDirectory name\n        callProcess \"git\" [\"init\"]\n        callProcess \"git\" [\"add\", \".\"]\n        setCurrentDirectory curDir\n\n-- BuildSpec -----------------------------------------------------------------------------------------------------\nbuildSpecCommand :: C.BuildSpecCommand -> IO ()\nbuildSpecCommand cmd =\n  case cmd of\n    C.BuildSpecUpdate jsonPath -> do\n      exists <- doesFileExist \"Build.act\"\n      unless exists $ printErrorAndExit \"Build.act not found in current directory\"\n      let actPath = \"Build.act\"\n      content <- readFile actPath\n      json <- if jsonPath == \"-\"\n                then BL.getContents\n                else BL.readFile jsonPath\n      case BuildSpec.updateBuildActFromJSON content json of\n        Left err      -> printErrorAndExit (\"Failed to update Build.act: \\n\" ++ err)\n        Right updated -> writeFile actPath updated >> putStrLn \"Updated Build.act\"\n    C.BuildSpecDump -> do\n      spec <- loadBuildSpec \".\"\n      BL.putStr (BuildSpec.encodeBuildSpecJSON spec)\n\n\n-- Build a project -----------------------------------------------------------------------------------------------\n\n-- | Dispatch a project build, routing to watch or single-shot compilation.\nbuildProject :: C.GlobalOptions -> C.CompileOptions -> IO ()\nbuildProject gopts opts = do\n                iff (not (null $ (C.root opts)) && (length $ splitOn \".\" (C.root opts)) == 1) $\n                  printErrorAndExit(\"Project build requires a qualified root actor name, like foo.main\")\n                if C.watch opts\n                  then do\n                    curDir <- getCurrentDirectory\n                    watchProjectAt gopts opts curDir\n                  else buildProjectOnce gopts opts\n\n-- | Handle \"acton build FILE...\" by compiling multiple .act files together\n-- when they share a project root; otherwise fall back to per-file handling.\nbuildFiles :: C.GlobalOptions -> C.CompileOptions -> [FilePath] -> IO ()\nbuildFiles gopts opts files =\n    case files of\n      [single] -> runFile gopts opts single\n      _ -> do\n        when (C.watch opts) $\n          printErrorAndExit \"Cannot use --watch with multiple files. Use `acton build --watch` for projects or `acton build FILE --watch` (or `acton FILE --watch`) for a single file.\"\n        absFiles <- mapM canonicalizePath files\n        let onlyAct = all ((== \".act\") . takeExtension) files\n        projDirs <- mapM findProjectDir absFiles\n        let projRoots = nub (catMaybes projDirs)\n        case projRoots of\n          [proj] | onlyAct && all (== Just proj) projDirs -> do\n            let sp = Source.diskSourceProvider\n                runBuild opts' =\n                  withProjectLockNotice gopts proj $\n                    compileFiles sp gopts opts' absFiles False\n            runBuild opts\n          _ -> mapM_ (runFile gopts opts) files\n\n-- | Collect all source files in a project's src/ directory.\nprojectSourceFiles :: Paths -> IO [FilePath]\nprojectSourceFiles paths = do\n    allFiles <- getFilesRecursive (srcDir paths)\n    return (catMaybes (map filterActFile allFiles))\n\nwithBackgroundCompilerLockOrExit :: FilePath -> String -> IO a -> IO a\nwithBackgroundCompilerLockOrExit projDir msg action = do\n    mlock <- tryBackgroundCompilerLock projDir\n    case mlock of\n      Nothing -> printErrorAndExit msg\n      Just lock -> action `finally` releaseBackgroundCompilerLock lock\n\nwithProjectLockNotice :: C.GlobalOptions -> FilePath -> IO a -> IO a\nwithProjectLockNotice gopts projDir action =\n    withProjectLockOnWait projDir onWait action\n  where\n    onWait =\n      unless (C.quiet gopts) $\n        putStrLn (\"Waiting for compiler lock in \" ++ projDir)\n\nwithProjectLockForGen :: C.GlobalOptions -> CompileScheduler -> Int -> FilePath -> IO () -> IO ()\nwithProjectLockForGen gopts sched gen projDir action =\n    whenCurrentGen sched gen $\n      withProjectLockNotice gopts projDir $\n        whenCurrentGen sched gen action\n\nrequireProjectLayout :: Paths -> IO ()\nrequireProjectLayout paths = do\n    exists <- doesDirectoryExist (srcDir paths)\n    unless exists $\n      printErrorAndExit \"Missing src/ directory\"\n-- | Strict path resolution: require a project config in the given directory.\nloadProjectPathsAt :: FilePath -> C.CompileOptions -> IO Paths\nloadProjectPathsAt curDir opts = do\n    actPath <- requireProjectConfigPath curDir\n    let projDir = takeDirectory actPath\n    srcExists <- doesDirectoryExist (joinPath [projDir, \"src\"])\n    unless srcExists $\n      printErrorAndExit \"Missing src/ directory\"\n    paths <- findPaths actPath opts\n    requireProjectLayout paths\n    return paths\n\nloadProjectPaths :: C.CompileOptions -> IO Paths\nloadProjectPaths opts = do\n    curDir <- getCurrentDirectory\n    loadProjectPathsAt curDir opts\n\nrequireProjectConfigPath :: FilePath -> IO FilePath\nrequireProjectConfigPath curDir = do\n    let candidates =\n          [ joinPath [curDir, \"Build.act\"]\n          ]\n    mpath <- firstExisting candidates\n    case mpath of\n      Just path -> return path\n      Nothing -> printErrorAndExit \"Project config not found in current directory (expected Build.act)\"\n  where\n    firstExisting [] = return Nothing\n    firstExisting (p:ps) = do\n      exists <- doesFileExist p\n      if exists then return (Just p) else firstExisting ps\n\nignoreNotExists :: IOException -> IO ()\nignoreNotExists _ = return ()\n\nwithScratchDirLock :: (FilePath -> IO a) -> IO a\nwithScratchDirLock action = do\n    home <- getHomeDirectory\n    let basePath = joinPath [home, \".cache\", \"acton\", \"scratch\"]\n    createDirectoryIfMissing True basePath\n    maybeLockInfo <- findAvailableScratch basePath\n    case maybeLockInfo of\n      Nothing -> error \"Could not acquire any scratch directory lock\"\n      Just (lock, lockPath) -> do\n        let scratchDir = dropExtension lockPath\n        removeDirectoryRecursive scratchDir `catch` ignoreNotExists\n        action scratchDir `finally` unlockFile lock\n\nwithTempDirOpts :: C.CompileOptions -> (C.CompileOptions -> Bool -> IO a) -> IO a\nwithTempDirOpts opts action\n  | C.tempdir opts /= \"\" = action opts False\n  | otherwise = withScratchDirLock $ \\scratchDir ->\n      action opts { C.tempdir = scratchDir } True\n\ninitCompileWatchContext :: C.GlobalOptions -> IO (CompileScheduler, ProgressUI, ProgressState)\ninitCompileWatchContext gopts = do\n    maxParallel <- compileMaxParallel gopts\n    sched <- newCompileScheduler gopts maxParallel\n    progressUI <- initProgressUI gopts maxParallel\n    progressState <- newProgressState\n    return (sched, progressUI, progressState)\n\nlogProjectBuild :: C.GlobalOptions -> ProgressUI -> ProgressState -> FilePath -> IO ()\nlogProjectBuild gopts progressUI progressState projDir =\n    iff (not(C.quiet gopts)) $ do\n      progressReset progressUI progressState\n      progressLogLine progressUI (\"Building project in \" ++ projDir)\n-- | Run a single project build under lock and generate docs.\nbuildProjectOnce :: C.GlobalOptions -> C.CompileOptions -> IO ()\nbuildProjectOnce gopts opts = do\n                let sp = Source.diskSourceProvider\n                paths <- loadProjectPaths opts\n                iff (not(C.quiet gopts)) $ do\n                  putStrLn(\"Building project in \" ++ projPath paths)\n                let projDir = projPath paths\n                    runBuild opts' = withProjectLockNotice gopts projDir $ do\n                      srcFiles <- projectSourceFiles paths\n                      compileFiles sp gopts opts' srcFiles True\n                      generateProjectDocIndex sp gopts opts' paths srcFiles\n                runBuild opts\n\n-- Test runner -------------------------------------------------------------------------------------------------\n\n-- | Entry point for acton test; configures options and selects mode/watch.\nrunTests :: C.GlobalOptions -> C.TestCommand -> IO ()\nrunTests gopts cmd = do\n    let (mode, topts) =\n          case cmd of\n            C.TestRun opts  -> (TestModeRun, opts)\n            C.TestList opts -> (TestModeList, opts)\n            C.TestPerf opts -> (TestModePerf, opts)\n            C.TestStress opts -> (TestModeStress, opts)\n        gopts' = if C.testJson topts then gopts { C.quiet = True } else gopts\n        opts0 = C.testCompile topts\n    let opts = opts0\n          { C.test = True\n          , C.skip_build = mode == TestModeList\n          , C.only_build = False\n          }\n    paths <- loadProjectPaths opts\n    if C.watch opts0\n      then case mode of\n             TestModeList -> runTestsOnce gopts' opts topts mode paths\n             _ -> runTestsWatch gopts' opts topts mode paths\n      else runTestsOnce gopts' opts topts mode paths\n\n-- | Build once and then list/run tests based on the selected mode.\nrunTestsOnce :: C.GlobalOptions -> C.CompileOptions -> C.TestOptions -> TestMode -> Paths -> IO ()\nrunTestsOnce gopts opts topts mode paths = do\n    buildProjectOnce gopts opts\n    modules <- listTestModules opts paths\n    case mode of\n      TestModeList -> listProjectTests opts paths topts modules\n      _ -> do\n        maxParallel0 <- testMaxParallel gopts\n        let maxParallel = if mode == TestModeStress then 1 else maxParallel0\n        useColorOut <- useColor gopts\n        exitCode <- runProjectTests useColorOut gopts opts paths topts mode modules maxParallel\n        exitWithTestCode exitCode\n\n-- | Watch mode for tests that rebuilds incrementally and reruns changed modules.\nrunTestsWatch :: C.GlobalOptions -> C.CompileOptions -> C.TestOptions -> TestMode -> Paths -> IO ()\nrunTestsWatch gopts opts topts mode paths = do\n    let sp = Source.diskSourceProvider\n        projDir = projPath paths\n        srcRoot = srcDir paths\n    withBackgroundCompilerLockOrExit projDir\n      \"Another long-running Acton compiler is already running; cannot start test watch.\" $ do\n        (sched, progressUI, progressState) <- initCompileWatchContext gopts\n        testParallel0 <- testMaxParallel gopts\n        let testParallel = if mode == TestModeStress then 1 else testParallel0\n        let runOnce gen mChanged = do\n              withProjectLockForGen gopts sched gen projDir $ do\n                logProjectBuild gopts progressUI progressState projDir\n                srcFiles <- projectSourceFiles paths\n                hadErrors <- compileFilesChanged sp gopts opts srcFiles True mChanged (Just (sched, gen)) (Just (progressUI, progressState))\n                unless hadErrors $ do\n                  testModules <- listTestModules opts paths\n                  modulesToTest <- selectTestModules paths srcFiles mChanged testModules\n                  unless (null modulesToTest) $\n                    do\n                      useColorOut <- useColor gopts\n                      void $ runProjectTests useColorOut gopts opts paths topts mode modulesToTest testParallel\n        runWatchProject gopts projDir srcRoot sched runOnce\n\nselectTestModules :: Paths -> [FilePath] -> Maybe [FilePath] -> [String] -> IO [String]\nselectTestModules paths srcFiles mChanged testModules =\n    case mChanged of\n      Nothing -> return testModules\n      Just changedPaths -> do\n        changedModules <- changedModulesFromPaths paths changedPaths\n        affected <- dependentTestModulesFromHeaders paths srcFiles changedModules\n        return (filter (`elem` testModules) affected)\n\n-- | Compute parallelism for test runs from jobs or core count.\ntestMaxParallel :: C.GlobalOptions -> IO Int\ntestMaxParallel gopts = do\n    nCaps <- getNumCapabilities\n    return (max 1 (if C.jobs gopts > 0 then C.jobs gopts else max 1 (nCaps `div` 2)))\n\n-- | Exit with a status derived from test errors and failures.\nexitWithTestCode :: Int -> IO ()\nexitWithTestCode code\n  | code <= 0 = System.Exit.exitSuccess\n  | otherwise = System.Exit.exitWith (ExitFailure code)\n\nchangedModulesFromPaths :: Paths -> [FilePath] -> IO [String]\nchangedModulesFromPaths paths files = do\n    mods <- forM files $ \\file -> do\n      mn <- moduleNameFromFile (srcDir paths) file\n      return (modNameToString mn)\n    return (Data.List.sort (nub mods))\n\nreadModuleImports :: Paths -> A.ModName -> IO [A.ModName]\nreadModuleImports paths mn = do\n    let tyFile = outBase paths mn ++ \".ty\"\n    exists <- doesFileExist tyFile\n    if not exists\n      then return []\n      else do\n        hdrE <- (try :: IO a -> IO (Either SomeException a)) $ InterfaceFiles.readHeader tyFile\n        case hdrE of\n          Left _ -> return []\n          Right (_sourceMeta, _hash, _ih, _implH, imps, _nameHashes, _roots, _tests, _doc) -> return (map fst imps)\n\ndependentTestModulesFromHeaders :: Paths -> [FilePath] -> [String] -> IO [String]\ndependentTestModulesFromHeaders paths srcFiles changedModules = do\n    depsByMod <- forM srcFiles $ \\file -> do\n      mn <- moduleNameFromFile (srcDir paths) file\n      imps <- readModuleImports paths mn\n      return (modNameToString mn, map modNameToString imps)\n    let revMap = foldl'\n          (\\acc (mn, deps) -> foldl' (\\a dep -> M.insertWith (++) dep [mn] a) acc deps)\n          M.empty\n          depsByMod\n        affected = reverseClosure revMap (Data.Set.fromList changedModules)\n    return (Data.List.sort (Data.Set.toList affected))\n  where\n    reverseClosure revMap start = go start (Data.Set.toList start)\n      where\n        go seen [] = seen\n        go seen (k:ks) =\n          let ds = M.findWithDefault [] k revMap\n              new = filter (`Data.Set.notMember` seen) ds\n              seen' = foldl' (flip Data.Set.insert) seen new\n          in go seen' (ks ++ new)\n\n-- | Watch a project directory and rebuild on source or build spec changes.\nwatchProjectAt :: C.GlobalOptions -> C.CompileOptions -> FilePath -> IO ()\nwatchProjectAt gopts opts projDir = do\n                let sp = Source.diskSourceProvider\n                paths <- loadProjectPathsAt projDir opts\n                withBackgroundCompilerLockOrExit (projPath paths)\n                  \"Another long-running Acton compiler is already running; cannot start watch.\" $ do\n                    (sched, progressUI, progressState) <- initCompileWatchContext gopts\n                    let runOnce gen mChanged =\n                          withProjectLockForGen gopts sched gen (projPath paths) $ do\n                            logProjectBuild gopts progressUI progressState (projPath paths)\n                            srcFiles <- projectSourceFiles paths\n                            void $ compileFilesChanged sp gopts opts srcFiles True mChanged (Just (sched, gen)) (Just (progressUI, progressState))\n                            when (isNothing mChanged) $\n                              generateProjectDocIndex sp gopts opts paths srcFiles\n                    runWatchProject gopts (projPath paths) (srcDir paths) sched runOnce\n\n-- | Build a single file, optionally running in watch mode.\nbuildFile :: C.GlobalOptions -> C.CompileOptions -> FilePath -> IO ()\nbuildFile gopts opts file\n    | C.watch opts = watchFile gopts opts file\n    | otherwise = buildFileOnce gopts opts file\n\n-- | Compile one file in project or scratch mode with locking.\nbuildFileOnce :: C.GlobalOptions -> C.CompileOptions -> FilePath -> IO ()\nbuildFileOnce gopts opts file = do\n    let sp = Source.diskSourceProvider\n    absFile <- canonicalizePath file\n    curDir <- getCurrentDirectory\n    -- Determine if we are in a project\n    projDir <- findProjectDir absFile\n    case projDir of\n      Just proj -> do\n        let relProj = makeRelative curDir proj\n        -- In a project, use project directory for compilation.\n        iff (not(C.quiet gopts)) $ do\n          putStrLn(\"Building file \" ++ file ++ \" in project \" ++ relProj)\n        let runBuild opts' =\n              withProjectLockNotice gopts proj $\n                compileFiles sp gopts opts' [file] False\n        runBuild opts\n      Nothing -> do\n        -- Not in a project, use scratch directory for compilation unless\n        -- --tempdir is provided - then use that\n        withTempDirOpts opts $ \\opts' usedScratch -> do\n          iff (not(C.quiet gopts)) $ do\n            if usedScratch\n              then do\n                let scratch_dir = if (C.verbose gopts) then \" \" ++ C.tempdir opts' else \"\"\n                putStrLn(\"Building file \" ++ file ++ \" using temporary scratch directory\" ++ scratch_dir)\n              else\n                putStrLn(\"Building file \" ++ file ++ \" using temporary directory \" ++ C.tempdir opts')\n          compileFiles sp gopts opts' [file] False\n\n-- | Watch a single file and rebuild on changes.\nwatchFile :: C.GlobalOptions -> C.CompileOptions -> FilePath -> IO ()\nwatchFile gopts opts file = do\n    absFile <- canonicalizePath file\n    projDir <- findProjectDir absFile\n    case projDir of\n      Just proj -> watchProjectAt gopts opts proj\n      Nothing -> do\n        let sp = Source.diskSourceProvider\n        (sched, progressUI, progressState) <- initCompileWatchContext gopts\n        let runWatch opts' =\n              let runOnce gen mChanged =\n                    whenCurrentGen sched gen $\n                      void $ compileFilesChanged sp gopts opts' [absFile] False mChanged (Just (sched, gen)) (Just (progressUI, progressState))\n              in runWatchFile gopts absFile sched runOnce\n        withTempDirOpts opts $ \\opts' _ ->\n          runWatch opts'\n\ndata WatchTrigger = WatchFull | WatchIncremental FilePath deriving (Eq, Show)\n\ndata FileStamp = FileStamp UTCTime Integer deriving (Eq, Show)\n\nreadFileStamp :: FilePath -> IO (Maybe FileStamp)\nreadFileStamp path = do\n    res <- try (do\n      exists <- doesFileExist path\n      if not exists\n        then return Nothing\n        else do\n          stampTime <- getModificationTime path\n          stampSize <- getFileSize path\n          return (Just (FileStamp stampTime stampSize))\n      ) :: IO (Either IOException (Maybe FileStamp))\n    case res of\n      Left _ -> return Nothing\n      Right stamp -> return stamp\n\nshouldTriggerFile :: IORef (M.Map FilePath FileStamp) -> FilePath -> IO Bool\nshouldTriggerFile stampsRef path = do\n    mstamp <- readFileStamp path\n    atomicModifyIORef' stampsRef $ \\stamps ->\n      case mstamp of\n        Nothing -> (M.delete path stamps, True)\n        Just stamp ->\n          case M.lookup path stamps of\n            Just old | old == stamp -> (stamps, False)\n            _ -> (M.insert path stamp stamps, True)\n\n-- | Translate watch triggers into optional path notifications.\ndispatchWatchTrigger :: (Maybe FilePath -> IO ()) -> WatchTrigger -> IO ()\ndispatchWatchTrigger notify trigger =\n    case trigger of\n      WatchFull -> notify Nothing\n      WatchIncremental path -> notify (Just path)\n\n-- | Classify project FS events into full or incremental rebuild triggers.\nactWatchTrigger :: FS.Event -> Maybe WatchTrigger\nactWatchTrigger ev =\n    case FS.eventIsDirectory ev of\n      FS.IsDirectory ->\n        case ev of\n          FS.Added{} -> Just WatchFull\n          FS.Removed{} -> Just WatchFull\n          FS.WatchedDirectoryRemoved{} -> Just WatchFull\n          FS.Unknown{} -> Just WatchFull\n          _ -> Nothing\n      FS.IsFile ->\n        if takeExtension (FS.eventPath ev) /= \".act\"\n          then Nothing\n          else case ev of\n                 FS.ModifiedAttributes{} -> Nothing\n                 FS.Added{} -> Just WatchFull\n                 FS.Removed{} -> Just WatchFull\n                 FS.WatchedDirectoryRemoved{} -> Just WatchFull\n                 FS.Unknown{} -> Just WatchFull\n                 _ -> Just (WatchIncremental (FS.eventPath ev))\n\n-- | Classify FS events for a specific file path.\nfileWatchTrigger :: FilePath -> FS.Event -> Maybe WatchTrigger\nfileWatchTrigger target ev =\n    let evPath = normalise (FS.eventPath ev)\n    in if evPath /= target\n         then Nothing\n         else case ev of\n                FS.ModifiedAttributes{} -> Nothing\n                _ -> Just (WatchIncremental (FS.eventPath ev))\n\n-- | Run the project watch loop and schedule compiles on events.\nrunWatchProject :: C.GlobalOptions\n                -> FilePath\n                -> FilePath\n                -> CompileScheduler\n                -> (Int -> Maybe [FilePath] -> IO ())\n                -> IO ()\nrunWatchProject gopts projDir srcRoot sched runOnce = do\n    stampsRef <- newIORef M.empty\n    let schedule mpath = void $ startCompile sched 0 $ \\gen ->\n          runOnce gen (fmap (:[]) mpath)\n        scheduleMaybe mpath =\n          case mpath of\n            Nothing -> schedule Nothing\n            Just path -> do\n              should <- shouldTriggerFile stampsRef path\n              when should (schedule (Just path))\n        onAct ev = forM_ (actWatchTrigger ev) $ \\trigger -> do\n          when (C.verbose gopts) $\n            putStrLn (\"[debug] watch event: \" ++ show ev ++ \" -> \" ++ show trigger)\n          dispatchWatchTrigger scheduleMaybe trigger\n        onRoot _ = schedule Nothing\n        isActEvent ev = isJust (actWatchTrigger ev)\n        isRootEvent ev =\n          let name = takeFileName (FS.eventPath ev)\n          in name == \"Build.act\"\n    FS.withManager $ \\mgr -> do\n      _ <- FS.watchTree mgr srcRoot isActEvent onAct\n      _ <- FS.watchDir mgr projDir isRootEvent onRoot\n      schedule Nothing\n      unless (C.quiet gopts) $\n        putStrLn (\"Watching for changes in \" ++ projDir)\n      forever $ threadDelay maxBound\n\n-- | Run the single-file watch loop and schedule compiles on events.\nrunWatchFile :: C.GlobalOptions\n             -> FilePath\n             -> CompileScheduler\n             -> (Int -> Maybe [FilePath] -> IO ())\n             -> IO ()\nrunWatchFile gopts absFile sched runOnce = do\n    stampsRef <- newIORef M.empty\n    let watchDir = takeDirectory absFile\n        watchPath = normalise absFile\n        isTarget ev = normalise (FS.eventPath ev) == watchPath\n        onEvent ev = do\n          forM_ (fileWatchTrigger watchPath ev) $ \\trigger ->\n            case trigger of\n              WatchFull -> dispatchWatchTrigger schedule trigger\n              WatchIncremental path -> do\n                should <- shouldTriggerFile stampsRef path\n                when should (dispatchWatchTrigger schedule trigger)\n        schedule mpath = void $ startCompile sched 0 $ \\gen ->\n          runOnce gen (fmap (:[]) mpath)\n    FS.withManager $ \\mgr -> do\n      _ <- FS.watchDir mgr watchDir isTarget onEvent\n      schedule Nothing\n      unless (C.quiet gopts) $\n        putStrLn (\"Watching for changes in \" ++ absFile)\n      forever $ threadDelay maxBound\n\n-- | Fetch dependencies for the current project without compiling.\nfetchCommand :: C.GlobalOptions -> IO ()\nfetchCommand gopts = do\n    paths <- loadProjectPaths defaultCompileOptions\n    res <- try (fetchDependencies gopts paths []) :: IO (Either ProjectError ())\n    case res of\n      Left (ProjectError msg) -> printErrorAndExit msg\n      Right () ->\n        unless (C.quiet gopts) $\n          putStrLn \"Dependencies fetched\"\n\ndata SigTarget\n    = SigSourceTarget ProjCtx A.ModName (Maybe A.Name) FilePath\n    | SigTyTarget A.ModName (Maybe A.Name) FilePath\n\nsigCommand :: C.GlobalOptions -> C.SigOptions -> IO ()\nsigCommand gopts sigOpts = do\n    let opts0 = (C.sigCompile sigOpts)\n          { C.skip_build = True\n          , C.only_build = False\n          , C.sigs = False\n          }\n        queryGopts = if C.verbose gopts then gopts else gopts { C.quiet = True }\n    paths0 <- loadProjectPaths opts0\n    depOverrides <- normalizeDepOverrides (projPath paths0) (C.dep_overrides opts0)\n    let opts = opts0 { C.dep_overrides = depOverrides }\n    paths <- loadProjectPaths opts\n    rootProj <- normalizePathSafe (projPath paths)\n    sysAbs <- normalizePathSafe (sysPath paths)\n    withProjectLockNotice queryGopts rootProj $ do\n      fetchDependencies queryGopts paths depOverrides\n      projMap <- discoverProjects queryGopts sysAbs rootProj depOverrides\n      target <- resolveSigTarget opts paths rootProj projMap (C.sigTarget sigOpts)\n      tyFile <- case target of\n        SigSourceTarget ctx mn _ srcPath ->\n          compileSigTarget gopts queryGopts opts paths rootProj sysAbs depOverrides ctx mn srcPath\n        SigTyTarget _ _ tyPath ->\n          return tyPath\n      case target of\n        SigSourceTarget _ mn mName _ -> printSigInterface paths mn mName tyFile\n        SigTyTarget mn mName _       -> printSigInterface paths mn mName tyFile\n\ncompileSigTarget :: C.GlobalOptions\n                 -> C.GlobalOptions\n                 -> C.CompileOptions\n                 -> Paths\n                 -> FilePath\n                 -> FilePath\n                 -> [(String, FilePath)]\n                 -> ProjCtx\n                 -> A.ModName\n                 -> FilePath\n                 -> IO FilePath\ncompileSigTarget gopts queryGopts opts paths rootProj sysAbs depOverrides targetCtx mn srcPath = do\n    buildStamp <- readBuildSpecStamp (projPath paths)\n    let sp = Source.diskSourceProvider\n        cctx = CompileContext\n          { ccOpts = opts\n          , ccDepOverrides = depOverrides\n          , ccPathsRoot = paths\n          , ccRootProj = rootProj\n          , ccSysAbs = sysAbs\n          , ccBuildStamp = buildStamp\n          }\n    plan <- prepareCompilePlanFromContext sp queryGopts cctx [srcPath] False Nothing\n    let cctx' = cpContext plan\n        opts' = ccOpts cctx'\n        callbacks = defaultCompileCallbacks\n          { ccOnDiagnostics = \\_ optsT diags -> printDiagnostics gopts optsT diags\n          , ccOnInfo = \\msg -> when (C.verbose gopts) $ putStrLn msg\n          , ccOnBackJob = \\_ -> return ()\n          }\n    compileRes <- compileTasks sp queryGopts opts' (ccPathsRoot cctx') (ccRootProj cctx') (cpNeededTasks plan) callbacks\n    case compileRes of\n      Left err -> printErrorAndExit (compileFailureMessage err)\n      Right (_, hadErrors) -> when hadErrors System.Exit.exitFailure\n    let targetCtx' = case M.lookup (projRoot targetCtx) (cpProjMap plan) of\n                       Just ctx -> ctx\n                       Nothing  -> targetCtx\n    targetPaths <- pathsForModule opts' (cpProjMap plan) targetCtx' mn\n    return (outBase targetPaths mn ++ \".ty\")\n\nresolveSigTarget :: C.CompileOptions -> Paths -> FilePath -> M.Map FilePath ProjCtx -> String -> IO SigTarget\nresolveSigTarget opts paths rootProj projMap rawTarget = do\n    parts <- parseSigTarget rawTarget\n    moduleIndex <- sigModuleIndex projMap rootProj\n    let fullMod = A.modName parts\n    case lookup fullMod moduleIndex of\n      Just (ctx, srcPath) ->\n        return (SigSourceTarget ctx fullMod Nothing srcPath)\n      Nothing -> do\n        mFullTy <- findSigTyFile tySearchPath fullMod\n        case mFullTy of\n          Just tyPath ->\n            return (SigTyTarget fullMod Nothing tyPath)\n          Nothing ->\n            resolveNameTarget parts moduleIndex\n  where\n    tySearchPath = sigTySearchPath opts paths rootProj projMap\n\n    resolveNameTarget parts moduleIndex\n      | length parts < 2 =\n          printErrorAndExit (\"Module not found: \" ++ rawTarget)\n      | otherwise = do\n          let modParts = init parts\n              namePart = last parts\n              mn = A.modName modParts\n              n = A.name namePart\n          case lookup mn moduleIndex of\n            Just (ctx, srcPath) ->\n              return (SigSourceTarget ctx mn (Just n) srcPath)\n            Nothing -> do\n              mTy <- findSigTyFile tySearchPath mn\n              case mTy of\n                Just tyPath ->\n                  return (SigTyTarget mn (Just n) tyPath)\n                Nothing ->\n                  printErrorAndExit (\"Module not found: \" ++ intercalate \".\" modParts\n                                     ++ \" (while resolving \" ++ rawTarget ++ \")\")\n\nparseSigTarget :: String -> IO [String]\nparseSigTarget rawTarget = do\n    let parts = splitOn \".\" rawTarget\n    if null rawTarget || any null parts\n      then printErrorAndExit (\"Invalid signature target: \" ++ rawTarget)\n      else return parts\n\nsigModuleIndex :: M.Map FilePath ProjCtx -> FilePath -> IO [(A.ModName, (ProjCtx, FilePath))]\nsigModuleIndex projMap rootProj = do\n    let roots = sigProjectSearchOrder projMap rootProj\n    fmap concat $ forM roots $ \\root ->\n      case M.lookup root projMap of\n        Nothing -> return []\n        Just ctx -> do\n          mods <- enumerateProjectModules ctx\n          return [ (mn, (ctx, srcPath)) | (srcPath, mn) <- mods ]\n\nsigProjectSearchOrder :: M.Map FilePath ProjCtx -> FilePath -> [FilePath]\nsigProjectSearchOrder projMap rootProj =\n    rootProj : snd (go (Data.Set.singleton rootProj) rootProj)\n  where\n    go seen root =\n      case M.lookup root projMap of\n        Nothing -> (seen, [])\n        Just ctx -> foldl' step (seen, []) (projDeps ctx)\n\n    step (seen, acc) (_, depRoot)\n      | Data.Set.member depRoot seen = (seen, acc)\n      | otherwise =\n          let seen' = Data.Set.insert depRoot seen\n              (seenNext, sub) = go seen' depRoot\n          in (seenNext, acc ++ [depRoot] ++ sub)\n\nsigTySearchPath :: C.CompileOptions -> Paths -> FilePath -> M.Map FilePath ProjCtx -> [FilePath]\nsigTySearchPath opts paths rootProj projMap =\n    case M.lookup rootProj projMap of\n      Just rootCtx -> searchPathForProject opts projMap rootCtx\n      Nothing      -> searchPath paths\n\nfindSigTyFile :: [FilePath] -> A.ModName -> IO (Maybe FilePath)\nfindSigTyFile = Acton.Env.findTyFile\n\nprintSigInterface :: Paths -> A.ModName -> Maybe A.Name -> FilePath -> IO ()\nprintSigInterface paths mn mName tyFile = do\n    exists <- doesFileExist tyFile\n    unless exists $\n      printErrorAndExit (\"Type interface not found for \" ++ modNameToString mn)\n    tyRes <- (try :: IO a -> IO (Either SomeException a)) $ InterfaceFiles.readFile tyFile\n    case tyRes of\n      Left err ->\n        printErrorAndExit (\"Could not read type interface for \" ++ modNameToString mn ++ \": \" ++ show err)\n      Right (ms, nmod, _, _, _, _, _, _, _, _, _, _) -> do\n        env0 <- Acton.Env.initEnv (sysTypes paths) False\n        let I.NModule imps te _ = nmod\n            envImports = foldr Acton.Env.addImport env0 ms\n            selected = case mName of\n              Nothing -> te\n              Just n  -> filter ((== n) . fst) te\n            envForPrint = case mName of\n              Nothing -> envImports\n              Just _  -> define te (setMod mn envImports)\n        case mName of\n          Just n | null selected ->\n            printErrorAndExit (\"Name not found: \" ++ modNameToString mn ++ \".\" ++ nameToString n)\n          _ ->\n            putStrLn (Acton.Types.prettySigs envForPrint mn imps selected)\n\n-- Show dependency tree with overrides applied from root pins\npkgShow :: C.GlobalOptions -> IO ()\npkgShow gopts = do\n    curDir <- getCurrentDirectory\n    _ <- requireProjectConfigPath curDir\n    spec <- loadBuildSpec curDir\n    let rootPins = BuildSpec.dependencies spec\n    unless (C.quiet gopts) $\n      putStrLn \"Dependency tree (hash overrides shown):\"\n    partial <- showTree rootPins curDir spec 0\n    when (partial && not (C.quiet gopts)) $\n      putStrLn \"Note: dependency tree is partial; some dependencies are not fetched yet. Run 'acton fetch'.\"\n  where\n    describeDep dep =\n      case BuildSpec.hash dep of\n        Just h -> \"hash=\" ++ h\n        Nothing -> case BuildSpec.path dep of\n                     Just p | not (null p) -> \"path=\" ++ p\n                     _ -> \"unversioned\"\n\n    isHashDep dep =\n      case BuildSpec.path dep of\n        Just p | not (null p) -> False\n        _ -> case BuildSpec.hash dep of\n               Just _ -> True\n               Nothing -> False\n\n    showTree pins dir spec depth = do\n      let deps = M.toList (BuildSpec.dependencies spec)\n      foldM (step pins dir depth) False deps\n\n    step pins dir depth partial (depName, dep) = do\n      let (chosen, conflict) =\n            case M.lookup depName pins of\n              Nothing -> (dep, False)\n              Just pinDep -> if pinDep == dep then (dep, False) else (pinDep, True)\n      depBase <- resolveDepBase dir depName chosen\n      depExists <- doesDirectoryExist depBase\n      let notFetched = isHashDep chosen && not depExists\n          prefix = replicate (2*depth) ' ' ++ \"- \"\n          suffix = if notFetched then \" (not fetched)\" else \"\"\n          line = prefix ++ depName ++ \" (\" ++ describeDep dep ++\n                 (if conflict then \" overridden -> \" ++ describeDep chosen else \"\") ++ \")\" ++ suffix\n      putStrLn line\n      if not depExists\n        then if notFetched\n          then return (partial || True)\n          else do\n            throwProjectError (\"Dependency \" ++ depName ++ \" path does not exist: \" ++ depBase ++ \"\\n\"\n                               ++ \"Hint: Local dependency paths must point to an Acton project root\\n\"\n                               ++ \"(directory with src/ and Build.act).\")\n        else do\n          spec' <- loadBuildSpec depBase\n          childPartial <- showTree pins depBase spec' (depth + 1)\n          return (partial || childPartial)\n\n-- Print documentation -------------------------------------------------------------------------------------------\n\n-- | Detect if we're running in a GUI environment\n-- On macOS: Always assume GUI unless SSH_CONNECTION is set\n-- On Linux: Check for DISPLAY variable\n-- On Windows: Always assume GUI\ndetectGuiEnvironment :: IO Bool\ndetectGuiEnvironment = do\n    case System.Info.os of\n        \"darwin\" -> do\n            -- On macOS, assume GUI unless we're in SSH session\n            sshConn <- lookupEnv \"SSH_CONNECTION\"\n            return $ isNothing sshConn\n        \"linux\" -> do\n            -- On Linux, check for DISPLAY\n            display <- lookupEnv \"DISPLAY\"\n            return $ isJust display && display /= Just \"\"\n        _ ->\n            -- Windows or other, assume GUI\n            return True\n\n-- | Generate and display documentation for Acton modules\n--\n-- Behavior summary:\n-- * No format flag + GUI environment → HTML to file + open browser\n-- * No format flag + terminal/SSH → ASCII to stdout\n-- * Explicit format (-t, --html, --md) → Always to stdout (unless -o specified)\n-- * -o flag → Always to that file\n-- * -o - → Always to stdout\n--\n-- GUI detection:\n-- * macOS: Assumes GUI unless SSH_CONNECTION is set\n-- * Linux: Checks for DISPLAY variable\n-- * Windows: Always assumes GUI\n--\n-- The command line parser just parses options without making behavior decisions.\n-- All logic is centralized here in printDocs for predictable, intuitive behavior.\nopenFileInGui :: FilePath -> IO ()\nopenFileInGui path = do\n    let openCmd = case System.Info.os of\n          \"darwin\" -> \"open\"\n          \"linux\" -> \"xdg-open\"\n          _ -> \"\"\n    unless (null openCmd) $\n      void $ system $ openCmd ++ \" \" ++ path\n\n-- | Generate and display documentation based on CLI options and environment.\nprintDocs :: C.GlobalOptions -> C.DocOptions -> IO ()\nprintDocs gopts opts = do\n    case C.inputFile opts of\n      \"\" -> do\n        -- No file provided - check what to do\n        case C.outputFormat opts of\n          Just C.AsciiFormat -> printErrorAndExit \"Terminal output requires a specific file. Usage: acton doc -t <file.act>\"\n          Just C.MarkdownFormat -> printErrorAndExit \"Markdown output requires a specific file. Usage: acton doc --md <file.act>\"\n          _ -> do\n              -- HTML or auto mode - check if we're in a project\n              curDir <- getCurrentDirectory\n              projDir <- findProjectDir curDir\n              case projDir of\n                Just _ -> do\n                  -- We're in a project - open the documentation index\n                  let indexFile = \"out/doc/index.html\"\n                  indexExists <- doesFileExist indexFile\n                  if indexExists\n                    then openFileInGui indexFile\n                    else printErrorAndExit \"No documentation found. Run 'acton build' first to generate documentation.\"\n                Nothing ->\n                  printErrorAndExit \"Not in an Acton project. Please specify a file to document.\"\n      filename -> do\n        let (fileBody,fileExt) = splitExtension $ takeFileName filename\n\n        case fileExt of\n          \".ty\" -> do\n            paths <- findPaths filename defaultCompileOptions\n            env0 <- Acton.Env.initEnv (sysTypes paths) False\n            Acton.Types.showTyFile env0 (modName paths) filename (C.verbose gopts)\n\n          \".act\" -> do\n            let modname = A.modName $ map (replace \".act\" \"\") $ splitOn \"/\" $ fileBody\n            paths <- findPaths filename defaultCompileOptions\n            parsedRes <- parseActFile defaultCompileOptions Source.diskSourceProvider modname filename Nothing\n            (_snap, parsed) <- case parsedRes of\n              Left diags -> do\n                printDiagnostics gopts defaultCompileOptions diags\n                System.Exit.exitFailure\n              Right res -> return res\n\n            -- Run compiler passes to get type information\n            env0 <- Acton.Env.initEnv (sysTypes paths) False\n            env <- Acton.Env.mkEnv (searchPath paths) env0 parsed\n            kchecked <- Acton.Kinds.check env parsed\n            (nmod, _, env', _) <- Acton.Types.reconstruct Nothing Nothing env kchecked\n            let I.NModule _ tenv mdoc = nmod\n\n            -- 1. If format is explicitly set (via -t, --html, --markdown), use it\n            -- 2. Otherwise, check if we're in a GUI environment\n            inGui <- detectGuiEnvironment\n            let format = case C.outputFormat opts of\n                    Just fmt -> fmt\n                    Nothing -> if inGui then C.HtmlFormat else C.AsciiFormat\n\n            docOutput <- case format of\n                C.HtmlFormat -> return $ DocP.printHtmlDoc nmod parsed\n                C.AsciiFormat -> do\n                    shouldColor <- useColor gopts\n                    return $ DocP.printAsciiDoc shouldColor nmod parsed\n                C.MarkdownFormat -> return $ DocP.printMdDoc nmod parsed\n\n            -- Handle output destination\n            case C.outputFile opts of\n              Just \"-\" ->\n                -- Explicit stdout\n                putStr docOutput\n              Just outFile -> do\n                -- Write to specified file\n                createDirectoryIfMissing True (takeDirectory outFile)\n                writeFile outFile docOutput\n                putStrLn $ \"Documentation written to: \" ++ outFile\n              Nothing\n                | isJust (C.outputFormat opts) || format == C.AsciiFormat ->\n                    -- Explicit format or auto ASCII: write to stdout\n                    putStr docOutput\n                | otherwise -> do\n                    -- Auto-detected HTML (DISPLAY set), write to file and open browser\n                    curDir <- getCurrentDirectory\n                    projDir <- findProjectDir curDir\n                    outputPath <- case projDir of\n                      Just _ -> do\n                        -- In project: use out/doc/\n                        let modPath = map (replace \".act\" \"\") $ splitOn \"/\" filename\n                            cleanPath = case modPath of\n                                \"src\":rest -> rest\n                                path -> path\n                            docFile = if null cleanPath\n                                      then \"out/doc/unnamed.html\"\n                                      else joinPath (\"out\" : \"doc\" : init cleanPath) </> last cleanPath <.> \"html\"\n                        return docFile\n                      Nothing ->\n                        -- Outside project: use temp file\n                        writeSystemTempFile \"acton-doc.html\" docOutput\n\n                    case projDir of\n                      Just _ -> do\n                        createDirectoryIfMissing True (takeDirectory outputPath)\n                        writeFile outputPath docOutput\n                      Nothing -> return ()\n\n                    putStrLn $ \"HTML documentation written to: \" ++ outputPath\n                    openFileInGui outputPath\n\n          _ -> printErrorAndExit (\"Unknown filetype: \" ++ filename)\n\n\n-- Compile Acton files ---------------------------------------------------------------------------------------------\n\n-- | Compute parallelism for compilation based on jobs or cores.\ncompileMaxParallel :: C.GlobalOptions -> IO Int\ncompileMaxParallel gopts = do\n    nCaps <- getNumCapabilities\n    return (max 1 (if C.jobs gopts > 0 then C.jobs gopts else nCaps))\n\n-- | Compile a set of files in a single-shot build.\ncompileFiles :: Source.SourceProvider -> C.GlobalOptions -> C.CompileOptions -> [String] -> Bool -> IO ()\ncompileFiles sp gopts opts srcFiles allowPrune =\n    void $ compileFilesChanged sp gopts opts srcFiles allowPrune Nothing Nothing Nothing\n\n-- | Compile with optional change set, wiring progress UI and back jobs.\ncompileFilesChanged :: Source.SourceProvider\n                    -> C.GlobalOptions\n                    -> C.CompileOptions\n                    -> [String]\n                    -> Bool\n                    -> Maybe [FilePath]\n                    -> Maybe (CompileScheduler, Int)\n                    -> Maybe (ProgressUI, ProgressState)\n                    -> IO Bool\ncompileFilesChanged sp gopts opts srcFiles allowPrune mChangedPaths mSched mProgress = do\n    maxParallel <- compileMaxParallel gopts\n    (progressUI, progressState) <- case mProgress of\n      Just ps -> return ps\n      Nothing -> do\n        ui <- initProgressUI gopts maxParallel\n        st <- newProgressState\n        return (ui, st)\n    let logLine = progressLogLine progressUI\n    (sched, gen) <- case mSched of\n      Just sg -> return sg\n      Nothing -> do\n        sched' <- newCompileScheduler gopts maxParallel\n        return (sched', 0)\n    let cleanupProgress = whenCurrentGen sched gen (progressReset progressUI progressState)\n    cleanupProgress\n    let runCompile = do\n          sp' <- overlayChangedPaths sp mChangedPaths\n          planRes <- try $\n            prepareCompilePlan sp' gopts sched opts srcFiles allowPrune mChangedPaths\n          let reportPlanError (ProjectError msg) = do\n                if C.watch opts\n                  then logLine msg\n                  else printErrorAndExit msg\n                return True\n              runPlan plan = do\n                let cctx = cpContext plan\n                    opts' = ccOpts cctx\n                    watchMode = C.watch opts'\n                cliHooks <- initCliCompileHooks progressUI progressState gopts sched gen plan\n                let clearProgress = whenCurrentGen sched gen (cchClearProgress cliHooks)\n                    finalizeCompile onError = do\n                      clearProgress\n                      onError\n                      return True\n                    reportCompileError msg =\n                      finalizeCompile $\n                        if watchMode\n                          then logLine msg\n                          else printErrorAndExit msg\n                    reportCompileErrors =\n                      finalizeCompile $\n                        unless watchMode System.Exit.exitFailure\n                compileRes <- runCompilePlan sp gopts plan sched gen (cchHooks cliHooks)\n                case compileRes of\n                  Left err ->\n                    reportCompileError (compileFailureMessage err)\n                  Right (env, hadErrors) -> do\n                    backFailure <-\n                      if C.only_build opts'\n                        then return Nothing\n                        else backQueueWait (csBackQueue sched) gen\n                    case backFailure of\n                      Just failure ->\n                        reportCompileError (backPassFailureMessage failure)\n                      Nothing ->\n                        if hadErrors\n                          then reportCompileErrors\n                          else do\n                            clearProgress\n                            whenCurrentGen sched gen (runCliPostCompile cliHooks gopts plan env)\n                            return False\n          either reportPlanError runPlan planRes\n    runCompile `finally` cleanupProgress\n\noverlayChangedPaths :: Source.SourceProvider -> Maybe [FilePath] -> IO Source.SourceProvider\noverlayChangedPaths sp mPaths = do\n    case mPaths of\n      Nothing -> return sp\n      Just paths -> do\n        overlays <- catMaybes <$> mapM readOverlay paths\n        let overlayMap = M.fromList overlays\n        return sp\n          { Source.spReadOverlay = \\path -> do\n              existing <- Source.spReadOverlay sp path\n              case existing of\n                Just snap -> return (Just snap)\n                Nothing -> return (M.lookup (normalise path) overlayMap)\n          }\n  where\n    readOverlay path = do\n      res <- (try :: IO a -> IO (Either SomeException a)) (Source.spReadFile sp path)\n      case res of\n        Left _ -> return Nothing\n        Right snap ->\n          return (Just (normalise path, snap { Source.ssIsOverlay = True }))\n\ndata CliCompileHooks = CliCompileHooks\n  { cchHooks :: CompileHooks\n  , cchLogLine :: String -> IO ()\n  , cchClearProgress :: IO ()\n  , cchFinalStart :: IO ()\n  , cchFinalDone :: Maybe TimeSpec -> IO ()\n  , cchProgressUI :: ProgressUI\n  }\n\n-- | Build compile hooks and state for CLI progress and completion logs.\ninitCliCompileHooks :: ProgressUI\n                    -> ProgressState\n                    -> C.GlobalOptions\n                    -> CompileScheduler\n                    -> Int\n                    -> CompilePlan\n                    -> IO CliCompileHooks\ninitCliCompileHooks progressUI progressState gopts sched gen plan = do\n    let neededTasks = cpNeededTasks plan\n        rootProj = ccRootProj (cpContext plan)\n        optsPlan = ccOpts (cpContext plan)\n        isBuiltinTask t = tkMod (gtKey t) == A.modName [\"__builtin__\"]\n        parseNeeded t =\n          case gtTask t of\n            ParseTask{} -> not (isBuiltinTask t) && not (C.only_build optsPlan)\n            _ -> False\n    sizeEntries <- forM neededTasks $ \\t -> do\n      let key = gtKey t\n          path = srcFile (gtPaths t) (tkMod key)\n      exists <- doesFileExist path\n      sz <- if exists then getFileSize path else return 0\n      return (key, sz)\n    progressRef <- newIORef (0 :: Double)\n    marksRef <- newIORef (M.empty :: M.Map TaskKey (Double, Double, Bool))\n    -- sizeMap is used for the progress bar indicator to determine how much a\n    -- modules compilation should contribute to the overall progress. We use\n    -- file size as a heuristic for this, but if all sizes are zero (e.g. due to\n    -- missing files or all files being empty), we fall back to equal weighting\n    -- to avoid division by zero. Since our compilation is split into front and\n    -- back passes, we also compute a share for each task that determines how\n    -- much of the total progress it should contribute to, which is used to give\n    -- a more accurate progress indication during the compile.\n    let sizeMap = M.fromList sizeEntries\n        totalSize = sum (map snd sizeEntries)\n        useEqual = totalSize <= 0\n        totalWeight :: Double\n        totalWeight =\n          if useEqual\n            then fromIntegral (max 1 (length neededTasks))\n            else fromIntegral totalSize\n        weightFor key =\n          if useEqual\n            then 1 / totalWeight\n            else fromIntegral (M.findWithDefault 0 key sizeMap) / totalWeight\n        compilePhaseTotal = 85.0\n        parseRatio = 0.1\n        frontRatio = 0.6\n        backRatio = 0.3\n        totalPhaseWeight =\n          sum\n            [ weightFor (gtKey t) * (frontRatio + backRatio + if parseNeeded t then parseRatio else 0)\n            | t <- neededTasks\n            ]\n        shareForPhase t ratio =\n          if totalPhaseWeight <= 0\n            then 0\n            else compilePhaseTotal * weightFor (gtKey t) * ratio / totalPhaseWeight\n        shareMap =\n          M.fromList\n            [ (gtKey t, (shareForPhase t (if parseNeeded t then parseRatio else 0)\n                        , shareForPhase t frontRatio\n                        , shareForPhase t backRatio))\n            | t <- neededTasks\n            ]\n    let gate = whenCurrentGen sched gen\n        logLine msg = gate $ do\n          progressLogLine progressUI msg\n        logRendered render = gate $ do\n          if puWidthAware progressUI\n            then do\n              (_, cols) <- termSizeRead (puTermSize progressUI)\n              progressLogLine progressUI (render (safeLiveWidth cols))\n            else progressLogLine progressUI (render plainLogWidth)\n        logDiagnostics optsT diags =\n          gate (progressWithLog progressUI (printDiagnostics gopts optsT diags))\n        termProgress = puTermProgress progressUI\n        termEnabled = termProgressEnabled termProgress\n        modLabel mn = modNameToString mn\n        timeSep = \"    \"\n        parseDoneStatus = \"Parse done\"\n        frontDoneStatus = \"Type check done\"\n        backDoneStatus = \"Compilation done\"\n        backFailStatus msg = \"Compilation failed: \" ++ msg\n        finalDoneStatus = \"Final compilation done\"\n        projMap = cpProjMap plan\n        depNameMap =\n          let rootDeps = maybe [] projDeps (M.lookup rootProj projMap)\n              otherDeps = concatMap projDeps (M.elems projMap)\n          in M.fromListWith (\\_ old -> old) [ (p, n) | (n, p) <- rootDeps ++ otherDeps ]\n        projectLabelFor proj\n          | proj == rootProj = \"\"\n          | otherwise =\n              case M.lookup proj depNameMap of\n                Just name -> name\n                Nothing -> projectLabel rootProj proj\n        projectModuleLabel proj mn =\n          case projectLabelFor proj of\n            \"\" -> modLabel mn\n            label -> label ++ \".\" ++ modLabel mn\n        labelWidth = maximum (0 : [ length (projectModuleLabel (tkProj (gtKey t)) (tkMod (gtKey t))) | t <- neededTasks ])\n        statusWidth = 68\n        nameWidth = labelWidth + 2 + statusWidth\n        timePadWidth = nameWidth + length timeSep\n        timerMinWidth = length \"999.999 s\"\n        plainLogWidth = timePadWidth + timerMinWidth\n        detailStmtIndentWide = replicate 5 ' '\n        detailBindsIndentWide = replicate 7 ' '\n        detailStmtIndentNarrow = \"  \"\n        detailBindsIndentNarrow = \"    \"\n        plainDoneIndent = replicate 3 ' '\n        plainStatusColumns modLbl status =\n          padRight labelWidth modLbl\n          ++ \"  \"\n          ++ padRight statusWidth (abbreviateRight statusWidth status)\n        plainDoneTimedLine modLbl status t =\n          padRight timePadWidth (plainDoneIndent ++ plainStatusColumns modLbl status)\n          ++ fmtTimePrecise t\n        plainDoneLine modLbl status =\n          plainDoneIndent ++ plainStatusColumns modLbl status\n        pickBestLine candidates =\n          case foldl' betterCandidate Nothing candidates of\n            Just (_, line) -> line\n            Nothing -> \"\"\n        betterCandidate best Nothing = best\n        betterCandidate Nothing cand = cand\n        betterCandidate best@(Just (bestScore, _)) cand@(Just (candScore, _))\n          | candScore > bestScore = cand\n          | otherwise = best\n        buildLineCandidate width preserveBlankLabel modLbl statusRender timerRank timerWidth timer =\n          let doneIndent = replicate (progressPrefixWidth width) ' '\n              timerCols = if null timer then 0 else 1 + timerWidth\n              bodyWidth = max 0 (width - length doneIndent - timerCols)\n              layout = fitBuildLineLayout bodyWidth labelWidth statusWidth preserveBlankLabel modLbl statusRender\n              body = bllText layout\n              line = doneIndent ++ body ++ if null timer then \"\" else \" \" ++ padLeft timerWidth timer\n              score =\n                ( if bllAligned layout then 1 :: Int else 0\n                , if bllHasStatus layout then 1 :: Int else 0\n                , bllLabelCols layout\n                , timerRank\n                )\n          in if null body || length line > width\n               then Nothing\n               else Just (score, line)\n        doneStatusLine width modLbl statusRender shortStatus mt =\n          let preciseTimer = maybe \"\" fmtTimePrecise mt\n              compactTimer = maybe \"\" fmtTimeCompact mt\n              timerWidth = max timerMinWidth (length preciseTimer)\n              fullRenderer budget =\n                case statusRender budget of\n                  Just status\n                    | length status <= budget -> Just status\n                  _ -> Nothing\n              shortRenderer =\n                staticStatusRenderer shortStatus shortStatus\n              preserveBlankLabel = null modLbl\n          in pickBestLine\n               [ buildLineCandidate width preserveBlankLabel modLbl fullRenderer 2 timerWidth preciseTimer\n               , buildLineCandidate width preserveBlankLabel modLbl fullRenderer 1 timerWidth compactTimer\n               , buildLineCandidate width preserveBlankLabel modLbl fullRenderer 0 0 \"\"\n               , buildLineCandidate width preserveBlankLabel modLbl shortRenderer 1 timerWidth compactTimer\n               , buildLineCandidate width preserveBlankLabel modLbl shortRenderer 0 0 \"\"\n               ]\n        detailLine width indentWide indentNarrow msg =\n          let wide = indentWide ++ msg\n          in if width >= length wide then wide else indentNarrow ++ msg\n        detailTimedLine width indentWide indentNarrow msg t =\n          let precise = fmtTimePrecise t\n              wideBase = indentWide ++ msg\n              wideLine = padRight timePadWidth wideBase ++ precise\n          in if width >= length wideLine\n               then wideLine\n               else indentNarrow ++ msg ++ \" \" ++ fmtTimeCompact t\n        frontTimingLine ft =\n          \"Front timing: env \" ++ fmtTimePrecise (ftEnv ft)\n          ++ \", kinds \" ++ fmtTimePrecise (ftKinds ft)\n          ++ \", types \" ++ fmtTimePrecise (ftTypes ft)\n        typeStmtTimingLine st =\n          \"Type stmt \" ++ show (tstCompleted st) ++ \"/\" ++ show (tstTotal st)\n        typeStmtBindsLine st =\n          \"binds: \" ++ intercalate \", \" (tstNames st)\n        inferredSignatureLine sig =\n          \"Non-total inferred signature: \" ++ intercalate \", \" (isigNames sig)\n        backTimingLine bt =\n          \"Back timing: normalize \" ++ fmtTimePrecise (btNormalize bt)\n          ++ \", deactorize \" ++ fmtTimePrecise (btDeactorize bt)\n          ++ \", cps \" ++ fmtTimePrecise (btCPS bt)\n          ++ \", llift \" ++ fmtTimePrecise (btLLift bt)\n          ++ \", boxing \" ++ fmtTimePrecise (btBoxing bt)\n          ++ \", codegen \" ++ fmtTimePrecise (btCodeGen bt)\n          ++ maybe \"\" (\\t -> \", write \" ++ fmtTimePrecise t) (btWriteCode bt)\n        parseDoneRenderer =\n          staticStatusRenderer parseDoneStatus \"Parsed\"\n        frontDoneRenderer =\n          staticStatusRenderer frontDoneStatus \"Typed\"\n        backDoneRenderer =\n          staticStatusRenderer backDoneStatus \"Built\"\n        backFailRenderer msg =\n          \\budget ->\n            if budget < 10\n              then Nothing\n              else Just (abbreviateRight budget (backFailStatus msg))\n        finalDoneRenderer =\n          staticStatusRenderer finalDoneStatus \"Final\"\n        parseDoneLine width proj mn t =\n          if puWidthAware progressUI\n            then doneStatusLine width (projectModuleLabel proj mn) parseDoneRenderer \"Parsed\" (Just t)\n            else plainDoneTimedLine (projectModuleLabel proj mn) parseDoneStatus t\n        frontDoneLine width proj mn t =\n          if puWidthAware progressUI\n            then doneStatusLine width (projectModuleLabel proj mn) frontDoneRenderer \"Typed\" (Just t)\n            else plainDoneTimedLine (projectModuleLabel proj mn) frontDoneStatus t\n        backDoneLine width proj mn mt =\n          if puWidthAware progressUI\n            then\n              case mt of\n                Just t -> doneStatusLine width (projectModuleLabel proj mn) backDoneRenderer \"Built\" (Just t)\n                Nothing -> doneStatusLine width (projectModuleLabel proj mn) backDoneRenderer \"Built\" Nothing\n            else\n              case mt of\n                Just t -> plainDoneTimedLine (projectModuleLabel proj mn) backDoneStatus t\n                Nothing -> plainDoneLine (projectModuleLabel proj mn) backDoneStatus\n        backFailLine width proj mn msg =\n          if puWidthAware progressUI\n            then doneStatusLine width (projectModuleLabel proj mn) (backFailRenderer msg) \"Failed\" Nothing\n            else plainDoneLine (projectModuleLabel proj mn) (backFailStatus msg)\n        finalDoneLine width t =\n          if puWidthAware progressUI\n            then doneStatusLine width \"\" finalDoneRenderer \"Final\" (Just t)\n            else plainDoneTimedLine \"\" finalDoneStatus t\n        renderProjectLine proj mn statusRender width =\n          let modLbl = projectModuleLabel proj mn\n          in fitBuildLineLayout width labelWidth statusWidth False modLbl statusRender\n        parseActiveLine proj mn =\n          renderProjectLine proj mn (staticStatusRenderer \"Parsing\" \"Parse\")\n        parseProgressLine proj mn p =\n          renderProjectLine proj mn (parseStatusRenderer p)\n        frontInitialLine proj mn =\n          renderProjectLine proj mn (staticStatusRenderer \"Kinds check\" \"Kinds\")\n        backActiveLine proj mn =\n          renderProjectLine proj mn (staticStatusRenderer \"Back passes\" \"Back\")\n        finalActiveLine width =\n          fitBuildLineLayout width labelWidth statusWidth True \"\" (staticStatusRenderer \"Final compilation\" \"Final\")\n        clamp01 x = max 0 (min 1 x)\n        parseProgressRatio p =\n          let total = ppTotal p\n          in if total <= 0\n               then 1\n               else clamp01 (fromIntegral (ppCompleted p) / fromIntegral total)\n        progressRatio p =\n          let total = fppTotal p\n          in if total <= 0\n               then 1\n               else clamp01 (fromIntegral (fppCompleted p) / fromIntegral total)\n        frontPassFraction p =\n          case fppPass p of\n            FrontPassKinds -> 0.10 * progressRatio p\n            FrontPassTypes -> 0.10 + 0.90 * progressRatio p\n        frontStatusRenderer p budget\n          | budget < 10 = Nothing\n          | otherwise =\n              let total = max 0 (fppTotal p)\n                  completed = min total (max 0 (fppCompleted p))\n                  countPart\n                    | total > 0 = \" \" ++ show completed ++ \"/\" ++ show total\n                    | otherwise = \"\"\n                  compact =\n                    let base = if total > 0 then \"Types\" ++ countPart else \"Types\"\n                    in if length base <= budget then base else \"Types\"\n                  fullTypeStatus mCurrent =\n                    let prefix = \"Type checking \"\n                        staticLen = length prefix + length countPart\n                    in if staticLen < budget\n                         then case mCurrent of\n                                Just nm -> prefix ++ abbreviateRight (budget - staticLen) nm ++ countPart\n                                Nothing -> \"Type checking\" ++ countPart\n                         else compact\n              in case fppPass p of\n                   FrontPassKinds -> staticStatusRenderer \"Kinds check\" \"Kinds\" budget\n                   FrontPassTypes -> Just (fullTypeStatus (fppCurrent p))\n        parseStatusRenderer p budget\n          | budget < 10 = Nothing\n          | otherwise =\n              let pct = floor (100 * parseProgressRatio p :: Double)\n                  full = \"Parsing \" ++ show pct ++ \"%\"\n                  short = \"Parse \" ++ show pct ++ \"%\"\n              in if length full <= budget\n                   then Just full\n                   else if length short <= budget\n                          then Just short\n                          else Just (show pct ++ \"%\")\n        frontProgressLine proj mn p =\n          renderProjectLine proj mn (frontStatusRenderer p)\n        finalKey = TaskKey rootProj (A.modName [\"__final__\"])\n        withTerm action = when termEnabled $ gate (withProgressLock progressUI action)\n        setPercent pct = withTerm (termProgressPercent termProgress pct)\n        addProgress delta =\n          when (termEnabled && delta > 0) $ do\n            new <- atomicModifyIORef' progressRef (\\x -> let x' = min compilePhaseTotal (x + delta) in (x', x'))\n            setPercent (floor new)\n        shareFor key = M.findWithDefault (0, 0, 0) key shareMap\n        creditParseTo key parseFrac = gate $ do\n          let (parseShare, _, _) = shareFor key\n          delta <- atomicModifyIORef' marksRef $ \\m ->\n            let (parseDoneFrac, frontDoneFrac, backDone) = M.findWithDefault (0, 0, False) key m\n                parseDoneFrac' = max parseDoneFrac (clamp01 parseFrac)\n                deltaFrac = max 0 (parseDoneFrac' - parseDoneFrac)\n            in (M.insert key (parseDoneFrac', frontDoneFrac, backDone) m, parseShare * deltaFrac)\n          addProgress delta\n        creditFrontTo key frontFrac = gate $ do\n          let (_, frontShare, _) = shareFor key\n          delta <- atomicModifyIORef' marksRef $ \\m ->\n            let (parseDoneFrac, frontDoneFrac, backDone) = M.findWithDefault (0, 0, False) key m\n                frontDoneFrac' = max frontDoneFrac (clamp01 frontFrac)\n                deltaFrac = max 0 (frontDoneFrac' - frontDoneFrac)\n            in (M.insert key (parseDoneFrac, frontDoneFrac', backDone) m, frontShare * deltaFrac)\n          addProgress delta\n        creditParse key = creditParseTo key 1\n        creditParseProgress key p = creditParseTo key (parseProgressRatio p)\n        creditFront key = creditFrontTo key 1\n        creditFrontProgress key p = creditFrontTo key (frontPassFraction p)\n        creditBack key = gate $ do\n          let (_, _, backShare) = shareFor key\n          delta <- atomicModifyIORef' marksRef $ \\m ->\n            let (parseDoneFrac, frontDoneFrac, backDone) = M.findWithDefault (0, 0, False) key m\n            in if backDone\n                 then (m, 0)\n                 else (M.insert key (parseDoneFrac, frontDoneFrac, True) m, backShare)\n          addProgress delta\n    setPercent 0\n    let backJobKey job =\n          TaskKey (projPath (bjPaths job)) (A.modname (biTypedMod (bjInput job)))\n        onBackStart job =\n          let proj = projPath (bjPaths job)\n              mn = A.modname (biTypedMod (bjInput job))\n          in do\n            gate (progressStartTask progressUI progressState (backJobKey job) (backActiveLine proj mn) (Just 0))\n        onBackDone job result = do\n          gate (progressDoneTask progressUI progressState (backJobKey job))\n          creditBack (backJobKey job)\n          when (not (quiet gopts optsPlan)) $\n            case result of\n              BackJobOk mtime mtiming -> do\n                logRendered (\\cols -> backDoneLine cols (projPath (bjPaths job)) (A.modname (biTypedMod (bjInput job))) mtime)\n                when (C.timing gopts) $\n                  forM_ mtiming $ \\bt ->\n                    logRendered (\\cols -> detailLine cols detailStmtIndentWide detailStmtIndentNarrow (backTimingLine bt))\n              BackJobFailed failure ->\n                logRendered (\\cols -> backFailLine cols (projPath (bjPaths job))\n                                                    (A.modname (biTypedMod (bjInput job)))\n                                                    (bpfMessage failure))\n        hooks = defaultCompileHooks\n          { chOnDiagnostics = \\t optsT diags -> do\n              gate (progressDoneTask progressUI progressState (gtKey t))\n              logDiagnostics optsT diags\n          , chOnParseStart = \\t ->\n              let key = gtKey t\n                  proj = tkProj key\n                  mn = tkMod key\n              in gate (progressStartTask progressUI progressState key (parseActiveLine proj mn) (Just 0))\n          , chOnParseProgress = \\t p ->\n              let key = gtKey t\n                  proj = tkProj key\n                  mn = tkMod key\n              in do\n                gate (progressUpdateTask progressUI progressState key (parseProgressLine proj mn p) (Just (parseProgressRatio p)))\n                creditParseProgress key p\n          , chOnParseDone = \\t mtime -> do\n              gate (progressDoneTask progressUI progressState (gtKey t))\n              creditParse (gtKey t)\n              when (not (quiet gopts optsPlan)) $\n                forM_ mtime $ \\tParse -> do\n                  let proj = tkProj (gtKey t)\n                      mn = tkMod (gtKey t)\n                  logRendered (\\cols -> parseDoneLine cols proj mn tParse)\n          , chOnFrontResult = \\t fr -> do\n              forM_ (frFrontTime fr) $ \\tFront -> do\n                let proj = tkProj (gtKey t)\n                    mn = tkMod (gtKey t)\n                logRendered (\\cols -> frontDoneLine cols proj mn tFront)\n                when (C.timing gopts) $\n                  forM_ (frFrontTiming fr) $ \\ft -> do\n                    logRendered (\\cols -> detailLine cols detailStmtIndentWide detailStmtIndentNarrow (frontTimingLine ft))\n                    forM_ (ftTypeStmtTimings ft) $ \\st -> do\n                      logRendered (\\cols -> detailTimedLine cols detailStmtIndentWide detailStmtIndentNarrow (typeStmtTimingLine st) (tstTime st))\n                      logRendered (\\cols -> detailLine cols detailBindsIndentWide detailBindsIndentNarrow (typeStmtBindsLine st))\n                when (C.timing gopts || C.verbose gopts) $\n                  forM_ (frInferredSigs fr) $ \\sig -> do\n                    logRendered (\\cols -> detailLine cols detailStmtIndentWide detailStmtIndentNarrow (inferredSignatureLine sig))\n                    forM_ (lines (isigSignature sig)) $ \\line ->\n                      logRendered (\\cols -> detailLine cols detailBindsIndentWide detailBindsIndentNarrow line)\n              case frBackJob fr of\n                Nothing -> creditBack (gtKey t)\n                Just _ -> return ()\n          , chOnFrontStart = \\t ->\n              let key = gtKey t\n                  proj = tkProj key\n                  mn = tkMod key\n              in gate (progressStartTask progressUI progressState key (frontInitialLine proj mn) (Just 0))\n          , chOnFrontProgress = \\t p ->\n              let key = gtKey t\n                  proj = tkProj key\n                  mn = tkMod key\n              in do\n                gate (progressUpdateTask progressUI progressState key (frontProgressLine proj mn p) (Just (frontPassFraction p)))\n                creditFrontProgress key p\n          , chOnFrontDone = \\t -> do\n              gate (progressDoneTask progressUI progressState (gtKey t))\n              creditFront (gtKey t)\n          , chOnBackQueued = \\_ _ -> return ()\n          , chOnBackStart = onBackStart\n          , chOnBackDone = onBackDone\n          , chOnInfo = logLine\n          }\n        onFinalStart = do\n          gate (progressStartTask progressUI progressState finalKey finalActiveLine Nothing)\n          setPercent 85\n        onFinalDone mtime = do\n          gate (progressDoneTask progressUI progressState finalKey)\n          setPercent 100\n          forM_ mtime $ \\tFinal ->\n            when (not (quiet gopts optsPlan)) $\n              logRendered (\\cols -> finalDoneLine cols tFinal)\n    return CliCompileHooks\n      { cchHooks = hooks\n      , cchLogLine = logLine\n      , cchClearProgress = progressReset progressUI progressState\n      , cchFinalStart = onFinalStart\n      , cchFinalDone = onFinalDone\n      , cchProgressUI = progressUI\n      }\n\n-- | Run CLI-only post-compile steps.\nrunCliPostCompile :: CliCompileHooks\n                  -> C.GlobalOptions\n                  -> CompilePlan\n                  -> Acton.Env.Env0\n                  -> IO ()\nrunCliPostCompile cliHooks gopts plan env = do\n    let logLine = cchLogLine cliHooks\n    let cctx = cpContext plan\n        opts' = ccOpts cctx\n        pathsRoot = ccPathsRoot cctx\n        rootProj = ccRootProj cctx\n        sysAbs = ccSysAbs cctx\n        rootTasks = cpRootTasks plan\n        rootPins = cpRootPins plan\n        allowPrune' = cpAllowPrune plan\n        globalTasks = cpGlobalTasks plan\n        neededTasks = cpNeededTasks plan\n        projMap = cpProjMap plan\n        sysRoot = addTrailingPathSeparator sysAbs\n    rootSpec <- case M.lookup rootProj projMap of\n                  Just ctx -> return (projBuildSpec ctx)\n                  Nothing -> throwProjectError (\"Missing root project context for \" ++ rootProj)\n    let rootParts = splitOn \".\" (C.root opts')\n        rootMod   = init rootParts\n        guessMod  = if length rootParts == 1 then modName pathsRoot else A.modName rootMod\n        binTask   = BinTask False (prstr guessMod) (A.GName guessMod (A.name $ last rootParts)) False\n        preBinTasks\n          | null (C.root opts') = map (\\t -> BinTask True (modNameToString (name t)) (A.GName (name t) (A.name \"main\")) False) rootTasks\n          | otherwise        = [binTask]\n        preTestBinTasks = map (\\t -> BinTask True (modNameToString (name t)) (A.GName (name t) (A.name \"test_main\")) True) rootTasks\n        selectedTasksByProj = selectedTasksWithProvidersByProj globalTasks neededTasks\n        depModuleOptsByProj = depModuleOptionsByProj selectedTasksByProj projMap\n        rootModuleEntries = selectedCSourceEntriesForProj rootProj (M.findWithDefault [] rootProj selectedTasksByProj)\n        rootDepModuleOpts = M.findWithDefault M.empty rootProj depModuleOptsByProj\n        rootDepPathOverrides = projectDepPathOverrides projMap rootProj\n    -- Generate build.zig(.zon) for dependencies too, to satisfy Zig builder links.\n    let projKeys = Data.Set.fromList (map (tkProj . gtKey) globalTasks)\n    forM_ (Data.Set.toList projKeys) $ \\p -> do\n      let isRootProj = p == rootProj\n          isSysProj  = p == sysAbs || sysRoot `isPrefixOf` p\n      unless (isRootProj || isSysProj) $\n        case M.lookup p projMap of\n          Just pctx -> do\n            when (C.verbose gopts) $\n              logLine (\"Generating build.zig for dependency project \" ++ p)\n            dummyPaths <- pathsForModule opts' projMap pctx (A.modName [\"__gen_build__\"])\n            let depOpts = M.findWithDefault M.empty p depModuleOptsByProj\n                depPathOverrides = projectDepPathOverrides projMap p\n            genBuildZigFiles (projBuildSpec pctx) rootPins (ccDepOverrides cctx) dummyPaths depOpts depPathOverrides\n          Nothing -> return ()\n    let runFinal action = do\n          cchFinalStart cliHooks\n          mtime <- action `onException` cchFinalDone cliHooks Nothing\n          cchFinalDone cliHooks (Just mtime)\n    if C.skip_build opts'\n      then\n        logLine \"  Skipping final build step\"\n      else\n        if C.test opts'\n          then do\n            testBinTasks <- catMaybes <$> mapM (filterMainActor env pathsRoot) preTestBinTasks\n            unless (altOutput opts') $\n              runFinal (compileBins gopts opts' pathsRoot env rootSpec rootTasks testBinTasks allowPrune' rootModuleEntries rootDepModuleOpts rootDepPathOverrides (Just (cchProgressUI cliHooks)))\n          else do\n            unless (altOutput opts') $\n              runFinal (compileBins gopts opts' pathsRoot env rootSpec rootTasks preBinTasks allowPrune' rootModuleEntries rootDepModuleOpts rootDepPathOverrides (Just (cchProgressUI cliHooks)))\n-- Generate documentation index for a project build by reading module names and\n-- docstrings from cached .ty headers or source headers.\ngenerateProjectDocIndex :: Source.SourceProvider -> C.GlobalOptions -> C.CompileOptions -> Paths -> [String] -> IO ()\ngenerateProjectDocIndex sp gopts opts paths srcFiles = do\n    unless (C.skip_build opts || C.only_build opts || isTmp paths) $ do\n        let docDir = joinPath [projPath paths, \"out\", \"doc\"]\n        createDirectoryIfMissing True docDir\n        entries <- catMaybes <$> forM srcFiles (\\f -> do\n                     p <- findPaths f opts\n                     readModuleDoc sp gopts opts p f)\n        DocP.generateDocIndex docDir entries\n\n-- | Relative C source paths for selected tasks in one project.\nselectedCSourceEntriesForProj :: FilePath -> [GlobalTask] -> [FilePath]\nselectedCSourceEntriesForProj proj tasks =\n    nub\n      [ collapseDots (makeRelativeOrAbsolute proj (outBase (gtPaths t) (name (gtTask t)) ++ \".c\"))\n      | t <- tasks\n      ]\n\n-- | For incremental builds, include providers so link inputs stay complete.\nselectedTasksWithProvidersByProj :: [GlobalTask] -> [GlobalTask] -> M.Map FilePath [GlobalTask]\nselectedTasksWithProvidersByProj globalTasks neededTasks =\n    M.fromListWith (++) [ (tkProj (gtKey t), [t]) | t <- selectedTasks ]\n  where\n    taskKeys = Data.Set.fromList (map gtKey globalTasks)\n    depMap = M.fromList\n      [ (gtKey t, Data.Set.fromList (filter (`Data.Set.member` taskKeys) (M.elems (gtImportProviders t))))\n      | t <- globalTasks\n      ]\n    start = Data.Set.fromList (map gtKey neededTasks)\n    selectedKeys = reachable depMap start\n    selectedTasks = [ t | t <- globalTasks, Data.Set.member (gtKey t) selectedKeys ]\n\n    reachable deps startKeys = go (Data.Set.toList startKeys) Data.Set.empty\n      where\n        go [] seen = seen\n        go (k:ks) seen =\n          if Data.Set.member k seen\n            then go ks seen\n            else\n              let ds = Data.Set.toList (M.findWithDefault Data.Set.empty k deps)\n              in go (ds ++ ks) (Data.Set.insert k seen)\n\n-- | Relative root-stub C paths for selected binaries.\nselectedRootStubEntriesForBins :: Paths -> [BinTask] -> [FilePath]\nselectedRootStubEntriesForBins paths bins =\n    nub\n      [ collapseDots (makeRelativeOrAbsolute (projPath paths) (binTaskRoot paths b))\n      | b <- bins\n      ]\n\n-- | For each consuming project, map dep name to selected C-source CSV.\ndepModuleOptionsByProj :: M.Map FilePath [GlobalTask] -> M.Map FilePath ProjCtx -> M.Map FilePath (M.Map String String)\ndepModuleOptionsByProj tasksByProj projMap =\n    M.map mkForProj projMap\n  where\n    mkForProj ctx =\n      M.fromList\n        [ (depName, mkCsv depProj)\n        | (depName, depProj) <- projDeps ctx\n        ]\n    mkCsv depProj =\n      intercalate \",\" (selectedCSourceEntriesForProj depProj (M.findWithDefault [] depProj tasksByProj))\n\n-- | Canonical package dependency roots reachable from one project.\n--\n-- These paths come from project discovery, so they already reflect root pin\n-- overrides and fingerprint deduplication. Reusing them for build.zig.zon keeps\n-- Zig pointed at the same dependency roots where we generated build.zig files.\nprojectDepPathOverrides :: M.Map FilePath ProjCtx -> FilePath -> M.Map String FilePath\nprojectDepPathOverrides projMap rootProj = snd (go Data.Set.empty rootProj M.empty)\n  where\n    go seen proj acc\n      | Data.Set.member proj seen = (seen, acc)\n      | otherwise =\n          case M.lookup proj projMap of\n            Nothing -> (Data.Set.insert proj seen, acc)\n            Just ctx ->\n              let seen' = Data.Set.insert proj seen\n              in foldl' step (seen', acc) (projDeps ctx)\n\n    step (seen, acc) (depName, depProj) =\n      let acc' = M.insertWith (\\_ old -> old) depName depProj acc\n      in go seen depProj acc'\n\n-- | Remove orphaned files in out/types.\n-- Non-root files are removed if their module isn’t part of this build (i.e.\n-- no corresponding source .act in this build). The 'roots' argument lists the\n-- exact set of root stub files (*.root.c, *.test_root.c) to keep; others are\n-- removed.\nremoveOrphanFiles :: Paths -> [CompileTask] -> [FilePath] -> IO ()\nremoveOrphanFiles paths tasks roots = do\n    let dir = projTypes paths\n    absOutFiles <- getFilesRecursive dir\n    let allowedBases = [ outBase paths (name t) | t <- tasks ]\n    forM_ absOutFiles $ \\absFile -> do\n        let isC  = takeExtension absFile == \".c\"\n            isH  = takeExtension absFile == \".h\"\n            isTy = takeExtension absFile == \".ty\"\n            bext = takeExtension (takeBaseName absFile)\n            isRootStub = isC && (bext == \".root\" || bext == \".test_root\")\n            base = dropExtension absFile\n            modBase = if isRootStub then dropExtension base else base\n        if isRootStub\n          then when (not (absFile `elem` roots) || not (modBase `elem` allowedBases)) (removeIfExists absFile)\n          else when (isC || isH || isTy) $ do\n                 unless (base `elem` allowedBases) (removeIfExists absFile)\n  where\n    removeIfExists f = removeFile f `catch` handleNotExists\n    handleNotExists :: IOException -> IO ()\n    handleNotExists _ = return ()\n\n-- | Determine which root stub files should be preserved for the current build.\n-- We read the freshly written .ty headers (post-compile) for each task to keep\n-- whichever roots are still declared. This lets us drop stale root stubs when\n-- a module loses its root actor while still retaining stubs that belong to\n-- other build modes (e.g. keeping .root.c when running `acton test`).\nexpectedRootStubs :: Paths -> [CompileTask] -> IO [FilePath]\nexpectedRootStubs paths tasks = do\n    roots <- forM tasks $ \\t -> do\n        let mn     = name t\n            outbase = outBase paths mn\n            tyPath = outbase ++ \".ty\"\n        hdrE <- (try :: IO a -> IO (Either SomeException a)) $ InterfaceFiles.readHeader tyPath\n        case hdrE of\n          Right (_sourceMeta, _, _, _implH, _imps, _nameHashes, rs, _tests, _) -> return (map (mkStub outbase) rs)\n          _ -> return []\n    return (concat roots)\n  where\n    mkStub outbase n =\n      if nameToString n == \"test_main\"\n        then outbase ++ \".test_root.c\"\n        else outbase ++ \".root.c\"\n\ndata BinTask = BinTask { isDefaultRoot :: Bool, binName :: String, rootActor :: A.QName, isTest :: Bool } deriving (Show)\n\nbinTaskRoot :: Paths -> BinTask -> FilePath\nbinTaskRoot paths binTask =\n    let A.GName m _ = rootActor binTask\n        outbase = outBase paths m\n    in if isTest binTask then outbase ++ \".test_root.c\" else outbase ++ \".root.c\"\n\n{-\n================================================================================\nBuild Pipeline Overview\n================================================================================\n\nWe want the compiler to be fast. The primary principle by which to achieve this\nis to avoid doing unnecessary work. Practically, this happens by caching\ninformation in .ty files and only selectively reading what we need. We do not\neagerly load whole .ty files but rather read the header fields: moduleSrcBytesHash,\nmodulePubHash, moduleImplHash, imports, per-name hashes (src/pub/impl + deps),\nroots, tests, and docstrings. This lets us quickly decide which passes to rerun and\nreuse work from previous compilations.\n\nPublic hashing: each top-level name gets a pubHash computed from its doc-free\nsignature plus the pub hashes of its public dependencies. The modulePubHash is\nthen the hash of pubHash values for exported names. Doc-only edits do not affect\npubHash, and a downstream module only needs front passes when a pubHash changes.\n\nImplementation hashing: each top-level name gets an implHash computed from its\nsource hash plus the impl hashes of its dependencies. The moduleImplHash is the\nhash of all per-name impl hashes. We embed moduleImplHash into generated .c/.h\nfiles so we can skip back passes when codegen is already up to date, and we use\nit (with impl deps) to drive the test cache.\n\nTerminology\n- ParseTask: a source-backed module whose imports are known but whose full AST\n  has not been materialized yet\n- ActonTask: a fully parsed source module ready for front passes\n- TyTask: a module loaded from the cached .ty file on disk. Note how there are\n  two variants, a stubbed TyTask where only header fields are loaded and the\n  full TyTask where all module content is available.\n\nHigh-level Steps\n1) Discover and read tasks using header-first strategy (readModuleTask)\n   - For each module, try to use its .ty header to avoid parsing:\n     - If .ty is missing/unreadable → read source and parse only the import\n       header (ParseTask).\n     - If the compiler compatibility guard says the cache is stale\n       → read source and parse the import header now (ParseTask).\n     - If source metadata in the .ty header still matches the current .act and\n       the source mtime is strictly older than the .ty mtime\n       → trust .ty header imports and create a TyTask stub (no heavy decode)\n       for graph building.\n     - If metadata differs, or source/.ty mtimes are equal, verify by content\n       hash:\n       – If stored moduleSrcBytesHash == current bytes hash → header is still\n         valid (TyTask) and refresh cached source metadata.\n       – Else → read source and parse the import header now (ParseTask)\n     - Equal source/.ty mtimes are treated as ambiguous because coarse-mtime\n       filesystems can assign the same visible timestamp to a changed source\n       and the cached .ty written from an earlier version of that source.\n   - This ensures that .ty is up to date with the .act source and lets us\n     read module imports/roots/docstring from the header, which is much faster\n     than parsing the full .act file.\n\n2) Expand to include transitive project imports (readImports)\n   - For project builds, we enumerate all modules under src/ upfront, so chasing\n     is typically a no-op.\n   - For single-file builds (or partial sets), we chase imports from the seeded\n     tasks to ensure all project-local dependencies are included. We prefer .ty\n     headers to avoid parsing; we parse only when a .ty is missing/unreadable.\n\n3) Compile and build\n   - compileTasks builds a stage graph and prefers front work over parse work:\n     - ParseTask stages have no dependencies and can run opportunistically.\n     - Front stages depend on the module's parse stage (if any) plus provider\n       front stages.\n   - Front-stage rebuild decisions are then made per module:\n     - Source changed (ParseTask/ActonTask) → run front passes\n     - Otherwise, compare each used pub dependency hash from the dependent’s\n       .ty header with the provider’s current pub hash. If any differ → front.\n     - Otherwise, compare each used impl dependency hash from the dependent’s\n       .ty header with the provider’s current impl hash. If any differ → refresh\n       impl hashes and run back passes.\n     - Otherwise, if generated .c/.h hashes do not match moduleImplHash → run\n       back passes.\n     - Otherwise → module is fresh (no work).\n   - We maintain a pubMap while walking modules in topological order. After a\n     module compiles, we insert its freshly computed public hash; when a\n     module is fresh (TyTask), we insert the recorded header hash. Dependents\n     then consult pubMap to detect public deltas among their imports.\n   - TyTask items remain lazy; code that needs only small bits (e.g., writeRootC)\n     reads roots/doc from the header instead of forcing heavy loads.\n   - Final Zig C compilation...\n\n================================================================================\n-}\n\ncompileBins:: C.GlobalOptions -> C.CompileOptions -> Paths -> Acton.Env.Env0 -> BuildSpec.BuildSpec -> [CompileTask] -> [BinTask] -> Bool -> [FilePath] -> M.Map String String -> M.Map String FilePath -> Maybe ProgressUI -> IO TimeSpec\ncompileBins gopts opts paths env rootSpec tasks binTasks allowPrune rootModules depModuleOpts depPathOverrides mProgressUI =\n    zigBuild env gopts opts paths rootSpec tasks binTasks allowPrune rootModules depModuleOpts depPathOverrides mProgressUI\n\nprintDiag :: C.GlobalOptions -> C.CompileOptions -> Diagnostic String -> IO ()\nprintDiag gopts opts d = do\n    -- TODO: change to print to stderr! current tests presume stdout so we print to stdout for now..\n    shouldColor <- useColor gopts\n    if shouldColor\n      then printDiagnostic stdout WithUnicode (TabSize 4) defaultStyle d\n      else hPutDoc stdout $ unAnnotate (prettyDiagnostic WithoutUnicode (TabSize 4) d)\n\nprintDiagnostics :: C.GlobalOptions -> C.CompileOptions -> [Diagnostic String] -> IO ()\nprintDiagnostics gopts opts diags =\n    mapM_ (printDiag gopts opts) diags\n\n-- | Generate a root actor C file when a root is still declared.\nwriteRootC :: Acton.Env.Env0 -> C.GlobalOptions -> C.CompileOptions -> Paths -> [CompileTask] -> BinTask -> IO (Maybe BinTask)\nwriteRootC env gopts opts paths tasks binTask = do\n    let qn@(A.GName m n) = rootActor binTask\n        mn = A.mname qn\n        outbase = outBase paths mn\n        rootFile = if (isTest binTask) then outbase ++ \".test_root.c\" else outbase ++ \".root.c\"\n    -- In --only-build mode, reuse existing root stubs; generate only if missing.\n    existing <- if C.only_build opts then doesFileExist rootFile else return False\n    if C.only_build opts && existing\n      then return (Just binTask)\n      else do\n        -- Read the up-to-date roots from the on-disk .ty header (post-compile)\n        -- Avoid using preloaded TyTask roots, which may be stale if the module\n        -- was rebuilt during this run.\n        tyPath <- Acton.Env.findTyFile (searchPath paths) m\n        rootsHeader <- case tyPath of\n                         Just ty -> do (_sourceMeta, _, _, _implH, _imps, _nameHashes, roots, _tests, _) <- InterfaceFiles.readHeader ty; return roots\n                         Nothing -> return []\n        let rootsEnv = case Acton.Env.lookupMod m env of\n                         Nothing -> []\n                         Just te -> [ n' | (n', i) <- te, rootEligible i ]\n            shouldGen = n `elem` rootsHeader || n `elem` rootsEnv\n        if shouldGen\n          then do\n            res <- (try :: IO a -> IO (Either SomeException a)) $ do\n              c <- Acton.CodeGen.genRoot env qn\n              createDirectoryIfMissing True (takeDirectory rootFile)\n              writeFile rootFile c\n            case res of\n              Right _ -> return (Just binTask)\n              Left _  -> return Nothing\n          else return Nothing\n\n-- | Check whether a target triple refers to Windows.\nisWindowsOS :: String -> Bool\nisWindowsOS targetTriple = case splitOn \"-\" targetTriple of\n    (_:os:_) -> os == \"windows\"\n    _        -> False\n\n-- | Run a process and capture output, canceling on exceptions.\nreadProcessWithExitCodeCancelable :: CreateProcess -> (ProcessHandle -> IO ()) -> IO (ExitCode, String, String)\nreadProcessWithExitCodeCancelable cp onStart = do\n    let cp' = cp { std_in = NoStream, std_out = CreatePipe, std_err = CreatePipe }\n    withCreateProcess cp' $ \\_ mOut mErr ph -> do\n      onStart ph\n      outVar <- newEmptyMVar\n      errVar <- newEmptyMVar\n      let readHandle mH var =\n            case mH of\n              Nothing -> putMVar var \"\"\n              Just h -> do\n                txt <- hGetContents h\n                _ <- evaluate (length txt)\n                hClose h\n                putMVar var txt\n      _ <- forkIO $ readHandle mOut outVar\n      _ <- forkIO $ readHandle mErr errVar\n      code <- waitForProcess ph `onException` do\n                terminateProcess ph\n                void (waitForProcess ph)\n      out <- takeMVar outVar\n      err <- takeMVar errVar\n      return (code, out, err)\n\nrunZig gopts opts zigExe zigArgs paths wd mProgressUI = do\n    let display = showCommandForUser zigExe zigArgs\n    iff (C.ccmd opts || C.verbose gopts) $ putStrLn (\"zigCmd: \" ++ display)\n    env0 <- System.Environment.getEnvironment\n    let ignoreIO :: IOException -> IO ()\n        ignoreIO _ = return ()\n        withLock = case mProgressUI of\n          Just ui -> withProgressLock ui\n          Nothing -> \\action -> action\n        mTermProgress = do\n          ui <- mProgressUI\n          let tp = puTermProgress ui\n          if termProgressEnabled tp then Just tp else Nothing\n    (envOverride, onStart, onStop, closeFds) <- case mTermProgress of\n      Nothing -> return (Nothing, \\_ -> return (), return (), True)\n      Just tp -> do\n        (readFd, writeFd) <- createPipe\n        setFdOption writeFd CloseOnExec False\n        setFdOption readFd CloseOnExec True\n        doneVar <- newEmptyMVar\n        pctRef <- newIORef (85 :: Int)\n        let updatePercent ratio = do\n              let clamped = max 0 (min 0.999 ratio)\n                  pctRaw = 85 + floor (clamped * 15)\n              pct <- atomicModifyIORef' pctRef (\\prev -> let next = max prev pctRaw in (next, next))\n              withLock (termProgressPercent tp pct)\n            reader = do\n              readZigProgressStream readFd $ \\msg ->\n                case zigProgressRatio msg of\n                  Nothing -> return ()\n                  Just ratio -> updatePercent ratio\n        _ <- forkIO (reader `finally` putMVar doneVar ())\n        let envVal = show (fromIntegral writeFd :: Int)\n            onStart' _ = closeFd writeFd `catch` ignoreIO\n            onStop' = do\n              closeFd writeFd `catch` ignoreIO\n              closeFd readFd `catch` ignoreIO\n              takeMVar doneVar\n        return (Just (\"ZIG_PROGRESS\", envVal), onStart', onStop', False)\n    let env1 = if System.Info.os == \"darwin\" && not (any ((== \"DEVELOPER_DIR\") . fst) env0)\n               then (\"DEVELOPER_DIR\", \"/dev/null\") : env0\n               else env0\n        env2 = case envOverride of\n          Nothing -> Just env1\n          Just (k, v) -> Just ((k, v) : filter ((/= k) . fst) env1)\n        cpBase = (proc zigExe zigArgs){ cwd = wd, env = env2 }\n        cp = if closeFds then cpBase else cpBase { close_fds = False }\n    (returnCode, zigStdout, zigStderr) <- readProcessWithExitCodeCancelable cp onStart `finally` onStop\n    case returnCode of\n        ExitSuccess -> do\n          iff (C.verboseZig gopts) $ putStrLn zigStderr\n          return ()\n        ExitFailure ret -> do\n          printIce (\"compilation of generated Zig code failed, returned error code\" ++ show ret)\n          putStrLn $ \"zig stdout:\\n\" ++ zigStdout\n          putStrLn $ \"zig stderr:\\n\" ++ zigStderr\n          unless (C.watch opts) System.Exit.exitFailure\n\ngenerateFingerprint :: String -> IO String\ngenerateFingerprint name = do\n    ident <- randomRIO (1, 0xfffffffe :: Word32)\n    let prefix = Fingerprint.fingerprintPrefixForName name\n        fp = (fromIntegral prefix `shiftL` 32) .|. fromIntegral ident\n    return (Fingerprint.formatFingerprint fp)\n\n-- Render build.zig and build.zig.zon from templates and BuildSpec.\n-- rootPins: dependency pins from the main project (applied to all deps, including transitive)\ngenBuildZigFiles :: BuildSpec.BuildSpec -> M.Map String BuildSpec.PkgDep -> [(String, FilePath)] -> Paths -> M.Map String String -> M.Map String FilePath -> IO ()\ngenBuildZigFiles spec rootPins depOverrides paths depModuleOpts depPathOverrides = do\n    let proj = projPath paths\n    projAbs <- canonicalizePath proj\n    let sys              = sysPath paths\n        buildZigPath     = joinPath [proj, \"build.zig\"]\n        buildZonPath     = joinPath [proj, \"build.zig.zon\"]\n        distBuildZigPath = joinPath [sys, \"builder\", \"build.zig\"]\n        distBuildZonPath = joinPath [sys, \"builder\", \"build.zig.zon\"]\n    buildZigTemplate <- readFile distBuildZigPath\n    buildZonTemplate <- readFile distBuildZonPath\n    let zonName = BuildSpec.specName spec\n        fp = BuildSpec.fingerprint spec\n    (transPkgs, transZigs) <- collectDepsRecursive spec proj rootPins depOverrides\n    absSys <- canonicalizePath sys\n    let relSys = relativeViaRoot projAbs absSys\n    homeDir <- getHomeDirectory\n    depsRootAbs <- normalizePathSafe (joinPath [homeDir, \".cache\", \"acton\", \"deps\"])\n    normalizedSpec <- normalizeSpecPaths proj spec\n    let directZigs = [ ZigDepRef depName (rebaseZigDep projAbs proj dep)\n                     | (depName, dep) <- M.toList (BuildSpec.zig_dependencies normalizedSpec)\n                     ]\n        applyPins deps = M.mapWithKey (\\n d -> M.findWithDefault d n rootPins) deps\n        mergedSpec0 = normalizedSpec { BuildSpec.dependencies = applyPins (BuildSpec.dependencies normalizedSpec) `M.union` transPkgs }\n        mergedSpec = applyPkgDepPathOverrides projAbs depPathOverrides mergedSpec0\n        resolvedZigs = resolveZigDepRefs (M.keys (BuildSpec.dependencies mergedSpec)) (directZigs ++ transZigs)\n        zonWithFp = replace \"{{fingerprint}}\" fp . replace \"{{name}}\" zonName\n    writeFile buildZigPath (genBuildZig buildZigTemplate mergedSpec resolvedZigs depModuleOpts)\n    writeFileAtomic buildZonPath (genBuildZigZon buildZonTemplate relSys depsRootAbs projAbs fp zonName mergedSpec resolvedZigs)\n\napplyPkgDepPathOverrides :: FilePath -> M.Map String FilePath -> BuildSpec.BuildSpec -> BuildSpec.BuildSpec\napplyPkgDepPathOverrides projRoot depPathOverrides spec =\n    spec { BuildSpec.dependencies = M.mapWithKey rewriteDep (BuildSpec.dependencies spec) }\n  where\n    rewriteDep depName dep =\n      case M.lookup depName depPathOverrides of\n        Nothing -> dep\n        Just depPath ->\n          dep { BuildSpec.path = Just (collapseDots (makeRelativeOrAbsolute projRoot depPath)) }\n\ndata ZigDepRef = ZigDepRef\n  { zigDepRefName :: String\n  , zigDepRefDep :: BuildSpec.ZigDep\n  }\n\ndata ZigDepResolved = ZigDepResolved\n  { zigDepResolvedVarName :: String\n  , zigDepResolvedPkgName :: String\n  , zigDepResolvedDep :: BuildSpec.ZigDep\n  }\n\ndata ZigDepIdentity\n  = ZigDepPathIdentity FilePath (M.Map String String)\n  | ZigDepHashIdentity String (M.Map String String)\n  | ZigDepUrlIdentity (Maybe String) (M.Map String String)\n  deriving (Eq, Ord, Show)\n\nzigDepIdentity :: BuildSpec.ZigDep -> ZigDepIdentity\nzigDepIdentity dep =\n  case BuildSpec.zpath dep of\n    Just p | not (null p) -> ZigDepPathIdentity p (BuildSpec.options dep)\n    _ -> case BuildSpec.zhash dep of\n           Just h | not (null h) -> ZigDepHashIdentity h (BuildSpec.options dep)\n           _ -> ZigDepUrlIdentity (BuildSpec.zurl dep) (BuildSpec.options dep)\n\nmergeUniqueStrings :: [String] -> [String] -> [String]\nmergeUniqueStrings xs ys =\n    xs ++ [ y | y <- ys, y `notElem` xs ]\n\nmergeZigDeps :: BuildSpec.ZigDep -> BuildSpec.ZigDep -> BuildSpec.ZigDep\nmergeZigDeps dep0 dep1 =\n    dep0 { BuildSpec.artifacts = mergeUniqueStrings (BuildSpec.artifacts dep0) (BuildSpec.artifacts dep1) }\n\ndedupZigDepRefs :: [ZigDepRef] -> [(String, BuildSpec.ZigDep)]\ndedupZigDepRefs refs =\n    let (orderRev, byIdentity) = foldl' step ([], M.empty) refs\n    in [ let ref = byIdentity M.! ident\n         in (zigDepRefName ref, zigDepRefDep ref)\n       | ident <- reverse orderRev\n       ]\n  where\n    step (orderRev, byIdentity) ref =\n      let ident = zigDepIdentity (zigDepRefDep ref)\n      in case M.lookup ident byIdentity of\n           Nothing ->\n             (ident : orderRev, M.insert ident ref byIdentity)\n           Just prevRef ->\n             let mergedRef = prevRef { zigDepRefDep = mergeZigDeps (zigDepRefDep prevRef) (zigDepRefDep ref) }\n             in (orderRev, M.insert ident mergedRef byIdentity)\n\nnextAvailableName :: Data.Set.Set String -> String -> String\nnextAvailableName usedNames baseName = go 0\n  where\n    go 0\n      | Data.Set.member baseName usedNames = go 2\n      | otherwise = baseName\n    go n =\n      let candidate = baseName ++ \"_\" ++ show n\n      in if Data.Set.member candidate usedNames\n           then go (n + 1)\n           else candidate\n\n-- | Zig and Acton package dependencies share one Zig package namespace at\n-- generation time. Keep generated zig package keys disjoint from package deps\n-- and reserved builder deps so a wrapper package and its underlying zig pkg can\n-- reuse the same logical dependency name.\nresolveZigDepRefs :: [String] -> [ZigDepRef] -> [ZigDepResolved]\nresolveZigDepRefs pkgDepNames refs =\n    reverse resolvedRev\n  where\n    reservedNames =\n      Data.Set.fromList ([\"actondb\", \"base\"] ++ pkgDepNames)\n    uniqueRefs = dedupZigDepRefs refs\n    (_, _, resolvedRev) = foldl' assign (reservedNames, Data.Set.empty, []) uniqueRefs\n\n    assign (usedPkgNames, usedVarNames, acc) (depName, dep) =\n      let pkgName = nextAvailableName usedPkgNames (\"acton_zig_\" ++ depName)\n          varName = nextAvailableName usedVarNames depName\n          resolved = ZigDepResolved\n            { zigDepResolvedVarName = varName\n            , zigDepResolvedPkgName = pkgName\n            , zigDepResolvedDep = dep\n            }\n      in ( Data.Set.insert pkgName usedPkgNames\n         , Data.Set.insert varName usedVarNames\n         , resolved : acc\n         )\n\ngenBuildZig :: String -> BuildSpec.BuildSpec -> [ZigDepResolved] -> M.Map String String -> String\ngenBuildZig template spec zigDeps depModuleOpts =\n    let\n        depsDefs = concatMap pkgDepDef (M.toList (BuildSpec.dependencies spec))\n        zigDefs  = concatMap zigDepDef zigDeps\n        depsAll  = depsDefs ++ zigDefs\n        libLinks = concatMap pkgLibLink (M.toList (BuildSpec.dependencies spec))\n                ++ concatMap zigLibLink zigDeps\n        exeLinks = concatMap pkgExeLink (M.toList (BuildSpec.dependencies spec))\n                ++ concatMap zigExeLink zigDeps\n        header = [ \"// AUTOMATICALLY GENERATED BY ACTON BUILD SYSTEM\"\n                 , \"// DO NOT EDIT, CHANGES WILL BE OVERWRITTEN!!!!!\"\n                 , \"\"\n                 ]\n        inject line =\n          let sline = dropWhile (== ' ') line\n          in [line]\n             ++ (if sline == \"// Dependencies from Build.act\" then [depsAll] else [])\n             ++ (if sline == \"// lib: link with dependencies / get headers from Build.act\" then [libLinks] else [])\n             ++ (if sline == \"// exe: link with dependencies / get headers from Build.act\" then [exeLinks] else [])\n    in unlines $ header ++ concatMap inject (lines template)\n  where\n    pkgDepDef (name, _) =\n      let selectedCsv = M.findWithDefault \"\" name depModuleOpts\n      in unlines [ \"    const actdep_\" ++ name ++ \" = b.dependency(\\\"\" ++ name ++ \"\\\", .{\"\n                 , \"        .target = target,\"\n                 , \"        .optimize = optimize,\"\n                 , \"        .acton_modules = \" ++ show selectedCsv ++ \",\"\n                 , \"        .acton_root_stubs = \\\"\\\",\"\n                 , \"    });\"\n                 ]\n    pkgLibLink (name, _) = \"    libActonProject.linkLibrary(actdep_\" ++ name ++ \".artifact(\\\"ActonProject\\\"));\\n\"\n    pkgExeLink (name, _) = \"            executable.linkLibrary(actdep_\" ++ name ++ \".artifact(\\\"ActonProject\\\"));\\n\"\n\n    zigDepDef resolved\n      | null (BuildSpec.artifacts dep) = \"\"\n      | otherwise =\n          let opts = concat [ \"        .\" ++ k ++ \" = \" ++ v ++ \",\\n\" | (k, v) <- M.toList (BuildSpec.options dep) ]\n          in unlines [ \"    const dep_\" ++ zigDepResolvedVarName resolved ++ \" = b.dependency(\\\"\" ++ zigDepResolvedPkgName resolved ++ \"\\\", .{\"\n                     , \"        .target = target,\"\n                     , \"        .optimize = optimize,\"\n                     , opts ++ \"    });\"\n                     ]\n      where dep = zigDepResolvedDep resolved\n    zigLibLink resolved = concat [ \"    libActonProject.linkLibrary(dep_\" ++ zigDepResolvedVarName resolved ++ \".artifact(\\\"\" ++ art ++ \"\\\"));\\n\"\n                                 | art <- BuildSpec.artifacts (zigDepResolvedDep resolved) ]\n    zigExeLink resolved = concat [ \"            executable.linkLibrary(dep_\" ++ zigDepResolvedVarName resolved ++ \".artifact(\\\"\" ++ art ++ \"\\\"));\\n\"\n                                 | art <- BuildSpec.artifacts (zigDepResolvedDep resolved) ]\n\ngenBuildZigZon :: String -> String -> FilePath -> FilePath -> String -> String -> BuildSpec.BuildSpec -> [ZigDepResolved] -> String\ngenBuildZigZon template relSys depsRootAbs projAbs fingerprint zonName spec zigDepsResolved =\n    let\n        pkgDeps = concatMap (pkgToZon projAbs depsRootAbs) (M.toList (BuildSpec.dependencies spec))\n        zigDeps = concatMap zigToZon zigDepsResolved\n        deps = pkgDeps ++ zigDeps\n        replaced = map (replace \"{{fingerprint}}\" fingerprint\n                     . replace \"{{syspath}}\" relSys\n                     . replace \"{{name}}\" zonName) (lines template)\n        header = [ \"// AUTOMATICALLY GENERATED BY ACTON BUILD SYSTEM\"\n                 , \"// DO NOT EDIT, CHANGES WILL BE OVERWRITTEN!!!!!\"\n                 , \"\"\n                 ]\n        inject line =\n          let sline = dropWhile (== ' ') line\n          in [line] ++ (if sline == \"// Dependencies from Build.act\" then [deps] else [])\n    in unlines $ header ++ concatMap inject replaced\n  where\n    pkgToZon projRoot depsRoot (name, dep) =\n      let rawPath = case BuildSpec.path dep of\n                      Just p | not (null p) -> p\n                      _ -> case BuildSpec.hash dep of\n                             Just h -> joinPath [depsRoot, name ++ \"-\" ++ h]\n                             Nothing -> errorWithoutStackTrace (\"Dependency \" ++ name ++ \" has no path or hash\")\n          pathAbs = collapseDots $\n                      if isAbsolutePath rawPath\n                        then normalise rawPath\n                        else normalise (rebasePath projRoot rawPath)\n          path = relativeViaRoot projRoot pathAbs\n      in unlines [ \"        .\" ++ name ++ \" = .{\"\n                 , \"            .path = \\\"\" ++ path ++ \"\\\",\"\n                 , \"        },\"\n                 ]\n    zigToZon resolved =\n      case BuildSpec.zpath dep of\n        Just p ->\n          let absPath = collapseDots $\n                          if isAbsolutePath p\n                            then normalise p\n                            else normalise (rebasePath projAbs p)\n              relPath = relativeViaRoot projAbs absPath\n          in unlines [ \"        .\" ++ zigDepResolvedPkgName resolved ++ \" = .{\"\n                     , \"            .path = \\\"\" ++ relPath ++ \"\\\",\"\n                     , \"        },\"\n                     ]\n        Nothing -> unlines [ \"        .\" ++ zigDepResolvedPkgName resolved ++ \" = .{\"\n                           , \"            .url = \\\"\" ++ maybeEmpty (BuildSpec.zurl dep) ++ \"\\\",\"\n                           , \"            .hash = \\\"\" ++ maybeEmpty (BuildSpec.zhash dep) ++ \"\\\",\"\n                           , \"        },\"\n                           ]\n      where\n        dep = zigDepResolvedDep resolved\n    maybeEmpty (Just s) = s\n    maybeEmpty Nothing  = \"\"\n\n#if defined(darwin_HOST_OS) && defined(aarch64_HOST_ARCH)\ndefCpuFlag = [\"-Dcpu=apple_m1\"]\n#elif defined(aarch64_HOST_ARCH)\ndefCpuFlag = [\"-Dcpu=generic+crypto\"]\n#elif defined(x86_64_HOST_ARCH)\ndefCpuFlag = [\"-Dcpu=x86_64_v2+aes\"]\n#else\n#error \"Unsupported platform\"\n#endif\n\n-- | Run zig build for generated artifacts and prune stale outputs.\nzigBuild :: Acton.Env.Env0 -> C.GlobalOptions -> C.CompileOptions -> Paths -> BuildSpec.BuildSpec -> [CompileTask] -> [BinTask] -> Bool -> [FilePath] -> M.Map String String -> M.Map String FilePath -> Maybe ProgressUI -> IO TimeSpec\nzigBuild env gopts opts paths rootSpec tasks binTasks allowPrune rootModules depModuleOpts depPathOverrides mProgressUI = do\n    allBinTasks <- mapM (writeRootC env gopts opts paths tasks) binTasks\n    let realBinTasks = catMaybes allBinTasks\n\n    let pruningAllowed = allowPrune && not (C.only_build opts)\n    when pruningAllowed $ do\n      -- Clean out/types: drop stray outputs and stale root stubs based on the\n      -- current headers. Also keep the roots we attempted to build in this run\n      -- so they survive even if a header failed to list them (defensive).\n      let requestedRoots = map (binTaskRoot paths) realBinTasks\n      headerRoots <- expectedRootStubs paths tasks\n      let roots = nub (headerRoots ++ requestedRoots)\n      removeOrphanFiles paths tasks roots\n      unless (isTmp paths) $\n        -- Clean old binaries from out/bin\n        removeOrphanExecutables (binDir paths) (projTypes paths) realBinTasks\n\n    timeStart <- getTime Monotonic\n\n    homeDir <- getHomeDirectory\n    let local_cache_dir = joinPath [ homeDir, \".cache\", \"acton\", \"zig-local-cache\" ]\n        global_cache_dir = joinPath [ homeDir, \".cache\", \"acton\", \"zig-global-cache\" ]\n        no_threads = if isWindowsOS (C.target opts) then True else C.no_threads opts\n    projAbs <- normalizePathSafe (projPath paths)\n    sysAbs  <- normalizePathSafe (sysPath paths)\n    depOverrides <- normalizeDepOverrides (projPath paths) (C.dep_overrides opts)\n    let sysRoot   = addTrailingPathSeparator sysAbs\n        isSysProj = projAbs == sysAbs || sysRoot `isPrefixOf` projAbs\n\n    -- Generate build.zig and build.zig.zon directly from Build.act.\n    iff (not isSysProj) $ do\n      let pins = BuildSpec.dependencies rootSpec\n      genBuildZigFiles rootSpec pins depOverrides paths depModuleOpts depPathOverrides\n\n    let zigExe = zig paths\n        baseArgs = [\"build\",\"--cache-dir\", local_cache_dir,\n                            \"--global-cache-dir\", global_cache_dir] ++\n                   (if (C.verboseZig gopts) then [\"--verbose\"] else [])\n        prefixArgs = [\"--prefix\", projOut paths, \"--prefix-exe-dir\", \"bin\"] ++\n                     (if (C.verboseZig gopts) then [\"--verbose\"] else [])\n        targetArgs = [\"-Dtarget=\" ++ C.target opts]\n        cpuArgs =\n            if (C.cpu opts /= \"\") then [\"-Dcpu=\" ++ C.cpu opts]\n            else case (splitOn \"-\" (C.target opts)) of\n                   (\"native\":_)            -> defCpuFlag\n                   (\"aarch64\":\"macos\":_)   -> [\"-Dcpu=apple_m1\"]\n                   (\"aarch64\":_)           -> [\"-Dcpu=generic+crypto\"]\n                   (\"x86_64\":_)            -> [\"-Dcpu=x86_64_v2+aes\"]\n                   (_:_)                   -> defCpuFlag\n                   []                      -> defCpuFlag\n        optArgs = [\"-Doptimize=\" ++ optimizeModeToZig (C.optimize opts)]\n        rootModulesCsv = intercalate \",\" rootModules\n        rootStubsCsv = intercalate \",\" (selectedRootStubEntriesForBins paths realBinTasks)\n        moduleArgs = [ \"-Dacton_modules=\" ++ rootModulesCsv\n                     , \"-Dacton_root_stubs=\" ++ rootStubsCsv\n                     ]\n        featureArgs = concat [ if C.db opts then [\"-Ddb\"] else []\n                             , if no_threads then [\"-Dno_threads\"] else []\n                             , if C.cpedantic opts then [\"-Dcpedantic\"] else []\n                             ]\n        zigArgs = baseArgs ++ prefixArgs ++ targetArgs ++ cpuArgs ++ optArgs ++ moduleArgs ++ featureArgs\n\n    runZig gopts opts zigExe zigArgs paths (Just (projPath paths)) mProgressUI\n    -- if we are in a temp acton project, copy the outputted binary next to the source file\n    if (isTmp paths && not (null realBinTasks))\n      then do\n        let baseName   = binName (head binTasks)\n            exeName    = if isWindowsOS (C.target opts) then baseName ++ \".exe\" else baseName\n            srcBinFile = joinPath [ projOut paths, \"bin\", exeName ]\n            dstBinFile = joinPath [ binDir paths, exeName ]\n        copyFile srcBinFile dstBinFile\n      else return ()\n    timeEnd <- getTime Monotonic\n    return (timeEnd - timeStart)\n\n-- Remove executables that no longer have corresponding root actors\n-- | Remove binaries that no longer have corresponding roots.\nremoveOrphanExecutables :: FilePath -> FilePath -> [BinTask] -> IO ()\nremoveOrphanExecutables binDir projTypes binTasks = do\n    binDirExists <- doesDirectoryExist binDir\n    when binDirExists $ do\n        binFiles <- listDirectory binDir\n        forM_ binFiles $ \\exeFile -> do\n            let exeName = takeBaseName exeFile\n                modPath = map (\\c -> if c == '.' then '/' else c) exeName\n                rootCFile = projTypes </> modPath <.> \"root.c\"\n                testRootCFile = projTypes </> modPath <.> \"test_root.c\"\n\n            let isCurrentBin = any (\\t -> binName t == exeName) binTasks\n\n            rootExists <- doesFileExist rootCFile\n            testRootExists <- doesFileExist testRootCFile\n            when (not isCurrentBin && not rootExists && not testRootExists) $ do\n              let fileName = binDir </> exeFile\n              removeFile fileName `catch` handleNotExists\n  where\n    handleNotExists :: IOException -> IO ()\n    handleNotExists _ = return ()\n\n-- | Compute a relative path when possible, otherwise a safe absolute form.\nmakeRelativeOrAbsolute :: FilePath -> FilePath -> FilePath\nmakeRelativeOrAbsolute base target =\n    let (bDriveRaw, bPath) = splitDrive (normalise base)\n        (tDriveRaw, tPath) = splitDrive (normalise target)\n        bDrive = map toLower bDriveRaw\n        tDrive = map toLower tDriveRaw\n        bParts = cleanParts bPath\n        tParts = cleanParts tPath\n        common = length (takeWhile (uncurry (==)) (zip bParts tParts))\n        ups = replicate (length bParts - common) \"..\"\n        relParts = ups ++ drop common tParts\n        rel = if null relParts then \".\" else joinPath relParts\n    in if bDrive /= tDrive && (not (null bDrive) || not (null tDrive))\n          then joinPath (replicate (length bParts) \"..\" ++ (tDriveRaw : tParts))\n          else rel\n  where\n    cleanParts = filter (\\c -> not (null c) && c /= \"/\") . splitDirectories\n\n-- | Compute a path relative to the project root with drive handling.\nrelativeViaRoot :: FilePath -> FilePath -> FilePath\nrelativeViaRoot baseAbs targetAbs\n  | not (isAbsolutePath targetAbs) = targetAbs\n  | otherwise =\n      let (bDriveRaw, bPath) = splitDrive (normalise baseAbs)\n          (tDriveRaw, tPath) = splitDrive (normalise targetAbs)\n          bDrive = map toLower bDriveRaw\n          tDrive = map toLower tDriveRaw\n      in if bDrive /= tDrive && (not (null bDrive) || not (null tDrive))\n           then makeRelativeOrAbsolute baseAbs targetAbs\n           else\n             let ups = replicate (length (cleanParts bPath)) \"..\"\n                 tParts = cleanParts tPath\n             in joinPath (ups ++ tParts)\n  where\n    cleanParts = filter (\\c -> not (null c) && c /= \"/\") . splitDirectories\n\n-- | Walk BuildSpec dependencies to collect transitive packages and zig deps.\ncollectDepsRecursive :: BuildSpec.BuildSpec -> FilePath -> M.Map String BuildSpec.PkgDep -> [(String, FilePath)] -> IO (M.Map String BuildSpec.PkgDep, [ZigDepRef])\ncollectDepsRecursive rootSpec projDir pins overrides = do\n  root <- normalizePathSafe projDir\n  spec <- applyDepOverrides root overrides rootSpec\n  (\\(_, pkgs, zigs) -> (pkgs, zigs)) <$> foldM (step root root) (Data.Set.empty, M.empty, []) (M.toList (BuildSpec.dependencies spec))\n  where\n    go root seen dir mSpec = do\n      spec0 <- case mSpec of\n                 Just s -> return s\n                 Nothing -> loadBuildSpec dir\n      spec <- applyDepOverrides dir overrides spec0\n      let depsHere = BuildSpec.dependencies spec\n          zigsHere = [ ZigDepRef depName (rebaseZigDep root dir dep)\n                     | (depName, dep) <- M.toList (BuildSpec.zig_dependencies spec)\n                     ]\n      foldM (step root dir) (seen, M.empty, zigsHere) (M.toList depsHere)\n\n    step root base (seen, pkgAcc, zigAcc) (depName, dep) = do\n      let depChosen = case M.lookup depName pins of\n                        Nothing   -> dep\n                        Just pdep -> pdep\n      depBase <- resolveDepBase base depName depChosen\n      let seen' = Data.Set.insert depBase seen\n          rebasePkgPath d =\n            case BuildSpec.path d of\n              Just p | not (null p) ->\n                let absP = rebasePath base p\n                    relP = makeRelativeOrAbsolute root absP\n                in d { BuildSpec.path = Just (collapseDots relP) }\n              _ -> d\n          dep' = rebasePkgPath depChosen\n      if Data.Set.member depBase seen\n        then return (seen', pkgAcc, zigAcc)\n        else do\n          (seenNext, subPkgs, subZigs) <- go root seen' depBase Nothing\n          let pkgAcc' = M.insertWith (\\_ old -> old) depName dep' pkgAcc\n          return (seenNext, pkgAcc' `M.union` subPkgs, zigAcc ++ subZigs)\n\nrebaseZigDep :: FilePath -> FilePath -> BuildSpec.ZigDep -> BuildSpec.ZigDep\nrebaseZigDep root base dep =\n  case BuildSpec.zpath dep of\n    Just p | not (null p) ->\n      let absP = rebasePath base p\n          relP = makeRelativeOrAbsolute root absP\n      in dep { BuildSpec.zpath = Just (collapseDots relP) }\n    _ -> dep\n\n-- | Normalize dependency paths in a BuildSpec.\nnormalizeSpecPaths :: FilePath -> BuildSpec.BuildSpec -> IO BuildSpec.BuildSpec\nnormalizeSpecPaths base spec = do\n    deps <- normalizePkgDeps base (BuildSpec.dependencies spec)\n    zigs <- normalizeZigDeps base (BuildSpec.zig_dependencies spec)\n    return spec { BuildSpec.dependencies = deps\n                , BuildSpec.zig_dependencies = zigs }\n  where\n    normalizePkgDeps b = fmap M.fromList . mapM (\\(k,v) -> do v' <- normalizePkgDep b v; return (k,v')) . M.toList\n    normalizePkgDep b dep =\n      case BuildSpec.path dep of\n        Just p | not (null p) -> do\n          if isAbsolutePath p\n            then do p' <- normalizePathSafe p\n                    return dep { BuildSpec.path = Just p' }\n            else return dep { BuildSpec.path = Just (collapseDots (normalise p)) }\n        _ -> return dep\n\n    normalizeZigDeps b = fmap M.fromList . mapM (\\(k,v) -> do v' <- normalizeZigDep b v; return (k,v')) . M.toList\n\n-- | Normalize a zig dependency path entry.\nnormalizeZigDep :: FilePath -> BuildSpec.ZigDep -> IO BuildSpec.ZigDep\nnormalizeZigDep b dep =\n  case BuildSpec.zpath dep of\n    Just p | not (null p) -> do\n      if isAbsolutePath p\n        then do p' <- normalizePathSafe p\n                return dep { BuildSpec.zpath = Just p' }\n        else return dep { BuildSpec.zpath = Just (collapseDots (normalise p)) }\n    _ -> return dep\n\n-- | Filter bin tasks to those with a valid root actor.\nfilterMainActor :: Acton.Env.Env0 -> Paths -> BinTask -> IO (Maybe BinTask)\nfilterMainActor env paths binTask = do\n    let qn@(A.GName m n) = rootActor binTask\n    let checkEnv = case Acton.Env.lookupMod m env of\n                     Nothing -> return Nothing\n                     Just te -> do\n                       let rootsEnv = [ n' | (n', i) <- te, rootEligible i ]\n                       if n `elem` rootsEnv then return (Just binTask) else return Nothing\n    mty <- Acton.Env.findTyFile (searchPath paths) m\n    case mty of\n      Just ty -> do\n        hdrE <- (try :: IO a -> IO (Either SomeException a)) $ InterfaceFiles.readHeader ty\n        case hdrE of\n          Right (_sourceMeta, _, _, _implH, _imps, _nameHashes, roots, _tests, _) | n `elem` roots -> return (Just binTask)\n          _ -> checkEnv\n      Nothing -> checkEnv\n\n-- | Check whether git is available on PATH.\nisGitAvailable :: IO Bool\nisGitAvailable = do\n    (exitCode, _, _) <- readProcessWithExitCode \"git\" [\"--version\"] \"\"\n    return $ exitCode == ExitSuccess\n\n-- | Decide whether to emit colored diagnostics.\nuseColor :: C.GlobalOptions -> IO Bool\nuseColor gopts = do\n    noColorEnv <- lookupEnv \"NO_COLOR\"\n    case noColorEnv of\n        Just _ -> return False\n        Nothing ->\n            case C.color gopts of\n                C.Never  -> return False\n                C.Always -> return True\n                C.Auto   -> do\n                    tty <- hIsTerminalDevice stdout\n                    return (tty || C.tty gopts)\n\ndata ProgressUI = ProgressUI\n  { puEnabled :: Bool\n  , puWidthAware :: Bool\n  , puMaxLines :: Int\n  , puLinesRef :: IORef [String]\n  , puVisibleRef :: IORef Int\n  , puSpinnerRef :: IORef Int\n  , puUseColor :: Bool\n  , puCursorHiddenRef :: IORef Bool\n  , puTickerRef :: IORef (Maybe ThreadId)\n  , puTermProgress :: TermProgress\n  , puTermSize :: TermSize\n  , puLock :: MVar ()\n  }\n\ndata ProgressState = ProgressState\n  { psActive :: IORef (M.Map TaskKey ProgressTask)\n  , psOrder :: IORef [TaskKey]\n  }\n\ndata ProgressTask = ProgressTask\n  { ptRenderLine :: Int -> BuildLineLayout\n  , ptStart :: TimeSpec\n  , ptProgress :: Maybe Double\n  }\n\n-- | Initialize terminal progress UI state and enablement.\ninitProgressUI :: C.GlobalOptions -> Int -> IO ProgressUI\ninitProgressUI gopts maxLines = do\n    tty <- hIsTerminalDevice stdout\n    let widthAware = (tty || C.tty gopts) && not (C.quiet gopts)\n        enabled = widthAware && not (C.noProgress gopts)\n    useColorOut <- useColor gopts\n    linesRef <- newIORef []\n    visibleRef <- newIORef 0\n    spinnerRef <- newIORef 0\n    cursorHiddenRef <- newIORef False\n    tickerRef <- newIORef Nothing\n    termProgress <- initTermProgress gopts\n    termSize <- initTermSize widthAware\n    lock <- newMVar ()\n    return ProgressUI\n      { puEnabled = enabled\n      , puWidthAware = widthAware\n      , puMaxLines = max 1 maxLines\n      , puLinesRef = linesRef\n      , puVisibleRef = visibleRef\n      , puSpinnerRef = spinnerRef\n      , puUseColor = useColorOut\n      , puCursorHiddenRef = cursorHiddenRef\n      , puTickerRef = tickerRef\n      , puTermProgress = termProgress\n      , puTermSize = termSize\n      , puLock = lock\n      }\n\n-- | Initialize tracking for active progress tasks.\nnewProgressState :: IO ProgressState\nnewProgressState = do\n    active <- newIORef M.empty\n    order <- newIORef []\n    return ProgressState { psActive = active, psOrder = order }\n\n-- | Serialize progress UI updates when rendering is enabled.\nwithProgressLock :: ProgressUI -> IO a -> IO a\nwithProgressLock ui action =\n    if not (puEnabled ui)\n      then action\n      else withMVar (puLock ui) (\\_ -> action)\n\n-- | Clear the progress area, run a log action, then redraw.\nprogressWithLog :: ProgressUI -> IO () -> IO ()\nprogressWithLog ui action = withProgressLock ui $ do\n    if not (puEnabled ui)\n      then action\n      else do\n        progressClearUnlocked ui\n        action\n        progressRenderUnlocked ui\n\n-- | Log a line while preserving the progress display.\nprogressLogLine :: ProgressUI -> String -> IO ()\nprogressLogLine ui msg = progressWithLog ui (putStrLn msg)\n\n-- | Clear the progress area from the terminal.\nprogressClearUnlocked :: ProgressUI -> IO ()\nprogressClearUnlocked ui = do\n    visible <- readIORef (puVisibleRef ui)\n    when (visible > 0) $ do\n      replicateM_ visible $ do\n        putStr \"\\ESC[1A\"\n        putStr \"\\r\\ESC[2K\"\n      hFlush stdout\n    writeIORef (puVisibleRef ui) 0\n\n-- | Progress heartbeat interval in microseconds.\nprogressTickMicros :: Int\nprogressTickMicros = 80000\n\n-- | Spinner frames used by the progress UI.\nspinnerChars :: [Char]\nspinnerChars = \"⠋⠙⠹⠸⠼⠴⠦⠧⠇⠏\"\n\n-- | Hide or show the cursor during progress rendering.\nsetCursorHidden :: ProgressUI -> Bool -> IO ()\nsetCursorHidden ui hidden =\n    when (puEnabled ui) $ do\n      cur <- readIORef (puCursorHiddenRef ui)\n      when (cur /= hidden) $ do\n        putStr (if hidden then \"\\ESC[?25l\" else \"\\ESC[?25h\")\n        writeIORef (puCursorHiddenRef ui) hidden\n\n-- | Render the current progress lines with one terminal row per live line.\nprogressRenderUnlocked :: ProgressUI -> IO ()\nprogressRenderUnlocked ui = do\n    (_, rows, cols) <- termSizeSync (puTermSize ui)\n    allLines <- readIORef (puLinesRef ui)\n    prevVisible <- readIORef (puVisibleRef ui)\n    let renderWidth = safeLiveWidth cols\n        visibleCap = min (puMaxLines ui) (max 0 (rows - 1))\n        lines = take visibleCap allLines\n        newVisible = length lines\n    if newVisible == 0\n      then do\n        setCursorHidden ui False\n        progressClearUnlocked ui\n      else do\n        when (prevVisible > 0) $\n          replicateM_ prevVisible (putStr \"\\ESC[1A\")\n        spinnerIx <- readIORef (puSpinnerRef ui)\n        let spinner = spinnerChars !! (spinnerIx `mod` length spinnerChars)\n            useSpinner = progressPrefixWidth cols > 0\n            prefix line\n              | useSpinner = termFitAnsiRight renderWidth (' ' : spinner : ' ' : line)\n              | otherwise = termFitAnsiRight renderWidth line\n        let renderLine i = do\n              putStr \"\\r\\ESC[2K\"\n              when (i < newVisible) $\n                putStr (prefix (lines !! i))\n              putStr \"\\n\"\n        setCursorHidden ui True\n        mapM_ renderLine [0 .. max prevVisible newVisible - 1]\n        hFlush stdout\n        writeIORef (puVisibleRef ui) (max prevVisible newVisible)\n\n-- | Start the progress heartbeat thread when needed.\nstartProgressTicker :: ProgressUI -> ProgressState -> IO ()\nstartProgressTicker ui st =\n    when (puEnabled ui) $ do\n      m <- readIORef (puTickerRef ui)\n      case m of\n        Just _ -> return ()\n        Nothing -> do\n          tid <- forkIO (progressTickerLoop ui st)\n          writeIORef (puTickerRef ui) (Just tid)\n\n-- | Stop the progress heartbeat thread.\nstopProgressTicker :: ProgressUI -> IO ()\nstopProgressTicker ui = do\n    m <- atomicModifyIORef' (puTickerRef ui) (\\cur -> (Nothing, cur))\n    forM_ m killThread\n\n-- | Heartbeat loop that redraws when the terminal is resized.\nprogressTickerLoop :: ProgressUI -> ProgressState -> IO ()\nprogressTickerLoop ui st = do\n    tid <- myThreadId\n    let loop = do\n          threadDelay progressTickMicros\n          keep <- withProgressLock ui $ do\n            active <- readIORef (psActive st)\n            if M.null active || not (puEnabled ui)\n              then return False\n              else do\n                modifyIORef' (puSpinnerRef ui) (+ 1)\n                progressRefreshUnlocked ui st\n                return True\n          when keep loop\n    loop\n    atomicModifyIORef' (puTickerRef ui) $ \\cur ->\n      if cur == Just tid then (Nothing, ()) else (cur, ())\n\n-- | Replace progress lines and redraw the UI.\nprogressSetLines :: ProgressUI -> ProgressState -> [String] -> IO ()\nprogressSetLines ui st lines = withProgressLock ui $ do\n    when (puEnabled ui) $ do\n      writeIORef (puLinesRef ui) lines\n      if null lines then stopProgressTicker ui else startProgressTicker ui st\n      progressRenderUnlocked ui\n\n-- | Clear active task state and remove any rendered progress lines.\nprogressReset :: ProgressUI -> ProgressState -> IO ()\nprogressReset ui st = withProgressLock ui $ do\n    writeIORef (psActive st) M.empty\n    writeIORef (psOrder st) []\n    writeIORef (puLinesRef ui) []\n    termProgressClear (puTermProgress ui)\n    when (puEnabled ui) $ do\n      stopProgressTicker ui\n      progressRenderUnlocked ui\n\n-- | Mark a task as active in the progress UI.\nprogressStartTask :: ProgressUI -> ProgressState -> TaskKey -> (Int -> BuildLineLayout) -> Maybe Double -> IO ()\nprogressStartTask ui st key renderLine mprog = withProgressLock ui $ do\n    now <- getTime Monotonic\n    modifyIORef' (psActive st) (M.insert key (ProgressTask renderLine now (fmap (\\x -> max 0 (min 1 x)) mprog)))\n    modifyIORef' (psOrder st) (\\xs -> if key `elem` xs then xs else xs ++ [key])\n    progressRefreshUnlocked ui st\n\n-- | Update the rendered line for an active progress task.\nprogressUpdateTask :: ProgressUI -> ProgressState -> TaskKey -> (Int -> BuildLineLayout) -> Maybe Double -> IO ()\nprogressUpdateTask ui st key renderLine mprog = withProgressLock ui $ do\n    modifyIORef' (psActive st) (M.adjust (\\task ->\n      task { ptRenderLine = renderLine\n           , ptProgress = fmap (\\x -> max 0 (min 1 x)) mprog\n           }) key)\n    progressRefreshUnlocked ui st\n\n-- | Remove a task from the progress UI.\nprogressDoneTask :: ProgressUI -> ProgressState -> TaskKey -> IO ()\nprogressDoneTask ui st key = withProgressLock ui $ do\n    modifyIORef' (psActive st) (M.delete key)\n    modifyIORef' (psOrder st) (filter (/= key))\n    progressRefreshUnlocked ui st\n\n-- | Recompute and render progress lines from active tasks.\nprogressRefreshUnlocked :: ProgressUI -> ProgressState -> IO ()\nprogressRefreshUnlocked ui st = do\n    active <- readIORef (psActive st)\n    order <- readIORef (psOrder st)\n    now <- getTime Monotonic\n    (_, _, cols) <- termSizeSync (puTermSize ui)\n    let renderCols = safeLiveWidth cols\n        spinnerPrefixWidth = progressPrefixWidth cols\n        timerMinWidth = length \"999.999 s\"\n    let progressDone = \"\\ESC[48;5;24m\"\n        progressReset = \"\\ESC[0m\"\n        paintProgressLine mprog line =\n          case mprog of\n            Just frac0 | puUseColor ui ->\n              let n = length line\n                  frac = max 0 (min 1 frac0)\n                  doneChars = max 0 (min n (floor (frac * fromIntegral n)))\n                  (done, todo) = splitAt doneChars line\n              in if null done\n                   then todo\n                   else progressDone ++ done ++ progressReset ++ todo\n            _ -> line\n        betterLine best Nothing = best\n        betterLine Nothing cand = cand\n        betterLine best@(Just (bestScore, _)) cand@(Just (candScore, _))\n          | candScore > bestScore = cand\n          | otherwise = best\n        formatLine task =\n          let elapsedPrecise = fmtTimePrecise (diffTimeSpec now (ptStart task))\n              elapsedCompact = fmtTimeCompact (diffTimeSpec now (ptStart task))\n              timerWidth = max timerMinWidth (length elapsedPrecise)\n              liveCandidate timerRank timer =\n                let timerCols = if null timer then 0 else 1 + timerWidth\n                    bodyWidth = max 0 (renderCols - spinnerPrefixWidth - timerCols)\n                    layout = ptRenderLine task bodyWidth\n                    body = bllText layout\n                    line = body ++ if null timer then \"\" else \" \" ++ padLeft timerWidth timer\n                    score =\n                      ( if bllAligned layout then 1 :: Int else 0\n                      , if bllHasStatus layout then 1 :: Int else 0\n                      , bllLabelCols layout\n                      , timerRank\n                      )\n                in if null body || renderCols < spinnerPrefixWidth + length line\n                     then Nothing\n                     else Just (score, line)\n              line =\n                case foldl' betterLine Nothing\n                       [ liveCandidate 2 elapsedPrecise\n                       , liveCandidate 1 elapsedCompact\n                       , liveCandidate 0 \"\"\n                       ]\n                of\n                  Just (_, bestLine) -> bestLine\n                  Nothing -> bllText (ptRenderLine task (max 0 (renderCols - spinnerPrefixWidth)))\n          in paintProgressLine (ptProgress task) line\n        lines = [ formatLine task | key <- order, Just task <- [M.lookup key active] ]\n    when (puEnabled ui) $ do\n      writeIORef (puLinesRef ui) lines\n      if null lines then stopProgressTicker ui else startProgressTicker ui st\n      progressRenderUnlocked ui\n      termProgressHeartbeat (puTermProgress ui)\n\n-- | Format project labels relative to the root for logs.\nprojectLabel :: FilePath -> FilePath -> String\nprojectLabel root proj =\n    let rel = makeRelative root proj\n    in if rel == \".\" || \"..\" `isPrefixOf` rel\n         then takeFileName proj\n         else rel\n"
  },
  {
    "path": "compiler/acton/PkgCommands.hs",
    "content": "{-# LANGUAGE OverloadedStrings #-}\nmodule PkgCommands\n  ( installCommand\n  , uninstallCommand\n  , pkgAddCommand\n  , pkgRemoveCommand\n  , pkgUpgradeCommand\n  , pkgUpdateCommand\n  , pkgSearchCommand\n  , zigPkgAddCommand\n  , zigPkgRemoveCommand\n  , PackageEntry(..)\n  , RepoInfo(..)\n  , githubCloneUrl\n  , isGithubCommitSha\n  , parseGithubRepoUrl\n  , decodePackageIndex\n  , decodeAppPackageIndex\n  , matchesAllTerms\n  ) where\n\nimport Prelude hiding (readFile, writeFile)\n\nimport qualified Acton.BuildSpec as BuildSpec\nimport qualified Acton.CommandLineParser as C\nimport Acton.Compile (loadBuildSpec, throwProjectError)\n\nimport Control.Exception (IOException, SomeException, try, displayException, evaluate)\nimport Control.Concurrent (threadDelay)\nimport Control.Monad (filterM, forM, forM_, unless, when)\nimport Data.Char (isHexDigit, isSpace)\nimport Data.Foldable (toList)\nimport Data.List (dropWhileEnd, isPrefixOf, isSuffixOf, sortOn)\nimport Data.List.Split (splitOn)\nimport Data.Maybe (isJust)\nimport qualified Data.Map as M\nimport qualified Data.ByteString.Char8 as B\nimport qualified Data.ByteString.Lazy as BL\nimport qualified Data.Aeson as Aeson\nimport qualified Data.Aeson.Key as AesonKey\nimport qualified Data.Aeson.KeyMap as AesonKM\nimport qualified Data.Text as T\nimport Network.HTTP.Client (Manager, Response, httpLbs, parseRequest, requestHeaders, responseBody, responseStatus)\nimport Network.HTTP.Client.TLS (newTlsManager)\nimport Network.HTTP.Types.Header (Header)\nimport Network.HTTP.Types.Status (statusCode)\nimport System.Directory (Permissions, canonicalizePath, copyFile, createDirectoryIfMissing, doesDirectoryExist, doesFileExist, doesPathExist, getCurrentDirectory, getHomeDirectory, getPermissions, listDirectory, removeFile, setPermissions)\nimport System.Environment (getExecutablePath, lookupEnv)\nimport System.Exit (ExitCode(..))\nimport System.FilePath ((</>), takeDirectory)\nimport System.IO (IOMode(ReadMode, WriteMode), hClose, hGetContents, hPutStr, hPutStrLn, hSetEncoding, openFile, stderr, utf8)\nimport System.Process (CreateProcess(cwd), proc, readCreateProcessWithExitCode)\nimport qualified Text.Regex.TDFA as TDFA\n\ndata PackageEntry = PackageEntry\n    { pkgName        :: String\n    , pkgDescription :: String\n    , pkgRepoUrl     :: String\n    } deriving (Eq, Show)\n\ndata PackageIndexEntry = PackageIndexEntry\n    { indexName        :: String\n    , indexKinds       :: [String]\n    , indexDescription :: String\n    , indexRepoUrl     :: String\n    } deriving (Eq, Show)\n\ndata InstallManifest = InstallManifest\n    { manifestName      :: String\n    , manifestRepoUrl   :: String\n    , manifestRepoRef   :: Maybe String\n    , manifestCommit    :: String\n    , manifestHash      :: String\n    , manifestSourceDir :: FilePath\n    , manifestBinaries  :: [String]\n    } deriving (Eq, Show)\n\ndata RepoInfo = RepoInfo\n    { repoOwner :: String\n    , repoName  :: String\n    , repoRef   :: Maybe String\n    } deriving (Eq, Show)\n\ninstallCommand :: C.GlobalOptions -> C.InstallOptions -> IO ()\ninstallCommand gopts opts = do\n    let appName = C.installName opts\n        repoUrlArg = C.installRepoUrl opts\n        repoRefArg = normalizeMaybe (C.installRepoRef opts)\n        pkgNameArg = C.installPkgName opts\n    validateInstallName appName\n    manager <- newTlsManager\n    token <- resolveGithubToken (normalizeMaybe (C.installGithubToken opts))\n    repoUrl <-\n      if null repoUrlArg\n        then lookupRepoUrlFromIndexByKind \"app\" appName pkgNameArg\n        else do\n          ensureGithubUrl \"install\" repoUrlArg\n          return repoUrlArg\n    archiveUrl <- requireRight =<< resolveGithubArchiveUrl manager token repoUrl repoRefArg\n    commitSha <- requireRight (commitShaFromArchiveUrl archiveUrl)\n    zigExe <- getZigExe\n    archiveHash <- requireRight =<< zigFetchHash zigExe archiveUrl\n    sourceDir <- prepareInstallSource appName repoUrl commitSha\n    unless (C.quiet gopts) $\n      putStrLn (\"Building \" ++ appName ++ \" with acton build --release\")\n    actonExe <- getExecutablePath\n    runProcessChecked (Just sourceDir) actonExe [\"build\", \"--release\"]\n    binaries <- discoverBuiltBinaries sourceDir\n    installBuiltBinaries appName repoUrl repoRefArg commitSha archiveHash sourceDir binaries\n    unless (C.quiet gopts) $ do\n      home <- getHomeDirectory\n      let binDir = home </> \".acton\" </> \"bin\"\n      putStrLn (\"Installed \" ++ appName ++ \" to \" ++ binDir)\n\nuninstallCommand :: C.GlobalOptions -> C.UninstallOptions -> IO ()\nuninstallCommand gopts opts = do\n    let appName = C.uninstallName opts\n    validateInstallName appName\n    home <- getHomeDirectory\n    let binDir = home </> \".acton\" </> \"bin\"\n        installedDir = home </> \".acton\" </> \"installed\"\n        manifestPath = installedDir </> appName ++ \".json\"\n    exists <- doesFileExist manifestPath\n    if not exists\n      then unless (C.quiet gopts) $\n        putStrLn (\"Application package \" ++ appName ++ \" is not installed. Nothing to do.\")\n      else do\n        manifest <- readInstallManifest manifestPath\n        when (manifestName manifest /= appName) $\n          throwProjectError (\"ERROR: Install manifest \" ++ manifestPath ++ \" belongs to \" ++ manifestName manifest)\n        manifests <- readInstallManifests installedDir\n        let otherOwners = M.fromList\n              [ (bin, manifestName other)\n              | other <- manifests\n              , manifestName other /= appName\n              , bin <- manifestBinaries other\n              ]\n        forM_ (manifestBinaries manifest) $ \\binName ->\n          case M.lookup binName otherOwners of\n            Just owner ->\n              throwProjectError (\"ERROR: Cannot uninstall \" ++ appName ++ \": \" ++ binName ++ \" is also owned by \" ++ owner)\n            Nothing -> do\n              let dest = binDir </> binName\n              pathExists <- doesPathExist dest\n              fileExists <- doesFileExist dest\n              when (pathExists && not fileExists) $\n                throwProjectError (\"ERROR: Cannot uninstall \" ++ appName ++ \": \" ++ dest ++ \" is not a regular file\")\n              when fileExists (removeFile dest)\n        removeFile manifestPath\n        unless (C.quiet gopts) $\n          putStrLn (\"Uninstalled \" ++ appName)\n\npkgAddCommand :: C.GlobalOptions -> C.PkgAddOptions -> IO ()\npkgAddCommand _ opts = do\n    let depName = C.pkgAddName opts\n    validateDepName depName\n    cwd <- getCurrentDirectory\n    spec0 <- loadBuildSpec cwd\n    manager <- newTlsManager\n    token <- resolveGithubToken (normalizeMaybe (C.pkgAddGithubToken opts))\n    let urlArg = C.pkgAddUrl opts\n        repoUrlArg = C.pkgAddRepoUrl opts\n        repoRefArg = normalizeMaybe (C.pkgAddRepoRef opts)\n        pkgNameArg = C.pkgAddPkgName opts\n    (depUrl, depRepoUrl, depRepoRef) <- decideUrl manager token depName urlArg repoUrlArg repoRefArg pkgNameArg\n    zigExe <- getZigExe\n    hash <- requireRight =<< zigFetchHash zigExe depUrl\n    let (spec1, msgs) = upsertPkgDep spec0 depName depUrl hash depRepoUrl depRepoRef\n    mapM_ putStrLn msgs\n    writeBuildSpec spec1\n  where\n    decideUrl manager token depName urlArg repoUrlArg repoRefArg pkgNameArg\n      | not (null urlArg) && not (null repoUrlArg) =\n          throwProjectError \"ERROR: Specify either --url or --repo-url, not both.\"\n      | not (null urlArg) =\n          return (urlArg, Nothing, Nothing)\n      | not (null repoUrlArg) = do\n          ensureGithubUrl \"pkg add\" repoUrlArg\n          archive <- requireRight =<< resolveGithubArchiveUrl manager token repoUrlArg repoRefArg\n          return (archive, Just repoUrlArg, repoRefArg)\n      | otherwise = do\n          repoUrl <- lookupRepoUrlFromIndex depName pkgNameArg\n          ensureGithubUrl \"pkg add\" repoUrl\n          archive <- requireRight =<< resolveGithubArchiveUrl manager token repoUrl repoRefArg\n          return (archive, Just repoUrl, repoRefArg)\n\npkgRemoveCommand :: C.GlobalOptions -> C.PkgRemoveOptions -> IO ()\npkgRemoveCommand _ opts = do\n    let depName = C.pkgRemoveName opts\n    validateDepName depName\n    cwd <- getCurrentDirectory\n    spec <- loadBuildSpec cwd\n    let deps = BuildSpec.dependencies spec\n    if M.member depName deps\n      then do\n        putStrLn (\"Removed package dependency \" ++ depName)\n        let spec' = spec { BuildSpec.dependencies = M.delete depName deps }\n        writeBuildSpec spec'\n      else putStrLn (\"Dependency \" ++ depName ++ \" not found in build configuration. Nothing to do.\")\n\npkgUpgradeCommand :: C.GlobalOptions -> C.PkgUpgradeOptions -> IO ()\npkgUpgradeCommand _ opts = do\n    cwd <- getCurrentDirectory\n    spec <- loadBuildSpec cwd\n    let deps = BuildSpec.dependencies spec\n    manager <- newTlsManager\n    token <- resolveGithubToken (normalizeMaybe (C.pkgUpgradeGithubToken opts))\n    resolved <- mapM (resolveDep manager token) (M.toList deps)\n    let newUrls = M.fromList [ (n,u) | Just (n,u) <- resolved ]\n    if M.null newUrls\n      then putStrLn \"No dependencies to upgrade\"\n      else do\n        zigExe <- getZigExe\n        hashes <- mapM (fetchHash zigExe deps) (M.toList newUrls)\n        let newHashes = M.fromList [ (n,h) | Just (n,h) <- hashes ]\n        if M.null newHashes\n          then putStrLn \"No dependencies to upgrade\"\n          else do\n            let (spec', updated) = applyUpgrades spec newUrls newHashes\n            if updated\n              then do\n                putStrLn \"Wrote changes to Build.act\"\n                writeBuildSpec spec'\n              else putStrLn \"No changes to Build.act\"\n  where\n    resolveDep manager token (depName, dep) =\n      case BuildSpec.repo_url dep of\n        Nothing -> do\n          hPutStrLn stderr (depName ++ \" - skipping upgrade: repo_url not set\")\n          return Nothing\n        Just repoUrl -> do\n          if not (isGithubUrl repoUrl)\n            then do\n              hPutStrLn stderr (depName ++ \" - skipping upgrade: Unsupported git forge URL for \" ++ depName ++ \": \" ++ repoUrl ++ \" only https://github.com is supported\")\n              return Nothing\n            else do\n              putStrLn (depName ++ \" - fetching ref from \" ++ repoUrl)\n              res <- resolveGithubArchiveUrl manager token repoUrl (BuildSpec.repo_ref dep)\n              case res of\n                Left err -> do\n                  hPutStrLn stderr (\"Error fetching ref for \" ++ depName ++ \": \" ++ err)\n                  return Nothing\n                Right url -> return (Just (depName, url))\n\n    fetchHash zigExe deps (depName, url) =\n      case M.lookup depName deps of\n        Nothing -> return Nothing\n        Just dep ->\n          case BuildSpec.url dep of\n            Just oldUrl | oldUrl == url -> return Nothing\n            _ -> do\n              res <- zigFetchHash zigExe url\n              case res of\n                Left err -> do\n                  putStrLn (\"Error fetching updated hash for \" ++ depName ++ \" \" ++ err)\n                  return Nothing\n                Right h -> return (Just (depName, h))\n\n    applyUpgrades spec newUrls newHashes =\n      let deps = BuildSpec.dependencies spec\n          (deps', updated) = M.foldlWithKey' applyOne (deps, False) deps\n      in (spec { BuildSpec.dependencies = deps' }, updated)\n      where\n        applyOne (acc, changed) depName dep =\n          case (M.lookup depName newUrls, M.lookup depName newHashes) of\n            (Just newUrl, Just newHash) ->\n              if BuildSpec.url dep /= Just newUrl || BuildSpec.hash dep /= Just newHash\n                then let dep' = dep { BuildSpec.url = Just newUrl, BuildSpec.hash = Just newHash }\n                     in (M.insert depName dep' acc, True)\n                else (acc, changed)\n            _ -> (acc, changed)\n\npkgUpdateCommand :: C.GlobalOptions -> IO ()\npkgUpdateCommand _ = do\n    let indexUrl = \"https://actonlang.github.io/package-index/index.json\"\n    manager <- newTlsManager\n    body <- requireRightWith (\"ERROR: Failed to download package index from \" ++ indexUrl ++ \": \") =<< httpGet manager [] indexUrl\n    home <- getHomeDirectory\n    let indexDir = home </> \".cache\" </> \"acton\"\n        indexPath = indexDir </> \"package-index.json\"\n    createDirectoryIfMissing True indexDir\n    BL.writeFile indexPath body\n    putStrLn (\"Updated package index at \" ++ indexPath)\n\npkgSearchCommand :: C.GlobalOptions -> C.PkgSearchOptions -> IO ()\npkgSearchCommand _ opts = do\n    home <- getHomeDirectory\n    let indexPath = home </> \".cache\" </> \"acton\" </> \"package-index.json\"\n    exists <- doesFileExist indexPath\n    unless exists $\n      throwProjectError (\"No package index found at \" ++ indexPath ++ \"\\nHINT: Run 'acton pkg update' to create or refresh it.\")\n    content <- readIndexFile indexPath\n    pkgs <- requireRight (decodePackageIndex content)\n    let terms = C.pkgSearchTerms opts\n    regexes <- compileTerms terms\n    let matched = filter (matchesAllRegexes regexes) pkgs\n    let printPkg pkg = do\n          putStrLn (pkgName pkg)\n          putStrLn (\"  \" ++ pkgDescription pkg)\n          putStrLn (\"  \" ++ pkgRepoUrl pkg)\n          putStrLn \"\"\n    if null matched\n      then putStrLn \"No packages matched your search.\"\n      else forM_ (sortOn pkgName matched) printPkg\n\nzigPkgAddCommand :: C.GlobalOptions -> C.ZigPkgAddOptions -> IO ()\nzigPkgAddCommand _ opts = do\n    let depName = C.zigPkgAddName opts\n        depUrl = C.zigPkgAddUrl opts\n        depArtifacts = C.zigPkgAddArtifacts opts\n    validateDepName depName\n    cwd <- getCurrentDirectory\n    spec0 <- loadBuildSpec cwd\n    zigExe <- getZigExe\n    hash <- requireRight =<< zigFetchHash zigExe depUrl\n    let (spec1, msgs) = upsertZigDep spec0 depName depUrl hash depArtifacts\n    mapM_ putStrLn msgs\n    writeBuildSpec spec1\n\nzigPkgRemoveCommand :: C.GlobalOptions -> C.ZigPkgRemoveOptions -> IO ()\nzigPkgRemoveCommand _ opts = do\n    let depName = C.zigPkgRemoveName opts\n    validateDepName depName\n    cwd <- getCurrentDirectory\n    spec <- loadBuildSpec cwd\n    let deps = BuildSpec.zig_dependencies spec\n    if M.member depName deps\n      then do\n        putStrLn (\"Removed Zig package dependency \" ++ depName)\n        let spec' = spec { BuildSpec.zig_dependencies = M.delete depName deps }\n        writeBuildSpec spec'\n      else putStrLn (\"Zig dependency \" ++ depName ++ \" not found in build configuration. Nothing to do.\")\n\nprepareInstallSource :: String -> String -> String -> IO FilePath\nprepareInstallSource appName repoUrl commitSha = do\n    home <- getHomeDirectory\n    let appsDir = home </> \".cache\" </> \"acton\" </> \"apps\"\n        sourceDir = appsDir </> appName ++ \"-\" ++ take 12 commitSha\n        cloneUrl = githubCloneUrl repoUrl\n    createDirectoryIfMissing True appsDir\n    exists <- doesDirectoryExist sourceDir\n    unless exists $\n      runProcessChecked Nothing \"git\" [\"clone\", \"--quiet\", \"--no-checkout\", cloneUrl, sourceDir]\n    runProcessChecked (Just sourceDir) \"git\" [\"fetch\", \"--quiet\", \"origin\", commitSha]\n    runProcessChecked (Just sourceDir) \"git\" [\"checkout\", \"--quiet\", \"--force\", \"--detach\", commitSha]\n    runProcessChecked (Just sourceDir) \"git\" [\"clean\", \"-fdx\", \"--quiet\"]\n    return sourceDir\n\ngithubCloneUrl :: String -> String\ngithubCloneUrl = takeWhile (/= '#')\n\ndiscoverBuiltBinaries :: FilePath -> IO [(FilePath, String, Permissions)]\ndiscoverBuiltBinaries sourceDir = do\n    let binDir = sourceDir </> \"out\" </> \"bin\"\n    exists <- doesDirectoryExist binDir\n    unless exists $\n      throwProjectError (\"ERROR: Build produced no out/bin directory in \" ++ sourceDir)\n    names <- listDirectory binDir\n    files <- filterM (\\name -> doesFileExist (binDir </> name)) names\n    when (null files) $\n      throwProjectError (\"ERROR: Build produced no binaries in \" ++ binDir)\n    forM (sortOn id files) $ \\name -> do\n      let src = binDir </> name\n      perms <- getPermissions src\n      return (src, name, perms)\n\ninstallBuiltBinaries :: String -> String -> Maybe String -> String -> String -> FilePath -> [(FilePath, String, Permissions)] -> IO ()\ninstallBuiltBinaries appName repoUrl repoRefArg commitSha archiveHash sourceDir binaries = do\n    home <- getHomeDirectory\n    let actonDir = home </> \".acton\"\n        binDir = actonDir </> \"bin\"\n        installedDir = actonDir </> \"installed\"\n        manifestPath = installedDir </> appName ++ \".json\"\n    createDirectoryIfMissing True binDir\n    createDirectoryIfMissing True installedDir\n    manifests <- readInstallManifests installedDir\n    let ownerByBin = M.fromList\n          [ (bin, manifestName manifest)\n          | manifest <- manifests\n          , bin <- manifestBinaries manifest\n          ]\n        oldManifest = findManifest appName manifests\n    forM_ binaries $ \\(_, binName, _) -> do\n      let dest = binDir </> binName\n      case M.lookup binName ownerByBin of\n        Just owner | owner /= appName ->\n          throwProjectError (\"ERROR: Cannot install \" ++ appName ++ \": \" ++ dest ++ \" is owned by \" ++ owner)\n        _ -> return ()\n      exists <- doesPathExist dest\n      when (exists && M.lookup binName ownerByBin == Nothing) $\n        throwProjectError (\"ERROR: Cannot install \" ++ appName ++ \": \" ++ dest ++ \" already exists and is not managed by Acton\")\n    forM_ binaries $ \\(src, binName, perms) -> do\n      let dest = binDir </> binName\n      copyFile src dest\n      setPermissions dest perms\n    case oldManifest of\n      Nothing -> return ()\n      Just manifest -> do\n        let newBins = map (\\(_, binName, _) -> binName) binaries\n            staleBins = filter (`notElem` newBins) (manifestBinaries manifest)\n        forM_ staleBins $ \\binName -> do\n          let dest = binDir </> binName\n          exists <- doesFileExist dest\n          when exists (removeFile dest)\n    writeInstallManifest manifestPath InstallManifest\n      { manifestName = appName\n      , manifestRepoUrl = repoUrl\n      , manifestRepoRef = repoRefArg\n      , manifestCommit = commitSha\n      , manifestHash = archiveHash\n      , manifestSourceDir = sourceDir\n      , manifestBinaries = map (\\(_, binName, _) -> binName) binaries\n      }\n\nfindManifest :: String -> [InstallManifest] -> Maybe InstallManifest\nfindManifest appName = go\n  where\n    go [] = Nothing\n    go (manifest:rest)\n      | manifestName manifest == appName = Just manifest\n      | otherwise = go rest\n\nreadInstallManifests :: FilePath -> IO [InstallManifest]\nreadInstallManifests installedDir = do\n    exists <- doesDirectoryExist installedDir\n    if not exists\n      then return []\n      else do\n        names <- listDirectory installedDir\n        let jsonFiles = filter (\".json\" `isSuffixOf`) names\n        mapM (readInstallManifest . (installedDir </>)) jsonFiles\n\nreadInstallManifest :: FilePath -> IO InstallManifest\nreadInstallManifest path = do\n    content <- readIndexFile path\n    case Aeson.eitherDecode content of\n      Left err -> throwProjectError (\"ERROR: Failed to parse install manifest \" ++ path ++ \": \" ++ err)\n      Right (Aeson.Object obj) ->\n        case ( lookupString \"name\" obj\n             , lookupString \"repo_url\" obj\n             , lookupString \"commit\" obj\n             , lookupString \"hash\" obj\n             , lookupString \"source_dir\" obj\n             , lookupStringList \"binaries\" obj\n             ) of\n          (Just n, Just ru, Just c, Just h, Just src, Just bins) ->\n            return InstallManifest\n              { manifestName = n\n              , manifestRepoUrl = ru\n              , manifestRepoRef = lookupString \"repo_ref\" obj\n              , manifestCommit = c\n              , manifestHash = h\n              , manifestSourceDir = src\n              , manifestBinaries = bins\n              }\n          _ ->\n            throwProjectError (\"ERROR: Invalid install manifest \" ++ path)\n      Right _ ->\n        throwProjectError (\"ERROR: Invalid install manifest \" ++ path)\n\nwriteInstallManifest :: FilePath -> InstallManifest -> IO ()\nwriteInstallManifest path manifest =\n    BL.writeFile path (Aeson.encode (Aeson.object (manifestFields manifest)))\n  where\n    manifestFields manifest =\n      [ \"name\" Aeson..= manifestName manifest\n      , \"repo_url\" Aeson..= manifestRepoUrl manifest\n      , \"commit\" Aeson..= manifestCommit manifest\n      , \"hash\" Aeson..= manifestHash manifest\n      , \"source_dir\" Aeson..= manifestSourceDir manifest\n      , \"binaries\" Aeson..= manifestBinaries manifest\n      ] ++ repoRefField manifest\n    repoRefField manifest =\n      case manifestRepoRef manifest of\n        Nothing -> []\n        Just repoRef -> [\"repo_ref\" Aeson..= repoRef]\n\nupsertPkgDep :: BuildSpec.BuildSpec -> String -> String -> String -> Maybe String -> Maybe String -> (BuildSpec.BuildSpec, [String])\nupsertPkgDep spec depName depUrl depHash depRepoUrl depRepoRef =\n    case M.lookup depName (BuildSpec.dependencies spec) of\n      Just dep ->\n        let (msgs1, dep1) = updateUrl dep\n            (msgs2, dep2) = updateHash dep1\n            dep3 = case depRepoUrl of\n                     Nothing -> dep2\n                     Just ru -> dep2 { BuildSpec.repo_url = Just ru, BuildSpec.repo_ref = depRepoRef }\n            deps' = M.insert depName dep3 (BuildSpec.dependencies spec)\n        in (spec { BuildSpec.dependencies = deps' }, msgs1 ++ msgs2)\n      Nothing ->\n        let newDep = BuildSpec.PkgDep\n              { BuildSpec.url = Just depUrl\n              , BuildSpec.hash = Just depHash\n              , BuildSpec.path = Nothing\n              , BuildSpec.repo_url = depRepoUrl\n              , BuildSpec.repo_ref = depRepoRef\n              }\n            deps' = M.insert depName newDep (BuildSpec.dependencies spec)\n        in (spec { BuildSpec.dependencies = deps' }, [\"Added new package dependency \" ++ depName ++ \" with hash \" ++ depHash])\n  where\n    updateUrl dep =\n      case BuildSpec.url dep of\n        Just old | old /= depUrl ->\n          ([\"Updated existing dependency \" ++ depName ++ \" with new URL \" ++ depUrl ++ \" (old \" ++ showMaybe (Just old) ++ \")\"], dep { BuildSpec.url = Just depUrl })\n        Nothing ->\n          ([\"Updated existing dependency \" ++ depName ++ \" with new URL \" ++ depUrl ++ \" (old \" ++ showMaybe Nothing ++ \")\"], dep { BuildSpec.url = Just depUrl })\n        _ -> ([], dep)\n\n    updateHash dep =\n      case BuildSpec.hash dep of\n        Just old | old == depHash ->\n          ([\"Dependency \" ++ depName ++ \" is already up to date, hash: \" ++ depHash], dep)\n        Just old ->\n          ([\"Updated existing dependency \" ++ depName ++ \" with new hash \" ++ depHash ++ \" (old \" ++ showMaybe (Just old) ++ \")\"], dep { BuildSpec.hash = Just depHash })\n        Nothing ->\n          ([\"Updated existing dependency \" ++ depName ++ \" with new hash \" ++ depHash ++ \" (old \" ++ showMaybe Nothing ++ \")\"], dep { BuildSpec.hash = Just depHash })\n\nupsertZigDep :: BuildSpec.BuildSpec -> String -> String -> String -> [String] -> (BuildSpec.BuildSpec, [String])\nupsertZigDep spec depName depUrl depHash depArtifacts =\n    case M.lookup depName (BuildSpec.zig_dependencies spec) of\n      Just dep ->\n        let (msgs1, dep1) = updateUrl dep\n            (msgs2, dep2) = updateHash dep1\n            deps' = M.insert depName dep2 (BuildSpec.zig_dependencies spec)\n        in (spec { BuildSpec.zig_dependencies = deps' }, msgs1 ++ msgs2)\n      Nothing ->\n        let newDep = BuildSpec.ZigDep\n              { BuildSpec.zurl = Just depUrl\n              , BuildSpec.zhash = Just depHash\n              , BuildSpec.zpath = Nothing\n              , BuildSpec.options = M.empty\n              , BuildSpec.artifacts = depArtifacts\n              }\n            deps' = M.insert depName newDep (BuildSpec.zig_dependencies spec)\n        in (spec { BuildSpec.zig_dependencies = deps' }, [\"Added new Zig package dependency \" ++ depName ++ \" with hash \" ++ depHash])\n  where\n    updateUrl dep =\n      case BuildSpec.zurl dep of\n        Just old | old /= depUrl ->\n          ([\"Updated existing dependency \" ++ depName ++ \" with new URL \" ++ depUrl ++ \" (old \" ++ showMaybe (Just old) ++ \")\"], dep { BuildSpec.zurl = Just depUrl })\n        Nothing ->\n          ([\"Updated existing dependency \" ++ depName ++ \" with new URL \" ++ depUrl ++ \" (old \" ++ showMaybe Nothing ++ \")\"], dep { BuildSpec.zurl = Just depUrl })\n        _ -> ([], dep)\n\n    updateHash dep =\n      case BuildSpec.zhash dep of\n        Just old | old == depHash ->\n          ([\"Dependency \" ++ depName ++ \" is already up to date, hash: \" ++ depHash], dep)\n        Just old ->\n          ([\"Updated existing dependency \" ++ depName ++ \" with new hash \" ++ depHash ++ \" (old \" ++ showMaybe (Just old) ++ \")\"], dep { BuildSpec.zhash = Just depHash })\n        Nothing ->\n          ([\"Updated existing dependency \" ++ depName ++ \" with new hash \" ++ depHash ++ \" (old \" ++ showMaybe Nothing ++ \")\"], dep { BuildSpec.zhash = Just depHash })\n\nwriteBuildSpec :: BuildSpec.BuildSpec -> IO ()\nwriteBuildSpec spec = do\n    buildActExists <- doesFileExist \"Build.act\"\n    if not buildActExists\n      then throwProjectError \"Build.act not found in current directory\"\n      else do\n        content <- readFile \"Build.act\"\n        let jsonDoc = BuildSpec.encodeBuildSpecJSON spec\n        case BuildSpec.updateBuildActFromJSON content jsonDoc of\n          Left err -> throwProjectError (\"Failed to update Build.act: \\n\" ++ err)\n          Right updated -> writeFile \"Build.act\" updated\n\nlookupRepoUrlFromIndex :: String -> String -> IO String\nlookupRepoUrlFromIndex = lookupRepoUrlFromIndexByKind \"library\"\n\nlookupRepoUrlFromIndexByKind :: String -> String -> String -> IO String\nlookupRepoUrlFromIndexByKind wantedKind depName pkgNameArg = do\n    home <- getHomeDirectory\n    let indexPath = home </> \".cache\" </> \"acton\" </> \"package-index.json\"\n    exists <- doesFileExist indexPath\n    unless exists $\n      throwProjectError (\"ERROR: Package index not found at \" ++ indexPath ++ \"\\nHINT: Run: acton pkg update\")\n    content <- readIndexFile indexPath\n    entries <- requireRight (decodePackageIndexEntries content)\n    let pkgName = if null pkgNameArg then depName else pkgNameArg\n        matchEntry e = indexName e == pkgName\n    case filter matchEntry entries of\n      [] -> throwProjectError (\"ERROR: Package \" ++ pkgName ++ \" not found in package index\")\n      entriesForName ->\n        case filter (elem wantedKind . indexKinds) entriesForName of\n          (entry:_) -> return (indexRepoUrl entry)\n          [] -> throwProjectError (\"ERROR: Package \" ++ pkgName ++ \" is not an acton-\" ++ wantedKind ++ \" package\")\n\ndecodePackageIndex :: BL.ByteString -> Either String [PackageEntry]\ndecodePackageIndex = decodePackageIndexByKind \"library\"\n\ndecodeAppPackageIndex :: BL.ByteString -> Either String [PackageEntry]\ndecodeAppPackageIndex = decodePackageIndexByKind \"app\"\n\ndecodePackageIndexByKind :: String -> BL.ByteString -> Either String [PackageEntry]\ndecodePackageIndexByKind wantedKind content = do\n    entries <- decodePackageIndexEntries content\n    let pkgs = [ PackageEntry n d r\n               | PackageIndexEntry n ks d r <- entries\n               , wantedKind `elem` ks\n               ]\n    return pkgs\n\ndecodePackageIndexEntries :: BL.ByteString -> Either String [PackageIndexEntry]\ndecodePackageIndexEntries content =\n    case Aeson.eitherDecode content of\n      Left err -> Left (\"ERROR: Failed to parse package index JSON: \" ++ err)\n      Right (Aeson.Object obj) ->\n        case AesonKM.lookup (AesonKey.fromString \"packages\") obj of\n          Just (Aeson.Array arr) -> mapM parseEntry (zip [0 :: Int ..] (toList arr))\n          _ -> Left \"ERROR: Invalid package index: top-level 'packages' list missing or wrong type\"\n      Right _ ->\n        Left \"ERROR: Invalid package index: top-level 'packages' list missing or wrong type\"\n  where\n    parseEntry (idx, Aeson.Object o) =\n      case ( lookupString \"name\" o\n           , lookupStringList \"kinds\" o\n           , lookupString \"description\" o\n           , lookupString \"repo_url\" o\n           ) of\n        (Just n, Just ks, Just d, Just r)\n          | null ks ->\n              Left (\"ERROR: Invalid package index entry \" ++ show idx ++ \": expected at least one kind\")\n          | all validPackageKind ks -> Right (PackageIndexEntry n ks d r)\n          | otherwise ->\n              Left (\"ERROR: Invalid package index entry \" ++ show idx ++ \": unsupported kind in 'kinds'\")\n        _ ->\n          Left (\"ERROR: Invalid package index entry \" ++ show idx ++ \": expected name, kinds, description, and repo_url\")\n    parseEntry (idx, _) =\n      Left (\"ERROR: Invalid package index entry \" ++ show idx ++ \": expected object\")\n\n    validPackageKind k = k == \"library\" || k == \"app\"\n\nmatchesAllTerms :: [String] -> PackageEntry -> IO Bool\nmatchesAllTerms terms pkg = do\n    regexes <- compileTerms terms\n    return (matchesAllRegexes regexes pkg)\n\ncompileTerms :: [String] -> IO [TDFA.Regex]\ncompileTerms terms =\n    mapM compileRegex (filter (not . null) terms)\n\ncompileRegex :: String -> IO TDFA.Regex\ncompileRegex pattern = do\n    res <- try (evaluate (TDFA.makeRegex (\"^\" ++ pattern) :: TDFA.Regex)) :: IO (Either SomeException TDFA.Regex)\n    case res of\n      Left err -> throwProjectError (\"ERROR: Invalid regex '\" ++ pattern ++ \"': \" ++ displayException err)\n      Right re -> return re\n\nmatchesAllRegexes :: [TDFA.Regex] -> PackageEntry -> Bool\nmatchesAllRegexes regexes pkg =\n    let haystack = pkgName pkg ++ \" \" ++ pkgDescription pkg ++ \" \" ++ pkgRepoUrl pkg\n    in all (\\re -> isJust (TDFA.matchOnceText re haystack)) regexes\n\nparseGithubRepoUrl :: String -> Either String RepoInfo\nparseGithubRepoUrl url =\n    case stripPrefixGithub url of\n      Nothing -> Left \"Unsupported git forge URL\"\n      Just rest -> do\n        let (pathPart, refPart) = break (== '#') rest\n            refVal = if null refPart then Nothing else Just (drop 1 refPart)\n            path = dropWhile (== '/') (dropGitSuffix pathPart)\n            parts = filter (not . null) (splitOn \"/\" path)\n        if length parts < 2\n          then Left \"No path in URL\"\n          else do\n            let owner = parts !! (length parts - 2)\n                repo = parts !! (length parts - 1)\n            Right (RepoInfo owner repo refVal)\n  where\n    stripPrefixGithub s\n      | prefix `isPrefixOf` s = Just (drop (length prefix) s)\n      | otherwise = Nothing\n      where\n        prefix = \"https://github.com\" :: String\n\n    dropGitSuffix s =\n      if \".git\" `isSuffixOf` s then take (length s - 4) s else s\n\ncommitShaFromArchiveUrl :: String -> Either String String\ncommitShaFromArchiveUrl url =\n    case splitOn \"/archive/\" url of\n      [_, archiveName]\n        | \".zip\" `isSuffixOf` archiveName ->\n            let zipSuffix = \".zip\" :: String\n                sha = take (length archiveName - length zipSuffix) archiveName\n            in if null sha\n                 then Left (\"Unable to determine commit SHA from \" ++ url)\n                 else Right sha\n      _ -> Left (\"Unable to determine commit SHA from \" ++ url)\n\nresolveGithubArchiveUrl :: Manager -> Maybe String -> String -> Maybe String -> IO (Either String String)\nresolveGithubArchiveUrl manager token repoUrl repoRefArg = do\n    case parseGithubRepoUrl repoUrl of\n      Left err -> return (Left err)\n      Right info -> do\n        ref <- selectRef manager token info repoRefArg\n        case ref of\n          Left err -> return (Left err)\n          Right refName -> do\n            sha <- fetchRefSha manager token info refName\n            case sha of\n              Left err -> return (Left err)\n              Right shaVal ->\n                return (Right (\"https://github.com/\" ++ repoOwner info ++ \"/\" ++ repoName info ++ \"/archive/\" ++ shaVal ++ \".zip\"))\n  where\n    selectRef manager token info refArg =\n      case refArg of\n        Just refVal ->\n          case repoRef info of\n            Just urlRef | urlRef /= refVal -> return (Left \"Ref mismatch\")\n            _ -> return (Right refVal)\n        Nothing ->\n          case repoRef info of\n            Just urlRef -> return (Right urlRef)\n            Nothing -> fetchDefaultBranch manager token info\n\nfetchDefaultBranch :: Manager -> Maybe String -> RepoInfo -> IO (Either String String)\nfetchDefaultBranch manager token info = do\n    let url = \"https://api.github.com/repos/\" ++ repoOwner info ++ \"/\" ++ repoName info\n    obj <- fetchGithubObject manager token url\n    case obj of\n      Left err -> return (Left err)\n      Right o ->\n        case lookupMessage o of\n          Just msg -> return (Left (\"Unable to retrieve branch information: \" ++ msg))\n          Nothing ->\n            case lookupString \"default_branch\" o of\n              Just branch -> return (Right branch)\n              Nothing -> return (Left (\"No default branch:\" ++ B.unpack (BL.toStrict (Aeson.encode (Aeson.Object o)))))\n\nfetchRefSha :: Manager -> Maybe String -> RepoInfo -> String -> IO (Either String String)\nfetchRefSha manager token info refName = do\n    if isGithubCommitSha refName\n      then return (Right refName)\n      else do\n        branch <- fetchGitRefSha manager token info (\"heads/\" ++ refName)\n        case branch of\n          Right shaVal -> return (Right shaVal)\n          Left branchErr -> do\n            tag <- fetchGitRefSha manager token info (\"tags/\" ++ refName)\n            case tag of\n              Right shaVal -> return (Right shaVal)\n              Left tagErr -> do\n                commit <- fetchCommitSha manager token info refName\n                case commit of\n                  Right shaVal -> return (Right shaVal)\n                  Left commitErr ->\n                    return (Left (\"Unable to resolve ref '\" ++ refName ++ \"' as branch, tag, or commit SHA: \"\n                               ++ branchErr ++ \"; \" ++ tagErr ++ \"; \" ++ commitErr))\n\nisGithubCommitSha :: String -> Bool\nisGithubCommitSha refName =\n    length refName == 40 && all isHexDigit refName\n\nfetchGitRefSha :: Manager -> Maybe String -> RepoInfo -> String -> IO (Either String String)\nfetchGitRefSha manager token info refName = do\n    let url = \"https://api.github.com/repos/\" ++ repoOwner info ++ \"/\" ++ repoName info ++ \"/git/refs/\" ++ refName\n    obj <- fetchGithubObject manager token url\n    case obj of\n      Left err -> return (Left err)\n      Right o ->\n        case lookupMessage o of\n          Just msg -> return (Left (\"Unable to retrieve ref information: \" ++ msg))\n          Nothing ->\n            case AesonKM.lookup (AesonKey.fromString \"object\") o of\n              Just (Aeson.Object obj) ->\n                case (lookupString \"type\" obj, lookupString \"sha\" obj) of\n                  (Just objType, Just shaVal) -> resolveGitObjectSha manager token info objType shaVal\n                  (_, Nothing) -> return (Left \"No SHA\")\n                  (Nothing, _) -> return (Left \"No object type\")\n              _ -> return (Left \"No object\")\n\nresolveGitObjectSha :: Manager -> Maybe String -> RepoInfo -> String -> String -> IO (Either String String)\nresolveGitObjectSha manager token info objType shaVal\n  | objType == \"commit\" = return (Right shaVal)\n  | objType == \"tag\" = fetchTagTargetSha manager token info shaVal 5\n  | otherwise = return (Left (\"Unsupported Git object type \" ++ objType))\n\nfetchTagTargetSha :: Manager -> Maybe String -> RepoInfo -> String -> Int -> IO (Either String String)\nfetchTagTargetSha _ _ _ _ 0 =\n    return (Left \"Annotated tag nesting too deep\")\nfetchTagTargetSha manager token info tagSha depth = do\n    let url = \"https://api.github.com/repos/\" ++ repoOwner info ++ \"/\" ++ repoName info ++ \"/git/tags/\" ++ tagSha\n    obj <- fetchGithubObject manager token url\n    case obj of\n      Left err -> return (Left err)\n      Right o ->\n        case lookupMessage o of\n          Just msg -> return (Left (\"Unable to retrieve tag information: \" ++ msg))\n          Nothing ->\n            case AesonKM.lookup (AesonKey.fromString \"object\") o of\n              Just (Aeson.Object target) ->\n                case (lookupString \"type\" target, lookupString \"sha\" target) of\n                  (Just objType, Just shaVal)\n                    | objType == \"tag\" -> fetchTagTargetSha manager token info shaVal (depth - 1)\n                    | otherwise -> resolveGitObjectSha manager token info objType shaVal\n                  (_, Nothing) -> return (Left \"No tag target SHA\")\n                  (Nothing, _) -> return (Left \"No tag target object type\")\n              _ -> return (Left \"No tag target object\")\n\nfetchCommitSha :: Manager -> Maybe String -> RepoInfo -> String -> IO (Either String String)\nfetchCommitSha manager token info refName = do\n    let url = \"https://api.github.com/repos/\" ++ repoOwner info ++ \"/\" ++ repoName info ++ \"/commits/\" ++ refName\n    obj <- fetchGithubObject manager token url\n    case obj of\n      Left err -> return (Left err)\n      Right o ->\n        case lookupMessage o of\n          Just msg -> return (Left (\"Unable to retrieve commit information: \" ++ msg))\n          Nothing ->\n            case lookupString \"sha\" o of\n              Just shaVal -> return (Right shaVal)\n              Nothing -> return (Left \"No commit SHA\")\n\nfetchGithubObject :: Manager -> Maybe String -> String -> IO (Either String Aeson.Object)\nfetchGithubObject manager token url = do\n    let authHeader =\n          case token of\n            Just t -> [(\"Authorization\", B.pack (\"Bearer \" ++ t))]\n            Nothing -> []\n        headers = (\"Accept\", \"application/vnd.github.v3+json\") : authHeader\n    body <- httpGet manager headers url\n    case body of\n      Left err -> return (Left (\"Failed to download \" ++ url ++ \": \" ++ err))\n      Right bs ->\n        case Aeson.eitherDecode bs of\n          Left err -> return (Left err)\n          Right (Aeson.Object obj) -> return (Right obj)\n          Right _ -> return (Left \"Invalid JSON response\")\n\nhttpGet :: Manager -> [Header] -> String -> IO (Either String BL.ByteString)\nhttpGet manager extraHeaders url = do\n    req0 <- parseRequest url\n    let headers = (\"User-Agent\", \"acton\") : extraHeaders\n        req = req0 { requestHeaders = headers ++ requestHeaders req0 }\n    let maxAttempts = 10\n        baseDelay = 500000\n        maxDelay = 120000000\n    let go attempt delay = do\n          res <- try (httpLbs req manager) :: IO (Either SomeException (Response BL.ByteString))\n          case res of\n            Left err ->\n              retryOrFail attempt delay (displayException err)\n            Right response -> do\n              let status = statusCode (responseStatus response)\n                  body = responseBody response\n              if status >= 200 && status < 300\n                then return (Right body)\n                else\n                  if shouldRetry status\n                    then retryOrFail attempt delay (httpErrorMessage status body)\n                    else return (Left (httpErrorMessage status body))\n        retryOrFail attempt delay errMsg\n          | attempt >= maxAttempts = return (Left errMsg)\n          | otherwise = do\n              threadDelay delay\n              go (attempt + 1) (min maxDelay (delay * 2))\n    go 1 baseDelay\n  where\n    shouldRetry status = status == 403 || status == 429 || status >= 500\n    httpErrorMessage status body =\n      let raw = trim (B.unpack (BL.toStrict body))\n          clipped = take 200 raw\n          suffix = if length raw > length clipped then \"...\" else \"\"\n          detail = if null clipped then \"\" else \": \" ++ clipped ++ suffix\n      in \"HTTP \" ++ show status ++ detail\n\nlookupString :: String -> Aeson.Object -> Maybe String\nlookupString key obj =\n    case AesonKM.lookup (AesonKey.fromString key) obj of\n      Just (Aeson.String s) -> Just (T.unpack s)\n      _ -> Nothing\n\nlookupStringList :: String -> Aeson.Object -> Maybe [String]\nlookupStringList key obj =\n    case AesonKM.lookup (AesonKey.fromString key) obj of\n      Just (Aeson.Array arr) -> mapM valueString (toList arr)\n      _ -> Nothing\n  where\n    valueString (Aeson.String s) = Just (T.unpack s)\n    valueString _ = Nothing\n\nlookupMessage :: Aeson.Object -> Maybe String\nlookupMessage = lookupString \"message\"\n\nnormalizeMaybe :: String -> Maybe String\nnormalizeMaybe s\n    | null s = Nothing\n    | otherwise = Just s\n\nresolveGithubToken :: Maybe String -> IO (Maybe String)\nresolveGithubToken tokenOpt = do\n    envToken <- lookupEnv \"GITHUB_TOKEN\"\n    return (selectToken tokenOpt envToken)\n  where\n    normalizeToken Nothing = Nothing\n    normalizeToken (Just s) = normalizeMaybe (trim s)\n    selectToken opt env =\n      case normalizeToken opt of\n        Just token -> Just token\n        Nothing -> normalizeToken env\n\nshowMaybe :: Maybe String -> String\nshowMaybe = maybe \"None\" id\n\nisGithubUrl :: String -> Bool\nisGithubUrl url = \"https://github.com\" `isPrefixOf` url\n\nensureGithubUrl :: String -> String -> IO ()\nensureGithubUrl cmd url =\n    unless (isGithubUrl url) $\n      throwProjectError (\"ERROR: Unsupported git forge URL for \" ++ cmd ++ \": \" ++ url ++ \" only https://github.com is supported\")\n\nrequireRight :: Either String a -> IO a\nrequireRight (Left err) = throwProjectError err\nrequireRight (Right val) = return val\n\nrequireRightWith :: String -> Either String a -> IO a\nrequireRightWith prefix (Left err) = throwProjectError (prefix ++ err)\nrequireRightWith _ (Right val) = return val\n\nreadIndexFile :: FilePath -> IO BL.ByteString\nreadIndexFile path = do\n    res <- try (BL.readFile path) :: IO (Either IOException BL.ByteString)\n    case res of\n      Left err -> throwProjectError (\"ERROR: Failed to read package index at \" ++ path ++ \": \" ++ displayException err)\n      Right content -> return content\n\nzigFetchHash :: FilePath -> String -> IO (Either String String)\nzigFetchHash zigExe depUrl = do\n    home <- getHomeDirectory\n    let globalCache = home </> \".cache\" </> \"acton\" </> \"zig-global-cache\"\n    createDirectoryIfMissing True globalCache\n    let cmd = proc zigExe [\"fetch\", \"--global-cache-dir\", globalCache, depUrl]\n    let maxAttempts = 10\n        baseDelay = 500000\n        maxDelay = 120000000\n    let go attempt delay = do\n          res <- try (readCreateProcessWithExitCode cmd \"\") :: IO (Either SomeException (ExitCode, String, String))\n          case res of\n            Left err ->\n              retryOrFail attempt delay (\"Error fetching \" ++ displayException err)\n            Right (ExitSuccess, out, _) -> return (Right (trim out))\n            Right (ExitFailure _, _, err) ->\n              retryOrFail attempt delay (\"Error fetching \" ++ trim err)\n        retryOrFail attempt delay errMsg\n          | attempt >= maxAttempts = return (Left errMsg)\n          | otherwise = do\n              threadDelay delay\n              go (attempt + 1) (min maxDelay (delay * 2))\n    go 1 baseDelay\n\nrunProcessChecked :: Maybe FilePath -> FilePath -> [String] -> IO ()\nrunProcessChecked cwdOpt exe args = do\n    res <- try (readCreateProcessWithExitCode command \"\") :: IO (Either SomeException (ExitCode, String, String))\n    case res of\n      Left err ->\n        throwProjectError (\"ERROR: Failed to run \" ++ unwords (exe:args) ++ \": \" ++ displayException err)\n      Right (ExitSuccess, _, _) ->\n        return ()\n      Right (ExitFailure code, out, err) ->\n        throwProjectError $\n          \"ERROR: Command failed (\" ++ show code ++ \"): \" ++ unwords (exe:args)\n          ++ renderOutput \"stdout\" out\n          ++ renderOutput \"stderr\" err\n  where\n    command = (proc exe args) { cwd = cwdOpt }\n    renderOutput label output =\n      let body = trim output\n      in if null body then \"\" else \"\\n\" ++ label ++ \":\\n\" ++ body\n\ngetZigExe :: IO FilePath\ngetZigExe = do\n    execDir <- takeDirectory <$> getExecutablePath\n    sysPath <- canonicalizePath (execDir </> \"..\")\n    return (sysPath </> \"zig\" </> \"zig\")\n\nvalidateDepName :: String -> IO ()\nvalidateDepName name =\n    unless (isValidDepName name) $\n      throwProjectError (\"Invalid dependency name '\" ++ name ++ \"', must start with a letter and only contain letters, numbers and underscores\")\n\nvalidateInstallName :: String -> IO ()\nvalidateInstallName name =\n    unless (isValidInstallName name) $\n      throwProjectError (\"Invalid application package name '\" ++ name ++ \"', must only contain letters, numbers, '.', '_' and '-'\")\n\nisValidInstallName :: String -> Bool\nisValidInstallName name =\n    not (null name)\n    && name /= \".\"\n    && name /= \"..\"\n    && all isValidInstallNameChar name\n\nisValidInstallNameChar :: Char -> Bool\nisValidInstallNameChar c =\n    isAsciiAlphaNumUnderscore c || c == '-' || c == '.'\n\nisValidDepName :: String -> Bool\nisValidDepName [] = False\nisValidDepName (c:cs) = isAsciiAlpha c && all isAsciiAlphaNumUnderscore cs\n\nisAsciiAlpha :: Char -> Bool\nisAsciiAlpha c = (c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z')\n\nisAsciiAlphaNumUnderscore :: Char -> Bool\nisAsciiAlphaNumUnderscore c = isAsciiAlpha c || (c >= '0' && c <= '9') || c == '_'\n\ntrim :: String -> String\ntrim = dropWhileEnd isSpace . dropWhile isSpace\n\nreadFile :: FilePath -> IO String\nreadFile f = do\n    h <- openFile f ReadMode\n    hSetEncoding h utf8\n    c <- hGetContents h\n    return c\n\nwriteFile :: FilePath -> String -> IO ()\nwriteFile f c = do\n    h <- openFile f WriteMode\n    hSetEncoding h utf8\n    hPutStr h c\n    hClose h\n"
  },
  {
    "path": "compiler/acton/TerminalProgress.hs",
    "content": "module TerminalProgress\n  ( TermProgress\n  , initTermProgress\n  , termProgressEnabled\n  , termProgressPercent\n  , termProgressIndeterminate\n  , termProgressClear\n  , termProgressHeartbeat\n  ) where\n\nimport qualified Acton.CommandLineParser as C\nimport Control.Monad (when)\nimport Data.Char (toLower)\nimport Data.IORef\nimport System.Environment (lookupEnv)\nimport System.IO (hFlush, hIsTerminalDevice, stdout)\nimport System.Clock (Clock(Monotonic), TimeSpec, getTime, toNanoSecs)\n\ndata TermProgress = TermProgress\n  { tpEnabled :: Bool\n  , tpLastRef :: IORef (Maybe (Int, Maybe Int))\n  , tpLastSentRef :: IORef (Maybe TimeSpec)\n  }\n\ntermProgressEnabled :: TermProgress -> Bool\ntermProgressEnabled = tpEnabled\n\ninitTermProgress :: C.GlobalOptions -> IO TermProgress\ninitTermProgress gopts = do\n    tty <- hIsTerminalDevice stdout\n    env <- lookupEnv \"ACTON_OSC_PROGRESS\"\n    let envSetting = env >>= parseBool\n        enabledByTty = (tty || C.tty gopts) && not (C.quiet gopts) && not (C.noProgress gopts)\n        enabled =\n          if C.noProgress gopts\n            then False\n            else case envSetting of\n                   Just True -> not (C.quiet gopts)\n                   Just False -> False\n                   Nothing -> enabledByTty\n    lastRef <- newIORef Nothing\n    lastSentRef <- newIORef Nothing\n    return TermProgress\n      { tpEnabled = enabled\n      , tpLastRef = lastRef\n      , tpLastSentRef = lastSentRef\n      }\n\nparseBool :: String -> Maybe Bool\nparseBool raw =\n    case map toLower raw of\n      \"1\" -> Just True\n      \"true\" -> Just True\n      \"yes\" -> Just True\n      \"on\" -> Just True\n      \"0\" -> Just False\n      \"false\" -> Just False\n      \"no\" -> Just False\n      \"off\" -> Just False\n      _ -> Nothing\n\ntermProgressPercent :: TermProgress -> Int -> IO ()\ntermProgressPercent tp pct = termProgressSet tp 1 (Just pct)\n\ntermProgressIndeterminate :: TermProgress -> IO ()\ntermProgressIndeterminate tp = termProgressSet tp 3 Nothing\n\ntermProgressClear :: TermProgress -> IO ()\ntermProgressClear tp = termProgressSet tp 0 Nothing\n\ntermProgressSet :: TermProgress -> Int -> Maybe Int -> IO ()\ntermProgressSet tp st mpr = when (tpEnabled tp) $ do\n    let st' = clamp 0 4 st\n        pr' = fmap (clamp 0 100) mpr\n        newState = if st' == 0 then Nothing else Just (st', pr')\n    prev <- readIORef (tpLastRef tp)\n    when (prev /= newState) $ do\n      putStr (oscSequence st' pr')\n      hFlush stdout\n      writeIORef (tpLastRef tp) newState\n      now <- getTime Monotonic\n      writeIORef (tpLastSentRef tp) (Just now)\n\noscSequence :: Int -> Maybe Int -> String\noscSequence st mpr =\n    let esc = \"\\x1b\"\n        bel = \"\\x07\"\n        base = esc ++ \"]9;4;\" ++ show st\n        body = case mpr of\n                 Nothing -> base\n                 Just p -> base ++ \";\" ++ show p\n    in body ++ bel\n\nclamp :: Int -> Int -> Int -> Int\nclamp lo hi v = max lo (min hi v)\n\nkeepaliveMicros :: Integer\nkeepaliveMicros = 1000000\n\ntermProgressHeartbeat :: TermProgress -> IO ()\ntermProgressHeartbeat tp = when (tpEnabled tp) $ do\n    mstate <- readIORef (tpLastRef tp)\n    case mstate of\n      Just (st, pr) -> do\n        now <- getTime Monotonic\n        mlast <- readIORef (tpLastSentRef tp)\n        let due = case mlast of\n                    Nothing -> True\n                    Just t ->\n                      let elapsed = toNanoSecs now - toNanoSecs t\n                      in elapsed >= keepaliveMicros * 1000\n        when due $ do\n          putStr (oscSequence st pr)\n          hFlush stdout\n          writeIORef (tpLastSentRef tp) (Just now)\n      Nothing -> return ()\n"
  },
  {
    "path": "compiler/acton/TerminalSize.hs",
    "content": "{-# LANGUAGE CApiFFI #-}\n\nmodule TerminalSize\n  ( TermSize\n  , initTermSize\n  , termSizeCurrent\n  , termSizeSync\n  , termSizeRead\n  , termVisibleLength\n  , termFitAnsiRight\n  , termFitPlainLeft\n  , termFitPlainRight\n  , termRenderedRows\n  , termRenderedRowsTotal\n  ) where\n\nimport Control.Exception (SomeException, try)\nimport Control.Monad (when)\nimport Data.IORef\nimport Data.List (isInfixOf)\nimport Foreign\nimport Foreign.C.Types\nimport System.Environment (lookupEnv)\nimport System.Posix.IO (stdOutput)\nimport System.Posix.Signals (Handler(..), installHandler)\n\ndata TermSize = TermSize\n  { tsEnabled :: Bool\n  , tsRowsRef :: IORef Int\n  , tsColsRef :: IORef Int\n  , tsDirtyRef :: IORef Bool\n  }\n\ndata WinSize = WinSize\n  { wsRows :: CUShort\n  , wsCols :: CUShort\n  , wsXPixel :: CUShort\n  , wsYPixel :: CUShort\n  }\n\ninstance Storable WinSize where\n    sizeOf _ = 8\n    alignment _ = alignment (undefined :: CUShort)\n    peek ptr =\n      WinSize\n        <$> peekByteOff ptr 0\n        <*> peekByteOff ptr 2\n        <*> peekByteOff ptr 4\n        <*> peekByteOff ptr 6\n    poke ptr (WinSize rows cols xp yp) = do\n      pokeByteOff ptr 0 rows\n      pokeByteOff ptr 2 cols\n      pokeByteOff ptr 4 xp\n      pokeByteOff ptr 6 yp\n\nforeign import capi unsafe \"sys/ioctl.h value TIOCGWINSZ\"\n  c_TIOCGWINSZ :: CULong\n\nforeign import capi unsafe \"signal.h value SIGWINCH\"\n  c_SIGWINCH :: CInt\n\nforeign import capi unsafe \"sys/ioctl.h ioctl\"\n  c_ioctlWinsize :: CInt -> CULong -> Ptr WinSize -> IO CInt\n\ndefaultRows :: Int\ndefaultRows = 24\n\ndefaultCols :: Int\ndefaultCols = 80\n\ninitTermSize :: Bool -> IO TermSize\ninitTermSize enabled = do\n    rows <- envOrDefault \"LINES\" defaultRows\n    cols <- envOrDefault \"COLUMNS\" defaultCols\n    rowsRef <- newIORef rows\n    colsRef <- newIORef cols\n    dirtyRef <- newIORef enabled\n    let ts = TermSize\n          { tsEnabled = enabled\n          , tsRowsRef = rowsRef\n          , tsColsRef = colsRef\n          , tsDirtyRef = dirtyRef\n          }\n    when enabled $ do\n      _ <- try (installHandler (fromIntegral c_SIGWINCH) (Catch (writeIORef dirtyRef True)) Nothing)\n             :: IO (Either SomeException Handler)\n      _ <- termSizeSync ts\n      return ()\n    return ts\n\ntermSizeSync :: TermSize -> IO (Bool, Int, Int)\ntermSizeSync ts\n  | not (tsEnabled ts) = do\n      (rows, cols) <- termSizeCurrent ts\n      return (False, rows, cols)\n  | otherwise = do\n      dirty <- atomicModifyIORef' (tsDirtyRef ts) (\\cur -> (False, cur))\n      if not dirty\n        then do\n          rows <- readIORef (tsRowsRef ts)\n          cols <- readIORef (tsColsRef ts)\n          return (False, rows, cols)\n        else do\n          prevRows <- readIORef (tsRowsRef ts)\n          prevCols <- readIORef (tsColsRef ts)\n          msize <- queryTermSize\n          case msize of\n            Just (rows, cols) -> do\n              writeIORef (tsRowsRef ts) rows\n              writeIORef (tsColsRef ts) cols\n              return (rows /= prevRows || cols /= prevCols, rows, cols)\n            Nothing -> return (False, prevRows, prevCols)\n\ntermSizeCurrent :: TermSize -> IO (Int, Int)\ntermSizeCurrent ts = do\n    rows <- readIORef (tsRowsRef ts)\n    cols <- readIORef (tsColsRef ts)\n    return (rows, cols)\n\ntermSizeRead :: TermSize -> IO (Int, Int)\ntermSizeRead ts = do\n    (_, rows, cols) <- termSizeSync ts\n    return (rows, cols)\n\ntermVisibleLength :: String -> Int\ntermVisibleLength = go 0\n  where\n    go acc [] = acc\n    go acc ('\\ESC':'[':xs) = go acc (dropAnsi xs)\n    go acc (_:xs) = go (acc + 1) xs\n\ntermFitAnsiRight :: Int -> String -> String\ntermFitAnsiRight width s\n  | width <= 0 = \"\"\n  | termVisibleLength s <= width = s\n  | otherwise =\n      let trimmed = go width s\n      in if \"\\ESC[\" `isInfixOf` trimmed then trimmed ++ \"\\ESC[0m\" else trimmed\n  where\n    go _ [] = []\n    go n _\n      | n <= 0 = []\n    go n ('\\ESC':'[':xs) =\n      let (esc, rest) = spanAnsi xs\n      in '\\ESC' : '[' : esc ++ go n rest\n    go n (x:xs) = x : go (n - 1) xs\n\ntermFitPlainRight :: Int -> String -> String\ntermFitPlainRight width s\n  | width <= 0 = \"\"\n  | length s <= width = s\n  | otherwise = take width s\n\ntermFitPlainLeft :: Int -> String -> String\ntermFitPlainLeft width s\n  | width <= 0 = \"\"\n  | length s <= width = s\n  | otherwise = drop (length s - width) s\n\ntermRenderedRows :: Int -> String -> Int\ntermRenderedRows width s\n  | width <= 0 = 1\n  | otherwise =\n      let visible = max 0 (termVisibleLength s)\n      in max 1 ((visible + width - 1) `div` width)\n\ntermRenderedRowsTotal :: Int -> [String] -> Int\ntermRenderedRowsTotal width = sum . map (termRenderedRows width)\n\nqueryTermSize :: IO (Maybe (Int, Int))\nqueryTermSize =\n    alloca $ \\ptr -> do\n      rc <- c_ioctlWinsize (fromIntegral stdOutput) c_TIOCGWINSZ ptr\n      if rc == -1\n        then return Nothing\n        else do\n          WinSize rows cols _ _ <- peek ptr\n          let rows' = fromIntegral rows\n              cols' = fromIntegral cols\n          if rows' > 0 && cols' > 0\n            then return (Just (rows', cols'))\n            else return Nothing\n\nenvOrDefault :: String -> Int -> IO Int\nenvOrDefault name fallback = do\n    raw <- lookupEnv name\n    case raw >>= readMaybeInt of\n      Just n | n > 0 -> return n\n      _ -> return fallback\n\nreadMaybeInt :: String -> Maybe Int\nreadMaybeInt s =\n    case reads s of\n      [(n, \"\")] -> Just n\n      _ -> Nothing\n\ndropAnsi :: String -> String\ndropAnsi [] = []\ndropAnsi (c:cs)\n  | c >= '@' && c <= '~' = cs\n  | otherwise = dropAnsi cs\n\nspanAnsi :: String -> (String, String)\nspanAnsi [] = ([], [])\nspanAnsi (c:cs)\n  | c >= '@' && c <= '~' = ([c], cs)\n  | otherwise =\n      let (prefix, rest) = spanAnsi cs\n      in (c : prefix, rest)\n"
  },
  {
    "path": "compiler/acton/TestFormat.hs",
    "content": "module TestFormat\n  ( formatTestStatus\n  , formatTestStatusLive\n  , formatTestLineWith\n  , formatTestLineFitted\n  , formatTestFinalLineRenderer\n  , formatTestLiveLineRenderer\n  , formatTestDetailLines\n  , testColorApply\n  , testColorBold\n  , testColorRed\n  , testColorGreen\n  , testColorYellow\n  , testColorReset\n  ) where\n\nimport Acton.Testing (TestResult(..))\nimport Data.Char (isSpace)\nimport Data.List (foldl', isPrefixOf, isInfixOf, intercalate)\nimport Data.Maybe (catMaybes, fromMaybe, isJust, listToMaybe, mapMaybe)\nimport qualified Data.Map as M\nimport TerminalSize (termFitPlainRight, termVisibleLength)\nimport qualified Data.Aeson as Aeson\nimport qualified Data.Aeson.Types as AesonTypes\nimport qualified Data.Aeson.Key as AesonKey\nimport qualified Data.Aeson.KeyMap as AesonKM\nimport Text.Printf (printf)\n\n-- | Compute the status label (OK/FAIL/ERR/FLAKY) for a test.\nformatTestStatus :: TestResult -> String\nformatTestStatus res =\n    let ok = trSuccess res == Just True && trException res == Nothing && not (trSkipped res)\n        base\n          | trSnapshotUpdated res = \"UPDATED\"\n          | trSkipped res = \"SKIP\"\n          | ok = \"OK\"\n          | trNumErrors res > 0 && trNumFailures res > 0 = \"ERR/FAIL\"\n          | trNumErrors res > 0 = \"ERR\"\n          | trNumFailures res > 0 = \"FAIL\"\n          | trSuccess res == Just False = \"FAIL\"\n          | otherwise = \"ERR\"\n        prefix = if not ok && trFlaky res then \"FLAKY \" else \"\"\n    in prefix ++ base\n\n-- | Compute a live status label for an in-progress test.\nformatTestStatusLive :: TestResult -> String\nformatTestStatusLive res\n  | trSnapshotUpdated res = \"UPDATED\"\n  | trSkipped res = \"SKIP\"\n  | isJust (trException res) = \"ERR\"\n  | trFlaky res = \"FLAKY\"\n  | trNumErrors res > 0 && trNumFailures res > 0 = \"ERR/FAIL\"\n  | trNumErrors res > 0 = \"ERR\"\n  | trNumFailures res > 0 = \"FAIL\"\n  | trSuccess res == Just False = \"FAIL\"\n  | trNumIterations res > 0 || trSuccess res == Just True = \"OK\"\n  | otherwise = \"RUN\"\n\ntestColorReset :: String\ntestColorReset = \"\\ESC[0m\"\n\ntestColorBold :: String\ntestColorBold = \"\\ESC[1m\"\n\ntestColorRed :: String\ntestColorRed = \"\\ESC[31m\"\n\ntestColorGreen :: String\ntestColorGreen = \"\\ESC[32m\"\n\ntestColorYellow :: String\ntestColorYellow = \"\\ESC[33m\"\n\ntestColorApply :: Bool -> [String] -> String -> String\ntestColorApply useColor codes msg =\n    if useColor\n      then concat codes ++ msg ++ testColorReset\n      else msg\n\ntestStatusWidth :: Int\ntestStatusWidth = (maximum (map length\n  [ \"RUN\"\n  , \"OK\"\n  , \"SKIP\"\n  , \"UPDATED\"\n  , \"FAIL\"\n  , \"ERR\"\n  , \"ERR/FAIL\"\n  , \"FLAKY FAIL\"\n  , \"FLAKY ERR\"\n  , \"FLAKY ERR/FAIL\"\n  ])) + 1\n\ncolorizeStatusPart :: Bool -> Bool -> String -> String -> String\ncolorizeStatusPart useColor cached statusRaw runs =\n    let suffix = if cached then \"*\" else \"\"\n        statusWithStar = statusRaw ++ suffix\n        pad = replicate (max 0 (testStatusWidth - length statusWithStar)) ' '\n        strip pref s = if pref `isPrefixOf` s then drop (length pref) s else s\n        core = strip \"FLAKY \" statusRaw\n        statusColored = case core of\n          \"RUN\" -> testColorApply useColor [testColorYellow] statusRaw\n          \"SKIP\" -> testColorApply useColor [testColorYellow] statusRaw\n          \"OK\" -> testColorApply useColor [testColorGreen] statusRaw\n          \"UPDATED\" -> testColorApply useColor [testColorYellow] statusRaw\n          _ -> testColorApply useColor [testColorBold, testColorRed] statusRaw\n        star =\n          if cached\n            then if useColor then testColorYellow ++ \"*\" ++ testColorReset else \"*\"\n            else \"\"\n    in statusColored ++ star ++ pad ++ \": \" ++ runs\n\nrenderStatusField :: Bool -> Bool -> String -> (String, String)\nrenderStatusField useColor cached statusRaw =\n    let (statusPlain, statusRendered) = renderStatusToken useColor cached statusRaw\n        pad = replicate (max 0 (testStatusWidth - length statusPlain)) ' '\n    in (statusPlain ++ pad ++ \":\", statusRendered ++ pad ++ \":\")\n\nrenderStatusToken :: Bool -> Bool -> String -> (String, String)\nrenderStatusToken useColor cached statusRaw =\n    let suffix = if cached then \"*\" else \"\"\n        strip pref s = if pref `isPrefixOf` s then drop (length pref) s else s\n        core = strip \"FLAKY \" statusRaw\n        statusColored = case core of\n          \"RUN\" -> testColorApply useColor [testColorYellow] statusRaw\n          \"SKIP\" -> testColorApply useColor [testColorYellow] statusRaw\n          \"OK\" -> testColorApply useColor [testColorGreen] statusRaw\n          \"UPDATED\" -> testColorApply useColor [testColorYellow] statusRaw\n          _ -> testColorApply useColor [testColorBold, testColorRed] statusRaw\n        star =\n          if cached\n            then if useColor then testColorYellow ++ \"*\" ++ testColorReset else \"*\"\n            else \"\"\n    in (statusRaw ++ suffix, statusColored ++ star)\n\nformatSecondsCompact :: Double -> String\nformatSecondsCompact ms\n  | ms <= 0 = \"0s\"\n  | ms < 1000 = \"<1s\"\n  | otherwise =\n      let secs = ms / 1000\n      in show (max 1 (round secs :: Int)) ++ \"s\"\n\nformatSecondsCompactPadded :: Double -> Double -> String\nformatSecondsCompactPadded expectedMs actualMs =\n    let expected = formatSecondsCompact expectedMs\n        actual = formatSecondsCompact actualMs\n        width = max (length expected) (length actual)\n    in replicate (max 0 (width - length actual)) ' ' ++ actual\n\nformatMillisPadded :: Double -> Double -> String\nformatMillisPadded expectedMs actualMs =\n    let digits ms = max 1 (length (show (max 0 (floor ms :: Int))))\n        width = max (digits expectedMs) (digits actualMs) + 4\n    in printf (\"%*.*fms\" :: String) width (3 :: Int) actualMs\n\nfitTestDisplay :: Int -> String -> String\nfitTestDisplay width display\n  | width <= 0 = \"\"\n  | length display <= width = display\n  | width <= 3 = take width display\n  | otherwise = termFitPlainRight (width - 3) display ++ \"...\"\n\n-- | Format a single test result line with alignment and timing.\nformatTestLineWith :: Bool -> (TestResult -> String) -> Double -> Int -> String -> TestResult -> String\nformatTestLineWith useColor statusFn expectedDurationMs nameWidth display res =\n    let prefix0 = \"   \" ++ display ++ \": \"\n        padding = replicate (max 0 (nameWidth - length prefix0)) ' '\n        statusRaw = statusFn res\n        runs = printf \"%4d runs in %s @ %6.1f/s\" (trNumIterations res) (formatMillisPadded expectedDurationMs (trTestDuration res)) (testsPerSecond (trNumIterations res) (trTestDuration res))\n        statusPart = colorizeStatusPart useColor (trCached res) statusRaw runs\n        stressPart =\n          case stressWorkerOverview res of\n            Just txt -> \" | \" ++ txt\n            Nothing -> \"\"\n    in prefix0 ++ padding ++ statusPart ++ stressPart\n\nstressWorkerOverview :: TestResult -> Maybe String\nstressWorkerOverview res =\n    case trRaw res of\n      Aeson.Object obj ->\n        let mEstMs = lookupDouble obj \"stress_est_iteration_ms\"\n            mPhaseResMs = lookupDouble obj \"stress_phase_resolution_ms\"\n            mSweep = lookupInt obj \"stress_target_sweep_iters\"\n            mCalib = lookupInt obj \"stress_calibrating_workers\"\n            mCovSeen = lookupInt obj \"stress_phase_bins_seen\"\n            mCovTotal = lookupInt obj \"stress_phase_bins_total\"\n            extraParts =\n              catMaybes\n                [ case mEstMs of\n                    Just est | est > 0 -> Just (printf \"iter~%0.3fms\" est)\n                    _ -> Nothing\n                , case mPhaseResMs of\n                    Just resMs | resMs > 0 -> Just (printf \"coarse~%0.3fms\" resMs)\n                    _ -> Nothing\n                , case mSweep of\n                    Just sweep | sweep > 0 -> Just (\"sweep=\" ++ show sweep)\n                    _ -> Nothing\n                , case mCalib of\n                    Just calib | calib > 0 -> Just (\"calib=\" ++ show calib)\n                    _ -> Nothing\n                , case (mCovSeen, mCovTotal) of\n                    (Just seen, Just total) | total > 0 ->\n                      let pct :: Double\n                          pct = (fromIntegral seen * 100.0) / fromIntegral total\n                      in Just (printf \"cov=%d/%d(%0.1f%%)\" seen total pct)\n                    _ -> Nothing\n                ]\n        in if null extraParts\n             then Nothing\n             else Just (unwords extraParts)\n      _ -> Nothing\n  where\n    lookupInt :: Aeson.Object -> String -> Maybe Int\n    lookupInt o key =\n      case AesonKM.lookup (AesonKey.fromString key) o of\n        Just v -> AesonTypes.parseMaybe Aeson.parseJSON v\n        _ -> Nothing\n\n    lookupDouble :: Aeson.Object -> String -> Maybe Double\n    lookupDouble o key =\n      case AesonKM.lookup (AesonKey.fromString key) o of\n        Just v -> AesonTypes.parseMaybe Aeson.parseJSON v\n        _ -> Nothing\n\ntestsPerSecond :: Int -> Double -> Double\ntestsPerSecond iterations durationMs\n  | iterations <= 0 = 0\n  | durationMs <= 0 = 0\n  | otherwise = (fromIntegral iterations * 1000.0) / durationMs\n\n-- | Format a live test line to the current terminal width.\nformatTestLineFitted :: Bool -> (TestResult -> String) -> Double -> Int -> Int -> String -> TestResult -> String\nformatTestLineFitted useColor statusFn expectedDurationMs nameWidth width display res\n  | width <= 0 = \"\"\n  | otherwise =\n      fromMaybe fallback (firstFit (legacyLine : map alignedLine summaries ++ map compactLine summaries))\n  where\n    indent = if width >= 4 then \"   \" else \"\"\n    statusRaw = statusFn res\n    (statusPlain, statusRendered) = renderStatusToken useColor (trCached res) statusRaw\n    (statusFieldPlain, statusFieldRendered) = renderStatusField useColor (trCached res) statusRaw\n    duration = formatSecondsCompactPadded expectedDurationMs (trTestDuration res)\n    summaryFull = show (trNumIterations res) ++ \" runs \" ++ duration\n    summaryCompact = show (trNumIterations res) ++ \"r \" ++ duration\n    summaries = [Just summaryFull, Just summaryCompact, Nothing]\n    legacyRendered = formatTestLineWith useColor statusFn expectedDurationMs nameWidth display res\n    legacyLine\n      | termVisibleLength legacyRendered <= width = Just legacyRendered\n      | otherwise = Nothing\n    prefix0 = indent ++ display ++ \": \"\n    alignedPrefix = prefix0 ++ replicate (max 0 (nameWidth - length prefix0)) ' '\n    alignedLine mSummary =\n      let summaryPad = maybe 0 (\\s -> 1 + length s) mSummary\n          fixed = length alignedPrefix + length statusFieldPlain + summaryPad\n      in if fixed <= width\n           then Just (alignedPrefix\n                      ++ statusFieldRendered\n                      ++ maybe \"\" (\\s -> \" \" ++ s) mSummary)\n           else Nothing\n    compactLine mSummary =\n      let summaryPad = maybe 0 (\\s -> 1 + length s) mSummary\n          fixed = length indent + 2 + length statusPlain + summaryPad\n          nameBudget = width - fixed\n      in if nameBudget >= 1\n           then Just (indent\n                      ++ fitTestDisplay nameBudget display\n                      ++ \": \"\n                      ++ statusRendered\n                      ++ maybe \"\" (\\s -> \" \" ++ s) mSummary)\n           else Nothing\n    firstFit = listToMaybe . mapMaybe id\n    fallback\n      | width >= length statusPlain = statusRendered\n      | otherwise = fitTestDisplay width display\n\nformatTestFinalLineRenderer :: Bool -> Double -> Int -> String -> TestResult -> Int -> String\nformatTestFinalLineRenderer useColor expectedDurationMs nameWidth display res cols =\n    formatTestLineFitted useColor formatTestStatus expectedDurationMs nameWidth cols display res\n\nformatTestLiveLineRenderer :: Bool -> Double -> Int -> String -> TestResult -> Int -> String\nformatTestLiveLineRenderer useColor expectedDurationMs nameWidth display res cols =\n    formatTestLineFitted useColor formatTestStatusLive expectedDurationMs nameWidth cols display res\n\nformatTestDetailLines :: Bool -> Bool -> TestResult -> [String]\nformatTestDetailLines useColor showLog res =\n    let skipped = trSkipped res\n        ok = trSuccess res == Just True && trException res == Nothing && not skipped\n        wantDetails = showLog || skipped || not ok\n        outcomeLines = case formatOutcomeSummaryLine useColor res of\n          Just line -> [line]\n          Nothing -> []\n        skipLines = case trSkipReason res of\n          Just reason ->\n            [ testColorApply useColor [testColorYellow] (\"    skipped: \" ++ reason)\n            ]\n          Nothing -> []\n        excLines = case trException res of\n          Just exc | not skipped ->\n            [ testColorApply useColor [testColorRed] (\"    \" ++ line)\n            | line <- lines exc\n            ]\n          Nothing -> []\n        outputLines =\n          if wantDetails\n            then formatCombinedLogLines (trStdOut res) (trStdErr res)\n            else []\n    in if wantDetails\n         then outcomeLines ++ skipLines ++ excLines ++ outputLines\n         else []\n  where\n    formatOutcomeSummaryLine useColor' result\n      | trNumIterations result <= 1 = Nothing\n      | trNumFailures result <= 0 && trNumErrors result <= 0 && trNumSkipped result <= 0 = Nothing\n      | otherwise =\n          let (numSuccesses, numFailures, numErrors, numSkipped) = outcomeCounts result\n              parts = catMaybes\n                [ formatOutcomePart useColor' [testColorGreen] numSuccesses \"ok\"\n                , formatOutcomePart useColor' [testColorRed] numFailures \"fail\"\n                , formatOutcomePart useColor' [testColorBold, testColorRed] numErrors \"err\"\n                , formatOutcomePart useColor' [testColorYellow] numSkipped \"skip\"\n                ]\n          in if null parts\n               then Nothing\n               else Just (\"    outcomes: \" ++ intercalate \", \" parts)\n    outcomeCounts result =\n      let numSkipped = max 0 (trNumSkipped result)\n          numFailures = max 0 (trNumFailures result)\n          numErrors = max 0 (trNumErrors result)\n          numSuccesses = max 0 (trNumIterations result - numSkipped - numFailures - numErrors)\n      in (numSuccesses, numFailures, numErrors, numSkipped)\n    formatOutcomePart useColor' styles count label\n      | count <= 0 = Nothing\n      | otherwise = Just (testColorApply useColor' styles (show count ++ \" \" ++ label))\n    formatCombinedLogLines mOut mErr =\n      let out = maybe \"\" id mOut\n          err = maybe \"\" id mErr\n      in if not (testOutputMeaningful out) && not (testOutputMeaningful err)\n           then []\n           else\n             let chunks = dedupCombinedOutput out err\n                 multi = length chunks > 1\n             in concatMap (renderChunk multi) chunks\n    renderChunk multi (chunk, count) =\n      let header =\n            if multi\n              then [\"    == \" ++ show count ++ \" test runs with this output:\"]\n              else []\n          body = map (\"    \" ++) (lines chunk)\n      in header ++ body ++ [\"\"]\n    testOutputMeaningful msgs =\n      any (\\line -> not (all isSpace line) && not (\"== Running test,\" `isPrefixOf` line)) (lines msgs)\n    splitTestOutput buf =\n      let ls = lines buf\n          isMarker line = \"== Running test, iteration:\" `isInfixOf` stripAnsi (trim line)\n          step (chunks, current, seenMarker) line\n            | isMarker line =\n                if seenMarker\n                  then (chunks ++ [trim current], \"\", True)\n                  else (chunks, \"\", True)\n            | otherwise =\n                let current' = if null current then line else current ++ \"\\n\" ++ line\n                in (chunks, current', seenMarker)\n          (chunks0, current0, seenMarker) = foldl' step ([], \"\", False) ls\n          chunks1 =\n            if seenMarker\n              then chunks0 ++ [trim current0]\n              else if null (trim buf) then [] else [trim buf]\n      in chunks1\n    renderIterationOutput out err =\n      let out' = trim out\n          err' = trim err\n          renderSection label content =\n            label ++ \":\\n\" ++ unlines (map (\"  \" ++) (lines content))\n          parts = catMaybes\n            [ if null out' then Nothing else Just (renderSection \"STDOUT\" out')\n            , if null err' then Nothing else Just (renderSection \"STDERR\" err')\n            ]\n      in intercalate \"\\n\" parts\n    dedupCombinedOutput out err =\n      let outChunks = splitTestOutput out\n          errChunks = splitTestOutput err\n          n = max (length outChunks) (length errChunks)\n          getChunk xs i = if i < length xs then xs !! i else \"\"\n          combined = [ renderIterationOutput (getChunk outChunks i) (getChunk errChunks i) | i <- [0..n-1] ]\n          parts = filter (not . null . trim) combined\n          stepCount (order, acc) chunk =\n            let acc' = M.insertWith (+) chunk 1 acc\n                order' = if M.member chunk acc then order else order ++ [chunk]\n            in (order', acc')\n          (order, acc) = foldl' stepCount ([], M.empty) parts\n      in [ (chunk, M.findWithDefault 0 chunk acc) | chunk <- order ]\n    trim s =\n      let dropEnd = reverse . dropWhile isSpace . reverse\n      in dropWhile isSpace (dropEnd s)\n    stripAnsi [] = []\n    stripAnsi ('\\ESC':'[':xs) = stripAnsi (dropAnsi xs)\n    stripAnsi (x:xs) = x : stripAnsi xs\n    dropAnsi [] = []\n    dropAnsi (c:cs)\n      | c == 'm' = cs\n      | otherwise = dropAnsi cs\n"
  },
  {
    "path": "compiler/acton/TestGolden.hs",
    "content": "{-# LANGUAGE OverloadedStrings #-}\n\nmodule TestGolden\n  ( normalizeProgressTimingLine\n  , normalizeProgressTimings\n  ) where\n\nimport           Data.Char (isDigit)\nimport qualified Data.Text as T\n\n-- | Replace trailing durations like \"12.345 s\" with a stable token.\nnormalizeProgressTimingLine :: T.Text -> T.Text\nnormalizeProgressTimingLine t =\n  case T.stripSuffix \" s\" t of\n    Nothing -> t\n    Just pre ->\n      let field = T.takeWhileEnd (\\c -> isDigit c || c == '.') pre\n          pre' = T.dropEnd (T.length field) pre\n      in case T.splitOn \".\" field of\n           [intPart, frac]\n             | not (T.null intPart)\n               && T.length frac == 3\n               && T.all isDigit intPart\n               && T.all isDigit frac ->\n                 let base = \"0.000\"\n                     padding = if T.length field > T.length base then \" \" else \"\"\n                 in pre' <> padding <> base <> \" s\"\n           _ -> t\n\nnormalizeProgressTimings :: String -> String\nnormalizeProgressTimings =\n    unlines . map (T.unpack . normalizeProgressTimingLine . T.pack) . lines\n"
  },
  {
    "path": "compiler/acton/TestRunner.hs",
    "content": "module TestRunner\n  ( TestMode(..)\n  , listTestModules\n  , listProjectTests\n  , runProjectTests\n  ) where\n\nimport qualified Acton.CommandLineParser as C\nimport Acton.Testing\nimport Acton.Compile\nimport qualified Acton.Syntax as A\nimport qualified InterfaceFiles\nimport TestFormat\nimport TestUI\nimport Control.Concurrent (forkIO)\nimport Control.Concurrent.Async\nimport Control.Concurrent.MVar (newEmptyMVar, putMVar, takeMVar)\nimport Control.Concurrent.Chan (Chan, newChan, readChan, writeChan)\nimport Control.Monad\nimport Data.IORef\nimport Data.Char (isSpace)\nimport Data.List (isPrefixOf, isSuffixOf, foldl', isInfixOf, intercalate)\nimport qualified Data.List\nimport Data.Maybe (catMaybes, listToMaybe, isJust)\nimport qualified Data.Map as M\nimport qualified Data.Set as Set\nimport System.Clock\nimport System.Directory\nimport System.Exit\nimport System.FilePath ((</>), (<.>), joinPath, takeExtension)\nimport System.IO (hClose, hGetContents, hGetLine, hIsEOF)\nimport System.Process\nimport Text.Printf\nimport qualified Data.Aeson as Aeson\nimport qualified Data.Aeson.Types as AesonTypes\nimport qualified Data.Aeson.Key as AesonKey\nimport qualified Data.Aeson.KeyMap as AesonKM\nimport qualified Data.ByteString.Lazy as BL\nimport qualified Data.Text as T\nimport qualified Data.Text.Encoding as TE\nimport Data.Time.Clock (UTCTime)\nimport Control.Exception (SomeException, AsyncException(..), displayException, evaluate, onException, try, fromException, throwIO)\nimport TerminalSize (termFitAnsiRight)\nimport qualified Text.Regex.TDFA as TDFA\nimport Data.Version (showVersion)\nimport qualified Paths_acton\n\ndata TestMode = TestModeRun | TestModeList | TestModePerf | TestModeStress deriving (Eq, Show)\n\ndata TestSpec = TestSpec\n  { tsModule :: String\n  , tsName :: String\n  , tsDisplay :: String\n  } deriving (Show)\n\ndata TestEvent\n  = TestEventDone TestResult\n  | TestEventRoom\n\ndata TestProgressCallbacks = TestProgressCallbacks\n  { tpcOnLive :: TestResult -> IO ()\n  , tpcOnDone :: TestResult -> IO ()\n  , tpcOnFinal :: TestResult -> IO ()\n  }\n\ndata StressWorkerRow = StressWorkerRow\n  { swrId :: Int\n  , swrSync :: Bool\n  , swrIterations :: Int\n  , swrDriftUs :: Int\n  , swrDriftTotalUs :: Int\n  , swrCalibrating :: Bool\n  , swrPhaseResolutionUs :: Int\n  , swrTargetSweepIters :: Int\n  }\n\ndata StressPhaseLane = StressPhaseLane\n  { splPhaseResolutionUs :: Int\n  , splTargetSweepIters :: Int\n  }\n\ngetVer :: String\ngetVer = showVersion Paths_acton.version\n\nprintErrorAndExit :: String -> IO a\nprintErrorAndExit msg = do\n    errorWithoutStackTrace msg\n    exitFailure\n\nmoduleHeaderLine :: String -> String\nmoduleHeaderLine modName\n  | null modName = \"Tests\"\n  | otherwise = \"Tests - module \" ++ modName ++ \":\"\n\n-- | List test modules by reading discovered tests from .ty headers.\nlistTestModules :: C.CompileOptions -> Paths -> IO [String]\nlistTestModules _opts paths = do\n    srcFiles <- listActFilesRecursive (srcDir paths)\n    mods <- forM srcFiles $ \\file -> do\n      mn <- moduleNameFromFile (srcDir paths) file\n      tests <- readModuleTests paths mn\n      return $ if null tests then Nothing else Just (modNameToString mn)\n    return (Data.List.sort (catMaybes mods))\n\n-- | Compute the test binary path for a module and target.\ntestBinaryPath :: C.CompileOptions -> Paths -> String -> FilePath\ntestBinaryPath opts paths modName =\n    let base = \".test_\" ++ modName\n        exe = if isWindowsTarget (C.target opts) then base <.> \"exe\" else base\n    in binDir paths </> exe\n\n-- | Check whether a target triple refers to Windows.\nisWindowsTarget :: String -> Bool\nisWindowsTarget targetTriple =\n    case break (== '-') targetTriple of\n      (_, \"\") -> False\n      (_, '-' : rest) ->\n        let (os, _) = break (== '-') rest\n        in os == \"windows\"\n\n-- | List tests for selected modules and print them in a stable order.\nlistProjectTests :: C.CompileOptions -> Paths -> C.TestOptions -> [String] -> IO ()\nlistProjectTests opts paths topts modules = do\n    let wantedModules = Data.List.sort (filterModules (C.testModules topts) modules)\n    nameRegexes <- compileTestNameRegexes (C.testNames topts)\n    tests <- forM wantedModules $ \\modName -> do\n      names <- listModuleTests opts paths modName\n      return (modName, Data.List.sort (filterTests nameRegexes names))\n    let nonEmpty = [ (modName, names) | (modName, names) <- tests, not (null names) ]\n    if C.testJson topts\n      then do\n        let testObj raw =\n              let display = displayTestName raw\n              in Aeson.object\n                   [ AesonKey.fromString \"name\" Aeson..= display\n                   , AesonKey.fromString \"raw_name\" Aeson..= raw\n                   ]\n            moduleObj (modName, names) =\n              Aeson.object\n                [ AesonKey.fromString \"name\" Aeson..= modName\n                , AesonKey.fromString \"tests\" Aeson..= map testObj names\n                ]\n            report = Aeson.object\n              [ AesonKey.fromString \"modules\" Aeson..= map moduleObj (Data.List.sortOn fst nonEmpty) ]\n        BL.putStr (Aeson.encode report)\n        putStrLn \"\"\n        exitSuccess\n      else if null nonEmpty\n        then do\n          putStrLn \"No tests found\"\n          exitSuccess\n        else do\n          forM_ (Data.List.sortOn fst nonEmpty) $ \\(modName, names) -> do\n            putStrLn (\"Module \" ++ modName ++ \":\")\n            forM_ names $ \\name -> do\n              let display = displayTestName name\n              if display /= name\n                then putStrLn (\"  \" ++ display ++ \" (\" ++ name ++ \")\")\n                else putStrLn (\"  \" ++ display)\n            putStrLn \"\"\n          exitSuccess\n\n-- | Run selected tests concurrently, stream results, and return an exit code.\nrunProjectTests :: Bool -> C.GlobalOptions -> C.CompileOptions -> Paths -> C.TestOptions -> TestMode -> [String] -> Int -> IO Int\nrunProjectTests useColorOut gopts opts paths topts mode modules maxParallel = do\n    timeStart <- getTime Monotonic\n    let emitJson = C.testJson topts\n    nameRegexes <- compileTestNameRegexes (C.testNames topts)\n    let wantedModules = Data.List.sort (filterModules (C.testModules topts) modules)\n    testsByModule <- forM wantedModules $ \\modName -> do\n      names <- listModuleTests opts paths modName\n      let wantedNames = Data.List.sort (filterTests nameRegexes names)\n      return (modName, wantedNames)\n    let specs =\n          [ TestSpec modName testName (displayTestName testName)\n          | (modName, names) <- testsByModule\n          , testName <- names\n          ]\n        allTests = [ (tsModule spec, tsName spec) | spec <- specs ]\n    if null specs\n      then do\n        if emitJson\n          then do\n            timeEnd <- getTime Monotonic\n            outputJsonReport (timeEnd - timeStart) []\n            return 0\n          else do\n            putStrLn \"Nothing to test\"\n            return 0\n      else do\n        let maxNameLen = maximum (0 : map (length . tsDisplay) specs)\n            nameWidth = max 20 (maxNameLen + 5)\n            runContext = mkRunContext opts topts mode\n            ctxHash = contextHashBytes runContext\n            useCache = not (C.testNoCache topts) && mode /= TestModeStress\n        cache <-\n          if useCache\n            then readTestCache (testCachePath paths) runContext\n            else return TestCache\n              { tcVersion = testCacheVersion\n              , tcContext = runContext\n              , tcTests = M.empty\n              }\n        testHashInfos <-\n          if useCache\n            then buildTestHashInfos paths ctxHash testsByModule\n            else return M.empty\n        let cacheEntries =\n              if useCache\n                then tcTests cache\n                else M.empty\n        when (C.verbose gopts && useCache) $\n          putStrLn (formatTestCacheContext ctxHash (testCachePath paths))\n        let logCache = if C.verbose gopts then putStrLn else \\_ -> return ()\n        (cachedResults0, _testsToRun) <-\n          if useCache\n            then classifyCachedTests logCache cacheEntries testHashInfos allTests\n            else return ([], allTests)\n        cachedResults1 <-\n          if useCache\n            then filterReusableCachedSnapshotResults logCache paths cachedResults0\n            else return []\n        cachedResults <-\n          if C.testSnapshotUpdate topts\n            then mapM (applySnapshotUpdate paths) cachedResults1\n            else return cachedResults1\n        let showCached = C.testShowCached topts\n        when (not emitJson && not useCache) $\n          if mode == TestModeStress\n            then putStrLn \"Skipping test result cache in stress mode; running all selected tests\"\n            else putStrLn \"Skipping test result cache (--no-cache); running all selected tests\"\n        when (not emitJson && showCached && not (null cachedResults)) $\n          putStrLn (\"Using cached results for \" ++ show (length cachedResults) ++ \" tests\")\n        ui <- initTestProgressUI gopts nameWidth (C.testShowLog topts) useColorOut\n        let totalTests = length specs\n        progressDoneRef <- newIORef 0\n        let (effectiveMinTime, effectiveMaxTime) = effectiveTestTiming mode topts\n            expectedDurationMs =\n              fromIntegral\n                (if effectiveMaxTime > 0\n                   then effectiveMaxTime\n                   else effectiveMinTime)\n        let progressStep = do\n              done <- atomicModifyIORef' progressDoneRef (\\x -> let x' = x + 1 in (x', x'))\n              let pct =\n                    if totalTests <= 0\n                      then 100\n                      else min 100 ((done * 100) `div` totalTests)\n              testUiProgressPercent ui pct\n        testUiProgressPercent ui 0\n        eventChan <- newChan\n        let cachedMap = M.fromList [ (TestKey (trModule res) (trName res), res) | res <- cachedResults ]\n            shouldShowCached res =\n              let ok = trSuccess res == Just True && trException res == Nothing && not (trSkipped res)\n              in showCached || not ok || trSnapshotUpdated res\n            startSpec spec running results = do\n              let key = TestKey (tsModule spec) (tsName spec)\n                  display = tsDisplay spec\n                  useColorLine = tpuUseColor ui\n                  showLog = tpuShowLog ui\n              case M.lookup key cachedMap of\n                Just cachedRes -> do\n                  let line = formatTestFinalLineRenderer useColorLine expectedDurationMs nameWidth display cachedRes\n                      details = formatTestDetailLines useColorLine showLog cachedRes\n                  if shouldShowCached cachedRes\n                    then do\n                      ok <- testUiAppendFinal ui key (tsModule spec) line\n                      if not ok\n                        then return Nothing\n                        else do\n                          inserted <- testUiInsertDetails ui key details\n                          unless inserted $ queuePendingDetails ui key details\n                          progressStep\n                          return (Just (running, cachedRes : results))\n                    else do\n                      progressStep\n                      return (Just (running, cachedRes : results))\n                Nothing -> do\n                  if running >= maxParallel\n                    then return Nothing\n                    else do\n                      let initRes = TestResult\n                            { trModule = tsModule spec\n                            , trName = tsName spec\n                            , trComplete = False\n                            , trSuccess = Nothing\n                            , trSkipped = False\n                            , trSkipReason = Nothing\n                            , trException = Nothing\n                            , trOutput = Nothing\n                            , trStdOut = Nothing\n                            , trStdErr = Nothing\n                            , trFlaky = False\n                            , trNumSkipped = 0\n                            , trNumFailures = 0\n                            , trNumErrors = 0\n                            , trNumIterations = 0\n                            , trTestDuration = 0\n                            , trRaw = Aeson.Null\n                            , trSnapshotUpdated = False\n                            , trCached = False\n                            }\n                          initLine = formatTestLiveLineRenderer useColorLine expectedDurationMs nameWidth display initRes\n                      started <- testUiStart ui key (tsModule spec) initLine\n                      if not started\n                        then return Nothing\n                        else do\n                          callbacks <- testProgressCallbacks ui eventChan key display expectedDurationMs\n                          void $ async $ do\n                            res <- runModuleTestStreaming opts paths topts mode (tsModule spec) (tsName spec)\n                                    (tpuEnabled ui) callbacks\n                            writeChan eventChan (TestEventDone res)\n                          return (Just (running + 1, results))\n            startAvailable pending running results = do\n              case pending of\n                [] -> return ([], running, results)\n                (spec:rest) -> do\n                  mnext <- startSpec spec running results\n                  case mnext of\n                    Nothing -> return (pending, running, results)\n                    Just (running', results') -> startAvailable rest running' results'\n            loop pending running results = do\n              flushPendingDetails ui\n              (pending', running', results') <- startAvailable pending running results\n              if null pending' && running' == 0\n                then do\n                  flushPendingDetails ui\n                  return results'\n                else do\n                  evt <- readChan eventChan\n                  case evt of\n                    TestEventDone res -> do\n                      progressStep\n                      let pending'' =\n                            if testResultInterrupted res\n                              then []\n                              else pending'\n                      loop pending'' (running' - 1) (res : results')\n                    TestEventRoom -> loop pending' running' results'\n        results <- loop specs 0 []\n        timeEnd <- getTime Monotonic\n        writeSnapshotOutputs paths results\n        let resultsRun =\n              if C.testSnapshotUpdate topts\n                then filter (\\r -> not (trCached r) || trSnapshotUpdated r) results\n                else filter (not . trCached) results\n        when (C.testRecord topts) $\n          writePerfData paths resultsRun\n        let cacheEntries' = foldl' (updateTestCacheEntry testHashInfos) cacheEntries resultsRun\n            newCache = TestCache\n              { tcVersion = testCacheVersion\n              , tcContext = runContext\n              , tcTests = cacheEntries'\n              }\n        when useCache $\n          writeTestCache (testCachePath paths) newCache\n        if emitJson\n          then do\n            outputJsonReport (timeEnd - timeStart) results\n            testUiProgressClear ui\n            return (testExitCode results)\n          else do\n            when (not (tpuEnabled ui)) $\n              printTestResultsOrdered (tpuUseColor ui) (tpuShowLog ui) showCached nameWidth specs results\n            _ <- printTestSummary (tpuUseColor ui) (timeEnd - timeStart) showCached results\n            testUiProgressClear ui\n            return (testExitCode results)\n  where\n    mkRunContext opts' topts' mode' = TestRunContext\n      { trcCompilerVersion = getVer\n      , trcTarget = C.target opts'\n      , trcOptimize = show (C.optimize opts')\n      , trcMode = show mode'\n      , trcArgs = testCmdArgs mode' topts'\n      }\n\ntestExitCode :: [TestResult] -> Int\ntestExitCode results =\n    let failures = length [ r | r <- results, trSuccess r == Just False ]\n        errors = length [ r | r <- results, trSuccess r == Nothing ]\n    in if errors > 0 then 2 else if failures > 0 then 1 else 0\n\noutputJsonReport :: TimeSpec -> [TestResult] -> IO ()\noutputJsonReport elapsed results = do\n    let total = length results\n        failures = length [ r | r <- results, trSuccess r == Just False ]\n        errors = length [ r | r <- results, trSuccess r == Nothing ]\n        skipped = length [ r | r <- results, trSkipped r ]\n        elapsedMs :: Double\n        elapsedMs =\n          let secs :: Double\n              secs = (fromIntegral (sec elapsed)) + (fromIntegral (nsec elapsed) / 1000000000)\n          in secs * 1000\n        isOk res = trSuccess res == Just True && trException res == Nothing && not (trSkipped res)\n        formatCombinedOutput mOut mErr =\n          let out = maybe \"\" id mOut\n              err = maybe \"\" id mErr\n          in if not (testOutputMeaningful out) && not (testOutputMeaningful err)\n                then Nothing\n                else\n                  let chunks = dedupCombinedOutput out err\n                      multi = length chunks > 1\n                      rendered = concatMap (renderChunk multi) chunks\n                      rendered' = stripTrailingBlanks rendered\n                      joined = unlines rendered'\n                  in if null (trim joined) then Nothing else Just joined\n        testObj res =\n          let status = formatTestStatus res\n              includeOutput = not (isOk res)\n              name = displayTestName (trName res)\n              combinedOutput = if includeOutput then formatCombinedOutput (trStdOut res) (trStdErr res) else Nothing\n          in Aeson.object\n               [ AesonKey.fromString \"module\" Aeson..= trModule res\n               , AesonKey.fromString \"name\" Aeson..= name\n               , AesonKey.fromString \"raw_name\" Aeson..= trName res\n               , AesonKey.fromString \"status\" Aeson..= status\n               , AesonKey.fromString \"cached\" Aeson..= trCached res\n               , AesonKey.fromString \"flaky\" Aeson..= trFlaky res\n               , AesonKey.fromString \"iterations\" Aeson..= trNumIterations res\n               , AesonKey.fromString \"duration_ms\" Aeson..= trTestDuration res\n               , AesonKey.fromString \"skipped\" Aeson..= trSkipped res\n               , AesonKey.fromString \"skip_reason\" Aeson..= trSkipReason res\n               , AesonKey.fromString \"exception\" Aeson..= trException res\n               , AesonKey.fromString \"output\" Aeson..= combinedOutput\n               ]\n        report = Aeson.object\n          [ AesonKey.fromString \"summary\" Aeson..= Aeson.object\n              [ AesonKey.fromString \"total\" Aeson..= total\n              , AesonKey.fromString \"failures\" Aeson..= failures\n              , AesonKey.fromString \"errors\" Aeson..= errors\n              , AesonKey.fromString \"skipped\" Aeson..= skipped\n              , AesonKey.fromString \"elapsed_ms\" Aeson..= elapsedMs\n              ]\n          , AesonKey.fromString \"tests\" Aeson..= map testObj results\n          ]\n    BL.putStr (Aeson.encode report)\n    putStrLn \"\"\n\nrenderChunk :: Bool -> (String, Int) -> [String]\nrenderChunk multi (chunk, count) =\n    let header =\n          if multi\n            then [\"== \" ++ show count ++ \" test runs with this output:\"]\n            else []\n        body = lines chunk\n    in header ++ body ++ [\"\"]\n\nstripTrailingBlanks :: [String] -> [String]\nstripTrailingBlanks = reverse . dropWhile null . reverse\n\ntestOutputMeaningful :: String -> Bool\ntestOutputMeaningful msgs =\n    any (\\line -> not (all isSpace line) && not (\"== Running test,\" `isPrefixOf` line)) (lines msgs)\n\nsplitTestOutput :: String -> [String]\nsplitTestOutput buf =\n    let ls = lines buf\n        isMarker line = \"== Running test, iteration:\" `isInfixOf` stripAnsi (trim line)\n        step (chunks, current, seenMarker) line\n          | isMarker line =\n              if seenMarker\n                then (chunks ++ [trim current], \"\", True)\n                else (chunks, \"\", True)\n          | otherwise =\n              let current' = if null current then line else current ++ \"\\n\" ++ line\n              in (chunks, current', seenMarker)\n        (chunks0, current0, seenMarker) = foldl' step ([], \"\", False) ls\n        chunks1 =\n          if seenMarker\n            then chunks0 ++ [trim current0]\n            else if null (trim buf) then [] else [trim buf]\n    in chunks1\n\nrenderIterationOutput :: String -> String -> String\nrenderIterationOutput out err =\n    let out' = trim out\n        err' = trim err\n        renderSection label content =\n          let body = intercalate \"\\n\" (map (\"  \" ++) (lines content))\n          in label ++ \":\\n\" ++ body\n        parts = catMaybes\n          [ if null out' then Nothing else Just (renderSection \"STDOUT\" out')\n          , if null err' then Nothing else Just (renderSection \"STDERR\" err')\n          ]\n    in intercalate \"\\n\" parts\n\ndedupCombinedOutput :: String -> String -> [(String, Int)]\ndedupCombinedOutput out err =\n    let outChunks = splitTestOutput out\n        errChunks = splitTestOutput err\n        n = max (length outChunks) (length errChunks)\n        getChunk xs i = if i < length xs then xs !! i else \"\"\n        combined = [ renderIterationOutput (getChunk outChunks i) (getChunk errChunks i) | i <- [0..n-1] ]\n        parts = filter (not . null . trim) combined\n        stepCount (order, acc) chunk =\n          let acc' = M.insertWith (+) chunk 1 acc\n              order' = if M.member chunk acc then order else order ++ [chunk]\n          in (order', acc')\n        (order, acc) = foldl' stepCount ([], M.empty) parts\n    in [ (chunk, M.findWithDefault 0 chunk acc) | chunk <- order ]\n\ntrim :: String -> String\ntrim s =\n    let dropEnd = reverse . dropWhile isSpace . reverse\n    in dropWhile isSpace (dropEnd s)\n\nstripAnsi :: String -> String\nstripAnsi [] = []\nstripAnsi ('\\ESC':'[':xs) = stripAnsi (dropAnsi xs)\nstripAnsi (x:xs) = x : stripAnsi xs\n\ndropAnsi :: String -> String\ndropAnsi [] = []\ndropAnsi (c:cs)\n  | c == 'm' = cs\n  | otherwise = dropAnsi cs\n\n-- | Filter module names based on CLI-provided allow lists.\nfilterModules :: [String] -> [String] -> [String]\nfilterModules [] mods = mods\nfilterModules wanted mods = filter (`elem` wanted) mods\n\n-- | Filter test names, matching raw or display names.\nfilterTests :: [TDFA.Regex] -> [String] -> [String]\nfilterTests [] names = names\nfilterTests regexes names =\n    filter matches names\n  where\n    matches name =\n      let display = displayTestName name\n      in any (\\re -> regexMatches re name || regexMatches re display) regexes\n\ncompileTestNameRegexes :: [String] -> IO [TDFA.Regex]\ncompileTestNameRegexes patterns =\n    mapM compileRegex (filter (not . null) patterns)\n  where\n    compileRegex pattern = do\n      let anchored = \"^\" ++ pattern ++ \"$\"\n      res <- try (evaluate (TDFA.makeRegex anchored :: TDFA.Regex)) :: IO (Either SomeException TDFA.Regex)\n      case res of\n        Left err -> printErrorAndExit (\"ERROR: Invalid regex '\" ++ pattern ++ \"': \" ++ displayException err)\n        Right re -> return re\n\nregexMatches :: TDFA.Regex -> String -> Bool\nregexMatches re text = isJust (TDFA.matchOnceText re text)\n\n-- | Read the discovered tests for a module from its .ty header.\nlistModuleTests :: C.CompileOptions -> Paths -> String -> IO [String]\nlistModuleTests _opts paths modName =\n    readModuleTests paths (modNameFromString modName)\n\n-- | Read tests from a module's .ty header, returning [] on any error.\nreadModuleTests :: Paths -> A.ModName -> IO [String]\nreadModuleTests paths mn = do\n    let tyFile = outBase paths mn ++ \".ty\"\n    exists <- doesFileExist tyFile\n    if not exists\n      then return []\n      else do\n        hdrE <- (try :: IO a -> IO (Either SomeException a)) $ InterfaceFiles.readHeader tyFile\n        case hdrE of\n          Left _ -> return []\n          Right (_sourceMeta, _srcH, _ih, _implH, _imps, _nameHashes, _roots, tests, _doc) ->\n            return tests\n\nmodNameFromString :: String -> A.ModName\nmodNameFromString s = A.modName (splitOnChar '.' s)\n\nsplitOnChar :: Char -> String -> [String]\nsplitOnChar ch input = case break (== ch) input of\n  (chunk, []) -> [chunk]\n  (chunk, _ : rest) -> chunk : splitOnChar ch rest\n\nlistActFilesRecursive :: FilePath -> IO [FilePath]\nlistActFilesRecursive dir = do\n    exists <- doesDirectoryExist dir\n    if not exists\n      then return []\n      else do\n        entries <- listDirectory dir\n        paths <- forM entries $ \\entry -> do\n          let path = dir </> entry\n          isDir <- doesDirectoryExist path\n          if isDir\n            then listActFilesRecursive path\n            else return [path]\n        return (filter (\\f -> takeExtension f == \".act\") (concat paths))\n\n-- | Run a single test case and stream JSON updates.\nrunModuleTestStreaming :: C.CompileOptions\n                       -> Paths\n                       -> C.TestOptions\n                       -> TestMode\n                       -> String\n                       -> String\n                       -> Bool\n                       -> TestProgressCallbacks\n                       -> IO TestResult\nrunModuleTestStreaming opts paths topts mode modName testName allowLive callbacks = do\n    let binPath = testBinaryPath opts paths modName\n        modeArgs =\n          case mode of\n            TestModePerf -> [\"perf\"]\n            TestModeStress -> [\"stress\"]\n            _ -> []\n        cmd = [\"test\", testName] ++ modeArgs ++ testCmdArgs mode topts\n    updatesRef <- newIORef []\n    lineDoneRef <- newIORef False\n    stdErrRef <- newIORef []\n    let onUpdate res = do\n          modifyIORef' updatesRef (\\xs -> xs ++ [res])\n          done <- readIORef lineDoneRef\n          when (not done && allowLive) $ do\n            if trComplete res\n              then do\n                tpcOnDone callbacks res\n                writeIORef lineDoneRef True\n              else tpcOnLive callbacks res\n        addStdErr line = modifyIORef' stdErrRef (line :)\n        onErrLine line =\n          case parseJsonLine line of\n            Nothing -> addStdErr line\n            Just val -> case parseTestInfo val of\n                          Just res -> onUpdate res\n                          Nothing -> addStdErr line\n    let procSpec = (proc binPath cmd){ cwd = Just (projPath paths), delegate_ctlc = True }\n    procRes <- try (readProcessWithExitCodeStreaming procSpec onErrLine) :: IO (Either SomeException (ExitCode, String, String))\n    (exitCode, out, _err, interruptedByUser) <-\n      case procRes of\n        Right (code, outTxt, errTxt) ->\n          return (code, outTxt, errTxt, False)\n        Left ex ->\n          case fromException ex of\n            Just UserInterrupt ->\n              return (ExitFailure (-2), \"\", \"\", True)\n            _ -> throwIO ex\n    infos <- readIORef updatesRef\n    stdErrLines <- reverse <$> readIORef stdErrRef\n    let stdErrText = unlines stdErrLines\n    let final = pickFinalTestInfo infos\n        fallback = TestResult\n          { trModule = modName\n          , trName = testName\n          , trComplete = False\n          , trSuccess = Nothing\n          , trSkipped = False\n          , trSkipReason = Nothing\n          , trException = Just \"No test result received\"\n          , trOutput = Nothing\n          , trStdOut = Nothing\n          , trStdErr = Nothing\n          , trFlaky = False\n          , trNumSkipped = 0\n          , trNumFailures = 0\n          , trNumErrors = 1\n          , trNumIterations = 0\n          , trTestDuration = 0\n          , trRaw = Aeson.Null\n          , trSnapshotUpdated = False\n          , trCached = False\n          }\n        res0 = maybe fallback id final\n        mergedStd field captured =\n          case field of\n            Just txt | not (null txt) -> Just txt\n            _ ->\n              if null captured\n                then field\n                else Just captured\n        res1 = res0\n          { trStdOut = mergedStd (trStdOut res0) out\n          , trStdErr = mergedStd (trStdErr res0) stdErrText\n          }\n        interrupted = interruptedByUser || isInterruptExitCode exitCode\n        incompleteSuccessExit = mode == TestModeStress && exitCode == ExitSuccess && not (trComplete res1)\n        res\n          | mode == TestModeStress && (interrupted || incompleteSuccessExit) = finalizeInterruptedStressResult res1\n          | otherwise =\n              case exitCode of\n                ExitSuccess -> res1\n                ExitFailure code ->\n                  res1 { trException = Just (\"Test process exited with code \" ++ show code) }\n    res' <-\n      if C.testSnapshotUpdate topts\n        then applySnapshotUpdate paths res\n        else return res\n    done <- readIORef lineDoneRef\n    if done\n      then tpcOnFinal callbacks res'\n      else do\n        tpcOnDone callbacks res'\n        tpcOnFinal callbacks res'\n    return res'\n  where\n    isInterruptExitCode ExitSuccess = False\n    isInterruptExitCode (ExitFailure code) = code == (-2) || code == 130\n\n    finalizeInterruptedStressResult res =\n      let success' =\n            case trSuccess res of\n              Just _ -> trSuccess res\n              Nothing ->\n                if trNumFailures res == 0 && trNumErrors res == 0\n                  then Just True\n                  else Nothing\n          exception' =\n            if trNumFailures res == 0 && trNumErrors res == 0\n              then Nothing\n              else trException res\n      in res\n         { trComplete = True\n         , trSuccess = success'\n         , trException = exception'\n         , trRaw = markInterruptedRaw (trRaw res)\n         }\n\n    markInterruptedRaw raw =\n      case raw of\n        Aeson.Object o ->\n          Aeson.Object (AesonKM.insert (AesonKey.fromString \"interrupted\") (Aeson.Bool True) o)\n        _ ->\n          Aeson.object [AesonKey.fromString \"interrupted\" Aeson..= True]\n\ntestProgressCallbacks :: TestProgressUI -> Chan TestEvent -> TestKey -> String -> Double -> IO TestProgressCallbacks\ntestProgressCallbacks ui eventChan key display expectedDurationMs = do\n    workerKeysRef <- newIORef M.empty\n    let nameWidth = tpuNameWidth ui\n        useColorOut = tpuUseColor ui\n        showLog = tpuShowLog ui\n        liveLine res = formatTestLiveLineRenderer useColorOut expectedDurationMs nameWidth display res\n        finalLine res = formatTestFinalLineRenderer useColorOut expectedDurationMs nameWidth display res\n        detailLines res = formatTestDetailLines useColorOut showLog res\n        workerLine done durationMs laneSpec row cols =\n          let role = if swrSync row then \"sync\" else \"drift\"\n              phase =\n                if done\n                  then \"DONE\"\n                  else if swrCalibrating row\n                    then \"CAL \"\n                    else \"RUN \"\n              iterations = swrIterations row\n              rate = testsPerSecond iterations durationMs\n              baseLine = printf \"      w%-3d %-5s %s : %7d iters @ %7.1f/s cur=%6dus tot=%8dus\"\n                              (swrId row) role phase iterations rate (swrDriftUs row) (swrDriftTotalUs row)\n              line = baseLine ++ renderStressPhaseLane useColorOut cols baseLine laneSpec row\n          in termFitAnsiRight cols line\n        workerKey wid = TestKey (tkModule key) (tkName key ++ \"#worker\" ++ show wid)\n        updateStressWorkers done res = do\n          let rows = stressWorkerRows res\n              laneSpec = stressPhaseLaneSpec res\n          unless (null rows) $ do\n            existing <- readIORef workerKeysRef\n            existing' <- foldM (\\acc row -> do\n              let wid = swrId row\n                  line = workerLine done (trTestDuration res) laneSpec row\n              case M.lookup wid acc of\n                Just wk -> do\n                  if done\n                    then do\n                      removed <- testUiFinalize ui wk line\n                      when removed $\n                        writeChan eventChan TestEventRoom\n                    else\n                      testUiUpdateLive ui wk line\n                  return acc\n                Nothing ->\n                  if done\n                    then return acc\n                    else do\n                      let wk = workerKey wid\n                      started <- testUiStart ui wk (tkModule key) line\n                      if started\n                        then return (M.insert wid wk acc)\n                        else return acc\n              ) existing rows\n            writeIORef workerKeysRef existing'\n    return TestProgressCallbacks\n      { tpcOnLive = \\res -> testUiUpdateLive ui key (liveLine res)\n          >> updateStressWorkers False res\n      , tpcOnDone = \\res -> do\n          updateStressWorkers True res\n          removed <- testUiFinalize ui key (finalLine res)\n          when removed $\n            writeChan eventChan TestEventRoom\n      , tpcOnFinal = \\res -> do\n          testUiUpdateFinal ui key (finalLine res)\n          let details = detailLines res\n          inserted <- testUiInsertDetails ui key details\n          unless inserted $\n            queuePendingDetails ui key details\n      }\n\nstressWorkerRows :: TestResult -> [StressWorkerRow]\nstressWorkerRows res =\n    case trRaw res of\n      Aeson.Object obj ->\n        case AesonKM.lookup (AesonKey.fromString \"stress_workers\") obj of\n          Just (Aeson.Array workers) ->\n            catMaybes (map parseWorker (foldr (:) [] workers))\n          _ -> []\n      _ -> []\n  where\n    parseWorker val =\n      case val of\n        Aeson.Object o -> do\n          wid <- lookupInt o \"id\"\n          iterations <- lookupInt o \"iterations\"\n          driftUs <- lookupIntDefault o \"drift_us\" 0\n          driftTotalUs <- lookupIntDefault o \"drift_total_us\" 0\n          syncW <- lookupBool o \"sync\"\n          calibrating <- lookupBoolDefault o \"calibrating\" False\n          phaseResolutionUs <- lookupIntDefault o \"phase_resolution_us\" 0\n          targetSweepIters <- lookupIntDefault o \"target_sweep_iters\" 0\n          return StressWorkerRow\n            { swrId = wid\n            , swrSync = syncW\n            , swrIterations = iterations\n            , swrDriftUs = driftUs\n            , swrDriftTotalUs = driftTotalUs\n            , swrCalibrating = calibrating\n            , swrPhaseResolutionUs = phaseResolutionUs\n            , swrTargetSweepIters = targetSweepIters\n            }\n        _ -> Nothing\n    lookupInt o keyName =\n      case AesonKM.lookup (AesonKey.fromString keyName) o of\n        Just v -> AesonTypes.parseMaybe Aeson.parseJSON v\n        _ -> Nothing\n    lookupIntDefault o keyName defVal =\n      case lookupInt o keyName of\n        Just n -> Just n\n        Nothing -> Just defVal\n    lookupBool o keyName =\n      case AesonKM.lookup (AesonKey.fromString keyName) o of\n        Just v -> AesonTypes.parseMaybe Aeson.parseJSON v\n        _ -> Nothing\n    lookupBoolDefault o keyName defVal =\n      case lookupBool o keyName of\n        Just b -> Just b\n        Nothing -> Just defVal\n\nstressPhaseLaneSpec :: TestResult -> Maybe StressPhaseLane\nstressPhaseLaneSpec res =\n    case trRaw res of\n      Aeson.Object obj -> do\n        phaseResolutionMs <- lookupDouble obj \"stress_phase_resolution_ms\"\n        targetSweepIters <- lookupInt obj \"stress_target_sweep_iters\"\n        let phaseResolutionUs = max 0 (round (phaseResolutionMs * 1000.0))\n        guard (phaseResolutionUs > 0 && targetSweepIters > 0)\n        return StressPhaseLane\n          { splPhaseResolutionUs = phaseResolutionUs\n          , splTargetSweepIters = targetSweepIters\n          }\n      _ -> Nothing\n  where\n    lookupInt o keyName =\n      case AesonKM.lookup (AesonKey.fromString keyName) o of\n        Just v -> AesonTypes.parseMaybe Aeson.parseJSON v\n        _ -> Nothing\n    lookupDouble o keyName =\n      case AesonKM.lookup (AesonKey.fromString keyName) o of\n        Just v -> (AesonTypes.parseMaybe Aeson.parseJSON v :: Maybe Double)\n        _ -> Nothing\n\nresolveStressPhaseLane :: Maybe StressPhaseLane -> StressWorkerRow -> Maybe StressPhaseLane\nresolveStressPhaseLane baseSpec row\n  | swrPhaseResolutionUs row > 0 && swrTargetSweepIters row > 0 =\n      Just StressPhaseLane\n        { splPhaseResolutionUs = swrPhaseResolutionUs row\n        , splTargetSweepIters = swrTargetSweepIters row\n        }\n  | otherwise = baseSpec\n\nrenderStressPhaseLane :: Bool -> Int -> String -> Maybe StressPhaseLane -> StressWorkerRow -> String\nrenderStressPhaseLane useColorOut cols baseLine baseSpec row\n  | not useColorOut = \"\"\n  | swrCalibrating row = \"\"\n  | otherwise =\n      case resolveStressPhaseLane baseSpec row of\n        Just spec ->\n          let avail = cols - length baseLine\n          in case stressPhaseLaneWidth avail of\n               Just laneWidth -> \" \" ++ stressPhaseLaneText laneWidth spec row\n               Nothing -> \"\"\n        Nothing -> \"\"\n\nstressPhaseLaneWidth :: Int -> Maybe Int\nstressPhaseLaneWidth avail\n  | avail < 11 = Nothing\n  | otherwise =\n      let width = min 32 (avail - 3)\n      in if width < 8 then Nothing else Just width\n\nstressPhaseLaneText :: Int -> StressPhaseLane -> StressWorkerRow -> String\nstressPhaseLaneText laneWidth spec row =\n    \"|\" ++ concatMap renderCell [0 .. laneWidth - 1] ++ testColorReset ++ \"|\"\n  where\n    totalPhaseUs = fromIntegral (max 1 (splPhaseResolutionUs spec * splTargetSweepIters spec)) :: Double\n    windowUs = fromIntegral (max 1 (splPhaseResolutionUs spec)) :: Double\n    phaseStartUs\n      | swrSync row = 0.0\n      | otherwise = fromIntegral (swrDriftTotalUs row `mod` max 1 (splPhaseResolutionUs spec * splTargetSweepIters spec))\n    centerUs = wrapPhase (phaseStartUs + (windowUs / 2.0))\n    windowCells = fromIntegral laneWidth / fromIntegral (max 1 (splTargetSweepIters spec)) :: Double\n    baselineBg = ansiBgReset\n    edgeBg = ansiBg 17\n    haloBg = ansiBg 18\n    coreBg\n      | windowCells < 0.35 = ansiBg 24\n      | windowCells < 0.70 = ansiBg 24\n      | otherwise = ansiBg 24\n\n    renderCell idx =\n      let cellStartUs = totalPhaseUs * fromIntegral idx / fromIntegral laneWidth\n          cellEndUs = totalPhaseUs * fromIntegral (idx + 1) / fromIntegral laneWidth\n          overlapFrac = circularOverlap phaseStartUs (phaseStartUs + windowUs) cellStartUs cellEndUs totalPhaseUs\n          isCore = circularContains centerUs cellStartUs cellEndUs totalPhaseUs\n          bg\n            | isCore = coreBg\n            | overlapFrac >= 0.66 = haloBg\n            | overlapFrac > 0.0 = edgeBg\n            | otherwise = baselineBg\n      in bg ++ \" \"\n\n    wrapPhase x\n      | totalPhaseUs <= 0.0 = 0.0\n      | otherwise =\n          let wrapped = x - (fromIntegral (floor (x / totalPhaseUs)) * totalPhaseUs)\n          in if wrapped < 0.0 then wrapped + totalPhaseUs else wrapped\n\n    circularContains point start end total =\n      overlapLinear start end point (point + 0.0001) total > 0.0\n\n    circularOverlap start end cellStart cellEnd total =\n      let segments = circularSegments start end total\n          cellSegments = circularSegments cellStart cellEnd total\n          overlapSum = sum [ overlapLinear' s1 e1 s2 e2 | (s1, e1) <- segments, (s2, e2) <- cellSegments ]\n          cellWidth = max 0.000001 (cellEnd - cellStart)\n      in overlapSum / cellWidth\n\n    circularSegments start end total\n      | total <= 0.0 = [(0.0, 1.0)]\n      | otherwise =\n          let start' = wrapPhase start\n              end' = start' + (end - start)\n          in if end' <= total\n               then [(start', end')]\n               else [(start', total), (0.0, end' - total)]\n\n    overlapLinear start end point pointEnd total =\n      let segments = circularSegments start end total\n          pointSegments = circularSegments point pointEnd total\n      in sum [ overlapLinear' s1 e1 s2 e2 | (s1, e1) <- segments, (s2, e2) <- pointSegments ]\n\n    overlapLinear' start1 end1 start2 end2 =\n      max 0.0 (min end1 end2 - max start1 start2)\n\n    ansiBg code = \"\\ESC[48;5;\" ++ show code ++ \"m\"\n    ansiBgReset = \"\\ESC[49m\"\n\ntestsPerSecond :: Int -> Double -> Double\ntestsPerSecond iterations durationMs\n  | iterations <= 0 = 0\n  | durationMs <= 0 = 0\n  | otherwise = (fromIntegral iterations * 1000.0) / durationMs\n\neffectiveTestTiming :: TestMode -> C.TestOptions -> (Int, Int)\neffectiveTestTiming mode topts =\n    let rawMinTime = C.testMinTime topts\n        minTime =\n          case mode of\n            TestModePerf ->\n              if not (C.testMinTimeSet topts)\n                then 1000\n                else rawMinTime\n            TestModeStress ->\n              if not (C.testMinTimeSet topts)\n                then 1000\n                else rawMinTime\n            _ -> rawMinTime\n        rawMaxTime = C.testMaxTime topts\n        modeDefaultMaxTime =\n          case mode of\n            TestModeRun -> minTime\n            TestModePerf -> 1000\n            TestModeStress -> 5000\n            _ -> 1000\n        maxTime\n          | C.testMaxTimeSet topts && rawMaxTime == 0 = 0\n          | C.testMaxTimeSet topts = max rawMaxTime minTime\n          | otherwise = modeDefaultMaxTime\n    in (minTime, maxTime)\n\n-- | Build test runner arguments from TestOptions limits.\ntestCmdArgs :: TestMode -> C.TestOptions -> [String]\ntestCmdArgs mode topts =\n    let iter = C.testIter topts\n        rawMaxIter = C.testMaxIter topts\n        (minTime, maxTime) = effectiveTestTiming mode topts\n        stressWorkerArgs\n          | mode == TestModeStress && C.testStressWorkers topts > 0 =\n              [\"--stress-workers\", show (C.testStressWorkers topts)]\n          | otherwise = []\n        maxIter\n          | mode == TestModeStress && maxTime == 0 && not (C.testMaxIterSet topts) = 0\n          | otherwise = rawMaxIter\n        baseArgs =\n          if iter > 0\n            then [\"--max-iter\", show iter, \"--min-iter\", show iter, \"--max-time\", show (10^6), \"--min-time\", \"1\"]\n            else [ \"--max-iter\", show maxIter\n                 , \"--min-iter\", show (C.testMinIter topts)\n                 , \"--max-time\", show maxTime\n                 , \"--min-time\", show minTime\n                 ]\n        tagArgs = concatMap (\\tag -> [\"--tag\", tag]) (C.testTags topts)\n    in baseArgs ++ stressWorkerArgs ++ tagArgs\n\n-- | Normalize test names by stripping prefixes and wrappers.\ndisplayTestName :: String -> String\ndisplayTestName name =\n    let withoutPrefix =\n          if \"_test_\" `isPrefixOf` name\n            then drop 6 name\n            else name\n    in if \"_wrapper\" `isSuffixOf` withoutPrefix\n         then take (length withoutPrefix - length \"_wrapper\") withoutPrefix\n         else withoutPrefix\n\n-- | Parse a single JSON line emitted by test binaries.\nparseJsonLine :: String -> Maybe Aeson.Value\nparseJsonLine line =\n    let trimmed = dropWhile isSpace line\n    in if null trimmed\n         then Nothing\n         else Aeson.decodeStrict' (TE.encodeUtf8 (T.pack trimmed))\n\n-- | Extract test result payloads from JSON events.\nextractTestInfo :: [Aeson.Value] -> [TestResult]\nextractTestInfo values =\n    catMaybes (map parseTestInfo values)\n\n-- | Parse a JSON value into a TestResult when test_info is present.\nparseTestInfo :: Aeson.Value -> Maybe TestResult\nparseTestInfo val =\n    case val of\n      Aeson.Object obj ->\n        case AesonKM.lookup (AesonKey.fromString \"test_info\") obj of\n          Just infoVal -> AesonTypes.parseMaybe parseTestInfoValue infoVal\n          Nothing -> Nothing\n      _ -> Nothing\n\n-- | Aeson parser for the test_info object.\nparseTestInfoValue :: Aeson.Value -> AesonTypes.Parser TestResult\nparseTestInfoValue = Aeson.withObject \"TestInfo\" $ \\o -> do\n    def <- o Aeson..: AesonKey.fromString \"definition\"\n    moduleName <- def Aeson..: AesonKey.fromString \"module\"\n    name <- def Aeson..: AesonKey.fromString \"name\"\n    complete <- o Aeson..: AesonKey.fromString \"complete\"\n    success <- o Aeson..:? AesonKey.fromString \"success\"\n    skipped <- o Aeson..:? AesonKey.fromString \"skipped\" Aeson..!= False\n    skipReason <- o Aeson..:? AesonKey.fromString \"skip_reason\"\n    exception <- o Aeson..:? AesonKey.fromString \"exception\"\n    output <- o Aeson..:? AesonKey.fromString \"output\"\n    stdOut <- o Aeson..:? AesonKey.fromString \"std_out\"\n    stdErr <- o Aeson..:? AesonKey.fromString \"std_err\"\n    flaky <- o Aeson..:? AesonKey.fromString \"flaky\" Aeson..!= False\n    numSkipped <- o Aeson..:? AesonKey.fromString \"num_skipped\" Aeson..!= 0\n    numFailures <- o Aeson..:? AesonKey.fromString \"num_failures\" Aeson..!= 0\n    numErrors <- o Aeson..:? AesonKey.fromString \"num_errors\" Aeson..!= 0\n    numIterations <- o Aeson..:? AesonKey.fromString \"num_iterations\" Aeson..!= 0\n    testDuration <- o Aeson..:? AesonKey.fromString \"test_duration\" Aeson..!= 0\n    return TestResult\n      { trModule = moduleName\n      , trName = name\n      , trComplete = complete\n      , trSuccess = success\n      , trSkipped = skipped\n      , trSkipReason = skipReason\n      , trException = exception\n      , trOutput = output\n      , trStdOut = stdOut\n      , trStdErr = stdErr\n      , trFlaky = flaky\n      , trNumSkipped = numSkipped\n      , trNumFailures = numFailures\n      , trNumErrors = numErrors\n      , trNumIterations = numIterations\n      , trTestDuration = testDuration\n      , trRaw = Aeson.Object o\n      , trSnapshotUpdated = False\n      , trCached = False\n      }\n\n-- | Pick the final or last-seen TestResult from a stream.\npickFinalTestInfo :: [TestResult] -> Maybe TestResult\npickFinalTestInfo infos =\n    case reverse infos of\n      [] -> Nothing\n      xs ->\n        case listToMaybe [i | i <- xs, trComplete i] of\n          Just i -> Just i\n          Nothing -> Just (head xs)\n\ntestResultInterrupted :: TestResult -> Bool\ntestResultInterrupted res =\n  case trRaw res of\n    Aeson.Object obj ->\n      case AesonKM.lookup (AesonKey.fromString \"interrupted\") obj of\n        Just v ->\n          case AesonTypes.parseMaybe Aeson.parseJSON v of\n            Just True -> True\n            _ -> False\n        _ -> False\n    _ -> False\n\n-- | Print a summary line and return the failure/error exit code.\nprintTestSummary :: Bool -> TimeSpec -> Bool -> [TestResult] -> IO Int\nprintTestSummary useColor elapsed showCached results = do\n    let total = length results\n        failures = length [ r | r <- results, trSuccess r == Just False ]\n        errors = length [ r | r <- results, trSuccess r == Nothing ]\n        skipped = length [ r | r <- results, trSkipped r ]\n        hiddenCachedSuccess = not showCached && any (\\r -> trCached r && trSuccess r == Just True && not (trSkipped r)) results\n        interrupted = any testResultInterrupted results\n        hasCached = any trCached results\n    case total of\n      0 -> do\n        putStrLn \"Nothing to test\"\n        return 0\n      _ -> do\n        putStrLn \"\"\n        if errors > 0 && failures > 0\n          then putStrLn (testColorApply useColor [testColorBold, testColorRed] (show errors ++ \" error and \" ++ show failures ++ \" failure out of \" ++ show total ++ \" tests (\" ++ fmtTime elapsed ++ \")\"))\n          else if errors > 0\n            then putStrLn (testColorApply useColor [testColorBold, testColorRed] (show errors ++ \" out of \" ++ show total ++ \" tests errored (\" ++ fmtTime elapsed ++ \")\"))\n            else if failures > 0\n              then putStrLn (testColorApply useColor [testColorBold, testColorRed] (show failures ++ \" out of \" ++ show total ++ \" tests failed (\" ++ fmtTime elapsed ++ \")\"))\n              else if skipped > 0\n                then putStrLn (testColorApply useColor [testColorGreen] (\"All \" ++ show total ++ \" tests passed, \" ++ show skipped ++ \" skipped (\" ++ fmtTime elapsed ++ \")\"))\n                else putStrLn (testColorApply useColor [testColorGreen] (\"All \" ++ show total ++ \" tests passed (\" ++ fmtTime elapsed ++ \")\"))\n        putStrLn \"\"\n        when hasCached $\n          putStrLn (if useColor then testColorYellow ++ \"*\" ++ testColorReset ++ \" = cached test result\" else \"* = cached test result\")\n        when interrupted $\n          putStrLn \"Stress run interrupted by user; showing partial results collected so far.\"\n        when hiddenCachedSuccess $\n          putStrLn \"Cached successful tests are hidden. Cached failures/errors are shown. Use --show-cached to include cached successes, or --no-cache to force rerunning selected tests.\"\n        if errors > 0\n          then return 2\n          else if failures > 0\n            then return 1\n            else return 0\n\nprintTestResultsOrdered :: Bool -> Bool -> Bool -> Int -> [TestSpec] -> [TestResult] -> IO ()\nprintTestResultsOrdered useColor showLog showCached nameWidth specs results = do\n    let resMap = M.fromList [ (TestKey (trModule res) (trName res), res) | res <- results ]\n        isOk res = trSuccess res == Just True && trException res == Nothing && not (trSkipped res)\n        shouldShow res = not (trCached res) || showCached || not (isOk res) || trSnapshotUpdated res\n        formatLine spec res =\n          formatTestLineWith useColor formatTestStatus (trTestDuration res) nameWidth (tsDisplay spec) res\n    let go _ _ [] = return ()\n        go printedMods printedAny (spec:rest) =\n          case M.lookup (TestKey (tsModule spec) (tsName spec)) resMap of\n            Nothing -> go printedMods printedAny rest\n            Just res ->\n              if not (shouldShow res)\n                then go printedMods printedAny rest\n                else do\n                  let modName = tsModule spec\n                  printedMods' <-\n                    if Set.member modName printedMods\n                      then return printedMods\n                      else do\n                        when printedAny $ putStrLn \"\"\n                        putStrLn (moduleHeaderLine modName)\n                        return (Set.insert modName printedMods)\n                  putStrLn (formatLine spec res)\n                  mapM_ putStrLn (formatTestDetailLines useColor showLog res)\n                  mapM_ putStrLn (formatStressWorkerFinalLines useColor res)\n                  go printedMods' True rest\n    go Set.empty False specs\n\nformatStressWorkerFinalLines :: Bool -> TestResult -> [String]\nformatStressWorkerFinalLines useColorOut res =\n    map renderRow (stressWorkerRows res)\n  where\n    durationMs = trTestDuration res\n    laneSpec = stressPhaseLaneSpec res\n    renderRow row =\n      let role = if swrSync row then \"sync\" else \"drift\"\n          iterations = swrIterations row\n          rate = testsPerSecond iterations durationMs\n          baseLine = printf \"      w%-3d %-5s DONE : %7d iters @ %7.1f/s cur=%6dus tot=%8dus\"\n                            (swrId row) role iterations rate (swrDriftUs row) (swrDriftTotalUs row)\n      in baseLine ++ renderStressPhaseLane useColorOut (maxBound :: Int) baseLine laneSpec row\n\n-- | Write snapshot outputs for all tests that produced output.\nwriteSnapshotOutputs :: Paths -> [TestResult] -> IO ()\nwriteSnapshotOutputs paths results =\n    mapM_ (writeSnapshotOutput paths) results\n\nwriteSnapshotOutput :: Paths -> TestResult -> IO ()\nwriteSnapshotOutput paths res =\n    case trOutput res of\n      Just out -> do\n        let fileName = displayTestName (trName res)\n            outDir = joinPath [projPath paths, \"snapshots\", \"output\", trModule res]\n        createDirectoryIfMissing True outDir\n        writeFile (outDir </> fileName) out\n      Nothing -> return ()\n\n-- | Update snapshot expected files from NotEqualError outputs.\napplySnapshotUpdate :: Paths -> TestResult -> IO TestResult\napplySnapshotUpdate paths res =\n    case (trException res, trOutput res) of\n      (Just exc, Just out)\n        | isSnapshotMismatch exc -> do\n            let fileName = displayTestName (trName res)\n                snapshotDir = joinPath [projPath paths, \"snapshots\", \"expected\", trModule res]\n            createDirectoryIfMissing True snapshotDir\n            writeFile (snapshotDir </> fileName) out\n            return (markSnapshotUpdated res)\n      _ -> return res\n\n-- | Reuse cached snapshot results only when the on-disk snapshot metadata still\n-- | shows that the expected file predates the last produced output. Any\n-- | uncertainty forces a rerun.\nfilterReusableCachedSnapshotResults :: (String -> IO ()) -> Paths -> [TestResult] -> IO [TestResult]\nfilterReusableCachedSnapshotResults logCache paths =\n    fmap catMaybes . mapM keepIfReusable\n  where\n    keepIfReusable res =\n      case trOutput res of\n        Nothing -> return (Just res)\n        Just _ -> do\n          reusable <- snapshotMetadataAllowsCacheHit logCache paths res\n          if reusable\n            then return (Just res)\n            else return Nothing\n\nsnapshotCacheLabel :: TestResult -> String\nsnapshotCacheLabel res = trModule res ++ \".\" ++ trName res\n\nsnapshotMetadataAllowsCacheHit :: (String -> IO ()) -> Paths -> TestResult -> IO Bool\nsnapshotMetadataAllowsCacheHit logCache paths res = do\n    mExpected <- readFirstExistingSnapshotMeta expectedPaths\n    case mExpected of\n      Nothing -> miss \"missing expected snapshot\"\n      Just (expectedSize, expectedMTime) -> do\n        mOutput <- readSnapshotMeta outputPath\n        case mOutput of\n          Nothing -> miss \"missing snapshot output\"\n          Just (outputSize, outputMTime)\n            | expectedSize /= outputSize -> miss \"snapshot size changed\"\n            | expectedMTime >= outputMTime -> miss \"snapshot expected is newer than output\"\n            | otherwise -> return True\n  where\n    fileName = displayTestName (trName res)\n    expectedPaths =\n      [ joinPath [projPath paths, \"snapshots\", \"expected\", trModule res, fileName]\n      , joinPath [projPath paths, \"test\", \"golden\", trModule res, fileName]\n      ]\n    outputPath = joinPath [projPath paths, \"snapshots\", \"output\", trModule res, fileName]\n    miss reason = do\n      logCache (\"[test-cache] \" ++ snapshotCacheLabel res ++ \" cache=miss (\" ++ reason ++ \")\")\n      return False\n\nreadFirstExistingSnapshotMeta :: [FilePath] -> IO (Maybe (Integer, UTCTime))\nreadFirstExistingSnapshotMeta [] = return Nothing\nreadFirstExistingSnapshotMeta (path:rest) = do\n    mMeta <- readSnapshotMeta path\n    case mMeta of\n      Just meta -> return (Just meta)\n      Nothing -> readFirstExistingSnapshotMeta rest\n\nreadSnapshotMeta :: FilePath -> IO (Maybe (Integer, UTCTime))\nreadSnapshotMeta path = do\n    exists <- doesFileExist path\n    if not exists\n      then return Nothing\n      else do\n        sizeE <- (try :: IO a -> IO (Either SomeException a)) $ getFileSize path\n        timeE <- (try :: IO a -> IO (Either SomeException a)) $ getModificationTime path\n        case (sizeE, timeE) of\n          (Right size, Right mtime) -> return (Just (size, mtime))\n          _ -> return Nothing\n\nsnapshotMismatchPrefix :: String\nsnapshotMismatchPrefix = \"testing.NotEqualError: Test output does not match expected snapshot value\"\n\nisSnapshotMismatch :: String -> Bool\nisSnapshotMismatch exc = snapshotMismatchPrefix `isPrefixOf` exc\n\nmarkSnapshotUpdated :: TestResult -> TestResult\nmarkSnapshotUpdated res = res\n  { trSnapshotUpdated = True\n  , trSuccess = Just True\n  , trSkipped = False\n  , trSkipReason = Nothing\n  , trException = Nothing\n  , trNumSkipped = 0\n  , trNumFailures = 0\n  , trNumErrors = 0\n  }\n\n-- | Write perf data JSON for the current test run.\nwritePerfData :: Paths -> [TestResult] -> IO ()\nwritePerfData paths results = do\n    let addTest acc res =\n          let modKey = AesonKey.fromString (trModule res)\n              testKey = AesonKey.fromString (trName res)\n              entry = case AesonKM.lookup modKey acc of\n                        Just (Aeson.Object obj) -> obj\n                        _ -> AesonKM.empty\n              entry' = AesonKM.insert testKey (trRaw res) entry\n              acc' = AesonKM.insert modKey (Aeson.Object entry') acc\n          in acc'\n        modulesObj = foldl' addTest AesonKM.empty results\n        outVal = Aeson.Object modulesObj\n        outPath = joinPath [projPath paths, \"perf_data\"]\n    BL.writeFile outPath (Aeson.encode outVal)\n\n-- | Run a process and stream stderr lines to a callback while capturing output.\nreadProcessWithExitCodeStreaming :: CreateProcess -> (String -> IO ()) -> IO (ExitCode, String, String)\nreadProcessWithExitCodeStreaming cp onErrLine = do\n    let cp' = cp { std_in = NoStream, std_out = CreatePipe, std_err = CreatePipe }\n    withCreateProcess cp' $ \\_ mOut mErr ph -> do\n      outVar <- newEmptyMVar\n      errVar <- newEmptyMVar\n      let readStdout mH var =\n            case mH of\n              Nothing -> putMVar var \"\"\n              Just h -> do\n                txt <- hGetContents h\n                _ <- evaluate (length txt)\n                hClose h\n                putMVar var txt\n          readStderr mH var =\n            case mH of\n              Nothing -> putMVar var \"\"\n              Just h -> do\n                txt <- readErrLines h\n                hClose h\n                putMVar var txt\n          readErrLines h = go []\n            where\n              go acc = do\n                eof <- hIsEOF h\n                if eof\n                  then return (unlines (reverse acc))\n                  else do\n                    line <- hGetLine h\n                    onErrLine line\n                    go (line : acc)\n      _ <- forkIO $ readStdout mOut outVar\n      _ <- forkIO $ readStderr mErr errVar\n      code <- waitForProcess ph `onException` do\n                terminateProcess ph\n                void (waitForProcess ph)\n      out <- takeMVar outVar\n      err <- takeMVar errVar\n      return (code, out, err)\n\nfmtTime :: TimeSpec -> String\nfmtTime t =\n    printf \"%6.3f s\" secs\n  where\n    secs :: Float\n    secs = (fromIntegral (sec t)) + (fromIntegral (nsec t) / 1000000000)\n"
  },
  {
    "path": "compiler/acton/TestUI.hs",
    "content": "module TestUI\n  ( TestKey(..)\n  , TestProgressUI(..)\n  , initTestProgressUI\n  , testUiStart\n  , testUiAppendFinal\n  , testUiUpdateLive\n  , testUiFinalize\n  , testUiUpdateFinal\n  , testUiInsertDetails\n  , testUiProgressPercent\n  , testUiProgressClear\n  , queuePendingDetails\n  , flushPendingDetails\n  ) where\n\nimport qualified Acton.CommandLineParser as C\nimport Control.Concurrent (ThreadId, forkIO, killThread, myThreadId, threadDelay)\nimport Control.Concurrent.MVar\nimport Control.Monad\nimport Data.IORef\nimport qualified Data.List\nimport qualified Data.Map as M\nimport Data.Ord (Down(..))\nimport qualified Data.Set as Set\nimport System.IO (hFlush, hIsTerminalDevice, stdout)\nimport TerminalProgress\nimport TerminalSize\n\ndata TestKey = TestKey\n  { tkModule :: String\n  , tkName :: String\n  } deriving (Eq, Ord, Show)\n\ntype TestLine = Int -> String\n\ndata TestProgressUI = TestProgressUI\n  { tpuEnabled :: Bool\n  , tpuTotalLinesRef :: IORef Int\n  , tpuLinesRef :: IORef [String]\n  , tpuLineRenderRef :: IORef [TestLine]\n  , tpuLineIndexRef :: IORef (M.Map TestKey Int)\n  , tpuLiveOrderRef :: IORef [TestKey]\n  , tpuLiveSetRef :: IORef (Set.Set TestKey)\n  , tpuLiveLineRef :: IORef (M.Map TestKey TestLine)\n  , tpuPrintedModulesRef :: IORef (Set.Set String)\n  , tpuPendingDetailsRef :: IORef (M.Map TestKey [String])\n  , tpuSpinnerRef :: IORef Int\n  , tpuTickerThreadRef :: IORef (Maybe ThreadId)\n  , tpuTermProgress :: TermProgress\n  , tpuTermSize :: TermSize\n  , tpuLock :: MVar ()\n  , tpuNameWidth :: Int\n  , tpuUseColor :: Bool\n  , tpuShowLog :: Bool\n  }\n\ninitTestProgressUI :: C.GlobalOptions -> Int -> Bool -> Bool -> IO TestProgressUI\ninitTestProgressUI gopts nameWidth showLog useColorOut = do\n    tty <- hIsTerminalDevice stdout\n    let enabled = (tty || C.tty gopts) && not (C.quiet gopts)\n    totalLinesRef <- newIORef 0\n    linesRef <- newIORef []\n    lineRenderRef <- newIORef []\n    lineIndexRef <- newIORef M.empty\n    liveOrderRef <- newIORef []\n    liveSetRef <- newIORef Set.empty\n    liveLineRef <- newIORef M.empty\n    printedModulesRef <- newIORef Set.empty\n    pendingDetailsRef <- newIORef M.empty\n    spinnerRef <- newIORef 0\n    tickerThreadRef <- newIORef Nothing\n    termProgress <- initTermProgress gopts\n    termSize <- initTermSize enabled\n    lock <- newMVar ()\n    return TestProgressUI\n      { tpuEnabled = enabled\n      , tpuTotalLinesRef = totalLinesRef\n      , tpuLinesRef = linesRef\n      , tpuLineRenderRef = lineRenderRef\n      , tpuLineIndexRef = lineIndexRef\n      , tpuLiveOrderRef = liveOrderRef\n      , tpuLiveSetRef = liveSetRef\n      , tpuLiveLineRef = liveLineRef\n      , tpuPrintedModulesRef = printedModulesRef\n      , tpuPendingDetailsRef = pendingDetailsRef\n      , tpuSpinnerRef = spinnerRef\n      , tpuTickerThreadRef = tickerThreadRef\n      , tpuTermProgress = termProgress\n      , tpuTermSize = termSize\n      , tpuLock = lock\n      , tpuNameWidth = nameWidth\n      , tpuUseColor = useColorOut\n      , tpuShowLog = showLog\n      }\n\nwithTestProgressLock :: TestProgressUI -> IO a -> IO a\nwithTestProgressLock ui action =\n    if not (tpuEnabled ui)\n      then action\n      else withMVar (tpuLock ui) (\\_ -> action)\n\ntestUiProgressPercent :: TestProgressUI -> Int -> IO ()\ntestUiProgressPercent ui pct =\n    withTestProgressLock ui (termProgressPercent (tpuTermProgress ui) pct)\n\ntestUiProgressClear :: TestProgressUI -> IO ()\ntestUiProgressClear ui =\n    withTestProgressLock ui (termProgressClear (tpuTermProgress ui))\n\ntestTickMicros :: Int\ntestTickMicros = 80000\n\ntestSpinnerThreshold :: Int\ntestSpinnerThreshold = 25\n\ntestSpinnerChars :: [Char]\ntestSpinnerChars = \"⠋⠙⠹⠸⠼⠴⠦⠧⠇⠏\"\n\ntestSpinnerEnabled :: Int -> Bool\ntestSpinnerEnabled cols = cols >= testSpinnerThreshold\n\ntestSpinnerChar :: TestProgressUI -> IO Char\ntestSpinnerChar ui = do\n    ix <- readIORef (tpuSpinnerRef ui)\n    return (testSpinnerChars !! (ix `mod` length testSpinnerChars))\n\nmoduleHeaderLine :: String -> String\nmoduleHeaderLine modName\n  | null modName = \"Tests\"\n  | otherwise = \"Tests - module \" ++ modName ++ \":\"\n\nsafeLiveWidth :: Int -> Int\nsafeLiveWidth width\n  | width <= 0 = 0\n  | width == 1 = 1\n  | otherwise = width - 1\n\nstaticLine :: String -> TestLine\nstaticLine line cols = termFitAnsiRight cols line\n\nvisibleLineCapacity :: Int -> Int\nvisibleLineCapacity rows = max 0 (rows - 1)\n\nvisibleStartIndex :: Int -> Int -> Int\nvisibleStartIndex rows total = max 0 (total - visibleLineCapacity rows)\n\nstartTestTicker :: TestProgressUI -> IO ()\nstartTestTicker ui =\n    when (tpuEnabled ui) $ do\n      m <- readIORef (tpuTickerThreadRef ui)\n      case m of\n        Just _ -> return ()\n        Nothing -> do\n          tid <- forkIO (testTickerLoop ui)\n          writeIORef (tpuTickerThreadRef ui) (Just tid)\n\nstopTestTicker :: TestProgressUI -> IO ()\nstopTestTicker ui = do\n    m <- atomicModifyIORef' (tpuTickerThreadRef ui) (\\cur -> (Nothing, cur))\n    forM_ m killThread\n\ntestTickerLoop :: TestProgressUI -> IO ()\ntestTickerLoop ui = do\n    tid <- myThreadId\n    let loop = do\n          threadDelay testTickMicros\n          keep <- withTestProgressLock ui $ do\n            liveSet <- readIORef (tpuLiveSetRef ui)\n            if Set.null liveSet || not (tpuEnabled ui)\n              then return False\n              else do\n                (_, cols) <- ensureViewportUnlocked ui\n                when (testSpinnerEnabled cols) $ do\n                  modifyIORef' (tpuSpinnerRef ui) (+ 1)\n                  refreshTestSpinnersUnlocked ui cols\n                termProgressHeartbeat (tpuTermProgress ui)\n                return True\n          when keep loop\n    loop\n    atomicModifyIORef' (tpuTickerThreadRef ui) $ \\cur ->\n      if cur == Just tid then (Nothing, ()) else (cur, ())\n\ncurrentViewportUnlocked :: TestProgressUI -> IO (Int, Int)\ncurrentViewportUnlocked ui = termSizeCurrent (tpuTermSize ui)\n\nensureViewportUnlocked :: TestProgressUI -> IO (Int, Int)\nensureViewportUnlocked ui\n  | not (tpuEnabled ui) = return (0, 0)\n  | otherwise = do\n      (oldRows, _) <- termSizeCurrent (tpuTermSize ui)\n      (changed, rows, cols) <- termSizeSync (tpuTermSize ui)\n      when changed $\n        rerenderVisibleUnlocked ui oldRows rows cols\n      return (rows, cols)\n\nappendLineUnlocked :: TestProgressUI -> TestLine -> IO Int\nappendLineUnlocked ui lineFn = do\n    idx <- readIORef (tpuTotalLinesRef ui)\n    rendered <- renderIndexedLineUnlocked ui idx lineFn\n    putStrLn rendered\n    modifyIORef' (tpuLinesRef ui) (\\xs -> xs ++ [rendered])\n    modifyIORef' (tpuLineRenderRef ui) (\\xs -> xs ++ [lineFn])\n    writeIORef (tpuTotalLinesRef ui) (idx + 1)\n    return idx\n\nupdateLineListAt :: Int -> a -> [a] -> [a]\nupdateLineListAt idx line xs =\n    case splitAt idx xs of\n      (prefix, _ : rest) -> prefix ++ [line] ++ rest\n      _ -> xs\n\ninsertLinesListAfter :: Int -> [a] -> [a] -> [a]\ninsertLinesListAfter idx newLines xs =\n    let (prefix, rest) = splitAt (idx + 1) xs\n    in prefix ++ newLines ++ rest\n\nrerenderVisibleUnlocked :: TestProgressUI -> Int -> Int -> Int -> IO ()\nrerenderVisibleUnlocked ui rowsBefore rowsAfter cols = do\n    total <- readIORef (tpuTotalLinesRef ui)\n    lineFns <- readIORef (tpuLineRenderRef ui)\n    renderedAll <- mapM (\\(idx, lineFn) -> renderIndexedLineWithColsUnlocked ui cols idx lineFn) (zip [0..] lineFns)\n    let\n        oldStartIdx = visibleStartIndex rowsBefore total\n        newStartIdx = visibleStartIndex rowsAfter total\n        oldVisibleCount = max 0 (total - oldStartIdx)\n        newVisible = drop newStartIdx renderedAll\n    when (oldVisibleCount > 0) $\n      putStr (\"\\ESC[\" ++ show oldVisibleCount ++ \"A\")\n    when (oldVisibleCount > 0 || not (null newVisible)) $ do\n      putStr \"\\r\\ESC[J\"\n      forM_ newVisible $ \\line -> do\n        putStr \"\\r\\ESC[2K\"\n        putStr line\n        putStr \"\\n\"\n      hFlush stdout\n    writeIORef (tpuLinesRef ui) renderedAll\n\nrefreshTestSpinnersUnlocked :: TestProgressUI -> Int -> IO ()\nrefreshTestSpinnersUnlocked ui cols = do\n    idxMap <- readIORef (tpuLineIndexRef ui)\n    liveLines <- readIORef (tpuLiveLineRef ui)\n    forM_ (M.toList liveLines) $ \\(key, lineFn) ->\n      case M.lookup key idxMap of\n        Just idx -> updateLineAtUnlockedWithCols ui cols idx lineFn\n        Nothing -> return ()\n\nrenderLiveLine :: Int -> Char -> String -> String\nrenderLiveLine cols spinner line\n  | not (testSpinnerEnabled cols) = line\n  | otherwise =\n      case line of\n        ' ':' ':' ':rest -> ' ' : spinner : ' ' : rest\n        _ -> line\n\nisLiveLineIndexUnlocked :: TestProgressUI -> Int -> IO Bool\nisLiveLineIndexUnlocked ui idx = do\n    liveSet <- readIORef (tpuLiveSetRef ui)\n    idxMap <- readIORef (tpuLineIndexRef ui)\n    return (any (\\key -> M.lookup key idxMap == Just idx) (Set.toList liveSet))\n\nrenderIndexedLineWithColsUnlocked :: TestProgressUI -> Int -> Int -> TestLine -> IO String\nrenderIndexedLineWithColsUnlocked ui cols idx lineFn = do\n    let base = lineFn (safeLiveWidth cols)\n    live <- isLiveLineIndexUnlocked ui idx\n    if live\n      then do\n        spinner <- testSpinnerChar ui\n        return (renderLiveLine cols spinner base)\n      else return base\n\nrenderIndexedLineUnlocked :: TestProgressUI -> Int -> TestLine -> IO String\nrenderIndexedLineUnlocked ui idx lineFn = do\n    (_, cols) <- currentViewportUnlocked ui\n    renderIndexedLineWithColsUnlocked ui cols idx lineFn\n\nensureModuleHeaderUnlocked :: TestProgressUI -> String -> IO ()\nensureModuleHeaderUnlocked ui modName = do\n    printed <- readIORef (tpuPrintedModulesRef ui)\n    unless (Set.member modName printed) $ do\n      total <- readIORef (tpuTotalLinesRef ui)\n      when (total > 0) $\n        void (appendLineUnlocked ui (staticLine \"\"))\n      _ <- appendLineUnlocked ui (staticLine (moduleHeaderLine modName))\n      writeIORef (tpuPrintedModulesRef ui) (Set.insert modName printed)\n\ncanAppendLinesUnlocked :: TestProgressUI -> Int -> IO Bool\ncanAppendLinesUnlocked ui n\n    | not (tpuEnabled ui) = return True\n    | n <= 0 = return True\n    | otherwise = do\n        (rows, _) <- currentViewportUnlocked ui\n        if rows <= 0\n          then return True\n          else do\n            liveOrder <- readIORef (tpuLiveOrderRef ui)\n            case liveOrder of\n              [] -> return True\n              (oldest:_) -> do\n                total <- readIORef (tpuTotalLinesRef ui)\n                idxMap <- readIORef (tpuLineIndexRef ui)\n                case M.lookup oldest idxMap of\n                  Nothing -> return True\n                  Just idx -> do\n                    let offset = total - idx\n                    return (offset + n < rows)\n\ntestUiStart :: TestProgressUI -> TestKey -> String -> TestLine -> IO Bool\ntestUiStart ui key modName lineFn = withTestProgressLock ui $ do\n    if not (tpuEnabled ui)\n      then return True\n      else do\n        void (ensureViewportUnlocked ui)\n        printed <- readIORef (tpuPrintedModulesRef ui)\n        total <- readIORef (tpuTotalLinesRef ui)\n        let headerNeeded = not (Set.member modName printed)\n            headerLines = if headerNeeded then if total > 0 then 2 else 1 else 0\n            linesNeeded = headerLines + 1\n        ok <- canAppendLinesUnlocked ui linesNeeded\n        if not ok\n          then return False\n          else do\n            ensureModuleHeaderUnlocked ui modName\n            idx <- readIORef (tpuTotalLinesRef ui)\n            modifyIORef' (tpuLineIndexRef ui) (M.insert key idx)\n            modifyIORef' (tpuLiveOrderRef ui) (\\xs -> if key `elem` xs then xs else xs ++ [key])\n            modifyIORef' (tpuLiveSetRef ui) (Set.insert key)\n            modifyIORef' (tpuLiveLineRef ui) (M.insert key lineFn)\n            _ <- appendLineUnlocked ui lineFn\n            startTestTicker ui\n            return True\n\ntestUiAppendFinal :: TestProgressUI -> TestKey -> String -> TestLine -> IO Bool\ntestUiAppendFinal ui key modName lineFn = withTestProgressLock ui $ do\n    if not (tpuEnabled ui)\n      then return True\n      else do\n        void (ensureViewportUnlocked ui)\n        printed <- readIORef (tpuPrintedModulesRef ui)\n        total <- readIORef (tpuTotalLinesRef ui)\n        let headerNeeded = not (Set.member modName printed)\n            headerLines = if headerNeeded then if total > 0 then 2 else 1 else 0\n            linesNeeded = headerLines + 1\n        ok <- canAppendLinesUnlocked ui linesNeeded\n        if not ok\n          then return False\n          else do\n            ensureModuleHeaderUnlocked ui modName\n            idx <- appendLineUnlocked ui lineFn\n            modifyIORef' (tpuLineIndexRef ui) (M.insert key idx)\n            return True\n\nupdateLineAtUnlocked :: TestProgressUI -> Int -> TestLine -> IO ()\nupdateLineAtUnlocked ui idx lineFn = do\n    (_, cols) <- currentViewportUnlocked ui\n    updateLineAtUnlockedWithCols ui cols idx lineFn\n\nupdateLineAtUnlockedWithCols :: TestProgressUI -> Int -> Int -> TestLine -> IO ()\nupdateLineAtUnlockedWithCols ui cols idx lineFn = do\n    rendered <- renderIndexedLineWithColsUnlocked ui cols idx lineFn\n    modifyIORef' (tpuLineRenderRef ui) (updateLineListAt idx lineFn)\n    modifyIORef' (tpuLinesRef ui) (updateLineListAt idx rendered)\n    total <- readIORef (tpuTotalLinesRef ui)\n    (rows, _) <- currentViewportUnlocked ui\n    let offset = total - idx\n    when (offset > 0 && (rows <= 0 || offset < rows)) $ do\n      putStr (\"\\ESC[\" ++ show offset ++ \"A\")\n      putStr \"\\r\\ESC[2K\"\n      putStr rendered\n      putStr (\"\\ESC[\" ++ show offset ++ \"B\")\n      putStr \"\\r\"\n      hFlush stdout\n\ntestUiUpdateLive :: TestProgressUI -> TestKey -> TestLine -> IO ()\ntestUiUpdateLive ui key lineFn = withTestProgressLock ui $ do\n    when (tpuEnabled ui) $ do\n      void (ensureViewportUnlocked ui)\n      idxMap <- readIORef (tpuLineIndexRef ui)\n      case M.lookup key idxMap of\n        Nothing -> return ()\n        Just idx -> do\n          modifyIORef' (tpuLiveLineRef ui) (M.insert key lineFn)\n          updateLineAtUnlocked ui idx lineFn\n\ntestUiFinalize :: TestProgressUI -> TestKey -> TestLine -> IO Bool\ntestUiFinalize ui key lineFn = withTestProgressLock ui $ do\n    liveSet <- readIORef (tpuLiveSetRef ui)\n    let wasLive = Set.member key liveSet\n    when wasLive $ do\n      writeIORef (tpuLiveSetRef ui) (Set.delete key liveSet)\n      modifyIORef' (tpuLiveOrderRef ui) (filter (/= key))\n      modifyIORef' (tpuLiveLineRef ui) (M.delete key)\n    when (tpuEnabled ui) $ do\n      void (ensureViewportUnlocked ui)\n      idxMap <- readIORef (tpuLineIndexRef ui)\n      case M.lookup key idxMap of\n        Nothing -> return ()\n        Just idx -> updateLineAtUnlocked ui idx lineFn\n    if wasLive\n      then do\n        liveSet' <- readIORef (tpuLiveSetRef ui)\n        when (tpuEnabled ui && Set.null liveSet') $\n          stopTestTicker ui\n        return True\n      else return False\n\ntestUiUpdateFinal :: TestProgressUI -> TestKey -> TestLine -> IO ()\ntestUiUpdateFinal ui key lineFn = withTestProgressLock ui $ do\n    when (tpuEnabled ui) $ do\n      void (ensureViewportUnlocked ui)\n      idxMap <- readIORef (tpuLineIndexRef ui)\n      case M.lookup key idxMap of\n        Nothing -> return ()\n        Just idx -> updateLineAtUnlocked ui idx lineFn\n\ncanInsertLinesUnlocked :: TestProgressUI -> Int -> Int -> IO Bool\ncanInsertLinesUnlocked ui insertIdx n\n    | not (tpuEnabled ui) = return True\n    | n <= 0 = return True\n    | otherwise = do\n        (rows, _) <- currentViewportUnlocked ui\n        if rows <= 0\n          then return True\n          else do\n            liveSet <- readIORef (tpuLiveSetRef ui)\n            idxMap <- readIORef (tpuLineIndexRef ui)\n            let idxs =\n                  [ idx\n                  | key <- Set.toList liveSet\n                  , Just idx <- [M.lookup key idxMap]\n                  , idx <= insertIdx\n                  ]\n            case idxs of\n              [] -> return True\n              _ -> do\n                total <- readIORef (tpuTotalLinesRef ui)\n                return ((total + n - minimum idxs) < rows)\n\ninsertLinesAfterUnlocked :: TestProgressUI -> Int -> [String] -> IO Bool\ninsertLinesAfterUnlocked ui idx lines = do\n    let n = length lines\n    if n <= 0\n      then return True\n      else do\n        (rows, cols) <- currentViewportUnlocked ui\n        total <- readIORef (tpuTotalLinesRef ui)\n        liveSet <- readIORef (tpuLiveSetRef ui)\n        let lineFns = map staticLine lines\n            rendered = map ($ safeLiveWidth cols) lineFns\n            startIdx = idx + 1\n            offsetNew = (total + n) - startIdx\n            visibleOk =\n              Set.null liveSet\n              || not (tpuEnabled ui)\n              || rows <= 0\n              || offsetNew < rows\n        ok <- canInsertLinesUnlocked ui idx n\n        if not ok || not visibleOk\n          then return False\n          else do\n            modifyIORef' (tpuLineRenderRef ui) (insertLinesListAfter idx lineFns)\n            modifyIORef' (tpuLinesRef ui) (insertLinesListAfter idx rendered)\n            modifyIORef' (tpuTotalLinesRef ui) (+ n)\n            modifyIORef' (tpuLineIndexRef ui) (M.map (\\i -> if i > idx then i + n else i))\n            if not (tpuEnabled ui)\n              then mapM_ putStrLn rendered\n              else rerenderFromUnlocked ui startIdx total\n            return True\n\nrerenderFromUnlocked :: TestProgressUI -> Int -> Int -> IO ()\nrerenderFromUnlocked ui startIdx oldTotal = do\n    let offset = oldTotal - startIdx\n    renderedLines <- readIORef (tpuLinesRef ui)\n    (rows, _) <- currentViewportUnlocked ui\n    let renderedTail = drop startIdx renderedLines\n    if offset <= 0\n      then do\n        forM_ renderedTail $ \\line -> do\n          putStr \"\\r\\ESC[2K\"\n          putStr line\n          putStr \"\\n\"\n        hFlush stdout\n      else when (rows <= 0 || offset < rows) $ do\n        putStr (\"\\ESC[\" ++ show offset ++ \"A\")\n        putStr \"\\r\\ESC[J\"\n        forM_ renderedTail $ \\line -> do\n          putStr \"\\r\\ESC[2K\"\n          putStr line\n          putStr \"\\n\"\n        hFlush stdout\n\ntestUiInsertDetails :: TestProgressUI -> TestKey -> [String] -> IO Bool\ntestUiInsertDetails ui key lines = withTestProgressLock ui $ do\n    if null lines\n      then return True\n      else if not (tpuEnabled ui)\n        then return True\n        else do\n          void (ensureViewportUnlocked ui)\n          idxMap <- readIORef (tpuLineIndexRef ui)\n          case M.lookup key idxMap of\n            Nothing -> return False\n            Just idx -> insertLinesAfterUnlocked ui idx lines\n\nqueuePendingDetails :: TestProgressUI -> TestKey -> [String] -> IO ()\nqueuePendingDetails ui key lines = withTestProgressLock ui $ do\n    unless (null lines) $\n      modifyIORef' (tpuPendingDetailsRef ui) (M.insert key lines)\n\nflushPendingDetails :: TestProgressUI -> IO ()\nflushPendingDetails ui = withTestProgressLock ui $ do\n    void (ensureViewportUnlocked ui)\n    pending <- readIORef (tpuPendingDetailsRef ui)\n    unless (M.null pending) $ do\n      idxMap <- readIORef (tpuLineIndexRef ui)\n      let withIdx =\n            Data.List.sortOn (\\(idx, _, _) -> Down idx)\n              [ (idx, key, lines)\n              | (key, lines) <- M.toList pending\n              , Just idx <- [M.lookup key idxMap]\n              ]\n      let go cur [] = return cur\n          go cur ((idx, key, lines):rest) = do\n            ok <- insertLinesAfterUnlocked ui idx lines\n            if ok\n              then go (M.delete key cur) rest\n              else go cur rest\n      pending' <- go pending withIdx\n      writeIORef (tpuPendingDetailsRef ui) pending'\n"
  },
  {
    "path": "compiler/acton/ZigProgress.hs",
    "content": "module ZigProgress\n  ( ZigProgress(..)\n  , ZigNode(..)\n  , parseZigProgressMessages\n  , zigProgressRatio\n  , readZigProgressStream\n  ) where\n\nimport Control.Exception (IOException, try)\nimport Data.Bits\nimport qualified Data.ByteString as BS\nimport qualified Data.ByteString.Char8 as BSC\nimport Data.List (foldl')\nimport qualified Data.Set as Set\nimport Data.Word (Word8, Word32)\nimport qualified System.Posix.IO.ByteString as PIOB\nimport System.Posix.Types (Fd)\n\ndata ZigNode = ZigNode\n  { znCompleted :: Word32\n  , znTotal :: Word32\n  , znName :: String\n  , znParent :: Maybe Int\n  } deriving (Show)\n\ndata ZigProgress = ZigProgress\n  { zpNodes :: [ZigNode]\n  } deriving (Show)\n\nreadZigProgressStream :: Fd -> (ZigProgress -> IO ()) -> IO ()\nreadZigProgressStream fd onMsg = go BS.empty\n  where\n    go buf = do\n      res <- (try (PIOB.fdRead fd 4096) :: IO (Either IOException BS.ByteString))\n      case res of\n        Left _ -> return ()\n        Right chunk | BS.null chunk -> return ()\n        Right chunk -> do\n          let buf' = BS.append buf chunk\n              (msgs, rest) = parseZigProgressMessages buf'\n          mapM_ onMsg msgs\n          go rest\n\nparseZigProgressMessages :: BS.ByteString -> ([ZigProgress], BS.ByteString)\nparseZigProgressMessages bs = go [] bs\n  where\n    go acc buf\n      | BS.length buf < 1 = (reverse acc, buf)\n      | otherwise =\n          let len = fromIntegral (BS.index buf 0) :: Int\n          in if len == 0xfe || len == 0xff\n                then go acc (BS.drop 1 buf)\n                else\n                  let msgLen = 1 + (len * 49)\n                  in if BS.length buf < msgLen\n                        then (reverse acc, buf)\n                        else\n                          let msgBytes = BS.take msgLen buf\n                              rest = BS.drop msgLen buf\n                              msg = decodeMessage len msgBytes\n                          in go (msg : acc) rest\n\ndecodeMessage :: Int -> BS.ByteString -> ZigProgress\ndecodeMessage len msgBytes =\n    let nodeBytes = BS.take (len * 48) (BS.drop 1 msgBytes)\n        parentBytes = BS.drop (1 + len * 48) msgBytes\n        nodes = [ decodeNode i nodeBytes parentBytes | i <- [0..len - 1] ]\n    in ZigProgress { zpNodes = nodes }\n\ndecodeNode :: Int -> BS.ByteString -> BS.ByteString -> ZigNode\ndecodeNode ix nodeBytes parentBytes =\n    let base = ix * 48\n        completed = word32le nodeBytes base\n        total = word32le nodeBytes (base + 4)\n        nameBytes = BS.take 40 (BS.drop (base + 8) nodeBytes)\n        name = BSC.unpack (BS.takeWhile (/= 0) nameBytes)\n        parentRaw = if ix < BS.length parentBytes\n                      then BS.index parentBytes ix\n                      else 0xff\n        parent = if parentRaw == 0xff then Nothing else Just (fromIntegral parentRaw)\n    in ZigNode\n         { znCompleted = completed\n         , znTotal = total\n         , znName = name\n         , znParent = parent\n         }\n\nword32le :: BS.ByteString -> Int -> Word32\nword32le bs offset =\n    let b0 = byteAt 0\n        b1 = byteAt 1\n        b2 = byteAt 2\n        b3 = byteAt 3\n    in (fromIntegral b0)\n       .|. (fromIntegral b1 `shiftL` 8)\n       .|. (fromIntegral b2 `shiftL` 16)\n       .|. (fromIntegral b3 `shiftL` 24)\n  where\n    byteAt i =\n      if offset + i < BS.length bs\n        then BS.index bs (offset + i)\n        else (0 :: Word8)\n\nzigProgressRatio :: ZigProgress -> Maybe Double\nzigProgressRatio progress =\n    let nodes = zpNodes progress\n        indexed = zip [0..] nodes\n        totals =\n          [ (i, clampTotal (znCompleted n) (znTotal n), znTotal n, znParent n)\n          | (i, n) <- indexed\n          , znTotal n > 0\n          ]\n        parentsWithTotals =\n          Set.fromList [ p | (_, _, _, Just p) <- totals ]\n        candidates =\n          [ (c, t) | (i, c, t, _) <- totals, not (Set.member i parentsWithTotals) ]\n        (sumC, sumT) = foldl' (\\(cAcc, tAcc) (c, t) ->\n                                 (cAcc + fromIntegral c, tAcc + fromIntegral t)) (0, 0) candidates\n    in if sumT <= 0\n         then Nothing\n         else Just (min 1.0 (sumC / sumT))\n  where\n    clampTotal c t = if c > t then t else c\n"
  },
  {
    "path": "compiler/acton/package.yaml.in",
    "content": "name:                acton\nversion: BUILD_VERSION\n# github:              \"/simple\"\nlicense:             BSD3\nauthor:              \"Johan Nordlander, Björn von Sydow, Kristian Larsson\"\nmaintainer:          \"example@example.com\"\ncopyright:           \"Data Ductus, Deutsche Telekom\"\n\n# Metadata used when publishing your package\n# synopsis:            Short description of your package\n# category:            Web\n\n# To avoid duplicated efforts in documentation and dealing with the\n# complications of embedding Haddock markup inside cabal files, it is\n# common to point users to the README.md file.\ndescription:         Please see the README on Github at <https://github.com/githubuser/simple#readme>\n\ndependencies:\n  - MissingH\n  - libacton\n  - aeson\n  - async\n  - base >= 4.7 && < 5\n  - base16-bytestring\n  - binary\n  - bytestring\n  - clock\n  - containers\n  - pretty\n  - cryptohash-sha256\n  - data-default-class\n  - diagnose\n  - dir-traverse\n  - directory >= 1.3.1\n  - filelock\n  - filepath\n  - fsnotify\n  - http-client\n  - http-client-tls\n  - http-types\n  - optparse-applicative\n  - megaparsec\n  - prettyprinter\n  - pretty-show\n  - process\n  - random\n  - split\n  - system-filepath\n  - sydtest\n  - tasty\n  - tasty-expected-failure\n  - tasty-golden\n  - tasty-hunit\n  - text\n  - temporary\n  - time\n  - timeit\n  - unix\n  - unordered-containers\n  - regex-tdfa\n  \nexecutables:\n  acton:\n    main:                Main.hs\n    source-dirs:         .\n    other-modules:\n      - PkgCommands\n      - Paths_acton\n      - TerminalProgress\n      - TerminalSize\n      - ZigProgress\n      - TestFormat\n      - TestRunner\n      - TestUI\n    ghc-options:\n      - -threaded\n      - -rtsopts\n      - '\"-with-rtsopts=-N -A64M\"'\n    when:\n    - condition: os(linux)\n      ghc-options:\n        - -no-pie\n        - -optl-no-pie\n        - -pgml=../tools/ld-wrapper.sh\n\ntests:\n  test_acton:\n    main:                test.hs\n    source-dirs:         .\n    ghc-options:\n      - -threaded\n      - -rtsopts\n      - -with-rtsopts=-N\n  incremental:\n    main:                test_incremental.hs\n    source-dirs:         .\n    ghc-options:\n      - -threaded\n      - -rtsopts\n      - -with-rtsopts=-N\n  test_acton_online:\n    main:                test_online.hs\n    source-dirs:         .\n    ghc-options:\n      - -threaded\n      - -rtsopts\n      - -with-rtsopts=-N\n"
  },
  {
    "path": "compiler/acton/test/incremental_cases/.gitignore",
    "content": "/Build.act\n/src/\n/deps/\n/out/\n/build.zig*\n/.acton.compile.lock\n/.acton.lock\n"
  },
  {
    "path": "compiler/acton/test/parse/simple.act",
    "content": "def main():\n    print(\"Hello parse!\")\n"
  },
  {
    "path": "compiler/acton/test/parse/simple.all.golden",
    "content": "\n\n== parse: simple ================================\ndef main ():\n    print(\"Hello parse!\")\n=================================================\n\n\n\n== kinds: simple ================================\nT_9w def main () -> T_5w:\n    print(\"Hello parse!\")\n=================================================\n\n\n\n== types: simple ================================\npure def main () -> None:\n    print@[(__builtin__.str,)](*(\"Hello parse!\",), sep = None, end = None, err = None, flush = None)\n=================================================\n\n\n\n== sigs: simple ================================\n\nmain : () -> None\n================================================\n\n\n\n== norm: simple ================================\npure def main () -> None:\n    print@[(__builtin__.str,)]((\"\\\"Hello parse!\\\"\",), None, None, None, None)\n    return None\n================================================\n\n\n\n== deact: simple ================================\npure def main () -> None:\n    print@[(__builtin__.str,)]((\"\\\"Hello parse!\\\"\",), None, None, None, None)\n    return None\n=================================================\n\n\n\n== cps: simple ================================\npure def main () -> None:\n    print@[(__builtin__.str,)]((\"\\\"Hello parse!\\\"\",), None, None, None, None)\n    return None\n===============================================\n\n\n\n== llift: simple ================================\npure def main () -> None:\n    print@[(__builtin__.str,)]((\"\\\"Hello parse!\\\"\",), None, None, None, None)\n    return None\n=================================================\n\n\n\n== box: simple ================================\npure def main () -> None:\n    print@[(__builtin__.str,)]((\"\\\"Hello parse!\\\"\",), None, None, None, None)\n    return None\n===============================================\n\n/* Acton impl hash: 90d154672dec39acdfe73f54da1124538a944a4989833b41555c4693f4283455 */\n#pragma once\n#include \"builtin/builtin.h\"\n#include \"rts/rts.h\"\nB_NoneType simpleQ_main ();\nvoid simpleQ___init__ ();\n"
  },
  {
    "path": "compiler/acton/test/parse/simple.box.golden",
    "content": "\n\n== box: simple ================================\npure def main () -> None:\n    print@[(__builtin__.str,)]((\"\\\"Hello parse!\\\"\",), None, None, None, None)\n    return None\n===============================================\n\n"
  },
  {
    "path": "compiler/acton/test/parse/simple.cgen.golden",
    "content": "/* Acton impl hash: 90d154672dec39acdfe73f54da1124538a944a4989833b41555c4693f4283455 */\n#include \"rts/common.h\"\n#include \"out/types/simple.h\"\nB_NoneType simpleQ_main () {\n    ((B_NoneType (*) (B_tuple, B_str, B_str, B_bool, B_bool))B_print)($NEWTUPLE(1, to$str(\"Hello parse!\")), B_None, B_None, B_None, B_None);\n    return B_None;\n}\nint simpleQ_done$ = 0;\nvoid simpleQ___init__ () {\n    if (simpleQ_done$) return;\n    simpleQ_done$ = 1;\n}\n"
  },
  {
    "path": "compiler/acton/test/parse/simple.cps.golden",
    "content": "\n\n== cps: simple ================================\npure def main () -> None:\n    print@[(__builtin__.str,)]((\"\\\"Hello parse!\\\"\",), None, None, None, None)\n    return None\n===============================================\n\n"
  },
  {
    "path": "compiler/acton/test/parse/simple.deact.golden",
    "content": "\n\n== deact: simple ================================\npure def main () -> None:\n    print@[(__builtin__.str,)]((\"\\\"Hello parse!\\\"\",), None, None, None, None)\n    return None\n=================================================\n\n"
  },
  {
    "path": "compiler/acton/test/parse/simple.golden",
    "content": "\n\n== parse: simple ================================\ndef main ():\n    print(\"Hello parse!\")\n=================================================\n\n"
  },
  {
    "path": "compiler/acton/test/parse/simple.hgen.golden",
    "content": "/* Acton impl hash: 90d154672dec39acdfe73f54da1124538a944a4989833b41555c4693f4283455 */\n#pragma once\n#include \"builtin/builtin.h\"\n#include \"rts/rts.h\"\nB_NoneType simpleQ_main ();\nvoid simpleQ___init__ ();\n"
  },
  {
    "path": "compiler/acton/test/parse/simple.kinds.golden",
    "content": "\n\n== kinds: simple ================================\nT_9w def main () -> T_5w:\n    print(\"Hello parse!\")\n=================================================\n\n"
  },
  {
    "path": "compiler/acton/test/parse/simple.llift.golden",
    "content": "\n\n== llift: simple ================================\npure def main () -> None:\n    print@[(__builtin__.str,)]((\"\\\"Hello parse!\\\"\",), None, None, None, None)\n    return None\n=================================================\n\n"
  },
  {
    "path": "compiler/acton/test/parse/simple.norm.golden",
    "content": "\n\n== norm: simple ================================\npure def main () -> None:\n    print@[(__builtin__.str,)]((\"\\\"Hello parse!\\\"\",), None, None, None, None)\n    return None\n================================================\n\n"
  },
  {
    "path": "compiler/acton/test/parse/simple.sigs.golden",
    "content": "\n\n== sigs: simple ================================\n\nmain : () -> None\n================================================\n\n"
  },
  {
    "path": "compiler/acton/test/parse/simple.types.golden",
    "content": "\n\n== types: simple ================================\npure def main () -> None:\n    print@[(__builtin__.str,)](*(\"Hello parse!\",), sep = None, end = None, err = None, flush = None)\n=================================================\n\n"
  },
  {
    "path": "compiler/acton/test/project/auto_root/.gitignore",
    "content": "build.zig*\n"
  },
  {
    "path": "compiler/acton/test/project/auto_root/Build.act",
    "content": "name = \"auto_root\"\nfingerprint = 0x25d729578a471226\n"
  },
  {
    "path": "compiler/acton/test/project/auto_root/src/b.act",
    "content": "def foo():\n    print(\"auto_root foo\")\n"
  },
  {
    "path": "compiler/acton/test/project/auto_root/src/test.act",
    "content": "import b\n\nactor main(env):\n    b.foo()\n    env.exit(0)\n"
  },
  {
    "path": "compiler/acton/test/project/conf_2bin/.gitignore",
    "content": "build.zig*\n"
  },
  {
    "path": "compiler/acton/test/project/conf_2bin/Build.act",
    "content": "name = \"conf_2bin\"\nfingerprint = 0x3a0f2be8959f1099\n\nbins = {\n    \"a\": \"a.main\",\n    \"b\": \"b.main\",\n    \"b2\": \"b.altroot\"\n}\n"
  },
  {
    "path": "compiler/acton/test/project/conf_2bin/src/a.act",
    "content": "actor main(env):\n    print(\"a\")\n    env.exit(0)\n"
  },
  {
    "path": "compiler/acton/test/project/conf_2bin/src/b.act",
    "content": "actor main(env):\n    print(\"b\")\n    env.exit(0)\n"
  },
  {
    "path": "compiler/acton/test/project/missing_src/.gitignore",
    "content": "build.zig*\n"
  },
  {
    "path": "compiler/acton/test/project/missing_src/Build.act",
    "content": "name = \"missing_src\"\nfingerprint = 0x3d6d0220ba420c23\n"
  },
  {
    "path": "compiler/acton/test/project/prune_executables/.gitignore",
    "content": "build.zig*\n"
  },
  {
    "path": "compiler/acton/test/project/prune_executables/Build.act",
    "content": "\nname = \"prune_executables\"\nfingerprint = 0xdd6b7ba1f8e40503\n\n"
  },
  {
    "path": "compiler/acton/test/project/prune_executables/src/bar.act",
    "content": "actor main(env):\n    print(\"bar\")\n    env.exit(0)\n\n"
  },
  {
    "path": "compiler/acton/test/project/prune_executables/src/foo.act",
    "content": "import testing\n\ndef _test_basic():\n    testing.assertEqual(1, 1)\n\nactor main(env):\n    print(\"foo\")\n    env.exit(0)\n"
  },
  {
    "path": "compiler/acton/test/project/prune_executables/src/tests/simple.act",
    "content": "import testing\n\ndef _test_basic():\n    testing.assertEqual(1, 1)\n\n"
  },
  {
    "path": "compiler/acton/test/project/prune_partials/.gitignore",
    "content": "build.zig*\n"
  },
  {
    "path": "compiler/acton/test/project/prune_partials/Build.act",
    "content": "\nname = \"prune_partials\"\nfingerprint = 0x014428b3365086ba\n\n"
  },
  {
    "path": "compiler/acton/test/project/prune_partials/src/bar.act",
    "content": "actor main(env):\n    print(\"bar\")\n    env.exit(0)\n"
  },
  {
    "path": "compiler/acton/test/project/prune_partials/src/foo.act",
    "content": "actor main(env):\n    print(\"foo\")\n    env.exit(0)\n"
  },
  {
    "path": "compiler/acton/test/project/prune_roots/.gitignore",
    "content": "build.zig*\n"
  },
  {
    "path": "compiler/acton/test/project/prune_roots/Build.act",
    "content": "\nname = \"prune_roots\"\nfingerprint = 0x1d991f5a9ab61159\n\n"
  },
  {
    "path": "compiler/acton/test/project/prune_roots/src/foo.act",
    "content": "actor main(env):\n    print(\"foo\")\n    env.exit(0)\n"
  },
  {
    "path": "compiler/acton/test/project/qualified_root/.gitignore",
    "content": "build.zig*\n"
  },
  {
    "path": "compiler/acton/test/project/qualified_root/Build.act",
    "content": "name = \"qualified_root\"\nfingerprint = 0xe20efcacd51a52a5\n"
  },
  {
    "path": "compiler/acton/test/project/qualified_root/src/b.act",
    "content": "def foo():\n    print(\"qualified_root foo\")\n"
  },
  {
    "path": "compiler/acton/test/project/qualified_root/src/test.act",
    "content": "import b\n\nactor main(env):\n    b.foo()\n    env.exit(0)\n"
  },
  {
    "path": "compiler/acton/test/project/simple/.gitignore",
    "content": "build.zig*\n"
  },
  {
    "path": "compiler/acton/test/project/simple/Build.act",
    "content": "name = \"simple\"\nfingerprint = 0xc17b3d02f0801944\n"
  },
  {
    "path": "compiler/acton/test/project/simple/src/a.act",
    "content": "import b\n"
  },
  {
    "path": "compiler/acton/test/project/simple/src/b.act",
    "content": "def foo():\n    print(\"b\")\n"
  },
  {
    "path": "compiler/acton/test/rebuild/.gitignore",
    "content": "/src/\n/deps/\n/out/\n/build.zig*\n/.acton.compile.lock\n/.acton.lock\n"
  },
  {
    "path": "compiler/acton/test/rebuild/Build.act",
    "content": "name = \"rebuild\"\nfingerprint = 0xc5208553327e37b8\n"
  },
  {
    "path": "compiler/acton/test/rebuild/golden/file_02-initial-build.golden",
    "content": "Building file src/c.act in project .\nResolving dependencies (fetching if missing)...\n   a  Parse done                                                            0.000 s\n  Stale a: source changed\n   a  Type check done                                                       0.000 s\n     Non-total inferred signature: aaa\n       aaa : int\n   b  Parse done                                                            0.000 s\n  Stale b: source changed\n   b  Type check done                                                       0.000 s\n     Non-total inferred signature: baa\n       baa : () -> int\n   c  Parse done                                                            0.000 s\n  Stale c: source changed\n   c  Type check done                                                       0.000 s\n   a  Compilation done                                                      0.000 s\n   b  Compilation done                                                      0.000 s\n   c  Compilation done                                                      0.000 s\n      Final compilation done                                                0.000 s\n"
  },
  {
    "path": "compiler/acton/test/rebuild/golden/file_03-up-to-date.golden",
    "content": "Building file src/c.act in project .\nResolving dependencies (fetching if missing)...\n  Fresh a: using cached .ty\n  Fresh b: using cached .ty\n  Fresh c: using cached .ty\n      Final compilation done                                                0.000 s\n"
  },
  {
    "path": "compiler/acton/test/rebuild/golden/file_04-touch-no-rebuild.golden",
    "content": "Building file src/c.act in project .\nResolving dependencies (fetching if missing)...\n  Fresh a: using cached .ty\n  Fresh b: using cached .ty\n  Fresh c: using cached .ty\n      Final compilation done                                                0.000 s\n"
  },
  {
    "path": "compiler/acton/test/rebuild/golden/file_06-change-a-impl.golden",
    "content": "Building file src/c.act in project .\nResolving dependencies (fetching if missing)...\n   a  Parse done                                                            0.000 s\n  Stale a: source changed\n  Hash deltas a: ~aaa{src HASH1 -> HASH2, impl HASH1 -> HASH2}\n   a  Type check done                                                       0.000 s\n     Non-total inferred signature: aaa\n       aaa : int\n  Stale b: impl changes in a.aaa HASH1 → HASH2 (used by baa)\n  Stale c: impl changes in b.baa HASH1 → HASH2 (used by main)\n   a  Compilation done                                                      0.000 s\n   b  Compilation done                                                      0.000 s\n   c  Compilation done                                                      0.000 s\n      Final compilation done                                                0.000 s\n"
  },
  {
    "path": "compiler/acton/test/rebuild/golden/file_08-change-b-impl.golden",
    "content": "Building file src/c.act in project .\nResolving dependencies (fetching if missing)...\n  Fresh a: using cached .ty\n   b  Parse done                                                            0.000 s\n  Stale b: source changed\n  Hash deltas b: +DocInfo, ~baa{src HASH1 -> HASH2, impl HASH1 -> HASH2}\n   b  Type check done                                                       0.000 s\n     Non-total inferred signature: baa\n       baa : () -> int\n     Non-total inferred signature: DocInfo\n       class DocInfo (value):\n           G_init : () -> None\n           get : () -> int\n  Stale c: impl changes in b.baa HASH1 → HASH2 (used by main)\n   b  Compilation done                                                      0.000 s\n   c  Compilation done                                                      0.000 s\n      Final compilation done                                                0.000 s\n"
  },
  {
    "path": "compiler/acton/test/rebuild/golden/project_02-initial-build.golden",
    "content": "Resolving dependencies (fetching if missing)...\n   a  Parse done                                                            0.000 s\n  Stale a: source changed\n   a  Type check done                                                       0.000 s\n     Non-total inferred signature: aaa\n       aaa : int\n   b  Parse done                                                            0.000 s\n  Stale b: source changed\n   b  Type check done                                                       0.000 s\n     Non-total inferred signature: baa\n       baa : () -> int\n     Non-total inferred signature: DocInfo\n       class DocInfo (value):\n           G_init : () -> None\n           get : () -> int\n   c  Parse done                                                            0.000 s\n  Stale c: source changed\n   c  Type check done                                                       0.000 s\n   a  Compilation done                                                      0.000 s\n   b  Compilation done                                                      0.000 s\n   c  Compilation done                                                      0.000 s\n      Final compilation done                                                0.000 s\n"
  },
  {
    "path": "compiler/acton/test/rebuild/golden/project_03-up-to-date.golden",
    "content": "Resolving dependencies (fetching if missing)...\n  Fresh a: using cached .ty\n  Fresh b: using cached .ty\n  Fresh c: using cached .ty\n      Final compilation done                                                0.000 s\n"
  },
  {
    "path": "compiler/acton/test/rebuild/golden/project_04-touch-no-rebuild.golden",
    "content": "Resolving dependencies (fetching if missing)...\n  Fresh a: using cached .ty\n  Fresh b: using cached .ty\n  Fresh c: using cached .ty\n      Final compilation done                                                0.000 s\n"
  },
  {
    "path": "compiler/acton/test/rebuild/golden/project_06-change-a-impl.golden",
    "content": "Resolving dependencies (fetching if missing)...\n   a  Parse done                                                            0.000 s\n  Stale a: source changed\n  Hash deltas a: ~aaa{src HASH1 -> HASH2, impl HASH1 -> HASH2}\n   a  Type check done                                                       0.000 s\n     Non-total inferred signature: aaa\n       aaa : int\n  Stale b: impl changes in a.aaa HASH1 → HASH2 (used by baa)\n  Stale c: impl changes in b.baa HASH1 → HASH2 (used by main)\n   a  Compilation done                                                      0.000 s\n   b  Compilation done                                                      0.000 s\n   c  Compilation done                                                      0.000 s\n      Final compilation done                                                0.000 s\n"
  },
  {
    "path": "compiler/acton/test/rebuild/golden/project_08-change-b-impl.golden",
    "content": "Resolving dependencies (fetching if missing)...\n  Fresh a: using cached .ty\n   b  Parse done                                                            0.000 s\n  Stale b: source changed\n  Hash deltas b: ~baa{src HASH1 -> HASH2, impl HASH1 -> HASH2}\n   b  Type check done                                                       0.000 s\n     Non-total inferred signature: baa\n       baa : () -> int\n     Non-total inferred signature: DocInfo\n       class DocInfo (value):\n           G_init : () -> None\n           get : () -> int\n  Stale c: impl changes in b.baa HASH1 → HASH2 (used by main)\n   b  Compilation done                                                      0.000 s\n   c  Compilation done                                                      0.000 s\n      Final compilation done                                                0.000 s\n"
  },
  {
    "path": "compiler/acton/test/rebuild/golden/project_10-change-a-iface.golden",
    "content": "Resolving dependencies (fetching if missing)...\n   a  Parse done                                                            0.000 s\n  Stale a: source changed\n  Hash deltas a: -W_aaa_3, ~aaa{src HASH1 -> HASH2, pub HASH1 -> HASH2, impl HASH1 -> HASH2}\n   a  Type check done                                                       0.000 s\n     Non-total inferred signature: aaa\n       aaa : str\n  Stale b: pub changes in a.aaa HASH1 → HASH2 (used by baa)\n  Hash deltas b: ~baa{pub HASH1 -> HASH2, impl HASH1 -> HASH2}\n   b  Type check done                                                       0.000 s\n     Non-total inferred signature: baa\n       baa : () -> str\n     Non-total inferred signature: DocInfo\n       class DocInfo (value):\n           G_init : () -> None\n           get : () -> int\n  Stale c: pub changes in b.baa HASH1 → HASH2 (used by main)\n  Hash deltas c: ~main{impl HASH1 -> HASH2}\n   c  Type check done                                                       0.000 s\n   a  Compilation done                                                      0.000 s\n   b  Compilation done                                                      0.000 s\n   c  Compilation done                                                      0.000 s\n      Final compilation done                                                0.000 s\n"
  },
  {
    "path": "compiler/acton/test/rebuild/golden/project_11-change-b-doc.golden",
    "content": "Resolving dependencies (fetching if missing)...\n  Fresh a: using cached .ty\n   b  Parse done                                                            0.000 s\n  Stale b: source changed\n  Hash deltas b: ~DocInfo{src HASH1 -> HASH2, impl HASH1 -> HASH2}\n   b  Type check done                                                       0.000 s\n     Non-total inferred signature: baa\n       baa : () -> str\n     Non-total inferred signature: DocInfo\n       class DocInfo (value):\n           G_init : () -> None\n           get : () -> int\n  Fresh c: using cached .ty\n   b  Compilation done                                                      0.000 s\n      Final compilation done                                                0.000 s\n"
  },
  {
    "path": "compiler/acton/test/rebuild/golden/project_12-codegen-stale.golden",
    "content": "Resolving dependencies (fetching if missing)...\n  Fresh a: using cached .ty\n  Stale b: generated code out of date {impl c missing -> HASH2, h missing -> HASH2}\n  Fresh c: using cached .ty\n   b  Compilation done                                                      0.000 s\n      Final compilation done                                                0.000 s\n"
  },
  {
    "path": "compiler/acton/test/root/test.act",
    "content": "actor main(env):\n    env.exit(0)\n"
  },
  {
    "path": "compiler/acton/test/syntaxerrors/err1.act",
    "content": "def f(x): if x>pass:\n    return 1\n  else\n    return 2"
  },
  {
    "path": "compiler/acton/test/syntaxerrors/err1.golden",
    "content": "Building file test/syntaxerrors/err1.act using temporary scratch directory\n[error Parse error]: unexpected \"if x>pass:<newline>   \"\n                     expecting end of line or simple statement\n\n     +--> test/syntaxerrors/err1.act@1:11-1:12\n     |\n   1 | def f(x): if x>pass:\n     :           ^ \n     :           `- unexpected \"if x>pass:<newline>   \"\n     :              expecting end of line or simple statement\n     :              \n-----+\n"
  },
  {
    "path": "compiler/acton/test/syntaxerrors/err10.act",
    "content": "# Missing colon after if statement\ndef check(x):\n    if x > 0\n        return True\n    return False"
  },
  {
    "path": "compiler/acton/test/syntaxerrors/err10.golden",
    "content": "Building file test/syntaxerrors/err10.act using temporary scratch directory\n[error Parse error]: unexpected newline\n                     expecting ':', call arguments, slice/index expression, digit, if clause, or operator\n\n     +--> test/syntaxerrors/err10.act@3:13-3:14\n     |\n   3 |     if x > 0\n     :             ^\n     :             `- unexpected newline\n     :                expecting ':', call arguments, slice/index expression, digit, if clause, or operator\n     :                \n-----+\n"
  },
  {
    "path": "compiler/acton/test/syntaxerrors/err11.act",
    "content": "# Unclosed string literal\ndef greet(name):\n    msg = \"Hello, \n    return msg"
  },
  {
    "path": "compiler/acton/test/syntaxerrors/err11.golden",
    "content": "Building file test/syntaxerrors/err11.act using temporary scratch directory\n[error Syntax error]: Missing closing \"\n     +--> test/syntaxerrors/err11.act@3:11-3:19\n     |\n   3 |     msg = \"Hello, \n     :           ^-------\n     :           `- Missing closing \"\n     :\n     | Hint: Add a closing quote (\") to match the opening one\n-----+\n"
  },
  {
    "path": "compiler/acton/test/syntaxerrors/err12.act",
    "content": "# Invalid character in identifier\ndef my-function(x):\n    return x + 1"
  },
  {
    "path": "compiler/acton/test/syntaxerrors/err12.golden",
    "content": "Building file test/syntaxerrors/err12.act using temporary scratch directory\n[error Parse error]: unexpected '-'\n                     expecting '(' or '['\n\n     +--> test/syntaxerrors/err12.act@2:7-2:8\n     |\n   2 | def my-function(x):\n     :       ^ \n     :       `- unexpected '-'\n     :          expecting '(' or '['\n     :          \n-----+\n"
  },
  {
    "path": "compiler/acton/test/syntaxerrors/err13.act",
    "content": "# Missing comma in list literal\ndef make_list():\n    return [1 2 3]"
  },
  {
    "path": "compiler/acton/test/syntaxerrors/err13.golden",
    "content": "Building file test/syntaxerrors/err13.act using temporary scratch directory\n[error Parse error]: unexpected '2'\n                     expecting \"for\", call arguments, slice/index expression, closing ']', comma, if clause, or operator\n\n     +--> test/syntaxerrors/err13.act@3:15-3:16\n     |\n   3 |     return [1 2 3]\n     :               ^ \n     :               `- unexpected '2'\n     :                  expecting \"for\", call arguments, slice/index expression, closing ']', comma, if clause, or operator\n     :                  \n-----+\n"
  },
  {
    "path": "compiler/acton/test/syntaxerrors/err14.act",
    "content": "# Invalid assignment target\ndef bad_assign():\n    1 + 2 = 3"
  },
  {
    "path": "compiler/acton/test/syntaxerrors/err14.golden",
    "content": "Building file test/syntaxerrors/err14.act using temporary scratch directory\n[error Parse error]: unexpected \"= \"\n                     expecting ';', call arguments, slice/index expression, comma, end of line, if clause, or operator\n\n     +--> test/syntaxerrors/err14.act@3:11-3:12\n     |\n   3 |     1 + 2 = 3\n     :           ^ \n     :           `- unexpected \"= \"\n     :              expecting ';', call arguments, slice/index expression, comma, end of line, if clause, or operator\n     :              \n-----+\n"
  },
  {
    "path": "compiler/acton/test/syntaxerrors/err15.act",
    "content": "# Mismatched brackets\ndef access_item():\n    arr = [1, 2, 3]\n    return arr[0}"
  },
  {
    "path": "compiler/acton/test/syntaxerrors/err15.golden",
    "content": "Building file test/syntaxerrors/err15.act using temporary scratch directory\n[error Parse error]: unexpected '}'\n                     expecting call arguments, slice/index expression, closing ']', comma, digit, if clause, or operator\n\n     +--> test/syntaxerrors/err15.act@4:17-4:18\n     |\n   4 |     return arr[0}\n     :                 ^\n     :                 `- unexpected '}'\n     :                    expecting call arguments, slice/index expression, closing ']', comma, digit, if clause, or operator\n     :                    \n-----+\n"
  },
  {
    "path": "compiler/acton/test/syntaxerrors/err16.act",
    "content": "# Invalid for loop syntax (missing 'in')\ndef loop():\n    for x [1, 2, 3]:\n        print(x)"
  },
  {
    "path": "compiler/acton/test/syntaxerrors/err16.golden",
    "content": "Building file test/syntaxerrors/err16.act using temporary scratch directory\n[error Parse error]: unexpected \"[1\"\n                     expecting \"in\", ':', or comma\n\n     +--> test/syntaxerrors/err16.act@3:11-3:12\n     |\n   3 |     for x [1, 2, 3]:\n     :           ^ \n     :           `- unexpected \"[1\"\n     :              expecting \"in\", ':', or comma\n     :              \n-----+\n"
  },
  {
    "path": "compiler/acton/test/syntaxerrors/err17.act",
    "content": "# Double dots in dictionary\ndef make_dict():\n    return {x:: 1}"
  },
  {
    "path": "compiler/acton/test/syntaxerrors/err17.golden",
    "content": "Building file test/syntaxerrors/err17.act using temporary scratch directory\n[error Parse error]: unexpected ':'\n                     expecting \"for\", call arguments, slice/index expression, closing '}', comma, if clause, or operator\n\n     +--> test/syntaxerrors/err17.act@3:14-3:15\n     |\n   3 |     return {x:: 1}\n     :              ^ \n     :              `- unexpected ':'\n     :                 expecting \"for\", call arguments, slice/index expression, closing '}', comma, if clause, or operator\n     :                 \n-----+\n"
  },
  {
    "path": "compiler/acton/test/syntaxerrors/err18.act",
    "content": "# Invalid lambda syntax\ndef higher_order():\n    f = x => x + 1\n    return f(5)"
  },
  {
    "path": "compiler/acton/test/syntaxerrors/err18.golden",
    "content": "Building file test/syntaxerrors/err18.act using temporary scratch directory\n[error Parse error]: unexpected \"> x + 1<newline>    re\"\n                     expecting \"action\", \"lambda\", \"mut\", \"proc\", \"pure\", \"yield\", '*', '=', '_', comma, or relational expression\n\n     +--> test/syntaxerrors/err18.act@3:12-3:13\n     |\n   3 |     f = x => x + 1\n     :            ^ \n     :            `- unexpected \"> x + 1<newline>    re\"\n     :               expecting \"action\", \"lambda\", \"mut\", \"proc\", \"pure\", \"yield\", '*', '=', '_', comma, or relational expression\n     :               \n-----+\n"
  },
  {
    "path": "compiler/acton/test/syntaxerrors/err19.act",
    "content": "# Invalid use of else without if\ndef orphan_else():\n    else:\n        pass"
  },
  {
    "path": "compiler/acton/test/syntaxerrors/err19.golden",
    "content": "Building file test/syntaxerrors/err19.act using temporary scratch directory\n[error Parse error]: unexpected \"else:<newline>        \"\n                     expecting statement\n\n     +--> test/syntaxerrors/err19.act@3:5-3:6\n     |\n   3 |     else:\n     :     ^ \n     :     `- unexpected \"else:<newline>        \"\n     :        expecting statement\n     :        \n-----+\n"
  },
  {
    "path": "compiler/acton/test/syntaxerrors/err2.act",
    "content": "def f(x):\n    actor a():\n        pass\n    return 2+x"
  },
  {
    "path": "compiler/acton/test/syntaxerrors/err2.golden",
    "content": "Building file test/syntaxerrors/err2.act using temporary scratch directory\n[error Context error]: actor declaration only allowed on the module top level\n     +--> err2.act@2:5-2:10\n     |\n   2 |     actor a():\n     :     ^---- \n     :     `- actor declaration only allowed on the module top level\n-----+\n"
  },
  {
    "path": "compiler/acton/test/syntaxerrors/err20.act",
    "content": "# Invalid decorator syntax\n@\ndef decorated():\n    pass"
  },
  {
    "path": "compiler/acton/test/syntaxerrors/err20.golden",
    "content": "Building file test/syntaxerrors/err20.act using temporary scratch directory\n[error Parse error]: unexpected \"@<newline>def decorate\"\n                     expecting statement\n\n     +--> test/syntaxerrors/err20.act@2:1-2:2\n     |\n   2 | @\n     : ^\n     : `- unexpected \"@<newline>def decorate\"\n     :    expecting statement\n     :    \n-----+\n"
  },
  {
    "path": "compiler/acton/test/syntaxerrors/err21.act",
    "content": "# Class definition without colon\nclass MyClass\n    pass"
  },
  {
    "path": "compiler/acton/test/syntaxerrors/err21.golden",
    "content": "Building file test/syntaxerrors/err21.act using temporary scratch directory\n[error Parse error]: unexpected newline\n                     expecting '(', ':', or '['\n\n     +--> test/syntaxerrors/err21.act@2:14-2:15\n     |\n   2 | class MyClass\n     :              ^\n     :              `- unexpected newline\n     :                 expecting '(', ':', or '['\n     :                 \n-----+\n"
  },
  {
    "path": "compiler/acton/test/syntaxerrors/err22.act",
    "content": "# Invalid comprehension syntax\ndef bad_comp():\n    return [x for x in]"
  },
  {
    "path": "compiler/acton/test/syntaxerrors/err22.golden",
    "content": "Building file test/syntaxerrors/err22.act using temporary scratch directory\n[error Parse error]: unexpected \"]<newline>\"\n                     expecting relational expression\n\n     +--> test/syntaxerrors/err22.act@3:23-3:24\n     |\n   3 |     return [x for x in]\n     :                       ^\n     :                       `- unexpected \"]<newline>\"\n     :                          expecting relational expression\n     :                          \n-----+\n"
  },
  {
    "path": "compiler/acton/test/syntaxerrors/err23.act",
    "content": "# Invalid f-string syntax\ndef bad_fstring():\n    name = \"world\"\n    return f\"Hello {name\""
  },
  {
    "path": "compiler/acton/test/syntaxerrors/err23.golden",
    "content": "Building file test/syntaxerrors/err23.act using temporary scratch directory\n[error Syntax error]: Missing closing '}' for expression\n     +--> test/syntaxerrors/err23.act@4:21-4:25\n     |\n   4 |     return f\"Hello {name\"\n     :                     ^--- \n     :                     `- Missing closing '}' for expression\n     :\n     | Hint: Add a closing brace to complete the interpolation\n-----+\n"
  },
  {
    "path": "compiler/acton/test/syntaxerrors/err24.act",
    "content": "# Double colon in type annotation\ndef typed_func() :: int:\n    return 42"
  },
  {
    "path": "compiler/acton/test/syntaxerrors/err24.golden",
    "content": "Building file test/syntaxerrors/err24.act using temporary scratch directory\n[error Parse error]: unexpected \": int:<newline>    ret\"\n                     expecting end of line or simple statement\n\n     +--> test/syntaxerrors/err24.act@2:19-2:20\n     |\n   2 | def typed_func() :: int:\n     :                   ^ \n     :                   `- unexpected \": int:<newline>    ret\"\n     :                      expecting end of line or simple statement\n     :                      \n-----+\n"
  },
  {
    "path": "compiler/acton/test/syntaxerrors/err25.act",
    "content": "# Invalid use of def inside expression\ndef expr_def():\n    x = def inner():\n        pass"
  },
  {
    "path": "compiler/acton/test/syntaxerrors/err25.golden",
    "content": "Building file test/syntaxerrors/err25.act using temporary scratch directory\n[error Parse error]: unexpected \"def inner():<newline> \"\n                     expecting \"action\", \"lambda\", \"mut\", \"proc\", \"pure\", \"yield\", '*', '=', '_', comma, or relational expression\n\n     +--> test/syntaxerrors/err25.act@3:9-3:10\n     |\n   3 |     x = def inner():\n     :         ^ \n     :         `- unexpected \"def inner():<newline> \"\n     :            expecting \"action\", \"lambda\", \"mut\", \"proc\", \"pure\", \"yield\", '*', '=', '_', comma, or relational expression\n     :            \n-----+\n"
  },
  {
    "path": "compiler/acton/test/syntaxerrors/err26.act",
    "content": "# Multiple statements on same line without semicolon\ndef multiple():\n    x = 1 y = 2"
  },
  {
    "path": "compiler/acton/test/syntaxerrors/err26.golden",
    "content": "Building file test/syntaxerrors/err26.act using temporary scratch directory\n[error Parse error]: unexpected \"y \"\n                     expecting ';', call arguments, slice/index expression, comma, end of line, if clause, or operator\n\n     +--> test/syntaxerrors/err26.act@3:11-3:12\n     |\n   3 |     x = 1 y = 2\n     :           ^ \n     :           `- unexpected \"y \"\n     :              expecting ';', call arguments, slice/index expression, comma, end of line, if clause, or operator\n     :              \n-----+\n"
  },
  {
    "path": "compiler/acton/test/syntaxerrors/err27.act",
    "content": "# Invalid numeric literal\ndef bad_number():\n    return 123abc"
  },
  {
    "path": "compiler/acton/test/syntaxerrors/err27.golden",
    "content": "Building file test/syntaxerrors/err27.act using temporary scratch directory\n[error Parse error]: unexpected \"ab\"\n                     expecting ';', call arguments, slice/index expression, comma, digit, end of line, if clause, or operator\n\n     +--> test/syntaxerrors/err27.act@3:15-3:16\n     |\n   3 |     return 123abc\n     :               ^ \n     :               `- unexpected \"ab\"\n     :                  expecting ';', call arguments, slice/index expression, comma, digit, end of line, if clause, or operator\n     :                  \n-----+\n"
  },
  {
    "path": "compiler/acton/test/syntaxerrors/err28.act",
    "content": "# Missing expression between commas\ndef bad_args():\n    print(1,,2)"
  },
  {
    "path": "compiler/acton/test/syntaxerrors/err28.golden",
    "content": "Building file test/syntaxerrors/err28.act using temporary scratch directory\n[error Parse error]: unexpected '2'\n                     expecting closing ')'\n\n     +--> test/syntaxerrors/err28.act@3:14-3:15\n     |\n   3 |     print(1,,2)\n     :              ^ \n     :              `- unexpected '2'\n     :                 expecting closing ')'\n     :                 \n-----+\n"
  },
  {
    "path": "compiler/acton/test/syntaxerrors/err29.act",
    "content": "# Invalid slice syntax\ndef bad_slice():\n    arr = [1, 2, 3, 4, 5]\n    return arr[1:::]"
  },
  {
    "path": "compiler/acton/test/syntaxerrors/err29.golden",
    "content": "Building file test/syntaxerrors/err29.act using temporary scratch directory\n[error Parse error]: unexpected ':'\n                     expecting \"action\", \"lambda\", \"mut\", \"proc\", \"pure\", '_', closing ']', or relational expression\n\n     +--> test/syntaxerrors/err29.act@4:19-4:20\n     |\n   4 |     return arr[1:::]\n     :                   ^ \n     :                   `- unexpected ':'\n     :                      expecting \"action\", \"lambda\", \"mut\", \"proc\", \"pure\", '_', closing ']', or relational expression\n     :                      \n-----+\n"
  },
  {
    "path": "compiler/acton/test/syntaxerrors/err3.act",
    "content": "def f(x):\n    return 2+"
  },
  {
    "path": "compiler/acton/test/syntaxerrors/err3.golden",
    "content": "Building file test/syntaxerrors/err3.act using temporary scratch directory\n[error Parse error]: unexpected newline\n                     expecting atomic expression or unary operator\n\n     +--> test/syntaxerrors/err3.act@2:14-2:15\n     |\n   2 |     return 2+\n     :              ^\n     :              `- unexpected newline\n     :                 expecting atomic expression or unary operator\n     :                 \n-----+\n"
  },
  {
    "path": "compiler/acton/test/syntaxerrors/err30.act",
    "content": "# Tab/space mixing indentation error\ndef mixed_indent():\n    x = 1\n\ty = 2  # This line starts with a tab"
  },
  {
    "path": "compiler/acton/test/syntaxerrors/err30.golden",
    "content": "Building file test/syntaxerrors/err30.act using temporary scratch directory\n[error Indentation error]: Too much indentation\n     +--> err30.act@4:9-4:9\n     |\n   4 |     y = 2  # This line starts with a tab\n     :             \n     :            `- Too much indentation\n-----+\n"
  },
  {
    "path": "compiler/acton/test/syntaxerrors/err31.act",
    "content": "# Invalid operator combination\ndef bad_op():\n    return 5 ** ** 2"
  },
  {
    "path": "compiler/acton/test/syntaxerrors/err31.golden",
    "content": "Building file test/syntaxerrors/err31.act using temporary scratch directory\n[error Parse error]: unexpected \"** 2<newline>\"\n                     expecting atomic expression or unary operator\n\n     +--> test/syntaxerrors/err31.act@3:17-3:18\n     |\n   3 |     return 5 ** ** 2\n     :                 ^ \n     :                 `- unexpected \"** 2<newline>\"\n     :                    expecting atomic expression or unary operator\n     :                    \n-----+\n"
  },
  {
    "path": "compiler/acton/test/syntaxerrors/err32.act",
    "content": "# Missing parenthesis in tuple\ndef bad_tuple():\n    return (1, 2, 3"
  },
  {
    "path": "compiler/acton/test/syntaxerrors/err32.golden",
    "content": "Building file test/syntaxerrors/err32.act using temporary scratch directory\n[error Parse error]: unexpected end of input\n                     expecting call arguments, slice/index expression, closing ')', comma, if clause, or operator\n\n     +--> test/syntaxerrors/err32.act@4:1-4:2\n     |\n   4 | <no line>\n     : ^\n     : `- unexpected end of input\n     :    expecting call arguments, slice/index expression, closing ')', comma, if clause, or operator\n     :    \n-----+\n"
  },
  {
    "path": "compiler/acton/test/syntaxerrors/err33.act",
    "content": "# Invalid import statement\nimport"
  },
  {
    "path": "compiler/acton/test/syntaxerrors/err33.golden",
    "content": "Building file test/syntaxerrors/err33.act using temporary scratch directory\n[error Parse error]: unexpected newline\n                     expecting identifier\n\n     +--> test/syntaxerrors/err33.act@2:7-2:8\n     |\n   2 | import\n     :       ^\n     :       `- unexpected newline\n     :          expecting identifier\n     :          \n-----+\n"
  },
  {
    "path": "compiler/acton/test/syntaxerrors/err34.act",
    "content": "# Protocol with invalid syntax\nprotocol MyProto:\n    def method()"
  },
  {
    "path": "compiler/acton/test/syntaxerrors/err34.golden",
    "content": "Building file test/syntaxerrors/err34.act using temporary scratch directory\n[error Parse error]: unexpected newline\n                     expecting \"->\" or ':'\n\n     +--> test/syntaxerrors/err34.act@3:17-3:18\n     |\n   3 |     def method()\n     :                 ^\n     :                 `- unexpected newline\n     :                    expecting \"->\" or ':'\n     :                    \n-----+\n"
  },
  {
    "path": "compiler/acton/test/syntaxerrors/err35.act",
    "content": "# Actor with invalid method definition\nactor MyActor:\n    def"
  },
  {
    "path": "compiler/acton/test/syntaxerrors/err35.golden",
    "content": "Building file test/syntaxerrors/err35.act using temporary scratch directory\n[error Parse error]: unexpected ':'\n                     expecting '(' or '['\n\n     +--> test/syntaxerrors/err35.act@2:14-2:15\n     |\n   2 | actor MyActor:\n     :              ^\n     :              `- unexpected ':'\n     :                 expecting '(' or '['\n     :                 \n-----+\n"
  },
  {
    "path": "compiler/acton/test/syntaxerrors/err36.act",
    "content": "# Invalid match/case syntax\ndef matcher(x):\n    match x:\n        case 1\n            return \"one\""
  },
  {
    "path": "compiler/acton/test/syntaxerrors/err36.golden",
    "content": "Building file test/syntaxerrors/err36.act using temporary scratch directory\n[error Parse error]: unexpected \"x:<newline>\"\n                     expecting \"%=\", \"&=\", \"**=\", \"*=\", \"+=\", \"-=\", \"//=\", \"/=\", \"<<=\", \">>=\", \"@=\", \"^=\", \"|=\", ':', '=', call arguments, slice/index expression, or comma\n\n     +--> test/syntaxerrors/err36.act@3:11-3:12\n     |\n   3 |     match x:\n     :           ^ \n     :           `- unexpected \"x:<newline>\"\n     :              expecting \"%=\", \"&=\", \"**=\", \"*=\", \"+=\", \"-=\", \"//=\", \"/=\", \"<<=\", \">>=\", \"@=\", \"^=\", \"|=\", ':', '=', call arguments, slice/index expression, or comma\n     :              \n-----+\n"
  },
  {
    "path": "compiler/acton/test/syntaxerrors/err37.act",
    "content": "# Binary literal error\ndef bad_binary():\n    return 0b102"
  },
  {
    "path": "compiler/acton/test/syntaxerrors/err37.golden",
    "content": "Building file test/syntaxerrors/err37.act using temporary scratch directory\n[error Parse error]: unexpected \"b1\"\n                     expecting ';', call arguments, slice/index expression, comma, digit, end of line, if clause, or operator\n\n     +--> test/syntaxerrors/err37.act@3:13-3:14\n     |\n   3 |     return 0b102\n     :             ^ \n     :             `- unexpected \"b1\"\n     :                expecting ';', call arguments, slice/index expression, comma, digit, end of line, if clause, or operator\n     :                \n-----+\n"
  },
  {
    "path": "compiler/acton/test/syntaxerrors/err38.act",
    "content": "# Hex literal error\ndef bad_hex():\n    return 0xGHI"
  },
  {
    "path": "compiler/acton/test/syntaxerrors/err38.golden",
    "content": "Building file test/syntaxerrors/err38.act using temporary scratch directory\n[error Parse error]: unexpected 'G'\n                     expecting hexadecimal integer\n\n     +--> test/syntaxerrors/err38.act@3:14-3:15\n     |\n   3 |     return 0xGHI\n     :              ^ \n     :              `- unexpected 'G'\n     :                 expecting hexadecimal integer\n     :                 \n-----+\n"
  },
  {
    "path": "compiler/acton/test/syntaxerrors/err39.act",
    "content": "# Invalid attribute access\ndef bad_attr():\n    return obj."
  },
  {
    "path": "compiler/acton/test/syntaxerrors/err39.golden",
    "content": "Building file test/syntaxerrors/err39.act using temporary scratch directory\n[error Parse error]: unexpected newline\n                     expecting \"\"\"\"\", \"'''\", '\"', ''', '~', identifier, or integer\n\n     +--> test/syntaxerrors/err39.act@3:16-3:17\n     |\n   3 |     return obj.\n     :                ^\n     :                `- unexpected newline\n     :                   expecting \"\"\"\"\", \"'''\", '\"', ''', '~', identifier, or integer\n     :                   \n-----+\n"
  },
  {
    "path": "compiler/acton/test/syntaxerrors/err4.act",
    "content": "def f(x):\n    return x+pass\n"
  },
  {
    "path": "compiler/acton/test/syntaxerrors/err4.golden",
    "content": "Building file test/syntaxerrors/err4.act using temporary scratch directory\n[error Parse error]: unexpected \"pass<newline>\"\n                     expecting atomic expression or unary operator\n\n     +--> test/syntaxerrors/err4.act@2:14-2:15\n     |\n   2 |     return x+pass\n     :              ^ \n     :              `- unexpected \"pass<newline>\"\n     :                 expecting atomic expression or unary operator\n     :                 \n-----+\n"
  },
  {
    "path": "compiler/acton/test/syntaxerrors/err40.act",
    "content": "# Unexpected token after valid statement\ndef unexpected():\n    x = 5 ]"
  },
  {
    "path": "compiler/acton/test/syntaxerrors/err40.golden",
    "content": "Building file test/syntaxerrors/err40.act using temporary scratch directory\n[error Parse error]: unexpected \"]<newline>\"\n                     expecting ';', call arguments, slice/index expression, comma, end of line, if clause, or operator\n\n     +--> test/syntaxerrors/err40.act@3:11-3:12\n     |\n   3 |     x = 5 ]\n     :           ^\n     :           `- unexpected \"]<newline>\"\n     :              expecting ';', call arguments, slice/index expression, comma, end of line, if clause, or operator\n     :              \n-----+\n"
  },
  {
    "path": "compiler/acton/test/syntaxerrors/err41.act",
    "content": "class Z(value):\n    pass"
  },
  {
    "path": "compiler/acton/test/syntaxerrors/err41.golden",
    "content": "Building file test/syntaxerrors/err41.act using temporary scratch directory\n[error Parse error]: Invalid name (reserved for type variables)\n\n     +--> test/syntaxerrors/err41.act@1:7-1:8\n     |\n   1 | class Z(value):\n     :       ^ \n     :       `- Invalid name 'Z'\n     :\n     | Note: Single upper case character (optionally followed by digits) are reserved for type variables\n     | Hint: Use a longer name\n-----+\n"
  },
  {
    "path": "compiler/acton/test/syntaxerrors/err42.act",
    "content": "def Z():\n    pass"
  },
  {
    "path": "compiler/acton/test/syntaxerrors/err42.golden",
    "content": "Building file test/syntaxerrors/err42.act using temporary scratch directory\n[error Parse error]: Invalid name (reserved for type variables)\n\n     +--> test/syntaxerrors/err42.act@1:5-1:6\n     |\n   1 | def Z():\n     :     ^ \n     :     `- Invalid name 'Z'\n     :\n     | Note: Single upper case character (optionally followed by digits) are reserved for type variables\n     | Hint: Use a longer name\n-----+\n"
  },
  {
    "path": "compiler/acton/test/syntaxerrors/err5.act",
    "content": "def f(x:\n    y = x * 2\n    return x + y\n"
  },
  {
    "path": "compiler/acton/test/syntaxerrors/err5.golden",
    "content": "Building file test/syntaxerrors/err5.act using temporary scratch directory\n[error Parse error]: unexpected 'r'\n                     expecting call arguments, slice/index expression, closing ')', comma, if clause, or operator\n\n     +--> test/syntaxerrors/err5.act@3:5-3:6\n     |\n   3 |     return x + y\n     :     ^ \n     :     `- unexpected 'r'\n     :        expecting call arguments, slice/index expression, closing ')', comma, if clause, or operator\n     :        \n-----+\n"
  },
  {
    "path": "compiler/acton/test/syntaxerrors/err6.act",
    "content": "def f(X):\n    a = 2\n    return X+a\n"
  },
  {
    "path": "compiler/acton/test/syntaxerrors/err6.golden",
    "content": "Building file test/syntaxerrors/err6.act using temporary scratch directory\n[error Parse error]: Invalid name (reserved for type variables)\n\n     +--> test/syntaxerrors/err6.act@1:7-1:8\n     |\n   1 | def f(X):\n     :       ^ \n     :       `- Invalid name 'X'\n     :\n     | Note: Single upper case character (optionally followed by digits) are reserved for type variables\n     | Hint: Use a longer name\n-----+\n"
  },
  {
    "path": "compiler/acton/test/syntaxerrors/err7.act",
    "content": "f : [a (Eq)] => (a,a) -> bool\n"
  },
  {
    "path": "compiler/acton/test/syntaxerrors/err7.golden",
    "content": "Building file test/syntaxerrors/err7.act using temporary scratch directory\n[error Parse error]: unexpected 'a'\n                     expecting type variable (upper case letter optionally followed by digits)\n\n     +--> test/syntaxerrors/err7.act@1:6-1:7\n     |\n   1 | f : [a (Eq)] => (a,a) -> bool\n     :      ^ \n     :      `- unexpected 'a'\n     :         expecting type variable (upper case letter optionally followed by digits)\n     :         \n-----+\n"
  },
  {
    "path": "compiler/acton/test/syntaxerrors/err8.act",
    "content": "def f(x):\n    y = 2\n     z = x+y\n    return z\n"
  },
  {
    "path": "compiler/acton/test/syntaxerrors/err8.golden",
    "content": "Building file test/syntaxerrors/err8.act using temporary scratch directory\n[error Indentation error]: Too much indentation\n     +--> err8.act@3:6-3:6\n     |\n   3 |      z = x+y\n     :       \n     :      `- Too much indentation\n-----+\n"
  },
  {
    "path": "compiler/acton/test/syntaxerrors/err9.act",
    "content": "f : [A]\n"
  },
  {
    "path": "compiler/acton/test/syntaxerrors/err9.golden",
    "content": "Building file test/syntaxerrors/err9.act using temporary scratch directory\n[error Parse error]: unexpected newline\n                     expecting \"=>\"\n\n     +--> test/syntaxerrors/err9.act@1:8-1:9\n     |\n   1 | f : [A]\n     :        ^\n     :        `- unexpected newline\n     :           expecting \"=>\"\n     :           \n-----+\n"
  },
  {
    "path": "compiler/acton/test/typeerrors/actor_self_reserved_assignment.act",
    "content": "actor Test():\n    self, x = 1, 2"
  },
  {
    "path": "compiler/acton/test/typeerrors/actor_self_reserved_assignment.golden",
    "content": "Building file test/typeerrors/actor_self_reserved_assignment.act using temporary scratch directory\n   actor_self_reserved_assignment  Parse done                                                            0.000 s\n[error Compilation error]: 'self' cannot be used as a parameter name in actors.\n     +--> actor_self_reserved_assignment.act@2:5-2:9\n     |\n   2 |     self, x = 1, 2\n     :     ^--- \n     :     `- 'self' cannot be used as a parameter name in actors.\n-----+\n"
  },
  {
    "path": "compiler/acton/test/typeerrors/actor_self_reserved_constructor_param.act",
    "content": "actor Test(first, self):\n    def test_method():\n        pass"
  },
  {
    "path": "compiler/acton/test/typeerrors/actor_self_reserved_constructor_param.golden",
    "content": "Building file test/typeerrors/actor_self_reserved_constructor_param.act using temporary scratch directory\n   actor_self_reserved_constructor_param  Parse done                                                            0.000 s\n[error Compilation error]: 'self' cannot be used as a parameter name in actors.\n     +--> actor_self_reserved_constructor_param.act@1:19-1:23\n     |\n   1 | actor Test(first, self):\n     :                   ^--- \n     :                   `- 'self' cannot be used as a parameter name in actors.\n-----+\n"
  },
  {
    "path": "compiler/acton/test/typeerrors/actor_self_reserved_except_as.act",
    "content": "actor Test():\n    try:\n        raise ValueError(\"test\")\n    except ValueError as self:\n        print(self)"
  },
  {
    "path": "compiler/acton/test/typeerrors/actor_self_reserved_except_as.golden",
    "content": "Building file test/typeerrors/actor_self_reserved_except_as.act using temporary scratch directory\n   actor_self_reserved_except_as  Parse done                                                            0.000 s\n[error Compilation error]: 'self' cannot be used as a parameter name in actors.\n     +--> actor_self_reserved_except_as.act@4:26-4:30\n     |\n   4 |     except ValueError as self:\n     :                          ^--- \n     :                          `- 'self' cannot be used as a parameter name in actors.\n-----+\n"
  },
  {
    "path": "compiler/acton/test/typeerrors/actor_self_reserved_loop_var.act",
    "content": "actor Test():\n    for self in [1, 2, 3]:\n        pass"
  },
  {
    "path": "compiler/acton/test/typeerrors/actor_self_reserved_loop_var.golden",
    "content": "Building file test/typeerrors/actor_self_reserved_loop_var.act using temporary scratch directory\n   actor_self_reserved_loop_var  Parse done                                                            0.000 s\n[error Compilation error]: 'self' cannot be used as a parameter name in actors.\n     +--> actor_self_reserved_loop_var.act@2:9-2:13\n     |\n   2 |     for self in [1, 2, 3]:\n     :         ^--- \n     :         `- 'self' cannot be used as a parameter name in actors.\n-----+\n"
  },
  {
    "path": "compiler/acton/test/typeerrors/actor_self_reserved_method_name.act",
    "content": "actor Test():\n    def self():\n        pass"
  },
  {
    "path": "compiler/acton/test/typeerrors/actor_self_reserved_method_name.golden",
    "content": "Building file test/typeerrors/actor_self_reserved_method_name.act using temporary scratch directory\n   actor_self_reserved_method_name  Parse done                                                            0.000 s\n[error Compilation error]: 'self' cannot be used as a parameter name in actors.\n     +--> actor_self_reserved_method_name.act@2:9-2:13\n     |\n   2 |     def self():\n     :         ^--- \n     :         `- 'self' cannot be used as a parameter name in actors.\n-----+\n"
  },
  {
    "path": "compiler/acton/test/typeerrors/actor_self_reserved_method_param.act",
    "content": "actor Test():\n    def test_method(first, self):\n        pass"
  },
  {
    "path": "compiler/acton/test/typeerrors/actor_self_reserved_method_param.golden",
    "content": "Building file test/typeerrors/actor_self_reserved_method_param.act using temporary scratch directory\n   actor_self_reserved_method_param  Parse done                                                            0.000 s\n[error Compilation error]: 'self' cannot be used as a parameter name in actors.\n     +--> actor_self_reserved_method_param.act@2:28-2:32\n     |\n   2 |     def test_method(first, self):\n     :                            ^--- \n     :                            `- 'self' cannot be used as a parameter name in actors.\n-----+\n"
  },
  {
    "path": "compiler/acton/test/typeerrors/actor_self_reserved_method_param2.act",
    "content": "actor Test():\n    def ok_method(param):\n        def test_method(first, self):\n            pass"
  },
  {
    "path": "compiler/acton/test/typeerrors/actor_self_reserved_method_param2.golden",
    "content": "Building file test/typeerrors/actor_self_reserved_method_param2.act using temporary scratch directory\n   actor_self_reserved_method_param2  Parse done                                                            0.000 s\n[error Compilation error]: 'self' cannot be used as a parameter name in actors.\n     +--> actor_self_reserved_method_param2.act@3:32-3:36\n     |\n   3 |         def test_method(first, self):\n     :                                ^--- \n     :                                `- 'self' cannot be used as a parameter name in actors.\n-----+\n"
  },
  {
    "path": "compiler/acton/test/typeerrors/actor_self_reserved_variable.act",
    "content": "actor Test():\n    var self = 42"
  },
  {
    "path": "compiler/acton/test/typeerrors/actor_self_reserved_variable.golden",
    "content": "Building file test/typeerrors/actor_self_reserved_variable.act using temporary scratch directory\n   actor_self_reserved_variable  Parse done                                                            0.000 s\n[error Compilation error]: 'self' cannot be used as a parameter name in actors.\n     +--> actor_self_reserved_variable.act@2:9-2:13\n     |\n   2 |     var self = 42\n     :         ^--- \n     :         `- 'self' cannot be used as a parameter name in actors.\n-----+\n"
  },
  {
    "path": "compiler/acton/test/typeerrors/ex1.act",
    "content": "def f(x,y):\n    return x+y\n\na = f(3)\n"
  },
  {
    "path": "compiler/acton/test/typeerrors/ex1.golden",
    "content": "Building file test/typeerrors/ex1.act using temporary scratch directory\n   ex1  Parse done                                                            0.000 s\n[error]: Incompatible types\n     +--> ex1.act@4:5-4:9\n     |\n   1 | def f(x,y):\n     :     ^ \n     :     `- f is defined here\n     :\n   4 | a = f(3)\n     :     ^---\n     :     `- keyword argument(s) 'y' is missing in call to f\n-----+\n"
  },
  {
    "path": "compiler/acton/test/typeerrors/ex10.act",
    "content": "def f(x):\n    try:\n        y = x+2\n    except int:\n        pass\n    \n    \n"
  },
  {
    "path": "compiler/acton/test/typeerrors/ex10.golden",
    "content": "Building file test/typeerrors/ex10.act using temporary scratch directory\n   ex10  Parse done                                                            0.000 s\n[error]: Constraint violation\n     +--> ex10.act@4:5-4:15\n     |\n   4 |     except int:\n     :     ^--------- \n     :     `- __builtin__.int must be a subclass of __builtin__.Exception\n-----+\n"
  },
  {
    "path": "compiler/acton/test/typeerrors/ex11.act",
    "content": "def f(s):\n    return s + \"!\"\n\na = f([8])\n"
  },
  {
    "path": "compiler/acton/test/typeerrors/ex11.golden",
    "content": "Building file test/typeerrors/ex11.act using temporary scratch directory\n   ex11  Parse done                                                            0.000 s\n[error]: Constraint violation\n     +--> ex11.act@4:5-4:11\n     |\n   1 | def f(s):\n     :     ^ \n     :     `- f is defined here\n     :\n   4 | a = f([8])\n     :     ^-----\n     :     `- Type incompatibility between definition of and call of f (__builtin__.list[_] must be a subclass of __builtin__.str)\n-----+\n"
  },
  {
    "path": "compiler/acton/test/typeerrors/ex13.act",
    "content": "actor main(env):\n  a = Act(7)\n\nactor Act(s:int,t:str):\n  a = s\n  b = t\n\n"
  },
  {
    "path": "compiler/acton/test/typeerrors/ex13.golden",
    "content": "Building file test/typeerrors/ex13.act using temporary scratch directory\n   ex13  Parse done                                                            0.000 s\n[error]: Incompatible types\n     +--> ex13.act@2:7-2:13\n     |\n   2 |   a = Act(7)\n     :       ^-----\n     :       `- keyword component(s) 't' is missing in tuple\n-----+\n"
  },
  {
    "path": "compiler/acton/test/typeerrors/ex14.act",
    "content": "def f(x):\n    return g(x)\n\ndef g(x,y):\n    return x+y\n\n"
  },
  {
    "path": "compiler/acton/test/typeerrors/ex14.golden",
    "content": "Building file test/typeerrors/ex14.act using temporary scratch directory\n   ex14  Parse done                                                            0.000 s\n[error]: Incompatible types\n     +--> ex14.act@2:12-2:16\n     |\n   2 |     return g(x)\n     :            ^---\n     :            `- keyword argument(s) 'y' is missing in call to g\n     :\n   4 | def g(x,y):\n     :     ^ \n     :     `- g is defined here\n-----+\n"
  },
  {
    "path": "compiler/acton/test/typeerrors/ex15.act",
    "content": "def f(x : str):\n    y = 1\n    raise y\n#    y = y + x[7]\n    return y\n\n"
  },
  {
    "path": "compiler/acton/test/typeerrors/ex15.golden",
    "content": "Building file test/typeerrors/ex15.act using temporary scratch directory\n   ex15  Parse done                                                            0.000 s\n[error]: Cannot satisfy the following simultaneous constraints for the unknown types\n     +--> ex15.act@2:9-2:10\n     |\n   2 |     y = 1\n     :         ^\n     :         |- The type of the indicated expression (which we call t1) must implement __builtin__.Number\n     :         `- The type of the indicated expression (which we call t1) must be a subtype of t0\n   3 |     raise y\n     :           ^\n     :           `- The type of the indicated expression (which we call t0) must be a subclass of __builtin__.Exception\n     :              \n-----+\n"
  },
  {
    "path": "compiler/acton/test/typeerrors/ex16.act",
    "content": "actor main(env):\n    def test():\n        foo: ?list[int] = None\n        foo = [1, 2, 3]\n#        if foo is not None:\n        foo.append(4)\n        print(foo)\n    test()\n    await async env.exit(0)\n    \n"
  },
  {
    "path": "compiler/acton/test/typeerrors/ex16.golden",
    "content": "Building file test/typeerrors/ex16.act using temporary scratch directory\n   ex16  Parse done                                                            0.000 s\n[error]: Constraint violation\n     +--> ex16.act@6:9-6:22\n     |\n   6 |         foo.append(4)\n     :         ^------------\n     :         `- ?__builtin__.list[__builtin__.int] does not have an attribute append\n     :            Hint: you may need to test if foo is not None\n-----+\n"
  },
  {
    "path": "compiler/acton/test/typeerrors/ex17.act",
    "content": "\na = pow(3,\"hej\")\n"
  },
  {
    "path": "compiler/acton/test/typeerrors/ex17.golden",
    "content": "Building file test/typeerrors/ex17.act using temporary scratch directory\n   ex17  Parse done                                                            0.000 s\n[error]: Cannot satisfy the following simultaneous constraints for the unknown types\n     +--> ex17.act@2:9-2:10\n     |\n   2 | a = pow(3,\"hej\")\n     :     ^---^-------\n     :     |   `- The type of the indicated expression (which we call t0) must implement __builtin__.Number\n     :     |      \n     :     |- pow has had its polymorphic type [A(Number)] => (a: A, b: A) -> A instantiated to (a: t1, b: t1) -> t1, so t1 must implement __builtin__.Number\n     :     |- The type of the indicated expression (which we call t1) must be a subtype of _\n     :     |- The type of the indicated expression (which we call t0) must be a subtype of t1\n     :     `- The type of the indicated expression (inferred to be __builtin__.str) must be a subtype of t1\n-----+\n"
  },
  {
    "path": "compiler/acton/test/typeerrors/ex18.act",
    "content": "def f(ls : list[A]):\n    return len(ls) + \"hej\"\n"
  },
  {
    "path": "compiler/acton/test/typeerrors/ex18.golden",
    "content": "Building file test/typeerrors/ex18.act using temporary scratch directory\n   ex18  Parse done                                                            0.000 s\n[error]: Cannot satisfy the following simultaneous constraints for the unknown type t0\n     +--> ex18.act@2:12-2:27\n     |\n   2 |     return len(ls) + \"hej\"\n     :            ^--------------\n     :            `- The type of the indicated expression (which we call t0) must implement __builtin__.Plus\n     :               __builtin__.atom must be a subclass of t0\n-----+\n"
  },
  {
    "path": "compiler/acton/test/typeerrors/ex19.act",
    "content": "def f(x,y):\n    if x<y:\n        return x\n    else:\n        return x+y\n\na = f(3,\"hej\")\n\n"
  },
  {
    "path": "compiler/acton/test/typeerrors/ex19.golden",
    "content": "Building file test/typeerrors/ex19.act using temporary scratch directory\n   ex19  Parse done                                                            0.000 s\n[error]: Cannot satisfy the following simultaneous constraints for the unknown types\n     +--> ex19.act@1:5-1:6\n     |\n   1 | def f(x,y):\n     :     ^ \n     :     |- \n     :     |- \n     :     `- \n     :\n   7 | a = f(3,\"hej\")\n     :     ^-^-------\n     :     | `- The type of the indicated expression (which we call t0) must implement __builtin__.Number\n     :     |    \n     :     |- f has had its polymorphic type [A(Plus, Ord)] => (x: A, y: A) -> A instantiated to (x: t1, y: t1) -> t1, so t1 must implement __builtin__.Ord\n     :     |- f has had its polymorphic type [A(Plus, Ord)] => (x: A, y: A) -> A instantiated to (x: t1, y: t1) -> t1, so t1 must implement __builtin__.Plus\n     :     |- Type incompatibility between definition of and call of f (t1 must be a subtype of _)\n     :     |- Type incompatibility between definition of and call of f (t0 must be a subtype of t1)\n     :     `- Type incompatibility between definition of and call of f (__builtin__.str must be a subtype of t1)\n-----+\n"
  },
  {
    "path": "compiler/acton/test/typeerrors/ex2.act",
    "content": "def f(x,y):\n    return x+y\n\na = f(3,4,5)\n"
  },
  {
    "path": "compiler/acton/test/typeerrors/ex2.golden",
    "content": "Building file test/typeerrors/ex2.act using temporary scratch directory\n   ex2  Parse done                                                            0.000 s\n[error]: Incompatible types\n     +--> ex2.act@4:5-4:13\n     |\n   1 | def f(x,y):\n     :     ^ \n     :     `- f is defined here\n     :\n   4 | a = f(3,4,5)\n     :     ^-------\n     :     `- too many positional argument(s) in call to f\n-----+\n"
  },
  {
    "path": "compiler/acton/test/typeerrors/ex20.act",
    "content": "f : (str,str) -> str\n\ndef f(s : str, a):\n    return s * a\n"
  },
  {
    "path": "compiler/acton/test/typeerrors/ex20.golden",
    "content": "Building file test/typeerrors/ex20.act using temporary scratch directory\n   ex20  Parse done                                                            0.000 s\n[error]: Constraint violation\n     +--> ex20.act@1:1-1:2\n     |\n   1 |    f : (str,str) -> str\n     :    ^ \n     :    `- Type incompatibility between signature for and definition of f (__builtin__.str must be a subclass of __builtin__.int)\n     :\n   3 | +> def f(s : str, a):\n   4 | |>     return s * a\n     : | \n     : `- f is defined here\n-----+\n"
  },
  {
    "path": "compiler/acton/test/typeerrors/ex21.act",
    "content": "import math\n\nactor main(env):\n   print(math.sin(\"hej\"))\n   env.exit(0)\n   \n"
  },
  {
    "path": "compiler/acton/test/typeerrors/ex21.golden",
    "content": "Building file test/typeerrors/ex21.act using temporary scratch directory\n   ex21  Parse done                                                            0.000 s\n[error]: Constraint violation\n     +--> ex21.act@4:10-4:25\n     |\n   4 |    print(math.sin(\"hej\"))\n     :          ^-------------- \n     :          `- The type of the indicated expression (inferred to be __builtin__.str) must be a subclass of __builtin__.float\n-----+\n"
  },
  {
    "path": "compiler/acton/test/typeerrors/ex22.act",
    "content": "f : [A(Plus)] => (A) -> A\n\ndef f(x,y):\n    return x\n"
  },
  {
    "path": "compiler/acton/test/typeerrors/ex22.golden",
    "content": "Building file test/typeerrors/ex22.act using temporary scratch directory\n   ex22  Parse done                                                            0.000 s\n[error]: Incompatible types\n     +--> ex22.act@1:1-1:2\n     |\n   1 |    f : [A(Plus)] => (A) -> A\n     :    ^ \n     :    `- keyword argument(s) 'y' is missing in call to f\n     :\n   3 | +> def f(x,y):\n   4 | |>     return x\n     : | \n     : `- f is defined here\n-----+\n"
  },
  {
    "path": "compiler/acton/test/typeerrors/ex23.act",
    "content": "def f(x,s : str):\n    if s==7:\n       return x\n    else:\n       return x+x\n\n# This gives a misleading error message; the last constraint is\n#\n#   |\n# 2 |    if s==7:\n#   |       ^^^^\n# The type of s == 7 (which we call t1) must implement __builtin__.Eq\n#\n# Instead of \"The type of s == 7\" one wants \"a common supertype of s and 7\" (?)\n#\n# Fix should be done in the\n#\n#     infer env e@(CompOp l e1 [OpArg op e2])\n#\n# case in Types.hs.\n#\n# Similar problems show up for other binary operators.\n"
  },
  {
    "path": "compiler/acton/test/typeerrors/ex23.golden",
    "content": "Building file test/typeerrors/ex23.act using temporary scratch directory\n   ex23  Parse done                                                            0.000 s\n[error]: Cannot satisfy the following simultaneous constraints for the unknown types\n     +--> ex23.act@2:11-2:12\n     |\n   2 |     if s==7:\n     :        ^--^ \n     :        |  |- The type of the indicated expression (which we call t0) must implement __builtin__.Number\n     :        |     \n     :        |  `- The type of the indicated expression (which we call t0) must be a subtype of t1\n     :        |- The type of the indicated expression (inferred to be __builtin__.str) must be a subtype of t1\n     :        `- The type of the indicated expression (which we call t1) must implement __builtin__.Eq\n-----+\n"
  },
  {
    "path": "compiler/acton/test/typeerrors/ex24.act",
    "content": "# TODO: error should print line numbers\n\ndef foo():\n    a : ?str = \"\"\n    b: dict[str, str] = {}\n    b[a] = \"hej\"\n"
  },
  {
    "path": "compiler/acton/test/typeerrors/ex24.golden",
    "content": "Building file test/typeerrors/ex24.act using temporary scratch directory\n   ex24  Parse done                                                            0.000 s\n[error]: Type unification error\n     +--> ex24.act@5:13-5:16\n     |\n   5 |     b: dict[str, str] = {}\n     :             ^-- \n     :             `- Incompatible types __builtin__.str and ?T_12\n-----+\n"
  },
  {
    "path": "compiler/acton/test/typeerrors/ex25.act",
    "content": "actor Bob():\n    def foo(cb):\n        pass\n\nactor Rob():\n    def bar():\n        b = Bob()\n        b.foo()\n"
  },
  {
    "path": "compiler/acton/test/typeerrors/ex25.golden",
    "content": "Building file test/typeerrors/ex25.act using temporary scratch directory\n   ex25  Parse done                                                            0.000 s\n[error]: Incompatible types\n     +--> ex25.act@8:9-8:16\n     |\n   8 |         b.foo()\n     :         ^------\n     :         `- keyword component(s) 'cb' is missing in tuple\n-----+\n"
  },
  {
    "path": "compiler/acton/test/typeerrors/ex26.act",
    "content": "class Foo(object):\n    thing: ?bool\n\n    def __init__(self, thing):\n        self.thing = thing\n\nmut def remove_thing(foos):\n    for f in foos:\n        f.thing = None\n\ndef process():\n    p = []\n    foos = [Foo(True)]\n    # This is obviously wrong, remove_thing() does not return Iterable\n    p.extend(remove_thing(foos))\n"
  },
  {
    "path": "compiler/acton/test/typeerrors/ex26.golden",
    "content": "Building file test/typeerrors/ex26.act using temporary scratch directory\n   ex26  Parse done                                                            0.000 s\n[error]: Constraint violation\n     +--> ex26.act@15:5-15:33\n     |\n  15 |     p.extend(remove_thing(foos))\n     :     ^---------------------------\n     :     `- None must be a subclass of __builtin__.list[_]\n-----+\n"
  },
  {
    "path": "compiler/acton/test/typeerrors/ex27.act",
    "content": "class Foo(object):\n    def __init__(self):\n        pass\n\n    def foo(a: int):\n        return 42\n"
  },
  {
    "path": "compiler/acton/test/typeerrors/ex27.golden",
    "content": "Building file test/typeerrors/ex27.act using temporary scratch directory\n   ex27  Parse done                                                            0.000 s\n[error]: Type unification error\n     +--> ex27.act@5:5-6:1\n     |\n   5 | +>     def foo(a: int):\n   6 | |>         return 42\n     : | \n     : `- Type of first parameter of class method does not unify with Self\n-----+\n"
  },
  {
    "path": "compiler/acton/test/typeerrors/ex4.act",
    "content": "def f(x,y):\n    return x+y\n\nactor main(env):\n    print(\"a\".center(f(3)))\n    \n"
  },
  {
    "path": "compiler/acton/test/typeerrors/ex4.golden",
    "content": "Building file test/typeerrors/ex4.act using temporary scratch directory\n   ex4  Parse done                                                            0.000 s\n[error]: Incompatible types\n     +--> ex4.act@5:22-5:26\n     |\n   1 | def f(x,y):\n     :     ^ \n     :     `- f is defined here\n     :\n   5 |     print(\"a\".center(f(3)))\n     :                      ^--- \n     :                      `- keyword argument(s) 'y' is missing in call to f\n-----+\n"
  },
  {
    "path": "compiler/acton/test/typeerrors/ex5.act",
    "content": "def f(x,y):\n    return x+y\n\ndef apply(g,x):\n    return g(x)\n\na = apply(f,3)\n\n"
  },
  {
    "path": "compiler/acton/test/typeerrors/ex5.golden",
    "content": "Building file test/typeerrors/ex5.act using temporary scratch directory\n   ex5  Parse done                                                            0.000 s\n[error]: Incompatible types\n     +--> ex5.act@7:5-7:15\n     |\n   4 | def apply(g,x):\n     :     ^---- \n     :     `- apply is defined here\n     :\n   7 | a = apply(f,3)\n     :     ^---------\n     :     `- keyword argument(s) 'y' is missing in call to apply\n-----+\n"
  },
  {
    "path": "compiler/acton/test/typeerrors/ex6.act",
    "content": "(a,b) = (1,3,5)\n\n"
  },
  {
    "path": "compiler/acton/test/typeerrors/ex6.golden",
    "content": "Building file test/typeerrors/ex6.act using temporary scratch directory\n   ex6  Parse done                                                            0.000 s\n[error]: Incompatible types\n     +--> ex6.act@1:9-1:16\n     |\n   1 | (a,b) = (1,3,5)\n     :         ^------\n     :         `- too many positional component(s) in tuple\n-----+\n"
  },
  {
    "path": "compiler/acton/test/typeerrors/ex7.act",
    "content": "actor main(env):\n    var k = 3\n    pure def g():\n        return k\n    \n"
  },
  {
    "path": "compiler/acton/test/typeerrors/ex7.golden",
    "content": "Building file test/typeerrors/ex7.act using temporary scratch directory\n   ex7  Parse done                                                            0.000 s\n[error]: Constraint violation\n     +--> ex7.act@4:16-4:17\n     |\n   4 |         return k\n     :                ^\n     :                `- State variable may only be accessed in a proc\n-----+\n"
  },
  {
    "path": "compiler/acton/test/typeerrors/ex8.act",
    "content": "actor main(env):\n    n : int = 7\n    for x in n:\n        pass\n    \n"
  },
  {
    "path": "compiler/acton/test/typeerrors/ex8.golden",
    "content": "Building file test/typeerrors/ex8.act using temporary scratch directory\n   ex8  Parse done                                                            0.000 s\n[error]: Cannot satisfy the following simultaneous constraints for the unknown type t0\n     +--> ex8.act@3:14-3:15\n     |\n   3 |     for x in n:\n     :              ^ \n     :              |- The type of the indicated expression (inferred to be __builtin__.int) must be a subtype of t0\n     :                 \n     :              `- The type of the indicated expression (which we call t0) must implement __builtin__.Iterable[_]\n-----+\n"
  },
  {
    "path": "compiler/acton/test/typeerrors/ex9.act",
    "content": "def f(x,y):\n    return x+y\n\na = f(3,\"hej\")\n"
  },
  {
    "path": "compiler/acton/test/typeerrors/ex9.golden",
    "content": "Building file test/typeerrors/ex9.act using temporary scratch directory\n   ex9  Parse done                                                            0.000 s\n[error]: Cannot satisfy the following simultaneous constraints for the unknown types\n     +--> ex9.act@1:5-1:6\n     |\n   1 | def f(x,y):\n     :     ^ \n     :     |- \n     :     |- \n     :     `- \n     :\n   4 | a = f(3,\"hej\")\n     :     ^-^-------\n     :     | `- The type of the indicated expression (which we call t0) must implement __builtin__.Number\n     :     |    \n     :     |- f has had its polymorphic type [A(Plus)] => (x: A, y: A) -> A instantiated to (x: t1, y: t1) -> t1, so t1 must implement __builtin__.Plus\n     :     |- Type incompatibility between definition of and call of f (t1 must be a subtype of _)\n     :     |- Type incompatibility between definition of and call of f (t0 must be a subtype of t1)\n     :     `- Type incompatibility between definition of and call of f (__builtin__.str must be a subtype of t1)\n-----+\n"
  },
  {
    "path": "compiler/acton/test/typeerrors/funargs1.act",
    "content": "def f(x,y):\n    return x+y\n\na = f(3,x=3,y=3)\n"
  },
  {
    "path": "compiler/acton/test/typeerrors/funargs1.golden",
    "content": "Building file test/typeerrors/funargs1.act using temporary scratch directory\n   funargs1  Parse done                                                            0.000 s\n[error]: Unexpected keyword argument\n     +--> funargs1.act@4:9-4:10\n     |\n   4 | a = f(3,x=3,y=3)\n     :         ^ \n     :         `- Unexpected keyword argument 'x'\n-----+\n"
  },
  {
    "path": "compiler/acton/test/typeerrors/funargs2.act",
    "content": "def f(x,y):\n    return x+y\n\na = f(3,z=3,y=3)\n"
  },
  {
    "path": "compiler/acton/test/typeerrors/funargs2.golden",
    "content": "Building file test/typeerrors/funargs2.act using temporary scratch directory\n   funargs2  Parse done                                                            0.000 s\n[error]: Unexpected keyword argument\n     +--> funargs2.act@4:9-4:10\n     |\n   4 | a = f(3,z=3,y=3)\n     :         ^ \n     :         `- Unexpected keyword argument 'z'\n-----+\n"
  },
  {
    "path": "compiler/acton/test/typeerrors/funargs3.act",
    "content": "def f(x,y):\n    return x+y\n\na = f(x=3,4)\n"
  },
  {
    "path": "compiler/acton/test/typeerrors/funargs3.golden",
    "content": "Building file test/typeerrors/funargs3.act using temporary scratch directory\n[error Parse error]: unexpected '4'\n                     expecting \"**\" or closing ')'\n\n     +--> test/typeerrors/funargs3.act@4:11-4:12\n     |\n   4 | a = f(x=3,4)\n     :           ^ \n     :           `- unexpected '4'\n     :              expecting \"**\" or closing ')'\n     :              \n-----+\n"
  },
  {
    "path": "compiler/acton/test/typeerrors/funargs4.act",
    "content": "def f(x,y):\n    return x+y\n\na = f(4,x=3,y=4)\n"
  },
  {
    "path": "compiler/acton/test/typeerrors/funargs4.golden",
    "content": "Building file test/typeerrors/funargs4.act using temporary scratch directory\n   funargs4  Parse done                                                            0.000 s\n[error]: Unexpected keyword argument\n     +--> funargs4.act@4:9-4:10\n     |\n   4 | a = f(4,x=3,y=4)\n     :         ^ \n     :         `- Unexpected keyword argument 'x'\n-----+\n"
  },
  {
    "path": "compiler/acton/test/typeerrors/funargs5.act",
    "content": "def f(x,y,*z,w):\n    return x\n\na = f(3,4,5,6)\n"
  },
  {
    "path": "compiler/acton/test/typeerrors/funargs5.golden",
    "content": "Building file test/typeerrors/funargs5.act using temporary scratch directory\n   funargs5  Parse done                                                            0.000 s\n[error]: Incompatible types\n     +--> funargs5.act@4:5-4:15\n     |\n   1 | def f(x,y,*z,w):\n     :     ^ \n     :     `- f is defined here\n     :\n   4 | a = f(3,4,5,6)\n     :     ^---------\n     :     `- keyword argument(s) 'w' is missing in call to f\n-----+\n"
  },
  {
    "path": "compiler/acton/test/typeerrors/funargs6.act",
    "content": "def f(x,y,*z,w):\n    return x\n\na = f(3,w=6)\n"
  },
  {
    "path": "compiler/acton/test/typeerrors/funargs6.golden",
    "content": "Building file test/typeerrors/funargs6.act using temporary scratch directory\n   funargs6  Parse done                                                            0.000 s\n[error]: Incompatible types\n     +--> funargs6.act@4:5-4:13\n     |\n   1 | def f(x,y,*z,w):\n     :     ^ \n     :     `- f is defined here\n     :\n   4 | a = f(3,w=6)\n     :     ^-------\n     :     `- too few argument(s) in call to f\n-----+\n"
  },
  {
    "path": "compiler/acton/test.hs",
    "content": "{-# LANGUAGE CPP #-}\n{-# LANGUAGE ScopedTypeVariables #-}\nimport Control.Monad\nimport Data.Char (isAlphaNum, isSpace)\nimport Data.List\nimport Data.List.Split\nimport Data.Maybe (catMaybes)\nimport Data.Ord\nimport Data.Time.Clock.POSIX\nimport qualified Data.ByteString.Lazy.Char8 as LBS\n\nimport Control.Exception (catch, IOException)\nimport System.Directory\nimport System.Directory.Recursive\nimport System.Environment (getEnvironment)\nimport System.Exit\nimport System.FilePath\nimport System.FilePath.Posix\nimport System.Process\nimport System.TimeIt\nimport System.IO.Temp (withSystemTempDirectory)\n\nimport Test.Tasty\nimport Test.Tasty.ExpectedFailure\nimport Test.Tasty.Golden (goldenVsString)\nimport Test.Tasty.HUnit\n\nimport qualified PkgCommands\nimport qualified Acton.CommandLineParser as C\nimport qualified Acton.Fingerprint as Fingerprint\nimport qualified Options.Applicative as OA\nimport qualified Paths_acton\nimport qualified TestGolden\n\n-- The default is to build and run each test program with the expectation that\n-- both compilation and running the program is successful as determined by exit\n-- status of 0. If a test is expected to fail compilation, it should be named\n-- __bf.act (for Build Failure). If a test is expected to fail at run time, name\n-- the file with __rf.act (for Run Failure).\n\nmain = do\n#if defined(darwin_HOST_OS)\n    let segfault_exitcode = (ExitFailure (-11))\n#else\n    let segfault_exitcode = (ExitFailure 139)\n#endif\n    builtinsAutoTests <- createAutoTests \"Builtins auto\" \"../../test/builtins_auto\"\n    coreLangAutoTests <- createAutoTests \"Core language auto\" \"../../test/core_lang_auto\"\n    dbAutoTests <- createAutoTests \"DB auto\" \"../../test/db_auto\"\n    exampleTests <- createTests \"Examples\" \"../../examples\" False [] (testBuild \"\" ExitSuccess)\n    regressionTests <- createAutoTests \"Regression auto\" \"../../test/regression_auto\"\n    regressionSegfaultTests <- createTests \"Regression segfaults\" \"../../test/regression_segfault\" False [] (testBuild \"\" ExitSuccess)\n    rtsAutoTests <- createAutoTests \"RTS auto\" \"../../test/rts_auto\"\n    stdlibAutoTests <- createAutoTests \"stdlib auto\" \"../../test/stdlib_auto\"\n    syntaxErrorAutoTests <- createGoldenErrorAutoTests \"syntax errors\" \"test/syntaxerrors\"\n    typeErrorAutoTests <- createGoldenErrorAutoTests \"type errors\" \"test/typeerrors\"\n    defaultMain $ localOption timeout $ testGroup \"Tests\" $\n      [ builtinsAutoTests\n      , coreLangAutoTests\n      , coreLangTests\n      , dbAutoTests\n      , compilerTests\n      , actonProjTests\n      , actonRootArgTests\n      , exampleTests\n      , regressionTests\n      , regressionSegfaultTests\n      , rtsAutoTests\n      , rtsTests\n      , stdlibTests\n      , stdlibAutoTests\n      , syntaxErrorAutoTests\n      , typeErrorAutoTests\n      , parseFlagTests\n      , crossCompileTests\n      , pkgCliTests\n      ]\n  where timeout :: Timeout\n        timeout = mkTimeout (30*60*1000000)\n        -- this normally doesn't take long on a local machine but in GitHub\n        -- Actions CI, in particular the MacOS workers can be really slow so it\n        -- has taken longer than 3 minutes, thus the rather lengthy timeout\n\ncoreLangTests =\n  testGroup \"Core language\"\n  [\n    testCase \"async context\" $ do\n        (returnCode, cmdOut, cmdErr) <- buildAndRun \"\" \"\" \"../../test/core_lang/async-context.act\"\n        assertEqual \"should compile\" ExitSuccess returnCode\n        assertEqual \"should see 2 pongs\" \"pong\\npong\\n\" cmdOut\n  ]\n\ncompilerTests =\n  testGroup \"compiler tests\"\n  [\n    testCase \"target native\" $ do\n        testBuild \"--target native\" ExitSuccess False \"test/project/simple\"\n  , testCase \"mixed dots in qualified name\" $ do\n        (returnCode, cmdOut, cmdErr) <- readCreateProcessWithExitCode (shell $ \"rm -rf ../../test/compiler/mixed-dots/out\") \"\"\n        testBuild \"\" ExitSuccess False \"../../test/compiler/mixed-dots/\"\n        testBuild \"\" ExitSuccess False \"../../test/compiler/mixed-dots/\"\n  , testCase \"sub-modules and dashes\" $ do\n        (returnCode, cmdOut, cmdErr) <- readCreateProcessWithExitCode (shell $ \"rm -rf ../../test/compiler/subdash/out\") \"\"\n        testBuild \"\" ExitSuccess False \"../../test/compiler/subdash/\"\n        testBuild \"\" ExitSuccess False \"../../test/compiler/subdash/\"\n  , testCase \"deps\" $ do\n        (returnCode, cmdOut, cmdErr) <- readCreateProcessWithExitCode (shell $ \"rm -rf ../../test/compiler/test_deps/build.zig*\") \"\"\n        (returnCode, cmdOut, cmdErr) <- readCreateProcessWithExitCode (shell $ \"rm -rf ../../test/compiler/test_deps/out\") \"\"\n        (returnCode, cmdOut, cmdErr) <- readCreateProcessWithExitCode (shell $ \"rm -rf ../../test/compiler/test_deps/deps/a/build.zig*\") \"\"\n        (returnCode, cmdOut, cmdErr) <- readCreateProcessWithExitCode (shell $ \"rm -rf ../../test/compiler/test_deps/deps/a/out\") \"\"\n        runActon \"build\" ExitSuccess False \"../../test/compiler/test_deps/\"\n  , testCase \"path dependency fetches transitive cached deps before discovery\" $ do\n        withSystemTempDirectory \"acton-transitive-path-fetch\" $ \\tmp -> do\n          actonExe <- canonicalizePath \"../../dist/bin/acton\"\n          env0 <- getEnvironment\n          let homeDir = tmp </> \"home\"\n              rootProj = tmp </> \"root\"\n              specProj = rootProj </> \"spec\"\n              fakeHash = \"transitive-hash-does-not-exist\"\n              envWithHome = (\"HOME\", homeDir) : filter ((/= \"HOME\") . fst) env0\n              mkFp name = Fingerprint.formatFingerprint\n                (Fingerprint.updateFingerprintPrefix\n                  (Fingerprint.fingerprintPrefixForName name) 1)\n          createDirectoryIfMissing True homeDir\n          createDirectoryIfMissing True (rootProj </> \"src\")\n          createDirectoryIfMissing True (specProj </> \"src\")\n          writeFile (rootProj </> \"Build.act\") $ unlines\n            [ \"name = \\\"root_proj\\\"\"\n            , \"fingerprint = \" ++ mkFp \"root_proj\"\n            , \"dependencies = {\"\n            , \"    \\\"spec\\\": (path=\\\"spec\\\")\"\n            , \"}\"\n            , \"zig_dependencies = {}\"\n            ]\n          writeFile (rootProj </> \"src\" </> \"main.act\") $ unlines\n            [ \"actor main(env):\"\n            , \"    env.exit(0)\"\n            ]\n          writeFile (specProj </> \"Build.act\") $ unlines\n            [ \"name = \\\"spec_proj\\\"\"\n            , \"fingerprint = \" ++ mkFp \"spec_proj\"\n            , \"dependencies = {\"\n            , \"    \\\"ghost\\\": (hash=\\\"\" ++ fakeHash ++ \"\\\")\"\n            , \"}\"\n            , \"zig_dependencies = {}\"\n            ]\n          writeFile (specProj </> \"src\" </> \"specproj.act\") \"def marker() -> int:\\n    return 1\\n\"\n          (returnCode, _cmdOut, cmdErr) <- readCreateProcessWithExitCode\n            (proc actonExe [\"build\"]) { cwd = Just rootProj, env = Just envWithHome } \"\"\n          assertEqual \"acton should fail for unfetchable transitive dependency\" (ExitFailure 1) returnCode\n          assertBool \"should fail during dependency fetch/copy, not later Build.act load\"\n            (\"not present in Zig cache after fetch\" `isInfixOf` cmdErr)\n          assertBool \"should not fail with missing Build.act in unresolved deps cache path\"\n            (not (\"Missing Build.act in \" `isInfixOf` cmdErr))\n  , testCase \"build.zig.zon uses canonical dep roots\" $ do\n        withSystemTempDirectory \"acton-buildzig-zon-dedup\" $ \\tmp -> do\n          actonExe <- canonicalizePath \"../../dist/bin/acton\"\n          env0 <- getEnvironment\n          let homeDir = tmp </> \"home\"\n              rootProj = tmp </> \"root\"\n              depKeep = rootProj </> \"dep_keep\"\n              midProj = rootProj </> \"mid\"\n              depDrop = tmp </> \"dep_drop\"\n              envWithHome = (\"HOME\", homeDir) : filter ((/= \"HOME\") . fst) env0\n              mkFp name = Fingerprint.formatFingerprint\n                (Fingerprint.updateFingerprintPrefix\n                  (Fingerprint.fingerprintPrefixForName name) 1)\n              writeBuildActAt :: FilePath -> String -> [(String, FilePath)] -> IO ()\n              writeBuildActAt dir name deps = do\n                createDirectoryIfMissing True (dir </> \"src\")\n                let depsBody = intercalate \",\\n\"\n                      [ \"    \\\"\" ++ depName ++ \"\\\": (\\n\"\n                        ++ \"        path=\" ++ show depPath ++ \"\\n\"\n                        ++ \"    )\"\n                      | (depName, depPath) <- deps\n                      ]\n                    depsSection =\n                      if null deps\n                        then \"dependencies = {}\"\n                        else \"dependencies = {\\n\" ++ depsBody ++ \"\\n}\"\n                writeFile (dir </> \"Build.act\") $ unlines\n                  [ \"name = \" ++ show name\n                  , \"fingerprint = \" ++ mkFp name\n                  , \"\"\n                  , depsSection\n                  , \"\"\n                  , \"zig_dependencies = {}\"\n                  ]\n              runBuild dir = readCreateProcessWithExitCode\n                (proc actonExe [\"build\", \"--always-build\"]) { cwd = Just dir, env = Just envWithHome } \"\"\n\n          createDirectoryIfMissing True homeDir\n\n          writeBuildActAt depKeep \"dep\" []\n          writeFile (depKeep </> \"src\" </> \"dep.act\") $ unlines\n            [ \"def keep() -> int:\"\n            , \"    return 1\"\n            ]\n\n          writeBuildActAt depDrop \"dep\" []\n          writeFile (depDrop </> \"src\" </> \"dep.act\") $ unlines\n            [ \"def drop() -> int:\"\n            , \"    return 2\"\n            ]\n\n          writeBuildActAt midProj \"mid\" [(\"dep\", depDrop)]\n          writeFile (midProj </> \"src\" </> \"mid.act\") $ unlines\n            [ \"def marker() -> int:\"\n            , \"    return 41\"\n            ]\n\n          writeBuildActAt rootProj \"root_proj\" [(\"dep\", depKeep), (\"mid\", midProj)]\n          writeFile (rootProj </> \"src\" </> \"main.act\") $ unlines\n            [ \"import mid\"\n            , \"\"\n            , \"actor main(env):\"\n            , \"    env.exit(mid.marker())\"\n            ]\n\n          (returnCode, cmdOut, cmdErr) <- runBuild rootProj\n          when (returnCode /= ExitSuccess) $\n            assertFailure (\"root build failed:\\nstdout:\\n\" ++ cmdOut ++ \"\\nstderr:\\n\" ++ cmdErr)\n\n          midBuildZon <- readFile (midProj </> \"build.zig.zon\")\n          assertBool \"mid build.zig.zon should point at the canonical dep root\"\n            (\"dep_keep\" `isInfixOf` midBuildZon)\n          assertBool \"mid build.zig.zon should not keep the overridden raw dep path\"\n            (not (\"dep_drop\" `isInfixOf` midBuildZon))\n  , testCase \"path dep build ignores stale dep out/types modules\" $ do\n        withSystemTempDirectory \"acton-stale-path-dep\" $ \\tmp ->\n          do\n            actonExe <- canonicalizePath \"../../dist/bin/acton\"\n            createDirectoryIfMissing True (tmp </> \"home\")\n            env0 <- getEnvironment\n            let depV1 = tmp </> \"dep_v1\"\n                depV2 = tmp </> \"dep_v2\"\n                midProj = tmp </> \"mid\"\n                appProj = tmp </> \"app\"\n                envWithHome = (\"HOME\", tmp </> \"home\") : filter ((/= \"HOME\") . fst) env0\n                mkFp name = Fingerprint.formatFingerprint\n                  (Fingerprint.updateFingerprintPrefix\n                    (Fingerprint.fingerprintPrefixForName name) 1)\n                writeBuildActAt dir name deps = do\n                  createDirectoryIfMissing True (dir </> \"src\")\n                  let depsBody = intercalate \",\\n\"\n                        [ \"    \\\"\" ++ depName ++ \"\\\": (\\n\"\n                          ++ \"        path=\\\"\" ++ depPath ++ \"\\\"\\n\"\n                          ++ \"    )\"\n                        | (depName, depPath) <- deps\n                        ]\n                      depsSection =\n                        if null deps\n                          then \"dependencies = {}\"\n                          else \"dependencies = {\\n\" ++ depsBody ++ \"\\n}\"\n                  writeFile (dir </> \"Build.act\") $ unlines\n                    [ \"name = \\\"\" ++ name ++ \"\\\"\"\n                    , \"fingerprint = \" ++ mkFp name\n                    , \"\"\n                    , depsSection\n                    , \"\"\n                    , \"zig_dependencies = {}\"\n                    , \"\"\n                    ]\n                runBuild dir = readCreateProcessWithExitCode\n                  (proc actonExe [\"build\", \"--always-build\"]) { cwd = Just dir, env = Just envWithHome } \"\"\n                assertBuildOk label (code, out, err) =\n                  when (code /= ExitSuccess) $\n                    assertFailure (label ++ \" failed:\\nstdout:\\n\" ++ out ++ \"\\nstderr:\\n\" ++ err)\n\n            writeBuildActAt depV1 \"dep\" []\n            createDirectoryIfMissing True (depV1 </> \"src\" </> \"dep\")\n            writeFile (depV1 </> \"src\" </> \"dep.act\") $ unlines\n              [ \"def base() -> int:\"\n              , \"    return 1\"\n              ]\n            writeFile (depV1 </> \"src\" </> \"dep\" </> \"legacy.act\") $ unlines\n              [ \"def legacy() -> int:\"\n              , \"    return 7\"\n              ]\n\n            writeBuildActAt depV2 \"dep\" []\n            writeFile (depV2 </> \"src\" </> \"dep.act\") $ unlines\n              [ \"def base() -> int:\"\n              , \"    return 1\"\n              ]\n\n            writeBuildActAt midProj \"mid\" [(\"dep\", depV1)]\n            createDirectoryIfMissing True (midProj </> \"src\" </> \"mid\")\n            writeFile (midProj </> \"src\" </> \"mid\" </> \"used.act\") $ unlines\n              [ \"import dep\"\n              , \"\"\n              , \"def value() -> int:\"\n              , \"    return dep.base()\"\n              ]\n            writeFile (midProj </> \"src\" </> \"mid\" </> \"stale.act\") $ unlines\n              [ \"import dep.legacy\"\n              , \"\"\n              , \"def stale() -> int:\"\n              , \"    return dep.legacy.legacy()\"\n              ]\n\n            writeBuildActAt appProj \"app\" [(\"mid\", midProj), (\"dep\", depV2)]\n            writeFile (appProj </> \"src\" </> \"main.act\") $ unlines\n              [ \"import mid.used\"\n              , \"\"\n              , \"actor main(env: Env):\"\n              , \"    print(mid.used.value())\"\n              , \"    env.exit(0)\"\n              ]\n\n            assertBuildOk \"initial build of mid dependency\" =<< runBuild midProj\n            staleCExists <- doesFileExist (midProj </> \"out\" </> \"types\" </> \"mid\" </> \"stale.c\")\n            assertBool \"expected stale dependency C output to exist\" staleCExists\n            assertBuildOk \"build of app with transitive dep override\" =<< runBuild appProj\n  , testCase \"build.zig.zon name matches Build.act\" $ do\n        let prefix = \"acton-long-project-name-12345678901234567890-\"\n        withSystemTempDirectory prefix $ \\proj -> do\n            let name = \"long_project_name_1234567890\"\n                fp = Fingerprint.formatFingerprint\n                       (Fingerprint.updateFingerprintPrefix\n                         (Fingerprint.fingerprintPrefixForName name) 1)\n                srcDir = proj </> \"src\"\n                actFile = srcDir </> \"main.act\"\n            createDirectoryIfMissing True srcDir\n            writeFile (proj </> \"Build.act\") $ unlines\n              [ \"name = \\\"\" ++ name ++ \"\\\"\"\n              , \"fingerprint = \" ++ fp\n              , \"\"\n              ]\n            writeFile actFile $ unlines\n              [ \"actor main(env):\"\n              , \"    print(\\\"Hello, world\\\")\"\n              , \"    env.exit(0)\"\n              ]\n            runActon \"build\" ExitSuccess False proj\n            zon <- readFile (proj </> \"build.zig.zon\")\n            let nameVal =\n                  let isNameLine l = \".name = .\" `isPrefixOf` dropWhile isSpace l\n                  in case find isNameLine (lines zon) of\n                       Just line ->\n                         case stripPrefix \".name = .\" (dropWhile isSpace line) of\n                           Just rest -> takeWhile (\\c -> isAlphaNum c || c == '_') rest\n                           Nothing -> \"\"\n                       Nothing -> \"\"\n            assertEqual \"build.zig.zon name should match Build.act\" name nameVal\n            assertBool \"build.zig.zon name should be <= 32 chars\" (length nameVal <= 32)\n\n  , testCase \"build without Build.act\" $ do\n        withSystemTempDirectory \"acton-build\" $ \\proj -> do\n            let actFile = proj </> \"acton-test.act\"\n            writeFile actFile $ unlines\n              [ \"#!/usr/bin/env runacton\"\n              , \"actor main(env):\"\n              , \"    print(\\\"Hello, world\\\")\"\n              , \"    env.exit(0)\"\n              ]\n            perms <- getPermissions actFile\n            setPermissions actFile perms{ executable = True }\n            actonExe <- canonicalizePath \"../../dist/bin/acton\"\n            (returnCode, _cmdOut, cmdErr) <- readCreateProcessWithExitCode (proc actonExe [\"build\"]) { cwd = Just proj } \"\"\n            assertEqual \"acton should fail without Build.act\" (ExitFailure 1) returnCode\n            assertBool \"error should mention Build.act\" (\"Build.act\" `isInfixOf` cmdErr)\n#if !defined(mingw32_HOST_OS)\n  , testCase \"runacton shebang runs standalone script\" $ do\n        withSystemTempDirectory \"acton-runacton\" $ \\proj -> do\n            let script = proj </> \"hello.act\"\n            writeFile script $ unlines\n              [ \"#!/usr/bin/env runacton\"\n              , \"actor main(env):\"\n              , \"    print(\\\"Hello from runacton\\\")\"\n              , \"    env.exit(0)\"\n              ]\n            perms <- getPermissions script\n            setPermissions script perms{ executable = True }\n            (returnCode, cmdOut, cmdErr) <- runRunacton script [] proj\n            assertEqual \"runacton should succeed\" ExitSuccess returnCode\n            assertEqual \"runacton output\" \"Hello from runacton\\n\" cmdOut\n            assertEqual \"runacton stderr\" \"\" cmdErr\n\n  , testCase \"runacton ignores project Build.act\" $ do\n        withSystemTempDirectory \"acton-runacton-proj\" $ \\proj -> do\n            let name = \"demo\"\n                fp = Fingerprint.formatFingerprint\n                       (Fingerprint.updateFingerprintPrefix\n                         (Fingerprint.fingerprintPrefixForName name) 1)\n                srcDir = proj </> \"src\"\n                mainFile = srcDir </> \"main.act\"\n                script = proj </> \"script.act\"\n            createDirectoryIfMissing True srcDir\n            writeFile (proj </> \"Build.act\") $ unlines\n              [ \"name = \\\"\" ++ name ++ \"\\\"\"\n              , \"fingerprint = \" ++ fp\n              , \"\"\n              ]\n            writeFile mainFile $ unlines\n              [ \"actor main(env):\"\n              , \"    print(\\\"Project main\\\")\"\n              , \"    env.exit(0)\"\n              ]\n            writeFile script $ unlines\n              [ \"#!/usr/bin/env runacton\"\n              , \"actor main(env):\"\n              , \"    print(\\\"Script main\\\")\"\n              , \"    env.exit(0)\"\n              ]\n            perms <- getPermissions script\n            setPermissions script perms{ executable = True }\n            (returnCode, cmdOut, cmdErr) <- runRunacton script [] proj\n            assertEqual \"runacton should succeed\" ExitSuccess returnCode\n            assertEqual \"runacton output\" \"Script main\\n\" cmdOut\n            assertEqual \"runacton stderr\" \"\" cmdErr\n#endif\n  ]\n\nparseFlagTests =\n  testGroup \"acton compiler flags\"\n  [\n    flagGolden \"parse flag prints AST\" \"test/parse/simple.golden\" [\"--quiet\", \"--parse\"]\n  , flagGolden \"kinds flag prints kinds\" \"test/parse/simple.kinds.golden\" [\"--quiet\", \"--kinds\"]\n  , flagGolden \"types flag prints types\" \"test/parse/simple.types.golden\" [\"--quiet\", \"--types\"]\n  , flagGolden \"sigs flag prints signatures\" \"test/parse/simple.sigs.golden\" [\"--quiet\", \"--sigs\"]\n  , flagGolden \"norm flag prints normalized\" \"test/parse/simple.norm.golden\" [\"--quiet\", \"--norm\"]\n  , flagGolden \"deact flag prints deactorized\" \"test/parse/simple.deact.golden\" [\"--quiet\", \"--deact\"]\n  , flagGolden \"cps flag prints CPS\" \"test/parse/simple.cps.golden\" [\"--quiet\", \"--cps\"]\n  , flagGolden \"llift flag prints lifted\" \"test/parse/simple.llift.golden\" [\"--quiet\", \"--llift\"]\n  , flagGolden \"box flag prints boxing\" \"test/parse/simple.box.golden\" [\"--quiet\", \"--box\"]\n  -- Avoid #line directives (absolute paths) so hgen/cgen goldens stay stable across machines\n  , flagGolden \"hgen flag prints header\" \"test/parse/simple.hgen.golden\" [\"--quiet\", \"--dbg-no-lines\", \"--hgen\"]\n  , flagGolden \"cgen flag prints c\" \"test/parse/simple.cgen.golden\" [\"--quiet\", \"--dbg-no-lines\", \"--cgen\"]\n  , flagGolden \"all flags combined\" \"test/parse/simple.all.golden\"\n        [\"--quiet\", \"--parse\", \"--kinds\", \"--types\", \"--sigs\", \"--norm\", \"--deact\", \"--cps\", \"--llift\", \"--box\", \"--dbg-no-lines\", \"--hgen\"]\n  , testCase \"optimize parser accepts release aliases\" $ do\n      assertParsedBuildOptimize [\"build\", \"--release\"] C.ReleaseFast\n      assertParsedBuildOptimize [\"build\", \"--release=safe\"] C.ReleaseSafe\n      assertParsedBuildOptimize [\"build\", \"--release=SmAlL\"] C.ReleaseSmall\n      assertParsedBuildOptimize [\"build\", \"--release=FAST\"] C.ReleaseFast\n      assertParsedBuildOptimize [\"build\", \"--optimize=release\"] C.ReleaseFast\n      assertParsedBuildOptimize [\"build\", \"--optimize=ReLeAsE\"] C.ReleaseFast\n      assertParsedBuildOptimize [\"build\", \"--optimize=dEbUg\"] C.Debug\n      assertParsedBuildOptimize [\"build\", \"--optimize=reLeAsEsMaLl\"] C.ReleaseSmall\n      assertParsedBuildOptimize [\"build\", \"--optimize=RELEASEFAST\"] C.ReleaseFast\n  , testCase \"explicit --optimize overrides --release alias\" $ do\n      assertParsedBuildOptimize [\"build\", \"--release\", \"--optimize=releasesmall\"] C.ReleaseSmall\n      assertParsedBuildOptimize [\"build\", \"--release=fast\", \"--optimize=debug\"] C.Debug\n      assertParsedBuildOptimize [\"build\", \"--optimize=debug\", \"--release\"] C.Debug\n  , testCase \"build parser accepts --parse-serial\" $ do\n      parsed <- parseArgs [\"build\", \"--parse-serial\"]\n      case parsed of\n        C.CmdOpt _ (C.Build buildOpts) ->\n          assertBool \"serial parser flag should be set\" (C.parse_serial (C.buildCompile buildOpts))\n        _ ->\n          assertFailure \"expected build command\"\n  , testCase \"build parser help includes --release alias\" $ do\n      helpText <- renderParserHelp [\"build\", \"--help\"]\n      assertBool \"help text should include --release\" (\"--release\" `isInfixOf` helpText)\n      assertBool \"help text should mention release variants\" (\"=safe or =small\" `isInfixOf` helpText)\n      assertBool \"help text should mention default release mode\" (\"same as --release=fast\" `isInfixOf` helpText)\n  , testCase \"sig parser accepts target and project options\" $ do\n      parsed <- parseArgs [\"sig\", \"--always-build\", \"--dep\", \"dep=../dep\", \"--searchpath\", \"out/types\", \"foo.bar\"]\n      case parsed of\n        C.CmdOpt _ (C.Sig sigOpts) -> do\n          let opts = C.sigCompile sigOpts\n          assertEqual \"sig target\" \"foo.bar\" (C.sigTarget sigOpts)\n          assertBool \"sig should force rebuild when requested\" (C.alwaysbuild opts)\n          assertEqual \"sig searchpath\" [\"out/types\"] (C.searchpath opts)\n          assertEqual \"sig dep overrides\" [(\"dep\", \"../dep\")] (C.dep_overrides opts)\n          assertBool \"sig should skip final build\" (C.skip_build opts)\n        _ ->\n          assertFailure \"expected sig command\"\n  , testCase \"install parser accepts package options\" $ do\n      parsed <- parseArgs [\"install\", \"ncurl\", \"--repo-url\", \"https://github.com/stratoweave/ncurl\", \"--repo-ref\", \"main\", \"--pkg-name\", \"ncurl-index\", \"--github-token\", \"tok\"]\n      case parsed of\n        C.CmdOpt _ (C.Install installOpts) -> do\n          assertEqual \"install name\" \"ncurl\" (C.installName installOpts)\n          assertEqual \"repo url\" \"https://github.com/stratoweave/ncurl\" (C.installRepoUrl installOpts)\n          assertEqual \"repo ref\" \"main\" (C.installRepoRef installOpts)\n          assertEqual \"pkg name\" \"ncurl-index\" (C.installPkgName installOpts)\n          assertEqual \"github token\" \"tok\" (C.installGithubToken installOpts)\n        _ ->\n          assertFailure \"expected install command\"\n  , testCase \"uninstall parser accepts app name\" $ do\n      parsed <- parseArgs [\"uninstall\", \"ncurl\"]\n      case parsed of\n        C.CmdOpt _ (C.Uninstall uninstallOpts) ->\n          assertEqual \"uninstall name\" \"ncurl\" (C.uninstallName uninstallOpts)\n        _ ->\n          assertFailure \"expected uninstall command\"\n  , testCase \"sig finds prebuilt dependency interfaces\" $ do\n      withSystemTempDirectory \"acton-sig-prebuilt-dep\" $ \\tmp -> do\n        actonBinDir <- Paths_acton.getBinDir\n        let actonCandidate = actonBinDir </> \"acton\"\n            distActon = \"../../dist/bin/acton\"\n        hasActonCandidate <- doesFileExist actonCandidate\n        actonExe <- canonicalizePath $\n          if hasActonCandidate then actonCandidate else distActon\n        sysPath <- canonicalizePath \"../../dist\"\n        env0 <- getEnvironment\n        let homeDir = tmp </> \"home\"\n            rootProj = tmp </> \"root\"\n            depProj = tmp </> \"dep\"\n            envWithHome = (\"HOME\", homeDir) : filter ((/= \"HOME\") . fst) env0\n            mkFp name = Fingerprint.formatFingerprint\n              (Fingerprint.updateFingerprintPrefix\n                (Fingerprint.fingerprintPrefixForName name) 1)\n            writeBuildActAt :: FilePath -> String -> [(String, FilePath)] -> IO ()\n            writeBuildActAt dir name deps = do\n              createDirectoryIfMissing True (dir </> \"src\")\n              let depsBody = intercalate \",\\n\"\n                    [ \"    \\\"\" ++ depName ++ \"\\\": (\\n\"\n                      ++ \"        path=\" ++ show depPath ++ \"\\n\"\n                      ++ \"    )\"\n                    | (depName, depPath) <- deps\n                    ]\n                  depsSection =\n                    if null deps\n                      then \"dependencies = {}\"\n                      else \"dependencies = {\\n\" ++ depsBody ++ \"\\n}\"\n              writeFile (dir </> \"Build.act\") $ unlines\n                [ \"name = \" ++ show name\n                , \"fingerprint = \" ++ mkFp name\n                , \"\"\n                , depsSection\n                , \"\"\n                , \"zig_dependencies = {}\"\n                ]\n        createDirectoryIfMissing True homeDir\n\n        writeBuildActAt depProj \"sig_dep\" []\n        writeFile (depProj </> \"src\" </> \"prebuilt.act\") $ unlines\n          [ \"def count() -> int:\"\n          , \"    return 1\"\n          ]\n        (buildCode, buildOut, buildErr) <- readCreateProcessWithExitCode\n          (proc actonExe [\"build\", \"--syspath\", sysPath, \"--skip-build\", \"src/prebuilt.act\"])\n            { cwd = Just depProj, env = Just envWithHome } \"\"\n        when (buildCode /= ExitSuccess) $\n          assertFailure (\"dependency build failed:\\nstdout:\\n\" ++ buildOut ++ \"\\nstderr:\\n\" ++ buildErr)\n\n        removeFile (depProj </> \"src\" </> \"prebuilt.act\")\n        writeBuildActAt rootProj \"sig_root\" [(\"sig_dep\", depProj)]\n        writeFile (rootProj </> \"src\" </> \"main.act\") $ unlines\n          [ \"actor main(env):\"\n          , \"    env.exit(0)\"\n          ]\n\n        (sigCode, sigOut, sigErr) <- readCreateProcessWithExitCode\n          (proc actonExe [\"sig\", \"--syspath\", sysPath, \"prebuilt\"])\n            { cwd = Just rootProj, env = Just envWithHome } \"\"\n        when (sigCode /= ExitSuccess) $\n          assertFailure (\"acton sig failed:\\nstdout:\\n\" ++ sigOut ++ \"\\nstderr:\\n\" ++ sigErr)\n        assertBool \"sig output should include the dependency function\"\n          (\"count : () -> int\" `isInfixOf` sigOut)\n  , testCase \"sig prints private names without importing them\" $ do\n      withSystemTempDirectory \"acton-sig-private-names\" $ \\tmp -> do\n        actonExe <- canonicalizePath \"../../dist/bin/acton\"\n        sysPath <- canonicalizePath \"../../dist\"\n        env0 <- getEnvironment\n        let homeDir = tmp </> \"home\"\n            proj = tmp </> \"proj\"\n            srcDir = proj </> \"src\"\n            rootProj = tmp </> \"root\"\n            rootSrcDir = rootProj </> \"src\"\n            envWithHome = (\"HOME\", homeDir) : filter ((/= \"HOME\") . fst) env0\n            mkFp name = Fingerprint.formatFingerprint\n              (Fingerprint.updateFingerprintPrefix\n                (Fingerprint.fingerprintPrefixForName name) 1)\n            writeBuildActAt :: FilePath -> String -> [(String, FilePath)] -> IO ()\n            writeBuildActAt dir pkgName deps = do\n              createDirectoryIfMissing True (dir </> \"src\")\n              let depsBody = intercalate \",\\n\"\n                    [ \"    \\\"\" ++ depName ++ \"\\\": (\\n\"\n                      ++ \"        path=\" ++ show depPath ++ \"\\n\"\n                      ++ \"    )\"\n                    | (depName, depPath) <- deps\n                    ]\n                  depsSection =\n                    if null deps\n                      then \"dependencies = {}\"\n                      else \"dependencies = {\\n\" ++ depsBody ++ \"\\n}\"\n              writeFile (dir </> \"Build.act\") $ unlines\n                [ \"name = \" ++ show pkgName\n                , \"fingerprint = \" ++ mkFp pkgName\n                , depsSection\n                , \"zig_dependencies = {}\"\n                ]\n        createDirectoryIfMissing True homeDir\n        writeBuildActAt proj \"sig_private\" []\n        writeFile (srcDir </> \"lib.act\") $ unlines\n          [ \"def _private() -> int:\"\n          , \"    return 1\"\n          , \"\"\n          , \"def public() -> int:\"\n          , \"    return _private()\"\n          ]\n        (buildCode, buildOut, buildErr) <- readCreateProcessWithExitCode\n          (proc actonExe [\"build\", \"--syspath\", sysPath, \"--skip-build\", \"src/lib.act\"])\n            { cwd = Just proj, env = Just envWithHome } \"\"\n        when (buildCode /= ExitSuccess) $\n          assertFailure (\"library build failed:\\nstdout:\\n\" ++ buildOut ++ \"\\nstderr:\\n\" ++ buildErr)\n\n        (sigCode, sigOut, sigErr) <- readCreateProcessWithExitCode\n          (proc actonExe [\"sig\", \"--syspath\", sysPath, \"lib\"])\n            { cwd = Just proj, env = Just envWithHome } \"\"\n        when (sigCode /= ExitSuccess) $\n          assertFailure (\"acton sig failed:\\nstdout:\\n\" ++ sigOut ++ \"\\nstderr:\\n\" ++ sigErr)\n        assertBool \"sig output should include private function\"\n          (\"_private : () -> int\" `isInfixOf` sigOut)\n        assertBool \"sig output should include public function\"\n          (\"public : () -> int\" `isInfixOf` sigOut)\n\n        writeFile (srcDir </> \"main.act\") $ unlines\n          [ \"from lib import _private\"\n          , \"\"\n          , \"actor main(env):\"\n          , \"    env.exit(0)\"\n          ]\n        (importCode, _importOut, importErr) <- readCreateProcessWithExitCode\n          (proc actonExe [\"build\", \"--syspath\", sysPath, \"--skip-build\", \"src/main.act\"])\n            { cwd = Just proj, env = Just envWithHome } \"\"\n        assertBool (\"private import should fail, stderr:\\n\" ++ importErr)\n          (importCode /= ExitSuccess)\n\n        removeFile (srcDir </> \"lib.act\")\n        (cachedSigCode, cachedSigOut, cachedSigErr) <- readCreateProcessWithExitCode\n          (proc actonExe [\"sig\", \"--syspath\", sysPath, \"lib._private\"])\n            { cwd = Just proj, env = Just envWithHome } \"\"\n        when (cachedSigCode /= ExitSuccess) $\n          assertFailure (\"cached acton sig failed:\\nstdout:\\n\" ++ cachedSigOut ++ \"\\nstderr:\\n\" ++ cachedSigErr)\n        assertBool \"cached sig output should include private function\"\n          (\"_private : () -> int\" `isInfixOf` cachedSigOut)\n\n        writeBuildActAt rootProj \"sig_private_root\" [(\"sig_private\", proj)]\n        writeFile (rootSrcDir </> \"main.act\") $ unlines\n          [ \"from lib import _private\"\n          , \"\"\n          , \"actor main(env):\"\n          , \"    env.exit(0)\"\n          ]\n        (cachedImportCode, _cachedImportOut, cachedImportErr) <- readCreateProcessWithExitCode\n          (proc actonExe [\"build\", \"--syspath\", sysPath, \"--skip-build\", \"src/main.act\"])\n            { cwd = Just rootProj, env = Just envWithHome } \"\"\n        assertBool (\"cached private import should fail, stderr:\\n\" ++ cachedImportErr)\n          (cachedImportCode /= ExitSuccess)\n  , testCase \"acton test --help includes --no-cache and --tag\" $ do\n      acton <- canonicalizePath \"../../dist/bin/acton\"\n      (returnCode, cmdOut, cmdErr) <- readCreateProcessWithExitCode (proc acton [\"test\", \"--help\"]) \"\"\n      assertEqual \"acton test --help should succeed\" ExitSuccess returnCode\n      assertEqual \"acton test --help stderr\" \"\" cmdErr\n      assertBool \"acton test --help should include --no-cache\" (\"--no-cache\" `isInfixOf` cmdOut)\n      assertBool \"acton test --help should include --tag\" (\"--tag\" `isInfixOf` cmdOut)\n  , testCase \"acton test reruns cached snapshot when expected file changes\" $ do\n      withSystemTempDirectory \"acton-test-snapshot-cache\" $ \\proj -> do\n        actonBinDir <- Paths_acton.getBinDir\n        let distActon = \"../../dist/bin/acton\"\n            actonCandidate = actonBinDir </> \"acton\"\n        hasDistActon <- doesFileExist distActon\n        acton <- canonicalizePath $\n          if hasDistActon\n            then distActon\n            else actonCandidate\n        let name = \"snapshot_cache\"\n            fp = Fingerprint.formatFingerprint\n              (Fingerprint.updateFingerprintPrefix\n                (Fingerprint.fingerprintPrefixForName name) 1)\n            srcDir = proj </> \"src\"\n            modName = \"snap\"\n            srcFile = srcDir </> modName <.> \"act\"\n            expectedDir = proj </> \"snapshots\" </> \"expected\" </> modName\n            expectedFile = expectedDir </> \"stable\"\n            runTest args = readCreateProcessWithExitCode (proc acton (\"test\" : args)) { cwd = Just proj } \"\"\n\n        createDirectoryIfMissing True srcDir\n        createDirectoryIfMissing True expectedDir\n        writeFile (proj </> \"Build.act\") $ unlines\n          [ \"name = \\\"\" ++ name ++ \"\\\"\"\n          , \"fingerprint = \" ++ fp\n          , \"\"\n          ]\n        writeFile srcFile $ unlines\n          [ \"import testing\"\n          , \"\"\n          , \"def _test_stable() -> str:\"\n          , \"    return \\\"snapshot v1\\\"\"\n          ]\n        writeFile expectedFile \"snapshot v1\"\n\n        (code1, out1, err1) <- runTest [\"--iter\", \"1\"]\n        when (code1 /= ExitSuccess) $\n          assertFailure (\"initial acton test failed:\\nstdout:\\n\" ++ out1 ++ \"\\nstderr:\\n\" ++ err1)\n\n        (code2, out2, err2) <- runTest [\"--iter\", \"1\", \"--show-cached\"]\n        when (code2 /= ExitSuccess) $\n          assertFailure (\"cached acton test failed:\\nstdout:\\n\" ++ out2 ++ \"\\nstderr:\\n\" ++ err2)\n        assertBool \"second run should reuse cached snapshot result\"\n          (\"Using cached results for 1 tests\" `isInfixOf` out2)\n        assertBool \"cached run should mark the result as cached\"\n          (\"* = cached test result\" `isInfixOf` out2)\n\n        writeFile expectedFile \"snapshot v2\"\n\n        (code3, out3, err3) <- runTest [\"--iter\", \"1\", \"--show-cached\"]\n        assertEqual \"changed expected snapshot should invalidate cached success\" (ExitFailure 1) code3\n        assertBool \"rerun should report snapshot mismatch\"\n          (\"Test output does not match expected snapshot value\" `isInfixOf` out3\n            || \"Test output does not match expected snapshot value\" `isInfixOf` err3)\n        assertBool \"stale cached snapshot result should not be reused after expected change\"\n          (not (\"Using cached results for 1 tests\" `isInfixOf` out3))\n  ]\n  where\n    parserInfo = OA.info (C.cmdLineParser OA.<**> OA.helper) C.descr\n\n    parseArgs args =\n      case OA.execParserPure OA.defaultPrefs parserInfo args of\n        OA.Success result -> return result\n        OA.Failure failure -> do\n          let (msg, _) = OA.renderFailure failure \"acton\"\n          assertFailure (\"parser failed for \" ++ unwords args ++ \":\\n\" ++ msg)\n        OA.CompletionInvoked _ ->\n          assertFailure (\"parser requested shell completion for \" ++ unwords args)\n\n    assertParsedBuildOptimize args expected = do\n      parsed <- parseArgs args\n      case parsed of\n        C.CmdOpt _ (C.Build buildOpts) ->\n          assertEqual (\"unexpected optimize mode for \" ++ unwords args)\n            expected\n            (C.optimize (C.buildCompile buildOpts))\n        _ ->\n          assertFailure (\"expected build command for \" ++ unwords args)\n\n    renderParserHelp args =\n      case OA.execParserPure OA.defaultPrefs parserInfo args of\n        OA.Failure failure -> pure (fst (OA.renderFailure failure \"acton\"))\n        OA.Success _ -> assertFailure (\"expected parser help for \" ++ unwords args)\n        OA.CompletionInvoked _ ->\n          assertFailure (\"parser requested shell completion for \" ++ unwords args)\n\n    flagGolden label golden flags =\n      goldenVsString label golden $ do\n        acton <- canonicalizePath \"../../dist/bin/acton\"\n        sample <- canonicalizePath \"test/parse/simple.act\"\n        (returnCode, cmdOut, cmdErr) <- readCreateProcessWithExitCode (proc acton (flags ++ [sample])) \"\"\n        assertEqual (\"acton \" ++ unwords flags ++ \" should succeed\") ExitSuccess returnCode\n        assertEqual (\"acton \" ++ unwords flags ++ \" stderr\") \"\" cmdErr\n        return (LBS.pack cmdOut)\n\nactonProjTests =\n  testGroup \"compiler project tests\"\n  [ testCase \"simple project\" $ do\n        testBuild \"\" ExitSuccess False \"test/project/simple\"\n        testBuild \"\" ExitSuccess False \"test/project/simple\"\n\n  , testCase \"with missing src/ dir\" $ do\n        testBuild \"\" (ExitFailure 1) False \"test/project/missing_src\"\n\n  , testCase \"qualified --root test.main\" $ do\n        testBuild \"--root test.main\" ExitSuccess False \"test/project/qualified_root\"\n\n  -- after used to avoid races on files in same project dir as above test\n  , after AllFinish \"qualified_root\" $\n    testCase \"unqualified --root main\" $ do\n        (returnCode, cmdOut, cmdErr) <- buildThing \"--root main\" \"test/project/qualified_root\"\n        assertEqual \"acton should error out\" (ExitFailure 1) returnCode\n        assertEqual \"acton should report error\" \"acton: Project build requires a qualified root actor name, like foo.main\\n\" cmdErr\n\n  , testCase \"project with nested path deps\" $ do\n        let proj = \"../../test/compiler/acton_proj_deps\"\n            depA = proj </> \"deps/dep_a\"\n            depB = proj </> \"deps/dep_b\"\n            wipe p = void $ readCreateProcessWithExitCode (shell $ \"rm -rf \" ++ p ++ \"/build.zig \" ++ p ++ \"/build.zig.zon \" ++ p ++ \"/out\") \"\"\n        mapM_ wipe [proj, depA, depB]\n        -- Build main project via acton; dependencies should be built automatically\n        testBuild \"\" ExitSuccess False proj\n        -- Run produced binary\n        (cRun, _outRun, _errRun) <- readCreateProcessWithExitCode (shell \"./out/bin/main\"){ cwd = Just proj } \"\"\n        assertEqual \"project binary should run\" ExitSuccess cRun\n        zon <- readFile (proj </> \"build.zig.zon\")\n        assertBool \"build.zig.zon should declare dep_a\" (\".dep_a\" `isInfixOf` zon)\n        assertBool \"build.zig.zon should declare dep_b\" (\".dep_b\" `isInfixOf` zon)\n  , testCase \"builds dependencies even if unused in imports\" $ do\n        let proj = \"../../test/compiler/unused_dep\"\n            depU = proj </> \"deps/dep_unused\"\n            wipe p = void $ readCreateProcessWithExitCode (shell $ \"rm -rf \" ++ p ++ \"/build.zig \" ++ p ++ \"/build.zig.zon \" ++ p ++ \"/out\") \"\"\n        mapM_ wipe [proj, depU]\n        testBuild \"\" ExitSuccess False proj\n        let depObj = depU </> \"out/types/acton_empty.c\"\n        exists <- doesFileExist depObj\n        assertBool \"dependency output should be generated even if unused (dummy allowed)\" exists\n  , testCase \"dep overrides propagate to build.zig.zon\" $ do\n        let proj = \"../../test/compiler/dep_override\"\n            depA = proj </> \"deps/dep_a\"\n            depB = proj </> \"deps/dep_b\"\n            depC = proj </> \"deps/dep_c\"\n            wipe p = void $ readCreateProcessWithExitCode (shell $ \"rm -rf \" ++ p ++ \"/build.zig \" ++ p ++ \"/build.zig.zon \" ++ p ++ \"/out\") \"\"\n            expect needle hay msg = assertBool msg (needle `isInfixOf` hay)\n            expectAny needles hay msg = assertBool msg (any (`isInfixOf` hay) needles)\n        mapM_ wipe [proj, depA, depB, depC]\n        runActon \"build --dep dep_a=deps/dep_a --dep dep_b=deps/dep_b --dep ghost=deps/ghost\" ExitSuccess False proj\n        rootZon <- readFile (proj </> \"build.zig.zon\")\n        depAZon <- readFile (depA </> \"build.zig.zon\")\n        expect \".dep_a = .{\" rootZon \"root build.zig.zon should declare dep_a\"\n        expectAny [\"dep_override/deps/dep_a\", \"dep_override\\\\deps\\\\dep_a\"] rootZon \"root build.zig.zon should use dep_a override path\"\n        expect \".dep_b = .{\" rootZon \"root build.zig.zon should declare dep_b\"\n        expectAny [\"dep_override/deps/dep_b\", \"dep_override\\\\deps\\\\dep_b\"] rootZon \"root build.zig.zon should use dep_b override path transitively\"\n        assertBool \"root build.zig.zon should not use cached dep_b hash path\" (not (\"dep_b-\" `isInfixOf` rootZon))\n        expect \".dep_c = .{\" rootZon \"root build.zig.zon should declare dep_c (non-overridden) transitively\"\n        expectAny [\"dep_override/deps/dep_c\", \"dep_override\\\\deps\\\\dep_c\"] rootZon \"root build.zig.zon should keep dep_c path\"\n        assertBool \"root build.zig.zon should not include undeclared ghost override\" (not (\"ghost\" `isInfixOf` rootZon))\n        expect \".dep_b = .{\" depAZon \"dep_a build.zig.zon should declare dep_b\"\n        expectAny [\"dep_override/deps/dep_b\", \"dep_override\\\\deps\\\\dep_b\", \"../dep_b\", \"..\\\\dep_b\"] depAZon \"dep_a build.zig.zon should use dep_b override path\"\n        assertBool \"dep_a build.zig.zon should not use cached dep_b hash path\" (not (\"dep_b-\" `isInfixOf` depAZon))\n        expect \".dep_c = .{\" depAZon \"dep_a build.zig.zon should declare dep_c\"\n        expectAny [\"dep_override/deps/dep_c\", \"dep_override\\\\deps\\\\dep_c\", \"../dep_c\", \"..\\\\dep_c\"] depAZon \"dep_a build.zig.zon should keep dep_c path\"\n        assertBool \"dep_a build.zig.zon should not include undeclared ghost override\" (not (\"ghost\" `isInfixOf` depAZon))\n  , testCase \"zig deps do not collide with package deps in build.zig.zon\" $ do\n        withSystemTempDirectory \"acton-zig-dep-name-collision\" $ \\tmp -> do\n          actonExe <- canonicalizePath \"../../dist/bin/acton\"\n          let rootProj = tmp </> \"root\"\n              wrapperProj = rootProj </> \"deps\" </> \"acton_lmdb\"\n              zigProj = rootProj </> \"deps\" </> \"lmdb_zig\"\n              mkFp name = Fingerprint.formatFingerprint\n                (Fingerprint.updateFingerprintPrefix\n                  (Fingerprint.fingerprintPrefixForName name) 1)\n          createDirectoryIfMissing True (rootProj </> \"src\")\n          createDirectoryIfMissing True (wrapperProj </> \"src\")\n          createDirectoryIfMissing True (zigProj </> \"src\")\n          writeFile (rootProj </> \"Build.act\") $ unlines\n            [ \"name = \\\"root_proj\\\"\"\n            , \"fingerprint = \" ++ mkFp \"root_proj\"\n            , \"dependencies = {\"\n            , \"    \\\"lmdb\\\": (path=\\\"deps/acton_lmdb\\\")\"\n            , \"}\"\n            , \"zig_dependencies = {}\"\n            ]\n          writeFile (rootProj </> \"src\" </> \"main.act\") $ unlines\n            [ \"from lmdb import ready\"\n            , \"\"\n            , \"actor main(env):\"\n            , \"    if ready():\"\n            , \"        env.exit(0)\"\n            , \"    else:\"\n            , \"        env.exit(1)\"\n            ]\n          writeFile (wrapperProj </> \"Build.act\") $ unlines\n            [ \"name = \\\"acton_lmdb\\\"\"\n            , \"fingerprint = \" ++ mkFp \"acton_lmdb\"\n            , \"dependencies = {}\"\n            , \"zig_dependencies = {\"\n            , \"    \\\"lmdb\\\": (path=\\\"../lmdb_zig\\\", artifacts=[\\\"lmdb\\\"])\"\n            , \"}\"\n            ]\n          writeFile (wrapperProj </> \"src\" </> \"lmdb.act\") $ unlines\n            [ \"def ready() -> bool:\"\n            , \"    return True\"\n            ]\n          writeFile (zigProj </> \"build.zig\") $ unlines\n            [ \"const std = @import(\\\"std\\\");\"\n            , \"\"\n            , \"pub fn build(b: *std.Build) void {\"\n            , \"    const target = b.standardTargetOptions(.{});\"\n            , \"    const optimize = b.standardOptimizeOption(.{});\"\n            , \"    const lib = b.addLibrary(.{\"\n            , \"        .name = \\\"lmdb\\\",\"\n            , \"        .linkage = .static,\"\n            , \"        .root_module = b.createModule(.{\"\n            , \"            .root_source_file = b.path(\\\"src/root.zig\\\"),\"\n            , \"            .target = target,\"\n            , \"            .optimize = optimize,\"\n            , \"        }),\"\n            , \"    });\"\n            , \"    b.installArtifact(lib);\"\n            , \"}\"\n            ]\n          writeFile (zigProj </> \"build.zig.zon\") $ unlines\n            [ \".{\"\n            , \"    .name = .lmdb_zig,\"\n            , \"    .version = \\\"0.0.0\\\",\"\n            , \"    .fingerprint = 0xd571f8beb86c413e,\"\n            , \"    .minimum_zig_version = \\\"0.15.2\\\",\"\n            , \"    .dependencies = .{},\"\n            , \"    .paths = .{\\\"\\\"},\"\n            , \"}\"\n            ]\n          writeFile (zigProj </> \"src\" </> \"root.zig\") $ unlines\n            [ \"pub export fn lmdb_test() void {}\"\n            ]\n          (returnCode, _cmdOut, cmdErr) <- readCreateProcessWithExitCode (proc actonExe [\"build\"]){ cwd = Just rootProj } \"\"\n          assertEqual \"acton should build when package and zig deps share a name\" ExitSuccess returnCode\n          assertBool \"acton should not report the old dependency option collision\" (not (\"invalid option: -Dacton_modules\" `isInfixOf` cmdErr))\n          rootZon <- readFile (rootProj </> \"build.zig.zon\")\n          rootBuildZig <- readFile (rootProj </> \"build.zig\")\n          assertBool \"root build.zig.zon should keep the package dep key\" (\"        .lmdb = .{\" `isInfixOf` rootZon)\n          assertBool \"root build.zig.zon should namespace the zig dep key\" (\"        .acton_zig_lmdb = .{\" `isInfixOf` rootZon)\n          assertEqual \"root build.zig.zon should emit the package dep key only once\"\n            1\n            (length (filter (== \"        .lmdb = .{\") (lines rootZon)))\n          assertBool \"root build.zig should keep the package dep lookup\"\n            (\"const actdep_lmdb = b.dependency(\\\"lmdb\\\"\" `isInfixOf` rootBuildZig)\n          assertBool \"root build.zig should namespace the zig dep lookup\"\n            (\"const dep_lmdb = b.dependency(\\\"acton_zig_lmdb\\\"\" `isInfixOf` rootBuildZig)\n  , testCase \"transitive zig deps deduplicate by identity and split on collision\" $ do\n        withSystemTempDirectory \"acton-zig-transitive-dedup\" $ \\tmp -> do\n          actonExe <- canonicalizePath \"../../dist/bin/acton\"\n          let rootProj = tmp </> \"root\"\n              depAProj = rootProj </> \"deps\" </> \"dep_a\"\n              depBProj = rootProj </> \"deps\" </> \"dep_b\"\n              depCProj = rootProj </> \"deps\" </> \"dep_c\"\n              zigCommonProj = rootProj </> \"deps\" </> \"zig_common\"\n              zigOtherProj = rootProj </> \"deps\" </> \"zig_other\"\n              mkFp name = Fingerprint.formatFingerprint\n                (Fingerprint.updateFingerprintPrefix\n                  (Fingerprint.fingerprintPrefixForName name) 1)\n              writeWrapper proj name zigPath moduleName = do\n                createDirectoryIfMissing True (proj </> \"src\")\n                writeFile (proj </> \"Build.act\") $ unlines\n                  [ \"name = \" ++ show name\n                  , \"fingerprint = \" ++ mkFp name\n                  , \"dependencies = {}\"\n                  , \"zig_dependencies = {\"\n                  , \"    \\\"shared\\\": (path=\" ++ show zigPath ++ \", artifacts=[\\\"shared\\\"])\"\n                  , \"}\"\n                  ]\n                writeFile (proj </> \"src\" </> (moduleName ++ \".act\")) $ unlines\n                  [ \"def ready() -> bool:\"\n                  , \"    return True\"\n                  ]\n              writeZigPkg proj = do\n                createDirectoryIfMissing True (proj </> \"src\")\n                writeFile (proj </> \"build.zig\") $ unlines\n                  [ \"const std = @import(\\\"std\\\");\"\n                  , \"\"\n                  , \"pub fn build(b: *std.Build) void {\"\n                  , \"    const target = b.standardTargetOptions(.{});\"\n                  , \"    const optimize = b.standardOptimizeOption(.{});\"\n                  , \"    const lib = b.addLibrary(.{\"\n                  , \"        .name = \\\"shared\\\",\"\n                  , \"        .linkage = .static,\"\n                  , \"        .root_module = b.createModule(.{\"\n                  , \"            .root_source_file = b.path(\\\"src/root.zig\\\"),\"\n                  , \"            .target = target,\"\n                  , \"            .optimize = optimize,\"\n                  , \"        }),\"\n                  , \"    });\"\n                  , \"    b.installArtifact(lib);\"\n                  , \"}\"\n                  ]\n                writeFile (proj </> \"build.zig.zon\") $ unlines\n                  [ \".{\"\n                  , \"    .name = .lmdb_zig,\"\n                  , \"    .version = \\\"0.0.0\\\",\"\n                  , \"    .fingerprint = 0xd571f8beb86c413e,\"\n                  , \"    .minimum_zig_version = \\\"0.15.2\\\",\"\n                  , \"    .dependencies = .{},\"\n                  , \"    .paths = .{\\\"\\\"},\"\n                  , \"}\"\n                  ]\n                writeFile (proj </> \"src\" </> \"root.zig\") $ unlines\n                  [ \"pub export fn shared_test() void {}\"\n                  ]\n          createDirectoryIfMissing True (rootProj </> \"src\")\n          writeFile (rootProj </> \"Build.act\") $ unlines\n            [ \"name = \\\"root_proj\\\"\"\n            , \"fingerprint = \" ++ mkFp \"root_proj\"\n            , \"dependencies = {\"\n            , \"    \\\"dep_a\\\": (path=\\\"deps/dep_a\\\"),\"\n            , \"    \\\"dep_b\\\": (path=\\\"deps/dep_b\\\"),\"\n            , \"    \\\"dep_c\\\": (path=\\\"deps/dep_c\\\")\"\n            , \"}\"\n            , \"zig_dependencies = {}\"\n            ]\n          writeFile (rootProj </> \"src\" </> \"main.act\") $ unlines\n            [ \"import dep_a\"\n            , \"import dep_b\"\n            , \"import dep_c\"\n            , \"\"\n            , \"actor main(env):\"\n            , \"    if dep_a.ready() and dep_b.ready() and dep_c.ready():\"\n            , \"        env.exit(0)\"\n            , \"    else:\"\n            , \"        env.exit(1)\"\n            ]\n          writeWrapper depAProj \"dep_a\" \"../zig_common\" \"dep_a\"\n          writeWrapper depBProj \"dep_b\" \"../zig_common\" \"dep_b\"\n          writeWrapper depCProj \"dep_c\" \"../zig_other\" \"dep_c\"\n          writeZigPkg zigCommonProj\n          writeZigPkg zigOtherProj\n          (returnCode, _cmdOut, cmdErr) <- readCreateProcessWithExitCode (proc actonExe [\"build\"]){ cwd = Just rootProj } \"\"\n          assertEqual \"acton should build with colliding transitive zig dep names\" ExitSuccess returnCode\n          assertBool \"acton should not report the old dependency option collision\" (not (\"invalid option: -Dacton_modules\" `isInfixOf` cmdErr))\n          rootZon <- readFile (rootProj </> \"build.zig.zon\")\n          rootBuildZig <- readFile (rootProj </> \"build.zig\")\n          assertBool \"root build.zig.zon should include the first local zig dep name\"\n            (\"        .acton_zig_shared = .{\" `isInfixOf` rootZon)\n          assertBool \"root build.zig.zon should include the second colliding zig dep name\"\n            (\"        .acton_zig_shared_2 = .{\" `isInfixOf` rootZon)\n          assertBool \"root build.zig.zon should not emit a third deduped copy\"\n            (not (\"        .acton_zig_shared_3 = .{\" `isInfixOf` rootZon))\n          assertBool \"root build.zig should bind the deduped zig dep once\"\n            (\"const dep_shared = b.dependency(\\\"acton_zig_shared\\\"\" `isInfixOf` rootBuildZig)\n          assertBool \"root build.zig should bind the colliding zig dep separately\"\n            (\"const dep_shared_2 = b.dependency(\\\"acton_zig_shared_2\\\"\" `isInfixOf` rootBuildZig)\n  , testCase \"dep override path must be an Acton project root\" $ do\n        withSystemTempDirectory \"acton-invalid-dep-override\" $ \\proj -> do\n          let srcDir = proj </> \"src\"\n              buildAct = proj </> \"Build.act\"\n              mainAct = srcDir </> \"main.act\"\n          createDirectoryIfMissing True srcDir\n          createDirectoryIfMissing True (proj </> \"deps\")\n          writeFile buildAct $ unlines\n            [ \"name = \\\"invalid_dep_override\\\"\"\n            , \"fingerprint = 0xb33bef4512345678\"\n            , \"\"\n            , \"dependencies = {\"\n            , \"  \\\"dep_a\\\": (path=\\\"deps/dep_a_missing\\\")\"\n            , \"}\"\n            ]\n          writeFile mainAct $ unlines\n            [ \"actor main(env):\"\n            , \"    print(\\\"hello\\\")\"\n            , \"    env.exit(0)\"\n            ]\n          actonExe <- canonicalizePath \"../../dist/bin/acton\"\n          (returnCode, _cmdOut, cmdErr) <- readCreateProcessWithExitCode (proc actonExe [\"build\", \"--dep\", \"dep_a=deps\"]){ cwd = Just proj } \"\"\n          assertEqual \"acton should fail for invalid --dep path\" (ExitFailure 1) returnCode\n          assertBool \"error should mention bad dependency path\" (\"Dependency dep_a path is not an Acton project root\" `isInfixOf` cmdErr)\n          assertBool \"error should mention required project files\" (\"Build.act\" `isInfixOf` cmdErr)\n          assertBool \"error should mention src requirement\" (\"src/\" `isInfixOf` cmdErr)\n\n  -- Verify pruning keeps binaries for modules that still have roots across build / test runs.\n  , testCase \"executable pruning\" $ do\n        let proj = \"test/project/prune_executables\"\n        cleanOut proj\n        -- Build once, then run tests: binaries should stay and both build/test\n        -- root .c stubs should coexist.\n        testBuild \"\" ExitSuccess False proj\n        let binFoo = proj </> \"out/bin/foo\"\n            binBar = proj </> \"out/bin/bar\"\n            testRoot = proj </> \"out/types/tests/simple.test_root.c\"\n            buildRoot = proj </> \"out/types/foo.root.c\"\n        assertBool \"foo binary should exist after build\" =<< doesFileExist binFoo\n        assertBool \"bar binary should exist after build\" =<< doesFileExist binBar\n        runActon \"test\" ExitSuccess False proj\n        assertBool \"foo binary should exist after acton test\" =<< doesFileExist binFoo\n        assertBool \"bar binary should exist after acton test\" =<< doesFileExist binBar\n        assertBool \"build root.c should exist after acton test\" =<< doesFileExist buildRoot\n        assertBool \"test_root.c should exist after acton test\"  =<< doesFileExist testRoot\n\n  -- Partial single-file rebuild must not prune other modules' outputs.\n  , testCase \"partial build leaves unrelated outputs\" $ do\n        let proj = \"test/project/prune_partials\"\n            srcDir = proj </> \"src\"\n            fooAct = srcDir </> \"foo.act\"\n            barAct = srcDir </> \"bar.act\"\n            fooContent = \"actor main(env):\\n    print(\\\"foo\\\")\\n    env.exit(0)\\n\"\n            barContent = \"actor main(env):\\n    print(\\\"bar\\\")\\n    env.exit(0)\\n\"\n            barC    = proj </> \"out/types/bar.c\"\n            barH    = proj </> \"out/types/bar.h\"\n            barTy   = proj </> \"out/types/bar.ty\"\n        createDirectoryIfMissing True srcDir\n        writeFile fooAct fooContent\n        writeFile barAct barContent\n        cleanOut proj\n        -- Full build first to create bar artifacts.\n        testBuild \"\" ExitSuccess False proj\n        acton <- canonicalizePath \"../../dist/bin/acton\"\n        -- Single-file build of foo must not prune outputs from other moduels\n        -- since we don't have full visibility, so bar should remain\n        (returnCode, _, _) <- readCreateProcessWithExitCode (proc acton [\"--skip-build\", \"--always-build\", \"src/foo.act\"]){ cwd = Just proj } \"\"\n        assertEqual \"acton single-file build should succeed\" ExitSuccess returnCode\n        mapM_ (\\p -> doesFileExist p >>= assertBool (p ++ \" should exist\")) [barC, barH, barTy]\n\n  -- Full rebuild should prune roots / bins when the source module is removed.\n  , testCase \"full build prunes stale roots and bins\" $ do\n        let proj = \"test/project/prune_roots\"\n            barAct = proj </> \"src/bar.act\"\n            barContent = \"#\\n# removed in test to trigger pruning\\n\\nactor main(env):\\n    print(\\\"bar\\\")\\n    env.exit(0)\\n\"\n            barRoot = proj </> \"out/types/bar.root.c\"\n            barBin  = proj </> \"out/bin/bar\"\n        -- Start from a clean slate and write bar.act to ensure it exists\n        cleanOut proj\n        writeFile barAct barContent\n        -- Initial build should emit bar root & bin.\n        testBuild \"\" ExitSuccess False proj\n        assertBool \"bar root stub should exist after initial build\" =<< doesFileExist barRoot\n        assertBool \"bar binary should exist after initial build\" =<< doesFileExist barBin\n        -- Delete source; full build should prune root/bin.\n        removeFile barAct `catch` (\\(_ :: IOException) -> return ())\n        testBuild \"\" ExitSuccess False proj\n        assertBool \"bar root stub should be removed after source deletion\" . not =<< doesFileExist barRoot\n        assertBool \"bar binary should be removed after source deletion\" . not =<< doesFileExist barBin\n\n  ]\n\nactonRootArgTests =\n  testGroup \"compiler acton --root tests\"\n  [ testCase \"qualified --root test.main\" $\n        testBuild \"--root test.main\" ExitSuccess False \"test/root/test.act\"\n  , testCase \"unqualified --root main\" $\n        testBuild \"--root main\" ExitSuccess False \"test/root/test.act\"\n  , after AllFinish \"qualified --root\" $\n    after AllFinish \"unqualified --root\" $\n    testCase \"discover root actor\" $\n        testBuildAndRun \"\" \"\" ExitSuccess False \"test/root/test.act\"\n  ]\n\n\nrtsTests =\n  testGroup \"RTS\"\n  [\n      testCase \"arg parsing: foo --bar --rts-verbose\" $ do\n          testBuildAndRun \"\" \"foo --bar --rts-verbose\" ExitSuccess False \"../../test/rts/argv1.act\"\n\n  ,   testCase \"arg parsing: --rts-verbose --rts-wthreads 7 foo --bar\" $ do\n          testBuildAndRun \"\" \"--rts-verbose --rts-wthreads 7 foo --bar\" ExitSuccess False \"../../test/rts/argv2.act\"\n\n  ,   testCase \"arg parsing: --rts-verbose --rts-wthreads=7 foo --bar\" $ do\n          testBuildAndRun \"\" \"--rts-verbose --rts-wthreads=7 foo --bar\" ExitSuccess False \"../../test/rts/argv3.act\"\n\n  ,   testCase \"arg parsing: --rts-wthreads 7 count\" $ do\n          testBuildThing \"\" ExitSuccess False \"../../test/rts/argv4.act\"\n          (returnCode, cmdOut, cmdErr) <- runThing \"--rts-verbose --rts-wthreads 7 foo --bar\" \"../../test/rts/argv4.act\"\n          assertEqual \"RTS wthreads success retCode\" ExitSuccess returnCode\n          assertEqual \"RTS wthreads output\" True (isInfixOf \"Using 7 worker threads\" cmdErr)\n\n  ,   testCase \"arg parsing: --rts-wthreads 7 count\" $ do\n          testBuildThing \"\" ExitSuccess False \"../../test/rts/argv5.act\"\n          (returnCode, cmdOut, cmdErr) <- runThing \"--rts-verbose --rts-wthreads=7 foo --bar\" \"../../test/rts/argv5.act\"\n          assertEqual \"RTS wthreads success retCode\" ExitSuccess returnCode\n          assertEqual \"RTS wthreads output\" True (isInfixOf \"Using 7 worker threads\" cmdErr)\n\n  ,   testCase \"arg parsing: --rts-verbose --rts-wthreads=7 -- foo --bar --rts-verbose\" $ do\n          testBuildAndRun \"\" \"--rts-verbose --rts-wthreads=7 -- foo --bar --rts-verbose\" ExitSuccess False \"../../test/rts/argv6.act\"\n\n  ,   testCase \"arg parsing: --rts-wthreads\" $ do\n          testBuildThing \"\" ExitSuccess False \"../../test/rts/argv7.act\"\n          (returnCode, cmdOut, cmdErr) <- runThing \"--rts-wthreads\" \"../../test/rts/argv7.act\"\n          assertEqual \"RTS wthreads error retCode\" (ExitFailure 1) returnCode\n          assertEqual \"RTS wthreads error cmdErr\" \"ERROR: --rts-wthreads requires an argument.\\n\" cmdErr\n  ]\n\nstdlibTests =\n  testGroup \"stdlib\"\n  [\n      testCase \"time\" $ do\n          epoch <- getCurrentTime >>= pure . utcTimeToPOSIXSeconds >>= pure . round\n          testBuildAndRun \"\" (show epoch) ExitSuccess False \"../../test/stdlib/test_time.act\"\n  ]\n\ncrossCompileTests =\n  testGroup \"cross-compilation tests\"\n  [\n    testCase \"build hello --target aarch64-macos-none --db\" $ do\n        runActon \"build --target aarch64-macos-none --db\" ExitSuccess False \"../../test/compiler/hello/\"\n  , testCase \"build hello --target aarch64-windows-gnu\" $ do\n        runActon \"build --target aarch64-windows-gnu\" ExitSuccess False \"../../test/compiler/hello/\"\n  , testCase \"build hello --target x86_64-macos-none --db\" $ do\n        runActon \"build --target x86_64-macos-none --db\" ExitSuccess False \"../../test/compiler/hello/\"\n  , testCase \"build hello --target x86_64-linux-gnu.2.27 --db\" $ do\n        runActon \"build --target x86_64-linux-gnu.2.27 --db\" ExitSuccess False \"../../test/compiler/hello/\"\n  , testCase \"build hello --target x86_64-linux-musl --db\" $ do\n        runActon \"build --target x86_64-linux-musl --db\" ExitSuccess False \"../../test/compiler/hello/\"\n  , testCase \"build hello --target x86_64-windows-gnu\" $ do\n        runActon \"build --target x86_64-windows-gnu\" ExitSuccess False \"../../test/compiler/hello/\"\n  ]\n\npkgCliTests =\n  testGroup \"pkg CLI\"\n  [ testCase \"parse github repo url\" $ do\n        case PkgCommands.parseGithubRepoUrl \"https://github.com/actonlang/foo.git#main\" of\n          Left err -> assertFailure err\n          Right info -> do\n            assertEqual \"owner\" \"actonlang\" (PkgCommands.repoOwner info)\n            assertEqual \"repo\" \"foo\" (PkgCommands.repoName info)\n            assertEqual \"ref\" (Just \"main\") (PkgCommands.repoRef info)\n  , testCase \"github clone url strips ref fragment\" $ do\n        assertEqual \"clone url\"\n          \"https://github.com/actonlang/foo.git\"\n          (PkgCommands.githubCloneUrl \"https://github.com/actonlang/foo.git#main\")\n  , testCase \"github commit sha recognizer requires full sha\" $ do\n        assertBool \"full sha\"\n          (PkgCommands.isGithubCommitSha \"0123456789abcdef0123456789abcdef01234567\")\n        assertBool \"short sha is resolved through GitHub\"\n          (not (PkgCommands.isGithubCommitSha \"0123456\"))\n  , testCase \"pkg search matches prefix\" $ do\n        let pkg = PkgCommands.PackageEntry \"foo\" \"desc\" \"https://github.com/actonlang/foo\"\n        ok <- PkgCommands.matchesAllTerms [\"foo\"] pkg\n        assertBool \"prefix matches\" ok\n        ok2 <- PkgCommands.matchesAllTerms [\"bar\"] pkg\n        assertBool \"non-prefix does not match\" (not ok2)\n  , testCase \"decode package index returns only libraries\" $ do\n        let body = concat\n              [ \"{\\\"packages\\\":[\"\n              , \"{\\\"name\\\":\\\"foo\\\",\\\"kinds\\\":[\\\"library\\\",\\\"app\\\"],\\\"description\\\":\\\"desc\\\",\\\"repo_url\\\":\\\"https://github.com/actonlang/foo\\\"}\"\n              , \",{\\\"name\\\":\\\"bar\\\",\\\"kinds\\\":[\\\"app\\\"],\\\"description\\\":\\\"app\\\",\\\"repo_url\\\":\\\"https://github.com/actonlang/bar\\\"}\"\n              , \"]}\"\n              ]\n        case PkgCommands.decodePackageIndex (LBS.pack body) of\n          Left err -> assertFailure err\n          Right pkgs -> do\n            assertEqual \"one package\" 1 (length pkgs)\n            assertEqual \"name\" \"foo\" (PkgCommands.pkgName (head pkgs))\n  , testCase \"decode package index returns apps\" $ do\n        let body = concat\n              [ \"{\\\"packages\\\":[\"\n              , \"{\\\"name\\\":\\\"foo\\\",\\\"kinds\\\":[\\\"library\\\",\\\"app\\\"],\\\"description\\\":\\\"desc\\\",\\\"repo_url\\\":\\\"https://github.com/actonlang/foo\\\"}\"\n              , \",{\\\"name\\\":\\\"bar\\\",\\\"kinds\\\":[\\\"app\\\"],\\\"description\\\":\\\"app\\\",\\\"repo_url\\\":\\\"https://github.com/actonlang/bar\\\"}\"\n              , \",{\\\"name\\\":\\\"baz\\\",\\\"kinds\\\":[\\\"library\\\"],\\\"description\\\":\\\"lib\\\",\\\"repo_url\\\":\\\"https://github.com/actonlang/baz\\\"}\"\n              , \"]}\"\n              ]\n        case PkgCommands.decodeAppPackageIndex (LBS.pack body) of\n          Left err -> assertFailure err\n          Right pkgs -> do\n            assertEqual \"two apps\" [\"bar\", \"foo\"] (sort (map PkgCommands.pkgName pkgs))\n  , testCase \"decode package index requires kinds\" $ do\n        let body = concat\n              [ \"{\\\"packages\\\":[\"\n              , \"{\\\"name\\\":\\\"foo\\\",\\\"description\\\":\\\"desc\\\",\\\"repo_url\\\":\\\"https://github.com/actonlang/foo\\\"}\"\n              , \"]}\"\n              ]\n        case PkgCommands.decodePackageIndex (LBS.pack body) of\n          Left _ -> return ()\n          Right _ -> assertFailure \"package index entry without kinds should fail\"\n  ]\n\n-- Creates testgroup from .act files found in specified directory\n--createTests :: String -> String -> List -> TestTree\ncreateTests name dir allExpFail fails testFunc = do\n    actFiles <- findThings dir\n    return $ testGroup name $ map (createTest allExpFail fails testFunc) actFiles\n\ncreateTest allExpFail fails testFunc file = do\n    let fileExpFail = elem fileBody fails\n        expFail = if fileExpFail == True\n                    then fileExpFail\n                    else allExpFail\n    failWrap (testFunc expFail) file expFail\n  where (fileBody, fileExt) = splitExtension $ takeFileName file\n\ncreateAutoTests name dir = do\n    actFiles <- findThings dir\n    return $ testGroup name $ map createAutoTest actFiles\n\ncreateAutoTest file = do\n    -- guesstimate how to run this test\n    -- no suffix = compile and run test program and expect success (exit 0)\n    -- __bf = build failure, expect acton to exit 1\n    -- __rf = run failure: compile, run and expect exit 1\n    let fileParts = splitOn \"__\" fileBody\n        testExp   = if (length fileParts) == 2\n                      then last fileParts\n                      else \"\"\n        testName  = if testExp == \"\"\n                      then head fileParts\n                      else (head fileParts) ++ \" (\" ++testExp ++ \")\"\n        testFunc  = case testExp of\n                        \"bf\" -> testBuild \"\"\n                        _    -> testBuildAndRunRepeat \"\" \"\" 2\n        expRet    = case testExp of\n                        \"bf\" -> (ExitFailure 1)\n                        \"rf\" -> (ExitFailure 1)\n                        _    -> ExitSuccess\n    testCase testName $ testFunc expRet False file\n  where (fileBody, fileExt) = splitExtension $ takeFileName file\n\ncreateGoldenErrorAutoTests name dir = do\n    actFiles <- findThings dir\n    return $ testGroup name $ map (createGoldenErrorAutoTest dir) actFiles\n\ncreateGoldenErrorAutoTest dir file = do\n    let testName  = fileBody\n        goldenFile = joinPath [dir, fileBody ++ \".golden\"]\n    goldenVsString testName goldenFile (getCompileError file)\n  where (fileBody, fileExt) = splitExtension $ takeFileName file\n\ngetCompileError file = do\n    (returnCode, cmdOut, cmdErr) <- buildThing \"\" file\n    assertEqual \"compile error retCode\" (ExitFailure 1) returnCode\n    return (LBS.pack (TestGolden.normalizeProgressTimings cmdOut))\n\nfindThings dir = do\n    items <- listDirectory dir\n    let absItems = map ((dir ++ \"/\") ++) items\n        actFiles = catMaybes $ map filterActFile absItems\n    projDirs <- catMaybes <$> mapM isActProj absItems\n    return $ actFiles ++ projDirs\n  where filterActFile file =\n          case fileExt of\n              \".act\" -> Just file\n              _ -> Nothing\n          where (fileBody, fileExt) = splitExtension $ takeFileName file\n\nisActProj dir = do\n    isDir <- doesDirectoryExist dir\n    if isDir\n      then do\n          let projectFiles = [\"Build.act\"]\n          hasProjectFile <- or <$> mapM (\\file -> doesFileExist $ dir ++ \"/\" ++ file) projectFiles\n          hasSrcDir <- doesDirectoryExist $ dir ++ \"/src\"\n          if hasProjectFile && hasSrcDir\n            then return $ Just dir\n            else return Nothing\n      else return Nothing\n\nfailWrap testFunc thing True =\n    expectFail $ testWrap testFunc thing\nfailWrap testFunc thing False =\n    testWrap testFunc thing\n\ntestWrap testFunc thing =\n    testCase fileBody $ testFunc thing\n  where (fileBody, fileExt) = splitExtension $ takeFileName thing\n\ncleanOut :: FilePath -> IO ()\ncleanOut proj = removePathForcibly (proj </> \"out\") `catch` (\\(_ :: IOException) -> return ())\n\n-- Actual test functions\n-- expRet refers to the return code of acton\ntestBuild opts expRet expFail thing = do\n    testBuildThing opts expRet expFail thing\n\n-- expFail & expRet refers to the acton program, we always assume compilation\n-- with acton succeeds\n\ntestBuildAndRun buildOpts runOpts expRet expFail thing =\n    testBuildAndRunRepeat buildOpts runOpts 1 expRet expFail thing\n\ntestBuildAndRunRepeat buildOpts runOpts numRuns expRet expFail thing = do\n    testBuildThing buildOpts ExitSuccess False thing\n    replicateM_ numRuns $ do\n        (returnCode, cmdOut, cmdErr) <- runThing runOpts thing\n        when (expFail == False && returnCode /= expRet) $\n            putStrLn(\"\\nERROR: when running application \" ++ thing ++\n                     \", the return code (\" ++ show returnCode ++\n                     \") not as expected (\" ++ show expRet ++\n                     \")\\nSTDOUT:\\n\" ++ cmdOut ++ \"STDERR:\\n\" ++ cmdErr)\n        assertEqual (\"application should return \" ++ show expRet) expRet returnCode\n--    (returnCode, cmdOut, cmdErr) <- runThing runOpts thing\n--    iff (expFail == False && returnCode /= expRet) (\n--        putStrLn(\"\\nERROR: when running application \" ++ thing ++ \", the return code (\" ++ (show returnCode) ++ \") not as expected (\" ++ (show expRet) ++ \")\\nSTDOUT:\\n\" ++ cmdOut ++ \"STDERR:\\n\" ++ cmdErr)\n--        )\n--    assertEqual (\"application should return \" ++ (show expRet)) expRet returnCode\n\nbuildAndRun :: String -> String -> FilePath -> IO (ExitCode, String, String)\nbuildAndRun buildOpts runOpts thing = do\n    buildThing buildOpts thing\n    (returnCode, cmdOut, cmdErr) <- runThing runOpts thing\n    return (returnCode, cmdOut, cmdErr)\n\n-- when in a project, expect the binary to be named the same as the project\n-- without our ending, like __bf. For example, if the project is\n-- import_actor__bf, then we will run ./import_actor in\n-- import_actor__bf/rel/bin\nrunThing opts thing = do\n    twd <- canonicalizePath $ takeDirectory thing\n    isProj <- doesDirectoryExist thing\n    projBinPath <- canonicalizePath $ thing ++ \"/out/bin\"\n    let wd = if isProj then projBinPath else twd\n    let exe = if isProj then binName else fileBody\n    (returnCode, cmdOut, cmdErr) <- readCreateProcessWithExitCode (proc (\"./\" ++ exe) (words opts)){ cwd = Just wd } \"\"\n    return (returnCode, cmdOut, cmdErr)\n  where (fileBody, fileExt) = splitExtension $ takeFileName thing\n        fileParts = splitOn \"__\" fileBody\n        binName = head fileParts\n\n\ntestBuildThing opts expRet expFail thing = do\n    (returnCode, cmdOut, cmdErr) <- buildThing opts thing\n    iff (expFail == False && returnCode /= expRet) (\n        putStrLn(\"\\nERROR: when building \" ++ thing ++ \", acton returned code (\" ++ (show returnCode) ++ \") not as expected (\" ++ (show expRet) ++ \")\\nSTDOUT:\\n\" ++ cmdOut ++ \"STDERR:\\n\" ++ cmdErr)\n        )\n    assertEqual (\"acton should return \" ++ (show expRet)) expRet returnCode\n\n\nbuildThing opts thing = do\n    actonExe <- canonicalizePath \"../../dist/bin/acton\"\n    proj <- doesDirectoryExist thing\n    projPath <- canonicalizePath thing\n    curDir <- getCurrentDirectory\n    let wd = if proj then projPath else curDir\n        args0 = if proj then [\"build\"] else [thing]\n        args  = args0 ++ [\"--always-build\"] ++ words opts\n    (returnCode, cmdOut, cmdErr) <- readCreateProcessWithExitCode (proc actonExe args){ cwd = Just wd } \"\"\n    return (returnCode, cmdOut, cmdErr)\n\n\nrunRunacton :: FilePath -> [String] -> FilePath -> IO (ExitCode, String, String)\nrunRunacton script args cwd = do\n    actonBin <- canonicalizePath \"../../dist/bin\"\n    env0 <- getEnvironment\n    let pathVal = case lookup \"PATH\" env0 of\n          Just p -> p\n          Nothing -> \"\"\n        env1 = (\"PATH\", actonBin ++ \":\" ++ pathVal) : filter ((/= \"PATH\") . fst) env0\n    readCreateProcessWithExitCode (proc script args){ cwd = Just cwd, env = Just env1 } \"\"\n\nrunActon opts expRet expFail proj = do\n    actonExe <- canonicalizePath \"../../dist/bin/acton\"\n    projPath <- canonicalizePath proj\n    (returnCode, cmdOut, cmdErr) <- readCreateProcessWithExitCode (proc actonExe (words opts)){ cwd = Just projPath } \"\"\n    iff (expFail == False && returnCode /= expRet) (\n        putStrLn(\"\\nERROR: when running acton \" ++ opts ++ \", acton returned code (\" ++ (show returnCode) ++ \") not as expected (\" ++ (show expRet) ++ \")\\nSTDOUT:\\n\" ++ cmdOut ++ \"STDERR:\\n\" ++ cmdErr)\n        )\n    assertEqual (\"acton should return \" ++ (show expRet)) expRet returnCode\n\n\niff True m                      = m >> return ()\niff False _                     = return ()\n"
  },
  {
    "path": "compiler/acton/test_incremental.hs",
    "content": "{-# LANGUAGE OverloadedStrings #-}\n\nmodule Main (main) where\n\nimport           Control.Monad (unless, when)\nimport qualified Data.Binary as Binary\nimport qualified Data.ByteString.Lazy.Char8 as LBS\nimport qualified Data.ByteString as B\nimport qualified Data.Text as T\nimport qualified Data.Text.IO as T\nimport qualified Data.Text.Encoding as TE\nimport           Data.Char (isHexDigit, isSpace)\nimport           Data.Bits (shiftL, (.|.))\nimport           Data.Word (Word64)\nimport qualified Acton.Fingerprint as Fingerprint\nimport qualified Crypto.Hash.SHA256 as SHA256\nimport           Data.List (find, partition, sort)\nimport qualified Data.Map.Strict as M\nimport           Data.Maybe (isJust)\nimport           System.Directory\nimport           System.Exit\nimport           System.FilePath\nimport           System.IO (Handle)\nimport           System.Posix.Files (deviceID, fileID, fileSize, getFileStatus, modificationTimeHiRes, statusChangeTimeHiRes)\nimport           System.Process\nimport           Data.Time.Clock        (addUTCTime, getCurrentTime)\nimport           Data.Time.Clock.POSIX  (posixSecondsToUTCTime)\nimport           System.Directory       (setModificationTime)\nimport qualified Control.Exception as E\nimport           Control.Concurrent     (threadDelay)\n\nimport           Test.Tasty\nimport           Test.Tasty.Runners (NumThreads(..))\nimport           Test.Tasty (DependencyType(..), after, TestName)\nimport           Test.Tasty.Golden (goldenVsString)\nimport           Test.Tasty.HUnit\nimport           TestGolden (normalizeProgressTimingLine)\nimport qualified Acton.Compile as Compile\nimport qualified Acton.CommandLineParser as C\nimport qualified Acton.SourceProvider as Source\nimport qualified Acton.NameInfo as I\nimport qualified Acton.Syntax as A\nimport qualified InterfaceFiles\nimport           Utils (prstr)\n\n-- Paths ----------------------------------------------------------------------\n\nprojDir :: FilePath\nprojDir = \"test\" </> \"rebuild\"\n\nsrcDir :: FilePath\nsrcDir = projDir </> \"src\"\n\ngoldenDir :: FilePath\ngoldenDir = projDir </> \"golden\"\n\ncasesProjDir :: FilePath\ncasesProjDir = \"test\" </> \"incremental_cases\"\n\ncasesSrcDir :: FilePath\ncasesSrcDir = casesProjDir </> \"src\"\n\ncasesProjName :: String\ncasesProjName = \"incremental_cases\"\n\n-- When running commands under compiler/acton/test, the acton binary at\n-- repo-root/dist/bin/acton is four levels up.\nactonExe :: FilePath\nactonExe = \"..\" </> \"..\" </> \"..\" </> \"..\" </> \"dist\" </> \"bin\" </> \"acton\"\n\n-- | Build an acton command line with fixed job count.\nactonCmd :: String -> String\nactonCmd args = actonExe ++ \" \" ++ args ++ \" --jobs 1\"\n\n-- Utils ----------------------------------------------------------------------\n\n-- | Normalize build output for golden comparisons.\nsanitize :: T.Text -> LBS.ByteString\nsanitize = LBS.fromStrict\n        . TE.encodeUtf8\n        . T.unlines\n        . reorderBackLines\n        . map censorHashes\n        . map normalizeProgressTimingLine\n        . dropPaths\n        . filter (not . isVolatile)\n        . T.lines\n  where\n    isVolatile :: T.Text -> Bool\n    isVolatile t =\n      T.isInfixOf \"zigCmd\" t ||\n      T.isInfixOf \"Building project in\" t ||\n      T.isInfixOf \"Building [cap\" t\n\n    -- Rewrite volatile hash literals in log lines to stable placeholders.\n    -- We keep semantic position in deltas:\n    --   old hash values  -> HASH1\n    --   new hash values  -> HASH2\n    -- Values like \"missing\" are intentionally left unchanged.\n    censorHashes :: T.Text -> T.Text\n    censorHashes txt = go 0\n      where\n        n = T.length txt\n\n        go :: Int -> T.Text\n        go i\n          | i >= n = T.empty\n          | isHexStart i =\n              let j = spanHex i\n                  run = T.take (j - i) (T.drop i txt)\n              in if isHashRun run\n                   then hashTag i j <> go j\n                   else run <> go j\n          | otherwise = T.singleton (T.index txt i) <> go (i + 1)\n\n        isHexStart :: Int -> Bool\n        isHexStart i = isHexDigit (T.index txt i)\n\n        spanHex :: Int -> Int\n        spanHex i\n          | i < n && isHexDigit (T.index txt i) = spanHex (i + 1)\n          | otherwise = i\n\n        isHashRun :: T.Text -> Bool\n        isHashRun h = let len = T.length h in len == 8 || len == 64\n\n        hashTag :: Int -> Int -> T.Text\n        hashTag i j\n          | isRightValue i = \"HASH2\"\n          | isLeftValue j = \"HASH1\"\n          | otherwise = \"HASH\"\n\n        isRightValue :: Int -> Bool\n        isRightValue i =\n          case skipSpacesLeft (i - 1) of\n            Nothing -> False\n            Just k\n              | T.index txt k == '→' -> True\n              | k >= 1 && T.index txt (k - 1) == '-' && T.index txt k == '>' -> True\n              | otherwise -> False\n\n        isLeftValue :: Int -> Bool\n        isLeftValue j =\n          case skipSpacesRight j of\n            Nothing -> False\n            Just k\n              | T.index txt k == '→' -> True\n              | k + 1 < n && T.index txt k == '-' && T.index txt (k + 1) == '>' -> True\n              | otherwise -> False\n\n        skipSpacesLeft :: Int -> Maybe Int\n        skipSpacesLeft k\n          | k < 0 = Nothing\n          | isSpace (T.index txt k) = skipSpacesLeft (k - 1)\n          | otherwise = Just k\n\n        skipSpacesRight :: Int -> Maybe Int\n        skipSpacesRight k\n          | k >= n = Nothing\n          | isSpace (T.index txt k) = skipSpacesRight (k + 1)\n          | otherwise = Just k\n\n    -- Remove the verbose Paths: block (and its per-field lines) to avoid\n    -- machine-specific absolute paths in goldens.\n    dropPaths :: [T.Text] -> [T.Text]\n    dropPaths [] = []\n    dropPaths (l:ls)\n      | T.isPrefixOf \"Paths:\" (T.stripStart l) = dropWhile isPathField ls\n      | otherwise = l : dropPaths ls\n      where\n        isPathField :: T.Text -> Bool\n        isPathField x = let s = T.stripStart x in any (`T.isPrefixOf` s)\n                          [ \"sysPath\"\n                          , \"sysTypes\"\n                          , \"projPath\"\n                          , \"projOut\"\n                          , \"projTypes\"\n                          , \"binDir\"\n                          , \"srcDir\"\n                          , \"modName\"\n                          ]\n\n    reorderBackLines :: [T.Text] -> [T.Text]\n    reorderBackLines ls =\n      let (backLines, otherLines) = partition isBackLine ls\n          (pre, post) = break isFinalLine otherLines\n      in pre ++ sort backLines ++ post\n      where\n        isBackLine t =\n          T.isPrefixOf \"   Finished compilation of\" t ||\n          (T.isInfixOf \"Compilation done\" t && not (isFinalLine t))\n        isFinalLine t =\n          T.isPrefixOf \"   Finished final compilation\" t ||\n          T.isPrefixOf \"   Finished final compilation step\" t ||\n          T.isInfixOf \"Final compilation done\" t ||\n          T.isPrefixOf \"  Skipping final build step\" t\n\n-- | Atomically write UTF-8 text to a file.\nwriteFileUtf8 :: FilePath -> T.Text -> IO ()\nwriteFileUtf8 p t = do\n  let tmp = p <.> \"tmp\"\n  T.writeFile tmp t\n  let handler :: IOError -> IO ()\n      handler _ = do\n        exists <- doesFileExist p\n        let handler2 :: IOError -> IO (); handler2 _ = pure ()\n        when exists $ E.catch (removeFile p) handler2\n        renameFile tmp p\n  E.catch (renameFile tmp p) handler\n\nfingerprintForName :: String -> String\nfingerprintForName name =\n  let prefix = Fingerprint.fingerprintPrefixForName name\n      fp = (fromIntegral prefix `shiftL` 32) .|. (1 :: Word64)\n  in Fingerprint.formatFingerprint fp\n\n-- | Update a file's modification time to now.\ntouch :: FilePath -> IO ()\ntouch p = do\n  now <- getCurrentTime\n  setModificationTime p now\n\n-- | Reset the default rebuild project to a clean state.\nensureClean :: IO ()\nensureClean = do\n  ensureCleanAt projDir\n\n-- | Reset a project directory to a clean state.\nensureCleanAt :: FilePath -> IO ()\nensureCleanAt proj = do\n  createDirectoryIfMissing True proj\n  let src = proj </> \"src\"\n  -- Reset src dir fully to avoid leftover temp/lock files\n  let handler :: IOError -> IO (); handler _ = pure ()\n  E.catch (removeDirectoryRecursive src) handler\n  createDirectoryIfMissing True src\n  let buildAct = proj </> \"Build.act\"\n  exists <- doesFileExist buildAct\n  unless exists $ writeBuildAct proj (takeFileName proj) []\n  -- Remove previous build output if present\n  let outDir = proj </> \"out\"\n  outExists <- doesDirectoryExist outDir\n  when outExists $ E.catch (removeDirectoryRecursive outDir) handler\n  -- Remove potential leftover project lock file\n  let lockFile = proj </> \".acton.lock\"\n  lockExists <- doesFileExist lockFile\n  when lockExists $ E.catch (removeFile lockFile) handler\n  let bgLockFile = proj </> \".acton.compile.lock\"\n  bgLockExists <- doesFileExist bgLockFile\n  when bgLockExists $ E.catch (removeFile bgLockFile) handler\n\n-- | Run a shell command in a directory and capture stdout+stderr.\nrunIn :: FilePath -> String -> IO (ExitCode, T.Text)\nrunIn cwd cmd = do\n  (ec,out,err) <- readCreateProcessWithExitCode (shell cmd){ cwd = Just cwd } \"\"\n  pure (ec, T.pack out <> T.pack err)\n\n-- | Run a project build and return raw output.\nbuildOut :: IO T.Text\nbuildOut = do\n  let cmd = actonCmd \"build --color never --verbose\"\n  (_ec,out) <- runIn projDir cmd\n  pure out\n\n-- | Run a project build and return sanitized output.\ngoldenBuild :: IO LBS.ByteString\ngoldenBuild = do\n  let cmd = actonCmd \"build --color never --verbose\"\n  (_ec,out) <- runIn projDir cmd\n  pure (sanitize out)\n\n-- | Run a single-file build and return sanitized output.\ngoldenBuildFile :: IO LBS.ByteString\ngoldenBuildFile = do\n  let cmd = actonCmd \"src/c.act --color never --verbose\"\n  (_ec,out) <- runIn projDir cmd\n  pure (sanitize out)\n\n-- | Run a single-file build and return raw output.\nbuildOutFile :: IO T.Text\nbuildOutFile = do\n  let cmd = actonCmd \"src/c.act --color never --verbose\"\n  (_ec,out) <- runIn projDir cmd\n  pure out\n\n-- | Check whether build output reports typechecking for a module.\ntypechecked :: T.Text -> T.Text -> Bool\ntypechecked out modName =\n  any (\\line -> isTypecheckLine line && matchesModule line modName) (T.lines out)\n  where\n    isTypecheckLine line =\n      \"Finished type check of\" `T.isInfixOf` line ||\n      \"Type check done\" `T.isInfixOf` line\n\n-- | Check whether build output reports compilation for a module.\ncompiled :: T.Text -> T.Text -> Bool\ncompiled out modName =\n  any (\\line -> isCompiledLine line && matchesModule line modName) (T.lines out)\n  where\n    isCompiledLine line =\n      \"Finished compilation of\" `T.isInfixOf` line ||\n      \"Compilation done\" `T.isInfixOf` line\n\n-- | Match module labels across legacy \"proj/mod\" and new \"proj.mod\" formats.\nmatchesModule :: T.Text -> T.Text -> Bool\nmatchesModule line modName =\n  let dotName = T.replace \"/\" \".\" modName\n      leafName = T.takeWhileEnd (/= '/') modName\n      tokens = T.words line\n  in any (`elem` tokens) [modName, dotName, leafName]\n\n-- | Remove a file if it exists.\nremoveIfExists :: FilePath -> IO ()\nremoveIfExists p = do\n  exists <- doesFileExist p\n  when exists $ removeFile p\n\n-- | Remove a directory if it exists.\nremoveDirIfExists :: FilePath -> IO ()\nremoveDirIfExists p = do\n  exists <- doesDirectoryExist p\n  when exists $ removeDirectoryRecursive p\n\n-- | Reset a project directory including deps and build outputs.\nensureCleanProjectAt :: FilePath -> IO ()\nensureCleanProjectAt proj = do\n  ensureCleanAt proj\n  removeDirIfExists (proj </> \"deps\")\n  removeIfExists (proj </> \"build.zig\")\n  removeIfExists (proj </> \"build.zig.zon\")\n  removeIfExists (proj </> \".acton.compile.lock\")\n  removeIfExists (proj </> \".acton.lock\")\n\nwithBackgroundCompilerLockHeld :: FilePath -> IO a -> IO a\nwithBackgroundCompilerLockHeld proj action = do\n  mlock <- Compile.tryBackgroundCompilerLock proj\n  case mlock of\n    Nothing ->\n      assertFailure (\"failed to acquire .acton.compile.lock in \" ++ proj)\n    Just lock ->\n      action `E.finally` Compile.releaseBackgroundCompilerLock lock\n\n-- | Write a Build.act file with optional path deps.\nwriteBuildAct :: FilePath -> String -> [(String, FilePath)] -> IO ()\nwriteBuildAct proj name deps = do\n  let header = [ T.pack (\"name = \\\"\" ++ name ++ \"\\\"\")\n               , T.pack (\"fingerprint = \" ++ fingerprintForName name)\n               ]\n      depLines\n        | null deps = []\n        | otherwise =\n            [ \"\"\n            , \"dependencies = {\"\n            ] ++\n            [ T.pack (\"  \\\"\" ++ depName ++ \"\\\": (path=\\\"\" ++ depPath ++ \"\\\")\")\n            | (depName, depPath) <- deps\n            ] ++\n            [ \"}\"\n            ]\n  writeFileUtf8 (proj </> \"Build.act\") (T.unlines (header ++ depLines))\n\n-- | Create a dependency project under deps/.\nensureDepProject :: FilePath -> String -> IO FilePath\nensureDepProject proj depName = do\n  let depDir = proj </> \"deps\" </> depName\n  createDirectoryIfMissing True (depDir </> \"src\")\n  writeBuildAct depDir depName []\n  pure depDir\n\nensureCasesProject :: IO ()\nensureCasesProject = ensureCasesProjectWithDeps []\n\nensureCasesProjectWithDeps :: [(String, FilePath)] -> IO ()\nensureCasesProjectWithDeps deps = do\n  ensureCleanProjectAt casesProjDir\n  writeBuildAct casesProjDir casesProjName deps\n\n-- | Replace the first line of a file with a new string.\nrewriteFirstLine :: FilePath -> String -> IO ()\nrewriteFirstLine path newLine = do\n  content <- T.readFile path\n  let rest = snd (T.breakOn \"\\n\" content)\n  T.writeFile path (T.pack newLine <> rest)\n\n-- | Resolve the acton binary path.\nactonPath :: IO FilePath\nactonPath = canonicalizePath (\"..\" </> \"..\" </> \"dist\" </> \"bin\" </> \"acton\")\n\n-- | Run acton in a directory with fixed job count.\nrunActonIn :: FilePath -> [String] -> IO (ExitCode, T.Text)\nrunActonIn cwd args = do\n  actonExe <- actonPath\n  let args' = args ++ [\"--jobs\", \"1\"]\n  (ec,out,err) <- readCreateProcessWithExitCode (proc actonExe args'){ cwd = Just cwd } \"\"\n  pure (ec, T.pack out <> T.pack err)\n\n-- | Assert an exit success and include output on failure.\nassertExitSuccess :: String -> (ExitCode, T.Text) -> IO ()\nassertExitSuccess label (ec, out) =\n  case ec of\n    ExitSuccess -> pure ()\n    ExitFailure c ->\n      assertFailure (label ++ \" failed (exit \" ++ show c ++ \")\\n\" ++ T.unpack out)\n\n-- | Assert a specific exit failure and include output on mismatch.\nassertExitFailure :: String -> Int -> (ExitCode, T.Text) -> IO ()\nassertExitFailure label code (ec, out) =\n  case ec of\n    ExitFailure c | c == code -> pure ()\n    ExitFailure c ->\n      assertFailure (label ++ \" failed (expected exit \" ++ show code ++ \", got \" ++ show c ++ \")\\n\" ++ T.unpack out)\n    ExitSuccess ->\n      assertFailure (label ++ \" unexpectedly succeeded\\n\" ++ T.unpack out)\n\n-- | Run a verbose build in a project directory and return raw output.\nbuildOutIn :: FilePath -> IO T.Text\nbuildOutIn proj = do\n  res@(ec, out) <- runActonIn proj [\"build\", \"--color\", \"never\", \"--verbose\"]\n  assertExitSuccess (\"build in \" ++ proj) res\n  pure out\n\n-- | Run a verbose build with extra args and return raw output.\nbuildOutInArgs :: FilePath -> [String] -> IO T.Text\nbuildOutInArgs proj args = do\n  res@(ec, out) <- runActonIn proj ([\"build\", \"--color\", \"never\", \"--verbose\"] ++ args)\n  assertExitSuccess (\"build in \" ++ proj) res\n  pure out\n\n-- | Format a module label for output comparisons.\nmodLabel :: FilePath -> String -> T.Text\nmodLabel proj mod = T.pack (takeFileName proj ++ \"/\" ++ mod)\n\n-- | Build the default rebuild project.\nbuildProject :: IO ()\nbuildProject = do\n  let cmd = actonCmd \"build --color never\"\n  (ec,out) <- runIn projDir cmd\n  case ec of\n    ExitSuccess -> pure ()\n    ExitFailure c -> assertFailure (\"acton build failed: \" ++ show c ++ \"\\n\" ++ T.unpack out)\n\n-- | Read name hashes from a .ty file.\nreadTyNameHashes :: FilePath -> IO [InterfaceFiles.NameHashInfo]\nreadTyNameHashes tyPath = do\n  (_, _, _, _, _, _, _, _, nameHashes, _, _, _) <- InterfaceFiles.readFile tyPath\n  pure nameHashes\n\n-- | Read pub/impl dependency names for a binding in a .ty file.\nreadTyDeps :: FilePath -> String -> IO ([String], [String])\nreadTyDeps tyPath nameLabel = do\n  nameHashes <- readTyNameHashes tyPath\n  let matchName nh = prstr (InterfaceFiles.nhName nh) == nameLabel\n  case find matchName nameHashes of\n    Nothing -> do\n      assertFailure (\"missing name \" ++ nameLabel ++ \" in \" ++ tyPath)\n      pure ([], [])\n    Just nh -> do\n      let pubDeps = sort (map (prstr . fst) (InterfaceFiles.nhPubDeps nh))\n          implDeps = sort (map (prstr . fst) (InterfaceFiles.nhImplDeps nh))\n      pure (pubDeps, implDeps)\n\n-- | Rewrite source hash and name-hash section of a .ty file.\nrewriteTySrcHashAndNameHashes :: FilePath -> B.ByteString -> ([InterfaceFiles.NameHashInfo] -> [InterfaceFiles.NameHashInfo]) -> IO ()\nrewriteTySrcHashAndNameHashes tyPath srcHash' f = do\n  (_mods, nmod, tmod, sourceMeta, _srcHash, pubHash, implHash, imps, nameHashes, roots, tests, mdoc) <- InterfaceFiles.readFile tyPath\n  InterfaceFiles.writeFile tyPath srcHash' pubHash implHash sourceMeta imps (f nameHashes) roots tests mdoc nmod tmod\n\nrewriteTySourceMeta :: FilePath -> Maybe InterfaceFiles.SourceFileMeta -> IO ()\nrewriteTySourceMeta tyPath sourceMeta' = do\n  (_mods, nmod, tmod, _sourceMeta, srcHash, pubHash, implHash, imps, nameHashes, roots, tests, mdoc) <- InterfaceFiles.readFile tyPath\n  InterfaceFiles.writeFile tyPath srcHash pubHash implHash sourceMeta' imps nameHashes roots tests mdoc nmod tmod\n\nrewriteTyVersion :: FilePath -> [Int] -> IO ()\nrewriteTyVersion tyPath version' = do\n  (_mods, nmod, tmod, sourceMeta, srcHash, pubHash, implHash, imps, nameHashes, roots, tests, mdoc) <- InterfaceFiles.readFile tyPath\n  LBS.writeFile tyPath $\n    Binary.encode ((version', sourceMeta, srcHash, pubHash, implHash), imps, nameHashes, roots, tests, mdoc, nmod, tmod)\n\nreadTySourceMeta :: FilePath -> IO (Maybe InterfaceFiles.SourceFileMeta)\nreadTySourceMeta tyPath = do\n  (sourceMeta, _srcHash, _pubHash, _implHash, _imps, _nameHashes, _roots, _tests, _doc) <- InterfaceFiles.readHeader tyPath\n  pure sourceMeta\n\nsourceFileMetaForPath :: FilePath -> IO InterfaceFiles.SourceFileMeta\nsourceFileMetaForPath path = do\n  st <- getFileStatus path\n  let mtimeNs = floor (toRational (modificationTimeHiRes st) * 1000000000)\n      ctimeNs = floor (toRational (statusChangeTimeHiRes st) * 1000000000)\n  pure InterfaceFiles.SourceFileMeta\n    { InterfaceFiles.sfmMTimeNs = mtimeNs\n    , InterfaceFiles.sfmCTimeNs = ctimeNs\n    , InterfaceFiles.sfmSize = fromIntegral (fileSize st)\n    , InterfaceFiles.sfmDevice = Just (fromIntegral (deviceID st))\n    , InterfaceFiles.sfmInode = Just (fromIntegral (fileID st))\n    }\n\nsetFileMTimeNs :: FilePath -> Integer -> IO ()\nsetFileMTimeNs path mtimeNs =\n  setModificationTime path (posixSecondsToUTCTime (fromRational (toRational mtimeNs / 1000000000)))\n\n-- | Drop a qualified dependency label from all stored pub/impl dep lists.\ndropTyDepByLabel :: String -> [InterfaceFiles.NameHashInfo] -> [InterfaceFiles.NameHashInfo]\ndropTyDepByLabel depLabel =\n  map dropFromInfo\n  where\n    keepDep (qn, _h) = prstr qn /= depLabel\n    dropFromInfo nh =\n      nh { InterfaceFiles.nhPubDeps  = filter keepDep (InterfaceFiles.nhPubDeps nh)\n         , InterfaceFiles.nhImplDeps = filter keepDep (InterfaceFiles.nhImplDeps nh)\n         }\n\n-- | Assert that a dependency list includes all expected names.\nassertDepsContain :: String -> [String] -> [String] -> IO ()\nassertDepsContain label expected actual =\n  let missing = filter (`notElem` actual) expected\n  in unless (null missing) $\n       assertFailure (label ++ \" missing deps: \" ++ show missing ++ \"\\nactual: \" ++ show actual)\n\n-- | Run a project binary and capture stdout.\nrunBinaryIn :: FilePath -> String -> IO T.Text\nrunBinaryIn proj name = do\n  let bin = \"out\" </> \"bin\" </> name\n  (ec,out,err) <- readCreateProcessWithExitCode (proc bin []){ cwd = Just proj } \"\"\n  case ec of\n    ExitSuccess -> pure (T.pack out)\n    ExitFailure c -> assertFailure (\"Binary failed (exit \" ++ show c ++ \") stderr: \" ++ err)\n\nrunBinary :: String -> IO T.Text\nrunBinary = runBinaryIn projDir\n\n-- Project scenario steps ------------------------------------------------------\n\np01_init :: TestTree\np01_init = testCase \"01-init\" $ do\n  ensureClean\n  writeFileUtf8 (srcDir </> \"a.act\") \"aaa = 123\\n\"\n  writeFileUtf8 (srcDir </> \"b.act\") $ T.unlines\n    [ \"import a\"\n    , \"def baa():\"\n    , \"    return a.aaa\"\n    , \"\"\n    , \"class DocInfo:\"\n    , \"    def get(self) -> int:\"\n    , \"        \\\"get value\\\"\"\n    , \"        return 1\"\n    ]\n  writeFileUtf8 (srcDir </> \"c.act\") $ T.unlines\n    [ \"import b\"\n    , \"\"\n    , \"actor main(env: Env):\"\n    , \"    print(b.baa())\"\n    , \"    env.exit(0)\"\n    ]\n\np02_initial_build :: TestTree\np02_initial_build = goldenVsString \"02-initial-build.golden\" (goldenDir </> \"project_02-initial-build.golden\") goldenBuild\n\np03_up_to_date :: TestTree\np03_up_to_date = goldenVsString \"03-up-to-date.golden\" (goldenDir </> \"project_03-up-to-date.golden\") goldenBuild\n\np04_touch_no_rebuild :: TestTree\np04_touch_no_rebuild = goldenVsString \"04-touch-no-rebuild.golden\" (goldenDir </> \"project_04-touch-no-rebuild.golden\") $ do\n  touch (srcDir </> \"a.act\")\n  goldenBuild\n\np05_run_123 :: TestTree\np05_run_123 = testCase \"05-run 123\" $ do\n  out <- runBinary \"c\"\n  out @?= \"123\\n\"\n\np06_change_a_impl :: TestTree\np06_change_a_impl = goldenVsString \"06-change-a-impl.golden\" (goldenDir </> \"project_06-change-a-impl.golden\") $ do\n  writeFileUtf8 (srcDir </> \"a.act\") \"aaa = 124\\n\"\n  out <- buildOut\n  -- Expect only a.act to type check; b/c should re-run codegen only.\n  assertBool \"expected a.act to compile\" (typechecked out \"rebuild/a\")\n  assertBool \"did not expect b.act to compile\" (not (typechecked out \"rebuild/b\"))\n  assertBool \"did not expect c.act to compile\" (not (typechecked out \"rebuild/c\"))\n  assertBool \"expected b.act to compile codegen\" (compiled out \"rebuild/b\")\n  assertBool \"expected c.act to compile codegen\" (compiled out \"rebuild/c\")\n  pure (sanitize out)\n\np06_impl_change_fresh :: TestTree\np06_impl_change_fresh = testCase \"06-impl-change-up-to-date\" $ do\n  out <- buildOut\n  assertBool \"did not expect a.act to compile\" (not (typechecked out \"rebuild/a\"))\n  assertBool \"did not expect b.act to compile\" (not (typechecked out \"rebuild/b\"))\n  assertBool \"did not expect c.act to compile\" (not (typechecked out \"rebuild/c\"))\n  assertBool \"did not expect b.act to compile codegen\" (not (compiled out \"rebuild/b\"))\n  assertBool \"did not expect c.act to compile codegen\" (not (compiled out \"rebuild/c\"))\n\np07_run_124 :: TestTree\np07_run_124 = testCase \"07-run 124\" $ do\n  out <- runBinary \"c\"\n  out @?= \"124\\n\"\n\np08_change_b_impl :: TestTree\np08_change_b_impl = goldenVsString \"08-change-b-impl.golden\" (goldenDir </> \"project_08-change-b-impl.golden\") $ do\n  writeFileUtf8 (srcDir </> \"b.act\") $ T.unlines\n    [ \"import a\"\n    , \"def baa():\"\n    , \"    tmp = a.aaa\"\n    , \"    return tmp\"\n    , \"\"\n    , \"class DocInfo:\"\n    , \"    def get(self) -> int:\"\n    , \"        \\\"get value\\\"\"\n    , \"        return 1\"\n    ]\n  out <- buildOut\n  -- Expect b.act to compile, but not a.act or c.act in project build\n  assertBool \"did not expect a.act to compile\" (not (typechecked out \"rebuild/a\"))\n  assertBool \"expected b.act to compile\" (typechecked out \"rebuild/b\")\n  assertBool \"did not expect c.act to compile\" (not (typechecked out \"rebuild/c\"))\n  pure (sanitize out)\n\np09_run_124 :: TestTree\np09_run_124 = testCase \"09-run 124\" $ do\n  out <- runBinary \"c\"\n  out @?= \"124\\n\"\n\n-- Public-hash behavior tests -----------------------------------------------\n\n-- Changing public interface of an import should rebuild dependents that use it\np10_change_a_iface :: TestTree\np10_change_a_iface =\n  goldenVsString \"10-change-a-iface.golden\"\n                 (goldenDir </> \"project_10-change-a-iface.golden\") $ do\n    -- Change the type of a.aaa (public signature change).\n    writeFileUtf8 (srcDir </> \"a.act\") \"aaa = \\\"125\\\"\\n\"\n    out <- buildOut\n    -- Should rebuild a.act and b.act; with import-augmented public hashing, b's\n    -- public hash changes when a's interface changes\n    assertBool \"expected a.act to compile\" (typechecked out \"rebuild/a\")\n    assertBool \"expected b.act to compile\" (typechecked out \"rebuild/b\")\n    -- c should rebuild too, since it imports b which has now changed since its import a changed..\n    assertBool \"expected c.act to compile\" (typechecked out \"rebuild/c\")\n    pure (sanitize out)\n\n-- Docstring-only change in an imported module should not rebuild dependents\np11_change_b_doc :: TestTree\np11_change_b_doc =\n  goldenVsString \"11-change-b-doc.golden\"\n                 (goldenDir </> \"project_11-change-b-doc.golden\") $ do\n    -- Change only the docstring of a method in b.act; this should recompile b\n    -- (source changed) but not its dependent c (public hash is doc-free).\n    writeFileUtf8 (srcDir </> \"b.act\") $ T.unlines\n      [ \"import a\"\n      , \"def baa():\"\n      , \"    tmp = a.aaa\"\n      , \"    return tmp\"\n      , \"\"\n      , \"class DocInfo:\"\n      , \"    def get(self) -> int:\"\n      , \"        \\\"GET VALUE v2\\\"\"\n      , \"        return 1\"\n      ]\n    out <- buildOut\n    assertBool \"expected b.act to compile\" (typechecked out \"rebuild/b\")\n    assertBool \"did not expect c.act to compile\" (not (typechecked out \"rebuild/c\"))\n    pure (sanitize out)\n\np12_codegen_stale :: TestTree\np12_codegen_stale =\n  goldenVsString \"12-codegen-stale.golden\"\n                 (goldenDir </> \"project_12-codegen-stale.golden\") $ do\n    let bBase = projDir </> \"out\" </> \"types\" </> \"b\"\n    removeIfExists (bBase ++ \".c\")\n    removeIfExists (bBase ++ \".h\")\n    out <- buildOut\n    assertBool \"expected b.act to compile codegen\" (compiled out \"rebuild/b\")\n    assertBool \"did not expect b.act to type check\" (not (typechecked out \"rebuild/b\"))\n    assertBool \"did not expect a.act to type check\" (not (typechecked out \"rebuild/a\"))\n    assertBool \"did not expect c.act to compile codegen\" (not (compiled out \"rebuild/c\"))\n    pure (sanitize out)\n\nf01_init :: TestTree\nf01_init = testCase \"01-init\" $ do\n  ensureClean\n  writeFileUtf8 (srcDir </> \"a.act\") \"aaa = 123\\n\"\n  writeFileUtf8 (srcDir </> \"b.act\") $ T.unlines\n    [ \"import a\"\n    , \"def baa():\"\n    , \"    return a.aaa\"\n    ]\n  writeFileUtf8 (srcDir </> \"c.act\") $ T.unlines\n    [ \"import b\"\n    , \"\"\n    , \"actor main(env: Env):\"\n    , \"    print(b.baa())\"\n    , \"    env.exit(0)\"\n    ]\n\nf02_initial_build :: TestTree\nf02_initial_build = goldenVsString \"02-initial-build.golden\" (goldenDir </> \"file_02-initial-build.golden\") goldenBuildFile\n\nf03_up_to_date :: TestTree\nf03_up_to_date = goldenVsString \"03-up-to-date.golden\" (goldenDir </> \"file_03-up-to-date.golden\") goldenBuildFile\n\nf04_touch_no_rebuild :: TestTree\nf04_touch_no_rebuild = goldenVsString \"04-touch-no-rebuild.golden\" (goldenDir </> \"file_04-touch-no-rebuild.golden\") $ do\n  touch (srcDir </> \"a.act\")\n  goldenBuildFile\n\nf05_run_123 :: TestTree\nf05_run_123 = testCase \"05-run 123\" $ do\n  out <- runBinary \"c\"\n  out @?= \"123\\n\"\n\nf06_change_a_impl :: TestTree\nf06_change_a_impl = goldenVsString \"06-change-a-impl.golden\" (goldenDir </> \"file_06-change-a-impl.golden\") $ do\n  writeFileUtf8 (srcDir </> \"a.act\") \"aaa = 124\\n\"\n  out <- buildOutFile\n  -- Expect only a.act to compile in single-file build\n  assertBool \"expected a.act to compile\" (typechecked out \"rebuild/a\")\n  assertBool \"did not expect b.act to compile\" (not (typechecked out \"rebuild/b\"))\n  assertBool \"did not expect c.act to compile\" (not (typechecked out \"rebuild/c\"))\n  pure (sanitize out)\n\nf07_run_124 :: TestTree\nf07_run_124 = testCase \"07-run 124\" $ do\n  out <- runBinary \"c\"\n  out @?= \"124\\n\"\n\nf08_change_b_impl :: TestTree\nf08_change_b_impl = goldenVsString \"08-change-b-impl.golden\" (goldenDir </> \"file_08-change-b-impl.golden\") $ do\n  writeFileUtf8 (srcDir </> \"b.act\") $ T.unlines\n    [ \"import a\"\n    , \"def baa():\"\n    , \"    tmp = a.aaa\"\n    , \"    return tmp\"\n    , \"\"\n    , \"class DocInfo:\"\n    , \"    def get(self) -> int:\"\n    , \"        \\\"get value\\\"\"\n    , \"        return 1\"\n    ]\n  out <- buildOutFile\n  -- Expect b.act to compile; c.act should not re-typecheck on impl-only changes.\n  assertBool \"did not expect a.act to compile\" (not (typechecked out \"rebuild/a\"))\n  assertBool \"expected b.act to compile\" (typechecked out \"rebuild/b\")\n  assertBool \"did not expect c.act to compile\" (not (typechecked out \"rebuild/c\"))\n  pure (sanitize out)\n\nf09_run_124 :: TestTree\nf09_run_124 = testCase \"09-run 124\" $ do\n  out <- runBinary \"c\"\n  out @?= \"124\\n\"\n\n-- Alt-output behavior --------------------------------------------------------\n\n-- When requesting alternative output (e.g., --types), ensure the compiler runs\n-- the relevant passes and prints the output even if the file is otherwise\n-- up-to-date.\nf10_alt_output :: TestTree\nf10_alt_output = testCase \"10-alt output\" $ do\n  -- Run build an extra time to make sure we are up to date\n  _ <- buildOutFile\n\n  -- Now request alternative output on the same file without modifying sources\n  let cmd = actonCmd \"src/c.act --color never --types\"\n  (_ec,out) <- runIn projDir cmd\n  -- Expect a types dump header for module c\n  assertBool \"expected types dump for module c\" (T.isInfixOf \"== types: c\" out)\n\n-- Project case tests --------------------------------------------------------\n\np14_partial_rebuild :: TestTree\np14_partial_rebuild = testCase \"14-partial rebuild\" $ do\n  ensureCasesProject\n  writeFileUtf8 (casesSrcDir </> \"rebuild.act\") $ T.unlines\n    [ \"actor main(env: Env):\"\n    , \"    env.exit(0)\"\n    ]\n  res1 <- runActonIn casesProjDir [\"build\", \"--color\", \"never\"]\n  assertExitSuccess \"initial build\" res1\n  touch (casesSrcDir </> \"rebuild.act\")\n  res2 <- runActonIn casesProjDir [\"build\", \"--color\", \"never\"]\n  assertExitSuccess \"rebuild after touch\" res2\n\np15_rebuild_import :: TestTree\np15_rebuild_import = testCase \"15-rebuild with stdlib import\" $ do\n  ensureCasesProject\n  writeFileUtf8 (casesSrcDir </> \"rebuild.act\") $ T.unlines\n    [ \"import json\"\n    , \"\"\n    , \"actor main(env: Env):\"\n    , \"    env.exit(0)\"\n    ]\n  res1 <- runActonIn casesProjDir [\"build\", \"--color\", \"never\"]\n  assertExitSuccess \"initial build\" res1\n  res2 <- runActonIn casesProjDir [\"build\", \"--color\", \"never\"]\n  assertExitSuccess \"second build\" res2\n\np16_dep_api_change :: TestTree\np16_dep_api_change = testCase \"16-dependency API change triggers rebuild\" $ do\n  let originalContent = T.unlines\n        [ \"# Initial version\"\n        , \"def calculate(x: int) -> int:\"\n        , \"    return x * 2\"\n        ]\n      modifiedContent = T.unlines\n        [ \"# Modified version\"\n        , \"def calculate(x: int, y: int) -> int:\"\n        , \"    return x * y\"\n        ]\n  ensureCasesProjectWithDeps [(\"libfoo\", \"deps/libfoo\")]\n  depDir <- ensureDepProject casesProjDir \"libfoo\"\n  let depSrc = depDir </> \"src\" </> \"libfoo.act\"\n  writeFileUtf8 depSrc originalContent\n  writeFileUtf8 (casesSrcDir </> \"main.act\") $ T.unlines\n    [ \"import libfoo\"\n    , \"\"\n    , \"actor main(env: Env):\"\n    , \"    result = libfoo.calculate(21)\"\n    , \"    print(\\\"Result: %d\\\" % result)\"\n    , \"    env.exit(0)\"\n    ]\n  res1 <- runActonIn casesProjDir [\"build\", \"--color\", \"never\"]\n  assertExitSuccess \"initial build\" res1\n  writeFileUtf8 depSrc modifiedContent\n  res2 <- runActonIn casesProjDir [\"build\", \"--color\", \"never\"]\n  assertExitFailure \"rebuild after API change\" 1 res2\n\np17_dep_impl_change :: TestTree\np17_dep_impl_change = testCase \"17-dependency impl change triggers back job\" $ do\n  let originalContent = T.unlines\n        [ \"# Initial version\"\n        , \"def calculate(x: int) -> int:\"\n        , \"    return x * 2\"\n        ]\n      modifiedContent = T.unlines\n        [ \"# Modified version\"\n        , \"def calculate(x: int) -> int:\"\n        , \"    return x * 3\"\n        ]\n      modMain = modLabel casesProjDir \"main\"\n  ensureCasesProjectWithDeps [(\"libfoo\", \"deps/libfoo\")]\n  depDir <- ensureDepProject casesProjDir \"libfoo\"\n  let depSrc = depDir </> \"src\" </> \"libfoo.act\"\n  writeFileUtf8 depSrc originalContent\n  writeFileUtf8 (casesSrcDir </> \"main.act\") $ T.unlines\n    [ \"import libfoo\"\n    , \"\"\n    , \"actor main(env: Env):\"\n    , \"    result = libfoo.calculate(21)\"\n    , \"    print(\\\"Result: %d\\\" % result)\"\n    , \"    env.exit(0)\"\n    ]\n  res1 <- runActonIn casesProjDir [\"build\", \"--color\", \"never\"]\n  assertExitSuccess \"initial build\" res1\n  writeFileUtf8 depSrc modifiedContent\n  res2@(ec2, out2) <- runActonIn casesProjDir [\"build\", \"--color\", \"never\", \"--verbose\"]\n  assertExitSuccess \"rebuild after impl change\" res2\n  assertBool \"expected impl change log\" (T.isInfixOf \"impl changes in libfoo.calculate\" out2)\n  assertBool \"did not expect main to type check\" (not (typechecked out2 modMain))\n  assertBool \"expected main to compile codegen\" (compiled out2 modMain)\n\n-- Incremental/hash case coverage --------------------------------------------\n\np18_type_only_deps :: TestTree\np18_type_only_deps = testCase \"18-type-only deps in signatures\" $ do\n  let proj = casesProjDir\n      src = casesSrcDir\n      modB = modLabel proj \"b\"\n      modC = modLabel proj \"c\"\n  ensureCasesProject\n  writeFileUtf8 (src </> \"a.act\") $ T.unlines\n    [ \"class Foo:\"\n    , \"    def get(self) -> int:\"\n    , \"        return 1\"\n    ]\n  writeFileUtf8 (src </> \"b.act\") $ T.unlines\n    [ \"import a\"\n    , \"\"\n    , \"def takes(x: a.Foo) -> int:\"\n    , \"    return 0\"\n    ]\n  writeFileUtf8 (src </> \"c.act\") $ T.unlines\n    [ \"actor main(env: Env):\"\n    , \"    env.exit(0)\"\n    ]\n  _ <- buildOutIn proj\n  writeFileUtf8 (src </> \"a.act\") $ T.unlines\n    [ \"class Foo:\"\n    , \"    def get(self) -> int:\"\n    , \"        return 2\"\n    ]\n  out1 <- buildOutIn proj\n  assertBool \"did not expect b.act to type check\" (not (typechecked out1 modB))\n  assertBool \"did not expect c.act to type check\" (not (typechecked out1 modC))\n  writeFileUtf8 (src </> \"a.act\") $ T.unlines\n    [ \"class Foo:\"\n    , \"    def get(self) -> float:\"\n    , \"        return 2.0\"\n    ]\n  out2 <- buildOutIn proj\n  assertBool \"expected b.act to type check\" (typechecked out2 modB)\n  assertBool \"did not expect c.act to type check\" (not (typechecked out2 modC))\n\np19_unused_import :: TestTree\np19_unused_import = testCase \"19-unused import does not propagate\" $ do\n  let proj = casesProjDir\n      src = casesSrcDir\n      modB = modLabel proj \"b\"\n      modC = modLabel proj \"c\"\n  ensureCasesProject\n  writeFileUtf8 (src </> \"a.act\") $ T.unlines\n    [ \"def foo() -> int:\"\n    , \"    return 1\"\n    ]\n  writeFileUtf8 (src </> \"b.act\") $ T.unlines\n    [ \"import a\"\n    , \"\"\n    , \"def bar() -> int:\"\n    , \"    return a.foo()\"\n    ]\n  writeFileUtf8 (src </> \"c.act\") $ T.unlines\n    [ \"import b\"\n    , \"\"\n    , \"actor main(env: Env):\"\n    , \"    b.bar()\"\n    , \"    env.exit(0)\"\n    ]\n  _ <- buildOutIn proj\n  writeFileUtf8 (src </> \"b.act\") $ T.unlines\n    [ \"import a\"\n    , \"import testing\"\n    , \"\"\n    , \"def bar() -> int:\"\n    , \"    return a.foo()\"\n    ]\n  out <- buildOutIn proj\n  assertBool \"expected b.act to type check\" (typechecked out modB)\n  assertBool \"did not expect c.act to type check\" (not (typechecked out modC))\n\np20_add_remove_names :: TestTree\np20_add_remove_names = testCase \"20-add/remove top-level names\" $ do\n  let proj = casesProjDir\n      src = casesSrcDir\n      modB = modLabel proj \"b\"\n      modC = modLabel proj \"c\"\n  ensureCasesProject\n  writeFileUtf8 (src </> \"a.act\") \"foo = 1\\n\"\n  writeFileUtf8 (src </> \"b.act\") $ T.unlines\n    [ \"import a\"\n    , \"\"\n    , \"def bar() -> int:\"\n    , \"    return a.foo\"\n    ]\n  writeFileUtf8 (src </> \"c.act\") $ T.unlines\n    [ \"import b\"\n    , \"\"\n    , \"actor main(env: Env):\"\n    , \"    b.bar()\"\n    , \"    env.exit(0)\"\n    ]\n  _ <- buildOutIn proj\n  writeFileUtf8 (src </> \"a.act\") $ T.unlines\n    [ \"foo = 1\"\n    , \"bar = 2\"\n    ]\n  out1 <- buildOutIn proj\n  let addDelta = \"+bar\"\n  assertBool \"expected +bar hash delta\" (addDelta `T.isInfixOf` out1)\n  assertBool \"did not expect b.act to type check\" (not (typechecked out1 modB))\n  assertBool \"did not expect c.act to type check\" (not (typechecked out1 modC))\n  writeFileUtf8 (src </> \"a.act\") \"foo = 1\\n\"\n  out2 <- buildOutIn proj\n  let removeDelta = \"-bar\"\n  assertBool \"expected -bar hash delta\" (removeDelta `T.isInfixOf` out2)\n  assertBool \"did not expect b.act to type check\" (not (typechecked out2 modB))\n  assertBool \"did not expect c.act to type check\" (not (typechecked out2 modC))\n\np21_recursive_group :: TestTree\np21_recursive_group = testCase \"21-recursive group impl change propagates\" $ do\n  let proj = casesProjDir\n      src = casesSrcDir\n      modB = modLabel proj \"b\"\n  ensureCasesProject\n  writeFileUtf8 (src </> \"a.act\") $ T.unlines\n    [ \"def even(n: int) -> bool:\"\n    , \"    if n == 0:\"\n    , \"        return True\"\n    , \"    else:\"\n    , \"        return odd(n - 1)\"\n    , \"\"\n    , \"def odd(n: int) -> bool:\"\n    , \"    if n == 0:\"\n    , \"        return False\"\n    , \"    else:\"\n    , \"        return even(n - 1)\"\n    ]\n  writeFileUtf8 (src </> \"b.act\") $ T.unlines\n    [ \"import a\"\n    , \"\"\n    , \"def use() -> bool:\"\n    , \"    return a.even(2)\"\n    ]\n  writeFileUtf8 (src </> \"c.act\") $ T.unlines\n    [ \"import b\"\n    , \"\"\n    , \"actor main(env: Env):\"\n    , \"    b.use()\"\n    , \"    env.exit(0)\"\n    ]\n  _ <- buildOutIn proj\n  writeFileUtf8 (src </> \"a.act\") $ T.unlines\n    [ \"def even(n: int) -> bool:\"\n    , \"    if n == 0:\"\n    , \"        return True\"\n    , \"    else:\"\n    , \"        return odd(n - 1)\"\n    , \"\"\n    , \"def odd(n: int) -> bool:\"\n    , \"    if n == 0:\"\n    , \"        return True\"\n    , \"    else:\"\n    , \"        return even(n - 1)\"\n    ]\n  out <- buildOutIn proj\n  assertBool \"expected even impl delta\" (T.isInfixOf \"~even{impl\" out)\n  assertBool \"expected odd src delta\" (T.isInfixOf \"~odd{src\" out)\n  assertBool \"expected b.act to compile codegen\" (compiled out modB)\n  assertBool \"did not expect b.act to type check\" (not (typechecked out modB))\n\np22_multibind :: TestTree\np22_multibind = testCase \"22-multi-binding updates per-name hashes\" $ do\n  let proj = casesProjDir\n      src = casesSrcDir\n      modB = modLabel proj \"b\"\n  ensureCasesProject\n  writeFileUtf8 (src </> \"a.act\") \"x, y = 1, 2\\n\"\n  writeFileUtf8 (src </> \"b.act\") $ T.unlines\n    [ \"import a\"\n    , \"\"\n    , \"def get() -> int:\"\n    , \"    return a.x\"\n    ]\n  writeFileUtf8 (src </> \"c.act\") $ T.unlines\n    [ \"import b\"\n    , \"\"\n    , \"actor main(env: Env):\"\n    , \"    b.get()\"\n    , \"    env.exit(0)\"\n    ]\n  _ <- buildOutIn proj\n  writeFileUtf8 (src </> \"a.act\") \"x, y = 1, 3\\n\"\n  out <- buildOutIn proj\n  assertBool \"expected x src delta\" (T.isInfixOf \"~x{src\" out)\n  assertBool \"expected y src delta\" (T.isInfixOf \"~y{src\" out)\n  assertBool \"expected b.act to compile codegen\" (compiled out modB)\n\np23_codegen_mismatch :: TestTree\np23_codegen_mismatch = testCase \"23-codegen hash mismatch triggers rebuild\" $ do\n  let proj = casesProjDir\n      src = casesSrcDir\n      modB = modLabel proj \"b\"\n      bC = proj </> \"out\" </> \"types\" </> \"b.c\"\n  ensureCasesProject\n  writeFileUtf8 (src </> \"a.act\") $ T.unlines\n    [ \"def foo() -> int:\"\n    , \"    return 1\"\n    ]\n  writeFileUtf8 (src </> \"b.act\") $ T.unlines\n    [ \"import a\"\n    , \"\"\n    , \"def bar() -> int:\"\n    , \"    return a.foo()\"\n    ]\n  writeFileUtf8 (src </> \"c.act\") $ T.unlines\n    [ \"import b\"\n    , \"\"\n    , \"actor main(env: Env):\"\n    , \"    b.bar()\"\n    , \"    env.exit(0)\"\n    ]\n  _ <- buildOutIn proj\n  rewriteFirstLine bC \"/* Acton impl hash: deadbeef */\"\n  out <- buildOutIn proj\n  assertBool \"expected codegen stale message\" (T.isInfixOf \"generated code out of date\" out)\n  assertBool \"expected b.act to compile codegen\" (compiled out modB)\n  assertBool \"did not expect b.act to type check\" (not (typechecked out modB))\n\np24_codegen_equal_hash :: TestTree\np24_codegen_equal_hash = testCase \"24-codegen equal hash mismatch formats single delta\" $ do\n  let proj = casesProjDir\n      src = casesSrcDir\n      modB = modLabel proj \"b\"\n      bC = proj </> \"out\" </> \"types\" </> \"b.c\"\n      bH = proj </> \"out\" </> \"types\" </> \"b.h\"\n  ensureCasesProject\n  writeFileUtf8 (src </> \"a.act\") $ T.unlines\n    [ \"def foo() -> int:\"\n    , \"    return 1\"\n    ]\n  writeFileUtf8 (src </> \"b.act\") $ T.unlines\n    [ \"import a\"\n    , \"\"\n    , \"def bar() -> int:\"\n    , \"    return a.foo()\"\n    ]\n  writeFileUtf8 (src </> \"c.act\") $ T.unlines\n    [ \"import b\"\n    , \"\"\n    , \"actor main(env: Env):\"\n    , \"    b.bar()\"\n    , \"    env.exit(0)\"\n    ]\n  _ <- buildOutIn proj\n  rewriteFirstLine bC \"/* Acton impl hash: deadbeef */\"\n  rewriteFirstLine bH \"/* Acton impl hash: deadbeef */\"\n  out <- buildOutIn proj\n  assertBool \"expected single-delta codegen message\"\n    (T.isInfixOf \"generated code out of date {impl deadbeef ->\" out)\n  assertBool \"expected b.act to compile codegen\" (compiled out modB)\n  assertBool \"did not expect b.act to type check\" (not (typechecked out modB))\n\np25_whitespace_change :: TestTree\np25_whitespace_change = testCase \"25-whitespace-only change does not propagate\" $ do\n  let proj = casesProjDir\n      src = casesSrcDir\n      modB = modLabel proj \"b\"\n      modC = modLabel proj \"c\"\n  ensureCasesProject\n  writeFileUtf8 (src </> \"a.act\") $ T.unlines\n    [ \"def foo() -> int:\"\n    , \"    return 1\"\n    ]\n  writeFileUtf8 (src </> \"b.act\") $ T.unlines\n    [ \"import a\"\n    , \"\"\n    , \"def bar() -> int:\"\n    , \"    return a.foo()\"\n    ]\n  writeFileUtf8 (src </> \"c.act\") $ T.unlines\n    [ \"import b\"\n    , \"\"\n    , \"actor main(env: Env):\"\n    , \"    b.bar()\"\n    , \"    env.exit(0)\"\n    ]\n  _ <- buildOutIn proj\n  writeFileUtf8 (src </> \"a.act\") $ T.unlines\n    [ \"# comment\"\n    , \"def foo() -> int:\"\n    , \"    return 1\"\n    ]\n  out <- buildOutIn proj\n  assertBool \"did not expect b.act to type check\" (not (typechecked out modB))\n  assertBool \"did not expect c.act to type check\" (not (typechecked out modC))\n\np26_corrupt_ty_header :: TestTree\np26_corrupt_ty_header = testCase \"26-corrupt .ty header forces re-parse\" $ do\n  let proj = casesProjDir\n      src = casesSrcDir\n      modA = modLabel proj \"a\"\n      tyA = proj </> \"out\" </> \"types\" </> \"a.ty\"\n  ensureCasesProject\n  writeFileUtf8 (src </> \"a.act\") \"aaa = 1\\n\"\n  writeFileUtf8 (src </> \"c.act\") $ T.unlines\n    [ \"import a\"\n    , \"\"\n    , \"actor main(env: Env):\"\n    , \"    print(a.aaa)\"\n    , \"    env.exit(0)\"\n    ]\n  _ <- buildOutIn proj\n  writeFileUtf8 tyA \"garbage\\n\"\n  out <- buildOutIn proj\n  assertBool \"expected a.act to type check after corrupt .ty\" (typechecked out modA)\n\np26_ty_version_mismatch :: TestTree\np26_ty_version_mismatch = testCase \"26b-.ty version mismatch forces re-parse\" $ do\n  let proj = casesProjDir\n      src = casesSrcDir\n      modA = modLabel proj \"a\"\n      tyA = proj </> \"out\" </> \"types\" </> \"a.ty\"\n  ensureCasesProject\n  writeFileUtf8 (src </> \"a.act\") \"aaa = 1\\n\"\n  writeFileUtf8 (src </> \"c.act\") $ T.unlines\n    [ \"import a\"\n    , \"\"\n    , \"actor main(env: Env):\"\n    , \"    print(a.aaa)\"\n    , \"    env.exit(0)\"\n    ]\n  _ <- buildOutIn proj\n  rewriteTyVersion tyA (map (+ 1) A.version)\n  out <- buildOutIn proj\n  assertBool \"expected a.act to type check after .ty version mismatch\" (typechecked out modA)\n  assertBool \"did not expect raw .ty version mismatch\" $\n    not (\".ty version mismatch\" `T.isInfixOf` out)\n\np27_overlay_source_provider :: TestTree\np27_overlay_source_provider = testCase \"27-overlay snapshots drive readModuleTask\" $ do\n  let proj = casesProjDir\n      src = casesSrcDir\n      actA = src </> \"a.act\"\n  ensureCasesProject\n  writeFileUtf8 actA \"aaa = 1\\n\"\n  writeFileUtf8 (src </> \"c.act\") $ T.unlines\n    [ \"import a\"\n    , \"\"\n    , \"actor main(env: Env):\"\n    , \"    print(a.aaa)\"\n    , \"    env.exit(0)\"\n    ]\n  _ <- buildOutIn proj\n  actAAbs <- canonicalizePath actA\n  bytes <- B.readFile actAAbs\n  let text = T.unpack (TE.decodeUtf8 bytes)\n      snapSame = Source.SourceSnapshot\n        { Source.ssText = text\n        , Source.ssBytes = bytes\n        , Source.ssIsOverlay = True\n        }\n      disk = Source.diskSourceProvider\n      spSame = disk { Source.spReadOverlay = \\path -> return (if path == actAAbs then Just snapSame else Nothing) }\n      gopts = C.GlobalOptions\n        { C.color = C.Never\n        , C.quiet = True\n        , C.noProgress = False\n        , C.timing = False\n        , C.tty = False\n        , C.verbose = False\n        , C.verboseZig = False\n        , C.jobs = 1\n        }\n  paths <- Compile.findPaths actAAbs Compile.defaultCompileOptions\n  taskSame <- Compile.readModuleTask spSame gopts Compile.defaultCompileOptions paths actAAbs\n  case taskSame of\n    Compile.TyTask{} -> pure ()\n    _ -> assertFailure \"expected TyTask when overlay matches header\"\n  let textDiff = \"\\\"\\\"\\\"Overlay doc\\\"\\\"\\\"\\naaa = 2\\n\"\n      bytesDiff = TE.encodeUtf8 (T.pack textDiff)\n      snapDiff = Source.SourceSnapshot\n        { Source.ssText = textDiff\n        , Source.ssBytes = bytesDiff\n        , Source.ssIsOverlay = True\n        }\n      spDiff = disk { Source.spReadOverlay = \\path -> return (if path == actAAbs then Just snapDiff else Nothing) }\n  taskDiff <- Compile.readModuleTask spDiff gopts Compile.defaultCompileOptions paths actAAbs\n  case taskDiff of\n    Compile.ParseTask{ Compile.src = srcText, Compile.srcBytes = srcBytes } -> do\n      srcText @?= textDiff\n      srcBytes @?= bytesDiff\n    _ -> assertFailure \"expected ParseTask when overlay differs from header\"\n  docDiff <- Compile.readModuleDoc spDiff gopts Compile.defaultCompileOptions paths actAAbs\n  case docDiff of\n    Just (mn, Just doc) -> do\n      mn @?= A.modName [\"a\"]\n      doc @?= \"Overlay doc\"\n    _ -> assertFailure \"expected module doc from overlay header\"\n\np28_protocol_extension_deps :: TestTree\np28_protocol_extension_deps = testCase \"28-protocol/extension deps are recorded by name\" $ do\n  let proj = casesProjDir\n      src = casesSrcDir\n      tyA = proj </> \"out\" </> \"types\" </> \"a.ty\"\n      tyB = proj </> \"out\" </> \"types\" </> \"b.ty\"\n  ensureCasesProject\n  writeFileUtf8 (src </> \"a.act\") $ T.unlines\n    [ \"protocol FooProto:\"\n    , \"    foo : () -> int\"\n    , \"\"\n    , \"protocol BazProto:\"\n    , \"    baz : () -> int\"\n    , \"\"\n    , \"protocol BarProto (FooProto, BazProto):\"\n    , \"    bar : () -> int\"\n    , \"\"\n    , \"class Widget:\"\n    , \"    def __init__(self):\"\n    , \"        pass\"\n    , \"\"\n    , \"extension Widget(BarProto):\"\n    , \"    def foo(self) -> int:\"\n    , \"        return 0\"\n    , \"    def baz(self) -> int:\"\n    , \"        return 2\"\n    , \"    def bar(self) -> int:\"\n    , \"        return 1\"\n    , \"\"\n    , \"def uses_proto(x: BarProto) -> int:\"\n    , \"    return 0\"\n    , \"\"\n    , \"def uses_class(x: Widget) -> int:\"\n    , \"    return 0\"\n    ]\n  writeFileUtf8 (src </> \"b.act\") $ T.unlines\n    [ \"import a\"\n    , \"\"\n    , \"def runner(x: a.BarProto) -> int:\"\n    , \"    return a.uses_class(a.Widget())\"\n    ]\n  writeFileUtf8 (src </> \"c.act\") $ T.unlines\n    [ \"import a\"\n    , \"import b\"\n    , \"\"\n    , \"actor main(env: Env):\"\n    , \"    b.runner(a.Widget())\"\n    , \"    env.exit(0)\"\n    ]\n  _ <- buildOutIn proj\n  nameHashesA <- readTyNameHashes tyA\n  let namesA = sort (map (prstr . InterfaceFiles.nhName) nameHashesA)\n  assertBool \"expected generated protocol sibling name\" (\"BazProtoD_BarProto\" `elem` namesA)\n  assertBool \"expected generated extension name\" (\"BarProtoD_Widget\" `elem` namesA)\n  (_, nmod, _, _, _, _, _, _, _, _, _, _) <- InterfaceFiles.readFile tyA\n  let I.NModule _ iface _ = nmod\n      extMatch (n, _) = prstr n == \"BarProtoD_Widget\"\n  case find extMatch iface of\n    Just (_, I.NExt _ _ ps _ _ _) -> do\n      let protoNames = sort [ prstr (A.tcname p) | (_, p) <- ps ]\n      assertEqual \"extension protocol mro\" (sort [\"a.BarProto\", \"a.BazProto\", \"a.FooProto\"]) protoNames\n    _ -> assertFailure \"missing extension NameInfo for BarProtoD_Widget\"\n  (pubDeps, implDeps) <- readTyDeps tyB \"runner\"\n  let expectedPub = sort [\"__builtin__.int\", \"a.BarProto\", \"a.Widget\", \"a.uses_class\"]\n      expectedImpl = sort [\"a.BarProto\", \"a.Widget\", \"a.uses_class\"]\n  assertEqual \"runner pub deps\" expectedPub pubDeps\n  assertEqual \"runner impl deps\" expectedImpl implDeps\n\np29_protocol_impl_rebuild :: TestTree\np29_protocol_impl_rebuild = testCase \"29-protocol impl change triggers back jobs and new binary\" $ do\n  let proj = casesProjDir\n      src = casesSrcDir\n      modA = modLabel proj \"a\"\n      modB = modLabel proj \"b\"\n      modC = modLabel proj \"c\"\n  ensureCasesProject\n  writeFileUtf8 (src </> \"a.act\") $ T.unlines\n    [ \"protocol FooProto:\"\n    , \"    foo : () -> int\"\n    , \"\"\n    , \"protocol BazProto:\"\n    , \"    baz : () -> int\"\n    , \"\"\n    , \"protocol BarProto (FooProto, BazProto):\"\n    , \"    bar : () -> int\"\n    , \"\"\n    , \"class Widget:\"\n    , \"    def __init__(self):\"\n    , \"        pass\"\n    , \"\"\n    , \"extension Widget(BarProto):\"\n    , \"    def foo(self) -> int:\"\n    , \"        return 1\"\n    , \"    def baz(self) -> int:\"\n    , \"        return 2\"\n    , \"    def bar(self) -> int:\"\n    , \"        return 3\"\n    , \"\"\n    , \"def value() -> int:\"\n    , \"    return Widget().bar()\"\n    ]\n  writeFileUtf8 (src </> \"b.act\") $ T.unlines\n    [ \"import a\"\n    , \"\"\n    , \"def calc() -> int:\"\n    , \"    return a.value()\"\n    ]\n  writeFileUtf8 (src </> \"c.act\") $ T.unlines\n    [ \"import b\"\n    , \"\"\n    , \"actor main(env: Env):\"\n    , \"    print(b.calc())\"\n    , \"    env.exit(0)\"\n    ]\n  _ <- buildOutIn proj\n  out1 <- runBinaryIn proj \"c\"\n  out1 @?= \"3\\n\"\n  writeFileUtf8 (src </> \"a.act\") $ T.unlines\n    [ \"protocol FooProto:\"\n    , \"    foo : () -> int\"\n    , \"\"\n    , \"protocol BazProto:\"\n    , \"    baz : () -> int\"\n    , \"\"\n    , \"protocol BarProto (FooProto, BazProto):\"\n    , \"    bar : () -> int\"\n    , \"\"\n    , \"class Widget:\"\n    , \"    def __init__(self):\"\n    , \"        pass\"\n    , \"\"\n    , \"extension Widget(BarProto):\"\n    , \"    def foo(self) -> int:\"\n    , \"        return 1\"\n    , \"    def baz(self) -> int:\"\n    , \"        return 5\"\n    , \"    def bar(self) -> int:\"\n    , \"        return 6\"\n    , \"\"\n    , \"def value() -> int:\"\n    , \"    return Widget().bar()\"\n    ]\n  out2 <- buildOutIn proj\n  assertBool \"expected a.act to type check\" (typechecked out2 modA)\n  assertBool \"did not expect b.act to type check\" (not (typechecked out2 modB))\n  assertBool \"did not expect c.act to type check\" (not (typechecked out2 modC))\n  assertBool \"expected b.act to compile codegen\" (compiled out2 modB)\n  assertBool \"expected c.act to compile codegen\" (compiled out2 modC)\n  out2Run <- runBinaryIn proj \"c\"\n  out2Run @?= \"6\\n\"\n\np30_only_build :: TestTree\np30_only_build = testCase \"30-only-build skips front passes\" $ do\n  let proj = casesProjDir\n      src = casesSrcDir\n      modA = modLabel proj \"a\"\n      modB = modLabel proj \"b\"\n      modC = modLabel proj \"c\"\n  ensureCasesProject\n  writeFileUtf8 (src </> \"a.act\") \"aaa = 1\\n\"\n  writeFileUtf8 (src </> \"b.act\") $ T.unlines\n    [ \"import a\"\n    , \"\"\n    , \"def bar() -> int:\"\n    , \"    return a.aaa\"\n    ]\n  writeFileUtf8 (src </> \"c.act\") $ T.unlines\n    [ \"import b\"\n    , \"\"\n    , \"actor main(env: Env):\"\n    , \"    b.bar()\"\n    , \"    env.exit(0)\"\n    ]\n  _ <- buildOutIn proj\n  writeFileUtf8 (src </> \"a.act\") \"aaa = 2\\n\"\n  res2@(ec2, out2) <- runActonIn proj [\"build\", \"--color\", \"never\", \"--verbose\", \"--only-build\"]\n  assertExitSuccess \"only-build\" res2\n  assertBool \"did not expect a.act to type check\" (not (typechecked out2 modA))\n  assertBool \"did not expect b.act to type check\" (not (typechecked out2 modB))\n  assertBool \"did not expect c.act to type check\" (not (typechecked out2 modC))\n  assertBool \"did not expect b.act to compile codegen\" (not (compiled out2 modB))\n  assertBool \"did not expect c.act to compile codegen\" (not (compiled out2 modC))\n\n  writeFileUtf8 (src </> \"b.act\") $ T.unlines\n    [ \"import a\"\n    , \"\"\n    , \"def bar() -> int:\"\n    , \"    return a.aaa\"\n    , \")\"\n    ]\n  res3@(ec3, out3) <- runActonIn proj [\"build\", \"--color\", \"never\", \"--verbose\", \"--only-build\"]\n  assertExitSuccess \"only-build with invalid body\" res3\n  assertBool \"did not expect invalid b.act to type check in only-build\" (not (typechecked out3 modB))\n  assertBool \"did not expect c.act to type check after invalid b.act in only-build\" (not (typechecked out3 modC))\n  assertBool \"did not expect parse diagnostics in only-build\" (not (\"Syntax error\" `T.isInfixOf` out3))\n\np31_always_build :: TestTree\np31_always_build = testCase \"31-always-build forces front passes\" $ do\n  let proj = casesProjDir\n      src = casesSrcDir\n      modA = modLabel proj \"a\"\n      modB = modLabel proj \"b\"\n      modC = modLabel proj \"c\"\n  ensureCasesProject\n  writeFileUtf8 (src </> \"a.act\") \"aaa = 1\\n\"\n  writeFileUtf8 (src </> \"b.act\") $ T.unlines\n    [ \"import a\"\n    , \"\"\n    , \"def bar() -> int:\"\n    , \"    return a.aaa\"\n    ]\n  writeFileUtf8 (src </> \"c.act\") $ T.unlines\n    [ \"import b\"\n    , \"\"\n    , \"actor main(env: Env):\"\n    , \"    b.bar()\"\n    , \"    env.exit(0)\"\n    ]\n  _ <- buildOutIn proj\n  out <- buildOutInArgs proj [\"--always-build\"]\n  assertBool \"expected a.act to type check\" (typechecked out modA)\n  assertBool \"expected b.act to type check\" (typechecked out modB)\n  assertBool \"expected c.act to type check\" (typechecked out modC)\n\np32_project_alt_output :: TestTree\np32_project_alt_output = testCase \"32-project --types emits output\" $ do\n  let proj = casesProjDir\n      src = casesSrcDir\n  ensureCasesProject\n  writeFileUtf8 (src </> \"a.act\") \"aaa = 1\\n\"\n  writeFileUtf8 (src </> \"c.act\") $ T.unlines\n    [ \"import a\"\n    , \"\"\n    , \"actor main(env: Env):\"\n    , \"    print(a.aaa)\"\n    , \"    env.exit(0)\"\n    ]\n  _ <- buildOutIn proj\n  res@(ec, out) <- runActonIn proj [\"build\", \"--color\", \"never\", \"--types\"]\n  assertExitSuccess \"project types\" res\n  assertBool \"expected types dump\" (T.isInfixOf \"== types:\" out)\n\np33_comprehensive_hashes :: TestTree\np33_comprehensive_hashes = testCase \"33-comprehensive hash propagation\" $ do\n  let proj = casesProjDir\n      src = casesSrcDir\n      modA = modLabel proj \"a\"\n      modB = modLabel proj \"b\"\n      modC = modLabel proj \"c\"\n      tyA = proj </> \"out\" </> \"types\" </> \"a.ty\"\n      tyB = proj </> \"out\" </> \"types\" </> \"b.ty\"\n  ensureCasesProjectWithDeps [(\"libfoo\", \"deps/libfoo\")]\n  depDir <- ensureDepProject proj \"libfoo\"\n  let depSrc = depDir </> \"src\" </> \"libfoo.act\"\n      libfooSource depConst addBonus =\n        let bonusLines =\n              if addBonus\n                then [ \"    bonus : () -> int\"\n                     , \"    def bonus(self) -> int:\"\n                     , \"        return self.mega() + 1\"\n                     ]\n                else []\n        in T.unlines $ concat\n            [ [ \"protocol BaseProto:\"\n              , \"    base : () -> int\"\n              , \"    def base(self) -> int:\"\n              , \"        return 1\"\n              , \"\"\n              , \"protocol ExtraProto:\"\n              , \"    extra : () -> int\"\n              , \"    def extra(self) -> int:\"\n              , \"        return 2\"\n              , \"\"\n              , \"protocol MegaProto (BaseProto, ExtraProto):\"\n              , \"    mega : () -> int\"\n              , \"    def mega(self) -> int:\"\n              , \"        return self.base() + self.extra()\"\n              ]\n            , bonusLines\n            , [ \"\"\n              , \"class DepClass:\"\n              , \"    def __init__(self, v: int):\"\n              , \"        self.v = v\"\n              , \"    def base(self) -> int:\"\n              , \"        return self.v\"\n              , \"    def extra(self) -> int:\"\n              , \"        return self.v + 1\"\n              , \"\"\n              , \"extension DepClass(MegaProto):\"\n              , \"    def mega(self) -> int:\"\n              , \"        return self.base() + self.extra()\"\n              , \"\"\n              , \"dep_const = \" <> T.pack (show depConst)\n              , \"\"\n              , \"def dep_value() -> int:\"\n              , \"    return DepClass(dep_const).mega()\"\n              ]\n            ]\n  writeFileUtf8 depSrc (libfooSource 5 False)\n  writeFileUtf8 (src </> \"a.act\") $ T.unlines\n    [ \"import libfoo\"\n    , \"\"\n    , \"const = 7\"\n    , \"x, y = 1, 2\"\n    , \"\"\n    , \"def add(n: int) -> int:\"\n    , \"    return n + const\"\n    , \"\"\n    , \"class Local:\"\n    , \"    def __init__(self, v: int):\"\n    , \"        self.v = v\"\n    , \"    def get(self) -> int:\"\n    , \"        return self.v\"\n    , \"\"\n    , \"actor Worker(v: int):\"\n    , \"    pass\"\n    , \"\"\n    , \"def dep_call() -> int:\"\n    , \"    return libfoo.dep_value()\"\n    ]\n  writeFileUtf8 (src </> \"b.act\") $ T.unlines\n    [ \"import a\"\n    , \"import libfoo\"\n    , \"\"\n    , \"def use_types(x: a.Local, w: a.Worker) -> int:\"\n    , \"    return a.add(x.get())\"\n    , \"\"\n    , \"def use_values() -> int:\"\n    , \"    return a.add(libfoo.dep_const) + a.dep_call()\"\n    , \"\"\n    , \"def use_method(x: a.Local) -> int:\"\n    , \"    return x.get()\"\n    , \"\"\n    , \"def use_actor(w: a.Worker) -> int:\"\n    , \"    return 0\"\n    ]\n  writeFileUtf8 (src </> \"c.act\") $ T.unlines\n    [ \"import a\"\n    , \"import b\"\n    , \"\"\n    , \"actor main(env: Env):\"\n    , \"    l = a.Local(3)\"\n    , \"    print(b.use_values() + b.use_method(l))\"\n    , \"    env.exit(0)\"\n    ]\n  _ <- buildOutIn proj\n  let tyDep = depDir </> \"out\" </> \"types\" </> \"libfoo.ty\"\n  depNameHashes <- readTyNameHashes tyDep\n  let depNames = sort (map (prstr . InterfaceFiles.nhName) depNameHashes)\n  assertBool \"expected derived proto name\" (\"ExtraProtoD_MegaProto\" `elem` depNames)\n  assertBool \"expected extension name\" (\"MegaProtoD_DepClass\" `elem` depNames)\n  case find (\\nh -> prstr (InterfaceFiles.nhName nh) == \"ExtraProtoD_MegaProto\") depNameHashes of\n    Nothing -> assertFailure \"missing ExtraProtoD_MegaProto in libfoo\"\n    Just nh ->\n      assertBool \"expected empty pub hash for derived proto\" (B.null (InterfaceFiles.nhPubHash nh))\n  (pubTypes, implTypes) <- readTyDeps tyB \"use_types\"\n  assertDepsContain \"use_types pub deps\" [\"a.Local\", \"a.Worker\", \"a.add\"] pubTypes\n  assertDepsContain \"use_types impl deps\" [\"a.add\"] implTypes\n  (pubVals, implVals) <- readTyDeps tyB \"use_values\"\n  assertDepsContain \"use_values pub deps\" [\"a.add\", \"a.dep_call\", \"libfoo.dep_const\"] pubVals\n  assertDepsContain \"use_values impl deps\" [\"a.add\", \"a.dep_call\", \"libfoo.dep_const\"] implVals\n  (pubActor, _) <- readTyDeps tyB \"use_actor\"\n  assertDepsContain \"use_actor pub deps\" [\"a.Worker\"] pubActor\n  (_, implDepCall) <- readTyDeps tyA \"dep_call\"\n  assertDepsContain \"dep_call impl deps\" [\"libfoo.dep_value\"] implDepCall\n  out1 <- runBinaryIn proj \"c\"\n  out1 @?= \"26\\n\"\n  writeFileUtf8 depSrc (libfooSource 5 True)\n  out2 <- buildOutIn proj\n  assertBool \"did not expect a.act to type check\" (not (typechecked out2 modA))\n  assertBool \"did not expect b.act to type check\" (not (typechecked out2 modB))\n  assertBool \"did not expect c.act to type check\" (not (typechecked out2 modC))\n  out2Run <- runBinaryIn proj \"c\"\n  out2Run @?= \"26\\n\"\n  writeFileUtf8 depSrc (libfooSource 8 True)\n  out3 <- buildOutIn proj\n  assertBool \"did not expect a.act to type check\" (not (typechecked out3 modA))\n  assertBool \"did not expect b.act to type check\" (not (typechecked out3 modB))\n  assertBool \"did not expect c.act to type check\" (not (typechecked out3 modC))\n  assertBool \"expected a.act to compile codegen\" (compiled out3 modA)\n  assertBool \"expected b.act to compile codegen\" (compiled out3 modB)\n  assertBool \"expected c.act to compile codegen\" (compiled out3 modC)\n  out3Run <- runBinaryIn proj \"c\"\n  out3Run @?= \"35\\n\"\n\np34_removed_import_module :: TestTree\np34_removed_import_module = testCase \"34-removed imported module fails before Zig\" $ do\n  let proj = casesProjDir\n      src = casesSrcDir\n      outA = proj </> \"out\" </> \"types\" </> \"a\"\n  ensureCasesProject\n  writeFileUtf8 (src </> \"a.act\") \"aaa = 1\\n\"\n  writeFileUtf8 (src </> \"b.act\") $ T.unlines\n    [ \"import a\"\n    , \"\"\n    , \"def bar() -> int:\"\n    , \"    return a.aaa\"\n    ]\n  writeFileUtf8 (src </> \"c.act\") $ T.unlines\n    [ \"import b\"\n    , \"\"\n    , \"actor main(env: Env):\"\n    , \"    print(b.bar())\"\n    , \"    env.exit(0)\"\n    ]\n  _ <- buildOutIn proj\n  removeFile (src </> \"a.act\")\n  res@(ec, out) <- runActonIn proj [\"build\", \"--color\", \"never\", \"--verbose\"]\n  assertExitFailure \"build after deleting imported module\" 1 res\n  mapM_ (\\ext -> do\n    exists <- doesFileExist (outA ++ ext)\n    assertBool (\"did not expect stale generated \" ++ outA ++ ext) (not exists))\n    [\".ty\", \".c\", \".h\"]\n  assertBool \"expected missing import diagnostic\"\n    (T.isInfixOf \"Type interface file not found or unreadable for a\" out)\n  assertBool \"did not expect Zig build to run\" (not (T.isInfixOf \"zigCmd:\" out))\n\np35_changed_path_keeps_unaffected_provider :: TestTree\np35_changed_path_keeps_unaffected_provider =\n  testCase \"35-changed-path incremental keeps unchanged providers\" $ do\n    let proj = casesProjDir\n        src = casesSrcDir\n        actA = src </> \"a.act\"\n        actB = src </> \"b.act\"\n        actC = src </> \"c.act\"\n        actMain = src </> \"main.act\"\n        gopts = C.GlobalOptions\n          { C.color = C.Never\n          , C.quiet = True\n          , C.noProgress = False\n          , C.timing = False\n          , C.tty = False\n          , C.verbose = False\n          , C.verboseZig = False\n          , C.jobs = 1\n          }\n        opts = Compile.defaultCompileOptions { C.only_build = True }\n    ensureCasesProject\n    writeFileUtf8 actA \"aaa = 1\\n\"\n    writeFileUtf8 actC \"ccc = 10\\n\"\n    writeFileUtf8 actB $ T.unlines\n      [ \"import a\"\n      , \"import c\"\n      , \"\"\n      , \"def bar() -> int:\"\n      , \"    return a.aaa + c.ccc\"\n      ]\n    writeFileUtf8 actMain $ T.unlines\n      [ \"import b\"\n      , \"\"\n      , \"actor main(env: Env):\"\n      , \"    print(b.bar())\"\n      , \"    env.exit(0)\"\n      ]\n    _ <- buildOutIn proj\n    writeFileUtf8 actA \"aaa = 2\\n\"\n    actAAbs <- canonicalizePath actA\n    actMainAbs <- canonicalizePath actMain\n    sched <- Compile.newCompileScheduler gopts 1\n    plan <- Compile.prepareCompilePlan\n      Source.diskSourceProvider\n      gopts\n      sched\n      opts\n      [actMainAbs]\n      False\n      (Just [actAAbs])\n    bTask <- case find (\\t -> Compile.name (Compile.gtTask t) == A.modName [\"b\"]) (Compile.cpNeededTasks plan) of\n      Just t -> pure t\n      Nothing -> assertFailure \"expected b in changed-path compile plan\" >> fail \"missing b task\"\n    let bProviders = Compile.gtImportProviders bTask\n    assertBool \"expected provider for changed import a\" (M.member (A.modName [\"a\"]) bProviders)\n    assertBool \"expected provider for unchanged import c\" (M.member (A.modName [\"c\"]) bProviders)\n\np36_removed_dep_name_triggers_front_refresh :: TestTree\np36_removed_dep_name_triggers_front_refresh =\n  testCase \"36-removed dep name forces front refresh\" $ do\n    let proj = casesProjDir\n        src = casesSrcDir\n    ensureCasesProjectWithDeps [(\"libfoo\", \"deps/libfoo\")]\n    depDir <- ensureDepProject proj \"libfoo\"\n    let depSrc = depDir </> \"src\" </> \"libfoo.act\"\n    writeFileUtf8 depSrc $ T.unlines\n      [ \"def foo() -> int:\"\n      , \"    return 1\"\n      ]\n    writeFileUtf8 (src </> \"main.act\") $ T.unlines\n      [ \"import libfoo\"\n      , \"\"\n      , \"actor main(env: Env):\"\n      , \"    print(libfoo.foo())\"\n      , \"    env.exit(0)\"\n      ]\n    res1 <- runActonIn proj [\"build\", \"--color\", \"never\", \"--skip-build\"]\n    assertExitSuccess \"initial build\" res1\n    writeFileUtf8 depSrc $ T.unlines\n      [ \"def bar() -> int:\"\n      , \"    return 2\"\n      ]\n    res2@(_ec2, out2) <- runActonIn proj [\"build\", \"--color\", \"never\", \"--verbose\", \"--skip-build\"]\n    assertExitFailure \"rebuild after removing imported dep name\" 1 res2\n    assertBool \"expected stale-cache log for missing dep hash\"\n      (T.isInfixOf \"missing dep hashes in\" out2 && T.isInfixOf \"libfoo.foo\" out2)\n    assertBool \"did not expect internal hash-missing diagnostic\"\n      (not (T.isInfixOf \"Hash info missing for libfoo.foo\" out2))\n\np37_impl_refresh_missing_dep_hashes_reruns_front :: TestTree\np37_impl_refresh_missing_dep_hashes_reruns_front =\n  testCase \"37-impl refresh missing dep hashes reruns front passes\" $ do\n    let proj = casesProjDir\n        src = casesSrcDir\n        modMain = modLabel proj \"main\"\n    ensureCasesProjectWithDeps [(\"libfoo\", \"deps/libfoo\")]\n    depDir <- ensureDepProject proj \"libfoo\"\n    let depSrc = depDir </> \"src\" </> \"libfoo.act\"\n        tyMain = proj </> \"out\" </> \"types\" </> \"main.ty\"\n    writeFileUtf8 depSrc $ T.unlines\n      [ \"def foo() -> int:\"\n      , \"    return 1\"\n      , \"\"\n      , \"def bar() -> int:\"\n      , \"    return 2\"\n      ]\n    writeFileUtf8 (src </> \"main.act\") $ T.unlines\n      [ \"import libfoo\"\n      , \"\"\n      , \"def value() -> int:\"\n      , \"    return libfoo.foo() + libfoo.bar()\"\n      , \"\"\n      , \"actor main(env: Env):\"\n      , \"    print(value())\"\n      , \"    env.exit(0)\"\n      ]\n    res1 <- runActonIn proj [\"build\", \"--color\", \"never\", \"--skip-build\"]\n    assertExitSuccess \"initial build\" res1\n    let mainV2 = T.unlines\n          [ \"import libfoo\"\n          , \"\"\n          , \"def value() -> int:\"\n          , \"    return libfoo.foo()\"\n          , \"\"\n          , \"actor main(env: Env):\"\n          , \"    print(value())\"\n          , \"    env.exit(0)\"\n          ]\n    writeFileUtf8 (src </> \"main.act\") mainV2\n    rewriteTySrcHashAndNameHashes tyMain (SHA256.hash (TE.encodeUtf8 mainV2)) (dropTyDepByLabel \"libfoo.bar\")\n    writeFileUtf8 depSrc $ T.unlines\n      [ \"def foo() -> int:\"\n      , \"    return 10\"\n      ]\n    res2@(_ec2, out2) <- runActonIn proj [\"build\", \"--color\", \"never\", \"--verbose\", \"--skip-build\"]\n    assertExitSuccess \"rebuild after impl refresh dep hash miss\" res2\n    assertBool (\"expected impl-refresh fallback log\\n\" ++ T.unpack out2)\n      (T.isInfixOf \"impl refresh encountered unresolved dep hashes; rerunning front passes\" out2)\n    assertBool (\"did not expect internal hash-missing diagnostic\\n\" ++ T.unpack out2)\n      (not (T.isInfixOf \"Hash info missing for libfoo.bar\" out2))\n    assertBool (\"did not expect internal NoItem failure\\n\" ++ T.unpack out2)\n      (not (T.isInfixOf \"NoItem\" out2))\n    assertBool (\"expected main.act to type check after fallback\\n\" ++ T.unpack out2) (typechecked out2 modMain)\n\np38_project_lock_blocks_build :: TestTree\np38_project_lock_blocks_build =\n  testCase \"38-project lock blocks concurrent build\" $ do\n    let proj = casesProjDir\n        src = casesSrcDir\n    ensureCasesProject\n    writeFileUtf8 (src </> \"main.act\") $ T.unlines\n      [ \"actor main(env: Env):\"\n      , \"    env.exit(0)\"\n      ]\n    actonExe <- actonPath\n    res <- Compile.withProjectLock proj $ do\n      (_, mOut, mErr, ph) <- createProcess\n        (proc actonExe [\"build\", \"--color\", \"never\", \"--jobs\", \"1\"])\n          { cwd = Just proj\n          , std_out = CreatePipe\n          , std_err = CreatePipe\n          }\n      let outH = requirePipe \"stdout\" mOut\n          errH = requirePipe \"stderr\" mErr\n      (do\n          threadDelay 500000\n          mExit <- getProcessExitCode ph\n          case mExit of\n            Nothing -> pure ()\n            Just ec -> assertFailure (\"build should have blocked on .acton.lock, exited early with \" ++ show ec)\n          pure (ph, outH, errH))\n        `E.onException` do\n          terminateProcess ph\n          _ <- waitForProcess ph\n          pure ()\n    let (ph, outH, errH) = res\n    ec <- waitForProcess ph\n    out <- T.hGetContents outH\n    err <- T.hGetContents errH\n    assertEqual \"build should succeed after lock is released\" ExitSuccess ec\n    let combined = out <> err\n    assertBool (\"expected wait message while build was blocked\\n\" ++ T.unpack combined)\n      (T.isInfixOf \"Waiting for compiler lock in\" combined)\n  where\n    requirePipe :: String -> Maybe Handle -> Handle\n    requirePipe label =\n      maybe (error (\"missing \" ++ label ++ \" pipe for lock wait test\")) id\n\np39_background_lock_does_not_block_build :: TestTree\np39_background_lock_does_not_block_build =\n  testCase \"39-background compiler lock does not block build\" $ do\n    let proj = casesProjDir\n        src = casesSrcDir\n    ensureCasesProject\n    writeFileUtf8 (src </> \"main.act\") $ T.unlines\n      [ \"actor main(env: Env):\"\n      , \"    env.exit(0)\"\n      ]\n    withBackgroundCompilerLockHeld proj $ do\n      res@(_ec, out) <- runActonIn proj [\"build\", \"--color\", \"never\", \"--verbose\"]\n      assertExitSuccess \"build should run under .acton.compile.lock\" res\n      assertBool (\"expected build to rerun front passes while background lock is held\\n\" ++ T.unpack out)\n        (typechecked out \"main\")\n\np40_background_lock_blocks_watch :: TestTree\np40_background_lock_blocks_watch =\n  testCase \"40-background compiler lock blocks watch\" $ do\n    let proj = casesProjDir\n        src = casesSrcDir\n    ensureCasesProject\n    writeFileUtf8 (src </> \"main.act\") $ T.unlines\n      [ \"actor main(env: Env):\"\n      , \"    env.exit(0)\"\n      ]\n    withBackgroundCompilerLockHeld proj $ do\n      actonExe <- actonPath\n      (_, _, _, ph) <- createProcess (proc actonExe [\"build\", \"--watch\", \"--color\", \"never\", \"--jobs\", \"1\"]) { cwd = Just proj }\n      (do\n          threadDelay 500000\n          mExit <- getProcessExitCode ph\n          case mExit of\n            Nothing -> do\n              terminateProcess ph\n              _ <- waitForProcess ph\n              assertFailure \"watch should fail quickly when .acton.compile.lock is already held\"\n            Just ExitSuccess ->\n              assertFailure \"watch should not succeed when .acton.compile.lock is already held\"\n            Just (ExitFailure _) ->\n              pure ())\n        `E.onException` do\n          terminateProcess ph\n          _ <- waitForProcess ph\n          pure ()\n\np41_stale_header_missing_import_reparses_source :: TestTree\np41_stale_header_missing_import_reparses_source =\n  testCase \"41-stale header missing import reparses source\" $ do\n    let proj = casesProjDir\n        src = casesSrcDir\n        actA = src </> \"a.act\"\n        actB = src </> \"b.act\"\n        tyB = proj </> \"out\" </> \"types\" </> \"b.ty\"\n        outA = proj </> \"out\" </> \"types\" </> \"a\"\n        modB = modLabel proj \"b\"\n    ensureCasesProject\n    writeFileUtf8 actA \"aaa = 1\\n\"\n    writeFileUtf8 actB $ T.unlines\n      [ \"import a\"\n      , \"\"\n      , \"def bar() -> int:\"\n      , \"    return a.aaa\"\n      ]\n    writeFileUtf8 (src </> \"main.act\") $ T.unlines\n      [ \"import b\"\n      , \"\"\n      , \"actor main(env: Env):\"\n      , \"    print(b.bar())\"\n      , \"    env.exit(0)\"\n      ]\n    _ <- buildOutIn proj\n    writeFileUtf8 actB $ T.unlines\n      [ \"def bar() -> int:\"\n      , \"    return 7\"\n      ]\n    tyTime <- getModificationTime tyB\n    setModificationTime actB (addUTCTime (-10) tyTime)\n    removeFile actA\n    res@(_ec, out) <- runActonIn proj [\"build\", \"--color\", \"never\", \"--verbose\"]\n    assertExitSuccess \"build after stale header import removal\" res\n    mapM_ (\\ext -> do\n      exists <- doesFileExist (outA ++ ext)\n      assertBool (\"did not expect stale generated \" ++ outA ++ ext) (not exists))\n      [\".ty\", \".c\", \".h\"]\n    assertBool \"expected b.act to type check after stale header reparse\"\n      (typechecked out modB)\n    assertBool (\"did not expect stale import diagnostic\\n\" ++ T.unpack out)\n      (not (T.isInfixOf \"Type interface file not found or unreadable for a\" out))\n\np42_metadata_drift_refreshes_header :: TestTree\np42_metadata_drift_refreshes_header =\n  testCase \"42-metadata drift refreshes header\" $ do\n    let proj = casesProjDir\n        src = casesSrcDir\n        actA = src </> \"a.act\"\n        tyA = proj </> \"out\" </> \"types\" </> \"a.ty\"\n        modA = modLabel proj \"a\"\n    ensureCasesProject\n    writeFileUtf8 actA \"aaa = 1\\n\"\n    writeFileUtf8 (src </> \"main.act\") $ T.unlines\n      [ \"import a\"\n      , \"\"\n      , \"actor main(env: Env):\"\n      , \"    print(a.aaa)\"\n      , \"    env.exit(0)\"\n      ]\n    _ <- buildOutIn proj\n    metaBefore <- readTySourceMeta tyA\n    threadDelay 1000000\n    touch actA\n    out <- buildOutIn proj\n    metaAfter <- readTySourceMeta tyA\n    currentMeta <- sourceFileMetaForPath actA\n    assertBool \"did not expect a.act to type check after metadata-only drift\"\n      (not (typechecked out modA))\n    assertBool \"expected .ty header to carry source metadata\"\n      (isJust metaAfter)\n    assertBool \"expected metadata drift to update cached source metadata\"\n      (metaBefore /= metaAfter)\n    metaAfter @?= Just currentMeta\n\np43_equal_act_ty_mtime_hashes_source :: TestTree\np43_equal_act_ty_mtime_hashes_source =\n  testCase \"43-equal act/ty mtimes still hash source\" $ do\n    let proj = casesProjDir\n        src = casesSrcDir\n        actA = src </> \"a.act\"\n        actB = src </> \"b.act\"\n        tyB = proj </> \"out\" </> \"types\" </> \"b.ty\"\n        outA = proj </> \"out\" </> \"types\" </> \"a\"\n        modB = modLabel proj \"b\"\n    ensureCasesProject\n    writeFileUtf8 actA \"aaa = 1\\n\"\n    writeFileUtf8 actB $ T.unlines\n      [ \"import a\"\n      , \"\"\n      , \"def bar() -> int:\"\n      , \"    return a.aaa\"\n      ]\n    writeFileUtf8 (src </> \"main.act\") $ T.unlines\n      [ \"import b\"\n      , \"\"\n      , \"actor main(env: Env):\"\n      , \"    print(b.bar())\"\n      , \"    env.exit(0)\"\n      ]\n    _ <- buildOutIn proj\n    writeFileUtf8 actB $ T.unlines\n      [ \"def bar() -> int:\"\n      , \"    return 7\"\n      ]\n    rewriteTySourceMeta tyB Nothing\n    tyStatus <- getFileStatus tyB\n    let tyMTimeNs = floor (toRational (modificationTimeHiRes tyStatus) * 1000000000)\n    setFileMTimeNs actB tyMTimeNs\n    currentMeta <- sourceFileMetaForPath actB\n    rewriteTySourceMeta tyB (Just currentMeta)\n    setFileMTimeNs tyB tyMTimeNs\n    metaAfter <- readTySourceMeta tyB\n    metaAfter @?= Just currentMeta\n    removeFile actA\n    res@(_ec, out) <- runActonIn proj [\"build\", \"--color\", \"never\", \"--verbose\"]\n    assertExitSuccess \"build after equal act/ty mtime stale header\" res\n    mapM_ (\\ext -> do\n      exists <- doesFileExist (outA ++ ext)\n      assertBool (\"did not expect stale generated \" ++ outA ++ ext) (not exists))\n      [\".ty\", \".c\", \".h\"]\n    assertBool \"expected b.act to type check after equal-mtime hash check\"\n      (typechecked out modB)\n    assertBool (\"did not expect stale import diagnostic\\n\" ++ T.unpack out)\n      (not (T.isInfixOf \"Type interface file not found or unreadable for a\" out))\n\np44_provider_import_rename_reruns_dependent_front :: TestTree\np44_provider_import_rename_reruns_dependent_front =\n  testCase \"44-provider import rename reruns dependent front passes\" $ do\n    let proj = casesProjDir\n        src = casesSrcDir\n        actMain = src </> \"main.act\"\n        actBase = src </> \"base.act\"\n        oldPkgDir = src </> \"oldpkg\"\n        newPkgDir = src </> \"newpkg\"\n        modMain = modLabel proj \"main\"\n        modBase = modLabel proj \"base\"\n    ensureCasesProject\n    createDirectoryIfMissing True oldPkgDir\n    writeFileUtf8 actMain $ T.unlines\n      [ \"import base\"\n      , \"\"\n      , \"class Derived(base.Base):\"\n      , \"    pass\"\n      , \"\"\n      , \"actor main(env: Env):\"\n      , \"    env.exit(0)\"\n      ]\n    writeFileUtf8 actBase $ T.unlines\n      [ \"import oldpkg.ttt as ttt\"\n      , \"\"\n      , \"class Base(ttt.TransformFunction):\"\n      , \"    pass\"\n      ]\n    writeFileUtf8 (src </> \"oldpkg.act\") \"\"\n    writeFileUtf8 (oldPkgDir </> \"ttt.act\") $ T.unlines\n      [ \"class TransformFunction(object):\"\n      , \"    pass\"\n      ]\n    res1 <- runActonIn proj [\"build\", \"--color\", \"never\", \"--skip-build\"]\n    assertExitSuccess \"initial build before provider import rename\" res1\n    createDirectoryIfMissing True newPkgDir\n    writeFileUtf8 actBase $ T.unlines\n      [ \"import newpkg.ttt as ttt\"\n      , \"\"\n      , \"class Base(ttt.TransformFunction):\"\n      , \"    pass\"\n      ]\n    writeFileUtf8 (src </> \"newpkg.act\") \"\"\n    writeFileUtf8 (newPkgDir </> \"ttt.act\") $ T.unlines\n      [ \"class TransformFunction(object):\"\n      , \"    pass\"\n      ]\n    removeFile (src </> \"oldpkg.act\")\n    removeFile (oldPkgDir </> \"ttt.act\")\n    removeDirIfExists oldPkgDir\n    res2@(_ec2, out2) <- runActonIn proj [\"build\", \"--color\", \"never\", \"--verbose\", \"--skip-build\"]\n    assertExitSuccess \"rebuild after provider import rename\" res2\n    assertBool (\"expected base.act to type check after provider import rename\\n\" ++ T.unpack out2)\n      (typechecked out2 modBase)\n    assertBool (\"expected main.act to type check after provider import rename\\n\" ++ T.unpack out2)\n      (typechecked out2 modMain)\n    assertBool (\"did not expect stale transitive import diagnostic\\n\" ++ T.unpack out2)\n      (not (T.isInfixOf \"Type interface file not found or unreadable for oldpkg.ttt\" out2))\n    assertBool (\"expected stale-cache log for missing transitive dep hash\\n\" ++ T.unpack out2)\n      (T.isInfixOf \"missing dep hashes in\" out2 && T.isInfixOf \"oldpkg.ttt.TransformFunction\" out2)\n\n-- Main -----------------------------------------------------------------------\n\n-- | Tasty entry point for incremental tests.\nmain :: IO ()\nmain = defaultMain $ localOption (NumThreads 1) $ testGroup \"incremental\"\n  [ sequentialTestGroup \"incremental-project\" AllSucceed\n      [ p01_init\n      , p02_initial_build\n      , p03_up_to_date\n      , p04_touch_no_rebuild\n      , p05_run_123\n      , p06_change_a_impl\n      , p06_impl_change_fresh\n      , p07_run_124\n      , p08_change_b_impl\n      , p09_run_124\n      , p10_change_a_iface\n      , p11_change_b_doc\n      , p12_codegen_stale\n  ]\n  , sequentialTestGroup \"incremental-file\" AllSucceed\n      [ f01_init\n      , f02_initial_build\n      , f03_up_to_date\n      , f04_touch_no_rebuild\n      , f05_run_123\n      , f06_change_a_impl\n      , f07_run_124\n      , f08_change_b_impl\n      , f09_run_124\n      , f10_alt_output\n      ]\n  , sequentialTestGroup \"incremental-project-cases\" AllSucceed\n      [ p14_partial_rebuild\n      , p15_rebuild_import\n      , p16_dep_api_change\n      , p17_dep_impl_change\n      , p18_type_only_deps\n      , p19_unused_import\n      , p20_add_remove_names\n      , p21_recursive_group\n      , p22_multibind\n      , p23_codegen_mismatch\n      , p24_codegen_equal_hash\n      , p25_whitespace_change\n      , p26_corrupt_ty_header\n      , p26_ty_version_mismatch\n      , p27_overlay_source_provider\n      , p28_protocol_extension_deps\n      , p29_protocol_impl_rebuild\n      , p30_only_build\n      , p31_always_build\n      , p32_project_alt_output\n      , p33_comprehensive_hashes\n      , p34_removed_import_module\n      , p35_changed_path_keeps_unaffected_provider\n      , p36_removed_dep_name_triggers_front_refresh\n      , p37_impl_refresh_missing_dep_hashes_reruns_front\n      , p38_project_lock_blocks_build\n      , p39_background_lock_does_not_block_build\n      , p40_background_lock_blocks_watch\n      ]\n  , sequentialTestGroup \"incremental-cache-cases\" AllSucceed\n      [ p41_stale_header_missing_import_reparses_source\n      , p42_metadata_drift_refreshes_header\n      , p43_equal_act_ty_mtime_hashes_source\n      , p44_provider_import_rename_reruns_dependent_front\n      ]\n  ]\n"
  },
  {
    "path": "compiler/acton/test_online.hs",
    "content": "import Control.Exception (finally)\nimport qualified Data.Map as M\nimport System.Directory (canonicalizePath)\nimport System.Environment (lookupEnv, setEnv, unsetEnv)\nimport System.Exit\nimport System.FilePath\nimport System.IO.Temp (withSystemTempDirectory)\nimport System.Process\n\nimport Test.Tasty\nimport Test.Tasty.HUnit\n\nimport Data.Bits (shiftL, (.|.))\nimport Data.Word (Word64)\nimport qualified Acton.BuildSpec as BuildSpec\nimport qualified Acton.Fingerprint as Fingerprint\n\nmain :: IO ()\nmain = defaultMain $ testGroup \"Online tests\" [pkgCliIntegrationTests]\n\nfingerprintForName :: String -> String\nfingerprintForName name =\n  let prefix = Fingerprint.fingerprintPrefixForName name\n      fp = (fromIntegral prefix `shiftL` 32) .|. (1 :: Word64)\n  in Fingerprint.formatFingerprint fp\n\nwriteBuildAct :: FilePath -> String -> IO ()\nwriteBuildAct dir name = do\n  let fp = fingerprintForName name\n      content = unlines\n        [ \"name = \\\"\" ++ name ++ \"\\\"\"\n        , \"fingerprint = \" ++ fp\n        , \"\"\n        , \"dependencies = {}\"\n        , \"\"\n        , \"zig_dependencies = {}\"\n        , \"\"\n        ]\n  writeFile (dir </> \"Build.act\") content\n\nreadBuildSpecAct :: FilePath -> IO BuildSpec.BuildSpec\nreadBuildSpecAct path = do\n  content <- readFile path\n  case BuildSpec.parseBuildAct content of\n    Left err -> assertFailure err >> error \"unreachable\"\n    Right (spec, _, _) -> return spec\n\npkgCliIntegrationTests :: TestTree\npkgCliIntegrationTests =\n  testGroup \"pkg CLI integration\"\n  [ testCase \"pkg add/upgrade/remove (network)\" $ do\n        withTempHome $ \\_ ->\n          withSystemTempDirectory \"acton-pkg\" $ \\proj -> do\n            let depName = \"foo\"\n                repoUrl = \"https://github.com/actonlang/foo\"\n                projName = \"acton_pkg_test\"\n            writeBuildAct proj projName\n            (codeAdd, outAdd, errAdd) <- runActonIn proj [\"pkg\", \"add\", depName, \"--repo-url\", repoUrl]\n            assertExit \"pkg add\" ExitSuccess codeAdd outAdd errAdd\n            spec1 <- readBuildSpecAct (proj </> \"Build.act\")\n            dep1 <- requirePkgDep spec1 depName\n            assertEqual \"repo_url\" (Just repoUrl) (BuildSpec.repo_url dep1)\n            assertBool \"url set\" (hasText (BuildSpec.url dep1))\n            assertBool \"hash set\" (hasText (BuildSpec.hash dep1))\n\n            (codeUp, outUp, errUp) <- runActonIn proj [\"pkg\", \"upgrade\"]\n            assertExit \"pkg upgrade\" ExitSuccess codeUp outUp errUp\n            spec2 <- readBuildSpecAct (proj </> \"Build.act\")\n            dep2 <- requirePkgDep spec2 depName\n            assertEqual \"repo_url after upgrade\" (Just repoUrl) (BuildSpec.repo_url dep2)\n\n            (codeRm, outRm, errRm) <- runActonIn proj [\"pkg\", \"remove\", depName]\n            assertExit \"pkg remove\" ExitSuccess codeRm outRm errRm\n            spec3 <- readBuildSpecAct (proj </> \"Build.act\")\n            assertBool \"dep removed\" (M.notMember depName (BuildSpec.dependencies spec3))\n  ]\n\nwithTempHome :: (FilePath -> IO a) -> IO a\nwithTempHome action =\n  withSystemTempDirectory \"acton-home\" $ \\home -> do\n    oldHome <- lookupEnv \"HOME\"\n    setEnv \"HOME\" home\n    action home `finally` restoreHome oldHome\n  where\n    restoreHome Nothing = unsetEnv \"HOME\"\n    restoreHome (Just val) = setEnv \"HOME\" val\n\nrunActonIn :: FilePath -> [String] -> IO (ExitCode, String, String)\nrunActonIn wd args = do\n    actonExe <- canonicalizePath \"../../dist/bin/acton\"\n    readCreateProcessWithExitCode (proc actonExe args){ cwd = Just wd } \"\"\n\nassertExit :: String -> ExitCode -> ExitCode -> String -> String -> IO ()\nassertExit label expected actual out err =\n    if actual == expected\n      then return ()\n      else assertFailure $ unlines\n        [ label ++ \" exit\"\n        , \"expected: \" ++ show expected\n        , \" but got: \" ++ show actual\n        , \"stdout:\"\n        , out\n        , \"stderr:\"\n        , err\n        ]\n\nrequirePkgDep :: BuildSpec.BuildSpec -> String -> IO BuildSpec.PkgDep\nrequirePkgDep spec depName =\n    case M.lookup depName (BuildSpec.dependencies spec) of\n      Nothing -> assertFailure (\"Missing dependency \" ++ depName) >> error \"unreachable\"\n      Just dep -> return dep\n\nhasText :: Maybe String -> Bool\nhasText val = maybe False (not . null) val\n"
  },
  {
    "path": "compiler/diagnose/.gitignore",
    "content": ".stack-work/\n*~\n\n*.lock\n# This is a lib, we'd rather not commit the lock file...\n"
  },
  {
    "path": "compiler/diagnose/LICENSE",
    "content": "Copyright Ghilain Bergeron (Mesabloo) (c) 2019-2020\n\nAll rights reserved.\n\nRedistribution and use in source and binary forms, with or without\nmodification, are permitted provided that the following conditions are met:\n\n    * Redistributions of source code must retain the above copyright\n      notice, this list of conditions and the following disclaimer.\n\n    * Redistributions in binary form must reproduce the above\n      copyright notice, this list of conditions and the following\n      disclaimer in the documentation and/or other materials provided\n      with the distribution.\n\n    * Neither the name of Ghilain Bergeron (Mesabloo) nor the names of other\n      contributors may be used to endorse or promote products derived\n      from this software without specific prior written permission.\n\nTHIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS\n\"AS IS\" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT\nLIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR\nA PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT\nOWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,\nSPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT\nLIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,\nDATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY\nTHEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE\nOF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
  },
  {
    "path": "compiler/diagnose/PATCHES.md",
    "content": "# Diagnose Vendor Notes\n\nBaseline: upstream `mesabloo/diagnose` commit `d3ffbb7f376ddc64f3f349fe3a6a8e49d405cde0`\n(`master`, package version `2.5.1`).\n\nThis baseline is newer than the Hackage `diagnose-2.5.1` release. It includes\nupstream PR #24, which removes the direct `text` dependency instead of forcing\nconsumers onto `text <=2.0`.\n\nMaintenance policy:\n\n- Treat this directory as a forkable upstream package, not project-specific code.\n- Keep local changes generic and suitable for a standalone `diagnose` fork or\n  upstream pull request.\n- Document each local patch here with its rationale.\n- Prefer separate commits for the upstream baseline import and each local patch.\n- If local changes grow beyond small dependency/build fixes, extract this\n  directory to a dedicated fork and pin this build to that repository commit.\n\nLocal patches:\n\n- None beyond vendoring this upstream snapshot and this note.\n"
  },
  {
    "path": "compiler/diagnose/README.md",
    "content": "# Error reporting made easy\n\nDiagnose is a small library used to report compiler/interpreter errors in a beautiful yet readable way.\nIt was in the beginning heavily inspired by [ariadne](https://github.com/zesterer/ariadne), but ended up quickly becoming its own thing.\n\nAs a great example, here's the output of the last test:\n\n![first example](./assets/real-world-example-unicode.png)\n\nIf you do not like unicode characters, or choose to target platforms which cannot output them natively;\nyou may alternatively print the whole diagnostic with ASCII characters, like this:\n\n![second example](./assets/real-world-example-ascii.png)\n\nColors are also optional, and you may choose not to print them.\n\n## Features\n\n- Show diagnostics with/without 8-bit colors, with/without Unicode characters\n- Inline and multiline markers are nicely displayed\n- The order of markers matters!\n  If there are multiple markers on the same line, they are ordered according to how they were put in each report\n- Reports spanning across multiple files are handled as well\n- Generic over the type of message which can be displayed, meaning that you can output custom data types as well as they can be pretty-printed\n- Diagnostics can be exported to JSON, if you don't quite like the rendering as it is, or if you need to transmit them to e.g. a website\n- Plug and play (mega)parsec integration and it magically works with your parsers!\n- Support for optional custom error codes, if you want to go the Rust way\n- Variable width Unicode characters are handled in a crossplatform manner\n- TAB characters have custom sizes specified when printing a diagnostic, so that *you* decide the width of a TAB, not your terminal emulator!\n- Colors can be tweaked thanks to the ability to export diagnostics as `Doc`uments\n\n## Usage\n\nYou only need to `import Error.Diagnose`, and everything should be ready to go.\nYou don't even need to `import Prettyprinter`, as it is already provided to you by `Error.Diagnose`!\n\n--------\n\nA diagnostic can be viewed as a collection of reports, spanning on files.\nThis is what the `Diagnostic` type embodies.\n\nIt is an instance of `Monoid`, which can be used to construct an empty\ndiagnostic (contains no reports, and has no files).\n\nThe second step is to add some reports.\nThere are two kinds of reports:\n- Error reports, created through `Err`\n- Warning reports, created by using `Warn`\n\nBoth of these fonctions have the following type:\n```haskell\n-- | An optional error code, shown right after @error@ or @warning@ in the square brackets\nMaybe msg ->\n-- | The main message, which is output at the top right after @[error]@ or @[warning]@\nmsg ->\n-- | A list of markers, along with the positions they span on\n[(Position, Marker msg)] ->\n-- | Some hints to be output at the bottom of the report\n[Note msg] ->\n-- | The created report\nReport msg\n```\n\nEach report contains markers, which are what underlines the code in the screenshots above.\nThey come in three flavors:\n- A `This` marker indicates the main reason of the error.\n  It is highlighted in red (for errors) or yellow (for warnings).\n  Ideally, there is only one per report, but this isn't strictly required.\n- A `Where` marker adds additional context to the error by adding highlighted code to the error.\n  This can be used to remind used that a variable was found of a given type earlier, or even where a previous declaration was found in another file.\n  This is output in blue by default.\n- A `Maybe` marker is probably the rarest one.\n  It is basically a way of suggesting fixes (as when GCC tells you that you probably mistyped a variable name).\n  These markers are highlighted in green.\n\nThe `Position` datatype is however required to be used with this library.\nIf you use another way of keeping track of position information, you will need to convert them to the `Position` datatype.\n\nOnce your reports are created, you will need to add them inside the diagnostic using `addReport`.\nYou will also need to put your files into the diagnostic with `addFile`, else lines won't be printed and you will get `<no-line>` in your reports.\n\nAfter all of this is done, you may choose to either:\n- print the diagnostic onto a file `Handle` (most likely `stdout` or `stderr`) using `printDiagnostic`;\n- create a `Doc`ument which can be further altered using `prettyDiagnostic`;\n- or export it to JSON with `diagnosticToJson` or the `ToJSON` class of Aeson (the output format is documented under the `diagnosticToJson` function).\n\n## Example\n\nHere is how the above screenshot was generated:\n```haskell\nlet beautifulExample =\n      err\n        Nothing\n        \"Could not deduce constraint 'Num(a)' from the current context\"\n        [ (Position (1, 25) (2, 6) \"somefile.zc\", This \"While applying function '+'\"),\n          (Position (1, 11) (1, 16) \"somefile.zc\", Where \"'x' is supposed to have type 'a'\"),\n          (Position (1, 8) (1, 9) \"somefile.zc\", Where \"type 'a' is bound here without constraints\")\n        ]\n        [\"Adding 'Num(a)' to the list of constraints may solve this problem.\"]\n        -- ^^^^ This is a 'Note' not a 'Hint', as specified by its 'IsString' instance\n\n-- Create the diagnostic\nlet diagnostic  = addFile mempty \"somefile.zc\" \"let id<a>(x : a) : a := x\\n  + 1\"\nlet diagnostic' = addReport diagnostic beautifulExample\n\n-- Print with unicode characters, and the default (colorful) style\nprintDiagnostic stdout WithUnicode 4 defaultStyle diagnostic'\n```\n\nMore examples are given in the [`test/rendering`](./test/rendering) folder (execute `stack test` to see the output).\n\n## TODO list\n\n<< empty, for now >>\n\n## License\n\nThis work is licensed under the BSD-3 clause license.\n\nCopyright (c) 2021-2022 Mesabloo, all rights reserved.\n"
  },
  {
    "path": "compiler/diagnose/diagnose.cabal",
    "content": "cabal-version: 1.12\n\n-- This file has been generated from package.yaml by hpack version 0.35.2.\n--\n-- see: https://github.com/sol/hpack\n\nname:           diagnose\nversion:        2.5.1\nsynopsis:       Beautiful error reporting done easily\ndescription:    This package provides a simple way of getting beautiful compiler/interpreter errors\n                using a very simple interface for the programmer.\n                .\n                A quick tutorial is available in the module \"Error.Diagnose\", which goes on most of the basis\n                of how to use it.\ncategory:       Error Reporting\nhomepage:       https://github.com/mesabloo/diagnose#readme\nbug-reports:    https://github.com/mesabloo/diagnose/issues\nauthor:         Ghilain Bergeron\nmaintainer:     Ghilain Bergeron\ncopyright:      2021-2022 Ghilain Bergeron\nlicense:        BSD3\nlicense-file:   LICENSE\nbuild-type:     Simple\nextra-source-files:\n    README.md\n\nsource-repository head\n  type: git\n  location: https://github.com/mesabloo/diagnose\n\nflag json\n  description: Allows exporting diagnostics as JSON. This is disabled by default as this relies on the very heavy dependency Aeson.\n  manual: True\n  default: False\n\nflag megaparsec-compat\n  description: Includes a small compatibility layer (in the module `Error.Diagnose.Compat.Megaparsec`) to transform megaparsec errors into reports for this library.\n  manual: True\n  default: False\n\nflag parsec-compat\n  description: Includes a small compatibility layer (in the module `Error.Diagnose.Compat.Parsec`) to transform parsec errors into reports for this library.\n  manual: True\n  default: False\n\nlibrary\n  exposed-modules:\n      Error.Diagnose\n      Error.Diagnose.Diagnostic\n      Error.Diagnose.Position\n      Error.Diagnose.Pretty\n      Error.Diagnose.Report\n      Error.Diagnose.Style\n  other-modules:\n      Data.List.Safe\n      Error.Diagnose.Compat.Hints\n      Error.Diagnose.Diagnostic.Internal\n      Error.Diagnose.Report.Internal\n      Paths_diagnose\n  hs-source-dirs:\n      src\n  default-extensions:\n      OverloadedStrings\n      LambdaCase\n      BlockArguments\n  ghc-options: -Wall -Wextra\n  build-depends:\n      array ==0.5.*\n    , base >=4.7 && <5\n    , data-default >=0.7 && <1\n    , dlist ==1.0.*\n    , hashable >=1.3 && <2\n    , prettyprinter >=1.7.0 && <2\n    , prettyprinter-ansi-terminal >=1.1.2 && <2\n    , unordered-containers >=0.2.11 && <0.3\n    , wcwidth >=0.0.1 && <1\n  default-language: Haskell2010\n  if flag(json)\n    cpp-options: -DUSE_AESON\n    build-depends:\n        aeson >=1.5 && <3\n      , bytestring >=0.9 && <1\n  if flag(megaparsec-compat)\n    build-depends:\n        containers ==0.6.*\n      , megaparsec >=9.0.0\n  if flag(parsec-compat)\n    build-depends:\n        parsec >=3.1.14\n  if flag(megaparsec-compat)\n    exposed-modules:\n        Error.Diagnose.Compat.Megaparsec\n  if flag(parsec-compat)\n    exposed-modules:\n        Error.Diagnose.Compat.Parsec\n\ntest-suite diagnose-megaparsec-tests\n  type: exitcode-stdio-1.0\n  main-is: Spec.hs\n  other-modules:\n      Instances\n      Repro6\n      Paths_diagnose\n  hs-source-dirs:\n      test/megaparsec\n  default-extensions:\n      OverloadedStrings\n      LambdaCase\n      BlockArguments\n  ghc-options: -Wall -Wextra -threaded -rtsopts -with-rtsopts=-N\n  build-depends:\n      array ==0.5.*\n    , base >=4.7 && <5\n    , data-default >=0.7 && <1\n    , diagnose\n    , dlist ==1.0.*\n    , hashable >=1.3 && <2\n    , prettyprinter >=1.7.0 && <2\n    , prettyprinter-ansi-terminal >=1.1.2 && <2\n    , text >=1.2 && <3\n    , unordered-containers >=0.2.11 && <0.3\n    , wcwidth >=0.0.1 && <1\n  default-language: Haskell2010\n  if flag(json)\n    cpp-options: -DUSE_AESON\n    build-depends:\n        aeson >=1.5 && <3\n      , bytestring >=0.9 && <1\n  if flag(megaparsec-compat)\n    build-depends:\n        containers ==0.6.*\n      , megaparsec >=9.0.0\n  if flag(parsec-compat)\n    build-depends:\n        parsec >=3.1.14\n  if !(flag(megaparsec-compat))\n    buildable: False\n\ntest-suite diagnose-parsec-tests\n  type: exitcode-stdio-1.0\n  main-is: Spec.hs\n  other-modules:\n      Repro2\n      Paths_diagnose\n  hs-source-dirs:\n      test/parsec\n  default-extensions:\n      OverloadedStrings\n      LambdaCase\n      BlockArguments\n  ghc-options: -Wall -Wextra -threaded -rtsopts -with-rtsopts=-N\n  build-depends:\n      array ==0.5.*\n    , base >=4.7 && <5\n    , data-default >=0.7 && <1\n    , diagnose\n    , dlist ==1.0.*\n    , hashable >=1.3 && <2\n    , prettyprinter >=1.7.0 && <2\n    , prettyprinter-ansi-terminal >=1.1.2 && <2\n    , text >=1.2 && <3\n    , unordered-containers >=0.2.11 && <0.3\n    , wcwidth >=0.0.1 && <1\n  default-language: Haskell2010\n  if flag(json)\n    cpp-options: -DUSE_AESON\n    build-depends:\n        aeson >=1.5 && <3\n      , bytestring >=0.9 && <1\n  if flag(megaparsec-compat)\n    build-depends:\n        containers ==0.6.*\n      , megaparsec >=9.0.0\n  if flag(parsec-compat)\n    build-depends:\n        parsec >=3.1.14\n  if !(flag(parsec-compat))\n    buildable: False\n\ntest-suite diagnose-rendering-tests\n  type: exitcode-stdio-1.0\n  main-is: Spec.hs\n  other-modules:\n      Paths_diagnose\n  hs-source-dirs:\n      test/rendering\n  default-extensions:\n      OverloadedStrings\n      LambdaCase\n      BlockArguments\n  ghc-options: -Wall -Wextra -threaded -rtsopts -with-rtsopts=-N\n  build-depends:\n      array ==0.5.*\n    , base >=4.7 && <5\n    , data-default >=0.7 && <1\n    , diagnose\n    , dlist ==1.0.*\n    , hashable >=1.3 && <2\n    , prettyprinter >=1.7.0 && <2\n    , prettyprinter-ansi-terminal >=1.1.2 && <2\n    , unordered-containers >=0.2.11 && <0.3\n    , wcwidth >=0.0.1 && <1\n  default-language: Haskell2010\n  if flag(json)\n    cpp-options: -DUSE_AESON\n    build-depends:\n        aeson >=1.5 && <3\n      , bytestring >=0.9 && <1\n  if flag(megaparsec-compat)\n    build-depends:\n        containers ==0.6.*\n      , megaparsec >=9.0.0\n  if flag(parsec-compat)\n    build-depends:\n        parsec >=3.1.14\n"
  },
  {
    "path": "compiler/diagnose/hie.yaml",
    "content": "cradle:\n  stack:\n    - path: \"./test/rendering\"\n      component: \"diagnose:test:diagnose-rendering-tests\"\n    - path: \"./test/megaparsec\"\n      component: \"diagnose:test:diagnose-megaparsec-tests\"\n    - path: \"./test/parsec\"\n      component: \"diagnose:test:diagnose-parsec-tests\"\n    - path: \"./src\"\n      component: \"diagnose:lib\"\n"
  },
  {
    "path": "compiler/diagnose/nix/nixpkgs-pinned.nix",
    "content": "import\n  (builtins.fetchTarball {\n    name = \"nixpkgs-pinned\";\n    url = \"https://github.com/nixos/nixpkgs/archive/a7ecde854aee5c4c7cd6177f54a99d2c1ff28a31.tar.gz\";\n    # Use `nix-prefetch-url --unpack <url>`\n    sha256 = \"162dywda2dvfj1248afxc45kcrg83appjd0nmdb541hl7rnncf02\";\n  })\n{ }\n\n"
  },
  {
    "path": "compiler/diagnose/nix/stack.nix",
    "content": "{ pkgs ? import ./nixpkgs-pinned.nix\n, ghc ? pkgs.ghc\n}:\n\npkgs.haskell.lib.buildStackProject {\n  inherit ghc;\n\n  buildInputs = with pkgs; [\n    \n  ];\n\n  name = \"diagnose\";\n}\n"
  },
  {
    "path": "compiler/diagnose/package.yaml",
    "content": "name: diagnose\nversion: 2.5.1\ngithub: \"mesabloo/diagnose\"\nlicense: BSD3\nauthor: \"Ghilain Bergeron\"\ncopyright: \"2021-2022 Ghilain Bergeron\"\ncategory: \"Error Reporting\"\n\ndependencies:\n- base >= 4.7 && < 5\n- array >= 0.5 && < 0.6\n- data-default >= 0.7 && < 1\n- dlist >= 1.0 && < 1.1\n- hashable >= 1.3 && < 2\n- prettyprinter >= 1.7.0 && < 2\n- prettyprinter-ansi-terminal >= 1.1.2 && < 2\n- unordered-containers >= 0.2.11 && < 0.3\n- wcwidth >= 0.0.1 && <1\n\ndefault-extensions:\n- OverloadedStrings\n- LambdaCase\n- BlockArguments\n\nlibrary:\n  source-dirs: src\n  exposed-modules:\n  - Error.Diagnose\n  - Error.Diagnose.Diagnostic\n  - Error.Diagnose.Position\n  - Error.Diagnose.Pretty\n  - Error.Diagnose.Report\n  - Error.Diagnose.Style\n  when:\n  - condition: flag(megaparsec-compat)\n    exposed-modules:\n    - Error.Diagnose.Compat.Megaparsec\n  - condition: flag(parsec-compat)\n    exposed-modules:\n    - Error.Diagnose.Compat.Parsec\n\nflags:\n  json:\n    description: \"Allows exporting diagnostics as JSON.\n      This is disabled by default as this relies on the very heavy dependency Aeson.\"\n    manual: true\n    default: false\n  megaparsec-compat:\n    description: \"Includes a small compatibility layer (in the module `Error.Diagnose.Compat.Megaparsec`) to transform megaparsec errors into reports for this library.\"\n    manual: true\n    default: false\n  parsec-compat:\n    description: \"Includes a small compatibility layer (in the module `Error.Diagnose.Compat.Parsec`) to transform parsec errors into reports for this library.\"\n    manual: true\n    default: false\n  # do the same for other parsing libraries like parsec or attoparsec\n\nwhen:\n  - condition: flag(json)\n    dependencies:\n    - aeson >= 1.5 && <3\n    - bytestring >= 0.9 && < 1\n\n    cpp-options:\n    - -DUSE_AESON\n  - condition: flag(megaparsec-compat)\n    dependencies:\n    - megaparsec >= 9.0.0\n    - containers == 0.6.*\n  - condition: flag(parsec-compat)\n    dependencies:\n    - parsec >= 3.1.14\n\nghc-options:\n- -Wall\n- -Wextra\n# - -Wmissing-local-signatures\n# - -Wmonomorphism-restriction\n\nextra-source-files:\n- README.md\n\ntests:\n  diagnose-rendering-tests:\n    main:                Spec.hs\n    source-dirs:         test/rendering\n    ghc-options:\n    - -threaded\n    - -rtsopts\n    - -with-rtsopts=-N\n    dependencies:\n    - diagnose\n  diagnose-megaparsec-tests:\n    main:                  Spec.hs\n    source-dirs:           test/megaparsec\n    ghc-options:\n    - -threaded\n    - -rtsopts\n    - -with-rtsopts=-N\n    dependencies:\n    - diagnose\n    - text >= 1.2 && < 3\n    when:\n     - condition: ! '!(flag(megaparsec-compat))'\n       buildable: false\n  diagnose-parsec-tests:\n    main:                  Spec.hs\n    source-dirs:           test/parsec\n    ghc-options:\n    - -threaded\n    - -rtsopts\n    - -with-rtsopts=-N\n    dependencies:\n    - diagnose\n    - text >= 1.2 && < 3\n    when:\n     - condition: ! '!(flag(parsec-compat))'\n       buildable: false\n\n\n# This is put at the end for convenience.\nsynopsis: Beautiful error reporting done easily\n \ndescription: |\n  This package provides a simple way of getting beautiful compiler/interpreter errors\n  using a very simple interface for the programmer.\n\n  A quick tutorial is available in the module \"Error.Diagnose\", which goes on most of the basis\n  of how to use it.\n"
  },
  {
    "path": "compiler/diagnose/src/Data/List/Safe.hs",
    "content": "module Data.List.Safe where\n\nimport Data.Bifunctor (first)\n\n\n-- | Analogous to 'Data.List.last', but returns 'Nothing' on an empty list, instead of throwing an error.\nsafeLast :: [a] -> Maybe a\nsafeLast [] = Nothing\nsafeLast l  = Just $ last l\n\n-- | Analogous to `Data.List.head`, but returns 'Nothing' in case of an empty list.\nsafeHead :: [a] -> Maybe a\nsafeHead []      = Nothing\nsafeHead (x : _) = Just x\n\n-- | Analogous tu 'Data.List.!!', but does not throw an error on missing index.\nsafeIndex :: Int -> [a] -> Maybe a\nsafeIndex _ []       = Nothing\nsafeIndex 0 (x : _)  = Just x\nsafeIndex n (_ : xs)\n  | n < 0            = Nothing\n  | otherwise        = safeIndex (n - 1) xs\n\n-- | Safely deconstructs a list from the end.\n--\n--   More efficient than @(init x, last x)@\nsafeUnsnoc :: [a] -> Maybe ([a], a)\nsafeUnsnoc []       = Nothing\nsafeUnsnoc [x]      = Just ([], x)\nsafeUnsnoc (x : xs) = first (x :) <$> safeUnsnoc xs\n\n-- | Safely deconstructs a list from the beginning, returning 'Nothing' if the list is empty.\nsafeUncons :: [a] -> Maybe (a, [a])\nsafeUncons []       = Nothing\nsafeUncons (x : xs) = Just (x, xs)\n"
  },
  {
    "path": "compiler/diagnose/src/Error/Diagnose/Compat/Hints.hs",
    "content": "{-# LANGUAGE MultiParamTypeClasses #-}\n\nmodule Error.Diagnose.Compat.Hints where\n\nimport Error.Diagnose (Note)\n    \n-- | A class mapping custom errors of type @e@ with messages of type @msg@.\nclass HasHints e msg where\n  -- | Defines all the hints associated with a given custom error.\n  hints :: e -> [Note msg]\n\n-- this is a sane default for 'Void'\n-- but this can be redefined\n--\n-- instance HasHints Void msg where\n--   hints _ = mempty\n"
  },
  {
    "path": "compiler/diagnose/src/Error/Diagnose/Compat/Megaparsec.hs",
    "content": "{-# LANGUAGE BlockArguments #-}\n{-# LANGUAGE LambdaCase #-}\n{-# LANGUAGE MultiWayIf #-}\n{-# LANGUAGE RecordWildCards #-}\n{-# LANGUAGE ScopedTypeVariables #-}\n{-# LANGUAGE TypeApplications #-}\n{-# LANGUAGE ViewPatterns #-}\n\n{-# OPTIONS -Wno-name-shadowing #-}\n\n-- |\n-- Module      : Error.Diagnose.Compat.Megaparsec\n-- Description : Compatibility layer for megaparsec\n-- Copyright   : (c) Mesabloo, 2021-2022\n-- License     : BSD3\n-- Stability   : experimental\n-- Portability : Portable\nmodule Error.Diagnose.Compat.Megaparsec\n  ( diagnosticFromBundle,\n    errorDiagnosticFromBundle,\n    warningDiagnosticFromBundle,\n    module Error.Diagnose.Compat.Hints,\n  )\nwhere\n\nimport Data.Bifunctor (second)\nimport Data.Maybe (fromMaybe)\nimport qualified Data.Set as Set (toList)\nimport Data.String (IsString (..))\nimport Error.Diagnose\nimport Error.Diagnose.Compat.Hints (HasHints (..))\nimport qualified Text.Megaparsec as MP\n\n-- | Transforms a megaparsec 'MP.ParseErrorBundle' into a well-formated 'Diagnostic' ready to be shown.\ndiagnosticFromBundle ::\n  forall msg s e.\n  (IsString msg, MP.Stream s, HasHints e msg, MP.ShowErrorComponent e, MP.VisualStream s, MP.TraversableStream s) =>\n  -- | How to decide whether this is an error or a warning diagnostic\n  (MP.ParseError s e -> Bool) ->\n  -- | An optional error code\n  Maybe msg ->\n  -- | The error message of the diagnostic\n  msg ->\n  -- | Default hints when trivial errors are reported\n  Maybe [Note msg] ->\n  -- | The bundle to create a diagnostic from\n  MP.ParseErrorBundle s e ->\n  Diagnostic msg\ndiagnosticFromBundle isError code msg (fromMaybe [] -> trivialHints) MP.ParseErrorBundle {..} =\n  foldl addReport mempty (toLabeledPosition <$> bundleErrors)\n  where\n    toLabeledPosition :: MP.ParseError s e -> Report msg\n    toLabeledPosition error =\n      let (_, pos) = MP.reachOffset (MP.errorOffset error) bundlePosState\n          source = fromSourcePos (MP.pstateSourcePos pos)\n          msgs = fromString @msg <$> lines (MP.parseErrorTextPretty error)\n       in flip\n            (if isError error then Err code msg else Warn code msg)\n            (errorHints error)\n            if\n                | [m] <- msgs -> [(source, This m)]\n                | [m1, m2] <- msgs -> [(source, This m1), (source, Where m2)]\n                | otherwise -> [(source, This $ fromString \"<<Unknown error>>\")]\n\n    fromSourcePos :: MP.SourcePos -> Position\n    fromSourcePos MP.SourcePos {..} =\n      let start = both (fromIntegral . MP.unPos) (sourceLine, sourceColumn)\n          end = second (+ 1) start\n       in Position start end sourceName\n\n    errorHints :: MP.ParseError s e -> [Note msg]\n    errorHints MP.TrivialError {} = trivialHints\n    errorHints (MP.FancyError _ errs) =\n      Set.toList errs >>= \\case\n        MP.ErrorCustom e -> hints e\n        _ -> mempty\n\n-- | Creates an error diagnostic from a megaparsec 'MP.ParseErrorBundle'.\nerrorDiagnosticFromBundle ::\n  forall msg s e.\n  (IsString msg, MP.Stream s, HasHints e msg, MP.ShowErrorComponent e, MP.VisualStream s, MP.TraversableStream s) =>\n  -- | An optional error code\n  Maybe msg ->\n  -- | The error message of the diagnostic\n  msg ->\n  -- | Default hints when trivial errors are reported\n  Maybe [Note msg] ->\n  -- | The bundle to create a diagnostic from\n  MP.ParseErrorBundle s e ->\n  Diagnostic msg\nerrorDiagnosticFromBundle = diagnosticFromBundle (const True)\n\n-- | Creates a warning diagnostic from a megaparsec 'MP.ParseErrorBundle'.\nwarningDiagnosticFromBundle ::\n  forall msg s e.\n  (IsString msg, MP.Stream s, HasHints e msg, MP.ShowErrorComponent e, MP.VisualStream s, MP.TraversableStream s) =>\n  -- | An optional error code\n  Maybe msg ->\n  -- | The error message of the diagnostic\n  msg ->\n  -- | Default hints when trivial errors are reported\n  Maybe [Note msg] ->\n  -- | The bundle to create a diagnostic from\n  MP.ParseErrorBundle s e ->\n  Diagnostic msg\nwarningDiagnosticFromBundle = diagnosticFromBundle (const False)\n\n------------------------------------\n------------ INTERNAL --------------\n------------------------------------\n\n-- | Applies a computation to both element of a tuple.\n--\n--   > both f = bimap @(,) f f\nboth :: (a -> b) -> (a, a) -> (b, b)\nboth f ~(x, y) = (f x, f y)\n"
  },
  {
    "path": "compiler/diagnose/src/Error/Diagnose/Compat/Parsec.hs",
    "content": "{-# LANGUAGE FlexibleContexts #-}\n{-# LANGUAGE ScopedTypeVariables #-}\n{-# LANGUAGE ViewPatterns #-}\n\n{-# OPTIONS -Wno-name-shadowing #-}\n\n-- |\n-- Module      : Error.Diagnose.Compat.Parsec\n-- Description : Compatibility layer for parsec\n-- Copyright   : (c) Mesabloo, 2021-2022\n-- License     : BSD3\n-- Stability   : experimental\n-- Portability : Portable\nmodule Error.Diagnose.Compat.Parsec\n  ( diagnosticFromParseError,\n    errorDiagnosticFromParseError,\n    warningDiagnosticFromParseError,\n    module Error.Diagnose.Compat.Hints,\n  )\nwhere\n\nimport Data.Bifunctor (second)\nimport Data.List (intercalate, nub)\nimport Data.Maybe (fromMaybe)\nimport Data.String (IsString (..))\nimport Data.Void (Void)\nimport Error.Diagnose\nimport Error.Diagnose.Compat.Hints (HasHints (..))\nimport qualified Text.Parsec.Error as PE\nimport qualified Text.Parsec.Pos as PP\n\n-- | Generates a diagnostic from a 'PE.ParseError'.\ndiagnosticFromParseError ::\n  forall msg.\n  (IsString msg, HasHints Void msg) =>\n  -- | Determine whether the diagnostic is an error or a warning\n  (PE.ParseError -> Bool) ->\n  -- | An optional error code\n  Maybe msg ->\n  -- | The main error of the diagnostic\n  msg ->\n  -- | Default hints\n  Maybe [Note msg] ->\n  -- | The 'PE.ParseError' to transform into a 'Diagnostic'\n  PE.ParseError ->\n  Diagnostic msg\ndiagnosticFromParseError isError code msg (fromMaybe [] -> defaultHints) error =\n  let pos = fromSourcePos $ PE.errorPos error\n      markers = toMarkers pos $ PE.errorMessages error\n      report = (if isError error then Err code msg else Warn code msg) markers (defaultHints <> hints (undefined :: Void))\n   in addReport mempty report\n  where\n    fromSourcePos :: PP.SourcePos -> Position\n    fromSourcePos pos =\n      let start = both fromIntegral (PP.sourceLine pos, PP.sourceColumn pos)\n          end = second (+ 1) start\n       in Position start end (PP.sourceName pos)\n\n    toMarkers :: Position -> [PE.Message] -> [(Position, Marker msg)]\n    toMarkers source [] = [(source, This $ fromString \"<<unknown error>>\")]\n    toMarkers source msgs =\n      let putTogether [] = ([], [], [], [])\n          putTogether (PE.SysUnExpect thing : ms) = let (a, b, c, d) = putTogether ms in (thing : a, b, c, d)\n          putTogether (PE.UnExpect thing : ms) = let (a, b, c, d) = putTogether ms in (a, thing : b, c, d)\n          putTogether (PE.Expect thing : ms) = let (a, b, c, d) = putTogether ms in (a, b, thing : c, d)\n          putTogether (PE.Message thing : ms) = let (a, b, c, d) = putTogether ms in (a, b, c, thing : d)\n\n          (nub -> sysUnexpectedList, nub -> unexpectedList, nub -> expectedList, nub -> messages) = putTogether msgs\n\n          firstSysUnexpectedMessage = head sysUnexpectedList\n          unexpectedMessage = \"unexpected \" <> if null unexpectedList then if null firstSysUnexpectedMessage then \"end of line\" else firstSysUnexpectedMessage else intercalate \", \" (filter (not . null) unexpectedList)\n       in [ (source, This $ fromString unexpectedMessage) ]\n            <> [ (source, This $ fromString msg) | msg <- messages ]\n            <> [ (source, Where $ fromString $ \"expecting any of \" <> intercalate \", \" (filter (not . null) expectedList)) ]\n\n-- | Generates an error diagnostic from a 'PE.ParseError'.\nerrorDiagnosticFromParseError ::\n  forall msg.\n  (IsString msg, HasHints Void msg) =>\n  -- | An optional error code\n  Maybe msg ->\n  -- | The main error message of the diagnostic\n  msg ->\n  -- | Default hints\n  Maybe [Note msg] ->\n  -- | The 'PE.ParseError' to convert\n  PE.ParseError ->\n  Diagnostic msg\nerrorDiagnosticFromParseError = diagnosticFromParseError (const True)\n\n-- | Generates a warning diagnostic from a 'PE.ParseError'.\nwarningDiagnosticFromParseError ::\n  forall msg.\n  (IsString msg, HasHints Void msg) =>\n  -- | An optional error code\n  Maybe msg ->\n  -- | The main error message of the diagnostic\n  msg ->\n  -- | Default hints\n  Maybe [Note msg] ->\n  -- | The 'PE.ParseError' to convert\n  PE.ParseError ->\n  Diagnostic msg\nwarningDiagnosticFromParseError = diagnosticFromParseError (const False)\n\n------------------------------------\n------------ INTERNAL --------------\n------------------------------------\n\n-- | Applies a computation to both element of a tuple.\n--\n--   > both f = bimap @(,) f f\nboth :: (a -> b) -> (a, a) -> (b, b)\nboth f ~(x, y) = (f x, f y)\n"
  },
  {
    "path": "compiler/diagnose/src/Error/Diagnose/Diagnostic/Internal.hs",
    "content": "{-# LANGUAGE CPP #-}\n{-# LANGUAGE DeriveTraversable #-}\n{-# LANGUAGE FlexibleInstances #-}\n\n-- |\n-- Module      : Error.Diagnose.Diagnostic.Internal\n-- Description : Internal workings for diagnostic definitions and pretty printing.\n-- Copyright   : (c) Mesabloo, 2021-2022\n-- License     : BSD3\n-- Stability   : experimental\n-- Portability : Portable\n--\n-- /Warning/: The API of this module can break between two releases, therefore you should not rely on it.\n--            It is also highly undocumented.\n--\n--            Please limit yourself to the \"Error.Diagnose.Diagnostic\" module, which exports some of the useful functions defined here.\nmodule Error.Diagnose.Diagnostic.Internal (module Error.Diagnose.Diagnostic.Internal, WithUnicode(..), TabSize(..)) where\n\nimport Control.Monad.IO.Class (MonadIO, liftIO)\n#ifdef USE_AESON\nimport Data.Aeson (ToJSON(..), encode, object, (.=))\nimport Data.ByteString.Lazy (ByteString)\n#endif\n\nimport Data.Array (listArray)\nimport Data.DList (DList)\nimport qualified Data.DList as DL\nimport Data.Foldable (fold, toList)\nimport qualified Data.HashMap.Lazy as HashMap\nimport Data.List (intersperse)\nimport Error.Diagnose.Report (Report)\nimport Error.Diagnose.Report.Internal (FileMap, errorToWarning, prettyReport, warningToError, WithUnicode(..), TabSize(..))\nimport Error.Diagnose.Style (Annotation, Style)\nimport Prettyprinter (Doc, Pretty, hardline, pretty, defaultLayoutOptions, reAnnotateS, layoutPretty)\nimport Prettyprinter.Render.Terminal (renderIO)\nimport System.IO (Handle)\n\n-- | The data type for diagnostic containing messages of an abstract type.\n--\n--   Users can use 'mempty' to create a new empty diagnostic, and 'addFile' and\n--   'addReport' to alter its internal state.\ndata Diagnostic msg\n  = Diagnostic\n      (DList (Report msg))\n      -- ^ All the reports contained in a diagnostic.\n      --\n      --   Reports are output one by one, without connections in between.\n      !FileMap\n      -- ^ A map associating files with their content as lists of lines.\n  deriving (Functor, Foldable, Traversable)\n\ninstance Monoid (Diagnostic msg) where\n  mempty = Diagnostic mempty mempty\n\ninstance Semigroup (Diagnostic msg) where\n  Diagnostic rs1 files1 <> Diagnostic rs2 files2 = Diagnostic (rs1 <> rs2) (files1 <> files2)\n\n#ifdef USE_AESON\ninstance ToJSON msg => ToJSON (Diagnostic msg) where\n  toJSON (Diagnostic reports files) =\n    object [ \"files\" .= fmap toJSONFile (fmap toList <$> (HashMap.toList files))\n           , \"reports\" .= reports\n           ]\n    where\n      toJSONFile (path, content) =\n        object [ \"name\" .= path\n               , \"content\" .= content\n               ]\n#endif\n\n-- | Checks whether the given diagnostic has any report or not (if it is effectively empty).\nhasReports :: Diagnostic msg -> Bool\nhasReports (Diagnostic DL.Nil _) = False\nhasReports _ = True\n\n-- | Retrieves the reports for this diagnostic.\nreportsOf :: Diagnostic msg -> [Report msg]\nreportsOf (Diagnostic reports _) = toList reports\n\n-- | Transforms every warning report in this diagnostic into an error report.\nwarningsToErrors :: Diagnostic msg -> Diagnostic msg\nwarningsToErrors (Diagnostic reports files) = Diagnostic (warningToError <$> reports) files\n\n-- | Transforms every error report in this diagnostic into a warning report.\nerrorsToWarnings :: Diagnostic msg -> Diagnostic msg\nerrorsToWarnings (Diagnostic reports files) = Diagnostic (errorToWarning <$> reports) files\n\n-- | Pretty prints a 'Diagnostic' into a 'Doc'ument that can be output using 'hPutDoc'.\n--\n--   Colors are put by default.\n--   If you do not want these, just 'unAnnotate' the resulting document like so:\n--\n--   >>> let doc = unAnnotate (prettyDiagnostic withUnicode tabSize diagnostic)\n--\n--   Changing the style is also rather easy:\n--\n--   >>> let myCustomStyle :: Style = _\n--   >>> let doc = myCustomStyle (prettyDiagnostic withUnicode tabSize diagnostic)\nprettyDiagnostic ::\n  Pretty msg =>\n  -- | Should we use unicode when printing paths?\n  WithUnicode ->\n  -- | The number of spaces each TAB character will span.\n  TabSize ->\n  -- | The diagnostic to print.\n  Diagnostic msg ->\n  Doc (Annotation ann)\nprettyDiagnostic withUnicode tabSize =\n  prettyDiagnostic' withUnicode tabSize . fmap pretty\n{-# INLINE prettyDiagnostic #-}\n\n-- | Like 'prettyDiagnostic' except that instead of requiring a 'pretty'\n-- instance for messages, this allows passing in your own 'Doc'. Custom\n-- annotations are retained in 'OtherStyle'\nprettyDiagnostic' ::\n  -- | Should we use unicode when printing paths?\n  WithUnicode ->\n  -- | The number of spaces each TAB character will span.\n  TabSize ->\n  -- | The diagnostic to print.\n  Diagnostic (Doc ann) ->\n  Doc (Annotation ann)\nprettyDiagnostic' withUnicode tabSize (Diagnostic reports file) =\n  fold . intersperse hardline $ prettyReport file withUnicode tabSize <$> toList reports\n\n-- | Prints a 'Diagnostic' onto a specific 'Handle'.\nprintDiagnostic ::\n  (MonadIO m, Pretty msg) =>\n  -- | The handle onto which to output the diagnostic.\n  Handle ->\n  -- | Should we print with unicode characters?\n  WithUnicode ->\n  -- | The number of spaces each TAB character will span.\n  TabSize ->\n  -- | The style in which to output the diagnostic.\n  Style ann ->\n  -- | The diagnostic to output.\n  Diagnostic msg ->\n  m ()\nprintDiagnostic handle withUnicode tabSize style =\n  printDiagnostic' handle withUnicode tabSize style . fmap pretty\n{-# INLINE printDiagnostic #-}\n\n-- | Like 'printDiagnostic' except that instead of requiring a 'pretty'\n-- instance for messages, this allows passing in your own 'Doc'.\nprintDiagnostic' ::\n  MonadIO m =>\n  -- | The handle onto which to output the diagnostic.\n  Handle ->\n  -- | Should we print with unicode characters?\n  WithUnicode ->\n  -- | The number of spaces each TAB character will span.\n  TabSize ->\n  -- | The style in which to output the diagnostic.\n  Style ann ->\n  -- | The diagnostic to output.\n  Diagnostic (Doc ann) ->\n  m ()\nprintDiagnostic' handle withUnicode tabSize style =\n  liftIO\n    . renderIO handle\n    . reAnnotateS style\n    . layoutPretty defaultLayoutOptions\n    . prettyDiagnostic' withUnicode tabSize\n\n-- | Inserts a new referenceable file within the diagnostic.\naddFile ::\n  Diagnostic msg ->\n  -- | The path to the file.\n  FilePath ->\n  -- | The content of the file as a single string, where lines are ended by @\\\\n@.\n  String ->\n  Diagnostic msg\naddFile (Diagnostic reports files) path content =\n  let fileLines = lines content\n      lineCount = length fileLines\n      lineArray = listArray (0, lineCount - 1) fileLines\n   in Diagnostic reports (HashMap.insert path lineArray files)\n{-# INLINE addFile #-}\n\n-- | Inserts a new report into a diagnostic.\naddReport ::\n  Diagnostic msg ->\n  -- | The new report to add to the diagnostic.\n  Report msg ->\n  Diagnostic msg\naddReport (Diagnostic reports files) report =\n  Diagnostic (reports `DL.snoc` report) files\n{-# INLINE addReport #-}\n\n#ifdef USE_AESON\n-- | Creates a JSON object from a diagnostic, containing those fields (only types are indicated):\n--\n--   > { files:\n--   >     { name: string\n--   >     , content: string[]\n--   >     }[]\n--   > , reports:\n--   >     { kind: 'error' | 'warning'\n--   >     , code: T?\n--   >     , message: T\n--   >     , markers:\n--   >         { kind: 'this' | 'where' | 'maybe'\n--   >         , position:\n--   >             { beginning: { line: int, column: int }\n--   >             , end: { line: int, column: int }\n--   >             , file: string\n--   >             }\n--   >         , message: T\n--   >         }[]\n--   >     , hints: ({ note: T } | { hint: T })[]\n--   >     }[]\n--   > }\n--\n--   where @T@ is the type of the JSON representation for the @msg@ type variable.\ndiagnosticToJson :: ToJSON msg => Diagnostic msg -> ByteString\ndiagnosticToJson = encode\n#endif\n"
  },
  {
    "path": "compiler/diagnose/src/Error/Diagnose/Diagnostic.hs",
    "content": "{-# LANGUAGE CPP #-}\n\n-- |\n-- Module      : Error.Diagnose.Diagnostic\n-- Description : Diagnostic definition and pretty printing\n-- Copyright   : (c) Mesabloo, 2021-2022\n-- License     : BSD3\n-- Stability   : experimental\n-- Portability : Portable\nmodule Error.Diagnose.Diagnostic\n  ( -- * Re-exports\n    module Export,\n  )\nwhere\n\nimport Error.Diagnose.Diagnostic.Internal as Export\n  ( Diagnostic,\n#ifdef USE_AESON\n  diagnosticToJson,\n#endif\n    addFile,\n    addReport,\n    errorsToWarnings,\n    hasReports,\n    reportsOf,\n    prettyDiagnostic,\n    prettyDiagnostic',\n    printDiagnostic,\n    printDiagnostic',\n    warningsToErrors,\n    WithUnicode(..),\n    TabSize(..),\n  )\nimport System.IO as Export (stderr, stdout)\n"
  },
  {
    "path": "compiler/diagnose/src/Error/Diagnose/Position.hs",
    "content": "{-# LANGUAGE CPP #-}\n{-# LANGUAGE DeriveGeneric #-}\n{-# LANGUAGE FlexibleInstances #-}\n{-# LANGUAGE RecordWildCards #-}\n{-# LANGUAGE TypeApplications #-}\n\n-- |\n-- Module      : Error.Diagnose.Diagnostic\n-- Description : Defines location information as a simple record.\n-- Copyright   : (c) Mesabloo, 2021-2022\n-- License     : BSD3\n-- Stability   : experimental\n-- Portability : Portable\nmodule Error.Diagnose.Position (Position (..)) where\n\n#ifdef USE_AESON\nimport Data.Aeson (ToJSON(..), object, (.=))\n#endif\nimport Data.Default (Default, def)\nimport Data.Hashable (Hashable)\nimport GHC.Generics (Generic (..))\nimport Prettyprinter (Pretty (..), colon)\n\n-- import Text.PrettyPrint.ANSI.Leijen (Pretty(..), text, colon, int)\n\n-- | Contains information about the location of something.\n--\n--   It is best used in a datatype like:\n--\n--   > data Located a\n--   >   = a :@ Position\n--   >   deriving (Show, Eq, Ord, Functor, Traversable)\n--\n--   Columns are specified in amount of Unicode codepoints from the beginning of the line.\n--   Lines and columns start at 1.\ndata Position = Position\n  { -- | The beginning line and column of the span.\n    begin :: (Int, Int),\n    -- | The end line and column of the span.\n    end :: (Int, Int),\n    -- | The file this position spans in.\n    file :: FilePath\n  }\n  deriving (Show, Eq, Ord, Generic)\n\ninstance Pretty Position where\n  pretty (Position (bl, bc) (el, ec) f) = pretty f <> at <> pretty bl <> colon <> pretty bc <> dash <> pretty el <> colon <> pretty ec\n    where\n      at = pretty @String \"@\"\n      dash = pretty @String \"-\"\n\ninstance Hashable Position\n\ninstance Default Position where\n  def = Position (1, 1) (1, 1) \"<no-file>\"\n\n#ifdef USE_AESON\ninstance ToJSON Position where\n  toJSON (Position (bl, bc) (el, ec) file) =\n    object [ \"beginning\" .= object [ \"line\" .= bl, \"column\" .= bc ]\n           , \"end\" .= object [ \"line\" .= el, \"column\" .= ec ]\n           , \"file\" .= file\n           ]\n#endif\n"
  },
  {
    "path": "compiler/diagnose/src/Error/Diagnose/Pretty.hs",
    "content": "module Error.Diagnose.Pretty (module Export) where\n\nimport qualified Prettyprinter as Export \n"
  },
  {
    "path": "compiler/diagnose/src/Error/Diagnose/Report/Internal.hs",
    "content": "{-# LANGUAGE BangPatterns #-}\n{-# LANGUAGE CPP #-}\n{-# LANGUAGE DeriveTraversable #-}\n{-# LANGUAGE FlexibleInstances #-}\n{-# LANGUAGE MultiWayIf #-}\n{-# LANGUAGE RecordWildCards #-}\n{-# LANGUAGE ScopedTypeVariables #-}\n{-# LANGUAGE TypeApplications #-}\n{-# LANGUAGE PatternSynonyms #-}\n{-# OPTIONS -Wno-name-shadowing #-}\n\n-- |\n-- Module      : Error.Diagnose.Report.Internal\n-- Description : Internal workings for report definitions and pretty printing.\n-- Copyright   : (c) Mesabloo, 2021-2022\n-- License     : BSD3\n-- Stability   : experimental\n-- Portability : Portable\n--\n-- /Warning/: The API of this module can break between two releases, therefore you should not rely on it.\n--            It is also highly undocumented.\n--\n--            Please limit yourself to the \"Error.Diagnose.Report\" module, which exports some of the useful functions defined here.\nmodule Error.Diagnose.Report.Internal\n  ( module Error.Diagnose.Report.Internal\n  , Report(.., Warn, Err)\n  , WithUnicode(..)\n  , TabSize(..)\n  ) where\n\n#ifdef USE_AESON\nimport Data.Aeson (ToJSON(..), object, (.=))\n#endif\nimport Control.Applicative ((<|>))\nimport qualified Data.Array.IArray as Array\nimport Data.Array.Unboxed (Array, IArray, Ix, UArray, listArray, (!))\nimport Data.Bifunctor (bimap, first, second)\nimport Data.Char.WCWidth (wcwidth)\nimport Data.Default (def)\nimport Data.Foldable (fold)\nimport Data.Function (on)\nimport Data.Functor ((<&>), void)\nimport Data.HashMap.Lazy (HashMap)\nimport qualified Data.HashMap.Lazy as HashMap\nimport qualified Data.List as List\nimport qualified Data.List.Safe as List\nimport Data.Maybe\nimport Data.String (IsString (fromString))\nimport Error.Diagnose.Position\nimport Error.Diagnose.Style (Annotation (..))\nimport Prettyprinter (Doc, Pretty (..), align, annotate, colon, hardline, lbracket, rbracket, space, width, (<+>), reAnnotate, SimpleDocStream (..), layoutCompact)\nimport Prettyprinter.Internal (Doc (..), textSpaces)\nimport Data.Bool (bool)\n\ntype FileMap = HashMap FilePath (Array Int String)\n\ntype WidthTable = UArray Int Int\n\n-- | The type of diagnostic reports with abstract message type.\ndata Report msg\n  = Report\n      Bool\n      -- ^ Is the report a warning or an error?\n      (Maybe msg)\n      -- ^ An optional error code to print at the top.\n      msg\n      -- ^ The message associated with the error.\n      [(Position, Marker msg)]\n      -- ^ A map associating positions with marker to show under the source code.\n      [Note msg]\n      -- ^ A list of notes to add at the end of the report.\n  deriving (Functor, Foldable, Traversable)\n\n-- | Pattern synonym for a warning report.\npattern Warn :: Maybe msg -> msg -> [(Position, Marker msg)] -> [Note msg] -> Report msg\npattern Warn errCode msg reports notes = Report False errCode msg reports notes\n\n-- | Pattern synonym for an error report.\npattern Err :: Maybe msg -> msg -> [(Position, Marker msg)] -> [Note msg] -> Report msg\npattern Err errCode msg reports notes = Report True errCode msg reports notes\n\n{-# COMPLETE Warn, Err #-}\n\ninstance Semigroup msg => Semigroup (Report msg) where\n  Report isError1 code1 msg1 pos1 hints1 <> Report isError2 code2 msg2 pos2 hints2 =\n    Report (isError1 || isError2) (code1 <|> code2) (msg1 <> msg2) (pos1 <> pos2) (hints1 <> hints2)\n\ninstance Monoid msg => Monoid (Report msg) where\n  mempty = Report False Nothing mempty mempty mempty\n\n#ifdef USE_AESON\ninstance ToJSON msg => ToJSON (Report msg) where\n  toJSON (Report isError code msg markers hints) =\n    object [ \"kind\" .= (if isError then \"error\" else \"warning\" :: String)\n           , \"code\" .= code\n           , \"message\" .= msg\n           , \"markers\" .= fmap showMarker markers\n           , \"hints\" .= hints\n           ]\n    where\n      showMarker (pos, marker) =\n        object $ [ \"position\" .= pos ]\n              <> case marker of\n                   This m  -> [ \"message\" .= m\n                              , \"kind\" .= (\"this\" :: String)\n                              ]\n                   Where m -> [ \"message\" .= m\n                              , \"kind\" .= (\"where\" :: String)\n                              ]\n                   Maybe m -> [ \"message\" .= m\n                              , \"kind\" .= (\"maybe\" :: String)\n                              ]\n                   Blank -> [ \"kind\" .= (\"blank\" :: String) ]\n#endif\n\n-- | The type of markers with abstract message type, shown under code lines.\ndata Marker msg\n  = -- | A red or yellow marker under source code, marking important parts of the code.\n    This msg\n  | -- | A blue marker symbolizing additional information.\n    Where msg\n  | -- | A magenta marker to report potential fixes.\n    Maybe msg\n  | -- | An empty marker, whose sole purpose is to include a line of code in the report without markers under.\n    Blank\n  deriving (Eq, Ord, Functor, Foldable, Traversable)\n\nisBlank :: Marker msg -> Bool\nisBlank = \\case\n  Blank -> True\n  _ -> False\n\n-- | A note is a piece of information that is found at the end of a report.\ndata Note msg\n  = -- | A note, which is meant to give valuable information related to the encountered error.\n    Note msg\n  | -- | A hint, to propose potential fixes or help towards fixing the issue.\n    Hint msg\n  deriving (Eq, Ord, Show, Functor, Foldable, Traversable)\n\n#ifdef USE_AESON\ninstance ToJSON msg => ToJSON (Note msg) where\n  toJSON (Note msg) = object [ \"note\" .= msg ]\n  toJSON (Hint msg) = object [ \"hint\" .= msg ]\n#endif\n\n-- | Constructs a 'Note' from the given message as a literal string.\ninstance IsString msg => IsString (Note msg) where\n  fromString = Note . fromString\n\n-- | Constructs a warning or an error report.\nwarn,\n  err ::\n    -- | An optional error code to be shown right next to \"error\" or \"warning\".\n    Maybe msg ->\n    -- | The report message, shown at the very top.\n    msg ->\n    -- | A list associating positions with markers.\n    [(Position, Marker msg)] ->\n    -- | A possibly mempty list of hints to add at the end of the report.\n    [Note msg] ->\n    Report msg\nwarn = Report False\n{-# INLINE warn #-}\n{-# DEPRECATED warn \"'warn' is deprecated. Use 'Warn' instead.\" #-}\nerr = Report True\n{-# INLINE err #-}\n{-# DEPRECATED err \"'err' is deprecated. Use 'Err' instead.\" #-}\n\n-- | Transforms a warning report into an error report.\nwarningToError :: Report msg -> Report msg\nwarningToError (Report False code msg markers notes) = Report True code msg markers notes\nwarningToError r@(Report True _ _ _ _) = r\n\n-- | Transforms an error report into a warning report.\nerrorToWarning :: Report msg -> Report msg\nerrorToWarning (Report True code msg markers notes) = Report False code msg markers notes\nerrorToWarning r@(Report False _ _ _ _) = r\n\ndata WithUnicode = WithoutUnicode | WithUnicode\n\nnewtype TabSize = TabSize Int\n\n-- | Pretty prints a report to a 'Doc' handling colors.\nprettyReport ::\n  -- | The content of the file the reports are for\n  FileMap ->\n  -- | Should we print paths in unicode?\n  WithUnicode ->\n  -- | The number of spaces each TAB character will span\n  TabSize ->\n  -- | The whole report to output\n  Report (Doc ann) ->\n  Doc (Annotation ann)\nprettyReport fileContent withUnicode tabSize (Report isError code message markers hints) =\n  let sortedMarkers = List.sortOn (fst . begin . fst) markers\n      -- sort the markers so that the first lines of the reports are the first lines of the file\n\n      groupedMarkers = groupMarkersPerFile sortedMarkers\n      -- group markers by the file they appear in, and put `This` markers at the top of the report\n\n      maxLineNumberLength = maybe 3 (max 3 . length . show . fst . end . fst) $ List.safeLast markers\n      -- if there are no markers, then default to 3, else get the maximum between 3 and the length of the last marker\n\n      header =\n        annotate\n          (KindColor isError)\n          ( lbracket\n              <> ( if isError\n                     then \"error\"\n                     else \"warning\"\n                 )\n              <> case code of\n                Nothing -> rbracket\n                Just code -> space <> annotated code <> rbracket\n          )\n   in {-\n              A report is of the form:\n              (1)    [error|warning]: <message>\n              (2)           +--> <file>\n              (3)           :\n              (4)    <line> | <line of code>\n                            : <marker lines>\n                            : <marker messages>\n              (5)           :\n                            : <hints>\n              (6)    -------+\n      -}\n\n      {- (1) -} header <> colon <+> align (annotated message)\n        <> {- (2), (3), (4) -} fold (uncurry (prettySubReport fileContent withUnicode isError tabSize maxLineNumberLength) <$> groupedMarkers)\n        <> {- (5) -} ( if\n                           | null hints && null markers -> mempty\n                           | null hints -> mempty\n                           | otherwise -> hardline <+> dotPrefix maxLineNumberLength withUnicode\n                     )\n        <> prettyAllHints hints maxLineNumberLength withUnicode\n        <> hardline\n        <> {- (6) -} ( if null markers && null hints\n                         then mempty\n                         else\n                           annotate RuleColor (pad (maxLineNumberLength + 2) (unicode '-' '─' withUnicode) mempty <> unicode \"+\" \"╯\" withUnicode)\n                             <> hardline\n                     )\n\n-------------------------------------------------------------------------------------\n----- INTERNAL STUFF ----------------------------------------------------------------\n-------------------------------------------------------------------------------------\n\n-- | Inserts a given number of character after a 'Doc'ument.\npad :: Int -> Char -> Doc ann -> Doc ann\npad n c d = width d \\w -> pretty $ replicate (n - w) c\n\n-- | Creates a \"dot\"-prefix for a report line where there is no code.\n--\n--   Pretty printing yields those results:\n--\n--   [with unicode] \"@␣␣␣␣␣•␣@\"\n--   [without unicode] \"@␣␣␣␣␣:␣@\"\ndotPrefix ::\n  -- | The length of the left space before the bullet.\n  Int ->\n  -- | Whether to print with unicode characters or not.\n  WithUnicode ->\n  Doc (Annotation ann)\ndotPrefix leftLen withUnicode =\n  pad leftLen ' ' mempty\n    <+> annotate RuleColor (unicode \":\" \"•\" withUnicode)\n{-# INLINE dotPrefix #-}\n\n-- | Creates a \"pipe\"-prefix for a report line where there is no code.\n--\n--   Pretty printing yields those results:\n--\n--   [with unicode] \"@␣␣␣␣␣│␣@\"\n--   [without unicode] \"@␣␣␣␣␣|␣@\"\npipePrefix ::\n  -- | The length of the left space before the pipe.\n  Int ->\n  -- | Whether to print with unicode characters or not.\n  WithUnicode ->\n  Doc (Annotation ann)\npipePrefix leftLen withUnicode = pad leftLen ' ' mempty <+> annotate RuleColor (unicode \"|\" \"│\" withUnicode)\n{-# INLINE pipePrefix #-}\n\n-- | Creates a line-prefix for a report line containing source code\n--\n--   Pretty printing yields those results:\n--\n--   [with unicode] \"@␣␣␣3␣│␣@\"\n--   [without unicode] \"@␣␣␣3␣|␣@\"\n--\n--   Results may be different, depending on the length of the line number.\nlinePrefix ::\n  -- | The length of the amount of space to span before the vertical bar.\n  Int ->\n  -- | The line number to show.\n  Int ->\n  -- | Whether to use unicode characters or not.\n  WithUnicode ->\n  Doc (Annotation ann)\nlinePrefix leftLen lineNo withUnicode =\n  let lineNoLen = length (show lineNo)\n   in annotate RuleColor $ mempty <+> pad (leftLen - lineNoLen) ' ' mempty <> pretty lineNo <+> unicode \"|\" \"│\" withUnicode\n{-# INLINE linePrefix #-}\n\n-- | Creates an ellipsis-prefix, when some line numbers are not consecutive.\n--\n--   Pretty printing yields those results:\n--\n--   [with unicode] \"@␣␣␣␣␣⋮␣@\"\n--   [without unicode] \"@␣␣␣␣...@\"\nellipsisPrefix ::\n  Int ->\n  WithUnicode ->\n  Doc (Annotation ann)\nellipsisPrefix leftLen withUnicode = pad leftLen ' ' mempty <> annotate RuleColor (unicode \"...\" (space <> \"⋮\") withUnicode)\n\ngroupMarkersPerFile ::\n  [(Position, Marker msg)] ->\n  [(Bool, [(Position, Marker msg)])]\ngroupMarkersPerFile [] = []\ngroupMarkersPerFile markers =\n  let markersPerFile = List.foldl' (HashMap.unionWith (<>)) mempty $ markers <&> \\tup@(p, _) -> HashMap.singleton (file p) [tup]\n   in -- put all markers on the same file together\n      -- NOTE: it's a shame that `HashMap.unionsWith f = foldl' (HashMap.unionWith f) mempty` does not exist\n\n      onlyFirstToTrue $ putThisMarkersAtTop $ HashMap.elems markersPerFile\n  where\n    onlyFirstToTrue = go True []\n\n    go _ acc [] = reverse acc\n    go t acc (x : xs) = go False ((t, x) : acc) xs\n\n    putThisMarkersAtTop = List.sortBy \\ms1 ms2 ->\n      if\n          | any isThisMarker (snd <$> ms1) -> LT\n          | any isThisMarker (snd <$> ms2) -> GT\n          | otherwise -> EQ\n\n-- | Prettyprint a sub-report, which is a part of the report spanning across a single file\nprettySubReport ::\n  -- | The content of files in the diagnostics\n  FileMap ->\n  -- | Is the output done with Unicode characters?\n  WithUnicode ->\n  -- | Is the current report an error report?\n  Bool ->\n  -- | The number of spaces each TAB character will span\n  TabSize ->\n  -- | The size of the biggest line number\n  Int ->\n  -- | Is this sub-report the first one in the list?\n  Bool ->\n  -- | The list of line-ordered markers appearing in a single file\n  [(Position, Marker (Doc ann))] ->\n  Doc (Annotation ann)\nprettySubReport fileContent withUnicode isError tabSize maxLineNumberLength isFirst markers =\n  let (markersPerLine, multilineMarkers) = splitMarkersPerLine markers\n      -- split the list on whether markers are multiline or not\n\n      sortedMarkersPerLine = {- second (List.sortOn (first $ snd . begin)) <$> -} List.sortOn fst (HashMap.toList markersPerLine)\n\n      reportFile = maybe (pretty @Position def) (pretty . fst) $ List.safeHead (List.sortOn (void . snd) markers)\n      -- the reported file is the file of the first 'This' marker (only one must be present)\n\n      allLineNumbers = List.sort $ List.nub $ (fst <$> sortedMarkersPerLine) <> (multilineMarkers >>= \\(Position (bl, _) (el, _) _, _) -> [bl .. el])\n\n      fileMarker =\n        ( if isFirst\n            then\n              space <> pad maxLineNumberLength ' ' mempty\n                <+> annotate RuleColor (unicode \"+-->\" \"╭──▶\" withUnicode)\n            else\n              space <> dotPrefix maxLineNumberLength withUnicode <> hardline\n                <> annotate RuleColor (pad (maxLineNumberLength + 2) (unicode '-' '─' withUnicode) mempty)\n                <> annotate RuleColor (unicode \"+-->\" \"┼──▶\" withUnicode)\n        )\n          <+> annotate FileColor reportFile\n   in {- (2) -} hardline <> fileMarker\n        <> hardline\n          <+> {- (3) -}  {- (3) -} pipePrefix maxLineNumberLength withUnicode\n        <> {- (4) -} prettyAllLines fileContent withUnicode isError tabSize maxLineNumberLength sortedMarkersPerLine multilineMarkers allLineNumbers\n\nisThisMarker :: Marker msg -> Bool\nisThisMarker (This _) = True\nisThisMarker _ = False\n\n-- |\nsplitMarkersPerLine :: [(Position, Marker msg)] -> (HashMap Int [(Position, Marker msg)], [(Position, Marker msg)])\nsplitMarkersPerLine [] = (mempty, mempty)\nsplitMarkersPerLine (m@(Position {..}, _) : ms) =\n  let (bl, _) = begin\n      (el, _) = end\n   in (if bl == el then first (HashMap.insertWith (<>) bl [m]) else second (m :))\n        (splitMarkersPerLine ms)\n\n-- |\nprettyAllLines ::\n  FileMap ->\n  WithUnicode ->\n  Bool ->\n  -- | The number of spaces each TAB character will span\n  TabSize ->\n  Int ->\n  [(Int, [(Position, Marker (Doc ann))])] ->\n  [(Position, Marker (Doc ann))] ->\n  [Int] ->\n  Doc (Annotation ann)\nprettyAllLines files withUnicode isError tabSize leftLen inline multiline lineNumbers =\n  case lineNumbers of\n    [] ->\n      showMultiline True multiline\n    [l] ->\n      let (ms, doc) = showForLine True l\n       in doc\n            <> prettyAllLines files withUnicode isError tabSize leftLen inline ms []\n    l1 : l2 : ls ->\n      let (ms, doc) = showForLine False l1\n       in doc\n            <> (if l2 /= l1 + 1 then hardline <+> dotPrefix leftLen withUnicode else mempty)\n            <> prettyAllLines files withUnicode isError tabSize leftLen inline ms (l2 : ls)\n  where\n    showForLine isLastLine line =\n      {-\n          A line of code is composed of:\n          (1)     <line> | <source code>\n          (2)            : <markers>\n          (3)            : <marker messages>\n\n          Multline markers may also take additional space (2 characters) on the right of the bar\n      -}\n      let allInlineMarkersInLine = snd =<< filter ((==) line . fst) inline\n\n          allMultilineMarkersInLine = flip filter multiline \\(Position (bl, _) (el, _) _, _) -> bl == line || el == line\n\n          allMultilineMarkersSpanningLine = flip filter multiline \\(Position (bl, _) (el, _) _, _) -> bl < line && el > line\n\n          inSpanOfMultiline = flip any multiline \\(Position (bl, _) (el, _) _, _) -> bl <= line && el >= line\n\n          colorOfFirstMultilineMarker = maybe id (annotate . markerColor isError . snd) (List.safeHead $ allMultilineMarkersInLine <> allMultilineMarkersSpanningLine)\n          -- take the first multiline marker to color the entire line, if there is one\n\n          (multilineEndingOnLine, otherMultilines) = flip List.partition multiline \\(Position _ (el, _) _, _) -> el == line\n          shouldShowMultiLine = isLastLine\n            || ((==) `on` fmap (fmap void)) (List.safeLast multilineEndingOnLine) (List.safeLast multiline)\n\n          !additionalPrefix = case allMultilineMarkersInLine of\n            [] ->\n              if not $ null multiline\n                then\n                  if not $ null allMultilineMarkersSpanningLine\n                    then colorOfFirstMultilineMarker (unicode \"|  \" \"│  \" withUnicode)\n                    else \"   \"\n                else mempty\n            (p@(Position _ (el, _) _), marker) : _ ->\n              let hasPredecessor = el == line || maybe False ((/=) p . fst . fst) (List.safeUncons multiline)\n               in colorOfFirstMultilineMarker\n                    (unicode (bool \"+\" \"|\" hasPredecessor ) (bool \"╭\" \"├\" hasPredecessor) withUnicode)\n                    <> annotate (markerColor isError marker) (unicode \">\" \"┤\" withUnicode)\n                    <> space\n\n          -- we need to remove all blank markers because they are irrelevant to the display\n          allInlineMarkersInLine' = filter (not . isBlank . snd) allInlineMarkersInLine\n          allMultilineMarkersSpanningLine' = filter (not . isBlank . snd) allMultilineMarkersSpanningLine\n\n          (widths, renderedCode) = getLine_ files (allInlineMarkersInLine <> allMultilineMarkersInLine <> allMultilineMarkersSpanningLine') line tabSize isError\n       in ( otherMultilines,\n            hardline\n              <> {- (1) -} linePrefix leftLen line withUnicode <+>  additionalPrefix\n              <> renderedCode\n              <> {- (2) -} showAllMarkersInLine (not $ null multiline) inSpanOfMultiline colorOfFirstMultilineMarker withUnicode isError leftLen widths allInlineMarkersInLine'\n              <> showMultiline shouldShowMultiLine multilineEndingOnLine\n          )\n\n    showMultiline _ [] = mempty\n    showMultiline isLastMultiline multiline =\n      let colorOfFirstMultilineMarker = markerColor isError . snd <$> List.safeHead multiline\n          -- take the color of the last multiline marker in case we need to add additional bars\n\n          prefix = space <> dotPrefix leftLen withUnicode <> space\n\n          prefixWithBar color = prefix <> maybe id annotate color (unicode \"| \" \"│ \" withUnicode)\n\n          showMultilineMarkerMessage (_, Blank) _ = mempty\n          showMultilineMarkerMessage (_, marker) isLast =\n            annotate (markerColor isError marker) $\n              ( if isLast && isLastMultiline\n                  then unicode \"`- \" \"╰╸ \" withUnicode\n                  else unicode \"|- \" \"├╸ \" withUnicode\n              )\n                <> replaceLinesWith (if isLast then prefix <> \"   \" else prefixWithBar (Just $ markerColor isError marker) <> space) 0 (annotated $ markerMessage marker)\n\n          showMultilineMarkerMessages [] = []\n          showMultilineMarkerMessages [m] = [showMultilineMarkerMessage m True]\n          showMultilineMarkerMessages (m : ms) = showMultilineMarkerMessage m False : showMultilineMarkerMessages ms\n       in hardline <> prefixWithBar colorOfFirstMultilineMarker <> hardline <> prefix <> fold (List.intersperse (hardline <> prefix) $ showMultilineMarkerMessages multiline)\n\n-- |\ngetLine_ ::\n  FileMap ->\n  [(Position, Marker msg)] ->\n  Int ->\n  TabSize ->\n  Bool ->\n  (WidthTable, Doc (Annotation ann))\ngetLine_ files markers line (TabSize tabSize) isError =\n  case safeArrayIndex (line - 1) =<< (HashMap.!?) files . file . fst =<< List.safeHead markers of\n    Nothing ->\n      ( mkWidthTable \"\",\n        annotate NoLineColor \"<no line>\"\n      )\n    Just code ->\n      ( mkWidthTable code,\n        flip foldMap (zip [1 ..] code) \\(n, c) ->\n          let cdoc = ifTab (pretty (replicate tabSize ' ')) pretty c\n              colorizingMarkers = flip filter markers \\case\n                (Position (bl, bc) (el, ec) _, _)\n                  | bl == el ->\n                    n >= bc && n < ec\n                  | otherwise ->\n                    (bl == line && n >= bc)\n                      || (el == line && n < ec)\n                      || (bl < line && el > line)\n           in maybe\n                (annotate CodeStyle)\n                ((\\m -> annotate (MarkerStyle $ markerColor isError m)) . snd)\n                (List.safeHead colorizingMarkers)\n                cdoc\n      )\n  where\n    ifTab :: a -> (Char -> a) -> Char -> a\n    ifTab a _ '\\t' = a\n    ifTab _ f c = f c\n\n    mkWidthTable :: String -> WidthTable\n    mkWidthTable s = listArray (1, length s) (ifTab tabSize wcwidth <$> s)\n\n-- |\nshowAllMarkersInLine :: Bool -> Bool -> (Doc (Annotation ann) -> Doc (Annotation ann)) -> WithUnicode -> Bool -> Int -> WidthTable -> [(Position, Marker (Doc ann))] -> Doc (Annotation ann)\nshowAllMarkersInLine _ _ _ _ _ _ _ [] = mempty\nshowAllMarkersInLine hasMultilines inSpanOfMultiline colorMultilinePrefix withUnicode isError leftLen widths ms =\n  let maxMarkerColumn = snd $ end $ fst $ List.last $ List.sortOn (snd . end . fst) ms\n      specialPrefix\n        | inSpanOfMultiline = colorMultilinePrefix (unicode \"| \" \"│ \" withUnicode) <> space\n        | hasMultilines = colorMultilinePrefix \"  \" <> space\n        | otherwise = mempty\n   in -- get the maximum end column, so that we know when to stop looking for other markers on the same line\n      hardline <+> dotPrefix leftLen withUnicode <+> (if List.null ms then mempty else specialPrefix <> showMarkers 1 maxMarkerColumn <> showMessages specialPrefix ms maxMarkerColumn)\n  where\n    widthAt i = 0 `fromMaybe` safeArrayIndex i widths\n    widthsBetween start end =\n      sum $ take (end - start) $ drop (start - 1) $ Array.elems widths\n\n    showMarkers n lineLen\n      | n > lineLen = mempty -- reached the end of the line\n      | otherwise =\n        let allMarkers = flip filter ms \\(Position (_, bc) (_, ec) _, mark) -> not (isBlank mark) && n >= bc && n < ec\n         in -- only consider markers which span onto the current column\n            case allMarkers of\n              [] -> fold (replicate (widthAt n) space) <> showMarkers (n + 1) lineLen\n              (Position {..}, marker) : _ ->\n                annotate\n                  (markerColor isError marker)\n                  ( if snd begin == n\n                      then unicode \"^\" \"┬\" withUnicode <> fold (replicate (widthAt n - 1) (unicode \"-\" \"─\" withUnicode))\n                      else fold (replicate (widthAt n) (unicode \"-\" \"─\" withUnicode))\n                  )\n                  <> showMarkers (n + 1) lineLen\n\n    showMessages specialPrefix ms lineLen = case List.safeUncons ms of\n      Nothing -> mempty -- no more messages to show\n      Just ((Position b@(_, bc) _ _, msg), pipes) ->\n        let filteredPipes = filter (uncurry (&&) . bimap ((/= b) . begin) (not . isBlank)) pipes\n            -- record only the pipes corresponding to markers on different starting positions\n            nubbedPipes = List.nubBy ((==) `on` (begin . fst)) filteredPipes\n            -- and then remove all duplicates\n\n            allColumns _ [] = (1, [])\n            allColumns n ms@((Position (_, bc) _ _, col) : ms')\n              | n == bc = bimap (+ 1) (col :) (allColumns (n + 1) ms')\n              | n < bc = bimap (+ 1) (replicate (widthAt n) space <>) (allColumns (n + 1) ms)\n              | otherwise = bimap (+ 1) (replicate (widthAt n) space <>) (allColumns (n + 1) ms')\n            -- transform the list of remaining markers into a single document line\n\n            hasSuccessor = length filteredPipes /= length pipes\n\n            lineStart pipes =\n              let (n, docs) = allColumns 1 $ List.sortOn (snd . begin . fst) pipes\n                  numberOfSpaces = widthsBetween n bc\n               in dotPrefix leftLen withUnicode <+> specialPrefix <> fold docs <> pretty (replicate numberOfSpaces ' ')\n            -- the start of the line contains the \"dot\"-prefix as well as all the pipes for all the still not rendered marker messages\n\n            prefix =\n              let (pipesBefore, pipesAfter) = List.partition ((< bc) . snd . begin . fst) nubbedPipes\n                  -- split the list so that all pipes before can have `|`s but pipes after won't\n\n                  pipesBeforeRendered = pipesBefore <&> second \\marker -> annotate (markerColor isError marker) (unicode \"|\" \"│\" withUnicode)\n                  -- pre-render pipes which are before because they will be shown\n\n                  lastBeginPosition = snd . begin . fst <$> List.safeLast (List.sortOn (snd . begin . fst) pipesAfter)\n\n                  lineLen = case lastBeginPosition of\n                    Nothing -> 0\n                    Just col -> widthsBetween bc col\n\n                  currentPipe = unicode (bool \"`\" \"|\" hasSuccessor) (bool \"╰\" \"├\" hasSuccessor) withUnicode\n\n                  lineChar = unicode '-' '─' withUnicode\n                  pointChar = unicode \"-\" \"╸\" withUnicode\n\n                  bc' = bc + lineLen + 2\n                  pipesBeforeMessageStart = List.filter ((< bc') . snd . begin . fst) pipesAfter\n                  -- consider pipes before, as well as pipes which came before the text rectangle bounds\n                  pipesBeforeMessageRendered = (pipesBefore <> pipesBeforeMessageStart) <&> second \\marker -> annotate (markerColor isError marker) (unicode \"|\" \"│\" withUnicode)\n               in -- also pre-render pipes which are before the message text bounds, because they will be shown if the message is on\n                  -- multiple lines\n\n                  lineStart pipesBeforeRendered\n                    <> annotate (markerColor isError msg) (currentPipe <> pretty (replicate lineLen lineChar) <> pointChar)\n                    <+> annotate (markerColor isError msg) (replaceLinesWith (space <> lineStart pipesBeforeMessageRendered <+> if List.null pipesBeforeMessageStart then \"  \" else \" \") 0 $ annotated $ markerMessage msg)\n         in hardline <+> prefix <> showMessages specialPrefix pipes lineLen\n\n-- WARN: uses the internal of the library\n--\n--       DO NOT use a wildcard here, in case the internal API exposes one more constructor\nreplaceLinesWith :: Doc ann -> Int -> Doc ann -> Doc ann\nreplaceLinesWith repl = go\n where\n  replWidth = sdsWidth . layoutCompact $ repl\n  sdsWidth = \\case\n    SFail -> 0\n    SEmpty -> 0\n    SChar _ sds -> 1 + sdsWidth sds\n    SText l _ sds -> l + sdsWidth sds\n    SLine _ _ -> error \"replaceLinesWith was given a prefix with a line break\"\n    SAnnPush _ sds -> sdsWidth sds\n    SAnnPop sds -> sdsWidth sds\n  replWithNesting n = hardline <> repl <> pretty (textSpaces n)\n  go n = \\case\n    Line -> replWithNesting n\n    Fail -> Fail\n    Empty -> Empty\n    Char c -> Char c\n    Text l txt -> Text l txt\n    FlatAlt f d -> FlatAlt (go n f) (go n d)\n    Cat c d -> Cat (go n c) (go n d)\n    Nest n' d -> go (n + n') d\n    Union c d -> Union (go n c) (go n d)\n    Column f -> Column (go n . f)\n    -- In this case we add both our fake nesting level (from the 'Nest'\n    -- constructors we've eliminated) and the nesting level from the line\n    -- prefixes\n    Nesting f -> Nesting (go n . f . (+ replWidth) . (+ n))\n    Annotated ann doc -> Annotated ann (go n doc)\n    WithPageWidth f -> WithPageWidth (go n . f)\n\n-- | Extracts the color of a marker as a 'Doc' coloring function.\nmarkerColor ::\n  -- | Whether the marker is in an error context or not.\n  --   This really makes a difference for a 'This' marker.\n  Bool ->\n  -- | The marker to extract the color from.\n  Marker msg ->\n  -- | A function used to color a 'Doc'.\n  Annotation ann\nmarkerColor isError (This _) = ThisColor isError\nmarkerColor _ (Where _) = WhereColor\nmarkerColor _ (Maybe _) = MaybeColor\nmarkerColor _ Blank = CodeStyle -- we take the same color as the code, for it to be invisible\n{-# INLINE markerColor #-}\n\n-- | Retrieves the message held by a marker.\nmarkerMessage :: Marker msg -> msg\nmarkerMessage (This m) = m\nmarkerMessage (Where m) = m\nmarkerMessage (Maybe m) = m\nmarkerMessage Blank = undefined\n{-# INLINE markerMessage #-}\n\n-- | Pretty prints all hints.\nprettyAllHints :: [Note (Doc ann)] -> Int -> WithUnicode -> Doc (Annotation ann)\nprettyAllHints [] _ _ = mempty\nprettyAllHints (h : hs) leftLen withUnicode =\n  {-\n        A hint is composed of:\n        (1)         : Hint: <hint message>\n  -}\n  let prefix = space <> pipePrefix leftLen withUnicode\n   in hardline <> prefix <+> annotate HintColor (notePrefix h <+> replaceLinesWith prefix 7 (annotated $ noteMessage h))\n        <> prettyAllHints hs leftLen withUnicode\n  where\n    notePrefix (Note _) = \"Note:\"\n    notePrefix (Hint _) = \"Hint:\"\n\n    noteMessage (Note msg) = msg\n    noteMessage (Hint msg) = msg\n\nsafeArrayIndex :: (Ix i, IArray a e) => i -> a i e -> Maybe e\nsafeArrayIndex i a\n  | Array.inRange (Array.bounds a) i = Just (a ! i)\n  | otherwise = Nothing\n\nannotated :: Doc ann -> Doc (Annotation ann)\nannotated = reAnnotate OtherStyle\n\nunicode :: a -> a -> WithUnicode -> a\nunicode f t = \\case\n  WithoutUnicode -> f\n  WithUnicode -> t\n"
  },
  {
    "path": "compiler/diagnose/src/Error/Diagnose/Report.hs",
    "content": "-- |\n-- Module      : Error.Diagnose.Report\n-- Description : Report definition and pretty printing\n-- Copyright   : (c) Mesabloo, 2021-2022\n-- License     : BSD3\n-- Stability   : experimental\n-- Portability : Portable\nmodule Error.Diagnose.Report\n  ( -- * Re-exports\n    module Export,\n  )\nwhere\n\nimport Error.Diagnose.Report.Internal as Export (Marker (..), Note (..), Report(Warn, Err), err, errorToWarning, warn, warningToError)\n"
  },
  {
    "path": "compiler/diagnose/src/Error/Diagnose/Style.hs",
    "content": "{-# LANGUAGE DeriveTraversable #-}\n{-# LANGUAGE DeriveGeneric #-}\n-- |\n-- Module      : Error.Diagnose.Style\n-- Description : Custom style definitions\n-- Copyright   : (c) Mesabloo, 2021-2022\n-- License     : BSD3\n-- Stability   : experimental\n-- Portability : Portable\nmodule Error.Diagnose.Style\n  ( -- * Defining new style\n    Annotation (..),\n    Style,\n    -- $defining_new_styles\n\n    -- * Styles\n    defaultStyle,\n    unadornedStyle,\n  )\nwhere\n\nimport GHC.Generics\nimport Prettyprinter.Render.Terminal (AnsiStyle, Color (..), bold, color, colorDull)\n\n-- $defining_new_styles\n--\n-- Defining new color styles (one may call them \"themes\") is actually rather easy.\n--\n-- A 'Style' is a function from an annotated 'Doc'ument to another annotated 'Doc'ument.\n-- Note that only the annotation type changes, hence the need of only providing a unidirectional mapping between those.\n--\n-- 'Annotation's are used when creating a 'Doc'ument and are simply placeholders to specify custom colors.\n-- 'AnsiStyle' is the concrete annotation to specify custom colors when rendering a 'Doc'ument.\n--\n-- One may define additional styles as follows:\n--\n-- > myNewCustomStyle :: Style\n-- > myNewCustomStyle = reAnnotate \\case\n-- >   -- all cases for all annotations\n--\n-- For simplicity's sake, a default style is given as 'defaultStyle'.\n\n-- | Some annotations as placeholders for colors in a 'Doc'.\ndata Annotation a\n  = -- | The color of 'Error.Diagnose.Report.This' markers, depending on whether the report is an error\n    --   report or a warning report.\n    ThisColor\n      Bool\n  | -- | The color of 'Error.Diagnose.Report.Maybe' markers.\n    MaybeColor\n  | -- | The color of 'Error.Diagnose.Report.Where' markers.\n    WhereColor\n  | -- | The color for hints.\n    --\n    --   Note that the beginning @Hint:@ text will always be in bold.\n    HintColor\n  | -- | The color for file names.\n    FileColor\n  | -- | The color of the rule separating the code/markers from the line numbers.\n    RuleColor\n  | -- | The color of the @[error]@/@[warning]@ at the top, depending on whether\n    --   this is an error or warning report.\n    KindColor\n      Bool\n  | -- | The color in which to output the @<no line>@ information when the file was not found.\n    NoLineColor\n  | -- | Additional style to apply to marker rules (e.g. bold) on top of some\n    --   already processed color annotation.\n    MarkerStyle\n      (Annotation a)\n  | -- | The color of the code when no marker is present.\n    CodeStyle\n  | -- | Something else, could be provided by the user\n    OtherStyle a\n  deriving (Eq, Ord, Show, Generic, Functor, Foldable, Traversable)\n\n-- | A style is a function which can be applied using 'reAnnotate'.\n--\n--   It transforms a 'Doc'ument containing 'Annotation's into a 'Doc'ument containing\n--   color information.\ntype Style a = Annotation a -> AnsiStyle\n\n-------------------------------------------\n\n-- | A style which disregards all annotations\nunadornedStyle :: Style a\nunadornedStyle = const mempty\n\n-- | The default style for diagnostics, where:\n--\n--   * 'Error.Diagnose.Report.This' markers are colored in red for errors and yellow for warnings\n--   * 'Error.Diagnose.Report.Where' markers are colored in dull blue\n--   * 'Error.Diagnose.Report.Maybe' markers are colored in magenta\n--   * Marker rules are of the same color of the marker, but also in bold\n--   * Hints are output in cyan\n--   * The left rules are colored in bold black\n--   * File names are output in dull green\n--   * The @[error]@/@[warning]@ at the top is colored in red for errors and yellow for warnings\n--   * The code is output in normal white\ndefaultStyle :: Style AnsiStyle\ndefaultStyle = \\case\n    ThisColor isError -> color if isError then Red else Yellow\n    MaybeColor -> color Magenta\n    WhereColor -> colorDull Blue\n    HintColor -> color Cyan\n    FileColor -> bold <> colorDull Green\n    RuleColor -> bold <> color Black\n    KindColor isError -> bold <> defaultStyle (ThisColor isError)\n    NoLineColor -> bold <> colorDull Magenta\n    MarkerStyle st ->\n      let ann = defaultStyle st\n       in if ann == defaultStyle CodeStyle\n            then ann\n            else bold <> ann\n    CodeStyle -> color White\n    OtherStyle s -> s\n"
  },
  {
    "path": "compiler/diagnose/src/Error/Diagnose.hs",
    "content": "module Error.Diagnose\n  ( -- $header\n\n    -- * How to use this module\n    -- $usage\n\n    -- ** Generating a report\n    -- $generate_report\n\n    -- ** Creating diagnostics from reports\n    -- $create_diagnostic\n\n    -- *** Pretty-printing a diagnostic onto a file 'System.IO.Handle'\n    -- $diagnostic_pretty\n\n    -- *** Pretty-printing a diagnostic as a document\n    -- $diagnostic_to_doc\n\n    -- *** Exporting a diagnostic to JSON\n    -- $diagnostic_json\n\n    -- ** Compatibility layers for popular parsing libraries\n    -- $compatibility_layers\n\n    -- *** megaparsec >= 9.0.0 (\"Error.Diagnose.Compat.Megaparsec\")\n    -- $compatibility_megaparsec\n\n    -- *** parsec >= 3.1.14.0 (\"Error.Diagnose.Compat.Parsec\")\n    -- $compatibility_parsec\n\n    -- *** Common errors\n    -- $compatibility_errors\n\n    -- * Re-exports\n    module Export,\n  )\nwhere\n\nimport Error.Diagnose.Diagnostic as Export\nimport Error.Diagnose.Position as Export\nimport Error.Diagnose.Pretty as Export\nimport Error.Diagnose.Report as Export\nimport Error.Diagnose.Style as Export\n\n-- $header\n--\n--   This module exports all the needed data types to use this library.\n--   It should be sufficient to only @import \"Error.Diagnose\"@.\n\n-- $usage\n--\n--   This library is intended to provide a very simple way of creating beautiful errors, by exposing\n--   a small yet simple API to the user.\n--\n--   The basic idea is that a diagnostic is a collection of reports (which embody errors or warnings) along\n--   with the files which can be referenced in those reports.\n\n-- $generate_report\n--\n--   A report contains:\n--\n--   - A message, to be shown at the top\n--\n--   - A list of located markers, used to underline parts of the source code and to emphasize it with a message\n--\n--   - A list of hints, shown at the very bottom\n--\n--   __Note__: The message type contained in a report is abstracted by a type variable.\n--             In order to render the report, the message must also be able to be rendered in some way\n--             (that we'll see later).\n--\n--   This library allows defining two kinds of reports:\n--\n--   - Errors, using 'Err'\n--\n--   - Warnings, using 'Warn'\n--\n--   Both take an optional error code, a message, a list of located markers and a list of hints.\n--\n--   A very simple example is:\n--\n--   > exampleReport :: Report String\n--   > exampleReport =\n--   >   Err\n--   >     -- vv  OPTIONAL ERROR CODE\n--   >     Nothing\n--   >     -- vv  ERROR MESSAGE\n--   >     \"This is my first error report\"\n--   >     -- vv  MARKERS\n--   >     [ (Position (1, 3) (1, 8) \"some_test.txt\", This \"Some text under the marker\") ]\n--   >     -- vv  HINTS\n--   >     []\n--\n--   In general, 'Position's are returned by either a lexer or a parser, so that you never have to construct them\n--   directly in the code.\n--\n--   __Note__: If using any parser library, you will have to convert from the internal positioning system to a 'Position'\n--             to be able to use this library.\n--\n--   Markers put in the report can be one of (the colors specified are used only when pretty-printing):\n--\n--   - A 'Error.Diagnose.Report.This' marker, which is the primary marker of the report.\n--     While it is allowed to have multiple of these inside one report, it is encouraged not to, because the position at the top of\n--     the report will only be the one of the /first/ 'Error.Diagnose.Report.This' marker, and because the resulting report may be harder to understand.\n--\n--         This marker is output in red in an error report, and yellow in a warning report.\n--\n--   - A 'Error.Diagnose.Report.Where' marker contains additional information\\/provides context to the error\\/warning report.\n--     For example, it may underline where a given variable @x@ is bound to emphasize it.\n--\n--         This marker is output in blue.\n--\n--   - A 'Error.Diagnose.Report.Maybe' marker may contain possible fixes (if the text is short, else hints are recommended for this use).\n--\n--         This marker is output in magenta.\n--\n--   - A 'Error.Diagnose.Report.Blank' marker is useful only to output additional lines of code in the report.\n--\n--         This marker is not output and has no color.\n\n-- $create_diagnostic\n--\n--   To create a new diagnostic, you need to use its 'Data.Default.Default' instance (which exposes a 'def' function, returning a new empty 'Diagnostic').\n--   Once the 'Diagnostic' is created, you can use either 'addReport' (which takes a 'Diagnostic' and a 'Report', abstract by the same message type,\n--   and returns a 'Diagnostic') to insert a new report inside the diagnostic, or 'addFile' (which takes a 'Diagnostic', a 'FilePath' and a @['String']@,\n--   and returns a 'Diagnostic') to insert a new file reference in the diagnostic.\n--\n--   You can then either pretty-print the diagnostic obtained (which requires all messages to be instances of the 'Prettyprinter.Pretty')\n--   -- directly onto a file handle or as a plain 'Prettyprinter.Doc'ument --\n--   or export it to a lazy JSON 'Data.Bytestring.Lazy.ByteString' (e.g. in a LSP context).\n\n-- $diagnostic_pretty\n--\n--   'Diagnostic's can be output to any 'System.IO.Handle' using the 'printDiagnostic' function.\n--   This function takes several parameters:\n--\n--   - The 'System.IO.Handle' onto which to output the 'Diagnostic'.\n--     It __must__ be a 'System.IO.Handle' capable of outputting data.\n--\n--   - A 'Bool' used to indicate whether you want to output the 'Diagnostic' with unicode characters, or simple ASCII characters.\n--\n--         Here are two examples of the same diagnostic, the first output with unicode characters, and the second output with ASCII characters:\n--\n--         > [error]: Error with one marker in bounds\n--         >      ╭──▶ test.zc@1:25-1:30\n--         >      │\n--         >    1 │ let id<a>(x : a) : a := x + 1\n--         >      •                         ┬────\n--         >      •                         ╰╸ Required here\n--         > ─────╯\n--\n--         > [error]: Error with one marker in bounds\n--         >      +--> test.zc@1:25-1:30\n--         >      |\n--         >    1 | let id<a>(x : a) : a := x + 1\n--         >      :                         ^----\n--         >      :                         `- Required here\n--         > -----+\n--\n--   - A 'Bool' set to 'False' if you don't want colors in the end result.\n--\n--   - A 'Int' describing the number of spaces with which to output a TAB character.\n--\n--   - The 'Style' describing colors of the report.\n--     See the module \"Error.Diagnose.Style\" for how to define new styles.\n--\n--   - And finally the 'Diagnostic' to output.\n\n-- $diagnostic_to_doc\n--\n-- 'Diagnostic's can be “output” (at least ready to be rendered) to a 'Prettyprinter.Doc' using 'prettyDiagnostic', which allows it to be easily added to other 'Prettyprinter.Doc' outputs.\n-- This makes it easy to customize the error messages further (though not the internal parts, only adding to it).\n-- As a 'Prettyprinter.Doc', there is also the possibility of altering internal annotations (styles) much easier (although this is already possible when printing the diagnostic).\n--\n-- The arguments of the function mostly follow the ones from 'printDiagnostic'.\n-- The style is not one, as it can be applied by simply applying the styling function to the resulting function (if wanted).\n\n-- $diagnostic_json\n--\n--   'Diagnostic's can be exported to a JSON record of the following type, using the 'diagnosticToJson' function:\n--\n--   > { files:\n--   >     { name: string\n--   >     , content: string[]\n--   >     }[]\n--   > , reports:\n--   >     { kind: 'error' | 'warning'\n--   >     , code: string?\n--   >     , message: string\n--   >     , markers:\n--   >         { kind: 'this' | 'where' | 'maybe'\n--   >         , position:\n--   >             { beginning: { line: int, column: int }\n--   >             , end: { line: int, column: int }\n--   >             , file: string\n--   >             }\n--   >         , message: string\n--   >         }[]\n--   >     , hints: ({ note: string } | { hint: string })[]\n--   >     }[]\n--   > }\n--\n--   This is particularly useful in the context of a LSP server, where outputting or parsing a raw error yields strange results or is unnecessarily complicated.\n--\n--   Please note that this requires the flag @diagnose:json@ to be enabled (it is disabled by default in order not to include @aeson@, which is a heavy library).\n\n-- $compatibility_layers\n--\n--   There are many parsing libraries available in the Haskell ecosystem, each coming with its own way of handling errors.\n--   Eventually, one needs to be able to map errors from these libraries to 'Diagnostic's, without having to include additional code for doing so.\n--   This is where compatibility layers come in handy.\n--\n--   As of now, there are compatibility layers for these libraries:\n\n-- $compatibility_megaparsec\n--\n--   This needs the flag @diagnose:megaparsec-compat@ to be enabled.\n--\n--   Using the compatibility layer is very easy, as it is designed to be as simple as possible.\n--   One simply needs to convert the 'Text.Megaparsec.ParseErrorBundle' which is returned by running a parser into a 'Diagnostic' by using 'Error.Diagnose.Compat.Megaparsec.diagnosticFromBundle'.\n--   Several wrappers are included for easy creation of kinds (error, warning) of diagnostics.\n--\n--   __Note:__ the returned diagnostic does not include file contents, which needs to be added manually afterwards.\n--\n--   As a quick example:\n--\n--   > import qualified Text.Megaparsec as MP\n--   > import qualified Text.Megaparsec.Char as MP\n--   > import qualified Text.Megaparsec.Char.Lexer as MP\n--   >\n--   > let filename = \"<interactive>\"\n--   >     content  = \"00000a2223266\"\n--   >\n--   > let myParser = MP.some MP.decimal <* MP.eof\n--   >\n--   > let res      = MP.runParser myParser filename content\n--   >\n--   > case res of\n--   >   Left bundle ->\n--   >     let diag  = errorDiagnosticFromBundle Nothing \"Parse error on input\" Nothing bundle\n--   >            --   Creates a new diagnostic with no default hints from the bundle returned by megaparsec\n--   >         diag' = addFile diag filename content\n--   >            --   Add the file used when parsing with the same filename given to 'MP.runParser'\n--   >     in printDiagnostic stderr True 4 diag'\n--   >   Right res   -> print res\n--\n--   This example will return the following error message (assuming default instances for @'Error.Diagnose.Compat.Megaparsec.HasHints' 'Data.Void.Void' msg@):\n--\n--   > [error]: Parse error on input\n--   >      ╭──▶ <interactive>@1:6-1:7\n--   >      │\n--   >    1 │ 00000a2223266\n--   >      •      ┬\n--   >      •      ├╸ unexpected 'a'\n--   >      •      ╰╸ expecting digit, end of input, or integer\n--   > ─────╯\n\n-- $compatibility_parsec\n--\n--   This needs the flag @diagnose:parsec-compat@ to be enabled.\n--\n--   This compatibility layer allows easily converting 'Text.Parsec.Error.ParseError's into a single-report diagnostic containing all available information such\n--   as unexpected/expected tokens or error messages.\n--   The function 'Error.Diagnose.Compat.Parsec.diagnosticFromParseError' is used to perform the conversion between a 'Text.Parsec.Error.ParseError' and a 'Diagnostic'.\n--\n--   __Note:__ the returned diagnostic does not include file contents, which needs to be added manually afterwards.\n--\n--   Quick example:\n--\n--   > import qualified Text.Parsec as P\n--   >\n--   > let filename = \"<interactive>\"\n--   >     content  = \"00000a2223266\"\n--   >\n--   > let myParser = P.many1 P.digit <* P.eof\n--   >\n--   > let res      = P.parse myParser filename content\n--   >\n--   > case res of\n--   >   Left error ->\n--   >     let diag  = errorDiagnosticFromParseError Nothing \"Parse error on input\" Nothing error\n--   >            --   Creates a new diagnostic with no default hints from the bundle returned by megaparsec\n--   >         diag' = addFile diag filename content\n--   >            --   Add the file used when parsing with the same filename given to 'MP.runParser'\n--   >     in printDiagnostic stderr True 4 diag'\n--   >   Right res  -> print res\n--\n--   This will output the following error on @stderr@:\n--\n--   > [error]: Parse error on input\n--   >      ╭──▶ <interactive>@1:6-1:7\n--   >      │\n--   >    1 │ 00000a2223266\n--   >      •      ┬\n--   >      •      ├╸ unexpected 'a'\n--   >      •      ╰╸ expecting any of digit, end of input\n--   > ─────╯\n\n-- $compatibility_errors\n--\n--   - @No instance for (HasHints ??? msg) arising from a use of ‘errorDiagnosticFromBundle’@ (@???@ is any type, depending on your parser's custom error type):\n--\n--       The typeclass 'Error.Diagnose.Compat.Megaparsec.HasHints' does not have any default instances, because treatments of custom errors is highly dependent on who is using the library.\n--       As such, you will need to create orphan instances for your parser's error type.\n--\n--       Note that the message type @msg@ can be left abstract if the implements of 'Error.Diagnose.Compat.Hints.hints' is @hints _ = mempty@.\n"
  },
  {
    "path": "compiler/diagnose/stack.yaml",
    "content": "# This file was automatically generated by 'stack init'\n#\n# Some commonly used options have been documented as comments in this file.\n# For advanced use and comprehensive documentation of the format, please see:\n# https://docs.haskellstack.org/en/stable/yaml_configuration/\n\n# Resolver to choose a 'specific' stackage snapshot or a compiler version.\n# A snapshot resolver dictates the compiler version and the set of packages\n# to be used for project dependencies. For example:\n#\n# resolver: lts-3.5\n# resolver: nightly-2015-09-21\n# resolver: ghc-7.10.2\n#\n# The location of a snapshot can be provided as a file or url. Stack assumes\n# a snapshot provided as a file might change, whereas a url resource does not.\n#\n# resolver: ./custom-snapshot.yaml\n# resolver: https://example.com/snapshots/2018-01-01.yaml\nresolver: lts-18.28\n\n# User packages to be built.\n# Various formats can be used as shown in the example below.\n#\n# packages:\n# - some-directory\n# - https://example.com/foo/bar/baz-0.0.2.tar.gz\n#   subdirs:\n#   - auto-update\n#   - wai\npackages:\n- .\n# Dependency packages to be pulled from upstream that are not in the resolver.\n# These entries can reference officially published versions as well as\n# forks / in-progress versions pinned to a git hash. For example:\n#\n# extra-deps:\n# - acme-missiles-0.3\n# - git: https://github.com/commercialhaskell/stack.git\n#   commit: e7b331f14bcffb8367cd58fbfc8b40ec7642100a\n#\n# extra-deps: []\nextra-deps:\n\n# Override default flag values for local packages and extra-deps\n# flags: {}\n\n# Extra package databases containing global packages\n# extra-package-dbs: []\n\n# Control whether we use the GHC we find on the path\n# system-ghc: true\n#\n# Require a specific version of stack, using version ranges\n# require-stack-version: -any # Default\n# require-stack-version: \">=2.3\"\n#\n# Override the architecture used by stack, especially useful on Windows\n# arch: i386\n# arch: x86_64\n#\n# Extra directories used by stack for building\n# extra-include-dirs: [/path/to/dir]\n# extra-lib-dirs: [/path/to/dir]\n#\n# Allow a newer minor version of GHC than the snapshot specifies\n# compiler-check: newer-minor\n\nnix:\n  shell-file: nix/stack.nix\n"
  },
  {
    "path": "compiler/diagnose/test/megaparsec/Instances.hs",
    "content": "{-# LANGUAGE FlexibleInstances #-}\n{-# LANGUAGE MultiParamTypeClasses #-}\n\nmodule Instances where\n\nimport Data.Void (Void)\nimport Error.Diagnose\nimport Error.Diagnose.Compat.Megaparsec\n\ninstance HasHints Void msg where\n  hints _ = mempty\n"
  },
  {
    "path": "compiler/diagnose/test/megaparsec/Repro6.hs",
    "content": "{-# LANGUAGE CPP #-}\n{-# LANGUAGE FlexibleInstances #-}\n{-# LANGUAGE GADTs #-}\n{-# LANGUAGE MultiParamTypeClasses #-}\n{-# LANGUAGE OverloadedStrings #-}\n{-# LANGUAGE ScopedTypeVariables #-}\n{-# LANGUAGE TypeApplications #-}\n\n{-# OPTIONS -Wno-orphans #-}\n\nmodule Repro6 where\n\nimport Data.Bifunctor (first)\nimport Data.Char (isAlpha)\nimport Data.Text (Text)\nimport qualified Data.Text as Text (unpack)\nimport Data.Void (Void)\nimport Error.Diagnose\nimport Error.Diagnose.Compat.Megaparsec\nimport Instances ()\nimport qualified Text.Megaparsec as MP\nimport qualified Text.Megaparsec.Char as MP\nimport qualified Text.Megaparsec.Char.Lexer as MP\n\nmain :: IO ()\nmain = do\n  let filename :: FilePath = \"<interactive>\"\n      content1 :: Text = \"0000000123456\"\n      content2 :: Text = \"00000a2223266\"\n      content3 :: Text = \"aaa\\naab\\naba\\na\\nb\\n\"\n\n  let res1 = first (errorDiagnosticFromBundle Nothing \"Parse error on input\" Nothing) $ MP.runParser @Void (MP.some MP.decimal <* MP.eof) filename content1\n      res2 = first (errorDiagnosticFromBundle Nothing \"Parse error on input\" Nothing) $ MP.runParser @Void (MP.some MP.decimal <* MP.eof) filename content2\n      res3 =\n        first (errorDiagnosticFromBundle Nothing \"Parse error on input\" Nothing) $\n          let a = MP.char 'a'\n              errSkip e = do\n                MP.registerParseError e\n                _ <- MP.takeWhileP Nothing isAlpha <* MP.eol\n                return \"\"\n           in MP.runParser @Void\n                (MP.many (MP.withRecovery errSkip (MP.some a <* MP.eol)) <* MP.eof)\n                filename\n                content3\n\n  case res1 of\n    Left diag -> printDiagnostic stdout WithUnicode (TabSize 4) defaultStyle (addFile diag filename (Text.unpack content1) :: Diagnostic String)\n    Right res -> print res\n  case res2 of\n    Left diag -> printDiagnostic stdout WithUnicode (TabSize 4) defaultStyle (addFile diag filename (Text.unpack content2) :: Diagnostic String)\n    Right res -> print res\n  putStrLn \"------------- res3 ----------------\"\n  case res3 of\n    Left diag -> printDiagnostic stdout WithUnicode (TabSize 4) defaultStyle (addFile diag filename (Text.unpack content3) :: Diagnostic String)\n    Right res -> print res\n"
  },
  {
    "path": "compiler/diagnose/test/megaparsec/Spec.hs",
    "content": "{-# LANGUAGE CPP #-}\n{-# LANGUAGE FlexibleInstances #-}\n{-# LANGUAGE MultiParamTypeClasses #-}\n{-# LANGUAGE OverloadedStrings #-}\n{-# LANGUAGE ScopedTypeVariables #-}\n{-# LANGUAGE TypeApplications #-}\n\n{-# OPTIONS -Wno-orphans #-}\n\nimport Data.Bifunctor (first)\nimport Data.Text (Text)\nimport qualified Data.Text as Text (unpack)\nimport Data.Void (Void)\nimport Error.Diagnose\nimport Error.Diagnose.Compat.Megaparsec\nimport Instances ()\nimport qualified Repro6\nimport qualified Text.Megaparsec as MP\nimport qualified Text.Megaparsec.Char.Lexer as MP\n\nmain :: IO ()\nmain = do\n  let filename :: FilePath = \"<interactive>\"\n      content1 :: Text = \"0000000123456\"\n      content2 :: Text = \"00000a2223266\"\n\n  let res1 = first (errorDiagnosticFromBundle Nothing \"Parse error on input\" Nothing) $ MP.runParser @Void (MP.some MP.decimal <* MP.eof) filename content1\n      res2 = first (errorDiagnosticFromBundle Nothing \"Parse error on input\" Nothing) $ MP.runParser @Void (MP.some MP.decimal <* MP.eof) filename content2\n\n  case res1 of\n    Left diag -> printDiagnostic stdout WithUnicode (TabSize 4) defaultStyle (addFile diag filename (Text.unpack content1) :: Diagnostic String)\n    Right res -> print @[Integer] res\n  case res2 of\n    Left diag -> printDiagnostic stdout WithUnicode (TabSize 4) defaultStyle (addFile diag filename (Text.unpack content2) :: Diagnostic String)\n    Right res -> print @[Integer] res\n\n  putStrLn \"---------------------------------------------------\"\n\n  Repro6.main\n"
  },
  {
    "path": "compiler/diagnose/test/parsec/Repro2.hs",
    "content": "{-# LANGUAGE FlexibleContexts #-}\n{-# LANGUAGE FlexibleInstances #-}\n{-# LANGUAGE MultiParamTypeClasses #-}\n{-# OPTIONS_GHC -fno-warn-orphans #-}\n\nmodule Repro2 where\n\nimport Data.Void\nimport Error.Diagnose\nimport Error.Diagnose.Compat.Parsec\nimport Text.Parsec\nimport Text.Parsec.Token\n\ninstance HasHints Void String where hints _ = mempty\n\ntype Parser = Parsec String ()\n\ndiagParse :: Parser a -> SourceName -> String -> Either (Diagnostic String) a\ndiagParse p filename content =\n  either (Left . diag) Right (parse p filename content)\n  where\n    diag e = addFile (errorDiagnosticFromParseError Nothing \"Parse error on input\" Nothing e) filename content\n\nparser1 :: Parser Char\nparser1 = op \"\\\\\" *> letter\n\nparser2 :: Parser Char\nparser2 = op' \"\\\\\" *> letter\n\nmain :: IO ()\nmain = do\n  either (printDiagnostic stderr WithUnicode (TabSize 4) defaultStyle) print $ diagParse parser1 \"issues/2.txt\" \"\\\\1\"\n  either (printDiagnostic stderr WithUnicode (TabSize 4) defaultStyle) print $ diagParse parser2 \"issues/2.txt\" \"\\\\1\"\n\n-- smaller example\nop' :: String -> Parser String\nop' name = string name <* spaces\n\nop :: String -> Parser ()\nop =\n  reservedOp $\n    makeTokenParser\n      LanguageDef\n        { commentStart = \"{-\",\n          commentEnd = \"-}\",\n          commentLine = \"--\",\n          reservedOpNames = [\"\\\\\"],\n          opStart = oneOf \"\\\\\",\n          opLetter = oneOf \"\\\\\"\n        }\n"
  },
  {
    "path": "compiler/diagnose/test/parsec/Spec.hs",
    "content": "{-# LANGUAGE CPP #-}\n{-# LANGUAGE FlexibleInstances #-}\n{-# LANGUAGE MultiParamTypeClasses #-}\n{-# LANGUAGE OverloadedStrings #-}\n{-# LANGUAGE ScopedTypeVariables #-}\n\n{-# OPTIONS -Wno-orphans #-}\n\nimport Data.Bifunctor (first)\nimport Data.Text (Text)\nimport qualified Data.Text as Text (unpack)\nimport Data.Void (Void)\nimport Error.Diagnose\nimport Error.Diagnose.Compat.Parsec\n--\nimport qualified Repro2 as Issue2\n--\nimport qualified Text.Parsec as P\n\ninstance HasHints Void Text where hints _ = mempty\n\nmain :: IO ()\nmain = do\n  let filename :: FilePath = \"<interactive>\"\n      content1 :: Text = \"0000000123456\"\n      content2 :: Text = \"00000a2223266\"\n      content3 :: Text = \"aab\"\n\n  let res1 = first (errorDiagnosticFromParseError Nothing \"Parse error on input\" Nothing) $ P.parse (P.many1 P.digit <* P.eof) filename content1\n      res2 = first (errorDiagnosticFromParseError Nothing \"Parse error on input\" Nothing) $ P.parse (P.many1 P.digit <* P.eof) filename content2\n      res3 = first (errorDiagnosticFromParseError Nothing \"Parse error on input\" Nothing) $ P.parse (test1 <* P.eof) filename content3\n\n  case res1 of\n    Left diag -> printDiagnostic stdout WithUnicode (TabSize 4) defaultStyle (addFile diag filename (Text.unpack content1) :: Diagnostic String)\n    Right res -> print res\n  case res2 of\n    Left diag -> printDiagnostic stdout WithUnicode (TabSize 4) defaultStyle (addFile diag filename (Text.unpack content2) :: Diagnostic String)\n    Right res -> print res\n  case res3 of\n    Left diag -> printDiagnostic stdout WithUnicode (TabSize 4) defaultStyle (addFile diag filename (Text.unpack content3) :: Diagnostic String)\n    Right res -> print res\n\n  -- all issue reproduction\n  Issue2.main\n\ntest1 = P.many (P.string \"a\") *> P.string \"b\" *> P.many1 (P.string \"c\")\n"
  },
  {
    "path": "compiler/diagnose/test/rendering/Spec.hs",
    "content": "{-# LANGUAGE CPP #-}\n{-# LANGUAGE ParallelListComp #-}\n{-# LANGUAGE ScopedTypeVariables #-}\n{-# OPTIONS_GHC -Wno-incomplete-uni-patterns #-}\n\n#ifdef USE_AESON\nimport qualified Data.ByteString.Lazy as BS\nimport Error.Diagnose(diagnosticToJson)\n#endif\nimport Data.HashMap.Lazy (HashMap)\nimport qualified Data.HashMap.Lazy as HashMap\nimport Error.Diagnose\n  ( Marker (..),\n    Note (..),\n    Position (..),\n    Report(..),\n    addFile,\n    addReport,\n    defaultStyle,\n    printDiagnostic,\n    printDiagnostic',\n    stdout,\n    WithUnicode (..),\n    TabSize (..),\n  )\nimport System.IO (hPutStrLn)\nimport Prettyprinter (Doc, annotate, pretty, hsep, indent, vsep, nest, (<+>), align, list)\nimport Prettyprinter.Util (reflow)\nimport Prettyprinter.Render.Terminal (AnsiStyle, Color (..), color, bold, italicized, underlined)\nimport Data.Traversable (mapAccumL)\nimport Data.Functor.Compose (Compose(..))\n\nmain :: IO ()\nmain = do\n  let files :: HashMap FilePath String =\n        HashMap.fromList\n          [ (\"test.zc\", \"let id<a>(x : a) : a := x + 1\\nrec fix(f) := f(fix(f))\\nlet const<a, b>(x : a, y : b) : a := x\"),\n            (\"somefile.zc\", \"let id<a>(x : a) : a := x\\n  + 1\"),\n            (\"err.nst\", \"\\n\\n\\n\\n    = jmp g\\n\\n    g: forall(s: Ts, e: Tc).{ %r0: *s64 | s -> e }\"),\n            (\"unsized.nst\", \"main: forall(a: Ta, s: Ts, e: Tc).{ %r5: forall().{| s -> e } | s -> %r5 }\\n    = salloc a\\n    ; sfree\\n\"),\n            (\"unicode.txt\", \"±⅀\\t★♲♥🎉汉⑳⓴ჳᏁℳ爪\"),\n            (\"gaps.txt\", \"abc\\ndef\\nghi\\njkl\\nmno\\npqr\"),\n            (\"repro3.file\", \"\\n\\n  ayo yoa\\n    a b\\n      c d e f g\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\n\\nlayer qwertyy using yoooo: \\\"a\\\" \\\"b\\\" \\\"c\\\"\\n\")\n          ]\n\n  let reports =\n        [ errorNoMarkersNoHints,\n          errorSingleMarkerNoHints,\n          warningSingleMarkerNoHints,\n          errorTwoMarkersSameLineNoOverlapNoHints,\n          errorSingleMarkerOutOfBoundsNoHints,\n          errorTwoMarkersSameLineOverlapNoHints,\n          errorTwoMarkersSameLinePartialOverlapNoHints,\n          errorTwoMarkersTwoLinesNoHints,\n          realWorldExample,\n          errorTwoMarkersSamePositionNoHints,\n          errorThreeMarkersWithOverlapNoHints,\n          errorWithMultilineErrorNoMarkerNoHints,\n          errorSingleMultilineMarkerMessageNoHints,\n          errorTwoMarkersSameOriginOverlapNoHints,\n          errorNoMarkersSingleHint,\n          errorNoMarkersSingleMultilineHint,\n          errorNoMarkersTwoHints,\n          errorSingleMultilineMarkerNoHints,\n          errorTwoMarkersWithMultilineNoHints,\n          errorTwoMultilineMarkersNoHints,\n          errorSingleMultilineMarkerMultilineMessageNoHints,\n          errorTwoMultilineMarkersFirstMultilineMessageNoHints,\n          errorThreeMultilineMarkersTwoMultilineMessageNoHints,\n          errorOrderSensitive,\n          errorMultilineAfterSingleLine,\n          errorOnEmptyLine,\n          errorMultipleFiles,\n          errorWithCode,\n          errorWithStrangeUnicodeInput,\n          errorWithMultilineMarkerOn3Lines,\n          errorMultilineMarkerNotAtEnd,\n          errorWithLineGap,\n          repro3,\n          errorWithMultilineMarkerMessage,\n          errorWithMultilineMarkerMessage',\n          errorWithSingleBlankMarker,\n          errorWithBlankAndNormalMarkerInLine,\n          beautifulExample\n        ]\n      customAnnReports =\n        [ colorfulReport,\n          indentedReport,\n          nestingReport\n        ]\n\n  let diag = HashMap.foldlWithKey' addFile (foldl addReport mempty reports) files\n      customDiag = HashMap.foldlWithKey' addFile (foldl addReport mempty customAnnReports) files\n\n  hPutStrLn stdout \"\\n\\nWith unicode: ─────────────────────────\\n\"\n  printDiagnostic stdout WithUnicode (TabSize 4) defaultStyle diag\n  hPutStrLn stdout \"\\n\\nWithout unicode: ----------------------\\n\"\n  printDiagnostic stdout WithoutUnicode (TabSize 4) defaultStyle diag\n  hPutStrLn stdout \"\\n\\nWith custom annotations: ----------------------\\n\"\n  printDiagnostic' stdout WithUnicode (TabSize 4) defaultStyle customDiag\n#ifdef USE_AESON\n  hPutStrLn stdout \"\\n\\nAs JSON: ------------------------------\\n\"\n  BS.hPutStr stdout (diagnosticToJson diag)\n#endif\n  hPutStrLn stdout \"\\n\"\n\ncolorfulReport :: Report (Doc AnsiStyle)\ncolorfulReport =\n  fmap hsep\n    . getCompose\n    . snd\n    . mapAccumL\n      (\\(c : cs) s -> (cs, annotate c (pretty s)))\n      styles\n    . Compose\n    . fmap words\n    $ realWorldExample\n where\n  styles = [ color fg <> e\n      | fg <- cycle [Black, Red, Green, Yellow, Blue, Magenta, Cyan, White]\n      | e <- cycle [bold, italicized, underlined]\n      ]\n\nindentedReport :: Report (Doc AnsiStyle)\nindentedReport =\n  Err\n    Nothing\n    (\"Indent...\" <> indent 3 (vsep [\"foo\", \"bar\", \"baz\"]))\n    [ (Position (1, 15) (1, 16) \"test.zc\", Maybe a)\n    , (Position (1, 11) (1, 12) \"test.zc\", This b)\n    ]\n    [Note c]\n where\n  a =\n    vsep\n      [ \"A woman’s face with Nature’s own hand painted\"\n      , \"Hast thou, the master-mistress of my passion;\"\n      , \"A woman’s gentle heart, but not acquainted\"\n      , \"With shifting change, as is false women’s fashion;\"\n      ]\n  b =\n    vsep\n      [ \"An eye more bright than theirs, less false in rolling,\"\n      , \"Gilding the object whereupon it gazeth;\"\n      , \"A man in hue, all “hues” in his controlling,\"\n      , \"Which steals men’s eyes and women’s souls amazeth.\"\n      ]\n  c =\n    vsep\n      [ \"And for a woman wert thou first created;\"\n      , \"Till Nature, as she wrought thee, fell a-doting,\"\n      , \"And by addition me of thee defeated,\"\n      , \"By adding one thing to my purpose nothing.\"\n      , indent 4 \"But since she prick’d thee out for women’s pleasure,\"\n      , indent 4 \"Mine be thy love and thy love’s use their treasure.\"\n      ]\n\nnestingReport :: Report (Doc AnsiStyle)\nnestingReport =\n  Err\n    Nothing\n    (nest 4 $ vsep [\"Nest...\", \"foo\", \"bar\", \"baz\"])\n    [ (Position (1, 15) (1, 16) \"test.zc\", Maybe a)\n    ]\n    [Note b, Hint c]\n where\n  a =\n    nest 3 $\n      vsep\n        [ \"'What day is it?' asked Pooh.\"\n        , \"'It's today,' squeaked Piglet.\"\n        , \"'My favourite day,' said Pooh.\"\n        ]\n  b =\n    foldr1\n      (\\p q -> nest 2 (vsep [p, q]))\n      [ \"It's a very funny thought that, if Bears were Bees,\"\n      , \"They'd build their nests at the bottom of trees.\"\n      , \"And that being so (if the Bees were Bears),\"\n      , \"We shouldn't have to climb up all these stairs.\"\n      ]\n  c =\n    \"The elements:\"\n      <+> align\n        ( list\n            [ \"antimony\"\n            , \"arsenic\"\n            , \"aluminum\"\n            , \"selenium\"\n            , \"hydrogen\"\n            , \"oxygen\"\n            , \"nitrogen\"\n            , \"rhenium\"\n            , align $ reflow \"And there may be many others, but they haven't been discovered\"\n            ]\n        )\n\n\nerrorNoMarkersNoHints :: Report String\nerrorNoMarkersNoHints =\n  Err\n    Nothing\n    \"Error with no marker\"\n    []\n    []\n\nerrorSingleMarkerNoHints :: Report String\nerrorSingleMarkerNoHints =\n  Err\n    Nothing\n    \"Error with one marker in bounds\"\n    [(Position (1, 25) (1, 30) \"test.zc\", This \"Required here\")]\n    []\n\nwarningSingleMarkerNoHints :: Report String\nwarningSingleMarkerNoHints =\n  Warn\n    Nothing\n    \"Warning with one marker in bounds\"\n    [(Position (1, 25) (1, 30) \"test.zc\", This \"Required here\")]\n    []\n\nerrorTwoMarkersSameLineNoOverlapNoHints :: Report String\nerrorTwoMarkersSameLineNoOverlapNoHints =\n  Err\n    Nothing\n    \"Error with two markers in bounds (no overlap) on the same line\"\n    [ (Position (1, 5) (1, 10) \"test.zc\", This \"First\"),\n      (Position (1, 15) (1, 22) \"test.zc\", Where \"Second\")\n    ]\n    []\n\nerrorSingleMarkerOutOfBoundsNoHints :: Report String\nerrorSingleMarkerOutOfBoundsNoHints =\n  Err\n    Nothing\n    \"Error with one marker out of bounds\"\n    [(Position (10, 5) (10, 15) \"test2.zc\", This \"Out of bounds\")]\n    []\n\nerrorTwoMarkersSameLineOverlapNoHints :: Report String\nerrorTwoMarkersSameLineOverlapNoHints =\n  Err\n    Nothing\n    \"Error with two overlapping markers in bounds\"\n    [ (Position (1, 6) (1, 13) \"test.zc\", This \"First\"),\n      (Position (1, 10) (1, 15) \"test.zc\", Where \"Second\")\n    ]\n    []\n\nerrorTwoMarkersSameLinePartialOverlapNoHints :: Report String\nerrorTwoMarkersSameLinePartialOverlapNoHints =\n  Err\n    Nothing\n    \"Error with two partially overlapping markers in bounds\"\n    [ (Position (1, 5) (1, 25) \"test.zc\", This \"First\"),\n      (Position (1, 12) (1, 20) \"test.zc\", Where \"Second\")\n    ]\n    []\n\nerrorTwoMarkersTwoLinesNoHints :: Report String\nerrorTwoMarkersTwoLinesNoHints =\n  Err\n    Nothing\n    \"Error with two markers on two lines in bounds\"\n    [ (Position (1, 5) (1, 12) \"test.zc\", This \"First\"),\n      (Position (2, 3) (2, 4) \"test.zc\", Where \"Second\")\n    ]\n    []\n\nrealWorldExample :: Report String\nrealWorldExample =\n  Err\n    Nothing\n    \"Could not deduce constraint 'Num(a)' from the current context\"\n    [ (Position (1, 25) (1, 30) \"test.zc\", This \"While applying function '+'\"),\n      (Position (1, 11) (1, 16) \"test.zc\", Where \"'x' is supposed to have type 'a'\"),\n      (Position (1, 8) (1, 9) \"test.zc\", Where \"type 'a' is bound here without constraints\")\n    ]\n    [\"Adding 'Num(a)' to the list of constraints may solve this problem.\"]\n\nerrorTwoMarkersSamePositionNoHints :: Report String\nerrorTwoMarkersSamePositionNoHints =\n  Err\n    Nothing\n    \"Error with two markers on the same exact position in bounds\"\n    [ (Position (1, 6) (1, 10) \"test.zc\", This \"First\"),\n      (Position (1, 6) (1, 10) \"test.zc\", Maybe \"Second\")\n    ]\n    []\n\nerrorThreeMarkersWithOverlapNoHints :: Report String\nerrorThreeMarkersWithOverlapNoHints =\n  Err\n    Nothing\n    \"Error with three markers with overlapping in bounds\"\n    [ (Position (1, 9) (1, 15) \"test.zc\", This \"First\"),\n      (Position (1, 9) (1, 18) \"test.zc\", Maybe \"Second\"),\n      (Position (1, 6) (1, 10) \"test.zc\", Where \"Third\")\n    ]\n    []\n\nerrorWithMultilineErrorNoMarkerNoHints :: Report String\nerrorWithMultilineErrorNoMarkerNoHints =\n  Err\n    Nothing\n    \"Error with multi\\nline message and no markers\"\n    []\n    []\n\nerrorSingleMultilineMarkerMessageNoHints :: Report String\nerrorSingleMultilineMarkerMessageNoHints =\n  Err\n    Nothing\n    \"Error with single marker with multiline message\"\n    [(Position (1, 9) (1, 15) \"test.zc\", This \"First\\nmultiline\")]\n    []\n\nerrorTwoMarkersSameOriginOverlapNoHints :: Report String\nerrorTwoMarkersSameOriginOverlapNoHints =\n  Err\n    Nothing\n    \"Error with two markers with same origin but partial overlap in bounds\"\n    [ (Position (1, 9) (1, 15) \"test.zc\", This \"First\"),\n      (Position (1, 9) (1, 20) \"test.zc\", Maybe \"Second\")\n    ]\n    []\n\nerrorNoMarkersSingleHint :: Report String\nerrorNoMarkersSingleHint =\n  Err\n    Nothing\n    \"Error with no marker and one hint\"\n    []\n    [\"First hint\"]\n\nerrorNoMarkersSingleMultilineHint :: Report String\nerrorNoMarkersSingleMultilineHint =\n  Err\n    Nothing\n    \"Error with no marker and one multiline hint\"\n    []\n    [\"First multi\\nline hint\"]\n\nerrorNoMarkersTwoHints :: Report String\nerrorNoMarkersTwoHints =\n  Err\n    Nothing\n    \"Error with no markers and two hints\"\n    []\n    [ \"First note\",\n      Hint \"Second hint\"\n    ]\n\nerrorSingleMultilineMarkerNoHints :: Report String\nerrorSingleMultilineMarkerNoHints =\n  Err\n    Nothing\n    \"Error with single marker spanning across multiple lines\"\n    [(Position (1, 15) (2, 6) \"test.zc\", This \"First\")]\n    []\n\nerrorTwoMarkersWithMultilineNoHints :: Report String\nerrorTwoMarkersWithMultilineNoHints =\n  Err\n    Nothing\n    \"Error with two markers, one single line and one multiline, in bounds\"\n    [ (Position (1, 9) (1, 13) \"test.zc\", This \"First\"),\n      (Position (1, 14) (2, 6) \"test.zc\", Where \"Second\")\n    ]\n    []\n\nerrorTwoMultilineMarkersNoHints :: Report String\nerrorTwoMultilineMarkersNoHints =\n  Err\n    Nothing\n    \"Error with two multiline markers in bounds\"\n    [ (Position (1, 9) (2, 5) \"test.zc\", This \"First\"),\n      (Position (2, 1) (3, 10) \"test.zc\", Where \"Second\")\n    ]\n    []\n\nerrorSingleMultilineMarkerMultilineMessageNoHints :: Report String\nerrorSingleMultilineMarkerMultilineMessageNoHints =\n  Err\n    Nothing\n    \"Error with one multiline marker with a multiline message in bounds\"\n    [(Position (1, 9) (2, 5) \"test.zc\", This \"Multi\\nline message\")]\n    []\n\nerrorTwoMultilineMarkersFirstMultilineMessageNoHints :: Report String\nerrorTwoMultilineMarkersFirstMultilineMessageNoHints =\n  Err\n    Nothing\n    \"Error with two multiline markers with one multiline message in bounds\"\n    [ (Position (1, 9) (2, 5) \"test.zc\", This \"First\"),\n      (Position (1, 9) (2, 6) \"test.zc\", Where \"Multi\\nline message\")\n    ]\n    []\n\nerrorThreeMultilineMarkersTwoMultilineMessageNoHints :: Report String\nerrorThreeMultilineMarkersTwoMultilineMessageNoHints =\n  Err\n    Nothing\n    \"Error with three multiline markers with two multiline messages in bounds\"\n    [ (Position (1, 9) (2, 5) \"test.zc\", This \"First\"),\n      (Position (1, 9) (2, 6) \"test.zc\", Where \"Multi\\nline message\"),\n      (Position (1, 9) (2, 7) \"test.zc\", Maybe \"Multi\\nline message #2\")\n    ]\n    []\n\nerrorOrderSensitive :: Report String\nerrorOrderSensitive =\n  Err\n    Nothing\n    \"Order-sensitive labels with crossing\"\n    [ (Position (1, 1) (1, 7) \"somefile.zc\", This \"Leftmost label\"),\n      (Position (1, 9) (1, 16) \"somefile.zc\", Where \"Rightmost label\")\n    ]\n    []\n\nbeautifulExample :: Report String\nbeautifulExample =\n  Err\n    Nothing\n    \"Could not deduce constraint 'Num(a)' from the current context\"\n    [ (Position (1, 25) (2, 6) \"somefile.zc\", This \"While applying function '+'\"),\n      (Position (1, 11) (1, 16) \"somefile.zc\", Where \"'x' is supposed to have type 'a'\"),\n      (Position (1, 8) (1, 9) \"somefile.zc\", Where \"type 'a' is bound here without constraints\")\n    ]\n    [\"Adding 'Num(a)' to the list of constraints may solve this problem.\"]\n\nerrorMultilineAfterSingleLine :: Report String\nerrorMultilineAfterSingleLine =\n  Err\n    Nothing\n    \"Multiline after single line\"\n    [ (Position (1, 17) (1, 18) \"unsized.nst\", Where \"Kind is infered from here\"),\n      (Position (2, 14) (3, 0) \"unsized.nst\", This \"is an error\")\n    ]\n    []\n\nerrorOnEmptyLine :: Report String\nerrorOnEmptyLine =\n  Err\n    Nothing\n    \"Error on empty line\"\n    [(Position (1, 5) (3, 8) \"err.nst\", This \"error on empty line\")]\n    []\n\nerrorMultipleFiles :: Report String\nerrorMultipleFiles =\n  Err\n    Nothing\n    \"Error on multiple files\"\n    [ (Position (1, 5) (1, 7) \"test.zc\", Where \"Function already declared here\"),\n      (Position (1, 5) (1, 7) \"somefile.zc\", This \"Function `id` is already declared in another module\")\n    ]\n    []\n\nerrorWithCode :: Report String\nerrorWithCode =\n  Err\n    (Just \"E0123\")\n    \"Error with code and markers\"\n    [(Position (1, 5) (1, 7) \"test.zc\", This \"is an error\")]\n    []\n\nerrorWithStrangeUnicodeInput :: Report String\nerrorWithStrangeUnicodeInput =\n  Err\n    (Just \"❎\")\n    \"ⓈⓉⓇⒶⓃⒼⒺ ⓊⓃⒾⒸⓄⒹⒺ\"\n    [ (Position (1, 1) (1, 7) \"unicode.txt\", This \"should work fine 🎉\"),\n      (Position (1, 7) (1, 9) \"unicode.txt\", Where \"After TAB\")\n    ]\n    []\n\nerrorWithMultilineMarkerOn3Lines :: Report String\nerrorWithMultilineMarkerOn3Lines =\n  Err\n    Nothing\n    \"Multiline marker on 3 lines\"\n    [(Position (1, 3) (3, 10) \"test.zc\", This \"should color all 3 lines correctly\")]\n    []\n\nerrorMultilineMarkerNotAtEnd :: Report String\nerrorMultilineMarkerNotAtEnd =\n  Err\n    Nothing\n    \"Multiline marker not at end of report\"\n    [ (Position (1, 10) (2, 3) \"test.zc\", This \"is a multline marker\"),\n      (Position (3, 5) (3, 13) \"test.zc\", Where \"inline marker found after\")\n    ]\n    []\n\nerrorWithLineGap :: Report String\nerrorWithLineGap =\n  Err\n    Nothing\n    \"Error with line gaps between two markers\"\n    [ (Position (1, 1) (1, 3) \"gaps.txt\", Where \"is a first marker\"),\n      (Position (5, 2) (5, 4) \"gaps.txt\", This \"is the main marker\")\n    ]\n    []\n\nerrorWithMultilineMarkerMessage :: Report String\nerrorWithMultilineMarkerMessage =\n  Err\n    Nothing\n    \"Error with multiline message in first marker\"\n    [ (Position (1, 5) (1, 10) \"test.zc\", This \"First\\nmarker\"),\n      (Position (1, 15) (1, 22) \"test.zc\", Where \"Second\")\n    ]\n    []\n\nerrorWithMultilineMarkerMessage' :: Report String\nerrorWithMultilineMarkerMessage' =\n  Err\n    Nothing\n    \"Error with multiline message in first marker\"\n    [ (Position (1, 5) (1, 10) \"test.zc\", This \"First\\nmarker\"),\n      (Position (1, 15) (1, 22) \"test.zc\", Where \"Second\"),\n      (Position (1, 10) (1, 15) \"test.zc\", Maybe \"Third\")\n    ]\n    []\n\nrepro3 :: Report String\nrepro3 =\n  Err\n    (Just \"WrongStaticLayerLength\")\n    \"The length of the static layer does not match the length of the template it uses\"\n    [ (Position (3, 3) (5, 16) \"repro3.file\", Where \"This template has 9 elements\"),\n      (Position (24, 28) (24, 39) \"repro3.file\", This \"... but this layer only has 3 members\"),\n      (Position (24, 21) (24, 26) \"repro3.file\", Where \"This is the template being used\"),\n      (Position (24, 7) (24, 15) \"repro3.file\", Where \"while checking this static layer\")\n    ]\n    []\n\nerrorWithSingleBlankMarker :: Report String\nerrorWithSingleBlankMarker =\n  Err\n    Nothing\n    \"Error with a single blank marker\"\n    [(Position (1, 5) (1, 10) \"test.zc\", Blank)]\n    []\n\nerrorWithBlankAndNormalMarkerInLine :: Report String\nerrorWithBlankAndNormalMarkerInLine =\n  Err\n    Nothing\n    \"Error with a single blank marker\"\n    [(Position (1, 5) (1, 10) \"test.zc\", Blank), (Position (1, 15) (1, 22) \"test.zc\", This \"After a blank\")]\n    []\n"
  },
  {
    "path": "compiler/lib/bench/KindsBench.hs",
    "content": "import qualified Acton.Env as Env\nimport qualified Acton.Kinds as Kinds\nimport qualified Acton.NameInfo as NameInfo\nimport qualified Acton.Parser as Parser\nimport qualified Acton.Syntax as Syntax\n\nimport Control.DeepSeq (rnf)\nimport qualified Control.Exception as E\nimport qualified Data.HashMap.Strict as HashMap\nimport Data.Time.Clock (diffUTCTime, getCurrentTime)\nimport GHC.Stats\nimport System.Environment (getArgs)\nimport System.FilePath (takeBaseName)\nimport System.IO (BufferMode(LineBuffering), hSetBuffering, stdout)\n\n-- Usage:\n--   stack build libacton:exe:kinds-bench\n--   stack exec kinds-bench -- ../dist/base/out/types path/to/file.act +RTS -T -RTS\n--\n-- This uses Parser.parseModule, the normal parallel parser entrypoint. The RTS\n-- flag is optional. With -T, the driver also prints per-phase allocation and\n-- GC deltas.\n\nelapsed label t0 t1 = putStrLn $ label ++ \" \" ++ show (diffUTCTime t1 t0)\n\nprintStats label before after =\n    putStrLn $ label ++ \" alloc \" ++ show alloc ++ \" gc_elapsed \" ++ show gcElapsed ++ \" gcs \" ++ show collections\n  where alloc = allocated_bytes after - allocated_bytes before\n        gcElapsed = gc_elapsed_ns after - gc_elapsed_ns before\n        collections = gcs after - gcs before\n\ngetStats enabled =\n    if enabled then Just <$> getRTSStats else return Nothing\n\nprintStatsMaybe label (Just before) (Just after) = printStats label before after\nprintStatsMaybe _ _ _                            = return ()\n\nforceHTEnv = HashMap.foldl' forceHNameInfo () where\n    forceHNameInfo () (NameInfo.HNModule _ te _) = forceHTEnv te\n    forceHNameInfo () hni                        = hni `seq` ()\n\nmain = do\n    hSetBuffering stdout LineBuffering\n    args <- getArgs\n    case args of\n      [typesPath, sourcePath] -> do\n        statsEnabled <- getRTSStatsEnabled\n        src <- readFile sourcePath\n        env0 <- Env.initEnv typesPath False\n        let modName = Syntax.modName [takeBaseName sourcePath]\n\n        s0 <- getStats statsEnabled\n        t0 <- getCurrentTime\n        parsed <- Parser.parseModule modName sourcePath src Nothing\n        E.evaluate (rnf parsed)\n        t1 <- getCurrentTime\n        s1 <- getStats statsEnabled\n        elapsed \"parse\" t0 t1\n        printStatsMaybe \"parse_stats\" s0 s1\n\n        env <- Env.mkEnv [typesPath] env0 parsed\n        E.evaluate (forceHTEnv (Env.hnames env))\n        E.evaluate (forceHTEnv (Env.hmodules env))\n        t2 <- getCurrentTime\n        s2 <- getStats statsEnabled\n        elapsed \"env\" t1 t2\n        printStatsMaybe \"env_stats\" s1 s2\n\n        kchecked <- Kinds.check env parsed\n        E.evaluate (rnf kchecked)\n        t3 <- getCurrentTime\n        s3 <- getStats statsEnabled\n        elapsed \"kinds\" t2 t3\n        printStatsMaybe \"kinds_stats\" s2 s3\n      _ ->\n        error \"usage: kinds-bench TYPES_PATH SOURCE.act\"\n"
  },
  {
    "path": "compiler/lib/bench/TypesBench.hs",
    "content": "import qualified Acton.Env as Env\nimport qualified Acton.Kinds as Kinds\nimport qualified Acton.NameInfo as NameInfo\nimport qualified Acton.Parser as Parser\nimport qualified Acton.Syntax as Syntax\nimport qualified Acton.Types as Types\n\nimport Control.DeepSeq (rnf)\nimport qualified Control.Exception as E\nimport qualified Data.HashMap.Strict as HashMap\nimport Data.Time.Clock (diffUTCTime, getCurrentTime)\nimport GHC.Stats\nimport System.Environment (getArgs)\nimport System.FilePath (takeBaseName)\nimport System.IO (BufferMode(LineBuffering), hSetBuffering, stdout)\n\n-- Usage:\n--   stack build libacton:exe:types-bench\n--   stack exec types-bench -- ../dist/base/out/types path/to/file.act +RTS -T -RTS\n--\n-- This uses Parser.parseModule, the normal parallel parser entrypoint. The RTS\n-- flag is optional. With -T, the driver also prints per-phase allocation and\n-- GC deltas.\n\nelapsed label t0 t1 = putStrLn $ label ++ \" \" ++ show (diffUTCTime t1 t0)\n\nprintStats label before after =\n    putStrLn $ label ++ \" alloc \" ++ show alloc ++ \" gc_elapsed \" ++ show gcElapsed ++ \" gcs \" ++ show collections\n  where alloc = allocated_bytes after - allocated_bytes before\n        gcElapsed = gc_elapsed_ns after - gc_elapsed_ns before\n        collections = gcs after - gcs before\n\ngetStats enabled =\n    if enabled then Just <$> getRTSStats else return Nothing\n\nprintStatsMaybe label (Just before) (Just after) = printStats label before after\nprintStatsMaybe _ _ _                            = return ()\n\nforceHTEnv = HashMap.foldl' forceHNameInfo () where\n    forceHNameInfo () (NameInfo.HNModule _ te _) = forceHTEnv te\n    forceHNameInfo () hni                        = hni `seq` ()\n\nmain = do\n    hSetBuffering stdout LineBuffering\n    args <- getArgs\n    case args of\n      [typesPath, sourcePath] -> do\n        statsEnabled <- getRTSStatsEnabled\n        src <- readFile sourcePath\n        env0 <- Env.initEnv typesPath False\n        let modName = Syntax.modName [takeBaseName sourcePath]\n\n        s0 <- getStats statsEnabled\n        t0 <- getCurrentTime\n        parsed <- Parser.parseModule modName sourcePath src Nothing\n        E.evaluate (rnf parsed)\n        t1 <- getCurrentTime\n        s1 <- getStats statsEnabled\n        elapsed \"parse\" t0 t1\n        printStatsMaybe \"parse_stats\" s0 s1\n\n        env <- Env.mkEnv [typesPath] env0 parsed\n        E.evaluate (forceHTEnv (Env.hnames env))\n        E.evaluate (forceHTEnv (Env.hmodules env))\n        t2 <- getCurrentTime\n        s2 <- getStats statsEnabled\n        elapsed \"env\" t1 t2\n        printStatsMaybe \"env_stats\" s1 s2\n\n        kchecked <- Kinds.check env parsed\n        E.evaluate (rnf kchecked)\n        t3 <- getCurrentTime\n        s3 <- getStats statsEnabled\n        elapsed \"kinds\" t2 t3\n        printStatsMaybe \"kinds_stats\" s2 s3\n\n        (nmod, tchecked, typeEnv, tests) <- Types.reconstruct Nothing Nothing env kchecked\n        E.evaluate (rnf nmod)\n        E.evaluate (rnf tchecked)\n        E.evaluate (forceHTEnv (Env.hnames typeEnv))\n        E.evaluate (forceHTEnv (Env.hmodules typeEnv))\n        E.evaluate (length tests)\n        t4 <- getCurrentTime\n        s4 <- getStats statsEnabled\n        elapsed \"types\" t3 t4\n        printStatsMaybe \"types_stats\" s3 s4\n      _ ->\n        error \"usage: types-bench TYPES_PATH SOURCE.act\"\n"
  },
  {
    "path": "compiler/lib/package.yaml.in",
    "content": "name:                libacton\nversion: BUILD_VERSION\n# github:              \"/simple\"\nlicense:             BSD3\nauthor:              \"Author name here\"\nmaintainer:          \"example@example.com\"\ncopyright:           \"2018 Author name here\"\n\n# Metadata used when publishing your package\n# synopsis:            Short description of your package\n# category:            Web\n\n# To avoid duplicated efforts in documentation and dealing with the\n# complications of embedding Haddock markup inside cabal files, it is\n# common to point users to the README.md file.\ndescription:         Please see the README on Github at <https://github.com/githubuser/simple#readme>\n\ndependencies:\n  - aeson\n  - aeson-pretty\n  - array\n  - async\n  - base\n  - base16-bytestring\n  - binary\n  - bytestring\n  - clock\n  - containers\n  - cryptohash-sha256\n  - deepseq\n  - diagnose\n  - dir-traverse\n  - directory >= 1.3.1\n  - filelock\n  - filepath\n  - hashable\n  - http-client\n  - http-client-tls\n  - http-types\n  - megaparsec\n  - mtl\n  - optparse-applicative\n  - parser-combinators\n  - pretty\n  - pretty-show\n  - prettyprinter\n  - process\n  - random\n  - scientific\n  - stm\n  - sydtest\n  - sydtest-discover\n  - temporary\n  - text\n  - time\n  - transformers\n  - unix\n  - unordered-containers\n  - utf8-string\n\nlibrary:\n  source-dirs: src\n  exposed-modules:\n    - Acton.Boxing\n    - Acton.BuildSpec\n    - Acton.Builtin\n    - Acton.CPS\n    - Acton.CodeGen\n    - Acton.Completion\n    - Acton.Compile\n    - Acton.CommandLineParser\n    - Acton.Deactorizer\n    - Acton.Diagnostics\n    - Acton.DocPrinter\n    - Acton.Env\n    - Acton.Fingerprint\n    - Acton.Hashing\n    - Acton.Kinds\n    - Acton.LambdaLifter\n    - Acton.NameInfo\n    - Acton.Normalizer\n    - Acton.Parser\n    - Acton.Printer\n    - Acton.QuickType\n    - Acton.Solver\n    - Acton.SourceProvider\n    - Acton.Syntax\n    - Acton.Testing\n    - Acton.Types\n    - Acton.TypeEnv\n    - Acton.WitKnots\n    - Utils\n    - Pretty\n    - InterfaceFiles\n\ntests:\n  test_lib:\n    main: ActonSpec.hs\n    source-dirs: test\n    dependencies:\n      - libacton\n    ghc-options:\n      - -threaded\n      - -rtsopts\n      - -with-rtsopts=-N\n\nexecutables:\n  kinds-bench:\n    main: KindsBench.hs\n    source-dirs: bench\n    other-modules: []\n    dependencies:\n      - libacton\n    ghc-options:\n      - -threaded\n      - -rtsopts\n      - '\"-with-rtsopts=-N -A64M\"'\n  types-bench:\n    main: TypesBench.hs\n    source-dirs: bench\n    other-modules: []\n    dependencies:\n      - libacton\n    ghc-options:\n      - -threaded\n      - -rtsopts\n      - '\"-with-rtsopts=-N -A64M\"'\n"
  },
  {
    "path": "compiler/lib/src/Acton/Boxing.hs",
    "content": "{-# LANGUAGE FlexibleInstances #-}\nmodule Acton.Boxing where\n\nimport Acton.Syntax\nimport Acton.Names\nimport Acton.NameInfo\nimport Acton.Env\nimport Acton.QuickType\nimport Acton.Prim\nimport Acton.Builtin\nimport Acton.Subst\nimport Pretty\nimport Utils\nimport Debug.Trace\nimport Control.Monad.State.Strict\nimport Control.Monad.Except\n\ndoBoxing                           :: Acton.Env.Env0 -> Module -> IO Module\ndoBoxing env m                     = do return m{mbody = ss}\n   where (_,ss)                    = runBoxM (boxing (boxEnv env) (mbody m))\n\n-- Boxing monad  ---------------------------------------------------------------------------------------------------\n\ntype BoxM a                        = State Int a\n\nnewName                            :: String -> BoxM Name\nnewName s                          = do n <- get\n                                        put (n+1)\n                                        return $ Internal BoxPass s n\n\nnewNames (n : ns)                  = do un <- newName (nstr n)\n                                        ps <- newNames ns\n                                        return ((n,un) : ps)\nnewNames []                        = return []\n\nrunBoxM ss                         = evalState ss 0\n\ndata BoxX                          = BoxX { unboxedVarsX :: [(Name,Name)], isTopLevelX :: Bool, delayedUnboxX :: Bool, inClassX :: Bool }\n\ntype BoxEnv                        = EnvF BoxX\n\nboxEnv                             :: Env0 -> BoxEnv\nboxEnv env0                        = setX env0 (BoxX [] True False False)\n\naddUnboxedVars                     :: [(Name,Name)] -> BoxEnv -> BoxEnv\naddUnboxedVars ps env               = modX env $ \\x -> x{unboxedVarsX = ps ++ unboxedVarsX x}\n\nunboxedVars                        :: BoxEnv -> [(Name,Name)]\nunboxedVars env                    = unboxedVarsX $ envX env\n\nsetTopLevel b env                  = modX env $ \\x -> x{isTopLevelX = b}\n\nisTopLevel env                     = isTopLevelX $ envX env\n\nsetDelayedUnbox b env              = modX env $ \\x -> x{delayedUnboxX = b}\n\nisDelayedUnbox env                 = delayedUnboxX $ envX env\n\n\n-- Auxiliaries ---------------------------------------------------------------------------------------------------\n\n-- unboxing\n\nintegralTypes                      = [tBigint, tInt, tI32, tI16, tU64, tU32, tU16]\nnumericTypes                       = integralTypes ++ [tFloat]\nunboxableTypes                     = tail numericTypes\n\nisUnboxable t                      = t `elem` unboxableTypes\n\nprims = [primISINSTANCE, primISNOTNONE, primISNONE]\n\nunboxedPrim p\n  | p == primISINSTANCE            = primISINSTANCE0\n  | p == primISNOTNONE             = primISNOTNONE0\n  | p == primISNONE                = primISNONE0\n\nqMath str = QName (ModName [name \"math\"]) (name str)\n\nmathfuns = map qMath [\"sqrt\", \"exp\", \"log\", \"sin\", \"cos\", \"tan\", \"asin\", \"acos\", \"atan\",  \"sinh\", \"cosh\", \"tanh\",  \"asinh\", \"acosh\", \"atanh\"]\n\n-- class UnBoxClass ---------------------------------------------------------------------------------------------------\n\nclass UnboxClass a where\n    unbox :: Type -> a -> a\n\ninstance UnboxClass Expr where\n   unbox _ (Box _ e)               = e\n   unbox t e                       = UnBox t e\n\ninstance UnboxClass PosArg where\n   unbox t (PosArg e p)            = PosArg (unbox t e) (unbox t p)\n   unbox t (PosStar e)             = PosStar (unbox t e)\n   unbox t PosNil                  = PosNil\n\n-- Walking the syntax tree to place Box/UnBox annotations and sometimes restructure code to mimic C code on unboxed values ---------------\n\nclass Boxing a where\n    boxing :: BoxEnv -> a -> BoxM ([Name],a)\n\ninstance {-# OVERLAPS #-} Boxing ([Stmt]) where\n    boxing env []                     = return ([],[])\n    boxing env (x@(Assign _ [PVar _ n _] _) : xs)\n       | isWitness n                  = do (ws1,x') <- boxing env x\n                                           (ws2,xs') <- boxing env1 xs\n                                           return $ if n `elem` ws2 then (ws1++ws2,x':xs') else (ws2,xs')\n      where te                        = envOf x\n            env1                      = define te env\n    boxing env (x@(Assign l [p@(PVar _ n (Just t))] e) : xs)\n       | isUnboxable t               = do case lookup n (unboxedVars env) of\n                                              Nothing -> do (ws1, e') <- boxing env e\n                                                            un <- newName  (nstr n)\n                                                            let env1 = define (envOf x) (addUnboxedVars [(n,un)] env)\n                                                            (ws2,p') <- boxing env1 p\n                                                            (ws3,xs') <- boxing env1 xs\n                                                            let ss = if isTopLevel env1 then [sAssign p (Box t (eVar un))] else []\n                                                            return (ws1++ws2++ws3, Assign l [p'] (if isUnboxed (pn p') then unbox t e' else e') : ss ++ xs')\n                                              Just un -> do (ws1,x') <- boxing env x\n                                                            (ws2,xs') <- boxing (define (envOf x) env) xs\n                                                            let ss = if isTopLevel env then [sAssign p (Box t (eVar un))] else []\n                                                            return (ws1++ws2, x' : ss ++ xs')\n\n    boxing env (x@If{} : xs)         = do ns <- newNames [ n | (n,NVar t) <- te, isUnboxable t ]\n                                          let env1 = addUnboxedVars ns env\n                                          (ws1,x') <- boxing env1 x\n                                          (ws2,xs') <- boxing (define te env1) xs\n                                          return (ws1++ws2, x' : xs')\n      where te                       = envOf x\n\n    boxing env (x : xs)              = do ps <- if (inClass env) then return [] else newNames [n | (n,NDef (TSchema _ [] (TFun _ _ p _ t)) _ _) <- te, isUnboxable t ||  hasUnboxableType p]\n                                          (ws1,x') <- boxing (addUnboxedVars ps env) x\n                                          (ws2,xs') <- boxing (addUnboxedVars ps env1) xs\n                                          return (ws1++ws2, x' : xs')\n      where te                       = envOf x\n            env1                     = define te env\n            hasUnboxableType (TRow _ _ _ t r)\n                                     = isUnboxable t || hasUnboxableType r\n            hasUnboxableType _       = False\n\n\ninstance (Boxing a) => Boxing ([a]) where\n    boxing env []                   = return ([],[])\n    boxing env (x : xs)             = do (ws1,x1)  <- boxing env x\n                                         (ws2,xs2) <- boxing env xs\n                                         return (ws1++ws2, x1:xs2)\n\ninstance Boxing a => Boxing (Maybe a) where\n    boxing env (Just x)           = do (ws1, x1) <- boxing env x\n                                       return (ws1, Just x1)\n    boxing env Nothing            = return ([], Nothing)\n\n\ninstance Boxing Expr where\n    boxing env e@(Var l (NoQ n))\n       | isWitness n                = return ([n], e)\n       | otherwise                  = case lookup n ps of\n                                          Just un -> return ([], Box (typeOf env e) (eVar un))\n                                          Nothing -> return ([], e)\n       where ps                     = unboxedVars env\n    boxing env v@Var{}              = return ([], v)\n    boxing env (Call _ (Dot _ e@(Var _ w@(NoQ n)) attr) p KwdNil)\n      | isWitness n                 = do (ws1,p1) <- boxing env p\n                                         (ws2,e1) <- boxingWitness env w attr ws1 p1\n                                         return (ws1++ws2,e1)\n      | attr == nextKW              = return ([n], eCallP (eDot (eQVar w) attr) p) \n     where\n      boxingWitness                 :: BoxEnv -> QName -> Name -> [Name] ->PosArg -> BoxM ([Name],Expr)\n      boxingWitness env w attr ws p = case findQName w env of\n                                        NVar (TCon _ (TC _ ts))\n                                           | any (not . vFree) ts    -> return ([n], eCallP (eDot (eQVar w) attr) p)\n                                           | attr == fromatomKW      -> boxingFromAtom w ts es\n                                           | attr == getitemKW       -> boxingGetItem w ts es\n                                           | attr `elem` binopKWs    -> boxingBinop w attr es ts\n                                           | attr `elem` eqordKWs    -> boxingCompop w attr es ts\n                                        _                            -> return ([n], eCallP (eDot (eQVar w) attr) p)\n       where es                     = posargs p\n             vFree (TCon _ (TC _ _))= True\n             vFree _                = False\n      boxingFromAtom w ts [i@Int{}]\n        | t == tBigint                 = return ([], i)\n        | t `elem` numericTypes     = return ([], Box (last ts) (unbox t i))\n        where t = head ts\n      boxingFromAtom w ts [x@Float{}]\n                                    = return ([], Box (last ts) (unbox (head ts) x))\n      boxingFromAtom w ts es        = return ([n], eCall (eDot (eQVar w) fromatomKW) es)\n      boxingGetItem w (t0:t:t1:_) es@[a, k]       \n        | t == tInt && tn == qnList = return ([], eCall (tApp (eQVar primUGetItem) [t1]) [a, unbox t k])  -- only list indexing optimized. TODO: str indexing\n        where TCon _ (TC tn _)      = t0\n      boxingGetItem w ts es         = return ([n], eCall (eDot (eQVar w) attr) es)\n   --   boxingNext w ts []\n      boxingBinop w attr es@[x1, x2] ts\n        | isUnboxable t            =  return ([], Box (last ts) $ Paren NoLoc $ BinOp NoLoc (unbox t x1) op (unbox t x2))\n        where t                     = head ts\n              op                    = bin2Binary attr\n      boxingBinop w attr es _       = return ([n], eCall (eDot (eQVar w) attr) es)\n\n      boxingCompop w attr es@[x1, x2] ts\n        | isUnboxable t             = return ([], Box tBool $ Paren NoLoc $ CompOp NoLoc (unbox t x1) [OpArg op (unbox t x2)])\n        where t = head ts\n              op = cmp2Comparison attr\n      boxingCompop w attr es _      = return ([n], eCall (eDot (eQVar w) attr) es)\n    boxing env (Call l e@(TApp _ (Var _ f) ts) p KwdNil)\n      | f `elem` prims              = do (ws1,p1) <- boxing env p\n                                         return (ws1,Box tBool $ eCallP e' p1)\n      | otherwise                   = do (ws1,p1) <- boxing env p\n                                         return (ws1, eCallP e p1)\n       where e'                     = tApp (eQVar (unboxedPrim f)) ts\n    boxing env c@(Call l e@(Var _ (NoQ n)) p KwdNil)\n      | isUnboxable t               = do (ws1,p1) <- boxing env p\n                                         case lookup n (unboxedVars env) of\n                                            Just un -> return (ws1, Box t (eCallP (eVar un) (ub env p1)))\n                                            Nothing -> return (ws1, eCallP e p1)\n       where t                      = typeOf env c\n             ub env (PosArg e p)\n               | isUnboxable t      = PosArg (unbox t e) (ub env p)\n               | otherwise          = PosArg e (ub env p)\n              where t = typeOf env e\n             ub env (PosStar e)\n               | isUnboxable t      = PosStar (unbox t e)\n               | otherwise          = PosStar e\n              where t = typeOf env e\n             ub env PosNil          = PosNil\n    boxing env (Call l e@(Var _ f) p KwdNil)\n      | f `elem`prims               = do (ws1,p1) <- boxing env p\n                                         return (ws1,Box tBool $ eCallP e' p1)\n      | f `elem` mathfuns           = do (ws1,p1)  <- boxing env p\n                                         return (ws1,Box tFloat $ eCallP e (unbox tFloat p1))\n      | otherwise                   = do (ws1,p1) <- boxing env p\n                                         return (ws1, eCallP e p1)\n       where e'                     = eQVar (unboxedPrim f)\n    boxing env (Call l f p KwdNil)  = do (ws1,f1) <- boxing env f\n                                         (ws2,p1) <- boxing env p\n                                         return (ws1++ws2, eCallP f1 p1)\n    boxing env (TApp l f ts)        = do (ws1,f1) <- boxing env f\n                                         return (ws1, TApp l f1 ts)\n    boxing env (Let l ss e)         = do (ws1, ss') <- boxing env ss\n                                         (ws2, e') <- boxing env e\n                                         return (ws1++ws2, Let l ss' e')\n    boxing env (Async l e)          = do (ws1,e1) <- boxing env e\n                                         return (ws1, Async l e1)\n    boxing env (Await l e)          = do (ws1,e1) <- boxing env e\n                                         return (ws1, Await l e1)\n    boxing env (Index l e1 e2)      = do (ws1,e1') <- boxing env e1\n                                         (ws2,e2') <- boxing env e2\n                                         return (ws1++ws2, Index l e1' e2')\n    boxing env (Cond l e1 e2 e3)    = do (ws1,e1') <- boxing env e1\n                                         (ws2,e2') <- boxing env e2\n                                         (ws3,e3') <- boxing env e3\n                                         return (ws1++ws2++ws3, Cond l e1' e2' e3')\n    boxing env (IsInstance l e qn)  = do (ws1,e1) <- boxing env e\n                                         return (ws1, IsInstance l e1 qn)\n    boxing env e@(BinOp l e1 op e2) = do (ws1,e1') <- boxing env e1   -- op is And or Or\n                                         (ws2,e2') <- boxing env e2\n                                         return (ws1++ws2, BinOp l e1' op e2')\n         where t                    = typeOf env e\n    boxing env (CompOp l e os)      = do (ws1,e1) <- boxing env e\n                                         (ws2,e2) <- boxing env os\n                                         return (ws1++ws2, CompOp l e1 e2)\n    boxing env (UnOp l uop e)       = do (ws1,e') <- boxing env e      --uop is Not\n                                         return (ws1, UnOp l uop e')\n         where t                    = typeOf env e\n    boxing env (Dot l e n)          = do (ws1,e1) <- boxing env e\n                                         return (ws1, Dot l e1 n)\n    boxing env (DotI l e i)         = do (ws1,e1) <- boxing env e\n                                         return (ws1, DotI l e1 i)\n    boxing env (Rest l e n)         = do (ws1,e1) <- boxing env e\n                                         return (ws1, Rest l e1 n)\n    boxing env (RestI l e i)        = do (ws1,e1) <- boxing env e\n                                         return (ws1, RestI l e1 i)\n--    boxing env (Lambda l p k f fx)  = Lambda l <$> boxing env p <*> boxing env k <*> boxing env f <*> return fx\n--    boxing env (Yield l mbe)        = Yield l <$> boxing env mbe\n--    boxing env (YieldFrom l e)      = YieldFrom l <$> boxing env e\n    boxing env (Tuple l p k)        = do (ws1,p1) <- boxing env p\n                                         return (ws1,Tuple l p1 k)\n    boxing env (List l es)          = do (ws1,es1) <- boxing env es\n                                         return (ws1, List l es1)\n    boxing env (Set l es)           = do (ws1,es1) <- boxing env es\n                                         return (ws1, Set l es1)\n    boxing env (Dict l es)          = do (ws1,es1) <- boxing env es\n                                         return (ws1, Dict l es1)\n    boxing env (Paren l e)          = do (ws1,e1) <- boxing env e\n                                         return (ws1, Paren l e1)\n    boxing env (Box t e)  =           do (ws1,e1) <- boxing env e\n                                         case e1 of\n                                            UnBox _ e' -> return (ws1,e')\n                                            _ -> return (ws1,Box t e1)\n                                         return (ws1, e1)\n--    boxing env (Box _ (UnBox _ e))  = do (ws1,e1) <- boxing env e\n--                                         return (ws1, e1)\n    boxing env e                    = return ([],e)\n\ninstance Boxing OpArg where\n    boxing env (OpArg op e)         = do (ws1,e1) <- boxing env e\n                                         return (ws1, OpArg op e1)\n\ninstance Boxing Stmt where\n    boxing env (Expr l e)           = do (ws1,e1) <- boxing env e\n                                         return (ws1, Expr l e1)\n    boxing env (Assign l [pt@(PVar _ x Nothing)]  e@(Call _ (Dot _ (Var _ w@(NoQ n)) attr) p KwdNil))\n      | isWitness n\n                                    = do (ws1,p1) <- boxing env p\n                                         (ws2,pt2) <- boxing env pt\n                                         (ws3,s3) <- boxingWitness env pt2 w attr p1\n                                         return (ws1++ws2++ws3,s3)\n      where\n         boxingWitness env pt w attr p = case findQName w env of\n                                            NVar (TCon _ (TC _ ts))\n                                              | any (not . vFree) ts     -> return ([n], Assign l [pt] (eCallP (eDot (eQVar w) attr) p))\n                                              | attr `elem` incrBinopKWs -> boxingincrBinop pt w attr es ts\n                                            _                            -> do (ws,e') <- boxing env e\n                                                                               return (ws, Assign l [pt] (if isUnboxed (pn pt) then unbox t e' else e'))\n          where es                 = posargs p\n                vFree (TCon _ (TC _ _))= True\n                vFree _            = False\n                t                  = typeOf env e\n         boxingincrBinop pt w attr es@[x1,x2] ts    \n          | isUnboxable t          = return ([], AugAssign NoLoc (unbox t x1) op (unbox t x2))\n             where t               = head ts\n                   op              = bin2Aug attr\n         boxingincrBinop pt w attr es _\n                                   = return ([n],  Assign l [pt] (eCall (eDot (eQVar w) attr) es))\n    boxing env (Assign l [pt@PVar{}] e)\n                                   = do (ws1,pt1) <- boxing env pt\n                                        (ws2,e2) <- boxing env e\n                                        return (ws1++ws2, Assign l [pt1] (if isUnboxed (pn pt1) then unbox t e2 else e2))\n             where t               = typeOf env e\n    boxing env (Assign l ps e)     = do (ws1,ps1) <- boxing env ps\n                                        (ws2,e2) <- boxing env e\n                                        return (ws1++ws2, Assign l ps1 e2)\n{-  This does not work. It may cause mutable updates to integer-typed varibles.                                   \n\n    boxing env (MutAssign l tg@Dot{}  e@(Call _ (Dot _ (Var _ w@(NoQ n)) attr) p KwdNil))\n      | isWitness n                 = do (ws0,tg1) <- boxing env tg\n                                         (ws1,p1) <- boxing env p\n                                         (ws2,s2) <- boxingWitness env tg1 w attr p1\n                                         return (ws1++ws2,s2)\n      where\n         t                          = typeOf env tg\n         boxingWitness env tg w attr p = case findQName w env of\n                                            NVar (TCon _ (TC _ ts))\n                                              | any (not . vFree) ts     -> return ([n], MutAssign l tg (eCallP (eDot (eQVar w) attr) p))\n                                              | attr `elem` incrBinopKWs -> boxingincrBinop tg w attr es ts\n                                            _                            -> do (ws,e') <- boxing env e\n                                                                               return (ws, if isUnboxable t\n                                                                                           then MutAssign l tg e'\n                                                                                           else MutAssign l tg e')\n          where es                 = posargs p\n                vFree (TCon _ (TC _ _))= True\n                vFree _            = False\n         boxingincrBinop tg w attr es@[x1,x2] ts\n          | isUnboxable t           = return ([], AugAssign NoLoc (unbox t x1) op (unbox t x2))\n             where t                = head ts\n                   op               = bin2Aug attr\n         boxingincrBinop w attr es _ = return ([n],  MutAssign l tg (eCall (eDot (eQVar w) attr) es))\n-}\n    boxing env (MutAssign l t e)    = do (ws0,t1) <- boxing env t\n                                         (ws1,e1) <- boxing env e\n                                         return (ws0++ws1, MutAssign l t1 e1)\n    boxing env (AugAssign l t aop e)= do (ws0,t1) <- boxing env t\n                                         (ws1,e1) <- boxing env e\n                                         return (ws0++ws1, AugAssign l t aop e1)\n    boxing env (Assert l e mbe)     = do (ws1,e1) <- boxing env e\n                                         (ws2,mbe1) <- boxing env mbe\n                                         return (ws1++ws2, Assert l e1 mbe1)\n    boxing env (Pass l)             = return ([], Pass l)\n    boxing env (Delete l t)         = return ([], Delete l t)\n    boxing env (Return l (Just e))  = do (ws1,e1) <- boxing env e\n                                         if (isUnboxable t && isDelayedUnbox env)\n                                          then return (ws1, Return l (Just (unbox t e1)))\n                                          else return (ws1, Return l (Just e1))\n        where t                     = typeOf env e\n    boxing env (Return l Nothing)   = return ([], Return l Nothing)\n    boxing env (Raise l e)          = do (ws1,e1) <- boxing env e\n                                         return (ws1, Raise l e1)\n    boxing env (Break l)            = return ([], Break l)\n    boxing env (Continue l)         = return ([], Continue l)\n    boxing env (If l bs ss)         = do (ws1,bs1) <- boxing env1 bs\n                                         (ws2,ss1) <- boxing env1 ss\n                                         return (ws1++ws2,If l bs1 ss1)\n       where env1 = setTopLevel False env\n    boxing env (While l e ss els)   = do (ws1,e1) <- boxing env e\n                                         (ws2,ss1) <- boxing env1 ss\n                                         (ws3,els1) <- boxing env1 els\n                                         return (ws1++ws2++ws3, While l e1 ss1 els1)\n       where env1 = setTopLevel False env\n    boxing env (Try l ss hs els fs) = do (ws1,ss1) <- boxing env1 ss\n                                         (ws2,hs1) <- boxing env1 hs\n                                         (ws3,els1) <- boxing env1 els\n                                         (ws4,fs1) <- boxing env1 fs\n                                         return (ws1++ws2++ws3++ws4, Try l ss1 hs1 els1 fs1)\n       where env1 = setTopLevel False env\n    boxing env (With l ws ss)       = do (ws1,ws') <- boxing env ws\n                                         (ws2,ss1) <- boxing (setTopLevel False env) ss\n                                         return (ws1++ws2, With l ws' ss1)\n    boxing env (VarAssign l ps e)   = do (ws1,e1) <- boxing env e\n                                         return (ws1, VarAssign l ps e)\n    boxing env (After l e1 e2)      = do (ws1,e1') <- boxing env e1\n                                         (ws2,e2') <- boxing env e2\n                                         return (ws1++ws2, After l e1' e2')\n    boxing env s@(Signature l ns sc d) = return ([], s)\n    boxing env g@(Decl l ds)        = do (ws1, ds1) <- boxing env1 ds\n                                         return (ws1, Decl l ds1)\n      where te                      = envOf g\n            env1                    = setTopLevel False $ define te env\n\ninstance {-# OVERLAPS #-} Boxing [Decl] where\n    boxing env (c@Class{} : ds)     = do (ws1,c1) <- boxing (setInClass env) c\n                                         (ws2,ds2) <- boxing env ds\n                                         return (ws1++ws2,c1:ds2)\n    boxing env (d@Def{} : ds)\n   --   | hasNotImpl (dbody d)        = do (ws,ds1) <- boxing env ds\n   --                                      return (ws, d : ds1)\n   --   | otherwise                   = case lookup (dname d) (unboxedVars env) of\n                                      = case lookup (dname d) (unboxedVars env) of\n                                        Just un -> do\n                                           (ws1,d1) <- boxing (setDelayedUnbox True env) d{dname = un}\n                                           let ds1 =  [mkWrapper d un]\n                                           (ws2,ds2) <- boxing env ds\n                                           return (ws1++ws2,d1 : ds1 ++ ds2)\n                                        _ -> do\n                                           (ws1,d1) <- boxing env d\n                                           (ws2,ds2) <- boxing env ds\n                                           return (ws1++ws2,d1:ds2)\n       where mkWrapper (Def l n q p _ (Just t) ss dec fx ddoc) un\n                | isUnboxable t     = Def l n q p KwdNIL (Just t) [Return NoLoc (Just (Box t (eCallP (eVar un) (ub p))))] dec fx ddoc\n                | otherwise         = Def l n q p KwdNIL (Just t) [Return NoLoc (Just (eCallP (eVar un) (ub p)))] dec fx ddoc\n             ub (PosPar n (Just t) _ p)\n               | isUnboxable t      = PosArg (unbox t (eVar n)) (ub p)\n               | otherwise          = PosArg (eVar n) (ub p)\n             ub (PosSTAR n _)       = PosStar (eVar n)\n             ub PosNIL              = PosNil\n    boxing env []                   = return ([],[])\n\ninstance Boxing Decl where\n    boxing env (Class l n q cs ss ddoc)\n                                    = do (ws1, ss1) <- boxing env1 ss'\n                                         return (ws1, Class l n q cs ss1 ddoc)\n        where ss'                   = vsubst [(tvSelf, tCon c)] ss\n              c                     = TC (NoQ n) (map tVar $ qbound q)\n              env1                  = defineTVars q env\n    boxing env (Def l n q p KwdNIL t ss dec fx ddoc)\n                                    = do ps <- if (inClass env || not (isUnboxed n)) then return [] else newNames [n | (n,NVar t) <- te, isUnboxable t]\n                                         let env2 = addUnboxedVars ps $ env1\n                                         (ws1,p1) <- boxing env2 p\n                                         (ws2,ss1) <- boxing env2 ss\n                                         return (ws1++ws2,Def l n q p1 KwdNIL t ss1 dec fx ddoc)\n      where te                      = envOf p\n            env1                    = define te env\n\ninstance Boxing Branch where\n    boxing env (Branch e ss)       = do (ws1,e1) <- boxing env e\n                                        (ws2,ss1) <- boxing env ss\n                                        return (ws1++ws2, Branch e1 ss1)\n\ninstance Boxing Handler where\n    boxing env (Handler ex b)      = do (ws1, b1) <- boxing env b\n                                        return (ws1, Handler ex b1)\n\ninstance Boxing PosPar where\n    boxing env (PosPar n t e p)    = do (ws1, e1) <- boxing env e\n                                        (ws2, p2) <- boxing env p\n                                        case lookup n (unboxedVars env) of\n                                           Just un -> return (ws1++ws2, PosPar un t e1 p2)\n                                           _ -> return (ws1++ws2, PosPar n t e1 p2)\n    boxing env (PosSTAR n t)       = return ([],PosSTAR n t)\n    boxing env PosNIL              = return ([],PosNIL)\n\n\ninstance Boxing PosArg where\n    boxing env (PosArg e p)        = do (ws1,e1) <- boxing env e\n                                        (ws2,p1) <- boxing env p\n                                        return (ws1++ws2, PosArg e1 p1)\n    boxing env (PosStar e)         = do (ws1,e1) <- boxing env e\n                                        return (ws1, PosStar e1)\n    boxing env PosNil              = return ([],PosNil)\n\ninstance Boxing Elem where\n    boxing env (Elem e)            = do (ws1,e1) <- boxing env e\n                                        return (ws1, Elem e1)\n    boxing env (Star e)            = do (ws1,e1) <- boxing env e\n                                        return (ws1, Star e1)\n\ninstance Boxing Assoc where\n    boxing env (Assoc k v)         = do (ws1,k1) <- boxing env k\n                                        (ws2,v1) <- boxing env v\n                                        return (ws1++ws2, Assoc k1 v1)\n    boxing env (StarStar e)        = do (ws1,e1) <- boxing env e\n                                        return (ws1, StarStar e1)\ninstance Boxing WithItem where\n    boxing env (WithItem e mbp)    = do (ws1,e1) <- boxing env e\n                                        return (ws1, WithItem e1 mbp)\n\ninstance Boxing Pattern where\n    boxing env v@(PVar l n mbt)    = case lookup n ps of\n                                            Just un -> return ([], PVar l un mbt)\n                                            Nothing -> return ([], v)\n        where ps                   = unboxedVars env\n    boxing env (PParen l p)        = do (ws,p') <- boxing env p\n                                        return (ws, PParen l p')\n    boxing env (PList l ps mbp)    = do (ws1, ps1) <- boxing env ps\n                                        (ws2, mbp2) <- boxing env mbp\n                                        return (ws1++ws2, PList l ps1 mbp2)\n\n\n\nbin2Binary kw\n   | kw == addKW                   = Plus\n   | kw == subKW                   = Minus\n   | kw == mulKW                   = Mult\n   | kw == powKW                   = Pow\n   | kw == truedivKW               = Div\n   | kw == modKW                   = Mod\n   | kw == floordivKW              = EuDiv\n   | kw == lshiftKW                = ShiftL\n   | kw == rshiftKW                = ShiftR\n   | kw == orKW                    = BOr\n   | kw == xorKW                   = BXor\n   | kw == andKW                   = BAnd\n\ncmp2Comparison kw\n   | kw == eqKW                    = Eq\n   | kw == neKW                    = NEq\n   | kw == ltKW                    = Lt\n   | kw == leKW                    = LE\n   | kw == gtKW                    = Gt\n   | kw == geKW                    = GE\n   | kw == isKW                    = Is\n   | kw == isnotKW                 = IsNot\n\n\nbin2Aug kw\n   | kw == iaddKW                  = PlusA\n   | kw == isubKW                  = MinusA\n   | kw == imulKW                  = MultA\n   | kw == ipowKW                  = PowA\n   | kw == itruedivKW              = DivA\n   | kw == imodKW                  = ModA\n   | kw == ifloordivKW             = EuDivA\n   | kw == ilshiftKW               = ShiftLA\n   | kw == irshiftKW               = ShiftRA\n   | kw == iorKW                   = BOrA\n   | kw == ixorKW                  = BXorA\n   | kw == iandKW                  = BAndA\n"
  },
  {
    "path": "compiler/lib/src/Acton/BuildSpec.hs",
    "content": "{-# LANGUAGE OverloadedStrings #-}\n{-# LANGUAGE DeriveGeneric #-}\nmodule Acton.BuildSpec\n  ( PkgDep(..)\n  , ZigDep(..)\n  , BuildSpec(..)\n  , encodeBuildSpecJSON\n  , renderBuildAct\n  , parseBuildAct\n  , parseBuildActDetailed\n  , BuildSpecParseError(..)\n  , updateBuildActFromJSON\n  ) where\n\nimport GHC.Generics (Generic)\nimport Data.Aeson (FromJSON(..), ToJSON(..), (.:), (.:?), (.=))\nimport qualified Data.Aeson as Ae\nimport qualified Data.ByteString.Lazy as BL\nimport qualified Data.Map as Map\nimport Data.Map (Map)\nimport Data.Char (isSpace)\nimport Data.Maybe (catMaybes, fromMaybe, isNothing, mapMaybe)\nimport qualified Data.List as L\nimport qualified Control.Exception as E\nimport System.IO.Unsafe (unsafePerformIO)\n\nimport Control.Applicative ((<|>))\nimport qualified Acton.Fingerprint as Fingerprint\nimport qualified Acton.Parser as AP\nimport qualified Acton.Syntax as S\nimport qualified Acton.Printer as Pr\nimport Utils (SrcLoc(..))\nimport qualified Data.Aeson.KeyMap as KM\n\n-- Acton build configuration data model\n\n-- We use this to specify various bits of information for an Acton project. The\n-- canonical way is to have a Build.act file, for example:\n--\n-- name = \"myproject\"\n--\n-- dependencies = {\n--   \"http2\": (repo_url=\"https://github.com/actonlang/http2\", repo_ref=\"v1.2.3\"),\n--   \"local\": (path=\"deps/local-lib\")\n-- }\n--\n-- zig_dependencies = {\n--   \"zlib\": (url=\"https://example.com/zlib.tar.gz\", hash=\"sha256:deadbeef...\", artifacts=[\"z\"]),\n--   \"ssl\": (path=\"/opt/zig/ssl\", options={\"with_tls\": \"true\"})\n-- }\n--\n\ndata PkgDep = PkgDep\n  { url       :: Maybe String\n  , hash      :: Maybe String\n  , path      :: Maybe String\n  , repo_url  :: Maybe String\n  , repo_ref  :: Maybe String\n  } deriving (Eq, Show, Generic)\n\ninstance FromJSON PkgDep where\n  parseJSON = Ae.withObject \"PkgDep\" $ \\o ->\n    PkgDep <$> o .:? \"url\"\n           <*> o .:? \"hash\"\n           <*> o .:? \"path\"\n           <*> o .:? \"repo_url\"\n           <*> o .:? \"repo_ref\"\n\ninstance ToJSON PkgDep where\n  toJSON (PkgDep u h p ru rr) = Ae.object $ catMaybes\n    [ (\"url\"      .=) <$> u\n    , (\"hash\"     .=) <$> h\n    , (\"path\"     .=) <$> p\n    , (\"repo_url\" .=) <$> ru\n    , (\"repo_ref\" .=) <$> rr\n    ]\n\ndata ZigDep = ZigDep\n  { zurl      :: Maybe String\n  , zhash     :: Maybe String\n  , zpath     :: Maybe String\n  , options   :: Map String String\n  , artifacts :: [String]\n  } deriving (Eq, Show, Generic)\n\ninstance FromJSON ZigDep where\n  parseJSON = Ae.withObject \"ZigDep\" $ \\o ->\n    ZigDep <$> o .:? \"url\"\n           <*> o .:? \"hash\"\n           <*> o .:? \"path\"\n           <*> (o .:? \"options\" Ae..!= Map.empty)\n           <*> (o .:? \"artifacts\" Ae..!= [])\n\ninstance ToJSON ZigDep where\n  toJSON (ZigDep u h p opts arts) = Ae.object $\n    catMaybes [ (\"url\"  .=) <$> u\n              , (\"hash\" .=) <$> h\n              , (\"path\" .=) <$> p\n              ] ++\n    [ \"options\"   .= opts\n    , \"artifacts\" .= arts\n    ]\n\ndata BuildSpec = BuildSpec\n  { specName         :: String\n  , specDescription  :: Maybe String\n  , fingerprint      :: String\n  , dependencies     :: Map String PkgDep\n  , zig_dependencies :: Map String ZigDep\n  } deriving (Eq, Show, Generic)\n\ndata BuildSpecParseError\n  = ParseError String\n  | MissingProjectName\n  | MissingFingerprint String\n  | InvalidFingerprint String String\n  deriving (Eq, Show)\n\nrenderBuildSpecParseError :: BuildSpecParseError -> String\nrenderBuildSpecParseError err =\n  case err of\n    ParseError msg -> msg\n    MissingProjectName -> \"Missing project name (add: name = \\\"my_project\\\")\"\n    MissingFingerprint _ -> \"Missing fingerprint (add: fingerprint = 0x1234abcd5678ef00)\"\n    InvalidFingerprint name raw ->\n      \"Invalid fingerprint \" ++ raw ++ \" (project name: \" ++ show name ++ \"). \"\n      ++ \"Expected an unquoted 64-bit hex fingerprint like \"\n      ++ \"0x1234abcd5678ef00\"\n\ninstance FromJSON BuildSpec where\n  parseJSON = Ae.withObject \"BuildSpec\" $ \\o -> do\n    nm   <- o .: \"name\"\n    desc <- o .:? \"description\"\n    fp   <- o .: \"fingerprint\"\n    deps <- o .:? \"dependencies\"     Ae..!= Map.empty\n    zig  <- o .:? \"zig_dependencies\" Ae..!= Map.empty\n    return (BuildSpec nm desc fp deps zig)\n\ninstance ToJSON BuildSpec where\n  toJSON (BuildSpec nm desc fp deps zig) = Ae.object $\n    [ \"name\"            .= nm\n    , \"fingerprint\"     .= fp\n    , \"dependencies\"    .= deps\n    , \"zig_dependencies\" .= zig\n    ] ++ catMaybes [ (\"description\" .=) <$> desc ]\n\n-- Render an Acton Build.act file from BuildSpec\n-- Example:\n-- dependencies = {\n--   \"http2\": (repo_url=\"https://github.com/...\", hash=\"...\"),\n-- }\n-- zig_dependencies = {\n--   \"zlib\": (url=\"...\", hash=\"...\", options={\"opt\":\"val\"}, artifacts=[\"z\"]),\n-- }\n\nrenderBuildAct :: BuildSpec -> String\nrenderBuildAct (BuildSpec nm mdesc fp deps zdeps) = unlines $\n  [ \"# Autogenerated from BuildSpec (acton)\"\n  , \"# Edit this file to update your project configuration.\"\n  , \"\"\n  , \"name = \" ++ show nm\n  ]\n  ++ maybe [] (\\d -> [\"description = \" ++ show d]) mdesc\n  ++ [ \"fingerprint = \" ++ renderFingerprint fp\n     , \"\"\n     , renderBlockText \"dependencies\" deps (Map.keys deps) renderPkgTuple\n     , \"\"\n     , \"\"\n     , renderBlockText \"zig_dependencies\" zdeps (Map.keys zdeps) renderZigTuple\n     , \"\"\n     ]\n\nupdateBuildActFromJSON :: String -> BL.ByteString -> Either String String\nupdateBuildActFromJSON content json = do\n  modAST <- parseModuleForSpec content\n  currSpec <- case extractSpecFromModule modAST of\n                Left err -> Left (renderBuildSpecParseError err)\n                Right spec -> Right spec\n  val <- Ae.eitherDecode' json\n  case val of\n    Ae.Object obj -> do\n      patch <- case Ae.fromJSON val of\n                 Ae.Error e   -> Left e\n                 Ae.Success s -> Right s\n      let depsPresent = KM.member \"dependencies\" obj\n          zigPresent  = KM.member \"zig_dependencies\" obj\n          namePresent = KM.member \"name\" obj\n          descPresent = KM.member \"description\" obj\n          fpPresent   = KM.member \"fingerprint\" obj\n      name' <- if namePresent then requireField \"name\" (patchName patch) else Right (specName currSpec)\n      fp' <- if fpPresent\n               then do\n                 fpVal <- requireField \"fingerprint\" (patchFingerprint patch)\n                 validatePatchFingerprint fpVal\n               else Right (fingerprint currSpec)\n      desc' <- if descPresent then requireField \"description\" (patchDescription patch) else Right (specDescription currSpec)\n      let deps' = if depsPresent then patchDependencies patch else dependencies currSpec\n          zigs' = if zigPresent  then patchZigDependencies patch else zig_dependencies currSpec\n          merged = currSpec { specName = name'\n                            , specDescription = desc'\n                            , fingerprint = fp'\n                            , dependencies = deps'\n                            , zig_dependencies = zigs' }\n      content1 <- applyTopLevelPatches content modAST merged namePresent descPresent fpPresent\n      modAST1 <- parseModuleForSpec content1\n      let bodyOffsets = Map.fromList $ catMaybes\n            [ fmap (\\off -> (\"dependencies\", off)) (findBodyOffsetsFromAST content1 \"dependencies\" modAST1)\n            , fmap (\\off -> (\"zig_dependencies\", off)) (findBodyOffsetsFromAST content1 \"zig_dependencies\" modAST1)\n            ]\n          content2 = spliceManyWithBodyOffsets content1 blockRenderers merged bodyOffsets\n      Right content2\n    _ -> Left \"Expected top-level JSON object for BuildSpec\"\n  where\n    requireField label mval =\n      case mval of\n        Just v  -> Right v\n        Nothing -> Left (\"Expected '\" ++ label ++ \"' to be present and non-null in JSON\")\n\n    validatePatchFingerprint fp =\n      case Fingerprint.parseFingerprint fp of\n        Just _  -> Right fp\n        Nothing -> Left (\"Expected 'fingerprint' to be a 64-bit hex literal \"\n                         ++ \"like 0x1234abcd5678ef00\")\n\napplyTopLevelPatches :: String -> S.Module -> BuildSpec -> Bool -> Bool -> Bool -> Either String String\napplyTopLevelPatches content modAST spec namePresent descPresent fpPresent = do\n  nameRepl <- if namePresent\n    then case findAssignExprOffsetsFromAST \"name\" modAST of\n           Just (s,e) -> Right (Just (s,e, show (specName spec)))\n           Nothing -> Left \"Missing name assignment in Build.act\"\n    else Right Nothing\n  fpRepl <- if fpPresent\n    then case findAssignExprOffsetsFromAST \"fingerprint\" modAST of\n           Just (s,e) -> Right (Just (s,e, renderFingerprint (fingerprint spec)))\n           Nothing -> Left \"Missing fingerprint assignment in Build.act\"\n    else Right Nothing\n  descRepls <- if descPresent\n    then case specDescription spec of\n           Just descVal ->\n             case findAssignExprOffsetsFromAST \"description\" modAST of\n               Just (s,e) -> Right [(s,e, show descVal)]\n               Nothing ->\n                 case findAssignStmtOffsetsFromAST \"name\" modAST of\n                   Just (_,e) ->\n                     let pos = insertAfterLine content e\n                     in Right [(pos,pos, \"description = \" ++ show descVal ++ \"\\n\")]\n                   Nothing -> Left \"Missing name assignment in Build.act\"\n           Nothing ->\n             case findAssignStmtOffsetsFromAST \"description\" modAST of\n               Just (s,e) ->\n                 let e' = extendToLineEnd content e\n                 in Right [(s,e', \"\")]\n               Nothing -> Right []\n    else Right []\n  let replacements = catMaybes [nameRepl, fpRepl] ++ descRepls\n  Right (applyReplacements content replacements)\n\napplyReplacements :: String -> [(Int,Int,String)] -> String\napplyReplacements content reps =\n  let sorted = L.sortBy (\\(s1,_,_) (s2,_,_) -> compare s2 s1) reps\n  in L.foldl' (\\acc (s,e,r) -> take s acc ++ r ++ drop e acc) content sorted\n\ninsertAfterLine :: String -> Int -> Int\ninsertAfterLine content end =\n  extendToLineEnd content end\n\nextendToLineEnd :: String -> Int -> Int\nextendToLineEnd content end =\n  case L.elemIndex '\\n' (drop end content) of\n    Nothing -> length content\n    Just off -> end + off + 1\n\n-- JSON encoding helper\n\nencodeBuildSpecJSON :: BuildSpec -> BL.ByteString\nencodeBuildSpecJSON = Ae.encode\n\nparseBuildAct :: String -> Either String (BuildSpec, Maybe (Int,Int), Maybe (Int,Int))\nparseBuildAct content =\n  case parseBuildActDetailed content of\n    Left err -> Left (renderBuildSpecParseError err)\n    Right res -> Right res\n\nparseBuildActDetailed :: String -> Either BuildSpecParseError (BuildSpec, Maybe (Int,Int), Maybe (Int,Int))\nparseBuildActDetailed content = do\n  -- Parse with Acton parser and extract BuildSpec from AST\n  modAST <- case parseModuleForSpec content of\n              Left err -> Left (ParseError err)\n              Right m -> Right m\n  specFromAST <- extractSpecFromModule modAST\n  -- Compute body offsets using AST locations\n  let mDepsOff = findBodyOffsetsFromAST content \"dependencies\" modAST\n      mZigsOff = findBodyOffsetsFromAST content \"zig_dependencies\" modAST\n  Right (specFromAST, mDepsOff, mZigsOff)\n\nsrcLocToPair :: SrcLoc -> Maybe (Int,Int)\nsrcLocToPair NoLoc     = Nothing\nsrcLocToPair (Loc s e) = Just (s,e)\n\npatternVarName :: S.Pattern -> Maybe String\npatternVarName (S.PVar _ (S.Name _ v) _) = Just v\npatternVarName (S.PParen _ p)            = patternVarName p\npatternVarName _                         = Nothing\n\nfindAssignStmtOffsetsFromAST :: String -> S.Module -> Maybe (Int,Int)\nfindAssignStmtOffsetsFromAST varName (S.Module _ _ _ stmts) =\n  case firstAssign stmts of\n    Just loc -> srcLocToPair loc\n    Nothing  -> Nothing\n  where\n    firstAssign [] = Nothing\n    firstAssign (S.Assign loc pats _ : rest)\n      | varName `elem` mapMaybe patternVarName pats = Just loc\n      | otherwise = firstAssign rest\n    firstAssign (_:rest) = firstAssign rest\n\nfindAssignExprOffsetsFromAST :: String -> S.Module -> Maybe (Int,Int)\nfindAssignExprOffsetsFromAST varName (S.Module _ _ _ stmts) =\n  case firstAssign stmts of\n    Just expr -> srcLocToPair (S.eloc expr)\n    Nothing   -> Nothing\n  where\n    firstAssign [] = Nothing\n    firstAssign (S.Assign _ pats expr : rest)\n      | varName `elem` mapMaybe patternVarName pats = Just expr\n      | otherwise = firstAssign rest\n    firstAssign (_:rest) = firstAssign rest\n\n-- Find the inner-body offsets (start,end) between braces of the dict assigned\n-- to a given top-level variable, using AST locations only. The returned range\n-- is the content between '{' and '}', excluding the braces themselves.\nfindBodyOffsetsFromAST :: String -> String -> S.Module -> Maybe (Int,Int)\nfindBodyOffsetsFromAST content varName (S.Module _ _ _ stmts) =\n  case firstDictLoc stmts of\n    Just (s,e) -> braceBody content s e\n    Nothing    -> Nothing\n  where\n    firstDictLoc [] = Nothing\n    firstDictLoc (S.Assign _ [S.PVar _ (S.Name _ v) _] (S.Dict l _) : rest)\n      | v == varName = srcLocToPair l <|> firstDictLoc rest\n    firstDictLoc (_:rest) = firstDictLoc rest\n    -- Given a range [s,e) covering the dict, return the inner body [s+1,e-1].\n    -- We assume the Acton parser locates the Dict to start at '{' and end\n    -- just after '}'. If that is not the case, we conservatively return Nothing.\n    braceBody txt s e =\n      let n = length txt\n      in if s >= 0 && e <= n && s+1 <= e-1 && txt !! s == '{' && txt !! (e-1) == '}'\n           then Just (s+1, e-1)\n           else Nothing\n    \n-- Parse build.act using the real Acton parser\nparseModuleForSpec :: String -> Either String S.Module\nparseModuleForSpec content =\n  let qn = S.ModName []  -- anonymous module\n  in case unsafePerformIO (E.try (AP.parseModule qn \"Build.act\" content Nothing) :: IO (Either E.SomeException S.Module)) of\n       Left e  -> Left (show e)\n       Right m -> Right m\n\n-- Extract name, description, dependencies and zig_dependencies from the AST\nextractSpecFromModule :: S.Module -> Either BuildSpecParseError BuildSpec\nextractSpecFromModule (S.Module _ _ _ stmts) =\n  let (mname, mdesc, mfp, mfpErr, deps, zigs) =\n        foldl step (Nothing, Nothing, Nothing, Nothing, Map.empty, Map.empty) stmts\n  in case (mname, mfp, mfpErr) of\n       (Nothing, _, _) -> Left MissingProjectName\n       (Just name, Nothing, Just raw) -> Left (InvalidFingerprint name raw)\n       (Just name, Nothing, Nothing) -> Left (MissingFingerprint name)\n       (Just name, Just fp, _) ->\n         Right BuildSpec { specName = name\n                         , specDescription = mdesc\n                         , fingerprint = fp\n                         , dependencies = deps\n                         , zig_dependencies = zigs\n                         }\n  where\n    step (mname, mdesc, mfp, mfpErr, deps, zigs) stmt = case stmt of\n      S.Assign _ pats expr ->\n        let names = mapMaybe patternVarName pats\n            mname' = if \"name\" `elem` names\n                       then exprToSimpleString expr <|> mname\n                       else mname\n            mdesc' = if \"description\" `elem` names\n                       then exprToSimpleString expr <|> mdesc\n                       else mdesc\n            (mfp', mfpErr') =\n              if \"fingerprint\" `elem` names\n                then case exprToFingerprint expr of\n                       Just fp -> (Just fp, Nothing)\n                       Nothing -> (mfp, if isNothing mfp\n                                          then mfpErr <|> Just (renderExpr expr)\n                                          else mfpErr)\n                else (mfp, mfpErr)\n            deps'  = if \"dependencies\" `elem` names\n                       then fromMaybe deps (exprToPkgDeps expr)\n                       else deps\n            zigs'  = if \"zig_dependencies\" `elem` names\n                       then fromMaybe zigs (exprToZigDeps expr)\n                       else zigs\n        in (mname', mdesc', mfp', mfpErr', deps', zigs')\n      _ -> (mname, mdesc, mfp, mfpErr, deps, zigs)\n\n\ndata BuildSpecPatch = BuildSpecPatch\n  { patchName :: Maybe String\n  , patchDescription :: Maybe (Maybe String)\n  , patchFingerprint :: Maybe String\n  , patchDependencies :: Map.Map String PkgDep\n  , patchZigDependencies :: Map.Map String ZigDep\n  } deriving (Eq, Show)\n\ninstance FromJSON BuildSpecPatch where\n  parseJSON = Ae.withObject \"BuildSpecPatch\" $ \\o -> do\n    let hasName = KM.member \"name\" o\n        hasDesc = KM.member \"description\" o\n        hasFp = KM.member \"fingerprint\" o\n    name <- if hasName then Just <$> o .: \"name\" else pure Nothing\n    desc <- if hasDesc then Just <$> o .:? \"description\" else pure Nothing\n    fp <- if hasFp then Just <$> o .: \"fingerprint\" else pure Nothing\n    deps <- o .:? \"dependencies\"     Ae..!= Map.empty\n    zigs <- o .:? \"zig_dependencies\" Ae..!= Map.empty\n    pure (BuildSpecPatch name desc fp deps zigs)\n\n\n\n-- Generic block rendering and splicing -------------------------------------------------\n\n-- Order here defines append order for missing blocks.\ntype BlockDef = (String, BuildSpec -> [String], BuildSpec -> String)\n\nblockRenderers :: [BlockDef]\nblockRenderers =\n  [ ( \"dependencies\"\n    , \\spec -> Map.keys (dependencies spec)\n    , \\spec -> renderBlockText \"dependencies\" (dependencies spec) (Map.keys (dependencies spec)) renderPkgTuple\n    )\n  , ( \"zig_dependencies\"\n    , \\spec -> Map.keys (zig_dependencies spec)\n    , \\spec -> renderBlockText \"zig_dependencies\" (zig_dependencies spec) (Map.keys (zig_dependencies spec)) renderZigTuple\n    )\n  ]\n\n-- Splice multiple blocks by label using precomputed inner-body offsets.\n-- Replaces present blocks in-place (preserving surrounding text) and appends\n-- any missing non-empty blocks at the end in declared order.\nspliceManyWithBodyOffsets :: String -> [BlockDef] -> BuildSpec -> Map.Map String (Int,Int) -> String\nspliceManyWithBodyOffsets content defs spec bodyOffsets =\n  let reps = [ (s,e, (if s < length content && content !! s == '\\n' then \"\\n\" else \"\") ++ renderInner lbl)\n             | (lbl,_,_) <- defs\n             , Just (s,e) <- [Map.lookup lbl bodyOffsets]\n             ]\n      missing = [ renderFull lbl\n                | (lbl, keysFn, _) <- defs\n                , Map.notMember lbl bodyOffsets\n                , not (null (keysFn spec))\n                ]\n      replaced = applyReplacements' content (L.sortOn (\\(s,_,_) -> s) reps)\n      appended = if null missing then replaced else appendBlocks' replaced missing\n  in appended\n  where\n    renderInner lbl = case lookup lbl [(l, keysFn) | (l, keysFn, _renderer) <- defs] of\n                        Just keysFn -> renderInnerBlock lbl (keysFn spec)\n                        Nothing     -> \"\"\n    renderFull lbl = case lookup lbl [(l, renderer) | (l, _keysFn, renderer) <- defs] of\n                       Just renderer -> renderer spec\n                       Nothing       -> \"\"\n    renderInnerBlock lbl keys\n      | lbl == \"dependencies\"     = renderInnerText (dependencies spec) keys renderPkgTuple\n      | lbl == \"zig_dependencies\" = renderInnerText (zig_dependencies spec) keys renderZigTuple\n      | otherwise = \"\"\n\n-- Render only the inner lines of a dict block, no label/braces\nrenderInnerText :: (Show k, Ord k) => Map k v -> [k] -> (v -> String) -> String\nrenderInnerText m keys renderTuple =\n  let total = length keys\n      comma i = if i < total then \",\" else \"\"\n      lines' = [ \"    \" ++ show k ++ \": \" ++ renderTuple (m Map.! k) ++ comma i\n               | (i,k) <- zip [1..] keys ]\n  in unlines lines'\n\n    -- Local helpers (replacements and append)\napplyReplacements' :: String -> [(Int,Int,String)] -> String\napplyReplacements' txt reps =\n  let go pos acc [] = acc ++ drop pos txt\n      go pos acc ((s,e,newT):xs) =\n        let pre = take (s - pos) (drop pos txt)\n        in go e (acc ++ pre ++ newT) xs\n  in go 0 \"\" reps\n\nappendBlocks' :: String -> [String] -> String\nappendBlocks' txt blks =\n  let base = if lastLineEndsNewline' txt then txt else txt ++ \"\\n\"\n  in base ++ L.intercalate \"\\n\" blks\n\nlastLineEndsNewline' :: String -> Bool\nlastLineEndsNewline' s = not (null s) && last s == '\\n'\n\n-- Rendering helpers\n\nrenderBlockText :: (Show k, Ord k) => String -> Map k v -> [k] -> (v -> String) -> String\nrenderBlockText label m keys renderTuple =\n  let lines' = [ \"  \" ++ show k ++ \": \" ++ renderTuple (m Map.! k) ++ comma i\n               | (i,k) <- zip [1..] keys ]\n  in unlines $ [label ++ \" = {\"] ++ lines' ++ [\"}\"]\n  where\n    comma i = if i < length keys then \",\" else \"\"\n\nrenderExpr :: S.Expr -> String\nrenderExpr e = Pr.render (Pr.pretty e)\n\n-- Turn a PkgDep into a multi-line parenthesized key=value tuple string, e.g.:\n-- (\n--     key1=\"val1\",\n--     key2=\"val2\"\n-- )\nrenderPkgTuple :: PkgDep -> String\nrenderPkgTuple (PkgDep u h p ru rr) =\n  let fields = catMaybes\n        [ fmap (\\x -> (\"repo_url\", mkStr x)) ru\n        , fmap (\\x -> (\"repo_ref\", mkStr x)) rr\n        , fmap (\\x -> (\"url\", mkStr x)) u\n        , fmap (\\x -> (\"hash\", mkStr x)) h\n        , fmap (\\x -> (\"path\", mkStr x)) p\n        ]\n  in case fields of\n       [] -> \"()\"\n       _  ->\n         let total = length fields\n             fieldLines = [ \"        \" ++ k ++ \"=\" ++ renderExpr v ++ comma i\n                          | (i, (k,v)) <- zip [1..] fields ]\n             comma i = if i < total then \",\" else \"\"\n         in \"(\\n\" ++ L.intercalate \"\\n\" fieldLines ++ \"\\n    )\"\n\n-- Turn a ZigDep into a multi-line parenthesized key=value tuple string\nrenderZigTuple :: ZigDep -> String\nrenderZigTuple (ZigDep u h p opts arts) =\n  let optExpr = if Map.null opts then Nothing else Just (mkOptions opts)\n      artExpr = if null arts then Nothing else Just (mkList arts)\n      fields = catMaybes\n        [ fmap (\\x -> (\"url\", mkStr x)) u\n        , fmap (\\x -> (\"hash\", mkStr x)) h\n        , fmap (\\x -> (\"path\", mkStr x)) p\n        , fmap (\\x -> (\"options\", x)) optExpr\n        , fmap (\\x -> (\"artifacts\", x)) artExpr\n        ]\n  in case fields of\n       [] -> \"()\"\n       _  ->\n         let total = length fields\n             fieldLines = [ \"        \" ++ k ++ \"=\" ++ renderExpr v ++ comma i\n                          | (i, (k,v)) <- zip [1..] fields ]\n             comma i = if i < total then \",\" else \"\"\n         in \"(\\n\" ++ L.intercalate \"\\n\" fieldLines ++ \"\\n    )\"\n\n-- Compose a tuple string with no spaces around '=' and comma+space between pairs\nrenderTuple :: [(String, S.Expr)] -> String\nrenderTuple pairs =\n  let items = [ k ++ \"=\" ++ renderExpr v | (k,v) <- pairs ]\n  in \"(\" ++ L.intercalate \", \" items ++ \")\"\n\n-- Minimal Expr builders used for value rendering\nmkStr :: String -> S.Expr\nmkStr s = S.Strings NoLoc [s]\nmkOptions :: Map String String -> S.Expr\nmkOptions mp = S.Dict NoLoc [ S.Assoc (mkStr k) (mkStr v) | (k,v) <- Map.toList mp ]\nmkList :: [String] -> S.Expr\nmkList xs = S.List NoLoc [ S.Elem (mkStr x) | x <- xs ]\n\n\nexprToSimpleString :: S.Expr -> Maybe String\nexprToSimpleString (S.Strings _ [s]) = Just s\nexprToSimpleString _ = Nothing\n\nexprToFingerprint :: S.Expr -> Maybe String\nexprToFingerprint (S.Int _ _ lexeme) = Just lexeme\nexprToFingerprint (S.Paren _ e) = exprToFingerprint e\nexprToFingerprint _ = Nothing\n\nrenderFingerprint :: String -> String\nrenderFingerprint fp\n  | Just formatted <- normalizeHexFingerprint fp = formatted\n  | otherwise               = show fp\n  where\n    normalizeHexFingerprint raw =\n      case dropWhile isSpace raw of\n        '0':'x':_ -> Fingerprint.formatFingerprint <$> Fingerprint.parseFingerprint raw\n        '0':'X':_ -> Fingerprint.formatFingerprint <$> Fingerprint.parseFingerprint raw\n        _         -> Nothing\n\nexprToPkgDeps :: S.Expr -> Maybe (Map.Map String PkgDep)\nexprToPkgDeps (S.Dict _ assocs) = Just $ Map.fromList (mapMaybe assocToPkg assocs)\n  where\n    assocToPkg (S.Assoc k v) = do\n      key <- exprToSimpleString k\n      dep <- tupleToPkg v\n      pure (key, dep)\n    assocToPkg _ = Nothing\nexprToPkgDeps _ = Nothing\n\ntupleToPkg :: S.Expr -> Maybe PkgDep\ntupleToPkg (S.Tuple _ _ kargs) =\n  let m = kwdToMap kargs\n  in Just PkgDep { url = Map.lookup \"url\" m >>= exprToSimpleString\n                 , hash = Map.lookup \"hash\" m >>= exprToSimpleString\n                 , path = Map.lookup \"path\" m >>= exprToSimpleString\n                 , repo_url = Map.lookup \"repo_url\" m >>= exprToSimpleString\n                 , repo_ref = Map.lookup \"repo_ref\" m >>= exprToSimpleString\n                 }\ntupleToPkg (S.Paren _ e) = tupleToPkg e\ntupleToPkg _ = Nothing\n\nexprToZigDeps :: S.Expr -> Maybe (Map.Map String ZigDep)\nexprToZigDeps (S.Dict _ assocs) = Just $ Map.fromList (mapMaybe assocToZig assocs)\n  where\n    assocToZig (S.Assoc k v) = do\n      key <- exprToSimpleString k\n      dep <- tupleToZig v\n      pure (key, dep)\n    assocToZig _ = Nothing\nexprToZigDeps _ = Nothing\n\ntupleToZig :: S.Expr -> Maybe ZigDep\ntupleToZig (S.Tuple _ _ kargs) =\n  let m = kwdToMap kargs\n  in Just ZigDep { zurl = Map.lookup \"url\" m >>= exprToSimpleString\n                 , zhash = Map.lookup \"hash\" m >>= exprToSimpleString\n                 , zpath = Map.lookup \"path\" m >>= exprToSimpleString\n                 , options = fromMaybe Map.empty (Map.lookup \"options\" m >>= exprToOptions)\n                 , artifacts = fromMaybe [] (Map.lookup \"artifacts\" m >>= exprToListStrings)\n                 }\ntupleToZig (S.Paren _ e) = tupleToZig e\ntupleToZig _ = Nothing\n\nkwdToMap :: S.KwdArg -> Map.Map String S.Expr\nkwdToMap S.KwdNil = Map.empty\nkwdToMap (S.KwdArg (S.Name _ n) e rest) = Map.insert n e (kwdToMap rest)\nkwdToMap (S.KwdStar _) = Map.empty\n\nexprToOptions :: S.Expr -> Maybe (Map.Map String String)\nexprToOptions (S.Dict _ assocs) = Just $ Map.fromList (mapMaybe kv assocs)\n  where kv (S.Assoc k v) = do\n          key <- exprToSimpleString k <|> (case k of { S.Var _ (S.NoQ n) -> Just (S.nstr n); _ -> Nothing })\n          val <- exprToSimpleString v\n          pure (key, val)\n        kv _ = Nothing\nexprToOptions _ = Nothing\n\nexprToListStrings :: S.Expr -> Maybe [String]\nexprToListStrings (S.List _ elems) = Just $ mapMaybe elemStr elems\n  where elemStr (S.Elem e) = exprToSimpleString e\n        elemStr _ = Nothing\nexprToListStrings _ = Nothing\n\n-- No fallback text parsing; we rely on the AST exclusively for semantics and\n-- use source locations only to find brace body spans for splicing.\n"
  },
  {
    "path": "compiler/lib/src/Acton/Builtin.hs",
    "content": "-- Copyright (C) 2019-2021 Data Ductus AB\n--\n-- Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:\n--\n-- 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.\n--\n-- 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.\n--\n-- 3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission.\n--\n-- THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS \"AS IS\" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n--\n\nmodule Acton.Builtin where\n\nimport Utils\nimport Acton.Syntax\n\nselfKW                              = name \"self\"\n\ninitKW                              = name \"__init__\"\nfromiterKW                          = name \"__fromiter__\"\nfromatomKW                          = name \"__fromatom__\"\nlenKW                               = name \"__len__\"\nenterKW                             = name \"__enter__\"\nexitKW                              = name \"__exit__\"\niterKW                              = name \"__iter__\"\nnextKW                              = name \"__next__\"\ncontainsKW                          = name \"__contains__\"\ncontainsnotKW                       = name \"__containsnot__\"\ngetitemKW                           = name \"__getitem__\"\nsetitemKW                           = name \"__setitem__\"\ndelitemKW                           = name \"__delitem__\"\ngetsliceKW                          = name \"__getslice__\"\nsetsliceKW                          = name \"__setslice__\"\ndelsliceKW                          = name \"__delslice__\"\nappendKW                            = name \"append\"\nboolKW                              = name \"__bool__\"\nstrKW                               = name \"__str__\"\nreprKW                              = name \"__repr__\"\ncleanupKW                           = name \"__cleanup__\"\nresumeKW                            = name \"__resume__\"\n\nvalueKWs                            = [boolKW, strKW, reprKW]\n\niaddKW                              = name \"__iadd__\"\nisubKW                              = name \"__isub__\"\nimulKW                              = name \"__imul__\"\nipowKW                              = name \"__ipow__\"\nitruedivKW                          = name \"__itruediv__\"\nimodKW                              = name \"__imod__\"\nifloordivKW                         = name \"__ifloordiv__\"\nilshiftKW                           = name \"__ilshift__\"\nirshiftKW                           = name \"__irshift__\"\niorKW                               = name \"__ior__\"\nixorKW                              = name \"__ixor__\"\niandKW                              = name \"__iand__\"\nimatmulKW                           = name \"__imatmul__\"\n\nincrBinopKWs                        = [iaddKW, isubKW, imulKW, ipowKW, itruedivKW, imodKW, ifloordivKW,\n                                       ilshiftKW, irshiftKW, iorKW, ixorKW, iandKW, imatmulKW]\n\naddKW                               = name \"__add__\"\nsubKW                               = name \"__sub__\"\nmulKW                               = name \"__mul__\"\npowKW                               = name \"__pow__\"\ntruedivKW                           = name \"__truediv__\"\nmodKW                               = name \"__mod__\"\nfloordivKW                          = name \"__floordiv__\"\nlshiftKW                            = name \"__lshift__\"\nrshiftKW                            = name \"__rshift__\"\norKW                                = name \"__or__\"\nxorKW                               = name \"__xor__\"\nandKW                               = name \"__and__\"\nmatmulKW                            = name \"__matmul__\"\n\nbinopKWs                            = [addKW, subKW, mulKW, powKW, truedivKW, modKW, floordivKW,\n                                       lshiftKW, rshiftKW, orKW, xorKW, andKW, matmulKW]\n\nposKW                               = name \"__pos__\"\nnegKW                               = name \"__neg__\"\ninvertKW                            = name \"__invert__\"\n\nunopKWs                             = [posKW, negKW, invertKW]\n\neqKW                                = name \"__eq__\"\nneKW                                = name \"__ne__\"\nltKW                                = name \"__lt__\"\nleKW                                = name \"__le__\"\ngtKW                                = name \"__gt__\"\ngeKW                                = name \"__ge__\"\nisKW                                = name \"__is__\"\nisnotKW                             = name \"__isnot__\"\n\ncompareKWs                          = [eqKW, neKW, ltKW, leKW, gtKW, geKW, isKW, isnotKW]\neqordKWs                            = [eqKW, neKW, ltKW, leKW, gtKW, geKW] \n\nnBuiltin                            = name \"__builtin__\"\nmBuiltin                            = ModName [nBuiltin]\ngBuiltin n                          = GName mBuiltin n\n\nnValue                              = name \"value\"\nnAtom                               = name \"atom\"\nnObject                             = name \"object\"\nnInt                                = name \"int\"\nnI32                                = name \"i32\"\nnI16                                = name \"i16\"\nnU64                                = name \"u64\"\nnU32                                = name \"u32\"\nnU16                                = name \"u16\"\nnBigint                             = name \"bigint\"\nnFloat                              = name \"float\"\nnComplex                            = name \"complex\"\nnBool                               = name \"bool\"\nnStr                                = name \"str\"\nnRepr                               = name \"repr\"\nnBytes                              = name \"bytes\"\nnRef                                = name \"Ref\"\nnMsg                                = name \"Msg\"\nnBaseException                      = name \"BaseException\"\nnException                          = name \"Exception\"\nnStopIteration                      = name \"StopIteration\"\nnValueError                         = name \"ValueError\"\n---\nnRange                              = name \"range\"\nnLen                                = name \"len\"\nnPrint                              = name \"print\"\nnPrintn                             = name \"printn\"\nnDict                               = name \"dict\"\nnList                               = name \"list\"\nnSetT                               = name \"set\"\nnSlice                              = name \"slice\"\nnIterator                           = name \"Iterator\"\n---\nnSequence                           = name \"Sequence\"\nnMapping                            = name \"Mapping\"\nnSetP                               = name \"Set\"\nnIndexed                            = name \"Indexed\"\nnSliceable                          = name \"Sliceable\"\nnHashable                           = name \"Hashable\"\nnPlus                               = name \"Plus\"\nnMinus                              = name \"Minus\"\nnTimes                              = name \"Times\"\nnDiv                                = name \"Div\"\nnNumber                             = name \"Number\"\nnReal                               = name \"Real\"\nnRealFloat                          = name \"RealFloat\"\nnRational                           = name \"Rational\"\nnIntegral                           = name \"Integral\"\nnLogical                            = name \"Logical\"\nnMatrix                             = name \"Matrix\"\nnEq                                 = name \"Eq\"\nnOrd                                = name \"Ord\"\nnIdentity                           = name \"Identity\"\nnCollection                         = name \"Collection\"\nnContainer                          = name \"Container\"\nnIterable                           = name \"Iterable\"\nnContextManager                     = name \"ContextManager\"\nnShow                               = name \"Show\"\n---\nnTuple                              = name \"tuple\"\nnNoneType                           = name \"NoneType\"\nnNone                               = name \"None\"\nnTrue                               = name \"True\"\nnFalse                              = name \"False\"\n\nqnValue                             = gBuiltin nValue\nqnAtom                              = gBuiltin nAtom\nqnObject                            = gBuiltin nObject\nqnInt                               = gBuiltin nInt\nqnI32                               = gBuiltin nI32\nqnI16                               = gBuiltin nI16\nqnU64                               = gBuiltin nU64\nqnU32                               = gBuiltin nU32\nqnU16                               = gBuiltin nU16\nqnBigint                            = gBuiltin nBigint\nqnFloat                             = gBuiltin nFloat\nqnComplex                           = gBuiltin nComplex\nqnBool                              = gBuiltin nBool\nqnStr                               = gBuiltin nStr\nqnRepr                              = gBuiltin nRepr\nqnBytes                             = gBuiltin nBytes\nqnRef                               = gBuiltin nRef\nqnMsg                               = gBuiltin nMsg\nqnBaseException                     = gBuiltin nBaseException\nqnException                         = gBuiltin nException\nqnStopIteration                     = gBuiltin nStopIteration\nqnValueError                        = gBuiltin nValueError\n---\nqnRange                             = gBuiltin nRange\nqnPrint                             = gBuiltin nPrint\nqnPrintn                            = gBuiltin nPrintn\nqnDict                              = gBuiltin nDict\nqnList                              = gBuiltin nList\nqnSetT                              = gBuiltin nSetT\nqnSlice                             = gBuiltin nSlice\nqnIterator                          = gBuiltin nIterator\n---\nqnSequence                          = gBuiltin nSequence\nqnMapping                           = gBuiltin nMapping\nqnSetP                              = gBuiltin nSetP\nqnIndexed                           = gBuiltin nIndexed\nqnSliceable                         = gBuiltin nSliceable\nqnHashable                          = gBuiltin nHashable\nqnPlus                              = gBuiltin nPlus\nqnMinus                             = gBuiltin nMinus\nqnTimes                             = gBuiltin nTimes\nqnDiv                               = gBuiltin nDiv\nqnNumber                            = gBuiltin nNumber\nqnReal                              = gBuiltin nReal\nqnRealFloat                         = gBuiltin nRealFloat\nqnRational                          = gBuiltin nRational\nqnIntegral                          = gBuiltin nIntegral\nqnLogical                           = gBuiltin nLogical\nqnMatrix                            = gBuiltin nMatrix\nqnEq                                = gBuiltin nEq\nqnOrd                               = gBuiltin nOrd\nqnIdentity                          = gBuiltin nIdentity\nqnCollection                        = gBuiltin nCollection\nqnContainer                         = gBuiltin nContainer\nqnIterable                          = gBuiltin nIterable\nqnContextManager                    = gBuiltin nContextManager\nqnShow                              = gBuiltin nShow\n---\nqnTuple                             = gBuiltin nTuple\nqnNoneType                          = gBuiltin nNoneType\nqnNone                              = gBuiltin nNone\nqnTrue                              = gBuiltin nTrue\nqnFalse                             = gBuiltin nFalse\n\ncValue                              = TC qnValue []\ncAtom                               = TC qnAtom []\ncObject                             = TC qnObject []\ncInt                                = TC qnInt []\ncI32                                = TC qnI32 []\ncI16                                = TC qnI16 []\ncU64                                = TC qnU64 []\ncU32                                = TC qnU32 []\ncU16                                = TC qnU16 []\ncBigint                             = TC qnBigint []\ncFloat                              = TC qnFloat []\ncComplex                            = TC qnComplex []\ncBool                               = TC qnBool []\ncStr                                = TC qnStr []\ncRepr                               = TC qnRepr []\ncBytes                              = TC qnBytes []\ncRef                                = TC qnRef []\ncMsg a                              = TC qnMsg [a]\ncList a                             = TC qnList [a]\ncDict a b                           = TC qnDict [a,b]\ncSet a                              = TC qnSetT [a]\ncSlice                              = TC qnSlice []\ncIterator a                         = TC qnIterator [a]\ncBaseException                      = TC qnBaseException []\ncException                          = TC qnException []\ncStopIteration                      = TC qnStopIteration []\ncValueError                         = TC qnValueError []\n---\npSequence a                         = TC qnSequence [a]\npMapping a b                        = TC qnMapping [a,b]\npSet a                              = TC qnSetP [a]\npIndexed a b                        = TC qnIndexed [a,b]\npSliceable a                        = TC qnSliceable [a]\npHashable                           = TC qnHashable []\npPlus                               = TC qnPlus []\npMinus                              = TC qnMinus []\npTimes a                            = TC qnTimes [a]\npDiv a                              = TC qnDiv [a]\npNumber                             = TC qnNumber []\npReal                               = TC qnReal []\npRealFloat                          = TC qnRealFloat []\npRational                           = TC qnRational []\npIntegral                           = TC qnIntegral []\npLogical                            = TC qnLogical []\npMatrix                             = TC qnMatrix []\npEq                                 = TC qnEq []\npOrd                                = TC qnOrd []\npIdentity                           = TC qnIdentity []\npCollection a                       = TC qnCollection [a]\npContainer a                        = TC qnContainer [a]\npIterable a                         = TC qnIterable [a]\npContextManager                     = TC qnContextManager []\npShow                               = TC qnShow []\n\ntValue                              = tCon cValue\ntAtom                               = tCon cAtom\ntObject                             = tCon cObject\ntInt                                = tCon cInt\ntI32                                = tCon cI32\ntI16                                = tCon cI16\ntU64                                = tCon cU64\ntU32                                = tCon cU32\ntU16                                = tCon cU16\ntBigint                             = tCon cBigint\ntFloat                              = tCon cFloat\ntComplex                            = tCon cComplex\ntBool                               = tCon cBool\ntStr                                = tCon cStr\ntBytes                              = tCon cBytes\ntRef                                = tCon cRef\ntMsg a                              = tCon (cMsg a)\ntList a                             = tCon (cList a)\ntDict a b                           = tCon (cDict a b)\ntSet a                              = tCon (cSet a)\ntSlice                              = tCon cSlice\ntIterator a                         = tCon (cIterator a)\ntBaseException                      = tCon cBaseException\ntException                          = tCon cException\ntStopIteration                      = tCon cStopIteration\ntValueError                         = tCon cValueError\n\n---\n\ntSequenceW self a                   = tCon (TC qnSequence [self,a])\ntMappingW self a b                  = tCon (TC qnMapping [self, a, b])\ntSetW self a                        = tCon (TC qnSetP [self, a])\ntCollectionW self a                 = tCon (TC qnCollection [self, a])\ntHashableW self                     = tCon (TC qnHashable [self])\n\nwitSequenceList                     = gBuiltin (Derived nSequence nList)\nwitSetSet                           = gBuiltin (Derived nSetP nSetT)\nwitMappingDict                      = gBuiltin (Derived nMapping nDict)\n"
  },
  {
    "path": "compiler/lib/src/Acton/CPS.hs",
    "content": "-- Copyright (C) 2019-2021 Data Ductus AB\n--\n-- Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:\n--\n-- 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.\n--\n-- 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.\n--\n-- 3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission.\n--\n-- THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS \"AS IS\" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n--\n\n{-# LANGUAGE MultiParamTypeClasses, FlexibleInstances, FlexibleContexts #-}\nmodule Acton.CPS(convert) where\n\nimport Debug.Trace\nimport Control.Monad.State.Strict\nimport Control.Monad.Writer\nimport Utils\nimport Pretty\nimport Acton.Syntax\nimport Acton.Printer\nimport Acton.Names\nimport Acton.Builtin\nimport Acton.Prim\nimport Acton.NameInfo\nimport Acton.Env\nimport Acton.QuickType\n\nconvert                                 :: Env0 -> Module -> IO (Module, Env0)\nconvert env0 m                          = return (runCpsM (convMod m), mapModules1 (conv env) env0)\n  where env                             = cpsEnv env0\n        convMod (Module m imps mdoc ss) = do ss' <- preSuite env ss\n                                             --traceM (\"######## preCPS:\\n\" ++ render (vcat $ map pretty ss') ++ \"\\n########\")\n                                             Module m imps mdoc <$> cps env ss'\n\ntype CpsM a                             = State CpsState a\n\ntype CpsState                           = ([Int], [Stmt])\n\nrunCpsM                                 :: CpsM a -> a\nrunCpsM m                               = evalState m ([1..], [])\n\ncontKW                                  = Internal CPSPass \"cont\" 0\n\nnewName                                 :: String -> CpsM Name\nnewName s                               = state (\\(uniq:supply, stmts) -> (Internal CPSPass s uniq, (supply, stmts)))\n\nprefix                                  :: [Stmt] -> CpsM ()\nprefix ss                               = state (\\(supply, stmts) -> ((), (supply, reverse ss ++ stmts)))\n\nswapPrefixes                            :: [Stmt] -> CpsM [Stmt]\nswapPrefixes ss                         = state (\\(supply, stmts) -> (stmts, (supply, ss)))\n\nwithPrefixes                            :: CpsM a -> CpsM ([Stmt],a)\nwithPrefixes m                          = do ss0 <- swapPrefixes []\n                                             r <- m\n                                             ss1 <- swapPrefixes ss0\n                                             return (reverse ss1, r)\n\n\ndata Frame                              = Meth   Name Type                  -- contParam with type\n                                        | Seq    Name [Name]                -- nextCont with extra args\n                                        | Loop   Name [Name]                -- loopEntry with extra args\n                                        deriving (Eq,Show)\n\ninstance Pretty Frame where\n    pretty (Meth n t)                   = text \"Meth\" <+> pretty n\n    pretty (Seq n ns)                   = text \"Seq\" <+> pretty n\n    pretty (Loop n ns)                  = text \"Loop\" <+> pretty n\n\ntype CPSEnv                             = EnvF CPSX\n\ndata CPSX                               = CPSX { ctxtX :: [Frame], volatileX :: [Name] }\n\ndata Where                              = OnTop | InClass | InDef | InInnerLoop deriving (Eq,Show)\n\ncpsEnv env0                             = setX env0 CPSX{ ctxtX = [], volatileX = [] }\n\nctxt env                                = ctxtX $ envX env\n\ninfixr +:\nframe +: env                            = modX env $ \\x -> x{ ctxtX = frame : ctxtX x }\n\nclearCtxt env                           = modX env $ \\x -> x{ ctxtX = [] }\n\nsetVolatiles ns env                     = modX env $ \\x -> x{ volatileX = ns }\n\nvolatiles env                           = volatileX (envX env)\n\neCallCont e (c,t)                       = eCall (tApp (eQVar primRContc) [t]) [c, e]\n\neCallCont0 (c, ns)                      = eCallCont eNone (c',tNone)\n  where c'                              = kRef c ns g_skip tNone\n\ncntcont (Seq _ _ : ctx)                 = cntcont ctx       -- 'continue'       followed by some cmd:   ignore it\ncntcont (Loop c ns : ctx)               = (c, ns)           --                  inside a loop:          jump to its top\n\nbrkcont (Seq _ _ : ctx)                 = brkcont ctx       -- 'break'          followed by some cmd:   ignore it\nbrkcont (Loop _ _ : ctx)                = seqcont ctx       --                  inside a loop:          jump to what follows\n\nseqcont (Seq c ns : ctx)                = (c, ns)           -- end of sequence  followed by some cmd:   jump to it\nseqcont (Loop c ns : ctx)               = (c, ns)           --                  inside a loop:          jump to its top\nseqcont (Meth c _ : _)                  = (c, [])           --                  in a method:            jump to its continuation\n\nretcont (Seq _ _ : ctx)                 = retcont ctx       -- 'return'         followed by some cmd:   ignore it\nretcont (Loop _ _ : ctx)                = retcont ctx       --                  inside a loop:          ignore it\nretcont (Meth c t : _)                  = (eVar c, t)       --                  in a method:            jump to its continuation\n\n\nclass CPS a where\n    cps                                 :: CPSEnv -> a -> CpsM a\n\ninstance CPS [Stmt] where\n    cps env []\n      | inCont env                      = return [sReturn $ eCallCont0 $ seqcont $ ctxt env]\n    cps env (Continue _ : _)\n      | inCont env                      = return [sReturn $ eCallCont0 $ cntcont $ ctxt env]\n    cps env (Break _ : _)\n      | inCont env                      = return [sReturn $ eCallCont0 $ brkcont $ ctxt env]\n    cps env (Return _ Nothing : _)\n      | inCont env                      = return [sReturn $ eCallCont eNone $ retcont $ ctxt env]\n    cps env (Return _ (Just e) : _)\n      | contCall env e                  = return [sReturn $ addContArg env (conv env e) $ fst $ retcont $ ctxt env]\n      | inCont env                      = return [sReturn $ eCallCont (conv env e) $ retcont $ ctxt env]\n\n    cps env (Assign _ [PVar _ n (Just _)] e :\n             Return _ (Just e') : _)\n      | contCall env e, e' == eVar n    = return [sReturn $ addContArg env (conv env e) $ fst $ retcont $ ctxt env]\n\n    cps env [Expr _ e]\n      | contCall env e                  = return [sReturn $ addContArg env (conv env e) $ cont $ seqcont $ ctxt env]\n      where t                           = typeOf env e\n            cont (c,ns)                 = if t == tNone then c' else eCall (tApp (eQVar primSKIPRESc) [t]) [c']\n              where c'                  = kRef c ns g_skip t\n\n    cps env (Expr _ e : ss)\n      | contCall env e                  = do k <- newName \"cont\"\n                                             x <- newName \"res\"\n                                             ss' <- cps env ss\n                                             --traceM (\"## kDef Expr \" ++ prstr k ++ \", updates: \" ++ prstrs nts)\n                                             return $ kDef env k nts x t ss' :\n                                                      sReturn (addContArg env (conv env e) (kRef k (dom nts) x t)) : []\n      where t                           = typeOf env e\n            nts                         = extraBinds env ss\n\n    cps env ss0@(Assign l [p] e : ss)\n      | contCall env e                  = do k <- newName \"cont\"\n                                             x <- newName \"res\"\n                                             ss' <- cps (define [(x,NVar t)] env) (Assign l [p] (eVar x) : ss)\n                                             --traceM (\"## kDef Assign \" ++ prstr k ++ \", updates: \" ++ prstrs nts)\n                                             return $ kDef env k nts x t ss' :\n                                                      sReturn (addContArg env (conv env e) (kRef k (dom nts) x t)) : []\n      where t                           = typeOf env e\n            nts                         = extraBinds env ss0\n\n    cps env (MutAssign l tg e : ss)\n      | contCall env e                  = do k <- newName \"cont\"\n                                             x <- newName \"res\"\n                                             ss' <- cps env (MutAssign l tg (eVar x) : ss)\n                                             --traceM (\"## kDef MutAssign \" ++ prstr k ++ \", updates: \" ++ prstrs nts)\n                                             return $ kDef env k nts x t ss' :\n                                                      sReturn (addContArg env (conv env e) (kRef k (dom nts) x t)) : []\n      where t                           = typeOf env e\n            nts                         = extraBinds env ss\n\n    cps env (Decl l ds : ss)            = do ds' <- mapM (cps env1) ds\n                                             ss' <- cps env1 ss\n                                             return $ sDecl ds' : ss'\n      where env1                        = define (envOf ds) env\n\n    cps env (s : ss)\n      | not (needCont env s)            = do ss' <- cps env1 ss\n                                             --traceM (\"### SIMPLE: \" ++ prstr s)\n                                             return $ conv env s : ss'\n      where env1                        = define (envOf s) env\n\n    cps env s@[If _ [Branch e ss1] ss2]\n      | isPUSH e                        = do k <- newName \"try\"\n                                             x <- newName \"res\"\n                                             ss1 <- cps env (map convPOPDROP ss1)\n                                             ss2 <- cps env (map convPOPDROP ss2)\n                                             let body = sIf1 (eVar x) ss1 ss2 : []\n                                             --traceM (\"## kDef PUSH \" ++ prstr k ++ \", updates: \" ++ prstrs nts)\n                                             return $ kDef env k nts x tBool body :\n                                                      sReturn (convPUSH e $ kRef k (dom nts) x tBool) : []\n      where nts                         = extraBinds env s\n\n    cps env [If _ bs els]               = do bs' <- mapM (cps env) bs\n                                             els' <- cps env els\n                                             return $ sIf bs' els' : []\n\n    cps env (If l bs els : s@(Expr _ e) : _)\n      | isRAISE e                       = cps env [If l [ Branch e (ss++[s]) | Branch e ss <- bs ] (els++[s])]\n\n    cps env s@[While _ e b els]         = do k    <- newName \"loop\"\n                                             x    <- newName \"res\"\n                                             b'   <- cps (Loop k (dom nts) +: env) b\n                                             els' <- cps env els\n                                             let body = sIf1 (conv env e) b' els' : []\n                                             --traceM (\"## kDef While \" ++ prstr k ++ \", updates: \" ++ prstrs nts)\n                                             return $ kDef env k nts x tNone body :\n                                                      kJump k nts\n      where nts                         = extraBinds env s\n\n    cps env (s : ss)                    = do k <- newName \"cont\"\n                                             x <- newName \"res\"\n                                             ss' <- cps env1 ss\n                                             s' <- cps (Seq k (dom nts) +: env) [s]\n                                             --traceM (\"## kDef Seq \" ++ prstr k ++ \", live/updates: \" ++ prstrs nts)\n                                             return $ kDef env k nts x tNone ss' :\n                                                      s'\n      where env1                        = define (envOf s) env\n            nts0                        = nvarsOf (envOf s) `restrict` free ss\n            nts                         = nts0 ++ extraBinds env1 ss\n\n    cps env []                          = return []\n\nextraBinds env ss                       = [ (x, t) | x <- nub $ updatesOf ss, x `notElem` volatiles env, Just t <- [lookupVar x env] ]\n\nvolatileVars env stmts                  = nub $ vols env stmts\n  where vols env []                     = []\n        vols env (s:ss)                 = vol env s ++ vols (define (envOf s) env) ss\n        vol env s@(If _ [Branch e ss] els)\n          | isPUSH e, needCont env s    = updatesOf ss ++ vols env ss ++ vols env els\n        vol env (If _ bs els)           = concat [ vols env ss | Branch _ ss <- bs ] ++ vols env els\n        vol env (While _ _ ss els)      = vols env ss ++ vols env els\n        vol env _                       = []\n\ninstance CPS Decl where\n    cps env (Class l n q cs b ddoc)     = do b' <- cps env1 b\n                                             return $ Class l n (conv env q) (conv env cs) b' ddoc\n      where env1                        = defineTVars (selfQuant (NoQ n) q) $ clearCtxt $ setInClass env\n\n    cps env (Def l n q p KwdNIL (Just t) b dec fx ddoc)\n      | contFX fx                       = do --traceM (\"#### Converting \" ++ prstr n)\n                                             b' <- cps env2 b\n                                             return $ Def l n q' (addContPar env dec p' fx t') KwdNIL (Just tR) (volinits ++ b') dec fx ddoc\n      | otherwise                       = do --traceM (\"#### Preserving \" ++ prstr n)\n                                             b' <- cps env1 b\n                                             return $ Def l n q' p' KwdNIL (Just t') b' dec fx ddoc\n      where env2                        = setVolatiles volvs $ Meth contKW t' +: env1\n            env1                        = define (envOf p) $ defineTVars q $ clearCtxt $ setInDef env\n            volvs                       = volatileVars env2 b\n            volinits                    = [ sAssign (pVar v (tBox t)) (eCall (tApp (eQVar primBox) [t]) [eVar v])\n                                          | (v,NVar t) <- envOf p, v `elem` volvs ]\n            q'                          = conv env q\n            p'                          = conv env p\n            t'                          = conv env t\n\n    cps env d                           = error (\"cps unexpected: \" ++ prstr d)\n\n\ninstance CPS Branch where\n    cps env (Branch e ss)               = Branch (conv env e) <$> cps env ss\n\n\nkJump k nts                             = sReturn (eCall (eVar k) $ eNone : map eVar (dom nts)) : []\n\n\naddContArg env (Call l e p KwdNil) c    = Call NoLoc e (PosArg c p) KwdNil\n\naddContPar env dec (PosPar n a Nothing p) fx t\n  | inClass env && dec /= Static        = PosPar n a Nothing (addContPar0 p fx t)\naddContPar env dec p fx t               = addContPar0 p fx t\n\naddContPar0 p fx t                      = PosPar contKW (Just $ tCont1 fx t) Nothing p\n\ntCont0                                  = tFun fxProc (posRow tNone posNil) kwdNil tR\n\ntCont1 fx t                             = tFun fx (posRow t posNil) kwdNil tR\n\nkDef env k nts x t b                    = sDef k (conv env $ pospar $ (x,t):nts) tR b fxProc\n\nkRef k [] x t                           = eVar k\nkRef k ns x t                           = eLambda' [(x,t)] $ eCall (eVar k) (map eVar (x:ns))\n\nfxCall env test (Call _ Async{} p k)    = False\nfxCall env test (Call _ e p k)          = test fx\n  where TFun _ fx _ _ _                 = typeOf env e\nfxCall env test e                       = False\n\ncontCall env e                          = fxCall env contFX e\n\nmutCall env e                           = fxCall env mutFX e\n\ncontFX (TFX _ FXProc)                   = True\ncontFX _                                = False\n\nmutFX (TFX _ FXMut)                     = True\nmutFX (TFX _ FXProc)                    = True\nmutFX _                                 = False\n\ninCont env                              = length (ctxt env) > 0\n\n\nconvPOPDROP s@(If _ [Branch e _] _)\n  | isPUSH e                            = s\nconvPOPDROP (If l bs els)               = If l [ Branch e (map convPOPDROP ss) | Branch e ss <- bs ] (map convPOPDROP els)\nconvPOPDROP (While l e ss els)          = While l e (map convPOPDROP ss) (map convPOPDROP els)\nconvPOPDROP (Expr l (Call l1 e ps ks))\n  | Var l2 x <- e, x == primDROP        = Expr l (Call l1 (Var l2 primDROP_C) ps ks)\nconvPOPDROP (Assign l p (Call l1 e ps ks))\n  | Var l2 x <- e, x == primPOP         = Assign l p (Call l1 (Var l2 primPOP_C) ps ks)\nconvPOPDROP s                           = s\n\nconvPUSH (Call _ (Var _ x) _ _) arg\n  | x == primPUSH                       = eCall (eQVar primPUSH_Cc) [arg]\n  | x == primPUSHF                      = eCall (eQVar primPUSHF_Cc) [arg]\n\nclass NeedCont a where\n    needCont                            :: CPSEnv -> a -> Bool\n\ninstance (NeedCont a, EnvOf a) => NeedCont [a] where\n    needCont env []                     = False\n    needCont env (s : ss)               = needCont env s || needCont (define (envOf s) env) ss\n\ninstance NeedCont Branch where\n    needCont env (Branch e ss)          = needCont env ss\n\ninstance NeedCont Stmt where\n    needCont env (Return _ _)           = inCont env\n    needCont env (Continue _)\n      | inLoop env                      = False\n      | otherwise                       = inCont env\n    needCont env (Break _)\n      | inLoop env                      = False\n      | otherwise                       = inCont env\n    needCont env (Expr _ e)             = contCall env e\n    needCont env (Assign _ _ e)         = contCall env e\n    needCont env (MutAssign _ _ e)      = contCall env e\n    needCont env (If _ bs els)          = needCont env bs || needCont env els\n    needCont env (While _ _ ss els)     = needCont (setInLoop env) ss || needCont env els\n    needCont env (Decl _ ds)            = needCont (define (envOf ds) env) ds\n    needCont env _                      = False\n\ninstance NeedCont Decl where\n    needCont env Class{}                = True\n    needCont env d@Def{}                = contFX (dfx d)\n\n------------------------------------------------\n------------------------------------------------\n------------------------------------------------\n\n\nclass PreCPS a where\n    pre                                 :: CPSEnv -> a -> CpsM a\n    preTop                              :: CPSEnv -> a -> CpsM a\n    preTop env                          = pre env\n\ninstance PreCPS Module where\n    pre env (Module m imps mdoc ss)     = Module m imps mdoc <$> preSuite env ss\n\npreSuite env []                         = return []\npreSuite env (s : ss)                   = do (prefixes,s') <- withPrefixes $ pre env s\n                                             ss' <- preSuite (define (envOf s) env) ss\n                                             return (prefixes ++ s' : ss')\n\n\ninstance (PreCPS a, EnvOf a) => PreCPS [a] where\n    pre env []                          = return []\n    pre env (a:as)                      = (:) <$> pre env a <*> pre env1 as\n      where env1                        = define (envOf a) env\n\ninstance PreCPS a => PreCPS (Maybe a) where\n    pre env Nothing                     = return Nothing\n    pre env (Just a)                    = fmap Just (pre env a)\n\n    preTop env Nothing                  = return Nothing\n    preTop env (Just a)                 = fmap Just (preTop env a)\n\ninstance PreCPS Stmt where\n    pre env (Expr l e)                  = Expr l <$> preTop env e\n    pre env (Assign l ps e)             = Assign l ps <$> preTop env e\n    pre env (MutAssign l t e)           = MutAssign l <$> pre env t <*> preTop env e\n    pre env (Return l e)                = Return l <$> preTop env e\n    pre env (If l bs els)               = If l <$> pre env bs <*> preSuite env els      -- TODO: rewrite in case the 'bs' produce out-of-order prefixes\n    pre env (While l e b els)           = While l <$> pre env e <*> preSuite env b <*> preSuite env els\n    pre env (Decl l ds)                 = Decl l <$> pre env1 ds\n      where env1                        = define (envOf ds) env\n    pre env s                           = return s\n\ninstance PreCPS Decl where\n    pre env (Class l n q cs b ddoc)     = Class l n q cs <$> pre env1 b <*> pure ddoc\n      where env1                        = defineTVars (selfQuant (NoQ n) q) env\n    pre env (Def l n q p _k a b d fx ddoc)\n                                        = Def l n q p _k a <$> preSuite env1 b <*> pure d <*> pure fx <*> pure ddoc\n      where env1                        = define (envOf p) $ defineTVars q env\n\ninstance PreCPS Branch where\n    pre env (Branch e ss)               = Branch  <$> pre env e <*> preSuite env ss\n\ninstance PreCPS Handler where\n    pre env (Handler ex ss)             = Handler ex <$> preSuite env1 ss\n      where env1                        = define (envOf ex) env\n\ninstance PreCPS PosArg where\n    pre env (PosArg e p)                = PosArg <$> pre env e <*> pre env p\n    pre env PosNil                      = return PosNil\n\ninstance PreCPS Expr where\n    pre env e0@(Call l e ps KwdNil)\n      | mutCall env e0                  = do e1 <- pre env e\n                                             ps1 <- pre env ps\n                                             v <- newName \"pre\"\n                                             prefix [sAssign (pVar v t) (Call l e1 ps1 KwdNil)]\n                                             return (eVar v)\n      | otherwise                       = Call l <$> pre env e <*> pre env ps <*> pure KwdNil\n      where t                           = typeOf env e0\n    pre env (Async l e)                 = Async l <$> pre env e\n    pre env (TApp l e ts)               = TApp l <$> pre env e <*> pure ts\n    pre env (Let l ss e)                = do ss' <- preSuite env ss\n                                             (prefixes,e') <- withPrefixes $ pre env1 e\n                                             -- Let suites are emitted directly by CodeGen and never\n                                             -- pass through the statement-level CPS conversion, so we\n                                             -- must lift their rewritten statements into outer prefixes.\n                                             prefix (ss' ++ prefixes)\n                                             return e'\n       where env1                       = define (envOf ss) env\n    pre env (Cond l e1 e e2)            = do (pre1,e1') <- withPrefixes $ pre env e1\n                                             (pre2,e2') <- withPrefixes $ pre env e2\n                                             (pre0,e0') <- withPrefixes $ pre env e\n                                             case pre1++pre2 of\n                                                 [] -> do\n                                                     prefix pre0\n                                                     return $ Cond l e1' e0' e2'\n                                                 _ -> do\n                                                     v <- newName \"pre\"\n                                                     let s1 = pre1 ++ [sAssign (pVar v t) e1']\n                                                         s2 = pre2 ++ [sAssign (pVar v t) e2']\n                                                     prefix $ pre0 ++ [sIf1 e0' s1 s2]\n                                                     return $ eVar v\n      where t                           = upbound env $ map (typeOf env) [e1,e2]\n    pre env (IsInstance l e c)          = IsInstance l <$> pre env e <*> return c\n    pre env (BinOp l e1 Or e2)          = do (pre1,e1') <- withPrefixes $ pre env e1\n                                             (pre2,e2') <- withPrefixes $ pre env e2\n                                             case pre2 of\n                                                 [] -> do\n                                                     prefix pre1\n                                                     return $ BinOp l e1' Or e2'\n                                                 _ -> do\n                                                     x <- newName \"pre\"\n                                                     v <- newName \"pre\"\n                                                     let s1 = [sAssign (pVar v t) (eVar x)]\n                                                         s2 = pre2 ++ [sAssign (pVar v t) e2']\n                                                     prefix $ pre1 ++ [sAssign (pVar x t1) e1', sIf1 (eVar x) s1 s2]\n                                                     return $ eVar v\n      where t                           = upbound env $ map (typeOf env) [e1,e2]\n            t1                          = typeOf env e1\n    pre env (BinOp l e1 And e2)         = do (pre1,e1') <- withPrefixes $ pre env e1\n                                             (pre2,e2') <- withPrefixes $ pre env e2\n                                             case pre2 of\n                                                 [] -> do\n                                                     prefix pre1\n                                                     return $ BinOp l e1' And e2'\n                                                 _ -> do\n                                                     x <- newName \"pre\"\n                                                     v <- newName \"pre\"\n                                                     let s1 = pre2 ++ [sAssign (pVar v t) e2']\n                                                         s2 = [sAssign (pVar v t) (eVar x)]\n                                                     prefix $ pre1 ++ [sAssign (pVar x t1) e1', sIf1 (eVar x) s1 s2]\n                                                     return $ eVar v\n      where t                           = upbound env $ map (typeOf env) [e1,e2]\n            t1                          = typeOf env e1\n    pre env (UnOp l Not e)              = UnOp l Not <$> pre env e\n    pre env (Dot l e n)                 = Dot l <$> pre env e <*> return n\n    pre env (DotI l e i)                = DotI l <$> pre env e <*> return i\n    pre env (RestI l e i)               = RestI l <$> pre env e <*> return i\n    pre env (Lambda l p KwdNIL e fx)    = do (prefixes,e') <- withPrefixes $ preTop env1 e\n                                             case prefixes of\n                                                [] | contFX fx ->\n                                                        let p' = conv env p; t' = conv env t\n                                                            e1 = if contCall env e then addContArg env1 e' econt else eCallCont e' (econt,t')\n                                                        in return $ Lambda l (addContPar0 p' fx t') KwdNIL e1 fx\n                                                   | otherwise ->\n                                                        return $ Lambda l p KwdNIL e' fx\n                                                _ -> do\n                                                    f <- newName \"lambda\"\n                                                    prefix [sDecl [Def l f [] p KwdNIL (Just t) (prefixes ++ [sReturn e']) NoDec fx Nothing]]\n                                                    return (Var l0 (NoQ f))\n      where env1                        = define (envOf p) env\n            t                           = typeOf env1 e\n            econt                       = eVar contKW\n    pre env (Yield l e)                 = Yield l <$> pre env e\n    pre env (YieldFrom l e)             = YieldFrom l <$> pre env e\n    pre env (Tuple l es KwdNil)         = Tuple l <$> pre env es <*> pure KwdNil\n    pre env (List l es)                 = List l <$> pre env es\n    pre env (Dict l as)                 = Dict l <$> pre env as\n    pre env (Set l es)                  = Set l <$> pre env es\n    pre env e                           = return e\n\n    preTop env e0@(Call l e ps KwdNil)\n      | mutCall env e0                  = Call l <$> pre env e <*> pre env ps <*> pure KwdNil\n    preTop env e                        = pre env e\n\n\ninstance PreCPS Elem where\n    pre env (Elem e)                    = Elem <$> pre env e\n\ninstance PreCPS Assoc where\n    pre env (Assoc k v)                 = Assoc <$> pre env k <*> pre env v\n\n\n-- Convert types ----------------------------------------------------------------------------------------\n\nclass Conv a where\n    conv                                :: CPSEnv -> a -> a\n\ninstance (Conv a) => Conv [a] where\n    conv env                            = map $ conv env\n\ninstance (Conv a) => Conv (Maybe a) where\n    conv env                            = fmap $ conv env\n\ninstance (Conv a) => Conv (Name, a) where\n    conv env (n, x)                     = (n, conv env x)\n\ninstance Conv NameInfo where\n    conv env (NClass q ps te doc)       = NClass q (conv env ps) (conv env te) doc\n    conv env (NSig sc dec doc)          = NSig (conv env sc) dec doc\n    conv env (NDef sc dec doc)          = NDef (conv env sc) dec doc\n    conv env (NVar t)                   = NVar (conv env t)\n    conv env (NSVar t)                  = NSVar (conv env t)\n    conv env ni                         = ni\n\ninstance Conv WTCon where\n    conv env (w,c)                      = (w, conv env c)\n\ninstance Conv TSchema where\n    conv env (TSchema l q t)            = TSchema l (conv env q) (conv env t)\n\ninstance Conv QBind where\n    conv env (QBind v cs)               = QBind v (conv env cs)\n\ninstance Conv Type where\n    conv env t0@(TFun l fx p TNil{} t)\n       | contFX fx && t /= tR           = TFun l fx (addCont (conv env p) (conv env t)) kwdNil tR\n       | otherwise                      = TFun l fx (conv env p) kwdNil (conv env t)\n       where addCont p c                = posRow (tFun fx (posRow c posNil) kwdNil tR) p\n    conv env (TCon l c)                 = TCon l (conv env c)\n    conv env (TTuple l p k)             = TTuple l (conv env p) (conv env k)\n    conv env (TOpt l t)                 = TOpt l (conv env t)\n    conv env (TRow l k n t r)           = TRow l k n (conv env t) (conv env r)\n    conv env t                          = t\n\ninstance Conv TCon where\n    conv env (TC c ts)                  = TC c (conv env ts)\n\ninstance Conv PosPar where\n    conv env (PosPar n t Nothing p)     = PosPar n (conv env t) Nothing (conv env p)\n    conv env PosNIL                     = PosNIL\n\ninstance Conv Stmt where\n    conv env (Expr l e)                 = Expr l (conv env e)\n    conv env (Assign l [PVar _ n Nothing] e)\n      | n `elem` volatiles env          = MutAssign l (eDot (eVar n) valKW) (conv env e)\n    conv env (Assign l [PVar _ n (Just t)] e)\n      | n `elem` volatiles env          = Assign l [pVar n (tBox t)] (eCall (tApp (eQVar primBox) [t]) [conv env e])\n    conv env (Assign l ps e)            = Assign l (conv env ps) (conv env e)\n    conv env (MutAssign l tg e)         = MutAssign l (conv env tg) (conv env e)\n    conv env (Return l e)               = Return l (conv env e)\n    conv env (If l bs els)              = If l (conv env bs) (conv env els)\n    conv env (While l e b els)          = While l (conv env e) (conv env b) (conv env els)\n    conv env (Signature l ns sc dec)    = Signature l ns (conv env sc) dec\n    conv env s                          = s\n\ninstance Conv Branch where\n    conv env (Branch e ss)              = Branch (conv env e) (conv env ss)\n\ninstance Conv Pattern where\n    conv env (PVar l n t)               = PVar l n (conv env t)\n    conv env p                          = p\n\ninstance Conv Expr where\n    conv env (Var l (NoQ n))\n      | n `elem` volatiles env          = Dot l (Var l (NoQ n)) valKW\n    conv env (Var l n)\n      | n == primASYNCf                 = Var l primASYNCc\n      | n == primAFTERf                 = Var l primAFTERc\n      | n == primAWAITf                 = Var l primAWAITc\n      | otherwise                       = Var l n\n    conv env (Call l e ps KwdNil)       = Call l (conv env e) (conv env ps) KwdNil\n    conv env (Async l e)                = Async l (conv env e)\n    conv env (TApp l e ts)              = TApp l (conv env e) (conv env ts)\n    conv env (Let l ss e)               = Let l (conv env1 ss) (conv env1 e)\n        where env1                      = define (envOf ss) env\n    conv env (Cond l e1 e e2)           = Cond l (conv env e1) (conv env e) (conv env e2)\n    conv env (IsInstance l e c)         = IsInstance l (conv env e) c\n    conv env (BinOp l e1 Or e2)         = BinOp l (conv env e1) Or (conv env e2)\n    conv env (BinOp l e1 And e2)        = BinOp l (conv env e1) And (conv env e2)\n    conv env (UnOp l Not e)             = UnOp l Not (conv env e)\n    conv env (Dot l e n)                = Dot l (conv env e) n\n    conv env (DotI l e i)               = DotI l (conv env e) i\n    conv env (RestI l e i)              = RestI l (conv env e) i\n    conv env (Lambda l p KwdNIL e fx)   = Lambda l (conv env p) KwdNIL (conv env e) fx\n    conv env (Yield l e)                = Yield l (conv env e)\n    conv env (YieldFrom l e)            = YieldFrom l (conv env e)\n    conv env (Tuple l es ks)            = Tuple l (conv env es) (conv env ks)\n    conv env (List l es)                = List l (conv env es)\n    conv env (Dict l as)                = Dict l (conv env as)\n    conv env (Set l es)                 = Set l (conv env es)\n    conv env e                          = e\n\ninstance Conv PosArg where\n    conv env (PosArg e p)               = PosArg (conv env e) (conv env p)\n    conv env PosNil                     = PosNil\n\ninstance Conv KwdArg where\n    conv env (KwdArg n e p)             = KwdArg n (conv env e) (conv env p)\n    conv env KwdNil                     = KwdNil\n\ninstance Conv Elem where\n    conv env (Elem e)                   = Elem (conv env e)\n\ninstance Conv Assoc where\n    conv env (Assoc k v)                = Assoc (conv env k) (conv env v)\n"
  },
  {
    "path": "compiler/lib/src/Acton/CodeGen.hs",
    "content": "-- Copyright (C) 2019-2021 Data Ductus AB\n--\n-- Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:\n--\n-- 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.\n--\n-- 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.\n--\n-- 3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission.\n--\n-- THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS \"AS IS\" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n--\n\n{-# LANGUAGE MultiParamTypeClasses, FlexibleInstances, FlexibleContexts, DeriveGeneric #-}\nmodule Acton.CodeGen where\n\nimport qualified Data.Set\nimport qualified Data.List\nimport qualified Acton.Env\nimport Utils\nimport Pretty\nimport Acton.Syntax\nimport Acton.Names\nimport Acton.Builtin\nimport Acton.Printer\nimport Acton.Prim\nimport Acton.NameInfo\nimport Acton.Env\nimport Acton.QuickType\nimport Acton.Subst\nimport qualified Acton.Boxing as B\nimport Control.Monad.State.Lazy\nimport Prelude hiding ((<>))\nimport System.FilePath.Posix\nimport Numeric\n-- For fast SrcLoc offset->line lookup when emitting #line\nimport qualified Data.IntMap.Strict as IM\n\ngenerate                            :: Acton.Env.Env0 -> FilePath -> String -> Bool -> Module -> String -> IO (String,String,String)\ngenerate env srcbase srcText emitLines m hash = do return (n, h, c)\n\n  where n                           = concat (Data.List.intersperse \".\" (modPath (modname m))) --render $ quotes $ gen env0 (modname m)\n        hashComment                 = text \"/* Acton impl hash:\" <+> text hash <+> text \"*/\"\n        h                           = render $ hashComment $+$ hModule env0 m\n        c                           = render $ hashComment $+$ cModule env0 srcbase srcText emitLines m\n        env0                        = genEnv $ setMod (modname m) env\n\ngenRoot                            :: Acton.Env.Env0 -> QName -> IO String\ngenRoot env0 qn@(GName m n)         = do return $ render (cInclude $+$ cIncludeMods $+$ cInit $+$ cRoot)\n  where env                         = genEnv $ setMod m env0\n        cInclude                    = text \"#include \\\"rts/common.h\\\"\"\n        cIncludeMods                = include env \"out/types\" m\n        cInit                       = (text \"void\" <+> gen env primROOTINIT <+> parens empty <+> char '{') $+$\n                                       nest 4 (gen env (GName m initKW) <> parens empty <> semi) $+$\n                                       char '}'\n        cRoot                       = (gen env tActor <+> gen env primROOT <+> parens empty <+> char '{') $+$\n                                       nest 4 (text \"return\" <+> parens (gen env tActor) <> gen env primNEWACTOR <> parens (gen env qn) <> semi) $+$\n                                       char '}'\n\n\n\n\nmyPretty (GName m n)\n      | m == mBuiltin               = text (\"B_\" ++ nstr n)\n      | otherwise                   = pretty m <> dot <> pretty n\nmyPretty (NoQ w@(Internal _ _ _))   = pretty w\n\ninstName (GName m n)                = GName m (Derived n (globalName \"instance\"))\nmethName (GName m n)                = GName m (Derived n (globalName \"methods\"))\n\nderivedHead (Derived d@(Derived{}) _) = derivedHead d\nderivedHead (Derived n _)           = n\n\nstaticWitnessName (Dot _ c@(Call _ _ _ KwdNil) a) = (nm, NoQ a:as)\n   where (nm,as)                    = staticWitnessName c\nstaticWitnessName (Call _ (Var _ v@(GName m n)) PosNil KwdNil)\n    | m == mBuiltin                 = (Just v, [])\nstaticWitnessName (Call _ (TApp _ (Var _ (GName m n@(Derived n1 n2))) [TCon _ (TC gn1 []), _]) _ KwdNil)\n   | m == mBuiltin && n1 == nMapping && n2 == nDict && gn1 == qnInt\n                                    = (Just (gBuiltin (Derived n nInt)),[])\nstaticWitnessName (Call _ (TApp _ (Var _ (GName m n@(Derived n1 n2))) [TCon _ (TC gn1 []), _]) _ KwdNil)\n   | m == mBuiltin && n1 == nMapping && n2 == nDict && gn1 == qnStr\n                                    = (Just (gBuiltin (Derived n nStr)),[])\nstaticWitnessName (Call _ (TApp _ (Var _ v@(GName m n)) _) PosNil KwdNil)\n    | m == mBuiltin                 = (Just v, [])\nstaticWitnessName _                 = (Nothing, [])\n\n-- Environment --------------------------------------------------------------------------------------\n\ngenEnv env0                         = setX env0 GenX{ globalX = [], localX = [], retX = tNone, volVarsX = [], lineEmitX = Nothing }\n\ntype GenEnv                         = EnvF GenX\n\ndata GenX                           = GenX { globalX :: [Name]\n                                           , localX :: [Name]\n                                           , retX :: Type\n                                           , volVarsX :: [Name]\n                                           , lineEmitX :: Maybe (SrcLoc -> Doc)\n                                           }\n\ngdefine te env                      = modX env1 $ \\x -> x{ globalX = dom te ++ globalX x }\n  where env1                        = define te env\n\nldefine te env                      = modX env1 $ \\x -> x{ localX = dom te ++ localX x }\n  where env1                        = define te env\n\nclassdefine stmts env               = gdefine [ (n,i) | (n,i@NClass{}) <- envOf stmts ] env\n\nsetRet t env                        = modX env $ \\x -> x{ retX = t }\n\nglobal env                          = globalX (envX env) \\\\ localX (envX env)\n\ndefined env                         = globalX (envX env) ++ localX (envX env)\n\nret env                             = retX $ envX env\n\nsetVolVars as env                   = modX env $ \\x -> x{ volVarsX = as }\n\nisVolVar a env                      = a `elem` volVarsX (envX env)\n\n-- Line emission helpers\nsetLineEmit :: (SrcLoc -> Doc) -> GenEnv -> GenEnv\nsetLineEmit f env                   = modX env $ \\x -> x{ lineEmitX = Just f }\n\ngetLineEmit :: GenEnv -> (SrcLoc -> Doc)\ngetLineEmit env                     = case lineEmitX (envX env) of\n                                        Just f  -> f\n                                        Nothing -> const empty\n\n-- Helpers ------------------------------------------------------------------------------------------\n\ninclude                             :: GenEnv -> String -> ModName -> Doc\ninclude env dir m                   = text \"#include\" <+> doubleQuotes (text (joinPath $ dir : modPath m) <> text \".h\")\n\nmodNames (Import _ ms : is)         = [ m | ModuleItem m _ <- ms ] ++ modNames is\nmodNames (FromImport _ (ModRef (0,Just m)) _ : is)\n                                    = m : modNames is\nmodNames (FromImportAll _ (ModRef (0,Just m)) : is)\n                                    = m : modNames is\nmodNames []                         = []\n\n\n-- Header -------------------------------------------------------------------------------------------\n\nhModule env (Module m imps _ stmts) = text \"#pragma\" <+> text \"once\" $+$\n                                      (if inBuiltin env\n                                       then empty\n                                       else text \"#include \\\"builtin/builtin.h\\\"\" $+$ -- TODO: can we include out/types/__builtin__.h instead?\n                                            include env \"rts\" (modName [\"rts\"])) $+$\n                                      vcat (map (include env \"out/types\") $ modNames imps) $+$\n                                      hSuite 1 env1 stmts $+$\n                                      hSuite 2 env1 stmts $+$\n                                      text \"void\" <+> genTopName env initKW <+> parens empty <> semi\n  where env1                        = classdefine stmts env\n\n\nhSuite phase env []                 = empty\nhSuite phase env (s:ss)             = hStmt phase env s $+$ hSuite phase (gdefine (envOf s) env) ss\n\nhStmt 1 env (Decl _ ds)             = vmap (declstub env1) ds $+$\n                                      vmap (typedef env1) ds $+$\n                                      vmap (decl env1) ds $+$\n                                      vmap (methstub env1) ds\n  where env1                        = gdefine (envOf ds) env\nhStmt 2 env s                       = vcat [ text \"extern\" <+> genTypeDecl env n t <+> genTopName env n <> semi | (n,NVar t) <- envOf s]\nhStmt _ env s                       = empty\n\ndeclstub env (Class _ n q a b ddoc) = text \"struct\" <+> genTopName env n <> semi\ndeclstub env Def{}                  = empty\n\ntypedef env (Class _ n q a b ddoc)  = text \"typedef\" <+> text \"struct\" <+> genTopName env n <+> char '*' <> genTopName env n <> semi\ntypedef env Def{}                   = empty\n\ndecl env (Class _ n q a b ddoc)     = (text \"struct\" <+> classname env n <+> char '{') $+$\n                                      nest 4 (vcat $ stdprefix env ++ initdef : serialize env tc : deserialize env tc : meths) $+$\n                                      char '}' <> semi $+$\n                                      inst_struct\n  where tc                          = TC (NoQ n) [ tVar v | QBind v _ <- q ]\n        initdef : meths             = fields env tc\n        properties                  = [ varsig env n (sctype sc) <> semi | (n, NSig sc Property _) <- fullAttrEnv env tc ]\n        inst_struct | initNotImpl   = empty\n                    | otherwise     = (text \"struct\" <+> genTopName env n <+> char '{') $+$\n                                      nest 4 (classlink env n $+$ vcat properties) $+$\n                                      char '}' <> semi\n        initNotImpl                 = any hasNotImpl [ b' | Decl _ ds <- b, Def{dname=n',dbody=b'} <- ds, n' == initKW ]\ndecl env (Def _ n q p _ (Just t) _ _ fx ddoc)\n                                    = genTypeDecl env n (exposeMsg fx t) <+> genTopName env n <+> parens (par env $ prowOf p) <> semi\n  where par                         = if isUnboxed n then uparams else params\nmethstub env (Class _ n q a b ddoc) = text \"extern\" <+> text \"struct\" <+> classname env n <+> methodtable env n <> semi $+$\n                                      constub env t n r b\n  where TFun _ _ r _ t              = sctype $ fst $ schemaOf env (eVar n)\nmethstub env Def{}                  = empty\n\nconstub env t n r b\n  | null ns || hasNotImpl b         = gen env t <+> newcon env n <> parens (params env r) <> semi\n  | otherwise                       = empty\n  where ns                          = abstractAttrs env (NoQ n)\n\nfields env c                        = map field (vsubst [(tvSelf,tCon c)] te)\n  where te                          = fullAttrEnv env c\n        field (n, NDef sc Static _) = funsig env n (sctype sc) <> semi\n        field (n, NDef sc NoDec _)  = methsig env c n (sctype sc) <> semi\n        field (n, NVar t)           = varsig env n t <> semi\n        field (n, NSig sc Static _) = funsig env n (sctype sc) <> semi\n        field (n, NSig sc NoDec _)  = methsig env c n (sctype sc) <> semi\n        field (n, NSig sc Property _)\n                                    = empty\n\nfunsig env n (TFun _ _ r _ t)       = gen env t <+> parens (char '*' <> gen env n) <+> parens (params env r)\nfunsig env n t                      = varsig env n t\n\nmethsig env c n (TFun _ fx r _ t)   = gen env (exposeMsg fx t) <+> parens (char '*' <> gen env n) <+> parens (params env $ posRow (tCon c) r)\nmethsig env c n t                   = varsig env n t\n\nparams env (TNil _ _)               = empty\nparams env (TRow _ _ _ t r@TRow{})  = gen env t <> comma <+> params env r\nparams env (TRow _ _ _ t TNil{})    = gen env t\nparams env (TRow _ _ _ t TVar{})    = gen env t                                         -- Ignore param tails for now...\nparams env t                        = error (\"codegen unexpected row: \" ++ prstr t)\n\nuparams env (TNil _ _)               = empty\nuparams env (TRow _ _ _ t r@TRow{})  = utype env t <> comma <+> uparams env r\nuparams env (TRow _ _ _ t TNil{})    = utype env t\nuparams env (TRow _ _ _ t TVar{})    = utype env t                                         -- Ignore param tails for now...\nuparams env t                        = error (\"codegen unexpected row: \" ++ prstr t)\n\nutype env t\n | B.isUnboxable t                  = text (unboxed_c_type t)\n | otherwise                        = gen env t\n\nexposeMsg fx t                      = if fx == fxAction then tMsg t else t\n\nexposeMsg' t@TFun{}                 = t{ restype = exposeMsg (effect t) (restype t) }\nexposeMsg' t                        = t\n\nvarsig env n t                      = gen env t <+> gen env n\n\nstdprefix env                       = [gcinfo env, classid env, superlink env]\n\ngcinfo env                          = text \"char\" <+> text \"*\" <> gen env gcinfoKW <> semi\n\nclassid env                         = text \"int\" <+> gen env classidKW <> semi\n\nsuperlink env                       = gen env tSuperclass <+> gen env superclassKW <> semi\n  where tSuperclass                 = tCon $ TC qnSuperClass []\n\nqnSuperClass                        = GName mPrim (Derived (name \"Super\") suffixClass)\n\nserialize env c                     = text \"void\" <+> parens (char '*' <> gen env serializeKW) <+> parens (gen env c <> comma <+> gen env tSerialstate) <> semi\n\ndeserialize env c                   = gen env (tCon c) <+> parens (char '*' <> gen env deserializeKW) <+> parens (gen env c <> comma <+> gen env tSerialstate) <> semi\n\nclasslink env n                     = text \"struct\" <+> classname env n <+> text \"*\" <> gen env classKW <> semi\n\nclassname env n                     = genTopName env (Derived n suffixClass)\n\nmethodtable env n                   = gen env (tableName $ gname env n)\n\nstaticwitness env n                 = gen env (witName n)\n\nmethodtable' env (NoQ n)            = methodtable env n\nmethodtable' env n                  = gen env $ tableName (unalias env n)\n\ntableName (GName m n)               = GName m (Derived n suffixMethods)\ntableName n                         = error (\"#### tableName \" ++ show n)\n\nwitName (GName m n)                 = GName m (Derived n suffixWitness)\nwitName n                           = error (\"#### witName \" ++ show n)\n\nnewcon env n                        = gen env (conName $ gname env n)\n\nnewcon' env (NoQ n)                 = newcon env n\nnewcon' env n                       = gen env $ conName $ unalias env n\n\nconName (GName m n)                 = GName m (Derived n suffixNew)\n\nserializeSup env c                  = methodtable' env c <> dot <> gen env serializeKW\ndeserializeSup env c                = methodtable' env c <> dot <> gen env deserializeKW\n\nclassKW                             = primKW \"class\"\ngcinfoKW                            = primKW \"GCINFO\"\nclassidKW                           = primKW \"class_id\"\nsuperclassKW                        = primKW \"superclass\"\ncomponentsKW                        = name \"components\"\nserializeKW                         = name \"__serialize__\"\ndeserializeKW                       = name \"__deserialize__\"\n\nprimAND                             = gPrim \"AND\"\nprimOR                              = gPrim \"OR\"\nprimNOT                             = gPrim \"NOT\"\nprimROOT                            = gPrim \"ROOT\"\nprimROOTINIT                        = gPrim \"ROOTINIT\"\nprimRegister                        = gPrim \"register\"\n\nprimToInt                           = name \"toB_int\"\nprimToU64                           = name \"toB_u64\"\nprimToBigInt                        = name \"toB_bigint\"\nprimToBigInt2                       = name \"toB_bigint2\"\nprimToFloat                         = name \"to$float\"\nprimToStr                           = name \"to$str\"\nprimToBytearray                     = name \"to$bytearray\"\nprimToBytes                         = Derived (name \"to$bytes\") (name \"len\")\n\ntmpV                                = primKW \"tmp\"\n\ntSerialstate                        = tCon $ TC (GName mPrim (name \"Serial$state\")) []\nprimStepSerialize                   = gPrim \"step_serialize\"\nprimStepDeserialize                 = gPrim \"step_deserialize\"\nprimDNEW                            = gPrim \"DNEW\"\nprimNEWTUPLE                        = gPrim \"NEWTUPLE\"\nprimNEWTUPLE0                       = gPrim \"NEWTUPLE0\"\n\n\n-- Implementation -----------------------------------------------------------------------------------\n\ncModule env srcbase srcText emitLines (Module m imps _ stmts)\n                                    = (if inBuiltin env then text \"#include \\\"builtin/builtin.c\\\"\" else empty) $+$\n                                      text \"#include \\\"rts/common.h\\\"\" $+$\n                                      include env (if inBuiltin env then \"\" else \"out/types\") m $+$\n                                      ext_include $+$\n                                      declModule envWithLine stmts $+$\n                                      text \"int\" <+> genTopName env initFlag <+> equals <+> text \"0\" <> semi $+$\n                                      (text \"void\" <+> genTopName env initKW <+> parens empty <+> char '{') $+$\n                                      nest 4 (text \"if\" <+> parens (genTopName env initFlag) <+> text \"return\" <> semi $+$\n                                              genTopName env initFlag <+> equals <+> text \"1\" <> semi $+$\n                                              ext_init $+$\n                                              initImports $+$\n                                              initTables env1 stmts $+$\n                                              initGlobals env1 stmts) $+$\n                                      char '}'\n  where initImports                 = vcat [ gen env (GName m initKW) <> parens empty <> semi | m <- modNames imps ]\n        external                    = notImpl && not (inBuiltin env)\n        ext_include                 = if notImpl then text \"#include\" <+> doubleQuotes (text srcbase <> text \".ext.c\") else empty\n        ext_init                    = if notImpl then genTopName env (name \"__ext_init__\") <+> parens empty <> semi else empty\n        notImpl                     = hasNotImpl stmts\n        env1                        = classdefine stmts env\n        -- Emit a C #line directive for a given Acton SrcLoc if available\n        actFile                     = srcbase ++ \".act\"\n        -- Our AST source locations (SrcLoc) carry byte offsets (start,end), not (row,col).\n        -- C's #line requires a 1-based line number, so we convert offsets -> line numbers.\n        -- We precompute line start offsets and use an IntMap + lookupLE for O(log n) mapping.\n        lineStarts :: [Int]\n        lineStarts                  = 0 : [ i+1 | (i,c) <- zip ([0..] :: [Int]) srcText, c == '\\n' ]\n        lineMap    :: IM.IntMap Int\n        lineMap                     = IM.fromList (zip lineStarts ([1..] :: [Int]))\n        offsetToLine :: Int -> Int\n        offsetToLine off            = case IM.lookupLE off lineMap of\n                                         Just (_, ln) -> ln\n                                         Nothing      -> 1\n        emitLine NoLoc              = empty\n        emitLine (Loc startOffset _) =\n            text \"#line\" <+> pretty (offsetToLine startOffset) <+> doubleQuotes (text actFile)\n        envWithLine                 = if emitLines then setLineEmit emitLine env1 else env1\n\n\ndeclModule env []                   = empty\ndeclModule env (Decl _ ds : ss)     = vcat [ declDecl env1 d | d <- ds ] $+$\n                                      declModule env1 ss\n  where env1                        = gdefine (envOf ds) env\n        te                          = envOf ds\ndeclModule env (Signature{} : ss)   = declModule env ss\ndeclModule env (s : ss)             = vcat [ genTypeDecl env n t <+> genTopName env n <> semi | (n,NVar t) <- te ] $+$\n                                      declModule env1 ss\n  where te                          = envOf s `exclude` defined env\n        env1                        = gdefine te env\n\n\ndeclDecl env (Def dloc n q p KwdNIL (Just t) b d fx ddoc)\n  | hasNotImpl b                    = genTypeDecl env n t1 <+> genTopName env n <+> parens (gen env p) <> semi $+$\n                                      text \"/*\" $+$\n                                      decl $+$\n                                      text \"*/\"\n  | otherwise                       = decl\n  where (ss',vs)                    = genSuite env1 b\n        decl                        = emit dloc $+$\n                                      (genTypeDecl env n t1 <+> genTopName env n <+> parens (gen (setVolVars vs env) p) <+> char '{') $+$\n                                      nest 4 ss' $+$\n                                      char '}'\n        env1                        = setRet t1 $ ldefine (envOf p) $ defineTVars q env\n        t1                          = exposeMsg fx t\n        emit                        = getLineEmit env\n\ndeclDecl env (Class _ n q as b ddoc)\n    | cDefinedClass                 = vcat [ declDecl env1 d{ dname = methodname n (dname d) } | Decl _ ds <- b', d@Def{} <- ds ] $+$\n                                      text \"struct\" <+> classname env n <+> methodtable env n <> semi\n    | otherwise                     = vcat [ declDecl env1 d{ dname = methodname n (dname d) } | Decl _ ds <- b', d@Def{} <- ds ] $+$\n                                      declSerialize env1 n c props sup_c $+$\n                                      declDeserialize env1 n c props sup_c $+$\n                                      declCleanup env1 n sup_c $+$\n                                      declCon env1 n q b $+$\n                                      text \"struct\" <+> classname env n <+> methodtable env n <> semi\n  where b'                          = vsubst [(tvSelf, tCon c)] b\n        c                           = TC (NoQ n) (map tVar $ qbound q)\n        env1                        = defineTVars q env\n        props                       = [ n | (n, NSig sc Property _) <- fullAttrEnv env c ]\n        sup_c                       = filter ((`elem` special_repr) . tcname) as\n        special_repr                = [primActor] -- To be extended...\n        cDefinedClass               = inBuiltin env && any hasNotImpl [b' | Decl _ ds <- b, Def{dname=n',dbody=b'} <- ds, n' == initKW ]\n\ndeclCleanup env n sup_c\n  -- TODO: only match if this is an actor, or even better if this actor has a __cleanup__ method defined (not empty!?)\n  | not (null sup_c)                = -- Only for actors\n                                      text \"void\" <+> genTopName env (methodname n attr_finalizer) <+> parens (text \"void *obj, void *cdata\") <+> char '{' $+$\n                                      -- t_cleanupQ_Foo self = (t_cleanupQ_Foo)obj;\n                                      -- self->$class->__cleanup__(self);\n                                      nest 4 ((genTopName env n) <+> gen env self <+> equals <+> parens (genTopName env n) <> text \"obj\" <> semi $+$\n                                              gen env self <> text \"->\" <> gen env classKW <> text \"->\" <> gen env cleanupKW <> parens (gen env self) <> semi) $+$\n                                      char '}'\n  | otherwise                       = empty\n  where self                        = name \"self\"\n\ndeclSerialize env n c props sup_c   = (text \"void\" <+> genTopName env (methodname n serializeKW) <+> parens (gen env pars) <+> char '{') $+$\n                                      nest 4 (super_step $+$ vcat [ step i | i <- props \\\\ super_attrs ]) $+$\n                                      char '}'\n  where pars                        = PosPar self (Just $ tCon c) Nothing $ PosPar st (Just tSerialstate) Nothing PosNIL\n        st                          = name \"state\"\n        self                        = name \"self\"\n        super_step | [c] <- sup_c   = serializeSup env (tcname c) <> parens (parens (gen env $ tcname c) <> gen env self <> comma <+> gen env st) <> semi\n                   | otherwise      = empty\n        super_attrs                 = [ i | c <- sup_c, i <- conAttrs env (tcname c) ]\n        step i                      = gen env primStepSerialize <> parens (gen env self <> text \"->\" <> gen env i <> comma <+> gen env st) <> semi\n\ndeclDeserialize env n c props sup_c = (gen env (tCon c) <+> genTopName env (methodname n deserializeKW) <+> parens (gen env pars) <+> char '{') $+$\n                                      nest 4 (optcreate $+$ super_step $+$ vcat [ step i | i <- props \\\\ super_attrs ] $+$ ret) $+$\n                                      char '}'\n  where pars                        = PosPar self (Just $ tCon c) Nothing $ PosPar st (Just tSerialstate) Nothing PosNIL\n        st                          = name \"state\"\n        self                        = name \"self\"\n        env1                        = ldefine [(st, NVar tSerialstate)] env\n        optcreate                   = (text \"if\" <+> parens (text \"!\" <> gen env self) <+> char '{') $+$\n                                      nest 4 ((text \"if\" <+> parens (text \"!\" <> gen env st) <+> char '{') $+$\n                                              nest 4 (alloc $+$ text \"return\" <+> gen env self <> semi) $+$\n                                              char '}' $+$\n                                              create) $+$\n                                      char '}'\n        create                      = gen env self <+> text \"=\" <+> gen env primDNEW <> parens (genTopName env n <> comma <+> gen env st) <> semi\n        alloc                       = gen env self <+> equals <+> acton_malloc env (gname env n) <> semi $+$\n                                      gen env self <> text \"->\" <> gen env1 classKW <+> equals <+> char '&' <> methodtable env1 n <> semi\n        super_step | [c] <- sup_c   = deserializeSup env (tcname c) <> parens (parens (gen env $ tcname c) <> gen env self <> comma <+> gen env st) <> semi\n                   | otherwise      = empty\n        super_attrs                 = [ i | c <- sup_c, i <- conAttrs env (tcname c) ]\n        step i                      = gen env self <> text \"->\" <> gen env i <+> text \"=\" <+> gen env primStepDeserialize <> parens (gen env st) <> semi\n        ret                         = text \"return\" <+> gen env self <> semi\n\n\ninitTables env []                   = empty\ninitTables env (Decl _ ds : ss)     = vcat [ char '{' $+$ nest 4 (initClassBase env1 n q as hC $+$ initClass env1 n b hC) $+$ char '}' | Class _ n q as b ddoc <- ds, let hC = hasCDef b ] $+$\n                                      initTables env1 ss\n  where env1                        = gdefine (envOf ds) env\n        hasCDef b                   = inBuiltin env && any hasNotImpl [b' | Decl _ ds <- b, Def{dname=n',dbody=b'} <- ds, n' == initKW ]\n\ninitTables env (s : ss)             = initTables env ss\n\n\ninitGlobals env []                  = empty\ninitGlobals env (Decl _ ds : ss)    = initGlobals env1 ss\n  where env1                        = gdefine (envOf ds) env\ninitGlobals env (Signature{} : ss)  = initGlobals env ss\ninitGlobals env (s : ss)            = genStmt1 env s $+$\n                                      vcat [ genTopName env n <+> equals <+> gen env n <> semi | (n,_) <- te ] $+$\n                                      initGlobals env1 ss\n  where te                          = envOf s `exclude` defined env\n        env1                        = gdefine te env\n\ninitClassBase env c q as hasCDef    = methodtable env c <> dot <> gen env gcinfoKW <+> equals <+> doubleQuotes (genTopName env c) <> semi $+$\n                                      methodtable env c <> dot <> gen env superclassKW <+> equals <+> super <> semi $+$\n                                      vcat [ inherit c' n | (c',n) <- inheritedAttrs env (NoQ c) ]\n  where super                       = if null as then text \"NULL\" else parens (gen env qnSuperClass) <> text \"&\" <> methodtable' env (tcname $ head as)\n        selfsubst                   = selfSubst (NoQ c) q\n        inherit c' n\n          | hasCDef                 = methodtable env c <> dot <> gen env n <+> equals <+> genTopName env (methodname c n) <> semi\n          | otherwise               = methodtable env c <> dot <> gen env n <+> equals <+> cast (fromJust $ lookup n te) <> methodtable' env c' <> dot <> gen env n <> semi\n        cast (NSig sc dec _)        = parens (gen env (selfsubst $ addSelf (sctype sc) (Just dec)))\n        cast (NDef sc dec _)        = parens (gen env (selfsubst $ addSelf (sctype sc) (Just dec)))\n        cast (NVar t)               = parens (gen env $ selfsubst t)\n        te                          = fullAttrEnv env $ TC (NoQ c) [ tVar v | QBind v _ <- q ]\n\ninitClass env c [] hasCDef          = vcat [ methodtable env c <> dot <> gen env n <+> equals <+> genTopName env (methodname c n) <> semi | n <- [serializeKW,deserializeKW] ] $+$\n                                      if hasCDef then empty else gen env primRegister <> parens (char '&' <> methodtable env c) <> semi\ninitClass env c (Decl _ ds : ss) b  = vcat [ methodtable env c <> dot <> gen env n <+> equals <+> genTopName env (methodname c n) <> semi | Def{dname=n} <- ds ] $+$\n                                      initClass env1 c ss b\n  where env1                        = gdefine (envOf ds) env\ninitClass env c (Signature{} : ss) b = initClass env c ss b\ninitClass env c (s : ss) b\n  | isNotImpl s                     = initClass env c ss b\n  | otherwise                       = genStmt1 env s $+$\n                                      vcat [ genTopName env c <> dot <> gen env n <+> equals <+> gen env n <> semi | (n,_) <- te ] $+$\n                                      initClass env1 c ss b\n  where te                          = envOf s `exclude` defined env\n        env1                        = ldefine te env\n\n\ninitFlag                            = name \"done$\"\n\nmethodname c n                      = Derived c n\n\nclass Gen a where\n    gen                             :: GenEnv -> a -> Doc\n    genV                            :: GenEnv -> a -> (Doc,[Name])\n\n    genV env x                      = (gen env x,[])\n    gen env x                       = fst(genV env x)\n\ninstance (Gen a) => Gen (Maybe a) where\n    gen env x                       = maybe empty (gen env) x\n    genV env x                      = maybe (empty,[]) (genV env) x\n\ninstance Gen ModName where\n    gen env (ModName ns)            = hcat $ punctuate (text \"Q_\") $ map (gen env) ns\n\ninstance Gen QName where\n    gen env (GName m n)\n      | m == mPrim                  = char '$' <> text (rawstr n)\n      | m == mBuiltin               = text \"B_\" <> text (nstr n)\n      | otherwise                   = gen env m <> text \"Q_\" <> text (mkCident $ nstr n)\n    gen env (NoQ n)                 = gen env n\n    gen env n@QName{}\n      | n `elem` B.mathfuns         = text (nstr (noq n))\n      | otherwise                   = gen env (unalias env n)\n\ninstance Gen Name where\n    gen env nm                      = text $ unCkeyword $ mkCident $ nstr nm\n\ngenTopName env n                    = gen env (gname env n)\n\ngenQName env (NoQ n)\n  | n `elem` global env             = genTopName env n\n  | isAlias n env                   = genTopName env n\ngenQName env n                      = gen env n\n\ngname env n                         = unalias env (NoQ n)\n\nmkCident \"complex\"                  = \"complx\"\nmkCident \"__complex__\"              = \"__complx__\"\nmkCident \"complx\"                   = \"A_complex\"\nmkCident \"__complx__\"               = \"A___complex__\"\n\nmkCident (c:s)\n  | isAlpha c                       = c : esc s\n  | otherwise                       = hex c ++ esc s\n  where isAlpha c                   = c `elem` ['a'..'z'] || c `elem` ['A'..'Z'] || c `elem` ['_','$']\n        isAlphaNum c                = isAlpha c || c `elem` ['0'..'9']\n        esc (c:s) | isAlphaNum c    = c : esc s\n                  | otherwise       = hex c ++ esc s\n        esc \"\"                      = \"\"\n        hex c                       = \"X_\" ++ showHex (fromEnum c) \"_\"\n\nunCkeyword str\n  | str `Data.Set.member` rws       = preEscape str\n  | otherwise                       = str\n  where rws                         = Data.Set.fromDistinctAscList [\n                                        \"alignas\",\n                                        \"alignof\",\n                                        \"auto\",\n                                        \"bool\",\n                                        \"break\",\n                                        \"case\",\n                                        \"char\",\n                                        \"const\",\n                                        \"constexpr\",\n                                        \"continue\",\n                                        \"default\",\n                                        \"do\",\n                                        \"double\",\n                                        \"else\",\n                                        \"enum\",\n                                        \"extern\",\n                                        \"false\",\n                                        \"float\",\n                                        \"for\",\n                                        \"goto\",\n                                        \"if\",\n                                        \"inline\",\n                                        \"int\",\n                                        \"long\",\n                                        \"nullptr\",\n                                        \"register\",\n                                        \"restrict\",\n                                        \"return\",\n                                        \"short\",\n                                        \"signed\",\n                                        \"sizeof\",\n                                        \"static\",\n                                        \"static_assert\",\n                                        \"struct\",\n                                        \"switch\",\n                                        \"thread_local\",\n                                        \"true\",\n                                        \"typedef\",\n                                        \"typeof\",\n                                        \"typeof_unequal\",\n                                        \"union\",\n                                        \"unsigned\",\n                                        \"void\",\n                                        \"volatile\",\n                                        \"while\",\n                                        \"_Alignas\",\n                                        \"_Alignof\",\n                                        \"_Atomic\",\n                                        \"_BitInt\",\n                                        \"_Bool\",\n                                        \"_Complex\",\n                                        \"_Decimal128\",\n                                        \"_Decimal32\",\n                                        \"_Decimal64\",\n                                        \"_Generic\",\n                                        \"_Imaginary\",\n                                        \"_Noreturn\",\n                                        \"_Static_assert\",\n                                        \"_Thread_local\"\n                                      ]\n\n\n\npreEscape str                       = \"A_\" ++ str\n\nword                                = text \"$WORD\"\n\ngenSuite :: GenEnv -> Suite -> (Doc,[Name])\ngenSuite env []                     = (empty,[])\ngenSuite env (s:ss)                 = ((emit (sloc s) $+$ c) $+$ cs, vs' ++ (vs `intersect` defined env))\n    where (cs,vs)                   = genSuite (ldefine (envOf s) env) ss\n          (c,vs')                   = genStmt (setVolVars vs env) s\n          emit                      = getLineEmit env\n\ngenTypeDecl env n t                 =  (if isVolVar n env then text \"volatile\" else empty) <+>\n                                       if isUnboxed n && B.isUnboxable t then text (unboxed_c_type t) else gen env t\n\n\ngenStmt env (Decl _ ds)             = (empty, [])\ngenStmt env (Assign _ [PVar _ n (Just t)] e)\n  | n `notElem` defined env         = (genTypeDecl env n t <+> gen env n <+> equals <+> rhs <> semi, [])\n  where rhs                         = if isWitness n\n                                      then case staticWitnessName e of\n                                           (Just nm,as) ->\n                                               foldr (\\x y -> y <> text \"->\" <> myPretty x) (parens (myPretty (tcname (tcon t))) <> myPretty (witName nm)) as\n                                           _  -> genExp env t e\n                                      else genExp env t e\ngenStmt env s                       = (vcat [ genTypeDecl env n t <+> gen env n <> semi | (n,NVar t) <- te ] $+$ s', vs)\n  where te                          = envOf s `exclude` defined env\n        env1                        = ldefine te env\n        (s', vs)                    = genV env1 s\n\ngenStmt1 env s                      = fst $ genStmt env s\n\ninstance Gen Stmt where\n    genV env s | isNotImpl s        = (text \"//\" <+> text \"NotImplemented\", [])\n    genV env (Expr _ Strings{})     = (semi, [])\n    genV env (Expr _ e)             = (genExp' env e <> semi, [])\n    genV env (Assign _ [p] e)\n        | B.isUnboxable t           = (gen env p <+> equals <+> gen env e <> semi, [])\n        | otherwise                 = (gen env p <+> equals <+> genExp env t e <> semi, [])\n\n      where t                       = typeOf env p\n    genV env (AugAssign _ tg op e)  = (genTarget env tg <+> augPretty op <+> genExp env t e <> semi, [])\n      where t                       = targetType env tg\n    genV env (MutAssign _ tg e)     = (genTarget env tg <+> equals <+> genExp env t e <> semi, [])\n      where t                       = targetType env tg\n    genV env (Pass _)               = (empty, [])\n    genV env (Return _ Nothing)     = (text \"return\" <+> gen env eNone <> semi, [])\n    genV env (Return _ (Just e))    = (text \"return\" <+> genExp env (ret env) e <> semi, [])\n    genV env (Break _)              = (text \"break\" <> semi, [])\n    genV env (Continue _)           = (text \"continue\" <> semi, [])\n    genV _ (If _ (Branch (Bool _ True) [Pass _] : _) _)\n                                    = (empty, [])\n    genV env (If  _ [b@(Branch e ss)] fin)\n      | isPUSH e                    = (b' $+$ fin', v1 ++ v2 ++ volatiles)\n      where (b',v1)                 = genBranch env \"if\" b\n            (fin',v2)               = genElse env fin\n            volatiles               = bound ss `intersect` defined env\n    genV env (If _ (b:bs) b2)       = (b' $+$ vcat bs' $+$ b2', v1 ++ concat v2 ++ v3)\n       where (b',v1)                = genBranch env \"if\" b\n             (bs',v2)               = unzip (map (genBranch env \"else if\") bs)\n             (b2',v3)               = genElse env b2\n    genV env (While _ e b [])       = genBranch env \"while\" (Branch e b)\n    genV env _                      = (empty, [])\n\ngenBranch env kw (Branch e b)       = ((text kw <+> parens(genBool env (B.unbox t e)) <+> char '{') $+$ nest 4 b' $+$ char '}', vs)\n   where (b',vs)                    = genSuite env b\n         t                          = typeOf env e\n\ngenElse env []                      = (empty, [])\ngenElse env b                       = ((text \"else\" <+> char '{') $+$ nest 4 b' $+$ char '}', vs)\n   where (b',vs)                    = genSuite env b\n\ninstance Gen PosPar where\n    gen env (PosPar n (Just t) _ PosNIL)\n                                    = genTypeDecl env n t <+> gen env n\n    gen env (PosPar n (Just t) _ p) = genTypeDecl env n t <+> gen env n <> comma <+> gen env p\n    gen env PosNIL                  = empty\n\ninstance Gen PosArg where\n    gen env (PosArg e PosNil)       = gen env e\n    gen env (PosArg e p)            = gen env e <> comma <+> gen env p\n    gen env PosNil                  = empty\n\n\nformatLit (Strings l ss)            = Strings l [format $ concat ss]\n  where format []                   = []\n        format ('%':s)              = '%' : flags s\n        format (c:s)                = c : format s\n        flags (f:s)\n          | f `elem` \"#0- +\"        = f : flags s\n        flags s                     = width s\n        width ('*':s)               = '*' : dot s\n        width (n:s)\n          | n `elem` \"123456789\"    = let (n',s') = span (`elem` \"0123456789\") s in n : n' ++ dot s'\n        width s                     = dot s\n        dot ('.':s)                 = '.' : prec s\n        dot s                       = len s\n        prec ('*':s)                = '*' : len s\n        prec (n:s)\n          | n `elem` \"0123456789\"   = let (n',s') = span (`elem` \"0123456789\") s in n : n' ++ len s'\n        prec s                      = len s\n        len (l:s)\n          | l `elem` \"hlL\"          = 'l' : conv s\n        len s                       = conv0 s\n        conv0 (t:s)\n          | t `elem` \"diouxXc\"      = 'l' : conv (t:s)\n        conv0 s                     = conv s\n        conv (t:s)                  = t : format s\n\ncastLit env (Strings l ss) p        = format (concat ss) p\n  where format [] p                 = empty\n        format ('%':s) p            = flags s p\n        format (c:s) p              = format s p\n        flags (f:s) p\n          | f `elem` \"#0- +\"        = flags s p\n        flags s p                   = width s p\n        width ('*':s) (PosArg e p)  = comma <+> parens (text \"int\") <> expr <> dot s p\n          where expr                = text \"fromB_int\" <> parens (gen env e)\n        width (n:s) p\n          | n `elem` \"123456789\"    = let (n',s') = span (`elem` \"0123456789\") s in dot s' p\n        width s p                   = dot s p\n        dot ('.':s) p               = prec s p\n        dot s p                     = len s p\n        prec ('*':s) (PosArg e p)   = comma <+> parens (text \"int\") <> expr <> len s p\n          where expr                = text \"fromB_int\" <> parens (gen env e)  --parens (parens (gen env tInt) <> gen env e) <> text \"->val\"\n        prec (n:s) p\n          | n `elem` \"0123456789\"   = let (n',s') = span (`elem` \"0123456789\") s in len s' p\n        prec s p                    = len s p\n        len (l:s) p\n          | l `elem` \"hlL\"          = conv s p\n        len s p                     = conv s p\n        conv (t:s) (PosArg e p)\n          | t `elem` \"diouxXc\"      = comma <+> expr <> format s p\n          where expr                = text \"fromB_int\" <> parens (gen env e) --parens (parens (gen env tInt) <> gen env e) <> text \"->val\"\n        conv (t:s) (PosArg e p)\n          | t `elem` \"eEfFgG\"       = comma <+> expr <> format s p\n          where expr                = parens (parens (gen env tFloat) <> gen env e) <> text \"->val\"\n        conv (t:s) (PosArg e p)\n          | t `elem` \"rsa\"          = comma <+> expr <> format s p\n          where expr                = parens (parens (gen env tStr) <> gen env e) <> text \"->str\"\n        conv ('%':s) p              = format s p\n\ngenCall env [] (TApp _ e ts) p      = genCall env ts e p\ngenCall env [_,t] (Var _ n) (PosArg e PosNil)\n  | n == primCAST                   = parens (parens (genTypeDecl env (noq n) t) <> gen env e)\ngenCall env [row] (Var _ n) (PosArg s@Strings{} (PosArg tup PosNil))\n  | n == primFORMAT                 = gen env n <> parens (genStr env (formatLit s) <> castLit env s (flatten tup))\n  where unbox (TNil _ _) p          = empty\n        unbox (TRow _  _ _ t r) (PosArg e p)\n          | t == tStr               = comma <+> expr <> text \"->str\" <> unbox r p\n          | otherwise               = comma <+> expr <> text \"->val\" <> unbox r p\n          where expr                = parens (parens (gen env t) <> gen env e)\n        flatten (Tuple _ p KwdNil)  = p\n        flatten e                   = foldr PosArg PosNil $ map (DotI l0 e) [0..]\ngenCall env [t] (Var _ n) PosNil\n  | n == primNEWACTOR               = gen env n <> parens (gen env t)\n-- Only install GCfinalizer if one is defined, i.e. we don't have the default\n-- $ActorD___cleanup__\n-- TODO: would be even better to determine this in the compiler and not emit\n-- this line rather than inspect the method table at run time\ngenCall env [TCon _ tc] (Var _ n) p\n  | n == primInstallFinalizer       = text \"if\" <+> parens (text \"(void*)\" <> gen env p <> text \"->\" <> gen env classKW <> text \"->\" <> gen env cleanupKW <+> text \"!= (void*)$ActorD___cleanup__\") <+> gen env n <> parens (gen env p <> comma <+> genTopName env (methodname (noq $ tcname tc) attr_finalizer))\ngenCall env ts e@(Var _ n) p\n  | NClass{} <- info                = genNew env n p\n  | NDef{} <- info                  = (instCast env ts e $ gen env e) <> parens (gen env p)\n  where info                        = findQName n env\ngenCall env ts (Async _ e) p        = genCall env ts e p\ngenCall env ts e0@(Dot _ e n) p     = genDotCall env ts (snd $ schemaOf env e0) e n p\ngenCall env ts e p                  = gen env e <> parens (gen env p)\n\ninstCast env [] e                   = id\ninstCast env ts e@(Var _ x)\n  | x == primUGetItem               = case typeInstOf env ts e of\n                                         TFun _ fx (TRow _ _ _ t1 (TRow _ _ _ t2 _)) _ r ->\n                                             parens . (parens (gen env r <+> parens (char '*') <+> parens (gen env t1 <> comma <+> text (unboxed_c_type t2))) <>)\n                                         t -> error(\"Interal error: unexpected typecast for list indexing\")\n  | GName m _ <- x, m == mPrim      = id\ninstCast env ts e                   = parens . (parens (gen env t) <>)\n  where t                           = typeInstOf env ts e  \n\ntargetType env (Dot _ e n)          = sctype sc\n  where t0                          = typeOf env e\n        (_,c0)                      = case t0 of\n                                         TCon _ tc -> splitTC env tc\n                                         TVar _ tv -> splitTC env (findTVBound env tv)\n        (sc, dec)                   = findAttr' env c0 n\ntargetType env e                    = typeOf env e                  -- Must be a Var with a monomorphic type since it is assignable\n\ndotCast env ent ts (Var _ x) n\n  | GName m _ <- x, m == mPrim      = id\ndotCast env ent ts e n\n  | gen_t == gen env t1             = id\n  | otherwise                       = parens . (parens gen_t <>)\n  where t0                          = typeOf env e\n        (argsubst, c0)              = case t0 of\n                                         TCon _ tc -> splitTC env tc\n                                         TVar _ tv -> splitTC env (findTVBound env tv)\n                                         TTuple{}  -> ([], cValue)\n        (sc, dec)                   = findAttr' env c0 n\n        t                           = vsubst fullsubst $ if ent then addSelf t1 dec else t1\n        t1                          = exposeMsg' (sctype sc)\n        fullsubst                   = (tvSelf,t0) : (qbound (scbind sc) `zip` ts) ++ argsubst\n        gen_t                       = gen env t\n\nclassCast env ts x q n              = parens . (parens (gen env t) <>)\n  where (ts0,ts1)                   = splitAt (length q) ts\n        tc                          = TC x ts0\n        (sc, dec)                   = findAttr' env tc n\n        t                           = vsubst fullsubst $ addSelf (sctype sc) dec\n        fullsubst                   = (tvSelf,tCon tc) : (qbound (scbind sc) `zip` ts1)\n\ngenNew env n p                      = newcon' env n <> parens (gen env p)\n\ndeclCon env n q b\n  | null abstr || hasNotImpl b      = (gen env tRes <+> newcon env n <> parens (gen env pars) <+> char '{') $+$\n                                      nest 4 (gen env tObj <+> gen env tmpV <+> equals <+> acton_malloc env (gname env n) <> semi $+$\n                                              gen env tmpV <> text \"->\" <> gen env1 classKW <+> equals <+> char '&' <> methodtable env1 n <> semi $+$\n                                              altcall $+$\n                                              initcall) $+$\n                                      char '}'\n  | otherwise                       = empty\n  where TFun _ fx r _ t             = sctype $ fst $ schemaOf env (eVar n)\n        tc                          = TC (NoQ n) (map tVar $ qbound q)\n        tObj                        = tCon tc\n        tRes                        = if t == tR then tR else tObj\n        pars                        = pPar paramNames r\n        args                        = pArg pars\n        altcall\n          | Just (_,sc,_) <- alt    = let i = arity $ posrow $ sctype sc\n                                          args' = pArg (chop i pars)\n                                      in methodtable env n <> dot <> gen env altInit <> parens (gen env1 tmpV <> comma' (gen env1 args')) <> semi\n          | otherwise               = empty\n          where alt                 = findAttr env tc altInit\n        initcall\n          | t == tR                 = text \"return\" <+> methodtable env n <> dot <> gen env initKW <> parens (gen env1 tmpV <> comma <+> gen env1 (retobj args)) <> semi\n          | otherwise               = methodtable env n <> dot <> gen env initKW <> parens (gen env1 tmpV <> comma' (gen env1 args)) <> semi $+$\n                                      text \"return\" <+> gen env tmpV <> semi\n        retobj (PosArg e p)         = PosArg (eCall (tApp (eQVar primCONSTCONT) [tObj]) [eVar tmpV, e]) p\n        env1                        = ldefine ((tmpV, NVar tObj) : envOf pars) env\n        abstr                       = abstractAttrs env (NoQ n)\n\nacton_malloc env n                  = text \"acton_malloc\" <> parens (text \"sizeof\" <> parens (text \"struct\" <+> gen env n))\n\ncomma' x                            = if isEmpty x then empty else comma <+> x\n\ngenDotCall env ts dec e@(Var _ x) n p\n  | NClass q _ _ _ <- info,\n    Just _ <- dec                   = classCast env ts x q n (methodtable' env x <> text \".\" <> gen env n) <> parens (gen env p)\n  where info                        = findQName x env\ngenDotCall env ts dec e n p\n  | Just NoDec <- dec               = genEnter env ts e n p\n  | Just Static <- dec              = dotCast env False ts e n (gen env e <> text \"->\" <> gen env classKW <> text \"->\" <> gen env n) <> parens (gen env p)\n\n\ngenDot env ts e@(Var _ x) n\n  | NClass q _ _ _ <- findQName x env = classCast env ts x q n $ methodtable' env x <> text \".\" <> gen env n\ngenDot env ts e n                   = dotCast env False ts e n $ gen env e <> text \"->\" <> gen env n\n-- NOTE: all method references are eta-expanded by the lambda-lifter at this point, so n cannot be a method (i.e., require methodtable lookup) here\n\ngenTarget env (Dot _ e n)           = gen env e <> text \"->\" <> gen env n\ngenTarget env e                     = gen env e\n\n\ngenEnter env ts e n p\n  | costly e                        = parens (lbrace <+> (gen env t <+> gen env tmpV <+> equals <+> gen env e <> semi $+$\n                                                          genEnter env1 ts (eVar tmpV) n p <> semi) <+> rbrace)\n  where costly Var{}                = False\n        costly (Dot _ e n)          = costly e\n        costly (DotI _ e i)         = costly e\n        costly e                    = True\n        t                           = typeOf env e\n        env1                        = ldefine [(tmpV,NVar t)] env\ngenEnter env ts e n p               = dotCast env True ts e n (gen env e <> text \"->\" <> gen env classKW <> text \"->\" <> gen env n) <> parens (gen env e <> comma' (gen env p))\n\ngenInst env ts e@Var{}              = instCast env ts e $ gen env e\ngenInst env ts (Dot _ e n)          = genDot env ts e n\n\nadjust t t' e\n  | t == t'                         = e\nadjust (TOpt _ t) t' e              = adjust t t' e\nadjust t (TOpt _ t') e              = adjust t t' e\nadjust TNone{} t' e                 = e\nadjust t t'@TVar{} e                = e\nadjust (TCon _ c) (TCon _ c') e\n  | tcname c == tcname c'           = e\nadjust t t' e\n   | B.isUnboxable t'               = e\n   | otherwise                      = typecast t t' e\n\ngenExp env t' e                     = gen env (adjust t t' e')\n  where (t, fx, e')                 = qType env adjust e\n\ngenExp' env e                       = gen env e'\n  where (t, fx, e')                 = qType env adjust e\n\ninstance Gen Expr where\n    gen env (Var _ n)\n      | NClass{} <- findQName n env = newcon' env n\n      | otherwise                   = genQName env n\n    gen env (Int _ i str)\n        | i < 0                     = gen env primToBigInt2 <> parens (doubleQuotes $ text str)       -- negative → string\n        | i <= 9223372036854775807  = gen env primToBigInt  <> parens (text (str++\"UL\"))             -- fits i64 → toB_bigint\n        | i <= 18446744073709551615 = gen env primToU64     <> parens (text (str++\"UL\"))             -- fits u64  → toB_u64\n        | otherwise                 = gen env primToBigInt2 <> parens (doubleQuotes $ text str)       -- large → string\n    gen env (Float _ _ str)         = gen env primToFloat <> parens (text str)\n    gen env (Bool _ True)           = gen env qnTrue\n    gen env (Bool _ False)          = gen env qnFalse\n    gen env (None _)                = gen env qnNone\n    gen env e@Strings{}             = gen env primToStr <> parens(hsep (map pretty (sval e)))\n    gen env e@BStrings{}            = gen env primToBytes <> parens( hsep (map pretty es) <> comma <+>text(show(length(read(concat es) :: String))))\n      where es                      = sval e\n    gen env (Call l  (TApp _ e@(Var _ mk) _) p@(PosArg w (PosArg (Set _ es) PosNil)) KwdNil)\n      | mk == primMkSet             = text \"B_mk_set\" <> parens (pretty (length es) <> comma <+> gen env w <> hsep [comma <+> gen env e | e <- es])\n    gen env (Call l  (TApp _ e@(Var _ mk) _) p@(PosArg w (PosArg (Dict _ es) PosNil)) KwdNil)\n      | mk == primMkDict            = text \"B_mk_dict\" <> parens (pretty (length es) <> comma <+> gen env w <>  hsep [comma <+> gen env e | e <- es])\n    gen env c@(Call _ e p _)        = genCall env [] e p\n    gen env (Async _ e)             = gen env e\n    gen env (TApp _ e ts)           = genInst env ts e\n    gen env (Let _ ss e)            = text \"({\" <+> fst(genSuite env ss) $+$ gen (ldefine (envOf ss) env) e <> text \";})\"\n    gen env (IsInstance _ e c)      = gen env primISINSTANCE <> parens (gen env e <> comma <+> genQName env c)\n    gen env (Dot _ e n)             = genDot env [] e n\n    gen env e0@(DotI _ e i)         = parens $ parens (gen env t) <> gen env e <> text \"->\" <> gen env componentsKW <> brackets (pretty i)\n      where t                       = typeOf env e0\n    gen env (RestI _ e i)           = gen env eNone <> semi <+> text \"// CodeGen for tuple tail not implemented\"\n    gen env (Tuple _ p KwdNil)\n       | n == 0                     = gen env primNEWTUPLE0\n       | otherwise                  = gen env primNEWTUPLE <> parens (text (show n) <> comma' (gen env p))\n       where n                      = nargs p\n    gen env (List _ es)             = text \"B_mk_list\" <> parens (pretty (length es) <> hsep [comma <+> gen env e | e <- es])\n    gen env (BinOp _ e1 And e2)     = gen env primAND <> parens (gen env t <> comma <+> gen env e1 <> comma <+> gen env e2)\n      where t                       = typeOf env e1\n    gen env (BinOp _ e1 Or e2)      = gen env primOR <> parens (gen env t <> comma <+> gen env e1 <> comma <+> gen env e2)\n      where t                       = typeOf env e1\n    gen env (BinOp _ e1 op e2)\n            | op == Div && t /= tFloat\n             || op `elem` [Pow, Mod, EuDiv]     -- Pow since there is no C operator, the others since they need to check for division by zero\n                                    = gencFunCall env (tstr ++ '_' : opstr op) [e1, e2]\n            | otherwise             = gen env e1 <+> binPretty op <+> gen env e2\n      where t                       = typeOf env e1\n            tstr                    = nstr (noq (tcname (tcon t)))\n            opstr Pow               = \"pow\"\n            opstr Div               = \"DIV\"\n            opstr Mod               = \"MOD\"\n            opstr EuDiv             = \"FLOORDIV\"\n    gen env (CompOp _ e [a])        = gen env e <+> gen env a\n    gen env (UnOp _ Not e)          = gen env primNOT <> parens (gen env t <> comma <+> gen env e)\n      where t                       = typeOf env e\n    gen env (Cond _ e1 e e2)        = parens (parens (gen env (B.unbox tBool e)) <+> text \"?\" <+> gen env e1 <+> text \":\" <+> gen env e2)\n    gen env (Paren _ e)             = parens (gen env e)\n    gen env (Box t e)               = text (\"toB_\"++render(pretty (noq (tcname(tcon t))))) <> parens (gen env e)\n    gen env (UnBox _ e@(Call _ (Var _ f) p KwdNil))\n        | f == primISNOTNONE        = genCall env [] (Var NoLoc primISNOTNONE0) p\n        | f == primISNONE           = genCall env [] (Var NoLoc primISNONE0) p\n        | f `elem` [primPUSH,primPUSHF]\n                                    = gen env f <> parens(empty)\n        | f `elem` B.mathfuns       = genCall env [] e p\n        | tCon (TC (gBuiltin (noq f)) []) `elem` B.integralTypes   -- f is the constructor for an integer type, so check if argument e is a literal\n                                    = genUnboxedInt env (posargs p) e\n    gen env (UnBox t e@(Call _ (Dot _ (Var _ w) op) (PosArg x (PosArg y PosNil)) KwdNil))  -- use macro for int (in)equality tests\n                                    = case findQName w env of\n                                        NVar (TCon _ (TC p [TCon _ (TC t [])]))\n                                          | (p==qnOrd || p==qnEq) &&  t == qnBigint ->\n                                             text \"ORD_\" <> tname <> text (nstr op) <> parens(parens (parens tname <> gen env x) <> comma <+> parens (parens tname <> gen env y))\n                                        _ ->  parens (parens (gen env t) <> gen env e) <> text \"->val\"\n      where tname                   = genQName env qnBigint \n\n    gen env (UnBox _ (IsInstance _ e c))\n                                    = gen env primISINSTANCE0 <> parens(gen env e <> comma <+> genQName env c)\n    gen env (UnBox t (Int _ n s))   = text (s++ suffix t)\n       where suffix t\n               | t == tInt          = \"LL\"\n               | t == tU64          = \"UL\"\n               | otherwise          = \"\"\n             \n    gen env (UnBox _ (Float _ x s)) = text s\n    gen env (UnBox _ (Bool _ b))    = if b then text \"true\" else text \"false\"\n    gen env (UnBox _ v@(Var _ (NoQ n)))\n       | isUnboxed n                = gen env v\n    gen env (UnBox t e)             = parens (parens (gen env t) <> gen env e) <> text \"->val\"\n--    gen env (UnBox t e)             = parens (gen env e) <> text \"->val\"\n    gen env e                       = error (\"CodeGen.gen for Expr: e = \" ++ show e)\n\ngencFunCall env nm []               = text nm <> parens empty\ngencFunCall env nm (x : xs)         = text nm <> parens (gen env x <> hsep [ comma <+> gen env x | x <- xs ])\n\ngenUnboxedInt env [Int _ n s, None _] _\n                                    = text s\ngenUnboxedInt env _ c               = parens (gen env c) <> text \"->val\"\n\ninstance Gen OpArg where\n    gen env (OpArg  op e)           = compPretty op <+> gen env e\n\n-- compPretty Is                       = text \"==\"\n-- compPretty IsNot                    = text \"!=\"\ncompPretty op                       = pretty op\n\nbinPretty And                       = text \"&&\"\nbinPretty Or                        = text \"||\"\nbinPretty EuDiv                     = text \"/\"\nbinPretty op                        = pretty op\n\naugPretty EuDivA                    = text \"/=\"\naugPretty op                        = pretty op\n\ngenStr env s                        = text $ head $ sval s\n\ngenBool env e                       = genExp env tBool e\n  where t                           = typeOf env e\n\nnargs                               :: PosArg -> Int\nnargs PosNil                        = 0\nnargs (PosArg _ p)                  = 1 + nargs p\n\ninstance Gen Elem where\n    gen env (Elem e)                = gen env e\n\ninstance Gen Assoc where\n    gen env (Assoc e1 e2)           = gen env primNEWTUPLE <> parens (text \"2\" <> comma <+> gen env e1 <> comma <+> gen env e2)\n\ninstance Gen Pattern where\n    gen env (PVar _ n _)            = gen env n\n\ninstance Gen TSchema where\n    gen env (TSchema _ _ t)         = gen env t\n\ninstance Gen TVar where\n    gen env (TV k n)                = word\n\ninstance Gen TCon where\n    gen env (TC n ts)               = gen env (unalias env n)\n\ninstance Gen Type where\n    gen env (TVar _ v)              = gen env v\n    gen env (TCon  _ c)             = gen env c\n    gen env (TFun _ _ p _ t)        = gen env t <+> parens (char '*') <+> parens (gen env p)\n    gen env (TTuple _ pos _)        = gen env qnTuple\n    gen env (TOpt _ t)              = gen env t\n    gen env (TNone _)               = gen env qnNoneType\n    gen env (TWild _)               = word\n    gen env (TRow _ _ _ t TNil{})   = gen env t\n    gen env (TRow _ _ _ t r)        = gen env t <> comma <+> gen env r\n    gen env (TNil _ _)              = empty\n\nunboxed_c_type t\n    | t == tInt = \"int64_t\"\n    | t == tU64 = \"uint64_t\"\n    | t == tI32 = \"int32_t\"\n    | t == tU32 = \"uint32_t\"\n    | t == tI16 = \"int16_t\"\n    | t == tU16 = \"uint16_t\"\n    | t == tFloat = \"double\"\n    | otherwise = error (\"Internal error: trying to find unboxed type for \" ++ show t)\n"
  },
  {
    "path": "compiler/lib/src/Acton/CommandLineParser.hs",
    "content": "{-# LANGUAGE CPP #-}\nmodule Acton.CommandLineParser where\n\nimport Options.Applicative\nimport Data.Char (toLower)\nimport Data.Maybe (fromMaybe, isJust)\n\n#if defined(darwin_HOST_OS) && defined(aarch64_HOST_ARCH)\ndefTarget = \"aarch64-macos-none\"\n#elif defined(darwin_HOST_OS) && defined(x86_64_HOST_ARCH)\ndefTarget = \"x86_64-macos-none\"\n#elif defined(linux_HOST_OS) && defined(aarch64_HOST_ARCH)\ndefTarget = \"aarch64-linux-gnu.2.27\"\n#elif defined(linux_HOST_OS) && defined(x86_64_HOST_ARCH)\ndefTarget = \"x86_64-linux-gnu.2.27\"\n#else\n#error \"Unsupported platform\"\n#endif\n\nparseCmdLine        :: IO CmdLineOptions\nparseCmdLine        = execParser (info (cmdLineParser <**> helper) descr)\n\ndata CmdLineOptions = CompileOpt [String] GlobalOptions CompileOptions\n                    | CmdOpt GlobalOptions Command\n                    deriving Show\n\ndata ColorWhen = Auto | Always | Never deriving (Show, Eq)\n\ndata OptimizeMode = Debug | ReleaseSafe | ReleaseSmall | ReleaseFast deriving (Show, Eq)\n\ndata GlobalOptions = GlobalOptions {\n                        color        :: ColorWhen,\n                        quiet        :: Bool,\n                        noProgress   :: Bool,\n                        timing       :: Bool,\n                        tty          :: Bool,\n                        verbose      :: Bool,\n                        verboseZig   :: Bool,\n                        jobs         :: Int\n                     } deriving Show\n\ndata Command        = New NewOptions\n                    | Build BuildOptions\n                    | Install InstallOptions\n                    | Uninstall UninstallOptions\n                    | Sig SigOptions\n                    | Test TestCommand\n                    | Fetch\n                    | PkgShow\n                    | PkgAdd PkgAddOptions\n                    | PkgRemove PkgRemoveOptions\n                    | PkgUpgrade PkgUpgradeOptions\n                    | PkgUpdate\n                    | PkgSearch PkgSearchOptions\n                    | BuildSpecCmd BuildSpecCommand\n                    | Cloud CloudOptions\n                    | Doc DocOptions\n                    | ZigPkgAdd ZigPkgAddOptions\n                    | ZigPkgRemove ZigPkgRemoveOptions\n                    | Version\n                    deriving Show\n\n\ndata NewOptions     = NewOptions {\n                         file      :: String\n                    }  deriving Show\n\ndata CompileOptions   = CompileOptions {\n                         alwaysbuild :: Bool,\n                         ignore_compiler_version :: Bool,\n                         db          :: Bool,\n                         parse       :: Bool,\n                         parse_ast   :: Bool,\n                         kinds       :: Bool,\n                         types       :: Bool,\n                         sigs        :: Bool,\n                         norm        :: Bool,\n                         deact       :: Bool,\n                         cps         :: Bool,\n                         llift       :: Bool,\n                         box         :: Bool,\n                         hgen        :: Bool,\n                         cgen        :: Bool,\n                         ccmd        :: Bool,\n                         ty          :: Bool,\n                         cpedantic   :: Bool,\n                         dbg_no_lines:: Bool,\n                         optimize    :: OptimizeMode,\n                         only_build  :: Bool,\n                         skip_build  :: Bool,\n                         watch       :: Bool,\n                         no_threads  :: Bool,\n                         parse_serial :: Bool,\n                         root        :: String,\n                         tempdir     :: String,\n                         syspath     :: String,\n                         target      :: String,\n                         cpu         :: String,\n                         test        :: Bool,\n                         searchpath  :: [String],\n                         dep_overrides :: [(String,String)]\n                     } deriving Show\n\ndata BuildOptions = BuildOptions\n    { buildCompile :: CompileOptions\n    , buildFiles   :: [String]\n    } deriving Show\n\ndata InstallOptions = InstallOptions\n    { installName        :: String\n    , installRepoUrl     :: String\n    , installRepoRef     :: String\n    , installPkgName     :: String\n    , installGithubToken :: String\n    } deriving Show\n\ndata UninstallOptions = UninstallOptions\n    { uninstallName :: String\n    } deriving Show\n\ndata SigOptions = SigOptions\n    { sigCompile :: CompileOptions\n    , sigTarget  :: String\n    } deriving Show\n\n\n\ndata CloudOptions   = CloudOptions {\n                         run  :: Bool,\n                         list :: Bool,\n                         show :: Bool,\n                         stop :: Bool\n                    }  deriving Show\n\n\ndata DocOptions     = DocOptions {\n                         inputFile :: String,\n                         outputFormat :: Maybe DocFormat,\n                         outputFile :: Maybe String\n                    }  deriving Show\n\ndata DocFormat = AsciiFormat | MarkdownFormat | HtmlFormat deriving (Show, Eq)\n\ndata TestCommand\n    = TestRun TestOptions\n    | TestList TestOptions\n    | TestPerf TestOptions\n    | TestStress TestOptions\n    deriving Show\n\ndata TestOptions = TestOptions\n    { testCompile      :: CompileOptions\n    , testShowLog      :: Bool\n    , testShowCached   :: Bool\n    , testNoCache      :: Bool\n    , testJson         :: Bool\n    , testRecord       :: Bool\n    , testSnapshotUpdate :: Bool\n    , testIter         :: Int\n    , testMaxIter      :: Int\n    , testMinIter      :: Int\n    , testMaxTime      :: Int\n    , testMinTime      :: Int\n    , testStressWorkers :: Int\n    , testTags         :: [String]\n    , testMaxIterSet   :: Bool\n    , testMaxTimeSet   :: Bool\n    , testMinTimeSet   :: Bool\n    , testModules      :: [String]\n    , testNames        :: [String]\n    } deriving Show\n\ndata PkgAddOptions = PkgAddOptions\n    { pkgAddName     :: String\n    , pkgAddUrl      :: String\n    , pkgAddRepoUrl  :: String\n    , pkgAddRepoRef  :: String\n    , pkgAddPkgName  :: String\n    , pkgAddHash     :: String\n    , pkgAddGithubToken :: String\n    } deriving Show\n\ndata PkgRemoveOptions = PkgRemoveOptions\n    { pkgRemoveName :: String\n    } deriving Show\n\ndata PkgUpgradeOptions = PkgUpgradeOptions\n    { pkgUpgradeGithubToken :: String\n    } deriving Show\n\ndata PkgSearchOptions = PkgSearchOptions\n    { pkgSearchTerms :: [String]\n    } deriving Show\n\ndata ZigPkgAddOptions = ZigPkgAddOptions\n    { zigPkgAddUrl       :: String\n    , zigPkgAddName      :: String\n    , zigPkgAddArtifacts :: [String]\n    } deriving Show\n\ndata ZigPkgRemoveOptions = ZigPkgRemoveOptions\n    { zigPkgRemoveName :: String\n    } deriving Show\n\n--------------------------------------------------------------------\n-- Internal stuff\n\ncmdLineParser       :: Parser CmdLineOptions\ncmdLineParser       = hsubparser\n                        (  command \"new\"     (info (CmdOpt <$> globalOptions <*> (New <$> newOptions)) (progDesc \"Create a new Acton project\"))\n                        <> command \"build\"   (info (CmdOpt <$> globalOptions <*> (Build <$> buildOptions)) (progDesc \"Build an Acton project\"))\n                        <> command \"install\" (info (CmdOpt <$> globalOptions <*> (Install <$> installOptions)) (progDesc \"Install an Acton application package\"))\n                        <> command \"uninstall\" (info (CmdOpt <$> globalOptions <*> (Uninstall <$> uninstallOptions)) (progDesc \"Uninstall an Acton application package\"))\n                        <> command \"sig\"     (info (CmdOpt <$> globalOptions <*> (Sig <$> sigOptions)) (progDesc \"Show inferred type signatures\"))\n                        <> command \"test\"    (info (CmdOpt <$> globalOptions <*> (Test <$> testCommand)) (progDesc \"Build and run project tests\"))\n                        <> command \"fetch\"   (info (CmdOpt <$> globalOptions <*> pure Fetch) (progDesc \"Fetch project dependencies (offline prep)\"))\n                        <> command \"pkg\"     (info (CmdOpt <$> globalOptions <*> pkgSubcommands) (progDesc \"Library package/dependency commands\"))\n                        <> command \"zig-pkg\" (info (CmdOpt <$> globalOptions <*> zigPkgSubcommands) (progDesc \"Zig package dependency commands\"))\n                        <> command \"spec\"    (info (CmdOpt <$> globalOptions <*> (BuildSpecCmd <$> buildSpecCommand)) (progDesc \"Inspect or update build specification\"))\n                        <> command \"cloud\"   (info (CmdOpt <$> globalOptions <*> (Cloud <$> cloudOptions)) (progDesc \"Run an Acton project in the cloud\"))\n                        <> command \"doc\"     (info (CmdOpt <$> globalOptions <*> (Doc <$> docOptions)) (progDesc \"Show type and docstring info\"))\n                        <> command \"version\" (info (CmdOpt <$> globalOptions <*> pure Version) (progDesc \"Show version\"))\n                      )\n                     <|> (CompileOpt <$> (fmap (:[]) $ argument str (metavar \"ACTONFILE\" <> help \"Compile Acton file\" <> completer (bashCompleter \"file -X '!*.act' -o plusdirs\"))) <*> globalOptions <*> compileOptions)\n\nglobalOptions :: Parser GlobalOptions\nglobalOptions = GlobalOptions\n    <$> option colorReader\n        (long \"color\"\n         <> metavar \"WHEN\"\n         <> value Auto\n         <> help \"Use colored output (WHEN: auto, always, never)\"\n        )\n    <*> switch (long \"quiet\"       <> help \"Don't print stuff\")\n    <*> switch (long \"no-progress\" <> help \"Disable live progress UI\")\n    <*> switch (long \"timing\"      <> help \"Print timing information\")\n    <*> switch (long \"tty\"         <> help \"Act as if run from interactive TTY\")\n    <*> switch (long \"verbose\"     <> help \"Verbose output\")\n    <*> switch (long \"verbose-zig\" <> help \"Verbose Zig output\")\n    <*> option auto (long \"jobs\"   <> metavar \"N\" <> value 0 <> help \"Max parallel compiler jobs (0 = auto)\")\n  where\n    colorReader :: ReadM ColorWhen\n    colorReader = eitherReader $ \\s ->\n        case s of\n            \"auto\"   -> Right Auto\n            \"always\" -> Right Always\n            \"never\"  -> Right Never\n            _        -> Left $ \"Invalid color option: \" ++ s ++ \" (expected: auto, always, never)\"\n\noptimizeReader :: ReadM OptimizeMode\noptimizeReader = eitherReader $ \\s ->\n    case map toLower s of\n        \"debug\"        -> Right Debug\n        \"release\"      -> Right ReleaseFast\n        \"releasesafe\"  -> Right ReleaseSafe\n        \"releasesmall\" -> Right ReleaseSmall\n        \"releasefast\"  -> Right ReleaseFast\n        _              -> Left $ \"Invalid optimize option: \" ++ s ++ \" (expected: Debug, Release, ReleaseSafe, ReleaseSmall, ReleaseFast)\"\n\nreleaseModeReader :: ReadM OptimizeMode\nreleaseModeReader = eitherReader $ \\s ->\n    case map toLower s of\n        \"safe\"  -> Right ReleaseSafe\n        \"small\" -> Right ReleaseSmall\n        \"fast\"  -> Right ReleaseFast\n        _       -> Left $ \"Invalid release option: \" ++ s ++ \" (expected: safe, small, fast)\"\n\n\n{-\ngeneralOptions         = GeneralOptions <$>\n                             strOption (long \"tempdir\" <> metavar \"TEMPDIR\" <> value \"\" <> help \"Set temporary directory for build files\")\n                         <*> strOption (long \"syspath\" <> metavar \"TARGETDIR\" <>  value \"\" <> help \"Set syspath\")\n                         <*> switch (long \"dev\"        <> help \"Development mode; include debug symbols etc\")\n -}\n\nnewOptions = NewOptions <$> argument (str :: ReadM String) (metavar \"PROJECTDIR\")\n\nbuildOptions :: Parser BuildOptions\nbuildOptions = BuildOptions\n        <$> compileOptions\n        <*> many (argument str (metavar \"ACTONFILE\" <> help \"Specific .act file(s) to build\"))\n\ninstallOptions :: Parser InstallOptions\ninstallOptions = InstallOptions\n    <$> argument str (metavar \"NAME\" <> help \"Name of application package\")\n    <*> strOption (long \"repo-url\" <> metavar \"URL\" <> value \"\" <> help \"Git repository URL of application package\")\n    <*> strOption (long \"repo-ref\" <> metavar \"REF\" <> value \"\" <> help \"Git ref (branch, tag or SHA) to use\")\n    <*> strOption (long \"pkg-name\" <> metavar \"NAME\" <> value \"\" <> help \"Package name in index (defaults to NAME)\")\n    <*> githubTokenOption\n\nuninstallOptions :: Parser UninstallOptions\nuninstallOptions =\n    UninstallOptions <$> argument str (metavar \"NAME\" <> help \"Name of application package\")\n\nsigOptions :: Parser SigOptions\nsigOptions = SigOptions\n        <$> sigCompileOptions\n        <*> argument str (metavar \"TARGET\" <> help \"Module or module.name to show, e.g. foo.bar\")\n\nsigCompileOptions :: Parser CompileOptions\nsigCompileOptions = mkSigCompileOptions\n        <$> switch (long \"always-build\" <> help \"Recompute signatures instead of reusing fresh cached interfaces\")\n        <*> switch (long \"ignore-compiler-version\" <> help \"Ignore acton version when checking .ty freshness\")\n        <*> strOption (long \"syspath\"   <> metavar \"TARGETDIR\" <> value \"\" <> help \"Set syspath\")\n        <*> many (strOption (long \"searchpath\" <> metavar \"DIR\" <> help \"Add search path\"))\n        <*> many (option depOverrideReader\n               (long \"dep\"\n                <> metavar \"NAME=PATH\"\n                <> help \"Override dependency NAME with local PATH\"))\n  where\n    mkSigCompileOptions always ignore syspath' search depOverrides =\n      CompileOptions\n        { alwaysbuild = always\n        , ignore_compiler_version = ignore\n        , db = False\n        , parse = False\n        , parse_ast = False\n        , kinds = False\n        , types = False\n        , sigs = False\n        , norm = False\n        , deact = False\n        , cps = False\n        , llift = False\n        , box = False\n        , hgen = False\n        , cgen = False\n        , ccmd = False\n        , ty = False\n        , cpedantic = False\n        , dbg_no_lines = False\n        , optimize = Debug\n        , only_build = False\n        , skip_build = True\n        , watch = False\n        , no_threads = False\n        , parse_serial = False\n        , root = \"\"\n        , tempdir = \"\"\n        , syspath = syspath'\n        , target = defTarget\n        , cpu = \"\"\n        , test = False\n        , searchpath = search\n        , dep_overrides = depOverrides\n        }\n\ncompileOptions = CompileOptions\n        <$> switch (long \"always-build\" <> help \"Show the result of parsing\")\n        <*> switch (long \"ignore-compiler-version\" <> help \"Ignore acton version when checking .ty freshness\")\n        <*> switch (long \"db\"           <> help \"Enable DB backend\")\n        <*> switch (long \"parse\"        <> help \"Show the result of parsing\")\n        <*> switch (long \"parse-ast\"    <> help \"Show the raw AST (Haskell Show)\")\n        <*> switch (long \"kinds\"        <> help \"Show all the result after kind-checking\")\n        <*> switch (long \"types\"        <> help \"Show all inferred expression types\")\n        <*> switch (long \"sigs\"         <> help \"Show the inferred type signatures\")\n        <*> switch (long \"norm\"         <> help \"Show the result after syntactic normalization\")\n        <*> switch (long \"deact\"        <> help \"Show the result after deactorization\")\n        <*> switch (long \"cps\"          <> help \"Show the result after CPS conversion\")\n        <*> switch (long \"llift\"        <> help \"Show the result of lambda-lifting\")\n        <*> switch (long \"box\"          <> help \"Show the result of (un)boxing\")\n        <*> switch (long \"hgen\"         <> help \"Show the generated .h header\")\n        <*> switch (long \"cgen\"         <> help \"Show the generated .c code\")\n        <*> switch (long \"ccmd\"         <> help \"Show CC / LD commands\")\n        <*> switch (long \"ty\"           <> help \"Write .ty file to src file directory\")\n        <*> switch (long \"cpedantic\"    <> help \"Pedantic C compilation with -Werror\")\n        <*> switch (long \"dbg-no-lines\" <> help \"Disable emission of C #line directives (for debugging codegen)\")\n        <*> optimizeOption\n        <*> switch (long \"only-build\"   <> help \"Only perform final build of .c files, do not compile .act files\")\n        <*> switch (long \"skip-build\"   <> help \"Skip final bulid of .c files\")\n        <*> switch (long \"watch\"        <> help \"Rebuild on file changes\")\n        <*> switch (long \"no-threads\"   <> help \"Don't use threads\")\n        <*> switch (long \"parse-serial\" <> help \"Use the serial whole-file parser\")\n        <*> strOption (long \"root\"      <> metavar \"ROOTACTOR\" <> value \"\" <> help \"Set root actor\")\n        <*> strOption (long \"tempdir\"   <> metavar \"TEMPDIR\" <> value \"\" <> help \"Set directory for build files\")\n        <*> strOption (long \"syspath\"   <> metavar \"TARGETDIR\" <> value \"\" <> help \"Set syspath\")\n        <*> strOption (long \"target\"    <> metavar \"TARGET\" <> value defTarget <> help \"Target, e.g. x86_64-linux-gnu.2.28\")\n        <*> strOption (long \"cpu\"       <> metavar \"CPU\" <> value \"\" <> help \"CPU, e.g. skylake\")\n        <*> switch (long \"test\"         <> help \"Build tests\")\n        <*> many (strOption (long \"searchpath\" <> metavar \"DIR\" <> help \"Add search path\"))\n        <*> many (option depOverrideReader\n               (long \"dep\"\n                <> metavar \"NAME=PATH\"\n                <> help \"Override dependency NAME with local PATH\"))\n\npkgSubcommands :: Parser Command\npkgSubcommands = hsubparser\n  (  command \"show\"    (info (pure PkgShow) (progDesc \"Show dependency tree with overrides\"))\n  <> command \"add\"     (info (PkgAdd <$> pkgAddOptions) (progDesc \"Add library package dependency\"))\n  <> command \"remove\"  (info (PkgRemove <$> pkgRemoveOptions) (progDesc \"Remove library package dependency\"))\n  <> command \"upgrade\" (info (PkgUpgrade <$> pkgUpgradeOptions) (progDesc \"Upgrade (or downgrade) library package dependency\"))\n  <> command \"update\"  (info (pure PkgUpdate) (progDesc \"Update package index\"))\n  <> command \"search\"  (info (PkgSearch <$> pkgSearchOptions) (progDesc \"Search library package index\"))\n  )\n\ngithubTokenOption :: Parser String\ngithubTokenOption =\n    strOption\n      (  long \"github-token\"\n      <> metavar \"TOKEN\"\n      <> value \"\"\n      <> help \"GitHub token for API requests (env: GITHUB_TOKEN)\"\n      )\n\npkgAddOptions :: Parser PkgAddOptions\npkgAddOptions = PkgAddOptions\n    <$> argument str (metavar \"NAME\" <> help \"Name of dependency\")\n    <*> strOption (long \"url\" <> metavar \"URL\" <> value \"\" <> help \"URL of dependency\")\n    <*> strOption (long \"repo-url\" <> metavar \"URL\" <> value \"\" <> help \"Git repository URL of dependency\")\n    <*> strOption (long \"repo-ref\" <> metavar \"REF\" <> value \"\" <> help \"Git ref (branch, tag or SHA) to use\")\n    <*> strOption (long \"pkg-name\" <> metavar \"NAME\" <> value \"\" <> help \"Package name in index (defaults to NAME)\")\n    <*> strOption (long \"hash\" <> metavar \"HASH\" <> value \"\" <> help \"Hash of dependency\")\n    <*> githubTokenOption\n\npkgRemoveOptions :: Parser PkgRemoveOptions\npkgRemoveOptions =\n    PkgRemoveOptions <$> argument str (metavar \"NAME\" <> help \"Name of dependency\")\n\npkgUpgradeOptions :: Parser PkgUpgradeOptions\npkgUpgradeOptions =\n    PkgUpgradeOptions <$> githubTokenOption\n\npkgSearchOptions :: Parser PkgSearchOptions\npkgSearchOptions =\n    PkgSearchOptions <$> many (argument str (metavar \"TERM\" <> help \"Search term (regex, ANDed)\"))\n\nzigPkgSubcommands :: Parser Command\nzigPkgSubcommands = hsubparser\n  (  command \"add\"    (info (ZigPkgAdd <$> zigPkgAddOptions) (progDesc \"Add Zig package dependency\"))\n  <> command \"remove\" (info (ZigPkgRemove <$> zigPkgRemoveOptions) (progDesc \"Remove Zig package dependency\"))\n  )\n\nzigPkgAddOptions :: Parser ZigPkgAddOptions\nzigPkgAddOptions = ZigPkgAddOptions\n    <$> argument str (metavar \"URL\" <> help \"URL of dependency\")\n    <*> argument str (metavar \"NAME\" <> help \"Name of dependency\")\n    <*> many (strOption (long \"artifact\" <> metavar \"NAME\" <> help \"Library artifact to link with\"))\n\nzigPkgRemoveOptions :: Parser ZigPkgRemoveOptions\nzigPkgRemoveOptions =\n    ZigPkgRemoveOptions <$> argument str (metavar \"NAME\" <> help \"Name of dependency\")\n\ncloudOptions = CloudOptions\n        <$> switch (long \"run\"          <> help \"Help run!\")\n        <*> switch (long \"list\"         <> help \"Help list!\")\n        <*> switch (long \"show\"         <> help \"Help show!\")\n        <*> switch (long \"stop\"         <> help \"Help stop!\")\n\ndocOptions = DocOptions\n    <$> (argument str (metavar \"FILE\" <> help \"Input file (.act or .ty) - optional in projects\" <> completer (bashCompleter \"file -X '!*.act' -X '!*.ty' -o plusdirs\")) <|> pure \"\")\n    <*> formatFlags\n    <*> optional (strOption (long \"output\" <> short 'o' <> metavar \"FILE\" <> help \"Output file (default: stdout)\"))\n  where\n    -- Parse format flags - simple and explicit\n    formatFlags = optional (\n              flag' AsciiFormat (long \"terminal\" <> short 't' <> help \"Terminal output (ASCII format)\")\n          <|> flag' MarkdownFormat (long \"md\" <> long \"markdown\" <> help \"Output in Markdown format\")\n          <|> flag' HtmlFormat (long \"html\" <> help \"Output in HTML format\")\n        )\n\noptimizeOption :: Parser OptimizeMode\noptimizeOption = resolveOptimizeOption\n    <$> optional releaseOption\n    <*> optional\n        (option optimizeReader\n            (long \"optimize\"\n             <> metavar \"MODE\"\n             <> help \"Optimization mode (case-insensitive: Debug, Release/ReleaseFast, ReleaseSafe, ReleaseSmall)\"\n            ))\n  where\n    releaseOption =\n        flag' ReleaseFast\n            (long \"release\"\n             <> help \"Release build mode; same as --release=fast and also accepts =safe or =small\"\n            )\n        <|> option releaseModeReader\n            (long \"release\"\n             <> internal\n            )\n\n    resolveOptimizeOption _ (Just mode) = mode\n    resolveOptimizeOption (Just mode) _ = mode\n    resolveOptimizeOption Nothing Nothing = Debug\n\ndata TestModeTag = ModeList | ModePerf | ModeStress deriving Show\n\ntestCommand :: Parser TestCommand\ntestCommand =\n    toCmd\n      <$> optional (argument testModeReader (metavar \"MODE\" <> help \"list | perf | stress\"))\n      <*> testOptions\n  where\n    toCmd mMode opts =\n      case mMode of\n        Just ModeList -> TestList opts\n        Just ModePerf -> TestPerf opts\n        Just ModeStress -> TestStress opts\n        Nothing -> TestRun opts\n\ntestModeReader :: ReadM TestModeTag\ntestModeReader = eitherReader $ \\s ->\n    case s of\n      \"list\" -> Right ModeList\n      \"perf\" -> Right ModePerf\n      \"stress\" -> Right ModeStress\n      _      -> Left \"Expected 'list', 'perf' or 'stress'\"\n\ntestOptions :: Parser TestOptions\ntestOptions = mkTestOptions\n    <$> compileOptions\n    <*> switch (long \"show-log\"      <> help \"Show test log output\")\n    <*> switch (long \"show-cached\"   <> help \"Show cached test results\")\n    <*> switch (long \"no-cache\"      <> help \"Always run tests instead of reusing cached results\")\n    <*> switch (long \"json\"          <> help \"Output final test results as JSON\")\n    <*> switch (long \"record\"        <> help \"Record test performance results\")\n    <*> switch (long \"snapshot-update\" <> long \"golden-update\" <> long \"accept\" <> help \"Accept current test output as expected snapshot values\")\n    <*> option auto (long \"iter\"     <> metavar \"N\" <> value (-1) <> help \"Number of iterations to run a test\")\n    <*> optional (option auto (long \"max-iter\" <> metavar \"N\" <> help \"Maximum number of iterations to run a test (mode defaults when omitted)\"))\n    <*> option auto (long \"min-iter\" <> metavar \"N\" <> value 3 <> help \"Minimum number of iterations to run a test\")\n    <*> optional (option auto (long \"max-time\" <> metavar \"MS\" <> help \"Maximum time to run a test in milliseconds (0 = no time limit, mode defaults when omitted)\"))\n    <*> optional (option auto (long \"min-time\" <> metavar \"MS\" <> help \"Minimum time to run a test in milliseconds\"))\n    <*> option auto (long \"stress-workers\" <> metavar \"N\" <> value 0 <> help \"Concurrent stress workers to run in stress mode (0 = auto)\")\n    <*> many (strOption (long \"tag\" <> metavar \"TAG\" <> help \"Enable test capability TAG for testing.require()\"))\n    <*> many (strOption (long \"module\" <> metavar \"MODULE\" <> help \"Filter on test module name\"))\n    <*> many (strOption (long \"name\" <> metavar \"NAME\" <> help \"Filter on test name (regex, anchored; use .* for substrings)\"))\n  where\n    mkTestOptions testCompile testShowLog testShowCached testNoCache testJson testRecord testSnapshotUpdate testIter testMaxIterOpt testMinIter testMaxTimeOpt testMinTimeOpt testStressWorkers testTags testModules testNames =\n      TestOptions\n        { testCompile = testCompile\n        , testShowLog = testShowLog\n        , testShowCached = testShowCached\n        , testNoCache = testNoCache\n        , testJson = testJson\n        , testRecord = testRecord\n        , testSnapshotUpdate = testSnapshotUpdate\n        , testIter = testIter\n        , testMaxIter = fromMaybe (10^6) testMaxIterOpt\n        , testMinIter = testMinIter\n        , testMaxTime = fromMaybe 1000 testMaxTimeOpt\n        , testMinTime = fromMaybe 50 testMinTimeOpt\n        , testStressWorkers = testStressWorkers\n        , testTags = testTags\n        , testMaxIterSet = isJust testMaxIterOpt\n        , testMaxTimeSet = isJust testMaxTimeOpt\n        , testMinTimeSet = isJust testMinTimeOpt\n        , testModules = testModules\n        , testNames = testNames\n        }\n\ndepOverrideReader :: ReadM (String,String)\ndepOverrideReader = eitherReader $ \\s ->\n  case break (== '=') s of\n    (name, '=':path) | not (null name) && not (null path) -> Right (name, path)\n    _ -> Left \"Expected NAME=PATH\"\n\ndescr               = fullDesc <> progDesc \"Compilation and management of Acton source code and projects\"\n                      <> header \"acton - the Acton compiler\"\n\n-- main = do\n--     f <- parseCmdLine\n--     print(f)\ndata BuildSpecCommand = BuildSpecDump\n                      | BuildSpecUpdate FilePath\n                      deriving Show\n\nbuildSpecCommand :: Parser BuildSpecCommand\nbuildSpecCommand = hsubparser\n    (  command \"dump\"\n          (info (pure BuildSpecDump)\n                (progDesc \"Dump build spec as JSON to stdout (from Build.act)\"))\n    <> command \"update\"\n          (info (BuildSpecUpdate <$> argument str (metavar \"FILE\"))\n                (progDesc \"Update Build.act using JSON file; override entries present in JSON only\"))\n    )\n"
  },
  {
    "path": "compiler/lib/src/Acton/Compile.hs",
    "content": "{-# LANGUAGE CPP #-}\n{-|\nOverview\n\nThis module implements the shared Acton compilation pipeline that both the\nacton CLI and the LSP server drive. It builds a dependency graph across\nprojects, runs the front passes (parse, kinds, types) to produce .ty interface\nfiles and diagnostics, and then emits the back passes (normalizer through\ncodegen) as separate jobs.\n\nThe design is intentionally incremental and event-friendly. While the compiler\nscheduler is running and actively compiling modules, we can receive a new event\nabout a modified module, cancel running tasks and restart compilation of that\nmodule from that point. This is used by watch mode and LSP where updates to\nfiles or in-editor buffers trigger recompilation. Dependencies are considered so\nthat updates to a module only cause the affected part of the subgraph, i.e. the\nmodified module and downstream dependencies to be recompiled. Cached .ty headers\nare reused when public module interfaces are unchanged. Per-name pub/impl hashes\nstored in the header drive front-pass vs back-pass decisions, and moduleImplHash\nis embedded in generated .c/.h to detect stale codegen. Inter-module\ndependencies only depend on the front passes completion, which is why they are\nseparated from back jobs. As soon as the front passes of a module have\ncompleted, dependent modules can start compilation while the back pass job is\nscheduled in the background. This maximizes parallelism. It is only the front\npasses that can generate user facing errors, which means that the LSP server can\nreturn with feedback to the user (module type checked successfully) immediately\nafter the front passes are done while the back passes can be run asynchronously\nin the background. This maximizes responsiveness of the LSP server.\n\nThe CLI/LSP layers handle progress UI, file watching, and event sources; this\nmodule focuses on deterministic compilation and structured callbacks.\n\nCall flow:\n  - Shared pipeline (acton build, acton watch, LSP):\n    1) prepareCompilePlan (via prepareCompileContext, readModuleTask/\n       buildGlobalTasks/readImports, and selectNeededTasks/selectAffectedTasks)\n       builds a CompilePlan for the requested subgraph. Parsing is performed\n       through parseActSource/parseActSnapshot/parseActFile so SourceProvider\n       overlays can supply unsaved buffers.\n    2) runCompilePlan drives compileTasks. As each module finishes its front\n       passes, the CompileHooks callbacks (for example chOnFrontResult)\n       enqueue a BackJob into the scheduler's\n       BackQueue, so back passes begin as soon as they are ready and can overlap\n       remaining front passes.\n    3) Callers either wait for backQueueWait (CLI builds) or let back jobs run\n       in the background. CLI builds wait before invoking Zig.\n    4) runBackJobs/runBackPasses can be used for standalone back-pass execution\n       when a caller already has BackJobs to run.\n  - Triggering:\n    - acton build runs the pipeline once for the requested files/project.\n    - acton watch and LSP call startCompile on each event; callers can gate\n      output with generation checks (e.g. whenCurrentGen), and BackQueue ignores\n      back jobs for stale generations.\n    - Callers may supply a delay (debounce) before startCompile runs (LSP uses\n      debounceMicros on change events; acton watch uses 0).\n  - Finalization:\n    - CLI waits on backQueueWait before running Zig build\n    - LSP does not implicitly run the Zig build, it is only run explicitly when\n      the user asks to build / run a module\n\nState and orchestration:\n  - Acton.Compile holds only small in-process caches (tyPathCache, pubHashCache,\n    and nameHashCache) to speed up .ty lookups; all orchestration state is\n    owned by the caller.\n  - Callers allocate and hold a CompileScheduler from this module. The\n    scheduler encapsulates mutable state (generation id, cancelable async\n    handle, build-spec stamp, and a shared back-queue); callers pass it into\n    startCompile and backQueueEnqueue rather than mutating it directly.\n  - LSP additionally keeps overlaysRef for in-memory buffers and builds an\n    overlay-aware SourceProvider on top of disk reads. acton watch reads\n    directly from disk.\n  - Each event bumps the generation via startCompile; callers may pass a delay\n    (LSP uses debounceMicros, acton watch uses 0). Back jobs are filtered by\n    generation inside BackQueue; front-pass diagnostics should be gated by the\n    caller if needed.\n  - CLI builds share the same pipeline and enqueue back jobs as soon as front\n    passes finish, overlapping work without needing a watch event source.\n\nTODO:\n  - Make generation invalidation more precise so unrelated in-flight modules\n    (e.g. long-running B) are not discarded when A changes.\n-}\nmodule Acton.Compile\n  ( Paths(..)\n  , ProjCtx(..)\n  , TaskKey(..)\n  , GlobalTask(..)\n  , CompileTask(..)\n  , BackInput(..)\n  , BackJob(..)\n  , FrontResult(..)\n  , FrontTiming(..)\n  , TypeStmtTiming(..)\n  , InferredSignature(..)\n  , BackTiming(..)\n  , FrontPass(..)\n  , FrontPassProgress(..)\n  , ParseProgress(..)\n  , CompileCallbacks(..)\n  , defaultCompileCallbacks\n  , BackJobCallbacks(..)\n  , defaultBackJobCallbacks\n  , BackQueue\n  , newBackQueue\n  , backQueueEnqueue\n  , backQueueWait\n  , CompileScheduler(..)\n  , newCompileScheduler\n  , startCompile\n  , whenCurrentGen\n  , BuildSpecStamp(..)\n  , readBuildSpecStamp\n  , checkBuildSpecChange\n  , CompileContext(..)\n  , prepareCompileContext\n  , CompilePlan(..)\n  , prepareCompilePlan\n  , prepareCompilePlanFromContext\n  , CompileHooks(..)\n  , defaultCompileHooks\n  , runCompilePlan\n  , CompileFailure(..)\n  , compileFailureMessage\n  , BackPassFailure(..)\n  , backPassFailureMessage\n  , BackJobResult(..)\n  , defaultCompileOptions\n  , ProjectError(..)\n  , throwProjectError\n  , fetchDependencies\n  , parseActSource\n  , parseActSnapshot\n  , parseActFile\n  , readModuleTask\n  , readModuleDoc\n  , readImports\n  , buildGlobalTasks\n  , selectNeededTasks\n  , selectAffectedTasks\n  , compileTasks\n  , runFrontPasses\n  , runBackPasses\n  , runBackJobs\n  , findProjectDir\n  , BackgroundCompilerLock\n  , backgroundCompilerLockPath\n  , tryBackgroundCompilerLock\n  , releaseBackgroundCompilerLock\n  , projectLockPath\n  , withProjectLockOnWait\n  , withProjectLock\n  , findPaths\n  , discoverProjects\n  , pathsForModule\n  , searchPathForProject\n  , moduleNameFromFile\n  , enumerateProjectModules\n  , normalizeDepOverrides\n  , applyDepOverrides\n  , collectDepTypePaths\n  , depTypePathsFromMap\n  , resolveDepBase\n  , loadBuildSpec\n  , filterActFile\n  , srcFile\n  , outBase\n  , srcBase\n  , getModPath\n  , modNameToFilename\n  , modNameToString\n  , nameToString\n  , importsOf\n  , quiet\n  , altOutput\n  , missingIfaceDiagnostics\n  , getPubHashCached\n  , updatePubHashCache\n  , rootEligible\n  , normalizePathSafe\n  , isAbsolutePath\n  , collapseDots\n  , rebasePath\n  ) where\n\nimport Prelude hiding (readFile, writeFile)\n\nimport qualified Acton.Parser\nimport Acton.Parser (CustomParseError, CustomParseException, ChunkScanError(..), ContextError, IndentationError)\nimport qualified Acton.Syntax as A\nimport qualified Acton.NameInfo as I\nimport Text.Megaparsec.Error (ParseErrorBundle)\nimport qualified Acton.CommandLineParser as C\nimport Acton.Printer ()\nimport qualified Acton.Env\nimport qualified Acton.TypeEnv\nimport Acton.Env (simp, define, setMod)\nimport qualified Acton.Hashing as Hashing\nimport qualified Acton.Names as Names\nimport qualified Acton.Kinds\nimport qualified Acton.Types\nimport qualified Acton.Converter as Converter\nimport qualified Acton.Normalizer\nimport qualified Acton.CPS\nimport qualified Acton.Deactorizer\nimport qualified Acton.LambdaLifter\nimport qualified Acton.Boxing\nimport qualified Acton.CodeGen\nimport Acton.Prim (mPrim)\nimport qualified Acton.BuildSpec as BuildSpec\nimport qualified Acton.DocPrinter as DocP\nimport qualified Acton.Fingerprint as Fingerprint\nimport qualified Acton.Diagnostics as Diag\nimport qualified Acton.SourceProvider as Source\nimport Utils\nimport qualified Pretty\nimport qualified InterfaceFiles\n\nimport Control.Applicative ((<|>))\nimport Control.Concurrent.Async\nimport Control.Concurrent.MVar\nimport Control.Concurrent (forkIO, myThreadId, threadCapability, threadDelay)\nimport Control.Concurrent.STM (TChan, TVar, atomically, check, modifyTVar', newTChanIO, newTVarIO, readTChan, readTVar, writeTChan)\nimport Control.DeepSeq (rnf)\nimport Control.Exception (Exception, IOException, SomeAsyncException, SomeException, catch, displayException, evaluate, finally, fromException, mask_, throwIO, try)\nimport Control.Monad\nimport Data.Bits (shiftL, shiftR, (.|.))\nimport Data.Char (isAlpha, isDigit, isHexDigit, isSpace, toLower)\nimport Data.Either (partitionEithers)\nimport Data.Graph\nimport Data.List (find, foldl', intercalate, intersperse, isPrefixOf, isSuffixOf, nub, partition)\nimport qualified Data.List\nimport Data.IORef\nimport Data.Maybe (catMaybes, isJust, listToMaybe, mapMaybe)\nimport qualified Data.HashMap.Strict as HM\nimport qualified Data.Map as M\nimport Data.Ord (Down(..))\nimport qualified Data.Set\nimport Data.Time.Clock (UTCTime)\nimport Data.Word (Word8, Word32, Word64)\nimport Error.Diagnose (Diagnostic)\nimport GHC.Conc (getNumCapabilities)\nimport qualified Network.HTTP.Client as HTTP\nimport Network.HTTP.Client.TLS (tlsManagerSettings)\nimport Network.HTTP.Types.Header (hContentDisposition, hContentType)\nimport Network.HTTP.Types.Status (statusCode)\nimport System.Clock\nimport System.Directory\nimport System.Directory.Recursive\nimport System.Environment (getExecutablePath, lookupEnv)\nimport System.FileLock (FileLock, SharedExclusive(Exclusive), tryLockFile, unlockFile, withFileLock)\nimport System.FilePath ((</>))\nimport System.FilePath.Posix\nimport System.Exit (ExitCode(..))\nimport System.IO hiding (readFile, writeFile)\nimport System.IO.Unsafe (unsafePerformIO)\nimport System.Posix.Files (FileStatus, deviceID, fileID, fileSize, getFileStatus, modificationTimeHiRes, statusChangeTimeHiRes)\nimport System.Process (readCreateProcessWithExitCode, proc)\nimport System.Random (randomRIO)\nimport Text.PrettyPrint (renderStyle, style, Style(..), Mode(PageMode))\nimport Text.Show.Pretty (ppDoc)\nimport Text.Printf\n\nimport qualified Data.ByteString as BS\nimport qualified Data.ByteString.Char8 as B\nimport qualified Data.ByteString.Base16 as Base16\nimport qualified Crypto.Hash.SHA256 as SHA256\n\n\nnewtype ProjectError = ProjectError String deriving (Show)\n\ninstance Exception ProjectError\n\n-- | Raise a ProjectError for library callers.\n-- Used by project discovery and path helpers to stop on unrecoverable errors.\nthrowProjectError :: String -> IO a\nthrowProjectError msg = throwIO (ProjectError msg)\n\n\ndata CompileFailure\n  = CompileCycleFailure String\n  | CompileBuiltinFailure\n  | CompileInternalFailure String\n  deriving (Eq, Show)\n\n-- | Render internal compile failures as user-facing messages.\n-- Centralizes wording so CLI output and tests stay consistent.\ncompileFailureMessage :: CompileFailure -> String\ncompileFailureMessage (CompileCycleFailure msg) = msg\ncompileFailureMessage CompileBuiltinFailure = \"Builtin compilation failed\"\ncompileFailureMessage (CompileInternalFailure msg) = msg\n\n\ndata BackPassFailure = BackPassFailure\n  { bpfKey :: TaskKey\n  , bpfMessage :: String\n  } deriving (Eq, Show)\n\nbackPassFailureMessage :: BackPassFailure -> String\nbackPassFailureMessage (BackPassFailure key msg) =\n  \"Back pass failed for \" ++ tkProj key ++ \"/\" ++ modNameToString (tkMod key) ++ \": \" ++ msg\n\ndata BackJobResult\n  = BackJobOk (Maybe TimeSpec) (Maybe BackTiming)\n  | BackJobFailed BackPassFailure\n  deriving (Eq, Show)\n\ndata FrontPass\n  = FrontPassKinds\n  | FrontPassTypes\n  deriving (Eq, Show)\n\ndata FrontPassProgress = FrontPassProgress\n  { fppPass :: FrontPass\n  , fppCompleted :: Int\n  , fppTotal :: Int\n  , fppCurrent :: Maybe String\n  } deriving (Eq, Show)\n\ndata ParseProgress = ParseProgress\n  { ppCompleted :: Int\n  , ppTotal :: Int\n  } deriving (Eq, Show)\n\ndata TypeStmtTiming = TypeStmtTiming\n  { tstCompleted :: Int\n  , tstTotal :: Int\n  , tstLabel :: String\n  , tstNames :: [String]\n  , tstTime :: TimeSpec\n  } deriving (Eq, Show)\n\ndata InferredSignature = InferredSignature\n  { isigNames :: [String]\n  , isigSignature :: String\n  } deriving (Eq, Show)\n\ndata FrontTiming = FrontTiming\n  { ftEnv :: TimeSpec\n  , ftKinds :: TimeSpec\n  , ftTypes :: TimeSpec\n  , ftTypeStmtTimings :: [TypeStmtTiming]\n  } deriving (Eq, Show)\n\ndata BackTiming = BackTiming\n  { btNormalize :: TimeSpec\n  , btDeactorize :: TimeSpec\n  , btCPS :: TimeSpec\n  , btLLift :: TimeSpec\n  , btBoxing :: TimeSpec\n  , btCodeGen :: TimeSpec\n  , btWriteCode :: Maybe TimeSpec\n  } deriving (Eq, Show)\n\n\ndata CompileCallbacks = CompileCallbacks\n  { ccOnDiagnostics :: GlobalTask -> C.CompileOptions -> [Diagnostic String] -> IO ()\n  , ccOnParseStart :: GlobalTask -> C.CompileOptions -> IO ()\n  , ccOnParseProgress :: GlobalTask -> C.CompileOptions -> ParseProgress -> IO ()\n  , ccOnParseDone :: GlobalTask -> C.CompileOptions -> Maybe TimeSpec -> IO ()\n  , ccOnFrontResult :: GlobalTask -> C.CompileOptions -> FrontResult -> IO ()\n  , ccOnFrontStart :: GlobalTask -> C.CompileOptions -> IO ()\n  , ccOnFrontDone :: GlobalTask -> C.CompileOptions -> IO ()\n  , ccOnFrontProgress :: GlobalTask -> C.CompileOptions -> FrontPassProgress -> IO ()\n  , ccOnBackJob :: BackJob -> IO ()\n  , ccOnInfo :: String -> IO ()\n  }\n\n-- | Default no-op callbacks for the compilation pipeline.\n-- Callers can start from this and override only the events they care about.\ndefaultCompileCallbacks :: CompileCallbacks\ndefaultCompileCallbacks = CompileCallbacks\n  { ccOnDiagnostics = \\_ _ _ -> return ()\n  , ccOnParseStart = \\_ _ -> return ()\n  , ccOnParseProgress = \\_ _ _ -> return ()\n  , ccOnParseDone = \\_ _ _ -> return ()\n  , ccOnFrontResult = \\_ _ _ -> return ()\n  , ccOnFrontStart = \\_ _ -> return ()\n  , ccOnFrontDone = \\_ _ -> return ()\n  , ccOnFrontProgress = \\_ _ _ -> return ()\n  , ccOnBackJob = \\_ -> return ()\n  , ccOnInfo = \\_ -> return ()\n  }\n\ndata BackJobCallbacks = BackJobCallbacks\n  { bjcOnStart :: BackJob -> IO ()\n  , bjcOnDone :: BackJob -> BackJobResult -> IO ()\n  }\n\n-- | Default no-op callbacks for back-pass execution.\ndefaultBackJobCallbacks :: BackJobCallbacks\ndefaultBackJobCallbacks =\n  BackJobCallbacks\n    { bjcOnStart = \\_ -> return ()\n    , bjcOnDone = \\_ _ -> return ()\n    }\n\ndata BackQueue = BackQueue\n  { backQueueEnqueue :: Int -> BackJob -> BackJobCallbacks -> IO Bool\n  , backQueueWait :: Int -> IO (Maybe BackPassFailure)\n  }\n\ndata BuildSpecStamp = BuildSpecStamp\n  { bssBuildAct :: Maybe UTCTime\n  } deriving (Eq, Show)\n\nreadBuildSpecStamp :: FilePath -> IO BuildSpecStamp\nreadBuildSpecStamp projDir = do\n  buildAct <- stampFor \"Build.act\"\n  return BuildSpecStamp\n    { bssBuildAct = buildAct\n    }\n  where\n    stampFor name = do\n      let path = projDir </> name\n      exists <- doesFileExist path\n      if exists\n        then Just <$> getModificationTime path\n        else return Nothing\n\ncheckBuildSpecChange :: CompileScheduler -> BuildSpecStamp -> IO Bool\ncheckBuildSpecChange sched stamp =\n  atomicModifyIORef' (csBuildStampRef sched) $ \\prev ->\n    let changed = prev /= Just stamp\n    in (Just stamp, changed)\n\n-- | Create a concurrent back-pass queue gated by a generation counter.\n-- Each job is tagged with a generation id; stale jobs are skipped.\nnewBackQueue :: IORef Int -> C.GlobalOptions -> Int -> IO BackQueue\nnewBackQueue genRef gopts maxPar = do\n  queue <- newTChanIO\n  counts <- newTVarIO M.empty\n  failures <- newTVarIO M.empty\n  let incPending gen = M.insertWith (+) gen 1\n      decPending gen m =\n        case M.lookup gen m of\n          Nothing -> m\n          Just n ->\n            let n' = n - 1\n            in if n' <= 0\n                 then M.delete gen m\n                 else M.insert gen n' m\n      recordFailure gen failure =\n        M.insertWith (\\_ old -> old) gen failure\n      enqueue gen job callbacks = do\n        current <- readIORef genRef\n        if current /= gen\n          then return False\n          else do\n            atomically $ do\n              modifyTVar' counts (incPending gen)\n              writeTChan queue (gen, job, callbacks)\n            return True\n      waitDone gen = atomically $ do\n        failuresNow <- readTVar failures\n        case M.lookup gen failuresNow of\n          Just failure -> do\n            modifyTVar' failures (M.delete gen)\n            return (Just failure)\n          Nothing -> do\n            pending <- readTVar counts\n            let n = M.findWithDefault 0 gen pending\n            check (n == 0)\n            return Nothing\n      worker = forever $ do\n        (gen, job, callbacks) <- atomically $ readTChan queue\n        current <- readIORef genRef\n        if current /= gen\n          then atomically $ modifyTVar' counts (decPending gen)\n          else do\n            failed <- atomically $ do\n              failuresNow <- readTVar failures\n              return (M.member gen failuresNow)\n            if failed\n              then atomically $ modifyTVar' counts (decPending gen)\n              else do\n                let shouldWrite = do\n                      currentWrite <- readIORef genRef\n                      return (currentWrite == gen)\n                bjcOnStart callbacks job\n                res <- (try $ runBackPasses gopts (bjOpts job) (bjPaths job) (bjInput job) shouldWrite)\n                        :: IO (Either SomeException (Maybe TimeSpec, Maybe BackTiming))\n                currentDone <- readIORef genRef\n                when (currentDone == gen) $\n                  case res of\n                    Left err -> do\n                      let key = TaskKey (projPath (bjPaths job)) (A.modname (biTypedMod (bjInput job)))\n                          failure = BackPassFailure key (displayException err)\n                      atomically $ modifyTVar' failures (recordFailure gen failure)\n                      bjcOnDone callbacks job (BackJobFailed failure)\n                    Right (t, bt) -> bjcOnDone callbacks job (BackJobOk t bt)\n                atomically $ modifyTVar' counts (decPending gen)\n  let workers = max 1 maxPar\n  replicateM_ workers (forkIO worker)\n  return BackQueue\n    { backQueueEnqueue = enqueue\n    , backQueueWait = waitDone\n    }\n\ndata CompileScheduler = CompileScheduler\n  { csGenRef :: IORef Int\n  , csAsyncRef :: MVar (Maybe (Async ()))\n  , csBackQueue :: BackQueue\n  , csBuildStampRef :: IORef (Maybe BuildSpecStamp)\n  }\n\n-- | Create a scheduler with generation tracking and a shared back queue.\nnewCompileScheduler :: C.GlobalOptions -> Int -> IO CompileScheduler\nnewCompileScheduler gopts maxPar = do\n  genRef <- newIORef 0\n  asyncRef <- newMVar Nothing\n  backQueue <- newBackQueue genRef gopts maxPar\n  buildStampRef <- newIORef Nothing\n  return CompileScheduler\n    { csGenRef = genRef\n    , csAsyncRef = asyncRef\n    , csBackQueue = backQueue\n    , csBuildStampRef = buildStampRef\n    }\n\n-- | Start a new compile action, canceling any in-flight run.\n-- Returns the generation id associated with this run.\nstartCompile :: CompileScheduler -> Int -> (Int -> IO ()) -> IO Int\nstartCompile sched delay run = do\n  gen <- atomicModifyIORef' (csGenRef sched) $ \\g -> let g' = g + 1 in (g', g')\n  modifyMVar_ (csAsyncRef sched) $ \\m -> do\n    forM_ m cancel\n    a <- async $ do\n      when (delay > 0) $ threadDelay delay\n      current <- readIORef (csGenRef sched)\n      when (current == gen) $ run gen\n    return (Just a)\n  return gen\n\n-- | Run an action only if the generation still matches.\nwhenCurrentGen :: CompileScheduler -> Int -> IO () -> IO ()\nwhenCurrentGen sched gen action = do\n  current <- readIORef (csGenRef sched)\n  when (current == gen) action\n\ndata CompileContext = CompileContext\n  { ccOpts :: C.CompileOptions\n  , ccDepOverrides :: [(String, FilePath)]\n  , ccPathsRoot :: Paths\n  , ccRootProj :: FilePath\n  , ccSysAbs :: FilePath\n  , ccBuildStamp :: BuildSpecStamp\n  }\n\nprepareCompileContext :: C.CompileOptions -> [FilePath] -> IO CompileContext\nprepareCompileContext opts srcFiles = do\n  when (null srcFiles) $\n    throwProjectError \"No source files found\"\n  cwd <- getCurrentDirectory\n  maybeRoot <- findProjectDir (takeDirectory (head srcFiles))\n  let baseForOverrides = maybe cwd id maybeRoot\n  depOverrides <- normalizeDepOverrides baseForOverrides (C.dep_overrides opts)\n  let opts' = opts { C.dep_overrides = depOverrides }\n  pathsRoot <- findPaths (head srcFiles) opts'\n  rootProj <- normalizePathSafe (projPath pathsRoot)\n  sysAbs <- normalizePathSafe (sysPath pathsRoot)\n  buildStamp <- readBuildSpecStamp (projPath pathsRoot)\n  return CompileContext\n    { ccOpts = opts'\n    , ccDepOverrides = depOverrides\n    , ccPathsRoot = pathsRoot\n    , ccRootProj = rootProj\n    , ccSysAbs = sysAbs\n    , ccBuildStamp = buildStamp\n    }\n\n-- | Prepare a compile plan, refreshing dependencies if the build spec changed.\nprepareCompilePlan :: Source.SourceProvider\n                   -> C.GlobalOptions\n                   -> CompileScheduler\n                   -> C.CompileOptions\n                   -> [FilePath]\n                   -> Bool\n                   -> Maybe [FilePath]\n                   -> IO CompilePlan\nprepareCompilePlan sp gopts sched opts srcFiles allowPrune mChangedPaths = do\n  ctx <- prepareCompileContext opts srcFiles\n  specChanged <- checkBuildSpecChange sched (ccBuildStamp ctx)\n  when specChanged $\n    fetchDependencies gopts (ccPathsRoot ctx) (ccDepOverrides ctx)\n  let mChanged = if specChanged then Nothing else mChangedPaths\n  prepareCompilePlanFromContext sp gopts ctx srcFiles allowPrune mChanged\n\ndata CompilePlan = CompilePlan\n  { cpContext :: CompileContext\n  , cpProjMap :: M.Map FilePath ProjCtx\n  , cpGlobalTasks :: [GlobalTask]\n  , cpNeededTasks :: [GlobalTask]\n  , cpRootTasks :: [CompileTask]\n  , cpRootPins :: M.Map String BuildSpec.PkgDep\n  , cpIncremental :: Bool\n  , cpAllowPrune :: Bool\n  , cpChangedPaths :: Maybe [FilePath]\n  , cpSrcFiles :: [FilePath]\n  }\n\nprepareCompilePlanFromContext :: Source.SourceProvider\n                              -> C.GlobalOptions\n                              -> CompileContext\n                              -> [FilePath]\n                              -> Bool\n                              -> Maybe [FilePath]\n                              -> IO CompilePlan\nprepareCompilePlanFromContext sp gopts ctx srcFiles allowPrune mChangedPaths = do\n  let opts' = ccOpts ctx\n      depOverrides = ccDepOverrides ctx\n      pathsRoot = ccPathsRoot ctx\n      rootProj = ccRootProj ctx\n      sysAbs = ccSysAbs ctx\n      incremental = isJust mChangedPaths\n      allowPrune' = allowPrune && not incremental\n  projMap <- if isTmp pathsRoot\n    then do\n      let ctx' = ProjCtx\n            { projRoot = rootProj\n            , projOutDir = projOut pathsRoot\n            , projTypesDir = projTypes pathsRoot\n            , projSrcDir = srcDir pathsRoot\n            , projSysPath = sysAbs\n            , projSysTypes = joinPath [sysAbs, \"base\", \"out\", \"types\"]\n            , projBuildSpec = scratchBuildSpec rootProj\n            , projDeps = []\n            }\n      return (M.singleton rootProj ctx')\n    else discoverProjects gopts sysAbs rootProj depOverrides\n  -- Keep generated module artifacts in sync with source removals.\n  -- For full builds, scan and prune all orphan outputs.\n  -- For incremental builds, prune only modules whose changed .act paths are now missing.\n  if incremental\n    then maybe (return ()) (pruneMissingChangedModuleOutputs (M.elems projMap)) mChangedPaths\n    else mapM_ pruneMissingModuleOutputs (M.elems projMap)\n  (globalTasks, _) <- buildGlobalTasks sp gopts opts' projMap\n    (if incremental || allowPrune then Nothing else Just srcFiles)\n  neededTasks <- case mChangedPaths of\n    Nothing -> selectNeededTasks pathsRoot rootProj globalTasks srcFiles\n    Just changed -> selectAffectedTasks globalTasks changed\n  let rootTasks = [ gtTask t | t <- neededTasks, tkProj (gtKey t) == rootProj ]\n      rootPins = maybe M.empty (BuildSpec.dependencies . projBuildSpec) (M.lookup rootProj projMap)\n  return CompilePlan\n    { cpContext = ctx\n    , cpProjMap = projMap\n    , cpGlobalTasks = globalTasks\n    , cpNeededTasks = neededTasks\n    , cpRootTasks = rootTasks\n    , cpRootPins = rootPins\n    , cpIncremental = incremental\n    , cpAllowPrune = allowPrune'\n    , cpChangedPaths = mChangedPaths\n    , cpSrcFiles = srcFiles\n    }\n\ndata CompileHooks = CompileHooks\n  { chOnDiagnostics :: GlobalTask -> C.CompileOptions -> [Diagnostic String] -> IO ()\n  , chOnParseStart :: GlobalTask -> IO ()\n  , chOnParseProgress :: GlobalTask -> ParseProgress -> IO ()\n  , chOnParseDone :: GlobalTask -> Maybe TimeSpec -> IO ()\n  , chOnFrontStart :: GlobalTask -> IO ()\n  , chOnFrontDone :: GlobalTask -> IO ()\n  , chOnFrontProgress :: GlobalTask -> FrontPassProgress -> IO ()\n  , chOnFrontResult :: GlobalTask -> FrontResult -> IO ()\n  , chOnBackQueued :: TaskKey -> Bool -> IO ()\n  , chOnBackStart :: BackJob -> IO ()\n  , chOnBackDone :: BackJob -> BackJobResult -> IO ()\n  , chOnInfo :: String -> IO ()\n  }\n\ndefaultCompileHooks :: CompileHooks\ndefaultCompileHooks =\n  CompileHooks\n    { chOnDiagnostics = \\_ _ _ -> return ()\n    , chOnParseStart = \\_ -> return ()\n    , chOnParseProgress = \\_ _ -> return ()\n    , chOnParseDone = \\_ _ -> return ()\n    , chOnFrontStart = \\_ -> return ()\n    , chOnFrontDone = \\_ -> return ()\n    , chOnFrontProgress = \\_ _ -> return ()\n    , chOnFrontResult = \\_ _ -> return ()\n    , chOnBackQueued = \\_ _ -> return ()\n    , chOnBackStart = \\_ -> return ()\n    , chOnBackDone = \\_ _ -> return ()\n    , chOnInfo = \\_ -> return ()\n    }\n\nrunCompilePlan :: Source.SourceProvider\n               -> C.GlobalOptions\n               -> CompilePlan\n               -> CompileScheduler\n               -> Int\n               -> CompileHooks\n               -> IO (Either CompileFailure (Acton.Env.Env0, Bool))\nrunCompilePlan sp gopts plan sched gen hooks = do\n  let ctx = cpContext plan\n      opts' = ccOpts ctx\n      pathsRoot = ccPathsRoot ctx\n      rootProj = ccRootProj ctx\n      backQueue = csBackQueue sched\n      backCallbacks = BackJobCallbacks\n        { bjcOnStart = chOnBackStart hooks\n        , bjcOnDone = chOnBackDone hooks\n        }\n      callbacks = defaultCompileCallbacks\n        { ccOnDiagnostics = \\t optsT diags -> chOnDiagnostics hooks t optsT diags\n        , ccOnParseStart = \\t _ -> chOnParseStart hooks t\n        , ccOnParseProgress = \\t _ p -> chOnParseProgress hooks t p\n        , ccOnParseDone = \\t _ mtime -> chOnParseDone hooks t mtime\n        , ccOnFrontResult = \\t _ fr -> chOnFrontResult hooks t fr\n        , ccOnFrontStart = \\t _ -> chOnFrontStart hooks t\n        , ccOnFrontDone = \\t _ -> chOnFrontDone hooks t\n        , ccOnFrontProgress = \\t _ p -> chOnFrontProgress hooks t p\n        , ccOnBackJob = \\job -> do\n            let key = TaskKey (projPath (bjPaths job)) (A.modname (biTypedMod (bjInput job)))\n            enqueued <- backQueueEnqueue backQueue gen job backCallbacks\n            chOnBackQueued hooks key enqueued\n        , ccOnInfo = chOnInfo hooks\n        }\n  compileTasks sp gopts opts' pathsRoot rootProj (cpNeededTasks plan) callbacks\n-- | Baseline compile options for internal helpers and tests.\n-- This mirrors CLI defaults so path discovery and parsing behave predictably\n-- when no command-line flags are present.\ndefaultCompileOptions :: C.CompileOptions\ndefaultCompileOptions =\n  C.CompileOptions\n    { C.alwaysbuild = False\n    , C.ignore_compiler_version = False\n    , C.db = False\n    , C.parse = False\n    , C.parse_ast = False\n    , C.kinds = False\n    , C.types = False\n    , C.sigs = False\n    , C.norm = False\n    , C.deact = False\n    , C.cps = False\n    , C.llift = False\n    , C.box = False\n    , C.hgen = False\n    , C.cgen = False\n    , C.ccmd = False\n    , C.ty = False\n    , C.cpedantic = False\n    , C.dbg_no_lines = False\n    , C.optimize = C.Debug\n    , C.only_build = False\n    , C.skip_build = False\n    , C.watch = False\n    , C.no_threads = False\n    , C.parse_serial = False\n    , C.root = \"\"\n    , C.tempdir = \"\"\n    , C.syspath = \"\"\n    , C.target = C.defTarget\n    , C.cpu = \"\"\n    , C.test = False\n    , C.searchpath = []\n    , C.dep_overrides = []\n    }\n\n-- | Debug helper for pass dumps.\n-- Prints a header and footer around the given text so pass output is easy to\n-- spot in verbose logs.\ndump :: A.ModName -> String -> String -> IO ()\ndump mn h txt =\n  putStrLn (\"\\n\\n== \" ++ h ++ \": \" ++ modNameToString mn ++ \" ================================\\n\" ++ txt\n            ++ '\\n' : replicate (38 + length h + length (modNameToString mn)) '=' ++ \"\\n\")\n\n-- | Compute the subdirectory for a module within a types root.\n-- Used when creating directories before writing .ty files.\ngetModPath :: FilePath -> A.ModName -> FilePath\ngetModPath path mn =\n  joinPath [path, joinPath $ init $ A.modPath mn]\n\n-- Global caches (process‑wide) to reduce repeated .ty lookups during parallel builds\n--\n-- We deliberately create top‑level MVars via unsafePerformIO and mark them\n-- NOINLINE so their initializer runs exactly once. Without NOINLINE, GHC could\n-- inline or float the initializer, accidentally creating multiple MVars under\n-- optimization. This guarantees a single cache per process.\n--\n-- Thread‑safety: all access goes through modifyMVar/modifyMVar_ so read/modify/\n-- write is atomic. These caches are best‑effort for performance; correctness\n-- does not depend on them. On a miss we fall back to reading .ty headers from\n-- disk. After a successful compile we update pubHashCache so dependents in\n-- this process see the new public hash.\n--\n-- tyPathCache    :: ModName -> absolute .ty path (resolved from searchPath)\n-- pubHashCache :: ModName -> current public hash (from header or compile)\n-- nameHashCache  :: ModName -> per-name hash info (from header or compile)\n{-# NOINLINE tyPathCache #-}\ntyPathCache :: MVar (M.Map A.ModName FilePath)\ntyPathCache = unsafePerformIO (newMVar M.empty)\n\n{-# NOINLINE pubHashCache #-}\npubHashCache :: MVar (M.Map A.ModName B.ByteString)\npubHashCache = unsafePerformIO (newMVar M.empty)\n\n{-# NOINLINE nameHashCache #-}\nnameHashCache :: MVar (M.Map A.ModName (M.Map A.Name InterfaceFiles.NameHashInfo))\nnameHashCache = unsafePerformIO (newMVar M.empty)\n\n-- | Resolve the on-disk .ty path for a module, using a process-wide cache.\n-- Avoids repeated filesystem walks when many modules share dependencies.\ngetTyFileCached :: [FilePath] -> A.ModName -> IO (Maybe FilePath)\ngetTyFileCached spaths mn = modifyMVar tyPathCache $ \\m -> do\n  normSearch <- mapM normalizePathSafe spaths\n  let inSearchPath p =\n        let pNorm = normalise p\n        in any (\\dir ->\n                  let dirNorm = addTrailingPathSeparator (normalise dir)\n                  in Data.List.isPrefixOf dirNorm pNorm)\n               normSearch\n      refresh cache = do\n        mty <- Acton.Env.findTyFile spaths mn\n        case mty of\n          Just p  -> return (M.insert mn p cache, Just p)\n          Nothing -> return (M.delete mn cache, Nothing)\n  case M.lookup mn m of\n    Just p -> do\n      pNorm <- normalizePathSafe p\n      exists <- doesFileExist pNorm\n      if exists && inSearchPath pNorm\n        then return (m, Just pNorm)\n        else refresh m\n    Nothing -> refresh m\n\n-- | Read a module's public hash using the cache and .ty header.\n-- This drives dependency invalidation when an imported interface changes.\ngetPubHashCached :: Paths -> A.ModName -> IO (Maybe B.ByteString)\ngetPubHashCached paths mn = modifyMVar pubHashCache $ \\m -> do\n  case M.lookup mn m of\n    Just ih -> return (m, Just ih)\n    Nothing -> do\n      mty <- getTyFileCached (searchPath paths) mn\n      case mty of\n        Just ty -> do\n          hdrE <- (try :: IO a -> IO (Either SomeException a)) $ InterfaceFiles.readHeader ty\n          case hdrE of\n            Right (_sourceMetaH, _srcH, ih, _implH, _impsH, _nameHashesH, _rootsH, _testsH, _docH) -> return (M.insert mn ih m, Just ih)\n            _ -> return (m, Nothing)\n        Nothing -> return (m, Nothing)\n\n-- | Update the public-hash cache after a successful compile.\n-- Keeps in-process dependency checks consistent for later modules.\nupdatePubHashCache :: A.ModName -> B.ByteString -> IO ()\nupdatePubHashCache mn ih = modifyMVar_ pubHashCache $ \\m -> return (M.insert mn ih m)\n\n-- | Build a name hash map keyed by Name.\nnameHashMapFromList :: [InterfaceFiles.NameHashInfo] -> M.Map A.Name InterfaceFiles.NameHashInfo\nnameHashMapFromList infos = M.fromList [ (InterfaceFiles.nhName i, i) | i <- infos ]\n\npublicIfaceTE :: [(A.Name, I.NameInfo)] -> [(A.Name, I.NameInfo)]\npublicIfaceTE = filter (Names.isPublicName . fst)\n\npublicNameHashes :: [InterfaceFiles.NameHashInfo] -> [InterfaceFiles.NameHashInfo]\npublicNameHashes = filter (Names.isPublicName . InterfaceFiles.nhName)\n\n-- | Read a module's per-name hash map using the cache and .ty header.\ngetNameHashMapCached :: Paths -> A.ModName -> IO (Maybe (M.Map A.Name InterfaceFiles.NameHashInfo))\ngetNameHashMapCached paths mn = modifyMVar nameHashCache $ \\m -> do\n  case M.lookup mn m of\n    Just hm -> return (m, Just hm)\n    Nothing -> do\n      mty <- getTyFileCached (searchPath paths) mn\n      case mty of\n        Just ty -> do\n          hdrE <- (try :: IO a -> IO (Either SomeException a)) $ InterfaceFiles.readHeader ty\n          case hdrE of\n            Right (_sourceMetaH, _srcH, _ih, _implH, _impsH, nameHashes, _rootsH, _testsH, _docH) -> do\n              let hm = nameHashMapFromList (publicNameHashes nameHashes)\n              return (M.insert mn hm m, Just hm)\n            _ -> return (m, Nothing)\n        Nothing -> return (m, Nothing)\n\n-- | Update the name-hash cache after a successful compile.\nupdateNameHashCache :: A.ModName -> [InterfaceFiles.NameHashInfo] -> IO ()\nupdateNameHashCache mn infos =\n  modifyMVar_ nameHashCache $ \\m -> return (M.insert mn (nameHashMapFromList infos) m)\n\n\n-- Handling Acton files -----------------------------------------------------------------------------\n\n-- | Keep only .act files when scanning directories.\n-- Returns Just the file path for Acton sources and Nothing otherwise.\nfilterActFile :: FilePath -> Maybe FilePath\nfilterActFile file =\n    case fileExt of\n        \".act\" -> Just file\n        _ -> Nothing\n  where (fileBody, fileExt) = splitExtension $ takeFileName file\n\n-- | Turn a list of (location, message) pairs into diagnostics.\n-- Used to normalize errors from different compiler subsystems.\nerrsToDiagnostics :: String -> FilePath -> String -> [(SrcLoc, String)] -> [Diagnostic String]\nerrsToDiagnostics errKind filename src errs =\n    [ Diag.actErrToDiagnostic errKind filename src loc msg | (loc, msg) <- errs ]\n\n-- | Emit diagnostics when a dependency .ty file is missing or unreadable.\n-- Anchors the error to the owning module's filename for consistent reporting.\nmissingIfaceDiagnostics :: A.ModName -> String -> A.ModName -> [Diagnostic String]\nmissingIfaceDiagnostics ownerMn src missingMn =\n    errsToDiagnostics \"Compilation error\" (modNameToFilename ownerMn) src\n      [(NoLoc, \"Type interface file not found or unreadable for \" ++ modNameToString missingMn)]\n\n-- | Parse a module from source text, returning diagnostics on failure.\n-- Wraps parser, context, and indentation errors into a uniform format.\nparseActSource :: C.CompileOptions -> A.ModName -> FilePath -> String -> Maybe (ParseProgress -> IO ()) -> IO (Either [Diagnostic String] A.Module)\nparseActSource opts mn actFile srcContent mOnProgress = do\n  let parseModule\n        | C.parse_serial opts = Acton.Parser.parseModuleSerial\n        | otherwise             = Acton.Parser.parseModule\n  (Right <$> parseModule mn actFile srcContent (fmap wrapProgress mOnProgress))\n    `catch` handleParseBundle\n    `catch` handleCustomParse\n    `catch` handleChunkScanError\n    `catch` handleContextError\n    `catch` handleIndentationError\n  where\n    wrapProgress onProgress completed total =\n      onProgress (ParseProgress completed total)\n\n    handleParseBundle :: ParseErrorBundle String CustomParseError -> IO (Either [Diagnostic String] A.Module)\n    handleParseBundle bundle =\n      return $ Left [Diag.parseDiagnosticFromBundle actFile srcContent bundle]\n\n    handleCustomParse :: CustomParseException -> IO (Either [Diagnostic String] A.Module)\n    handleCustomParse err =\n      return $ Left [Diag.customParseExceptionToDiagnostic actFile srcContent err]\n\n    handleChunkScanError :: ChunkScanError -> IO (Either [Diagnostic String] A.Module)\n    handleChunkScanError (ChunkScanError loc msg) =\n      return $ Left (errsToDiagnostics \"Parse error\" actFile srcContent [(loc, msg)])\n\n    handleContextError :: ContextError -> IO (Either [Diagnostic String] A.Module)\n    handleContextError err =\n      return $ Left (errsToDiagnostics \"Context error\" (modNameToFilename mn) srcContent (Acton.Parser.contextError err))\n\n    handleIndentationError :: IndentationError -> IO (Either [Diagnostic String] A.Module)\n    handleIndentationError err =\n      return $ Left (errsToDiagnostics \"Indentation error\" (modNameToFilename mn) srcContent (Acton.Parser.indentationError err))\n\n-- | Parse only the module header from a SourceSnapshot.\nparseActHeaderSnapshot :: A.ModName\n                       -> FilePath\n                       -> Source.SourceSnapshot\n                       -> IO (Either [Diagnostic String] ([A.ModName], Maybe String))\nparseActHeaderSnapshot mn actFile snap = do\n  cwd <- getCurrentDirectory\n  let displayFile = makeRelative cwd actFile\n      srcContent = Source.ssText snap\n  (Right <$> do\n      (imps, mdoc) <- Acton.Parser.parseModuleHeader displayFile srcContent\n      return (A.importsOf (A.Module mn imps Nothing []), mdoc))\n    `catch` handleParseBundle displayFile srcContent\n    `catch` handleCustomParse displayFile srcContent\n    `catch` handleContextError srcContent\n    `catch` handleIndentationError srcContent\n  where\n    handleParseBundle file srcContent bundle =\n      return $ Left [Diag.parseDiagnosticFromBundle file srcContent bundle]\n\n    handleCustomParse file srcContent err =\n      return $ Left [Diag.customParseExceptionToDiagnostic file srcContent err]\n\n    handleContextError srcContent err =\n      return $ Left (errsToDiagnostics \"Context error\" (modNameToFilename mn) srcContent (Acton.Parser.contextError err))\n\n    handleIndentationError srcContent err =\n      return $ Left (errsToDiagnostics \"Indentation error\" (modNameToFilename mn) srcContent (Acton.Parser.indentationError err))\n\n-- | Parse a SourceSnapshot with a display path relative to cwd.\n-- Keeps diagnostics stable regardless of absolute paths or overlays.\nparseActSnapshot :: C.CompileOptions -> A.ModName -> FilePath -> Source.SourceSnapshot -> IO (Either [Diagnostic String] A.Module)\nparseActSnapshot opts mn actFile snap = do\n  cwd <- getCurrentDirectory\n  let displayFile = makeRelative cwd actFile\n  parseActSource opts mn displayFile (Source.ssText snap) Nothing\n\n-- | Read and parse a source file via SourceProvider (overlay-aware).\n-- Returns both the snapshot and the parsed AST for reuse by callers.\nparseActFile :: C.CompileOptions\n             -> Source.SourceProvider\n             -> A.ModName\n             -> FilePath\n             -> Maybe (ParseProgress -> IO ())\n             -> IO (Either [Diagnostic String] (Source.SourceSnapshot, A.Module))\nparseActFile opts sp mn actFile mOnProgress = do\n  snap <- Source.readSource sp actFile\n  cwd <- getCurrentDirectory\n  let displayFile = makeRelative cwd actFile\n  emod <- parseActSource opts mn displayFile (Source.ssText snap) mOnProgress\n  return $ fmap (\\m -> (snap, m)) emod\n\n-- | Read stable source metadata used for quick .ty reuse checks.\n-- Device/inode act as file identity on POSIX so metadata drift from copies or\n-- restores falls back to content hashing instead of blindly trusting mtimes.\nreadSourceFileMeta :: FilePath -> IO InterfaceFiles.SourceFileMeta\nreadSourceFileMeta path = do\n  st <- getFileStatus path\n  let mtimeNs = fileStatusMTimeNs st\n      ctimeNs = fileStatusCTimeNs st\n  return InterfaceFiles.SourceFileMeta\n    { InterfaceFiles.sfmMTimeNs = mtimeNs\n    , InterfaceFiles.sfmCTimeNs = ctimeNs\n    , InterfaceFiles.sfmSize = fromIntegral (fileSize st)\n    , InterfaceFiles.sfmDevice = Just (fromIntegral (deviceID st))\n    , InterfaceFiles.sfmInode = Just (fromIntegral (fileID st))\n    }\n  where\n    fileStatusMTimeNs st = floor (toRational (modificationTimeHiRes st) * 1000000000)\n    fileStatusCTimeNs st = floor (toRational (statusChangeTimeHiRes st) * 1000000000)\n\n\n-- Compilation tasks, chasing imported modules, compilation and building executables -----------------\n\ndata BackInput = BackInput\n  { biTypeEnv   :: Acton.Env.Env0\n  , biTypedMod  :: A.Module\n  , biSrc       :: String\n  , biImplHash  :: B.ByteString\n  }\n\ndata BackJob = BackJob\n  { bjPaths :: Paths\n  , bjOpts  :: C.CompileOptions\n  , bjInput :: BackInput\n  }\n\ndata FrontResult = FrontResult\n  { frIfaceTE  :: [(A.Name, I.NameInfo)]\n  , frImps     :: [A.ModName]\n  , frDoc      :: Maybe String\n  , frPubHash :: B.ByteString\n  , frNameHashes :: [InterfaceFiles.NameHashInfo]\n  , frFrontTime :: Maybe TimeSpec\n  , frFrontTiming :: Maybe FrontTiming\n  , frInferredSigs :: [InferredSignature]\n  , frBackJob  :: Maybe BackJob\n  }\n\ndata CompileTask        = ParseTask { name :: A.ModName, src :: String, srcBytes :: B.ByteString, sourceMeta :: Maybe InterfaceFiles.SourceFileMeta, parseImports :: [A.ModName] }\n                        | ActonTask { name :: A.ModName, src :: String, srcBytes :: B.ByteString, sourceMeta :: Maybe InterfaceFiles.SourceFileMeta, atree:: A.Module }\n                        | TyTask    { name :: A.ModName\n                                    , tyHash :: B.ByteString               -- raw source bytes hash\n                                    , tyPubHash :: B.ByteString          -- module public hash\n                                    , tyImplHash :: B.ByteString         -- module impl hash\n                                    , tyImports :: [(A.ModName, B.ByteString)] -- imports with pub hash used\n                                    , tyNameHashes :: [InterfaceFiles.NameHashInfo]\n                                    , tyRoots :: [A.Name]\n                                    , tyTests :: [String]\n                                    , tyDoc :: Maybe String\n                                    , iface :: I.NameInfo\n                                    , typed :: A.Module\n                                    }\n                        | ParseErrorTask { name :: A.ModName, parseDiagnostics :: [Diagnostic String] }\n\ninstance Show CompileTask where\n  show ParseTask{ name = mn } = \"ParseTask \" ++ modNameToString mn\n  show ActonTask{ name = mn } = \"ActonTask \" ++ modNameToString mn\n  show TyTask{ name = mn } = \"TyTask \" ++ modNameToString mn\n  show ParseErrorTask{ name = mn, parseDiagnostics = ds } =\n    \"ParseErrorTask \" ++ modNameToString mn ++ \" (\" ++ show (length ds) ++ \" diagnostics)\"\n\n-- TODO: replace binName String type with ModName just like for CompileTask.\n-- ModName is a array so a hierarchy with submodules is represented, we can then\n-- get it use joinPath (modPath) to get a path or modName to get a string\n-- representation. We need both of BinTask when generating build.zig, so it\n-- would be more robust to use that type rather than a hacky character\n-- replacement (replaceDot in genBuildZigExe)\n\ndata TaskKey = TaskKey { tkProj :: FilePath, tkMod :: A.ModName } deriving (Eq, Ord, Show)\n\ndata StageKey = ParseStage TaskKey | FrontStage TaskKey deriving (Eq, Ord, Show)\n\ndata StageSuccess = StageParsed CompileTask (Maybe TimeSpec) | StageFronted FrontResult\n\nforceHTEnv :: I.HTEnv -> ()\nforceHTEnv hte                  = HM.foldl' forceHNameInfo () hte\n  where forceHNameInfo () (I.HNModule _ te _) = forceHTEnv te\n        forceHNameInfo () hni  = hni `seq` ()\n\nforceTypeResult :: I.NameInfo -> A.Module -> Acton.Env.EnvF x -> [String] -> IO ()\nforceTypeResult nmod tchecked typeEnv tests = do\n  evaluate (rnf nmod)\n  evaluate (rnf tchecked)\n  evaluate (forceHTEnv (Acton.Env.hnames typeEnv))\n  evaluate (forceHTEnv (Acton.Env.hmodules typeEnv))\n  evaluate (rnf tests)\n\ndata GlobalTask = GlobalTask\n  { gtKey             :: TaskKey\n  , gtPaths           :: Paths\n  , gtTask            :: CompileTask\n  , gtImportProviders :: M.Map A.ModName TaskKey   -- resolved in-graph providers (if any) for imports\n  }\n\n-- | Extract imported module names from a CompileTask.\n-- TyTask uses header imports, ActonTask uses the parsed AST, and parse errors\n-- yield no imports.\nimportsOf :: CompileTask -> [A.ModName]\nimportsOf (ParseTask _ _ _ _ imps) = imps\nimportsOf (ActonTask _ _ _ _ m) = A.importsOf m\nimportsOf (TyTask { tyImports = ms }) = map fst ms\nimportsOf (ParseErrorTask _ _) = []\n\n\n-- | Resolve imports to in-graph providers using project search order.\n-- This chooses the first project in the search order that declares the module,\n-- producing TaskKeys for dependency edges.\nresolveProviders :: [FilePath] -> M.Map FilePath (Data.Set.Set A.ModName) -> [A.ModName] -> M.Map A.ModName TaskKey\nresolveProviders order modSets imps =\n    M.fromList $ catMaybes $ map (\\mn -> fmap (\\p -> (mn, TaskKey p mn)) (findProvider mn)) imps\n  where\n    findProvider mn = listToMaybe [ p | p <- order, maybe False (Data.Set.member mn) (M.lookup p modSets) ]\n\n\n-- | Build GlobalTasks for all discovered projects.\n-- Crawls project sources, resolves provider edges, and optionally limits the\n-- seed set to specific files to keep the DAG small for incremental builds.\nbuildGlobalTasks :: Source.SourceProvider\n                 -> C.GlobalOptions\n                 -> C.CompileOptions\n                 -> M.Map FilePath ProjCtx\n                 -> Maybe [String]                  -- optional seed source files; Nothing = all modules\n                 -> IO ([GlobalTask], M.Map FilePath (Data.Set.Set A.ModName))\nbuildGlobalTasks sp gopts opts projMap mSeeds = do\n    perProj <- forM (M.elems projMap) $ \\ctx -> do\n                  mods <- enumerateProjectModules ctx\n                  return (ctx, mods)\n    let modMaps = M.fromList [ (projRoot ctx, M.fromList [ (mn, actFile) | (actFile, mn) <- mods ]) | (ctx, mods) <- perProj ]\n        modSets = M.map Data.Set.fromList (M.map M.keys modMaps)\n        orderCache = M.fromList [ (projRoot ctx, projRoot ctx : projDepClosure projMap (projRoot ctx)) | (ctx, _) <- perProj ]\n        allKeys = [ TaskKey (projRoot ctx) mn | (ctx, mods) <- perProj, (_, mn) <- mods ]\n    seedKeys <- case mSeeds of\n                  Nothing -> return allKeys\n                  Just files -> do\n                    absFiles <- mapM canonicalizePath files\n                    let pathIndex = M.fromList [ (actFile, TaskKey (projRoot ctx) mn) | (ctx, mods) <- perProj, (actFile, mn) <- mods ]\n                        found = mapMaybe (`M.lookup` pathIndex) absFiles\n                    return (if null found then allKeys else found)\n    tasks <- go modMaps modSets orderCache Data.Set.empty seedKeys []\n    return (reverse tasks, modSets)\n  where\n    go modMaps modSets orderCache seen [] acc = return acc\n    go modMaps modSets orderCache seen (k:qs) acc\n      | Data.Set.member k seen = go modMaps modSets orderCache seen qs acc\n      | otherwise =\n          case M.lookup (tkProj k) modMaps >>= M.lookup (tkMod k) of\n            Nothing -> go modMaps modSets orderCache (Data.Set.insert k seen) qs acc\n            Just actFile -> do\n              let ctx = projMap M.! tkProj k\n              paths <- pathsForModule opts projMap ctx (tkMod k)\n              task  <- readModuleTask sp gopts opts paths actFile\n              let order = M.findWithDefault [tkProj k] (tkProj k) orderCache\n                  providers = resolveProviders order modSets (importsOf task)\n                  newKeys = M.elems providers\n                  acc' = GlobalTask { gtKey = k\n                                    , gtPaths = paths\n                                    , gtTask = task\n                                    , gtImportProviders = providers\n                                    } : acc\n              go modMaps modSets orderCache (Data.Set.insert k seen) (qs ++ newKeys) acc'\n\n\n-- | Select the subgraph needed for a given build request.\n-- Maps file paths to TaskKeys, adds __builtin__, and computes the reachable\n-- dependency closure.\nselectNeededTasks :: Paths -> FilePath -> [GlobalTask] -> [FilePath] -> IO [GlobalTask]\nselectNeededTasks pathsRoot rootProj globalTasks srcFiles = do\n    requestedKeys <- catMaybes <$> mapM (lookupTaskKey globalTasks) srcFiles\n    let wantedNames   = map takeFileName srcFiles\n        requestedKeys' = if null requestedKeys\n                           then [ gtKey t\n                                | t <- globalTasks\n                                , takeFileName (srcFile (gtPaths t) (tkMod (gtKey t))) `elem` wantedNames\n                                ]\n                           else requestedKeys\n        builtinKeys = [ gtKey t | t <- globalTasks, tkMod (gtKey t) == A.modName [\"__builtin__\"] ]\n        startKeys   = if null requestedKeys' then map gtKey globalTasks else requestedKeys' ++ builtinKeys\n        depMapSet   = M.fromList [ (gtKey t, Data.Set.fromList (M.elems (gtImportProviders t))) | t <- globalTasks ]\n        neededKeys  = reachable depMapSet (Data.Set.fromList startKeys)\n    return [ t | t <- globalTasks, Data.Set.member (gtKey t) neededKeys ]\n  where\n    lookupTaskKey ts f = do\n      absF <- canonicalizePath f\n      let byPath = listToMaybe [ gtKey t\n                               | t <- ts\n                               , let k = gtKey t\n                                     pths = gtPaths t\n                               , srcFile pths (tkMod k) == absF\n                               ]\n      case byPath of\n        Just k -> return (Just k)\n        Nothing -> do\n          mn <- moduleNameFromFile (srcDir pathsRoot) absF\n          return $ listToMaybe [ gtKey t\n                               | t <- ts\n                               , tkProj (gtKey t) == rootProj\n                               , tkMod (gtKey t) == mn\n                               ]\n\n    reachable depMap start = go (Data.Set.toList start) Data.Set.empty\n      where\n        go [] seen = seen\n        go (k:ks) seen =\n          if Data.Set.member k seen\n            then go ks seen\n            else\n              let deps = Data.Set.toList (M.findWithDefault Data.Set.empty k depMap)\n              in go (deps ++ ks) (Data.Set.insert k seen)\n\n-- | Select the minimal subgraph affected by a set of changed files.\n-- Computes reverse dependencies so we rebuild dependents while keeping\n-- unrelated modules untouched.\nselectAffectedTasks :: [GlobalTask] -> [FilePath] -> IO [GlobalTask]\nselectAffectedTasks globalTasks changedFiles = do\n    if null changedFiles\n      then return globalTasks\n      else do\n        absChanged <- mapM normalizePathSafe changedFiles\n        taskPaths <- forM globalTasks $ \\t -> do\n          let k = gtKey t\n              pths = gtPaths t\n          p <- normalizePathSafe (srcFile pths (tkMod k))\n          return (p, k)\n        let pathIndex = M.fromList taskPaths\n            changedKeys = catMaybes [ M.lookup p pathIndex | p <- absChanged ]\n        if null changedKeys\n          then return globalTasks\n          else do\n            let taskKeys = Data.Set.fromList (map gtKey globalTasks)\n                depMap = M.fromList\n                  [ (gtKey t, filter (`Data.Set.member` taskKeys) (M.elems (gtImportProviders t)))\n                  | t <- globalTasks\n                  ]\n                revMap = foldl' (\\acc (k, ds) ->\n                                  foldl' (\\a d -> M.insertWith (++) d [k] a) acc ds)\n                                M.empty\n                                (M.toList depMap)\n                affected = reverseClosure revMap (Data.Set.fromList changedKeys)\n            -- Keep original provider mappings so unchanged imports can still\n            -- resolve via cached interfaces during incremental checks.\n            return [ t | t <- globalTasks, Data.Set.member (gtKey t) affected ]\n  where\n    reverseClosure revMap start = go start (Data.Set.toList start)\n      where\n        go seen [] = seen\n        go seen (k:ks) =\n          let ds = M.findWithDefault [] k revMap\n              new = filter (`Data.Set.notMember` seen) ds\n              seen' = foldl' (flip Data.Set.insert) seen new\n          in go seen' (ks ++ new)\n\n\ndata ModuleHead\n  = TyHead\n      { mhName       :: A.ModName\n      , mhSrcHash    :: B.ByteString\n      , mhPubHash    :: B.ByteString\n      , mhImplHash   :: B.ByteString\n      , mhTyImports  :: [(A.ModName, B.ByteString)]\n      , mhNameHashes :: [InterfaceFiles.NameHashInfo]\n      , mhRoots      :: [A.Name]\n      , mhTests      :: [String]\n      , mhDoc        :: Maybe String\n      }\n  | SrcHead\n      { mhName       :: A.ModName\n      , mhSrc        :: String\n      , mhBytes      :: B.ByteString\n      , mhSourceMeta :: Maybe InterfaceFiles.SourceFileMeta\n      , mhSrcImports :: [A.ModName]\n      , mhDoc        :: Maybe String\n      }\n  | HeadError\n      { mhName        :: A.ModName\n      , mhDiagnostics :: [Diagnostic String]\n      }\n\n-- | Read the cheap module header used by discovery and doc indexing.\n-- Reuse a valid .ty header when possible; otherwise read the source snapshot\n-- and parse only the module docstring plus imports.\nreadModuleHeader :: Source.SourceProvider\n                 -> C.GlobalOptions\n                 -> C.CompileOptions\n                 -> Paths\n                 -> String\n                 -> IO ModuleHead\nreadModuleHeader sp gopts opts paths actFile = do\n    let mn      = modName paths\n        tyFile  = outBase paths mn ++ \".ty\"\n    tyExists <- doesFileExist tyFile\n    if not tyExists\n      then readSourceHead mn\n      else do\n        -- .ty exists: read the cached header and validate it against compiler\n        -- compatibility plus source metadata/content as needed.\n        hdrE <- (try :: IO a -> IO (Either SomeException a)) $ InterfaceFiles.readHeader tyFile\n        case hdrE of\n          Left _ -> readSourceHead mn\n          Right (cachedSourceMeta, moduleSrcBytesHash, modulePubHash, moduleImplHash, imps, nameHashes, roots, tests, mdoc) -> do\n            tyStatus <- getFileStatus tyFile\n            let tyMTimeNs = fileStatusMTimeNs tyStatus\n            newCompiler <- compilerNewerThan tyMTimeNs\n            mOverlay <- Source.spReadOverlay sp actFile\n            case mOverlay of\n              Just snap ->\n                if newCompiler\n                  then sourceHeadFromSnapshot mn snap\n                  else verifyOrParse mn snap moduleSrcBytesHash modulePubHash moduleImplHash cachedSourceMeta Nothing imps nameHashes roots tests mdoc\n              Nothing -> do\n                if newCompiler\n                  then readSourceHead mn\n                  else do\n                    currentSourceMeta <- readSourceFileMeta actFile\n                    if canReuseHeader cachedSourceMeta currentSourceMeta tyMTimeNs\n                      then return (mkTyHead mn moduleSrcBytesHash modulePubHash moduleImplHash imps nameHashes roots tests mdoc)\n                      else do\n                        snap <- Source.spReadFile sp actFile\n                        verifyOrParse mn snap moduleSrcBytesHash modulePubHash moduleImplHash cachedSourceMeta (Just currentSourceMeta) imps nameHashes roots tests mdoc\n  where\n    fileStatusMTimeNs st = floor (toRational (modificationTimeHiRes st) * 1000000000)\n\n    mkTyHead mn moduleSrcBytesHash modulePubHash moduleImplHash imps nameHashes roots tests mdoc =\n      TyHead\n        { mhName       = mn\n        , mhSrcHash    = moduleSrcBytesHash\n        , mhPubHash    = modulePubHash\n        , mhImplHash   = moduleImplHash\n        , mhTyImports  = imps\n        , mhNameHashes = nameHashes\n        , mhRoots      = roots\n        , mhTests      = tests\n        , mhDoc        = mdoc\n        }\n\n    metadataMatches cached current =\n      case cached of\n        Nothing -> False\n        Just meta -> meta == current\n\n    canReuseHeader cached current tyMTimeNs =\n      metadataMatches cached current\n      && InterfaceFiles.sfmMTimeNs current < tyMTimeNs\n\n    readSourceHead mn = do\n      snap <- Source.readSource sp actFile\n      sourceHeadFromSnapshot mn snap\n\n    sourceHeadFromSnapshot mn snap = do\n      headerRes <- parseActHeaderSnapshot mn actFile snap\n      case headerRes of\n        Left diags -> return $ HeadError mn diags\n        Right (imps, mdoc) -> do\n          mSourceMeta <- snapshotSourceMeta snap\n          return $ SrcHead mn (Source.ssText snap) (Source.ssBytes snap) mSourceMeta imps mdoc\n\n    snapshotSourceMeta snap\n      | Source.ssIsOverlay snap = return Nothing\n      | otherwise = Just <$> readSourceFileMeta actFile\n\n    compilerNewerThan tyMTimeNs\n      | C.ignore_compiler_version opts = return False\n      | otherwise = do\n          exePathE <- (try getExecutablePath :: IO (Either SomeException FilePath))\n          case exePathE of\n            Left _ -> return False\n            Right exePath -> do\n              exeStatusE <- (try (getFileStatus exePath) :: IO (Either SomeException FileStatus))\n              case exeStatusE of\n                Left _ -> return False\n                Right exeStatus -> return (fileStatusMTimeNs exeStatus > tyMTimeNs)\n\n    refreshCachedSourceMeta currentSourceMeta = do\n      let tyFilePath = outBase paths (modName paths) ++ \".ty\"\n      tyRes <- (try :: IO a -> IO (Either SomeException a)) $ InterfaceFiles.readFile tyFilePath\n      case tyRes of\n        Left _ -> return ()\n        Right (_ms, nmod, tmod, _oldSourceMeta, srcHash, pubHash, implHash, imps, nameHashes, roots, tests, mdoc) ->\n          InterfaceFiles.writeFile tyFilePath srcHash pubHash implHash currentSourceMeta imps nameHashes roots tests mdoc nmod tmod\n\n    verifyOrParse mn snap moduleSrcBytesHash modulePubHash moduleImplHash cachedSourceMeta currentSourceMeta imps nameHashes roots tests mdoc = do\n      let curHash = SHA256.hash (Source.ssBytes snap)\n          short8 bs = take 8 (B.unpack $ Base16.encode bs)\n          same = curHash == moduleSrcBytesHash\n      when (C.verbose gopts && Source.ssIsOverlay snap) $ do\n        actTime <- Source.spGetModTime sp actFile\n        tyTime <- getModificationTime (outBase paths mn ++ \".ty\")\n        let len = B.length (Source.ssBytes snap)\n        putStrLn (\"[debug] readModuleHeader \" ++ modNameToString mn\n                  ++ \" act=\" ++ show actTime\n                  ++ \" ty=\" ++ show tyTime\n                  ++ \" hash=\" ++ short8 curHash\n                  ++ \" header=\" ++ short8 moduleSrcBytesHash\n                  ++ \" len=\" ++ show len\n                  ++ if same then \" (match)\" else \" (diff)\")\n      if same\n        then do\n          when (currentSourceMeta /= Nothing && currentSourceMeta /= cachedSourceMeta) $\n            refreshCachedSourceMeta currentSourceMeta\n          return (mkTyHead mn moduleSrcBytesHash modulePubHash moduleImplHash imps nameHashes roots tests mdoc)\n        else sourceHeadFromSnapshot mn snap\n\n-- | Prepare a task for dependency graph construction.\n-- The full source parse is deferred for modules whose .ty header cannot be\n-- reused, but discovery still gets accurate imports from the source header.\nreadModuleTask :: Source.SourceProvider -> C.GlobalOptions -> C.CompileOptions -> Paths -> String -> IO CompileTask\nreadModuleTask sp gopts opts paths actFile = do\n  h <- readModuleHeader sp gopts opts paths actFile\n  return $ case h of\n    TyHead{ mhName = mn\n          , mhSrcHash = srcHash\n          , mhPubHash = pubHash\n          , mhImplHash = implHash\n          , mhTyImports = imps\n          , mhNameHashes = nameHashes\n          , mhRoots = roots\n          , mhTests = tests\n          , mhDoc = mdoc\n          } ->\n      let nmodStub = I.NModule [] [] mdoc\n          tmodStub = A.Module mn [] mdoc []\n      in TyTask { name      = mn\n                , tyHash     = srcHash\n                , tyPubHash  = pubHash\n                , tyImplHash = implHash\n                , tyImports  = imps\n                , tyNameHashes = nameHashes\n                , tyRoots   = roots\n                , tyTests   = tests\n                , tyDoc     = mdoc\n                , iface     = nmodStub\n                , typed     = tmodStub }\n    SrcHead{ mhName = mn\n           , mhSrc = srcContent\n           , mhBytes = bytes\n           , mhSourceMeta = mSourceMeta\n           , mhSrcImports = imps\n           } ->\n      ParseTask mn srcContent bytes mSourceMeta imps\n    HeadError{ mhName = mn, mhDiagnostics = diags } ->\n      ParseErrorTask mn diags\n\nreadModuleDoc :: Source.SourceProvider\n              -> C.GlobalOptions\n              -> C.CompileOptions\n              -> Paths\n              -> String\n              -> IO (Maybe (A.ModName, Maybe String))\nreadModuleDoc sp gopts opts paths actFile = do\n  h <- readModuleHeader sp gopts opts paths actFile\n  return $ case h of\n    TyHead{ mhName = mn, mhDoc = mdoc } -> Just (mn, mdoc)\n    SrcHead{ mhName = mn, mhDoc = mdoc } -> Just (mn, mdoc)\n    HeadError{} -> Nothing\n\n-- | Materialize a source-backed task into a fully parsed ActonTask.\n-- ParseTask reuses the snapshot captured during graph discovery; TyTask reparses\n-- from the current source file because the cached header was deemed stale.\nmaterializeTask :: C.CompileOptions\n                -> Source.SourceProvider\n                -> A.ModName\n                -> FilePath\n                -> Maybe (ParseProgress -> IO ())\n                -> CompileTask\n                -> IO CompileTask\nmaterializeTask opts sp mn actFile mOnProgress task =\n  case task of\n    ActonTask{} -> return task\n    ParseErrorTask{} -> return task\n    ParseTask{ src = srcContent, srcBytes = bytes, sourceMeta = mSourceMeta } -> do\n      emod <- parseStoredSource mn actFile srcContent\n      case emod of\n        Left diags -> return (ParseErrorTask mn diags)\n        Right m -> return (ActonTask mn srcContent bytes mSourceMeta m)\n    TyTask{} -> do\n      parsedRes <- parseActFile opts sp mn actFile mOnProgress\n      case parsedRes of\n        Left diags -> return (ParseErrorTask mn diags)\n        Right (snap, m) -> do\n          mSourceMeta <- if Source.ssIsOverlay snap then return Nothing else Just <$> readSourceFileMeta actFile\n          return $ ActonTask mn (Source.ssText snap) (Source.ssBytes snap) mSourceMeta m\n  where\n    parseStoredSource mn' file srcContent = do\n      cwd <- getCurrentDirectory\n      let displayFile = makeRelative cwd file\n      parseActSource opts mn' displayFile srcContent mOnProgress\n\n\n-- | Recursively read imports for a set of tasks within the same project.\n-- Any missing module is added by parsing or reading its .ty header via\n-- readModuleTask, yielding a self-contained task list.\nreadImports :: Source.SourceProvider -> C.GlobalOptions -> C.CompileOptions -> Paths -> [CompileTask] -> IO [CompileTask]\nreadImports sp gopts opts paths tasks = do\n    let tasks' = filter (\\t -> name t /= modName paths) tasks\n    chaseRecursively tasks' [] (concatMap importsOf tasks')\n  where\n    readAFile tasks mn = case lookUp mn tasks of\n      Just _ -> return Nothing\n      Nothing -> do\n        let actFile = srcFile paths mn\n        ok <- doesFileExist actFile\n        if ok\n          then do\n            p <- findPaths actFile opts\n            t <- readModuleTask sp gopts opts p actFile\n            return (Just t)\n          else return Nothing\n\n    lookUp mn (t:ts)\n      | name t == mn = Just t\n      | otherwise = lookUp mn ts\n    lookUp _ [] = Nothing\n\n    chaseRecursively tasks mns [] = return tasks\n    chaseRecursively tasks mns (imn:imns)\n      | imn `elem` mns = chaseRecursively tasks mns imns\n      | otherwise = do\n          t <- readAFile tasks imn\n          chaseRecursively (maybe tasks (:tasks) t)\n                           (imn:mns)\n                           (imns ++ concatMap importsOf (maybe [] (:[]) t))\n\n\n-- | Decide whether to suppress per-module timing/log output.\n-- We also treat any alternate output mode (parse/sigs/cgen/etc) as quiet.\nquiet :: C.GlobalOptions -> C.CompileOptions -> Bool\nquiet gopts opts = C.quiet gopts || altOutput opts\n\n-- | Read an interface from a .ty file and return its NameInfo and public hash.\n-- This is used when a module is deemed fresh and we want to avoid reparsing.\nreadIfaceFromTy :: Paths -> A.ModName -> String -> Maybe B.ByteString -> IO (Either [Diagnostic String] ([A.ModName], [(A.Name, I.NameInfo)], Maybe String, B.ByteString))\nreadIfaceFromTy paths mn src mHash = do\n    mty <- Acton.Env.findTyFile (searchPath paths) mn\n    case mty of\n      Nothing -> return $ Left (missingIfaceDiagnostics mn src mn)\n      Just tyF -> do\n        fileRes <- (try :: IO a -> IO (Either SomeException a)) $ InterfaceFiles.readFile tyF\n        case fileRes of\n          Left _ -> return $ Left (missingIfaceDiagnostics mn src mn)\n          Right (_ms, nmod, _tmod, _sourceMeta, _srcH, _pubH, _implH, _imps, _nameHashes, _roots, _tests, _tm) -> do\n            let I.NModule ms teFull mdoc = nmod\n                te = publicIfaceTE teFull\n            ih <- case mHash of\n                    Just h -> return h\n                    Nothing -> do\n                      hdrE <- (try :: IO a -> IO (Either SomeException a)) $ InterfaceFiles.readHeader tyF\n                      case hdrE of\n                        Right (_sourceMetaH, _srcH, ihash, _implH, _impsH, _nameHashesH, _rootsH, _testsH, _docH) -> return ihash\n                        _ -> return B.empty\n            return $ Right (ms, te, mdoc, ih)\n\n\n-- | Snapshot of expected/recorded impl hashes for generated code.\ndata CodegenStatus = CodegenStatus\n  { csExpected :: String\n  , csC :: Maybe String\n  , csH :: Maybe String\n  }\n\n-- | Header prefix used to tag generated code with the module impl hash.\ncodegenHashTag :: String\ncodegenHashTag = \"/* Acton impl hash:\"\n\n-- | Parse a tagged hash line from generated output.\nextractCodegenHash :: String -> Maybe String\nextractCodegenHash line = do\n  rest <- Data.List.stripPrefix codegenHashTag line\n  let rest' = dropWhile isSpace rest\n      hex = takeWhile isHexDigit rest'\n  if null hex then Nothing else Just hex\n\n-- | Read the tagged hash from a generated file, if present.\nreadCodegenHash :: FilePath -> IO (Maybe String)\nreadCodegenHash path = do\n  exists <- doesFileExist path\n  if not exists\n    then return Nothing\n    else do\n      res <- (try :: IO a -> IO (Either SomeException a)) $ withFile path ReadMode hGetLine\n      case res of\n        Left _ -> return Nothing\n        Right line -> return (extractCodegenHash line)\n\n-- | Collect codegen hash status for a module.\ncodegenStatus :: Paths -> A.ModName -> B.ByteString -> IO CodegenStatus\ncodegenStatus paths mn implHash = do\n  let expected = B.unpack $ Base16.encode implHash\n      cFile = outBase paths mn ++ \".c\"\n      hFile = outBase paths mn ++ \".h\"\n  cHash <- readCodegenHash cFile\n  hHash <- readCodegenHash hFile\n  return CodegenStatus { csExpected = expected, csC = cHash, csH = hHash }\n\n-- | Check whether generated .c/.h hashes match the expected impl hash.\ncodegenUpToDate :: CodegenStatus -> Bool\ncodegenUpToDate status =\n  csC status == Just (csExpected status) && csH status == Just (csExpected status)\n\n-- | Format a short delta message for stale codegen.\nformatCodegenDelta :: CodegenStatus -> String\nformatCodegenDelta status =\n  let expected = take 8 (csExpected status)\n      short actual = maybe \"missing\" (take 8) actual\n  in case (csC status, csH status) of\n       (Just c, Just h) | c == h ->\n         \" {impl \" ++ take 8 c ++ \" -> \" ++ expected ++ \"}\"\n       _ ->\n         \" {impl c \" ++ short (csC status) ++ \" -> \" ++ expected\n         ++ \", h \" ++ short (csH status) ++ \" -> \" ++ expected ++ \"}\"\n\n-- | Run the front passes for a single module.\n-- Builds the environment, runs kinds/types, computes per-name src/pub/impl\n-- hashes plus module pub/impl hashes, and writes the .ty header. Returns the\n-- front result plus a BackJob for later passes when compilation is needed.\nrunFrontPasses :: C.GlobalOptions\n               -> C.CompileOptions\n               -> Paths\n               -> Acton.Env.Env0\n               -> A.Module\n               -> String\n               -> B.ByteString\n               -> Maybe InterfaceFiles.SourceFileMeta\n               -> (A.ModName -> IO (Maybe B.ByteString))\n               -> (A.ModName -> IO (Maybe (M.Map A.Name InterfaceFiles.NameHashInfo)))\n               -> (FrontPassProgress -> IO ())\n               -> IO (Either [Diagnostic String] FrontResult)\nrunFrontPasses gopts opts paths env0 parsed srcContent srcBytes sourceMeta resolveImportHash resolveNameHashMap onFrontProgress = do\n  createDirectoryIfMissing True (getModPath (projTypes paths) mn)\n  core\n    `catch` handleGeneral\n    `catch` handleCompilation\n    `catch` handleTypeErrors\n    `catch` handleTypeError\n  where\n    mn = A.modname parsed\n    filename = modNameToFilename mn\n    outbase = outBase paths mn\n    absSrcBase = srcBase paths mn\n    actFile = absSrcBase ++ \".act\"\n    prettyAstStyle = style { mode = PageMode, lineLength = 120, ribbonsPerLine = 1.0 }\n\n    handleGeneral :: GeneralError -> IO (Either [Diagnostic String] FrontResult)\n    handleGeneral err =\n      return $ Left (errsToDiagnostics \"Compilation error\" filename srcContent (generalError err))\n\n    handleCompilation :: Acton.Env.CompilationError -> IO (Either [Diagnostic String] FrontResult)\n    handleCompilation err =\n      return $ Left (errsToDiagnostics \"Compilation error\" filename srcContent (Acton.Env.compilationError err))\n\n    handleTypeError :: Acton.TypeEnv.TypeError -> IO (Either [Diagnostic String] FrontResult)\n    handleTypeError err =\n      return $ Left [Acton.TypeEnv.mkErrorDiagnostic filename srcContent (Acton.TypeEnv.typeReport err filename srcContent)]\n\n    handleTypeErrors :: Acton.Types.TypeErrors -> IO (Either [Diagnostic String] FrontResult)\n    handleTypeErrors (Acton.Types.TypeErrors errs) =\n      return $ Left [ Acton.TypeEnv.mkErrorDiagnostic filename srcContent (Acton.TypeEnv.typeReport err filename srcContent)\n                    | err <- errs\n                    ]\n\n    resolveImportHashes :: [A.ModName] -> IO (Either [Diagnostic String] [(A.ModName, B.ByteString)])\n    resolveImportHashes mrefs = do\n      resolved <- forM mrefs $ \\mref -> do\n        mh <- resolveImportHash mref\n        case mh of\n          Just ih -> return (Right (mref, ih))\n          Nothing -> return (Left (missingIfaceDiagnostics mn srcContent mref))\n      let (errs, vals) = partitionEithers resolved\n      if null errs\n        then return (Right vals)\n        else return (Left (concat errs))\n\n    missingNameHashDiagnostics :: A.QName -> [Diagnostic String]\n    missingNameHashDiagnostics qn =\n      errsToDiagnostics \"Compilation error\" filename srcContent\n        [(NoLoc, \"Hash info missing for \" ++ prstr qn)]\n\n    missingDepHashDiagnostics :: String -> A.Name -> SrcLoc -> A.QName -> [Diagnostic String]\n    missingDepHashDiagnostics label owner loc qn =\n      errsToDiagnostics \"Compilation error\" filename srcContent\n        [(loc, label ++ \" hash missing for \" ++ prstr qn ++ \" (used by \" ++ A.nstr owner ++ \")\")]\n\n    resolveNameHashMaps :: [A.ModName] -> IO (Either [Diagnostic String] (M.Map A.ModName (M.Map A.Name InterfaceFiles.NameHashInfo)))\n    resolveNameHashMaps mrefs = do\n      resolved <- forM mrefs $ \\mref -> do\n        mh <- resolveNameHashMap mref\n        case mh of\n          Just hm -> return (Right (mref, hm))\n          Nothing -> return (Left (missingIfaceDiagnostics mn srcContent mref))\n      let (errs, vals) = partitionEithers resolved\n      if null errs\n        then return (Right (M.fromList vals))\n        else return (Left (concat errs))\n\n    resolveDepHashes :: String\n                     -> (InterfaceFiles.NameHashInfo -> B.ByteString)\n                     -> M.Map A.Name [A.QName]\n                     -> M.Map A.ModName (M.Map A.Name InterfaceFiles.NameHashInfo)\n                     -> M.Map A.Name SrcLoc\n                     -> Either [Diagnostic String] (M.Map A.Name [(A.QName, B.ByteString)])\n    resolveDepHashes label getHash deps extMaps nameLocs =\n      let resolveQName owner qn = case qn of\n            A.GName m n -> lookupName owner m n\n            A.QName m n -> lookupName owner m n\n            A.NoQ _ -> Left (missingNameHashDiagnostics qn)\n          lookupName owner m n =\n            case M.lookup m extMaps of\n              Nothing -> Left (missingIfaceDiagnostics mn srcContent m)\n              Just hm ->\n                case M.lookup n hm of\n                  Just info ->\n                    let h = getHash info\n                        loc = M.findWithDefault NoLoc owner nameLocs\n                    in if B.null h\n                         then Left (missingDepHashDiagnostics label owner loc (A.GName m n))\n                         else Right (Just (A.GName m n, h))\n                  Nothing -> Left (missingNameHashDiagnostics (A.GName m n))\n          resolveForName (n, qns) =\n            let qnsSorted = Data.List.sortOn Hashing.qnameKey (Data.Set.toList (Data.Set.fromList qns))\n                resolved = map (resolveQName n) qnsSorted\n                (errs, vals) = partitionEithers resolved\n            in if null errs then Right (n, catMaybes vals) else Left (concat errs)\n          (errs, vals) = partitionEithers (map resolveForName (M.toList deps))\n      in if null errs then Right (M.fromList vals) else Left (concat errs)\n\n    emitFrontProgress pass completed total current =\n      onFrontProgress FrontPassProgress\n        { fppPass = pass\n        , fppCompleted = completed\n        , fppTotal = total\n        , fppCurrent = current\n        }\n\n    core = do\n      timeStart <- getTime Monotonic\n      let isRoot = mn == modName paths\n      when (C.parse opts && isRoot) $\n        dump mn \"parse\" (Pretty.print parsed)\n      when (C.parse_ast opts && isRoot) $\n        dump mn \"parse-ast\" (renderStyle prettyAstStyle (ppDoc parsed))\n\n      typeStmtTimingsRef <- newIORef ([] :: [TypeStmtTiming])\n      inferredSigsRef <- newIORef ([] :: [InferredSignature])\n      typeActiveRef <- newIORef Nothing\n      let onTypeProgress total completed current names _weight = do\n            now <- getTime Monotonic\n            mActive <- readIORef typeActiveRef\n            forM_ mActive $ \\(label, bindNames, activeTotal, t0) ->\n              modifyIORef' typeStmtTimingsRef\n                ( TypeStmtTiming\n                    { tstCompleted = completed\n                    , tstTotal = activeTotal\n                    , tstLabel = label\n                    , tstNames = bindNames\n                    , tstTime = now - t0\n                    }\n                : )\n            case current of\n              Just label -> writeIORef typeActiveRef (Just (label, names, total, now))\n              Nothing -> writeIORef typeActiveRef Nothing\n            emitFrontProgress FrontPassTypes completed total current\n          onInferredSignature names sig =\n            modifyIORef' inferredSigsRef (InferredSignature names sig :)\n          inferredSignatureCb =\n            if C.timing gopts || C.verbose gopts\n              then Just onInferredSignature\n              else Nothing\n\n      env <- Acton.Env.mkEnv (searchPath paths) env0 parsed\n      timeEnv <- getTime Monotonic\n\n      emitFrontProgress FrontPassKinds 0 1 Nothing\n      kchecked <- Acton.Kinds.check env parsed\n      emitFrontProgress FrontPassKinds 1 1 Nothing\n      iff (C.kinds opts && isRoot) $ dump mn \"kinds\" (Pretty.print kchecked)\n      timeKindsCheck <- getTime Monotonic\n\n      -- Type-check and return both the typed AST and the interface NameInfo.\n      (nmod,tchecked,typeEnv,tests) <- Acton.Types.reconstruct (Just onTypeProgress) inferredSignatureCb env kchecked\n      forceTypeResult nmod tchecked typeEnv tests\n      -- Module-level src hash uses raw bytes so any source edit forces re-parse.\n      let moduleSrcBytesHash = SHA256.hash srcBytes\n      -- Store roots so later builds can discover entry points without reparse.\n      let I.NModule imps fullIface mdoc = nmod\n          publicIface = publicIfaceTE fullIface\n      let roots = [ n | (n,i) <- fullIface, rootEligible i ]\n      -- Import hashes are recorded in the .ty header so dep changes can be detected.\n      impsRes <- resolveImportHashes imps\n      case impsRes of\n        Left diags -> return (Left diags)\n        Right impsWithHash -> do\n          -- Extract top-level items from parsed and typed ASTs for per-name hashes.\n          let srcItems = Hashing.topLevelItems parsed\n              implItems = Hashing.topLevelItems tchecked\n              -- src hashes come only from parsed AST fragments.\n              nameSrcHashes = Hashing.nameHashesFromItems srcItems\n              -- impl hashes are derived from the typed AST bodies. this is the\n              -- local function hash, implDeps are added later\n              nameImplHashes = Hashing.nameHashesFromItems implItems\n              -- NameInfo defines the full local environment for this module.\n              nameInfoMap = M.fromList fullIface\n              nameSrcKeys = M.keysSet nameSrcHashes\n              nameImplKeys = M.keysSet nameImplHashes\n              nameKeys = Data.Set.union nameSrcKeys nameImplKeys\n              nameLocsParsed = M.fromListWith (\\a _ -> a)\n                [ (n, A.dloc d) | Hashing.TLDecl n d <- srcItems ] `M.union`\n                M.fromListWith (\\a _ -> a)\n                [ (n, A.sloc s) | Hashing.TLStmt n s <- srcItems ]\n              nameLocsTyped = M.fromListWith (\\a _ -> a)\n                [ (n, A.dloc d) | Hashing.TLDecl n d <- implItems ] `M.union`\n                M.fromListWith (\\a _ -> a)\n                [ (n, A.sloc s) | Hashing.TLStmt n s <- implItems ]\n              nameLocs = M.union nameLocsParsed nameLocsTyped\n          -- pubSigDeps: signature-level deps from NameInfo (types only).\n          let isDerivedName n = case n of\n                A.Derived{} -> True\n                _ -> False\n              isDerivedQName qn = case qn of\n                A.GName _ n -> isDerivedName n\n                A.QName _ n -> isDerivedName n\n                A.NoQ n -> isDerivedName n\n              dropDerived = filter (not . isDerivedQName)\n              pubSigDepsRaw = M.fromList\n                [ (n, dropDerived (Names.freeQ info)) | (n, info) <- M.toList nameInfoMap ]\n              -- implDeps: term-level deps from typed bodies.\n              implDepsRaw = Hashing.implDepsFromItems implItems\n              -- pubDeps include signature deps plus any term-level deps for reuse in pubHash.\n              -- Derived names are internal and should never require a pub hash.\n              pubDepsRaw = M.map dropDerived (M.unionWith (++) pubSigDepsRaw implDepsRaw)\n              hashEnv = setMod mn env\n              -- Split deps into local (same module) vs external (qualified) names.\n              (pubSigLocalDeps, pubSigExtDeps) = Hashing.splitDeps mn hashEnv nameKeys pubSigDepsRaw\n              (_, pubExtDeps) = Hashing.splitDeps mn hashEnv nameKeys pubDepsRaw\n              (implLocalDeps, implExtDeps) = Hashing.splitDeps mn hashEnv nameKeys implDepsRaw\n              -- Load .ty maps for any external modules referenced by deps.\n              extMods = Data.Set.toList (Hashing.externalModules pubExtDeps `Data.Set.union` Hashing.externalModules implExtDeps)\n          extMapsRes <- resolveNameHashMaps extMods\n          case extMapsRes of\n            Left diags -> return (Left diags)\n            Right extMaps -> do\n              -- Resolve external deps to their recorded hashes.\n              let pubSigExtRes = resolveDepHashes \"pub\" InterfaceFiles.nhPubHash pubSigExtDeps extMaps nameLocs\n                  pubExtRes = resolveDepHashes \"pub\" InterfaceFiles.nhPubHash pubExtDeps extMaps nameLocs\n                  implExtRes = resolveDepHashes \"impl\" InterfaceFiles.nhImplHash implExtDeps extMaps nameLocs\n              case (pubSigExtRes, pubExtRes, implExtRes) of\n                (Left diags, _, _) -> return (Left diags)\n                (_, Left diags, _) -> return (Left diags)\n                (_, _, Left diags) -> return (Left diags)\n                (Right pubSigExtHashes, Right pubExtHashes, Right implExtHashes) -> do\n                  -- Build per-name hash records (src/pub/impl + deps) for .ty.\n                  let nameHashes =\n                        Hashing.buildNameHashes\n                          nameKeys\n                          nameSrcHashes\n                          nameImplHashes\n                          nameInfoMap\n                          pubSigLocalDeps\n                          pubSigExtHashes\n                          implLocalDeps\n                          implExtHashes\n                          pubExtHashes\n\n                  -- Module-level hashes summarize the per-name hashes.\n                  let modulePubHash = Hashing.modulePubHashFromIface nmod nameHashes\n                      moduleImplHash = Hashing.moduleImplHashFromNameHashes nameHashes\n                  -- Write .ty now so later builds can reuse this front-pass work.\n                  InterfaceFiles.writeFile (outbase ++ \".ty\") moduleSrcBytesHash modulePubHash moduleImplHash sourceMeta impsWithHash nameHashes roots tests mdoc nmod tchecked\n\n                  iff (C.types opts && isRoot) $ dump mn \"types\" (Pretty.print tchecked)\n                  iff (C.sigs opts && isRoot) $ dump mn \"sigs\" (Acton.Types.prettySigs env mn imps fullIface)\n\n                  -- Generate documentation, if building for a project\n                  when (not (C.skip_build opts) && not (isTmp paths)) $ do\n                    let docDir = joinPath [projPath paths, \"out\", \"doc\"]\n                        modPathList = A.modPath mn\n                        docFile = if null modPathList\n                                  then docDir </> \"unnamed\" <.> \"html\"\n                                  else joinPath (docDir : init modPathList) </> last modPathList <.> \"html\"\n                        docFileDir = takeDirectory docFile\n                        -- Get the type environment for this module\n                        modTypeEnv = case Acton.Env.lookupMod mn typeEnv of\n                          Just te -> te\n                          Nothing -> publicIface\n                        -- Apply the same simplification as --sigs uses\n                        env1 = define publicIface $ setMod mn env\n                        simplifiedTypeEnv = simp env1 modTypeEnv\n                    createDirectoryIfMissing True docFileDir\n                    -- Use parsed (original AST) to preserve docstrings\n                    let htmlDoc = DocP.printHtmlDoc (I.NModule imps simplifiedTypeEnv mdoc) parsed\n                    writeFile docFile htmlDoc\n\n                  timeTypeCheck <- getTime Monotonic\n                  typeStmtTimings <- reverse <$> readIORef typeStmtTimingsRef\n\n                  timeFrontEnd <- getTime Monotonic\n                  inferredSigs <- reverse <$> readIORef inferredSigsRef\n                  let frontTime = timeFrontEnd - timeStart\n                      frontTimeMaybe = if not (quiet gopts opts)\n                                         then Just frontTime\n                                         else Nothing\n                      frontTimingMaybe =\n                        if C.timing gopts\n                          then Just FrontTiming\n                                 { ftEnv = timeEnv - timeStart\n                                 , ftKinds = timeKindsCheck - timeEnv\n                                 , ftTypes = timeTypeCheck - timeKindsCheck\n                                 , ftTypeStmtTimings = typeStmtTimings\n                                 }\n                          else Nothing\n                      backJob = Just BackJob { bjPaths = paths\n                                             , bjOpts = opts\n                                             , bjInput = BackInput { biTypeEnv = typeEnv\n                                                                  , biTypedMod = tchecked\n                                                                  , biSrc = srcContent\n                                                                  , biImplHash = moduleImplHash\n                                                                  }\n                                             }\n                  return $ Right FrontResult { frIfaceTE = publicIface\n                                             , frImps = imps\n                                             , frDoc = mdoc\n                                             , frPubHash = modulePubHash\n                                             , frNameHashes = publicNameHashes nameHashes\n                                             , frFrontTime = frontTimeMaybe\n                                             , frFrontTiming = frontTimingMaybe\n                                             , frInferredSigs = inferredSigs\n                                             , frBackJob = backJob\n                                             }\n\n\n-- | Run the back passes for a single module.\n-- Executes normalization through codegen, writes .c/.h output as needed, and\n-- returns the back-pass elapsed time for logging.\nrunBackPasses :: C.GlobalOptions -> C.CompileOptions -> Paths -> BackInput -> IO Bool -> IO (Maybe TimeSpec, Maybe BackTiming)\nrunBackPasses gopts opts paths backInput shouldWrite = do\n      let mn = A.modname (biTypedMod backInput)\n          outbase = outBase paths mn\n          relSrcBase = makeRelative (projPath paths) (srcBase paths mn)\n      timeStart <- getTime Monotonic\n      writeTimingRef <- newIORef Nothing\n\n      (normalized, normEnv) <- Acton.Normalizer.normalize (biTypeEnv backInput) (biTypedMod backInput)\n      iff (C.norm opts && mn == (modName paths)) $ dump mn \"norm\" (Pretty.print normalized)\n      timeNormalized <- getTime Monotonic\n\n      (deacted,deactEnv) <- Acton.Deactorizer.deactorize normEnv normalized\n      iff (C.deact opts && mn == (modName paths)) $ dump mn \"deact\" (Pretty.print deacted)\n      timeDeactorizer <- getTime Monotonic\n\n      (cpstyled,cpsEnv) <- Acton.CPS.convert deactEnv deacted\n      iff (C.cps opts && mn == (modName paths)) $ dump mn \"cps\" (Pretty.print cpstyled)\n      timeCPS <- getTime Monotonic\n\n      (lifted,liftEnv) <- Acton.LambdaLifter.liftModule cpsEnv cpstyled\n      iff (C.llift opts && mn == (modName paths)) $ dump mn \"llift\" (Pretty.print lifted)\n      timeLLift <- getTime Monotonic\n\n      boxed <- Acton.Boxing.doBoxing liftEnv lifted\n      iff (C.box opts && mn == (modName paths)) $ dump mn \"box\" (Pretty.print boxed)\n      timeBoxing <- getTime Monotonic\n\n      let hexHash = B.unpack $ Base16.encode (biImplHash backInput)\n          emitLines = not (C.dbg_no_lines opts)\n      (n,h,c) <- Acton.CodeGen.generate liftEnv relSrcBase (biSrc backInput) emitLines boxed hexHash\n      timeCodeGen <- getTime Monotonic\n      let finish = do\n            timeEnd <- getTime Monotonic\n            let backTime = timeEnd - timeStart\n            mWriteTime <- readIORef writeTimingRef\n            let backTimingMaybe =\n                  if C.timing gopts\n                    then Just BackTiming\n                           { btNormalize = timeNormalized - timeStart\n                           , btDeactorize = timeDeactorizer - timeNormalized\n                           , btCPS = timeCPS - timeDeactorizer\n                           , btLLift = timeLLift - timeCPS\n                           , btBoxing = timeBoxing - timeLLift\n                           , btCodeGen = timeCodeGen - timeBoxing\n                           , btWriteCode = mWriteTime\n                           }\n                    else Nothing\n            if not (quiet gopts opts)\n              then return (Just backTime, backTimingMaybe)\n              else return (Nothing, backTimingMaybe)\n          forceOut s = evaluate (rnf s)\n\n      if C.hgen opts\n        then do\n          forceOut h\n          putStrLn h\n          finish\n        else if C.cgen opts\n          then do\n            forceOut c\n            putStrLn c\n            finish\n          else do\n            forceOut h\n            forceOut c\n            iff (not (altOutput opts)) (do\n                ok <- shouldWrite\n                when ok $ do\n                  let cFile = outbase ++ \".c\"\n                      hFile = outbase ++ \".h\"\n\n                  writeFile hFile h\n                  writeFile cFile c\n                  let tyFileName = modNameToString(modName paths) ++ \".ty\"\n                  iff (C.ty opts) $\n                       copyFileWithMetadata (joinPath [projTypes paths, tyFileName]) (joinPath [srcDir paths, tyFileName])\n\n                  timeCodeWrite <- getTime Monotonic\n                  writeIORef writeTimingRef (Just (timeCodeWrite - timeCodeGen))\n                                     )\n            finish\n\n\n-- | Compile a set of GlobalTasks using a parallel, dependency-aware scheduler.\n-- This drives front passes, emits diagnostics via callbacks, and collects\n-- back-pass jobs for later execution.\n--\n-- Total build graph scheduler: this compiles all tasks across all projects,\n-- i.e. dependencies of the main project are also compiled here, as well as\n-- their dependencies, etc. We construct a large DAG of all modules to be\n-- compiled and then compile in topological order using concurrent async\n-- workers.\n--\n-- What we build the graph from:\n--   - Input is a list of GlobalTask. Each carries a CompileTask (ActonTask or\n--     TyTask), its Paths, and a pre-resolved provider map (gtImportProviders ::\n--     Map ModName TaskKey) telling us which in-graph node satisfies a given\n--     import. TaskKey is (projectRoot, modName).\n--   - We always read an initial set of modules (either all src/ files in the\n--     root project for a project build or the user-specified files). From those\n--     keys we chase imports via gtImportProviders to pull in exactly the\n--     reachable dependencies across projects. __builtin__ is compiled first if\n--     present, i.e. we are building the base lib.\n--\n--   1) Construct a dependency graph over non-builtin tasks and topologically order it.\n--   2) Compile __builtin__ first if present.\n--   3) Walk modules in topo order, deciding per module whether to compile or reuse cached .ty,\n--      and update the shared environment.\n--   4) Track per-name pub/impl hashes and only redo the work that changed:\n--      pub changes trigger front passes; impl changes trigger back passes (with\n--      an impl-hash refresh); codegen hash mismatches trigger back passes only.\n--\n-- Key ideas (ActonTask vs TyTask caching):\n--   - TyTask is lightweight, read from the .ty header: moduleSrcBytesHash, modulePubHash,\n--     moduleImplHash, imports annotated with the pub hash used, per-name hashes (src/pub/impl\n--     + deps), roots, tests, and docstring. It avoids decoding heavy sections.\n--   - ParseTask carries source text plus discovered imports; full parsing is\n--     deferred until front passes are needed.\n--   - ActonTask carries parsed source and must be compiled.\n--   - pubMap :: Map TaskKey ByteString and nameMap :: Map TaskKey (Map Name NameHashInfo) are\n--     maintained during the run. TyTask compares recorded dependency hashes against current\n--     provider hashes (in-graph via pubMap/nameMap, otherwise via cached .ty headers). Pub deltas\n--     trigger front passes; impl deltas trigger back passes with an impl-hash refresh.\n--   - When a TyTask is stale for public reasons (or altOutput on the root), we convert it to an\n--     ActonTask by parsing the .act file and run front passes; when it is fresh we reuse the\n--     header and carry forward the recorded hashes.\n--\n-- Scheduling:\n--   - Critical-path heuristic (file size proxy) picks among ready tasks; runs up to job cap.\n--   - Each worker uses an env snapshot; coordinator merges the resulting interface/doc and\n--     updates indegrees/ready sets. Dependents receive public hashes via pubMap.\n--   - Non-root projects are compiled with depOpts (skip_build/test) while the root keeps user opts.\ncompileTasks :: Source.SourceProvider\n             -> C.GlobalOptions\n             -> C.CompileOptions\n             -> Paths                     -- root project paths (for alt output root selection)\n             -> FilePath                  -- root project path\n             -> [GlobalTask]\n             -> CompileCallbacks\n             -> IO (Either CompileFailure (Acton.Env.Env0, Bool))\ncompileTasks sp gopts opts rootPaths rootProj tasks callbacks = do\n    runningRef <- newIORef []\n    let cancelRunning = readIORef runningRef >>= mapM_ cancel\n    let compileMain = do\n          -- Reject cycles\n          if not (null cycles)\n            then return $ Left (CompileCycleFailure (\"Cyclic imports: \" ++ concatMap showTaskGraph cycles))\n            else do\n              -- Compile __builtin__ first if present anywhere in the graph\n              case builtinOrder of\n                [t] -> do\n                  res <- compileBuiltin t\n                  case res of\n                    Left err -> return (Left err)\n                    Right () -> continue runningRef\n                _ -> continue runningRef\n    compileMain `finally` cancelRunning\n  where\n    continue runningRef = do\n      baseEnv <- Acton.Env.initEnv builtinPath False\n\n      costMap <- fmap M.fromList $ forM otherOrder $ \\t -> do\n                    let mn = name (gtTask t)\n                        pth = gtPaths t\n                        fp  = srcFile pth mn\n                    ok <- doesFileExist fp\n                    sz <- if ok then getFileSize fp else return 0\n                    return (gtKey t, sz)\n      let cwMap = computeCriticalWeights costMap\n\n      nCaps <- getNumCapabilities\n      let maxParallel = max 1 (if C.jobs gopts > 0 then C.jobs gopts else nCaps)\n\n      (envFinal, hadErrors) <- loop runningRef stageInitialReady [] M.empty M.empty M.empty stageIndeg stagePending0 baseEnv False maxParallel cwMap\n      return (Right (envFinal, hadErrors))\n\n    -- Basic maps/sets ----------------------------------------------------\n    taskMap = M.fromList [ (gtKey t, t) | t <- tasks ]\n    isBuiltinKey k = tkMod k == A.modName [\"__builtin__\"]\n    builtinOrder = [ t | t <- tasks, isBuiltinKey (gtKey t) ]\n    nonBuiltinTasks = [ t | t <- tasks, not (isBuiltinKey (gtKey t)) ]\n    nonBuiltinKeys = Data.Set.fromList [ gtKey t | t <- nonBuiltinTasks ]\n    depsOf t = nub [ d | d <- M.elems (gtImportProviders t), Data.Set.member d nonBuiltinKeys ]\n    nodes    = [ (t, gtKey t, depsOf t) | t <- nonBuiltinTasks ]\n    sccs     = stronglyConnComp nodes\n    cycles   = [ ts | ts@(CyclicSCC _) <- sccs ]\n    order    = [ t | AcyclicSCC t <- sccs ]\n    showTaskGraph (CyclicSCC ts) = \"\\n\" ++ concatMap fmt ts\n    showTaskGraph _              = \"\"\n    fmt t = tkProj (gtKey t) ++ \":\" ++ modNameToString (name (gtTask t)) ++ \" \"\n\n    otherOrder = order\n    revMap :: M.Map TaskKey [TaskKey]\n    revMap = foldl' (\\acc (k, ds) -> foldl' (\\a d -> M.insertWith (++) d [k] a) acc ds) M.empty (M.toList depMap)\n    depMap :: M.Map TaskKey [TaskKey]\n    depMap = M.fromList [ (gtKey t, depsOf t) | t <- order ]\n    indeg  = M.map length depMap\n\n    depOpts = opts { C.skip_build = True, C.test = False }\n    optsFor k = if tkProj k == rootProj then opts else depOpts\n\n    needsParseStage t =\n      case gtTask t of\n        ParseTask{} -> not (C.only_build (optsFor (gtKey t)))\n        _ -> False\n\n    stageDepsOf t =\n      let k = gtKey t\n          parseDeps = [ParseStage k | needsParseStage t]\n          frontDeps = map FrontStage (depsOf t)\n      in (parseDeps ++ frontDeps)\n\n    stageDepMap :: M.Map StageKey [StageKey]\n    stageDepMap =\n      M.fromList $\n        [ (ParseStage (gtKey t), [])\n        | t <- order\n        , needsParseStage t\n        ] ++\n        [ (FrontStage (gtKey t), stageDepsOf t)\n        | t <- order\n        ]\n\n    stageRevMap :: M.Map StageKey [StageKey]\n    stageRevMap =\n      foldl'\n        (\\acc (k, ds) -> foldl' (\\a d -> M.insertWith (++) d [k] a) acc ds)\n        M.empty\n        (M.toList stageDepMap)\n\n    stageIndeg :: M.Map StageKey Int\n    stageIndeg = M.map length stageDepMap\n\n    stageInitialReady :: [StageKey]\n    stageInitialReady = [ k | (k, d) <- M.toList stageIndeg, d == 0 ]\n\n    stagePending0 :: Data.Set.Set StageKey\n    stagePending0 = Data.Set.fromList (M.keys stageIndeg)\n\n    rootAlt = modName rootPaths\n\n    builtinPath =\n      case builtinOrder of\n        (t:_) -> projTypes (gtPaths t)\n        _     -> sysTypes rootPaths\n\n    computeCriticalWeights :: M.Map TaskKey Integer -> M.Map TaskKey Integer\n    computeCriticalWeights cm = cwMap\n      where\n        costOf m = M.findWithDefault 0 m cm\n        depsOfK m = M.findWithDefault [] m revMap\n        cwMap    = M.fromList [ (m, costOf m + max0 [ weight d | d <- depsOfK m ]) | m <- M.keys indeg ]\n        weight m = M.findWithDefault 0 m cwMap\n        max0 []  = 0\n        max0 xs  = maximum xs\n\n    dependentClosure :: TaskKey -> Data.Set.Set TaskKey\n    dependentClosure k = go Data.Set.empty [k]\n      where\n        go seen [] = seen\n        go seen (x:xs) =\n          let ds = M.findWithDefault [] x revMap\n              new = filter (`Data.Set.notMember` seen) ds\n              seen' = foldl' (flip Data.Set.insert) seen new\n          in go seen' (new ++ xs)\n\n    -- TODO: can we reintegrate this into the normal loop to avoid duplication?\n    -- NOTE: FYI, it was originally part of the main loop but factored out for\n    -- clarity when we changed to use async, front/back jobs etc. There were so\n    -- many other changes so at the time it was easier to separate builtin\n    -- compilation but perhaps we can find a way to merge it back in to one\n    -- general loop.\n    compileBuiltin :: GlobalTask -> IO (Either CompileFailure ())\n    compileBuiltin t = do\n      let bPaths = gtPaths t\n          mn = name (gtTask t)\n          optsBuiltin = optsFor (gtKey t)\n          actFile = srcFile bPaths mn\n          forceAlt = altOutput optsBuiltin && mn == rootAlt\n      if C.only_build optsBuiltin\n        then return (Right ())\n        else do\n          t' <- case gtTask t of\n            TyTask{} | forceAlt -> materializeTask optsBuiltin sp mn actFile Nothing (gtTask t)\n            ParseTask{} -> materializeTask optsBuiltin sp mn actFile Nothing (gtTask t)\n            _ -> return (gtTask t)\n          case t' of\n            ParseErrorTask{ parseDiagnostics = diags } -> do\n              ccOnDiagnostics callbacks t optsBuiltin diags\n              return (Left CompileBuiltinFailure)\n            TyTask{} -> return (Right ())\n            ParseTask{} -> error (\"Internal error: unmaterialized ParseTask \" ++ modNameToString mn)\n            ActonTask{ src = srcContent, srcBytes = srcBytes, sourceMeta = mSourceMeta, atree = m } -> do\n              ccOnFrontStart callbacks t optsBuiltin\n              builtinEnv0 <- Acton.Env.initEnv (projTypes bPaths) True\n              res <- runFrontPasses\n                gopts\n                optsBuiltin\n                bPaths\n                builtinEnv0\n                m\n                srcContent\n                srcBytes\n                mSourceMeta\n                (getPubHashCached bPaths)\n                (getNameHashMapCached bPaths)\n                (\\p -> ccOnFrontProgress callbacks t optsBuiltin p)\n              case res of\n                Left diags -> do\n                  ccOnFrontDone callbacks t optsBuiltin\n                  ccOnDiagnostics callbacks t optsBuiltin diags\n                  return (Left CompileBuiltinFailure)\n                Right fr -> do\n                  ccOnFrontDone callbacks t optsBuiltin\n                  ccOnFrontResult callbacks t optsBuiltin fr\n                  updatePubHashCache mn (frPubHash fr)\n                  updateNameHashCache mn (frNameHashes fr)\n                  forM_ (frBackJob fr) $ ccOnBackJob callbacks\n                  return (Right ())\n\n    -- One module ---------------------------------------------------------\n    doOne :: Acton.Env.Env0\n          -> M.Map TaskKey B.ByteString\n          -> M.Map TaskKey (M.Map A.Name InterfaceFiles.NameHashInfo)\n          -> M.Map TaskKey CompileTask\n          -> TaskKey\n          -> IO (TaskKey, Either [Diagnostic String] FrontResult)\n    doOne envSnap pubMap nameMap parsedTasks key = do\n      t <- case M.lookup key taskMap of\n             Just x -> return x\n             Nothing -> error (\"Internal error: missing task for key \" ++ show key)\n      let taskCurrent = M.findWithDefault (gtTask t) key parsedTasks\n          paths = gtPaths t\n          mn    = name (gtTask t)\n          optsT = optsFor key\n          providers = gtImportProviders t\n          actFile = srcFile paths mn\n          tyFile = outBase paths mn ++ \".ty\"\n          short8 bs   = take 8 (B.unpack $ Base16.encode bs)\n          mkFrontResult imps ifaceTE mdoc pubHash nameHashes backJob =\n            FrontResult\n              { frIfaceTE = ifaceTE\n              , frImps = imps\n              , frDoc = mdoc\n              , frPubHash = pubHash\n              , frNameHashes = nameHashes\n              , frFrontTime = Nothing\n              , frFrontTiming = Nothing\n              , frInferredSigs = []\n              , frBackJob = backJob\n              }\n          emptyFrontResult =\n            FrontResult\n              { frIfaceTE = []\n              , frImps = []\n              , frDoc = Nothing\n              , frPubHash = B.empty\n              , frNameHashes = []\n              , frFrontTime = Nothing\n              , frFrontTiming = Nothing\n              , frInferredSigs = []\n              , frBackJob = Nothing\n              }\n          cacheFrontResult fr = do\n            updatePubHashCache mn (frPubHash fr)\n            updateNameHashCache mn (frNameHashes fr)\n            return (key, Right fr)\n          readTyFile = do\n            tyRes <- (try :: IO a -> IO (Either SomeException a)) $ InterfaceFiles.readFile tyFile\n            case tyRes of\n              Left _ -> return (Left (missingIfaceDiagnostics mn \"\" mn))\n              Right ty -> return (Right ty)\n          mkBackJob env1 tmod srcText moduleImplHash =\n            BackJob\n              { bjPaths = paths\n              , bjOpts = optsT\n              , bjInput = BackInput\n                  { biTypeEnv = Converter.convEnvProtos env1\n                  , biTypedMod = tmod\n                  , biSrc = srcText\n                  , biImplHash = moduleImplHash\n                  }\n              }\n\n          resolveImportHash m =\n            case M.lookup m providers of\n              Just depKey ->\n                case M.lookup depKey pubMap of\n                  Just h  -> return (Just h)\n                  Nothing ->\n                    if M.member depKey taskMap\n                      then error (\"Internal error: missing pub hash for dep \" ++ modNameToString m)\n                      else getPubHashCached paths m\n              Nothing -> getPubHashCached paths m\n          resolveNameHashMap' m =\n            case M.lookup m providers of\n              Just depKey ->\n                case M.lookup depKey nameMap of\n                  Just hm -> return (Just hm)\n                  Nothing ->\n                    if M.member depKey taskMap\n                      then error (\"Internal error: missing name hashes for dep \" ++ modNameToString m)\n                      else getNameHashMapCached paths m\n              Nothing -> getNameHashMapCached paths m\n\n          missingNameHashDiagnostics qn =\n            errsToDiagnostics \"Compilation error\" (modNameToFilename mn) \"\"\n              [(NoLoc, \"Hash info missing for \" ++ prstr qn)]\n\n          missingDepHashDiagnostics label qn users =\n            errsToDiagnostics \"Compilation error\" (modNameToFilename mn) \"\"\n              [(NoLoc, label ++ \" hash missing for \" ++ prstr qn ++ users)]\n\n          checkMissingImports imps = do\n            userSearchAbs <- mapM normalizePathSafe (C.searchpath optsT)\n            sysTypesAbs <- normalizePathSafe (sysTypes paths)\n            searchAbs <- mapM normalizePathSafe (searchPath paths)\n            let userSearchSet = Data.Set.fromList (map normalise userSearchAbs)\n                managedTypeDirs =\n                  [ p\n                  | p <- searchAbs\n                  , let pNorm = normalise p\n                  , pNorm /= normalise sysTypesAbs\n                  , Data.Set.notMember pNorm userSearchSet\n                  ]\n                isUnder dir path =\n                  let dir' = addTrailingPathSeparator (normalise dir)\n                      path' = normalise path\n                  in Data.List.isPrefixOf dir' path'\n                isManagedTyPath path = any (\\dir -> isUnder dir path) managedTypeDirs\n            missing <- foldM\n              (\\acc (depMn, _depHash) ->\n                 if M.member depMn providers\n                   then return acc\n                   else do\n                     mTy <- getTyFileCached (searchPath paths) depMn\n                     case mTy of\n                       Nothing -> return (Data.Set.insert depMn acc)\n                       Just tyPath -> do\n                         tyAbs <- normalizePathSafe tyPath\n                         if isManagedTyPath tyAbs\n                           then return (Data.Set.insert depMn acc)\n                           else return acc\n              )\n              Data.Set.empty\n              imps\n            if Data.Set.null missing\n              then return (Right ())\n              else do\n                let missingSorted = Data.List.sortOn modNameToString (Data.Set.toList missing)\n                    diags = concatMap (\\depMn -> missingIfaceDiagnostics mn \"\" depMn) missingSorted\n                return (Left diags)\n\n          collectDiags results =\n            let (errs, vals) = partitionEithers results\n            in if null errs\n                 then Right vals\n                 else Left (concat errs)\n          traverseDiags f items = collectDiags <$> mapM f items\n\n          depMap getDeps infos =\n            M.fromListWith (\\a _ -> a) (concatMap getDeps infos)\n\n          depUsers getDeps infos =\n            foldl' add M.empty infos\n            where\n              add acc info =\n                foldl' (\\m (qn, _) -> M.insertWith (++) qn [InterfaceFiles.nhName info] m) acc (getDeps info)\n\n          fmtUsers users qn =\n            case M.lookup qn users of\n              Nothing -> \"\"\n              Just ns ->\n                let uniq = Data.Set.toList (Data.Set.fromList ns)\n                    names = map A.nstr (Data.List.sortOn Hashing.nameKey uniq)\n                in if null names\n                     then \"\"\n                     else \" (used by \" ++ intercalate \", \" names ++ \")\"\n\n          nameHashSummary prevMap newInfos =\n            let newMap = nameHashMapFromList newInfos\n                oldKeys = Data.Set.fromList (M.keys prevMap)\n                newKeys = Data.Set.fromList (M.keys newMap)\n                added = Data.Set.toList (Data.Set.difference newKeys oldKeys)\n                removed = Data.Set.toList (Data.Set.difference oldKeys newKeys)\n                shared = Data.Set.toList (Data.Set.intersection oldKeys newKeys)\n                fieldChange label getHash old new\n                  | getHash old == getHash new = Nothing\n                  | otherwise = Just (label ++ \" \" ++ short8 (getHash old) ++ \" -> \" ++ short8 (getHash new))\n                changesFor n =\n                  let oldInfo = prevMap M.! n\n                      newInfo = newMap M.! n\n                      fields = catMaybes\n                        [ fieldChange \"src\" InterfaceFiles.nhSrcHash oldInfo newInfo\n                        , fieldChange \"pub\" InterfaceFiles.nhPubHash oldInfo newInfo\n                        , fieldChange \"impl\" InterfaceFiles.nhImplHash oldInfo newInfo\n                        ]\n                  in if null fields\n                       then Nothing\n                       else Just (\"~\" ++ A.nstr n ++ \"{\" ++ intercalate \", \" fields ++ \"}\")\n                addedItems = [ \"+\" ++ A.nstr n | n <- Data.List.sortOn Hashing.nameKey added ]\n                removedItems = [ \"-\" ++ A.nstr n | n <- Data.List.sortOn Hashing.nameKey removed ]\n                changedItems = mapMaybe changesFor (Data.List.sortOn Hashing.nameKey shared)\n                items = addedItems ++ removedItems ++ changedItems\n            in if null items then Nothing else Just (intercalate \", \" items)\n\n          resolveNameHashInfo m n = do\n            hm <- resolveNameHashMap' m\n            case hm of\n              Nothing -> return (Left (missingIfaceDiagnostics mn \"\" m))\n              Just hmap ->\n                case M.lookup n hmap of\n                  Just info -> return (Right info)\n                  Nothing -> return (Left (missingNameHashDiagnostics (A.GName m n)))\n\n          resolveQNameHash label getHash users qn =\n            case qn of\n              A.GName m n -> resolveNameHashInfo m n >>= \\res ->\n                return $ case res of\n                  Left diags -> Left diags\n                  Right info ->\n                    let h = getHash info\n                    in if B.null h\n                         then Left (missingDepHashDiagnostics label (A.GName m n) users)\n                         else Right h\n              A.QName m n -> resolveNameHashInfo m n >>= \\res ->\n                return $ case res of\n                  Left diags -> Left diags\n                  Right info ->\n                    let h = getHash info\n                    in if B.null h\n                         then Left (missingDepHashDiagnostics label (A.GName m n) users)\n                         else Right h\n              A.NoQ _ -> return (Left (missingNameHashDiagnostics qn))\n\n          resolveDepHashes label getHash deps = do\n            resolved <- traverseDiags (\\(n, qns) -> do\n              let qnsSorted = Data.List.sortOn Hashing.qnameKey (Data.Set.toList (Data.Set.fromList qns))\n                  users = \" (used by \" ++ A.nstr n ++ \")\"\n              resolvedQns <- traverseDiags (\\qn -> do\n                currE <- resolveQNameHash label getHash users qn\n                return (fmap (\\curr -> (qn, curr)) currE)) qnsSorted\n              return (fmap (\\vals -> (n, vals)) resolvedQns)) (M.toList deps)\n            return (fmap M.fromList resolved)\n\n          -- For stale checks on cached .ty tasks we treat missing names/hashes\n          -- as \"stale cache\" signals and force front passes, instead of failing\n          -- early with internal hash diagnostics.\n          resolveQNameHashForStaleCheck getHash qn =\n            case qn of\n              A.GName m n -> resolveNameHashMap' m >>= \\hm ->\n                return $ case hm of\n                  Nothing -> Right Nothing\n                  Just hmap ->\n                    case M.lookup n hmap of\n                      Nothing -> Right Nothing\n                      Just info ->\n                        let h = getHash info\n                        in if B.null h then Right Nothing else Right (Just h)\n              A.QName m n -> resolveNameHashMap' m >>= \\hm ->\n                return $ case hm of\n                  Nothing -> Right Nothing\n                  Just hmap ->\n                    case M.lookup n hmap of\n                      Nothing -> Right Nothing\n                      Just info ->\n                        let h = getHash info\n                        in if B.null h then Right Nothing else Right (Just h)\n              A.NoQ _ -> return (Right Nothing)\n\n          checkDeps _label getHash _users deps = do\n            resolved <- traverseDiags (\\(qn, recorded) -> do\n              currE <- resolveQNameHashForStaleCheck getHash qn\n              return (fmap (\\curr -> (qn, recorded, curr)) currE)) (M.toList deps)\n            return (fmap\n              (\\triples ->\n                let deltas = [ (qn, old, new) | (qn, old, Just new) <- triples, old /= new ]\n                    missing = [ qn | (qn, _old, Nothing) <- triples ]\n                in (deltas, missing))\n              resolved)\n\n      case taskCurrent of\n        ParseErrorTask{ parseDiagnostics = diags } -> return (key, Left diags)\n        _ | C.only_build optsT -> do\n              ifaceRes <- case taskCurrent of\n                            TyTask{ tyPubHash = h } -> readIfaceFromTy paths mn \"\" (Just h)\n                            ParseTask{ src = srcContent } -> readIfaceFromTy paths mn srcContent Nothing\n                            ActonTask{ src = srcContent } -> readIfaceFromTy paths mn srcContent Nothing\n              case ifaceRes of\n                Right (imps, ifaceTE, mdoc, ih) -> do\n                  let cachedNameHashes = case taskCurrent of\n                        TyTask{ tyNameHashes = nhs } -> publicNameHashes nhs\n                        _ -> []\n                      fr = mkFrontResult imps ifaceTE mdoc ih cachedNameHashes Nothing\n                  cacheFrontResult fr\n                Left _ ->\n                  return (key, Right emptyFrontResult)\n        _ -> do\n          -- For cached .ty tasks, compare recorded dep hashes against current deps.\n          -- This is the up-to-date check that decides if we can skip work. If\n          -- any implDeps have changed we need to rerun out back passes and if\n          -- any pubDeps have changed we need to rerun front passes (and back\n          -- passes)\n          needByDepsRes <- case taskCurrent of\n            TyTask{ tyImports = imps, tyNameHashes = nameHashes } -> do\n              missingImportsRes <- checkMissingImports imps\n              case missingImportsRes of\n                Left diags -> return (Left diags)\n                Right () -> do\n              -- Build dep maps and reverse \"used by\" index for logging.\n                  let pubDeps = depMap InterfaceFiles.nhPubDeps nameHashes\n                      implDeps = depMap InterfaceFiles.nhImplDeps nameHashes\n                      pubUsers = depUsers InterfaceFiles.nhPubDeps nameHashes\n                      implUsers = depUsers InterfaceFiles.nhImplDeps nameHashes\n                  -- Resolve current hashes for each dep and report any deltas.\n                  pubRes <- checkDeps \"pub\" InterfaceFiles.nhPubHash pubUsers pubDeps\n                  implRes <- checkDeps \"impl\" InterfaceFiles.nhImplHash implUsers implDeps\n                  case (pubRes, implRes) of\n                    (Left diags, _) -> return (Left diags)\n                    (_, Left diags) -> return (Left diags)\n                    (Right (pubDeltas, pubMissing), Right (implDeltas, implMissing)) ->\n                      return (Right (pubDeltas, implDeltas, pubMissing, implMissing, pubUsers, implUsers))\n            -- Source tasks always run front passes, so deps are irrelevant.\n            _ -> return (Right ([], [], [], [], M.empty, M.empty))\n\n          case needByDepsRes of\n            Left diags -> return (key, Left diags)\n            Right (pubDeltas, implDeltas, pubMissing, implMissing, pubUsers, implUsers) -> do\n              let needBySource = case taskCurrent of { ParseTask{} -> True; ActonTask{} -> True; _ -> False }\n                  -- Public deltas require front passes; impl deltas only need back jobs.\n                  needByPub = not (null pubDeltas)\n                  needByMissing = not (null pubMissing) || not (null implMissing)\n                  needByImpl = not (null implDeltas)\n                  forceAlt    = altOutput optsT && mn == rootAlt\n                  forceAlways = C.alwaysbuild optsT\n                  -- Front passes run on source or API changes, or when forced.\n                  needFront = needBySource || needByPub || needByMissing || forceAlt || forceAlways\n                  mModuleImplHash = case taskCurrent of\n                    TyTask{ tyImplHash = implHash } -> Just implHash\n                    _ -> Nothing\n              let canCheckCodegen = not needFront && not needByImpl && not (altOutput optsT)\n              mCodegenStatus <- case mModuleImplHash of\n                Just implHash | canCheckCodegen -> Just <$> codegenStatus paths mn implHash\n                _ -> return Nothing\n              let needByCodegen = maybe False (not . codegenUpToDate) mCodegenStatus\n              let runFront = do\n                    prevNameHashes <- if C.verbose gopts\n                      then case taskCurrent of\n                        TyTask{ tyNameHashes = nhs } -> return (Just (nameHashMapFromList (publicNameHashes nhs)))\n                        _ -> getNameHashMapCached paths mn\n                      else return Nothing\n                    when (C.verbose gopts) $ do\n                      if needBySource\n                        then ccOnInfo callbacks (\"  Stale \" ++ modNameToString mn ++ \": source changed\")\n                        else do\n                          when needByPub $ do\n                            let fmtDelta (qn, old, new) = prstr qn ++ \" \" ++ short8 old ++ \" → \" ++ short8 new ++ fmtUsers pubUsers qn\n                            ccOnInfo callbacks (\"  Stale \" ++ modNameToString mn ++ \": pub changes in \" ++ Data.List.intercalate \", \" (map fmtDelta pubDeltas))\n                          when needByMissing $ do\n                            let fmtMissing users qn = prstr qn ++ fmtUsers users qn\n                                pubMissingItems =\n                                  [ \"pub \" ++ fmtMissing pubUsers qn\n                                  | qn <- Data.List.sortOn Hashing.qnameKey pubMissing\n                                  ]\n                                implMissingItems =\n                                  [ \"impl \" ++ fmtMissing implUsers qn\n                                  | qn <- Data.List.sortOn Hashing.qnameKey implMissing\n                                  ]\n                            ccOnInfo callbacks (\"  Stale \" ++ modNameToString mn ++ \": missing dep hashes in \" ++ Data.List.intercalate \", \" (pubMissingItems ++ implMissingItems))\n                    t' <- case taskCurrent of\n                            ActonTask{} -> return taskCurrent\n                            _ -> materializeTask optsT sp mn actFile Nothing taskCurrent\n                    case t' of\n                      ParseErrorTask{ parseDiagnostics = diags } -> return (key, Left diags)\n                      ActonTask{ src = srcContent, srcBytes = srcBytes, sourceMeta = mSourceMeta, atree = m } -> do\n                        res <- runFrontPasses\n                          gopts\n                          optsT\n                          paths\n                          envSnap\n                          m\n                          srcContent\n                          srcBytes\n                          mSourceMeta\n                          resolveImportHash\n                          resolveNameHashMap'\n                          (\\p -> ccOnFrontProgress callbacks t optsT p)\n                        case res of\n                          Left diags -> return (key, Left diags)\n                          Right fr -> do\n                            when (C.verbose gopts) $\n                              forM_ prevNameHashes $ \\prevMap ->\n                                forM_ (nameHashSummary prevMap (frNameHashes fr)) $ \\summary ->\n                                  ccOnInfo callbacks (\"  Hash deltas \" ++ modNameToString mn ++ \": \" ++ summary)\n                            cacheFrontResult fr\n                      ParseTask{} -> error (\"Internal error: unmaterialized ParseTask \" ++ modNameToString mn)\n                      _ -> error (\"Internal error: unexpected task \" ++ show t')\n                  runImplRefresh = do\n                    let rerunFront = do\n                          when (C.verbose gopts) $\n                            ccOnInfo callbacks (\"  Stale \" ++ modNameToString mn ++ \": impl refresh encountered unresolved dep hashes; rerunning front passes\")\n                          runFront\n                        handleSyncFailure :: SomeException -> IO (TaskKey, Either [Diagnostic String] FrontResult)\n                        handleSyncFailure err =\n                          if isJust (fromException err :: Maybe SomeAsyncException)\n                            then throwIO err\n                            else rerunFront\n                        handleImplRefreshException :: SomeException -> IO (TaskKey, Either [Diagnostic String] FrontResult)\n                        handleImplRefreshException = handleSyncFailure\n                    (do\n                      when (C.verbose gopts) $ do\n                        let fmtDelta (qn, old, new) = prstr qn ++ \" \" ++ short8 old ++ \" → \" ++ short8 new ++ fmtUsers implUsers qn\n                        ccOnInfo callbacks (\"  Stale \" ++ modNameToString mn ++ \": impl changes in \" ++ Data.List.intercalate \", \" (map fmtDelta implDeltas))\n                      tyRes <- readTyFile\n                      case tyRes of\n                        Left diags -> return (key, Left diags)\n                        Right (_ms, nmod, tmod, sourceMeta, moduleSrcBytesHash, modulePubHash, _moduleImplHash, imps, nameHashes, roots, tests, mdoc) -> do\n                          parsedRes <- parseActFile optsT sp mn actFile Nothing\n                          case parsedRes of\n                            Left diags -> return (key, Left diags)\n                            Right (snap, parsedMod) -> do\n                              let nameSrcHashes =\n                                    M.fromList [ (InterfaceFiles.nhName nh, InterfaceFiles.nhSrcHash nh)\n                                               | nh <- nameHashes\n                                               ]\n                                  nameKeys = M.keysSet nameSrcHashes\n                                  nameImplHashes0 = Hashing.nameHashesFromItems (Hashing.topLevelItems tmod)\n                                  nameImplHashes = M.filterWithKey (\\k _ -> Data.Set.member k nameKeys) nameImplHashes0\n                                  localNames = nameKeys\n                                  implDepsRaw0 = Hashing.implDepsFromItems (Hashing.topLevelItems tmod)\n                                  implDepsRaw = M.fromList\n                                    [ (n, M.findWithDefault [] n implDepsRaw0)\n                                    | n <- M.keys nameSrcHashes\n                                    ]\n                              envRes <- (try :: IO Acton.Env.Env0 -> IO (Either SomeException Acton.Env.Env0)) $\n                                Acton.Env.mkEnv (searchPath paths) envSnap parsedMod\n                              case envRes of\n                                Left err -> handleSyncFailure err\n                                Right env1 -> do\n                                  depRes <- (try :: IO a -> IO (Either SomeException a)) $ do\n                                    let hashEnv = setMod mn env1\n                                        (implLocalDeps, implExtDeps) = Hashing.splitDeps mn hashEnv localNames implDepsRaw\n                                        depCount = sum (map length (M.elems implLocalDeps))\n                                                 + sum (map length (M.elems implExtDeps))\n                                    -- Force dep maps now so stale aliases/missing names\n                                    -- are handled via the front-pass fallback path.\n                                    _ <- evaluate depCount\n                                    implExtRes <- resolveDepHashes \"impl\" InterfaceFiles.nhImplHash implExtDeps\n                                    return (implLocalDeps, implExtRes)\n                                  case depRes of\n                                    Left err -> handleSyncFailure err\n                                    Right (_, Left _) -> rerunFront\n                                    Right (implLocalDeps, Right implExtHashes) -> do\n                                      let updatedNameHashes =\n                                            Hashing.refreshImplHashes nameHashes nameImplHashes implLocalDeps implExtHashes\n                                          moduleImplHash = Hashing.moduleImplHashFromNameHashes updatedNameHashes\n                                      InterfaceFiles.writeFile tyFile moduleSrcBytesHash modulePubHash moduleImplHash sourceMeta imps updatedNameHashes roots tests mdoc nmod tmod\n                                      let I.NModule imps ifaceFull _mdoc = nmod\n                                          ifaceTE = publicIfaceTE ifaceFull\n                                          backJob = Just (mkBackJob env1 tmod (Source.ssText snap) moduleImplHash)\n                                          fr = mkFrontResult imps ifaceTE mdoc modulePubHash (publicNameHashes updatedNameHashes) backJob\n                                      cacheFrontResult fr\n                      ) `catch` handleImplRefreshException\n                  runCodegenRefresh = do\n                    when (C.verbose gopts) $ do\n                      let suffix = maybe \"\" formatCodegenDelta mCodegenStatus\n                      ccOnInfo callbacks (\"  Stale \" ++ modNameToString mn ++ \": generated code out of date\" ++ suffix)\n                    tyRes <- readTyFile\n                    case tyRes of\n                      Left diags -> return (key, Left diags)\n                      Right (_ms, nmod, tmod, _sourceMeta, _moduleSrcBytesHash, modulePubHash, moduleImplHashStored, _imps, nameHashes, _roots, _tests, mdoc) -> do\n                        snap <- Source.readSource sp actFile\n                        env1 <- Acton.Env.mkEnv (searchPath paths) envSnap tmod\n                        let I.NModule imps ifaceFull _mdoc = nmod\n                            ifaceTE = publicIfaceTE ifaceFull\n                            backJob = Just (mkBackJob env1 tmod (Source.ssText snap) moduleImplHashStored)\n                            fr = mkFrontResult imps ifaceTE mdoc modulePubHash (publicNameHashes nameHashes) backJob\n                        cacheFrontResult fr\n                  runReuse = do\n                    when (C.verbose gopts) $\n                      ccOnInfo callbacks (\"  Fresh \" ++ modNameToString mn ++ \": using cached .ty\")\n                    ifaceRes <- case taskCurrent of\n                                  TyTask{ tyPubHash = h } -> readIfaceFromTy paths mn \"\" (Just h)\n                                  _ -> readIfaceFromTy paths mn \"\" Nothing\n                    case ifaceRes of\n                      Left diags -> return (key, Left diags)\n                      Right (imps, ifaceTE, mdoc, ih) -> do\n                        let cachedNameHashes = case taskCurrent of\n                              TyTask{ tyNameHashes = nhs } -> publicNameHashes nhs\n                              _ -> []\n                            fr = mkFrontResult imps ifaceTE mdoc ih cachedNameHashes Nothing\n                        cacheFrontResult fr\n              case () of\n                _ | needFront -> runFront\n                _ | needByImpl -> runImplRefresh\n                _ | needByCodegen -> runCodegenRefresh\n                _ -> runReuse\n\n    stageTaskKey :: StageKey -> TaskKey\n    stageTaskKey sk =\n      case sk of\n        ParseStage k -> k\n        FrontStage k -> k\n\n    stagePriority :: M.Map TaskKey Integer -> StageKey -> (Int, Integer)\n    stagePriority cw sk =\n      let phase = case sk of\n                    FrontStage _ -> 1\n                    ParseStage _ -> 0\n      in (phase, M.findWithDefault 0 (stageTaskKey sk) cw)\n\n    runParseStage :: TaskKey -> IO (StageKey, Either [Diagnostic String] StageSuccess)\n    runParseStage key = do\n      t <- case M.lookup key taskMap of\n             Just x -> return x\n             Nothing -> error (\"Internal error: missing task for key \" ++ show key)\n      let optsT = optsFor key\n          mn = name (gtTask t)\n          actFile = srcFile (gtPaths t) mn\n          onProgress p = ccOnParseProgress callbacks t optsT p\n      timeStart <- getTime Monotonic\n      parsed <- if C.only_build optsT\n                  then return (gtTask t)\n                  else case gtTask t of\n                         ParseTask{} -> materializeTask optsT sp mn actFile (Just onProgress) (gtTask t)\n                         _ -> return (gtTask t)\n      case parsed of\n        ParseTask{} -> return (ParseStage key, Right (StageParsed parsed Nothing))\n        ActonTask{ atree = m } -> do\n          _ <- evaluate (rnf m)\n          timeEnd <- getTime Monotonic\n          let parseTime = if not (quiet gopts optsT) then Just (timeEnd - timeStart) else Nothing\n          return (ParseStage key, Right (StageParsed parsed parseTime))\n        ParseErrorTask{} -> return (ParseStage key, Right (StageParsed parsed Nothing))\n        _ -> error (\"Internal error: parse stage did not materialize \" ++ modNameToString mn)\n\n    runFrontStage :: Acton.Env.Env0\n                  -> M.Map TaskKey B.ByteString\n                  -> M.Map TaskKey (M.Map A.Name InterfaceFiles.NameHashInfo)\n                  -> M.Map TaskKey CompileTask\n                  -> TaskKey\n                  -> IO (StageKey, Either [Diagnostic String] StageSuccess)\n    runFrontStage envSnap res nameRes parsedTasks key = do\n      (doneKey, outcome) <- doOne envSnap res nameRes parsedTasks key\n      return (FrontStage doneKey, fmap StageFronted outcome)\n\n    scheduleMore :: Int -> [StageKey]\n                 -> [(Async (StageKey, Either [Diagnostic String] StageSuccess), StageKey)]\n                 -> M.Map TaskKey B.ByteString\n                 -> M.Map TaskKey (M.Map A.Name InterfaceFiles.NameHashInfo)\n                 -> M.Map TaskKey CompileTask\n                 -> Acton.Env.Env0\n                 -> M.Map TaskKey Integer\n                 -> IO ([StageKey]\n                       , [(Async (StageKey, Either [Diagnostic String] StageSuccess), StageKey)])\n    scheduleMore k rdy running res nameRes parsedTasks envSnap cw = do\n      let rdySorted = Data.List.sortOn (Down . stagePriority cw) rdy\n          (toStart, rdy') = splitAt k rdySorted\n      new <- forM toStart $ \\sk -> do\n                case sk of\n                  FrontStage key ->\n                    case M.lookup key taskMap of\n                      Just t -> ccOnFrontStart callbacks t (optsFor key)\n                      Nothing -> return ()\n                  ParseStage key ->\n                    case M.lookup key taskMap of\n                      Just t -> ccOnParseStart callbacks t (optsFor key)\n                      Nothing -> return ()\n                a <- async $\n                  case sk of\n                    ParseStage key -> runParseStage key\n                    FrontStage key -> runFrontStage envSnap res nameRes parsedTasks key\n                return (a, sk)\n      return (rdy', new ++ running)\n\n    loop :: IORef [Async (StageKey, Either [Diagnostic String] StageSuccess)]\n         -> [StageKey]\n         -> [(Async (StageKey, Either [Diagnostic String] StageSuccess), StageKey)]\n         -> M.Map TaskKey B.ByteString\n         -> M.Map TaskKey (M.Map A.Name InterfaceFiles.NameHashInfo)\n         -> M.Map TaskKey CompileTask\n         -> M.Map StageKey Int\n         -> Data.Set.Set StageKey\n         -> Acton.Env.Env0\n         -> Bool\n         -> Int\n         -> M.Map TaskKey Integer\n         -> IO (Acton.Env.Env0, Bool)\n    loop runningRef rdy running res nameRes parsedTasks ind pend envAcc hadErrors maxPar cw = do\n      (rdy1, running1) <- mask_ $ do\n        res@(rdy1', running1') <- scheduleMore (maxPar - length running) rdy running res nameRes parsedTasks envAcc cw\n        writeIORef runningRef (map fst running1')\n        return res\n      if null running1 && null rdy1\n        then if Data.Set.null pend\n               then do\n                 writeIORef runningRef []\n                 return (envAcc, hadErrors)\n               else return (envAcc, True)\n        else do\n          (doneA, (stageDone, outcome)) <- waitAny $ map fst running1\n          let running2 = filter ((/= doneA) . fst) running1\n          writeIORef runningRef (map fst running2)\n          let keyDone = stageTaskKey stageDone\n              tDone = taskMap M.! keyDone\n              optsDone = optsFor keyDone\n          case outcome of\n            Left diags -> do\n              case stageDone of\n                FrontStage _ -> ccOnFrontDone callbacks tDone optsDone\n                ParseStage _ -> ccOnParseDone callbacks tDone optsDone Nothing\n              ccOnDiagnostics callbacks tDone optsDone diags\n              let blockedMods = dependentClosure keyDone\n                  blockedStages =\n                    Data.Set.fromList $\n                      concatMap (\\m -> [ParseStage m, FrontStage m]) (Data.Set.toList blockedMods)\n                  (blockedRunning, running3) =\n                    partition (\\(_, sk) -> Data.Set.member sk blockedStages) running2\n              mapM_ (cancel . fst) blockedRunning\n              writeIORef runningRef (map fst running3)\n              let pend2 = Data.Set.delete stageDone (pend `Data.Set.difference` blockedStages)\n                  rdy2 = filter (`Data.Set.notMember` blockedStages) rdy1\n                  dropKeys = keyDone : Data.Set.toList blockedMods\n                  parsedTasks2 = foldl' (flip M.delete) parsedTasks dropKeys\n              loop runningRef rdy2 running3 res nameRes parsedTasks2 ind pend2 envAcc True maxPar cw\n            Right success -> do\n              let pend2 = Data.Set.delete stageDone pend\n                  ind2  = case M.lookup stageDone stageRevMap of\n                            Nothing -> ind\n                            Just ds -> foldl' (\\m d -> M.adjust (\\x -> x-1) d m) ind ds\n                  runningKeys = map snd running2\n                  newlyReady = [ sk | sk <- Data.Set.toList pend2\n                                    , M.findWithDefault 0 sk ind2 == 0\n                                    , not (sk `elem` rdy1)\n                                    , not (sk `elem` runningKeys)\n                                    ]\n                  rdy2 = rdy1 ++ newlyReady\n              case success of\n                StageParsed parsed mParseTime -> do\n                  ccOnParseDone callbacks tDone optsDone mParseTime\n                  let parsedTasks2 = M.insert keyDone parsed parsedTasks\n                  loop runningRef rdy2 running2 res nameRes parsedTasks2 ind2 pend2 envAcc hadErrors maxPar cw\n                StageFronted fr -> do\n                  ccOnFrontDone callbacks tDone optsDone\n                  ccOnFrontResult callbacks tDone optsDone fr\n                  forM_ (frBackJob fr) $ ccOnBackJob callbacks\n                  let res2  = M.insert keyDone (frPubHash fr) res\n                      nameRes2 = M.insert keyDone (nameHashMapFromList (frNameHashes fr)) nameRes\n                      parsedTasks2 = M.delete keyDone parsedTasks\n                      envAcc' = Acton.Env.addMod (tkMod keyDone) (frImps fr) (frIfaceTE fr) (frDoc fr) envAcc\n                  loop runningRef rdy2 running2 res2 nameRes2 parsedTasks2 ind2 pend2 envAcc' hadErrors maxPar cw\n\n\n-- | Execute back-pass jobs in parallel while keeping output order stable.\n-- Jobs are started up to the concurrency limit, then completions are buffered\n-- and flushed in job order so logs are deterministic.\nrunBackJobs :: C.GlobalOptions -> Int -> (BackJob -> IO ()) -> (BackJob -> Maybe TimeSpec -> IO ()) -> [BackJob] -> IO ()\nrunBackJobs _ _ _ _ [] = return ()\nrunBackJobs gopts maxPar onStart onDone jobs = do\n  runningRef <- newIORef []\n  let cancelRunning = readIORef runningRef >>= mapM_ cancel\n  let runMain = loopBack runningRef indexed [] M.empty 0\n  runMain `finally` cancelRunning\n  where\n    indexed = zip [0..] (orderBackJobs jobs)\n\n    backJobKey :: BackJob -> TaskKey\n    backJobKey job =\n      TaskKey (projPath (bjPaths job)) (A.modname (biTypedMod (bjInput job)))\n\n    orderBackJobs :: [BackJob] -> [BackJob]\n    orderBackJobs js = Data.List.sortOn backJobKey js\n\n    loopBack runningRef pending running results nextIx = do\n      let capacity = maxPar - length running\n          (toStart, pending') = splitAt capacity pending\n      running' <- mask_ $ do\n        new <- forM toStart $ \\(ix, job) ->\n                 async $ do\n                   onStart job\n                   (res, _timing) <- runBackPasses gopts (bjOpts job) (bjPaths job) (bjInput job) (return True)\n                   return (ix, job, res)\n        let running' = running ++ new\n        writeIORef runningRef running'\n        return running'\n      if null running' && null pending'\n        then do\n          (_, _) <- flushReady results nextIx\n          return ()\n        else do\n          (doneA, (ix, job, res)) <- waitAny running'\n          let running'' = filter (/= doneA) running'\n              results' = M.insert ix (job, res) results\n          writeIORef runningRef running''\n          (results'', nextIx') <- flushReady results' nextIx\n          loopBack runningRef pending' running'' results'' nextIx'\n\n    flushReady :: M.Map Int (BackJob, Maybe TimeSpec) -> Int -> IO (M.Map Int (BackJob, Maybe TimeSpec), Int)\n    flushReady res ix =\n      case M.lookup ix res of\n        Nothing -> return (res, ix)\n        Just (job, mline) -> do\n          onDone job mline\n          flushReady (M.delete ix res) (ix + 1)\n\n\n-- Paths handling -------------------------------------------------------------------------------------\n\ndata Paths      = Paths {\n                    searchPath  :: [FilePath],\n                    sysPath     :: FilePath,\n                    sysTypes    :: FilePath,\n                    projPath    :: FilePath,\n                    projOut     :: FilePath,\n                    projTypes   :: FilePath,\n                    binDir      :: FilePath,\n                    srcDir      :: FilePath,\n                    isTmp       :: Bool,\n                    fileExt     :: String,\n                    modName     :: A.ModName\n                  }\n\n-- Per-project context used for multi-project orchestration.\n-- Identified by projRoot (absolute path). Keeps directories and BuildSpec if present.\ndata ProjCtx = ProjCtx {\n                     projRoot    :: FilePath,\n                     projOutDir  :: FilePath,\n                     projTypesDir:: FilePath,\n                     projSrcDir  :: FilePath,\n                     projSysPath :: FilePath,\n                     projSysTypes:: FilePath,\n                     projBuildSpec :: BuildSpec.BuildSpec,\n                     projDeps     :: [(String, FilePath)]          -- resolved dependency roots (abs paths)\n                   } deriving (Show)\n\ntype FingerprintMap = M.Map String FilePath\n\nscratchBuildSpec :: FilePath -> BuildSpec.BuildSpec\nscratchBuildSpec projRoot =\n    let name = \"acton_scratch\"\n        prefix = Fingerprint.fingerprintPrefixForName name\n        suffix = Fingerprint.fingerprintPrefixForName projRoot\n        fp = Fingerprint.formatFingerprint (Fingerprint.updateFingerprintPrefix prefix (fromIntegral suffix))\n    in BuildSpec.BuildSpec\n         { BuildSpec.specName = name\n         , BuildSpec.specDescription = Nothing\n         , BuildSpec.fingerprint = fp\n         , BuildSpec.dependencies = M.empty\n         , BuildSpec.zig_dependencies = M.empty\n         }\n\n\nnormalizeFingerprintKey :: String -> Maybe String\nnormalizeFingerprintKey raw =\n    Fingerprint.formatFingerprint <$> Fingerprint.parseFingerprint raw\n\nfingerprintKeyFromSpec :: BuildSpec.BuildSpec -> String\nfingerprintKeyFromSpec spec =\n    case normalizeFingerprintKey (BuildSpec.fingerprint spec) of\n      Just fp -> fp\n      Nothing -> BuildSpec.fingerprint spec\n\napplyFingerprint :: FilePath -> BuildSpec.BuildSpec -> FingerprintMap -> (FilePath, FingerprintMap, String)\napplyFingerprint path spec fpMap =\n    let fp = fingerprintKeyFromSpec spec\n    in case M.lookup fp fpMap of\n         Just canonical -> (canonical, fpMap, fp)\n         Nothing -> (path, M.insert fp path fpMap, fp)\n\n-- | Discover all projects reachable from a root project.\n-- Follows Build.act dependencies, applies overrides/pins, and\n-- returns a map from project root to ProjCtx while skipping duplicates.\ndiscoverProjects :: C.GlobalOptions -> FilePath -> FilePath -> [(String, FilePath)] -> IO (M.Map FilePath ProjCtx)\ndiscoverProjects gopts sysAbs rootProj depOverrides = do\n    rootAbs <- normalizePathSafe rootProj\n    rootSpec0 <- loadBuildSpec rootAbs\n    rootSpec  <- applyDepOverrides rootAbs depOverrides rootSpec0\n    let rootPins = BuildSpec.dependencies rootSpec\n        (_, fpMap0, _) = applyFingerprint rootAbs rootSpec M.empty\n    fst <$> go rootAbs Data.Set.empty M.empty fpMap0 rootPins rootAbs (Just rootSpec)\n  where\n    go root seen acc fpMap pins dir mSpec = do\n      dirAbs <- normalizePathSafe dir\n      if Data.Set.member dirAbs seen\n        then return (acc, fpMap)\n        else do\n          spec0 <- case mSpec of\n                     Just s -> return s\n                     Nothing -> loadBuildSpec dirAbs\n          spec <- applyDepOverrides dirAbs depOverrides spec0\n          let (_, fpMap1, _) = applyFingerprint dirAbs spec fpMap\n          (deps, fpMap2) <- do\n            let depsList = M.toList (BuildSpec.dependencies spec)\n            foldM (collectDep pins dirAbs) ([], fpMap1) depsList\n          let outDir   = joinPath [dirAbs, \"out\"]\n              typesDir = joinPath [outDir, \"types\"]\n              srcDir'  = joinPath [dirAbs, \"src\"]\n              ctx = ProjCtx { projRoot = dirAbs\n                            , projOutDir = outDir\n                            , projTypesDir = typesDir\n                            , projSrcDir = srcDir'\n                            , projSysPath = sysAbs\n                            , projSysTypes = joinPath [sysAbs, \"base\", \"out\", \"types\"]\n                            , projBuildSpec = spec\n                            , projDeps = [ (n, p) | (n, p, _) <- reverse deps ]\n                            }\n              acc' = M.insert dirAbs ctx acc\n              seen' = Data.Set.insert dirAbs seen\n          foldM (step root seen' pins) (acc', fpMap2) (reverse deps)\n\n    collectDep pins base (accDeps, fpMap) (depName, dep) = do\n      let (chosenDep, conflict) =\n            case M.lookup depName pins of\n              Nothing -> (dep, Nothing)\n              Just pinDep ->\n                if pinDep == dep\n                  then (dep, Nothing)\n                  else (pinDep, Just dep)\n      when (isJust conflict) $\n        unless (C.quiet gopts) $\n          putStrLn (\"Warning: dependency '\" ++ depName ++ \"' in \" ++ base\n                    ++ \" overridden by root pin\")\n      depBase <- resolveDepBase base depName chosenDep\n      depAbs  <- normalizePathSafe depBase\n      (depPath, fpMap', depSpec) <- canonicalizeDep depAbs fpMap\n      return ((depName, depPath, depSpec) : accDeps, fpMap')\n\n    canonicalizeDep depAbs fpMap = do\n      spec0 <- loadBuildSpec depAbs\n      spec <- applyDepOverrides depAbs depOverrides spec0\n      let (canonPath, fpMap', fp) = applyFingerprint depAbs spec fpMap\n      when (canonPath /= depAbs) $\n        unless (C.quiet gopts) $\n          putStrLn (\"Warning: dependency fingerprint \" ++ fp\n                    ++ \" at \" ++ depAbs ++ \" deduplicated to \" ++ canonPath)\n      let depSpec = if canonPath == depAbs then Just spec else Nothing\n      return (canonPath, fpMap', depSpec)\n\n    step root seen pins (acc, fpMap) (_, depBase, mSpec) =\n      go root seen acc fpMap pins depBase mSpec\n\n-- Given a FILE and optionally --syspath PATH:\n-- 'sysPath' is the path to the system directory as given by PATH, defaulting to the acton executable directory.\n-- 'sysTypes' is directory \"types\" under 'sysPath'.\n-- 'projPath' is the closest parent directory of FILE that contains a Build.act\n-- file, or a temporary directory in \"/tmp\" if no such parent exists.\n-- 'projOut' is directory \"out\" under 'projPath'.\n-- 'projTypes' is directory \"types\" under 'projOut'.\n-- 'binDir' is the directory prefix of FILE if 'projPath' is temporary, otherwise it is directory \"bin\" under 'projOut'\n-- 'srcDir' is the directory prefix of FILE if 'projPath' is temporary, otherwise it is directory \"src\" under 'projPath'\n-- 'fileExt' is file suffix of FILE.\n-- 'modName' is the module name of FILE (its path after 'src' except 'fileExt', split at every '/')\n\n-- | Compute the source file path for a module under its project src dir.\nsrcFile                 :: Paths -> A.ModName -> FilePath\nsrcFile paths mn        = joinPath (srcDir paths : A.modPath mn) ++ \".act\"\n\n-- | Compute the output base path (without extension) for a module.\n-- Used to locate .ty/.c/.h output under the project's types directory.\noutBase                 :: Paths -> A.ModName -> FilePath\noutBase paths mn        = joinPath (projTypes paths : A.modPath mn)\n\n-- | Compute the module path without extension under the project's src dir.\n-- Used to derive the .act path or related per-module files.\nsrcBase                 :: Paths -> A.ModName -> FilePath\nsrcBase paths mn        = joinPath (srcDir paths : A.modPath mn)\n\n\n-- | Walk upward from a path to find a project root.\n-- A project root is identified by Build.act plus a\n-- src/ directory; returns Nothing if we reach filesystem root.\n\n-- | Check whether a directory is an Acton project root.\n-- Requires Build.act and a src/ directory.\nisActonProjectRoot :: FilePath -> IO Bool\nisActonProjectRoot path = do\n    runacton <- lookupEnv \"ACTON_RUNACTON\"\n    if isJust runacton\n      then return False\n      else do\n        hasBuildAct <- doesFileExist (path </> \"Build.act\")\n        hasSrcDir <- doesDirectoryExist (path </> \"src\")\n        return (hasBuildAct && hasSrcDir)\n\nfindProjectDir :: FilePath -> IO (Maybe FilePath)\nfindProjectDir path = do\n    isProjectRoot <- isActonProjectRoot path\n    if isProjectRoot\n        then return (Just path)\n        else if path == takeDirectory path  -- Check if we're at root\n            then return Nothing\n            else findProjectDir (takeDirectory path)\n\n\n-- | Opaque handle for the lifetime lock of a long-running project compiler.\ndata BackgroundCompilerLock = BackgroundCompilerLock FileLock FilePath\n\n-- | Path to the lock held for the lifetime of a long-running project compiler.\n--\n-- This lock only establishes unique ownership of a background compiler\n-- process such as LSP or watch mode. It does not imply that project state\n-- is current, so all compile/build work must still take 'withProjectLock'.\nbackgroundCompilerLockPath :: FilePath -> FilePath\nbackgroundCompilerLockPath projDir =\n    joinPath [projDir, \".acton.compile.lock\"]\n\n-- | Acquire the long-running compiler lock for a project root, if available.\ntryBackgroundCompilerLock :: FilePath -> IO (Maybe BackgroundCompilerLock)\ntryBackgroundCompilerLock projDir = do\n    let lockPath = backgroundCompilerLockPath projDir\n    mlock <- tryLockFile lockPath Exclusive\n    return ((\\lock -> BackgroundCompilerLock lock lockPath) <$> mlock)\n\n-- | Release the long-running compiler lock and remove its lock file if possible.\nreleaseBackgroundCompilerLock :: BackgroundCompilerLock -> IO ()\nreleaseBackgroundCompilerLock (BackgroundCompilerLock lock lockPath) = do\n    unlockFile lock\n    mlock <- tryLockFile lockPath Exclusive\n    case mlock of\n      Nothing -> return ()\n      Just lock2 -> do\n        removeFile lockPath `catch` handleNotExists\n        unlockFile lock2\n  where\n    handleNotExists :: IOException -> IO ()\n    handleNotExists _ = return ()\n\n-- | Path to the single per-project compiler work lock.\nprojectLockPath :: FilePath -> FilePath\nprojectLockPath projDir =\n    joinPath [projDir, \".acton.lock\"]\n\n-- | Run an action while holding the single per-project compiler work lock.\n--\n-- If the lock is not immediately available, run the callback once before\n-- blocking until the lock can be acquired.\nwithProjectLockOnWait :: FilePath -> IO () -> IO a -> IO a\nwithProjectLockOnWait projDir onWait action = do\n    let lockPath = projectLockPath projDir\n    mlock <- tryLockFile lockPath Exclusive\n    case mlock of\n      Just lock -> action `finally` unlockFile lock\n      Nothing -> do\n        onWait\n        withFileLock lockPath Exclusive (\\_ -> action)\n\n-- | Run an action while holding the single per-project compiler work lock.\nwithProjectLock :: FilePath -> IO a -> IO a\nwithProjectLock projDir action =\n    withProjectLockOnWait projDir (return ()) action\n\n\n-- | Compute Paths for a given source file and compile options.\n-- Resolves the project root (or temp root), output dirs, and search path,\n-- creating required directories along the way.\nfindPaths               :: FilePath -> C.CompileOptions -> IO Paths\nfindPaths actFile opts  = do execDir <- takeDirectory <$> getExecutablePath\n                             sysPath <- canonicalizePath (if null $ C.syspath opts then execDir ++ \"/..\" else C.syspath opts)\n                             absSrcFile <- canonicalizePath actFile\n                             (isTmp, projPath, dirInSrc) <- analyze (takeDirectory absSrcFile) []\n                             let sysTypes = joinPath [sysPath, \"base\", \"out\", \"types\"]\n                                 srcDir  = if isTmp then takeDirectory absSrcFile else joinPath [projPath, \"src\"]\n                                 projOut = joinPath [projPath, \"out\"]\n                                 projTypes = joinPath [projOut, \"types\"]\n                                 binDir  = if isTmp then srcDir else joinPath [projOut, \"bin\"]\n                                 modName = A.modName $ dirInSrc ++ [fileBody]\n                             -- join the search paths from command line options with the ones found in the deps directory\n                             depOverrides <- normalizeDepOverrides projPath (C.dep_overrides opts)\n                             depTypePaths <- if isTmp then return [] else collectDepTypePaths projPath depOverrides\n                             let sPaths = [projTypes] ++ depTypePaths ++ (C.searchpath opts) ++ [sysTypes]\n                             createDirectoryIfMissing True binDir\n                             createDirectoryIfMissing True projOut\n                             createDirectoryIfMissing True projTypes\n                             createDirectoryIfMissing True (getModPath projTypes modName)\n                             return $ Paths sPaths sysPath sysTypes projPath projOut projTypes binDir srcDir isTmp fileExt modName\n  where (fileBody,fileExt) = splitExtension $ takeFileName actFile\n\n        analyze \"/\" ds  = do tmp <- canonicalizePath (C.tempdir opts)\n                             return (True, tmp, [])\n        analyze pre ds  = do isProjectRoot <- isActonProjectRoot pre\n                             if isProjectRoot\n                                then case ds of\n                                    [] -> return $ (False, pre, [])\n                                    \"src\":dirs -> return $ (False, pre, dirs)\n                                    \"out\":\"types\":dirs -> return $ (False, pre, dirs)\n                                    _ -> throwProjectError (\"Source file is not in a valid project directory: \" ++ joinPath ds)\n                                else analyze (takeDirectory pre) (takeFileName pre : ds)\n\n-- Module helpers for multi-project builds ---------------------------------------------------------\n\n-- | Derive a module name from a file path under a project's src root.\n-- The result uses path segments and strips the .act extension.\nmoduleNameFromFile :: FilePath -> FilePath -> IO A.ModName\nmoduleNameFromFile srcBase actFile = do\n    base <- normalizePathSafe srcBase\n    file <- normalizePathSafe actFile\n    let rel = dropExtension (makeRelative base file)\n    return $ A.modName (splitDirectories rel)\n\n-- | Enumerate all .act files in a project and pair them with module names.\n-- Used to seed the project module index for graph construction.\nenumerateProjectModules :: ProjCtx -> IO [(FilePath, A.ModName)]\nenumerateProjectModules ctx = do\n    exists <- doesDirectoryExist (projSrcDir ctx)\n    if not exists\n      then return []\n      else do\n        files <- getFilesRecursive (projSrcDir ctx)\n        let actFiles = filter (\\f -> takeExtension f == \".act\") files\n        forM actFiles $ \\f -> do\n          mn <- moduleNameFromFile (projSrcDir ctx) f\n          return (f, mn)\n\n-- | Remove stale generated module artifacts when source modules disappear.\n-- Prunes orphan .ty/.c/.h outputs under out/types before task planning so\n-- cached headers cannot mask deleted .act modules.\npruneMissingModuleOutputs :: ProjCtx -> IO ()\npruneMissingModuleOutputs ctx = do\n    let srcRoot = projSrcDir ctx\n        typesRoot = projTypesDir ctx\n    typesExists <- doesDirectoryExist typesRoot\n    when typesExists $ do\n      srcExists <- doesDirectoryExist srcRoot\n      srcMods <- if srcExists\n                   then do\n                     srcFiles <- getFilesRecursive srcRoot\n                     let actFiles = filter (\\f -> takeExtension f == \".act\") srcFiles\n                         modBases = map (normalise . dropExtension . makeRelative srcRoot) actFiles\n                     return (Data.Set.fromList modBases)\n                   else return Data.Set.empty\n      outFiles <- getFilesRecursive typesRoot\n      mapM_ (pruneFile srcMods typesRoot) outFiles\n  where\n    isRootStub rel ext =\n      ext == \".c\" &&\n      (\".root\" `Data.List.isSuffixOf` dropExtension rel ||\n       \".test_root\" `Data.List.isSuffixOf` dropExtension rel)\n\n    moduleBase rel ext\n      | isRootStub rel ext = dropExtension (dropExtension rel)\n      | otherwise = dropExtension rel\n\n    pruneFile srcMods typesRoot absFile = do\n      let ext = takeExtension absFile\n      when (ext == \".ty\" || ext == \".c\" || ext == \".h\") $ do\n        let rel = normalise (makeRelative typesRoot absFile)\n            base = normalise (moduleBase rel ext)\n        unless (Data.Set.member base srcMods) $\n          removeFile absFile `catch` ignoreNotExists\n\n    ignoreNotExists :: IOException -> IO ()\n    ignoreNotExists _ = return ()\n\n-- | Incremental variant: prune only modules whose changed .act file no longer exists.\npruneMissingChangedModuleOutputs :: [ProjCtx] -> [FilePath] -> IO ()\npruneMissingChangedModuleOutputs ctxs changedPaths = do\n    absChanged <- mapM normalizePathSafe changedPaths\n    let actPaths = filter (\\p -> takeExtension p == \".act\") absChanged\n    forM_ actPaths $ \\actPath -> do\n      exists <- doesFileExist actPath\n      unless exists $\n        mapM_ (pruneForCtx actPath) ctxs\n  where\n    pruneForCtx actPath ctx = do\n      srcRoot <- normalizePathSafe (projSrcDir ctx)\n      let srcRoot' = addTrailingPathSeparator (normalise srcRoot)\n          actPath' = normalise actPath\n      when (Data.List.isPrefixOf srcRoot' actPath') $ do\n        let modBase = normalise (dropExtension (makeRelative srcRoot actPath'))\n            outBase = projTypesDir ctx </> modBase\n        mapM_ (\\ext -> removeFile (outBase ++ ext) `catch` ignoreNotExists) [\".ty\", \".c\", \".h\"]\n\n    ignoreNotExists :: IOException -> IO ()\n    ignoreNotExists _ = return ()\n\n-- | Build a search path for module interfaces for a project.\n-- Includes the project's types dir, dependency types, user searchpath, and\n-- the system types directory.\nsearchPathForProject :: C.CompileOptions -> M.Map FilePath ProjCtx -> ProjCtx -> [FilePath]\nsearchPathForProject opts projMap ctx =\n    let deps = depTypePathsFromMap projMap (projRoot ctx)\n    in [projTypesDir ctx] ++ deps ++ (C.searchpath opts) ++ [projSysTypes ctx]\n\n-- | Construct a Paths record for a module within a project context.\n-- Creates output directories and ensures the types directory exists.\npathsForModule :: C.CompileOptions -> M.Map FilePath ProjCtx -> ProjCtx -> A.ModName -> IO Paths\npathsForModule opts projMap ctx mn = do\n    let sPaths = searchPathForProject opts projMap ctx\n        bin = joinPath [projOutDir ctx, \"bin\"]\n        src = projSrcDir ctx\n        p = Paths sPaths (projSysPath ctx) (projSysTypes ctx) (projRoot ctx) (projOutDir ctx) (projTypesDir ctx) bin src False \".act\" mn\n    createDirectoryIfMissing True bin\n    createDirectoryIfMissing True (projOutDir ctx)\n    createDirectoryIfMissing True (projTypesDir ctx)\n    createDirectoryIfMissing True (getModPath (projTypesDir ctx) mn)\n    return p\n\n\n-- | Load a BuildSpec from Build.act.\n-- Throws ProjectError on parse or validation failure.\nloadBuildSpec :: FilePath -> IO BuildSpec.BuildSpec\nloadBuildSpec dir = do\n    let actPath = joinPath [dir, \"Build.act\"]\n    actExists <- doesFileExist actPath\n    if actExists\n      then do\n        content <- readFile actPath\n        case BuildSpec.parseBuildActDetailed content of\n          Left err ->\n            case err of\n              BuildSpec.MissingFingerprint name -> do\n                suggestion <- suggestFingerprint name\n                throwProjectError (\"Missing fingerprint in \" ++ actPath ++ \".\\n\"\n                                   ++ \"ERROR: Build.act requires `fingerprint`. For example: fingerprint = \" ++ suggestion ++ \"\\n\"\n                                   ++ \"HINT: Fingerprint = CRC32(name) in the high 32 bits + random low 32 bits. You may choose a different value.\")\n              BuildSpec.InvalidFingerprint name raw -> do\n                suggestion <- suggestFingerprint name\n                throwProjectError (\"Invalid fingerprint \" ++ raw ++ \" in \" ++ actPath\n                                   ++ \" (project name: \" ++ show name ++ \").\\n\"\n                                   ++ \"Expected an unquoted 64-bit hex fingerprint like 0x1234abcd5678ef00.\\n\"\n                                   ++ \"Suggested fingerprint: \" ++ suggestion)\n              BuildSpec.MissingProjectName -> do\n                suggestion <- suggestProjectName dir\n                throwProjectError (\"Missing project name in \" ++ actPath ++ \".\\n\"\n                                   ++ \"Add: name = \" ++ show suggestion)\n              BuildSpec.ParseError msg ->\n                throwProjectError (\"Failed to parse Build.act in \" ++ dir ++ \":\\n\" ++ msg)\n          Right (spec, _, _) -> validateBuildSpec actPath spec\n      else\n        throwProjectError (\"Missing Build.act in \" ++ dir ++ \".\\n\"\n                           ++ \"Create Build.act with required name and fingerprint fields.\")\n\nvalidateBuildSpec :: FilePath -> BuildSpec.BuildSpec -> IO BuildSpec.BuildSpec\nvalidateBuildSpec sourcePath spec = do\n    validateProjectName sourcePath (BuildSpec.specName spec)\n    validateFingerprint sourcePath (BuildSpec.specName spec) (BuildSpec.fingerprint spec)\n    return spec\n\nvalidateProjectName :: FilePath -> String -> IO ()\nvalidateProjectName sourcePath name =\n    if not (isProjectIdent name)\n      then throwProjectError (\"Invalid project name '\" ++ name ++ \"' in \" ++ sourcePath ++ \".\\n\"\n                              ++ \"The name must be a valid Acton project name (letters, digits, underscore; cannot start with a digit).\")\n      else if length name > projectNameMax\n        then throwProjectError (\"Invalid project name '\" ++ name ++ \"' in \" ++ sourcePath ++ \".\\n\"\n                                ++ \"The name must be at most \" ++ show projectNameMax ++ \" characters.\")\n        else return ()\n  where\n    isProjectIdent [] = False\n    isProjectIdent (c:cs) =\n      (isAlpha c || c == '_') && all isIdentChar cs\n      where\n        isIdentChar x = isAlpha x || isDigit x || x == '_'\n\nsuggestProjectName :: FilePath -> IO String\nsuggestProjectName dir = do\n    resolved <- normalizePathSafe dir\n    let base = takeBaseName resolved\n    if null base || base == \".\"\n      then return \"my_project\"\n      else return base\n\nsuggestFingerprint :: String -> IO String\nsuggestFingerprint name = do\n    let prefix = Fingerprint.fingerprintPrefixForName name\n    low <- randomRIO (1, maxBound :: Word32)\n    let fp = (fromIntegral prefix `shiftL` 32) .|. (fromIntegral low :: Word64)\n    return (Fingerprint.formatFingerprint fp)\n\nvalidateFingerprint :: FilePath -> String -> String -> IO ()\nvalidateFingerprint sourcePath name fpRaw =\n    case Fingerprint.parseFingerprint fpRaw of\n      Nothing -> do\n        suggestion <- suggestFingerprint name\n        throwProjectError (\"Invalid fingerprint '\" ++ fpRaw ++ \"' in \" ++ sourcePath\n                           ++ \" (project name: \" ++ show name ++ \").\\n\"\n                           ++ \"Expected an unquoted 64-bit hex fingerprint like 0x1234abcd5678ef00.\\n\"\n                           ++ \"Suggested fingerprint: \" ++ suggestion)\n      Just fp -> do\n        let formatted = Fingerprint.formatFingerprint fp\n            expectedPrefix = Fingerprint.fingerprintPrefixForName name\n            expectedPrefixHex = Fingerprint.formatFingerprintPrefix expectedPrefix\n            actualPrefix = fromIntegral (fp `shiftR` 32)\n        if formatted == Fingerprint.fingerprintPlaceholder\n          then do\n            suggestion <- suggestFingerprint name\n            throwProjectError (\"Fingerprint placeholder \" ++ formatted ++ \" in \" ++ sourcePath\n                               ++ \" is not valid.\\n\"\n                               ++ \"Suggested fingerprint: \" ++ suggestion)\n          else if expectedPrefix == actualPrefix\n            then return ()\n            else do\n              suggestion <- suggestFingerprint name\n              throwProjectError (\"Fingerprint mismatch in \" ++ sourcePath\n                                 ++ \" for project name \" ++ show name ++ \".\\n\"\n                                 ++ \"Expected prefix: \" ++ expectedPrefixHex\n                                 ++ \" (CRC32 of name).\\n\"\n                                 ++ \"Current fingerprint: \" ++ formatted ++ \"\\n\"\n                                 ++ \"Renames and forks require a new fingerprint for this name.\\n\"\n                                 ++ \"Suggested fingerprint: \" ++ suggestion)\n\n\nprojectNameMax :: Int\nprojectNameMax = 32\n\n-- | Treat drive-letter paths as absolute in addition to POSIX roots.\n-- This keeps path normalization consistent on Windows hosts.\nisAbsolutePath :: FilePath -> Bool\nisAbsolutePath p =\n    isAbsolute p ||\n    case p of\n      (c:':':_) -> isAlpha c\n      _         -> False\n\n-- | Normalize a path without failing if it does not exist.\n-- Falls back to normalise for non-existent paths (useful for temporary builds).\nnormalizePathSafe :: FilePath -> IO FilePath\nnormalizePathSafe p = do\n    res <- try (canonicalizePath p) :: IO (Either IOException FilePath)\n    return $ either (const (normalise p)) id res\n\n-- | Trim leading and trailing whitespace from a string.\n-- Used when parsing or normalizing BuildSpec inputs.\ntrim :: String -> String\ntrim = f . f\n  where f = reverse . dropWhile isSpace\n\n-- | Collapse \".\" and \"..\" segments without dropping leading \"..\" on relative paths.\n-- Example: \"a/b/../c/./d\" becomes \"a/c/d\".\ncollapseDots :: FilePath -> FilePath\ncollapseDots p =\n    let parts = splitDirectories p\n        (root, rest) = case parts of\n                         (r:xs) | isRoot r -> (Just r, xs)\n                         xs                -> (Nothing, xs)\n        (revAcc, ups) = foldl step ([], 0) rest\n        cleaned = replicate ups \"..\" ++ reverse revAcc\n        prefix = maybe [] (\\r -> [r]) root\n    in joinPath (prefix ++ cleaned)\n  where\n    isRoot r = r == \"/\" || (length r >= 2 && r !! 1 == ':')\n    step (acc, ups) comp =\n      case comp of\n        \".\"  -> (acc, ups)\n        \"\"   -> (acc, ups)\n        \"..\" -> case acc of\n                  (_:as) -> (as, ups)\n                  []     -> (acc, ups + 1)\n        _    -> (comp:acc, ups)\n\n-- | Rebase a path against a base directory and normalize it.\n-- Absolute paths are left as-is; relative paths are joined to the base.\nrebasePath :: FilePath -> FilePath -> FilePath\nrebasePath base p\n  | isAbsolutePath p = normalise p\n  | otherwise        = normalise (joinPath [base, p])\n\n-- | Normalize --dep overrides relative to a base directory.\n-- Absolute override paths are kept, relative paths are rebased and normalized.\nnormalizeDepOverrides :: FilePath -> [(String, FilePath)] -> IO [(String, FilePath)]\nnormalizeDepOverrides base overrides =\n  mapM (\\(n,p) -> do\n           let absP0 = if isAbsolutePath p then p else joinPath [base, p]\n           p' <- normalizePathSafe absP0\n           return (n, p'))\n       overrides\n\n-- | Apply --dep overrides (NAME=PATH) to a BuildSpec.\n-- Resolves override paths relative to the given base directory when needed.\napplyDepOverrides :: FilePath -> [(String, FilePath)] -> BuildSpec.BuildSpec -> IO BuildSpec.BuildSpec\napplyDepOverrides base overrides spec = do\n    deps' <- foldM applyOne (BuildSpec.dependencies spec) overrides\n    return spec { BuildSpec.dependencies = deps' }\n  where\n    applyOne depsMap (depName, depPath) =\n      case M.lookup depName depsMap of\n        Nothing -> return depsMap\n        Just dep -> do\n          let absP0 = if isAbsolutePath depPath then depPath else joinPath [base, depPath]\n          absP <- normalizePathSafe absP0\n          validateDepOverridePath depName absP\n          let dep' = dep { BuildSpec.path = Just absP }\n          return (M.insert depName dep' depsMap)\n\nvalidateDepOverridePath :: String -> FilePath -> IO ()\nvalidateDepOverridePath depName depPath = do\n    exists <- doesDirectoryExist depPath\n    unless exists $\n      throwProjectError (\"Dependency \" ++ depName ++ \" path does not exist: \" ++ depPath ++ \"\\n\"\n                         ++ \"Hint: Local dependency paths must point to an Acton project root\\n\"\n                         ++ \"(directory with src/ and Build.act).\")\n    isProjectRoot <- isActonProjectRoot depPath\n    unless isProjectRoot $\n      throwProjectError (\"Dependency \" ++ depName ++ \" path is not an Acton project root: \" ++ depPath ++ \"\\n\"\n                         ++ \"Hint: Local dependency paths must point to an Acton project root\\n\"\n                         ++ \"(directory with src/ and Build.act).\")\n\nfetchDependencies :: C.GlobalOptions -> Paths -> [(String, FilePath)] -> IO ()\nfetchDependencies gopts paths depOverrides = do\n    if isTmp paths\n      then return ()\n      else do\n        rootSpec0 <- loadBuildSpec (projPath paths)\n        rootSpec <- applyDepOverrides (projPath paths) depOverrides rootSpec0\n        unless (C.quiet gopts) $\n          putStrLn \"Resolving dependencies (fetching if missing)...\"\n        home <- getHomeDirectory\n        let zigExe      = joinPath [sysPath paths, \"zig\", \"zig\"]\n            globalCache = joinPath [home, \".cache\", \"acton\", \"zig-global-cache\"]\n            depsCache   = joinPath [home, \".cache\", \"acton\", \"deps\"]\n            cacheDir h  = joinPath [globalCache, \"p\", h]\n        createDirectoryIfMissing True globalCache\n        createDirectoryIfMissing True depsCache\n        let rootPins = BuildSpec.dependencies rootSpec\n        _ <- walkProject rootPins cacheDir zigExe globalCache depsCache\n                         Data.Set.empty (projPath paths) rootSpec\n        return ()\n  where\n    walkProject rootPins cacheDir zigExe globalCache depsCache seen projDir spec = do\n      projAbs <- normalizePathSafe projDir\n      if Data.Set.member projAbs seen\n        then return seen\n        else do\n          selectedDeps <- forM (M.toList (BuildSpec.dependencies spec)) $\n            selectDependency rootPins projAbs\n          let pkgFetches = catMaybes\n                [ mkPkgFetch cacheDir zigExe globalCache name dep | (name, dep) <- selectedDeps ]\n              zigFetches = catMaybes\n                [ mkZigFetch cacheDir zigExe globalCache name dep\n                | (name, dep) <- M.toList (BuildSpec.zig_dependencies spec)\n                ]\n          results <- mapConcurrently id (pkgFetches ++ zigFetches)\n          let errs = [ e | Left e <- results ]\n          unless (null errs) $ throwProjectError (unlines errs)\n          forM_ selectedDeps $ \\(name, dep) -> copyPkgDep cacheDir depsCache name dep\n          let seen' = Data.Set.insert projAbs seen\n          foldM (walkDependency rootPins cacheDir zigExe globalCache depsCache projAbs)\n                seen' selectedDeps\n\n    selectDependency rootPins base (depName, dep) = do\n      let (chosenDep, conflict) =\n            case M.lookup depName rootPins of\n              Nothing -> (dep, Nothing)\n              Just pinDep ->\n                if pinDep == dep\n                  then (dep, Nothing)\n                  else (pinDep, Just dep)\n      when (isJust conflict) $\n        unless (C.quiet gopts) $\n          putStrLn (\"Warning: dependency '\" ++ depName ++ \"' in \" ++ base\n                    ++ \" overridden by root pin\")\n      return (depName, chosenDep)\n\n    walkDependency rootPins cacheDir zigExe globalCache depsCache base seen (depName, dep) = do\n      depBase <- resolveDepBase base depName dep\n      depAbs <- normalizePathSafe depBase\n      depExists <- doesDirectoryExist depAbs\n      if not depExists\n        then case BuildSpec.path dep of\n               Just p | not (null p) ->\n                 throwProjectError (\"Dependency \" ++ depName ++ \" path does not exist: \" ++ depAbs ++ \"\\n\"\n                                    ++ \"Hint: Local dependency paths must point to an Acton project root\\n\"\n                                    ++ \"(directory with src/ and Build.act).\")\n               _ -> return seen\n        else do\n          depSpec0 <- loadBuildSpec depAbs\n          depSpec <- applyDepOverrides depAbs depOverrides depSpec0\n          walkProject rootPins cacheDir zigExe globalCache depsCache seen depAbs depSpec\n\n    mkPkgFetch cacheDir zigExe globalCache name dep =\n      case BuildSpec.path dep of\n        Just p | not (null p) -> Nothing\n        _ -> case (BuildSpec.url dep, BuildSpec.hash dep) of\n               (Just u, Just h) ->\n                 Just (fetchOne \"pkg\" name u (Just h) cacheDir zigExe globalCache)\n               (Just _, Nothing) ->\n                 Just (return (Left (\"Dependency \" ++ name ++ \" is missing hash\")))\n               _ -> Nothing\n\n    mkZigFetch cacheDir zigExe globalCache name dep =\n      case BuildSpec.zpath dep of\n        Just p | not (null p) -> Nothing\n        _ -> case (BuildSpec.zurl dep, BuildSpec.zhash dep) of\n               (Just u, Just h) ->\n                 Just (fetchOne \"zig\" name u (Just h) cacheDir zigExe globalCache)\n               (Just _, Nothing) ->\n                 Just (return (Left (\"Zig dependency \" ++ name ++ \" is missing hash\")))\n               _ -> Nothing\n\n    copyPkgDep cacheDir depsCache name dep =\n      case BuildSpec.path dep of\n        Just p | not (null p) -> return ()\n        _ -> case BuildSpec.hash dep of\n               Nothing -> return ()\n               Just h -> do\n                 let src = cacheDir h\n                     dst = joinPath [depsCache, name ++ \"-\" ++ h]\n                 exists <- doesDirectoryExist dst\n                 unless exists $ do\n                   srcOk <- doesDirectoryExist src\n                   unless srcOk $\n                     throwProjectError (\"Dependency \" ++ name ++ \" not present in Zig cache after fetch: \" ++ src)\n                   when (C.verbose gopts) $\n                     putStrLn (\"Copying dependency \" ++ name ++ \" (\" ++ h ++ \") from Zig cache\")\n                   copyTree src dst\n\n    fetchOne kind name url mh cacheDir zigExe globalCache = do\n      case mh of\n        Just h -> do\n          present <- doesDirectoryExist (cacheDir h)\n          if present\n            then do\n              unless (C.quiet gopts) $\n                putStrLn (\"Using cached \" ++ kind ++ \" dependency \" ++ name ++ \" (\" ++ h ++ \")\")\n              return (Right h)\n            else runFetch kind name url mh cacheDir zigExe globalCache\n        Nothing ->\n          runFetch kind name url mh cacheDir zigExe globalCache\n\n    runFetch kind name url mh cacheDir zigExe globalCache = do\n      unless (C.quiet gopts) $\n        putStrLn (\"Fetching \" ++ kind ++ \" dependency \" ++ name ++ \" from \" ++ url)\n      if isHttpUrl url\n        then fetchViaDownloadedArchive kind name url mh cacheDir zigExe globalCache\n        else do -- other URLs, like file:// - not very common, maybe we want to constrain this somehow?\n          res <- runZigFetch zigExe globalCache url\n          case res of\n            Left ex -> return (Left (\"Failed to fetch dependency \" ++ name ++ \": \" ++ displayException ex))\n            Right (ExitSuccess, out, _) ->\n              validateFetchOutput name mh cacheDir out\n            Right (ExitFailure _, _, err) ->\n              return (Left (\"Failed to fetch dependency \" ++ name ++ \":\\n\" ++ err))\n\n    runZigFetch :: FilePath -> FilePath -> FilePath -> IO (Either SomeException (ExitCode, String, String))\n    runZigFetch zigExe globalCache target = do\n      let cmd = proc zigExe [\"fetch\", \"--global-cache-dir\", globalCache, target]\n      try (readCreateProcessWithExitCode cmd \"\") :: IO (Either SomeException (ExitCode, String, String))\n\n    validateFetchOutput :: String -> Maybe String -> (String -> FilePath) -> String -> IO (Either String String)\n    validateFetchOutput name mh cacheDir out = do\n      let hashVal = trim out\n      case mh of\n        Just h | h /= hashVal ->\n          return (Left (\"Hash mismatch for dependency \" ++ name ++ \" (expected \" ++ h ++ \", got \" ++ hashVal ++ \")\"))\n        _ -> do\n          exists <- doesDirectoryExist (cacheDir hashVal)\n          if exists\n            then return (Right hashVal)\n            else return (Left (\"Dependency \" ++ name ++ \" not present in Zig cache after fetch: \" ++ cacheDir hashVal))\n\n    fetchViaDownloadedArchive kind name depUrl mh cacheDir zigExe globalCache = do\n      dl <- downloadToLocalArchive kind name depUrl\n      case dl of\n        Left dlErr -> do\n          direct <- runZigFetch zigExe globalCache depUrl\n          case direct of\n            Left ex ->\n              return (Left (\"Failed to fetch dependency \" ++ name ++ \":\\nDownload step failed: \" ++ dlErr\n                            ++ \"\\nDirect zig fetch failed: \" ++ displayException ex))\n            Right (ExitSuccess, out, _) ->\n              validateFetchOutput name mh cacheDir out\n            Right (ExitFailure _, _, err) ->\n              return (Left (\"Failed to fetch dependency \" ++ name ++ \":\\nDownload step failed: \" ++ dlErr\n                            ++ \"\\nDirect zig fetch failed:\\n\" ++ err))\n        Right localArchive -> do\n          fetched <- runZigFetch zigExe globalCache localArchive\n          _ <- try (removeFile localArchive) :: IO (Either IOException ())\n          case fetched of\n            Left ex ->\n              return (Left (\"Failed to fetch dependency \" ++ name ++ \": \" ++ displayException ex))\n            Right (ExitSuccess, out, _) ->\n              validateFetchOutput name mh cacheDir out\n            Right (ExitFailure _, _, err) ->\n              return (Left (\"Failed to fetch dependency \" ++ name ++ \":\\n\" ++ err))\n\n    isHttpUrl :: String -> Bool\n    isHttpUrl depUrl =\n      let u = map toLower depUrl\n      in \"http://\" `isPrefixOf` u || \"https://\" `isPrefixOf` u\n\n    downloadToLocalArchive :: String -> String -> String -> IO (Either String FilePath)\n    downloadToLocalArchive _kind _name depUrl = do\n      parsedReq <- try (HTTP.parseRequest depUrl) :: IO (Either SomeException HTTP.Request)\n      case parsedReq of\n        Left ex -> return (Left (\"Invalid dependency URL: \" ++ displayException ex))\n        Right req -> do\n          let settings = HTTP.managerSetProxy (HTTP.proxyEnvironment Nothing) tlsManagerSettings\n          manager <- HTTP.newManager settings\n          opened <- try (HTTP.responseOpen req manager) :: IO (Either SomeException (HTTP.Response HTTP.BodyReader))\n          case opened of\n            Left ex -> return (Left (displayException ex))\n            Right response -> do\n              let code = statusCode (HTTP.responseStatus response)\n              if code < 200 || code >= 300\n                then do\n                  _ <- try (HTTP.responseClose response) :: IO (Either SomeException ())\n                  return (Left (\"HTTP error \" ++ show code))\n                else do\n                  tmpDir <- getTemporaryDirectory\n                  (tmpPath, tmpHandle) <- openBinaryTempFile tmpDir \"acton-fetch\"\n                  let initialSuffix = archiveSuffixForRequestResponse req response\n                  streamRes <- try (streamDownloadToFile (HTTP.responseBody response) tmpHandle) :: IO (Either SomeException BS.ByteString)\n                  _ <- try (hClose tmpHandle) :: IO (Either IOException ())\n                  _ <- try (HTTP.responseClose response) :: IO (Either SomeException ())\n                  case streamRes of\n                    Left ex -> do\n                      _ <- try (removeFile tmpPath) :: IO (Either IOException ())\n                      return (Left (\"Unable to save downloaded archive: \" ++ displayException ex))\n                    Right sniffBytes ->\n                      case initialSuffix <|> detectArchiveSuffixFromBytes sniffBytes of\n                        Nothing -> do\n                          _ <- try (removeFile tmpPath) :: IO (Either IOException ())\n                          return (Left \"Could not determine archive type from URL path, response headers, or file bytes\")\n                        Just suffix -> do\n                          let finalPath = tmpPath ++ suffix\n                          moveRes <- try (renameFile tmpPath finalPath) :: IO (Either IOException ())\n                          case moveRes of\n                            Left ex -> do\n                              _ <- try (removeFile tmpPath) :: IO (Either IOException ())\n                              return (Left (\"Unable to finalize downloaded archive path: \" ++ displayException ex))\n                            Right _ ->\n                              return (Right finalPath)\n\n    streamDownloadToFile :: HTTP.BodyReader -> Handle -> IO BS.ByteString\n    streamDownloadToFile bodyReader outHandle =\n      loop BS.empty\n      where\n        sniffLimit = 600\n        loop sniff = do\n          chunk <- HTTP.brRead bodyReader\n          if BS.null chunk\n            then return sniff\n            else do\n              BS.hPut outHandle chunk\n              let sniff' =\n                    if BS.length sniff >= sniffLimit\n                      then sniff\n                      else BS.take sniffLimit (sniff <> chunk)\n              loop sniff'\n\n    archiveSuffixForRequestResponse :: HTTP.Request -> HTTP.Response HTTP.BodyReader -> Maybe String\n    archiveSuffixForRequestResponse req response =\n      case archiveSuffixFromPath (B.unpack (HTTP.path req)) of\n        Just suffix -> Just suffix\n        Nothing ->\n          case archiveSuffixFromContentDisposition (lookup hContentDisposition (HTTP.responseHeaders response)) of\n            Just suffix -> Just suffix\n            Nothing -> archiveSuffixFromContentType (lookup hContentType (HTTP.responseHeaders response))\n\n    archiveSuffixFromPath :: String -> Maybe String\n    archiveSuffixFromPath rawPath =\n      let p = map toLower rawPath\n      in if \".tar.gz\" `isSuffixOf` p then Just \".tar.gz\"\n         else if \".tgz\" `isSuffixOf` p then Just \".tgz\"\n         else if \".tar.xz\" `isSuffixOf` p then Just \".tar.xz\"\n         else if \".txz\" `isSuffixOf` p then Just \".txz\"\n         else if \".tar.zst\" `isSuffixOf` p then Just \".tar.zst\"\n         else if \".tzst\" `isSuffixOf` p then Just \".tzst\"\n         else if \".tar\" `isSuffixOf` p then Just \".tar\"\n         else if \".zip\" `isSuffixOf` p then Just \".zip\"\n         else if \".jar\" `isSuffixOf` p then Just \".jar\"\n         else Nothing\n\n    archiveSuffixFromContentType :: Maybe B.ByteString -> Maybe String\n    archiveSuffixFromContentType mType =\n      case map toLower . trim . takeWhile (/= ';') . B.unpack <$> mType of\n        Just \"application/x-tar\" -> Just \".tar\"\n        Just \"application/gzip\" -> Just \".tar.gz\"\n        Just \"application/x-gzip\" -> Just \".tar.gz\"\n        Just \"application/tar+gzip\" -> Just \".tar.gz\"\n        Just \"application/x-tar-gz\" -> Just \".tar.gz\"\n        Just \"application/x-gtar-compressed\" -> Just \".tar.gz\"\n        Just \"application/x-xz\" -> Just \".tar.xz\"\n        Just \"application/zstd\" -> Just \".tar.zst\"\n        Just \"application/zip\" -> Just \".zip\"\n        Just \"application/x-zip-compressed\" -> Just \".zip\"\n        Just \"application/java-archive\" -> Just \".zip\"\n        _ -> Nothing\n\n    archiveSuffixFromContentDisposition :: Maybe B.ByteString -> Maybe String\n    archiveSuffixFromContentDisposition mVal = do\n      headerVal <- mVal\n      filenameVal <- extractField (B.pack \"filename*=\") headerVal <|> extractField (B.pack \"filename=\") headerVal\n      archiveSuffixFromPath (B.unpack filenameVal)\n      where\n        extractField key raw =\n          let lowerRaw = B.map toLower raw\n              (prefix, rest) = B.breakSubstring key lowerRaw\n          in if B.null rest\n               then Nothing\n               else\n                 let origRest = B.drop (B.length prefix) raw\n                     val0 = B.drop (B.length key) origRest\n                     val1 = B.takeWhile (/= ';') val0\n                     val2 = stripQuotes (B.dropWhile isSpace (trimBS val1))\n                     val3 =\n                       case B.breakSubstring (B.pack \"''\") val2 of\n                         (_, t) | B.null t -> val2\n                         (_, t) -> B.drop 2 t\n                 in if B.null val3 then Nothing else Just val3\n        trimBS = B.dropWhileEnd isSpace . B.dropWhile isSpace\n        stripQuotes s\n          | B.length s >= 2 && B.head s == '\"' && B.last s == '\"' = B.tail (B.init s)\n          | otherwise = s\n\n    detectArchiveSuffixFromBytes :: BS.ByteString -> Maybe String\n    detectArchiveSuffixFromBytes bytes\n      | startsWith [0x50, 0x4b, 0x03, 0x04] bytes = Just \".zip\"\n      | startsWith [0x50, 0x4b, 0x05, 0x06] bytes = Just \".zip\"\n      | startsWith [0x50, 0x4b, 0x07, 0x08] bytes = Just \".zip\"\n      | startsWith [0x1f, 0x8b] bytes = Just \".tar.gz\"\n      | startsWith [0xfd, 0x37, 0x7a, 0x58, 0x5a, 0x00] bytes = Just \".tar.xz\"\n      | startsWith [0x28, 0xb5, 0x2f, 0xfd] bytes = Just \".tar.zst\"\n      | hasUstar bytes = Just \".tar\"\n      | otherwise = Nothing\n      where\n        startsWith :: [Word8] -> BS.ByteString -> Bool\n        startsWith sig bs =\n          BS.length bs >= length sig && BS.take (length sig) bs == BS.pack sig\n        hasUstar bs =\n          BS.length bs >= 262 && BS.take 5 (BS.drop 257 bs) == BS.pack [0x75, 0x73, 0x74, 0x61, 0x72]\n\n    copyTree :: FilePath -> FilePath -> IO ()\n    copyTree src dst = do\n      exists <- doesDirectoryExist src\n      unless exists $ throwProjectError (\"Source path for copyTree does not exist: \" ++ src)\n      createDirectoryIfMissing True dst\n      entries <- listDirectory src\n      forM_ entries $ \\e -> do\n        let s = src </> e\n            d = dst </> e\n        isDir <- doesDirectoryExist s\n        if isDir\n          then copyTree s d\n          else do\n            createDirectoryIfMissing True (takeDirectory d)\n            copyFile s d\n\n-- | Collect dependency type directories using an existing ProjCtx map.\n-- Traverses dependency edges so downstream lookups can build search paths.\ndepTypePathsFromMap :: M.Map FilePath ProjCtx -> FilePath -> [FilePath]\ndepTypePathsFromMap ctxs root = snd (go Data.Set.empty root)\n  where\n    go seen node =\n      case M.lookup node ctxs of\n        Nothing  -> (seen, [])\n        Just ctx ->\n          foldl' step (Data.Set.insert node seen, []) (projDeps ctx)\n\n    step (seen, acc) (_, depRoot) =\n      case M.lookup depRoot ctxs of\n        Nothing -> (Data.Set.insert depRoot seen, acc)\n        Just depCtx ->\n          if Data.Set.member depRoot seen\n            then (seen, acc)\n            else\n              let seen' = Data.Set.insert depRoot seen\n                  (seenNext, sub) = go seen' depRoot\n              in (seenNext, acc ++ [projTypesDir depCtx] ++ sub)\n\n-- | Resolve a dependency's base directory from a BuildSpec PkgDep.\n-- Prefers explicit path, otherwise uses the hashed cache location.\nresolveDepBase :: FilePath -> String -> BuildSpec.PkgDep -> IO FilePath\nresolveDepBase base name dep =\n    case BuildSpec.path dep of\n      Just p | not (null p) -> normalizePathSafe (rebasePath base p)\n      _ -> case BuildSpec.hash dep of\n             Just h -> do\n               home <- getHomeDirectory\n               normalizePathSafe (joinPath [home, \".cache\", \"acton\", \"deps\", name ++ \"-\" ++ h])\n             Nothing -> throwProjectError (\"Dependency \" ++ name ++ \" has no path or hash\")\n\n-- | Recursively collect out/types paths for all declared dependencies.\n-- Reads Build.act and follows dependency edges.\ncollectDepTypePaths :: FilePath -> [(String, FilePath)] -> IO [FilePath]\ncollectDepTypePaths projDir overrides = do\n  root <- normalizePathSafe projDir\n  (_, _, paths) <- go Data.Set.empty M.empty root Nothing\n  return paths\n  where\n    go seen fpMap dir mSpec = do\n      spec0 <- case mSpec of\n                 Just s -> return s\n                 Nothing -> loadBuildSpec dir\n      spec <- applyDepOverrides dir overrides spec0\n      let (_, fpMap1, _) = applyFingerprint dir spec fpMap\n      foldM (step dir) (seen, fpMap1, []) (M.toList (BuildSpec.dependencies spec))\n\n    step base (seen, fpMap, acc) (depName, dep) = do\n      depBase <- resolveDepBase base depName dep\n      depAbs  <- normalizePathSafe depBase\n      depExists <- doesDirectoryExist depAbs\n      if not depExists\n        then case BuildSpec.path dep of\n               Just p | not (null p) ->\n                 throwProjectError (\"Dependency \" ++ depName ++ \" path does not exist: \" ++ depAbs ++ \"\\n\"\n                                    ++ \"Hint: Local dependency paths must point to an Acton project root\\n\"\n                                    ++ \"(directory with src/ and Build.act).\")\n               _ -> return (seen, fpMap, acc)\n        else do\n          (depPath, fpMap') <- canonicalizeDep depAbs fpMap\n          let typesDir = joinPath [depPath, \"out\", \"types\"]\n          if Data.Set.member depPath seen\n            then return (seen, fpMap', acc)\n            else do\n              let seen' = Data.Set.insert depPath seen\n              (seenNext, fpMapNext, sub) <- go seen' fpMap' depPath Nothing\n              return (seenNext, fpMapNext, acc ++ [typesDir] ++ sub)\n\n    canonicalizeDep depAbs fpMap = do\n      spec0 <- loadBuildSpec depAbs\n      spec <- applyDepOverrides depAbs overrides spec0\n      let (canonPath, fpMap', _) = applyFingerprint depAbs spec fpMap\n      return (canonPath, fpMap')\n\n\n-- | Convert a module name to its source filename (path + .act).\n-- This is used for diagnostics and display output.\nmodNameToFilename :: A.ModName -> String\nmodNameToFilename mn = joinPath (map nameToString names) ++ \".act\"\n  where\n    A.ModName names = mn\n\n-- | Render a module name as a dotted string (foo.bar.baz).\nmodNameToString :: A.ModName -> String\nmodNameToString (A.ModName names) = intercalate \".\" (map nameToString names)\n\n-- | Render a name identifier to a plain string.\nnameToString :: A.Name -> String\nnameToString (A.Name _ s) = s\n\n\n-- | Check whether a NameInfo represents a root-eligible actor.\n-- Used to decide which roots to include in .ty headers and root generation.\nrootEligible :: I.NameInfo -> Bool\nrootEligible (I.NAct [] p k _ _) = case (p,k) of\n                                      (A.TNil{}, A.TRow _ _ _ t A.TNil{}) ->\n                                        prstr t == \"Env\" || prstr t == \"None\" ||\n                                        prstr t == \"__builtin__.Env\" || prstr t == \"__builtin__.None\"\n                                      _ -> False\nrootEligible _ = False\n\n-- | Determine whether any non-standard output mode is enabled.\n-- Used to suppress normal timing/output when dumping parse/sigs/cgen, etc.\naltOutput :: C.CompileOptions -> Bool\naltOutput opts =\n  (C.parse opts) || (C.parse_ast opts) || (C.kinds opts) || (C.types opts) || (C.sigs opts) || (C.norm opts) || (C.deact opts) || (C.cps opts) || (C.llift opts) || (C.box opts) || (C.hgen opts) || (C.cgen opts)\n\n-- | Read a UTF-8 text file with explicit encoding.\n-- Keeps compiler IO consistent across platforms.\nreadFile :: FilePath -> IO String\nreadFile f = do\n    h <- openFile f ReadMode\n    hSetEncoding h utf8\n    c <- hGetContents h\n    return c\n\n-- | Write a UTF-8 text file atomically.\n-- Used for generated sources and BuildSpec parsing.\nwriteFile :: FilePath -> String -> IO ()\nwriteFile = writeFileUtf8Atomic\n\n-- | Format a TimeSpec as a fixed-width seconds string.\n-- Used for stable logging and snapshot test output.\nfmtTime :: TimeSpec -> String\nfmtTime t =\n    printf \"%6.3f s\" secs\n  where\n    secs :: Float\n    secs = (fromIntegral(sec t)) + (fromIntegral (nsec t) / 1000000000)\n\n-- | Topologically order projects so dependencies come first.\n-- Used to build search paths and providers in dependency order.\nprojDepClosure :: M.Map FilePath ProjCtx -> FilePath -> [FilePath]\nprojDepClosure ctxs root = reverse (dfs Data.Set.empty [] root)\n  where\n    depsOf p = maybe [] (map snd . projDeps) (M.lookup p ctxs)\n\n    dfs seen acc node\n      | Data.Set.member node seen = acc\n      | otherwise =\n          let seen' = Data.Set.insert node seen\n              acc'  = foldl' (\\a n -> dfs seen' a n) acc (depsOf node)\n          in node : acc'\n"
  },
  {
    "path": "compiler/lib/src/Acton/Completion.hs",
    "content": "{-# LANGUAGE ScopedTypeVariables #-}\n\nmodule Acton.Completion\n  ( Completion(..)\n  , CompletionKind(..)\n  , CallSignature(..)\n  , HoverInfo(..)\n  , SignatureParameter(..)\n  , CallRequest(..)\n  , ArgumentRequest(..)\n  , MemberRequest(..)\n  , argumentCompletions\n  , argumentCompletionsWithEnv\n  , callContextAt\n  , callSignatures\n  , callSignaturesWithEnv\n  , completionImportKey\n  , hoverInfo\n  , hoverInfoWithEnv\n  , memberContextAt\n  , memberCompletions\n  , memberCompletionsWithEnv\n  , prepareCompletionEnv\n  ) where\n\nimport qualified Control.Exception as E\nimport Control.Monad (foldM)\nimport qualified Control.Monad.Trans.State.Strict as St\nimport Data.Char (isAlpha, isAlphaNum, isSpace)\nimport Data.List (find, findIndex, intercalate, isPrefixOf, nubBy)\nimport Data.Maybe (listToMaybe, mapMaybe)\nimport qualified Data.HashMap.Strict as HM\nimport qualified InterfaceFiles as IF\nimport Text.Megaparsec (eof, runParser)\n\nimport qualified Acton.Env as Env\nimport qualified Acton.NameInfo as I\nimport qualified Acton.Parser as P\nimport qualified Acton.Syntax as S\nimport Utils (prstr)\n\ndata CompletionKind\n  = CompletionField\n  | CompletionMethod\n  | CompletionProperty\n  | CompletionValue\n  | CompletionKeyword\n  deriving (Eq, Show)\n\ndata Completion = Completion\n  { completionLabel :: String\n  , completionKind :: CompletionKind\n  , completionDetail :: Maybe String\n  } deriving (Eq, Show)\n\ndata MemberRequest = MemberRequest\n  { memberReceiver :: String\n  , memberPrefix :: String\n  } deriving (Eq, Show)\n\ndata CallRequest = CallRequest\n  { callTarget :: [String]\n  , callActiveParameter :: Int\n  , callArgumentText :: String\n  } deriving (Eq, Show)\n\ndata ArgumentRequest = ArgumentRequest\n  { argumentTarget :: [String]\n  , argumentPrefix :: String\n  , argumentSuppliedKeywords :: [String]\n  } deriving (Eq, Show)\n\ndata SignatureParameter = SignatureParameter\n  { signatureParameterLabel :: String\n  } deriving (Eq, Show)\n\ndata CallSignature = CallSignature\n  { callSignatureLabel :: String\n  , callSignatureParameters :: [SignatureParameter]\n  , callSignatureActiveParameter :: Int\n  } deriving (Eq, Show)\n\ndata HoverInfo = HoverInfo\n  { hoverLabel :: String\n  , hoverDetail :: String\n  , hoverDocumentation :: Maybe String\n  } deriving (Eq, Show)\n\ndata StringState = StringState Char Bool deriving (Eq, Show)\n\ndata SourceContext = SourceContext\n  { sourceClass :: Maybe ClassContext\n  , sourceDef :: Maybe DefContext\n  , sourceLocalBindings :: [LocalBinding]\n  } deriving (Eq, Show)\n\ndata ClassContext = ClassContext\n  { className :: String\n  , classParents :: [String]\n  , classIndent :: Int\n  } deriving (Eq, Show)\n\ndata DefContext = DefContext\n  { defName :: String\n  , defParams :: [Param]\n  , defIndent :: Int\n  } deriving (Eq, Show)\n\ndata Param = Param\n  { paramName :: String\n  , paramAnn :: Maybe String\n  } deriving (Eq, Show)\n\ndata LocalBinding = LocalBinding\n  { localName :: String\n  , localClassName :: Maybe String\n  , localClassIndent :: Maybe Int\n  , localDefName :: String\n  , localDefIndent :: Int\n  , localKind :: LocalKind\n  } deriving (Eq, Show)\n\ndata LocalKind\n  = LocalAnnotated String\n  | LocalCallResult [String]\n  | LocalMemberPath [String]\n  deriving (Eq, Show)\n\ndata HoverTarget = HoverTarget\n  { hoverResolvedType :: S.Type\n  , hoverResolvedDoc :: Maybe String\n  } deriving (Eq, Show)\n\ndata KeywordParameter = KeywordParameter\n  { keywordParameterName :: String\n  , keywordParameterType :: S.Type\n  } deriving (Eq, Show)\n\ndata Scope = ScopeClass ClassContext | ScopeDef DefContext deriving (Eq, Show)\n\ndata ScanState = ScanState\n  { scanScopes :: [Scope]\n  , scanLocals :: [LocalBinding]\n  } deriving (Eq, Show)\n\nmemberCompletions :: Env.Env0 -> [FilePath] -> S.ModName -> FilePath -> String -> Int -> IO [Completion]\nmemberCompletions baseEnv searchPath modName fileName src cursor = do\n  res <- E.try $ do\n    case memberContextAt src cursor of\n      Nothing -> return []\n      Just req -> do\n        env <- prepareCompletionEnv baseEnv searchPath modName fileName src\n        let ctx = scanSourceContext src cursor\n            comps = completeMember env ctx req\n        E.evaluate (forceCompletions comps)\n  case res of\n    Left (_ :: E.SomeException) -> return []\n    Right comps -> return comps\n\nmemberCompletionsWithEnv :: Env.Env0 -> String -> Int -> [Completion]\nmemberCompletionsWithEnv env src cursor =\n  case memberContextAt src cursor of\n    Nothing -> []\n    Just req ->\n      let ctx = scanSourceContext src cursor\n      in completeMember env ctx req\n\nargumentCompletions :: Env.Env0 -> [FilePath] -> S.ModName -> FilePath -> String -> Int -> IO [Completion]\nargumentCompletions baseEnv searchPath modName fileName src cursor = do\n  res <- E.try $ do\n    case argumentContextAt src cursor of\n      Nothing -> return []\n      Just req -> do\n        env <- prepareCompletionEnv baseEnv searchPath modName fileName src\n        let ctx = scanSourceContext src cursor\n            comps = completeArguments env ctx req\n        E.evaluate (forceCompletions comps)\n  case res of\n    Left (_ :: E.SomeException) -> return []\n    Right comps -> return comps\n\nargumentCompletionsWithEnv :: Env.Env0 -> String -> Int -> [Completion]\nargumentCompletionsWithEnv env src cursor =\n  case argumentContextAt src cursor of\n    Nothing -> []\n    Just req ->\n      let ctx = scanSourceContext src cursor\n      in completeArguments env ctx req\n\ncallSignatures :: Env.Env0 -> [FilePath] -> S.ModName -> FilePath -> String -> Int -> IO [CallSignature]\ncallSignatures baseEnv searchPath modName fileName src cursor = do\n  res <- E.try $ do\n    case callContextAt src cursor of\n      Nothing -> return []\n      Just req -> do\n        env <- prepareCompletionEnv baseEnv searchPath modName fileName src\n        let ctx = scanSourceContext src cursor\n            sigs = maybe [] (:[]) (callSignature env ctx req)\n        E.evaluate (forceSignatures sigs)\n  case res of\n    Left (_ :: E.SomeException) -> return []\n    Right sigs -> return sigs\n\ncallSignaturesWithEnv :: Env.Env0 -> String -> Int -> [CallSignature]\ncallSignaturesWithEnv env src cursor =\n  case callContextAt src cursor of\n    Nothing -> []\n    Just req ->\n      let ctx = scanSourceContext src cursor\n      in maybe [] (:[]) (callSignature env ctx req)\n\nhoverInfo :: Env.Env0 -> [FilePath] -> S.ModName -> FilePath -> String -> Int -> IO (Maybe HoverInfo)\nhoverInfo baseEnv searchPath modName fileName src cursor = do\n  res <- E.try $ do\n    case hoverTargetAt src cursor of\n      Nothing -> return Nothing\n      Just parts -> do\n        env <- prepareCompletionEnv baseEnv searchPath modName fileName src\n        let ctx = scanSourceContext src cursor\n            info = hoverInfoForParts env ctx parts\n        E.evaluate (forceMaybeHover info)\n  case res of\n    Left (_ :: E.SomeException) -> return Nothing\n    Right info -> return info\n\nhoverInfoWithEnv :: Env.Env0 -> String -> Int -> Maybe HoverInfo\nhoverInfoWithEnv env src cursor = do\n  parts <- hoverTargetAt src cursor\n  let ctx = scanSourceContext src cursor\n  hoverInfoForParts env ctx parts\n\nprepareCompletionEnv :: Env.Env0 -> [FilePath] -> S.ModName -> FilePath -> String -> IO Env.Env0\nprepareCompletionEnv baseEnv searchPath modName fileName src = do\n  imps <- parseImports fileName src\n  completionEnv searchPath baseEnv modName imps\n\ncompletionImportKey :: FilePath -> String -> IO String\ncompletionImportKey fileName src = do\n  imps <- parseImports fileName src\n  return (show imps)\n\nmemberContextAt :: String -> Int -> Maybe MemberRequest\nmemberContextAt src cursor =\n  case restAfterPrefix of\n    '.':rest ->\n      let receiver = reverse (takeWhile receiverChar rest)\n          receiver' = trimDots receiver\n      in if null receiver'\n           then Nothing\n           else Just MemberRequest\n                  { memberReceiver = receiver'\n                  , memberPrefix = reverse prefixRev\n                  }\n    _ -> Nothing\n  where\n    before = take (max 0 (min cursor (length src))) src\n    (prefixRev, restAfterPrefix) = span identChar (reverse before)\n\n    identChar c = isAlphaNum c || c == '_'\n    receiverChar c = identChar c || c == '.' || c == '?'\n    trimDots = reverse . dropWhile (== '.') . reverse . dropWhile (== '.')\n\nhoverTargetAt :: String -> Int -> Maybe [String]\nhoverTargetAt src cursor = do\n  let cursor' = max 0 (min cursor (length src))\n      before = take cursor' src\n      after = drop cursor' src\n      identPrefix = reverse (takeWhile identChar (reverse before))\n      identSuffix = takeWhile identChar after\n      ident = identPrefix ++ identSuffix\n      identStart = cursor' - length identPrefix\n  if not (validIdent ident)\n    then Nothing\n    else do\n      let beforeIdent = take identStart src\n          target =\n            case reverse beforeIdent of\n              '.':rest ->\n                let receiver = reverse (takeWhile receiverChar rest)\n                in receiver ++ \".\" ++ ident\n              _ -> ident\n          parts = receiverParts target\n      if all validIdent parts && not (null parts)\n        then Just parts\n        else Nothing\n  where\n    receiverChar c = identChar c || c == '.' || c == '?'\n\ncallContextAt :: String -> Int -> Maybe CallRequest\ncallContextAt src cursor = do\n  openIx <- activeOpenParen before\n  let args = drop (openIx + 1) before\n      calleeBeforeParen = take openIx before\n      callee = reverse $\n        takeWhile callPathChar $\n        dropWhile isSpace $\n        reverse calleeBeforeParen\n      target = receiverParts callee\n  if null target\n    then Nothing\n    else Just CallRequest\n      { callTarget = target\n      , callActiveParameter = activeArgIndex args\n      , callArgumentText = args\n      }\n  where\n    before = take (max 0 (min cursor (length src))) src\n    callPathChar c = identChar c || c == '.' || c == '?'\n\nargumentContextAt :: String -> Int -> Maybe ArgumentRequest\nargumentContextAt src cursor = do\n  req <- callContextAt src cursor\n  prefix <- activeKeywordPrefix (callArgumentText req)\n  return ArgumentRequest\n    { argumentTarget = callTarget req\n    , argumentPrefix = prefix\n    , argumentSuppliedKeywords = suppliedKeywordNames (callArgumentText req)\n    }\n\nactiveKeywordPrefix :: String -> Maybe String\nactiveKeywordPrefix args = do\n  current <- lastMaybe (splitArgSegments args)\n  if topLevelContains '=' current\n    then Nothing\n    else\n      let prefix = reverse (takeWhile identChar (reverse current))\n          beforePrefix = take (length current - length prefix) current\n      in if all isSpace beforePrefix\n           then Just prefix\n           else Nothing\n\nsuppliedKeywordNames :: String -> [String]\nsuppliedKeywordNames args =\n  mapMaybe keywordName (splitArgSegments args)\n  where\n    keywordName segment =\n      let (lhs, eqPart) = breakArgTopLevel '=' segment\n          nm = trim lhs\n      in case eqPart of\n           '=':_ | validIdent nm -> Just nm\n           _ -> Nothing\n\nsplitArgSegments :: String -> [String]\nsplitArgSegments = reverse . map reverse . go 0 0 0 Nothing [[]]\n  where\n    go _ _ _ _ acc [] = acc\n    go p b c str (x:xs) (ch:chs)\n      | Just st <- str =\n          go p b c (advanceString st ch) ((ch:x):xs) chs\n      | isStringQuote ch = go p b c (Just (StringState ch False)) ((ch:x):xs) chs\n      | ch == ',' && p == 0 && b == 0 && c == 0 = go p b c str ([]:x:xs) chs\n      | ch == '(' = go (p + 1) b c str ((ch:x):xs) chs\n      | ch == ')' = go (max 0 (p - 1)) b c str ((ch:x):xs) chs\n      | ch == '[' = go p (b + 1) c str ((ch:x):xs) chs\n      | ch == ']' = go p (max 0 (b - 1)) c str ((ch:x):xs) chs\n      | ch == '{' = go p b (c + 1) str ((ch:x):xs) chs\n      | ch == '}' = go p b (max 0 (c - 1)) str ((ch:x):xs) chs\n      | otherwise = go p b c str ((ch:x):xs) chs\n    go _ _ _ _ [] _ = []\n\ntopLevelContains :: Char -> String -> Bool\ntopLevelContains needle = go 0 0 0 Nothing\n  where\n    go _ _ _ _ [] = False\n    go p b c str (ch:chs)\n      | Just st <- str =\n          go p b c (advanceString st ch) chs\n      | isStringQuote ch = go p b c (Just (StringState ch False)) chs\n      | ch == needle && p == 0 && b == 0 && c == 0 = True\n      | ch == '(' = go (p + 1) b c str chs\n      | ch == ')' = go (max 0 (p - 1)) b c str chs\n      | ch == '[' = go p (b + 1) c str chs\n      | ch == ']' = go p (max 0 (b - 1)) c str chs\n      | ch == '{' = go p b (c + 1) str chs\n      | ch == '}' = go p b (max 0 (c - 1)) str chs\n      | otherwise = go p b c str chs\n\nbreakArgTopLevel :: Char -> String -> (String, String)\nbreakArgTopLevel needle = go 0 0 0 Nothing []\n  where\n    go _ _ _ _ acc [] = (reverse acc, [])\n    go p b c str acc s@(ch:chs)\n      | Just st <- str =\n          go p b c (advanceString st ch) (ch:acc) chs\n      | isStringQuote ch = go p b c (Just (StringState ch False)) (ch:acc) chs\n      | ch == needle && p == 0 && b == 0 && c == 0 = (reverse acc, s)\n      | ch == '(' = go (p + 1) b c str (ch:acc) chs\n      | ch == ')' = go (max 0 (p - 1)) b c str (ch:acc) chs\n      | ch == '[' = go p (b + 1) c str (ch:acc) chs\n      | ch == ']' = go p (max 0 (b - 1)) c str (ch:acc) chs\n      | ch == '{' = go p b (c + 1) str (ch:acc) chs\n      | ch == '}' = go p b (max 0 (c - 1)) str (ch:acc) chs\n      | otherwise = go p b c str (ch:acc) chs\n\nlastMaybe :: [a] -> Maybe a\nlastMaybe [] = Nothing\nlastMaybe xs = Just (last xs)\n\nactiveOpenParen :: String -> Maybe Int\nactiveOpenParen = listToMaybe . go 0 Nothing []\n  where\n    go _ _ stack [] = stack\n    go ix str stack (ch:chs)\n      | Just st <- str =\n          go (ix + 1) (advanceString st ch) stack chs\n      | isStringQuote ch =\n          go (ix + 1) (Just (StringState ch False)) stack chs\n      | ch == '(' =\n          go (ix + 1) str (ix:stack) chs\n      | ch == ')' =\n          go (ix + 1) str (drop 1 stack) chs\n      | otherwise =\n          go (ix + 1) str stack chs\n\nactiveArgIndex :: String -> Int\nactiveArgIndex = go 0 0 0 0 Nothing\n  where\n    go arg _ _ _ _ [] = arg\n    go arg p b c str (x:xs)\n      | Just st <- str =\n          go arg p b c (advanceString st x) xs\n      | isStringQuote x = go arg p b c (Just (StringState x False)) xs\n      | x == '(' = go arg (p + 1) b c str xs\n      | x == ')' = go arg (max 0 (p - 1)) b c str xs\n      | x == '[' = go arg p (b + 1) c str xs\n      | x == ']' = go arg p (max 0 (b - 1)) c str xs\n      | x == '{' = go arg p b (c + 1) str xs\n      | x == '}' = go arg p b (max 0 (c - 1)) str xs\n      | x == ',' && p == 0 && b == 0 && c == 0 = go (arg + 1) p b c str xs\n      | otherwise = go arg p b c str xs\n\nisStringQuote :: Char -> Bool\nisStringQuote ch = ch == '\"' || ch == '\\''\n\nadvanceString :: StringState -> Char -> Maybe StringState\nadvanceString (StringState quote escaped) ch\n  | escaped = Just (StringState quote False)\n  | ch == '\\\\' = Just (StringState quote True)\n  | ch == quote = Nothing\n  | otherwise = Just (StringState quote False)\n\ncompleteMember :: Env.Env0 -> SourceContext -> MemberRequest -> [Completion]\ncompleteMember env ctx req =\n  case resolveReceiverType env ctx (receiverParts (memberReceiver req)) of\n    Nothing -> []\n    Just typ -> attrsForType env typ (memberPrefix req)\n\ncompleteArguments :: Env.Env0 -> SourceContext -> ArgumentRequest -> [Completion]\ncompleteArguments env ctx req =\n  case resolveCallableInfo env ctx (argumentTarget req) >>= typeOfInfo of\n    Just typ ->\n      case Env.unalias env typ of\n        S.TFun _ _ _ kw _ ->\n          [ Completion\n              (keywordParameterName param ++ \"=\")\n              CompletionKeyword\n              (Just (displayType (keywordParameterType param)))\n          | param <- keywordParameterRows kw\n          , argumentPrefix req `isPrefixOf` keywordParameterName param\n          , keywordParameterName param `notElem` argumentSuppliedKeywords req\n          ]\n        _ -> []\n    _ -> []\n\ncallSignature :: Env.Env0 -> SourceContext -> CallRequest -> Maybe CallSignature\ncallSignature env ctx req = do\n  info <- resolveCallableInfo env ctx (callTarget req)\n  typ <- typeOfInfo info\n  case Env.unalias env typ of\n    S.TFun _ _ pos kw ret ->\n      let params = signatureParameters pos kw\n          active = if null params\n                     then 0\n                     else min (callActiveParameter req) (length params - 1)\n          label = intercalate \".\" (callTarget req)\n            ++ \"(\"\n            ++ intercalate \", \" (map signatureParameterLabel params)\n            ++ \") -> \"\n            ++ displayType ret\n      in Just CallSignature\n        { callSignatureLabel = label\n        , callSignatureParameters = params\n        , callSignatureActiveParameter = active\n        }\n    _ -> Nothing\n\nhoverInfoForParts :: Env.Env0 -> SourceContext -> [String] -> Maybe HoverInfo\nhoverInfoForParts env ctx parts = do\n  target <- hoverTarget env ctx parts\n  let label = intercalate \".\" parts\n  return HoverInfo\n    { hoverLabel = label\n    , hoverDetail = label ++ \": \" ++ displayType (hoverResolvedType target)\n    , hoverDocumentation = hoverResolvedDoc target\n    }\n\nhoverTarget :: Env.Env0 -> SourceContext -> [String] -> Maybe HoverTarget\nhoverTarget env ctx parts =\n  memberHoverTarget env ctx parts\n  <|> baseHoverTarget env ctx parts\n  <|> globalHoverTarget env parts\n\nmemberHoverTarget :: Env.Env0 -> SourceContext -> [String] -> Maybe HoverTarget\nmemberHoverTarget env ctx parts = do\n  (receiver, attr) <- unsnoc parts\n  typ <- resolveReceiverType env ctx receiver\n  tc <- typeTCon env typ\n  info <- attrInfo env tc (S.name attr)\n  attrTyp <- Env.unalias env <$> typeOfInfo info\n  return HoverTarget\n    { hoverResolvedType = attrTyp\n    , hoverResolvedDoc = docOfInfo info <|> typeDoc env attrTyp\n    }\n\nbaseHoverTarget :: Env.Env0 -> SourceContext -> [String] -> Maybe HoverTarget\nbaseHoverTarget env ctx parts = do\n  typ <- resolveReceiverType env ctx parts\n  return HoverTarget\n    { hoverResolvedType = typ\n    , hoverResolvedDoc = typeDoc env typ\n    }\n\nglobalHoverTarget :: Env.Env0 -> [String] -> Maybe HoverTarget\nglobalHoverTarget env parts = do\n  info <- lookupPathInfo env parts\n  typ <- Env.unalias env <$> typeOfInfo info\n  return HoverTarget\n    { hoverResolvedType = typ\n    , hoverResolvedDoc = docOfInfo info <|> typeDoc env typ\n    }\n\nresolveCallableInfo :: Env.Env0 -> SourceContext -> [String] -> Maybe I.NameInfo\nresolveCallableInfo env ctx parts =\n  memberCallableInfo env ctx parts <|> lookupPathInfo env parts\n\nmemberCallableInfo :: Env.Env0 -> SourceContext -> [String] -> Maybe I.NameInfo\nmemberCallableInfo env ctx parts = do\n  (receiver, attr) <- unsnoc parts\n  typ <- resolveReceiverType env ctx receiver\n  tc <- typeTCon env typ\n  attrInfo env tc (S.name attr)\n\nunsnoc :: [a] -> Maybe ([a], a)\nunsnoc [] = Nothing\nunsnoc xs = Just (init xs, last xs)\n\nsignatureParameters :: S.Type -> S.Type -> [SignatureParameter]\nsignatureParameters pos kw =\n  zipWith positional [1..] (positionalTypes pos) ++ keywordParameters kw\n  where\n    positional ix typ =\n      SignatureParameter (\"arg\" ++ show (ix :: Int) ++ \": \" ++ displayType typ)\n\npositionalTypes :: S.Type -> [S.Type]\npositionalTypes row =\n  case row of\n    S.TRow _ S.PRow _ typ rest -> typ : positionalTypes rest\n    S.TStar _ S.PRow rest -> [S.tTupleP rest]\n    _ -> []\n\nkeywordParameters :: S.Type -> [SignatureParameter]\nkeywordParameters row =\n  case row of\n    S.TRow _ S.KRow name typ rest ->\n      SignatureParameter (S.rawstr name ++ \": \" ++ displayType typ) : keywordParameters rest\n    S.TStar _ S.KRow rest ->\n      [SignatureParameter (\"**kwargs: \" ++ displayType (S.tTupleK rest))]\n    _ -> []\n\nkeywordParameterRows :: S.Type -> [KeywordParameter]\nkeywordParameterRows row =\n  case row of\n    S.TRow _ S.KRow name typ rest ->\n      KeywordParameter (S.rawstr name) typ : keywordParameterRows rest\n    _ -> []\n\ncompletionEnv :: [FilePath] -> Env.Env0 -> S.ModName -> [S.Import] -> IO Env.Env0\ncompletionEnv searchPath baseEnv modName imps =\n  Env.mkEnv searchPath baseEnv mod `E.catch` \\(_ :: E.SomeException) ->\n    shallowCompletionEnv searchPath baseEnv imps\n  where\n    mod = S.Module modName imps Nothing []\n\n-- Completion should still work when an otherwise usable direct import records\n-- stale transitive interfaces. Load only the imported modules themselves as a\n-- fallback, which is enough for generated base classes and typed constructors.\nshallowCompletionEnv :: [FilePath] -> Env.Env0 -> [S.Import] -> IO Env.Env0\nshallowCompletionEnv searchPath baseEnv imps =\n  refreshHModules <$> foldM (shallowImport searchPath) baseEnv imps\n\nrefreshHModules :: Env.Env0 -> Env.Env0\nrefreshHModules env =\n  env { Env.hmodules = I.convTEnv2HTEnv (Env.modules env) }\n\nshallowImport :: [FilePath] -> Env.Env0 -> S.Import -> IO Env.Env0\nshallowImport searchPath env imp =\n  case imp of\n    S.Import _ items ->\n      foldM (shallowModuleItem searchPath) env items\n    S.FromImport _ (S.ModRef (0, Just m)) items ->\n      shallowModule searchPath env m $ \\te env' ->\n        Env.importSome items m te env'\n    S.FromImportAll _ (S.ModRef (0, Just m)) ->\n      shallowModule searchPath env m $ \\te env' ->\n        Env.importAll m te env'\n    _ ->\n      return env\n\nshallowModuleItem :: [FilePath] -> Env.Env0 -> S.ModuleItem -> IO Env.Env0\nshallowModuleItem searchPath env (S.ModuleItem m as) =\n  shallowModule searchPath env m $ \\te env' ->\n    case as of\n      Nothing -> Env.addImport m env'\n      Just n -> Env.defineClosed [(n, I.NMAlias m)] env'\n\nshallowModule\n  :: [FilePath]\n  -> Env.Env0\n  -> S.ModName\n  -> (I.TEnv -> Env.Env0 -> Env.Env0)\n  -> IO Env.Env0\nshallowModule searchPath env m applyImport = do\n  loaded <- readModuleInterface searchPath m\n  case loaded of\n    Nothing -> return env\n    Just (ms, te, mdoc) ->\n      return $ applyImport te (Env.addMod m ms te mdoc env)\n\nreadModuleInterface :: [FilePath] -> S.ModName -> IO (Maybe ([S.ModName], I.TEnv, Maybe String))\nreadModuleInterface searchPath m = do\n  mty <- Env.findTyFile searchPath m\n  case mty of\n    Nothing -> return Nothing\n    Just ty -> do\n      res <- (Just <$> IF.readFile ty) `E.catch` \\(_ :: E.SomeException) ->\n        return Nothing\n      case res of\n        Just (_, I.NModule imps te mdoc, _, _, _, _, _, _, _, _, _, _) ->\n          return (Just (imps, te, mdoc))\n        _ ->\n          return Nothing\n\nresolveReceiverType :: Env.Env0 -> SourceContext -> [String] -> Maybe S.Type\nresolveReceiverType _ _ [] = Nothing\nresolveReceiverType env ctx (base:attrs) = do\n  baseType <- resolveBaseType env ctx base\n  foldl step (Just baseType) attrs\n  where\n    step Nothing _ = Nothing\n    step (Just typ) attr = do\n      tc <- typeTCon env typ\n      attrType env tc (S.name attr)\n\nresolveBaseType :: Env.Env0 -> SourceContext -> String -> Maybe S.Type\nresolveBaseType env ctx name =\n  localBindingType env ctx name\n  <|> explicitParamType env ctx name\n  <|> inheritedParamType env ctx name\n\nlocalBindingType :: Env.Env0 -> SourceContext -> String -> Maybe S.Type\nlocalBindingType env ctx name =\n  listToMaybe $ mapMaybe bindingType matching\n  where\n    matching =\n      case sourceDef ctx of\n        Nothing -> []\n        Just def ->\n          filter (sameDef def) $\n            filter ((== name) . localName) (sourceLocalBindings ctx)\n\n    sameDef def binding =\n      localDefName binding == defName def &&\n      localDefIndent binding == defIndent def &&\n      localClassKey binding == sourceClassKey\n\n    sourceClassKey =\n      fmap (\\cls -> (className cls, classIndent cls)) (sourceClass ctx)\n\n    localClassKey binding =\n      (,) <$> localClassName binding <*> localClassIndent binding\n\n    bindingType binding =\n      case localKind binding of\n        LocalAnnotated ann -> parseTypeText env ann\n        LocalCallResult callee -> callResultType env ctx callee\n        LocalMemberPath path -> resolveReceiverType env ctx path\n\nexplicitParamType :: Env.Env0 -> SourceContext -> String -> Maybe S.Type\nexplicitParamType env ctx name = do\n  def <- sourceDef ctx\n  param <- find ((== name) . paramName) (defParams def)\n  ann <- paramAnn param\n  parseTypeText env ann\n\ninheritedParamType :: Env.Env0 -> SourceContext -> String -> Maybe S.Type\ninheritedParamType env ctx name = do\n  cls <- sourceClass ctx\n  def <- sourceDef ctx\n  paramIx <- methodParamIndex name (defParams def)\n  listToMaybe $ mapMaybe (parentParamType paramIx name (defName def)) (classParents cls)\n  where\n    parentParamType ix pname method parentText = do\n      parentType <- parseTypeText env parentText\n      parentTc <- typeTCon env parentType\n      (_, schema, _) <- Env.findAttr env parentTc (S.name method)\n      parentMod <- qnameModule (S.tcname parentTc)\n      Env.unalias (Env.setMod parentMod env) <$> paramTypeFromSchema ix pname schema\n\n    qnameModule qn =\n      case qn of\n        S.QName mn _ -> Just mn\n        S.GName mn _ -> Just mn\n        S.NoQ _ -> Nothing\n\nmethodParamIndex :: String -> [Param] -> Maybe Int\nmethodParamIndex name params = do\n  ix <- findIndex ((== name) . paramName) params\n  let selfOffset = case params of\n                     Param \"self\" _ : _ -> 1\n                     _ -> 0\n      ix' = ix - selfOffset\n  if ix' < 0 then Nothing else Just ix'\n\nparamTypeFromSchema :: Int -> String -> S.TSchema -> Maybe S.Type\nparamTypeFromSchema ix pname (S.TSchema _ _ typ) =\n  case typ of\n    S.TFun _ _ pos kwd _ ->\n      positionalType ix pos <|> keywordType (S.name pname) kwd\n    _ -> Nothing\n\npositionalType :: Int -> S.Type -> Maybe S.Type\npositionalType ix row =\n  case row of\n    S.TRow _ S.PRow _ typ rest\n      | ix == 0 -> Just typ\n      | otherwise -> positionalType (ix - 1) rest\n    _ -> Nothing\n\nkeywordType :: S.Name -> S.Type -> Maybe S.Type\nkeywordType name row =\n  case row of\n    S.TRow _ S.KRow n typ rest\n      | S.rawstr n == S.rawstr name -> Just typ\n      | otherwise -> keywordType name rest\n    _ -> Nothing\n\nattrsForType :: Env.Env0 -> S.Type -> String -> [Completion]\nattrsForType env typ prefix =\n  case typeTCon env typ of\n    Nothing -> []\n    Just tc ->\n      dedup $\n        [ Completion (S.rawstr n) (kindOf info) (detailOf info)\n        | (n, info) <- Env.fullAttrEnv env tc\n        , prefix `isPrefixOf` S.rawstr n\n        ]\n\nattrType :: Env.Env0 -> S.TCon -> S.Name -> Maybe S.Type\nattrType env tc attr =\n  attrInfo env tc attr >>= typeOfInfo\n\nattrInfo :: Env.Env0 -> S.TCon -> S.Name -> Maybe I.NameInfo\nattrInfo env tc attr =\n  snd <$> find ((== S.rawstr attr) . S.rawstr . fst) (Env.fullAttrEnv env tc)\n\ntypeOfInfo :: I.NameInfo -> Maybe S.Type\ntypeOfInfo info =\n  case info of\n    I.NVar t -> Just t\n    I.NSVar t -> Just t\n    I.NDef schema _ _ -> Just (S.sctype schema)\n    I.NSig schema _ _ -> Just (S.sctype schema)\n    _ -> Nothing\n\ncallResultType :: Env.Env0 -> SourceContext -> [String] -> Maybe S.Type\ncallResultType env ctx parts = do\n  info <- resolveCallableInfo env ctx parts\n  functionReturnType env info\n\nlookupPathInfo :: Env.Env0 -> [String] -> Maybe I.NameInfo\nlookupPathInfo _ [] = Nothing\nlookupPathInfo env [n] =\n  lookupQNameInfo env (S.NoQ (S.name n))\nlookupPathInfo env parts =\n  let modPart = init parts\n      n = last parts\n      qn = S.QName (S.ModName (map S.name modPart)) (S.name n)\n  in lookupQNameInfo env qn\n\nlookupQNameInfo :: Env.Env0 -> S.QName -> Maybe I.NameInfo\nlookupQNameInfo env qn =\n  case qn of\n    S.NoQ n ->\n      lookupNoQ n\n    S.QName m n ->\n      lookupModuleItem env (Env.findHMod m env) n\n    S.GName m n\n      | Just m == Env.thismod env ->\n          lookupQNameInfo env (S.NoQ n)\n      | otherwise ->\n          lookupModuleItem env (Env.lookupHMod m env) n\n  where\n    lookupNoQ n              = resolve =<< Env.lookupName n env\n\n    resolve (I.HNAlias qn')  = lookupQNameInfo env qn'\n    resolve info             = Just (I.convHNameInfo2NameInfo info)\n\nlookupModuleItem :: Env.Env0 -> Maybe I.HTEnv -> S.Name -> Maybe I.NameInfo\nlookupModuleItem env mtenv n = do\n  tenv <- mtenv\n  info <- HM.lookup n tenv\n  case info of\n    I.HNAlias qn -> lookupQNameInfo env qn\n    _ -> Just (I.convHNameInfo2NameInfo info)\n\nfunctionReturnType :: Env.Env0 -> I.NameInfo -> Maybe S.Type\nfunctionReturnType env info = do\n  typ <- typeOfInfo info\n  case typ of\n    S.TFun _ _ _ _ ret -> Just (Env.unalias env ret)\n    _ -> Nothing\n\nkindOf :: I.NameInfo -> CompletionKind\nkindOf info =\n  case info of\n    I.NSig schema dec _\n      | dec == S.Property -> CompletionProperty\n      | isFun (S.sctype schema) -> CompletionMethod\n      | otherwise -> CompletionField\n    I.NDef schema dec _\n      | dec == S.Property -> CompletionProperty\n      | isFun (S.sctype schema) -> CompletionMethod\n      | otherwise -> CompletionValue\n    I.NVar{} -> CompletionField\n    I.NSVar{} -> CompletionField\n    _ -> CompletionValue\n  where\n    isFun S.TFun{} = True\n    isFun _ = False\n\ndetailOf :: I.NameInfo -> Maybe String\ndetailOf info =\n  fmap displayType (typeOfInfo info)\n\ndocOfInfo :: I.NameInfo -> Maybe String\ndocOfInfo info =\n  cleanDoc $\n    case info of\n      I.NDef _ _ doc -> doc\n      I.NSig _ _ doc -> doc\n      I.NAct _ _ _ _ doc -> doc\n      I.NClass _ _ _ doc -> doc\n      I.NProto _ _ _ doc -> doc\n      I.NExt _ _ _ _ _ doc -> doc\n      I.NModule _ _ doc -> doc\n      _ -> Nothing\n\ntypeDoc :: Env.Env0 -> S.Type -> Maybe String\ntypeDoc env typ = do\n  tc <- typeTCon env typ\n  info <- lookupTConInfo env tc\n  docOfInfo info\n\nlookupTConInfo :: Env.Env0 -> S.TCon -> Maybe I.NameInfo\nlookupTConInfo env tc =\n  lookupQNameInfo env (S.tcname tc)\n\ncleanDoc :: Maybe String -> Maybe String\ncleanDoc Nothing = Nothing\ncleanDoc (Just doc) =\n  let doc' = trim doc\n  in if null doc' then Nothing else Just doc'\n\ndisplayType :: S.Type -> String\ndisplayType = stripBuiltinPrefix . prstr\n\nstripBuiltinPrefix :: String -> String\nstripBuiltinPrefix [] = []\nstripBuiltinPrefix s\n  | builtinPrefix `isPrefixOf` s =\n      stripBuiltinPrefix (drop (length builtinPrefix) s)\n  | otherwise =\n      head s : stripBuiltinPrefix (tail s)\n  where\n    builtinPrefix = \"__builtin__.\"\n\ntypeTCon :: Env.Env0 -> S.Type -> Maybe S.TCon\ntypeTCon env typ =\n  case typ of\n    S.TCon _ tc -> Just tc\n    S.TOpt _ inner -> typeTCon env inner\n    S.TVar _ tv -> Just (Env.findTVBound env tv)\n    _ -> Nothing\n\nparseTypeText :: Env.Env0 -> String -> Maybe S.Type\nparseTypeText env raw =\n  case runParser (St.evalStateT (P.ttype <* eof) P.initState) \"\" raw of\n    Left _ -> Nothing\n    Right typ -> Just (Env.unalias env typ)\n\nparseImports :: FilePath -> String -> IO [S.Import]\nparseImports fileName src = do\n  res <- E.try (P.parseModuleHeader fileName src)\n  case res of\n    Left (_ :: E.SomeException) -> return []\n    Right (imps, _) -> return imps\n\nscanSourceContext :: String -> Int -> SourceContext\nscanSourceContext src cursor =\n  let st = foldl scanLine (ScanState [] []) (contextLines src cursor)\n      scopes = scanScopes st\n  in SourceContext\n       { sourceClass = listToMaybe [ c | ScopeClass c <- scopes ]\n       , sourceDef = listToMaybe [ d | ScopeDef d <- scopes ]\n       , sourceLocalBindings = scanLocals st\n       }\n\nscanLine :: ScanState -> String -> ScanState\nscanLine st line\n  | null stripped = st\n  | \"#\" `isPrefixOf` stripped = st\n  | otherwise =\n      let indent = lineIndent line\n          scopes' = popClosed indent (scanScopes st)\n      in case parseClass indent stripped of\n           Just cls -> st { scanScopes = ScopeClass cls : scopes' }\n           Nothing ->\n             case parseDef indent stripped of\n               Just def -> st { scanScopes = ScopeDef def : scopes' }\n               Nothing ->\n                 st { scanScopes = scopes'\n                    , scanLocals = scanLocal scopes' stripped (scanLocals st)\n                    }\n  where\n    stripped = trimLeft line\n\nscanLocal :: [Scope] -> String -> [LocalBinding] -> [LocalBinding]\nscanLocal scopes stripped locals\n  | Just def <- activeDef =\n      case parseLocalBinding stripped of\n        Just (nm, kind) ->\n          LocalBinding\n            { localName = nm\n            , localClassName = className <$> activeClass\n            , localClassIndent = classIndent <$> activeClass\n            , localDefName = defName def\n            , localDefIndent = defIndent def\n            , localKind = kind\n            } : locals\n        Nothing -> locals\n  | otherwise = locals\n  where\n    activeDef = listToMaybe [ d | ScopeDef d <- scopes ]\n    activeClass = listToMaybe [ c | ScopeClass c <- scopes ]\n\npopClosed :: Int -> [Scope] -> [Scope]\npopClosed indent = dropWhile ((>= indent) . scopeIndent)\n\nscopeIndent :: Scope -> Int\nscopeIndent (ScopeClass cls) = classIndent cls\nscopeIndent (ScopeDef def) = defIndent def\n\nparseClass :: Int -> String -> Maybe ClassContext\nparseClass indent line\n  | \"class \" `isPrefixOf` line = do\n      let rest = dropWhile isSpace (drop (length \"class \") line)\n          (nm, afterName) = span identChar rest\n      if null nm\n        then Nothing\n        else Just ClassContext\n               { className = nm\n               , classParents = parseParents (skipTypeBinder afterName)\n               , classIndent = indent\n               }\n  | otherwise = Nothing\n\nparseParents :: String -> [String]\nparseParents afterName =\n  case dropWhile isSpace afterName of\n    '(':rest ->\n      case balancedContent '(' ')' rest of\n        Just inside -> filter (not . null) (map trim (splitTopLevel ',' inside))\n        Nothing -> []\n    _ -> []\n\nparseDef :: Int -> String -> Maybe DefContext\nparseDef indent line = do\n  afterDef <- afterDefKeyword line\n  let (nm, afterName) = span identChar (dropWhile isSpace afterDef)\n  paramsText <- case skipTypeBinder afterName of\n                  '(':rest -> balancedContent '(' ')' rest\n                  _ -> Nothing\n  return DefContext\n    { defName = nm\n    , defParams = mapMaybe parseParam (splitTopLevel ',' paramsText)\n    , defIndent = indent\n    }\n\nafterDefKeyword :: String -> Maybe String\nafterDefKeyword line\n  | \"def \" `isPrefixOf` line = Just (drop 4 line)\n  | otherwise =\n      case stripEffect line of\n        Just rest | \"def \" `isPrefixOf` rest -> Just (drop 4 rest)\n        _ -> Nothing\n  where\n    stripEffect s =\n      case words s of\n        w:_ | w `elem` [\"mut\", \"proc\", \"pure\", \"action\"] ->\n              Just (dropWhile isSpace (drop (length w) s))\n        _ -> Nothing\n\nparseParam :: String -> Maybe Param\nparseParam raw\n  | null nm = Nothing\n  | otherwise = Just Param { paramName = nm, paramAnn = ann }\n  where\n    s0 = trim raw\n    s = dropWhile (== '*') s0\n    (beforeDefault, _) = breakTopLevel '=' s\n    (namePart, annPart) = breakTopLevel ':' beforeDefault\n    nm = trim namePart\n    ann = case annPart of\n            ':' : rest ->\n              let a = trim rest\n              in if null a then Nothing else Just a\n            _ -> Nothing\n\nparseLocalBinding :: String -> Maybe (String, LocalKind)\nparseLocalBinding line = do\n  let (lhs, eqPart) = breakTopLevel '=' line\n  rhs <- case eqPart of\n           '=' : rest -> Just rest\n           _ -> Nothing\n  let (namePart, annPart) = breakTopLevel ':' lhs\n      nm = trim namePart\n  if not (validIdent nm)\n    then Nothing\n    else case annPart of\n           ':' : annRaw ->\n             let ann = trim annRaw\n             in if null ann\n                  then Nothing\n                  else Just (nm, LocalAnnotated ann)\n           _ ->\n             case parseCallTarget rhs of\n               Just callee -> Just (nm, LocalCallResult callee)\n               Nothing -> do\n                 path <- parseMemberPath rhs\n                 return (nm, LocalMemberPath path)\n\nparseCallTarget :: String -> Maybe [String]\nparseCallTarget raw =\n  let s = trim raw\n      (callee, rest) = span callPathChar s\n  in case (strictReceiverParts callee, dropWhile isSpace rest) of\n       (Just parts, '(' : _) | validCallPath parts -> Just parts\n       _ -> Nothing\n  where\n    callPathChar c = identChar c || c == '.' || c == '?'\n    validCallPath parts = all validIdent parts && not (null parts)\n\nparseMemberPath :: String -> Maybe [String]\nparseMemberPath raw =\n  let s = trim raw\n      (path, rest) = span memberPathChar s\n  in case strictReceiverParts path of\n       Just parts | all isSpace rest && validMemberPath parts -> Just parts\n       _ -> Nothing\n  where\n    memberPathChar c = identChar c || c == '.' || c == '?'\n    validMemberPath parts = length parts > 1 && all validIdent parts\n\nvalidIdent :: String -> Bool\nvalidIdent [] = False\nvalidIdent (c:cs) = (isAlpha c || c == '_') && all identChar cs\n\ncontextLines :: String -> Int -> [String]\ncontextLines src cursor =\n  let before = take (max 0 (min cursor (length src))) src\n      ls = lines before\n  in case reverse before of\n       '\\n':_ -> ls\n       _ -> case ls of\n              [] -> []\n              _ -> init ls\n\nreceiverParts :: String -> [String]\nreceiverParts =\n  filter (not . null) . map stripOptionalMarker . splitOn '.'\n\nstrictReceiverParts :: String -> Maybe [String]\nstrictReceiverParts raw =\n  let parts = map stripOptionalMarker (splitOn '.' raw)\n  in if any null parts then Nothing else Just parts\n\nstripOptionalMarker :: String -> String\nstripOptionalMarker = reverse . dropWhile (== '?') . reverse\n\nlineIndent :: String -> Int\nlineIndent = go 0\n  where\n    go n (' ':xs) = go (n + 1) xs\n    go n ('\\t':xs) = go (n + 8) xs\n    go n _ = n\n\nidentChar :: Char -> Bool\nidentChar c = isAlphaNum c || c == '_'\n\nsplitOn :: Char -> String -> [String]\nsplitOn sep = splitTopLevel sep\n\nsplitTopLevel :: Char -> String -> [String]\nsplitTopLevel sep = reverse . map reverse . go 0 0 0 [[]]\n  where\n    go _ _ _ acc [] = acc\n    go p b c (x:xs) (ch:chs)\n      | ch == sep && p == 0 && b == 0 && c == 0 = go p b c ([]:x:xs) chs\n      | ch == '(' = go (p + 1) b c ((ch:x):xs) chs\n      | ch == ')' = go (max 0 (p - 1)) b c ((ch:x):xs) chs\n      | ch == '[' = go p (b + 1) c ((ch:x):xs) chs\n      | ch == ']' = go p (max 0 (b - 1)) c ((ch:x):xs) chs\n      | ch == '{' = go p b (c + 1) ((ch:x):xs) chs\n      | ch == '}' = go p b (max 0 (c - 1)) ((ch:x):xs) chs\n      | otherwise = go p b c ((ch:x):xs) chs\n    go _ _ _ [] _ = []\n\nbreakTopLevel :: Char -> String -> (String, String)\nbreakTopLevel needle = go 0 0 0 []\n  where\n    go _ _ _ acc [] = (reverse acc, [])\n    go p b c acc s@(ch:chs)\n      | ch == needle && p == 0 && b == 0 && c == 0 = (reverse acc, s)\n      | ch == '(' = go (p + 1) b c (ch:acc) chs\n      | ch == ')' = go (max 0 (p - 1)) b c (ch:acc) chs\n      | ch == '[' = go p (b + 1) c (ch:acc) chs\n      | ch == ']' = go p (max 0 (b - 1)) c (ch:acc) chs\n      | ch == '{' = go p b (c + 1) (ch:acc) chs\n      | ch == '}' = go p b (max 0 (c - 1)) (ch:acc) chs\n      | otherwise = go p b c (ch:acc) chs\n\nskipTypeBinder :: String -> String\nskipTypeBinder raw =\n  case dropWhile isSpace raw of\n    '[':rest ->\n      case balancedContentRest '[' ']' rest of\n        Just (_, after) -> dropWhile isSpace after\n        Nothing -> dropWhile isSpace raw\n    rest -> rest\n\nbalancedContent :: Char -> Char -> String -> Maybe String\nbalancedContent open close src =\n  fst <$> balancedContentRest open close src\n\nbalancedContentRest :: Char -> Char -> String -> Maybe (String, String)\nbalancedContentRest open close = go 1 []\n  where\n    go 0 acc rest = Just (reverse acc, rest)\n    go _ _ [] = Nothing\n    go n acc (ch:chs)\n      | ch == open = go (n + 1) (ch:acc) chs\n      | ch == close =\n          if n == 1\n            then Just (reverse acc, chs)\n            else go (n - 1) (ch:acc) chs\n      | otherwise = go n (ch:acc) chs\n\ntrimLeft :: String -> String\ntrimLeft = dropWhile isSpace\n\ntrim :: String -> String\ntrim = reverse . dropWhile isSpace . reverse . dropWhile isSpace\n\ndedup :: [Completion] -> [Completion]\ndedup = nubBy (\\a b -> completionLabel a == completionLabel b)\n\nforceCompletions :: [Completion] -> [Completion]\nforceCompletions xs =\n  sum [ length (completionLabel c)\n      + maybe 0 length (completionDetail c)\n      + kindCode (completionKind c)\n      | c <- xs\n      ] `seq` xs\n  where\n    kindCode CompletionField = 1\n    kindCode CompletionMethod = 2\n    kindCode CompletionProperty = 3\n    kindCode CompletionValue = 4\n    kindCode CompletionKeyword = 5\n\nforceSignatures :: [CallSignature] -> [CallSignature]\nforceSignatures xs =\n  sum [ length (callSignatureLabel sig)\n      + callSignatureActiveParameter sig\n      + sum (map (length . signatureParameterLabel) (callSignatureParameters sig))\n      | sig <- xs\n      ] `seq` xs\n\nforceMaybeHover :: Maybe HoverInfo -> Maybe HoverInfo\nforceMaybeHover info =\n  case info of\n    Nothing -> Nothing\n    Just hover ->\n      length (hoverLabel hover)\n      + length (hoverDetail hover)\n      + maybe 0 length (hoverDocumentation hover) `seq` info\n\n(<|>) :: Maybe a -> Maybe a -> Maybe a\nNothing <|> b = b\na <|> _ = a\n"
  },
  {
    "path": "compiler/lib/src/Acton/Converter.hs",
    "content": "-- Copyright (C) 2019-2021 Data Ductus AB\n--\n-- Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:\n--\n-- 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.\n--\n-- 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.\n--\n-- 3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission.\n--\n-- THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS \"AS IS\" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n--\n\n{-# LANGUAGE FlexibleInstances, FlexibleContexts #-}\nmodule Acton.Converter where\n\nimport Pretty\nimport Utils\nimport Acton.Syntax\nimport Acton.Names\nimport Acton.Builtin\nimport Acton.Prim\nimport Acton.NameInfo\nimport Acton.Env\nimport Acton.Subst\nimport Acton.TypeEnv\nimport qualified Data.Map.Strict as Map\nimport Data.Map.Strict (Map)\n\npruneStmts xs (Signature l ns t d : ss)\n  | null ns'                            = pruneStmts xs ss\n  | otherwise                           = Signature l ns' t d : pruneStmts xs ss\n  where ns'                             = ns `intersect` xs\npruneStmts xs (Decl l ds : ss)\n  | null ds'                            = pruneStmts xs ss\n  | otherwise                           = Decl l ds' : pruneStmts xs ss\n  where ds'                             = filter ((`elem`xs) . dname) ds\npruneStmts xs (s@Assign{} : ss)\n  | null ns                             = pruneStmts xs ss\n  | otherwise                           = s : pruneStmts xs ss\n  where ns                              = bound s `intersect` xs\npruneStmts xs (s : ss)                  = s : pruneStmts xs ss\npruneStmts xs []                        = []\n\npruneBody env n ss                      = pruneStmts xs ss\n  where xs                              = directAttrs env n\n\nconvProtocol env n0 q ps0 eq wmap b     = mainClass : sibClasses\n  where ps                              = trim ps0\n        q1                              = qSelf' : noqual env q\n        p0                              = TC (NoQ n0) $ map tVar $ qbound q\n        t0                              = tCon $ convProto p0\n        w0                              = witAttr (NoQ n0)\n        main                            = head bases\n        bases                           = [ convProto p | (ws,p) <- ps0, null (catRight ws) ] ++ [cValue]\n\n        immsibs                         = [ (witAttr w, tCon $ convProto p, inherited ws0) | ([w],ws0,p) <- ps ]\n\n        mainClass                       = --trace (\"###  MRO for \" ++ prstr n0 ++ \": \" ++ prstrs ps0) $\n                                          --trace (\"  # SIBS for \" ++ prstr n0 ++ \": \" ++ prstrs [ sibName ws n0 | (ws,_,_,_,_) <- allsibs ]) $\n                                          Class NoLoc n0 q1 bases mainClassBody Nothing\n          where mainClassBody           = qsigs ++ psigs ++ bindWits eq ++ Decl NoLoc [mainInit] : convStmts tSelf' eq1 (pruneBody env (NoQ n0) b)\n                psigs                   = [ Signature NoLoc [n] (monotype t) Property | (n,t,False) <- immsibs ]\n                mainInit                = Def NoLoc initKW [] mainParams KwdNIL (Just tNone) (mkBody mainInitBody) NoDec fxPure Nothing\n                mainParams              = wit2par ((selfKW',tSelf) : qpars ++ [ (n,t) | (n,t,_) <- immsibs ]) PosNIL\n                mainInitBody            = bindWits eq0 ++ initCall (tcargs main) mainArgs main ++ mainCopies\n                mainArgs                = witArgs (tcname main) wmap ++ [ eVar n | (n,_,True) <- immsibs ]\n                mainCopies              = qcopies ++ [ MutAssign NoLoc (eDot (eVar selfKW') n) (eVar n) | (n,t,False) <- immsibs ]\n                eq0                     = mkEqn env (tvarWit tvSelf p0) t0 (eVar selfKW') : []\n                eq1                     = mkEqn env (tvarWit tvSelf p0) t0 (eVar selfKW') : qcopies'\n\n        allsibs                         = [ sib ws ws0 p | (ws,ws0,p) <- ps, not (null ws) ]\n          where sib ws ws0 p            = (ws, tcname p, us, witArgs w0 wmap, inherited ws0)\n                  where us              = us0 ++ us1\n                        us1             = [ convProto p | (ws',p) <- ps0, catRight ws' == ws ] ++ [cValue]\n                        us0             = [ TC (baseGName w) (tcargs $ head us1) | w <- zipWith (:) (wheads ws0) (wtails ws0) ]\n                        w0              = if inherited ws0 then tcname main else tcname p\n\n        sibClasses                      = [ Class NoLoc (sibName ws n0) q1 us (sibClassBody ws n (head us) wes inh) Nothing | (ws,n,us,wes,inh) <- allsibs ]\n\n        sibClassBody ws n p wes inh     = qsigs ++ psigs ++ bindWits eq ++ Decl NoLoc [sibInit] : convStmts tSelf' eq1 (pruneBody env n b)\n          where sibInit                 = Def NoLoc initKW [] sibParams KwdNIL (Just tNone) (mkBody sibInitBody) NoDec fxPure Nothing\n                sibParams               = wit2par ((selfKW',tSelf) : qpars ++ sibSubParams ++ sibCtxt) PosNIL\n                sibCtxt                 = witCtxt ps ws ++ [(w0,t0)]\n                sibInitBody             = bindWits eq0 ++ initCall (tcargs p) (wes ++ sibSubArgs ++ sibCtxtArgs) p ++ sibCopies\n                sibCopies               = qcopies ++ [ MutAssign NoLoc (eDot (eVar selfKW') w0) (eVar w0) ]\n                sibSubParams            = [ (witAttr (last ws'), tCon $ convProto p') | (ws',_,p') <- ps, truePrefix ws ws' ]\n                sibSubArgs              = [ eVar (witAttr (last ws')) | (ws',_,p') <- ps, truePrefix ws ws' ]\n                sibCtxtArgs             = (if inh then id else init) [ eVar n | (n,t) <- sibCtxt ]\n                eq0                     = mkEqn env (tvarWit tvSelf p0) t0 (eVar w0) : []\n                eq1                     = mkEqn env (tvarWit tvSelf p0) t0 (eDot (eVar selfKW') w0) : qcopies'\n\n        qsigs                           = [ Signature NoLoc [qualAttr p v n0] (monotype $ proto2type (tVar v) p) Property | (v,p) <- quals env q ]\n        psigs                           = [ Signature NoLoc [w0] (monotype t0) Property ]\n        qpars                           = [ (tvarWit v p, proto2type (tVar v) p) | (v,p) <- quals env q ]\n        qcopies                         = [ MutAssign NoLoc (eDot (eVar selfKW') $ qualAttr p v n0) (eVar $ tvarWit v p) | (v,p) <- quals env q ]\n        qcopies'                        = [ mkEqn env (tvarWit v p) (proto2type (tVar v) p) (eDot (eVar selfKW') $ qualAttr p v n0) | (v,p) <- quals env q ]\n\ninherited (Left _ : _)                  = True\ninherited _                             = False\n\nwtails (w:ws)\n  | null ws'                            = []\n  | otherwise                           = ws' : wtails ws\n  where ws'                             = catRight ws\n\nwheads (Right w:ws)\n  | null $ catRight ws                  = []\n  | otherwise                           = w : wheads ws\nwheads (Left w:ws)                      = w : wheads ws\n\ngroupBranch ([],_) m                    = m\ngroupBranch p@(w:_,_) m                 = Map.insertWith (++) w [p] m\n\nconvExtension env n1 c0 q ps0 eq wmap b opts\n                                        = mainClass : sibClasses\n  where pss                             = Map.elems $ foldr groupBranch Map.empty ps0\n        ps                              = trim ps0\n        q1                              = noqual env q\n        tvs                             = map tVar $ qbound q1\n        t0                              = tCon c0\n        w0                              = witAttr (tcname main)\n        ts                              = tcargs main\n        main                            = head bases\n        bases                           = [ instProto t0 p | (ws,p) <- ps0, null (catRight ws) ] ++ [cValue]\n\n        mainClass                       = --trace (\"###  mro for \" ++ prstr n1 ++ \": \" ++ prstrs ps0) $\n                                          --trace (\"### branches for \" ++ prstr n1 ++ \"\\n\" ++ render (nest 4 $ vcat [ commaSep pretty ps1 | ps1 <- pss ])) $\n                                          --trace (\"  # sibs for \" ++ prstr n1 ++ \": \" ++ prstrs [ sibName ws n1 | (ws,_,_,_,_) <- allsibs ]) $\n                                          Class NoLoc n1 q1 bases mainClassBody Nothing\n          where mainClassBody           = qsigs ++ bindWits eq ++ Decl NoLoc [mainInit] : convStmts t0 eq1 (pruneBody env (tcname main) b)\n                mainInit                = Def NoLoc initKW [] mainParams KwdNIL (Just tNone) (mkBody mainInitBody) NoDec fxPure Nothing\n                mainParams              = wit2par ((selfKW',tSelf) : qpars ++ optpars) PosNIL\n                optpars                 = [ (witAttr (NoQ n), tCon (TC (NoQ n) (map tVar $ qbound q1))) | n <- opts ]\n                mainInitBody            = bindWits eq0 ++ initCall ts (witArgs (tcname main) wmap ++ sibSubs []) main ++ qcopies\n                eq0                     = mkEqn env thisKW' (tCon main) (eVar selfKW') : []\n                eq1                     = mkEqn env thisKW' (tCon main) (eVar selfKW') : qcopies'\n\n        allsibs                         = [ sib ws ws0 p | (ws,ws0,p) <- ps, not (null ws) ]\n          where sib ws ws0 p            = (ws, tcname p, us, witArgs w0 wmap, inherited ws0)\n                  where us              = us0 ++ us1\n                        us1             = [ instProto t0 p | (ws',p) <- ps0, catRight ws' == ws ] ++ [cValue]\n                        us0             = [ TC (baseGName w) (tcargs $ head us1) | w <- zipWith (:) (wheads ws0) (wtails ws0) ]\n                        w0              = if inherited ws0 then tcname main else tcname p\n\n        sibClasses                      = [ Class NoLoc (sibName ws n1) q1 us (sibClassBody ws n (head us) wes inh) Nothing | (ws,n,us,wes,inh) <- allsibs ]\n\n        sibClassBody ws n p wes inh     = qsigs ++ bindWits eq ++ Decl NoLoc [sibInit] : convStmts t0 eq1 (pruneBody env n b)\n          where sibInit                 = Def NoLoc initKW [] sibParams KwdNIL (Just tNone) (mkBody sibInitBody) NoDec fxPure Nothing\n                sibParams               = wit2par ((selfKW',tSelf) : qpars ++ sibCtxt) PosNIL\n                sibCtxt                 = witCtxt ps ws ++ [(w0,tCon main)]\n                sibInitBody             = bindWits eq0 ++ initCall ts (wes ++ sibSubs ws ++ sibArgs ws) p ++ qcopies\n                eq0                     = mkEqn env thisKW' (tCon main) (eVar  w0) : []\n                eq1                     = mkEqn env thisKW' (tCon main) (eDot (eVar selfKW') w0) : qcopies'\n\n        sibSubs ws                      = [ eCall (tApp (eVar $ sibName ws' n1) tvs) (qargs ++ eVar selfKW' : sibArgs ws) | (ws',_,p') <- ps, truePrefix ws ws' ]\n\n        sibArgs []                      = []\n        sibArgs ws                      = map eVar (map witAttr $ init ws) ++ [eVar w0]\n\n        qsigs                           = [ Signature NoLoc [qualAttr p v n1] (monotype $ proto2type (tVar v) p) Property | (v,p) <- quals env q ]\n        qpars                           = [ (tvarWit v p, proto2type (tVar v) p) | (v,p) <- quals env q ]\n        qargs                           = [ eVar n | (n,p) <- qpars ]\n        qcopies                         = [ MutAssign NoLoc (eDot (eVar selfKW') $ qualAttr p v n1) (eVar $ tvarWit v p) | (v,p) <- quals env q ]\n        qcopies'                        = [ mkEqn env (tvarWit v p) (proto2type (tVar v) p) (eDot (eVar selfKW') $ qualAttr p v n1) | (v,p) <- quals env q ]\n\n\ntrim ps0                                = nubBy eqWit [ (catRight ws0, ws0, p) | (ws0,p) <- ps0 ]\n  where eqWit (ws1,_,_) (ws2,_,_)       = ws1 == ws2\n\ntruePrefix pre ws\n  | Just [_] <- stripPrefix pre ws      = True\n  | otherwise                           = False\n\nwitCtxt ps ws                           = ctxt $ tail $ reverse ws\n  where ctxt []                         = []\n        ctxt (w:ws)                     = (witAttr w, fromJust $ lookup (w:ws) typemap) : ctxt ws\n        typemap                         = [ (reverse ws, tCon $ convProto p) | (ws,_,p) <- ps ]\n\ninitCall ts args p\n  | tcname p == qnValue                 = []\n  | otherwise                           = [Expr NoLoc (eCall (tApp (eDot (eQVar (tcname p)) initKW) ts) (eVar selfKW' : args))]\n\nwitArgs w wmap                          = case lookup w wmap of\n                                            Just es -> es\n                                            Nothing -> []   -- must be 'value'\n                                            -- Nothing -> trace (\"##### wmap empty for \" ++ prstrs ws) []\n\nnoqual env q                            = [ QBind v (filter (not . isProto env . tcname) us) | QBind v us <- q ]\n\nquals env q                             = [ (v, p) | QBind v ps <- q, p <- ps, isProto env (tcname p) ]\n\nqualAttr p v n                          = Derived (tvarWit v p) n\n\nsibName ws n                            = Derived (baseName ws) n\n\nbaseName [w]                            = deriveQ w\nbaseName (w : ws)                       = Derived (baseName ws) (deriveQ w)\n\nbaseGName ws                            = modOf (head ws) $ baseName ws\n\nmodOf (NoQ _)                           = NoQ\nmodOf (QName m _)                       = QName m\nmodOf (GName m _)                       = GName m\n\n\nconvProto (TC n ts)                     = TC n (tSelf' : convSelf tSelf' ts)\n\ninstProto t (TC n ts)                   = TC n (t : convSelf t ts)\n\nselfpar                                 = TV KType g_self\ntSelf'                                  = tVar selfpar\nqSelf'                                  = QBind selfpar []\n\nconvSelf t0 t                           = vsubst [(tvSelf, t0)] t\n\nconvStmts t0 eq stmts                   = map conv stmts\n  where conv (Signature l ns sc Static) = Signature l ns (convSelf t0 sc) NoDec\n        conv (Signature l ns sc _)      = Signature l ns (convSelf t0 $ convS sc) NoDec\n        conv (Decl l ds)                = Decl l (map convD ds)\n        conv s                          = s\n        convS (TSchema l q t)           = TSchema l (q) (convT t)\n        convT (TFun l fx p k t)         = TFun l fx (posRow (tVar tvSelf) p) k t\n        convT t                         = t\n        convD (Def l n q p k t b _ x ddoc)\n                                        = Def l n (convSelf t0 q) (wit2par [(selfKW',tSelf)] $ convSelf t0 p) (convSelf t0 k) (convSelf t0 t) b' NoDec x ddoc\n          where b'                      = bindWits eq ++ b\n        convD d                         = d\n\nfixupSelf (Decl l ds)                   = Decl l (map fixup ds)\n  where fixup c@Class{}                 = c{ dbody = map fixupSelf (dbody c) }\n        fixup d@Def{pos = PosPar n t e p} | n == selfKW'\n                                        = d{ pos = PosPar n t e (fix p), kwd = fix (kwd d), ann = fix (ann d), dbody = fix (dbody d) }\n        fixup d                         = d\n        fix x                           = convSelf tSelf' x\nfixupSelf s                             = s\n\n\n-- Convert a TEnv -------------------------------------------------------------------------------------------\n\nconvEnvProtos env                       = mapModules conv env\n  where\n    conv env1 m (n, NDef sc d doc)      = [(n, NDef (convS sc) d doc)]\n    conv env1 m (n, NSig sc d doc)      = [(n, NSig (convS sc) d doc)]\n    conv env1 m (n, NAct q p k te doc)  = [(n, NAct (noqual env q) (qualWRow env q p) k (concat $ map (conv env m) te) doc)]\n    conv env1 m ni@(n, NProto q us te doc)\n                                        = map (fromClass env) $ convProtocol (define [ni] env) n q us [] [] (fromTEnv te)\n    conv env1 m ni@(n, NExt q c us te opts doc)\n                                        = map (fromClass env) $ convExtension (define [ni] env) n c q us [] [] (fromTEnv te) opts\n    conv env1 m (n, NClass q us te doc) = [(n, NClass (noqual env q) us (convClassTEnv env q te) doc)]\n    conv env1 m ni                      = [ni]\n    convS (TSchema l q t)               = TSchema l (noqual env q) (convT q t)\n    convT q (TFun l x p k t)            = TFun l x (qualWRow env q p) k t\n    convT q t                           = t\n\nfromClass env (Class _ n q us b ddoc)   = (n, NClass q (leftpath us) (fromStmts env b) ddoc)\n\nfromStmts env (Signature _ ns sc d : ss)= [ (n, NSig (convS sc) d Nothing) | n <- ns ] ++ fromStmts env ss\n  where convS (TSchema l q t)           = TSchema l (noqual env q) (convT q t)\n        convT q (TFun l x p k t)        = TFun l x (qualWRow env q p) k t\n        convT q t                       = t\nfromStmts env (Decl _ ds : ss)          = fromDefs env ds ++ fromStmts env ss\nfromStmts env (Assign _ [PVar _ n (Just t)] _ : ss)\n                                        = (n, NVar t) : fromStmts env ss\nfromStmts env (_ : ss)                  = fromStmts env ss\nfromStmts env []                        = []\n\nfromDefs env (Def l n q p k a _ d fx ddoc : ds)\n                                        = (n, NDef (TSchema NoLoc q (TFun NoLoc fx (prowOf' p d) (krowOf k) (fromJust a))) d ddoc) : fromDefs env ds\n  where prowOf' p Static                = prowOf p\n        prowOf' (PosPar _ _ _ p) _      = prowOf p\nfromDefs env (_ : ds)                   = fromDefs env ds\nfromDefs env []                         = []\n\nfromTEnv ((n, NSig sc dec doc) : te)    = Signature NoLoc [n] sc dec : fromTEnv te\nfromTEnv ((n, NDef sc dec doc) : te)    = Decl NoLoc [def] : fromTEnv te\n  where TSchema _ q (TFun _ fx p k t)   = sc\n        def                             = Def NoLoc n q (pPar' dec p) (kPar attrKW k) (Just t) [sNotImpl] dec fx doc\n        pPar' Static p                  = pPar pNames p\n        pPar' _ p                       = pPar pNames (posRow tSelf p)\nfromTEnv ((n, NVar t) : te)             = sAssign (pVar n t) eNotImpl : fromTEnv te\nfromTEnv (_ : te)                       = fromTEnv te\nfromTEnv []                             = []\n\nconvClassTEnv env q0 te                 = [ conv n i | (n,i) <- te ]\n  where conv n (NSig sc dec doc)        = (n, NSig (convS n dec sc) dec doc)\n        conv n (NDef sc dec doc)        = (n, NDef (convS n dec sc) dec doc)\n        conv n i                        = (n, i)\n        convS n dec (TSchema l q t)\n          | n==initKW || dec==Static    = TSchema l (noqual env q) (convT (q0++q) t)\n          | otherwise                   = TSchema l (noqual env q) (convT q t)\n        convT q (TFun l x p k t)        = TFun l x (qualWRow env q p) k t\n        convT q t                       = t\n\n\n{-\n\nf : [A(Eq),B,C(Ord)] => (A,B) -> C                          f : [A,B,C] => (Eq[A],Ord[C],A,B) -> C\n\nclass c[A(Eq),B] (b[A]):                                    class c[A,B] (b[A]):\n    f : [C(Ord)] => (A,B) -> C                                  f : [C] => (Eq[A],Ord[C],A,B) -> C\n    @static                                                     @static\n    g : [C(Ord)] => (Self,Self) -> C                            g : [C] => (Eq[A],Ord[C],Self,Self) -> C\n\nprotocol p[A(Eq),B] (q[A]):                                 class p[S,A,B] (q[S,A]):\n    f : [C(Ord)] => (A,B) -> C                                  __init__ : (Eq[A]) -> None\n    @static                                                     f : [C] => (S,Ord[C],A,B) -> C\n    g : [C(Ord)] => (Self,Self) -> C                            g : [C] => (Ord[C],S,S) -> C\n\nextension c[A(Eq),B] (p[A,B]):                              class p$c[A,B] (p[c[A,B],A,B]):\n    ...                                                         __init__ : (Eq[A]) -> None\n\nactor[ a[A(Eq),B] (b[A]):                                   class a[A,B] ($Actor[]):\n    f : [C(Ord)] => action(A,B) -> C                            __init__ : (Eq[A],b[A]) -> None\n                                                                f        : [C] => action(Ord[C],A,B) -> C\n                                                                f$local  : [C] => proc(Ord[C],A,B) -> C\n\n-}\n"
  },
  {
    "path": "compiler/lib/src/Acton/Deactorizer.hs",
    "content": "-- Copyright (C) 2019-2021 Data Ductus AB\n--\n-- Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:\n--\n-- 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.\n--\n-- 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.\n--\n-- 3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission.\n--\n-- THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS \"AS IS\" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n--\n\n{-# LANGUAGE FlexibleInstances #-}\nmodule Acton.Deactorizer where\n\nimport Acton.Syntax\nimport Acton.Names\nimport Acton.Subst\nimport Acton.Prim\nimport Acton.Builtin\nimport Acton.NameInfo\nimport Acton.QuickType\nimport Acton.Env\nimport Acton.Transform\nimport Utils\nimport Pretty\nimport Control.Monad.State.Strict\n\ndeactorize                          :: Env0 -> Module -> IO (Module, Env0)\ndeactorize env0 (Module m imps mdoc b)\n                                    = return (Module m imps mdoc (runDeactM $ deactSuite env b), mapModules conv env0)\n  where env                         = deactEnv env0\n\n\n-- Deactorizing monad\ntype DeactM a                       = State DeactState a\n\ntype DeactState                     = [Int]\n\nrunDeactM                           :: DeactM a -> a\nrunDeactM m                         = evalState m [1..]\n\ntype DeactEnv                       = EnvF DeactX\n\ndata DeactX                         = DeactX { wrappedX :: [Name], stvarsX :: [Name], localsX :: [Name], sampledX :: [Name] }\n\ndeactEnv                            :: Env0 -> DeactEnv\ndeactEnv env0                       = setX env0 DeactX{ wrappedX = [], stvarsX = [], localsX = [], sampledX = [] }\n\ndefineAndShadow                     :: TEnv -> DeactEnv -> DeactEnv\ndefineAndShadow te env              = modX (define te env) $ \\x -> x{ wrappedX = wrapped env \\\\ ns, localsX = locals env \\\\ ns }\n  where ns                          = dom te\n\n\nwrapped env                         = wrappedX $ envX env\n\nstvars env                          = stvarsX $ envX env\n\nlocals env                          = localsX $ envX env\n\nsampled env                         = sampledX $ envX env\n\nsetActor wrapped stvars locals env  = modX env $ \\x -> x{ wrappedX = wrapped, stvarsX = stvars, localsX = locals, sampledX = [] }\n\nsetSampled ns env                   = modX env $ \\x -> x{ sampledX = ns ++ sampled env }\n\nclearSampled env                    = modX env $ \\x -> x{ sampledX = [] }\n\n\n-- Deactorize actor declarations -----------------------------------------------------------------------\n\nclass Deact a where\n    deact                           :: DeactEnv -> a -> DeactM a\n\ninstance Deact a => Deact (Maybe a) where\n    deact env                       = traverse (deact env)\n\ninstance Deact a => Deact [a] where\n    deact env                       = traverse (deact env)\n\n\ndeactSuite env []                   = return []\ndeactSuite env (s : ss)             = do s' <- deact (setSampled ns env) s\n                                         ss' <- deactSuite env1 ss\n                                         return (samples ++ s' : ss')\n  where env1                        = define (envOf s) env\n        ns                          = nub $ stvars env `intersect` lamfree s\n        samples                     = [ sAssign (pVar n $ typeOf env (eVar n)) (eDot (eVar selfKW) n) | n <- ns ]\n\n\ninstance Deact Stmt where\n    deact env s@(Expr _ (NotImplemented _))\n                                    = return s\n    deact env (Expr l (Call l' e p KwdNil))\n      | fx == fxAction              = Expr l <$> (Call l' <$> deact env (eAsync e) <*> deact env p <*> pure KwdNil)\n      where TFun{effect=fx}         = typeOf env e\n    deact env (Expr l e)            = Expr l <$> deact env e\n    deact env (Assign l [p@(PVar _ n _)] e)\n      | n `elem` locals env         = MutAssign l (selfRef n) <$> deact env e\n      | otherwise                   = Assign l [p] <$> deact env e\n      where t                       = typeOf env p\n    deact env (MutAssign l tg e)    = MutAssign l <$> deact env tg <*> deact env e\n      where t                       = typeOf env tg\n    deact env (Pass l)              = return $ Pass l\n    deact env (Return l Nothing)    = return $ Return l Nothing\n    deact env (Return l (Just e))   = Return l . Just <$> deact env e\n    deact env (Break l)             = return $ Break l\n    deact env (Continue l)          = return $ Continue l\n    deact env (If l bs els)         = If l <$> deact env bs <*> deactSuite env1 els\n      where env1                    = clearSampled env\n    deact env (While l e b els)     = While l <$> deact env e <*> deactSuite env1 b <*> deactSuite env1 els\n      where env1                    = clearSampled env\n    deact env (VarAssign l [p@(PVar _ n _)] e)\n                                    = MutAssign l (selfRef n) <$> deact env e\n      where t                       = typeOf env p\n    deact env (After l e1 e2)       = do delta <- deact env e1\n                                         lambda <- deact env $ Lambda l0 PosNIL KwdNIL e2 fxProc\n                                         return $ Expr l $ Call l0 (tApp (eQVar primAFTERf) [t2]) (PosArg delta $ PosArg lambda PosNil) KwdNil\n      where t2                      = typeOf env e2\n            t                       = tFun fxProc posNil kwdNil t2\n    deact env (Decl l ds)           = do ds1 <- deact env1 ds\n                                         return $ Decl l $ ds1 ++ [ newact env1 n q p Nothing | Actor _ n q p _ _ _ <- ds, not $ abstractActor env1 (NoQ n) ]\n      where env1                    = define (envOf ds) env\n    deact env (Signature l ns t d)  = return $ Signature l ns t d\n    deact env s                     = error (\"deact unexpected stmt: \" ++ prstr s)\n\ninstance Deact Decl where\n    deact env (Actor l n q params KwdNIL body ddoc)\n                                    = do inits1 <- deactSuite (define (envOf decls) env1) inits\n                                         decls1 <- deactSuite (define (envOf inits) env1) decls\n                                         let _init_ = Def l0 initKW [] (addSelfPar params) KwdNIL (Just tNone) (mkBody $ copies++inits1) NoDec fxProc Nothing\n                                             decls2 = [ Decl l $ map deactMeth ds | Decl l ds <- decls1 ]\n                                         return $ Class l n q [TC primActor [], cValue] (propsigs ++ [Decl l0 [_init_]] ++ decls2 ++ wraps) ddoc\n      where env1                    = setActor wrapped stvars locals $ define (envOf params) $ define [(selfKW, NVar t0)] $ defineTVars q env\n            t0                      = tCon $ TC (NoQ n) (map tVar $ qbound q)\n\n            (decls,ss)              = partition isDecl body\n            inits                   = filter (not . isSig) ss\n            stvars                  = statevars body\n            fvs                     = free decls\n            live_vars\n              | hasNotImpl body     = bound params ++ dom (envOf inits)\n              | otherwise           = bound params `intersect` fvs ++ [ n | n <- dom $ envOf inits, not (isHidden n) || n `elem` (stvars++fvs) ]\n            locals                  = nub $ live_vars ++ bound decls\n            wrapped                 = bound wrapdefs\n            wrapdefs                = [ d | Decl _ ds <- decls, d@Def{dname=n, dfx=fx} <- ds, fx == fxProc || fx == fxAction ]\n\n            propsigs                = [ Signature l0 [n] (monotype t) Property | (n,t) <- concat $ props' params : map props inits ]\n\n            props (VarAssign _ p _) = [ (n, t) | PVar _ n (Just t) <- p ]\n            props (Assign _ p _)    = [ (n, t) | PVar _ n (Just t) <- p, n `elem` locals ]\n            props (If _ bs els)     = restrict (concat $ map props els) (foldr1 intersect [ assigned b | Branch _ b <- bs ])\n            props _                 = []\n\n            props' (PosPar n a _ p)\n              | n `elem` locals     = (n, fromJust a) : props' p\n              | otherwise           = props' p\n            props' (PosSTAR n a)\n              | n `elem` locals     = [(n, fromJust a)]\n            props' _                = []\n\n            copies                  = [ MutAssign l0 (selfRef n) (Var l0 (NoQ n)) | n <- bound params, n `elem` locals ]\n\n            deactMeth (Def l n q p KwdNIL t b d fx ddoc)\n                                    = Def l n' q (addSelfPar p) KwdNIL t b d fx ddoc\n              where n'              = if n `elem` wrapped then localName n else n\n\n            wraps                   = [ wrap n q p t | Def _ n q p KwdNIL (Just t) _ _ _ _ <- wrapdefs ]\n\n            wrap n q p t            = Decl l0 [Def l0 n q (addSelfPar p) KwdNIL (Just t) [ret] NoDec fxAction Nothing]\n              where ret             = sReturn $ eCall (tApp (eQVar primASYNCf) [t]) [self,lam]\n                    lam             = Lambda l0 PosNIL KwdNIL (eCallP (tApp (eDot self $ localName n) (map tVar $ qbound q)) (pArg p)) fxProc\n                    self            = eVar selfKW\n\n    deact env (Def l n q p KwdNIL (Just t) b d fx ddoc)\n                                    = do b <- deactSuite env1 b\n                                         return $ Def l n q p KwdNIL (Just t) b d fx ddoc\n      where env1                    = defineAndShadow (envOf p) $ defineTVars q env\n\n    deact env (Class l n q u b ddoc)\n                                    = Class l n q u <$> deactSuite env1 b <*> pure ddoc\n      where env1                    = defineTVars (selfQuant (NoQ n) q) env\n\n    deact env d                     = error (\"deact unexpected decl: \" ++ prstr d)\n\nnewact env n q p ddoc               = Def l0 (newactName n) q p KwdNIL (Just t) [newassign, install_gc_finalizer, waitinit, sReturn x] NoDec fxProc ddoc\n  where t                           = tCon $ TC (NoQ n) (map tVar $ qbound q)\n        x                           = eVar g_act\n        newassign                   = sAssign (pVar g_act t) (eCall (tApp (eQVar primNEWACTOR) [t]) [])\n        install_gc_finalizer        = sExpr $ eCall (tApp (eQVar primInstallFinalizer) [t]) [x]\n        waitinit                    = sExpr $ eCall (tApp (eQVar primAWAITf) [tNone]) [asyncmsg]\n        asyncmsg                    = eCall (tApp (eQVar primASYNCf) [tNone]) [x, closure]\n        closure                     = Lambda l0 PosNIL KwdNIL initcall fxProc\n        initcall                    = Call l0 (eDot x initKW) (pArg p) KwdNil\n\nnewactQName (QName m n)             = QName m (newactName n)\nnewactQName (NoQ n)                 = NoQ (newactName n)\nnewactQName (GName m n)             = GName m (newactName n)\n\nqnName :: QName -> Name\nqnName (NoQ n) = n\nqnName (QName _ n) = n\nqnName (GName _ n) = n\n\naddSelfPar p                        = PosPar selfKW (Just tSelf) Nothing p\n\nselfRef n                           = Dot l0 (Var l0 (NoQ selfKW)) n\n\n\n-- $ASYNCf : [A] => action($Actor, proc()->A) -> Msg[A]\n-- $AFTERf : [A] => proc(int,      proc()->A) -> Msg[A]\n-- $AWAITf : [A] => proc(Msg[A])              -> A\n\n\ninstance Deact Branch where\n    deact env (Branch e ss)         = Branch <$> deact env e <*> deactSuite env1 ss\n      where env1                    = clearSampled env\n\nisProcMeth env e\n  | Just n <- isQVar e,\n    NDef sc _ _ <- findQName n env,\n    TFun{effect=fx} <- sctype sc    = fx == fxProc\nisProcMeth env _                    = False\n\nsealedMeth env e\n  | Just n <- isVar e,\n    n `elem` wrapped env            = Just n\nsealedMeth env _                    = Nothing\n\ninstance Deact Expr where\n    deact env (Var l (NoQ n))\n      | n `elem` sampled env        = return $ Var l (NoQ n)\n      | n `elem` locals env         = return $ Dot l (Var l (NoQ selfKW)) n'\n      where n'                      = if n `elem` wrapped env then localName n else n\n    deact env (Var l n)\n      | isActor env n               = return $ Var l $ newactQName (unalias env n)\n      | otherwise                   = return $ Var l n\n    deact env (Async l e)           = Async l <$> deact env e\n    deact env (Await l e)           = do e' <- deact env e\n                                         return $ Call l (tApp (eQVar primAWAITf) ts) (PosArg e' PosNil) KwdNil\n      where TCon _ msg              = typeOf env e\n            ts                      = tcargs msg\n    deact env (Int l i s)           = return $ Int l i s\n    deact env (Float l f s)         = return $ Float l f s\n    deact env (Imaginary l i s)     = return $ Imaginary l i s\n    deact env (Bool l b)            = return $ Bool l b\n    deact env (None l)              = return $ None l\n    deact env (NotImplemented l)    = return $ NotImplemented l\n    deact env (Ellipsis l)          = return $ Ellipsis l\n    deact env (Strings l s)         = return $ Strings l s\n    deact env (BStrings l s)        = return $ BStrings l s\n    deact env (Call l e as KwdNil)  = deactCall env True l e as\n    deact env (TApp l e ts)         = TApp l <$> deact env e <*> pure ts\n    deact env (Let l ss e)          = Let l <$> deact env1 ss <*> deact env1 e\n       where env1                   = define (envOf ss) env\n    deact env (Cond l e1 e e2)      = Cond l <$> deact env e1 <*> deact env e <*> deact env e2\n    deact env (IsInstance l e c)    = IsInstance l <$> deact env e <*> return c\n    deact env (BinOp l e1 Or e2)    = BinOp l <$> deact env e1 <*> pure Or <*> deact env e2\n    deact env (BinOp l e1 And e2)   = BinOp l <$> deact env e1 <*> pure And <*> deact env e2\n    deact env (UnOp l Not e)        = UnOp l Not <$> deact env e\n    deact env (Dot l e nm)          = Dot l <$> deact env e <*> return nm\n    deact env (DotI l e i)          = DotI l <$> deact env e <*> return i\n    deact env (RestI l e i)         = RestI l <$> deact env e <*> return i\n    deact env (Lambda l p KwdNIL e fx)\n      | Call l' e' as KwdNil <- e   = Lambda l p KwdNIL <$> deactCall env1 False l' e' as <*> return fx\n      | otherwise                   = Lambda l p KwdNIL <$> deact env1 e <*> return fx\n      where env1                    = defineAndShadow (envOf p) env\n    deact env (Yield l e)           = Yield l <$> deact env e\n    deact env (YieldFrom l e)       = YieldFrom l <$> deact env e\n    deact env (Tuple l es KwdNil)   = Tuple l <$> deact env es <*> pure KwdNil\n    deact env (List l es)           = List l <$> deact env es\n    deact env (Dict l as)           = Dict l <$> deact env as\n    deact env (Set l es)            = Set l <$> deact env es\n    deact env e                     = error (\"deact unexpected expr: \" ++ prstr e)\n\ndeactCall env unwrap l (TApp _ (Var _ n) ts) (PosArg self (PosArg e PosNil))\n  | n == primWRAP,\n    Just n' <- sealedMeth env e     = return $ Dot l (Var l (NoQ selfKW)) n'\n  | n == primWRAP                   = do e <- deact env e\n                                         self <- deact env self\n                                         let lam = Lambda l0 PosNIL KwdNIL (eCallP e (pArg ps)) fxProc\n                                         return $ Lambda l0 ps KwdNIL (eCall (tApp (eQVar primASYNCf) [t]) [self,lam]) fxAction\n  where TFun _ fx p _ t             = typeOf env e\n        ps                          = pPar paramNames p\ndeactCall env unwrap l e as\n  | fx == fxAction && unwrap        = deact env (eAwait $ Call l (eAsync e) as KwdNil)\n  | otherwise                       = do e <- deact env e\n                                         as <- deact env as\n                                         case e of\n                                            Lambda _ ps KwdNIL e' _ | Just s <- pzip ps as ->\n                                                 return $ termsubst s e'\n                                            _ -> return $ Call l e as KwdNil\n  where TFun{effect=fx}             = typeOf env e\n\ninstance Deact PosArg where\n    deact env (PosArg e p)          = PosArg <$> deact env e <*> deact env p\n    deact env PosNil                = return PosNil\n\ninstance Deact Elem where\n    deact env (Elem e)              = Elem <$> deact env e\n    deact env (Star e)              = Star <$> deact env e\n\ninstance Deact Assoc where\n    deact env (Assoc k v)           = Assoc <$> deact env k <*> deact env v\n    deact env (StarStar e)          = StarStar <$> deact env e\n\n\n-- Variables free in a lambda -----------------------------------------------------------------------------------\n\nclass LambdaFree a where\n    lamfree                         :: a -> [Name]\n\ninstance (LambdaFree a) => LambdaFree [a] where\n    lamfree                         = concat . map lamfree\n\ninstance (LambdaFree a) => LambdaFree (Maybe a) where\n    lamfree                         = maybe [] lamfree\n\ninstance LambdaFree Stmt where\n    lamfree (Expr _ e)              = lamfree e\n    lamfree (Assign _ p e)          = lamfree e\n    lamfree (MutAssign _ t e)       = lamfree t ++ lamfree e\n    lamfree (Return _ e)            = maybe [] lamfree e\n    lamfree (If _ bs els)           = concat [ lamfree e | Branch e ss <- bs ]\n    lamfree (While _ e b els)       = lamfree e\n    lamfree (VarAssign _ p e)       = lamfree e\n    lamfree (After l e1 e2)         = lamfree e1 ++ free e2         -- deact will turn e2 into a lambda\n    lamfree _                       = []\n\ninstance LambdaFree Expr where\n    lamfree (Await _ e)             = lamfree e\n    lamfree (Call _ e ps KwdNil)    = lamfree e ++ lamfree ps\n    lamfree (TApp _ e ts)           = lamfree e\n    lamfree (Cond _ e1 e e2)        = lamfree e1 ++ lamfree e ++ lamfree e2\n    lamfree (IsInstance _ e c)      = lamfree e\n    lamfree (BinOp _ e1 Or e2)      = lamfree e1 ++ lamfree e2\n    lamfree (BinOp _ e1 And e2)     = lamfree e1 ++ lamfree e2\n    lamfree (UnOp _ Not e)          = lamfree e\n    lamfree (Dot _ e n)             = lamfree e\n    lamfree (DotI _ e i)            = lamfree e\n    lamfree (RestI _ e i)           = lamfree e\n    lamfree (Yield _ e)             = lamfree e\n    lamfree (YieldFrom _ e)         = lamfree e\n    lamfree (Tuple _ p k)           = lamfree p ++ lamfree k\n    lamfree (List _ es)             = lamfree es\n    lamfree e@Lambda{}              = free e                        -- Free in lambda!\n    lamfree _                       = []\n\ninstance LambdaFree PosArg where\n    lamfree (PosArg e p)            = lamfree e ++ lamfree p\n    lamfree PosNil                  = []\n\ninstance LambdaFree KwdArg where\n    lamfree (KwdArg n e k)          = lamfree e ++ lamfree k\n    lamfree KwdNil                  = []\n\ninstance LambdaFree Elem where\n    lamfree (Elem e)                = lamfree e\n\n\n-- Convert types and environments -----------------------------------------------------------------------\n\nconv env m (n, NAct q p k te' doc)  = (n, NClass q (leftpath [TC primActor [], cValue]) (convActorEnv q p k te') doc) :\n                                      (newactName n, NDef (tSchema q (tFun fxProc p k t)) NoDec Nothing) :\n                                      []\n  where convActorEnv q0 p k te'     = (initKW, NDef t0 NoDec Nothing) : te'\n          where t0                  = tSchema q0 (tFun fxProc p k tNone)\n        t                           = tCon $ TC (GName m n) (map tVar $ qbound q)\nconv env m ni                       = [ni]\n"
  },
  {
    "path": "compiler/lib/src/Acton/Diagnostics.hs",
    "content": "{-# LANGUAGE FlexibleInstances #-}\n{-# OPTIONS_GHC -fno-warn-orphans #-}\n\n-- | Bridge between Acton error representations and the diagnose pretty-printing library\nmodule Acton.Diagnostics where\n\nimport Error.Diagnose.Diagnostic\nimport Error.Diagnose.Report\nimport Error.Diagnose.Position\nimport Error.Diagnose.Style\nimport Error.Diagnose (addReport, addFile, printDiagnostic, prettyDiagnostic)\nimport Error.Diagnose.Report (Note(..))\n\nimport Data.List (intersperse, isPrefixOf, isInfixOf, intercalate)\nimport Data.Maybe (fromMaybe)\nimport Control.Exception (Exception(..), SomeException)\nimport qualified Data.List.NonEmpty as NE\nimport Text.Read (readMaybe)\nimport Data.Char (isDigit, isSpace)\nimport qualified Data.Set as S\n\nimport Text.Megaparsec (PosState(..), reachOffset)\nimport Text.Megaparsec.Error (ParseErrorBundle(..), parseErrorPretty, bundleErrors, errorBundlePretty, ShowErrorComponent(..), ParseError(..), errorOffset, parseErrorTextPretty, ErrorFancy(..))\nimport Text.Megaparsec.Pos (SourcePos(..), unPos, sourceLine, sourceColumn, mkPos)\nimport qualified Text.Megaparsec.Error as ME\n\nimport Acton.Syntax\nimport SrcLocation\nimport Utils (SrcLoc(..), loc)\nimport Acton.Parser (CustomParseError(..), CustomParseException(..), ContextError(..), IndentationError(..), ctxMsg) -- Import for custom error types\nimport qualified Utils as U\nimport qualified Acton.Env as Env\nimport Pretty (render, pretty, text, (<+>), (<>), comma, equals)\nimport Prelude hiding ((<>))\n\n\n-- | Convert CustomParseError to diagnostic components (error message and hints/notes)\ncustomParseErrorToDiagnostic :: CustomParseError -> (String, [Note String])\ncustomParseErrorToDiagnostic (TypeVariableNameError name)      = (\"Invalid name '\" ++ name ++ \"'\",\n                                                                  [Note \"Single upper case character (optionally followed by digits) are reserved for type variables\",\n                                                                   Hint \"Use a longer name\"])\ncustomParseErrorToDiagnostic (InvalidFormatSpecifier spec)     = (\"Invalid format specifier\" ++ if null spec then \"\" else \": \" ++ spec,\n                                                                  [])\ncustomParseErrorToDiagnostic (TooManyQuotesError quote)        = (\"Too many quote characters\",\n                                                                  [Note \"Triple-quoted strings accept 3-5 quotes at the end\",\n                                                                   Hint \"Using 4 quotes results in a string with 1 quote at the end, e.g. \\\"\\\"\\\"text\\\"\\\"\\\"\\\" -> text\\\"\",\n                                                                   Hint \"Using 5 quotes results in a string with 2 quotes at the end, e.g. \\\"\\\"\\\"text\\\"\\\"\\\"\\\"\\\" -> text\\\"\\\"\",\n                                                                   Hint \"Use escape sequences for quotes inside strings, e.g. \\\"\\\"\\\"text \\\\\\\"with quotes\\\\\\\"\\\"\\\" -> text \\\"with quotes\\\"\"])\ncustomParseErrorToDiagnostic (MissingClosingQuote quote)       = (\"Missing closing \" ++ quote,\n                                                                  [Hint $ \"Add a closing quote (\" ++ quote ++ \") to match the opening one\"])\ncustomParseErrorToDiagnostic InvalidModuleStatement            = (\"Only declarations and assignments are allowed at the module top level\",\n                                                                  [Hint \"Assign the value to a name or move runtime work into an actor or function\"])\ncustomParseErrorToDiagnostic InvalidTopLevelAssignmentPattern  = (\"Module top-level assignments must bind at least one name\",\n                                                                  [Note \"Module top-level assignments define constants by name\",\n                                                                   Hint \"Bind the value to a name or move the computation into an actor or function\"])\ncustomParseErrorToDiagnostic (DuplicateTopLevelAssignment name) = (\"Module top-level name '\" ++ name ++ \"' cannot be assigned more than once\",\n                                                                   [Note \"Module top-level assignments define constants\",\n                                                                    Hint \"Use a fresh name or move mutable state into an actor\"])\n-- String interpolation errors\ncustomParseErrorToDiagnostic EmptyInterpolationExpression       = (\"Empty expression in string interpolation\",\n                                                                  [Hint \"Add an expression between the braces, e.g. {name}\"])\ncustomParseErrorToDiagnostic MissingExpressionBeforeFormat      = (\"Missing expression before format specifier\",\n                                                                  [Hint \"Add an expression before the colon, e.g. {value:10}\"])\ncustomParseErrorToDiagnostic UnclosedInterpolationBrace         = (\"Missing closing '}' for expression\",\n                                                                  [Hint \"Add a closing brace to complete the interpolation\"])\ncustomParseErrorToDiagnostic EmptyFormatSpecifierError          = (\"Empty format specifier after ':'\",\n                                                                  [Hint \"Add a format specification or remove the colon\"])\ncustomParseErrorToDiagnostic TabInFormatSpecifier               = (\"Tab character not allowed in format specifier\",\n                                                                  [])\ncustomParseErrorToDiagnostic NewlineInFormatSpecifier           = (\"Newline not allowed in format specifier\",\n                                                                  [Hint \"Keep format specifiers on a single line\"])\ncustomParseErrorToDiagnostic (InvalidCharInFormatSpecifier c)   = (\"Invalid character '\" ++ [c] ++ \"' in format specifier\",\n                                                                  [Note \"Valid format specifiers use <, >, ^, +, -, #, 0, width, .precision, and type characters\",\n                                                                   Hint \"Use a format specifier, e.g. '{name:<18}'\"])\ncustomParseErrorToDiagnostic MissingFormatPrecisionDigits       = (\"Expected digits after '.' in format specifier\",\n                                                                  [Hint \"Add precision digits, e.g. .2f for 2 decimal places\"])\n-- Escape sequence errors\ncustomParseErrorToDiagnostic (IncompleteHexEscape c)            = (\"Incomplete hex character\",\n                                                                  [Note \"Hex-escaped characters must be specified by two hexadecimal digits\",\n                                                                   Hint \"Use two characters, e.g. \\\\x9a\"])\ncustomParseErrorToDiagnostic OctalEscapeOutOfRange              = (\"Octal escape sequence out of range\",\n                                                                  [Note \"Octal values must be between \\\\000 and \\\\377\"])\ncustomParseErrorToDiagnostic (IncompleteUnicodeEscape exp found) = (\"Incomplete universal character name\",\n                                                                   [Note $ \"Expected \" ++ show exp ++ \" hex digits, found \" ++ show found])\ncustomParseErrorToDiagnostic NonAsciiInBytesLiteral             = (\"Only ASCII characters allowed in bytes literal\",\n                                                                  [Hint \"Use escape sequences for non-ASCII values\"])\ncustomParseErrorToDiagnostic UnknownEscapeSequence              = (\"Unknown escape sequence\",\n                                                                  [Note \"Valid escape sequences: \\\\\\\\, \\\\\\\", \\\\', \\\\n, \\\\r, \\\\t, \\\\a, \\\\b, \\\\f, \\\\v, \\\\xHH, \\\\ooo, \\\\uHHHH, \\\\UHHHHHHHH\"])\ncustomParseErrorToDiagnostic (OtherError msg)                  = (msg,\n                                                                  [])\n\n\n-- | Convert Megaparsec parse errors to diagnose format\n-- Handles syntax errors from the parsing phase with rich error information\n-- like expected/unexpected tokens and parse positions.\nparseDiagnosticFromBundle :: String -> String -> ParseErrorBundle String CustomParseError -> Diagnostic String\nparseDiagnosticFromBundle filename src bundle =\n    let -- Extract the first error (most relevant)\n        firstError = NE.head (bundleErrors bundle)\n        -- Get the error offset\n        offset = errorOffset firstError\n        -- Get the position state and calculate source position\n        posState = bundlePosState bundle\n        (_, newPosState) = reachOffset offset posState\n        sourcePos = pstateSourcePos newPosState\n        line = unPos (sourceLine sourcePos)\n        col = unPos (sourceColumn sourcePos)\n        msg = parseErrorTextPretty firstError\n\n        -- For parse errors, we only have a single position, not a span\n        -- Just highlight one character at the error position\n        -- Create position span\n        position = Position (line, col) (line, col + 1) filename\n\n        -- Check if this is a custom error and get the text message & hints / notes\n        (prettyMsg, hints) = case firstError of\n                  ME.FancyError _ errs ->\n                    case findCustomError (S.toList errs) of\n                      Just customErr -> customParseErrorToDiagnostic customErr\n                      Nothing -> (msg, [])\n                  _ -> (msg, [])\n\n        findCustomError :: [ErrorFancy CustomParseError] -> Maybe CustomParseError\n        findCustomError [] = Nothing\n        findCustomError (ErrorCustom err : _) = Just err\n        findCustomError (_ : rest) = findCustomError rest\n\n        report = Err (Just \"Parse error\") msg [(position, This prettyMsg)] hints\n        diagnostic = addReport mempty report\n    in addFile diagnostic filename src\n\n\n-- | Convert CustomParseException to diagnostic format directly\n-- CustomParseExceptions are essentially an exception container for\n-- CustomParseError, so extract the error and convert that\ncustomParseExceptionToDiagnostic :: String -> String -> CustomParseException -> Diagnostic String\ncustomParseExceptionToDiagnostic filename src (CustomParseException loc customErr) =\n    customParseErrorDiagnostic \"Syntax error\" filename src loc customErr\n\n\n-- | Convert CustomParseError to Diagnostic\n-- This is used by tests to ensure consistent error formatting\ncustomParseErrorDiagnostic :: String -> String -> String -> SrcLoc -> CustomParseError -> Diagnostic String\ncustomParseErrorDiagnostic errKind filename src srcLoc customErr =\n    let (msg, hints) = customParseErrorToDiagnostic customErr\n        (line, col, endCol) = case srcLoc of\n            NoLoc -> (1, 1, 2)\n            Loc startOffset endOffset ->\n                let initialState = PosState\n                        { pstateInput = src\n                        , pstateOffset = 0\n                        , pstateSourcePos = SourcePos filename (mkPos 1) (mkPos 1)\n                        , pstateTabWidth = mkPos 8\n                        , pstateLinePrefix = \"\"\n                        }\n                    (_, startState) = reachOffset startOffset initialState\n                    (_, endState) = reachOffset endOffset initialState\n                    startPos = pstateSourcePos startState\n                    endPos = pstateSourcePos endState\n                in (unPos (sourceLine startPos), unPos (sourceColumn startPos), unPos (sourceColumn endPos))\n        \n        position = Position (line, col) (line, endCol) filename\n        report = Err (Just errKind) msg [(position, This msg)] hints\n        diagnostic = addReport mempty report\n    in addFile diagnostic filename src\n\n-- | Convert Acton compiler errors to diagnose format\n-- Classic Acton errors consist of (loc, msg). Wrap in OtherError and convert to\n-- Diagnostic.\n-- One day we'll convert everything to more structured errors and get rid of\n-- this function\nactErrToDiagnostic errKind filename src srcLoc msg =\n    customParseErrorDiagnostic errKind filename src srcLoc (OtherError msg)\n"
  },
  {
    "path": "compiler/lib/src/Acton/DocPrinter.hs",
    "content": "-- Copyright (C) 2019-2025 Data Ductus AB\n--\n-- Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:\n--\n-- 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.\n--\n-- 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.\n--\n-- 3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission.\n--\n-- THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS \"AS IS\" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n--\n\n{-# LANGUAGE FlexibleInstances #-}\nmodule Acton.DocPrinter\n    ( -- * Main documentation functions\n      printAsciiDoc\n    , printMdDoc\n    , printHtmlDoc\n    , generateDocIndex\n    ) where\n\nimport Utils\nimport Acton.Printer (Pretty(..), Doc, render, text, (<+>), ($+$), (<>), blank, vcat, empty,\n                      nest, brackets, parens, colon, comma, punctuate, commaSep, commaList, isEmpty, hcat)\nimport Acton.Syntax\nimport Acton.Builtin (qnList, qnDict, qnSetT, nBuiltin)\nimport Acton.Prim\nimport Acton.NameInfo\nimport Data.List (nub)\nimport Prelude hiding ((<>))\nimport Data.List (intercalate, intersperse, sortBy)\nimport Data.Ord (comparing)\nimport Data.Char (isDigit)\nimport Data.Set (Set)\nimport qualified Data.Set as Set\nimport System.FilePath ((</>), (<.>), joinPath)\n\n\n-- | Generate documentation from a module in Markdown format with types\ndocModuleWithTypes :: NameInfo -> Module -> Doc\ndocModuleWithTypes (NModule _ tenv mdocstring) (Module qn _ _ stmts) =\n    -- Use module docstring from NModule\n    let moduleDocstring = mdocstring\n        (title, restDoc) = case moduleDocstring of\n            Just ds -> splitDocstring ds\n            Nothing -> (\"\", Nothing)\n        header = if null title\n                 then text \"#\" <+> pretty qn\n                 else text \"#\" <+> text \"`\" <> pretty qn <> text \"`:\" <+> text title\n        bodyDoc = case restDoc of\n            Just body -> blank $+$ text body $+$ blank\n            Nothing -> empty\n    in header $+$ bodyDoc $+$ blank $+$ docTopLevelWithTypes tenv stmts\n\n-- | Split docstring into first line (title) and rest\nsplitDocstring :: String -> (String, Maybe String)\nsplitDocstring s =\n    let ls = lines s\n    in case ls of\n        [] -> (\"\", Nothing)\n        [l] -> (l, Nothing)\n        (l:rest) ->\n            let remainder = dropWhile null rest  -- Skip blank lines after title\n            in if null remainder\n               then (l, Nothing)\n               else (l, Just $ unlines remainder)\n\n\n-- | Extract and document top-level definitions with types\ndocTopLevelWithTypes :: TEnv -> Suite -> Doc\ndocTopLevelWithTypes tenv stmts =\n    let docs = concatMap (extractTopLevelWithTypes tenv) stmts\n        separated = case docs of\n            [] -> []\n            [d] -> [d]\n            (d:ds) -> d : map (blank $+$ blank $+$) ds\n    in vcat separated\n\n\n-- | Extract documentation-worthy top-level statements with types\nextractTopLevelWithTypes :: TEnv -> Stmt -> [Doc]\nextractTopLevelWithTypes tenv (Decl _ decls) = map (docDeclWithTypes tenv) decls\nextractTopLevelWithTypes tenv (With _ _ body) = concatMap (extractTopLevelWithTypes tenv) body\nextractTopLevelWithTypes _ _ = []\n\n-- | Extract docstring from NameInfo\nextractNameDocstring :: NameInfo -> Maybe String\nextractNameDocstring (NDef _ _ mdoc) = mdoc\nextractNameDocstring (NSig _ _ mdoc) = mdoc\nextractNameDocstring (NAct _ _ _ _ mdoc) = mdoc\nextractNameDocstring (NClass _ _ _ mdoc) = mdoc\nextractNameDocstring (NProto _ _ _ mdoc) = mdoc\nextractNameDocstring (NExt _ _ _ _ _ mdoc) = mdoc\nextractNameDocstring (NModule _ _ mdoc) = mdoc\nextractNameDocstring _ = Nothing\n\n-- | Document a declaration in Markdown format with types\ndocDeclWithTypes :: TEnv -> Decl -> Doc\ndocDeclWithTypes tenv (Def _ n q p k a b d x ddoc) =\n    let -- Look up inferred type information\n        (inferredType, qConstraints, mdocstring) = case lookup n tenv of\n            Just info@(NDef schema _ _) -> (Just schema, getQBindsFromSchema schema, extractNameDocstring info)\n            Just info@(NSig schema _ _) -> (Just schema, getQBindsFromSchema schema, extractNameDocstring info)\n            _ -> (Nothing, [], Nothing)\n\n        -- Create a mapping from ugly type vars to nice generic names\n        uglyTypeVarsFromQBinds = collectUglyTypeVars qConstraints\n        uglyTypeVarsFromType = case inferredType of\n            Just (TSchema _ _ t) -> collectUglyTypeVarsFromType t\n            _ -> []\n        allUglyTypeVars = nub (uglyTypeVarsFromQBinds ++ uglyTypeVarsFromType)\n        typeVarMapping = createTypeVarMapping allUglyTypeVars\n\n        -- Process the type information with cleanup\n        (paramsWithTypes, retType, cleanedQ) = case inferredType of\n            Just (TSchema _ qConstraints (TFun _ _ posRow kwdRow resType)) ->\n                let cleanPosRow = cleanupTypeVars typeVarMapping posRow\n                    cleanKwdRow = cleanupTypeVars typeVarMapping kwdRow\n                    cleanRetType = cleanupTypeVars typeVarMapping resType\n                    cleanConstraints = cleanupQBinds typeVarMapping qConstraints\n                in (enrichParamsMarkdown cleanPosRow cleanKwdRow p k, Just cleanRetType, if null q then cleanConstraints else q)\n            _ -> (docParamsWithTypes p k, a, q)\n\n        -- Use docstring from AST declaration\n        docstr = case mdocstring of\n            Just ds -> Just ds\n            Nothing -> ddoc\n\n        -- Use cleaned up constraints for generics display\n        genericsDoc = if null cleanedQ\n                      then empty\n                      else docGenericsMarkdown cleanedQ\n\n        header = text \"##\" <+> text \"`\" <> pretty n <> text \"`\" <> genericsDoc <> paramsWithTypes <>\n                 docRetTypeFormatted retType\n        docstrDoc = case docstr of\n            Just ds -> blank $+$ text ds\n            Nothing -> empty\n    in header $+$ docstrDoc\n  where\n    isJust (Just _) = True\n    isJust Nothing = False\n\n    enrichParamsMarkdown :: PosRow -> KwdRow -> PosPar -> KwdPar -> Doc\n    enrichParamsMarkdown posRow kwdRow p k =\n        parens $ enrichPosParamsMarkdown posRow p <> kwdParSepLocal p k <> enrichKwdParamsMarkdown kwdRow k\n\n    kwdParSepLocal :: PosPar -> KwdPar -> Doc\n    kwdParSepLocal PosNIL KwdNIL = empty\n    kwdParSepLocal PosNIL _ = empty\n    kwdParSepLocal _ KwdNIL = empty\n    kwdParSepLocal _ _ = text \", \"\n\n    enrichPosParamsMarkdown :: PosRow -> PosPar -> Doc\n    enrichPosParamsMarkdown _ PosNIL = empty\n    enrichPosParamsMarkdown posRow (PosPar n t e p) =\n        -- Skip witness parameters\n        if isWitnessParam n\n        then enrichPosParamsMarkdown (advanceRow posRow) p\n        else\n            let inferredType = extractParamTypeFromRow (nstr n) posRow\n                paramType = case inferredType of\n                    Just it -> Just it\n                    Nothing -> t\n                param = pretty n <> formatType paramType <> formatDefault e\n                nextParams = enrichPosParamsMarkdown (advanceRow posRow) p\n            in case p of\n                PosNIL -> param\n                _ -> if isEmpty nextParams\n                     then param\n                     else param <> comma <+> nextParams\n    enrichPosParamsMarkdown _ (PosSTAR n t) = text \"*\" <> pretty n <> formatType t\n\n    enrichKwdParamsMarkdown :: KwdRow -> KwdPar -> Doc\n    enrichKwdParamsMarkdown _ KwdNIL = empty\n    enrichKwdParamsMarkdown kwdRow (KwdPar n t e k) =\n        let inferredType = extractParamTypeFromRow (nstr n) kwdRow\n            paramType = case inferredType of\n                Just it -> Just it\n                Nothing -> t\n            param = pretty n <> formatType paramType <> formatDefault e\n        in case k of\n            KwdNIL -> param\n            _ -> param <> comma <+> enrichKwdParamsMarkdown kwdRow k\n    enrichKwdParamsMarkdown _ (KwdSTAR n t) = text \"**\" <> pretty n <> formatType t\n\n    extractParamTypeFromRow :: String -> Type -> Maybe Type\n    extractParamTypeFromRow _ (TNil _ _) = Nothing\n    extractParamTypeFromRow name (TRow _ _ n t rest)\n        | nstr n == name = Just t\n        | otherwise = extractParamTypeFromRow name rest\n    extractParamTypeFromRow _ _ = Nothing\n\n    advanceRow :: Type -> Type\n    advanceRow (TRow _ _ _ _ rest) = rest\n    advanceRow t = t\n\ndocDeclWithTypes tenv (Actor _ n q p k b ddoc) =\n    let mdocstring = case lookup n tenv of\n            Just info -> extractNameDocstring info\n            _ -> Nothing\n        -- Use docstring from AST declaration\n        docstr = case mdocstring of\n            Just ds -> Just ds\n            Nothing -> ddoc\n        header = text \"##\" <+> text \"*actor*\" <+> text \"`\" <> pretty n <> text \"`\" <> docGenerics q <> docParamsWithTypes p k\n        docstrDoc = case docstr of\n            Just ds -> blank $+$ text ds\n            Nothing -> empty\n    in header $+$ docstrDoc\n\ndocDeclWithTypes tenv (Class _ n q a b ddoc) =\n    let mdocstring = case lookup n tenv of\n            Just info -> extractNameDocstring info\n            _ -> Nothing\n        -- Use docstring from AST declaration\n        docstr = case mdocstring of\n            Just ds -> Just ds\n            Nothing -> ddoc\n        header = text \"##\" <+> text \"*class*\" <+> text \"`\" <> pretty n <> text \"`\" <> docGenerics q <> docAncestors a\n        docstrDoc = case docstr of\n            Just ds -> blank $+$ text ds\n            Nothing -> empty\n        methods = docClassBodyWithTypes tenv b\n    in header $+$ docstrDoc $+$\n       (if isEmpty methods then empty else blank $+$ methods)\n\ndocDeclWithTypes tenv (Protocol _ n q a b ddoc) =\n    let mdocstring = case lookup n tenv of\n            Just info -> extractNameDocstring info\n            _ -> Nothing\n        -- Fall back to extracting from body if not in TEnv\n        docstr = case mdocstring of\n            Just ds -> Just ds\n            Nothing -> ddoc\n        header = text \"##\" <+> text \"*protocol*\" <+> text \"`\" <> pretty n <> text \"`\" <> docGenerics q <> docAncestors a\n        docstrDoc = case docstr of\n            Just ds -> blank $+$ text ds\n            Nothing -> empty\n        methods = docProtocolBodyWithTypes tenv b\n    in header $+$ docstrDoc $+$\n       (if isEmpty methods then empty else blank $+$ methods)\n\ndocDeclWithTypes tenv (Extension _ q c a b ddoc) =\n    let mdocstring = Nothing  -- Extensions don't have their own docstrings in TEnv\n        -- Use docstring from AST declaration\n        docstr = ddoc\n        header = text \"##\" <+> text \"*extension*\" <+> text \"`\" <> pretty c <> text \"`\" <> docGenerics q <> docAncestors a\n        docstrDoc = case docstr of\n            Just ds -> blank $+$ text ds\n            Nothing -> empty\n    in header $+$ docstrDoc\n\n-- | Helper functions for Markdown generation\ndocGenerics :: QBinds -> Doc\ndocGenerics [] = empty\ndocGenerics q = brackets (commaList q)\n\n-- | Document generics for Markdown format\ndocGenericsMarkdown :: QBinds -> Doc\ndocGenericsMarkdown [] = empty\ndocGenericsMarkdown qbs = brackets $ hcat $ punctuate comma $ map renderQBind qbs\n  where\n    renderQBind (QBind tv []) = pretty (tvname tv)\n    renderQBind (QBind tv constraints) =\n        pretty (tvname tv) <> parens (hcat $ punctuate comma $ map pretty constraints)\n\n-- | Document generic constraints in ASCII format (showing type variable names and constraints)\ndocGenericsAscii :: QBinds -> Doc\ndocGenericsAscii [] = empty\ndocGenericsAscii qbs = brackets $ commaList qbs\n\ndocRetType :: Maybe Type -> Doc\ndocRetType Nothing = empty\ndocRetType (Just t) = text \" ->\" <+> pretty t\n\ndocRetTypeFormatted :: Maybe Type -> Doc\ndocRetTypeFormatted Nothing = empty\ndocRetTypeFormatted (Just t) = text \" → \" <> text \"*\" <> pretty (SimplifiedType t) <> text \"*\"\n\ndocAncestors :: Pretty a => [a] -> Doc\ndocAncestors [] = empty\ndocAncestors as = parens (commaList as)\n\n-- | Format parameters with italicized types\ndocParamsWithTypes :: PosPar -> KwdPar -> Doc\ndocParamsWithTypes p k = parens $ docPosParFormatted p <> docKwdParSep p k <> docKwdParFormatted k\n  where\n    docKwdParSep PosNIL KwdNIL = empty\n    docKwdParSep PosNIL _ = empty\n    docKwdParSep _ KwdNIL = empty\n    docKwdParSep _ _ = text \", \"\n\ndocPosParFormatted :: PosPar -> Doc\ndocPosParFormatted PosNIL = empty\ndocPosParFormatted (PosPar n t e p) =\n    let param = pretty n <> formatType t <> formatDefault e\n    in case p of\n        PosNIL -> param\n        _ -> param <> comma <+> docPosParFormatted p\ndocPosParFormatted (PosSTAR n t) = text \"*\" <> pretty n <> formatType t\n\ndocKwdParFormatted :: KwdPar -> Doc\ndocKwdParFormatted KwdNIL = empty\ndocKwdParFormatted (KwdPar n t e k) =\n    let param = pretty n <> formatType t <> formatDefault e\n    in case k of\n        KwdNIL -> param\n        _ -> param <> comma <+> docKwdParFormatted k\ndocKwdParFormatted (KwdSTAR n t) = text \"**\" <> pretty n <> formatType t\n\nformatType :: Maybe Type -> Doc\nformatType Nothing = empty\nformatType (Just t) = colon <+> text \"*\" <> pretty (SimplifiedType t) <> text \"*\"\n\nformatDefault :: Maybe Expr -> Doc\nformatDefault Nothing = empty\nformatDefault (Just e) = text \" = \" <> pretty e\n\n\n\n-- | Document class body with types - extract attributes and methods in Markdown\ndocClassBodyWithTypes :: TEnv -> Suite -> Doc\ndocClassBodyWithTypes tenv stmts =\n    let (attrs, methods) = partitionClassMembersWithTypes tenv stmts\n        attrsDoc = if null attrs\n                   then empty\n                   else text \"**Attributes:**\" $+$ blank $+$ vcat (punctuate blank attrs)\n        methodsDoc = if null methods\n                     then empty\n                     else text \"**Methods:**\" $+$ blank $+$ vcat (punctuate blank methods)\n    in case (isEmpty attrsDoc, isEmpty methodsDoc) of\n        (True, True) -> empty\n        (False, True) -> attrsDoc\n        (True, False) -> methodsDoc\n        (False, False) -> attrsDoc $+$ blank $+$ methodsDoc\n\n-- | Document protocol body with types - extract method signatures in Markdown\ndocProtocolBodyWithTypes :: TEnv -> Suite -> Doc\ndocProtocolBodyWithTypes tenv stmts =\n    let methods = concatMap (extractMethodsWithTypes tenv) stmts\n    in if null methods\n       then empty\n       else text \"**Methods:**\" $+$ blank $+$ vcat (punctuate blank methods)\n\n\n-- | Partition class members into attributes and methods with types\npartitionClassMembersWithTypes :: TEnv -> Suite -> ([Doc], [Doc])\npartitionClassMembersWithTypes tenv stmts = foldl partition ([], []) stmts\n  where\n    partition (attrs, methods) (Signature _ vs sc d) = (attrs ++ [docAttribute vs sc], methods)\n    partition (attrs, methods) (Decl _ decls) = (attrs, methods ++ map (docMethodWithTypes tenv) decls)\n    partition acc _ = acc\n\n-- | Extract method documentation from statements with types\nextractMethodsWithTypes :: TEnv -> Stmt -> [Doc]\nextractMethodsWithTypes tenv (Decl _ decls) = map (docMethodWithTypes tenv) decls\nextractMethodsWithTypes _ (Signature _ vs sc d) = [docMethodSignature vs sc]\nextractMethodsWithTypes _ _ = []\n\n-- | Document an attribute in Markdown\ndocAttribute :: [Name] -> TSchema -> Doc\ndocAttribute vs (TSchema _ _ t) =\n    text \"-\" <+> text \"`\" <> commaList vs <> text \"`:\" <+> text \"*\" <> pretty (SimplifiedType t) <> text \"*\"\n\n\n-- | Document a method signature in Markdown\ndocMethodSignature :: [Name] -> TSchema -> Doc\ndocMethodSignature vs (TSchema _ _ t) =\n    text \"-\" <+> text \"`\" <> commaList vs <> text \"`:\" <+> text \"*\" <> pretty (SimplifiedType t) <> text \"*\"\n\n-- | Document a method in Markdown with types\ndocMethodWithTypes :: TEnv -> Decl -> Doc\ndocMethodWithTypes tenv (Def _ n q p k a b _ _ ddoc) =\n    let (inferredType, paramsWithTypes, retType) = case lookup n tenv of\n            Just (NDef (TSchema _ _ t@(TFun _ _ posRow kwdRow resType)) _ _) ->\n                (Just t, enrichParamsMarkdown posRow kwdRow p k, Just resType)\n            Just (NSig (TSchema _ _ t@(TFun _ _ posRow kwdRow resType)) _ _) ->\n                (Just t, enrichParamsMarkdown posRow kwdRow p k, Just resType)\n            _ -> (Nothing, docParamsWithTypes p k, a)\n        signature = text \"-\" <+> text \"`\" <> pretty n <> text \"`\" <> docGenerics q <> paramsWithTypes <>\n                    docRetTypeFormatted (if isJust retType then retType else a)\n        docstr = case ddoc of\n            Just ds -> nest 2 (text ds)\n            Nothing -> empty\n    in signature $+$\n       (if isEmpty docstr then empty else blank $+$ docstr)\n  where\n    isJust (Just _) = True\n    isJust Nothing = False\n\n    enrichParamsMarkdown :: PosRow -> KwdRow -> PosPar -> KwdPar -> Doc\n    enrichParamsMarkdown posRow kwdRow p k =\n        parens $ enrichPosParamsMarkdown posRow p <> kwdParSepLocal p k <> enrichKwdParamsMarkdown kwdRow k\n\n    kwdParSepLocal :: PosPar -> KwdPar -> Doc\n    kwdParSepLocal PosNIL KwdNIL = empty\n    kwdParSepLocal PosNIL _ = empty\n    kwdParSepLocal _ KwdNIL = empty\n    kwdParSepLocal _ _ = text \", \"\n\n    enrichPosParamsMarkdown :: PosRow -> PosPar -> Doc\n    enrichPosParamsMarkdown _ PosNIL = empty\n    enrichPosParamsMarkdown posRow (PosPar n t e p) =\n        -- Skip witness parameters\n        if isWitnessParam n\n        then enrichPosParamsMarkdown (advanceRow posRow) p\n        else\n            let inferredType = extractParamTypeFromRow (nstr n) posRow\n                paramType = case inferredType of\n                    Just it -> Just it\n                    Nothing -> t\n                param = pretty n <> formatType paramType <> formatDefault e\n                nextParams = enrichPosParamsMarkdown (advanceRow posRow) p\n            in case p of\n                PosNIL -> param\n                _ -> if isEmpty nextParams\n                     then param\n                     else param <> comma <+> nextParams\n    enrichPosParamsMarkdown _ (PosSTAR n t) = text \"*\" <> pretty n <> formatType t\n\n    enrichKwdParamsMarkdown :: KwdRow -> KwdPar -> Doc\n    enrichKwdParamsMarkdown _ KwdNIL = empty\n    enrichKwdParamsMarkdown kwdRow (KwdPar n t e k) =\n        let inferredType = extractParamTypeFromRow (nstr n) kwdRow\n            paramType = case inferredType of\n                Just it -> Just it\n                Nothing -> t\n            param = pretty n <> formatType paramType <> formatDefault e\n        in case k of\n            KwdNIL -> param\n            _ -> param <> comma <+> enrichKwdParamsMarkdown kwdRow k\n    enrichKwdParamsMarkdown _ (KwdSTAR n t) = text \"**\" <> pretty n <> formatType t\n\n    extractParamTypeFromRow :: String -> Type -> Maybe Type\n    extractParamTypeFromRow _ (TNil _ _) = Nothing\n    extractParamTypeFromRow name (TRow _ _ n t rest)\n        | nstr n == name = Just t\n        | otherwise = extractParamTypeFromRow name rest\n    extractParamTypeFromRow _ _ = Nothing\n\n    advanceRow :: Type -> Type\n    advanceRow (TRow _ _ _ _ rest) = rest\n    advanceRow t = t\ndocMethodWithTypes _ _ = empty\n\n-- | Print documentation as Markdown with type information\nprintMdDoc :: NameInfo -> Module -> String\nprintMdDoc nmod m = render (docModuleWithTypes nmod m)\n\n-- | Print documentation as ASCII with optional styling and type information\n-- Parameters:\n--   useStyle: Enable ANSI control codes (bold + color)\n--   tenv: Type environment for enhanced type information\n--   module: The module to document\nprintAsciiDoc :: Bool -> NameInfo -> Module -> String\nprintAsciiDoc useStyle nmod m =\n    render (docModuleAsciiUnified useStyle nmod m) ++ \"\\n\"\n\n\n-- Terminal formatting codes\nbold, underline, reset :: Bool -> String\nbold True = \"\\ESC[1m\"\nbold False = \"\"\nunderline True = \"\\ESC[4m\"\nunderline False = \"\"\nreset True = \"\\ESC[0m\"\nreset False = \"\"\n\n-- Color codes (only when color is enabled)\ncyan, yellow, green, dim :: Bool -> String\ncyan True = \"\\ESC[36m\"\ncyan False = \"\"\nyellow True = \"\\ESC[33m\"\nyellow False = \"\"\ngreen True = \"\\ESC[32m\"\ngreen False = \"\"\ndim True = \"\\ESC[2m\"\ndim False = \"\"\n\n-- | Generate ASCII documentation from a module with unified style and type handling\ndocModuleAsciiUnified :: Bool -> NameInfo -> Module -> Doc\ndocModuleAsciiUnified useStyle (NModule _ tenv mdocstring) (Module qn _ _ stmts) =\n    -- Use module docstring from NModule\n    let moduleDocstring = mdocstring\n        (title, restDoc) = case moduleDocstring of\n            Just ds -> splitDocstring ds\n            Nothing -> (\"\", Nothing)\n        -- Module header with visual emphasis\n        header = text (bold useStyle) <> pretty qn <> text (reset useStyle) <>\n                 (if null title then empty else text \" - \" <> text title)\n        bodyDoc = case restDoc of\n            Just body -> blank $+$ text body $+$ blank\n            Nothing -> empty\n    in header $+$ bodyDoc $+$ blank $+$ docTopLevelAsciiUnified useStyle tenv stmts\n\n-- | Document top-level definitions with unified style and type handling\ndocTopLevelAsciiUnified :: Bool -> TEnv -> Suite -> Doc\ndocTopLevelAsciiUnified useStyle tenv stmts =\n    let docs = concatMap (extractTopLevelUnified useStyle tenv) stmts\n        separated = case docs of\n            [] -> []\n            [d] -> [d]\n            (d:ds) -> d : map (blank $+$) ds\n    in vcat separated\n\n-- | Extract and document top-level declarations with unified handling\nextractTopLevelUnified :: Bool -> TEnv -> Stmt -> [Doc]\nextractTopLevelUnified useStyle tenv (Decl _ decls) = map (docDeclUnified useStyle tenv) decls\nextractTopLevelUnified useStyle tenv (With _ _ body) = concatMap (extractTopLevelUnified useStyle tenv) body\nextractTopLevelUnified _ _ _ = []\n\n\n\n\n\n\n\n-- | Extract QBinds from a type schema\ngetQBindsFromSchema :: TSchema -> QBinds\ngetQBindsFromSchema (TSchema _ qb _) = qb\n\n-- | Collect all ugly type variable names from QBinds\ncollectUglyTypeVars :: QBinds -> [Name]\ncollectUglyTypeVars qbs = [tvname tv | QBind tv _ <- qbs, isUglyName (tvname tv)]\n  where\n    isUglyName n = let name = nstr n\n                   in length name > 2 && elem '_' name && all isDigit (drop 2 name)\n\n-- | Collect all ugly type variable names from a Type\ncollectUglyTypeVarsFromType :: Type -> [Name]\ncollectUglyTypeVarsFromType (TVar _ tv) =\n    let name = tvname tv\n    in if isUglyName name then [name] else []\n  where\n    isUglyName n = let nameStr = nstr n\n                   in length nameStr > 2 && elem '_' nameStr && all isDigit (drop 2 nameStr)\ncollectUglyTypeVarsFromType (TFun _ _ posRow kwdRow resType) =\n    collectUglyTypeVarsFromType posRow ++ collectUglyTypeVarsFromType kwdRow ++ collectUglyTypeVarsFromType resType\ncollectUglyTypeVarsFromType (TCon _ (TC _ ts)) = concatMap collectUglyTypeVarsFromType ts\ncollectUglyTypeVarsFromType (TRow _ _ _ t rest) = collectUglyTypeVarsFromType t ++ collectUglyTypeVarsFromType rest\ncollectUglyTypeVarsFromType (TTuple _ posRow kwdRow) = collectUglyTypeVarsFromType posRow ++ collectUglyTypeVarsFromType kwdRow\ncollectUglyTypeVarsFromType (TOpt _ t) = collectUglyTypeVarsFromType t\ncollectUglyTypeVarsFromType _ = []\n\n-- | Create a mapping from ugly names to nice generic names (A, B, C...)\ncreateTypeVarMapping :: [Name] -> [(Name, Name)]\ncreateTypeVarMapping uglyNames = zip uglyNames niceNames\n  where\n    niceNames = [Name NoLoc [c] | c <- ['A'..'Z']]\n\n-- | Replace ugly type vars with nice names in a type\ncleanupTypeVars :: [(Name, Name)] -> Type -> Type\ncleanupTypeVars mapping (TVar l tv) =\n    case lookup (tvname tv) mapping of\n        Just niceName -> TVar l (TV (tvkind tv) niceName)\n        Nothing -> TVar l tv\ncleanupTypeVars mapping (TFun l fx posRow kwdRow resType) =\n    TFun l fx (cleanupTypeVars mapping posRow) (cleanupTypeVars mapping kwdRow) (cleanupTypeVars mapping resType)\ncleanupTypeVars mapping (TCon l (TC qn ts)) =\n    TCon l (TC qn (map (cleanupTypeVars mapping) ts))\ncleanupTypeVars mapping (TRow l k n t rest) =\n    TRow l k n (cleanupTypeVars mapping t) (cleanupTypeVars mapping rest)\ncleanupTypeVars mapping (TTuple l posRow kwdRow) =\n    TTuple l (cleanupTypeVars mapping posRow) (cleanupTypeVars mapping kwdRow)\ncleanupTypeVars mapping (TOpt l t) =\n    TOpt l (cleanupTypeVars mapping t)\ncleanupTypeVars _ t = t\n\n-- | Replace ugly type vars with nice names in QBinds\ncleanupQBinds :: [(Name, Name)] -> [QBind] -> [QBind]\ncleanupQBinds mapping = map cleanupQBind\n  where\n    cleanupQBind (QBind tv tcons) =\n        case lookup (tvname tv) mapping of\n            Just niceName -> QBind (TV (tvkind tv) niceName) (map (cleanupTCon mapping) tcons)\n            Nothing -> QBind tv (map (cleanupTCon mapping) tcons)\n\n    cleanupTCon :: [(Name, Name)] -> TCon -> TCon\n    cleanupTCon mapping (TC qn ts) = TC qn (map (cleanupTypeVars mapping) ts)\n\n-- | Document a declaration with unified style and type handling\ndocDeclUnified :: Bool -> TEnv -> Decl -> Doc\ndocDeclUnified useStyle tenv decl@(Def _ n q p k a b d x ddoc) =\n    let explicitGenerics = extractGenerics q\n        -- Look up inferred type information\n        (inferredType, qConstraints, docstringFromTEnv) = case lookup n tenv of\n            Just info@(NDef schema _ _) -> (Just schema, getQBindsFromSchema schema, extractNameDocstring info)\n            Just info@(NSig schema _ _) -> (Just schema, getQBindsFromSchema schema, extractNameDocstring info)\n            _ -> (Nothing, [], Nothing)\n\n        -- Create a mapping from ugly type vars to nice generic names\n        uglyTypeVarsFromQBinds = collectUglyTypeVars qConstraints\n        uglyTypeVarsFromType = case inferredType of\n            Just (TSchema _ _ t) -> collectUglyTypeVarsFromType t\n            _ -> []\n        allUglyTypeVars = nub (uglyTypeVarsFromQBinds ++ uglyTypeVarsFromType)\n        typeVarMapping = createTypeVarMapping allUglyTypeVars\n\n        -- Transform the inferred types using the mapping\n        (paramsWithTypes, retType) = case inferredType of\n            Just (TSchema _ _ (TFun _ _ posRow kwdRow resType)) ->\n                let cleanPosRow = cleanupTypeVars typeVarMapping posRow\n                    cleanKwdRow = cleanupTypeVars typeVarMapping kwdRow\n                    cleanRetType = cleanupTypeVars typeVarMapping resType\n                in (enrichParamsStyledAsciiDecl useStyle cleanPosRow cleanKwdRow p k, Just cleanRetType)\n            _ -> (docParamsStyledAscii useStyle useStyle p k, a)\n\n        -- Use docstring from AST declaration\n        docstr = case docstringFromTEnv of\n            Just ds -> Just ds\n            Nothing -> ddoc\n\n        -- Show generics if we have them (either explicit or inferred)\n        allGenerics = if null q && not (null typeVarMapping)\n                      then map snd typeVarMapping  -- Use the nice names from mapping\n                      else map (\\(QBind tv _) -> tvname tv) q\n        genericsDoc = if null allGenerics\n                      then empty\n                      else brackets $ hcat $ punctuate comma $ map pretty allGenerics\n\n        header = text (bold useStyle) <> pretty n <> text (reset useStyle) <>\n                 genericsDoc <> paramsWithTypes <> docRetTypeStyled useStyle useStyle retType\n        docstrDoc = case docstr of\n            Just ds -> nest 2 (text ds)\n            Nothing -> empty\n    in header $+$ (if isEmpty docstrDoc then empty else docstrDoc)\n  where\n    -- Check if a QBind contains ugly type variable names like T_638\n    isUglyTypeVar :: QBind -> Bool\n    isUglyTypeVar (QBind tv _) =\n        let name = nstr (tvname tv)\n        in length name > 2 && elem '_' name && all isDigit (drop 2 name)\n\n    -- Check if a type contains ugly type variable names\n    containsUglyTypeVar :: Type -> Bool\n    containsUglyTypeVar (TVar _ tv) =\n        let name = nstr (tvname tv)\n        in length name > 2 && elem '_' name && all isDigit (drop 2 name)\n    containsUglyTypeVar (TFun _ _ posRow kwdRow resType) =\n        containsUglyTypeVar posRow || containsUglyTypeVar kwdRow || containsUglyTypeVar resType\n    containsUglyTypeVar (TCon _ (TC _ ts)) = any containsUglyTypeVar ts\n    containsUglyTypeVar (TRow _ _ _ t rest) = containsUglyTypeVar t || containsUglyTypeVar rest\n    containsUglyTypeVar (TTuple _ posRow kwdRow) = containsUglyTypeVar posRow || containsUglyTypeVar kwdRow\n    containsUglyTypeVar (TOpt _ t) = containsUglyTypeVar t\n    containsUglyTypeVar _ = False\n\n    isNothing :: Maybe a -> Bool\n    isNothing Nothing = True\n    isNothing _ = False\n\n    -- Simple parameter display without types\n    docParamsSimpleAscii :: PosPar -> KwdPar -> Doc\n    docParamsSimpleAscii p k = parens $ docPosParSimple p <> docKwdParSepAscii p k <> docKwdParSimple k\n\n    docPosParSimple :: PosPar -> Doc\n    docPosParSimple PosNIL = empty\n    docPosParSimple (PosPar n _ _ p) =\n        let param = pretty n\n        in case p of\n            PosNIL -> param\n            _ -> param <> comma <+> docPosParSimple p\n    docPosParSimple (PosSTAR n _) = text \"*\" <> pretty n\n\n    docKwdParSimple :: KwdPar -> Doc\n    docKwdParSimple KwdNIL = empty\n    docKwdParSimple (KwdPar n _ _ k) =\n        let param = pretty n\n        in case k of\n            KwdNIL -> param\n            _ -> param <> comma <+> docKwdParSimple k\n    docKwdParSimple (KwdSTAR n _) = text \"**\" <> pretty n\n\n\n    enrichParamsStyledAsciiDecl :: Bool -> PosRow -> KwdRow -> PosPar -> KwdPar -> Doc\n    enrichParamsStyledAsciiDecl useStyle posRow kwdRow p k =\n        parens $ enrichPosParamsStyledDecl useStyle posRow p <> docKwdParSepAscii p k <>\n                 enrichKwdParamsStyledDecl useStyle kwdRow k\n\n    enrichPosParamsStyledDecl :: Bool -> PosRow -> PosPar -> Doc\n    enrichPosParamsStyledDecl _ _ PosNIL = empty\n    enrichPosParamsStyledDecl useStyle posRow (PosPar n t e p) =\n        -- Skip witness parameters\n        if isWitnessParam n\n        then enrichPosParamsStyledDecl useStyle (advanceRow posRow) p\n        else\n            let inferredType = extractParamTypeFromRow (nstr n) posRow\n                paramType = case inferredType of\n                    Just it -> Just it\n                    Nothing -> t\n                param = pretty n <> formatTypeStyled useStyle useStyle paramType <> formatDefault e\n                nextParams = enrichPosParamsStyledDecl useStyle (advanceRow posRow) p\n            in case p of\n                PosNIL -> param\n                _ -> if isEmpty nextParams\n                     then param\n                     else param <> comma <+> nextParams\n\n    enrichKwdParamsStyledDecl :: Bool -> KwdRow -> KwdPar -> Doc\n    enrichKwdParamsStyledDecl _ _ KwdNIL = empty\n    enrichKwdParamsStyledDecl useStyle kwdRow (KwdPar n t e k) =\n        -- Skip witness parameters\n        if isWitnessParam n\n        then enrichKwdParamsStyledDecl useStyle (advanceRow kwdRow) k\n        else\n            let inferredType = extractParamTypeFromKwdRow (nstr n) kwdRow\n                paramType = case inferredType of\n                    Just it -> Just it\n                    Nothing -> t\n                param = pretty n <> formatTypeStyled useStyle useStyle paramType <> formatDefault e\n                nextParams = enrichKwdParamsStyledDecl useStyle (advanceRow kwdRow) k\n            in case k of\n                KwdNIL -> param\n                _ -> if isEmpty nextParams\n                     then param\n                     else param <> comma <+> nextParams\n\ndocDeclUnified useStyle tenv (Actor _ n q p k b ddoc) =\n    let (paramsWithTypes, docstringFromTEnv) = case lookup n tenv of\n            Just info@(NAct _ posRow kwdRow _ mdoc) ->\n                (enrichParamsStyledAsciiActr useStyle posRow kwdRow p k, mdoc)\n            _ -> (docParamsStyledAscii useStyle useStyle p k, Nothing)\n        -- Use docstring from AST declaration\n        docstr = case docstringFromTEnv of\n            Just ds -> Just ds\n            Nothing -> ddoc\n        header = text (cyan useStyle ++ \"actor\" ++ reset useStyle) <+>\n                 text (bold useStyle) <> pretty n <> text (reset useStyle) <>\n                 docGenerics q <> paramsWithTypes\n        docstrDoc = case docstr of\n            Just ds -> nest 2 (text ds)\n            Nothing -> empty\n    in header $+$ (if isEmpty docstrDoc then empty else docstrDoc)\n  where\n    enrichParamsStyledAsciiActr useStyle posRow kwdRow p k =\n        parens $ enrichPosParamsStyledDecl useStyle posRow p <> docKwdParSepAscii p k <>\n                 enrichKwdParamsStyledDecl useStyle kwdRow k\n\n    enrichPosParamsStyledDecl _ _ PosNIL = empty\n    enrichPosParamsStyledDecl useStyle posRow (PosPar n t e p) =\n        if isWitnessParam n\n        then enrichPosParamsStyledDecl useStyle (advanceRow posRow) p\n        else\n            let inferredType = extractParamTypeFromRow (nstr n) posRow\n                paramType = case inferredType of\n                    Just it -> Just it\n                    Nothing -> t\n                param = pretty n <> formatTypeStyled useStyle useStyle paramType <> formatDefault e\n                nextParams = enrichPosParamsStyledDecl useStyle (advanceRow posRow) p\n            in case p of\n                PosNIL -> param\n                _ -> if isEmpty nextParams\n                     then param\n                     else param <> comma <+> nextParams\n\n    enrichKwdParamsStyledDecl _ _ KwdNIL = empty\n    enrichKwdParamsStyledDecl useStyle kwdRow (KwdPar n t e k) =\n        if isWitnessParam n\n        then enrichKwdParamsStyledDecl useStyle (advanceRow kwdRow) k\n        else\n            let inferredType = extractParamTypeFromKwdRow (nstr n) kwdRow\n                paramType = case inferredType of\n                    Just it -> Just it\n                    Nothing -> t\n                param = pretty n <> formatTypeStyled useStyle useStyle paramType <> formatDefault e\n                nextParams = enrichKwdParamsStyledDecl useStyle (advanceRow kwdRow) k\n            in case k of\n                KwdNIL -> param\n                _ -> if isEmpty nextParams\n                     then param\n                     else param <> comma <+> nextParams\n\ndocDeclUnified useStyle tenv (Class _ n q a b ddoc) =\n    let docstringFromTEnv = case lookup n tenv of\n            Just info -> extractNameDocstring info\n            _ -> Nothing\n        -- Always get docstring from either TEnv or AST\n        docstr = case docstringFromTEnv of\n            Just ds -> Just ds\n            Nothing -> ddoc\n        header = text (cyan useStyle ++ \"class\" ++ reset useStyle) <+>\n                 text (bold useStyle) <> pretty n <> text (reset useStyle) <>\n                 docGenerics q <> docAncestors a\n        docstrDoc = case docstr of\n            Just ds -> nest 2 (text ds)\n            Nothing -> empty\n        -- Document methods and attributes\n        (attrs, methods) = extractClassMembers b\n        attrsDoc = if null attrs then empty else\n            blank $+$ nest 2 (text (yellow useStyle ++ \"Attributes:\" ++ reset useStyle)) $+$\n            vcat [nest 4 (docAttrUnified useStyle attr) | attr <- attrs]\n        methodsDoc = if null methods then empty else\n            blank $+$ nest 2 (text (yellow useStyle ++ \"Methods:\" ++ reset useStyle)) $+$\n            vcat [nest 4 (docMethodUnified useStyle tenv n meth) | meth <- methods]\n    in header $+$ (if isEmpty docstrDoc then empty else docstrDoc) $+$ attrsDoc $+$ methodsDoc\n  where\n    -- Document a single attribute\n    docAttrUnified :: Bool -> (Name, Maybe Type) -> Doc\n    docAttrUnified useStyle (name, mtype) =\n        pretty name <>\n        case mtype of\n            Just t -> text \": \" <> pretty (SimplifiedType t)\n            Nothing -> empty\n\n    -- Document a method signature\n    docMethodUnified :: Bool -> TEnv -> Name -> (Name, QBinds, PosPar, KwdPar, Maybe Type, Maybe String) -> Doc\n    docMethodUnified useStyle tenv className (methodName, q, p, k, retType, docstr) =\n        let (paramsWithTypes, inferredRetType) =\n                -- Try to get type info from TEnv\n                case lookup className tenv of\n                    Just (NClass _ _ methods _) ->\n                        case lookup methodName methods of\n                            Just info ->\n                                case extractTypeFromNameInfo info of\n                                    Just (TFun _ _ posRow kwdRow resType) ->\n                                        (enrichParamsStyledAsciiDecl useStyle posRow kwdRow p k, Just resType)\n                                    _ -> (docParamsStyledAscii useStyle useStyle p k, retType)\n                            _ -> (docParamsStyledAscii useStyle useStyle p k, retType)\n                    _ -> (docParamsStyledAscii useStyle useStyle p k, retType)\n            -- Don't show return type for __init__ methods or methods that return None\n            showRetType = case fromMaybe retType inferredRetType of\n                          Just (TNone _) -> empty\n                          Just t -> if nstr methodName == \"__init__\"\n                                    then empty\n                                    else docRetTypeStyled useStyle useStyle (Just t)\n                          Nothing -> empty\n            header = text (bold useStyle) <> pretty methodName <> text (reset useStyle) <>\n                     docGenerics q <> paramsWithTypes <> showRetType\n            docstrDoc = case docstr of\n                Just ds -> text ds\n                Nothing -> empty\n        in header $+$ (if isEmpty docstrDoc then empty else nest 2 docstrDoc)\n      where\n        fromMaybe def Nothing = def\n        fromMaybe _ (Just x) = Just x\n\n        extractTypeFromNameInfo :: NameInfo -> Maybe Type\n        extractTypeFromNameInfo (NDef (TSchema _ _ t) _ _) = Just t\n        extractTypeFromNameInfo (NSig (TSchema _ _ t) _ _) = Just t\n        extractTypeFromNameInfo _ = Nothing\n\n        enrichParamsStyledAsciiDecl useStyle posRow kwdRow p k =\n            parens $ enrichPosParamsStyledMeth useStyle posRow p <> docKwdParSepAscii p k <>\n                     enrichKwdParamsStyledMeth useStyle kwdRow k\n\n        enrichPosParamsStyledMeth _ _ PosNIL = empty\n        enrichPosParamsStyledMeth useStyle posRow (PosPar n t e p) =\n            if isWitnessParam n\n            then enrichPosParamsStyledMeth useStyle (advanceRow posRow) p\n            else\n                let inferredType = extractParamTypeFromRow (nstr n) posRow\n                    paramType = case inferredType of\n                        Just it -> Just it\n                        Nothing -> t\n                    param = pretty n <> formatTypeStyled useStyle useStyle paramType <> formatDefault e\n                    nextParams = enrichPosParamsStyledMeth useStyle (advanceRow posRow) p\n                in case p of\n                    PosNIL -> param\n                    _ -> if isEmpty nextParams\n                         then param\n                         else param <> comma <+> nextParams\n\n        enrichKwdParamsStyledMeth _ _ KwdNIL = empty\n        enrichKwdParamsStyledMeth useStyle kwdRow (KwdPar n t e k) =\n            if isWitnessParam n\n            then enrichKwdParamsStyledMeth useStyle (advanceRow kwdRow) k\n            else\n                let inferredType = extractParamTypeFromKwdRow (nstr n) kwdRow\n                    paramType = case inferredType of\n                        Just it -> Just it\n                        Nothing -> t\n                    param = pretty n <> formatTypeStyled useStyle useStyle paramType <> formatDefault e\n                    nextParams = enrichKwdParamsStyledMeth useStyle (advanceRow kwdRow) k\n                in case k of\n                    KwdNIL -> param\n                    _ -> if isEmpty nextParams\n                         then param\n                         else param <> comma <+> nextParams\n\ndocDeclUnified useStyle tenv (Protocol _ n q a b ddoc) =\n    let docstringFromTEnv = case lookup n tenv of\n            Just info -> extractNameDocstring info\n            _ -> Nothing\n        -- Always get docstring from either TEnv or AST\n        docstr = case docstringFromTEnv of\n            Just ds -> Just ds\n            Nothing -> ddoc\n        header = text (cyan useStyle ++ \"protocol\" ++ reset useStyle) <+>\n                 text (bold useStyle) <> pretty n <> text (reset useStyle) <>\n                 docGenerics q <> docAncestors a\n        docstrDoc = case docstr of\n            Just ds -> nest 2 (text ds)\n            Nothing -> empty\n        -- Document protocol methods\n        methods = extractProtocolMethods b\n        methodsDoc = if null methods then empty else\n            blank $+$ nest 2 (text (yellow useStyle ++ \"Methods:\" ++ reset useStyle)) $+$\n            vcat (intersperse blank [nest 4 (docProtocolMethod meth) | meth <- methods])\n    in header $+$ (if isEmpty docstrDoc then empty else docstrDoc) $+$ methodsDoc\n  where\n    -- Document a protocol method\n    docProtocolMethod :: (Name, QBinds, PosPar, KwdPar, Maybe Type, Maybe String) -> Doc\n    docProtocolMethod (methodName, q, p, k, retType, docstr) =\n        -- Protocol methods are just signatures\n        let header = pretty methodName <> text \":\" <+>\n                     case retType of\n                         Just t -> pretty (SimplifiedType t)\n                         Nothing -> text \"()\"\n            docstrDoc = case docstr of\n                Just ds -> nest 2 (text ds)\n                Nothing -> empty\n        in header $+$ (if isEmpty docstrDoc then empty else docstrDoc)\n\ndocDeclUnified useStyle tenv (Extension _ q c a b ddoc) =\n    let docstringFromTEnv = Nothing  -- Extensions don't have docstrings in TEnv\n        -- Get docstring from AST\n        docstr = ddoc\n        header = text (cyan useStyle ++ \"extension\" ++ reset useStyle) <+>\n                 pretty c <> docAncestors a\n        docstrDoc = case docstr of\n            Just ds -> nest 2 (text ds)\n            Nothing -> empty\n    in header $+$ (if isEmpty docstrDoc then empty else docstrDoc)\n\n\n-- | Document a declaration with man-page visual style and types\n\n-- | Format parameters with visual styling\ndocParamsStyledAscii :: Bool -> Bool -> PosPar -> KwdPar -> Doc\ndocParamsStyledAscii useBold useColor p k = parens $ docPosParStyled useBold useColor p <> docKwdParSepAscii p k <> docKwdParStyled useBold useColor k\n\ndocPosParStyled :: Bool -> Bool -> PosPar -> Doc\ndocPosParStyled _ _ PosNIL = empty\ndocPosParStyled useBold useColor (PosPar n t e p) =\n    let param = pretty n <> formatTypeStyled useBold useColor t <> formatDefault e\n    in case p of\n        PosNIL -> param\n        _ -> param <> comma <+> docPosParStyled useBold useColor p\ndocPosParStyled useBold useColor (PosSTAR n t) = text \"*\" <> pretty n <> formatTypeStyled useBold useColor t\n\ndocKwdParStyled :: Bool -> Bool -> KwdPar -> Doc\ndocKwdParStyled _ _ KwdNIL = empty\ndocKwdParStyled useBold useColor (KwdPar n t e k) =\n    let param = pretty n <> formatTypeStyled useBold useColor t <> formatDefault e\n    in case k of\n        KwdNIL -> param\n        _ -> param <> comma <+> docKwdParStyled useBold useColor k\ndocKwdParStyled useBold useColor (KwdSTAR n t) = text \"**\" <> pretty n <> formatTypeStyled useBold useColor t\n\nformatTypeStyled :: Bool -> Bool -> Maybe Type -> Doc\nformatTypeStyled _ _ Nothing = empty\nformatTypeStyled useBold useColor (Just t) =\n    if useColor\n    then colon <+> text (green True) <> pretty (SimplifiedType t) <> text (reset True)\n    else colon <+> text (underline useBold) <> pretty (SimplifiedType t) <> text (reset useBold)\n\ndocRetTypeStyled :: Bool -> Bool -> Maybe Type -> Doc\ndocRetTypeStyled _ _ Nothing = empty\ndocRetTypeStyled useBold useColor (Just t) =\n    if useColor\n    then text \" -> \" <> text (green True) <> pretty (SimplifiedType t) <> text (reset True)\n    else text \" -> \" <> text (underline useBold) <> pretty (SimplifiedType t) <> text (reset useBold)\n\n-- | Document class body with visual styling\n-- | Document class body with visual styling and types\ndocClassBodyStyledWithTypes :: Bool -> Bool -> TEnv -> Suite -> Doc\ndocClassBodyStyledWithTypes useBold useColor tenv stmts =\n    let (attrs, methods) = partitionClassMembersStyledWithTypes useBold useColor tenv stmts\n        attrsDoc = if null attrs\n                   then empty\n                   else nest 2 (text \"Attributes:\" $+$ vcat attrs)\n        methodsDoc = if null methods\n                     then empty\n                     else nest 2 (text \"Methods:\" $+$ vcatWithSpacing methods)\n    in case (isEmpty attrsDoc, isEmpty methodsDoc) of\n        (True, True) -> empty\n        (False, True) -> attrsDoc\n        (True, False) -> methodsDoc\n        (False, False) -> attrsDoc $+$ blank $+$ methodsDoc\n  where\n    vcatWithSpacing [] = empty\n    vcatWithSpacing [m] = m\n    vcatWithSpacing (m:ms) = m $+$ vcat (map addSpacing ms)\n\n    addSpacing m = blank $+$ m\n\n-- | Document protocol body with visual styling and types\ndocProtocolBodyStyledWithTypes :: Bool -> Bool -> TEnv -> Suite -> Doc\ndocProtocolBodyStyledWithTypes useBold useColor tenv stmts =\n    let methods = concatMap (extractMethodsStyledWithTypes useBold useColor tenv) stmts\n    in if null methods\n       then empty\n       else nest 2 (text \"Methods:\" $+$ vcatWithSpacing methods)\n  where\n    vcatWithSpacing [] = empty\n    vcatWithSpacing [m] = m\n    vcatWithSpacing (m:ms) = m $+$ vcat (map addSpacing ms)\n\n    addSpacing m = blank $+$ m\n\n-- | Partition class members into attributes and methods with styling\npartitionClassMembersStyled :: Bool -> Bool -> Suite -> ([Doc], [Doc])\npartitionClassMembersStyled useBold useColor stmts = foldl partition ([], []) stmts\n  where\n    partition (attrs, methods) (Signature _ vs sc d) = (attrs ++ [docAttributeStyled useBold useColor vs sc], methods)\n    partition (attrs, methods) (Decl _ decls) = (attrs, methods ++ map (docMethodStyled useBold useColor) decls)\n    partition acc _ = acc\n\n-- | Partition class members into attributes and methods with styling and types\npartitionClassMembersStyledWithTypes :: Bool -> Bool -> TEnv -> Suite -> ([Doc], [Doc])\npartitionClassMembersStyledWithTypes useBold useColor tenv stmts = foldl partition ([], []) stmts\n  where\n    partition (attrs, methods) (Signature _ vs sc d) = (attrs ++ [docAttributeStyled useBold useColor vs sc], methods)\n    partition (attrs, methods) (Decl _ decls) = (attrs, methods ++ map (docMethodStyledWithTypes useBold useColor tenv) decls)\n    partition acc _ = acc\n\n-- | Extract method documentation with styling\nextractMethodsStyled :: Bool -> Bool -> Stmt -> [Doc]\nextractMethodsStyled useBold useColor (Decl _ decls) = map (docMethodStyled useBold useColor) decls\nextractMethodsStyled useBold useColor (Signature _ vs sc d) = [docMethodSignatureStyled useBold useColor vs sc]\nextractMethodsStyled _ _ _ = []\n\n-- | Extract method documentation with styling and types\nextractMethodsStyledWithTypes :: Bool -> Bool -> TEnv -> Stmt -> [Doc]\nextractMethodsStyledWithTypes useBold useColor tenv (Decl _ decls) = map (docMethodStyledWithTypes useBold useColor tenv) decls\nextractMethodsStyledWithTypes useBold useColor _ (Signature _ vs sc d) = [docMethodSignatureStyled useBold useColor vs sc]\nextractMethodsStyledWithTypes _ _ _ _ = []\n\n-- | Document an attribute with styling\ndocAttributeStyled :: Bool -> Bool -> [Name] -> TSchema -> Doc\ndocAttributeStyled useBold useColor vs (TSchema _ _ t) =\n    if useColor\n    then nest 2 $ text \"- \" <> commaList vs <> text \": \" <> text (green True) <> pretty (SimplifiedType t) <> text (reset True)\n    else nest 2 $ text \"- \" <> commaList vs <> text \": \" <> text (underline useBold) <> pretty (SimplifiedType t) <> text (reset useBold)\n\n-- | Document a method with styling\ndocMethodStyled :: Bool -> Bool -> Decl -> Doc\ndocMethodStyled useBold useColor (Def _ n q p k a b _ _ ddoc) =\n    let signature = nest 2 $ text \"- \" <> text (bold useBold) <> pretty n <> text (reset useBold) <>\n                    docGenerics q <> docParamsStyledAscii useBold useColor p k <> docRetTypeStyled useBold useColor a\n        docstr = case ddoc of\n            Just ds -> nest 4 (text ds)\n            Nothing -> empty\n    in signature $+$\n       (if isEmpty docstr then empty else docstr)\ndocMethodStyled _ _ _ = empty\n\n-- | Document a method signature with styling\ndocMethodSignatureStyled :: Bool -> Bool -> [Name] -> TSchema -> Doc\ndocMethodSignatureStyled useBold useColor vs (TSchema _ _ t) =\n    if useColor\n    then nest 2 $ text \"- \" <> commaList vs <> text \": \" <> text (green True) <> pretty (SimplifiedType t) <> text (reset True)\n    else nest 2 $ text \"- \" <> commaList vs <> text \": \" <> text (underline useBold) <> pretty (SimplifiedType t) <> text (reset useBold)\n\n-- | Document a method with styling and types\ndocMethodStyledWithTypes :: Bool -> Bool -> TEnv -> Decl -> Doc\ndocMethodStyledWithTypes useBold useColor tenv (Def _ n q p k a b _ _ ddoc) =\n    let (inferredType, paramsWithTypes, retType) = case lookup n tenv of\n            Just (NDef (TSchema _ _ t@(TFun _ _ posRow kwdRow resType)) _ _) ->\n                (Just t, enrichParamsStyledAscii useBold useColor posRow kwdRow p k, Just resType)\n            Just (NSig (TSchema _ _ t@(TFun _ _ posRow kwdRow resType)) _ _) ->\n                (Just t, enrichParamsStyledAscii useBold useColor posRow kwdRow p k, Just resType)\n            _ -> (Nothing, docParamsStyledAscii useBold useColor p k, a)\n        signature = nest 2 $ text \"- \" <> text (bold useBold) <> pretty n <> text (reset useBold) <>\n                    docGenerics q <> paramsWithTypes <>\n                    docRetTypeStyled useBold useColor (if isJust retType then retType else a)\n        docstr = case ddoc of\n            Just ds -> nest 4 (text ds)\n            Nothing -> empty\n    in signature $+$\n       (if isEmpty docstr then empty else docstr)\n  where\n    isJust (Just _) = True\n    isJust Nothing = False\n\n    enrichParamsStyledAscii :: Bool -> Bool -> PosRow -> KwdRow -> PosPar -> KwdPar -> Doc\n    enrichParamsStyledAscii useBold useColor posRow kwdRow p k =\n        parens $ enrichPosParamsStyled useBold useColor posRow p <> docKwdParSepAscii p k <>\n                 enrichKwdParamsStyled useBold useColor kwdRow k\n\n    enrichPosParamsStyled :: Bool -> Bool -> PosRow -> PosPar -> Doc\n    enrichPosParamsStyled _ _ _ PosNIL = empty\n    enrichPosParamsStyled useBold useColor posRow (PosPar n t e p) =\n        -- Skip witness parameters\n        if isWitnessParam n\n        then enrichPosParamsStyled useBold useColor (advanceRow posRow) p\n        else\n            let inferredType = extractParamTypeFromRow (nstr n) posRow\n                paramType = case inferredType of\n                    Just it -> Just it\n                    Nothing -> t\n                param = pretty n <> formatTypeStyled useBold useColor paramType <> formatDefault e\n                nextParams = enrichPosParamsStyled useBold useColor (advanceRow posRow) p\n            in case p of\n                PosNIL -> param\n                _ -> if isEmpty nextParams\n                     then param\n                     else param <> comma <+> nextParams\n    enrichPosParamsStyled useBold useColor _ (PosSTAR n t) =\n        text \"*\" <> pretty n <> formatTypeStyled useBold useColor t\n\n    enrichKwdParamsStyled :: Bool -> Bool -> KwdRow -> KwdPar -> Doc\n    enrichKwdParamsStyled _ _ _ KwdNIL = empty\n    enrichKwdParamsStyled useBold useColor kwdRow (KwdPar n t e k) =\n        let inferredType = extractParamTypeFromRow (nstr n) kwdRow\n            paramType = case inferredType of\n                Just it -> Just it\n                Nothing -> t\n            param = pretty n <> formatTypeStyled useBold useColor paramType <> formatDefault e\n        in case k of\n            KwdNIL -> param\n            _ -> param <> comma <+> enrichKwdParamsStyled useBold useColor kwdRow k\n    enrichKwdParamsStyled useBold useColor _ (KwdSTAR n t) =\n        text \"**\" <> pretty n <> formatTypeStyled useBold useColor t\n\n    extractParamTypeFromRow :: String -> Type -> Maybe Type\n    extractParamTypeFromRow _ (TNil _ _) = Nothing\n    extractParamTypeFromRow name (TRow _ _ n t rest)\n        | nstr n == name = Just t\n        | otherwise = extractParamTypeFromRow name rest\n    extractParamTypeFromRow _ _ = Nothing\n\n    advanceRow :: Type -> Type\n    advanceRow (TRow _ _ _ _ rest) = rest\n    advanceRow t = t\ndocMethodStyledWithTypes _ _ _ _ = empty\n\n-- | Format parameters for ASCII\ndocParamsAscii :: PosPar -> KwdPar -> Doc\ndocParamsAscii p k = parens $ docPosParAscii p <> docKwdParSepAscii p k <> docKwdParAscii k\n\ndocKwdParSepAscii :: PosPar -> KwdPar -> Doc\ndocKwdParSepAscii PosNIL KwdNIL = empty\ndocKwdParSepAscii PosNIL _ = empty\ndocKwdParSepAscii _ KwdNIL = empty\ndocKwdParSepAscii _ _ = text \", \"\n\ndocPosParAscii :: PosPar -> Doc\ndocPosParAscii PosNIL = empty\ndocPosParAscii (PosPar n t e p) =\n    let param = pretty n <> formatTypeAscii t <> formatDefault e\n    in case p of\n        PosNIL -> param\n        _ -> param <> comma <+> docPosParAscii p\ndocPosParAscii (PosSTAR n t) = text \"*\" <> pretty n <> formatTypeAscii t\n\ndocKwdParAscii :: KwdPar -> Doc\ndocKwdParAscii KwdNIL = empty\ndocKwdParAscii (KwdPar n t e k) =\n    let param = pretty n <> formatTypeAscii t <> formatDefault e\n    in case k of\n        KwdNIL -> param\n        _ -> param <> comma <+> docKwdParAscii k\ndocKwdParAscii (KwdSTAR n t) = text \"**\" <> pretty n <> formatTypeAscii t\n\nformatTypeAscii :: Maybe Type -> Doc\nformatTypeAscii Nothing = empty\nformatTypeAscii (Just t) = colon <+> pretty (SimplifiedType t)\n\ndocRetTypeAscii :: Maybe Type -> Doc\ndocRetTypeAscii Nothing = empty\ndocRetTypeAscii (Just t) = text \" -> \" <> pretty (SimplifiedType t)\n\n\n-- | Print documentation as HTML with type information\nprintHtmlDoc :: NameInfo -> Module -> String\nprintHtmlDoc nmod m = unlines\n        [ \"<!DOCTYPE html>\"\n        , \"<html lang=\\\"en\\\">\"\n        , \"<head>\"\n        , \"  <meta charset=\\\"UTF-8\\\">\"\n        , \"  <meta name=\\\"viewport\\\" content=\\\"width=device-width, initial-scale=1.0\\\">\"\n        , \"  <title>\" ++ moduleTitle m ++ \"</title>\"\n        , \"  <style>\"\n        , htmlStyles\n        , \"  </style>\"\n        , \"  <script>\"\n        , htmlScript\n        , \"  </script>\"\n        , \"</head>\"\n        , \"<body>\"\n        , \"  <div class=\\\"container\\\">\"\n        , render (docModuleHtmlWithTypes nmod m)\n        , \"  </div>\"\n        , \"</body>\"\n        , \"</html>\"\n        ]\n\n-- | Get module title for HTML\nmoduleTitle :: Module -> String\nmoduleTitle (Module qn _ _ _) = render (pretty qn)\n\n-- | CSS styles for HTML documentation\nhtmlStyles :: String\nhtmlStyles = unlines\n    [ \"    /* Light theme colors (default) */\"\n    , \"    :root {\"\n    , \"      --text-primary: #24292e;\"\n    , \"      --text-secondary: #6a737d;\"\n    , \"      --text-link: #0366d6;\"\n    , \"      --bg-primary: #ffffff;\"\n    , \"      --bg-secondary: #f6f8fa;\"\n    , \"      --border: #e1e4e8;\"\n    , \"      --code-bg: #f6f8fa;\"\n    , \"      --type-color: #6f42c1;\"\n    , \"      --keyword-color: #d73a49;\"\n    , \"      --generic-color: #e36209;\"\n    , \"      --generic-hover: #fb8532;\"\n    , \"      --shadow: rgba(27, 31, 35, 0.04);\"\n    , \"      --shadow-medium: rgba(27, 31, 35, 0.12);\"\n    , \"    }\"\n    , \"    \"\n    , \"    /* Dark theme colors (activated by OS preference) */\"\n    , \"    @media (prefers-color-scheme: dark) {\"\n    , \"      :root {\"\n    , \"        --text-primary: #c9d1d9;\"\n    , \"        --text-secondary: #8b949e;\"\n    , \"        --text-link: #58a6ff;\"\n    , \"        --bg-primary: #0d1117;\"\n    , \"        --bg-secondary: #161b22;\"\n    , \"        --border: #30363d;\"\n    , \"        --code-bg: #161b22;\"\n    , \"        --type-color: #d2a8ff;\"\n    , \"        --keyword-color: #ff7b72;\"\n    , \"        --generic-color: #ffa657;\"\n    , \"        --generic-hover: #ffb77c;\"\n    , \"        --shadow: rgba(0, 0, 0, 0.3);\"\n    , \"        --shadow-medium: rgba(0, 0, 0, 0.5);\"\n    , \"      }\"\n    , \"    }\"\n    , \"    \"\n    , \"    * { box-sizing: border-box; }\"\n    , \"    \"\n    , \"    body {\"\n    , \"      font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Helvetica, Arial, sans-serif;\"\n    , \"      font-size: 16px;\"\n    , \"      line-height: 1.5;\"\n    , \"      color: var(--text-primary);\"\n    , \"      background: var(--bg-primary);\"\n    , \"      margin: 0;\"\n    , \"      padding: 0;\"\n    , \"    }\"\n    , \"    \"\n    , \"    .container {\"\n    , \"      max-width: 960px;\"\n    , \"      margin: 0 auto;\"\n    , \"      padding: 2rem;\"\n    , \"    }\"\n    , \"    \"\n    , \"    /* Typography */\"\n    , \"    h1 {\"\n    , \"      font-size: 2rem;\"\n    , \"      font-weight: 600;\"\n    , \"      margin: 0 0 1rem 0;\"\n    , \"      padding-bottom: 0.3rem;\"\n    , \"      border-bottom: 1px solid var(--border);\"\n    , \"    }\"\n    , \"    \"\n    , \"    h2 {\"\n    , \"      font-size: 1.25rem;\"\n    , \"      font-weight: 600;\"\n    , \"      margin: 2.5rem 0 1rem 0;\"\n    , \"    }\"\n    , \"    \"\n    , \"    h3 {\"\n    , \"      font-size: 1rem;\"\n    , \"      font-weight: 600;\"\n    , \"      color: var(--text-secondary);\"\n    , \"      margin: 1.5rem 0 0.5rem 0;\"\n    , \"      text-transform: uppercase;\"\n    , \"      letter-spacing: 0.02em;\"\n    , \"    }\"\n    , \"    \"\n    , \"    /* Indent ATTRIBUTES/METHODS headers under classes/actors */\"\n    , \"    .declaration-block h3 {\"\n    , \"      margin-left: 2rem;\"\n    , \"    }\"\n    , \"    \"\n    , \"    p {\"\n    , \"      margin: 0 0 1rem 0;\"\n    , \"    }\"\n    , \"    \"\n    , \"    /* Code */\"\n    , \"    code {\"\n    , \"      font-family: 'SF Mono', Monaco, Consolas, 'Liberation Mono', 'Courier New', monospace;\"\n    , \"      font-size: 0.875em;\"\n    , \"      background: var(--code-bg);\"\n    , \"      padding: 0.2em 0.4em;\"\n    , \"      border-radius: 3px;\"\n    , \"      border: 1px solid var(--border);\"\n    , \"    }\"\n    , \"    \"\n    , \"    h2 code {\"\n    , \"      background: none;\"\n    , \"      padding: 0;\"\n    , \"      font-size: 1em;\"\n    , \"      border: none;\"\n    , \"    }\"\n    , \"    \"\n    , \"    /* Type coloring */\"\n    , \"    .type {\"\n    , \"      color: var(--type-color);\"\n    , \"    }\"\n    , \"    \"\n    , \"    /* Type links */\"\n    , \"    .type-link {\"\n    , \"      color: var(--type-color);\"\n    , \"      text-decoration: none;\"\n    , \"      border-bottom: 1px dotted var(--type-color);\"\n    , \"    }\"\n    , \"    \"\n    , \"    .type-link:hover {\"\n    , \"      text-decoration: none;\"\n    , \"      border-bottom: 1px solid var(--type-color);\"\n    , \"    }\"\n    , \"    \"\n    , \"    .keyword {\"\n    , \"      color: var(--keyword-color);\"\n    , \"      font-weight: 500;\"\n    , \"      font-size: 1rem;\"\n    , \"    }\"\n    , \"    \"\n    , \"    .param-name {\"\n    , \"      font-weight: 500;\"\n    , \"    }\"\n    , \"    \"\n    , \"    .default-value {\"\n    , \"      color: var(--text-secondary);\"\n    , \"    }\"\n    , \"    \"\n    , \"    /* Generic type parameters */\"\n    , \"    .generic-type {\"\n    , \"      color: var(--generic-color);\"\n    , \"      cursor: pointer;\"\n    , \"      transition: color 0.2s ease;\"\n    , \"      position: relative;\"\n    , \"      display: inline-block;\"\n    , \"    }\"\n    , \"    \"\n    , \"    .generic-type:hover,\"\n    , \"    .generic-type.highlight {\"\n    , \"      color: var(--generic-hover);\"\n    , \"      text-decoration: underline;\"\n    , \"      text-decoration-style: dotted;\"\n    , \"    }\"\n    , \"    \"\n    , \"    /* Tooltip for generic types - default position below */\"\n    , \"    .generic-type[data-tooltip]:hover::after {\"\n    , \"      content: attr(data-tooltip);\"\n    , \"      display: block;\"\n    , \"      position: absolute;\"\n    , \"      top: 100%;\"\n    , \"      left: 50%;\"\n    , \"      transform: translateX(-50%);\"\n    , \"      margin-top: 5px;\"\n    , \"      padding: 8px 12px;\"\n    , \"      background-color: rgba(0, 0, 0, 0.8);\"\n    , \"      color: white;\"\n    , \"      font-size: 0.75rem;\"\n    , \"      font-weight: normal;\"\n    , \"      white-space: pre-wrap;\"\n    , \"      max-width: 700px;\"\n    , \"      min-width: 200px;\"\n    , \"      text-align: left;\"\n    , \"      border-radius: 4px;\"\n    , \"      pointer-events: none;\"\n    , \"      opacity: 0;\"\n    , \"      animation: fadeIn 0.2s ease-in-out forwards;\"\n    , \"      z-index: 1000;\"\n    , \"    }\"\n    , \"    \"\n    , \"    /* Tooltip positioned above when not near top */\"\n    , \"    .generic-type[data-tooltip]:not(.tooltip-below):hover::after {\"\n    , \"      top: auto;\"\n    , \"      bottom: 100%;\"\n    , \"      margin-top: 0;\"\n    , \"      margin-bottom: 5px;\"\n    , \"    }\"\n    , \"    \"\n    , \"    @keyframes fadeIn {\"\n    , \"      from { opacity: 0; }\"\n    , \"      to { opacity: 1; }\"\n    , \"    }\"\n    , \"    \"\n    , \"    /* Documentation strings */\"\n    , \"    .docstring {\"\n    , \"      color: var(--text-secondary);\"\n    , \"      margin: 0.5rem 0 1.5rem 0;\"\n    , \"      padding-left: 1rem;\"\n    , \"    }\"\n    , \"    \"\n    , \"    .module-doc {\"\n    , \"      margin: 1rem 0 2rem 0;\"\n    , \"      color: var(--text-primary);\"\n    , \"      font-size: 1.1rem;\"\n    , \"      line-height: 1.6;\"\n    , \"    }\"\n    , \"    \"\n    , \"    /* Sections */\"\n    , \"    .section {\"\n    , \"      margin: 1.5rem 0;\"\n    , \"      padding-left: 2rem;\"\n    , \"    }\"\n    , \"    \"\n    , \"    /* Lists */\"\n    , \"    ul {\"\n    , \"      list-style: none;\"\n    , \"      padding: 0;\"\n    , \"      margin: 0;\"\n    , \"    }\"\n    , \"    \"\n    , \"    li {\"\n    , \"      margin: 0.5rem 0;\"\n    , \"    }\"\n    , \"    \"\n    , \"    /* Attribute items */\"\n    , \"    .attribute-item {\"\n    , \"      margin: 0.5rem 0;\"\n    , \"      padding-left: 1rem;\"\n    , \"      border-left: 3px solid var(--border);\"\n    , \"    }\"\n    , \"    \"\n    , \"    .attribute-item code {\"\n    , \"      background: none;\"\n    , \"      padding: 0;\"\n    , \"      border: none;\"\n    , \"    }\"\n    , \"    \"\n    , \"    /* Method items */\"\n    , \"    .method-item {\"\n    , \"      margin: 1rem 0;\"\n    , \"    }\"\n    , \"    \"\n    , \"    .method-signature {\"\n    , \"      font-family: 'SF Mono', Monaco, Consolas, monospace;\"\n    , \"      font-size: 0.875rem;\"\n    , \"      padding-left: 1rem;\"\n    , \"      border-left: 3px solid var(--border);\"\n    , \"    }\"\n    , \"    \"\n    , \"    .method-signature code {\"\n    , \"      background: none;\"\n    , \"      padding: 0;\"\n    , \"      border: none;\"\n    , \"    }\"\n    , \"    \"\n    , \"    .method-doc {\"\n    , \"      color: var(--text-secondary);\"\n    , \"      margin: 0.25rem 0 0 1.5rem;\"\n    , \"      font-size: 0.875rem;\"\n    , \"    }\"\n    , \"    \"\n    , \"    /* Attributes and methods sections */\"\n    , \"    .attributes, .methods {\"\n    , \"      margin: 1.5rem 0 1.5rem 2rem;\"\n    , \"    }\"\n    , \"    \"\n    , \"    /* Declaration blocks - no visual boxes, just spacing */\"\n    , \"    .declaration-block {\"\n    , \"      margin: 2rem 0;\"\n    , \"    }\"\n    , \"    \"\n    , \"    /* Module index styles */\"\n    , \"    .module-list {\"\n    , \"      list-style: none;\"\n    , \"      padding: 0;\"\n    , \"      margin: 0;\"\n    , \"    }\"\n    , \"    \"\n    , \"    .module-item {\"\n    , \"      margin: 0.5rem 0;\"\n    , \"      padding: 0.75rem 1rem;\"\n    , \"      background: var(--bg-secondary);\"\n    , \"      border-radius: 6px;\"\n    , \"      border: 1px solid var(--border);\"\n    , \"      transition: all 0.2s ease;\"\n    , \"    }\"\n    , \"    \"\n    , \"    .module-item:hover {\"\n    , \"      border-color: var(--text-link);\"\n    , \"      transform: translateY(-1px);\"\n    , \"    }\"\n    , \"    \"\n    , \"    .module-link {\"\n    , \"      text-decoration: none;\"\n    , \"      color: var(--text-link);\"\n    , \"      font-weight: 500;\"\n    , \"      display: block;\"\n    , \"    }\"\n    , \"    \"\n    , \"    .module-path {\"\n    , \"      font-family: 'SF Mono', Monaco, Consolas, monospace;\"\n    , \"      font-size: 0.875rem;\"\n    , \"    }\"\n    , \"    \"\n    , \"    .module-doc {\"\n    , \"      color: var(--text-secondary);\"\n    , \"      font-size: 0.875rem;\"\n    , \"      margin-top: 0.25rem;\"\n    , \"    }\"\n    , \"    \"\n    , \"    /* Smooth transitions for theme changes */\"\n    , \"    * {\"\n    , \"      transition: background-color 0.3s ease, color 0.3s ease, border-color 0.3s ease;\"\n    , \"    }\"\n    , \"    \"\n    , \"    /* Responsive */\"\n    , \"    @media (max-width: 768px) {\"\n    , \"      .container {\"\n    , \"        padding: 1rem;\"\n    , \"      }\"\n    , \"      h1 {\"\n    , \"        font-size: 1.75rem;\"\n    , \"      }\"\n    , \"      h2 {\"\n    , \"        font-size: 1.25rem;\"\n    , \"      }\"\n    , \"    }\"\n    ]\n\n-- | JavaScript for generic type hover effects\nhtmlScript :: String\nhtmlScript = unlines\n    [ \"    document.addEventListener('DOMContentLoaded', function() {\"\n    , \"      const genericTypes = document.querySelectorAll('.generic-type');\"\n    , \"      \"\n    , \"      genericTypes.forEach(function(elem) {\"\n    , \"        elem.addEventListener('mouseenter', function() {\"\n    , \"          const typeName = elem.getAttribute('data-generic');\"\n    , \"          \"\n    , \"          // Check if tooltip would go off-screen at the top\"\n    , \"          const rect = elem.getBoundingClientRect();\"\n    , \"          const tooltipHeight = 200; // Approximate height\"\n    , \"          if (rect.top < tooltipHeight) {\"\n    , \"            elem.classList.add('tooltip-below');\"\n    , \"          } else {\"\n    , \"            elem.classList.remove('tooltip-below');\"\n    , \"          }\"\n    , \"          \"\n    , \"          // Get the scope attribute - all generic types should have this\"\n    , \"          const scope = elem.getAttribute('data-scope');\"\n    , \"          \"\n    , \"          // Only highlight elements with same type name AND same scope\"\n    , \"          document.querySelectorAll('.generic-type[data-generic=\\\"' + typeName + '\\\"][data-scope=\\\"' + scope + '\\\"]').forEach(function(t) {\"\n    , \"            t.classList.add('highlight');\"\n    , \"          });\"\n    , \"        });\"\n    , \"        \"\n    , \"        elem.addEventListener('mouseleave', function() {\"\n    , \"          const typeName = elem.getAttribute('data-generic');\"\n    , \"          document.querySelectorAll('.generic-type[data-generic=\\\"' + typeName + '\\\"].highlight').forEach(function(t) {\"\n    , \"            t.classList.remove('highlight');\"\n    , \"          });\"\n    , \"        });\"\n    , \"      });\"\n    , \"    });\"\n    ]\n\n\n-- | Generate HTML documentation from a module with type information\ndocModuleHtmlWithTypes :: NameInfo -> Module -> Doc\ndocModuleHtmlWithTypes (NModule _ tenv mdocstring) (Module modName _ _ stmts) =\n    -- Use module docstring from NModule\n    let moduleDocstring = mdocstring\n        (title, restDoc) = case moduleDocstring of\n            Just ds -> splitDocstring ds\n            Nothing -> (\"\", Nothing)\n        header = text \"<h1>\" <> text (render (pretty modName)) <>\n                 (if null title then empty else text \" - \" <> text (htmlEscape title)) <> text \"</h1>\"\n        bodyDoc = case restDoc of\n            Just body -> text \"<div class=\\\"module-doc\\\">\" <> text (nl2br $ htmlEscape body) <> text \"</div>\"\n            Nothing -> empty\n        -- Collect class info from both local module and type environment\n        classInfos = collectClassInfos modName tenv stmts\n    in header $+$ bodyDoc $+$ docTopLevelHtmlWithTypesAndClassInfo tenv modName classInfos stmts\n  where\n    nl2br = intercalate \"<br>\" . lines\n\n-- | Collect class information from local module and imported modules\ncollectClassInfos :: ModName -> TEnv -> Suite -> Set ClassInfo\ncollectClassInfos currentModule tenv stmts =\n    let localClasses = Set.map (\\n -> ClassInfo n currentModule True) (collectClassNames stmts)\n        importedClasses = Set.fromList $ concatMap extractClassFromTEnv tenv\n    in Set.union localClasses importedClasses\n  where\n    extractClassFromTEnv (n, NClass _ _ _ _) = [ClassInfo n currentModule False]  -- Mark as imported\n    extractClassFromTEnv _ = []\n\n-- | Collect all class names defined in the module\ncollectClassNames :: Suite -> Set Name\ncollectClassNames stmts = Set.fromList $ concatMap extractClassNames stmts\n  where\n    extractClassNames :: Stmt -> [Name]\n    extractClassNames (Decl _ decls) = concatMap extractClassNamesFromDecl decls\n    extractClassNames (With _ _ body) = concatMap extractClassNames body\n    extractClassNames _ = []\n\n    extractClassNamesFromDecl :: Decl -> [Name]\n    extractClassNamesFromDecl (Class _ n _ _ _ _) = [n]\n    extractClassNamesFromDecl _ = []\n\n-- | Data type to track class locations for cross-module linking\ndata ClassInfo = ClassInfo\n    { ciName :: Name\n    , ciModule :: ModName\n    , ciIsLocal :: Bool  -- True if in current module\n    } deriving (Eq, Ord, Show)\n\n-- | Build URL for a class reference\nbuildClassUrl :: ModName -> ClassInfo -> String\nbuildClassUrl currentModule ci\n    | ciIsLocal ci = \"#class-\" ++ render (pretty (ciName ci))\n    | otherwise =\n        let targetPath = modPath (ciModule ci)\n            currentPath = modPath currentModule\n            relativePath = computeRelativePath currentPath targetPath\n        in relativePath ++ \"#class-\" ++ render (pretty (ciName ci))\n  where\n    -- Compute relative path from current module to target module\n    computeRelativePath :: [String] -> [String] -> String\n    computeRelativePath current target =\n        let upLevels = length current - 1  -- -1 because we're in a file, not a directory\n            prefix = concat (replicate upLevels \"../\")\n            targetFile = intercalate \"/\" target ++ \".html\"\n        in if upLevels == 0 then targetFile else prefix ++ targetFile\n\n-- | Compute relative path between two module paths\ncomputeRelativeModulePath :: ModName -> ModName -> String\ncomputeRelativeModulePath currentModule targetModule =\n    let currentPath = modPath currentModule\n        targetPath = modPath targetModule\n        -- Number of directories to go up from current module\n        -- For modules in the root (length 1), we don't go up any levels\n        -- For nested modules, we go up (length - 1) levels\n        upLevels = if length currentPath > 1 then length currentPath - 1 else 0\n        prefix = concat (replicate upLevels \"../\")\n        targetFile = if null targetPath\n                     then \"index.html\"  -- Root module\n                     else intercalate \"/\" targetPath ++ \".html\"\n    in if upLevels == 0 then targetFile else prefix ++ targetFile\n\n-- | Extract and document top-level definitions in HTML\ndocTopLevelHtml :: Suite -> Doc\ndocTopLevelHtml = docTopLevelHtmlWithTypes []\n\n-- | Extract and document top-level definitions in HTML with types\ndocTopLevelHtmlWithTypes :: TEnv -> Suite -> Doc\ndocTopLevelHtmlWithTypes tenv stmts = docTopLevelHtmlWithTypesAndClasses tenv Set.empty stmts\n\n-- | Extract and document top-level definitions in HTML with types and class links\ndocTopLevelHtmlWithTypesAndClasses :: TEnv -> Set Name -> Suite -> Doc\ndocTopLevelHtmlWithTypesAndClasses tenv classNames stmts =\n    let docs = concatMap (extractTopLevelHtmlWithTypesAndClasses tenv classNames) stmts\n        separated = case docs of\n            [] -> []\n            [d] -> [d]\n            (d:ds) -> d : map (blank $+$) ds\n    in vcat separated\n\n-- | Extract and document top-level definitions in HTML with types and class info\ndocTopLevelHtmlWithTypesAndClassInfo :: TEnv -> ModName -> Set ClassInfo -> Suite -> Doc\ndocTopLevelHtmlWithTypesAndClassInfo tenv currentModule classInfos stmts =\n    let docs = concatMap (extractTopLevelHtmlWithTypesAndClassInfo tenv currentModule classInfos) stmts\n        separated = case docs of\n            [] -> []\n            [d] -> [d]\n            (d:ds) -> d : map (blank $+$) ds\n    in vcat separated\n\n-- | Extract documentation-worthy top-level statements for HTML\nextractTopLevelHtml :: Stmt -> [Doc]\nextractTopLevelHtml = extractTopLevelHtmlWithTypes []\n\n-- | Extract documentation-worthy top-level statements for HTML with types\nextractTopLevelHtmlWithTypes :: TEnv -> Stmt -> [Doc]\nextractTopLevelHtmlWithTypes tenv (Decl _ decls) = map (docDeclHtmlWithTypes tenv) decls\nextractTopLevelHtmlWithTypes tenv (With _ _ body) = concatMap (extractTopLevelHtmlWithTypes tenv) body\nextractTopLevelHtmlWithTypes _ _ = []\n\n-- | Extract documentation-worthy top-level statements for HTML with types and class links\nextractTopLevelHtmlWithTypesAndClasses :: TEnv -> Set Name -> Stmt -> [Doc]\nextractTopLevelHtmlWithTypesAndClasses tenv classNames (Decl _ decls) = map (docDeclHtmlWithTypesAndClasses tenv classNames) decls\nextractTopLevelHtmlWithTypesAndClasses tenv classNames (With _ _ body) = concatMap (extractTopLevelHtmlWithTypesAndClasses tenv classNames) body\nextractTopLevelHtmlWithTypesAndClasses _ _ _ = []\n\n-- | Extract documentation-worthy top-level statements for HTML with types and class info\nextractTopLevelHtmlWithTypesAndClassInfo :: TEnv -> ModName -> Set ClassInfo -> Stmt -> [Doc]\nextractTopLevelHtmlWithTypesAndClassInfo tenv currentModule classInfos (Decl _ decls) =\n    map (docDeclHtmlWithTypesAndClassInfo tenv currentModule classInfos) decls\nextractTopLevelHtmlWithTypesAndClassInfo tenv currentModule classInfos (With _ _ body) =\n    concatMap (extractTopLevelHtmlWithTypesAndClassInfo tenv currentModule classInfos) body\nextractTopLevelHtmlWithTypesAndClassInfo _ _ _ _ = []\n\n-- | Escape HTML special characters\nhtmlEscape :: String -> String\nhtmlEscape [] = []\nhtmlEscape ('<':xs) = \"&lt;\" ++ htmlEscape xs\nhtmlEscape ('>':xs) = \"&gt;\" ++ htmlEscape xs\nhtmlEscape ('&':xs) = \"&amp;\" ++ htmlEscape xs\nhtmlEscape ('\"':xs) = \"&quot;\" ++ htmlEscape xs\nhtmlEscape ('\\'':xs) = \"&#39;\" ++ htmlEscape xs\nhtmlEscape (x:xs) = x : htmlEscape xs\n\n-- | Extract generic type names from QBinds\nextractGenerics :: QBinds -> Set Name\nextractGenerics binds = Set.fromList [tvname tv | QBind tv _ <- binds]\n\n-- | Check if a parameter name is a witness parameter\nisWitnessParam :: Name -> Bool\nisWitnessParam n = case nstr n of\n    'W':'_':rest -> all isDigit rest && not (null rest)\n    _ -> False\n  where\n    isDigit c = c >= '0' && c <= '9'\n\n-- | Simplify a qualified name by removing builtin module prefix\nsimplifyQName :: QName -> QName\nsimplifyQName (GName m n) | modPath m == [\"__builtin__\"] = NoQ n\nsimplifyQName qn = qn\n\n-- | Wrapper for simplified type pretty printing\nnewtype SimplifiedType = SimplifiedType Type\n\ninstance Pretty SimplifiedType where\n    pretty (SimplifiedType t) = prettySimplifiedType t\n\n-- | Pretty print a type with simplified qualified names\nprettySimplifiedType :: Type -> Doc\nprettySimplifiedType (TVar _ tv) = pretty tv\nprettySimplifiedType (TCon _ tc) = prettySimplifiedTCon tc\nprettySimplifiedType (TFun _ _ posrow kwdrow restype) =\n    let args = prettySimplifiedFunArgs posrow kwdrow\n    in if isEmpty args\n       then prettySimplifiedType restype\n       else args <+> text \"->\" <+> prettySimplifiedType restype\nprettySimplifiedType (TTuple _ posrow kwdrow) =\n    parens (prettySimplifiedTupleArgs posrow kwdrow)\nprettySimplifiedType (TOpt _ t) = text \"?\" <> prettySimplifiedType t\nprettySimplifiedType (TNone _) = text \"None\"\nprettySimplifiedType (TWild _) = text \"_\"\nprettySimplifiedType (TNil _ _) = empty\nprettySimplifiedType (TRow _ _ label rtype rtail) =\n    pretty label <> colon <+> prettySimplifiedType rtype <>\n    case rtail of\n        TNil _ _ -> empty\n        _ -> comma <+> prettySimplifiedType rtail\nprettySimplifiedType (TStar _ _ rtail) = text \"*\" <> prettySimplifiedType rtail\nprettySimplifiedType (TFX _ fx) = pretty fx\n\nprettySimplifiedTCon :: TCon -> Doc\nprettySimplifiedTCon (TC qn ts)\n    | qn == qnList && length ts == 1 = text \"list\" <> brackets (prettySimplifiedType (head ts))\n    | qn == qnDict && length ts == 2 = text \"dict\" <> brackets (prettySimplifiedType (head ts) <> comma <+> prettySimplifiedType (ts !! 1))\n    | qn == qnSetT && length ts == 1 = text \"set\" <> brackets (prettySimplifiedType (head ts))\n    | otherwise = pretty (simplifyQName qn) <>\n        if null ts then empty else brackets (hcat $ punctuate comma [pretty (SimplifiedType t) | t <- ts])\n  where\n    hcat [] = empty\n    hcat [x] = x\n    hcat (x:xs) = x <> hcat xs\n\nprettySimplifiedFunArgs :: PosRow -> KwdRow -> Doc\nprettySimplifiedFunArgs posrow kwdrow =\n    let posArgs = prettySimplifiedPosRow posrow\n        kwdArgs = prettySimplifiedKwdRow kwdrow\n    in case (isEmpty posArgs, isEmpty kwdArgs) of\n        (True, True) -> empty\n        (False, True) -> parens posArgs\n        (True, False) -> parens kwdArgs\n        (False, False) -> parens (posArgs <> comma <+> kwdArgs)\n\nprettySimplifiedTupleArgs :: PosRow -> KwdRow -> Doc\nprettySimplifiedTupleArgs posrow kwdrow =\n    let posArgs = prettySimplifiedPosRow posrow\n        kwdArgs = prettySimplifiedKwdRow kwdrow\n    in case (isEmpty posArgs, isEmpty kwdArgs) of\n        (True, True) -> empty\n        (False, True) -> posArgs\n        (True, False) -> kwdArgs\n        (False, False) -> posArgs <> comma <+> kwdArgs\n\nprettySimplifiedPosRow :: PosRow -> Doc\nprettySimplifiedPosRow (TNil _ _) = empty\nprettySimplifiedPosRow (TRow _ _ _ rtype rtail) =\n    prettySimplifiedType rtype <>\n    case rtail of\n        TNil _ _ -> empty\n        _ -> comma <+> prettySimplifiedPosRow rtail\nprettySimplifiedPosRow (TStar _ _ _) = text \"*args\"\nprettySimplifiedPosRow t = prettySimplifiedType t\n\nprettySimplifiedKwdRow :: KwdRow -> Doc\nprettySimplifiedKwdRow (TNil _ _) = empty\nprettySimplifiedKwdRow (TRow _ _ label rtype rtail) =\n    pretty label <> colon <+> prettySimplifiedType rtype <>\n    case rtail of\n        TNil _ _ -> empty\n        _ -> comma <+> prettySimplifiedKwdRow rtail\nprettySimplifiedKwdRow (TStar _ _ _) = text \"**kwargs\"\nprettySimplifiedKwdRow t = prettySimplifiedType t\n\n-- | Render type with generic type highlighting\nrenderTypeWithGenerics :: Set Name -> Type -> String\nrenderTypeWithGenerics generics t = renderTypeWithGenericsAndConstraints generics [] t\n\n-- | Render type with generic type highlighting and constraints\nrenderTypeWithGenericsAndConstraints :: Set Name -> QBinds -> Type -> String\nrenderTypeWithGenericsAndConstraints generics constraints t = renderTypeHtml generics constraints t\n  where\n    renderTypeHtml :: Set Name -> QBinds -> Type -> String\n    renderTypeHtml gens cons (TVar _ tv)\n        | Set.member (tvname tv) gens =\n            let nameStr = render (pretty (tvname tv))\n                -- Find constraints for this type variable\n                tvConstraints = [preds | QBind qtv preds <- cons, tvname qtv == tvname tv]\n                tooltip = case tvConstraints of\n                    [] -> \"Generic type \" ++ nameStr ++ \"\\n\\nThis is a placeholder for any type.\\nAll \" ++\n                          nameStr ++ \"s must be the same type.\"\n                    (preds:_) -> if null preds\n                        then \"Generic type \" ++ nameStr ++ \"\\n\\nThis is a placeholder for any type.\\nAll \" ++\n                             nameStr ++ \"s must be the same type.\"\n                        else \"Generic type \" ++ nameStr ++ \"\\n\\nThis is a placeholder for any type.\\nAll \" ++\n                             nameStr ++ \"s must be the same type.\\n\\n\" ++ nameStr ++ \" must support:\\n\" ++\n                             concatMap formatPredAsListItem preds\n                formatPredAsListItem p = \"  • \" ++ formatConstraintNameLocal p ++ \" protocol (\" ++ formatExampleForPredLocal p ++ \")\\n\"\n                formatConstraintNameLocal (TC qn _) = render . pretty . simplifyQName $ qn\n                formatExampleForPredLocal (TC (NoQ (Name _ \"Plus\")) _) = \"+ operator\"\n                formatExampleForPredLocal (TC (NoQ (Name _ \"Minus\")) _) = \"- operator\"\n                formatExampleForPredLocal (TC (NoQ (Name _ \"Times\")) _) = \"* operator\"\n                formatExampleForPredLocal (TC (NoQ (Name _ \"Divide\")) _) = \"/ operator\"\n                formatExampleForPredLocal (TC (NoQ (Name _ \"Eq\")) _) = \"== operator\"\n                formatExampleForPredLocal (TC (NoQ (Name _ \"Ord\")) _) = \"< > operators\"\n                formatExampleForPredLocal (TC (NoQ (Name _ \"Hash\")) _) = \"hash function\"\n                formatExampleForPredLocal _ = \"protocol methods\"\n            in \"<span class=\\\"generic-type\\\" data-generic=\\\"\" ++ nameStr ++\n               \"\\\" data-tooltip=\\\"\" ++ tooltip ++ \"\\\">\" ++ nameStr ++ \"</span>\"\n        | otherwise =\n            let simplified = render (pretty (SimplifiedType (TVar NoLoc tv)))\n            in if simplified == render (pretty (tvname tv))\n               then simplified  -- Already simplified\n               else simplified\n    renderTypeHtml gens cons (TCon _ tc) = renderTConHtmlSimplified gens cons tc\n    renderTypeHtml gens cons (TFun _ _ posrow kwdrow restype) =\n        let args = renderFunArgs gens cons posrow kwdrow\n        in if null args\n           then renderTypeHtml gens cons restype\n           else args ++ \" -> \" ++ renderTypeHtml gens cons restype\n    renderTypeHtml gens cons (TTuple _ posrow kwdrow) =\n        \"(\" ++ renderTupleArgs gens cons posrow kwdrow ++ \")\"\n    renderTypeHtml gens cons (TOpt _ t) = \"?\" ++ renderTypeHtml gens cons t\n    renderTypeHtml gens _ (TNone _) = \"None\"\n    renderTypeHtml gens _ (TWild _) = \"_\"\n    renderTypeHtml gens _ (TNil _ _) = \"\"\n    renderTypeHtml gens cons (TRow _ _ label rtype rtail) =\n        render (pretty label) ++ \": \" ++ renderTypeHtml gens cons rtype ++\n        case rtail of\n            TNil _ _ -> \"\"\n            _ -> \", \" ++ renderTypeHtml gens cons rtail\n    renderTypeHtml gens cons (TStar _ _ rtail) = \"*\" ++ renderTypeHtml gens cons rtail\n    renderTypeHtml gens _ (TFX _ fx) = render (pretty fx)\n    renderTypeHtml gens _ t = render (pretty (SimplifiedType t))  -- Fallback for any other type\n\n    renderTConHtml :: Set Name -> QBinds -> TCon -> String\n    renderTConHtml gens cons (TC qn ts)\n        | qn == qnList && length ts == 1 = \"[\" ++ renderTypeHtml gens cons (head ts) ++ \"]\"\n        | qn == qnDict && length ts == 2 = \"{\" ++ renderTypeHtml gens cons (head ts) ++ \": \" ++ renderTypeHtml gens cons (ts !! 1) ++ \"}\"\n        | qn == qnSetT && length ts == 1 = \"{\" ++ renderTypeHtml gens cons (head ts) ++ \"}\"\n        | otherwise = render (pretty (simplifyQName qn)) ++\n            if null ts then \"\" else \"[\" ++ intercalate \", \" (map (renderTypeHtml gens cons) ts) ++ \"]\"\n\n    renderTConHtmlSimplified :: Set Name -> QBinds -> TCon -> String\n    renderTConHtmlSimplified gens cons (TC qn ts)\n        | qn == qnList && length ts == 1 = \"[\" ++ renderTypeHtml gens cons (head ts) ++ \"]\"\n        | qn == qnDict && length ts == 2 = \"{\" ++ renderTypeHtml gens cons (head ts) ++ \": \" ++ renderTypeHtml gens cons (ts !! 1) ++ \"}\"\n        | qn == qnSetT && length ts == 1 = \"{\" ++ renderTypeHtml gens cons (head ts) ++ \"}\"\n        | otherwise = render (pretty (SimplifiedType (TCon NoLoc (TC qn ts))))\n\n    renderFunArgs :: Set Name -> QBinds -> PosRow -> KwdRow -> String\n    renderFunArgs gens cons posrow kwdrow =\n        let posArgs = renderPosRow gens cons posrow\n            kwdArgs = renderKwdRow gens cons kwdrow\n        in case (posArgs, kwdArgs) of\n            (\"\", \"\") -> \"\"\n            (p, \"\") -> \"(\" ++ p ++ \")\"\n            (\"\", k) -> \"(\" ++ k ++ \")\"\n            (p, k) -> \"(\" ++ p ++ \", \" ++ k ++ \")\"\n\n    renderTupleArgs :: Set Name -> QBinds -> PosRow -> KwdRow -> String\n    renderTupleArgs gens cons posrow kwdrow =\n        let posArgs = renderPosRow gens cons posrow\n            kwdArgs = renderKwdRow gens cons kwdrow\n        in case (posArgs, kwdArgs) of\n            (\"\", \"\") -> \"\"\n            (p, \"\") -> p\n            (\"\", k) -> k\n            (p, k) -> p ++ \", \" ++ k\n\n    renderPosRow :: Set Name -> QBinds -> PosRow -> String\n    renderPosRow gens _ (TNil _ _) = \"\"\n    renderPosRow gens cons (TRow _ _ _ rtype rtail) =\n        renderTypeHtml gens cons rtype ++\n        case rtail of\n            TNil _ _ -> \"\"\n            _ -> \", \" ++ renderPosRow gens cons rtail\n    renderPosRow gens _ (TStar _ _ _) = \"*args\"\n    renderPosRow gens cons t = renderTypeHtml gens cons t\n\n    renderKwdRow :: Set Name -> QBinds -> KwdRow -> String\n    renderKwdRow gens _ (TNil _ _) = \"\"\n    renderKwdRow gens cons (TRow _ _ label rtype rtail) =\n        render (pretty label) ++ \"=\" ++ renderTypeHtml gens cons rtype ++\n        case rtail of\n            TNil _ _ -> \"\"\n            _ -> \", \" ++ renderKwdRow gens cons rtail\n    renderKwdRow gens _ (TStar _ _ _) = \"**kwargs\"\n    renderKwdRow gens cons t = renderTypeHtml gens cons t\n\n-- | Render type with generic type highlighting, constraints and class links (with current module for relative paths)\nrenderTypeWithGenericsConstraintsAndClassesAndModule :: ModName -> Set Name -> QBinds -> Set Name -> Type -> String\nrenderTypeWithGenericsConstraintsAndClassesAndModule currentModule generics constraints classNames t =\n    renderTypeHtmlWithClassesAndModule currentModule generics constraints classNames t\n  where\n    renderTypeHtmlWithClassesAndModule :: ModName -> Set Name -> QBinds -> Set Name -> Type -> String\n    renderTypeHtmlWithClassesAndModule curMod gens cons classes (TVar _ tv)\n        | Set.member (tvname tv) gens =\n            let nameStr = render (pretty (tvname tv))\n                -- Find constraints for this type variable\n                tvConstraints = [preds | QBind qtv preds <- cons, tvname qtv == tvname tv]\n                tooltip = case tvConstraints of\n                    [] -> \"Generic type \" ++ nameStr ++ \"\\n\\nThis is a placeholder for any type.\\nAll \" ++\n                          nameStr ++ \"s must be the same type.\"\n                    (preds:_) -> if null preds\n                        then \"Generic type \" ++ nameStr ++ \"\\n\\nThis is a placeholder for any type.\\nAll \" ++\n                             nameStr ++ \"s must be the same type.\"\n                        else \"Generic type \" ++ nameStr ++ \"\\n\\nThis is a placeholder for any type.\\nAll \" ++\n                             nameStr ++ \"s must be the same type.\\n\\n\" ++ nameStr ++ \" must support:\\n\" ++\n                             concatMap formatPredAsListItem preds\n                formatPredAsListItem p = \"  • \" ++ formatConstraintNameLocal p ++ \" protocol (\" ++ formatExampleForPredLocal p ++ \")\\n\"\n                formatConstraintNameLocal (TC qn _) = render . pretty . simplifyQName $ qn\n                formatExampleForPredLocal (TC (NoQ (Name _ \"Plus\")) _) = \"+ operator\"\n                formatExampleForPredLocal (TC (NoQ (Name _ \"Minus\")) _) = \"- operator\"\n                formatExampleForPredLocal (TC (NoQ (Name _ \"Times\")) _) = \"* operator\"\n                formatExampleForPredLocal (TC (NoQ (Name _ \"Divide\")) _) = \"/ operator\"\n                formatExampleForPredLocal (TC (NoQ (Name _ \"Eq\")) _) = \"== operator\"\n                formatExampleForPredLocal (TC (NoQ (Name _ \"Ord\")) _) = \"< > operators\"\n                formatExampleForPredLocal (TC (NoQ (Name _ \"Hash\")) _) = \"hash function\"\n                formatExampleForPredLocal _ = \"protocol methods\"\n            in \"<span class=\\\"generic-type\\\" data-generic=\\\"\" ++ nameStr ++\n               \"\\\" data-tooltip=\\\"\" ++ tooltip ++ \"\\\">\" ++ nameStr ++ \"</span>\"\n        | otherwise =\n            let simplified = render (pretty (SimplifiedType (TVar NoLoc tv)))\n            in if simplified == render (pretty (tvname tv))\n               then simplified  -- Already simplified\n               else simplified\n    renderTypeHtmlWithClassesAndModule curMod gens cons classes (TCon _ tc) =\n        renderTConHtmlSimplifiedWithClassesAndModule curMod gens cons classes tc\n    renderTypeHtmlWithClassesAndModule curMod gens cons classes (TFun _ _ posrow kwdrow restype) =\n        let args = renderFunArgsWithClassesAndModule curMod gens cons classes posrow kwdrow\n        in if null args\n           then renderTypeHtmlWithClassesAndModule curMod gens cons classes restype\n           else args ++ \" -> \" ++ renderTypeHtmlWithClassesAndModule curMod gens cons classes restype\n    renderTypeHtmlWithClassesAndModule curMod gens cons classes (TTuple _ posrow kwdrow) =\n        \"(\" ++ renderTupleArgsWithClassesAndModule curMod gens cons classes posrow kwdrow ++ \")\"\n    renderTypeHtmlWithClassesAndModule curMod gens cons classes (TOpt _ t) =\n        \"?\" ++ renderTypeHtmlWithClassesAndModule curMod gens cons classes t\n    renderTypeHtmlWithClassesAndModule _ gens _ _ (TNone _) = \"None\"\n    renderTypeHtmlWithClassesAndModule _ gens _ _ (TWild _) = \"_\"\n    renderTypeHtmlWithClassesAndModule _ gens _ _ (TNil _ _) = \"\"\n    renderTypeHtmlWithClassesAndModule curMod gens cons classes (TRow _ _ label rtype rtail) =\n        render (pretty label) ++ \": \" ++ renderTypeHtmlWithClassesAndModule curMod gens cons classes rtype ++\n        case rtail of\n            TNil _ _ -> \"\"\n            _ -> \", \" ++ renderTypeHtmlWithClassesAndModule curMod gens cons classes rtail\n    renderTypeHtmlWithClassesAndModule curMod gens cons classes (TStar _ _ rtail) =\n        \"*\" ++ renderTypeHtmlWithClassesAndModule curMod gens cons classes rtail\n    renderTypeHtmlWithClassesAndModule _ gens _ _ (TFX _ fx) = render (pretty fx)\n    renderTypeHtmlWithClassesAndModule curMod gens _ classes t =\n        render (pretty (SimplifiedType t))  -- Fallback for any other type\n\n    renderTConHtmlSimplifiedWithClassesAndModule :: ModName -> Set Name -> QBinds -> Set Name -> TCon -> String\n    renderTConHtmlSimplifiedWithClassesAndModule curMod gens cons classes (TC qn ts)\n        | qn == qnList && length ts == 1 = \"[\" ++ renderTypeHtmlWithClassesAndModule curMod gens cons classes (head ts) ++ \"]\"\n        | qn == qnDict && length ts == 2 =\n            \"{\" ++ renderTypeHtmlWithClassesAndModule curMod gens cons classes (head ts) ++ \": \" ++\n            renderTypeHtmlWithClassesAndModule curMod gens cons classes (ts !! 1) ++ \"}\"\n        | qn == qnSetT && length ts == 1 = \"{\" ++ renderTypeHtmlWithClassesAndModule curMod gens cons classes (head ts) ++ \"}\"\n        | otherwise =\n            let simpleName = simplifyQName qn\n                nameStr = render (pretty simpleName)\n                -- Generate link based on qualified name with relative paths\n                linkStr = case qn of\n                    NoQ n -> if Set.member n classes\n                            then \"<a href=\\\"#class-\" ++ nameStr ++ \"\\\" class=\\\"type-link\\\">\" ++ nameStr ++ \"</a>\"\n                            else nameStr\n                    QName m n ->\n                        -- This is a qualified name from another module\n                        let relativePath = computeRelativeModulePath curMod m\n                            url = relativePath ++ \"#class-\" ++ render (pretty n)\n                        in \"<a href=\\\"\" ++ url ++ \"\\\" class=\\\"type-link\\\">\" ++ nameStr ++ \"</a>\"\n                    GName m n ->\n                        -- Global name (e.g., from __builtin__)\n                        let modPathList = modPath m\n                        in if modPathList == [\"__builtin__\"]\n                           then nameStr  -- Don't link builtin types\n                           else\n                               let relativePath = computeRelativeModulePath curMod m\n                                   url = relativePath ++ \"#class-\" ++ render (pretty n)\n                               in \"<a href=\\\"\" ++ url ++ \"\\\" class=\\\"type-link\\\">\" ++ nameStr ++ \"</a>\"\n            in linkStr ++ if null ts then \"\" else \"[\" ++ intercalate \", \" (map (renderTypeHtmlWithClassesAndModule curMod gens cons classes) ts) ++ \"]\"\n\n    renderFunArgsWithClassesAndModule :: ModName -> Set Name -> QBinds -> Set Name -> PosRow -> KwdRow -> String\n    renderFunArgsWithClassesAndModule curMod gens cons classes posrow kwdrow =\n        let posArgs = renderPosRowWithClassesAndModule curMod gens cons classes posrow\n            kwdArgs = renderKwdRowWithClassesAndModule curMod gens cons classes kwdrow\n        in case (posArgs, kwdArgs) of\n            (\"\", \"\") -> \"\"\n            (p, \"\") -> \"(\" ++ p ++ \")\"\n            (\"\", k) -> \"(\" ++ k ++ \")\"\n            (p, k) -> \"(\" ++ p ++ \", \" ++ k ++ \")\"\n\n    renderTupleArgsWithClassesAndModule :: ModName -> Set Name -> QBinds -> Set Name -> PosRow -> KwdRow -> String\n    renderTupleArgsWithClassesAndModule curMod gens cons classes posrow kwdrow =\n        let posArgs = renderPosRowWithClassesAndModule curMod gens cons classes posrow\n            kwdArgs = renderKwdRowWithClassesAndModule curMod gens cons classes kwdrow\n        in case (posArgs, kwdArgs) of\n            (\"\", \"\") -> \"\"\n            (p, \"\") -> p\n            (\"\", k) -> k\n            (p, k) -> p ++ \", \" ++ k\n\n    renderPosRowWithClassesAndModule :: ModName -> Set Name -> QBinds -> Set Name -> PosRow -> String\n    renderPosRowWithClassesAndModule _ _ _ _ (TNil _ _) = \"\"\n    renderPosRowWithClassesAndModule curMod gens cons classes (TRow _ _ _ rtype rtail) =\n        renderTypeHtmlWithClassesAndModule curMod gens cons classes rtype ++\n        case rtail of\n            TNil _ _ -> \"\"\n            _ -> \", \" ++ renderPosRowWithClassesAndModule curMod gens cons classes rtail\n    renderPosRowWithClassesAndModule _ _ _ _ (TStar _ _ _) = \"*args\"\n    renderPosRowWithClassesAndModule curMod gens cons classes t = renderTypeHtmlWithClassesAndModule curMod gens cons classes t\n\n    renderKwdRowWithClassesAndModule :: ModName -> Set Name -> QBinds -> Set Name -> KwdRow -> String\n    renderKwdRowWithClassesAndModule _ _ _ _ (TNil _ _) = \"\"\n    renderKwdRowWithClassesAndModule curMod gens cons classes (TRow _ _ label rtype rtail) =\n        render (pretty label) ++ \"=\" ++ renderTypeHtmlWithClassesAndModule curMod gens cons classes rtype ++\n        case rtail of\n            TNil _ _ -> \"\"\n            _ -> \", \" ++ renderKwdRowWithClassesAndModule curMod gens cons classes rtail\n    renderKwdRowWithClassesAndModule _ _ _ _ (TStar _ _ _) = \"**kwargs\"\n    renderKwdRowWithClassesAndModule curMod gens cons classes t = renderTypeHtmlWithClassesAndModule curMod gens cons classes t\n\n-- | Render type with generic type highlighting, constraints, class links and scope\nrenderTypeWithGenericsConstraintsClassesModuleAndScope :: ModName -> Set Name -> QBinds -> Set Name -> String -> Type -> String\nrenderTypeWithGenericsConstraintsClassesModuleAndScope currentModule generics constraints classNames scope t =\n    renderTypeHtmlWithClassesModuleAndScope currentModule generics constraints classNames scope t\n  where\n    renderTypeHtmlWithClassesModuleAndScope :: ModName -> Set Name -> QBinds -> Set Name -> String -> Type -> String\n    renderTypeHtmlWithClassesModuleAndScope curMod gens cons classes scope (TVar _ tv)\n        | Set.member (tvname tv) gens =\n            let nameStr = render (pretty (tvname tv))\n                -- Find constraints for this type variable\n                tvConstraints = [preds | QBind qtv preds <- cons, tvname qtv == tvname tv]\n                tooltip = case tvConstraints of\n                    [] -> \"Generic type \" ++ nameStr ++ \"\\n\\nThis is a placeholder for any type.\\nAll \" ++\n                          nameStr ++ \"s must be the same type.\"\n                    (preds:_) -> if null preds\n                        then \"Generic type \" ++ nameStr ++ \"\\n\\nThis is a placeholder for any type.\\nAll \" ++\n                             nameStr ++ \"s must be the same type.\"\n                        else \"Generic type \" ++ nameStr ++ \"\\n\\nThis is a placeholder for any type.\\nAll \" ++\n                             nameStr ++ \"s must be the same type.\\n\\n\" ++ nameStr ++ \" must support:\\n\" ++\n                             concatMap formatPredAsListItem preds\n                formatPredAsListItem p = \"  • \" ++ formatConstraintNameLocal p ++ \" protocol (\" ++ formatExampleForPredLocal p ++ \")\\n\"\n                formatConstraintNameLocal (TC qn _) = render . pretty . simplifyQName $ qn\n                formatExampleForPredLocal (TC (NoQ (Name _ \"Plus\")) _) = \"+ operator\"\n                formatExampleForPredLocal (TC (NoQ (Name _ \"Minus\")) _) = \"- operator\"\n                formatExampleForPredLocal (TC (NoQ (Name _ \"Times\")) _) = \"* operator\"\n                formatExampleForPredLocal (TC (NoQ (Name _ \"Divide\")) _) = \"/ operator\"\n                formatExampleForPredLocal (TC (NoQ (Name _ \"Eq\")) _) = \"== operator\"\n                formatExampleForPredLocal (TC (NoQ (Name _ \"Ord\")) _) = \"< > operators\"\n                formatExampleForPredLocal (TC (NoQ (Name _ \"Hash\")) _) = \"hash function\"\n                formatExampleForPredLocal _ = \"protocol methods\"\n            in \"<span class=\\\"generic-type\\\" data-generic=\\\"\" ++ nameStr ++\n               \"\\\" data-scope=\\\"\" ++ scope ++\n               \"\\\" data-tooltip=\\\"\" ++ tooltip ++ \"\\\">\" ++ nameStr ++ \"</span>\"\n        | otherwise =\n            let simplified = render (pretty (SimplifiedType (TVar NoLoc tv)))\n            in if simplified == render (pretty (tvname tv))\n               then simplified  -- Already simplified\n               else simplified\n    renderTypeHtmlWithClassesModuleAndScope curMod gens cons classes scope (TCon _ tc) =\n        renderTConHtmlSimplifiedWithClassesModuleAndScope curMod gens cons classes scope tc\n    renderTypeHtmlWithClassesModuleAndScope curMod gens cons classes scope (TFun _ _ posrow kwdrow restype) =\n        let args = renderFunArgsWithClassesModuleAndScope curMod gens cons classes scope posrow kwdrow\n        in if null args\n           then renderTypeHtmlWithClassesModuleAndScope curMod gens cons classes scope restype\n           else args ++ \" -> \" ++ renderTypeHtmlWithClassesModuleAndScope curMod gens cons classes scope restype\n    renderTypeHtmlWithClassesModuleAndScope curMod gens cons classes scope (TTuple _ posrow kwdrow) =\n        \"(\" ++ renderTupleArgsWithClassesModuleAndScope curMod gens cons classes scope posrow kwdrow ++ \")\"\n    renderTypeHtmlWithClassesModuleAndScope curMod gens cons classes scope (TOpt _ t) =\n        \"?\" ++ renderTypeHtmlWithClassesModuleAndScope curMod gens cons classes scope t\n    renderTypeHtmlWithClassesModuleAndScope _ _ _ _ _ (TNone _) = \"None\"\n    renderTypeHtmlWithClassesModuleAndScope _ _ _ _ _ (TWild _) = \"_\"\n    renderTypeHtmlWithClassesModuleAndScope _ _ _ _ _ (TNil _ _) = \"\"\n    renderTypeHtmlWithClassesModuleAndScope curMod gens cons classes scope (TRow _ _ label rtype rtail) =\n        render (pretty label) ++ \": \" ++ renderTypeHtmlWithClassesModuleAndScope curMod gens cons classes scope rtype ++\n        case rtail of\n            TNil _ _ -> \"\"\n            _ -> \", \" ++ renderTypeHtmlWithClassesModuleAndScope curMod gens cons classes scope rtail\n    renderTypeHtmlWithClassesModuleAndScope curMod gens cons classes scope (TStar _ _ rtail) =\n        \"*\" ++ renderTypeHtmlWithClassesModuleAndScope curMod gens cons classes scope rtail\n    renderTypeHtmlWithClassesModuleAndScope _ _ _ _ _ (TFX _ fx) = render (pretty fx)\n    renderTypeHtmlWithClassesModuleAndScope curMod gens _ classes scope t =\n        render (pretty (SimplifiedType t))  -- Fallback for any other type\n\n    renderTConHtmlSimplifiedWithClassesModuleAndScope :: ModName -> Set Name -> QBinds -> Set Name -> String -> TCon -> String\n    renderTConHtmlSimplifiedWithClassesModuleAndScope curMod gens cons classes scope (TC qn ts)\n        | qn == qnList && length ts == 1 = \"[\" ++ renderTypeHtmlWithClassesModuleAndScope curMod gens cons classes scope (head ts) ++ \"]\"\n        | qn == qnDict && length ts == 2 =\n            \"{\" ++ renderTypeHtmlWithClassesModuleAndScope curMod gens cons classes scope (head ts) ++ \": \" ++\n            renderTypeHtmlWithClassesModuleAndScope curMod gens cons classes scope (ts !! 1) ++ \"}\"\n        | qn == qnSetT && length ts == 1 = \"{\" ++ renderTypeHtmlWithClassesModuleAndScope curMod gens cons classes scope (head ts) ++ \"}\"\n        | otherwise =\n            let simpleName = simplifyQName qn\n                nameStr = render (pretty simpleName)\n                -- Generate link based on qualified name with relative paths\n                linkStr = case qn of\n                    NoQ n -> if Set.member n classes\n                            then \"<a href=\\\"#class-\" ++ nameStr ++ \"\\\" class=\\\"type-link\\\">\" ++ nameStr ++ \"</a>\"\n                            else nameStr\n                    QName m n ->\n                        -- This is a qualified name from another module\n                        let relativePath = computeRelativeModulePath curMod m\n                            url = relativePath ++ \"#class-\" ++ render (pretty n)\n                        in \"<a href=\\\"\" ++ url ++ \"\\\" class=\\\"type-link\\\">\" ++ nameStr ++ \"</a>\"\n                    GName m n ->\n                        -- Global name (e.g., from __builtin__)\n                        let modPathList = modPath m\n                        in if modPathList == [\"__builtin__\"]\n                           then nameStr  -- Don't link builtin types\n                           else\n                               let relativePath = computeRelativeModulePath curMod m\n                                   url = relativePath ++ \"#class-\" ++ render (pretty n)\n                               in \"<a href=\\\"\" ++ url ++ \"\\\" class=\\\"type-link\\\">\" ++ nameStr ++ \"</a>\"\n            in linkStr ++ if null ts then \"\" else \"[\" ++ intercalate \", \" (map (renderTypeHtmlWithClassesModuleAndScope curMod gens cons classes scope) ts) ++ \"]\"\n\n    renderFunArgsWithClassesModuleAndScope :: ModName -> Set Name -> QBinds -> Set Name -> String -> PosRow -> KwdRow -> String\n    renderFunArgsWithClassesModuleAndScope curMod gens cons classes scope posrow kwdrow =\n        let posArgs = renderPosRowWithClassesModuleAndScope curMod gens cons classes scope posrow\n            kwdArgs = renderKwdRowWithClassesModuleAndScope curMod gens cons classes scope kwdrow\n        in case (posArgs, kwdArgs) of\n            (\"\", \"\") -> \"\"\n            (p, \"\") -> \"(\" ++ p ++ \")\"\n            (\"\", k) -> \"(\" ++ k ++ \")\"\n            (p, k) -> \"(\" ++ p ++ \", \" ++ k ++ \")\"\n\n    renderTupleArgsWithClassesModuleAndScope :: ModName -> Set Name -> QBinds -> Set Name -> String -> PosRow -> KwdRow -> String\n    renderTupleArgsWithClassesModuleAndScope curMod gens cons classes scope posrow kwdrow =\n        let posArgs = renderPosRowWithClassesModuleAndScope curMod gens cons classes scope posrow\n            kwdArgs = renderKwdRowWithClassesModuleAndScope curMod gens cons classes scope kwdrow\n        in case (posArgs, kwdArgs) of\n            (\"\", \"\") -> \"\"\n            (p, \"\") -> p\n            (\"\", k) -> k\n            (p, k) -> p ++ \", \" ++ k\n\n    renderPosRowWithClassesModuleAndScope :: ModName -> Set Name -> QBinds -> Set Name -> String -> PosRow -> String\n    renderPosRowWithClassesModuleAndScope _ _ _ _ _ (TNil _ _) = \"\"\n    renderPosRowWithClassesModuleAndScope curMod gens cons classes scope (TRow _ _ _ rtype rtail) =\n        renderTypeHtmlWithClassesModuleAndScope curMod gens cons classes scope rtype ++\n        case rtail of\n            TNil _ _ -> \"\"\n            _ -> \", \" ++ renderPosRowWithClassesModuleAndScope curMod gens cons classes scope rtail\n    renderPosRowWithClassesModuleAndScope _ _ _ _ _ (TStar _ _ _) = \"*args\"\n    renderPosRowWithClassesModuleAndScope curMod gens cons classes scope t = renderTypeHtmlWithClassesModuleAndScope curMod gens cons classes scope t\n\n    renderKwdRowWithClassesModuleAndScope :: ModName -> Set Name -> QBinds -> Set Name -> String -> KwdRow -> String\n    renderKwdRowWithClassesModuleAndScope _ _ _ _ _ (TNil _ _) = \"\"\n    renderKwdRowWithClassesModuleAndScope curMod gens cons classes scope (TRow _ _ label rtype rtail) =\n        render (pretty label) ++ \"=\" ++ renderTypeHtmlWithClassesModuleAndScope curMod gens cons classes scope rtype ++\n        case rtail of\n            TNil _ _ -> \"\"\n            _ -> \", \" ++ renderKwdRowWithClassesModuleAndScope curMod gens cons classes scope rtail\n    renderKwdRowWithClassesModuleAndScope _ _ _ _ _ (TStar _ _ _) = \"**kwargs\"\n    renderKwdRowWithClassesModuleAndScope curMod gens cons classes scope t = renderTypeHtmlWithClassesModuleAndScope curMod gens cons classes scope t\n\n-- | Render type with generic type highlighting, constraints and class links\nrenderTypeWithGenericsConstraintsAndClasses :: Set Name -> QBinds -> Set Name -> Type -> String\nrenderTypeWithGenericsConstraintsAndClasses generics constraints classNames t = renderTypeHtmlWithClasses generics constraints classNames t\n  where\n    renderTypeHtmlWithClasses :: Set Name -> QBinds -> Set Name -> Type -> String\n    renderTypeHtmlWithClasses gens cons classes (TVar _ tv)\n        | Set.member (tvname tv) gens =\n            let nameStr = render (pretty (tvname tv))\n                -- Find constraints for this type variable\n                tvConstraints = [preds | QBind qtv preds <- cons, tvname qtv == tvname tv]\n                tooltip = case tvConstraints of\n                    [] -> \"Generic type \" ++ nameStr ++ \"\\n\\nThis is a placeholder for any type.\\nAll \" ++\n                          nameStr ++ \"s must be the same type.\"\n                    (preds:_) -> if null preds\n                        then \"Generic type \" ++ nameStr ++ \"\\n\\nThis is a placeholder for any type.\\nAll \" ++\n                             nameStr ++ \"s must be the same type.\"\n                        else \"Generic type \" ++ nameStr ++ \"\\n\\nThis is a placeholder for any type.\\nAll \" ++\n                             nameStr ++ \"s must be the same type.\\n\\n\" ++ nameStr ++ \" must support:\\n\" ++\n                             concatMap formatPredAsListItem preds\n                formatPredAsListItem p = \"  • \" ++ formatConstraintNameLocal p ++ \" protocol (\" ++ formatExampleForPredLocal p ++ \")\\n\"\n                formatConstraintNameLocal (TC qn _) = render . pretty . simplifyQName $ qn\n                formatExampleForPredLocal (TC (NoQ (Name _ \"Plus\")) _) = \"+ operator\"\n                formatExampleForPredLocal (TC (NoQ (Name _ \"Minus\")) _) = \"- operator\"\n                formatExampleForPredLocal (TC (NoQ (Name _ \"Times\")) _) = \"* operator\"\n                formatExampleForPredLocal (TC (NoQ (Name _ \"Divide\")) _) = \"/ operator\"\n                formatExampleForPredLocal (TC (NoQ (Name _ \"Eq\")) _) = \"== operator\"\n                formatExampleForPredLocal (TC (NoQ (Name _ \"Ord\")) _) = \"< > operators\"\n                formatExampleForPredLocal (TC (NoQ (Name _ \"Hash\")) _) = \"hash function\"\n                formatExampleForPredLocal _ = \"protocol methods\"\n            in \"<span class=\\\"generic-type\\\" data-generic=\\\"\" ++ nameStr ++\n               \"\\\" data-tooltip=\\\"\" ++ tooltip ++ \"\\\">\" ++ nameStr ++ \"</span>\"\n        | otherwise =\n            let simplified = render (pretty (SimplifiedType (TVar NoLoc tv)))\n            in if simplified == render (pretty (tvname tv))\n               then simplified  -- Already simplified\n               else simplified\n    renderTypeHtmlWithClasses gens cons classes (TCon _ tc) = renderTConHtmlSimplifiedWithClasses gens cons classes tc\n    renderTypeHtmlWithClasses gens cons classes (TFun _ _ posrow kwdrow restype) =\n        let args = renderFunArgsWithClasses gens cons classes posrow kwdrow\n        in if null args\n           then renderTypeHtmlWithClasses gens cons classes restype\n           else args ++ \" -> \" ++ renderTypeHtmlWithClasses gens cons classes restype\n    renderTypeHtmlWithClasses gens cons classes (TTuple _ posrow kwdrow) =\n        \"(\" ++ renderTupleArgsWithClasses gens cons classes posrow kwdrow ++ \")\"\n    renderTypeHtmlWithClasses gens cons classes (TOpt _ t) = \"?\" ++ renderTypeHtmlWithClasses gens cons classes t\n    renderTypeHtmlWithClasses gens _ _ (TNone _) = \"None\"\n    renderTypeHtmlWithClasses gens _ _ (TWild _) = \"_\"\n    renderTypeHtmlWithClasses gens _ _ (TNil _ _) = \"\"\n    renderTypeHtmlWithClasses gens cons classes (TRow _ _ label rtype rtail) =\n        render (pretty label) ++ \": \" ++ renderTypeHtmlWithClasses gens cons classes rtype ++\n        case rtail of\n            TNil _ _ -> \"\"\n            _ -> \", \" ++ renderTypeHtmlWithClasses gens cons classes rtail\n    renderTypeHtmlWithClasses gens cons classes (TStar _ _ rtail) = \"*\" ++ renderTypeHtmlWithClasses gens cons classes rtail\n    renderTypeHtmlWithClasses gens _ _ (TFX _ fx) = render (pretty fx)\n    renderTypeHtmlWithClasses gens _ classes t = render (pretty (SimplifiedType t))  -- Fallback for any other type\n\n    renderTConHtmlSimplifiedWithClasses :: Set Name -> QBinds -> Set Name -> TCon -> String\n    renderTConHtmlSimplifiedWithClasses gens cons classes (TC qn ts)\n        | qn == qnList && length ts == 1 = \"[\" ++ renderTypeHtmlWithClasses gens cons classes (head ts) ++ \"]\"\n        | qn == qnDict && length ts == 2 = \"{\" ++ renderTypeHtmlWithClasses gens cons classes (head ts) ++ \": \" ++ renderTypeHtmlWithClasses gens cons classes (ts !! 1) ++ \"}\"\n        | qn == qnSetT && length ts == 1 = \"{\" ++ renderTypeHtmlWithClasses gens cons classes (head ts) ++ \"}\"\n        | otherwise =\n            let simpleName = simplifyQName qn\n                nameStr = render (pretty simpleName)\n                -- Generate link based on qualified name\n                linkStr = case qn of\n                    NoQ n -> if Set.member n classes\n                            then \"<a href=\\\"#class-\" ++ nameStr ++ \"\\\" class=\\\"type-link\\\">\" ++ nameStr ++ \"</a>\"\n                            else nameStr\n                    QName m n ->\n                        -- This is a qualified name from another module\n                        let modPathList = modPath m\n                            modPathStr = intercalate \"/\" modPathList\n                            modFile = if null modPathStr\n                                     then \"index.html\"  -- Root module\n                                     else modPathStr ++ \".html\"\n                            url = modFile ++ \"#class-\" ++ render (pretty n)\n                        in \"<a href=\\\"\" ++ url ++ \"\\\" class=\\\"type-link\\\">\" ++ nameStr ++ \"</a>\"\n                    GName m n ->\n                        -- Global name (e.g., from __builtin__)\n                        let modPathList = modPath m\n                        in if modPathList == [\"__builtin__\"]\n                           then nameStr  -- Don't link builtin types\n                           else\n                               let modPathStr = intercalate \"/\" modPathList\n                                   modFile = if null modPathStr\n                                            then \"index.html\"\n                                            else modPathStr ++ \".html\"\n                                   url = modFile ++ \"#class-\" ++ render (pretty n)\n                               in \"<a href=\\\"\" ++ url ++ \"\\\" class=\\\"type-link\\\">\" ++ nameStr ++ \"</a>\"\n            in linkStr ++ if null ts then \"\" else \"[\" ++ intercalate \", \" (map (renderTypeHtmlWithClasses gens cons classes) ts) ++ \"]\"\n\n    renderFunArgsWithClasses :: Set Name -> QBinds -> Set Name -> PosRow -> KwdRow -> String\n    renderFunArgsWithClasses gens cons classes posrow kwdrow =\n        let posArgs = renderPosRowWithClasses gens cons classes posrow\n            kwdArgs = renderKwdRowWithClasses gens cons classes kwdrow\n        in case (posArgs, kwdArgs) of\n            (\"\", \"\") -> \"\"\n            (p, \"\") -> \"(\" ++ p ++ \")\"\n            (\"\", k) -> \"(\" ++ k ++ \")\"\n            (p, k) -> \"(\" ++ p ++ \", \" ++ k ++ \")\"\n\n    renderTupleArgsWithClasses :: Set Name -> QBinds -> Set Name -> PosRow -> KwdRow -> String\n    renderTupleArgsWithClasses gens cons classes posrow kwdrow =\n        let posArgs = renderPosRowWithClasses gens cons classes posrow\n            kwdArgs = renderKwdRowWithClasses gens cons classes kwdrow\n        in case (posArgs, kwdArgs) of\n            (\"\", \"\") -> \"\"\n            (p, \"\") -> p\n            (\"\", k) -> k\n            (p, k) -> p ++ \", \" ++ k\n\n    renderPosRowWithClasses :: Set Name -> QBinds -> Set Name -> PosRow -> String\n    renderPosRowWithClasses gens _ _ (TNil _ _) = \"\"\n    renderPosRowWithClasses gens cons classes (TRow _ _ _ rtype rtail) =\n        renderTypeHtmlWithClasses gens cons classes rtype ++\n        case rtail of\n            TNil _ _ -> \"\"\n            _ -> \", \" ++ renderPosRowWithClasses gens cons classes rtail\n    renderPosRowWithClasses gens _ _ (TStar _ _ _) = \"*args\"\n    renderPosRowWithClasses gens cons classes t = renderTypeHtmlWithClasses gens cons classes t\n\n    renderKwdRowWithClasses :: Set Name -> QBinds -> Set Name -> KwdRow -> String\n    renderKwdRowWithClasses gens _ _ (TNil _ _) = \"\"\n    renderKwdRowWithClasses gens cons classes (TRow _ _ label rtype rtail) =\n        render (pretty label) ++ \"=\" ++ renderTypeHtmlWithClasses gens cons classes rtype ++\n        case rtail of\n            TNil _ _ -> \"\"\n            _ -> \", \" ++ renderKwdRowWithClasses gens cons classes rtail\n    renderKwdRowWithClasses gens _ _ (TStar _ _ _) = \"**kwargs\"\n    renderKwdRowWithClasses gens cons classes t = renderTypeHtmlWithClasses gens cons classes t\n\n\n-- | Helper function to enrich parameter display with inferred types and constraints\nenrichParamsWithTypesHtml :: Set Name -> QBinds -> PosRow -> KwdRow -> PosPar -> KwdPar -> Doc\nenrichParamsWithTypesHtml generics constraints posRow kwdRow p k =\n    let posParams = enrichPosParamsHtml generics constraints posRow p\n        kwdParams = enrichKwdParamsHtml generics constraints kwdRow k\n        sep = if isEmpty posParams || isEmpty kwdParams then empty else text \", \"\n    in text \"(\" <> posParams <> sep <> kwdParams <> text \")\"\n\n-- | Helper function to enrich parameter display with inferred types, constraints and class links\nenrichParamsWithTypesHtmlAndClasses :: Set Name -> QBinds -> Set Name -> PosRow -> KwdRow -> PosPar -> KwdPar -> Doc\nenrichParamsWithTypesHtmlAndClasses generics constraints classNames posRow kwdRow p k =\n    let posParams = enrichPosParamsHtmlWithClasses generics constraints classNames posRow p\n        kwdParams = enrichKwdParamsHtmlWithClasses generics constraints classNames kwdRow k\n        sep = if isEmpty posParams || isEmpty kwdParams then empty else text \", \"\n    in text \"(\" <> posParams <> sep <> kwdParams <> text \")\"\n\nenrichPosParamsHtml :: Set Name -> QBinds -> PosRow -> PosPar -> Doc\nenrichPosParamsHtml _ _ _ PosNIL = empty\nenrichPosParamsHtml generics constraints posRow (PosPar n t e p) =\n    -- Skip witness parameters\n    if isWitnessParam n\n    then enrichPosParamsHtml generics constraints (advanceRow posRow) p\n    else\n        let inferredType = extractParamTypeFromRow (nstr n) posRow\n            paramType = case inferredType of\n                Just it -> Just it\n                Nothing -> t\n            param = text \"<span class=\\\"param-name\\\">\" <> pretty n <> text \"</span>\" <>\n                    formatTypeHtmlWithGenericsAndConstraints generics constraints paramType <> formatDefaultHtml e\n            nextParams = enrichPosParamsHtml generics constraints (advanceRow posRow) p\n        in if isEmpty nextParams\n           then param\n           else param <> text \", \" <> nextParams\nenrichPosParamsHtml generics constraints _ (PosSTAR n t) = text \"*<span class=\\\"param-name\\\">\" <> pretty n <> text \"</span>\" <> formatTypeHtmlWithGenericsAndConstraints generics constraints t\n\nenrichKwdParamsHtml :: Set Name -> QBinds -> KwdRow -> KwdPar -> Doc\nenrichKwdParamsHtml _ _ _ KwdNIL = empty\nenrichKwdParamsHtml generics constraints kwdRow (KwdPar n t e k) =\n    let inferredType = extractParamTypeFromRow (nstr n) kwdRow\n        paramType = case inferredType of\n            Just it -> Just it\n            Nothing -> t\n        param = text \"<span class=\\\"param-name\\\">\" <> pretty n <> text \"</span>\" <>\n                formatTypeHtmlWithGenericsAndConstraints generics constraints paramType <> formatDefaultHtml e\n    in case k of\n        KwdNIL -> param\n        _ -> param <> text \", \" <> enrichKwdParamsHtml generics constraints kwdRow k\nenrichKwdParamsHtml generics constraints _ (KwdSTAR n t) = text \"**<span class=\\\"param-name\\\">\" <> pretty n <> text \"</span>\" <> formatTypeHtmlWithGenericsAndConstraints generics constraints t\n\nenrichPosParamsHtmlWithClasses :: Set Name -> QBinds -> Set Name -> PosRow -> PosPar -> Doc\nenrichPosParamsHtmlWithClasses _ _ _ _ PosNIL = empty\nenrichPosParamsHtmlWithClasses generics constraints classNames posRow (PosPar n t e p) =\n    -- Skip witness parameters\n    if isWitnessParam n\n    then enrichPosParamsHtmlWithClasses generics constraints classNames (advanceRow posRow) p\n    else\n        let inferredType = extractParamTypeFromRow (nstr n) posRow\n            paramType = case inferredType of\n                Just it -> Just it\n                Nothing -> t\n            param = text \"<span class=\\\"param-name\\\">\" <> pretty n <> text \"</span>\" <>\n                    formatTypeHtmlWithGenericsConstraintsAndClasses generics constraints classNames paramType <> formatDefaultHtml e\n            nextParams = enrichPosParamsHtmlWithClasses generics constraints classNames (advanceRow posRow) p\n        in if isEmpty nextParams\n           then param\n           else param <> text \", \" <> nextParams\nenrichPosParamsHtmlWithClasses generics constraints classNames _ (PosSTAR n t) = text \"*<span class=\\\"param-name\\\">\" <> pretty n <> text \"</span>\" <> formatTypeHtmlWithGenericsConstraintsAndClasses generics constraints classNames t\n\nenrichKwdParamsHtmlWithClasses :: Set Name -> QBinds -> Set Name -> KwdRow -> KwdPar -> Doc\nenrichKwdParamsHtmlWithClasses _ _ _ _ KwdNIL = empty\nenrichKwdParamsHtmlWithClasses generics constraints classNames kwdRow (KwdPar n t e k) =\n    let inferredType = extractParamTypeFromRow (nstr n) kwdRow\n        paramType = case inferredType of\n            Just it -> Just it\n            Nothing -> t\n        param = text \"<span class=\\\"param-name\\\">\" <> pretty n <> text \"</span>\" <>\n                formatTypeHtmlWithGenericsConstraintsAndClasses generics constraints classNames paramType <> formatDefaultHtml e\n    in case k of\n        KwdNIL -> param\n        _ -> param <> text \", \" <> enrichKwdParamsHtmlWithClasses generics constraints classNames kwdRow k\nenrichKwdParamsHtmlWithClasses generics constraints classNames _ (KwdSTAR n t) = text \"**<span class=\\\"param-name\\\">\" <> pretty n <> text \"</span>\" <> formatTypeHtmlWithGenericsConstraintsAndClasses generics constraints classNames t\n\n-- Extract parameter type from row\nextractParamTypeFromRow :: String -> Type -> Maybe Type\nextractParamTypeFromRow _ (TNil _ _) = Nothing\nextractParamTypeFromRow name (TRow _ _ n t rest)\n    | nstr n == name = Just t\n    | otherwise = extractParamTypeFromRow name rest\nextractParamTypeFromRow _ _ = Nothing\n\n-- Advance to next position in row\nadvanceRow :: Type -> Type\nadvanceRow (TRow _ _ _ _ rest) = rest\nadvanceRow t = t\n\n-- Extract parameter type from keyword row\nextractParamTypeFromKwdRow :: String -> Type -> Maybe Type\nextractParamTypeFromKwdRow _ (TNil _ _) = Nothing\nextractParamTypeFromKwdRow name (TRow _ _ n t rest)\n    | nstr n == name = Just t\n    | otherwise = extractParamTypeFromKwdRow name rest\nextractParamTypeFromKwdRow _ _ = Nothing\n\n-- | Document a declaration in HTML format\ndocDeclHtml :: Decl -> Doc\ndocDeclHtml = docDeclHtmlWithTypes []\n\n-- | Document a declaration in HTML format with type information\ndocDeclHtmlWithTypes :: TEnv -> Decl -> Doc\ndocDeclHtmlWithTypes tenv = docDeclHtmlWithTypesAndClasses tenv Set.empty\n\n-- | Document a declaration in HTML format with type information and class links\n-- | Document a declaration in HTML with types and class info for cross-module linking\ndocDeclHtmlWithTypesAndClassInfo :: TEnv -> ModName -> Set ClassInfo -> Decl -> Doc\ndocDeclHtmlWithTypesAndClassInfo tenv currentModule classInfos decl =\n    let classNames = Set.map ciName $ Set.filter ciIsLocal classInfos\n    in docDeclHtmlWithTypesAndClassesAndModule tenv currentModule classNames decl\n\n-- | Document a declaration in HTML with module context for proper cross-module links\ndocDeclHtmlWithTypesAndClassesAndModule :: TEnv -> ModName -> Set Name -> Decl -> Doc\ndocDeclHtmlWithTypesAndClassesAndModule tenv currentModule classNames decl =\n    -- Update all type rendering to use the module-aware version\n    case decl of\n        Def _ n q p k a b d x ddoc -> docDefHtmlWithModule tenv currentModule classNames n q p k a b d ddoc\n        Actor _ n q p k b ddoc -> docActorHtmlWithModule tenv currentModule classNames n q p k b ddoc\n        Class _ n q a b ddoc ->\n            let wtcons = map (\\tc -> ([], tc)) a  -- PCon is just a type alias for TCon\n            in docClassHtmlWithModule tenv currentModule classNames n q wtcons b ddoc\n        Protocol _ n q a b ddoc ->\n            let wtcons = map (\\pc -> ([], pc)) a\n            in docProtocolHtmlWithModule tenv currentModule classNames n q wtcons b ddoc\n        Extension _ q c a b ddoc ->\n            let wtcons = map (\\pc -> ([], pc)) a\n            in docExtensionHtmlWithModule tenv currentModule classNames q c wtcons b ddoc\n  where\n    docDefHtmlWithModule tenv curMod classNames n q p k a b d ddoc =\n        let explicitGenerics = extractGenerics q\n            funcScope = \"def-\" ++ nstr n\n            -- Look up inferred type information\n            (inferredType, qConstraints) = case lookup n tenv of\n                Just (NDef schema _ _) -> (Just schema, getQBindsFromSchema schema)\n                Just (NSig schema _ _) -> (Just schema, getQBindsFromSchema schema)\n                _ -> (Nothing, [])\n\n            -- Create a mapping from ugly type vars to nice generic names\n            uglyTypeVarsFromQBinds = collectUglyTypeVars qConstraints\n            uglyTypeVarsFromType = case inferredType of\n                Just (TSchema _ _ t) -> collectUglyTypeVarsFromType t\n                _ -> []\n            allUglyTypeVars = nub (uglyTypeVarsFromQBinds ++ uglyTypeVarsFromType)\n            typeVarMapping = createTypeVarMapping allUglyTypeVars\n\n            -- Process the type information with cleanup\n            (paramsWithTypes, inferredRetType, constraints, allGenerics) = case inferredType of\n                Just (TSchema _ qConstraints (TFun _ _ posRow kwdRow retType)) ->\n                    let cleanPosRow = cleanupTypeVars typeVarMapping posRow\n                        cleanKwdRow = cleanupTypeVars typeVarMapping kwdRow\n                        cleanRetType = cleanupTypeVars typeVarMapping retType\n                        cleanConstraints = cleanupQBinds typeVarMapping qConstraints\n                        inferredGenerics = extractGenerics cleanConstraints\n                        mappedGenerics = if null q && not (null typeVarMapping)\n                                         then Set.fromList (map snd typeVarMapping)\n                                         else explicitGenerics\n                        combinedGenerics = Set.union mappedGenerics inferredGenerics\n                    in (enrichParamsWithTypesHtmlAndClassesModuleAndScope curMod combinedGenerics cleanConstraints classNames funcScope cleanPosRow cleanKwdRow p k, Just cleanRetType, cleanConstraints, combinedGenerics)\n                _ -> (docParamsHtmlWithGenericsAndClassesModuleAndScope curMod explicitGenerics classNames funcScope p k, a, [], explicitGenerics)\n\n            -- Use inferred return type if available, otherwise use annotation\n            actualRetType = case inferredRetType of\n                Just t -> docRetTypeHtmlWithGenericsConstraintsAndClassesModuleAndScope curMod allGenerics constraints classNames funcScope (Just t)\n                Nothing -> docRetTypeHtmlWithGenericsConstraintsAndClassesModuleAndScope curMod allGenerics constraints classNames funcScope a\n\n            -- Format constraints if present, or generics if no constraints\n            (constraintsDoc, genericsDoc) = if null constraints\n                then (empty, docGenericsHtmlWithHighlightAndScope allGenerics funcScope q)\n                else (docConstraintsHtmlWithScope allGenerics funcScope constraints <> text \" => \", empty)\n\n            header = text \"<h2 class=\\\"type-context\\\"><code>\" <> pretty n <> text \"</code>\" <>\n                     constraintsDoc <> genericsDoc <> paramsWithTypes <> actualRetType <> text \"</h2>\"\n            docstr = case ddoc of\n                Just ds -> text \"<div class=\\\"docstring\\\">\" <> text (nl2br $ htmlEscape ds) <> text \"</div>\"\n                Nothing -> empty\n        in header $+$ docstr\n\n    docActorHtmlWithModule tenv curMod classNames n q p k b ddoc =\n        let explicitGenerics = extractGenerics q\n            -- Look up inferred type information for actors\n            (paramsWithTypes, allGenerics, constraints) = case lookup n tenv of\n                Just (NAct qConstraints posRow kwdRow _ _) ->\n                    let inferredGenerics = extractGenerics qConstraints\n                        combinedGenerics = Set.union explicitGenerics inferredGenerics\n                    in (enrichParamsWithTypesHtmlAndClassesModule curMod combinedGenerics qConstraints classNames posRow kwdRow p k, combinedGenerics, qConstraints)\n                _ -> (docParamsHtmlWithGenericsAndClassesModule curMod explicitGenerics classNames p k, explicitGenerics, [])\n\n            -- Always use docConstraintsHtml for rich tooltips - it handles both constrained and unconstrained generics\n            genericsDoc = if null q && null constraints\n                         then empty  -- No generics at all\n                         else if null constraints\n                              then docConstraintsHtml allGenerics q\n                              else docConstraintsHtml allGenerics constraints\n            header = text \"<h2 class=\\\"type-context\\\"><span class=\\\"keyword\\\">actor</span> <code>\" <> pretty n <> text \"</code>\" <>\n                     genericsDoc <> paramsWithTypes <> text \"</h2>\"\n            docstr = case ddoc of\n                Just ds -> text \"<div class=\\\"docstring\\\">\" <> text (nl2br $ htmlEscape ds) <> text \"</div>\"\n                Nothing -> empty\n            -- Process actor body to extract public constants, internal attributes and methods\n            body = docActorBodyHtmlWithGenericsTypesAndClassesModule tenv curMod allGenerics classNames b\n        in text \"<div class=\\\"declaration-block\\\">\" $+$\n           header $+$ docstr $+$\n           (if isEmpty body then empty else blank $+$ body) $+$\n           text \"</div>\"\n\n    docClassHtmlWithModule tenv curMod classNames n q a b ddoc =\n        let generics = extractGenerics q\n            -- Always use docConstraintsHtml for rich tooltips - it handles both constrained and unconstrained generics\n            classScope = \"class-\" ++ nstr n\n            genericsDoc = if null q\n                         then empty  -- No generics at all\n                         else docConstraintsHtmlWithScope generics classScope q\n            header = text \"<h2 id=\\\"class-\" <> text (nstr n) <> text \"\\\" class=\\\"type-context\\\"><span class=\\\"keyword\\\">class</span> <code>\" <> pretty n <> text \"</code>\" <>\n                     genericsDoc <> docAncestorsHtmlWithGenericsAndClassesModule curMod generics classNames a <> text \"</h2>\"\n            docstr = case ddoc of\n                Just ds -> text \"<div class=\\\"docstring\\\">\" <> text (nl2br $ htmlEscape ds) <> text \"</div>\"\n                Nothing -> empty\n            methods = docClassBodyHtmlWithGenericsTypesAndClassesModule tenv curMod generics classNames b\n        in text \"<div class=\\\"declaration-block\\\">\" $+$\n           header $+$ docstr $+$\n           (if isEmpty methods then empty else blank $+$ methods) $+$\n           text \"</div>\"\n\n    docProtocolHtmlWithModule tenv curMod classNames n q a b ddoc =\n        let generics = extractGenerics q\n            -- Always use docConstraintsHtml for rich tooltips - it handles both constrained and unconstrained generics\n            protocolScope = \"protocol-\" ++ nstr n\n            genericsDoc = if null q\n                         then empty  -- No generics at all\n                         else docConstraintsHtmlWithScope generics protocolScope q\n            header = text \"<h2 class=\\\"type-context\\\"><span class=\\\"keyword\\\">protocol</span> <code>\" <> pretty n <> text \"</code>\" <>\n                     genericsDoc <> docAncestorsHtmlWithGenericsAndClassesModule curMod generics classNames a <> text \"</h2>\"\n            docstr = case ddoc of\n                Just ds -> text \"<div class=\\\"docstring\\\">\" <> text (nl2br $ htmlEscape ds) <> text \"</div>\"\n                Nothing -> empty\n            methods = docProtocolBodyHtmlWithGenericsTypesAndClassesModule tenv curMod generics classNames b\n        in text \"<div class=\\\"declaration-block\\\">\" $+$\n           header $+$ docstr $+$\n           (if isEmpty methods then empty else blank $+$ methods) $+$\n           text \"</div>\"\n\n    docExtensionHtmlWithModule tenv curMod classNames q c a b ddoc =\n        let generics = extractGenerics q\n            -- Always use docConstraintsHtml for rich tooltips - it handles both constrained and unconstrained generics\n            genericsDoc = if null q\n                         then empty  -- No generics at all\n                         else docConstraintsHtml generics q\n            header = text \"<h2 class=\\\"type-context\\\"><span class=\\\"keyword\\\">extension</span> <code>\" <> pretty c <> text \"</code>\" <>\n                     genericsDoc <> docAncestorsHtmlWithGenericsAndClassesModule curMod generics classNames a <> text \"</h2>\"\n            docstr = case ddoc of\n                Just ds -> text \"<div class=\\\"docstring\\\">\" <> text (nl2br $ htmlEscape ds) <> text \"</div>\"\n                Nothing -> empty\n            methods = docClassBodyHtmlWithGenericsTypesAndClassesModule tenv curMod generics classNames b\n        in text \"<div class=\\\"declaration-block\\\">\" $+$\n           header $+$ docstr $+$\n           (if isEmpty methods then empty else blank $+$ methods) $+$\n           text \"</div>\"\n\n    nl2br = intercalate \"<br>\" . lines\n\ndocDeclHtmlWithTypesAndClasses :: TEnv -> Set Name -> Decl -> Doc\ndocDeclHtmlWithTypesAndClasses tenv classNames (Def _ n q p k a b d x ddoc) =\n    let explicitGenerics = extractGenerics q\n        -- Look up inferred type information\n        (inferredType, qConstraints) = case lookup n tenv of\n            Just (NDef schema _ _) -> (Just schema, getQBindsFromSchema schema)\n            Just (NSig schema _ _) -> (Just schema, getQBindsFromSchema schema)\n            _ -> (Nothing, [])\n\n        -- Create a mapping from ugly type vars to nice generic names\n        uglyTypeVarsFromQBinds = collectUglyTypeVars qConstraints\n        uglyTypeVarsFromType = case inferredType of\n            Just (TSchema _ _ t) -> collectUglyTypeVarsFromType t\n            _ -> []\n        allUglyTypeVars = nub (uglyTypeVarsFromQBinds ++ uglyTypeVarsFromType)\n        typeVarMapping = createTypeVarMapping allUglyTypeVars\n\n        -- Process the type information with cleanup\n        (paramsWithTypes, inferredRetType, constraints, allGenerics) = case inferredType of\n            Just (TSchema _ qConstraints (TFun _ _ posRow kwdRow retType)) ->\n                let cleanPosRow = cleanupTypeVars typeVarMapping posRow\n                    cleanKwdRow = cleanupTypeVars typeVarMapping kwdRow\n                    cleanRetType = cleanupTypeVars typeVarMapping retType\n                    cleanConstraints = cleanupQBinds typeVarMapping qConstraints\n                    inferredGenerics = extractGenerics cleanConstraints\n                    mappedGenerics = if null q && not (null typeVarMapping)\n                                     then Set.fromList (map snd typeVarMapping)\n                                     else explicitGenerics\n                    combinedGenerics = Set.union mappedGenerics inferredGenerics\n                in (enrichParamsWithTypesHtmlAndClasses combinedGenerics cleanConstraints classNames cleanPosRow cleanKwdRow p k, Just cleanRetType, cleanConstraints, combinedGenerics)\n            _ -> (docParamsHtmlWithGenericsAndClasses explicitGenerics classNames p k, a, [], explicitGenerics)\n\n        -- Use inferred return type if available, otherwise use annotation\n        actualRetType = case inferredRetType of\n            Just t -> docRetTypeHtmlWithGenericsConstraintsAndClasses allGenerics constraints classNames (Just t)\n            Nothing -> docRetTypeHtmlWithGenericsConstraintsAndClasses allGenerics constraints classNames a\n\n        -- Format constraints if present, or generics if no constraints\n        (constraintsDoc, genericsDoc) = if null constraints\n            then (empty, docGenericsHtmlWithHighlight allGenerics q)\n            else (docConstraintsHtml allGenerics constraints <> text \" => \", empty)\n\n        header = text \"<h2 class=\\\"type-context\\\"><code>\" <> pretty n <> text \"</code>\" <>\n                 constraintsDoc <> genericsDoc <> paramsWithTypes <> actualRetType <> text \"</h2>\"\n        mdocstring = case lookup n tenv of\n            Just info -> extractNameDocstring info\n            _ -> Nothing\n        docstr = case mdocstring of\n            Just ds -> text \"<div class=\\\"docstring\\\">\" <> text (nl2br $ htmlEscape ds) <> text \"</div>\"\n            Nothing -> empty\n    in header $+$ docstr\n  where\n    nl2br = intercalate \"<br>\" . lines\n\ndocDeclHtmlWithTypesAndClasses tenv classNames (Actor _ n q p k b ddoc) =\n    let explicitGenerics = extractGenerics q\n        -- Look up inferred type information for actors\n        (paramsWithTypes, allGenerics, constraints) = case lookup n tenv of\n            Just (NAct qConstraints posRow kwdRow _ _) ->\n                let inferredGenerics = extractGenerics qConstraints\n                    combinedGenerics = Set.union explicitGenerics inferredGenerics\n                in (enrichParamsWithTypesHtmlAndClasses combinedGenerics qConstraints classNames posRow kwdRow p k, combinedGenerics, qConstraints)\n            _ -> (docParamsHtmlWithGenericsAndClasses explicitGenerics classNames p k, explicitGenerics, [])\n\n        header = text \"<h2 class=\\\"type-context\\\"><span class=\\\"keyword\\\">actor</span> <code>\" <> pretty n <> text \"</code>\" <>\n                 docGenericsHtmlWithHighlight allGenerics q <> paramsWithTypes <> text \"</h2>\"\n        mdocstring = case lookup n tenv of\n            Just info -> extractNameDocstring info\n            _ -> Nothing\n        docstr = case mdocstring of\n            Just ds -> text \"<div class=\\\"docstring\\\">\" <> text (nl2br $ htmlEscape ds) <> text \"</div>\"\n            Nothing -> empty\n        -- Process actor body to extract attributes and methods\n        body = docActorBodyHtmlWithGenericsTypesAndClasses tenv allGenerics classNames b\n    in header $+$ docstr $+$\n       (if isEmpty body then empty else blank $+$ body)\n  where\n    nl2br = intercalate \"<br>\" . lines\n\ndocDeclHtmlWithTypesAndClasses tenv classNames (Class _ n q a b ddoc) =\n    let generics = extractGenerics q\n        header = text \"<h2 id=\\\"class-\" <> text (nstr n) <> text \"\\\" class=\\\"type-context\\\"><span class=\\\"keyword\\\">class</span> <code>\" <> pretty n <> text \"</code>\" <>\n                 docGenericsHtmlWithHighlight generics q <> docAncestorsHtmlWithGenericsAndClasses generics classNames a <> text \"</h2>\"\n        mdocstring = case lookup n tenv of\n            Just info -> extractNameDocstring info\n            _ -> Nothing\n        docstr = case mdocstring of\n            Just ds -> text \"<div class=\\\"docstring\\\">\" <> text (nl2br $ htmlEscape ds) <> text \"</div>\"\n            Nothing -> empty\n        methods = docClassBodyHtmlWithGenericsTypesAndClasses tenv generics classNames b\n    in header $+$ docstr $+$\n       (if isEmpty methods then empty else blank $+$ methods)\n  where\n    nl2br = intercalate \"<br>\" . lines\n\ndocDeclHtmlWithTypesAndClasses tenv classNames (Protocol _ n q a b ddoc) =\n    let generics = extractGenerics q\n        protocolScope = \"protocol-\" ++ nstr n\n        header = text \"<h2 class=\\\"type-context\\\"><span class=\\\"keyword\\\">protocol</span> <code>\" <> pretty n <> text \"</code>\" <>\n                 docGenericsHtmlWithHighlightAndScope generics protocolScope q <> docAncestorsHtmlWithGenericsAndClasses generics classNames a <> text \"</h2>\"\n        mdocstring = case lookup n tenv of\n            Just info -> extractNameDocstring info\n            _ -> Nothing\n        docstr = case mdocstring of\n            Just ds -> text \"<div class=\\\"docstring\\\">\" <> text (nl2br $ htmlEscape ds) <> text \"</div>\"\n            Nothing -> empty\n        methods = docProtocolBodyHtmlWithGenericsTypesAndClasses tenv generics classNames b\n    in header $+$ docstr $+$\n       (if isEmpty methods then empty else blank $+$ methods)\n  where\n    nl2br = intercalate \"<br>\" . lines\n\ndocDeclHtmlWithTypesAndClasses tenv classNames (Extension _ q c a b ddoc) =\n    let generics = extractGenerics q\n        header = text \"<h2 class=\\\"type-context\\\"><span class=\\\"keyword\\\">extension</span> <code>\" <> pretty c <> text \"</code>\" <>\n                 docGenericsHtmlWithHighlight generics q <> docAncestorsHtmlWithGenericsAndClasses generics classNames a <> text \"</h2>\"\n        mdocstring = Nothing  -- Extensions don't have their own docstrings in TEnv\n        docstr = case mdocstring of\n            Just ds -> text \"<div class=\\\"docstring\\\">\" <> text (nl2br $ htmlEscape ds) <> text \"</div>\"\n            Nothing -> empty\n    in header $+$ docstr\n  where\n    nl2br = intercalate \"<br>\" . lines\n\n-- | Module-aware helper functions for type rendering in HTML\nenrichParamsWithTypesHtmlAndClassesModule :: ModName -> Set Name -> QBinds -> Set Name -> PosRow -> KwdRow -> PosPar -> KwdPar -> Doc\nenrichParamsWithTypesHtmlAndClassesModule curMod generics constraints classNames posRow kwdRow p k =\n    text \"(\" <> enrichPosParamsHtmlModule curMod generics constraints classNames posRow p <>\n    docKwdParSepHtml p k <>\n    enrichKwdParamsHtmlModule curMod generics constraints classNames kwdRow k <> text \")\"\n\n-- | Enrich parameters with types from type environment in HTML format with scope\nenrichParamsWithTypesHtmlAndClassesModuleAndScope :: ModName -> Set Name -> QBinds -> Set Name -> String -> PosRow -> KwdRow -> PosPar -> KwdPar -> Doc\nenrichParamsWithTypesHtmlAndClassesModuleAndScope curMod generics constraints classNames scope posRow kwdRow p k =\n    text \"(\" <> enrichPosParamsHtmlModuleAndScope curMod generics constraints classNames scope posRow p <>\n    docKwdParSepHtml p k <>\n    enrichKwdParamsHtmlModuleAndScope curMod generics constraints classNames scope kwdRow k <> text \")\"\n\nenrichPosParamsHtmlModule :: ModName -> Set Name -> QBinds -> Set Name -> PosRow -> PosPar -> Doc\nenrichPosParamsHtmlModule _ _ _ _ _ PosNIL = empty\nenrichPosParamsHtmlModule curMod generics constraints classNames posRow (PosPar n t e p) =\n    -- Skip witness parameters\n    if isWitnessParam n\n    then enrichPosParamsHtmlModule curMod generics constraints classNames (advanceRow posRow) p\n    else\n        let inferredType = extractParamTypeFromRow (nstr n) posRow\n            paramType = case inferredType of\n                Just it -> Just it\n                Nothing -> t\n            param = text \"<span class=\\\"param-name\\\">\" <> pretty n <> text \"</span>\" <>\n                    formatTypeHtmlModule curMod generics constraints classNames paramType <>\n                    formatDefaultHtml e\n            nextParams = enrichPosParamsHtmlModule curMod generics constraints classNames (advanceRow posRow) p\n        in if isEmpty nextParams\n           then param\n           else param <> text \", \" <> nextParams\n\nenrichKwdParamsHtmlModule :: ModName -> Set Name -> QBinds -> Set Name -> KwdRow -> KwdPar -> Doc\nenrichKwdParamsHtmlModule _ _ _ _ _ KwdNIL = empty\nenrichKwdParamsHtmlModule curMod generics constraints classNames kwdRow (KwdPar n t e k) =\n    let inferredType = extractParamTypeFromKwdRow (nstr n) kwdRow\n        paramType = case inferredType of\n            Just it -> Just it\n            Nothing -> t\n        param = text \"<span class=\\\"param-name\\\">\" <> pretty n <> text \"</span>\" <>\n                formatTypeHtmlModule curMod generics constraints classNames paramType <>\n                formatDefaultHtml e\n        nextParams = enrichKwdParamsHtmlModule curMod generics constraints classNames kwdRow k\n    in if isEmpty nextParams\n       then param\n       else param <> text \", \" <> nextParams\n\n-- | Enrich positional parameters with types from row and add scope\nenrichPosParamsHtmlModuleAndScope :: ModName -> Set Name -> QBinds -> Set Name -> String -> PosRow -> PosPar -> Doc\nenrichPosParamsHtmlModuleAndScope _ _ _ _ _ _ PosNIL = empty\nenrichPosParamsHtmlModuleAndScope curMod generics constraints classNames scope posRow (PosSTAR n t) =\n    let inferredType = extractParamTypeFromRow (nstr n) posRow\n        paramType = case inferredType of\n            Just it -> Just it\n            Nothing -> t\n    in text \"*<span class=\\\"param-name\\\">\" <> pretty n <> text \"</span>\" <>\n       formatTypeHtmlModuleAndScope curMod generics constraints classNames scope paramType\nenrichPosParamsHtmlModuleAndScope curMod generics constraints classNames scope posRow (PosPar n t e p) =\n    -- Skip witness parameters\n    if isWitnessParam n\n    then enrichPosParamsHtmlModuleAndScope curMod generics constraints classNames scope (advanceRow posRow) p\n    else\n        let inferredType = extractParamTypeFromRow (nstr n) posRow\n            paramType = case inferredType of\n                Just it -> Just it\n                Nothing -> t\n            param = text \"<span class=\\\"param-name\\\">\" <> pretty n <> text \"</span>\" <>\n                    formatTypeHtmlModuleAndScope curMod generics constraints classNames scope paramType <>\n                    formatDefaultHtml e\n            nextParams = enrichPosParamsHtmlModuleAndScope curMod generics constraints classNames scope (advanceRow posRow) p\n        in if isEmpty nextParams\n           then param\n           else param <> text \", \" <> nextParams\n\n-- | Enrich keyword parameters with types from row and add scope\nenrichKwdParamsHtmlModuleAndScope :: ModName -> Set Name -> QBinds -> Set Name -> String -> KwdRow -> KwdPar -> Doc\nenrichKwdParamsHtmlModuleAndScope _ _ _ _ _ _ KwdNIL = empty\nenrichKwdParamsHtmlModuleAndScope curMod generics constraints classNames scope kwdRow (KwdSTAR n t) =\n    let inferredType = extractParamTypeFromKwdRow (nstr n) kwdRow\n        paramType = case inferredType of\n            Just it -> Just it\n            Nothing -> t\n    in text \"**<span class=\\\"param-name\\\">\" <> pretty n <> text \"</span>\" <>\n       formatTypeHtmlModuleAndScope curMod generics constraints classNames scope paramType\nenrichKwdParamsHtmlModuleAndScope curMod generics constraints classNames scope kwdRow (KwdPar n t e k) =\n    let inferredType = extractParamTypeFromKwdRow (nstr n) kwdRow\n        paramType = case inferredType of\n            Just it -> Just it\n            Nothing -> t\n        param = text \"<span class=\\\"param-name\\\">\" <> pretty n <> text \"</span>\" <>\n                formatTypeHtmlModuleAndScope curMod generics constraints classNames scope paramType <>\n                formatDefaultHtml e\n        nextParams = enrichKwdParamsHtmlModuleAndScope curMod generics constraints classNames scope kwdRow k\n    in if isEmpty nextParams\n       then param\n       else param <> text \", \" <> nextParams\n\nformatTypeHtmlModule :: ModName -> Set Name -> QBinds -> Set Name -> Maybe Type -> Doc\nformatTypeHtmlModule _ _ _ _ Nothing = empty\nformatTypeHtmlModule curMod generics constraints classNames (Just t) =\n    text \": <span class=\\\"type\\\">\" <> text (renderTypeWithGenericsConstraintsAndClassesAndModule curMod generics constraints classNames t) <> text \"</span>\"\n\nformatTypeHtmlModuleAndScope :: ModName -> Set Name -> QBinds -> Set Name -> String -> Maybe Type -> Doc\nformatTypeHtmlModuleAndScope _ _ _ _ _ Nothing = empty\nformatTypeHtmlModuleAndScope curMod generics constraints classNames scope (Just t) =\n    text \": <span class=\\\"type\\\">\" <> text (renderTypeWithGenericsConstraintsClassesModuleAndScope curMod generics constraints classNames scope t) <> text \"</span>\"\n\ndocParamsHtmlWithGenericsAndClassesModule :: ModName -> Set Name -> Set Name -> PosPar -> KwdPar -> Doc\ndocParamsHtmlWithGenericsAndClassesModule _ _ _ PosNIL KwdNIL = text \"()\"\ndocParamsHtmlWithGenericsAndClassesModule curMod generics classNames p k =\n    text \"(\" <> docPosParamsHtmlWithGenericsAndClassesModule curMod generics classNames p <>\n    docKwdParSepHtml p k <>\n    docKwdParamsHtmlWithGenericsAndClassesModule curMod generics classNames k <> text \")\"\n\ndocPosParamsHtmlWithGenericsAndClassesModule :: ModName -> Set Name -> Set Name -> PosPar -> Doc\ndocPosParamsHtmlWithGenericsAndClassesModule _ _ _ PosNIL = empty\ndocPosParamsHtmlWithGenericsAndClassesModule curMod generics classNames (PosPar n t e p) =\n    -- Skip witness parameters\n    if isWitnessParam n\n    then docPosParamsHtmlWithGenericsAndClassesModule curMod generics classNames p\n    else\n        let param = text \"<span class=\\\"param-name\\\">\" <> pretty n <> text \"</span>\" <>\n                    formatTypeHtmlModule curMod generics [] classNames t <>\n                    formatDefaultHtml e\n            nextParams = docPosParamsHtmlWithGenericsAndClassesModule curMod generics classNames p\n        in if isEmpty nextParams\n           then param\n           else param <> text \", \" <> nextParams\ndocPosParamsHtmlWithGenericsAndClassesModule curMod generics classNames (PosSTAR n t) =\n    text \"*<span class=\\\"param-name\\\">\" <> pretty n <> text \"</span>\" <>\n    formatTypeHtmlModule curMod generics [] classNames t\n\ndocKwdParamsHtmlWithGenericsAndClassesModule :: ModName -> Set Name -> Set Name -> KwdPar -> Doc\ndocKwdParamsHtmlWithGenericsAndClassesModule _ _ _ KwdNIL = empty\ndocKwdParamsHtmlWithGenericsAndClassesModule curMod generics classNames (KwdPar n t e k) =\n    let param = text \"<span class=\\\"param-name\\\">\" <> pretty n <> text \"</span>\" <>\n                formatTypeHtmlModule curMod generics [] classNames t <>\n                formatDefaultHtml e\n        nextParams = docKwdParamsHtmlWithGenericsAndClassesModule curMod generics classNames k\n    in if isEmpty nextParams\n       then param\n       else param <> text \", \" <> nextParams\ndocKwdParamsHtmlWithGenericsAndClassesModule curMod generics classNames (KwdSTAR n t) =\n    text \"**<span class=\\\"param-name\\\">\" <> pretty n <> text \"</span>\" <>\n    formatTypeHtmlModule curMod generics [] classNames t\n\n-- | Document parameters with scope for generic type highlighting\ndocParamsHtmlWithGenericsAndClassesModuleAndScope :: ModName -> Set Name -> Set Name -> String -> PosPar -> KwdPar -> Doc\ndocParamsHtmlWithGenericsAndClassesModuleAndScope _ _ _ _ PosNIL KwdNIL = text \"()\"\ndocParamsHtmlWithGenericsAndClassesModuleAndScope curMod generics classNames scope p k =\n    text \"(\" <> docPosParamsHtmlWithGenericsAndClassesModuleAndScope curMod generics classNames scope p <>\n    docKwdParSepHtml p k <>\n    docKwdParamsHtmlWithGenericsAndClassesModuleAndScope curMod generics classNames scope k <> text \")\"\n\ndocPosParamsHtmlWithGenericsAndClassesModuleAndScope :: ModName -> Set Name -> Set Name -> String -> PosPar -> Doc\ndocPosParamsHtmlWithGenericsAndClassesModuleAndScope _ _ _ _ PosNIL = empty\ndocPosParamsHtmlWithGenericsAndClassesModuleAndScope curMod generics classNames scope (PosPar n t e p) =\n    -- Skip witness parameters\n    if isWitnessParam n\n    then docPosParamsHtmlWithGenericsAndClassesModuleAndScope curMod generics classNames scope p\n    else\n        let param = text \"<span class=\\\"param-name\\\">\" <> pretty n <> text \"</span>\" <>\n                    formatTypeHtmlModuleAndScope curMod generics [] classNames scope t <>\n                    formatDefaultHtml e\n            nextParams = docPosParamsHtmlWithGenericsAndClassesModuleAndScope curMod generics classNames scope p\n        in if isEmpty nextParams\n           then param\n           else param <> text \", \" <> nextParams\ndocPosParamsHtmlWithGenericsAndClassesModuleAndScope curMod generics classNames scope (PosSTAR n t) =\n    text \"*<span class=\\\"param-name\\\">\" <> pretty n <> text \"</span>\" <>\n    formatTypeHtmlModuleAndScope curMod generics [] classNames scope t\n\ndocKwdParamsHtmlWithGenericsAndClassesModuleAndScope :: ModName -> Set Name -> Set Name -> String -> KwdPar -> Doc\ndocKwdParamsHtmlWithGenericsAndClassesModuleAndScope _ _ _ _ KwdNIL = empty\ndocKwdParamsHtmlWithGenericsAndClassesModuleAndScope curMod generics classNames scope (KwdPar n t e k) =\n    let param = text \"<span class=\\\"param-name\\\">\" <> pretty n <> text \"</span>\" <>\n                formatTypeHtmlModuleAndScope curMod generics [] classNames scope t <>\n                formatDefaultHtml e\n        nextParams = docKwdParamsHtmlWithGenericsAndClassesModuleAndScope curMod generics classNames scope k\n    in if isEmpty nextParams\n       then param\n       else param <> text \", \" <> nextParams\ndocKwdParamsHtmlWithGenericsAndClassesModuleAndScope curMod generics classNames scope (KwdSTAR n t) =\n    text \"**<span class=\\\"param-name\\\">\" <> pretty n <> text \"</span>\" <>\n    formatTypeHtmlModuleAndScope curMod generics [] classNames scope t\n\ndocRetTypeHtmlWithGenericsConstraintsAndClassesModule :: ModName -> Set Name -> QBinds -> Set Name -> Maybe Type -> Doc\ndocRetTypeHtmlWithGenericsConstraintsAndClassesModule _ _ _ _ Nothing = empty\ndocRetTypeHtmlWithGenericsConstraintsAndClassesModule curMod generics constraints classNames (Just t) =\n    text \" → <span class=\\\"type\\\">\" <> text (renderTypeWithGenericsConstraintsAndClassesAndModule curMod generics constraints classNames t) <> text \"</span>\"\n\n-- | Document return type in HTML format with scope\ndocRetTypeHtmlWithGenericsConstraintsAndClassesModuleAndScope :: ModName -> Set Name -> QBinds -> Set Name -> String -> Maybe Type -> Doc\ndocRetTypeHtmlWithGenericsConstraintsAndClassesModuleAndScope _ _ _ _ _ Nothing = empty\ndocRetTypeHtmlWithGenericsConstraintsAndClassesModuleAndScope curMod generics constraints classNames scope (Just t) =\n    text \" → <span class=\\\"type\\\">\" <> text (renderTypeWithGenericsConstraintsClassesModuleAndScope curMod generics constraints classNames scope t) <> text \"</span>\"\n\ndocAncestorsHtmlWithGenericsAndClassesModule :: ModName -> Set Name -> Set Name -> [WTCon] -> Doc\ndocAncestorsHtmlWithGenericsAndClassesModule _ _ _ [] = empty\ndocAncestorsHtmlWithGenericsAndClassesModule curMod generics classNames (a:_) =\n    let (_, tc) = a\n    in text \"(<span class=\\\"type\\\">\" <> text (renderTypeWithGenericsConstraintsAndClassesAndModule curMod generics [] classNames (TCon NoLoc tc)) <> text \"</span>)\"\n\n-- | Extract class members (attributes and methods) from a class body\nextractClassMembers :: Suite -> ([(Name, Maybe Type)], [(Name, QBinds, PosPar, KwdPar, Maybe Type, Maybe String)])\nextractClassMembers stmts = foldr extractMember ([], []) stmts\n  where\n    extractMember (Assign _ [PVar _ n _] _) (attrs, methods) = ((n, Nothing) : attrs, methods)\n    extractMember (VarAssign _ [PVar _ n ann] _) (attrs, methods) = ((n, ann) : attrs, methods)\n    extractMember (Signature _ [n] (TSchema _ _ t) _) (attrs, methods) =\n        case t of\n            TFun {} -> (attrs, methods)  -- Function signatures are handled separately\n            _ -> ((n, Just t) : attrs, methods)\n    extractMember (Decl _ decls) (attrs, methods) =\n        foldr extractDeclMember (attrs, methods) decls\n    extractMember _ acc = acc\n\n    extractDeclMember (Def _ n q p k ret body _ _ ddoc) (attrs, methods) =\n        (attrs, (n, q, p, k, ret, ddoc) : methods)\n    extractDeclMember _ acc = acc\n\n-- | Extract actor members (public constants, internal attributes, and methods) from an actor body\nextractActorMembers :: Suite -> ([(Name, Maybe Type)], [(Name, Maybe Type)], [(Name, QBinds, PosPar, KwdPar, Maybe Type, Maybe String)])\nextractActorMembers stmts = foldr extractMember ([], [], []) stmts\n  where\n    extractMember (Assign _ [PVar _ n ann] _) (publics, internals, methods) = ((n, ann) : publics, internals, methods)\n    extractMember (VarAssign _ [PVar _ n ann] _) (publics, internals, methods) = (publics, (n, ann) : internals, methods)\n    extractMember (Signature _ [n] (TSchema _ _ t) _) (publics, internals, methods) =\n        case t of\n            TFun {} -> (publics, internals, methods)  -- Function signatures are handled separately\n            _ -> ((n, Just t) : publics, internals, methods)  -- Type signatures for public constants\n    extractMember (Decl _ decls) (publics, internals, methods) =\n        foldr extractDeclMember (publics, internals, methods) decls\n    extractMember _ acc = acc\n\n    extractDeclMember (Def _ n q p k ret body _ _ ddoc) (publics, internals, methods) =\n        (publics, internals, (n, q, p, k, ret, ddoc) : methods)\n    extractDeclMember _ acc = acc\n\n-- | Extract protocol methods from a protocol body\nextractProtocolMethods :: Suite -> [(Name, QBinds, PosPar, KwdPar, Maybe Type, Maybe String)]\nextractProtocolMethods stmts = foldr extractMethod [] stmts\n  where\n    extractMethod (Decl _ decls) methods = foldr extractDeclMethod methods decls\n    extractMethod (Signature _ names (TSchema _ q t) _) methods =\n        case t of\n            TFun _ _ posRow kwdRow retType ->\n                -- Convert signature to method format\n                let (p, k) = rowsToParams posRow kwdRow\n                in [(n, q, p, k, Just retType, Nothing) | n <- names] ++ methods\n            _ -> [(n, q, PosNIL, KwdNIL, Just t, Nothing) | n <- names] ++ methods  -- Non-function signatures\n    extractMethod _ methods = methods\n\n    extractDeclMethod (Def _ n q p k ret body _ _ ddoc) methods =\n        (n, q, p, k, ret, ddoc) : methods\n    extractDeclMethod _ methods = methods\n\n    -- Convert rows to parameters for protocol methods\n    rowsToParams :: PosRow -> KwdRow -> (PosPar, KwdPar)\n    rowsToParams posRow kwdRow = (PosNIL, KwdNIL)  -- Simplified for now\n\ndocClassBodyHtmlWithGenericsTypesAndClassesModule :: TEnv -> ModName -> Set Name -> Set Name -> Suite -> Doc\ndocClassBodyHtmlWithGenericsTypesAndClassesModule tenv curMod generics classNames body =\n    let (attrs, methods) = extractClassMembers body\n        attrDocs = if null attrs then empty else\n                   text \"<h3>Attributes</h3>\" $+$\n                   text \"<div class=\\\"attributes\\\">\" $+$\n                   vcat (map (docAttributeHtmlWithGenericsAndClassesModule curMod generics classNames) attrs) $+$\n                   text \"</div>\"\n        methodDocs = if null methods then empty else\n                     text \"<h3>Methods</h3>\" $+$\n                     text \"<div class=\\\"methods\\\">\" $+$\n                     vcat (map (docMethodHtmlWithGenericsTypesAndClassesModule tenv curMod generics classNames) methods) $+$\n                     text \"</div>\"\n    in attrDocs $+$ (if isEmpty attrDocs || isEmpty methodDocs then empty else blank) $+$ methodDocs\n\ndocProtocolBodyHtmlWithGenericsTypesAndClassesModule :: TEnv -> ModName -> Set Name -> Set Name -> Suite -> Doc\ndocProtocolBodyHtmlWithGenericsTypesAndClassesModule tenv curMod generics classNames body =\n    let methods = extractProtocolMethods body\n        methodDocs = if null methods then empty else\n                     text \"<h3>Required Methods</h3>\" $+$\n                     text \"<div class=\\\"methods\\\">\" $+$\n                     vcat (map (docMethodHtmlWithGenericsTypesAndClassesModule tenv curMod generics classNames) methods) $+$\n                     text \"</div>\"\n    in methodDocs\n\ndocAttributeHtmlWithGenericsAndClassesModule :: ModName -> Set Name -> Set Name -> (Name, Maybe Type) -> Doc\ndocAttributeHtmlWithGenericsAndClassesModule curMod generics classNames (n, t) =\n    text \"<div class=\\\"attribute-item\\\"><code>\" <> pretty n <> text \"</code>\" <>\n    formatTypeHtmlModule curMod generics [] classNames t <> text \"</div>\"\n\ndocActorBodyHtmlWithGenericsTypesAndClassesModule :: TEnv -> ModName -> Set Name -> Set Name -> Suite -> Doc\ndocActorBodyHtmlWithGenericsTypesAndClassesModule tenv curMod generics classNames body =\n    let (publics, internals, methods) = extractActorMembers body\n        -- Enrich public constants with type information from TEnv\n        enrichedPublics = map enrichAttribute publics\n          where\n            enrichAttribute (n, Nothing) =\n                case lookup n tenv of\n                    Just (NSig (TSchema _ _ t) _ _) -> (n, Just t)\n                    Just (NDef (TSchema _ _ t) _ _) -> (n, Just t)\n                    _ -> (n, Nothing)\n            enrichAttribute attr = attr\n        publicDocs = if null publics then empty else\n                     text \"<h3>Public Constants</h3>\" $+$\n                     text \"<div class=\\\"attributes\\\">\" $+$\n                     vcat (map (docAttributeHtmlWithGenericsAndClassesModule curMod generics classNames) enrichedPublics) $+$\n                     text \"</div>\"\n        internalDocs = if null internals then empty else\n                       text \"<h3>Internal Attributes</h3>\" $+$\n                       text \"<div class=\\\"attributes\\\">\" $+$\n                       vcat (map (docAttributeHtmlWithGenericsAndClassesModule curMod generics classNames) internals) $+$\n                       text \"</div>\"\n        methodDocs = if null methods then empty else\n                     text \"<h3>Methods</h3>\" $+$\n                     text \"<div class=\\\"methods\\\">\" $+$\n                     vcat (map (docMethodHtmlWithGenericsTypesAndClassesModule tenv curMod generics classNames) methods) $+$\n                     text \"</div>\"\n    in publicDocs $+$ internalDocs $+$ methodDocs\n\ndocMethodHtmlWithGenericsTypesAndClassesModule :: TEnv -> ModName -> Set Name -> Set Name -> (Name, QBinds, PosPar, KwdPar, Maybe Type, Maybe String) -> Doc\ndocMethodHtmlWithGenericsTypesAndClassesModule tenv curMod generics classNames (n, q, p, k, ret, docstr) =\n    let nl2br = intercalate \"<br>\" . lines\n        inferredParams = case lookup n tenv of\n            Just (NDef (TSchema _ _ (TFun _ _ posRow kwdRow retType)) _ _) ->\n                (enrichParamsWithTypesHtmlAndClassesModule curMod generics [] classNames posRow kwdRow p k, Just retType)\n            Just (NSig (TSchema _ _ (TFun _ _ posRow kwdRow retType)) _ _) ->\n                (enrichParamsWithTypesHtmlAndClassesModule curMod generics [] classNames posRow kwdRow p k, Just retType)\n            _ -> (docParamsHtmlWithGenericsAndClassesModule curMod generics classNames p k, ret)\n        (params, retType) = inferredParams\n        -- Extract method-specific generics\n        methodGenerics = extractGenerics q\n        allGenerics = Set.union generics methodGenerics\n        genericsDoc = if null q\n                     then empty\n                     else docConstraintsHtml methodGenerics q\n        methodSig = text \"<div class=\\\"method-item\\\">\" $+$\n                    text \"<div class=\\\"method-signature\\\"><code>\" <> pretty n <> text \"</code>\" <>\n                    genericsDoc <> params <> docRetTypeHtmlWithGenericsConstraintsAndClassesModule curMod allGenerics [] classNames retType <> text \"</div>\"\n        methodDoc = case docstr of\n            Just ds -> text \"<div class=\\\"method-doc\\\">\" <> text (nl2br $ htmlEscape ds) <> text \"</div>\"\n            Nothing -> empty\n    in methodSig $+$ methodDoc $+$ text \"</div>\"\n\n-- | Helper functions for HTML generation\ndocGenericsHtml :: QBinds -> Doc\ndocGenericsHtml [] = empty\ndocGenericsHtml q = text \"[\" <> commaList q <> text \"]\"\n\n-- | Render generics with highlighting for HTML\ndocGenericsHtmlWithHighlight :: Set Name -> QBinds -> Doc\ndocGenericsHtmlWithHighlight generics q = docGenericsHtmlWithHighlightAndScope generics \"\" q\n\n-- | Render generics with highlighting and scope for HTML\ndocGenericsHtmlWithHighlightAndScope :: Set Name -> String -> QBinds -> Doc\ndocGenericsHtmlWithHighlightAndScope _ _ [] = empty\ndocGenericsHtmlWithHighlightAndScope generics scope q =\n    let renderGeneric (QBind tv _) =\n            let name = tvname tv\n                nameStr = render (pretty name)\n            in if Set.member name generics\n               then text $ \"<span class=\\\"generic-type\\\" data-generic=\\\"\" ++ nameStr ++\n                          \"\\\" data-scope=\\\"\" ++ scope ++\n                          \"\\\" data-tooltip=\\\"Generic type \" ++ nameStr ++ \"\\n\\nThis is a placeholder for any type.\\nAll \" ++\n                          nameStr ++ \"s must be the same type.\\\">\" ++ nameStr ++ \"</span>\"\n               else text nameStr\n        genericsDoc = punctuate (text \", \") (map renderGeneric q)\n    in text \"[\" <> hcat genericsDoc <> text \"]\"\n\n-- | Document type constraints in HTML format\ndocConstraintsHtml :: Set Name -> QBinds -> Doc\ndocConstraintsHtml generics constraints = docConstraintsHtmlWithScope generics \"\" constraints\n\n-- | Document type constraints in HTML format with scope\ndocConstraintsHtmlWithScope :: Set Name -> String -> QBinds -> Doc\ndocConstraintsHtmlWithScope _ _ [] = empty\ndocConstraintsHtmlWithScope generics scope constraints =\n    let renderConstraint (QBind tv preds) =\n            let name = tvname tv\n                nameStr = render (pretty name)\n                tooltip = if null preds\n                    then \"Generic type \" ++ nameStr ++ \"\\n\\nThis is a placeholder for any type.\\nAll \" ++\n                         nameStr ++ \"s must be the same type.\"\n                    else \"Generic type \" ++ nameStr ++ \"\\n\\nThis is a placeholder for any type.\\nAll \" ++\n                         nameStr ++ \"s must be the same type.\\n\\n\" ++ nameStr ++ \" must support:\\n\" ++\n                         concatMap (\\p -> \"  • \" ++ formatConstraintName p ++ \" protocol (\" ++ formatExampleForPred p ++ \")\\n\") preds\n                nameDoc = if Set.member name generics\n                    then text $ \"<span class=\\\"generic-type\\\" data-generic=\\\"\" ++ nameStr ++\n                               \"\\\" data-scope=\\\"\" ++ scope ++\n                               \"\\\" data-tooltip=\\\"\" ++ tooltip ++ \"\\\">\" ++ nameStr ++ \"</span>\"\n                    else text nameStr\n                formatConstraintName (TC qn _) = render . pretty . simplifyQName $ qn\n\n                formatExampleForPred :: TCon -> String\n                formatExampleForPred (TC (NoQ (Name _ \"Plus\")) _) = \"+ operator\"\n                formatExampleForPred (TC (NoQ (Name _ \"Minus\")) _) = \"- operator\"\n                formatExampleForPred (TC (NoQ (Name _ \"Times\")) _) = \"* operator\"\n                formatExampleForPred (TC (NoQ (Name _ \"Divide\")) _) = \"/ operator\"\n                formatExampleForPred (TC (NoQ (Name _ \"Eq\")) _) = \"== operator\"\n                formatExampleForPred (TC (NoQ (Name _ \"Ord\")) _) = \"< > operators\"\n                formatExampleForPred (TC (NoQ (Name _ \"Hash\")) _) = \"hash function\"\n                formatExampleForPred _ = \"protocol methods\"\n\n                formatExampleOperators :: [TCon] -> String\n                formatExampleOperators preds = intercalate \", \" $ map getExample preds\n                  where\n                    getExample (TC (NoQ (Name _ \"Plus\")) _) = \"+ operator\"\n                    getExample (TC (NoQ (Name _ \"Minus\")) _) = \"- operator\"\n                    getExample (TC (NoQ (Name _ \"Times\")) _) = \"* operator\"\n                    getExample (TC (NoQ (Name _ \"Divide\")) _) = \"/ operator\"\n                    getExample (TC (NoQ (Name _ \"Eq\")) _) = \"== operator\"\n                    getExample (TC (NoQ (Name _ \"Ord\")) _) = \"< > operators\"\n                    getExample (TC (NoQ (Name _ \"Hash\")) _) = \"hash function\"\n                    getExample _ = \"protocol methods\"\n                -- Format predicates/constraints\n                predsDoc = if null preds\n                    then empty\n                    else text \"(\" <> hcat (punctuate (text \", \") (map formatConstraint preds)) <> text \")\"\n                formatConstraint (TC qn _) = text . render . pretty . simplifyQName $ qn\n            in nameDoc <> predsDoc\n        constraintsDoc = punctuate (text \", \") (map renderConstraint constraints)\n    in text \"[\" <> hcat constraintsDoc <> text \"]\"\n\n-- | Parameter rendering with generic type support\ndocParamsHtmlWithGenerics :: Set Name -> PosPar -> KwdPar -> Doc\ndocParamsHtmlWithGenerics generics p k =\n    text \"(\" <> docPosParHtmlWithGenerics generics p <> docKwdParSepHtml p k <> docKwdParHtmlWithGenerics generics k <> text \")\"\n\n-- | Parameter rendering with generic type support and class links\ndocParamsHtmlWithGenericsAndClasses :: Set Name -> Set Name -> PosPar -> KwdPar -> Doc\ndocParamsHtmlWithGenericsAndClasses generics classNames p k =\n    text \"(\" <> docPosParHtmlWithGenericsAndClasses generics classNames p <> docKwdParSepHtml p k <> docKwdParHtmlWithGenericsAndClasses generics classNames k <> text \")\"\n\ndocPosParHtmlWithGenerics :: Set Name -> PosPar -> Doc\ndocPosParHtmlWithGenerics _ PosNIL = empty\ndocPosParHtmlWithGenerics generics (PosPar n t e p) =\n    let param = text \"<span class=\\\"param-name\\\">\" <> pretty n <> text \"</span>\" <> formatTypeHtmlWithGenerics generics t <> formatDefaultHtml e\n    in case p of\n        PosNIL -> param\n        _ -> param <> text \", \" <> docPosParHtmlWithGenerics generics p\ndocPosParHtmlWithGenerics generics (PosSTAR n t) =\n    text \"*<span class=\\\"param-name\\\">\" <> pretty n <> text \"</span>\" <> formatTypeHtmlWithGenerics generics t\n\ndocKwdParHtmlWithGenerics :: Set Name -> KwdPar -> Doc\ndocKwdParHtmlWithGenerics _ KwdNIL = empty\ndocKwdParHtmlWithGenerics generics (KwdPar n t e k) =\n    let param = text \"<span class=\\\"param-name\\\">\" <> pretty n <> text \"</span>\" <> formatTypeHtmlWithGenerics generics t <> formatDefaultHtml e\n    in case k of\n        KwdNIL -> param\n        _ -> param <> text \", \" <> docKwdParHtmlWithGenerics generics k\ndocKwdParHtmlWithGenerics generics (KwdSTAR n t) =\n    text \"**<span class=\\\"param-name\\\">\" <> pretty n <> text \"</span>\" <> formatTypeHtmlWithGenerics generics t\n\ndocPosParHtmlWithGenericsAndClasses :: Set Name -> Set Name -> PosPar -> Doc\ndocPosParHtmlWithGenericsAndClasses _ _ PosNIL = empty\ndocPosParHtmlWithGenericsAndClasses generics classNames (PosPar n t e p) =\n    let param = text \"<span class=\\\"param-name\\\">\" <> pretty n <> text \"</span>\" <> formatTypeHtmlWithGenericsAndClasses generics classNames t <> formatDefaultHtml e\n    in case p of\n        PosNIL -> param\n        _ -> param <> text \", \" <> docPosParHtmlWithGenericsAndClasses generics classNames p\ndocPosParHtmlWithGenericsAndClasses generics classNames (PosSTAR n t) =\n    text \"*<span class=\\\"param-name\\\">\" <> pretty n <> text \"</span>\" <> formatTypeHtmlWithGenericsAndClasses generics classNames t\n\ndocKwdParHtmlWithGenericsAndClasses :: Set Name -> Set Name -> KwdPar -> Doc\ndocKwdParHtmlWithGenericsAndClasses _ _ KwdNIL = empty\ndocKwdParHtmlWithGenericsAndClasses generics classNames (KwdPar n t e k) =\n    let param = text \"<span class=\\\"param-name\\\">\" <> pretty n <> text \"</span>\" <> formatTypeHtmlWithGenericsAndClasses generics classNames t <> formatDefaultHtml e\n    in case k of\n        KwdNIL -> param\n        _ -> param <> text \", \" <> docKwdParHtmlWithGenericsAndClasses generics classNames k\ndocKwdParHtmlWithGenericsAndClasses generics classNames (KwdSTAR n t) =\n    text \"**<span class=\\\"param-name\\\">\" <> pretty n <> text \"</span>\" <> formatTypeHtmlWithGenericsAndClasses generics classNames t\n\nformatTypeHtmlWithGenerics :: Set Name -> Maybe Type -> Doc\nformatTypeHtmlWithGenerics generics t = formatTypeHtmlWithGenericsAndConstraints generics [] t\n\nformatTypeHtmlWithGenericsAndClasses :: Set Name -> Set Name -> Maybe Type -> Doc\nformatTypeHtmlWithGenericsAndClasses generics classNames t = formatTypeHtmlWithGenericsConstraintsAndClasses generics [] classNames t\n\nformatTypeHtmlWithGenericsAndConstraints :: Set Name -> QBinds -> Maybe Type -> Doc\nformatTypeHtmlWithGenericsAndConstraints _ _ Nothing = empty\nformatTypeHtmlWithGenericsAndConstraints generics constraints (Just t) =\n    text \": <span class=\\\"type\\\">\" <> text (renderTypeWithGenericsAndConstraints generics constraints t) <> text \"</span>\"\n\nformatTypeHtmlWithGenericsConstraintsAndClasses :: Set Name -> QBinds -> Set Name -> Maybe Type -> Doc\nformatTypeHtmlWithGenericsConstraintsAndClasses _ _ _ Nothing = empty\nformatTypeHtmlWithGenericsConstraintsAndClasses generics constraints classNames (Just t) =\n    text \": <span class=\\\"type\\\">\" <> text (renderTypeWithGenericsConstraintsAndClasses generics constraints classNames t) <> text \"</span>\"\n\ndocRetTypeHtmlWithGenerics :: Set Name -> Maybe Type -> Doc\ndocRetTypeHtmlWithGenerics generics t = docRetTypeHtmlWithGenericsAndConstraints generics [] t\n\ndocRetTypeHtmlWithGenericsAndConstraints :: Set Name -> QBinds -> Maybe Type -> Doc\ndocRetTypeHtmlWithGenericsAndConstraints _ _ Nothing = empty\ndocRetTypeHtmlWithGenericsAndConstraints generics constraints (Just t) =\n    text \" → <span class=\\\"type\\\">\" <> text (renderTypeWithGenericsAndConstraints generics constraints t) <> text \"</span>\"\n\ndocRetTypeHtmlWithGenericsConstraintsAndClasses :: Set Name -> QBinds -> Set Name -> Maybe Type -> Doc\ndocRetTypeHtmlWithGenericsConstraintsAndClasses _ _ _ Nothing = empty\ndocRetTypeHtmlWithGenericsConstraintsAndClasses generics constraints classNames (Just t) =\n    text \" → <span class=\\\"type\\\">\" <> text (renderTypeWithGenericsConstraintsAndClasses generics constraints classNames t) <> text \"</span>\"\n\ndocAncestorsHtmlWithGenerics :: Pretty a => Set Name -> [a] -> Doc\ndocAncestorsHtmlWithGenerics _ [] = empty\ndocAncestorsHtmlWithGenerics _ as = text \"(\" <> commaList as <> text \")\"\n\ndocAncestorsHtmlWithGenericsAndClasses :: Pretty a => Set Name -> Set Name -> [a] -> Doc\ndocAncestorsHtmlWithGenericsAndClasses _ _ [] = empty\ndocAncestorsHtmlWithGenericsAndClasses _ _ as = text \"(\" <> commaList as <> text \")\"\n\n-- | Original parameter rendering (without generics)\ndocParamsHtml :: PosPar -> KwdPar -> Doc\ndocParamsHtml p k = text \"(\" <> docPosParHtml p <> docKwdParSepHtml p k <> docKwdParHtml k <> text \")\"\n\ndocKwdParSepHtml :: PosPar -> KwdPar -> Doc\ndocKwdParSepHtml PosNIL KwdNIL = empty\ndocKwdParSepHtml PosNIL _ = empty\ndocKwdParSepHtml _ KwdNIL = empty\ndocKwdParSepHtml _ _ = text \", \"\n\ndocPosParHtml :: PosPar -> Doc\ndocPosParHtml PosNIL = empty\ndocPosParHtml (PosPar n t e p) =\n    let param = text \"<span class=\\\"param-name\\\">\" <> pretty n <> text \"</span>\" <> formatTypeHtml t <> formatDefaultHtml e\n    in case p of\n        PosNIL -> param\n        _ -> param <> text \", \" <> docPosParHtml p\ndocPosParHtml (PosSTAR n t) = text \"*<span class=\\\"param-name\\\">\" <> pretty n <> text \"</span>\" <> formatTypeHtml t\n\ndocKwdParHtml :: KwdPar -> Doc\ndocKwdParHtml KwdNIL = empty\ndocKwdParHtml (KwdPar n t e k) =\n    let param = text \"<span class=\\\"param-name\\\">\" <> pretty n <> text \"</span>\" <> formatTypeHtml t <> formatDefaultHtml e\n    in case k of\n        KwdNIL -> param\n        _ -> param <> text \", \" <> docKwdParHtml k\ndocKwdParHtml (KwdSTAR n t) = text \"**<span class=\\\"param-name\\\">\" <> pretty n <> text \"</span>\" <> formatTypeHtml t\n\nformatTypeHtml :: Maybe Type -> Doc\nformatTypeHtml Nothing = empty\nformatTypeHtml (Just t) = text \": <span class=\\\"type\\\">\" <> pretty (SimplifiedType t) <> text \"</span>\"\n\nformatDefaultHtml :: Maybe Expr -> Doc\nformatDefaultHtml Nothing = empty\nformatDefaultHtml (Just e) = text \" = <span class=\\\"default-value\\\">\" <> pretty e <> text \"</span>\"\n\ndocRetTypeHtml :: Maybe Type -> Doc\ndocRetTypeHtml Nothing = empty\ndocRetTypeHtml (Just t) = text \" → <span class=\\\"type\\\">\" <> pretty (SimplifiedType t) <> text \"</span>\"\n\ndocAncestorsHtml :: Pretty a => [a] -> Doc\ndocAncestorsHtml [] = empty\ndocAncestorsHtml as = text \"(\" <> commaList as <> text \")\"\n\n-- | Document class body in HTML with generic type support\ndocClassBodyHtmlWithGenerics :: Set Name -> Suite -> Doc\ndocClassBodyHtmlWithGenerics = docClassBodyHtmlWithGenericsAndTypes []\n\n-- | Document class body in HTML with generic type support and type environment\ndocClassBodyHtmlWithGenericsAndTypes :: TEnv -> Set Name -> Suite -> Doc\ndocClassBodyHtmlWithGenericsAndTypes tenv generics stmts = docClassBodyHtmlWithGenericsTypesAndClasses tenv generics Set.empty stmts\n\n-- | Document class body in HTML with generic type support, type environment and class links\ndocClassBodyHtmlWithGenericsTypesAndClasses :: TEnv -> Set Name -> Set Name -> Suite -> Doc\ndocClassBodyHtmlWithGenericsTypesAndClasses tenv generics classNames stmts =\n    let (attrs, methods) = partitionClassMembersHtmlWithGenericsTypesAndClasses tenv generics classNames stmts\n        attrsDoc = if null attrs\n                   then empty\n                   else text \"<div class=\\\"attributes\\\">\" $+$\n                        text \"<h3>Attributes:</h3>\" $+$\n                        text \"<ul>\" $+$\n                        vcat (map wrapLi attrs) $+$\n                        text \"</ul>\" $+$\n                        text \"</div>\"\n        methodsDoc = if null methods\n                     then empty\n                     else text \"<div class=\\\"methods\\\">\" $+$\n                          text \"<h3>Methods:</h3>\" $+$\n                          text \"<ul>\" $+$\n                          vcat methods $+$\n                          text \"</ul>\" $+$\n                          text \"</div>\"\n    in case (isEmpty attrsDoc, isEmpty methodsDoc) of\n        (True, True) -> empty\n        (False, True) -> attrsDoc\n        (True, False) -> methodsDoc\n        (False, False) -> attrsDoc $+$ methodsDoc\n  where\n    wrapLi doc = text \"<li>\" <> doc <> text \"</li>\"\n\n-- | Document actor body in HTML with generic type support, type environment and class links\ndocActorBodyHtmlWithGenericsTypesAndClasses :: TEnv -> Set Name -> Set Name -> Suite -> Doc\ndocActorBodyHtmlWithGenericsTypesAndClasses tenv generics classNames stmts =\n    let (publicConstants, internalAttrs, methods) = partitionActorMembersHtmlWithGenericsTypesAndClasses tenv generics classNames stmts\n        publicDoc = if null publicConstants\n                    then empty\n                    else text \"<h3>Public Constants</h3>\" $+$\n                         text \"<div class=\\\"attributes\\\">\" $+$\n                         vcat publicConstants $+$\n                         text \"</div>\"\n        internalDoc = if null internalAttrs\n                      then empty\n                      else text \"<h3>Internal Attributes</h3>\" $+$\n                           text \"<div class=\\\"attributes\\\">\" $+$\n                           vcat internalAttrs $+$\n                           text \"</div>\"\n        methodsDoc = if null methods\n                     then empty\n                     else text \"<h3>Methods</h3>\" $+$\n                          text \"<div class=\\\"methods\\\">\" $+$\n                          vcat (map renderMethod methods) $+$\n                          text \"</div>\"\n    in vcat $ filter (not . isEmpty) [publicDoc, internalDoc, methodsDoc]\n  where\n    renderMethod (n, q, p, k, ret, docstr) =\n        let nl2br = intercalate \"<br>\" . lines\n            methodGenerics = extractGenerics q\n            allGenerics = Set.union generics methodGenerics\n            inferredParams = case lookup n tenv of\n                Just (NDef (TSchema _ _ (TFun _ _ posRow kwdRow retType)) _ _) ->\n                    (enrichParamsWithTypesHtmlAndClasses allGenerics [] classNames posRow kwdRow p k, Just retType)\n                Just (NSig (TSchema _ _ (TFun _ _ posRow kwdRow retType)) _ _) ->\n                    (enrichParamsWithTypesHtmlAndClasses allGenerics [] classNames posRow kwdRow p k, Just retType)\n                _ -> (docParamsHtmlWithGenericsAndClasses allGenerics classNames p k, ret)\n            (params, retType) = inferredParams\n            genericsDoc = if null q\n                         then empty\n                         else docConstraintsHtml methodGenerics q\n            methodSig = text \"<div class=\\\"method-item\\\">\" $+$\n                        text \"<div class=\\\"method-signature\\\"><code>\" <> pretty n <> text \"</code>\" <>\n                        genericsDoc <> params <> docRetTypeHtmlWithGenericsConstraintsAndClasses allGenerics [] classNames retType <> text \"</div>\"\n            methodDoc = case docstr of\n                Just ds -> text \"<div class=\\\"method-doc\\\">\" <> text (nl2br $ htmlEscape ds) <> text \"</div>\"\n                Nothing -> empty\n        in methodSig $+$ methodDoc $+$ text \"</div>\"\n\n-- | Partition actor members into public constants, internal attributes, and methods\npartitionActorMembersHtmlWithGenericsTypesAndClasses :: TEnv -> Set Name -> Set Name -> Suite -> ([Doc], [Doc], [(Name, QBinds, PosPar, KwdPar, Maybe Type, Maybe String)])\npartitionActorMembersHtmlWithGenericsTypesAndClasses tenv generics classNames stmts = foldl partition ([], [], []) stmts\n  where\n    partition (publics, internals, methods) (Assign _ [PVar _ n ann] _) =\n        let enrichedType = case ann of\n                Just t -> Just t\n                Nothing -> case lookup n tenv of\n                    Just (NSig (TSchema _ _ t) _ _) -> Just t\n                    Just (NDef (TSchema _ _ t) _ _) -> Just t\n                    _ -> Nothing\n            doc = case enrichedType of\n                Just t -> text \"<div class=\\\"attribute-item\\\"><code>\" <> pretty n <> text \"</code>: <span class=\\\"type\\\">\" <>\n                          text (renderTypeWithGenericsConstraintsAndClasses generics [] classNames t) <> text \"</span></div>\"\n                Nothing -> text \"<div class=\\\"attribute-item\\\"><code>\" <> pretty n <> text \"</code></div>\"\n        in (publics ++ [doc], internals, methods)\n    partition (publics, internals, methods) (VarAssign _ [PVar _ n ann] _) =\n        let doc = case ann of\n                Just t -> text \"<div class=\\\"attribute-item\\\"><code>\" <> pretty n <> text \"</code>: <span class=\\\"type\\\">\" <>\n                          text (renderTypeWithGenericsConstraintsAndClasses generics [] classNames t) <> text \"</span></div>\"\n                Nothing -> text \"<div class=\\\"attribute-item\\\"><code>\" <> pretty n <> text \"</code></div>\"\n        in (publics, internals ++ [doc], methods)\n    partition (publics, internals, methods) (Signature _ [n] (TSchema _ _ t) _) =\n        case t of\n            TFun {} -> (publics, internals, methods)  -- Function signatures are handled separately\n            _ -> let doc = text \"<div class=\\\"attribute-item\\\"><code>\" <> pretty n <> text \"</code>: <span class=\\\"type\\\">\" <>\n                          text (renderTypeWithGenericsConstraintsAndClasses generics [] classNames t) <> text \"</span></div>\"\n                 in (publics ++ [doc], internals, methods)  -- Type signatures for public constants\n    partition (publics, internals, methods) (Decl _ decls) =\n        foldl extractDeclMember (publics, internals, methods) decls\n    partition acc _ = acc\n\n    extractDeclMember (publics, internals, methods) (Def _ n q p k ret body _ _ ddoc) =\n        (publics, internals, methods ++ [(n, q, p, k, ret, ddoc)])\n    extractDeclMember acc _ = acc\n\n-- | Document protocol body in HTML with generic type support\ndocProtocolBodyHtmlWithGenerics :: Set Name -> Suite -> Doc\ndocProtocolBodyHtmlWithGenerics = docProtocolBodyHtmlWithGenericsAndTypes []\n\n-- | Document protocol body in HTML with generic type support and type environment\ndocProtocolBodyHtmlWithGenericsAndTypes :: TEnv -> Set Name -> Suite -> Doc\ndocProtocolBodyHtmlWithGenericsAndTypes tenv generics stmts = docProtocolBodyHtmlWithGenericsTypesAndClasses tenv generics Set.empty stmts\n\n-- | Document protocol body in HTML with generic type support, type environment and class links\ndocProtocolBodyHtmlWithGenericsTypesAndClasses :: TEnv -> Set Name -> Set Name -> Suite -> Doc\ndocProtocolBodyHtmlWithGenericsTypesAndClasses tenv generics classNames stmts =\n    let methods = concatMap (extractMethodsHtmlWithGenericsTypesAndClasses tenv generics classNames) stmts\n    in if null methods\n       then empty\n       else text \"<div class=\\\"methods\\\">\" $+$\n            text \"<h3>Methods:</h3>\" $+$\n            text \"<ul>\" $+$\n            vcat methods $+$\n            text \"</ul>\" $+$\n            text \"</div>\"\n\n\n-- | Partition class members for HTML with generics\npartitionClassMembersHtmlWithGenerics :: Set Name -> Suite -> ([Doc], [Doc])\npartitionClassMembersHtmlWithGenerics = partitionClassMembersHtmlWithGenericsAndTypes []\n\n-- | Partition class members for HTML with generics and type environment\npartitionClassMembersHtmlWithGenericsAndTypes :: TEnv -> Set Name -> Suite -> ([Doc], [Doc])\npartitionClassMembersHtmlWithGenericsAndTypes tenv generics stmts = partitionClassMembersHtmlWithGenericsTypesAndClasses tenv generics Set.empty stmts\n\n-- | Partition class members for HTML with generics, type environment and class links\npartitionClassMembersHtmlWithGenericsTypesAndClasses :: TEnv -> Set Name -> Set Name -> Suite -> ([Doc], [Doc])\npartitionClassMembersHtmlWithGenericsTypesAndClasses tenv generics classNames stmts = foldl partition ([], []) stmts\n  where\n    partition (attrs, methods) (Signature _ vs sc d) = (attrs ++ [docAttributeHtmlWithGenericsAndClasses generics classNames vs sc], methods)\n    partition (attrs, methods) (VarAssign _ [PVar _ n ann] _) =\n        case ann of\n            Just t -> (attrs ++ [text \"<div class=\\\"attribute-item\\\"><code>\" <> pretty n <> text \"</code>: <span class=\\\"type\\\">\" <>\n                      text (renderTypeWithGenericsConstraintsAndClasses generics [] classNames t) <> text \"</span></div>\"], methods)\n            Nothing -> (attrs ++ [text \"<div class=\\\"attribute-item\\\"><code>\" <> pretty n <> text \"</code></div>\"], methods)\n    partition (attrs, methods) (Assign _ [PVar _ n ann] _) =\n        case ann of\n            Just t -> (attrs ++ [text \"<div class=\\\"attribute-item\\\"><code>\" <> pretty n <> text \"</code>: <span class=\\\"type\\\">\" <>\n                      text (renderTypeWithGenericsConstraintsAndClasses generics [] classNames t) <> text \"</span></div>\"], methods)\n            Nothing -> (attrs ++ [text \"<div class=\\\"attribute-item\\\"><code>\" <> pretty n <> text \"</code></div>\"], methods)\n    partition (attrs, methods) (Decl _ decls) = (attrs, methods ++ map (docMethodHtmlWithGenericsTypesAndClasses tenv generics classNames) decls)\n    partition acc _ = acc\n\n-- | Extract methods for HTML with generics\nextractMethodsHtmlWithGenerics :: Set Name -> Stmt -> [Doc]\nextractMethodsHtmlWithGenerics = extractMethodsHtmlWithGenericsAndTypes []\n\n-- | Extract methods for HTML with generics and type environment\nextractMethodsHtmlWithGenericsAndTypes :: TEnv -> Set Name -> Stmt -> [Doc]\nextractMethodsHtmlWithGenericsAndTypes tenv generics stmts = extractMethodsHtmlWithGenericsTypesAndClasses tenv generics Set.empty stmts\n\n-- | Extract methods for HTML with generics, type environment and class links\nextractMethodsHtmlWithGenericsTypesAndClasses :: TEnv -> Set Name -> Set Name -> Stmt -> [Doc]\nextractMethodsHtmlWithGenericsTypesAndClasses tenv generics classNames (Decl _ decls) = map (docMethodHtmlWithGenericsTypesAndClasses tenv generics classNames) decls\nextractMethodsHtmlWithGenericsTypesAndClasses tenv generics classNames (Signature _ vs sc d) = [docMethodSignatureHtmlWithGenericsAndClasses generics classNames vs sc]\nextractMethodsHtmlWithGenericsTypesAndClasses _ _ _ _ = []\n\n-- | Document an attribute in HTML with generics\ndocAttributeHtmlWithGenerics :: Set Name -> [Name] -> TSchema -> Doc\ndocAttributeHtmlWithGenerics generics vs ts = docAttributeHtmlWithGenericsAndClasses generics Set.empty vs ts\n\n-- | Document an attribute in HTML with generics and class links\ndocAttributeHtmlWithGenericsAndClasses :: Set Name -> Set Name -> [Name] -> TSchema -> Doc\ndocAttributeHtmlWithGenericsAndClasses generics classNames vs (TSchema _ _ t) =\n    text \"<code>\" <> commaList vs <> text \"</code>: <span class=\\\"type\\\">\" <> text (renderTypeWithGenericsConstraintsAndClasses generics [] classNames t) <> text \"</span>\"\n\n-- | Document a method in HTML with generics\ndocMethodHtmlWithGenerics :: Set Name -> Decl -> Doc\ndocMethodHtmlWithGenerics = docMethodHtmlWithGenericsAndTypes []\n\n-- | Document a method in HTML with generics and type environment\ndocMethodHtmlWithGenericsAndTypes :: TEnv -> Set Name -> Decl -> Doc\ndocMethodHtmlWithGenericsAndTypes tenv generics = docMethodHtmlWithGenericsTypesAndClasses tenv generics Set.empty\n\n-- | Document a method in HTML with generics, type environment and class links\ndocMethodHtmlWithGenericsTypesAndClasses :: TEnv -> Set Name -> Set Name -> Decl -> Doc\ndocMethodHtmlWithGenericsTypesAndClasses tenv generics classNames (Def _ n q p k a b _ _ ddoc) =\n    let methodGenerics = Set.union generics (extractGenerics q)\n        -- Look up inferred type information\n        (paramsWithTypes, inferredRetType, constraints) = case lookup n tenv of\n            Just (NDef (TSchema _ qConstraints (TFun _ _ posRow kwdRow retType)) _ _) ->\n                (enrichParamsWithTypesHtmlAndClasses methodGenerics qConstraints classNames posRow kwdRow p k, Just retType, qConstraints)\n            Just (NSig (TSchema _ qConstraints (TFun _ _ posRow kwdRow retType)) _ _) ->\n                (enrichParamsWithTypesHtmlAndClasses methodGenerics qConstraints classNames posRow kwdRow p k, Just retType, qConstraints)\n            _ -> (docParamsHtmlWithGenericsAndClasses methodGenerics classNames p k, a, [])\n\n        -- Use inferred return type if available, otherwise use annotation\n        actualRetType = case inferredRetType of\n            Just t -> docRetTypeHtmlWithGenericsConstraintsAndClasses methodGenerics constraints classNames (Just t)\n            Nothing -> docRetTypeHtmlWithGenericsConstraintsAndClasses methodGenerics constraints classNames a\n\n        signature = text \"<div class=\\\"method-signature type-context\\\"><code>\" <> pretty n <> text \"</code>\" <>\n                    docGenericsHtmlWithHighlight methodGenerics q <> paramsWithTypes <> actualRetType <> text \"</div>\"\n        docstr = case ddoc of\n            Just ds -> text \"<div class=\\\"method-doc\\\">\" <> text (nl2br $ htmlEscape ds) <> text \"</div>\"\n            Nothing -> empty\n    in text \"<li class=\\\"method-item\\\">\" <> signature <> docstr <> text \"</li>\"\n  where\n    nl2br = intercalate \"<br>\" . lines\ndocMethodHtmlWithGenericsTypesAndClasses _ _ _ _ = empty\n\n-- | Document a method signature in HTML with generics\ndocMethodSignatureHtmlWithGenerics :: Set Name -> [Name] -> TSchema -> Doc\ndocMethodSignatureHtmlWithGenerics generics vs ts = docMethodSignatureHtmlWithGenericsAndClasses generics Set.empty vs ts\n\n-- | Document a method signature in HTML with generics and class links\ndocMethodSignatureHtmlWithGenericsAndClasses :: Set Name -> Set Name -> [Name] -> TSchema -> Doc\ndocMethodSignatureHtmlWithGenericsAndClasses generics classNames vs (TSchema _ _ t) =\n    text \"<li class=\\\"type-context\\\"><code>\" <> commaList vs <> text \"</code>: <span class=\\\"type\\\">\" <>\n    text (renderTypeWithGenericsConstraintsAndClasses generics [] classNames t) <> text \"</span></li>\"\n\n-- | Convert ModName to string representation\nmodNameToString :: ModName -> String\nmodNameToString (ModName names) = intercalate \".\" (map nstr names)\n\n-- | Generate HTML documentation index for a list of modules\ngenerateDocIndex :: FilePath -> [(ModName, Maybe String)] -> IO ()\ngenerateDocIndex docDir tasks = do\n    let indexFile = docDir </> \"index.html\"\n        sortedTasks = sortBy (comparing (\\(mn,_) -> modNameToString mn)) tasks\n        moduleEntries = concatMap generateModuleEntry sortedTasks\n        indexHtml = unlines $\n            [ \"<!DOCTYPE html>\"\n            , \"<html lang=\\\"en\\\">\"\n            , \"<head>\"\n            , \"  <meta charset=\\\"UTF-8\\\">\"\n            , \"  <meta name=\\\"viewport\\\" content=\\\"width=device-width, initial-scale=1.0\\\">\"\n            , \"  <title>Acton Documentation Index</title>\"\n            , \"  <style>\"\n            , htmlStyles\n            , \"  </style>\"\n            , \"</head>\"\n            , \"<body>\"\n            , \"  <div class=\\\"container\\\">\"\n            , \"    <h1>Acton Project Documentation</h1>\"\n            , \"    <p>Documentation for all modules in this project.</p>\"\n            , \"    <ul class=\\\"module-list\\\">\"\n            ] ++ moduleEntries ++\n            [ \"    </ul>\"\n            , \"  </div>\"\n            , \"</body>\"\n            , \"</html>\"\n            ]\n    writeFileUtf8Atomic indexFile indexHtml\n  where\n    generateModuleEntry :: (ModName, Maybe String) -> [String]\n    generateModuleEntry (mn, mDoc) =\n        let modPaths = modPath mn  -- Use different name to avoid shadowing\n            modName = modNameToString mn\n            htmlFile = if null modPaths\n                       then \"unnamed.html\"\n                       else joinPath (init modPaths) </> last modPaths <.> \"html\"\n            docString = maybe \"\" (takeWhile (/= '\\n')) mDoc\n        in [ \"      <li class=\\\"module-item\\\">\"\n           , \"        <a href=\\\"\" ++ htmlFile ++ \"\\\" class=\\\"module-link\\\">\"\n           , \"          <span class=\\\"module-path\\\">\" ++ modName ++ \"</span>\"\n           , \"          <div class=\\\"module-doc\\\">\" ++ htmlEscape docString ++ \"</div>\"\n           , \"        </a>\"\n           , \"      </li>\"\n           ]\n"
  },
  {
    "path": "compiler/lib/src/Acton/Env.hs",
    "content": "-- Copyright (C) 2019-2021 Data Ductus AB\n--\n-- Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:\n--\n-- 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.\n--\n-- 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.\n--\n-- 3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission.\n--\n-- THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS \"AS IS\" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n--\n\n{-# LANGUAGE FlexibleInstances, FlexibleContexts, DeriveGeneric #-}\nmodule Acton.Env where\n\nimport qualified Control.Exception\nimport qualified Data.Binary\nimport GHC.Generics (Generic)\nimport Data.Typeable\nimport Data.Char\nimport System.FilePath.Posix (joinPath,takeDirectory)\nimport System.Directory (doesFileExist)\nimport System.Environment (getExecutablePath)\nimport Control.Monad\nimport Control.Monad.Except\nimport qualified Data.HashMap.Strict as M\nimport qualified Data.Set as S\n\nimport Acton.Syntax\nimport Acton.Builtin\nimport Acton.Prim\nimport Acton.Printer\nimport Acton.Names\nimport Acton.Subst\nimport Acton.NameInfo\nimport Utils\nimport Pretty\nimport InterfaceFiles\nimport Prelude hiding ((<>))\n\n\n\n\n\nmkEnv                       :: [FilePath] -> Env0 -> Module -> IO Env0\nmkEnv spath env m           = getImps spath env (imps m)\n\n-- Full environment -------------------------------------------------------------------------------\n\ndata EnvF x                 = EnvF {\n                                activeNames:: TEnv,\n                                closedNames:: TEnv,\n                                hnames     :: HTEnv,\n                                closedHNames:: HTEnv,\n                                imports    :: [ModName],\n                                improots   :: [Name],\n                                modules    :: TEnv,\n                                hmodules   :: HTEnv,\n                                thismod    :: Maybe ModName,\n                                context    :: [EnvCtx],\n                                qlevel     :: Int,\n                                envX       :: x\n                              } deriving (Show)\n\ntype Env0                   = EnvF ()\n\n-- activeNames may contain live unification variables; closedNames must not.\n-- hnames is the full active-over-closed lookup index, while closedHNames is\n-- the reusable closed-only part.\n\nsetX                        :: EnvF y -> x -> EnvF x\nsetX env x                  = EnvF { activeNames = activeNames env, closedNames = closedNames env,\n                                     hnames = hnames env, closedHNames = closedHNames env,\n                                     imports = imports env, improots = improots env,\n                                     modules = modules env, hmodules = hmodules env, thismod = thismod env,\n                                     context = context env, qlevel = qlevel env, envX = x }\n\nmodX                        :: EnvF x -> (x -> x) -> EnvF x\nmodX env f                  = env{ envX = f (envX env) }\n\n\ndata EnvCtx                 = CtxDef | CtxAct | CtxClass | CtxLoop deriving (Eq,Show)\n\nsetInAct env                = env{ context = CtxAct : context env  }\n\nsetInDef env                = env{ context = CtxDef : context env }\n\nsetInClass env              = env{ context = CtxClass : context env  }\n\nsetInLoop env               = env{ context = CtxLoop : context env  }\n\nonTop env                   = context env == []\n\ncontextIs env ctx           = case context env of c:_ -> c == ctx; _ -> False\n\ncontextHas env ctx          = ctx `elem` context env\n\ninAct env                   = contextHas env CtxAct\n\ninDef env                   = contextIs env CtxDef\n\ninClass env                 = contextIs env CtxClass\n\ninLoop env                  = contextIs env CtxLoop\n\n\nmapModules1                 :: ((Name,NameInfo) -> (Name,NameInfo)) -> Env0 -> Env0\nmapModules1 f env           = mapModules (\\_ _ ni -> [f ni]) env\n\nmapModules                  :: (Env0 -> ModName -> (Name,NameInfo) -> TEnv) -> Env0 -> Env0\nmapModules f env            = env1 { hmodules = convTEnv2HTEnv (modules env1) }\n  where env1                =  walk env0 [] mods\n        env0                = env{ modules = [prim] }\n        prim : mods         = modules env\n\n        walk env ns []      = env\n        walk env ns ((n,NModule ms te1 _):te)\n                            = walk env2 ns te\n          where env1        = env{ modules = app ns (modules env) [(n, NModule ms [] Nothing)] }\n                env2        = walk env1 (ns++[n]) te1\n        walk env ns (ni:te) = walk env1 ns te\n          where env1        = env{ modules = app ns (modules env) (f env (ModName ns) ni) }\n\n        app (n:ns) ((m,NModule ms te1 doc):te) te'\n          | n == m          = (m, NModule ms (app ns te1 te') doc) : te\n        app ns (ni:te) te'  = ni : app ns te te'\n        app ns [] te'       = te'\n\n\ninstance (Pretty x) => Pretty (EnvF x) where\n    pretty env                  = text \"--- modules:\"  $+$\n                                  vcat (map pretty (modules env)) $+$\n                                  text \"--- active names\" <+> pretty (thismod env) <+> parens (text (show (qlevel env))) <> colon $+$\n                                  vcat (map pretty (activeNames env)) $+$\n                                  text \"--- closed names\" <+> pretty (thismod env) <> colon $+$\n                                  vcat (map pretty (closedNames env)) $+$\n                                  text \"--- imports\" <+> pretty (thismod env) <> colon $+$\n                                  vcat (map pretty (imports env)) $+$\n                                  pretty (envX env) $+$\n                                  text \".\"\n\ncloseDepVarsQ vs q\n  | null vs'                        = nub vs\n  | otherwise                       = closeDepVarsQ (vs'++vs) q\n  where vs'                         = concat [ vfree us \\\\ vs | QBind v us <- q, v `elem` vs ]\n\n\n-- Unalias --------------------------------------------------------------------------------------\n\nclass Unalias a where\n    unalias                         :: EnvF x -> a -> a\n    unalias env                     = id\n\ninstance (Unalias a) => Unalias [a] where\n    unalias env                     = map (unalias env)\n\ninstance (Unalias a) => Unalias (Maybe a) where\n    unalias env                     = fmap (unalias env)\n\ninstance Unalias ModName where\n    unalias env m@(ModName ns)\n      | inBuiltin env               = m\n      | otherwise                   = case lookupName (head ns) env of\n                                        Just (HNMAlias m') -> m'\n                                        Nothing | m `elem` (mPrim:mBuiltin:imports env)  -> m\n                                        _ -> noModule m\ninstance Unalias QName where\n    unalias env n0@(QName m n)      = case findHMod m env of\n                                        Just te -> case M.lookup n te of\n                                                      Just (HNAlias qn) -> setLoc (loc n0) qn\n                                                      Just _ -> GName m' n\n                                                      _ -> noItem m n\n                                        Nothing -> error (\"#### unalias fails for \" ++ prstr (QName m n))\n      where m'                      = unalias env m\n    unalias env (NoQ n)\n      | inBuiltin env               = GName mBuiltin n\n      | otherwise                   = case lookupName n env of\n                                        Just (HNAlias qn) -> setLoc (loc n) qn\n                                        _ -> case thismod env of Just m -> GName m n; _ -> NoQ n\n    unalias env (GName m n)\n--      | inBuiltin env, m==mBuiltin  = NoQ n\n      | otherwise                   = GName m n\n\nsetLoc l (QName m n)                = QName (setModLoc l m) (setNameLoc l n)\nsetLoc l (GName m n)                = GName (setModLoc l m) (setNameLoc l n)\nsetLoc l (NoQ n)                    = NoQ (setNameLoc l n)\n\nsetNameLoc l (Name _ s)             = Name l s\nsetNameLoc _ n                      = n\n\nsetModLoc l (ModName ns)            = ModName (map (setNameLoc l) ns)\n\n\ninstance Unalias TSchema where\n    unalias env (TSchema l q t)     = TSchema l (unalias env q) (unalias env t)\n\ninstance Unalias TCon where\n    unalias env (TC qn ts)          = TC (unalias env qn) (unalias env ts)\n\ninstance Unalias QBind where\n    unalias env (QBind tv cs)       = QBind tv (unalias env cs)\n\ninstance Unalias Type where\n    unalias env (TCon l c)          = TCon l (unalias env c)\n    unalias env (TFun l e p r t)    = TFun l (unalias env e) (unalias env p) (unalias env r) (unalias env t)\n    unalias env (TTuple l p k)      = TTuple l (unalias env p) (unalias env k)\n    unalias env (TOpt l t)          = TOpt l (unalias env t)\n    unalias env (TRow l k n t r)    = TRow l k n (unalias env t) (unalias env r)\n    unalias env (TStar l k r)       = TStar l k (unalias env r)\n    unalias env t                   = t\n\ninstance Unalias NameInfo where\n    unalias env (NVar t)            = NVar (unalias env t)\n    unalias env (NSVar t)           = NSVar (unalias env t)\n    unalias env (NDef t d doc)      = NDef (unalias env t) d doc\n    unalias env (NSig t d doc)      = NSig (unalias env t) d doc\n    unalias env (NAct q p k te doc) = NAct (unalias env q) (unalias env p) (unalias env k) (unalias env te) doc\n    unalias env (NClass q us te doc)= NClass (unalias env q) (unalias env us) (unalias env te) doc\n    unalias env (NProto q us te doc)= NProto (unalias env q) (unalias env us) (unalias env te) doc\n    unalias env (NExt q c ps te opts doc)= NExt (unalias env q) (unalias env c) (unalias env ps) (unalias env te) opts doc\n    unalias env (NTVar k c ps)      = NTVar k (unalias env c) (unalias env ps)\n    unalias env (NAlias qn)         = NAlias (unalias env qn)\n    unalias env (NMAlias m)         = NMAlias (unalias env m)\n    unalias env (NModule ms te doc) = NModule (unalias env ms) (unalias env te) doc\n    unalias env NReserved           = NReserved\n\ninstance Unalias (Name,NameInfo) where\n    unalias env (n,i)               = (n, unalias env i)\n\ninstance Unalias WTCon where\n    unalias env (w,u)               = (unalias env w, unalias env u)\n\ninstance Unalias (Either QName QName) where\n    unalias env (Left n)            = Left $ unalias env n\n    unalias env (Right n)           = Right $ unalias env n\n\n\n-- Env construction and modification -------------------------------------------------------------------------------------------\n\n-- | Initialize the base environment; the builtin mode skips interface loading.\n-- first variant is special case for compiling __builtin__.act\npublicTEnv                 :: TEnv -> TEnv\npublicTEnv                 = filter (isPublicName . fst)\n\ninitEnv                    :: FilePath -> Bool -> IO Env0\ninitEnv path True          = return $ EnvF{ activeNames = [],\n                                            closedNames = [(nPrim,NMAlias mPrim)],\n                                            hnames = hnamesFrom [(nPrim,NMAlias mPrim)],\n                                            closedHNames = hnamesFrom [(nPrim,NMAlias mPrim)],\n                                            imports = [],\n                                            improots = [],\n                                            modules = [(nPrim,NModule [] primEnv Nothing)],\n                                            hmodules = M.empty,\n                                            thismod = Nothing,\n                                            context = [],\n                                            qlevel = 0,\n                                            envX = () }\ninitEnv path False         = do (_,nmod,_,_,_,_,_,_,_,_,_,_) <- InterfaceFiles.readFile (joinPath [path,\"__builtin__.ty\"])\n                                let NModule _ envBuiltin builtinDocstring = nmod\n                                    envBuiltinPublic = publicTEnv envBuiltin\n                                    initialNames = [(nPrim,NMAlias mPrim), (nBuiltin,NMAlias mBuiltin)]\n                                    env0 = EnvF{ activeNames = [],\n                                                 closedNames = initialNames,\n                                                 hnames = hnamesFrom initialNames,\n                                                 closedHNames = hnamesFrom initialNames,\n                                                 imports = [],\n                                                 improots = [],\n                                                 modules = [(nPrim,NModule [] primEnv Nothing), (nBuiltin,NModule [] envBuiltin builtinDocstring)],\n                                                 hmodules = M.empty,\n                                                 thismod = Nothing,\n                                                 context = [],\n                                                 qlevel = 0,\n                                                 envX = () }\n                                    env = importAll mBuiltin envBuiltinPublic env0\n                                return env\n\nwithModulesFrom             :: EnvF x -> EnvF x -> EnvF x\nenv `withModulesFrom` env'  = env{modules = modules env'}\n\nhnamesFrom                  :: TEnv -> HTEnv\nhnamesFrom te               = extendHNames te M.empty\n\nextendHNames                :: TEnv -> HTEnv -> HTEnv\nextendHNames te hte         = foldr add hte te\n  where add (n,i) hte       = M.insert n (convNameInfo2HNameInfo i) hte\n\nsetActiveNames              :: TEnv -> EnvF x -> EnvF x\nsetActiveNames te env       = env{ activeNames = te, hnames = extendHNames te (closedHNames env) }\n\naddActiveNames              :: TEnv -> EnvF x -> EnvF x\naddActiveNames te env       = env{ activeNames = te ++ activeNames env, hnames = extendHNames te (hnames env) }\n\naddClosedNames              :: TEnv -> EnvF x -> EnvF x\naddClosedNames te env       = env{ closedNames = te ++ closedNames env, hnames = extendHNames (activeNames env) hte, closedHNames = hte }\n  where hte                 = extendHNames te (closedHNames env)\n\nlookupName                  :: Name -> EnvF x -> Maybe HNameInfo\nlookupName n env            = M.lookup n (hnames env)\n\nreserve                     :: [Name] -> EnvF x -> EnvF x\nreserve xs env\n  | not $ null badSelf      = selfParamError (loc $ head badSelf)\n  | otherwise               = addActiveNames te env\n  where badSelf             = if inAct env then xs `intersect` [selfKW] else []\n        te                  = [ (x, NReserved) | x <- uniqueNames xs ]\n\nreserveClosed               :: [Name] -> EnvF x -> EnvF x\nreserveClosed xs env\n  | not $ null badSelf      = selfParamError (loc $ head badSelf)\n  | otherwise               = addClosedNames te env\n  where badSelf             = if inAct env then xs `intersect` [selfKW] else []\n        te                  = [ (x, NReserved) | x <- uniqueNames xs ]\n\nuniqueNames                 :: [Name] -> [Name]\nuniqueNames ns              = reverse $ snd $ foldl' add (M.empty, []) ns\n  where add (seen, out) n\n          | M.member n seen = (seen, out)\n          | otherwise       = (M.insert n () seen, n:out)\n\ndefine                      :: TEnv -> EnvF x -> EnvF x\ndefine te env\n  | not $ null badSelf      = selfParamError (loc $ head badSelf)\n  | otherwise               = addActiveNames te' env\n  where badSelf             = if inAct env then dom te `intersect` [selfKW] else []\n        te'                 = reverse te\n\ndefineClosed                :: TEnv -> EnvF x -> EnvF x\ndefineClosed te env\n  | not $ null badSelf      = selfParamError (loc $ head badSelf)\n  | otherwise               = addClosedNames te' env\n  where badSelf             = if inAct env then dom te `intersect` [selfKW] else []\n        te'                 = reverse te\n\n\naddImport                   :: ModName -> EnvF x -> EnvF x\naddImport m env\n  | m `elem` imports env    = env\n  | otherwise               = env{ imports = m : imports env }\n\naddImpRoot m env            = env{ improots = n : improots env }\n  where ModName (n:_)       = m\n\ngetImports env              = reverse (imports env)\n\ndefineTVars                 :: QBinds -> EnvF x -> EnvF x\ndefineTVars q env           = foldr f env (unalias env q)\n  where f (QBind tv us) env = addActiveNames [ni] (env{ qlevel = qlevel env + 1 })\n          where (c,ps)      = case us of u:us' | not $ isProto env (tcname u) -> (u,us'); _ -> (cValue,us)\n                ni          = (tvname tv, NTVar (tvkind tv) c ps)\n\nselfSubst n q               = vsubst [(tvSelf, tCon tc)]\n  where tc                  = TC n (map tVar $ qbound q)\n\nselfQuant n q               = QBind tvSelf [tc] : q\n  where tc                  = TC n (map tVar $ qbound q)\n\nsetMod                      :: ModName -> EnvF x -> EnvF x\nsetMod m env                = env{ thismod = Just m }\n\naddMod                      :: ModName -> [ModName] -> TEnv -> Maybe String -> EnvF x -> EnvF x\naddMod m ms newte mdoc env  = env{ modules = addM ns (modules env) }\n  where\n    ModName ns              = m\n    addM [] te              = newte ++ te\n    addM (n:ns) te          = update n ns te\n    update n ns ((x,i):te)\n      | n == x, NModule ms1 te1 doc <- i\n                            = (n, NModule ms1 (addM ns te1) doc) : te\n    update n ns (ni:te)     = ni : update n ns te\n    update n ns []          = (n, NModule ms (addM ns []) mdoc) : []\n\n\n-- General Env queries -----------------------------------------------------------------------------------------------------------\n\ninBuiltin                   :: EnvF x -> Bool\ninBuiltin env               = length (modules env) == 1     -- mPrim only\n\nstateScope                  :: EnvF x -> [Name]\nstateScope env              = scopes (activeNames env) ++ scopes (closedNames env)\n  where scopes te           = [ z | (z, NSVar _) <- te ]\n\nquantScope0                 :: EnvF x -> QBinds\nquantScope0 env             = [ QBind (TV k n) (if c==cValue then ps else (c:ps)) | (n, NTVar k c ps) <- activeNames env ]\n\nquantScope                  :: EnvF x -> QBinds\nquantScope env              = [ q | q@(QBind tv _) <- quantScope0 env, tv /= tvSelf ]\n\ntvarDescendants             :: EnvF x -> [TCon] -> [TVar]\ntvarDescendants env cs      = [ TV k n | (n, NTVar k c _) <- activeNames env, c `elem` cs ]\n\nselfScopeSubst              :: EnvF x -> Substitution\nselfScopeSubst env          = [ (TV k n, tCon c) | (n, NTVar k c ps) <- activeNames env, n == nSelf ]\n\n\n-- Name queries -------------------------------------------------------------------------------------------------------------------\n\nfindQName                   :: QName -> EnvF x -> NameInfo\nfindQName n env             = case tryQName n env of\n                                 Just i -> convHNameInfo2NameInfo i\n                                 Nothing -> nameNotFound (noq n)\n\ntryQName                    :: QName -> EnvF x -> Maybe HNameInfo\ntryQName (QName m n) env    = case findHMod m env of\n                                Just te -> case M.lookup n te of\n                                    Just (HNAlias qn) -> tryQName qn env\n                                    Just i -> Just i\n                                    _ -> noItem m n\n                                _ -> noModule m\ntryQName (NoQ n) env        = case lookupName n env of\n                                Just (HNAlias qn) -> tryQName qn env\n                                Just ni -> Just ni\n                                Nothing -> Nothing\ntryQName (GName m n) env\n  | Just m == thismod env   = tryQName (NoQ n) env\n  | inBuiltin env,\n    m==mBuiltin             = tryQName (NoQ n) env\n  | otherwise               = case lookupHMod m env of\n                                Just te -> case M.lookup n te of\n                                    Just i -> Just i\n                                    Nothing -> noItem m n -- error (\"## Failed lookup of \" ++ prstr n ++ \" in module \" ++ prstr m)\n                                Nothing -> noModule m -- error (\"## Failed lookup of module \" ++ prstr m)\n\nfindSigLoc n env            = findSL (activeNames env) (closedNames env)\n    where findSL ((n',t):ps) rest\n             | NSig{} <- t, n==n' = Just (loc n')\n             | otherwise          = findSL ps rest\n          findSL [] []            = Nothing\n          findSL [] rest          = findSL rest []\n\nfindDefLoc n env            = findSL (activeNames env) (closedNames env)\n    where findSL ((n',t):ps) rest\n             | NDef{} <- t, n==n' = Just (loc n')\n             | otherwise          = findSL ps rest\n          findSL [] []            = Nothing\n          findSL [] rest          = findSL rest []\n\nfindName n env              = findQName (NoQ n) env\n\nlookupVar n env             = case lookupName n env of\n                                Just (HNVar t) -> Just t\n                                _ -> Nothing\n\nfindHMod                    :: ModName -> EnvF x -> Maybe HTEnv  -- m is modname part of a QName, so we must check for aliasing\nfindHMod m env | inBuiltin env, m==mBuiltin\n                            = Just (hnames env)\nfindHMod m@(ModName ns) env = case lookupName (head ns) env of\n                                Just (HNMAlias (ModName m')) -> lookupHMod (ModName $ m'++tail ns) env\n                                Nothing | m `elem` (mPrim:mBuiltin:imports env) -> lookupHMod m env\n                                _ -> Nothing\n\nlookupHMod                      :: ModName -> EnvF x -> Maybe HTEnv -- m is modname part of a GName, so search directly for module\nlookupHMod m env                = case lookupHModule m env of Just (imps, te, doc) -> Just te; _ -> Nothing\n\n\nlookupHModule m env\n | inBuiltin env, m==mBuiltin   = Just ([], hnames env, Nothing)\nlookupHModule (ModName ns) env  = f ns (hmodules env)\n  where f (n:ns) te             = case M.lookup n te of\n                                    Just (HNModule imps te' doc) -> g ns imps te' doc\n                                    Just (HNMAlias (ModName m)) -> lookupHModule (ModName $ m++ns) env\n                                    _ -> Nothing\n        g ns imps te doc\n          | null ns             = Just (imps, te, doc)\n          | otherwise           = f ns te\n\nlookupMod                       :: ModName -> EnvF x -> Maybe TEnv\nlookupMod m env                 = case lookupModule m env of Just (imps, te, doc) -> Just te; _ -> Nothing\n\nlookupModule m env\n  | inBuiltin env, m==mBuiltin  = Just ([], activeNames env ++ closedNames env, Nothing)\nlookupModule (ModName ns) env   = f ns (modules env)\n  where f (n:ns) te             = case lookup n te of\n                                    Just (NModule imps te' doc) -> g ns imps te' doc\n                                    Just (NMAlias (ModName m)) -> lookupModule (ModName $ m++ns) env\n                                    _ -> Nothing\n        g ns imps te doc\n          | null ns             = Just (imps, te, doc)\n          | otherwise           = f ns te\n\n\nisMod                       :: EnvF x -> [Name] -> Bool\nisMod env ns@(n:_)          = maybe False (const True) (findHMod (ModName ns) env) && rooted\n  where rooted              = n `elem` improots env || isMAlias n env\n\nisMAlias                    :: Name -> EnvF x -> Bool\nisMAlias n env              = case lookupName n env of\n                                Just HNMAlias{} -> True\n                                _ -> False\n\nisAlias                     :: Name -> EnvF x -> Bool\nisAlias n env               = case lookupName n env of\n                                Just HNAlias{} -> True\n                                _ -> False\n\nkindOf env (TVar _ tv)      = tvkind tv\nkindOf env (TUni _ uv)      = uvkind uv\nkindOf env (TCon _ tc)      = tconKind (tcname tc) env\nkindOf env TFun{}           = KType\nkindOf env TTuple{}         = KType\nkindOf env TOpt{}           = KType\nkindOf env TNone{}          = KType\nkindOf env TWild{}          = KWild\nkindOf env r@TNil{}         = rkind r\nkindOf env r@TRow{}         = rkind r\nkindOf env r@TStar{}        = rkind r\nkindOf env TFX{}            = KFX\n\n\ntconKind                    :: QName -> EnvF x -> Kind\ntconKind n env              = case findQName n env of\n                                NAct q _ _ _ _ -> kind KType q\n                                NClass q _ _ _ -> kind KType q\n                                NProto q _ _ _ -> kind KProto q\n                                NReserved    -> nameReserved n\n                                _            -> notClassOrProto n\n  where kind k []           = k\n        kind k q            = KFun [ tvkind v | QBind v _ <- q ] k\n\nactorSelf env               = case lookupName selfKW env of\n                                Just (HNVar (TCon _ tc)) | isActor env (tcname tc) -> True\n                                _ -> False\n\nactorMethod env n0          = walk [] (activeNames env) (closedNames env)\n  where\n    walk ns ((n,NDef{}):te) rest\n                            = walk (n:ns) te rest\n    walk ns ((n,NVar (TCon _ tc)):te) rest\n      | n == selfKW         = isActor env (tcname tc) && n0 `elem` ns\n    walk ns (_ : te) rest   = walk ns te rest\n    walk ns [] []           = False\n    walk ns [] rest         = walk ns rest []\n\nisDef                       :: EnvF x -> QName -> Bool\nisDef env n                 = case tryQName n env of\n                                Just HNDef{} -> True\n                                _ -> False\n\nisActor                     :: EnvF x -> QName -> Bool\nisActor env n               = case tryQName n env of\n                                Just HNAct{} -> True\n                                _ -> False\n\nisClass                     :: EnvF x -> QName -> Bool\nisClass env n               = case tryQName n env of\n                                Just HNClass{} -> True\n                                _ -> False\n\nisProto                     :: EnvF x -> QName -> Bool\nisProto env n               = case tryQName n env of\n                                Just HNProto{} -> True\n                                _ -> False\n\nisDefOrClass                :: EnvF x -> QName -> Bool\nisDefOrClass env n          = case tryQName n env of\n                                Just HNDef{} -> True\n                                Just HNClass{} -> True\n                                _ -> False\n\n\n-- TCon queries ------------------------------------------------------------------------------------------------------------------\n\nfindAttr'                   :: EnvF x -> TCon -> Name -> (TSchema, Maybe Deco)\nfindAttr' env tc n          = case findAttr env tc n of\n                                  Just (_, sc, mbdec) -> (sc, mbdec)\n                                  Nothing -> error (\"#### findAttr' fails for \" ++ prstr tc ++ \" . \" ++ prstr n)\n\nsplitTC                     :: EnvF x -> TCon -> (Substitution, TCon)\nsplitTC env (TC n ts)       = (qbound q `zip` ts, TC n $ map tVar $ qbound q)\n  where (q,_,_)             = findConName n env\n\nfindAncestry                :: EnvF x -> TCon -> [WTCon]\nfindAncestry env tc         = ([],tc) : fst (findCon env tc)\n\nfindAncestor                :: EnvF x -> TCon -> QName -> Maybe (Expr->Expr,TCon)\nfindAncestor env p qn       = listToMaybe [ (wexpr ws, p') | (ws,p') <- findAncestry env p, tcname p' == qn ]\n\nhasAncestor'                :: EnvF x -> QName -> QName -> Bool\nhasAncestor' env qn qn'     = qn' `elem` [ tcname c' | (w,c') <- us ]\n  where (_,us,_)            = findConName qn env\n\nhasAncestor                 :: EnvF x -> TCon -> TCon -> Bool\nhasAncestor env c c'        = hasAncestor' env (tcname c) (tcname c')\n\ncommonAncestors             :: EnvF x -> TCon -> TCon -> [TCon]\ncommonAncestors env c1 c2   = filter ((`elem` ns) . tcname) $ map snd (findAncestry env c1)\n  where ns                  = map (tcname . snd) (findAncestry env c2)\n\ndirectAncestors             :: EnvF x -> QName -> [QName]\ndirectAncestors env qn      = [ tcname p | (ws,p) <- us, null $ catRight ws ]\n  where (q,us,_)            = findConName qn env\n\nallAncestors                :: EnvF x -> TCon -> [TCon]\nallAncestors env tc         = reverse [ schematic' c | (_, c) <- us ]\n  where (us,te)             = findCon env tc\n\nallDescendants              :: EnvF x -> TCon -> [TCon]\nallDescendants env tc       = [ schematic' c | c <- allCons env, hasAncestor' env (tcname c) (tcname tc) ]\n\nfindCon                     :: EnvF x -> TCon -> ([WTCon],TEnv)\nfindCon env (TC n ts)\n  | map tVar tvs == ts      = (us, te)\n  | otherwise               = (vsubst s us, vsubst s te)\n  where (q,us,te)           = findConName n env\n        tvs                 = qbound q\n        s                   = tvs `zip` ts\n\nfindConName n env           = case findQName n env of\n                                NAct q p k te _  -> (q,[],te)\n                                NClass q us te _ -> (q,us,te)\n                                NProto q us te _ -> (q,us,te)\n                                NExt q c us te _ _ -> (q,us,te)\n                                NReserved -> nameReserved n\n                                i -> err1 n (\"findConName: Class or protocol name expected, got \" ++ show i ++ \" --- \")\n\nconAttrs                    :: EnvF x -> QName -> [Name]\nconAttrs env qn             = dom te\n  where (_,_,te)            = findConName qn env\n\nattributes                  :: (WPath -> NameInfo -> Name -> Maybe a) -> EnvF x -> TCon -> [a]\nattributes f env tc         = catMaybes [ f wp i n | n <- ns, let Just (wp,i) = lookup n aenv ]\n  where ns                  = nub $ reverse $ dom aenv                                                                                  -- in offset order\n        aenv                = [ (n,(wp,i)) | (wp,c) <- findAncestry env tc, let (_,te) = findCon env c, (n,i) <- reverse te ]           -- in override order\n\nfullAttrEnv                 :: EnvF x -> TCon -> TEnv\nfullAttrEnv                 = attributes f\n  where f wp i n            = Just (n,i)\n\nparentTEnv                  :: EnvF x -> [WTCon] -> TEnv\nparentTEnv env us           = [ (n,i) | (_,c) <- us, let (_,te) = findCon env c, (n,i) <- reverse te ]                                  -- in override order\n\nfindAttr                    :: EnvF x -> TCon -> Name -> Maybe (Expr->Expr, TSchema, Maybe Deco)\nfindAttr env tc n           = listToMaybe $ attributes f env tc\n  where f wp i x | x /= n   = Nothing\n        f wp (NSig sc d _) x  = Just (wexpr wp, sc, Just d)\n        f wp (NDef sc d _) x  = Just (wexpr wp, sc, Just d)\n        f wp (NVar t)    x  = Just (wexpr wp, monotype t, Nothing)\n        f wp (NSVar t)   x  = Just (wexpr wp, monotype t, Nothing)\n\nattributes'                 :: (WPath -> NameInfo -> Name -> Maybe a) -> EnvF x -> QName -> [a]\nattributes' f env qn        = catMaybes [ f wp i n | n <- ns, let Just (wp,i) = lookup n aenv ]\n  where ns                  = nub $ reverse $ dom aenv                                                                                  -- in offset order\n        aenv                = [ (n,(wp,i)) | (wp,c) <- ([],tc) : us, let (_,_,te) = findConName (tcname c) env, (n,i) <- reverse te ]   -- in override order\n        (q,us,_)            = findConName qn env\n        tc                  = TC qn [ tVar v | QBind v _ <- q ]\n\ninheritedAttrs              :: EnvF x -> QName -> [(QName,Name)]\ninheritedAttrs              = attributes' f\n  where f _ NSig{} _        = Nothing\n        f wp _ n            = case reverse wp of Left w : _ -> Just (w,n); _ -> Nothing\n\nallAttrs'                   :: EnvF x -> TCon -> [Name]\nallAttrs' env tc            = allAttrs env (tcname tc)\n\nallAttrs                    :: EnvF x -> QName -> [Name]\nallAttrs                    = attributes' f\n  where f _ _ n             = Just n\n\ndirectAttrs                 :: EnvF x -> QName -> [Name]\ndirectAttrs                 = attributes' f\n  where f wp _ n            = if null (catRight wp) then Just n else Nothing\n\nabstractAttrs               :: EnvF x -> QName -> [Name]\nabstractAttrs env n         = attributes' f env n\n  where f _ (NSig _ dec _) n  = if dec == Property then Nothing else Just n\n        f _ _ _             = Nothing\n\nclosedAttr                  :: EnvF x -> TCon -> Name -> Bool\nclosedAttr env tc n         = n `elem` closedAttrs env (tcname tc)\n\nclosedAttrs                 :: EnvF x -> QName -> [Name]\nclosedAttrs                 = attributes' f\n  where\n    f _ i n | isClosed i    = Just n\n    f _ _ n                 = Nothing\n\nisClosed (NVar _)                   = True\nisClosed (NSVar _)                  = True\nisClosed (NSig _ Property _)          = True\nisClosed (NSig sc _ _)\n  | TFun{} <- sctype sc             = False\n  | otherwise                       = True      -- 'closed' ~ 'not a function'\nisClosed _                          = False\n\n\nabstractClass env n         = not $ null (abstractAttrs env n)\n\nabstractActor env n         = not $ null (abstractAttrs env n)\n\nabstractAttr                :: EnvF x -> TCon -> Name -> Bool\nabstractAttr env tc n       = n `elem` abstractAttrs env (tcname tc)\n\ntransitiveImports env       = mBuiltin : reverse (foldl trav [] (getImports env))\n  where trav seen m\n          | m `elem` seen   = seen\n          | otherwise       = m : foldl trav seen ms\n          where ms          = case lookupModule m env of Just (imps,_,_) -> imps\n\nallTypes                    :: (NameInfo -> Bool) -> EnvF x -> [TCon]\nallTypes select env         = concatMap impcons mods ++ localcons\n  where mods                = transitiveImports env\n        local te\n          | inBuiltin env   = [ TC (GName mBuiltin n) (wildargs i) | (n,i) <- te, select i ]\n          | otherwise       = [ TC (NoQ n) (wildargs i) | (n,i) <- te, select i ]\n        localcons\n                            = local (reverse (closedNames env)) ++ local (reverse (activeNames env))\n        impcons m           = [ TC (GName m n) (wildargs i) | (n,i) <- te, select i ]\n          where Just te     = lookupMod m env\n\nallCons                     :: EnvF x -> [TCon]\nallCons env                 = allTypes isCon env\n  where isCon NClass{}      = True\n        isCon NAct{}        = True\n        isCon _             = False\n\nallActors                   :: EnvF x -> [TCon]\nallActors env               = allTypes isActor env\n  where isActor NAct{}      = True\n        isActor _           = False\n\nallProtos env               = allTypes isProto env\n  where isProto NProto{}    = True\n        isProto _           = False\n\nallConAttr                  :: EnvF x -> Name -> [TCon]\nallConAttr env n            = [ tc | tc <- allCons env, n `elem` allAttrs' env tc ]\n\nallConAttrUFree             :: EnvF x -> Name -> [TUni]\nallConAttrUFree env n       = concat [ ufree $ fst $ findAttr' env tc n | tc <- activeConAttr env n ]\n\nactiveConAttr               :: EnvF x -> Name -> [TCon]\nactiveConAttr env n         = [ tc | (x,i) <- activeNames env, isCon i, let tc = TC (localQName x) (wildargs i), n `elem` allAttrs' env tc ]\n  where isCon NClass{}      = True\n        isCon NAct{}        = True\n        isCon _             = False\n        localQName x\n          | inBuiltin env   = GName mBuiltin x\n          | otherwise       = NoQ x\n\nallPConAttr                 :: EnvF x -> Name -> [PCon]\nallPConAttr env n           = [ p | p <- allProtos env, n `elem` allAttrs' env p ]\n\n\n-- TVar queries ------------------------------------------------------------------------------------------------------------------\n\nfindSelf                    :: EnvF x -> TCon\nfindSelf env                = case findName (tvname tvSelf) env of\n                                NTVar _ c ps -> c\n\nfindTVBound                 :: EnvF x -> TVar -> CCon\nfindTVBound env tv          = case findName (tvname tv) env of\n                                NTVar _ c ps -> c\n                                _ -> err1 tv \"Unknown type variable\"\n\nfindTVAttr                  :: EnvF x -> TVar -> Name -> Maybe (Expr->Expr, TSchema, Maybe Deco)\nfindTVAttr env tv n         = findAttr env c n\n  where c                   = findTVBound env tv\n\ntvarWit                     :: TVar -> PCon -> Name\ntvarWit tv p                = Internal Witness (nstr $ Derived (deriveQ $ tcname p) (tvname tv)) 0\n\n-- Method resolution order ------------------------------------------------------------------------------------------------------\n\nmro2                                    :: EnvF x -> [TCon] -> ([WTCon],[WTCon])\nmro2 env []                             = ([], [])\nmro2 env (u:us)\n  | isActor env (tcname u)              = err1 u \"Actor subclassing not allowed\"\n  | isProto env (tcname u)              = ([], mro env (u:us))\n  | otherwise                           = (mro env [u], mro env us)\n\nmro1 env us                             = mro env us\n\nmro                                     :: EnvF x -> [TCon] -> [WTCon]\nmro env us                              = merge [] $ map lin us' ++ [us']\n  where\n    us'                                 = case us of [] -> []; u:us -> ([Left (tcname u)],u) : [ ([Right (tcname u)],u) | u <- us ]\n\n    lin                                 :: WTCon -> [WTCon]\n    lin (w,u)                           = (w,u) : [ (w++w',u') | (w',u') <- us' ]\n      where (us',_)                     = findCon env u\n\n    merge                               :: [WTCon] -> [[WTCon]] -> [WTCon]\n    merge out lists\n      | null heads                      = reverse out\n      | h:_ <- good                     = merge (h:out) [ if equal hd h then tl else hd:tl | (hd,tl) <- zip heads tails ]\n      | otherwise                       = err2 (map snd heads) \"Inconsistent resolution order for\"\n      where (heads,tails)               = unzip [ (hd,tl) | hd:tl <- lists ]\n            good                        = [ h | h <- heads, all (absent h) tails]\n\n    equal                               :: WTCon -> WTCon -> Bool\n    equal (w1,u1) (w2,u2)\n      | tcname u1 == tcname u2          = tcargs u1 == tcargs u2 || err2 [u1,u2] \"Inconsistent protocol instantiations\"\n      | otherwise                       = False\n\n    absent                              :: WTCon -> [WTCon] -> Bool\n    absent (w,h) us                     = tcname h `notElem` map (tcname . snd) us\n\n\n----------------------------------------------------------------------------------------------------------------------\n-- castable predicate\n----------------------------------------------------------------------------------------------------------------------\n\ncastable                                    :: EnvF x -> Type -> Type -> Bool\ncastable env (TWild _) t2                   = True\ncastable env t1 (TWild _)                   = True\n\ncastable env (TCon _ c1) (TCon _ c2)\n  | tcname c1 == tcname c2,\n    tcname c1 `elem` covariant              = all (uncurry $ castable env) (tcargs c1 `zip` tcargs c2)\n  | Just (wf,c') <- search                  = tcargs c2 == tcargs c'\n  where search                              = findAncestor env c1 (tcname c2)\n\ncastable env (TFun _ fx1 p1 k1 t1) (TFun _ fx2 p2 k2 t2)\n                                            = castable env fx1 fx2 && castable env p2 p1 && castable env k2 k1 && castable env t1 t2\n\ncastable env (TTuple _ p1 k1) (TTuple _ p2 k2)\n                                            = castable env p1 p2 && castable env k1 k2\n\ncastable env (TOpt _ t1) (TOpt _ t2)        = castable env t1 t2\ncastable env (TNone _) (TOpt _ t)           = True\ncastable env (TNone _) (TNone _)            = True\n\ncastable env (TFX _ fx1) (TFX _ fx2)        = castable' fx1 fx2\n  where castable' FXPure   FXPure           = True\n        castable' FXPure   FXMut            = True\n        castable' FXPure   FXProc           = True\n        castable' FXMut    FXMut            = True\n        castable' FXMut    FXProc           = True\n        castable' FXProc   FXProc           = True\n        castable' FXAction FXAction         = True\n        castable' FXAction FXProc           = True\n        castable' fx1      fx2              = False\n\ncastable env (TNil _ k1) (TNil _ k2)\n  | k1 == k2                                = True\ncastable env (TRow _ k1 n1 t1 r1) (TRow _ k2 n2 t2 r2)\n  | k1 == k2 && n1 == n2                    = castable env t1 t2 && castable env r1 r2\ncastable env (TStar _ k1 r1) (TStar _ k2 r2)\n  | k1 == k2                                = castable env r1 r2\n\ncastable env (TVar _ tv1) (TVar _ tv2)\n  | tv1 == tv2                              = True\n\ncastable env t1@(TVar _ tv) t2              = castable env (tCon c) t2\n  where c                                   = findTVBound env tv\n\ncastable env t1 t2@(TVar _ tv)              = False\n\ncastable env t1 (TOpt _ t2)                 = castable env t1 t2\n\ncastable env t1 t2                          = False\n\n\nheadcast env t1 t2                          = castable env (schematic t1) (schematic t2)\n\n\n----------------------------------------------------------------------------------------------------------------------\n-- GLB\n----------------------------------------------------------------------------------------------------------------------\n\nglb env (TWild _) t2                    = pure tWild\nglb env t1 (TWild _)                    = pure tWild\n\nglb env t1@TVar{} t2@TVar{}\n  | t1 == t2                            = pure t1\nglb env (TUni _ u) _                    = pure tWild\nglb env _ (TUni _ u)                    = pure tWild\n\nglb env (TCon _ c1) (TCon _ c2)\n  | tcname c1 == tcname c2              = pure $ tCon c1\n  | hasAncestor env c1 c2               = pure $ tCon c1\n  | hasAncestor env c2 c1               = pure $ tCon c2\n\nglb env (TFun _ e1 p1 k1 t1) (TFun _ e2 p2 k2 t2)\n                                        = do e <- glb env e1 e2\n                                             (p, k) <- lub2 env p1 k1 p2 k2\n                                             t <- glb env t1 t2\n                                             return (tFun e p k t)\nglb env t1@(TTuple _ p1 k1) t2@(TTuple _ p2 k2)\n                                        = do --traceM (\"## GLB \" ++ prstr t1 ++ \" \\\\/ \" ++ prstr t2)\n                                             (p, k) <- glb2 env p1 k1 p2 k2\n                                             --traceM (\"## GLB \" ++ prstr t1 ++ \" \\\\/ \" ++ prstr t2 ++ \"  =  \" ++ prstr (tTuple p k))\n                                             return (tTuple p k)\n\nglb env (TOpt _ t1) (TOpt _ t2)         = tOpt <$> glb env t1 t2\nglb env (TNone _) t2                    = pure tNone\nglb env t1 (TNone _)                    = pure tNone\nglb env (TOpt _ t1) t2                  = glb env t1 t2\nglb env t1 (TOpt _ t2)                  = glb env t1 t2\n\nglb env t1@(TFX _ fx1) t2@(TFX _ fx2)\n  | Just fx <- glfx fx1 fx2             = pure $ tTFX fx\n  where glfx FXPure   FXPure            = Just FXPure\n        glfx FXPure   FXMut             = Just FXPure\n        glfx FXPure   FXProc            = Just FXPure\n        glfx FXPure   FXAction          = Nothing\n        glfx FXMut    FXPure            = Just FXPure\n        glfx FXMut    FXMut             = Just FXMut\n        glfx FXMut    FXProc            = Just FXMut\n        glfx FXMut    FXAction          = Nothing\n        glfx FXProc   FXPure            = Just FXPure\n        glfx FXProc   FXMut             = Just FXMut\n        glfx FXProc   FXProc            = Just FXProc\n        glfx FXProc   FXAction          = Just FXAction\n        glfx FXAction FXPure            = Nothing\n        glfx FXAction FXMut             = Nothing\n        glfx FXAction FXProc            = Just FXAction\n        glfx FXAction FXAction          = Just FXAction\n\nglb env (TNil _ k1) (TNil _ k2)\n  | k1 == k2                            = pure $ tNil k1\nglb env (TRow _ k1 n1 t1 r1) (TRow _ k2 n2 t2 r2)\n  | k1 == k2 && n1 == n2                = tRow k1 n1 <$> glb env t1 t2 <*> glb env r1 r2\nglb env (TStar _ k1 r1) (TStar _ k2 r2)\n  | k1 == k2                            = tStar k1 <$> glb env r1 r2\n\nglb env t1 t2                           = Nothing\n\n\nglb2 env (TRow _ _ _ t1 p1) k1 (TRow _ _ _ t2 p2) k2\n                                        = do t <- glb env t1 t2\n                                             (p,k) <- glb2 env p1 k1 p2 k2\n                                             return (posRow t p, k)\nglb2 env p1@TRow{} k1 p2@TNil{} (TRow _ _ _ t2 k2)\n                                        = glb2 env p1 k1 (posRow t2 p2) k2\nglb2 env p1@TNil{} (TRow _ _ _ t1 k1) p2@TRow{} k2\n                                        = glb2 env (posRow t1 p1) k1 p2 k2\nglb2 env p1 k1 p2 k2                    = do p <- glb env p1 p2\n                                             k <- glb env k1 k2\n                                             return (p, k)\n\n\nglbfold env ts                          = case filter (/= tWild) ts of\n                                            [] -> pure tWild\n                                            t:ts -> foldM (glb env) t ts\n\n\n----------------------------------------------------------------------------------------------------------------------\n-- LUB\n----------------------------------------------------------------------------------------------------------------------\n\nlub env (TWild _) t2                    = pure tWild\nlub env t1 (TWild _)                    = pure tWild\n\nlub env t1@TVar{} t2@TVar{}\n  | t1 == t2                            = pure t1\nlub env t (TVar _ v)                    = lub env t (tCon $ findTVBound env v)\nlub env (TVar _ v) t                    = lub env (tCon $ findTVBound env v) t\n\nlub env (TUni _ u) _                    = pure tWild\nlub env _ (TUni _ u)                    = pure tWild\n\nlub env (TCon _ c1) (TCon _ c2)\n  | tcname c1 == tcname c2              = pure $ tCon c1\n  | hasAncestor env c1 c2               = pure $ tCon c2\n  | hasAncestor env c2 c1               = pure $ tCon c1\n  | not $ null common                   = pure $ tCon $ head common\n  where common                          = commonAncestors env c1 c2\n\nlub env f1@(TFun _ e1 p1 k1 t1) f2@(TFun _ e2 p2 k2 t2)\n                                        = do e <- lub env e1 e2\n                                             (p,k) <- glb2 env p1 k1 p2 k2\n                                             t <- lub env t1 t2\n                                             --traceM (\"## LUB \" ++ prstr f1 ++ \" /\\\\ \" ++ prstr f2 ++ \"  =  \" ++ prstr (tFun e p k t))\n                                             return $ tFun e p k t\nlub env t1@(TTuple _ p1 k1) t2@(TTuple _ p2 k2)\n                                        = do (p,k) <- lub2 env p1 k1 p2 k2\n                                             --traceM (\"## LUB \" ++ prstr t1 ++ \" /\\\\ \" ++ prstr t2 ++ \"  =  \" ++ prstr (tTuple p k))\n                                             return $ tTuple p k\n\nlub env (TOpt _ t1) (TOpt _ t2)         = tOpt <$> lub env t1 t2\nlub env (TNone _) (TNone _)             = pure tNone\nlub env (TNone _) t2@TOpt{}             = pure t2\nlub env t1@TOpt{} (TNone _)             = pure t1\nlub env (TNone _) t2                    = pure $ tOpt t2\nlub env t1 (TNone _)                    = pure $ tOpt t1\nlub env (TOpt _ t1) t2                  = tOpt <$> lub env t1 t2\nlub env t1 (TOpt _ t2)                  = tOpt <$> lub env t1 t2\n\nlub env t1@(TFX _ fx1) t2@(TFX _ fx2)   = pure $ tTFX (lufx fx1 fx2)\n  where lufx FXPure   FXPure            = FXPure\n        lufx FXPure   FXMut             = FXMut\n        lufx FXPure   FXProc            = FXProc\n        lufx FXPure   FXAction          = FXProc\n        lufx FXMut    FXPure            = FXMut\n        lufx FXMut    FXMut             = FXMut\n        lufx FXMut    FXProc            = FXProc\n        lufx FXMut    FXAction          = FXProc\n        lufx FXProc   FXPure            = FXProc\n        lufx FXProc   FXMut             = FXProc\n        lufx FXProc   FXProc            = FXProc\n        lufx FXProc   FXAction          = FXProc\n        lufx FXAction FXPure            = FXProc\n        lufx FXAction FXMut             = FXProc\n        lufx FXAction FXProc            = FXProc\n        lufx FXAction FXAction          = FXAction\n\nlub env (TNil _ k1) (TNil _ k2)\n  | k1 == k2                            = pure $ tNil k1\nlub env (TRow _ k1 n1 t1 r1) (TRow _ k2 n2 t2 r2)\n  | k1 == k2 && n1 == n2                = tRow k1 n1 <$> lub env t1 t2 <*> lub env r1 r2\nlub env (TStar _ k1 r1) (TStar _ k2 r2)\n  | k1 == k2                            = tStar k1 <$> lub env r1 r2\n\nlub env t1 t2                           = Nothing\n\n\nlub2 env (TRow _ _ _ t1 p1) k1 (TRow _ _ _ t2 p2) k2\n                                        = do t <- lub env t1 t2\n                                             (p,k) <- lub2 env p1 k1 p2 k2\n                                             return (posRow t p, k)\nlub2 env (TRow _ _ _ t1 p1) k1 p2@TNil{} k2@TRow{}\n                                        = lub2 env p1 (kwdRow (label k2) t1 k1) p2 k2\nlub2 env p1@TNil{} k1@TRow{} (TRow _ _ _ t2 p2) k2\n                                        = lub2 env p1 k1 p2 (kwdRow (label k1) t2 k2)\nlub2 env p1 k1 p2 k2                    = do p <- lub env p1 p2\n                                             k <- lub env k1 k2\n                                             return (p, k)\n\n\nlubfold env ts                          = case filter (/= tWild) ts of\n                                            [] -> pure tWild\n                                            t:ts -> foldM (lub env) t ts\n\n\n-- Control flow --------------------\n\ndata Flow                           = RET | BRK | CNT | SEQ deriving (Eq, Show)\n\nclass Flows a where\n    flows                           :: a -> [Flow]\n\nfallsthru x                         = SEQ `elem` flows x\n\nbrkseq flow                         = (if BRK `elem` flow then SEQ:flow else flow) \\\\ [BRK,CNT]\n\n\ninstance Flows a => Flows [a] where\n    flows []                        = [SEQ]\n    flows (s : ss)                  = flows s `seq` flows ss\n      where f1 `seq` f2             = if SEQ `elem` f1 then (f1\\\\[SEQ])++f2 else f1\n\ninstance Flows Stmt where\n    flows (Expr _ e)\n      | e == eNotImpl               = []                -- Not tracked\n      | Call _ (Var _ n) _ _ <- e,\n        n == primRAISE              = []                -- Not tracked\n    flows Raise{}                   = []                -- Not tracked\n    flows Return{}                  = [RET]\n    flows Break{}                   = [BRK]\n    flows Continue{}                = [CNT]\n    flows (If _ bs els)             = concatMap flows bs ++ flows els\n    flows (While _ _ b els)         = brkseq (flows b) ++ flows els\n    flows (For _ _ _ b els)         = brkseq (flows b) ++ flows els\n    flows (With _ _ b)              = flows b\n    flows (Try _ b hs els fin)      = flows (b++els) ++ concatMap flows hs ++ (flows fin \\\\ [SEQ])\n    flows _                         = [SEQ]\n\ninstance Flows Branch where\n    flows (Branch _ ss)             = flows ss\n\ninstance Flows Handler where\n    flows (Handler _ ss)            = flows ss\n\n\n\n-- Import handling (local definitions only) -------------------------------------------------------------------------\n\n--getImps                         :: [FilePath] -> EnvF x -> [Import] -> IO (EnvF x)\ngetImps spath env []         = return env { hmodules = convTEnv2HTEnv (modules env) }\ngetImps spath env (i:is)     = do env' <- impModule spath env i\n                                  getImps spath env' is\n\n\n--impModule                       :: [FilePath] -> EnvF x -> Import -> IO (EnvF x)\nimpModule spath env (Import _ ms)\n                                = imp env ms\n  where imp env []              = return env\n        imp env (ModuleItem m as : is)\n                                = do (env1,te) <- doImp spath env m\n                                     let env2 = maybe (addImpRoot m) (\\n->defineClosed [(n, NMAlias m)]) as env1\n                                     imp env2 is\nimpModule spath env (FromImport _ (ModRef (0,Just m)) items)\n                                = do (env1,te) <- doImp spath env m\n                                     return $ importSome items m te env1\nimpModule spath env (FromImportAll _ (ModRef (0,Just m)))\n                                = do (env1,te) <- doImp spath env m\n                                     return $ importAll m te env1\nimpModule _ _ i                 = illegalImport (loc i)\n\n\nsubImp spath env []          = return env\nsubImp spath env (m:ms)      = do (env',_) <- doImp spath env m\n                                  subImp spath env' ms\n\nfindTyFile spaths mn = go spaths\n  where\n    go []     = return Nothing\n    go (p:ps) = do\n      let fullPath = joinPath (p : modPath mn) ++ \".ty\"\n      exists <- doesFileExist fullPath\n      --traceM (\"findTyFile: \" ++ fullPath ++ \" \" ++ show exists)\n      if exists\n        then return (Just fullPath)\n        else go ps\n\n-- | Import a module, loading its .ty and extending the environment.\ndoImp                        :: [FilePath] -> EnvF x -> ModName -> IO (EnvF x, TEnv)\ndoImp spath env m            = do (env', te, _) <- doImpSeen S.empty env m\n                                  return (addImport m env', te)\n  where\n    -- A cached module still needs its recorded import closure available in the\n    -- environment. Otherwise later imports of that cached module can miss\n    -- transitive dependencies that were never added to the shared module cache.\n    doImpSeen seen env m\n      | S.member m seen      =\n          case lookupMod m env of\n            Just te -> return (env, te, seen)\n            Nothing -> fileNotFound m\n      | otherwise            =\n          let seen' = S.insert m seen in\n          case lookupMod m env of\n            Just te -> do\n              hdr <- readFoundTy InterfaceFiles.readHeaderMaybe m\n              case hdr of\n                Nothing -> return (env, te, seen')\n                Just (_sourceMeta, _, _, _, imps, _, _, _, _) -> do\n                  (env', seen'') <- subImpSeen seen' env (map fst imps)\n                  return (env', te, seen'')\n            Nothing -> do\n              ty <- readFoundTy InterfaceFiles.readFileMaybe m\n              case ty of\n                Nothing -> fileNotFound m\n                Just (ms,nmod,_,_,_,_,_,_,_,_,_,_) -> do\n                  (env', seen'') <- subImpSeen seen' env ms\n                  let NModule ms' teFull mdoc = nmod\n                      te = publicTEnv teFull\n                  return (addMod m ms' te mdoc env', te, seen'')\n\n    readFoundTy readTy m = do\n      tyFile <- findTyFile spath m\n      case tyFile of\n        Nothing -> return Nothing\n        Just tyF -> readTy tyF\n\n    subImpSeen seen env []   = return (env, seen)\n    subImpSeen seen env (m:ms) = do\n      (env', _, seen') <- doImpSeen seen env m\n      subImpSeen seen' env' ms\n\nimportSome                  :: [ImportItem] -> ModName -> TEnv -> EnvF x -> EnvF x\nimportSome items m te env   = defineClosed (map pick items) env\n  where\n    te1                     = impNames m te\n    pick (ImportItem n mbn) = case lookup n te1 of\n                                    Just i  -> (maybe n id mbn, i)\n                                    Nothing -> noItem m n\n\nimportAll                   :: ModName -> TEnv -> EnvF x -> EnvF x\nimportAll m te env          = defineClosed (impNames m te) env\n\nimpNames                    :: ModName -> TEnv -> TEnv\nimpNames m te               = mapMaybe imp (publicTEnv te)\n  where\n    imp (n, NAct _ _ _ _ _)   = Just (n, NAlias (GName m n))\n    imp (n, NClass _ _ _ _)   = Just (n, NAlias (GName m n))\n    imp (n, NProto _ _ _ _)   = Just (n, NAlias (GName m n))\n    imp (n, NExt _ _ _ _ _ _) = Nothing\n    imp (n, NAlias _)       = Just (n, NAlias (GName m n))\n    imp (n, NVar t)         = Just (n, NAlias (GName m n))\n    imp (n, NDef t d _)       = Just (n, NAlias (GName m n))\n    imp _                   = Nothing                               -- cannot happen\n\n\n\n-- Error handling ----------------------------------------------------------------------------------------------------\n\ndata CompilationError               = KindError SrcLoc Kind Kind\n                                    | InfiniteKind SrcLoc KUni Kind\n                                    | VariableFX TVar\n\n                                    | FileNotFound ModName\n                                    | NameNotFound Name\n                                    | NameReserved QName\n                                    | NameBlocked QName\n                                    | NameUnexpected QName\n                                    | TypedReassign Pattern\n                                    | IllegalRedef Name\n                                    | IllegalSigOverride Name\n                                    | IllegalExtension QName\n                                    | MissingSelf Name\n                                    | IllegalImport SrcLoc\n                                    | DuplicateImport Name\n                                    | NoItem ModName Name\n                                    | NoModule ModName\n                                    | NoClassOrProto QName\n                                    | DecorationMismatch Name TSchema Deco\n                                    | SelfParamError SrcLoc\n                                    | OtherError SrcLoc String\n                                    deriving (Show)\n\ninstance Control.Exception.Exception CompilationError\n\ninstance HasLoc CompilationError where\n    loc (KindError l _ _)           = l\n    loc (InfiniteKind l _ _)        = l\n    loc (VariableFX tv)             = loc tv\n\n    loc (FileNotFound n)            = loc n\n    loc (NameNotFound n)            = loc n\n    loc (NameReserved n)            = loc n\n    loc (NameBlocked n)             = loc n\n    loc (NameUnexpected n)          = loc n\n    loc (TypedReassign p)           = loc p\n    loc (IllegalRedef n)            = loc n\n    loc (IllegalSigOverride n)      = loc n\n    loc (IllegalExtension n)        = loc n\n    loc (MissingSelf n)             = loc n\n    loc (IllegalImport l)           = l\n    loc (DuplicateImport n)         = loc n\n    loc (NoModule m)                = loc m\n    loc (NoItem m n)                = loc n\n    loc (NoClassOrProto n)          = loc n\n    loc (DecorationMismatch n t d)  = loc n\n    loc (SelfParamError l)          = l\n    loc (OtherError l str)          = l\n\n\ncompilationError                    :: CompilationError -> [(SrcLoc, String)]\ncompilationError err                = [(loc err, render (expl err))]\n  where\n    expl (KindError l k1 k2)        = text \"Expected a\" <+> pretty k2 <> comma <+> text \"actual kind is\" <+> pretty k1\n    expl (InfiniteKind l v k)       = text \"Infinite kind inferred:\" <+> pretty v <+> equals <+> pretty k\n    expl (VariableFX tv)            = text \"Effect annotation cannot be a variable:\" <+> pretty tv\n\n    expl (FileNotFound n)           = text \"Type interface file not found for\" <+> pretty n\n    expl (NameNotFound n)           = text \"Name\" <+> pretty n <+> text \"is not in scope\"\n    expl (NameReserved n)           = text \"Name\" <+> pretty n <+> text \"is reserved but not yet defined\"\n    expl (NameBlocked n)            = text \"Name\" <+> pretty n <+> text \"is currently not accessible\"\n    expl (NameUnexpected n)         = text \"Unexpected variable name:\" <+> pretty n\n    expl (TypedReassign p)          = text \"Type annotation on reassignment:\" <+> pretty p\n    expl (IllegalRedef n)           = text \"Illegal redefinition of\" <+> pretty n\n    expl (IllegalSigOverride n)     = text \"Illegal signature override:\" <+> pretty n\n    expl (IllegalExtension n)       = text \"Illegal extension of\" <+> pretty n\n    expl (MissingSelf n)            = text \"Missing 'self' parameter in definition of\"\n    expl (IllegalImport l)          = text \"Relative import not yet supported\"\n    expl (DuplicateImport n)        = text \"Duplicate import of name\" <+> pretty n\n    expl (NoModule m)               = text \"Module\" <+> pretty m <+> text \"does not exist\"\n    expl (NoItem m n)               = text \"Module\" <+> pretty m <+> text \"does not export\" <+> pretty n\n    expl (NoClassOrProto n)         = text \"Class or protocol name expected, got\" <+> pretty n\n    expl (DecorationMismatch n t d) = text \"Decoration for\" <+> pretty n <+> text \"does not match signature\" <+> pretty d\n    expl (SelfParamError l)         = text \"'self' cannot be used as a parameter name in actors.\"\n    expl (OtherError l str)         = text str\n\n\nnoKUnify l k1 k2                    = Control.Exception.throw $ KindError l k1 k2\ninfiniteKind l v k                  = Control.Exception.throw $ InfiniteKind l v k\nvariableFX tv                       = Control.Exception.throw $ VariableFX tv\n\nnameNotFound n                      = Control.Exception.throw $ NameNotFound n\nnameReserved n                      = Control.Exception.throw $ NameReserved n\nnameBlocked n                       = Control.Exception.throw $ NameBlocked n\nnameUnexpected n                    = Control.Exception.throw $ NameUnexpected n\ntypedReassign p                     = Control.Exception.throw $ TypedReassign p\nillegalRedef n                      = Control.Exception.throw $ IllegalRedef n\nillegalSigOverride n                = Control.Exception.throw $ IllegalSigOverride n\nillegalExtension n                  = Control.Exception.throw $ IllegalExtension n\nmissingSelf n                       = Control.Exception.throw $ MissingSelf n\nfileNotFound n                      = Control.Exception.throw $ FileNotFound n\nillegalImport l                     = Control.Exception.throw $ IllegalImport l\nduplicateImport n                   = Control.Exception.throw $ DuplicateImport n\nnoItem m n                          = Control.Exception.throw $ NoItem m n\nnoModule m                          = Control.Exception.throw $ NoModule m\nnotClassOrProto n                   = Control.Exception.throw $ NoClassOrProto n\ndecorationMismatch n t d            = Control.Exception.throw $ DecorationMismatch n t d\nselfParamError l                    = Control.Exception.throw $ SelfParamError l\nerr l s                             = Control.Exception.throw $ OtherError l s\n\nerr0 xs s                           = err (loc $ head xs) s\nerr1 x s                            = err (loc x) (s ++ \" \" ++ prstr x)\nerr2 xs s                           = err (loc $ head xs) (s ++ \" \" ++ prstrs xs)\nerr3 l xs s                         = err l (s ++ \" \" ++ prstrs xs)\n\nnotYetExpr e                        = notYet (loc e) e\n\nstripQual q                         = [ QBind v [] | QBind v us <- q ]\n\n\nclass Simp a where\n    simp                            :: EnvF x -> a -> a\n\ninstance (Simp a) => Simp [a] where\n    simp env                        = map (simp env)\n\ninstance Simp TSchema where\n    simp env (TSchema l q t)        = TSchema l q' (vsubst s $ simp env' t)\n      where (q', s)                 = simpQuant env (simp env' q) (vfree t)\n            env'                    = defineTVars (stripQual q) env\n\nsimpQuant env q vs0                 = (vsubst s [ QBind v ps | QBind v ps <- q2, not $ null ps ], s)\n  where (q1,q2)                     = partition isEX q\n        isEX (QBind v [p])          = length (filter (==v) vs) == 1\n        isEX _                      = False\n        vs                          = concat [ vfree ps | QBind v ps <- q ] ++ vs0\n        s                           = [ (v, tCon p) | QBind v [p] <- q1 ]                       -- Inline existentials\n\ninstance Simp QBind where\n    simp env (QBind v ps)           = QBind v (simp env ps)\n\ninstance Simp WTCon where\n    simp env (w, c)                 = (w, simp env c)\n\ninstance Simp (Name, NameInfo) where\n    simp env (n, NSig sc dec doc)   = (n, NSig (simp env sc) dec doc)\n    simp env (n, NDef sc dec doc)   = (n, NDef (simp env sc) dec doc)\n    simp env (n, NVar t)            = (n, NVar (simp env t))\n    simp env (n, NSVar t)           = (n, NSVar (simp env t))\n    simp env (n, NClass q us te doc)= (n, NClass (simp env' q) (simp env' us) (simp env' te) doc)\n      where env'                    = defineTVars (stripQual q) env\n    simp env (n, NProto q us te doc)= (n, NProto (simp env' q) (simp env' us) (simp env' te) doc)\n      where env'                    = defineTVars (stripQual q) env\n    simp env (n, NExt q c us te opts doc)\n                                    = (n, NExt q' (vsubst s $ simp env' c) (vsubst s $ simp env' us) (vsubst s $ simp env' te) opts doc)\n      where (q', s)                 = simpQuant env (simp env' q) (vfree c ++ vfree us ++ vfree te)\n            env'                    = defineTVars (stripQual q) env\n    simp env (n, NAct q p k te doc) = (n, NAct (simp env' q) (simp env' p) (simp env' k) (simp env' te) doc)\n      where env'                    = defineTVars (stripQual q) env\n    simp env (n, i)                 = (n, i)\n\ninstance Simp Type where\n    simp env (TCon l c)             = TCon l (simp env c)\n    simp env (TFun l fx p k t)      = TFun l (simp env fx) (simp env p) (simp env k) (simp env t)\n    simp env (TTuple l p k)         = TTuple l (simp env p) (simp env k)\n    simp env (TOpt l t)             = TOpt l (simp env t)\n    simp env (TRow l k n t r)       = TRow l k n (simp env t) (simp env r)\n    simp env (TStar l k r)          = TStar l k (simp env r)\n    simp env t                      = t\n\ninstance Simp TCon where\n    simp env (TC n ts)              = TC (simp env n) (simp env ts)                             -- Simplify constructor names\n\ninstance Simp QName where\n    simp env (GName m n)\n      | inBuiltin env               = NoQ n                                                     -- Restore builtins\n      | Just m == thismod env       = NoQ n                                                     -- Restore locals\n    simp env n\n      | Just n1 <- findAlias (activeNames env) = NoQ n1                                      -- Restore aliases\n      | Just n1 <- findAlias (closedNames env) = NoQ n1                                      -- Restore aliases\n      | otherwise                   = n\n      where findAlias ((n1, NAlias n2):te)\n              | n2 == n             = Just n1\n            findAlias (_:te)        = findAlias te\n            findAlias []            = Nothing\n"
  },
  {
    "path": "compiler/lib/src/Acton/Fingerprint.hs",
    "content": "module Acton.Fingerprint\n  ( fingerprintPlaceholder\n  , fingerprintPrefixForName\n  , formatFingerprint\n  , formatFingerprintPrefix\n  , parseFingerprint\n  , updateFingerprintPrefix\n  ) where\n\nimport Data.Bits (shiftL, xor, shiftR, complement, (.|.), (.&.))\nimport Data.Char (isSpace, toLower)\nimport Data.Word (Word32, Word64)\nimport Numeric (readHex, showHex)\nimport qualified Data.ByteString.Char8 as B\nimport qualified Data.ByteString as BS\n\nfingerprintPlaceholder :: String\nfingerprintPlaceholder = \"0xacedf00dacedf00d\"\n\ncrc32IsoHdlc :: BS.ByteString -> Word32\ncrc32IsoHdlc bs = complement (BS.foldl' update 0xffffffff bs)\n  where\n    update crc byte = go 0 (crc `xor` fromIntegral byte)\n    go 8 crc = crc\n    go n crc =\n        let crc' = if (crc .&. 1) /= 0\n                     then (crc `shiftR` 1) `xor` 0xEDB88320\n                     else crc `shiftR` 1\n        in go (n + 1) crc'\n\nfingerprintPrefixForName :: String -> Word32\nfingerprintPrefixForName name =\n    crc32IsoHdlc (B.pack name)\n\nformatFingerprint :: Word64 -> String\nformatFingerprint fp =\n    \"0x\" ++ padHex 16 fp\n\nformatFingerprintPrefix :: Word32 -> String\nformatFingerprintPrefix fp =\n    \"0x\" ++ padHex 8 (fromIntegral fp :: Word64)\n\nupdateFingerprintPrefix :: Word32 -> Word64 -> Word64\nupdateFingerprintPrefix prefix fp =\n    (fromIntegral prefix `shiftL` 32) .|. (fp .&. 0xffffffff)\n\nparseFingerprint :: String -> Maybe Word64\nparseFingerprint raw =\n    let trimmed = trim raw\n    in case trimmed of\n         '0':'x':rest -> parseHex rest\n         '0':'X':rest -> parseHex rest\n         _ -> Nothing\n  where\n    trim = dropWhile isSpace . reverse . dropWhile isSpace . reverse\n\n    parseHex s =\n      case readHex (map toLower s) of\n        [(n, \"\")] | n <= toInteger (maxBound :: Word64) -> Just (fromInteger n)\n        _ -> Nothing\n\npadHex :: Int -> Word64 -> String\npadHex width value =\n    let hex = showHex value \"\"\n        zeros = replicate (max 0 (width - length hex)) '0'\n    in zeros ++ hex\n"
  },
  {
    "path": "compiler/lib/src/Acton/Hashing.hs",
    "content": "module Acton.Hashing\n  ( TopLevelItem(..)\n  , topLevelItems\n  , nameHashesFromItems\n  , implDepsFromItems\n  , splitDeps\n  , externalModules\n  , computeHashes\n  , buildNameHashes\n  , refreshImplHashes\n  , modulePubHashFromIface\n  , moduleImplHashFromNameHashes\n  , nameKey\n  , qnameKey\n  ) where\n\nimport qualified Acton.Env as Env\nimport qualified Acton.NameInfo as I\nimport qualified Acton.Names as Names\nimport Acton.Prim (mPrim)\nimport qualified Acton.Syntax as A\nimport qualified InterfaceFiles\nimport qualified Pretty\n\nimport Data.Binary (encode)\nimport qualified Crypto.Hash.SHA256 as SHA256\nimport qualified Data.ByteString.Char8 as B\nimport qualified Data.ByteString.Lazy as BL\nimport Data.Graph (SCC(..), stronglyConnComp)\nimport Data.List (foldl', intercalate, nub)\nimport qualified Data.List\nimport qualified Data.Map as M\nimport Data.Maybe (mapMaybe)\nimport qualified Data.Set\n\n\ndata TopLevelItem = TLDecl A.Name A.Decl | TLStmt A.Name A.Stmt\n\n-- | Render a local name as a stable string key.\nnameKey :: A.Name -> String\nnameKey = A.nstr\n\n-- | Render a qualified name as a stable string key.\nqnameKey :: A.QName -> String\nqnameKey qn = case qn of\n  A.GName m n -> modNameToString m ++ \".\" ++ A.nstr n\n  A.QName m n -> modNameToString m ++ \".\" ++ A.nstr n\n  A.NoQ n -> A.nstr n\n\n-- | Render a module name as dot-separated text.\nmodNameToString :: A.ModName -> String\nmodNameToString m = intercalate \".\" (A.modPath m)\n\n-- | Extract hashable top-level items from a module.\ntopLevelItems :: A.Module -> [TopLevelItem]\ntopLevelItems (A.Module _ _ _ suite) = concatMap items suite\n  where\n    items stmt = case stmt of\n      A.Decl _ ds ->\n        [ TLDecl (Names.dname' d) d | d <- ds ]\n      A.Signature _ ns _ _ ->\n        [ TLStmt n stmt | n <- ns ]\n      A.Assign _ ps _ ->\n        [ TLStmt n stmt | n <- nub (Names.bound ps) ]\n      A.VarAssign _ ps _ ->\n        [ TLStmt n stmt | n <- nub (Names.bound ps) ]\n      _ -> []\n\n-- | Collect pretty-printed fragments per top-level name.\nnameFragmentsFromItems :: [TopLevelItem] -> M.Map A.Name [String]\nnameFragmentsFromItems items =\n  foldl' addFrag M.empty items\n  where\n    addFrag acc item =\n      let (n, frag) = case item of\n            TLDecl name decl -> (name, Pretty.print decl)\n            TLStmt name stmt -> (name, Pretty.print stmt)\n      in M.insertWith (flip (++)) n [frag] acc\n\n-- | Hash each name's pretty-printed fragments.\nnameHashesFromItems :: [TopLevelItem] -> M.Map A.Name B.ByteString\nnameHashesFromItems items =\n  M.map (SHA256.hash . B.pack . intercalate \"\\n\") (nameFragmentsFromItems items)\n\n-- | Collect qualified-name dependencies for each item body.\nimplDepsFromItems :: [TopLevelItem] -> M.Map A.Name [A.QName]\nimplDepsFromItems items =\n  foldl' addDeps M.empty items\n  where\n    addDeps acc item =\n      let (n, deps) = case item of\n            TLDecl name decl -> (name, Names.freeQ decl)\n            TLStmt name stmt -> (name, Names.freeQ stmt)\n      in M.insertWith (++) n deps acc\n\n-- | Split deps into locals and external qualified names for hashing.\nsplitDeps :: A.ModName\n          -> Env.Env0\n          -> Data.Set.Set A.Name\n          -> M.Map A.Name [A.QName]\n          -> (M.Map A.Name [A.Name], M.Map A.Name [A.QName])\nsplitDeps mn env localNames depMap =\n  let toLocalExt qns = foldl' step (Data.Set.empty, Data.Set.empty) qns\n      step (locals, externals) qn =\n        case Env.unalias env qn of\n          A.GName m _ | m == mPrim -> (locals, externals)\n          A.QName m _ | m == mPrim -> (locals, externals)\n          A.GName m n\n            | m == mn && Data.Set.member n localNames -> (Data.Set.insert n locals, externals)\n            | m == mn -> (locals, externals)\n            | otherwise -> (locals, Data.Set.insert (A.GName m n) externals)\n          A.QName m n\n            | m == mn && Data.Set.member n localNames -> (Data.Set.insert n locals, externals)\n            | m == mn -> (locals, externals)\n            | otherwise -> (locals, Data.Set.insert (A.GName m n) externals)\n          A.NoQ n\n            | Data.Set.member n localNames -> (Data.Set.insert n locals, externals)\n            | otherwise -> (locals, externals)\n      pairs = M.map toLocalExt depMap\n      localMap = M.map (Data.Set.toList . fst) pairs\n      extMap = M.map (Data.Set.toList . snd) pairs\n  in (localMap, extMap)\n\n-- | Collect referenced external modules from dependency lists.\nexternalModules :: M.Map A.Name [A.QName] -> Data.Set.Set A.ModName\nexternalModules deps =\n  Data.Set.fromList $ mapMaybe modOf (concat (M.elems deps))\n  where\n    modOf qn = case qn of\n      A.GName m _ -> Just m\n      A.QName m _ -> Just m\n      A.NoQ _ -> Nothing\n\n-- | Compute final hashes by folding in local and external deps.\ncomputeHashes :: M.Map A.Name B.ByteString\n              -> M.Map A.Name [A.Name]\n              -> M.Map A.Name [(A.QName, B.ByteString)]\n              -> M.Map A.Name B.ByteString\ncomputeHashes selfHashes localDeps extDeps =\n  foldl' addScc M.empty (stronglyConnComp nodes)\n  where\n    nodes = [ (n, n, M.findWithDefault [] n localDeps) | n <- M.keys selfHashes ]\n\n    addScc acc scc = case scc of\n      AcyclicSCC n ->\n        let depHashes = depHashList acc (M.findWithDefault [] n localDeps) (M.findWithDefault [] n extDeps)\n            finalHash = SHA256.hash (BL.toStrict (encode (selfHashes M.! n, depHashes)))\n        in M.insert n finalHash acc\n      CyclicSCC ns ->\n        let nsSet = Data.Set.fromList ns\n            selfHashesSorted = [ selfHashes M.! n | n <- Data.List.sortOn nameKey ns ]\n            outsideDeps = Data.Set.toList $ Data.Set.fromList\n              [ d | n <- ns, d <- M.findWithDefault [] n localDeps, Data.Set.notMember d nsSet ]\n            externalDeps = Data.Set.toList $ Data.Set.fromList (concat [ M.findWithDefault [] n extDeps | n <- ns ])\n            depHashes = depHashList acc outsideDeps externalDeps\n            groupHash = SHA256.hash (BL.toStrict (encode (selfHashesSorted, depHashes)))\n            insertOne m n =\n              let finalHash = SHA256.hash (BL.toStrict (encode (selfHashes M.! n, groupHash, nameKey n)))\n              in M.insert n finalHash m\n        in foldl' insertOne acc ns\n\n    depHashList acc locals externals =\n      let lookupHash n = case M.lookup n acc of\n                           Just h -> Just h\n                           Nothing -> M.lookup n selfHashes\n          localHashes =\n            [ h | n <- Data.List.sortOn nameKey locals\n                , Just h <- [lookupHash n] ]\n          externalHashes =\n            [ h | (_, h) <- Data.List.sortOn (qnameKey . fst) externals ]\n      in localHashes ++ externalHashes\n\n-- | Build NameHashInfo entries from per-name hashes and deps.\nbuildNameHashes :: Data.Set.Set A.Name\n                -> M.Map A.Name B.ByteString\n                -> M.Map A.Name B.ByteString\n                -> M.Map A.Name I.NameInfo\n                -> M.Map A.Name [A.Name]\n                -> M.Map A.Name [(A.QName, B.ByteString)]\n                -> M.Map A.Name [A.Name]\n                -> M.Map A.Name [(A.QName, B.ByteString)]\n                -> M.Map A.Name [(A.QName, B.ByteString)]\n                -> [InterfaceFiles.NameHashInfo]\nbuildNameHashes nameKeys nameSrcHashes nameImplHashes nameInfoMap pubSigLocalDeps pubSigExtHashes implLocalDeps implExtHashes pubExtHashes =\n  let hashNameInfo info = SHA256.hash (BL.toStrict $ encode (I.stripLocsNI (I.stripDocsNI info)))\n      selfPubHashes = M.map hashNameInfo nameInfoMap\n      selfImplHashes = nameImplHashes\n      pubHashes = computeHashes selfPubHashes pubSigLocalDeps pubSigExtHashes\n      implHashes = computeHashes selfImplHashes implLocalDeps implExtHashes\n      namesSorted = Data.List.sortOn nameKey (Data.Set.toList nameKeys)\n  in\n    [ InterfaceFiles.NameHashInfo\n        { InterfaceFiles.nhName = n\n        , InterfaceFiles.nhSrcHash = M.findWithDefault B.empty n nameSrcHashes\n        , InterfaceFiles.nhPubHash = M.findWithDefault B.empty n pubHashes\n        , InterfaceFiles.nhImplHash = M.findWithDefault B.empty n implHashes\n        , InterfaceFiles.nhPubDeps = M.findWithDefault [] n pubExtHashes\n        , InterfaceFiles.nhImplDeps = M.findWithDefault [] n implExtHashes\n        }\n    | n <- namesSorted\n    ]\n\n-- | Refresh impl hashes and impl deps for existing name hashes.\nrefreshImplHashes :: [InterfaceFiles.NameHashInfo]\n                  -> M.Map A.Name B.ByteString\n                  -> M.Map A.Name [A.Name]\n                  -> M.Map A.Name [(A.QName, B.ByteString)]\n                  -> [InterfaceFiles.NameHashInfo]\nrefreshImplHashes nameHashes nameImplHashes implLocalDeps implExtHashes =\n  let implHashes = computeHashes nameImplHashes implLocalDeps implExtHashes\n      infoMap = M.fromList [ (InterfaceFiles.nhName nh, nh) | nh <- nameHashes ]\n      namesSorted = Data.List.sortOn nameKey (M.keys nameImplHashes)\n  in\n    [ let nh = infoMap M.! n\n      in nh { InterfaceFiles.nhImplHash = M.findWithDefault B.empty n implHashes\n            , InterfaceFiles.nhImplDeps = M.findWithDefault [] n implExtHashes\n            }\n    | n <- namesSorted\n    ]\n\n-- | Hash the module public interface entries.\nmodulePubHashFromIface :: I.NameInfo -> [InterfaceFiles.NameHashInfo] -> B.ByteString\nmodulePubHashFromIface nmod nameHashes =\n  let I.NModule _ iface _ = nmod\n      pubHashMap = M.fromList\n        [ (InterfaceFiles.nhName nh, InterfaceFiles.nhPubHash nh)\n        | nh <- nameHashes\n        ]\n      pubNamesSorted = Data.List.sortOn nameKey\n        [ n | (n, _) <- iface, Names.isPublicName n ]\n      pubEntries = [ (nameKey n, M.findWithDefault B.empty n pubHashMap) | n <- pubNamesSorted ]\n  in SHA256.hash (BL.toStrict $ encode pubEntries)\n\n-- | Hash the module impl entries from per-name impl hashes.\nmoduleImplHashFromNameHashes :: [InterfaceFiles.NameHashInfo] -> B.ByteString\nmoduleImplHashFromNameHashes infos =\n  let items =\n        [ (nameKey (InterfaceFiles.nhName nh), InterfaceFiles.nhImplHash nh)\n        | nh <- Data.List.sortOn (nameKey . InterfaceFiles.nhName) infos\n        ]\n  in SHA256.hash (BL.toStrict (encode items))\n"
  },
  {
    "path": "compiler/lib/src/Acton/Kinds.hs",
    "content": "-- Copyright (C) 2019-2021 Data Ductus AB\n--\n-- Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:\n--\n-- 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.\n--\n-- 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.\n--\n-- 3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission.\n--\n-- THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS \"AS IS\" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n--\n\n{-# LANGUAGE MultiParamTypeClasses, FlexibleInstances, FlexibleContexts #-}\nmodule Acton.Kinds(check) where\n\nimport qualified Control.Exception\nimport Control.DeepSeq (force)\nimport qualified Data.Map.Strict as Map\nimport Data.Map.Strict (Map)\nimport Control.Monad.State.Strict\nimport Control.Monad\nimport Pretty\nimport Utils\nimport Acton.Syntax\nimport Acton.Names\nimport Acton.Builtin\nimport Acton.Subst\nimport Acton.NameInfo\nimport Acton.Env\n\n\ncheck                               :: Env0 -> Module -> IO Module\ncheck env0 (Module m imps mdoc ss)  = do Control.Exception.evaluate $ force checked\n  where env                         = kindEnv env0\n        ss1                         = runKindM (kchkTop env ss)\n        checked                     = Module m imps mdoc ss1\n\n\ndata KindState                      = KindState {\n                                        nextint     :: Int,\n                                        unisubst    :: Map KUni Kind,\n                                        xvars       :: QBinds\n                                      }\n\ntype KindM a                        = State KindState a\n\nrunKindM                            :: KindM a -> a\nrunKindM m                          = evalState m $ KindState { nextint = 1, unisubst = Map.empty, xvars = [] }\n\nnewUnique                           :: KindM Int\nnewUnique                           = state $ \\st -> (nextint st, st{ nextint = nextint st + 1 })\n\nusubstitute                         :: KUni -> Kind -> KindM ()\nusubstitute kv k                    = state $ \\st -> ((), st{ unisubst = Map.insert kv k (unisubst st)})\n\nusubstitution                       :: KindM (Map KUni Kind)\nusubstitution                       = state $ \\st -> (unisubst st, st)\n\nstoreXVar                           :: TVar -> TCon -> KindM ()\nstoreXVar xv p                      = state $ \\st -> ((), st{ xvars = QBind xv [p] : xvars st })\n\nswapXVars                           :: QBinds -> KindM QBinds\nswapXVars q                         = state $ \\st -> (xvars st, st{ xvars = q })\n\nnewWildvar l                        = do k <- newKUni\n                                         i <- newUnique\n                                         return $ uniwild k l i\n\nnewKUni                             = KUni <$> newUnique\n\nnewXVar                             = TV KType <$> (Internal Xistvar \"\" <$> newUnique)\n\ntype KindEnv                        = EnvF ()\n\nkindEnv env0                        = env0\n\ntvars env                           = tvs (activeNames env) ++ tvs (closedNames env)\n  where tvs te                      = [ TV k n | (n, NTVar k _ _) <- te ]\n\nextcons ke env                      = define ke env\n\nextvars vs env\n  | not $ null clash                = err1 (head clash) \"Type variable already in scope:\"    -- No type variable shadowing\n  | not $ null dups                 = err1 (head dups) \"Duplicate type variable in binding:\"\n  | otherwise                       = return $ defineTVars [ QBind tv [] | tv <- vs ] env\n  where clash                       = vs `intersect` tvars env\n        dups                        = duplicates vs\n\ntcKind qn env                       = tconKind qn env\n\ntvKind v env                        = case filter (==v) (tvars env) of\n                                        [] -> err1 v \"Unbound type variable:\"\n                                        TV k _ : _ -> k\n\ninstance Pretty (Name,Kind) where\n    pretty (n,k)                    = pretty n <+> colon <+> pretty k\n\n\nautoQuantS env (TSchema l q t)      = TSchema l (q ++ auto_q) t\n  where auto_q                      = map qbind $ nub (vfree q ++ vfree t) \\\\ (tvSelf : qbound q ++ tvars env)\n\nautoQuantD env (Def l n q p k t b d x doc)\n                                    = Def l n (q ++ auto_q) p k t b d x doc\n  where auto_q                      = map qbind $ nub (vfree q ++ vfree p ++ vfree k ++ vfree t) \\\\ (tvSelf : qbound q ++ tvars env)\nautoQuantD env (Extension l q c ps b doc)\n                                    = Extension l (q ++ auto_q) c ps b doc\n  where auto_q                      = map qbind $ nub (vfree q ++ vfree c ++ vfree ps) \\\\ (tvSelf : qbound q ++ tvars env)\nautoQuantD env d                    = d\n\n\n--                  TWild             ~TWild\n--                -------------------------------------------\n--         Exist  | Def             | TSchema,Extension     |\n--                -------------------------------------------\n--        ~Exist  | Lambda,Pattern  | Actor,Class,Protocol  |\n--                -------------------------------------------\n\n\n----------------------------------------------------------------------------------------------------------------------\n-- instKWild\n----------------------------------------------------------------------------------------------------------------------\n\nclass InstKWild a where\n    instKWild                       :: a -> KindM a\n\ninstance (InstKWild a) => InstKWild [a] where\n    instKWild                       = mapM instKWild\n\ninstance InstKWild Decl where\n    instKWild d                     = do q <- instKWild (qbinds d); return d{ qbinds = q }\n\ninstance InstKWild QBind where\n    instKWild (QBind v us)          = QBind <$> instKWild v <*> return us\n\ninstance InstKWild TSchema where\n    instKWild (TSchema l q t)       = TSchema l <$> instKWild q <*> return t\n\ninstance InstKWild TVar where\n    instKWild (TV KWild n)          = TV <$> newKUni <*> return n\n    instKWild tv                    = return tv\n\ninstance InstKWild TUni where\n    instKWild (UV KWild l i)        = do k <- newKUni; return $ UV k l i\n    instKWild uv                    = return uv\n\ninstance InstKWild (Maybe Type) where\n    instKWild (Just (TVar l v))     = Just <$> TVar l <$> instKWild v\n    instKWild x                     = return x\n\n\n----------------------------------------------------------------------------------------------------------------------\n-- convTWild\n----------------------------------------------------------------------------------------------------------------------\n\nclass ConvTWild a where\n    convTWild                       :: KindEnv -> a -> KindM a\n\ninstance ConvTWild Type where\n    convTWild env (TWild l)         = TUni l <$> newWildvar (qlevel env)\n    convTWild env (TFun l e p k t)  = TFun l <$> convTWild env e <*> convTWild env p <*> convTWild env k <*> convTWild env t\n    convTWild env (TTuple l p k)    = TTuple l <$> convTWild env p <*> convTWild env k\n    convTWild env (TOpt l t)        = TOpt l <$> convTWild env t\n    convTWild env (TCon l c)        = TCon l <$> convTWild env c\n    convTWild env (TRow l k n t r)  = TRow l k n <$> convTWild env t <*> convTWild env r\n    convTWild env (TStar l k r)     = TStar l k <$> convTWild env r\n    convTWild env t                 = return t\n\ninstance ConvTWild TCon where\n    convTWild env (TC n ts)         = TC n <$> mapM (convTWild env) ts\n\ninstance ConvTWild QBinds where\n    convTWild env q                 = mapM instq q\n      where instq (QBind v us)      = QBind v <$> mapM (convTWild env) us\n\ninstance ConvTWild (Maybe Type) where\n    convTWild env Nothing           = Just <$> convTWild env tWild\n    convTWild env (Just t)          = Just <$> convTWild env t\n\nmaybeConvTWild env Nothing          = return Nothing\nmaybeConvTWild env x                = convTWild env x\n\ninstance ConvTWild PosPar where\n    convTWild env (PosPar n t e p)  = PosPar n <$> convTWild env t <*> return e <*> convTWild env p\n    convTWild env (PosSTAR n Nothing)\n                                    = PosSTAR n <$> Just <$> (TTuple NoLoc <$> convTWild env tWild <*> pure kwdNil)\n    convTWild env (PosSTAR n (Just t))\n      | TTuple{} <- t               = PosSTAR n <$> Just <$> convTWild env t\n      | otherwise                   = err1 t \"Tuple type expected\"\n    convTWild env PosNIL            = return PosNIL\n\ninstance ConvTWild KwdPar where\n    convTWild env (KwdPar n t e k)  = KwdPar n <$> convTWild env t <*> return e <*> convTWild env k\n    convTWild env (KwdSTAR n Nothing)\n                                    = KwdSTAR n <$> Just <$> (TTuple NoLoc posNil <$> convTWild env tWild)\n    convTWild env (KwdSTAR n (Just t))\n      | TTuple{} <- t               = KwdSTAR n <$> Just <$> convTWild env t\n      | otherwise                   = err1 t \"Tuple type expected\"\n    convTWild env KwdNIL            = return KwdNIL\n\n\n----------------------------------------------------------------------------------------------------------------------\n-- convPExist\n----------------------------------------------------------------------------------------------------------------------\n\nclass ConvPExist a where\n    convPExist                      :: KindEnv -> a -> KindM a\n\ninstance ConvPExist Type where\n    convPExist env (TCon l c)       = do c <- convPExist env c\n                                         case khead $ tcKind (tcname c) env of\n                                             KProto -> do\n                                                 xv <- newXVar\n                                                 storeXVar xv c\n                                                 return $ TVar l xv\n                                             _ ->\n                                                 return $ TCon l c\n      where khead (KFun _ k)        = k\n            khead k                 = k\n    convPExist env (TFun l e p k t) = TFun l <$> convPExist env e <*> convPExist env p <*> convPExist env k <*> convPExist env t\n    convPExist env (TTuple l p k)   = TTuple l <$> convPExist env p <*> convPExist env k\n    convPExist env (TOpt l t)       = TOpt l <$> convPExist env t\n    convPExist env (TRow l k n t r) = TRow l k n <$> convPExist env t <*> convPExist env r\n    convPExist env (TStar l k r)    = TStar l k <$> convPExist env r\n    convPExist env t                = return t\n\ninstance ConvPExist TCon where\n    convPExist env (TC n ts)        = TC n <$> mapM (convPExist env) ts\n\ninstance ConvPExist QBind where\n    convPExist env (QBind v us)     = QBind v <$> convPExist env us\n\ninstance (ConvPExist a) => ConvPExist (Maybe a) where\n    convPExist env t                = sequence $ fmap (convPExist env) t\n\ninstance (ConvPExist a) => ConvPExist [a] where\n    convPExist env                  = mapM (convPExist env)\n\ninstance ConvPExist PosPar where\n    convPExist env (PosPar n t e p) = PosPar n <$> convPExist env t <*> return e <*> convPExist env p\n    convPExist env (PosSTAR n t)    = PosSTAR n <$> convPExist env t\n    convPExist env PosNIL           = return PosNIL\n\ninstance ConvPExist KwdPar where\n    convPExist env (KwdPar n t e k) = KwdPar n <$> convPExist env t <*> return e <*> convPExist env k\n    convPExist env (KwdSTAR n t)    = KwdSTAR n <$> convPExist env t\n    convPExist env KwdNIL           = return KwdNIL\n\n\n----------------------------------------------------------------------------------------------------------------------\n-- kchk\n----------------------------------------------------------------------------------------------------------------------\n\nkchkTop env ss                      = do ss <- kchkSuite env ss\n                                         ksubst True ss\n\nclass KCheck a where\n    kchk                            :: KindEnv -> a -> KindM a\n\ninstance KCheck a => KCheck [a] where\n    kchk env                        = mapM (kchk env)\n\ninstance KCheck a => KCheck (Maybe a) where\n    kchk env                        = traverse (kchk env)\n\ninstance (KCheck a, KCheck b) => KCheck (a,b) where\n    kchk env (a, b)                 = (,) <$> kchk env a <*> kchk env b\n\nkchkSuite env []                    = return []\nkchkSuite env (Decl l ds : ss)      = do ds <- instKWild (map (autoQuantD env) ds)\n                                         let env1 = extcons (concatMap kinds ds) env\n                                         ds <- kchk env1 ds\n                                         ss <- kchkSuite env1 ss\n                                         return (Decl l ds : ss)\n  where kinds (Actor _ n q _ _ _ _) = [(n, NAct q posNil kwdNil [] Nothing)]\n        kinds (Class _ n q _ _ _)   = [(n, NClass q [] [] Nothing)]\n        kinds (Protocol _ n q _ _ _)= [(n, NProto q [] [] Nothing)]\n        kinds _                     = []\n        kind k []                   = k\n        kind k q                    = KFun [ tvkind v | QBind v _ <- q ] k\nkchkSuite env (s : ss)              = do s <- kchk env s; ss <- kchkSuite env ss; return (s:ss)\n\ninstance KCheck Stmt where\n    kchk env (Expr l e)             = Expr l <$> kchk env e\n    kchk env (Assign l ps e)        = Assign l <$> kchk env ps <*> kchk env e\n    kchk env (MutAssign l t e)      = MutAssign l <$> kchk env t <*> kchk env e\n    kchk env (AugAssign l t op e)   = AugAssign l <$> kchk env t <*> return op <*> kchk env e\n    kchk env (Assert l e mbe)       = Assert l <$> kchk env e <*> kchk env mbe\n    kchk env (Pass l)               = return $ Pass l\n    kchk env (Delete l t)           = Delete l <$> kchk env t\n    kchk env (Return l mbe)         = Return l <$> kchk env mbe\n    kchk env (Raise l e)            = Raise l <$> kchk env e\n    kchk env (Break l)              = return $ Break l\n    kchk env (Continue l)           = return $ Continue l\n    kchk env (If l bs els)          = If l <$> kchk env bs <*> kchkSuite env els\n    kchk env (While l e b els)      = While l <$> kchk env e <*> kchkSuite env b <*> kchkSuite env els\n    kchk env (For l p e b els)      = For l <$> kchk env p <*> kchk env e <*> kchkSuite env b <*> kchkSuite env els\n    kchk env (Try l b hs els fin)   = Try l <$> kchkSuite env b <*> kchk env hs <*> kchkSuite env els <*> kchkSuite env fin\n    kchk env (With l is b)          = With l <$> kchk env is <*> kchkSuite env b\n    kchk env (Data l mbt ss)        = Data l <$> kchk env mbt <*> kchkSuite env ss\n    kchk env (VarAssign l ps e)     = VarAssign l <$> kchk env ps <*> kchk env e\n    kchk env (After l e e')         = After l <$> kchk env e <*> kchk env e'\n    kchk env (Decl l ds)            = Decl l <$> kchk env ds\n    kchk env (Signature l ns sc d)  = Signature l ns <$> (kchk env =<< instKWild (autoQuantS env sc)) <*> return d\n\ninstance KCheck Decl where\n    kchk env (Def l n q p k t b d x doc)\n      | not $ null ambig            = err2 ambig \"Ambiguous type variable in annotation:\"\n      | otherwise                   = do tmp <- swapXVars []\n                                         q <- convPExist env q\n                                         p <- convPExist env p\n                                         k <- convPExist env k\n                                         t <- convPExist env t\n                                         x <- convPExist env x\n                                         q <- (q++) <$> swapXVars tmp\n                                         env1 <- extvars (qbound q) env\n                                         q <- convTWild env1 q\n                                         p <- convTWild env1 p\n                                         k <- convTWild env1 k\n                                         t <- convTWild env1 t\n                                         x <- convTWild env1 x\n                                         Def l n <$> kchkQBinds env1 q <*> kchk env1 p <*> kchk env1 k <*> kexp KType env1 t <*> kchkSuite env1 b <*> \n                                                     pure d <*> kfx env1 x <*> pure doc\n      where ambig                   = qualbound q \\\\ closeDepVarsQ (vfree p ++ vfree k ++ vfree t ++ vfree x) q\n    kchk env (Actor l n q p k b doc)= do tmp <- swapXVars []\n                                         p <- convPExist env p\n                                         k <- convPExist env k\n                                         q <- (q++) <$> swapXVars tmp\n                                         env1 <- extvars (qbound q) env\n                                         p <- convTWild env1 p\n                                         k <- convTWild env1 k\n                                         Actor l n <$> kchkQBinds env1 q <*> kchk env1 p <*> kchk env1 k <*> kchkSuite env1 b <*> pure doc\n    kchk env (Class l n q us b doc) = do env1 <- extvars (tvSelf : qbound q) env\n                                         Class l n <$> kchkQBinds env1 q <*> kchkBounds env1 us <*> kchkSuite env1 b <*> pure doc\n    kchk env (Protocol l n q us b doc)\n                                    = do env1 <- extvars (tvSelf : qbound q) env\n                                         Protocol l n <$> kchkQBinds env1 q <*> kchkPBounds env1 us <*> kchkSuite env1 b <*> pure doc\n    kchk env (Extension l q c us b doc)\n      | not $ null ambig            = err2 ambig \"Ambiguous type variables in extension:\"\n      | not $ null undet            = err2 undet \"Type variables undetermined by extended class:\"\n      | otherwise                   = do tmp <- swapXVars []\n                                         q <- convPExist env q\n                                         c <- convPExist env c\n                                         us <- convPExist env us\n                                         q <- (q++) <$> swapXVars tmp\n                                         env1 <- extvars (tvSelf : qbound q) env\n                                         Extension l <$> kchkQBinds env1 q <*> kexp KType env1 c <*> kchkPBounds env1 us <*> kchkSuite env1 b <*> pure doc\n      where ambig                   = qualbound q \\\\ vs\n            undet                   = vfree us \\\\ (tvSelf : vs)\n            vs                      = closeDepVarsQ (vfree c) q\n\ninstance KCheck Expr where\n    kchk env (Var l n)              = return $ Var l n\n    kchk env (Int l i s)            = return $ Int l i s\n    kchk env (Float l f s)          = return $ Float l f s\n    kchk env (Imaginary l i s)      = return $ Imaginary l i s\n    kchk env (Bool l b)             = return $ Bool l b\n    kchk env (None l)               = return $ None l\n    kchk env (NotImplemented l)     = return $ NotImplemented l\n    kchk env (Ellipsis l)           = return $ Ellipsis l\n    kchk env (Strings l ss)         = return $ Strings l ss\n    kchk env (BStrings l ss)        = return $ BStrings l ss\n    kchk env (Call l e ps ks)       = Call l <$> kchk env e <*> kchk env ps <*> kchk env ks\n    kchk env (TApp l e ts)          = internal l \"Unexpected TApp in kchk\"\n    kchk env (Let l ss e)           = Let l <$> kchk env ss <*> kchk env e\n    kchk env (Async l e)            = Async l <$> kchk env e\n    kchk env (Await l e)            = Await l <$> kchk env e\n    kchk env (Index l e is)         = Index l <$> kchk env e <*> kchk env is\n    kchk env (Slice l e sl)         = Slice l <$> kchk env e <*> kchk env sl\n    kchk env (Cond l e1 e2 e3)      = Cond l <$> kchk env e1 <*> kchk env e2 <*> kchk env e3\n    kchk env (IsInstance l e c)     = IsInstance l <$> kchk env e <*> return (unalias env c)\n    kchk env (BinOp l e1 op e2)     = BinOp l <$> kchk env e1 <*> return op <*> kchk env e2\n    kchk env (CompOp l e ops)       = CompOp l <$> kchk env e <*> kchk env ops\n    kchk env (UnOp l op e)          = UnOp l op <$> kchk env e\n    kchk env (Dot l e n)\n      | Just m <- isModule env e    = return $ Var l (QName m n)\n      | otherwise                   = Dot l <$> kchk env e <*> return n\n    kchk env (Rest l e n)           = Rest l <$> kchk env e <*> return n\n    kchk env (DotI l e i)           = DotI l <$> kchk env e <*> return i\n    kchk env (RestI l e i)          = RestI l <$> kchk env e <*> return i\n    kchk env (Opt l e b)            = Opt l <$> kchk env e <*> return b\n    kchk env (OptChain l e)         = OptChain l <$> kchk env e\n    kchk env (Lambda l p k e x)     = Lambda l <$> (kchk env =<< convTWild env p) <*> (kchk env =<< convTWild env k) <*>\n                                                   kchk env e <*> (kfx env =<< convTWild env x)\n    kchk env (Yield l e)            = Yield l <$> kchk env e\n    kchk env (YieldFrom l e)        = YieldFrom l <$> kchk env e\n    kchk env (Tuple l es ks)        = Tuple l <$> kchk env es <*> kchk env ks\n    kchk env (List l es)            = List l <$> kchk env es\n    kchk env (ListComp l e c)       = ListComp l <$> kchk env e <*> kchk env c\n    kchk env (Dict l as)            = Dict l <$> kchk env as\n    kchk env (DictComp l a c)       = DictComp l <$> kchk env a <*> kchk env c\n    kchk env (Set l es)             = Set l <$> kchk env es\n    kchk env (SetComp l e c)        = SetComp l <$> kchk env e <*> kchk env c\n    kchk env (Paren l e)            = Paren l <$> kchk env e\n\nisModule env e                          = fmap ModName $ mfilter (isMod env) $ fmap reverse $ dotChain e\n  where dotChain (Var _ (NoQ n))        = Just [n]\n        dotChain (Dot _ e n)            = fmap (n:) (dotChain e)\n        dotChain _                      = Nothing\n\ninstance KCheck Pattern where\n    kchk env (PWild l t)            = PWild l <$> (kexp KType env =<< maybeConvTWild env t)\n    kchk env (PVar l n t)           = PVar l n <$> (kexp KType env =<< maybeConvTWild env t)\n    kchk env (PTuple l ps ks)       = PTuple l <$> kchk env ps <*> kchk env ks\n    kchk env (PList l ps p)         = PList l <$> kchk env ps <*> kchk env p\n    kchk env (PParen l p)           = PParen l <$> kchk env p\n\ninstance KCheck Branch where\n    kchk env (Branch e ss)          = Branch <$> kchk env e <*> kchkSuite env ss\n\ninstance KCheck Handler where\n    kchk env (Handler ex b)         = Handler <$> kchk env ex <*> kchkSuite env b\n\ninstance KCheck Except where\n    kchk env (ExceptAll l)          = return $ ExceptAll l\n    kchk env (Except l x)           = do kexp KType env (TC x []); return $ Except l x\n    kchk env (ExceptAs l x n)       = do kexp KType env (TC x []); return $ ExceptAs l x n\n\ninstance KCheck PosPar where\n    kchk env (PosPar n t e p)       = PosPar n <$> kexp KType env t <*> kchk env e <*> kchk env p\n    kchk env (PosSTAR n t)          = PosSTAR n <$> kexp KType env t\n    kchk env PosNIL                 = return PosNIL\n\ninstance KCheck KwdPar where\n    kchk env (KwdPar n t e k)       = KwdPar n <$> kexp KType env t <*> kchk env e <*> kchk env k\n    kchk env (KwdSTAR n t)          = KwdSTAR n <$> kexp KType env t\n    kchk env KwdNIL                 = return KwdNIL\n\ninstance KCheck PosArg where\n    kchk env (PosArg e p)           = PosArg <$> kchk env e <*> kchk env p\n    kchk env (PosStar e)            = PosStar <$> kchk env e\n    kchk env PosNil                 = return PosNil\n\ninstance KCheck KwdArg where\n    kchk env (KwdArg n e k)         = KwdArg n <$> kchk env e <*> kchk env k\n    kchk env (KwdStar e)            = KwdStar <$> kchk env e\n    kchk env KwdNil                 = return KwdNil\n\ninstance KCheck PosPat where\n    kchk env (PosPat p ps)          = PosPat <$> kchk env p <*> kchk env ps\n    kchk env (PosPatStar p)         = PosPatStar <$> kchk env p\n    kchk env PosPatNil              = return PosPatNil\n\ninstance KCheck KwdPat where\n    kchk env (KwdPat n p ps)        = KwdPat n <$> kchk env p <*> kchk env ps\n    kchk env (KwdPatStar p)         = KwdPatStar <$> kchk env p\n    kchk env KwdPatNil              = return KwdPatNil\n\ninstance KCheck OpArg where\n    kchk env (OpArg op e)           = OpArg op <$> kchk env e\n\ninstance KCheck Comp where\n    kchk env (CompFor l p e c)      = CompFor l <$> kchk env p <*> kchk env e <*> kchk env c\n    kchk env (CompIf l e c)         = CompIf l <$> kchk env e <*> kchk env c\n    kchk env NoComp                 = return NoComp\n\ninstance KCheck WithItem where\n    kchk env (WithItem e p)         = WithItem <$> kchk env e <*> kchk env p\n\ninstance KCheck Elem where\n    kchk env (Elem e)               = Elem <$> kchk env e\n    kchk env (Star e)               = Star <$> kchk env e\n\ninstance KCheck Assoc where\n    kchk env (Assoc e1 e2)          = Assoc <$> kchk env e1 <*> kchk env e2\n    kchk env (StarStar e)           = StarStar <$> kchk env e\n\ninstance KCheck Sliz where\n    kchk env (Sliz l e1 e2 e3)      = Sliz l <$> kchk env e1 <*> kchk env e2 <*> kchk env e3\n\ninstance KCheck TSchema where\n    kchk env (TSchema l q t)\n      | not $ null ambig            = err2 ambig \"Ambiguous type variable in schema:\"\n      | otherwise                   = do tmp <- swapXVars []\n                                         q <- convPExist env q\n                                         t <- convPExist env t\n                                         q <- (q++) <$> swapXVars tmp\n                                         env1 <- extvars (qbound q) env\n                                         TSchema l <$> kchkQBinds env1 q <*> kexp KType env1 t\n      where ambig                   = qualbound q \\\\ closeDepVarsQ (vfree t) q\n\nkchkQBinds env []                   = return []\nkchkQBinds env (QBind v us : q)     = do us <- kchkBounds env us\n                                         q <- kchkQBinds env q\n                                         return $ QBind v us : q\n\nkchkBounds env []                   = return []\nkchkBounds env (u:us)               = do (k,u) <- kinfer env u\n                                         case k of\n                                            KProto -> (:) u <$> kchkPBounds env us\n                                            _ -> do kunify (loc u) k KType; (:) u <$> kchkPBounds env us\n\nkchkPBounds env us                  = mapM (kexp KProto env) us\n\n\n----------------------------------------------------------------------------------------------------------------------\n-- kinfer\n----------------------------------------------------------------------------------------------------------------------\n\nclass KInfer t where\n    kinfer                          :: KindEnv -> t -> KindM (Kind,t)\n\n\ninstance (KInfer t) => KInfer (Maybe t) where\n    kinfer env Nothing              = do k <- newKUni; return (k, Nothing)\n    kinfer env (Just t)             = do (k,t) <- kinfer env t; return (k, Just t)\n\ninstance KInfer TVar where\n    kinfer env tv                   = do tv <- instKWild tv\n                                         return (tvkind tv, tv)\n\ninstance KInfer TUni where\n    kinfer env uv                   = do uv <- instKWild uv\n                                         return (uvkind uv, uv)\n\ninstance KInfer TCon where\n    kinfer env (TC n [])            = return (tcKind n env, TC (unalias env n) [])\n    kinfer env (TC n ts)            = do let kn = tcKind n env\n                                         (ks,ts) <- fmap unzip $ mapM (kinfer env) ts\n                                         k <- newKUni\n                                         kunify (loc n) kn (KFun ks k)\n                                         k <- ksubst False k\n                                         return (k, TC (unalias env n) ts)\n\nenvBound (TV k (Internal p _ _))    = False\nenvBound _                          = True\n\ninstance KInfer Type where\n    kinfer env (TWild l)            = err1 l \"Illegal wildcard type\"\n    kinfer env (TVar l v)           = do (k,v) <- kinfer env v\n                                         kunify l k (tvKind v env)\n                                         return (k, TVar l v)\n    kinfer env (TUni l u)           = do (k,u) <- kinfer env u                              -- Internal tyvars are not in the environment\n                                         return (k, TUni l u)\n    kinfer env (TCon l c)           = do c <- kexp KType env c\n                                         return (KType, TCon l c)\n    kinfer env (TFun l fx p k t)    = do fx <- kfx env fx\n                                         p <- kexp PRow env p\n                                         k <- kexp KRow env k\n                                         t <- kexp KType env t\n                                         return (KType, TFun l fx p k t)\n    kinfer env (TTuple l p k)       = do p <- kexp PRow env p\n                                         k <- kexp KRow env k\n                                         return (KType, TTuple l p k)\n    kinfer env (TOpt _ t@TOpt{})    = kinfer env t\n    kinfer env (TOpt l t)           = do t <- kexp KType env t\n                                         return (KType, TOpt l t)\n    kinfer env (TNone l)            = return (KType, TNone l)\n    kinfer env (TNil l k)           = return (k, TNil l k)\n    kinfer env (TRow l k n t r)     = do t <- kexp KType env t\n                                         r <- kexp k env r\n                                         return (k, TRow l k n t r)\n    kinfer env (TStar l k r)        = do r <- kexp k env r\n                                         return (k, TStar l k r)\n    kinfer env (TFX l fx)           = return (KFX, TFX l fx)\n\nkfx env (TVar _ tv)                 = variableFX tv\nkfx env t                           = kexp KFX env t\n\nkexp k env t                        = do (k',t') <- kinfer env t\n                                         kunify (loc t) k' k\n                                         return t'\n\n----------------------------------------------------------------------------------------------------------------------\n-- kunify\n----------------------------------------------------------------------------------------------------------------------\n\nkunify l k1 k2                      = do k1 <- ksubst False k1; k2 <- ksubst False k2; kunify' l k1 k2\n\nkunify' l (KUni v1) (KUni v2)\n  | v1 == v2                        = return ()\nkunify' l (KUni v) k2               = do when (v `elem` kfree k2) (infiniteKind l v k2)\n                                         usubstitute v k2\nkunify' l k1 (KUni v)               = do when (v `elem` kfree k1) (infiniteKind l v k1)\n                                         usubstitute v k1\nkunify' l (KFun ks1 k1) (KFun ks2 k2)\n  | length ks1 == length ks2        = do mapM_ (uncurry $ kunify l) (ks1 `zip` ks2)\n                                         kunify l k1 k2\nkunify' l k1 k2\n  | k1 == k2                        = return ()\n  | otherwise                       = noKUnify l k1 k2\n\n\nkfree (KUni v)                      = []\nkfree (KFun ks k)                   = concatMap kfree (k:ks)\nkfree _                             = []\n\n\n----------------------------------------------------------------------------------------------------------------------\n-- ksubst\n----------------------------------------------------------------------------------------------------------------------\n\nclass KSubst s where\n    ksubst                          :: Bool -> s -> KindM s             -- Bool flag controls whether free KUnis are replaced with KType or not\n\ninstance KSubst a => KSubst [a] where\n    ksubst g                        = mapM (ksubst g)\n\ninstance KSubst a => KSubst (Maybe a) where\n    ksubst g                        = maybe (return Nothing) (\\x -> Just <$> ksubst g x)\n\n\ninstance (KSubst a, KSubst b) => KSubst (a,b) where\n    ksubst g (a, b)                = (,) <$> ksubst g a <*> ksubst g b\n    \ninstance KSubst Kind where\n    ksubst g KWild                  = return KWild\n    ksubst g (KUni i)               = do s <- usubstitution\n                                         case Map.lookup i s of\n                                            Just k  -> ksubst g k\n                                            Nothing -> return (if g then KType else KUni i)\n    ksubst g (KFun ks k)            = KFun <$> mapM (ksubst g) ks <*> ksubst g k\n    ksubst g k                      = return k\n\ninstance KSubst TSchema where\n    ksubst g (TSchema l q t)        = TSchema l <$> ksubst g q <*> ksubst g t\n\ninstance KSubst TVar where\n    ksubst g (TV k n)               = TV <$> ksubst g k <*> return n\n\ninstance KSubst TUni where\n    ksubst g (UV k l i)             = do k <- ksubst g k; return $ UV k l i\n\ninstance KSubst TCon where\n    ksubst g (TC n ts)              = TC n <$> ksubst g ts\n\ninstance KSubst QBind where\n    ksubst g (QBind v cs)           = QBind <$> ksubst g v <*> ksubst g cs\n\ninstance KSubst Type where\n    ksubst g (TVar l v)             = TVar l <$> ksubst g v\n    ksubst g (TUni l u)             = TUni l <$> ksubst g u\n    ksubst g (TCon l c)             = TCon l <$> ksubst g c\n    ksubst g (TFun l fx p k t)      = TFun l <$> ksubst g fx <*> ksubst g p <*> ksubst g k<*> ksubst g t\n    ksubst g (TTuple l p k)         = TTuple l <$> ksubst g p <*> ksubst g k\n    ksubst g (TOpt l t)             = TOpt l <$> ksubst g t\n    ksubst g (TNone l)              = return $ TNone l\n    ksubst g (TNil l s)             = return $ TNil l s\n    ksubst g (TRow l k n t r)       = TRow l k n <$> ksubst g t <*> ksubst g r\n    ksubst g (TStar l k r)          = TStar l k <$> ksubst g r\n    ksubst g (TFX l fx)             = return $ TFX l fx\n\ninstance KSubst Stmt where\n    ksubst g (Expr l e)             = Expr l <$> ksubst g e\n    ksubst g (Assign l ps e)        = Assign l <$> ksubst g ps <*> ksubst g e\n    ksubst g (MutAssign l t e)      = MutAssign l <$> ksubst g t <*> ksubst g e\n    ksubst g (AugAssign l t op e)   = AugAssign l <$> ksubst g t <*> return op <*> ksubst g e\n    ksubst g (Assert l e mbe)       = Assert l <$> ksubst g e <*> ksubst g mbe\n    ksubst g (Pass l)               = return $ Pass l\n    ksubst g (Delete l t)           = Delete l <$> ksubst g t\n    ksubst g (Return l mbe)         = Return l <$> ksubst g mbe\n    ksubst g (Raise l e)            = Raise l <$> ksubst g e\n    ksubst g (Break l)              = return $ Break l\n    ksubst g (Continue l)           = return $ Continue l\n    ksubst g (If l bs els)          = If l <$> ksubst g bs <*> ksubst g els\n    ksubst g (While l e b els)      = While l <$> ksubst g e <*> ksubst g b <*> ksubst g els\n    ksubst g (For l p e b els)      = For l <$> ksubst g p <*> ksubst g e <*> ksubst g b <*> ksubst g els\n    ksubst g (Try l b hs els fin)   = Try l <$> ksubst g b <*> ksubst g hs <*> ksubst g els <*> ksubst g fin\n    ksubst g (With l is b)          = With l <$> ksubst g is <*> ksubst g b\n    ksubst g (Data l mbt ss)        = Data l <$> ksubst g mbt <*> ksubst g ss\n    ksubst g (VarAssign l ps e)     = VarAssign l <$> ksubst g ps <*> ksubst g e\n    ksubst g (After l e e')         = After l <$> ksubst g e <*> ksubst g e'\n    ksubst g (Decl l ds)            = Decl l <$> ksubst g ds\n    ksubst g (Signature l ns t d)   = Signature l ns <$> ksubst g t <*> return d\n\ninstance KSubst Decl where\n    ksubst g (Def l n q p k a b d x doc)\n                                    = Def l n <$> ksubst g q <*> ksubst g p <*> ksubst g k <*> ksubst g a <*> ksubst g b <*> return d <*> ksubst g x <*> return doc\n    ksubst g (Actor l n q p k b doc)\n                                    = Actor l n <$> ksubst g q <*> ksubst g p <*> ksubst g k <*> ksubst g b <*> return doc\n    ksubst g (Class l n q as b doc) = Class l n <$> ksubst g q <*> ksubst g as <*> ksubst g b <*> return doc\n    ksubst g (Protocol l n q as b doc)\n                                    = Protocol l n <$> ksubst g q <*> ksubst g as <*> ksubst g b <*> return doc\n    ksubst g (Extension l q c as b doc)\n                                    = Extension l <$> ksubst g q <*> ksubst g c <*> ksubst g as <*> ksubst g b <*> return doc\n\ninstance KSubst Expr where\n    ksubst g (Var l n)              = return $ Var l n\n    ksubst g (Int l i s)            = return $ Int l i s\n    ksubst g (Float l f s)          = return $ Float l f s\n    ksubst g (Imaginary l i s)      = return $ Imaginary l i s\n    ksubst g (Bool l b)             = return $ Bool l b\n    ksubst g (None l)               = return $ None l\n    ksubst g (NotImplemented l)     = return $ NotImplemented l\n    ksubst g (Ellipsis l)           = return $ Ellipsis l\n    ksubst g (Strings l ss)         = return $ Strings l ss\n    ksubst g (BStrings l ss)        = return $ BStrings l ss\n    ksubst g (Call l e ps ks)       = Call l <$> ksubst g e <*> ksubst g ps <*> ksubst g ks\n    ksubst g (TApp l e ts)          = TApp l <$> ksubst g e <*> ksubst g ts\n    ksubst g (Let l ss e)           = Let l <$> ksubst g ss <*> ksubst g e\n    ksubst g (Async l e)            = Async l <$> ksubst g e\n    ksubst g (Await l e)            = Await l <$> ksubst g e\n    ksubst g (Index l e is)         = Index l <$> ksubst g e <*> ksubst g is\n    ksubst g (Slice l e sl)         = Slice l <$> ksubst g e <*> ksubst g sl\n    ksubst g (Cond l e1 e2 e3)      = Cond l <$> ksubst g e1 <*> ksubst g e2 <*> ksubst g e3\n    ksubst g (IsInstance l e c)     = IsInstance l <$> ksubst g e <*> return c\n    ksubst g (BinOp l e1 op e2)     = BinOp l <$> ksubst g e1 <*> return op <*> ksubst g e2\n    ksubst g (CompOp l e ops)       = CompOp l <$> ksubst g e <*> ksubst g ops\n    ksubst g (UnOp l op e)          = UnOp l op <$> ksubst g e\n    ksubst g (Dot l e n)            = Dot l <$> ksubst g e <*> return n\n    ksubst g (Rest l e n)           = Rest l <$> ksubst g e <*> return n\n    ksubst g (DotI l e i)           = DotI l <$> ksubst g e <*> return i\n    ksubst g (RestI l e i)          = RestI l <$> ksubst g e <*> return i\n    ksubst g (Opt l e b)            = Opt l <$> ksubst g e <*> return b\n    ksubst g (OptChain l e)         = OptChain l <$> ksubst g e\n    ksubst g (Lambda l ps ks e fx)  = Lambda l <$> ksubst g ps <*> ksubst g ks <*> ksubst g e <*> ksubst g fx\n    ksubst g (Yield l e)            = Yield l <$> ksubst g e\n    ksubst g (YieldFrom l e)        = YieldFrom l <$> ksubst g e\n    ksubst g (Tuple l es ks)        = Tuple l <$> ksubst g es <*> ksubst g ks\n    ksubst g (List l es)            = List l <$> ksubst g es\n    ksubst g (ListComp l e c)       = ListComp l <$> ksubst g e <*> ksubst g c\n    ksubst g (Dict l as)            = Dict l <$> ksubst g as\n    ksubst g (DictComp l a c)       = DictComp l <$> ksubst g a <*> ksubst g c\n    ksubst g (Set l es)             = Set l <$> ksubst g es\n    ksubst g (SetComp l e c)        = SetComp l <$> ksubst g e <*> ksubst g c\n    ksubst g (Paren l e)            = Paren l <$> ksubst g e\n\ninstance KSubst Pattern where\n    ksubst g (PWild l a)            = PWild l <$> ksubst g a\n    ksubst g (PVar l n a)           = PVar l n <$> ksubst g a\n    ksubst g (PTuple l ps ks)       = PTuple l <$> ksubst g ps <*> ksubst g ks\n    ksubst g (PList l ps p)         = PList l <$> ksubst g ps <*> ksubst g p\n    ksubst g (PParen l p)           = PParen l <$> ksubst g p\n\ninstance KSubst Branch where\n    ksubst g (Branch e ss)          = Branch <$> ksubst g e <*> ksubst g ss\n\ninstance KSubst Handler where\n    ksubst g (Handler ex b)         = Handler ex <$> ksubst g b\n\ninstance KSubst PosPar where\n    ksubst g (PosPar n t e p)       = PosPar n <$> ksubst g t <*> ksubst g e <*> ksubst g p\n    ksubst g (PosSTAR n t)          = PosSTAR n <$> ksubst g t\n    ksubst g PosNIL                 = return PosNIL\n\ninstance KSubst KwdPar where\n    ksubst g (KwdPar n t e k)       = KwdPar n <$> ksubst g t <*> ksubst g e <*> ksubst g k\n    ksubst g (KwdSTAR n t)          = KwdSTAR n <$> ksubst g t\n    ksubst g KwdNIL                 = return KwdNIL\n\ninstance KSubst PosArg where\n    ksubst g (PosArg e p)           = PosArg <$> ksubst g e <*> ksubst g p\n    ksubst g (PosStar e)            = PosStar <$> ksubst g e\n    ksubst g PosNil                 = return PosNil\n\ninstance KSubst KwdArg where\n    ksubst g (KwdArg n e k)         = KwdArg n <$> ksubst g e <*> ksubst g k\n    ksubst g (KwdStar e)            = KwdStar <$> ksubst g e\n    ksubst g KwdNil                 = return KwdNil\n\ninstance KSubst PosPat where\n    ksubst g (PosPat p ps)          = PosPat <$> ksubst g p <*> ksubst g ps\n    ksubst g (PosPatStar p)         = PosPatStar <$> ksubst g p\n    ksubst g PosPatNil              = return PosPatNil\n\ninstance KSubst KwdPat where\n    ksubst g (KwdPat n p ps)        = KwdPat n <$> ksubst g p <*> ksubst g ps\n    ksubst g (KwdPatStar p)         = KwdPatStar <$> ksubst g p\n    ksubst g KwdPatNil              = return KwdPatNil\n\ninstance KSubst OpArg where\n    ksubst g (OpArg op e)           = OpArg op <$> ksubst g e\n\ninstance KSubst Comp where\n    ksubst g (CompFor l p e c)      = CompFor l <$> ksubst g p <*> ksubst g e <*> ksubst g c\n    ksubst g (CompIf l e c)         = CompIf l <$> ksubst g e <*> ksubst g c\n    ksubst g NoComp                 = return NoComp\n\ninstance KSubst WithItem where\n    ksubst g (WithItem e p)         = WithItem <$> ksubst g e <*> ksubst g p\n\ninstance KSubst Elem where\n    ksubst g (Elem e)               = Elem <$> ksubst g e\n    ksubst g (Star e)               = Star <$> ksubst g e\n\ninstance KSubst Assoc where\n    ksubst g (Assoc e1 e2)          = Assoc <$> ksubst g e1 <*> ksubst g e2\n    ksubst g (StarStar e)           = StarStar <$> ksubst g e\n\ninstance KSubst Sliz where\n    ksubst g (Sliz l e1 e2 e3)      = Sliz l <$> ksubst g e1 <*> ksubst g e2 <*> ksubst g e3\n"
  },
  {
    "path": "compiler/lib/src/Acton/LambdaLifter.hs",
    "content": "-- Copyright (C) 2019-2021 Data Ductus AB\n--\n-- Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:\n--\n-- 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.\n--\n-- 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.\n--\n-- 3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission.\n--\n-- THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS \"AS IS\" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n--\n\n{-# LANGUAGE FlexibleInstances #-}\nmodule Acton.LambdaLifter(liftModule) where\n\nimport Control.Monad.State.Strict\nimport Utils\nimport Acton.Syntax\nimport Acton.Names\nimport Acton.Builtin\nimport Acton.Prim\nimport Acton.Printer\nimport Acton.NameInfo\nimport Acton.Env\nimport Acton.QuickType\nimport Acton.Subst\nimport Pretty\nimport Prelude hiding((<>))\n\nliftModule env0 (Module m imp mdoc stmts) = return $ (Module m imp mdoc stmts', mapModules1 conv env0)\n  where stmts' = runL (llSuite (liftEnv env0) stmts)\n\n\n-- L :: list of all local variables and parameters in scope, initially empty (locals)\n-- F :: map of all function names in scope to their (expanded) set of free variables, initially empty (freemap)\n-- N :: map of all function names in scope to their unique aliases, initially empty (namemap)\n\n-- Lambda-lifting\n-- --------------\n-- For each successive statement s in a function body:\n--   If s is a declaration group defining functions fs (classes cannot occur in function bodies):\n--     Let M be a map of each f in fs to its free variables (funfree0)\n--     For each f in fs and each g in M(f) such that M(g) exists: add M(g) to M(f)\n--     Iterate until M reaches a fixpoint (funfree)\n--     For each f in fs and each g in M(f) such that F(g) exists: add F(g) to M(f)\n--     For each f in fs: restrict M(f) to L\n--     Extend F with M\n--     Extend N by mapping each f in fs to a globally unique name\n--     For each def f[q](ws):b in s:\n--       Extend L with ws\n--       Recursively transform b into b'\n--       Add def N(f) [q] (*F(f),ws):b' to the module top level\n--     Replace s with 'pass'\n--   Otherwise s is a non-def statement binding names vs (possibly empty):\n--     Replace any call g@ts(es) in s, where g is in F, by N(g)@ts(*F(g),es)\n--     Replace all non-call references in s to any g@ts in F by lambda ws: g@ts(*F(g),ws), where ws are the parameters of g\n--     Extend L with vs\n\n-- Closure conversion\n-- ------------------\n-- For each successive (non-def) statement s in any lambda-lifted statement list:\n--   Replace any lambda ws: e in s by Lam(vs),\n--     where Lam is a new class name defined as\n--        class Lam (function[x,p,(),t]):\n--            def __init__(self,vs'): self.vs' = vs'\n--            def __call__(self,ws): vs' = self.vs'; return e\n--     and x, p, t and vs' are the parameter row, return type and free variables (restricted to L) of the lambda expression\n--   Replace any call e(es) in s, where e has a closure type (not a known function or method), by e.__call__(es)\n--   Extend L with vs (the variables bound by s)\n\n\n-- Lift monad ----------------------------------------------------------------------------------------------------------\n\ntype LiftM a                    = State LiftState a\n\ntype LiftState                  = ([Decl],[Int])        -- lifted defs, name supply\n\nrunL                            :: LiftM a -> a\nrunL m                          = evalState m ([],[1..])\n\nnewName                         :: String -> LiftM Name\nnewName s                       = state (\\(totop,uniq:supply) -> (Internal LLiftPass s uniq, (totop,supply)))\n\nliftToTop                       :: [Decl] -> LiftM ()\nliftToTop ds                    = state (\\(totop,supply) -> ((), (totop++ds,supply)))\n\nliftedToTop                     :: LiftM [Decl]\nliftedToTop                     = state (\\(totop,supply) -> (totop, ([],supply)))\n\n\nllCont                          = Internal LLiftPass \"cont\" 0\n\nllSelf                          = Internal LLiftPass \"self\" 0\n\n\n-- Environment ---------------------------------------------------------------------------------------------------------\n\ntype LiftEnv                    = EnvF LiftX\n\ndata LiftX                      = LiftX {\n                                    ctxtX     :: LiftCtxt,\n                                    localsX   :: [(Name,Type)],\n                                    freemapX  :: [(Name,[Name])],\n                                    quantmapX :: [(Name,[TVar])],\n                                    namemapX  :: [(Name,Name)]\n                                  }\n                                  deriving (Eq,Show)\n\ndata LiftCtxt                   = OnTop | InDef | InClass deriving (Eq,Show)\n\ninstance Pretty (Name, [Name]) where\n    pretty (n,ns)               = pretty n <+> braces (commaSep pretty ns)\n\n\nliftEnv env0                    = setX env0 LiftX{ ctxtX = OnTop, localsX = [], freemapX = [], quantmapX = [], namemapX = [] }\n\nctxt env                        = ctxtX $ envX env\n\nsetCtxt c env                   = modX env $ \\x -> x{ ctxtX = c }\n\nlocals env                      = localsX $ envX env\nfreemap env                     = freemapX $ envX env\nquantmap env                    = quantmapX $ envX env\nnamemap env                     = namemapX $ envX env\n\nextLocals e env                 = modX env $ \\x -> x{ localsX = vts ++ locals env `exclude` dom vts }\n  where vts                     = [ (v, conv t) | (v,NVar t) <- envOf e ]\n\nextFree m env                   = modX env $ \\x -> x{ freemapX = m ++ freemap env,\n                                                      quantmapX = [ (f, qbound $ quantScope env) | f <- dom m ] ++ quantmap env }\n\nextNames m env                  = modX env $ \\x -> x{ namemapX = m ++ namemap env }\n\nfindFree n env                  = case lookup n (freemap env) of\n                                    Just vs -> Just [ (v,t) | v <- vs, Just t <- [lookup v $ locals env] ]\n                                    _ -> Nothing\n\n\nliftedName env n                = case lookup n (namemap env) of\n                                    Just n' -> n'\n                                    _       -> n\n\nextraArgs env n                 = case findFree n env of\n                                    Just vts -> vts\n                                    _        -> []\n\n\n-- Helpers ------------------------------------------------------------------------------------------------------------------\n\nexpand funfree0 funfree         = map exp1 funfree\n  where exp1 (f,vs)             = (f, nub (concat (vs : catMaybes [ lookup v funfree0 | v <- vs ])))\n\niterexpand funfree\n  | len funfree == len funfree' = funfree\n  | otherwise                   = iterexpand funfree'\n  where funfree'                = expand funfree funfree\n        len                     = map (length . snd)\n\naddParams vts ps                = foldr (\\(n,t) p -> PosPar n (Just t) Nothing p) ps vts\n\naddArgs vts p                   = foldr (PosArg . eVar) p (dom vts)\n\n\n----------------------------------------------------------------------------------------------------------\n\nclass Lift e where\n    ll                                  :: LiftEnv -> e -> LiftM e\n\ninstance Lift a => Lift (Maybe a) where\n    ll env                              = traverse (ll env)\n\ninstance (Lift a, EnvOf a, Vars a) => Lift [a] where\n    ll env []                           = return []\n    ll env (a:as)\n      | ctxt env == InDef               = (:) <$> ll env a <*> ll (extLocals a env1) as\n      | otherwise                       = (:) <$> ll env a <*> ll env1 as\n      where env1                        = define (envOf a) env\n\nllSuite env []                          = return []\nllSuite env (Decl l ds : ss)\n  | ctxt env == InDef                   = do ns <- zip fs <$> mapM (newName . nstr) (bound ds)\n                                             let env1 = extNames ns env'\n                                             ds1 <- ll env1 ds\n                                             liftToTop (vsubst (selfScopeSubst env) ds1)\n                                             llSuite env1 ss\n  | ctxt env == InClass                 = do ds' <- ll env1 ds\n                                             ss' <- llSuite env1 ss\n                                             return $ Decl l ds' : ss'\n  | ctxt env == OnTop                   = do ds1 <- ll env1 ds\n                                             ds2 <- liftedToTop\n                                             ss' <- llSuite env1 ss\n                                             return $ Decl l (ds2++ds1) : ss'\n  where env'                            = extFree funfree $ define (envOf ds) env\n        funfree                         = [ (n, vs \\\\ bound p) | (n,vs) <- funfree1, let p = [ pos d | d <- ds, dname d == n ] ]\n        funfree1                        = expand (freemap env) $ iterexpand funfree0\n        funfree0                        = [ (dname d, nub $ free d) | d@Def{} <- ds ]\n        fs                              = dom funfree0\n        env1                            = define (envOf ds) env\nllSuite env (s : ss)\n  | ctxt env == InDef                   = (:) <$> ll env s <*> llSuite (extLocals s env1) ss\n  | ctxt env == InClass                 = (:) <$> ll env s <*> llSuite env1 ss\n  | ctxt env == OnTop                   = do s' <- ll env s\n                                             ds <- liftedToTop\n                                             ss' <- llSuite env1 ss\n                                             return $ if null ds then s':ss' else Decl l0 ds : s' : ss'\n  where env1                            = define (envOf s) env\n\n\ninstance Lift Stmt where\n    ll env (Return l (Just (Call _ e p KwdNil)))\n      | closedType env e,\n        effect t == fxProc,\n        not (isCont t)                  = do e' <- llSub env e                                  -- A CPS-converted proc, but not a $Cont!\n                                             p' <- ll env p\n                                             return $ Return l $ Just $ Call l (eDot e' attr_exec_) p' KwdNil\n      where t                           = typeOf env e\n    ll env (Expr l e)                   = Expr l <$> ll env e\n    ll env (Assign l pats e)            = Assign l <$> ll env pats <*> ll env e\n    ll env (MutAssign l t e)            = MutAssign l <$> ll env t <*> ll env e\n    ll env (Return l e)                 = Return l <$> ll env e\n    ll env s@(Pass _)                   = pure s\n    ll env s@(Break _)                  = pure s\n    ll env s@(Continue _)               = pure s\n    ll env (If l branches els)          = If l <$> ll env branches <*> llSuite env els\n    ll env (While l e b els)            = While l <$> ll env e <*> llSuite env b <*> llSuite env els\n    ll env (Signature l ns sc Property) = pure $ Signature l ns (conv sc) Property\n    ll env (Signature l ns sc dec)      = pure $ Signature l ns (convTop sc) dec\n    ll env s                            = error (\"ll unexpected: \" ++ prstr s)\n\ninstance Lift Decl where\n    ll env (Def l n q p KwdNIL a b d fx doc)\n                                        = do b' <- llSuite (setCtxt InDef env1) b\n                                             return $ Def l n' q' p' KwdNIL (conv a) b' d fx doc\n      where env1                        = extLocals p $ define (envOf p) $ defineTVars q env\n            q'                          = if ctxt env == InDef then quantScope env ++ q else q\n            p'                          = addParams vts (conv p)\n            n'                          = liftedName env n\n            vts                         = extraArgs env n\n    ll env (Class l n q cs b doc)       = do b' <- llSuite (setCtxt InClass env1) b\n                                             return $ Class l n q (conv cs) b' doc\n      where env1                        = defineTVars (selfQuant (NoQ n) q) env\n    ll env d                            = error (\"ll unexpected: \" ++ prstr d)\n\ninstance Lift Branch where\n    ll env (Branch e ss)                = Branch <$> ll env e <*> llSuite env ss\n\nfreefun env e@(Var l qn@(NoQ n))\n  | Just vts <- findFree n env          = Just (tApp (Var l (NoQ $ liftedName env n)) (map tVar tvs), vts)\n  where Just tvs                        = lookup n (quantmap env)\nfreefun env (Var l n)\n  | isDefOrClass env n                  = Just (Var l (primSubst n), [])\nfreefun env (TApp l e@(Var l' qn@(NoQ n)) ts)\n  | Just vts <- findFree n env          = Just (TApp l (Var l' (NoQ $ liftedName env n)) (map tVar tvs ++ conv ts), vts)\n  where Just tvs                        = lookup n (quantmap env)\nfreefun env (TApp l (Var l' n) ts)\n  | isDefOrClass env n                  = Just (TApp l (Var l' (primSubst n)) (conv ts), [])\nfreefun env e                           = Nothing\n\nclosureConvert env lambda t0 vts0 es    = do n <- newName (nstr $ noq basename)\n                                             --traceM (\"## closureConvert \" ++ prstr lambda ++ \"  as  \" ++ prstr n)\n                                             liftToTop [Class l0 n q bases body Nothing]\n                                             return $ eCall (tApp (eVar n) (map tVar $ qbound q)) es\n  where q                               = quantScope env\n        s                               = selfScopeSubst env\n        Lambda _ p _ e fx               = vsubst s lambda\n        t1                              = vsubst s t0\n        cBase                           = conv $ closureCon fx (prowOf p) t1\n        basename                        = tcname cBase\n        bases                           = map snd $ findAncestry env cBase\n        vts                             = conv $ vsubst s vts0\n        body                            = props ++ [Decl l0 [initDef], Decl l0 defs]\n        props                           = [ Signature l0 [v] (monotype t) Property | (v,t) <- vsubst s vts ]\n        initDef                         = Def l0 initKW [] initPars KwdNIL (Just tNone) (initBody++[sReturn eNone]) NoDec fxPure Nothing\n        initPars                        = PosPar llSelf (Just tSelf) Nothing $ pospar vts\n        initBody                        = mkBody [ MutAssign l0 (eDot (eVar llSelf) v) (eVar v) | (v,t) <- vts ]\n        mainDef attr                    = Def l0 attr [] pars KwdNIL (Just $ conv t1) mainBody NoDec fx Nothing\n        pars                            = conv $ addSelfPar p\n        args                            = pArg p\n        methCall to                     = eCallP (eDot (eVar llSelf) to) args\n        parsC tc                        = conv $ addSelfPar $ addContPar tc p\n        mainBody                        = [ sAssign (pVar v t) (eDot (eVar llSelf) v) | (v,t) <- vts ] ++ [sReturn e]\n        callDef                         = mainDef attr_call_\n        execDef                         = Def l0 attr_exec_ [] pars KwdNIL (Just t1) [ sReturn (methCall attr_call_) ] NoDec fxProc Nothing\n        asynDef                         = mainDef attr_asyn_\n        callDefA                        = Def l0 attr_call_ [] (parsC t1) KwdNIL (Just tR) callBodyA NoDec fxProc Nothing\n        callBodyA                       = [ sReturn $ eCall (tApp (eQVar primAWAIT) [t1]) [eVar llCont, methCall attr_asyn_] ]\n        execDefA                        = delegate attr_exec_ attr_asyn_ tValue\n        evalDef                         = mainDef attr_eval_\n        callDefF                        = delegate attr_call_ attr_eval_ t1\n        execDefF                        = delegate attr_exec_ attr_eval_ tValue\n        delegate name to tc             = Def l0 name [] (parsC tc) KwdNIL (Just tR) (delegateBody to tc) NoDec fxProc Nothing\n        delegateBody to tc              = [ sReturn $ eCall (tApp (eQVar primRCont) [tValue]) [eVar llCont, methCall to] ]\n        defs\n          | basename == primCont        = [callDef]\n          | basename == primProc        = [callDef, execDef]\n          | basename == primAction      = [callDefA, execDefA, asynDef]\n          | basename == primMut         = [callDefF, execDefF, evalDef]\n          | basename == primPure        = [callDefF, execDefF, evalDef]\n\naddSelfPar p                            = PosPar llSelf (Just tSelf) Nothing p\n\naddContPar t p                          = PosPar llCont (Just $ tCont t) Nothing p\n\nclosureCon fx p t\n  | isCont (tFun fx p kwdNil t)         = TC primCont [rtype p]\n  | fx == fxProc                        = TC primProc [rtail p, contArg (rtype p)]\n  | fx == fxAction                      = TC primAction [p,t]\n  | fx == fxMut                         = TC primMut [p,t]\n  | fx == fxPure                        = TC primPure [p,t]\n  | otherwise                           = error (\"### BAD closureCon fx: \" ++ prstr fx)\n  where contArg (TFun _ fx p _ r)       = rtype p\n        contArg t                       = error (\"### BAD contArg \" ++ prstr t)\n\nisCont (TFun _ fx p@TRow{} _ r)         = fx == fxProc && r == tR && rtail p == posNil && not (isCont $ rtype p)\nisCont _                                = False\n\n\ninstance Lift Expr where\n    ll env e@(Var l (NoQ n))\n      | n `elem` dom (locals env)       = pure e\n    ll env e\n      | Just (e',vts) <- freefun env e  = closureConvert env (Lambda l0 par KwdNIL (call e' vts) fx) t vts (map (eVar . fst) vts )\n      where par                         = pPar paramNames p\n            call e' vts                 = Call l0 e' (addArgs vts $ pArg par) KwdNil\n            TFun _ fx p _ t             = typeOf env e\n\n    ll env (Call l e p KwdNil)\n      | Just (e',vts) <- freefun env e  = do p' <- ll env p\n                                             return $ Call l e' (addArgs vts p') KwdNil\n      | Async _ e' <- e,\n        closedType env e'               = do e' <- ll env e'\n                                             p' <- ll env p\n                                             return $ Call l (eDot e' attr_asyn_) p' KwdNil\n      | closedType env e                = do let t@TFun{effect = fx}    = typeOf env e\n                                                 attr | isCont t        = attr_call_\n                                                      | fx == fxProc    = attr_call_\n                                                      | fx == fxMut     = attr_eval_\n                                                      | fx == fxPure    = attr_eval_\n                                                      | fx == fxAction  = attr_asyn_\n                                             e' <- llSub env e\n                                             p' <- ll env p\n                                             return $ Call l (eDot e' attr) p' KwdNil\n      | otherwise                       = do e' <- llSub env e\n                                             p' <- ll env p\n                                             return $ Call l e' p' KwdNil\n\n    ll env (Async l e)\n      | closedType env e                = do e <- ll env e\n                                             let vts = restrict (locals env) (free e)\n                                                 call = Call l0 (eDot e attr_asyn_) (pArg par) KwdNil\n                                             closureConvert env (Lambda l0 par KwdNIL call fxProc) (tMsg t) vts (map (eVar . fst) vts)\n      | otherwise                       = do e <- ll env e\n                                             return $ Async l e\n      where par                         = pPar paramNames p\n            TFun _ fx p _ t             = typeOf env e\n\n    ll env e0@(Lambda l p KwdNIL e fx)  = do e' <- ll env1 e\n                                             let vts = restrict (locals env) (free e' \\\\ bound p)\n                                             closureConvert env (Lambda l p KwdNIL e' fx) t vts (map (eVar . fst) vts)\n      where env1                        = extLocals p $ define (envOf p) env\n            t                           = typeOf env1 e\n\n    ll env (Var l n)                    = pure $ Var l (primSubst n)\n\n    ll env e@Int{}                      = pure e\n    ll env e@Float{}                    = pure e\n    ll env e@Imaginary{}                = pure e\n    ll env e@Bool{}                     = pure e\n    ll env e@None{}                     = pure e\n    ll env e@NotImplemented{}           = pure e\n    ll env e@Ellipsis{}                 = pure e\n    ll env e@Strings{}                  = pure e\n    ll env e@BStrings{}                 = pure e\n    ll env (Cond l e1 e e2)             = Cond l <$> ll env e1 <*> ll env e <*> ll env e2\n    ll env (IsInstance l e c)           = IsInstance l <$> ll env e <*> pure c\n    ll env (BinOp l e1 Or e2)           = BinOp l <$> ll env e1 <*> pure Or <*> ll env e2\n    ll env (BinOp l e1 And e2)          = BinOp l <$> ll env e1 <*> pure And <*> ll env e2\n    ll env (UnOp l Not e)               = UnOp l Not <$> ll env e\n    ll env (TApp _ (Dot l e n) ts)      = llDot env l e n ts\n    ll env (Dot l e n)                  = llDot env l e n []\n    ll env (TApp l e ts)                = TApp l <$> ll env e <*> pure (conv ts)\n    ll env (Let l ss e)                 = Let l <$> ll env1 ss <*> ll env1 e\n        where env1                      = define (envOf ss) env\n    ll env (DotI l e i)                 = DotI l <$> llSub env e <*> pure i\n    ll env (RestI l e i)                = RestI l <$> llSub env e <*> pure i\n    ll env (Yield l e)                  = Yield l <$> ll env e\n    ll env (YieldFrom l e)              = YieldFrom l <$> ll env e\n    ll env (Tuple l es KwdNil)          = Tuple l <$> ll env es <*> pure KwdNil\n    ll env (List l es)                  = List l <$> ll env es\n    ll env (Dict l as)                  = Dict l <$> ll env as\n    ll env (Set l es)                   = Set l <$> ll env es\n    ll env e                            = error (\"ll unexpected: \" ++ prstr e)\n\nllDot env l e n ts\n  | closedType env e0                   = Dot l <$> llSub env e <*> pure n\n  | Var _ x <- e,\n    NClass{} <- findQName x env         = closureConvert env (Lambda l0 par KwdNIL (calldot x n) fx) t [] []\n  | otherwise                           = do e' <- llSub env e\n                                             x <- newName \"obj\"\n                                             closureConvert env (Lambda l0 par KwdNIL (calldot (NoQ x) n) fx) t [(x,t')] [e']\n  where par                             = pPar paramNames p\n        TFun _ fx p _ t                 = typeOf env e0\n        calldot x n                     = Call l0 (eDot (eQVar x) n) (pArg par) KwdNil\n        t'                              = typeOf env e\n        e0                              = tApp (Dot l e n) (conv ts)\n\nllSub                                   :: LiftEnv -> Expr -> LiftM Expr\nllSub env (Var l n)                     = pure $ Var l (primSubst n)\nllSub env (Dot l e n)                   = Dot l <$> llSub env e <*> pure n\nllSub env (TApp l e ts)                 = TApp l <$> llSub env e <*> pure (conv ts)\nllSub env (Async l e)                   = Async l <$> llSub env e\nllSub env e                             = ll env e\n\nprimSubst n\n  | n == primASYNCc                     = primASYNC\n  | n == primAFTERc                     = primAFTER\n  | n == primAWAITc                     = primAWAIT\n  | n == primPUSH_Cc                    = primPUSH_C\n  | n == primPUSHF_Cc                   = primPUSHF_C\n  | n == primRContc                     = primRCont\n  | n == primSKIPRESc                   = primSKIPRES\n  | otherwise                           = n\n\ninstance Lift Elem where\n    ll env (Elem e)                     = Elem <$> ll env e\n    ll env (Star e)                     = Star <$> ll env e\n\ninstance Lift Assoc where\n    ll env (Assoc k v)                  = Assoc <$> ll env k <*> ll env v\n    ll env (StarStar e)                 = StarStar <$> ll env e\n\ninstance Lift PosArg where\n    ll env (PosArg e p)                 = PosArg <$> ll env e <*> ll env p\n    ll env PosNil                       = pure PosNil\n\ninstance Lift Pattern where\n    ll env (PVar l n t)                 = return (PVar l n (conv t))\n\n\n-- Convert environment types -----------------------------------------------------------------------------------------\n\nclass Conv a where\n    conv                                :: a -> a\n\ninstance (Conv a) => Conv (Maybe a) where\n    conv                                = fmap conv\n\ninstance (Conv a) => Conv [a] where\n    conv                                = map conv\n\ninstance (Conv a) => Conv (Name, a) where\n    conv (n, x)                         = (n, conv x)\n\ninstance Conv NameInfo where\n    conv (NClass q ps te doc)           = NClass (conv q) (conv ps) (conv te) doc\n    conv (NSig sc Property doc)         = NSig (conv sc) Property doc\n    conv (NSig sc dec doc)              = NSig (convTop sc) dec doc\n    conv (NDef sc dec doc)              = NDef (convTop sc) dec doc\n    conv (NVar t)                       = NVar (conv t)\n    conv (NSVar t)                      = NSVar (conv t)\n    conv ni                             = ni\n\ninstance Conv QBind where\n    conv (QBind tv cs)                  = QBind tv (conv cs)\n\ninstance Conv WTCon where\n    conv (w,c)                          = (w, conv c)\n\nconvTop (TSchema l q t)                 = TSchema l (conv q) (convTop' t)\n  where convTop' (TFun l fx p TNil{} t) = TFun l (conv fx) (conv p) kwdNil (conv t)\n        convTop' t                      = conv t\n\ninstance Conv TSchema where\n    conv (TSchema l q t)                = TSchema l (conv q) (conv t)\n\ninstance Conv Type where\n    conv t0@(TFun l fx p _ t)           = TCon l (conv $ closureCon fx p t)\n    conv (TCon l c)                     = TCon l (conv c)\n    conv (TTuple l p k)                 = TTuple l (conv p) (conv k)\n    conv (TOpt l t)                     = TOpt l (conv t)\n    conv (TRow l k n t r)               = TRow l k n (conv t) (conv r)\n    conv (TFX l x)                      = TFX l x\n    conv t                              = t\n\ninstance Conv TCon where\n    conv (TC c ts)                      = TC c (conv ts)\n\ninstance Conv PosPar where\n    conv (PosPar n t Nothing p)         = PosPar n (conv t) Nothing (conv p)\n    conv PosNIL                         = PosNIL\n"
  },
  {
    "path": "compiler/lib/src/Acton/NameInfo.hs",
    "content": "-- Copyright (C) 2019-2021 Data Ductus AB\n--\n-- Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:\n--\n-- 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.\n--\n-- 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.\n--\n-- 3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission.\n--\n-- THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS \"AS IS\" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n--\n\n{-# LANGUAGE FlexibleInstances, FlexibleContexts, DeriveGeneric, DeriveAnyClass #-}\nmodule Acton.NameInfo where\n\nimport Control.DeepSeq\nimport qualified Data.Binary\nimport GHC.Generics (Generic)\nimport Data.Typeable\nimport qualified Data.HashMap.Strict as M\nimport Prelude hiding ((<>))\n\nimport Utils\nimport Acton.Syntax\nimport Acton.Builtin\nimport Acton.Names\nimport Acton.Subst\nimport Acton.Printer\n\n\n-- NameInfo -----------------------------------------------------------------------------------------------\n\n{-  TEnv principles:\n    -   A TEnv is an association of NameInfo details to a list of names.\n    -   NSig holds the schema of an explicit Signature, while NDef and NVar give schemas and types to names created by Defs and assignments.\n    -   NClass, NProto, NExt and NAct represent class, protocol, extension and actor declarations. They each contain a TEnv of visible local attributes.\n    -   Signatures must appear before the defs/assignments they describe, and every TEnv respects the order of the syntactic constructs binding each name.\n    -   The attribute TEnvs of NClass, NProto, NExt and NAct are searched left-to-right, thus favoring (explicit) NSigs over (inferred) NDefs/NVars.\n    -   The global inference environment is searched from active names to closed names, thereby prioritizing NDefs/NVars over NSigs, as well as any inner bindings in scope.\n    -   The NameInfo assumption on a (recursive) Def is always an NDef, initialized to the corresponding NSig if present, or a fresh unquantified variable.\n    -   The inferred schema for each def is checked to be no less general than the corresponding NDef assumption.\n    -   Unquantified NDefs are generalized at the close of the outermost recursive declaration in scope.\n    -   An NSig is always fully quantified, not possible to generalize\n    -   To enable method override (and disable method signature override), the NSigs of parent class are inserted into the global env when checking a child class\n    -   For the same reason, NDefs and NVars without an NSig of a parent class are inserted as NSigs when a child class is checked\n-}\n\ntype TEnv               = [(Name, NameInfo)]\n\ndata NameInfo           = NVar      Type\n                        | NSVar     Type\n                        | NDef      TSchema Deco (Maybe String)\n                        | NSig      TSchema Deco (Maybe String)\n                        | NAct      QBinds PosRow KwdRow TEnv (Maybe String)\n                        | NClass    QBinds [WTCon] TEnv (Maybe String)\n                        | NProto    QBinds [WTCon] TEnv (Maybe String)\n                        | NExt      QBinds TCon [WTCon] TEnv [Name] (Maybe String)\n                        | NTVar     Kind CCon [PCon]\n                        | NAlias    QName\n                        | NMAlias   ModName\n                        | NModule   [ModName] TEnv (Maybe String)\n                        | NReserved\n                        deriving (Eq,Show,Read,Generic,NFData)\n\ntypeDecl (_,NDef{})     = False\ntypeDecl _              = True\n\ntype HTEnv            =  M.HashMap Name HNameInfo\n\ndata HNameInfo          = HNVar      Type\n                        | HNSVar     Type\n                        | HNDef      TSchema Deco (Maybe String)\n                        | HNSig      TSchema Deco (Maybe String)\n                        | HNAct      QBinds PosRow KwdRow TEnv (Maybe String)\n                        | HNClass    QBinds [WTCon] TEnv (Maybe String)\n                        | HNProto    QBinds [WTCon] TEnv (Maybe String)\n                        | HNExt      QBinds TCon [WTCon] TEnv [Name] (Maybe String)\n                        | HNTVar     Kind CCon [PCon]\n                        | HNAlias    QName\n                        | HNMAlias   ModName\n                        | HNModule   [ModName] HTEnv (Maybe String)\n                        | HNReserved\n                        deriving (Eq, Show, Read, Generic)\n\ninstance Data.Binary.Binary NameInfo\n\nconvNameInfo2HNameInfo               :: NameInfo -> HNameInfo\nconvNameInfo2HNameInfo (NModule ms te mdoc)   = HNModule ms (convTEnv2HTEnv te) mdoc\nconvNameInfo2HNameInfo (NVar t)               = HNVar t\nconvNameInfo2HNameInfo (NSVar t)              = HNSVar t\nconvNameInfo2HNameInfo (NDef sc dec mdoc)     = HNDef sc dec mdoc\nconvNameInfo2HNameInfo (NSig sc dec mdoc)     = HNSig sc dec mdoc\nconvNameInfo2HNameInfo (NAct q p k te mdoc)   = HNAct q p k te mdoc\nconvNameInfo2HNameInfo (NClass q ws te mdoc)  = HNClass q ws te mdoc\nconvNameInfo2HNameInfo (NProto q ws te mdoc)  = HNProto q ws te mdoc\nconvNameInfo2HNameInfo (NExt q tc ws te ns mdoc) = HNExt q tc ws te ns mdoc\nconvNameInfo2HNameInfo (NTVar k c ps)         = HNTVar k c ps\nconvNameInfo2HNameInfo (NAlias qn)            = HNAlias qn\nconvNameInfo2HNameInfo (NMAlias mn)           = HNMAlias mn\nconvNameInfo2HNameInfo (NReserved)            = HNReserved\n\nconvHNameInfo2NameInfo               :: HNameInfo -> NameInfo\nconvHNameInfo2NameInfo (HNModule ms te mdoc)   = NModule ms (convHTEnv2TEnv te) mdoc\nconvHNameInfo2NameInfo (HNVar t)               = NVar t\nconvHNameInfo2NameInfo (HNSVar t)              = NSVar t\nconvHNameInfo2NameInfo (HNDef sc dec mdoc)     = NDef sc dec mdoc\nconvHNameInfo2NameInfo (HNSig sc dec mdoc)     = NSig sc dec mdoc\nconvHNameInfo2NameInfo (HNAct q p k te mdoc)   = NAct q p k te mdoc\nconvHNameInfo2NameInfo (HNClass q ws te mdoc)  = NClass q ws te mdoc\nconvHNameInfo2NameInfo (HNProto q ws te mdoc)  = NProto q ws te mdoc\nconvHNameInfo2NameInfo (HNExt q tc ws te ns mdoc) = NExt q tc ws te ns mdoc\nconvHNameInfo2NameInfo (HNTVar k c ps)         = NTVar k c ps\nconvHNameInfo2NameInfo (HNAlias qn)            = NAlias qn\nconvHNameInfo2NameInfo (HNMAlias mn)           = NMAlias mn\nconvHNameInfo2NameInfo (HNReserved)            = NReserved\n\nconvTEnv2HTEnv                       :: TEnv -> HTEnv\nconvTEnv2HTEnv te                     = M.fromList (map convPair te)\n  where\n     convPair (n, ni)      = (n, convNameInfo2HNameInfo ni)\n\nconvHTEnv2TEnv                       :: HTEnv -> TEnv\nconvHTEnv2TEnv te                     = map convPair (M.toList te)\n  where\n     convPair (n, hni)      = (n, convHNameInfo2NameInfo hni)\n\n-- | Strip all docstrings from NameInfo (and nested environments).\n-- This is used when computing a public-interface hash so that\n-- documentation-only edits do not cause dependents to rebuild.\nstripDocsNI :: NameInfo -> NameInfo\nstripDocsNI ni = case ni of\n  NModule ms te _     -> NModule ms (map stripBind te) Nothing\n  NAct q p k te _     -> NAct q p k (map stripBind te) Nothing\n  NClass q cs te _    -> NClass q cs (map stripBind te) Nothing\n  NProto q ps te _    -> NProto q ps (map stripBind te) Nothing\n  NExt q c ps te o _  -> NExt q c ps (map stripBind te) o Nothing\n  NDef sc dec _       -> NDef sc dec Nothing\n  NSig sc dec _       -> NSig sc dec Nothing\n  other               -> other\n  where\n    stripBind (n, info) = (n, stripDocsNI info)\n\n-- | Strip source locations from NameInfo (and nested syntax fragments).\n-- This keeps public interface hashes independent from whitespace-only source\n-- edits while preserving locations in the cached .ty payload itself.\nstripLocsNI :: NameInfo -> NameInfo\nstripLocsNI ni = case ni of\n  NVar t             -> NVar (stripLocsType t)\n  NSVar t            -> NSVar (stripLocsType t)\n  NDef sc dec doc    -> NDef (stripLocsTSchema sc) dec doc\n  NSig sc dec doc    -> NSig (stripLocsTSchema sc) dec doc\n  NAct q p k te doc  -> NAct (stripLocsQBinds q) (stripLocsType p) (stripLocsType k) (stripLocsTEnv te) doc\n  NClass q cs te doc -> NClass (stripLocsQBinds q) (map stripLocsWTCon cs) (stripLocsTEnv te) doc\n  NProto q ps te doc -> NProto (stripLocsQBinds q) (map stripLocsWTCon ps) (stripLocsTEnv te) doc\n  NExt q c ps te o doc ->\n    NExt (stripLocsQBinds q) (stripLocsTCon c) (map stripLocsWTCon ps) (stripLocsTEnv te) (map stripLocsName o) doc\n  NTVar k c ps       -> NTVar k (stripLocsTCon c) (map stripLocsTCon ps)\n  NAlias qn          -> NAlias (stripLocsQName qn)\n  NMAlias mn         -> NMAlias (stripLocsModName mn)\n  NModule ms te doc  -> NModule ms (stripLocsTEnv te) doc\n  NReserved          -> NReserved\n  where\n    stripLocsTEnv :: TEnv -> TEnv\n    stripLocsTEnv = map $ \\(n, info) -> (stripLocsName n, stripLocsNI info)\n\n    stripLocsTSchema :: TSchema -> TSchema\n    stripLocsTSchema (TSchema _ q t) = TSchema NoLoc (stripLocsQBinds q) (stripLocsType t)\n\n    stripLocsQBinds :: QBinds -> QBinds\n    stripLocsQBinds = map stripLocsQBind\n\n    stripLocsQBind :: QBind -> QBind\n    stripLocsQBind (QBind tv cs) = QBind (stripLocsTVar tv) (map stripLocsTCon cs)\n\n    stripLocsTVar :: TVar -> TVar\n    stripLocsTVar (TV k n) = TV k (stripLocsName n)\n\n    stripLocsTCon :: TCon -> TCon\n    stripLocsTCon (TC qn ts) = TC (stripLocsQName qn) (map stripLocsType ts)\n\n    stripLocsWTCon :: WTCon -> WTCon\n    stripLocsWTCon (wpath, pcon) = (map stripLocsWStep wpath, stripLocsTCon pcon)\n\n    stripLocsWStep :: Either QName QName -> Either QName QName\n    stripLocsWStep (Left qn) = Left (stripLocsQName qn)\n    stripLocsWStep (Right qn) = Right (stripLocsQName qn)\n\n    stripLocsType :: Type -> Type\n    stripLocsType t = case t of\n      TUni _ u          -> TUni NoLoc u\n      TVar _ tv         -> TVar NoLoc (stripLocsTVar tv)\n      TCon _ tc         -> TCon NoLoc (stripLocsTCon tc)\n      TFun _ fx p k r   -> TFun NoLoc (stripLocsType fx) (stripLocsType p) (stripLocsType k) (stripLocsType r)\n      TTuple _ p k      -> TTuple NoLoc (stripLocsType p) (stripLocsType k)\n      TOpt _ opt        -> TOpt NoLoc (stripLocsType opt)\n      TNone _           -> TNone NoLoc\n      TWild _           -> TWild NoLoc\n      TNil _ k          -> TNil NoLoc k\n      TRow _ k n ty row -> TRow NoLoc k (stripLocsName n) (stripLocsType ty) (stripLocsType row)\n      TStar _ k row     -> TStar NoLoc k (stripLocsType row)\n      TFX _ fx          -> TFX NoLoc fx\n\n    stripLocsQName :: QName -> QName\n    stripLocsQName qn = case qn of\n      QName mn n -> QName (stripLocsModName mn) (stripLocsName n)\n      NoQ n      -> NoQ (stripLocsName n)\n      GName mn n -> GName (stripLocsModName mn) (stripLocsName n)\n\n    stripLocsModName :: ModName -> ModName\n    stripLocsModName (ModName ns) = ModName (map stripLocsName ns)\n\n    stripLocsName :: Name -> Name\n    stripLocsName n = case n of\n      Name _ s       -> Name NoLoc s\n      Derived n1 n2  -> Derived (stripLocsName n1) (stripLocsName n2)\n      Internal{}     -> n\n\ninstance Leaves NameInfo where\n    leaves (NClass q cs te _) = leaves q ++ leaves cs ++ leaves te\n    leaves (NProto q ps te _) = leaves q ++ leaves ps ++ leaves te\n    leaves (NAct q p k te _)  = leaves q ++ leaves [p,k] ++ leaves te\n    leaves (NExt q c ps te _ _) = leaves q ++ leaves c ++ leaves ps ++ leaves te\n    leaves (NDef sc dec _)    = leaves sc\n    leaves _                  = []\n\ninstance Pretty TEnv where\n    pretty tenv               = vcat (map pretty $ normTEnv tenv)\n      where normTEnv te       = f [] te\n              where\n                  f ns []          = []\n                  f ns ((n,i):te)\n                    | n `elem` ns  = f ns te\n                    | otherwise    = (n,i) : f (n:ns) te\n\n\ninstance Pretty (Name,NameInfo) where\n    pretty (n, NVar t)          = pretty n <+> colon <+> pretty t\n    pretty (n, NSVar t)         = text \"var\" <+> pretty n <+> colon <+> pretty t\n    pretty (n, NDef t d doc)    = prettyDec d $ pretty n <+> colon <+> pretty t $+$ nest 4 (prettyDocstring doc)\n    pretty (n, NSig t d doc)    = prettyDec d $ pretty n <+> colon <+> pretty t $+$ nest 4 (prettyDocstring doc)\n    pretty (n, NAct q p k te doc)\n                                = text \"actor\" <+> pretty n <> nonEmpty brackets commaList q <+>\n                                  parens (prettyFunRow p k) <> colon $+$ nest 4 (prettyDocstring doc) $+$ (nest 4 $ prettyOrPass te)\n    pretty (n, NClass q us te doc)\n                                = text \"class\" <+> pretty n <> nonEmpty brackets commaList q <+>\n                                  nonEmpty parens commaList us <> colon $+$ nest 4 (prettyDocstring doc) $+$ (nest 4 $ prettyOrPass te)\n    pretty (n, NProto q us te doc)\n                                = text \"protocol\" <+> pretty n <> nonEmpty brackets commaList q <+>\n                                  nonEmpty parens commaList us <> colon $+$ nest 4 (prettyDocstring doc) $+$ (nest 4 $ prettyOrPass te)\n    pretty (w, NExt [] c ps te opts doc)\n                                = {-pretty w  <+> colon <+> -}\n                                  text \"extension\" <+> pretty c <+> parens (commaList ps) <>\n                                  colon $+$ nest 4 (prettyDocstring doc) $+$ (nest 4 $ prettyOrPass te)\n    pretty (w, NExt q c ps te opts doc)\n                                = {-pretty w  <+> colon <+> -}\n                                  text \"extension\" <+> pretty q <+> text \"=>\" <+> pretty c <+> parens (commaList ps) <>\n                                  colon $+$ nest 4 (prettyDocstring doc) $+$ (nest 4 $ prettyOrPass te)\n    pretty (n, NTVar k c ps)    = pretty n <> parens (commaList (c:ps))\n    pretty (n, NAlias qn)       = text \"alias\" <+> pretty n <+> equals <+> pretty qn\n    pretty (n, NMAlias m)       = text \"module\" <+> pretty n <+> equals <+> pretty m\n    pretty (n, NModule ms te doc)\n                                = text \"module\" <+> pretty n <> colon $+$ \n                                  nest 4 (vcat [ text \"import\" <+> pretty m | m <- ms ]) $+$\n                                  nest 4 (prettyDocstring doc) $+$\n                                  nest 4 (pretty te)\n    pretty (n, NReserved)       = pretty n <+> text \"(reserved)\"\n\nprettyOrPass te\n  | isEmpty doc                 = text \"pass\"\n  | otherwise                   = doc\n  where doc                     = pretty te\n\nprettyDocstring :: Maybe String -> Doc\nprettyDocstring Nothing         = empty\nprettyDocstring (Just docstring) = text \"\\\"\\\"\\\"\" <> text docstring <> text \"\\\"\\\"\\\"\"\n\ninstance VFree NameInfo where\n    vfree (NVar t)              = vfree t\n    vfree (NSVar t)             = vfree t\n    vfree (NDef t d _)          = vfree t\n    vfree (NSig t d _)          = vfree t\n    vfree (NAct q p k te _)     = (vfree q ++ vfree p ++ vfree k ++ vfree te) \\\\ (tvSelf : qbound q)\n    vfree (NClass q us te _)    = (vfree q ++ vfree us ++ vfree te) \\\\ (tvSelf : qbound q)\n    vfree (NProto q us te _)    = (vfree q ++ vfree us ++ vfree te) \\\\ (tvSelf : qbound q)\n    vfree (NExt q c ps te _ _)  = (vfree q ++ vfree c ++ vfree ps ++ vfree te) \\\\ (tvSelf : qbound q)\n    vfree (NTVar k c ps)        = vfree c ++ vfree ps\n    vfree (NAlias qn)           = []\n    vfree (NMAlias qn)          = []\n    vfree (NModule ms te doc)   = []        -- actually vfree te, but a module has no free variables on the top level\n    vfree NReserved             = []\n\ninstance VSubst NameInfo where\n    vsubst s (NVar t)           = NVar (vsubst s t)\n    vsubst s (NSVar t)          = NSVar (vsubst s t)\n    vsubst s (NDef t d x)       = NDef (vsubst s t) d x\n    vsubst s (NSig t d x)       = NSig (vsubst s t) d x\n    vsubst s (NAct q p k te x)  = NAct (vsubst s q) (vsubst s p) (vsubst s k) (vsubst s te) x\n    vsubst s (NClass q us te x) = NClass (vsubst s q) (vsubst s us) (vsubst s te) x\n    vsubst s (NProto q us te x) = NProto (vsubst s q) (vsubst s us) (vsubst s te) x\n    vsubst s (NExt q c ps te opts x) = NExt (vsubst s q) (vsubst s c) (vsubst s ps) (vsubst s te) opts x\n    vsubst s (NTVar k c ps)        = NTVar k (vsubst s c) (vsubst s ps)\n    vsubst s (NAlias qn)        = NAlias qn\n    vsubst s (NMAlias m)        = NMAlias m\n    vsubst s (NModule ms te x)  = NModule ms te x        -- actually vsubst s te, but te has no free variables (top-level)\n    vsubst s NReserved          = NReserved\n\ninstance UFree NameInfo where\n    ufree (NVar t)              = ufree t\n    ufree (NSVar t)             = ufree t\n    ufree (NDef t d _)          = ufree t\n    ufree (NSig t d _)          = ufree t\n    ufree (NAct q p k te _)     = ufree q ++ ufree p ++ ufree k ++ ufree te\n    ufree (NClass q us te _)    = ufree q ++ ufree us ++ ufree te\n    ufree (NProto q us te _)    = ufree q ++ ufree us ++ ufree te\n    ufree (NExt q c ps te _ _)  = ufree q ++ ufree c ++ ufree ps ++ ufree te\n    ufree (NTVar k c ps)        = ufree c ++ ufree ps\n    ufree (NAlias qn)           = []\n    ufree (NMAlias qn)          = []\n    ufree (NModule ms te doc)   = []        -- actually ufree te, but a module has no free variables on the top level\n    ufree NReserved             = []\n\ninstance Polarity (Name,NameInfo) where\n    polvars (n, i)              = polvars i\n\ninstance Polarity NameInfo where\n    polvars (NVar t)            = polvars t\n    polvars (NSVar t)           = invvars t\n    polvars (NDef t d _)        = polvars t\n    polvars (NSig t d _)        = polvars t\n    polvars (NAct q p k te _)   = polvars q `polcat` polneg (polvars p `polcat` polvars k) `polcat` polvars te\n    polvars (NClass q us te _)  = polvars q `polcat` polvars us `polcat` polvars te\n    polvars (NProto q us te _)  = polvars q `polcat` polvars us `polcat` polvars te\n    polvars (NExt q c ps te _ _) = polvars q `polcat` polvars c `polcat` polvars ps `polcat` polvars te\n    polvars (NTVar k c ps)      = polvars c `polcat` polvars ps\n    polvars _                   = ([],[])\n\ninstance Tailvars (Name, NameInfo) where\n    tailvars (n, NVar t)        = tailvars t\n    tailvars (n, NSVar t)       = tailvars t\n    tailvars (n, NDef sc _ _)   = tailvars sc\n    tailvars _                  = []\n\nwildargs i                      = [ tWild | _ <- nbinds i ]\n  where\n    nbinds (NAct q _ _ _ _)     = q\n    nbinds (NClass q _ _ _)     = q\n    nbinds (NProto q _ _ _)     = q\n    nbinds (NExt q _ _ _ _ _)   = q\n\n-- TEnv filters --------------------------------------------------------------------------------------------------------\n\nnSigs                       :: TEnv -> TEnv\nnSigs te                    = [ (n,i) | (n, i@(NSig sc dec _)) <- te, not $ isProp dec sc ]\n\npropSigs                    :: TEnv -> TEnv\npropSigs te                 = [ (n,i) | (n, i@(NSig sc dec _)) <- te, isProp dec sc ]\n\nisProp                      :: Deco -> TSchema -> Bool\nisProp Property _           = True\nisProp NoDec sc             = case sctype sc of TFun{} -> False; _ -> True\nisProp _ _                  = False\n\nnTerms                      :: TEnv -> TEnv\nnTerms te                   = [ (n,i) | (n,i) <- te, isNTerm i ]\n\nisNTerm NDef{}              = True\nisNTerm NVar{}              = True\nisNTerm _                   = False\n\nsigTerms                    :: TEnv -> (TEnv, TEnv)\nsigTerms te                 = (nSigs te, nTerms te)\n\nnoDefs                      :: TEnv -> TEnv\nnoDefs te                   = [ (n,i) | (n,i) <- te, keep i ]\n  where keep NDef{}         = False\n        keep NAct{}         = False\n        keep _              = True\n\nunSig                       :: TEnv -> TEnv\nunSig te                    = map f te\n  where f (n, NSig (TSchema _ [] t) Property _) = (n, NVar t)\n        f (n, NSig sc@(TSchema _ _ TFun{}) dec doc)\n                                                = (n, NDef sc dec doc)\n        f (n, NSig (TSchema _ _ t) _ _)         = (n, NVar t)\n        f (n, i)                                = (n, i)\n\n\n-- Witnesses -----------------------------------------------------------------------------------------------\n\ndata Witness            = WClass    { binds::QBinds, wtype::Type, proto::PCon, wname::QName, wsteps::WPath, wopts::Int }\n                        | WInst     { binds::QBinds, wtype::Type, proto::PCon, wname::QName, wsteps::WPath }\n                        deriving (Show)\n\ntype WPath              = [Either QName QName]\n\ntype WTCon              = (WPath,PCon)\n\nwexpr                   :: WPath -> Expr -> Expr\nwexpr [] e              = e\nwexpr (Left _ : w) e    = wexpr w e\nwexpr (Right n : w) e   = wexpr w $ eDot e (witAttr n)\n\n\ninstance Pretty Witness where\n    pretty (WClass q t p w ws _)\n                        = text \"WClass\" <+> prettyQual q <+> pretty t <+> parens (pretty p) <+>\n                          equals <+> pretty (wexpr ws (eCall (eQVar w) []))\n    pretty (WInst q t p w ws)\n                        = text \"WInst\" <+> prettyQual q <+> pretty t <+> parens (pretty p) <+>\n                          equals <+> pretty (wexpr ws (eQVar w))\n\ninstance UFree Witness where\n    ufree w@WClass{}    = []\n    ufree w@WInst{}     = ufree (wtype w) ++ ufree (proto w)\n\n\ninstance Leaves WTCon where\n    leaves (wp,p)       = leaves p\n\ninstance VFree WTCon where\n    vfree (wpath, p)    = vfree p\n\ninstance UFree WTCon where\n    ufree (wpath, p)    = ufree p\n\ninstance Tailvars WTCon where\n    tailvars (wpath, p) = tailvars p\n\ninstance VSubst WTCon where\n    vsubst s (w,u)      = (w, vsubst s u)\n\ninstance Vars WTCon where\n    freeQ (wpath, p)    = freeQ p\n\ninstance Vars NameInfo where\n    freeQ ni = case ni of\n      NVar t -> freeQ t\n      NSVar t -> freeQ t\n      NDef sc _ _ -> freeQ sc\n      NSig sc _ _ -> freeQ sc\n      NAct q p k te _ -> freeQ q ++ freeQ p ++ freeQ k ++ freeQTEnv te\n      NClass q ws te _ -> freeQ q ++ freeQWTCons ws ++ freeQTEnv te\n      NProto q ws te _ -> freeQ q ++ freeQWTCons ws ++ freeQTEnv te\n      NExt q c ws te _ _ -> freeQ q ++ freeQ c ++ freeQWTCons ws ++ freeQTEnv te\n      NTVar _ c ps -> freeQ c ++ freeQ ps\n      NAlias qn -> freeQ qn\n      NMAlias _ -> []\n      NModule ms te _ -> freeQTEnv te\n      NReserved -> []\n      where\n        freeQTEnv :: TEnv -> [QName]\n        freeQTEnv tenv = concatMap (freeQ . snd) tenv\n\n        freeQWTCons :: [WTCon] -> [QName]\n        freeQWTCons = concatMap freeQWTCon\n\n        freeQWTCon :: WTCon -> [QName]\n        freeQWTCon (wpath, pcon) = freeQWPath wpath ++ freeQ pcon\n\n        freeQWPath :: WPath -> [QName]\n        freeQWPath = concatMap step\n          where\n            step (Left qn) = freeQ qn\n            step (Right qn) = freeQ qn\n\ninstance UWild WTCon where\n    uwild (wpath, p)    = (wpath, uwild p)\n\ninstance Pretty WTCon where\n    pretty (wpath, p)   = pretty p\n\ninstance Polarity WTCon where\n    polvars (w, c)      = polvars c\n"
  },
  {
    "path": "compiler/lib/src/Acton/Names.hs",
    "content": "-- Copyright (C) 2019-2021 Data Ductus AB\n--\n-- Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:\n--\n-- 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.\n--\n-- 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.\n--\n-- 3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission.\n--\n-- THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS \"AS IS\" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n--\n\n{-# LANGUAGE FlexibleInstances #-}\nmodule Acton.Names where\n\nimport Utils\nimport Acton.Syntax\nimport Acton.Builtin\nimport Debug.Trace\n\n\nisWitness (Internal Witness _ _)    = True\nisWitness _                         = False\n\nisInternal (Internal _ _ _)         = True\nisInternal _                        = False\n\nisUnboxed (Internal BoxPass _ _)    = True\nisUnboxed _                         = False\n\n\nself                                = Name NoLoc \"self\"\n\nlocalName n                         = Derived n suffixLocal\nnewactName n                        = Derived n suffixNewact\n\nselfKW'                             = Internal Witness \"self\" 0\nthisKW'                             = Internal Witness \"this\" 0\n\ng_self                              = globalName \"self\"\n\ng_act                               = globalName \"act\"\ng_skip                              = globalName \"skip\"\n\naltInit                             = globalName \"init\"\n\nsuffixLocal                         = globalName \"local\"\nsuffixNewact                        = globalName \"newact\"\nsuffixClass                         = globalName \"class\"\nsuffixMethods                       = globalName \"methods\"\nsuffixNew                           = globalName \"new\"\nsuffixWitness                       = globalName \"witness\"\n\nparamNames                          = globalNames \"\"\npNames                              = globalNames \"p\"\nxNames                              = globalNames \"x\"\nyNames                              = globalNames \"y\"\ntmpNames                            = globalNames \"tmp\"\n\nattrKW                              = globalName \"kw\"\n\n\nderiveQ (NoQ n)                     = n\nderiveQ (QName (ModName m) n)       = deriveMod n m\nderiveQ (GName m n)\n  | m == mBuiltin                   = n\nderiveQ (GName (ModName m) n)       = deriveMod n m\n\nderiveMod n0 []                     = n0\nderiveMod n0 (n:m)                  = deriveMod (Derived n0 n) m\n\nderiveT (TVar _ v)                  = tvname v\nderiveT (TCon _ c)                  = deriveQ (tcname c)\n\nwitAttr qn                          = Internal Witness (nstr $ deriveQ qn) 0\n\nextensionName [] c                  = Derived (globalName \"ext\") (deriveQ $ tcname c)\nextensionName (p:_) c\n  | length ts == length vs          = n0\n  | otherwise                       = foldl Derived n0 (map deriveT ts)\n  where ts                          = tcargs c\n        vs                          = [ v | TVar _ v <- ts ]\n        n0                          = Derived (deriveQ $ tcname p) (deriveQ $ tcname c)\n\n\n-- Mutually recursive groups -------\n\ndeclnames (Extension{} : ds)        = declnames ds\ndeclnames (d : ds)                  = dname d : declnames ds\ndeclnames []                        = []\n\ndname' (Extension _ _ c us _ _)     = extensionName us c\ndname' d                            = dname d\n\nsplitDeclGroup []                   = []\nsplitDeclGroup (d:ds)               = join $ split (free d) [d] ds\n  where split vs ds0 []             = [reverse ds0]\n        split vs ds0 (d:ds)\n          | any (`elem` ws) vs      = split (free d++vs) (d:ds0) ds\n          | otherwise               = reverse ds0 : split (free d) [d] ds\n          where ws                  = declnames (d:ds)\n        join []                     = []\n        join dss\n          | not $ null dss1         = concat dss1 : join dss2\n          where (dss1,dss2)         = span (all tydecl) dss\n                tydecl Def{}        = False\n                tydecl _            = True\n        join (ds:dss)               = ds : join dss\n\n\n-- Data variables ------------------\n\nclass DataVars a where\n    datavars                        :: Int -> a -> [Name]      -- Variables in any lhs data pattern, with minimum arity\n\ninstance DataVars a => DataVars [a] where\n    datavars n                      = concatMap (datavars n)\n\ninstance DataVars Stmt where\n    datavars n (Assign _ ps _)      = datavars n ps\n    datavars n (Data _ p b)         = maybe [] (datavars n) p\n    datavars n (While _ e b els)    = datavars n b ++ datavars n els\n    datavars n (For _ p e b els)    = datavars n b ++ datavars n els\n    datavars n (If _ bs els)        = concatMap (datavars n) bs ++ datavars n els\n    datavars n _                    = []\n\ninstance DataVars Branch where\n    datavars n (Branch e ss)        = datavars n ss\n\ninstance DataVars Pattern where\n    datavars n (PTuple _ ps ks)     = bound ps ++ bound ks\n    datavars n (PList _ ps p)       = bound ps ++ bound p\n    datavars n (PParen _ p)         = bound p\n    datavars n (PData _ v ixs)\n      | length ixs >= n             = [v]\n    datavars n _                    = []\n\n\n-- Special attributes variables ----\n\nmethods b                           = [ n | Decl _ ds <- b, Def{dname=n} <- ds ]\n\nstatevars b                         = concat [ bound ps | VarAssign _ ps _ <- b ]\n\n\nisHidden n@(Name _ str)             = length (takeWhile (=='_') str) == 1 || n == resumeKW || n == cleanupKW\nisHidden _                          = True\n\nnotHidden                           = filter (not . isHidden)\n\nisPrivateName                       :: Name -> Bool\nisPrivateName n                     = case nstr n of\n                                        ('_':_) -> True\n                                        _       -> False\n\nisPublicName                        :: Name -> Bool\nisPublicName                        = not . isPrivateName\n\n\n-- Free and bound names ------------\n\nclass Vars a where\n    free                            :: a -> [Name]\n    freeQ                           :: a -> [QName]\n    bound                           :: a -> [Name]\n\n    free x                          = free $ freeQ x\n    freeQ x                         = []\n    bound x                         = []\n\nqns `diffQ` ns                      = filter f qns\n  where f (NoQ n)                   = n `notElem` ns\n        f _                         = True\n\ninstance Vars a => Vars [a] where\n    free                            = concatMap free\n    freeQ                           = concatMap freeQ\n    bound                           = concatMap bound\n\ninstance Vars a => Vars (Maybe a) where\n    free                            = maybe [] free\n    freeQ                           = maybe [] freeQ\n    bound                           = maybe [] bound\n\ninstance Vars Stmt where\n    freeQ (Expr _ e)                = freeQ e\n    freeQ (Assign _ ps e)           = freeQ ps ++ freeQ e\n    freeQ (MutAssign _ t e)         = freeQ t ++ freeQ e\n    freeQ (AugAssign _ t op e)      = freeQ t ++ freeQ e\n    freeQ (Assert _ e mbe)          = freeQ e ++ freeQ mbe\n    freeQ (Pass _)                  = []\n    freeQ (Delete _ t)              = freeQ t\n    freeQ (Return _ e)              = freeQ e\n    freeQ (Raise _ e)               = freeQ e\n    freeQ (Break _)                 = []\n    freeQ (Continue _)              = []\n    freeQ (If _ branches els)       = freeQ branches ++ freeQ els\n    freeQ (While _ e b els)         = freeQ e ++ freeQ b ++ freeQ els\n    freeQ (For _ p e b els)         = freeQ p ++ freeQ e ++ (freeQ b `diffQ` bound p) ++ freeQ els\n    freeQ (Try _ b hs els fin)      = freeQ b ++ freeQ hs ++ freeQ els ++ freeQ fin\n    freeQ (With _ items b)          = freeQ items ++ (freeQ b `diffQ` bound items)\n    freeQ (Data _ p b)              = freeQ p ++ freeQ b\n    freeQ (VarAssign _ ps e)        = freeQ ps ++ freeQ e\n    freeQ (After _ e e')            = freeQ e ++ freeQ e'\n    freeQ (Decl _ ds)               = freeQ ds\n    freeQ (Signature _ ns t d)      = freeQ t\n\n    bound (Assign _ ps _)           = bound ps\n    bound (VarAssign _ ps e)        = bound ps\n    bound (AugAssign _ t _ e)       = free t\n    bound (Decl _ ds)               = bound ds\n    bound (Signature _ ns t d)      = ns\n    bound (If _ bs els)             = bound bs ++ bound els\n    bound (While _ _ b els)         = bound b ++ bound els\n    bound (With _ items b)          = bound b\n    bound _                         = []\n\n\nassigned stmts                      = concatMap assig stmts\n  where assig (While _ e b els)     = assigned b ++ assigned els\n        assig (For _ p e b els)     = assigned b ++ assigned els ++ bound p\n        assig (With _ items b)      = assigned b ++ bound items\n        assig (Try _ b hs els fin)  = assigned b ++ concat [ bound ex ++ assigned b | Handler ex b <- hs ] ++ assigned els ++ assigned fin\n        assig (If _ bs els)         = concat [ assigned b | Branch _ b <- bs ] ++ assigned els\n        assig (Assign _ ps _)       = bound ps\n        assig s                     = bound s\n\n\ninstance Vars Decl where\n    freeQ (Def _ n q ps ks t b d fx _)\n                                    = (freeQ ps ++ freeQ ks ++ freeQ b ++ freeQ fx) `diffQ` (n : bound q ++ bound ps ++ bound ks ++ assigned b)\n    freeQ (Actor _ n q ps ks b _)   = (freeQ ps ++ freeQ ks ++ freeQ b) `diffQ` (n : self : bound q ++ bound ps ++ bound ks ++ assigned b)\n    freeQ (Class _ n q cs b _)      = (freeQ cs ++ freeQ b) `diffQ` (n : bound q ++ assigned b)\n    freeQ (Protocol _ n q ps b _)   = (freeQ ps ++ freeQ b) `diffQ` (n : bound q ++ assigned b)\n    freeQ (Extension _ q c ps b _)  = (freeQ c ++ freeQ ps ++ freeQ b) `diffQ` (bound q ++ assigned b)\n\n    bound (Def _ n _ _ _ _ _ _ _ _) = [n]\n    bound (Actor _ n _ _ _ _ _)     = [n]\n    bound (Class _ n _ _ _ _)       = [n]\n    bound (Protocol _ n _ _ _ _)    = [n]\n    bound (Extension _ _ _ _ _ _)   = []\n\ninstance Vars Branch where\n    freeQ (Branch e ss)             = freeQ e ++ freeQ ss\n    bound (Branch e ss)             = bound ss\n\ninstance Vars Handler where\n    freeQ (Handler ex ss)           = freeQ ex ++ (freeQ ss `diffQ` bound ex)\n    bound (Handler ex ss)           = bound ss ++ bound ex\n\ninstance Vars Expr where\n    freeQ (Var _ n)                 = [n]\n    freeQ (Int _ _ str)             = []\n    freeQ (Float _ _ str)           = []\n    freeQ (Imaginary _ _ str)       = []\n    freeQ (Bool _ v)                = []\n    freeQ (None _)                  = []\n    freeQ (NotImplemented _)        = []\n    freeQ (Ellipsis _)              = []\n    freeQ (Strings _ ss)            = []\n    freeQ (BStrings _ ss)           = []\n    freeQ (Call _ e ps ks)          = freeQ e ++ freeQ ps ++ freeQ ks\n    freeQ (TApp _ e ts)             = freeQ e ++ freeQ ts\n    freeQ (Let _ ss e)              = freeQ ss ++ (freeQ e `diffQ` bound ss)\n    freeQ (Async _ e)               = freeQ e\n    freeQ (Await _ e)               = freeQ e\n    freeQ (Index _ e ix)            = freeQ e ++ freeQ ix\n    freeQ (Slice _ e sl)            = freeQ e ++ freeQ sl\n    freeQ (Cond _ e1 e e2)          = freeQ [e1,e,e2]\n    freeQ (IsInstance _ e c)        = freeQ e ++ freeQ c\n    freeQ (BinOp _ e1 o e2)         = freeQ [e1,e2]\n    freeQ (CompOp _ e ops)          = freeQ e ++ freeQ ops\n    freeQ (UnOp _ o e)              = freeQ e\n    freeQ (Dot _ e n)               = freeQ e  \n    freeQ (Opt _ e _)               = freeQ e\n    freeQ (OptChain _ e)            = freeQ e\n    freeQ (Rest _ e n)              = freeQ e\n    freeQ (DotI _ e i)              = freeQ e\n    freeQ (RestI _ e i)             = freeQ e\n    freeQ (Lambda _ ps ks e fx)     = freeQ ps ++ freeQ ks ++ (freeQ e `diffQ` (bound ps ++ bound ks))\n    freeQ (Yield _ e)               = freeQ e\n    freeQ (YieldFrom _ e)           = freeQ e\n    freeQ (Tuple _ ps ks)           = freeQ ps ++ freeQ ks\n    freeQ (List _ es)               = freeQ es\n    freeQ (ListComp _ e co)         = (freeQ e `diffQ` bound co) ++ freeQ co\n    freeQ (Dict _ es)               = freeQ es\n    freeQ (DictComp _ e co)         = (freeQ e `diffQ` bound co) ++ freeQ co\n    freeQ (Set _ es)                = freeQ es\n    freeQ (SetComp _ e co)          = (freeQ e `diffQ` bound co) ++ freeQ co\n    freeQ (Paren _ e)               = freeQ e\n    freeQ (UnBox t e)               = freeQ e\n    freeQ (Box t e)                 = freeQ e\n\ninstance Vars Name where\n    free n                          = [n]\n\ninstance Vars ModName where\n    free (ModName (n:ns))           = [n]\n\ninstance Vars QName where\n    free (QName m n)                = free m\n    free (NoQ n)                    = free n\n    free (GName m n)                = free m\n    \n    freeQ n                         = [n]\n\ninstance Vars Except where\n    freeQ (ExceptAll _)             = []\n    freeQ (Except _ x)              = freeQ x\n    freeQ (ExceptAs _ x n)          = freeQ x\n\n    bound (ExceptAll _)             = []\n    bound (Except _ x)              = []\n    bound (ExceptAs _ x n)          = [n]\n\ninstance Vars PosPar where\n    freeQ (PosPar n t e p)          = freeQ t ++ freeQ e ++ freeQ p\n    freeQ (PosSTAR n t)             = freeQ t\n    freeQ PosNIL                    = []\n\n    bound (PosPar n t e p)          = n : bound p\n    bound (PosSTAR n t)             = [n]\n    bound PosNIL                    = []\n\ninstance Vars KwdPar where\n    freeQ (KwdPar n t e k)          = freeQ t ++ freeQ e ++ freeQ k\n    freeQ (KwdSTAR n t)             = freeQ t\n    freeQ KwdNIL                    = []\n\n    bound (KwdPar n t e k)          = n : bound k\n    bound (KwdSTAR n t)             = [n]\n    bound KwdNIL                    = []\n\ninstance Vars (PosPar,KwdPar) where\n    freeQ (ppar,kpar)               = freeQ ppar ++ freeQ kpar\n\n    bound (ppar,kpar)               = bound ppar ++ bound kpar\n\ninstance Vars Elem where\n    freeQ (Elem e)                  = freeQ e\n    freeQ (Star e)                  = freeQ e\n\n    bound (Elem p)                  = bound p\n    bound (Star p)                  = bound p\n\ninstance Vars Assoc where\n    freeQ (Assoc k v)               = freeQ k ++ freeQ v\n    freeQ (StarStar e)              = freeQ e\n\ninstance Vars WithItem where\n    freeQ (WithItem e p)            = freeQ e ++ freeQ p\n\n    bound (WithItem e p)            = bound p\n\ninstance Vars PosArg where\n    freeQ (PosArg e p)              = freeQ e ++ freeQ p\n    freeQ (PosStar e)               = freeQ e\n    freeQ PosNil                    = []\n\ninstance Vars KwdArg where\n    freeQ (KwdArg n e k)            = freeQ e ++ freeQ k\n    freeQ (KwdStar e)               = freeQ e\n    freeQ KwdNil                    = []\n\ninstance Vars OpArg where\n    freeQ (OpArg o e)               = freeQ e\n\ninstance Vars Sliz where\n    freeQ (Sliz _ e1 e2 e3)         = freeQ e1 ++ freeQ e2 ++ freeQ e3\n\ninstance Vars Comp where\n    freeQ (CompFor _ pat e c)       = (freeQ e ++ freeQ c) `diffQ` bound pat\n    freeQ (CompIf _ e c)            = freeQ e ++ freeQ c\n    freeQ NoComp                    = []\n\n    bound (CompFor _ pat e c)       = bound pat ++ bound c\n    bound (CompIf _ e c)            = bound c\n    bound NoComp                    = []\n\ninstance Vars PosPat where\n    freeQ (PosPat p ps)             = freeQ p ++ freeQ ps\n    freeQ (PosPatStar p)            = freeQ p\n    freeQ PosPatNil                 = []\n\n    bound (PosPat p ps)             = bound p ++ bound ps\n    bound (PosPatStar p)            = bound p\n    bound PosPatNil                 = []\n\ninstance Vars KwdPat where\n    freeQ (KwdPat n p ps)           = freeQ p ++ freeQ ps\n    freeQ (KwdPatStar p)            = freeQ p\n    freeQ KwdPatNil                 = []\n\n    bound (KwdPat n p ps)           = bound p ++ bound ps\n    bound (KwdPatStar p)            = bound p\n    bound KwdPatNil                 = []\n\ninstance Vars Pattern where\n    freeQ (PWild _ _)               = []\n    freeQ (PVar _ n a)              = []\n    freeQ (PTuple _ ps ks)          = freeQ ps ++ freeQ ks\n    freeQ (PList _ ps p)            = freeQ ps ++ freeQ p\n    freeQ (PParen _ p)              = freeQ p\n    freeQ (PData _ n ixs)           = freeQ ixs\n\n    bound (PWild _ _)               = []\n    bound (PVar _ n _)              = [n]\n    bound (PTuple _ ps ks)          = bound ps ++ bound ks\n    bound (PList _ ps p)            = bound ps ++ bound p\n    bound (PParen _ p)              = bound p\n    bound (PData _ n ixs)           = [n]\n\ninstance Vars ModuleItem where\n    bound (ModuleItem qn Nothing)   = free qn\n    bound (ModuleItem qn (Just n))  = free n\n\ninstance Vars ImportItem where\n    free (ImportItem n1 as)         = []\n\n    bound (ImportItem n Nothing)    = free n\n    bound (ImportItem n (Just as))  = free as\n\ninstance Vars ModRef where\n    bound (ModRef (0, n))           = free n\n    bound _                         = []\n\ninstance Vars TSchema where\n    freeQ (TSchema _ q t)           = freeQ q ++ freeQ t\n\ninstance Vars TVar where\n    freeQ (TV k v)                  = []\n\ninstance Vars TUni where\n    freeQ (UV k l v)                = []\n\ninstance Vars TCon where\n    freeQ (TC n ts)                 = freeQ n ++ freeQ ts\n\ninstance Vars QBind where\n    freeQ (QBind v cs)              = freeQ cs\n\ninstance Vars Type where\n    freeQ (TVar _ v)                = freeQ v\n    freeQ (TUni _ u)                = freeQ u\n    freeQ (TFun _ es p k t)         = freeQ es ++ freeQ p ++ freeQ k ++ freeQ t\n    freeQ (TTuple _ p k)            = freeQ p ++ freeQ k\n    freeQ (TOpt _ t)                = freeQ t\n    freeQ (TCon  _ c)               = freeQ c\n    freeQ (TRow _ _ _ t r)          = freeQ t ++ freeQ r\n    freeQ (TStar _ _ r)             = freeQ r\n    freeQ _                         = []\n"
  },
  {
    "path": "compiler/lib/src/Acton/Normalizer.hs",
    "content": "-- Copyright (C) 2019-2021 Data Ductus AB\n--\n-- Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:\n--\n-- 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.\n--\n-- 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.\n--\n-- 3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission.\n--\n-- THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS \"AS IS\" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n--\n\n{-# LANGUAGE FlexibleInstances, FlexibleContexts #-}\nmodule Acton.Normalizer where\n\nimport Acton.Syntax\nimport Acton.Names\nimport Acton.NameInfo\nimport Acton.Env\nimport Acton.QuickType\nimport Acton.Prim\nimport Acton.Builtin\nimport Data.List\nimport Pretty\nimport Utils\nimport Control.Monad.State.Strict\nimport Debug.Trace\n\nnormalize                           :: Env0 -> Module -> IO (Module, Env0)\nnormalize env0 m                    = return (evalState (norm env m) (0,[]), env0')\n  where env                         = normEnv env0\n        env0'                       = mapModules convEnv env0\n\n\n--  Normalization:\n--  X All module aliases are replaced by their original module name\n--  X All parameters are positional\n--  X Comprehensions are translated into loops\n--  X String literals are concatenated and delimited by double quotes\n--  X Tuple (and list) patterns are replaced by a var pattern followed by explicit element assignments\n--  - With statemenmts are replaced by enter/exit prim calls + exception handling\n--  X The assert statement is replaced by a prim call ASSERT\n--  X Return without argument is replaced by return None\n                                                                                                                 --  - The else branch of a while loop is replaced by an explicit if statement enclosing the loop\n--  X Superclass lists are transitively closed\n\n\n-- Normalizing monad\ntype NormM a                        = State (Int,[(Name,PosPar,Expr)]) a\n\nnewName                             :: String -> NormM Name\nnewName s                           = do (n,ts) <- get\n                                         put (n+1,ts)\n                                         return $ Internal NormPass s n\n\naddComp                             :: (Name,PosPar,Expr) -> NormM ()\naddComp (n,p,e)                     = state (\\(i,ts) -> ((),(i,(n,p,e):ts)))\n\ngetComps                            :: NormM [(Name,PosPar,Expr)]\ngetComps                            = state (\\(n,ts) -> (ts, (n,[])))\n\ntype NormEnv                        = EnvF NormX\n\ndata NormX                          = NormX {\n                                        marksX :: [ContextMark],\n                                        rtypeX :: Maybe Type,\n                                        lambdavarsX :: PosPar,\n                                        classattrsX :: [Name],\n                                        selfparamX :: Maybe Name\n                                      }\n\ndata ContextMark                    = DROP | LOOP | FINAL deriving (Eq,Show)\n\nsetMarks c env                      = modX env $ \\x -> x{ marksX = c }\n\npushMark c env                      = modX env $ \\x -> x{ marksX = c :  marksX x }\n\nmarks env                           = marksX $ envX env\n\nsetRet t env                        = modX env $ \\x -> x{ rtypeX = t }\n\ngetRet env                          = fromJust $ rtypeX $ envX env\n\naddLambdavars p env                 = modX env $ \\x -> x{ lambdavarsX = joinP (lambdavarsX x) p }\n  where joinP PosNIL p              = p\n        joinP (PosPar n mbt mbe p') p\n                                    = PosPar n mbt mbe (joinP p' p)\n\ngetLambdavars env                   = lambdavarsX $ envX env\n\nclassattrs env                      = classattrsX $ envX env\n\nselfparam env                       = selfparamX $ envX env\n\nsetClassAttrs ns env                = modX env $ \\x -> x{ classattrsX = ns }\n\nsetSelfParam n env                  = modX env $ \\x -> x{ selfparamX = Just n }\n\nnormEnv env0                        = setX env0 NormX{ marksX = [], rtypeX = Nothing, lambdavarsX = PosNIL, classattrsX = [], selfparamX = Nothing }\n\n\n-- Normalize terms ---------------------------------------------------------------------------------------\n\nnormSuite env []                    = return []\nnormSuite env (s : ss)              = do s' <- norm' env s\n                                         comps <- getComps\n                                         ss' <- normSuite (define (envOf s) env) ss\n                                         defs <- mapM mkCompFun comps\n                                         return (concat defs ++ s' ++ ss')\n  where mkCompFun (f,lambound,comp) = do w <- newName \"w\"\n                                         r <- newName \"res\"\n                                         let env0 = define (envOf lambound) env\n                                             fx = fxOf env0 comp\n                                             (tw,w1,tr,e0,stmt) = transComp env0 w r comp\n                                             body = sAssign (pVar w tw) w1 :\n                                                    sAssign (pVar r tr) e0 :\n                                                    stmt :\n                                                    sReturn (eVar r) : []\n                                         norm' env (sDef f lambound tr body fx)\n\n        transComp env w r (ListComp _ (Elem e) co)\n                                    = (tw, w1, tr, e0, compStmt co e1)\n          where env1                = define (envOf co) env\n                te                  = typeOf env1 e\n                tr                  = tList te\n                tw                  = tSequenceW tr te\n                e0                  = List NoLoc []\n                e1                  = eCall (eDot (eVar w) appendKW) [eVar r, e]\n                w1                  = eCall (tApp (eQVar witSequenceList) [te]) []\n        transComp env w r (SetComp _ (Elem annot_e) co)\n                                    = (tw, w1, tr, e0, compStmt co e1)\n          where env1                = define (envOf co) env\n                te                  = typeOf env1 annot_e\n                tr                  = tSet te\n                tw                  = tSetW tr te\n                (w0, e)             = unAnnot (tHashableW te) annot_e\n                e0                  = eCall (tApp (eQVar primMkSet) [te]) [w0, Set NoLoc []]\n                e1                  = eCall (eDot (eVar w) (name \"add\")) [eVar r, e]\n                w1                  = eCall (tApp (eQVar witSetSet) [te]) [w0]\n        transComp env w r (DictComp _ (Assoc annot_k v) co)\n                                    = (tw, w1, tr, e0, compStmt co e1)\n          where env1                = define (envOf co) env\n                tk                  = typeOf env1 annot_k\n                tv                  = typeOf env1 v\n                tr                  = tDict tk tv\n                tw                  = tMappingW tr tk tv\n                (w0, k)             = unAnnot (tHashableW tk) annot_k\n                e0                  = eCall (tApp (eQVar primMkDict) [tv,tk]) [w0, Dict NoLoc []]\n                e1                  = eCall (eDot (eDot (eVar w) (Internal Witness \"Indexed\" 0)) setitemKW) [eVar r, k, v]\n                w1                  = eCall (tApp (eQVar witMappingDict) [tk,tv]) [w0]\n\n        compStmt (CompFor l p e c) x = For l p e [compStmt c x] []\n        compStmt (CompIf l e c) x   = If l [Branch e [compStmt c x]] []\n        compStmt (NoComp) x         = sExpr x\n\n\nnormPat                             :: NormEnv -> Pattern -> NormM (Pattern,Suite)\nnormPat _ (PWild l a)               = do n <- newName \"ignore\"\n                                         return (PVar l n $ conv a,[])\nnormPat _ (PVar l n a)              = return (PVar l n $ conv a,[])\nnormPat env (PParen _ p)            = normPat env p\nnormPat env p@(PTuple _ pp kp)      = do v <- newName \"tup\"\n                                         ss <- normSuite (define [(v, NVar t)] env) $ normPP v 0 pp ++ normKP v [] kp\n                                         return (pVar v $ conv t, ss)\n  where normPP v n (PosPat p pp)    = Assign NoLoc [p] (DotI NoLoc (eVar v) n) : normPP v (n+1) pp\n        normPP v n (PosPatStar p)   = [Assign NoLoc [p] (foldl (RestI NoLoc) (eVar v) [0..n-1])]\n        normPP _ _ PosPatNil        = []\n        normKP v ns (KwdPat n p kp) = Assign NoLoc [p] (Dot NoLoc (eVar v) n) : normKP v (n:ns) kp\n        normKP v ns (KwdPatStar p)  = [Assign NoLoc [p] (foldl (Rest NoLoc) (eVar v) (reverse ns))]\n        normKP _ _ KwdPatNil        = []\n        t                           = typeOf env p\nnormPat env p@(PList _ ps pt)       = do v <- newName \"lst\"\n                                         ss <- normSuite env $ normList v 0 ps pt\n                                         return (pVar v $ conv t, ss)\n  where normList v n (p:ps) pt      = s : normList v (n+1) ps pt\n          where s                   = Assign NoLoc [p] (eCall (eDot (eQVar qnIndexed) getitemKW)\n                                        [eVar v, Int NoLoc n (show n)])\n        normList v n [] (Just p)    = [Assign NoLoc [p] (eCall (eDot (eQVar qnSliceable) getsliceKW)\n                                        [eVar v, Int NoLoc n (show n), None NoLoc, None NoLoc])]\n        normList v n [] Nothing     = []\n        t                           = typeOf env p\n\n\n\nclass Norm a where\n    norm                            :: NormEnv -> a -> NormM a\n    norm'                           :: NormEnv -> a -> NormM [a]\n    norm' env x                     = (:[]) <$> norm env x\n\ninstance (Norm a, EnvOf a) => Norm [a] where\n    norm env []                     = return []\n    norm env (a:as)                 = do as1 <- norm' env a\n                                         as2 <- norm env1 as\n                                         return (as1++as2)\n      where env1                    = define (envOf a) env\n\ninstance Norm a => Norm (Maybe a) where\n    norm env Nothing                = return Nothing\n    norm env (Just a)               = Just <$> norm env a\n\ninstance Norm Module where\n    norm env (Module m imps mdoc ss) = Module m imps mdoc <$> normSuite env ss\n\nhandle env x hs                     = do bs <- sequence [ branch e b | Handler e b <- hs ]\n                                         return $ [sIf bs [sExpr $ eCall (eQVar primRAISE) [eVar x]]]\n  where branch (ExceptAll _) b      = Branch (eBool True) <$> normSuite env b\n        branch (Except _ y) b       = Branch (eIsInstance x y) <$> normSuite env b\n        branch (ExceptAs _ y z) b   = Branch (eIsInstance x y) <$> (bind:) <$> normSuite env' b\n          where env'                = define [(z,NVar t)] env\n                bind                = sAssign (pVar z $ conv t) (eVar x)\n                t                   = tCon $ TC y []\n\nexitContext env s\n  | DROP:c <- marks env             = sDROP : exitContext (setMarks c env) s\n  | FINAL:c <- marks env            = [sRAISE $ exn s]\n  | LOOP:c <- marks env             = if s `elem` [sBreak,sContinue] then [s] else exitContext (setMarks c env) s\n  | otherwise                       = [s]\n  where exn (Break _)               = eCall (eQVar primBRK) []\n        exn (Continue _)            = eCall (eQVar primCNT) []\n        exn (Return _ (Just e))     = eCall (eQVar primRET) [e]\n\nsDROP                               = sExpr (eCall (eQVar primDROP) [])\nsPOP x                              = sAssign (pVar x tBaseException) (eCall (eQVar primPOP) [])\nePUSH                               = eCall (eQVar primPUSH) []\nePUSHF                              = eCall (eQVar primPUSHF) []\nsSEQ                                = sExpr (eCall (eQVar primRAISE) [eCall (eQVar primSEQ) []])\nsRAISE e                            = sExpr (eCall (eQVar primRAISE) [e])\n\n-- TODO: maybe less approximation?\nisVal Var{}                         = True\nisVal Int{}                         = True\nisVal Float{}                       = True\nisVal Imaginary{}                   = True\nisVal Bool{}                        = True\nisVal None{}                        = True\nisVal Strings{}                     = True\nisVal BStrings{}                    = True\nisVal Lambda{}                      = True\nisVal (Call _ (TApp _ (Var _ n) _) (PosArg e PosNil) KwdNil)\n                                    = n == primCAST && isVal e\nisVal (TApp _ e _)                  = isVal e\nisVal (Dot _ e _)                   = isVal e\nisVal (DotI _ e _)                  = isVal e\nisVal (Paren _ e)                   = isVal e\nisVal _                             = False\n\ninstance Norm Stmt where\n    norm env (Expr l e)             = Expr l <$> norm env e\n    norm env (MutAssign l t e)      = MutAssign l <$> norm env t <*> norm env e\n    norm env (Assert l e mbe)       = do e' <- normBool env e\n                                         mbe' <- norm env mbe\n                                         return $ Expr l $ eCall (eQVar primASSERT) [e', maybe eNone id mbe']\n    norm env (Pass l)               = return $ Pass l\n    norm env (Raise l e)            = do e' <- norm env e\n                                         return $ Expr l $ eCall (eQVar primRAISE) [e']\n    norm env (If l bs els)          = If l <$> norm env bs <*> normSuite env els\n    norm env (While l e b els)      = While l (eBool True) <$> normSuite (pushMark LOOP env) (sIf1 e [sPass] (els++[sBreak]) : b) <*> return []\n    norm env (Data l mbp ss)        = Data l <$> norm env mbp <*> normSuite env ss\n    norm env (VarAssign l ps e)     = VarAssign l <$> norm env ps <*> norm env e\n    norm env (After l e e')         = After l <$> norm env e <*> norm env e'\n    norm env (Signature l ns t d)   = return $ Signature l ns (conv t) d\n    norm env s                      = error (\"norm unexpected stmt: \" ++ prstr s)\n\n    norm' env (Decl l ds)           = do (eqs,ds) <- normDecls env ds\n                                         return $ eqs ++ [Decl l ds]\n\n    norm' env (Try l b [] els [])   = normSuite env (b ++ els)\n    norm' env (Try l b hs els [])   = do b <- normSuite (pushMark DROP env) b\n                                         els <- normSuite (define (envOf b) env) els\n                                         x <- newName \"x\"\n                                         hdl <- handle env x hs\n                                         return [sIf [Branch ePUSH (b ++ sDROP : els)] (sPOP x : hdl)]\n      where ePUSH                   = eCall (eQVar primPUSH) []\n    norm' env (Try l b hs els fin)  = do ss <- norm' (pushMark FINAL env) try0\n                                         x <- newName \"xx\"\n                                         fin <- normSuite (define [(x,NVar tBaseException)] env) fin\n                                         return [sIf [Branch ePUSHF (ss++mbseq)] (sPOP x : fin ++ relays x)]\n      where try0                    = Try l b hs els []\n            relays x                = iff [ Branch (eIsInstance x n) s | (n,s) <- map (relay x) ctrl, valid s] [sRAISE $ eVar x]\n            relay _ SEQ             = (primSEQ, [sPass])\n            relay _ BRK             = (primBRK, exitContext env sBreak)\n            relay _ CNT             = (primCNT, exitContext env sContinue)\n            relay x RET             = (primRET, downcast : exitContext env ret)\n              where x'              = Derived x (globalName \"RET\")\n                    downcast        = sAssign (pVar x' tRET) (eCAST tBaseException tRET (eVar x))\n                    ret             = sReturn (eCAST tValue (getRet env) (eDot (eVar x') attrVal))\n            valid [Expr{}]          = False\n            valid [Assign{},Expr{}] = False\n            valid _                 = True\n            mbseq                   = if SEQ `elem` ctrl then [sSEQ] else []\n            ctrl                    = nub (flows try0)\n            iff [] els              = els\n            iff bs els              = [sIf bs els]\n\n    norm' env s@(Break l)           = return $ exitContext env s\n    norm' env s@(Continue l)        = return $ exitContext env s\n    norm' env (Return l Nothing)    = return $ exitContext env (Return l $ Just eNone)\n    norm' env (Return l (Just e))   = do e <- norm env e\n                                         case isVal e of\n                                             True -> return $ retContext e\n                                             False -> do\n                                                 n <- newName \"tmp\"\n                                                 return $ sAssign (pVar n $ conv t) e : retContext (eVar n)\n      where retContext e            = exitContext env $ Return l $ Just e\n            t                       = typeOf env e\n\n    norm' env (Assign l ps e)       = do e' <- norm env e\n                                         (ps1,stmts) <- unzip <$> mapM (normPat env) ps\n                                         ps2 <- norm env ps1\n                                         let p'@(PVar _ n _) : ps' = ps2\n                                         return $ Assign l [p'] e' : [ Assign l [p] (eVar n) | p <- ps' ] ++ concat stmts\n      where t                       = typeOf env e\n    norm' env s@(For l p e b els)   = do i <- newName \"iter\"\n                                         v <- newName \"val\"\n                                         normSuite env [sAssign (pVar i $ conv t) e,\n                                                        handleStop (While l (eBool True) (body v i) []) els]\n      where t@(TCon _ (TC c [t']))  = typeOf env e\n            next i                  = eCall (eDot (eVar i) nextKW) []\n            handleStop loop els     = Try l [loop] [Handler (Except l0 qnStopIteration) (mkBody els)] [] []\n            body v i\n               | isPVar p           = sAssign p (next i) : b\n               | otherwise          = sAssign (pVar v t') (next i) : sAssign p (eVar v) : b\n            isPVar PVar{}           = True\n            isPVar _                = False\n    {-\n    with EXPRESSION as PATTERN:\n        SUITE\n    ===>\n    $mgr = EXPRESSION\n    $val = $mgr.__enter__()\n    $exc = False\n    try:\n        PATTERN = $val\n        SUITE\n    except Exception as ex:\n        $exc = True\n        if not $mgr.__exit__(ex):\n            raise\n    finally:\n        if not $exc:\n            $mgr.__exit__(None)\n    -}\n    norm' env s@(With l (i:is) b)   = do notYet l s                     -- TODO: remove\n                                         m <- newName \"mgr\"\n                                         v <- newName \"val\"\n                                         x <- newName \"exc\"\n                                         (e,mbp,ss) <- normItem env i\n                                         b' <- normSuite env1 (ss ++ b)\n                                         return undefined\n      where env1                    = define (envOf i) env\n    norm' env (With l [] b)         = normSuite env b\n    norm' env s                     = do s' <- norm env s\n                                         return [s']\n\nnormItem env (WithItem e Nothing)   = do e' <- norm env e\n                                         return (e', Nothing, [])\nnormItem env (WithItem e (Just p))  = do e' <- norm env e\n                                         (p',ss) <- normPat env p\n                                         return (e', Just p', ss)\n\nnormDecls env ds                    = do (pres, ds) <- unzip <$> mapM (normDecl env1 ns) ds\n                                         pre <- normSuite env (concat pres)\n                                         return (pre, ds)\n      where env1                    = define (envOf ds) env\n            ns                      = bound ds\n\nnormDecl env ns d@Class{}           = do d <- norm env1 d{ dbody = props ++ body }\n                                         pre <- normSuite env pre\n                                         return (pre, d)\n      where (pre,te,body)           = fixupClassAttrs ns d\n            env1                    = define (envOf pre ++ te) $ setClassAttrs (dom te) env\n            props                   = [ Signature NoLoc [w] (monotype t) Property | (w,NVar t) <- te ]\nnormDecl env ns d                   = do d <- norm env d\n                                         return ([], d)\n\n\n-- The type-checker may leave witness bindings on the level of classes, even though our class\n-- syntax does not yet support this in the same way as is does for actors. But the creation and\n-- reduction of witnesses that mutually depend on classes becomes so much easier if we allow\n-- ourselves to make use of this planned feature already today. The code below thus implements\n-- class level bindings, albeit limited to witnesses, by transforming them into either global\n-- binding prefixes (if the circular class dependencies actually got eliminated during witness\n-- reduction), __init__ method locals (if they are only referenced during initialization) or\n-- proper instance attributes (in the general case).\n\n\n--                    dbody\n--                   /     \\\n--                  /       \\\n--               eqs         defs\n--              /   \\       /    \\\n--             /     \\   inits   dynamic\n--           pre     dep\n--                  /   \\\n--                 /     \\\n--               attr    local\nfixupClassAttrs ns d0@Class{dname=n}\n  | null eqs                        = ([], [], defs)\n  | otherwise                       = --trace (\"### Fixup class \" ++ prstr n ++ \":\") $\n                                      --trace (\"  # te:\\n\" ++ render (nest 8 $ vcat $ map pretty te)) $\n                                      --trace (\"  # pre: \" ++ prstrs (bound pre)) $\n                                      --trace (\"  # attr: \" ++ prstrs (bound attr)) $\n                                      --trace (\"  # local: \" ++ prstrs (bound local)) $\n                                      --trace (\"  # defs:\\n\" ++ render (nest 4 $ vcat [ pretty d | Decl _ ds <- defs1, d <- ds, dname d `elem` [initKW, altInit]])) $\n                                      (pre, te, defs1)\n  where (eqs, defs)                 = split [] [] (dbody d0)\n          where\n            split eqs defs []       = (reverse eqs, reverse defs)\n            split eqs defs (s:ss)   = case s of\n                                        Assign _ [PVar _ (Internal Witness _ _) (Just _)] _ ->\n                                            split(s:eqs) defs ss\n                                        _ ->\n                                            split eqs (s:defs) ss\n\n        (dynref, initpar)           = dvars [] [] $ concat [ ds | Decl _ ds <- defs ]\n          where\n            dvars dyn ini []        = (dyn `intersect` bound eqs, ini)\n            dvars dyn ini (d:ds)\n              | dname d == initKW   = dvars dyn ([ n | n@(Internal Witness _ _) <- bound (pos d) ] ++ ini) ds\n              | otherwise           = dvars (free d ++ dyn) ini ds\n\n        (pre, dep)                  = split ns [] [] eqs\n          where\n            split ns pre dep []     = (reverse pre, reverse dep)\n            split ns pre dep (eq:eqs)\n              | null fvs            = split ns (eq:pre) dep eqs\n              | otherwise           = split (bound eq ++ ns) pre (eq:dep) eqs\n              where fvs             = free (expr eq) `intersect` (initpar++ns)\n\n        (attr, local)               = split [] [] dep\n          where\n            split attr local []     = (reverse attr, reverse local)\n            split attr local (eq:eqs)\n              | null fvs            = split attr (eq:local) eqs\n              | otherwise           = split (eq:attr) local eqs\n              where fvs             = bound eq `intersect` (dynref++free eqs)\n\n        initMeth                    = if altInit `elem` bound defs then altInit else initKW\n\n        defs1                       = map (initS initMeth) defs\n          where\n            initS n (Decl l ds)     = Decl l $ map (initL . initD n) ds\n            initS n s               = s\n\n            initD n d@Def{}\n              | dname d == n, Just self <- selfPar d\n                                    = d{ dbody = [ sMutAssign (eDot (eVar self) w) e | Assign _ [PVar _ w _] e <- attr ] ++ dbody d }\n              | deco d == Static    = d{ dbody = attr ++ dbody d }\n            initD n d               = d\n\n            initL d@Def{}\n              | dname d == initKW   = d{ dbody = local ++ dbody d }\n            initL d                 = d\n\n        te                          = [ (w, NVar t) | Assign _ [PVar _ w (Just t)] _ <- attr ]\n\n\ninstance Norm Decl where\n    norm env (Def l n q p k t b d x doc)\n                                    = do p' <- joinPar <$> norm env0 p <*> norm (define (envOf p) env0) k\n                                         b' <- normSuite env1 b\n                                         return $ Def l n q p' KwdNIL (conv t) (ret b') d x doc\n      where env1                    = setMarks [] $ setRet t $ define (envOf p ++ envOf k) env0\n            env0                    = defineTVars q env00\n            env00                   = case p of\n                                        PosPar self _ _ _ | not $ null $ classattrs env, d /= Static ->\n                                            setSelfParam self env\n                                        _ ->\n                                            env\n            ret b | fallsthru b     = b ++ [sReturn eNone]\n                  | otherwise       = b\n    norm env (Actor l n q p k b doc)\n                                    = do p' <- joinPar <$> norm env0 p <*> norm (define (envOf p) env0) k\n                                         b' <- normSuite env1 b\n                                         return $ Actor l n q p' KwdNIL b' doc\n      where env1                    = setMarks [] $ define (envOf p ++ envOf k) env0\n            env0                    = define [(selfKW, NVar t0)] $ defineTVars q env\n            t0                      = tCon $ TC (NoQ n) (map tVar $ qbound q)\n    norm env (Class l n q as b doc) = Class l n q as <$> normSuite env1 b <*> return doc\n      where env1                    = defineTVars (selfQuant (NoQ n) q) env\n    norm env d                      = error (\"norm unexpected: \" ++ prstr d)\n\n\ncatStrings ss                       = map (quote . escape '\"') ss\n  where escape c []                 = []\n        escape c ('\\\\':x:xs)        = '\\\\' : x : escape c xs\n        escape c (x:xs)\n          | x == c                  = '\\\\' : x : escape c xs\n          | otherwise               = x : escape c xs\n        quote s                     = '\"' : s ++ \"\\\"\"\n\n\nnormInst env ts e                   = norm env e\n\nnormBool env e\n  | t == tBool                      = norm env e\n  | TOpt _ t' <- t, Var{} <- e      = return $ eBinOp (eCall (tApp (eQVar primISNOTNONE) [t']) [e]) And (eCall (eDot (eCAST t t' e) boolKW) [])\n  | BinOp l e1 op e2 <- e,\n    op `elem` [And,Or]              = do e1 <- normBool env e1\n                                         e2 <- normBool env e2\n                                         return $ BinOp l e1 op e2\n  | otherwise                       = do e' <- norm env e\n                                         return $ eCall (eDot e' boolKW) []\n  where t                           = typeOf env e\n\ninstance Norm Expr where\n    norm env (Var l (NoQ n))\n      | n `elem` classattrs env,\n        Just self <- selfparam env  = return $ eDot (eVar self) n\n    norm env (Var l nm)             = return $ Var l nm\n    norm env (Int l i s)            = Int l <$> return i <*> return s\n    norm env (Float l f s)          = Float l <$> return f <*> return s\n    norm env (Imaginary l i s)      = Imaginary l <$> return i <*> return s\n    norm env (Bool l b)             = Bool l <$> return b\n    norm env (None l)               = return $ None l\n    norm env (NotImplemented l)     = return $ NotImplemented l\n    norm env (Ellipsis l)           = return $ Ellipsis l\n    norm env (Strings l ss)         = return $ Strings l (catStrings ss)\n    norm env (BStrings l ss)        = return $ BStrings l (catStrings ss)\n    norm env (Call l e p k)         = Call l <$> norm env e <*> norm env (joinArg p k) <*> pure KwdNil\n    norm env (TApp l e ts)          = TApp l <$> normInst env ts e <*> pure (conv ts)\n    norm env (Let l ss e)          = Let l <$> norm env ss <*> norm env e\n    norm env (Dot l (Var l' x) n)\n      | NClass{} <- findQName x env = pure $ Dot l (Var l' x) n\n    norm env (Dot l e n)\n      | TTuple _ p k <- t,\n        n `notElem` valueKWs        = DotI l <$> norm env e <*> pure (nargs p + narg n k)\n      | otherwise                   = Dot l <$> norm env e <*> pure n\n      where t                       = typeOf env e\n    norm env (Async l e)            = Async l <$> norm env e\n    norm env (Await l e)            = Await l <$> norm env e\n    norm env (Cond l e1 e2 e3)      = Cond l <$> norm env e1 <*> normBool env e2 <*> norm env e3\n    norm env (IsInstance l e c)     = IsInstance l <$> norm env e <*> pure c\n    norm env (BinOp l e1 Or e2)     = BinOp l <$> norm env e1 <*> pure Or <*> norm env e2\n    norm env (BinOp l e1 And e2)    = BinOp l <$> norm env e1 <*> pure And <*> norm env e2\n    norm env (UnOp l Not e)         = UnOp l Not <$> normBool env e\n    norm env (Rest l e n)           = RestI l <$> norm env e <*> pure (nargs p + narg n k)\n      where TTuple _ p k            = typeOf env e\n    norm env (DotI l e i)           = DotI l <$> norm env e <*> pure i\n    norm env (RestI l e i)          = RestI l <$> norm env e <*> pure i\n    norm env (Lambda l p k e fx)    = do p' <- joinPar <$> norm env p <*> norm (define (envOf p) env) k\n                                         let env1 = define (envOf p ++ envOf k) (addLambdavars p' env)\n                                         eta <$> (Lambda l p' KwdNIL <$> norm env1 e <*> pure fx)\n    norm env (Yield l e)            = Yield l <$> norm env e\n    norm env (YieldFrom l e)        = YieldFrom l <$> norm env e\n    norm env (Tuple l ps ks)        = Tuple l <$> norm env (joinArg ps ks) <*> pure KwdNil\n    norm env (List l es)            = List l <$> norm env es\n    norm env e@ListComp{}           = deferComp env e\n    norm env (Dict l as)            = Dict l <$> norm env as\n    norm env e@DictComp{}           = deferComp env e\n    norm env (Set l es)             = Set l <$> norm env es\n    norm env e@SetComp{}            = deferComp env e\n    norm env (Paren l e)            = norm env e\n    norm env e                      = error (\"norm unexpected: \" ++ prstr e)\n\ndeferComp env e                     = do f <- newName \"compfun\"\n                                         let p = getLambdavars env\n                                         addComp (f,p,e)\n                                         return (Call NoLoc (eVar f) (posarg $ map eVar $ pospars' p) KwdNil)\n\neta (Lambda _ p KwdNIL (Call _ e p' KwdNil) fx)\n  | eq1 p p'                        = e\n  where\n    eq1 (PosPar n _ _ p) (PosArg e p')  = eVar n == e && eq1 p p'\n    eq1 (PosSTAR n _) (PosStar e)       = eVar n == e\n    eq1 PosNIL PosNil                   = True\n    eq1 _ _                             = False\neta e                               = e\n\nnargs (TRow _ _ _ _ r)              = 1 + nargs r\nnargs (TStar _ _ _)                 = 1\nnargs (TNil _ _)                    = 0\n\nnarg n (TRow _ _ n' _ r)\n  | n == n'                         = 0\n  | otherwise                       = 1 + narg n r\nnarg n (TStar _ _ _)\n  | n == attrKW                     = 0\nnarg n k                            = error (\"### Bad narg \" ++ prstr n ++ \" \" ++ prstr k)\n\ninstance Norm Pattern where\n    norm env (PWild l a)            = return $ PWild l (conv a)\n    norm env (PVar l n a)           = return $ PVar l n (conv a)\n    norm env (PTuple l ps ks)       = PTuple l <$> norm env ps <*> norm env ks\n    norm env (PList l ps p)         = PList l <$> norm env ps <*> norm env p        -- TODO: eliminate here\n    norm env (PParen l p)           = norm env p\n\ninstance Norm Branch where\n    norm env (Branch e ss)          = Branch <$> normBool env e <*> normSuite env ss\n\ninstance Norm Handler where\n    norm env (Handler ex b)         = Handler ex <$> normSuite env1 b\n      where env1                    = define (envOf ex) env\n\ninstance Norm PosPar where\n    norm env (PosPar n t e p)       = PosPar n (conv t) <$> norm env e <*> norm (define [(n,NVar $ fromJust t)] env) p\n    norm env (PosSTAR n t)          = return $ PosSTAR n (conv t)\n    norm env PosNIL                 = return PosNIL\n\ninstance Norm KwdPar where\n    norm env (KwdPar n t e k)       = KwdPar n (conv t) <$> norm env e <*> norm (define [(n,NVar $ fromJust t)] env) k\n    norm env (KwdSTAR n t)          = return $ KwdSTAR n (conv t)\n    norm env KwdNIL                 = return KwdNIL\n\njoinPar (PosPar n t e p) k          = PosPar n t e (joinPar p k)\njoinPar (PosSTAR n t) k             = PosPar n t Nothing (kwdToPosPar k)\njoinPar PosNIL k                    = kwdToPosPar k\n\nkwdToPosPar (KwdPar n t e k)        = PosPar n t e (kwdToPosPar k)\nkwdToPosPar (KwdSTAR n t)           = PosPar n t Nothing PosNIL\nkwdToPosPar KwdNIL                  = PosNIL\n\njoinArg (PosArg e p) k              = PosArg e (joinArg p k)\njoinArg (PosStar e) k               = PosArg e (kwdToPosArg k)\njoinArg PosNil k                    = kwdToPosArg k\n\nkwdToPosArg (KwdArg n e k)          = PosArg e (kwdToPosArg k)\nkwdToPosArg (KwdStar e)             = PosArg e PosNil\nkwdToPosArg KwdNil                  = PosNil\n\n\ninstance Norm PosArg where\n    norm env (PosArg e p)           = PosArg <$> norm env e <*> norm env p\n    norm env (PosStar e)            = PosStar <$> norm env e\n    norm env PosNil                 = return PosNil\n\ninstance Norm KwdArg where\n    norm env (KwdArg n e k)         = KwdArg n <$> norm env e <*> norm env k\n    norm env (KwdStar e)            = KwdStar <$> norm env e\n    norm env KwdNil                 = return KwdNil\n\ninstance Norm PosPat where\n    norm env (PosPat p ps)          = PosPat <$> norm env p <*> norm env ps\n    norm env (PosPatStar p)         = PosPatStar <$> norm env p\n    norm env PosPatNil              = return PosPatNil\n\ninstance Norm KwdPat where\n    norm env (KwdPat n p ps)        = KwdPat n <$> norm env p <*> norm env ps\n    norm env (KwdPatStar p)         = KwdPatStar <$> norm env p\n    norm env KwdPatNil              = return KwdPatNil\n\ninstance Norm Comp where\n    norm env (CompFor l p e c)      = CompFor l <$> norm env p <*> norm env e <*> norm (define (envOf p) env) c\n    norm env (CompIf l e c)         = CompIf l <$> normBool env e <*> norm env c\n    norm env NoComp                 = return NoComp\n\ninstance Norm Elem where\n    norm env (Elem e)               = Elem <$> norm env e\n    norm env (Star e)               = Star <$> norm env e               -- TODO: eliminate here\n\ninstance Norm Assoc where\n    norm env (Assoc k v)            = Assoc <$> norm env k <*> norm env v\n    norm env (StarStar e)           = StarStar <$> norm env e           -- TODO: eliminate here\n\n\n-- Convert function types ---------------------------------------------------------------------------------\n\nconvEnv env m (n, i)                = [(n, conv i)]\n\n\nclass Conv a where\n    conv                            :: a -> a\n\ninstance (Conv a) => Conv [a] where\n    conv                            = map conv\n\ninstance (Conv a) => Conv (Maybe a) where\n    conv                            = fmap conv\n\ninstance (Conv a) => Conv (Name, a) where\n    conv (n, x)                     = (n, conv x)\n\ninstance Conv NameInfo where\n    conv (NAct q p k te doc)        = NAct q (joinRow p k) kwdNil (conv te) doc\n    conv (NClass q ps te doc)       = NClass q (conv ps) (conv te) doc\n    conv (NSig sc dec doc)          = NSig (conv sc) dec doc\n    conv (NDef sc dec doc)          = NDef (conv sc) dec doc\n    conv (NVar t)                   = NVar (conv t)\n    conv (NSVar t)                  = NSVar (conv t)\n    conv ni                         = ni\n\ninstance Conv WTCon where\n    conv (w,c)                      = (w, conv c)\n\ninstance Conv TSchema where\n    conv (TSchema l q t)            = TSchema l q (conv t)\n\ninstance Conv Type where\n    conv (TFun l fx p k t)          = TFun l fx (joinRow p k) kwdNil (conv t)\n    conv (TCon l c)                 = TCon l (conv c)\n    conv (TTuple l p k)             = TTuple l (joinRow p k) kwdNil\n    conv (TOpt l t)                 = TOpt l (conv t)\n    conv (TRow l k n t r)           = TRow l PRow nWild (conv t) (conv r)\n    conv (TStar l k r)              = TRow l PRow nWild (TTuple l (conv r) kwdNil) posNil\n    conv (TNil l k)                 = TNil l PRow\n    conv t                          = t\n\ninstance Conv TCon where\n    conv (TC c ts)                  = TC c (conv ts)\n\njoinRow (TRow l k n t p) r          = TRow l PRow nWild (conv t) (joinRow p r)\njoinRow (TStar l k p) r             = TRow l PRow nWild (TTuple l (conv p) kwdNil) (conv r)\njoinRow (TNil _ _) r                = conv r\n-- To be removed:\njoinRow p (TNil _ _)                = conv p\njoinRow p r                         = error (\"##### joinRow \" ++ prstr p ++ \"  AND  \" ++ prstr r)\n"
  },
  {
    "path": "compiler/lib/src/Acton/Parser.hs",
    "content": "-- Copyright (C) 2019-2021 Data Ductus AB\n--\n-- Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:\n--\n-- 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.\n--\n-- 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.\n--\n-- 3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission.\n--\n-- THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS \"AS IS\" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n--\n\n{-# LANGUAGE FlexibleInstances #-}\n{-# OPTIONS_GHC -fno-warn-orphans #-}\nmodule Acton.Parser\n  ( module Acton.Parser\n  , CustomParseError(..)\n  ) where\n\nimport qualified Control.Monad.Trans.State.Strict as St\nimport qualified Control.Exception\nimport Control.Concurrent.Async (Async, async, cancel, wait)\nimport Control.Concurrent.Chan\nimport Control.Concurrent.MVar\nimport Control.Concurrent.QSem\nimport Control.Monad (replicateM, replicateM_, void, when, join)\nimport Control.DeepSeq (rnf)\nimport Data.IORef\nimport Data.List (isPrefixOf)\nimport Data.Maybe (fromMaybe)\nimport Data.Void\nimport Data.Char\nimport qualified Data.List.NonEmpty as N\nimport qualified Data.Set as Set\nimport GHC.Conc (getNumCapabilities)\nimport Numeric\nimport Text.Megaparsec\nimport Text.Megaparsec.Char\nimport Text.Megaparsec.Error\nimport Text.Megaparsec.Pos (mkPos)\n--import Control.Monad.Combinators.Expr\nimport Text_Megaparsec_Expr\nimport qualified Text.Megaparsec.Char.Lexer as L\nimport qualified Text.Megaparsec.Debug as D\nimport qualified Data.List.NonEmpty\nimport qualified Acton.Syntax as S\nimport qualified Acton.Builtin as Builtin\nimport qualified Acton.Names as Names\nimport Utils\nimport Debug.Trace\nimport System.IO.Unsafe\n\n-- Custom error types for better structured error handling\ndata CustomParseError = TypeVariableNameError String  -- Name that looks like type variable\n                      | InvalidFormatSpecifier String\n                      | MissingClosingQuote String  -- String is the quote type (e.g., \"\\\"\\\"\\\"\" or \"'\")\n                      | TooManyQuotesError String\n                      | InvalidModuleStatement\n                      | InvalidTopLevelAssignmentPattern\n                      | DuplicateTopLevelAssignment String\n                      -- String interpolation errors\n                      | EmptyInterpolationExpression\n                      | MissingExpressionBeforeFormat\n                      | UnclosedInterpolationBrace\n                      | EmptyFormatSpecifierError\n                      | TabInFormatSpecifier\n                      | NewlineInFormatSpecifier\n                      | InvalidCharInFormatSpecifier Char\n                      | MissingFormatPrecisionDigits\n                      -- Escape sequence errors\n                      | IncompleteHexEscape String  -- String is the 1 char found\n                      | OctalEscapeOutOfRange\n                      | IncompleteUnicodeEscape Int Int  -- expected, found\n                      | NonAsciiInBytesLiteral\n                      | UnknownEscapeSequence\n                      -- General fallback\n                      | OtherError String\n                      deriving (Eq, Ord, Show)\n\ninstance ShowErrorComponent CustomParseError where\n  showErrorComponent (TypeVariableNameError name) = \"Invalid name (reserved for type variables)\"\n  showErrorComponent (InvalidFormatSpecifier spec) = \"Invalid format specifier\" ++ if null spec then \"\" else \": \" ++ spec\n  showErrorComponent (MissingClosingQuote quote) = \"missing closing \" ++ quote\n  showErrorComponent (TooManyQuotesError quote) = \"too many quote characters\"\n  showErrorComponent InvalidModuleStatement =\n    \"Only declarations and assignments are allowed at the module top level\"\n  showErrorComponent InvalidTopLevelAssignmentPattern =\n    \"Module top-level assignments must bind at least one name\"\n  showErrorComponent (DuplicateTopLevelAssignment name) =\n    \"Module top-level name '\" ++ name ++ \"' cannot be assigned more than once\"\n  -- String interpolation errors\n  showErrorComponent EmptyInterpolationExpression = \"Empty expression in string interpolation\"\n  showErrorComponent MissingExpressionBeforeFormat = \"Missing expression before format specifier\"\n  showErrorComponent UnclosedInterpolationBrace = \"missing closing '}' for expression\"\n  showErrorComponent EmptyFormatSpecifierError = \"Empty format specifier after ':'\"\n  showErrorComponent TabInFormatSpecifier = \"Tab character not allowed in format specifier\"\n  showErrorComponent NewlineInFormatSpecifier = \"Newline not allowed in format specifier\"\n  showErrorComponent (InvalidCharInFormatSpecifier c) = \"Invalid character '\" ++ [c] ++ \"' in format specifier\"\n  showErrorComponent MissingFormatPrecisionDigits = \"Expected digits after '.' in format specifier\"\n  -- Escape sequence errors\n  showErrorComponent (IncompleteHexEscape n) = \"\\\"\\\\x\\\" must be followed by two hexadecimal digits\"\n  showErrorComponent OctalEscapeOutOfRange = \"octal escape sequence out of range\"\n  showErrorComponent (IncompleteUnicodeEscape expected found) =\n    \"Incomplete universal character name (\" ++ show expected ++ \" hex digits needed)\"\n  showErrorComponent NonAsciiInBytesLiteral = \"Only ASCII chars allowed in bytes literal\"\n  showErrorComponent UnknownEscapeSequence = \"unknown escape sequence in string/bytes literal\"\n  -- General fallback\n  showErrorComponent (OtherError msg) = msg\n\n-- Context errors -------------------------------------------------------------------------------\n\ntr :: Show a => String -> Parser a -> Parser a\ntr msg p = do\n  r <-  observing p\n  case r of\n     Left err -> trace (\"failure \"++msg ++\": \"++show err) (parseError err)\n     Right ok -> trace (\"success \"++msg++\": \"++show ok) (return ok)\n\nmakeReport ps src = errReport (map setSpan ps) src\n  where setSpan (loc, msg) = (extractSrcSpan loc src, msg)\n\n--- Main parsing and error message functions ------------------------------------------------------\n\nparseModule :: S.ModName -> String -> String -> Maybe (Int -> Int -> IO ()) -> IO S.Module\nparseModule qn fileName fileContent mReportProgress = do\n    let contentWithNewline = addFinalNewline fileContent\n    (is, mdoc, bodyStart) <-\n      case runParser (St.evalStateT module_header_with_offset initState) fileName contentWithNewline of\n        Left err -> Control.Exception.throwIO err\n        Right h  -> return h\n    parsed <- parseTopLevelChunks fileName contentWithNewline bodyStart mReportProgress\n    let suite = regroupTopDecls (concat parsed)\n    case runParser (St.evalStateT (validateModuleSuite suite) initState) fileName contentWithNewline of\n      Left err -> Control.Exception.throwIO err\n      Right () -> do\n        reportFinalParseProgress contentWithNewline mReportProgress\n        return $ S.Module qn is mdoc suite\n\nparseModuleSerial :: S.ModName -> String -> String -> Maybe (Int -> Int -> IO ()) -> IO S.Module\nparseModuleSerial qn fileName fileContent mReportProgress = do\n    let contentWithNewline = addFinalNewline fileContent\n    st <- parserStateWithProgress contentWithNewline mReportProgress\n    case runParser (St.evalStateT file_input st) fileName contentWithNewline of\n        Left err -> Control.Exception.throw err\n        Right (i,mdoc,s) -> return $ S.Module qn i mdoc s\n\nparseModuleImports :: String -> String -> IO [S.Import]\nparseModuleImports fileName fileContent = fst <$> parseModuleHeader fileName fileContent\n\nparseModuleHeader :: String -> String -> IO ([S.Import], Maybe String)\nparseModuleHeader fileName fileContent =\n    let contentWithNewline = addFinalNewline fileContent\n    in case runParser (St.evalStateT import_input initState) fileName contentWithNewline of\n        Left err -> Control.Exception.throw err\n        Right res -> return res\n\naddFinalNewline :: String -> String\naddFinalNewline s\n    | null s || last s == '\\n' = s\n    | otherwise = s ++ \"\\n\"\n\n-- parseTest file = snd (unsafePerformIO (do cont <- readFile file; parseModule (S.modName [\"test\"]) file cont))\n\nparseTestStr p str = case runParser (St.evalStateT p initState) \"\" str of\n                         Left err -> putStrLn (errorBundlePretty err)\n                         Right t  -> print t\n\nextractSrcSpan :: SrcLoc -> String -> SrcSpan\nextractSrcSpan NoLoc src = SpanEmpty\nextractSrcSpan (Loc l r) src = sp\n  where Right sp = runParser (St.evalStateT (extractP l r) initState) \"\" src\n        extractP :: Int -> Int -> Parser SrcSpan\n        extractP l r = do\n            setOffset l\n            SourcePos f srow scol <- getSourcePos\n            setOffset r\n            SourcePos _ erow ecol <- getSourcePos\n            if srow == erow\n                then if scol == ecol\n                    then return $ SpanPoint f (unPos srow) (unPos scol)\n                    else return $ SpanCoLinear f (unPos srow) (unPos scol) (unPos ecol - 1)\n                else return $ SpanMultiLine f (unPos srow) (unPos scol) (unPos erow) (unPos ecol - 1)\n\n\n-- Parser state -----------------------------------------------------------\n\ndata ParserState = ParserState\n  { psContexts :: [CTX]\n  , psProgress :: Maybe ParseProgressReporter\n  }\n\ndata ParseProgressReporter = ParseProgressReporter\n  { pprTotal :: Int\n  , pprLastPercent :: IORef Int\n  , pprReport :: Int -> Int -> IO ()\n  }\n\ntype Parser = St.StateT ParserState (Parsec CustomParseError String)\n\npushCtx ctx st = st { psContexts = ctx : psContexts st }\npopCtx st      = st { psContexts = tail (psContexts st) }\ngetCtxs        = psContexts\n\ninitState        = ParserState [] Nothing\n\nparserStateWithProgress :: String -> Maybe (Int -> Int -> IO ()) -> IO ParserState\nparserStateWithProgress contentWithNewline mReportProgress =\n    case mReportProgress of\n      Nothing -> return initState\n      Just reportProgress -> do\n        lastPercent <- newIORef 0\n        return initState { psProgress = Just (ParseProgressReporter (length contentWithNewline) lastPercent reportProgress) }\n\nreportFinalParseProgress :: String -> Maybe (Int -> Int -> IO ()) -> IO ()\nreportFinalParseProgress contentWithNewline mReportProgress =\n    case mReportProgress of\n      Nothing -> return ()\n      Just reportProgress ->\n        let total = length contentWithNewline\n        in reportProgress total total\n\nreportParseProgress :: Parser ()\nreportParseProgress = do\n    st <- St.get\n    case psProgress st of\n      Nothing -> return ()\n      Just p -> do\n        off <- getOffset\n        emitParseProgressUnsafe p off `seq` return ()\n\n-- The reporter is installed only when parseModule receives one and emits\n-- monotonic percent updates at successful statement/import boundaries.\nemitParseProgressUnsafe :: ParseProgressReporter -> Int -> ()\nemitParseProgressUnsafe p off = unsafePerformIO (emitParseProgress p off)\n{-# NOINLINE emitParseProgressUnsafe #-}\n\nemitParseProgress :: ParseProgressReporter -> Int -> IO ()\nemitParseProgress p off = do\n    let total = pprTotal p\n        completed = max 0 (min total off)\n        percent\n          | total <= 0 = 100\n          | otherwise = max 0 (min 100 ((completed * 100) `div` total))\n    prev <- readIORef (pprLastPercent p)\n    let shouldReport = percent > prev\n    when shouldReport $\n      writeIORef (pprLastPercent p) percent\n    when shouldReport (pprReport p completed total)\n\n-- Parser contexts ---------------------------------------------------------\n\ndata CTX = TOP | PAR | IF | SEQ | LOOP | DATA | DEF | CLASS | PROTO | EXT | ACTOR deriving (Show,Eq)\n\nwithCtx ctx = between (St.modify (pushCtx ctx)) (St.modify popCtx)\n\nifCtx accept ignore yes no = do\n    cs <- St.gets getCtxs\n    case filter (`notElem` ignore) cs of\n        c:_ | c `elem` accept -> yes\n        _                     -> no\n\nifNotCtx avoid ignore yes no = do\n    cs <- St.gets getCtxs\n    case filter (`notElem` ignore) cs of\n        c:_ | c `elem` avoid -> no\n        _  -> yes\n\n-- onlyIn s            = fail (\"statement only allowed inside \" ++ s)\n-- notIn s             = fail (\"statement not allowed inside \" ++ s)\nsuccess             = return ()\n\ncontextError                    :: ContextError -> [(SrcLoc, String)]\ncontextError err                = [(loc err, ctxMsg err)]\n\ndata ContextError   = OnlyTopLevel SrcLoc String\n                    | OnlyInActor SrcLoc String\n                    | OnlyInLoop SrcLoc String\n                    | OnlyInClassProtoExt SrcLoc String\n                    | OnlyInClass SrcLoc String\n                    | OnlyInFunction SrcLoc String\n                    | OnlyInFunctionOrActor SrcLoc String\n                    | NotInClassProtoExt SrcLoc String\n                    | NotInData SrcLoc String\n                    deriving (Show, Eq)\n\ninstance Control.Exception.Exception ContextError\n\ninstance HasLoc ContextError where\n  loc (OnlyTopLevel l _) = l\n  loc (OnlyInActor l _) = l\n  loc (OnlyInLoop l _) = l\n  loc (OnlyInClassProtoExt l _) = l\n  loc (OnlyInClass l _) = l\n  loc (OnlyInFunction l _) = l\n  loc (OnlyInFunctionOrActor l _) = l\n  loc (NotInClassProtoExt l _) = l\n  loc (NotInData l _) = l\n\n\nctxMsg (OnlyTopLevel loc str)          = str ++ \" declaration only allowed on the module top level\"\nctxMsg (OnlyInActor loc str)           = str ++ \" statement only allowed inside an actor body\"\nctxMsg (OnlyInLoop loc str)            = str ++ \" statement only allowed inside a loop\"\nctxMsg (OnlyInClassProtoExt loc str)   = str ++ \" decoration only allowed inside a class, protocol or extension\"\nctxMsg (OnlyInClass loc str)           = str ++ \" decoration only allowed inside a class\"\nctxMsg (OnlyInFunction loc str)        = str ++ \" statement only allowed inside a function\"\nctxMsg (OnlyInFunctionOrActor loc str) = str ++ \" statement only allowed inside a function or actor\"\nctxMsg (NotInClassProtoExt loc str)    = str ++ \" statement not allowed inside a class, protocol or extension\"\nctxMsg (NotInData loc str)             = str ++ \" statement not allowed inside a data tree\"\n\nassertTop loc str       = ifCtx [TOP]                   []                  success (Control.Exception.throw $ OnlyTopLevel loc str)\nassertActBody loc str   = ifCtx [ACTOR]                 []                  success (Control.Exception.throw $ OnlyInActor loc str)\nassertLoop loc str      = ifCtx [LOOP]                  [IF,SEQ]            success (Control.Exception.throw $ OnlyInLoop loc str)\nassertDecl loc str      = ifCtx [CLASS,PROTO,EXT]       []                  success (Control.Exception.throw $ OnlyInClassProtoExt loc str)\nassertClass loc str     = ifCtx [CLASS]                 []                  success (Control.Exception.throw $ OnlyInClass loc str)\nassertDef loc str       = ifCtx [DEF]                   [IF,SEQ,LOOP]       success (Control.Exception.throw $ OnlyInFunction loc str)\nassertDefAct loc str    = ifCtx [DEF,ACTOR]             [IF,SEQ,LOOP]       success (Control.Exception.throw $ OnlyInFunctionOrActor loc str)\nassertNotDecl loc str   = ifNotCtx [CLASS,PROTO,EXT]    [IF]                success (Control.Exception.throw $ NotInClassProtoExt loc str)\nassertNotData loc str   = ifNotCtx [DATA]               [IF,SEQ,LOOP]       success (Control.Exception.throw $ NotInData loc str)\n\nifPar                   = ifCtx [PAR]                   []\n\n--- Indentation error -------------------------------------------------------\n\ndata IndentationError  = IndentationError SrcLoc deriving (Show, Eq)\n\ninstance Control.Exception.Exception IndentationError\n\ninstance HasLoc IndentationError where\n   loc (IndentationError l) = l\n\nindentationError     :: IndentationError -> [(SrcLoc, String)]\nindentationError err = [(loc err, \"Too much indentation\")]\n\n-- Parser Exceptions --------------------------------------------------------\n\ndata CustomParseException = CustomParseException SrcLoc CustomParseError deriving (Show, Eq)\n\ninstance Control.Exception.Exception CustomParseException\n\nparseException :: SrcLoc -> CustomParseError -> a\nparseException loc customErr = Control.Exception.throw $ CustomParseException loc customErr\n\ndata ChunkScanError = ChunkScanError SrcLoc String deriving (Show, Eq)\n\ninstance Control.Exception.Exception ChunkScanError\n\n--- Whitespace consumers ----------------------------------------------------\n\n-- Whitespace consumer, which *does not* consume newlines\n-- but accepts line joining.\n-- This is used outside parentheses/brackets/braces\nsc1 :: Parser ()\nsc1 = void $ do\n  sc0\n  optional (char '\\\\' *> eol *> sc0) <?> \"\"\n  where sc0 = L.space (void $ takeWhile1P Nothing f) lineCmnt empty\n        f x = x == ' ' || x == '\\t'\n        lineCmnt  = L.skipLineComment \"#\"\n\n-- Whitespace consumer, which *does* consume also newlines.\n-- Used inside parentheses/brackets/braces\nsc2 :: Parser ()\nsc2 = L.space space1 (L.skipLineComment \"#\") empty\n\ncurrSC =  ifPar sc2 sc1\n\n\n--- Adding position info to a parser ------------------------------------------\n\n-- fetching the start column of a construct\nwithPos :: Parser a -> Parser (Pos,a)\nwithPos p = do\n          c <- L.indentLevel\n--          SourcePos f r c <- getSourcePos\n          a <- p\n--          getSourcePos\n          return (c,a)\n\n-- forcing a construct to start in prescribed column\natPos :: Pos -> Parser a -> Parser a\natPos p a = do\n         p2 <- L.indentLevel\n         if p2==p then a else L.incorrectIndent EQ p p2\n\nwithLoc :: Parser a -> Parser (SrcLoc,a)\nwithLoc p = do\n          off1 <- getOffset\n          a  <- p\n          off2 <- getOffset\n          return (Loc off1 off2, a)\n\nclass AddLoc a where\n  addLoc :: Parser a -> Parser a\n\ninstance AddLoc S.Import where\n  addLoc p = do\n         (l,stmt) <- withLoc p\n         return stmt{S.iloc = l}\n\ninstance AddLoc S.Stmt where\n  addLoc p = do\n         (l,stmt) <- withLoc p\n         return stmt{S.sloc = l}\n\ninstance AddLoc S.Decl where\n  addLoc p = do\n         (l,stmt) <- withLoc p\n         return stmt{S.dloc = l}\n\ninstance AddLoc S.Expr where\n  addLoc p = do\n         (l,expr) <- withLoc p\n         return expr{S.eloc = l}\n\ninstance AddLoc S.Name where\n  addLoc p = do\n         (l,name) <- withLoc p\n         case name of\n             S.Name _ n -> return (S.Name l n)\n             _          -> return name\n\ninstance AddLoc S.Except where\n  addLoc p = do\n         (l,exc) <- withLoc p\n         case exc of\n           S.ExceptAll _ -> return (S.ExceptAll l)\n           S.Except _ e -> return (S.Except l e)\n           S.ExceptAs _ e nm -> return (S.ExceptAs l e nm)\n\ninstance AddLoc S.Sliz where\n  addLoc p = do\n          (l,i) <- withLoc p\n          case i of\n            S.Sliz _ e1 e2 e3 -> return (S.Sliz l e1 e2 e3)\n\ninstance AddLoc S.Comp where\n  addLoc p = do\n          (l,cmp) <- withLoc p\n          case cmp of\n             S.CompFor _ t e c -> return (S.CompFor l t e c)\n             S.CompIf _ e c -> return (S.CompIf l e c)\n             S.NoComp -> return S.NoComp\n\ninstance AddLoc S.TSchema where\n  addLoc p = do\n          (l, S.TSchema _ q t) <- withLoc p\n          return $ S.TSchema l q t\n\ninstance AddLoc S.Type where\n  addLoc p = do\n          (l,ct) <- withLoc p\n          return ct{S.tloc = l}\n\ninstance AddLoc S.Pattern where\n  addLoc p = do\n         (l,pat) <- withLoc p\n         return pat{S.ploc = l}\n\n\nrwordLoc :: String -> Parser SrcLoc\nrwordLoc word = do\n          off <- getOffset\n          rword word\n          return $ Loc off (off+length word)\n\nlocate (Loc l _) = setOffset l\n\n--- Functions recognizing lexical items ----------------------------------------\n\nlexeme:: Parser a -> Parser a\nlexeme p = p <* currSC\n\nsymbol :: String -> Parser String\nsymbol str = lexeme (string str)\n\nnewline1 :: Parser [S.Stmt]\nnewline1 = const [] <$> (eol *> sc2)\n\n\n--- START OF STRING PARSING --------------------------------------------------------\n\n{-\n\nThe following principles for bytes and string literals are implemented by the following parse functions and\nthe transformations in Acton.Normalize\n\nLiteral syntax is as in subsections 2.4.1 and 2.4.2 in the Python Language Reference, version 3.10.4,\nexcept that only the following prefixes are allowed:\n- no prefix: string literal with interpolation\n- prefix 'f': string literal with interpolation. the f prefix is optional and\n  has no effect, it is supported as a convenience for users coming from Python\n- prefix 'r': raw string literal with no interpolation\n- prefix 'b': plain bytes literal\n- prefix 'rb': raw bytes literals\n\nThus we disallow\n- upper case versions of the above prefixes (for no particular reason other than the opinion that it is not an\n  unreasonable burden on the programmer to have to stick to lower case prefixes). For similar reasons we disallow\n  prefix 'br' and thus just form a raw literal by prefixing a plain literal with 'r'.)\n- the 'u' prefix which only exists in Python for legacy reasons.\n\nPrefix sequences are also as in subsection 2.4.1 with the following exceptions\n- unrecognized escape sequences (like \\p or \\z or any other sequence not listed in the table of 2.4.1)\n  are disallowed (unlike Python where they are allowed but the language reference declares that they will\n  become illegal in a future Python version.).\n- universal character names \\uxxxx and \\Uxxxxxxxx are unrecognized in bytes literals.\n- \\x must be followed by exactly two hex digits (unlike in C). To avoid a compilation error in the\n  generated C code, e.g. the string \"\\x12a\" is changed to \"\\x12\" \"a\" so that the 'a' is not interpreted by\n  the C compiler as a third hexadecimal digit in the \\x... sequence. Note that C allows sequences of string\n  literals which are concatenated during C compilation.\n\n-}\n\nstrings :: Parser S.Expr\nstrings = addLoc $\n       bytesLiteral\n       <|>\n       rawStringLiteral\n       <|>\n       fstringLiteral  -- Explicit f\"...\" syntax, with interpolation\n       <|>\n       stringLiteral -- \"\" strings - all strings support interpolation\n\n-- We use this `some` construct because Acton allows multiple adjacent strings\n-- to be effectively concatenated together without specifying any explicit\n-- operator. This is allowed in Python, and we have inherited this behavior.\n-- It's weird though, so we might want to change it in the future.\n-- For example, in Acton / Python, the following is valid:\n--   s = \"Hello, \" \"world!\"\n-- This will be parsed as a single string literal, not two separate ones.\n\nbytesLiteral :: Parser S.Expr\nbytesLiteral = S.BStrings NoLoc . concat <$> some bytesLiteralCombo\n\n-- | b\"\" and rb\"\"\nbytesLiteralCombo :: Parser [String]\nbytesLiteralCombo = plainbytesLiteral <|> rawbytesLiteral <?> \"bytes literal\"\n\n-- | Raw string literals (r\"...\") that don't support interpolation\nrawStringLiteral :: Parser S.Expr\nrawStringLiteral = S.Strings NoLoc . concat <$> some rawstrLiteral <?> \"string literal\"\n\n-- Docstring parser - parses strings with normal escape handling but no interpolation\ndocstringLiteral :: Parser S.Expr\ndocstringLiteral = (do\n    parts <- some docstringPlainLiteral\n    return $ S.Strings NoLoc [concat (concat parts)]\n  ) <?> \"docstring\"\n  where\n    docstringPlainLiteral =\n          plainstrLiteral\n      <|> rawstrLiteral\n\n-- Explicit f-string syntax (f\"...\") - kept for compatibility\n-- Note: Regular strings (\"...\") also support interpolation via the unified parser\nfstringLiteral :: Parser S.Expr\nfstringLiteral = concatStringLiterals singleFstring <?> \"string literal\"\n  where\n    -- Parse a single f-string\n    singleFstring =\n         try (parseInterpolatedString \"f\\\"\\\"\\\"\" \"\\\"\\\"\\\"\" (parseTextPart \"\\\"\" True True))\n      <|> try (parseInterpolatedString \"f'''\" \"'''\" (parseTextPart \"'\" True True))\n      <|> try (parseInterpolatedString \"f\\\"\" \"\\\"\" (parseTextPart \"\\\"\" False False))\n      <|> parseInterpolatedString \"f'\" \"'\" (parseTextPart \"'\" False False)\n\n-- | Normal strings in Acton support interpolation\n-- This means literal { and } must be escaped as {{ and }}\nstringLiteral :: Parser S.Expr\nstringLiteral = concatStringLiterals singleInterpolatedString <?> \"string literal\"\n  where\n    -- Parse a single string\n    singleInterpolatedString =\n         try (parseInterpolatedString \"\\\"\\\"\\\"\" \"\\\"\\\"\\\"\" (parseTextPart \"\\\"\" True True))\n      <|> try (parseInterpolatedString \"'''\" \"'''\" (parseTextPart \"'\" True True))\n      <|> try (parseInterpolatedString \"\\\"\" \"\\\"\" (parseTextPart \"\\\"\" False False))\n      <|> parseInterpolatedString \"'\" \"'\" (parseTextPart \"'\" False False)\n\n-- | Helper function to concatenate multiple adjacent string literals\n-- Supports both regular strings and f-strings with the same logic\nconcatStringLiterals :: Parser S.Expr -> Parser S.Expr\nconcatStringLiterals singleStringParser = do\n    -- Parse one or more consecutive string literals which are concatenated into a single string\n    -- like: a = 'foo' 'bar' or a = f'foo' f'bar'\n    parts <- some singleStringParser\n    -- Combine all parts into a single expression\n    case parts of\n        [single] -> return single  -- Single string, return as-is\n        multiple -> do\n            -- Multiple strings need to be concatenated\n            -- We need to combine all the format strings and collect all expressions\n            let (formatParts, exprLists) = unzip $ map extractParts multiple\n                combinedFormat = concat formatParts\n                combinedExprs = concat exprLists\n\n            if null combinedExprs\n                then return $ S.Strings NoLoc [combinedFormat]\n                else return $ S.BinOp NoLoc\n                               (S.Strings NoLoc [combinedFormat])\n                               S.Mod\n                               (if length combinedExprs == 1\n                                 then head combinedExprs\n                                 else S.Tuple NoLoc (foldr S.PosArg S.PosNil combinedExprs) S.KwdNil)\n  where\n    -- Extract format string and expressions from each part\n    extractParts :: S.Expr -> (String, [S.Expr])\n    extractParts (S.Strings _ ss) = (concat ss, [])\n    extractParts (S.BinOp _ (S.Strings _ [fmt]) S.Mod expr) =\n        case expr of\n            S.Tuple _ args _ -> (fmt, tupleToList args)\n            e -> (fmt, [e])\n    extractParts _ = (\"\", [])  -- Should not happen\n\n    -- Convert tuple arguments to list\n    tupleToList :: S.PosArg -> [S.Expr]\n    tupleToList S.PosNil = []\n    tupleToList (S.PosArg e rest) = e : tupleToList rest\n\n\n-- | Parts of an interpolated string\ndata StringPart\n  = TextPart String      -- ^ Regular text content\n  | ExprPart S.Expr String  -- ^ Expression with format specifier\n  deriving Show\n\n-- | Convert f-string parts to a format string with specifiers\nbuildFormatString :: [StringPart] -> String\nbuildFormatString [] = \"\"\nbuildFormatString (TextPart s : rest) = s ++ buildFormatString rest\nbuildFormatString (ExprPart _ fmt : rest) = \"%\" ++ fmt ++ buildFormatString rest\n\n-- | Parse a string with optional interpolation expressions\n-- Both regular strings and f-strings support interpolation in Acton\n-- i.e. \"{foo}\" and f\"{foo}\" are equivalent\nparseInterpolatedString :: String -> String -> (Int -> Parser StringPart) -> Parser S.Expr\nparseInterpolatedString startQuote endQuote textPartParser = lexeme $ do\n  startLoc <- getOffset\n  try $ string startQuote\n  let startQuoteCharOffset = startLoc + (length startQuote - length endQuote)\n  let stringPart = choice [\n          -- Escaped braces - handle these BEFORE expression parsing\n          try (string \"{{\" >> return (TextPart \"{\")),\n          try (string \"}}\" >> return (TextPart \"}\")),\n          -- Expression parts (now without the notFollowedBy check)\n          try exprPart,\n          -- Regular text\n          textPartParser startQuoteCharOffset\n        ]\n  parts <- many stringPart\n  string endQuote <|> do\n    -- If we couldn't parse the closing quote, check why\n    currentPos <- getOffset\n    nextChar <- lookAhead (optional anySingle)\n    let isMultiline = length endQuote == 3  -- Triple quotes indicate multiline strings\n    case nextChar of\n      Nothing ->\n        if isMultiline\n        then parseException (Loc (startLoc - length startQuote) startLoc) $ MissingClosingQuote endQuote\n        else fail $ \"string at position \" ++ show startLoc ++ \" is not closed\"\n      _ -> fail $ \"missing closing \" ++ endQuote\n\n  -- Check if we found any expressions\n  let exprs = [e | ExprPart e _ <- parts]\n\n  if null exprs\n    then do\n      -- No expressions found, create a regular string\n      let textContent = concat [s | TextPart s <- parts]\n      -- Apply hex splitting to handle cases like \"\\x48ello\" -> [\"\\x48\", \"ello\"]\n      return $ S.Strings NoLoc (hexSplitString textContent)\n    else do\n      -- Found expressions, create interpolated string format\n      let formatStr = buildFormatString parts\n          result = S.BinOp NoLoc\n                    (S.Strings NoLoc [formatStr])\n                    S.Mod\n                    (if length exprs == 1\n                      then head exprs\n                      else S.Tuple NoLoc (foldr S.PosArg S.PosNil exprs) S.KwdNil)\n      return result\n\n-- | Create a text part parser for given quote style\nparseTextPart :: String -> Bool -> Bool -> Int -> Parser StringPart\nparseTextPart quoteStr isTriple handleNewlines startOfString = do\n  chunks <- some $ choice [\n      -- Use existing escape sequence parsers with better error handling\n      try (char '\\\\' >> choice [\n          -- Escaped quotes - handle quote-specific escaping\n          try (string quoteStr >> return quoteStr),\n\n          -- Use existing escape parsers for consistency and better error messages\n          try hexEscape,\n          try univ1Escape,\n          try univ2Escape,\n          try octEscape,\n          try singleCharEscape,\n          try newlineEscape,\n\n          -- Handle unknown escape sequences with proper error\n          anyC >>= \\c -> unknownEscape (return c)\n        ]),\n\n      -- Handle newlines in triple-quoted strings\n      if handleNewlines\n        then try (string \"\\n\" >> return \"\\\\n\")\n        else empty,\n\n      -- Handle quotes in triple-quoted strings\n      if isTriple\n        then try (do\n                -- When we see a quote char, check if it's part of closing sequence\n                c <- char (head quoteStr)\n                quotes <- lookAhead $ many (char (head quoteStr))\n                let totalQuotes = 1 + length quotes\n                case totalQuotes of\n                  -- 1-2 quotes: always consume as content\n                  1 -> return [c]\n                  2 -> char (head quoteStr) >> return [c, head quoteStr]\n                  -- 3 quotes exactly: this is the closing sequence, stop\n                  3 -> empty\n                  -- 4 quotes: consume 1, leave 3 for closing\n                  4 -> return [c]\n                  -- 5 quotes: consume 2, leave 3 for closing\n                  5 -> char (head quoteStr) >> return [c, head quoteStr]\n                  -- 6+ quotes: this is an error\n                  _ -> do\n                    curPos <- getOffset\n                    let startPos = curPos - 1\n                        endPos   = startPos + totalQuotes\n                    parseException (Loc (startPos) endPos) (TooManyQuotesError quoteStr)\n                    )\n        else empty,\n\n      -- Any other character not in braces or quotes\n      if not isTriple\n        then do\n          -- Check for newline in single-line string\n          nextChar <- lookAhead (optional (char '\\n'))\n          case nextChar of\n            Just _ -> do\n              pos <- getOffset\n              parseException (Loc startOfString pos) $ MissingClosingQuote quoteStr\n            Nothing -> do\n              (loc, c) <- withLoc $ noneOf (\"{}\" ++ quoteStr ++ \"\\n\")\n              return [c]\n        else\n          (:[]) <$> noneOf (\"{}\" ++ quoteStr)\n    ]\n\n  -- Concatenate chunks\n  return (TextPart (concat chunks))\n\n\n-- | Parse an expression in braces with optional format specifier\nexprPart :: Parser StringPart\nexprPart = do\n    openLoc <- getOffset\n    char '{'\n    -- Allow for spaces around the expression\n    many (char ' ')\n\n    -- Check for empty expression or immediate colon\n    closeLoc <- getOffset\n    nextChar <- lookAhead (optional (oneOf \"}:\"))\n    case nextChar of\n        Just '}' -> parseException (Loc closeLoc closeLoc) EmptyInterpolationExpression\n        Just ':' -> parseException (Loc closeLoc closeLoc) MissingExpressionBeforeFormat\n        _ -> return ()\n\n    -- Parse the expression - now allowing interpolated strings since f-prefix is optional\n    parsedExpr <- expr <?> \"expression\"\n\n    -- Allow spaces before format specifier or closing brace\n    many (char ' ')\n\n    -- Check for optional format specifier\n    formatInfo <- (char ':' *> formatSpec) <|> do\n        closeBraceLoc <- getOffset\n        char '}' <|> parseException (Loc (openLoc + 1) (closeBraceLoc)) UnclosedInterpolationBrace\n        return (\"s\", False, Nothing, Nothing, False, Nothing)\n\n    let (fmt, isZeroPad, precisionInfo, typeSpecInfo, isCenterAlign, widthInfo) = formatInfo\n\n    -- Apply formatting logic\n    finalExpr <-\n        if isCenterAlign && widthInfo /= Nothing\n        then do\n            -- Handle center alignment by using str.center() method\n            let widthExpr = case widthInfo of\n                                Just w -> S.Int NoLoc (read w) w\n                                Nothing -> S.Int NoLoc 0 \"0\"\n                -- First convert the expression to a string\n                strExpr = S.Call NoLoc (S.Var NoLoc (S.NoQ (S.Name NoLoc \"str\"))) (S.PosArg parsedExpr S.PosNil) S.KwdNil\n                -- Then call the center method on the string\n                centerMethod = S.Dot NoLoc strExpr (S.Name NoLoc \"center\")\n                -- Call center(width)\n                centeredExpr = S.Call NoLoc centerMethod (S.PosArg widthExpr S.PosNil) S.KwdNil\n            return centeredExpr\n        -- Handle float format specifiers directly\n        else if isZeroPad || (precisionInfo /= Nothing)\n        then\n            -- For formatting with a type specifier (like .2f), pass the raw expression\n            -- This allows printf to apply the format directly to the value\n            return parsedExpr\n        -- For normal formatting, convert to str\n        else return $ S.Call NoLoc (S.Var NoLoc (S.NoQ (S.Name NoLoc \"str\"))) (S.PosArg parsedExpr S.PosNil) S.KwdNil\n\n    return $ ExprPart finalExpr fmt\n\n-- | Parse format specifier after the colon (colon is already consumed)\nformatSpec :: Parser (String, Bool, Maybe String, Maybe Char, Bool, Maybe String)  -- Returns (format, isZeroPadded, precision, typeSpec, isCenterAlign, width)\nformatSpec = do\n    specLoc <- getOffset\n    -- Allow spaces at the beginning\n    many (char ' ')\n\n    -- Check if there's any content before trying to parse\n    beforeParseLoc <- getOffset\n    nextChar <- lookAhead (optional anySingle)\n    case nextChar of\n        Just '}' -> parseException (Loc specLoc beforeParseLoc) EmptyFormatSpecifierError\n        _ -> return ()\n\n    -- Try to parse fill character and alignment\n    -- First, check if we have an invalid character at the start\n    firstChar <- lookAhead (optional anySingle)\n    _ <- case firstChar of\n        Just c | c `notElem` \"<>^+-#0123456789.} \" && c /= '\\t' && c /= '\\n' -> do\n            -- Check if this might be a fill character followed by alignment\n            secondChar <- lookAhead (optional (anySingle >> anySingle))\n            case secondChar of\n                Just a | a `elem` \"<>^\" -> return ()  -- Valid fill+align pattern\n                _ -> do\n                    -- Record position before consuming\n                    badCharPos <- getOffset\n                    -- Consume the character to advance position\n                    _ <- anySingle\n                    parseException (Loc badCharPos (badCharPos + 1)) $\n                         InvalidCharInFormatSpecifier c\n        Just '\\t' -> do\n            tabPos <- getOffset\n            _ <- anySingle\n            parseException (Loc tabPos (tabPos + 1)) TabInFormatSpecifier\n        Just '\\n' -> do\n            nlPos <- getOffset\n            _ <- anySingle\n            parseException (Loc nlPos (nlPos + 1)) NewlineInFormatSpecifier\n        _ -> return ()\n\n    mbFillAlign <- optional $ try (do\n        -- Try to parse fill + alignment (strict validation)\n        try (do\n            f <- anySingle\n            a <- oneOf \"<>^\" <?> \"alignment character (<, >, or ^)\"\n            return (f, Just a)\n          ) <|> do\n            a <- oneOf \"<>^\" <?> \"alignment character (<, >, or ^)\"\n            return (' ', Just a)\n      )\n\n    let (fill, align) = fromMaybe (' ', Nothing) mbFillAlign\n\n    -- Optional sign\n    _sign <- optional $ oneOf \"+-\"\n\n    -- Optional # (alternate form)\n    _alternate <- optional $ char '#'\n\n    -- Optional zero padding (0 flag)\n    zeroPad <- optional $ char '0'\n\n    -- Optional width\n    width <- optional $ some digitChar\n\n    -- Optional precision\n    precision <- optional $ do\n        char '.'\n        digitLoc <- getOffset\n        digits <- optional $ some digitChar\n        case digits of\n            Nothing -> parseException (Loc digitLoc digitLoc) MissingFormatPrecisionDigits\n            Just d -> return d\n\n    -- Optional type specifier\n    typeLoc <- getOffset\n    typeSpec <- optional (oneOf \"fdeEgGnoxX%bos\" <?> \"type specifier\")\n\n    -- Allow spaces before closing brace\n    many (char ' ')\n\n    -- Check for any remaining invalid characters\n    invalidCharLoc <- getOffset\n    invalidChar <- lookAhead (optional (noneOf \"}\"))\n    case invalidChar of\n        Just c ->\n            if c == '\\t'\n            then parseException (Loc invalidCharLoc invalidCharLoc) TabInFormatSpecifier\n            else if c == '\\n'\n            then parseException (Loc invalidCharLoc invalidCharLoc) NewlineInFormatSpecifier\n            else parseException (Loc invalidCharLoc invalidCharLoc) $ InvalidCharInFormatSpecifier c\n        Nothing -> return ()\n\n    -- Check if we parsed nothing meaningful (this should be rare now)\n    endLoc <- getOffset\n    when (align == Nothing && _sign == Nothing && zeroPad == Nothing &&\n          width == Nothing && precision == Nothing && typeSpec == Nothing &&\n          beforeParseLoc == endLoc) $\n        parseException (Loc specLoc endLoc) $ InvalidFormatSpecifier \"\"\n\n    -- Consume the closing brace\n    char '}' <?> \"closing brace '}' after format specifier\"\n\n    -- Determine various format properties\n    let isZeroPadding = zeroPad == Just '0' && width /= Nothing\n        isCenterAlign = align == Just '^'\n\n    -- Convert to printf format\n    let fmt = case (precision, typeSpec) of\n            -- Float with precision and width (e.g., 10.2f becomes %10.2f for printf)\n            (Just p, Just 'f') -> case (zeroPad, width) of\n                (Just '0', Just w) -> \"0\" ++ w ++ \".\" ++ p ++ \"f\"  -- Zero-padded float\n                (_, Just w) -> w ++ \".\" ++ p ++ \"f\"               -- Regular float with width\n                (_, Nothing) -> \".\" ++ p ++ \"f\"                   -- Just precision, no width\n            -- Default to float if precision specified but no type\n            (Just p, _) -> case (zeroPad, width) of\n                (Just '0', Just w) -> \"0\" ++ w ++ \".\" ++ p ++ \"f\"\n                (_, Just w) -> w ++ \".\" ++ p ++ \"f\"\n                (_, Nothing) -> \".\" ++ p ++ \"f\"\n            -- Float without precision\n            (Nothing, Just 'f') -> \"f\"\n            -- Other formats based on alignment and width\n            (Nothing, _) -> case (zeroPad, align, width) of\n                -- Zero padding with width (for numbers) - use integer format\n                (Just '0', _, Just w) -> \"0\" ++ w ++ \"d\"\n                -- Left-aligned with width\n                (_, Just '<', Just w) -> \"-\" ++ w ++ \"s\"\n                -- Right-aligned with width\n                (_, Just '>', Just w) -> w ++ \"s\"\n                -- Center-aligned with width\n                (_, Just '^', Just w) -> \"s\"  -- Width handled separately in expr processing\n                -- Just width, no alignment\n                (_, Nothing, Just w) -> w ++ \"s\"\n                -- Default case\n                _ -> \"s\"\n\n    return (fmt, isZeroPadding, precision, typeSpec, isCenterAlign, width)\n\n-- Split string when hex escape is followed by hex digit (to prevent C compiler issues)\n-- Only splits if the string contains actual hex escapes (not literal \\x patterns)\nhexSplitString :: String -> [String]\nhexSplitString \"\" = [\"\"]\nhexSplitString s\n  | hasActualHexEscapes s = filter (not . null) $ reverse $ map reverse $ process s [] []\n  | otherwise = [s]  -- No splitting needed for raw strings or strings without hex escapes\n  where\n    -- Check if string has actual hex escapes (single backslash followed by x and hex digits)\n    -- Raw strings produce \\\\x patterns (double backslashes) which should NOT be split\n    hasActualHexEscapes [] = False\n    hasActualHexEscapes ('\\\\':'\\\\':'x':rest) = hasActualHexEscapes rest  -- Skip \\\\x pattern (raw string)\n    hasActualHexEscapes ('\\\\':'x':h1:h2:rest)\n      | isHex h1 && isHex h2 = True\n      | otherwise = hasActualHexEscapes rest\n    hasActualHexEscapes (_:rest) = hasActualHexEscapes rest\n\n    process [] acc chunks = acc : chunks\n    process ('\\\\':'x':h1:h2:rest) acc chunks\n      | isHex h1 && isHex h2 && (not (null rest) && isHex (head rest)) =\n          -- Next char is hex, split here - complete current chunk with hex escape\n          let completedChunk = h2:h1:'x':'\\\\':acc\n          in process rest [] (completedChunk : chunks)\n      | isHex h1 && isHex h2 =\n          -- Valid hex escape, continue accumulating\n          process rest (h2:h1:'x':'\\\\':acc) chunks\n      | otherwise =\n          -- Invalid hex escape, keep as-is\n          process (h1:h2:rest) ('x':'\\\\':acc) chunks\n    process (c:cs) acc chunks = process cs (c:acc) chunks\n    isHex c = c `elem` \"0123456789abcdefABCDEF\"\n\n\nnewlineEscape =  \"\" <$ newline\nsingleCharEscape =  (\\c -> '\\\\':c:[]) <$> (oneOf (\"\\'\\\"\\\\abfnrtv\"))\nhexEscape = do\n      char 'x'\n      (loc,cs) <- withLoc (count' 0 2 hexDigitChar)\n      if length cs == 2\n       then return (\"\\\\x\" ++ cs)\n       else parseException loc $ IncompleteHexEscape cs\noctEscape = do\n       (loc,cs) <- withLoc (count' 1 3 octDigitChar)\n       if length cs == 3 && head cs > '3'\n          then  parseException loc OctalEscapeOutOfRange\n          else return (\"\\\\\" ++ cs)\nuniv1Escape = do\n      char 'u'\n      (loc,cs) <- withLoc (count' 0 4 hexDigitChar)\n      if length cs < 4\n        then parseException loc $ IncompleteUnicodeEscape 4 (length cs)\n        else return (\"\\\\u\" ++ cs)\nuniv2Escape = do\n      char 'U'\n      (loc,cs) <- withLoc (count' 0 8 hexDigitChar)\n      if length cs < 8\n        then parseException loc $ IncompleteUnicodeEscape 8 (length cs)\n        else return (\"\\\\U\" ++ cs)\n\nasciiC   = do\n      (loc,c) <- withLoc anySingle\n      if c == '\\n'\n         then parseException loc (MissingClosingQuote \"\\\"\")\n         else if isAscii c\n              then return [c]\n              else parseException loc NonAsciiInBytesLiteral\n\nanyC  = do\n      (loc,c) <- withLoc anySingle\n      if c == '\\n'\n         then parseException loc (MissingClosingQuote \"\\\"\")\n         else return [c]\n\nunknownEscape charParser = do\n         (loc,c) <- withLoc charParser\n         parseException loc UnknownEscapeSequence\n\nplainLiteral charParser prefix tailEscapes = stringTempl \"\\\"\\\"\\\"\" longItem esc prefix\n                                          <|> stringTempl \"'''\" longItem esc prefix\n                                          <|> stringTempl \"\\\"\" charParser esc prefix\n                                          <|> stringTempl \"'\" charParser esc prefix\n    where longItem = (\"\\\\n\" <$ newline) <|> charParser  -- newlines allowed in triple-quoted literals\n          esc =  newlineEscape <|> singleCharEscape <|> hexEscape <|> octEscape <|> tailEscapes\n\nplainbytesLiteral = plainLiteral asciiC \"b\" (unknownEscape asciiC)\n\nplainstrLiteral = plainLiteral anyC \"\" ( univ1Escape <|> univ2Escape <|> unknownEscape anyC)\n\nrawLiteral charParser prefix = stringTempl \"\\\"\\\"\\\"\" longItem esc prefix\n              <|> stringTempl \"'''\" longItem esc prefix\n              <|> stringTempl \"\\\"\" charParser esc prefix\n              <|> stringTempl \"'\"  charParser  esc prefix\n   where longItem =  (\"\\\\n\" <$ newline) <|> charParser\n         esc = newlineEscapeRaw <|> singleCharEscapeRaw <|> generalEscapeRaw\n         newlineEscapeRaw = \"\\\\\\\\\\\\n\" <$ newline\n         singleCharEscapeRaw = (\\c -> \"\\\\\\\\\\\\\" ++ [c]) <$> (oneOf (\"\\'\\\"\"))\n         generalEscapeRaw = return \"\\\\\\\\\"\n\nrawbytesLiteral = rawLiteral asciiC \"rb\"\n\nrawstrLiteral = rawLiteral ((:[]) <$> anySingle) \"r\"\n\nstringTempl :: String -> Parser String -> Parser String -> String -> Parser [String]\nstringTempl q single esc prefix = do\n    startLoc <- getOffset\n    _ <- string (prefix++q)\n    -- For single-quoted strings, guard against newline before closing quote\n    let startQuoteOffset = startLoc + length prefix\n        guardedSingle = if length q == 1\n                        then do\n                          -- If the next char is a newline, treat as unclosed string\n                          mb <- lookAhead (optional anySingle)\n                          case mb of\n                            Just '\\n' -> do\n                              pos <- getOffset\n                              parseException (Loc startQuoteOffset pos) (MissingClosingQuote q)\n                            _ -> single\n                        else single\n    content <- manyTillEsc guardedSingle esc (string q <?> closingQuoteError startLoc q)\n    currSC  -- Apply lexeme whitespace consumption\n    return $ hexSplitString . concat $ content\n  where\n    closingQuoteError startLoc quote\n      | quote `elem` [\"\\\"\\\"\\\"\", \"'''\"] = \"closing triple quote \" ++ quote ++ \" for string starting at position \" ++ show startLoc\n      | otherwise = \"closing quote \" ++ quote ++ \" for string\"\n\nmanyTillEsc, someTillEsc :: Parser String -> Parser String -> Parser String -> Parser [String]\nmanyTillEsc p esc end =  (const [] <$> end) <|> (someTillEsc p esc end)\n\nsomeTillEsc p esc end = do\n    a <- (char '\\\\' *> esc) <|> p\n    b <- manyTillEsc p esc end\n    return $ a : b\n\n--- END OF STRING PARSING --------------------------------------------------------\n\n-- Reserved words, other symbols and names ----------------------------------------------------------\n\nrword :: String -> Parser ()\nrword w = (lexeme . try) (string w *> notFollowedBy (alphaNumChar <|> char '_'))\n\ncomma     = symbol \",\" <?> \"comma\"\ncolon     = symbol \":\"\nsemicolon = symbol \";\"\nequals    = symbol \"=\"\nstar      = symbol \"*\"\nstarstar  = symbol \"**\"\ndot       = symbol \".\"\narrow     = symbol \"->\"\nfatarrow  = symbol \"=>\"\nqmark     = symbol \"?\"\nvbar      = symbol \"|\"\n\n-- Parser for operator that is a prefix of another operator\n-- Slightly hackish; depends on the (presently true) fact that chars in argument to oneOf are\n-- the only chars that can follow directly after the prefix operator in a longer operator name.\nopPref :: String -> Parser String\nopPref op = (lexeme . try) (string op <* notFollowedBy (oneOf \"<>=/*\"))\n\nsingleStar = (lexeme . try) (char '*' <* notFollowedBy (char '*'))\n\nidentifier :: Parser String\nidentifier = (lexeme . try) $ do\n    off <- getOffset\n    c <-  satisfy (\\c -> isAlpha c || c=='_') <?> \"identifier\"\n    cs <- hidden (takeWhileP Nothing (\\c -> isAlphaNum c || c=='_'))\n    let x = c:cs\n    if S.isKeyword x\n      then parseError (TrivialError off (Just (Tokens (N.fromList x))) (Set.fromList [Label (N.fromList \"identifier\")]))\n      else return x\n\nname, escname, tvarname :: Parser S.Name\nname = do off <- getOffset\n          x <- identifier\n          if isUpper (head x) && all isDigit (tail x)\n            then parseError (FancyError off (Set.fromList [ErrorCustom (TypeVariableNameError x)]))\n            else return $ S.Name (Loc off (off+length x)) x\n\nescname = name <|> addLoc (S.Name NoLoc . head <$> plainstrLiteral)  -- Assumes an escname cannot contain hex escape sequences\n\ntvarname = do off <- getOffset\n              x <- identifier\n              if isUpper (head x) && all isDigit (tail x)\n               then return $ S.Name (Loc off (off+length x)) x\n               else parseError (TrivialError off (Just (Tokens (N.fromList x))) (Set.fromList [Label (N.fromList (\"type variable (upper case letter optionally followed by digits)\"))]))\n\nmodule_name :: Parser S.ModName\nmodule_name = do\n  n <- name\n  ns <- many (dot *> escname)\n  return $ S.ModName (n:ns)\n\nqual_name :: Parser S.QName\nqual_name = do\n  n <- name\n  ns <- many (dot *> escname)\n  case n:ns of\n    [n] -> return $ S.NoQ n\n    ns' -> return $ S.QName (S.ModName (init ns')) (last ns')\n\n\n-- recognizers for numbers are used directly in function atom below.\n\n--- Helper functions for parenthesised forms -----------------------------------\n\nparens, brackets, braces :: Parser a -> Parser a\nparens p = withCtx PAR (L.symbol sc2 \"(\" *> p <* (char ')' <?> \"closing ')'\")) <* currSC\n\nbrackets p = withCtx PAR (L.symbol sc2 \"[\" *> p <* (char ']' <?> \"closing ']'\")) <* currSC\n\nbraces p = withCtx PAR (L.symbol sc2 \"{\" *> p <* (char '}' <?> \"closing '}'\")) <* currSC\n\n--- Top-level parsers ------------------------------------------------------------\n\nmodule_docstring :: Parser String\nmodule_docstring = do\n    S.Strings _ ss <- addLoc docstringLiteral\n    return (unescapeString (concat ss))\n\nfile_input :: Parser ([S.Import], Maybe String, S.Suite)\nfile_input = sc2 *> do\n    -- Allow optional module docstring before imports\n    mbDocstring <- optional (try (L.nonIndented sc2 module_docstring <* eol <* sc2))\n    is <- imports\n    s <-  withCtx TOP top_suite\n    validateModuleSuite s\n    eof\n    return (is, mbDocstring, s)\n\n-- (((,) <$> imports <*> withCtx TOP top_suite) <* eof)\n\nimport_input :: Parser ([S.Import], Maybe String)\nimport_input = do\n    (is, mbDocstring, _) <- module_header_with_offset\n    return (is, mbDocstring)\n\nmodule_header_with_offset :: Parser ([S.Import], Maybe String, Int)\nmodule_header_with_offset = sc2 *> do\n    mbDocstring <- optional (try (L.nonIndented sc2 module_docstring <* eol <* sc2))\n    is <- imports\n    off <- getOffset\n    return (is, mbDocstring, off)\n\nimports :: Parser [S.Import]\nimports = many (L.nonIndented sc2 import_stmt <* eol <* sc2 <* reportParseProgress)\n\ntop_suite :: Parser S.Suite\ntop_suite = concat <$> (many (L.nonIndented sc2 (stmt <* reportParseProgress) <|> (newline1 <* reportParseProgress)))\n\nvalidateModuleSuite :: S.Suite -> Parser ()\nvalidateModuleSuite = go Set.empty\n  where\n    go seen [] = return ()\n    go seen (stmt:stmts) =\n      case stmt of\n        S.Assign _ pats _ -> do\n          let names = Names.bound pats\n          if null names\n            then parseException (loc pats) InvalidTopLevelAssignmentPattern\n            else do\n              seen' <- addNames seen names\n              go seen' stmts\n        S.Signature{} -> go seen stmts\n        S.Decl{}      -> go seen stmts\n        _             -> parseException (S.sloc stmt) InvalidModuleStatement\n\n    addNames seen [] = return seen\n    addNames seen (n:ns)\n      | n `Set.member` seen = parseException (loc n) (DuplicateTopLevelAssignment (S.rawstr n))\n      | otherwise           = addNames (Set.insert n seen) ns\n\ndata SourceSpan = SourceSpan !Int !Int deriving (Eq, Show)\n\ndata TopLevelChunk = TopLevelChunk\n  { chunkSpan  :: !SourceSpan\n  , chunkInput :: String\n  , chunkLine  :: !Int\n  } deriving (Eq, Show)\n\ndata ScanMode = ScanString\n  { scanQuote       :: Char\n  , scanTriple      :: Bool\n  , scanInterpolate :: Bool\n  , scanInterpDepth :: Int\n  } deriving (Eq, Show)\n\ndata ChunkScanState = ChunkScanState\n  { scanActiveStart :: Maybe Int\n  , scanActiveInput :: Maybe String\n  , scanActiveLine  :: Maybe Int\n  , scanDepth       :: Int\n  , scanModes       :: [ScanMode]\n  , scanAtLineStart :: Bool\n  , scanLine        :: Int\n  , scanContinued   :: Bool\n  , scanBackslash   :: Bool\n  , scanPrev1       :: Maybe Char\n  , scanPrev2       :: Maybe Char\n  } deriving (Eq, Show)\n\nscanTopLevelChunks :: String -> Int -> (TopLevelChunk -> IO ()) -> IO (Either ChunkScanError ())\nscanTopLevelChunks src start emit\n  | start < 0 || start > length src = return (Left (ChunkScanError NoLoc \"invalid module body offset\"))\n  | otherwise = go start (drop start src) initScan\n  where\n    initScan = ChunkScanState\n      { scanActiveStart = Nothing\n      , scanActiveInput = Nothing\n      , scanActiveLine = Nothing\n      , scanDepth = 0\n      , scanModes = []\n      , scanAtLineStart = start == 0 || charBefore start == Just '\\n'\n      , scanLine = startLine\n      , scanContinued = False\n      , scanBackslash = False\n      , scanPrev1 = charBefore start\n      , scanPrev2 = if start >= 2 then Just (src !! (start - 2)) else Nothing\n      }\n\n    charBefore 0 = Nothing\n    charBefore n = Just (src !! (n - 1))\n\n    startLine = 1 + length (filter (== '\\n') (take start src))\n\n    go i [] st = do\n      emitOpenChunk i st\n      return (Right ())\n    go i xs@(c:_) st\n      | startsBoundary c st =\n          openChunk i xs st >>= scanCode i xs\n      | scanActiveStart st == Nothing\n        && null (scanModes st)\n        && scanDepth st == 0\n        && not (isTriviaStart c) =\n          return (Left (ChunkScanError (Loc i (i + 1)) \"non-top-level text before first chunk\"))\n      | otherwise =\n          scanStep i xs st\n\n    startsBoundary c st =\n      scanAtLineStart st &&\n      not (scanContinued st) &&\n      scanDepth st == 0 &&\n      null (scanModes st) &&\n      not (isTriviaStart c)\n\n    isTriviaStart c = c == '\\n' || c == '\\r' || c == ' ' || c == '\\t' || c == '#'\n\n    openChunk i xs st = do\n      emitOpenChunk i st\n      return st\n        { scanActiveStart = Just i\n        , scanActiveInput = Just xs\n        , scanActiveLine = Just (scanLine st)\n        }\n\n    emitOpenChunk i st =\n      case scanActiveStart st of\n        Just s\n          | s < i ->\n              emit (TopLevelChunk (SourceSpan s i)\n                                    (fromMaybe [] (scanActiveInput st))\n                                    (fromMaybe (scanLine st) (scanActiveLine st)))\n        _ -> return ()\n\n    scanStep i xs st =\n      case scanModes st of\n        [] -> scanCode i xs st\n        _  -> scanString i xs st\n\n    scanCode i xs@(c:_) st\n      | c == '#' =\n          skipComment i xs st { scanBackslash = False }\n      | Just (mode, qlen) <- stringStartMode xs st =\n          let (_, rest, st') = consumeMany False qlen i xs st\n          in go (i + qlen) rest st' { scanModes = mode : scanModes st', scanBackslash = False }\n      | c `elem` \"([{\" =\n          let (_, rest, st') = consumeMany True 1 i xs st { scanDepth = scanDepth st + 1 }\n          in go (i + 1) rest st'\n      | c `elem` \")]}\" =\n          let depth' = max 0 (scanDepth st - 1)\n              (_, rest, st') = consumeMany True 1 i xs st { scanDepth = depth' }\n          in go (i + 1) rest st'\n      | otherwise =\n          let (_, rest, st') = consumeMany True 1 i xs st\n          in go (i + 1) rest st'\n\n    scanString i [] st = go i [] st\n    scanString i xs@(c:_) st =\n      case scanModes st of\n        [] -> scanCode i xs st\n        mode:rest\n          | scanInterpDepth mode == 0 -> scanStringText i xs mode rest st\n          | otherwise                 -> scanInterpolation i xs mode rest st\n\n    scanStringText i xs@(c:_) mode rest st\n      | c == '\\\\' =\n          let n = case xs of\n                _:_:_ -> 2\n                _     -> 1\n              (_, xs', st') = consumeMany False n i xs st\n          in go (i + n) xs' st'\n      | scanInterpolate mode && startsWith \"{{\" xs =\n          let (_, xs', st') = consumeMany False 2 i xs st\n          in go (i + 2) xs' st'\n      | scanInterpolate mode && startsWith \"}}\" xs =\n          let (_, xs', st') = consumeMany False 2 i xs st\n          in go (i + 2) xs' st'\n      | scanInterpolate mode && c == '{' =\n          let mode' = mode { scanInterpDepth = 1 }\n              (_, xs', st') = consumeMany False 1 i xs st { scanModes = mode' : rest }\n          in go (i + 1) xs' st'\n      | Just n <- tripleInterpolatedQuoteText xs mode =\n          let (_, xs', st') = consumeMany False n i xs st\n          in go (i + n) xs' st'\n      | closesString xs mode =\n          let n = if scanTriple mode then 3 else 1\n              (_, xs', st') = consumeMany False n i xs st { scanModes = rest }\n          in go (i + n) xs' st'\n      | otherwise =\n          let (_, xs', st') = consumeMany False 1 i xs st\n          in go (i + 1) xs' st'\n\n    scanInterpolation i xs@(c:_) mode rest st\n      | c == '#' =\n          skipComment i xs st\n      | Just (nested, qlen) <- stringStartMode xs st =\n          let (_, xs', st') = consumeMany False qlen i xs st\n          in go (i + qlen) xs' st' { scanModes = nested : scanModes st' }\n      | c == '{' =\n          let mode' = mode { scanInterpDepth = scanInterpDepth mode + 1 }\n              (_, xs', st') = consumeMany False 1 i xs st { scanModes = mode' : rest }\n          in go (i + 1) xs' st'\n      | c == '}' =\n          let depth' = scanInterpDepth mode - 1\n              modes' = if depth' == 0 then mode { scanInterpDepth = 0 } : rest\n                                      else mode { scanInterpDepth = depth' } : rest\n              (_, xs', st') = consumeMany False 1 i xs st { scanModes = modes' }\n          in go (i + 1) xs' st'\n      | otherwise =\n          let (_, xs', st') = consumeMany False 1 i xs st\n          in go (i + 1) xs' st'\n\n    stringStartMode xs@(q:_) st\n      | q == '\"' || q == '\\'' =\n          let triple = startsWith [q, q, q] xs\n              raw = scanPrev1 st == Just 'r' ||\n                    (scanPrev2 st == Just 'r' && scanPrev1 st == Just 'b')\n              bytes = scanPrev1 st == Just 'b' ||\n                      (scanPrev2 st == Just 'r' && scanPrev1 st == Just 'b')\n              interpolate = not raw && not bytes\n              qlen = if triple then 3 else 1\n          in Just (ScanString q triple interpolate 0, qlen)\n      | otherwise = Nothing\n    stringStartMode [] _ = Nothing\n\n    closesString xs mode\n      | scanTriple mode = startsWith (replicate 3 (scanQuote mode)) xs\n      | otherwise = case xs of\n          c:_ -> c == scanQuote mode\n          []  -> False\n\n    tripleInterpolatedQuoteText xs mode\n      | scanTriple mode && scanInterpolate mode =\n          case quoteRunLength (scanQuote mode) xs of\n            4 -> Just 1\n            5 -> Just 2\n            _ -> Nothing\n      | otherwise = Nothing\n\n    quoteRunLength q = length . takeWhile (== q)\n\n    startsWith prefix xs = prefix `isPrefixOf` xs\n\n    skipComment i [] st = go i [] st\n    skipComment i xs@(c:_) st\n      | c == '\\n' =\n          let (_, xs', st') = consumeMany False 1 i xs st\n          in go (i + 1) xs' st'\n      | otherwise =\n          let (_, xs', st') = consumeMany False 1 i xs st\n          in skipComment (i + 1) xs' st'\n\n    consumeMany _ 0 i xs st = (i, xs, st)\n    consumeMany track n i (c:cs) st =\n      let st' = advance track c st\n      in consumeMany track (n - 1) (i + 1) cs st'\n    consumeMany _ _ i [] st = (i, [], st)\n\n    advance track c st =\n      let stPrev = st { scanPrev2 = scanPrev1 st, scanPrev1 = Just c }\n      in if c == '\\n'\n           then stPrev\n             { scanAtLineStart = True\n             , scanLine = scanLine st + 1\n             , scanContinued = scanBackslash st\n             , scanBackslash = False\n             }\n           else stPrev\n             { scanAtLineStart = False\n             , scanContinued = False\n             , scanBackslash =\n                 if track && c /= ' ' && c /= '\\t' && c /= '\\r'\n                   then c == '\\\\'\n                   else scanBackslash st\n             }\n\nparseTopLevelChunk :: String -> String -> TopLevelChunk -> IO (Either Control.Exception.SomeException [S.Stmt])\nparseTopLevelChunk fileName fileContent chunk = do\n  parsed <- tryNonAsync $\n    Control.Exception.evaluate $\n      runParser (St.evalStateT (top_chunk_input fileName chunk) initState) fileName fileContent\n  case parsed of\n    Left err -> return (Left err)\n    Right (Left bundle) -> return (Left (Control.Exception.toException bundle))\n    Right (Right stmts) -> do\n      forced <- tryNonAsync (Control.Exception.evaluate (rnf stmts))\n      case forced of\n        Left err -> return (Left err)\n        Right () -> return (Right stmts)\n  where\n    tryNonAsync action = do\n      result <- Control.Exception.try action\n      case result of\n        Left err ->\n          case Control.Exception.fromException err :: Maybe Control.Exception.SomeAsyncException of\n            Just _  -> Control.Exception.throwIO err\n            Nothing -> return (Left err)\n        Right ok -> return (Right ok)\n\ndata ChunkProgressEvent = ChunkProgressDone Int | ChunkProgressStop\n\ndata ChunkProgress = ChunkProgress (Chan ChunkProgressEvent) (Async ())\n\nparseTopLevelChunks :: String -> String -> Int -> Maybe (Int -> Int -> IO ()) -> IO [[S.Stmt]]\nparseTopLevelChunks fileName fileContent bodyStart mReportProgress = do\n  ncap <- getNumCapabilities\n  let nworkers = max 1 ncap\n  withChunkProgress mReportProgress (length fileContent) bodyStart $ \\progress -> do\n    let window = max 1 (10 * nworkers)\n    slots <- newQSem window\n    workQ <- newChan\n    resultsRef <- newIORef []\n    workers <- replicateM nworkers (async (worker slots workQ progress))\n    let stopWorkers = replicateM_ nworkers (writeChan workQ Nothing) >> mapM_ wait workers\n        run = do\n          scanResult <- scanTopLevelChunks fileContent bodyStart $ \\chunk -> do\n            waitQSem slots\n            result <- newEmptyMVar\n            modifyIORef' resultsRef (result :)\n            writeChan workQ (Just (chunk, result))\n          case scanResult of\n            Left err -> Control.Exception.throwIO err\n            Right () -> do\n              stopWorkers\n              finishChunkProgress progress\n              results <- mapM readMVar . reverse =<< readIORef resultsRef\n              collectParsedChunks results\n    run `Control.Exception.finally` mapM_ cancel workers\n  where\n    worker slots workQ progress = do\n      job <- readChan workQ\n      case job of\n        Nothing -> return ()\n        Just (chunk, result) -> do\n          Control.Exception.finally\n            (runWorker chunk result progress)\n            (signalQSem slots)\n          worker slots workQ progress\n\n    runWorker chunk result progress = Control.Exception.mask $ \\restore -> do\n      parsed <- Control.Exception.try (restore (parseTopLevelChunk fileName fileContent chunk))\n      case parsed of\n        Left err -> do\n          putMVar result (Left err)\n          case Control.Exception.fromException err :: Maybe Control.Exception.SomeAsyncException of\n            Just _  -> Control.Exception.throwIO err\n            Nothing -> return ()\n        Right chunkResult -> do\n          putMVar result chunkResult\n          reportChunkDone progress chunk\n\ncollectParsedChunks :: [Either Control.Exception.SomeException [S.Stmt]] -> IO [[S.Stmt]]\ncollectParsedChunks results =\n  case [ err | Left err <- results ] of\n    err:_ -> Control.Exception.throwIO err\n    []    -> return [ stmts | Right stmts <- results ]\n\nwithChunkProgress :: Maybe (Int -> Int -> IO ()) -> Int -> Int -> (Maybe ChunkProgress -> IO a) -> IO a\nwithChunkProgress mReportProgress total done0 action = do\n  progress <- startChunkProgress mReportProgress total done0\n  action progress `Control.Exception.finally` cancelChunkProgress progress\n\nstartChunkProgress :: Maybe (Int -> Int -> IO ()) -> Int -> Int -> IO (Maybe ChunkProgress)\nstartChunkProgress Nothing _ _ = return Nothing\nstartChunkProgress (Just reportProgress) total done0 = do\n  progressQ <- newChan\n  progressA <- async $ do\n    lastPercent <- emit done0 0\n    loop done0 lastPercent progressQ\n  return (Just (ChunkProgress progressQ progressA))\n  where\n    loop done lastPercent progressQ = do\n      event <- readChan progressQ\n      case event of\n        ChunkProgressDone n -> do\n          let done' = min total (done + n)\n          lastPercent' <- emit done' lastPercent\n          loop done' lastPercent' progressQ\n        ChunkProgressStop -> return ()\n\n    emit done lastPercent = do\n      let completed\n            | total <= 1 = 0\n            | otherwise  = max 0 (min (total - 1) done)\n          percent\n            | total <= 0 = 100\n            | otherwise  = max 0 (min 99 ((completed * 100) `div` total))\n      if percent > lastPercent\n        then reportProgress completed total >> return percent\n        else return lastPercent\n\nfinishChunkProgress :: Maybe ChunkProgress -> IO ()\nfinishChunkProgress Nothing = return ()\nfinishChunkProgress (Just (ChunkProgress progressQ progressA)) =\n  writeChan progressQ ChunkProgressStop >> wait progressA\n\ncancelChunkProgress :: Maybe ChunkProgress -> IO ()\ncancelChunkProgress Nothing = return ()\ncancelChunkProgress (Just (ChunkProgress _ progressA)) = cancel progressA\n\nreportChunkDone :: Maybe ChunkProgress -> TopLevelChunk -> IO ()\nreportChunkDone Nothing _ = return ()\nreportChunkDone (Just (ChunkProgress progressQ _)) chunk =\n  writeChan progressQ (ChunkProgressDone (topLevelChunkLength chunk))\n\ntopLevelChunkLength :: TopLevelChunk -> Int\ntopLevelChunkLength chunk =\n  let SourceSpan start end = chunkSpan chunk\n  in end - start\n\ntop_chunk_input :: String -> TopLevelChunk -> Parser [S.Stmt]\ntop_chunk_input fileName chunk = do\n  state <- getParserState\n  let SourceSpan start end = chunkSpan chunk\n      input = chunkInput chunk\n      startPosState = (statePosState state)\n        { pstateSourcePos = SourcePos fileName (mkPos (chunkLine chunk)) (mkPos 1)\n        , pstateInput = input\n        , pstateOffset = start\n        , pstateLinePrefix = \"\"\n        }\n  let chunkState = state\n        { stateInput = input\n        , stateOffset = start\n        , statePosState = startPosState\n        }\n  setParserState chunkState\n  ss <- withCtx TOP (L.nonIndented sc2 top_chunk_stmt)\n  sc2\n  off <- getOffset\n  if off == end\n    then return ss\n    else fail (\"chunk parser stopped at offset \" ++ show off ++ \", expected \" ++ show end)\n\nregroupTopDecls :: S.Suite -> S.Suite\nregroupTopDecls = go []\n  where\n    go [] [] = []\n    go ds [] = flush ds\n    go ds (S.Decl _ ds' : rest) = go (ds ++ ds') rest\n    go ds (stmt : rest) = flush ds ++ stmt : go [] rest\n\n    flush [] = []\n    flush ds = [ S.Decl (loc group) group | group <- Names.splitDeclGroup ds ]\n\n-- Row parsers ----------------------------------------------------------------------\n\n-- non-empty positional row without trailing comma\nposItems:: (a -> b -> b) -> (c -> b) -> b -> Parser a -> Parser c -> Parser b\nposItems fCons fStar fNil item staritem =\n           fStar <$> (star *> staritem)\n        <|>\n           do e <- item\n              es <- many (try (comma *> item))\n              mbe <- optional (try (comma *> star *> staritem))\n              let tail = maybe fNil fStar mbe\n              return (foldr fCons tail (e:es))\n\n--non-empty kwd row with optional trailing comma\nkwdItems:: (a -> b -> b) -> (c -> b) -> b -> Parser a -> Parser c -> Parser b\nkwdItems fCons fStar fNil item staritem =\n          fStar <$> (starstar *> staritem <* optional comma)\n        <|>\n          do b <- item\n             bs <- many (try (comma *> item))\n             mbe <- optional (try (comma *> optional ((starstar *> staritem) <* optional comma )))\n             let tail = maybe fNil (maybe fNil fStar) mbe\n             return (foldr fCons tail (b:bs))\n\n-- parameter list consisting of posItems followed by kwdItems\n-- Unfortunately, the parser below does not make use of posItems\nfunItems :: (a1 -> t1 -> t1) -> (a -> t1) -> t1 -> Parser a1 -> Parser a -> Parser t -> t -> Parser (Either (t1,t) a1)\nfunItems posCons posStar posNil positem posstaritem kwdItems kwdNil =\n            do i <- singleStar *> posstaritem\n               mbc <- optional comma\n               case mbc of\n                  Just _ -> do k <- kwdItems\n                               return  (Left (posStar i, k))\n                           <|>\n                               return  (Left (posStar i, kwdNil))\n                  Nothing ->  return  (Left (posStar i, kwdNil))\n           <|>\n            try (do k <- kwdItems; return (Left (posNil, k)))\n           <|>\n             do i <- positem\n                mbc <- optional comma\n                case mbc of\n                   Just _ -> do r <- funItems posCons posStar posNil positem posstaritem kwdItems kwdNil\n                                case r of\n                                   Left (p,k) -> return (Left (posCons i p, k))\n                                   Right p -> return (Left (posCons i (posCons p posNil),kwdNil))\n                             <|> return (Left (posCons i posNil, kwdNil))\n                   Nothing -> return (Right i)\n            <|>\n               do optional comma; return (Left (posNil, kwdNil))\n\ntuple_or_single posItems headItems singleHead tup =\n      do pa <- posItems\n         mbc <- optional comma\n         return (f pa mbc)\n    where f pa mbc\n            | singleHead pa = maybe (headItems pa) (const (tup pa)) mbc\n            | otherwise  = tup pa\n\n\n-- Patterns ------------------------------------------------------------------------------------\n\npospat :: Parser S.PosPat\npospat = posItems S.PosPat S.PosPatStar S.PosPatNil apat apat\n\nkwdpat :: Parser S.KwdPat\nkwdpat = kwdItems (uncurry S.KwdPat) S.KwdPatStar S.KwdPatNil kpat apat\n     where kpat = do v <- name\n                     equals\n                     p <- apat\n                     return (v,p)\n\ngen_pattern = do r <- funItems  S.PosPat S.PosPatStar S.PosPatNil apat apat (fail \"No kwdpat\") S.KwdPatNil\n                 case r of\n                   Left (p,k) -> return $ S.PTuple NoLoc p k\n                   Right p -> return p\n\ngen_pattern1 = do r <- funItems  S.PosPat S.PosPatStar S.PosPatNil apat apat kwdpat S.KwdPatNil\n                  case r of\n                    Left (p,k) -> return $ S.PTuple NoLoc p k\n                    Right p -> return p\n\npelems ::Parser ([S.Pattern], Maybe S.Pattern)\npelems = do\n    p <- apat\n    ps <- many (try (comma *> apat))\n    mbp <- optional (comma *> star *> apat)\n    return (p:ps, mbp)\n\napat :: Parser S.Pattern\napat = addLoc (\n            (try $ rword \"_\" *> (S.PWild NoLoc <$> optannot))\n        <|>\n            (try $ S.PVar NoLoc <$> name <*> optannot)\n        <|>\n            ((try . parens) $ return $ S.PParen NoLoc (S.PTuple NoLoc S.PosPatNil S.KwdPatNil))\n        <|>\n            ((try . parens) $ S.PParen NoLoc <$> gen_pattern1)\n        <|>\n            (brackets $ (maybe (S.PList NoLoc [] Nothing) (\\(ps,mbp)-> S.PList NoLoc ps mbp)) <$> optional pelems)\n        )\n  where  -- datapat = S.PData NoLoc <$> escname <*> many (brackets exprlist)\n        optannot = try (Just <$> (colon *> ttype)) <|> return Nothing\n\n-- Targets -------------------------------------------------------------------------------------\n\ntarget :: Parser S.Target\ntarget = try $ do\n            tmp <- atom_expr\n            case tmp of\n                S.Var _ (S.NoQ n) -> return tmp\n                S.Dot _ e n       -> return tmp\n                S.Index _ e ix    -> return tmp\n                S.Slice _ e sl    -> return tmp\n                _                 -> locate (loc tmp) >> fail (\"illegal target: \" ++ show tmp)\n\n------------------------------------------------------------------------------------------------\n-- Statements ----------------------------------------------------------------------------------\n------------------------------------------------------------------------------------------------\n\nstmt, simple_stmt :: Parser [S.Stmt]\nstmt = ((:[]) <$> compound_stmt)  <|> try ((:[]) <$> (signature <* newline1)) <|> decl_group <|> simple_stmt <?> \"statement\"\n\ntop_chunk_stmt :: Parser [S.Stmt]\ntop_chunk_stmt =\n       ((:[]) <$> compound_stmt)\n  <|> try ((:[]) <$> (signature <* newline1))\n  <|> ((\\d -> [S.Decl (loc d) [d]]) <$> decl)\n  <|> simple_stmt\n  <?> \"statement\"\n\nsimple_stmt = (small_stmt `sepEndBy1` semicolon) <* newline1 <?> \"simple statement\"\n\n--- Small statements ---------------------------------------------------------------------------------\n\nsmall_stmt :: Parser S.Stmt\nsmall_stmt = del_stmt <|> pass_stmt <|> flow_stmt <|> assert_stmt <|> var_stmt <|> after_stmt  <|> expr_stmt\n\nexpr_stmt :: Parser S.Stmt\nexpr_stmt = addLoc $ do\n            o <- getOffset\n            S.Assign NoLoc <$> some (try assign) <*> rhs                                 -- Single variable lhs matches here\n             <|> (do t <- target\n                     ((S.AugAssign NoLoc t <$> augassign <*> rhs) <* assertNotData (Loc o o) \"augmented assignment\")\n                       <|> (S.MutAssign NoLoc t <$> (equals *> rhs)))                    -- and not here\n             <|> (((S.Expr NoLoc <$> rhs) <* assertNotData (Loc o o) \"call\") <?> \"expression statement\")\n   where augassign :: Parser S.Aug\n         augassign = augops\n          where augops = S.PlusA   <$ symbol \"+=\"\n                     <|> S.MinusA  <$ symbol \"-=\"\n                     <|> S.MultA   <$ symbol \"*=\"\n                     <|> S.MMultA  <$ symbol \"@=\"\n                     <|> S.DivA    <$ symbol \"/=\"\n                     <|> S.ModA    <$ symbol \"%=\"\n                     <|> S.BAndA   <$ symbol \"&=\"\n                     <|> S.BOrA    <$ symbol \"|=\"\n                     <|> S.BXorA   <$ symbol \"^=\"\n                     <|> S.ShiftLA <$ symbol \"<<=\"\n                     <|> S.ShiftRA <$ symbol \">>=\"\n                     <|> S.PowA    <$ symbol \"**=\"\n                     <|> S.EuDivA  <$ symbol \"//=\"\n\nassign :: Parser S.Pattern\nassign = gen_pattern <* equals\n\nrhs :: Parser S.Expr\nrhs = yield_expr <|> exprlist\n\ntrysome p = do x <- p; rest [x]\n  where rest xs = (try p >>= \\x -> rest (x:xs)) <|> return (reverse xs)\n\nafter_stmt :: Parser S.Stmt\nafter_stmt = addLoc $ do\n                l <- rwordLoc \"after\"\n                assertDefAct l \"after\"\n                e <- expr\n                colon\n                e' <- expr\n                return $ S.After NoLoc e e'\n\nvar_stmt :: Parser S.Stmt\nvar_stmt = addLoc $ do\n             l <- rwordLoc \"var\"\n             assertActBody l \"var\"\n             S.VarAssign NoLoc <$> trysome assign <*> rhs\n\ndel_stmt = addLoc $ do\n            l <- rwordLoc \"del\"\n            assertNotData l \"del\"\n            S.Delete NoLoc <$> target\n\npass_stmt =  S.Pass <$> rwordLoc \"pass\"\n\nflow_stmt = break_stmt <|>  continue_stmt <|>  return_stmt <|>  raise_stmt <|>  yield_stmt\n\nbreak_stmt =  do l <- rwordLoc \"break\"\n                 assertLoop l \"break\"\n                 return (S.Break l)\n\ncontinue_stmt =  do l <- rwordLoc \"continue\"\n                    assertLoop l \"continue\"\n                    return (S.Continue l)\n\nreturn_stmt = addLoc $ do    -- the notFollowedBy colon here is to avoid confusion with data_stmt return case\n                l <- rwordLoc \"return\" <* notFollowedBy colon\n                assertDef l \"return\"\n                S.Return NoLoc <$> optional exprlist\n\nyield_stmt = yield_expr >>= \\e -> return $ S.Expr (S.eloc e) e\n\nraise_stmt = addLoc $ do\n               rword \"raise\"\n               S.Raise NoLoc <$> expr\n\nimport_stmt = import_name <|> import_from <?> \"import statement\"\n   where import_name = addLoc $ do\n                rword \"import\"\n                S.Import NoLoc <$> module_item `sepBy1` comma\n\n         module_item = do\n                dn <- module_name\n                S.ModuleItem dn <$> optional (rword \"as\" *> name)\n\n         import_from = addLoc $ do\n                rword \"from\"\n                mr <- import_module\n                rword \"import\"\n                is <- import_items\n                case is of\n                   [] -> return $ S.FromImportAll NoLoc mr\n                   _  -> return $ S.FromImport NoLoc mr is\n\n         import_module = do\n                ds <- many dot\n                mbn <- optional module_name\n                return $ S.ModRef (length ds, mbn)\n         import_items = ([] <$ star)   -- Note: [] means all...\n                     <|> parens import_as_names\n                     <|> import_as_names\n         import_as_name = S.ImportItem <$> name <*> optional (rword \"as\" *> name)\n         import_as_names = (:) <$> import_as_name <*> commaList import_as_name\n\n-- global_stmt: 'global' NAME (',' NAME)*\n-- nonlocal_stmt: 'nonlocal' NAME (',' NAME)*\n-- assert_stmt: 'assert' expr [',' expr]\n\nassert_stmt = addLoc (rword \"assert\" >> S.Assert NoLoc <$> expr <*> optional (comma *> expr))\n\nsignature :: Parser S.Stmt\nsignature = addLoc (do dec <- decorator True; (ns,t) <- tsig; return $ S.Signature NoLoc ns t dec)\n   where tsig = do v <- name\n                   vs <- commaList name\n                   colon\n                   t <- tschema\n                   return (v:vs,t)\n\n-- Declaration groups ------------------------------------------------------------------\n\ndecl_group :: Parser [S.Stmt]\ndecl_group = do p <- L.indentLevel\n                g <- some (atPos p decl)\n                return [ S.Decl (loc ds) ds | ds <- Names.splitDeclGroup g ]\n\ndecl :: Parser S.Decl\ndecl = funcdef <|> classdef <|> protodef <|> extdef <|> actordef\n\ndecorator :: Bool -> Parser S.Deco\ndecorator sig = do\n       p <- L.indentLevel\n       d <- decoration\n       p1 <- L.indentLevel\n       if (p /= p1)\n         then fail \"Decorated statement must have same indentation as decoration\"\n         else return d\n   where property = do l <- rwordLoc \"@property\"\n                       assertClass l \"@property\"\n                       newline1\n                       return S.Property\n         static   = do l <-rwordLoc \"@staticmethod\" <|> rwordLoc \"@static\"\n                       assertDecl l \"@static\"\n                       newline1\n                       return S.Static\n         decoration = (if sig then property <|> static else static) <|> return S.NoDec\n\n\nfuncdef :: Parser S.Decl\nfuncdef =  addLoc $ do\n              (p,(deco,fx,l)) <- withPos (((,,) <$> decorator False <*> optional effect <*> rwordLoc \"def\"))\n              assertNotData l \"def\"\n              n <- name\n              q <- optbinds\n              (ppar,kpar) <- params\n              t <- optional (arrow *> ttype)\n              (ss, docstring) <- suiteWithDocstring DEF p\n              return $ S.Def NoLoc n q ppar kpar t ss deco (maybe S.tWild id fx) docstring\n\nparams :: Parser (S.PosPar, S.KwdPar)\nparams = try ((\\k ->(S.PosNIL,k)) <$> parens (kwdpar True))\n         <|> parens (funpars True)\n\nbinds :: Parser S.QBinds\nbinds = brackets (do b <- qbind; bs <- many (comma *> qbind); return (b:bs))\n\noptbinds :: Parser S.QBinds\noptbinds = binds <|> return []\n\nactordef = addLoc $ do\n                (s,l) <- withPos (rwordLoc \"actor\")\n                assertTop l \"actor\"\n                nm <- name <?> \"actor name\"\n                q <- optbinds\n                (ppar,kpar) <- params\n                (ss, docstring) <- suiteWithDocstring ACTOR s\n                return $ S.Actor NoLoc nm q ppar kpar ss docstring\n\n-- classdef: 'class' NAME ['(' [arglist] ')'] ':' suite\n-- protodef: 'class' NAME ['(' [arglist] ')'] ':' suite\n-- extdef: 'class' NAME ['(' [arglist] ')'] ':' suite\n\nclassdef    = classdefGen \"class\" name CLASS S.Class\nprotodef    = classdefGen \"protocol\" name PROTO S.Protocol\n--extdef      = classdefGen \"extension\" qual_name EXT S.Extension\n\nclassdefGen k pname ctx con = addLoc $ do\n                (s,l) <- withPos (rwordLoc k)\n                assertTop l k\n                nm <- pname\n                q <- optbinds\n                cs <- optbounds\n                (ss, docstring) <- suiteWithDocstring ctx s\n                return $ con NoLoc nm q cs ss docstring\n\nextdef = addLoc $ do\n                (s,l) <- withPos (rwordLoc \"extension\")\n                assertTop l \"extension\"\n                (q,c) <- try head1 <|> try head2 <|> head3\n                cs <- optbounds\n                (ss, docstring) <- suiteWithDocstring EXT s\n                return $ S.Extension NoLoc q c cs ss docstring\n  where head1 = do q <- binds\n                   fatarrow\n                   c <- tcon\n                   return (q, c)\n        head2 = do c <- tcon\n                   return ([], c)\n        head3 = do n <- qual_name\n                   q <- binds\n                   return (q, S.TC n [ S.tVar v | S.QBind v _ <- q ])\n\n-- Compound statements -------------------------------------------------------------------------\n\ncompound_stmt :: Parser S.Stmt\ncompound_stmt =  if_stmt <|> while_stmt <|> for_stmt <|> try_stmt <|> with_stmt -- <|> data_stmt\n\n\nelse_part p = atPos p (rword \"else\" *> suite SEQ p)\n\nif_stmt = addLoc $ do\n             (p,_) <- withPos (rword \"if\")\n             b <- branch p\n             bs <- many (atPos p (rword \"elif\" *> branch p))\n             S.If NoLoc (b:bs) . maybe [] id <$>  optional (else_part p)\n\nbranch p = S.Branch <$> expr <*> suite IF p\n\nwhile_stmt = addLoc $ do\n                 (p,l) <- withPos (rwordLoc \"while\")\n                 assertNotDecl l \"while\"\n                 e <- expr\n                 ss1 <- suite LOOP p\n                 S.While NoLoc e ss1 . maybe [] id <$>  optional (else_part p)\n\nfor_stmt = addLoc $ do\n                 (p,l) <- withPos (rwordLoc \"for\")\n                 assertNotDecl l \"for\"\n                 pat <- gen_pattern\n                 rword \"in\"\n                 e <- exprlist\n                 ss <- suite LOOP p\n                 S.For NoLoc pat e ss . maybe [] id <$> optional (else_part p)\n\nexcept :: Parser S.Except\nexcept = addLoc $ do\n             rword \"except\"\n             mbx <- optional ((,) <$> qual_name <*> optional (rword \"as\" *> name))\n             return (maybe (S.ExceptAll NoLoc) (\\(x,mbn) -> maybe (S.Except NoLoc x) (S.ExceptAs NoLoc x) mbn) mbx)\n\ntry_stmt = addLoc $ do\n                (p,l) <- withPos (rwordLoc \"try\")\n                assertNotData l \"try\"\n                assertNotDecl l \"try\"\n                ss <- suite SEQ p\n                do\n                    hs <- some (handler p)\n                    mbe <- optional (else_part p)\n                    S.Try NoLoc ss hs (maybe [] id mbe) . maybe [] id <$>  optional (finally_part p)\n                   <|>\n                    S.Try NoLoc ss [] [] <$> finally_part p\n  where handler :: Pos -> Parser S.Handler\n        handler p = atPos p $ do\n                        exc <- except\n                        S.Handler exc <$> suite SEQ p\n        finally_part p = atPos p $ do\n                        rword \"finally\"\n                        suite SEQ p\n\nwith_stmt = addLoc $ do\n                (s,l) <- withPos (rwordLoc \"with\")\n                assertNotData l \"with\"\n                assertNotDecl l \"with\"\n                S.With NoLoc <$> (with_item `sepBy1` comma) <*> suite SEQ s\n  where with_item = S.WithItem <$> expr <*> optional (rword \"as\" *> gen_pattern)\n\n\ndata_stmt = addLoc $\n           do (s,pat) <- withPos gen_pattern\n              S.Data NoLoc (Just pat) <$> suite DATA s\n        <|>\n           do (s,l) <- withPos (rwordLoc \"return\")\n              assertDef l \"data\"\n              S.Data NoLoc Nothing <$> suite DATA s\n\nsuiteWithDocstring :: CTX -> Pos -> Parser (S.Suite, Maybe String)\nsuiteWithDocstring c p = do\n    withCtx c colon\n    withCtx c (indentSuiteWithDocstring p <|> (simple_stmt_with_docstring <* reportParseProgress))\n\nsuite :: CTX -> Pos -> Parser S.Suite\nsuite c p = do\n    o <- getOffset\n    withCtx c colon\n    stmts <- withCtx c (indentSuite p <|> (simple_stmt <* reportParseProgress))\n    return stmts\n  where indentSuite p = do\n          newline1\n          p1 <- L.indentGuard sc1 GT p\n          concat <$> some (stmtAtIndent p1)\n\nindentSuiteWithDocstring :: Pos -> Parser (S.Suite, Maybe String)\nindentSuiteWithDocstring p = do\n    newline1\n    p1 <- L.indentGuard sc1 GT p\n    (firstStmts, mbDoc) <- stmtAtIndentWithDocstring p1\n    rest <- concat <$> many (stmtAtIndent p1)\n    return (firstStmts ++ rest, mbDoc)\n\nstmtAtIndentWithDocstring :: Pos -> Parser (S.Suite, Maybe String)\nstmtAtIndentWithDocstring p1 = do\n    p2 <- L.indentLevel\n    case compare p1 p2 of\n        LT -> do o <- getOffset\n                 Control.Exception.throw $ IndentationError (Loc o o)\n        EQ -> stmtWithDocstring <* reportParseProgress\n        GT -> L.incorrectIndent GT p2 p1\n\nstmtAtIndent :: Pos -> Parser S.Suite\nstmtAtIndent p1 = do\n    p2 <- L.indentLevel\n    case compare p1 p2 of\n        LT -> do o <- getOffset\n                 Control.Exception.throw $ IndentationError (Loc o o)\n        EQ -> stmt <* reportParseProgress\n        GT -> L.incorrectIndent GT p2 p1\n\nstmtWithDocstring :: Parser (S.Suite, Maybe String)\nstmtWithDocstring = (\n    ((\\s -> ([s], Nothing)) <$> compound_stmt)\n    <|> try ((\\s -> ([s], Nothing)) <$> (signature <* newline1))\n    <|> ((\\s -> (s, Nothing)) <$> decl_group)\n    <|> simple_stmt_with_docstring\n  ) <?> \"statement\"\n\nsimple_stmt_with_docstring :: Parser (S.Suite, Maybe String)\nsimple_stmt_with_docstring = (\n    do\n      (mbDoc, firstStmts) <- try docstringSmallStmt <|> ((\\s -> (Nothing, [s])) <$> small_stmt)\n      rest <- many (try (semicolon *> small_stmt))\n      _ <- optional semicolon\n      newline1\n      return (firstStmts ++ rest, mbDoc)\n  ) <?> \"simple statement\"\n\ndocstringSmallStmt :: Parser (Maybe String, S.Suite)\ndocstringSmallStmt = do\n    S.Strings _ ss <- addLoc docstringLiteral\n    _ <- lookAhead (void (char ';') <|> void eol <|> eof)\n    return (Just (unescapeString (concat ss)), [])\n\n\nunescapeString :: String -> String\nunescapeString [] = []\nunescapeString ('\\\\':'n':xs) = '\\n' : unescapeString xs\nunescapeString ('\\\\':'t':xs) = '\\t' : unescapeString xs\nunescapeString ('\\\\':'r':xs) = '\\r' : unescapeString xs\nunescapeString ('\\\\':'\\\\':xs) = '\\\\' : unescapeString xs\nunescapeString ('\\\\':'\"':xs) = '\"' : unescapeString xs\nunescapeString ('\\\\':'\\'':xs) = '\\'' : unescapeString xs\nunescapeString (x:xs) = x : unescapeString xs\n\n------------------------------------------------------------------------------------------------\n--- Expressions ----------------------------------------------------------------\n------------------------------------------------------------------------------------------------\n\n-- The most general form of expression\nexpr :: Parser S.Expr\nexpr =  lambdef\n       <|>\n        do\n          e1 <- or_expr\n          mbp <- optional if_part\n          case mbp of\n            Nothing -> return e1\n            Just (c,e2) -> return $ S.Cond (S.eloc e1) e1 c e2\n   where if_part = (,) <$> (rword \"if\" *> or_expr) <*> (rword \"else\" *> expr) <?> \"if clause\"\n\n-- Non-empty list of comma-separated expressions.\n-- If more than one expr, build a tuple.\n-- if only one, leave as it is unless there is a trailing comma when we build a one-element tuple.\nexprlist :: Parser S.Expr\nexprlist = addLoc $ tuple_or_single posarg S.posArgHead S.singlePosArg (\\p -> S.Tuple NoLoc p S.KwdNil)\n\n\nexpr_nocond = or_expr <|> lambdef_nocond\n\nlambdefGen t = addLoc $ do\n            fx <- optional effect\n            rword \"lambda\"\n            (ppar,kpar) <- funpars False\n            colon\n            S.Lambda NoLoc ppar kpar <$> t <*> return (maybe S.tWild id fx)\n\nlambdef = try $ lambdefGen expr\nlambdef_nocond = try $ lambdefGen expr_nocond\n\n-- Logical expressions ------------------------------------------------------------------\n\n-- The intermediate levels between or_expr and comparison, i.e. expressions involving and, or and not,\n-- are handled by makeExprParser from Text.Megaparsec.Expr 6.4.0,  here Text_Megaparsec_Expr\n\n-- Three auxiliary functions used in building tables for makeExprParser\nbinary name op = InfixL $ do\n                name\n                return $ \\e1 e2 ->  S.BinOp (S.eloc e1 `upto` S.eloc e2) e1 op e2\n\nunop name op = do\n                (lop, _) <- withLoc name\n                return $ \\e ->\n                  case (op, e) of\n                    (S.UMinus, i@S.Int{}) ->\n                      let el = lop `upto` S.eloc i\n                      in i{ S.eloc = el\n                          , S.ival = negate (S.ival i)\n                          , S.lexeme = '-' : S.lexeme i }\n                    -- TODO: should loc cover operator + operand here??\n                    _ -> S.UnOp (S.eloc e) op e\n\nprefix name op = Prefix (unop name op)\n\nor_expr = makeExprParser comparison btable\n\nbtable :: [[Operator Parser S.Expr]]\nbtable = [ [ prefix (rwordLoc \"not\") S.Not]\n         , [ binary (rwordLoc \"and\") S.And]\n         , [ binary (rwordLoc \"or\") S.Or] ]\n\ncomparison = addLoc (do\n  e <- arithexpr\n  ps <- many (do\n                 op <- comp_op\n                 S.OpArg op <$> arithexpr)\n  case ps of\n        [] -> return e\n        _  -> return $ S.CompOp NoLoc e ps) <?> \"relational expression\"\n   where comp_op = S.Lt <$ opPref \"<\"\n                <|> S.Gt <$ opPref \">\"\n                <|> S.Eq <$ symbol \"==\"\n                <|> S.GE <$ symbol \">=\"\n                <|> S.LE <$ symbol \"<=\"\n                <|> S.LtGt <$ symbol \"<>\"\n                <|> S.NEq <$ symbol \"!=\"\n                <|> S.In <$ symbol \"in\"\n                <|> S.NotIn <$ (symbol \"not\" *> symbol \"in\")\n                <|> S.IsNot <$ try (symbol \"is\" *> symbol \"not\")\n                <|> S.Is <$ (symbol \"is\")\n                <?> \"operator\"\n\nstar_expr :: Parser S.Elem\nstar_expr = S.Star <$> (star *> arithexpr)\n\n-- Arithmetic expressions ----------------------------------------------------------\n-- Again, everything between arithexpr and factor is handled by makeExprParser\n\narithexpr :: Parser S.Expr\narithexpr = makeExprParser factor table\n\ntable :: [[Operator Parser S.Expr]]\ntable = [ [ binary (opPref \"*\") S.Mult, binary (opPref \"/\") S.Div, binary (opPref \"@\") S.MMult,\n            binary (opPref \"//\") S.EuDiv, binary (opPref \"%\") S.Mod]\n        , [ binary (opPref \"+\") S.Plus, binary (opPref \"-\") S.Minus]\n        , [ binary (opPref \"<<\") S.ShiftL, binary (opPref \">>\") S.ShiftR]\n        , [ binary (opPref \"&\") S.BAnd]\n        , [ binary (opPref \"^\") S.BXor]\n        , [ binary (opPref \"|\") S.BOr]\n        ]\n\nfactor :: Parser S.Expr\nfactor = (((unop (opPref \"+\") S.UPlus <|> unop (opPref \"-\") S.UMinus <|> unop (opPref \"~\") S.BNot) <?> \"unary operator\") <*> factor)\n        <|> power\n\npower = addLoc $ do\n           ae <- atom_expr\n           mbe <- optional expo\n           return (maybe ae (S.BinOp NoLoc ae S.Pow) mbe)\n  where expo = do opPref \"**\"\n                  factor\n                <?> \"operator\"\n\nisinstance = addLoc $ do\n                rword \"isinstance\"\n                (e,c) <- parens ((,) <$> expr <* comma <*> qual_name)\n                return $ S.IsInstance NoLoc e c\n\n-- recurring pattern below\ncommaList p = many (try (comma *> p)) <* optional comma\n\ndata ChainKind = COpt | CCall | COther deriving Eq\n\natom_expr = do\n              await <- optional $ withLoc $ rword \"await\" *> return (S.Await NoLoc)\n              async <- optional $ withLoc $ rword \"async\" *> return (S.Async NoLoc)\n              a <- atom\n              ts <- many trailer\n              let (outerOpt,e) = foldapp async a ts\n                  e' = maybe e (app e) await\n              return $ if outerOpt then wrapOptChain e' else e'\n              <?> \"atomic expression\"\n  where app a (l,f) = (f a){S.eloc = exprLoc a `upto` l}\n        appChain a (l,_,f) = app a (l,f)\n        exprLoc S.OptChain{S.exp1=e} = exprLoc e\n        exprLoc e = S.eloc e\n        wrapOptChain e = S.OptChain (loc e) e\n\n        foldapp async e = finish . go async False False e\n          where closeChain True e = wrapOptChain e\n                closeChain False e = e\n\n                go async preAsyncOpt outerOpt e [] = (async,preAsyncOpt,outerOpt,e)\n                go (Just a) preAsyncOpt outerOpt e (t@(_,kind,_):ts)\n                  | kind == CCall =\n                      let e' = appChain (app (closeChain preAsyncOpt e) a) t\n                      in go Nothing False outerOpt e' ts\n                go async preAsyncOpt outerOpt e (t@(_,kind,_):ts)\n                  | kind == COpt =\n                      case async of\n                        Just _ ->\n                          let e' = appChain (closeChain preAsyncOpt e) t\n                          in go async True outerOpt e' ts\n                        Nothing ->\n                          let e' = appChain (closeChain outerOpt e) t\n                          in go async preAsyncOpt True e' ts\n                go async preAsyncOpt outerOpt e (t:ts) =\n                      go async preAsyncOpt outerOpt (appChain e t) ts\n\n                finish (Just a,preAsyncOpt,outerOpt,e) =\n                  (outerOpt, app (closeChain preAsyncOpt e) a)\n                finish (Nothing,_,outerOpt,e) = (outerOpt,e)\n        \n        atom :: Parser S.Expr\n        atom =  addLoc (try strings\n               <|>\n                 ((try . parens) $ return $ S.Paren NoLoc (S.Tuple NoLoc S.PosNil S.KwdNil))\n               <|>\n                 ((try . parens) $ S.Paren NoLoc <$> yield_expr)\n               <|>\n                 (parens $ S.Paren NoLoc <$> expr_or_tuplemaker)\n               <|>\n                 (brackets $ do\n                             mbe <- optional listmaker\n                             return $ maybe (S.List NoLoc []) id mbe)\n               <|>\n                 (braces $ do\n                             mbe <- optional dictorsetmaker\n                             return $ maybe (S.Dict NoLoc []) id mbe)\n               <|> var\n               <|> isinstance\n               <|> (try ((\\f -> S.Imaginary NoLoc f (show f ++ \"j\")) <$> lexeme (L.float <* string \"j\")))\n               <|> (try ((\\f -> S.Float NoLoc f (show f)) <$> lexeme L.float))\n               <|> (\\i -> S.Int NoLoc i (\"0o\"++showOct i \"\")) <$> (string \"0o\" *> lexeme L.octal)\n               <|> (\\i -> S.Int NoLoc i (\"0x\"++showHex i \"\")) <$> (string \"0x\" *> lexeme L.hexadecimal)\n               <|> (\\i -> S.Int NoLoc i (show i)) <$> (lexeme L.decimal)\n               <|> (S.Ellipsis <$> rwordLoc \"...\")\n               <|> (S.None <$>  rwordLoc \"None\")\n               <|> (S.NotImplemented  <$>  rwordLoc \"NotImplemented\")\n               <|> (\\l -> S.Bool l True) <$> rwordLoc \"True\"\n               <|> (\\l -> S.Bool l False) <$> rwordLoc \"False\")\n\n        expr_or_tuplemaker              = do r <- funItems S.PosArg S.PosStar S.PosNil expr expr kwdarg S.KwdNil\n                                             case r of\n                                                Left (p,k) -> return (S.Tuple NoLoc p k)\n                                                Right e -> return e\n\n\n        -- common pattern in functions building lists, sets and dictionaries\n        maker constr constrComp p = do\n                   (l,a) <- withLoc p\n                   (constrComp l a <$> comp_for) <|> ((\\as -> (constr l (a:as))) <$> commaList p)\n\n        -- exprlist_comp version used in  brackets, building a list\n        listmaker = maker S.List S.ListComp elem\n           where elem = (S.Elem <$> expr) <|> star_expr\n\n        dictorsetmaker :: Parser S.Expr\n        dictorsetmaker = (try $ maker S.Dict S.DictComp assoc)\n                            <|> maker S.Set S.SetComp elem\n             where elem = (S.Elem <$> expr) <|> star_expr\n                   assoc = (S.Assoc <$> expr) <*> (colon *> expr)\n                        <|>\n                           (S.StarStar <$> (starstar *> arithexpr))\n\n        var = do nm <- name\n                 return (S.Var (S.nloc nm) (S.NoQ nm))\n\n        trailer :: Parser (SrcLoc,ChainKind,S.Expr -> S.Expr)\n        trailer = do\n                     (l,(kind,f)) <- withLoc (\n                         (do\n                            (l,_) <- withLoc(symbol \"?\")\n                            return (COpt,\\a -> S.Opt (loc a `upto` l) a True))\n                        <|>\n                          (do\n                            (l,_) <- withLoc(opPref \"!\")\n                            return (COpt,\\a -> S.Opt (loc a `upto` l) a False))\n                        <|>\n                         (do\n                           f <- brackets sliceOrIndex\n                           return (COther,f))\n                       <|>\n                         (do\n                            (ps,ks) <- parens funargs \n                            return (CCall,\\a -> S.Call (loc a `upto` loc ks) a ps ks))\n                        <|>\n                         (do\n                            dot\n                            f <- try intdot <|> iddot <|> strdot\n                            return (COther,f))\n                        <?> \"call arguments, slice/index expression\")\n                     return (l,kind,f)\n\n           where iddot  = do\n                        mb <- optional (opPref \"~\")\n                        nm <- name\n                        return (\\a -> maybe (S.Dot (loc a `upto` loc nm) a nm) (const $ S.Rest (loc a `upto` loc nm) a nm) mb)\n                 intdot  = do\n                        mb <- optional (opPref \"~\")\n                        (l,i) <- withLoc $ lexeme L.decimal\n                        return (\\a -> maybe (S.DotI (loc a `upto` l) a i) (const $ S.RestI (loc a `upto` l) a i) mb)\n                 strdot = do\n                        (l,ss) <- withLoc plainstrLiteral\n                        return (\\a -> S.Dot (loc a `upto` l) a (S.Name l (head ss)))\n\n                 -- Parse slice or index: try slice first since it can start with expr\n                 sliceOrIndex = try sliceParser <|> indexParser\n\n                 -- Parse slice notation: [start]:[stop][:[step]]\n                 sliceParser  = do\n                     start <- optional expr\n                     colon\n                     stop <- optional expr\n                     step <- optional (colon *> optional expr)\n                     return (\\a -> S.Slice NoLoc a (S.Sliz NoLoc start stop (join step)))\n\n                 -- Parse index: single expr or comma-separated exprs (tuple)\n                 indexParser  = do\n                     es <- expr `sepBy1` comma\n                     return (\\a -> S.Index NoLoc a (if length es == 1 then head es else S.eTuple es))\n\n\ncomp_iter, comp_for, comp_if :: Parser S.Comp\ncomp_iter = comp_for <|> comp_if\n\ncomp_for = addLoc (do\n            rword \"for\"\n            pat <- gen_pattern\n            rword \"in\"\n            e <- or_expr\n            S.CompFor NoLoc pat e . maybe S.NoComp id <$> optional comp_iter)\n\ncomp_if = addLoc $ do\n            rword \"if\"\n            e <- expr_nocond\n            S.CompIf NoLoc e . maybe S.NoComp id <$> optional comp_iter\n\nyield_expr = addLoc $ do\n             l <- rwordLoc \"yield\"\n             assertDef l \"yield\"\n             (S.YieldFrom NoLoc <$> (rword \"from\" *> expr)\n              <|> S.Yield NoLoc <$> optional exprlist)\n\n\n--- Params ---------------------------------------------------------------------\n\nparm :: Bool -> Parser (S.Name, Maybe S.Type, Maybe S.Expr)\nparm ann = do n <- name\n              mbt <- if ann then optional (colon *> ttype) else return Nothing\n              mbe <- optional (equals *> expr)\n              return (n, mbt, mbe)\n\npstar :: Bool -> Parser S.Type -> Parser (S.Name, Maybe S.Type)\npstar ann startype = do n <- name\n                        mbt <- if ann then optional (colon *> startype) else return Nothing\n                        return (n, mbt)\n\npstartype :: Parser S.Type\npstartype = parens (S.TTuple NoLoc <$> (posrow <|> return S.posNil) <*> return S.kwdNil <* optional comma)\n\nkstartype :: Parser S.Type\nkstartype = parens (S.TTuple NoLoc S.posNil <$> (kwdrow <|> return S.kwdNil) <* optional comma)\n\npospar :: Bool -> Parser S.PosPar\npospar ann = posItems (\\(n,t,e) par -> S.PosPar n t e par) (uncurry S.PosSTAR) S.PosNIL (parm ann) (pstar ann pstartype)\n\nkwdpar :: Bool -> Parser S.KwdPar\nkwdpar ann = kwdItems (\\(n,t,e) par -> S.KwdPar n t e par) (uncurry S.KwdSTAR) S.KwdNIL (parm ann) (pstar ann kstartype)\n\nfunpars :: Bool -> Parser (S.PosPar, S.KwdPar)\nfunpars ann =   (\\(n,mbt) -> (S.PosNIL,S.KwdSTAR n mbt)) <$> (starstar *> pstar ann kstartype <* optional comma)\n            <|> do ps <- pospar ann\n                   mbmbks <- optional (comma *> optional (kwdpar ann))\n                   return (maybe (ps,S.KwdNIL) (maybe (ps,S.KwdNIL) (\\ks -> (ps,ks))) mbmbks)\n            <|> return (S.PosNIL,S.KwdNIL)\n\n--- Args -----------------------------------------------------------------------\n\n-- Position/Keyword lists of expr's.\n-- posarg is used in exprlist to build the general form of comma-separated expressions\n\nkwdbind :: Parser (S.Name, S.Expr)\nkwdbind = do v <- escname\n             equals\n             e <- expr\n             return (v,e)\n\nposarg :: Parser S.PosArg\nposarg = posItems S.PosArg S.PosStar S.PosNil expr expr\n\nkwdarg :: Parser S.KwdArg\nkwdarg = kwdItems (uncurry S.KwdArg) S.KwdStar S.KwdNil kwdbind expr\n\nfunargs :: Parser (S.PosArg, S.KwdArg)\nfunargs = do r <- funItems S.PosArg S.PosStar S.PosNil expr expr kwdarg S.KwdNil\n             case r of\n               Left p -> return p\n               Right t -> return (S.PosArg t S.PosNil, S.KwdNil)\n\n--- Types ----------------------------------------------------------------------\n\neffect  :: Parser S.Type\neffect  = addLoc $\n            rword \"_\" *> return (S.TWild NoLoc)\n        <|> rword \"proc\" *> return S.fxProc\n        <|> rword \"mut\" *> return S.fxMut\n        <|> rword \"pure\" *> return S.fxPure\n        <|> rword \"action\" *> return S.fxAction\n\nposrow :: Parser S.PosRow\nposrow = posItems S.posRow S.posStar' S.posNil ttype (optional tvar)\n\nkwdrow :: Parser S.KwdRow\nkwdrow = kwdItems (uncurry S.kwdRow) S.kwdStar' S.kwdNil tsig1 (optional tvar)\n   where tsig1 = do v <- name\n                    colon\n                    t <- ttype\n                    return (v,t)\n\nfunrows :: Parser (S.PosRow, S.KwdRow)\nfunrows = do r <- funItems S.posRow S.posStar' S.posNil ttype (optional tvar) kwdrow S.kwdNil\n             case r of\n               Left p -> return p\n               Right t -> return (S.posRow t S.posNil, S.kwdNil)\n\ntcon :: Parser S.TCon\ntcon =  do n <- qual_name\n           args <- optional (brackets (do t <- ttype\n                                          ts <- commaList ttype\n                                          return (t:ts)))\n           return $ S.TC n (maybe [] id args)\n\ntvar :: Parser S.TVar\ntvar = S.TV S.KWild <$> try tvarname\n\nqbind :: Parser S.QBind\nqbind = S.QBind <$> tvar <*> optbounds\n\noptbounds :: Parser [S.TCon]\noptbounds = do bounds <- optional (parens (optional ((:) <$> tcon <*> commaList tcon)))\n               return $ maybe [] (maybe [] id) bounds\n\ntschema :: Parser S.TSchema\ntschema = addLoc $\n            do\n                bs <- brackets (do n <- qbind\n                                   ns <- commaList qbind\n                                   return (n:ns))\n                fatarrow\n                t <- ttype\n                return (S.tSchema bs t)\n            <|>\n            (S.monotype <$> ttype)\n\nttype :: Parser S.Type\nttype    =  addLoc (\n            rword \"None\" *> return (S.TNone NoLoc)\n        <|> (S.TVar NoLoc . S.TV S.KType) <$> (S.Name <$> rwordLoc \"Self\" <*> return \"Self\")\n        <|> S.TOpt NoLoc <$> (qmark *> ttype)\n        <|> try (do mbfx <- optional effect\n                    (p,k) <- parens funrows\n                    arrow\n                    t <- ttype\n                    return (S.TFun NoLoc (maybe S.fxPure id mbfx) p k t))\n        <|> try (do r <- parens (funItems S.posRow S.posStar' S.posNil ttype (optional tvar) kwdrow S.kwdNil)\n                    case r of\n                      Left (p,k) -> return (S.TTuple NoLoc p k)\n                      Right t -> return t)\n        <|> parens (return (S.TTuple NoLoc S.posNil S.kwdNil))\n        <|> try (S.TVar NoLoc <$> tvar)\n        <|> rword \"_\" *> return (S.TWild NoLoc)\n        <|> S.TCon NoLoc <$> tcon)\n        <?> \"type\"\n"
  },
  {
    "path": "compiler/lib/src/Acton/Prim.hs",
    "content": "-- Copyright (C) 2019-2021 Data Ductus AB\n--\n-- Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:\n--\n-- 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.\n--\n-- 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.\n--\n-- 3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission.\n--\n-- THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS \"AS IS\" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n--\n\nmodule Acton.Prim where\n\nimport Utils\nimport Pretty\nimport Acton.Syntax\nimport Acton.Builtin\nimport Acton.Names\nimport Acton.NameInfo\n\nnPrim               = name \"$\"\nmPrim               = ModName [nPrim]\ngPrim s             = GName mPrim (name s)\n\nprimKW s            = name (\"$\" ++ s)\n\nprimProc            = gPrim \"proc\"\nprimAction          = gPrim \"action\"\nprimMut             = gPrim \"mut\"\nprimPure            = gPrim \"pure\"\n\ncProc r t           = TC primProc [r,t]\ncAction r t         = TC primAction [r,t]\ncMut r t            = TC primMut [r,t]\ncPure r t           = TC primPure [r,t]\n\nattr_call_          = name \"__call__\"\nattr_exec_          = name \"__exec__\"\nattr_asyn_          = name \"__asyn__\"\nattr_eval_          = name \"__eval__\"\n\nprimActor           = gPrim \"Actor\"\nprimR               = gPrim \"R\"\nprimCont            = gPrim \"Cont\"\n\nprimASYNCf          = gPrim \"ASYNCf\"\nprimAFTERf          = gPrim \"AFTERf\"\nprimAWAITf          = gPrim \"AWAITf\"\n\nprimASYNCc          = gPrim \"ASYNCc\"\nprimAFTERc          = gPrim \"AFTERc\"\nprimAWAITc          = gPrim \"AWAITc\"\n\nprimASYNC           = gPrim \"ASYNC\"\nprimAFTER           = gPrim \"AFTER\"\nprimAWAIT           = gPrim \"AWAIT\"\n\nprimPUSH_Cc         = gPrim \"PUSH_Cc\"\nprimPUSHF_Cc        = gPrim \"PUSHF_Cc\"\nprimPUSH_C          = gPrim \"PUSH_C\"\nprimPUSHF_C         = gPrim \"PUSHF_C\"\nprimPOP_C           = gPrim \"POP_C\"\nprimDROP_C          = gPrim \"DROP_C\"\n\nprimPUSH            = gPrim \"PUSH\"\nprimPUSHF           = gPrim \"PUSHF\"\nprimPOP             = gPrim \"POP\"\nprimDROP            = gPrim \"DROP\"\nprimRAISE           = gPrim \"RAISE\"\n\nprimSEQ             = gPrim \"SEQ\"\nprimBRK             = gPrim \"BRK\"\nprimCNT             = gPrim \"CNT\"\nprimRET             = gPrim \"RET\"\n\ntSEQ                = tCon $ TC primSEQ []\ntBRK                = tCon $ TC primBRK []\ntCNT                = tCon $ TC primCNT []\ntRET                = tCon $ TC primRET []\n\nprimASSERT          = gPrim \"ASSERT\"\nprimNEWACTOR        = gPrim \"NEWACTOR\"\nprimInstallFinalizer = gPrim \"InstallFinalizer\"\n\nattr_finalizer      = name \"GCfinalizer\"\n\nprimISINSTANCE      = gPrim \"ISINSTANCE\"\nprimISINSTANCE0     = gPrim \"ISINSTANCE0\"\nprimCONSTCONT       = gPrim \"CONSTCONT\"\nprimCAST            = gPrim \"CAST\"\n\neCAST t t' e        = eCall (tApp (eQVar primCAST) [t,t']) [e]\n\nprimFORMAT          = gPrim \"FORMAT\"\n\nprimRContc          = gPrim \"R_CONTc\"\nprimRCont           = gPrim \"R_CONT\"\n\nprimRFail           = gPrim \"R_FAIL\"\n\nprimEqOpt           = gPrim \"EqOpt\"\n\nprimIdentityActor   = gPrim \"IdentityActor\"\n\nprimWEqNone         = gPrim \"wEqNone\"\n\nwitIntegralInt      = GName mPrim $ Derived (deriveQ qnIntegral) $ Derived (deriveQ qnInt) suffixWitness\nwitIntegralBigint  = GName mPrim $ Derived (deriveQ qnIntegral) $ Derived (deriveQ qnBigint) suffixWitness\n\nprimISNOTNONE       = gPrim \"ISNOTNONE\"\nprimISNOTNONE0      = gPrim \"ISNOTNONE0\"\nprimISNONE          = gPrim \"ISNONE\"\nprimISNONE0         = gPrim \"ISNONE0\"\n\nprimSKIPRESc        = gPrim \"SKIPRESc\"\nprimSKIPRES         = gPrim \"SKIPRES\"\n\nprimBox             = gPrim \"Box\"\ntBox t              = tCon $ TC primBox [t]\n\nvalKW               = name \"val\"\n\ncActor              = TC primActor []\ntActor              = tCon cActor\ntR                  = tCon $ TC primR []\ntCont t             = tCon $ TC primCont [t]\n\nprimWrappedP        = gPrim \"Wrapped\"\npWrapped x y        = TC primWrappedP [x,y]\n\nprimWrappedC        = gPrim \"WrappedC\"\ntWrapped s x y      = tCon $ TC primWrappedC [s,x,y]\n\nattrVal             = name \"val\"\nattrWrap            = name \"wrap\"\nattrUnwrap          = name \"unwrap\"\n\nprimWrapProc        = gPrim \"wWrapProc\"\nprimWrapAction      = gPrim \"wWrapAction\"\nprimWrapMut         = gPrim \"wWrapMut\"\nprimWrapPure        = gPrim \"wWrapPure\"\n\nprimWRAP            = gPrim \"WRAP\"\n\nprimMkSet           = gPrim \"mkSet\"\nprimMkDict          = gPrim \"mkDict\"\nprimAnnot           = gPrim \"annot\"\n\nprimRaiseValueError = gPrim \"raiseValueError\"\nprimUGetItem        = gPrim \"listD_U__getitem__\"\nprimUNext           = gPrim \"rangeD_U__next__\"\n\nannot t_ann ann t e = eCall (tApp (eQVar primAnnot) [t_ann, t]) [ann, e]\n\nunAnnot t_ann (Call _ (TApp _ (Var _ n) [t,_]) (PosArg w (PosArg e PosNil)) KwdNil)\n  | n == primAnnot && t == t_ann    = (w, e)\n\nprimEnv             = [     (noq primASYNCf,        NDef scASYNCf NoDec Nothing),\n                            (noq primAFTERf,        NDef scAFTERf NoDec Nothing),\n                            (noq primAWAITf,        NDef scAWAITf NoDec Nothing),\n\n                            (noq primASYNCc,        NDef scASYNCc NoDec Nothing),\n                            (noq primAFTERc,        NDef scAFTERc NoDec Nothing),\n                            (noq primAWAITc,        NDef scAWAITc NoDec Nothing),\n\n                            (noq primASYNC,         NDef scASYNC NoDec Nothing),\n                            (noq primAFTER,         NDef scAFTER NoDec Nothing),\n                            (noq primAWAIT,         NDef scAWAIT NoDec Nothing),\n\n                            (noq primPUSH_Cc,       NDef scPUSH_Cc NoDec Nothing),\n                            (noq primPUSHF_Cc,      NDef scPUSHF_Cc NoDec Nothing),\n                            (noq primPUSH_C,        NDef scPUSH_C NoDec Nothing),\n                            (noq primPUSHF_C,       NDef scPUSHF_C NoDec Nothing),\n                            (noq primPOP_C,         NDef scPOP_C NoDec Nothing),\n                            (noq primDROP_C,        NDef scDROP_C NoDec Nothing),\n\n                            (noq primPUSH,          NDef scPUSH NoDec Nothing),\n                            (noq primPUSHF,         NDef scPUSHF NoDec Nothing),\n                            (noq primPOP,           NDef scPOP NoDec Nothing),\n                            (noq primDROP,          NDef scDROP NoDec Nothing),\n                            (noq primRAISE,         NDef scRAISE NoDec Nothing),\n\n                            (noq primSEQ,           clSEQ),\n                            (noq primBRK,           clBRK),\n                            (noq primCNT,           clCNT),\n                            (noq primRET,           clRET),\n\n                            (noq primASSERT,        NDef scASSERT NoDec Nothing),\n                            (noq primNEWACTOR,      NDef scNEWACTOR NoDec Nothing),\n                            (noq primInstallFinalizer, NDef scGCfinalizer NoDec Nothing),\n\n                            (noq primISINSTANCE,    NDef scISINSTANCE NoDec Nothing),\n                            (noq primISINSTANCE0,   NDef scISINSTANCE NoDec Nothing),\n                            (noq primCAST,          NDef scCAST NoDec Nothing),\n                            (noq primCONSTCONT,     NDef scCONSTCONT NoDec Nothing),\n\n                            (noq primFORMAT,        NDef scFORMAT NoDec Nothing),\n\n                            (noq primProc,          clProc),\n                            (noq primAction,        clAction),\n                            (noq primMut,           clMut),\n                            (noq primPure,          clPure),\n\n                            (noq primActor,         clActor),\n                            (noq primR,             clR),\n                            (noq primCont,          clCont),\n\n                            (noq primBox,           clBox),\n\n                            (noq primRContc,        NDef scRContc NoDec Nothing),\n                            (noq primRCont,         NDef scRCont NoDec Nothing),\n                            (noq primRFail,         NDef scRFail NoDec Nothing),\n\n                            (noq primEqOpt,         clEqOpt),\n                            (noq primIdentityActor, clIdentityActor),\n\n                            (noq primWEqNone,       NVar tEqNone),\n                            (noq witIntegralInt,    NVar tIntegralInt),\n\n                            (noq primISNOTNONE,     NDef scISNOTNONE NoDec Nothing),\n                            (noq primISNONE,        NDef scISNONE NoDec Nothing),\n                            (noq primISNOTNONE0,    NDef scISNOTNONE NoDec Nothing),\n                            (noq primISNONE0,       NDef scISNONE NoDec Nothing),\n\n                            (noq primSKIPRESc,      NDef scSKIPRESc NoDec Nothing),\n                            (noq primSKIPRES,       NDef scSKIPRES NoDec Nothing),\n\n                            (noq primWrappedP,      proWrapped),\n                            (noq primWrappedC,      clWrapped),\n--                            (noq primWrapProc,      NVar $ tWrapped fxProc fxProc fxProc),\n--                            (noq primWrapAction,    NVar $ tWrapped fxAction fxProc fxProc),\n\n                            (noq primWRAP,          NDef scWRAP NoDec Nothing),\n\n                            (noq primMkSet,         NDef scMkSet NoDec Nothing),\n                            (noq primMkDict,        NDef scMkDict NoDec Nothing),\n                            (noq primAnnot,         NDef scAnnot NoDec Nothing),\n                            (noq primRaiseValueError,NDef scRaiseValueError NoDec Nothing), \n                            (noq primUGetItem,      NDef scUGetItem NoDec Nothing),\n                            (noq primUNext,         NDef scUNext NoDec Nothing)\n                      ]\n\n--  class $Cont[T] (value): pass\n--      __call__    : proc(T) -> $R\nclCont              = NClass [qbind t] (leftpath [cValue]) te Nothing\n  where te          = [ (attr_call_, NSig (monotype $ tFun fxProc (posRow (tVar t) posNil) kwdNil tR) NoDec Nothing) ]\n        t           = TV KType (name \"T\")\n\n--  class $proc[R,T] (value):\n--      __call__    : proc($Cont[T], *R) -> $R\n--      __exec__    : proc($Cont[value], *R) -> $R\nclProc              = NClass [qbind r, qbind t] (leftpath [cValue]) te Nothing\n  where te          = [ (attr_call_, NSig (monotype $ tFun fxProc (posRow (tVar t) (tVar r)) kwdNil tR) NoDec Nothing),\n                        (attr_exec_, NSig (monotype $ tFun fxProc (posRow tValue (tVar r)) kwdNil tR) NoDec Nothing) ]\n        r           = TV PRow (name \"R\")\n        t           = TV KType (name \"T\")\n\n--  class $action[R,T] ($proc[R,T], value):\n--      __asyn__    : action(*R) -> T\nclAction            = NClass [qbind r, qbind t] (leftpath [ cProc (tVar r) (tVar t), cValue]) te Nothing\n  where te          = [ (attr_asyn_, NSig (monotype $ tFun fxAction (tVar r) kwdNil (tVar t)) NoDec Nothing) ]\n        r           = TV PRow (name \"R\")\n        t           = TV KType (name \"T\")\n\n\n--  class $mut[R,T] ($proc[R,T], value):\n--      __eval__    : mut(*R) -> T\nclMut               = NClass [qbind r, qbind t] (leftpath [ cProc (tVar r) (tVar t), cValue]) te Nothing\n  where te          = [ (attr_eval_, NSig (monotype $ tFun fxMut (tVar r) kwdNil (tVar t)) NoDec Nothing) ]\n        r           = TV PRow (name \"R\")\n        t           = TV KType (name \"T\")\n\n--  class $pure[R,T] ($mut[R,T], $proc[R,T], value):\n--      __eval__    : pure(*R) -> T\nclPure              = NClass [qbind r, qbind t] (leftpath [ cMut (tVar r) (tVar t), cProc (tVar r) (tVar t), cValue]) te Nothing\n  where te          = [ (attr_eval_, NSig (monotype $ tFun fxPure (tVar r) kwdNil (tVar t)) NoDec Nothing) ]\n        r           = TV PRow (name \"R\")\n        t           = TV KType (name \"T\")\n\n--  class $Box[A] (object, value):\n--      ref         : A\n--      __init__    : (A) -> None\nclBox               = NClass [qbind a] (leftpath [cObject, cValue]) te Nothing\n  where te          = [ (valKW,  NSig (monotype $ tVar a) Property Nothing),\n                        (initKW, NDef (monotype $ tFun fxPure (posRow (tVar a) posNil) kwdNil tNone) NoDec Nothing) ]\n        a           = TV KType (name \"A\")\n\n\n--  class $Actor (): pass\nclActor             = NClass [] (leftpath [cValue]) te Nothing\n  where te          = [ (primKW \"next\",       NSig (monotype tActor) Property Nothing),\n                        (primKW \"msg\",        NSig (monotype (tMsg tWild)) Property Nothing),\n                        (primKW \"msg_tail\",   NSig (monotype (tMsg tWild)) Property Nothing),\n                        (primKW \"msg_lock\",   NSig (monotype $ tCon $ TC (gPrim \"Lock\") []) Property Nothing),\n                        (primKW \"affinity\",   NSig (monotype $ tCon $ TC (gPrim \"int64\") []) Property Nothing),\n                        (primKW \"outgoing\",   NSig (monotype (tMsg tWild)) Property Nothing),\n                        (primKW \"waitsfor\",   NSig (monotype (tMsg tWild)) Property Nothing),\n                        (primKW \"consume_hd\", NSig (monotype $ tCon $ TC (gPrim \"int64\") []) Property Nothing),\n                        (primKW \"catcher\",    NSig (monotype $ tCon $ TC (gPrim \"Catcher\") []) Property Nothing),\n                        (primKW \"globkey\",    NSig (monotype $ tCon $ TC (gPrim \"long\") []) Property Nothing),\n                        (boolKW,              NDef (monotype $ tFun fxPure posNil kwdNil tBool) NoDec Nothing),\n                        (strKW,               NDef (monotype $ tFun fxPure posNil kwdNil tStr) NoDec Nothing),\n                        (reprKW,              NDef (monotype $ tFun fxPure posNil kwdNil tStr) NoDec Nothing),\n                        (resumeKW,            NDef (monotype $ tFun fxMut posNil kwdNil tNone) NoDec Nothing),\n                        (cleanupKW,           NDef (monotype $ tFun fxMut posNil kwdNil tNone) NoDec Nothing)\n                      ]\n\n--  class $SEQ (BaseException, value):\n--      __init__ : () -> None\nclSEQ               = NClass [] (leftpath [cBaseException, cValue]) te Nothing\n  where te          = [ (initKW, NSig (monotype $ tFun fxPure posNil kwdNil tNone) NoDec Nothing) ]\n\n--  class $BRK (BaseException, value):\n--      __init__ : () -> None\nclBRK               = NClass [] (leftpath [cBaseException, cValue]) te Nothing\n  where te          = [ (initKW, NSig (monotype $ tFun fxPure posNil kwdNil tNone) NoDec Nothing) ]\n\n--  class $CNT (BaseException, value):\n--      __init__ : () -> None\nclCNT               = NClass [] (leftpath [cBaseException, cValue]) te Nothing\n  where te          = [ (initKW, NSig (monotype $ tFun fxPure posNil kwdNil tNone) NoDec Nothing) ]\n\n--  class $RET (BaseException, value):\n--      @property\n--      val      : value\n--      __init__ : (value) -> None\nclRET               = NClass [] (leftpath [cBaseException, cValue]) te Nothing\n  where te          = [ (attrVal, NSig (monotype tValue) Property Nothing),\n                        (initKW,  NSig (monotype $ tFun fxPure (posRow tValue posNil) kwdNil tNone) NoDec Nothing) ]\n\n\n--  class $R (): pass\nclR                 = NClass [] [] [] Nothing\n\n--  $ASYNCf         : [A] => action($Actor, proc()->A) -> A\nscASYNCf            = tSchema [qbind a] tASYNC\n  where tASYNC      = tFun fxAction (posRow tActor $ posRow tFun' posNil) kwdNil (tVar a)\n        a           = TV KType $ name \"A\"\n        tFun'       = tFun fxProc posNil kwdNil (tVar a)\n\n--  $AFTERf         : [A] => action(int, proc()->A) -> A\nscAFTERf            = tSchema [qbind a] tAFTER\n  where tAFTER      = tFun fxAction (posRow tFloat $ posRow tFun' posNil) kwdNil (tVar a)\n        a           = TV KType $ name \"A\"\n        tFun'       = tFun fxProc posNil kwdNil (tVar a)\n\n--  $AWAITf         : [A] => proc(Msg[A]) -> A\nscAWAITf            = tSchema [qbind a] tAWAIT\n  where tAWAIT      = tFun fxProc (posRow (tMsg $ tVar a) posNil) kwdNil (tVar a)\n        a           = TV KType $ name \"T\"\n\n\n--  $ASYNCc         : [A] => action($Actor, proc(proc(A)->$R)->$R) -> A\nscASYNCc            = tSchema [qbind a] tASYNC\n  where tASYNC      = tFun fxAction (posRow tActor $ posRow tCont' posNil) kwdNil (tVar a)\n        a           = TV KType $ name \"A\"\n        tCont'      = tFun fxProc (posRow tCont'' posNil) kwdNil tR\n        tCont''     = tFun fxProc (posRow (tVar a) posNil) kwdNil tR\n\n--  $AFTERc         : [A] => action(int, proc(proc(A)->$R)->$R) -> A\nscAFTERc            = tSchema [qbind a] tAFTER\n  where tAFTER      = tFun fxAction (posRow tFloat $ posRow tCont' posNil) kwdNil (tVar a)\n        a           = TV KType $ name \"A\"\n        tCont'      = tFun fxProc (posRow tCont'' posNil) kwdNil tR\n        tCont''     = tFun fxProc (posRow (tVar a) posNil) kwdNil tR\n\n--  $AWAITc         : [A] => proc(proc(A)->$R, Msg[A]) -> $R\nscAWAITc            = tSchema [qbind a] tAWAIT\n  where tAWAIT      = tFun fxProc (posRow tCont' $ posRow (tMsg $ tVar a) posNil) kwdNil tR\n        a           = TV KType $ name \"A\"\n        tCont'      = tFun fxProc (posRow (tVar a) posNil) kwdNil tR\n\n\n--  $ASYNC          : [A] => action($Actor, $Cont[$Cont[A]]) -> A\nscASYNC             = tSchema [qbind a] tASYNC\n  where tASYNC      = tFun fxAction (posRow tActor $ posRow tCont' posNil) kwdNil (tVar a)\n        a           = TV KType $ name \"A\"\n        tCont'      = tCont tCont''\n        tCont''     = tCont (tVar a)\n\n--  $AFTER          : [A] => action(int, $Cont[$Cont[A]]) -> A\nscAFTER             = tSchema [qbind a] tAFTER\n  where tAFTER      = tFun fxAction (posRow tFloat $ posRow tCont' posNil) kwdNil (tVar a)\n        a           = TV KType $ name \"A\"\n        tCont'      = tCont tCont''\n        tCont''     = tCont (tVar a)\n\n--  $AWAIT          : [A] => proc($Cont[A], Msg[A]) -> $R\nscAWAIT             = tSchema [qbind a] tAWAIT\n  where tAWAIT      = tFun fxProc (posRow tCont' $ posRow (tMsg $ tVar a) posNil) kwdNil tR\n        a           = TV KType $ name \"A\"\n        tCont'      = tCont (tVar a)\n\n\n\n--  $PUSH_Cc        : pure (proc(bool)->$R) -> None\nscPUSH_Cc           = tSchema [] tPUSH_C\n  where tPUSH_C     = tFun fxPure (posRow tCont' posNil) kwdNil tNone\n        tCont'      = tFun fxProc (posRow tBool posNil) kwdNil tR\n\n--  $PUSH_FCc       : pure (proc(bool)->$R) -> None\nscPUSHF_Cc          = tSchema [] tPUSHF_C\n  where tPUSHF_C    = tFun fxPure (posRow tCont' posNil) kwdNil tNone\n        tCont'      = tFun fxProc (posRow tBool posNil) kwdNil tR\n\n--  $PUSH_C         : pure ($Cont[bool]) -> None\nscPUSH_C            = tSchema [] tPUSH_C\n  where tPUSH_C     = tFun fxPure (posRow (tCont tBool) posNil) kwdNil tNone\n\n--  $PUSHF_C        : pure ($Cont[bool]) -> None\nscPUSHF_C           = tSchema [] tPUSHF_C\n  where tPUSHF_C    = tFun fxPure (posRow (tCont tBool) posNil) kwdNil tNone\n\n--  $POP_C          : pure () -> BaseExceptiom\nscPOP_C             = tSchema [] tPOP_C\n  where tPOP_C      = tFun fxPure posNil kwdNil tBaseException\n\n--  $DROP_C         : pure () -> None\nscDROP_C            = tSchema [] tDROP_C\n  where tDROP_C     = tFun fxPure posNil kwdNil tNone\n\n--  $PUSH           : () -> bool\nscPUSH              = tSchema [] tPUSH\n  where tPUSH       = tFun fxPure posNil kwdNil tBool\n\n--  $PUSHF          : () -> bool\nscPUSHF             = tSchema [] tPUSHF\n  where tPUSHF      = tFun fxPure posNil kwdNil tBool\n\n--  $POP            : () -> BaseException\nscPOP               = tSchema [] tPOP\n  where tPOP        = tFun fxPure posNil kwdNil tBaseException\n\n--  $DROP           : () -> None\nscDROP              = tSchema [] tDROP\n  where tDROP       = tFun fxPure posNil kwdNil tNone\n\n--  $RAISE          : (BaseException) -> None\nscRAISE             = tSchema [] tRAISE\n  where tRAISE      = tFun fxPure (posRow tBaseException posNil) kwdNil tNone\n\n\n--  $ASSERT         : pure (bool, ?str) -> None\nscASSERT            = tSchema [] tASSERT\n  where tASSERT     = tFun fxPure (posRow tBool $ posRow (tOpt tStr) posNil) kwdNil tNone\n\n--  $NEWACTOR       : [A($Actor)] => pure () -> A\nscNEWACTOR          = tSchema [QBind a [cActor]] tNEWACTOR\n  where tNEWACTOR   = tFun fxPure posNil kwdNil (tVar a)\n        a           = TV KType $ name \"A\"\n\n--  $GCfinalizer    : [A($Actor)] => pure (A) -> None\nscGCfinalizer       = tSchema [QBind a [cActor]] tGCfin\n  where tGCfin      = tFun fxPure (posRow (tVar a) posNil) kwdNil tNone\n        a           = TV KType $ name \"A\"\n\n--  $ISINSTANCE     : pure (struct, _) -> bool\nscISINSTANCE        = tSchema [] tISINSTANCE\n  where tISINSTANCE = tFun fxPure (posRow tValue $ posRow tWild posNil) kwdNil tNone\n\n--  $CAST           : [A, B] => (A) -> B\nscCAST              = tSchema [qbind a, qbind b] tCAST\n  where tCAST       = tFun fxPure (posRow (tVar a) posNil) kwdNil (tVar b)\n        a           = TV KType $ name \"A\"\n        b           = TV KType $ name \"B\"\n\n--  $CONSTCONT      : [A] => (A, $Cont[A]) -> $Cont[tNone]\nscCONSTCONT         = tSchema [qbind a] tCONSTCONT\n  where tCONSTCONT  = tFun fxPure (posRow (tVar a) $ posRow tCont' posNil) kwdNil tCont''\n        tCont'      = tCont (tVar a)\n        tCont''     = tCont tNone\n        a           = TV KType $ name \"A\"\n\n--  $FORMAT         : [P] => (str, (*P)) -> str\nscFORMAT            = tSchema [qbind p] tFORMAT\n  where tFORMAT     = tFun fxPure (posRow tStr $ posRow (tTuple (tVar p) kwdNil) posNil) kwdNil tStr\n        p           = TV KType $ name \"P\"\n\n--  $R_CONTc        : [A] => proc(proc(A)->$R, A) -> $R\nscRContc            = tSchema [qbind a] tRCont\n  where tRCont      = tFun fxProc (posRow tCont' $ posRow (tVar a) posNil) kwdNil tR\n        tCont'      = tFun fxProc (posRow (tVar a) posNil) kwdNil tR\n        a           = TV KType $ name \"A\"\n\n--  $R_CONT         : [A] => proc($Cont[A], A) -> $R\nscRCont             = tSchema [qbind a] tRCont\n  where tRCont      = tFun fxProc (posRow tCont' $ posRow (tVar a) posNil) kwdNil tR\n        tCont'      = tCont (tVar a)\n        a           = TV KType $ name \"A\"\n\n--  $R_FAIL         : proc(BaseException) -> $R\nscRFail             = tSchema [] tRFail\n  where tRFail      = tFun fxProc (posRow tBaseException posNil) kwdNil tR\n\n\n--  class $EqOpt[A] (Eq[?A]): pass\nclEqOpt             = NClass [qbind a] (leftpath [TC qnEq [tOpt $ tVar a]]) clTEnv Nothing\n  where clTEnv      = [ (initKW, NDef scInit NoDec Nothing) ]\n        scInit      = tSchema [] $ tFun fxPure (posRow (tCon $ TC qnEq [tVar a]) posNil) kwdNil tNone\n        a           = TV KType (name \"A\")\n\n--  class $IdentityActor (Identity[$Actor]): pass\nclIdentityActor     = NClass [] (leftpath [TC qnIdentity [tActor]]) [] Nothing                 -- methods not modelled\n\n--  w$EqNone        : Eq[None]\ntEqNone             = tCon $ TC qnEq [tNone]\n\n--  $Integral$Int$witness : Integral[int]\ntIntegralInt        = tCon $ TC qnIntegral [tInt]\n\n--  $Integral$Bigint$witness : Integral[bigint]\ntIntegralBigint     = tCon $ TC qnIntegral [tBigint]\n\n\n--  $ISNOTNONE      : [A] => pure (?A) -> bool\nscISNOTNONE         = tSchema [qbind a] tISNOTNONE\n  where tISNOTNONE  = tFun fxPure (posRow (tOpt $ tVar a) posNil) kwdNil tBool\n        a           = TV KType (name \"A\")\n\n--  $ISNONE         : [A] => pure (?A) -> bool\nscISNONE            = tSchema [qbind a] tISNONE\n  where tISNONE     = tFun fxPure (posRow (tOpt $ tVar a) posNil) kwdNil tBool\n        a           = TV KType (name \"A\")\n\n--  $SKIPRESc       : [A] => pure(proc(None)->$R) -> proc(A)->$R\nscSKIPRESc          = tSchema [qbind a] tSKIPRES\n  where tSKIPRES    = tFun fxPure (posRow tCont' posNil) kwdNil tCont''\n        tCont'      = tFun fxProc (posRow tNone posNil) kwdNil tR\n        tCont''     = tFun fxProc (posRow (tVar a) posNil) kwdNil tR\n        a           = TV KType $ name \"A\"\n\n--  $SKIPRES        : [X,A] => pure($Cont[None]) -> $Cont[A]\nscSKIPRES           = tSchema [qbind a] tSKIPRES\n  where tSKIPRES    = tFun fxPure (posRow tCont' posNil) kwdNil tCont''\n        tCont'      = tCont tNone\n        tCont''     = tCont (tVar a)\n        a           = TV KType $ name \"A\"\n\n\n--  $MkSet          : [A] => (Hashable[A], set[A]) -> set[A]\nscMkSet             = tSchema [qbind a] tMkSet\n  where tMkSet      = tFun fxPure (posRow tHashableA (posRow (tSet (tVar a)) posNil)) kwdNil (tSet (tVar a))\n        tHashableA  = tCon (TC qnHashable [tVar a])\n        a           = TV KType $ name \"A\"\n\n--  $MkDict         : [A] => (Hashable[A], dict[A]) -> dict[A]\nscMkDict            = tSchema [qbind a, qbind b] tMkDict\n  where tMkDict     = tFun fxPure (posRow tHashableA (posRow (tDict (tVar a) (tVar b)) posNil)) kwdNil (tDict (tVar a)(tVar b))\n        tHashableA  = tCon (TC qnHashable [tVar a])\n        a           = TV KType $ name \"A\"\n        b           = TV KType $ name \"B\"\n\n--  $annot : [A,B] => (A,B) -> B\nscAnnot             = tSchema [qbind a, qbind b] tAnnot\n  where tAnnot      = tFun fxPure (posRow (tVar a) (posRow (tVar b) posNil)) kwdNil (tVar b)\n        a           = TV KType $ name \"A\"\n        b           = TV KType $ name \"B\"\n\n-- $listD_U__getitem__ : [A] => (list[A], int) -> A\nscUGetItem          = tSchema [qbind a] tUGetItem\n  where tUGetItem   = tFun fxPure (posRow (tList (tVar a)) (posRow tInt posNil)) kwdNil (tVar a)\n        a           = TV KType $ name \"A\"\n\nscRaiseValueError   = tSchema [qbind a] tRaiseValErr\n  where tRaiseValErr= tFun fxPure (posRow tStr posNil) kwdNil (tVar a)\n        a           = TV KType (name \"A\")\n        \n-- $rangeD_U__next__ : [A] => (Iterator[A]) -> A   will only be used to replace B_IteratorD_range.__next__\nscUNext             = tSchema [] tUNext\n  where tUNext      = tFun fxMut (posRow (tIterator (tInt)) posNil) kwdNil tInt\n        \n--  $WRAP           : [A,B,C] => ($Actor, proc(*A,**B)->C) -> action(*A,**B)->C\nscWRAP              = tSchema [qbind a, qbind b, qbind c] tWRAP\n  where tWRAP       = tFun0 [tActor, abcFun fxProc] (abcFun fxAction)\n        abcFun fx   = tFun fx (tVar a) (tVar b) (tVar c)\n        a           = TV KType (name \"A\")\n        b           = TV KType (name \"B\")\n        c           = TV KType (name \"C\")\n\n--  protocol $Wrapped[X,Y]:\n--      @static\n--      wrap        : [A,B,C] => ($Actor, X(*A,**B)->C) -> Self(*A,**B)->C\n--      @static\n--      unwrap      : [A,B,C] => (Self(*A,**B)->C) -> Y(*A,**B)->C\nproWrapped          = NProto [qbind x, qbind y] [] te Nothing\n  where te          = [(attrWrap,scWrap), (attrUnwrap,scUnwrap)]\n        scWrap      = NSig (tSchema q (tFun0 [tActor, fxFun tX] (fxFun tSelf)))  Static Nothing\n        scUnwrap    = NSig (tSchema q (tFun0 [fxFun tSelf] (fxFun tY))) Static Nothing\n        fxFun fx    = tFun fx (tVar a) (tVar b) (tVar c)\n        tX          = tVar x\n        tY          = tVar y\n        tSelf       = tVar fxSelf\n        q           = [qbind a, qbind b, qbind c]\n        x           = TV KFX (name \"X\")\n        y           = TV KFX (name \"Y\")\n        a           = TV PRow (name \"A\")\n        b           = TV KRow (name \"B\")\n        c           = TV KType (name \"C\")\n\n--  class $WrappedC[S,X,Y]: pass\n--      wrap        : [A,B,C] => ($Actor, X(*A,**B)->C) -> S(*A,**B)->C\n--      unwrap      : [A,B,C] => (S(*A,**B)->C) -> X(*A,**B)->C\nclWrapped           = NClass [qbind s, qbind x, qbind y] [] te Nothing\n  where te          = [(attrWrap,scWrap), (attrUnwrap,scUnwrap)]\n        scWrap      = NDef (tSchema q (tFun0 [tActor, fxFun tX] (fxFun tS))) NoDec Nothing\n        scUnwrap    = NDef (tSchema q (tFun0 [fxFun tS] (fxFun tY))) NoDec Nothing\n        fxFun fx    = tFun fx (tVar a) (tVar b) (tVar c)\n        tS          = tVar s\n        tX          = tVar x\n        tY          = tVar y\n        q           = [qbind a, qbind b, qbind c]\n        s           = TV KFX (name \"S\")\n        x           = TV KFX (name \"X\")\n        y           = TV KFX (name \"Y\")\n        a           = TV PRow (name \"A\")\n        b           = TV KRow (name \"B\")\n        c           = TV KType (name \"C\")\n\n\n\nprimWits            = [ WInst []        fxAction (pWrapped fxProc fxProc)   primWrapAction path,\n                        WInst []        fxProc   (pWrapped fxProc fxProc)   primWrapProc path,\n                        WInst []        fxMut    (pWrapped fxMut  fxMut)    primWrapMut path,\n                        WInst [qbind y] fxPure   (pWrapped fxPure (tVar y)) primWrapPure path\n                      ]\n  where path        = [Left (noQ \"_\")]\n        y           = TV KFX (name \"Y\")\n\nisPUSH (Call _ (Var _ x) _ _)   = x `elem` [primPUSH,primPUSHF]\nisPUSH _                        = False\n\nisPUSHF (Call _ (Var _ x) _ _)  = x == primPUSHF\nisPUSHF _                       = False\n\nisRAISE (Call _ (Var _ x) _ _)  = x == primRAISE\nisRAISE _                       = False\n\n\n"
  },
  {
    "path": "compiler/lib/src/Acton/Printer.hs",
    "content": "-- Copyright (C) 2019-2021 Data Ductus AB\n--\n-- Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:\n--\n-- 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.\n--\n-- 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.\n--\n-- 3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission.\n--\n-- THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS \"AS IS\" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n--\n\n{-# LANGUAGE MultiParamTypeClasses, FlexibleInstances, FlexibleContexts, DeriveGeneric #-}\nmodule Acton.Printer (module Acton.Printer, module Pretty) where\n\nimport Utils\nimport Pretty\nimport Acton.Syntax\nimport Prelude hiding ((<>))\n\n\n\ninstance Pretty Module where\n    pretty (Module qn imps doc stmts)\n                                    = joinSections [prHead qn, prettyModDoc doc, vpretty imps, vpretty stmts]\n\nprHead qn                           = empty\n--prHead qn                           = text \"module\" <+> pretty qn <> colon $+$ blank\n\ninstance Pretty Import where\n    pretty (Import _ ms)            = text \"import\" <+> commaSep pretty ms\n    pretty (FromImport _ n ns)      = text \"from\" <+> pretty n <+> text \"import\" <+> commaSep pretty ns\n    pretty (FromImportAll _ n)      = text \"from\" <+> pretty n <+> text \"import\" <+> text \"*\"\n\nprettySuite ss                      = nest 4 $ vcat $ map pretty ss\n\njoinSections :: [Doc] -> Doc\njoinSections = vcat . punctuate blank . filter (not . isEmpty)\n\nprettyModDoc :: Maybe String -> Doc\nprettyModDoc Nothing                = empty\nprettyModDoc (Just doc)             = text \"\\\"\\\"\\\"\" <> text (escapeDocstring doc) <> text \"\\\"\\\"\\\"\"\n\n-- Pretty print a suite with optional docstring at the beginning\nprettyDocSuite :: Maybe String -> Suite -> Doc\nprettyDocSuite Nothing ss           = prettySuite ss\nprettyDocSuite (Just doc) ss        = nest 4 $ vcat $ text \"\\\"\\\"\\\"\" <> text (escapeDocstring doc) <> text \"\\\"\\\"\\\"\" : map pretty ss\n\n-- Escape special characters in docstrings for pretty printing\nescapeDocstring :: String -> String\nescapeDocstring []                  = []\nescapeDocstring ('\\\\':xs)           = '\\\\' : '\\\\' : escapeDocstring xs\nescapeDocstring ('\"':xs)            = '\\\\' : '\"' : escapeDocstring xs\nescapeDocstring (x:xs)              = x : escapeDocstring xs\n\ninstance Pretty Stmt where\n    pretty (Expr _ e)               = pretty e\n    pretty (Assign _ ps e)          = hsep . punctuate (space <> equals) $ map pretty ps ++ [pretty e]\n    pretty (MutAssign _ t e)        = pretty t <+> equals <+> pretty e\n    pretty (AugAssign _ t o e)      = pretty t <+> pretty o <+> pretty e\n    pretty (Assert _ e mbe)         = text \"assert\" <+> pretty e <> nonEmpty (comma <+>) pretty mbe\n    pretty (Pass _)                 = text \"pass\"\n    pretty (Delete _ t)             = text \"del\" <+> pretty t\n    pretty (Return _ e)             = text \"return\" <+> pretty e\n    pretty (Raise _ e)              = text \"raise\" <+> pretty e\n    pretty (Break _)                = text \"break\"\n    pretty (Continue _)             = text \"continue\"\n    pretty (If _ (b:bs) b2)         = prettyBranch \"if\" b $+$ vmap (prettyBranch \"elif\") bs $+$ prettyEnd \"else\" b2\n    pretty (While _ e b b2)         = text \"while\" <+> pretty e <> colon $+$ prettySuite b $+$ prettyEnd \"else\" b2\n    pretty (For _ p e b b2)         = text \"for\" <+> pretty p <+> text \"in\" <+> pretty e <> colon $+$\n                                      prettySuite b $+$ prettyEnd \"else\" b2\n    pretty (Try _ b hs b2 b3)       = text \"try\" <> colon $+$ prettySuite b $+$ vmap pretty hs $+$\n                                      prettyEnd \"else\" b2 $+$ prettyEnd \"finally\" b3\n    pretty (With _ items b)         = text \"with\" <+> commaSep pretty items <> colon $+$ prettySuite b\n    pretty (Data _ (Just e) b)      = pretty e <> colon $+$ prettySuite b\n    pretty (Data _ Nothing b)       = text \"return\" <> colon $+$ prettySuite b\n    pretty (VarAssign _ ps e)       = text \"var\" <+> (hsep . punctuate (space <> equals) $ map pretty ps ++ [pretty e])\n    pretty (After _ e e')           = text \"after\" <+> pretty e <> colon <+> pretty e'\n    pretty (Decl _ [d])             = pretty d\n    pretty (Decl _ ds)              = text \"# recursive group:\" $+$ (vcat $ map pretty ds) $+$ text \"# (recursive group)\"\n    pretty (Signature _ vs sc d)    = prettyDec d $ commaList vs <+> colon <+> pretty sc\n\ninstance Pretty Decl where\n    pretty (Def _ n q p k a b d x doc)\n                                    = (prettyDecFX d x $ text \"def\" <+> pretty n <> nonEmpty brackets commaList q <+>\n                                      parens (pretty (p,k)) <> nonEmpty (text \" -> \" <>) pretty a <> colon) $+$ prettyDocSuite doc b\n    pretty (Actor _ n q p k b doc)  = text \"actor\" <+> pretty n <> nonEmpty brackets commaList q <+>\n                                      parens (pretty (p,k)) <> colon $+$ prettyDocSuite doc b\n    pretty (Class _ n q a b doc)    = text \"class\" <+> pretty n <> nonEmpty brackets commaList q <+>\n                                      nonEmpty parens commaList a <> colon $+$ prettyDocSuite doc b\n    pretty (Protocol _ n q a b doc) = text \"protocol\" <+> pretty n <> nonEmpty brackets commaList q <+>\n                                      nonEmpty parens commaList a <> colon $+$ prettyDocSuite doc b\n    pretty (Extension _ q c a b doc)\n      | tvs == tcargs c             = text \"extension\" <+> pretty (tcname c) <> nonEmpty brackets commaList q <+>\n                                      nonEmpty parens commaList a <> colon $+$ prettyDocSuite doc b\n      | otherwise                   = text \"extension\" <+> prettyQual q <+> pretty c <+>\n                                      nonEmpty parens commaList a <> colon $+$ prettyDocSuite doc b\n      where tvs                     = map tVar $ qbound q\n\nprettyDecFX d fx                    = prettyDec d . (prettyFXnoWild fx <+>)\n\nprettyFXnoWild (TWild _)            = empty\nprettyFXnoWild fx                   = pretty fx\n\nprettyBranch kw (Branch e b)        = text kw <+> pretty e <> colon $+$ prettySuite b\n\nprettyEnd kw []                     = empty\nprettyEnd kw b                      = text kw <> colon $+$ prettySuite b\n\nprettyOpt sep Nothing               = empty\nprettyOpt sep (Just a)              = sep <+> pretty a\n\n\ninstance Pretty PosPar where\n    pretty (PosPar n t e PosNIL)    = pretty n <+> prettyOpt colon t <+> prettyOpt equals e\n    pretty (PosPar n t e p)         = pretty n <+> prettyOpt colon t <+> prettyOpt equals e <> comma <+> pretty p\n    pretty (PosSTAR n t)            = text \"*\" <> pretty n <+> prettyOpt colon t\n    pretty PosNIL                   = empty\n\ninstance Pretty KwdPar where\n    pretty (KwdPar n t e KwdNIL)    = pretty n <+> prettyOpt colon t <+> prettyOpt equals e\n    pretty (KwdPar n t e k)         = pretty n <+> prettyOpt colon t <+> prettyOpt equals e <> comma <+> pretty k\n    pretty (KwdSTAR n t)            = text \"**\" <> pretty n <+> prettyOpt colon t\n    pretty KwdNIL                   = empty\n\ninstance Pretty (PosPar,KwdPar) where\n    pretty (PosNIL, ks)             = pretty ks\n    pretty (ps, KwdNIL)             = pretty ps\n    pretty (ps, ks)                 = pretty ps <> comma <+> pretty ks\n\ninstance Pretty PosArg where\n    pretty (PosArg e PosNil)        = pretty e\n    pretty (PosArg e p)             = pretty e <> comma <+> pretty p\n    pretty (PosStar e)\n      | atomic e                    = text \"*\" <> pretty e\n      | otherwise                   = text \"*\" <> parens (pretty e)\n    pretty PosNil                   = empty\n\ninstance Pretty KwdArg where\n    pretty (KwdArg n e KwdNil)      = pretty n <+> equals <+> pretty e\n    pretty (KwdArg n e k)           = pretty n <+> equals <+> pretty e <> comma <+> pretty k\n    pretty (KwdStar e)\n      | atomic e                    = text \"**\" <> pretty e\n      | otherwise                   = text \"**\" <> parens (pretty e)\n    pretty KwdNil                   = empty\n\ninstance Pretty (PosArg,KwdArg) where\n    pretty (PosNil, ks)             = pretty ks\n    pretty (ps, KwdNil)             = pretty ps\n    pretty (ps, ks)                 = pretty ps  <> comma <+> pretty ks\n\natomic Await{}                      = False\natomic Cond{}                       = False\natomic BinOp{}                      = False\natomic CompOp{}                     = False\natomic UnOp{}                       = False\natomic Lambda{}                     = False\natomic Yield{}                      = False\natomic YieldFrom{}                  = False\natomic _                            = True\n\nprettyAtom e\n  | atomic e                        = pretty e\n  | otherwise                       = parens (pretty e)\n\ninstance Pretty Expr where\n    pretty (Var _ n)                = pretty n\n    pretty (Int _ _ str)            = text str\n    pretty (Float _ _ str)          = text str\n    pretty (Imaginary _ _ str)      = text str\n    pretty (Bool _ v)               = pretty v\n    pretty (None _)                 = text \"None\"\n    pretty (NotImplemented _)       = text \"NotImplemented\"\n    pretty (Ellipsis _)             = text \"...\"\n    pretty (Strings _ ss)           = hsep (map (pretty . show) ss)\n    pretty (BStrings _ ss)          = hsep (map (\\s -> text \" b\" <> pretty s) ss)\n    pretty (Call _ e ps ks)         = prettyAtom e <> parens (pretty (ps,ks))\n    pretty (TApp _ e ts)            = pretty e <> text \"@\" <> brackets (commaSep pretty ts)\n    pretty (Let _ ss e)             = text \"let:\" $+$ prettySuite ss $+$  text \"in\" <+> pretty e\n    pretty (Async _ e)              = parens (text \"async\" <+> pretty e)\n    pretty (Await _ e)              = text \"await\" <+> pretty e\n    pretty (Index _ e ix)           = prettyAtom e <> brackets (pretty ix)\n    pretty (Slice _ e sl)           = prettyAtom e <> brackets (pretty sl)\n    pretty (IsInstance _ e c)       = text \"isinstance\" <> parens (pretty e <> comma <+> pretty c)\n    pretty (Dot _ e n)              = prettyAtom e <> dot <> pretty n\n    pretty (Rest _ e n)             = prettyAtom e <> dot <> text \"~\" <> pretty n\n    pretty (DotI _ e i)             = prettyAtom e <> dot <> pretty i\n    pretty (RestI _ e i)            = prettyAtom e <> dot <> text \"~\" <> pretty i\n    pretty (Opt _ e True)           = pretty e <> text \"?\"\n    pretty (Opt _ e False)          = pretty e <> text \"!\"\n    pretty (OptChain _ e)           = pretty e\n    pretty (Lambda _ ps ks e fx)    = prettyFXnoWild fx <+> text \"lambda\" <+> prettyLambdaPar ps ks <> colon <+> pretty e\n    pretty (Yield _ e)              = text \"yield\" <+> pretty e\n    pretty (YieldFrom _ e)          = text \"yield\" <+> text \"from\" <+> pretty e\n    pretty (Tuple _ ps KwdNil)\n        | singlePosArg ps           = parens (pretty ps <> comma)\n    pretty (Tuple _ ps ks)          = parens (pretty (ps,ks))\n    pretty (List _ es)              = brackets (commaList es)\n    pretty (ListComp _ e co)        = brackets (pretty e <+> pretty co)\n    pretty (Dict _ es)              = braces (commaList es)\n    pretty (DictComp _ e co)        = braces (pretty e <+> pretty co)\n    pretty (Set _ [])               = text \"set\" <> parens empty\n    pretty (Set _ es)               = braces (commaList es)\n    pretty (SetComp _ e co)         = braces (pretty e <+> pretty co)\n    pretty (Paren _ e@Tuple{})      = pretty e\n    pretty (Paren _ e)              = parens (pretty e)\n    pretty (Box t e)                = parens (text \"BOX\" <+> pretty t <+> pretty e)\n    pretty (UnBox t e)              = parens (text \"UNBOX\" <+> pretty t <+> pretty e)\n    pretty e                        = prettyPrec 0 e  -- BinOp, CompOp, UnOp and Cond\n\n{-\nWe assign precedences to operator expressions according to their main operator as follows.\nThe Python language reference does not assign numerical precedences, but the precedence order\nimplied by the syntax rules is consistent with the values below, with one exception:\nQuote from section 6.5 in The Python Language Reference (v 3.8.6):\n    \"The power operator binds more tightly than unary operators on its left;\n     it binds less tightly than unary operators on its right.\"\nPrinting here does not minimize the use of parentheses; unary operator expressions are\nput in parenthesis (for clarity) in all operator contexts, also where the parser does not need them.\n\n12 **\n11 (unary) + - ~\n10 * / // / @\n 9 + -\n 8 << >>\n 7 &\n 6 ^\n 5 |\n 4 < > <= >= == !=, is, is not, in, not in\n 3 not\n 2 and\n 1 or\n 0 _ if _ else _\n-}\n\nprettyPrec n e@(BinOp _ e1 op e2)   = parensIf (n > prc) ps\n     where prc                      = fromJust (lookup op bps)\n           bps                      = [(Or,1),(And,2),(Plus,9),(Minus,9),(Mult,10),(Pow,12),(Div,10),(Mod,10),\n                                       (EuDiv,10),(BOr,5),(BXor,6),(BAnd,7),(ShiftL,8),(ShiftR,8),(MMult,10)]\n           ps | op == Pow           = prettyPrec (prc+1) e1 <+> pretty op <+> prettyPrec prc e2\n              | otherwise           = prettyPrec prc e1 <+> pretty op <+> prettyPrec (prc+1) e2\nprettyPrec n (CompOp _ e ops)       = parensIf (n > 4) $ pretty e <+> hsep (map pretty ops)\nprettyPrec n e1@(UnOp _ op e)       = parensIf (n > 0) $ pretty op <> prettyPrec prc e\n   where prc                        = if op == Not then 3 else 11\nprettyPrec n (Cond _ e1 e e2)       = parensIf (n > 1) $ pretty e1 <+> text \"if\" <+> pretty e <+> text \"else\" <+> pretty e2\nprettyPrec _ e                      = pretty e\n\nprettyLambdaPar ps ks\n  | annotP ps || annotK ks          = parens (pretty (ps,ks))\n  | otherwise                       = pretty (ps,ks)\n  where annotP (PosPar _ mba _ p)   = mba /= Nothing || annotP p\n        annotP (PosSTAR _ mba)      = mba /= Nothing\n        annotP PosNIL               = False\n        annotK (KwdPar _ mba _ k)   = mba /= Nothing || annotK k\n        annotK (KwdSTAR _ mba)      = mba /= Nothing\n        annotK KwdNIL               = False\n\ninstance Pretty OpArg where\n    pretty (OpArg op e)             = pretty op <+> pretty e\n\n\nprettyTuple []                      = text \"()\"\nprettyTuple [e]                     = pretty e <> char ','\nprettyTuple es                      = commaCat es\n\ninstance Pretty Name where\n    pretty nm\n      | nm == nSelf                 = text \"Self\"\n      | isIdent str                 = text str\n      | otherwise                   = quotes (text str)\n      where str                     = nstr nm\n\ninstance Pretty ModName where\n    pretty (ModName ns)             = dotCat pretty ns\n\ninstance Pretty QName where\n--    pretty (QName m n)              = char '~' <> pretty m <> dot <> pretty n\n    pretty (QName m n)              = pretty m <> dot <> pretty n\n--    pretty (NoQ n)                  = char '~' <> pretty n\n    pretty (NoQ n)                  = pretty n\n    pretty (GName m n)\n      | ModName [Name _ \"$\"] <- m   = text (\"$\" ++ rawstr n)\n      | otherwise                   = pretty m <> dot <> pretty n\n\ninstance Pretty ModRef where\n    pretty (ModRef (i,n))           = hcat (replicate i dot) <> pretty n\n\ninstance Pretty Handler where\n    pretty (Handler ex b)           = pretty ex <> colon $+$ prettySuite b\n\ninstance Pretty Except where\n    pretty (ExceptAll _)            = text \"except\"\n    pretty (Except _ x)             = text \"except\" <+> pretty x\n    pretty (ExceptAs _ x n)         = text \"except\" <+> pretty x <+> text \"as\" <+> pretty n\n\nprettyAnn Nothing                   = empty\nprettyAnn (Just a)                  = colon <+> pretty a\n\ninstance Pretty Elem where\n    pretty (Elem e)                 = pretty e\n    pretty (Star e)                 = text \"*\" <> pretty e\n\ninstance Pretty Assoc where\n    pretty (Assoc k v)              = pretty k <> colon <+> pretty v\n    pretty (StarStar e)             = text \"**\" <> pretty e\n\ninstance Pretty WithItem where\n    pretty (WithItem e p)           = pretty e <+> nonEmpty (text \"as\" <+>) pretty p\n\ninstance Pretty ModuleItem where\n    pretty (ModuleItem n1 n2)       = pretty n1 <+> nonEmpty (text \"as\" <+>) pretty n2\n\ninstance Pretty ImportItem where\n    pretty (ImportItem n1 n2)       = pretty n1 <+> nonEmpty (text \"as\" <+>) pretty n2\n\ninstance Pretty Sliz where\n    pretty (Sliz _ a b c)           = pretty a <> colon <> pretty b <> nonEmpty (colon <>) pretty c\n\ninstance Pretty Comp where\n    pretty (CompFor _ p e c)        = text \"for\" <+> pretty p <+> text \"in\" <+> pretty e <+> pretty c\n    pretty (CompIf _ e c)           = text \"if\" <+> pretty e <+> pretty c\n    pretty NoComp                   = empty\n\n\ninstance Pretty PosPat where\n    pretty (PosPat p PosPatNil)     = pretty p\n    pretty (PosPat p ps)            = pretty p <> comma <+> pretty ps\n    pretty (PosPatStar p)           = text \"*\" <> pretty p\n    pretty PosPatNil                = empty\n\ninstance Pretty KwdPat where\n    pretty (KwdPat n p KwdPatNil)   = pretty n <+> equals <+> pretty p\n    pretty (KwdPat n p ps)          = pretty n <+> equals <+> pretty p <> comma <+> pretty ps\n    pretty (KwdPatStar p)           = text \"**\" <> pretty p\n    pretty KwdPatNil                = empty\n\ninstance Pretty (PosPat,KwdPat) where\n    pretty (PosPatNil, ks)          = pretty ks\n    pretty (ps, KwdPatNil)          = pretty ps\n    pretty (ps, ks)                 = pretty ps <> comma <+> pretty ks\n\ninstance Pretty Pattern where\n    pretty (PWild _ a)              = text \"_\" <> prettyAnn a\n    pretty (PVar _ n a)             = pretty n <> prettyAnn a\n    pretty (PTuple _ ps KwdPatNil)\n      | singlePosPat ps             = pretty ps <> comma\n    pretty (PTuple _ ps ks)         = pretty (ps, ks)\n    pretty (PList _ ps p)           = brackets (prettyPats ps p)\n    pretty (PParen _ p)             = parens (pretty p)\n    pretty (PData _ n ixs)          = pretty n <> hcat (map (brackets . pretty) ixs)\n\nprettyPats [] Nothing               = empty\nprettyPats ps Nothing               = commaSep pretty ps\nprettyPats [] (Just p)              = text \"*\" <> pretty p\nprettyPats ps (Just p)              = commaSep pretty ps <> comma <+> text \"*\" <> pretty p\n\nprettyDec d                         = (pretty d $+$)\n\ninstance Pretty Deco where\n    pretty NoDec                    = empty\n    pretty Static                   = text \"@static\"\n    pretty Property                 = text \"@property\"\n\ninstance Pretty Unary where\n    pretty Not                      = text \"not \"\n    pretty BNot                     = text \"~\"\n    pretty UMinus                   = text \"-\"\n    pretty UPlus                    = text \"+\"\n\ninstance Pretty Binary where\n    pretty Or                       = text \"or\"\n    pretty And                      = text \"and\"\n    pretty BOr                      = text \"|\"\n    pretty BXor                     = text \"^\"\n    pretty BAnd                     = text \"&\"\n    pretty ShiftL                   = text \"<<\"\n    pretty ShiftR                   = text \">>\"\n    pretty Plus                     = text \"+\"\n    pretty Minus                    = text \"-\"\n    pretty Mult                     = text \"*\"\n    pretty MMult                    = text \"@\"\n    pretty Div                      = text \"/\"\n    pretty Mod                      = text \"%\"\n    pretty EuDiv                    = text \"//\"\n    pretty Pow                      = text \"**\"\n\ninstance Pretty Comparison where\n    pretty Lt                       = text \"<\"\n    pretty Gt                       = text \">\"\n    pretty Eq                       = text \"==\"\n    pretty GE                       = text \">=\"\n    pretty LE                       = text \"<=\"\n    pretty NEq                      = text \"!=\"\n    pretty In                       = text \"in\"\n    pretty NotIn                    = text \"not in\"\n    pretty Is                       = text \"is\"\n    pretty IsNot                    = text \"is not\"\n\n\ninstance Pretty Aug where\n    pretty PlusA                    = text \"+=\"\n    pretty MinusA                   = text \"-=\"\n    pretty MultA                    = text \"*=\"\n    pretty MMultA                   = text \"@=\"\n    pretty DivA                     = text \"/=\"\n    pretty ModA                     = text \"%=\"\n    pretty PowA                     = text \"**=\"\n    pretty BAndA                    = text \"&=\"\n    pretty BOrA                     = text \"|=\"\n    pretty BXorA                    = text \"^=\"\n    pretty ShiftLA                  = text \"<<=\"\n    pretty ShiftRA                  = text \">>=\"\n    pretty EuDivA                   = text \"//=\"\n\ninstance Pretty TSchema where\n    pretty (TSchema _ q t)          = prettyQual q <+> pretty t\n\nprettyQual []                       = empty\nprettyQual q                        = pretty q <+> text \"=>\"\n\ninstance Pretty TVar where\n    pretty (TV k n)                 = pretty n -- <> parens (colon <> pretty k)\n\ninstance Pretty TUni where\n    pretty (UV k l i)\n      | i < 0                       = text \"T_\" <> pretty (-i) <> text \"w\" <> prl\n      | otherwise                   = text \"T_\" <> pretty i <> prk k <> prl\n      where prk PRow                = text \"p\"\n            prk KRow                = text \"k\"\n            prk KFX                 = text \"x\"\n            prk _                   = empty\n\n--            prl                     = parens (pretty l)\n            prl                     = empty\n\ninstance Pretty TCon where\n    pretty (TC n [])                = pretty n\n--    pretty (TC n [t])\n--      | n == qnSequence             = brackets (pretty t)\n--      | n == qnSetP                 = braces (pretty t)\n--    pretty (TC n [kt,vt])\n--      | n == qnMapping              = braces (pretty kt <> colon <+> pretty vt)\n    pretty (TC n ts)                = pretty n <> brackets (commaList ts)\n\ninstance Pretty QBinds where\n    pretty q                        = brackets (commaList q)\n\ninstance Pretty QBind where\n    pretty (QBind v [])             = pretty v\n    pretty (QBind v cs)             = pretty v <> parens (commaList cs)\n\nprettyPosRow (TRow _ PRow _ t (TNil _ PRow))\n                                    = pretty t\nprettyPosRow (TRow _ PRow _ t p)    = pretty t <> comma <+> prettyPosRow p\nprettyPosRow (TStar _ PRow r)\n  | TVar _ v <- r                   = text \"*\" <> pretty v\n  | TUni _ u <- r                   = text \"*\" <> pretty u\n  | TWild _ <- r                    = text \"*\"\n  | otherwise                       = text \"*\" <> parens (prettyPosRow r)   -- Print row as a tuple\nprettyPosRow (TVar _ v)             = text \"+\" <> pretty v\nprettyPosRow (TUni _ u)             = text \"+\" <> pretty u\nprettyPosRow (TWild _)              = text \"+\"\nprettyPosRow (TNil _ PRow)          = empty\nprettyPosRow t                      = text \"??\" <>  pretty t\n\nprettyKwdRow (TRow _ KRow n t (TNil _ KRow))\n                                    = pretty n <> colon <+> pretty t\nprettyKwdRow (TRow _ KRow n t k)    = pretty n <> colon <+> pretty t <> comma <+> prettyKwdRow k\nprettyKwdRow (TStar _ KRow r)\n  | TVar _ v <- r                   = text \"**\" <> pretty v\n  | TUni _ u <- r                   = text \"**\" <> pretty u\n  | TWild _ <- r                    = text \"**\"\n  | otherwise                       = text \"**\" <> parens (prettyKwdRow r)  -- Print row as a tuple\nprettyKwdRow (TVar _ v)             = text \"++\" <> pretty v\nprettyKwdRow (TUni _ u)             = text \"++\" <> pretty u\nprettyKwdRow (TWild _)              = text \"++\"\nprettyKwdRow (TNil _ KRow)          = empty\nprettyKwdRow t                      = text \"??\" <>  pretty t\n\nprettyFunRow (TNil _ PRow) k        = prettyKwdRow k\nprettyFunRow p (TNil _ KRow)        = prettyPosRow p\nprettyFunRow p k                    = prettyPosRow p <> comma <+> prettyKwdRow k\n\ninstance Pretty Type where\n    pretty (TVar _ v)               = pretty v\n    pretty (TUni _ u)               = pretty u\n    pretty (TCon  _ c)              = pretty c\n    pretty (TFun _ fx p k t)        = prettyFXnoPure fx <> parens (prettyFunRow p k) <+> text \"->\" <+> pretty t\n      where spaceSep f              = hsep . punctuate space . map f\n    pretty (TTuple _ p k)\n      | TVar{} <- p, TNil{} <- k    = pretty p                              -- Print top row variable as a tyvar\n      | TNil{} <- p, TVar{} <- k    = pretty k                              -- Print top row variable as a tyvar\n      | TUni{} <- p, TNil{} <- k    = pretty p                              -- Print top row variable as a univar\n      | TNil{} <- p, TUni{} <- k    = pretty k                              -- Print top row variable as a univar\n      | TRow _ _ _ t TNil{} <- p,\n        TNil{} <- k                 = parens (pretty t <> comma)\n      | otherwise                   = parens (prettyFunRow p k)\n    pretty (TOpt _ t)               = text \"?\" <> pretty t\n    pretty (TNone _)                = text \"None\"\n    pretty (TWild _)                = text \"_\"\n    pretty (TRow _ PRow _ t TNil{}) = parens $ pretty t <> comma\n    pretty r@TRow{rkind=PRow}       = parens $ prettyPosRow r\n    pretty r@TRow{rkind=KRow}       = parens $ prettyKwdRow r\n    pretty r@TStar{rkind=PRow}      = parens $ prettyPosRow r\n    pretty r@TStar{rkind=KRow}      = parens $ prettyKwdRow r\n    pretty r@TNil{rkind=PRow}       = parens empty\n    pretty r@TNil{rkind=KRow}       = parens empty\n    pretty (TFX _ fx)               = pretty fx\n\nprettyFXnoPure (TFX _ FXPure)       = empty\nprettyFXnoPure t                    = pretty t\n\ninstance Pretty FX where\n    pretty FXProc                   = text \"proc\"\n    pretty FXMut                    = text \"mut\"\n    pretty FXPure                   = text \"pure\"\n    pretty FXAction                 = text \"action\"\n\ninstance Pretty Kind where\n    pretty KType                    = text \"type\"\n    pretty KProto                   = text \"protocol\"\n    pretty KFX                      = text \"effect\"\n    pretty PRow                     = text \"positional row\"\n    pretty KRow                     = text \"keyword row\"\n    pretty (KFun ks k)              = brackets (commaSep pretty ks) <+> text \"=>\" <+> pretty k\n    pretty (KUni i)                 = text \"K_\" <> pretty i\n    pretty KWild                    = text \"_\"\n"
  },
  {
    "path": "compiler/lib/src/Acton/QuickType.hs",
    "content": "-- Copyright (C) 2019-2021 Data Ductus AB\n--\n-- Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:\n--\n-- 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.\n--\n-- 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.\n--\n-- 3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission.\n--\n-- THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS \"AS IS\" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n--\n\nmodule Acton.QuickType where\n\nimport Acton.Syntax\nimport Acton.Names\nimport Acton.Subst\nimport Acton.Env\nimport Acton.NameInfo\nimport Acton.Builtin\nimport Acton.Prim\nimport Utils\n\n\nclass QType a where\n    qType                           :: EnvF x -> Checker -> a -> (Type, Type, a)\n    qMatch                          :: Checker -> Type -> Type -> a -> a\n\ntype Checker                        = Type -> Type -> Expr -> Expr\n\naccept                              :: Checker\naccept t t' e                       = e\n\ntypecast                            :: Checker\ntypecast t t' e\n  | t == t'                         = e\n  | otherwise                       = eCAST t t' e\n\n\ntypeOf env x                        = t\n  where (t, fx, x')                 = qType env accept x\n\nfxOf env x                          = fx\n  where (t, fx, x')                 = qType env accept x\n\ntypeInstOf env ts e                 = t\n  where (t, fx, e')                 = qInst env accept ts e\n\nschemaOf env e                      = (sc, dec)\n  where (sc, fx, dec, e')           = qSchema env accept e\n\nclosedType                          :: EnvF x -> Expr -> Bool\nclosedType env (Var _ n)            = isClosed $ findQName n env\nclosedType env (Dot _ (Var _ x) n)\n  | NClass q _ _ _ <- findQName x env = closedAttr env (TC x (map tVar $ qbound q)) n\nclosedType env (Dot _ e n)          = case typeOf env e of\n                                        TCon _ c -> closedAttr env c n\n                                        TVar _ v  -> closedAttr env (findTVBound env v) n\n                                        TTuple _ p k -> n `notElem` valueKWs\n                                        t -> error (\"t = \"++prstr t)\nclosedType env (TApp _ e _)         = closedType env e\nclosedType env (Async _ e)          = closedType env e\nclosedType env _                    = True\n\nisUnboxedExpr (UnBox _ _)           = True\nisUnboxedExpr (Var _ (NoQ (Internal BoxPass _ _)))\n                                    = True\nisUnboxedExpr (BinOp _ l _ r)       = isUnboxedExpr l || isUnboxedExpr r\nisUnboxedExpr _                     = False\n\n\nqSchema                             :: EnvF x -> Checker -> Expr -> (TSchema, Type, Maybe Deco, Expr)\nqSchema env f e@(Var _ n)           = case findQName n env of\n                                        NVar t ->\n                                            (monotype t, fxPure, Nothing, e)\n                                        NSVar t ->\n                                            (monotype t, fxPure, Nothing, e)\n                                        NDef sc dec _ ->\n                                            (sc, fxPure, Just dec, e)\n                                        NSig sc dec _ ->\n                                            (sc, fxPure, Just dec, e)\n                                        NClass q _ _ _ ->\n                                            let tc = TC (unalias env n) (map tVar $ qbound q)\n                                                (TSchema _ q' t, _) = findAttr' env tc initKW\n                                                t' = if restype t == tR then t else t{ restype = tSelf }\n                                            in (tSchema (q++q') $ vsubst [(tvSelf,tCon tc)] t', fxPure, Just NoDec, e)\n                                        NAct q p k _ _ ->\n                                            (tSchema q (tFun fxProc p k (tCon0 n q)), fxPure, Just NoDec, e)\n                                        i -> error (\"### qSchema Var unexpected \" ++ prstr (noq n,i))\nqSchema env f e@(Dot _ (Var _ x) n)\n  | NClass q _ _ _ <- info          = let tc = TC x (map tVar $ qbound q)\n                                          (TSchema _ q' t, mbdec) = findAttr' env tc n\n                                      in (tSchema (q++q') $ vsubst [(tvSelf,tCon tc)] (addSelf t mbdec), fxPure, mbdec, e)\n  where info                        = findQName x env\nqSchema env f e0@(Dot l e n)        = case t of\n                                        TCon _ c -> addE e' $ findAttr' env c n\n                                        TTuple _ p k\n                                          | n `elem` valueKWs -> addE e' $ findAttr' env cValue n\n                                          | otherwise -> addE e' $ (monotype $ pick n k, Nothing)\n                                        TVar _ v  -> addE e' $ findAttr' env tc n\n                                           where tc = findTVBound env v\n                                        t -> error (\"### qSchema Dot unexpected \" ++ prstr e0 ++ \"  ::  \" ++ prstr t)\n  where (t, fx, e')                 = qType env f e\n        addE e1 (sc, dec)           = (vsubst [(tvSelf,t)] sc, fx, dec, Dot l e1 n)\n        pick n (TRow l k x t r)     = if x == n then t else pick n r\n        pick n (TStar l k r)\n          | n == attrKW             = tTupleK r\n        pick n (TNil l k)\n          | n == attrKW             = tTupleK (tNil KRow)\n        pick n _                    = error (\"### qSchema Dot \" ++ prstr n ++ \" on \" ++ prstr e0 ++ \"  ::  \"  ++ prstr t)\nqSchema env f e                     = (monotype t, fx, Nothing, e')\n  where (t, fx, e')                 = qType env f e\n\nqInst                               :: EnvF x -> Checker -> [Type] -> Expr -> (Type, Type, Expr)\nqInst env f [] (TApp _ e ts)        = qInst env f ts e\nqInst env f ts e                    = case qSchema env f e of\n                                        (TSchema _ q t, fx, _, e') | length q == length ts -> (t', fx, tApp e' ts)\n                                           where t' = vsubst (qbound q `zip` ts) t\n                                        (sc, _, _, _) -> error (\"###### qInst [\" ++ prstrs ts ++ \"] \" ++ prstr e ++ \" is \" ++ prstr sc)\n\ninstance QType Expr where\n    qType env f e@Var{}             = qInst env f [] e\n    qType env f e@Dot{}             = qInst env f [] e\n    qType env f (TApp _ e ts)       = qInst env f ts e\n    qType env f e@(Int _ _ _)       = (tInt, fxPure, e)\n    qType env f e@(Float _ _ s)     = (tFloat, fxPure, e)\n    qType env f e@(Bool _ _)        = (tBool, fxPure, e)\n    qType env f e@(None _)          = (tNone, fxPure, e)\n    qType env f e@(Strings _ _)     = (tStr, fxPure, e)\n    qType env f e@(BStrings _ _)    = (tBytes, fxPure, e)\n--  qType env f (Imaginary _ i s)   = undefined\n--  qType env f (NotImplemented _)  = undefined\n--  qType env f (Ellipsis _)        = undefined\n    qType env f e0@(Call l e ps ks)\n      | TFun{} <- t                 = --trace (\"## qType Call \" ++ prstr e0 ++ \", t = \" ++ prstr t) $\n                                      (restype t, fx', Call l e' (qMatch f p (posrow t) ps') (qMatch f k (kwdrow t) ks'))\n      | otherwise                   = error (\"###### qType Fun \" ++ prstr e ++ \" : \" ++ prstr t)\n      where (t, fx, e')             = qType env f e\n            (p, fxp, ps')           = qType env f ps\n            (k, fxk, ks')           = qType env f ks\n            fx'                     = upbound env [fx,fxp,fxk,effect t]\n    qType env f (Let l ss e)        = (t, fx, Let l ss e')\n       where te                     = envOf ss\n             (t,fx,e')              = qType (define te env) f e\n    qType env f (Async l e)         = case t of\n                                        TFun _ (TFX _ FXAction) p k t' -> (tFun fxProc p k (tMsg t'), fx, Async l e')\n      where (t, fx, e')             = qType env f e\n    qType env f (Await l e)         = case t of\n                                        TCon _ (TC c [t]) | c == qnMsg -> (t, fxProc, Await l e')\n      where (t, fx, e')             = qType env f e\n    qType env f e@(BinOp l e1 op e2)\n       | isUnboxedExpr e            = (t, fx, BinOp l e1' op e2')\n       | otherwise                  = (t, fx, BinOp l (qMatch f t1 t e1') op (qMatch f t2 t e2'))\n      where (t1, fx1, e1')          = qType env f e1\n            (t2, fx2, e2')          = qType env f e2\n            t                       = upbound env [t1,t2]\n            fx                      = upbound env [fx1,fx2]\n    qType env f (CompOp l e1 [OpArg op e2])\n                                    = (tBool, fx, CompOp l (qMatch f t1 t e1') [OpArg op (qMatch f t2 t e2')])\n      where (t1, fx1, e1')          = qType env f e1\n            (t2, fx2, e2')          = qType env f e2\n            t                       = upbound env [t1,t2]\n            fx                      = upbound env [fx1,fx2]\n    qType env f (UnOp l Not e)      = (tBool, fx, UnOp l Not (qMatch f t tBool e'))\n      where (t, fx, e')             = qType env f e\n    qType env f (Cond l e1 e e2)    = (t', fx', Cond l (qMatch f t1 t' e1') (qMatch f t tBool e') (qMatch f t2 t' e2'))\n      where (t1, fx1, e1')          = qType env f e1\n            (t, fx, e')             = qType env f e\n            (t2, fx2, e2')          = qType env f e2\n            t'                      = upbound env [t1,t2]\n            fx'                     = upbound env [fx1,fx,fx2]\n    qType env f (IsInstance l e c)  = (tBool, fx, IsInstance l e' c)\n      where (t, fx, e')             = qType env f e\n    qType env f (DotI l e i)        = case t of\n                                        TTuple _ p _ -> (pick i p, fx, DotI l e' i)\n      where (t, fx, e')             = qType env f e\n            pick i (TRow _ _ _ t' p) = if i == 0 then t' else pick (i-1) p\n    qType env f (RestI l e i)       = case t of\n                                        TTuple _ p _ -> (TTuple NoLoc (pick i p) kwdNil, fx, RestI l e' i)\n      where (t, fx, e')             = qType env f e\n            pick i (TRow l k x t r) = if i == 0 then r else TRow l k x t (pick (i-1) r)\n            pick i (TNil l k)       = TNil l k\n    qType env f (Rest l e n)        = case t of\n                                        TTuple _ p k -> (TTuple NoLoc posNil (pick n k), fx, Rest l e' n)\n      where (t, fx, e')             = qType env f e\n            pick n (TRow l k x t r) = if x == n then r else TRow l k x t (pick n r)\n            pick n (TNil l k)       = TNil l k\n    qType env f (Lambda l p k e fx) = (TFun NoLoc fx (prowOf p) (krowOf k) t, fxPure, Lambda l p k e' fx)\n      where (t, _, e')              = qType env1 f e\n            env1                    = define (envOf k) $ define (envOf p) env\n    qType env f (Tuple l ps ks)     = (TTuple NoLoc p k, fx, Tuple l ps' ks')\n      where (p, fxp, ps')           = qType env f ps\n            (k, fxk, ks')           = qType env f ks\n            fx                      = upbound env [fxp,fxk]\n    qType env f (List l es)         = (tList (upbound env ts), upbound env fxs, List l es')\n      where (ts, fxs, es')          = unzip3 $ map (qType env f) es\n    qType env f (ListComp l e c)    = (tList t, upbound env [fxc,fx], ListComp l e' c')\n      where (_, fxc, c')            = qType env f c\n            (t, fx, e')             = qType env1 f e\n            env1                    = define (envOf c) env\n    qType env f (SetComp l e c)     = (tSet t, upbound env [fxc,fx], SetComp l e' c')\n      where (_, fxc, c')            = qType env f c\n            (t, fx, e')             = qType env1 f e\n            env1                    = define (envOf c) env\n    qType env f (DictComp l a c)    = (tDict tk tv, upbound env [fxc,fx], DictComp l a' c')\n      where (_, fxc, c')            = qType env f c\n            (TTuple _ tk tv, fx, a') = qType env1 f a\n            env1                    = define (envOf c) env\n    qType env f (Dict l as)         = (tDict (upbound env ts1) (upbound env ts2), upbound env (fxk++fxv), Dict l (zipWith Assoc ks vs))\n      where (ts1, fxk, ks)          = unzip3 $ [ qType env f k | Assoc k v <- as ]\n            (ts2, fxv, vs)          = unzip3 $ [ qType env f v | Assoc k v <- as ]\n    qType env f (Set l es)          = (tSet (upbound env ts), upbound env fxs, Set l es')\n      where (ts, fxs, es')          = unzip3 $ map (qType env f) es\n    qType env f (Paren l e)         = (t, fx, Paren l e')\n      where (t, fx, e')             = qType env f e\n    qType env f (Box t e)           = (t, fx, Box t e')\n      where (_, fx, e')             = qType env f e\n    qType env f (UnBox t e)         = (t, fx, UnBox t e')\n      where (_, fx, e')             = qType env f e\n    qType env f e                   = error (\"qType, e = \" ++ show e)\n\n    qMatch f t t' e                 = f t t' e\n\ninstance QType Elem where\n    qType env f (Elem e)            = (t, fx, Elem e')\n      where (t, fx, e')             = qType env f e\n\n    qMatch f t t' (Elem e)          = Elem (qMatch f t t' e)\n\ninstance QType Assoc where\n    qType env f (Assoc ek ev)       = (tTuple tk tv, upbound env [fxk,fxv], Assoc ek' ev')\n      where (tk, fxk, ek')          = qType env f ek\n            (tv, fxv, ev')          = qType env f ev\n\n    qMatch f t t' a                 = a\n\ninstance QType PosArg where\n    qType env f (PosArg e p)        = (posRow t r, upbound env [fx,fxp], PosArg e' p')\n      where (t, fx, e')             = qType env f e\n            (r, fxp, p')            = qType env f p\n    qType env f (PosStar e)         = case t of TTuple _ p _ -> (p, fx, PosStar e')\n      where (t, fx, e')             = qType env f e\n    qType env f PosNil              = (posNil, fxPure, PosNil)\n\n    qMatch f TVar{} r p             = p\n    qMatch f r TVar{} p             = p\n    qMatch f r r' (PosArg e p)\n      | TRow{} <- r,\n        TRow{} <- r'                = PosArg (qMatch f (rtype r) (rtype r') e) (qMatch f (rtail r) (rtail r') p)\n      | otherwise                   = error (\"#### rtail \" ++ prstr r ++ \" < \" ++ prstr r' ++ \" for \" ++ prstr (PosArg e p))\n    qMatch f _ _ PosNil             = PosNil\n\ninstance QType KwdArg where\n    qType env f (KwdArg n e k)      = (kwdRow n t r, upbound env [fx,fxk], KwdArg n e' k')\n      where (t, fx, e')             = qType env f e\n            (r, fxk, k')            = qType env f k\n    qType env f (KwdStar e)         = case t of TTuple _ _ k -> (k, fx, KwdStar e')\n      where (t, fx, e')             = qType env f e\n    qType env f KwdNil              = (kwdNil, fxPure, KwdNil)\n\n    qMatch f TVar{} r k             = k\n    qMatch f r TVar{} k             = k\n    qMatch f r r' (KwdArg n e k)\n      | TRow{} <- r,\n        TRow{} <- r'                = KwdArg n (qMatch f (rtype r) (rtype r') e) (qMatch f (rtail r) (rtail r') k)\n      | otherwise                   = error (\"#### rtail \" ++ prstr r ++ \" < \" ++ prstr r' ++ \" for \" ++ prstr (KwdArg n e k))\n    qMatch f _ _ KwdNil             = KwdNil\n\ninstance QType Pattern where\n    qType env f (PWild l (Just t))  = (t, fxPure, PWild l (Just t))\n    qType env f (PVar l n (Just t)) = (t, fxPure, PVar l n (Just t))\n    qType env f (PVar l n Nothing)  = (typeOf env (eVar n), fxPure, PVar l n Nothing)\n    qType env f (PTuple l ps ks)    = (tTuple (typeOf env ps) (typeOf env ks), fxPure, PTuple l ps ks)\n    qType env f (PList l ps p)      = (tList (typeOf env $ head ps), fxPure, PList l ps p)\n    qType env f (PParen l p)        = (typeOf env p, fxPure, PParen l p)\n\n    qMatch f t t' p                 = p\n\ninstance QType PosPat where\n    qType env f (PosPat p ps)       = (posRow (typeOf env p) (typeOf env ps), fxPure, PosPat p ps)\n    qType env f (PosPatStar p)      = (typeOf env p, fxPure, PosPatStar p)\n    qType env f PosPatNil           = (posNil, fxPure, PosPatNil)\n\n    qMatch f r r' p                 = p\n\ninstance QType KwdPat where\n    qType env f (KwdPat n p ps)     = (kwdRow n (typeOf env p) (typeOf env ps), fxPure, KwdPat n p ps)\n    qType env f (KwdPatStar p)      = (typeOf env p, fxPure, KwdPatStar p)\n    qType env f KwdPatNil           = (kwdNil, fxPure, KwdPatNil)\n\n    qMatch f r r' p                 = p\n\ninstance QType Comp where\n    qType env f (CompFor l p e c)   = (tNone, upbound env [fx,fxc], CompFor l p (qMatch f t (typeOf env p) e') c')\n      where (t, fx, e')             = qType env f e\n            (_, fxc, c')            = qType env1 f c\n            env1                    = define (envOf p) env\n    qType env f (CompIf l e c)      = (tNone, upbound env [fx,fxc], CompIf l e' c')\n      where (t, fx, e')             = qType env f e\n            (_, fxc, c')            = qType env f c\n    qType env f NoComp              = (tNone, fxPure, NoComp)\n\n    qMatch f t t' c                 = c\n\n\n\nclass EnvOf a where\n    envOf                           :: a -> TEnv\n\ninstance (EnvOf a) => EnvOf [a] where\n    envOf                           = concat . map envOf\n\ninstance (EnvOf a) => EnvOf (Maybe a) where\n    envOf                           = maybe [] envOf\n\ninstance EnvOf PosPar where\n    envOf (PosPar n (Just t) _ p)   = (n,NVar t) : envOf p\n    envOf (PosSTAR n (Just t))      = [(n,NVar t)]\n    envOf PosNIL                    = []\n    envOf p                         = error (\"### BAD envOf \" ++ prstr p)\n\ninstance EnvOf KwdPar where\n    envOf (KwdPar n (Just t) _ k)   = (n,NVar t) : envOf k\n    envOf (KwdSTAR n (Just t))      = [(n,NVar t)]\n    envOf KwdNIL                    = []\n\ninstance EnvOf Comp where\n    envOf (CompFor _ p e c)         = envOf p ++ envOf c\n    envOf (CompIf _ e c)            = envOf c\n    envOf NoComp                    = []\n\ninstance EnvOf Pattern where\n    envOf (PWild _ (Just t))        = []\n    envOf (PVar _ n (Just t))       = [(n, NVar t)]\n    envOf (PVar _ n Nothing)        = []\n    envOf (PTuple _ ps ks)          = envOf ps ++ envOf ks\n    envOf (PList _ ps p)            = envOf ps ++ envOf p\n    envOf (PParen _ p)              = envOf p\n\ninstance EnvOf PosPat where\n    envOf (PosPat p ps)             = envOf p ++ envOf ps\n    envOf (PosPatStar p)            = envOf p\n    envOf PosPatNil                 = []\n\ninstance EnvOf KwdPat where\n    envOf (KwdPat n p ps)           = envOf p ++ envOf ps\n    envOf (KwdPatStar p)            = envOf p\n    envOf KwdPatNil                 = []\n\ninstance EnvOf Stmt where\n    envOf (Assign _ ps e)           = envOf ps\n    envOf (VarAssign _ ps e)        = envOf ps\n    envOf (Decl _ ds)               = envOf ds\n    envOf (Signature _ ns sc dec)   = [ (n, NSig sc dec Nothing) | n <- ns ]\n    envOf (If _ [Branch e ss] fin)\n      | isPUSHF e                   = envOf ss ++ envOf fin\n    envOf (If _ bs els)             = commonEnvOf ([ ss | Branch _ ss <- bs ] ++ [els])\n    envOf (Try _ b hs els fin)      = commonEnvOf ([ ss | Handler _ ss <- hs ] ++ [b++els]) ++ envOf fin\n    envOf (With _ items b)          = envOf b `exclude` bound items\n    envOf s                         = []\n\ncommonEnvOf suites\n  | null liveSuites                 = []\n  | otherwise                       = foldl restrict (envOf $ head liveSuites) (map bound $ tail liveSuites)\n  where liveSuites                  = filter fallsthru suites\n\ninstance EnvOf Decl where\n    envOf (Def _ n q p k (Just t) b dec fx doc)\n                                    = [(n, NDef (TSchema NoLoc q $ TFun NoLoc fx (prowOf p) (krowOf k) t) dec doc)]\n    envOf (Class _ n q as ss doc)   = [(n, NClass q (leftpath as) (map dropDefSelf $ envOf ss) doc)]\n\n    envOf (Actor _ n q p k ss doc)  = [(n, NAct q (prowOf p) (krowOf k) (map wrap te) doc)]\n      where te                      = filter (not . isHidden . fst) $ envOf ss `exclude` statevars ss\n            wrap (n, NDef sc dec doc) = (n, NDef (wrapFX sc) dec doc)\n            wrap (n, i)             = (n, i)\n            wrapFX (TSchema l q t)  = TSchema l q (if effect t == fxProc then t{ effect = fxAction } else t)\n\ndropDefSelf (n, NDef (TSchema l q t) dec doc)\n                                    = (n, NDef (TSchema l q (dropSelf t dec)) dec doc)\ndropDefSelf (n, i)                  = (n, i)\n\n--  The following constructs are translated away during type inference:\n--  envOf (Protocol _ n q as ss)    = undefined\n--  envOf (Extension _ n q as ss)   = undefined\n\ninstance EnvOf Except where\n    envOf (ExceptAll _)             = []\n    envOf (Except _ x)              = []\n    envOf (ExceptAs _ x n)          = [(n, NVar $ tCon (TC x []))]\n\ninstance EnvOf WithItem where\n    envOf (WithItem e p)            = envOf p\n\ninstance EnvOf Branch where\n    envOf _                         = []\n\ninstance EnvOf Handler where\n    envOf _                         = []\n\ninstance EnvOf Sliz where\n    envOf _                         = []\n\ninstance EnvOf OpArg where\n    envOf _                         = []\n\ninstance EnvOf Elem where\n    envOf _                         = []\n\ninstance EnvOf Assoc where\n    envOf _                         = []\n\n\nupbound env ts                      = case lubfold env ts of Just u -> u\n\nnvarsOf te                          = [ (n,t) | (n, NVar t) <- te ]\n\nupdatesOf stmts                     = concatMap upd stmts\n  where upd (Assign _ p _)          = concatMap uvars p\n        upd (If _ bs els)           = concat [ updatesOf ss | Branch _ ss <- bs ] ++ updatesOf els\n        upd (While _ _ ss els)      = updatesOf ss ++ updatesOf els\n        upd (Try _ ss hs els fin)   = updatesOf ss ++ concat [ updatesOf ss | Handler _ ss <- hs ] ++ updatesOf els ++ updatesOf fin\n        upd _                       = []\n        uvars (PVar _ v Nothing)    = [v]\n        uvars (PParen _ p)          = uvars p\n        uvars (PTuple _ ps ks)      = uvarsP ps ++ uvarsK ks\n        uvars (PList _ ps mbp)      = concatMap uvars ps ++ maybe [] uvars mbp\n        uvars _                     = []\n        uvarsP (PosPat p r)         = uvars p ++ uvarsP r\n        uvarsP (PosPatStar p)       = uvars p\n        uvarsP (PosPatNil)          = []\n        uvarsK (KwdPat _ k r)       = uvars k ++ uvarsK r\n        uvarsK (KwdPatStar k)       = uvars k\n        uvarsK (KwdPatNil)          = []\n"
  },
  {
    "path": "compiler/lib/src/Acton/Solver.hs",
    "content": "-- Copyright (C) 2019-2021 Data Ductus AB\n--\n-- Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:\n--\n-- 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.\n--\n-- 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.\n--\n-- 3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission.\n--\n-- THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS \"AS IS\" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n--\n\n{-# LANGUAGE MultiParamTypeClasses, FlexibleInstances, FlexibleContexts #-}\nmodule Acton.Solver where\n\nimport Control.Monad\nimport Control.Monad.Except\nimport qualified Data.Map.Strict as Map\nimport Data.Map.Strict (Map)\nimport qualified Control.Exception\nimport Control.DeepSeq\n\nimport Utils\nimport Pretty\nimport Acton.Syntax\nimport Acton.Printer\nimport Acton.Builtin\nimport Acton.Names\nimport Acton.Prim\nimport Acton.NameInfo\nimport Acton.Env\nimport Acton.Subst\nimport Acton.TypeEnv\n\n\nrun_new_solver = False\n\nnewSimplify env te cs                       = simplifyNew env cs\n\noldSimplify env te cs                       = simplify env te cs\n\nnoSimplify env te cs                        = return (cs, [])\n\n\n-- Reduce conservatively and remove entailed constraints\nsimplifyNew                                 :: Env -> Constraints -> TypeM (Constraints,Equations)\nsimplifyNew env cs                          = do css <- groupCs env cs\n                                                 --traceM (\"#### SIMPLIFY NEW \" ++ prstr (length cs))\n                                                 --sequence [ traceM (\"## long:\\n\" ++ render (nest 4 $ vcat $ map pretty cs)) | cs <- css, length cs > 500 ]\n                                                 simplifyGroupsNew env css\n\nsimplifyGroupsNew env []                    = return ([], [])\nsimplifyGroupsNew env (cs:css)              = do --traceM (\"\\n\\n######### simplifyNewGroup\\n\" ++ render (nest 4 $ vcat $ map pretty cs))\n                                                 eq1 <- reduce [] cs `catchError` \\err -> Control.Exception.throw err\n                                                 cs1 <- usubst =<< collectDeferred\n                                                 (cs2,eq2) <- simplifyGroupsNew env css\n                                                 return (cs1++cs2, eq1++eq2)\n\n-- Reduce conservatively and remove entailed constraints\nsimplify                                    :: Env -> TEnv -> Constraints -> TypeM (Constraints,Equations)\nsimplify env te cs                          = do css <- groupCs env cs\n                                                 te <- usubst te\n                                                 --traceM (\"#### SIMPLIFY \" ++ prstr (length cs))\n                                                 --sequence [ traceM (\"## long:\\n\" ++ render (nest 4 $ vcat $ map pretty cs)) | cs <- css, length cs > 500 ]\n                                                 simplifyGroups env te css\n\nsimplifyGroups env te []                    = return ([], [])\nsimplifyGroups env te (cs:css)              = do --traceM (\"\\n\\n######### simplifyGroup\\n\" ++ render (nest 4 $ vcat $ map pretty cs))\n                                                 (cs1,eq1) <- simplify' env te [] cs `catchError` \\err -> Control.Exception.throw err\n                                                 (cs2,eq2) <- simplifyGroups env te css\n                                                 return (cs1++cs2, eq1++eq2)\n\nsimplify'                                   :: Env -> TEnv -> Equations -> Constraints -> TypeM (Constraints,Equations)\nsimplify' env te eq []                      = return ([], eq)\nsimplify' env te eq cs                      = do eq <- reduce eq cs\n                                                 cs <- usubst =<< collectDeferred\n                                                 let len = length cs\n                                                 --when (len > 0) $ traceM (\"## Improving \" ++ show len)\n                                                 --when (len > 0) $ traceM (\"## Improving:\\n\" ++ render (nest 8 $ vcat $ map pretty cs))\n                                                 env <- usubst env      -- Remove....\n                                                 te <- usubst te\n                                                 improve env te eq cs\n\nquicksimp env eq []                         = return ([], eq)\nquicksimp env eq cs                         = do eq1 <- reduce eq cs\n                                                 cs1 <- usubst =<< collectDeferred\n                                                 return (cs1, eq1)\n\ngroupCs env cs                              = do st <- currentState\n                                                 mark 1 cs\n                                                 m <- foldM group Map.empty cs\n                                                 rollbackState st\n                                                 let css = Map.elems m\n                                                     n = length (concat css)\n                                                 --traceM (\"#### Grouped \" ++ show n ++ \" constraints into \" ++ show (map length css) ++ \" groups\")\n                                                 return css\n  where mark n []                           = return n\n        mark n (c : cs)                     = do tvs <- ufree <$> usubst c\n                                                 tvs' <- ufree <$> usubst (map tUni $ attrfree c)\n                                                 sequence [ unify (noinfo 1) (newUnivarToken n) (tUni tv) | tv <- nub (tvs++tvs') ]\n                                                 mark (n+1) cs\n        group m c                           = do tvs <- ufree <$> usubst c\n                                                 let tv = case tvs of [] -> tv0; tv:_ -> tv\n                                                 return $ Map.insertWith (++) tv [c] m\n        attrfree c@(Sel _ _ _ _ n _)        = allConAttrUFree env n\n        attrfree c@(Mut _ _ _ n _)          = allConAttrUFree env n\n        attrfree _                          = []\n        TUni _ tv0                          = newUnivarToken 0\n\n\n----------------------------------------------------------------------------------------------------------------------\n-- solve\n----------------------------------------------------------------------------------------------------------------------\n-- ###################################################################################################################\n\ndata Newrank                                = R_red\n                                            | R_pos TUni [Type]\n                                            | R_low TUni [Type]\n                                            | R_neg TUni [Type]\n                                            | R_amb TUni [Type]\n                                            | R_var TUni TUni\n                                            | R_ret\n                                            deriving (Show)\n\nweight R_red{}                              = 0\nweight R_pos{}                              = 1\nweight R_low{}                              = 2\nweight R_neg{}                              = 3\nweight R_amb{}                              = 4\nweight R_var{}                              = 5\nweight R_ret{}                              = 6\n\ninstance Eq Newrank where\n    a == b                                  = weight a == weight b\n\ninstance Ord Newrank where\n    a <= b                                  = weight a <= weight b\n\n\ninfo0 = noinfo 0\n\n\nnewrank pol (Sub info env _ t1 t2)          = newrank pol (Cast info env t1 t2)\nnewrank pol (Cast _ env (TUni _ v) (TUni _ v'))\n                                            = R_var v v'\nnewrank pol (Cast _ env t (TUni _ v))\n  | pos && not neg                          = R_pos v alts\n  | otherwise                               = R_low v alts\n  where (pos, neg)                          = (v `elem` fst pol, v `elem` snd pol)\n        alts                                = reverse $ allAbove (limitQuant v env) t\nnewrank pol (Cast _ env (TUni _ v) t)\n  | TOpt _ (TUni _ v') <- t                 = R_var v v'\n  | neg && pos                              = R_ret\n  | neg                                     = R_neg v alts\n  | otherwise                               = R_amb v alts\n  where (pos, neg)                          = (v `elem` fst pol, v `elem` snd pol)\n        alts                                = allBelow (limitQuant v env) t\nnewrank pol (Proto _ env _ (TUni _ v) p)                                                        -- Proto behaves as an upper type bound\n  | neg && pos                              = R_ret\n--  | neg                                     = R_neg v alts                                    -- Later, when protos have become proper types\n  | neg || pos                              = R_ret\n  | otherwise                               = R_amb v alts\n  where (pos, neg)                          = (v `elem` fst pol, v `elem` snd pol)\n        alts                                = allBelowProto (limitQuant v env) p\nnewrank pol (Sel _ env _ (TUni _ v) n _)                                                        -- Sel behaves as an upper type/proto bound\n  | neg && pos                              = R_amb v alts\n  | neg                                     = R_neg v alts\n  | otherwise                               = R_amb v alts\n  where (pos, neg)                          = (v `elem` fst pol, v `elem` snd pol)\n        alts                                = allClassAttr env_ n ++ allProtoAttr env_ n ++ [wildTuple]\n        env_                                = limitQuant v env\nnewrank pol (Mut _ env (TUni _ v) n _)      = R_amb v alts                                      -- Mut behaves as an upper type bound\n  where alts                                = allClassAttr (limitQuant v env) n\nnewrank pol (Seal _ env (TUni _ v))\n  | uvkind v == KFX                         = R_amb v [fxAction, fxPure]\nnewrank pol c                               = R_red\n\n\nnewsolve                                    :: Env -> TEnv -> Equations -> Constraints -> TypeM (Equations, Constraints)\nnewsolve env te eq cs                       = do te <- usubst te\n                                                 cs <- usubst cs\n                                                 newsolve' env te eq cs\n\nnewsolve' env te eq []                      = return (eq, [])                                   -- done\nnewsolve' env te eq cs                      = do let pol = closePolVars (polvars te) cs\n                                                 st <- currentState\n                                                 case head $ sort $ map (newrank pol) cs of\n                                                    R_red -> do                                 -- reducible\n                                                        eq <- reduce eq cs\n                                                        cs <- collectDeferred\n                                                        newsolve env te eq cs\n                                                    R_pos v ts ->                               -- positive lower con\n                                                        newtry env st te eq cs v ts\n                                                    R_low v ts ->                               -- must-solve lower con\n                                                        newtry env st te eq cs v ts\n                                                    R_neg v ts ->                               -- negative upper con\n                                                        newtry env st te eq cs v ts\n                                                    R_amb v ts ->                               -- must-solve upper con\n                                                        newtry env st te eq cs v ts\n                                                    R_var v v' -> do                            -- var-var\n                                                        unify info0 (tUni v) (tUni v')\n                                                        newsolve env te eq cs\n                                                    R_ret -> do                                 -- acceptable upper con \n                                                        (eq,cs) <- validate env eq cs\n                                                        coalesce env eq cs\n\nnewtry env st te eq cs v []                 = noSolve0 env (Just $ tUni v) [] cs\nnewtry env st te eq cs v (t:ts)             = (unify info0 (tUni v) t >> newsolve env te eq cs)\n                                              `catchError`\n                                              const (rollbackState st >> newtry env st te eq cs v ts)\n\nvalidate env eq cs                          = do st <- currentState\n                                                 _ <- newsolve env [] eq cs                      -- check that a solution exists\n                                                 cs' <- usubst cs\n                                                 let us = nub $ concat [ ufree c | (c,c') <- cs `zip` cs', not $ null $ vfree c' ]\n                                                 ts <- usubst (map tUni us)                      -- collect scope dependent substitution\n                                                 let s = [ (u,t) | (u,t) <- us `zip` ts, t /= tUni u ]\n                                                 rollbackState st\n                                                 uextend s                                      -- apply to old state\n                                                 eq <- reduce eq cs\n                                                 cs <- collectDeferred\n                                                 return (eq, cs)\n\ncoalesce env eq cs                          = red env eq [] cs\n  where red env eq cs []                    = return (eq, cs)\n        red env eq cs (Cast _ _ (TUni _ v) t : cs')\n          | t' : _ <- hits                  = do eq' <- reduce eq [Cast info0 env t' t]\n                                                 red env eq' cs cs'\n          where hits                        = [ t' | Cast _ env' (TUni _ v') t' <- cs++cs', v'==v, headcast env t' t ]\n        red env eq cs (Sub _ _ w (TUni _ v) t : cs')\n          | (w',t') : _ <- hits             = do w2 <- newWitness\n                                                 let eq' = mkEqn env w (wFun (tUni v) t) (compWit (tUni v) w2 w')\n                                                 eq <- reduce (eq':eq) [Sub info0 env w2 t' t]\n                                                 red env eq cs cs'\n          where hits                        = [ (w',t') | Sub _ _ w' (TUni _ v') t' <- cs++cs', v'==v, headcast env t' t ]\n        red env eq cs (Proto _ _ w (TUni _ v) p : cs')\n          | (w',p') : _ <- hits             = do w2 <- newWitness\n                                                 let eq' = mkEqn env w (proto2type (tUni v) p) (compWit (tUni v) w2 w')\n                                                 eq <- reduce (eq':eq) [Sub info0 env w2 (tCon p') (tCon p)]\n                                                 red env eq cs cs'\n          where hits                        = [ (w',p') | Proto _ _ w' (TUni _ v') p' <- cs++cs', v'==v, headcast env (tCon p') (tCon p) ]\n        red env eq cs (c : cs')             = red env eq (c:cs) cs'\n\n\n-- ###################################################################################################################\n\ndata Rank                                   = RRed { cstr :: Constraint }\n                                            | RSealed { tgt :: TUni }\n                                            | RTry { tgt :: TUni, alts :: [Type], rev :: Bool }\n                                            | RVar { tgt :: TUni, alts :: [Type] }\n                                            | RSkip\n                                            deriving (Show)\n\ninstance Eq Rank where\n    RRed _      == RRed _                   = True\n    RSealed v1  == RSealed v2               = v1 == v2\n    RTry v1 _ _ == RTry v2 _ _              = v1 == v2\n    RVar v1 _   == RVar v2 _                = v1 == v2\n    RSkip       == RSkip                    = True\n    _           == _                        = False\n\ninstance Pretty Rank where\n    pretty (RRed c)                         = text \"<reduce>\" <+> pretty c\n    pretty (RSealed v)                      = pretty v <+> text \"sealed\"\n    pretty (RTry v ts rev)                  = pretty v <+> braces (commaSep pretty ts) Pretty.<> (if rev then char '\\'' else empty)\n    pretty (RVar v ts)                      = pretty v <+> char '~' <+> commaSep pretty ts\n    pretty RSkip                            = text \"<skip>\"\n\nsolve                                       :: Env -> (Constraint -> Bool) ->\n                                               TEnv -> Equations -> Constraints -> TypeM (Constraints,Equations)\nsolve env select te eq cs                   = do css <- groupCs env cs\n                                                 te <- usubst te\n                                                 solveGroups env select te eq css\n\nsolveGroups env select te eq []             = return ([], eq)\nsolveGroups env select te eq (cs:css)       = do --traceM (\"\\n\\n######### solveGroup\\n\" ++ render (nest 4 $ vcat $ map pretty cs))\n                                                 --traceM (\"  ### te:\\n\" ++ render (nest 4 $ vcat $ map pretty te))\n                                                 (cs1,eq1) <- solve' env select [] te eq cs `catchError` \\err -> Control.Exception.throw err\n                                                 (cs2,eq2) <- solveGroups env select te eq1 css\n                                                 return (cs1++cs2, eq2)\n\nsolve' env select hist te eq cs\n  | not $ null vargoals                     = do --traceM (unlines [ \"### var goal \" ++ prstr t ++ \" ~ \" ++ prstrs alts | RVar t alts <- vargoals ])\n                                                 --traceM (\"### var goals: \" ++ show (sum [ length alts | RVar t alts <- vargoals ]))\n                                                 sequence [ unify (noinfo 2) (tUni v) t | RVar v alts <- vargoals, t <- alts ]\n                                                 proceed hist eq cs\n  | any not keep_evidence                   = noSolve0 env Nothing [] keep_cs\n  | null solve_cs || null goals             = return (keep_cs, eq)\n  | otherwise                               = do st <- currentState\n                                                 --traceM (\"## keep:\\n\" ++ render (nest 8 $ vcat $ map pretty keep_cs))\n                                                 --traceM (\"## solve:\\n\" ++ render (nest 8 $ vcat $ map pretty solve_cs))\n                                                 --traceM (\"## ranks:\\n\" ++ render (nest 8 $ vcat $ map pretty rnks))\n                                                 --traceM (\"## optvs: \" ++ prstrs optvs)\n                                                 --traceM (\"## posvs: \" ++ prstrs posvs)\n                                                 --traceM (\"## negvs: \" ++ prstrs negvs)\n                                                 case head goals of\n                                                    RRed c -> do\n                                                        --traceM (\"### reduce \" ++ prstr c)\n                                                        proceed hist eq cs\n                                                    RSealed v -> do\n                                                        --traceM (\"### try goal \" ++ prstr v ++ \", candidates: \" ++ prstrs [fxAction, fxPure])\n                                                        tryAlts st v [fxAction, fxPure]\n                                                    RTry v alts r -> do\n                                                        --traceM (\"### try goal \" ++ prstr v ++ \", candidates: \" ++ prstrs alts ++ if r then \" (rev)\" else \"\")\n                                                        tryAlts st v alts\n                                                    RVar v alts -> do\n                                                        --traceM (\"### var goal \" ++ prstr v ++ \", unifying with \" ++ prstrs alts)\n                                                        unifyM (noinfo 3) alts (repeat $ tUni v) >> proceed hist eq cs\n                                                    RSkip ->\n                                                        return (keep_cs, eq)\n\n  where (solve_cs, keep_cs)                 = partition select cs\n        keep_evidence                       = [ hasWitness env t p | Proto _ env _ t p <- keep_cs ]\n\n        (vargoals, goals)                   = span isVar $ sortOn deco $ condense env rnks\n\n        rnks                                = map (rank env) solve_cs\n\n        tryAlts st tv []                    = do --traceM (\"### FAIL \" ++ prstr tv ++ \":\\n\" ++ render (nest 4 $ vcat $ map pretty cs))\n                                                 let ts = map (\\n -> tCon (TC (noQ ('t':show n)) [])) [0..]\n                                                     vs = filter (\\v -> length (filter (\\c -> v `elem` ufree c) cs) > 1) (nub (ufree cs))\n                                                     cs' = if length cs == 1 then cs else filter (not . useless vs) cs\n                                                     vs' = filter (\\v -> length (filter (\\c -> v `elem` ufree c) cs') > 1) (nub (ufree cs'))\n                                                 sequence [ usubstitute uv t | (uv,t) <- vs' `zip` ts ]\n                                                 cs' <- usubst cs'\n                                                 noSolve0 env (Just $ tUni tv) (take (length vs') ts) cs'\n        tryAlts st tv (t:ts)                = tryAlt tv t `catchError` const (\n                                                    do --traceM (\"=== ROLLBACK \" ++ prstr tv)\n                                                       rollbackState st >> tryAlts st tv ts)\n        tryAlt v (TCon _ c)\n          | isProto env (tcname c)          = do p <- instwildcon env c\n                                                 w <- newWitness\n                                                 --traceM (\"  # trying \" ++ prstr v ++ \" (\" ++ prstr p ++ \")\")\n                                                 proceed hist eq (Proto (noinfo 4) env w (tUni v) p : cs)\n        tryAlt v (TTuple _ _ _)\n          | not $ null attrs                = do t <- instwild env KType (tTupleK $ foldr (\\n -> kwdRow n tWild) tWild attrs)\n                                                 --traceM (\"  # trying tuple \" ++ prstr v ++ \" = \" ++ prstr t)\n                                                 unify (noinfo 5) (tUni v) t\n                                                 proceed (t:hist) eq cs\n          where selsOf cs                   = sortBy (\\a b -> compare (nstr a) (nstr b)) $ nub [ n | Sel _ _ _ (TUni _ v') n _ <- cs, v' == v ]\n                attrs                       = nub $ selsOf solve_cs \\\\ valueKWs\n        tryAlt v t\n          | uvkind v == KFX                 = do t <- instwild env (uvkind v) t\n                                                 --traceM (\"  # TRYING \" ++ prstr v ++ \" = \" ++ prstr t)\n                                                 unify (noinfo 5) (tUni v) t\n                                                 (cs,eq) <- quicksimp env eq cs\n                                                 hist <- usubst hist\n                                                 te <- usubst te\n                                                 solve' env select hist te eq cs\n        tryAlt v t                          = do t <- instwild env (uvkind v) t\n                                                 --traceM (\"  # trying \" ++ prstr v ++ \" = \" ++ prstr t)\n                                                 unify (noinfo 5) (tUni v) t\n                                                 proceed (t:hist) eq cs\n        proceed hist eq cs                  = do te <- usubst te\n                                                 (cs,eq) <- simplify' env te eq cs\n                                                 te <- usubst te\n                                                 hist <- usubst hist\n                                                 solve' env select hist te eq cs\n\n        condense env rs                     = map cond (group rs)\n          where cond (RRed c : rs)          = RRed c\n                cond (RSealed v : rs)       = RSealed v\n                cond (RTry v as r : rs)     = RTry v (if rev' then subrev ts' else ts') rev'\n                  where ts                  = foldr intersect as $ map alts rs\n                        ts'                 = if v `elem` optvs then ts \\\\ [tOpt tWild] else ts\n--                        rev'                = (or $ r : map rev rs) || v `elem` posvs       -- (new, matches new solver but picks bad order for lower None)\n                        rev'                = (and $ r : map rev rs) || v `elem` posvs        -- (old, incorrect in general, but avoids the None problem)\n                cond (RVar v as : rs)       = RVar v (foldr union as $ map alts rs)\n                cond (RSkip : rs)           = RSkip\n                cond rs                     = error (\"### condense \" ++ show rs)\n\n                subrev []                   = []\n                subrev (t:ts)               = subrev ts1 ++ t : subrev ts2\n                  where (ts1,ts2)           = partition (\\t' -> castable' t' t) ts\n\n                -- Interim: the env above is a simplification, it won't necessarily contain all TVars\n                castable' t'@TVar{} t       = True      -- But a TVar is less than any of its bounds anyway\n                castable' t' t@TVar{}       = False     -- And vice versa\n                castable' t' t              = castable env t' t\n\n                group []                    = []\n                group (r:rs)                = (r : rs1) : group rs2\n                  where (rs1,rs2)           = partition (==r) rs\n\n        optvs                               = optvars hist\n        embvs                               = embvars cs\n        univs                               = univars cs\n        (posvs, negvs)                      = closePolVars (polvars te) cs\n\n        isVar RVar{}                        = True\n        isVar _                             = False\n\n\n        deco (RRed cs)                      = (0, 0, 0, 0)\n        deco (RSealed v)                    = (2, 0, 0, 0)\n        deco (RTry v as r)                  = (w, length as, length $ filter (==v) embvs, length $ filter (==v) univs)\n          where w | uvkind v == KFX         =  5    -- effect search, last to be explored\n                  | [TTuple{}] <- as        =  4    -- default selection solution, deferred search\n                  | otherwise               =  3    -- types and rows, normal search\n        deco (RVar v as)                    = (6, length as, 0, 0)\n        deco (RSkip)                        = (7, 0, 0, 0)\n\n\n-- subrev [int,Pt,float,CPt,C3Pt]           = [] ++ int : subrev [Pt,float,CPt,C3Pt]\n--                                          = int : subrev [CPt,C3Pt] ++ Pt : subrev [float]\n--                                          = int : [C3Pt] ++ CPt ++ subrev [] ++ Pt : [] ++ float : subrev []\n--                                          = int : C3Pt : CPt : Pt : float\n\nrank                                        :: Env -> Constraint -> Rank\nrank _ (Sub info env _ t1 t2)               = rank env (Cast info env t1 t2)\n\nrank _ (Cast _ env (TUni _ v) t2@TUni{})    = RVar v [t2]\nrank _ (Cast _ env (TUni _ v) t2)\n  | TOpt _ t2@TUni{} <- t2                  = RVar v [t2]\n  | otherwise                               = RTry v (allBelow (limitQuant v env) t2) False\nrank _ (Cast _ env t1 (TUni _ v))           = RTry v (allAbove (limitQuant v env) t1) True\n\nrank _ (Proto _ env _ (TUni _ v) p)         = RTry v ts False\n  where ts                                  = allBelowProto (limitQuant v env) p\n\nrank _ (Sel _ env _ (TUni _ v) n _)         = RTry v (allClassAttr env_ n ++ allProtoAttr env_ n ++ [wildTuple]) False\n  where env_                                = limitQuant v env\nrank _ (Mut _ env (TUni _ v) n _)           = RTry v (allClassAttr (limitQuant v env) n) False\n\nrank _ (Seal _ env (TUni _ v))\n  | uvkind v == KFX                         = RSealed v\n  | otherwise                               = RSkip\n\nrank _ c                                    = RRed c\n\nwildTuple                                   = tTuple tWild tWild\n\n\n-------------------------------------------------------------------------------------------------------------------------\n\nclass OptVars a where\n    optvars                             :: a -> [TUni]\n\ninstance (OptVars a) => OptVars [a] where\n    optvars                             = concat . map optvars\n\ninstance OptVars Constraint where\n    optvars (Cast _ _ t1 t2)            = optvars [t1, t2]\n    optvars (Sub _ w _ t1 t2)           = optvars [t1, t2]\n    optvars (Proto _ w _ t p)           = optvars t ++ optvars p\n    optvars (Sel _ w _ t1 n t2)         = optvars [t1, t2]\n    optvars (Mut _ _ t1 n t2)           = optvars [t1, t2]\n    optvars (Seal _ _ t)                = optvars t\n\ninstance OptVars Type where\n    optvars (TOpt _ (TUni _ v))         = [v]\n    optvars (TOpt _ t)                  = optvars t\n    optvars (TCon _ c)                  = optvars c\n    optvars (TFun _ fx p k t)           = optvars [p, k, t]\n    optvars (TTuple _ p k)              = optvars [p, k]\n    optvars (TRow _ _ _ t r)            = optvars [t, r]\n    optvars (TStar _ _ r)               = optvars r\n    optvars _                           = []\n\ninstance OptVars TCon where\n    optvars (TC n ts)                   = optvars ts\n\nembvars cs                              = concat $ map emb cs\n  where emb (Cast _ _ (TUni _ v) (TUni _ v'))\n                                        = []\n        emb (Cast _ _ (TUni _ v) t)     = ufree t\n        emb (Cast _ _ t (TUni _ v))     = ufree t\n        emb (Sub _ _ _ (TUni _ v) (TUni _ v'))\n                                        = []\n        emb (Sub _ _ _ (TUni _ v) t)    = ufree t\n        emb (Sub _ _ _ t (TUni _ v))    = ufree t\n        emb (Proto _ _ _ (TUni _ v) p)  = ufree p\n        emb (Proto _ _ _ (TCon _ c) p)  = ufree c ++ ufree p\n        emb (Sel _ _ _ (TUni _ v) n t)  = ufree t\n        emb (Mut _ _ (TUni _ v) n t)    = ufree t\n        emb _                           = []\n\nunivars cs                              = concat $ map uni cs\n  where uni (Cast _ _ (TUni _ v) (TUni _ v'))\n                                        = [v,v']\n        uni (Sub _ _ _ (TUni _ v) (TUni _ v'))\n                                        = [v,v']\n        uni _                           = []\n\nallAbove env (TCon _ tc)            = tOpt tWild : map tCon tcons\n  where n                           = tcname tc\n        tcons                       = allAncestors env tc ++ [schematic' tc]\nallAbove env (TVar _ tv)            = allAbove env (tCon tc) ++ [tVar tv]\n  where tc                          = findTVBound env tv\nallAbove env (TOpt _ t)             = [tOpt tWild]\nallAbove env (TNone _)              = [tOpt tWild, tNone]\nallAbove env (TFun _ _ _ _ _)       = [tOpt tWild, tFun tWild tWild tWild tWild]\nallAbove env (TTuple _ _ _)         = [tOpt tWild, tTuple tWild tWild]\nallAbove env (TFX _ FXProc)         = [fxProc]\nallAbove env (TFX _ FXMut)          = [fxProc, fxMut]\nallAbove env (TFX _ FXPure)         = [fxProc, fxMut, fxPure]\nallAbove env (TFX _ FXAction)       = [fxProc, fxAction]\n\nallBelow env (TCon _ tc)            = map tCon tcons ++ map tVar tvars\n  where tcons                       = schematic' tc : allDescendants env tc\n        tvars                       = tvarDescendants env tcons\nallBelow env (TVar _ tv)            = [tVar tv]\nallBelow env (TOpt _ t)             = tOpt tWild : allBelow env t ++ [tNone]\nallBelow env (TNone _)              = [tNone]\nallBelow env (TFun _ _ _ _ _)       = [tFun tWild tWild tWild tWild]\nallBelow env (TTuple _ _ _)         = [tTuple tWild tWild]\nallBelow env (TFX _ FXProc)         = [fxProc, fxMut, fxPure, fxAction]\nallBelow env (TFX _ FXMut)          = [fxMut, fxPure]\nallBelow env (TFX _ FXPure)         = [fxPure]\nallBelow env (TFX _ FXAction)       = [fxAction]\n\nallBelowProto env (TC n [t@TFX{},_])\n  | n == primWrappedP               = reverse [ schematic (wtype w) | w <- witsByPName env n, t == (head $ tcargs $ proto w) ]\nallBelowProto env p\n  | p == pIdentity                  = ts ++ [ schematic $ tCon tc | tc <- allActors env ]\n  | p == pEq                        = ts ++ [tOpt tWild]\n  | otherwise                       = ts\n  where ts                          = reverse [ schematic (wtype w) | w <- witsByPName env (tcname p) ] -- includes tvars\n\nallClassAttr env n                  = map tCon tcons ++ map tVar tvars\n  where tcons                       = allConAttr env n\n        tvars                       = tvarDescendants env tcons\n\nallProtoAttr env n                  = map tCon pcons ++ concatMap (allBelowProto env) pcons\n  where pcons                       = allPConAttr env n\n\n\n----------------------------------------------------------------------------------------------------------------------\n-- reduce\n----------------------------------------------------------------------------------------------------------------------\n\nreduce                                      :: Equations -> Constraints -> TypeM Equations\nreduce eq []                              = return eq\nreduce eq (c:cs)                            = do c <- usubst c\n                                                 --traceM (\"   reduce \" ++ prstr c)\n                                                 eq1 <- reduce' eq c\n                                                 reduce eq1 cs\n\nreduce'                                     :: Equations -> Constraint -> TypeM Equations\nreduce' eq c@(Cast i env t1 t2)             = do cast' env i t1 t2\n                                                 return eq\n\nreduce' eq c@(Sub i env w t1 t2)            = sub' env i eq w t1 t2\n\nreduce' eq c@(Proto _ env w TUni{} p)       = do defer [c]; return eq\n\nreduce' eq c@(Proto _ env w t@(TVar _ tv) p)\n  | [wit] <- witSearch                      = do (eq',cs) <- solveProto env wit w t p\n                                                 reduce (eq'++eq) cs\n  | [wit] <- witSearch'                     = do (eq',cs) <- solveProto env wit w (tCon tc) p\n                                                 reduce (eq'++eq) cs\n  where witSearch                           = findWitness env t p\n        tc                                  = findTVBound env tv\n        witSearch'                          = findWitness env (tCon tc) p\n\nreduce' eq c@(Proto _ env w t@(TCon _ tc) p)\n  | tcname p == qnIdentity,\n    isActor env (tcname tc)                 = do let e = eCall (eQVar primIdentityActor) []\n                                                 return (mkEqn env w (proto2type t p) e : eq)\n  | [wit] <- witSearch                      = do (eq',cs) <- solveProto env wit w t p\n                                                 reduce (eq'++eq) cs\n  where witSearch                           = findWitness env t p\n\nreduce' eq c@(Proto _ env w t@(TFX _ tc) p)\n  | [wit] <- witSearch                      = do (eq',cs) <- solveProto env wit w t p\n                                                 reduce (eq'++eq) cs\n  where witSearch                           = findWitness env t p\n\nreduce' eq c@(Proto info env w t@(TOpt _ t') p)\n  | tcname p == qnEq                        = do w' <- newWitness\n                                                 let e = eCall (tApp (eQVar primEqOpt) [t']) [eVar w']\n                                                 reduce (mkEqn env w (proto2type t p) e : eq) [Proto info env w' t' p]\n\nreduce' eq c@(Proto _ env w t@(TNone _) p)\n  | tcname p == qnEq                        = return (mkEqn env w (proto2type t p) (eQVar primWEqNone) : eq)\n\nreduce' eq c@(Sel _ env w TUni{} n _)       = do defer [c]; return eq\n\nreduce' eq c@(Sel _ env w (TVar _ tv) n _)\n  | Just wsc <- attrSearch                  = do (eq',cs) <- solveSelAttr wsc c\n                                                 reduce (eq'++eq) cs\n  | Just p <- protoSearch                   = do (eq',cs) <- solveSelProto p c\n                                                 reduce (eq'++eq) cs\n  | otherwise                               = tyerr n \"Attribute not found\"\n  where attrSearch                          = findTVAttr env tv n\n        protoSearch                         = findProtoByAttr env (NoQ $ tvname tv) n\n\nreduce' eq c@(Sel _ env w (TCon _ tc) n _)\n  | Just wsc <- attrSearch                  = do (eq',cs) <- solveSelAttr wsc c\n                                                 reduce (eq'++eq) cs\n  | Just p <- protoSearch                   = do (eq',cs) <- solveSelProto p c\n                                                 reduce (eq'++eq) cs\n  | otherwise                               = tyerr n \"Attribute not found\"\n  where attrSearch                          = findAttr env tc n\n        protoSearch                         = findProtoByAttr env (tcname tc) n\n\n\nreduce' eq c@(Sel info env w t1@(TTuple _ _ TUni{}) n t2)\n                                            = do defer [c]; return eq\n\nreduce' eq c@(Sel info env w t1@(TTuple _ _ r) n t2)\n  | n `elem` valueKWs                       = do let e = eLambda [(px0,t1)] (eDot (eVar px0) n)\n                                                 return (mkEqn env w (wFun t1 t2) e : eq)\n  | otherwise                               = do --traceM (\"### Sel \" ++ prstr c)\n                                                 select r\n  where select (TRow _ _ n' t r)\n          | n == n'                         = do w' <- newWitness\n                                                 let e = eLambda [(px0,t1)] (eDot (eCallVar w' [eVar px0]) n)\n                                                 reduce (mkEqn env w (wFun t1 t2) e : eq) [Sub info env w' t t2]\n          | otherwise                       = select r\n        select (TStar _ _ r)                = do w' <- newWitness\n                                                 let e = eLambda [(px0,t1)] (eCallVar w' [eDot (eVar px0) attrKW])\n                                                 reduce (mkEqn env w (wFun t1 t2) e : eq) [Sel info env w' (tTupleK r) n t2]\n        select (TNil _ _)                   = kwdNotFound0 env info n\n\n--  lambda (x:(a:int,b:int,**(c:int))): x.b  ==>  lambda x: (b=x.b, a=x.a, KW=x.KW).b            ==>  lambda x: x.b\n--  lambda (x:(a:int,b:int,**(c:int))): x.c  ==>  lambda x: (c=x.KW.x, a=x.a, b=x.b, KW=x.KW).c  ==>  lambda x: x.KW.c\n\nreduce' eq c@(Mut _ env TUni{} n _)         = do defer [c]; return eq\n\nreduce' eq c@(Mut _ env (TVar _ tv) n _)\n  | Just wsc <- attrSearch                  = do solveMutAttr wsc c\n                                                 return eq\n  | otherwise                               = tyerr n \"Attribute not found:\"\n  where attrSearch                          = findTVAttr env tv n\n\nreduce' eq c@(Mut _ env (TCon _ tc) n _)\n  | Just wsc <- attrSearch                  = do solveMutAttr wsc c\n                                                 return eq\n  | otherwise                               = tyerr n \"Attribute not found:\"\n  where attrSearch                          = findAttr env tc n\n\nreduce' eq c@(Seal _ env TUni{})            = do defer [c]; return eq\n\nreduce' eq c@(Seal _ env t@(TVar _ tv))     = return eq\nreduce' eq (Seal info env t@(TCon _ tc))\n--  | castable env t tObject                  = tyerr t \"Leaking actor seal:\"                       -- when we start prohibit sharing of mutable data\n  | otherwise                               = reduce eq (map (Seal info env) $ tcargs tc)\nreduce' eq (Seal _ env t@(TFX _ fx))\n--  | fx `elem` [FXMut,FXProc]                = tyerr t \"Leaking actor seal:\"\n--  | fx `elem` [FXProc]                      = tyerr t \"Leaking actor seal:\"\n  | otherwise                               = return eq\nreduce' eq (Seal info env t)                = reduce eq (map (Seal info env) ts)\n  where ts                                  = leaves t\n\nreduce' eq c                                = noRed0 (scope c) c\n\n\nsolveProto env wit w t p                    = do (cs,t',we) <- instWitness env p wit\n                                                 unify (noinfo 7) t t'\n                                                 return ([mkEqn env w (proto2type t p) we], cs)\n\nsolveSelAttr (wf,sc,d) (Sel info env w t1 n t2)\n  | d == Just Static                        = tyerr n \"A static method cannot be selected by instance:\"\n  | otherwise                               = do (cs,tvs,t) <- instantiate env sc\n                                                 when (negself t) (tyerr n \"A contravariant Self attribute cannot be selected by instance:\")\n                                                 w' <- newWitness\n                                                 let e = eLambda [(px0,t1)] (eCallVar w' [app t (tApp (eDot (wf $ eVar px0) n) tvs) $ protoWitsOf cs])\n                                                     c = Sub (locinfo info 8) env w' (vsubst [(tvSelf,t1)] t) t2\n                                                 return ([mkEqn env w (wFun t1 t2) e], c:cs)\n\n--  e1.__setslice__(sl, e2)\n--  e1.__setslice__(w_Iterable, sl, e2)\n--  w_Sliceable.__setslice__(e1, w_Iterable, sl, e2)\n\n--  w(e1)(sl,e2)                                                        w = lambda x0: lambda p1,p2: w_Sliceable.__setslice__(x0, w1, p1, p2)\n--  (lambda p1,p2: w_Sliceable.__setslice__(x0, w1, p1, p2))(sl,e2)\n--  w_Sliceable.__setslice__(x0, w1, sl, e2)                            w1 = w_Iterable\n--  w_Sliceable.__setslice__(e1, w_Iterable, sl, e2)\n\nsolveSelProto pn c@(Sel info env w t1 n t2) = do p <- instwildcon env pn\n                                                 w' <- newWitness\n                                                 (eq,cs) <- solveSelWit (p, eVar w') c\n                                                 return (eq, Proto info env w' t1 p : cs)\n\nsolveSelWit (p,we) c0@(Sel info env w t1 n t2)\n                                            = do let Just (wf,sc,d) = findAttr env p n\n                                                 (cs,tvs,t) <- instantiate env sc\n                                                 when (negself t) (tyerr n \"A contravariant Self attribute cannot be selected by instance:\")\n                                                 w' <- newWitness\n                                                 let e = eLambda [(px0,t1)] (eCallVar w' [app t (tApp (eDot (wf we) n) tvs) $ eVar px0 : protoWitsOf cs])\n                                                     c = Sub (noinfo 9) env w' (vsubst [(tvSelf,t1)] t) t2\n                                                 return ([mkEqn env w (wFun t1 t2) e], c:cs)\n\nsolveMutAttr (wf,sc,dec) c@(Mut info env t1 n t2)\n                                            = do when (dec /= Just Property) (noMut n)\n                                                 let TSchema _ [] t = sc\n                                                 cast env (locinfo c 10) t2 (vsubst [(tvSelf,t1)] t)\n\n----------------------------------------------------------------------------------------------------------------------\n-- witness lookup\n----------------------------------------------------------------------------------------------------------------------\n\nfindWitness                 :: Env -> Type -> PCon -> [Witness]\nfindWitness env t p         = reverse $ filter (eqhead t . wtype) $ witsByPName env $ tcname p\n  where eqhead (TCon _ c) (TCon _ c')   = tcname c == tcname c'\n        eqhead (TFX _ fx) (TFX _ fx')   = fx == fx'\n        eqhead (TVar _ v) (TVar _ v')   = v == v'\n        eqhead _          _             = False\n\nfindProtoByAttr env cn n    = case filter hasAttr $ witsByTName env cn of\n                                [] -> Nothing\n                                w:_ -> Just $ schematic' $ proto w\n  where hasAttr w           = n `elem` conAttrs env (tcname $ proto w)\n\nhasWitness                  :: Env -> Type -> PCon -> Bool\nhasWitness env TUni{} p     = True\nhasWitness env (TCon _ c) p\n  | isActor env (tcname c),\n    tcname p == qnIdentity  = True\nhasWitness env t p          =  not $ null $ findWitness env t p\n\n\n----------------------------------------------------------------------------------------------------------------------\n-- cast\n----------------------------------------------------------------------------------------------------------------------\n\ncast                                        :: Env -> ErrInfo -> Type -> Type -> TypeM ()\ncast env info t1 t2                         = do t1' <- usubst t1\n                                                 t2' <- usubst t2\n                                                 info' <- usubst info\n                                                 --traceM (\"   cast \" ++ prstr t1' ++ \" < \" ++ prstr t2')\n                                                 cast' env info' t1' t2'\n\ncastM env info ts1 ts2                      = mapM_ (uncurry $ cast env info) (ts1 `zip` ts2)\n\ncast' env _ (TWild _) t2                    = return ()\ncast' env _ t1 (TWild _)                    = return ()\n\ncast' env info (TCon _ c1) (TCon _ c2)\n  | Just (wf,c') <- search                  = if tcname c1 == tcname c2 && tcname c1 `elem` covariant then\n                                                  castM env info (tcargs c') (tcargs c2)\n                                              else                                              -- TODO: infer polarities in general!\n                                                  unifyM info (tcargs c') (tcargs c2)\n  where search                              = findAncestor env c1 (tcname c2)\n\n--                 as declared               as called\n--                 existing                  expected\ncast' env info t1@(TFun _ fx1 p1 k1 t1') t2@(TFun _ fx2 p2 k2 t2')\n  | varTails [p1,p2] || varTails [k1,k2]    = do --traceM (\"## Unifying funs: \" ++ prstr t1 ++ \" ~ \" ++ prstr t2)\n                                                 unify info t1 t2\n                                                 return ()\n  | otherwise                               = do --traceM (\"### Aligning fun \" ++ prstr t1 ++ \" < \" ++ prstr t2)\n                                                 (cs1,ts) <- castpos env info p2 p1\n                                                 cs2 <- castkwd0 env info ts k2 k1\n                                                 t1 <- usubst t1\n                                                 t2 <- usubst t2\n                                                 let (TFun _ fx1 p1 k1 t1', TFun _ fx2 p2 k2 t2') = (t1, t2)\n                                                 reduce [] (Cast info env fx1 fx2 : Cast info env t1' t2' : cs1 ++ cs2)\n                                                 return ()\n\ncast' env info t1@(TTuple _ p1 k1) t2@(TTuple _ p2 k2)\n  | varTails [p1,p2] || varTails [k1,k2]    = do --traceM (\"### Unifying tuples: \" ++ prstr t1 ++ \" ~ \" ++ prstr t2)\n                                                 unify info t1 t2\n                                                 return ()\n  | otherwise                               = do --traceM (\"### Aligning tuple \" ++ prstr t1 ++ \" < \" ++ prstr t2)\n                                                 (cs1,ts) <- castpos env info p1 p2\n                                                 cs2 <- castkwd0 env info ts k1 k2\n                                                 t1 <- usubst t1\n                                                 t2 <- usubst t2\n                                                 let (TTuple _ p1 k1, TTuple _ p2 k2) = (t1, t2)\n                                                 reduce [] (cs1 ++ cs2)\n                                                 return ()\n\ncast' env info (TOpt _ t1@TOpt{}) t2        = cast env info t1 t2\ncast' env info t1 (TOpt _ t2@TOpt{})        = cast env info t1 t2\ncast' env info (TOpt _ t1) (TOpt _ t2)      = cast env info t1 t2\ncast' env info (TUni _ tv) t2@TNone{}       = do usubstitute tv tNone\n                                                 cast env info tNone t2\ncast' env info t1@TOpt{} (TUni _ tv)        = do t2 <- instwild env KType $ tOpt tWild      -- What if tv is in t1???\n                                                 usubstitute tv t2\n                                                 cast env info t1 t2\ncast' env info t1 (TOpt _ t2)\n  | t1 == t2                                = return ()\ncast' env _ (TNone _) (TOpt _ t)            = return ()\ncast' env _ (TNone _) (TNone _)             = return ()\n\ncast' env info t1@(TFX _ fx1) t2@(TFX _ fx2)\n  | castFX fx1 fx2                          = return ()\n  where castFX FXPure   FXPure              = True\n        castFX FXPure   FXMut               = True\n        castFX FXPure   FXProc              = True\n        castFX FXMut    FXMut               = True\n        castFX FXMut    FXProc              = True\n        castFX FXProc   FXProc              = True\n        castFX FXAction FXAction            = True\n        castFX FXAction FXProc              = True\n        castFX _        _                   = False\n\ncast' env info (TUni _ tv) t2@TFun{}\n  | uvkind tv == KType                      = do t1 <- instwild env KType $ tFun tWild tWild tWild tWild\n                                                 usubstitute tv t1\n                                                 cast env info t1 t2\ncast' env info t1@TFun{} (TUni _ tv)                                                                             -- Should remove this, rejects tv = TOpt...\n  | KType == uvkind tv                      = do t2 <- instwild env KType $ tFun tWild tWild tWild tWild\n                                                 usubstitute tv t2\n                                                 cast env info t1 t2\ncast' env info (TUni _ tv) t2@TTuple{}\n  | uvkind tv == KType                      = do t1 <- instwild env KType $ tTuple tWild tWild\n                                                 usubstitute tv t1\n                                                 cast env info t1 t2\n\ncast' env info (TVar _ tv1) (TVar _ tv2)\n  | tv1 == tv2                              = return ()\n\ncast' env info (TUni _ tv1) (TUni _ tv2)\n  | tv1 == tv2                              = return ()\n\ncast' env info t1@(TUni _ tv) t2            = defer [Cast info env t1 t2]\ncast' env info t1 t2@(TUni _ tv)            = defer [Cast info env t1 t2]\n\ncast' env info t1@(TVar _ tv) t2            = cast' env info (tCon tc) t2\n  where tc                                  = findTVBound env tv\n\ncast' env info t1 (TOpt _ t2)               = cast env info t1 t2                -- Only matches when t1 is NOT a univar\n\ncast' env info t1 t2                        = noRed0 env (Cast info env t1 t2)\n\n\ncastpos                                     :: Env -> ErrInfo -> PosRow -> PosRow -> TypeM (Constraints, [Type])\ncastpos env info TUni{}         TUni{}      = error \"INTERNAL ERROR: castpos\"\ncastpos env info (TUni _ tv)     r2\n  | tv `elem` ufree r2                      = conflictingRow tv                     -- use rowTail?\n  | otherwise                               = do r1 <- rowShape env r2\n                                                 --traceM (\" ## castpos L \" ++ prstr tv ++ \" ~ \" ++ prstr r1)\n                                                 usubstitute tv r1\n                                                 castpos env info r1 r2\ncastpos env info r1             (TUni _ tv)\n  | tv `elem` ufree r1                      = conflictingRow tv                     -- use rowTail?\n  | otherwise                               = do r2 <- rowShape env r1\n                                                 --traceM (\" ## castpos R \" ++ prstr r2 ++ \" ~ \" ++ prstr tv)\n                                                 usubstitute tv r2\n                                                 castpos env info r1 r2\n\ncastpos env info (TRow _ _ _ t1 r1) (TRow _ _ _ t2 r2)\n                                            = do --traceM (\" ## castpos A \" ++ prstr t1 ++ \" < \" ++ prstr t2)\n                                                 (cs,ts) <- castpos env info r1 r2\n                                                 return (Cast info env t1 t2 : cs, ts)\ncastpos env info (TStar _ _ r1)     (TStar _ _ r2)\n                                            = do --traceM (\" ## castpos B \" ++ prstr (tTupleP r1) ++ \" < \" ++ prstr (tTupleP r2))\n                                                 return ([Cast info env (tTupleP r1) (tTupleP r2)], [])\ncastpos env info TNil{}             TNil{}\n                                            = do --traceM (\" ## castpos C \")\n                                                 return ([], [])\n\ncastpos env info (TStar _ _ r1)     r2      = do --traceM (\" ## castpos D \" ++ prstr r1 ++ \" ~ \" ++ prstr r2)\n                                                 castpos env info r1 r2\ncastpos env info r1                 (TStar _ _ r2)\n                                            = do --traceM (\" ## castpos E \" ++ prstr r1 ++ \" ~ \" ++ prstr r2)\n                                                 castpos env info r1 r2\n\ncastpos env info r1@TNil{}          r@(TRow _ _ _ t2 r2)\n  | TOpt{} <- t2                            = do --traceM (\" ## castpos F Opt ~ \" ++ prstr t2)\n                                                 castpos env info r1 r2\n  | otherwise                               = do --traceM (\" ## castpos G Nil ~ \" ++ prstr r)\n                                                 posElemNotFound0 env True (Cast info env r1 r) nWild\ncastpos env info (TRow _ _ _ t1 r1) r2@TNil{}\n                                            = do --traceM (\" ## castpos H \" ++ prstr t1)\n                                                 (cs,ts) <- castpos env info r1 r2\n                                                 return (cs, t1 : ts)\n\n\ncastkwd0                                    :: Env -> ErrInfo -> [Type] -> KwdRow -> KwdRow -> TypeM Constraints\ncastkwd0 env info [] r1 r2                  = castkwd env info r1 r2\ncastkwd0 env info (t1:ts) r1 (TRow _ _ n t2 r2)\n                                            = do --traceM (\" ## castkwd0 extra pos for \" ++ prstr n ++ \": \" ++ prstr t1 ++ \" < \" ++ prstr t2)\n                                                 cs <- castkwd0 env info ts r1 r2\n                                                 return (Cast info env t1 t2 : cs)\ncastkwd0 env info ts r1 r2                  = posElemNotFound0 env False (Cast info env r1 r2) nWild\n\ncastkwd                                     :: Env -> ErrInfo -> KwdRow -> KwdRow -> TypeM Constraints\ncastkwd env info r1 (TUni _ tv)             = do unif r1\n                                                 r2 <- usubst (tUni tv)\n                                                 castkwd env info r1 r2\n  where unif TUni{}                         = error \"INTERNAL ERROR: castkwd\"\n        unif (TRow _ _ n t r)\n          | tv `elem` ufree r               = conflictingRow tv                     -- use rowTail?\n          | otherwise                       = do --traceM (\" ## castkwd Row - Var: \" ++ prstr (tRow KRow n t r) ++ \" = \" ++ prstr tv)\n                                                 t2 <- newUnivar env\n                                                 r2 <- tRow KRow n t2 <$> newUnivarOfKind KRow env\n                                                 unify info (tUni tv) r2\n        unif (TStar _ _ r)\n          | tv `elem` ufree r               = conflictingRow tv                     -- use rowTail?\n          | otherwise                       = do --traceM (\" ## castkwd Star - Var: \" ++ prstr (tStar KRow r) ++ \" = \" ++ prstr tv)\n                                                 r2 <- tStar KRow <$> newUnivarOfKind KRow env\n                                                 unify info (tUni tv) r2\n        unif TNil{}                         = do --traceM (\" ## castkwd Nil - Var: \" ++ prstr (tNil KRow) ++ \" = \" ++ prstr tv)\n                                                 r2 <- pure $ tNil KRow\n                                                 unify info (tUni tv) r2\n\ncastkwd env info r1 (TRow _ _ n2 t2 r2)     = do (t1,r1') <- pick r1\n                                                 r2 <- usubst r2\n                                                 cs <- castkwd env info r1' r2\n                                                 return (Cast info env t1 t2 : cs)\n  where pick (TUni _ tv)\n          | tv `elem` ufree r2              = conflictingRow tv                     -- use rowTail?\n          | otherwise                       = do --traceM (\" ## castkwd Var - Row: \" ++ prstr (tUni tv) ++ \" = \" ++ prstr (tRow KRow n2 t2 r2))\n                                                 r1 <- tRow KRow n2 t2 <$> newUnivarOfKind KRow env\n                                                 unify info (tUni tv) r1\n                                                 pick r1\n        pick (TRow _ _ n t r)\n          | n == n2                         = do --traceM (\" ## castkwd Row - Row: \" ++ prstr (tRow KRow n t r) ++ \" = \" ++ prstr (tRow KRow n2 t2 r2))\n                                                 return (t, r)\n          | otherwise                       = do --traceM (\" ## castkwd Row - Row: \" ++ prstr (tRow KRow n t r) ++ \" ≠ \" ++ prstr (tRow KRow n2 t2 r2))\n                                                 kwdNotFound0 env info n2\n        pick (TStar _ _ r)                  = do --traceM (\" ## castkwd Star - Row: \" ++ prstr (tStar KRow r) ++ \" ≠ \" ++ prstr (tRow KRow n2 t2 r2))\n                                                 kwdNotFound0 env info n2\n        pick TNil{}                         = do --traceM (\" ## castkwd None - Row: \" ++ prstr (tNil KRow) ++ \" ≠ \" ++ prstr (tRow KRow n2 t2 r2))\n                                                 kwdNotFound0 env info n2\n\ncastkwd env info r1 (TStar _ _ r2)          = match r1\n  where match (TUni _ tv)\n          | tv `elem` ufree r2              = conflictingRow tv                     -- use rowTail?\n          | otherwise                       = do --traceM (\" ## castkwd Var - Star: \" ++ prstr (tUni tv) ++ \" = \" ++ prstr (tStar KRow r2))\n                                                 r1 <- tStar KRow <$> newUnivarOfKind KRow env\n                                                 unify info (tUni tv) r1\n                                                 match r1\n        match (TRow _ _ n t r)              = do --traceM (\" ## castkwd Row - Star: \" ++ prstr (tRow KRow n t r) ++ \" ≠ \" ++ prstr (tStar KRow r2))\n                                                 kwdUnexpected info n\n        match r1@(TStar _ _ r)\n          | TUni _ v <- r, TUni _ v2 <- r2  = do --traceM (\" ## castkwd StarVar - StarVar: \" ++ prstr (tStar KRow r) ++ \" = \" ++ prstr (tStar KRow r2))\n                                                 unify info r r2\n                                                 return []\n          | TUni _ v <- r                   = do --traceM (\" ## castkwd StarVar - Star: \" ++ prstr (tStar KRow r) ++ \" = \" ++ prstr (tStar KRow r2))\n                                                 castkwd env info r1 r2\n          | otherwise                       = do --traceM (\" ## castkwd Star - Star: \" ++ prstr (tStar KRow r) ++ \" = \" ++ prstr (tStar KRow r2))\n                                                 castkwd env info r r2\n        match r1@TNil{}                     = do --traceM (\" ## castkwd Nil - Star: \" ++ prstr (tNil KRow) ++ \" ≠ \" ++ prstr (tStar KRow r2))\n                                                 noRed0 env (Cast info env r1 r2)\n\ncastkwd env info r1 r2@TNil{}               = term r1\n  where term (TUni _ tv)                    = do --traceM (\" ## castkwd Var - Nil: \" ++ prstr (tUni tv) ++ \" = \" ++ prstr (tNil KRow))\n                                                 r1 <- pure $ tNil KRow\n                                                 unify info (tUni tv) r1\n                                                 term (tNil KRow)\n        term (TNil _ _)                     = do --traceM (\" ## castkwd Nil - Nil: \" ++ prstr (tNil KRow) ++ \" = \" ++ prstr (tNil KRow))\n                                                 return []\n        term (TRow _ _ n t r)               = do --traceM (\" ## castkwd Row - Nil: \" ++ prstr (tRow KRow n t r) ++ \" ≠ \" ++ prstr (tNil KRow))\n                                                 kwdUnexpected info n\n        term (TStar _ _ r)                  = do --traceM (\" ## castkwd Star - Nil: \" ++ prstr (tStar KRow r) ++ \" ≠ \" ++ prstr (tNil KRow))\n                                                 noRed0 env (Cast info env r1 r2)\n\n\n\nsimpInfo env info                           = case info of\n                                                 DeclInfo l1 l2 n sc msg -> DeclInfo l1 l2 n (simp env sc) msg\n                                              --   SelInfo l1 l2 n t msg -> SelInfo l1 l2 n (simp env t) msg\n                                                 _ -> info\n\nnoRed0 env c                                = do c <- uwild <$> usubst c\n                                                 noRed (c{info = simpInfo env (info c)})\n\nnoSolve0 env mbt vs cs                      = do mbt <- uwild <$> usubst mbt\n                                                 cs <- uwild <$> usubst cs\n                                                 noSolve mbt vs $ map (\\c -> c{info = simpInfo env (info c)}) cs\n\nposElemNotFound0 env b c n                  = do c <- uwild <$> usubst c\n                                                 posElemNotFound b (c{info = simpInfo env (info c)}) n\n\nkwdNotFound0 env info n                     = do i <- uwild <$> usubst info\n                                                 kwdNotFound (simpInfo env i) n\n\n\n----------------------------------------------------------------------------------------------------------------------\n-- sub\n----------------------------------------------------------------------------------------------------------------------\n\nsub                                         :: Env -> ErrInfo -> Equations -> Name -> Type -> Type ->TypeM Equations\nsub env info eq w t1 t2                     = do t1' <- usubst t1\n                                                 t2' <- usubst t2\n                                                 info' <- usubst info\n                                                 sub' env info' eq w t1' t2'\n\nsub'                                        :: Env -> ErrInfo -> Equations -> Name -> Type -> Type ->TypeM Equations\n\nsub' env _ eq w t1@TWild{} t2               = return (idwit env w t1 t2 : eq)\nsub' env _ eq w t1 t2@TWild{}               = return (idwit env w t1 t2 : eq)\n\n--                     as declared               as called\n--                     existing                  expected\nsub' env info eq w t1@(TFun _ fx1 p1 k1 t1') t2@(TFun _ fx2 p2 k2 t2')\n  | varTails [p1,p2] || varTails [k1,k2]    = do --traceM (\"## Unifying funs: \" ++ prstr w ++ \": \" ++ prstr t1 ++ \" ~ \" ++ prstr t2)\n                                                 unify info t1 t2\n                                                 return (idwit env w t1 t2 : eq)\n  | otherwise                               = do --traceM (\"### Aligning fun \" ++ prstr w ++ \": \" ++ prstr t1 ++ \" < \" ++ prstr t2)\n                                                 (cs1,ap,es) <- subpos env info ((map eVar pNames)!!) 0 p2 p1\n                                                 (cs2,ak) <- subkwd0 env info eVar es k2 k1\n                                                 t1 <- usubst t1\n                                                 t2 <- usubst t2\n                                                 w' <- newWitness\n                                                 let (TFun _ fx1 p1 k1 t1', TFun _ fx2 p2 k2 t2') = (t1, t2)\n                                                     (pp,pk) = (pPar pNames p2, kPar attrKW k2)\n                                                     lambda = eLambda [(px0,t1)] $ Lambda l0 pp pk (eCallVar w' [Call l0 (eVar px0) ap ak]) fx1\n                                                 reduce (mkEqn env w (wFun t1 t2) lambda : eq) (Cast info env fx1 fx2 : Sub info env w' t1' t2':cs1++cs2)\n\n--                     existing            expected\nsub' env info eq w t1@(TTuple _ p1 k1) t2@(TTuple _ p2 k2)\n  | varTails [p1,p2] || varTails [k1,k2]    = do --traceM (\"### Unifying tuples: \" ++ prstr w ++ \": \" ++ prstr t1 ++ \" ~ \" ++ prstr t2)\n                                                 unify info t1 t2\n                                                 return (idwit env w t1 t2 : eq)\n  | otherwise                               = do --traceM (\"### Aligning tuple \" ++ prstr w ++ \": \" ++ prstr t1 ++ \" < \" ++ prstr t2)\n                                                 (cs1,ap,es) <- subpos env info (eDotI (eVar px0) . toInteger) 0 p1 p2\n                                                 (cs2,ak) <- subkwd0 env info (eDot (eVar px0)) es k1 k2\n                                                 t1 <- usubst t1\n                                                 t2 <- usubst t2\n                                                 let (TTuple _ p1 k1, TTuple _ p2 k2) = (t1, t2)\n                                                     lambda = eLambda [(px0,t1)] (Paren l0 $ Tuple l0 ap ak)\n                                                 reduce (mkEqn env w (wFun t1 t2) lambda : eq) (cs1++cs2)\n\nsub' env info eq w (TUni _ tv) t2@TFun{}    = do t1 <- instwild env KType $ tFun tWild tWild tWild tWild\n                                                 usubstitute tv t1\n                                                 sub env info eq w t1 t2\nsub' env info eq w t1@TFun{} (TUni _ tv)    = do t2 <- instwild env KType $ tFun tWild tWild tWild tWild\n                                                 usubstitute tv t2\n                                                 sub env info eq w t1 t2\n\nsub' env info eq w (TUni _ tv) t2@TTuple{}  = do t1 <- instwild env KType $ tTuple tWild tWild\n                                                 usubstitute tv t1\n                                                 sub env info eq w t1 t2\n\nsub' env info eq w t1@TTuple{} t2@(TUni _ tv)\n                                            = do defer [Sub info env w t1 t2]; return eq        -- Don't let cast solve this by idwit!\n\nsub' env info eq w t1@(TVar _ tv1) t2@(TVar _ tv2)\n  | tv1 == tv2                              = return (idwit env w t1 t2 : eq)\n\nsub' env info eq w t1@(TUni _ tv1) t2@(TUni _ tv2)\n  | tv1 == tv2                              = return (idwit env w t1 t2 : eq)\n  | otherwise                               = do defer [Sub info env w t1 t2]; return eq\n\nsub' env info eq w t1@TUni{} t2@TCon{}      = do defer [Sub info env w t1 t2]; return eq\nsub' env info eq w t1@TCon{} t2@TUni{}      = do defer [Sub info env w t1 t2]; return eq\n\nsub' env info eq w t1 t2                    = do cast env info t1 t2\n                                                 return (idwit env w t1 t2 : eq)\n\n\nrowTail (TRow _ _ _ _ r)                    = rowTail r\nrowTail r                                   = r\n\nvarTails                                    = all (isUnivar . rowTail)\n\nrowShape env (TRow _ k n t r)               = do t' <- newUnivar env\n                                                 r' <- rowShape env r\n                                                 return (tRow k n t' r')\nrowShape env (TStar _ k r)                  = do r' <- rowShape env r\n                                                 return (tStar k r')\nrowShape env r                              = return r\n\nsubpos                                      :: Env -> ErrInfo -> (Int -> Expr) -> Int -> PosRow -> PosRow -> TypeM (Constraints, PosArg, [(Expr,Type)])\nsubpos env info f i TUni{}         TUni{}   = error \"INTERNAL ERROR: subpos\"\nsubpos env info f i (TUni _ tv)     r2\n  | tv `elem` ufree r2                      = conflictingRow tv                     -- use rowTail?\n  | otherwise                               = do r1 <- rowShape env r2\n                                                 --traceM (\" ## subpos L \" ++ prstr tv ++ \" ~ \" ++ prstr r1)\n                                                 usubstitute tv r1\n                                                 subpos env info f i r1 r2\nsubpos env info f i r1             (TUni _ tv)\n  | tv `elem` ufree r1                      = conflictingRow tv                     -- use rowTail?\n  | otherwise                               = do r2 <- rowShape env r1\n                                                 --traceM (\" ## subpos R \" ++ prstr r2 ++ \" ~ \" ++ prstr tv)\n                                                 usubstitute tv r2\n                                                 subpos env info f i r1 r2\n\nsubpos env info f i (TRow _ _ _ t1 r1) (TRow _ _ _ t2 r2)\n                                            = do --traceM (\" ## subpos A \" ++ prstr t1 ++ \" < \" ++ prstr t2)\n                                                 (cs,as,es) <- subpos env info f (i+1) r1 r2\n                                                 w <- newWitness\n                                                 return (Sub info env w t1 t2 : cs, PosArg (eCallVar w [f i]) as, es)\nsubpos env info f i (TStar _ _ r1)     (TStar _ _ r2)\n                                            = do --traceM (\" ## subpos B \" ++ prstr (tTupleP r1) ++ \" < \" ++ prstr (tTupleP r2))\n                                                 w <- newWitness\n                                                 return ([Sub info env w (tTupleP r1) (tTupleP r2)], PosStar (eCallVar w [f i]), [])\nsubpos env info f i TNil{}             TNil{}\n                                            = do --traceM (\" ## subpos C \")\n                                                 return ([], PosNil, [])\n\nsubpos env info f i (TStar _ _ r1)     r2   = do --traceM (\" ## subpos D \" ++ prstr r1 ++ \" ~ \" ++ prstr r2)\n                                                 subpos env info (eDotI (f i) . toInteger) 0 r1 r2\nsubpos env info f i r1                (TStar _ _ r2)\n                                            = do --traceM (\" ## subpos E \" ++ prstr r1 ++ \" ~ \" ++ prstr r2)\n                                                 (cs,as,es) <- subpos env info f i r1 r2\n                                                 return (cs, PosStar (eTupleP as), es)\n\nsubpos env info f i r1@TNil{}          r@(TRow _ _ _ t2 r2)\n  | TOpt{} <- t2                            = do --traceM (\" ## subpos F Opt ~ \" ++ prstr t2)\n                                                 (cs,as,es) <- subpos env info f i r1 r2\n                                                 return (cs, PosArg eNone as, es)\n  | otherwise                               = do --traceM (\" ## subpos G Nil ~ \" ++ prstr r)\n                                                 posElemNotFound0 env True (Cast info env r1 r) nWild\nsubpos env info f i (TRow _ _ _ t1 r1) r2@TNil{}\n                                            = do --traceM (\" ## subpos H \" ++ prstr t1 ++ \" = \" ++ prstr (f i))\n                                                 (cs,as,es) <- subpos env info f (i+1) r1 r2\n                                                 return (cs, as, (f i, t1) : es)\n\n\n-----------------------\n\nsubkwd0                                     :: Env -> ErrInfo -> (Name -> Expr) -> [(Expr,Type)] -> KwdRow -> KwdRow -> TypeM (Constraints, KwdArg)\nsubkwd0 env info f [] r1 r2                 = subkwd env info f [] r1 r2\nsubkwd0 env info f ((e,t1):es) r1 (TRow _ _ n t2 r2)\n                                            = do --traceM (\" ## subkwd0 extra pos for \" ++ prstr n ++ \": \" ++ prstr t1 ++ \" < \" ++ prstr t2)\n                                                 (cs,as) <- subkwd0 env info f es r1 r2\n                                                 w <- newWitness\n                                                 return (Sub info env w t1 t2 : cs, KwdArg n (eCallVar w [e]) as)\nsubkwd0 env info f ((e,t1):es) r1 r2        = posElemNotFound0 env False (Cast info env r1 r2) nWild\n\nsubkwd                                      :: Env -> ErrInfo -> (Name -> Expr) -> [Name] -> KwdRow -> KwdRow -> TypeM (Constraints, KwdArg)\nsubkwd env info f seen r1 (TUni _ tv)       = do unif f seen r1\n                                                 r2 <- usubst (tUni tv)\n                                                 subkwd env info f seen r1 r2\n  where unif f seen TUni{}                  = error \"INTERNAL ERROR: subkwd\"\n        unif f seen (TRow _ _ n t r)\n          | n `elem` seen                   = do --traceM (\" ## subkwd (Row) - Var: \" ++ prstr (tRow KRow n t r) ++ \" [\" ++ prstrs seen ++ \"] ≈ \" ++ prstr tv)\n                                                 unif f (seen\\\\[n]) r\n          | tv `elem` ufree r               = conflictingRow tv                     -- use rowTail?\n          | otherwise                       = do --traceM (\" ## subkwd Row - Var: \" ++ prstr (tRow KRow n t r) ++ \" [\" ++ prstrs seen ++ \"] ≈ \" ++ prstr tv)\n                                                 t2 <- newUnivar env\n                                                 r2 <- tRow KRow n t2 <$> newUnivarOfKind KRow env\n                                                 unify info (tUni tv) r2\n        unif f seen (TStar _ _ r)\n          | tv `elem` ufree r               = conflictingRow tv                     -- use rowTail?\n          | otherwise                       = do --traceM (\" ## subkwd Star - Var: \" ++ prstr (tStar KRow r) ++ \" [\" ++ prstrs seen ++ \"] ≈ \" ++ prstr tv)\n                                                 r2 <- tStar KRow <$> newUnivarOfKind KRow env\n                                                 unify info (tUni tv) r2\n        unif f seen TNil{}                  = do --traceM (\" ## subkwd Nil - Var: \" ++ prstr (tNil KRow) ++ \" [\" ++ prstrs seen ++ \"] ≈ \" ++ prstr tv)\n                                                 r2 <- pure $ tNil KRow\n                                                 unify info (tUni tv) r2\n\nsubkwd env info f seen r1 (TRow _ _ n2 t2 r2)\n                                            = do (cs1,e) <- pick f seen r1\n                                                 r1 <- usubst r1\n                                                 r2 <- usubst r2\n                                                 (cs2,as) <- subkwd env info f (n2:seen) r1 r2\n                                                 return (cs1++cs2, KwdArg n2 e as)\n  where pick f seen (TUni _ tv)\n          | tv `elem` ufree r2              = conflictingRow tv                     -- use rowTail?\n          | otherwise                       = do --traceM (\" ## subkwd Var - Row: \" ++ prstr (tVar tv) ++ \" [\" ++ prstrs seen ++ \"] ≈ \" ++ prstr (tRow KRow n2 t2 r2))\n                                                 r1 <- tRow KRow n2 t2 <$> newUnivarOfKind KRow env\n                                                 unify info (tUni tv) r1\n                                                 pick f seen r1\n        pick f seen (TRow _ _ n t r)\n          | n `elem` seen                   = do --traceM (\" ## subkwd (Row) - Row: \" ++ prstr (tRow KRow n t r) ++ \" [\" ++ prstrs seen ++ \"] ≈ \" ++ prstr (tRow KRow n2 t2 r2))\n                                                 pick f (seen\\\\[n]) r\n          | n /= n2                         = pick f seen r\n          | otherwise                       = do --traceM (\" ## subkwd Row! - Row: \" ++ prstr (tRow KRow n t r) ++ \" [\" ++ prstrs seen ++ \"] ≈ \" ++ prstr (tRow KRow n2 t2 r2))\n                                                 w <- newWitness\n                                                 return ([Sub info env w t t2], eCallVar w [f n])\n        pick f seen (TStar _ _ r)           = do --traceM (\" ## subkwd Star - Row: \" ++ prstr (tStar KRow r) ++ \" [\" ++ prstrs seen ++ \"] ≈ \" ++ prstr (tRow KRow n2 t2 r2))\n                                                 pick (eDot (f attrKW)) seen r\n        pick f seen (TNil _ _)\n          | TOpt{} <- t2                    = do --traceM (\" ## subkwd None - Row: \" ++ prstr (tNil KRow) ++ \" [\" ++ prstrs seen ++ \"] ≈ \" ++ prstr (tRow KRow n2 t2 r2))\n                                                 return ([], eNone)\n          | otherwise                       = kwdNotFound0 env info n2\n\nsubkwd env info f seen r1 (TStar _ _ r2)    = do (cs,e) <- match f seen r1\n                                                 return (cs, KwdStar e)\n  where match f seen (TUni _ tv)\n          | tv `elem` ufree r2              = conflictingRow tv                     -- use rowTail?\n          | otherwise                       = do --traceM (\" ## subkwd Var - Star: \" ++ prstr (tVar tv) ++ \" [\" ++ prstrs seen ++ \"] ≈ \" ++ prstr (tStar KRow r2))\n                                                 r1 <- tStar KRow <$> newUnivarOfKind KRow env\n                                                 unify info (tUni tv) r1\n                                                 match f seen r1\n        match f seen r1@(TRow _ _ n t r)\n          | n `elem` seen                   = do --traceM (\" ## subkwd (Row) - Star: \" ++ prstr (tRow KRow n t r) ++ \" [\" ++ prstrs seen ++ \"] ≈ \" ++ prstr (tStar KRow r2))\n                                                 match f (seen\\\\[n]) r\n          | otherwise                       = do --traceM (\" ## subkwd Row - Star: \" ++ prstr (tRow KRow n t r) ++ \" [\" ++ prstrs seen ++ \"] ≈ \" ++ prstr (tStar KRow r2))\n                                                 (cs,as) <- subkwd env info f seen r1 r2\n                                                 return (cs, eTupleK as)\n        match f seen r1@(TStar _ _ r)\n          | TUni _ v <- r, TUni _ v2 <- r2  = do --traceM (\" ## subkwd StarVar - StarVar: \" ++ prstr (tStar KRow r) ++ \" [\" ++ prstrs seen ++ \"] ≈ \" ++ prstr (tStar KRow r2))\n                                                 unify info r r2\n                                                 return ([], f attrKW)\n          | TUni _ v <- r                   = do --traceM (\" ## subkwd StarVar - Star: \" ++ prstr (tStar KRow r) ++ \" [\" ++ prstrs seen ++ \"] ≈ \" ++ prstr (tStar KRow r2))\n                                                 (cs,as) <- subkwd env info f seen r1 r2\n                                                 return (cs, eTupleK as)\n          | otherwise                       = do --traceM (\" ## subkwd Star - Star: \" ++ prstr (tStar KRow r) ++ \" [\" ++ prstrs seen ++ \"] ≈ \" ++ prstr (tStar KRow r2))\n                                                 match (eDot (f attrKW)) seen r\n        match f seen r1@TNil{}              = do --traceM (\" ## subkwd Nil - Star: \" ++ prstr (tNil KRow) ++ \" [\" ++ prstrs seen ++ \"] ≈ \" ++ prstr (tStar KRow r2))\n                                                 (cs,as) <- subkwd env info f seen r1 r2\n                                                 return (cs, eTupleK as)\n\nsubkwd env info f seen r1 TNil{}            = term f seen r1\n  where term f seen (TUni _ tv)             = do --traceM (\" ## subkwd Var - Nil: \" ++ prstr (tVar tv) ++ \" [\" ++ prstrs seen ++ \"] ≈ \" ++ prstr (tNil KRow))\n                                                 r1 <- pure $ tNil KRow\n                                                 unify info (tUni tv) r1\n                                                 term f seen (tNil KRow)\n        term f seen (TRow _ _ n t r)\n          | n `elem` seen                   = do --traceM (\" ## subkwd (Row) - Nil: \" ++ prstr (tRow KRow n t r) ++ \" [\" ++ prstrs seen ++ \"] ≈ \" ++ prstr (tNil KRow))\n                                                 term f (seen\\\\[n]) r\n          | otherwise                       = do --traceM (\" ## subkwd Row - Nil: \" ++ prstr (tRow KRow n t r) ++ \" [\" ++ prstrs seen ++ \"] ≈ \" ++ prstr (tNil KRow))\n                                                 kwdUnexpected info n\n        term f seen (TStar _ _ r)           = do --traceM (\" ## subkwd Star - Nil: \" ++ prstr (tStar KRow r) ++ \" [\" ++ prstrs seen ++ \"] ≈ \" ++ prstr (tNil KRow))\n                                                 term f seen r\n        term f seen (TNil _ _)              = do --traceM (\" ## subkwd Nil - Nil: \" ++ prstr (tNil KRow) ++ \" [\" ++ prstrs seen ++ \"] ≈ \" ++ prstr (tNil KRow))\n                                                 return ([], KwdNil)\n\n\n{-\n\n---- OK:\n\nx.          c,a             a,c                     a = x.a                                 Row!            Row\nx.          c,a             c           a           c = x.a                                 Row!            Row\nx.          c,a             .           ac                                                  (Row)           Nil\nx.          .               .                       .                                       Nil             Nil\n\n---- OK:\n\nx.          c,a*(b*A)       a,b,c,e                 a = (x.)a, ...                          Row!            Row\nx.          c,a*(b*A)       b,c,e       a                                                   Star            Row\nx.KW.           b*A         b,c,e       a           b = (x.KW.)b                                Row!        Row\nx.          c,a*(b*A)       c,e         ab          c = (x.)c, ...                          Row!            Row\nx.          c,a*(b*A)       e           abc                                                 Star            Row\nx.KW.           b*A         e           abc                                                     StarVar     Row\nx.KW.KW.            A       e           abc                             A ~ e,B                 Var         Row\nx.KW.KW.            e,B     e           abc         e = (x.KW.KW.)e, ...                        Row!        Row\nx.          c,a*(b*(e,B))   .           abce                                                (Row)           Nil\nx.          *(b*(e,B))      .           be                                                  Star            Nil\nx.KW.           b*(e,B)     .           be                                                      (Row)       Nil\nx.KW.           *(e,B)      .           e                                                       Star        Nil\nx.KW.KW             e,B     .           e                                                       (Row)       Nil\nx.KW.KW             B       .                                           B ~ .                   Var         Nil\n                    .       .                                                                   Nil         Nil\n\nx = (c = 1, a = 2, KW = (b = 4, KW = (e = 5)))                          (a = x.a, b = x.KW.b, c = x.c, e = x.KW.KW.e)\n\n---- OK:\n\nx.          c*(b*A)         c*X                     c = x.c                                 Row!            Row\nx.          c*(b*A)         *X          c                                                   (Row)           Star\nx.          *(b*A)          *X                                                              Star            Star\nx.KW.           b*A         *X                      KW = (...)                                  Row         Star\nx.KW.           b*A             X                                       X ~ b,Y                 Row             Var\nx.KW.           b*A             b,Y                     b = x.KW.b                              Row!            Row\nx.KW.           b*A             Y       b                                                       (Row)           Var\nx.KW.           *A              Y                                       Y ~ *Z                  StarVar         Var\nx.KW.           *A              *Z                      KW = x.KW.KW    A ~ Z                   StarVar         StarVar\n\nx = (c = 1, KW = (b = 4, KW = y))                                       (c = x.c, KW = (b = x.KW.b, KW = x.KW.KW))\n\n---- OK:\n\nx.          c,a*(b*A)       a,b,c*X                 a = (x.)a, ...                          Row!            Row\nx.          c,a*(b*A)       b,c*X       a                                                   Star            Row\nx.KW.           b*A         b,c*X       a           b = (x.KW.)b, ...                           Row!        Row\nx.          c,a*(b*A)       c*X         ab          c = (x.)c, ...                          Row!            Row\nx.          c,a*(b*A)       *X          abc                                                 (Row)           Star\nx.          *(b*A)          *X          b                                                   Star            Star\nx.KW.           b*A         *X          b                                                       (Row)       Star\nx.KW.           *A          *X                      KW = (x.KW.)KW      A ~ X                   StarVar     StarVar\n\nx = (c = 1, a = 2, KW = (b = 4, KW = y))                                (a = x.a, b = x.KW.b, c = x.c, KW = x.KW.KW)\n\n---- OK:\n\nx.          c,a*(b*A)       a,b,c,e*X               a = (x.)a, ...                          Row!            Row\nx.          c,a*(b*A)       b,c,e*X     a                                                   Star            Row\nx.KW.           b*A         b,c,e*X                 b = (x.KW.)b, ...                           Row!        Row\nx.          c,a*(b*A)       c,e*X       ab          c = (x.)c, ...                          Row!            Row\nx.          c,a*(b*A)       e*X         abc                                                 Star            Row\nx.KW.           b*A         e*X         b                                                       Star        Row\nx.KW.KW.            A       e*X         b                               A ~ e,B                     Var     Row\nx.KW.KW.            e,B     e*X         b           e = (x.KW.KW.)e                                 Row!    Row\nx.          c,a*(b*(e,B))   *X          abce                                                (Row)           Star\nx.          *(b*(e,B))      *X          be                                                  Star            Star\nx.KW.           b*(e,B)     *X          be                                                      (Row)       Star\nx.KW.           *(e,B)      *X          e                                                       Star        Star\nx.KW.KW.            e,B     *X          e                                                           (Row)   Star\nx.KW.KW.            B       *X                                          B ~ *X                      Var     Star\nx.KW.KW.            *X      *X                      KW = (x.KW.KW.)KW                               StarVar StarVar\n\nx = (c = 1, a = 2, KW = (b = 4, KW = (e = 5, KW = y)))                  (a = x.a, b = x.KW.b, c = x.c, e = x.KW.KW.e, KW = x.KW.KW.KW)\n\n---- OK:\n\nx.          c,a*A           a,b,c,e*X               a = (x.)a, ...                          Row!        Row\nx.          c,a*A           b,c,e*X     a                                                   StarVar     Row\nx.KW.           A           b,c,e*X                                     A ~ b,B                 Var     Row\nx.KW.           b,B         b,c,e*X                 b = (x.KW.)b, ...                           Row!    Row\nx.          c,a*(b,B)       c,e*X       ab          c = (x.)c, ...                          Row!        Row\nx.          c,a*(b,B)       e*X         abc                                                 Star        Row\nx.KW.           b,B         e*X         b                               B ~ e,C                 Var     Row\nx.KW.           b,e,C       e*X         b           e = (x.KW.)e, ...                           Row!    Row\nx.          c,a*(b,e,C)     *X          abce                                                (Row)       Star\nx.          *(b,e,C)        *X          be                                                  Star        Star\nx.KW.           b,e,C       *X          be                                                      (Row)   Star\nx.KW.           C           *X                                          C ~ *X                  Var     Star\nx.KW.           *X          *X                      KW = (x.KW.)KW                              StarVar StarVar\n\nx = (c = 1, a = 2, KW = (b = 4, e = 5, KW = y))                         (a = x.a, b = x.KW.b, c = x.c, e = x.KW.e, KW = x.KW.KW)\n\n---- OK:\n\nx.          c,a,d*A         a,b,c,e*X               a = (x.)a, ...                          Row!        Row\nx.          c,a,d*A         b,c,e*X     a                                                   StarVar     Row\nx.KW.           A           b,c,e*X     a                               A ~ b,B                 Var     Row\nx.KW.           b,B         b,c,e*X     a           b = (x.KW.)b, ...                           Row!    Row\nx.          c,a,d*(b,B)     c,e*X       ab          c = x.c, ...                            Row!        Row\nx.          c,a,d*(b,B)     e*X         abc                                                 Star        Row\nx.KW.           b,B         e*X         b                               B ~ e,C                 Var     Row\nx.KW.           b,e,C       e*X         b           e = x.KW.e, ...                             Row!    Row\nx.          c,a,d*(b,e,C)   *X          abce                                                (Row)       Star\nx.          d*(b,e,C)       *X          be          KW = (...)                              Row         Star\nx.          d*(b,e,C)           X       be                              X ~ d,Y             Row             Var\nx.          d*(b,e,C)           d,Y     be              d = (x.)d, ...                      Row!            Row\nx.          d*(b,e,C)           Y       bed                                                 (Row)           Var\nx.          *(b,e,C)            Y       be                              Y ~ *Z              Star            Var\nx.          *(b,e,C)            *Z      be                                                  Star            Star\nx.KW.           b,e,C           *Z      be                                                      (Row)       Star\nx.KW.           C               *Z                                      C ~ *Z                  Var         Star\nx.KW.           *Z              *Z                      KW = (x.KW.)KW                          StarVar     StarVar\n\nx = (c = 1, a = 2, d = 3, KW = (b = 4, e = 5, KW = y))                  (a = x.a, b = x.KW.b, c = x.c, e = x.KW.e, KW = (d = x.d, KW = x.KW.KW))\n\n\n---- OK:\n\nx.          c,a*A           a,c*X                   a = (x.)a, ...                          Row!        Row\nx.          c,a*A           c*X         a           c = (x.)c, ...                          Row!        Row\nx.          c,a*A           *X          ac                                                  (Row)       Star\nx.          *A              *X                      KW = (x.)KW         A ~ X               StarVar     StarVar\n\nx = (c = 1, a = 2, KW = y)                                              (a = x.a, c = x.c, KW = x.KW)\n\n---- OK:\n\nx.          c,a,d*A         a,c*X                   a = (x.)a, ...                          Row!        Row\nx.          c,a,d*A         c*X         a           c = (x.)c, ...                          Row!        Row\nx.          c,a,d*A         *X          ac                                                  (Row)       Star\nx.          d*A             *X                      KW = (...)                              Row         Star\nx.          d*A                 X                                       X ~ d,Y             Row             Var\nx.          d*A                 d,Y                     d = (x.)d, ...                      Row!            Row\nx.          d*A                 Y       d                                                   (Row)           Var\nx.          *A                  Y                                       Y ~ *A              Star            Var\nx.          *A                  *A                      KW = (x.)KW                         StarVar         StarVar\n\nx = (c = 1, a = 2, d = 3, KW = y)                                       (a = x.a, c = x.c, KW = (d = x.d, KW = x.KW))\n\n---- OK:\n\nx.          c,a,d*A         a,c*(d*X)               a = (x.)a, ...                          Row!        Row\nx.          c,a,d*A         c*(d*X)     a           c = (x.)c, ...                          Row!        Row\nx.          c,a,d*A         *(d*X)      ac                                                  (Row)       Star\nx.          d*A             *(d*X)                  KW = (...)                              Row         Star\nx.          d*A                 d*X                     d = x.d, ...                        Row!            Row\nx.          d*A                 *X      d                                                   (Row)           Star\nx.          *A                  *X                      KW = (x.)KW     A ~ X               StarVar         StarVar\n\nx = (c = 1, a = 2, d = 3, KW = y)                                       (a = x.a, c = x.c, KW = (d = x.d, KW = x.KW))\n\n---- OK:\n\nx.          c,a*A           a,c*(d*X)               a = (x.)a                               Row!        Row\nx.          c,a*A           c*(d*X)     a           c = (x.)c                               Row!        Row\nx.          c,a*A           *(d*X)      ac                                                  (Row)       Star\nx.          *A              *(d*X)                  KW = (...)                              StarVar     Star\nx.          *A                  d*X                                                         Star            Row\nx.KW.           A               d*X                                     A ~ d,B             Var             Row\nx.KW.           d,B             d*X                     d = x.KW.d                          Row!            Row\nx.          *(d,B)              d*X     d                                                   Star            Star\nx.KW.           d,B             *X      d                                                   (Row)           Star\nx.KW.           B               *X                                      B ~ *X              Var             Star\nx.KW.           *X              *X                      KW = x.KW.KW                        StarVar         StarVar\n\nx = (c = 1, a = 2, KW = (d = 3, KW = y))                                (a = x.a, c = x.c, KW = (d = x.KW.d, KW = x.KW.KW))\n\n---- OK:\n\nx.          c,a,d           a*X                     a = x.a                                 Row!        Row\nx.          c,a,d           *X          a                                                   (Row)       Star\nx.          c,d             *X                      KW = (...)                              Row         Star\nx.          c,d                 X                                       X ~ c,Y             Row             Var\nx.          c,d                 c,Y                     c = x.c                             Row!            Row\nx.          c,d                 Y       c                               Y ~ d,Z             Row             Var\nx.          c,d                 d,Z     c               d = x.d                             Row!            Row\nx.          c,d                 Z       cd                                                  (Row)           Var\nx.          .                   Z                                       Z ~ .               Nil             Var\n\nx = (c = 1, a = 2, d = 3)                                               (a = x.a, KW = (c = x.c, d = x.d))\n\n---- OK:\n\nx.          c,a,d*A         a*X                     a = x.a                                 Row!        Row\nx.          c,a,d*A         *X          a                                                   (Row)       Star\nx.          c,d*A           *X                      KW = (...)                              Row         Star\nx.          c,d*A               X                                       X ~ c,Y             (Row)           Var\nx.          c,d*A               c,Y                     c = x.c                             Row!            Row\nx.          c,d*A               Y       c                               Y ~ d,Z             (Row)           Var\nx.          c,d*A               d,Z     c               d = x.d                             Row!            Row\nx.          c,d*A               Z       cd                                                  (Row)           Var\nx.          *A                  Z                                       Z ~ *A              Star            Var\nx.          *A                  *A                      KW = x.KW                           StarVar         StarVar\n\nx = c = 1, a = 2, d = 3, KW = y)                                        (a = x.a, KW = (c = x.c, d = x.d, KW = x.KW))\n\n-}\n\n\n\n{-\nsubpos 0 (A,B,*R) (A,B,C,D)                     = Arg x.0 $ subpos 1 (B,*R) (B,C,D)                                     f = x.\n                                                = Arg x.0 $ Arg x.1 $ subpos 2 (*R) (C,D)\n                                                = Arg x.0 $ Arg x.1 $ subpos 0 R (C,D)                                  f = x.2.   R ~ (C,D)\n                                                = Arg x.0 $ Arg x.1 $ subpos 0 (C,D) (C,D)\n                                                = Arg x.0 $ Arg x.1 $ Arg x.2.0 $ subpos 1 (D) (D)\n                                                = Arg x.0 $ Arg x.1 $ Arg x.2.0 $ Arg x.2.1 $ subpos 2 () ()\n                                                = Arg x.0 $ Arg x.1 $ Arg x.2.0 $ Arg x.2.1 $ Nil\n\nsubpos 0 (A,B,C,D) (A,B,*S)                     = Arg x.0 $ subpos 1 (B,C,D) (B,*S)                                     f = x.\n                                                = Arg x.0 $ Arg x.1 $ subpos 2 (C,D) (*S)\n                                                = Arg x.0 $ Arg x.1 $ Arg (subpos 2 (C,D) S) Nil\n                                                = Arg x.0 $ Arg x.1 $ Arg (subpos 2 (C,D) (C,D)) Nil\n                                                = Arg x.0 $ Arg x.1 $ Arg (Arg x.2 $ subpos 3 (D) (D)) Nil\n                                                = Arg x.0 $ Arg x.1 $ Arg (Arg x.2 $ Arg x.3 $ subpos 4 () ()) Nil\n                                                = Arg x.0 $ Arg x.1 $ Arg (Arg x.2 $ Arg x.3 $ Nil) Nil\n\nsubpos 0 (A,*R) (A,B,*S)                        = Arg x.0 $ subpos 1 (*R) (B,*S)                                        f = x.\n                                                = Arg x.0 $ subpos 0 R (B,*S)                                           f = x.1.    R ~ (B,*S)\n                                                = Arg x.0 $ subpos 0 (B,*S) (B,*S)\n                                                = Arg x.0 $ Arg x.1.0 $ subpos 1 (*S) (*S)\n                                                = Arg x.0 $ Arg x.1.0 $ Arg w(x.1.1) Nil\n\n-}\n\n\n----------------------------------------------------------------------------------------------------------------------\n-- Variable info\n----------------------------------------------------------------------------------------------------------------------\n\ndata VInfo                                  = VInfo {\n                                                varvars     :: [(TUni,TUni)],\n                                                embedded    :: [TUni],\n                                                sealed      :: [TUni],\n                                                ubounds     :: Map TUni [Type],\n                                                lbounds     :: Map TUni [Type],\n                                                pbounds     :: Map TUni [(Name,PCon)],\n                                                mutattrs    :: Map TUni [Name],\n                                                selattrs    :: Map TUni [Name] }\n\nvarvar v1 v2 vi                             = vi{ varvars = (v1,v2) : varvars vi }\nembed vs vi                                 = vi{ embedded = vs ++ embedded vi }\nseal v vi                                   = vi{ sealed = v : sealed vi }\nubound v t vi                               = vi{ ubounds = Map.insertWith (++) v [t] (ubounds vi) }\nlbound v t vi                               = vi{ lbounds = Map.insertWith (++) v [t] (lbounds vi) }\npbound v w p vi                             = vi{ pbounds = Map.insertWith (++) v [(w,p)] (pbounds vi) }\nmutattr v n vi                              = vi{ mutattrs = Map.insertWith (++) v [n] (mutattrs vi) }\nselattr v n vi                              = vi{ selattrs = Map.insertWith (++) v [n] (selattrs vi) }\n\nlookup' v m                                 = maybe [] id $ Map.lookup v m\n\nvarinfo cs                                  = f cs (VInfo [] [] [] Map.empty Map.empty Map.empty Map.empty Map.empty)\n  where\n    f (Cast _ _ (TUni _ v1) (TUni _ v2) : cs)\n      | v1 == v2                            = f cs\n      | otherwise                           = f cs . varvar v1 v2\n    f (Cast _ _ (TUni _ v) t : cs)          = f cs . ubound v t . embed (ufree t)\n    f (Cast _ _ t (TUni _ v) : cs)          = f cs . lbound v t . embed (ufree t)\n    f (Sub _ _ _ (TUni _ v1) (TUni _ v2) : cs)\n      | v1 == v2                            = f cs\n      | otherwise                           = f cs . varvar v1 v2\n    f (Sub _ _ _ (TUni _ v) t : cs)         = f cs . ubound v t . embed (ufree t)\n    f (Sub _ _ _ t (TUni _ v) : cs)         = f cs . lbound v t . embed (ufree t)\n    f (Proto _ _ w (TUni _ v) p : cs)       = f cs . pbound v w p . embed (ufree p)\n    f (Proto _ _ w t p : cs)\n      | not $ null vs                       = f cs . embed (vs ++ ufree p)\n      where vs                              = nub $ ufree t\n    f (Mut _ _ (TUni _ v) n t : cs)         = f cs . mutattr v n . embed (ufree t)\n    f (Sel _ _ _ (TUni _ v) n t : cs)       = f cs . selattr v n . embed (ufree t)\n    f (Sel _ _ _ (TTuple _ _ TUni{}) _ _ : cs)\n                                            = f cs\n    f (Seal _ _ (TUni _ v) : cs)            = f cs . seal v\n    f []                                    = Just\n    f (_ : cs)                              = \\_ -> Nothing\n\nvarclose xys                                = clos [] xys\n  where clos cl []                          = Right cl\n        clos cl ((x,y):xys)\n          | (x,y) `elem` cl                 = clos cl xys\n          | not $ null common               = Left (x,y:common)\n          | otherwise                       = clos ((x,y):cl)  (new_below++new_above++xys)\n          where below_x                     = below x cl\n                above_y                     = above y cl\n                common                      = below_x `intersect` above_y\n                new_below                   = [ (w,y) | w <- below_x ]\n                new_above                   = [ (x,v) | v <- above_y ]\n\nbelow x cl                                  = [ v | (v,w) <- cl, w==x ]\nabove y cl                                  = [ w | (v,w) <- cl, v==y ]\n\ngsimp vi cl obs []                      = []\ngsimp vi cl obs ((x,y):xys)\n  | not subsumed                        = gsimp vi cl obs xys\n  | x_obs && y_obs                      = gsimp vi cl obs xys\n  | x_obs                               = (x,y) : gsimp vi cl (y:obs) xys\n  | y_obs                               = (x,y) : gsimp vi cl (x:obs) xys\n  | otherwise                           = (x,y) : gsimp vi cl obs xys\n  where subsumed                        = (above x cl \\\\ [y]) `eq` above y cl && (below y cl \\\\ [x]) `eq` below x cl &&\n                                          lookup' x (ubounds vi) `subset` lookup' y (ubounds vi) && lookup' y (lbounds vi) `subset` lookup' x (lbounds vi) &&\n                                          rng (lookup' x (pbounds vi)) `eq` rng (lookup' y (pbounds vi))\n        a `eq` b                        = a `subset` b && b `subset` a\n        a `subset` b                    = all (`elem` b) a\n        x_obs                           = x `elem` obs\n        y_obs                           = y `elem` obs\n\ninstwild env k (TWild _)                = newUnivarOfKind k env\ninstwild env _ (TFun l e p k t)         = TFun l <$> instwild env KFX e <*> instwild env PRow p <*> instwild env KRow k <*> instwild env KType t\ninstwild env _ (TTuple l p k)           = TTuple l <$> instwild env PRow p <*> instwild env KRow k\ninstwild env _ (TOpt l t)               = TOpt l <$> instwild env KType t\ninstwild env _ (TCon l c)               = TCon l <$> instwildcon env c\ninstwild env _ (TRow l k n t r)         = TRow l k n <$> instwild env KType t <*> instwild env k r\ninstwild env _ (TStar l k r)            = TStar l k <$> instwild env k r\ninstwild env k t                        = return t\n\ninstwildcon env c                       = case tconKind (tcname c) env of\n                                            KFun ks _ -> TC (tcname c) <$> sequence [ instwild env k t | (k,t) <- ks `zip` tcargs c ]\n                                            _ -> return $ TC (tcname c) []\n\n\nmkGLB env (v,ts)\n  | Just t <- glbfold env ts'           = do t <- instwild env KType t\n                                             --traceM (\"   glb \" ++ prstrs ts ++ \" = \" ++ prstr t)\n                                             return (v, t)\n  | otherwise                           = tyerrs ts (\"No common subtype:\")\n  where ts'                             = map schematic ts\n\n\nmkLUB env (v,ts)\n  | Just t <- lubfold env ts'           = do t <- instwild env KType t\n                                             --traceM (\"   lub \" ++ prstrs ts ++ \" = \" ++ prstr t)\n                                             return (v, t)\n  | otherwise                           = tyerrs ts (\"No common supertype:\")\n  where ts'                             = map schematic ts\n\n\n----------------------------------------------------------------------------------------------------------------------\n-- Improvement\n----------------------------------------------------------------------------------------------------------------------\n\n-- Check if the deferred constraint set should be resubmitted\n-- Unify all var cycles\n-- Perform G-simplification on internal variables\n-- Check that there's at least one non-embedded variable\n-- For all non-embedded variables: replace multiple lower/upper con bounds with a LUB/GLB\n-- For non-embedded variables with a single lower/upper bound: replace with bound if not negative/positive\n-- For non-embedded variables with multiple protocol constraints: identify equal and subtype-related protocols\n\n-- After improvement:\n--  headvar is defined\n--  Cast/Sub bound is either TUni (upper), TCon, TNone (lower), TOpt (upper) or TFX\n--  acyclic\n--  G-minimal (constrained vars are observable)\n--  S-minimal (constrained vars are invariant)\n--  just single upper/lower bounds\n--  no closed upper/lower bounds\n--  no redundant Proto\n--  no Sel/Mut covered by Cast/Sub/Proto bounds\n\n\ninstance Pretty (TUni, [Type]) where\n    pretty (uv, ts)                     = pretty uv <+> text \"<\" <+> pretty ts\n\ninstance Pretty [Type] where\n    pretty ts                           = brackets (commaSep pretty ts)\n\ninstance Pretty (TUni, Type) where\n    pretty (uv, t)                      = pretty uv <+> text \"~\" <+> pretty t\n\nimprove                                 :: Env -> TEnv -> Equations -> Constraints -> TypeM (Constraints,Equations)\nimprove env te eq []                    = return ([], eq)\nimprove env te eq cs\n  | Nothing <- info                     = do --traceM (\"  *Resubmit \" ++ show (length cs))\n                                             simplify' env te eq cs\n  | Left (v,vs) <- closure              = do --traceM (\"  *Unify cycle \" ++ prstr v ++ \" = \" ++ prstrs vs)\n                                             sequence [ unify (noinfo 12) (tUni v) (tUni v') | v' <- vs ]\n                                             simplify' env te eq cs\n  | not $ null gsimple                  = do --traceM (\"  *G-simplify \" ++ prstrs [ (v,tUni v') | (v,v') <- gsimple ])\n                                             --traceM (\"  *obsvars: \" ++ prstrs obsvars)\n                                             --traceM (\"  *varvars: \" ++ prstrs (varvars vi))\n                                             sequence [ unify (noinfo 13) (tUni v) (tUni v') | (v,v') <- gsimple ]\n                                             simplify' env te eq cs\n  | not $ null cyclic                   = tyerrs cyclic (\"Cyclic subtyping:\")\n  | not $ null (multiUBnd++multiLBnd)   = do ub <- mapM (mkGLB env) multiUBnd   -- GLB of the upper bounds\n                                             lb <- mapM (mkLUB env) multiLBnd   -- LUB of the lower bounds\n                                             --traceM (\"  *GLB \" ++ prstrs ub)\n                                             --traceM (\"  *LUB \" ++ prstrs lb)\n                                             simplify' env te eq (replace ub lb cs)\n  | not $ null posLBnd                  = do --traceM (\"  *S-simplify (dn) \" ++ prstrs posLBnd)\n                                             --traceM (\"   posnames \"  ++ prstrs (posnames $ envX env))\n                                             sequence [ unify (noinfo 15) (tUni v) t | (v,t) <- posLBnd ]\n                                             simplify' env te eq cs\n  | not $ null negUBnd                  = do --traceM (\"  *S-simplify (up) \" ++ prstrs negUBnd)\n                                             --traceM (\"   posnames \"  ++ prstrs (posnames $ envX env))\n                                             sequence [ unify (noinfo 16) (tUni v) t | (v,t) <- negUBnd ]\n                                             simplify' env te eq cs\n  | not $ null closUBnd                 = do --traceM (\"  *Simplify upper closed bound \" ++ prstrs closUBnd)\n                                             sequence [ unify (noinfo 17) (tUni v) t | (v,t) <- closUBnd ]\n                                             simplify' env te eq cs\n  | not $ null closLBnd                 = do --traceM (\"  *Simplify lower closed bound \" ++ prstrs closLBnd)\n                                             sequence [ unify (noinfo 18) (tUni v) t | (v,t) <- closLBnd ]\n                                             simplify' env te eq cs\n  | not $ null redEq                    = do --traceM (\"  *(Context red) \" ++ prstrs (bound redEq))\n                                             sequence [ unify (noinfo 19) t1 t2 | (t1,t2) <- redUni ]\n                                             simplify' env te (redEq++eq) (remove (bound redEq) cs)\n  | not $ null dots                     = do --traceM (\"  *Implied mutation/selection solutions \" ++ prstrs dots)\n                                             (eq',cs') <- solveDots mutC selC selP cs\n                                             simplify' env te (eq'++eq) cs'\n  | not $ null redSeal                  = do --traceM (\"  *removing redundant Seal constraints on: \" ++ prstrs redSeal)\n                                             return (filterOut redSeal cs, eq)\n  | otherwise                           = do --traceM (\"  *improvement done \" ++ show (length cs))\n                                             return (cs, eq)\n  where info                            = varinfo cs\n        Just vi                         = info\n        closure                         = varclose (varvars vi)\n        Right vclosed                   = closure\n        (vvsL,vvsU)                     = unzip vclosed\n        gsimple                         = gsimp vi vclosed obsvars (varvars vi)\n        multiUBnd                       = [ (v,ts) | (v,ts) <- multiUBounds cs, noEmbed v, noLOpt v ]\n        multiLBnd                       = [ (v,ts) | (v,ts) <- multiLBounds cs, noEmbed v ]\n        lowerBnd                        = [ (v,t) | (v,[t]) <- Map.assocs (lbounds vi), noEmbed v ]\n        upperBnd                        = [ (v,t) | (v,[t]) <- Map.assocs (ubounds vi), noEmbed v ]\n        posLBnd                         = [ (v,t) | (v,t) <- lowerBnd, v `notElem` negvars, implAll env (lookup' v $ pbounds vi) t ]\n        negUBnd                         = [ (v,t) | (v,t) <- upperBnd, v `notElem` posvars, implAll env (lookup' v $ pbounds vi) t, noDots vi v ]\n        closLBnd                        = [ (v,t) | (v, [t]) <- Map.assocs (lbounds vi), upClosed env t, implAll env (lookup' v $ pbounds vi) t ]\n        closUBnd                        = [ (v,t) | (v, [t]) <- Map.assocs (ubounds vi), dnClosed env t, implAll env (lookup' v $ pbounds vi) t, noDots vi v ]\n        (redEq,redUni)                  = ctxtReduce env cs\n        mutC                            = findBoundAttrs env (mutattrs vi) (ubounds vi)\n        selC                            = findBoundAttrs env (selattrs vi) (ubounds vi)\n        selP                            = findWitAttrs env (selattrs vi) (pbounds vi)\n        dots                            = dom mutC ++ dom selC ++ dom selP\n        pvars                           = Map.keys (pbounds vi) ++ ufree (Map.elems (pbounds vi))\n        dotvars                         = Map.keys (selattrs vi) ++ Map.keys (mutattrs vi)\n        (posvars0,negvars0)             = polvars te `polcat` polvars env\n        (posvars,negvars)               = (posvars0++vvsL, negvars0++vvsU)\n        obsvars                         = posvars0 ++ negvars0 ++ pvars ++ dotvars ++ embedded vi ++ sealed vi\n        boundvars                       = Map.keys (ubounds vi) ++ Map.keys (lbounds vi)\n        boundprot                       = ufree (Map.elems $ ubounds vi) ++ ufree (Map.elems $ lbounds vi)\n        cyclic                          = if null (boundvars\\\\boundprot) then [ c | c <- cs, headvar c `elem` boundvars ] else []\n        redSeal                         = sealed vi \\\\ (posvars ++ negvars ++ embedded vi ++ Map.keys (ubounds vi) ++ Map.keys (lbounds vi)\n                                          ++ Map.keys (pbounds vi) ++ Map.keys (mutattrs vi) ++ Map.keys (selattrs vi))\n        noEmbed v                       = v `notElem` embedded vi\n        noLOpt v                        = not $ any optCon $ lookup' v (lbounds vi)\n          where optCon TNone{}                  = True\n                optCon TOpt{}                   = True\n                optCon _                        = False\n\nmultiUBounds cs                         = Map.assocs $ Map.map deOpt $ Map.filter ((>1) . length) $ bnds cs\n  where\n    bnds []                             = Map.empty\n    bnds (Cast _ _ TUni{} TUni{} : cs)  = bnds cs\n    bnds (Cast _ _ TUni{} (TOpt _ TUni{}) : cs) = bnds cs\n    bnds (Cast _ env (TUni _ v) t : cs) = Map.insertWith (++) v [t] $ bnds cs\n    bnds (Sub _ _ _ TUni{} TUni{} : cs) = bnds cs\n    bnds (Sub _ _ env TUni{} (TOpt _ TUni{}) : cs) = bnds cs\n    bnds (Sub _ _ _ (TUni _ v) t : cs)  = Map.insertWith (++) v [t] $ bnds cs\n    bnds (_ : cs)                       = bnds cs\n\n    deOpt ts                            = if all isOpt ts then ts else map unOpt ts\n      where isOpt TOpt{}                = True\n            isOpt _                     = False\n            unOpt (TOpt _ t)            = t\n            unOpt t                     = t\n\n\nmultiLBounds cs                         = Map.assocs $ Map.map deEnv $ Map.filter ((>1) . length) $ bnds cs\n  where\n    bnds []                             = Map.empty\n    bnds (Cast _ _ TUni{} TUni{} : cs)  = bnds cs\n    bnds (Cast _ env t (TUni _ v) : cs) = Map.insertWith (++) v [(env,t)] $ bnds cs\n    bnds (Sub _ _ _ TUni{} TUni{} : cs) = bnds cs\n    bnds (Sub _ env _ t (TUni _ v) : cs)= Map.insertWith (++) v [(env,t)] $ bnds cs\n    bnds (_ : cs)                       = bnds cs\n\n    deEnv envts\n      | length ts == 1                  = ts\n      | otherwise                       = map deVar envts\n      where ts                          = nub [ t | (env,t) <- envts ]\n            deVar (env,TVar _ v)        = tCon (findTVBound env v)\n            deVar (env,t)               = t\n\n\ndnClosed env (TCon _ c)                 = isActor env (tcname c)\ndnClosed env (TFX _ FXPure)             = True\ndnClosed env (TFX _ FXAction)           = True\ndnClosed env (TNone _)                  = True\ndnClosed env (TNil _ _)                 = True\ndnClosed env _                          = False\n\nupClosed env (TFX _ FXProc)             = True\nupClosed env (TOpt _ _)                 = True\nupClosed env (TNil _ _)                 = True\nupClosed env _                          = False\n\nfindBoundAttrs env attrs bounds         = [ ((v,n),wsc) | (v,ns) <- Map.assocs attrs, n <- ns, wsc <- bounds' v n ]\n  where bounds' v n                     = [ wsc | TCon _ c <- lookup' v bounds, Just wsc <- [findAttr env c n] ]\nfindWitAttrs env attrs bounds           = [ ((v,n), (p, wexpr ws $ eVar w)) | (v,ns) <- Map.assocs attrs, n <- ns, (w,p,ws) <- bounds' v n ]\n  where bounds' v n                     = [ (w,p,ws) | (w,p0) <- lookup' v bounds, (ws,p) <- findAncestry env p0, n `elem` conAttrs env (tcname p) ]\n\n\nimplAll env [] t                        = True\nimplAll env ps t@TCon{}                 = and [ hasWitness env t p | (w,p) <- ps ]\nimplAll env ps t@TFX{}                  = and [ hasWitness env t p | (w,p) <- ps ]\nimplAll env ps t@TOpt{}                 = all ((`elem` [qnIdentity,qnEq]) . tcname . snd) ps\nimplAll env ps t                        = False\n\nnoDots vi v                             = null (lookup' v $ selattrs vi) && null (lookup' v $ mutattrs vi)\n\nreplace ub lb cs                        = ubs ++ lbs ++ cs'\n  where\n    (vss,cs')                           = unzip $ map repl cs\n    vs                                  = nubBy (\\a b -> fst a == fst b) (concat vss)\n    ubs                                 = [ Cast info env (tUni v) t | (v,env) <- vs, Just t <- [lookup v ub] ]\n    lbs                                 = [ Cast info env t (tUni v) | (v,env) <- vs, Just t <- [lookup v lb] ]\n    info                                = noinfo 14\n\n    repl c@(Cast _ _ TUni{} TUni{})           = ([], c)\n    repl c@(Cast _ _ TUni{} (TOpt _ TUni{}))  = ([], c)\n    repl (Cast info env (TUni _ v) t)\n      | Just t' <- lookup v ub                = ([(v,env)], Cast info env t' t)\n    repl (Cast info env t (TUni _ v))\n      | Just t' <- lookup v lb                = ([(v,env)], Cast info env t t')\n    repl c@(Sub _ _ _ TUni{} TUni{})          = ([], c)\n    repl c@(Sub _ _ _ TUni{} (TOpt _ TUni{})) = ([], c)\n    repl (Sub info env w (TUni _ v) t)\n      | Just t' <- lookup v ub                = ([(v,env)], Sub info env w t' t)\n    repl (Sub info env w t (TUni _ v))\n      | Just t' <- lookup v lb                = ([(v,env)], Sub info env w t t')\n    repl c                                    = ([], c)\n\n\nsolveDots mutC selC selP cs             = do (eqs,css) <- unzip <$> mapM solveDot cs\n                                             return (concat eqs, concat css)\n  where solveDot c@(Mut _ env (TUni _ v) n _)\n          | Just w <- lookup (v,n) mutC = solveMutAttr w c >> return ([], [])\n        solveDot c@(Sel _ _ env (TUni _ v) n _)\n          | Just w <- lookup (v,n) selC = solveSelAttr w c\n          | Just w <- lookup (v,n) selP = solveSelWit w c\n        solveDot c                      = return ([], [c])\n\ninstance Pretty (TUni,Name) where\n    pretty (v,n)                        = pretty v Pretty.<> text \".\" Pretty.<> pretty n\n\nctxtReduce                              :: Env -> Constraints -> (Equations, [(Type,Type)])\nctxtReduce env cs                       = ctxtRed env (multiPBounds cs)\n\nmultiPBounds cs                         = Map.assocs $ f cs Map.empty\n  where\n    f []                                = Map.filter ((>1) . length)\n    f (Proto _ env w (TUni _ v) p : cs) = f cs . Map.insertWith (++) v [(w, p, qlevel env)]\n    f (_ : cs)                          = f cs\n\nctxtRed                                 :: Env -> [(TUni, [(Name, PCon, Int)])] -> (Equations, [(Type,Type)])\nctxtRed env multiPBnds                  = (concat eqs, concat unis)\n  where (eqs,unis)                      = unzip $ map red multiPBnds\n        red (v,wps)                     = imp v [] [] [] wps\n        imp v eq uni wps ((w,p,i):wps')\n          | (e,p',j):_ <- hits          = --trace (\"  *\" ++ prstr w ++ \" (level \" ++ show i ++ \") covered by \" ++ prstr e ++ \" (level \" ++ show j ++ \")\") $\n                                          imp v (Eqn (min i j) w (proto2type (tUni v) p) e : eq) ((tcargs p `zip` tcargs p') ++ uni) wps wps'\n          | otherwise                   = --trace (\"   (Not covered: \" ++ prstr p ++ \" in context \" ++ prstrs [ w | (w,_,_) <- wps++wps' ] ++ \")\") $\n                                          imp v eq uni ((w,p,i):wps) wps'\n          where hits                    = [ (wf $ eVar w', vsubst s p', j) | (w',p0,j) <- wps++wps', j <= i, Just (wf,p') <- [findAncestor env p0 (tcname p)] ]\n                s                       = [(tvSelf,tUni v)]\n        imp v eq uni wps []             = (reverse eq, uni)\n\nremove ws []                            = []\nremove ws (Proto _ _ w t p : cs)\n  | w `elem` ws                         = remove ws cs\nremove ws (c : cs)                      = c : remove ws cs\n\n\nfilterOut vs cs                         = filter preserve cs\n  where preserve (Seal _ _ (TUni _ v))  = v `notElem` vs\n        preserve _                      = True\n\n\n----------------------------------------------------------------------------------------------------------------------\n-- Misc.\n----------------------------------------------------------------------------------------------------------------------\n\npx0:px1:px2:_                           = xNames\n\napp tx e []                             = e\napp (TFun _ fx p k _) e es              = Lambda NoLoc p' k' (Call NoLoc e (exp2arg es (pArg p')) (kArg k')) fx\n  where (p',k')                         = (pPar pNames p, kPar attrKW k)\napp tx e es                             = Call NoLoc e (exp2arg es PosNil) KwdNil\n\napp2nd (Just Static) tx e es            = app tx e es\napp2nd (Just Property) tx e es          = app tx e es\napp2nd Nothing tx e es                  = app tx e es\napp2nd _ tx e []                        = e\napp2nd _ tx e es                        = Lambda NoLoc p' k' (Call NoLoc e (PosArg pSelf (exp2arg es pArgs)) (kArg k')) fx\n  where TFun _ fx p k _                 = tx                    -- If it already takes a first argument, it must be a function!\n        (p',k')                         = (pPar pNames p, kPar attrKW k)\n        PosArg pSelf pArgs              = pArg p'\n\nidwit env w t1 t2                       = mkEqn env w (wFun t1 t2) (eLambda [(px0,t1)] (eVar px0))\n\nrowFun PRow r1 r2                       = tFun fxPure (posRow (tTupleP r1) posNil) kwdNil (tTupleP r2)\nrowFun KRow r1 r2                       = tFun fxPure (posRow (tTupleK r1) posNil) kwdNil (tTupleK r2)\n\ncompWit t w1 w2                         = eLambda [(px0,t)] (eCallVar w1 [eCallVar w2 [eVar px0]])\n\nrowWit PRow n t r wt wr                 = eLambda [(px0,tTupleP $ posRow t r)] eTup\n  where eTup                            = Paren l0 $ Tuple l0 (PosArg e1 (PosStar e2)) KwdNil\n        e1                              = eCall (eVar wt) [DotI l0 (eVar px0) 0]\n        e2                              = eCall (eVar wr) [RestI l0 (eVar px0) 0]\nrowWit KRow n t r wt wr                 = eLambda [(px0,tTupleK $ kwdRow n t r)] eTup\n  where eTup                            = Paren l0 $ Tuple l0 PosNil (KwdArg n e1 (KwdStar e2))\n        e1                              = eCall (eVar wt) [Dot l0 (eVar px0) n]\n        e2                              = eCall (eVar wr) [Rest l0 (eVar px0) n]\n\nwFun t1 t2                              = tFun fxPure (posRow t1 posNil) kwdNil t2\n"
  },
  {
    "path": "compiler/lib/src/Acton/SourceProvider.hs",
    "content": "-- | Source access abstraction used by the compiler and LSP.\n-- Provides an overlay-first view of files while still allowing disk fallback.\n-- This is needed because the LSP server must read on-disk files and also\n-- accept unsaved buffer contents from the editor as overlays.\nmodule Acton.SourceProvider\n  ( SourceProvider(..)\n  , SourceSnapshot(..)\n  , diskSourceProvider\n  , readSource\n  ) where\n\nimport qualified Data.ByteString as B\nimport Data.Time.Clock (UTCTime)\nimport System.Directory (getModificationTime)\nimport System.IO (IOMode(ReadMode), hGetContents, hSetEncoding, openFile, utf8)\n\n-- | Snapshot of a file's contents.\n-- The same contents are available as decoded text and raw bytes.\ndata SourceSnapshot = SourceSnapshot\n  { ssText :: String        -- ^ UTF-8 decoded text view.\n  , ssBytes :: B.ByteString -- ^ Raw bytes for hashing or byte-precise work.\n  , ssIsOverlay :: Bool     -- ^ True when the snapshot comes from an overlay.\n  }\n\n-- | Interface for reading sources with optional in-memory overlays.\ndata SourceProvider = SourceProvider\n  { spReadOverlay :: FilePath -> IO (Maybe SourceSnapshot) -- ^ Return overlay contents for a path, if any.\n  , spReadFile :: FilePath -> IO SourceSnapshot            -- ^ Read contents from disk.\n  , spGetModTime :: FilePath -> IO UTCTime                 -- ^ Retrieve disk modification time.\n  }\n\n-- | Read a path, preferring overlay contents when available.\nreadSource :: SourceProvider -> FilePath -> IO SourceSnapshot\nreadSource sp path = do\n  mo <- spReadOverlay sp path\n  case mo of\n    Just snap -> return snap\n    Nothing -> spReadFile sp path\n\n-- | Default provider that reads directly from disk with no overlays.\ndiskSourceProvider :: SourceProvider\ndiskSourceProvider =\n  SourceProvider\n    { spReadOverlay = \\_ -> return Nothing\n    , spReadFile = \\path -> do\n        txt <- readFileUtf8 path\n        bytes <- B.readFile path\n        return SourceSnapshot\n          { ssText = txt\n          , ssBytes = bytes\n          , ssIsOverlay = False\n          }\n    , spGetModTime = getModificationTime\n    }\n\n-- | Read a UTF-8 text file without altering newlines or encoding.\nreadFileUtf8 :: FilePath -> IO String\nreadFileUtf8 path = do\n  h <- openFile path ReadMode\n  hSetEncoding h utf8\n  hGetContents h\n"
  },
  {
    "path": "compiler/lib/src/Acton/Subst.hs",
    "content": "-- Copyright (C) 2019-2021 Data Ductus AB\n--\n-- Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:\n--\n-- 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.\n--\n-- 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.\n--\n-- 3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission.\n--\n-- THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS \"AS IS\" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n--\n\n{-# LANGUAGE FlexibleInstances #-}\nmodule Acton.Subst where\n\nimport Control.Monad.State.Strict\n\nimport Acton.Syntax\nimport Acton.Builtin\nimport Acton.Printer\nimport Utils\n\n\naddSelf                                 :: Type -> Maybe Deco -> Type\naddSelf (TFun l x p k t) (Just NoDec)   = TFun l x (posRow tSelf p) k t\naddSelf t _                             = t\n\ndropSelf                                :: Type -> Deco -> Type\ndropSelf (TFun l x p k t) NoDec\n  | TRow _ _ _ _ p' <- p                = TFun l x p' k t\n  | TRow _ _ _ _ k' <- k                = TFun l x p k' t\ndropSelf t _                            = t\n\nselfType                                :: PosPar -> KwdPar -> Deco -> Type\nselfType p k NoDec\n  | TRow _ _ _ t _ <- prowOf p          = t\n  | TRow _ _ _ t _ <- krowOf k          = t\nselfType _ _ _                          = tSelf\n\nqualbound q                         = [ v | QBind v ps <- q, not $ null ps ]\n\n\n-- VFree ----------------------------------------------------------------------------------------------\n\nclass VFree a where\n    vfree                           :: a -> [TVar]\n\ninstance VFree a => VFree [a] where\n    vfree                           = concatMap vfree\n\ninstance VFree a => VFree (Maybe a) where\n    vfree                           = maybe [] vfree\n\ninstance VFree a => VFree (Name,a) where\n    vfree (n, t)                    = vfree t\n\ninstance VFree Type where\n    vfree (TVar _ v)                = [v]\n    vfree (TCon _ c)                = vfree c\n    vfree (TFun _ fx p k t)         = vfree fx ++ vfree p ++ vfree k ++ vfree t\n    vfree (TTuple _ p k)            = vfree p ++ vfree k\n    vfree (TOpt _ t)                = vfree t\n    vfree (TRow _ k n t r)          = vfree t ++ vfree r\n    vfree (TStar _ k r)             = vfree r\n    vfree _                         = []\n\ninstance VFree TCon where\n    vfree (TC n ts)                 = vfree ts\n\ninstance VFree QBind where\n    vfree (QBind v cs)              = vfree cs\n\ninstance VFree TSchema where\n    vfree (TSchema _ q t)           = (vfree q ++ vfree t) \\\\ qbound q\n\ninstance VFree PosPar where\n    vfree (PosPar n t e p)          = vfree t ++ vfree p\n    vfree (PosSTAR n t)             = vfree t\n    vfree PosNIL                    = []\n\ninstance VFree KwdPar where\n    vfree (KwdPar n t e k)          = vfree t ++ vfree k\n    vfree (KwdSTAR n t)             = vfree t\n    vfree KwdNIL                    = []\n\ninstance VFree Decl where\n    vfree (Def _ n q p k a ss de fx doc) = vfree q ++ vfree p ++ vfree k ++ vfree a ++ vfree ss ++ vfree fx\n    vfree (Actor _ n q p k ss doc)       = vfree q ++ vfree p ++ vfree k ++ vfree ss\n    vfree (Class _ n q bs ss doc)        = vfree q ++ vfree bs ++ vfree ss\n    vfree (Protocol _ n q bs ss doc)     = vfree q ++ vfree bs ++ vfree ss\n    vfree (Extension _ q c bs ss doc)    = vfree q ++ vfree c ++ vfree bs ++ vfree ss\n\ninstance VFree Stmt where\n    vfree (Expr _ e)               = vfree e\n    vfree (Assign _ ps e)          = vfree ps ++ vfree e\n    vfree (MutAssign _ t e)        = vfree t ++ vfree e\n    vfree (AugAssign _ t op e)     = vfree t ++ vfree e\n    vfree (Assert _ e mbe)         = vfree e ++ vfree mbe\n    vfree (Delete _ t)             = vfree t\n    vfree (Return _ mbe)           = vfree mbe\n    vfree (Raise _ e)              = vfree e\n    vfree (If _ bs els)            = vfree bs ++ vfree els\n    vfree (While _ e b els)        = vfree e ++ vfree b ++ vfree els\n    vfree (For _ p e b els)        = vfree p ++ vfree e ++ vfree b ++ vfree els\n    vfree (Try _ b hs els fin)     = vfree b ++ vfree hs ++ vfree els ++ vfree fin\n    vfree (With _ is b)            = vfree is ++ vfree b\n    vfree (VarAssign _ ps e)       = vfree ps ++ vfree e\n    vfree (After _ e e')           = vfree e ++ vfree e'\n    vfree (Decl _ ds)              = vfree ds\n    vfree (Signature _ ns tsc d)   = vfree tsc\n    vfree s                        = []\n\ninstance VFree Branch where\n    vfree (Branch e b)              = vfree e ++ vfree b\n\ninstance VFree Handler where\n    vfree (Handler ex b)            = vfree b\n\ninstance VFree WithItem where\n    vfree (WithItem e p)            = vfree e ++ vfree p\n\ninstance VFree Expr where\n    vfree (Call l e p k)            = vfree e ++ vfree p ++ vfree k\n    vfree (TApp l e ts)             = vfree e ++ vfree ts\n    vfree (Let l ss e)              = vfree ss ++ vfree e\n    vfree (Async l e)               = vfree e\n    vfree (Await l e)               = vfree e\n    vfree (Index l e ix)            = vfree e ++ vfree ix\n    vfree (Slice l e sl)            = vfree e ++ vfree sl\n    vfree (Cond l e1 cond e2)       = vfree e1 ++ vfree cond ++ vfree e2\n    vfree (IsInstance l e c)        = vfree e\n    vfree (BinOp l e1 op e2)        = vfree e1 ++ vfree e2\n    vfree (CompOp l e ops)          = vfree e ++ vfree ops\n    vfree (UnOp l op e)             = vfree e\n    vfree (Dot l e n)               = vfree e\n    vfree (Rest l e n)              = vfree e\n    vfree (DotI l e i)              = vfree e\n    vfree (RestI l e i)             = vfree e\n    vfree (Lambda l p k e fx)       = vfree p ++ vfree k ++ vfree e ++ vfree fx\n    vfree (Yield l e)               = vfree e\n    vfree (YieldFrom l e)           = vfree e\n    vfree (Tuple l p k)             = vfree p ++ vfree k\n    vfree (List l es)               = vfree es\n    vfree (ListComp l e c)          = vfree e ++ vfree c\n    vfree (Dict l as)               = vfree as\n    vfree (DictComp l a c)          = vfree a ++ vfree c\n    vfree (Set l es)                = vfree es\n    vfree (SetComp l e c)           = vfree e ++ vfree c\n    vfree (Paren l e)               = vfree e\n    vfree e                         = []\n\ninstance VFree Pattern where\n    vfree (PWild _ t)               = vfree t\n    vfree (PVar _ n t)              = vfree t\n    vfree (PParen _ p)              = vfree p\n    vfree (PTuple _ p k)            = vfree p ++ vfree k\n    vfree (PList _ ps p)            = vfree ps ++ vfree p\n\ninstance VFree PosPat where\n    vfree (PosPat p pp)             = vfree p ++ vfree pp\n    vfree (PosPatStar p)            = vfree p\n    vfree PosPatNil                 = []\n\ninstance VFree KwdPat where\n    vfree (KwdPat n p kp)           = vfree p ++ vfree kp\n    vfree (KwdPatStar p)            = vfree p\n    vfree KwdPatNil                 = []\n\ninstance VFree PosArg where\n    vfree (PosArg e p)              = vfree e ++ vfree p\n    vfree (PosStar e)               = vfree e\n    vfree PosNil                    = []\n\ninstance VFree KwdArg where\n    vfree (KwdArg n e k)            = vfree e ++ vfree k\n    vfree (KwdStar e)               = vfree e\n    vfree KwdNil                    = []\n\ninstance VFree Elem where\n    vfree (Elem e)                  = vfree e\n    vfree (Star e)                  = vfree e\n\ninstance VFree Assoc where\n    vfree (Assoc k v)               = vfree k ++ vfree v\n    vfree (StarStar e)              = vfree e\n\ninstance VFree Comp where\n    vfree (CompFor _ p e c)         = vfree p ++ vfree e ++ vfree c\n    vfree (CompIf _ e c)            = vfree e ++ vfree c\n    vfree NoComp                    = []\n\ninstance VFree Sliz where\n    vfree (Sliz _ e1 e2 e3)         = vfree e1 ++ vfree e2 ++ vfree e3\n\ninstance VFree OpArg where\n    vfree (OpArg op e)              = vfree e\n\n\n-- VSubst ---------------------------------------------------------------------------------------------\n\nclass VSubst a where\n    vsubst                          :: Substitution -> a -> a\n\ninstance VSubst a => VSubst [a] where\n    vsubst s                        = map $ vsubst s\n\ninstance VSubst a => VSubst (Maybe a) where\n    vsubst s                        = fmap $ vsubst s\n\ninstance VSubst a => VSubst (Name,a) where\n    vsubst s (n, t)                 = (n, vsubst s t)\n\ninstance VSubst Type where\n    vsubst s (TVar l v)             = case lookup v s of\n                                        Just t ->  t\n                                        Nothing -> TVar l v\n    vsubst s (TUni l u)             = TUni l u\n    vsubst s (TCon l c)             = TCon l (vsubst s c)\n    vsubst s (TFun l fx p k t)      = TFun l (vsubst s fx) (vsubst s p) (vsubst s k) (vsubst s t)\n    vsubst s (TTuple l p k)         = TTuple l (vsubst s p) (vsubst s k)\n    vsubst s (TOpt l t)             = case vsubst s t of\n                                         t'@TOpt{} -> t'\n                                         t' -> TOpt l t'\n    vsubst s (TRow l k n t r)       = TRow l k n (vsubst s t) (vsubst s r)\n    vsubst s (TStar l k r)          = TStar l k (vsubst s r)\n    vsubst s (TNone l)              = TNone l\n    vsubst s (TWild l)              = TWild l\n    vsubst s (TNil l k)             = TNil l k\n    vsubst s (TFX l fx)             = TFX l fx\n\ninstance VSubst TCon where\n    vsubst s (TC n ts)              = TC n (vsubst s ts)\n\ninstance VSubst TVar where\n    vsubst s v                      = case lookup v s of\n                                         Just (TVar _ v') -> v'\n                                         _ -> v\n\ninstance VSubst TSchema where\n    vsubst s (TSchema l q t)        = TSchema l (vsubst s' q) (vsubst s' t)\n      where s'                      = quantsubst s q (vfree t)\n\nquantsubst s [] vs                  = s\nquantsubst s q vs                   = alpha ++ pruned\n  where pruned                      = s `exclude` qbound q\n        new                         = nub $ vfree (rng pruned)\n        clash                       = new `intersect` qbound q\n        alpha                       = clash `zip` map tVar (tvarSupply \\\\ avoid)\n        avoid                       = new ++ vfree q ++ vs\n\ninstance VSubst QBind where\n    vsubst s (QBind v ts)           = QBind (vsubst s v) (vsubst s ts)\n\ninstance VSubst PosPar where\n    vsubst s (PosPar n t e p)       = PosPar n (vsubst s t) e (vsubst s p)\n    vsubst s (PosSTAR n t)          = PosSTAR n (vsubst s t)\n    vsubst s PosNIL                 = PosNIL\n\ninstance VSubst KwdPar where\n    vsubst s (KwdPar n t e k)       = KwdPar n (vsubst s t) e (vsubst s k)\n    vsubst s (KwdSTAR n t)          = KwdSTAR n (vsubst s t)\n    vsubst s KwdNIL                 = KwdNIL\n\ninstance VSubst Decl where\n    vsubst s (Def l n q p k a ss de fx doc) = Def l n (vsubst r q) (vsubst r p) (vsubst r k) (vsubst r a) (vsubst r ss) de (vsubst r fx) doc\n      where r                               = quantsubst s q (vfree p ++ vfree k ++ vfree a ++ vfree ss ++ vfree fx)\n    vsubst s (Actor l n q p k ss doc)       = Actor l n (vsubst r q) (vsubst r p) (vsubst r k) (vsubst r ss) doc\n      where r                               = quantsubst s q (vfree p ++ vfree k ++ vfree ss)\n    vsubst s (Class l n q bs ss doc)        = Class l n (vsubst s q) (vsubst s bs) (vsubst s ss) doc\n      where r                               = quantsubst s q (vfree bs ++ vfree ss)\n    vsubst s (Protocol l n q bs ss doc)     = Protocol l n (vsubst s q) (vsubst s bs) (vsubst s ss) doc\n      where r                               = quantsubst s q (vfree bs ++ vfree ss)\n    vsubst s (Extension l q c bs ss doc)    = Extension l (vsubst s q) (vsubst s c) (vsubst s bs) (vsubst s ss) doc\n      where r                               = quantsubst s q (vfree c ++ vfree bs ++ vfree ss)\n\ninstance VSubst Stmt where\n    vsubst s (Expr l e)             = Expr l (vsubst s e)\n    vsubst s (Assign l ps e)        = Assign l (vsubst s ps) (vsubst s e)\n    vsubst s (MutAssign l t e)      = MutAssign l (vsubst s t) (vsubst s e)\n    vsubst s (AugAssign l t op e)   = AugAssign l (vsubst s t) op (vsubst s e)\n    vsubst s (Assert l e mbe)       = Assert l (vsubst s e) (vsubst s mbe)\n    vsubst s (Delete l t)           = Delete l (vsubst s t)\n    vsubst s (Return l mbe)         = Return l (vsubst s mbe)\n    vsubst s (Raise l e)            = Raise l (vsubst s e)\n    vsubst s (If l bs els)          = If l (vsubst s bs) (vsubst s els)\n    vsubst s (While l e b els)      = While l (vsubst s e) (vsubst s b) (vsubst s els)\n    vsubst s (For l p e b els)      = For l (vsubst s p) (vsubst s e) (vsubst s b) (vsubst s els)\n    vsubst s (Try l b hs els fin)   = Try l (vsubst s b) (vsubst s hs) (vsubst s els) (vsubst s fin)\n    vsubst s (With l is b)          = With l (vsubst s is) (vsubst s b)\n    vsubst s (VarAssign l ps e)     = VarAssign l (vsubst s ps) (vsubst s e)\n    vsubst s (After l e e')         = After l (vsubst s e) (vsubst s e')\n    vsubst s (Decl l ds)            = Decl l (vsubst s ds)\n    vsubst s (Signature l ns tsc d) = Signature l ns (vsubst s tsc) d\n    vsubst s stmt                   = stmt\n\ninstance VSubst Expr where\n    vsubst s (Call l e p k)         = Call l (vsubst s e) (vsubst s p) (vsubst s k)\n    vsubst s (TApp l e ts)          = TApp l (vsubst s e) (vsubst s ts)\n    vsubst s (Let l ss e)           = Let l (vsubst s ss) (vsubst s e)\n    vsubst s (Async l e)            = Async l (vsubst s e)\n    vsubst s (Await l e)            = Await l (vsubst s e)\n    vsubst s (Index l e ix)         = Index l (vsubst s e) (vsubst s ix)\n    vsubst s (Slice l e sl)         = Slice l (vsubst s e) (vsubst s sl)\n    vsubst s (Cond l e1 cond e2)    = Cond l (vsubst s e1) (vsubst s cond) (vsubst s e2)\n    vsubst s (IsInstance l e c)     = IsInstance l (vsubst s e) c\n    vsubst s (BinOp l e1 op e2)     = BinOp l (vsubst s e1) op (vsubst s e2)\n    vsubst s (CompOp l e ops)       = CompOp l (vsubst s e) (vsubst s ops)\n    vsubst s (UnOp l op e)          = UnOp l op (vsubst s e)\n    vsubst s (Dot l e n)            = Dot l (vsubst s e) n\n    vsubst s (Rest l e n)           = Rest l (vsubst s e) n\n    vsubst s (DotI l e i)           = DotI l (vsubst s e) i\n    vsubst s (RestI l e i)          = RestI l (vsubst s e) i\n    vsubst s (Lambda l p k e fx)    = Lambda l (vsubst s p) (vsubst s k) (vsubst s e) (vsubst s fx)\n    vsubst s (Yield l e)            = Yield l (vsubst s e)\n    vsubst s (YieldFrom l e)        = YieldFrom l (vsubst s e)\n    vsubst s (Tuple l p k)          = Tuple l (vsubst s p) (vsubst s k)\n    vsubst s (List l es)            = List l (vsubst s es)\n    vsubst s (ListComp l e c)       = ListComp l (vsubst s e) (vsubst s c)\n    vsubst s (Dict l as)            = Dict l (vsubst s as)\n    vsubst s (DictComp l a c)       = DictComp l (vsubst s a) (vsubst s c)\n    vsubst s (Set l es)             = Set l (vsubst s es)\n    vsubst s (SetComp l e c)        = SetComp l (vsubst s e) (vsubst s c)\n    vsubst s (Paren l e)            = Paren l (vsubst s e)\n    vsubst s e                      = e\n\ninstance VSubst Branch where\n    vsubst s (Branch e b)           = Branch (vsubst s e) (vsubst s b)\n\ninstance VSubst Pattern where\n    vsubst s (PWild l t)            = PWild l (vsubst s t)\n    vsubst s (PVar l n t)           = PVar l n (vsubst s t)\n    vsubst s (PParen l p)           = PParen l (vsubst s p)\n    vsubst s (PTuple l p k)         = PTuple l (vsubst s p) (vsubst s k)\n    vsubst s (PList l ps p)         = PList l (vsubst s ps) (vsubst s p)\n    \ninstance VSubst PosPat where\n    vsubst s (PosPat p pp)          = PosPat (vsubst s p) (vsubst s pp)\n    vsubst s (PosPatStar p)         = PosPatStar (vsubst s p)\n    vsubst s PosPatNil              = PosPatNil\n\ninstance VSubst KwdPat where\n    vsubst s (KwdPat n p kp)        = KwdPat n (vsubst s p) (vsubst s kp)\n    vsubst s (KwdPatStar p)         = KwdPatStar (vsubst s p)\n    vsubst s KwdPatNil              = KwdPatNil\n\ninstance VSubst Handler where\n    vsubst s (Handler ex b)         = Handler ex (vsubst s b)\n\ninstance VSubst WithItem where\n    vsubst s (WithItem e p)         = WithItem (vsubst s e) (vsubst s p)\n    \ninstance VSubst PosArg where\n    vsubst s (PosArg e p)           = PosArg (vsubst s e) (vsubst s p)\n    vsubst s (PosStar e)            = PosStar (vsubst s e)\n    vsubst s PosNil                 = PosNil\n\ninstance VSubst KwdArg where\n    vsubst s (KwdArg n e k)         = KwdArg n (vsubst s e) (vsubst s k)\n    vsubst s (KwdStar e)            = KwdStar (vsubst s e)\n    vsubst s KwdNil                 = KwdNil\n\ninstance VSubst Assoc where\n    vsubst s (Assoc k v)            = Assoc (vsubst s k) (vsubst s v)\n    vsubst s (StarStar e)           = StarStar (vsubst s e)\n\ninstance VSubst Elem where\n    vsubst s (Elem e)               = Elem (vsubst s e)\n    vsubst s (Star e)               = Star (vsubst s e)\n\ninstance VSubst Comp where\n    vsubst s (CompFor l p e c)      = CompFor l (vsubst s p) (vsubst s e) (vsubst s c)\n    vsubst s (CompIf l e c)         = CompIf l (vsubst s e) (vsubst s c)\n    vsubst s NoComp                 = NoComp\n\ninstance VSubst Sliz where\n    vsubst s (Sliz l e1 e2 e3)      = Sliz l (vsubst s e1) (vsubst s e2) (vsubst s e3)\n\ninstance VSubst OpArg where\n    vsubst s (OpArg op e)           = OpArg op (vsubst s e)\n\n\n-- UFree ----------------------------------------------------------------------------------------------\n\nclass UFree t where\n    ufree                           :: t -> [TUni]\n\ninstance UFree a => UFree (Name,a) where\n    ufree (n, t)                    = ufree t\n\ninstance (UFree a, UFree b) => UFree (QName,a,b) where\n    ufree (n, t, u)                 = ufree t ++ ufree u\n\ninstance UFree a => UFree [a] where\n    ufree                           = concat . map ufree\n\ninstance UFree a => UFree (Maybe a) where\n    ufree                           = maybe [] ufree\n\ninstance UFree TSchema where\n    ufree (TSchema _ q t)           = ufree q ++ ufree t\n\ninstance UFree TVar where\n    ufree v                         = []\n        \ninstance UFree TCon where\n    ufree (TC n ts)                 = ufree ts\n\ninstance UFree QBind where\n    ufree (QBind v cs)              = ufree cs\n\ninstance UFree Type where\n    ufree (TUni _ u)                = [u]\n    ufree (TVar _ v)                = []\n    ufree (TCon _ c)                = ufree c\n    ufree (TFun _ fx p k t)         = ufree fx ++ ufree p ++ ufree k ++ ufree t\n    ufree (TTuple _ p k)            = ufree p ++ ufree k\n    ufree (TOpt _ t)                = ufree t\n    ufree (TNone _)                 = []\n    ufree (TWild _)                 = []\n    ufree (TNil _ _)                = []\n    ufree (TRow _ _ _ t r)          = ufree t ++ ufree r\n    ufree (TStar _ _ r)             = ufree r\n    ufree (TFX l fx)                = []\n\ninstance UFree PosPar where\n    ufree (PosPar n t e p)          = ufree t ++ ufree p\n    ufree (PosSTAR n t)             = ufree t\n    ufree PosNIL                    = []\n\ninstance UFree KwdPar where\n    ufree (KwdPar n t e p)          = ufree t ++ ufree p\n    ufree (KwdSTAR n t)             = ufree t\n    ufree KwdNIL                    = []\n\ninstance UFree Decl where\n    ufree (Def _ n q p k a ss de fx _)  = ufree q ++ ufree p ++ ufree k ++ ufree a ++ ufree ss ++ ufree fx\n    ufree (Actor _ n q p k ss _)        = ufree q ++ ufree p ++ ufree k ++ ufree ss\n    ufree (Class _ n q bs ss _)         = ufree q ++ ufree bs ++ ufree ss\n    ufree (Protocol _ n q bs ss _)      = ufree q ++ ufree bs ++ ufree ss\n    ufree (Extension _ q c bs ss _)     = ufree q ++ ufree c ++ ufree bs ++ ufree ss\n\ninstance UFree Stmt where\n    ufree (Expr _ e)                = ufree e\n    ufree (Assign _ ps e)           = ufree ps ++ ufree e\n    ufree (MutAssign _ t e)         = ufree t ++ ufree e\n    ufree (AugAssign _ t op e)      = ufree t ++ ufree e\n    ufree (Assert _ e mbe)          = ufree e ++ ufree mbe\n    ufree (Delete _ t)              = ufree t\n    ufree (Return _ mbe)            = ufree mbe\n    ufree (Raise _ e)               = ufree e\n    ufree (If _ bs els)             = ufree bs ++ ufree els\n    ufree (While _ e b els)         = ufree e ++ ufree b ++ ufree els\n    ufree (For _ p e b els)         = ufree p ++ ufree e ++ ufree b ++ ufree els\n    ufree (Try _ b hs els fin)      = ufree b ++ ufree hs ++ ufree els ++ ufree fin\n    ufree (With _ is b)             = ufree is ++ ufree b\n    ufree (VarAssign _ ps e)        = ufree ps ++ ufree e\n    ufree (After _ e e')            = ufree e ++ ufree e'\n    ufree (Decl _ ds)               = ufree ds\n    ufree (Signature _ ns tsc d)    = ufree tsc\n    ufree s                         = []\n\ninstance UFree Expr where\n    ufree (Call l e p k)            = ufree e ++ ufree p ++ ufree k\n    ufree (TApp l e ts)             = ufree e ++ ufree ts\n    ufree (Let l ss e)              = ufree ss ++ ufree e\n    ufree (Async l e)               = ufree e\n    ufree (Await l e)               = ufree e\n    ufree (Index l e ix)            = ufree e ++ ufree ix\n    ufree (Slice l e sl)            = ufree e ++ ufree sl\n    ufree (Cond l e1 cond e2)       = ufree e1 ++ ufree cond ++ ufree e2\n    ufree (IsInstance l e c)        = ufree e\n    ufree (BinOp l e1 op e2)        = ufree e1 ++ ufree e2\n    ufree (CompOp l e ops)          = ufree e ++ ufree ops\n    ufree (UnOp l op e)             = ufree e\n    ufree (Dot l e n)               = ufree e\n    ufree (Rest l e n)              = ufree e\n    ufree (DotI l e i)              = ufree e\n    ufree (RestI l e i)             = ufree e\n    ufree (Lambda l p k e fx)       = ufree p ++ ufree k ++ ufree e ++ ufree fx\n    ufree (Yield l e)               = ufree e\n    ufree (YieldFrom l e)           = ufree e\n    ufree (Tuple l p k)             = ufree p ++ ufree k\n    ufree (List l es)               = ufree es\n    ufree (ListComp l e c)          = ufree e ++ ufree c\n    ufree (Dict l as)               = ufree as\n    ufree (DictComp l a c)          = ufree a ++ ufree c\n    ufree (Set l es)                = ufree es\n    ufree (SetComp l e c)           = ufree e ++ ufree c\n    ufree (Paren l e)               = ufree e\n    ufree e                         = []\n\ninstance UFree Pattern where\n    ufree (PWild _ t)               = ufree t\n    ufree (PVar _ n t)              = ufree t\n    ufree (PParen _ p)              = ufree p\n    ufree (PTuple _ p k)            = ufree p ++ ufree k\n    ufree (PList _ ps p)            = ufree ps ++ ufree p\n\ninstance UFree PosPat where\n    ufree (PosPat p pp)             = ufree p ++ ufree pp\n    ufree (PosPatStar p)            = ufree p\n    ufree PosPatNil                 = []\n\ninstance UFree KwdPat where\n    ufree (KwdPat n p kp)           = ufree p ++ ufree kp\n    ufree (KwdPatStar p)            = ufree p\n    ufree KwdPatNil                 = []\n\ninstance UFree Branch where\n    ufree (Branch e b)              = ufree e ++ ufree b\n\ninstance UFree Handler where\n    ufree (Handler ex b)            = ufree b\n\ninstance UFree WithItem where\n    ufree (WithItem e p)            = ufree e ++ ufree p\n\ninstance UFree PosArg where\n    ufree (PosArg e p)              = ufree e ++ ufree p\n    ufree (PosStar e)               = ufree e\n    ufree PosNil                    = []\n\ninstance UFree KwdArg where\n    ufree (KwdArg n e k)            = ufree e ++ ufree k\n    ufree (KwdStar e)               = ufree e\n    ufree KwdNil                    = []\n\ninstance UFree Elem where\n    ufree (Elem e)                  = ufree e\n    ufree (Star e)                  = ufree e\n\ninstance UFree Assoc where\n    ufree (Assoc k v)               = ufree k ++ ufree v\n    ufree (StarStar e)              = ufree e\n\ninstance UFree Comp where\n    ufree (CompFor _ p e c)         = ufree p ++ ufree e ++ ufree c\n    ufree (CompIf _ e c)            = ufree e ++ ufree c\n    ufree NoComp                    = []\n\ninstance UFree Sliz where\n    ufree (Sliz _ e1 e2 e3)         = ufree e1 ++ ufree e2 ++ ufree e3\n\ninstance UFree OpArg where\n    ufree (OpArg op e)              = ufree e\n\n\n-- Polarity -------------------------------------------------------------------------------------------\n\nclass UFree a => Polarity a where\n    polvars                         :: a -> ([TUni],[TUni])\n\n(p,n) `polcat` (p',n')              = (p++p', n++n')\n\npolnil                              = ([], [])\n\npolnull (p,n)                       = null p && null n\n\npolneg (p,n)                        = (n,p)\n\n(p,n) `polminus` (p',n')            = (p\\\\p', n\\\\n')\n\ninstance Polarity Type where\n    polvars (TUni _ u)              = ([u],[])\n    polvars (TVar _ v)              = polnil\n    polvars (TCon _ c)              = polvars c\n    polvars (TFun _ fx p k t)       = polvars fx `polcat` polvars t `polcat` polneg (polvars p `polcat` polvars k)\n    polvars (TTuple _ p k)          = polvars p `polcat` polvars k\n    polvars (TOpt _ t)              = polvars t\n    polvars (TNone _)               = polnil\n    polvars (TWild _)               = polnil\n    polvars (TNil _ _)              = polnil\n    polvars (TRow _ _ _ t r)        = polvars t `polcat` polvars r\n    polvars (TStar _ _ r)           = polvars r\n    polvars (TFX l fx)              = polnil\n\ninvvars x                           = (vs, vs)\n  where vs                          = ufree x\n\ncovariant                           = [qnSetT,qnDict,qnList]                -- Ignore mutation for now!\n\ninstance Polarity TCon where\n    polvars (TC c ts)\n      | c `elem` covariant          = (vs,[])\n      | otherwise                   = (vs,vs)\n      where vs                      = ufree ts\n\ninstance Polarity QBind where\n    polvars (QBind v cs)            = (vs,vs) where vs = ufree cs\n\ninstance Polarity TSchema where\n    polvars (TSchema _ q t)         = polvars q `polcat` polvars t\n\ninstance (Polarity a) => Polarity (Maybe a) where\n    polvars                         = maybe polnil polvars\n\ninstance (Polarity a) => Polarity [a] where\n    polvars                         = foldr polcat polnil . map polvars\n\n\n-- Does Self occur positively?\nposself (TVar _ v)                  = v == tvSelf\nposself (TCon _ c)                  = any posself (tcargs c)\nposself (TFun _ fx p k t)           = any posself [fx,t] || any negself [p,k]\nposself (TTuple _ p k)              = any posself [p,k]\nposself (TOpt _ t)                  = posself t\nposself (TRow _ _ _ t r)            = any posself [t,r]\nposself (TStar _ _ r)               = posself r\nposself _                           = False\n\n-- Does Self occur negatively?\nnegself (TCon _ c)                  = any negself (tcargs c)\nnegself (TFun _ fx p k t)           = any negself [fx,t] || any posself [p,k]\nnegself (TTuple _ p k)              = any negself [p,k]\nnegself (TOpt _ t)                  = negself t\nnegself (TRow _ _ _ t r)            = any negself [t,r]\nnegself (TStar _ _ r)               = negself r\nnegself _                           = False\n\n\n-- Tailvars -------------------------------------------------------------------------------------------\n\nclass (UFree a) => Tailvars a where\n    -- Find free univars of kind PRow or KRow (for the purpose of defaulting them to TNil)\n    tailvars                        :: a -> [TUni]\n\ninstance Tailvars Type where\n    tailvars (TCon _ c)             = tailvars c\n    tailvars (TFun _ fx p k t)      = tailvars fx ++ tailvars' p ++ tailvars' k ++ tailvars t\n    tailvars (TTuple _ p k)\n      | TUni{} <- p, TNil{} <- k    = []    -- Exclude open * tuples\n      | TNil{} <- p, TUni{} <- k    = []    -- Exclude open ** tuples\n      | otherwise                   = tailvars' p ++ tailvars' k\n    tailvars (TOpt _ t)             = tailvars t\n    tailvars _                      = []\n\ntailvars' (TRow _ _ _ t r)          = tailvars t ++ tailvars' r\ntailvars' (TStar _ _ r)             = tailvars r\ntailvars' (TNil _ _)                = []\ntailvars' (TUni _ u)                = [u]\n\ninstance Tailvars TCon where\n    tailvars (TC c ts)              = tailvars ts\n\ninstance Tailvars QBind where\n    tailvars (QBind v cs)           = tailvars cs\n\ninstance Tailvars TSchema where\n    tailvars (TSchema _ q t)        = tailvars q ++ tailvars t\n\ninstance (Tailvars a) => Tailvars (Maybe a) where\n    tailvars                        = maybe [] tailvars\n\ninstance (Tailvars a) => Tailvars [a] where\n    tailvars                        = concat . map tailvars\n\nschematic (TCon _ tc)               = tCon (schematic' tc)\nschematic (TFun _ _ _ _ _)          = tFun tWild tWild tWild tWild\nschematic (TTuple _ _ _)            = tTuple tWild tWild\nschematic (TOpt _ _)                = tOpt tWild\nschematic (TRow _ k n _ r)          = tRow k n tWild (schematic r)\nschematic (TStar _ k _)             = tStar k tWild\nschematic t                         = t\n\nschematic' (TC n ts)                = TC n [ tWild | _ <- ts ]\n\n\nclass UWild a where\n    uwild                           :: a -> a\n\ninstance UWild a => UWild [a] where\n    uwild                           = map uwild\n\ninstance UWild a => UWild (Maybe a) where\n    uwild                           = fmap uwild\n\ninstance UWild TCon where\n    uwild (TC n ts)                 = TC n (uwild ts)\n\ninstance UWild Type where\n    uwild (TUni l u)                = tWild\n    uwild (TCon l c)                = TCon l (uwild c)\n    uwild (TFun l fx p k t)         = TFun l fx (uwild p) (uwild k) (uwild t)\n    uwild (TTuple l p k)            = TTuple l (uwild p) (uwild k)\n    uwild (TOpt l t)                = TOpt l (uwild t)\n    uwild (TRow l k n t r)          = TRow l k n (uwild t) (uwild r)\n    uwild (TStar l k r)             = TStar l k (uwild r)\n    uwild t                         = t\n\ninstance UWild TSchema where\n    uwild (TSchema l q t)           = TSchema l (uwild q) (uwild t)\n\ninstance UWild QBind where\n    uwild (QBind v cs)              = QBind v (uwild cs)\n\ninstance (UWild a, UWild b) => UWild (QName,a,b) where\n    uwild (n, t, u)                 = (n, uwild t, uwild u)\n"
  },
  {
    "path": "compiler/lib/src/Acton/Syntax.hs",
    "content": "-- Copyright (C) 2019-2021 Data Ductus AB\n--\n-- Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:\n--\n-- 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.\n--\n-- 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.\n--\n-- 3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission.\n--\n-- THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS \"AS IS\" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n--\n\n{-# LANGUAGE MultiParamTypeClasses, FlexibleInstances, FlexibleContexts, DeriveGeneric, DeriveAnyClass #-}\nmodule Acton.Syntax where\n\nimport Utils\nimport qualified Data.Binary\nimport qualified Data.Set\nimport qualified Data.HashMap.Strict as M\nimport qualified Data.Hashable\nimport Data.Char\nimport GHC.Generics (Generic)\nimport Control.DeepSeq\nimport Prelude hiding((<>))\n\nversion :: [Int]\nversion = [0,17]\n\ndata Module     = Module        { modname::ModName, imps::[Import], mdoc::Maybe String, mbody::Suite } deriving (Eq,Show,Generic,NFData)\n\ndata Import     = Import        { iloc::SrcLoc, moduls::[ModuleItem] }\n                | FromImport    { iloc::SrcLoc, modul::ModRef, items::[ImportItem] }\n                | FromImportAll { iloc::SrcLoc, modul::ModRef }\n                deriving (Show,Read,NFData,Generic)\n\ntype Suite      = [Stmt]\n\ndata Stmt       = Expr          { sloc::SrcLoc, expr::Expr }\n                | Assign        { sloc::SrcLoc, patterns::[Pattern], expr::Expr }\n                | MutAssign     { sloc::SrcLoc, target::Target, expr::Expr }\n                | AugAssign     { sloc::SrcLoc, target::Target, aop::Aug, expr::Expr }\n                | Assert        { sloc::SrcLoc, expr::Expr, optExpr::Maybe Expr }\n                | Pass          { sloc::SrcLoc }\n                | Delete        { sloc::SrcLoc, target::Target }\n                | Return        { sloc::SrcLoc, optExpr::Maybe Expr }\n                | Raise         { sloc::SrcLoc, expr::Expr }\n                | Break         { sloc::SrcLoc }\n                | Continue      { sloc::SrcLoc }\n                | If            { sloc::SrcLoc, branches::[Branch], els::Suite }\n                | While         { sloc::SrcLoc, expr::Expr, body::Suite, els::Suite }\n                | For           { sloc::SrcLoc, pattern::Pattern, expr::Expr, body::Suite, els::Suite }\n                | Try           { sloc::SrcLoc, body::Suite, handlers::[Handler], els::Suite, finally::Suite }\n                | With          { sloc::SrcLoc, witems::[WithItem], body::Suite }\n                | Data          { sloc::SrcLoc, mbpat::Maybe Pattern, dsuite::Suite }\n                | VarAssign     { sloc::SrcLoc, patterns::[Pattern], expr::Expr }\n                | After         { sloc::SrcLoc, expr::Expr, expr2::Expr }\n                | Signature     { sloc::SrcLoc, vars::[Name], typ::TSchema, dec::Deco }\n                | Decl          { sloc::SrcLoc, decls::[Decl] }\n                deriving (Show,Read,NFData,Generic)\n\ndata Decl       = Def           { dloc::SrcLoc, dname:: Name, qbinds::QBinds, pos::PosPar, kwd::KwdPar, ann::Maybe Type, dbody::Suite, deco::Deco, dfx::TFX, ddoc::Maybe String }\n                | Actor         { dloc::SrcLoc, dname:: Name, qbinds::QBinds, pos::PosPar, kwd::KwdPar, dbody::Suite, ddoc::Maybe String }\n                | Class         { dloc::SrcLoc, dname:: Name, qbinds::QBinds, bounds::[TCon], dbody::Suite, ddoc::Maybe String }\n                | Protocol      { dloc::SrcLoc, dname:: Name, qbinds::QBinds, bounds::[PCon], dbody::Suite, ddoc::Maybe String }\n--                | Extension     { dloc::SrcLoc, dqname::QName, qbinds::QBinds, bounds::[PCon], dbody::Suite }\n                | Extension     { dloc::SrcLoc, qbinds::QBinds, tycon::TCon, bounds::[PCon], dbody::Suite, ddoc::Maybe String }\n                deriving (Show,Read,NFData,Generic)\n\ndata Expr       = Var           { eloc::SrcLoc, var::QName }\n                | Int           { eloc::SrcLoc, ival::Integer, lexeme::String }\n                | Float         { eloc::SrcLoc, dval::Double, lexeme::String }\n                | Imaginary     { eloc::SrcLoc, dval::Double, lexeme::String }\n                | Bool          { eloc::SrcLoc, bval::Bool }\n                | None          { eloc::SrcLoc }\n                | NotImplemented{ eloc::SrcLoc }\n                | Ellipsis      { eloc::SrcLoc }\n                | Strings       { eloc::SrcLoc, sval::[String] }\n                | BStrings      { eloc::SrcLoc, sval::[String] }\n                | Call          { eloc::SrcLoc, fun::Expr, pargs::PosArg, kargs::KwdArg }\n                | Let           { eloc::SrcLoc, suit::Suite, exp1::Expr }\n                | TApp          { eloc::SrcLoc, fun::Expr, targs::[Type] }\n                | Async         { eloc::SrcLoc, exp1::Expr }\n                | Await         { eloc::SrcLoc, exp1::Expr }\n                | Index         { eloc::SrcLoc, exp1::Expr, index::Expr }\n                | Slice         { eloc::SrcLoc, exp1::Expr, slice::Sliz }\n                | Cond          { eloc::SrcLoc, exp1::Expr, cond::Expr, exp2::Expr }\n                | IsInstance    { eloc::SrcLoc, exp1::Expr, classref::QName }\n                | BinOp         { eloc::SrcLoc, exp1::Expr, bop::Binary, exp2::Expr }\n                | CompOp        { eloc::SrcLoc, exp1::Expr, ops::[OpArg] }\n                | UnOp          { eloc::SrcLoc, uop::Unary, exp1::Expr }\n                | Dot           { eloc::SrcLoc, exp1::Expr, attr::Name }\n                | Rest          { eloc::SrcLoc, exp1::Expr, attr::Name }\n                | DotI          { eloc::SrcLoc, exp1::Expr, ival::Integer }\n                | RestI         { eloc::SrcLoc, exp1::Expr, ival::Integer }\n                | Opt           { eloc::SrcLoc, exp1::Expr, optVal::Bool }\n                | OptChain      { eloc::SrcLoc, exp1::Expr }\n                | Lambda        { eloc::SrcLoc, ppar::PosPar, kpar::KwdPar, exp1::Expr, efx::TFX }\n                | Yield         { eloc::SrcLoc, yexp1::Maybe Expr }\n                | YieldFrom     { eloc::SrcLoc, yfrom::Expr }\n                | Tuple         { eloc::SrcLoc, pargs::PosArg, kargs::KwdArg }\n                | List          { eloc::SrcLoc, elems::[Elem] }\n                | ListComp      { eloc::SrcLoc, elem1::Elem, comp::Comp }\n                | Dict          { eloc::SrcLoc, assocs::[Assoc] }\n                | DictComp      { eloc::SrcLoc, assoc1::Assoc, comp::Comp }\n                | Set           { eloc::SrcLoc, elems::[Elem] }\n                | SetComp       { eloc::SrcLoc, elem1::Elem, comp::Comp }\n                | Paren         { eloc::SrcLoc, exp1::Expr }\n                | Box           { tp :: Type, exp1 :: Expr }\n                | UnBox         { tp :: Type, exp1 :: Expr }\n                deriving (Show,Read,NFData,Generic)\n\ndata Pattern    = PWild         { ploc::SrcLoc, pann::Maybe Type }\n                | PVar          { ploc::SrcLoc, pn::Name, pann::Maybe Type }\n                | PParen        { ploc::SrcLoc, pat::Pattern }\n                | PTuple        { ploc::SrcLoc, ppat::PosPat, kpat::KwdPat}\n                | PList         { ploc::SrcLoc, pats::[Pattern], ptail::Maybe Pattern }\n                | PData         { ploc::SrcLoc, pn::Name, pixs::[Expr] }\n                deriving (Show,Read,NFData,Generic)\n\ntype Target     = Expr\n\ndata Prefix     = Globvar | Xistvar | Tempvar | Witness | NormPass | CPSPass | LLiftPass | BoxPass\n                deriving (Eq,Ord,Show,Read,Generic,NFData)\n\ndata Name       = Name SrcLoc String | Derived Name Name | Internal Prefix String Int deriving (Generic,Show,NFData)\n\nnloc (Name l _) = l\nnloc _          = NoLoc\n\nnstr (Name _ s)             = esc s\n  where esc (c:'_':s)\n          | isUpper c       = c : {- 'X' : -} '_' : esc s\n        esc (c:s)           = c : esc s\n        esc \"\"              = \"\"\nnstr (Derived n s)\n  | Internal{} <- s         = nstr n ++ nstr s\n  | otherwise               = nstr n ++ \"D_\" ++ nstr s\nnstr (Internal p s i)       = prefix p ++ \"_\" ++ unique i ++ s\n  where prefix Globvar      = \"G\"\n        prefix Xistvar      = \"E\"\n        prefix Tempvar      = \"V\"\n        prefix Witness      = \"W\"\n        prefix NormPass     = \"N\"\n        prefix CPSPass      = \"C\"\n        prefix LLiftPass    = \"L\"\n        prefix BoxPass      = \"U\"\n        unique 0            = \"\"\n        unique i            = show i\n\nrawstr (Name _ s)           = s\nrawstr n                    = nstr n\n\nname            = Name NoLoc\n\nnWild           = name \"_\"\n\nglobalName s    = Internal Globvar s 0\n\nglobalNames s   = map (Internal Globvar s) [1..]\n\n\ndata ModName    = ModName [Name] deriving (Show,Read,Eq,Generic,NFData)\n\nmodName ss      = ModName (map name ss)\n\nmodPath (ModName ns) = map nstr ns\n\nmodCat (ModName ns) n = ModName (ns++[n])\n\ninstance Ord ModName where\n    compare a b = compare (modPath a) (modPath b)\n\ndata QName      = QName { mname::ModName, noq::Name } | NoQ { noq::Name } | GName { mname::ModName, noq::Name } deriving (Show,Read,Eq,Ord,Generic,NFData)\n\nqName ss s      = QName (modName ss) (name s)\n\nnoQ s           = NoQ (name s)\n\n\ndata ModuleItem = ModuleItem ModName (Maybe Name) deriving (Show,Eq,Read,NFData,Generic)\ndata ModRef     = ModRef (Int, Maybe ModName) deriving (Show,Eq,Read,NFData,Generic)\ndata ImportItem = ImportItem Name (Maybe Name) deriving (Show,Eq,Read,NFData,Generic)\ndata Branch     = Branch Expr Suite deriving (Show,Eq,Read,NFData,Generic)\ndata Handler    = Handler Except Suite deriving (Show,Eq,Read,NFData,Generic)\ndata Except     = ExceptAll SrcLoc | Except SrcLoc QName | ExceptAs SrcLoc QName Name deriving (Show,Read,NFData,Generic)\n\ndata Elem       = Elem Expr | Star Expr deriving (Show,Eq,Read,NFData,Generic)\ndata Assoc      = Assoc Expr Expr | StarStar Expr deriving (Show,Eq,Read,NFData,Generic)\n\ndata PosPar     = PosPar Name (Maybe Type) (Maybe Expr) PosPar | PosSTAR Name (Maybe Type) | PosNIL deriving (Show,Eq,Read,NFData,Generic)\ndata KwdPar     = KwdPar Name (Maybe Type) (Maybe Expr) KwdPar | KwdSTAR Name (Maybe Type) | KwdNIL deriving (Show,Eq,Read,NFData,Generic)\n\ndata PosArg     = PosArg Expr PosArg | PosStar Expr | PosNil deriving (Show,NFData,Eq,Read,Generic)\ndata KwdArg     = KwdArg Name Expr KwdArg | KwdStar Expr | KwdNil deriving (Show,Eq,Read,NFData,Generic)\n\ndata PosPat     = PosPat Pattern PosPat | PosPatStar Pattern | PosPatNil deriving (Show,Eq,Read,NFData,Generic)\ndata KwdPat     = KwdPat Name Pattern KwdPat | KwdPatStar Pattern | KwdPatNil deriving (Show,Eq,Read,NFData,Generic)\n\ndata OpArg      = OpArg Comparison Expr deriving (Eq,Show,Read,NFData,Generic)\ndata Sliz       = Sliz SrcLoc (Maybe Expr) (Maybe Expr) (Maybe Expr) deriving (Show,Read,NFData,Generic)\ndata Comp       = CompFor SrcLoc Pattern Expr Comp | CompIf SrcLoc Expr Comp | NoComp deriving (Show,Read,NFData,Generic)\ndata WithItem   = WithItem Expr (Maybe Pattern) deriving (Show,Eq,Read,NFData,Generic)\n\n\ndata Unary      = Not|UPlus|UMinus|BNot deriving (Show,Eq,Read,NFData,Generic)\ndata Binary     = Or|And|Plus|Minus|Mult|Pow|Div|Mod|EuDiv|BOr|BXor|BAnd|ShiftL|ShiftR|MMult deriving (Show,Read,Eq,NFData,Generic)\ndata Aug        = PlusA|MinusA|MultA|PowA|DivA|ModA|EuDivA|BOrA|BXorA|BAndA|ShiftLA|ShiftRA|MMultA deriving (Show,Eq,Read,NFData,Generic)\ndata Comparison = Eq|NEq|LtGt|Lt|Gt|GE|LE|In|NotIn|Is|IsNot deriving (Show,Eq,Read,NFData,Generic)\n\ndata Deco       = NoDec | Property | Static deriving (Eq,Show,Read,Generic,NFData)\n\ndata Kind       = KType | KProto | KFX | PRow | KRow | KFun [Kind] Kind | KUni Int | KWild deriving (Eq,Ord,Show,Read,Generic,NFData)\n\ndata TSchema    = TSchema { scloc::SrcLoc, scbind::QBinds, sctype::Type } deriving (Show,Read,Generic,NFData)\n\ndata TVar       = TV { tvkind::Kind, tvname::Name } -- the Name is an uppercase letter, optionally followed by digits.\n                deriving (Show,Read,Generic,NFData)\n\ndata TUni       = UV { uvkind::Kind, uvlevel::Int, uvid::Int }\n                deriving (Show,Read,Generic,NFData)\n\nunivar k l i    = UV k l i\nunitoken i      = UV KWild 0 (-(i*2))\nuniwild k l i   = UV k l (-(i*2+1))\n\ndata TCon       = TC { tcname::QName, tcargs::[Type] } deriving (Eq,Show,Read,Generic,NFData)\n\ndata FX         = FXPure | FXMut | FXProc | FXAction deriving (Eq,Show,Read,Generic,NFData)\n\ndata QBind      = QBind TVar [TCon] deriving (Eq,Show,Read,Generic,NFData)\n\ntype QBinds     = [QBind]\n\ntype PCon       = TCon\ntype CCon       = TCon\n\ntype KUni       = Int\n\ndata Type       = TUni      { tloc::SrcLoc, uvar::TUni }\n                | TVar      { tloc::SrcLoc, tvar::TVar }\n                | TCon      { tloc::SrcLoc, tcon::TCon }\n                | TFun      { tloc::SrcLoc, effect::TFX, posrow::PosRow, kwdrow::KwdRow, restype::Type }\n                | TTuple    { tloc::SrcLoc, posrow::PosRow, kwdrow::KwdRow }\n                | TOpt      { tloc::SrcLoc, opttype::Type }\n                | TNone     { tloc::SrcLoc }\n                | TWild     { tloc::SrcLoc }\n                | TNil      { tloc::SrcLoc, rkind::Kind }\n                | TRow      { tloc::SrcLoc, rkind::Kind, label::Name, rtype::Type, rtail::TRow }\n                | TStar     { tloc::SrcLoc, rkind::Kind, rtail::TRow }\n                | TFX       { tloc::SrcLoc, tfx::FX }\n                deriving (Show,Read,Generic,NFData)\n\ntype TFX        = Type\ntype PosRow     = Type\ntype KwdRow     = Type\ntype TRow       = Type\n\n\nleftpath tcs    = [ (map Left ns, tc) | (ns,tc) <- nss `zip` tcs ]\n  where nss     = tail $ inits $ map tcname tcs\n\nmkBody []       = [Pass NoLoc]\nmkBody b        = b\n\nsDef n p t b fx = sDecl [Def NoLoc n [] p KwdNIL (Just t) b NoDec fx Nothing]\nsReturn e       = Return NoLoc (Just e)\nsAssign p e     = Assign NoLoc [p] e\nsMutAssign t e  = MutAssign NoLoc t e\nsRaise e        = Raise NoLoc e\nsExpr e         = Expr NoLoc e\nsDecl ds        = Decl NoLoc ds\nsIf bs els      = If NoLoc bs els\nsIf1 e b els    = sIf [Branch e b] els\nsNotImpl        = Expr NoLoc eNotImpl\nsPass           = Pass NoLoc\nsBreak          = Break NoLoc\nsContinue       = Continue NoLoc\n\nhandler qn b    = Handler (Except NoLoc qn) b\n\ntApp e []       = e\ntApp e ts       = TApp NoLoc e ts\n\neCall e es      = Call NoLoc e (posarg es) KwdNil\neCallVar c es   = eCall (eVar c) es\neCallV c es     = eCall (Var NoLoc c) es\neCallP e as     = Call NoLoc e as KwdNil\neTuple es       = Tuple NoLoc (posarg es) KwdNil\neTupleP args    = Tuple NoLoc args KwdNil\neTupleK args    = Tuple NoLoc PosNil args\neQVar n         = Var NoLoc n\neVar n          = Var NoLoc (NoQ n)\neDot e n        = Dot NoLoc e n\neDotI e i       = DotI NoLoc e i\neNone           = None NoLoc\neCond e b e'    = Cond NoLoc e b e'\neInt n          = Int NoLoc n (show n)\neBool b         = Bool NoLoc b\neBinOp e o e'   = BinOp NoLoc e o e'\neLambda nts e   = Lambda NoLoc (pospar nts) KwdNIL e fxPure\neLambda' nts e  = Lambda NoLoc (pospar nts) KwdNIL e fxProc\neLet ss e       = Let NoLoc ss e\neAsync e        = Async NoLoc e\neAwait e        = Await NoLoc e\neNotImpl        = NotImplemented NoLoc\neIsInstance x n = IsInstance NoLoc (eVar x) n\n\npospar nts      = foldr (\\(n,t) p -> PosPar n (Just t) Nothing p) PosNIL nts\npospar' ns      = foldr (\\n p -> PosPar n Nothing Nothing p) PosNIL ns\n\npospars' (PosPar n _ _ p)\n                = n : pospars' p\npospars' PosNIL = []\n\nposarg es       = foldr PosArg PosNil es\n\nposargs (PosArg e p)\n                = e : posargs p\nposargs (PosStar e)\n                = [e]\nposargs PosNil  = []\n\nselfPar Def{pos=PosPar x _ _ _} = Just x\nselfPar Def{kwd=KwdPar x _ _ _} = Just x\nselfPar _                       = Nothing\n\npVar n t        = PVar NoLoc n (Just t)\npVar' n         = PVar NoLoc n Nothing\n\nmonotype t      = TSchema NoLoc [] t\ntSchema q t     = TSchema NoLoc q t\n\nqbind v         = QBind v []\nqbound q        = [ tv | QBind tv _ <- q ]\n\ntVar v          = TVar NoLoc v\ntUni v          = TUni NoLoc v\ntCon c          = TCon NoLoc c\ntFun fx p k t   = TFun NoLoc fx p k t\ntTuple p k      = TTuple NoLoc p k\ntTupleP p       = TTuple NoLoc p kwdNil\ntTupleK k       = TTuple NoLoc posNil k\ntUnit           = tTuple posNil kwdNil\ntOpt t@TOpt{}   = t\ntOpt t          = TOpt NoLoc t\ntNone           = TNone NoLoc\ntWild           = TWild NoLoc\ntNil k          = TNil NoLoc k\ntRow k          = TRow NoLoc k\ntStar k         = TStar NoLoc k\ntTFX fx         = TFX NoLoc fx\n\ntCon0 n q       = tCon $ TC n [ tVar tv | QBind tv _ <- q ]\n\ntFun0 ps t      = tFun fxPure (foldr posRow posNil ps) kwdNil t\n\ntSelf           = TVar NoLoc tvSelf\ntvSelf          = TV KType nSelf\nnSelf           = Name NoLoc \"Self\"\n\nfxSelf          = TV KFX nSelf\n\nfxPure          = tTFX FXPure\nfxMut           = tTFX FXMut\nfxProc          = tTFX FXProc\nfxAction        = tTFX FXAction\nfxWild          = tWild\n\nfxFun fx1 fx2   = tFun fxPure (posRow (tF0 fx1) posNil) kwdNil (tF0 fx2)\n  where tF0 fx  = tFun fx posNil kwdNil tNone\n\nposNil          = tNil PRow\nposRow          = tRow PRow nWild\nposStar         = tStar PRow\nposStar'        = posStar . maybe tWild tVar\n\nkwdNil          = tNil KRow\nkwdRow          = tRow KRow\nkwdStar         = tStar KRow\nkwdStar'        = kwdStar . maybe tWild tVar\n\nprowOf (PosPar n a d p) = posRow (dflt d $ case a of Just t -> t; _ -> tWild) (prowOf p)\n  where dflt Nothing    = id\n        dflt (Just e)   = tOpt\nprowOf (PosSTAR n a)    = posStar (case a of Just (TTuple _ r _) -> r; _ -> tWild)\n--prowOf (PosSTAR n a)    = (case a of Just (TTuple _ r _) -> r; _ -> tWild)\nprowOf PosNIL           = posNil\n\nkrowOf (KwdPar n a d k) = kwdRow n (dflt d $ case a of Just t -> t; _ -> tWild) (krowOf k)\n  where dflt Nothing    = id\n        dflt (Just e)   = tOpt\nkrowOf (KwdSTAR n a)    = kwdStar (case a of Just (TTuple _ _ r) -> r; _ -> tWild)\n--krowOf (KwdSTAR n a)    = (case a of Just (TTuple _ _ r) -> r; _ -> tWild)\nkrowOf KwdNIL           = kwdNil\n\npArg (PosPar n a _ p)   = PosArg (eVar n) (pArg p)\npArg (PosSTAR n a)      = PosStar (eVar n)\npArg PosNIL             = PosNil\n\nkArg (KwdPar n a _ p)   = KwdArg n (eVar n) (kArg p)\nkArg (KwdSTAR n a)      = KwdStar (eVar n)\nkArg KwdNIL             = KwdNil\n\nchop 0 _                = PosNIL\nchop i (PosPar n a d p) = PosPar n a d (chop (i-1) p)\nchop _ p                = p\n\narity (TRow _ _ _ _ r)  = 1 + arity r\narity _                 = 0\n\npPar ns (TRow _ PRow n t p)\n                        = PosPar (head ns) (Just t) Nothing (pPar (tail ns) p)\npPar ns (TNil _ PRow)   = PosNIL\npPar ns (TStar _ PRow r)= PosSTAR (head ns) (Just $ tTupleP r)\n\nkPar kw (TRow _ KRow n t r)\n                        = KwdPar n (Just t) Nothing (kPar kw r)\nkPar kw (TNil _ KRow)   = KwdNIL\nkPar kw (TStar _ KRow r)= KwdSTAR kw (Just $ tTupleK r)\n\ntRowLoc t@TRow{}        = getLoc [tloc t, loc (rtype t)]\n\ntvarSupply              = [ TV KType $ name (c:tl) | tl <- \"\" : map show [1..], c <- \"ABCDEFGHIJKLMNOPQRSTUVW\" ]\n\nfxSupply                = [ TV KType $ name (c:tl) | tl <- \"\" : map show [1..], c <- \"XYZ\" ]\n\ntvarSupplyMap vs avoid  = map setk (vs `zip` (tvarSupply \\\\ avoid))\n  where setk (v,v')     = (v, tVar $ v'{ tvkind = tvkind v })\n\n\ntype Substitution       = [(TVar,Type)]\n\ninstance Data.Hashable.Hashable Name where\n    hashWithSalt s (Name _ nstr)    = Data.Hashable.hashWithSalt s nstr\n    hashWithSalt s (Derived  n1 n2) = Data.Hashable.hashWithSalt s (n1,n2)\n    hashWithSalt s (Internal pre str n) = Data.Hashable.hashWithSalt s (show pre,str,n)\n\n\n-- Finding type leaves -----\n\nclass Leaves a where\n    leaves                  :: a -> [Type]\n\ninstance (Leaves a) => Leaves [a] where\n    leaves                  = concatMap leaves\n\ninstance (Leaves a) => Leaves (Name,a) where\n    leaves (n,x)            = leaves x\n\ninstance Leaves QBind where\n    leaves (QBind tv ps)    = tVar tv : leaves ps\n\ninstance Leaves TSchema where\n    leaves (TSchema _ q t)  = leaves q ++ leaves t\n\ninstance Leaves Type where\n    leaves t@TCon{}         = [t]\n    leaves t@TVar{}         = [t]\n    leaves t@TUni{}         = [t]\n    leaves t@TFX{}          = [t]\n    leaves (TFun _ x p k t) = leaves [x,p,k,t]\n    leaves (TTuple _ p k)   = leaves [p,k]\n    leaves (TOpt _ t)       = leaves t\n    leaves (TRow _ _ _ t r) = leaves [t,r]\n    leaves (TStar _ _ r)    = leaves r\n    leaves _                = []\n\ninstance Leaves TCon where\n    leaves tc               = [tCon tc]\n\ninstance Leaves TVar where\n    leaves tv               = [tVar tv]\n\n\ninstance Data.Binary.Binary Prefix\ninstance Data.Binary.Binary Name\ninstance Data.Binary.Binary ModName\ninstance Data.Binary.Binary QName\ninstance Data.Binary.Binary Deco\ninstance Data.Binary.Binary TSchema\ninstance Data.Binary.Binary TVar\ninstance Data.Binary.Binary TUni\ninstance Data.Binary.Binary TCon\ninstance Data.Binary.Binary QBind\ninstance Data.Binary.Binary Type\ninstance Data.Binary.Binary Kind\ninstance Data.Binary.Binary FX\ninstance Data.Binary.Binary Expr\ninstance Data.Binary.Binary Stmt\ninstance Data.Binary.Binary Decl\ninstance Data.Binary.Binary Branch\ninstance Data.Binary.Binary Handler\ninstance Data.Binary.Binary Except\ninstance Data.Binary.Binary Elem\ninstance Data.Binary.Binary Assoc\ninstance Data.Binary.Binary Pattern\ninstance Data.Binary.Binary PosPar\ninstance Data.Binary.Binary KwdPar\ninstance Data.Binary.Binary PosArg\ninstance Data.Binary.Binary KwdArg\ninstance Data.Binary.Binary PosPat\ninstance Data.Binary.Binary KwdPat\ninstance Data.Binary.Binary OpArg\ninstance Data.Binary.Binary Sliz\ninstance Data.Binary.Binary Comp\ninstance Data.Binary.Binary WithItem\ninstance Data.Binary.Binary Unary\ninstance Data.Binary.Binary Binary\ninstance Data.Binary.Binary Aug\ninstance Data.Binary.Binary Comparison\ninstance Data.Binary.Binary Module\ninstance Data.Binary.Binary Import\ninstance Data.Binary.Binary ModuleItem\ninstance Data.Binary.Binary ImportItem\ninstance Data.Binary.Binary ModRef\n\n\n-- Locations ----------------\n\ninstance HasLoc Import where\n    loc                 = iloc\n\ninstance HasLoc Stmt where\n    loc                 = sloc\n\ninstance HasLoc Decl where\n    loc                 = dloc\n\ninstance HasLoc Expr where\n    loc                 = eloc\n\ninstance HasLoc Name where\n    loc                 = nloc\n\ninstance HasLoc ModName where\n    loc (ModName ns)    = loc ns\n\ninstance HasLoc QName where\n    loc (QName m n)     = loc m `upto` loc n\n    loc (NoQ n)         = loc n\n    loc (GName m n)     = loc m `upto` loc n\n\ninstance HasLoc Elem where\n    loc (Elem e)        = loc e\n    loc (Star e)        = loc e\n\ninstance HasLoc Assoc where\n    loc (Assoc k v)     = loc k `upto` loc v\n    loc (StarStar e)    = loc e\n\ninstance HasLoc Pattern where\n    loc                 = ploc\n\ninstance HasLoc TSchema where\n    loc (TSchema l _ _) = l\n\ninstance HasLoc TVar where\n    loc (TV _ v)        = loc v\n\ninstance HasLoc TUni where\n    loc (UV _ _ v)      = NoLoc\n\ninstance HasLoc TCon where\n    loc (TC c ts)       = loc c `upto` loc ts\n\ninstance HasLoc Type where\n    loc                 = tloc\n\ninstance HasLoc PosArg where\n      loc (PosArg e p) = loc e  `upto` loc p\n      loc (PosStar e)  = loc e\n      loc PosNil       = NoLoc\n\ninstance HasLoc KwdArg where\n      loc (KwdArg n e k) = loc n `upto` loc k\n      loc (KwdStar e)    = loc e\n      loc KwdNil         = NoLoc\n\ninstance HasLoc PosPar where\n    loc (PosPar n _ _ _) = loc n\n    loc (PosSTAR n _)    = loc n\n    loc _                = NoLoc\n\ninstance HasLoc KwdPar where\n    loc (KwdPar n _ _ _) = loc n\n    loc (KwdSTAR n _)    = loc n\n    loc _                = NoLoc\n\n\n-- Eq -------------------------\n\ninstance Eq Import where\n    x@Import{}          ==  y@Import{}          = moduls x == moduls y\n    x@FromImport{}      ==  y@FromImport{}      = modul x == modul y && items x == items y\n    x@FromImportAll{}   ==  y@FromImportAll{}   = modul x == modul y\n    _                   ==  _                   = False\n\ninstance Eq Stmt where\n    x@Expr{}            ==  y@Expr{}            = expr x == expr y\n    x@Assign{}          ==  y@Assign{}          = patterns x == patterns y && expr x == expr y\n    x@MutAssign{}       ==  y@MutAssign{}       = target x == target y && expr x == expr y\n    x@AugAssign{}       ==  y@AugAssign{}       = target x == target y && aop x == aop y && expr x == expr y\n    x@Assert{}          ==  y@Assert{}          = expr x == expr y && optExpr x == optExpr y\n    x@Pass{}            ==  y@Pass{}            = True\n    x@Delete{}          ==  y@Delete{}          = target x == target y\n    x@Return{}          ==  y@Return{}          = optExpr x == optExpr y\n    x@Raise{}           ==  y@Raise{}           = expr x == expr y\n    x@Break{}           ==  y@Break{}           = True\n    x@Continue{}        ==  y@Continue{}        = True\n    x@If{}              ==  y@If{}              = branches x == branches y && els x == els y\n    x@While{}           ==  y@While{}           = expr x == expr y && body x == body y && els x == els y\n    x@For{}             ==  y@For{}             = pattern x == pattern y && expr x == expr y && body x == body y\n                                                  && els x == els y\n    x@Try{}             ==  y@Try{}             = body x == body y && handlers x == handlers y && els x == els y\n                                                  && finally x == finally y\n    x@With{}            ==  y@With{}            = witems x == witems y && body x == body y\n    x@Data{}            ==  y@Data{}            = mbpat x == mbpat y && dsuite x == dsuite y\n    x@VarAssign{}       ==  y@VarAssign{}       = patterns x == patterns y && expr x == expr y\n    x@After{}           ==  y@After{}           = expr x == expr y && expr2 x == expr2 y\n    x@Decl{}            ==  y@Decl{}            = decls x == decls y\n    x@Signature{}       ==  y@Signature{}       = vars x == vars y && typ x == typ y && dec x == dec y\n    _                   ==  _                   = False\n\ninstance Eq Decl where\n    Def _ n1 q1 p1 k1 a1 b1 m1 d1 doc1   ==  Def _ n2 q2 p2 k2 a2 b2 m2 d2 doc2\n                                                                    = n1==n2 && q1==q2 && p1==p2 && k1==k2 && a1==a2 && b1==b2 && d1==d2 && m1==m2 && doc1==doc2\n    Actor _ n1 q1 p1 k1 b1 doc1          ==  Actor _ n2 q2 p2 k2 b2 doc2      = n1 == n2 && q1 == q2 && p1 == p2 && k1 == k2 && b1 == b2 && doc1 == doc2\n    Class _ n1 q1 a1 b1 doc1             ==  Class _ n2 q2 a2 b2 doc2         = n1 == n2 && q1 == q2 && a1 == a2 && b1 == b2 && doc1 == doc2\n    Protocol _ n1 q1 a1 b1 doc1          ==  Protocol _ n2 q2 a2 b2 doc2      = n1 == n2 && q1 == q2 && a1 == a2 && b1 == b2 && doc1 == doc2\n    Extension _ q1 c1 a1 b1 doc1         ==  Extension _ q2 c2 a2 b2 doc2     = q1 == q2 && c1 == c2 && a1 == a2 && b1 == b2 && doc1 == doc2\n    _                               == _                            = False\n\ninstance Eq Expr where\n    x@Var{}             ==  y@Var{}             = var x == var y\n    x@Int{}             ==  y@Int{}             = lexeme x == lexeme y\n    x@Float{}           ==  y@Float{}           = lexeme x == lexeme y\n    x@Imaginary{}       ==  y@Imaginary{}       = lexeme x == lexeme y\n    x@Bool{}            ==  y@Bool{}            = bval x == bval y\n    x@None{}            ==  y@None{}            = True\n    x@NotImplemented{}  ==  y@NotImplemented{}  = True\n    x@Ellipsis{}        ==  y@Ellipsis{}        = True\n    x@Strings{}         ==  y@Strings{}         = sval x == sval y\n    x@BStrings{}        ==  y@BStrings{}        = sval x == sval y\n    x@Call{}            ==  y@Call{}            = fun x == fun y && pargs x == pargs y && kargs x == kargs y\n    x@TApp{}            ==  y@TApp{}            = fun x == fun y && targs x == targs y\n    x@Let{}             ==  y@Let{}             = suit x == suit y && exp1 x == exp1 y\n    x@Async{}           ==  y@Async{}           = exp1 x == exp1 y\n    x@Await{}           ==  y@Await{}           = exp1 x == exp1 y\n    x@Index{}           ==  y@Index{}           = exp1 x == exp1 y && index x == index y\n    x@Slice{}           ==  y@Slice{}           = exp1 x == exp1 y && slice x == slice y\n    x@Cond{}            ==  y@Cond{}            = exp1 x == exp1 y && cond x == cond y && exp2 x == exp2 y\n    x@IsInstance{}      ==  y@IsInstance{}      = exp1 x == exp1 y && classref x == classref y\n    x@BinOp{}           ==  y@BinOp{}           = exp1 x == exp1 y && bop x == bop y && exp2 x == exp2 y\n    x@CompOp{}          ==  y@CompOp{}          = exp1 x == exp1 y && ops x == ops y\n    x@UnOp{}            ==  y@UnOp{}            = uop x == uop y && exp1 x == exp1 y\n    x@Dot{}             ==  y@Dot{}             = exp1 x == exp1 y && attr x == attr y\n    x@Rest{}            ==  y@Rest{}            = exp1 x == exp1 y && attr x == attr y\n    x@DotI{}            ==  y@DotI{}            = exp1 x == exp1 y && ival x == ival y\n    x@RestI{}           ==  y@RestI{}           = exp1 x == exp1 y && ival x == ival y\n    x@Opt{}             ==  y@Opt{}             = exp1 x == exp1 y && optVal x == optVal y\n    x@OptChain{}        ==  y@OptChain{}        = exp1 x == exp1 y\n    x@Lambda{}          ==  y@Lambda{}          = ppar x == ppar y && kpar x == kpar y && exp1 x == exp1 y && efx x == efx y\n    x@Yield{}           ==  y@Yield{}           = yexp1 x == yexp1 y\n    x@YieldFrom{}       ==  y@YieldFrom{}       = yfrom x == yfrom y\n    x@Tuple{}           ==  y@Tuple{}           = pargs x == pargs y && kargs x == kargs y\n    x@List{}            ==  y@List{}            = elems x == elems y\n    x@ListComp{}        ==  y@ListComp{}        = elem1 x == elem1 y && comp x == comp y\n    x@Dict{}            ==  y@Dict{}            = assocs x == assocs y\n    x@DictComp{}        ==  y@DictComp{}        = assoc1 x == assoc1 y && comp x == comp y\n    x@Set{}             ==  y@Set{}             = elems x == elems y\n    x@SetComp{}         ==  y@SetComp{}         = elem1 x == elem1 y && comp x == comp y\n    x@Paren{}           ==  y                   = exp1 x == y\n    x                   ==  y@Paren{}           = x == exp1 y\n    _                   ==  _                   = False\n\ninstance Eq Name where\n    Name _ s1           == Name _ s2            = s1 == s2\n    Derived n1 s1       == Derived n2 s2        = n1 == n2 && s1 == s2\n    Internal p1 s1 i1   == Internal p2 s2 i2    = p1 == p2 && s1 == s2 && i1 == i2\n    _                   == _                    = False\n\ninstance Ord Name where\n    Name _ s1           <= Name _ s2            = s1 <= s2\n    Derived n1 s1       <= Derived n2 s2        = (n1,s1) <= (n2,s2)\n    Internal p1 s1 i1   <= Internal p2 s2 i2    = (p1,s1,i1) <= (p2,s2,i2)\n    Name{}              <= Derived{}            = True\n    Name{}              <= Internal{}           = True\n    Derived{}           <= Internal{}           = True\n    _                   <= _                    = False\n\ninstance Eq Except where\n    ExceptAll _         ==  ExceptAll _         = True\n    Except _ x1         ==  Except _ x2         = x1 == x2\n    ExceptAs _ x1 n1    ==  ExceptAs _ x2 n2    = x1 == x2 && n1 == n2\n    _                   ==  _                   = False\n\ninstance Eq Sliz where\n    Sliz _ a1 b1 c1     ==  Sliz _ a2 b2 c2     = a1 == a2 && b1 == b2 && c1 == c2\n\ninstance Eq Comp where\n    CompFor _ p1 e1 c1  ==  CompFor _ p2 e2 c2  = p1 == p2 && e1 == e2 && c1 == c2\n    CompIf _ e1 c1      ==  CompIf _ e2 c2      = e1 == e2 && c1 == c2\n    NoComp              ==  NoComp              = True\n    _                   ==  _                   = False\n\ninstance Eq Pattern where\n    PWild _ a1          == PWild _ a2           = a1 == a2\n    PVar _ n1 a1        == PVar _ n2 a2         = n1 == n2 && a1 == a2\n    PTuple _ p1 k1      == PTuple _ p2 k2       = p1 == p2 && k1 == k2\n    PList _ ps1 p1      == PList _ ps2 p2       = ps1 == ps2 && p1 == p2\n    PData _ n1 ix1      == PData _ n2 ix2       = n1 == n2 && ix1 == ix2\n    PParen _ p1         == p2                   = p1 == p2\n    p1                  == PParen _ p2          = p1 == p2\n    _                   == _                    = False\n\ninstance Eq TSchema where\n    TSchema _ q1 t1     == TSchema _ q2 t2      = q1 == q2 && t1 == t2\n\ninstance Eq TVar where\n    TV k1 v1            == TV k2 v2             = v1 == v2\n\ninstance Eq TUni where\n    UV _ _ i1           == UV _ _ i2            = i1 == i2\n\ninstance Ord TVar where\n    TV _ v1             <= TV _ v2              = v1 <= v2\n\ninstance Ord TUni where\n    UV _ _ i1           <= UV _ _ i2            = i1 <= i2\n\ninstance Eq Type where\n    TUni _ u1           == TUni _ u2            = u1 == u2\n    TVar _ v1           == TVar _ v2            = v1 == v2\n    TCon _ c1           == TCon _ c2            = c1 == c2\n    TFun _ e1 p1 r1 t1  == TFun _ e2 p2 r2 t2   = e1 == e2 && p1 == p2 && r1 == r2 && t1 == t2\n    TTuple _ p1 r1      == TTuple _ p2 r2       = p1 == p2 && r1 == r2\n    TOpt _ t1           == TOpt _ t2            = t1 == t2\n    TNone _             == TNone _              = True\n    TWild _             == TWild _              = True\n    TNil _ k1           == TNil _ k2            = k1 == k2\n    TRow _ k1 n1 t1 r1  == TRow _ k2 n2 t2 r2   = k1 == k2 && n1 == n2 && t1 == t2 && r1 == r2\n    TStar _ k1 r1       == TStar _ k2 r2        = k1 == k2 && r1 == r2\n    TFX _ fx1           == TFX _ fx2            = fx1 == fx2\n    _                   == _                    = False\n\n-- Show & Read ----------------\n\n--instance Show Name where\n--    show n              = show (nstr n)\n\ninstance Read Name where\n    readsPrec p str     = [ (Name NoLoc s, str') | (s,str') <- readsPrec p str ]\n\n\n-- Helpers ------------------\n\nimportsOf (Module _ imps _ _)       = impsOf imps\n  where\n    impsOf []                       = []\n    impsOf (Import _ mis : i)       = map mName mis ++ impsOf i\n    impsOf (FromImport _ mr _ : i)  = mRef mr : impsOf i\n    impsOf (FromImportAll _ mr : i) = mRef mr : impsOf i\n\n    mName (ModuleItem qn _)         = qn\n\n    mRef (ModRef (0,Just qn))       = qn\n    mRef _                          = error \"dot prefix in name of import modules not supported\"\n\nunop op e                           = UnOp l0 op e\nbinop e1 op e2                      = BinOp l0 e1 op e2\ncmp e1 op e2                        = CompOp l0 e1 [OpArg op e2]\n\nmkStringLit s                       = Strings l0 ['\\'' : s ++ \"\\'\"]\n\nisIdent s@(c:cs)                    = isAlpha c && all isAlphaNum cs && not (isKeyword s)\n  where isAlpha c                   = c `elem` ['a'..'z'] || c `elem` ['A'..'Z'] || c == '_'\n        isAlphaNum c                = isAlpha c || c `elem` ['0'..'9']\n\nisKeyword x                         = x `Data.Set.member` rws\n  where rws                         = Data.Set.fromDistinctAscList [\n                                        \"False\",\"None\",\"NotImplemented\",\"Self\",\"True\",\"action\",\"actor\",\"after\",\"and\",\"as\",\n                                        \"assert\",\"async\",\"await\",\"break\",\"class\",\"continue\",\"def\",\"del\",\"elif\",\"else\",\n                                        \"except\",\"extension\",\"finally\",\"for\",\"from\",\"if\",\"import\",\"in\",\"is\",\"isinstance\",\n                                        \"lambda\",\"mut\",\"not\",\"or\",\"pass\",\"proc\",\"protocol\",\"pure\",\"raise\",\"return\",\"try\",\n                                        \"var\",\"while\",\"with\",\"yield\",\"_\"\n                                      ]\n\nisSig Signature{}                   = True\nisSig _                             = False\n\nisDecl Decl{}                       = True\nisDecl _                            = False\n\nisQVar (Var _ n)                    = Just n\nisQVar (TApp _ e _)                 = isQVar e\nisQVar e                            = Nothing\n\nisVar e                             = case isQVar e of Just (NoQ n) -> Just n; _ -> Nothing\n\nhasNotImpl ss                       = any isNotImpl ss\n\n-- Check for __cleanup__ method on actor\nhasCleanup ss                       = any isCleanup ss\n\nisCleanup (Def _ n _ _ _ _ _ _ _ _) = n == Name NoLoc \"__cleanup__\"\n\nisNotImpl (Expr _ e)                = e == eNotImpl\nisNotImpl (Assign _ _ e)            = e == eNotImpl\nisNotImpl (Decl _ ds)               = any (hasNotImpl . dbody) ds\nisNotImpl _                         = False\n\nnotImplBody b                       = not $ null $ notImpls b\n\nnotImpls b                          = [ e | Expr _ e <- b, e == eNotImpl ]\n\nisUnivar TUni{}                     = True\nisUnivar _                          = False\n\nsinglePosArg (PosArg _ PosNil)      = True\nsinglePosArg _                      = False\n\nsinglePosPat (PosPat _ PosPatNil)   = True\nsinglePosPat _                      = False\n\nposParHead (PosPar a b c _)         = (a,b,c)\nposArgHead (PosArg a _)             = a\n"
  },
  {
    "path": "compiler/lib/src/Acton/Testing.hs",
    "content": "module Acton.Testing\n  ( TestResult(..)\n  , TestRunContext(..)\n  , TestCachedResult(..)\n  , TestCacheEntry(..)\n  , TestCache(..)\n  , TestHashInfo(..)\n  , testCacheVersion\n  , cachedResultFromTest\n  , testResultFromCache\n  , testCachePath\n  , readTestCache\n  , writeTestCache\n  , contextHashBytes\n  , hashRun\n  , hashDeps\n  , formatTestCacheContext\n  , formatTestCacheLog\n  , buildTestHashInfos\n  , classifyCachedTests\n  , updateTestCacheEntry\n  , mkTestKey\n  , testNameCandidates\n  , lookupTestInfo\n  , readModuleNameHashes\n  , readModuleNameHashesByModName\n  , readModuleNameHashesCached\n  , resolveDepImplHash\n  , resolveTestImplDeps\n  , buildTestHashInfo\n  ) where\n\nimport qualified Acton.Compile as Compile\nimport qualified Acton.Env\nimport qualified Acton.Hashing as Hashing\nimport qualified Acton.Syntax as A\nimport qualified InterfaceFiles\nimport Utils (prstr)\n\nimport Control.Exception (SomeException, try)\nimport Control.Monad (forM)\nimport Data.Binary (encode)\nimport qualified Crypto.Hash.SHA256 as SHA256\nimport qualified Data.Aeson as Aeson\nimport qualified Data.Aeson.Key as AesonKey\nimport qualified Data.ByteString.Char8 as B\nimport qualified Data.ByteString.Base16 as Base16\nimport qualified Data.ByteString.Lazy as BL\nimport Data.Either (partitionEithers)\nimport Data.IORef\nimport Data.List (intercalate, isPrefixOf, isSuffixOf, nub)\nimport qualified Data.List\nimport Data.Maybe (catMaybes, fromMaybe, listToMaybe)\nimport qualified Data.Map as M\nimport System.Directory (createDirectoryIfMissing, doesFileExist, renameFile)\nimport System.FilePath ((</>), takeDirectory)\n\n\ndata TestResult = TestResult\n  { trModule       :: String\n  , trName         :: String\n  , trComplete     :: Bool\n  , trSuccess      :: Maybe Bool\n  , trSkipped      :: Bool\n  , trSkipReason   :: Maybe String\n  , trException    :: Maybe String\n  , trOutput       :: Maybe String\n  , trStdOut       :: Maybe String\n  , trStdErr       :: Maybe String\n  , trFlaky        :: Bool\n  , trNumSkipped   :: Int\n  , trNumFailures  :: Int\n  , trNumErrors    :: Int\n  , trNumIterations :: Int\n  , trTestDuration :: Double\n  , trRaw          :: Aeson.Value\n  , trSnapshotUpdated :: Bool\n  , trCached       :: Bool\n  } deriving (Show)\n\ntestCacheVersion :: Int\ntestCacheVersion = 2\n\ndata TestRunContext = TestRunContext\n  { trcCompilerVersion :: String\n  , trcTarget          :: String\n  , trcOptimize        :: String\n  , trcMode            :: String\n  , trcArgs            :: [String]\n  } deriving (Show, Eq)\n\ninstance Aeson.ToJSON TestRunContext where\n  toJSON ctx = Aeson.object\n    [ AesonKey.fromString \"compilerVersion\" Aeson..= trcCompilerVersion ctx\n    , AesonKey.fromString \"target\" Aeson..= trcTarget ctx\n    , AesonKey.fromString \"optimize\" Aeson..= trcOptimize ctx\n    , AesonKey.fromString \"mode\" Aeson..= trcMode ctx\n    , AesonKey.fromString \"args\" Aeson..= trcArgs ctx\n    ]\n\ninstance Aeson.FromJSON TestRunContext where\n  parseJSON = Aeson.withObject \"TestRunContext\" $ \\o ->\n    TestRunContext\n      <$> o Aeson..: AesonKey.fromString \"compilerVersion\"\n      <*> o Aeson..: AesonKey.fromString \"target\"\n      <*> o Aeson..: AesonKey.fromString \"optimize\"\n      <*> o Aeson..: AesonKey.fromString \"mode\"\n      <*> o Aeson..: AesonKey.fromString \"args\"\n\ndata TestCachedResult = TestCachedResult\n  { tcrComplete     :: Bool\n  , tcrSuccess      :: Maybe Bool\n  , tcrSkipped      :: Bool\n  , tcrSkipReason   :: Maybe String\n  , tcrException    :: Maybe String\n  , tcrOutput       :: Maybe String\n  , tcrStdOut       :: Maybe String\n  , tcrStdErr       :: Maybe String\n  , tcrFlaky        :: Bool\n  , tcrNumSkipped   :: Int\n  , tcrNumFailures  :: Int\n  , tcrNumErrors    :: Int\n  , tcrNumIterations :: Int\n  , tcrTestDuration :: Double\n  } deriving (Show, Eq)\n\ninstance Aeson.ToJSON TestCachedResult where\n  toJSON res = Aeson.object\n    [ AesonKey.fromString \"complete\" Aeson..= tcrComplete res\n    , AesonKey.fromString \"success\" Aeson..= tcrSuccess res\n    , AesonKey.fromString \"skipped\" Aeson..= tcrSkipped res\n    , AesonKey.fromString \"skip_reason\" Aeson..= tcrSkipReason res\n    , AesonKey.fromString \"exception\" Aeson..= tcrException res\n    , AesonKey.fromString \"output\" Aeson..= tcrOutput res\n    , AesonKey.fromString \"std_out\" Aeson..= tcrStdOut res\n    , AesonKey.fromString \"std_err\" Aeson..= tcrStdErr res\n    , AesonKey.fromString \"flaky\" Aeson..= tcrFlaky res\n    , AesonKey.fromString \"num_skipped\" Aeson..= tcrNumSkipped res\n    , AesonKey.fromString \"num_failures\" Aeson..= tcrNumFailures res\n    , AesonKey.fromString \"num_errors\" Aeson..= tcrNumErrors res\n    , AesonKey.fromString \"num_iterations\" Aeson..= tcrNumIterations res\n    , AesonKey.fromString \"test_duration\" Aeson..= tcrTestDuration res\n    ]\n\ninstance Aeson.FromJSON TestCachedResult where\n  parseJSON = Aeson.withObject \"TestCachedResult\" $ \\o ->\n    TestCachedResult\n      <$> o Aeson..: AesonKey.fromString \"complete\"\n      <*> o Aeson..:? AesonKey.fromString \"success\"\n      <*> o Aeson..:? AesonKey.fromString \"skipped\" Aeson..!= False\n      <*> o Aeson..:? AesonKey.fromString \"skip_reason\"\n      <*> o Aeson..:? AesonKey.fromString \"exception\"\n      <*> o Aeson..:? AesonKey.fromString \"output\"\n      <*> o Aeson..:? AesonKey.fromString \"std_out\"\n      <*> o Aeson..:? AesonKey.fromString \"std_err\"\n      <*> o Aeson..:? AesonKey.fromString \"flaky\" Aeson..!= False\n      <*> o Aeson..:? AesonKey.fromString \"num_skipped\" Aeson..!= 0\n      <*> o Aeson..:? AesonKey.fromString \"num_failures\" Aeson..!= 0\n      <*> o Aeson..:? AesonKey.fromString \"num_errors\" Aeson..!= 0\n      <*> o Aeson..:? AesonKey.fromString \"num_iterations\" Aeson..!= 0\n      <*> o Aeson..:? AesonKey.fromString \"test_duration\" Aeson..!= 0\n\ndata TestCacheEntry = TestCacheEntry\n  { tceRunHash  :: String\n  , tceImplHash :: Maybe String\n  , tceResult   :: TestCachedResult\n  } deriving (Show, Eq)\n\ninstance Aeson.ToJSON TestCacheEntry where\n  toJSON entry = Aeson.object\n    [ AesonKey.fromString \"runHash\" Aeson..= tceRunHash entry\n    , AesonKey.fromString \"implHash\" Aeson..= tceImplHash entry\n    , AesonKey.fromString \"result\" Aeson..= tceResult entry\n    ]\n\ninstance Aeson.FromJSON TestCacheEntry where\n  parseJSON = Aeson.withObject \"TestCacheEntry\" $ \\o ->\n    TestCacheEntry\n      <$> o Aeson..: AesonKey.fromString \"runHash\"\n      <*> o Aeson..:? AesonKey.fromString \"implHash\"\n      <*> o Aeson..: AesonKey.fromString \"result\"\n\ndata TestCache = TestCache\n  { tcVersion :: Int\n  , tcContext :: TestRunContext\n  , tcTests   :: M.Map String TestCacheEntry\n  } deriving (Show, Eq)\n\ninstance Aeson.ToJSON TestCache where\n  toJSON tc = Aeson.object\n    [ AesonKey.fromString \"version\" Aeson..= tcVersion tc\n    , AesonKey.fromString \"context\" Aeson..= tcContext tc\n    , AesonKey.fromString \"tests\" Aeson..= tcTests tc\n    ]\n\ninstance Aeson.FromJSON TestCache where\n  parseJSON = Aeson.withObject \"TestCache\" $ \\o ->\n    TestCache\n      <$> o Aeson..: AesonKey.fromString \"version\"\n      <*> o Aeson..: AesonKey.fromString \"context\"\n      <*> o Aeson..:? AesonKey.fromString \"tests\" Aeson..!= M.empty\n\n-- | Convert a live test result into a cacheable payload.\ncachedResultFromTest :: TestResult -> TestCachedResult\ncachedResultFromTest res = TestCachedResult\n  { tcrComplete = trComplete res\n  , tcrSuccess = trSuccess res\n  , tcrSkipped = trSkipped res\n  , tcrSkipReason = trSkipReason res\n  , tcrException = trException res\n  , tcrOutput = trOutput res\n  , tcrStdOut = trStdOut res\n  , tcrStdErr = trStdErr res\n  , tcrFlaky = trFlaky res\n  , tcrNumSkipped = trNumSkipped res\n  , tcrNumFailures = trNumFailures res\n  , tcrNumErrors = trNumErrors res\n  , tcrNumIterations = trNumIterations res\n  , tcrTestDuration = trTestDuration res\n  }\n\n-- | Rehydrate a cached payload into a TestResult.\ntestResultFromCache :: String -> String -> TestCachedResult -> TestResult\ntestResultFromCache modName testName res = TestResult\n  { trModule = modName\n  , trName = testName\n  , trComplete = tcrComplete res\n  , trSuccess = tcrSuccess res\n  , trSkipped = tcrSkipped res\n  , trSkipReason = tcrSkipReason res\n  , trException = tcrException res\n  , trOutput = tcrOutput res\n  , trStdOut = tcrStdOut res\n  , trStdErr = tcrStdErr res\n  , trFlaky = tcrFlaky res\n  , trNumSkipped = tcrNumSkipped res\n  , trNumFailures = tcrNumFailures res\n  , trNumErrors = tcrNumErrors res\n  , trNumIterations = tcrNumIterations res\n  , trTestDuration = tcrTestDuration res\n  , trRaw = Aeson.Null\n  , trSnapshotUpdated = False\n  , trCached = True\n  }\n\ndata TestHashInfo = TestHashInfo\n  { thiImplHash    :: Maybe B.ByteString\n  , thiRunHash     :: Maybe String\n  , thiResolvedName :: Maybe String\n  , thiImplDeps    :: Maybe [(A.QName, B.ByteString)]\n  } deriving (Show, Eq)\n\n-- | Build an empty cache with the current context.\nemptyTestCache :: TestRunContext -> TestCache\nemptyTestCache ctx = TestCache\n  { tcVersion = testCacheVersion\n  , tcContext = ctx\n  , tcTests = M.empty\n  }\n\n-- | Resolve the on-disk test cache path for a project.\ntestCachePath :: Compile.Paths -> FilePath\ntestCachePath paths = Compile.projPath paths </> \"out\" </> \"test\" </> \"cache.json\"\n\n-- | Read the cache file, returning an empty cache on error/mismatch.\nreadTestCache :: FilePath -> TestRunContext -> IO TestCache\nreadTestCache path ctx = do\n    exists <- doesFileExist path\n    if not exists\n      then return (emptyTestCache ctx)\n      else do\n        res <- (try :: IO a -> IO (Either SomeException a)) $ BL.readFile path\n        case res of\n          Left _ -> return (emptyTestCache ctx)\n          Right bs ->\n            case Aeson.decode bs of\n              Just tc | tcVersion tc == testCacheVersion -> return tc\n              _ -> return (emptyTestCache ctx)\n\n-- | Write the cache file atomically.\nwriteTestCache :: FilePath -> TestCache -> IO ()\nwriteTestCache path tc = do\n    createDirectoryIfMissing True (takeDirectory path)\n    let tmpPath = path ++ \".tmp\"\n    BL.writeFile tmpPath (Aeson.encode tc)\n    renameFile tmpPath path\n\n-- | Hash the test run context to include in cache keys.\ncontextHashBytes :: TestRunContext -> B.ByteString\ncontextHashBytes ctx = SHA256.hash (BL.toStrict (Aeson.encode ctx))\n\n-- | Hex-encode a hash.\ntoHex :: B.ByteString -> String\ntoHex = B.unpack . Base16.encode\n\n-- | Hash impl/deps/context into a cache run hash string.\nhashRun :: B.ByteString -> B.ByteString -> B.ByteString -> String\nhashRun implHash depsHash ctxHash = toHex (SHA256.hash (B.concat [implHash, depsHash, ctxHash]))\n\n-- | Hash a dependency list with a stable ordering.\nhashDeps :: [(A.QName, B.ByteString)] -> B.ByteString\nhashDeps deps =\n    let sorted = Data.List.sortOn (Hashing.qnameKey . fst) deps\n    in SHA256.hash (BL.toStrict (encode sorted))\n\n-- | Shorten a hash to 8 hex characters.\nshortHash :: B.ByteString -> String\nshortHash bs = take 8 (toHex bs)\n\n-- | Shorten a hex hash string to 8 characters.\nshortHashStr :: String -> String\nshortHashStr s = take 8 s\n\n-- | Format the verbose test cache context header.\nformatTestCacheContext :: B.ByteString -> FilePath -> String\nformatTestCacheContext ctxHash cachePath =\n    \"[test-cache] context=\" ++ shortHash ctxHash ++ \" path=\" ++ cachePath\n\n-- | Format a dependency list with shortened hashes.\nformatDepsShort :: [(A.QName, B.ByteString)] -> String\nformatDepsShort deps =\n    let entries = [ prstr qn ++ \":\" ++ shortHash h | (qn, h) <- deps ]\n        shown = take 6 entries\n        suffix = if length entries > 6 then \" +\" ++ show (length entries - 6) ++ \" more\" else \"\"\n    in \"[\" ++ intercalate \", \" shown ++ suffix ++ \"]\"\n\n-- | Format a verbose cache log line for a test.\nformatTestCacheLog :: String -> String -> TestHashInfo -> Maybe TestCacheEntry -> String\nformatTestCacheLog modName testName info entry =\n    let testLabel = formatTestName modName testName\n        candidates = intercalate \", \" (testNameCandidates testName)\n        cacheStatus =\n          case (thiRunHash info, entry) of\n            (Just runHash, Just e) | tceRunHash e == runHash -> \"hit\"\n            (Just _, Just _) -> \"miss (hash)\"\n            (Just _, Nothing) -> \"miss (none)\"\n            (Nothing, _) -> \"miss (no hash)\"\n        base = \"[test-cache] \" ++ testLabel\n        implDeps = maybe \"\" (\\deps -> \" deps=\" ++ formatDepsShort deps) (thiImplDeps info)\n    in case info of\n         TestHashInfo (Just implHash) (Just runHash) resolved _ ->\n           base\n             ++ \" name=\" ++ maybe \"?\" id resolved\n             ++ \" impl=\" ++ shortHash implHash\n             ++ \" run=\" ++ shortHashStr runHash\n             ++ implDeps\n             ++ \" cache=\" ++ cacheStatus\n         _ ->\n           base\n             ++ \" no impl hash\"\n             ++ \" candidates=[\" ++ candidates ++ \"]\"\n             ++ \" cache=\" ++ cacheStatus\n\n-- | Build TestHashInfo records for a list of tests.\nbuildTestHashInfos :: Compile.Paths\n                   -> B.ByteString\n                   -> [(String, [String])]\n                   -> IO (M.Map String TestHashInfo)\nbuildTestHashInfos paths ctxHash testsByModule = do\n    moduleHashes <- forM testsByModule $ \\(modName, _) -> do\n      nameHashes <- readModuleNameHashes paths modName\n      return (modName, nameHashes)\n    let nameHashesByModule = M.fromList moduleHashes\n        seedCache = M.fromList\n          [ (A.modName (splitOnDot modName), nameMap)\n          | (modName, nameMap) <- M.toList nameHashesByModule\n          ]\n        allTests =\n          concatMap (\\(modName, names) -> map (\\name -> (modName, name)) names) testsByModule\n    depCacheRef <- newIORef seedCache\n    M.fromList <$> forM allTests (\\(modName, testName) -> do\n      let nameMap = M.findWithDefault M.empty modName nameHashesByModule\n      info <- buildTestHashInfo depCacheRef paths ctxHash nameMap testName\n      return (mkTestKey modName testName, info))\n\n-- | Split tests into cached results and ones to run.\nclassifyCachedTests :: (String -> IO ())\n                    -> M.Map String TestCacheEntry\n                    -> M.Map String TestHashInfo\n                    -> [(String, String)]\n                    -> IO ([TestResult], [(String, String)])\nclassifyCachedTests logLine cacheEntries testHashInfos allTests = do\n    classified <- forM allTests $ \\(modName, testName) -> do\n      let key = mkTestKey modName testName\n          info = M.findWithDefault (TestHashInfo Nothing Nothing Nothing Nothing) key testHashInfos\n          entry = M.lookup key cacheEntries\n      logLine (formatTestCacheLog modName testName info entry)\n      case entry of\n        Just cached\n          | Just runHash <- thiRunHash info\n          , tceRunHash cached == runHash ->\n              return (Left (testResultFromCache modName testName (tceResult cached)))\n        _ -> return (Right (modName, testName))\n    return (partitionEithers classified)\n\n-- | Build a cache key from module and test name.\nmkTestKey :: String -> String -> String\nmkTestKey modName testName = modName ++ \":\" ++ testName\n\n-- | Drop a prefix once if present.\nstripPrefixOnce :: String -> String -> Maybe String\nstripPrefixOnce pref s\n  | pref `isPrefixOf` s = Just (drop (length pref) s)\n  | otherwise = Nothing\n\n-- | Drop a suffix once if present.\nstripSuffixOnce :: String -> String -> Maybe String\nstripSuffixOnce suff s\n  | suff `isSuffixOf` s = Just (take (length s - length suff) s)\n  | otherwise = Nothing\n\n-- | Generate alternate test names for wrapper/prefix variants.\ntestNameCandidates :: String -> [String]\ntestNameCandidates name =\n    nub $ catMaybes\n      [ Just name\n      , stripSuffixOnce \"_wrapper\" name\n      , stripPrefixOnce \"_test_\" name\n      , stripPrefixOnce \"_test_\" =<< stripSuffixOnce \"_wrapper\" name\n      , stripSuffixOnce \"_wrapper\" =<< stripPrefixOnce \"_test_\" name\n      ]\n\n-- | Resolve a test name to the stored NameHashInfo, if any.\nlookupTestInfo :: M.Map String InterfaceFiles.NameHashInfo -> String -> Maybe (String, InterfaceFiles.NameHashInfo)\nlookupTestInfo nameMap testName =\n    listToMaybe [ (cand, info)\n                | cand <- testNameCandidates testName\n                , Just info <- [M.lookup cand nameMap]\n                ]\n\n-- | Read the name hash map for a module name string.\nreadModuleNameHashes :: Compile.Paths -> String -> IO (M.Map String InterfaceFiles.NameHashInfo)\nreadModuleNameHashes paths modName =\n    readModuleNameHashesByModName paths (A.modName (splitOnDot modName))\n\n-- | Split a module name string on dots.\nsplitOnDot :: String -> [String]\nsplitOnDot = splitOnChar '.'\n\n-- | Split a string on a single delimiter character.\nsplitOnChar :: Char -> String -> [String]\nsplitOnChar ch input = case break (== ch) input of\n  (chunk, []) -> [chunk]\n  (chunk, _ : rest) -> chunk : splitOnChar ch rest\n\n-- | Read the name hash map for a module name.\nreadModuleNameHashesByModName :: Compile.Paths -> A.ModName -> IO (M.Map String InterfaceFiles.NameHashInfo)\nreadModuleNameHashesByModName paths mn = do\n    mty <- Acton.Env.findTyFile (Compile.searchPath paths) mn\n    case mty of\n      Nothing -> return M.empty\n      Just tyFile -> do\n        hdrE <- (try :: IO a -> IO (Either SomeException a)) $ InterfaceFiles.readHeader tyFile\n        case hdrE of\n          Left _ -> return M.empty\n          Right (_sourceMeta, _srcH, _ih, _implH, _imps, nameHashes, _roots, _tests, _doc) ->\n            return $ M.fromList [ (A.nstr (InterfaceFiles.nhName nh), nh) | nh <- nameHashes ]\n\n-- | Cache-aware wrapper for reading name hashes.\nreadModuleNameHashesCached :: IORef (M.Map A.ModName (M.Map String InterfaceFiles.NameHashInfo))\n                           -> Compile.Paths\n                           -> A.ModName\n                           -> IO (M.Map String InterfaceFiles.NameHashInfo)\nreadModuleNameHashesCached cacheRef paths mn = do\n    cache <- readIORef cacheRef\n    case M.lookup mn cache of\n      Just nameMap -> return nameMap\n      Nothing -> do\n        nameMap <- readModuleNameHashesByModName paths mn\n        atomicModifyIORef' cacheRef (\\m -> (M.insert mn nameMap m, ()))\n        return nameMap\n\n-- | Resolve a dependency QName to its current impl hash, if any.\nresolveDepImplHash :: IORef (M.Map A.ModName (M.Map String InterfaceFiles.NameHashInfo))\n                   -> Compile.Paths\n                   -> A.QName\n                   -> IO (Maybe (A.QName, B.ByteString))\nresolveDepImplHash cacheRef paths qn =\n    case qn of\n      A.GName m n -> resolve m n (A.GName m n)\n      A.QName m n -> resolve m n (A.GName m n)\n      A.NoQ _ -> return Nothing\n  where\n    resolve m n qn' = do\n      nameMap <- readModuleNameHashesCached cacheRef paths m\n      return $ (\\info -> (qn', InterfaceFiles.nhImplHash info)) <$> M.lookup (A.nstr n) nameMap\n\n-- | Resolve recorded impl deps to current hashes, preserving fallbacks.\nresolveTestImplDeps :: IORef (M.Map A.ModName (M.Map String InterfaceFiles.NameHashInfo))\n                    -> Compile.Paths\n                    -> InterfaceFiles.NameHashInfo\n                    -> IO [(A.QName, B.ByteString)]\nresolveTestImplDeps cacheRef paths info = do\n    let deps = InterfaceFiles.nhImplDeps info\n    forM deps $ \\(qn, recorded) -> do\n      resolved <- resolveDepImplHash cacheRef paths qn\n      return (fromMaybe (qn, recorded) resolved)\n\n-- | Build the hash info for a single test name.\nbuildTestHashInfo :: IORef (M.Map A.ModName (M.Map String InterfaceFiles.NameHashInfo))\n                  -> Compile.Paths\n                  -> B.ByteString\n                  -> M.Map String InterfaceFiles.NameHashInfo\n                  -> String\n                  -> IO TestHashInfo\nbuildTestHashInfo cacheRef paths ctxHash nameMap testName = do\n    case lookupTestInfo nameMap testName of\n      Nothing -> return (TestHashInfo Nothing Nothing Nothing Nothing)\n      Just (resolved, info) -> do\n        let implHash = InterfaceFiles.nhImplHash info\n        deps <- resolveTestImplDeps cacheRef paths info\n        let depsHash = hashDeps deps\n            runHash = hashRun implHash depsHash ctxHash\n        return (TestHashInfo (Just implHash) (Just runHash) (Just resolved) (Just deps))\n\n-- | Update the cache map with a new test result.\nupdateTestCacheEntry :: M.Map String TestHashInfo\n                     -> M.Map String TestCacheEntry\n                     -> TestResult\n                     -> M.Map String TestCacheEntry\nupdateTestCacheEntry testHashInfos acc res =\n    let key = mkTestKey (trModule res) (trName res)\n        info = M.lookup key testHashInfos\n        runHash = maybe \"\" (\\ti -> fromMaybe \"\" (thiRunHash ti)) info\n        implHashHex = info >>= fmap toHex . thiImplHash\n        entry = TestCacheEntry\n          { tceRunHash = runHash\n          , tceImplHash = implHashHex\n          , tceResult = cachedResultFromTest res\n          }\n    in M.insert key entry acc\n\n-- | Format a module+test display name.\nformatTestName :: String -> String -> String\nformatTestName modName testName = modName ++ \".\" ++ testName\n"
  },
  {
    "path": "compiler/lib/src/Acton/Transform.hs",
    "content": "-- Copyright (C) 2019-2021 Data Ductus AB\n--\n-- Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:\n--\n-- 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.\n--\n-- 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.\n--\n-- 3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission.\n--\n-- THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS \"AS IS\" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n--\n\n{-# LANGUAGE MultiParamTypeClasses, FlexibleInstances, FlexibleContexts #-}\nmodule Acton.Transform where\n\nimport qualified Data.HashMap.Strict as M\n\nimport Utils\nimport Acton.Syntax\nimport Acton.Names\nimport Acton.Builtin\nimport Acton.Prim\nimport Acton.Printer\nimport Acton.TypeEnv\n\n\ntermred                                 :: Equations -> Stmt -> Stmt\ntermred eq s                            = --trace (\"### equations:\\n\" ++ render (nest 4 $ vcat $ map pretty eq)) $\n                                          --trace (\"### termred:\\n\" ++ render (nest 4 $ pretty s)) $\n                                          trans env0{ eqns = eq } s\n\ntermsubst                               :: (Transform a) => [(Name,Expr)] -> a -> a\ntermsubst [] x                          = x\ntermsubst s x                           = trans (finalize $ extsubst s env0) x\n\nclass Transform a where\n    trans                               :: TransEnv -> a -> a\n\ntype TSubst                             = M.HashMap Name (Maybe Expr)\n\ndata TransEnv                           = TransEnv {\n                                            eqns     :: Equations,                  -- Top-level constraint solutions\n                                            trsubst  :: TSubst,                     -- Inlineable assignments and scope blockers\n                                            witscope :: [(Name,Type,Expr)],         -- Preserved witness bindings in scope, for the purpose of duplicate removals\n                                            final    :: Bool\n                                          }\n\nenv0                                    = TransEnv{ eqns = [], trsubst = M.empty, witscope = [], final = False }\n\nblockscope ns env                       = env{ trsubst = foldr (`M.insert` Nothing) (trsubst env) ns }\n\nextsubst ns env                         = env{ trsubst = foldr (\\(n,e) -> M.insert n (Just e)) (trsubst env) ns }\n\nlimsubst ns env                         = env{ trsubst = foldr M.delete (trsubst env) ns }\n\ntrfind n env                            = case M.lookup n (trsubst env) of\n                                            Just (Just e) -> Just e\n                                            _ -> Nothing\n\ntrfinds ns env                          = [ e | n <- ns, Just e <- [trfind n env] ]\n\n\nextscope n t e env                      = env{ witscope = (n,t,e) : witscope env }\n\nequalwit env e t                        = listToMaybe [ eVar w | (w,t',e') <- witscope env, e' == e, t' == t ]\n\nfinalize env                            = env{ final = True }\n\n\ninstance Pretty (Name,Expr) where\n    pretty (n,e)                        = pretty n <+> text \"~\" <+> pretty e\n\nwtrans env ss\n  | final env                           = map (trans env) ss\nwtrans env (Signature _ ws (TSchema _ [] (TWild _)) NoDec : ss)\n                                        = wtrans env (bindWits eq ++ ss)\n  where eq                              = findeqns ws (eqns env)\nwtrans env (s@(Assign l p@[PVar _ w (Just t)] e) : ss)\n  | not (isWitness w)                   = trans env s : wtrans env ss\n  | Lambda{} <- e                       = wtrans (extsubst [(w,e1)] env) ss\n  | TApp _ Var{} _ <- e                 = wtrans (extsubst [(w,e1)] env) ss\n  | Var{} <- e                          = wtrans (extsubst [(w,e1)] env) ss\n  | Dot _ Var{} _ <- e                  = wtrans (extsubst [(w,e1)] env) ss\n  | Just e' <- equalwit env e t         = wtrans (extsubst [(w,e')] env) ss\n  | otherwise                           = Assign l p e1 : wtrans (extscope w t e1 env) ss\n  where e1                              = trans env e\nwtrans env (s:ss)                       = trans env s : wtrans env ss\nwtrans env []                           = []\n\ninstance (Transform a) => Transform [a] where\n    trans env                           = map (trans env)\n\ninstance (Transform a) => Transform (Maybe a) where\n    trans env                           = fmap (trans env)\n\ninstance Transform Stmt where\n    trans env (Assign l ps e)           = Assign l ps (trans env e)\n    trans env (Expr l e)                = Expr l (trans env e)\n    trans env (MutAssign l t e)         = MutAssign l (trans env t) (trans env e)\n    trans env (AugAssign l t op e)      = AugAssign l (trans env t) op (trans env e)\n    trans env (Assert l e mbe)          = Assert l (trans env e) (trans env mbe)\n    trans env (Delete l t)              = Delete l (trans env t)\n    trans env (Return l mbe)            = Return l (trans env mbe)\n    trans env (Raise l e)               = Raise l (trans env e)\n    trans env (If l bs els)             = If l (trans env bs) (trans env els)\n    trans env (While l e b els)         = While l (trans env e) (trans env b) (trans env els)\n    trans env (For l p e b els)         = For l p (trans env e) (trans env1 b) (trans env els)\n      where env1                        = blockscope (bound p) env\n    trans env (Try l b hs els fin)      = Try l (trans env b) (trans env hs) (trans env els) (trans env fin)\n    trans env (With l is b)             = With l (trans env1 is) (wtrans env1 b)\n      where env1                        = blockscope (bound is) env\n    trans env (Data l mbp ss)           = Data l mbp (trans env ss)\n    trans env (VarAssign l ps e)        = VarAssign l ps (trans env e)\n    trans env (After l e e')            = After l (trans env e) (trans env e')\n    trans env (Decl l ds)               = Decl l (trans env ds)\n    trans env s                         = s\n\ninstance Transform Decl where\n    trans env (Def l n q p k t b d fx doc)\n                                        = Def l n q (trans env1 p) (trans env1 k) t (wtrans env1 b) d fx doc\n      where env1                        = blockscope (bound p ++ bound k) env\n    trans env (Actor l n q p k b doc)   = Actor l n q (trans env1 p) (trans env1 k) (wtrans env1 b) doc\n      where env1                        = blockscope (bound p ++ bound k) env\n    trans env (Class l n q us b doc)    = Class l n q us (wtrans env b) doc\n    trans env (Protocol l n q us b doc) = Protocol l n q us (wtrans env b) doc\n    trans env (Extension l n q us b doc)= Extension l n q us (wtrans env b) doc\n\ntransCall (Dot _ (Var _ n) m) ts [e1,e2]\n  | n == primWrapProc,  m == attrWrap   = Just e2\n  | n == primWrapAction,m == attrWrap   = Just $ eCall (tApp (eQVar primWRAP) ts) [e1,e2]\n  | n == primWrapMut,   m == attrWrap   = Just e2\n  | n == primWrapPure,  m == attrWrap   = Just e2\ntransCall (Dot _ (Var _ n) m) ts [e1]\n  | n == primWrapProc,  m == attrUnwrap = Just e1\n  | n == primWrapAction,m == attrUnwrap = Just e1\n  | n == primWrapMut,   m == attrUnwrap = Just e1\n  | n == primWrapPure,  m == attrUnwrap = Just e1\ntransCall _ _ _                         = Nothing\n\ninstance Transform Expr where\n    trans env (Var l (NoQ n))\n      | Just e <- trfind n env          = if final env then e else trans (blockscope [n] env) e\n\n    trans env ee@(Call l e p k)\n      | Lambda{} <- e',\n        Just s1 <- pzip (ppar e') p',\n        Just s2 <- kzip (kpar e') k'    = termsubst (s1++s2) (exp1 e')     -- TODO: check that e' is linear in all its parameters!\n      | TApp _ e0 ts <- e',\n        Just e1 <- transCall e0 ts es   = e1\n      | otherwise                       = Call l e' p' k'\n      where e'                          = trans env e\n            p'                          = trans env p\n            k'                          = trans env k\n            es                          = posargs p'\n    trans env (TApp l e ts)             = TApp l (trans env e) ts\n    trans env (Async l e)               = Async l (trans env e)\n    trans env (Await l e)               = Await l (trans env e)\n    trans env (Let l ss e)              = Let l (trans env ss) (trans env e)\n    trans env (Index l e is)            = Index l (trans env e) (trans env is)\n    trans env (Slice l e sl)            = Slice l (trans env e) (trans env sl)\n    trans env (Cond l e1 e2 e3)         = Cond l (trans env e1) (trans env e2) (trans env e3)\n    trans env (IsInstance l e c)        = IsInstance l (trans env e) c\n    trans env (BinOp l e1 op e2)        = BinOp l (trans env e1) op (trans env e2)\n    trans env (CompOp l e ops)          = CompOp l (trans env e) (trans env ops)\n    trans env (UnOp l op e)             = UnOp l op (trans env e)\n    trans env (Dot l e n)\n      | n `elem` valueKWs               = Dot l e' n\n      | Tuple{} <- e'                   = kwditem n $ kargs e'                              -- TODO: outrule side-effects in e\n      | otherwise                       = Dot l e' n\n      where e'                          = trans env e\n    trans env (OptChain l e)            = OptChain l (trans env e)\n    trans env (Rest l e n)\n      | Tuple{} <- e'                   = Tuple NoLoc PosNil (kwdrest n $ kargs e')         -- TODO: outrule side-effects in e\n      | otherwise                       = Rest l e' n\n      where e'                          = trans env e\n    trans env (DotI l e i)\n      | Tuple{} <- e'                   = positem i $ pargs e'                              -- TODO: outrule side-effects in e\n      | otherwise                       = DotI l e' i\n      where e'                          = trans env e\n    trans env (RestI l e i)\n      | Tuple{} <- e'                   = Tuple NoLoc (posrest i $ pargs e') KwdNil         -- TODO: outrule side-effects in e\n      | otherwise                       = RestI l e' i\n      where e'                          = trans env e\n    trans env e0@(Lambda l p k e fx)\n      | null clash                      = eta $ Lambda l (trans env1 p) (trans env1 k) (trans env1 e) fx\n      | otherwise                       = eta $ Lambda l (trans env1 $ prename s p) (trans env1 $ krename s k) (trans env1 $ erename s e) fx\n      where fvs                         = free e\n            bvs                         = bound p ++ bound k\n            env1                        = limsubst bvs env\n            clash                       = bvs `intersect` free (trfinds fvs env1)\n            s                           = clash `zip` (yNames \\\\ (fvs++bvs))\n            e1                          = Lambda l (prename s p) (krename s k) (erename s e) fx\n    trans env (Yield l e)               = Yield l (trans env e)\n    trans env (YieldFrom l e)           = YieldFrom l (trans env e)\n    trans env (Tuple l p k)             = Tuple l (trans env p) (trans env k)\n    trans env (List l es)               = List l (trans env es)\n    trans env (ListComp l e c)          = ListComp l (trans env1 e) (trans env1 c)\n      where env1                        = blockscope (bound c) env\n    trans env (Dict l as)               = Dict l (trans env as)\n    trans env (DictComp l a c)          = DictComp l (trans env1 a) (trans env1 c)\n      where env1                        = blockscope (bound c) env\n    trans env (Set l es)                = Set l (trans env es)\n    trans env (SetComp l e c)           = SetComp l (trans env1 e) (trans env1 c)\n      where env1                        = blockscope (bound c) env\n--    trans env (Paren l e)               = Paren l (trans env e)\n    trans env (Paren l e)               = trans env e\n    trans env e                         = e\n\neta (Lambda _ p k (Call _ e p' k') fx)\n  | eq1 p p' && eq2 k k'                = e\n  where\n    eq1 (PosPar n _ _ p) (PosArg e p')  = eVar n == e && eq1 p p'\n    eq1 (PosSTAR n _) (PosStar e)       = eVar n == e\n    eq1 PosNIL PosNil                   = True\n    eq1 _ _                             = False\n    eq2 (KwdPar n _ _ k) (KwdArg _ e k')= eVar n == e && eq2 k k'                       -- Requires perfectly sorted args, which the type-checker produces\n    eq2 (KwdSTAR n _) (KwdStar e)       = eVar n == e\n    eq2 KwdNIL KwdNil                   = True\n    eq2 _ _                             = False\neta ee@(Lambda _ (PosPar n (Just t) Nothing PosNIL) KwdNIL (Tuple _ p k) (TFX _ FXPure))\n  | idtup t p k                         = eLambda [(n,t)] (eVar n)\n  where idtup (TTuple _ prow krow) p k  = ptup (eVar n) 0 prow p && ktup (eVar n) krow k\n        ptup e0 i TNil{} PosNil         = True\n        ptup e0 i r@TRow{} (PosArg e p) = idot e0 i e && ptup e0 (i+1) (rtail r) p\n        ptup e0 i r@TStar{} (PosStar e)\n          | Tuple _ p KwdNil <- e       = ptup (eDotI e0 i) 0 (rtail r) p\n          | otherwise                   = idot e0 i e\n        ptup e0 i _ _                   = False\n        idot e0 i (DotI _ e i')         = e == e0 && i' == i\n        idot e0 i _                     = False\n        ktup e0 TNil{} KwdNil           = True\n        ktup e0 r@TRow{} (KwdArg x e k) = x == label r && xdot e0 x e && ktup e0 (rtail r) k\n        ktup e0 r@TStar{} (KwdStar e)\n          | Tuple _ PosNil k <- e       = ktup (eDot e0 attrKW) (rtail r) k\n          | otherwise                   = xdot e0 attrKW e\n        ktup e0 _ _                     = False\n        xdot e0 x (Dot _ e x')          = e == e0 && x' == x\n        xdot e0 x _                     = False\neta e                                   = e\n\npzip (PosPar n _ _ p) (PosArg e a)      = do p' <- pzip p a; return $ (n, e) : p'\npzip (PosSTAR n _) (PosStar e)          = Just [(n, e)]\npzip PosNIL _                           = Just []\npzip _ _                                = Nothing\n\nkzip (KwdPar n _ _ k) (KwdArg _ e a)    = do k' <- kzip k a; return $ (n, e) : k'       -- Requires perfectly sorted args, which the type-checker produces\nkzip (KwdSTAR n _) (KwdStar e)          = Just [(n, e)]\nkzip KwdNIL _                           = Just []\nkzip _ _                                = Nothing\n\npositem 0 (PosArg e _)                  = e\npositem i (PosArg _ p)                  = positem (i-1) p\n\nkwditem n (KwdArg n' e _) | n == n'     = e\nkwditem n (KwdArg _ _ k)                = kwditem n k\nkwditem n (KwdStar e) | n == attrKW     = e\nkwditem n arg                           = error (\"#### Bad kwditem \" ++ prstr n ++ \" in \" ++ prstr arg)\n\nposrest 0 (PosArg _ p)                  = p\nposrest i (PosArg e p)                  = PosArg e (posrest (i-1) p)\n\nkwdrest n (KwdArg n' e k) | n == n'     = k\nkwdrest n (KwdArg n' e k)               = KwdArg n' e (kwdrest n k)\n\n\nprename s (PosPar n t e p)              = PosPar (rename s n) t e (prename s p)\nprename s (PosSTAR n t)                 = PosSTAR (rename s n) t\nprename s p                             = p\n\nkrename s (KwdPar n t e k)              = KwdPar (rename s n) t e (krename s k)\nkrename s (KwdSTAR n t)                 = KwdSTAR (rename s n) t\nkrename s k                             = k\n\nrename s n                              = case lookup n s of\n                                            Just n' -> n'\n                                            _ -> n\n\nerename s e                             = termsubst [ (n, eVar n') | (n,n') <- s ] e\n\ninstance Transform Branch where\n    trans env (Branch e ss)             = Branch (trans env e) (trans env ss)\n\ninstance Transform Handler where\n    trans env (Handler ex b)            = Handler ex (trans env1 b)\n      where env1                        = blockscope (bound ex) env\n\ninstance Transform PosPar where\n    trans env (PosPar n t e p)          = PosPar n t (trans env e) (trans env p)\n    trans env p                         = p\n\ninstance Transform KwdPar where\n    trans env (KwdPar n t e k)          = KwdPar n t (trans env e) (trans env k)\n    trans env k                         = k\n\ninstance Transform PosArg where\n    trans env (PosArg e p)              = PosArg (trans env e) (trans env p)\n    trans env (PosStar e)               = PosStar (trans env e)\n    trans env PosNil                    = PosNil\n\ninstance Transform KwdArg where\n    trans env (KwdArg n e k)            = KwdArg n (trans env e) (trans env k)\n    trans env (KwdStar e)               = KwdStar (trans env e)\n    trans env KwdNil                    = KwdNil\n\ninstance Transform OpArg where\n    trans env (OpArg op e)              = OpArg op (trans env e)\n\ninstance Transform Comp where\n    trans env (CompFor l p e c)         = CompFor l p (trans env e) (trans env c)\n    trans env (CompIf l e c)            = CompIf l (trans env e) (trans env c)\n    trans env NoComp                    = NoComp\n\ninstance Transform WithItem where\n    trans env (WithItem e p)            = WithItem (trans env e) p\n\ninstance Transform Elem where\n    trans env (Elem e)                  = Elem (trans env e)\n    trans env (Star e)                  = Star (trans env e)\n\ninstance Transform Assoc where\n    trans env (Assoc e1 e2)             = Assoc (trans env e1) (trans env e2)\n    trans env (StarStar e)              = StarStar (trans env e)\n\ninstance Transform Sliz where\n    trans env (Sliz l e1 e2 e3)         = Sliz l (trans env e1) (trans env e2) (trans env e3)\n"
  },
  {
    "path": "compiler/lib/src/Acton/TypeEnv.hs",
    "content": "-- Copyright (C) 2019-2021 Data Ductus AB\n--\n-- Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:\n--\n-- 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.\n--\n-- 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.\n--\n-- 3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission.\n--\n-- THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS \"AS IS\" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n--\n\n{-# LANGUAGE FlexibleInstances, FlexibleContexts, DeriveGeneric #-}\nmodule Acton.TypeEnv where\n\nimport Control.Monad\nimport qualified Control.Exception\nimport Control.Monad.State.Strict\nimport Control.Monad.Except\nimport Data.Char\nimport Error.Diagnose hiding ((<>), err)\nimport Prelude hiding ((<>))\n\nimport qualified Data.Map.Strict as Map\nimport Data.Map.Strict (Map)\n\nimport qualified Data.Set as Set\nimport Data.Set (Set)\n\nimport qualified Data.IntMap.Strict as IntMap\nimport Data.IntMap.Strict (IntMap)\nimport qualified Data.IntSet as IntSet\nimport Data.IntSet (IntSet)\n\nimport Pretty\nimport Utils\nimport Acton.Syntax\nimport Acton.Builtin\nimport Acton.Prim\nimport Acton.Printer\nimport Acton.Names\nimport Acton.NameInfo\nimport Acton.Subst\nimport Acton.Env\n\n\ndata TypeX                      = TypeX {\n                                    activeWits  :: [Witness],\n                                    closedWits  :: [Witness],\n                                    activeWitMap :: WitMap,\n                                    closedWitMap :: WitMap,\n                                    posnames    :: [Name],\n                                    indecl      :: Bool,\n                                    forced      :: Bool,\n                                    tyids       :: Map QName Int,\n                                    tyinfos     :: IntMap TyInfo,\n                                    typrotos    :: IntSet,\n                                    tyactors    :: IntSet\n                                  }\n\ndata TyInfo                     = TyInfo {\n                                    tywild      :: Type,\n                                    tyabove     :: IntSet,\n                                    tybelow     :: IntSet,\n                                    tyattrs     :: Set Name\n                                  }\n\ntype Env                        = EnvF TypeX\ntype WitMap                     = Map QName [Witness]\n\ninitTypeEnv                     :: Env0 -> Env\ninitTypeEnv env0                = setX env0 $ foldl' importInfo x0 imps\n  where x0                      = TypeX {\n                                    activeWits  = [],\n                                    closedWits  = primWits,\n                                    activeWitMap = Map.empty,\n                                    closedWitMap = witMap primWits,\n                                    posnames    = [],\n                                    indecl      = False,\n                                    forced      = False,\n                                    tyids       = Map.empty,\n                                    tyinfos     = tyinfos0,\n                                    typrotos    = IntSet.empty,\n                                    tyactors    = IntSet.empty\n                                  }\n        importInfo x (m,te)     = setupCons f te $ setupWits addClosedWit f te x\n          where f               = GName m\n        imps | inBuiltin env0   = []\n             | otherwise        = [ (m, fromJust $ lookupMod m env0) | m <- mBuiltin : transitiveImports env0 ]\n\n\ntyinfos0                        = IntMap.fromDistinctAscList pairs\n  where pairs                   = [ (tyid t, TyInfo t (iset above) (iset below) Set.empty) | (t,above,below) <- graph ]\n        tyid t                  = fromJust $ elemIndex t wtypes\n        iset ts                 = IntSet.fromDistinctAscList $ map tyid ts\n        wtypes                  = [ t | (t,_,_) <- graph ]\n        graph                   = [\n                                    (wOpt,      [wOpt],                 [wOpt,tNone]),      -- Watch out for tNone here!\n                                    (tNone,     [wOpt,tNone],           [tNone]),\n                                    (wFun,      [wOpt, wFun],           [wFun]),\n                                    (wTuple,    [wOpt, wTuple],         [wTuple]),\n                                    (fxProc,    [fxProc],               [fxProc,fxMut,fxPure,fxAction]),\n                                    (fxMut,     [fxProc,fxMut],         [fxMut,fxPure]),\n                                    (fxPure,    [fxProc,fxMut,fxPure],  [fxPure]),\n                                    (fxAction,  [fxProc,fxAction],      [fxAction])\n                                  ]\n        wFun                    = tFun tWild tWild tWild tWild\n        wTuple                  = tTuple tWild tWild\n        wOpt                    = tOpt tWild\n\ninstance Show TypeX where\n    show _                      = \"\"\n\nprintX env                      = render (nest 4 $ vcat $ map (prinfo x) $ Map.assocs $ tyids x)\n  where x                       = envX env\n\n\ninstance Pretty TypeX where\n    pretty x                    = text \"--- witnesses:\"  $+$\n                                  vcat (map pretty (witnesses x))\n\nprinfo x (n, tid)               = pretty (noq n) <+> text \"=\" <+> pretty tid <> colon $+$\n                                  nest 4 (text \"above\" <> colon <+> commaSep pretty (IntSet.toAscList $ tyabove info) $+$\n                                          text \"below\" <> colon <+> commaSep pretty (IntSet.toAscList $ tybelow info) $+$\n                                          text \"attrs\" <> colon <+> commaSep pretty (Set.elems $ tyattrs info))\n  where info                    = tyinfos x IntMap.! tid\n\ninstance USubst TypeX where\n    usubst x                    = do we <- usubst (activeWits x)\n                                     return x{ activeWits = we, activeWitMap = witMap we }\n\ninstance UFree TypeX where\n    ufree x                     = ufree (activeWits x)\n\nwitnesses                       :: TypeX -> [Witness]\nwitnesses x                     = activeWits x ++ closedWits x\n\nwitMap                          :: [Witness] -> WitMap\nwitMap                          = foldr addWit Map.empty\n\n\nnextid x                        = 1 + fst (IntMap.findMax $ tyinfos x)\n\naddconinfo                      :: (Name -> QName) -> TypeX -> (Name,NameInfo) -> TypeX\naddconinfo f x (n,i)\n  | NClass q us te _ <- i       = addcon n q us te x\n  | NProto q us te _ <- i       = addproto $ addcon n q us te x\n  | NAct q _ _ te _ <- i        = addactor $ addcon n q [] te x\n  | otherwise                   = x\n  where tid                     = nextid x\n        addproto x              = x{ typrotos = IntSet.insert tid (typrotos x) }\n        addactor x              = x{ tyactors = IntSet.insert tid (tyactors x) }\n\n        addcon n q us te x      = x{ tyids = Map.insert (f n) tid (tyids x), tyinfos = IntMap.insert tid info tyinfos' }\n          where ui              = [ tyids x Map.! tcname c | (_,c) <- us ]\n                info            = TyInfo {\n                                    tywild = tCon $ TC (NoQ n) [ tWild | _ <- q ],\n                                    tyabove = IntSet.fromList ui,\n                                    tybelow = IntSet.singleton tid,\n                                    tyattrs = foldr Set.union (Set.fromList $ dom te) [ tyattrs $ fromJust $ IntMap.lookup u $ tyinfos x | u <- ui ]\n                                  }\n                tyinfos'        = foldr (IntMap.adjust addbelow) (tyinfos x) ui\n                addbelow info   = info{ tybelow = IntSet.insert tid (tybelow info) }\n\n\n\ntydefine                        :: TEnv -> Env -> Env\ntydefine te env                 = modX (define te env) (setupCons f te . setupWits addActiveWit NoQ te)\n  where f                       = if inBuiltin env then GName mBuiltin else NoQ\n\ntydefineClosed                  :: TEnv -> Env -> Env\ntydefineClosed te env           = modX (defineClosed te env) (setupCons f te . setupWits addClosedWit NoQ te)\n  where f                       = if inBuiltin env then GName mBuiltin else NoQ\n\nsetupCons                       :: (Name -> QName) -> TEnv -> TypeX -> TypeX\nsetupCons f te x                = foldl' (addconinfo f) x te\n \nsetupWits                       :: (TypeX -> Witness -> TypeX) -> (Name -> QName) -> TEnv -> TypeX -> TypeX\nsetupWits add f te x            = foldl' add x wits\n  where wits                    = [ WClass q (tCon c) p (f n) ws (length opts) | (n, NExt q c ps te' opts _) <- te, (ws,p) <- ps ]\n\naddvarinfo x (tv, c, _)         = x{ tyids = Map.insert (NoQ $ tvname tv) tid (tyids x), tyinfos = IntMap.insert tid info tyinfos' }\n  where tid                     = nextid x\n        ci                      = tyinfos x IntMap.! (tyids x Map.! tcname c)\n        info                    = TyInfo {\n                                    tywild = tVar tv,\n                                    tyabove = IntSet.insert tid $ tyabove ci,\n                                    tybelow = IntSet.singleton tid,\n                                    tyattrs = tyattrs ci\n                                  }\n        tyinfos'                = IntSet.foldr' (IntMap.adjust addbelow) (tyinfos x) (tyabove ci)\n        addbelow info           = info{ tybelow = IntSet.insert tid (tybelow info) }\n\ntydefineVars                    :: QBinds -> Env -> Env\ntydefineVars q env              = modX env1 (\\x -> foldl' addvarinfo x tvs)\n  where env1                    = modX env0 (\\x -> foldl' addActiveWit x wits)\n        env0                    = defineTVars q env\n        tvs                     = [ (TV k v, c, us) | (v, NTVar k c us) <- take (length q) (activeNames env0), let tv = TV k v ]\n        wits                    = [ WInst [] (tVar tv) p (NoQ $ tvarWit tv u) wchain | (tv, _, us) <- tvs, u <- us, (wchain,p) <- findAncestry env u ]\n\ntydefineInst                    :: TCon -> [WTCon] -> Name -> Env -> Env\ntydefineInst c ps w env         = modX env (\\x -> foldl' addActiveWit x wits)\n  where wits                    = [ WInst [] (tCon c) p (NoQ w) ws | (ws,p) <- ps ]\n\naddActiveWit                    :: TypeX -> Witness -> TypeX\naddActiveWit x wit\n  | null same                   = x{ activeWits = wit : activeWits x,\n                                     activeWitMap = addWit wit (activeWitMap x) }\n  | otherwise                   = x\n  where same                    = [ w | w <- witsByPNameX x (tcname $ proto wit), wtype w == wtype wit ]\n\naddClosedWit                    :: TypeX -> Witness -> TypeX\naddClosedWit x wit\n  | null same                   = x{ closedWits = wit : closedWits x,\n                                     closedWitMap = addWit wit (closedWitMap x) }\n  | otherwise                   = x\n  where same                    = [ w | w <- witsByPNameX x (tcname $ proto wit), wtype w == wtype wit ]\n\naddWit                          :: Witness -> WitMap -> WitMap\naddWit w                        = Map.insertWith (++) (tcname $ proto w) [w]\n\nwitsByPNameX x pn               = Map.findWithDefault [] pn (activeWitMap x) ++\n                                  Map.findWithDefault [] pn (closedWitMap x)\n\nwitsByPName                     :: Env -> QName -> [Witness]\nwitsByPName env pn              = witsByPNameX (envX env) pn\n\nwitsByTName                     :: Env -> QName -> [Witness]\nwitsByTName env tn              = [ w | w <- activeWits x, eqname (wtype w) ] ++\n                                  [ w | w <- closedWits x, eqname (wtype w) ]\n  where eqname (TCon _ c)       = tcname c == tn\n        eqname (TVar _ v)       = NoQ (tvname v) == tn\n        eqname _                = False\n        x                       = envX env\n\nlimitQuant                      :: TUni -> Env -> Env\nlimitQuant (UV _ l _) env\n  | n <= 0                      = env\n  | otherwise                   = modX env1 $ \\x -> let we = dropw (activeWits x)\n                                                    in x{ activeWits = we, activeWitMap = witMap we }\n  where env1                    = setActiveNames (dropv n (activeNames env)) env{ qlevel = qlevel env - n }\n        n                       = qlevel env - l\n        vs                      = takev n (activeNames env)\n        takev 0 te              = []\n        takev n ((v,i):te)\n          | NTVar{} <- i        = v : takev (n-1) te\n          | otherwise           = takev n te\n        dropv 0 te              = te\n        dropv n ((v,i):te)\n          | NTVar{} <- i        = dropv (n-1) te\n          | otherwise           = (v,i) : dropv n te\n        dropw (WInst{wtype=TVar _ (TV _ v)} : we)\n          | v `elem` vs         = dropw we\n        dropw we                = we\n\n\nposdefine te env                = modX (tydefine te env) $ \\x -> x{ posnames = dom te ++ posnames x }\n\nsetInDecl env                   = modX env $ \\x -> x{ indecl = True }\n\nuseForce env                    = modX env $ \\x -> x{ forced = True }\n\ninDecl env                      = indecl $ envX env\n\nisForced env                    = forced $ envX env\n\n\ninstance Polarity Env where\n    polvars env                 = polvars pte `polcat` invvars ite\n      where (pte, ite)          = span ((`elem` pvs) . fst) (activeNames env)\n            pvs                 = posnames $ envX env\n\n\n-- Constraints -------------------------------------------------------------------------------\n\ndata Constraint = Cast  {info :: ErrInfo, scope :: Env, type1 :: Type, type2 :: Type}\n                | Sub   {info :: ErrInfo, scope :: Env, wit :: Name, type1 :: Type, type2 :: Type}\n                | Proto {info :: ErrInfo, scope :: Env, wit :: Name, type1 :: Type, proto1 :: PCon}\n                | Sel   {info :: ErrInfo, scope :: Env, wit :: Name, type1 :: Type, name1 :: Name, type2 :: Type}\n                | Mut   {info :: ErrInfo, scope :: Env, type1 :: Type, name1 :: Name, type2 :: Type}\n                | Seal  {info :: ErrInfo, scope :: Env, type1 :: Type}\n                deriving (Show)\n\ntype Constraints = [Constraint]\n\ninstance HasLoc Constraint where\n    loc (Cast info env t1 t2)       = getLoc [loc info, loc t1, loc t2]\n    loc (Sub info env _ t1 t2)      = getLoc [loc info, loc t1, loc t2]\n    loc (Proto info _ env t1 _)     = getLoc [loc info, loc t1]\n    loc (Sel info _ env t1  n1 t2)  = getLoc [loc info, loc t1, loc n1, loc t2]\n    loc (Mut info env t1  n1 t2)    = getLoc [loc info, loc t1, loc n1, loc t2]\n    loc (Seal info env t1)          = getLoc [loc info, loc t1]\n\ninstance Pretty Constraint where\n    pretty (Cast _ env t1 t2)       = prettyQuant env <+> pretty t1 <+> text \"<\" <+> pretty t2\n    pretty (Sub _ env w t1 t2)      = prettyQuant env <+> pretty w <+> colon <+> pretty t1 <+> text \"<\" <+> pretty t2\n    pretty (Proto _ env w t u)      = prettyQuant env <+> pretty w <+> colon <+> pretty t <+> parens (pretty u)\n    pretty (Sel _ env w t1 n t2)    = prettyQuant env <+> pretty w <+> colon <+> pretty t1 <> text \".\" <> pretty n <+> text \"<\" <+> pretty t2\n    pretty (Mut _ env t1 n t2)      = prettyQuant env <+> pretty t1 <+> text \".\" <> pretty n <+> text \">\" <+> pretty t2\n    pretty (Seal _ env t)           = prettyQuant env <+> text \"$Seal\" <+> pretty t\n\nprettyQuant env\n  | qlevel env > 0                  = brackets (commaSep pretty q) <+> text \"=>\"\n  | otherwise                       = empty\n  where q                           = [ QBind (TV k tv) (if c == cValue then ps else c:ps) | (tv, NTVar k c ps) <- activeNames env ]\n\ninstance VFree Constraint where\n    vfree (Cast info env t1 t2)     = vfree t1 ++ vfree t2\n    vfree (Sub info env w t1 t2)    = vfree t1 ++ vfree t2\n    vfree (Proto info env w t p)    = vfree t ++ vfree p\n    vfree (Sel info env w t1 n t2)  = vfree t1 ++ vfree t2\n    vfree (Mut info env t1 n t2)    = vfree t1 ++ vfree t2\n    vfree (Seal info env t)         = vfree t\n\ninstance UFree Constraint where\n    ufree (Cast info env t1 t2)     = ufree t1 ++ ufree t2\n    ufree (Sub info env w t1 t2)    = ufree t1 ++ ufree t2\n    ufree (Proto info env w t p)    = ufree t ++ ufree p\n    ufree (Sel info env w t1 n t2)  = ufree t1 ++ ufree t2\n    ufree (Mut info env t1 n t2)    = ufree t1 ++ ufree t2\n    ufree (Seal info env t)         = ufree t\n\ninstance Tailvars Constraint where\n    tailvars (Cast _ env t1 t2)     = tailvars t1 ++ tailvars t2\n    tailvars (Sub _ env w t1 t2)    = tailvars t1 ++ tailvars t2\n    tailvars (Proto _ env w t p)    = tailvars t ++ tailvars p\n    tailvars (Sel _ env w t1 n t2)  = tailvars t1 ++ tailvars t2\n    tailvars (Mut _ env t1 n t2)    = tailvars t1 ++ tailvars t2\n    tailvars (Seal _ env t)         = tailvars t\n\ninstance Vars Constraint where\n    freeQ (Cast _ env t1 t2)        = freeQ t1 ++ freeQ t2\n    freeQ (Sub _ env w t1 t2)       = freeQ t1 ++ freeQ t2\n    freeQ (Proto _ env w t p)       = freeQ t ++ freeQ p\n    freeQ (Sel _ env w t1 n t2)     = freeQ t1 ++ freeQ t2\n    freeQ (Mut _ env t1 n t2)       = freeQ t1 ++ freeQ t2\n    freeQ (Seal _ env t)            = freeQ t\n\ninstance UWild Constraint where\n    uwild (Cast info env t1 t2)     = Cast info env (uwild t1) (uwild t2)\n    uwild (Sub info env w t1 t2)    = Sub info env w (uwild t1) (uwild t2)\n    uwild (Proto info env w t p)    = Proto info env w (uwild t) (uwild p)\n    uwild (Sel info env w t1 n t2)  = Sel info env w (uwild t1) n (uwild t2)\n    uwild (Mut info env t1 n t2)    = Mut info env (uwild t1) n (uwild t2)\n    uwild (Seal info env t)         = Seal info env (uwild t)\n\ninstance VSubst Constraint where\n    vsubst s (Cast i env t1 t2)     = Cast i env (vsubst s t1) (vsubst s t2)\n    vsubst s (Sub i env w t1 t2)    = Sub i env w (vsubst s t1) (vsubst s t2)\n    vsubst s (Proto i env w t p)    = Proto i env w (vsubst s t) (vsubst s p)\n    vsubst s (Sel i env w t1 n t2)  = Sel i env w (vsubst s t1) n (vsubst s t2)\n    vsubst s (Mut i env t1 n t2)    = Mut i env (vsubst s t1) n (vsubst s t2)\n    vsubst s (Seal i env t)         = Seal i env (vsubst s t)\n\nrequantize env cs                   = map requant cs\n  where requant (Cast i _ t1 t2)    = Cast i env t1 t2\n        requant (Sub i _ w t1 t2)   = Sub i env w t1 t2\n        requant (Proto i _ w t p)   = Proto i env w t p\n        requant (Sel i _ w t1 n t2) = Sel i env w t1 n t2\n        requant (Mut i _ t1 n t2)   = Mut i env t1 n t2\n        requant (Seal i _ t)        = Seal i env t\n\n\ncloseDepVars vs cs\n  | null vs'                        = nub vs\n  | otherwise                       = closeDepVars (vs'++vs) cs\n  where vs'                         = concat [ deps c \\\\ vs | c <- cs, all (`elem` vs) (heads c) ]\n\n        heads (Proto _ w _ t _)     = ufree t\n        heads (Cast _ _ t _)        = ufree t\n        heads (Sub _ w _ t _)       = ufree t\n        heads (Sel _ w _ t n _)     = ufree t\n        heads (Mut _ _ t n _)       = ufree t\n        heads (Seal _ _ t)          = ufree t\n\n        deps (Proto _ w _ _ p)      = ufree p\n        deps (Cast _ _ _ t)         = typarams t\n        deps (Sub _ w _ _ t)        = typarams t\n        deps (Sel _ w _ _ n t)      = ufree t\n        deps (Mut _ _ _ n t)        = ufree t\n        deps (Seal _ _ _)           = []\n\n        typarams (TOpt _ t)         = typarams t\n        typarams (TCon _ c)         = ufree c\n        typarams _                  = []\n\n\nclosePolVars                        :: ([TUni],[TUni]) -> Constraints -> ([TUni],[TUni])\nclosePolVars pvs cs\n  | polnull (pvs' `polminus` pvs)   = pvs'\n  | otherwise                       = closePolVars pvs' cs'\n  where\n    (pvs',cs')                      = boundvs pvs cs\n\n    boundvs pn []                   = (pn, [])\n    boundvs (p,n) (Cast _ _ (TUni _ v) (TUni _ u) : cs)\n                                    = boundvs (if u `elem` p then v:p else p, if v `elem` n then u:n else n) cs\n    boundvs (p,n) (Sub _ _ _ (TUni _ v) (TUni _ u) : cs)\n                                    = boundvs (if u `elem` p then v:p else p, if v `elem` n then u:n else n) cs\n    boundvs pn (Cast _ _ t (TUni _ v) : cs)\n      | v `elem` fst pn             = boundvs (polvars t `polcat` pn) cs\n    boundvs pn (Sub _ _ _ t (TUni _ v) : cs)\n      | v `elem` fst pn             = boundvs (polvars t `polcat` pn) cs\n    boundvs pn (Cast _ _ (TUni _ v) t : cs)\n      | v `elem` snd pn             = boundvs (polneg (polvars t) `polcat` pn) cs\n    boundvs pn (Sub _ _ _ (TUni _ v) t : cs)\n      | v `elem` snd pn             = boundvs (polneg (polvars t) `polcat` pn) cs\n    boundvs pn (Proto _ _ _ (TUni _ v) p : cs)\n      | v `elem` snd pn             = boundvs (polneg (polvars p) `polcat` pn) cs\n    boundvs pn (Sel _ _ _ (TUni _ v) _ t : cs)\n      | v `elem` snd pn             = boundvs (polneg (polvars t) `polcat` pn) cs\n    boundvs pn (Mut _ _ (TUni _ v) _ t : cs)\n      | v `elem` (fst pn ++ snd pn) = boundvs (invvars t `polcat` pn) cs\n    boundvs pn (c : cs)             = let (pn',cs') = boundvs pn cs in (pn', c:cs')\n\n\nheadvar (Proto _ w _ (TUni _ u) p)    = u\n\nheadvar (Cast _ _ TVar{} (TUni _ u))  = u\nheadvar (Cast _ _ (TUni _ u) t)       = u\nheadvar (Cast _ _ t (TUni _ u))       = u     -- ?\n\nheadvar (Sub _ w _ TVar{} (TUni _ u)) = u\nheadvar (Sub _ w _ (TUni _ u) t)      = u\nheadvar (Sub _ w _ t (TUni _ u))      = u     -- ?\n\nheadvar (Sel _ w _ (TUni _ u) n t)    = u\n\nheadvar (Mut _ _ (TUni _ u) n t)      = u\n\nheadvar (Seal _ _ (TUni _ u))         = u\n\n\n\n-- Type inference monad ------------------------------------------------------------------\n\ndata TypeState                          = TypeState {\n                                                nextint         :: Int,\n                                                uniqprefix      :: String, -- Prefix for generated names\n                                                effectstack     :: [(TFX,Type)],\n                                                deferred        :: Constraints,\n                                                unisubst        :: IntMap Type\n                                          }\n\ninitTypeState p                         = TypeState { nextint = 1, uniqprefix = p, effectstack = [], deferred = [], unisubst = IntMap.empty }\n\ntype TypeM a                            = ExceptT TypeError (State TypeState) a\n\nrunTypeMState                           :: String -> TypeM a -> Either TypeError (a, TypeState)\nrunTypeMState p m                       = case runState (runExceptT m) (initTypeState p) of\n                                            (Right x, st') -> Right (x, st')\n                                            (Left err, _)  -> Left err\n\nrunTypeM                                :: TypeM a -> a\nrunTypeM m                              = case runTypeMState \"\" m of\n                                            Right (x,_) -> x\n                                            Left err    -> Control.Exception.throw err\n\ncurrentState                            :: TypeM TypeState\ncurrentState                            = lift $ state $ \\st -> (st, st)\n\nrollbackState                           :: TypeState -> TypeM ()\nrollbackState st                        = lift $ state $ \\_ -> ((), st)\n\nnewUnique                               :: TypeM Int\nnewUnique                               = lift $ state $ \\st -> (nextint st, st{ nextint = nextint st + 1 })\n\npushFX                                  :: TFX -> Type -> TypeM ()\npushFX fx ret                           = lift $ state $ \\st -> ((), st{ effectstack = (fx,ret) : effectstack st })\n\ncurrFX                                  :: TypeM TFX\ncurrFX                                  = lift $ state $ \\st -> (fst $ head $ effectstack st, st)\n\ncurrRet                                 :: TypeM Type\ncurrRet                                 = lift $ state $ \\st -> (snd $ head $ effectstack st, st)\n\npopFX                                   :: TypeM ()\npopFX                                   = lift $ state $ \\st -> ((), st{ effectstack = tail (effectstack st) })\n\ndefer                                   :: Constraints -> TypeM ()\ndefer cs                                = lift $ state $ \\st -> ((), st{ deferred = cs ++ deferred st })\n\ncollectDeferred                         :: TypeM Constraints\ncollectDeferred                         = lift $ state $ \\st -> (deferred st, st{ deferred = [] })\n\nusubstitute                             :: TUni -> Type -> TypeM ()\nusubstitute uv t                        = lift $\n                                          --trace (\"  #usubstitute \" ++ prstr uv ++ \" ~ \" ++ prstr t) $\n                                          state $ \\st -> ((), st{ unisubst = IntMap.insert (uvid uv) t (unisubst st)})\n\nusubstitution                           :: TypeM (IntMap Type)\nusubstitution                           = lift $ state $ \\st -> (unisubst st, st)\n\nuextend                                 :: [(TUni,Type)] -> TypeM ()\nuextend s                               = lift $\n                                          state $ \\st -> ((), st{ unisubst = IntMap.union (unisubst st) (IntMap.fromList [ (uvid u,t) | (u,t) <- s ])})\n\n-- Name generation ------------------------------------------------------------------------------------------------------------------\n\nnewGenerated p                          = do i <- newUnique\n                                             st <- currentState\n                                             return $ Internal p (tag (uniqprefix st) i) 0\n  where tag \"\" i                        = show i\n        tag s i                         = s ++ \"_\" ++ show i\n\nnewWitness                              = newGenerated Witness\n\nnewTmp                                  = newGenerated Tempvar\n\nnewUnivarOfKind k env                   = TUni NoLoc <$> univar k (qlevel env) <$> newUnique\n\nnewUnivarToken n                        = TUni NoLoc $ unitoken n\n\nnewUnivars env ks                       = mapM (\\k -> newUnivarOfKind k env) ks\n\nnewUnivar env                           = newUnivarOfKind KType env\n\n\n-- unification ----------------------------------------------------------------------------------------------------------------------\n\ntryUnify info t1 t2                         = unify info t1 t2 `catchError` \\err -> Control.Exception.throw err\n\nunify                                       :: ErrInfo -> Type -> Type -> TypeM ()\nunify info t1 t2                            = do t1' <- usubst t1\n                                                 t2' <- usubst t2\n                                                 --traceM (\"  #unify \" ++ prstr t1' ++ \" and \" ++ prstr t2')\n                                                 unify' info t1' t2'\n\nunifyM info ts1 ts2                         = mapM_ (uncurry $ unify info) (ts1 `zip` ts2)\n\n\nunify' _ (TWild _) t2                       = return ()\nunify' _ t1 (TWild _)                       = return ()\n\nunify' info (TCon _ c1) (TCon _ c2)\n  | tcname c1 == tcname c2                  = unifyM info (tcargs c1) (tcargs c2)\n\nunify' info (TFun _ fx1 p1 k1 t1) (TFun _ fx2 p2 k2 t2)\n                                            = do unify info fx1 fx2\n                                                 unify info p2 p1\n                                                 unify info k2 k1\n                                                 unify info t1 t2\n\nunify' info (TTuple _ p1 k1) (TTuple _ p2 k2)\n                                            = do unify info p1 p2\n                                                 unify info k1 k2\n\nunify' info (TOpt _ t1) (TOpt _ t2)         = unify info t1 t2\nunify' _ (TNone _) (TNone _)                = return ()\n\nunify' _ (TFX _ fx1) (TFX _ fx2)\n  | fx1 == fx2                              = return ()\n\nunify' _ (TNil _ k1) (TNil _ k2)\n  | k1 == k2                                = return ()\nunify' info (TRow _ k1 n1 t1 r1) (TRow _ k2 n2 t2 r2)\n  | k1 == k2 && n1 == n2                    = do unify info t1 t2\n                                                 unify info r1 r2\nunify' info (TStar _ k1 r1) (TStar _ k2 r2)\n  | k1 == k2                                = unify info r1 r2\n\nunify' info (TVar _ v1) (TVar _ v2)\n  | v1 == v2                                = return ()\n\nunify' info t1@(TUni _ v1) t2@(TUni _ v2)\n  | v1 == v2                                = return ()\n  | uvlevel v1 < uvlevel v2                 = usubstitute v2 t1\n  | otherwise                               = usubstitute v1 t2     -- Retain the var with the smallest ulevel (largest scope)\n\nunify' info (TUni _  v) t2                  = do when (v `elem` ufree t2) (infiniteType v t2)\n                                                 usubstitute v t2\nunify' info t1 (TUni _  v)                  = do when (v `elem` ufree t1) (infiniteType v t1)\n                                                 usubstitute v t1\n\nunify' info t1 t2                           = noUnify info t1 t2\n\n\n-- Asymmetric matching --------------------------------------------------------------------------------\n\nmatch vs (TWild _) t                        = Just []\nmatch vs t (TWild _)                        = Just []\nmatch vs (TUni _ _) t                       = Just []\nmatch vs t (TUni _ _)                       = Just []\nmatch vs (TCon _ c1) (TCon _ c2)\n  | tcname c1 == tcname c2                  = matches vs (tcargs c1) (tcargs c2)\nmatch vs (TFun _ fx1 p1 k1 t1) (TFun _ fx2 p2 k2 t2)\n                                            = matches vs [fx1,p1,k1,t1] [fx2,p2,k2,t2]\nmatch vs (TTuple _ p1 k1) (TTuple _ p2 k2)\n                                            = matches vs [p1,k1] [p2,k2]\nmatch vs (TOpt _ t1) (TOpt _ t2)            = match vs t1 t2\nmatch vs (TNone _) (TNone _)                = Just []\nmatch vs (TFX _ fx1) (TFX _ fx2)\n  | fx1 == fx2                              = Just []\n\nmatch vs (TNil _ k1) (TNil _ k2)\n  | k1 == k2                                = Just []\nmatch vs (TRow _ k1 n1 t1 r1) (TRow _ k2 n2 t2 r2)\n  | k1 == k2 && n1 == n2                    = matches vs [t1,r1] [t2,r2]\nmatch vs (TStar _ k1 r1) (TStar _ k2 r2)\n  | k1 == k2                                = match vs r1 r2\nmatch vs (TVar _ tv1) (TVar _ tv2)\n  | tv1 == tv2                              = Just []\nmatch vs t1 (TVar _ tv)\n  | tv `elem` vs && tv `notElem` vfree t1   = Just [(tv, t1)]\nmatch vs t1 t2                              = Nothing\n\nmatches vs [] []                            = Just []\nmatches vs (t:ts) (t':ts')                  = do s1 <- match vs t t'\n                                                 s2 <- matches vs ts ts'\n                                                 merge s1 s2\n  where merge s1 s2\n          | agree                           = Just $ s1 ++ s2\n          | otherwise                       = Nothing\n          where agree                       = and [ vsubst s1 (tVar v) `wildeq` vsubst s2 (tVar v) | v <- dom s1 `intersect` dom s2 ]\n                t `wildeq` t'               = match [] t t' == Just []\n\n\n-- USubst ---------------------------------------------------------------------------------------------\n\nclass USubst t where\n    usubst                          :: t -> TypeM t\n\ninstance USubst a => USubst (Name,a) where\n    usubst (n, t)                   = (,) <$> return n <*> usubst t\n\ninstance (USubst a, USubst b) => USubst (QName,a,b) where\n    usubst (n, t, u)                = (,,) <$> return n <*> usubst t <*> usubst u\n\ninstance USubst a => USubst [a] where\n    usubst                          = mapM usubst\n\ninstance USubst a => USubst (Maybe a) where\n    usubst                          = maybe (return Nothing) (\\x -> Just <$> usubst x)\n\ninstance USubst Constraint where\n    usubst (Cast info env t1 t2)    = Cast <$> usubst info <*> return env <*> usubst t1 <*> usubst t2\n    usubst (Sub info env w t1 t2)   = Sub <$> usubst info <*> return env <*> return w <*> usubst t1 <*> usubst t2\n    usubst (Proto info env w t p)   = Proto <$> usubst info <*> return env <*> return w <*> usubst t <*> usubst p\n    usubst (Sel info env w t1 n t2) = Sel <$> usubst info <*> return env <*> return w <*> usubst t1 <*> return n <*> usubst t2\n    usubst (Mut info env t1 n t2)   = Mut <$> usubst info <*> return env <*> usubst t1 <*> return n <*> usubst t2\n    usubst (Seal info env t)        = Seal <$> usubst info <*> return env <*> usubst t\n\ninstance USubst ErrInfo where\n    usubst (DfltInfo l n mbe ts)    = DfltInfo l n <$> usubst mbe <*> usubst ts\n    usubst (DeclInfo l1 l2 n t msg) = DeclInfo l1 l2 n <$> usubst t <*> return msg\n    usubst info                     = return info\n\ninstance USubst TSchema where\n    usubst (TSchema l [] t)         = TSchema l [] <$> usubst t\n    usubst (TSchema l q t)          = TSchema l <$> usubst q <*> usubst t\n\ninstance USubst TVar where\n    usubst v                        = do t <- usubst (TVar NoLoc v)\n                                         case t of\n                                            TVar _ v' -> return v'\n                                            _         -> return v\n\ninstance USubst TCon where\n    usubst (TC n ts)                = TC n <$> usubst ts\n\ninstance USubst QBind where\n    usubst (QBind v cs)             = QBind <$> usubst v <*> usubst cs\n\ninstance USubst WTCon where\n    usubst (wpath, p)               = do p <- usubst p; return (wpath, p)\n\ninstance USubst Type where\n    usubst (TUni l u)               = do s <- usubstitution\n                                         case IntMap.lookup (uvid u) s of\n                                            Just t  -> usubst t\n                                            Nothing -> return (TUni l u)\n    usubst (TVar l v)               = return $ TVar l v\n    usubst (TCon l c)               = TCon l <$> usubst c\n    usubst (TFun l fx p k t)        = TFun l <$> usubst fx <*> usubst p <*> usubst k <*> usubst t\n    usubst (TTuple l p k)           = TTuple l <$> usubst p <*> usubst k\n    usubst (TOpt l t)               = do t' <- usubst t\n                                         case t' of\n                                            TOpt{} -> return t'\n                                            _ -> return $ TOpt l t'\n    usubst (TNone l)                = return $ TNone l\n    usubst (TWild l)                = return $ TWild l\n    usubst (TNil l s)               = return $ TNil l s\n    usubst (TRow l k n t r)         = TRow l k n <$> usubst t <*> usubst r\n    usubst (TStar l k r)            = TStar l k <$> usubst r\n    usubst (TFX l fx)               = return $ TFX l fx\n\ninstance USubst PosPar where\n    usubst (PosPar n t e p)         = PosPar n <$> usubst t <*> usubst e <*> usubst p\n    usubst (PosSTAR n t)            = PosSTAR n <$> usubst t\n    usubst PosNIL                   = return PosNIL\n\ninstance USubst KwdPar where\n    usubst (KwdPar n t e p)         = KwdPar n <$> usubst t <*> usubst e <*> usubst p\n    usubst (KwdSTAR n t)            = KwdSTAR n <$> usubst t\n    usubst KwdNIL                   = return KwdNIL\n\ninstance USubst Decl where\n    usubst (Def l n q p k a ss de fx doc)   = Def l n <$> usubst q <*> usubst p <*> usubst k <*> usubst a <*> usubst ss <*> return de <*> usubst fx <*> return doc\n    usubst (Actor l n q p k ss doc)         = Actor l n <$> usubst q <*> usubst p <*> usubst k <*> usubst ss <*> return doc\n    usubst (Class l n q bs ss doc)          = Class l n <$> usubst q <*> usubst bs <*> usubst ss <*> return doc\n    usubst (Protocol l n q bs ss doc)       = Protocol l n <$> usubst q <*> usubst bs <*> usubst ss <*> return doc\n    usubst (Extension l q c bs ss doc)      = Extension l <$> usubst q <*> usubst c <*> usubst bs <*> usubst ss <*> return doc\n\ninstance USubst Stmt where\n    usubst (Expr l e)               = Expr l <$> usubst e\n    usubst (Assign l ps e)          = Assign l <$> usubst ps <*> usubst e\n    usubst (MutAssign l t e)        = MutAssign l <$> usubst t <*> usubst e\n    usubst (AugAssign l t op e)     = AugAssign l <$> usubst t <*> return op <*> usubst e\n    usubst (Assert l e mbe)         = Assert l <$> usubst e <*> usubst mbe\n    usubst (Delete l t)             = Delete l <$> usubst t\n    usubst (Return l mbe)           = Return l <$> usubst mbe\n    usubst (Raise l e)              = Raise l <$> usubst e\n    usubst (If l bs els)            = If l <$> usubst bs <*> usubst els\n    usubst (While l e b els)        = While l <$> usubst e <*> usubst b <*> usubst els\n    usubst (For l p e b els)        = For l <$> usubst p <*> usubst e <*> usubst b <*> usubst els\n    usubst (Try l b hs els fin)     = Try l <$> usubst b <*> usubst hs <*> usubst els <*> usubst fin\n    usubst (With l is b)            = With l <$> usubst is <*> usubst b\n    usubst (VarAssign l ps e)       = VarAssign l <$> usubst ps <*> usubst e\n    usubst (After l e e')           = After l <$> usubst e <*> usubst e'\n    usubst (Decl l ds)              = Decl l <$> usubst ds\n    usubst (Signature l ns tsc d)   = Signature l ns <$> usubst tsc <*> return d\n    usubst s                        = return s\n\ninstance USubst Expr where\n    usubst (Call l e p k)           = Call l <$> usubst e <*> usubst p <*> usubst k\n    usubst (TApp l e ts)            = TApp l <$> usubst e <*> usubst ts\n    usubst (Let l ss e)             = Let l <$> usubst ss <*> usubst e\n    usubst (Async l e)              = Async l <$> usubst e\n    usubst (Await l e)              = Await l <$> usubst e\n    usubst (Index l e ix)           = Index l <$> usubst e <*> usubst ix\n    usubst (Slice l e sl)           = Slice l <$> usubst e <*> usubst sl\n    usubst (Cond l e1 cond e2)      = Cond l <$> usubst e1 <*> usubst cond <*> usubst e2\n    usubst (IsInstance l e c)       = IsInstance l <$> usubst e <*> return c\n    usubst (BinOp l e1 op e2)       = BinOp l <$> usubst e1 <*> return op <*> usubst e2\n    usubst (CompOp l e ops)         = CompOp l <$> usubst e <*> usubst ops\n    usubst (UnOp l op e)            = UnOp l op <$> usubst e\n    usubst (Dot l e n)              = Dot l <$> usubst e <*> return n\n    usubst (Rest l e n)             = Rest l <$> usubst e <*> return n\n    usubst (DotI l e i)             = DotI l <$> usubst e <*> return i\n    usubst (RestI l e i)            = RestI l <$> usubst e <*> return i\n    usubst (Lambda l p k e fx)      = Lambda l <$> usubst p <*> usubst k <*> usubst e <*> usubst fx\n    usubst (Yield l e)              = Yield l <$> usubst e\n    usubst (YieldFrom l e)          = YieldFrom l <$> usubst e\n    usubst (Tuple l p k)            = Tuple l <$> usubst p <*> usubst k\n    usubst (List l es)              = List l <$> usubst es\n    usubst (ListComp l e c)         = ListComp l <$> usubst e <*> usubst c\n    usubst (Dict l as)              = Dict l <$> usubst as\n    usubst (DictComp l a c)         = DictComp l <$> usubst a <*> usubst c\n    usubst (Set l es)               = Set l <$> usubst es\n    usubst (SetComp l e c)          = SetComp l <$> usubst e <*> usubst c\n    usubst (Paren l e)              = Paren l <$> usubst e\n    usubst e                        = return e\n\ninstance USubst Pattern where\n    usubst (PWild l t)              = PWild l <$> usubst t\n    usubst (PVar l n t)             = PVar l n <$> usubst t\n    usubst (PParen l p)             = PParen l <$> usubst p\n    usubst (PTuple l p k)           = PTuple l <$> usubst p <*> usubst k\n    usubst (PList l ps p)           = PList l <$> usubst ps <*> usubst p\n\ninstance USubst PosPat where\n    usubst (PosPat p pp)            = PosPat <$> usubst p <*> usubst pp\n    usubst (PosPatStar p)           = PosPatStar <$> usubst p\n    usubst PosPatNil                = return PosPatNil\n\ninstance USubst KwdPat where\n    usubst (KwdPat n p kp)          = KwdPat n <$> usubst p <*> usubst kp\n    usubst (KwdPatStar p)           = KwdPatStar <$> usubst p\n    usubst KwdPatNil                = return KwdPatNil\n\ninstance USubst Branch where\n    usubst (Branch e b)             = Branch <$> usubst e <*> usubst b\n\ninstance USubst Handler where\n    usubst (Handler ex b)           = Handler ex <$> usubst b\n\ninstance USubst WithItem where\n    usubst (WithItem e p)           = WithItem <$> usubst e <*> usubst p\n\ninstance USubst PosArg where\n    usubst (PosArg e p)             = PosArg <$> usubst e <*> usubst p\n    usubst (PosStar e)              = PosStar <$> usubst e\n    usubst PosNil                   = return PosNil\n\ninstance USubst KwdArg where\n    usubst (KwdArg n e k)           = KwdArg n <$> usubst e <*> usubst k\n    usubst (KwdStar e)              = KwdStar <$> usubst e\n    usubst KwdNil                   = return KwdNil\n\ninstance USubst Assoc where\n    usubst (Assoc k v)              = Assoc <$> usubst k <*> usubst v\n    usubst (StarStar e)             = StarStar <$> usubst e\n\ninstance USubst Elem where\n    usubst (Elem e)                 = Elem <$> usubst e\n    usubst (Star e)                 = Star <$> usubst e\n\ninstance USubst Comp where\n    usubst (CompFor l p e c)        = CompFor l <$> usubst p <*> usubst e <*> usubst c\n    usubst (CompIf l e c)           = CompIf l <$> usubst e <*> usubst c\n    usubst NoComp                   = return NoComp\n\ninstance USubst Sliz where\n    usubst (Sliz l e1 e2 e3)        = Sliz l <$> usubst e1 <*> usubst e2 <*> usubst e3\n\ninstance USubst OpArg where\n    usubst (OpArg op e)             = OpArg op <$> usubst e\n\n\ninstance USubst NameInfo where\n    usubst (NVar t)             = NVar <$> usubst t\n    usubst (NSVar t)            = NSVar <$> usubst t\n    usubst (NDef t d doc)       = NDef <$> usubst t <*> return d <*> return doc\n    usubst (NSig t d doc)       = NSig <$> usubst t <*> return d <*> return doc\n    usubst (NAct q p k te doc)  = NAct <$> usubst q <*> usubst p <*> usubst k <*> usubst te <*> return doc\n    usubst (NClass q us te doc) = NClass <$> usubst q <*> usubst us <*> usubst te <*> return doc\n    usubst (NProto q us te doc) = NProto <$> usubst q <*> usubst us <*> usubst te <*> return doc\n    usubst (NExt q c ps te opts doc) = NExt <$> usubst q <*> usubst c <*> usubst ps <*> usubst te <*> return opts <*> return doc\n    usubst (NTVar k c ps)       = NTVar k <$> usubst c <*> usubst ps\n    usubst (NAlias qn)          = NAlias <$> return qn\n    usubst (NMAlias m)          = NMAlias <$> return m\n    usubst (NModule ms te doc)  = NModule ms <$> return te <*> return doc     -- actually usubst te, but te has no free variables (top-level)\n    usubst NReserved            = return NReserved\n\ninstance USubst Witness where\n    usubst w@WClass{}           = return w                      -- A WClass (i.e., an extension) can't have any free type variables\n    usubst w@WInst{}            = do t <- usubst (wtype w)\n                                     p <- usubst (proto w)\n                                     return w{ wtype  = t, proto = p }\n\n\ninstance USubst Env where\n    usubst env                  = do ne <- usubst (activeNames env)\n                                     ex <- usubst (envX env)\n                                     return $ setActiveNames ne env{ envX = ex }\n\ninstance UFree Env where\n    ufree env                   = ufree (activeNames env) ++ ufree (envX env)\n\n\n-- Well-formed tycon applications -------------------------------------------------------------------------------------------------\n\nclass WellFormed a where\n    wf                      :: Env -> a -> Constraints\n\ninstance (WellFormed a) => WellFormed (Maybe a) where\n    wf env                  = maybe [] (wf env)\n\ninstance (WellFormed a) => WellFormed [a] where\n    wf env                  = concatMap (wf env)\n\ninstance WellFormed TCon where\n    wf env (TC n ts)        = wf env ts ++ [ constr (vsubst s u) (vsubst s $ tVar v) | QBind v us <- q, u <- us ]\n      where q               = case findQName n env of\n                                NAct q p k te _ -> q\n                                NClass q us te _ -> q\n                                NProto q us te _ -> q\n                                NReserved -> nameReserved n\n                                i -> err1 n (\"wf: Class or protocol name expected, got \" ++ show i)\n            s               = qbound q `zip` ts\n            constr u t      = if isProto env (tcname u)\n                              then Proto (noinfo 20) env nWild t u\n                              else Cast (noinfo 21) env t (tCon u)\n\nwfProto                     :: Env -> TCon -> TypeM (Constraints, Constraints)\nwfProto env (TC n ts)       = do cs <- instQuals env q ts\n                                 return (wf env ts, cs)\n  where q                   = case findQName n env of\n                                NProto q us te _ -> q\n                                NReserved -> nameReserved n\n                                i -> err1 n (\"wfProto: Protocol name expected, got \" ++ show i)\n\ninstance WellFormed Type where\n    wf env (TCon _ tc)      = wf env tc\n    wf env (TFun _ x p k t) = wf env x ++ wf env p ++ wf env p ++ wf env k ++ wf env t\n    wf env (TTuple _ p k)   = wf env p ++ wf env k\n    wf env (TOpt _ t)       = wf env t\n    wf env (TRow _ _ _ t r) = wf env t ++ wf env r\n    wf env (TStar _ _ r)    = wf env r\n    wf env _                = []\n\n\ninstance WellFormed QBind where\n    wf env (QBind v us)\n      | not $ null ideps    = err2 (head ideps) \"Interdependent type variable bounds:\"\n      | otherwise           = wf env us\n      where (_,ps)          = mro2 env us\n            ideps           = [ [tcname u, root $ head w] | u <- us, (w,p) <- ps, length w > 1, p == u ]\n            root (Left n)   = n\n            root (Right n)  = n\n\n\n\n-- Instantiation -------------------------------------------------------------------------------------------------------------------\n\ninstantiate                 :: Env -> TSchema -> TypeM (Constraints, [Type], Type)\ninstantiate env (TSchema _ q t)\n                            = do (cs, tvs) <- instQBinds env q\n                                 let s = qbound q `zip` tvs\n                                 return (cs, tvs, vsubst s t)\n\ninstQBinds                  :: Env -> QBinds -> TypeM (Constraints, [Type])\ninstQBinds env q            = do ts <- newUnivars env [ tvkind v | QBind v _ <- q ]\n                                 cs <- instQuals env q ts\n                                 return (cs, ts)\n\ninstWitness                 :: Env -> PCon -> Witness -> TypeM (Constraints,Type,Expr)\ninstWitness env p0 wit      = case wit of\n                                 WClass q t p w ws opts -> do\n                                    (cs,tvs) <- instQBinds env q\n                                    let s = (tvSelf,t) : qbound q `zip` tvs\n                                    unifyM (locinfo p0 22) (tcargs p0) (tcargs $ vsubst s p)\n                                    t <- usubst (vsubst s t)\n                                    cs <- usubst cs\n                                    return (cs, t, wexpr ws (eCall (tApp (eQVar w) tvs) (wvars cs ++ replicate opts eNone)))\n                                 WInst q t p w ws -> do\n                                    (cs,tvs) <- instQBinds env q\n                                    let s = (tvSelf,t) : qbound q `zip` tvs\n                                    unifyM (locinfo p0 23) (tcargs p0) (tcargs $ vsubst s p)\n                                    t <- usubst (vsubst s t)\n                                    return (cs, t, wexpr ws (eQVar w))\n\ninstQuals                   :: Env -> QBinds -> [Type] -> TypeM Constraints\ninstQuals env q ts          = do let s = qbound q `zip` ts\n                                 sequence [ constr (vsubst s (tVar v)) (vsubst s u) | QBind v us <- q, u <- us ]\n  where constr t u@(TC n _)\n          | isProto env n   = do w <- newWitness; return $ Proto (noinfo 24) env w t u\n          | otherwise       = return $ Cast (noinfo 25) env t (tCon u)\n\nwvars                       :: Constraints -> [Expr]\nwvars cs                    = [ eVar v | Proto _ _ v _ _ <- cs ]\n\n\n-- Equations -----------------------------------------------------------------------------------------------------------------------\n\ndata Equation                           = Eqn Int Name Type Expr\n\ntype Equations                          = [Equation]\n\nmkEqn env                               = Eqn (qlevel env)\n\ninstance Pretty Equations where\n    pretty eqs                          = vcat $ map pretty eqs\n\ninstance Pretty Equation where\n    pretty (Eqn i n t e)                = pretty n <+> colon <+> pretty t <+> equals <+> pretty e <+> text (\"# level \" ++ show i)\n\ninstance USubst Equation where\n    usubst (Eqn i w t e)                = Eqn i w <$> usubst t <*> usubst e\n\ninstance UFree Equation where\n    ufree (Eqn i w t e)                 = ufree t ++ ufree e\n\ninstance Vars Equation where\n    free (Eqn i w t e)                  = free e\n\n    bound (Eqn i w t e)                 = [w]\n\n\nbindWits eqs\n  | null sigws                          = binds\n  | otherwise                           = Signature NoLoc sigws (monotype tWild) NoDec : binds\n  where sigws                           = [ w | Eqn _ w _ (NotImplemented _) <- eqs ]\n        binds                           = [ sAssign (pVar w t) e | Eqn _ w t e <- eqs, w `notElem` sigws ]\n\nscopedWits env0 q cs                    = scoped cs\n  where level1                          = qlevel env0 + length q\n        scoped (Sub _ env w _ _ : cs)\n          | qlevel env == level1        = w : scoped cs\n          | qlevel env < level1         = trace (\"### Bad constraint level for \" ++ prstr w) $ scoped cs\n        scoped (Proto _ env w _ _ : cs)\n          | qlevel env == level1        = w : scoped cs\n          | qlevel env < level1         = trace (\"### Bad constraint level for \" ++ prstr w) $ scoped cs\n        scoped (Sel _ env w _ _ _ : cs)\n          | qlevel env == level1        = w : scoped cs\n          | qlevel env < level1         = trace (\"### Bad constraint level for \" ++ prstr w) $ scoped cs\n        scoped (_ : cs)                 = scoped cs\n        scoped []                       = []\n\nfindeqns [] eqns                        = []\nfindeqns ws eqns                        = findeqns ws' eqns ++ match\n  where match                           = [ eq | eq@(Eqn _ w t e) <- eqns, w `elem` ws ]\n        ws'                             = filter isWitness $ free match\n\nspliteqns eqns                          = partition isTop eqns\n  where isTop (Eqn 0 _ _ _)             = True\n        isTop _                         = False\n\n\n-- Misc. ---------------------------------------------------------------------------------------------------------------------------\n\nproto2type t (TC n ts)                   = tCon $ TC n (t:ts)\n\nwit2row ws                              = \\p -> foldr f p ws\n  where f (w,t)                         = TRow NoLoc PRow nWild t\n\nwit2arg ws                              = \\p -> foldr f p ws\n  where f (w,t)                         = PosArg (eVar w)\n\nwit2par ws                              = \\p -> foldr f p ws\n  where f (w,t)                         = PosPar w (Just t) Nothing\n\nvar2arg xs                              = \\p -> foldr f p xs\n  where f x                             = PosArg (eVar x)\n\nexp2arg es                              = \\p -> foldr PosArg p es\n\nprotoWitsOf cs                          = [ eVar w | Proto _ _ w t p <- cs ]\n\nqualWPar env q                          = wit2par (qualWits env q)\n\nqualWRow env q                          = wit2row (qualWits env q)\n\nqualWits env q                          = [ (tvarWit tv p, proto2type (tVar tv) p) | QBind tv ps <- q, p <- ps, isProto env (tcname p) ]\n\nwitSubst env q cs                       = [ mkEqn env w0 t (eVar w) | ((w,t),w0) <- ws `zip` ws0 ]\n  where ws                              = [ (w, proto2type t p) | Proto _ _ w t p <- cs ]\n        ws0                             = [ tvarWit tv p | QBind tv ps <- q, p <- ps, isProto env (tcname p) ]\n\n-- Type errors ---------------------------------------------------------------------------------------------------------------------\n\ndata TypeError                      = TypeError SrcLoc String\n                                    | RigidVariable TVar\n                                    | InfiniteType TUni Type\n                                    | ConflictingRow TUni\n                                    | KwdNotFound ErrInfo Name\n                                    | KwdUnexpected ErrInfo Name\n                                    | PosElemNotFound ErrInfo String\n                                    | IncompatError ErrInfo String\n                                    | EscapingVar [TVar] TSchema\n                                    | NoSelStatic Name TCon\n                                    | NoSelInstByClass Name TCon\n                                    | NoMut Name\n                                    | LackSig Name\n                                    | LackDef Name\n                                    | SurplusRow PosRow\n                                    | NoRed Constraint\n                                    | NoSolve (Maybe Type) [Type] [Constraint]\n                                    | NoUnify ErrInfo Type Type\n                                    | UninitializedAttribute SrcLoc Name Bool SrcLoc SrcLoc Name (Maybe (Name, SrcLoc)) -- attr loc, attr name, is inferred, init loc, class loc, class name, parent class info\n                                    deriving (Show)\n\ndata ErrInfo    = DfltInfo {errloc :: SrcLoc, errno :: Int, errexpr :: Maybe Expr, errinsts :: [(QName,TSchema,Type)]}\n                | DeclInfo {errloc :: SrcLoc, errloc2 :: SrcLoc, errname :: Name, errschema :: TSchema, errmsg :: String}\n                | Simple {errloc ::SrcLoc, errmsg :: String}\n                deriving (Show)\n\nnoinfo n        = DfltInfo NoLoc n Nothing []\n\nlocinfo x n     = DfltInfo (loc x) n Nothing []\n\nlocinfo' x n e  = DfltInfo (loc x) n (Just e) []\n\nlocinfo2 n e    = DfltInfo (loc e) n (Just e) []\n\n\ninstance Control.Exception.Exception TypeError\n\ninstance HasLoc TypeError where\n    loc (TypeError l str)           = l\n    loc (RigidVariable tv)          = loc tv\n    loc (InfiniteType tv t)         = loc t\n    loc (ConflictingRow tv)         = loc tv\n    loc (KwdNotFound _ n)           = loc n\n    loc (KwdUnexpected _ n)         = loc n\n    loc (PosElemNotFound info s)    = loc info -- NoLoc     -- TODO: supply position\n    loc (EscapingVar tvs t)         = loc tvs\n    loc (NoSelStatic n u)           = loc n\n    loc (NoSelInstByClass n u)      = loc n\n    loc (NoMut n)                   = loc n\n    loc (LackSig n)                 = loc n\n    loc (LackDef n)                 = loc n\n    loc (SurplusRow p)              = NoLoc     -- TODO: supply position\n    loc (NoRed c)                   = loc c\n    loc (NoSolve _ _ _)             = NoLoc\n    loc (NoUnify info t1 t2)        = loc info\n    loc (UninitializedAttribute l _ _ _ _ _ _) = l\n\ninstance HasLoc ErrInfo where\n    loc (Simple l _)                = l\n    loc (DfltInfo l _ _ _)          = l\n    loc (DeclInfo l _ _ _ _)        = l\n\ninstance UFree ErrInfo where\n    ufree (DfltInfo l n mbe ts)     = ufree mbe ++ ufree ts\n    ufree (DeclInfo l1 l2 n t msg)  = ufree t\n    ufree _                         = []\n    \ninstance UWild ErrInfo where\n    uwild (DfltInfo l n mbe ts)     = DfltInfo l n mbe (uwild ts)\n    uwild (DeclInfo l1 l2 n t msg)  = DeclInfo l1 l2 n (uwild t) msg\n    uwild info                      = info\n\n\nintro t mbe                            = case mbe of\n                                             Nothing ->  pretty t\n                                             Just e ->   text \"The type of the indicated expression\" <+> text \"(\" Pretty.<>\n                                                           (if isGen t then text \"which we call\" else text \"inferred to be\") <+> pretty t Pretty.<> text \")\"\n   where isGen (TCon _ (TC (NoQ (Name _ ('t' : ds))) [])) = all isDigit ds\n         isGen _ = False\n\nexplainRequirement c                = case info c of\n                                          Simple l s -> text s\n                                          DfltInfo l n mbe ts ->\n                                             (if ts /= []\n                                              then text (concatMap (\\(n,s,t) -> Pretty.print n ++ \" has had its polymorphic type \"\n                                                            ++  Pretty.print s ++ \" instantiated to \" ++ Pretty.print t) ts++\", so \")\n\n                                              else empty) Pretty.<>\n                                               (case c of\n                                                   Cast _ _ t1 t2 -> intro t1 mbe <+> text \"must be a subclass of\" <+> pretty t2\n                                                   Sub i _ _ t1 t2 -> intro t1 mbe <+> text \"must be a subtype of\" <+> pretty t2\n                                                   Proto _ _ _ t p -> intro t mbe <+> text \"must implement\" <+> pretty p\n                                                   Sel _ _ _ t n t0 -> intro t mbe <+> text \"must have an attribute\" <+> pretty n <+> text \"with type\" <+> pretty t0\n                                                                          Pretty.<> text \"; no such type is known.\"\n                                                   _ -> pretty c <+> text \"must hold\")\n                                          DeclInfo _ _ n sc msg -> text msg   -- $+$ pretty n <+> text \"is inferred to have type\"<+> pretty sc\n\n\n\nuseless vs c                           = case c of\n                                             Cast _ _ t1 t2 -> f t1 || f t2\n                                             Sub _ _ _ t1 t2 -> f t1 || f t2\n                                             Proto _ _ _ t p -> f t\n                                             Sel _ _ _ t n t0 -> f t || f t0\n                                             Mut _ _ t1 n t2 -> True   -- TODO\n                                             Seal _ _ _ -> True        -- TODO\n     where f (TUni _ v) = notElem v vs\n           f _          = False\n\n--typeReport :: TypeError -> Report\ntypeReport (TypeError l msg) filename src           = Err Nothing msg [(locToPosition l filename src, This msg)] []\ntypeReport (RigidVariable tv) filename src          = Err Nothing msg [(locToPosition (loc tv) filename src, This msg)] []\n                                                      where msg = render (text \"Type\" <+> pretty tv <+> text \"is rigid\")\ntypeReport (InfiniteType tv t) filename src         = Err Nothing msg [(locToPosition (loc t) filename src, This msg)] []\n                                                      where msg = render (text \"Type\" <+> pretty tv <+> text \"~\" <+> pretty t <+> text \"is infinite\")\ntypeReport (ConflictingRow tv) filename src         = Err Nothing msg [(locToPosition (loc tv) filename src, This msg)] []\n                                                      where msg = render (text \"Type\" <+> pretty tv <+> text \"has conflicting extensions\")\ntypeReport (KwdNotFound info n) filename src        = Err Nothing \"Keyword argument missing\" [(locToPosition (loc n) filename src, This msg)] []\n                                                      where msg = render (text \"Keyword element\" <+> quotes (pretty n) <+> text \"is not found\")\ntypeReport (KwdUnexpected info n) filename src      = Err Nothing \"Unexpected keyword argument\" [(locToPosition (loc n) filename src, This msg)] []\n                                                      where msg = render (text \"Unexpected keyword argument\" <+> quotes (pretty n))\ntypeReport (PosElemNotFound info s) filename src    = Err Nothing s [(locToPosition (loc info) filename src, This s)] []\ntypeReport (EscapingVar tvs t) filename src         = Err Nothing msg [(locToPosition (loc tvs) filename src, This msg)] []\n                                                      where msg = render (text \"Type annotation\" <+> pretty t <+> text \"is too general, type variable\" <+>\n                                                                  pretty (head tvs) <+> text \"escapes\")\ntypeReport (NoSelStatic n u) filename src           = Err Nothing msg [(locToPosition (loc n) filename src, This msg)] []\n                                                      where msg = render (text \"Static method\" <+> pretty n <+> text \"cannot be selected from\" <+> pretty u <+> text \"instance\")\ntypeReport (NoSelInstByClass n u) filename src      = Err Nothing msg [(locToPosition (loc n) filename src, This msg)] []\n                                                      where msg = render (text \"Instance attribute\" <+> pretty n <+> text \"cannot be selected from class\" <+> pretty u)\ntypeReport (NoMut n) filename src                   = Err Nothing msg [(locToPosition (loc n) filename src, This msg)] []\n                                                      where msg = render (text \"Non @property attribute\" <+> pretty n <+> text \"cannot be mutated\")\ntypeReport (LackSig n) filename src                 = Err Nothing msg [(locToPosition (loc n) filename src, This msg)] []\n                                                      where msg = render (text \"Declaration lacks accompanying signature\")\ntypeReport (LackDef n) filename src                 = Err Nothing msg [(locToPosition (loc n) filename src, This msg)] []\n                                                      where msg = render (text \"Signature lacks accompanying definition\")\ntypeReport (NoRed c) filename src\n    | DeclInfo l1 l2 n _ _ <- info c = Err\n                                         Nothing\n                                         \"Constraint violation\"\n                                         [ (locToPosition l1 filename src, This (render (explainRequirement c <+> parens (explainRequirement c{info = dummyInfo}))))\n                                         , (locToPosition l2 filename src, Where (Pretty.print n ++ \" is defined here\"))\n                                         ]\n                                         []\n    | otherwise                      = Err\n                                          Nothing\n                                          \"Constraint violation\"\n                                          [(locToPosition (loc c) filename src, This (render (explainRequirement c)))]\n                                          []\n\ntypeReport (NoSolve mbt vs cs) filename src         =\n    let header = case length cs of\n                    0 -> \"Unable to give good error message: please report example\"\n                    1 -> \"Cannot satisfy the following constraint:\"\n                    _ -> \"Cannot satisfy the following simultaneous constraints for the unknown \" ++\n                         (if length vs == 1\n                          then \"type \" ++ case head vs of\n                                          TCon _ tc -> nameStr (noq (tcname tc))\n                                          _ -> show (head vs)\n                          else \"types\")\n        -- Each constraint gets its own complete error message with source line\n        constraint_messages = concatMap (typeError . NoRed) cs\n        -- Filter out empty positions and merge their messages into the first real position\n        (noLocs, withLocs) = partition ((==NoLoc) . fst) constraint_messages\n        withLocsMsgs = case (withLocs, noLocs) of\n            ([], []) -> [(NoLoc, \"Error: No location information\")]\n            ([], (l,m):_) -> [(l,m)]\n            ((l,m):rest, extras) -> (l, m ++ \"\\n\" ++ concatMap snd extras) : rest\n    in Err\n        Nothing\n        header\n        [(locToPosition l filename src, This m) | (l,m) <- withLocsMsgs]\n        []\n  where\n        nameStr (Name _ str) = str\n\ntypeReport (NoUnify (Simple l msg) _ _) filename src = Err Nothing \"Type unification error\" [(locToPosition l filename src, This msg)] []\ntypeReport (NoUnify info t1 t2) filename src        =\n    case (loc t1, loc t2) of\n        (l1@Loc{}, l2@Loc{}) -> Err\n                                 Nothing\n                                 \"Type unification error\"\n                                 [ (locToPosition l1 filename src, This \"First type appears here\")\n                                 , (locToPosition l2 filename src, This \"Second type appears here\")\n                                 ]\n                                 []\n        _                     -> Err\n                                 Nothing\n                                 \"Type unification error\"\n                                 [(locToPosition (getLoc[loc info, loc t1, loc t2]) filename src, This msg)]\n                                 []\n    where msg = render (text \"Incompatible types\" <+> pretty t1 <+> text \"and\" <+> pretty t2)\n\ntypeReport (IncompatError info msg) filename src    =\n    case info of\n        DeclInfo l1 l2 n sc msg1    -> Err\n                                         Nothing\n                                         \"Incompatible types\"\n                                         [ (locToPosition l1 filename src, This msg)\n                                         , (locToPosition l2 filename src, Where (Pretty.print n ++ \" is defined here\"))\n                                         ]\n                                         []\n        _                           -> Err\n                                         Nothing\n                                         \"Incompatible types\"\n                                         [(locToPosition (loc info) filename src, This msg)]\n                                         []\ntypeReport (SurplusRow p) filename src =\n                                    Err Nothing \"Too many arguments supplied\" [(locToPosition NoLoc filename src, This (prstr (label p)))] []\ntypeReport (UninitializedAttribute attrLoc attrName isInferred initLoc classLoc className parentInfo) filename src =\n                                    Err (Just \"Type error\") msg\n                                        ([ (locToPosition initLoc filename src, This $ \"Attribute '\" ++ prstr attrName ++ \"' is not initialized in __init__\")\n                                         , (locToPosition (makeLineOnlyLoc classLoc src) filename src, Where $ \"In class \" ++ prstr className)\n                                         ] ++\n                                         (case parentInfo of\n                                             Just (parentName, parentLoc) -> [(locToPosition (makeLineOnlyLoc parentLoc src) filename src, Where $ \"Attribute inherited from \" ++ prstr parentName)]\n                                             Nothing -> []) ++\n                                         [ (locToPosition attrLoc filename src, Where $ \"Attribute '\" ++ prstr attrName ++ \"' \" ++ \n                                             if isInferred then \"inferred from use\" else \"is defined here\")\n                                         ])\n                                        []\n                                    where msg = \"Attribute '\" ++ prstr attrName ++ \"' is not initialized in \" ++ prstr className ++ \".__init__\"\n\n\ntypeError                           :: TypeError -> [(SrcLoc, String)]\ntypeError (TypeError l str)          = [(l, str)]\ntypeError (RigidVariable tv)         = [(loc tv, render (text \"Type\" <+> pretty tv <+> text \"is rigid\"))]\ntypeError (InfiniteType tv t)        = [(loc tv, render (text \"Type\" <+> pretty tv <+> text \"~\" <+> pretty t <+> text \"is infinite\"))]\ntypeError (ConflictingRow tv)        = [(loc tv, render (text \"Type\" <+> pretty tv <+> text \"has conflicting extensions\"))]\ntypeError (KwdNotFound _ n)          = [(loc n, render (text \"Keyword element\" <+> quotes (pretty n) <+> text \"is not found\"))]\ntypeError (KwdUnexpected _ n)        = [(loc n, render (text \"Keyword element\" <+> quotes (pretty n) <+> text \"is not expected\"))]\ntypeError (PosElemNotFound info s)   = [(loc info, s)]\ntypeError (EscapingVar tvs t)        = [(loc tvs, render (text \"Type annotation\" <+> pretty t <+> text \"is too general, type variable\" <+>\n                                        pretty (head tvs) <+> text \"escapes\"))]\ntypeError (NoSelStatic n u)          = [(loc n, render (text \"Static method\" <+> pretty n <+> text \"cannot be selected from\" <+> pretty u <+> text \"instance\"))]\ntypeError (NoSelInstByClass n u)     = [(loc n, render (text \"Instance attribute\" <+> pretty n <+> text \"cannot be selected from class\" <+> pretty u))]\ntypeError (NoMut n)                  = [(loc n, render (text \"Non @property attribute\" <+> pretty n <+> text \"cannot be mutated\"))]\ntypeError (LackSig n)                = [(loc n, render (text \"Declaration lacks accompanying signature\"))]\ntypeError (LackDef n)                = [(loc n, render (text \"Signature lacks accompanying definition\"))]\ntypeError (UninitializedAttribute attrLoc attrName isInferred initLoc classLoc className parentInfo) = [(initLoc, \"attribute '\" ++ prstr attrName ++ \"' is not initialized in __init__ of \" ++ prstr className)]\ntypeError (NoRed c)\n    | DeclInfo l1 l2 _ _ _ <- info c = [(min l1 l2,\"\"), (max l1 l2,render (explainRequirement c <+> parens (explainRequirement c{info = dummyInfo})))]\n--    | DfltInfo l n mbe is <- info c  = [(loc c, render (explainRequirement c <+> parens (text (\"errcode \" ++ show n))))]\n    | otherwise                      = [(loc c, render (explainRequirement c))]\ntypeError (NoSolve mbt vs cs)        = case length cs of\n                                           0 -> [(NoLoc, \"Unable to give good error message: please report example\")]\n                                           1 ->  (NoLoc, \"Cannot satisfy the following constraint:\\n\") : concatMap mkReq cs\n                                           _ ->  (NoLoc, \"Cannot satisfy the following simultaneous constraints for the unknown \"\n                                                         ++ (if length vs==1 then \"type \" else \"types \") ++ render(commaList vs)  ++\":\\n\")\n                                                : concatMap mkReq cs\n         where mkReq                 = typeError . NoRed\ntypeError (NoUnify info t1 t2)       = case (loc t1, loc t2) of\n                                          (l1@Loc{},l2@Loc{}) -> [(l1, \"\"),(l2,render(text \"Incompatible types\" <+> pretty t1 <+> text \"and\" <+> pretty t2))]\n                                          _ ->  [(getLoc[loc info, loc t1, loc t2],render(text \"Incompatible types\" <+> pretty t1 <+> text \"and\" <+> pretty t2))]\ntypeError (IncompatError info msg)   = case info of\n                                           DeclInfo l1 l2 f sc _ -> [(min l1 l2,\"\"),(max l1 l2,msg)]\n                                           _ -> [(loc info, msg)]\n\n\n\n-- Error throwing functions:\ntyerr x s                           = throwError $ TypeError (loc x) (s ++ \" \" ++ prstr x)\ntyerrs xs s                         = throwError $ TypeError (loc $ head xs) (s ++ \" \" ++ prstrs xs)\nrigidVariable tv                    = throwError $ RigidVariable tv\ninfiniteType tv t                   = throwError $ InfiniteType tv t\nconflictingRow tv                   = throwError $ ConflictingRow tv\nkwdNotFound info n                  = throwError $ incompatError info (render(text (\"keyword \" ++ elemSpec info) <+> quotes (pretty n) <+> text (\"is missing\" ++ elemSuffix info)))\nkwdUnexpected info n                = throwError $ KwdUnexpected info n\nescapingVar tvs t                   = throwError $ EscapingVar tvs t\nnoSelStatic n u                     = throwError $ NoSelStatic n u\nnoSelInstByClass n u                = throwError $ NoSelInstByClass n u\nnoMut n                             = throwError $ NoMut n\nlackSig ns                          = throwError $ LackSig (head ns)\nlackDef ns                          = throwError $ LackDef (head ns)\nsurplusRow p                        = throwError $ SurplusRow p\nnoRed c                             = throwError $ NoRed c\nnoSolve mbt vs cs                   = throwError $ NoSolve mbt vs cs\nnoUnify info t1 t2                  = throwError $ NoUnify info t1 t2\n\nposElemNotFound b c n               = throwError $ incompatError (info c) (\"too \" ++ (if b then \"few \" else \"many positional \") ++ elemSpec (info c) ++ elemSuffix (info c))\n\nincompatError info msg             = case info of\n                                        DeclInfo l1 l2 f sc msg1 -> IncompatError info (msg ++ Pretty.print f)\n                                        _ -> IncompatError info msg\n\nelemSpec DeclInfo{}               = \"argument(s)\"\nelemSpec _                        = \"component(s)\"\n\nelemSuffix DeclInfo{}             = \" in call to \"\nelemSuffix _                      = \" in tuple\"\n\n-- elemHint DeclInfo{}               = \" Hint: The previous definition may have been implicit, using positional notation.\"\n-- elemHint _                        = \"\"\n\ndummyInfo                         = noinfo 0\n\n\n--mkErrorDiagnostic :: String -> String -> Report String -> Diagnostic String\nmkErrorDiagnostic filename src report =\n  let diag = addFile mempty filename src\n  in addReport (addFile diag filename src) report\n\n-- | Convert internal locations to Diagnose positions\nlocToPosition :: SrcLoc -> String -> String -> Position\nlocToPosition NoLoc _ _ =\n  Position (0,0) (0,0) \"\"  -- Empty position\nlocToPosition (Loc start end) filename src =\n  -- Convert byte offsets to line/col positions by counting in source\n  let startPos = offsetToLineCol start src\n      (endLine, endCol) = offsetToLineCol end src\n      -- For multi-line spans, adjust end line to match original error format\n      finalEndPos = if endLine > fst startPos\n                   then (endLine - 1, endCol)\n                   else (endLine, endCol)\n  in Position startPos finalEndPos filename\n\n-- | Helper to convert byte offset to line/col tuple\noffsetToLineCol :: Int -> String -> (Int, Int)\noffsetToLineCol offset src =\n  let beforeOffset = take offset src\n      lines = splitLines beforeOffset\n      lineNum = length lines\n      colNum = if null lines\n               then 1\n               else (length (last lines) + 1)\n  in (lineNum, colNum)\n  where\n    splitLines [] = [\"\"]\n    splitLines s =\n      let (first, rest) = break (=='\\n') s\n      in first : case rest of\n                  [] -> []\n                  (_:rest') -> splitLines rest'\n\n-- | Make a location that only spans the first line\n-- Many of our locations, like for a class definition, span all the lines of the\n-- definition. For printing error messages it's commonly more useful to just\n-- point to where the definition starts rather than highlighting the whole.\nmakeLineOnlyLoc :: SrcLoc -> String -> SrcLoc\nmakeLineOnlyLoc NoLoc _ = NoLoc\nmakeLineOnlyLoc (Loc start _) src =\n  let endOfLine = findEndOfLine start src\n  in Loc start endOfLine\n  where\n    findEndOfLine pos s =\n      let remaining = drop pos s\n          lineEnd = takeWhile (/= '\\n') remaining\n      in pos + length lineEnd\n"
  },
  {
    "path": "compiler/lib/src/Acton/Types.hs",
    "content": "-- Copyright (C) 2019-2021 Data Ductus AB\n--\n-- Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:\n--\n-- 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.\n--\n-- 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.\n--\n-- 3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission.\n--\n-- THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS \"AS IS\" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n--\n\n{-# LANGUAGE MultiParamTypeClasses, FlexibleInstances, FlexibleContexts #-}\nmodule Acton.Types(reconstruct, showTyFile, prettySigs, TypeError(..), TypeErrors(..), TypeProgressCallback, TypeInferredCallback) where\n\nimport Control.Concurrent.Async\nimport Control.Concurrent.Chan\nimport Control.Concurrent.MVar\nimport Control.Concurrent.QSem\nimport Control.DeepSeq\nimport Control.Monad\nimport Control.Monad.Except (runExceptT)\nimport Control.Monad.State.Strict (runState)\nimport Data.Maybe (isJust)\nimport Data.List (nub, intersect, sort)\nimport Pretty\nimport qualified Control.Exception\nimport Debug.Trace\nimport Utils\nimport Acton.Syntax\nimport Acton.Names\nimport Acton.Builtin\nimport Acton.Prim\nimport Acton.NameInfo\nimport Acton.Env\nimport Acton.Solver\nimport Acton.Subst\nimport Acton.Transform\nimport Acton.Converter\nimport Acton.TypeEnv\nimport Acton.WitKnots\nimport qualified InterfaceFiles\nimport qualified Data.ByteString.Char8 as B\nimport qualified Data.ByteString.Base16 as Base16\nimport Data.List (foldl', intersperse, isPrefixOf, partition)\nimport Data.Maybe (mapMaybe)\nimport GHC.Conc (getNumCapabilities)\n\ntype TypeProgressCallback = Int -> Int -> Maybe String -> [String] -> Int -> IO ()\ntype TypeInferredCallback = [String] -> String -> IO ()\n\nemitTypeProgressIO :: Maybe TypeProgressCallback -> Int -> Int -> Maybe String -> [String] -> Int -> IO ()\nemitTypeProgressIO Nothing _ _ _ _ _ = return ()\nemitTypeProgressIO (Just cb) total completed current names weight = cb total completed current names weight\n\nemitTypeInferredIO :: Maybe TypeInferredCallback -> Env -> TEnv -> IO ()\nemitTypeInferredIO Nothing _ _        = return ()\nemitTypeInferredIO (Just cb) env te   = cb (map nstr (dom te)) (render $ pretty (simp env [(n, stripDocsNI i) | (n,i) <- te]))\n\ndata TypeErrors = TypeErrors [TypeError]\n                  deriving (Show)\n\ninstance Control.Exception.Exception TypeErrors\n\n-- | Type-check a module and return its NameInfo, typed module, env, and discovered tests.\nreconstruct                             :: Maybe TypeProgressCallback -> Maybe TypeInferredCallback -> Env0 -> Module -> IO (NameInfo, Module, Env0, [String])\nreconstruct progressCb inferredCb env0 (Module m i mdoc ss)    = do --traceM (\"#################### original env0 for \" ++ prstr m ++ \":\")\n                                             --traceM (render (pretty env0))\n                                             (te,ss1) <- infTop progressCb inferredCb env1 ss\n                                             let env2 = defineClosed te (setMod m env0)\n                                                 (teT,ssT,tests) =\n                                                   if hasTesting i\n                                                     then let (testSs, discovered) = testStmts env2 (modNameStr m) ss1\n                                                          in (te ++ testEnv, ss1 ++ testSs, discovered)\n                                                     else (te, ss1, [])\n                                                 iface = unalias env2 teT\n                                                 nmod = NModule (getImports env2) iface mdoc\n                                             --traceM (\"#################### converted env0:\")\n                                             --traceM (render (pretty env0'))\n                                             return (nmod, Module m i mdoc ssT, env0', tests)\n\n  where env1                            = reserveClosed (assigned ss) (initTypeEnv env0)\n        env0'                           = convEnvProtos env0\n        hasTesting i                    = Import NoLoc [ModuleItem (ModName [name \"testing\"]) Nothing] `elem` i\n        rmTests (Assign _ [PVar _ n _] _ : ss)\n          | nstr n `elem` [\"__unit_tests\",\"__simple_sync_tests\",\"__sync_tests\",\"__async_tests\",\"__env_tests\"]\n                                        = rmTests ss\n        rmTests (Decl _ [Actor _ n _ _ _ _ _] : ss)\n          | nstr n == \"test_main\"       = rmTests ss\n        rmTests (s : ss)                = s : rmTests ss\n        rmTests []                      = []\n\n        -- Convert the module name (ModName) to a string, e.g. \"foo.bar\"\n        modNameStr (ModName ns) = concat (intersperse \".\" (map nstr ns))\n\n\n-- | Print a .ty file header and interface; include name hashes when verbose.\nshowTyFile env0 m fname verbose = do\n                                     (_,nmod,_,sourceMeta,srcH,pubH,implH,imps,nameHashes,roots,tests,mdocH) <- InterfaceFiles.readFile fname\n                                     putStrLn (\"\\n############### Header ###############\")\n                                     putStrLn (\"Imports: \" ++ (show [ (prstr mn, take 16 (B.unpack $ Base16.encode h)) | (mn,h) <- imps ]))\n                                     putStrLn (\"Roots  : \" ++ (show (map prstr roots)))\n                                     putStrLn (\"Tests  : \" ++ (show tests))\n                                     case mdocH of\n                                       Just ds -> putStrLn (\"Doc    : \\\"\\\"\\\"\" ++ ds ++ \"\\\"\\\"\\\"\")\n                                       Nothing -> return ()\n                                     putStrLn (\"ModuleSrcBytesHash: 0x\" ++ (B.unpack $ Base16.encode srcH))\n                                     putStrLn (\"ModulePubHash     : 0x\" ++ (B.unpack $ Base16.encode pubH))\n                                     putStrLn (\"ModuleImplHash    : 0x\" ++ (B.unpack $ Base16.encode implH))\n\n                                     when verbose $ do\n                                       putStrLn (\"\\n############### Source Meta ############\")\n                                       case sourceMeta of\n                                         Nothing -> putStrLn \"None\"\n                                         Just meta -> do\n                                           putStrLn (\"mtimeNs: \" ++ show (InterfaceFiles.sfmMTimeNs meta))\n                                           putStrLn (\"ctimeNs: \" ++ show (InterfaceFiles.sfmCTimeNs meta))\n                                           putStrLn (\"size   : \" ++ show (InterfaceFiles.sfmSize meta))\n                                           putStrLn (\"device : \" ++ maybe \"-\" show (InterfaceFiles.sfmDevice meta))\n                                           putStrLn (\"inode  : \" ++ maybe \"-\" show (InterfaceFiles.sfmInode meta))\n                                       putStrLn (\"\\n############### Name Hashes ############\")\n                                       forM_ nameHashes $ \\nh -> do\n                                         let formatHash h =\n                                               if B.null h\n                                                 then \"\"\n                                                 else \"0x\" ++ B.unpack (Base16.encode h)\n                                             srcHex = formatHash (InterfaceFiles.nhSrcHash nh)\n                                             pubHex = formatHash (InterfaceFiles.nhPubHash nh)\n                                             implHex = formatHash (InterfaceFiles.nhImplHash nh)\n                                             showDep (qn,h) = (prstr qn, take 16 (B.unpack $ Base16.encode h))\n                                         putStrLn (\"Name   : \" ++ prstr (InterfaceFiles.nhName nh))\n                                         putStrLn (\"  src  : \" ++ srcHex)\n                                         putStrLn (\"  pub  : \" ++ pubHex)\n                                         putStrLn (\"  impl : \" ++ implHex)\n                                         when (not (null (InterfaceFiles.nhPubDeps nh))) $\n                                           putStrLn (\"  pubDeps : \" ++ show (map showDep (InterfaceFiles.nhPubDeps nh)))\n                                         when (not (null (InterfaceFiles.nhImplDeps nh))) $\n                                           putStrLn (\"  implDeps: \" ++ show (map showDep (InterfaceFiles.nhImplDeps nh)))\n\n                                     putStrLn (\"\\n############### Interface ############\")\n                                     let NModule imps te mdoc = nmod\n                                     forM_ mdoc $ \\docstring ->\n                                       putStrLn $ \"\\\"\\\"\\\"\" ++ docstring ++ \"\\\"\\\"\\\"\"\n\n                                     putStrLn $ prettySigs env0 m imps te\n\nprettySigs env m imps te        = render $ vcat [ text \"import\" <+> pretty m | m <- imps ] $++$\n                                           vpretty (simp env1 te)\n  where env1                    = defineClosed te $ setMod m env\n\nnodup x\n  | not $ null vs               = err2 vs \"Duplicate names:\"\n  | otherwise                   = True\n  where vs                      = duplicates (bound x)\n\n\naddTyping env n s t c                   = c {info = addT n (simp env s) t (info c){errloc = loc n}}\n    where addT n s t (DfltInfo l m mbe ts)\n                                        = DfltInfo l m mbe ((n,s,t):ts)\n          addT _ _ _ info               = info\n\n------------------------------\n\n-- | One source-level progress unit: the names in the top-level statement and\n-- its weight.  A recursive group can bind several names, so the weight is kept\n-- separate from the label.\ntype TopProgressItem                    = ([String], Int)\n\n-- | Progress events are sent from the scanner thread and from background\n-- checker workers to the single progress reporter thread.\ndata TopProgressEvent                   = TopProgressStarted TopProgressItem\n                                        | TopProgressFinished TopProgressItem\n                                        | TopProgressStop\n\n-- Concurrent type checker\ninfTop                                  :: Maybe TypeProgressCallback -> Maybe TypeInferredCallback -> Env -> Suite -> IO (TEnv,Suite)\ninfTop _ _ _ []                         = return ([], [])\ninfTop progressCb inferredCb env ss     = do -- The scanner itself is sequential, but total statements, i.e.\n                                             -- with a complete type signature can be independently type checked\n                                             -- by a fixed worker queue in the background.\n                                             ncap <- getNumCapabilities\n                                             -- nworkers is the active checkTopStmt parallelism. window is bounded\n                                             -- scanner lookahead, so generated modules cannot allocate one queued\n                                             -- result and closure per total top-level statement.\n                                             let nworkers = max 1 (min ncap (length ss))\n                                                 window = max 1 (min (10 * nworkers) (length ss))\n                                             -- slots is acquired before enqueueing and released by the worker\n                                             -- after that queued total statement has finished checking.\n                                             slots <- newQSem window\n                                             workQ <- newChan\n                                             -- Progress reporting is serialized through one channel so concurrent\n                                             -- workers do not call the UI callback directly.\n                                             progressQ <- newChan\n                                             workers <- replicateM nworkers (async $ worker slots workQ progressQ)\n                                             -- The progress reporter is independent from scanning/checking; it\n                                             -- consumes start/finish events until it receives TopProgressStop.\n                                             progressA <- async $ topProgress progressCb total progressQ\n                                             -- Stop the reporter after all work has been collected, and wait so\n                                             -- the final progress update is emitted before infTop returns.\n                                             let stopProgress = writeChan progressQ TopProgressStop >> wait progressA\n                                                 -- Workers exit on Nothing, written only after collect has consumed\n                                                 -- all real jobs.\n                                                 stopWorkers = replicateM_ nworkers (writeChan workQ Nothing) >> mapM_ wait workers\n                                                 -- run is the real top-level flow: scan left-to-right, collect\n                                                 -- all completed worker results, then validate signatures once\n                                                 -- the whole top-level environment is known.\n                                                 run = do\n                                                   (te,ss,errs) <- go slots workQ progressQ env [] [] ss\n                                                   stopWorkers\n                                                   stopProgress\n                                                   if null errs\n                                                     then do runType \"\" (checkSigs env te)\n                                                             return (te, ss)\n                                                     else throwTopErrors errs\n                                             -- If scan/check throws before stopProgress runs, make sure the\n                                             -- background threads do not stay blocked on readChan.\n                                             run `Control.Exception.finally` (mapM_ cancel workers >> cancel progressA)\n  where -- Total source progress is known syntactically before any type checking.\n        total                           = sum (map stmtProgressWeight ss)\n\n        -- Each worker runs total statements from workQ. Nothing is the stop\n        -- marker; Just jobs must always publish their result MVar and release\n        -- their scanner slot before the worker moves on.\n        worker slots workQ progressQ    = do job <- readChan workQ\n                                             case job of\n                                               Nothing -> return ()\n                                               Just (env,te,s,item,result) -> do\n                                                 writeChan progressQ (TopProgressStarted item)\n                                                 Control.Exception.finally\n                                                   (runWorker env te s result)\n                                                   (writeChan progressQ (TopProgressFinished item) >> signalQSem slots)\n                                                 worker slots workQ progressQ\n\n        -- End of input: every statement has either produced an immediate\n        -- result or a worker wait action, so now wait for them and assemble the\n        -- final top-level environment and typed suite in source order.\n        go slots workQ q env tes rs []  = collect tes rs\n        -- Main scanner loop. This is deliberately sequential: every new scan\n        -- sees a type environment containing all previous top-level declarations.\n        go slots workQ q env tes rs (s:ss)\n                                        = do let item = topProgressItem s\n                                             -- scanOrCheck always scans in this thread.  If the statement is not\n                                             -- total, scanOrCheck also runs checkTopStmt here and blocks progress.\n                                             r <- scanOrCheck env s item q\n                                             case r of\n                                               -- A scan error stops the source-order scan.\n                                               -- Existing worker results are still collected so their errors can\n                                               -- be reported together with this one.\n                                               Left err ->\n                                                 collect tes (return (Left err) : rs)\n                                               -- A total statement has a complete boundary after scanning.  Its\n                                               -- declarations can be put in env immediately, while full checking\n                                               -- continues in the background.\n                                               Right (True,te1,s1,_) -> do\n                                                 -- Acquire a queue slot before enqueueing so scanner lookahead\n                                                 -- is bounded, then let a fixed worker run checkTopStmt.\n                                                 waitQSem slots\n                                                 result <- newEmptyMVar\n                                                 writeChan workQ (Just (env,te1,s1,item,result))\n                                                 -- Continue scanning with the scanned declarations visible.\n                                                 -- Store te1 and result wait on reversed accumulators to preserve\n                                                 -- source order cheaply when collect reverses them.\n                                                 go slots workQ q (tydefineClosed te1 env) (te1:tes) (readMVar result:rs) ss\n                                               -- A non-total statement was already fully checked by scanOrCheck,\n                                               -- so becomes complete / total before we get here and the scanner may\n                                               -- continue.\n                                               Right (_,te2,_,ss1) ->\n                                                 go slots workQ q (tydefineClosed te2 env) (te2:tes) (return (Right ss1):rs) ss\n        -- Wait for all statement results in source order, concatenate the\n        -- accumulated environments, keep typed statements whose checks\n        -- succeeded, and keep every error for aggregate reporting.\n        collect tes rs                  = do xs <- sequence (reverse rs)\n                                             return (concat (reverse tes), [ s | Right ss1 <- xs, s <- ss1 ], [ e | Left e <- xs ])\n        -- Scanner/checker front door for one statement. Ordinary exceptions\n        -- become Left values so infTop can collect multiple errors; async\n        -- exceptions still escape through tryTop.\n        scanOrCheck env s item q        = tryTop $ do\n                                             let p = nstr $ uniqPrefix s\n                                             ((total,te1,s1),st) <- runTypeFromState p (initTypeState p) $ do\n                                               pushFX fxPure tNone\n                                               -- The scanner returns the syntactic totality bit, the scanned\n                                               -- top-level env, and the rewritten statement.\n                                               scanTopStmt env s\n                                             if total\n                                               -- Total means the signature boundary is complete, so the\n                                               -- expensive check can be deferred to a worker.\n                                               then do te1 <- Control.Exception.evaluate (force te1)\n                                                       return (True,te1,s1,[])\n                                               -- Non-total means inference/checking is needed now. This blocks\n                                               -- the scanner because later statements need this completed env.\n                                               else do\n                                                 writeChan q (TopProgressStarted item)\n                                                 Control.Exception.finally\n                                                   (do ((te2,ss1),_) <- runTypeFromState p st (checkTopStmt env te1 s1)\n                                                       (te2,ss1) <- forceChecked te2 ss1\n                                                       emitTypeInferredIO inferredCb env te2\n                                                       return (False,te2,s1,ss1))\n                                                   (writeChan q (TopProgressFinished item))\n        -- Background worker body for a total statement.  It receives exactly\n        -- the scanned env and scanned statement returned by scanTopStmt.\n        checkTotal env te s             = tryTop $ do\n                                             (te1,ss1) <- runType (nstr $ uniqPrefix s) $ do\n                                               pushFX fxPure tNone\n                                               checkTopStmt env te s\n                                             forceSuite te1 ss1\n        -- Once a worker has taken a job, collect may wait on result. Mask the\n        -- publish step so every claimed job fills the MVar; async exceptions are\n        -- rethrown afterwards so cancellation still propagates normally.\n        runWorker env te s result       = Control.Exception.mask $ \\restore -> do\n                                             r <- Control.Exception.try (restore (checkTotal env te s))\n                                             case r of\n                                               Left err -> do putMVar result (Left err)\n                                                              when (isAsyncException err) (Control.Exception.throwIO err)\n                                               Right x -> putMVar result x\n        -- Run a TypeM action and convert TypeM's Either error into the IO\n        -- exception path used by tryTop.\n        runType p m                     = do r <- Control.Exception.evaluate (runTypeMState p m)\n                                             case r of\n                                               Left err -> Control.Exception.throwIO err\n                                               Right (x,_) -> return x\n        runTypeFromState p st m         = do r <- Control.Exception.evaluate (runState (runExceptT m) st)\n                                             case r of\n                                               (Left err, _) -> Control.Exception.throwIO err\n                                               (Right x, st') -> return (x, st')\n        -- checkTotal returns only the typed statements, but still forces the\n        -- worker's type environment so any delayed failures surface in worker.\n        forceSuite te ss                = snd <$> forceChecked te ss\n        forceChecked te ss              = do te <- Control.Exception.evaluate (force te)\n                                             ss <- Control.Exception.evaluate (force ss)\n                                             return (te,ss)\n\ntopProgress                             :: Maybe TypeProgressCallback -> Int -> Chan TopProgressEvent -> IO ()\ntopProgress progressCb total q          = do when (total > 0) $\n                                               emit [] 0\n                                             loop [] 0\n  where loop active done                = do event <- readChan q\n                                             case event of\n                                               TopProgressStarted item -> do\n                                                 let active' = active ++ [item]\n                                                 emit active' done\n                                                 loop active' done\n                                               TopProgressFinished item -> do\n                                                 let active' = removeProgressItem item active\n                                                     done' = done + snd item\n                                                 emit active' done'\n                                                 loop active' done'\n                                               TopProgressStop ->\n                                                 emit [] done\n        emit active done                = emitTypeProgressIO progressCb total done (activeProgressLabel active) (concatMap fst active) 0\n\ntopProgressItem                         :: Stmt -> TopProgressItem\ntopProgressItem s                       = (stmtProgressNames s, stmtProgressWeight s)\n\nremoveProgressItem                      :: TopProgressItem -> [TopProgressItem] -> [TopProgressItem]\nremoveProgressItem item []              = []\nremoveProgressItem item (x:xs)\n  | item == x                           = xs\n  | otherwise                           = x : removeProgressItem item xs\n\nactiveProgressLabel                     :: [TopProgressItem] -> Maybe String\nactiveProgressLabel []                  = Nothing\nactiveProgressLabel active              = Just (formatActive active)\n  where formatActive active             = show nstmt ++ \" \" ++ plural \"stmt\" nstmt ++ \", \"\n                                       ++ show nnames ++ \" \" ++ plural \"name\" nnames ++ \": \"\n                                       ++ formatNames names\n          where nstmt                   = length active\n                names                   = concatMap fst active\n                nnames                  = length names\n        plural s n                      = s ++ if n == 1 then \"\" else \"s\"\n        formatNames [n]                 = n\n        formatNames [n1,n2]             = n1 ++ \", \" ++ n2\n        formatNames (n1:n2:rest)        = n1 ++ \", \" ++ n2 ++ \" (+\" ++ show (length rest) ++ \" others)\"\n        formatNames []                  = \"\"\n\ntryTop                                  :: IO a -> IO (Either Control.Exception.SomeException a)\ntryTop m                                = do r <- Control.Exception.try m\n                                             case r of\n                                               Left err | isAsyncException err -> Control.Exception.throwIO err\n                                               _ -> return r\n\nisAsyncException                        :: Control.Exception.SomeException -> Bool\nisAsyncException err                    = isJust (Control.Exception.fromException err :: Maybe Control.Exception.SomeAsyncException)\n\nthrowTopErrors                          :: [Control.Exception.SomeException] -> IO a\nthrowTopErrors errs                     = case others of\n                                           err:_ -> Control.Exception.throwIO err\n                                           [] -> case typeErrs of\n                                                   [] -> error \"Internal error: empty type error list\"\n                                                   [err] -> Control.Exception.throwIO err\n                                                   _ -> Control.Exception.throwIO (TypeErrors typeErrs)\n  where (typeErrs, others)              = foldl' collect ([], []) errs\n        collect (ts, os) err            = case topTypeErrors err of\n                                            Just ts' -> (ts ++ ts', os)\n                                            Nothing -> (ts, os ++ [err])\n\ntopTypeErrors                           :: Control.Exception.SomeException -> Maybe [TypeError]\ntopTypeErrors err                       = case Control.Exception.fromException err of\n                                            Just (TypeErrors errs) -> Just errs\n                                            Nothing -> case Control.Exception.fromException err of\n                                                         Just typeErr -> Just [typeErr]\n                                                         Nothing -> Nothing\n\n-- | Progress weight for one top-level statement, based on bound names.\n-- This makes large recursive groups count proportionally.\nstmtProgressWeight :: Stmt -> Int\nstmtProgressWeight s = length (stmtProgressNames s)\n\n-- | Top-level bound names used for progress reporting and weighting.\nstmtProgressNames :: Stmt -> [String]\nstmtProgressNames (Decl _ ds)          = [ nstr (dname' d) | d <- ds ]\nstmtProgressNames s@Assign{}           = map nstr (bound s)\nstmtProgressNames s@Signature{}        = map nstr (bound s)\nstmtProgressNames s                    = error (\"Unexpected top-level stmt: \" ++ prstr s)\n\nuniqPrefix :: Stmt -> Name\nuniqPrefix (Decl _ (d : _))            = dname' d\nuniqPrefix s@Assign{}                  = head (bound s)\nuniqPrefix s@Signature{}               = head (bound s)\nuniqPrefix s                           = error (\"Unexpected top-level stmt: \" ++ prstr s)\n\n\ninfTopStmt                              :: Env -> Stmt -> TypeM (TEnv, [Stmt])\ninfTopStmt env s                        = do (total,te1,s) <- scanTopStmt env s\n                                             -- NOTE: when total is True, te2 below is guaranteed to be identical to te1\n                                             --when total $ traceM (\"## Scanned total env for \" ++ prstrs (dom te1))\n                                             (te2,s) <- checkTopStmt env te1 s\n                                             return (te2, s)\n\n\nscanTopStmt                             :: Env -> Stmt -> TypeM (Bool, TEnv, Stmt)\nscanTopStmt env (Decl l ds)             = do (_,te,ds) <- infEnv (setInDecl env) ds\n                                             return (null $ ufree te, te, Decl l ds)\nscanTopStmt env (Signature l ns sc d)   = return (True, [ (n, NSig sc d Nothing) | n <- ns ], Signature l ns sc d)\nscanTopStmt env (Assign l pats e)       = do (te,_,pats) <- infEnvT env pats\n                                             return (null $ ufree te, te, Assign l pats e)\n\n\ncheckTopStmt                            :: Env -> TEnv -> Stmt -> TypeM (TEnv, [Stmt])\ncheckTopStmt env te (Decl l ds)         = do (cs,ds) <- checkEnv (tydefine te env) ds\n\n                                             --traceM (\"****************************************** infer (\" ++ show (length cs) ++ \") \" ++ prstrs (bound ds))\n                                             --traceM (\"\\n\\n\\n############\\n\" ++ render (nest 4 $ vcat $ map pretty te))\n                                             --traceM (\"------------\\n\" ++ render (nest 4 $ vcat $ map pretty ds))\n                                             --traceM (\"\\\\\\\\\\\\\\\\\\\\\\\\\\n\" ++ render (nest 4 $ vcat $ map pretty cs))\n\n                                             (te,eq,ds) <- genEnv env cs te ds\n                                             --traceM (\"============ push\\n\" ++ render (nest 4 $ vcat $ map pretty eq))\n                                             --traceM (\"~~~~~~~~~~~~ i.e. top:\\n\" ++ render (nest 4 $ vcat $ map pretty eq0))\n                                             --traceM (\"============ and scoped:\\n\" ++ render (nest 4 $ vcat $ map pretty eq1))\n                                             --traceM (\"------------ onto\\n\" ++ render (nest 4 $ vcat $ map pretty ds))\n                                             finishToStmt env te eq (Decl l ds)\ncheckTopStmt env te (Signature l ns sc d)\n                                        = return ([ (n, NSig sc d Nothing) | n <- ns ], [Signature l ns sc d])\ncheckTopStmt env te (Assign l pats e)   = do (_,t,pats) <- infEnvT env pats\n                                             (cs,e) <- inferSub env t e\n                                             eq <- solveAll env te cs\n                                             finishToStmt env te eq (Assign l pats e)\n\nfinishToStmt env te eq s                = do te <- defaultX env te\n                                             --traceM (\"===========\\n\" ++ render (nest 4 $ vcat $ map pretty te))\n                                             --traceM (\"..........................................\"  ++ prstrs (bound s) ++ \"\\n\")\n                                             let (eq0, eq1) = spliteqns eq\n                                             s <- defaultX env =<< termred eq1 <$> usubst (pushEqns env eq0 s)\n                                             tieWitKnots te [fixupSelf s]\n\ndefaultX                                :: (UFree a, USubst a) => Env -> a -> TypeM a\ndefaultX env x                          = do defaultVars (ufree x)\n                                             usubst x\n  where defaultVars tvs                 = do tvs' <- ufree <$> usubst (map tUni tvs)\n                                             sequence [ usubstitute tv (dflt (uvkind tv)) | tv <- tvs' ]\n        dflt KType                      = tNone\n        dflt KFX                        = fxPure\n        dflt PRow                       = posNil\n        dflt KRow                       = kwdNil\n\npushEqns                                :: Env -> Equations -> Stmt -> Stmt\npushEqns env [] s                       = s\npushEqns env eqs s\n  | null pre                            = inject env inj s\n  | otherwise                           = withLocal (bindWits pre) $ inject env inj s\n  where backward                        = free s `intersect` bound eqs\n        (pre,inj)                       = split [] [] (bound s) eqs\n        split pre inj bvs []            = (reverse pre, reverse inj)\n        split pre inj bvs (eq:eqs)\n          | null forward                = split (eq:pre) inj bvs eqs\n          | otherwise                   = split pre (eq:inj) (bound eq ++ bvs) eqs\n          where forward                 = free eq `intersect` bvs\n\ninject env [] s                         = s\ninject env eqs (Decl l ds)              = Decl l [ d{ dbody = prune [] (free d) reveqs ++ dbody d } | d <- ds ]\n  where reveqs                          = reverse eqs\n        prune inj fvs []                = --trace (\"### Injecting \" ++ prstrs (bound inj) ++ \" into \" ++ prstr n) $\n                                          bindWits inj\n        prune inj fvs (eq:eqs)\n          | null needed                 = prune inj fvs eqs\n          | otherwise                   = prune (eq:inj) (free eq ++ fvs) eqs\n          where needed                  = bound eq `intersect` fvs\ninject env eqs (With l [] ss)           = With l [] (injlast eqs ss)\n  where injlast eqs [s]                 = [inject env eqs s]\n        injlast eqs (s:ss)              = s : injlast eqs ss\ninject env eqs s                        = error (\"# Internal error: cyclic witnesses \" ++ prstrs eqs ++ \"\\n# and statement\\n\" ++ prstr s)\n\n\ngenEnv                                  :: Env -> Constraints -> TEnv -> [Decl] -> TypeM (TEnv,Equations,[Decl])\ngenEnv env cs te ds\n  | any typeDecl te                     = do te <- usubst te\n                                             --traceM (\"## genEnv types 1\\n\" ++ render (nest 6 $ pretty te))\n                                             --traceM (\"   where\\n\" ++ render (nest 6 $ vcat $ map pretty cs))\n                                             eq <- solveAll (posdefine (filter typeDecl te) env) te cs\n                                             te <- usubst te\n                                             --traceM (\"## genEnv types 2\\n\" ++ render (nest 6 $ pretty te))\n                                             --traceM (\"   where\\n\" ++ render (nest 6 $ vcat $ map pretty cs))\n                                             return (te, eq, ds)\n  | otherwise                           = do te <- usubst te\n                                             --traceM (\"## genEnv defs 1\\n\" ++ render (nest 6 $ pretty te))\n                                             --traceM (\"   where\\n\" ++ render (nest 6 $ vcat $ map pretty cs))\n                                             (cs,eq) <- newSimplify env te cs\n                                             te <- usubst te\n                                             (gen_us, gen_cs, te, eq) <- refine env cs te eq\n                                             let gen_vs = take (length gen_us) tvarSupply\n                                             sequence [ usubstitute uv (tVar tv) | (uv,tv) <- gen_us `zip` gen_vs ]\n                                             te <- usubst te\n                                             gen_cs <- usubst gen_cs\n                                             --traceM (\"## genEnv defs 2 [\" ++ prstrs gen_vs ++ \"]\\n\" ++ render (nest 6 $ pretty te))\n                                             --traceM (\"   where\\n\" ++ render (nest 6 $ vcat $ map pretty gen_cs))\n                                             let (q,ws) = qualify gen_vs gen_cs\n                                                 te1 = map (generalize q) te\n                                                 (eq1,eq2) = splitEqs (dom ws) eq\n                                                 ds1 = map (abstract q ds ws eq1) ds\n                                             --traceM (\"## genEnv defs 3 [\" ++ prstrs q ++ \"]\\n\" ++ render (nest 6 $ pretty te1))\n                                             return (te1, eq2, ds1)\n  where\n    qualify vs cs                       = (q, concat wss)\n      where (q,wss)                     = unzip $ map qbind vs\n            qbind v                     = (QBind v bounds, wits)\n              where bounds              = [ p | Proto _ _ w (TVar _ v') p <- cs, v == v' ]\n                    wits                = [ (w, proto2type t p) | Proto _ _ w t@(TVar _ v') p <- cs, v == v' ]\n\n    generalize q (n, NDef (TSchema l [] t) d doc)\n                                        = (n, NDef (TSchema l q t) d doc)\n    generalize q (n, i)                 = (n, i)\n\n\n    abstract q ds ws eq d@Def{}\n      | null $ qbinds d                 = d{ qbinds = noqual env q,\n                                             pos = wit2par ws (pos d),\n                                             dbody = bindWits eq ++ wsubst ds q ws (dbody d) }\n      | otherwise                       = d{ dbody = bindWits eq ++ wsubst ds q ws (dbody d) }\n\n    wsubst ds [] []                     = id\n    wsubst ds q ws                      = termsubst s\n      where s                           = [ (n, Lambda l0 p k (Call l0 (tApp (eVar n) tvs) (wit2arg ws (pArg p)) (kArg k)) fx)\n                                            | Def _ n [] p k _ _ _ fx _ <- ds ]\n            tvs                         = map tVar $ qbound q\n\n    splitEqs ws eq\n      | null eq1                        = ([], eq)\n      | otherwise                       = (eq1++eq1', eq2')\n      where (eq1,eq2)                   = partition (any (`elem` ws) . free) eq\n            (eq1',eq2')                 = splitEqs (bound eq1 ++ ws) eq2\n\n    newRefine env cs te eq              = do (eq,cs) <- newsolve env te eq cs\n                                             te <- usubst te\n                                             eq <- usubst eq\n                                             return (ufree te, cs, te, eq)\n\n    refine env cs te eq\n      | run_new_solver                  = newRefine env cs te eq\n      | not $ null solve_cs             = do --traceM (\"  #solving: \" ++ prstrs solve_cs)\n                                             (cs',eq') <- solve env noQual te eq cs\n                                             refineAgain cs' eq'\n      | not $ null ambig_vs             = do --traceM (\"  #defaulting: \" ++ prstrs ambig_vs)\n                                             (cs',eq') <- solve env isAmbig te eq cs\n                                             refineAgain cs' eq'\n      | not $ null tail_vs              = do sequence [ tryUnify (Simple NoLoc \"internal\") (tUni v) (tNil $ uvkind v) | v <- tail_vs ]\n                                             refineAgain cs eq\n      | otherwise                       = do eq <- usubst eq\n                                             return (gen_vs, cs, te, eq)\n      where ambig_vs                    = ufree cs \\\\ closeDepVars (safe_vs) cs\n            tail_vs                     = gen_vs `intersect` (tailvars te ++ tailvars cs)\n\n            safe_vs                     = if null def_vss then [] else nub $ foldr1 intersect def_vss\n            def_vss                     = [ nub $ filter canGen $ ufree sc | (_, NDef sc _ _) <- te, null $ scbind sc ]\n            gen_vs                      = nub (foldr union (ufree cs) def_vss)\n\n            isAmbig c                   = any (`elem` ambig_vs) (ufree c)\n\n            refineAgain cs eq           = do (cs1,eq1) <- newSimplify env te cs\n                                             te <- usubst te\n                                             refine env cs1 te (eq1++eq)\n\n            solve_cs                    = [ c | c <- cs, noQual c ]\n\n            noQual (Proto _ _ _ (TUni _ u) p)\n                                        = False\n            noQual c                    = True\n\n            canGen tv                   = uvkind tv /= KFX\n\n\nmarkScoped env n q te []                = return ([], [])\n-- Should remove this simplify call too, but doing so destroys performance of our current inferior constraint-solver (see module yang.schema in acton-yang).\nmarkScoped env n [] te cs               = newSimplify env te cs\n-- Return the marks in terms of NotImplemented equations for now, so that we can coexist with the need to also run simplify (see above)\nmarkScoped env n q te cs                = return (cs, eq)\n  where eq                              = [ mkEqn env w tWild eNotImpl | w <- ws ]\n        ws                              = scopedWits env q cs\n\ntempGoal t                              = [(nWild, NVar t)]\n\nnewSolveAll env te cs                   = do (eq,cs) <- newsolve env te [] cs\n                                             (eq,_) <- newsolve env [] eq cs\n                                             return eq\n\nsolveAll env te []                      = return []\nsolveAll env te cs\n  | run_new_solver                      = newSolveAll env te cs\n  | otherwise                           = do --traceM (\"\\n\\n### solveAll \" ++ prstrs cs)\n                                             (cs,eq) <- newSimplify env te cs\n                                             (cs,eq) <- solve env (const True) te eq cs\n                                             return eq\n\n\n--------------------------------------------------------------------------------------------------------------------------\n\nclass Infer a where\n    infer                               :: Env -> a -> TypeM (Constraints,Type,a)\n\nclass InfEnv a where\n    infEnv                              :: Env -> a -> TypeM (Constraints,TEnv,a)\n\nclass InfEnvT a where\n    infEnvT                             :: Env -> a -> TypeM (TEnv,Type,a)\n\n\n--------------------------------------------------------------------------------------------------------------------------\n\ncommonTEnv                              :: Env -> [TEnv] -> TypeM (Constraints,TEnv)\ncommonTEnv env []                       = return ([], [])\ncommonTEnv env (te:tes)                 = unifEnv tes (restrict te vs)\n  where vs                              = foldr intersect (dom te) $ map dom tes\n        l                               = length tes\n        unifEnv tes []                  = return ([], [])\n        unifEnv tes ((n,i):te)          = do t <- newUnivar env\n                                             let (cs1,i') = unif n t i\n                                             (cs2,te') <- unifEnv tes te\n                                             return (cs1++cs2, (n,i'):te')\n        unif n t0 (NVar t)\n          | length ts == l              = ([ Cast (locinfo t 26) env t1 t0 | t1 <- t:ts ], NVar t0)\n          where ts                      = [ t | te <- tes, Just (NVar t) <- [lookup n te] ]\n        unif n t0 (NSVar t)\n          | length ts == l              = ([ Cast (locinfo t 27) env t1 t0 | t1 <- t:ts ], NSVar t0)\n          where ts                      = [ t | te <- tes, Just (NSVar t) <- [lookup n te] ]\n{-\n        unif n t0 (NDef sc d)\n          | null (scbind sc) &&\n            length ts == l              = ([ Cast t t0 | t <- ts ], NDef (monotype t0) d)\n          where ts                      = [ sctype sc | te <- tes, Just (NDef sc d') <- [lookup n te], null (scbind sc), d==d' ]\n        unif n t0 (NDef _ _)\n          | length scs == l             = case findName n env of\n                                             NReserved -> err1 n \"Expected a common signature for\"\n                                             NSig sc d -> ([], NDef sc d)\n          where scs                     = [ sc | te <- tes, Just (NDef sc d) <- [lookup n te] ]\n-}\n        unif n _ _                      = err1 n \"Conflicting bindings for\"\n\n\n\ninfSuiteEnv env ss                      = do (cs,te,ss') <- infEnv env ss\n                                             checkSigs env te\n                                             return (cs, te, ss')\n\ncheckSigs env te\n  | null ns                            = return ()\n  | otherwise                           = err2 ns \"Signature lacks subsequent binding\"\n  where (sigs,terms)                    = sigTerms te\n        ns                              = dom sigs \\\\ dom terms\n\ninfLiveEnv env x\n  | fallsthru x                         = do (cs,te,x') <- infSuiteEnv env x\n                                             return (cs, Just te, x')\n  | otherwise                           = do (cs,te,x') <- infSuiteEnv env x\n                                             return (cs, Nothing, x')\n\nliveCombine te Nothing                  = Nothing\nliveCombine Nothing te'                 = Nothing\nliveCombine (Just te) (Just te')        = Just $ te++te'\n\nfxUnwrapSc env sc                       = sc{ sctype = fxUnwrap env $ sctype sc }\n\nfxUnwrap env (TFun l fx p k t)          = TFun l (fxUnwrap env fx) p k t\nfxUnwrap env (TFX l FXAction)\n  | inAct env                           = TFX l FXProc\nfxUnwrap env t                          = t\n\nwrap env t@TFun{}                       = do tvx <- newUnivarOfKind KFX env\n                                             tvy <- newUnivarOfKind KFX env\n                                             w <- newWitness\n                                             return (Proto (locinfo t 28) env w tvx (pWrapped (effect t) tvy), t{ effect = tvx })\n\nwrapped l kw env cs ts args             = do tvx <- newUnivarOfKind KFX env\n                                             tvy <- newUnivarOfKind KFX env\n                                             let p = pWrapped tvx tvy\n                                                 Just (_, sc, Just Static) = findAttr env p kw\n                                             (_,tvs,t0) <- instantiate env sc\n                                             fx <- newUnivarOfKind KFX env\n                                             t' <- newUnivar env\n                                             let t1 = vsubst [(fxSelf,fx)] t0\n                                                 t2 = tFun fxPure (foldr posRow posNil ts) kwdNil t'\n                                             w <- newWitness\n                                             unify (locinfo l 30) t1 t2\n                                             t' <- usubst t'\n                                             cs' <- usubst (Proto (locinfo l 29) env w fx p : cs)\n                                             return (cs', t', eCall (tApp (Dot l0 (eVar w) kw) tvs) args)\n\n--------------------------------------------------------------------------------------------------------------------------\n\ninstance (InfEnv a) => InfEnv [a] where\n    infEnv env []                       = return ([], [], [])\n    infEnv env (s : ss)                 = do (cs1,te1,s1) <- infEnv env s\n                                             let te1' = if inDecl env then noDefs te1 else te1      -- TODO: also stop class instantiation!\n                                                 env' = tydefine te1' env\n                                             (cs2,te2,ss2) <- infEnv env' ss\n                                             return (cs1++cs2, te1++te2, s1:ss2)\n\ninstance InfEnv Stmt where\n    infEnv env (Expr l e)\n      | e == eNotImpl                   = return ([], [], Expr l e)\n      | otherwise                       = do (cs,_,e') <- infer env e\n                                             return (cs, [], Expr l e')\n\n    infEnv env (Assign l pats e)\n      | nodup pats, e == eNotImpl       = do (te,t,pats') <- infEnvT env pats\n                                             return ([], te, Assign l pats' e)\n      | otherwise                       = do (te,t,pats') <- infEnvT env pats\n                                             (cs,e') <- inferSub env t e\n                                             return (cs, te, Assign l pats' e')\n\n    infEnv env (Assert l e1 e2)         = do (cs1,_,_,_,e1') <- inferTest env e1\n                                             (cs2,e2') <- inferSub env tStr e2\n                                             return (cs1++cs2, [], Assert l e1' e2')\n    infEnv env s@(Pass l)               = return ([], [], s)\n\n    infEnv env s@(Return l Nothing)     = do t <- currRet\n                                             return ([Cast (locinfo l 31) env tNone t], [], Return l Nothing)\n    infEnv env (Return l (Just e))      = do t <- currRet\n                                             (cs,e') <- inferSub env t e\n                                             return (cs, [], Return l (Just e'))\n    infEnv env (Raise l e)              = do (cs,t,e') <- infer env e\n                                             return (Cast (locinfo2 32 e) env t tException : cs, [], Raise l e')\n    infEnv env s@(Break _)              = return ([], [], s)\n    infEnv env s@(Continue _)           = return ([], [], s)\n    infEnv env (If l bs els)            = do (css,tes,bs') <- fmap unzip3 $ mapM (infLiveEnv env) bs\n                                             (cs0,te,els') <- infLiveEnv env els\n                                             (cs1,te1) <- commonTEnv env $ catMaybes (te:tes)\n                                             return (cs0++cs1++concat css, te1, If l bs' els')\n    infEnv env (While l e b els)        = do (cs1,env',s,_,e') <- inferTest env e\n                                             (cs2,te1,b') <- infSuiteEnv env' b\n                                             (cs3,te2,els') <- infSuiteEnv env els\n                                             return (cs1++cs2++cs3, [], While l e' (termsubst s b') els')\n    infEnv env (For l p e b els)\n      | nodup p                         = do (te,t1,p') <- infEnvT env p\n                                             t2 <- newUnivar env\n                                             (cs2,e') <- inferSub env t2 e\n                                             (cs3,te1,b') <- infSuiteEnv (define te env) b\n                                             (cs4,te2,els') <- infSuiteEnv env els\n                                             w <- newWitness\n                                             return (Proto (locinfo2 33 e) env w t2 (pIterable t1) :\n                                                     cs2++cs3++cs4, [], For l p' (eCall (eDot (eVar w) iterKW) [e']) b' els')\n    infEnv env (Try l b hs els fin)     = do (cs1,te,b') <- infLiveEnv env b\n                                             (cs2,te',els') <- infLiveEnv (maybe id define te $ env) els\n                                             (css,tes,hs') <- fmap unzip3 $ mapM (infLiveEnv env) hs\n                                             (cs3,te1) <- commonTEnv env $ catMaybes $ (liveCombine te te'):tes\n                                             (cs4,te2,fin') <- infSuiteEnv env fin\n                                             fx <- currFX\n                                             return (--Cast fxProc fx :\n                                                     cs1++cs2++cs3++cs4++concat css, te1++te2, Try l b' hs' els' fin')\n    infEnv env (With l items b)\n      | nodup items                     = do (cs1,te,items') <- infEnv env items\n                                             (cs2,te1,b') <- infSuiteEnv (define te env) b\n                                             return $ (cs1++cs2, exclude te1 (dom te), With l items' b')\n\n    infEnv env (VarAssign l pats e)\n      | nodup pats                      = do (te,t,pats') <- infEnvT env pats\n                                             (cs,e') <- inferSub env t e\n                                             return (cs, [ (n,NSVar t) | (n,NVar t) <- te], VarAssign l pats' e')\n\n    infEnv env (After l e1 e2)          = do (cs1,e1') <- inferSub env tFloat e1\n                                             (cs2,t,e2') <- infer env e2\n                                             -- TODO: constrain t\n                                             fx <- currFX\n                                             return (Cast (locinfo l 34) env fxProc fx :\n                                                     cs1++cs2, [], After l e1' e2')\n\n    infEnv env (Signature l ns sc@(TSchema _ q t) dec)\n      | not $ null bad                  = illegalSigOverride (head bad)\n      | otherwise                       = return ([], [(n, NSig sc dec' Nothing) | n <- ns], Signature l ns sc dec)\n      where\n        redefs                          = [ (n,i) | n <- ns, let i = findName n env, i /= NReserved ]\n        bad                             = [ n | (n,i) <- redefs, not $ ok i ]\n        ok (NSig (TSchema _ [] t') d _) = null q && castable env t t' && dec == d\n        ok _                            = False\n        dec'                            = if inClass env && isProp dec sc then Property else dec\n\n    infEnv env (Data l _ _)             = notYet l \"data syntax\"\n\n    infEnv env (Decl l ds)\n      | inDecl env && nodup ds          = do (cs1,te1,ds1) <- infEnv env ds\n                                             return (cs1, te1, Decl l ds1)\n      | nodup ds                        = do --traceM (\"######## decls: \" ++ prstrs (declnames ds))\n                                             (_,te1,ds1) <- infEnv (setInDecl env) ds\n                                             (cs2,ds2) <- checkEnv (tydefine te1 env) ds1\n                                             --traceM (\"-------- done: \" ++ prstrs (declnames ds))\n                                             return (cs2, te1, Decl l ds2)\n\n    infEnv env (Delete l targ)          = do (cs0,t0,e0,tg) <- infTarg env targ\n                                             (cs1,stmt) <- del t0 e0 tg\n                                             return (cs0++cs1, [], stmt)\n      where del t0 e0 (TgVar n)         = do return ( Cast (locinfo l 35) env tNone t0 : [], sAssign (pVar' n) eNone)\n            del t0 e0 (TgIndex ix)      = do ti <- newUnivar env\n                                             (cs,ix) <- inferSub env ti ix\n                                             t <- newUnivar env\n                                             w <- newWitness\n                                             return ( Proto (locinfo l 36) env w t0 (pIndexed ti t) : cs, sExpr $ dotCall w delitemKW [e0, ix] )\n            del t0 e0 (TgSlice sl)      = do (cs,sl) <- inferSlice env sl\n                                             t <- newUnivar env\n                                             w <- newWitness\n                                             return ( Proto (locinfo l 37) env w t0 (pSliceable t) : cs, sExpr $ dotCall w delsliceKW [e0, sliz2exp sl] )\n            del t0 e0 (TgDot n)         = do t <- newUnivar env\n                                             return ( Mut (locinfo l 38) env t0 n t : Cast (locinfo l 39) env tNone t : [], sMutAssign (eDot e0 n) eNone )\n\n    infEnv env (MutAssign l targ e)     = do (cs0,t0,e0,tg) <- infTarg env targ\n                                             t <- newUnivar env\n                                             (cs1,e) <- inferSub env t e\n                                             (cs2,stmt) <- asgn t0 t e0 e tg\n                                             return (cs0++cs1++cs2, [], stmt)\n      where asgn t0 t e0 e (TgVar n)    = do tryUnify (locinfo l 40) t0 t\n                                             return ( [], sAssign (pVar' n) e )\n            asgn t0 t e0 e (TgIndex ix) = do ti <- newUnivar env\n                                             (cs,ix) <- inferSub env ti ix\n                                             w <- newWitness\n                                             return ( Proto (locinfo l 41) env w t0 (pIndexed ti t) : cs, sExpr $ dotCall w setitemKW [e0, ix, e] )\n            asgn t0 t e0 e (TgSlice sl) = do (cs,sl) <- inferSlice env sl\n                                             t' <- newUnivar env\n                                             w <- newWitness\n                                             w' <- newWitness\n                                             return ( Proto (locinfo l 42) env w t0 (pSliceable t') :\n                                                      Proto (locinfo l 43) env w' t (pIterable t') :\n                                                      cs, sExpr $ eCall (tApp (eDot (eVar w) setsliceKW) [t]) [e0, eVar w', sliz2exp sl, e] )\n            asgn t0 t e0 e (TgDot n)    = do return ( Mut (locinfo l 44) env t0 n t : [], sMutAssign (eDot e0 n) e )\n\n    infEnv env (AugAssign l targ o e)   = do (cs0,t0,e0,tg) <- infTarg env targ\n                                             t1 <- newUnivar env\n                                             (cs1,e) <- inferSub env t1 e\n                                             let (proto,kw) = oper t1 o\n                                             t <- if o `elem` [MultA,DivA] then newUnivar env else pure t1\n                                             w <- newWitness\n                                             (ss,x) <- mkvar t0 e0\n                                             (cs2,stmt) <- aug t0 t x (dotCall w kw) e tg\n                                             return ( Proto (locinfo l 45) env w t proto : cs0++cs1++cs2, [], withLocal ss stmt )\n      where oper t MultA                = (pTimes t,  imulKW)\n            oper t DivA                 = (pDiv t,    itruedivKW)\n            oper _ PlusA                = (pPlus,     iaddKW)\n            oper _ MinusA               = (pMinus,    isubKW)\n            oper _ PowA                 = (pNumber,   ipowKW)\n            oper _ ModA                 = (pIntegral, imodKW)\n            oper _ EuDivA               = (pIntegral, ifloordivKW)\n            oper _ ShiftLA              = (pIntegral, ilshiftKW)\n            oper _ ShiftRA              = (pIntegral, irshiftKW)\n            oper _ BOrA                 = (pLogical,  iorKW)\n            oper _ BAndA                = (pLogical,  iandKW)\n            oper _ MMultA               = (pMatrix,   imatmulKW)\n\n            aug t0 t x f e (TgVar _)    = do tryUnify (locinfo l 46) t0 t\n                                             return ( [], sAssign (pVar' x) $ f [eVar x, e] )\n            aug t0 t x f e (TgIndex ix) = do ti <- newUnivar env\n                                             (cs,ix) <- inferSub env ti ix\n                                             w <- newWitness\n                                             return ( Proto (locinfo l 47) env w t0 (pIndexed ti t) :\n                                                      cs, sExpr $ dotCall w setitemKW [eVar x, ix, f [dotCall w getitemKW [eVar x, ix], e]])\n            aug t0 t x f e (TgSlice sl) = do tryUnify (locinfo l 1115) t0 t\n                                             (cs,sl) <- inferSlice env sl\n                                             t' <- newUnivar env\n                                             w <- newWitness\n                                             w' <- newWitness\n                                             let e1 = f [dotCall w getsliceKW [eVar x, sliz2exp sl], e]\n                                             return ( Proto (locinfo l 48) env w t (pSliceable t') :\n                                                      Proto (locinfo l 49) env w' t (pIterable t') :\n                                                      cs, sExpr $ eCall (tApp (eDot (eVar w) setsliceKW) [t]) [eVar x, eVar w', sliz2exp sl, e1] )\n            aug t0 t x f e (TgDot n)    = do return ( Mut (locinfo l 50) env t0 n t : [], sMutAssign (eDot (eVar x) n) $ f [eDot (eVar x) n, e])\n\n\ndotCall w kw                            = eCall (eDot (eVar w) kw)\n\nmkvar t (Var _ (NoQ x))                 = return ([], x)\nmkvar t e                               = do x <- newTmp\n                                             return ([sAssign (pVar x t) e], x)\n\ndata Tg                                 = TgVar Name | TgIndex Expr | TgSlice Sliz | TgDot Name\n\ninfTarg env e@(Var l (NoQ n))           = case findName n env of\n                                             NReserved ->\n                                                 err1 n \"Variable not yet assigned\"\n                                             NSig{} ->\n                                                 err1 n \"Variable not yet assigned\"\n                                             NVar t ->\n                                                 return ([], t, e, TgVar n)\n                                             NSVar t -> do\n                                                 fx <- currFX\n                                                 return ([Cast (locinfo l 51) env fxProc fx], t, e, TgVar n)\n                                             _ ->\n                                                 err1 n \"Variable not assignable:\"\ninfTarg env (Index l e ix)              = do (cs,t,e) <- infer env e\n                                             fx <- currFX\n                                             return (Cast (locinfo l 52) env fxMut fx : Cast (locinfo' l 53 e) env t tObject : cs, t, e, TgIndex ix)\ninfTarg env (Slice l e sl)              = do (cs,t,e) <- infer env e\n                                             fx <- currFX\n                                             return (Cast (locinfo l 54) env fxMut fx : Cast (locinfo' l 55 e) env t tObject : cs, t, e, TgSlice sl)\ninfTarg env (Dot l e n)                 = do (cs,t,e) <- infer env e\n                                             fx <- currFX\n                                             return (Cast (locinfo l 56) env fxMut fx : Cast (locinfo' l 57 e) env t tObject : cs, t, e, TgDot n)\n\nsliz2exp (Sliz _ e1 e2 e3)              = eCall (eQVar qnSlice) $ map (maybe eNone id) [e1,e2,e3]\n\nwithLocal [] s                          = s\nwithLocal ss s                          = With l0 [] (ss ++ [s])\n\n--------------------------------------------------------------------------------------------------------------------------\n\nmatchingDec n sc dec NoDec              = True\nmatchingDec n sc dec dec'\n  | dec == dec'                         = True\n  | otherwise                           = decorationMismatch n sc dec\n\nmatchDefAssumption env cs1 def@Def{dname=n, qbinds=q1}\n  | q0 == q1                            = match cs1 [] def\n  | null q1                             = do let uvs = nub (ufree def ++ ufree cs1) \\\\ ufree env\n                                             --traceM (\"### matching \" ++ prstr def)\n                                             --traceM (\"### with\\n\" ++ render (nest 4 $ vcat $ map pretty cs1))\n                                             --traceM (\"### against \" ++ prstr (n, findName n env) ++ \"\\n\")\n                                             sequence [ usubstitute uv =<< newUnivarOfKind (uvkind uv) env0 | uv <- uvs ]\n                                             def <- usubst def\n                                             cs1 <- usubst (requantize env0 cs1)\n                                             match cs1 [] def\n  | otherwise                           = do (cs, uvs) <- instQBinds env0 q1\n                                             let eq1 = witSubst env0 q1 cs\n                                                 s = qbound q1 `zip` uvs\n                                                 cs1' = vsubst s (requantize env0 cs1)\n                                                 def' = vsubst s def\n                                             match (cs ++ cs1') eq1 def'\n  where NDef (TSchema _ q0 t) dec _     = findName n env\n        t0 | inClass env                = addSelf t (Just dec)\n           | otherwise                  = t\n        env0                            = tydefineVars q0 env\n        fx | inAct env                  = dfx def\n           | otherwise                  = effect t0\n\n        match cs eq def                 = do --traceM (\"## matchDefAssumption \" ++ prstr n ++ \": [\" ++ prstrs q0 ++ \"] => \")\n                                             --traceM (render (nest 4 $ vcat $ map pretty $ Cast info env0 t1 t0 : cs))\n                                             (cs',eq') <- markScoped env n q0 (tempGoal t1) (Cast info env0 t1 t0 : cs)\n                                             cs' <- usubst cs'\n                                             return (cs', def{ qbinds = noqual env0 q0, pos = pos0, kwd = kwd0,\n                                                               dbody = bindWits (eq++eq') ++ dbody def, dfx = fx })\n           where t1                     = tFun (dfx def) (prowOf $ pos def) (krowOf $ kwd def) (fromJust $ ann def)\n                 (pos0,kwd0)            = qualDef env dec (pos def) (kwd def) (qualWPar env q0)\n                 sc1                    = TSchema NoLoc q1 t1\n                 mbl                    = findSigLoc n env\n                 msg                    = \"Type incompatibility between signature for and definition of \"++Pretty.print n\n                 info                   = maybe (locinfo def 58) (\\l -> DeclInfo l (loc def) n sc1 msg) mbl\n\nqualDef env dec p k qf | not (inClass env) = (qf p, k)\nqualDef env Static p k qf                  = (qf p, k)\nqualDef env dec PosNIL (KwdPar n t e k) qf = (PosPar n t e (qf PosNIL), k)\nqualDef env dec (PosPar n t e p) k qf      = (PosPar n t e (qf p), k)\n\n\ninitComplement env n as body\n-- | True                                = body\n  | inBuiltin env || null as            = body\n  | otherwise                           = defAltInit : body\n  where defAltInit\n          | baseHasAltInit              = --trace (\"### Connecting altInit chain to \" ++ prstr base) $\n                                          mkInit (sExpr (eCall (eDot (eQVar basename) altInit) [eVar selfKW]))\n          | otherwise                   = --trace (\"### Stopping altInit chain before \" ++ prstr base) $\n                                          mkInit sPass\n        base                            = snd $ head as\n        basename                        = tcname base\n        baseHasAltInit                  = isJust $ findAttr env base altInit\n        mkInit stmt                     = sDef altInit (pospar [(selfKW,tSelf)]) tNone [stmt] fxPure\n\nlockSelf l p k dec                      = tryUnify (Simple l \"Type of first parameter of class method does not unify with Self\") tSelf $ selfType p k dec\n\n--------------------------------------------------------------------------------------------------------------------------\n\ninstance InfEnv Decl where\n    infEnv env d@(Def l n q p k a _ dec' fx ddoc)\n      | nodup (p,k)                     = case findName n env of\n                                             NSig sc dec _ | t@TFun{} <- sctype sc, matchingDec n sc dec dec' -> do\n                                                 --traceM (\"\\n## infEnv (sig) def \" ++ prstr (n, NDef sc dec Nothing))\n                                                 when (inClass env) $ lockSelf l p k dec\n                                                 return ([], [(n, NDef (fxUnwrapSc env sc) dec ddoc)], d{deco = dec})\n                                             NReserved -> do\n                                                 when (inClass env) $ lockSelf l p k dec'\n                                                 t <- tFun (fxUnwrap env fx) (prowOf p) (krowOf k) <$> maybe (newUnivar env) return a\n                                                 let sc = tSchema q (if inClass env then dropSelf t dec' else t)\n                                                 --traceM (\"\\n## infEnv def \" ++ prstr (n, NDef sc dec' Nothing))\n                                                 return ([], [(n, NDef sc dec' ddoc)], d)\n                                             _ ->\n                                                 illegalRedef n\n\n\n    infEnv env d@(Actor _ n q p k b ddoc)\n      | nodup (p,k)                     = case findName n env of\n                                             NReserved -> do\n                                                 te <- infActorEnv env b\n                                                 let prow = prowOf p\n                                                     krow = krowOf k\n                                                 --traceM (\"\\n## infEnv actor \" ++ prstr (n, NAct q prow krow te ddoc))\n                                                 return ([], [(n, NAct q prow krow te ddoc)], d)\n                                             _ ->\n                                                 illegalRedef n\n\n    infEnv env (Class l n q us b ddoc)\n      | not $ null ps                   = notYet (loc n) \"Classes with direct extensions\"\n      | otherwise                       = case findName n env of\n                                             NReserved -> do\n                                                 --traceM (\"\\n## infEnv class \" ++ prstr n)\n                                                 pushFX fxPure tNone\n                                                 te0 <- infProperties env1 as' b\n                                                 (cs,te,b1) <- infEnv env1 b0\n                                                 popFX\n                                                 when (not $ null cs) $ err (loc n) \"Deprecated class syntax\"\n                                                 checkClassAttributesInitialized n l env as' b\n                                                 (nterms,asigs,_) <- checkAttributes [] te' te\n                                                 let (te2,b2) = if notImplBody b then let te1 = unSig asigs in (te++te1, addImpl te1 b1)\n                                                                else if null asigs && initKW `notElem` dom te then relayInit te b1\n                                                                else (te,b1)\n                                                 return ([], [(n, NClass q as' (te0++te2) ddoc)], Class l n q us (props te0 ++ b2) ddoc)\n                                             _ -> illegalRedef n\n      where env1                        = define (exclude (toSigs te') [initKW]) $ reserve (assigned b0) $ tydefineVars (stripQual q') $ setInClass env\n            (as,ps)                     = mro2 env us\n            as'                         = if null as && not (inBuiltin env && n == nValue) then leftpath [cValue] else as\n            te'                         = parentTEnv env as'\n            q'                          = selfQuant (NoQ n) q\n            props te0                   = [ Signature l0 [n] sc Property | (n,NSig sc Property _) <- te0 ]\n            tc                          = TC (NoQ n) (map tVar $ qbound q)\n            b0                          = initComplement env n as' b\n            relayInit te b              = --trace (\"####### Creating relayInit for class \" ++ prstr n) $\n                                          case lookup initKW te' of\n                                            Just ni@(NDef sc _ _) ->\n                                                ((initKW,ni):te, sDecl [Def NoLoc initKW [] pp kp Nothing body NoDec fx Nothing]:b)\n                                              where t  = addSelf (sctype sc) (Just NoDec)\n                                                    pp = pPar pNames $ posrow t\n                                                    kp = kPar attrKW $ kwdrow t\n                                                    fx = effect t\n                                                    body = [sExpr $ Call NoLoc (eDot (eQVar $ tcname $ head us) initKW) (pArg pp) (kArg kp)]\n\n    infEnv env (Protocol l n q us b ddoc)\n                                        = case findName n env of\n                                             NReserved -> do\n                                                 --traceM (\"\\n## infEnv protocol \" ++ prstr n)\n                                                 pushFX fxPure tNone\n                                                 (cs,te,b') <- infEnv env1 b\n                                                 popFX\n                                                 when (not $ null cs) $ err (loc n) \"Deprecated protocol syntax\"\n                                                 (nterms,_,sigs) <- checkAttributes [] te' te\n                                                 let noself = [ n | (n, NSig sc Static _) <- te, tvSelf `notElem` vfree sc ]\n                                                 when (notImplBody b) $ err0 (notImpls b) \"A protocol body cannot be NotImplemented\"\n                                                 when (not $ null nterms) $ err2 (dom nterms) \"Method/attribute lacks signature:\"\n                                                 when (initKW `elem` sigs) $ err2 (filter (==initKW) sigs) \"A protocol cannot define __init__\"\n                                                 when (not $ null noself) $ err2 noself \"A static protocol signature must mention Self\"\n                                                 return ([], [(n, NProto q ps te ddoc)], Protocol l n q us b' ddoc)\n                                             _ -> illegalRedef n\n      where env1                        = define (toSigs te') $ reserve (assigned b) $ tydefineVars (stripQual q') $ setInClass env\n            ps                          = mro1 env us\n            te'                         = parentTEnv env ps\n            q'                          = selfQuant (NoQ n) q\n\n    infEnv env (Extension l q c us b ddoc)\n      | length us == 0                  = err (loc n) \"Extension lacks a protocol\"\n--      | length us > 1                   = notYet (loc n) \"Extensions with multiple protocols\"\n      | not $ null witsearch            = err (loc n) (\"Extension already exists: \" ++ prstr (head witsearch))\n      | otherwise                       = do --traceM (\"\\n## infEnv extension \" ++ prstr (extensionName us c))\n                                             pushFX fxPure tNone\n                                             (cs,te,b1) <- infEnv env1 b\n                                             popFX\n                                             when (not $ null cs) $ err (loc n) \"Deprecated extension syntax\"\n                                             (nterms,asigs,sigs) <- checkAttributes final te' te\n                                             when (not $ null nterms) $ err2 (dom nterms) \"Method/attribute not in listed protocols:\"\n                                             when (not $ null sigs) $ err2 sigs \"Extension with new methods/attributes not supported\"\n                                             when (not (null asigs || notImplBody b)) $ err3 l (dom asigs) \"Protocol method/attribute lacks implementation:\"\n                                             let te1 = unSig $ selfSubst n q asigs\n                                                 te2 = te ++ te1\n                                                 b2 = addImpl te1 b1\n                                             return ([], [(extensionName us c, NExt q c ps te2 [] ddoc)], Extension l q c us b2 ddoc)\n      where TC n ts                     = c\n            env1                        = define (toSigs te') $ reserve (assigned b) $ tydefineVars (stripQual q') $ setInClass env\n            witsearch                   = findWitness env (tCon c) u\n            u                           = head us\n            ps                          = selfSubst n q $ mro1 env us -- TODO: check that ps doesn't contradict any previous extension mro for c\n            final                       = concat [ conAttrs env (tcname p) | (_,p) <- tail ps, hasWitness env (tCon c) p ]\n            te'                         = parentTEnv env ps\n            q'                          = selfQuant n q\n\n--------------------------------------------------------------------------------------------------------------------------\n\ncheckAttributes final te' te\n  | not $ null dupsigs                  = err2 dupsigs \"Duplicate signatures for\"\n  | not $ null props                    = err2 props \"Property attributes cannot have class-level definitions:\"\n  | not $ null nodef                    = err2 nodef \"Methods finalized in a previous extension cannot be overridden:\"\n  | otherwise                           = return (nterms, abssigs, dom sigs)\n  where (sigs,terms)                    = sigTerms te\n        (sigs',terms')                  = sigTerms te'\n        (allsigs,allterms)              = (sigs ++ sigs', terms ++ terms')\n        dupsigs                         = duplicates (dom sigs)\n        nterms                          = exclude terms (dom allsigs)\n        abssigs                         = allsigs `exclude` (dom allterms ++ final)\n        props                           = dom terms `intersect` dom (propSigs allsigs)\n        nodef                           = dom terms `intersect` final\n\naddImpl [] ss                           = ss\naddImpl asigs (s : ss)\n  | isNotImpl s                         = fromTEnv (unSig asigs) ++ s : ss\n  | otherwise                           = s : addImpl asigs ss\n\ntoSigs te                               = map makeSig te\n  where makeSig (n, NDef sc dec doc)    = (n, NSig sc dec doc)\n        makeSig (n, NVar t)             = (n, NSig (monotype t) Static Nothing)\n        makeSig (n, i)                  = (n,i)\n\n\n--------------------------------------------------------------------------------------------------------------------------\n\ncheckClassAttributesInitialized         :: Name -> SrcLoc -> Env -> [WTCon] -> Suite -> TypeM ()\ncheckClassAttributesInitialized className classLoc env ancestors b\n                                        = do -- Only check if the class defines its own __init__. If it doesn't, it uses the parent's\n                                             -- __init__ which already initialized everything (and we check the parent separately)\n                                             case findInitMethod b of\n                                                 Nothing -> return ()  -- No __init__, uses parent's\n                                                 Just (self, initBody, initLoc) ->\n                                                     -- Check if __init__ is implemented in C (body is NotImplemented)\n                                                     if hasNotImpl initBody\n                                                       then return ()  -- Assume all is OK - we can't analyze C implementation\n                                                       else do\n                                                         let inherited = concatMap (getPropertiesFromClass env . tcname . snd) ancestors\n                                                             explicit  = concat [ ns | Signature _ ns sc dec <- b, isProp dec sc ]\n                                                             inferred  = inferClassAttributes self initBody\n                                                             expected  = nub $ inherited ++ explicit ++ inferred\n                                                             initialized = scanSelfAssigns env self b initBody\n                                                             -- Track which parent __init__ methods are called\n                                                             calledParentInits = getCalledParentInits env initBody\n                                                             -- Get attributes initialized by called parent __init__ methods\n                                                             parentInitialized = nub $ concatMap (getInitializedByParent env) calledParentInits\n                                                             uninitialized = expected \\\\ (initialized ++ parentInitialized)\n\n                                                         forM_ uninitialized $ \\prop ->\n                                                             let parentInfo = findAttributeParent prop\n                                                                 isInferred = prop `elem` inferred && prop `notElem` explicit && prop `notElem` inherited\n                                                             in Control.Exception.throw $ UninitializedAttribute (loc prop) prop isInferred initLoc classLoc className parentInfo\n  where getPropertiesFromClass env qn   = let (_,_,te) = findConName qn env\n                                          in [ n | (n, NSig _ Property _) <- te ]\n\n        -- Helper to look up class location in environment\n        getClassLoc env qname           = case findClass (activeNames env) of\n                                            Just l  -> l\n                                            Nothing -> maybe NoLoc id (findClass (closedNames env))\n          where findClass ((n, NClass{}):te)\n                  | n == noq qname      = Just (loc n)\n                findClass (_:te)        = findClass te\n                findClass []            = Nothing\n\n        -- Find which parent class (if any) defines the given attribute\n        findAttributeParent attrName    = case [ n | Signature _ ns _ _ <- b, n <- ns, n == attrName ] of\n                                              (_:_) -> Nothing  -- Defined in current class\n                                              []    -> -- Look for it in ancestors\n                                                     case mapMaybe (findInAncestor attrName) ancestors of\n                                                         (result:_) -> Just result\n                                                         []         -> Nothing\n\n        -- Check if a specific ancestor defines the attribute\n        findInAncestor attrName (_, anc)= let ancName = tcname anc\n                                          in if attrName `elem` getPropertiesFromClass env ancName\n                                             then Just (noq ancName, getClassLoc env ancName)\n                                             else Nothing\n\n\nwellformed                              :: (WellFormed a) => Env -> a -> TypeM ()\nwellformed env x                        = do _ <- solveAll env [] cs\n                                             return ()\n  where cs                              = wf env x\n\nwellformedProtos                        :: Env -> [PCon] -> TypeM (Constraints, [(QName,[Expr])])\nwellformedProtos env ps                 = do (css0, css1) <- unzip <$> mapM (wfProto env) ps\n                                             _ <- solveAll env [] (concat css0)\n                                             return (concat css1, [ (tcname p, protoWitsOf cs) | (p,cs) <- ps `zip` css1 ])\n\n\n--------------------------------------------------------------------------------------------------------------------------\n\nclass Check a where\n    checkEnv                            :: Env -> a -> TypeM (Constraints,a)\n    checkEnv'                           :: Env -> a -> TypeM (Constraints,[a])\n    checkEnv env x                      = undefined\n    checkEnv' env x                     = do (cs,x') <- checkEnv env x\n                                             return (cs, [x'])\n\ninstance (Check a) => Check [a] where\n    checkEnv env []                     = return ([], [])\n    checkEnv env (d:ds)                 = do (cs1,d') <- checkEnv' env d\n                                             (cs2,ds') <- checkEnv env ds\n                                             return (cs1++cs2, d'++ds')\n\n------------------\n\ninfActorEnv env ss                      = do dsigs <- mapM mkNDef dvars                                 -- exposed defs without sigs\n                                             bsigs <- mapM mkNVar pvars                                 -- exposed assigns without sigs\n                                             return (abssigs ++ unSig concsigs ++ dsigs ++ bsigs)       -- abstract sigs ++ exposed sigs + the above\n  where sigs                            = [ (n, NSig sc dec Nothing) | Signature _ ns sc dec <- ss, n <- ns, not $ isHidden n ]\n        (concsigs, abssigs)             = partition ((`elem`(dvars++pvars)) . fst) sigs\n        dvars                           = notHidden $ methods ss \\\\ dom sigs\n        mkNDef n                        = do t <- newUnivar env\n                                             return (n, NDef (monotype $ t) NoDec Nothing)\n        svars                           = statevars ss\n        pvars                           = pvarsF ss \\\\ dom (sigs) \\\\ dvars\n        pvarsF ss                       = nub $ concat $ map pvs ss\n          where pvs (Assign _ pats _)   = notHidden $ bound pats \\\\ svars   -- svars only excluded until we move stateful actor cmds to __init__\n                pvs (If _ bs els)       = foldr intersect (pvarsF els) [ pvarsF ss | Branch _ ss <- bs ]\n                pvs _                   = []\n        mkNVar n                        = do t <- newUnivar env\n                                             return (n, NVar t)\n\nmatchActorAssumption env n0 p k te      = do --traceM (\"## matchActorAssumption \" ++ prstrs te)\n                                             (css,eqs) <- unzip <$> mapM check1 te0\n                                             let cs = [Cast (locinfo p 60) env (tTuple p0 k0) (tTuple (prowOf p) (krowOf k)),\n                                                       Seal (locinfo p 112) env p0, Seal (locinfo k 113) env k0]\n                                             (cs,eq) <- oldSimplify env obs (cs ++ concat css)\n                                             return (cs, eq ++ concat eqs)\n  where NAct q p0 k0 te0 _              = findName n0 env\n        ns                              = dom te0\n        obs                             = te0 ++ te\n        te1                             = nTerms $ te `restrict` ns\n        check1 (n, NSig _ _ _)          = return ([], [])\n        check1 (n, NVar t0)             = do --traceM (\"## matchActorAssumption for attribute \" ++ prstr n)\n                                             return ([Cast (locinfo n 62) env t t0, Seal (locinfo n 114) env t0],[])\n          where Just (NVar t)           = lookup n te1\n        check1 (n, NDef sc0 _ _)        = do (cs0,_,t) <- instantiate env sc\n                                             (c0,t') <- wrap env t\n                                             let c1 = Cast (locinfo n 63) env t' (sctype sc0)\n                                                 cs1 = map (Seal (locinfo n 115) env) (leaves sc0)\n                                                 q0 = scbind sc0\n                                             --traceM (\"## matchActorAssumption for method \" ++ prstr n ++ \": \" ++ prstr c1)\n                                             (cs2,eq) <- markScoped env n0 q0 obs (c0:c1:cs0++cs1)\n                                             return (cs2, eq)\n          where Just (NDef sc _ _)      = lookup n te1\n        check1 (n, i)                   = return ([], [])\n\n\n-- Find __init__ method in class body, return self parameter, body and location\nfindInitMethod :: Suite -> Maybe (Name, Suite, SrcLoc)\nfindInitMethod b                        = listToMaybe [ (x, dbody d, loc d) | Decl _ ds <- b, d <- ds, dname d == initKW, Just x <- [selfPar d] ]\n\n-- Scan __init__ for \"self.x = ...\" to find which attributes are definitely\n-- assigned before any references to `self` escape externally. We allow most\n-- statements in the constructor as long as `self` does not escape although\n-- there are a few statements that will also be considered the end of the\n-- constructor (this isn't well documented). We are handling if/elif/else as\n-- well as some variations of exception handling and raising. Loops are allowed\n-- but any assignments in a loop does not count to the set of initialized\n-- attributes since we cannot statically determine if the loop executes. The\n-- loop is scanned to ensure `self` does not escape.\nscanSelfAssigns :: Env -> Name -> Suite -> Suite -> [Name]\nscanSelfAssigns env self classBody stmts = scanSuite [] stmts\n  where\n    -- Check if a method in the class has NotImplemented body\n    isNotImplMethod :: Name -> Bool\n    isNotImplMethod methodName          = case [ d | Decl _ ds <- classBody, d@Def{dname=n} <- ds, n == methodName ] of\n                                                (d:_) -> hasNotImpl (dbody d)\n                                                []    -> False\n    -- Check if a statement list ends with an early exit (only raise - not return!)\n    -- Return would give back an uninitialized object, so it doesn't excuse initialization\n    branchExitsEarly :: Suite -> Bool\n    branchExitsEarly []                 = False\n    branchExitsEarly stmts              = case last stmts of\n                                              Raise _ _ -> True  -- Only raise truly prevents object creation\n                                              -- Recursively check nested if/else\n                                              If _ branches elseBranch ->\n                                                  all (\\(Branch _ body) -> branchExitsEarly body) branches &&\n                                                  (not (null elseBranch) && branchExitsEarly elseBranch)\n                                              -- Recursively check try/except\n                                              Try _ tryBody handlers elseBranch finallyBlock ->\n                                                  -- If finally block raises, that's an early exit\n                                                  if not (null finallyBlock) && branchExitsEarly finallyBlock\n                                                    then True\n                                                    else -- Otherwise, check if all normal paths exit early\n                                                         branchExitsEarly tryBody &&\n                                                         all (\\(Handler _ hbody) -> branchExitsEarly hbody) handlers &&\n                                                         (null elseBranch || branchExitsEarly elseBranch)\n                                              _ -> False\n    scanSuite seen []                   = []\n    -- Handle assignments\n    scanSuite seen (MutAssign _ (Dot _ (Var _ qn) n) e : rest)\n        | noq qn == self                = if checkNoSelfReference self seen e\n                                            then n : scanSuite (n:seen) rest\n                                            else []  -- Stop at self reference\n    scanSuite seen (MutAssign _ _ _ : rest)\n                                        =     -- Continue: local assignment is OK\n                                          scanSuite seen rest\n    scanSuite seen (Assign _ _ e : rest)\n                                        =     -- Continue past local assignments, unless RHS contains self reference\n                                          if checkNoSelfReference self seen e\n                                            then scanSuite seen rest  -- Continue past assignment\n                                            else []  -- Stop at self reference\n    scanSuite seen (AugAssign _ (Dot _ (Var _ qn) n) _ _ : rest)\n        | noq qn == self && n `elem` seen  -- OK: augmenting already-initialized attribute\n                                        = scanSuite seen rest\n        | noq qn == self                = []  -- STOP: can't augment uninitialized attribute\n    scanSuite seen (AugAssign _ _ _ _ : rest)\n                                        =     -- Continue: local augmented assignment is OK\n                                          scanSuite seen rest\n    -- Handle if/elif/else statements. Count assignments that happen in all\n    -- branches as unconditional. Note how we must have an else branch in order\n    -- to consider it exhaustive. Each branch either:\n    --   1. Completes normally and returns an object (must have initialized attributes), or\n    --   2. Exits early via raise (never returns an object, so doesn't constrain initialization)\n    --\n    -- We need the intersection of assignments from all branches. Branches that exit early\n    -- are \"compatible\" with any assignment set (they contribute the universal set to the\n    -- intersection), so in practice we only intersect the branches that complete normally.\n    --\n    -- Example: if cond:          if cond:          if cond:\n    --            self.x = 1        self.x = 1        raise Error()\n    --          else:             else:             else:\n    --            self.x = 2        raise Error()     self.x = 1\n    --          Result: {x}       Result: {x}       Result: {x}\n    --\n    -- Without an else branch, the if/elif is non-exhaustive - we might skip all branches,\n    -- so we can't guarantee any assignments. (Note: We don't attempt to analyze whether\n    -- the predicates are exhaustive through logical analysis - that's undecidable in general\n    -- and NP-complete even for boolean satisfiability. The else branch is our simple,\n    -- syntactic criterion for exhaustiveness.)\n    scanSuite seen (If _ branches elseBranch : rest)\n                                        =     -- Scan all branches for assignments\n                                          let branchResults = map (\\(Branch _ body) ->\n                                                  (scanSuite seen body, branchExitsEarly body)) branches\n                                              elseResult = (scanSuite seen elseBranch, branchExitsEarly elseBranch)\n\n                                              -- Branches that complete normally must be considered\n                                              normalBranches = [assigns | (assigns, exits) <- branchResults, not exits]\n                                              -- Else branch if it completes normally\n                                              normalElse = case elseResult of\n                                                             (assigns, False) -> [assigns]  -- Else completes normally\n                                                             (_, True) -> []  -- Else exits early\n\n                                              -- All normal branches that do not exit early\n                                              allNormalBranches = normalBranches ++ normalElse\n\n                                              -- if we have else, it's exhaustive, otherwise it's not\n                                              newAssigns = case not (null elseBranch) of\n                                                  False -> []  -- No else: not exhaustive, nothing counts\n                                                  True -> case allNormalBranches of\n                                                            [] -> []  -- All branches exit: no object returned\n                                                            branches -> foldl1 intersect branches  -- Require intersection\n                                          in newAssigns ++ scanSuite (newAssigns ++ seen) rest\n    -- Only continue past simple statements\n    scanSuite seen (Pass _ : rest)      = scanSuite seen rest\n    -- Parent init calls are special - they initialize parent attributes\n    scanSuite seen (Expr _ (Call _ (Dot _ (Var _ c) n) _ _) : rest)\n        | isClass env c, n == initKW    = scanSuite seen rest\n    -- Allow calling self methods that have NotImplemented body (C implementations)\n    scanSuite seen (Expr _ (Call _ (Dot _ (Var _ (NoQ x)) methodName) _ _) : rest)\n        | x == self && isNotImplMethod methodName\n                                        = scanSuite seen rest  -- Continue: NotImplemented method on self\n    -- Stop at other self method calls\n    scanSuite seen (Expr _ (Call _ (Dot _ _ _) _ _) : _)\n                                        = []  -- STOP: method call\n    -- Allow expressions without references to `self`\n    scanSuite seen (Expr _ e : rest)\n        | checkNoSelfReference self seen e\n                                        = scanSuite seen rest\n    -- Handle try/except/else/finally\n    --\n    -- The possible execution paths are:\n    --   1. try → else (no exception raised)\n    --   2. handler (exception raised and caught)\n    --   3. exception propagates (not caught - early exit, no object returned)\n    -- Finally always executes regardless of path taken.\n    --\n    -- Since we don't know WHERE in try an exception might occur, we can't count ANY\n    -- assignments from try when considering the exception path. But if try completes\n    -- normally (no exception), we know ALL its assignments happened.\n    --\n    -- Note: else is a CONTINUATION of try (only runs if try completes without exception),\n    -- not an alternative branch like in if/else.\n    --\n    -- Example: try:                  try:                try:\n    --            self.x = 1             self.x = 1           raise Error()\n    --            self.y = 2             raise Error()      except:\n    --          except:               except:                self.x = 1\n    --            self.x = 1             self.x = 1         else:\n    --          else:                 else:                  self.y = 2\n    --            self.z = 3             self.z = 3\n    --\n    --          Normal paths:         Normal paths:       Normal paths:\n    --          - try+else: {x,y,z}   - except: {x}       - except: {x}\n    --          - except: {x}         (try+else exits)    (try exits, else never runs)\n    --          Result: {x}           Result: {x}         Result: {x}\n    --\n    -- If try always exits (raises), we only consider handlers. If a handler exits,\n    -- it doesn't contribute to the intersection (like if/else branches that exit).\n    -- Finally assignments always count since finally always executes.\n    scanSuite seen (Try _ tryBody handlers elseBranch finallyBlock : rest)\n                                        = let -- Finally always executes\n                                              finallyAssigns = scanSuite seen finallyBlock\n                                              seenAfterFinally = finallyAssigns ++ seen\n\n                                              -- Scan all code paths\n                                              tryAssigns = scanSuite seenAfterFinally tryBody\n                                              elseAssigns = scanSuite seenAfterFinally elseBranch\n                                              handlerAssigns = map (\\(Handler _ hbody) ->\n                                                  scanSuite seenAfterFinally hbody) handlers\n\n                                              -- Check which paths exit early\n                                              tryExits = branchExitsEarly tryBody\n                                              elseExits = branchExitsEarly elseBranch\n                                              handlerExits = map (\\(Handler _ hbody) ->\n                                                  branchExitsEarly hbody) handlers\n\n                                              -- Build list of paths that complete normally:\n                                              -- 1. try+else path (if try doesn't exit)\n                                              -- 2. each handler that doesn't exit\n                                              tryElsePath = if not tryExits\n                                                           then [tryAssigns ++ if elseExits then [] else elseAssigns]\n                                                           else []\n                                              handlerPaths = [assigns | (assigns, exits) <- zip handlerAssigns handlerExits, not exits]\n                                              normalPaths = tryElsePath ++ handlerPaths\n\n                                              -- Intersect all normal paths (or empty if all exit)\n                                              guaranteedFromPaths = case normalPaths of\n                                                  [] -> []\n                                                  paths -> foldl1 intersect paths\n\n                                          in finallyAssigns ++ guaranteedFromPaths ++\n                                             scanSuite (finallyAssigns ++ guaranteedFromPaths ++ seen) rest\n    -- Handle loops - skip over them if they don't leak self references\n    scanSuite seen (While _ cond body elseBranch : rest)\n        | checkNoSelfReference self seen cond &&\n          checkNoSelfReferenceInSuite self seen body &&\n          checkNoSelfReferenceInSuite self seen elseBranch\n                                        = scanSuite seen rest  -- Continue past safe loop\n        | otherwise                     = []  -- STOP: loop references self\n    scanSuite seen (For _ pat expr body elseBranch : rest)\n        | checkNoSelfReference self seen expr &&\n          checkNoSelfReferenceInSuite self seen body &&\n          checkNoSelfReferenceInSuite self seen elseBranch\n                                        = scanSuite seen rest  -- Continue past safe loop\n        | otherwise                     = []  -- STOP: loop references self\n    scanSuite _ (With _ _ _ : _)        = []  -- STOP: with statements not supported\n    -- Handle assert like if & raise - continue if test doesn't reference self\n    scanSuite seen (Assert _ test msg : rest)\n        | checkNoSelfReference self seen test &&\n          maybe True (checkNoSelfReference self seen) msg\n                                        = scanSuite seen rest  -- Continue: assert doesn't leak self\n        | otherwise                     = []  -- STOP: assert references self\n    scanSuite _ (Return _ _ : _)        = []  -- STOP: early exit\n    scanSuite _ (Raise _ _ : _)         = []  -- STOP: raises exception\n    -- Skip past break and continue - they are loop control flow, and we skip loops anyway\n    scanSuite seen (Break _ : rest)     = scanSuite seen rest\n    scanSuite seen (Continue _ : rest)  = scanSuite seen rest\n    scanSuite seen (Delete _ _ : rest)  = scanSuite seen rest\n    scanSuite _ (After _ _ _ : _)       = []  -- STOP: after statement (async)\n    -- Check nested function declarations for self references\n    scanSuite seen (Decl _ decls : rest)\n        | all (checkDeclNoSelfReference self seen) decls\n                                        = scanSuite seen rest  -- Continue: nested functions don't capture self\n        | otherwise                     = []  -- STOP: nested function captures self\n    scanSuite _ (_ : _)                 = []  -- STOP: unhandled statement type (safe default)\n\n\n-- Check if a suite (list of statements) contains disallowed references to self\ncheckNoSelfReferenceInSuite :: Name -> [Name] -> Suite -> Bool\ncheckNoSelfReferenceInSuite self seen stmts = all checkStmt stmts\n  where\n    checkStmt (Expr _ e)                = checkNoSelfReference self seen e\n    checkStmt (Assign _ _ e)            = checkNoSelfReference self seen e\n    checkStmt (MutAssign _ target e)    = checkNoSelfReference self seen e && checkNoSelfReference self seen target\n    checkStmt (AugAssign _ target _ e)  = checkNoSelfReference self seen e && checkNoSelfReference self seen target\n    checkStmt (Return _ Nothing)        = True\n    checkStmt (Return _ (Just e))       = checkNoSelfReference self seen e\n    checkStmt (If _ branches elseBranch) = all (\\(Branch cond body) -> checkNoSelfReference self seen cond && checkNoSelfReferenceInSuite self seen body) branches &&\n                                           checkNoSelfReferenceInSuite self seen elseBranch\n    checkStmt (While _ cond body elseBranch) = checkNoSelfReference self seen cond &&\n                                                checkNoSelfReferenceInSuite self seen body &&\n                                                checkNoSelfReferenceInSuite self seen elseBranch\n    checkStmt (For _ _ expr body elseBranch) = checkNoSelfReference self seen expr &&\n                                                checkNoSelfReferenceInSuite self seen body &&\n                                                checkNoSelfReferenceInSuite self seen elseBranch\n    checkStmt (Try _ tryBody handlers elseBranch finallyBlock) =\n                                           checkNoSelfReferenceInSuite self seen tryBody &&\n                                           all (\\(Handler _ hbody) -> checkNoSelfReferenceInSuite self seen hbody) handlers &&\n                                           checkNoSelfReferenceInSuite self seen elseBranch &&\n                                           checkNoSelfReferenceInSuite self seen finallyBlock\n    checkStmt _                          = True  -- Conservative: allow other statements\n\n-- Check if an expression contains disallowed references to self\n-- We allow self.x since it can be seen as just a lone variable, which is valid\n-- as long as it has been previously assigned, but we cannot pass a reference to\n-- the whole `self`\ncheckNoSelfReference :: Name -> [Name] -> Expr -> Bool\ncheckNoSelfReference self seen expr = checkExpr expr\n  where\n    -- Check if an expression is allowed\n    checkExpr :: Expr -> Bool\n    checkExpr (Await _ _)               = False  -- Await is not allowed\n    checkExpr (Var _ qn) | noq qn == self\n                                        = False  -- Direct reference to self not allowed\n    checkExpr e@(Dot _ (Var _ qn) attr)\n        | noq qn == self                = attr `elem` seen  -- self.attr is OK only if attr is initialized\n    -- For other expressions, recursively check subexpressions\n    checkExpr (Call _ func args kwds)   = checkExpr func && checkPosArgs args && checkKwdArgs kwds\n    checkExpr (BinOp _ e1 _ e2)         = checkExpr e1 && checkExpr e2\n    checkExpr (CompOp _ e1 ops)         = checkExpr e1 && all checkOpArg ops\n      where checkOpArg (OpArg _ e)      = checkExpr e\n    checkExpr (UnOp _ _ e)              = checkExpr e\n    checkExpr (List _ elems)            = all checkElem elems\n    checkExpr (Tuple _ args kwds)       = checkPosArgs args && checkKwdArgs kwds\n    checkExpr (Paren _ e)               = checkExpr e\n    checkExpr (Cond _ cond thenE elseE) = checkExpr cond && checkExpr thenE && checkExpr elseE\n    checkExpr (Index _ base idx)        = checkExpr base && checkExpr idx\n    checkExpr (Slice _ base (Sliz _ start stop step))\n                                        = checkExpr base &&\n                                          maybe True checkExpr start &&\n                                          maybe True checkExpr stop &&\n                                          maybe True checkExpr step\n    checkExpr (Dict _ items)            = all checkItem items\n    checkExpr (Set _ elems)             = all checkElem elems\n    checkExpr (ListComp _ elem comp)    = checkElem elem && checkComp comp\n    checkExpr (DictComp _ (Assoc k v) comp)\n                                        = checkExpr k && checkExpr v && checkComp comp\n    checkExpr (SetComp _ elem comp)     = checkElem elem && checkComp comp\n    checkExpr (Lambda _ _ _ body _)     = checkExpr body\n    checkExpr (Yield _ e)               = maybe True checkExpr e\n    checkExpr (YieldFrom _ e)           = checkExpr e\n    checkExpr (Dot _ e _)               = checkExpr e  -- Check base expression\n    checkExpr (Int _ _ _)               = True  -- Integer literals are OK\n    checkExpr (Float _ _ _)             = True  -- Float literals are OK\n    checkExpr (Strings _ _)             = True  -- String literals are OK\n    checkExpr (BStrings _ _)            = True  -- Byte string literals are OK\n    checkExpr (Bool _ _)                = True  -- Boolean literals are OK\n    checkExpr None{}                    = True  -- None is OK\n    checkExpr _                         = True  -- Other expressions are OK (for now)\n\n    checkPosArgs (PosArg e rest)        = checkExpr e && checkPosArgs rest\n    checkPosArgs (PosStar e)            = checkExpr e\n    checkPosArgs PosNil                 = True\n\n    checkKwdArgs (KwdArg _ e rest)      = checkExpr e && checkKwdArgs rest\n    checkKwdArgs (KwdStar e)            = checkExpr e\n    checkKwdArgs KwdNil                 = True\n\n    checkElem (Elem e)                  = checkExpr e\n    checkElem (Star e)                  = checkExpr e\n\n    checkItem (Assoc k v)               = checkExpr k && checkExpr v\n\n    checkComp (CompFor _ _ iter c)      = checkExpr iter && checkComp c\n    checkComp (CompIf _ test c)         = checkExpr test && checkComp c\n    checkComp NoComp                    = True\n\n\n-- Check if a declaration (nested function) references self\n-- We conservatively stop if ANY nested function references self at all,\n-- even if it only accesses already-initialized attributes\ncheckDeclNoSelfReference :: Name -> [Name] -> Decl -> Bool\ncheckDeclNoSelfReference self seen decl = case decl of\n    Def _ _ _ _ _ _ body _ _ _ -> checkNoSelfReferenceInSuite self [] body  -- Pass empty list to disallow ANY self reference\n    Actor _ _ _ _ _ body _     -> checkNoSelfReferenceInSuite self [] body  -- Pass empty list to disallow ANY self reference\n    Class _ _ _ _ body _       -> True  -- Nested classes don't capture self by default\n    Protocol _ _ _ _ body _    -> True  -- Nested protocols don't capture self\n    Extension _ _ _ _ body _   -> True  -- Extensions don't capture self\n\n-- Infer all class attributes by scanning the entire __init__ method for any\n-- self.x assignments, regardless of control flow. This is used for attribute\n-- discovery/inference, not for initialization checking.\ninferClassAttributes :: Name -> Suite -> [Name]\ninferClassAttributes self stmts = nub $ scanAll stmts\n  where\n    scanAll []                          = []\n    -- Direct assignment to self.attribute\n    scanAll (MutAssign _ (Dot _ (Var _ qn) n) _ : rest)\n        | noq qn == self                = n : scanAll rest\n    -- Scan inside control structures\n    scanAll (If _ branches elseBranch : rest)\n                                        = concatMap (\\(Branch _ body) -> scanAll body) branches\n                                          ++ scanAll elseBranch\n                                          ++ scanAll rest\n    scanAll (While _ _ body elseBranch : rest)\n                                        = scanAll body ++ scanAll elseBranch ++ scanAll rest\n    scanAll (For _ _ _ body elseBranch : rest)\n                                        = scanAll body ++ scanAll elseBranch ++ scanAll rest\n    scanAll (Try _ tryBody handlers elseBranch finallyBlock : rest)\n                                        = scanAll tryBody ++\n                                          concatMap (\\(Handler _ hbody) -> scanAll hbody) handlers ++\n                                          scanAll elseBranch ++\n                                          scanAll finallyBlock ++\n                                          scanAll rest\n    -- TODO: uh, do what with \"with\"??\n    scanAll (With _ witems body : rest) = scanAll body ++ scanAll rest\n    scanAll (After _ _ _ : rest)        = scanAll rest  -- After has expressions, not suite\n    -- Skip declarations - we don't scan nested function bodies\n    scanAll (Decl _ _ : rest)           = scanAll rest\n    -- Continue past other statements\n    scanAll (_ : rest)                  = scanAll rest\n\n-- Get all parent classes whose __init__ methods are called\ngetCalledParentInits :: Env -> Suite -> [QName]\ngetCalledParentInits _ []               = []\ngetCalledParentInits env (Expr _ (Call _ (Dot _ (Var _ c) n) _ _) : rest)\n    | isClass env c, n == initKW        = c : getCalledParentInits env rest\ngetCalledParentInits env (_ : rest)     = getCalledParentInits env rest\n\n-- Get attributes that would be initialized by calling a parent's __init__\n-- This assumes the parent's __init__ properly initializes all attributes it's\n-- responsible for - we can rely on this since the parent's __init__ in turn\n-- will be checked\ngetInitializedByParent :: Env -> QName -> [Name]\ngetInitializedByParent env qn           = -- When calling ParentClass.__init__(self), we assume it initializes:\n                                          -- 1. All attributes declared in ParentClass\n                                          -- 2. All attributes ParentClass inherited (since it should call its parent's __init__)\n                                          let (_,ancestors,te) = findConName qn env\n                                              inherited = concatMap (getPropertiesFromClass env . tcname . snd) ancestors\n                                              declared = [ n | (n, NSig _ Property _) <- te ]\n                                          in nub $ inherited ++ declared\n  where getPropertiesFromClass env qn   = let (_,_,te) = findConName qn env\n                                          in [ n | (n, NSig _ Property _) <- te ]\n\n\n\ninfProperties env as b\n  | Just (self,ss) <- inits             = forM newProps $ \\n -> do\n                                             t <- newUnivarOfKind KType env\n                                             return (n, NSig (monotype t) Property Nothing)\n  | otherwise                           = return []\n  where inherited                       = concat $ map (conAttrs env . tcname . snd) as\n        explicit                        = concat [ ns | Signature _ ns sc dec <- b, isProp dec sc ]\n        inits                           = case findInitMethod b of\n                                              Just (self, body, _) -> Just (self, body)\n                                              Nothing -> Nothing\n        assigned                        = maybe [] (\\(self,ss) -> inferClassAttributes self ss) inits\n        newProps                        = assigned \\\\ (inherited ++ explicit)\n\n\ninfDefBody env n (PosPar x _ _ _) k b\n  | inClass env && n == initKW          = infInitEnv (setInDef env) x b\ninfDefBody env n p (KwdPar x _ _ _) b\n  | inClass env && n == initKW          = infInitEnv (setInDef env) x b\ninfDefBody env _ _ _ b                  = infSuiteEnv (setInDef env) b\n\ninfInitEnv env self (MutAssign l (Dot l' e1@(Var _ (NoQ x)) n) e2 : b)\n  | x == self                           = do (cs1,t1,e1') <- infer env e1\n                                             t2 <- newUnivar env\n                                             (cs2,e2') <- inferSub env t2 e2\n                                             (cs3,te,b') <- infInitEnv env self b\n                                             return (Mut (locinfo l 64) env t1 n t2 :\n                                                     cs1++cs2++cs3, te, MutAssign l (Dot l' e1' n) e2' : b')\ninfInitEnv env self (Expr l e : b)\n  | Call{fun=Dot _ (Var _ c) n} <- e,\n    isClass env c, n == initKW          = do (cs1,_,e') <- infer env e\n                                             (cs2,te,b') <- infInitEnv env self b\n                                             return (cs1++cs2, te, Expr l e' : b')\ninfInitEnv env self b                   = infSuiteEnv env b\n\nabstractDefs env q b                    = qsigs ++ map absDef b\n  where qsigs                           = [ Signature NoLoc [n] (monotype $ proto2type (tVar v) p) Property | (v,p) <- quals env q, let n = tvarWit v p ]\n        absDef (Decl l ds)              = Decl l (map absDef' ds)\n        absDef (If l bs els)            = If l [ Branch e (map absDef ss) | Branch e ss <- bs ] (map absDef els)\n        absDef stmt                     = stmt\n        absDef' d@Def{}\n          | deco d == Static            = d{ pos = pos1 }\n          | dname d == initKW           = d{ pos = pos1, dbody = qcopies ++ dbody d }\n          | otherwise                   = d{ dbody = bindWits qcopies' ++ dbody d }\n          where nSelf                   = case pos d of PosPar nSelf _ _ _ -> nSelf\n                pos1                    = case pos d of\n                                            PosPar nSelf t e p | deco d /= Static ->\n                                                PosPar nSelf t e $ qualWPar env q p\n                                            p -> qualWPar env q p\n                qcopies                 = [ MutAssign NoLoc (eDot (eVar nSelf) n) (eVar n) | (v,p) <- quals env q, let n = tvarWit v p ]\n                qcopies'                = [ mkEqn env n (proto2type (tVar v) p) (eDot (eVar nSelf) n) | (v,p) <- quals env q, let n = tvarWit v p ]\n\n\ninstance Check Decl where\n    checkEnv env (Def l n q p k a b dec fx ddoc)\n                                        = do --traceM (\"## checkEnv def \" ++ prstr n ++ \" FX \" ++ prstr fx')\n                                             t <- maybe (newUnivar env) return a\n                                             pushFX fx' t\n                                             st <- newUnivar env\n                                             wellformed env1 q\n                                             wellformed env1 a\n                                             when (inClass env) $\n                                                 tryUnify (Simple l \"Type of first parameter of class method does not unify with Self\") tSelf $ selfType p k dec\n                                             (csp,te0,p') <- infEnv env1 p\n                                             (csk,te1,k') <- infEnv (define te0 env1) k\n                                             (csb,_,b') <- infDefBody (define te1 (define te0 env1)) n p' k' b\n                                             popFX\n                                             let cst = if fallsthru b then [Cast (locinfo l 65) env1 tNone t] else []\n                                                 t1 = tFun fx' (prowOf p') (krowOf k') t\n                                             (cs0,eq1) <- oldSimplify env1 (tempGoal t1) (csp++csk++csb++cst)\n                                             -- At this point, n has the type given by its def annotations.\n                                             -- Now check that this type is no less general than its recursion assumption in env.\n                                             let body = bindWits eq1 ++ defaultsP p' ++ defaultsK k' ++ b'\n                                             (cs1,def) <- matchDefAssumption env cs0 (Def l n q p' k' (Just t) body dec fx' ddoc)\n                                             return (cs1, def{ pos = noDefaultsP (pos def), kwd = noDefaultsK (kwd def) })\n      where env1                        = reserve (bound (p,k) ++ assigned b \\\\ stateScope env) $ tydefineVars q env\n            fx'                         = fxUnwrap env fx\n\n    checkEnv env (Actor l n q p k b ddoc)\n                                        = do --traceM (\"## checkEnv actor \" ++ prstr n)\n                                             pushFX fxProc tNone\n                                             wellformed env1 q\n                                             (csp,te1,p') <- infEnv env1 p\n                                             (csk,te2,k') <- infEnv (define te1 env1) k\n                                             (csb,te,b') <- infSuiteEnv (define te2 $ define te1 env1) b\n                                             -- At this point, each name defined in b has the type given by its annotations\n                                             -- and possible type signatures. Now check that these types are no less general\n                                             -- than the recursion assumption on actor n itself (which is distinct from any\n                                             -- direct assumptions on its methods because actor interfaces are sealed).\n                                             (cs0,eq0) <- matchActorAssumption env1 n p' k' te\n                                             popFX\n                                             (cs1,eq1) <- markScoped env n q te (csp++csk++csb++cs0)\n                                             let body = bindWits (eq1++eq0) ++ defaultsP p' ++ defaultsK k' ++ b'\n                                                 act = Actor l n (noqual env q) (qualWPar env q p') k' body ddoc\n                                             return (cs1, act{ pos = noDefaultsP (pos act), kwd = noDefaultsK (kwd act) })\n      where env1                        = reserve (bound (p,k) ++ assigned b) $ setInAct $\n                                          define [(selfKW, NVar (tCon tc))] $ tydefineVars q env\n            tc                          = TC (NoQ n) (map tVar $ qbound q)\n\n    checkEnv' env (Class l n q us b ddoc)\n                                        = do --traceM (\"## checkEnv class \" ++ prstr n)\n                                             pushFX fxPure tNone\n                                             wellformed env1 q\n                                             wellformed env1 us\n                                             (csb,b') <- checkEnv (define te' env1) b\n                                             popFX\n                                             (cs1,eq1) <- markScoped env n q' te csb\n                                             return (cs1, [Class l n (noqual env q) (map snd as) (bindWits eq1 ++ abstractDefs env q b') ddoc])\n      where env1                        = tydefineVars q' $ setInClass env\n            NClass _ as te _            = findName n env\n            te'                         = selfSubst n' q te\n            q'                          = selfQuant n' q\n            n'                          = NoQ n\n\n    checkEnv' env (Protocol l n q us b ddoc)\n                                        = do --traceM (\"## checkEnv protocol \" ++ prstr n)\n                                             pushFX fxPure tNone\n                                             wellformed env1 q\n                                             (csu,wmap) <- wellformedProtos env1 us\n                                             (csb,b') <- checkEnv (define te env1) b\n                                             popFX\n                                             (cs1,eq1) <- markScoped env n q' te (csu++csb)\n                                             b' <- usubst b'\n                                             return (cs1, convProtocol env n q ps eq1 wmap b')\n      where env1                        = tydefineVars q' $ setInClass env\n            NProto _ ps te _            = findName n env\n            te'                         = selfSubst n' q te\n            q'                          = selfQuant n' q\n            n'                          = NoQ n\n\n    checkEnv' env (Extension l q c us b ddoc)\n      | isActor env n                   = notYet (loc n) \"Extension of an actor\"\n      | isProto env n                   = notYet (loc n) \"Extension of a protocol\"\n      | otherwise                       = do --traceM (\"## checkEnv extension \" ++ prstr n ++ \"(\" ++ prstrs us ++ \")\")\n                                             pushFX fxPure tNone\n                                             wellformed env1 q\n                                             (csu,wmap) <- wellformedProtos env1 us\n                                             (csb,b') <- checkEnv (define te' env1) b\n                                             popFX\n                                             (cs1,eq1) <- markScoped env n' q' te (csu++csb)\n                                             b' <- usubst b'\n                                             return (cs1, convExtension env n' c q ps eq1 wmap b' [])\n      where env1                        = tydefineInst c ps thisKW' $ tydefineVars q' $ setInClass env\n            n                           = tcname c\n            n'                          = extensionName us c\n            NExt _ _ ps te _ _          = findName n' env\n            te'                         = selfSubst n q te\n            q'                          = selfQuant n q\n            tc                          = TC n (map tVar $ qbound q)\n\n    checkEnv' env x                     = do (cs,x') <- checkEnv env x\n                                             return (cs, [x'])\n\ninstance Check Stmt where\n    checkEnv env (If l bs els)          = do (cs1,bs') <- checkEnv env bs\n                                             (cs2,els') <- checkEnv env els\n                                             return (cs1++cs2, If l bs' els')\n    checkEnv env (Decl l ds)            = do (cs,ds') <- checkEnv env ds\n                                             return (cs, Decl l ds')\n    checkEnv env (Signature l ns sc dec)\n                                        = do wellformed env1 q\n                                             wellformed env1 t\n                                             return ([], Signature l ns sc' dec')\n      where TSchema l q t               = sc\n            sc' | null q                = sc\n                | otherwise             = let TFun l' x p k t' = t in TSchema l (noqual env q) (TFun l' x (qualWRow env q p) k t')\n            dec'                        = if inClass env && isProp dec sc then Property else dec\n            env1                        = tydefineVars q env\n    checkEnv env s                      = return ([], s)\n\ninstance Check Branch where\n    checkEnv env (Branch e b)           = do (cs,b') <- checkEnv env b\n                                             return (cs, Branch e b')\n\n--------------------------------------------------------------------------------------------------------------------------\n\n\n\ndefaultsP (PosPar n (Just t) (Just e) p)\n  | e /= eNone                          = set : defaultsP p\n  where test                            = eCall (tApp (eQVar primISNONE) [t]) [eVar n]\n        set                             = sAssign (pVar n t) (eCond e test (eVar n))\ndefaultsP (PosPar n _ _ p)              = defaultsP p\ndefaultsP _                             = []\n\nnoDefaultsP (PosPar n (Just t) (Just e) p)\n                                        = PosPar n (Just $ tOpt t) Nothing (noDefaultsP p)\nnoDefaultsP (PosPar n t e p)            = PosPar n t e (noDefaultsP p)\nnoDefaultsP k                           = k\n\ndefaultsK (KwdPar n (Just t) (Just e) k)\n  | e /= eNone                          = set : defaultsK k\n  where test                            = eCall (tApp (eQVar primISNONE) [t]) [eVar n]\n        set                             = sAssign (pVar n t) (eCond e test (eVar n))\ndefaultsK (KwdPar n _ _ k)              = defaultsK k\ndefaultsK _                             = []\n\nnoDefaultsK (KwdPar n (Just t) (Just e) k)\n                                        = KwdPar n (Just $ tOpt t) Nothing (noDefaultsK k)\nnoDefaultsK (KwdPar n t e k)            = KwdPar n t e (noDefaultsK k)\nnoDefaultsK k                           = k\n\n\n--------------------------------------------------------------------------------------------------------------------------\n\ninstance InfEnv Branch where\n    infEnv env (Branch e b)             = do (cs1,env',s,_,e') <- inferTest env e\n                                             (cs2,te,b') <- infEnv env' b\n                                             return (cs1++cs2, te, Branch e' (termsubst s b'))\n\ninstance InfEnv WithItem where\n    infEnv env (WithItem e Nothing)     = do (cs,t,e') <- infer env e\n                                             w <- newWitness\n                                             return (Proto (locinfo2  66 e) env w t pContextManager :\n                                                     cs, [], WithItem e' Nothing)           -- TODO: translate using w\n    infEnv env (WithItem e (Just p))    = do (cs1,t1,e') <- infer env e\n                                             (te,t2,p') <- infEnvT env p\n                                             w <- newWitness\n                                             return (Cast (locinfo2 67 e) env t1 t2 :\n                                                     Proto (locinfo2 68 e) env w t1 pContextManager :\n                                                     cs1, te, WithItem e' (Just p'))         -- TODO: translate using w\n\ninstance InfEnv Handler where\n    infEnv env (Handler ex b)           = do (cs1,te,ex') <- infEnv env ex\n                                             (cs2,te1,b') <- infEnv (define te env) b\n                                             return (cs1++cs2, exclude te1 (dom te), Handler ex' b')\n\ninstance InfEnv Except where\n    infEnv env (ExceptAll l)            = return ([], [], ExceptAll l)\n    infEnv env (Except l x)             = return ([Cast (locinfo l 69) env t tException], [], Except l x)\n      where t                           = tCon (TC (unalias env x) [])\n    infEnv env (ExceptAs l x n)         = return ([Cast (locinfo l 70) env t tException], [(n, NVar t)], ExceptAs l x n)\n      where t                           = tCon (TC (unalias env x) [])\n\ninstance Infer Expr where\n    infer env x@(Var l n)               = case findQName n env of\n                                            NVar t -> return ([], t, x)\n                                            NSVar t -> do\n                                                fx <- currFX\n                                                return ([Cast info env fxProc fx], t, x)\n                                              where info = Simple l (\"State variable may only be accessed in a proc\")\n                                            NDef sc d _ -> do\n                                                (cs,tvs,t) <- instantiate env sc\n                                                let e = app t (tApp x tvs) $ protoWitsOf cs\n                                                    cs1 = map (addTyping env n sc t) cs\n                                                --traceM (\"## type of \" ++ prstr n ++ \" = \" ++ prstr t ++ \", cs = \" ++ render(commaList cs))\n                                                if actorSelf env\n                                                    then wrapped l attrWrap env cs1 [tActor,t] [eVar selfKW,e]\n                                                    else return (cs1, t, e)\n                                            NClass q _ _ _ -> do\n                                                (cs0,ts) <- instQBinds env q\n                                                --traceM (\"## Instantiating \" ++ prstr n)\n                                                let ns = abstractAttrs env n\n                                                when (not $ null ns) (err3 (loc n) ns \"Abstract attributes prevent instantiation:\")\n                                                case findAttr env (TC n ts) initKW of\n                                                    Just (_,sc,_) -> do\n                                                        (cs1,tvs,t) <- instantiate env sc\n                                                        let t0 = tCon $ TC (unalias env n) ts\n                                                            t' = vsubst [(tvSelf,t0)] t{ restype = tSelf }\n                                                        return (cs0++cs1, t', app t' (tApp x (ts++tvs)) $ protoWitsOf (cs0++cs1))\n                                            NAct q p k _ _ -> do\n--                                                when (abstractActor env n) (err1 n \"Abstract actor cannot be instantiated:\")\n                                                (cs,tvs,t) <- instantiate env (tSchema q (tFun fxProc p k (tCon0 (unalias env n) q)))\n                                                return (cs, t, app t (tApp x tvs) $ protoWitsOf cs)\n                                            NSig _ _ _ -> nameReserved n\n                                            NReserved -> nameReserved n\n                                            _ -> nameUnexpected n\n\n    infer env e@(Int _ val s)\n       | val < (-9223372036854775808)   = return ([], tBigint, e) -- below i64 range ⇒ bigint\n       | val > 18446744073709551615     = return ([], tBigint, e) -- above u64 range ⇒ bigint\n       | val > 9223372036854775807      = return ([], tU64, e)    -- between i64 max and u64 max ⇒ u64\n       | otherwise                      = do t <- newUnivar env\n                                             w <- newWitness\n                                             return ([Proto (locinfo2 72 e) env w t pNumber], t, eCall (eDot (eVar w) fromatomKW) [e])\n    infer env e@(Float _ val s)         = do t <- newUnivar env\n                                             w <- newWitness\n                                             return ([Proto (locinfo2 73 e) env w t pRealFloat], t, eCall (eDot (eVar w) fromatomKW) [e])\n    infer env e@Imaginary{}             = notYetExpr e\n    infer env e@(Bool _ val)            = return ([], tBool, e)\n    infer env e@(None _)                = return ([], tNone, e)\n    infer env e@(NotImplemented _)      = notYetExpr e\n    infer env e@(Ellipsis _)            = notYetExpr e\n    infer env e@(Strings _ ss)          = return ([], tStr, e)\n    infer env e@(BStrings _ ss)         = return ([], tBytes, e)\n    infer env (Call l e ps ks)          = inferCall env True l e ps ks\n    infer env (TApp l e ts)             = internal l \"Unexpected TApp in infer\"\n    infer env (Let l ss e)              = do (cs1, te, ss') <- infEnv env ss\n                                             (cs2, t, e') <- infer (define te env) e\n                                             return (cs1++cs2, t, Let l ss' e')\n    infer env (Async l e)               = do (cs,t,e) <- infer env e                        -- expect an action returning t'\n                                             prow <- newUnivarOfKind PRow env\n                                             krow <- newUnivarOfKind KRow env\n                                             t' <- newUnivar env\n                                             let tf fx = tFun fx prow krow\n                                             return (Cast (locinfo2 74 e) env t (tf fxAction t') :\n                                                     cs, tf fxProc (tMsg t'), Async l e)    -- produce a proc returning Msg[t']\n    infer env (Await l e)               = do t0 <- newUnivar env\n                                             (cs1,e') <- inferSub env (tMsg t0) e\n                                             fx <- currFX\n                                             return (Cast (locinfo2 75 e) env fxProc fx :\n                                                     cs1, t0, Await l e')\n    infer env (Index l e ix)            = do ti <- newUnivar env\n                                             (cs1,ix') <- inferSub env ti ix\n                                             t0 <- newUnivar env\n                                             w <- newWitness\n                                             (cs2,t,e') <- infer env e\n                                             return (Proto (locinfo2 76 e) env w t (pIndexed ti t0) :\n                                                     cs1++cs2, t0, eCall (eDot (eVar w) getitemKW) [e', ix'])\n    infer env (Slice l e sl)            = do (cs1,sl') <- inferSlice env sl\n                                             (cs2,t,e') <- infer env e\n                                             t0 <- newUnivar env\n                                             w <- newWitness\n                                             return (Proto (locinfo2 77 e) env w t (pSliceable t0) :\n                                                     cs1++cs2, t, eCall (eDot (eVar w) getsliceKW) [e', sliz2exp sl'])\n    infer env (Cond l e1 e e2)          = do t0 <- newUnivar env\n                                             (cs0,env',s,_,e') <- inferTest env e\n                                             (cs1,e1') <- inferSub env' t0 e1\n                                             (cs2,e2') <- inferSub env t0 e2\n                                             return (cs0++cs1++cs2, t0, Cond l (termsubst s e1') e' e2')\n    infer env (IsInstance l e c)        = case findQName c env of\n                                             NClass q _ _ _ -> do\n                                                (cs,t,e') <- infer env e\n                                                ts <- newUnivars env [ tvkind v | v <- qbound q ]\n                                                return (cs, tBool, IsInstance l e' c)\n                                             _ -> nameUnexpected c\n    infer env (BinOp l s@Strings{} Mod e)\n      | TRow _ _ _ t TNil{} <- prow     = do (cs,e') <- inferSub env t e\n                                             return (cs, tStr, eCall formatF [s,eTuple [e']])\n      | otherwise                       = do (cs,e') <- inferSub env tup e\n                                             return (cs, tStr, eCall formatF [s,e'])\n      where formatF                     = tApp (eQVar primFORMAT) [prow]\n            tup                         = tTuple prow kwdNil\n            prow                        = format $ concat $ sval s\n            format []                   = posNil\n            format ('%':s)              = nokey s\n            format (c:s)                = format s\n            nokey ('(':s)               = err l (\"Mapping keys not supported in format strings\")\n            nokey s                     = flags s\n            flags (f:s)\n              | f `elem` \"#0- +\"        = flags s\n            flags s                     = width s\n            width ('*':s)               = posRow tInt (dot s)\n            width (n:s)\n              | n `elem` \"123456789\"    = dot (dropWhile (`elem` \"0123456789\") s)\n            width s                     = dot s\n            dot ('.':s)                 = prec s\n            dot s                       = len s\n            prec ('*':s)                = posRow tInt (len s)\n            prec (n:s)\n              | n `elem` \"0123456789\"   = len (dropWhile (`elem` \"0123456789\") s)\n            prec s                      = len s\n            len (l:s)\n              | l `elem` \"hlL\"          = conv s\n            len s                       = conv s\n            conv (t:s)\n              | t `elem` \"diouxXc\"      = posRow tInt (format s)\n              | t `elem` \"eEfFgG\"       = posRow tFloat (format s)\n              | t `elem` \"rsa\"          = posRow tStr (format s)\n              | t == '%'                = format s\n            conv (c:s)                  = err l (\"Bad conversion character: \" ++ [c])\n            conv []                     = err l (\"Bad conversion string\")\n    infer env e@(BinOp l e1 op e2)\n      | op `elem` [Or,And]              = do (cs,_,_,t,e') <- inferTest env e\n                                             return (cs, t, e')\n      | op == Mult                      = do t <- newUnivar env\n                                             t' <- newUnivar env\n                                             (cs1,e1') <- inferSub env t e1\n                                             (cs2,e2') <- inferSub env t' e2\n                                             w <- newWitness\n                                             return (Proto (locinfo' l 79 e) env w t (pTimes t') :\n                                                     cs1++cs2, t, eCall (eDot (eVar w) mulKW) [e1',e2'])\n      | op == Div                       = do t <- newUnivar env\n                                             t' <- newUnivar env\n                                             (cs1,e1') <- inferSub env t e1\n                                             (cs2,e2') <- inferSub env t e2\n                                             w <- newWitness\n                                             return (Proto (locinfo' l 80 e) env w t (pDiv t') :\n                                                     cs1++cs2, t', eCall (eDot (eVar w) truedivKW) [e1',e2'])\n      | otherwise                       = do t <- newUnivar env\n                                             (cs1,e1') <- inferSub env t e1\n                                             (cs2,e2') <- inferSub env (rtype op t) e2\n                                             w <- newWitness\n                                             return (Proto (locinfo2 81 e) env w t (protocol op) :\n                                                     cs1++cs2, t, eCall (eDot (eVar w) (method op)) [e1',e2'])\n      where protocol Plus               = pPlus\n            protocol Minus              = pMinus\n            protocol Pow                = pNumber\n            protocol Mod                = pIntegral\n            protocol EuDiv              = pIntegral\n            protocol ShiftL             = pIntegral\n            protocol ShiftR             = pIntegral\n            protocol BOr                = pLogical\n            protocol BXor               = pLogical\n            protocol BAnd               = pLogical\n            protocol MMult              = pMatrix\n            method Plus                 = addKW\n            method Minus                = subKW\n            method Pow                  = powKW\n            method Mod                  = modKW\n            method EuDiv                = floordivKW\n            method ShiftL               = lshiftKW\n            method ShiftR               = rshiftKW\n            method BOr                  = orKW\n            method BXor                 = xorKW\n            method BAnd                 = andKW\n            method MMult                = matmulKW\n            rtype ShiftL t              = tInt\n            rtype ShiftR t              = tInt\n            rtype _ t                   = t\n    infer env (UnOp l op e)\n      | op == Not                       = do (cs,_,_,_,e') <- inferTest env e\n                                             return (cs, tBool, UnOp l op e')\n      | otherwise                       = do (cs,t,e') <- infer env e\n                                             w <- newWitness\n                                             return (Proto (locinfo2 82 e) env w t (protocol op) :\n                                                     cs, t, eCall (eDot (eVar w) (method op)) [e'])\n      where protocol UPlus              = pNumber\n            protocol UMinus             = pNumber\n            protocol BNot               = pIntegral\n            method UPlus                = posKW\n            method UMinus               = negKW\n            method BNot                 = invertKW\n    infer env e@(CompOp l e1 [OpArg op e2])\n      | op `elem` [In,NotIn]            = do t1 <- newUnivar env\n                                             (cs1,e1') <- inferSub env t1 e1\n                                             t2 <- newUnivar env\n                                             (cs2,e2') <- inferSub env t2 e2\n                                             w <- newWitness\n                                             return (Proto (locinfo2 83 e) env w t2 (pContainer t1) :\n                                                     cs1++cs2, tBool, eCall (eDot (eVar w) (method op)) [e2', e1'])\n      | op `elem` [Is,IsNot], e2==eNone = do (cs,_,_,t,e') <- inferTest env e\n                                             return (cs, t, e')\n      | otherwise                       = do t <- newUnivar env\n                                             (cs1,e1') <- inferSub env t e1\n                                             (cs2,e2') <- inferSub env t e2\n                                             w <- newWitness\n                                             return (Proto (locinfo' l 84 e) env w t (protocol op) :\n                                                     cs1++cs2, tBool, eCall (eDot (eVar w) (method op)) [e1',e2'])\n                                             -- TODO: This gives misleading error msg; it says that \"e1 op e2 must implement protocol op\"\n      where protocol Eq                 = pEq\n            protocol NEq                = pEq\n            protocol LtGt               = pEq\n            protocol Lt                 = pOrd\n            protocol Gt                 = pOrd\n            protocol LE                 = pOrd\n            protocol GE                 = pOrd\n            protocol Is                 = pIdentity\n            protocol IsNot              = pIdentity\n            method Eq                   = eqKW\n            method NEq                  = neKW\n            method LtGt                 = neKW\n            method Lt                   = ltKW\n            method Gt                   = gtKW\n            method LE                   = leKW\n            method GE                   = geKW\n            method Is                   = isKW\n            method IsNot                = isnotKW\n            method In                   = containsKW\n            method NotIn                = containsnotKW\n    infer env (CompOp l e1 ops)         = notYet l \"Comparison chaining\"\n\n    infer env (Dot l x@(Var _ c) n)\n      | NClass q us te _ <- cinfo       = do (cs0,ts) <- instQBinds env q\n                                             let tc = TC c' ts\n                                             case findAttr env tc n of\n                                                Just (_,sc,dec)\n                                                  | dec == Just Property -> err l \"Property attribute not selectable by class\"\n                                                  | abstractAttr env tc n -> err l \"Abstract attribute not selectable by class\"\n                                                  | otherwise -> do\n                                                      (cs1,tvs,t) <- instantiate env sc\n                                                      let t' = vsubst [(tvSelf,tCon tc)] $ addSelf t dec\n                                                          csq = if dec == Just Static || n == initKW then cs0 else []\n                                                      return (csq++cs1, t', app2nd dec t' (tApp (Dot l x n) (ts++tvs)) $ protoWitsOf (csq++cs1))\n                                                Nothing ->\n                                                    case findProtoByAttr env c' n of\n                                                        Just p -> do\n                                                            p <- instwildcon env p\n                                                            we <- eVar <$> newWitness\n                                                            let Just (wf,sc,dec) = findAttr env p n\n                                                            (cs2,tvs,t) <- instantiate env sc\n                                                            let t' = vsubst [(tvSelf,tCon tc)] $ addSelf t dec\n                                                            return (cs2, t', app t' (tApp (eDot (wf we) n) tvs) $ protoWitsOf cs2)\n                                                        Nothing -> err1 l \"Attribute not found\"\n      | NProto q us te _ <- cinfo       = do (_,ts) <- instQBinds env q\n                                             let tc = TC c' ts\n                                             case findAttr env tc n of\n                                                Just (wf,sc,dec) -> do\n                                                    (cs1,tvs,t) <- instantiate env sc\n                                                    t0 <- newUnivar env\n                                                    let t' = vsubst [(tvSelf,t0)] $ addSelf t dec\n                                                    w <- newWitness\n                                                    return (Proto (locinfo l 85) env w t0 tc :\n                                                            cs1, t', app t' (tApp (Dot l (wf $ eVar w) n) tvs) $ protoWitsOf cs1)\n                                                Nothing -> err1 l \"Attribute not found\"\n      where c'                          = unalias env c\n            cinfo                       = findQName c' env\n\n    infer env (Dot l e n)\n      | n == initKW                     = err1 n \"__init__ cannot be selected by instance\"\n      | otherwise                       = do (cs,t,e') <- infer env e\n                                             w <- newWitness\n                                             t0 <- newUnivar env\n                                             let con = case t of\n                                                          TOpt _ _ -> Sel info env w t n t0\n                                                          _ ->  Sel (locinfo' l 86 e) env w t n t0\n                                                 info = Simple l (Pretty.print t ++ \" does not have an attribute \"++ Pretty.print n ++\n                                                                  \"\\nHint: you may need to test if \" ++ Pretty.print e ++ \" is not None\")\n                                             return  (con : cs, t0, eCall (eVar w) [e'])\n\n                                         -- The parser inserts Opt nodes only within OptChain nodes (which each contains exactly one Opt node).\n                                         -- The Opt nodes are handled and eliminated by infer on an OptChain node.\n                                         -- e is an atomic expression (atom_expr in the parser) which contains exactly one ? in its sequence of trailers\n    infer env (OptChain l e)           = do x <- newTmp                                                                                      -- Example: a s1 s2 ? t1 t2\n                                            let (b,e1,e2) = split x e                                                                          -- e1 = a s1 s2, e2 = x t1 t2\n                                            te <- newUnivar env\n                                            (cs1,e1') <- inferSub env (tOpt te) e1\n                                            let env1 = define [(x,NVar te)] env\n                                            (cs2,t,e2') <- infer env1 e2\n                                            y <- newTmp\n                                            (cs3,t',e3) <- alt t te b\n                                            return (cs1++cs2++cs3,\n                                                     t', eLet [sAssign (pVar y (tOpt te)) e1']\n                                                                           (eCond (termsubst [(x,eCAST (tOpt te) te (eVar y))] e2')\n                                                                                  (eCall (tApp (eQVar primISNOTNONE) [te]) [eVar y])\n                                                                                  e3))\n      where split x (Opt l e b)         = (b, e, eVar x)\n            split x (Dot l e n)         = (b, e1,Dot l e2 n) where (b,e1,e2) = split x e\n            split x (Call l f ps ks)    = (b, e1,Call l e2 ps ks) where (b,e1,e2) = split x f\n            split x (Index l e ix)      = (b, e1,Index l e2 ix) where (b,e1,e2) = split x e\n            split x (Slice l e sz)      = (b, e1,Slice l e2 sz) where (b,e1,e2) = split x e\n            alt t te True               = do w <- newWitness\n                                             w1 <- newWitness\n                                             t1 <- newUnivar env\n                                             return ([Sub (noinfo 444) env w tNone t1, Sub (noinfo 555) env w1 t t1],t1,eNone)\n            alt t te False              = return ([],t,eCall (tApp (eQVar primRaiseValueError) [te]) [Strings NoLoc [\"Forced unwrapping applied to None\"]] )\n \n    infer env e@(Rest _ _ _)            = notYetExpr e\n--    infer env (Rest l e n)              = do p <- newUnivarOfKind PRow env\n--                                             k <- newUnivarOfKind KRow env\n--                                             t0 <- newUnivar env\n--                                             (cs,e') <- inferSub env (tTuple p (kwdRow n t0 k)) e\n--                                             return (cs, tTuple p k, Rest l e' n)\n\n    infer env (DotI l e i)              = do (tup,ti,_) <- tupleTemplate env i\n                                             (cs,e') <- inferSub env tup e\n                                             return (cs, ti, DotI l e' i)\n\n    infer env e@(RestI _ _ _)           = notYetExpr e\n--    infer env (RestI l e i)             = do (tup,_,rest) <- tupleTemplate env i\n--                                             (cs,e') <- inferSub env tup e\n--                                             return (cs, rest, RestI l e' i)\n\n    infer env (Lambda l p k e fx)\n      | nodup (p,k)                     = do pushFX fx tNone\n                                             (cs0,te0,p') <- infEnv env1 p\n                                             (cs1,te1,k') <- infEnv (define te0 env1) k\n                                             let env2 = define te1 $ define te0 env1\n                                             (cs2,t,e') <- case e of\n                                                             Call l' e' ps ks -> inferCall env2 False l' e' ps ks\n                                                             _ -> infer env2 e\n                                             popFX\n                                             return (cs0++cs1++cs2, tFun fx (prowOf p') (krowOf k') t, Lambda l (noDefaultsP p') (noDefaultsK k') e' fx)\n                                                     -- TODO: replace defaulted params with Conds\n      where env1                        = reserve (bound (p,k)) env\n    infer env e@Yield{}                 = notYetExpr e\n    infer env e@YieldFrom{}             = notYetExpr e\n    infer env (Tuple l pargs kargs)     = do (cs1,prow,pargs') <- infer env pargs\n                                             (cs2,krow,kargs') <- infer env kargs\n                                             return (cs1++cs2, TTuple l prow krow, Tuple l pargs' kargs')\n    infer env (List l es)               = do t0 <- newUnivar env\n                                             (cs,es') <- infElems env es t0\n                                             return (cs, tList t0, List l es')\n    infer env (ListComp l e co)\n      | nodup co                        = do (cs1,env',s,co') <- infComp env co\n                                             t0 <- newUnivar env\n                                             (cs2,es) <- infElems env' [e] t0\n                                             let [e'] = es\n                                             return (cs1++cs2, tList t0, ListComp l (termsubst s e') co')\n    infer env (Set l es)                = do t0 <- newUnivar env\n                                             (cs,es')  <- infElems env es t0\n                                             w <- newWitness\n                                             return (Proto (locinfo l 87) env w t0 pHashable : cs, tSet t0, eCall (tApp (eQVar primMkSet) [t0]) [eVar w,Set l es'])\n    infer env (SetComp l e co)\n      | nodup co                        = do (cs1,env',s,co') <- infComp env co\n                                             t0 <- newUnivar env\n                                             (cs2,es) <- infElems env' [e] t0\n                                             w <- newWitness\n                                             let Elem v = head es\n                                                 e' = Elem (annot (tHashableW t0) (eVar w) t0 v)\n                                             return (Proto (locinfo l 89) env w t0 pHashable : cs1++cs2, tSet t0, SetComp l (termsubst s e') co')\n    infer env (Dict l as)               = do tk <- newUnivar env\n                                             tv <- newUnivar env\n                                             (cs,as') <- infAssocs env as tk tv\n                                             w <- newWitness\n                                             return (Proto (locinfo l 88) env w tk pHashable : cs, tDict tk tv, eCall (tApp (eQVar primMkDict) [tk, tv]) [eVar w,Dict l as'])\n    infer env (DictComp l a co)\n      | nodup co                        = do (cs1,env',s,co') <- infComp env co\n                                             tk <- newUnivar env\n                                             tv <- newUnivar env\n                                             (cs2,as) <- infAssocs env' [a] tk tv\n                                             w <- newWitness\n                                             let Assoc k v = head as\n                                                 a' = Assoc (annot (tHashableW tk) (eVar w) tk k) v\n                                             return (Proto (locinfo l 90) env w tk pHashable : cs1++cs2, tDict tk tv, DictComp l (termsubst s a') co')\n\n    infer env (Paren l e)               = do (cs,t,e') <- infer env e\n                                             return (cs, t, Paren l e')\n\ninferCall env unwrap l e ps ks          = do (cs1,t,e') <- infer env e{eloc = l}\n                                             (cs1,t,e') <- if unwrap && actorSelf env then wrapped l attrUnwrap env cs1 [t] [e'] else pure (cs1,t,e')\n                                             (cs2,prow,ps') <- infer env ps\n                                             (cs3,krow,ks') <- infer env ks\n                                             t0 <- newUnivar env\n                                             fx <- currFX\n                                             w <- newWitness\n                                             let i = case e of\n                                                        Var _ n@(NoQ n')\n                                                          | NDef sc _ _ <- findQName n env,\n                                                            Just l2 <- findDefLoc n' env ->\n                                                                   DeclInfo l l2 n' sc (\"Type incompatibility between definition of and call of \"++Pretty.print n')\n                                                        _ -> DfltInfo l 837 (Just (Call l e ps ks)) []\n                                             return (Sub i env w t (tFun fx prow krow t0)  :\n                                            -- return (Sub (DfltInfo l 837 (Just (Call l e ps ks)) []) w [] t (tFun fx prow krow t0) :\n                                                     cs1++cs2++cs3, t0, Call l (eCall (eVar w) [e']) ps' ks')\n\n\n\ntupleTemplate env i                     = do ts <- mapM (const $ newUnivar env) [0..i]        -- Handle DotI or RestI...\n                                             p <- newUnivarOfKind PRow env\n                                             k <- newUnivarOfKind KRow env\n                                             let p0 = foldl (flip posRow) p ts\n                                                 p1 = foldl (flip posRow) p (tail ts)\n                                             return (TTuple NoLoc p0 k, head ts, TTuple NoLoc p1 k)\n\n\ninfElems env [] t0                      = return ([], [])\ninfElems env (Elem e : es) t0           = do (cs1,e') <- inferSub env t0 e\n                                             (cs2,es') <- infElems env es t0\n                                             return (cs1++cs2, Elem e' : es')\ninfElems env (Star e : es) t0           = do t1 <- newUnivar env\n                                             (cs1,e') <- inferSub env t1 e\n                                             (cs2,es') <- infElems env es t0\n                                             w <- newWitness\n                                             return (Proto (locinfo2 89 e) env w t1 (pIterable t0) :\n                                                     cs1++cs2, Star e' : es')\n\n\ninfAssocs env [] tk tv                  = return ([], [])\ninfAssocs env (Assoc k v : as) tk tv    = do (cs1,k') <- inferSub env tk k\n                                             (cs2,v') <- inferSub env tv v\n                                             (cs3,as') <- infAssocs env as tk tv\n--                                             return (cs1++cs2++cs3, Elem (eTuple [k',v']) : as')\n                                             return (cs1++cs2++cs3, Assoc k' v' : as')\ninfAssocs env (StarStar e : as) tk tv   = do t1 <- newUnivar env\n                                             (cs1,e') <- inferSub env t1 e\n                                             (cs2,as') <- infAssocs env as tk tv\n                                             w <- newWitness\n                                             return (Proto (locinfo2 90 e) env w t1 (pIterable $ tTupleP $ posRow tk $ posRow tv posNil) :\n--                                                     cs1++cs2, Star e' : as')\n                                                     cs1++cs2, StarStar e' : as')\n\n\ninferTest env (BinOp l e1 And e2)       = do (cs1,env1,s1,t1,e1') <- inferTest env e1\n                                             (cs2,env2,s2,t2,e2') <- inferTest env1 e2\n                                             t <- newUnivar env\n                                             w1 <- newWitness\n                                             w2 <- newWitness\n                                             return (Sub (locinfo' l 91 e1) env w1 t1 t : Sub (locinfo' l 92 e2) env w2 t2 t :\n                                                     cs1++cs2, env2, s1++s2, t, BinOp l (eCall (eVar w1) [e1']) And (eCall (eVar w2) [termsubst s1 e2']))\ninferTest env (BinOp l e1 Or e2)        = do (cs1,_,_,t1,e1') <- inferTest env e1\n                                             (cs2,_,_,t2,e2') <- inferTest env e2\n                                             t <- newUnivar env\n                                             w1 <- newWitness\n                                             w2 <- newWitness\n                                             return (Sub (locinfo2 93 e1) env w1 t1 (tOpt t) : Sub (locinfo2 94 e2) env w2 t2 t :\n                                                     cs1++cs2, env, [], t, BinOp l (eCall (eVar w1) [e1']) Or (eCall (eVar w2) [e2']))\ninferTest env (UnOp l Not e)            = do (cs,_,_,_,e') <- inferTest env e\n                                             return (cs, env, [], tBool, UnOp l Not e')\ninferTest env (CompOp l e [OpArg IsNot None{}])\n                                        = do t <- newUnivar env\n                                             (cs1,e1) <- inferSub env (tOpt t) e\n                                             let e' = eCall (tApp (eQVar primISNOTNONE) [t]) [e1]\n                                             case e of\n                                               Var _ (NoQ n) ->\n                                                  return (cs1, define [(n,NVar t)] env, sCast n (tOpt t) t, tBool, e')\n                                               _ ->\n                                                 return (cs1, env, [], tBool, e')\ninferTest env (CompOp l e [OpArg Is None{}])\n                                        = do t <- newUnivar env\n                                             (cs1,e') <- inferSub env (tOpt t) e\n                                             return (cs1, env, [], tBool, eCall (tApp (eQVar primISNONE) [t]) [e'])\ninferTest env (IsInstance l e@(Var _ (NoQ n)) c)\n                                        = case findQName c env of\n                                             NClass q _ _ _ -> do\n                                                (cs,t,e') <- infer env e\n                                                ts <- newUnivars env [ tvkind v | v <- qbound q ]\n                                                let tc = tCon (TC c ts)\n                                                return (cs, define [(n,NVar tc)] env, sCast n t tc, tBool, IsInstance l e' c)\n                                             _ -> nameUnexpected c\ninferTest env (Paren l e)               = do (cs,env',s,t,e') <- inferTest env e\n                                             return (cs, env', s, t, Paren l e')\ninferTest env e                         = do (cs,t,e') <- infer env e\n                                             return (cs, env, [], t, e')\n\n\nsCast n t t'                            = [(n, eCAST t t' (eVar n))]\n\ninferSlice env (Sliz l e1 e2 e3)        = do (cs1,e1') <- inferSub env tInt e1\n                                             (cs2,e2') <- inferSub env tInt e2\n                                             (cs3,e3') <- inferSub env tInt e3\n                                             return (cs1++cs2++cs3, Sliz l e1' e2' e3')\n\n\nclass InferSub a where\n    inferSub                            :: Env -> Type -> a -> TypeM (Constraints,a)\n\ninstance InferSub Expr where\n    inferSub env t e                    = do (cs,t',e') <- infer env e\n                                             w <- newWitness\n                                             return (Sub (locinfo2 96 e) env w t' t : cs, eCall (eVar w) [e'])\n\ninstance InferSub (Maybe Expr) where\n    inferSub env t Nothing              = return ([], Nothing)\n    inferSub env t (Just e)             = do (cs,e') <- inferSub env t e\n                                             return (cs, Just e')\n\n\ninstance (Infer a) => Infer (Maybe a) where\n    infer env Nothing                   = do t <- newUnivar env\n                                             return ([], t, Nothing)\n    infer env (Just x)                  = do (cs,t,e') <- infer env x\n                                             return (cs, t, Just e')\n\ninstance InfEnv PosPar where\n    infEnv env (PosPar n a Nothing p)   = do t <- maybe (newUnivar env) return a\n                                             wellformed env t\n                                             let t' = t -- {tloc = loc n}\n                                             (cs,te,p') <- infEnv (define [(n, NVar t')] env) p\n                                             return (cs, (n, NVar t'):te, PosPar n (Just t') Nothing p')\n    infEnv env (PosPar n a (Just e) p)  = do t <- maybe (newUnivar env) return a\n                                             wellformed env t\n                                             (cs1,e') <- inferSub env t e\n                                             (cs2,te,p') <- infEnv (define [(n, NVar t)] env) p\n                                             return (cs1++cs2, (n, NVar t):te, PosPar n (Just t) (Just e') p')\n    infEnv env (PosSTAR n a)            = do t <- maybe (newUnivar env) return a\n                                             wellformed env t\n                                             r <- newUnivarOfKind PRow env\n                                             return ([Cast (locinfo n 97) env t (tTupleP r)], [(n, NVar t)], PosSTAR n (Just $ tTupleP r))\n    infEnv env PosNIL                   = return ([], [], PosNIL)\n\ninstance InfEnv KwdPar where\n    infEnv env (KwdPar n a Nothing k)   = do t <- maybe (newUnivar env) return a\n                                             wellformed env t\n                                             (cs,te,k') <- infEnv (define [(n, NVar t)] env) k\n                                             return (cs, (n, NVar t):te, KwdPar n (Just t) Nothing k')\n    infEnv env (KwdPar n a (Just e) k)  = do t <- maybe (newUnivar env) return a\n                                             wellformed env t\n                                             (cs1,e') <- inferSub env t e\n                                             (cs2,te,k') <- infEnv (define [(n, NVar t)] env) k\n                                             return (cs1++cs2, (n, NVar t):te, KwdPar n (Just t) (Just e') k')\n    infEnv env (KwdSTAR n a)            = do t <- maybe (newUnivar env) return a\n                                             wellformed env t\n                                             r <- newUnivarOfKind KRow env\n                                             return ([Cast (locinfo n 98) env t (tTupleK r)], [(n, NVar t)], KwdSTAR n (Just $ tTupleK r))\n    infEnv env KwdNIL                   = return ([], [], KwdNIL)\n\n---------\n\ninstance Infer PosArg where\n    infer env (PosArg e p)              = do (cs1,t,e') <- infer env e\n                                             (cs2,prow,p') <- infer env p\n                                             return (cs1++cs2, posRow t prow, PosArg e' p')\n    infer env (PosStar e)               = do prow <- newUnivarOfKind PRow env\n                                             (cs,e') <- inferSub env (tTupleP prow) e\n                                             return (cs, posStar prow, PosStar e')\n    infer env PosNil                    = return ([], posNil, PosNil)\n\ninstance Infer KwdArg where\n    infer env (KwdArg n e k)            = do (cs1,t,e') <- infer env e\n                                             (cs2,krow,k') <- infer env k\n                                             return (cs1++cs2, kwdRow n t krow, KwdArg n e' k')\n    infer env (KwdStar e)               = do krow <- newUnivarOfKind KRow env\n                                             (cs,e') <- inferSub env (tTupleK krow) e\n                                             return (cs, kwdStar krow, KwdStar e')\n    infer env KwdNil                    = return ([], kwdNil, KwdNil)\n\n\ninfComp env NoComp                      = return ([], env, [], NoComp)\ninfComp env (CompIf l e c)              = do (cs1,env1,s,_,e') <- inferTest env e\n                                             (cs2,env2,s',c') <- infComp env1 c\n                                             return (cs1++cs2, env2, s++s', CompIf l e' (termsubst s c'))\ninfComp env (CompFor l p e c)           = do (te1,t1,p') <- infEnvT (reserve (bound p) env) p\n                                             t2 <- newUnivar env\n                                             (cs2,e') <- inferSub env t2 e\n                                             (cs3,env',s,c') <- infComp (define te1 env) c\n                                             w <- newWitness\n                                             return (Proto (locinfo2 101 e) env w t2 (pIterable t1) :\n                                                     cs2++cs3, env', s, CompFor l p' (eCall (eDot (eVar w) iterKW) [e']) c')\n\ninstance InfEnvT PosPat where\n    infEnvT env (PosPat p ps)           = do (te1,t,p') <- infEnvT env p\n                                             (te2,r,ps') <- infEnvT env ps\n                                             return (te1++te2, posRow t r, PosPat p' ps')\n    infEnvT env (PosPatStar p)          = do (te,t,p') <- infEnvT env p\n                                             r <- newUnivarOfKind PRow env\n                                             tryUnify (locinfo p 102) t (tTupleP r)\n                                             return (te, posStar r, PosPatStar p')\n    infEnvT env PosPatNil               = return ([], posNil, PosPatNil)\n\n\ninstance InfEnvT KwdPat where\n    infEnvT env (KwdPat n p ps)         = do (te1,t,p') <- infEnvT env p\n                                             (te2,r,ps') <- infEnvT env ps\n                                             return (te1++te2, kwdRow n t r, KwdPat n p' ps')\n    infEnvT env (KwdPatStar p)          = do (te,t,p') <- infEnvT env p\n                                             r <- newUnivarOfKind KRow env\n                                             tryUnify (locinfo p 103) t (tTupleK r)\n                                             return (te, kwdStar r, KwdPatStar p')\n    infEnvT env KwdPatNil               = return ([], kwdNil, KwdPatNil)\n\n\n\ninstance InfEnvT Pattern where\n    infEnvT env (PWild l a)             = do t <- maybe (newUnivar env) return a\n                                             wellformed env t\n                                             return ([], t, PWild l (Just t))\n    infEnvT env (PVar l n a)            = do t <- maybe (newUnivar env) return a\n                                             wellformed env t\n                                             case findName n env of\n                                                 NReserved -> do\n                                                     --traceM (\"## infEnvT \" ++ prstr n ++ \" : \" ++ prstr t)\n                                                     return ([(n, NVar t)], t, PVar l n (Just t))\n                                                 NSig (TSchema _ [] t') _ _\n                                                   | TFun{} <- t' -> notYet l \"Pattern variable with previous function signature\"\n                                                   | otherwise -> do\n                                                     --traceM (\"## infEnvT (sig) \" ++ prstr n ++ \" : \" ++ prstr t' ++ \" < \" ++ prstr t)\n                                                     let te = [(n, NVar t')]\n                                                     solveAll env te [Cast (locinfo l 104) env t' t]\n                                                     return (te, t', PVar l n (Just t'))\n                                                 NVar t'\n                                                   | isJust a -> do\n                                                     return ([], t, PVar l n (Just t))\n                                                   | otherwise ->\n                                                     return ([], t', PVar l n Nothing)\n                                                 NSVar t' -> do\n                                                     fx <- currFX\n                                                     solveAll env [(n,NVar t)] [Cast (locinfo l 106) env fxProc fx, Cast (locinfo l 107) env t t']\n                                                     return ([], t', PVar l n Nothing)\n                                                 _ ->\n                                                     err1 n \"Variable not assignable:\"\n    infEnvT env (PTuple l ps ks)        = do (te1,prow,ps') <- infEnvT env ps\n                                             (te2,krow,ks') <- infEnvT env ks\n                                             return (te1++te2, TTuple NoLoc prow krow, PTuple l ps' ks')\n    infEnvT env (PList l ps p)          = do (te1,t1,ps') <- infEnvT env ps\n                                             (te2,t2,p') <- infEnvT (define te1 env) p\n                                             tryUnify (locinfo l 108) t2 (tList t1)\n                                             return (te1++te2, t2, PList l ps' p')\n    infEnvT env (PParen l p)            = do (te,t,p') <- infEnvT env p\n                                             return (te, t, PParen l p')\n    infEnvT env (PData l n es)          = notYet l \"data syntax\"\n\n\ninstance InfEnvT (Maybe Pattern) where\n    infEnvT env Nothing                 = do t <- newUnivar env\n                                             return ([], t, Nothing)\n    infEnvT env (Just p)                = do (te,t,p') <- infEnvT env p\n                                             return (te, t, Just p')\n\ninstance InfEnvT [Pattern] where\n    infEnvT env [p]                     = do (te1,t1,p') <- infEnvT env p\n                                             return (te1,t1,[p'])\n    infEnvT env (p:ps)                  = do (te1,t1,p') <- infEnvT env p\n                                             (te2,t2,ps') <- infEnvT env ps\n                                             tryUnify (locinfo p 109) t1 t2\n                                             return (te1++te2, t1, p':ps')\n\n\n\n-- Test discovery --------------------------------------------------------------\n\ntEnv                                    = tCon (TC (gname [name \"__builtin__\"] (name \"Env\")) [])\nemptyDict                               = Dict NoLoc []\n\ntestDicts                               = [ (\"__unit_tests\",        \"UnitTest\"),\n                                            (\"__simple_sync_tests\", \"SimpleSyncTest\"),\n                                            (\"__sync_tests\",        \"SyncTest\"),\n                                            (\"__async_tests\",       \"AsyncTest\"),\n                                            (\"__env_tests\",         \"EnvTest\") ]\n\ntestStmts env m ss                      = (stmts, tests)\n  where assocs                          = testFuns (define te env) m (ss++ss')\n        (te, ss')                       = genTestActorWrappers ss\n        stmts                           = ss' ++\n                                          [ dictAssign n cl assoc | ((n,cl), assoc) <- testDicts `zip` assocs ] ++\n                                          [ testActor ]\n        tests                           = sort (nub (concatMap assocNames assocs))\n        assocNames assocList            = mapMaybe assocName assocList\n        assocName (Assoc (Strings _ ssParts) _) = Just (concat ssParts)\n        assocName _                     = Nothing\n\ntestEnv                                 = [ (name n, NVar (tDict tStr (testing cl))) | (n,cl) <- testDicts ] ++\n                                          [ (name \"test_main\", NAct [] posNil (kwdRow (name \"env\") tEnv kwdNil) [] Nothing) ]\n\ngname ns n                              = GName (ModName ns) n\ndername a b                             = Derived (name a) (name b)\n\ndictAssign dictname cl dict             = sAssign (pVar (name dictname) (tDict tStr (testing cl))) (mkDict cl dict)\n\ntesting tstr                            = tCon (TC (gname [name \"testing\"] (name tstr)) [])\n\nmkDict cl as                            = eCall (tApp (eQVar primMkDict) [tStr, testing cl]) [w,Dict NoLoc as]\n    where w                             = eCall (eQVar (gname [name \"__builtin__\"] (dername \"Hashable\" \"str\"))) []\n\ntestActor                               = sDecl [Actor NoLoc (name \"test_main\") []\n                                                 PosNIL (KwdPar (name \"env\")  (Just tEnv) Nothing KwdNIL)\n                                             [sExpr (eCall (eQVar (gname [name \"testing\"] (name \"test_runner\")))\n                                                           (map (eVar . name) [\"env\",\"__unit_tests\",\"__simple_sync_tests\",\"__sync_tests\",\"__async_tests\",\"__env_tests\"]))] Nothing]\n\nrow2list (TRow _ _ _ t r)               = t : row2list r\nrow2list (TNil _ _)                     = []\n\nmkAssoc d testType modName =\n    Assoc (Strings NoLoc [nstr (dname d)])\n          (eCall (eQVar (gname [name \"testing\"] testType))\n                 [ eVar (dname d)\n                 , Strings NoLoc [nstr (dname d)]\n                 , comment (dbody d)\n                 , Strings NoLoc [modName]\n                 ])\n  where comment (Expr _ s@(Strings _ ss) : _) = s\n        comment _ = Strings NoLoc [\"\"]\n\nmkAssocActor (Actor _ n _ _ _ body _) testType modName =\n    Assoc (Strings NoLoc [nstr n])\n          (eCall (eQVar (gname [name \"testing\"] testType))\n                 [ eVar n\n                 , Strings NoLoc [nstr n]\n                 , comment body\n                 , Strings NoLoc [modName]\n                 ])\n  where comment (Expr _ s@(Strings _ ss) : _) = s\n        comment _ = Strings NoLoc [\"\"]\n\n\ntestFuns :: Env0 -> String -> Suite -> [[Assoc]]\ntestFuns env modName ss = tF ss [] [] [] [] []\n  where\n    tF (With _ _ ss' : ss) uts ssts sts ats ets = tF (ss' ++ ss) uts ssts sts ats ets\n    tF (Decl l (d@Def{}:ds) : ss) uts ssts sts ats ets\n      | isTestName (dname d) =\n          case testType (findQName (NoQ (dname d)) env) of\n            Just UnitTest ->\n              tF (Decl l ds : ss) (mkAssoc d (name \"UnitTest\") modName : uts) ssts sts ats ets\n            Just SimpleSyncTest ->\n              tF (Decl l ds : ss) uts (mkAssoc d (name \"SimpleSyncTest\") modName : ssts) sts ats ets\n            Just SyncTest ->\n              tF (Decl l ds : ss) uts ssts (mkAssoc d (name \"SyncTest\") modName : sts) ats ets\n            Just AsyncTest ->\n              tF (Decl l ds : ss) uts ssts sts (mkAssoc d (name \"AsyncTest\") modName : ats) ets\n            Just EnvTest ->\n              tF (Decl l ds : ss) uts ssts sts ats (mkAssoc d (name \"EnvTest\") modName : ets)\n            Nothing -> tF (Decl l ds : ss) uts ssts sts ats ets\n    -- Don't discover actors here - they're handled via wrapper generation\n    tF (Decl l (_:ds) : ss) uts ssts sts ats ets = tF (Decl l ds : ss) uts ssts sts ats ets\n    tF (Decl _ [] : ss) uts ssts sts ats ets = tF ss uts ssts sts ats ets\n    tF (_ : ss) uts ssts sts ats ets = tF ss uts ssts sts ats ets\n    tF [] uts ssts sts ats ets = [reverse uts, reverse ssts, reverse sts, reverse ats, reverse ets]\n\nisTestName n                             = take 6 (nstr n) == \"_test_\"\n\n-- Generate wrapper functions for test actors\ngenTestActorWrappers :: Suite -> (TEnv, Suite)\ngenTestActorWrappers ss =\n    let testActors = findTestActors ss\n        existingFunctions = collectFunctionNames ss\n        wrappers = mapMaybe (genWrapper existingFunctions) testActors\n    in unzip wrappers\n  where\n    -- Find actors that are test actors (either with testing params or _test_ prefix)\n    findTestActors :: Suite -> [Decl]\n    findTestActors = go []\n      where\n        go actors [] = actors\n        go actors (Decl _ ds : rest) =\n            go (actors ++ filter isTestActor ds) rest\n        go actors (With _ [] ss : rest) =\n            go actors (ss ++ rest)\n        go actors (_ : rest) = go actors rest\n\n    isTestActor (Actor _ n _ ppar kpar _ _) =\n        checkTestActorParams ppar kpar || (isTestName n && ppar == PosNIL && kpar == KwdNIL)\n    isTestActor _ = False\n\n    checkTestActorParams PosNIL (KwdPar _ (Just t) _ KwdNIL) =\n        t == tCon (TC (gname [name \"testing\"] (name \"SyncT\")) []) ||\n        t == tCon (TC (gname [name \"testing\"] (name \"AsyncT\")) []) ||\n        t == tCon (TC (gname [name \"testing\"] (name \"EnvT\")) [])\n    checkTestActorParams (PosPar _ (Just t) _ PosNIL) KwdNIL =\n        t == tCon (TC (gname [name \"testing\"] (name \"SyncT\")) []) ||\n        t == tCon (TC (gname [name \"testing\"] (name \"AsyncT\")) []) ||\n        t == tCon (TC (gname [name \"testing\"] (name \"EnvT\")) [])\n    checkTestActorParams _ _ = False\n\n    -- Collect all function names to check for conflicts\n    collectFunctionNames :: Suite -> [Name]\n    collectFunctionNames = go []\n      where\n        go names [] = names\n        go names (Decl _ ds : rest) = go (names ++ mapMaybe getFuncName ds) rest\n        go names (_ : rest) = go names rest\n        getFuncName (Def _ n _ _ _ _ _ _ _ _) = Just n\n        getFuncName _ = Nothing\n\n    -- Generate a wrapper function for a test actor if needed\n    genWrapper :: [Name] -> Decl -> Maybe ((Name,NameInfo), Stmt)\n    genWrapper existingFuncs (Actor _ actorName _ ppar kpar _ _) =\n        let tParam = name \"t\"\n            paramType = getActorParamType ppar kpar\n            -- actor Foo(t: testing.AsyncT)           -> _test_Foo\n            -- actor _test_Foo(t: testing.AsyncT)     -> _test_Foo_wrapper\n            wrapperName = if \"_test_\" `isPrefixOf` nstr actorName\n                          then name (nstr actorName ++ \"_wrapper\")\n                          else name (\"_test_\" ++ nstr actorName)\n            checkName = case paramType of\n                          Nothing | isTestName actorName && ppar == PosNIL && kpar == KwdNIL ->\n                            name (nstr actorName ++ \"_wrapper\")\n                          _ -> wrapperName\n        in if checkName `elem` existingFuncs\n           then Nothing  -- Wrapper / test function already exists, don't generate\n           else case paramType of\n                Just pType ->\n                    Just $ ((wrapperName, NDef (monotype $ tFun fxProc (posRow pType posNil) kwdNil tNone) NoDec Nothing),\n                            sDecl [Def NoLoc wrapperName []  -- Wrapper function with positional param\n                                        (PosPar tParam (Just pType) Nothing PosNIL)\n                                        KwdNIL\n                                        (Just (TNone NoLoc))\n                                        [Expr NoLoc (eCall (eVar actorName) [eVar tParam])]  -- Call original actor, passing parameters\n                                        NoDec\n                                        fxProc\n                                        Nothing])\n                Nothing ->\n                    -- SimpleSyncTest actor - no parameters\n                    if isTestName actorName && ppar == PosNIL && kpar == KwdNIL\n                    then\n                        Just $ ((wrapperName, NDef (monotype $ tFun fxProc posNil kwdNil tNone) NoDec Nothing),\n                                sDecl [Def NoLoc wrapperName []\n                                        PosNIL\n                                        KwdNIL\n                                        (Just (TNone NoLoc))\n                                        [Expr NoLoc (eCall (eVar actorName) [])]  -- Call original actor\n                                        NoDec\n                                        fxProc\n                                        Nothing])\n                    else Nothing\n    genWrapper _ _ = Nothing\n\n    -- Get the parameter type from actor parameters\n    getActorParamType PosNIL (KwdPar _ (Just t) _ KwdNIL) = Just t\n    getActorParamType (PosPar _ (Just t) _ PosNIL) KwdNIL = Just t\n    getActorParamType _ _ = Nothing\n\n\n\ndata TestType = UnitTest | SimpleSyncTest | SyncTest | AsyncTest | EnvTest\n                deriving (Eq,Show,Read)\n\n-- Determine test type based on function signature\ntestType (NDef (TSchema _ [] (TFun _ fx ppar kpar res)) _ _)\n                                        = case (res, fx, row2list ppar, row2list kpar) of\n                                             -- Functions with no parameters\n                                             (r, fx', [], [])  | validReturn r && (fx' == fxPure || fx' == fxMut) -> Just UnitTest\n                                             (r, fx', [], [])  | validReturn r && fx' == fxProc                   -> Just SimpleSyncTest\n                                             -- Functions with positional test parameters\n                                             (r, fx', [t], []) | t == syncT  && validReturn r                     -> Just SyncTest\n                                             (r, fx', [t], []) | t == asyncT && validReturn r                     -> Just AsyncTest\n                                             (r, fx', [t], []) | t == envT   && validReturn r                     -> Just EnvTest\n                                             -- Functions with keyword test parameters\n                                             (r, fx', [], [t]) | t == syncT  && validReturn r                     -> Just SyncTest\n                                             _                                                                    -> Nothing\n    where validReturn r                 = r == tNone || r == TNone NoLoc || r == tStr\n          syncT                         = tCon (TC (gname [name \"testing\"] (name \"SyncT\")) [])\n          asyncT                        = tCon (TC (gname [name \"testing\"] (name \"AsyncT\")) [])\n          envT                          = tCon (TC (gname [name \"testing\"] (name \"EnvT\")) [])\ntestType _                              = Nothing\n"
  },
  {
    "path": "compiler/lib/src/Acton/WitKnots.hs",
    "content": "-- Copyright (C) 2019-2021 Data Ductus AB\n--\n-- Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:\n--\n-- 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.\n--\n-- 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.\n--\n-- 3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission.\n--\n-- THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS \"AS IS\" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n--\n\n{-# LANGUAGE MultiParamTypeClasses, FlexibleInstances, FlexibleContexts #-}\nmodule Acton.WitKnots(tieWitKnots) where\n\nimport Control.Monad\nimport Data.List (nub, intersect,intersperse, isPrefixOf, partition)\nimport Data.Maybe (isJust,mapMaybe)\nimport Pretty\nimport Debug.Trace\nimport Utils\nimport Acton.Syntax\nimport Acton.Names\nimport Acton.Builtin\nimport Acton.Prim\nimport Acton.NameInfo\nimport Acton.Env\nimport Acton.Subst\nimport Acton.Transform\nimport Acton.TypeEnv\nimport Prelude hiding ((<>))\n\n\ntieWitKnots te (Decl l ds : ss) = return (te', Decl l ds' : ss)\n  where (te',ds')               = tieDeclKnots te ds\ntieWitKnots te (With _ [] b : ss)\n                                = tieWitKnots te (b ++ ss)\ntieWitKnots te (s : ss)         = do (te', ss') <- tieWitKnots te ss\n                                     return (te', s:ss')\ntieWitKnots te []               = return (te, [])\n\n\ntieDeclKnots te ds\n  | null ws                     = (te, ds)\n  | null wdeps                  = (te, ds)\n  | null cycles                 = (te, ds)\n  | null cycledeps              = (te, ds)\n  | not $ null insts            = error (\"INTERNAL: #### Witness cycles with instantiations, not yet handled:\\n\" ++ \n                                         render (nest 4 $ vcat $ map pretty insts))\n  | otherwise                   = do --trace (\"#### Local witness deps:\\n\" ++ render (nest 4 $ vcat $ map pretty wdeps)) $\n                                     --trace (\"#### Chains:\\n\" ++ render (nest 4 $ vcat $ map pretty wchains)) $\n                                     --trace (\"#### Cycles:\\n\" ++ render (nest 4 $ vcat $ map pretty cycles)) $\n                                     --trace (\"#### Cycle dependencies:\\n\" ++ render (nest 4 $ vcat $ map pretty cycledeps )) $\n                                     let ds' = map (tieknots cycledeps) ds\n                                         te' = map (addopts cycledeps) te\n                                     (te', ds')\n  where ws                      = [ n | (n,NExt{}) <- te ]\n        wexts                   = [ d | d <- ds, dname d `elem` ws ]\n        wdeps                   = map (witDeps ws) wexts\n        wchains                 = [ ch | dep <- wdeps, ch <- witChains wdeps (absToApp dep) ]\n        (cycles, insts)         = collect [] [] wchains\n        cycledeps               = analyze ws cycles\n\n\n\ndata WAbs                       = WAbs [TVar] [Name] [WApp] deriving Eq\ndata WApp                       = WApp Name [Type] [Expr] deriving Eq\ntype WChain                     = [WApp]\ntype Cut                        = (Name, [Name])\n\ninstance Pretty (Name, WAbs) where\n    pretty (w, WAbs tvs ps as)  = pretty w <> pretty_q <> parens (commaSep pretty ps) <+> text \"-->\" <+> commaSep pretty as\n      where pretty_q            = if null tvs then empty else text \"@\" <> brackets (commaSep pretty tvs)\n\ninstance Pretty WApp where\n    pretty (WApp n ts es)       = pretty n <> pretty_ts <> parens (commaSep pretty es)\n      where pretty_ts           = if null ts then empty else text \"@\" <> brackets (commaSep pretty ts)\n\ninstance Pretty WChain where\n    pretty chain                = pr chain\n      where pr [wa]             = pretty wa\n            pr (wa : was)       = pretty wa <+> text \" - - > \" <+> pr was\n\ninstance Pretty Cut where\n    pretty (hd, deps)           = pretty hd  <+> text \"<--\" <+> commaSep pretty deps\n\n\ninitMeth d                      = head [ m | Decl _ ms <- dbody d, m <- ms, dname m == initKW ]\n\nwitDeps ws d                    = (w, WAbs tvs ps as)\n  where w                       = dname d\n        as                      = nub $ [ wapp | Assign _ [PVar _ _ (Just t)] e <- dbody d, Just wapp <- [witCall ws t e] ]\n        ps                      = tail $ bound $ pos $ initMeth d\n        tvs                     = qbound $ qbinds d\n\nwitCall ws t e@Call{}\n  | Var _ (NoQ n) <- fun e,\n    n `elem` ws                 = Just (WApp n [] $ arglist (pargs e))\n  | TApp _ f tvs <- fun e,\n    Var _ (NoQ n) <- f,\n    n `elem` ws                 = Just (WApp n tvs $ arglist (pargs e))\n  where arglist (PosArg e p)    = e : arglist p\n        arglist _               = []\nwitCall ws t _                  = Nothing\n\nabsToApp (w, (WAbs tvs ps _))   = WApp w (map tVar tvs) (map eVar ps)\n \nwitChains deps a@(WApp w ts es)\n  | null deps0                  = [[a]]\n  | otherwise                   = [ a : as' | a' <- as, as' <- witChains deps1 (apply a') ]\n  where (deps0, deps1)          = partition ((==w) . fst) deps\n        WAbs vs ps as           = snd $ head deps0\n        s0                      = vs `zip` ts\n        s1                      = ps `zip` es\n        apply (WApp n ts es)    = WApp n (vsubst s0 ts) (termsubst s1 es)\n\ncollect cycles insts []         = (reverse cycles, reverse insts)\ncollect cycles insts (chain : chains)\n  | length chain <= 1           = collect cycles insts chains\n  | a_0 == a_n                  = collect (chain:cycles) insts chains         -- New unique cycle\n  | appname a_0 == appname a_n  = collect cycles (chain:insts) chains         -- Instantiated cycle\n  | otherwise                   = collect cycles insts chains\n  where a_0                     = head chain\n        a_n                     = last chain\n\nappname (WApp n _ _)            = n\n\nanalyze ws chains               = [ (n, chainOrigins n) | n <- ws ]\n  where bare                    = map (map appname) chains\n        chainLinks n            = nub [ ap | hd:tl <- bare, hd == n, ap <- init tl ]    -- Intuitive...\n        chainOrigins n          = nub [ hd | hd:tl <- bare, hd /= n, n `elem` tl ]      -- Works better as long as we're ignoring cyclic instantiations\n\n\n-- Now, for each declaration dec in ds:\n--      Let me = dname(dec)\n--      Let mydeps = depsof(me)\n--      For all d in mydeps:\n--          append W_d : ?d[Xs] to the parameters of __init__, where Xs are dec's generics\n--      For each top level assignment v : t = d@[ts](es) in dec:\n--          If d is me and me is in cyclic:\n--              Replace rhs with  W_self\n--          Else:\n--              For each x in depsof(d), append to the rhs arguments:\n--                  W_self  if x is me\n--                  W_x     if x is in mydeps\n--                  None    otherwise\n--              if d is in mydeps:\n--                  Prefix the rhs with  W_d if W_d is not None else ...\n\ndepsof w cycledeps              = case lookup w cycledeps of\n                                    Just deps -> deps\n                                    _ -> []\n\n\naddopts cycledeps (n, NExt q c us te _ doc)\n                                = --trace (\"#### Extending \" ++ prstr n ++ \" with opts \" ++ prstrs opts) $\n                                  (n, NExt q c us te opts doc)\n  where opts                    = depsof n cycledeps\naddopts cycledeps ni            = ni\n\n\ntieknots cycledeps dec          = dec{ dbody = map tie (dbody dec) }\n  where\n    me                          = dname dec\n    mydeps                      = depsof me cycledeps\n    generics                    = qbound (qbinds dec)\n    cyclic                      = (`elem` (dom cycledeps))\n\n    tie (Decl l ds)             = Decl l (map tieI ds)\n    tie s@Assign{}              = s{ expr = tieE (expr s) }\n    tie s                       = s\n\n    tieI d@Def{}\n      | dname d == initKW       = d{ pos = ap (pos d) }\n      where ap (PosPar n t e p) = PosPar n t e (ap p)\n            ap (PosNIL)         = foldr depParam PosNIL mydeps\n    tieI d                      = d\n\n    tieE e@Call{fun=Var _ (NoQ n)}\n                                = tieCall n e\n    tieE e@Call{fun=TApp _ (Var _ (NoQ n)) _}\n                                = tieCall n e\n    tieE e                      = e\n    \n    tieCall n e@Call{}\n      | n == me && cyclic me    = eVar selfKW'\n      | n `elem` mydeps         = depKnot n e'\n      | otherwise               = e'\n      where e'                  = e{ pargs = ap (pargs e)}\n            ap (PosArg e p)     = PosArg e (ap p)\n            ap (PosNil)         = foldr extra PosNil (depsof n cycledeps)\n            extra x\n              | x == me         = PosArg (eVar selfKW')\n              | x `elem` mydeps = PosArg (eVar $ depVar x)\n              | otherwise       = PosArg eNone\n    tieCall n e                 = e\n\n    depVar n                    = witAttr (NoQ n)\n\n    depType n                   = tCon (TC (NoQ n) (map tVar generics))\n\n    depParam n                  = PosPar n' (Just $ tOpt t) Nothing\n      where t                   = depType n\n            n'                  = depVar n\n\n    depKnot n                   = eCond (eCAST (tOpt t) t $ eVar n') (eCall (tApp (eQVar primISNOTNONE) [t]) [eVar n'])\n      where t                   = depType n\n            n'                  = depVar n"
  },
  {
    "path": "compiler/lib/src/InterfaceFiles.hs",
    "content": "-- Copyright (C) 2019-2021 Data Ductus AB\n--\n-- Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:\n--\n-- 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.\n--\n-- 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.\n--\n-- 3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission.\n--\n-- THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS \"AS IS\" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n--\n\n{-# LANGUAGE DeriveGeneric #-}\n-- Acton Interface (.ty) Files\n--\n-- Purpose\n-- - Cache compiled module information so later builds can avoid unnecessary\n--   work by reading a small header instead of decoding large structures.\n-- - If a .ty cannot be decoded or the version mismatches, the caller must\n--   treat the module as out-of-date and recompile from source.\n--\n-- On-disk layout (Binary, in this exact order)\n--   1) version            :: [Int]                         -- Acton.Syntax.version\n--   2) sourceMeta         :: Maybe SourceFileMeta          -- cached source stat metadata\n--   3) moduleSrcBytesHash :: ByteString                    -- SHA-256 of raw source bytes\n--   4) modulePubHash      :: ByteString                    -- SHA-256 of public NameInfo (doc-free)\n--                                                       -- augmented with imports' pub hashes\n--   5) moduleImplHash     :: ByteString                    -- SHA-256 of per-name impl hashes\n--   6) imports            :: [(A.ModName, ByteString)]     -- imported module and pub hash used\n--   7) nameHashes         :: [NameHashInfo]                -- per-name src/pub/impl hashes + deps\n--   8) roots              :: [A.Name]                      -- root actors (e.g., main or test_main)\n--   9) tests              :: [String]                      -- discovered test names\n--  10) docstring          :: Maybe String                  -- module docstring\n--  11) nameInfo           :: I.NameInfo                    -- type/name environment\n--  12) typedModule        :: A.Module                      -- typed module\n--\n-- Rationale for ordering\n-- - Put cache validity fields first so callers can validate and reuse a cache\n--   entry without decoding the large NameInfo and typed Module sections.\n-- - Follow with the remaining module hashes used for dependency checks.\n-- - Follow with small variable fields (imports, roots, docstring).\n-- - Put heavy sections last (NameInfo, typed Module) to preserve laziness.\n\nmodule InterfaceFiles where\n\nimport Prelude hiding (readFile, writeFile)\nimport Data.Binary\nimport qualified Control.Exception as E\nimport qualified Data.Binary.Get as BinaryGet\nimport qualified Data.ByteString as BS\nimport qualified Data.ByteString.Lazy as BL\nimport qualified Acton.Syntax as A\nimport qualified Acton.NameInfo as I\nimport GHC.Generics (Generic)\nimport System.Directory (renameFile)\nimport System.IO (IOMode(ReadMode), hClose, hFileSize, openBinaryFile)\nimport System.Posix.Process (getProcessID)\n\ndata NameHashInfo = NameHashInfo\n  { nhName     :: A.Name\n  , nhSrcHash  :: BS.ByteString\n  , nhPubHash  :: BS.ByteString\n  , nhImplHash :: BS.ByteString\n  , nhPubDeps  :: [(A.QName, BS.ByteString)]\n  , nhImplDeps :: [(A.QName, BS.ByteString)]\n  } deriving (Show, Eq, Generic)\n\ninstance Binary NameHashInfo\n\ndata SourceFileMeta = SourceFileMeta\n  { sfmMTimeNs :: Integer\n  , sfmCTimeNs :: Integer\n  , sfmSize    :: Integer\n  , sfmDevice  :: Maybe Integer\n  , sfmInode   :: Maybe Integer\n  } deriving (Show, Eq, Generic)\n\ninstance Binary SourceFileMeta\n\ntype TyFile =\n  ( [A.ModName]\n  , I.NameInfo\n  , A.Module\n  , Maybe SourceFileMeta\n  , BS.ByteString\n  , BS.ByteString\n  , BS.ByteString\n  , [(A.ModName, BS.ByteString)]\n  , [NameHashInfo]\n  , [A.Name]\n  , [String]\n  , Maybe String\n  )\n\ntype TyHeader =\n  ( Maybe SourceFileMeta\n  , BS.ByteString\n  , BS.ByteString\n  , BS.ByteString\n  , [(A.ModName, BS.ByteString)]\n  , [NameHashInfo]\n  , [A.Name]\n  , [String]\n  , Maybe String\n  )\n\n-- Note: tests are stored in the header to support listing without compiling\n--       or executing test binaries.\n\nreadTyBytes :: FilePath -> IO BL.ByteString\nreadTyBytes f = do\n    h <- openBinaryFile f ReadMode\n    size <- hFileSize h\n    bs <- BS.hGet h (fromIntegral size)\n    hClose h\n    return (BL.fromStrict bs)\n\nversionMismatch :: [Int] -> IO a\nversionMismatch vs =\n    ioError (userError (\".ty version mismatch: file has \" ++ show vs ++ \", expected \" ++ show A.version))\n\nreadTyVersion :: BL.ByteString -> IO BL.ByteString\nreadTyVersion bsLazy =\n    case BinaryGet.runGetOrFail (get :: BinaryGet.Get [Int]) bsLazy of\n      Left _ -> ioError (userError \"Failed to decode .ty version\")\n      Right (rest, _, vs)\n        | vs == A.version -> return rest\n        | otherwise -> versionMismatch vs\n\ndecodeTyPrefix :: BL.ByteString -> IO (Maybe SourceFileMeta, BS.ByteString, BS.ByteString, BS.ByteString, BL.ByteString)\ndecodeTyPrefix bsLazy =\n    case BinaryGet.runGetOrFail getPrefix bsLazy of\n      Left _ -> ioError (userError \"Failed to decode .ty prefix\")\n      Right (rest, _, (sourceMeta, moduleSrcBytesHash, modulePubHash, moduleImplHash)) ->\n        return (sourceMeta, moduleSrcBytesHash, modulePubHash, moduleImplHash, rest)\n  where\n    getPrefix = do\n      sourceMeta <- get :: BinaryGet.Get (Maybe SourceFileMeta)\n      moduleSrcBytesHash <- get :: BinaryGet.Get BS.ByteString\n      modulePubHash <- get :: BinaryGet.Get BS.ByteString\n      moduleImplHash <- get :: BinaryGet.Get BS.ByteString\n      return (sourceMeta, moduleSrcBytesHash, modulePubHash, moduleImplHash)\n\nwriteFile :: FilePath -> BS.ByteString -> BS.ByteString -> BS.ByteString -> Maybe SourceFileMeta -> [(A.ModName, BS.ByteString)] -> [NameHashInfo] -> [A.Name] -> [String] -> Maybe String -> I.NameInfo -> A.Module -> IO ()\nwriteFile f moduleSrcBytesHash modulePubHash moduleImplHash sourceMeta imps nameHashes roots tests mdoc nmod tchecked = do\n    pid <- getProcessID\n    let tmpFile = f ++ \".\" ++ show pid\n    BL.writeFile tmpFile (encode ((A.version, sourceMeta, moduleSrcBytesHash, modulePubHash, moduleImplHash), imps, nameHashes, roots, tests, mdoc, nmod, tchecked))\n    renameFile tmpFile f\n\nreadFile :: FilePath -> IO TyFile\nreadFile f = do\n    bsLazy <- readTyBytes f\n    body0 <- readTyVersion bsLazy\n    (sourceMeta, moduleSrcBytesHash, modulePubHash, moduleImplHash, body1) <- decodeTyPrefix body0\n    let getBody = do\n          imps <- get :: BinaryGet.Get [(A.ModName, BS.ByteString)]\n          nameHashes <- get :: BinaryGet.Get [NameHashInfo]\n          roots <- get :: BinaryGet.Get [A.Name]\n          tests <- get :: BinaryGet.Get [String]\n          mdoc <- get :: BinaryGet.Get (Maybe String)\n          nmod <- get :: BinaryGet.Get I.NameInfo\n          tmod <- get :: BinaryGet.Get A.Module\n          return (imps, nameHashes, roots, tests, mdoc, nmod, tmod)\n    case BinaryGet.runGetOrFail getBody body1 of\n      Left _ -> ioError (userError \"Failed to decode .ty file\")\n      Right (_, _, (imps, nameHashes, roots, tests, mdoc, nmod, tmod)) ->\n        return (map fst imps, nmod, tmod, sourceMeta, moduleSrcBytesHash, modulePubHash, moduleImplHash, imps, nameHashes, roots, tests, mdoc)\n\n-- Read only the cached header fields from .ty: source metadata, module hashes,\n-- imports, name hashes, roots, tests, and docstring.\n-- This avoids decoding the large NameInfo and typed Module sections and is\n-- much faster than readFile for freshness checks and dependency discovery.\nreadHeader :: FilePath -> IO TyHeader\nreadHeader f = do\n    bsLazy <- readTyBytes f\n    body0 <- readTyVersion bsLazy\n    (sourceMeta, moduleSrcBytesHash, modulePubHash, moduleImplHash, body1) <- decodeTyPrefix body0\n    let getHdr = do\n          imps  <- get :: BinaryGet.Get [(A.ModName, BS.ByteString)]\n          nameHashes <- get :: BinaryGet.Get [NameHashInfo]\n          roots <- get :: BinaryGet.Get [A.Name]\n          tests <- get :: BinaryGet.Get [String]\n          doc   <- get :: BinaryGet.Get (Maybe String)\n          return (imps, nameHashes, roots, tests, doc)\n    case BinaryGet.runGetOrFail getHdr body1 of\n      Left _ -> ioError (userError \"Failed to decode .ty header\")\n      Right (_, _, (imps, nameHashes, roots, tests, doc)) ->\n        return (sourceMeta, moduleSrcBytesHash, modulePubHash, moduleImplHash, imps, nameHashes, roots, tests, doc)\n\n-- Interface files are caches for most callers. If a file is missing,\n-- unreadable, corrupt, or from a different compiler interface version, the\n-- cache entry is not usable.\nreadFileMaybe :: FilePath -> IO (Maybe TyFile)\nreadFileMaybe = readTyMaybe readFile\n\nreadHeaderMaybe :: FilePath -> IO (Maybe TyHeader)\nreadHeaderMaybe = readTyMaybe readHeader\n\nreadTyMaybe :: (FilePath -> IO a) -> FilePath -> IO (Maybe a)\nreadTyMaybe readTy f = (Just <$> readTy f) `E.catch` tyCacheMiss\n\ntyCacheMiss :: E.IOException -> IO (Maybe a)\ntyCacheMiss _ = return Nothing\n"
  },
  {
    "path": "compiler/lib/src/Pretty.hs",
    "content": "{-# LANGUAGE TypeSynonymInstances, FlexibleInstances #-}\n-----------------------------------------------------------------------------\n-- |\n-- Module      : Language.Python.Common.Pretty\n-- Copyright   : (c) 2009 Bernie Pope \n-- License     : BSD-style\n-- Maintainer  : bjpop@csse.unimelb.edu.au\n-- Stability   : experimental\n-- Portability : ghc\n--\n-- Convenience class for pretty printing combinators.\n-----------------------------------------------------------------------------\n\nmodule Pretty (module TextPP, module Pretty) where\n\nimport Text.PrettyPrint as TextPP\n\n--------------------------------------------------------------------------------\n\ninfixl 5 $++$\n\na $++$ b    = a $+$ blank $+$ b\n\n\nprint x     = render $ pretty x\n\nvprint x    = render $ vpretty x\n\nvpretty x   = vcat $ punctuate (text \"\\n\") $ map pretty x\n\n\n-- | All types which can be transformed into a 'Doc'.\nclass Pretty a where\n   pretty :: a -> Doc\n\n-- | Transform values into strings.\nprettyText :: Pretty a => a -> String\nprettyText = render . pretty\n\n-- | Print just the prefix of something\nprettyPrefix :: Pretty a => Int -> a -> Doc\nprettyPrefix maxLen x\n   | length fullText <= maxLen = pretty fullText\n   | otherwise = pretty (take maxLen fullText) <+> text \"...\" \n   where\n   fullText = prettyText x \n\ninstance Pretty String where\n   pretty s = text s\n\n{-\nThis is not used in Acton compiler, so we reuse the name for the following function, which we have use for.\n\n-- | Conditionally wrap parentheses around an item.\nparensIf :: Pretty a => (a -> Bool) -> a -> Doc\nparensIf test x = if test x then parens $ pretty x else pretty x \n-}\n\nparensIf :: Bool -> Doc -> Doc\nparensIf b e = if b then parens e else e\n\n\nperhaps :: Pretty a => Maybe a -> Doc -> Doc\nperhaps Nothing doc = empty\nperhaps (Just {}) doc = doc \n\ndot = char '.'\n\nblank = text \"\"\n\n-- | A list of things separated by dots (and no spaces).\ndotCat :: (a -> Doc) -> [a] -> Doc\ndotCat f = hcat . punctuate dot . map f\n\n-- | A list of things separated by commas.\ncommaSep :: (a -> Doc) -> [a] -> Doc\ncommaSep f = hsep . punctuate comma . map f\n\ncommaCat :: Pretty a => [a] -> Doc\ncommaCat = hcat . punctuate comma . map pretty\n\ncommaList :: Pretty a => [a] -> Doc\ncommaList = commaSep pretty \n\ncommaIf :: [a] -> Doc\ncommaIf [] = empty\ncommaIf _  = comma\n\n-- | A list of things separated by equals signs.\nequalsList :: Pretty a => [a] -> Doc\nequalsList = hsep . punctuate (space TextPP.<> equals) . map pretty\n\nvmap :: (a -> Doc) -> [a] -> Doc\nvmap f = vcat . map f\n\nnonEmpty :: (Doc -> Doc) -> (t -> Doc) -> t -> Doc\nnonEmpty f g x\n  | isEmpty doc = doc\n  | otherwise = f doc\n  where doc = g x\n\nprettyPair :: (Pretty a, Pretty b) => String -> (a, b) -> Doc\nprettyPair str (a, b) = pretty a <+> nonEmpty (text str <+>) pretty b\n\n\ninstance Pretty Int where\n  pretty = int\n\ninstance Pretty Integer where\n  pretty = integer\n\ninstance Pretty Double where\n   pretty = double\n\ninstance Pretty Bool where\n  pretty True = text \"True\"\n  pretty False = text \"False\"\n\ninstance Pretty a => Pretty (Maybe a) where\n   pretty Nothing = empty\n   pretty (Just x) = pretty x\n"
  },
  {
    "path": "compiler/lib/src/SrcLocation.hs",
    "content": "{-# LANGUAGE DeriveDataTypeable, DeriveGeneric #-}\n-----------------------------------------------------------------------------\n-- |\n-- Module      : Language.Python.Common.SrcLocation \n-- Copyright   : (c) 2009 Bernie Pope \n-- License     : BSD-style\n-- Maintainer  : bjpop@csse.unimelb.edu.au\n-- Stability   : experimental\n-- Portability : ghc\n--\n-- Source location information for the Python lexer and parser. This module\n-- provides single-point locations and spans, and conversions between them.\n-----------------------------------------------------------------------------\n\nmodule SrcLocation (\n  -- * Construction \n  SrcLocation (..),\n  SrcSpan (..),\n  Span (..),\n  spanning,\n  (><),\n  mkSrcSpan,\n  combineSrcSpans,\n  initialSrcLocation,\n  spanStartPoint,\n  -- * Modification\n  incColumn, \n  decColumn,\n  incLine,\n  incTab,\n  -- * Projection of components of a span\n  spanFile,\n  endCol,\n  endRow,\n  startCol,\n  startRow,\n  showLine\n) where\n\nimport Pretty\nimport Data.Data\nimport Debug.Trace\nimport qualified Data.Binary\nimport GHC.Generics (Generic)\nimport Prelude hiding((<>))\n\n-- | A location for a syntactic entity from the source code.\n-- The location is specified by its filename, and starting row\n-- and column. \ndata SrcLocation = \n   Sloc { sloc_filename :: !String\n        , sloc_row :: {-# UNPACK #-} !Int\n        , sloc_column :: {-# UNPACK #-} !Int \n        } \n   | NoLocation\n   deriving (Eq,Ord,Show,Typeable,Data)\n\ninstance Pretty SrcLocation where\n   pretty = pretty . getSpan\n\n-- | Types which have a span.\nclass Span a where\n   getSpan :: a -> SrcSpan\n   getSpan x = SpanEmpty\n\n-- | Create a new span which encloses two spanned things.\nspanning :: (Span a, Span b) => a -> b -> SrcSpan\nspanning x y = combineSrcSpans (getSpan x) (getSpan y)\n\ninfixr 7 ><\n(><) :: (Span a, Span b) => a -> b -> SrcSpan\na >< b = spanning a b\n\n\ninstance Span a => Span [a] where\n   getSpan [] = SpanEmpty\n   getSpan [x] = getSpan x \n   getSpan list@(x:xs) = combineSrcSpans (getSpan x) (getSpan (last list))\n\ninstance Span a => Span (Maybe a) where\n   getSpan Nothing = SpanEmpty\n   getSpan (Just x) = getSpan x\n\ninstance (Span a, Span b) => Span (Either a b) where\n   getSpan (Left x) = getSpan x\n   getSpan (Right x) = getSpan x\n\ninstance (Span a, Span b) => Span (a, b) where\n   getSpan (x,y) = spanning x y\n\ninstance Span SrcSpan where\n   getSpan = id\n\n-- | Construct the initial source location for a file.\ninitialSrcLocation :: String -> SrcLocation\ninitialSrcLocation filename \n    = Sloc \n      { sloc_filename = filename\n      , sloc_row = 1\n      , sloc_column = 1\n      }\n\n-- | Decrement the column of a location, only if they are on the same row.\ndecColumn :: Int -> SrcLocation -> SrcLocation\ndecColumn n loc\n   | n < col = loc { sloc_column = col - n }\n   | otherwise = loc \n   where\n   col = sloc_column loc\n\n-- | Increment the column of a location. \nincColumn :: Int -> SrcLocation -> SrcLocation\nincColumn n loc@(Sloc { sloc_column = col })\n   = loc { sloc_column = col + n }\n\n-- | Increment the column of a location by one tab stop.\nincTab :: SrcLocation -> SrcLocation\nincTab loc@(Sloc { sloc_column = col })\n   = loc { sloc_column = newCol } \n   where\n   newCol = col + 8 - (col - 1) `mod` 8\n\n-- | Increment the line number (row) of a location by one.\nincLine :: Int -> SrcLocation -> SrcLocation\nincLine n loc@(Sloc { sloc_row = row }) \n   = loc { sloc_column = 1, sloc_row = row + n }\n\n{-\nInspired heavily by compiler/basicTypes/SrcLoc.lhs \nA SrcSpan delimits a portion of a text file.  \n-}\n\n-- | Source location spanning a contiguous section of a file.\ndata SrcSpan\n    -- | A span which starts and ends on the same line.\n  = SpanCoLinear\n    { span_filename     :: !String\n    , span_row          :: {-# UNPACK #-} !Int\n    , span_start_column :: {-# UNPACK #-} !Int\n    , span_end_column   :: {-# UNPACK #-} !Int\n    }\n    -- | A span which starts and ends on different lines.\n  | SpanMultiLine\n    { span_filename     :: !String\n    , span_start_row    :: {-# UNPACK #-} !Int\n    , span_start_column :: {-# UNPACK #-} !Int\n    , span_end_row      :: {-# UNPACK #-} !Int\n    , span_end_column   :: {-# UNPACK #-} !Int\n    }\n    -- | A span which is actually just one point in the file.\n  | SpanPoint\n    { span_filename :: !String\n    , span_row      :: {-# UNPACK #-} !Int\n    , span_column   :: {-# UNPACK #-} !Int\n    }\n    -- | No span information.\n  | SpanNested\n    { span_outer :: !SrcSpan\n    , span_inner :: !SrcSpan\n    }\n  | SpanEmpty \n   deriving (Eq,Ord,Typeable,Data,Read,Show,Generic)\n\ninstance Data.Binary.Binary SrcSpan\n\n{-\ninstance Show SrcSpan where\n    show _ = \"_\"\n\ninstance Read SrcSpan where\n    readsPrec p (' ':s)  = readsPrec p s\n    readsPrec p ('\\t':s) = readsPrec p s\n    readsPrec p ('\\n':s) = readsPrec p s\n    readsPrec _ ('_':s)  = [(SpanEmpty,s)]\n    readsPrec _ s        = []\n-}\n\ninstance Pretty SrcSpan where\n   pretty span@(SpanCoLinear {}) = prettyMultiSpan span\n   pretty span@(SpanMultiLine {}) = prettyMultiSpan span\n   pretty span@(SpanPoint {})\n      = text (span_filename span) <> colon <+>\n        parens (pretty (span_row span) <> comma <> pretty (span_column span))\n   pretty SpanNested{span_outer=o, span_inner=i} = pretty o <+> text \"referencing\" $$ pretty i\n   pretty SpanEmpty = empty\n\nprettyMultiSpan :: SrcSpan -> Doc \nprettyMultiSpan span \n  = text (spanFile span) <> colon <+>\n    parens (pretty (startRow span) <> comma <> pretty (startCol span)) <> char '-' <>\n    parens (pretty (endRow span) <> comma <> pretty (endCol span))\n\ninstance Span SrcLocation where\n   getSpan loc@(Sloc {})\n      = SpanPoint \n        { span_filename = sloc_filename loc\n        , span_row = sloc_row loc\n        , span_column = sloc_column loc\n        }\n   getSpan NoLocation = SpanEmpty \n\n-- | Make a point span from the start of a span\nspanStartPoint :: SrcSpan -> SrcSpan\nspanStartPoint SpanEmpty = SpanEmpty\nspanStartPoint span = \n   SpanPoint \n   { span_filename = spanFile span\n   , span_row = startRow span\n   , span_column = startCol span\n   }\n\n-- | Make a span from two locations. Assumption: either the\n-- arguments are the same, or the left one preceeds the right one.\nmkSrcSpan :: SrcLocation -> SrcLocation -> SrcSpan\nmkSrcSpan NoLocation _ = SpanEmpty\nmkSrcSpan _ NoLocation = SpanEmpty \nmkSrcSpan loc1 loc2\n  | line1 == line2 = \n       if col2 <= col1 \n          then SpanPoint file line1 col1\n          else SpanCoLinear file line1 col1 col2\n  | otherwise = \n       SpanMultiLine file line1 col1 line2 col2\n  where\n  line1 = sloc_row loc1\n  line2 = sloc_row loc2\n  col1 = sloc_column loc1\n  col2 = sloc_column loc2\n  file = sloc_filename loc1\n\n-- | Combines two 'SrcSpan' into one that spans at least all the characters\n-- within both spans. Assumes the \"file\" part is the same in both inputs\ncombineSrcSpans :: SrcSpan -> SrcSpan -> SrcSpan\ncombineSrcSpans SpanEmpty r = r -- this seems more useful\ncombineSrcSpans l SpanEmpty = l\ncombineSrcSpans (SpanNested o1 i1) (SpanNested o2 i2)\n  | o1 == o2 = SpanNested o1 (combineSrcSpans i1 i2)\ncombineSrcSpans (SpanNested o i) r = combineSrcSpans i r\ncombineSrcSpans l (SpanNested o i) = combineSrcSpans l i\ncombineSrcSpans start end\n = case row1 `compare` row2 of\n     EQ -> case col1 `compare` col2 of\n                EQ -> SpanPoint file row1 col1\n                LT -> SpanCoLinear file row1 col1 col2\n                GT -> SpanCoLinear file row1 col2 col1\n     LT -> SpanMultiLine file row1 col1 row2 col2\n     GT -> SpanMultiLine file row2 col2 row1 col1\n  where\n  row1 = startRow start\n  col1 = startCol start\n  row2 = endRow end\n  col2 = endCol end\n  file = spanFile start\n\nspanFile :: SrcSpan -> String\nspanFile (SpanNested o i) = spanFile o\nspanFile SpanEmpty = error \"spanFile called on empty span\"\nspanFile sp = span_filename sp\n\n-- | Get the row of the start of a span.\nstartRow :: SrcSpan -> Int\nstartRow (SpanCoLinear { span_row = row }) = row\nstartRow (SpanMultiLine { span_start_row = row }) = row\nstartRow (SpanPoint { span_row = row }) = row\nstartRow (SpanNested o i) = startRow o\nstartRow SpanEmpty = error \"startRow called on empty span\"\n\n-- | Get the row of the end of a span.\nendRow :: SrcSpan -> Int\nendRow (SpanCoLinear { span_row = row }) = row\nendRow (SpanMultiLine { span_end_row = row }) = row\nendRow (SpanPoint { span_row = row }) = row\nendRow (SpanNested o i) = endRow o\nendRow SpanEmpty = error \"endRow called on empty span\"\n\n-- | Get the column of the start of a span.\nstartCol :: SrcSpan -> Int\nstartCol (SpanCoLinear { span_start_column = col }) = col \nstartCol (SpanMultiLine { span_start_column = col }) = col \nstartCol (SpanPoint { span_column = col }) = col \nstartCol (SpanNested o i) = startCol o\nstartCol SpanEmpty = error \"startCol called on empty span\"\n\n-- | Get the column of the end of a span.\nendCol :: SrcSpan -> Int\nendCol (SpanCoLinear { span_end_column = col }) = col \nendCol (SpanMultiLine { span_end_column = col }) = col \nendCol (SpanPoint { span_column = col }) = col \nendCol (SpanNested o i) = endCol o\nendCol SpanEmpty = error \"endCol called on empty span\"\n\nshowLine :: SrcSpan -> String\nshowLine (SpanNested o i)   = showLine o ++ \"->\" ++ showLine i\nshowLine l                  = show (startRow l)\n"
  },
  {
    "path": "compiler/lib/src/Text_Megaparsec_Expr.hs",
    "content": "-- |\n-- Module      :  Text.Megaparsec.Expr\n-- Copyright   :  © 2015–2017 Megaparsec contributors\n--                © 2007 Paolo Martini\n--                © 1999–2001 Daan Leijen\n-- License     :  FreeBSD\n--\n-- Maintainer  :  Mark Karpov <markkarpov92@gmail.com>\n-- Stability   :  experimental\n-- Portability :  non-portable\n--\n-- A helper module to parse expressions. It can build a parser given a table\n-- of operators.\n\nmodule Text_Megaparsec_Expr\n  ( Operator (..)\n  , makeExprParser )\nwhere\n\n\nimport Text.Megaparsec\n\n-- | This data type specifies operators that work on values of type @a@. An\n-- operator is either binary infix or unary prefix or postfix. A binary\n-- operator has also an associated associativity.\n\ndata Operator m a\n  = InfixN  (m (a -> a -> a)) -- ^ Non-associative infix\n  | InfixL  (m (a -> a -> a)) -- ^ Left-associative infix\n  | InfixR  (m (a -> a -> a)) -- ^ Right-associative infix\n  | Prefix  (m (a -> a))      -- ^ Prefix\n  | Postfix (m (a -> a))      -- ^ Postfix\n\n-- | @'makeExprParser' term table@ builds an expression parser for terms\n-- @term@ with operators from @table@, taking the associativity and\n-- precedence specified in the @table@ into account.\n--\n-- @table@ is a list of @[Operator m a]@ lists. The list is ordered in\n-- descending precedence. All operators in one list have the same precedence\n-- (but may have different associativity).\n--\n-- Prefix and postfix operators of the same precedence associate to the left\n-- (i.e. if @++@ is postfix increment, than @-2++@ equals @-1@, not @-3@).\n--\n-- Unary operators of the same precedence can only occur once (i.e. @--2@ is\n-- not allowed if @-@ is prefix negate). If you need to parse several prefix\n-- or postfix operators in a row, (like C pointers—@**i@) you can use this\n-- approach:\n--\n-- > manyUnaryOp = foldr1 (.) <$> some singleUnaryOp\n--\n-- This is not done by default because in some cases allowing repeating\n-- prefix or postfix operators is not desirable.\n--\n-- If you want to have an operator that is a prefix of another operator in\n-- the table, use the following (or similar) wrapper instead of plain\n-- 'Text.Megaparsec.Char.Lexer.symbol':\n--\n-- > op n = (lexeme . try) (string n <* notFollowedBy punctuationChar)\n--\n-- 'makeExprParser' takes care of all the complexity involved in building an\n-- expression parser. Here is an example of an expression parser that\n-- handles prefix signs, postfix increment and basic arithmetic:\n--\n-- > expr = makeExprParser term table <?> \"expression\"\n-- >\n-- > term = parens expr <|> integer <?> \"term\"\n-- >\n-- > table = [ [ prefix  \"-\"  negate\n-- >           , prefix  \"+\"  id ]\n-- >         , [ postfix \"++\" (+1) ]\n-- >         , [ binary  \"*\"  (*)\n-- >           , binary  \"/\"  div  ]\n-- >         , [ binary  \"+\"  (+)\n-- >           , binary  \"-\"  (-)  ] ]\n-- >\n-- > binary  name f = InfixL  (f <$ symbol name)\n-- > prefix  name f = Prefix  (f <$ symbol name)\n-- > postfix name f = Postfix (f <$ symbol name)\n\nmakeExprParser :: MonadParsec e s m\n  => m a               -- ^ Term parser\n  -> [[Operator m a]]  -- ^ Operator table, see 'Operator'\n  -> m a               -- ^ Resulting expression parser\nmakeExprParser = foldl addPrecLevel\n{-# INLINEABLE makeExprParser #-}\n\n-- | @addPrecLevel p ops@ adds the ability to parse operators in table @ops@\n-- to parser @p@.\n\naddPrecLevel :: MonadParsec e s m => m a -> [Operator m a] -> m a\naddPrecLevel term ops =\n  term' >>= \\x -> choice [ras' x, las' x, nas' x, return x] <?> \"operator\"\n  where (ras, las, nas, prefix, postfix) = foldr splitOp ([],[],[],[],[]) ops\n        term' = pTerm (choice prefix) term (choice postfix)\n        ras'  = pInfixR (choice ras) term'\n        las'  = pInfixL (choice las) term' \n        nas'  = pInfixN (choice nas) term'\n\n-- | @pTerm prefix term postfix@ parses a @term@ surrounded by optional\n-- prefix and postfix unary operators. Parsers @prefix@ and @postfix@ are\n-- allowed to fail, in this case 'id' is used.\n\npTerm :: MonadParsec e s m => m (a -> a) -> m a -> m (a -> a) -> m a\npTerm prefix term postfix = do\n  pre  <- option id (hidden prefix)\n  x    <- term\n  post <- option id (hidden postfix)\n  return . post . pre $ x\n\n \n-- | @pInfixN op p x@ parses non-associative infix operator @op@, then term\n-- with parser @p@, then returns result of the operator application on @x@\n-- and the term.\n\npInfixN :: MonadParsec e s m => m (a -> a -> a) -> m a -> a -> m a\npInfixN op p x = do\n  f <- op\n  y <- p\n  return $ f x y\n <?> \"operator\"\n \n-- | @pInfixL op p x@ parses left-associative infix operator @op@, then term\n-- with parser @p@, then returns result of the operator application on @x@\n-- and the term.\n\npInfixL :: MonadParsec e s m => m (a -> a -> a) -> m a -> a -> m a\npInfixL op p x = do\n  f <- op\n  y <- p\n  let r = f x y\n  pInfixL op p r <|> return r\n <?> \"operator\"\n \n-- | @pInfixR op p x@ parses right-associative infix operator @op@, then\n-- term with parser @p@, then returns result of the operator application on\n-- @x@ and the term.\n\npInfixR :: MonadParsec e s m => m (a -> a -> a) -> m a -> a -> m a\npInfixR op p x = do\n  f <- op\n  y <- p >>= \\r -> pInfixR op p r <|> return r\n  return $ f x y\n <?> \"operator\"\n \ntype Batch m a =\n  ( [m (a -> a -> a)]\n  , [m (a -> a -> a)]\n  , [m (a -> a -> a)]\n  , [m (a -> a)]\n  , [m (a -> a)] )\n\n-- | A helper to separate various operators (binary, unary, and according to\n-- associativity) and return them in a tuple.\n\nsplitOp :: Operator m a -> Batch m a -> Batch m a\nsplitOp (InfixR  op) (r, l, n, pre, post) = (op:r, l, n, pre, post)\nsplitOp (InfixL  op) (r, l, n, pre, post) = (r, op:l, n, pre, post)\nsplitOp (InfixN  op) (r, l, n, pre, post) = (r, l, op:n, pre, post)\nsplitOp (Prefix  op) (r, l, n, pre, post) = (r, l, n, op:pre, post)\nsplitOp (Postfix op) (r, l, n, pre, post) = (r, l, n, pre, op:post)"
  },
  {
    "path": "compiler/lib/src/Utils.hs",
    "content": "-- Copyright (C) 2019-2021 Data Ductus AB\n--\n-- Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:\n--\n-- 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.\n--\n-- 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.\n--\n-- 3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission.\n--\n-- THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS \"AS IS\" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n--\n\n{-# LANGUAGE DeriveDataTypeable, DeriveGeneric, DeriveAnyClass #-}\nmodule Utils(module Utils, module SrcLocation, module Data.List, module Data.Maybe, module Debug.Trace) where\n\nimport Debug.Trace\nimport Data.List hiding ((\\\\))\nimport Data.Maybe\nimport qualified Data.Binary\nimport qualified Control.Exception\nimport Data.Typeable\nimport GHC.Generics (Generic)\nimport SrcLocation\nimport Pretty\nimport Control.DeepSeq\nimport Prelude hiding((<>))\nimport System.Directory (renameFile, removeFile)\nimport System.FilePath (takeDirectory, takeFileName)\nimport System.IO (openTempFile, hSetEncoding, utf8, hPutStr, hClose)\nimport System.IO.Error (catchIOError)\n\ndata SrcLoc                     = Loc Int Int | NoLoc deriving (Eq,Ord,Show,Read,Generic,NFData)\n\ninstance Data.Binary.Binary SrcLoc where\n    put NoLoc                    = Data.Binary.put False\n    put (Loc l r)                = Data.Binary.put True >> Data.Binary.put l >> Data.Binary.put r\n    get                          = do\n        hasLoc <- Data.Binary.get\n        if hasLoc\n            then Loc <$> Data.Binary.get <*> Data.Binary.get\n            else return NoLoc\n\ninstance Pretty SrcLoc where\n    pretty (Loc l r)            = pretty l <> text \"-\" <> pretty r\n    pretty NoLoc                = text \"??\"\n\nLoc i _ `upto` Loc _ j          = Loc i j\nNoLoc `upto` l                  = l\nl `upto` NoLoc                  = l\n\nlocAfter (Loc _ j)              = Loc j j\n\ngetLoc []                       = NoLoc\ngetLoc (NoLoc : ls)             = getLoc ls\ngetLoc (l : _)                  = l\n                                    \nclass HasLoc a where\n    loc                         :: a -> SrcLoc\n\ninstance HasLoc SrcLoc where\n    loc                         = id\n\ninstance HasLoc a => HasLoc [a] where\n    loc                         = foldl (\\l x -> l `upto` loc x) NoLoc\n\ninstance HasLoc a => HasLoc (Maybe a) where\n    loc                         = maybe NoLoc loc\n\ninstance (HasLoc a, HasLoc b) => HasLoc (a,b) where\n    loc (a,b)                   = loc a `upto` loc b\n\nxs \\\\ ys                        = [ x | x <- xs, x `notElem` ys ]       -- remove *all* occurrences of xs elements from ys\n\nduplicates []                   = []\nduplicates (x:xs)               = eqs ++ duplicates others\n  where (eqs,others)            = partition (==x) xs\n\ndom                             = map fst\n\nrng                             = map snd\n\nkvs `exclude` ks                = filter ((`notElem` ks) . fst) kvs\n\nkvs `restrict` ks               = filter ((`elem` ks) . fst) kvs\n\nmapFst f xs                     = [ (f a, b) | (a,b) <- xs ]\n\nmapSnd f xs                     = [ (a, f b) | (a,b) <- xs ]\n\ncatLeft xs                      = [ x | Left x <- xs ]\n\ncatRight xs                     = [ x | Right x <- xs ]\n\nl0                              = NoLoc\n\nignore t                        = return ()\n\nprstr x                         = render (pretty x)\n\nprstrs xs                       = render (hsep $ punctuate comma (map pretty xs))\n\nprcat xs                        = render (vcat $ (map pretty xs))\n\ntraceF f x                      = trace (f x) x\n\ntr s f x                        = trace (s ++ \": \" ++ prstr x) $ f x\n\nptrace doc                      = trace (render doc)\n\nptraceM doc                     = traceM (render doc)\n\nptraceF f                       = traceF (render . f)\n\nhead_ tag []                    = error (\"Prelude.head: empty list (\" ++ show tag ++ \")\")\nhead_ tag xs                    = head xs\n\nerrSep                          =  '\\n' : concat (replicate 40 \"- \") ++ \"\\n\"\n\nerrReport ((SpanCoLinear file row start end,msg) : ps) src\n                                = unlines [\"\",line2,line3,line4,msg] ++ errReport ps src\n  where rowstr                  = show row\n        --line1                   = file ++ \" \"++show row++\":\"++show start++\"-\"++show end\n        line2                   = replicate (length rowstr+1) ' '++\"|\"\n        line3                   = rowstr ++ \" |\" ++ lines(src)!!!(row-1)\n        line4                   = replicate (length rowstr+1) ' '++\"|\"++replicate (start-1) ' '++replicate (end-start+1) '^'\nerrReport ((SpanMultiLine file srow scol erow ecol,msg) : ps) src\n                                = unlines (line2:quote++(if erow-srow<=2 then [] else [replicate (length erowstr) ' ' ++ \" | ...\"])++[line2,msg]) ++ errReport ps src\n  where erowstr                 = show erow\n        --line1                   = file ++ \" \"++show srow++\":\"++show scol++\"-\"++show erow++\":\"++show ecol\n        line2                   = replicate (length erowstr+1) ' '++\"|\"\n        pad n                   = replicate (length erowstr - length nstr) ' ' ++ nstr\n          where nstr            = show n\n        quote                   = map line [srow..minimum [srow+2,erow,length ls]]\n        ls                      = lines src\n        line n                  = pad n ++ \" |\" ++ ls!!!(n-1)\nerrReport ((SpanPoint file row col,msg) : ps) src\n                                = unlines [line2,line3,line4,msg] ++ errReport ps src\n  where rowstr                  = show row\n        --line1                   = file ++ \" \"++show row++\":\"++show col\n        line2                   = replicate (length rowstr+1) ' '++\"|\"\n        line3                   = rowstr ++ \" |\" ++ lines src!!!(row-1)\n        line4                   = replicate (length rowstr+1) ' '++\"|\"++replicate (col-1) ' '++\"^\"\nerrReport ((SpanEmpty,msg) : ps) src = '\\n' : msg ++ errReport ps src\nerrReport [] _                  = errSep\n\nlst !!! ix | ix >= length lst   = lst !! 0\n           | otherwise          = lst !! ix\n\n---------------------------------\n\ndata GeneralError               = InternalErr SrcLoc Doc\n                                | NotYet SrcLoc Doc\n                                deriving (Eq,Show,Typeable)\n\ninstance Control.Exception.Exception GeneralError\n\ninstance HasLoc GeneralError where\n    loc (InternalErr l doc)     = l\n    loc (NotYet l doc)          = l\n\ninternal loc x                  = Control.Exception.throw $ InternalErr loc (pretty x)\nnotYet loc x                    = Control.Exception.throw $ NotYet loc (pretty x)\n\ngeneralError err                = [(loc err,render (expl err))]\n  where\n    expl (InternalErr _ doc)    = text \"(internal)\" <+> doc\n    expl (NotYet _ doc)         = text \"Not yet supported:\" <+> doc\n\niff True m                      = m >> return ()\niff False _                     = return ()\n\n-- | Write a UTF-8 text file atomically (temp file + rename).\n-- Keeps readers from observing partial writes of generated artifacts.\nwriteFileUtf8Atomic :: FilePath -> String -> IO ()\nwriteFileUtf8Atomic path contents =\n    Control.Exception.bracketOnError\n      (openTempFile dir template)\n      (\\(tmp, h) -> do\n          catchIOError (hClose h) (\\_ -> return ())\n          catchIOError (removeFile tmp) (\\_ -> return ()))\n      (\\(tmp, h) -> do\n          hSetEncoding h utf8\n          hPutStr h contents\n          hClose h\n          renameFile tmp path)\n  where\n    dir = takeDirectory path\n    template = takeFileName path ++ \".tmp\"\n"
  },
  {
    "path": "compiler/lib/test/1-parse/docstrings.input",
    "content": "\"\"\"Test module for docstring functionality with {braces}.\"\"\"\nimport math\ndef test_function (x : int) -> int:\n    \"\"\"Test function with docstring.\"\"\"\n    return x * 2\n\ndef no_docstring_function (x : int) -> int:\n    return x * 3\n\n# recursive group:\nclass TestClass:\n    \"\"\"Test class with docstring.\"\"\"\n    def method (self, x : int) -> int:\n        return x + 1\nactor TestActor (name : str):\n    \"\"\"Test actor with docstring.\"\"\"\n    var name = name\nprotocol TestProtocol:\n    \"\"\"Test protocol with docstring.\"\"\"\n    test_method : (int) -> int\nextension TestClass (TestProtocol):\n    \"\"\"Extension with docstring.\"\"\"\n    def test_method (self, x : int) -> int:\n        return x * 10\n# (recursive group)\n\ndef function_with_non_first_string (x : int) -> int:\n    y = x + 1\n    \"Not a docstring\"\n    return y\n\ndef function_with_multiple_strings (x : int) -> int:\n    \"\"\"First string is docstring.\"\"\"\n    \"Second string is not\"\n    return x\n\ndef function_with_f_prefix_docstring () -> int:\n    \"Not a docstring %s\" % str(1)\n    return 1\n\ndef function_with_single_quotes (x : int) -> int:\n    \"\"\"Single quote docstring\"\"\"\n    return x\n\ndef function_with_triple_single_quotes (x : int) -> int:\n    \"\"\"Triple quote docstring\"\"\"\n    return x\n\ndef function_with_mixed_quotes (x : int) -> int:\n    \"\"\"Mixed 'quotes' in docstring\"\"\"\n    return x\n\ndef function_with_braces_docstring ():\n    \"\"\"Docstring with {braces} should not interpolate.\"\"\"\n    pass\n\ndef function_empty_docstring ():\n    \"\"\"\"\"\"\n    pass\n\ndef function_with_control_flow ():\n    if True:\n        \"Not a docstring\"\n    return 42\n\ndef function_just_docstring ():\n    \"\"\"Just a docstring, no code.\"\"\""
  },
  {
    "path": "compiler/lib/test/1-parse/docstrings.output",
    "content": "\"\"\"Test module for docstring functionality with {braces}.\"\"\"\nimport math\ndef test_function (x : int) -> int:\n    \"\"\"Test function with docstring.\"\"\"\n    return x * 2\n\ndef no_docstring_function (x : int) -> int:\n    return x * 3\n\n# recursive group:\nclass TestClass:\n    \"\"\"Test class with docstring.\"\"\"\n    def method (self, x : int) -> int:\n        return x + 1\nactor TestActor (name : str):\n    \"\"\"Test actor with docstring.\"\"\"\n    var name = name\nprotocol TestProtocol:\n    \"\"\"Test protocol with docstring.\"\"\"\n    test_method : (int) -> int\nextension TestClass (TestProtocol):\n    \"\"\"Extension with docstring.\"\"\"\n    def test_method (self, x : int) -> int:\n        return x * 10\n# (recursive group)\n\ndef function_with_non_first_string (x : int) -> int:\n    y = x + 1\n    \"Not a docstring\"\n    return y\n\ndef function_with_multiple_strings (x : int) -> int:\n    \"\"\"First string is docstring.\"\"\"\n    \"Second string is not\"\n    return x\n\ndef function_with_f_prefix_docstring () -> int:\n    \"Not a docstring %s\" % str(1)\n    return 1\n\ndef function_with_single_quotes (x : int) -> int:\n    \"\"\"Single quote docstring\"\"\"\n    return x\n\ndef function_with_triple_single_quotes (x : int) -> int:\n    \"\"\"Triple quote docstring\"\"\"\n    return x\n\ndef function_with_mixed_quotes (x : int) -> int:\n    \"\"\"Mixed 'quotes' in docstring\"\"\"\n    return x\n\ndef function_with_braces_docstring ():\n    \"\"\"Docstring with {braces} should not interpolate.\"\"\"\n    pass\n\ndef function_empty_docstring ():\n    \"\"\"\"\"\"\n    pass\n\ndef function_with_control_flow ():\n    if True:\n        \"Not a docstring\"\n    return 42\n\ndef function_just_docstring ():\n    \"\"\"Just a docstring, no code.\"\"\""
  },
  {
    "path": "compiler/lib/test/1-parse/syntax1.input",
    "content": "\"\"\"Module docstring for syntax1 test.\nThis tests docstring support across all language constructs.\n\"\"\"\nimport net\ndef add (x : int, y : int) -> int:\n    \"\"\"Add two numbers together.\n\n    This function takes two integers and returns their sum.\n    \"\"\"\n    def foo ():\n        \"\"\"A nested function that does nothing.\"\"\"\n        pass\n    return x + y\n\n# recursive group:\nclass Calculator:\n    \"\"\"A calculator class with basic operations.\n\n    This class provides methods for arithmetic operations.\n    \"\"\"\n    def multiply (self, x : int, y : int) -> int:\n        \"\"\"Multiply two numbers.\n\n        Args:\n            x: First number\n            y: Second number\n\n        Returns:\n            The product of x and y\n        \"\"\"\n        return x * y\n    def divide (self, x : int, y : int) -> float:\n        \"\"\"Divide x by y.\"\"\"\n        return float(x) / float(y)\nactor Counter (name : str):\n    \"\"\"An actor that counts things.\n\n    This actor maintains a count and can increment it.\n    \"\"\"\n    var count = 0\n    var name = name\n    def increment ():\n        \"\"\"Increment the counter by one.\"\"\"\n        count += 1\n    def get_count () -> int:\n        \"\"\"Get the current count value.\"\"\"\n        return count\nprotocol Drawable:\n    \"\"\"Protocol for objects that can be drawn.\n\n    Any class implementing this protocol must provide a draw method.\n    \"\"\"\n    draw : () -> None\n    get_color : () -> str\nextension Calculator (Drawable):\n    \"\"\"Extension to make Calculator drawable.\n\n    This adds drawing capabilities to the Calculator class.\n    \"\"\"\n    def draw (self):\n        \"\"\"Draw the calculator.\"\"\"\n        print(\"Drawing a calculator\")\n    def get_color (self) -> str:\n        \"\"\"Get the calculator's color.\"\"\"\n        return \"black\"\n# (recursive group)\n\ndef subtract (x : int, y : int) -> int:\n    return x - y\n\ndef outer_function (x : int) -> int:\n    \"\"\"Outer function with a nested function inside.\"\"\"\n    def inner_function (y : int) -> int:\n        \"\"\"Inner function that adds to the outer parameter.\"\"\"\n        return x + y\n    return inner_function(10)"
  },
  {
    "path": "compiler/lib/test/1-parse/syntax1.output",
    "content": "\"\"\"Module docstring for syntax1 test.\nThis tests docstring support across all language constructs.\n\"\"\"\nimport net\ndef add (x : int, y : int) -> int:\n    \"\"\"Add two numbers together.\n\n    This function takes two integers and returns their sum.\n    \"\"\"\n    def foo ():\n        \"\"\"A nested function that does nothing.\"\"\"\n        pass\n    return x + y\n\n# recursive group:\nclass Calculator:\n    \"\"\"A calculator class with basic operations.\n\n    This class provides methods for arithmetic operations.\n    \"\"\"\n    def multiply (self, x : int, y : int) -> int:\n        \"\"\"Multiply two numbers.\n\n        Args:\n            x: First number\n            y: Second number\n\n        Returns:\n            The product of x and y\n        \"\"\"\n        return x * y\n    def divide (self, x : int, y : int) -> float:\n        \"\"\"Divide x by y.\"\"\"\n        return float(x) / float(y)\nactor Counter (name : str):\n    \"\"\"An actor that counts things.\n\n    This actor maintains a count and can increment it.\n    \"\"\"\n    var count = 0\n    var name = name\n    def increment ():\n        \"\"\"Increment the counter by one.\"\"\"\n        count += 1\n    def get_count () -> int:\n        \"\"\"Get the current count value.\"\"\"\n        return count\nprotocol Drawable:\n    \"\"\"Protocol for objects that can be drawn.\n\n    Any class implementing this protocol must provide a draw method.\n    \"\"\"\n    draw : () -> None\n    get_color : () -> str\nextension Calculator (Drawable):\n    \"\"\"Extension to make Calculator drawable.\n\n    This adds drawing capabilities to the Calculator class.\n    \"\"\"\n    def draw (self):\n        \"\"\"Draw the calculator.\"\"\"\n        print(\"Drawing a calculator\")\n    def get_color (self) -> str:\n        \"\"\"Get the calculator's color.\"\"\"\n        return \"black\"\n# (recursive group)\n\ndef subtract (x : int, y : int) -> int:\n    return x - y\n\ndef outer_function (x : int) -> int:\n    \"\"\"Outer function with a nested function inside.\"\"\"\n    def inner_function (y : int) -> int:\n        \"\"\"Inner function that adds to the outer parameter.\"\"\"\n        return x + y\n    return inner_function(10)"
  },
  {
    "path": "compiler/lib/test/2-kinds/deact.input",
    "content": "# recursive group:\nactor Apa ():\n    def setup (cb):\n        print(\"setup\")\n        cb(0)\n    def compute (cb):\n        print(\"compute\")\n        v = cb(1)\n        m = (async cb)(2)\n        return v * 10\n    def notice (i):\n        print(\"notice\")\n        return i + 1\n    setup(notice)\n    print(\"Apa\")\nactor Bepa ():\n    def callback (i):\n        print(\"callback\", i)\n        return i + 1\n    print(\"Bepa\")\nactor main (env):\n    def myproc (i):\n        print(\"myproc\", i)\n        if i == 2:\n            env.exit(0)\n        return i\n    a = Apa()\n    b = Bepa()\n    print(\"-----\")\n    a.setup(a.notice)\n    x = (async a.compute)(b.callback)\n    r = await x\n    print(\"r =\", r)\n    a.compute(myproc)\n    print(\"main\")\n# (recursive group)"
  },
  {
    "path": "compiler/lib/test/2-kinds/deact.output",
    "content": "# recursive group:\nactor Apa ():\n    T_13w def setup (cb : T_5w) -> T_9w:\n        print(\"setup\")\n        cb(0)\n    T_25w def compute (cb : T_17w) -> T_21w:\n        print(\"compute\")\n        v = cb(1)\n        m = (async cb)(2)\n        return v * 10\n    T_41w def notice (i : T_33w) -> T_37w:\n        print(\"notice\")\n        return i + 1\n    setup(notice)\n    print(\"Apa\")\nactor Bepa ():\n    T_53w def callback (i : T_45w) -> T_49w:\n        print(\"callback\", i)\n        return i + 1\n    print(\"Bepa\")\nactor main (env : T_57w):\n    T_69w def myproc (i : T_61w) -> T_65w:\n        print(\"myproc\", i)\n        if i == 2:\n            env.exit(0)\n        return i\n    a = Apa()\n    b = Bepa()\n    print(\"-----\")\n    a.setup(a.notice)\n    x = (async a.compute)(b.callback)\n    r = await x\n    print(\"r =\", r)\n    a.compute(myproc)\n    print(\"main\")\n# (recursive group)"
  },
  {
    "path": "compiler/lib/test/3-types/class_init_attrs/uninit_assert_uninit_attr.golden",
    "content": "[error Type error]: Attribute 'result' is not initialized in TestClass.__init__\n     +--> uninit_assert_uninit_attr.act@6:5-14:1\n     |\n   2 |    class TestClass(object):\n     :    ^-----------------------\n     :    `- In class TestClass\n     :\n   4 |        result: int\n     :        ^----- \n     :        `- Attribute 'result' is defined here\n     :\n   6 | +>     def __init__(self, x: int):\n   7 | |          self.value = x\n   8 | |          \n   9 | |          # Assert that references uninitialized self.result - should fail!\n  10 | |          assert self.result > 0, \"result must be positive\"\n  11 | |          \n  12 | |          # This should NOT be recognized as initialized\n  13 | |          self.result = 42\n  14 | |> \n     : | \n     : `- Attribute 'result' is not initialized in __init__\n-----+\n"
  },
  {
    "path": "compiler/lib/test/3-types/class_init_attrs/uninit_augmented_assign.golden",
    "content": "[error Type error]: Attribute 'x' is not initialized in TestClass.__init__\n     +--> uninit_augmented_assign.act@4:5-5:1\n     |\n   1 |    class TestClass(object):\n     :    ^-----------------------\n     :    `- In class TestClass\n   2 |        x: int\n     :        ^ \n     :        `- Attribute 'x' is defined here\n     :\n   4 | +>     def __init__(self):\n   5 | |>         self.x += 1  # Should fail - x not initialized before augmented assignment\n     : | \n     : `- Attribute 'x' is not initialized in __init__\n-----+\n"
  },
  {
    "path": "compiler/lib/test/3-types/class_init_attrs/uninit_basic.golden",
    "content": "[error Type error]: Attribute 'x' is not initialized in TestClass.__init__\n     +--> uninit_basic.act@3:5-5:1\n     |\n   1 |    class TestClass(object):\n     :    ^-----------------------\n     :    `- In class TestClass\n   2 |        x: int\n     :        ^ \n     :        `- Attribute 'x' is defined here\n   3 | +>     def __init__(self):\n   4 | |          pass\n   5 | |> \n     : | \n     : `- Attribute 'x' is not initialized in __init__\n-----+\n"
  },
  {
    "path": "compiler/lib/test/3-types/class_init_attrs/uninit_basic_inferred.golden",
    "content": "[error Type error]: Attribute 'x' is not initialized in TestClass.__init__\n     +--> uninit_basic_inferred.act@2:5-5:1\n     |\n   1 |    class TestClass(object):\n     :    ^-----------------------\n     :    `- In class TestClass\n   2 | +>     def __init__(self):\n   3 | |          if False:\n   4 | |              self.x = 1  # Should fail - x not initialized before use\n     : |                   ^ \n     : |                   `- Attribute 'x' inferred from use\n   5 | |> \n     : | \n     : `- Attribute 'x' is not initialized in __init__\n-----+\n"
  },
  {
    "path": "compiler/lib/test/3-types/class_init_attrs/uninit_elif_missing.golden",
    "content": "[error Type error]: Attribute 'x' is not initialized in TestClass.__init__\n     +--> uninit_elif_missing.act@5:5-11:1\n     |\n   2 |    class TestClass(object):\n     :    ^-----------------------\n     :    `- In class TestClass\n   3 |        x: int\n     :        ^ \n     :        `- Attribute 'x' is defined here\n     :\n   5 | +>     def __init__(self, mode: int):\n   6 | |          if mode == 1:\n   7 | |              self.x = 1\n   8 | |          elif mode == 2:\n   9 | |              self.x = 2\n  10 | |          # No else - x not initialized for other values\n  11 | |> \n     : | \n     : `- Attribute 'x' is not initialized in __init__\n-----+\n"
  },
  {
    "path": "compiler/lib/test/3-types/class_init_attrs/uninit_for_loop.golden",
    "content": "[error Type error]: Attribute 'y' is not initialized in TestClass.__init__\n     +--> uninit_for_loop.act@6:5-12:1\n     |\n   2 |    class TestClass(object):\n     :    ^-----------------------\n     :    `- In class TestClass\n     :\n   4 |        y: int\n     :        ^ \n     :        `- Attribute 'y' is defined here\n     :\n   6 | +>     def __init__(self, items: list[int]):\n   7 | |          self.x = 1\n   8 | |          for item in items:\n   9 | |              if item == 0:\n  10 | |                  break\n  11 | |              self.y = item  # Might not execute if we break early or items is empty\n  12 | |> \n     : | \n     : `- Attribute 'y' is not initialized in __init__\n-----+\n"
  },
  {
    "path": "compiler/lib/test/3-types/class_init_attrs/uninit_grandparent.golden",
    "content": "[error Type error]: Attribute 'x' is not initialized in TestClass.__init__\n     +--> uninit_grandparent.act@8:5-10:1\n     |\n   1 |    class BaseA:\n     :          ^-----\n     :          `- Attribute inherited from BaseA\n   2 |        x: int\n     :        ^ \n     :        `- Attribute 'x' is defined here\n     :\n   7 |    class TestClass(BaseB):\n     :    ^----------------------\n     :    `- In class TestClass\n   8 | +>     def __init__(self):\n   9 | |          self.y = 1\n  10 | |> \n     : | \n     : `- Attribute 'x' is not initialized in __init__\n-----+\n"
  },
  {
    "path": "compiler/lib/test/3-types/class_init_attrs/uninit_grandparent2.golden",
    "content": "[error Type error]: Attribute 'y' is not initialized in TestClass.__init__\n     +--> uninit_grandparent2.act@14:5-17:1\n     |\n   6 |    class BaseB(BaseA):\n     :          ^------------\n     :          `- Attribute inherited from BaseB\n   7 |        y: int\n     :        ^ \n     :        `- Attribute 'y' is defined here\n     :\n  13 |    class TestClass(BaseB):\n     :    ^----------------------\n     :    `- In class TestClass\n  14 | +>     def __init__(self):\n  15 | |          BaseA.__init__(self)\n  16 | |          # Should get a failure since y is not initialized\n  17 | |> \n     : | \n     : `- Attribute 'y' is not initialized in __init__\n-----+\n"
  },
  {
    "path": "compiler/lib/test/3-types/class_init_attrs/uninit_inherited.golden",
    "content": "[error Type error]: Attribute 'x' is not initialized in TestClass.__init__\n     +--> uninit_inherited.act@5:5-7:1\n     |\n   1 |    class Base:\n     :          ^----\n     :          `- Attribute inherited from Base\n   2 |        x: int\n     :        ^ \n     :        `- Attribute 'x' is defined here\n     :\n   4 |    class TestClass(Base):\n     :    ^---------------------\n     :    `- In class TestClass\n   5 | +>     def __init__(self):\n   6 | |          pass\n   7 | |> \n     : | \n     : `- Attribute 'x' is not initialized in __init__\n-----+\n"
  },
  {
    "path": "compiler/lib/test/3-types/class_init_attrs/uninit_init_in_method.golden",
    "content": "[error Type error]: Attribute 'x' is not initialized in TestClass.__init__\n     +--> uninit_init_in_method.act@6:5-8:5\n     |\n   3 |    class TestClass(object):\n     :    ^-----------------------\n     :    `- In class TestClass\n   4 |        x: int\n     :        ^ \n     :        `- Attribute 'x' is defined here\n     :\n   6 | +>     def __init__(self):\n   7 | |          self.setup()\n   8 | |>     \n     : | \n     : `- Attribute 'x' is not initialized in __init__\n-----+\n"
  },
  {
    "path": "compiler/lib/test/3-types/class_init_attrs/uninit_loop_references_self.golden",
    "content": "[error Type error]: Attribute 'x' is not initialized in TestClass.__init__\n     +--> uninit_loop_references_self.act@6:5-14:1\n     |\n   2 |    class TestClass(object):\n     :    ^-----------------------\n     :    `- In class TestClass\n   3 |        x: int\n     :        ^ \n     :        `- Attribute 'x' is defined here\n     :\n   6 | +>     def __init__(self):\n   7 | |          # Loop that references self - not safe to continue\n   8 | |          for i in range(10):\n   9 | |              process(self)  # Leaks self reference!\n  10 | |          # These assignments are after the loop but we can't reach them\n  11 | |          # because the loop leaked self\n  12 | |          self.x = 1\n  13 | |          self.y = 2\n  14 | |> \n     : | \n     : `- Attribute 'x' is not initialized in __init__\n-----+\n"
  },
  {
    "path": "compiler/lib/test/3-types/class_init_attrs/uninit_method_call.golden",
    "content": "[error Type error]: Attribute 'y' is not initialized in TestClass.__init__\n     +--> uninit_method_call.act@10:5-15:5\n     |\n   5 |    class TestClass(object):\n     :    ^-----------------------\n     :    `- In class TestClass\n     :\n   7 |        y: int\n     :        ^ \n     :        `- Attribute 'y' is defined here\n     :\n  10 | +>     def __init__(self):\n  11 | |          self.counter = 0\n  12 | |          self.x = 1\n  13 | |          self.helper()  # Method call on self - scanner should stop here\n  14 | |          self.y = 2  # Not reached by scanner\n  15 | |> \n     : | \n     : `- Attribute 'y' is not initialized in __init__\n-----+\n"
  },
  {
    "path": "compiler/lib/test/3-types/class_init_attrs/uninit_method_call_assign.golden",
    "content": "[error Type error]: Attribute 'pi' is not initialized in TestClass.__init__\n     +--> uninit_method_call_assign.act@12:5-17:5\n     |\n   6 |    class TestClass(object):\n     :    ^-----------------------\n     :    `- In class TestClass\n   7 |        pi: int\n     :        ^- \n     :        `- Attribute 'pi' is defined here\n     :\n  12 | +>     def __init__(self):\n  13 | |          self.counter = 0\n  14 | |          self.x = 1\n  15 | |          self.pi = self.pure_helper()\n  16 | |          self.y = 2  # Not reached by scanner\n  17 | |>     \n     : | \n     : `- Attribute 'pi' is not initialized in __init__\n-----+\n"
  },
  {
    "path": "compiler/lib/test/3-types/class_init_attrs/uninit_method_reference.golden",
    "content": "[error Type error]: Attribute 'handler' is not initialized in TestClass.__init__\n     +--> uninit_method_reference.act@12:5-17:5\n     |\n   8 |    class TestClass(object):\n     :    ^-----------------------\n     :    `- In class TestClass\n   9 |        handler: Callback\n     :        ^------ \n     :        `- Attribute 'handler' is defined here\n     :\n  12 | +>     def __init__(self):\n  13 | |          # This should work - we're just passing a method reference\n  14 | |          # But currently the compiler sees self._on_event as leaking self\n  15 | |          self.handler = Callback(self._on_event)\n  16 | |          self.value = 42  # This won't be seen as initialized\n  17 | |>     \n     : | \n     : `- Attribute 'handler' is not initialized in __init__\n-----+\n"
  },
  {
    "path": "compiler/lib/test/3-types/class_init_attrs/uninit_nested_function_escape.golden",
    "content": "[error Type error]: Attribute 'result' is not initialized in TestClass.__init__\n     +--> uninit_nested_function_escape.act@6:5-18:1\n     |\n   2 |    class TestClass(object):\n     :    ^-----------------------\n     :    `- In class TestClass\n     :\n   4 |        result: int\n     :        ^----- \n     :        `- Attribute 'result' is defined here\n     :\n   6 | +>     def __init__(self, x: int):\n   7 | |          self.value = x\n   8 | |          \n   9 | |          # Nested function that captures self with uninitialized attribute\n  10 | |          def get_result() -> int:\n  11 | |              return self.result  # References uninitialized self.result!\n  12 | |          \n  13 | |          # Pass the function externally (self escapes via closure)\n  14 | |          register(get_result)\n  15 | |          \n  16 | |          # This won't be recognized as initialized (self escaped)\n  17 | |          self.result = 42\n  18 | |> \n     : | \n     : `- Attribute 'result' is not initialized in __init__\n-----+\n"
  },
  {
    "path": "compiler/lib/test/3-types/class_init_attrs/uninit_nested_function_with_self.golden",
    "content": "[error Type error]: Attribute 'result' is not initialized in TestClass.__init__\n     +--> uninit_nested_function_with_self.act@6:5-16:1\n     |\n   2 |    class TestClass(object):\n     :    ^-----------------------\n     :    `- In class TestClass\n     :\n   4 |        result: int\n     :        ^----- \n     :        `- Attribute 'result' is defined here\n     :\n   6 | +>     def __init__(self, x: int):\n   7 | |          self.value = x\n   8 | |          \n   9 | |          # Nested function that captures self - stops scanning\n  10 | |          def get_value() -> int:\n  11 | |              return self.value  # References self (even though value is initialized)\n  12 | |          \n  13 | |          # The nested function captured self, so we conservatively stop scanning\n  14 | |          # This will NOT be seen as initialized\n  15 | |          self.result = 42\n  16 | |> \n     : | \n     : `- Attribute 'result' is not initialized in __init__\n-----+\n"
  },
  {
    "path": "compiler/lib/test/3-types/class_init_attrs/uninit_nested_if.golden",
    "content": "[error Type error]: Attribute 'y' is not initialized in TestClass.__init__\n     +--> uninit_nested_if.act@6:5-17:1\n     |\n   2 |    class TestClass(object):\n     :    ^-----------------------\n     :    `- In class TestClass\n     :\n   4 |        y: int\n     :        ^ \n     :        `- Attribute 'y' is defined here\n     :\n   6 | +>     def __init__(self, a: bool, b: bool):\n   7 | |          if a:\n   8 | |              if b:\n   9 | |                  self.x = 1\n  10 | |                  self.y = 1\n  11 | |              else:\n  12 | |                  self.x = 2\n  13 | |                  # Missing y in this path\n  14 | |          else:\n  15 | |              self.x = 3\n  16 | |              self.y = 3\n  17 | |> \n     : | \n     : `- Attribute 'y' is not initialized in __init__\n-----+\n"
  },
  {
    "path": "compiler/lib/test/3-types/class_init_attrs/uninit_no_parent_init.golden",
    "content": "[error Compilation error]: Abstract attribute not selectable by class\n     +--> uninit_no_parent_init.act@6:9-6:28\n     |\n   6 |         Base.__init__(self)\n     :         ^------------------\n     :         `- Abstract attribute not selectable by class\n-----+\n"
  },
  {
    "path": "compiler/lib/test/3-types/class_init_attrs/uninit_notimpl_call_other.golden",
    "content": "[error Type error]: Attribute 'y' is not initialized in TestClass.__init__\n     +--> uninit_notimpl_call_other.act@8:5-15:5\n     |\n   4 |    class TestClass(object):\n     :    ^-----------------------\n     :    `- In class TestClass\n     :\n   6 |        y: int\n     :        ^ \n     :        `- Attribute 'y' is defined here\n     :\n   8 | +>     def __init__(self):\n   9 | |          # Calling a NotImplemented method on self should be allowed since it's\n  10 | |          # implemented in C and thus trusted to do the right thing.\n  11 | |          self.setup()\n  12 | |          self.x = 1\n  13 | |          self.setup2()\n  14 | |          self.y = 2\n  15 | |> \n     : | \n     : `- Attribute 'y' is not initialized in __init__\n-----+\n"
  },
  {
    "path": "compiler/lib/test/3-types/class_init_attrs/uninit_partial.golden",
    "content": "[error Type error]: Attribute 'y' is not initialized in TestClass.__init__\n     +--> uninit_partial.act@4:5-6:1\n     |\n   1 |    class TestClass(object):\n     :    ^-----------------------\n     :    `- In class TestClass\n     :\n   3 |        y: str\n     :        ^ \n     :        `- Attribute 'y' is defined here\n   4 | +>     def __init__(self):\n   5 | |          self.x = 1\n   6 | |> \n     : | \n     : `- Attribute 'y' is not initialized in __init__\n-----+\n"
  },
  {
    "path": "compiler/lib/test/3-types/class_init_attrs/uninit_return_early.golden",
    "content": "[error Type error]: Attribute 'y' is not initialized in TestClass.__init__\n     +--> uninit_return_early.act@6:5-13:1\n     |\n   2 |    class TestClass(object):\n     :    ^-----------------------\n     :    `- In class TestClass\n     :\n   4 |        y: int\n     :        ^ \n     :        `- Attribute 'y' is defined here\n     :\n   6 | +>     def __init__(self, quick_exit: bool):\n   7 | |          if quick_exit:\n   8 | |              self.x = 0\n   9 | |              return  # Early return - but y is still uninitialized!\n  10 | |          else:\n  11 | |              self.x = 1\n  12 | |              self.y = 2\n  13 | |> \n     : | \n     : `- Attribute 'y' is not initialized in __init__\n-----+\n"
  },
  {
    "path": "compiler/lib/test/3-types/class_init_attrs/uninit_self_attr_access.golden",
    "content": "[error Type error]: Attribute 'x' is not initialized in TestClass.__init__\n     +--> uninit_self_attr_access.act@6:5-9:1\n     |\n   2 |    class TestClass(object):\n     :    ^-----------------------\n     :    `- In class TestClass\n   3 |        x: int\n     :        ^ \n     :        `- Attribute 'x' is defined here\n     :\n   6 | +>     def __init__(self):\n   7 | |          self.x = self.y * 2  # ERROR: y is not initialized yet!\n   8 | |          self.y = 10\n   9 | |> \n     : | \n     : `- Attribute 'x' is not initialized in __init__\n-----+\n"
  },
  {
    "path": "compiler/lib/test/3-types/class_init_attrs/uninit_self_in_list.golden",
    "content": "[error Type error]: Attribute 'y' is not initialized in TestClass.__init__\n     +--> uninit_self_in_list.act@10:5-20:1\n     |\n   6 |    class TestClass(object):\n     :    ^-----------------------\n     :    `- In class TestClass\n     :\n   8 |        y: int\n     :        ^ \n     :        `- Attribute 'y' is defined here\n     :\n  10 | +>     def __init__(self):\n  11 | |          self.x = 1\n  12 | |          \n  13 | |          # Direct reference to self - stop scanning here\n  14 | |          # We don't actually know if objects how objects is used or if it even is\n  15 | |          # used, but that is untractable to analyze, so we stop analyzing at any\n  16 | |          # point where self is referenced.\n  17 | |          objects = [self, self]\n  18 | |          # This won't be scanned, so y will be considered uninitialized\n  19 | |          self.y = do_something(objects)\n  20 | |> \n     : | \n     : `- Attribute 'y' is not initialized in __init__\n-----+\n"
  },
  {
    "path": "compiler/lib/test/3-types/class_init_attrs/uninit_self_reference.golden",
    "content": "[error Type error]: Attribute 'y' is not initialized in TestClass.__init__\n     +--> uninit_self_reference.act@14:5-23:1\n     |\n   9 |    class TestClass(object):\n     :    ^-----------------------\n     :    `- In class TestClass\n     :\n  11 |        y: int\n     :        ^ \n     :        `- Attribute 'y' is defined here\n     :\n  14 | +>     def __init__(self):\n  15 | |          self.x = 1\n  16 | |          \n  17 | |          # This should stop scanning because we're passing self\n  18 | |          result = external_func(self)  \n  19 | |          \n  20 | |          # These won't be scanned, so z will be reported as uninitialized\n  21 | |          self.y = result\n  22 | |          self.z = 3\n  23 | |> \n     : | \n     : `- Attribute 'y' is not initialized in __init__\n-----+\n"
  },
  {
    "path": "compiler/lib/test/3-types/class_init_attrs/uninit_try_except.golden",
    "content": "[error Type error]: Attribute 'y' is not initialized in TestClass.__init__\n     +--> uninit_try_except.act@6:5-13:1\n     |\n   2 |    class TestClass(object):\n     :    ^-----------------------\n     :    `- In class TestClass\n     :\n   4 |        y: int\n     :        ^ \n     :        `- Attribute 'y' is defined here\n     :\n   6 | +>     def __init__(self):\n   7 | |          try:\n   8 | |              self.x = risky_operation()\n   9 | |              self.y = 1\n  10 | |          except:\n  11 | |              self.x = 0\n  12 | |              # y not initialized in except block\n  13 | |> \n     : | \n     : `- Attribute 'y' is not initialized in __init__\n-----+\n"
  },
  {
    "path": "compiler/lib/test/3-types/deact.input",
    "content": "# recursive group:\nactor Apa ():\n    T_13w def setup (cb : T_5w) -> T_9w:\n        print(\"setup\")\n        cb(0)\n    T_25w def compute (cb : T_17w) -> T_21w:\n        print(\"compute\")\n        v = cb(1)\n        m = (async cb)(2)\n        return v * 10\n    T_41w def notice (i : T_33w) -> T_37w:\n        print(\"notice\")\n        return i + 1\n    setup(notice)\n    print(\"Apa\")\nactor Bepa ():\n    T_53w def callback (i : T_45w) -> T_49w:\n        print(\"callback\", i)\n        return i + 1\n    print(\"Bepa\")\nactor main (env : T_57w):\n    T_69w def myproc (i : T_61w) -> T_65w:\n        print(\"myproc\", i)\n        if i == 2:\n            env.exit(0)\n        return i\n    a = Apa()\n    b = Bepa()\n    print(\"-----\")\n    a.setup(a.notice)\n    x = (async a.compute)(b.callback)\n    r = await x\n    print(\"r =\", r)\n    a.compute(myproc)\n    print(\"main\")\n# (recursive group)"
  },
  {
    "path": "compiler/lib/test/3-types/deact.output",
    "content": "W_Apa_39: __builtin__.Number[__builtin__.int] = __builtin__.IntegralD_int()\n\nW_Apa_140: __builtin__.Plus[__builtin__.int] = __builtin__.IntegralD_int()\n\nW_Apa_105: __builtin__.Times[__builtin__.int, __builtin__.int] = __builtin__.IntegralD_int()\n\nW_Apa_308: __builtin__.Eq[__builtin__.int] = __builtin__.OrdD_int()\n\n# recursive group:\nactor Apa ():\n    proc def setup (cb : action(__builtin__.int) -> __builtin__.int) -> None:\n        print@[(__builtin__.str,)](*(\"setup\",), sep = None, end = None, err = None, flush = None)\n        cb(W_Apa_39.__fromatom__(0))\n    proc def compute (cb : action(__builtin__.int) -> __builtin__.int) -> __builtin__.int:\n        print@[(__builtin__.str,)](*(\"compute\",), sep = None, end = None, err = None, flush = None)\n        v: __builtin__.int = cb(W_Apa_39.__fromatom__(1))\n        m: __builtin__.Msg[__builtin__.int] = (async cb)(W_Apa_39.__fromatom__(2))\n        return W_Apa_105.__mul__(v, W_Apa_39.__fromatom__(10))\n    proc def notice (i : __builtin__.int) -> __builtin__.int:\n        print@[(__builtin__.str,)](*(\"notice\",), sep = None, end = None, err = None, flush = None)\n        return W_Apa_140.__add__(i, W_Apa_39.__fromatom__(1))\n    setup(cb = action lambda (G_1y : __builtin__.int): $WRAP@[(), (i: __builtin__.int), __builtin__.int](self, notice)(i = G_1y))\n    print@[(__builtin__.str,)](*(\"Apa\",), sep = None, end = None, err = None, flush = None)\nactor Bepa ():\n    proc def callback (i : __builtin__.int) -> __builtin__.int:\n        print@[(__builtin__.str, __builtin__.int)](*(\"callback\", i), sep = None, end = None, err = None, flush = None)\n        return W_Apa_140.__add__(i, W_Apa_39.__fromatom__(1))\n    print@[(__builtin__.str,)](*(\"Bepa\",), sep = None, end = None, err = None, flush = None)\nactor main (env : __builtin__.Env):\n    proc def myproc (i : __builtin__.int) -> __builtin__.int:\n        print@[(__builtin__.str, __builtin__.int)](*(\"myproc\", i), sep = None, end = None, err = None, flush = None)\n        if W_Apa_308.__eq__(i, W_Apa_39.__fromatom__(2)):\n            env.exit(n = W_Apa_39.__fromatom__(0))\n        return i\n    a: Apa = Apa()\n    b: Bepa = Bepa()\n    print@[(__builtin__.str,)](*(\"-----\",), sep = None, end = None, err = None, flush = None)\n    a.setup(cb = action lambda (G_1y : __builtin__.int): a.notice(i = G_1y))\n    x: __builtin__.Msg[__builtin__.int] = (async action lambda (G_1p : action(__builtin__.int) -> __builtin__.int): a.compute(cb = G_1p))(action lambda (G_1y : __builtin__.int): b.callback(i = G_1y))\n    r: __builtin__.int = await x\n    print@[(__builtin__.str, __builtin__.int)](*(\"r =\", r), sep = None, end = None, err = None, flush = None)\n    a.compute(cb = action lambda (G_1y : __builtin__.int): $WRAP@[(), (i: __builtin__.int), __builtin__.int](self, myproc)(i = G_1y))\n    print@[(__builtin__.str,)](*(\"main\",), sep = None, end = None, err = None, flush = None)\n# (recursive group)"
  },
  {
    "path": "compiler/lib/test/3-types/test_discovery.input",
    "content": "import logging\n\nimport testing\nactor MathTester ():\n    T_17w def add (a : T_5w, b : T_9w) -> T_13w:\n        return a + b\n\nT_21w def _test_foo () -> None:\n    pass\n\n# recursive group:\nactor _test_SimpleSyncTester ():\n    m = MathTester()\n    print(\"SimpleSyncTester.test()\")\n    testing.assertEqual(m.add(1, 2), 3, \"1 + 2 = 3\")\nactor _SyncTester (t : testing.SyncT):\n    log = logging.Logger(t.log_handler)\n    m = MathTester()\n    log.info(\"SyncTester.test()\")\n    print(\"SyncTester.test()\")\n    testing.assertEqual(m.add(1, 2), 3, \"1 + 2 = 3\")\nactor _SyncTesterCore ():\n    m = MathTester()\n    print(\"SimpleSyncTester.test()\")\n    testing.assertEqual(m.add(1, 2), 3, \"1 + 2 = 3\")\n# (recursive group)\n\nT_37w def _test_simple_sync () -> T_33w:\n    s = _SyncTesterCore()\n\nT_47w def _test_sync (t : testing.SyncT) -> T_43w:\n    m = MathTester()\n    return str(m.add(1, 2))\n\n# recursive group:\nactor AsyncTester (t : testing.AsyncT):\n    log = logging.Logger(t.log_handler)\n    T_59w def test () -> T_55w:\n        log.info(\"AsyncTester.test()\", {\"data\": \"test\"})\n        t.success()\n    after 0: test()\nactor EnvTester (t : testing.EnvT):\n    log = logging.Logger(t.log_handler)\n    T_69w def test () -> T_65w:\n        log.info(\"EnvTester.test() wthreads:\", {\"nr_wthreads\": t.env.nr_wthreads})\n        print(\"EnvTester.test() wthreads:\", t.env.nr_wthreads)\n        t.success()\n    after 0: test()\n# (recursive group)"
  },
  {
    "path": "compiler/lib/test/3-types/test_discovery.output",
    "content": "import logging\n\nimport testing\nW_MathTester_6: __builtin__.Plus[__builtin__.int] = __builtin__.IntegralD_int()\n\nactor MathTester ():\n    proc def add (a : __builtin__.int, b : __builtin__.int) -> __builtin__.int:\n        return W_MathTester_6.__add__(a, b)\n\npure def _test_foo () -> None:\n    pass\n\nW__test_SimpleSyncTester_268: __builtin__.Number[__builtin__.int] = __builtin__.IntegralD_int()\n\nW__test_SimpleSyncTester_234: __builtin__.Eq[__builtin__.int] = __builtin__.OrdD_int()\n\n# recursive group:\nactor _test_SimpleSyncTester ():\n    m: MathTester = MathTester()\n    print@[(__builtin__.str,)](*(\"SimpleSyncTester.test()\",), sep = None, end = None, err = None, flush = None)\n    testing.assertEqual@[__builtin__.int](W__test_SimpleSyncTester_234, a = m.add(a = W__test_SimpleSyncTester_268.__fromatom__(1), b = W__test_SimpleSyncTester_268.__fromatom__(2)), b = W__test_SimpleSyncTester_268.__fromatom__(3), msg = \"1 + 2 = 3\", print_vals = None, print_diff = None)\nactor _SyncTester (t : testing.SyncT):\n    log: logging.Logger = logging.Logger(handler = t.log_handler)\n    m: MathTester = MathTester()\n    log.info(msg = \"SyncTester.test()\", data = None)\n    print@[(__builtin__.str,)](*(\"SyncTester.test()\",), sep = None, end = None, err = None, flush = None)\n    testing.assertEqual@[__builtin__.int](W__test_SimpleSyncTester_234, a = m.add(a = W__test_SimpleSyncTester_268.__fromatom__(1), b = W__test_SimpleSyncTester_268.__fromatom__(2)), b = W__test_SimpleSyncTester_268.__fromatom__(3), msg = \"1 + 2 = 3\", print_vals = None, print_diff = None)\nactor _SyncTesterCore ():\n    m: MathTester = MathTester()\n    print@[(__builtin__.str,)](*(\"SimpleSyncTester.test()\",), sep = None, end = None, err = None, flush = None)\n    testing.assertEqual@[__builtin__.int](W__test_SimpleSyncTester_234, a = m.add(a = W__test_SimpleSyncTester_268.__fromatom__(1), b = W__test_SimpleSyncTester_268.__fromatom__(2)), b = W__test_SimpleSyncTester_268.__fromatom__(3), msg = \"1 + 2 = 3\", print_vals = None, print_diff = None)\n# (recursive group)\n\nproc def _test_simple_sync () -> None:\n    s: _SyncTesterCore = _SyncTesterCore()\n\nproc def _test_sync (t : testing.SyncT) -> __builtin__.str:\n    W__test_sync_11: __builtin__.Number[__builtin__.int] = __builtin__.IntegralD_int()\n    m: MathTester = MathTester()\n    return str(val = m.add(a = W__test_sync_11.__fromatom__(1), b = W__test_sync_11.__fromatom__(2)))\n\nW_AsyncTester_183: __builtin__.Number[__builtin__.float] = __builtin__.RealFloatD_float()\n\nW_AsyncTester_125: __builtin__.Hashable[__builtin__.str] = __builtin__.HashableD_str()\n\n# recursive group:\nactor AsyncTester (t : testing.AsyncT):\n    log: logging.Logger = logging.Logger(handler = t.log_handler)\n    proc def test () -> None:\n        log.info(msg = \"AsyncTester.test()\", data = $mkDict@[__builtin__.str, __builtin__.str](W_AsyncTester_125, {\"data\": \"test\"}))\n        t.success(output = None)\n    after W_AsyncTester_183.__fromatom__(0): test()\nactor EnvTester (t : testing.EnvT):\n    log: logging.Logger = logging.Logger(handler = t.log_handler)\n    proc def test () -> None:\n        log.info(msg = \"EnvTester.test() wthreads:\", data = $mkDict@[__builtin__.str, __builtin__.int](W_AsyncTester_125, {\"nr_wthreads\": t.env.nr_wthreads}))\n        print@[(__builtin__.str, __builtin__.int)](*(\"EnvTester.test() wthreads:\", t.env.nr_wthreads), sep = None, end = None, err = None, flush = None)\n        t.success(output = None)\n    after W_AsyncTester_183.__fromatom__(0): test()\n# (recursive group)\n\nproc def _test_SimpleSyncTester_wrapper () -> None:\n    _test_SimpleSyncTester()\n\nproc def _test__SyncTester (t : testing.SyncT) -> None:\n    _SyncTester(t)\n\nproc def _test_AsyncTester (t : testing.AsyncT) -> None:\n    AsyncTester(t)\n\nproc def _test_EnvTester (t : testing.EnvT) -> None:\n    EnvTester(t)\n\n__unit_tests: __builtin__.dict[__builtin__.str, testing.UnitTest] = $mkDict@[__builtin__.str, testing.UnitTest](__builtin__.HashableD_str(), {\"_test_foo\": testing.UnitTest(_test_foo, \"_test_foo\", \"\", \"test_discovery\")})\n\n__simple_sync_tests: __builtin__.dict[__builtin__.str, testing.SimpleSyncTest] = $mkDict@[__builtin__.str, testing.SimpleSyncTest](__builtin__.HashableD_str(), {\"_test_simple_sync\": testing.SimpleSyncTest(_test_simple_sync, \"_test_simple_sync\", \"\", \"test_discovery\"), \"_test_SimpleSyncTester_wrapper\": testing.SimpleSyncTest(_test_SimpleSyncTester_wrapper, \"_test_SimpleSyncTester_wrapper\", \"\", \"test_discovery\")})\n\n__sync_tests: __builtin__.dict[__builtin__.str, testing.SyncTest] = $mkDict@[__builtin__.str, testing.SyncTest](__builtin__.HashableD_str(), {\"_test_sync\": testing.SyncTest(_test_sync, \"_test_sync\", \"\", \"test_discovery\"), \"_test__SyncTester\": testing.SyncTest(_test__SyncTester, \"_test__SyncTester\", \"\", \"test_discovery\")})\n\n__async_tests: __builtin__.dict[__builtin__.str, testing.AsyncTest] = $mkDict@[__builtin__.str, testing.AsyncTest](__builtin__.HashableD_str(), {\"_test_AsyncTester\": testing.AsyncTest(_test_AsyncTester, \"_test_AsyncTester\", \"\", \"test_discovery\")})\n\n__env_tests: __builtin__.dict[__builtin__.str, testing.EnvTest] = $mkDict@[__builtin__.str, testing.EnvTest](__builtin__.HashableD_str(), {\"_test_EnvTester\": testing.EnvTest(_test_EnvTester, \"_test_EnvTester\", \"\", \"test_discovery\")})\n\nactor test_main (env : __builtin__.Env):\n    testing.test_runner(env, __unit_tests, __simple_sync_tests, __sync_tests, __async_tests, __env_tests)"
  },
  {
    "path": "compiler/lib/test/4-normalizer/deact.input",
    "content": "W_Apa_39: __builtin__.Number[__builtin__.int] = __builtin__.IntegralD_int()\n\nW_Apa_140: __builtin__.Plus[__builtin__.int] = __builtin__.IntegralD_int()\n\nW_Apa_105: __builtin__.Times[__builtin__.int, __builtin__.int] = __builtin__.IntegralD_int()\n\nW_Apa_308: __builtin__.Eq[__builtin__.int] = __builtin__.OrdD_int()\n\n# recursive group:\nactor Apa ():\n    proc def setup (cb : action(__builtin__.int) -> __builtin__.int) -> None:\n        print@[(__builtin__.str,)](*(\"setup\",), sep = None, end = None, err = None, flush = None)\n        cb(W_Apa_39.__fromatom__(0))\n    proc def compute (cb : action(__builtin__.int) -> __builtin__.int) -> __builtin__.int:\n        print@[(__builtin__.str,)](*(\"compute\",), sep = None, end = None, err = None, flush = None)\n        v: __builtin__.int = cb(W_Apa_39.__fromatom__(1))\n        m: __builtin__.Msg[__builtin__.int] = (async cb)(W_Apa_39.__fromatom__(2))\n        return W_Apa_105.__mul__(v, W_Apa_39.__fromatom__(10))\n    proc def notice (i : __builtin__.int) -> __builtin__.int:\n        print@[(__builtin__.str,)](*(\"notice\",), sep = None, end = None, err = None, flush = None)\n        return W_Apa_140.__add__(i, W_Apa_39.__fromatom__(1))\n    setup(cb = action lambda (G_1y : __builtin__.int): $WRAP@[(), (i: __builtin__.int), __builtin__.int](self, notice)(i = G_1y))\n    print@[(__builtin__.str,)](*(\"Apa\",), sep = None, end = None, err = None, flush = None)\nactor Bepa ():\n    proc def callback (i : __builtin__.int) -> __builtin__.int:\n        print@[(__builtin__.str, __builtin__.int)](*(\"callback\", i), sep = None, end = None, err = None, flush = None)\n        return W_Apa_140.__add__(i, W_Apa_39.__fromatom__(1))\n    print@[(__builtin__.str,)](*(\"Bepa\",), sep = None, end = None, err = None, flush = None)\nactor main (env : __builtin__.Env):\n    proc def myproc (i : __builtin__.int) -> __builtin__.int:\n        print@[(__builtin__.str, __builtin__.int)](*(\"myproc\", i), sep = None, end = None, err = None, flush = None)\n        if W_Apa_308.__eq__(i, W_Apa_39.__fromatom__(2)):\n            env.exit(n = W_Apa_39.__fromatom__(0))\n        return i\n    a: Apa = Apa()\n    b: Bepa = Bepa()\n    print@[(__builtin__.str,)](*(\"-----\",), sep = None, end = None, err = None, flush = None)\n    a.setup(cb = action lambda (G_1y : __builtin__.int): a.notice(i = G_1y))\n    x: __builtin__.Msg[__builtin__.int] = (async action lambda (G_1p : action(__builtin__.int) -> __builtin__.int): a.compute(cb = G_1p))(action lambda (G_1y : __builtin__.int): b.callback(i = G_1y))\n    r: __builtin__.int = await x\n    print@[(__builtin__.str, __builtin__.int)](*(\"r =\", r), sep = None, end = None, err = None, flush = None)\n    a.compute(cb = action lambda (G_1y : __builtin__.int): $WRAP@[(), (i: __builtin__.int), __builtin__.int](self, myproc)(i = G_1y))\n    print@[(__builtin__.str,)](*(\"main\",), sep = None, end = None, err = None, flush = None)\n# (recursive group)"
  },
  {
    "path": "compiler/lib/test/4-normalizer/deact.output",
    "content": "W_Apa_39: __builtin__.Number[__builtin__.int] = __builtin__.IntegralD_int()\n\nW_Apa_140: __builtin__.Plus[__builtin__.int] = __builtin__.IntegralD_int()\n\nW_Apa_105: __builtin__.Times[__builtin__.int, __builtin__.int] = __builtin__.IntegralD_int()\n\nW_Apa_308: __builtin__.Eq[__builtin__.int] = __builtin__.OrdD_int()\n\n# recursive group:\nactor Apa ():\n    proc def setup (cb : action(__builtin__.int) -> __builtin__.int) -> None:\n        print@[(__builtin__.str,)]((\"\\\"setup\\\"\",), None, None, None, None)\n        cb(W_Apa_39.__fromatom__(0))\n        return None\n    proc def compute (cb : action(__builtin__.int) -> __builtin__.int) -> __builtin__.int:\n        print@[(__builtin__.str,)]((\"\\\"compute\\\"\",), None, None, None, None)\n        v: __builtin__.int = cb(W_Apa_39.__fromatom__(1))\n        m: __builtin__.Msg[__builtin__.int] = (async cb)(W_Apa_39.__fromatom__(2))\n        N_tmp: __builtin__.int = W_Apa_105.__mul__(v, W_Apa_39.__fromatom__(10))\n        return N_tmp\n    proc def notice (i : __builtin__.int) -> __builtin__.int:\n        print@[(__builtin__.str,)]((\"\\\"notice\\\"\",), None, None, None, None)\n        N_1tmp: __builtin__.int = W_Apa_140.__add__(i, W_Apa_39.__fromatom__(1))\n        return N_1tmp\n    setup($WRAP@[(), (__builtin__.int,), __builtin__.int](self, notice))\n    print@[(__builtin__.str,)]((\"\\\"Apa\\\"\",), None, None, None, None)\nactor Bepa ():\n    proc def callback (i : __builtin__.int) -> __builtin__.int:\n        print@[(__builtin__.str, __builtin__.int)]((\"\\\"callback\\\"\", i), None, None, None, None)\n        N_2tmp: __builtin__.int = W_Apa_140.__add__(i, W_Apa_39.__fromatom__(1))\n        return N_2tmp\n    print@[(__builtin__.str,)]((\"\\\"Bepa\\\"\",), None, None, None, None)\nactor main (env : __builtin__.Env):\n    proc def myproc (i : __builtin__.int) -> __builtin__.int:\n        print@[(__builtin__.str, __builtin__.int)]((\"\\\"myproc\\\"\", i), None, None, None, None)\n        if W_Apa_308.__eq__(i, W_Apa_39.__fromatom__(2)):\n            env.exit(W_Apa_39.__fromatom__(0))\n        return i\n    a: Apa = Apa()\n    b: Bepa = Bepa()\n    print@[(__builtin__.str,)]((\"\\\"-----\\\"\",), None, None, None, None)\n    a.setup(a.notice)\n    x: __builtin__.Msg[__builtin__.int] = (async a.compute)(b.callback)\n    r: __builtin__.int = await x\n    print@[(__builtin__.str, __builtin__.int)]((\"\\\"r =\\\"\", r), None, None, None, None)\n    a.compute($WRAP@[(), (__builtin__.int,), __builtin__.int](self, myproc))\n    print@[(__builtin__.str,)]((\"\\\"main\\\"\",), None, None, None, None)\n# (recursive group)"
  },
  {
    "path": "compiler/lib/test/5-deactorizer/deact.input",
    "content": "W_Apa_39: __builtin__.Number[__builtin__.int] = __builtin__.IntegralD_int()\n\nW_Apa_140: __builtin__.Plus[__builtin__.int] = __builtin__.IntegralD_int()\n\nW_Apa_105: __builtin__.Times[__builtin__.int, __builtin__.int] = __builtin__.IntegralD_int()\n\nW_Apa_308: __builtin__.Eq[__builtin__.int] = __builtin__.OrdD_int()\n\n# recursive group:\nactor Apa ():\n    proc def setup (cb : action(__builtin__.int) -> __builtin__.int) -> None:\n        print@[(__builtin__.str,)]((\"\\\"setup\\\"\",), None, None, None, None)\n        cb(W_Apa_39.__fromatom__(0))\n        return None\n    proc def compute (cb : action(__builtin__.int) -> __builtin__.int) -> __builtin__.int:\n        print@[(__builtin__.str,)]((\"\\\"compute\\\"\",), None, None, None, None)\n        v: __builtin__.int = cb(W_Apa_39.__fromatom__(1))\n        m: __builtin__.Msg[__builtin__.int] = (async cb)(W_Apa_39.__fromatom__(2))\n        N_tmp: __builtin__.int = W_Apa_105.__mul__(v, W_Apa_39.__fromatom__(10))\n        return N_tmp\n    proc def notice (i : __builtin__.int) -> __builtin__.int:\n        print@[(__builtin__.str,)]((\"\\\"notice\\\"\",), None, None, None, None)\n        N_1tmp: __builtin__.int = W_Apa_140.__add__(i, W_Apa_39.__fromatom__(1))\n        return N_1tmp\n    setup($WRAP@[(), (__builtin__.int,), __builtin__.int](self, notice))\n    print@[(__builtin__.str,)]((\"\\\"Apa\\\"\",), None, None, None, None)\nactor Bepa ():\n    proc def callback (i : __builtin__.int) -> __builtin__.int:\n        print@[(__builtin__.str, __builtin__.int)]((\"\\\"callback\\\"\", i), None, None, None, None)\n        N_2tmp: __builtin__.int = W_Apa_140.__add__(i, W_Apa_39.__fromatom__(1))\n        return N_2tmp\n    print@[(__builtin__.str,)]((\"\\\"Bepa\\\"\",), None, None, None, None)\nactor main (env : __builtin__.Env):\n    proc def myproc (i : __builtin__.int) -> __builtin__.int:\n        print@[(__builtin__.str, __builtin__.int)]((\"\\\"myproc\\\"\", i), None, None, None, None)\n        if W_Apa_308.__eq__(i, W_Apa_39.__fromatom__(2)):\n            env.exit(W_Apa_39.__fromatom__(0))\n        return i\n    a: Apa = Apa()\n    b: Bepa = Bepa()\n    print@[(__builtin__.str,)]((\"\\\"-----\\\"\",), None, None, None, None)\n    a.setup(a.notice)\n    x: __builtin__.Msg[__builtin__.int] = (async a.compute)(b.callback)\n    r: __builtin__.int = await x\n    print@[(__builtin__.str, __builtin__.int)]((\"\\\"r =\\\"\", r), None, None, None, None)\n    a.compute($WRAP@[(), (__builtin__.int,), __builtin__.int](self, myproc))\n    print@[(__builtin__.str,)]((\"\\\"main\\\"\",), None, None, None, None)\n# (recursive group)"
  },
  {
    "path": "compiler/lib/test/5-deactorizer/deact.output",
    "content": "W_Apa_39: __builtin__.Number[__builtin__.int] = __builtin__.IntegralD_int()\n\nW_Apa_140: __builtin__.Plus[__builtin__.int] = __builtin__.IntegralD_int()\n\nW_Apa_105: __builtin__.Times[__builtin__.int, __builtin__.int] = __builtin__.IntegralD_int()\n\nW_Apa_308: __builtin__.Eq[__builtin__.int] = __builtin__.OrdD_int()\n\n# recursive group:\nclass Apa ($Actor, __builtin__.value):\n    proc def __init__ (self : Self) -> None:\n        self.setupG_local(self.notice)\n        print@[(__builtin__.str,)]((\"\\\"Apa\\\"\",), None, None, None, None)\n    proc def setupG_local (self : Self, cb : action(__builtin__.int) -> __builtin__.int) -> None:\n        print@[(__builtin__.str,)]((\"\\\"setup\\\"\",), None, None, None, None)\n        (async cb)(W_Apa_39.__fromatom__(0))\n        return None\n    proc def computeG_local (self : Self, cb : action(__builtin__.int) -> __builtin__.int) -> __builtin__.int:\n        print@[(__builtin__.str,)]((\"\\\"compute\\\"\",), None, None, None, None)\n        v: __builtin__.int = $AWAITf@[__builtin__.int]((async cb)(W_Apa_39.__fromatom__(1)))\n        m: __builtin__.Msg[__builtin__.int] = (async cb)(W_Apa_39.__fromatom__(2))\n        N_tmp: __builtin__.int = W_Apa_105.__mul__(v, W_Apa_39.__fromatom__(10))\n        return N_tmp\n    proc def noticeG_local (self : Self, i : __builtin__.int) -> __builtin__.int:\n        print@[(__builtin__.str,)]((\"\\\"notice\\\"\",), None, None, None, None)\n        N_1tmp: __builtin__.int = W_Apa_140.__add__(i, W_Apa_39.__fromatom__(1))\n        return N_1tmp\n    action def setup (self : Self, cb : action(__builtin__.int) -> __builtin__.int) -> None:\n        return $ASYNCf@[None](self, proc lambda: self.setupG_local(cb))\n    action def compute (self : Self, cb : action(__builtin__.int) -> __builtin__.int) -> __builtin__.int:\n        return $ASYNCf@[__builtin__.int](self, proc lambda: self.computeG_local(cb))\n    action def notice (self : Self, i : __builtin__.int) -> __builtin__.int:\n        return $ASYNCf@[__builtin__.int](self, proc lambda: self.noticeG_local(i))\nclass Bepa ($Actor, __builtin__.value):\n    proc def __init__ (self : Self) -> None:\n        print@[(__builtin__.str,)]((\"\\\"Bepa\\\"\",), None, None, None, None)\n    proc def callbackG_local (self : Self, i : __builtin__.int) -> __builtin__.int:\n        print@[(__builtin__.str, __builtin__.int)]((\"\\\"callback\\\"\", i), None, None, None, None)\n        N_2tmp: __builtin__.int = W_Apa_140.__add__(i, W_Apa_39.__fromatom__(1))\n        return N_2tmp\n    action def callback (self : Self, i : __builtin__.int) -> __builtin__.int:\n        return $ASYNCf@[__builtin__.int](self, proc lambda: self.callbackG_local(i))\nclass main ($Actor, __builtin__.value):\n    @property\n    env : __builtin__.Env\n    @property\n    a : Apa\n    @property\n    b : Bepa\n    @property\n    x : __builtin__.Msg[__builtin__.int]\n    @property\n    r : __builtin__.int\n    proc def __init__ (self : Self, env : __builtin__.Env) -> None:\n        self.env = env\n        self.a = ApaG_newact()\n        self.b = BepaG_newact()\n        print@[(__builtin__.str,)]((\"\\\"-----\\\"\",), None, None, None, None)\n        (async self.a.setup)(self.a.notice)\n        self.x = (async self.a.compute)(self.b.callback)\n        self.r = $AWAITf@[__builtin__.int](self.x)\n        print@[(__builtin__.str, __builtin__.int)]((\"\\\"r =\\\"\", self.r), None, None, None, None)\n        (async self.a.compute)(self.myproc)\n        print@[(__builtin__.str,)]((\"\\\"main\\\"\",), None, None, None, None)\n    proc def myprocG_local (self : Self, i : __builtin__.int) -> __builtin__.int:\n        print@[(__builtin__.str, __builtin__.int)]((\"\\\"myproc\\\"\", i), None, None, None, None)\n        if W_Apa_308.__eq__(i, W_Apa_39.__fromatom__(2)):\n            (async self.env.exit)(W_Apa_39.__fromatom__(0))\n        return i\n    action def myproc (self : Self, i : __builtin__.int) -> __builtin__.int:\n        return $ASYNCf@[__builtin__.int](self, proc lambda: self.myprocG_local(i))\nproc def ApaG_newact () -> Apa:\n    G_act: Apa = $NEWACTOR@[Apa]()\n    $InstallFinalizer@[Apa](G_act)\n    $AWAITf@[None]($ASYNCf@[None](G_act, proc lambda: G_act.__init__()))\n    return G_act\nproc def BepaG_newact () -> Bepa:\n    G_act: Bepa = $NEWACTOR@[Bepa]()\n    $InstallFinalizer@[Bepa](G_act)\n    $AWAITf@[None]($ASYNCf@[None](G_act, proc lambda: G_act.__init__()))\n    return G_act\nproc def mainG_newact (env : __builtin__.Env) -> main:\n    G_act: main = $NEWACTOR@[main]()\n    $InstallFinalizer@[main](G_act)\n    $AWAITf@[None]($ASYNCf@[None](G_act, proc lambda: G_act.__init__(env)))\n    return G_act\n# (recursive group)"
  },
  {
    "path": "compiler/lib/test/5-deactorizer/deact_from_import.input",
    "content": "from deact import Apa\nW_Manager_124: __builtin__.Number[__builtin__.int] = __builtin__.IntegralD_int()\n\n# recursive group:\nactor Manager ():\n    proc def create_decoder () -> __builtin__.StringDecoder:\n        decoder: __builtin__.StringDecoder = StringDecoder(self.decode_callback, None, None)\n        return decoder\n    proc def create_apa () -> deact.Apa:\n        apa: deact.Apa = Apa()\n        return apa\n    proc def decode_callback (s : __builtin__.str) -> None:\n        pass\n        return None\nactor main (env : __builtin__.Env):\n    mgr: Manager = Manager()\n    decoder: __builtin__.StringDecoder = mgr.create_decoder()\n    apa: deact.Apa = mgr.create_apa()\n    env.exit(W_Manager_124.__fromatom__(0))\n# (recursive group)"
  },
  {
    "path": "compiler/lib/test/5-deactorizer/deact_from_import.output",
    "content": "from deact import Apa\nW_Manager_124: __builtin__.Number[__builtin__.int] = __builtin__.IntegralD_int()\n\n# recursive group:\nclass Manager ($Actor, __builtin__.value):\n    proc def __init__ (self : Self) -> None:\n        pass\n    proc def create_decoderG_local (self : Self) -> __builtin__.StringDecoder:\n        decoder: __builtin__.StringDecoder = __builtin__.StringDecoderG_newact(self.decode_callback, None, None)\n        return decoder\n    proc def create_apaG_local (self : Self) -> deact.Apa:\n        apa: deact.Apa = deact.ApaG_newact()\n        return apa\n    proc def decode_callbackG_local (self : Self, s : __builtin__.str) -> None:\n        pass\n        return None\n    action def create_decoder (self : Self) -> __builtin__.StringDecoder:\n        return $ASYNCf@[__builtin__.StringDecoder](self, proc lambda: self.create_decoderG_local())\n    action def create_apa (self : Self) -> deact.Apa:\n        return $ASYNCf@[deact.Apa](self, proc lambda: self.create_apaG_local())\n    action def decode_callback (self : Self, s : __builtin__.str) -> None:\n        return $ASYNCf@[None](self, proc lambda: self.decode_callbackG_local(s))\nclass main ($Actor, __builtin__.value):\n    @property\n    mgr : Manager\n    @property\n    decoder : __builtin__.StringDecoder\n    @property\n    apa : deact.Apa\n    proc def __init__ (self : Self, env : __builtin__.Env) -> None:\n        self.mgr = ManagerG_newact()\n        self.decoder = $AWAITf@[__builtin__.StringDecoder]((async self.mgr.create_decoder)())\n        self.apa = $AWAITf@[deact.Apa]((async self.mgr.create_apa)())\n        (async env.exit)(W_Manager_124.__fromatom__(0))\nproc def ManagerG_newact () -> Manager:\n    G_act: Manager = $NEWACTOR@[Manager]()\n    $InstallFinalizer@[Manager](G_act)\n    $AWAITf@[None]($ASYNCf@[None](G_act, proc lambda: G_act.__init__()))\n    return G_act\nproc def mainG_newact (env : __builtin__.Env) -> main:\n    G_act: main = $NEWACTOR@[main]()\n    $InstallFinalizer@[main](G_act)\n    $AWAITf@[None]($ASYNCf@[None](G_act, proc lambda: G_act.__init__(env)))\n    return G_act\n# (recursive group)"
  },
  {
    "path": "compiler/lib/test/6-cps/cps_andor.input",
    "content": "proc def p () -> __builtin__.bool:\n    return True\n\nproc def f (b : __builtin__.bool) -> __builtin__.bool:\n    N_tmp: __builtin__.bool = b and p()\n    return N_tmp\n\nproc def g (b : __builtin__.bool) -> __builtin__.bool:\n    N_1tmp: __builtin__.bool = b or p()\n    return N_1tmp"
  },
  {
    "path": "compiler/lib/test/6-cps/cps_andor.output",
    "content": "proc def p (C_cont : proc(__builtin__.bool) -> $R) -> $R:\n    return $R_CONTc@[__builtin__.bool](C_cont, True)\n\nproc def f (C_cont : proc(__builtin__.bool) -> $R, b : __builtin__.bool) -> $R:\n    C_2pre: __builtin__.bool = b\n    proc def C_7cont (C_8res : None, C_3pre : __builtin__.bool) -> $R:\n        N_tmp: __builtin__.bool = C_3pre\n        return $R_CONTc@[__builtin__.bool](C_cont, N_tmp)\n    if C_2pre:\n        proc def C_9cont (C_10res : __builtin__.bool) -> $R:\n            C_1pre: __builtin__.bool = C_10res\n            C_3pre: __builtin__.bool = C_1pre\n            return $R_CONTc@[None](proc lambda (G_skip : None): C_7cont(G_skip, C_3pre), None)\n        return p(C_9cont)\n    else:\n        C_3pre: __builtin__.bool = C_2pre\n        return $R_CONTc@[None](proc lambda (G_skip : None): C_7cont(G_skip, C_3pre), None)\n\nproc def g (C_cont : proc(__builtin__.bool) -> $R, b : __builtin__.bool) -> $R:\n    C_5pre: __builtin__.bool = b\n    proc def C_11cont (C_12res : None, C_6pre : __builtin__.bool) -> $R:\n        N_1tmp: __builtin__.bool = C_6pre\n        return $R_CONTc@[__builtin__.bool](C_cont, N_1tmp)\n    if C_5pre:\n        C_6pre: __builtin__.bool = C_5pre\n        return $R_CONTc@[None](proc lambda (G_skip : None): C_11cont(G_skip, C_6pre), None)\n    else:\n        proc def C_13cont (C_14res : __builtin__.bool) -> $R:\n            C_4pre: __builtin__.bool = C_14res\n            C_6pre: __builtin__.bool = C_4pre\n            return $R_CONTc@[None](proc lambda (G_skip : None): C_11cont(G_skip, C_6pre), None)\n        return p(C_13cont)"
  },
  {
    "path": "compiler/lib/test/6-cps/cps_optchain.input",
    "content": "class Cls (__builtin__.value):\n    pure def G_init (self : Self) -> None:\n        pass\n        return None\n    proc def f (self : Self, msg : __builtin__.str) -> None:\n        pass\n        return None\n\nproc def maybe_log (c : ?Cls) -> None:\n    let:\n        V_maybe_log_9: ?Cls = c\n    in $CAST@[?Cls, Cls](V_maybe_log_9).f(\"\\\"boom\\\"\") if $ISNOTNONE@[Cls](V_maybe_log_9) else None\n    return None"
  },
  {
    "path": "compiler/lib/test/6-cps/cps_optchain.output",
    "content": "class Cls (__builtin__.value):\n    pure def G_init (self : Self) -> None:\n        pass\n        return None\n    proc def f (self : Self, C_cont : proc(None) -> $R, msg : __builtin__.str) -> $R:\n        pass\n        return $R_CONTc@[None](C_cont, None)\n\nproc def maybe_log (C_cont : proc(None) -> $R, c : ?Cls) -> $R:\n    V_maybe_log_9: ?Cls = c\n    proc def C_3cont (C_4res : None, C_2pre : None) -> $R:\n        C_2pre\n        return $R_CONTc@[None](C_cont, None)\n    if $ISNOTNONE@[Cls](V_maybe_log_9):\n        proc def C_5cont (C_6res : None) -> $R:\n            C_1pre: None = C_6res\n            C_2pre: None = C_1pre\n            return $R_CONTc@[None](proc lambda (G_skip : None): C_3cont(G_skip, C_2pre), None)\n        return $CAST@[?Cls, Cls](V_maybe_log_9).f(C_5cont, \"\\\"boom\\\"\")\n    else:\n        C_2pre: None = None\n        return $R_CONTc@[None](proc lambda (G_skip : None): C_3cont(G_skip, C_2pre), None)"
  },
  {
    "path": "compiler/lib/test/6-cps/cps_volatiles.input",
    "content": "proc def force_cps (arg : __builtin__.int) -> __builtin__.int:\n    return arg\n\nproc def compute (aa : __builtin__.int) -> __builtin__.int:\n    W_compute_19: __builtin__.Plus[__builtin__.int] = __builtin__.IntegralD_int()\n    W_compute_4: __builtin__.Number[__builtin__.int] = __builtin__.IntegralD_int()\n    xx: __builtin__.int = W_compute_4.__fromatom__(1)\n    if $PUSH():\n        xx = W_compute_19.__iadd__(xx, force_cps(W_compute_4.__fromatom__(1)))\n        aa = W_compute_19.__iadd__(aa, force_cps(W_compute_4.__fromatom__(1)))\n        $DROP()\n    else:\n        N_x: __builtin__.BaseException = $POP()\n        if isinstance(N_x, ValueError):\n            pass\n        else:\n            $RAISE(N_x)\n    N_1tmp: __builtin__.int = W_compute_19.__add__(xx, aa)\n    return N_1tmp\n\nW_main_74: __builtin__.Number[__builtin__.int] = __builtin__.IntegralD_int()\n\nW_main_91: __builtin__.Eq[__builtin__.int] = __builtin__.OrdD_int()\n\nW_main_29: __builtin__.Eq[?__builtin__.int] = $EqOpt@[__builtin__.int](W_main_91)\n\n# recursive group:\nclass main ($Actor, __builtin__.value):\n    @property\n    v : __builtin__.int\n    proc def __init__ (self : Self, env : __builtin__.Env) -> None:\n        self.v = compute(W_main_74.__fromatom__(10))\n        if W_main_29.__eq__(self.v, W_main_74.__fromatom__(13)):\n            (async env.exit)(W_main_74.__fromatom__(0))\n        else:\n            print@[(__builtin__.str, __builtin__.int)]((\"\\\"Excpected 13, got\\\"\", self.v), None, None, None, None)\n            (async env.exit)(W_main_74.__fromatom__(1))\nproc def mainG_newact (env : __builtin__.Env) -> main:\n    G_act: main = $NEWACTOR@[main]()\n    $InstallFinalizer@[main](G_act)\n    $AWAITf@[None]($ASYNCf@[None](G_act, proc lambda: G_act.__init__(env)))\n    return G_act\n# (recursive group)"
  },
  {
    "path": "compiler/lib/test/6-cps/cps_volatiles.output",
    "content": "proc def force_cps (C_cont : proc(__builtin__.int) -> $R, arg : __builtin__.int) -> $R:\n    return $R_CONTc@[__builtin__.int](C_cont, arg)\n\nproc def compute (C_cont : proc(__builtin__.int) -> $R, aa : __builtin__.int) -> $R:\n    aa: $Box[__builtin__.int] = $Box@[__builtin__.int](aa)\n    W_compute_19: __builtin__.Plus[__builtin__.int] = __builtin__.IntegralD_int()\n    W_compute_4: __builtin__.Number[__builtin__.int] = __builtin__.IntegralD_int()\n    xx: $Box[__builtin__.int] = $Box@[__builtin__.int](W_compute_4.__fromatom__(1))\n    proc def C_3cont (C_4res : None) -> $R:\n        N_1tmp: __builtin__.int = W_compute_19.__add__(xx.val, aa.val)\n        return $R_CONTc@[__builtin__.int](C_cont, N_1tmp)\n    proc def C_5try (C_6res : __builtin__.bool) -> $R:\n        if C_6res:\n            proc def C_7cont (C_8res : __builtin__.int) -> $R:\n                C_1pre: __builtin__.int = C_8res\n                xx.val = W_compute_19.__iadd__(xx.val, C_1pre)\n                proc def C_9cont (C_10res : __builtin__.int) -> $R:\n                    C_2pre: __builtin__.int = C_10res\n                    aa.val = W_compute_19.__iadd__(aa.val, C_2pre)\n                    $DROP_C()\n                    return $R_CONTc@[None](C_3cont, None)\n                return force_cps(C_9cont, W_compute_4.__fromatom__(1))\n            return force_cps(C_7cont, W_compute_4.__fromatom__(1))\n        else:\n            N_x: __builtin__.BaseException = $POP_C()\n            if isinstance(N_x, ValueError):\n                pass\n            else:\n                $RAISE(N_x)\n            return $R_CONTc@[None](C_3cont, None)\n    return $PUSH_Cc(C_5try)\n\nW_main_74: __builtin__.Number[__builtin__.int] = __builtin__.IntegralD_int()\n\nW_main_91: __builtin__.Eq[__builtin__.int] = __builtin__.OrdD_int()\n\nW_main_29: __builtin__.Eq[?__builtin__.int] = $EqOpt@[__builtin__.int](W_main_91)\n\n# recursive group:\nclass main ($Actor, __builtin__.value):\n    @property\n    v : __builtin__.int\n    proc def __init__ (self : Self, C_cont : proc(None) -> $R, env : __builtin__.Env) -> $R:\n        proc def C_11cont (C_12res : __builtin__.int) -> $R:\n            self.v = C_12res\n            if W_main_29.__eq__(self.v, W_main_74.__fromatom__(13)):\n                (async env.exit)(W_main_74.__fromatom__(0))\n            else:\n                print@[(__builtin__.str, __builtin__.int)]((\"\\\"Excpected 13, got\\\"\", self.v), None, None, None, None)\n                (async env.exit)(W_main_74.__fromatom__(1))\n            return $R_CONTc@[None](C_cont, None)\n        return compute(C_11cont, W_main_74.__fromatom__(10))\nproc def mainG_newact (C_cont : proc(main) -> $R, env : __builtin__.Env) -> $R:\n    G_act: main = $NEWACTOR@[main]()\n    $InstallFinalizer@[main](G_act)\n    proc def C_13cont (C_14res : None) -> $R:\n        return $R_CONTc@[main](C_cont, G_act)\n    return $AWAITc@[None](C_13cont, $ASYNCc@[None](G_act, proc lambda (C_cont : proc(None) -> $R): G_act.__init__(C_cont, env)))\n# (recursive group)"
  },
  {
    "path": "compiler/lib/test/7-lambdalifting/deact.input",
    "content": "W_Apa_39: __builtin__.Number[__builtin__.int] = __builtin__.IntegralD_int()\n\nW_Apa_140: __builtin__.Plus[__builtin__.int] = __builtin__.IntegralD_int()\n\nW_Apa_105: __builtin__.Times[__builtin__.int, __builtin__.int] = __builtin__.IntegralD_int()\n\nW_Apa_308: __builtin__.Eq[__builtin__.int] = __builtin__.OrdD_int()\n\n# recursive group:\nclass Apa ($Actor, __builtin__.value):\n    proc def __init__ (self : Self, C_cont : proc(None) -> $R) -> $R:\n        proc def C_1cont (C_2res : None) -> $R:\n            print@[(__builtin__.str,)]((\"\\\"Apa\\\"\",), None, None, None, None)\n            return $R_CONTc@[None](C_cont, None)\n        return self.setupG_local(C_1cont, self.notice)\n    proc def setupG_local (self : Self, C_cont : proc(None) -> $R, cb : action(__builtin__.int) -> __builtin__.int) -> $R:\n        print@[(__builtin__.str,)]((\"\\\"setup\\\"\",), None, None, None, None)\n        (async cb)(W_Apa_39.__fromatom__(0))\n        return $R_CONTc@[None](C_cont, None)\n    proc def computeG_local (self : Self, C_cont : proc(__builtin__.int) -> $R, cb : action(__builtin__.int) -> __builtin__.int) -> $R:\n        print@[(__builtin__.str,)]((\"\\\"compute\\\"\",), None, None, None, None)\n        proc def C_3cont (C_4res : __builtin__.int) -> $R:\n            v: __builtin__.int = C_4res\n            m: __builtin__.Msg[__builtin__.int] = (async cb)(W_Apa_39.__fromatom__(2))\n            N_tmp: __builtin__.int = W_Apa_105.__mul__(v, W_Apa_39.__fromatom__(10))\n            return $R_CONTc@[__builtin__.int](C_cont, N_tmp)\n        return $AWAITc@[__builtin__.int](C_3cont, (async cb)(W_Apa_39.__fromatom__(1)))\n    proc def noticeG_local (self : Self, C_cont : proc(__builtin__.int) -> $R, i : __builtin__.int) -> $R:\n        print@[(__builtin__.str,)]((\"\\\"notice\\\"\",), None, None, None, None)\n        N_1tmp: __builtin__.int = W_Apa_140.__add__(i, W_Apa_39.__fromatom__(1))\n        return $R_CONTc@[__builtin__.int](C_cont, N_1tmp)\n    action def setup (self : Self, cb : action(__builtin__.int) -> __builtin__.int) -> None:\n        return $ASYNCc@[None](self, proc lambda (C_cont : proc(None) -> $R): self.setupG_local(C_cont, cb))\n    action def compute (self : Self, cb : action(__builtin__.int) -> __builtin__.int) -> __builtin__.int:\n        return $ASYNCc@[__builtin__.int](self, proc lambda (C_cont : proc(__builtin__.int) -> $R): self.computeG_local(C_cont, cb))\n    action def notice (self : Self, i : __builtin__.int) -> __builtin__.int:\n        return $ASYNCc@[__builtin__.int](self, proc lambda (C_cont : proc(__builtin__.int) -> $R): self.noticeG_local(C_cont, i))\nclass Bepa ($Actor, __builtin__.value):\n    proc def __init__ (self : Self, C_cont : proc(None) -> $R) -> $R:\n        print@[(__builtin__.str,)]((\"\\\"Bepa\\\"\",), None, None, None, None)\n        return $R_CONTc@[None](C_cont, None)\n    proc def callbackG_local (self : Self, C_cont : proc(__builtin__.int) -> $R, i : __builtin__.int) -> $R:\n        print@[(__builtin__.str, __builtin__.int)]((\"\\\"callback\\\"\", i), None, None, None, None)\n        N_2tmp: __builtin__.int = W_Apa_140.__add__(i, W_Apa_39.__fromatom__(1))\n        return $R_CONTc@[__builtin__.int](C_cont, N_2tmp)\n    action def callback (self : Self, i : __builtin__.int) -> __builtin__.int:\n        return $ASYNCc@[__builtin__.int](self, proc lambda (C_cont : proc(__builtin__.int) -> $R): self.callbackG_local(C_cont, i))\nclass main ($Actor, __builtin__.value):\n    @property\n    env : __builtin__.Env\n    @property\n    a : Apa\n    @property\n    b : Bepa\n    @property\n    x : __builtin__.Msg[__builtin__.int]\n    @property\n    r : __builtin__.int\n    proc def __init__ (self : Self, C_cont : proc(None) -> $R, env : __builtin__.Env) -> $R:\n        self.env = env\n        proc def C_5cont (C_6res : Apa) -> $R:\n            self.a = C_6res\n            proc def C_7cont (C_8res : Bepa) -> $R:\n                self.b = C_8res\n                print@[(__builtin__.str,)]((\"\\\"-----\\\"\",), None, None, None, None)\n                (async self.a.setup)(self.a.notice)\n                self.x = (async self.a.compute)(self.b.callback)\n                proc def C_9cont (C_10res : __builtin__.int) -> $R:\n                    self.r = C_10res\n                    print@[(__builtin__.str, __builtin__.int)]((\"\\\"r =\\\"\", self.r), None, None, None, None)\n                    (async self.a.compute)(self.myproc)\n                    print@[(__builtin__.str,)]((\"\\\"main\\\"\",), None, None, None, None)\n                    return $R_CONTc@[None](C_cont, None)\n                return $AWAITc@[__builtin__.int](C_9cont, self.x)\n            return BepaG_newact(C_7cont)\n        return ApaG_newact(C_5cont)\n    proc def myprocG_local (self : Self, C_cont : proc(__builtin__.int) -> $R, i : __builtin__.int) -> $R:\n        print@[(__builtin__.str, __builtin__.int)]((\"\\\"myproc\\\"\", i), None, None, None, None)\n        if W_Apa_308.__eq__(i, W_Apa_39.__fromatom__(2)):\n            (async self.env.exit)(W_Apa_39.__fromatom__(0))\n        return $R_CONTc@[__builtin__.int](C_cont, i)\n    action def myproc (self : Self, i : __builtin__.int) -> __builtin__.int:\n        return $ASYNCc@[__builtin__.int](self, proc lambda (C_cont : proc(__builtin__.int) -> $R): self.myprocG_local(C_cont, i))\nproc def ApaG_newact (C_cont : proc(Apa) -> $R) -> $R:\n    G_act: Apa = $NEWACTOR@[Apa]()\n    $InstallFinalizer@[Apa](G_act)\n    proc def C_11cont (C_12res : None) -> $R:\n        return $R_CONTc@[Apa](C_cont, G_act)\n    return $AWAITc@[None](C_11cont, $ASYNCc@[None](G_act, proc lambda (C_cont : proc(None) -> $R): G_act.__init__(C_cont)))\nproc def BepaG_newact (C_cont : proc(Bepa) -> $R) -> $R:\n    G_act: Bepa = $NEWACTOR@[Bepa]()\n    $InstallFinalizer@[Bepa](G_act)\n    proc def C_13cont (C_14res : None) -> $R:\n        return $R_CONTc@[Bepa](C_cont, G_act)\n    return $AWAITc@[None](C_13cont, $ASYNCc@[None](G_act, proc lambda (C_cont : proc(None) -> $R): G_act.__init__(C_cont)))\nproc def mainG_newact (C_cont : proc(main) -> $R, env : __builtin__.Env) -> $R:\n    G_act: main = $NEWACTOR@[main]()\n    $InstallFinalizer@[main](G_act)\n    proc def C_15cont (C_16res : None) -> $R:\n        return $R_CONTc@[main](C_cont, G_act)\n    return $AWAITc@[None](C_15cont, $ASYNCc@[None](G_act, proc lambda (C_cont : proc(None) -> $R): G_act.__init__(C_cont, env)))\n# (recursive group)"
  },
  {
    "path": "compiler/lib/test/7-lambdalifting/deact.output",
    "content": "W_Apa_39: __builtin__.Number[__builtin__.int] = __builtin__.IntegralD_int()\n\nW_Apa_140: __builtin__.Plus[__builtin__.int] = __builtin__.IntegralD_int()\n\nW_Apa_105: __builtin__.Times[__builtin__.int, __builtin__.int] = __builtin__.IntegralD_int()\n\nW_Apa_308: __builtin__.Eq[__builtin__.int] = __builtin__.OrdD_int()\n\n# recursive group:\nproc def L_1C_1cont (C_cont : $Cont[None], C_2res : None) -> $R:\n    print@[(__builtin__.str,)]((\"\\\"Apa\\\"\",), None, None, None, None)\n    return $R_CONT@[None](C_cont, None)\nclass L_2Cont ($Cont[None], __builtin__.value):\n    @property\n    C_cont : $Cont[None]\n    pure def __init__ (L_self : Self, C_cont : $Cont[None]) -> None:\n        L_self.C_cont = C_cont\n        return None\n    proc def __call__ (L_self : Self, G_1 : None) -> $R:\n        C_cont: $Cont[None] = L_self.C_cont\n        return L_1C_1cont(C_cont, G_1)\nclass L_4action ($action[(__builtin__.int,), __builtin__.int], $proc[(__builtin__.int,), __builtin__.int], __builtin__.value):\n    @property\n    L_3obj : Apa\n    pure def __init__ (L_self : Self, L_3obj : Apa) -> None:\n        L_self.L_3obj = L_3obj\n        return None\n    # recursive group:\n    proc def __call__ (L_self : Self, L_cont : $Cont[__builtin__.int], G_1 : __builtin__.int) -> $R:\n        return $AWAIT@[__builtin__.int](L_cont, L_self.__asyn__(G_1))\n    proc def __exec__ (L_self : Self, L_cont : $Cont[__builtin__.value], G_1 : __builtin__.int) -> $R:\n        return $R_CONT@[__builtin__.value](L_cont, L_self.__asyn__(G_1))\n    action def __asyn__ (L_self : Self, G_1 : __builtin__.int) -> __builtin__.int:\n        L_3obj: Apa = L_self.L_3obj\n        return L_3obj.notice(G_1)\n    # (recursive group)\nproc def L_5C_3cont (cb : $action[(__builtin__.int,), __builtin__.int], C_cont : $Cont[__builtin__.int], C_4res : __builtin__.int) -> $R:\n    v: __builtin__.int = C_4res\n    m: __builtin__.Msg[__builtin__.int] = cb.__asyn__(W_Apa_39.__fromatom__(2))\n    N_tmp: __builtin__.int = W_Apa_105.__mul__(v, W_Apa_39.__fromatom__(10))\n    return $R_CONT@[__builtin__.int](C_cont, N_tmp)\nclass L_6Cont ($Cont[__builtin__.int], __builtin__.value):\n    @property\n    cb : $action[(__builtin__.int,), __builtin__.int]\n    @property\n    C_cont : $Cont[__builtin__.int]\n    pure def __init__ (L_self : Self, cb : $action[(__builtin__.int,), __builtin__.int], C_cont : $Cont[__builtin__.int]) -> None:\n        L_self.cb = cb\n        L_self.C_cont = C_cont\n        return None\n    proc def __call__ (L_self : Self, G_1 : __builtin__.int) -> $R:\n        cb: $action[(__builtin__.int,), __builtin__.int] = L_self.cb\n        C_cont: $Cont[__builtin__.int] = L_self.C_cont\n        return L_5C_3cont(cb, C_cont, G_1)\nclass L_7proc ($proc[(), None], __builtin__.value):\n    @property\n    self : Apa\n    @property\n    cb : $action[(__builtin__.int,), __builtin__.int]\n    pure def __init__ (L_self : Self, self : Apa, cb : $action[(__builtin__.int,), __builtin__.int]) -> None:\n        L_self.self = self\n        L_self.cb = cb\n        return None\n    # recursive group:\n    proc def __call__ (L_self : Self, C_cont : $Cont[None]) -> $R:\n        self: Apa = L_self.self\n        cb: $action[(__builtin__.int,), __builtin__.int] = L_self.cb\n        return self.setupG_local(C_cont, cb)\n    proc def __exec__ (L_self : Self, C_cont : $Cont[None]) -> $R:\n        return L_self.__call__(C_cont)\n    # (recursive group)\nclass L_8proc ($proc[(), __builtin__.int], __builtin__.value):\n    @property\n    self : Apa\n    @property\n    cb : $action[(__builtin__.int,), __builtin__.int]\n    pure def __init__ (L_self : Self, self : Apa, cb : $action[(__builtin__.int,), __builtin__.int]) -> None:\n        L_self.self = self\n        L_self.cb = cb\n        return None\n    # recursive group:\n    proc def __call__ (L_self : Self, C_cont : $Cont[__builtin__.int]) -> $R:\n        self: Apa = L_self.self\n        cb: $action[(__builtin__.int,), __builtin__.int] = L_self.cb\n        return self.computeG_local(C_cont, cb)\n    proc def __exec__ (L_self : Self, C_cont : $Cont[__builtin__.int]) -> $R:\n        return L_self.__call__(C_cont)\n    # (recursive group)\nclass L_9proc ($proc[(), __builtin__.int], __builtin__.value):\n    @property\n    self : Apa\n    @property\n    i : __builtin__.int\n    pure def __init__ (L_self : Self, self : Apa, i : __builtin__.int) -> None:\n        L_self.self = self\n        L_self.i = i\n        return None\n    # recursive group:\n    proc def __call__ (L_self : Self, C_cont : $Cont[__builtin__.int]) -> $R:\n        self: Apa = L_self.self\n        i: __builtin__.int = L_self.i\n        return self.noticeG_local(C_cont, i)\n    proc def __exec__ (L_self : Self, C_cont : $Cont[__builtin__.int]) -> $R:\n        return L_self.__call__(C_cont)\n    # (recursive group)\nclass L_10proc ($proc[(), __builtin__.int], __builtin__.value):\n    @property\n    self : Bepa\n    @property\n    i : __builtin__.int\n    pure def __init__ (L_self : Self, self : Bepa, i : __builtin__.int) -> None:\n        L_self.self = self\n        L_self.i = i\n        return None\n    # recursive group:\n    proc def __call__ (L_self : Self, C_cont : $Cont[__builtin__.int]) -> $R:\n        self: Bepa = L_self.self\n        i: __builtin__.int = L_self.i\n        return self.callbackG_local(C_cont, i)\n    proc def __exec__ (L_self : Self, C_cont : $Cont[__builtin__.int]) -> $R:\n        return L_self.__call__(C_cont)\n    # (recursive group)\nclass L_14action ($action[(__builtin__.int,), __builtin__.int], $proc[(__builtin__.int,), __builtin__.int], __builtin__.value):\n    @property\n    L_13obj : Apa\n    pure def __init__ (L_self : Self, L_13obj : Apa) -> None:\n        L_self.L_13obj = L_13obj\n        return None\n    # recursive group:\n    proc def __call__ (L_self : Self, L_cont : $Cont[__builtin__.int], G_1 : __builtin__.int) -> $R:\n        return $AWAIT@[__builtin__.int](L_cont, L_self.__asyn__(G_1))\n    proc def __exec__ (L_self : Self, L_cont : $Cont[__builtin__.value], G_1 : __builtin__.int) -> $R:\n        return $R_CONT@[__builtin__.value](L_cont, L_self.__asyn__(G_1))\n    action def __asyn__ (L_self : Self, G_1 : __builtin__.int) -> __builtin__.int:\n        L_13obj: Apa = L_self.L_13obj\n        return L_13obj.notice(G_1)\n    # (recursive group)\nclass L_16action ($action[(__builtin__.int,), __builtin__.int], $proc[(__builtin__.int,), __builtin__.int], __builtin__.value):\n    @property\n    L_15obj : Bepa\n    pure def __init__ (L_self : Self, L_15obj : Bepa) -> None:\n        L_self.L_15obj = L_15obj\n        return None\n    # recursive group:\n    proc def __call__ (L_self : Self, L_cont : $Cont[__builtin__.int], G_1 : __builtin__.int) -> $R:\n        return $AWAIT@[__builtin__.int](L_cont, L_self.__asyn__(G_1))\n    proc def __exec__ (L_self : Self, L_cont : $Cont[__builtin__.value], G_1 : __builtin__.int) -> $R:\n        return $R_CONT@[__builtin__.value](L_cont, L_self.__asyn__(G_1))\n    action def __asyn__ (L_self : Self, G_1 : __builtin__.int) -> __builtin__.int:\n        L_15obj: Bepa = L_self.L_15obj\n        return L_15obj.callback(G_1)\n    # (recursive group)\nclass L_19action ($action[(__builtin__.int,), __builtin__.int], $proc[(__builtin__.int,), __builtin__.int], __builtin__.value):\n    @property\n    L_18obj : main\n    pure def __init__ (L_self : Self, L_18obj : main) -> None:\n        L_self.L_18obj = L_18obj\n        return None\n    # recursive group:\n    proc def __call__ (L_self : Self, L_cont : $Cont[__builtin__.int], G_1 : __builtin__.int) -> $R:\n        return $AWAIT@[__builtin__.int](L_cont, L_self.__asyn__(G_1))\n    proc def __exec__ (L_self : Self, L_cont : $Cont[__builtin__.value], G_1 : __builtin__.int) -> $R:\n        return $R_CONT@[__builtin__.value](L_cont, L_self.__asyn__(G_1))\n    action def __asyn__ (L_self : Self, G_1 : __builtin__.int) -> __builtin__.int:\n        L_18obj: main = L_self.L_18obj\n        return L_18obj.myproc(G_1)\n    # (recursive group)\nproc def L_17C_9cont (self : main, C_cont : $Cont[None], C_10res : __builtin__.int) -> $R:\n    self.r = C_10res\n    print@[(__builtin__.str, __builtin__.int)]((\"\\\"r =\\\"\", self.r), None, None, None, None)\n    (async self.a.compute)(L_19action(self))\n    print@[(__builtin__.str,)]((\"\\\"main\\\"\",), None, None, None, None)\n    return $R_CONT@[None](C_cont, None)\nclass L_20Cont ($Cont[__builtin__.int], __builtin__.value):\n    @property\n    self : main\n    @property\n    C_cont : $Cont[None]\n    pure def __init__ (L_self : Self, self : main, C_cont : $Cont[None]) -> None:\n        L_self.self = self\n        L_self.C_cont = C_cont\n        return None\n    proc def __call__ (L_self : Self, G_1 : __builtin__.int) -> $R:\n        self: main = L_self.self\n        C_cont: $Cont[None] = L_self.C_cont\n        return L_17C_9cont(self, C_cont, G_1)\nproc def L_12C_7cont (self : main, C_cont : $Cont[None], C_8res : Bepa) -> $R:\n    self.b = C_8res\n    print@[(__builtin__.str,)]((\"\\\"-----\\\"\",), None, None, None, None)\n    (async self.a.setup)(L_14action(self.a))\n    self.x = (async self.a.compute)(L_16action(self.b))\n    return $AWAIT@[__builtin__.int](L_20Cont(self, C_cont), self.x)\nclass L_21Cont ($Cont[Bepa], __builtin__.value):\n    @property\n    self : main\n    @property\n    C_cont : $Cont[None]\n    pure def __init__ (L_self : Self, self : main, C_cont : $Cont[None]) -> None:\n        L_self.self = self\n        L_self.C_cont = C_cont\n        return None\n    proc def __call__ (L_self : Self, G_1 : Bepa) -> $R:\n        self: main = L_self.self\n        C_cont: $Cont[None] = L_self.C_cont\n        return L_12C_7cont(self, C_cont, G_1)\nproc def L_11C_5cont (self : main, C_cont : $Cont[None], C_6res : Apa) -> $R:\n    self.a = C_6res\n    return BepaG_newact(L_21Cont(self, C_cont))\nclass L_22Cont ($Cont[Apa], __builtin__.value):\n    @property\n    self : main\n    @property\n    C_cont : $Cont[None]\n    pure def __init__ (L_self : Self, self : main, C_cont : $Cont[None]) -> None:\n        L_self.self = self\n        L_self.C_cont = C_cont\n        return None\n    proc def __call__ (L_self : Self, G_1 : Apa) -> $R:\n        self: main = L_self.self\n        C_cont: $Cont[None] = L_self.C_cont\n        return L_11C_5cont(self, C_cont, G_1)\nclass L_23proc ($proc[(), __builtin__.int], __builtin__.value):\n    @property\n    self : main\n    @property\n    i : __builtin__.int\n    pure def __init__ (L_self : Self, self : main, i : __builtin__.int) -> None:\n        L_self.self = self\n        L_self.i = i\n        return None\n    # recursive group:\n    proc def __call__ (L_self : Self, C_cont : $Cont[__builtin__.int]) -> $R:\n        self: main = L_self.self\n        i: __builtin__.int = L_self.i\n        return self.myprocG_local(C_cont, i)\n    proc def __exec__ (L_self : Self, C_cont : $Cont[__builtin__.int]) -> $R:\n        return L_self.__call__(C_cont)\n    # (recursive group)\nproc def L_24C_11cont (C_cont : $Cont[Apa], G_act : Apa, C_12res : None) -> $R:\n    return $R_CONT@[Apa](C_cont, G_act)\nclass L_25Cont ($Cont[None], __builtin__.value):\n    @property\n    C_cont : $Cont[Apa]\n    @property\n    G_act : Apa\n    pure def __init__ (L_self : Self, C_cont : $Cont[Apa], G_act : Apa) -> None:\n        L_self.C_cont = C_cont\n        L_self.G_act = G_act\n        return None\n    proc def __call__ (L_self : Self, G_1 : None) -> $R:\n        C_cont: $Cont[Apa] = L_self.C_cont\n        G_act: Apa = L_self.G_act\n        return L_24C_11cont(C_cont, G_act, G_1)\nclass L_26proc ($proc[(), None], __builtin__.value):\n    @property\n    G_act : Apa\n    pure def __init__ (L_self : Self, G_act : Apa) -> None:\n        L_self.G_act = G_act\n        return None\n    # recursive group:\n    proc def __call__ (L_self : Self, C_cont : $Cont[None]) -> $R:\n        G_act: Apa = L_self.G_act\n        return G_act.__init__(C_cont)\n    proc def __exec__ (L_self : Self, C_cont : $Cont[None]) -> $R:\n        return L_self.__call__(C_cont)\n    # (recursive group)\nproc def L_27C_13cont (C_cont : $Cont[Bepa], G_act : Bepa, C_14res : None) -> $R:\n    return $R_CONT@[Bepa](C_cont, G_act)\nclass L_28Cont ($Cont[None], __builtin__.value):\n    @property\n    C_cont : $Cont[Bepa]\n    @property\n    G_act : Bepa\n    pure def __init__ (L_self : Self, C_cont : $Cont[Bepa], G_act : Bepa) -> None:\n        L_self.C_cont = C_cont\n        L_self.G_act = G_act\n        return None\n    proc def __call__ (L_self : Self, G_1 : None) -> $R:\n        C_cont: $Cont[Bepa] = L_self.C_cont\n        G_act: Bepa = L_self.G_act\n        return L_27C_13cont(C_cont, G_act, G_1)\nclass L_29proc ($proc[(), None], __builtin__.value):\n    @property\n    G_act : Bepa\n    pure def __init__ (L_self : Self, G_act : Bepa) -> None:\n        L_self.G_act = G_act\n        return None\n    # recursive group:\n    proc def __call__ (L_self : Self, C_cont : $Cont[None]) -> $R:\n        G_act: Bepa = L_self.G_act\n        return G_act.__init__(C_cont)\n    proc def __exec__ (L_self : Self, C_cont : $Cont[None]) -> $R:\n        return L_self.__call__(C_cont)\n    # (recursive group)\nproc def L_30C_15cont (C_cont : $Cont[main], G_act : main, C_16res : None) -> $R:\n    return $R_CONT@[main](C_cont, G_act)\nclass L_31Cont ($Cont[None], __builtin__.value):\n    @property\n    C_cont : $Cont[main]\n    @property\n    G_act : main\n    pure def __init__ (L_self : Self, C_cont : $Cont[main], G_act : main) -> None:\n        L_self.C_cont = C_cont\n        L_self.G_act = G_act\n        return None\n    proc def __call__ (L_self : Self, G_1 : None) -> $R:\n        C_cont: $Cont[main] = L_self.C_cont\n        G_act: main = L_self.G_act\n        return L_30C_15cont(C_cont, G_act, G_1)\nclass L_32proc ($proc[(), None], __builtin__.value):\n    @property\n    G_act : main\n    @property\n    env : __builtin__.Env\n    pure def __init__ (L_self : Self, G_act : main, env : __builtin__.Env) -> None:\n        L_self.G_act = G_act\n        L_self.env = env\n        return None\n    # recursive group:\n    proc def __call__ (L_self : Self, C_cont : $Cont[None]) -> $R:\n        G_act: main = L_self.G_act\n        env: __builtin__.Env = L_self.env\n        return G_act.__init__(C_cont, env)\n    proc def __exec__ (L_self : Self, C_cont : $Cont[None]) -> $R:\n        return L_self.__call__(C_cont)\n    # (recursive group)\nclass Apa ($Actor, __builtin__.value):\n    proc def __init__ (self : Self, C_cont : $Cont[None]) -> $R:\n        return self.setupG_local(L_2Cont(C_cont), L_4action(self))\n    proc def setupG_local (self : Self, C_cont : $Cont[None], cb : $action[(__builtin__.int,), __builtin__.int]) -> $R:\n        print@[(__builtin__.str,)]((\"\\\"setup\\\"\",), None, None, None, None)\n        cb.__asyn__(W_Apa_39.__fromatom__(0))\n        return $R_CONT@[None](C_cont, None)\n    proc def computeG_local (self : Self, C_cont : $Cont[__builtin__.int], cb : $action[(__builtin__.int,), __builtin__.int]) -> $R:\n        print@[(__builtin__.str,)]((\"\\\"compute\\\"\",), None, None, None, None)\n        return $AWAIT@[__builtin__.int](L_6Cont(cb, C_cont), cb.__asyn__(W_Apa_39.__fromatom__(1)))\n    proc def noticeG_local (self : Self, C_cont : $Cont[__builtin__.int], i : __builtin__.int) -> $R:\n        print@[(__builtin__.str,)]((\"\\\"notice\\\"\",), None, None, None, None)\n        N_1tmp: __builtin__.int = W_Apa_140.__add__(i, W_Apa_39.__fromatom__(1))\n        return $R_CONT@[__builtin__.int](C_cont, N_1tmp)\n    action def setup (self : Self, cb : $action[(__builtin__.int,), __builtin__.int]) -> None:\n        return $ASYNC@[None](self, L_7proc(self, cb))\n    action def compute (self : Self, cb : $action[(__builtin__.int,), __builtin__.int]) -> __builtin__.int:\n        return $ASYNC@[__builtin__.int](self, L_8proc(self, cb))\n    action def notice (self : Self, i : __builtin__.int) -> __builtin__.int:\n        return $ASYNC@[__builtin__.int](self, L_9proc(self, i))\nclass Bepa ($Actor, __builtin__.value):\n    proc def __init__ (self : Self, C_cont : $Cont[None]) -> $R:\n        print@[(__builtin__.str,)]((\"\\\"Bepa\\\"\",), None, None, None, None)\n        return $R_CONT@[None](C_cont, None)\n    proc def callbackG_local (self : Self, C_cont : $Cont[__builtin__.int], i : __builtin__.int) -> $R:\n        print@[(__builtin__.str, __builtin__.int)]((\"\\\"callback\\\"\", i), None, None, None, None)\n        N_2tmp: __builtin__.int = W_Apa_140.__add__(i, W_Apa_39.__fromatom__(1))\n        return $R_CONT@[__builtin__.int](C_cont, N_2tmp)\n    action def callback (self : Self, i : __builtin__.int) -> __builtin__.int:\n        return $ASYNC@[__builtin__.int](self, L_10proc(self, i))\nclass main ($Actor, __builtin__.value):\n    @property\n    env : __builtin__.Env\n    @property\n    a : Apa\n    @property\n    b : Bepa\n    @property\n    x : __builtin__.Msg[__builtin__.int]\n    @property\n    r : __builtin__.int\n    proc def __init__ (self : Self, C_cont : $Cont[None], env : __builtin__.Env) -> $R:\n        self.env = env\n        return ApaG_newact(L_22Cont(self, C_cont))\n    proc def myprocG_local (self : Self, C_cont : $Cont[__builtin__.int], i : __builtin__.int) -> $R:\n        print@[(__builtin__.str, __builtin__.int)]((\"\\\"myproc\\\"\", i), None, None, None, None)\n        if W_Apa_308.__eq__(i, W_Apa_39.__fromatom__(2)):\n            (async self.env.exit)(W_Apa_39.__fromatom__(0))\n        return $R_CONT@[__builtin__.int](C_cont, i)\n    action def myproc (self : Self, i : __builtin__.int) -> __builtin__.int:\n        return $ASYNC@[__builtin__.int](self, L_23proc(self, i))\nproc def ApaG_newact (C_cont : $Cont[Apa]) -> $R:\n    G_act: Apa = $NEWACTOR@[Apa]()\n    $InstallFinalizer@[Apa](G_act)\n    return $AWAIT@[None](L_25Cont(C_cont, G_act), $ASYNC@[None](G_act, L_26proc(G_act)))\nproc def BepaG_newact (C_cont : $Cont[Bepa]) -> $R:\n    G_act: Bepa = $NEWACTOR@[Bepa]()\n    $InstallFinalizer@[Bepa](G_act)\n    return $AWAIT@[None](L_28Cont(C_cont, G_act), $ASYNC@[None](G_act, L_29proc(G_act)))\nproc def mainG_newact (C_cont : $Cont[main], env : __builtin__.Env) -> $R:\n    G_act: main = $NEWACTOR@[main]()\n    $InstallFinalizer@[main](G_act)\n    return $AWAIT@[None](L_31Cont(C_cont, G_act), $ASYNC@[None](G_act, L_32proc(G_act, env)))\n# (recursive group)"
  },
  {
    "path": "compiler/lib/test/8-boxing/deact.input",
    "content": "W_Apa_39: __builtin__.Number[__builtin__.int] = __builtin__.IntegralD_int()\n\nW_Apa_140: __builtin__.Plus[__builtin__.int] = __builtin__.IntegralD_int()\n\nW_Apa_105: __builtin__.Times[__builtin__.int, __builtin__.int] = __builtin__.IntegralD_int()\n\nW_Apa_308: __builtin__.Eq[__builtin__.int] = __builtin__.OrdD_int()\n\n# recursive group:\nproc def L_1C_1cont (C_cont : $Cont[None], C_2res : None) -> $R:\n    print@[(__builtin__.str,)]((\"\\\"Apa\\\"\",), None, None, None, None)\n    return $R_CONT@[None](C_cont, None)\nclass L_2Cont ($Cont[None], __builtin__.value):\n    @property\n    C_cont : $Cont[None]\n    pure def __init__ (L_self : Self, C_cont : $Cont[None]) -> None:\n        L_self.C_cont = C_cont\n        return None\n    proc def __call__ (L_self : Self, G_1 : None) -> $R:\n        C_cont: $Cont[None] = L_self.C_cont\n        return L_1C_1cont(C_cont, G_1)\nclass L_4action ($action[(__builtin__.int,), __builtin__.int], $proc[(__builtin__.int,), __builtin__.int], __builtin__.value):\n    @property\n    L_3obj : Apa\n    pure def __init__ (L_self : Self, L_3obj : Apa) -> None:\n        L_self.L_3obj = L_3obj\n        return None\n    # recursive group:\n    proc def __call__ (L_self : Self, L_cont : $Cont[__builtin__.int], G_1 : __builtin__.int) -> $R:\n        return $AWAIT@[__builtin__.int](L_cont, L_self.__asyn__(G_1))\n    proc def __exec__ (L_self : Self, L_cont : $Cont[__builtin__.value], G_1 : __builtin__.int) -> $R:\n        return $R_CONT@[__builtin__.value](L_cont, L_self.__asyn__(G_1))\n    action def __asyn__ (L_self : Self, G_1 : __builtin__.int) -> __builtin__.int:\n        L_3obj: Apa = L_self.L_3obj\n        return L_3obj.notice(G_1)\n    # (recursive group)\nproc def L_5C_3cont (cb : $action[(__builtin__.int,), __builtin__.int], C_cont : $Cont[__builtin__.int], C_4res : __builtin__.int) -> $R:\n    v: __builtin__.int = C_4res\n    m: __builtin__.Msg[__builtin__.int] = cb.__asyn__(W_Apa_39.__fromatom__(2))\n    N_tmp: __builtin__.int = W_Apa_105.__mul__(v, W_Apa_39.__fromatom__(10))\n    return $R_CONT@[__builtin__.int](C_cont, N_tmp)\nclass L_6Cont ($Cont[__builtin__.int], __builtin__.value):\n    @property\n    cb : $action[(__builtin__.int,), __builtin__.int]\n    @property\n    C_cont : $Cont[__builtin__.int]\n    pure def __init__ (L_self : Self, cb : $action[(__builtin__.int,), __builtin__.int], C_cont : $Cont[__builtin__.int]) -> None:\n        L_self.cb = cb\n        L_self.C_cont = C_cont\n        return None\n    proc def __call__ (L_self : Self, G_1 : __builtin__.int) -> $R:\n        cb: $action[(__builtin__.int,), __builtin__.int] = L_self.cb\n        C_cont: $Cont[__builtin__.int] = L_self.C_cont\n        return L_5C_3cont(cb, C_cont, G_1)\nclass L_7proc ($proc[(), None], __builtin__.value):\n    @property\n    self : Apa\n    @property\n    cb : $action[(__builtin__.int,), __builtin__.int]\n    pure def __init__ (L_self : Self, self : Apa, cb : $action[(__builtin__.int,), __builtin__.int]) -> None:\n        L_self.self = self\n        L_self.cb = cb\n        return None\n    # recursive group:\n    proc def __call__ (L_self : Self, C_cont : $Cont[None]) -> $R:\n        self: Apa = L_self.self\n        cb: $action[(__builtin__.int,), __builtin__.int] = L_self.cb\n        return self.setupG_local(C_cont, cb)\n    proc def __exec__ (L_self : Self, C_cont : $Cont[None]) -> $R:\n        return L_self.__call__(C_cont)\n    # (recursive group)\nclass L_8proc ($proc[(), __builtin__.int], __builtin__.value):\n    @property\n    self : Apa\n    @property\n    cb : $action[(__builtin__.int,), __builtin__.int]\n    pure def __init__ (L_self : Self, self : Apa, cb : $action[(__builtin__.int,), __builtin__.int]) -> None:\n        L_self.self = self\n        L_self.cb = cb\n        return None\n    # recursive group:\n    proc def __call__ (L_self : Self, C_cont : $Cont[__builtin__.int]) -> $R:\n        self: Apa = L_self.self\n        cb: $action[(__builtin__.int,), __builtin__.int] = L_self.cb\n        return self.computeG_local(C_cont, cb)\n    proc def __exec__ (L_self : Self, C_cont : $Cont[__builtin__.int]) -> $R:\n        return L_self.__call__(C_cont)\n    # (recursive group)\nclass L_9proc ($proc[(), __builtin__.int], __builtin__.value):\n    @property\n    self : Apa\n    @property\n    i : __builtin__.int\n    pure def __init__ (L_self : Self, self : Apa, i : __builtin__.int) -> None:\n        L_self.self = self\n        L_self.i = i\n        return None\n    # recursive group:\n    proc def __call__ (L_self : Self, C_cont : $Cont[__builtin__.int]) -> $R:\n        self: Apa = L_self.self\n        i: __builtin__.int = L_self.i\n        return self.noticeG_local(C_cont, i)\n    proc def __exec__ (L_self : Self, C_cont : $Cont[__builtin__.int]) -> $R:\n        return L_self.__call__(C_cont)\n    # (recursive group)\nclass L_10proc ($proc[(), __builtin__.int], __builtin__.value):\n    @property\n    self : Bepa\n    @property\n    i : __builtin__.int\n    pure def __init__ (L_self : Self, self : Bepa, i : __builtin__.int) -> None:\n        L_self.self = self\n        L_self.i = i\n        return None\n    # recursive group:\n    proc def __call__ (L_self : Self, C_cont : $Cont[__builtin__.int]) -> $R:\n        self: Bepa = L_self.self\n        i: __builtin__.int = L_self.i\n        return self.callbackG_local(C_cont, i)\n    proc def __exec__ (L_self : Self, C_cont : $Cont[__builtin__.int]) -> $R:\n        return L_self.__call__(C_cont)\n    # (recursive group)\nclass L_14action ($action[(__builtin__.int,), __builtin__.int], $proc[(__builtin__.int,), __builtin__.int], __builtin__.value):\n    @property\n    L_13obj : Apa\n    pure def __init__ (L_self : Self, L_13obj : Apa) -> None:\n        L_self.L_13obj = L_13obj\n        return None\n    # recursive group:\n    proc def __call__ (L_self : Self, L_cont : $Cont[__builtin__.int], G_1 : __builtin__.int) -> $R:\n        return $AWAIT@[__builtin__.int](L_cont, L_self.__asyn__(G_1))\n    proc def __exec__ (L_self : Self, L_cont : $Cont[__builtin__.value], G_1 : __builtin__.int) -> $R:\n        return $R_CONT@[__builtin__.value](L_cont, L_self.__asyn__(G_1))\n    action def __asyn__ (L_self : Self, G_1 : __builtin__.int) -> __builtin__.int:\n        L_13obj: Apa = L_self.L_13obj\n        return L_13obj.notice(G_1)\n    # (recursive group)\nclass L_16action ($action[(__builtin__.int,), __builtin__.int], $proc[(__builtin__.int,), __builtin__.int], __builtin__.value):\n    @property\n    L_15obj : Bepa\n    pure def __init__ (L_self : Self, L_15obj : Bepa) -> None:\n        L_self.L_15obj = L_15obj\n        return None\n    # recursive group:\n    proc def __call__ (L_self : Self, L_cont : $Cont[__builtin__.int], G_1 : __builtin__.int) -> $R:\n        return $AWAIT@[__builtin__.int](L_cont, L_self.__asyn__(G_1))\n    proc def __exec__ (L_self : Self, L_cont : $Cont[__builtin__.value], G_1 : __builtin__.int) -> $R:\n        return $R_CONT@[__builtin__.value](L_cont, L_self.__asyn__(G_1))\n    action def __asyn__ (L_self : Self, G_1 : __builtin__.int) -> __builtin__.int:\n        L_15obj: Bepa = L_self.L_15obj\n        return L_15obj.callback(G_1)\n    # (recursive group)\nclass L_19action ($action[(__builtin__.int,), __builtin__.int], $proc[(__builtin__.int,), __builtin__.int], __builtin__.value):\n    @property\n    L_18obj : main\n    pure def __init__ (L_self : Self, L_18obj : main) -> None:\n        L_self.L_18obj = L_18obj\n        return None\n    # recursive group:\n    proc def __call__ (L_self : Self, L_cont : $Cont[__builtin__.int], G_1 : __builtin__.int) -> $R:\n        return $AWAIT@[__builtin__.int](L_cont, L_self.__asyn__(G_1))\n    proc def __exec__ (L_self : Self, L_cont : $Cont[__builtin__.value], G_1 : __builtin__.int) -> $R:\n        return $R_CONT@[__builtin__.value](L_cont, L_self.__asyn__(G_1))\n    action def __asyn__ (L_self : Self, G_1 : __builtin__.int) -> __builtin__.int:\n        L_18obj: main = L_self.L_18obj\n        return L_18obj.myproc(G_1)\n    # (recursive group)\nproc def L_17C_9cont (self : main, C_cont : $Cont[None], C_10res : __builtin__.int) -> $R:\n    self.r = C_10res\n    print@[(__builtin__.str, __builtin__.int)]((\"\\\"r =\\\"\", self.r), None, None, None, None)\n    (async self.a.compute)(L_19action(self))\n    print@[(__builtin__.str,)]((\"\\\"main\\\"\",), None, None, None, None)\n    return $R_CONT@[None](C_cont, None)\nclass L_20Cont ($Cont[__builtin__.int], __builtin__.value):\n    @property\n    self : main\n    @property\n    C_cont : $Cont[None]\n    pure def __init__ (L_self : Self, self : main, C_cont : $Cont[None]) -> None:\n        L_self.self = self\n        L_self.C_cont = C_cont\n        return None\n    proc def __call__ (L_self : Self, G_1 : __builtin__.int) -> $R:\n        self: main = L_self.self\n        C_cont: $Cont[None] = L_self.C_cont\n        return L_17C_9cont(self, C_cont, G_1)\nproc def L_12C_7cont (self : main, C_cont : $Cont[None], C_8res : Bepa) -> $R:\n    self.b = C_8res\n    print@[(__builtin__.str,)]((\"\\\"-----\\\"\",), None, None, None, None)\n    (async self.a.setup)(L_14action(self.a))\n    self.x = (async self.a.compute)(L_16action(self.b))\n    return $AWAIT@[__builtin__.int](L_20Cont(self, C_cont), self.x)\nclass L_21Cont ($Cont[Bepa], __builtin__.value):\n    @property\n    self : main\n    @property\n    C_cont : $Cont[None]\n    pure def __init__ (L_self : Self, self : main, C_cont : $Cont[None]) -> None:\n        L_self.self = self\n        L_self.C_cont = C_cont\n        return None\n    proc def __call__ (L_self : Self, G_1 : Bepa) -> $R:\n        self: main = L_self.self\n        C_cont: $Cont[None] = L_self.C_cont\n        return L_12C_7cont(self, C_cont, G_1)\nproc def L_11C_5cont (self : main, C_cont : $Cont[None], C_6res : Apa) -> $R:\n    self.a = C_6res\n    return BepaG_newact(L_21Cont(self, C_cont))\nclass L_22Cont ($Cont[Apa], __builtin__.value):\n    @property\n    self : main\n    @property\n    C_cont : $Cont[None]\n    pure def __init__ (L_self : Self, self : main, C_cont : $Cont[None]) -> None:\n        L_self.self = self\n        L_self.C_cont = C_cont\n        return None\n    proc def __call__ (L_self : Self, G_1 : Apa) -> $R:\n        self: main = L_self.self\n        C_cont: $Cont[None] = L_self.C_cont\n        return L_11C_5cont(self, C_cont, G_1)\nclass L_23proc ($proc[(), __builtin__.int], __builtin__.value):\n    @property\n    self : main\n    @property\n    i : __builtin__.int\n    pure def __init__ (L_self : Self, self : main, i : __builtin__.int) -> None:\n        L_self.self = self\n        L_self.i = i\n        return None\n    # recursive group:\n    proc def __call__ (L_self : Self, C_cont : $Cont[__builtin__.int]) -> $R:\n        self: main = L_self.self\n        i: __builtin__.int = L_self.i\n        return self.myprocG_local(C_cont, i)\n    proc def __exec__ (L_self : Self, C_cont : $Cont[__builtin__.int]) -> $R:\n        return L_self.__call__(C_cont)\n    # (recursive group)\nproc def L_24C_11cont (C_cont : $Cont[Apa], G_act : Apa, C_12res : None) -> $R:\n    return $R_CONT@[Apa](C_cont, G_act)\nclass L_25Cont ($Cont[None], __builtin__.value):\n    @property\n    C_cont : $Cont[Apa]\n    @property\n    G_act : Apa\n    pure def __init__ (L_self : Self, C_cont : $Cont[Apa], G_act : Apa) -> None:\n        L_self.C_cont = C_cont\n        L_self.G_act = G_act\n        return None\n    proc def __call__ (L_self : Self, G_1 : None) -> $R:\n        C_cont: $Cont[Apa] = L_self.C_cont\n        G_act: Apa = L_self.G_act\n        return L_24C_11cont(C_cont, G_act, G_1)\nclass L_26proc ($proc[(), None], __builtin__.value):\n    @property\n    G_act : Apa\n    pure def __init__ (L_self : Self, G_act : Apa) -> None:\n        L_self.G_act = G_act\n        return None\n    # recursive group:\n    proc def __call__ (L_self : Self, C_cont : $Cont[None]) -> $R:\n        G_act: Apa = L_self.G_act\n        return G_act.__init__(C_cont)\n    proc def __exec__ (L_self : Self, C_cont : $Cont[None]) -> $R:\n        return L_self.__call__(C_cont)\n    # (recursive group)\nproc def L_27C_13cont (C_cont : $Cont[Bepa], G_act : Bepa, C_14res : None) -> $R:\n    return $R_CONT@[Bepa](C_cont, G_act)\nclass L_28Cont ($Cont[None], __builtin__.value):\n    @property\n    C_cont : $Cont[Bepa]\n    @property\n    G_act : Bepa\n    pure def __init__ (L_self : Self, C_cont : $Cont[Bepa], G_act : Bepa) -> None:\n        L_self.C_cont = C_cont\n        L_self.G_act = G_act\n        return None\n    proc def __call__ (L_self : Self, G_1 : None) -> $R:\n        C_cont: $Cont[Bepa] = L_self.C_cont\n        G_act: Bepa = L_self.G_act\n        return L_27C_13cont(C_cont, G_act, G_1)\nclass L_29proc ($proc[(), None], __builtin__.value):\n    @property\n    G_act : Bepa\n    pure def __init__ (L_self : Self, G_act : Bepa) -> None:\n        L_self.G_act = G_act\n        return None\n    # recursive group:\n    proc def __call__ (L_self : Self, C_cont : $Cont[None]) -> $R:\n        G_act: Bepa = L_self.G_act\n        return G_act.__init__(C_cont)\n    proc def __exec__ (L_self : Self, C_cont : $Cont[None]) -> $R:\n        return L_self.__call__(C_cont)\n    # (recursive group)\nproc def L_30C_15cont (C_cont : $Cont[main], G_act : main, C_16res : None) -> $R:\n    return $R_CONT@[main](C_cont, G_act)\nclass L_31Cont ($Cont[None], __builtin__.value):\n    @property\n    C_cont : $Cont[main]\n    @property\n    G_act : main\n    pure def __init__ (L_self : Self, C_cont : $Cont[main], G_act : main) -> None:\n        L_self.C_cont = C_cont\n        L_self.G_act = G_act\n        return None\n    proc def __call__ (L_self : Self, G_1 : None) -> $R:\n        C_cont: $Cont[main] = L_self.C_cont\n        G_act: main = L_self.G_act\n        return L_30C_15cont(C_cont, G_act, G_1)\nclass L_32proc ($proc[(), None], __builtin__.value):\n    @property\n    G_act : main\n    @property\n    env : __builtin__.Env\n    pure def __init__ (L_self : Self, G_act : main, env : __builtin__.Env) -> None:\n        L_self.G_act = G_act\n        L_self.env = env\n        return None\n    # recursive group:\n    proc def __call__ (L_self : Self, C_cont : $Cont[None]) -> $R:\n        G_act: main = L_self.G_act\n        env: __builtin__.Env = L_self.env\n        return G_act.__init__(C_cont, env)\n    proc def __exec__ (L_self : Self, C_cont : $Cont[None]) -> $R:\n        return L_self.__call__(C_cont)\n    # (recursive group)\nclass Apa ($Actor, __builtin__.value):\n    proc def __init__ (self : Self, C_cont : $Cont[None]) -> $R:\n        return self.setupG_local(L_2Cont(C_cont), L_4action(self))\n    proc def setupG_local (self : Self, C_cont : $Cont[None], cb : $action[(__builtin__.int,), __builtin__.int]) -> $R:\n        print@[(__builtin__.str,)]((\"\\\"setup\\\"\",), None, None, None, None)\n        cb.__asyn__(W_Apa_39.__fromatom__(0))\n        return $R_CONT@[None](C_cont, None)\n    proc def computeG_local (self : Self, C_cont : $Cont[__builtin__.int], cb : $action[(__builtin__.int,), __builtin__.int]) -> $R:\n        print@[(__builtin__.str,)]((\"\\\"compute\\\"\",), None, None, None, None)\n        return $AWAIT@[__builtin__.int](L_6Cont(cb, C_cont), cb.__asyn__(W_Apa_39.__fromatom__(1)))\n    proc def noticeG_local (self : Self, C_cont : $Cont[__builtin__.int], i : __builtin__.int) -> $R:\n        print@[(__builtin__.str,)]((\"\\\"notice\\\"\",), None, None, None, None)\n        N_1tmp: __builtin__.int = W_Apa_140.__add__(i, W_Apa_39.__fromatom__(1))\n        return $R_CONT@[__builtin__.int](C_cont, N_1tmp)\n    action def setup (self : Self, cb : $action[(__builtin__.int,), __builtin__.int]) -> None:\n        return $ASYNC@[None](self, L_7proc(self, cb))\n    action def compute (self : Self, cb : $action[(__builtin__.int,), __builtin__.int]) -> __builtin__.int:\n        return $ASYNC@[__builtin__.int](self, L_8proc(self, cb))\n    action def notice (self : Self, i : __builtin__.int) -> __builtin__.int:\n        return $ASYNC@[__builtin__.int](self, L_9proc(self, i))\nclass Bepa ($Actor, __builtin__.value):\n    proc def __init__ (self : Self, C_cont : $Cont[None]) -> $R:\n        print@[(__builtin__.str,)]((\"\\\"Bepa\\\"\",), None, None, None, None)\n        return $R_CONT@[None](C_cont, None)\n    proc def callbackG_local (self : Self, C_cont : $Cont[__builtin__.int], i : __builtin__.int) -> $R:\n        print@[(__builtin__.str, __builtin__.int)]((\"\\\"callback\\\"\", i), None, None, None, None)\n        N_2tmp: __builtin__.int = W_Apa_140.__add__(i, W_Apa_39.__fromatom__(1))\n        return $R_CONT@[__builtin__.int](C_cont, N_2tmp)\n    action def callback (self : Self, i : __builtin__.int) -> __builtin__.int:\n        return $ASYNC@[__builtin__.int](self, L_10proc(self, i))\nclass main ($Actor, __builtin__.value):\n    @property\n    env : __builtin__.Env\n    @property\n    a : Apa\n    @property\n    b : Bepa\n    @property\n    x : __builtin__.Msg[__builtin__.int]\n    @property\n    r : __builtin__.int\n    proc def __init__ (self : Self, C_cont : $Cont[None], env : __builtin__.Env) -> $R:\n        self.env = env\n        return ApaG_newact(L_22Cont(self, C_cont))\n    proc def myprocG_local (self : Self, C_cont : $Cont[__builtin__.int], i : __builtin__.int) -> $R:\n        print@[(__builtin__.str, __builtin__.int)]((\"\\\"myproc\\\"\", i), None, None, None, None)\n        if W_Apa_308.__eq__(i, W_Apa_39.__fromatom__(2)):\n            (async self.env.exit)(W_Apa_39.__fromatom__(0))\n        return $R_CONT@[__builtin__.int](C_cont, i)\n    action def myproc (self : Self, i : __builtin__.int) -> __builtin__.int:\n        return $ASYNC@[__builtin__.int](self, L_23proc(self, i))\nproc def ApaG_newact (C_cont : $Cont[Apa]) -> $R:\n    G_act: Apa = $NEWACTOR@[Apa]()\n    $InstallFinalizer@[Apa](G_act)\n    return $AWAIT@[None](L_25Cont(C_cont, G_act), $ASYNC@[None](G_act, L_26proc(G_act)))\nproc def BepaG_newact (C_cont : $Cont[Bepa]) -> $R:\n    G_act: Bepa = $NEWACTOR@[Bepa]()\n    $InstallFinalizer@[Bepa](G_act)\n    return $AWAIT@[None](L_28Cont(C_cont, G_act), $ASYNC@[None](G_act, L_29proc(G_act)))\nproc def mainG_newact (C_cont : $Cont[main], env : __builtin__.Env) -> $R:\n    G_act: main = $NEWACTOR@[main]()\n    $InstallFinalizer@[main](G_act)\n    return $AWAIT@[None](L_31Cont(C_cont, G_act), $ASYNC@[None](G_act, L_32proc(G_act, env)))\n# (recursive group)"
  },
  {
    "path": "compiler/lib/test/8-boxing/deact.output",
    "content": "# recursive group:\nproc def L_1C_1cont (C_cont : $Cont[None], C_2res : None) -> $R:\n    print@[(__builtin__.str,)]((\"\\\"Apa\\\"\",), None, None, None, None)\n    return $R_CONT@[None](C_cont, None)\nclass L_2Cont ($Cont[None], __builtin__.value):\n    @property\n    C_cont : $Cont[None]\n    pure def __init__ (L_self : L_2Cont, C_cont : $Cont[None]) -> None:\n        L_self.C_cont = C_cont\n        return None\n    proc def __call__ (L_self : L_2Cont, G_1 : None) -> $R:\n        C_cont: $Cont[None] = L_self.C_cont\n        return L_1C_1cont(C_cont, G_1)\nclass L_4action ($action[(__builtin__.int,), __builtin__.int], $proc[(__builtin__.int,), __builtin__.int], __builtin__.value):\n    @property\n    L_3obj : Apa\n    pure def __init__ (L_self : L_4action, L_3obj : Apa) -> None:\n        L_self.L_3obj = L_3obj\n        return None\n    # recursive group:\n    proc def __call__ (L_self : L_4action, L_cont : $Cont[__builtin__.int], G_1 : __builtin__.int) -> $R:\n        return $AWAIT@[__builtin__.int](L_cont, L_self.__asyn__(G_1))\n    proc def __exec__ (L_self : L_4action, L_cont : $Cont[__builtin__.value], G_1 : __builtin__.int) -> $R:\n        return $R_CONT@[__builtin__.value](L_cont, L_self.__asyn__(G_1))\n    action def __asyn__ (L_self : L_4action, G_1 : __builtin__.int) -> __builtin__.int:\n        L_3obj: Apa = L_self.L_3obj\n        return L_3obj.notice(G_1)\n    # (recursive group)\nproc def U_L_5C_3cont (cb : $action[(__builtin__.int,), __builtin__.int], C_cont : $Cont[__builtin__.int], U_2C_4res : __builtin__.int) -> $R:\n    U_3v: __builtin__.int = U_2C_4res\n    m: __builtin__.Msg[__builtin__.int] = cb.__asyn__((BOX __builtin__.int (UNBOX __builtin__.int 2)))\n    U_4N_tmp: __builtin__.int = (U_3v * (UNBOX __builtin__.int 10))\n    return $R_CONT@[__builtin__.int](C_cont, (BOX __builtin__.int U_4N_tmp))\nproc def L_5C_3cont (cb : $action[(__builtin__.int,), __builtin__.int], C_cont : $Cont[__builtin__.int], C_4res : __builtin__.int) -> $R:\n    return U_L_5C_3cont(cb, C_cont, (UNBOX __builtin__.int C_4res))\nclass L_6Cont ($Cont[__builtin__.int], __builtin__.value):\n    @property\n    cb : $action[(__builtin__.int,), __builtin__.int]\n    @property\n    C_cont : $Cont[__builtin__.int]\n    pure def __init__ (L_self : L_6Cont, cb : $action[(__builtin__.int,), __builtin__.int], C_cont : $Cont[__builtin__.int]) -> None:\n        L_self.cb = cb\n        L_self.C_cont = C_cont\n        return None\n    proc def __call__ (L_self : L_6Cont, G_1 : __builtin__.int) -> $R:\n        cb: $action[(__builtin__.int,), __builtin__.int] = L_self.cb\n        C_cont: $Cont[__builtin__.int] = L_self.C_cont\n        return L_5C_3cont(cb, C_cont, G_1)\nclass L_7proc ($proc[(), None], __builtin__.value):\n    @property\n    self : Apa\n    @property\n    cb : $action[(__builtin__.int,), __builtin__.int]\n    pure def __init__ (L_self : L_7proc, self : Apa, cb : $action[(__builtin__.int,), __builtin__.int]) -> None:\n        L_self.self = self\n        L_self.cb = cb\n        return None\n    # recursive group:\n    proc def __call__ (L_self : L_7proc, C_cont : $Cont[None]) -> $R:\n        self: Apa = L_self.self\n        cb: $action[(__builtin__.int,), __builtin__.int] = L_self.cb\n        return self.setupG_local(C_cont, cb)\n    proc def __exec__ (L_self : L_7proc, C_cont : $Cont[None]) -> $R:\n        return L_self.__call__(C_cont)\n    # (recursive group)\nclass L_8proc ($proc[(), __builtin__.int], __builtin__.value):\n    @property\n    self : Apa\n    @property\n    cb : $action[(__builtin__.int,), __builtin__.int]\n    pure def __init__ (L_self : L_8proc, self : Apa, cb : $action[(__builtin__.int,), __builtin__.int]) -> None:\n        L_self.self = self\n        L_self.cb = cb\n        return None\n    # recursive group:\n    proc def __call__ (L_self : L_8proc, C_cont : $Cont[__builtin__.int]) -> $R:\n        self: Apa = L_self.self\n        cb: $action[(__builtin__.int,), __builtin__.int] = L_self.cb\n        return self.computeG_local(C_cont, cb)\n    proc def __exec__ (L_self : L_8proc, C_cont : $Cont[__builtin__.int]) -> $R:\n        return L_self.__call__(C_cont)\n    # (recursive group)\nclass L_9proc ($proc[(), __builtin__.int], __builtin__.value):\n    @property\n    self : Apa\n    @property\n    i : __builtin__.int\n    pure def __init__ (L_self : L_9proc, self : Apa, i : __builtin__.int) -> None:\n        L_self.self = self\n        L_self.i = i\n        return None\n    # recursive group:\n    proc def __call__ (L_self : L_9proc, C_cont : $Cont[__builtin__.int]) -> $R:\n        self: Apa = L_self.self\n        U_5i: __builtin__.int = (UNBOX __builtin__.int L_self.i)\n        return self.noticeG_local(C_cont, (BOX __builtin__.int U_5i))\n    proc def __exec__ (L_self : L_9proc, C_cont : $Cont[__builtin__.int]) -> $R:\n        return L_self.__call__(C_cont)\n    # (recursive group)\nclass L_10proc ($proc[(), __builtin__.int], __builtin__.value):\n    @property\n    self : Bepa\n    @property\n    i : __builtin__.int\n    pure def __init__ (L_self : L_10proc, self : Bepa, i : __builtin__.int) -> None:\n        L_self.self = self\n        L_self.i = i\n        return None\n    # recursive group:\n    proc def __call__ (L_self : L_10proc, C_cont : $Cont[__builtin__.int]) -> $R:\n        self: Bepa = L_self.self\n        U_6i: __builtin__.int = (UNBOX __builtin__.int L_self.i)\n        return self.callbackG_local(C_cont, (BOX __builtin__.int U_6i))\n    proc def __exec__ (L_self : L_10proc, C_cont : $Cont[__builtin__.int]) -> $R:\n        return L_self.__call__(C_cont)\n    # (recursive group)\nclass L_14action ($action[(__builtin__.int,), __builtin__.int], $proc[(__builtin__.int,), __builtin__.int], __builtin__.value):\n    @property\n    L_13obj : Apa\n    pure def __init__ (L_self : L_14action, L_13obj : Apa) -> None:\n        L_self.L_13obj = L_13obj\n        return None\n    # recursive group:\n    proc def __call__ (L_self : L_14action, L_cont : $Cont[__builtin__.int], G_1 : __builtin__.int) -> $R:\n        return $AWAIT@[__builtin__.int](L_cont, L_self.__asyn__(G_1))\n    proc def __exec__ (L_self : L_14action, L_cont : $Cont[__builtin__.value], G_1 : __builtin__.int) -> $R:\n        return $R_CONT@[__builtin__.value](L_cont, L_self.__asyn__(G_1))\n    action def __asyn__ (L_self : L_14action, G_1 : __builtin__.int) -> __builtin__.int:\n        L_13obj: Apa = L_self.L_13obj\n        return L_13obj.notice(G_1)\n    # (recursive group)\nclass L_16action ($action[(__builtin__.int,), __builtin__.int], $proc[(__builtin__.int,), __builtin__.int], __builtin__.value):\n    @property\n    L_15obj : Bepa\n    pure def __init__ (L_self : L_16action, L_15obj : Bepa) -> None:\n        L_self.L_15obj = L_15obj\n        return None\n    # recursive group:\n    proc def __call__ (L_self : L_16action, L_cont : $Cont[__builtin__.int], G_1 : __builtin__.int) -> $R:\n        return $AWAIT@[__builtin__.int](L_cont, L_self.__asyn__(G_1))\n    proc def __exec__ (L_self : L_16action, L_cont : $Cont[__builtin__.value], G_1 : __builtin__.int) -> $R:\n        return $R_CONT@[__builtin__.value](L_cont, L_self.__asyn__(G_1))\n    action def __asyn__ (L_self : L_16action, G_1 : __builtin__.int) -> __builtin__.int:\n        L_15obj: Bepa = L_self.L_15obj\n        return L_15obj.callback(G_1)\n    # (recursive group)\nclass L_19action ($action[(__builtin__.int,), __builtin__.int], $proc[(__builtin__.int,), __builtin__.int], __builtin__.value):\n    @property\n    L_18obj : main\n    pure def __init__ (L_self : L_19action, L_18obj : main) -> None:\n        L_self.L_18obj = L_18obj\n        return None\n    # recursive group:\n    proc def __call__ (L_self : L_19action, L_cont : $Cont[__builtin__.int], G_1 : __builtin__.int) -> $R:\n        return $AWAIT@[__builtin__.int](L_cont, L_self.__asyn__(G_1))\n    proc def __exec__ (L_self : L_19action, L_cont : $Cont[__builtin__.value], G_1 : __builtin__.int) -> $R:\n        return $R_CONT@[__builtin__.value](L_cont, L_self.__asyn__(G_1))\n    action def __asyn__ (L_self : L_19action, G_1 : __builtin__.int) -> __builtin__.int:\n        L_18obj: main = L_self.L_18obj\n        return L_18obj.myproc(G_1)\n    # (recursive group)\nproc def U_1L_17C_9cont (self : main, C_cont : $Cont[None], U_7C_10res : __builtin__.int) -> $R:\n    self.r = (BOX __builtin__.int U_7C_10res)\n    print@[(__builtin__.str, __builtin__.int)]((\"\\\"r =\\\"\", self.r), None, None, None, None)\n    (async self.a.compute)(L_19action(self))\n    print@[(__builtin__.str,)]((\"\\\"main\\\"\",), None, None, None, None)\n    return $R_CONT@[None](C_cont, None)\nproc def L_17C_9cont (self : main, C_cont : $Cont[None], C_10res : __builtin__.int) -> $R:\n    return U_1L_17C_9cont(self, C_cont, (UNBOX __builtin__.int C_10res))\nclass L_20Cont ($Cont[__builtin__.int], __builtin__.value):\n    @property\n    self : main\n    @property\n    C_cont : $Cont[None]\n    pure def __init__ (L_self : L_20Cont, self : main, C_cont : $Cont[None]) -> None:\n        L_self.self = self\n        L_self.C_cont = C_cont\n        return None\n    proc def __call__ (L_self : L_20Cont, G_1 : __builtin__.int) -> $R:\n        self: main = L_self.self\n        C_cont: $Cont[None] = L_self.C_cont\n        return L_17C_9cont(self, C_cont, G_1)\nproc def L_12C_7cont (self : main, C_cont : $Cont[None], C_8res : Bepa) -> $R:\n    self.b = C_8res\n    print@[(__builtin__.str,)]((\"\\\"-----\\\"\",), None, None, None, None)\n    (async self.a.setup)(L_14action(self.a))\n    self.x = (async self.a.compute)(L_16action(self.b))\n    return $AWAIT@[__builtin__.int](L_20Cont(self, C_cont), self.x)\nclass L_21Cont ($Cont[Bepa], __builtin__.value):\n    @property\n    self : main\n    @property\n    C_cont : $Cont[None]\n    pure def __init__ (L_self : L_21Cont, self : main, C_cont : $Cont[None]) -> None:\n        L_self.self = self\n        L_self.C_cont = C_cont\n        return None\n    proc def __call__ (L_self : L_21Cont, G_1 : Bepa) -> $R:\n        self: main = L_self.self\n        C_cont: $Cont[None] = L_self.C_cont\n        return L_12C_7cont(self, C_cont, G_1)\nproc def L_11C_5cont (self : main, C_cont : $Cont[None], C_6res : Apa) -> $R:\n    self.a = C_6res\n    return BepaG_newact(L_21Cont(self, C_cont))\nclass L_22Cont ($Cont[Apa], __builtin__.value):\n    @property\n    self : main\n    @property\n    C_cont : $Cont[None]\n    pure def __init__ (L_self : L_22Cont, self : main, C_cont : $Cont[None]) -> None:\n        L_self.self = self\n        L_self.C_cont = C_cont\n        return None\n    proc def __call__ (L_self : L_22Cont, G_1 : Apa) -> $R:\n        self: main = L_self.self\n        C_cont: $Cont[None] = L_self.C_cont\n        return L_11C_5cont(self, C_cont, G_1)\nclass L_23proc ($proc[(), __builtin__.int], __builtin__.value):\n    @property\n    self : main\n    @property\n    i : __builtin__.int\n    pure def __init__ (L_self : L_23proc, self : main, i : __builtin__.int) -> None:\n        L_self.self = self\n        L_self.i = i\n        return None\n    # recursive group:\n    proc def __call__ (L_self : L_23proc, C_cont : $Cont[__builtin__.int]) -> $R:\n        self: main = L_self.self\n        U_8i: __builtin__.int = (UNBOX __builtin__.int L_self.i)\n        return self.myprocG_local(C_cont, (BOX __builtin__.int U_8i))\n    proc def __exec__ (L_self : L_23proc, C_cont : $Cont[__builtin__.int]) -> $R:\n        return L_self.__call__(C_cont)\n    # (recursive group)\nproc def L_24C_11cont (C_cont : $Cont[Apa], G_act : Apa, C_12res : None) -> $R:\n    return $R_CONT@[Apa](C_cont, G_act)\nclass L_25Cont ($Cont[None], __builtin__.value):\n    @property\n    C_cont : $Cont[Apa]\n    @property\n    G_act : Apa\n    pure def __init__ (L_self : L_25Cont, C_cont : $Cont[Apa], G_act : Apa) -> None:\n        L_self.C_cont = C_cont\n        L_self.G_act = G_act\n        return None\n    proc def __call__ (L_self : L_25Cont, G_1 : None) -> $R:\n        C_cont: $Cont[Apa] = L_self.C_cont\n        G_act: Apa = L_self.G_act\n        return L_24C_11cont(C_cont, G_act, G_1)\nclass L_26proc ($proc[(), None], __builtin__.value):\n    @property\n    G_act : Apa\n    pure def __init__ (L_self : L_26proc, G_act : Apa) -> None:\n        L_self.G_act = G_act\n        return None\n    # recursive group:\n    proc def __call__ (L_self : L_26proc, C_cont : $Cont[None]) -> $R:\n        G_act: Apa = L_self.G_act\n        return G_act.__init__(C_cont)\n    proc def __exec__ (L_self : L_26proc, C_cont : $Cont[None]) -> $R:\n        return L_self.__call__(C_cont)\n    # (recursive group)\nproc def L_27C_13cont (C_cont : $Cont[Bepa], G_act : Bepa, C_14res : None) -> $R:\n    return $R_CONT@[Bepa](C_cont, G_act)\nclass L_28Cont ($Cont[None], __builtin__.value):\n    @property\n    C_cont : $Cont[Bepa]\n    @property\n    G_act : Bepa\n    pure def __init__ (L_self : L_28Cont, C_cont : $Cont[Bepa], G_act : Bepa) -> None:\n        L_self.C_cont = C_cont\n        L_self.G_act = G_act\n        return None\n    proc def __call__ (L_self : L_28Cont, G_1 : None) -> $R:\n        C_cont: $Cont[Bepa] = L_self.C_cont\n        G_act: Bepa = L_self.G_act\n        return L_27C_13cont(C_cont, G_act, G_1)\nclass L_29proc ($proc[(), None], __builtin__.value):\n    @property\n    G_act : Bepa\n    pure def __init__ (L_self : L_29proc, G_act : Bepa) -> None:\n        L_self.G_act = G_act\n        return None\n    # recursive group:\n    proc def __call__ (L_self : L_29proc, C_cont : $Cont[None]) -> $R:\n        G_act: Bepa = L_self.G_act\n        return G_act.__init__(C_cont)\n    proc def __exec__ (L_self : L_29proc, C_cont : $Cont[None]) -> $R:\n        return L_self.__call__(C_cont)\n    # (recursive group)\nproc def L_30C_15cont (C_cont : $Cont[main], G_act : main, C_16res : None) -> $R:\n    return $R_CONT@[main](C_cont, G_act)\nclass L_31Cont ($Cont[None], __builtin__.value):\n    @property\n    C_cont : $Cont[main]\n    @property\n    G_act : main\n    pure def __init__ (L_self : L_31Cont, C_cont : $Cont[main], G_act : main) -> None:\n        L_self.C_cont = C_cont\n        L_self.G_act = G_act\n        return None\n    proc def __call__ (L_self : L_31Cont, G_1 : None) -> $R:\n        C_cont: $Cont[main] = L_self.C_cont\n        G_act: main = L_self.G_act\n        return L_30C_15cont(C_cont, G_act, G_1)\nclass L_32proc ($proc[(), None], __builtin__.value):\n    @property\n    G_act : main\n    @property\n    env : __builtin__.Env\n    pure def __init__ (L_self : L_32proc, G_act : main, env : __builtin__.Env) -> None:\n        L_self.G_act = G_act\n        L_self.env = env\n        return None\n    # recursive group:\n    proc def __call__ (L_self : L_32proc, C_cont : $Cont[None]) -> $R:\n        G_act: main = L_self.G_act\n        env: __builtin__.Env = L_self.env\n        return G_act.__init__(C_cont, env)\n    proc def __exec__ (L_self : L_32proc, C_cont : $Cont[None]) -> $R:\n        return L_self.__call__(C_cont)\n    # (recursive group)\nclass Apa ($Actor, __builtin__.value):\n    proc def __init__ (self : Apa, C_cont : $Cont[None]) -> $R:\n        return self.setupG_local(L_2Cont(C_cont), L_4action(self))\n    proc def setupG_local (self : Apa, C_cont : $Cont[None], cb : $action[(__builtin__.int,), __builtin__.int]) -> $R:\n        print@[(__builtin__.str,)]((\"\\\"setup\\\"\",), None, None, None, None)\n        cb.__asyn__((BOX __builtin__.int (UNBOX __builtin__.int 0)))\n        return $R_CONT@[None](C_cont, None)\n    proc def computeG_local (self : Apa, C_cont : $Cont[__builtin__.int], cb : $action[(__builtin__.int,), __builtin__.int]) -> $R:\n        print@[(__builtin__.str,)]((\"\\\"compute\\\"\",), None, None, None, None)\n        return $AWAIT@[__builtin__.int](L_6Cont(cb, C_cont), cb.__asyn__((BOX __builtin__.int (UNBOX __builtin__.int 1))))\n    proc def noticeG_local (self : Apa, C_cont : $Cont[__builtin__.int], i : __builtin__.int) -> $R:\n        print@[(__builtin__.str,)]((\"\\\"notice\\\"\",), None, None, None, None)\n        U_9N_1tmp: __builtin__.int = ((UNBOX __builtin__.int i) + (UNBOX __builtin__.int 1))\n        return $R_CONT@[__builtin__.int](C_cont, (BOX __builtin__.int U_9N_1tmp))\n    action def setup (self : Apa, cb : $action[(__builtin__.int,), __builtin__.int]) -> None:\n        return $ASYNC@[None](self, L_7proc(self, cb))\n    action def compute (self : Apa, cb : $action[(__builtin__.int,), __builtin__.int]) -> __builtin__.int:\n        return $ASYNC@[__builtin__.int](self, L_8proc(self, cb))\n    action def notice (self : Apa, i : __builtin__.int) -> __builtin__.int:\n        return $ASYNC@[__builtin__.int](self, L_9proc(self, i))\nclass Bepa ($Actor, __builtin__.value):\n    proc def __init__ (self : Bepa, C_cont : $Cont[None]) -> $R:\n        print@[(__builtin__.str,)]((\"\\\"Bepa\\\"\",), None, None, None, None)\n        return $R_CONT@[None](C_cont, None)\n    proc def callbackG_local (self : Bepa, C_cont : $Cont[__builtin__.int], i : __builtin__.int) -> $R:\n        print@[(__builtin__.str, __builtin__.int)]((\"\\\"callback\\\"\", i), None, None, None, None)\n        U_10N_2tmp: __builtin__.int = ((UNBOX __builtin__.int i) + (UNBOX __builtin__.int 1))\n        return $R_CONT@[__builtin__.int](C_cont, (BOX __builtin__.int U_10N_2tmp))\n    action def callback (self : Bepa, i : __builtin__.int) -> __builtin__.int:\n        return $ASYNC@[__builtin__.int](self, L_10proc(self, i))\nclass main ($Actor, __builtin__.value):\n    @property\n    env : __builtin__.Env\n    @property\n    a : Apa\n    @property\n    b : Bepa\n    @property\n    x : __builtin__.Msg[__builtin__.int]\n    @property\n    r : __builtin__.int\n    proc def __init__ (self : main, C_cont : $Cont[None], env : __builtin__.Env) -> $R:\n        self.env = env\n        return ApaG_newact(L_22Cont(self, C_cont))\n    proc def myprocG_local (self : main, C_cont : $Cont[__builtin__.int], i : __builtin__.int) -> $R:\n        print@[(__builtin__.str, __builtin__.int)]((\"\\\"myproc\\\"\", i), None, None, None, None)\n        if (BOX __builtin__.bool ((UNBOX __builtin__.int i) == (UNBOX __builtin__.int 2))):\n            (async self.env.exit)((BOX __builtin__.int (UNBOX __builtin__.int 0)))\n        return $R_CONT@[__builtin__.int](C_cont, i)\n    action def myproc (self : main, i : __builtin__.int) -> __builtin__.int:\n        return $ASYNC@[__builtin__.int](self, L_23proc(self, i))\nproc def ApaG_newact (C_cont : $Cont[Apa]) -> $R:\n    G_act: Apa = $NEWACTOR@[Apa]()\n    $InstallFinalizer@[Apa](G_act)\n    return $AWAIT@[None](L_25Cont(C_cont, G_act), $ASYNC@[None](G_act, L_26proc(G_act)))\nproc def BepaG_newact (C_cont : $Cont[Bepa]) -> $R:\n    G_act: Bepa = $NEWACTOR@[Bepa]()\n    $InstallFinalizer@[Bepa](G_act)\n    return $AWAIT@[None](L_28Cont(C_cont, G_act), $ASYNC@[None](G_act, L_29proc(G_act)))\nproc def mainG_newact (C_cont : $Cont[main], env : __builtin__.Env) -> $R:\n    G_act: main = $NEWACTOR@[main]()\n    $InstallFinalizer@[main](G_act)\n    return $AWAIT@[None](L_31Cont(C_cont, G_act), $ASYNC@[None](G_act, L_32proc(G_act, env)))\n# (recursive group)"
  },
  {
    "path": "compiler/lib/test/9-codegen/deact.c",
    "content": "/* Acton impl hash: test-hash */\n#include \"rts/common.h\"\n#include \"out/types/deact.h\"\n$R deactQ_L_1C_1cont ($Cont C_cont, B_NoneType C_2res) {\n    #line 15 \"test/src/deact.act\"\n    ((B_NoneType (*) (B_tuple, B_str, B_str, B_bool, B_bool))B_print)($NEWTUPLE(1, to$str(\"Apa\")), B_None, B_None, B_None, B_None);\n    return $R_CONT(C_cont, B_None);\n}\nB_NoneType deactQ_L_2ContD___init__ (deactQ_L_2Cont L_self, $Cont C_cont) {\n    L_self->C_cont = C_cont;\n    return B_None;\n}\n$R deactQ_L_2ContD___call__ (deactQ_L_2Cont L_self, B_NoneType G_1) {\n    $Cont C_cont = L_self->C_cont;\n    return deactQ_L_1C_1cont(C_cont, G_1);\n}\nvoid deactQ_L_2ContD___serialize__ (deactQ_L_2Cont self, $Serial$state state) {\n    $step_serialize(self->C_cont, state);\n}\ndeactQ_L_2Cont deactQ_L_2ContD___deserialize__ (deactQ_L_2Cont self, $Serial$state state) {\n    if (!self) {\n        if (!state) {\n            self = acton_malloc(sizeof(struct deactQ_L_2Cont));\n            self->$class = &deactQ_L_2ContG_methods;\n            return self;\n        }\n        self = $DNEW(deactQ_L_2Cont, state);\n    }\n    self->C_cont = $step_deserialize(state);\n    return self;\n}\ndeactQ_L_2Cont deactQ_L_2ContG_new($Cont G_1) {\n    deactQ_L_2Cont $tmp = acton_malloc(sizeof(struct deactQ_L_2Cont));\n    $tmp->$class = &deactQ_L_2ContG_methods;\n    deactQ_L_2ContG_methods.__init__($tmp, G_1);\n    return $tmp;\n}\nstruct deactQ_L_2ContG_class deactQ_L_2ContG_methods;\nB_NoneType deactQ_L_4actionD___init__ (deactQ_L_4action L_self, deactQ_Apa L_3obj) {\n    L_self->L_3obj = L_3obj;\n    return B_None;\n}\n$R deactQ_L_4actionD___call__ (deactQ_L_4action L_self, $Cont L_cont, B_int G_1) {\n    return $AWAIT(L_cont, ((B_Msg)((B_Msg (*) (deactQ_L_4action, B_int))L_self->$class->__asyn__)(L_self, G_1)));\n}\n$R deactQ_L_4actionD___exec__ (deactQ_L_4action L_self, $Cont L_cont, B_int G_1) {\n    return $R_CONT(L_cont, ((B_value)((B_Msg (*) (deactQ_L_4action, B_int))L_self->$class->__asyn__)(L_self, G_1)));\n}\nB_Msg deactQ_L_4actionD___asyn__ (deactQ_L_4action L_self, B_int G_1) {\n    deactQ_Apa L_3obj = L_self->L_3obj;\n    return ((B_Msg)((B_Msg (*) (deactQ_Apa, B_int))L_3obj->$class->notice)(L_3obj, G_1));\n}\nvoid deactQ_L_4actionD___serialize__ (deactQ_L_4action self, $Serial$state state) {\n    $step_serialize(self->L_3obj, state);\n}\ndeactQ_L_4action deactQ_L_4actionD___deserialize__ (deactQ_L_4action self, $Serial$state state) {\n    if (!self) {\n        if (!state) {\n            self = acton_malloc(sizeof(struct deactQ_L_4action));\n            self->$class = &deactQ_L_4actionG_methods;\n            return self;\n        }\n        self = $DNEW(deactQ_L_4action, state);\n    }\n    self->L_3obj = $step_deserialize(state);\n    return self;\n}\ndeactQ_L_4action deactQ_L_4actionG_new(deactQ_Apa G_1) {\n    deactQ_L_4action $tmp = acton_malloc(sizeof(struct deactQ_L_4action));\n    $tmp->$class = &deactQ_L_4actionG_methods;\n    deactQ_L_4actionG_methods.__init__($tmp, G_1);\n    return $tmp;\n}\nstruct deactQ_L_4actionG_class deactQ_L_4actionG_methods;\n$R deactQ_U_L_5C_3cont ($action cb, $Cont C_cont, int64_t U_2C_4res) {\n    #line 7 \"test/src/deact.act\"\n    int64_t U_3v = U_2C_4res;\n    #line 8 \"test/src/deact.act\"\n    B_Msg m = ((B_Msg)((B_Msg (*) ($action, B_int))cb->$class->__asyn__)(cb, toB_int(2LL)));\n    int64_t U_4N_tmp = (U_3v * 10LL);\n    return $R_CONT(C_cont, toB_int(U_4N_tmp));\n}\n$R deactQ_L_5C_3cont ($action cb, $Cont C_cont, B_int C_4res) {\n    return deactQ_U_L_5C_3cont(cb, C_cont, ((B_int)C_4res)->val);\n}\nB_NoneType deactQ_L_6ContD___init__ (deactQ_L_6Cont L_self, $action cb, $Cont C_cont) {\n    L_self->cb = cb;\n    L_self->C_cont = C_cont;\n    return B_None;\n}\n$R deactQ_L_6ContD___call__ (deactQ_L_6Cont L_self, B_int G_1) {\n    $action cb = L_self->cb;\n    $Cont C_cont = L_self->C_cont;\n    return deactQ_L_5C_3cont(cb, C_cont, G_1);\n}\nvoid deactQ_L_6ContD___serialize__ (deactQ_L_6Cont self, $Serial$state state) {\n    $step_serialize(self->cb, state);\n    $step_serialize(self->C_cont, state);\n}\ndeactQ_L_6Cont deactQ_L_6ContD___deserialize__ (deactQ_L_6Cont self, $Serial$state state) {\n    if (!self) {\n        if (!state) {\n            self = acton_malloc(sizeof(struct deactQ_L_6Cont));\n            self->$class = &deactQ_L_6ContG_methods;\n            return self;\n        }\n        self = $DNEW(deactQ_L_6Cont, state);\n    }\n    self->cb = $step_deserialize(state);\n    self->C_cont = $step_deserialize(state);\n    return self;\n}\ndeactQ_L_6Cont deactQ_L_6ContG_new($action G_1, $Cont G_2) {\n    deactQ_L_6Cont $tmp = acton_malloc(sizeof(struct deactQ_L_6Cont));\n    $tmp->$class = &deactQ_L_6ContG_methods;\n    deactQ_L_6ContG_methods.__init__($tmp, G_1, G_2);\n    return $tmp;\n}\nstruct deactQ_L_6ContG_class deactQ_L_6ContG_methods;\nB_NoneType deactQ_L_7procD___init__ (deactQ_L_7proc L_self, deactQ_Apa self, $action cb) {\n    L_self->self = self;\n    L_self->cb = cb;\n    return B_None;\n}\n$R deactQ_L_7procD___call__ (deactQ_L_7proc L_self, $Cont C_cont) {\n    deactQ_Apa self = L_self->self;\n    $action cb = L_self->cb;\n    return (($R (*) (deactQ_Apa, $Cont, $action))self->$class->setupG_local)(self, C_cont, cb);\n}\n$R deactQ_L_7procD___exec__ (deactQ_L_7proc L_self, $Cont C_cont) {\n    return (($R (*) (deactQ_L_7proc, $Cont))L_self->$class->__call__)(L_self, C_cont);\n}\nvoid deactQ_L_7procD___serialize__ (deactQ_L_7proc self, $Serial$state state) {\n    $step_serialize(self->self, state);\n    $step_serialize(self->cb, state);\n}\ndeactQ_L_7proc deactQ_L_7procD___deserialize__ (deactQ_L_7proc self, $Serial$state state) {\n    if (!self) {\n        if (!state) {\n            self = acton_malloc(sizeof(struct deactQ_L_7proc));\n            self->$class = &deactQ_L_7procG_methods;\n            return self;\n        }\n        self = $DNEW(deactQ_L_7proc, state);\n    }\n    self->self = $step_deserialize(state);\n    self->cb = $step_deserialize(state);\n    return self;\n}\ndeactQ_L_7proc deactQ_L_7procG_new(deactQ_Apa G_1, $action G_2) {\n    deactQ_L_7proc $tmp = acton_malloc(sizeof(struct deactQ_L_7proc));\n    $tmp->$class = &deactQ_L_7procG_methods;\n    deactQ_L_7procG_methods.__init__($tmp, G_1, G_2);\n    return $tmp;\n}\nstruct deactQ_L_7procG_class deactQ_L_7procG_methods;\nB_NoneType deactQ_L_8procD___init__ (deactQ_L_8proc L_self, deactQ_Apa self, $action cb) {\n    L_self->self = self;\n    L_self->cb = cb;\n    return B_None;\n}\n$R deactQ_L_8procD___call__ (deactQ_L_8proc L_self, $Cont C_cont) {\n    deactQ_Apa self = L_self->self;\n    $action cb = L_self->cb;\n    return (($R (*) (deactQ_Apa, $Cont, $action))self->$class->computeG_local)(self, C_cont, cb);\n}\n$R deactQ_L_8procD___exec__ (deactQ_L_8proc L_self, $Cont C_cont) {\n    return (($R (*) (deactQ_L_8proc, $Cont))L_self->$class->__call__)(L_self, C_cont);\n}\nvoid deactQ_L_8procD___serialize__ (deactQ_L_8proc self, $Serial$state state) {\n    $step_serialize(self->self, state);\n    $step_serialize(self->cb, state);\n}\ndeactQ_L_8proc deactQ_L_8procD___deserialize__ (deactQ_L_8proc self, $Serial$state state) {\n    if (!self) {\n        if (!state) {\n            self = acton_malloc(sizeof(struct deactQ_L_8proc));\n            self->$class = &deactQ_L_8procG_methods;\n            return self;\n        }\n        self = $DNEW(deactQ_L_8proc, state);\n    }\n    self->self = $step_deserialize(state);\n    self->cb = $step_deserialize(state);\n    return self;\n}\ndeactQ_L_8proc deactQ_L_8procG_new(deactQ_Apa G_1, $action G_2) {\n    deactQ_L_8proc $tmp = acton_malloc(sizeof(struct deactQ_L_8proc));\n    $tmp->$class = &deactQ_L_8procG_methods;\n    deactQ_L_8procG_methods.__init__($tmp, G_1, G_2);\n    return $tmp;\n}\nstruct deactQ_L_8procG_class deactQ_L_8procG_methods;\nB_NoneType deactQ_L_9procD___init__ (deactQ_L_9proc L_self, deactQ_Apa self, B_int i) {\n    L_self->self = self;\n    L_self->i = i;\n    return B_None;\n}\n$R deactQ_L_9procD___call__ (deactQ_L_9proc L_self, $Cont C_cont) {\n    deactQ_Apa self = L_self->self;\n    int64_t U_5i = ((B_int)L_self->i)->val;\n    return (($R (*) (deactQ_Apa, $Cont, B_int))self->$class->noticeG_local)(self, C_cont, toB_int(U_5i));\n}\n$R deactQ_L_9procD___exec__ (deactQ_L_9proc L_self, $Cont C_cont) {\n    return (($R (*) (deactQ_L_9proc, $Cont))L_self->$class->__call__)(L_self, C_cont);\n}\nvoid deactQ_L_9procD___serialize__ (deactQ_L_9proc self, $Serial$state state) {\n    $step_serialize(self->self, state);\n    $step_serialize(self->i, state);\n}\ndeactQ_L_9proc deactQ_L_9procD___deserialize__ (deactQ_L_9proc self, $Serial$state state) {\n    if (!self) {\n        if (!state) {\n            self = acton_malloc(sizeof(struct deactQ_L_9proc));\n            self->$class = &deactQ_L_9procG_methods;\n            return self;\n        }\n        self = $DNEW(deactQ_L_9proc, state);\n    }\n    self->self = $step_deserialize(state);\n    self->i = $step_deserialize(state);\n    return self;\n}\ndeactQ_L_9proc deactQ_L_9procG_new(deactQ_Apa G_1, B_int G_2) {\n    deactQ_L_9proc $tmp = acton_malloc(sizeof(struct deactQ_L_9proc));\n    $tmp->$class = &deactQ_L_9procG_methods;\n    deactQ_L_9procG_methods.__init__($tmp, G_1, G_2);\n    return $tmp;\n}\nstruct deactQ_L_9procG_class deactQ_L_9procG_methods;\nB_NoneType deactQ_L_10procD___init__ (deactQ_L_10proc L_self, deactQ_Bepa self, B_int i) {\n    L_self->self = self;\n    L_self->i = i;\n    return B_None;\n}\n$R deactQ_L_10procD___call__ (deactQ_L_10proc L_self, $Cont C_cont) {\n    deactQ_Bepa self = L_self->self;\n    int64_t U_6i = ((B_int)L_self->i)->val;\n    return (($R (*) (deactQ_Bepa, $Cont, B_int))self->$class->callbackG_local)(self, C_cont, toB_int(U_6i));\n}\n$R deactQ_L_10procD___exec__ (deactQ_L_10proc L_self, $Cont C_cont) {\n    return (($R (*) (deactQ_L_10proc, $Cont))L_self->$class->__call__)(L_self, C_cont);\n}\nvoid deactQ_L_10procD___serialize__ (deactQ_L_10proc self, $Serial$state state) {\n    $step_serialize(self->self, state);\n    $step_serialize(self->i, state);\n}\ndeactQ_L_10proc deactQ_L_10procD___deserialize__ (deactQ_L_10proc self, $Serial$state state) {\n    if (!self) {\n        if (!state) {\n            self = acton_malloc(sizeof(struct deactQ_L_10proc));\n            self->$class = &deactQ_L_10procG_methods;\n            return self;\n        }\n        self = $DNEW(deactQ_L_10proc, state);\n    }\n    self->self = $step_deserialize(state);\n    self->i = $step_deserialize(state);\n    return self;\n}\ndeactQ_L_10proc deactQ_L_10procG_new(deactQ_Bepa G_1, B_int G_2) {\n    deactQ_L_10proc $tmp = acton_malloc(sizeof(struct deactQ_L_10proc));\n    $tmp->$class = &deactQ_L_10procG_methods;\n    deactQ_L_10procG_methods.__init__($tmp, G_1, G_2);\n    return $tmp;\n}\nstruct deactQ_L_10procG_class deactQ_L_10procG_methods;\nB_NoneType deactQ_L_14actionD___init__ (deactQ_L_14action L_self, deactQ_Apa L_13obj) {\n    L_self->L_13obj = L_13obj;\n    return B_None;\n}\n$R deactQ_L_14actionD___call__ (deactQ_L_14action L_self, $Cont L_cont, B_int G_1) {\n    return $AWAIT(L_cont, ((B_Msg)((B_Msg (*) (deactQ_L_14action, B_int))L_self->$class->__asyn__)(L_self, G_1)));\n}\n$R deactQ_L_14actionD___exec__ (deactQ_L_14action L_self, $Cont L_cont, B_int G_1) {\n    return $R_CONT(L_cont, ((B_value)((B_Msg (*) (deactQ_L_14action, B_int))L_self->$class->__asyn__)(L_self, G_1)));\n}\nB_Msg deactQ_L_14actionD___asyn__ (deactQ_L_14action L_self, B_int G_1) {\n    deactQ_Apa L_13obj = L_self->L_13obj;\n    return ((B_Msg)((B_Msg (*) (deactQ_Apa, B_int))L_13obj->$class->notice)(L_13obj, G_1));\n}\nvoid deactQ_L_14actionD___serialize__ (deactQ_L_14action self, $Serial$state state) {\n    $step_serialize(self->L_13obj, state);\n}\ndeactQ_L_14action deactQ_L_14actionD___deserialize__ (deactQ_L_14action self, $Serial$state state) {\n    if (!self) {\n        if (!state) {\n            self = acton_malloc(sizeof(struct deactQ_L_14action));\n            self->$class = &deactQ_L_14actionG_methods;\n            return self;\n        }\n        self = $DNEW(deactQ_L_14action, state);\n    }\n    self->L_13obj = $step_deserialize(state);\n    return self;\n}\ndeactQ_L_14action deactQ_L_14actionG_new(deactQ_Apa G_1) {\n    deactQ_L_14action $tmp = acton_malloc(sizeof(struct deactQ_L_14action));\n    $tmp->$class = &deactQ_L_14actionG_methods;\n    deactQ_L_14actionG_methods.__init__($tmp, G_1);\n    return $tmp;\n}\nstruct deactQ_L_14actionG_class deactQ_L_14actionG_methods;\nB_NoneType deactQ_L_16actionD___init__ (deactQ_L_16action L_self, deactQ_Bepa L_15obj) {\n    L_self->L_15obj = L_15obj;\n    return B_None;\n}\n$R deactQ_L_16actionD___call__ (deactQ_L_16action L_self, $Cont L_cont, B_int G_1) {\n    return $AWAIT(L_cont, ((B_Msg)((B_Msg (*) (deactQ_L_16action, B_int))L_self->$class->__asyn__)(L_self, G_1)));\n}\n$R deactQ_L_16actionD___exec__ (deactQ_L_16action L_self, $Cont L_cont, B_int G_1) {\n    return $R_CONT(L_cont, ((B_value)((B_Msg (*) (deactQ_L_16action, B_int))L_self->$class->__asyn__)(L_self, G_1)));\n}\nB_Msg deactQ_L_16actionD___asyn__ (deactQ_L_16action L_self, B_int G_1) {\n    deactQ_Bepa L_15obj = L_self->L_15obj;\n    return ((B_Msg)((B_Msg (*) (deactQ_Bepa, B_int))L_15obj->$class->callback)(L_15obj, G_1));\n}\nvoid deactQ_L_16actionD___serialize__ (deactQ_L_16action self, $Serial$state state) {\n    $step_serialize(self->L_15obj, state);\n}\ndeactQ_L_16action deactQ_L_16actionD___deserialize__ (deactQ_L_16action self, $Serial$state state) {\n    if (!self) {\n        if (!state) {\n            self = acton_malloc(sizeof(struct deactQ_L_16action));\n            self->$class = &deactQ_L_16actionG_methods;\n            return self;\n        }\n        self = $DNEW(deactQ_L_16action, state);\n    }\n    self->L_15obj = $step_deserialize(state);\n    return self;\n}\ndeactQ_L_16action deactQ_L_16actionG_new(deactQ_Bepa G_1) {\n    deactQ_L_16action $tmp = acton_malloc(sizeof(struct deactQ_L_16action));\n    $tmp->$class = &deactQ_L_16actionG_methods;\n    deactQ_L_16actionG_methods.__init__($tmp, G_1);\n    return $tmp;\n}\nstruct deactQ_L_16actionG_class deactQ_L_16actionG_methods;\nB_NoneType deactQ_L_19actionD___init__ (deactQ_L_19action L_self, deactQ_main L_18obj) {\n    L_self->L_18obj = L_18obj;\n    return B_None;\n}\n$R deactQ_L_19actionD___call__ (deactQ_L_19action L_self, $Cont L_cont, B_int G_1) {\n    return $AWAIT(L_cont, ((B_Msg)((B_Msg (*) (deactQ_L_19action, B_int))L_self->$class->__asyn__)(L_self, G_1)));\n}\n$R deactQ_L_19actionD___exec__ (deactQ_L_19action L_self, $Cont L_cont, B_int G_1) {\n    return $R_CONT(L_cont, ((B_value)((B_Msg (*) (deactQ_L_19action, B_int))L_self->$class->__asyn__)(L_self, G_1)));\n}\nB_Msg deactQ_L_19actionD___asyn__ (deactQ_L_19action L_self, B_int G_1) {\n    deactQ_main L_18obj = L_self->L_18obj;\n    return ((B_Msg)((B_Msg (*) (deactQ_main, B_int))L_18obj->$class->myproc)(L_18obj, G_1));\n}\nvoid deactQ_L_19actionD___serialize__ (deactQ_L_19action self, $Serial$state state) {\n    $step_serialize(self->L_18obj, state);\n}\ndeactQ_L_19action deactQ_L_19actionD___deserialize__ (deactQ_L_19action self, $Serial$state state) {\n    if (!self) {\n        if (!state) {\n            self = acton_malloc(sizeof(struct deactQ_L_19action));\n            self->$class = &deactQ_L_19actionG_methods;\n            return self;\n        }\n        self = $DNEW(deactQ_L_19action, state);\n    }\n    self->L_18obj = $step_deserialize(state);\n    return self;\n}\ndeactQ_L_19action deactQ_L_19actionG_new(deactQ_main G_1) {\n    deactQ_L_19action $tmp = acton_malloc(sizeof(struct deactQ_L_19action));\n    $tmp->$class = &deactQ_L_19actionG_methods;\n    deactQ_L_19actionG_methods.__init__($tmp, G_1);\n    return $tmp;\n}\nstruct deactQ_L_19actionG_class deactQ_L_19actionG_methods;\n$R deactQ_U_1L_17C_9cont (deactQ_main self, $Cont C_cont, int64_t U_7C_10res) {\n    #line 34 \"test/src/deact.act\"\n    self->r = toB_int(U_7C_10res);\n    #line 35 \"test/src/deact.act\"\n    ((B_NoneType (*) (B_tuple, B_str, B_str, B_bool, B_bool))B_print)($NEWTUPLE(2, to$str(\"r =\"), self->r), B_None, B_None, B_None, B_None);\n    #line 36 \"test/src/deact.act\"\n    ((B_Msg (*) (deactQ_Apa, $action))self->a->$class->compute)(self->a, (($action)deactQ_L_19actionG_new(self)));\n    #line 37 \"test/src/deact.act\"\n    ((B_NoneType (*) (B_tuple, B_str, B_str, B_bool, B_bool))B_print)($NEWTUPLE(1, to$str(\"main\")), B_None, B_None, B_None, B_None);\n    return $R_CONT(C_cont, B_None);\n}\n$R deactQ_L_17C_9cont (deactQ_main self, $Cont C_cont, B_int C_10res) {\n    return deactQ_U_1L_17C_9cont(self, C_cont, ((B_int)C_10res)->val);\n}\nB_NoneType deactQ_L_20ContD___init__ (deactQ_L_20Cont L_self, deactQ_main self, $Cont C_cont) {\n    L_self->self = self;\n    L_self->C_cont = C_cont;\n    return B_None;\n}\n$R deactQ_L_20ContD___call__ (deactQ_L_20Cont L_self, B_int G_1) {\n    deactQ_main self = L_self->self;\n    $Cont C_cont = L_self->C_cont;\n    return deactQ_L_17C_9cont(self, C_cont, G_1);\n}\nvoid deactQ_L_20ContD___serialize__ (deactQ_L_20Cont self, $Serial$state state) {\n    $step_serialize(self->self, state);\n    $step_serialize(self->C_cont, state);\n}\ndeactQ_L_20Cont deactQ_L_20ContD___deserialize__ (deactQ_L_20Cont self, $Serial$state state) {\n    if (!self) {\n        if (!state) {\n            self = acton_malloc(sizeof(struct deactQ_L_20Cont));\n            self->$class = &deactQ_L_20ContG_methods;\n            return self;\n        }\n        self = $DNEW(deactQ_L_20Cont, state);\n    }\n    self->self = $step_deserialize(state);\n    self->C_cont = $step_deserialize(state);\n    return self;\n}\ndeactQ_L_20Cont deactQ_L_20ContG_new(deactQ_main G_1, $Cont G_2) {\n    deactQ_L_20Cont $tmp = acton_malloc(sizeof(struct deactQ_L_20Cont));\n    $tmp->$class = &deactQ_L_20ContG_methods;\n    deactQ_L_20ContG_methods.__init__($tmp, G_1, G_2);\n    return $tmp;\n}\nstruct deactQ_L_20ContG_class deactQ_L_20ContG_methods;\n$R deactQ_L_12C_7cont (deactQ_main self, $Cont C_cont, deactQ_Bepa C_8res) {\n    #line 30 \"test/src/deact.act\"\n    self->b = C_8res;\n    #line 31 \"test/src/deact.act\"\n    ((B_NoneType (*) (B_tuple, B_str, B_str, B_bool, B_bool))B_print)($NEWTUPLE(1, to$str(\"-----\")), B_None, B_None, B_None, B_None);\n    #line 32 \"test/src/deact.act\"\n    ((B_Msg (*) (deactQ_Apa, $action))self->a->$class->setup)(self->a, (($action)deactQ_L_14actionG_new(self->a)));\n    #line 33 \"test/src/deact.act\"\n    self->x = ((B_Msg (*) (deactQ_Apa, $action))self->a->$class->compute)(self->a, (($action)deactQ_L_16actionG_new(self->b)));\n    return $AWAIT((($Cont)deactQ_L_20ContG_new(self, C_cont)), self->x);\n}\nB_NoneType deactQ_L_21ContD___init__ (deactQ_L_21Cont L_self, deactQ_main self, $Cont C_cont) {\n    L_self->self = self;\n    L_self->C_cont = C_cont;\n    return B_None;\n}\n$R deactQ_L_21ContD___call__ (deactQ_L_21Cont L_self, deactQ_Bepa G_1) {\n    deactQ_main self = L_self->self;\n    $Cont C_cont = L_self->C_cont;\n    return deactQ_L_12C_7cont(self, C_cont, G_1);\n}\nvoid deactQ_L_21ContD___serialize__ (deactQ_L_21Cont self, $Serial$state state) {\n    $step_serialize(self->self, state);\n    $step_serialize(self->C_cont, state);\n}\ndeactQ_L_21Cont deactQ_L_21ContD___deserialize__ (deactQ_L_21Cont self, $Serial$state state) {\n    if (!self) {\n        if (!state) {\n            self = acton_malloc(sizeof(struct deactQ_L_21Cont));\n            self->$class = &deactQ_L_21ContG_methods;\n            return self;\n        }\n        self = $DNEW(deactQ_L_21Cont, state);\n    }\n    self->self = $step_deserialize(state);\n    self->C_cont = $step_deserialize(state);\n    return self;\n}\ndeactQ_L_21Cont deactQ_L_21ContG_new(deactQ_main G_1, $Cont G_2) {\n    deactQ_L_21Cont $tmp = acton_malloc(sizeof(struct deactQ_L_21Cont));\n    $tmp->$class = &deactQ_L_21ContG_methods;\n    deactQ_L_21ContG_methods.__init__($tmp, G_1, G_2);\n    return $tmp;\n}\nstruct deactQ_L_21ContG_class deactQ_L_21ContG_methods;\n$R deactQ_L_11C_5cont (deactQ_main self, $Cont C_cont, deactQ_Apa C_6res) {\n    #line 29 \"test/src/deact.act\"\n    self->a = C_6res;\n    return deactQ_BepaG_newact((($Cont)deactQ_L_21ContG_new(self, C_cont)));\n}\nB_NoneType deactQ_L_22ContD___init__ (deactQ_L_22Cont L_self, deactQ_main self, $Cont C_cont) {\n    L_self->self = self;\n    L_self->C_cont = C_cont;\n    return B_None;\n}\n$R deactQ_L_22ContD___call__ (deactQ_L_22Cont L_self, deactQ_Apa G_1) {\n    deactQ_main self = L_self->self;\n    $Cont C_cont = L_self->C_cont;\n    return deactQ_L_11C_5cont(self, C_cont, G_1);\n}\nvoid deactQ_L_22ContD___serialize__ (deactQ_L_22Cont self, $Serial$state state) {\n    $step_serialize(self->self, state);\n    $step_serialize(self->C_cont, state);\n}\ndeactQ_L_22Cont deactQ_L_22ContD___deserialize__ (deactQ_L_22Cont self, $Serial$state state) {\n    if (!self) {\n        if (!state) {\n            self = acton_malloc(sizeof(struct deactQ_L_22Cont));\n            self->$class = &deactQ_L_22ContG_methods;\n            return self;\n        }\n        self = $DNEW(deactQ_L_22Cont, state);\n    }\n    self->self = $step_deserialize(state);\n    self->C_cont = $step_deserialize(state);\n    return self;\n}\ndeactQ_L_22Cont deactQ_L_22ContG_new(deactQ_main G_1, $Cont G_2) {\n    deactQ_L_22Cont $tmp = acton_malloc(sizeof(struct deactQ_L_22Cont));\n    $tmp->$class = &deactQ_L_22ContG_methods;\n    deactQ_L_22ContG_methods.__init__($tmp, G_1, G_2);\n    return $tmp;\n}\nstruct deactQ_L_22ContG_class deactQ_L_22ContG_methods;\nB_NoneType deactQ_L_23procD___init__ (deactQ_L_23proc L_self, deactQ_main self, B_int i) {\n    L_self->self = self;\n    L_self->i = i;\n    return B_None;\n}\n$R deactQ_L_23procD___call__ (deactQ_L_23proc L_self, $Cont C_cont) {\n    deactQ_main self = L_self->self;\n    int64_t U_8i = ((B_int)L_self->i)->val;\n    return (($R (*) (deactQ_main, $Cont, B_int))self->$class->myprocG_local)(self, C_cont, toB_int(U_8i));\n}\n$R deactQ_L_23procD___exec__ (deactQ_L_23proc L_self, $Cont C_cont) {\n    return (($R (*) (deactQ_L_23proc, $Cont))L_self->$class->__call__)(L_self, C_cont);\n}\nvoid deactQ_L_23procD___serialize__ (deactQ_L_23proc self, $Serial$state state) {\n    $step_serialize(self->self, state);\n    $step_serialize(self->i, state);\n}\ndeactQ_L_23proc deactQ_L_23procD___deserialize__ (deactQ_L_23proc self, $Serial$state state) {\n    if (!self) {\n        if (!state) {\n            self = acton_malloc(sizeof(struct deactQ_L_23proc));\n            self->$class = &deactQ_L_23procG_methods;\n            return self;\n        }\n        self = $DNEW(deactQ_L_23proc, state);\n    }\n    self->self = $step_deserialize(state);\n    self->i = $step_deserialize(state);\n    return self;\n}\ndeactQ_L_23proc deactQ_L_23procG_new(deactQ_main G_1, B_int G_2) {\n    deactQ_L_23proc $tmp = acton_malloc(sizeof(struct deactQ_L_23proc));\n    $tmp->$class = &deactQ_L_23procG_methods;\n    deactQ_L_23procG_methods.__init__($tmp, G_1, G_2);\n    return $tmp;\n}\nstruct deactQ_L_23procG_class deactQ_L_23procG_methods;\n$R deactQ_L_24C_11cont ($Cont C_cont, deactQ_Apa G_act, B_NoneType C_12res) {\n    return $R_CONT(C_cont, G_act);\n}\nB_NoneType deactQ_L_25ContD___init__ (deactQ_L_25Cont L_self, $Cont C_cont, deactQ_Apa G_act) {\n    L_self->C_cont = C_cont;\n    L_self->G_act = G_act;\n    return B_None;\n}\n$R deactQ_L_25ContD___call__ (deactQ_L_25Cont L_self, B_NoneType G_1) {\n    $Cont C_cont = L_self->C_cont;\n    deactQ_Apa G_act = L_self->G_act;\n    return deactQ_L_24C_11cont(C_cont, G_act, G_1);\n}\nvoid deactQ_L_25ContD___serialize__ (deactQ_L_25Cont self, $Serial$state state) {\n    $step_serialize(self->C_cont, state);\n    $step_serialize(self->G_act, state);\n}\ndeactQ_L_25Cont deactQ_L_25ContD___deserialize__ (deactQ_L_25Cont self, $Serial$state state) {\n    if (!self) {\n        if (!state) {\n            self = acton_malloc(sizeof(struct deactQ_L_25Cont));\n            self->$class = &deactQ_L_25ContG_methods;\n            return self;\n        }\n        self = $DNEW(deactQ_L_25Cont, state);\n    }\n    self->C_cont = $step_deserialize(state);\n    self->G_act = $step_deserialize(state);\n    return self;\n}\ndeactQ_L_25Cont deactQ_L_25ContG_new($Cont G_1, deactQ_Apa G_2) {\n    deactQ_L_25Cont $tmp = acton_malloc(sizeof(struct deactQ_L_25Cont));\n    $tmp->$class = &deactQ_L_25ContG_methods;\n    deactQ_L_25ContG_methods.__init__($tmp, G_1, G_2);\n    return $tmp;\n}\nstruct deactQ_L_25ContG_class deactQ_L_25ContG_methods;\nB_NoneType deactQ_L_26procD___init__ (deactQ_L_26proc L_self, deactQ_Apa G_act) {\n    L_self->G_act = G_act;\n    return B_None;\n}\n$R deactQ_L_26procD___call__ (deactQ_L_26proc L_self, $Cont C_cont) {\n    deactQ_Apa G_act = L_self->G_act;\n    return (($R (*) (deactQ_Apa, $Cont))G_act->$class->__init__)(G_act, C_cont);\n}\n$R deactQ_L_26procD___exec__ (deactQ_L_26proc L_self, $Cont C_cont) {\n    return (($R (*) (deactQ_L_26proc, $Cont))L_self->$class->__call__)(L_self, C_cont);\n}\nvoid deactQ_L_26procD___serialize__ (deactQ_L_26proc self, $Serial$state state) {\n    $step_serialize(self->G_act, state);\n}\ndeactQ_L_26proc deactQ_L_26procD___deserialize__ (deactQ_L_26proc self, $Serial$state state) {\n    if (!self) {\n        if (!state) {\n            self = acton_malloc(sizeof(struct deactQ_L_26proc));\n            self->$class = &deactQ_L_26procG_methods;\n            return self;\n        }\n        self = $DNEW(deactQ_L_26proc, state);\n    }\n    self->G_act = $step_deserialize(state);\n    return self;\n}\ndeactQ_L_26proc deactQ_L_26procG_new(deactQ_Apa G_1) {\n    deactQ_L_26proc $tmp = acton_malloc(sizeof(struct deactQ_L_26proc));\n    $tmp->$class = &deactQ_L_26procG_methods;\n    deactQ_L_26procG_methods.__init__($tmp, G_1);\n    return $tmp;\n}\nstruct deactQ_L_26procG_class deactQ_L_26procG_methods;\n$R deactQ_L_27C_13cont ($Cont C_cont, deactQ_Bepa G_act, B_NoneType C_14res) {\n    return $R_CONT(C_cont, G_act);\n}\nB_NoneType deactQ_L_28ContD___init__ (deactQ_L_28Cont L_self, $Cont C_cont, deactQ_Bepa G_act) {\n    L_self->C_cont = C_cont;\n    L_self->G_act = G_act;\n    return B_None;\n}\n$R deactQ_L_28ContD___call__ (deactQ_L_28Cont L_self, B_NoneType G_1) {\n    $Cont C_cont = L_self->C_cont;\n    deactQ_Bepa G_act = L_self->G_act;\n    return deactQ_L_27C_13cont(C_cont, G_act, G_1);\n}\nvoid deactQ_L_28ContD___serialize__ (deactQ_L_28Cont self, $Serial$state state) {\n    $step_serialize(self->C_cont, state);\n    $step_serialize(self->G_act, state);\n}\ndeactQ_L_28Cont deactQ_L_28ContD___deserialize__ (deactQ_L_28Cont self, $Serial$state state) {\n    if (!self) {\n        if (!state) {\n            self = acton_malloc(sizeof(struct deactQ_L_28Cont));\n            self->$class = &deactQ_L_28ContG_methods;\n            return self;\n        }\n        self = $DNEW(deactQ_L_28Cont, state);\n    }\n    self->C_cont = $step_deserialize(state);\n    self->G_act = $step_deserialize(state);\n    return self;\n}\ndeactQ_L_28Cont deactQ_L_28ContG_new($Cont G_1, deactQ_Bepa G_2) {\n    deactQ_L_28Cont $tmp = acton_malloc(sizeof(struct deactQ_L_28Cont));\n    $tmp->$class = &deactQ_L_28ContG_methods;\n    deactQ_L_28ContG_methods.__init__($tmp, G_1, G_2);\n    return $tmp;\n}\nstruct deactQ_L_28ContG_class deactQ_L_28ContG_methods;\nB_NoneType deactQ_L_29procD___init__ (deactQ_L_29proc L_self, deactQ_Bepa G_act) {\n    L_self->G_act = G_act;\n    return B_None;\n}\n$R deactQ_L_29procD___call__ (deactQ_L_29proc L_self, $Cont C_cont) {\n    deactQ_Bepa G_act = L_self->G_act;\n    return (($R (*) (deactQ_Bepa, $Cont))G_act->$class->__init__)(G_act, C_cont);\n}\n$R deactQ_L_29procD___exec__ (deactQ_L_29proc L_self, $Cont C_cont) {\n    return (($R (*) (deactQ_L_29proc, $Cont))L_self->$class->__call__)(L_self, C_cont);\n}\nvoid deactQ_L_29procD___serialize__ (deactQ_L_29proc self, $Serial$state state) {\n    $step_serialize(self->G_act, state);\n}\ndeactQ_L_29proc deactQ_L_29procD___deserialize__ (deactQ_L_29proc self, $Serial$state state) {\n    if (!self) {\n        if (!state) {\n            self = acton_malloc(sizeof(struct deactQ_L_29proc));\n            self->$class = &deactQ_L_29procG_methods;\n            return self;\n        }\n        self = $DNEW(deactQ_L_29proc, state);\n    }\n    self->G_act = $step_deserialize(state);\n    return self;\n}\ndeactQ_L_29proc deactQ_L_29procG_new(deactQ_Bepa G_1) {\n    deactQ_L_29proc $tmp = acton_malloc(sizeof(struct deactQ_L_29proc));\n    $tmp->$class = &deactQ_L_29procG_methods;\n    deactQ_L_29procG_methods.__init__($tmp, G_1);\n    return $tmp;\n}\nstruct deactQ_L_29procG_class deactQ_L_29procG_methods;\n$R deactQ_L_30C_15cont ($Cont C_cont, deactQ_main G_act, B_NoneType C_16res) {\n    return $R_CONT(C_cont, G_act);\n}\nB_NoneType deactQ_L_31ContD___init__ (deactQ_L_31Cont L_self, $Cont C_cont, deactQ_main G_act) {\n    L_self->C_cont = C_cont;\n    L_self->G_act = G_act;\n    return B_None;\n}\n$R deactQ_L_31ContD___call__ (deactQ_L_31Cont L_self, B_NoneType G_1) {\n    $Cont C_cont = L_self->C_cont;\n    deactQ_main G_act = L_self->G_act;\n    return deactQ_L_30C_15cont(C_cont, G_act, G_1);\n}\nvoid deactQ_L_31ContD___serialize__ (deactQ_L_31Cont self, $Serial$state state) {\n    $step_serialize(self->C_cont, state);\n    $step_serialize(self->G_act, state);\n}\ndeactQ_L_31Cont deactQ_L_31ContD___deserialize__ (deactQ_L_31Cont self, $Serial$state state) {\n    if (!self) {\n        if (!state) {\n            self = acton_malloc(sizeof(struct deactQ_L_31Cont));\n            self->$class = &deactQ_L_31ContG_methods;\n            return self;\n        }\n        self = $DNEW(deactQ_L_31Cont, state);\n    }\n    self->C_cont = $step_deserialize(state);\n    self->G_act = $step_deserialize(state);\n    return self;\n}\ndeactQ_L_31Cont deactQ_L_31ContG_new($Cont G_1, deactQ_main G_2) {\n    deactQ_L_31Cont $tmp = acton_malloc(sizeof(struct deactQ_L_31Cont));\n    $tmp->$class = &deactQ_L_31ContG_methods;\n    deactQ_L_31ContG_methods.__init__($tmp, G_1, G_2);\n    return $tmp;\n}\nstruct deactQ_L_31ContG_class deactQ_L_31ContG_methods;\nB_NoneType deactQ_L_32procD___init__ (deactQ_L_32proc L_self, deactQ_main G_act, B_Env env) {\n    L_self->G_act = G_act;\n    L_self->env = env;\n    return B_None;\n}\n$R deactQ_L_32procD___call__ (deactQ_L_32proc L_self, $Cont C_cont) {\n    deactQ_main G_act = L_self->G_act;\n    B_Env env = L_self->env;\n    return (($R (*) (deactQ_main, $Cont, B_Env))G_act->$class->__init__)(G_act, C_cont, env);\n}\n$R deactQ_L_32procD___exec__ (deactQ_L_32proc L_self, $Cont C_cont) {\n    return (($R (*) (deactQ_L_32proc, $Cont))L_self->$class->__call__)(L_self, C_cont);\n}\nvoid deactQ_L_32procD___serialize__ (deactQ_L_32proc self, $Serial$state state) {\n    $step_serialize(self->G_act, state);\n    $step_serialize(self->env, state);\n}\ndeactQ_L_32proc deactQ_L_32procD___deserialize__ (deactQ_L_32proc self, $Serial$state state) {\n    if (!self) {\n        if (!state) {\n            self = acton_malloc(sizeof(struct deactQ_L_32proc));\n            self->$class = &deactQ_L_32procG_methods;\n            return self;\n        }\n        self = $DNEW(deactQ_L_32proc, state);\n    }\n    self->G_act = $step_deserialize(state);\n    self->env = $step_deserialize(state);\n    return self;\n}\ndeactQ_L_32proc deactQ_L_32procG_new(deactQ_main G_1, B_Env G_2) {\n    deactQ_L_32proc $tmp = acton_malloc(sizeof(struct deactQ_L_32proc));\n    $tmp->$class = &deactQ_L_32procG_methods;\n    deactQ_L_32procG_methods.__init__($tmp, G_1, G_2);\n    return $tmp;\n}\nstruct deactQ_L_32procG_class deactQ_L_32procG_methods;\n$R deactQ_ApaD___init__ (deactQ_Apa self, $Cont C_cont) {\n    return (($R (*) (deactQ_Apa, $Cont, $action))self->$class->setupG_local)(self, (($Cont)deactQ_L_2ContG_new(C_cont)), (($action)deactQ_L_4actionG_new(self)));\n}\n#line 2 \"test/src/deact.act\"\n$R deactQ_ApaD_setupG_local (deactQ_Apa self, $Cont C_cont, $action cb) {\n    #line 3 \"test/src/deact.act\"\n    ((B_NoneType (*) (B_tuple, B_str, B_str, B_bool, B_bool))B_print)($NEWTUPLE(1, to$str(\"setup\")), B_None, B_None, B_None, B_None);\n    #line 4 \"test/src/deact.act\"\n    ((B_Msg (*) ($action, B_int))cb->$class->__asyn__)(cb, toB_int(0LL));\n    return $R_CONT(C_cont, B_None);\n}\n#line 5 \"test/src/deact.act\"\n$R deactQ_ApaD_computeG_local (deactQ_Apa self, $Cont C_cont, $action cb) {\n    #line 6 \"test/src/deact.act\"\n    ((B_NoneType (*) (B_tuple, B_str, B_str, B_bool, B_bool))B_print)($NEWTUPLE(1, to$str(\"compute\")), B_None, B_None, B_None, B_None);\n    return $AWAIT((($Cont)deactQ_L_6ContG_new(cb, C_cont)), ((B_Msg)((B_Msg (*) ($action, B_int))cb->$class->__asyn__)(cb, toB_int(1LL))));\n}\n#line 10 \"test/src/deact.act\"\n$R deactQ_ApaD_noticeG_local (deactQ_Apa self, $Cont C_cont, B_int i) {\n    #line 11 \"test/src/deact.act\"\n    ((B_NoneType (*) (B_tuple, B_str, B_str, B_bool, B_bool))B_print)($NEWTUPLE(1, to$str(\"notice\")), B_None, B_None, B_None, B_None);\n    int64_t U_9N_1tmp = (((B_int)i)->val + 1LL);\n    return $R_CONT(C_cont, toB_int(U_9N_1tmp));\n}\nB_Msg deactQ_ApaD_setup (deactQ_Apa self, $action cb) {\n    return $ASYNC((($Actor)self), (($Cont)deactQ_L_7procG_new(self, cb)));\n}\nB_Msg deactQ_ApaD_compute (deactQ_Apa self, $action cb) {\n    return ((B_Msg)$ASYNC((($Actor)self), (($Cont)deactQ_L_8procG_new(self, cb))));\n}\nB_Msg deactQ_ApaD_notice (deactQ_Apa self, B_int i) {\n    return ((B_Msg)$ASYNC((($Actor)self), (($Cont)deactQ_L_9procG_new(self, i))));\n}\nvoid deactQ_ApaD___serialize__ (deactQ_Apa self, $Serial$state state) {\n    $ActorG_methods.__serialize__(($Actor)self, state);\n}\ndeactQ_Apa deactQ_ApaD___deserialize__ (deactQ_Apa self, $Serial$state state) {\n    if (!self) {\n        if (!state) {\n            self = acton_malloc(sizeof(struct deactQ_Apa));\n            self->$class = &deactQ_ApaG_methods;\n            return self;\n        }\n        self = $DNEW(deactQ_Apa, state);\n    }\n    $ActorG_methods.__deserialize__(($Actor)self, state);\n    return self;\n}\nvoid deactQ_ApaD_GCfinalizer (void *obj, void *cdata) {\n    deactQ_Apa self = (deactQ_Apa)obj;\n    self->$class->__cleanup__(self);\n}\n$R deactQ_ApaG_new($Cont G_1) {\n    deactQ_Apa $tmp = acton_malloc(sizeof(struct deactQ_Apa));\n    $tmp->$class = &deactQ_ApaG_methods;\n    return deactQ_ApaG_methods.__init__($tmp, $CONSTCONT($tmp, G_1));\n}\nstruct deactQ_ApaG_class deactQ_ApaG_methods;\n$R deactQ_BepaD___init__ (deactQ_Bepa self, $Cont C_cont) {\n    #line 21 \"test/src/deact.act\"\n    ((B_NoneType (*) (B_tuple, B_str, B_str, B_bool, B_bool))B_print)($NEWTUPLE(1, to$str(\"Bepa\")), B_None, B_None, B_None, B_None);\n    return $R_CONT(C_cont, B_None);\n}\n#line 18 \"test/src/deact.act\"\n$R deactQ_BepaD_callbackG_local (deactQ_Bepa self, $Cont C_cont, B_int i) {\n    #line 19 \"test/src/deact.act\"\n    ((B_NoneType (*) (B_tuple, B_str, B_str, B_bool, B_bool))B_print)($NEWTUPLE(2, to$str(\"callback\"), i), B_None, B_None, B_None, B_None);\n    int64_t U_10N_2tmp = (((B_int)i)->val + 1LL);\n    return $R_CONT(C_cont, toB_int(U_10N_2tmp));\n}\nB_Msg deactQ_BepaD_callback (deactQ_Bepa self, B_int i) {\n    return ((B_Msg)$ASYNC((($Actor)self), (($Cont)deactQ_L_10procG_new(self, i))));\n}\nvoid deactQ_BepaD___serialize__ (deactQ_Bepa self, $Serial$state state) {\n    $ActorG_methods.__serialize__(($Actor)self, state);\n}\ndeactQ_Bepa deactQ_BepaD___deserialize__ (deactQ_Bepa self, $Serial$state state) {\n    if (!self) {\n        if (!state) {\n            self = acton_malloc(sizeof(struct deactQ_Bepa));\n            self->$class = &deactQ_BepaG_methods;\n            return self;\n        }\n        self = $DNEW(deactQ_Bepa, state);\n    }\n    $ActorG_methods.__deserialize__(($Actor)self, state);\n    return self;\n}\nvoid deactQ_BepaD_GCfinalizer (void *obj, void *cdata) {\n    deactQ_Bepa self = (deactQ_Bepa)obj;\n    self->$class->__cleanup__(self);\n}\n$R deactQ_BepaG_new($Cont G_1) {\n    deactQ_Bepa $tmp = acton_malloc(sizeof(struct deactQ_Bepa));\n    $tmp->$class = &deactQ_BepaG_methods;\n    return deactQ_BepaG_methods.__init__($tmp, $CONSTCONT($tmp, G_1));\n}\nstruct deactQ_BepaG_class deactQ_BepaG_methods;\n$R deactQ_mainD___init__ (deactQ_main self, $Cont C_cont, B_Env env) {\n    self->env = env;\n    return deactQ_ApaG_newact((($Cont)deactQ_L_22ContG_new(self, C_cont)));\n}\n#line 24 \"test/src/deact.act\"\n$R deactQ_mainD_myprocG_local (deactQ_main self, $Cont C_cont, B_int i) {\n    #line 25 \"test/src/deact.act\"\n    ((B_NoneType (*) (B_tuple, B_str, B_str, B_bool, B_bool))B_print)($NEWTUPLE(2, to$str(\"myproc\"), i), B_None, B_None, B_None, B_None);\n    #line 26 \"test/src/deact.act\"\n    if ((((B_int)i)->val == 2LL)) {\n        #line 27 \"test/src/deact.act\"\n        ((B_Msg (*) (B_Env, B_int))self->env->$class->exit)(self->env, toB_int(0LL));\n    }\n    return $R_CONT(C_cont, i);\n}\nB_Msg deactQ_mainD_myproc (deactQ_main self, B_int i) {\n    return ((B_Msg)$ASYNC((($Actor)self), (($Cont)deactQ_L_23procG_new(self, i))));\n}\nvoid deactQ_mainD___serialize__ (deactQ_main self, $Serial$state state) {\n    $ActorG_methods.__serialize__(($Actor)self, state);\n    $step_serialize(self->env, state);\n    $step_serialize(self->a, state);\n    $step_serialize(self->b, state);\n    $step_serialize(self->x, state);\n    $step_serialize(self->r, state);\n}\ndeactQ_main deactQ_mainD___deserialize__ (deactQ_main self, $Serial$state state) {\n    if (!self) {\n        if (!state) {\n            self = acton_malloc(sizeof(struct deactQ_main));\n            self->$class = &deactQ_mainG_methods;\n            return self;\n        }\n        self = $DNEW(deactQ_main, state);\n    }\n    $ActorG_methods.__deserialize__(($Actor)self, state);\n    self->env = $step_deserialize(state);\n    self->a = $step_deserialize(state);\n    self->b = $step_deserialize(state);\n    self->x = $step_deserialize(state);\n    self->r = $step_deserialize(state);\n    return self;\n}\nvoid deactQ_mainD_GCfinalizer (void *obj, void *cdata) {\n    deactQ_main self = (deactQ_main)obj;\n    self->$class->__cleanup__(self);\n}\n$R deactQ_mainG_new($Cont G_1, B_Env G_2) {\n    deactQ_main $tmp = acton_malloc(sizeof(struct deactQ_main));\n    $tmp->$class = &deactQ_mainG_methods;\n    return deactQ_mainG_methods.__init__($tmp, $CONSTCONT($tmp, G_1), G_2);\n}\nstruct deactQ_mainG_class deactQ_mainG_methods;\n$R deactQ_ApaG_newact ($Cont C_cont) {\n    deactQ_Apa G_act = $NEWACTOR(deactQ_Apa);\n    if ((void*)G_act->$class->__cleanup__ != (void*)$ActorD___cleanup__) $InstallFinalizer(G_act, deactQ_ApaD_GCfinalizer);\n    return $AWAIT((($Cont)deactQ_L_25ContG_new(C_cont, G_act)), $ASYNC((($Actor)G_act), (($Cont)deactQ_L_26procG_new(G_act))));\n}\n$R deactQ_BepaG_newact ($Cont C_cont) {\n    deactQ_Bepa G_act = $NEWACTOR(deactQ_Bepa);\n    if ((void*)G_act->$class->__cleanup__ != (void*)$ActorD___cleanup__) $InstallFinalizer(G_act, deactQ_BepaD_GCfinalizer);\n    return $AWAIT((($Cont)deactQ_L_28ContG_new(C_cont, G_act)), $ASYNC((($Actor)G_act), (($Cont)deactQ_L_29procG_new(G_act))));\n}\n$R deactQ_mainG_newact ($Cont C_cont, B_Env env) {\n    deactQ_main G_act = $NEWACTOR(deactQ_main);\n    if ((void*)G_act->$class->__cleanup__ != (void*)$ActorD___cleanup__) $InstallFinalizer(G_act, deactQ_mainD_GCfinalizer);\n    return $AWAIT((($Cont)deactQ_L_31ContG_new(C_cont, G_act)), $ASYNC((($Actor)G_act), (($Cont)deactQ_L_32procG_new(G_act, env))));\n}\nint deactQ_done$ = 0;\nvoid deactQ___init__ () {\n    if (deactQ_done$) return;\n    deactQ_done$ = 1;\n    {\n        deactQ_L_2ContG_methods.$GCINFO = \"deactQ_L_2Cont\";\n        deactQ_L_2ContG_methods.$superclass = ($SuperG_class)&$ContG_methods;\n        deactQ_L_2ContG_methods.__bool__ = (B_bool (*) (deactQ_L_2Cont))B_valueG_methods.__bool__;\n        deactQ_L_2ContG_methods.__str__ = (B_str (*) (deactQ_L_2Cont))B_valueG_methods.__str__;\n        deactQ_L_2ContG_methods.__repr__ = (B_str (*) (deactQ_L_2Cont))B_valueG_methods.__repr__;\n        deactQ_L_2ContG_methods.__init__ = deactQ_L_2ContD___init__;\n        deactQ_L_2ContG_methods.__call__ = deactQ_L_2ContD___call__;\n        deactQ_L_2ContG_methods.__serialize__ = deactQ_L_2ContD___serialize__;\n        deactQ_L_2ContG_methods.__deserialize__ = deactQ_L_2ContD___deserialize__;\n        $register(&deactQ_L_2ContG_methods);\n    }\n    {\n        deactQ_L_4actionG_methods.$GCINFO = \"deactQ_L_4action\";\n        deactQ_L_4actionG_methods.$superclass = ($SuperG_class)&$actionG_methods;\n        deactQ_L_4actionG_methods.__bool__ = (B_bool (*) (deactQ_L_4action))B_valueG_methods.__bool__;\n        deactQ_L_4actionG_methods.__str__ = (B_str (*) (deactQ_L_4action))B_valueG_methods.__str__;\n        deactQ_L_4actionG_methods.__repr__ = (B_str (*) (deactQ_L_4action))B_valueG_methods.__repr__;\n        deactQ_L_4actionG_methods.__init__ = deactQ_L_4actionD___init__;\n        deactQ_L_4actionG_methods.__call__ = deactQ_L_4actionD___call__;\n        deactQ_L_4actionG_methods.__exec__ = deactQ_L_4actionD___exec__;\n        deactQ_L_4actionG_methods.__asyn__ = deactQ_L_4actionD___asyn__;\n        deactQ_L_4actionG_methods.__serialize__ = deactQ_L_4actionD___serialize__;\n        deactQ_L_4actionG_methods.__deserialize__ = deactQ_L_4actionD___deserialize__;\n        $register(&deactQ_L_4actionG_methods);\n    }\n    {\n        deactQ_L_6ContG_methods.$GCINFO = \"deactQ_L_6Cont\";\n        deactQ_L_6ContG_methods.$superclass = ($SuperG_class)&$ContG_methods;\n        deactQ_L_6ContG_methods.__bool__ = (B_bool (*) (deactQ_L_6Cont))B_valueG_methods.__bool__;\n        deactQ_L_6ContG_methods.__str__ = (B_str (*) (deactQ_L_6Cont))B_valueG_methods.__str__;\n        deactQ_L_6ContG_methods.__repr__ = (B_str (*) (deactQ_L_6Cont))B_valueG_methods.__repr__;\n        deactQ_L_6ContG_methods.__init__ = deactQ_L_6ContD___init__;\n        deactQ_L_6ContG_methods.__call__ = deactQ_L_6ContD___call__;\n        deactQ_L_6ContG_methods.__serialize__ = deactQ_L_6ContD___serialize__;\n        deactQ_L_6ContG_methods.__deserialize__ = deactQ_L_6ContD___deserialize__;\n        $register(&deactQ_L_6ContG_methods);\n    }\n    {\n        deactQ_L_7procG_methods.$GCINFO = \"deactQ_L_7proc\";\n        deactQ_L_7procG_methods.$superclass = ($SuperG_class)&$procG_methods;\n        deactQ_L_7procG_methods.__bool__ = (B_bool (*) (deactQ_L_7proc))B_valueG_methods.__bool__;\n        deactQ_L_7procG_methods.__str__ = (B_str (*) (deactQ_L_7proc))B_valueG_methods.__str__;\n        deactQ_L_7procG_methods.__repr__ = (B_str (*) (deactQ_L_7proc))B_valueG_methods.__repr__;\n        deactQ_L_7procG_methods.__init__ = deactQ_L_7procD___init__;\n        deactQ_L_7procG_methods.__call__ = deactQ_L_7procD___call__;\n        deactQ_L_7procG_methods.__exec__ = deactQ_L_7procD___exec__;\n        deactQ_L_7procG_methods.__serialize__ = deactQ_L_7procD___serialize__;\n        deactQ_L_7procG_methods.__deserialize__ = deactQ_L_7procD___deserialize__;\n        $register(&deactQ_L_7procG_methods);\n    }\n    {\n        deactQ_L_8procG_methods.$GCINFO = \"deactQ_L_8proc\";\n        deactQ_L_8procG_methods.$superclass = ($SuperG_class)&$procG_methods;\n        deactQ_L_8procG_methods.__bool__ = (B_bool (*) (deactQ_L_8proc))B_valueG_methods.__bool__;\n        deactQ_L_8procG_methods.__str__ = (B_str (*) (deactQ_L_8proc))B_valueG_methods.__str__;\n        deactQ_L_8procG_methods.__repr__ = (B_str (*) (deactQ_L_8proc))B_valueG_methods.__repr__;\n        deactQ_L_8procG_methods.__init__ = deactQ_L_8procD___init__;\n        deactQ_L_8procG_methods.__call__ = deactQ_L_8procD___call__;\n        deactQ_L_8procG_methods.__exec__ = deactQ_L_8procD___exec__;\n        deactQ_L_8procG_methods.__serialize__ = deactQ_L_8procD___serialize__;\n        deactQ_L_8procG_methods.__deserialize__ = deactQ_L_8procD___deserialize__;\n        $register(&deactQ_L_8procG_methods);\n    }\n    {\n        deactQ_L_9procG_methods.$GCINFO = \"deactQ_L_9proc\";\n        deactQ_L_9procG_methods.$superclass = ($SuperG_class)&$procG_methods;\n        deactQ_L_9procG_methods.__bool__ = (B_bool (*) (deactQ_L_9proc))B_valueG_methods.__bool__;\n        deactQ_L_9procG_methods.__str__ = (B_str (*) (deactQ_L_9proc))B_valueG_methods.__str__;\n        deactQ_L_9procG_methods.__repr__ = (B_str (*) (deactQ_L_9proc))B_valueG_methods.__repr__;\n        deactQ_L_9procG_methods.__init__ = deactQ_L_9procD___init__;\n        deactQ_L_9procG_methods.__call__ = deactQ_L_9procD___call__;\n        deactQ_L_9procG_methods.__exec__ = deactQ_L_9procD___exec__;\n        deactQ_L_9procG_methods.__serialize__ = deactQ_L_9procD___serialize__;\n        deactQ_L_9procG_methods.__deserialize__ = deactQ_L_9procD___deserialize__;\n        $register(&deactQ_L_9procG_methods);\n    }\n    {\n        deactQ_L_10procG_methods.$GCINFO = \"deactQ_L_10proc\";\n        deactQ_L_10procG_methods.$superclass = ($SuperG_class)&$procG_methods;\n        deactQ_L_10procG_methods.__bool__ = (B_bool (*) (deactQ_L_10proc))B_valueG_methods.__bool__;\n        deactQ_L_10procG_methods.__str__ = (B_str (*) (deactQ_L_10proc))B_valueG_methods.__str__;\n        deactQ_L_10procG_methods.__repr__ = (B_str (*) (deactQ_L_10proc))B_valueG_methods.__repr__;\n        deactQ_L_10procG_methods.__init__ = deactQ_L_10procD___init__;\n        deactQ_L_10procG_methods.__call__ = deactQ_L_10procD___call__;\n        deactQ_L_10procG_methods.__exec__ = deactQ_L_10procD___exec__;\n        deactQ_L_10procG_methods.__serialize__ = deactQ_L_10procD___serialize__;\n        deactQ_L_10procG_methods.__deserialize__ = deactQ_L_10procD___deserialize__;\n        $register(&deactQ_L_10procG_methods);\n    }\n    {\n        deactQ_L_14actionG_methods.$GCINFO = \"deactQ_L_14action\";\n        deactQ_L_14actionG_methods.$superclass = ($SuperG_class)&$actionG_methods;\n        deactQ_L_14actionG_methods.__bool__ = (B_bool (*) (deactQ_L_14action))B_valueG_methods.__bool__;\n        deactQ_L_14actionG_methods.__str__ = (B_str (*) (deactQ_L_14action))B_valueG_methods.__str__;\n        deactQ_L_14actionG_methods.__repr__ = (B_str (*) (deactQ_L_14action))B_valueG_methods.__repr__;\n        deactQ_L_14actionG_methods.__init__ = deactQ_L_14actionD___init__;\n        deactQ_L_14actionG_methods.__call__ = deactQ_L_14actionD___call__;\n        deactQ_L_14actionG_methods.__exec__ = deactQ_L_14actionD___exec__;\n        deactQ_L_14actionG_methods.__asyn__ = deactQ_L_14actionD___asyn__;\n        deactQ_L_14actionG_methods.__serialize__ = deactQ_L_14actionD___serialize__;\n        deactQ_L_14actionG_methods.__deserialize__ = deactQ_L_14actionD___deserialize__;\n        $register(&deactQ_L_14actionG_methods);\n    }\n    {\n        deactQ_L_16actionG_methods.$GCINFO = \"deactQ_L_16action\";\n        deactQ_L_16actionG_methods.$superclass = ($SuperG_class)&$actionG_methods;\n        deactQ_L_16actionG_methods.__bool__ = (B_bool (*) (deactQ_L_16action))B_valueG_methods.__bool__;\n        deactQ_L_16actionG_methods.__str__ = (B_str (*) (deactQ_L_16action))B_valueG_methods.__str__;\n        deactQ_L_16actionG_methods.__repr__ = (B_str (*) (deactQ_L_16action))B_valueG_methods.__repr__;\n        deactQ_L_16actionG_methods.__init__ = deactQ_L_16actionD___init__;\n        deactQ_L_16actionG_methods.__call__ = deactQ_L_16actionD___call__;\n        deactQ_L_16actionG_methods.__exec__ = deactQ_L_16actionD___exec__;\n        deactQ_L_16actionG_methods.__asyn__ = deactQ_L_16actionD___asyn__;\n        deactQ_L_16actionG_methods.__serialize__ = deactQ_L_16actionD___serialize__;\n        deactQ_L_16actionG_methods.__deserialize__ = deactQ_L_16actionD___deserialize__;\n        $register(&deactQ_L_16actionG_methods);\n    }\n    {\n        deactQ_L_19actionG_methods.$GCINFO = \"deactQ_L_19action\";\n        deactQ_L_19actionG_methods.$superclass = ($SuperG_class)&$actionG_methods;\n        deactQ_L_19actionG_methods.__bool__ = (B_bool (*) (deactQ_L_19action))B_valueG_methods.__bool__;\n        deactQ_L_19actionG_methods.__str__ = (B_str (*) (deactQ_L_19action))B_valueG_methods.__str__;\n        deactQ_L_19actionG_methods.__repr__ = (B_str (*) (deactQ_L_19action))B_valueG_methods.__repr__;\n        deactQ_L_19actionG_methods.__init__ = deactQ_L_19actionD___init__;\n        deactQ_L_19actionG_methods.__call__ = deactQ_L_19actionD___call__;\n        deactQ_L_19actionG_methods.__exec__ = deactQ_L_19actionD___exec__;\n        deactQ_L_19actionG_methods.__asyn__ = deactQ_L_19actionD___asyn__;\n        deactQ_L_19actionG_methods.__serialize__ = deactQ_L_19actionD___serialize__;\n        deactQ_L_19actionG_methods.__deserialize__ = deactQ_L_19actionD___deserialize__;\n        $register(&deactQ_L_19actionG_methods);\n    }\n    {\n        deactQ_L_20ContG_methods.$GCINFO = \"deactQ_L_20Cont\";\n        deactQ_L_20ContG_methods.$superclass = ($SuperG_class)&$ContG_methods;\n        deactQ_L_20ContG_methods.__bool__ = (B_bool (*) (deactQ_L_20Cont))B_valueG_methods.__bool__;\n        deactQ_L_20ContG_methods.__str__ = (B_str (*) (deactQ_L_20Cont))B_valueG_methods.__str__;\n        deactQ_L_20ContG_methods.__repr__ = (B_str (*) (deactQ_L_20Cont))B_valueG_methods.__repr__;\n        deactQ_L_20ContG_methods.__init__ = deactQ_L_20ContD___init__;\n        deactQ_L_20ContG_methods.__call__ = deactQ_L_20ContD___call__;\n        deactQ_L_20ContG_methods.__serialize__ = deactQ_L_20ContD___serialize__;\n        deactQ_L_20ContG_methods.__deserialize__ = deactQ_L_20ContD___deserialize__;\n        $register(&deactQ_L_20ContG_methods);\n    }\n    {\n        deactQ_L_21ContG_methods.$GCINFO = \"deactQ_L_21Cont\";\n        deactQ_L_21ContG_methods.$superclass = ($SuperG_class)&$ContG_methods;\n        deactQ_L_21ContG_methods.__bool__ = (B_bool (*) (deactQ_L_21Cont))B_valueG_methods.__bool__;\n        deactQ_L_21ContG_methods.__str__ = (B_str (*) (deactQ_L_21Cont))B_valueG_methods.__str__;\n        deactQ_L_21ContG_methods.__repr__ = (B_str (*) (deactQ_L_21Cont))B_valueG_methods.__repr__;\n        deactQ_L_21ContG_methods.__init__ = deactQ_L_21ContD___init__;\n        deactQ_L_21ContG_methods.__call__ = deactQ_L_21ContD___call__;\n        deactQ_L_21ContG_methods.__serialize__ = deactQ_L_21ContD___serialize__;\n        deactQ_L_21ContG_methods.__deserialize__ = deactQ_L_21ContD___deserialize__;\n        $register(&deactQ_L_21ContG_methods);\n    }\n    {\n        deactQ_L_22ContG_methods.$GCINFO = \"deactQ_L_22Cont\";\n        deactQ_L_22ContG_methods.$superclass = ($SuperG_class)&$ContG_methods;\n        deactQ_L_22ContG_methods.__bool__ = (B_bool (*) (deactQ_L_22Cont))B_valueG_methods.__bool__;\n        deactQ_L_22ContG_methods.__str__ = (B_str (*) (deactQ_L_22Cont))B_valueG_methods.__str__;\n        deactQ_L_22ContG_methods.__repr__ = (B_str (*) (deactQ_L_22Cont))B_valueG_methods.__repr__;\n        deactQ_L_22ContG_methods.__init__ = deactQ_L_22ContD___init__;\n        deactQ_L_22ContG_methods.__call__ = deactQ_L_22ContD___call__;\n        deactQ_L_22ContG_methods.__serialize__ = deactQ_L_22ContD___serialize__;\n        deactQ_L_22ContG_methods.__deserialize__ = deactQ_L_22ContD___deserialize__;\n        $register(&deactQ_L_22ContG_methods);\n    }\n    {\n        deactQ_L_23procG_methods.$GCINFO = \"deactQ_L_23proc\";\n        deactQ_L_23procG_methods.$superclass = ($SuperG_class)&$procG_methods;\n        deactQ_L_23procG_methods.__bool__ = (B_bool (*) (deactQ_L_23proc))B_valueG_methods.__bool__;\n        deactQ_L_23procG_methods.__str__ = (B_str (*) (deactQ_L_23proc))B_valueG_methods.__str__;\n        deactQ_L_23procG_methods.__repr__ = (B_str (*) (deactQ_L_23proc))B_valueG_methods.__repr__;\n        deactQ_L_23procG_methods.__init__ = deactQ_L_23procD___init__;\n        deactQ_L_23procG_methods.__call__ = deactQ_L_23procD___call__;\n        deactQ_L_23procG_methods.__exec__ = deactQ_L_23procD___exec__;\n        deactQ_L_23procG_methods.__serialize__ = deactQ_L_23procD___serialize__;\n        deactQ_L_23procG_methods.__deserialize__ = deactQ_L_23procD___deserialize__;\n        $register(&deactQ_L_23procG_methods);\n    }\n    {\n        deactQ_L_25ContG_methods.$GCINFO = \"deactQ_L_25Cont\";\n        deactQ_L_25ContG_methods.$superclass = ($SuperG_class)&$ContG_methods;\n        deactQ_L_25ContG_methods.__bool__ = (B_bool (*) (deactQ_L_25Cont))B_valueG_methods.__bool__;\n        deactQ_L_25ContG_methods.__str__ = (B_str (*) (deactQ_L_25Cont))B_valueG_methods.__str__;\n        deactQ_L_25ContG_methods.__repr__ = (B_str (*) (deactQ_L_25Cont))B_valueG_methods.__repr__;\n        deactQ_L_25ContG_methods.__init__ = deactQ_L_25ContD___init__;\n        deactQ_L_25ContG_methods.__call__ = deactQ_L_25ContD___call__;\n        deactQ_L_25ContG_methods.__serialize__ = deactQ_L_25ContD___serialize__;\n        deactQ_L_25ContG_methods.__deserialize__ = deactQ_L_25ContD___deserialize__;\n        $register(&deactQ_L_25ContG_methods);\n    }\n    {\n        deactQ_L_26procG_methods.$GCINFO = \"deactQ_L_26proc\";\n        deactQ_L_26procG_methods.$superclass = ($SuperG_class)&$procG_methods;\n        deactQ_L_26procG_methods.__bool__ = (B_bool (*) (deactQ_L_26proc))B_valueG_methods.__bool__;\n        deactQ_L_26procG_methods.__str__ = (B_str (*) (deactQ_L_26proc))B_valueG_methods.__str__;\n        deactQ_L_26procG_methods.__repr__ = (B_str (*) (deactQ_L_26proc))B_valueG_methods.__repr__;\n        deactQ_L_26procG_methods.__init__ = deactQ_L_26procD___init__;\n        deactQ_L_26procG_methods.__call__ = deactQ_L_26procD___call__;\n        deactQ_L_26procG_methods.__exec__ = deactQ_L_26procD___exec__;\n        deactQ_L_26procG_methods.__serialize__ = deactQ_L_26procD___serialize__;\n        deactQ_L_26procG_methods.__deserialize__ = deactQ_L_26procD___deserialize__;\n        $register(&deactQ_L_26procG_methods);\n    }\n    {\n        deactQ_L_28ContG_methods.$GCINFO = \"deactQ_L_28Cont\";\n        deactQ_L_28ContG_methods.$superclass = ($SuperG_class)&$ContG_methods;\n        deactQ_L_28ContG_methods.__bool__ = (B_bool (*) (deactQ_L_28Cont))B_valueG_methods.__bool__;\n        deactQ_L_28ContG_methods.__str__ = (B_str (*) (deactQ_L_28Cont))B_valueG_methods.__str__;\n        deactQ_L_28ContG_methods.__repr__ = (B_str (*) (deactQ_L_28Cont))B_valueG_methods.__repr__;\n        deactQ_L_28ContG_methods.__init__ = deactQ_L_28ContD___init__;\n        deactQ_L_28ContG_methods.__call__ = deactQ_L_28ContD___call__;\n        deactQ_L_28ContG_methods.__serialize__ = deactQ_L_28ContD___serialize__;\n        deactQ_L_28ContG_methods.__deserialize__ = deactQ_L_28ContD___deserialize__;\n        $register(&deactQ_L_28ContG_methods);\n    }\n    {\n        deactQ_L_29procG_methods.$GCINFO = \"deactQ_L_29proc\";\n        deactQ_L_29procG_methods.$superclass = ($SuperG_class)&$procG_methods;\n        deactQ_L_29procG_methods.__bool__ = (B_bool (*) (deactQ_L_29proc))B_valueG_methods.__bool__;\n        deactQ_L_29procG_methods.__str__ = (B_str (*) (deactQ_L_29proc))B_valueG_methods.__str__;\n        deactQ_L_29procG_methods.__repr__ = (B_str (*) (deactQ_L_29proc))B_valueG_methods.__repr__;\n        deactQ_L_29procG_methods.__init__ = deactQ_L_29procD___init__;\n        deactQ_L_29procG_methods.__call__ = deactQ_L_29procD___call__;\n        deactQ_L_29procG_methods.__exec__ = deactQ_L_29procD___exec__;\n        deactQ_L_29procG_methods.__serialize__ = deactQ_L_29procD___serialize__;\n        deactQ_L_29procG_methods.__deserialize__ = deactQ_L_29procD___deserialize__;\n        $register(&deactQ_L_29procG_methods);\n    }\n    {\n        deactQ_L_31ContG_methods.$GCINFO = \"deactQ_L_31Cont\";\n        deactQ_L_31ContG_methods.$superclass = ($SuperG_class)&$ContG_methods;\n        deactQ_L_31ContG_methods.__bool__ = (B_bool (*) (deactQ_L_31Cont))B_valueG_methods.__bool__;\n        deactQ_L_31ContG_methods.__str__ = (B_str (*) (deactQ_L_31Cont))B_valueG_methods.__str__;\n        deactQ_L_31ContG_methods.__repr__ = (B_str (*) (deactQ_L_31Cont))B_valueG_methods.__repr__;\n        deactQ_L_31ContG_methods.__init__ = deactQ_L_31ContD___init__;\n        deactQ_L_31ContG_methods.__call__ = deactQ_L_31ContD___call__;\n        deactQ_L_31ContG_methods.__serialize__ = deactQ_L_31ContD___serialize__;\n        deactQ_L_31ContG_methods.__deserialize__ = deactQ_L_31ContD___deserialize__;\n        $register(&deactQ_L_31ContG_methods);\n    }\n    {\n        deactQ_L_32procG_methods.$GCINFO = \"deactQ_L_32proc\";\n        deactQ_L_32procG_methods.$superclass = ($SuperG_class)&$procG_methods;\n        deactQ_L_32procG_methods.__bool__ = (B_bool (*) (deactQ_L_32proc))B_valueG_methods.__bool__;\n        deactQ_L_32procG_methods.__str__ = (B_str (*) (deactQ_L_32proc))B_valueG_methods.__str__;\n        deactQ_L_32procG_methods.__repr__ = (B_str (*) (deactQ_L_32proc))B_valueG_methods.__repr__;\n        deactQ_L_32procG_methods.__init__ = deactQ_L_32procD___init__;\n        deactQ_L_32procG_methods.__call__ = deactQ_L_32procD___call__;\n        deactQ_L_32procG_methods.__exec__ = deactQ_L_32procD___exec__;\n        deactQ_L_32procG_methods.__serialize__ = deactQ_L_32procD___serialize__;\n        deactQ_L_32procG_methods.__deserialize__ = deactQ_L_32procD___deserialize__;\n        $register(&deactQ_L_32procG_methods);\n    }\n    {\n        deactQ_ApaG_methods.$GCINFO = \"deactQ_Apa\";\n        deactQ_ApaG_methods.$superclass = ($SuperG_class)&$ActorG_methods;\n        deactQ_ApaG_methods.__bool__ = (B_bool (*) (deactQ_Apa))$ActorG_methods.__bool__;\n        deactQ_ApaG_methods.__str__ = (B_str (*) (deactQ_Apa))$ActorG_methods.__str__;\n        deactQ_ApaG_methods.__repr__ = (B_str (*) (deactQ_Apa))$ActorG_methods.__repr__;\n        deactQ_ApaG_methods.__resume__ = (B_NoneType (*) (deactQ_Apa))$ActorG_methods.__resume__;\n        deactQ_ApaG_methods.__cleanup__ = (B_NoneType (*) (deactQ_Apa))$ActorG_methods.__cleanup__;\n        deactQ_ApaG_methods.__init__ = deactQ_ApaD___init__;\n        deactQ_ApaG_methods.setupG_local = deactQ_ApaD_setupG_local;\n        deactQ_ApaG_methods.computeG_local = deactQ_ApaD_computeG_local;\n        deactQ_ApaG_methods.noticeG_local = deactQ_ApaD_noticeG_local;\n        deactQ_ApaG_methods.setup = deactQ_ApaD_setup;\n        deactQ_ApaG_methods.compute = deactQ_ApaD_compute;\n        deactQ_ApaG_methods.notice = deactQ_ApaD_notice;\n        deactQ_ApaG_methods.__serialize__ = deactQ_ApaD___serialize__;\n        deactQ_ApaG_methods.__deserialize__ = deactQ_ApaD___deserialize__;\n        $register(&deactQ_ApaG_methods);\n    }\n    {\n        deactQ_BepaG_methods.$GCINFO = \"deactQ_Bepa\";\n        deactQ_BepaG_methods.$superclass = ($SuperG_class)&$ActorG_methods;\n        deactQ_BepaG_methods.__bool__ = (B_bool (*) (deactQ_Bepa))$ActorG_methods.__bool__;\n        deactQ_BepaG_methods.__str__ = (B_str (*) (deactQ_Bepa))$ActorG_methods.__str__;\n        deactQ_BepaG_methods.__repr__ = (B_str (*) (deactQ_Bepa))$ActorG_methods.__repr__;\n        deactQ_BepaG_methods.__resume__ = (B_NoneType (*) (deactQ_Bepa))$ActorG_methods.__resume__;\n        deactQ_BepaG_methods.__cleanup__ = (B_NoneType (*) (deactQ_Bepa))$ActorG_methods.__cleanup__;\n        deactQ_BepaG_methods.__init__ = deactQ_BepaD___init__;\n        deactQ_BepaG_methods.callbackG_local = deactQ_BepaD_callbackG_local;\n        deactQ_BepaG_methods.callback = deactQ_BepaD_callback;\n        deactQ_BepaG_methods.__serialize__ = deactQ_BepaD___serialize__;\n        deactQ_BepaG_methods.__deserialize__ = deactQ_BepaD___deserialize__;\n        $register(&deactQ_BepaG_methods);\n    }\n    {\n        deactQ_mainG_methods.$GCINFO = \"deactQ_main\";\n        deactQ_mainG_methods.$superclass = ($SuperG_class)&$ActorG_methods;\n        deactQ_mainG_methods.__bool__ = (B_bool (*) (deactQ_main))$ActorG_methods.__bool__;\n        deactQ_mainG_methods.__str__ = (B_str (*) (deactQ_main))$ActorG_methods.__str__;\n        deactQ_mainG_methods.__repr__ = (B_str (*) (deactQ_main))$ActorG_methods.__repr__;\n        deactQ_mainG_methods.__resume__ = (B_NoneType (*) (deactQ_main))$ActorG_methods.__resume__;\n        deactQ_mainG_methods.__cleanup__ = (B_NoneType (*) (deactQ_main))$ActorG_methods.__cleanup__;\n        deactQ_mainG_methods.__init__ = deactQ_mainD___init__;\n        deactQ_mainG_methods.myprocG_local = deactQ_mainD_myprocG_local;\n        deactQ_mainG_methods.myproc = deactQ_mainD_myproc;\n        deactQ_mainG_methods.__serialize__ = deactQ_mainD___serialize__;\n        deactQ_mainG_methods.__deserialize__ = deactQ_mainD___deserialize__;\n        $register(&deactQ_mainG_methods);\n    }\n}"
  },
  {
    "path": "compiler/lib/test/9-codegen/deact.h",
    "content": "/* Acton impl hash: test-hash */\n#pragma once\n#include \"builtin/builtin.h\"\n#include \"rts/rts.h\"\nstruct deactQ_L_2Cont;\nstruct deactQ_L_4action;\nstruct deactQ_L_6Cont;\nstruct deactQ_L_7proc;\nstruct deactQ_L_8proc;\nstruct deactQ_L_9proc;\nstruct deactQ_L_10proc;\nstruct deactQ_L_14action;\nstruct deactQ_L_16action;\nstruct deactQ_L_19action;\nstruct deactQ_L_20Cont;\nstruct deactQ_L_21Cont;\nstruct deactQ_L_22Cont;\nstruct deactQ_L_23proc;\nstruct deactQ_L_25Cont;\nstruct deactQ_L_26proc;\nstruct deactQ_L_28Cont;\nstruct deactQ_L_29proc;\nstruct deactQ_L_31Cont;\nstruct deactQ_L_32proc;\nstruct deactQ_Apa;\nstruct deactQ_Bepa;\nstruct deactQ_main;\ntypedef struct deactQ_L_2Cont *deactQ_L_2Cont;\ntypedef struct deactQ_L_4action *deactQ_L_4action;\ntypedef struct deactQ_L_6Cont *deactQ_L_6Cont;\ntypedef struct deactQ_L_7proc *deactQ_L_7proc;\ntypedef struct deactQ_L_8proc *deactQ_L_8proc;\ntypedef struct deactQ_L_9proc *deactQ_L_9proc;\ntypedef struct deactQ_L_10proc *deactQ_L_10proc;\ntypedef struct deactQ_L_14action *deactQ_L_14action;\ntypedef struct deactQ_L_16action *deactQ_L_16action;\ntypedef struct deactQ_L_19action *deactQ_L_19action;\ntypedef struct deactQ_L_20Cont *deactQ_L_20Cont;\ntypedef struct deactQ_L_21Cont *deactQ_L_21Cont;\ntypedef struct deactQ_L_22Cont *deactQ_L_22Cont;\ntypedef struct deactQ_L_23proc *deactQ_L_23proc;\ntypedef struct deactQ_L_25Cont *deactQ_L_25Cont;\ntypedef struct deactQ_L_26proc *deactQ_L_26proc;\ntypedef struct deactQ_L_28Cont *deactQ_L_28Cont;\ntypedef struct deactQ_L_29proc *deactQ_L_29proc;\ntypedef struct deactQ_L_31Cont *deactQ_L_31Cont;\ntypedef struct deactQ_L_32proc *deactQ_L_32proc;\ntypedef struct deactQ_Apa *deactQ_Apa;\ntypedef struct deactQ_Bepa *deactQ_Bepa;\ntypedef struct deactQ_main *deactQ_main;\n$R deactQ_L_1C_1cont ($Cont, B_NoneType);\nstruct deactQ_L_2ContG_class {\n    char *$GCINFO;\n    int $class_id;\n    $SuperG_class $superclass;\n    B_NoneType (*__init__) (deactQ_L_2Cont, $Cont);\n    void (*__serialize__) (deactQ_L_2Cont, $Serial$state);\n    deactQ_L_2Cont (*__deserialize__) (deactQ_L_2Cont, $Serial$state);\n    B_bool (*__bool__) (deactQ_L_2Cont);\n    B_str (*__str__) (deactQ_L_2Cont);\n    B_str (*__repr__) (deactQ_L_2Cont);\n    $R (*__call__) (deactQ_L_2Cont, B_NoneType);\n};\nstruct deactQ_L_2Cont {\n    struct deactQ_L_2ContG_class *$class;\n    $Cont C_cont;\n};\nstruct deactQ_L_4actionG_class {\n    char *$GCINFO;\n    int $class_id;\n    $SuperG_class $superclass;\n    B_NoneType (*__init__) (deactQ_L_4action, deactQ_Apa);\n    void (*__serialize__) (deactQ_L_4action, $Serial$state);\n    deactQ_L_4action (*__deserialize__) (deactQ_L_4action, $Serial$state);\n    B_bool (*__bool__) (deactQ_L_4action);\n    B_str (*__str__) (deactQ_L_4action);\n    B_str (*__repr__) (deactQ_L_4action);\n    $R (*__call__) (deactQ_L_4action, $Cont, B_int);\n    $R (*__exec__) (deactQ_L_4action, $Cont, B_int);\n    B_Msg (*__asyn__) (deactQ_L_4action, B_int);\n};\nstruct deactQ_L_4action {\n    struct deactQ_L_4actionG_class *$class;\n    deactQ_Apa L_3obj;\n};\n$R deactQ_U_L_5C_3cont ($action, $Cont, int64_t);\n$R deactQ_L_5C_3cont ($action, $Cont, B_int);\nstruct deactQ_L_6ContG_class {\n    char *$GCINFO;\n    int $class_id;\n    $SuperG_class $superclass;\n    B_NoneType (*__init__) (deactQ_L_6Cont, $action, $Cont);\n    void (*__serialize__) (deactQ_L_6Cont, $Serial$state);\n    deactQ_L_6Cont (*__deserialize__) (deactQ_L_6Cont, $Serial$state);\n    B_bool (*__bool__) (deactQ_L_6Cont);\n    B_str (*__str__) (deactQ_L_6Cont);\n    B_str (*__repr__) (deactQ_L_6Cont);\n    $R (*__call__) (deactQ_L_6Cont, B_int);\n};\nstruct deactQ_L_6Cont {\n    struct deactQ_L_6ContG_class *$class;\n    $action cb;\n    $Cont C_cont;\n};\nstruct deactQ_L_7procG_class {\n    char *$GCINFO;\n    int $class_id;\n    $SuperG_class $superclass;\n    B_NoneType (*__init__) (deactQ_L_7proc, deactQ_Apa, $action);\n    void (*__serialize__) (deactQ_L_7proc, $Serial$state);\n    deactQ_L_7proc (*__deserialize__) (deactQ_L_7proc, $Serial$state);\n    B_bool (*__bool__) (deactQ_L_7proc);\n    B_str (*__str__) (deactQ_L_7proc);\n    B_str (*__repr__) (deactQ_L_7proc);\n    $R (*__call__) (deactQ_L_7proc, $Cont);\n    $R (*__exec__) (deactQ_L_7proc, $Cont);\n};\nstruct deactQ_L_7proc {\n    struct deactQ_L_7procG_class *$class;\n    deactQ_Apa self;\n    $action cb;\n};\nstruct deactQ_L_8procG_class {\n    char *$GCINFO;\n    int $class_id;\n    $SuperG_class $superclass;\n    B_NoneType (*__init__) (deactQ_L_8proc, deactQ_Apa, $action);\n    void (*__serialize__) (deactQ_L_8proc, $Serial$state);\n    deactQ_L_8proc (*__deserialize__) (deactQ_L_8proc, $Serial$state);\n    B_bool (*__bool__) (deactQ_L_8proc);\n    B_str (*__str__) (deactQ_L_8proc);\n    B_str (*__repr__) (deactQ_L_8proc);\n    $R (*__call__) (deactQ_L_8proc, $Cont);\n    $R (*__exec__) (deactQ_L_8proc, $Cont);\n};\nstruct deactQ_L_8proc {\n    struct deactQ_L_8procG_class *$class;\n    deactQ_Apa self;\n    $action cb;\n};\nstruct deactQ_L_9procG_class {\n    char *$GCINFO;\n    int $class_id;\n    $SuperG_class $superclass;\n    B_NoneType (*__init__) (deactQ_L_9proc, deactQ_Apa, B_int);\n    void (*__serialize__) (deactQ_L_9proc, $Serial$state);\n    deactQ_L_9proc (*__deserialize__) (deactQ_L_9proc, $Serial$state);\n    B_bool (*__bool__) (deactQ_L_9proc);\n    B_str (*__str__) (deactQ_L_9proc);\n    B_str (*__repr__) (deactQ_L_9proc);\n    $R (*__call__) (deactQ_L_9proc, $Cont);\n    $R (*__exec__) (deactQ_L_9proc, $Cont);\n};\nstruct deactQ_L_9proc {\n    struct deactQ_L_9procG_class *$class;\n    deactQ_Apa self;\n    B_int i;\n};\nstruct deactQ_L_10procG_class {\n    char *$GCINFO;\n    int $class_id;\n    $SuperG_class $superclass;\n    B_NoneType (*__init__) (deactQ_L_10proc, deactQ_Bepa, B_int);\n    void (*__serialize__) (deactQ_L_10proc, $Serial$state);\n    deactQ_L_10proc (*__deserialize__) (deactQ_L_10proc, $Serial$state);\n    B_bool (*__bool__) (deactQ_L_10proc);\n    B_str (*__str__) (deactQ_L_10proc);\n    B_str (*__repr__) (deactQ_L_10proc);\n    $R (*__call__) (deactQ_L_10proc, $Cont);\n    $R (*__exec__) (deactQ_L_10proc, $Cont);\n};\nstruct deactQ_L_10proc {\n    struct deactQ_L_10procG_class *$class;\n    deactQ_Bepa self;\n    B_int i;\n};\nstruct deactQ_L_14actionG_class {\n    char *$GCINFO;\n    int $class_id;\n    $SuperG_class $superclass;\n    B_NoneType (*__init__) (deactQ_L_14action, deactQ_Apa);\n    void (*__serialize__) (deactQ_L_14action, $Serial$state);\n    deactQ_L_14action (*__deserialize__) (deactQ_L_14action, $Serial$state);\n    B_bool (*__bool__) (deactQ_L_14action);\n    B_str (*__str__) (deactQ_L_14action);\n    B_str (*__repr__) (deactQ_L_14action);\n    $R (*__call__) (deactQ_L_14action, $Cont, B_int);\n    $R (*__exec__) (deactQ_L_14action, $Cont, B_int);\n    B_Msg (*__asyn__) (deactQ_L_14action, B_int);\n};\nstruct deactQ_L_14action {\n    struct deactQ_L_14actionG_class *$class;\n    deactQ_Apa L_13obj;\n};\nstruct deactQ_L_16actionG_class {\n    char *$GCINFO;\n    int $class_id;\n    $SuperG_class $superclass;\n    B_NoneType (*__init__) (deactQ_L_16action, deactQ_Bepa);\n    void (*__serialize__) (deactQ_L_16action, $Serial$state);\n    deactQ_L_16action (*__deserialize__) (deactQ_L_16action, $Serial$state);\n    B_bool (*__bool__) (deactQ_L_16action);\n    B_str (*__str__) (deactQ_L_16action);\n    B_str (*__repr__) (deactQ_L_16action);\n    $R (*__call__) (deactQ_L_16action, $Cont, B_int);\n    $R (*__exec__) (deactQ_L_16action, $Cont, B_int);\n    B_Msg (*__asyn__) (deactQ_L_16action, B_int);\n};\nstruct deactQ_L_16action {\n    struct deactQ_L_16actionG_class *$class;\n    deactQ_Bepa L_15obj;\n};\nstruct deactQ_L_19actionG_class {\n    char *$GCINFO;\n    int $class_id;\n    $SuperG_class $superclass;\n    B_NoneType (*__init__) (deactQ_L_19action, deactQ_main);\n    void (*__serialize__) (deactQ_L_19action, $Serial$state);\n    deactQ_L_19action (*__deserialize__) (deactQ_L_19action, $Serial$state);\n    B_bool (*__bool__) (deactQ_L_19action);\n    B_str (*__str__) (deactQ_L_19action);\n    B_str (*__repr__) (deactQ_L_19action);\n    $R (*__call__) (deactQ_L_19action, $Cont, B_int);\n    $R (*__exec__) (deactQ_L_19action, $Cont, B_int);\n    B_Msg (*__asyn__) (deactQ_L_19action, B_int);\n};\nstruct deactQ_L_19action {\n    struct deactQ_L_19actionG_class *$class;\n    deactQ_main L_18obj;\n};\n$R deactQ_U_1L_17C_9cont (deactQ_main, $Cont, int64_t);\n$R deactQ_L_17C_9cont (deactQ_main, $Cont, B_int);\nstruct deactQ_L_20ContG_class {\n    char *$GCINFO;\n    int $class_id;\n    $SuperG_class $superclass;\n    B_NoneType (*__init__) (deactQ_L_20Cont, deactQ_main, $Cont);\n    void (*__serialize__) (deactQ_L_20Cont, $Serial$state);\n    deactQ_L_20Cont (*__deserialize__) (deactQ_L_20Cont, $Serial$state);\n    B_bool (*__bool__) (deactQ_L_20Cont);\n    B_str (*__str__) (deactQ_L_20Cont);\n    B_str (*__repr__) (deactQ_L_20Cont);\n    $R (*__call__) (deactQ_L_20Cont, B_int);\n};\nstruct deactQ_L_20Cont {\n    struct deactQ_L_20ContG_class *$class;\n    deactQ_main self;\n    $Cont C_cont;\n};\n$R deactQ_L_12C_7cont (deactQ_main, $Cont, deactQ_Bepa);\nstruct deactQ_L_21ContG_class {\n    char *$GCINFO;\n    int $class_id;\n    $SuperG_class $superclass;\n    B_NoneType (*__init__) (deactQ_L_21Cont, deactQ_main, $Cont);\n    void (*__serialize__) (deactQ_L_21Cont, $Serial$state);\n    deactQ_L_21Cont (*__deserialize__) (deactQ_L_21Cont, $Serial$state);\n    B_bool (*__bool__) (deactQ_L_21Cont);\n    B_str (*__str__) (deactQ_L_21Cont);\n    B_str (*__repr__) (deactQ_L_21Cont);\n    $R (*__call__) (deactQ_L_21Cont, deactQ_Bepa);\n};\nstruct deactQ_L_21Cont {\n    struct deactQ_L_21ContG_class *$class;\n    deactQ_main self;\n    $Cont C_cont;\n};\n$R deactQ_L_11C_5cont (deactQ_main, $Cont, deactQ_Apa);\nstruct deactQ_L_22ContG_class {\n    char *$GCINFO;\n    int $class_id;\n    $SuperG_class $superclass;\n    B_NoneType (*__init__) (deactQ_L_22Cont, deactQ_main, $Cont);\n    void (*__serialize__) (deactQ_L_22Cont, $Serial$state);\n    deactQ_L_22Cont (*__deserialize__) (deactQ_L_22Cont, $Serial$state);\n    B_bool (*__bool__) (deactQ_L_22Cont);\n    B_str (*__str__) (deactQ_L_22Cont);\n    B_str (*__repr__) (deactQ_L_22Cont);\n    $R (*__call__) (deactQ_L_22Cont, deactQ_Apa);\n};\nstruct deactQ_L_22Cont {\n    struct deactQ_L_22ContG_class *$class;\n    deactQ_main self;\n    $Cont C_cont;\n};\nstruct deactQ_L_23procG_class {\n    char *$GCINFO;\n    int $class_id;\n    $SuperG_class $superclass;\n    B_NoneType (*__init__) (deactQ_L_23proc, deactQ_main, B_int);\n    void (*__serialize__) (deactQ_L_23proc, $Serial$state);\n    deactQ_L_23proc (*__deserialize__) (deactQ_L_23proc, $Serial$state);\n    B_bool (*__bool__) (deactQ_L_23proc);\n    B_str (*__str__) (deactQ_L_23proc);\n    B_str (*__repr__) (deactQ_L_23proc);\n    $R (*__call__) (deactQ_L_23proc, $Cont);\n    $R (*__exec__) (deactQ_L_23proc, $Cont);\n};\nstruct deactQ_L_23proc {\n    struct deactQ_L_23procG_class *$class;\n    deactQ_main self;\n    B_int i;\n};\n$R deactQ_L_24C_11cont ($Cont, deactQ_Apa, B_NoneType);\nstruct deactQ_L_25ContG_class {\n    char *$GCINFO;\n    int $class_id;\n    $SuperG_class $superclass;\n    B_NoneType (*__init__) (deactQ_L_25Cont, $Cont, deactQ_Apa);\n    void (*__serialize__) (deactQ_L_25Cont, $Serial$state);\n    deactQ_L_25Cont (*__deserialize__) (deactQ_L_25Cont, $Serial$state);\n    B_bool (*__bool__) (deactQ_L_25Cont);\n    B_str (*__str__) (deactQ_L_25Cont);\n    B_str (*__repr__) (deactQ_L_25Cont);\n    $R (*__call__) (deactQ_L_25Cont, B_NoneType);\n};\nstruct deactQ_L_25Cont {\n    struct deactQ_L_25ContG_class *$class;\n    $Cont C_cont;\n    deactQ_Apa G_act;\n};\nstruct deactQ_L_26procG_class {\n    char *$GCINFO;\n    int $class_id;\n    $SuperG_class $superclass;\n    B_NoneType (*__init__) (deactQ_L_26proc, deactQ_Apa);\n    void (*__serialize__) (deactQ_L_26proc, $Serial$state);\n    deactQ_L_26proc (*__deserialize__) (deactQ_L_26proc, $Serial$state);\n    B_bool (*__bool__) (deactQ_L_26proc);\n    B_str (*__str__) (deactQ_L_26proc);\n    B_str (*__repr__) (deactQ_L_26proc);\n    $R (*__call__) (deactQ_L_26proc, $Cont);\n    $R (*__exec__) (deactQ_L_26proc, $Cont);\n};\nstruct deactQ_L_26proc {\n    struct deactQ_L_26procG_class *$class;\n    deactQ_Apa G_act;\n};\n$R deactQ_L_27C_13cont ($Cont, deactQ_Bepa, B_NoneType);\nstruct deactQ_L_28ContG_class {\n    char *$GCINFO;\n    int $class_id;\n    $SuperG_class $superclass;\n    B_NoneType (*__init__) (deactQ_L_28Cont, $Cont, deactQ_Bepa);\n    void (*__serialize__) (deactQ_L_28Cont, $Serial$state);\n    deactQ_L_28Cont (*__deserialize__) (deactQ_L_28Cont, $Serial$state);\n    B_bool (*__bool__) (deactQ_L_28Cont);\n    B_str (*__str__) (deactQ_L_28Cont);\n    B_str (*__repr__) (deactQ_L_28Cont);\n    $R (*__call__) (deactQ_L_28Cont, B_NoneType);\n};\nstruct deactQ_L_28Cont {\n    struct deactQ_L_28ContG_class *$class;\n    $Cont C_cont;\n    deactQ_Bepa G_act;\n};\nstruct deactQ_L_29procG_class {\n    char *$GCINFO;\n    int $class_id;\n    $SuperG_class $superclass;\n    B_NoneType (*__init__) (deactQ_L_29proc, deactQ_Bepa);\n    void (*__serialize__) (deactQ_L_29proc, $Serial$state);\n    deactQ_L_29proc (*__deserialize__) (deactQ_L_29proc, $Serial$state);\n    B_bool (*__bool__) (deactQ_L_29proc);\n    B_str (*__str__) (deactQ_L_29proc);\n    B_str (*__repr__) (deactQ_L_29proc);\n    $R (*__call__) (deactQ_L_29proc, $Cont);\n    $R (*__exec__) (deactQ_L_29proc, $Cont);\n};\nstruct deactQ_L_29proc {\n    struct deactQ_L_29procG_class *$class;\n    deactQ_Bepa G_act;\n};\n$R deactQ_L_30C_15cont ($Cont, deactQ_main, B_NoneType);\nstruct deactQ_L_31ContG_class {\n    char *$GCINFO;\n    int $class_id;\n    $SuperG_class $superclass;\n    B_NoneType (*__init__) (deactQ_L_31Cont, $Cont, deactQ_main);\n    void (*__serialize__) (deactQ_L_31Cont, $Serial$state);\n    deactQ_L_31Cont (*__deserialize__) (deactQ_L_31Cont, $Serial$state);\n    B_bool (*__bool__) (deactQ_L_31Cont);\n    B_str (*__str__) (deactQ_L_31Cont);\n    B_str (*__repr__) (deactQ_L_31Cont);\n    $R (*__call__) (deactQ_L_31Cont, B_NoneType);\n};\nstruct deactQ_L_31Cont {\n    struct deactQ_L_31ContG_class *$class;\n    $Cont C_cont;\n    deactQ_main G_act;\n};\nstruct deactQ_L_32procG_class {\n    char *$GCINFO;\n    int $class_id;\n    $SuperG_class $superclass;\n    B_NoneType (*__init__) (deactQ_L_32proc, deactQ_main, B_Env);\n    void (*__serialize__) (deactQ_L_32proc, $Serial$state);\n    deactQ_L_32proc (*__deserialize__) (deactQ_L_32proc, $Serial$state);\n    B_bool (*__bool__) (deactQ_L_32proc);\n    B_str (*__str__) (deactQ_L_32proc);\n    B_str (*__repr__) (deactQ_L_32proc);\n    $R (*__call__) (deactQ_L_32proc, $Cont);\n    $R (*__exec__) (deactQ_L_32proc, $Cont);\n};\nstruct deactQ_L_32proc {\n    struct deactQ_L_32procG_class *$class;\n    deactQ_main G_act;\n    B_Env env;\n};\nstruct deactQ_ApaG_class {\n    char *$GCINFO;\n    int $class_id;\n    $SuperG_class $superclass;\n    $R (*__init__) (deactQ_Apa, $Cont);\n    void (*__serialize__) (deactQ_Apa, $Serial$state);\n    deactQ_Apa (*__deserialize__) (deactQ_Apa, $Serial$state);\n    B_bool (*__bool__) (deactQ_Apa);\n    B_str (*__str__) (deactQ_Apa);\n    B_str (*__repr__) (deactQ_Apa);\n    B_NoneType (*__resume__) (deactQ_Apa);\n    B_NoneType (*__cleanup__) (deactQ_Apa);\n    $R (*setupG_local) (deactQ_Apa, $Cont, $action);\n    $R (*computeG_local) (deactQ_Apa, $Cont, $action);\n    $R (*noticeG_local) (deactQ_Apa, $Cont, B_int);\n    B_Msg (*setup) (deactQ_Apa, $action);\n    B_Msg (*compute) (deactQ_Apa, $action);\n    B_Msg (*notice) (deactQ_Apa, B_int);\n};\nstruct deactQ_Apa {\n    struct deactQ_ApaG_class *$class;\n    $Actor $next;\n    B_Msg $msg;\n    B_Msg $msg_tail;\n    $Lock $msg_lock;\n    $int64 $affinity;\n    B_Msg $outgoing;\n    B_Msg $waitsfor;\n    $int64 $consume_hd;\n    $Catcher $catcher;\n    $long $globkey;\n};\nstruct deactQ_BepaG_class {\n    char *$GCINFO;\n    int $class_id;\n    $SuperG_class $superclass;\n    $R (*__init__) (deactQ_Bepa, $Cont);\n    void (*__serialize__) (deactQ_Bepa, $Serial$state);\n    deactQ_Bepa (*__deserialize__) (deactQ_Bepa, $Serial$state);\n    B_bool (*__bool__) (deactQ_Bepa);\n    B_str (*__str__) (deactQ_Bepa);\n    B_str (*__repr__) (deactQ_Bepa);\n    B_NoneType (*__resume__) (deactQ_Bepa);\n    B_NoneType (*__cleanup__) (deactQ_Bepa);\n    $R (*callbackG_local) (deactQ_Bepa, $Cont, B_int);\n    B_Msg (*callback) (deactQ_Bepa, B_int);\n};\nstruct deactQ_Bepa {\n    struct deactQ_BepaG_class *$class;\n    $Actor $next;\n    B_Msg $msg;\n    B_Msg $msg_tail;\n    $Lock $msg_lock;\n    $int64 $affinity;\n    B_Msg $outgoing;\n    B_Msg $waitsfor;\n    $int64 $consume_hd;\n    $Catcher $catcher;\n    $long $globkey;\n};\nstruct deactQ_mainG_class {\n    char *$GCINFO;\n    int $class_id;\n    $SuperG_class $superclass;\n    $R (*__init__) (deactQ_main, $Cont, B_Env);\n    void (*__serialize__) (deactQ_main, $Serial$state);\n    deactQ_main (*__deserialize__) (deactQ_main, $Serial$state);\n    B_bool (*__bool__) (deactQ_main);\n    B_str (*__str__) (deactQ_main);\n    B_str (*__repr__) (deactQ_main);\n    B_NoneType (*__resume__) (deactQ_main);\n    B_NoneType (*__cleanup__) (deactQ_main);\n    $R (*myprocG_local) (deactQ_main, $Cont, B_int);\n    B_Msg (*myproc) (deactQ_main, B_int);\n};\nstruct deactQ_main {\n    struct deactQ_mainG_class *$class;\n    $Actor $next;\n    B_Msg $msg;\n    B_Msg $msg_tail;\n    $Lock $msg_lock;\n    $int64 $affinity;\n    B_Msg $outgoing;\n    B_Msg $waitsfor;\n    $int64 $consume_hd;\n    $Catcher $catcher;\n    $long $globkey;\n    B_Env env;\n    deactQ_Apa a;\n    deactQ_Bepa b;\n    B_Msg x;\n    B_int r;\n};\n$R deactQ_ApaG_newact ($Cont);\n$R deactQ_BepaG_newact ($Cont);\n$R deactQ_mainG_newact ($Cont, B_Env);\nextern struct deactQ_L_2ContG_class deactQ_L_2ContG_methods;\ndeactQ_L_2Cont deactQ_L_2ContG_new($Cont);\nextern struct deactQ_L_4actionG_class deactQ_L_4actionG_methods;\ndeactQ_L_4action deactQ_L_4actionG_new(deactQ_Apa);\nextern struct deactQ_L_6ContG_class deactQ_L_6ContG_methods;\ndeactQ_L_6Cont deactQ_L_6ContG_new($action, $Cont);\nextern struct deactQ_L_7procG_class deactQ_L_7procG_methods;\ndeactQ_L_7proc deactQ_L_7procG_new(deactQ_Apa, $action);\nextern struct deactQ_L_8procG_class deactQ_L_8procG_methods;\ndeactQ_L_8proc deactQ_L_8procG_new(deactQ_Apa, $action);\nextern struct deactQ_L_9procG_class deactQ_L_9procG_methods;\ndeactQ_L_9proc deactQ_L_9procG_new(deactQ_Apa, B_int);\nextern struct deactQ_L_10procG_class deactQ_L_10procG_methods;\ndeactQ_L_10proc deactQ_L_10procG_new(deactQ_Bepa, B_int);\nextern struct deactQ_L_14actionG_class deactQ_L_14actionG_methods;\ndeactQ_L_14action deactQ_L_14actionG_new(deactQ_Apa);\nextern struct deactQ_L_16actionG_class deactQ_L_16actionG_methods;\ndeactQ_L_16action deactQ_L_16actionG_new(deactQ_Bepa);\nextern struct deactQ_L_19actionG_class deactQ_L_19actionG_methods;\ndeactQ_L_19action deactQ_L_19actionG_new(deactQ_main);\nextern struct deactQ_L_20ContG_class deactQ_L_20ContG_methods;\ndeactQ_L_20Cont deactQ_L_20ContG_new(deactQ_main, $Cont);\nextern struct deactQ_L_21ContG_class deactQ_L_21ContG_methods;\ndeactQ_L_21Cont deactQ_L_21ContG_new(deactQ_main, $Cont);\nextern struct deactQ_L_22ContG_class deactQ_L_22ContG_methods;\ndeactQ_L_22Cont deactQ_L_22ContG_new(deactQ_main, $Cont);\nextern struct deactQ_L_23procG_class deactQ_L_23procG_methods;\ndeactQ_L_23proc deactQ_L_23procG_new(deactQ_main, B_int);\nextern struct deactQ_L_25ContG_class deactQ_L_25ContG_methods;\ndeactQ_L_25Cont deactQ_L_25ContG_new($Cont, deactQ_Apa);\nextern struct deactQ_L_26procG_class deactQ_L_26procG_methods;\ndeactQ_L_26proc deactQ_L_26procG_new(deactQ_Apa);\nextern struct deactQ_L_28ContG_class deactQ_L_28ContG_methods;\ndeactQ_L_28Cont deactQ_L_28ContG_new($Cont, deactQ_Bepa);\nextern struct deactQ_L_29procG_class deactQ_L_29procG_methods;\ndeactQ_L_29proc deactQ_L_29procG_new(deactQ_Bepa);\nextern struct deactQ_L_31ContG_class deactQ_L_31ContG_methods;\ndeactQ_L_31Cont deactQ_L_31ContG_new($Cont, deactQ_main);\nextern struct deactQ_L_32procG_class deactQ_L_32procG_methods;\ndeactQ_L_32proc deactQ_L_32procG_new(deactQ_main, B_Env);\nextern struct deactQ_ApaG_class deactQ_ApaG_methods;\n$R deactQ_ApaG_new($Cont);\nextern struct deactQ_BepaG_class deactQ_BepaG_methods;\n$R deactQ_BepaG_new($Cont);\nextern struct deactQ_mainG_class deactQ_mainG_methods;\n$R deactQ_mainG_new($Cont, B_Env);\nvoid deactQ___init__ ();"
  },
  {
    "path": "compiler/lib/test/9-codegen/deact.input",
    "content": "# recursive group:\nproc def L_1C_1cont (C_cont : $Cont[None], C_2res : None) -> $R:\n    print@[(__builtin__.str,)]((\"\\\"Apa\\\"\",), None, None, None, None)\n    return $R_CONT@[None](C_cont, None)\nclass L_2Cont ($Cont[None], __builtin__.value):\n    @property\n    C_cont : $Cont[None]\n    pure def __init__ (L_self : L_2Cont, C_cont : $Cont[None]) -> None:\n        L_self.C_cont = C_cont\n        return None\n    proc def __call__ (L_self : L_2Cont, G_1 : None) -> $R:\n        C_cont: $Cont[None] = L_self.C_cont\n        return L_1C_1cont(C_cont, G_1)\nclass L_4action ($action[(__builtin__.int,), __builtin__.int], $proc[(__builtin__.int,), __builtin__.int], __builtin__.value):\n    @property\n    L_3obj : Apa\n    pure def __init__ (L_self : L_4action, L_3obj : Apa) -> None:\n        L_self.L_3obj = L_3obj\n        return None\n    # recursive group:\n    proc def __call__ (L_self : L_4action, L_cont : $Cont[__builtin__.int], G_1 : __builtin__.int) -> $R:\n        return $AWAIT@[__builtin__.int](L_cont, L_self.__asyn__(G_1))\n    proc def __exec__ (L_self : L_4action, L_cont : $Cont[__builtin__.value], G_1 : __builtin__.int) -> $R:\n        return $R_CONT@[__builtin__.value](L_cont, L_self.__asyn__(G_1))\n    action def __asyn__ (L_self : L_4action, G_1 : __builtin__.int) -> __builtin__.int:\n        L_3obj: Apa = L_self.L_3obj\n        return L_3obj.notice(G_1)\n    # (recursive group)\nproc def U_L_5C_3cont (cb : $action[(__builtin__.int,), __builtin__.int], C_cont : $Cont[__builtin__.int], U_2C_4res : __builtin__.int) -> $R:\n    U_3v: __builtin__.int = U_2C_4res\n    m: __builtin__.Msg[__builtin__.int] = cb.__asyn__((BOX __builtin__.int (UNBOX __builtin__.int 2)))\n    U_4N_tmp: __builtin__.int = (U_3v * (UNBOX __builtin__.int 10))\n    return $R_CONT@[__builtin__.int](C_cont, (BOX __builtin__.int U_4N_tmp))\nproc def L_5C_3cont (cb : $action[(__builtin__.int,), __builtin__.int], C_cont : $Cont[__builtin__.int], C_4res : __builtin__.int) -> $R:\n    return U_L_5C_3cont(cb, C_cont, (UNBOX __builtin__.int C_4res))\nclass L_6Cont ($Cont[__builtin__.int], __builtin__.value):\n    @property\n    cb : $action[(__builtin__.int,), __builtin__.int]\n    @property\n    C_cont : $Cont[__builtin__.int]\n    pure def __init__ (L_self : L_6Cont, cb : $action[(__builtin__.int,), __builtin__.int], C_cont : $Cont[__builtin__.int]) -> None:\n        L_self.cb = cb\n        L_self.C_cont = C_cont\n        return None\n    proc def __call__ (L_self : L_6Cont, G_1 : __builtin__.int) -> $R:\n        cb: $action[(__builtin__.int,), __builtin__.int] = L_self.cb\n        C_cont: $Cont[__builtin__.int] = L_self.C_cont\n        return L_5C_3cont(cb, C_cont, G_1)\nclass L_7proc ($proc[(), None], __builtin__.value):\n    @property\n    self : Apa\n    @property\n    cb : $action[(__builtin__.int,), __builtin__.int]\n    pure def __init__ (L_self : L_7proc, self : Apa, cb : $action[(__builtin__.int,), __builtin__.int]) -> None:\n        L_self.self = self\n        L_self.cb = cb\n        return None\n    # recursive group:\n    proc def __call__ (L_self : L_7proc, C_cont : $Cont[None]) -> $R:\n        self: Apa = L_self.self\n        cb: $action[(__builtin__.int,), __builtin__.int] = L_self.cb\n        return self.setupG_local(C_cont, cb)\n    proc def __exec__ (L_self : L_7proc, C_cont : $Cont[None]) -> $R:\n        return L_self.__call__(C_cont)\n    # (recursive group)\nclass L_8proc ($proc[(), __builtin__.int], __builtin__.value):\n    @property\n    self : Apa\n    @property\n    cb : $action[(__builtin__.int,), __builtin__.int]\n    pure def __init__ (L_self : L_8proc, self : Apa, cb : $action[(__builtin__.int,), __builtin__.int]) -> None:\n        L_self.self = self\n        L_self.cb = cb\n        return None\n    # recursive group:\n    proc def __call__ (L_self : L_8proc, C_cont : $Cont[__builtin__.int]) -> $R:\n        self: Apa = L_self.self\n        cb: $action[(__builtin__.int,), __builtin__.int] = L_self.cb\n        return self.computeG_local(C_cont, cb)\n    proc def __exec__ (L_self : L_8proc, C_cont : $Cont[__builtin__.int]) -> $R:\n        return L_self.__call__(C_cont)\n    # (recursive group)\nclass L_9proc ($proc[(), __builtin__.int], __builtin__.value):\n    @property\n    self : Apa\n    @property\n    i : __builtin__.int\n    pure def __init__ (L_self : L_9proc, self : Apa, i : __builtin__.int) -> None:\n        L_self.self = self\n        L_self.i = i\n        return None\n    # recursive group:\n    proc def __call__ (L_self : L_9proc, C_cont : $Cont[__builtin__.int]) -> $R:\n        self: Apa = L_self.self\n        U_5i: __builtin__.int = (UNBOX __builtin__.int L_self.i)\n        return self.noticeG_local(C_cont, (BOX __builtin__.int U_5i))\n    proc def __exec__ (L_self : L_9proc, C_cont : $Cont[__builtin__.int]) -> $R:\n        return L_self.__call__(C_cont)\n    # (recursive group)\nclass L_10proc ($proc[(), __builtin__.int], __builtin__.value):\n    @property\n    self : Bepa\n    @property\n    i : __builtin__.int\n    pure def __init__ (L_self : L_10proc, self : Bepa, i : __builtin__.int) -> None:\n        L_self.self = self\n        L_self.i = i\n        return None\n    # recursive group:\n    proc def __call__ (L_self : L_10proc, C_cont : $Cont[__builtin__.int]) -> $R:\n        self: Bepa = L_self.self\n        U_6i: __builtin__.int = (UNBOX __builtin__.int L_self.i)\n        return self.callbackG_local(C_cont, (BOX __builtin__.int U_6i))\n    proc def __exec__ (L_self : L_10proc, C_cont : $Cont[__builtin__.int]) -> $R:\n        return L_self.__call__(C_cont)\n    # (recursive group)\nclass L_14action ($action[(__builtin__.int,), __builtin__.int], $proc[(__builtin__.int,), __builtin__.int], __builtin__.value):\n    @property\n    L_13obj : Apa\n    pure def __init__ (L_self : L_14action, L_13obj : Apa) -> None:\n        L_self.L_13obj = L_13obj\n        return None\n    # recursive group:\n    proc def __call__ (L_self : L_14action, L_cont : $Cont[__builtin__.int], G_1 : __builtin__.int) -> $R:\n        return $AWAIT@[__builtin__.int](L_cont, L_self.__asyn__(G_1))\n    proc def __exec__ (L_self : L_14action, L_cont : $Cont[__builtin__.value], G_1 : __builtin__.int) -> $R:\n        return $R_CONT@[__builtin__.value](L_cont, L_self.__asyn__(G_1))\n    action def __asyn__ (L_self : L_14action, G_1 : __builtin__.int) -> __builtin__.int:\n        L_13obj: Apa = L_self.L_13obj\n        return L_13obj.notice(G_1)\n    # (recursive group)\nclass L_16action ($action[(__builtin__.int,), __builtin__.int], $proc[(__builtin__.int,), __builtin__.int], __builtin__.value):\n    @property\n    L_15obj : Bepa\n    pure def __init__ (L_self : L_16action, L_15obj : Bepa) -> None:\n        L_self.L_15obj = L_15obj\n        return None\n    # recursive group:\n    proc def __call__ (L_self : L_16action, L_cont : $Cont[__builtin__.int], G_1 : __builtin__.int) -> $R:\n        return $AWAIT@[__builtin__.int](L_cont, L_self.__asyn__(G_1))\n    proc def __exec__ (L_self : L_16action, L_cont : $Cont[__builtin__.value], G_1 : __builtin__.int) -> $R:\n        return $R_CONT@[__builtin__.value](L_cont, L_self.__asyn__(G_1))\n    action def __asyn__ (L_self : L_16action, G_1 : __builtin__.int) -> __builtin__.int:\n        L_15obj: Bepa = L_self.L_15obj\n        return L_15obj.callback(G_1)\n    # (recursive group)\nclass L_19action ($action[(__builtin__.int,), __builtin__.int], $proc[(__builtin__.int,), __builtin__.int], __builtin__.value):\n    @property\n    L_18obj : main\n    pure def __init__ (L_self : L_19action, L_18obj : main) -> None:\n        L_self.L_18obj = L_18obj\n        return None\n    # recursive group:\n    proc def __call__ (L_self : L_19action, L_cont : $Cont[__builtin__.int], G_1 : __builtin__.int) -> $R:\n        return $AWAIT@[__builtin__.int](L_cont, L_self.__asyn__(G_1))\n    proc def __exec__ (L_self : L_19action, L_cont : $Cont[__builtin__.value], G_1 : __builtin__.int) -> $R:\n        return $R_CONT@[__builtin__.value](L_cont, L_self.__asyn__(G_1))\n    action def __asyn__ (L_self : L_19action, G_1 : __builtin__.int) -> __builtin__.int:\n        L_18obj: main = L_self.L_18obj\n        return L_18obj.myproc(G_1)\n    # (recursive group)\nproc def U_1L_17C_9cont (self : main, C_cont : $Cont[None], U_7C_10res : __builtin__.int) -> $R:\n    self.r = (BOX __builtin__.int U_7C_10res)\n    print@[(__builtin__.str, __builtin__.int)]((\"\\\"r =\\\"\", self.r), None, None, None, None)\n    (async self.a.compute)(L_19action(self))\n    print@[(__builtin__.str,)]((\"\\\"main\\\"\",), None, None, None, None)\n    return $R_CONT@[None](C_cont, None)\nproc def L_17C_9cont (self : main, C_cont : $Cont[None], C_10res : __builtin__.int) -> $R:\n    return U_1L_17C_9cont(self, C_cont, (UNBOX __builtin__.int C_10res))\nclass L_20Cont ($Cont[__builtin__.int], __builtin__.value):\n    @property\n    self : main\n    @property\n    C_cont : $Cont[None]\n    pure def __init__ (L_self : L_20Cont, self : main, C_cont : $Cont[None]) -> None:\n        L_self.self = self\n        L_self.C_cont = C_cont\n        return None\n    proc def __call__ (L_self : L_20Cont, G_1 : __builtin__.int) -> $R:\n        self: main = L_self.self\n        C_cont: $Cont[None] = L_self.C_cont\n        return L_17C_9cont(self, C_cont, G_1)\nproc def L_12C_7cont (self : main, C_cont : $Cont[None], C_8res : Bepa) -> $R:\n    self.b = C_8res\n    print@[(__builtin__.str,)]((\"\\\"-----\\\"\",), None, None, None, None)\n    (async self.a.setup)(L_14action(self.a))\n    self.x = (async self.a.compute)(L_16action(self.b))\n    return $AWAIT@[__builtin__.int](L_20Cont(self, C_cont), self.x)\nclass L_21Cont ($Cont[Bepa], __builtin__.value):\n    @property\n    self : main\n    @property\n    C_cont : $Cont[None]\n    pure def __init__ (L_self : L_21Cont, self : main, C_cont : $Cont[None]) -> None:\n        L_self.self = self\n        L_self.C_cont = C_cont\n        return None\n    proc def __call__ (L_self : L_21Cont, G_1 : Bepa) -> $R:\n        self: main = L_self.self\n        C_cont: $Cont[None] = L_self.C_cont\n        return L_12C_7cont(self, C_cont, G_1)\nproc def L_11C_5cont (self : main, C_cont : $Cont[None], C_6res : Apa) -> $R:\n    self.a = C_6res\n    return BepaG_newact(L_21Cont(self, C_cont))\nclass L_22Cont ($Cont[Apa], __builtin__.value):\n    @property\n    self : main\n    @property\n    C_cont : $Cont[None]\n    pure def __init__ (L_self : L_22Cont, self : main, C_cont : $Cont[None]) -> None:\n        L_self.self = self\n        L_self.C_cont = C_cont\n        return None\n    proc def __call__ (L_self : L_22Cont, G_1 : Apa) -> $R:\n        self: main = L_self.self\n        C_cont: $Cont[None] = L_self.C_cont\n        return L_11C_5cont(self, C_cont, G_1)\nclass L_23proc ($proc[(), __builtin__.int], __builtin__.value):\n    @property\n    self : main\n    @property\n    i : __builtin__.int\n    pure def __init__ (L_self : L_23proc, self : main, i : __builtin__.int) -> None:\n        L_self.self = self\n        L_self.i = i\n        return None\n    # recursive group:\n    proc def __call__ (L_self : L_23proc, C_cont : $Cont[__builtin__.int]) -> $R:\n        self: main = L_self.self\n        U_8i: __builtin__.int = (UNBOX __builtin__.int L_self.i)\n        return self.myprocG_local(C_cont, (BOX __builtin__.int U_8i))\n    proc def __exec__ (L_self : L_23proc, C_cont : $Cont[__builtin__.int]) -> $R:\n        return L_self.__call__(C_cont)\n    # (recursive group)\nproc def L_24C_11cont (C_cont : $Cont[Apa], G_act : Apa, C_12res : None) -> $R:\n    return $R_CONT@[Apa](C_cont, G_act)\nclass L_25Cont ($Cont[None], __builtin__.value):\n    @property\n    C_cont : $Cont[Apa]\n    @property\n    G_act : Apa\n    pure def __init__ (L_self : L_25Cont, C_cont : $Cont[Apa], G_act : Apa) -> None:\n        L_self.C_cont = C_cont\n        L_self.G_act = G_act\n        return None\n    proc def __call__ (L_self : L_25Cont, G_1 : None) -> $R:\n        C_cont: $Cont[Apa] = L_self.C_cont\n        G_act: Apa = L_self.G_act\n        return L_24C_11cont(C_cont, G_act, G_1)\nclass L_26proc ($proc[(), None], __builtin__.value):\n    @property\n    G_act : Apa\n    pure def __init__ (L_self : L_26proc, G_act : Apa) -> None:\n        L_self.G_act = G_act\n        return None\n    # recursive group:\n    proc def __call__ (L_self : L_26proc, C_cont : $Cont[None]) -> $R:\n        G_act: Apa = L_self.G_act\n        return G_act.__init__(C_cont)\n    proc def __exec__ (L_self : L_26proc, C_cont : $Cont[None]) -> $R:\n        return L_self.__call__(C_cont)\n    # (recursive group)\nproc def L_27C_13cont (C_cont : $Cont[Bepa], G_act : Bepa, C_14res : None) -> $R:\n    return $R_CONT@[Bepa](C_cont, G_act)\nclass L_28Cont ($Cont[None], __builtin__.value):\n    @property\n    C_cont : $Cont[Bepa]\n    @property\n    G_act : Bepa\n    pure def __init__ (L_self : L_28Cont, C_cont : $Cont[Bepa], G_act : Bepa) -> None:\n        L_self.C_cont = C_cont\n        L_self.G_act = G_act\n        return None\n    proc def __call__ (L_self : L_28Cont, G_1 : None) -> $R:\n        C_cont: $Cont[Bepa] = L_self.C_cont\n        G_act: Bepa = L_self.G_act\n        return L_27C_13cont(C_cont, G_act, G_1)\nclass L_29proc ($proc[(), None], __builtin__.value):\n    @property\n    G_act : Bepa\n    pure def __init__ (L_self : L_29proc, G_act : Bepa) -> None:\n        L_self.G_act = G_act\n        return None\n    # recursive group:\n    proc def __call__ (L_self : L_29proc, C_cont : $Cont[None]) -> $R:\n        G_act: Bepa = L_self.G_act\n        return G_act.__init__(C_cont)\n    proc def __exec__ (L_self : L_29proc, C_cont : $Cont[None]) -> $R:\n        return L_self.__call__(C_cont)\n    # (recursive group)\nproc def L_30C_15cont (C_cont : $Cont[main], G_act : main, C_16res : None) -> $R:\n    return $R_CONT@[main](C_cont, G_act)\nclass L_31Cont ($Cont[None], __builtin__.value):\n    @property\n    C_cont : $Cont[main]\n    @property\n    G_act : main\n    pure def __init__ (L_self : L_31Cont, C_cont : $Cont[main], G_act : main) -> None:\n        L_self.C_cont = C_cont\n        L_self.G_act = G_act\n        return None\n    proc def __call__ (L_self : L_31Cont, G_1 : None) -> $R:\n        C_cont: $Cont[main] = L_self.C_cont\n        G_act: main = L_self.G_act\n        return L_30C_15cont(C_cont, G_act, G_1)\nclass L_32proc ($proc[(), None], __builtin__.value):\n    @property\n    G_act : main\n    @property\n    env : __builtin__.Env\n    pure def __init__ (L_self : L_32proc, G_act : main, env : __builtin__.Env) -> None:\n        L_self.G_act = G_act\n        L_self.env = env\n        return None\n    # recursive group:\n    proc def __call__ (L_self : L_32proc, C_cont : $Cont[None]) -> $R:\n        G_act: main = L_self.G_act\n        env: __builtin__.Env = L_self.env\n        return G_act.__init__(C_cont, env)\n    proc def __exec__ (L_self : L_32proc, C_cont : $Cont[None]) -> $R:\n        return L_self.__call__(C_cont)\n    # (recursive group)\nclass Apa ($Actor, __builtin__.value):\n    proc def __init__ (self : Apa, C_cont : $Cont[None]) -> $R:\n        return self.setupG_local(L_2Cont(C_cont), L_4action(self))\n    proc def setupG_local (self : Apa, C_cont : $Cont[None], cb : $action[(__builtin__.int,), __builtin__.int]) -> $R:\n        print@[(__builtin__.str,)]((\"\\\"setup\\\"\",), None, None, None, None)\n        cb.__asyn__((BOX __builtin__.int (UNBOX __builtin__.int 0)))\n        return $R_CONT@[None](C_cont, None)\n    proc def computeG_local (self : Apa, C_cont : $Cont[__builtin__.int], cb : $action[(__builtin__.int,), __builtin__.int]) -> $R:\n        print@[(__builtin__.str,)]((\"\\\"compute\\\"\",), None, None, None, None)\n        return $AWAIT@[__builtin__.int](L_6Cont(cb, C_cont), cb.__asyn__((BOX __builtin__.int (UNBOX __builtin__.int 1))))\n    proc def noticeG_local (self : Apa, C_cont : $Cont[__builtin__.int], i : __builtin__.int) -> $R:\n        print@[(__builtin__.str,)]((\"\\\"notice\\\"\",), None, None, None, None)\n        U_9N_1tmp: __builtin__.int = ((UNBOX __builtin__.int i) + (UNBOX __builtin__.int 1))\n        return $R_CONT@[__builtin__.int](C_cont, (BOX __builtin__.int U_9N_1tmp))\n    action def setup (self : Apa, cb : $action[(__builtin__.int,), __builtin__.int]) -> None:\n        return $ASYNC@[None](self, L_7proc(self, cb))\n    action def compute (self : Apa, cb : $action[(__builtin__.int,), __builtin__.int]) -> __builtin__.int:\n        return $ASYNC@[__builtin__.int](self, L_8proc(self, cb))\n    action def notice (self : Apa, i : __builtin__.int) -> __builtin__.int:\n        return $ASYNC@[__builtin__.int](self, L_9proc(self, i))\nclass Bepa ($Actor, __builtin__.value):\n    proc def __init__ (self : Bepa, C_cont : $Cont[None]) -> $R:\n        print@[(__builtin__.str,)]((\"\\\"Bepa\\\"\",), None, None, None, None)\n        return $R_CONT@[None](C_cont, None)\n    proc def callbackG_local (self : Bepa, C_cont : $Cont[__builtin__.int], i : __builtin__.int) -> $R:\n        print@[(__builtin__.str, __builtin__.int)]((\"\\\"callback\\\"\", i), None, None, None, None)\n        U_10N_2tmp: __builtin__.int = ((UNBOX __builtin__.int i) + (UNBOX __builtin__.int 1))\n        return $R_CONT@[__builtin__.int](C_cont, (BOX __builtin__.int U_10N_2tmp))\n    action def callback (self : Bepa, i : __builtin__.int) -> __builtin__.int:\n        return $ASYNC@[__builtin__.int](self, L_10proc(self, i))\nclass main ($Actor, __builtin__.value):\n    @property\n    env : __builtin__.Env\n    @property\n    a : Apa\n    @property\n    b : Bepa\n    @property\n    x : __builtin__.Msg[__builtin__.int]\n    @property\n    r : __builtin__.int\n    proc def __init__ (self : main, C_cont : $Cont[None], env : __builtin__.Env) -> $R:\n        self.env = env\n        return ApaG_newact(L_22Cont(self, C_cont))\n    proc def myprocG_local (self : main, C_cont : $Cont[__builtin__.int], i : __builtin__.int) -> $R:\n        print@[(__builtin__.str, __builtin__.int)]((\"\\\"myproc\\\"\", i), None, None, None, None)\n        if (BOX __builtin__.bool ((UNBOX __builtin__.int i) == (UNBOX __builtin__.int 2))):\n            (async self.env.exit)((BOX __builtin__.int (UNBOX __builtin__.int 0)))\n        return $R_CONT@[__builtin__.int](C_cont, i)\n    action def myproc (self : main, i : __builtin__.int) -> __builtin__.int:\n        return $ASYNC@[__builtin__.int](self, L_23proc(self, i))\nproc def ApaG_newact (C_cont : $Cont[Apa]) -> $R:\n    G_act: Apa = $NEWACTOR@[Apa]()\n    $InstallFinalizer@[Apa](G_act)\n    return $AWAIT@[None](L_25Cont(C_cont, G_act), $ASYNC@[None](G_act, L_26proc(G_act)))\nproc def BepaG_newact (C_cont : $Cont[Bepa]) -> $R:\n    G_act: Bepa = $NEWACTOR@[Bepa]()\n    $InstallFinalizer@[Bepa](G_act)\n    return $AWAIT@[None](L_28Cont(C_cont, G_act), $ASYNC@[None](G_act, L_29proc(G_act)))\nproc def mainG_newact (C_cont : $Cont[main], env : __builtin__.Env) -> $R:\n    G_act: main = $NEWACTOR@[main]()\n    $InstallFinalizer@[main](G_act)\n    return $AWAIT@[None](L_31Cont(C_cont, G_act), $ASYNC@[None](G_act, L_32proc(G_act, env)))\n# (recursive group)"
  },
  {
    "path": "compiler/lib/test/9-codegen/ints.c",
    "content": "/* Acton impl hash: test-hash */\n#include \"rts/common.h\"\n#include \"out/types/ints.h\"\nint64_t intsQ_U_int64_min;\nB_int intsQ_int64_min;\nint64_t intsQ_U_1int64_max;\nB_int intsQ_int64_max;\nint32_t intsQ_U_2int32_min;\nB_i32 intsQ_int32_min;\nint32_t intsQ_U_3int32_max;\nB_i32 intsQ_int32_max;\nint16_t intsQ_U_4int16_min;\nB_i16 intsQ_int16_min;\nint16_t intsQ_U_5int16_max;\nB_i16 intsQ_int16_max;\nB_Number intsQ_W_int8_min_2;\nB_i8 intsQ_int8_min;\nB_Number intsQ_W_int8_max_2;\nB_i8 intsQ_int8_max;\nuint64_t intsQ_U_6uint64_min;\nB_u64 intsQ_uint64_min;\nuint64_t intsQ_U_7uint64_max;\nB_u64 intsQ_uint64_max;\nuint32_t intsQ_U_8uint32_min;\nB_u32 intsQ_uint32_min;\nuint32_t intsQ_U_9uint32_max;\nB_u32 intsQ_uint32_max;\nuint16_t intsQ_U_10uint16_min;\nB_u16 intsQ_uint16_min;\nuint16_t intsQ_U_11uint16_max;\nB_u16 intsQ_uint16_max;\nB_Number intsQ_W_uint8_min_2;\nB_u8 intsQ_uint8_min;\nB_Number intsQ_W_uint8_max_2;\nB_u8 intsQ_uint8_max;\nB_bigint intsQ_bigint_small;\nB_bigint intsQ_bigint_neg_small;\nB_bigint intsQ_bigint_i64_max;\nB_bigint intsQ_bigint_i64_min;\nB_bigint intsQ_bigint_i64_underflow;\nB_bigint intsQ_bigint_u64_edge;\nB_bigint intsQ_bigint_u64_edge_minus1;\nB_bigint intsQ_bigint_u64_overflow;\nB_bigint intsQ_xint_i64_min_minus1;\nint intsQ_done$ = 0;\nvoid intsQ___init__ () {\n    if (intsQ_done$) return;\n    intsQ_done$ = 1;\n    int64_t U_int64_min = -9223372036854775808LL;\n    intsQ_U_int64_min = U_int64_min;\n    B_int int64_min = toB_int(intsQ_U_int64_min);\n    intsQ_int64_min = int64_min;\n    int64_t U_1int64_max = 9223372036854775807LL;\n    intsQ_U_1int64_max = U_1int64_max;\n    B_int int64_max = toB_int(intsQ_U_1int64_max);\n    intsQ_int64_max = int64_max;\n    int32_t U_2int32_min = -2147483648;\n    intsQ_U_2int32_min = U_2int32_min;\n    B_i32 int32_min = toB_i32(intsQ_U_2int32_min);\n    intsQ_int32_min = int32_min;\n    int32_t U_3int32_max = 2147483647;\n    intsQ_U_3int32_max = U_3int32_max;\n    B_i32 int32_max = toB_i32(intsQ_U_3int32_max);\n    intsQ_int32_max = int32_max;\n    int16_t U_4int16_min = -32768;\n    intsQ_U_4int16_min = U_4int16_min;\n    B_i16 int16_min = toB_i16(intsQ_U_4int16_min);\n    intsQ_int16_min = int16_min;\n    int16_t U_5int16_max = 32767;\n    intsQ_U_5int16_max = U_5int16_max;\n    B_i16 int16_max = toB_i16(intsQ_U_5int16_max);\n    intsQ_int16_max = int16_max;\n    B_Number W_int8_min_2 = (B_Number)B_IntegralD_i8G_witness;\n    intsQ_W_int8_min_2 = W_int8_min_2;\n    B_i8 int8_min = ((B_i8 (*) (B_Number, B_atom))intsQ_W_int8_min_2->$class->__fromatom__)(intsQ_W_int8_min_2, ((B_atom)toB_bigint2(\"-128\")));\n    intsQ_int8_min = int8_min;\n    B_Number W_int8_max_2 = (B_Number)B_IntegralD_i8G_witness;\n    intsQ_W_int8_max_2 = W_int8_max_2;\n    B_i8 int8_max = ((B_i8 (*) (B_Number, B_atom))intsQ_W_int8_max_2->$class->__fromatom__)(intsQ_W_int8_max_2, ((B_atom)toB_bigint(127UL)));\n    intsQ_int8_max = int8_max;\n    uint64_t U_6uint64_min = 0UL;\n    intsQ_U_6uint64_min = U_6uint64_min;\n    B_u64 uint64_min = toB_u64(intsQ_U_6uint64_min);\n    intsQ_uint64_min = uint64_min;\n    uint64_t U_7uint64_max = 18446744073709551615UL;\n    intsQ_U_7uint64_max = U_7uint64_max;\n    B_u64 uint64_max = toB_u64(intsQ_U_7uint64_max);\n    intsQ_uint64_max = uint64_max;\n    uint32_t U_8uint32_min = 0;\n    intsQ_U_8uint32_min = U_8uint32_min;\n    B_u32 uint32_min = toB_u32(intsQ_U_8uint32_min);\n    intsQ_uint32_min = uint32_min;\n    uint32_t U_9uint32_max = 4294967295;\n    intsQ_U_9uint32_max = U_9uint32_max;\n    B_u32 uint32_max = toB_u32(intsQ_U_9uint32_max);\n    intsQ_uint32_max = uint32_max;\n    uint16_t U_10uint16_min = 0;\n    intsQ_U_10uint16_min = U_10uint16_min;\n    B_u16 uint16_min = toB_u16(intsQ_U_10uint16_min);\n    intsQ_uint16_min = uint16_min;\n    uint16_t U_11uint16_max = 65535;\n    intsQ_U_11uint16_max = U_11uint16_max;\n    B_u16 uint16_max = toB_u16(intsQ_U_11uint16_max);\n    intsQ_uint16_max = uint16_max;\n    B_Number W_uint8_min_2 = (B_Number)B_IntegralD_u8G_witness;\n    intsQ_W_uint8_min_2 = W_uint8_min_2;\n    B_u8 uint8_min = ((B_u8 (*) (B_Number, B_atom))intsQ_W_uint8_min_2->$class->__fromatom__)(intsQ_W_uint8_min_2, ((B_atom)toB_bigint(0UL)));\n    intsQ_uint8_min = uint8_min;\n    B_Number W_uint8_max_2 = (B_Number)B_IntegralD_u8G_witness;\n    intsQ_W_uint8_max_2 = W_uint8_max_2;\n    B_u8 uint8_max = ((B_u8 (*) (B_Number, B_atom))intsQ_W_uint8_max_2->$class->__fromatom__)(intsQ_W_uint8_max_2, ((B_atom)toB_bigint(255UL)));\n    intsQ_uint8_max = uint8_max;\n    B_bigint bigint_small = ((B_bigint)toB_bigint(42UL));\n    intsQ_bigint_small = bigint_small;\n    B_bigint bigint_neg_small = ((B_bigint)toB_bigint2(\"-1\"));\n    intsQ_bigint_neg_small = bigint_neg_small;\n    B_bigint bigint_i64_max = ((B_bigint)toB_bigint(9223372036854775807UL));\n    intsQ_bigint_i64_max = bigint_i64_max;\n    B_bigint bigint_i64_min = ((B_bigint)toB_bigint2(\"-9223372036854775808\"));\n    intsQ_bigint_i64_min = bigint_i64_min;\n    B_bigint bigint_i64_underflow = ((B_bigint)toB_bigint2(\"-9223372036854775809\"));\n    intsQ_bigint_i64_underflow = bigint_i64_underflow;\n    B_bigint bigint_u64_edge = B_bigintG_new(((B_atom)toB_u64(18446744073709551615UL)), B_None);\n    intsQ_bigint_u64_edge = bigint_u64_edge;\n    B_bigint bigint_u64_edge_minus1 = B_bigintG_new(((B_atom)toB_u64(18446744073709551614UL)), B_None);\n    intsQ_bigint_u64_edge_minus1 = bigint_u64_edge_minus1;\n    B_bigint bigint_u64_overflow = ((B_bigint)toB_bigint2(\"18446744073709551616\"));\n    intsQ_bigint_u64_overflow = bigint_u64_overflow;\n    B_bigint xint_i64_min_minus1 = ((B_bigint)toB_bigint2(\"-9223372036854775809\"));\n    intsQ_xint_i64_min_minus1 = xint_i64_min_minus1;\n}"
  },
  {
    "path": "compiler/lib/test/9-codegen/ints.h",
    "content": "/* Acton impl hash: test-hash */\n#pragma once\n#include \"builtin/builtin.h\"\n#include \"rts/rts.h\"\nextern int64_t intsQ_U_int64_min;\nextern B_int intsQ_int64_min;\nextern int64_t intsQ_U_1int64_max;\nextern B_int intsQ_int64_max;\nextern int32_t intsQ_U_2int32_min;\nextern B_i32 intsQ_int32_min;\nextern int32_t intsQ_U_3int32_max;\nextern B_i32 intsQ_int32_max;\nextern int16_t intsQ_U_4int16_min;\nextern B_i16 intsQ_int16_min;\nextern int16_t intsQ_U_5int16_max;\nextern B_i16 intsQ_int16_max;\nextern B_Number intsQ_W_int8_min_2;\nextern B_i8 intsQ_int8_min;\nextern B_Number intsQ_W_int8_max_2;\nextern B_i8 intsQ_int8_max;\nextern uint64_t intsQ_U_6uint64_min;\nextern B_u64 intsQ_uint64_min;\nextern uint64_t intsQ_U_7uint64_max;\nextern B_u64 intsQ_uint64_max;\nextern uint32_t intsQ_U_8uint32_min;\nextern B_u32 intsQ_uint32_min;\nextern uint32_t intsQ_U_9uint32_max;\nextern B_u32 intsQ_uint32_max;\nextern uint16_t intsQ_U_10uint16_min;\nextern B_u16 intsQ_uint16_min;\nextern uint16_t intsQ_U_11uint16_max;\nextern B_u16 intsQ_uint16_max;\nextern B_Number intsQ_W_uint8_min_2;\nextern B_u8 intsQ_uint8_min;\nextern B_Number intsQ_W_uint8_max_2;\nextern B_u8 intsQ_uint8_max;\nextern B_bigint intsQ_bigint_small;\nextern B_bigint intsQ_bigint_neg_small;\nextern B_bigint intsQ_bigint_i64_max;\nextern B_bigint intsQ_bigint_i64_min;\nextern B_bigint intsQ_bigint_i64_underflow;\nextern B_bigint intsQ_bigint_u64_edge;\nextern B_bigint intsQ_bigint_u64_edge_minus1;\nextern B_bigint intsQ_bigint_u64_overflow;\nextern B_bigint intsQ_xint_i64_min_minus1;\nvoid intsQ___init__ ();"
  },
  {
    "path": "compiler/lib/test/9-codegen/ints.input",
    "content": "U_int64_min: __builtin__.int = (UNBOX __builtin__.int -9223372036854775808)\n\nint64_min: __builtin__.int = (BOX __builtin__.int U_int64_min)\n\nU_1int64_max: __builtin__.int = (UNBOX __builtin__.int 9223372036854775807)\n\nint64_max: __builtin__.int = (BOX __builtin__.int U_1int64_max)\n\nU_2int32_min: __builtin__.i32 = (UNBOX __builtin__.i32 -2147483648)\n\nint32_min: __builtin__.i32 = (BOX __builtin__.i32 U_2int32_min)\n\nU_3int32_max: __builtin__.i32 = (UNBOX __builtin__.i32 2147483647)\n\nint32_max: __builtin__.i32 = (BOX __builtin__.i32 U_3int32_max)\n\nU_4int16_min: __builtin__.i16 = (UNBOX __builtin__.i16 -32768)\n\nint16_min: __builtin__.i16 = (BOX __builtin__.i16 U_4int16_min)\n\nU_5int16_max: __builtin__.i16 = (UNBOX __builtin__.i16 32767)\n\nint16_max: __builtin__.i16 = (BOX __builtin__.i16 U_5int16_max)\n\nW_int8_min_2: __builtin__.Number[__builtin__.i8] = __builtin__.IntegralD_i8()\n\nint8_min: __builtin__.i8 = W_int8_min_2.__fromatom__(-128)\n\nW_int8_max_2: __builtin__.Number[__builtin__.i8] = __builtin__.IntegralD_i8()\n\nint8_max: __builtin__.i8 = W_int8_max_2.__fromatom__(127)\n\nU_6uint64_min: __builtin__.u64 = (UNBOX __builtin__.u64 0)\n\nuint64_min: __builtin__.u64 = (BOX __builtin__.u64 U_6uint64_min)\n\nU_7uint64_max: __builtin__.u64 = (UNBOX __builtin__.u64 18446744073709551615)\n\nuint64_max: __builtin__.u64 = (BOX __builtin__.u64 U_7uint64_max)\n\nU_8uint32_min: __builtin__.u32 = (UNBOX __builtin__.u32 0)\n\nuint32_min: __builtin__.u32 = (BOX __builtin__.u32 U_8uint32_min)\n\nU_9uint32_max: __builtin__.u32 = (UNBOX __builtin__.u32 4294967295)\n\nuint32_max: __builtin__.u32 = (BOX __builtin__.u32 U_9uint32_max)\n\nU_10uint16_min: __builtin__.u16 = (UNBOX __builtin__.u16 0)\n\nuint16_min: __builtin__.u16 = (BOX __builtin__.u16 U_10uint16_min)\n\nU_11uint16_max: __builtin__.u16 = (UNBOX __builtin__.u16 65535)\n\nuint16_max: __builtin__.u16 = (BOX __builtin__.u16 U_11uint16_max)\n\nW_uint8_min_2: __builtin__.Number[__builtin__.u8] = __builtin__.IntegralD_u8()\n\nuint8_min: __builtin__.u8 = W_uint8_min_2.__fromatom__(0)\n\nW_uint8_max_2: __builtin__.Number[__builtin__.u8] = __builtin__.IntegralD_u8()\n\nuint8_max: __builtin__.u8 = W_uint8_max_2.__fromatom__(255)\n\nbigint_small: __builtin__.bigint = 42\n\nbigint_neg_small: __builtin__.bigint = -1\n\nbigint_i64_max: __builtin__.bigint = 9223372036854775807\n\nbigint_i64_min: __builtin__.bigint = -9223372036854775808\n\nbigint_i64_underflow: __builtin__.bigint = -9223372036854775809\n\nbigint_u64_edge: __builtin__.bigint = bigint(18446744073709551615, None)\n\nbigint_u64_edge_minus1: __builtin__.bigint = bigint(18446744073709551614, None)\n\nbigint_u64_overflow: __builtin__.bigint = 18446744073709551616\n\nxint_i64_min_minus1: __builtin__.bigint = -9223372036854775809"
  },
  {
    "path": "compiler/lib/test/9-codegen/lines.c",
    "content": "/* Acton impl hash: test-hash */\n#include \"rts/common.h\"\n#include \"out/types/lines.h\"\nB_Eq linesQ_W_Apa_1097;\nB_Eq linesQ_W_Apa_759;\nB_Iterable linesQ_W_Apa_779;\nB_Eq linesQ_W_Apa_331;\nB_Eq linesQ_W_Apa_785;\n$R linesQ_L_1C_1cont (linesQ_Apa self, $Cont C_cont, B_NoneType C_2res) {\n    #line 18 \"test/src/lines.act\"\n    self->z = toB_int(1LL);\n    #line 19 \"test/src/lines.act\"\n    ((B_NoneType (*) (B_tuple, B_str, B_str, B_bool, B_bool))B_print)($NEWTUPLE(1, to$str(\"Apa\")), B_None, B_None, B_None, B_None);\n    return $R_CONT(C_cont, B_None);\n}\nB_NoneType linesQ_L_2ContD___init__ (linesQ_L_2Cont L_self, linesQ_Apa self, $Cont C_cont) {\n    L_self->self = self;\n    L_self->C_cont = C_cont;\n    return B_None;\n}\n$R linesQ_L_2ContD___call__ (linesQ_L_2Cont L_self, B_NoneType G_1) {\n    linesQ_Apa self = L_self->self;\n    $Cont C_cont = L_self->C_cont;\n    return linesQ_L_1C_1cont(self, C_cont, G_1);\n}\nvoid linesQ_L_2ContD___serialize__ (linesQ_L_2Cont self, $Serial$state state) {\n    $step_serialize(self->self, state);\n    $step_serialize(self->C_cont, state);\n}\nlinesQ_L_2Cont linesQ_L_2ContD___deserialize__ (linesQ_L_2Cont self, $Serial$state state) {\n    if (!self) {\n        if (!state) {\n            self = acton_malloc(sizeof(struct linesQ_L_2Cont));\n            self->$class = &linesQ_L_2ContG_methods;\n            return self;\n        }\n        self = $DNEW(linesQ_L_2Cont, state);\n    }\n    self->self = $step_deserialize(state);\n    self->C_cont = $step_deserialize(state);\n    return self;\n}\nlinesQ_L_2Cont linesQ_L_2ContG_new(linesQ_Apa G_1, $Cont G_2) {\n    linesQ_L_2Cont $tmp = acton_malloc(sizeof(struct linesQ_L_2Cont));\n    $tmp->$class = &linesQ_L_2ContG_methods;\n    linesQ_L_2ContG_methods.__init__($tmp, G_1, G_2);\n    return $tmp;\n}\nstruct linesQ_L_2ContG_class linesQ_L_2ContG_methods;\nB_NoneType linesQ_L_4actionD___init__ (linesQ_L_4action L_self, linesQ_Apa L_3obj) {\n    L_self->L_3obj = L_3obj;\n    return B_None;\n}\n$R linesQ_L_4actionD___call__ (linesQ_L_4action L_self, $Cont L_cont, B_int G_1) {\n    return $AWAIT(L_cont, ((B_Msg)((B_Msg (*) (linesQ_L_4action, B_int))L_self->$class->__asyn__)(L_self, G_1)));\n}\n$R linesQ_L_4actionD___exec__ (linesQ_L_4action L_self, $Cont L_cont, B_int G_1) {\n    return $R_CONT(L_cont, ((B_value)((B_Msg (*) (linesQ_L_4action, B_int))L_self->$class->__asyn__)(L_self, G_1)));\n}\nB_Msg linesQ_L_4actionD___asyn__ (linesQ_L_4action L_self, B_int G_1) {\n    linesQ_Apa L_3obj = L_self->L_3obj;\n    return ((B_Msg)((B_Msg (*) (linesQ_Apa, B_int))L_3obj->$class->notice)(L_3obj, G_1));\n}\nvoid linesQ_L_4actionD___serialize__ (linesQ_L_4action self, $Serial$state state) {\n    $step_serialize(self->L_3obj, state);\n}\nlinesQ_L_4action linesQ_L_4actionD___deserialize__ (linesQ_L_4action self, $Serial$state state) {\n    if (!self) {\n        if (!state) {\n            self = acton_malloc(sizeof(struct linesQ_L_4action));\n            self->$class = &linesQ_L_4actionG_methods;\n            return self;\n        }\n        self = $DNEW(linesQ_L_4action, state);\n    }\n    self->L_3obj = $step_deserialize(state);\n    return self;\n}\nlinesQ_L_4action linesQ_L_4actionG_new(linesQ_Apa G_1) {\n    linesQ_L_4action $tmp = acton_malloc(sizeof(struct linesQ_L_4action));\n    $tmp->$class = &linesQ_L_4actionG_methods;\n    linesQ_L_4actionG_methods.__init__($tmp, G_1);\n    return $tmp;\n}\nstruct linesQ_L_4actionG_class linesQ_L_4actionG_methods;\n$R linesQ_U_L_5C_3cont ($action cb, $Cont C_cont, int64_t U_2C_4res) {\n    #line 9 \"test/src/lines.act\"\n    int64_t U_3v = U_2C_4res;\n    #line 10 \"test/src/lines.act\"\n    B_Msg m = ((B_Msg)((B_Msg (*) ($action, B_int))cb->$class->__asyn__)(cb, toB_int(2LL)));\n    int64_t U_4N_tmp = (U_3v * 10LL);\n    return $R_CONT(C_cont, toB_int(U_4N_tmp));\n}\n$R linesQ_L_5C_3cont ($action cb, $Cont C_cont, B_int C_4res) {\n    return linesQ_U_L_5C_3cont(cb, C_cont, ((B_int)C_4res)->val);\n}\nB_NoneType linesQ_L_6ContD___init__ (linesQ_L_6Cont L_self, $action cb, $Cont C_cont) {\n    L_self->cb = cb;\n    L_self->C_cont = C_cont;\n    return B_None;\n}\n$R linesQ_L_6ContD___call__ (linesQ_L_6Cont L_self, B_int G_1) {\n    $action cb = L_self->cb;\n    $Cont C_cont = L_self->C_cont;\n    return linesQ_L_5C_3cont(cb, C_cont, G_1);\n}\nvoid linesQ_L_6ContD___serialize__ (linesQ_L_6Cont self, $Serial$state state) {\n    $step_serialize(self->cb, state);\n    $step_serialize(self->C_cont, state);\n}\nlinesQ_L_6Cont linesQ_L_6ContD___deserialize__ (linesQ_L_6Cont self, $Serial$state state) {\n    if (!self) {\n        if (!state) {\n            self = acton_malloc(sizeof(struct linesQ_L_6Cont));\n            self->$class = &linesQ_L_6ContG_methods;\n            return self;\n        }\n        self = $DNEW(linesQ_L_6Cont, state);\n    }\n    self->cb = $step_deserialize(state);\n    self->C_cont = $step_deserialize(state);\n    return self;\n}\nlinesQ_L_6Cont linesQ_L_6ContG_new($action G_1, $Cont G_2) {\n    linesQ_L_6Cont $tmp = acton_malloc(sizeof(struct linesQ_L_6Cont));\n    $tmp->$class = &linesQ_L_6ContG_methods;\n    linesQ_L_6ContG_methods.__init__($tmp, G_1, G_2);\n    return $tmp;\n}\nstruct linesQ_L_6ContG_class linesQ_L_6ContG_methods;\nB_NoneType linesQ_L_7procD___init__ (linesQ_L_7proc L_self, linesQ_Apa self, $action cb) {\n    L_self->self = self;\n    L_self->cb = cb;\n    return B_None;\n}\n$R linesQ_L_7procD___call__ (linesQ_L_7proc L_self, $Cont C_cont) {\n    linesQ_Apa self = L_self->self;\n    $action cb = L_self->cb;\n    return (($R (*) (linesQ_Apa, $Cont, $action))self->$class->setupG_local)(self, C_cont, cb);\n}\n$R linesQ_L_7procD___exec__ (linesQ_L_7proc L_self, $Cont C_cont) {\n    return (($R (*) (linesQ_L_7proc, $Cont))L_self->$class->__call__)(L_self, C_cont);\n}\nvoid linesQ_L_7procD___serialize__ (linesQ_L_7proc self, $Serial$state state) {\n    $step_serialize(self->self, state);\n    $step_serialize(self->cb, state);\n}\nlinesQ_L_7proc linesQ_L_7procD___deserialize__ (linesQ_L_7proc self, $Serial$state state) {\n    if (!self) {\n        if (!state) {\n            self = acton_malloc(sizeof(struct linesQ_L_7proc));\n            self->$class = &linesQ_L_7procG_methods;\n            return self;\n        }\n        self = $DNEW(linesQ_L_7proc, state);\n    }\n    self->self = $step_deserialize(state);\n    self->cb = $step_deserialize(state);\n    return self;\n}\nlinesQ_L_7proc linesQ_L_7procG_new(linesQ_Apa G_1, $action G_2) {\n    linesQ_L_7proc $tmp = acton_malloc(sizeof(struct linesQ_L_7proc));\n    $tmp->$class = &linesQ_L_7procG_methods;\n    linesQ_L_7procG_methods.__init__($tmp, G_1, G_2);\n    return $tmp;\n}\nstruct linesQ_L_7procG_class linesQ_L_7procG_methods;\nB_NoneType linesQ_L_8procD___init__ (linesQ_L_8proc L_self, linesQ_Apa self, $action cb) {\n    L_self->self = self;\n    L_self->cb = cb;\n    return B_None;\n}\n$R linesQ_L_8procD___call__ (linesQ_L_8proc L_self, $Cont C_cont) {\n    linesQ_Apa self = L_self->self;\n    $action cb = L_self->cb;\n    return (($R (*) (linesQ_Apa, $Cont, $action))self->$class->computeG_local)(self, C_cont, cb);\n}\n$R linesQ_L_8procD___exec__ (linesQ_L_8proc L_self, $Cont C_cont) {\n    return (($R (*) (linesQ_L_8proc, $Cont))L_self->$class->__call__)(L_self, C_cont);\n}\nvoid linesQ_L_8procD___serialize__ (linesQ_L_8proc self, $Serial$state state) {\n    $step_serialize(self->self, state);\n    $step_serialize(self->cb, state);\n}\nlinesQ_L_8proc linesQ_L_8procD___deserialize__ (linesQ_L_8proc self, $Serial$state state) {\n    if (!self) {\n        if (!state) {\n            self = acton_malloc(sizeof(struct linesQ_L_8proc));\n            self->$class = &linesQ_L_8procG_methods;\n            return self;\n        }\n        self = $DNEW(linesQ_L_8proc, state);\n    }\n    self->self = $step_deserialize(state);\n    self->cb = $step_deserialize(state);\n    return self;\n}\nlinesQ_L_8proc linesQ_L_8procG_new(linesQ_Apa G_1, $action G_2) {\n    linesQ_L_8proc $tmp = acton_malloc(sizeof(struct linesQ_L_8proc));\n    $tmp->$class = &linesQ_L_8procG_methods;\n    linesQ_L_8procG_methods.__init__($tmp, G_1, G_2);\n    return $tmp;\n}\nstruct linesQ_L_8procG_class linesQ_L_8procG_methods;\nB_NoneType linesQ_L_9procD___init__ (linesQ_L_9proc L_self, linesQ_Apa self, B_int i) {\n    L_self->self = self;\n    L_self->i = i;\n    return B_None;\n}\n$R linesQ_L_9procD___call__ (linesQ_L_9proc L_self, $Cont C_cont) {\n    linesQ_Apa self = L_self->self;\n    int64_t U_5i = ((B_int)L_self->i)->val;\n    return (($R (*) (linesQ_Apa, $Cont, B_int))self->$class->noticeG_local)(self, C_cont, toB_int(U_5i));\n}\n$R linesQ_L_9procD___exec__ (linesQ_L_9proc L_self, $Cont C_cont) {\n    return (($R (*) (linesQ_L_9proc, $Cont))L_self->$class->__call__)(L_self, C_cont);\n}\nvoid linesQ_L_9procD___serialize__ (linesQ_L_9proc self, $Serial$state state) {\n    $step_serialize(self->self, state);\n    $step_serialize(self->i, state);\n}\nlinesQ_L_9proc linesQ_L_9procD___deserialize__ (linesQ_L_9proc self, $Serial$state state) {\n    if (!self) {\n        if (!state) {\n            self = acton_malloc(sizeof(struct linesQ_L_9proc));\n            self->$class = &linesQ_L_9procG_methods;\n            return self;\n        }\n        self = $DNEW(linesQ_L_9proc, state);\n    }\n    self->self = $step_deserialize(state);\n    self->i = $step_deserialize(state);\n    return self;\n}\nlinesQ_L_9proc linesQ_L_9procG_new(linesQ_Apa G_1, B_int G_2) {\n    linesQ_L_9proc $tmp = acton_malloc(sizeof(struct linesQ_L_9proc));\n    $tmp->$class = &linesQ_L_9procG_methods;\n    linesQ_L_9procG_methods.__init__($tmp, G_1, G_2);\n    return $tmp;\n}\nstruct linesQ_L_9procG_class linesQ_L_9procG_methods;\nB_NoneType linesQ_L_10procD___init__ (linesQ_L_10proc L_self, linesQ_Bepa self, B_int i) {\n    L_self->self = self;\n    L_self->i = i;\n    return B_None;\n}\n$R linesQ_L_10procD___call__ (linesQ_L_10proc L_self, $Cont C_cont) {\n    linesQ_Bepa self = L_self->self;\n    int64_t U_6i = ((B_int)L_self->i)->val;\n    return (($R (*) (linesQ_Bepa, $Cont, B_int))self->$class->callbackG_local)(self, C_cont, toB_int(U_6i));\n}\n$R linesQ_L_10procD___exec__ (linesQ_L_10proc L_self, $Cont C_cont) {\n    return (($R (*) (linesQ_L_10proc, $Cont))L_self->$class->__call__)(L_self, C_cont);\n}\nvoid linesQ_L_10procD___serialize__ (linesQ_L_10proc self, $Serial$state state) {\n    $step_serialize(self->self, state);\n    $step_serialize(self->i, state);\n}\nlinesQ_L_10proc linesQ_L_10procD___deserialize__ (linesQ_L_10proc self, $Serial$state state) {\n    if (!self) {\n        if (!state) {\n            self = acton_malloc(sizeof(struct linesQ_L_10proc));\n            self->$class = &linesQ_L_10procG_methods;\n            return self;\n        }\n        self = $DNEW(linesQ_L_10proc, state);\n    }\n    self->self = $step_deserialize(state);\n    self->i = $step_deserialize(state);\n    return self;\n}\nlinesQ_L_10proc linesQ_L_10procG_new(linesQ_Bepa G_1, B_int G_2) {\n    linesQ_L_10proc $tmp = acton_malloc(sizeof(struct linesQ_L_10proc));\n    $tmp->$class = &linesQ_L_10procG_methods;\n    linesQ_L_10procG_methods.__init__($tmp, G_1, G_2);\n    return $tmp;\n}\nstruct linesQ_L_10procG_class linesQ_L_10procG_methods;\nB_NoneType linesQ_L_14actionD___init__ (linesQ_L_14action L_self, linesQ_Apa L_13obj) {\n    L_self->L_13obj = L_13obj;\n    return B_None;\n}\n$R linesQ_L_14actionD___call__ (linesQ_L_14action L_self, $Cont L_cont, B_int G_1) {\n    return $AWAIT(L_cont, ((B_Msg)((B_Msg (*) (linesQ_L_14action, B_int))L_self->$class->__asyn__)(L_self, G_1)));\n}\n$R linesQ_L_14actionD___exec__ (linesQ_L_14action L_self, $Cont L_cont, B_int G_1) {\n    return $R_CONT(L_cont, ((B_value)((B_Msg (*) (linesQ_L_14action, B_int))L_self->$class->__asyn__)(L_self, G_1)));\n}\nB_Msg linesQ_L_14actionD___asyn__ (linesQ_L_14action L_self, B_int G_1) {\n    linesQ_Apa L_13obj = L_self->L_13obj;\n    return ((B_Msg)((B_Msg (*) (linesQ_Apa, B_int))L_13obj->$class->notice)(L_13obj, G_1));\n}\nvoid linesQ_L_14actionD___serialize__ (linesQ_L_14action self, $Serial$state state) {\n    $step_serialize(self->L_13obj, state);\n}\nlinesQ_L_14action linesQ_L_14actionD___deserialize__ (linesQ_L_14action self, $Serial$state state) {\n    if (!self) {\n        if (!state) {\n            self = acton_malloc(sizeof(struct linesQ_L_14action));\n            self->$class = &linesQ_L_14actionG_methods;\n            return self;\n        }\n        self = $DNEW(linesQ_L_14action, state);\n    }\n    self->L_13obj = $step_deserialize(state);\n    return self;\n}\nlinesQ_L_14action linesQ_L_14actionG_new(linesQ_Apa G_1) {\n    linesQ_L_14action $tmp = acton_malloc(sizeof(struct linesQ_L_14action));\n    $tmp->$class = &linesQ_L_14actionG_methods;\n    linesQ_L_14actionG_methods.__init__($tmp, G_1);\n    return $tmp;\n}\nstruct linesQ_L_14actionG_class linesQ_L_14actionG_methods;\nB_NoneType linesQ_L_16actionD___init__ (linesQ_L_16action L_self, linesQ_Bepa L_15obj) {\n    L_self->L_15obj = L_15obj;\n    return B_None;\n}\n$R linesQ_L_16actionD___call__ (linesQ_L_16action L_self, $Cont L_cont, B_int G_1) {\n    return $AWAIT(L_cont, ((B_Msg)((B_Msg (*) (linesQ_L_16action, B_int))L_self->$class->__asyn__)(L_self, G_1)));\n}\n$R linesQ_L_16actionD___exec__ (linesQ_L_16action L_self, $Cont L_cont, B_int G_1) {\n    return $R_CONT(L_cont, ((B_value)((B_Msg (*) (linesQ_L_16action, B_int))L_self->$class->__asyn__)(L_self, G_1)));\n}\nB_Msg linesQ_L_16actionD___asyn__ (linesQ_L_16action L_self, B_int G_1) {\n    linesQ_Bepa L_15obj = L_self->L_15obj;\n    return ((B_Msg)((B_Msg (*) (linesQ_Bepa, B_int))L_15obj->$class->callback)(L_15obj, G_1));\n}\nvoid linesQ_L_16actionD___serialize__ (linesQ_L_16action self, $Serial$state state) {\n    $step_serialize(self->L_15obj, state);\n}\nlinesQ_L_16action linesQ_L_16actionD___deserialize__ (linesQ_L_16action self, $Serial$state state) {\n    if (!self) {\n        if (!state) {\n            self = acton_malloc(sizeof(struct linesQ_L_16action));\n            self->$class = &linesQ_L_16actionG_methods;\n            return self;\n        }\n        self = $DNEW(linesQ_L_16action, state);\n    }\n    self->L_15obj = $step_deserialize(state);\n    return self;\n}\nlinesQ_L_16action linesQ_L_16actionG_new(linesQ_Bepa G_1) {\n    linesQ_L_16action $tmp = acton_malloc(sizeof(struct linesQ_L_16action));\n    $tmp->$class = &linesQ_L_16actionG_methods;\n    linesQ_L_16actionG_methods.__init__($tmp, G_1);\n    return $tmp;\n}\nstruct linesQ_L_16actionG_class linesQ_L_16actionG_methods;\nB_NoneType linesQ_L_19actionD___init__ (linesQ_L_19action L_self, linesQ_main L_18obj) {\n    L_self->L_18obj = L_18obj;\n    return B_None;\n}\n$R linesQ_L_19actionD___call__ (linesQ_L_19action L_self, $Cont L_cont, B_int G_1) {\n    return $AWAIT(L_cont, ((B_Msg)((B_Msg (*) (linesQ_L_19action, B_int))L_self->$class->__asyn__)(L_self, G_1)));\n}\n$R linesQ_L_19actionD___exec__ (linesQ_L_19action L_self, $Cont L_cont, B_int G_1) {\n    return $R_CONT(L_cont, ((B_value)((B_Msg (*) (linesQ_L_19action, B_int))L_self->$class->__asyn__)(L_self, G_1)));\n}\nB_Msg linesQ_L_19actionD___asyn__ (linesQ_L_19action L_self, B_int G_1) {\n    linesQ_main L_18obj = L_self->L_18obj;\n    return ((B_Msg)((B_Msg (*) (linesQ_main, B_int))L_18obj->$class->myproc)(L_18obj, G_1));\n}\nvoid linesQ_L_19actionD___serialize__ (linesQ_L_19action self, $Serial$state state) {\n    $step_serialize(self->L_18obj, state);\n}\nlinesQ_L_19action linesQ_L_19actionD___deserialize__ (linesQ_L_19action self, $Serial$state state) {\n    if (!self) {\n        if (!state) {\n            self = acton_malloc(sizeof(struct linesQ_L_19action));\n            self->$class = &linesQ_L_19actionG_methods;\n            return self;\n        }\n        self = $DNEW(linesQ_L_19action, state);\n    }\n    self->L_18obj = $step_deserialize(state);\n    return self;\n}\nlinesQ_L_19action linesQ_L_19actionG_new(linesQ_main G_1) {\n    linesQ_L_19action $tmp = acton_malloc(sizeof(struct linesQ_L_19action));\n    $tmp->$class = &linesQ_L_19actionG_methods;\n    linesQ_L_19actionG_methods.__init__($tmp, G_1);\n    return $tmp;\n}\nstruct linesQ_L_19actionG_class linesQ_L_19actionG_methods;\nB_NoneType linesQ_L_20procD___init__ (linesQ_L_20proc L_self, linesQ_main self) {\n    L_self->self = self;\n    return B_None;\n}\n$R linesQ_L_20procD___call__ (linesQ_L_20proc L_self, $Cont C_cont) {\n    linesQ_main self = L_self->self;\n    return (($R (*) (linesQ_main, $Cont, B_int))self->$class->myprocG_local)(self, C_cont, toB_int(0LL));\n}\n$R linesQ_L_20procD___exec__ (linesQ_L_20proc L_self, $Cont C_cont) {\n    return (($R (*) (linesQ_L_20proc, $Cont))L_self->$class->__call__)(L_self, C_cont);\n}\nvoid linesQ_L_20procD___serialize__ (linesQ_L_20proc self, $Serial$state state) {\n    $step_serialize(self->self, state);\n}\nlinesQ_L_20proc linesQ_L_20procD___deserialize__ (linesQ_L_20proc self, $Serial$state state) {\n    if (!self) {\n        if (!state) {\n            self = acton_malloc(sizeof(struct linesQ_L_20proc));\n            self->$class = &linesQ_L_20procG_methods;\n            return self;\n        }\n        self = $DNEW(linesQ_L_20proc, state);\n    }\n    self->self = $step_deserialize(state);\n    return self;\n}\nlinesQ_L_20proc linesQ_L_20procG_new(linesQ_main G_1) {\n    linesQ_L_20proc $tmp = acton_malloc(sizeof(struct linesQ_L_20proc));\n    $tmp->$class = &linesQ_L_20procG_methods;\n    linesQ_L_20procG_methods.__init__($tmp, G_1);\n    return $tmp;\n}\nstruct linesQ_L_20procG_class linesQ_L_20procG_methods;\n$R linesQ_U_1L_17C_9cont (linesQ_main self, $Cont C_cont, int64_t U_7C_10res) {\n    #line 38 \"test/src/lines.act\"\n    self->r = toB_int(U_7C_10res);\n    #line 39 \"test/src/lines.act\"\n    ((B_NoneType (*) (B_tuple, B_str, B_str, B_bool, B_bool))B_print)($NEWTUPLE(2, to$str(\"r =\"), self->r), B_None, B_None, B_None, B_None);\n    #line 40 \"test/src/lines.act\"\n    ((B_Msg (*) (linesQ_Apa, $action))self->a->$class->compute)(self->a, (($action)linesQ_L_19actionG_new(self)));\n    #line 41 \"test/src/lines.act\"\n    ((B_NoneType (*) (B_tuple, B_str, B_str, B_bool, B_bool))B_print)($NEWTUPLE(1, to$str(\"main\")), B_None, B_None, B_None, B_None);\n    #line 44 \"test/src/lines.act\"\n    self->v = toB_int(0LL);\n    #line 45 \"test/src/lines.act\"\n    if ((((B_int)self->v)->val == 0LL)) {\n        #line 46 \"test/src/lines.act\"\n        ((B_NoneType (*) (B_tuple, B_str, B_str, B_bool, B_bool))B_print)($NEWTUPLE(1, to$str(\"if branch\")), B_None, B_None, B_None, B_None);\n        #line 47 \"test/src/lines.act\"\n        if ((((B_int)self->v)->val < 1LL)) {\n            #line 48 \"test/src/lines.act\"\n            ((B_NoneType (*) (B_tuple, B_str, B_str, B_bool, B_bool))B_print)($NEWTUPLE(1, to$str(\"nested if\")), B_None, B_None, B_None, B_None);\n        }\n        else if ((((B_int)self->v)->val == -1LL)) {\n            #line 50 \"test/src/lines.act\"\n            ((B_NoneType (*) (B_tuple, B_str, B_str, B_bool, B_bool))B_print)($NEWTUPLE(1, to$str(\"nested elif\")), B_None, B_None, B_None, B_None);\n        }\n        else {\n            #line 52 \"test/src/lines.act\"\n            ((B_NoneType (*) (B_tuple, B_str, B_str, B_bool, B_bool))B_print)($NEWTUPLE(1, to$str(\"nested else\")), B_None, B_None, B_None, B_None);\n        }\n    }\n    else if ((((B_int)self->v)->val == 1LL)) {\n        #line 54 \"test/src/lines.act\"\n        ((B_NoneType (*) (B_tuple, B_str, B_str, B_bool, B_bool))B_print)($NEWTUPLE(1, to$str(\"outer elif\")), B_None, B_None, B_None, B_None);\n    }\n    else {\n        #line 56 \"test/src/lines.act\"\n        ((B_NoneType (*) (B_tuple, B_str, B_str, B_bool, B_bool))B_print)($NEWTUPLE(1, to$str(\"outer else\")), B_None, B_None, B_None, B_None);\n    }\n    #line 59 \"test/src/lines.act\"\n    self->i = toB_int(0LL);\n    #line 60 \"test/src/lines.act\"\n    while (true) {\n        if ((((B_int)self->i)->val < 3LL)) {\n        }\n        else {\n            #line 70 \"test/src/lines.act\"\n            ((B_NoneType (*) (B_tuple, B_str, B_str, B_bool, B_bool))B_print)($NEWTUPLE(1, to$str(\"while else\")), B_None, B_None, B_None, B_None);\n            break;\n        }\n        #line 61 \"test/src/lines.act\"\n        self->i = toB_int((((B_int)self->i)->val + 1LL));\n        #line 62 \"test/src/lines.act\"\n        if ((((B_int)self->i)->val == 1LL)) {\n            #line 63 \"test/src/lines.act\"\n            ((B_NoneType (*) (B_tuple, B_str, B_str, B_bool, B_bool))B_print)($NEWTUPLE(1, to$str(\"continue path\")), B_None, B_None, B_None, B_None);\n            #line 64 \"test/src/lines.act\"\n            continue;\n        }\n        #line 65 \"test/src/lines.act\"\n        if ((((B_int)self->i)->val == 2LL)) {\n            #line 66 \"test/src/lines.act\"\n            ((B_NoneType (*) (B_tuple, B_str, B_str, B_bool, B_bool))B_print)($NEWTUPLE(1, to$str(\"break path\")), B_None, B_None, B_None, B_None);\n            #line 67 \"test/src/lines.act\"\n            break;\n        }\n        #line 68 \"test/src/lines.act\"\n        ((B_NoneType (*) (B_tuple, B_str, B_str, B_bool, B_bool))B_print)($NEWTUPLE(2, to$str(\"loop body\"), self->i), B_None, B_None, B_None, B_None);\n    }\n    B_Iterator N_3iter = ((B_Iterator (*) (B_Iterable, B_list))linesQ_W_Apa_779->$class->__iter__)(linesQ_W_Apa_779, B_mk_list(3, toB_int(1LL) , toB_int(2LL) , toB_int(3LL)));\n    if ($PUSH()) {\n        #line 73 \"test/src/lines.act\"\n        while (true) {\n            B_int j = ((B_int (*) (B_Iterator))N_3iter->$class->__next__)(N_3iter);\n            #line 74 \"test/src/lines.act\"\n            if (((B_bool)((B_bool (*) (B_Eq, B_int, B_int))linesQ_W_Apa_759->$class->__eq__)(linesQ_W_Apa_759, j, toB_int(2LL)))->val) {\n                #line 75 \"test/src/lines.act\"\n                continue;\n            }\n            #line 76 \"test/src/lines.act\"\n            ((B_NoneType (*) (B_tuple, B_str, B_str, B_bool, B_bool))B_print)($NEWTUPLE(2, to$str(\"for j\"), j), B_None, B_None, B_None, B_None);\n        }\n        $DROP();\n    }\n    else {\n        B_BaseException N_5x = $POP();\n        if ($ISINSTANCE0(N_5x, B_StopIteration)) {\n        }\n        else {\n            $RAISE(N_5x);\n        }\n    }\n    B_BaseException N_7xx;\n    if ($PUSHF()) {\n        if ($PUSH()) {\n            #line 80 \"test/src/lines.act\"\n            if (((B_bool)((B_bool (*) (B_Eq, B_int, B_int))linesQ_W_Apa_785->$class->__eq__)(linesQ_W_Apa_785, self->v, toB_int(0LL)))->val) {\n                #line 81 \"test/src/lines.act\"\n                $RAISE(((B_BaseException)B_ValueErrorG_new(to$str(\"boom\"))));\n            }\n            #line 82 \"test/src/lines.act\"\n            ((B_NoneType (*) (B_tuple, B_str, B_str, B_bool, B_bool))B_print)($NEWTUPLE(1, to$str(\"unreached\")), B_None, B_None, B_None, B_None);\n            $DROP();\n        }\n        else {\n            B_BaseException N_6x = $POP();\n            B_ValueError e;\n            if ($ISINSTANCE0(N_6x, B_ValueError)) {\n                e = ((B_ValueError)N_6x);\n                #line 84 \"test/src/lines.act\"\n                ((B_NoneType (*) (B_tuple, B_str, B_str, B_bool, B_bool))B_print)($NEWTUPLE(2, to$str(\"caught\"), to$str(\"ValueError\")), B_None, B_None, B_None, B_None);\n            }\n            else {\n                $RAISE(N_6x);\n            }\n        }\n        $RAISE(((B_BaseException)$SEQG_new()));\n    }\n    else {\n        N_7xx = $POP();\n        #line 86 \"test/src/lines.act\"\n        ((B_NoneType (*) (B_tuple, B_str, B_str, B_bool, B_bool))B_print)($NEWTUPLE(1, to$str(\"finally\")), B_None, B_None, B_None, B_None);\n        if ($ISINSTANCE0(N_7xx, $SEQ)) {\n        }\n        else {\n            $RAISE(N_7xx);\n        }\n    }\n    #line 89 \"test/src/lines.act\"\n    $AFTER(toB_float(1), (($Cont)linesQ_L_20procG_new(self)));\n    return (($R (*) (linesQ_main, $Cont))self->$class->nopG_local)(self, C_cont);\n}\n$R linesQ_L_17C_9cont (linesQ_main self, $Cont C_cont, B_int C_10res) {\n    return linesQ_U_1L_17C_9cont(self, C_cont, ((B_int)C_10res)->val);\n}\nB_NoneType linesQ_L_21ContD___init__ (linesQ_L_21Cont L_self, linesQ_main self, $Cont C_cont) {\n    L_self->self = self;\n    L_self->C_cont = C_cont;\n    return B_None;\n}\n$R linesQ_L_21ContD___call__ (linesQ_L_21Cont L_self, B_int G_1) {\n    linesQ_main self = L_self->self;\n    $Cont C_cont = L_self->C_cont;\n    return linesQ_L_17C_9cont(self, C_cont, G_1);\n}\nvoid linesQ_L_21ContD___serialize__ (linesQ_L_21Cont self, $Serial$state state) {\n    $step_serialize(self->self, state);\n    $step_serialize(self->C_cont, state);\n}\nlinesQ_L_21Cont linesQ_L_21ContD___deserialize__ (linesQ_L_21Cont self, $Serial$state state) {\n    if (!self) {\n        if (!state) {\n            self = acton_malloc(sizeof(struct linesQ_L_21Cont));\n            self->$class = &linesQ_L_21ContG_methods;\n            return self;\n        }\n        self = $DNEW(linesQ_L_21Cont, state);\n    }\n    self->self = $step_deserialize(state);\n    self->C_cont = $step_deserialize(state);\n    return self;\n}\nlinesQ_L_21Cont linesQ_L_21ContG_new(linesQ_main G_1, $Cont G_2) {\n    linesQ_L_21Cont $tmp = acton_malloc(sizeof(struct linesQ_L_21Cont));\n    $tmp->$class = &linesQ_L_21ContG_methods;\n    linesQ_L_21ContG_methods.__init__($tmp, G_1, G_2);\n    return $tmp;\n}\nstruct linesQ_L_21ContG_class linesQ_L_21ContG_methods;\n$R linesQ_L_12C_7cont (linesQ_main self, $Cont C_cont, linesQ_Bepa C_8res) {\n    #line 34 \"test/src/lines.act\"\n    self->b = C_8res;\n    #line 35 \"test/src/lines.act\"\n    ((B_NoneType (*) (B_tuple, B_str, B_str, B_bool, B_bool))B_print)($NEWTUPLE(1, to$str(\"-----\")), B_None, B_None, B_None, B_None);\n    #line 36 \"test/src/lines.act\"\n    ((B_Msg (*) (linesQ_Apa, $action))self->a->$class->setup)(self->a, (($action)linesQ_L_14actionG_new(self->a)));\n    #line 37 \"test/src/lines.act\"\n    self->x = ((B_Msg (*) (linesQ_Apa, $action))self->a->$class->compute)(self->a, (($action)linesQ_L_16actionG_new(self->b)));\n    return $AWAIT((($Cont)linesQ_L_21ContG_new(self, C_cont)), self->x);\n}\nB_NoneType linesQ_L_22ContD___init__ (linesQ_L_22Cont L_self, linesQ_main self, $Cont C_cont) {\n    L_self->self = self;\n    L_self->C_cont = C_cont;\n    return B_None;\n}\n$R linesQ_L_22ContD___call__ (linesQ_L_22Cont L_self, linesQ_Bepa G_1) {\n    linesQ_main self = L_self->self;\n    $Cont C_cont = L_self->C_cont;\n    return linesQ_L_12C_7cont(self, C_cont, G_1);\n}\nvoid linesQ_L_22ContD___serialize__ (linesQ_L_22Cont self, $Serial$state state) {\n    $step_serialize(self->self, state);\n    $step_serialize(self->C_cont, state);\n}\nlinesQ_L_22Cont linesQ_L_22ContD___deserialize__ (linesQ_L_22Cont self, $Serial$state state) {\n    if (!self) {\n        if (!state) {\n            self = acton_malloc(sizeof(struct linesQ_L_22Cont));\n            self->$class = &linesQ_L_22ContG_methods;\n            return self;\n        }\n        self = $DNEW(linesQ_L_22Cont, state);\n    }\n    self->self = $step_deserialize(state);\n    self->C_cont = $step_deserialize(state);\n    return self;\n}\nlinesQ_L_22Cont linesQ_L_22ContG_new(linesQ_main G_1, $Cont G_2) {\n    linesQ_L_22Cont $tmp = acton_malloc(sizeof(struct linesQ_L_22Cont));\n    $tmp->$class = &linesQ_L_22ContG_methods;\n    linesQ_L_22ContG_methods.__init__($tmp, G_1, G_2);\n    return $tmp;\n}\nstruct linesQ_L_22ContG_class linesQ_L_22ContG_methods;\n$R linesQ_L_11C_5cont (linesQ_main self, $Cont C_cont, linesQ_Apa C_6res) {\n    #line 33 \"test/src/lines.act\"\n    self->a = C_6res;\n    return linesQ_BepaG_newact((($Cont)linesQ_L_22ContG_new(self, C_cont)));\n}\nB_NoneType linesQ_L_23ContD___init__ (linesQ_L_23Cont L_self, linesQ_main self, $Cont C_cont) {\n    L_self->self = self;\n    L_self->C_cont = C_cont;\n    return B_None;\n}\n$R linesQ_L_23ContD___call__ (linesQ_L_23Cont L_self, linesQ_Apa G_1) {\n    linesQ_main self = L_self->self;\n    $Cont C_cont = L_self->C_cont;\n    return linesQ_L_11C_5cont(self, C_cont, G_1);\n}\nvoid linesQ_L_23ContD___serialize__ (linesQ_L_23Cont self, $Serial$state state) {\n    $step_serialize(self->self, state);\n    $step_serialize(self->C_cont, state);\n}\nlinesQ_L_23Cont linesQ_L_23ContD___deserialize__ (linesQ_L_23Cont self, $Serial$state state) {\n    if (!self) {\n        if (!state) {\n            self = acton_malloc(sizeof(struct linesQ_L_23Cont));\n            self->$class = &linesQ_L_23ContG_methods;\n            return self;\n        }\n        self = $DNEW(linesQ_L_23Cont, state);\n    }\n    self->self = $step_deserialize(state);\n    self->C_cont = $step_deserialize(state);\n    return self;\n}\nlinesQ_L_23Cont linesQ_L_23ContG_new(linesQ_main G_1, $Cont G_2) {\n    linesQ_L_23Cont $tmp = acton_malloc(sizeof(struct linesQ_L_23Cont));\n    $tmp->$class = &linesQ_L_23ContG_methods;\n    linesQ_L_23ContG_methods.__init__($tmp, G_1, G_2);\n    return $tmp;\n}\nstruct linesQ_L_23ContG_class linesQ_L_23ContG_methods;\nB_NoneType linesQ_L_24procD___init__ (linesQ_L_24proc L_self, linesQ_main self, B_int i) {\n    L_self->self = self;\n    L_self->i = i;\n    return B_None;\n}\n$R linesQ_L_24procD___call__ (linesQ_L_24proc L_self, $Cont C_cont) {\n    linesQ_main self = L_self->self;\n    int64_t U_8i = ((B_int)L_self->i)->val;\n    return (($R (*) (linesQ_main, $Cont, B_int))self->$class->myprocG_local)(self, C_cont, toB_int(U_8i));\n}\n$R linesQ_L_24procD___exec__ (linesQ_L_24proc L_self, $Cont C_cont) {\n    return (($R (*) (linesQ_L_24proc, $Cont))L_self->$class->__call__)(L_self, C_cont);\n}\nvoid linesQ_L_24procD___serialize__ (linesQ_L_24proc self, $Serial$state state) {\n    $step_serialize(self->self, state);\n    $step_serialize(self->i, state);\n}\nlinesQ_L_24proc linesQ_L_24procD___deserialize__ (linesQ_L_24proc self, $Serial$state state) {\n    if (!self) {\n        if (!state) {\n            self = acton_malloc(sizeof(struct linesQ_L_24proc));\n            self->$class = &linesQ_L_24procG_methods;\n            return self;\n        }\n        self = $DNEW(linesQ_L_24proc, state);\n    }\n    self->self = $step_deserialize(state);\n    self->i = $step_deserialize(state);\n    return self;\n}\nlinesQ_L_24proc linesQ_L_24procG_new(linesQ_main G_1, B_int G_2) {\n    linesQ_L_24proc $tmp = acton_malloc(sizeof(struct linesQ_L_24proc));\n    $tmp->$class = &linesQ_L_24procG_methods;\n    linesQ_L_24procG_methods.__init__($tmp, G_1, G_2);\n    return $tmp;\n}\nstruct linesQ_L_24procG_class linesQ_L_24procG_methods;\nB_NoneType linesQ_L_25procD___init__ (linesQ_L_25proc L_self, linesQ_main self) {\n    L_self->self = self;\n    return B_None;\n}\n$R linesQ_L_25procD___call__ (linesQ_L_25proc L_self, $Cont C_cont) {\n    linesQ_main self = L_self->self;\n    return (($R (*) (linesQ_main, $Cont))self->$class->nopG_local)(self, C_cont);\n}\n$R linesQ_L_25procD___exec__ (linesQ_L_25proc L_self, $Cont C_cont) {\n    return (($R (*) (linesQ_L_25proc, $Cont))L_self->$class->__call__)(L_self, C_cont);\n}\nvoid linesQ_L_25procD___serialize__ (linesQ_L_25proc self, $Serial$state state) {\n    $step_serialize(self->self, state);\n}\nlinesQ_L_25proc linesQ_L_25procD___deserialize__ (linesQ_L_25proc self, $Serial$state state) {\n    if (!self) {\n        if (!state) {\n            self = acton_malloc(sizeof(struct linesQ_L_25proc));\n            self->$class = &linesQ_L_25procG_methods;\n            return self;\n        }\n        self = $DNEW(linesQ_L_25proc, state);\n    }\n    self->self = $step_deserialize(state);\n    return self;\n}\nlinesQ_L_25proc linesQ_L_25procG_new(linesQ_main G_1) {\n    linesQ_L_25proc $tmp = acton_malloc(sizeof(struct linesQ_L_25proc));\n    $tmp->$class = &linesQ_L_25procG_methods;\n    linesQ_L_25procG_methods.__init__($tmp, G_1);\n    return $tmp;\n}\nstruct linesQ_L_25procG_class linesQ_L_25procG_methods;\n$R linesQ_L_26C_11cont ($Cont C_cont, linesQ_Apa G_act, B_NoneType C_12res) {\n    return $R_CONT(C_cont, G_act);\n}\nB_NoneType linesQ_L_27ContD___init__ (linesQ_L_27Cont L_self, $Cont C_cont, linesQ_Apa G_act) {\n    L_self->C_cont = C_cont;\n    L_self->G_act = G_act;\n    return B_None;\n}\n$R linesQ_L_27ContD___call__ (linesQ_L_27Cont L_self, B_NoneType G_1) {\n    $Cont C_cont = L_self->C_cont;\n    linesQ_Apa G_act = L_self->G_act;\n    return linesQ_L_26C_11cont(C_cont, G_act, G_1);\n}\nvoid linesQ_L_27ContD___serialize__ (linesQ_L_27Cont self, $Serial$state state) {\n    $step_serialize(self->C_cont, state);\n    $step_serialize(self->G_act, state);\n}\nlinesQ_L_27Cont linesQ_L_27ContD___deserialize__ (linesQ_L_27Cont self, $Serial$state state) {\n    if (!self) {\n        if (!state) {\n            self = acton_malloc(sizeof(struct linesQ_L_27Cont));\n            self->$class = &linesQ_L_27ContG_methods;\n            return self;\n        }\n        self = $DNEW(linesQ_L_27Cont, state);\n    }\n    self->C_cont = $step_deserialize(state);\n    self->G_act = $step_deserialize(state);\n    return self;\n}\nlinesQ_L_27Cont linesQ_L_27ContG_new($Cont G_1, linesQ_Apa G_2) {\n    linesQ_L_27Cont $tmp = acton_malloc(sizeof(struct linesQ_L_27Cont));\n    $tmp->$class = &linesQ_L_27ContG_methods;\n    linesQ_L_27ContG_methods.__init__($tmp, G_1, G_2);\n    return $tmp;\n}\nstruct linesQ_L_27ContG_class linesQ_L_27ContG_methods;\nB_NoneType linesQ_L_28procD___init__ (linesQ_L_28proc L_self, linesQ_Apa G_act) {\n    L_self->G_act = G_act;\n    return B_None;\n}\n$R linesQ_L_28procD___call__ (linesQ_L_28proc L_self, $Cont C_cont) {\n    linesQ_Apa G_act = L_self->G_act;\n    return (($R (*) (linesQ_Apa, $Cont))G_act->$class->__init__)(G_act, C_cont);\n}\n$R linesQ_L_28procD___exec__ (linesQ_L_28proc L_self, $Cont C_cont) {\n    return (($R (*) (linesQ_L_28proc, $Cont))L_self->$class->__call__)(L_self, C_cont);\n}\nvoid linesQ_L_28procD___serialize__ (linesQ_L_28proc self, $Serial$state state) {\n    $step_serialize(self->G_act, state);\n}\nlinesQ_L_28proc linesQ_L_28procD___deserialize__ (linesQ_L_28proc self, $Serial$state state) {\n    if (!self) {\n        if (!state) {\n            self = acton_malloc(sizeof(struct linesQ_L_28proc));\n            self->$class = &linesQ_L_28procG_methods;\n            return self;\n        }\n        self = $DNEW(linesQ_L_28proc, state);\n    }\n    self->G_act = $step_deserialize(state);\n    return self;\n}\nlinesQ_L_28proc linesQ_L_28procG_new(linesQ_Apa G_1) {\n    linesQ_L_28proc $tmp = acton_malloc(sizeof(struct linesQ_L_28proc));\n    $tmp->$class = &linesQ_L_28procG_methods;\n    linesQ_L_28procG_methods.__init__($tmp, G_1);\n    return $tmp;\n}\nstruct linesQ_L_28procG_class linesQ_L_28procG_methods;\n$R linesQ_L_29C_13cont ($Cont C_cont, linesQ_Bepa G_act, B_NoneType C_14res) {\n    return $R_CONT(C_cont, G_act);\n}\nB_NoneType linesQ_L_30ContD___init__ (linesQ_L_30Cont L_self, $Cont C_cont, linesQ_Bepa G_act) {\n    L_self->C_cont = C_cont;\n    L_self->G_act = G_act;\n    return B_None;\n}\n$R linesQ_L_30ContD___call__ (linesQ_L_30Cont L_self, B_NoneType G_1) {\n    $Cont C_cont = L_self->C_cont;\n    linesQ_Bepa G_act = L_self->G_act;\n    return linesQ_L_29C_13cont(C_cont, G_act, G_1);\n}\nvoid linesQ_L_30ContD___serialize__ (linesQ_L_30Cont self, $Serial$state state) {\n    $step_serialize(self->C_cont, state);\n    $step_serialize(self->G_act, state);\n}\nlinesQ_L_30Cont linesQ_L_30ContD___deserialize__ (linesQ_L_30Cont self, $Serial$state state) {\n    if (!self) {\n        if (!state) {\n            self = acton_malloc(sizeof(struct linesQ_L_30Cont));\n            self->$class = &linesQ_L_30ContG_methods;\n            return self;\n        }\n        self = $DNEW(linesQ_L_30Cont, state);\n    }\n    self->C_cont = $step_deserialize(state);\n    self->G_act = $step_deserialize(state);\n    return self;\n}\nlinesQ_L_30Cont linesQ_L_30ContG_new($Cont G_1, linesQ_Bepa G_2) {\n    linesQ_L_30Cont $tmp = acton_malloc(sizeof(struct linesQ_L_30Cont));\n    $tmp->$class = &linesQ_L_30ContG_methods;\n    linesQ_L_30ContG_methods.__init__($tmp, G_1, G_2);\n    return $tmp;\n}\nstruct linesQ_L_30ContG_class linesQ_L_30ContG_methods;\nB_NoneType linesQ_L_31procD___init__ (linesQ_L_31proc L_self, linesQ_Bepa G_act) {\n    L_self->G_act = G_act;\n    return B_None;\n}\n$R linesQ_L_31procD___call__ (linesQ_L_31proc L_self, $Cont C_cont) {\n    linesQ_Bepa G_act = L_self->G_act;\n    return (($R (*) (linesQ_Bepa, $Cont))G_act->$class->__init__)(G_act, C_cont);\n}\n$R linesQ_L_31procD___exec__ (linesQ_L_31proc L_self, $Cont C_cont) {\n    return (($R (*) (linesQ_L_31proc, $Cont))L_self->$class->__call__)(L_self, C_cont);\n}\nvoid linesQ_L_31procD___serialize__ (linesQ_L_31proc self, $Serial$state state) {\n    $step_serialize(self->G_act, state);\n}\nlinesQ_L_31proc linesQ_L_31procD___deserialize__ (linesQ_L_31proc self, $Serial$state state) {\n    if (!self) {\n        if (!state) {\n            self = acton_malloc(sizeof(struct linesQ_L_31proc));\n            self->$class = &linesQ_L_31procG_methods;\n            return self;\n        }\n        self = $DNEW(linesQ_L_31proc, state);\n    }\n    self->G_act = $step_deserialize(state);\n    return self;\n}\nlinesQ_L_31proc linesQ_L_31procG_new(linesQ_Bepa G_1) {\n    linesQ_L_31proc $tmp = acton_malloc(sizeof(struct linesQ_L_31proc));\n    $tmp->$class = &linesQ_L_31procG_methods;\n    linesQ_L_31procG_methods.__init__($tmp, G_1);\n    return $tmp;\n}\nstruct linesQ_L_31procG_class linesQ_L_31procG_methods;\n$R linesQ_L_32C_15cont ($Cont C_cont, linesQ_main G_act, B_NoneType C_16res) {\n    return $R_CONT(C_cont, G_act);\n}\nB_NoneType linesQ_L_33ContD___init__ (linesQ_L_33Cont L_self, $Cont C_cont, linesQ_main G_act) {\n    L_self->C_cont = C_cont;\n    L_self->G_act = G_act;\n    return B_None;\n}\n$R linesQ_L_33ContD___call__ (linesQ_L_33Cont L_self, B_NoneType G_1) {\n    $Cont C_cont = L_self->C_cont;\n    linesQ_main G_act = L_self->G_act;\n    return linesQ_L_32C_15cont(C_cont, G_act, G_1);\n}\nvoid linesQ_L_33ContD___serialize__ (linesQ_L_33Cont self, $Serial$state state) {\n    $step_serialize(self->C_cont, state);\n    $step_serialize(self->G_act, state);\n}\nlinesQ_L_33Cont linesQ_L_33ContD___deserialize__ (linesQ_L_33Cont self, $Serial$state state) {\n    if (!self) {\n        if (!state) {\n            self = acton_malloc(sizeof(struct linesQ_L_33Cont));\n            self->$class = &linesQ_L_33ContG_methods;\n            return self;\n        }\n        self = $DNEW(linesQ_L_33Cont, state);\n    }\n    self->C_cont = $step_deserialize(state);\n    self->G_act = $step_deserialize(state);\n    return self;\n}\nlinesQ_L_33Cont linesQ_L_33ContG_new($Cont G_1, linesQ_main G_2) {\n    linesQ_L_33Cont $tmp = acton_malloc(sizeof(struct linesQ_L_33Cont));\n    $tmp->$class = &linesQ_L_33ContG_methods;\n    linesQ_L_33ContG_methods.__init__($tmp, G_1, G_2);\n    return $tmp;\n}\nstruct linesQ_L_33ContG_class linesQ_L_33ContG_methods;\nB_NoneType linesQ_L_34procD___init__ (linesQ_L_34proc L_self, linesQ_main G_act, B_Env env) {\n    L_self->G_act = G_act;\n    L_self->env = env;\n    return B_None;\n}\n$R linesQ_L_34procD___call__ (linesQ_L_34proc L_self, $Cont C_cont) {\n    linesQ_main G_act = L_self->G_act;\n    B_Env env = L_self->env;\n    return (($R (*) (linesQ_main, $Cont, B_Env))G_act->$class->__init__)(G_act, C_cont, env);\n}\n$R linesQ_L_34procD___exec__ (linesQ_L_34proc L_self, $Cont C_cont) {\n    return (($R (*) (linesQ_L_34proc, $Cont))L_self->$class->__call__)(L_self, C_cont);\n}\nvoid linesQ_L_34procD___serialize__ (linesQ_L_34proc self, $Serial$state state) {\n    $step_serialize(self->G_act, state);\n    $step_serialize(self->env, state);\n}\nlinesQ_L_34proc linesQ_L_34procD___deserialize__ (linesQ_L_34proc self, $Serial$state state) {\n    if (!self) {\n        if (!state) {\n            self = acton_malloc(sizeof(struct linesQ_L_34proc));\n            self->$class = &linesQ_L_34procG_methods;\n            return self;\n        }\n        self = $DNEW(linesQ_L_34proc, state);\n    }\n    self->G_act = $step_deserialize(state);\n    self->env = $step_deserialize(state);\n    return self;\n}\nlinesQ_L_34proc linesQ_L_34procG_new(linesQ_main G_1, B_Env G_2) {\n    linesQ_L_34proc $tmp = acton_malloc(sizeof(struct linesQ_L_34proc));\n    $tmp->$class = &linesQ_L_34procG_methods;\n    linesQ_L_34procG_methods.__init__($tmp, G_1, G_2);\n    return $tmp;\n}\nstruct linesQ_L_34procG_class linesQ_L_34procG_methods;\n$R linesQ_ApaD___init__ (linesQ_Apa self, $Cont C_cont) {\n    #line 2 \"test/src/lines.act\"\n    self->apa = toB_int(2001LL);\n    #line 6 \"test/src/lines.act\"\n    self->apb = toB_int(2002LL);\n    #line 16 \"test/src/lines.act\"\n    self->y = toB_int(123LL);\n    return (($R (*) (linesQ_Apa, $Cont, $action))self->$class->setupG_local)(self, (($Cont)linesQ_L_2ContG_new(self, C_cont)), (($action)linesQ_L_4actionG_new(self)));\n}\n#line 3 \"test/src/lines.act\"\n$R linesQ_ApaD_setupG_local (linesQ_Apa self, $Cont C_cont, $action cb) {\n    #line 4 \"test/src/lines.act\"\n    ((B_NoneType (*) (B_tuple, B_str, B_str, B_bool, B_bool))B_print)($NEWTUPLE(1, to$str(\"setup\")), B_None, B_None, B_None, B_None);\n    #line 5 \"test/src/lines.act\"\n    ((B_Msg (*) ($action, B_int))cb->$class->__asyn__)(cb, toB_int(0LL));\n    return $R_CONT(C_cont, B_None);\n}\n#line 7 \"test/src/lines.act\"\n$R linesQ_ApaD_computeG_local (linesQ_Apa self, $Cont C_cont, $action cb) {\n    #line 8 \"test/src/lines.act\"\n    ((B_NoneType (*) (B_tuple, B_str, B_str, B_bool, B_bool))B_print)($NEWTUPLE(1, to$str(\"compute\")), B_None, B_None, B_None, B_None);\n    return $AWAIT((($Cont)linesQ_L_6ContG_new(cb, C_cont)), ((B_Msg)((B_Msg (*) ($action, B_int))cb->$class->__asyn__)(cb, toB_int(1LL))));\n}\n#line 12 \"test/src/lines.act\"\n$R linesQ_ApaD_noticeG_local (linesQ_Apa self, $Cont C_cont, B_int i) {\n    #line 13 \"test/src/lines.act\"\n    ((B_NoneType (*) (B_tuple, B_str, B_str, B_bool, B_bool))B_print)($NEWTUPLE(1, to$str(\"notice\")), B_None, B_None, B_None, B_None);\n    int64_t U_9N_1tmp = (((B_int)i)->val + 1LL);\n    return $R_CONT(C_cont, toB_int(U_9N_1tmp));\n}\nB_Msg linesQ_ApaD_setup (linesQ_Apa self, $action cb) {\n    return $ASYNC((($Actor)self), (($Cont)linesQ_L_7procG_new(self, cb)));\n}\nB_Msg linesQ_ApaD_compute (linesQ_Apa self, $action cb) {\n    return ((B_Msg)$ASYNC((($Actor)self), (($Cont)linesQ_L_8procG_new(self, cb))));\n}\nB_Msg linesQ_ApaD_notice (linesQ_Apa self, B_int i) {\n    return ((B_Msg)$ASYNC((($Actor)self), (($Cont)linesQ_L_9procG_new(self, i))));\n}\nvoid linesQ_ApaD___serialize__ (linesQ_Apa self, $Serial$state state) {\n    $ActorG_methods.__serialize__(($Actor)self, state);\n    $step_serialize(self->apa, state);\n    $step_serialize(self->apb, state);\n    $step_serialize(self->y, state);\n    $step_serialize(self->z, state);\n}\nlinesQ_Apa linesQ_ApaD___deserialize__ (linesQ_Apa self, $Serial$state state) {\n    if (!self) {\n        if (!state) {\n            self = acton_malloc(sizeof(struct linesQ_Apa));\n            self->$class = &linesQ_ApaG_methods;\n            return self;\n        }\n        self = $DNEW(linesQ_Apa, state);\n    }\n    $ActorG_methods.__deserialize__(($Actor)self, state);\n    self->apa = $step_deserialize(state);\n    self->apb = $step_deserialize(state);\n    self->y = $step_deserialize(state);\n    self->z = $step_deserialize(state);\n    return self;\n}\nvoid linesQ_ApaD_GCfinalizer (void *obj, void *cdata) {\n    linesQ_Apa self = (linesQ_Apa)obj;\n    self->$class->__cleanup__(self);\n}\n$R linesQ_ApaG_new($Cont G_1) {\n    linesQ_Apa $tmp = acton_malloc(sizeof(struct linesQ_Apa));\n    $tmp->$class = &linesQ_ApaG_methods;\n    return linesQ_ApaG_methods.__init__($tmp, $CONSTCONT($tmp, G_1));\n}\nstruct linesQ_ApaG_class linesQ_ApaG_methods;\n$R linesQ_BepaD___init__ (linesQ_Bepa self, $Cont C_cont) {\n    #line 25 \"test/src/lines.act\"\n    ((B_NoneType (*) (B_tuple, B_str, B_str, B_bool, B_bool))B_print)($NEWTUPLE(1, to$str(\"Bepa\")), B_None, B_None, B_None, B_None);\n    return $R_CONT(C_cont, B_None);\n}\n#line 22 \"test/src/lines.act\"\n$R linesQ_BepaD_callbackG_local (linesQ_Bepa self, $Cont C_cont, B_int i) {\n    #line 23 \"test/src/lines.act\"\n    ((B_NoneType (*) (B_tuple, B_str, B_str, B_bool, B_bool))B_print)($NEWTUPLE(2, to$str(\"callback\"), i), B_None, B_None, B_None, B_None);\n    int64_t U_10N_2tmp = (((B_int)i)->val + 1LL);\n    return $R_CONT(C_cont, toB_int(U_10N_2tmp));\n}\nB_Msg linesQ_BepaD_callback (linesQ_Bepa self, B_int i) {\n    return ((B_Msg)$ASYNC((($Actor)self), (($Cont)linesQ_L_10procG_new(self, i))));\n}\nvoid linesQ_BepaD___serialize__ (linesQ_Bepa self, $Serial$state state) {\n    $ActorG_methods.__serialize__(($Actor)self, state);\n}\nlinesQ_Bepa linesQ_BepaD___deserialize__ (linesQ_Bepa self, $Serial$state state) {\n    if (!self) {\n        if (!state) {\n            self = acton_malloc(sizeof(struct linesQ_Bepa));\n            self->$class = &linesQ_BepaG_methods;\n            return self;\n        }\n        self = $DNEW(linesQ_Bepa, state);\n    }\n    $ActorG_methods.__deserialize__(($Actor)self, state);\n    return self;\n}\nvoid linesQ_BepaD_GCfinalizer (void *obj, void *cdata) {\n    linesQ_Bepa self = (linesQ_Bepa)obj;\n    self->$class->__cleanup__(self);\n}\n$R linesQ_BepaG_new($Cont G_1) {\n    linesQ_Bepa $tmp = acton_malloc(sizeof(struct linesQ_Bepa));\n    $tmp->$class = &linesQ_BepaG_methods;\n    return linesQ_BepaG_methods.__init__($tmp, $CONSTCONT($tmp, G_1));\n}\nstruct linesQ_BepaG_class linesQ_BepaG_methods;\n$R linesQ_mainD___init__ (linesQ_main self, $Cont C_cont, B_Env env) {\n    self->env = env;\n    return linesQ_ApaG_newact((($Cont)linesQ_L_23ContG_new(self, C_cont)));\n}\n#line 28 \"test/src/lines.act\"\n$R linesQ_mainD_myprocG_local (linesQ_main self, $Cont C_cont, B_int i) {\n    #line 29 \"test/src/lines.act\"\n    ((B_NoneType (*) (B_tuple, B_str, B_str, B_bool, B_bool))B_print)($NEWTUPLE(2, to$str(\"myproc\"), i), B_None, B_None, B_None, B_None);\n    #line 30 \"test/src/lines.act\"\n    if (((B_bool)((B_bool (*) (B_Eq, B_int, B_int))linesQ_W_Apa_331->$class->__eq__)(linesQ_W_Apa_331, i, toB_int(2LL)))->val) {\n        #line 31 \"test/src/lines.act\"\n        ((B_Msg (*) (B_Env, B_int))self->env->$class->exit)(self->env, toB_int(0LL));\n    }\n    return $R_CONT(C_cont, i);\n}\n#line 92 \"test/src/lines.act\"\n$R linesQ_mainD_nopG_local (linesQ_main self, $Cont C_cont) {\n    #line 93 \"test/src/lines.act\"\n    return $R_CONT(C_cont, B_None);\n}\nB_Msg linesQ_mainD_myproc (linesQ_main self, B_int i) {\n    return ((B_Msg)$ASYNC((($Actor)self), (($Cont)linesQ_L_24procG_new(self, i))));\n}\nB_Msg linesQ_mainD_nop (linesQ_main self) {\n    return $ASYNC((($Actor)self), (($Cont)linesQ_L_25procG_new(self)));\n}\nvoid linesQ_mainD___serialize__ (linesQ_main self, $Serial$state state) {\n    $ActorG_methods.__serialize__(($Actor)self, state);\n    $step_serialize(self->env, state);\n    $step_serialize(self->a, state);\n    $step_serialize(self->b, state);\n    $step_serialize(self->x, state);\n    $step_serialize(self->r, state);\n    $step_serialize(self->v, state);\n    $step_serialize(self->i, state);\n}\nlinesQ_main linesQ_mainD___deserialize__ (linesQ_main self, $Serial$state state) {\n    if (!self) {\n        if (!state) {\n            self = acton_malloc(sizeof(struct linesQ_main));\n            self->$class = &linesQ_mainG_methods;\n            return self;\n        }\n        self = $DNEW(linesQ_main, state);\n    }\n    $ActorG_methods.__deserialize__(($Actor)self, state);\n    self->env = $step_deserialize(state);\n    self->a = $step_deserialize(state);\n    self->b = $step_deserialize(state);\n    self->x = $step_deserialize(state);\n    self->r = $step_deserialize(state);\n    self->v = $step_deserialize(state);\n    self->i = $step_deserialize(state);\n    return self;\n}\nvoid linesQ_mainD_GCfinalizer (void *obj, void *cdata) {\n    linesQ_main self = (linesQ_main)obj;\n    self->$class->__cleanup__(self);\n}\n$R linesQ_mainG_new($Cont G_1, B_Env G_2) {\n    linesQ_main $tmp = acton_malloc(sizeof(struct linesQ_main));\n    $tmp->$class = &linesQ_mainG_methods;\n    return linesQ_mainG_methods.__init__($tmp, $CONSTCONT($tmp, G_1), G_2);\n}\nstruct linesQ_mainG_class linesQ_mainG_methods;\n$R linesQ_ApaG_newact ($Cont C_cont) {\n    linesQ_Apa G_act = $NEWACTOR(linesQ_Apa);\n    if ((void*)G_act->$class->__cleanup__ != (void*)$ActorD___cleanup__) $InstallFinalizer(G_act, linesQ_ApaD_GCfinalizer);\n    return $AWAIT((($Cont)linesQ_L_27ContG_new(C_cont, G_act)), $ASYNC((($Actor)G_act), (($Cont)linesQ_L_28procG_new(G_act))));\n}\n$R linesQ_BepaG_newact ($Cont C_cont) {\n    linesQ_Bepa G_act = $NEWACTOR(linesQ_Bepa);\n    if ((void*)G_act->$class->__cleanup__ != (void*)$ActorD___cleanup__) $InstallFinalizer(G_act, linesQ_BepaD_GCfinalizer);\n    return $AWAIT((($Cont)linesQ_L_30ContG_new(C_cont, G_act)), $ASYNC((($Actor)G_act), (($Cont)linesQ_L_31procG_new(G_act))));\n}\n$R linesQ_mainG_newact ($Cont C_cont, B_Env env) {\n    linesQ_main G_act = $NEWACTOR(linesQ_main);\n    if ((void*)G_act->$class->__cleanup__ != (void*)$ActorD___cleanup__) $InstallFinalizer(G_act, linesQ_mainD_GCfinalizer);\n    return $AWAIT((($Cont)linesQ_L_33ContG_new(C_cont, G_act)), $ASYNC((($Actor)G_act), (($Cont)linesQ_L_34procG_new(G_act, env))));\n}\nint linesQ_done$ = 0;\nvoid linesQ___init__ () {\n    if (linesQ_done$) return;\n    linesQ_done$ = 1;\n    {\n        linesQ_L_2ContG_methods.$GCINFO = \"linesQ_L_2Cont\";\n        linesQ_L_2ContG_methods.$superclass = ($SuperG_class)&$ContG_methods;\n        linesQ_L_2ContG_methods.__bool__ = (B_bool (*) (linesQ_L_2Cont))B_valueG_methods.__bool__;\n        linesQ_L_2ContG_methods.__str__ = (B_str (*) (linesQ_L_2Cont))B_valueG_methods.__str__;\n        linesQ_L_2ContG_methods.__repr__ = (B_str (*) (linesQ_L_2Cont))B_valueG_methods.__repr__;\n        linesQ_L_2ContG_methods.__init__ = linesQ_L_2ContD___init__;\n        linesQ_L_2ContG_methods.__call__ = linesQ_L_2ContD___call__;\n        linesQ_L_2ContG_methods.__serialize__ = linesQ_L_2ContD___serialize__;\n        linesQ_L_2ContG_methods.__deserialize__ = linesQ_L_2ContD___deserialize__;\n        $register(&linesQ_L_2ContG_methods);\n    }\n    {\n        linesQ_L_4actionG_methods.$GCINFO = \"linesQ_L_4action\";\n        linesQ_L_4actionG_methods.$superclass = ($SuperG_class)&$actionG_methods;\n        linesQ_L_4actionG_methods.__bool__ = (B_bool (*) (linesQ_L_4action))B_valueG_methods.__bool__;\n        linesQ_L_4actionG_methods.__str__ = (B_str (*) (linesQ_L_4action))B_valueG_methods.__str__;\n        linesQ_L_4actionG_methods.__repr__ = (B_str (*) (linesQ_L_4action))B_valueG_methods.__repr__;\n        linesQ_L_4actionG_methods.__init__ = linesQ_L_4actionD___init__;\n        linesQ_L_4actionG_methods.__call__ = linesQ_L_4actionD___call__;\n        linesQ_L_4actionG_methods.__exec__ = linesQ_L_4actionD___exec__;\n        linesQ_L_4actionG_methods.__asyn__ = linesQ_L_4actionD___asyn__;\n        linesQ_L_4actionG_methods.__serialize__ = linesQ_L_4actionD___serialize__;\n        linesQ_L_4actionG_methods.__deserialize__ = linesQ_L_4actionD___deserialize__;\n        $register(&linesQ_L_4actionG_methods);\n    }\n    {\n        linesQ_L_6ContG_methods.$GCINFO = \"linesQ_L_6Cont\";\n        linesQ_L_6ContG_methods.$superclass = ($SuperG_class)&$ContG_methods;\n        linesQ_L_6ContG_methods.__bool__ = (B_bool (*) (linesQ_L_6Cont))B_valueG_methods.__bool__;\n        linesQ_L_6ContG_methods.__str__ = (B_str (*) (linesQ_L_6Cont))B_valueG_methods.__str__;\n        linesQ_L_6ContG_methods.__repr__ = (B_str (*) (linesQ_L_6Cont))B_valueG_methods.__repr__;\n        linesQ_L_6ContG_methods.__init__ = linesQ_L_6ContD___init__;\n        linesQ_L_6ContG_methods.__call__ = linesQ_L_6ContD___call__;\n        linesQ_L_6ContG_methods.__serialize__ = linesQ_L_6ContD___serialize__;\n        linesQ_L_6ContG_methods.__deserialize__ = linesQ_L_6ContD___deserialize__;\n        $register(&linesQ_L_6ContG_methods);\n    }\n    {\n        linesQ_L_7procG_methods.$GCINFO = \"linesQ_L_7proc\";\n        linesQ_L_7procG_methods.$superclass = ($SuperG_class)&$procG_methods;\n        linesQ_L_7procG_methods.__bool__ = (B_bool (*) (linesQ_L_7proc))B_valueG_methods.__bool__;\n        linesQ_L_7procG_methods.__str__ = (B_str (*) (linesQ_L_7proc))B_valueG_methods.__str__;\n        linesQ_L_7procG_methods.__repr__ = (B_str (*) (linesQ_L_7proc))B_valueG_methods.__repr__;\n        linesQ_L_7procG_methods.__init__ = linesQ_L_7procD___init__;\n        linesQ_L_7procG_methods.__call__ = linesQ_L_7procD___call__;\n        linesQ_L_7procG_methods.__exec__ = linesQ_L_7procD___exec__;\n        linesQ_L_7procG_methods.__serialize__ = linesQ_L_7procD___serialize__;\n        linesQ_L_7procG_methods.__deserialize__ = linesQ_L_7procD___deserialize__;\n        $register(&linesQ_L_7procG_methods);\n    }\n    {\n        linesQ_L_8procG_methods.$GCINFO = \"linesQ_L_8proc\";\n        linesQ_L_8procG_methods.$superclass = ($SuperG_class)&$procG_methods;\n        linesQ_L_8procG_methods.__bool__ = (B_bool (*) (linesQ_L_8proc))B_valueG_methods.__bool__;\n        linesQ_L_8procG_methods.__str__ = (B_str (*) (linesQ_L_8proc))B_valueG_methods.__str__;\n        linesQ_L_8procG_methods.__repr__ = (B_str (*) (linesQ_L_8proc))B_valueG_methods.__repr__;\n        linesQ_L_8procG_methods.__init__ = linesQ_L_8procD___init__;\n        linesQ_L_8procG_methods.__call__ = linesQ_L_8procD___call__;\n        linesQ_L_8procG_methods.__exec__ = linesQ_L_8procD___exec__;\n        linesQ_L_8procG_methods.__serialize__ = linesQ_L_8procD___serialize__;\n        linesQ_L_8procG_methods.__deserialize__ = linesQ_L_8procD___deserialize__;\n        $register(&linesQ_L_8procG_methods);\n    }\n    {\n        linesQ_L_9procG_methods.$GCINFO = \"linesQ_L_9proc\";\n        linesQ_L_9procG_methods.$superclass = ($SuperG_class)&$procG_methods;\n        linesQ_L_9procG_methods.__bool__ = (B_bool (*) (linesQ_L_9proc))B_valueG_methods.__bool__;\n        linesQ_L_9procG_methods.__str__ = (B_str (*) (linesQ_L_9proc))B_valueG_methods.__str__;\n        linesQ_L_9procG_methods.__repr__ = (B_str (*) (linesQ_L_9proc))B_valueG_methods.__repr__;\n        linesQ_L_9procG_methods.__init__ = linesQ_L_9procD___init__;\n        linesQ_L_9procG_methods.__call__ = linesQ_L_9procD___call__;\n        linesQ_L_9procG_methods.__exec__ = linesQ_L_9procD___exec__;\n        linesQ_L_9procG_methods.__serialize__ = linesQ_L_9procD___serialize__;\n        linesQ_L_9procG_methods.__deserialize__ = linesQ_L_9procD___deserialize__;\n        $register(&linesQ_L_9procG_methods);\n    }\n    {\n        linesQ_L_10procG_methods.$GCINFO = \"linesQ_L_10proc\";\n        linesQ_L_10procG_methods.$superclass = ($SuperG_class)&$procG_methods;\n        linesQ_L_10procG_methods.__bool__ = (B_bool (*) (linesQ_L_10proc))B_valueG_methods.__bool__;\n        linesQ_L_10procG_methods.__str__ = (B_str (*) (linesQ_L_10proc))B_valueG_methods.__str__;\n        linesQ_L_10procG_methods.__repr__ = (B_str (*) (linesQ_L_10proc))B_valueG_methods.__repr__;\n        linesQ_L_10procG_methods.__init__ = linesQ_L_10procD___init__;\n        linesQ_L_10procG_methods.__call__ = linesQ_L_10procD___call__;\n        linesQ_L_10procG_methods.__exec__ = linesQ_L_10procD___exec__;\n        linesQ_L_10procG_methods.__serialize__ = linesQ_L_10procD___serialize__;\n        linesQ_L_10procG_methods.__deserialize__ = linesQ_L_10procD___deserialize__;\n        $register(&linesQ_L_10procG_methods);\n    }\n    {\n        linesQ_L_14actionG_methods.$GCINFO = \"linesQ_L_14action\";\n        linesQ_L_14actionG_methods.$superclass = ($SuperG_class)&$actionG_methods;\n        linesQ_L_14actionG_methods.__bool__ = (B_bool (*) (linesQ_L_14action))B_valueG_methods.__bool__;\n        linesQ_L_14actionG_methods.__str__ = (B_str (*) (linesQ_L_14action))B_valueG_methods.__str__;\n        linesQ_L_14actionG_methods.__repr__ = (B_str (*) (linesQ_L_14action))B_valueG_methods.__repr__;\n        linesQ_L_14actionG_methods.__init__ = linesQ_L_14actionD___init__;\n        linesQ_L_14actionG_methods.__call__ = linesQ_L_14actionD___call__;\n        linesQ_L_14actionG_methods.__exec__ = linesQ_L_14actionD___exec__;\n        linesQ_L_14actionG_methods.__asyn__ = linesQ_L_14actionD___asyn__;\n        linesQ_L_14actionG_methods.__serialize__ = linesQ_L_14actionD___serialize__;\n        linesQ_L_14actionG_methods.__deserialize__ = linesQ_L_14actionD___deserialize__;\n        $register(&linesQ_L_14actionG_methods);\n    }\n    {\n        linesQ_L_16actionG_methods.$GCINFO = \"linesQ_L_16action\";\n        linesQ_L_16actionG_methods.$superclass = ($SuperG_class)&$actionG_methods;\n        linesQ_L_16actionG_methods.__bool__ = (B_bool (*) (linesQ_L_16action))B_valueG_methods.__bool__;\n        linesQ_L_16actionG_methods.__str__ = (B_str (*) (linesQ_L_16action))B_valueG_methods.__str__;\n        linesQ_L_16actionG_methods.__repr__ = (B_str (*) (linesQ_L_16action))B_valueG_methods.__repr__;\n        linesQ_L_16actionG_methods.__init__ = linesQ_L_16actionD___init__;\n        linesQ_L_16actionG_methods.__call__ = linesQ_L_16actionD___call__;\n        linesQ_L_16actionG_methods.__exec__ = linesQ_L_16actionD___exec__;\n        linesQ_L_16actionG_methods.__asyn__ = linesQ_L_16actionD___asyn__;\n        linesQ_L_16actionG_methods.__serialize__ = linesQ_L_16actionD___serialize__;\n        linesQ_L_16actionG_methods.__deserialize__ = linesQ_L_16actionD___deserialize__;\n        $register(&linesQ_L_16actionG_methods);\n    }\n    {\n        linesQ_L_19actionG_methods.$GCINFO = \"linesQ_L_19action\";\n        linesQ_L_19actionG_methods.$superclass = ($SuperG_class)&$actionG_methods;\n        linesQ_L_19actionG_methods.__bool__ = (B_bool (*) (linesQ_L_19action))B_valueG_methods.__bool__;\n        linesQ_L_19actionG_methods.__str__ = (B_str (*) (linesQ_L_19action))B_valueG_methods.__str__;\n        linesQ_L_19actionG_methods.__repr__ = (B_str (*) (linesQ_L_19action))B_valueG_methods.__repr__;\n        linesQ_L_19actionG_methods.__init__ = linesQ_L_19actionD___init__;\n        linesQ_L_19actionG_methods.__call__ = linesQ_L_19actionD___call__;\n        linesQ_L_19actionG_methods.__exec__ = linesQ_L_19actionD___exec__;\n        linesQ_L_19actionG_methods.__asyn__ = linesQ_L_19actionD___asyn__;\n        linesQ_L_19actionG_methods.__serialize__ = linesQ_L_19actionD___serialize__;\n        linesQ_L_19actionG_methods.__deserialize__ = linesQ_L_19actionD___deserialize__;\n        $register(&linesQ_L_19actionG_methods);\n    }\n    {\n        linesQ_L_20procG_methods.$GCINFO = \"linesQ_L_20proc\";\n        linesQ_L_20procG_methods.$superclass = ($SuperG_class)&$procG_methods;\n        linesQ_L_20procG_methods.__bool__ = (B_bool (*) (linesQ_L_20proc))B_valueG_methods.__bool__;\n        linesQ_L_20procG_methods.__str__ = (B_str (*) (linesQ_L_20proc))B_valueG_methods.__str__;\n        linesQ_L_20procG_methods.__repr__ = (B_str (*) (linesQ_L_20proc))B_valueG_methods.__repr__;\n        linesQ_L_20procG_methods.__init__ = linesQ_L_20procD___init__;\n        linesQ_L_20procG_methods.__call__ = linesQ_L_20procD___call__;\n        linesQ_L_20procG_methods.__exec__ = linesQ_L_20procD___exec__;\n        linesQ_L_20procG_methods.__serialize__ = linesQ_L_20procD___serialize__;\n        linesQ_L_20procG_methods.__deserialize__ = linesQ_L_20procD___deserialize__;\n        $register(&linesQ_L_20procG_methods);\n    }\n    {\n        linesQ_L_21ContG_methods.$GCINFO = \"linesQ_L_21Cont\";\n        linesQ_L_21ContG_methods.$superclass = ($SuperG_class)&$ContG_methods;\n        linesQ_L_21ContG_methods.__bool__ = (B_bool (*) (linesQ_L_21Cont))B_valueG_methods.__bool__;\n        linesQ_L_21ContG_methods.__str__ = (B_str (*) (linesQ_L_21Cont))B_valueG_methods.__str__;\n        linesQ_L_21ContG_methods.__repr__ = (B_str (*) (linesQ_L_21Cont))B_valueG_methods.__repr__;\n        linesQ_L_21ContG_methods.__init__ = linesQ_L_21ContD___init__;\n        linesQ_L_21ContG_methods.__call__ = linesQ_L_21ContD___call__;\n        linesQ_L_21ContG_methods.__serialize__ = linesQ_L_21ContD___serialize__;\n        linesQ_L_21ContG_methods.__deserialize__ = linesQ_L_21ContD___deserialize__;\n        $register(&linesQ_L_21ContG_methods);\n    }\n    {\n        linesQ_L_22ContG_methods.$GCINFO = \"linesQ_L_22Cont\";\n        linesQ_L_22ContG_methods.$superclass = ($SuperG_class)&$ContG_methods;\n        linesQ_L_22ContG_methods.__bool__ = (B_bool (*) (linesQ_L_22Cont))B_valueG_methods.__bool__;\n        linesQ_L_22ContG_methods.__str__ = (B_str (*) (linesQ_L_22Cont))B_valueG_methods.__str__;\n        linesQ_L_22ContG_methods.__repr__ = (B_str (*) (linesQ_L_22Cont))B_valueG_methods.__repr__;\n        linesQ_L_22ContG_methods.__init__ = linesQ_L_22ContD___init__;\n        linesQ_L_22ContG_methods.__call__ = linesQ_L_22ContD___call__;\n        linesQ_L_22ContG_methods.__serialize__ = linesQ_L_22ContD___serialize__;\n        linesQ_L_22ContG_methods.__deserialize__ = linesQ_L_22ContD___deserialize__;\n        $register(&linesQ_L_22ContG_methods);\n    }\n    {\n        linesQ_L_23ContG_methods.$GCINFO = \"linesQ_L_23Cont\";\n        linesQ_L_23ContG_methods.$superclass = ($SuperG_class)&$ContG_methods;\n        linesQ_L_23ContG_methods.__bool__ = (B_bool (*) (linesQ_L_23Cont))B_valueG_methods.__bool__;\n        linesQ_L_23ContG_methods.__str__ = (B_str (*) (linesQ_L_23Cont))B_valueG_methods.__str__;\n        linesQ_L_23ContG_methods.__repr__ = (B_str (*) (linesQ_L_23Cont))B_valueG_methods.__repr__;\n        linesQ_L_23ContG_methods.__init__ = linesQ_L_23ContD___init__;\n        linesQ_L_23ContG_methods.__call__ = linesQ_L_23ContD___call__;\n        linesQ_L_23ContG_methods.__serialize__ = linesQ_L_23ContD___serialize__;\n        linesQ_L_23ContG_methods.__deserialize__ = linesQ_L_23ContD___deserialize__;\n        $register(&linesQ_L_23ContG_methods);\n    }\n    {\n        linesQ_L_24procG_methods.$GCINFO = \"linesQ_L_24proc\";\n        linesQ_L_24procG_methods.$superclass = ($SuperG_class)&$procG_methods;\n        linesQ_L_24procG_methods.__bool__ = (B_bool (*) (linesQ_L_24proc))B_valueG_methods.__bool__;\n        linesQ_L_24procG_methods.__str__ = (B_str (*) (linesQ_L_24proc))B_valueG_methods.__str__;\n        linesQ_L_24procG_methods.__repr__ = (B_str (*) (linesQ_L_24proc))B_valueG_methods.__repr__;\n        linesQ_L_24procG_methods.__init__ = linesQ_L_24procD___init__;\n        linesQ_L_24procG_methods.__call__ = linesQ_L_24procD___call__;\n        linesQ_L_24procG_methods.__exec__ = linesQ_L_24procD___exec__;\n        linesQ_L_24procG_methods.__serialize__ = linesQ_L_24procD___serialize__;\n        linesQ_L_24procG_methods.__deserialize__ = linesQ_L_24procD___deserialize__;\n        $register(&linesQ_L_24procG_methods);\n    }\n    {\n        linesQ_L_25procG_methods.$GCINFO = \"linesQ_L_25proc\";\n        linesQ_L_25procG_methods.$superclass = ($SuperG_class)&$procG_methods;\n        linesQ_L_25procG_methods.__bool__ = (B_bool (*) (linesQ_L_25proc))B_valueG_methods.__bool__;\n        linesQ_L_25procG_methods.__str__ = (B_str (*) (linesQ_L_25proc))B_valueG_methods.__str__;\n        linesQ_L_25procG_methods.__repr__ = (B_str (*) (linesQ_L_25proc))B_valueG_methods.__repr__;\n        linesQ_L_25procG_methods.__init__ = linesQ_L_25procD___init__;\n        linesQ_L_25procG_methods.__call__ = linesQ_L_25procD___call__;\n        linesQ_L_25procG_methods.__exec__ = linesQ_L_25procD___exec__;\n        linesQ_L_25procG_methods.__serialize__ = linesQ_L_25procD___serialize__;\n        linesQ_L_25procG_methods.__deserialize__ = linesQ_L_25procD___deserialize__;\n        $register(&linesQ_L_25procG_methods);\n    }\n    {\n        linesQ_L_27ContG_methods.$GCINFO = \"linesQ_L_27Cont\";\n        linesQ_L_27ContG_methods.$superclass = ($SuperG_class)&$ContG_methods;\n        linesQ_L_27ContG_methods.__bool__ = (B_bool (*) (linesQ_L_27Cont))B_valueG_methods.__bool__;\n        linesQ_L_27ContG_methods.__str__ = (B_str (*) (linesQ_L_27Cont))B_valueG_methods.__str__;\n        linesQ_L_27ContG_methods.__repr__ = (B_str (*) (linesQ_L_27Cont))B_valueG_methods.__repr__;\n        linesQ_L_27ContG_methods.__init__ = linesQ_L_27ContD___init__;\n        linesQ_L_27ContG_methods.__call__ = linesQ_L_27ContD___call__;\n        linesQ_L_27ContG_methods.__serialize__ = linesQ_L_27ContD___serialize__;\n        linesQ_L_27ContG_methods.__deserialize__ = linesQ_L_27ContD___deserialize__;\n        $register(&linesQ_L_27ContG_methods);\n    }\n    {\n        linesQ_L_28procG_methods.$GCINFO = \"linesQ_L_28proc\";\n        linesQ_L_28procG_methods.$superclass = ($SuperG_class)&$procG_methods;\n        linesQ_L_28procG_methods.__bool__ = (B_bool (*) (linesQ_L_28proc))B_valueG_methods.__bool__;\n        linesQ_L_28procG_methods.__str__ = (B_str (*) (linesQ_L_28proc))B_valueG_methods.__str__;\n        linesQ_L_28procG_methods.__repr__ = (B_str (*) (linesQ_L_28proc))B_valueG_methods.__repr__;\n        linesQ_L_28procG_methods.__init__ = linesQ_L_28procD___init__;\n        linesQ_L_28procG_methods.__call__ = linesQ_L_28procD___call__;\n        linesQ_L_28procG_methods.__exec__ = linesQ_L_28procD___exec__;\n        linesQ_L_28procG_methods.__serialize__ = linesQ_L_28procD___serialize__;\n        linesQ_L_28procG_methods.__deserialize__ = linesQ_L_28procD___deserialize__;\n        $register(&linesQ_L_28procG_methods);\n    }\n    {\n        linesQ_L_30ContG_methods.$GCINFO = \"linesQ_L_30Cont\";\n        linesQ_L_30ContG_methods.$superclass = ($SuperG_class)&$ContG_methods;\n        linesQ_L_30ContG_methods.__bool__ = (B_bool (*) (linesQ_L_30Cont))B_valueG_methods.__bool__;\n        linesQ_L_30ContG_methods.__str__ = (B_str (*) (linesQ_L_30Cont))B_valueG_methods.__str__;\n        linesQ_L_30ContG_methods.__repr__ = (B_str (*) (linesQ_L_30Cont))B_valueG_methods.__repr__;\n        linesQ_L_30ContG_methods.__init__ = linesQ_L_30ContD___init__;\n        linesQ_L_30ContG_methods.__call__ = linesQ_L_30ContD___call__;\n        linesQ_L_30ContG_methods.__serialize__ = linesQ_L_30ContD___serialize__;\n        linesQ_L_30ContG_methods.__deserialize__ = linesQ_L_30ContD___deserialize__;\n        $register(&linesQ_L_30ContG_methods);\n    }\n    {\n        linesQ_L_31procG_methods.$GCINFO = \"linesQ_L_31proc\";\n        linesQ_L_31procG_methods.$superclass = ($SuperG_class)&$procG_methods;\n        linesQ_L_31procG_methods.__bool__ = (B_bool (*) (linesQ_L_31proc))B_valueG_methods.__bool__;\n        linesQ_L_31procG_methods.__str__ = (B_str (*) (linesQ_L_31proc))B_valueG_methods.__str__;\n        linesQ_L_31procG_methods.__repr__ = (B_str (*) (linesQ_L_31proc))B_valueG_methods.__repr__;\n        linesQ_L_31procG_methods.__init__ = linesQ_L_31procD___init__;\n        linesQ_L_31procG_methods.__call__ = linesQ_L_31procD___call__;\n        linesQ_L_31procG_methods.__exec__ = linesQ_L_31procD___exec__;\n        linesQ_L_31procG_methods.__serialize__ = linesQ_L_31procD___serialize__;\n        linesQ_L_31procG_methods.__deserialize__ = linesQ_L_31procD___deserialize__;\n        $register(&linesQ_L_31procG_methods);\n    }\n    {\n        linesQ_L_33ContG_methods.$GCINFO = \"linesQ_L_33Cont\";\n        linesQ_L_33ContG_methods.$superclass = ($SuperG_class)&$ContG_methods;\n        linesQ_L_33ContG_methods.__bool__ = (B_bool (*) (linesQ_L_33Cont))B_valueG_methods.__bool__;\n        linesQ_L_33ContG_methods.__str__ = (B_str (*) (linesQ_L_33Cont))B_valueG_methods.__str__;\n        linesQ_L_33ContG_methods.__repr__ = (B_str (*) (linesQ_L_33Cont))B_valueG_methods.__repr__;\n        linesQ_L_33ContG_methods.__init__ = linesQ_L_33ContD___init__;\n        linesQ_L_33ContG_methods.__call__ = linesQ_L_33ContD___call__;\n        linesQ_L_33ContG_methods.__serialize__ = linesQ_L_33ContD___serialize__;\n        linesQ_L_33ContG_methods.__deserialize__ = linesQ_L_33ContD___deserialize__;\n        $register(&linesQ_L_33ContG_methods);\n    }\n    {\n        linesQ_L_34procG_methods.$GCINFO = \"linesQ_L_34proc\";\n        linesQ_L_34procG_methods.$superclass = ($SuperG_class)&$procG_methods;\n        linesQ_L_34procG_methods.__bool__ = (B_bool (*) (linesQ_L_34proc))B_valueG_methods.__bool__;\n        linesQ_L_34procG_methods.__str__ = (B_str (*) (linesQ_L_34proc))B_valueG_methods.__str__;\n        linesQ_L_34procG_methods.__repr__ = (B_str (*) (linesQ_L_34proc))B_valueG_methods.__repr__;\n        linesQ_L_34procG_methods.__init__ = linesQ_L_34procD___init__;\n        linesQ_L_34procG_methods.__call__ = linesQ_L_34procD___call__;\n        linesQ_L_34procG_methods.__exec__ = linesQ_L_34procD___exec__;\n        linesQ_L_34procG_methods.__serialize__ = linesQ_L_34procD___serialize__;\n        linesQ_L_34procG_methods.__deserialize__ = linesQ_L_34procD___deserialize__;\n        $register(&linesQ_L_34procG_methods);\n    }\n    {\n        linesQ_ApaG_methods.$GCINFO = \"linesQ_Apa\";\n        linesQ_ApaG_methods.$superclass = ($SuperG_class)&$ActorG_methods;\n        linesQ_ApaG_methods.__bool__ = (B_bool (*) (linesQ_Apa))$ActorG_methods.__bool__;\n        linesQ_ApaG_methods.__str__ = (B_str (*) (linesQ_Apa))$ActorG_methods.__str__;\n        linesQ_ApaG_methods.__repr__ = (B_str (*) (linesQ_Apa))$ActorG_methods.__repr__;\n        linesQ_ApaG_methods.__resume__ = (B_NoneType (*) (linesQ_Apa))$ActorG_methods.__resume__;\n        linesQ_ApaG_methods.__cleanup__ = (B_NoneType (*) (linesQ_Apa))$ActorG_methods.__cleanup__;\n        linesQ_ApaG_methods.__init__ = linesQ_ApaD___init__;\n        linesQ_ApaG_methods.setupG_local = linesQ_ApaD_setupG_local;\n        linesQ_ApaG_methods.computeG_local = linesQ_ApaD_computeG_local;\n        linesQ_ApaG_methods.noticeG_local = linesQ_ApaD_noticeG_local;\n        linesQ_ApaG_methods.setup = linesQ_ApaD_setup;\n        linesQ_ApaG_methods.compute = linesQ_ApaD_compute;\n        linesQ_ApaG_methods.notice = linesQ_ApaD_notice;\n        linesQ_ApaG_methods.__serialize__ = linesQ_ApaD___serialize__;\n        linesQ_ApaG_methods.__deserialize__ = linesQ_ApaD___deserialize__;\n        $register(&linesQ_ApaG_methods);\n    }\n    {\n        linesQ_BepaG_methods.$GCINFO = \"linesQ_Bepa\";\n        linesQ_BepaG_methods.$superclass = ($SuperG_class)&$ActorG_methods;\n        linesQ_BepaG_methods.__bool__ = (B_bool (*) (linesQ_Bepa))$ActorG_methods.__bool__;\n        linesQ_BepaG_methods.__str__ = (B_str (*) (linesQ_Bepa))$ActorG_methods.__str__;\n        linesQ_BepaG_methods.__repr__ = (B_str (*) (linesQ_Bepa))$ActorG_methods.__repr__;\n        linesQ_BepaG_methods.__resume__ = (B_NoneType (*) (linesQ_Bepa))$ActorG_methods.__resume__;\n        linesQ_BepaG_methods.__cleanup__ = (B_NoneType (*) (linesQ_Bepa))$ActorG_methods.__cleanup__;\n        linesQ_BepaG_methods.__init__ = linesQ_BepaD___init__;\n        linesQ_BepaG_methods.callbackG_local = linesQ_BepaD_callbackG_local;\n        linesQ_BepaG_methods.callback = linesQ_BepaD_callback;\n        linesQ_BepaG_methods.__serialize__ = linesQ_BepaD___serialize__;\n        linesQ_BepaG_methods.__deserialize__ = linesQ_BepaD___deserialize__;\n        $register(&linesQ_BepaG_methods);\n    }\n    {\n        linesQ_mainG_methods.$GCINFO = \"linesQ_main\";\n        linesQ_mainG_methods.$superclass = ($SuperG_class)&$ActorG_methods;\n        linesQ_mainG_methods.__bool__ = (B_bool (*) (linesQ_main))$ActorG_methods.__bool__;\n        linesQ_mainG_methods.__str__ = (B_str (*) (linesQ_main))$ActorG_methods.__str__;\n        linesQ_mainG_methods.__repr__ = (B_str (*) (linesQ_main))$ActorG_methods.__repr__;\n        linesQ_mainG_methods.__resume__ = (B_NoneType (*) (linesQ_main))$ActorG_methods.__resume__;\n        linesQ_mainG_methods.__cleanup__ = (B_NoneType (*) (linesQ_main))$ActorG_methods.__cleanup__;\n        linesQ_mainG_methods.__init__ = linesQ_mainD___init__;\n        linesQ_mainG_methods.myprocG_local = linesQ_mainD_myprocG_local;\n        linesQ_mainG_methods.nopG_local = linesQ_mainD_nopG_local;\n        linesQ_mainG_methods.myproc = linesQ_mainD_myproc;\n        linesQ_mainG_methods.nop = linesQ_mainD_nop;\n        linesQ_mainG_methods.__serialize__ = linesQ_mainD___serialize__;\n        linesQ_mainG_methods.__deserialize__ = linesQ_mainD___deserialize__;\n        $register(&linesQ_mainG_methods);\n    }\n    B_Eq W_Apa_1097 = (B_Eq)B_OrdD_intG_witness;\n    linesQ_W_Apa_1097 = W_Apa_1097;\n    B_Eq W_Apa_759 = ((B_Eq)$EqOptG_new(linesQ_W_Apa_1097));\n    linesQ_W_Apa_759 = W_Apa_759;\n    B_Iterable W_Apa_779 = (B_Iterable)B_SequenceD_listG_witness->W_Collection;\n    linesQ_W_Apa_779 = W_Apa_779;\n    B_Eq W_Apa_331 = ((B_Eq)$EqOptG_new(linesQ_W_Apa_1097));\n    linesQ_W_Apa_331 = W_Apa_331;\n    B_Eq W_Apa_785 = ((B_Eq)$EqOptG_new(linesQ_W_Apa_1097));\n    linesQ_W_Apa_785 = W_Apa_785;\n}"
  },
  {
    "path": "compiler/lib/test/9-codegen/lines.h",
    "content": "/* Acton impl hash: test-hash */\n#pragma once\n#include \"builtin/builtin.h\"\n#include \"rts/rts.h\"\nstruct linesQ_L_2Cont;\nstruct linesQ_L_4action;\nstruct linesQ_L_6Cont;\nstruct linesQ_L_7proc;\nstruct linesQ_L_8proc;\nstruct linesQ_L_9proc;\nstruct linesQ_L_10proc;\nstruct linesQ_L_14action;\nstruct linesQ_L_16action;\nstruct linesQ_L_19action;\nstruct linesQ_L_20proc;\nstruct linesQ_L_21Cont;\nstruct linesQ_L_22Cont;\nstruct linesQ_L_23Cont;\nstruct linesQ_L_24proc;\nstruct linesQ_L_25proc;\nstruct linesQ_L_27Cont;\nstruct linesQ_L_28proc;\nstruct linesQ_L_30Cont;\nstruct linesQ_L_31proc;\nstruct linesQ_L_33Cont;\nstruct linesQ_L_34proc;\nstruct linesQ_Apa;\nstruct linesQ_Bepa;\nstruct linesQ_main;\ntypedef struct linesQ_L_2Cont *linesQ_L_2Cont;\ntypedef struct linesQ_L_4action *linesQ_L_4action;\ntypedef struct linesQ_L_6Cont *linesQ_L_6Cont;\ntypedef struct linesQ_L_7proc *linesQ_L_7proc;\ntypedef struct linesQ_L_8proc *linesQ_L_8proc;\ntypedef struct linesQ_L_9proc *linesQ_L_9proc;\ntypedef struct linesQ_L_10proc *linesQ_L_10proc;\ntypedef struct linesQ_L_14action *linesQ_L_14action;\ntypedef struct linesQ_L_16action *linesQ_L_16action;\ntypedef struct linesQ_L_19action *linesQ_L_19action;\ntypedef struct linesQ_L_20proc *linesQ_L_20proc;\ntypedef struct linesQ_L_21Cont *linesQ_L_21Cont;\ntypedef struct linesQ_L_22Cont *linesQ_L_22Cont;\ntypedef struct linesQ_L_23Cont *linesQ_L_23Cont;\ntypedef struct linesQ_L_24proc *linesQ_L_24proc;\ntypedef struct linesQ_L_25proc *linesQ_L_25proc;\ntypedef struct linesQ_L_27Cont *linesQ_L_27Cont;\ntypedef struct linesQ_L_28proc *linesQ_L_28proc;\ntypedef struct linesQ_L_30Cont *linesQ_L_30Cont;\ntypedef struct linesQ_L_31proc *linesQ_L_31proc;\ntypedef struct linesQ_L_33Cont *linesQ_L_33Cont;\ntypedef struct linesQ_L_34proc *linesQ_L_34proc;\ntypedef struct linesQ_Apa *linesQ_Apa;\ntypedef struct linesQ_Bepa *linesQ_Bepa;\ntypedef struct linesQ_main *linesQ_main;\n$R linesQ_L_1C_1cont (linesQ_Apa, $Cont, B_NoneType);\nstruct linesQ_L_2ContG_class {\n    char *$GCINFO;\n    int $class_id;\n    $SuperG_class $superclass;\n    B_NoneType (*__init__) (linesQ_L_2Cont, linesQ_Apa, $Cont);\n    void (*__serialize__) (linesQ_L_2Cont, $Serial$state);\n    linesQ_L_2Cont (*__deserialize__) (linesQ_L_2Cont, $Serial$state);\n    B_bool (*__bool__) (linesQ_L_2Cont);\n    B_str (*__str__) (linesQ_L_2Cont);\n    B_str (*__repr__) (linesQ_L_2Cont);\n    $R (*__call__) (linesQ_L_2Cont, B_NoneType);\n};\nstruct linesQ_L_2Cont {\n    struct linesQ_L_2ContG_class *$class;\n    linesQ_Apa self;\n    $Cont C_cont;\n};\nstruct linesQ_L_4actionG_class {\n    char *$GCINFO;\n    int $class_id;\n    $SuperG_class $superclass;\n    B_NoneType (*__init__) (linesQ_L_4action, linesQ_Apa);\n    void (*__serialize__) (linesQ_L_4action, $Serial$state);\n    linesQ_L_4action (*__deserialize__) (linesQ_L_4action, $Serial$state);\n    B_bool (*__bool__) (linesQ_L_4action);\n    B_str (*__str__) (linesQ_L_4action);\n    B_str (*__repr__) (linesQ_L_4action);\n    $R (*__call__) (linesQ_L_4action, $Cont, B_int);\n    $R (*__exec__) (linesQ_L_4action, $Cont, B_int);\n    B_Msg (*__asyn__) (linesQ_L_4action, B_int);\n};\nstruct linesQ_L_4action {\n    struct linesQ_L_4actionG_class *$class;\n    linesQ_Apa L_3obj;\n};\n$R linesQ_U_L_5C_3cont ($action, $Cont, int64_t);\n$R linesQ_L_5C_3cont ($action, $Cont, B_int);\nstruct linesQ_L_6ContG_class {\n    char *$GCINFO;\n    int $class_id;\n    $SuperG_class $superclass;\n    B_NoneType (*__init__) (linesQ_L_6Cont, $action, $Cont);\n    void (*__serialize__) (linesQ_L_6Cont, $Serial$state);\n    linesQ_L_6Cont (*__deserialize__) (linesQ_L_6Cont, $Serial$state);\n    B_bool (*__bool__) (linesQ_L_6Cont);\n    B_str (*__str__) (linesQ_L_6Cont);\n    B_str (*__repr__) (linesQ_L_6Cont);\n    $R (*__call__) (linesQ_L_6Cont, B_int);\n};\nstruct linesQ_L_6Cont {\n    struct linesQ_L_6ContG_class *$class;\n    $action cb;\n    $Cont C_cont;\n};\nstruct linesQ_L_7procG_class {\n    char *$GCINFO;\n    int $class_id;\n    $SuperG_class $superclass;\n    B_NoneType (*__init__) (linesQ_L_7proc, linesQ_Apa, $action);\n    void (*__serialize__) (linesQ_L_7proc, $Serial$state);\n    linesQ_L_7proc (*__deserialize__) (linesQ_L_7proc, $Serial$state);\n    B_bool (*__bool__) (linesQ_L_7proc);\n    B_str (*__str__) (linesQ_L_7proc);\n    B_str (*__repr__) (linesQ_L_7proc);\n    $R (*__call__) (linesQ_L_7proc, $Cont);\n    $R (*__exec__) (linesQ_L_7proc, $Cont);\n};\nstruct linesQ_L_7proc {\n    struct linesQ_L_7procG_class *$class;\n    linesQ_Apa self;\n    $action cb;\n};\nstruct linesQ_L_8procG_class {\n    char *$GCINFO;\n    int $class_id;\n    $SuperG_class $superclass;\n    B_NoneType (*__init__) (linesQ_L_8proc, linesQ_Apa, $action);\n    void (*__serialize__) (linesQ_L_8proc, $Serial$state);\n    linesQ_L_8proc (*__deserialize__) (linesQ_L_8proc, $Serial$state);\n    B_bool (*__bool__) (linesQ_L_8proc);\n    B_str (*__str__) (linesQ_L_8proc);\n    B_str (*__repr__) (linesQ_L_8proc);\n    $R (*__call__) (linesQ_L_8proc, $Cont);\n    $R (*__exec__) (linesQ_L_8proc, $Cont);\n};\nstruct linesQ_L_8proc {\n    struct linesQ_L_8procG_class *$class;\n    linesQ_Apa self;\n    $action cb;\n};\nstruct linesQ_L_9procG_class {\n    char *$GCINFO;\n    int $class_id;\n    $SuperG_class $superclass;\n    B_NoneType (*__init__) (linesQ_L_9proc, linesQ_Apa, B_int);\n    void (*__serialize__) (linesQ_L_9proc, $Serial$state);\n    linesQ_L_9proc (*__deserialize__) (linesQ_L_9proc, $Serial$state);\n    B_bool (*__bool__) (linesQ_L_9proc);\n    B_str (*__str__) (linesQ_L_9proc);\n    B_str (*__repr__) (linesQ_L_9proc);\n    $R (*__call__) (linesQ_L_9proc, $Cont);\n    $R (*__exec__) (linesQ_L_9proc, $Cont);\n};\nstruct linesQ_L_9proc {\n    struct linesQ_L_9procG_class *$class;\n    linesQ_Apa self;\n    B_int i;\n};\nstruct linesQ_L_10procG_class {\n    char *$GCINFO;\n    int $class_id;\n    $SuperG_class $superclass;\n    B_NoneType (*__init__) (linesQ_L_10proc, linesQ_Bepa, B_int);\n    void (*__serialize__) (linesQ_L_10proc, $Serial$state);\n    linesQ_L_10proc (*__deserialize__) (linesQ_L_10proc, $Serial$state);\n    B_bool (*__bool__) (linesQ_L_10proc);\n    B_str (*__str__) (linesQ_L_10proc);\n    B_str (*__repr__) (linesQ_L_10proc);\n    $R (*__call__) (linesQ_L_10proc, $Cont);\n    $R (*__exec__) (linesQ_L_10proc, $Cont);\n};\nstruct linesQ_L_10proc {\n    struct linesQ_L_10procG_class *$class;\n    linesQ_Bepa self;\n    B_int i;\n};\nstruct linesQ_L_14actionG_class {\n    char *$GCINFO;\n    int $class_id;\n    $SuperG_class $superclass;\n    B_NoneType (*__init__) (linesQ_L_14action, linesQ_Apa);\n    void (*__serialize__) (linesQ_L_14action, $Serial$state);\n    linesQ_L_14action (*__deserialize__) (linesQ_L_14action, $Serial$state);\n    B_bool (*__bool__) (linesQ_L_14action);\n    B_str (*__str__) (linesQ_L_14action);\n    B_str (*__repr__) (linesQ_L_14action);\n    $R (*__call__) (linesQ_L_14action, $Cont, B_int);\n    $R (*__exec__) (linesQ_L_14action, $Cont, B_int);\n    B_Msg (*__asyn__) (linesQ_L_14action, B_int);\n};\nstruct linesQ_L_14action {\n    struct linesQ_L_14actionG_class *$class;\n    linesQ_Apa L_13obj;\n};\nstruct linesQ_L_16actionG_class {\n    char *$GCINFO;\n    int $class_id;\n    $SuperG_class $superclass;\n    B_NoneType (*__init__) (linesQ_L_16action, linesQ_Bepa);\n    void (*__serialize__) (linesQ_L_16action, $Serial$state);\n    linesQ_L_16action (*__deserialize__) (linesQ_L_16action, $Serial$state);\n    B_bool (*__bool__) (linesQ_L_16action);\n    B_str (*__str__) (linesQ_L_16action);\n    B_str (*__repr__) (linesQ_L_16action);\n    $R (*__call__) (linesQ_L_16action, $Cont, B_int);\n    $R (*__exec__) (linesQ_L_16action, $Cont, B_int);\n    B_Msg (*__asyn__) (linesQ_L_16action, B_int);\n};\nstruct linesQ_L_16action {\n    struct linesQ_L_16actionG_class *$class;\n    linesQ_Bepa L_15obj;\n};\nstruct linesQ_L_19actionG_class {\n    char *$GCINFO;\n    int $class_id;\n    $SuperG_class $superclass;\n    B_NoneType (*__init__) (linesQ_L_19action, linesQ_main);\n    void (*__serialize__) (linesQ_L_19action, $Serial$state);\n    linesQ_L_19action (*__deserialize__) (linesQ_L_19action, $Serial$state);\n    B_bool (*__bool__) (linesQ_L_19action);\n    B_str (*__str__) (linesQ_L_19action);\n    B_str (*__repr__) (linesQ_L_19action);\n    $R (*__call__) (linesQ_L_19action, $Cont, B_int);\n    $R (*__exec__) (linesQ_L_19action, $Cont, B_int);\n    B_Msg (*__asyn__) (linesQ_L_19action, B_int);\n};\nstruct linesQ_L_19action {\n    struct linesQ_L_19actionG_class *$class;\n    linesQ_main L_18obj;\n};\nstruct linesQ_L_20procG_class {\n    char *$GCINFO;\n    int $class_id;\n    $SuperG_class $superclass;\n    B_NoneType (*__init__) (linesQ_L_20proc, linesQ_main);\n    void (*__serialize__) (linesQ_L_20proc, $Serial$state);\n    linesQ_L_20proc (*__deserialize__) (linesQ_L_20proc, $Serial$state);\n    B_bool (*__bool__) (linesQ_L_20proc);\n    B_str (*__str__) (linesQ_L_20proc);\n    B_str (*__repr__) (linesQ_L_20proc);\n    $R (*__call__) (linesQ_L_20proc, $Cont);\n    $R (*__exec__) (linesQ_L_20proc, $Cont);\n};\nstruct linesQ_L_20proc {\n    struct linesQ_L_20procG_class *$class;\n    linesQ_main self;\n};\n$R linesQ_U_1L_17C_9cont (linesQ_main, $Cont, int64_t);\n$R linesQ_L_17C_9cont (linesQ_main, $Cont, B_int);\nstruct linesQ_L_21ContG_class {\n    char *$GCINFO;\n    int $class_id;\n    $SuperG_class $superclass;\n    B_NoneType (*__init__) (linesQ_L_21Cont, linesQ_main, $Cont);\n    void (*__serialize__) (linesQ_L_21Cont, $Serial$state);\n    linesQ_L_21Cont (*__deserialize__) (linesQ_L_21Cont, $Serial$state);\n    B_bool (*__bool__) (linesQ_L_21Cont);\n    B_str (*__str__) (linesQ_L_21Cont);\n    B_str (*__repr__) (linesQ_L_21Cont);\n    $R (*__call__) (linesQ_L_21Cont, B_int);\n};\nstruct linesQ_L_21Cont {\n    struct linesQ_L_21ContG_class *$class;\n    linesQ_main self;\n    $Cont C_cont;\n};\n$R linesQ_L_12C_7cont (linesQ_main, $Cont, linesQ_Bepa);\nstruct linesQ_L_22ContG_class {\n    char *$GCINFO;\n    int $class_id;\n    $SuperG_class $superclass;\n    B_NoneType (*__init__) (linesQ_L_22Cont, linesQ_main, $Cont);\n    void (*__serialize__) (linesQ_L_22Cont, $Serial$state);\n    linesQ_L_22Cont (*__deserialize__) (linesQ_L_22Cont, $Serial$state);\n    B_bool (*__bool__) (linesQ_L_22Cont);\n    B_str (*__str__) (linesQ_L_22Cont);\n    B_str (*__repr__) (linesQ_L_22Cont);\n    $R (*__call__) (linesQ_L_22Cont, linesQ_Bepa);\n};\nstruct linesQ_L_22Cont {\n    struct linesQ_L_22ContG_class *$class;\n    linesQ_main self;\n    $Cont C_cont;\n};\n$R linesQ_L_11C_5cont (linesQ_main, $Cont, linesQ_Apa);\nstruct linesQ_L_23ContG_class {\n    char *$GCINFO;\n    int $class_id;\n    $SuperG_class $superclass;\n    B_NoneType (*__init__) (linesQ_L_23Cont, linesQ_main, $Cont);\n    void (*__serialize__) (linesQ_L_23Cont, $Serial$state);\n    linesQ_L_23Cont (*__deserialize__) (linesQ_L_23Cont, $Serial$state);\n    B_bool (*__bool__) (linesQ_L_23Cont);\n    B_str (*__str__) (linesQ_L_23Cont);\n    B_str (*__repr__) (linesQ_L_23Cont);\n    $R (*__call__) (linesQ_L_23Cont, linesQ_Apa);\n};\nstruct linesQ_L_23Cont {\n    struct linesQ_L_23ContG_class *$class;\n    linesQ_main self;\n    $Cont C_cont;\n};\nstruct linesQ_L_24procG_class {\n    char *$GCINFO;\n    int $class_id;\n    $SuperG_class $superclass;\n    B_NoneType (*__init__) (linesQ_L_24proc, linesQ_main, B_int);\n    void (*__serialize__) (linesQ_L_24proc, $Serial$state);\n    linesQ_L_24proc (*__deserialize__) (linesQ_L_24proc, $Serial$state);\n    B_bool (*__bool__) (linesQ_L_24proc);\n    B_str (*__str__) (linesQ_L_24proc);\n    B_str (*__repr__) (linesQ_L_24proc);\n    $R (*__call__) (linesQ_L_24proc, $Cont);\n    $R (*__exec__) (linesQ_L_24proc, $Cont);\n};\nstruct linesQ_L_24proc {\n    struct linesQ_L_24procG_class *$class;\n    linesQ_main self;\n    B_int i;\n};\nstruct linesQ_L_25procG_class {\n    char *$GCINFO;\n    int $class_id;\n    $SuperG_class $superclass;\n    B_NoneType (*__init__) (linesQ_L_25proc, linesQ_main);\n    void (*__serialize__) (linesQ_L_25proc, $Serial$state);\n    linesQ_L_25proc (*__deserialize__) (linesQ_L_25proc, $Serial$state);\n    B_bool (*__bool__) (linesQ_L_25proc);\n    B_str (*__str__) (linesQ_L_25proc);\n    B_str (*__repr__) (linesQ_L_25proc);\n    $R (*__call__) (linesQ_L_25proc, $Cont);\n    $R (*__exec__) (linesQ_L_25proc, $Cont);\n};\nstruct linesQ_L_25proc {\n    struct linesQ_L_25procG_class *$class;\n    linesQ_main self;\n};\n$R linesQ_L_26C_11cont ($Cont, linesQ_Apa, B_NoneType);\nstruct linesQ_L_27ContG_class {\n    char *$GCINFO;\n    int $class_id;\n    $SuperG_class $superclass;\n    B_NoneType (*__init__) (linesQ_L_27Cont, $Cont, linesQ_Apa);\n    void (*__serialize__) (linesQ_L_27Cont, $Serial$state);\n    linesQ_L_27Cont (*__deserialize__) (linesQ_L_27Cont, $Serial$state);\n    B_bool (*__bool__) (linesQ_L_27Cont);\n    B_str (*__str__) (linesQ_L_27Cont);\n    B_str (*__repr__) (linesQ_L_27Cont);\n    $R (*__call__) (linesQ_L_27Cont, B_NoneType);\n};\nstruct linesQ_L_27Cont {\n    struct linesQ_L_27ContG_class *$class;\n    $Cont C_cont;\n    linesQ_Apa G_act;\n};\nstruct linesQ_L_28procG_class {\n    char *$GCINFO;\n    int $class_id;\n    $SuperG_class $superclass;\n    B_NoneType (*__init__) (linesQ_L_28proc, linesQ_Apa);\n    void (*__serialize__) (linesQ_L_28proc, $Serial$state);\n    linesQ_L_28proc (*__deserialize__) (linesQ_L_28proc, $Serial$state);\n    B_bool (*__bool__) (linesQ_L_28proc);\n    B_str (*__str__) (linesQ_L_28proc);\n    B_str (*__repr__) (linesQ_L_28proc);\n    $R (*__call__) (linesQ_L_28proc, $Cont);\n    $R (*__exec__) (linesQ_L_28proc, $Cont);\n};\nstruct linesQ_L_28proc {\n    struct linesQ_L_28procG_class *$class;\n    linesQ_Apa G_act;\n};\n$R linesQ_L_29C_13cont ($Cont, linesQ_Bepa, B_NoneType);\nstruct linesQ_L_30ContG_class {\n    char *$GCINFO;\n    int $class_id;\n    $SuperG_class $superclass;\n    B_NoneType (*__init__) (linesQ_L_30Cont, $Cont, linesQ_Bepa);\n    void (*__serialize__) (linesQ_L_30Cont, $Serial$state);\n    linesQ_L_30Cont (*__deserialize__) (linesQ_L_30Cont, $Serial$state);\n    B_bool (*__bool__) (linesQ_L_30Cont);\n    B_str (*__str__) (linesQ_L_30Cont);\n    B_str (*__repr__) (linesQ_L_30Cont);\n    $R (*__call__) (linesQ_L_30Cont, B_NoneType);\n};\nstruct linesQ_L_30Cont {\n    struct linesQ_L_30ContG_class *$class;\n    $Cont C_cont;\n    linesQ_Bepa G_act;\n};\nstruct linesQ_L_31procG_class {\n    char *$GCINFO;\n    int $class_id;\n    $SuperG_class $superclass;\n    B_NoneType (*__init__) (linesQ_L_31proc, linesQ_Bepa);\n    void (*__serialize__) (linesQ_L_31proc, $Serial$state);\n    linesQ_L_31proc (*__deserialize__) (linesQ_L_31proc, $Serial$state);\n    B_bool (*__bool__) (linesQ_L_31proc);\n    B_str (*__str__) (linesQ_L_31proc);\n    B_str (*__repr__) (linesQ_L_31proc);\n    $R (*__call__) (linesQ_L_31proc, $Cont);\n    $R (*__exec__) (linesQ_L_31proc, $Cont);\n};\nstruct linesQ_L_31proc {\n    struct linesQ_L_31procG_class *$class;\n    linesQ_Bepa G_act;\n};\n$R linesQ_L_32C_15cont ($Cont, linesQ_main, B_NoneType);\nstruct linesQ_L_33ContG_class {\n    char *$GCINFO;\n    int $class_id;\n    $SuperG_class $superclass;\n    B_NoneType (*__init__) (linesQ_L_33Cont, $Cont, linesQ_main);\n    void (*__serialize__) (linesQ_L_33Cont, $Serial$state);\n    linesQ_L_33Cont (*__deserialize__) (linesQ_L_33Cont, $Serial$state);\n    B_bool (*__bool__) (linesQ_L_33Cont);\n    B_str (*__str__) (linesQ_L_33Cont);\n    B_str (*__repr__) (linesQ_L_33Cont);\n    $R (*__call__) (linesQ_L_33Cont, B_NoneType);\n};\nstruct linesQ_L_33Cont {\n    struct linesQ_L_33ContG_class *$class;\n    $Cont C_cont;\n    linesQ_main G_act;\n};\nstruct linesQ_L_34procG_class {\n    char *$GCINFO;\n    int $class_id;\n    $SuperG_class $superclass;\n    B_NoneType (*__init__) (linesQ_L_34proc, linesQ_main, B_Env);\n    void (*__serialize__) (linesQ_L_34proc, $Serial$state);\n    linesQ_L_34proc (*__deserialize__) (linesQ_L_34proc, $Serial$state);\n    B_bool (*__bool__) (linesQ_L_34proc);\n    B_str (*__str__) (linesQ_L_34proc);\n    B_str (*__repr__) (linesQ_L_34proc);\n    $R (*__call__) (linesQ_L_34proc, $Cont);\n    $R (*__exec__) (linesQ_L_34proc, $Cont);\n};\nstruct linesQ_L_34proc {\n    struct linesQ_L_34procG_class *$class;\n    linesQ_main G_act;\n    B_Env env;\n};\nstruct linesQ_ApaG_class {\n    char *$GCINFO;\n    int $class_id;\n    $SuperG_class $superclass;\n    $R (*__init__) (linesQ_Apa, $Cont);\n    void (*__serialize__) (linesQ_Apa, $Serial$state);\n    linesQ_Apa (*__deserialize__) (linesQ_Apa, $Serial$state);\n    B_bool (*__bool__) (linesQ_Apa);\n    B_str (*__str__) (linesQ_Apa);\n    B_str (*__repr__) (linesQ_Apa);\n    B_NoneType (*__resume__) (linesQ_Apa);\n    B_NoneType (*__cleanup__) (linesQ_Apa);\n    $R (*setupG_local) (linesQ_Apa, $Cont, $action);\n    $R (*computeG_local) (linesQ_Apa, $Cont, $action);\n    $R (*noticeG_local) (linesQ_Apa, $Cont, B_int);\n    B_Msg (*setup) (linesQ_Apa, $action);\n    B_Msg (*compute) (linesQ_Apa, $action);\n    B_Msg (*notice) (linesQ_Apa, B_int);\n};\nstruct linesQ_Apa {\n    struct linesQ_ApaG_class *$class;\n    $Actor $next;\n    B_Msg $msg;\n    B_Msg $msg_tail;\n    $Lock $msg_lock;\n    $int64 $affinity;\n    B_Msg $outgoing;\n    B_Msg $waitsfor;\n    $int64 $consume_hd;\n    $Catcher $catcher;\n    $long $globkey;\n    B_int apa;\n    B_int apb;\n    B_int y;\n    B_int z;\n};\nstruct linesQ_BepaG_class {\n    char *$GCINFO;\n    int $class_id;\n    $SuperG_class $superclass;\n    $R (*__init__) (linesQ_Bepa, $Cont);\n    void (*__serialize__) (linesQ_Bepa, $Serial$state);\n    linesQ_Bepa (*__deserialize__) (linesQ_Bepa, $Serial$state);\n    B_bool (*__bool__) (linesQ_Bepa);\n    B_str (*__str__) (linesQ_Bepa);\n    B_str (*__repr__) (linesQ_Bepa);\n    B_NoneType (*__resume__) (linesQ_Bepa);\n    B_NoneType (*__cleanup__) (linesQ_Bepa);\n    $R (*callbackG_local) (linesQ_Bepa, $Cont, B_int);\n    B_Msg (*callback) (linesQ_Bepa, B_int);\n};\nstruct linesQ_Bepa {\n    struct linesQ_BepaG_class *$class;\n    $Actor $next;\n    B_Msg $msg;\n    B_Msg $msg_tail;\n    $Lock $msg_lock;\n    $int64 $affinity;\n    B_Msg $outgoing;\n    B_Msg $waitsfor;\n    $int64 $consume_hd;\n    $Catcher $catcher;\n    $long $globkey;\n};\nstruct linesQ_mainG_class {\n    char *$GCINFO;\n    int $class_id;\n    $SuperG_class $superclass;\n    $R (*__init__) (linesQ_main, $Cont, B_Env);\n    void (*__serialize__) (linesQ_main, $Serial$state);\n    linesQ_main (*__deserialize__) (linesQ_main, $Serial$state);\n    B_bool (*__bool__) (linesQ_main);\n    B_str (*__str__) (linesQ_main);\n    B_str (*__repr__) (linesQ_main);\n    B_NoneType (*__resume__) (linesQ_main);\n    B_NoneType (*__cleanup__) (linesQ_main);\n    $R (*myprocG_local) (linesQ_main, $Cont, B_int);\n    $R (*nopG_local) (linesQ_main, $Cont);\n    B_Msg (*myproc) (linesQ_main, B_int);\n    B_Msg (*nop) (linesQ_main);\n};\nstruct linesQ_main {\n    struct linesQ_mainG_class *$class;\n    $Actor $next;\n    B_Msg $msg;\n    B_Msg $msg_tail;\n    $Lock $msg_lock;\n    $int64 $affinity;\n    B_Msg $outgoing;\n    B_Msg $waitsfor;\n    $int64 $consume_hd;\n    $Catcher $catcher;\n    $long $globkey;\n    B_Env env;\n    linesQ_Apa a;\n    linesQ_Bepa b;\n    B_Msg x;\n    B_int r;\n    B_int v;\n    B_int i;\n};\n$R linesQ_ApaG_newact ($Cont);\n$R linesQ_BepaG_newact ($Cont);\n$R linesQ_mainG_newact ($Cont, B_Env);\nextern struct linesQ_L_2ContG_class linesQ_L_2ContG_methods;\nlinesQ_L_2Cont linesQ_L_2ContG_new(linesQ_Apa, $Cont);\nextern struct linesQ_L_4actionG_class linesQ_L_4actionG_methods;\nlinesQ_L_4action linesQ_L_4actionG_new(linesQ_Apa);\nextern struct linesQ_L_6ContG_class linesQ_L_6ContG_methods;\nlinesQ_L_6Cont linesQ_L_6ContG_new($action, $Cont);\nextern struct linesQ_L_7procG_class linesQ_L_7procG_methods;\nlinesQ_L_7proc linesQ_L_7procG_new(linesQ_Apa, $action);\nextern struct linesQ_L_8procG_class linesQ_L_8procG_methods;\nlinesQ_L_8proc linesQ_L_8procG_new(linesQ_Apa, $action);\nextern struct linesQ_L_9procG_class linesQ_L_9procG_methods;\nlinesQ_L_9proc linesQ_L_9procG_new(linesQ_Apa, B_int);\nextern struct linesQ_L_10procG_class linesQ_L_10procG_methods;\nlinesQ_L_10proc linesQ_L_10procG_new(linesQ_Bepa, B_int);\nextern struct linesQ_L_14actionG_class linesQ_L_14actionG_methods;\nlinesQ_L_14action linesQ_L_14actionG_new(linesQ_Apa);\nextern struct linesQ_L_16actionG_class linesQ_L_16actionG_methods;\nlinesQ_L_16action linesQ_L_16actionG_new(linesQ_Bepa);\nextern struct linesQ_L_19actionG_class linesQ_L_19actionG_methods;\nlinesQ_L_19action linesQ_L_19actionG_new(linesQ_main);\nextern struct linesQ_L_20procG_class linesQ_L_20procG_methods;\nlinesQ_L_20proc linesQ_L_20procG_new(linesQ_main);\nextern struct linesQ_L_21ContG_class linesQ_L_21ContG_methods;\nlinesQ_L_21Cont linesQ_L_21ContG_new(linesQ_main, $Cont);\nextern struct linesQ_L_22ContG_class linesQ_L_22ContG_methods;\nlinesQ_L_22Cont linesQ_L_22ContG_new(linesQ_main, $Cont);\nextern struct linesQ_L_23ContG_class linesQ_L_23ContG_methods;\nlinesQ_L_23Cont linesQ_L_23ContG_new(linesQ_main, $Cont);\nextern struct linesQ_L_24procG_class linesQ_L_24procG_methods;\nlinesQ_L_24proc linesQ_L_24procG_new(linesQ_main, B_int);\nextern struct linesQ_L_25procG_class linesQ_L_25procG_methods;\nlinesQ_L_25proc linesQ_L_25procG_new(linesQ_main);\nextern struct linesQ_L_27ContG_class linesQ_L_27ContG_methods;\nlinesQ_L_27Cont linesQ_L_27ContG_new($Cont, linesQ_Apa);\nextern struct linesQ_L_28procG_class linesQ_L_28procG_methods;\nlinesQ_L_28proc linesQ_L_28procG_new(linesQ_Apa);\nextern struct linesQ_L_30ContG_class linesQ_L_30ContG_methods;\nlinesQ_L_30Cont linesQ_L_30ContG_new($Cont, linesQ_Bepa);\nextern struct linesQ_L_31procG_class linesQ_L_31procG_methods;\nlinesQ_L_31proc linesQ_L_31procG_new(linesQ_Bepa);\nextern struct linesQ_L_33ContG_class linesQ_L_33ContG_methods;\nlinesQ_L_33Cont linesQ_L_33ContG_new($Cont, linesQ_main);\nextern struct linesQ_L_34procG_class linesQ_L_34procG_methods;\nlinesQ_L_34proc linesQ_L_34procG_new(linesQ_main, B_Env);\nextern struct linesQ_ApaG_class linesQ_ApaG_methods;\n$R linesQ_ApaG_new($Cont);\nextern struct linesQ_BepaG_class linesQ_BepaG_methods;\n$R linesQ_BepaG_new($Cont);\nextern struct linesQ_mainG_class linesQ_mainG_methods;\n$R linesQ_mainG_new($Cont, B_Env);\nextern B_Eq linesQ_W_Apa_1097;\nextern B_Eq linesQ_W_Apa_759;\nextern B_Iterable linesQ_W_Apa_779;\nextern B_Eq linesQ_W_Apa_331;\nextern B_Eq linesQ_W_Apa_785;\nvoid linesQ___init__ ();"
  },
  {
    "path": "compiler/lib/test/9-codegen/lines.input",
    "content": "W_Apa_1097: __builtin__.Eq[__builtin__.int] = __builtin__.OrdD_int()\n\nW_Apa_759: __builtin__.Eq[?__builtin__.int] = $EqOpt@[__builtin__.int](W_Apa_1097)\n\nW_Apa_779: __builtin__.Iterable[__builtin__.list[?__builtin__.int], ?__builtin__.int] = __builtin__.SequenceD_list@[?__builtin__.int]().W_Collection\n\nW_Apa_331: __builtin__.Eq[?__builtin__.int] = $EqOpt@[__builtin__.int](W_Apa_1097)\n\nW_Apa_785: __builtin__.Eq[?__builtin__.int] = $EqOpt@[__builtin__.int](W_Apa_1097)\n\n# recursive group:\nproc def L_1C_1cont (self : Apa, C_cont : $Cont[None], C_2res : None) -> $R:\n    self.z = (BOX __builtin__.int (UNBOX __builtin__.int 1))\n    print@[(__builtin__.str,)]((\"\\\"Apa\\\"\",), None, None, None, None)\n    return $R_CONT@[None](C_cont, None)\nclass L_2Cont ($Cont[None], __builtin__.value):\n    @property\n    self : Apa\n    @property\n    C_cont : $Cont[None]\n    pure def __init__ (L_self : L_2Cont, self : Apa, C_cont : $Cont[None]) -> None:\n        L_self.self = self\n        L_self.C_cont = C_cont\n        return None\n    proc def __call__ (L_self : L_2Cont, G_1 : None) -> $R:\n        self: Apa = L_self.self\n        C_cont: $Cont[None] = L_self.C_cont\n        return L_1C_1cont(self, C_cont, G_1)\nclass L_4action ($action[(__builtin__.int,), __builtin__.int], $proc[(__builtin__.int,), __builtin__.int], __builtin__.value):\n    @property\n    L_3obj : Apa\n    pure def __init__ (L_self : L_4action, L_3obj : Apa) -> None:\n        L_self.L_3obj = L_3obj\n        return None\n    # recursive group:\n    proc def __call__ (L_self : L_4action, L_cont : $Cont[__builtin__.int], G_1 : __builtin__.int) -> $R:\n        return $AWAIT@[__builtin__.int](L_cont, L_self.__asyn__(G_1))\n    proc def __exec__ (L_self : L_4action, L_cont : $Cont[__builtin__.value], G_1 : __builtin__.int) -> $R:\n        return $R_CONT@[__builtin__.value](L_cont, L_self.__asyn__(G_1))\n    action def __asyn__ (L_self : L_4action, G_1 : __builtin__.int) -> __builtin__.int:\n        L_3obj: Apa = L_self.L_3obj\n        return L_3obj.notice(G_1)\n    # (recursive group)\nproc def U_L_5C_3cont (cb : $action[(__builtin__.int,), __builtin__.int], C_cont : $Cont[__builtin__.int], U_2C_4res : __builtin__.int) -> $R:\n    U_3v: __builtin__.int = U_2C_4res\n    m: __builtin__.Msg[__builtin__.int] = cb.__asyn__((BOX __builtin__.int (UNBOX __builtin__.int 2)))\n    U_4N_tmp: __builtin__.int = (U_3v * (UNBOX __builtin__.int 10))\n    return $R_CONT@[__builtin__.int](C_cont, (BOX __builtin__.int U_4N_tmp))\nproc def L_5C_3cont (cb : $action[(__builtin__.int,), __builtin__.int], C_cont : $Cont[__builtin__.int], C_4res : __builtin__.int) -> $R:\n    return U_L_5C_3cont(cb, C_cont, (UNBOX __builtin__.int C_4res))\nclass L_6Cont ($Cont[__builtin__.int], __builtin__.value):\n    @property\n    cb : $action[(__builtin__.int,), __builtin__.int]\n    @property\n    C_cont : $Cont[__builtin__.int]\n    pure def __init__ (L_self : L_6Cont, cb : $action[(__builtin__.int,), __builtin__.int], C_cont : $Cont[__builtin__.int]) -> None:\n        L_self.cb = cb\n        L_self.C_cont = C_cont\n        return None\n    proc def __call__ (L_self : L_6Cont, G_1 : __builtin__.int) -> $R:\n        cb: $action[(__builtin__.int,), __builtin__.int] = L_self.cb\n        C_cont: $Cont[__builtin__.int] = L_self.C_cont\n        return L_5C_3cont(cb, C_cont, G_1)\nclass L_7proc ($proc[(), None], __builtin__.value):\n    @property\n    self : Apa\n    @property\n    cb : $action[(__builtin__.int,), __builtin__.int]\n    pure def __init__ (L_self : L_7proc, self : Apa, cb : $action[(__builtin__.int,), __builtin__.int]) -> None:\n        L_self.self = self\n        L_self.cb = cb\n        return None\n    # recursive group:\n    proc def __call__ (L_self : L_7proc, C_cont : $Cont[None]) -> $R:\n        self: Apa = L_self.self\n        cb: $action[(__builtin__.int,), __builtin__.int] = L_self.cb\n        return self.setupG_local(C_cont, cb)\n    proc def __exec__ (L_self : L_7proc, C_cont : $Cont[None]) -> $R:\n        return L_self.__call__(C_cont)\n    # (recursive group)\nclass L_8proc ($proc[(), __builtin__.int], __builtin__.value):\n    @property\n    self : Apa\n    @property\n    cb : $action[(__builtin__.int,), __builtin__.int]\n    pure def __init__ (L_self : L_8proc, self : Apa, cb : $action[(__builtin__.int,), __builtin__.int]) -> None:\n        L_self.self = self\n        L_self.cb = cb\n        return None\n    # recursive group:\n    proc def __call__ (L_self : L_8proc, C_cont : $Cont[__builtin__.int]) -> $R:\n        self: Apa = L_self.self\n        cb: $action[(__builtin__.int,), __builtin__.int] = L_self.cb\n        return self.computeG_local(C_cont, cb)\n    proc def __exec__ (L_self : L_8proc, C_cont : $Cont[__builtin__.int]) -> $R:\n        return L_self.__call__(C_cont)\n    # (recursive group)\nclass L_9proc ($proc[(), __builtin__.int], __builtin__.value):\n    @property\n    self : Apa\n    @property\n    i : __builtin__.int\n    pure def __init__ (L_self : L_9proc, self : Apa, i : __builtin__.int) -> None:\n        L_self.self = self\n        L_self.i = i\n        return None\n    # recursive group:\n    proc def __call__ (L_self : L_9proc, C_cont : $Cont[__builtin__.int]) -> $R:\n        self: Apa = L_self.self\n        U_5i: __builtin__.int = (UNBOX __builtin__.int L_self.i)\n        return self.noticeG_local(C_cont, (BOX __builtin__.int U_5i))\n    proc def __exec__ (L_self : L_9proc, C_cont : $Cont[__builtin__.int]) -> $R:\n        return L_self.__call__(C_cont)\n    # (recursive group)\nclass L_10proc ($proc[(), __builtin__.int], __builtin__.value):\n    @property\n    self : Bepa\n    @property\n    i : __builtin__.int\n    pure def __init__ (L_self : L_10proc, self : Bepa, i : __builtin__.int) -> None:\n        L_self.self = self\n        L_self.i = i\n        return None\n    # recursive group:\n    proc def __call__ (L_self : L_10proc, C_cont : $Cont[__builtin__.int]) -> $R:\n        self: Bepa = L_self.self\n        U_6i: __builtin__.int = (UNBOX __builtin__.int L_self.i)\n        return self.callbackG_local(C_cont, (BOX __builtin__.int U_6i))\n    proc def __exec__ (L_self : L_10proc, C_cont : $Cont[__builtin__.int]) -> $R:\n        return L_self.__call__(C_cont)\n    # (recursive group)\nclass L_14action ($action[(__builtin__.int,), __builtin__.int], $proc[(__builtin__.int,), __builtin__.int], __builtin__.value):\n    @property\n    L_13obj : Apa\n    pure def __init__ (L_self : L_14action, L_13obj : Apa) -> None:\n        L_self.L_13obj = L_13obj\n        return None\n    # recursive group:\n    proc def __call__ (L_self : L_14action, L_cont : $Cont[__builtin__.int], G_1 : __builtin__.int) -> $R:\n        return $AWAIT@[__builtin__.int](L_cont, L_self.__asyn__(G_1))\n    proc def __exec__ (L_self : L_14action, L_cont : $Cont[__builtin__.value], G_1 : __builtin__.int) -> $R:\n        return $R_CONT@[__builtin__.value](L_cont, L_self.__asyn__(G_1))\n    action def __asyn__ (L_self : L_14action, G_1 : __builtin__.int) -> __builtin__.int:\n        L_13obj: Apa = L_self.L_13obj\n        return L_13obj.notice(G_1)\n    # (recursive group)\nclass L_16action ($action[(__builtin__.int,), __builtin__.int], $proc[(__builtin__.int,), __builtin__.int], __builtin__.value):\n    @property\n    L_15obj : Bepa\n    pure def __init__ (L_self : L_16action, L_15obj : Bepa) -> None:\n        L_self.L_15obj = L_15obj\n        return None\n    # recursive group:\n    proc def __call__ (L_self : L_16action, L_cont : $Cont[__builtin__.int], G_1 : __builtin__.int) -> $R:\n        return $AWAIT@[__builtin__.int](L_cont, L_self.__asyn__(G_1))\n    proc def __exec__ (L_self : L_16action, L_cont : $Cont[__builtin__.value], G_1 : __builtin__.int) -> $R:\n        return $R_CONT@[__builtin__.value](L_cont, L_self.__asyn__(G_1))\n    action def __asyn__ (L_self : L_16action, G_1 : __builtin__.int) -> __builtin__.int:\n        L_15obj: Bepa = L_self.L_15obj\n        return L_15obj.callback(G_1)\n    # (recursive group)\nclass L_19action ($action[(__builtin__.int,), __builtin__.int], $proc[(__builtin__.int,), __builtin__.int], __builtin__.value):\n    @property\n    L_18obj : main\n    pure def __init__ (L_self : L_19action, L_18obj : main) -> None:\n        L_self.L_18obj = L_18obj\n        return None\n    # recursive group:\n    proc def __call__ (L_self : L_19action, L_cont : $Cont[__builtin__.int], G_1 : __builtin__.int) -> $R:\n        return $AWAIT@[__builtin__.int](L_cont, L_self.__asyn__(G_1))\n    proc def __exec__ (L_self : L_19action, L_cont : $Cont[__builtin__.value], G_1 : __builtin__.int) -> $R:\n        return $R_CONT@[__builtin__.value](L_cont, L_self.__asyn__(G_1))\n    action def __asyn__ (L_self : L_19action, G_1 : __builtin__.int) -> __builtin__.int:\n        L_18obj: main = L_self.L_18obj\n        return L_18obj.myproc(G_1)\n    # (recursive group)\nclass L_20proc ($proc[(), __builtin__.int], __builtin__.value):\n    @property\n    self : main\n    pure def __init__ (L_self : L_20proc, self : main) -> None:\n        L_self.self = self\n        return None\n    # recursive group:\n    proc def __call__ (L_self : L_20proc, C_cont : $Cont[__builtin__.int]) -> $R:\n        self: main = L_self.self\n        return self.myprocG_local(C_cont, (BOX __builtin__.int (UNBOX __builtin__.int 0)))\n    proc def __exec__ (L_self : L_20proc, C_cont : $Cont[__builtin__.int]) -> $R:\n        return L_self.__call__(C_cont)\n    # (recursive group)\nproc def U_1L_17C_9cont (self : main, C_cont : $Cont[None], U_7C_10res : __builtin__.int) -> $R:\n    self.r = (BOX __builtin__.int U_7C_10res)\n    print@[(__builtin__.str, __builtin__.int)]((\"\\\"r =\\\"\", self.r), None, None, None, None)\n    (async self.a.compute)(L_19action(self))\n    print@[(__builtin__.str,)]((\"\\\"main\\\"\",), None, None, None, None)\n    self.v = (BOX __builtin__.int (UNBOX __builtin__.int 0))\n    if (BOX __builtin__.bool ((UNBOX __builtin__.int self.v) == (UNBOX __builtin__.int 0))):\n        print@[(__builtin__.str,)]((\"\\\"if branch\\\"\",), None, None, None, None)\n        if (BOX __builtin__.bool ((UNBOX __builtin__.int self.v) < (UNBOX __builtin__.int 1))):\n            print@[(__builtin__.str,)]((\"\\\"nested if\\\"\",), None, None, None, None)\n        elif (BOX __builtin__.bool ((UNBOX __builtin__.int self.v) == (UNBOX __builtin__.int -1))):\n            print@[(__builtin__.str,)]((\"\\\"nested elif\\\"\",), None, None, None, None)\n        else:\n            print@[(__builtin__.str,)]((\"\\\"nested else\\\"\",), None, None, None, None)\n    elif (BOX __builtin__.bool ((UNBOX __builtin__.int self.v) == (UNBOX __builtin__.int 1))):\n        print@[(__builtin__.str,)]((\"\\\"outer elif\\\"\",), None, None, None, None)\n    else:\n        print@[(__builtin__.str,)]((\"\\\"outer else\\\"\",), None, None, None, None)\n    self.i = (BOX __builtin__.int (UNBOX __builtin__.int 0))\n    while True:\n        if (BOX __builtin__.bool ((UNBOX __builtin__.int self.i) < (UNBOX __builtin__.int 3))):\n            pass\n        else:\n            print@[(__builtin__.str,)]((\"\\\"while else\\\"\",), None, None, None, None)\n            break\n        self.i = (BOX __builtin__.int ((UNBOX __builtin__.int self.i) + (UNBOX __builtin__.int 1)))\n        if (BOX __builtin__.bool ((UNBOX __builtin__.int self.i) == (UNBOX __builtin__.int 1))):\n            print@[(__builtin__.str,)]((\"\\\"continue path\\\"\",), None, None, None, None)\n            continue\n        if (BOX __builtin__.bool ((UNBOX __builtin__.int self.i) == (UNBOX __builtin__.int 2))):\n            print@[(__builtin__.str,)]((\"\\\"break path\\\"\",), None, None, None, None)\n            break\n        print@[(__builtin__.str, __builtin__.int)]((\"\\\"loop body\\\"\", self.i), None, None, None, None)\n    N_3iter: __builtin__.Iterator[?__builtin__.int] = W_Apa_779.__iter__([(BOX __builtin__.int (UNBOX __builtin__.int 1)), (BOX __builtin__.int (UNBOX __builtin__.int 2)), (BOX __builtin__.int (UNBOX __builtin__.int 3))])\n    if $PUSH():\n        while True:\n            if True:\n                pass\n            else:\n                break\n            j: ?__builtin__.int = N_3iter.__next__()\n            if W_Apa_759.__eq__(j, (BOX __builtin__.int (UNBOX __builtin__.int 2))):\n                continue\n            print@[(__builtin__.str, ?__builtin__.int)]((\"\\\"for j\\\"\", j), None, None, None, None)\n        $DROP()\n    else:\n        N_5x: __builtin__.BaseException = $POP()\n        if isinstance(N_5x, __builtin__.StopIteration):\n            pass\n        else:\n            $RAISE(N_5x)\n    if $PUSHF():\n        if $PUSH():\n            if W_Apa_785.__eq__(self.v, (BOX __builtin__.int (UNBOX __builtin__.int 0))):\n                $RAISE(ValueError(\"\\\"boom\\\"\"))\n            print@[(__builtin__.str,)]((\"\\\"unreached\\\"\",), None, None, None, None)\n            $DROP()\n        else:\n            N_6x: __builtin__.BaseException = $POP()\n            if isinstance(N_6x, ValueError):\n                e: ValueError = N_6x\n                print@[(__builtin__.str, __builtin__.str)]((\"\\\"caught\\\"\", \"\\\"ValueError\\\"\"), None, None, None, None)\n            else:\n                $RAISE(N_6x)\n        $RAISE($SEQ())\n    else:\n        N_7xx: __builtin__.BaseException = $POP()\n        print@[(__builtin__.str,)]((\"\\\"finally\\\"\",), None, None, None, None)\n        if isinstance(N_7xx, $SEQ):\n            pass\n        else:\n            $RAISE(N_7xx)\n    $AFTER@[__builtin__.int]((BOX __builtin__.float (UNBOX __builtin__.float 1)), L_20proc(self))\n    return self.nopG_local(C_cont)\nproc def L_17C_9cont (self : main, C_cont : $Cont[None], C_10res : __builtin__.int) -> $R:\n    return U_1L_17C_9cont(self, C_cont, (UNBOX __builtin__.int C_10res))\nclass L_21Cont ($Cont[__builtin__.int], __builtin__.value):\n    @property\n    self : main\n    @property\n    C_cont : $Cont[None]\n    pure def __init__ (L_self : L_21Cont, self : main, C_cont : $Cont[None]) -> None:\n        L_self.self = self\n        L_self.C_cont = C_cont\n        return None\n    proc def __call__ (L_self : L_21Cont, G_1 : __builtin__.int) -> $R:\n        self: main = L_self.self\n        C_cont: $Cont[None] = L_self.C_cont\n        return L_17C_9cont(self, C_cont, G_1)\nproc def L_12C_7cont (self : main, C_cont : $Cont[None], C_8res : Bepa) -> $R:\n    self.b = C_8res\n    print@[(__builtin__.str,)]((\"\\\"-----\\\"\",), None, None, None, None)\n    (async self.a.setup)(L_14action(self.a))\n    self.x = (async self.a.compute)(L_16action(self.b))\n    return $AWAIT@[__builtin__.int](L_21Cont(self, C_cont), self.x)\nclass L_22Cont ($Cont[Bepa], __builtin__.value):\n    @property\n    self : main\n    @property\n    C_cont : $Cont[None]\n    pure def __init__ (L_self : L_22Cont, self : main, C_cont : $Cont[None]) -> None:\n        L_self.self = self\n        L_self.C_cont = C_cont\n        return None\n    proc def __call__ (L_self : L_22Cont, G_1 : Bepa) -> $R:\n        self: main = L_self.self\n        C_cont: $Cont[None] = L_self.C_cont\n        return L_12C_7cont(self, C_cont, G_1)\nproc def L_11C_5cont (self : main, C_cont : $Cont[None], C_6res : Apa) -> $R:\n    self.a = C_6res\n    return BepaG_newact(L_22Cont(self, C_cont))\nclass L_23Cont ($Cont[Apa], __builtin__.value):\n    @property\n    self : main\n    @property\n    C_cont : $Cont[None]\n    pure def __init__ (L_self : L_23Cont, self : main, C_cont : $Cont[None]) -> None:\n        L_self.self = self\n        L_self.C_cont = C_cont\n        return None\n    proc def __call__ (L_self : L_23Cont, G_1 : Apa) -> $R:\n        self: main = L_self.self\n        C_cont: $Cont[None] = L_self.C_cont\n        return L_11C_5cont(self, C_cont, G_1)\nclass L_24proc ($proc[(), __builtin__.int], __builtin__.value):\n    @property\n    self : main\n    @property\n    i : __builtin__.int\n    pure def __init__ (L_self : L_24proc, self : main, i : __builtin__.int) -> None:\n        L_self.self = self\n        L_self.i = i\n        return None\n    # recursive group:\n    proc def __call__ (L_self : L_24proc, C_cont : $Cont[__builtin__.int]) -> $R:\n        self: main = L_self.self\n        U_8i: __builtin__.int = (UNBOX __builtin__.int L_self.i)\n        return self.myprocG_local(C_cont, (BOX __builtin__.int U_8i))\n    proc def __exec__ (L_self : L_24proc, C_cont : $Cont[__builtin__.int]) -> $R:\n        return L_self.__call__(C_cont)\n    # (recursive group)\nclass L_25proc ($proc[(), None], __builtin__.value):\n    @property\n    self : main\n    pure def __init__ (L_self : L_25proc, self : main) -> None:\n        L_self.self = self\n        return None\n    # recursive group:\n    proc def __call__ (L_self : L_25proc, C_cont : $Cont[None]) -> $R:\n        self: main = L_self.self\n        return self.nopG_local(C_cont)\n    proc def __exec__ (L_self : L_25proc, C_cont : $Cont[None]) -> $R:\n        return L_self.__call__(C_cont)\n    # (recursive group)\nproc def L_26C_11cont (C_cont : $Cont[Apa], G_act : Apa, C_12res : None) -> $R:\n    return $R_CONT@[Apa](C_cont, G_act)\nclass L_27Cont ($Cont[None], __builtin__.value):\n    @property\n    C_cont : $Cont[Apa]\n    @property\n    G_act : Apa\n    pure def __init__ (L_self : L_27Cont, C_cont : $Cont[Apa], G_act : Apa) -> None:\n        L_self.C_cont = C_cont\n        L_self.G_act = G_act\n        return None\n    proc def __call__ (L_self : L_27Cont, G_1 : None) -> $R:\n        C_cont: $Cont[Apa] = L_self.C_cont\n        G_act: Apa = L_self.G_act\n        return L_26C_11cont(C_cont, G_act, G_1)\nclass L_28proc ($proc[(), None], __builtin__.value):\n    @property\n    G_act : Apa\n    pure def __init__ (L_self : L_28proc, G_act : Apa) -> None:\n        L_self.G_act = G_act\n        return None\n    # recursive group:\n    proc def __call__ (L_self : L_28proc, C_cont : $Cont[None]) -> $R:\n        G_act: Apa = L_self.G_act\n        return G_act.__init__(C_cont)\n    proc def __exec__ (L_self : L_28proc, C_cont : $Cont[None]) -> $R:\n        return L_self.__call__(C_cont)\n    # (recursive group)\nproc def L_29C_13cont (C_cont : $Cont[Bepa], G_act : Bepa, C_14res : None) -> $R:\n    return $R_CONT@[Bepa](C_cont, G_act)\nclass L_30Cont ($Cont[None], __builtin__.value):\n    @property\n    C_cont : $Cont[Bepa]\n    @property\n    G_act : Bepa\n    pure def __init__ (L_self : L_30Cont, C_cont : $Cont[Bepa], G_act : Bepa) -> None:\n        L_self.C_cont = C_cont\n        L_self.G_act = G_act\n        return None\n    proc def __call__ (L_self : L_30Cont, G_1 : None) -> $R:\n        C_cont: $Cont[Bepa] = L_self.C_cont\n        G_act: Bepa = L_self.G_act\n        return L_29C_13cont(C_cont, G_act, G_1)\nclass L_31proc ($proc[(), None], __builtin__.value):\n    @property\n    G_act : Bepa\n    pure def __init__ (L_self : L_31proc, G_act : Bepa) -> None:\n        L_self.G_act = G_act\n        return None\n    # recursive group:\n    proc def __call__ (L_self : L_31proc, C_cont : $Cont[None]) -> $R:\n        G_act: Bepa = L_self.G_act\n        return G_act.__init__(C_cont)\n    proc def __exec__ (L_self : L_31proc, C_cont : $Cont[None]) -> $R:\n        return L_self.__call__(C_cont)\n    # (recursive group)\nproc def L_32C_15cont (C_cont : $Cont[main], G_act : main, C_16res : None) -> $R:\n    return $R_CONT@[main](C_cont, G_act)\nclass L_33Cont ($Cont[None], __builtin__.value):\n    @property\n    C_cont : $Cont[main]\n    @property\n    G_act : main\n    pure def __init__ (L_self : L_33Cont, C_cont : $Cont[main], G_act : main) -> None:\n        L_self.C_cont = C_cont\n        L_self.G_act = G_act\n        return None\n    proc def __call__ (L_self : L_33Cont, G_1 : None) -> $R:\n        C_cont: $Cont[main] = L_self.C_cont\n        G_act: main = L_self.G_act\n        return L_32C_15cont(C_cont, G_act, G_1)\nclass L_34proc ($proc[(), None], __builtin__.value):\n    @property\n    G_act : main\n    @property\n    env : __builtin__.Env\n    pure def __init__ (L_self : L_34proc, G_act : main, env : __builtin__.Env) -> None:\n        L_self.G_act = G_act\n        L_self.env = env\n        return None\n    # recursive group:\n    proc def __call__ (L_self : L_34proc, C_cont : $Cont[None]) -> $R:\n        G_act: main = L_self.G_act\n        env: __builtin__.Env = L_self.env\n        return G_act.__init__(C_cont, env)\n    proc def __exec__ (L_self : L_34proc, C_cont : $Cont[None]) -> $R:\n        return L_self.__call__(C_cont)\n    # (recursive group)\nclass Apa ($Actor, __builtin__.value):\n    @property\n    apa : __builtin__.int\n    @property\n    apb : __builtin__.int\n    @property\n    y : __builtin__.int\n    @property\n    z : __builtin__.int\n    proc def __init__ (self : Apa, C_cont : $Cont[None]) -> $R:\n        self.apa = (BOX __builtin__.int (UNBOX __builtin__.int 2001))\n        self.apb = (BOX __builtin__.int (UNBOX __builtin__.int 2002))\n        self.y = (BOX __builtin__.int (UNBOX __builtin__.int 123))\n        return self.setupG_local(L_2Cont(self, C_cont), L_4action(self))\n    proc def setupG_local (self : Apa, C_cont : $Cont[None], cb : $action[(__builtin__.int,), __builtin__.int]) -> $R:\n        print@[(__builtin__.str,)]((\"\\\"setup\\\"\",), None, None, None, None)\n        cb.__asyn__((BOX __builtin__.int (UNBOX __builtin__.int 0)))\n        return $R_CONT@[None](C_cont, None)\n    proc def computeG_local (self : Apa, C_cont : $Cont[__builtin__.int], cb : $action[(__builtin__.int,), __builtin__.int]) -> $R:\n        print@[(__builtin__.str,)]((\"\\\"compute\\\"\",), None, None, None, None)\n        return $AWAIT@[__builtin__.int](L_6Cont(cb, C_cont), cb.__asyn__((BOX __builtin__.int (UNBOX __builtin__.int 1))))\n    proc def noticeG_local (self : Apa, C_cont : $Cont[__builtin__.int], i : __builtin__.int) -> $R:\n        print@[(__builtin__.str,)]((\"\\\"notice\\\"\",), None, None, None, None)\n        U_9N_1tmp: __builtin__.int = ((UNBOX __builtin__.int i) + (UNBOX __builtin__.int 1))\n        return $R_CONT@[__builtin__.int](C_cont, (BOX __builtin__.int U_9N_1tmp))\n    action def setup (self : Apa, cb : $action[(__builtin__.int,), __builtin__.int]) -> None:\n        return $ASYNC@[None](self, L_7proc(self, cb))\n    action def compute (self : Apa, cb : $action[(__builtin__.int,), __builtin__.int]) -> __builtin__.int:\n        return $ASYNC@[__builtin__.int](self, L_8proc(self, cb))\n    action def notice (self : Apa, i : __builtin__.int) -> __builtin__.int:\n        return $ASYNC@[__builtin__.int](self, L_9proc(self, i))\nclass Bepa ($Actor, __builtin__.value):\n    proc def __init__ (self : Bepa, C_cont : $Cont[None]) -> $R:\n        print@[(__builtin__.str,)]((\"\\\"Bepa\\\"\",), None, None, None, None)\n        return $R_CONT@[None](C_cont, None)\n    proc def callbackG_local (self : Bepa, C_cont : $Cont[__builtin__.int], i : __builtin__.int) -> $R:\n        print@[(__builtin__.str, __builtin__.int)]((\"\\\"callback\\\"\", i), None, None, None, None)\n        U_10N_2tmp: __builtin__.int = ((UNBOX __builtin__.int i) + (UNBOX __builtin__.int 1))\n        return $R_CONT@[__builtin__.int](C_cont, (BOX __builtin__.int U_10N_2tmp))\n    action def callback (self : Bepa, i : __builtin__.int) -> __builtin__.int:\n        return $ASYNC@[__builtin__.int](self, L_10proc(self, i))\nclass main ($Actor, __builtin__.value):\n    @property\n    env : __builtin__.Env\n    @property\n    a : Apa\n    @property\n    b : Bepa\n    @property\n    x : __builtin__.Msg[__builtin__.int]\n    @property\n    r : __builtin__.int\n    @property\n    v : __builtin__.int\n    @property\n    i : __builtin__.int\n    proc def __init__ (self : main, C_cont : $Cont[None], env : __builtin__.Env) -> $R:\n        self.env = env\n        return ApaG_newact(L_23Cont(self, C_cont))\n    proc def myprocG_local (self : main, C_cont : $Cont[__builtin__.int], i : __builtin__.int) -> $R:\n        print@[(__builtin__.str, __builtin__.int)]((\"\\\"myproc\\\"\", i), None, None, None, None)\n        if W_Apa_331.__eq__(i, (BOX __builtin__.int (UNBOX __builtin__.int 2))):\n            (async self.env.exit)((BOX __builtin__.int (UNBOX __builtin__.int 0)))\n        return $R_CONT@[__builtin__.int](C_cont, i)\n    proc def nopG_local (self : main, C_cont : $Cont[None]) -> $R:\n        pass\n        return $R_CONT@[None](C_cont, None)\n    action def myproc (self : main, i : __builtin__.int) -> __builtin__.int:\n        return $ASYNC@[__builtin__.int](self, L_24proc(self, i))\n    action def nop (self : main) -> None:\n        return $ASYNC@[None](self, L_25proc(self))\nproc def ApaG_newact (C_cont : $Cont[Apa]) -> $R:\n    G_act: Apa = $NEWACTOR@[Apa]()\n    $InstallFinalizer@[Apa](G_act)\n    return $AWAIT@[None](L_27Cont(C_cont, G_act), $ASYNC@[None](G_act, L_28proc(G_act)))\nproc def BepaG_newact (C_cont : $Cont[Bepa]) -> $R:\n    G_act: Bepa = $NEWACTOR@[Bepa]()\n    $InstallFinalizer@[Bepa](G_act)\n    return $AWAIT@[None](L_30Cont(C_cont, G_act), $ASYNC@[None](G_act, L_31proc(G_act)))\nproc def mainG_newact (C_cont : $Cont[main], env : __builtin__.Env) -> $R:\n    G_act: main = $NEWACTOR@[main]()\n    $InstallFinalizer@[main](G_act)\n    return $AWAIT@[None](L_33Cont(C_cont, G_act), $ASYNC@[None](G_act, L_34proc(G_act, env)))\n# (recursive group)"
  },
  {
    "path": "compiler/lib/test/ActonSpec.hs",
    "content": "{-# LANGUAGE OverloadedStrings, ScopedTypeVariables #-}\n\nmodule Main (main) where\n\nimport Data.Char (toLower, isAlphaNum)\n\n\nimport qualified Acton.Parser as P\nimport qualified Acton.Syntax as S\nimport qualified Acton.Builtin as Builtin\nimport qualified Acton.NameInfo as I\nimport qualified Acton.Printer as AP\nimport qualified Acton.DocPrinter as DocP\nimport qualified Acton.Env\nimport Acton.Env (CompilationError(..))\nimport qualified Acton.Kinds\nimport qualified Acton.Types\nimport Acton.TypeEnv (TypeError(..),typeReport)\nimport qualified Acton.Normalizer\nimport qualified Acton.Deactorizer\nimport qualified Acton.CPS\nimport qualified Acton.LambdaLifter\nimport qualified Acton.Boxing\nimport qualified Acton.CodeGen\nimport qualified Acton.Diagnostics as Diag\nimport qualified Acton.Compile as Compile\nimport qualified Acton.Fingerprint as Fingerprint\nimport qualified Acton.Completion as Completion\nimport qualified InterfaceFiles\nimport Pretty (print, prettyText)\nimport qualified Pretty\nimport Test.Syd\nimport Test.Syd.Def.Golden (goldenTextFile)\nimport qualified Control.Monad.Trans.State.Strict as St\nimport Text.Megaparsec (ParseErrorBundle, PosState(..), bundleErrors, bundlePosState, errorOffset, reachOffset, runParser, errorBundlePretty, ShowErrorComponent(..))\nimport Text.Megaparsec.Pos (sourceLine, unPos)\nimport qualified Data.Text as T\nimport Data.List (isInfixOf, isPrefixOf, nub, sort)\nimport qualified Data.List.NonEmpty as NE\nimport Data.IORef\nimport Data.Bits (shiftL, (.|.))\nimport Error.Diagnose (printDiagnostic, prettyDiagnostic, WithUnicode(..), TabSize(..), defaultStyle, addReport, addFile)\nimport Error.Diagnose.Report (Report(..))\nimport Prettyprinter (unAnnotate, layoutPretty, defaultLayoutOptions)\nimport Prettyprinter.Render.Text (renderStrict)\nimport System.FilePath ((</>), joinPath, takeFileName, takeBaseName, takeDirectory, splitDirectories, takeExtension)\nimport System.Directory (createDirectoryIfMissing, getCurrentDirectory, setCurrentDirectory, listDirectory, doesDirectoryExist)\nimport System.IO.Temp (withSystemTempDirectory)\nimport Control.Monad (forM_, when, foldM)\nimport qualified Control.Exception as E\nimport Control.DeepSeq (rnf)\nimport Utils (SrcLoc(..), loc, prstr)\nimport qualified Acton.BuildSpec as BuildSpec\nimport qualified Data.Binary as Binary\nimport qualified Data.ByteString.Lazy as BL\nimport qualified Data.ByteString.Char8 as B8\nimport qualified Data.Aeson as Ae\nimport qualified System.IO.Unsafe\n\n\n\n\nmain :: IO ()\nmain = do\n  let sysTypesPath = \"..\" </> \"..\" </> \"dist\" </> \"base\" </> \"out\" </> \"types\"\n  env0 <- Acton.Env.initEnv sysTypesPath False\n\n  sydTest $ do\n    describe \"Environment\" $ do\n      it \"treats mismatched .ty headers for loaded modules as stale\" $ do\n        withSystemTempDirectory \"acton-env\" $ \\dir -> do\n          let directMod = S.modName [\"direct\"]\n              directTy = dir </> \"direct.ty\"\n              valueName = S.name \"value\"\n              iface = [(valueName, I.NVar S.tWild)]\n              directIface = I.NModule [] iface Nothing\n              directModule = S.Module directMod [] Nothing []\n              env1 = Acton.Env.addMod directMod [] iface Nothing env0\n          InterfaceFiles.writeFile\n            directTy\n            B8.empty\n            B8.empty\n            B8.empty\n            Nothing\n            []\n            []\n            []\n            []\n            Nothing\n            directIface\n            directModule\n          (_mods, nmod, tmod, sourceMeta, srcHash, pubHash, implHash, imps, nameHashes, roots, tests, mdoc) <-\n            InterfaceFiles.readFile directTy\n          BL.writeFile directTy $\n            Binary.encode\n              ( (map (+ 1) S.version, sourceMeta, srcHash, pubHash, implHash)\n              , imps, nameHashes, roots, tests, mdoc, nmod, tmod\n              )\n          (_env2, te) <- Acton.Env.doImp [dir] env1 directMod\n          map fst te `shouldBe` [valueName]\n\n    describe \"Pass 1: Parser\" $ do\n\n      it \"reports rough parse progress by source offset\" $ do\n        progressRef <- newIORef []\n        _ <- P.parseModule (S.modName [\"progress\"]) \"progress.act\" \"x = 1\\n\" (Just $ \\completed total ->\n          modifyIORef' progressRef (++ [(completed, total)]))\n        progress <- readIORef progressRef\n        let completed = map fst progress\n            monotonic xs = and (zipWith (<=) xs (drop 1 xs))\n        progress `shouldSatisfy` (not . null)\n        completed `shouldSatisfy` monotonic\n        last progress `shouldBe` (6, 6)\n\n      describe \"Basic Syntax\" $ do\n        testParse env0 [\"syntax1\"]\n\n      describe \"Docstrings\" $ do\n        testParse env0 [\"docstrings\"]\n        testDocstrings env0 \"docstrings\"\n\n      describe \"Module Structure\" $ do\n        describe \"Module-level docstrings\" $ do\n          it \"allows single-line docstring before import\" $ do\n            let input = \"\\\"\\\"\\\"Module docstring\\\"\\\"\\\"\\nimport math\\n\"\n            case parseModuleTest input of\n              Left err -> expectationFailure $ \"Parse failed: \" ++ err\n              Right _ -> return ()\n\n          it \"allows multi-line docstring before import\" $ do\n            let input = \"\\\"\\\"\\\"Module docstring\\nwith multiple lines\\\"\\\"\\\"\\nimport math\\n\"\n            case parseModuleTest input of\n              Left err -> expectationFailure $ \"Parse failed: \" ++ err\n              Right _ -> return ()\n\n        describe \"Invalid module structure (before imports)\" $ do\n          testModuleParseError \"module_var_before_import\" \"x = 42\\nimport math\\n\"\n          testModuleParseError \"module_call_before_import\" \"print(\\\"hello\\\")\\nimport math\\n\"\n          testModuleParseError \"module_number_before_import\" \"42\\nimport math\\n\"\n          testModuleParseError \"module_list_before_import\" \"[1, 2, 3]\\nimport math\\n\"\n          testModuleParseError \"module_dict_before_import\" \"{\\\"key\\\": \\\"value\\\"}\\nimport math\\n\"\n          testModuleParseError \"module_if_before_import\" \"if True:\\n    pass\\nimport math\\n\"\n          testModuleParseError \"module_for_before_import\" \"for i in range(10):\\n    pass\\nimport math\\n\"\n          testModuleParseError \"module_class_before_import\" \"class Foo:\\n    pass\\nimport math\\n\"\n          testModuleParseError \"module_func_before_import\" \"def foo():\\n    pass\\nimport math\\n\"\n          testModuleParseError \"module_actor_before_import\" \"actor Foo():\\n    pass\\nimport math\\n\"\n\n        describe \"Module-level constants\" $ do\n          it \"allows top-level declarations, signatures, and assignments\" $ do\n            expectModuleParseSuccess $ unlines\n              [ \"value : int\"\n              , \"def helper() -> int:\"\n              , \"    return 41\"\n              , \"value = helper()\"\n              ]\n\n          it \"rejects top-level expression statements\" $ do\n            err <- expectModuleParseFailure $ unlines\n              [ \"value = 1\"\n              , \"1 + 2\"\n              ]\n            err `shouldContain` \"Only declarations and assignments are allowed at the module top level\"\n\n          it \"rejects top-level control flow\" $ do\n            err <- expectModuleParseFailure $ unlines\n              [ \"import math\"\n              , \"if True:\"\n              , \"    value = 1\"\n              ]\n            err `shouldContain` \"Only declarations and assignments are allowed at the module top level\"\n\n          it \"rejects top-level reassignment\" $ do\n            err <- expectModuleParseFailure $ unlines\n              [ \"value = 1\"\n              , \"value = 2\"\n              ]\n            err `shouldContain` \"Module top-level name 'value' cannot be assigned more than once\"\n\n          it \"allows top-level destructuring with at least one bound name\" $ do\n            expectModuleParseSuccess \"left, _ = (1, 2)\\n\"\n\n          it \"rejects duplicate names within one top-level assignment\" $ do\n            err <- expectModuleParseFailure \"left, left = (1, 2)\\n\"\n            err `shouldContain` \"Module top-level name 'left' cannot be assigned more than once\"\n\n          it \"rejects top-level wildcard-only assignment\" $ do\n            _ <- expectModuleParseFailure \"_ = 1\\n\"\n            return ()\n\n          it \"rejects top-level assignments with no bound names\" $ do\n            err <- expectModuleParseFailure \"[] = []\\n\"\n            err `shouldContain` \"Module top-level assignments must bind at least one name\"\n\n          it \"rejects top-level wildcard-only destructuring assignment\" $ do\n            err <- expectModuleParseFailure \"[_, _] = [1, 2]\\n\"\n            err `shouldContain` \"Module top-level assignments must bind at least one name\"\n\n        describe \"Chunked module parser\" $ do\n          it \"matches the serial parser for mixed top-level forms\" $ do\n            expectChunkedParseMatchesSerial $ unlines\n              [ \"\\\"\\\"\\\"module docs\\\"\\\"\\\"\"\n              , \"import math\"\n              , \"answer: int\"\n              , \"answer = (\"\n              , \"    40 +\"\n              , \"    2\"\n              , \")\"\n              , \"class Box:\"\n              , \"    def get(self):\"\n              , \"        return answer\"\n              , \"actor Worker(env):\"\n              , \"    def run(self):\"\n              , \"        env.exit(0)\"\n              ]\n\n          it \"does not split on column-zero text inside strings\" $ do\n            expectChunkedParseMatchesSerial $ unlines\n              [ \"text = \\\"\\\"\\\"\"\n              , \"def not_a_chunk():\"\n              , \"    pass\"\n              , \"\\\"\\\"\\\"\"\n              , \"formatted = \\\"value {str('class also_not_a_chunk:')}\\\"\"\n              , \"def real():\"\n              , \"    return text\"\n              ]\n\n          it \"matches triple-string quote run handling\" $ do\n            expectChunkedParseMatchesSerial $ unlines\n              [ \"quote_tail = \\\"\\\"\\\"foo\\\"\\\"\\\"\\\"\"\n              , \"two_quote_tail = \\\"\\\"\\\"foo\\\"\\\"\\\"\\\"\\\"\"\n              , \"formatted = \\\"\\\"\\\"value {str(\\\"class not_a_chunk:\\\")}\\\"\\\"\\\"\\\"\"\n              , \"def real():\"\n              , \"    return formatted\"\n              ]\n\n          it \"preserves adjacent declaration grouping\" $ do\n            expectChunkedParseMatchesSerial $ unlines\n              [ \"def even(n):\"\n              , \"    if n == 0:\"\n              , \"        return True\"\n              , \"    return odd(n - 1)\"\n              , \"def odd(n):\"\n              , \"    if n == 0:\"\n              , \"        return False\"\n              , \"    return even(n - 1)\"\n              , \"value = even(2)\"\n              ]\n\n          it \"reports later chunk parse errors at original source lines\" $ do\n            let input = unlines\n                  [ \"ok = 1\"\n                  , \"def broken():\"\n                  , \"    if True\"\n                  , \"        pass\"\n                  ]\n                moduleName = S.modName [\"chunked\"]\n            result <- E.try (P.parseModule moduleName \"chunked.act\" input Nothing)\n            case result of\n              Left (bundle :: ParseErrorBundle String P.CustomParseError) ->\n                parseBundleErrorLine bundle `shouldBe` 3\n              Right _ ->\n                expectationFailure \"Expected chunked parser to reject malformed input\"\n\n          it \"returns diagnostics for chunk scanner failures\" $ do\n            let input = \"    pass\\n\"\n                moduleName = S.modName [\"chunked\"]\n            result <- Compile.parseActSource Compile.defaultCompileOptions moduleName \"chunked.act\" input Nothing\n            case result of\n              Left [diagnostic] ->\n                renderDiagnosticText diagnostic `shouldContain` \"non-top-level text before first chunk\"\n              Left diagnostics ->\n                expectationFailure (\"Expected one diagnostic, got \" ++ show (length diagnostics))\n              Right _ ->\n                expectationFailure \"Expected scanner failure diagnostic\"\n\n          it \"matches the serial parser for existing fixtures\" $ do\n            actFiles <- actFilesUnder (\"test\" </> \"src\")\n            forM_ actFiles $ \\actFile -> do\n              input <- readFile actFile\n              expectChunkedParseMatchesSerialFile actFile input\n\n      describe \"Numeric literals\" $ do\n        it \"parses INT64_MIN as a single literal\" $ do\n          case parseStmtAst \"a = -9223372036854775808\" of\n            Left err -> expectationFailure $ \"Parse failed: \" ++ err\n            Right [S.Assign _ _ expr] -> case expr of\n              S.Int _ ival lexeme -> do\n                ival `shouldBe` (-9223372036854775808)\n                lexeme `shouldBe` \"-9223372036854775808\"\n              other -> expectationFailure $ \"Expected Int literal, got \" ++ show other\n            Right other -> expectationFailure $ \"Unexpected AST: \" ++ show other\n\n        it \"keeps unary minus above exponentiation for -1**2\" $ do\n          case parseExprAst \"-1**2\" of\n            Left err -> expectationFailure $ \"Parse failed: \" ++ err\n            Right (S.UnOp _ S.UMinus inner) -> case inner of\n              S.BinOp _ lhs op rhs -> do\n                op `shouldBe` S.Pow\n                case lhs of\n                  S.Int _ ival lexeme -> do\n                    ival `shouldBe` 1\n                    lexeme `shouldBe` \"1\"\n                  other -> expectationFailure $ \"Expected left int literal, got \" ++ show other\n                case rhs of\n                  S.Int _ ival lexeme -> do\n                    ival `shouldBe` 2\n                    lexeme `shouldBe` \"2\"\n                  other -> expectationFailure $ \"Expected right int literal, got \" ++ show other\n              other -> expectationFailure $ \"Expected power expression, got \" ++ show other\n            Right other -> expectationFailure $ \"Expected unary minus, got \" ++ show other\n\n        it \"respects parentheses for (-1)**2\" $ do\n          case parseExprAst \"(-1)**2\" of\n            Left err -> expectationFailure $ \"Parse failed: \" ++ err\n            Right (S.BinOp _ lhs op rhs) -> do\n              op `shouldBe` S.Pow\n              case lhs of\n                S.Paren _ (S.Int _ ival lexeme) -> do\n                  ival `shouldBe` (-1)\n                  lexeme `shouldBe` \"-1\"\n                other -> expectationFailure $ \"Expected parenthesized negative literal, got \" ++ show other\n              case rhs of\n                S.Int _ ival lexeme -> do\n                  ival `shouldBe` 2\n                  lexeme `shouldBe` \"2\"\n                other -> expectationFailure $ \"Expected right int literal, got \" ++ show other\n            Right other -> expectationFailure $ \"Expected power expression, got \" ++ show other\n\n      describe \"Optional chaining\" $ do\n        it \"parses optional chaining expression statements without crashing\" $ do\n          case parseStmtAst \"l?.append(1)\" of\n            Left err -> expectationFailure $ \"Parse failed: \" ++ err\n            Right [S.Expr _ expr@S.OptChain{}] -> loc expr `shouldNotBe` NoLoc\n            Right other -> expectationFailure $ \"Unexpected AST: \" ++ show other\n\n      describe \"Completion\" $ do\n        it \"completes inherited transform input attributes\" $ do\n          let env = completionFixtureEnv env0\n              (src, cursor) = cursorSource $ unlines\n                [ \"import mini.layers.base_1 as base\"\n                , \"import mini.layers.y_1 as y1\"\n                , \"\"\n                , \"class L3vpnEndpoint(base.L3vpnEndpoint):\"\n                , \"    def transform(self, i, di):\"\n                , \"        i.<CURSOR>\"\n                ]\n          items <- Completion.memberCompletions env [] (S.modName [\"rfs\"]) \"rfs.act\" src cursor\n          let labels = map Completion.completionLabel items\n          forM_ [\"interface_name\", \"vpn_name\", \"ipv4_address\"] $ \\label ->\n            labels `shouldSatisfy` elem label\n\n        it \"completes explicitly typed transform input attributes\" $ do\n          let env = completionFixtureEnv env0\n              inputTypeName = \"y1.stratoweave_rfs__rfs__l3vpn_endpoint_entry\"\n              (src, cursor) = cursorSource $ unlines\n                [ \"import mini.layers.base_1 as base\"\n                , \"import mini.layers.y_1 as y1\"\n                , \"\"\n                , \"class L3vpnEndpoint(base.L3vpnEndpoint):\"\n                , \"    def transform(self, i: \" ++ inputTypeName ++ \", di):\"\n                , \"        i.v<CURSOR>\"\n                ]\n          items <- Completion.memberCompletions env [] (S.modName [\"rfs\"]) \"rfs.act\" src cursor\n          map Completion.completionLabel items `shouldBe` [\"vpn_name\"]\n\n        it \"completes annotated parameters inside generic functions\" $ do\n          let env = completionFixtureEnv env0\n              inputTypeName = \"y1.stratoweave_rfs__rfs__l3vpn_endpoint_entry\"\n              (src, cursor) = cursorSource $ unlines\n                [ \"import mini.layers.y_1 as y1\"\n                , \"\"\n                , \"def helper [T](i: \" ++ inputTypeName ++ \"):\"\n                , \"    i.v<CURSOR>\"\n                ]\n          items <- Completion.memberCompletions env [] (S.modName [\"rfs\"]) \"rfs.act\" src cursor\n          map Completion.completionLabel items `shouldBe` [\"vpn_name\"]\n\n        it \"completes local values assigned from typed calls\" $ do\n          let env = completionFixtureEnv env0\n              (src, cursor) = cursorSource $ unlines\n                [ \"import mini.layers.base_1 as base\"\n                , \"\"\n                , \"class L3vpnEndpoint(base.L3vpnEndpoint):\"\n                , \"    def transform(self, i, di):\"\n                , \"        o = base.o_root()\"\n                , \"        o.<CURSOR>\"\n                ]\n          items <- Completion.memberCompletions env [] (S.modName [\"rfs\"]) \"rfs.act\" src cursor\n          map Completion.completionLabel items `shouldSatisfy` elem \"netinfra\"\n\n        it \"completes local values assigned from nested member calls\" $ do\n          let env = completionFixtureEnv env0\n              (src, cursor) = cursorSource $ unlines\n                [ \"import mini.layers.base_1 as base\"\n                , \"\"\n                , \"class L3vpnEndpoint(base.L3vpnEndpoint):\"\n                , \"    def transform(self, i, di):\"\n                , \"        o = base.o_root()\"\n                , \"        o_router = o.netinfra.router.create(i.name, id=i.id)\"\n                , \"        o_router.<CURSOR>\"\n                ]\n          items <- Completion.memberCompletions env [] (S.modName [\"rfs\"]) \"rfs.act\" src cursor\n          map Completion.completionLabel items `shouldSatisfy` elem \"router_id\"\n\n        it \"completes local values assigned from member paths\" $ do\n          let env = completionFixtureEnv env0\n              (src, cursor) = cursorSource $ unlines\n                [ \"import mini.layers.base_1 as base\"\n                , \"\"\n                , \"class L3vpnEndpoint(base.L3vpnEndpoint):\"\n                , \"    def transform(self, i, di):\"\n                , \"        o = base.o_root()\"\n                , \"        o_router = o.netinfra.router.create(i.name, id=i.id)\"\n                , \"        bc = o_router.base_config\"\n                , \"        bc.<CURSOR>\"\n                ]\n          items <- Completion.memberCompletions env [] (S.modName [\"rfs\"]) \"rfs.act\" src cursor\n          map Completion.completionLabel items `shouldSatisfy` elem \"asn\"\n          [ Completion.completionDetail item\n            | item <- items\n            , Completion.completionLabel item == \"asn\"\n            ] `shouldBe` [Just \"int\"]\n\n        it \"uses inherited parameter types inside generic classes\" $ do\n          let env = completionFixtureEnv env0\n              (src, cursor) = cursorSource $ unlines\n                [ \"import mini.layers.base_1 as base\"\n                , \"\"\n                , \"class L3vpnEndpoint[T](base.L3vpnEndpoint):\"\n                , \"    def transform(self, i, di):\"\n                , \"        i.<CURSOR>\"\n                ]\n          items <- Completion.memberCompletions env [] (S.modName [\"rfs\"]) \"rfs.act\" src cursor\n          map Completion.completionLabel items `shouldSatisfy` elem \"interface_name\"\n\n        it \"resolves inherited parameter types in the parent module\" $ do\n          let env = completionFixtureEnv env0\n              (src, cursor) = cursorSource $ unlines\n                [ \"import mini.layers.base_1 as base\"\n                , \"\"\n                , \"class LocalEndpoint(base.LocalEndpoint):\"\n                , \"    def transform(self, i):\"\n                , \"        a = i.<CURSOR>\"\n                ]\n          items <- Completion.memberCompletions env [] (S.modName [\"rfs\"]) \"rfs.act\" src cursor\n          map Completion.completionLabel items `shouldSatisfy` elem \"local_field\"\n\n        it \"uses direct imports when transitive interfaces are stale\" $ do\n          withSystemTempDirectory \"acton-completion\" $ \\dir -> do\n            let directMod = S.modName [\"direct\"]\n                staleMod = S.modName [\"stale\"]\n                directTy = dir </> \"direct.ty\"\n                staleTy = dir </> \"stale.ty\"\n                inputName = S.name \"LocalInput\"\n                routerName = S.name \"Router\"\n                inputType = S.tCon (S.TC (S.NoQ inputName) [])\n                transformType =\n                  S.tFun S.fxMut\n                    (S.posRow inputType S.posNil)\n                    S.kwdNil\n                    S.tWild\n                transformInfo = I.NSig (S.tSchema [] transformType) S.NoDec Nothing\n                inputClass = I.NClass [] [] [(S.name \"local_field\", I.NVar S.tWild)] Nothing\n                routerClass = I.NClass [] [] [(S.name \"transform\", transformInfo)] Nothing\n                directIface = I.NModule []\n                  [ (routerName, routerClass)\n                  , (inputName, inputClass)\n                  ] Nothing\n                directModule = S.Module directMod [] Nothing []\n                (src, cursor) = cursorSource $ unlines\n                  [ \"import direct as base\"\n                  , \"\"\n                  , \"class Router(base.Router):\"\n                  , \"    def transform(self, i):\"\n                  , \"        i.<CURSOR>\"\n                  ]\n            createDirectoryIfMissing True dir\n            B8.writeFile staleTy \"not a current ty file\"\n            InterfaceFiles.writeFile\n              directTy\n              B8.empty\n              B8.empty\n              B8.empty\n              Nothing\n              [(staleMod, B8.empty)]\n              []\n              []\n              []\n              Nothing\n              directIface\n              directModule\n            items <- Completion.memberCompletions env0 [dir] (S.modName [\"rfs\"]) \"rfs.act\" src cursor\n            map Completion.completionLabel items `shouldSatisfy` elem \"local_field\"\n\n        it \"shows signatures for nested member calls\" $ do\n          let env = completionFixtureEnv env0\n              (src, cursor) = cursorSource $ unlines\n                [ \"import mini.layers.base_1 as base\"\n                , \"\"\n                , \"class L3vpnEndpoint(base.L3vpnEndpoint):\"\n                , \"    def transform(self, i, di):\"\n                , \"        o = base.o_root()\"\n                , \"        o.netinfra.router.create(\\\"r1\\\", <CURSOR>)\"\n                ]\n          sigs <- Completion.callSignatures env [] (S.modName [\"rfs\"]) \"rfs.act\" src cursor\n          case sigs of\n            [sig] -> do\n              Completion.callSignatureLabel sig `shouldSatisfy` isPrefixOf \"o.netinfra.router.create(\"\n              Completion.callSignatureLabel sig `shouldSatisfy` not . isInfixOf \"__builtin__.\"\n              Completion.callSignatureActiveParameter sig `shouldBe` 1\n              let params = map Completion.signatureParameterLabel (Completion.callSignatureParameters sig)\n              params `shouldSatisfy` any (isPrefixOf \"arg1:\")\n              params `shouldSatisfy` any (isPrefixOf \"id:\")\n              params `shouldSatisfy` all (not . isInfixOf \"__builtin__.\")\n            other ->\n              expectationFailure $ \"Unexpected signatures: \" ++ show other\n\n        it \"ignores string parentheses when finding call signatures\" $ do\n          let env = completionFixtureEnv env0\n          forM_ [\"\\\"(\\\"\", \"\\\"x)\\\"\"] $ \\arg -> do\n            let (src, cursor) = cursorSource $ unlines\n                  [ \"import mini.layers.base_1 as base\"\n                  , \"\"\n                  , \"class L3vpnEndpoint(base.L3vpnEndpoint):\"\n                  , \"    def transform(self, i, di):\"\n                  , \"        o = base.o_root()\"\n                  , \"        o.netinfra.router.create(\" ++ arg ++ \", <CURSOR>)\"\n                  ]\n            sigs <- Completion.callSignatures env [] (S.modName [\"rfs\"]) \"rfs.act\" src cursor\n            case sigs of\n              [sig] ->\n                Completion.callSignatureActiveParameter sig `shouldBe` 1\n              other ->\n                expectationFailure $ \"Unexpected signatures: \" ++ show other\n\n        it \"completes keyword arguments for nested member calls\" $ do\n          let env = completionFixtureEnv env0\n              (src, cursor) = cursorSource $ unlines\n                [ \"import mini.layers.base_1 as base\"\n                , \"\"\n                , \"class L3vpnEndpoint(base.L3vpnEndpoint):\"\n                , \"    def transform(self, i, di):\"\n                , \"        o = base.o_root()\"\n                , \"        o.netinfra.router.create(\\\"r1\\\", <CURSOR>)\"\n                ]\n          items <- Completion.argumentCompletions env [] (S.modName [\"rfs\"]) \"rfs.act\" src cursor\n          map Completion.completionLabel items `shouldBe` [\"id=\", \"role=\", \"mock=\"]\n          map Completion.completionKind items `shouldBe` replicate 3 Completion.CompletionKeyword\n          map Completion.completionDetail items `shouldBe` map Just [\"int\", \"str\", \"bool\"]\n\n        it \"filters supplied keyword argument completions\" $ do\n          let env = completionFixtureEnv env0\n              (src, cursor) = cursorSource $ unlines\n                [ \"import mini.layers.base_1 as base\"\n                , \"\"\n                , \"class L3vpnEndpoint(base.L3vpnEndpoint):\"\n                , \"    def transform(self, i, di):\"\n                , \"        o = base.o_root()\"\n                , \"        o.netinfra.router.create(\\\"r1\\\", id=1, <CURSOR>)\"\n                ]\n          items <- Completion.argumentCompletions env [] (S.modName [\"rfs\"]) \"rfs.act\" src cursor\n          map Completion.completionLabel items `shouldBe` [\"role=\", \"mock=\"]\n\n        it \"prefixes keyword argument completions\" $ do\n          let env = completionFixtureEnv env0\n              (src, cursor) = cursorSource $ unlines\n                [ \"import mini.layers.base_1 as base\"\n                , \"\"\n                , \"class L3vpnEndpoint(base.L3vpnEndpoint):\"\n                , \"    def transform(self, i, di):\"\n                , \"        o = base.o_root()\"\n                , \"        o.netinfra.router.create(\\\"r1\\\", id=1, r<CURSOR>)\"\n                ]\n          items <- Completion.argumentCompletions env [] (S.modName [\"rfs\"]) \"rfs.act\" src cursor\n          map Completion.completionLabel items `shouldBe` [\"role=\"]\n\n        it \"keeps escaped commas inside string arguments\" $ do\n          let env = completionFixtureEnv env0\n              (src, cursor) = cursorSource $ unlines\n                [ \"import mini.layers.base_1 as base\"\n                , \"\"\n                , \"class L3vpnEndpoint(base.L3vpnEndpoint):\"\n                , \"    def transform(self, i, di):\"\n                , \"        o = base.o_root()\"\n                , \"        o.netinfra.router.create(\\\"r1\\\", id=1, role=\\\"a\\\\\\\",b\\\", m<CURSOR>)\"\n                ]\n          items <- Completion.argumentCompletions env [] (S.modName [\"rfs\"]) \"rfs.act\" src cursor\n          map Completion.completionLabel items `shouldBe` [\"mock=\"]\n\n        it \"does not complete keyword names inside argument values\" $ do\n          let env = completionFixtureEnv env0\n              (src, cursor) = cursorSource $ unlines\n                [ \"import mini.layers.base_1 as base\"\n                , \"\"\n                , \"class L3vpnEndpoint(base.L3vpnEndpoint):\"\n                , \"    def transform(self, i, di):\"\n                , \"        o = base.o_root()\"\n                , \"        o.netinfra.router.create(\\\"r1\\\", id=<CURSOR>)\"\n                ]\n          items <- Completion.argumentCompletions env [] (S.modName [\"rfs\"]) \"rfs.act\" src cursor\n          items `shouldBe` []\n\n        it \"hovers local values assigned from member paths\" $ do\n          let env = completionFixtureEnv env0\n              (src, cursor) = cursorSource $ unlines\n                [ \"import mini.layers.base_1 as base\"\n                , \"\"\n                , \"class L3vpnEndpoint(base.L3vpnEndpoint):\"\n                , \"    def transform(self, i, di):\"\n                , \"        o = base.o_root()\"\n                , \"        o_router = o.netinfra.router.create(i.name, id=i.id)\"\n                , \"        bc = o_router.base_config\"\n                , \"        bc<CURSOR>.asn = 1\"\n                ]\n          info <- Completion.hoverInfo env [] (S.modName [\"rfs\"]) \"rfs.act\" src cursor\n          case info of\n            Just hover -> do\n              Completion.hoverDetail hover `shouldSatisfy` isInfixOf \"BaseConfig\"\n              Completion.hoverDocumentation hover `shouldBe` Just \"Base router configuration.\"\n            Nothing ->\n              expectationFailure \"Expected hover info for bc\"\n\n        it \"hovers nested member fields\" $ do\n          let env = completionFixtureEnv env0\n              (src, cursor) = cursorSource $ unlines\n                [ \"import mini.layers.base_1 as base\"\n                , \"\"\n                , \"class L3vpnEndpoint(base.L3vpnEndpoint):\"\n                , \"    def transform(self, i, di):\"\n                , \"        o = base.o_root()\"\n                , \"        o_router = o.netinfra.router.create(i.name, id=i.id)\"\n                , \"        bc = o_router.base_config\"\n                , \"        bc.<CURSOR>asn = 1\"\n                ]\n          info <- Completion.hoverInfo env [] (S.modName [\"rfs\"]) \"rfs.act\" src cursor\n          case info of\n            Just hover -> do\n              Completion.hoverDetail hover `shouldBe` \"bc.asn: int\"\n              Completion.hoverDocumentation hover `shouldBe` Just \"Autonomous system number.\"\n            Nothing ->\n              expectationFailure \"Expected hover info for bc.asn\"\n\n        it \"hovers methods resolved through local call results\" $ do\n          let env = completionFixtureEnv env0\n              (src, cursor) = cursorSource $ unlines\n                [ \"import mini.layers.base_1 as base\"\n                , \"\"\n                , \"class L3vpnEndpoint(base.L3vpnEndpoint):\"\n                , \"    def transform(self, i, di):\"\n                , \"        o = base.o_root()\"\n                , \"        o.netinfra.router.<CURSOR>create(\\\"r1\\\", id=1)\"\n                ]\n          info <- Completion.hoverInfo env [] (S.modName [\"rfs\"]) \"rfs.act\" src cursor\n          case info of\n            Just hover -> do\n              Completion.hoverDetail hover `shouldSatisfy` isPrefixOf \"o.netinfra.router.create:\"\n              Completion.hoverDetail hover `shouldSatisfy` isInfixOf \"RouterEntry\"\n              Completion.hoverDetail hover `shouldSatisfy` not . isInfixOf \"__builtin__.\"\n              Completion.hoverDocumentation hover `shouldBe` Just \"Create a router entry.\"\n            Nothing ->\n              expectationFailure \"Expected hover info for create\"\n\n        it \"ignores imported module path hovers\" $ do\n          let env = completionFixtureEnv env0\n              (src, cursor) = cursorSource \"import mini.layers.y_1<CURSOR>\\n\"\n          result <- E.try (E.evaluate (Completion.hoverInfoWithEnv env src cursor))\n          case result of\n            Left (err :: E.SomeException) ->\n              expectationFailure $ \"Unexpected hover exception: \" ++ E.displayException err\n            Right info ->\n              info `shouldBe` Nothing\n\n      describe \"String Interpolation\" $ do\n        -- Note: In these tests, we use Haskell string literals which require escaping.\n        -- The test format is: testParseOutput <Haskell literal> <expected parser output>\n        --\n        -- Examples of what the Haskell escapes mean in actual Acton code:\n        --   Haskell literal: \"\\\"\\\"\"           → Acton code: \"\"\n        --   Haskell literal: \"\\\"hello\\\"\"      → Acton code: \"hello\"\n        --   Haskell literal: \"'world'\"        → Acton code: 'world'\n        --   Haskell literal: \"f\\\"x = {x}\\\"\"   → Acton code: f\"x = {x}\"\n        --   Haskell literal: \"\\\"x = {x}\\\"\"    → Acton code: \"x = {x}\"\n        --\n        -- Interpolation is a core feature in standard Acton strings.\n        -- Both \"string {expr}\" and f\"string {expr}\" support interpolation\n\n        -- Basic functionality (simplest to more complex)\n        describe \"Basic string literals\" $ do\n          testParseOutput \"\\\"\\\"\" \"\\\"\\\"\"\n          testParseOutput \"\\\"plain text\\\"\" \"\\\"plain text\\\"\"\n          testParseOutput \"'hello world'\" \"\\\"hello world\\\"\"  -- single quotes convert to double\n\n        describe \"Basic interpolation\" $ do\n          testParseOutput \"\\\"hello {name}\\\"\" \"\\\"hello %s\\\" % str(name)\"  -- default interpolation\n          testParseOutput \"f\\\"hello {name}!\\\"\" \"\\\"hello %s!\\\" % str(name)\"  -- with f-prefix\n          testParseOutput \"'Value: {x}'\" \"\\\"Value: %s\\\" % str(x)\"  -- single quotes work too\n\n        describe \"Multiple interpolations\" $ do\n          testParseOutput \"f\\\"Hello {name}, your score is {score}\\\"\" \"\\\"Hello %s, your score is %s\\\" % (str(name), str(score))\"\n          testParseOutput \"\\\"First: {a}, Second: {b}, Third: {c}\\\"\" \"\\\"First: %s, Second: %s, Third: %s\\\" % (str(a), str(b), str(c))\"\n\n        describe \"Expressions in interpolation\" $ do\n          testParseOutput \"\\\"Sum: {a + b}\\\"\" \"\\\"Sum: %s\\\" % str(a + b)\"  -- simple expression\n          testParseOutput \"f\\\"Calculation: {a * b // 2}\\\"\" \"\\\"Calculation: %s\\\" % str(a * b // 2)\"  -- complex expression\n          testParseOutput \"f\\\"Result: {func({a: b})}\\\"\" \"\\\"Result: %s\\\" % str(func({a: b}))\"  -- nested braces\n\n        describe \"Formatting specifications\" $ do\n          -- Width\n          testParseOutput \"f\\\"{num:5}\\\"\" \"\\\"%5s\\\" % str(num)\"\n          testParseOutput \"f\\\"{num:10}\\\"\" \"\\\"%10s\\\" % str(num)\"\n\n          -- Alignment\n          testParseOutput \"f\\\"{name:<9}\\\"\" \"\\\"%-9s\\\" % str(name)\"           -- left\n          testParseOutput \"f\\\"{name:>10}\\\"\" \"\\\"%10s\\\" % str(name)\"         -- right\n          testParseOutput \"f\\\"{name:^10}\\\"\" \"\\\"%s\\\" % str(name).center(10)\" -- center\n\n          -- Zero padding\n          testParseOutput \"f\\\"{num:05}\\\"\" \"\\\"%05d\\\" % num\"\n          testParseOutput \"f\\\"{num:010}\\\"\" \"\\\"%010d\\\" % num\"\n\n          -- Floating point precision\n          testParseOutput \"f\\\"{pi:.2f}\\\"\" \"\\\"%.2f\\\" % pi\"\n          testParseOutput \"f\\\"{pi:.4f}\\\"\" \"\\\"%.4f\\\" % pi\"\n          testParseOutput \"f\\\"{pi:.0f}\\\"\" \"\\\"%.0f\\\" % pi\"\n          testParseOutput \"f\\\"{pi:10.2f}\\\"\" \"\\\"%10.2f\\\" % pi\"\n\n          -- Combined formatting\n          testParseOutput \"f\\\"{a:>10}:{b:^10}:{c:<10}\\\"\" \"\\\"%10s:%s:%-10s\\\" % (str(a), str(b).center(10), str(c))\"\n          testParseOutput \"f\\\"{num:+08.2f}\\\"\" \"\\\"%08.2f\\\" % num\"\n\n          -- Spaces in format spec (various positions allowed)\n          testParseOutput \"f\\\"{ num : 10 }\\\"\" \"\\\"%10s\\\" % str(num)\"  -- spaces everywhere\n\n        describe \"String quote variations\" $ do\n          -- Triple quotes support interpolation by default\n          testParseOutput \"\\\"\\\"\\\"hello {name}!\\\"\\\"\\\"\" \"\\\"hello %s!\\\" % str(name)\"  -- triple double quotes\n          testParseOutput \"'''multi-line\\n{value}'''\" \"\\\"multi-line\\\\\\\\n%s\\\" % str(value)\"  -- triple single quotes\n          testParseOutput \"f\\\"\\\"\\\"Name: {name}\\nAge: {age}\\\"\\\"\\\"\" \"\\\"Name: %s\\\\\\\\nAge: %s\\\" % (str(name), str(age))\"  -- f-prefix with multi-line\n          testParseOutput \"\\\"\\\"\\\"Plain text without interpolation\\\"\\\"\\\"\" \"\\\"Plain text without interpolation\\\"\"  -- no braces = no interpolation\n\n        describe \"Triple quotes with 4-5 quotes (ending with quotes)\" $ do\n          -- Triple double quotes with 4 quotes (string ends with single \")\n          testParseOutput \"\\\"\\\"\\\"\\\"foo\\\"\\\"\\\"\" \"\\\"\\\\\\\"foo\\\"\"  -- \"\"\"\"foo\"\"\" -> \"foo (1 quote in content)\n          testParseOutput \"\\\"\\\"\\\"\\\"hello world\\\"\\\"\\\"\\\"\" \"\\\"\\\\\\\"hello world\\\\\\\"\\\"\"  -- \"\"\"\"\"hello world\"\"\"\"\" -> \"\"hello world\"\" (2 quotes in content)\n          testParseOutput \"r\\\"\\\"\\\"\\\"raw quote\\\"\\\"\\\"\" \"\\\"\\\\\\\"raw quote\\\"\"  -- raw string with 4 quotes\n          testParseOutput \"r\\\"\\\"\\\"\\\"\\\"raw two quotes\\\"\\\"\\\"\" \"\\\"\\\\\\\"\\\\\\\"raw two quotes\\\"\"  -- raw string with 5 quotes\n\n          -- Triple single quotes with 4 quotes (string ends with single ')\n          testParseOutput \"''''bar'''\" \"\\\"'bar\\\"\"  -- ''''bar''' -> 'bar (1 quote in content)\n          testParseOutput \"'''''test me'''''\" \"\\\"''test me''\\\"\"  -- '''''test me''''' -> ''test me'' (2 quotes in content)\n          testParseOutput \"r''''raw single'''\" \"\\\"'raw single\\\"\"  -- raw string with 4 quotes\n          testParseOutput \"r'''''raw two singles'''\" \"\\\"''raw two singles\\\"\"  -- raw string with 5 quotes\n\n          -- Interpolation with trailing quotes\n          testParseOutput \"\\\"\\\"\\\"\\\"value: {x}\\\"\\\"\\\"\" \"\\\"\\\\\\\"value: %s\\\" % str(x)\"  -- interpolation with trailing quote\n          testParseOutput \"\\\"\\\"\\\"\\\"\\\"formatted {y}\\\"\\\"\\\"\\\"\\\"\" \"\\\"\\\\\\\"\\\\\\\"formatted %s\\\\\\\"\\\\\\\"\\\" % str(y)\"  -- 2 quotes before and after\n          testParseOutput \"f''''x = {x}'''\" \"\\\"'x = %s\\\" % str(x)\"  -- f-string with 4 single quotes\n          testParseOutput \"f'''''vals: {a}, {b}'''''\" \"\\\"''vals: %s, %s''\\\" % (str(a), str(b))\"  -- f-string with 5 single quotes\n\n        describe \"Triple quotes with 6+ quotes (error cases)\" $ do\n          -- Triple double quotes with 6+ quotes should fail\n          testParseError \"triple_double_6quotes\" \"\\\"\\\"\\\"foo\\\"\\\"\\\"\\\"\\\"\\\"\"  -- 3 opening, 6 closing\n          testParseError \"triple_double_7quotes\" \"\\\"\\\"\\\"bar\\\"\\\"\\\"\\\"\\\"\\\"\\\"\"  -- 3 opening, 7 closing\n          testParseError \"triple_double_8quotes\" \"\\\"\\\"\\\"test\\\"\\\"\\\"\\\"\\\"\\\"\\\"\\\"\"  -- 3 opening, 8 closing\n          testParseError \"triple_double_10quotes\" \"\\\"\\\"\\\"content\\\"\\\"\\\"\\\"\\\"\\\"\\\"\\\"\\\"\\\"\"  -- 3 opening, 10 closing\n\n          -- Triple single quotes with 6+ quotes should fail\n          testParseError \"triple_single_6quotes\" \"'''foo''''''\"  -- 3 opening, 6 closing\n          testParseError \"triple_single_7quotes\" \"'''bar'''''''\"  -- 3 opening, 7 closing\n          testParseError \"triple_single_8quotes\" \"'''test''''''''\"  -- 3 opening, 8 closing\n          testParseError \"triple_single_10quotes\" \"'''content''''''''''\"  -- 3 opening, 10 closing\n\n          -- Raw strings with 6+ quotes should fail\n          testParseError \"raw_triple_double_6quotes\" \"r\\\"\\\"\\\"raw\\\"\\\"\\\"\\\"\\\"\\\"\"  -- raw with 6 closing quotes\n          testParseError \"raw_triple_single_6quotes\" \"r'''raw''''''\"  -- raw with 6 closing quotes\n\n          -- F-strings with 6+ quotes should fail\n          testParseError \"fstring_triple_double_6quotes\" \"f\\\"\\\"\\\"x={x}\\\"\\\"\\\"\\\"\\\"\\\"\"  -- f-string with 6 closing quotes\n          testParseError \"fstring_triple_single_6quotes\" \"f'''x={x}''''''\"  -- f-string with 6 closing quotes\n\n        describe \"Special characters and escaping\" $ do\n          -- Escaped braces\n          testParseOutput \"f\\\"something but {{{substituted}}}\\\"\" \"\\\"something but {%s}\\\" % str(substituted)\"\n          testParseOutput \"\\\"{{a}}\\\"\" \"\\\"{a}\\\"\"  -- Escaped braces should not trigger interpolation\n          testParseOutput \"\\\"{{\\\"\" \"\\\"{\\\"\"  -- Just escaped opening brace\n          testParseOutput \"\\\"}}\\\"\" \"\\\"}\\\"\"  -- Just escaped closing brace\n          testParseOutput \"f\\\"{{hello}}\\\"\" \"\\\"{hello}\\\"\"  -- f-string with escaped braces\n          testParseOutput \"\\\"{{hello}} {world}\\\"\" \"\\\"{hello} %s\\\" % str(world)\"  -- Mix of escaped and interpolated\n\n          -- Escaped quotes\n          testParseOutput \"f\\\"hello \\\\\\\"thing\\\\\\\"\\\"\" \"\\\"hello \\\\\\\"thing\\\\\\\"\\\"\"\n          testParseOutput \"f'hello \\\\'thing\\\\''\" \"\\\"hello 'thing'\\\"\"\n          testParseOutput \"f\\\"Value: {x} with \\\\\\\"quotes\\\\\\\"\\\"\" \"\\\"Value: %s with \\\\\\\"quotes\\\\\\\"\\\" % str(x)\"\n\n          -- Unicode\n          testParseOutput \"f\\\"Hello, {name}! 你好!\\\"\" \"\\\"Hello, %s! \\\\20320\\\\22909!\\\" % str(name)\"\n\n        describe \"Slice expressions in interpolation\" $ do\n          -- Basic slice patterns\n          testParseOutput \"\\\"slice: {arr[1:3]}\\\"\" \"\\\"slice: %s\\\" % str(arr[1:3])\"  -- basic range\n          testParseOutput \"\\\"slice: {arr[:5]}\\\"\" \"\\\"slice: %s\\\" % str(arr[:5])\"  -- from start\n          testParseOutput \"\\\"slice: {arr[2:]}\\\"\" \"\\\"slice: %s\\\" % str(arr[2:])\"  -- to end\n\n          -- Step parameter\n          testParseOutput \"\\\"step: {arr[1:10:2]}\\\"\" \"\\\"step: %s\\\" % str(arr[1:10:2])\"  -- with step\n          testParseOutput \"\\\"reverse: {arr[::-1]}\\\"\" \"\\\"reverse: %s\\\" % str(arr[::-1])\"  -- negative step\n\n          -- Complex expressions\n          testParseOutput \"\\\"complex: {arr[i+1:j*2]}\\\"\" \"\\\"complex: %s\\\" % str(arr[i + 1:j * 2])\"  -- expressions in slice\n          testParseOutput \"\\\"nested: {matrix[i][j:k]}\\\"\" \"\\\"nested: %s\\\" % str(matrix[i][j:k])\"  -- nested indexing\n\n        describe \"Nested string interpolation\" $ do\n          testParseOutput \"\\\"outer {\\\"inner {x}\\\"}\\\"\" \"\\\"outer %s\\\" % str(\\\"inner %s\\\" % str(x))\"\n          testParseOutput \"\\\"outer {'inner {x}'}\\\"\" \"\\\"outer %s\\\" % str(\\\"inner %s\\\" % str(x))\"\n          testParseOutput \"'outer {\\\"inner {x}\\\"}'\" \"\\\"outer %s\\\" % str(\\\"inner %s\\\" % str(x))\"\n          testParseOutput \"\\\"level1 {\\\"level2 {\\\"level3 {x}\\\"}\\\"}\\\"\"  \"\\\"level1 %s\\\" % str(\\\"level2 %s\\\" % str(\\\"level3 %s\\\" % str(x)))\"\n          testParseOutput \"\\\"outer {{literal}} {\\\"inner {x}\\\"}\\\"\" \"\\\"outer {literal} %s\\\" % str(\\\"inner %s\\\" % str(x))\"\n\n        describe \"Escape sequences\" $ do\n          -- Standard escapes (preserved during parsing)\n          testParseOutput \"\\\"\\\\n\\\\t\\\\r\\\"\" \"\\\"\\\\\\\\n\\\\\\\\t\\\\\\\\r\\\"\"\n\n          -- Hex escapes (note splitting behavior when followed by hex chars)\n          testParseOutput \"\\\"\\\\x48ello\\\"\" \"\\\"\\\\\\\\x48\\\" \\\"ello\\\"\"  -- splits to prevent C reading too many hex digits\n          testParseOutput \"\\\"\\\\x41BC\\\"\" \"\\\"\\\\\\\\x41\\\" \\\"BC\\\"\"\n\n          -- Unicode escapes\n          testParseOutput \"\\\"\\\\u0041\\\"\" \"\\\"\\\\\\\\u0041\\\"\"  -- 4-digit unicode\n          testParseOutput \"\\\"\\\\U00000041\\\"\" \"\\\"\\\\\\\\U00000041\\\"\"  -- 8-digit unicode\n\n          -- Octal escapes\n          testParseOutput \"\\\"\\\\123\\\"\" \"\\\"\\\\\\\\123\\\"\"  -- 3-digit octal\n          testParseOutput \"\\\"\\\\7\\\"\" \"\\\"\\\\\\\\7\\\"\"  -- 1-digit octal\n\n          -- Mixed with interpolation\n          testParseOutput \"f\\\"Hello \\\\n{name}\\\\t!\\\"\" \"\\\"Hello \\\\\\\\n%s\\\\\\\\t!\\\" % str(name)\"\n\n      -- ==== OTHER STRING LITERAL TESTS ====\n      describe \"Other String Literals\" $ do\n\n        describe \"Raw strings (no interpolation)\" $ do\n          testParseOutput \"r\\\"hello {world}\\\"\" \"\\\"hello {world}\\\"\"\n          testParseOutput \"r'test {x} value'\" \"\\\"test {x} value\\\"\"\n          testParseOutput \"r\\\"\\\"\\\"multi\\nline {no} interpolation\\\"\\\"\\\"\" \"\\\"multi\\\\\\\\nline {no} interpolation\\\"\"\n          testParseOutput \"r\\\"path\\\\to\\\\file\\\"\" \"\\\"path\\\\\\\\\\\\\\\\to\\\\\\\\\\\\\\\\file\\\"\"\n          testParseOutput \"r\\\"regex: \\\\x[0-9a-f]+\\\"\" \"\\\"regex: \\\\\\\\\\\\\\\\x[0-9a-f]+\\\"\"\n          testParseOutput \"r\\\"test \\\\n \\\\t \\\\r\\\"\" \"\\\"test \\\\\\\\\\\\\\\\n \\\\\\\\\\\\\\\\t \\\\\\\\\\\\\\\\r\\\"\"\n\n        describe \"Bytes literals\" $ do\n          -- Basic bytes\n          testParseOutput \"b\\\"hello\\\"\" \" bhello\"\n          testParseOutput \"b\\\"\\\"\\\"multi\\nline\\\"\\\"\\\"\" \" bmulti\\\\nline\"\n\n          -- Bytes with hex escapes (note splitting behavior)\n          testParseOutput \"b\\\"\\\\x48ello\\\"\" \" b\\\\x48  bello\"  -- splits hex from following text\n          testParseOutput \"b\\\"\\\\x48\\\\x65llo\\\"\" \" b\\\\x48\\\\x65llo\"  -- multiple hex escapes\n\n          -- Other escapes in bytes\n          testParseOutput \"b\\\"Hello\\\\nWorld\\\"\" \" bHello\\\\nWorld\"\n\n        describe \"Raw bytes literals\" $ do\n          testParseOutput \"rb\\\"hello\\\"\" \" bhello\"\n          testParseOutput \"rb'world'\" \" bworld\"\n          testParseOutput \"rb\\\"\\\"\\\"multi\\nline\\\"\\\"\\\"\" \" bmulti\\\\nline\"\n\n        describe \"Legacy percent formatting (not interpolated)\" $ do\n          testParseOutput \"\\\"hello %s\\\" % name\" \"\\\"hello %s\\\" % name\"\n          testParseOutput \"\\\"Value: %d\\\" % count\" \"\\\"Value: %d\\\" % count\"\n\n      -- ==== ERROR HANDLING TESTS ====\n      describe \"String Parsing Errors\" $ do\n        describe \"Basic string errors\" $ do\n          testModuleParseError \"unclosed_string\" \"a = \\\"hello\"\n          testModuleParseError \"unclosed_string_triple\" \"z = 1\\na = \\\"\\\"\\\"hello\\nb = 3\\ndef foo():\\n    pass\"\n          testModuleParseError \"unclosed_raw_string\" \"a = r\\\"hello\"\n          testModuleParseError \"unclosed_bytes_string\" \"a = b\\\"hello\"\n          testModuleParseError \"unclosed_raw_bytes_string\" \"a = rb\\\"hello\"\n          testModuleParseError \"unclosed_raw_string_single\" \"a = r'hello\"\n          testModuleParseError \"unclosed_bytes_string_single\" \"a = b'hello\"\n          testModuleParseError \"unclosed_raw_bytes_string_single\" \"a = rb'hello\"\n\n        describe \"Triple quote errors (6+ quotes)\" $ do\n          testModuleParseError \"six_double_quotes\" \"a = \\\"\\\"\\\"\\\"\\\"\\\"test\\\"\\\"\\\"\\\"\\\"\\\"\"  -- 6 quotes each side\n          testModuleParseError \"six_single_quotes\" \"a = ''''''test''''''\"  -- 6 quotes each side\n          testModuleParseError \"seven_double_quotes\" \"a = \\\"\\\"\\\"\\\"\\\"\\\"\\\"test\\\"\\\"\\\"\\\"\\\"\\\"\\\"\"  -- 7 quotes each side\n          testModuleParseError \"mixed_six_quotes_double\" \"a = \\\"\\\"\\\"\\\"\\\"\\\"mixed content with {interpolation}\\\"\\\"\\\"\\\"\\\"\\\"\"\n          testModuleParseError \"raw_six_quotes\" \"a = r\\\"\\\"\\\"\\\"\\\"\\\"raw test\\\"\\\"\\\"\\\"\\\"\\\"\"\n\n        describe \"Basic interpolation errors\" $ do\n          -- F-string errors\n          testParseError \"fstring_unclosed_brace\" \"f\\\"Unclosed brace: {name\"\n          testParseError \"fstring_empty_expression\" \"f\\\"Empty expression {}\\\"\"\n          testParseError \"fstring_missing_expression\" \"f\\\"Missing expression {:10}\\\"\"\n          testParseError \"fstring_unbalanced_format\" \"f\\\"Unbalanced format {name:}:10}\\\"\"\n\n          -- String interpolation errors (without f-prefix)\n          testParseError \"string_unclosed_brace\" \"\\\"Unclosed brace: {name\"\n          testParseError \"tristring_unclosed_brace\" \"\\\"\\\"\\\"Unclosed brace: {name\"\n          testParseError \"string_empty_expression\" \"\\\"Empty expression {}\\\"\"\n          testParseError \"string_missing_expression\" \"\\\"Missing expression {:10}\\\"\"\n\n        describe \"Format specification errors\" $ do\n          testParseError \"fstring_invalid_format\" \"f\\\"Invalid format specifier {name:@Z}\\\"\"\n          testParseError \"fstring_invalid_alignment\" \"f\\\"{name:@10}\\\"\"\n          testParseError \"string_invalid_format\" \"\\\"{name:@Z}\\\"\"\n          testParseError \"fstring_empty_format_specifier\" \"f\\\"Empty format spec {x:}\\\"\"\n          testParseError \"fstring_missing_precision_digits_error\" \"f\\\"Missing precision digits {value:10.}\\\"\"\n          testParseError \"invalid_after_width\" \"\\\"value: {x:10@}\\\"\"\n          testParseError \"invalid_after_align\" \"\\\"value: {x:>10@}\\\"\"\n          testParseError \"invalid_after_precision\" \"\\\"value: {x:10.2@}\\\"\"\n          testParseError \"invalid_in_type_spec\" \"\\\"value: {x:10.2@f}\\\"\"\n\n        describe \"Nested interpolation errors\" $ do\n          testParseError \"nested_unclosed_outer\" \"\\\"outer {\\\"inner\"\n          testParseError \"nested_unclosed_inner\" \"\\\"outer {\\\"inner {x}\\\"\"\n          testParseError \"nested_empty_inner\" \"\\\"outer {\\\"inner {}\\\"}\\\"\"\n          testParseError \"nested_invalid_format\" \"\\\"outer {\\\"inner {x:@10}\\\"}\\\"\"\n          testParseError \"triple_nested_unclosed\" \"\\\"level1 {\\\"level2 {\\\"level3 {x\"\n          testParseError \"mixed_quotes_unclosed\" \"\\\"outer {'inner {x\"\n          testParseError \"escaped_brace_error\" \"\\\"outer {{broken {x}\\\"\"\n          testParseError \"nested_empty_format\" \"\\\"outer {\\\"inner {x:}\\\"}\\\"\"\n          testParseError \"nested_invalid_align\" \"\\\"outer {\\\"inner {x:@5}\\\"}\\\"\"\n          testParseError \"nested_bad_type_spec\" \"\\\"outer {\\\"inner {x:5@}\\\"}\\\"\"\n          testParseError \"deep_nesting_error\" \"\\\"a {\\\"b {\\\"c {\\\"d {\\\"e {f:@}\\\"}\\\"}\\\"}\\\"}\\\"}\\\"\"\n          testParseError \"alternating_quotes_error\" \"\\\"a {'b {\\\"c {'d {e'}\\\"}'}\\\"\"\n\n        describe \"Position-specific errors\" $ do\n          testParseError \"error_at_start\" \"{x} at start\"\n          testParseError \"error_at_end\" \"\\\"at end {x\"\n          testParseError \"error_in_middle\" \"\\\"start {x:@} end\\\"\"\n          testParseError \"multiline_unclosed\" \"\\\"\\\"\\\"Line 1\\nLine 2 {x\\nLine 3\\\"\\\"\\\"\"\n          testParseError \"multiline_nested_error\" \"\\\"\\\"\\\"First line\\n{\\\"inner\\n  {broken}\\n\\\"}\\\"\\\"\\\"\"\n          testParseError \"multiline_format_error\" \"\\\"\\\"\\\"\\nValue: {x:@invalid}\\nMore text\\\"\\\"\\\"\"\n          testParseError \"newline_in_expr\" \"\\\"value: {x\\n}\\\"\"\n          testParseError \"tab_in_format\" \"\\\"value: {x:\\t10}\\\"\"\n          testParseError \"unicode_format_error\" \"\\\"你好 {name:你}\\\"\"\n\n        describe \"Slice expression errors\" $ do\n          testParseError \"slice_unclosed_bracket\" \"\\\"slice: {arr[1:3\\\"\"\n          testParseError \"slice_invalid_step\" \"\\\"slice: {arr[:::\\\"\"\n          testParseError \"slice_missing_bracket\" \"\\\"slice: {arr 1:3]}\\\"\"\n          testParseError \"slice_nested_error\" \"\\\"outer {arr[inner[}\\\"\"\n          testParseError \"slice_format_error\" \"\\\"slice: {arr[1:3]:@10}\\\"\"\n\n      describe \"Escape Sequence Errors\" $ do\n\n        describe \"Hex escape errors\" $ do\n          testParseError \"hex_incomplete_one_digit\" \"\\\"\\\\x4\\\"\"\n          testParseError \"hex_incomplete_no_digits\" \"\\\"\\\\x\\\"\"\n          testParseError \"hex_invalid_char\" \"\\\"\\\\xAG\\\"\"\n          testParseError \"hex_incomplete_in_interpolation\" \"f\\\"value: {x} and \\\\x4\\\"\"\n\n        describe \"Unicode escape errors\" $ do\n          testParseError \"unicode_short_incomplete\" \"\\\"\\\\u123\\\"\"\n          testParseError \"unicode_short_no_digits\" \"\\\"\\\\u\\\"\"\n          testParseError \"unicode_short_invalid_char\" \"\\\"\\\\u123G\\\"\"\n          testParseError \"unicode_short_in_fstring\" \"f\\\"Hello \\\\u123\\\"\"\n          testParseError \"unicode_long_incomplete\" \"\\\"\\\\U1234567\\\"\"\n          testParseError \"unicode_long_no_digits\" \"\\\"\\\\U\\\"\"\n          testParseError \"unicode_long_invalid_char\" \"\\\"\\\\U1234567G\\\"\"\n          testParseError \"unicode_long_in_fstring\" \"f\\\"Hello \\\\U1234567\\\"\"\n\n        describe \"Octal escape errors\" $ do\n          testParseError \"octal_out_of_range\" \"\\\"\\\\777\\\"\"\n          testParseError \"octal_invalid_first_digit\" \"\\\"\\\\8\\\"\"\n          testParseError \"octal_invalid_char\" \"\\\"\\\\12G\\\"\"\n          testParseError \"octal_out_of_range_in_fstring\" \"f\\\"value: {x} \\\\777\\\"\"\n\n        describe \"Unknown escape sequences\" $ do\n          testParseError \"unknown_escape_p\" \"\\\"\\\\p\\\"\"\n          testParseError \"unknown_escape_z\" \"\\\"\\\\z\\\"\"\n          testParseError \"unknown_escape_in_fstring\" \"f\\\"unknown: \\\\q\\\"\"\n          testParseError \"unknown_escape_with_interpolation\" \"f\\\"value: {x} \\\\k\\\"\"\n\n    describe \"Documentation Generation\" $ do\n      testDocGen env0 [\"bar\", \"foo\"]\n\n    describe \"Pass 2: Kinds\" $ do\n      testKinds env0 [\"deact\"]\n\n    describe \"Pass 3: Types\" $ do\n      testTypes env0 [\"deact\"]\n      testTypes env0 [\"test_discovery\"]\n\n      testAttributesInitialization env0\n\n      it \"keeps generated names stable within unchanged defs\" $ do\n        let fooSource = unlines\n              [ \"def foo(xs: list[int], y: int):\"\n              , \"    [xs][0][0] += y\"\n              ]\n            warmSource = unlines\n              [ \"def warm(a):\"\n              , \"    return (a + 1) * 2\"\n              , \"\"\n              ]\n        namesA <- typedDefGeneratedNames env0 \"stable_names_a\" fooSource \"foo\"\n        namesB <- typedDefGeneratedNames env0 \"stable_names_b\" (warmSource ++ fooSource) \"foo\"\n        namesA `shouldSatisfy` any (\"W_foo_\" `isPrefixOf`)\n        namesA `shouldSatisfy` any (\"V_foo_\" `isPrefixOf`)\n        namesA `shouldBe` namesB\n\n      it \"accepts docstrings and extension decls at top level\" $ do\n        let src = unlines\n              [ \"\\\"\\\"\\\"Module docstring\\\"\\\"\\\"\"\n              , \"\"\n              , \"protocol Proto:\"\n              , \"    f: () -> int\"\n              , \"\"\n              , \"class Cls:\"\n              , \"    pass\"\n              , \"\"\n              , \"extension Cls(Proto):\"\n              , \"    def f(self) -> int:\"\n              , \"        return 0\"\n              ]\n        tchecked <- typecheckSource env0 \"tlname_doc_ext\" src\n        tchecked `shouldSatisfy` const True\n\n      it \"continues after a non-total top-level statement has been checked\" $ do\n        let src = unlines\n              [ \"value = 41\"\n              , \"\"\n              , \"def later() -> int:\"\n              , \"    return value + 1\"\n              ]\n        tchecked <- typecheckSource env0 \"top_non_total_then_total\" src\n        tchecked `shouldSatisfy` const True\n\n      it \"reports inferred signatures for non-total top-level statements\" $ do\n        sigsRef <- liftIO $ newIORef []\n        let src = \"value = 41\\n\"\n            moduleName = S.modName [\"top_non_total_sig\"]\n            actFile = \"<top_non_total_sig>\"\n            sysTypesPath = \"..\" </> \"..\" </> \"dist\" </> \"base\" </> \"out\" </> \"types\"\n            onInferred names sig = modifyIORef' sigsRef ((names, sig) :)\n        parsed <- liftIO $ P.parseModule moduleName actFile src Nothing\n        env <- liftIO $ Acton.Env.mkEnv [sysTypesPath] env0 parsed\n        kchecked <- liftIO $ Acton.Kinds.check env parsed\n        _ <- liftIO $ Acton.Types.reconstruct Nothing (Just onInferred) env kchecked\n        sigs <- liftIO $ reverse <$> readIORef sigsRef\n        sigs `shouldSatisfy` any (\\(names, sig) -> names == [\"value\"] && \"value : int\" `isInfixOf` sig)\n\n      it \"collects errors from independent total top-level statements\" $ do\n        let src = unlines\n              [ \"proc def first() -> int:\"\n              , \"    return \\\"one\\\"\"\n              , \"\"\n              , \"value = 1\"\n              , \"\"\n              , \"proc def second() -> int:\"\n              , \"    return \\\"two\\\"\"\n              ]\n        result <- E.try (do\n          tchecked <- typecheckSource env0 \"top_total_errors\" src\n          E.evaluate (length (show tchecked))\n          return ()) :: IO (Either Acton.Types.TypeErrors ())\n        case result of\n          Left (Acton.Types.TypeErrors errs) -> length errs `shouldBe` 2\n          Right _ -> expectationFailure \"Expected multiple type errors but type checking succeeded\"\n\n    describe \"Import Semantics\" $ do\n      it \"omits private names from the public interface\" $ do\n        (envA, parsedA) <- parseAct env0 \"import_private_a\"\n        kcheckedA <- liftIO $ Acton.Kinds.check envA parsedA\n        (nmodA, _, _, _) <- liftIO $ Acton.Types.reconstruct Nothing Nothing envA kcheckedA\n        let I.NModule impsA tenvA mdocA = nmodA\n            env1 = Acton.Env.addMod (S.modname parsedA) impsA tenvA mdocA env0\n\n        (envB, _) <- parseAct env1 \"import_private\"\n        case Acton.Env.lookupName (S.name \"__foo\") envB of\n          Nothing -> pure ()\n          Just _ -> expectationFailure \"from import * should skip __foo\"\n\n        case Acton.Env.lookupName (S.name \"public_value\") envB of\n          Just (I.HNAlias _) -> pure ()\n          _ -> expectationFailure \"from import * should include public_value\"\n\n      it \"blocks qualified access to private names\" $ do\n        (envA, parsedA) <- parseAct env0 \"import_private_a\"\n        kcheckedA <- liftIO $ Acton.Kinds.check envA parsedA\n        (nmodA, _, _, _) <- liftIO $ Acton.Types.reconstruct Nothing Nothing envA kcheckedA\n        let I.NModule impsA tenvA mdocA = nmodA\n            publicTEnvA = Acton.Env.publicTEnv tenvA\n            env1 = Acton.Env.addMod (S.modname parsedA) impsA publicTEnvA mdocA env0\n\n        (envB, parsedB) <- parseAct env1 \"import_private_qualified\"\n        kcheckedB <- liftIO $ Acton.Kinds.check envB parsedB\n        result <- liftIO $ (E.try (do\n          (_, tcheckedB, _, _) <- Acton.Types.reconstruct Nothing Nothing envB kcheckedB\n          _ <- E.evaluate (rnf tcheckedB)\n          pure ()\n          ) :: IO (Either CompilationError ()))\n\n        case result of\n          Left NoItem{} -> pure ()\n          Left err -> expectationFailure $ \"Expected NoItem error, got \" ++ show err\n          Right _ -> expectationFailure \"Expected type check failure for private name access\"\n\n    describe \"Pass 4: Normalizer\" $ do\n      testNorm env0 [\"deact\"]\n\n    describe \"Pass 5: Deactorizer\" $ do\n      testDeact env0 [\"deact\", \"deact_from_import\"]\n\n    describe \"Pass 6: CPS\" $ do\n      testCps env0 [\"cps_andor\"]\n      testCps env0 [\"cps_volatiles\"]\n      testCps env0 [\"cps_optchain\"]\n\n    describe \"Pass 7: Lambda Lifting\" $ do\n      testLL env0 [\"deact\"]\n\n    describe \"Pass 8: Boxing\" $ do\n      testBoxing env0 [\"deact\"]\n\n    describe \"Pass 9: CodeGen\" $ do\n      testCodeGen env0 [\"ints\"]\n      testCodeGen env0 [\"deact\"]\n      testCodeGen env0 [\"lines\"]\n\n    -- BuildSpec: parsing and update-in-place of Build.act (canonical layout)\n    describe \"BuildSpec\" $ do\n      it \"parses canonical Build.act and dumps JSON\" $ do\n        let buildAct = unlines\n              [ \"# Canonical Build.act file\"\n              , \"name = \\\"demo\\\"\"\n              , \"description = \\\"Demo project\\\"\"\n              , \"fingerprint = 0x1234abcd5678ef00\"\n              , \"\"\n              , \"# Dependencies section\"\n              , \"dependencies = {\"\n              , \"  \\\"a\\\": (path=\\\"deps/a\\\")\"\n              , \"}\"\n              , \"\"\n              , \"# Zig dependencies section\"\n              , \"zig_dependencies = {\"\n              , \"  \\\"z\\\": (\"\n              , \"        url=\\\"https://z\\\",\"\n              , \"        hash=\\\"abcd\\\",\"\n              , \"        artifacts=[\\\"z\\\"]\"\n              , \"    )\"\n              , \"}\"\n              , \"\"\n              , \"# bla bla bla\"\n              , \"actor main(env: Env):\"\n              , \"    pass\"\n              , \"\"\n              ]\n        case BuildSpec.parseBuildAct buildAct of\n          Left err -> expectationFailure err\n          Right (spec,_,_) -> do\n            BuildSpec.fingerprint spec `shouldBe` \"0x1234abcd5678ef00\"\n            let json = BuildSpec.encodeBuildSpecJSON spec\n            case Ae.eitherDecode' json of\n              Left err2 -> expectationFailure err2\n              Right spec2 -> spec2 `shouldBe` spec\n\n      it \"errors when fingerprint prefix does not match name\" $ do\n        withSystemTempDirectory \"acton-fp\" $ \\dir -> do\n          let buildAct = unlines\n                [ \"name = \\\"demo\\\"\"\n                , \"fingerprint = 0x0000000000000000\"\n                , \"\"\n                ]\n          writeFile (dir </> \"Build.act\") buildAct\n          res <- (E.try (Compile.loadBuildSpec dir) :: IO (Either Compile.ProjectError BuildSpec.BuildSpec))\n          case res of\n            Left (Compile.ProjectError msg) ->\n              msg `shouldSatisfy` (isInfixOf \"Fingerprint mismatch\")\n            Right _ ->\n              expectationFailure \"Expected fingerprint mismatch error\"\n\n      it \"accepts matching fingerprint for name\" $ do\n        withSystemTempDirectory \"acton-fp\" $ \\dir -> do\n          let prefix = Fingerprint.fingerprintPrefixForName \"demo\"\n              fp = Fingerprint.formatFingerprint ((fromIntegral prefix `shiftL` 32) .|. 0x1)\n              buildAct = unlines\n                [ \"name = \\\"demo\\\"\"\n                , \"fingerprint = \" ++ fp\n                , \"\"\n                ]\n          writeFile (dir </> \"Build.act\") buildAct\n          res <- (E.try (Compile.loadBuildSpec dir) :: IO (Either Compile.ProjectError BuildSpec.BuildSpec))\n          case res of\n            Left (Compile.ProjectError msg) ->\n              expectationFailure (\"Unexpected fingerprint error: \" ++ msg)\n            Right spec ->\n              BuildSpec.fingerprint spec `shouldBe` fp\n\n      it \"errors when fingerprint is malformed\" $ do\n        withSystemTempDirectory \"acton-fp\" $ \\dir -> do\n          let buildAct = unlines\n                [ \"name = \\\"demo\\\"\"\n                , \"fingerprint = \\\"not-a-number\\\"\"\n                , \"\"\n                ]\n          writeFile (dir </> \"Build.act\") buildAct\n          res <- (E.try (Compile.loadBuildSpec dir) :: IO (Either Compile.ProjectError BuildSpec.BuildSpec))\n          case res of\n            Left (Compile.ProjectError msg) ->\n              msg `shouldSatisfy` (isInfixOf \"Invalid fingerprint\")\n            Right _ ->\n              expectationFailure \"Expected invalid fingerprint error\"\n\n      it \"errors when fingerprint is quoted hex\" $ do\n        withSystemTempDirectory \"acton-fp\" $ \\dir -> do\n          let buildAct = unlines\n                [ \"name = \\\"demo\\\"\"\n                , \"fingerprint = \\\"0x1234abcd5678ef00\\\"\"\n                , \"\"\n                ]\n          writeFile (dir </> \"Build.act\") buildAct\n          res <- (E.try (Compile.loadBuildSpec dir) :: IO (Either Compile.ProjectError BuildSpec.BuildSpec))\n          case res of\n            Left (Compile.ProjectError msg) ->\n              msg `shouldSatisfy` (isInfixOf \"Invalid fingerprint\")\n            Right _ ->\n              expectationFailure \"Expected invalid fingerprint error\"\n\n      it \"errors when fingerprint is decimal\" $ do\n        withSystemTempDirectory \"acton-fp\" $ \\dir -> do\n          let buildAct = unlines\n                [ \"name = \\\"demo\\\"\"\n                , \"fingerprint = 1234\"\n                , \"\"\n                ]\n          writeFile (dir </> \"Build.act\") buildAct\n          res <- (E.try (Compile.loadBuildSpec dir) :: IO (Either Compile.ProjectError BuildSpec.BuildSpec))\n          case res of\n            Left (Compile.ProjectError msg) ->\n              msg `shouldSatisfy` (isInfixOf \"Invalid fingerprint\")\n            Right _ ->\n              expectationFailure \"Expected invalid fingerprint error\"\n\n      it \"errors when name is missing\" $ do\n        withSystemTempDirectory \"acton-fp\" $ \\dir -> do\n          let buildAct = unlines\n                [ \"fingerprint = 0x1234abcd5678ef00\"\n                , \"\"\n                ]\n          writeFile (dir </> \"Build.act\") buildAct\n          res <- (E.try (Compile.loadBuildSpec dir) :: IO (Either Compile.ProjectError BuildSpec.BuildSpec))\n          case res of\n            Left (Compile.ProjectError msg) ->\n              msg `shouldSatisfy` (isInfixOf \"Missing project name\")\n            Right _ ->\n              expectationFailure \"Expected missing project name error\"\n\n      it \"errors when fingerprint is missing\" $ do\n        withSystemTempDirectory \"acton-fp\" $ \\dir -> do\n          let buildAct = unlines\n                [ \"name = \\\"demo\\\"\"\n                , \"\"\n                ]\n          writeFile (dir </> \"Build.act\") buildAct\n          res <- (E.try (Compile.loadBuildSpec dir) :: IO (Either Compile.ProjectError BuildSpec.BuildSpec))\n          case res of\n            Left (Compile.ProjectError msg) ->\n              msg `shouldSatisfy` (isInfixOf \"Missing fingerprint\")\n            Right _ ->\n              expectationFailure \"Expected missing fingerprint error\"\n\n      it \"updates Build.act in-place, preserving comments and main actor\" $ do\n        let buildAct0 = unlines\n              [ \"# Canonical Build.act file\"\n              , \"name = \\\"demo\\\"\"\n              , \"description = \\\"Demo project\\\"\"\n              , \"fingerprint = 0x1234abcd5678ef00\"\n              , \"\"\n              , \"# Dependencies section (keep my comments)\"\n              , \"dependencies = {\"\n              , \"  \\\"a\\\": (path=\\\"deps/a\\\")\"\n              , \"}\"\n              , \"\"\n              , \"# Zig dependencies section\"\n              , \"zig_dependencies = {\"\n              , \"}\"\n              , \"\"\n              , \"# bla bla bla\"\n              , \"actor main(env: Env):\"\n              , \"    pass\"\n              , \"\"\n              ]\n        let prefix = Fingerprint.fingerprintPrefixForName \"demo2\"\n            newFp = Fingerprint.formatFingerprint ((fromIntegral prefix `shiftL` 32) .|. 0x1)\n            newJson = unlines\n              [ \"{\"\n              , \"  \\\"name\\\": \\\"demo2\\\",\"\n              , \"  \\\"description\\\": \\\"Demo project v2\\\",\"\n              , \"  \\\"fingerprint\\\": \\\"\" ++ newFp ++ \"\\\",\"\n              , \"  \\\"dependencies\\\": {\"\n              , \"    \\\"a\\\": {\\\"path\\\": \\\"deps/aa\\\"},\"\n              , \"    \\\"b\\\": {\\\"url\\\": \\\"u\\\", \\\"hash\\\": \\\"h\\\"}\"\n              , \"  },\"\n              , \"  \\\"zig_dependencies\\\": {\"\n              , \"    \\\"z\\\": {\\\"url\\\": \\\"zu\\\", \\\"hash\\\": \\\"zh\\\", \\\"artifacts\\\": [\\\"z\\\"]}\"\n              , \"  }\"\n              , \"}\"\n              ]\n        case BuildSpec.updateBuildActFromJSON buildAct0 (BL.fromStrict (B8.pack newJson)) of\n          Left err -> expectationFailure err\n          Right buildAct1 -> do\n            let expected = unlines\n                  [ \"# Canonical Build.act file\"\n                  , \"name = \\\"demo2\\\"\"\n                  , \"description = \\\"Demo project v2\\\"\"\n                  , \"fingerprint = \" ++ newFp\n                  , \"\"\n                  , \"# Dependencies section (keep my comments)\"\n                  , \"dependencies = {\"\n                  , \"    \\\"a\\\": (\"\n                  , \"        path=\\\"deps/aa\\\"\"\n                  , \"    ),\"\n                  , \"    \\\"b\\\": (\"\n                  , \"        url=\\\"u\\\",\"\n                  , \"        hash=\\\"h\\\"\"\n                  , \"    )\"\n                  , \"}\"\n                  , \"\"\n                  , \"# Zig dependencies section\"\n                  , \"zig_dependencies = {\"\n                  , \"    \\\"z\\\": (\"\n                  , \"        url=\\\"zu\\\",\"\n                  , \"        hash=\\\"zh\\\",\"\n                  , \"        artifacts=[\\\"z\\\"]\"\n                  , \"    )\"\n                  , \"}\"\n                  , \"\"\n                  , \"# bla bla bla\"\n                  , \"actor main(env: Env):\"\n                  , \"    pass\"\n                  , \"\"\n                  ]\n            buildAct1 `shouldBe` expected\n\n      it \"keeps hex fingerprints zero-padded when rewriting Build.act\" $ do\n        let buildAct0 = unlines\n              [ \"name = \\\"demo\\\"\"\n              , \"fingerprint = 0x056275683c869ace\"\n              , \"\"\n              , \"dependencies = {}\"\n              , \"\"\n              , \"zig_dependencies = {}\"\n              , \"\"\n              ]\n        case BuildSpec.parseBuildAct buildAct0 of\n          Left err -> expectationFailure err\n          Right (spec, _, _) ->\n            case BuildSpec.updateBuildActFromJSON buildAct0 (BuildSpec.encodeBuildSpecJSON spec) of\n              Left err -> expectationFailure err\n              Right buildAct1 -> do\n                buildAct1 `shouldSatisfy` (isInfixOf \"fingerprint = 0x056275683c869ace\")\n                buildAct1 `shouldSatisfy` (not . isInfixOf \"fingerprint = 0x56275683c869ace\")\n\n      it \"rejects non-hex fingerprints in Build.act updates\" $ do\n        let buildAct0 = unlines\n              [ \"name = \\\"demo\\\"\"\n              , \"fingerprint = 0x1234abcd5678ef00\"\n              , \"\"\n              , \"dependencies = {}\"\n              , \"\"\n              , \"zig_dependencies = {}\"\n              , \"\"\n              ]\n            newJson = \"{\\\"fingerprint\\\": \\\"1234\\\"}\"\n        case BuildSpec.updateBuildActFromJSON buildAct0 (BL.fromStrict (B8.pack newJson)) of\n          Left err ->\n            err `shouldSatisfy` (isInfixOf \"64-bit hex literal\")\n          Right _ ->\n            expectationFailure \"Expected Build.act update to reject decimal fingerprint\"\n\n      it \"parses Build.act with only dependencies (zig deps missing)\" $ do\n        let buildAct = unlines\n              [ \"# Only dependencies\"\n              , \"name = \\\"demo\\\"\"\n              , \"fingerprint = 0x1234abcd5678ef00\"\n              , \"dependencies = {\"\n              , \"    \\\"a\\\": (path=\\\"deps/a\\\")\"\n              , \"}\"\n              , \"\"\n              , \"actor main(env: Env):\"\n              , \"    pass\"\n              , \"\"\n              ]\n        case BuildSpec.parseBuildAct buildAct of\n          Left err -> expectationFailure err\n          Right (spec,_,_) -> do\n            -- deps present, zig deps empty\n            BuildSpec.dependencies spec `shouldSatisfy` (not . null)\n            BuildSpec.zig_dependencies spec `shouldSatisfy` null\n\n      it \"parses Build.act with only zig_dependencies (deps missing)\" $ do\n        let buildAct = unlines\n              [ \"# Only zig deps\"\n              , \"name = \\\"demo\\\"\"\n              , \"fingerprint = 0x1234abcd5678ef00\"\n              , \"zig_dependencies = {\"\n              , \"    \\\"z\\\": (\"\n              , \"        url=\\\"zu\\\",\"\n              , \"        hash=\\\"zh\\\",\"\n              , \"        artifacts=[\\\"z\\\"]\"\n              , \"    )\"\n              , \"}\"\n              , \"\"\n              , \"actor main(env: Env):\"\n              , \"    pass\"\n              , \"\"\n              ]\n        case BuildSpec.parseBuildAct buildAct of\n          Left err -> expectationFailure err\n          Right (spec,_,_) -> do\n            -- zig present, deps empty\n            BuildSpec.zig_dependencies spec `shouldSatisfy` (not . null)\n            BuildSpec.dependencies spec `shouldSatisfy` null\n\n      it \"parses Build.act with no dependency blocks\" $ do\n        let buildAct = unlines\n              [ \"# No deps here\"\n              , \"name = \\\"demo\\\"\"\n              , \"fingerprint = 0x1234abcd5678ef00\"\n              , \"\"\n              , \"actor main(env: Env):\"\n              , \"    pass\"\n              , \"\"\n              ]\n        case BuildSpec.parseBuildAct buildAct of\n          Left err -> expectationFailure err\n          Right (spec,_,_) -> do\n            BuildSpec.dependencies spec `shouldSatisfy` null\n            BuildSpec.zig_dependencies spec `shouldSatisfy` null\n\n      it \"appends missing zig_dependencies block when absent\" $ do\n        let buildAct0 = unlines\n              [ \"# Build with only dependencies\"\n              , \"name = \\\"demo\\\"\"\n              , \"fingerprint = 0x1234abcd5678ef00\"\n              , \"dependencies = {\"\n              , \"    \\\"a\\\": (path=\\\"deps/a\\\")\"\n              , \"}\"\n              , \"\"\n              , \"actor main(env: Env):\"\n              , \"    pass\"\n              , \"\"\n              ]\n        let newJson = \"{\\n  \\\"zig_dependencies\\\": {\\n    \\\"z\\\": {\\\"url\\\": \\\"zu\\\", \\\"hash\\\": \\\"zh\\\", \\\"artifacts\\\": [\\\"z\\\"]}\\n  }\\n}\\n\"\n        case BuildSpec.updateBuildActFromJSON buildAct0 (BL.fromStrict (B8.pack newJson)) of\n          Left err -> expectationFailure err\n          Right buildAct1 -> do\n            -- Original dependencies remain\n            buildAct1 `shouldSatisfy` (isInfixOf $ unlines\n              [ \"    \\\"a\\\": (\"\n              , \"        path=\\\"deps/a\\\"\"\n              , \"    )\"\n              ])\n            -- Missing zig_dependencies appended with expected formatting\n            buildAct1 `shouldSatisfy` (isInfixOf $ unlines\n              [ \"zig_dependencies = {\"\n              , \"  \\\"z\\\": (\"\n              , \"        url=\\\"zu\\\",\"\n              , \"        hash=\\\"zh\\\",\"\n              , \"        artifacts=[\\\"z\\\"]\"\n              , \"    )\"\n              , \"}\"\n              ])\n\n      it \"appends missing dependencies block when absent\" $ do\n        let buildAct0 = unlines\n              [ \"# Build with only zig deps\"\n              , \"name = \\\"demo\\\"\"\n              , \"fingerprint = 0x1234abcd5678ef00\"\n              , \"zig_dependencies = {\"\n              , \"    \\\"z\\\": (url=\\\"zu\\\", hash=\\\"zh\\\", artifacts=[\\\"z\\\"])\"\n              , \"}\"\n              , \"\"\n              , \"actor main(env: Env):\"\n              , \"    pass\"\n              , \"\"\n              ]\n        let newJson = \"{\\n  \\\"dependencies\\\": {\\n    \\\"a\\\": {\\\"path\\\": \\\"deps/a\\\"}\\n  }\\n}\\n\"\n        case BuildSpec.updateBuildActFromJSON buildAct0 (BL.fromStrict (B8.pack newJson)) of\n          Left err -> expectationFailure err\n          Right buildAct1 -> do\n            -- Original zig deps remain\n            buildAct1 `shouldSatisfy` (isInfixOf $ unlines\n              [ \"    \\\"z\\\": (\"\n              , \"        url=\\\"zu\\\",\"\n              , \"        hash=\\\"zh\\\",\"\n              , \"        artifacts=[\\\"z\\\"]\"\n              , \"    )\"\n              ])\n            -- Missing dependencies appended with expected formatting\n            buildAct1 `shouldSatisfy` (isInfixOf $ unlines\n              [ \"dependencies = {\"\n              , \"  \\\"a\\\": (\"\n              , \"        path=\\\"deps/a\\\"\"\n              , \"    )\"\n              , \"}\"\n              ])\n\n      it \"updates dependencies block with non-canonical whitespace, preserving outer line\" $ do\n        let buildAct0 = unlines\n              [ \"# Whitespace variant Build.act\"\n              , \"name = \\\"demo\\\"\"\n              , \"fingerprint = 0x1234abcd5678ef00\"\n              , \"dependencies  =   {\"\n              , \"\"\n              , \"  \\\"a\\\"  :  ( path = \\\"deps/a\\\" )\"\n              , \"}\"\n              , \"\"\n              , \"actor main(env: Env):\"\n              , \"    pass\"\n              , \"\"\n              ]\n        let newJson = \"{\\n  \\\"dependencies\\\": {\\n    \\\"a\\\": {\\\"path\\\": \\\"deps/aa\\\"}\\n  }\\n}\\n\"\n        case BuildSpec.updateBuildActFromJSON buildAct0 (BL.fromStrict (B8.pack newJson)) of\n          Left err -> expectationFailure err\n          Right buildAct1 -> do\n            -- Outer label line (with extra spaces) is preserved\n            buildAct1 `shouldSatisfy` (isInfixOf \"dependencies  =   {\")\n            -- Inner body is canonicalised and updated\n            buildAct1 `shouldSatisfy` (isInfixOf $ unlines\n              [ \"    \\\"a\\\": (\"\n              , \"        path=\\\"deps/aa\\\"\"\n              , \"    )\"\n              ])\n\n      it \"updates only the overlaid dependency entry, preserving others\" $ do\n        let buildAct0 = unlines\n              [ \"# Multiple dependencies\"\n              , \"name = \\\"demo\\\"\"\n              , \"fingerprint = 0x1234abcd5678ef00\"\n              , \"dependencies = {\"\n              , \"    \\\"a\\\": (path=\\\"deps/a\\\"),\"\n              , \"    \\\"b\\\": (path=\\\"deps/b\\\")\"\n              , \"}\"\n              , \"\"\n              , \"actor main(env: Env):\"\n              , \"    pass\"\n              , \"\"\n              ]\n        let newJson = \"{\\n  \\\"dependencies\\\": {\\n    \\\"b\\\": {\\\"path\\\": \\\"deps/bb\\\"}\\n  }\\n}\\n\"\n        case BuildSpec.updateBuildActFromJSON buildAct0 (BL.fromStrict (B8.pack newJson)) of\n          Left err -> expectationFailure err\n          Right buildAct1 -> do\n            -- JSON dependencies is treated as full set: only \"b\" remains, with updated path.\n            buildAct1 `shouldSatisfy` (not . isInfixOf \"    \\\"a\\\": (path=\\\"deps/a\\\"),\")\n            buildAct1 `shouldSatisfy` (isInfixOf $ unlines\n              [ \"    \\\"b\\\": (\"\n              , \"        path=\\\"deps/bb\\\"\"\n              , \"    )\"\n              ])\n\n      it \"removes all dependencies and zig deps when new spec objects are empty\" $ do\n        let buildAct0 = unlines\n              [ \"# Canonical Build.act file\"\n              , \"name = \\\"demo\\\"\"\n              , \"fingerprint = 0x1234abcd5678ef00\"\n              , \"\"\n              , \"# Dependencies section (keep my comments)\"\n              , \"dependencies = {\"\n              , \"    \\\"a\\\": (path=\\\"deps/a\\\")\"\n              , \"}\"\n              , \"\"\n              , \"# Zig dependencies section\"\n              , \"zig_dependencies = {\"\n              , \"    \\\"z\\\": (\"\n              , \"        url=\\\"zu\\\",\"\n              , \"        hash=\\\"zh\\\",\"\n              , \"        artifacts=[\\\"z\\\"]\"\n              , \"    )\"\n              , \"}\"\n              , \"\"\n              , \"# bla bla bla\"\n              , \"actor main(env: Env):\"\n              , \"    pass\"\n              , \"\"\n              ]\n        let newJson = \"{\\n  \\\"dependencies\\\": {},\\n  \\\"zig_dependencies\\\": {}\\n}\\n\"\n        case BuildSpec.updateBuildActFromJSON buildAct0 (BL.fromStrict (B8.pack newJson)) of\n          Left err -> expectationFailure err\n          Right buildAct1 -> do\n            let expected = unlines\n                  [ \"# Canonical Build.act file\"\n                  , \"name = \\\"demo\\\"\"\n                  , \"fingerprint = 0x1234abcd5678ef00\"\n                  , \"\"\n                  , \"# Dependencies section (keep my comments)\"\n                  , \"dependencies = {\"\n                  , \"}\"\n                  , \"\"\n                  , \"# Zig dependencies section\"\n                  , \"zig_dependencies = {\"\n                  , \"}\"\n                  , \"\"\n                  , \"# bla bla bla\"\n                  , \"actor main(env: Env):\"\n                  , \"    pass\"\n                  , \"\"\n                  ]\n            buildAct1 `shouldBe` expected\n\n\n-- Helper function to format custom parse errors consistently\nformatCustomParseError :: String -> String -> SrcLoc -> P.CustomParseError -> String\nformatCustomParseError filename input loc err =\n  let diagnostic = Diag.customParseErrorDiagnostic \"Syntax error\" filename input loc err\n      doc = prettyDiagnostic WithUnicode (TabSize 4) diagnostic\n      layout = layoutPretty defaultLayoutOptions (unAnnotate doc)\n  in T.unpack $ renderStrict layout\n\nwithTrailingNewline :: String -> String\nwithTrailingNewline s\n  | null s = s\n  | last s == '\\n' = s\n  | otherwise = s ++ \"\\n\"\n\nparseActon :: String -> Either String String\nparseActon input =\n  System.IO.Unsafe.unsafePerformIO $\n    E.catch\n      (E.evaluate $ case runParser (St.evalStateT P.stmt P.initState) \"\" inputWithNewline of\n        Left err -> Left $ renderDiagnostic err\n        Right result -> Right $ concatMap (Pretty.print) result)\n      handleCustomParseException\n  where\n    inputWithNewline = withTrailingNewline input\n    handleCustomParseException :: P.CustomParseException -> IO (Either String String)\n    renderDiagnostic err =\n      let diagnostic = Diag.parseDiagnosticFromBundle \"test\" inputWithNewline err\n          doc = prettyDiagnostic WithUnicode (TabSize 4) diagnostic\n          layout = layoutPretty defaultLayoutOptions (unAnnotate doc)\n      in T.unpack $ renderStrict layout\n    handleCustomParseException (P.CustomParseException loc err) =\n      return $ Left $ formatCustomParseError \"test\" inputWithNewline loc err\n\n-- Helper function to parse a full module (for testing module-level constructs)\nparseModuleTest :: String -> Either String String\nparseModuleTest input =\n  System.IO.Unsafe.unsafePerformIO $\n    E.catch\n      (E.evaluate $ case runParser (St.evalStateT P.file_input P.initState) \"test.act\" inputWithNewline of\n        Left err -> Left $ renderDiagnostic err\n        Right (_imports, _mdoc, _suite) -> Right $ \"Module parsed successfully\")\n      handleCustomParseException\n  where\n    inputWithNewline = withTrailingNewline input\n    renderDiagnostic err =\n      let diagnostic = Diag.parseDiagnosticFromBundle \"test.act\" inputWithNewline err\n          doc = prettyDiagnostic WithUnicode (TabSize 4) diagnostic\n          layout = layoutPretty defaultLayoutOptions (unAnnotate doc)\n      in T.unpack $ renderStrict layout\n    handleCustomParseException :: P.CustomParseException -> IO (Either String String)\n    handleCustomParseException (P.CustomParseException loc err) =\n      return $ Left $ formatCustomParseError \"test.act\" inputWithNewline loc err\n\nexpectChunkedParseMatchesSerial :: String -> Expectation\nexpectChunkedParseMatchesSerial input = do\n  let actFile = \"chunked.act\"\n  expectChunkedParseMatchesSerialFile actFile input\n\nexpectChunkedParseMatchesSerialFile :: FilePath -> String -> Expectation\nexpectChunkedParseMatchesSerialFile actFile input = do\n  let moduleName = S.modName [\"chunked\"]\n  serial <- P.parseModuleSerial moduleName actFile input Nothing\n  chunked <- P.parseModule moduleName actFile input Nothing\n  when (chunked /= serial) $\n    expectationFailure (\"Chunked parser AST differs from serial parser for \" ++ actFile)\n\nparseBundleErrorLine :: ParseErrorBundle String P.CustomParseError -> Int\nparseBundleErrorLine bundle =\n  let firstError = NE.head (bundleErrors bundle)\n      (_, posState) = reachOffset (errorOffset firstError) (bundlePosState bundle)\n  in unPos (sourceLine (pstateSourcePos posState))\n\nrenderDiagnosticText diagnostic =\n  let doc = prettyDiagnostic WithUnicode (TabSize 4) diagnostic\n      layout = layoutPretty defaultLayoutOptions (unAnnotate doc)\n  in T.unpack $ renderStrict layout\n\nactFilesUnder :: FilePath -> IO [FilePath]\nactFilesUnder root = do\n  entries <- sort <$> listDirectory root\n  fmap concat $ mapM (\\entry -> do\n    let path = root </> entry\n    isDir <- doesDirectoryExist path\n    if isDir\n      then actFilesUnder path\n      else return [path | takeExtension path == \".act\"]\n    ) entries\n\nexpectModuleParseSuccess :: String -> IO ()\nexpectModuleParseSuccess input =\n  case parseModuleTest input of\n    Left err -> expectationFailure $ \"Parse failed: \" ++ err\n    Right _ -> return ()\n\nexpectModuleParseFailure :: String -> IO String\nexpectModuleParseFailure input =\n  case parseModuleTest input of\n    Left err -> return err\n    Right result -> expectationFailure $ \"Expected parse failure, got: \" ++ result\n\ncompletionFixtureEnv :: Acton.Env.Env0 -> Acton.Env.Env0\ncompletionFixtureEnv env0 =\n  let y1Mod = S.modName [\"mini\", \"layers\", \"y_1\"]\n      baseMod = S.modName [\"mini\", \"layers\", \"base_1\"]\n      inputName = S.name \"stratoweave_rfs__rfs__l3vpn_endpoint_entry\"\n      inputType = S.tCon (S.TC (S.GName y1Mod inputName) [])\n      localInputName = S.name \"LocalInput\"\n      localInputType = S.tCon (S.TC (S.NoQ localInputName) [])\n      transformType =\n        S.tFun S.fxMut\n          (S.posRow inputType (S.posRow S.tWild S.posNil))\n          S.kwdNil\n          S.tWild\n      transformInfo = I.NSig (S.tSchema [] transformType) S.NoDec Nothing\n      localTransformType =\n        S.tFun S.fxMut\n          (S.posRow localInputType S.posNil)\n          S.kwdNil\n          S.tWild\n      localTransformInfo = I.NSig (S.tSchema [] localTransformType) S.NoDec Nothing\n      outputRootName = S.name \"OutputRoot\"\n      outputRootType = S.tCon (S.TC (S.GName baseMod outputRootName) [])\n      netinfraName = S.name \"Netinfra\"\n      netinfraType = S.tCon (S.TC (S.GName baseMod netinfraName) [])\n      routerCollectionName = S.name \"RouterCollection\"\n      routerCollectionType = S.tCon (S.TC (S.GName baseMod routerCollectionName) [])\n      routerEntryName = S.name \"RouterEntry\"\n      routerEntryType = S.tCon (S.TC (S.GName baseMod routerEntryName) [])\n      baseConfigName = S.name \"BaseConfig\"\n      baseConfigType = S.tCon (S.TC (S.GName baseMod baseConfigName) [])\n      oRootType = S.tFun S.fxPure S.posNil S.kwdNil outputRootType\n      oRootInfo = I.NDef (S.tSchema [] oRootType) S.NoDec Nothing\n      createType =\n        S.tFun S.fxMut\n          (S.posRow Builtin.tStr S.posNil)\n          (S.kwdRow (S.name \"id\") Builtin.tInt\n            (S.kwdRow (S.name \"role\") Builtin.tStr\n              (S.kwdRow (S.name \"mock\") Builtin.tBool S.kwdNil)))\n          routerEntryType\n      createInfo = I.NDef (S.tSchema [] createType) S.NoDec (Just \"Create a router entry.\")\n      baseClass = I.NClass [] [] [(S.name \"transform\", transformInfo)] (Just \"Base transform class.\")\n      localBaseClass = I.NClass [] [] [(S.name \"transform\", localTransformInfo)] Nothing\n      outputRootClass = I.NClass [] []\n        [ fieldOf \"netinfra\" netinfraType\n        , field \"l3vpns\"\n        ] Nothing\n      netinfraClass = I.NClass [] []\n        [ fieldOf \"router\" routerCollectionType\n        ] Nothing\n      routerCollectionClass = I.NClass [] []\n        [ (S.name \"create\", createInfo)\n        ] Nothing\n      routerEntryClass = I.NClass [] []\n        [ field \"router_id\"\n        , field \"hostname\"\n        , fieldOf \"base_config\" baseConfigType\n        ] Nothing\n      baseConfigClass = I.NClass [] []\n        [ docFieldOf \"asn\" Builtin.tInt \"Autonomous system number.\"\n        , fieldOf \"ipv4_address\" Builtin.tStr\n        ] (Just \"Base router configuration.\")\n      localInputClass = I.NClass [] []\n        [ field \"local_field\"\n        ] Nothing\n      inputClass = I.NClass [] []\n        [ field \"interface_name\"\n        , field \"vpn_name\"\n        , field \"customer_name\"\n        , field \"ipv4_address\"\n        ] (Just \"L3VPN endpoint input.\")\n      field n = fieldOf n S.tWild\n      fieldOf n typ = (S.name n, I.NVar typ)\n      docFieldOf n typ doc = (S.name n, I.NSig (S.tSchema [] typ) S.NoDec (Just doc))\n  in Acton.Env.addMod baseMod []\n       [ (S.name \"L3vpnEndpoint\", baseClass)\n       , (S.name \"LocalEndpoint\", localBaseClass)\n       , (localInputName, localInputClass)\n       , (outputRootName, outputRootClass)\n       , (netinfraName, netinfraClass)\n       , (routerCollectionName, routerCollectionClass)\n       , (routerEntryName, routerEntryClass)\n       , (baseConfigName, baseConfigClass)\n       , (S.name \"o_root\", oRootInfo)\n       ] Nothing $\n     Acton.Env.addMod y1Mod [] [(inputName, inputClass)] Nothing env0\n\ncursorSource :: String -> (String, Int)\ncursorSource src =\n  let marker = T.pack \"<CURSOR>\"\n      (before, after) = T.breakOn marker (T.pack src)\n  in if T.null after\n       then (src, length src)\n       else (T.unpack before ++ T.unpack (T.drop (T.length marker) after), T.length before)\n\nparseStmtAst :: String -> Either String [S.Stmt]\nparseStmtAst input =\n  System.IO.Unsafe.unsafePerformIO $\n    E.catch\n      (E.evaluate $ case runParser (St.evalStateT P.stmt P.initState) \"\" inputWithNewline of\n        Left err -> Left $ renderDiagnostic err\n        Right result -> Right result)\n      handleCustomParseException\n  where\n    inputWithNewline = withTrailingNewline input\n    renderDiagnostic err =\n      let diagnostic = Diag.parseDiagnosticFromBundle \"test\" inputWithNewline err\n          doc = prettyDiagnostic WithUnicode (TabSize 4) diagnostic\n          layout = layoutPretty defaultLayoutOptions (unAnnotate doc)\n      in T.unpack $ renderStrict layout\n    handleCustomParseException :: P.CustomParseException -> IO (Either String [S.Stmt])\n    handleCustomParseException (P.CustomParseException loc err) =\n      return $ Left $ formatCustomParseError \"test\" inputWithNewline loc err\n\nparseExprAst :: String -> Either String S.Expr\nparseExprAst input =\n  System.IO.Unsafe.unsafePerformIO $\n    E.catch\n      (E.evaluate $ case runParser (St.evalStateT P.expr P.initState) \"\" inputWithNewline of\n        Left err -> Left $ renderDiagnostic err\n        Right result -> Right result)\n      handleCustomParseException\n  where\n    inputWithNewline = withTrailingNewline input\n    renderDiagnostic err =\n      let diagnostic = Diag.parseDiagnosticFromBundle \"test\" inputWithNewline err\n          doc = prettyDiagnostic WithUnicode (TabSize 4) diagnostic\n          layout = layoutPretty defaultLayoutOptions (unAnnotate doc)\n      in T.unpack $ renderStrict layout\n    handleCustomParseException :: P.CustomParseException -> IO (Either String S.Expr)\n    handleCustomParseException (P.CustomParseException loc err) =\n      return $ Left $ formatCustomParseError \"test\" inputWithNewline loc err\n\n-- Helper function to test module-level parser errors with golden files\ntestModuleParseError :: String -> String -> Spec\ntestModuleParseError testName input = do\n  it testName $ do\n    case parseModuleTest input of\n      Left err -> goldenTextFile (\"test/parser_golden/\" ++ testName ++ \".golden\") $\n        return $ T.pack $ \"ERROR: \" ++ err\n      Right result -> goldenTextFile (\"test/parser_golden/\" ++ testName ++ \".golden\") $\n        return $ T.pack $ \"PARSED: \" ++ result\n\n-- Helper function to test parsing (just that it succeeds)\ntestParse :: Acton.Env.Env0 -> [String] -> Spec\ntestParse env0 modulePaths = do\n  let dir = \"test\" </> \"1-parse\"\n\n  modules <- runIO $ do\n    let processModule (accEnv, accModules) modulePath = do\n          (env, parsed) <- parseAct accEnv modulePath\n          return (accEnv, accModules ++ [(takeFileName modulePath, parsed)])\n\n    (_, modules) <- foldM processModule (env0, []) modulePaths\n    return modules\n\n  forM_ modules $ \\(modName, parsed) ->\n    genTests \"Parse Check\" dir modName parsed parsed\n\n-- Helper function to test parsing with output validation\ntestParseOutput :: String -> String -> Spec\ntestParseOutput input expected = do\n  it (show input) $ do\n    case parseActon input of\n      Left err -> expectationFailure $ \"Parse failed: \" ++ err\n      Right output -> output `shouldBe` expected\n\n-- Helper function to test parser errors with golden files\ntestParseError :: String -> String -> Spec\ntestParseError testName input = do\n  it testName $ do\n    case parseActon input of\n      Left err -> goldenTextFile (\"test/parser_golden/\" ++ testName ++ \".golden\") $\n        return $ T.pack $ \"ERROR: \" ++ err\n      Right result -> goldenTextFile (\"test/parser_golden/\" ++ testName ++ \".golden\") $\n        return $ T.pack $ \"PARSED: \" ++ result\n\n-- Helper function for documentation golden tests\n-- Takes a list of module paths in dependency order\n-- Examples: [\"bar\", \"foo\"] or [\"utils/math\", \"utils/strings\", \"app\"]\n-- Generates golden files for all formats: .txt (ASCII), .md (Markdown), .html (HTML)\ntestDocGen :: Acton.Env.Env0 -> [String] -> Spec\ntestDocGen env0 modulePaths = do\n  oldDir <- runIO getCurrentDirectory\n  let goldenDir = oldDir </> \"test\" </> \"doc-golden\"\n\n  modules <- runIO $ do\n    let processModule (accEnv, accModules) modulePath = do\n          (env, parsed) <- parseAct accEnv modulePath\n          kchecked <- Acton.Kinds.check env parsed\n          (nmod, _, _, _) <- Acton.Types.reconstruct Nothing Nothing env kchecked\n          let I.NModule imps moduleTypeEnv moduleDoc = nmod\n          let newAccEnv = Acton.Env.addMod (S.modname parsed) imps moduleTypeEnv moduleDoc accEnv\n          return (newAccEnv, accModules ++ [((takeFileName modulePath), parsed, nmod)])\n\n    (finalEnv, modules) <- foldM processModule (env0, []) modulePaths\n    return modules\n\n  -- Generate documentation for each module\n  forM_ modules $ \\(modName, parsed, nmod) -> do\n    describe modName $ do\n      it \"generates ASCII documentation (plain)\" $ do\n        let asciiDoc = DocP.printAsciiDoc False nmod parsed\n        goldenTextFile (goldenDir </> modName ++ \".txt\") $ return $ T.pack asciiDoc\n\n      it \"generates ASCII documentation (styled)\" $ do\n        let asciiDoc = DocP.printAsciiDoc True nmod parsed\n        goldenTextFile (goldenDir </> modName ++ \"-color.txt\") $ return $ T.pack asciiDoc\n\n      it \"generates Markdown documentation\" $ do\n        let mdDoc = DocP.printMdDoc nmod parsed\n        goldenTextFile (goldenDir </> modName ++ \".md\") $ return $ T.pack mdDoc\n\n      it \"generates HTML documentation\" $ do\n        let htmlDoc = DocP.printHtmlDoc nmod parsed\n        goldenTextFile (goldenDir </> modName ++ \".html\") $ return $ T.pack htmlDoc\n\n-- Parse an Acton module by module path\n-- Examples: \"foo\" -> src/foo.act, module foo\n--           \"foo/bar\" -> src/foo/bar.act, module foo.bar\nparseAct env0 modulePath = do\n  let moduleComponents = splitDirectories modulePath\n      moduleName = S.modName moduleComponents\n      act_file = \"test\" </> \"src\" </> modulePath ++ \".act\"\n      sysTypesPath = \"..\" </> \"..\" </> \"dist\" </> \"base\" </> \"out\" </> \"types\"\n\n  src <- liftIO $ readFile act_file\n  parsed <- liftIO $ P.parseModule moduleName act_file src Nothing\n  env <- liftIO $ Acton.Env.mkEnv [sysTypesPath] env0 parsed\n  return (env, parsed)\n\ntypecheckSource env0 modName src = do\n  let moduleName = S.modName [modName]\n      actFile = \"<\" ++ modName ++ \">\"\n      sysTypesPath = \"..\" </> \"..\" </> \"dist\" </> \"base\" </> \"out\" </> \"types\"\n  parsed <- liftIO $ P.parseModule moduleName actFile src Nothing\n  env <- liftIO $ Acton.Env.mkEnv [sysTypesPath] env0 parsed\n  kchecked <- liftIO $ Acton.Kinds.check env parsed\n  (_, tchecked, _, _) <- liftIO $ Acton.Types.reconstruct Nothing Nothing env kchecked\n  return tchecked\n\ntypedDefGeneratedNames env0 modName src defName = do\n  tchecked <- typecheckSource env0 modName src\n  case findTypedDef defName tchecked of\n    Just d ->\n      pure $ generatedInternalNames (Pretty.print d)\n    Nothing ->\n      expectationFailure (\"Definition not found: \" ++ defName) >> pure []\n\nfindTypedDef defName (S.Module _ _ _ ss) = findInSuite ss\n  where findInSuite [] = Nothing\n        findInSuite (S.Decl _ ds : ss) =\n          case [ d | d@(S.Def _ n _ _ _ _ _ _ _ _) <- ds, prstr n == defName ] of\n            d : _ -> Just d\n            [] -> findInSuite ss\n        findInSuite (_ : ss) = findInSuite ss\n\ngeneratedInternalNames s = sort . nub . filter isGenerated $ words $ map keep s\n  where keep c\n          | isAlphaNum c || c == '_' = c\n          | otherwise                = ' '\n        isGenerated n                = \"W_\" `isPrefixOf` n || \"V_\" `isPrefixOf` n\n\n\ngenTests pass_name dir testname input_data output_data = do\n  let input_golden = dir </> testname ++ \".input\"\n      output_golden = dir </> testname ++ \".output\"\n\n  describe testname $ do\n    it (\"Check \" ++ pass_name ++ \" input\") $ do\n      goldenTextFile input_golden $ return $ T.pack $ Pretty.print input_data\n    it (\"Check \" ++ pass_name ++ \" output\") $ do\n      goldenTextFile output_golden $ return $ T.pack $ Pretty.print output_data\n\n-- pass 2 Kinds check\ntestKinds :: Acton.Env.Env0 -> [String] -> Spec\ntestKinds env0 modulePaths = do\n  let dir = \"test\" </> \"2-kinds\"\n\n  modules <- runIO $ do\n    let processModule (accEnv, accModules) modulePath = do\n          (env, parsed) <- parseAct accEnv modulePath\n          kchecked <- Acton.Kinds.check env parsed\n          return (accEnv, accModules ++ [(takeFileName modulePath, parsed, kchecked)])\n\n    (_, modules) <- foldM processModule (env0, []) modulePaths\n    return modules\n\n  forM_ modules $ \\(modName, parsed, kchecked) ->\n    genTests \"Kinds Check\" dir modName parsed kchecked\n\n-- pass 3 Type check\ntestTypes :: Acton.Env.Env0 -> [String] -> Spec\ntestTypes env0 modulePaths = do\n  let dir = \"test\" </> \"3-types\"\n\n  modules <- runIO $ do\n    let processModule (accEnv, accModules) modulePath = do\n          (env, parsed) <- parseAct accEnv modulePath\n          kchecked <- Acton.Kinds.check env parsed\n          (nmod, tchecked, _, _) <- Acton.Types.reconstruct Nothing Nothing env kchecked\n          let I.NModule imps tenv mdoc = nmod\n          let newAccEnv = Acton.Env.addMod (S.modname parsed) imps tenv mdoc accEnv\n          return (newAccEnv, accModules ++ [(takeFileName modulePath, kchecked, tchecked)])\n\n    (_, modules) <- foldM processModule (env0, []) modulePaths\n    return modules\n\n  forM_ modules $ \\(modName, kchecked, tchecked) ->\n    genTests \"Type Check\" dir modName kchecked tchecked\n\n-- pass 4 Normalizer\ntestNorm :: Acton.Env.Env0 -> [String] -> Spec\ntestNorm env0 modulePaths = do\n  let dir = \"test\" </> \"4-normalizer\"\n\n  modules <- runIO $ do\n    let processModule (accEnv, accModules) modulePath = do\n          (env, parsed) <- parseAct accEnv modulePath\n          kchecked <- Acton.Kinds.check env parsed\n          (nmod, tchecked, env0Typed, _) <- Acton.Types.reconstruct Nothing Nothing env kchecked\n          let I.NModule imps tenv mdoc = nmod\n          (normalized, normEnv) <- Acton.Normalizer.normalize env0Typed tchecked\n          let newAccEnv = Acton.Env.addMod (S.modname parsed) imps tenv mdoc accEnv\n          return (newAccEnv, accModules ++ [(takeFileName modulePath, tchecked, normalized)])\n\n    (_, modules) <- foldM processModule (env0, []) modulePaths\n    return modules\n\n  forM_ modules $ \\(modName, tchecked, normalized) ->\n    genTests \"Normalizer\" dir modName tchecked normalized\n\n-- pass 5 Deactorizer\ntestDeact :: Acton.Env.Env0 -> [String] -> Spec\ntestDeact env0 modulePaths = do\n  let dir = \"test\" </> \"5-deactorizer\"\n\n  modules <- runIO $ do\n    let processModule (accEnv, accModules) modulePath = do\n          (env, parsed) <- parseAct accEnv modulePath\n          kchecked <- Acton.Kinds.check env parsed\n          (nmod, tchecked, env0Typed, _) <- Acton.Types.reconstruct Nothing Nothing env kchecked\n          let I.NModule imps tenv mdoc = nmod\n          (normalized, normEnv) <- Acton.Normalizer.normalize env0Typed tchecked\n          (deacted, deactEnv) <- Acton.Deactorizer.deactorize normEnv normalized\n          let newAccEnv = Acton.Env.addMod (S.modname parsed) imps tenv mdoc accEnv\n          return (newAccEnv, accModules ++ [(takeFileName modulePath, normalized, deacted)])\n\n    (_, modules) <- foldM processModule (env0, []) modulePaths\n    return modules\n\n  forM_ modules $ \\(modName, normalized, deacted) ->\n    genTests \"Deactorizer\" dir modName normalized deacted\n\n-- pass 6 CPS\ntestCps :: Acton.Env.Env0 -> [String] -> Spec\ntestCps env0 modulePaths = do\n  let dir = \"test\" </> \"6-cps\"\n\n  modules <- runIO $ do\n    let processModule (accEnv, accModules) modulePath = do\n          (env, parsed) <- parseAct accEnv modulePath\n          kchecked <- Acton.Kinds.check env parsed\n          (nmod, tchecked, env0Typed, _) <- Acton.Types.reconstruct Nothing Nothing env kchecked\n          let I.NModule imps tenv mdoc = nmod\n          (normalized, normEnv) <- Acton.Normalizer.normalize env0Typed tchecked\n          (deacted, deactEnv) <- Acton.Deactorizer.deactorize normEnv normalized\n          (cpstyled, _) <- Acton.CPS.convert deactEnv deacted\n          let newAccEnv = Acton.Env.addMod (S.modname parsed) imps tenv mdoc accEnv\n          return (newAccEnv, accModules ++ [(takeFileName modulePath, deacted, cpstyled)])\n\n    (_, modules) <- foldM processModule (env0, []) modulePaths\n    return modules\n\n  forM_ modules $ \\(modName, deacted, cpstyled) ->\n    genTests \"CPS\" dir modName deacted cpstyled\n\n-- pass 7 Lambda Lifting\ntestLL :: Acton.Env.Env0 -> [String] -> Spec\ntestLL env0 modulePaths = do\n  let dir = \"test\" </> \"7-lambdalifting\"\n\n  modules <- runIO $ do\n    let processModule (accEnv, accModules) modulePath = do\n          (env, parsed) <- parseAct accEnv modulePath\n          kchecked <- Acton.Kinds.check env parsed\n          (nmod, tchecked, env0Typed, _) <- Acton.Types.reconstruct Nothing Nothing env kchecked\n          let I.NModule imps tenv mdoc = nmod\n          (normalized, normEnv) <- Acton.Normalizer.normalize env0Typed tchecked\n          (deacted, deactEnv) <- Acton.Deactorizer.deactorize normEnv normalized\n          (cpstyled, cpsEnv) <- Acton.CPS.convert deactEnv deacted\n          (lifted,liftEnv) <- Acton.LambdaLifter.liftModule cpsEnv cpstyled\n          let newAccEnv = Acton.Env.addMod (S.modname parsed) imps tenv mdoc accEnv\n          return (newAccEnv, accModules ++ [(takeFileName modulePath, cpstyled, lifted)])\n\n    (_, modules) <- foldM processModule (env0, []) modulePaths\n    return modules\n\n  forM_ modules $ \\(modName, cpstyled, lifted) ->\n    genTests \"Lambda Lifting\" dir modName cpstyled lifted\n\n-- pass 8 Boxing\ntestBoxing :: Acton.Env.Env0 -> [String] -> Spec\ntestBoxing env0 modulePaths = do\n  let dir = \"test\" </> \"8-boxing\"\n\n  modules <- runIO $ do\n    let processModule (accEnv, accModules) modulePath = do\n          (env, parsed) <- parseAct accEnv modulePath\n          kchecked <- Acton.Kinds.check env parsed\n          (nmod, tchecked, env0Typed, _) <- Acton.Types.reconstruct Nothing Nothing env kchecked\n          let I.NModule imps tenv mdoc = nmod\n          (normalized, normEnv) <- Acton.Normalizer.normalize env0Typed tchecked\n          (deacted, deactEnv) <- Acton.Deactorizer.deactorize normEnv normalized\n          (cpstyled, cpsEnv) <- Acton.CPS.convert deactEnv deacted\n          (lifted,liftEnv) <- Acton.LambdaLifter.liftModule cpsEnv cpstyled\n          boxed <- Acton.Boxing.doBoxing liftEnv lifted\n          let newAccEnv = Acton.Env.addMod (S.modname parsed) imps tenv mdoc accEnv\n          return (newAccEnv, accModules ++ [(takeFileName modulePath, lifted, boxed)])\n\n    (_, modules) <- foldM processModule (env0, []) modulePaths\n    return modules\n\n  forM_ modules $ \\(modName, lifted, boxed) ->\n    genTests \"Boxing\" dir modName lifted boxed\n\n-- pass 9 CodeGen\ntestCodeGen :: Acton.Env.Env0 -> [String] -> Spec\ntestCodeGen env0 modulePaths = do\n  let dir = \"test\" </> \"9-codegen\"\n\n  modules <- runIO $ do\n    let processModule (accEnv, accModules) modulePath = do\n          (env, parsed) <- parseAct accEnv modulePath\n          kchecked <- Acton.Kinds.check env parsed\n          (nmod, tchecked, env0Typed, _) <- Acton.Types.reconstruct Nothing Nothing env kchecked\n          let I.NModule imps tenv mdoc = nmod\n          (normalized, normEnv) <- Acton.Normalizer.normalize env0Typed tchecked\n          (deacted, deactEnv) <- Acton.Deactorizer.deactorize normEnv normalized\n          (cpstyled, cpsEnv) <- Acton.CPS.convert deactEnv deacted\n          (lifted,liftEnv) <- Acton.LambdaLifter.liftModule cpsEnv cpstyled\n          boxed <- Acton.Boxing.doBoxing liftEnv lifted\n          let act_file = \"test\" </> \"src\" </> modulePath ++ \".act\"\n          srcText <- readFile act_file\n          let srcbase = \"test\" </> \"src\" </> modulePath\n          (n,h,c) <- Acton.CodeGen.generate liftEnv srcbase srcText True boxed \"test-hash\"\n          let newAccEnv = Acton.Env.addMod (S.modname parsed) imps tenv mdoc accEnv\n          return (newAccEnv, accModules ++ [(takeFileName modulePath, boxed, n, h, c)])\n\n    (_, modules) <- foldM processModule (env0, []) modulePaths\n    return modules\n\n  forM_ modules $ \\(modName, boxed, n, h, c) -> do\n    let pass_name = \"CodeGen\"\n    let input_golden = dir </> modName ++ \".input\"\n        h_golden = dir </> modName ++ \".h\"\n        c_golden = dir </> modName ++ \".c\"\n\n    describe modName $ do\n      it (\"Check \" ++ pass_name ++ \" input\") $ do\n        goldenTextFile input_golden $ return $ T.pack $ Pretty.print boxed\n      it (\"Check \" ++ pass_name ++ \" .h output\") $ do\n        goldenTextFile h_golden $ return $ T.pack $ Pretty.print h\n      it (\"Check \" ++ pass_name ++ \" .c output\") $ do\n        goldenTextFile c_golden $ return $ T.pack $ Pretty.print c\n\n\ntestDocstrings :: Acton.Env.Env0 -> String -> Spec\ntestDocstrings env0 testname = do\n  (env, parsed) <- parseAct env0 testname\n\n  kchecked <- liftIO $ Acton.Kinds.check env parsed\n  (nmod, _, _, _) <- liftIO $ Acton.Types.reconstruct Nothing Nothing env kchecked\n  let I.NModule _ tenv mdoc = nmod\n\n  -- Extract docstrings from the parsed AST\n  let S.Module _ _ _ stmts = parsed\n      extractDeclDocstrings (S.Decl _ decls) = concatMap extractDocFromDecl decls\n      extractDeclDocstrings _ = []\n\n      extractDocFromDecl (S.Def _ n _ _ _ _ _ _ _ ddoc) = [(S.nstr n, ddoc)]\n      extractDocFromDecl (S.Class _ n _ _ _ ddoc) = [(S.nstr n, ddoc)]\n      extractDocFromDecl (S.Actor _ n _ _ _ _ ddoc) = [(S.nstr n, ddoc)]\n      extractDocFromDecl (S.Protocol _ n _ _ _ ddoc) = [(S.nstr n, ddoc)]\n      extractDocFromDecl (S.Extension _ _ _ _ _ ddoc) = [(\"extension\", ddoc)]\n\n      docstrings = concatMap extractDeclDocstrings stmts\n\n  describe testname $ do\n    -- Basic functionality tests\n    it \"extracts module docstrings\" $ do\n      case mdoc of\n        Just doc -> do\n          doc `shouldContain` \"Test module\"\n          doc `shouldContain` \"{braces}\"\n        Nothing -> expectationFailure \"Module docstring not extracted\"\n\n    it \"extracts function docstrings\" $ do\n      case lookup \"test_function\" docstrings of\n        Just (Just doc) -> doc `shouldContain` \"Test function\"\n        Just Nothing -> expectationFailure \"Function should have docstring\"\n        Nothing -> expectationFailure \"Function not found\"\n\n    it \"handles functions without docstrings\" $ do\n      case lookup \"no_docstring_function\" docstrings of\n        Just Nothing -> return ()  -- Expected: no docstring\n        Just (Just _) -> expectationFailure \"Function should not have docstring\"\n        Nothing -> expectationFailure \"Function not found\"\n\n    it \"extracts class docstrings\" $ do\n      case lookup \"TestClass\" docstrings of\n        Just (Just doc) -> doc `shouldContain` \"Test class\"\n        Just Nothing -> expectationFailure \"Class should have docstring\"\n        Nothing -> expectationFailure \"Class not found\"\n\n    it \"extracts actor docstrings\" $ do\n      case lookup \"TestActor\" docstrings of\n        Just (Just doc) -> doc `shouldContain` \"Test actor\"\n        Just Nothing -> expectationFailure \"Actor should have docstring\"\n        Nothing -> expectationFailure \"Actor not found\"\n\n    it \"extracts protocol docstrings\" $ do\n      case lookup \"TestProtocol\" docstrings of\n        Just (Just doc) -> doc `shouldContain` \"Test protocol\"\n        Just Nothing -> expectationFailure \"Protocol should have docstring\"\n        Nothing -> expectationFailure \"Protocol not found\"\n\n    it \"extracts extension docstrings\" $ do\n      case lookup \"extension\" docstrings of\n        Just (Just doc) -> doc `shouldContain` \"Extension\"\n        Just Nothing -> expectationFailure \"Extension should have docstring\"\n        Nothing -> expectationFailure \"Extension not found\"\n\n    -- Edge case tests\n    it \"ignores non-first string statements\" $ do\n      case lookup \"function_with_non_first_string\" docstrings of\n        Just Nothing -> return ()  -- Expected: no docstring\n        Just (Just _) -> expectationFailure \"Non-first string should not be docstring\"\n        Nothing -> expectationFailure \"Function not found\"\n\n    it \"extracts only first string as docstring\" $ do\n      case lookup \"function_with_multiple_strings\" docstrings of\n        Just (Just doc) -> do\n          doc `shouldContain` \"First string is docstring\"\n          when (\"Second string\" `isInfixOf` doc) $\n            expectationFailure \"Later strings should not be in docstring\"\n        Just Nothing -> expectationFailure \"Function should have docstring\"\n        Nothing -> expectationFailure \"Function not found\"\n\n    it \"does not treat f-prefixed strings as docstrings\" $ do\n      case lookup \"function_with_f_prefix_docstring\" docstrings of\n        Just Nothing -> return ()\n        Just (Just _) -> expectationFailure \"f-prefixed string should not be docstring\"\n        Nothing -> expectationFailure \"Function not found\"\n\n    it \"handles single quote docstrings\" $ do\n      case lookup \"function_with_single_quotes\" docstrings of\n        Just (Just doc) -> doc `shouldContain` \"Single quote\"\n        Just Nothing -> expectationFailure \"Function should have docstring\"\n        Nothing -> expectationFailure \"Function not found\"\n\n    it \"handles triple single quote docstrings\" $ do\n      case lookup \"function_with_triple_single_quotes\" docstrings of\n        Just (Just doc) -> doc `shouldContain` \"Triple quote\"\n        Just Nothing -> expectationFailure \"Function should have docstring\"\n        Nothing -> expectationFailure \"Function not found\"\n\n    it \"handles mixed quotes in docstrings\" $ do\n      case lookup \"function_with_mixed_quotes\" docstrings of\n        Just (Just doc) -> doc `shouldContain` \"Mixed 'quotes'\"\n        Just Nothing -> expectationFailure \"Function should have docstring\"\n        Nothing -> expectationFailure \"Function not found\"\n\n    it \"does not interpolate docstrings\" $ do\n      case lookup \"function_with_braces_docstring\" docstrings of\n        Just (Just doc) -> doc `shouldContain` \"{braces}\"\n        Just Nothing -> expectationFailure \"Function should have docstring\"\n        Nothing -> expectationFailure \"Function not found\"\n\n    it \"handles empty docstrings\" $ do\n      case lookup \"function_empty_docstring\" docstrings of\n        Just (Just doc) -> doc `shouldBe` \"\"\n        Just Nothing -> expectationFailure \"Function should have empty docstring\"\n        Nothing -> expectationFailure \"Function not found\"\n\n    it \"ignores strings in control flow\" $ do\n      case lookup \"function_with_control_flow\" docstrings of\n        Just Nothing -> return ()  -- Expected: no docstring\n        Just (Just _) -> expectationFailure \"String in control flow should not be docstring\"\n        Nothing -> expectationFailure \"Function not found\"\n\n    it \"handles functions with just docstrings\" $ do\n      case lookup \"function_just_docstring\" docstrings of\n        Just (Just doc) -> doc `shouldContain` \"Just a docstring\"\n        Just Nothing -> expectationFailure \"Function should have docstring\"\n        Nothing -> expectationFailure \"Function not found\"\n\n-- Tests for uninitialized class attribute checking\n\ntestAttributesInitialization :: Acton.Env.Env0 -> Spec\ntestAttributesInitialization env0 = do\n  describe \"Class Attribute Initialization Check\" $ do\n    testTypeSuccess env0 \"class_init_attrs/init_basic\"\n    testTypeSuccess env0 \"class_init_attrs/init_inferred_only\"\n    testTypeError   env0 \"class_init_attrs/uninit_basic\"\n    testTypeError   env0 \"class_init_attrs/uninit_basic_inferred\"\n\n    testTypeSuccess env0 \"class_init_attrs/init_multiple\"\n    testTypeError   env0 \"class_init_attrs/uninit_partial\"\n\n    testTypeSuccess env0 \"class_init_attrs/init_inherited\"\n    testTypeError   env0 \"class_init_attrs/uninit_inherited\"\n    testTypeSuccess env0 \"class_init_attrs/init_parent_call\"\n    testTypeSuccess env0 \"class_init_attrs/init_mixed_parent_self\"\n    testTypeSuccess env0 \"class_init_attrs/init_grandparent_call\"\n    testTypeError   env0 \"class_init_attrs/uninit_no_parent_init\"\n    testTypeError   env0 \"class_init_attrs/uninit_grandparent\"\n    testTypeError   env0 \"class_init_attrs/uninit_grandparent2\"\n    testTypeSuccess env0 \"class_init_attrs/init_no_init_uses_parent\"\n\n    testTypeSuccess env0 \"class_init_attrs/init_conditional\"\n\n    testTypeSuccess env0 \"class_init_attrs/init_nested_if\"\n    testTypeSuccess env0 \"class_init_attrs/init_nested_if_raise\"\n    testTypeError   env0 \"class_init_attrs/uninit_nested_if\"\n    testTypeError   env0 \"class_init_attrs/uninit_elif_missing\"\n\n    testTypeSuccess env0 \"class_init_attrs/init_try_except\"\n    testTypeSuccess env0 \"class_init_attrs/init_try_finally\"\n    testTypeSuccess env0 \"class_init_attrs/init_try_except_finally\"\n    testTypeError   env0 \"class_init_attrs/uninit_try_except\"\n    testTypeSuccess env0 \"class_init_attrs/init_try_except_raise\"\n    testTypeSuccess env0 \"class_init_attrs/init_try_else_combined\"\n    testTypeSuccess env0 \"class_init_attrs/init_multiple_except_handlers\"\n    testTypeSuccess env0 \"class_init_attrs/init_except_raise_after_assignment\"\n    testTypeSuccess env0 \"class_init_attrs/init_try_inside_if\"\n    testTypeSuccess env0 \"class_init_attrs/init_constant_condition\"\n    testTypeSuccess env0 \"class_init_attrs/init_raise_after_assignment\"\n    testTypeSuccess env0 \"class_init_attrs/init_both_branches_with_raise\"\n    testTypeSuccess env0 \"class_init_attrs/init_elif_raise_after_assignment\"\n    testTypeSuccess env0 \"class_init_attrs/init_after_statements\"\n\n    testTypeSuccess env0 \"class_init_attrs/init_self_attr_access\"\n    testTypeSuccess env0 \"class_init_attrs/init_self_attr_in_expr\"\n    testTypeError   env0 \"class_init_attrs/uninit_self_attr_access\"\n    testTypeSuccess env0 \"class_init_attrs/init_self_attr_conditional\"\n    testTypeSuccess env0 \"class_init_attrs/init_self_attr_in_loop\"\n    testTypeError   env0 \"class_init_attrs/uninit_method_reference\"\n\n    testTypeSuccess env0 \"class_init_attrs/init_function_call\"\n    testTypeSuccess env0 \"class_init_attrs/init_nested_function_call\"\n    testTypeError   env0 \"class_init_attrs/uninit_method_call\"\n    testTypeError   env0 \"class_init_attrs/uninit_method_call_assign\"\n    testTypeSuccess env0 \"class_init_attrs/init_actor\"\n    testTypeSuccess env0 \"class_init_attrs/init_actor_call\"\n\n    testTypeSuccess env0 \"class_init_attrs/init_notimplemented\"\n    testTypeSuccess env0 \"class_init_attrs/init_notimpl_call\"\n    testTypeError   env0 \"class_init_attrs/uninit_notimpl_call_other\"\n    testTypeError   env0 \"class_init_attrs/uninit_augmented_assign\"\n    testTypeError   env0 \"class_init_attrs/uninit_for_loop\"\n    testTypeSuccess env0 \"class_init_attrs/init_after_loop\"\n    testTypeSuccess env0 \"class_init_attrs/init_after_while\"\n    testTypeError   env0 \"class_init_attrs/uninit_loop_references_self\"\n    testTypeError   env0 \"class_init_attrs/uninit_init_in_method\"\n    testTypeError   env0 \"class_init_attrs/uninit_return_early\"\n\n    testTypeError   env0 \"class_init_attrs/uninit_self_reference\"\n    testTypeSuccess env0 \"class_init_attrs/init_self_attr_reference\"\n    testTypeError   env0 \"class_init_attrs/uninit_self_in_list\"\n\n    testTypeSuccess env0 \"class_init_attrs/init_loop_break\"\n    testTypeSuccess env0 \"class_init_attrs/init_loop_continue\"\n    testTypeSuccess env0 \"class_init_attrs/init_assert\"\n    testTypeSuccess env0 \"class_init_attrs/init_assert_with_self\"\n    testTypeError   env0 \"class_init_attrs/uninit_assert_uninit_attr\"\n    testTypeSuccess env0 \"class_init_attrs/init_delete\"\n    testTypeSuccess env0 \"class_init_attrs/init_nested_function\"\n    testTypeError   env0 \"class_init_attrs/uninit_nested_function_with_self\"\n    testTypeError   env0 \"class_init_attrs/uninit_nested_function_escape\"\n\n\n-- Test a file that should produce a type error\n-- Path can be \"testname\" or \"subdir/testname\"\ntestTypeError :: Acton.Env.Env0 -> String -> Spec\ntestTypeError env0 path = do\n  let (subdir, testname) = case break (=='/') path of\n                             (name, \"\") -> (\"\", name)\n                             (dir, '/':name) -> (dir, name)\n                             _ -> error $ \"Invalid test path: \" ++ path\n      act_file = \"test\" </> \"src\" </> path ++ \".act\"\n      golden_file = \"test\" </> \"3-types\" </> path ++ \".golden\"\n      -- For error display, use just the basename like acton does\n      display_file = testname ++ \".act\"\n\n  it testname $ do\n    goldenTextFile golden_file $ liftIO $ do\n      -- Read the source file for error formatting\n      srcContent <- readFile act_file\n\n      result <- E.try $ do\n        (env, parsed) <- parseAct env0 path\n        kchecked <- Acton.Kinds.check env parsed\n        (nmod, tchecked, _, _) <- Acton.Types.reconstruct Nothing Nothing env kchecked\n        -- Force evaluation to trigger any lazy exceptions\n        E.evaluate $ length (show tchecked)\n        return ()\n\n      case result of\n        Left (e :: E.SomeException) -> do\n          -- Format the error like acton does\n          let diagnostic = case E.fromException e :: Maybe TypeError of\n                Just typeErr ->\n                  -- Use the typeReport function to format all TypeError variants with richer diagnostics\n                  let report = typeReport typeErr display_file srcContent\n                      diag = addReport mempty report\n                  in addFile diag display_file srcContent\n                _ -> case E.fromException e :: Maybe CompilationError of\n                  Just (IllegalSigOverride n) ->\n                    Diag.actErrToDiagnostic \"Compilation error\" display_file srcContent (loc n) (\"Illegal signature override: \" ++ prettyText n)\n                  Just (OtherError loc msg) ->\n                    Diag.actErrToDiagnostic \"Compilation error\" display_file srcContent loc msg\n                  Just compErr ->\n                    -- For other compilation errors, use the default show instance\n                    Diag.actErrToDiagnostic \"Compilation error\" display_file srcContent (loc compErr) (show compErr)\n                  _ ->\n                    -- For now, just use the default formatting for other errors\n                    let diagnostic = addReport mempty $ Err (Just \"error\") (show e) [] []\n                    in addFile diagnostic display_file srcContent\n\n          -- Pretty print the diagnostic\n          return $ T.pack $ show $\n            unAnnotate (prettyDiagnostic WithoutUnicode (TabSize 4) diagnostic)\n        Right _ ->\n          return $ T.pack \"ERROR: Expected type error but compilation succeeded\"\n\n-- Test a file that should type check successfully\n-- Path can be \"testname\" or \"subdir/testname\"\ntestTypeSuccess :: Acton.Env.Env0 -> String -> Spec\ntestTypeSuccess env0 path = do\n  let testname = takeBaseName path\n      act_file = \"test\" </> \"src\" </> path ++ \".act\"\n\n  it testname $ do\n    result <- E.try $ do\n      (env, parsed) <- parseAct env0 path\n      kchecked <- Acton.Kinds.check env parsed\n      (nmod, tchecked, _, _) <- Acton.Types.reconstruct Nothing Nothing env kchecked\n      -- Force evaluation to trigger any lazy exceptions\n      E.evaluate $ length (show tchecked)\n      return ()\n\n    case result of\n      Left (e :: E.SomeException) ->\n        expectationFailure $ \"Expected success but got error: \" ++ show e\n      Right _ ->\n        return ()\n"
  },
  {
    "path": "compiler/lib/test/doc-golden/bar-color.txt",
    "content": "\u001b[1mbar\u001b[0m - Bar module - defines shared types and utilities\n\nThis module provides common data structures and utilities\nthat are used across the application.\n\n\n\n\u001b[36mclass\u001b[0m \u001b[1mData\u001b[0m(object)\n  A data container with metadata\n\n    This class holds arbitrary data along with metadata\n    about when it was created and last modified.\n\n    Examples:\n        >>> d = Data(\"hello\", \"test-data\")\n        >>> d.get_value()\n        \"hello\"\n    \n\n  \u001b[33mAttributes:\u001b[0m\n    value: str\n    label: str\n    count: int\n\n  \u001b[33mMethods:\u001b[0m\n    \u001b[1m__init__\u001b[0m(self, value: \u001b[32mstr\u001b[0m, label: \u001b[32mstr\u001b[0m)\n      Initialize data with value and label\n\n        Args:\n            value: The data value\n            label: A descriptive label\n        \n    \u001b[1mget_value\u001b[0m(self) -> \u001b[32mstr\u001b[0m\n      Get the stored value\n\n        Returns:\n            The data value\n        \n    \u001b[1mupdate\u001b[0m(self, new_value: \u001b[32mstr\u001b[0m)\n      Update the value\n\n        Args:\n            new_value: New value to store\n\n        Note:\n            This increments the access count\n        \n    \u001b[1mget_info\u001b[0m(self) -> \u001b[32mstr\u001b[0m\n      Get formatted information about this data\n\n        Returns:\n            A string with label, value, and count\n        \n\n\u001b[36mclass\u001b[0m \u001b[1mContainer\u001b[0m[T](object)\n  A generic container that can hold items of any type\n\n    This container maintains a list of items with various\n    operations for manipulation and querying.\n\n    Type Args:\n        T: The type of items stored in the container\n    \n\n  \u001b[33mAttributes:\u001b[0m\n    items: list[T]\n    name: str\n\n  \u001b[33mMethods:\u001b[0m\n    \u001b[1m__init__\u001b[0m(self, name: \u001b[32mstr\u001b[0m)\n      Create an empty container\n\n        Args:\n            name: Container name for identification\n        \n    \u001b[1madd\u001b[0m(self, item: \u001b[32mT\u001b[0m)\n      Add an item to the container\n\n        Args:\n            item: Item to add\n\n        Raises:\n            ValueError: If container is full\n        \n    \u001b[1mget_all\u001b[0m(self) -> \u001b[32mlist[T]\u001b[0m\n      Get all items\n\n        Returns:\n            List of all items in the container\n        \n    \u001b[1mfilter\u001b[0m[U](self, predicate: \u001b[32m(T) -> bool\u001b[0m, transform: \u001b[32m(T) -> U\u001b[0m) -> \u001b[32mlist[U]\u001b[0m\n      Filter and transform items\n\n        Args:\n            predicate: Function to test each item\n            transform: Function to transform matching items\n\n        Returns:\n            List of transformed items that match predicate\n\n        Examples:\n            >>> c = Container[int](\"numbers\")\n            >>> c.add(1)\n            >>> c.add(2)\n            >>> c.filter(lambda x: x > 1, lambda x: str(x))\n            [\"2\"]\n        \n    \u001b[1mcount\u001b[0m(self) -> \u001b[32mint\u001b[0m\n      Get number of items in container\n\n        Returns:\n            Number of items\n        \n\n\u001b[1mprocess_data\u001b[0m(d: \u001b[32mbar.Data\u001b[0m) -> \u001b[32mstr\u001b[0m\n  Process a data object and return summary\n\n    Args:\n        d: Data object to process\n\n    Returns:\n        Processed summary string\n\n    See Also:\n        Data.get_info: For detailed information\n    \n\n\u001b[1mcombine_data\u001b[0m(d1: \u001b[32mbar.Data\u001b[0m, d2: \u001b[32mbar.Data\u001b[0m) -> \u001b[32mbar.Data\u001b[0m\n  Combine two data objects\n\n    Args:\n        d1: First data object\n        d2: Second data object\n\n    Returns:\n        New Data object with combined values\n    \n\n\u001b[36mactor\u001b[0m \u001b[1mDataProcessor\u001b[0m()\n  Actor that processes Data objects\n\n    This actor maintains a queue of data objects\n    and processes them asynchronously.\n    \n\n\u001b[1msum_counts\u001b[0m[T](items: \u001b[32mlist[T]\u001b[0m) -> \u001b[32mT\u001b[0m\n  Sum a list of items that support addition\n\n    Args:\n        items: List of summable items\n\n    Returns:\n        Sum of all items\n\n    Raises:\n        ValueError: If list is empty\n    \n\n\u001b[36mprotocol\u001b[0m \u001b[1mProcessable\u001b[0m[T]\n  Protocol for objects that can be processed\n\n    This protocol defines the interface for objects that\n    can be processed and transformed into a result of type T.\n\n    Type Args:\n        T: The type of the processing result\n    \n\n  \u001b[33mMethods:\u001b[0m\n    process: T\n    validate: bool\n    get_metadata: dict[str,str]\n\n\u001b[36mextension\u001b[0m Data(Processable[str])\n  Makes Data implement the Processable protocol\n\n    This extension allows Data objects to be processed\n    according to the Processable protocol, returning\n    string results.\n    \n\n\u001b[1mprocess_items\u001b[0m[T](items: \u001b[32mlist[A]\u001b[0m) -> \u001b[32mlist[T]\u001b[0m\n  Process a list of processable items\n\n    Args:\n        items: List of items implementing Processable protocol\n\n    Returns:\n        List of processed results\n\n    Examples:\n        >>> d1 = Data(\"hello\", \"test\")\n        >>> d2 = Data(\"world\", \"test2\")\n        >>> results = process_items([d1, d2])\n        >>> results\n        [\"HELLO\", \"WORLD\"]\n    \n\n\u001b[1mgt\u001b[0m(a: \u001b[32mA\u001b[0m, b: \u001b[32mA\u001b[0m, c: \u001b[32mB\u001b[0m, d: \u001b[32mB\u001b[0m) -> \u001b[32m(A, A, B)\u001b[0m\n  Function that takes generic types\n"
  },
  {
    "path": "compiler/lib/test/doc-golden/bar.html",
    "content": "<!DOCTYPE html>\n<html lang=\"en\">\n<head>\n  <meta charset=\"UTF-8\">\n  <meta name=\"viewport\" content=\"width=device-width, initial-scale=1.0\">\n  <title>bar</title>\n  <style>\n    /* Light theme colors (default) */\n    :root {\n      --text-primary: #24292e;\n      --text-secondary: #6a737d;\n      --text-link: #0366d6;\n      --bg-primary: #ffffff;\n      --bg-secondary: #f6f8fa;\n      --border: #e1e4e8;\n      --code-bg: #f6f8fa;\n      --type-color: #6f42c1;\n      --keyword-color: #d73a49;\n      --generic-color: #e36209;\n      --generic-hover: #fb8532;\n      --shadow: rgba(27, 31, 35, 0.04);\n      --shadow-medium: rgba(27, 31, 35, 0.12);\n    }\n    \n    /* Dark theme colors (activated by OS preference) */\n    @media (prefers-color-scheme: dark) {\n      :root {\n        --text-primary: #c9d1d9;\n        --text-secondary: #8b949e;\n        --text-link: #58a6ff;\n        --bg-primary: #0d1117;\n        --bg-secondary: #161b22;\n        --border: #30363d;\n        --code-bg: #161b22;\n        --type-color: #d2a8ff;\n        --keyword-color: #ff7b72;\n        --generic-color: #ffa657;\n        --generic-hover: #ffb77c;\n        --shadow: rgba(0, 0, 0, 0.3);\n        --shadow-medium: rgba(0, 0, 0, 0.5);\n      }\n    }\n    \n    * { box-sizing: border-box; }\n    \n    body {\n      font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Helvetica, Arial, sans-serif;\n      font-size: 16px;\n      line-height: 1.5;\n      color: var(--text-primary);\n      background: var(--bg-primary);\n      margin: 0;\n      padding: 0;\n    }\n    \n    .container {\n      max-width: 960px;\n      margin: 0 auto;\n      padding: 2rem;\n    }\n    \n    /* Typography */\n    h1 {\n      font-size: 2rem;\n      font-weight: 600;\n      margin: 0 0 1rem 0;\n      padding-bottom: 0.3rem;\n      border-bottom: 1px solid var(--border);\n    }\n    \n    h2 {\n      font-size: 1.25rem;\n      font-weight: 600;\n      margin: 2.5rem 0 1rem 0;\n    }\n    \n    h3 {\n      font-size: 1rem;\n      font-weight: 600;\n      color: var(--text-secondary);\n      margin: 1.5rem 0 0.5rem 0;\n      text-transform: uppercase;\n      letter-spacing: 0.02em;\n    }\n    \n    /* Indent ATTRIBUTES/METHODS headers under classes/actors */\n    .declaration-block h3 {\n      margin-left: 2rem;\n    }\n    \n    p {\n      margin: 0 0 1rem 0;\n    }\n    \n    /* Code */\n    code {\n      font-family: 'SF Mono', Monaco, Consolas, 'Liberation Mono', 'Courier New', monospace;\n      font-size: 0.875em;\n      background: var(--code-bg);\n      padding: 0.2em 0.4em;\n      border-radius: 3px;\n      border: 1px solid var(--border);\n    }\n    \n    h2 code {\n      background: none;\n      padding: 0;\n      font-size: 1em;\n      border: none;\n    }\n    \n    /* Type coloring */\n    .type {\n      color: var(--type-color);\n    }\n    \n    /* Type links */\n    .type-link {\n      color: var(--type-color);\n      text-decoration: none;\n      border-bottom: 1px dotted var(--type-color);\n    }\n    \n    .type-link:hover {\n      text-decoration: none;\n      border-bottom: 1px solid var(--type-color);\n    }\n    \n    .keyword {\n      color: var(--keyword-color);\n      font-weight: 500;\n      font-size: 1rem;\n    }\n    \n    .param-name {\n      font-weight: 500;\n    }\n    \n    .default-value {\n      color: var(--text-secondary);\n    }\n    \n    /* Generic type parameters */\n    .generic-type {\n      color: var(--generic-color);\n      cursor: pointer;\n      transition: color 0.2s ease;\n      position: relative;\n      display: inline-block;\n    }\n    \n    .generic-type:hover,\n    .generic-type.highlight {\n      color: var(--generic-hover);\n      text-decoration: underline;\n      text-decoration-style: dotted;\n    }\n    \n    /* Tooltip for generic types - default position below */\n    .generic-type[data-tooltip]:hover::after {\n      content: attr(data-tooltip);\n      display: block;\n      position: absolute;\n      top: 100%;\n      left: 50%;\n      transform: translateX(-50%);\n      margin-top: 5px;\n      padding: 8px 12px;\n      background-color: rgba(0, 0, 0, 0.8);\n      color: white;\n      font-size: 0.75rem;\n      font-weight: normal;\n      white-space: pre-wrap;\n      max-width: 700px;\n      min-width: 200px;\n      text-align: left;\n      border-radius: 4px;\n      pointer-events: none;\n      opacity: 0;\n      animation: fadeIn 0.2s ease-in-out forwards;\n      z-index: 1000;\n    }\n    \n    /* Tooltip positioned above when not near top */\n    .generic-type[data-tooltip]:not(.tooltip-below):hover::after {\n      top: auto;\n      bottom: 100%;\n      margin-top: 0;\n      margin-bottom: 5px;\n    }\n    \n    @keyframes fadeIn {\n      from { opacity: 0; }\n      to { opacity: 1; }\n    }\n    \n    /* Documentation strings */\n    .docstring {\n      color: var(--text-secondary);\n      margin: 0.5rem 0 1.5rem 0;\n      padding-left: 1rem;\n    }\n    \n    .module-doc {\n      margin: 1rem 0 2rem 0;\n      color: var(--text-primary);\n      font-size: 1.1rem;\n      line-height: 1.6;\n    }\n    \n    /* Sections */\n    .section {\n      margin: 1.5rem 0;\n      padding-left: 2rem;\n    }\n    \n    /* Lists */\n    ul {\n      list-style: none;\n      padding: 0;\n      margin: 0;\n    }\n    \n    li {\n      margin: 0.5rem 0;\n    }\n    \n    /* Attribute items */\n    .attribute-item {\n      margin: 0.5rem 0;\n      padding-left: 1rem;\n      border-left: 3px solid var(--border);\n    }\n    \n    .attribute-item code {\n      background: none;\n      padding: 0;\n      border: none;\n    }\n    \n    /* Method items */\n    .method-item {\n      margin: 1rem 0;\n    }\n    \n    .method-signature {\n      font-family: 'SF Mono', Monaco, Consolas, monospace;\n      font-size: 0.875rem;\n      padding-left: 1rem;\n      border-left: 3px solid var(--border);\n    }\n    \n    .method-signature code {\n      background: none;\n      padding: 0;\n      border: none;\n    }\n    \n    .method-doc {\n      color: var(--text-secondary);\n      margin: 0.25rem 0 0 1.5rem;\n      font-size: 0.875rem;\n    }\n    \n    /* Attributes and methods sections */\n    .attributes, .methods {\n      margin: 1.5rem 0 1.5rem 2rem;\n    }\n    \n    /* Declaration blocks - no visual boxes, just spacing */\n    .declaration-block {\n      margin: 2rem 0;\n    }\n    \n    /* Module index styles */\n    .module-list {\n      list-style: none;\n      padding: 0;\n      margin: 0;\n    }\n    \n    .module-item {\n      margin: 0.5rem 0;\n      padding: 0.75rem 1rem;\n      background: var(--bg-secondary);\n      border-radius: 6px;\n      border: 1px solid var(--border);\n      transition: all 0.2s ease;\n    }\n    \n    .module-item:hover {\n      border-color: var(--text-link);\n      transform: translateY(-1px);\n    }\n    \n    .module-link {\n      text-decoration: none;\n      color: var(--text-link);\n      font-weight: 500;\n      display: block;\n    }\n    \n    .module-path {\n      font-family: 'SF Mono', Monaco, Consolas, monospace;\n      font-size: 0.875rem;\n    }\n    \n    .module-doc {\n      color: var(--text-secondary);\n      font-size: 0.875rem;\n      margin-top: 0.25rem;\n    }\n    \n    /* Smooth transitions for theme changes */\n    * {\n      transition: background-color 0.3s ease, color 0.3s ease, border-color 0.3s ease;\n    }\n    \n    /* Responsive */\n    @media (max-width: 768px) {\n      .container {\n        padding: 1rem;\n      }\n      h1 {\n        font-size: 1.75rem;\n      }\n      h2 {\n        font-size: 1.25rem;\n      }\n    }\n\n  </style>\n  <script>\n    document.addEventListener('DOMContentLoaded', function() {\n      const genericTypes = document.querySelectorAll('.generic-type');\n      \n      genericTypes.forEach(function(elem) {\n        elem.addEventListener('mouseenter', function() {\n          const typeName = elem.getAttribute('data-generic');\n          \n          // Check if tooltip would go off-screen at the top\n          const rect = elem.getBoundingClientRect();\n          const tooltipHeight = 200; // Approximate height\n          if (rect.top < tooltipHeight) {\n            elem.classList.add('tooltip-below');\n          } else {\n            elem.classList.remove('tooltip-below');\n          }\n          \n          // Get the scope attribute - all generic types should have this\n          const scope = elem.getAttribute('data-scope');\n          \n          // Only highlight elements with same type name AND same scope\n          document.querySelectorAll('.generic-type[data-generic=\"' + typeName + '\"][data-scope=\"' + scope + '\"]').forEach(function(t) {\n            t.classList.add('highlight');\n          });\n        });\n        \n        elem.addEventListener('mouseleave', function() {\n          const typeName = elem.getAttribute('data-generic');\n          document.querySelectorAll('.generic-type[data-generic=\"' + typeName + '\"].highlight').forEach(function(t) {\n            t.classList.remove('highlight');\n          });\n        });\n      });\n    });\n\n  </script>\n</head>\n<body>\n  <div class=\"container\">\n<h1>bar - Bar module - defines shared types and utilities</h1>\n<div class=\"module-doc\">This module provides common data structures and utilities<br>that are used across the application.</div>\n<div class=\"declaration-block\">\n<h2 id=\"class-Data\" class=\"type-context\"><span class=\"keyword\">class</span> <code>Data</code>(<span class=\"type\">object</span>)</h2>\n<div class=\"docstring\">A data container with metadata<br><br>    This class holds arbitrary data along with metadata<br>    about when it was created and last modified.<br><br>    Examples:<br>        &gt;&gt;&gt; d = Data(&quot;hello&quot;, &quot;test-data&quot;)<br>        &gt;&gt;&gt; d.get_value()<br>        &quot;hello&quot;<br>    </div>\n\n<h3>Attributes</h3>\n<div class=\"attributes\">\n<div class=\"attribute-item\"><code>value</code>: <span class=\"type\">str</span></div>\n<div class=\"attribute-item\"><code>label</code>: <span class=\"type\">str</span></div>\n<div class=\"attribute-item\"><code>count</code>: <span class=\"type\">int</span></div>\n</div>\n\n<h3>Methods</h3>\n<div class=\"methods\">\n<div class=\"method-item\">\n<div class=\"method-signature\"><code>__init__</code>(<span class=\"param-name\">self</span>, <span class=\"param-name\">value</span>: <span class=\"type\">str</span>, <span class=\"param-name\">label</span>: <span class=\"type\">str</span>)</div>\n<div class=\"method-doc\">Initialize data with value and label<br><br>        Args:<br>            value: The data value<br>            label: A descriptive label<br>        </div>\n</div>\n<div class=\"method-item\">\n<div class=\"method-signature\"><code>get_value</code>(<span class=\"param-name\">self</span>) → <span class=\"type\">str</span></div>\n<div class=\"method-doc\">Get the stored value<br><br>        Returns:<br>            The data value<br>        </div>\n</div>\n<div class=\"method-item\">\n<div class=\"method-signature\"><code>update</code>(<span class=\"param-name\">self</span>, <span class=\"param-name\">new_value</span>: <span class=\"type\">str</span>)</div>\n<div class=\"method-doc\">Update the value<br><br>        Args:<br>            new_value: New value to store<br><br>        Note:<br>            This increments the access count<br>        </div>\n</div>\n<div class=\"method-item\">\n<div class=\"method-signature\"><code>get_info</code>(<span class=\"param-name\">self</span>) → <span class=\"type\">str</span></div>\n<div class=\"method-doc\">Get formatted information about this data<br><br>        Returns:<br>            A string with label, value, and count<br>        </div>\n</div>\n</div>\n</div>\n\n<div class=\"declaration-block\">\n<h2 id=\"class-Container\" class=\"type-context\"><span class=\"keyword\">class</span> <code>Container</code>[<span class=\"generic-type\" data-generic=\"T\" data-scope=\"class-Container\" data-tooltip=\"Generic type T\n\nThis is a placeholder for any type.\nAll Ts must be the same type.\">T</span>](<span class=\"type\">object</span>)</h2>\n<div class=\"docstring\">A generic container that can hold items of any type<br><br>    This container maintains a list of items with various<br>    operations for manipulation and querying.<br><br>    Type Args:<br>        T: The type of items stored in the container<br>    </div>\n\n<h3>Attributes</h3>\n<div class=\"attributes\">\n<div class=\"attribute-item\"><code>items</code>: <span class=\"type\">list[<span class=\"generic-type\" data-generic=\"T\" data-tooltip=\"Generic type T\n\nThis is a placeholder for any type.\nAll Ts must be the same type.\">T</span>]</span></div>\n<div class=\"attribute-item\"><code>name</code>: <span class=\"type\">str</span></div>\n</div>\n\n<h3>Methods</h3>\n<div class=\"methods\">\n<div class=\"method-item\">\n<div class=\"method-signature\"><code>__init__</code>(<span class=\"param-name\">self</span>, <span class=\"param-name\">name</span>: <span class=\"type\">str</span>)</div>\n<div class=\"method-doc\">Create an empty container<br><br>        Args:<br>            name: Container name for identification<br>        </div>\n</div>\n<div class=\"method-item\">\n<div class=\"method-signature\"><code>add</code>(<span class=\"param-name\">self</span>, <span class=\"param-name\">item</span>: <span class=\"type\"><span class=\"generic-type\" data-generic=\"T\" data-tooltip=\"Generic type T\n\nThis is a placeholder for any type.\nAll Ts must be the same type.\">T</span></span>)</div>\n<div class=\"method-doc\">Add an item to the container<br><br>        Args:<br>            item: Item to add<br><br>        Raises:<br>            ValueError: If container is full<br>        </div>\n</div>\n<div class=\"method-item\">\n<div class=\"method-signature\"><code>get_all</code>(<span class=\"param-name\">self</span>) → <span class=\"type\">list[<span class=\"generic-type\" data-generic=\"T\" data-tooltip=\"Generic type T\n\nThis is a placeholder for any type.\nAll Ts must be the same type.\">T</span>]</span></div>\n<div class=\"method-doc\">Get all items<br><br>        Returns:<br>            List of all items in the container<br>        </div>\n</div>\n<div class=\"method-item\">\n<div class=\"method-signature\"><code>filter</code>[<span class=\"generic-type\" data-generic=\"U\" data-scope=\"\" data-tooltip=\"Generic type U\n\nThis is a placeholder for any type.\nAll Us must be the same type.\">U</span>](<span class=\"param-name\">self</span>, <span class=\"param-name\">predicate</span>: <span class=\"type\">(<span class=\"generic-type\" data-generic=\"T\" data-tooltip=\"Generic type T\n\nThis is a placeholder for any type.\nAll Ts must be the same type.\">T</span>) -> bool</span>, <span class=\"param-name\">transform</span>: <span class=\"type\">(<span class=\"generic-type\" data-generic=\"T\" data-tooltip=\"Generic type T\n\nThis is a placeholder for any type.\nAll Ts must be the same type.\">T</span>) -> U</span>) → <span class=\"type\">list[<span class=\"generic-type\" data-generic=\"U\" data-tooltip=\"Generic type U\n\nThis is a placeholder for any type.\nAll Us must be the same type.\">U</span>]</span></div>\n<div class=\"method-doc\">Filter and transform items<br><br>        Args:<br>            predicate: Function to test each item<br>            transform: Function to transform matching items<br><br>        Returns:<br>            List of transformed items that match predicate<br><br>        Examples:<br>            &gt;&gt;&gt; c = Container[int](&quot;numbers&quot;)<br>            &gt;&gt;&gt; c.add(1)<br>            &gt;&gt;&gt; c.add(2)<br>            &gt;&gt;&gt; c.filter(lambda x: x &gt; 1, lambda x: str(x))<br>            [&quot;2&quot;]<br>        </div>\n</div>\n<div class=\"method-item\">\n<div class=\"method-signature\"><code>count</code>(<span class=\"param-name\">self</span>) → <span class=\"type\">int</span></div>\n<div class=\"method-doc\">Get number of items in container<br><br>        Returns:<br>            Number of items<br>        </div>\n</div>\n</div>\n</div>\n\n<h2 class=\"type-context\"><code>process_data</code>(<span class=\"param-name\">d</span>: <span class=\"type\"><a href=\"bar.html#class-Data\" class=\"type-link\">bar.Data</a></span>) → <span class=\"type\">str</span></h2>\n<div class=\"docstring\">Process a data object and return summary<br><br>    Args:<br>        d: Data object to process<br><br>    Returns:<br>        Processed summary string<br><br>    See Also:<br>        Data.get_info: For detailed information<br>    </div>\n\n<h2 class=\"type-context\"><code>combine_data</code>(<span class=\"param-name\">d1</span>: <span class=\"type\"><a href=\"bar.html#class-Data\" class=\"type-link\">bar.Data</a></span>, <span class=\"param-name\">d2</span>: <span class=\"type\"><a href=\"bar.html#class-Data\" class=\"type-link\">bar.Data</a></span>) → <span class=\"type\"><a href=\"bar.html#class-Data\" class=\"type-link\">bar.Data</a></span></h2>\n<div class=\"docstring\">Combine two data objects<br><br>    Args:<br>        d1: First data object<br>        d2: Second data object<br><br>    Returns:<br>        New Data object with combined values<br>    </div>\n\n<div class=\"declaration-block\">\n<h2 class=\"type-context\"><span class=\"keyword\">actor</span> <code>DataProcessor</code>()</h2>\n<div class=\"docstring\">Actor that processes Data objects<br><br>    This actor maintains a queue of data objects<br>    and processes them asynchronously.<br>    </div>\n\n<h3>Internal Attributes</h3>\n<div class=\"attributes\">\n<div class=\"attribute-item\"><code>queue</code>: <span class=\"type\">list[<a href=\"#class-Data\" class=\"type-link\">Data</a>]</span></div>\n<div class=\"attribute-item\"><code>processed_count</code>: <span class=\"type\">int</span></div>\n</div>\n<h3>Methods</h3>\n<div class=\"methods\">\n<div class=\"method-item\">\n<div class=\"method-signature\"><code>enqueue</code>(<span class=\"param-name\">d</span>: <span class=\"type\"><a href=\"#class-Data\" class=\"type-link\">Data</a></span>)</div>\n<div class=\"method-doc\">Add data to processing queue<br><br>        Args:<br>            d: Data object to process<br>        </div>\n</div>\n<div class=\"method-item\">\n<div class=\"method-signature\"><code>process_next</code>() → <span class=\"type\">?<a href=\"#class-Data\" class=\"type-link\">Data</a></span></div>\n<div class=\"method-doc\">Process next item in queue<br><br>        Returns:<br>            Processed data or None if queue empty<br>        </div>\n</div>\n<div class=\"method-item\">\n<div class=\"method-signature\"><code>get_stats</code>() → <span class=\"type\">dict[str, int]</span></div>\n<div class=\"method-doc\">Get processing statistics<br><br>        Returns:<br>            Dict with queue size and processed count<br>        </div>\n</div>\n</div>\n</div>\n\n<h2 class=\"type-context\"><code>sum_counts</code>[<span class=\"generic-type\" data-generic=\"T\" data-scope=\"def-sum_counts\" data-tooltip=\"Generic type T\n\nThis is a placeholder for any type.\nAll Ts must be the same type.\n\nT must support:\n  • Plus protocol (protocol methods)\n\">T</span>(Plus)] => (<span class=\"param-name\">items</span>: <span class=\"type\">[<span class=\"generic-type\" data-generic=\"T\" data-scope=\"def-sum_counts\" data-tooltip=\"Generic type T\n\nThis is a placeholder for any type.\nAll Ts must be the same type.\n\nT must support:\n  • Plus protocol (protocol methods)\n\">T</span>]</span>) → <span class=\"type\"><span class=\"generic-type\" data-generic=\"T\" data-scope=\"def-sum_counts\" data-tooltip=\"Generic type T\n\nThis is a placeholder for any type.\nAll Ts must be the same type.\n\nT must support:\n  • Plus protocol (protocol methods)\n\">T</span></span></h2>\n<div class=\"docstring\">Sum a list of items that support addition<br><br>    Args:<br>        items: List of summable items<br><br>    Returns:<br>        Sum of all items<br><br>    Raises:<br>        ValueError: If list is empty<br>    </div>\n\n<div class=\"declaration-block\">\n<h2 class=\"type-context\"><span class=\"keyword\">protocol</span> <code>Processable</code>[<span class=\"generic-type\" data-generic=\"T\" data-scope=\"protocol-Processable\" data-tooltip=\"Generic type T\n\nThis is a placeholder for any type.\nAll Ts must be the same type.\">T</span>]</h2>\n<div class=\"docstring\">Protocol for objects that can be processed<br><br>    This protocol defines the interface for objects that<br>    can be processed and transformed into a result of type T.<br><br>    Type Args:<br>        T: The type of the processing result<br>    </div>\n\n<h3>Required Methods</h3>\n<div class=\"methods\">\n<div class=\"method-item\">\n<div class=\"method-signature\"><code>process</code>() → <span class=\"type\"><span class=\"generic-type\" data-generic=\"T\" data-tooltip=\"Generic type T\n\nThis is a placeholder for any type.\nAll Ts must be the same type.\">T</span></span></div>\n</div>\n<div class=\"method-item\">\n<div class=\"method-signature\"><code>validate</code>() → <span class=\"type\">bool</span></div>\n</div>\n<div class=\"method-item\">\n<div class=\"method-signature\"><code>get_metadata</code>() → <span class=\"type\">dict[str, str]</span></div>\n</div>\n</div>\n</div>\n\n<div class=\"declaration-block\">\n<h2 class=\"type-context\"><span class=\"keyword\">extension</span> <code>Data</code>(<span class=\"type\">Processable[str]</span>)</h2>\n<div class=\"docstring\">Makes Data implement the Processable protocol<br><br>    This extension allows Data objects to be processed<br>    according to the Processable protocol, returning<br>    string results.<br>    </div>\n\n<h3>Methods</h3>\n<div class=\"methods\">\n<div class=\"method-item\">\n<div class=\"method-signature\"><code>process</code>(<span class=\"param-name\">self</span>) → <span class=\"type\">str</span></div>\n<div class=\"method-doc\">Process data by converting to uppercase<br><br>        Returns:<br>            Uppercase version of the data value<br>        </div>\n</div>\n<div class=\"method-item\">\n<div class=\"method-signature\"><code>validate</code>(<span class=\"param-name\">self</span>) → <span class=\"type\">bool</span></div>\n<div class=\"method-doc\">Check if data is non-empty<br><br>        Returns:<br>            True if data has content, False if empty<br>        </div>\n</div>\n<div class=\"method-item\">\n<div class=\"method-signature\"><code>get_metadata</code>(<span class=\"param-name\">self</span>) → <span class=\"type\">dict[str, str]</span></div>\n<div class=\"method-doc\">Get data metadata<br><br>        Returns:<br>            Metadata including label and access count<br>        </div>\n</div>\n</div>\n</div>\n\n<h2 class=\"type-context\"><code>process_items</code>[<span class=\"generic-type\" data-generic=\"T\" data-scope=\"def-process_items\" data-tooltip=\"Generic type T\n\nThis is a placeholder for any type.\nAll Ts must be the same type.\">T</span>, <span class=\"generic-type\" data-generic=\"A\" data-scope=\"def-process_items\" data-tooltip=\"Generic type A\n\nThis is a placeholder for any type.\nAll As must be the same type.\n\nA must support:\n  • bar.Processable protocol (protocol methods)\n\">A</span>(bar.Processable)] => (<span class=\"param-name\">items</span>: <span class=\"type\">[<span class=\"generic-type\" data-generic=\"A\" data-scope=\"def-process_items\" data-tooltip=\"Generic type A\n\nThis is a placeholder for any type.\nAll As must be the same type.\n\nA must support:\n  • bar.Processable protocol (protocol methods)\n\">A</span>]</span>) → <span class=\"type\">[<span class=\"generic-type\" data-generic=\"T\" data-scope=\"def-process_items\" data-tooltip=\"Generic type T\n\nThis is a placeholder for any type.\nAll Ts must be the same type.\">T</span>]</span></h2>\n<div class=\"docstring\">Process a list of processable items<br><br>    Args:<br>        items: List of items implementing Processable protocol<br><br>    Returns:<br>        List of processed results<br><br>    Examples:<br>        &gt;&gt;&gt; d1 = Data(&quot;hello&quot;, &quot;test&quot;)<br>        &gt;&gt;&gt; d2 = Data(&quot;world&quot;, &quot;test2&quot;)<br>        &gt;&gt;&gt; results = process_items([d1, d2])<br>        &gt;&gt;&gt; results<br>        [&quot;HELLO&quot;, &quot;WORLD&quot;]<br>    </div>\n\n<h2 class=\"type-context\"><code>gt</code>[<span class=\"generic-type\" data-generic=\"A\" data-scope=\"def-gt\" data-tooltip=\"Generic type A\n\nThis is a placeholder for any type.\nAll As must be the same type.\n\nA must support:\n  • Minus protocol (protocol methods)\n  • Plus protocol (protocol methods)\n\">A</span>(Minus, Plus), <span class=\"generic-type\" data-generic=\"B\" data-scope=\"def-gt\" data-tooltip=\"Generic type B\n\nThis is a placeholder for any type.\nAll Bs must be the same type.\n\nB must support:\n  • Plus protocol (protocol methods)\n\">B</span>(Plus)] => (<span class=\"param-name\">a</span>: <span class=\"type\"><span class=\"generic-type\" data-generic=\"A\" data-scope=\"def-gt\" data-tooltip=\"Generic type A\n\nThis is a placeholder for any type.\nAll As must be the same type.\n\nA must support:\n  • Minus protocol (protocol methods)\n  • Plus protocol (protocol methods)\n\">A</span></span>, <span class=\"param-name\">b</span>: <span class=\"type\"><span class=\"generic-type\" data-generic=\"A\" data-scope=\"def-gt\" data-tooltip=\"Generic type A\n\nThis is a placeholder for any type.\nAll As must be the same type.\n\nA must support:\n  • Minus protocol (protocol methods)\n  • Plus protocol (protocol methods)\n\">A</span></span>, <span class=\"param-name\">c</span>: <span class=\"type\"><span class=\"generic-type\" data-generic=\"B\" data-scope=\"def-gt\" data-tooltip=\"Generic type B\n\nThis is a placeholder for any type.\nAll Bs must be the same type.\n\nB must support:\n  • Plus protocol (protocol methods)\n\">B</span></span>, <span class=\"param-name\">d</span>: <span class=\"type\"><span class=\"generic-type\" data-generic=\"B\" data-scope=\"def-gt\" data-tooltip=\"Generic type B\n\nThis is a placeholder for any type.\nAll Bs must be the same type.\n\nB must support:\n  • Plus protocol (protocol methods)\n\">B</span></span>) → <span class=\"type\">(<span class=\"generic-type\" data-generic=\"A\" data-scope=\"def-gt\" data-tooltip=\"Generic type A\n\nThis is a placeholder for any type.\nAll As must be the same type.\n\nA must support:\n  • Minus protocol (protocol methods)\n  • Plus protocol (protocol methods)\n\">A</span>, <span class=\"generic-type\" data-generic=\"A\" data-scope=\"def-gt\" data-tooltip=\"Generic type A\n\nThis is a placeholder for any type.\nAll As must be the same type.\n\nA must support:\n  • Minus protocol (protocol methods)\n  • Plus protocol (protocol methods)\n\">A</span>, <span class=\"generic-type\" data-generic=\"B\" data-scope=\"def-gt\" data-tooltip=\"Generic type B\n\nThis is a placeholder for any type.\nAll Bs must be the same type.\n\nB must support:\n  • Plus protocol (protocol methods)\n\">B</span>)</span></h2>\n<div class=\"docstring\">Function that takes generic types</div>\n  </div>\n</body>\n</html>\n"
  },
  {
    "path": "compiler/lib/test/doc-golden/bar.md",
    "content": "# `bar`: Bar module - defines shared types and utilities\n\nThis module provides common data structures and utilities\nthat are used across the application.\n\n\n\n## *class* `Data`(object)\n\nA data container with metadata\n\n    This class holds arbitrary data along with metadata\n    about when it was created and last modified.\n\n    Examples:\n        >>> d = Data(\"hello\", \"test-data\")\n        >>> d.get_value()\n        \"hello\"\n    \n\n**Attributes:**\n\n- `value`: *str*\n- `label`: *str*\n- `count`: *int*\n\n**Methods:**\n\n- `__init__`(self, value: *str*, label: *str*)\n\n  Initialize data with value and label\n\n        Args:\n            value: The data value\n            label: A descriptive label\n        \n- `get_value`(self) → *str*\n\n  Get the stored value\n\n        Returns:\n            The data value\n        \n- `update`(self, new_value: *str*)\n\n  Update the value\n\n        Args:\n            new_value: New value to store\n\n        Note:\n            This increments the access count\n        \n- `get_info`(self) → *str*\n\n  Get formatted information about this data\n\n        Returns:\n            A string with label, value, and count\n        \n\n\n## *class* `Container`[T](object)\n\nA generic container that can hold items of any type\n\n    This container maintains a list of items with various\n    operations for manipulation and querying.\n\n    Type Args:\n        T: The type of items stored in the container\n    \n\n**Attributes:**\n\n- `items`: *list[T]*\n- `name`: *str*\n\n**Methods:**\n\n- `__init__`(self, name: *str*)\n\n  Create an empty container\n\n        Args:\n            name: Container name for identification\n        \n- `add`(self, item: *T*)\n\n  Add an item to the container\n\n        Args:\n            item: Item to add\n\n        Raises:\n            ValueError: If container is full\n        \n- `get_all`(self) → *list[T]*\n\n  Get all items\n\n        Returns:\n            List of all items in the container\n        \n- `filter`[U](self, predicate: *(T) -> bool*, transform: *(T) -> U*) → *list[U]*\n\n  Filter and transform items\n\n        Args:\n            predicate: Function to test each item\n            transform: Function to transform matching items\n\n        Returns:\n            List of transformed items that match predicate\n\n        Examples:\n            >>> c = Container[int](\"numbers\")\n            >>> c.add(1)\n            >>> c.add(2)\n            >>> c.filter(lambda x: x > 1, lambda x: str(x))\n            [\"2\"]\n        \n- `count`(self) → *int*\n\n  Get number of items in container\n\n        Returns:\n            Number of items\n        \n\n\n## `process_data`(d: *bar.Data*) → *str*\n\nProcess a data object and return summary\n\n    Args:\n        d: Data object to process\n\n    Returns:\n        Processed summary string\n\n    See Also:\n        Data.get_info: For detailed information\n    \n\n\n## `combine_data`(d1: *bar.Data*, d2: *bar.Data*) → *bar.Data*\n\nCombine two data objects\n\n    Args:\n        d1: First data object\n        d2: Second data object\n\n    Returns:\n        New Data object with combined values\n    \n\n\n## *actor* `DataProcessor`()\n\nActor that processes Data objects\n\n    This actor maintains a queue of data objects\n    and processes them asynchronously.\n    \n\n\n## `sum_counts`[T(Plus)](items: *list[T]*) → *T*\n\nSum a list of items that support addition\n\n    Args:\n        items: List of summable items\n\n    Returns:\n        Sum of all items\n\n    Raises:\n        ValueError: If list is empty\n    \n\n\n## *protocol* `Processable`[T]\n\nProtocol for objects that can be processed\n\n    This protocol defines the interface for objects that\n    can be processed and transformed into a result of type T.\n\n    Type Args:\n        T: The type of the processing result\n    \n\n**Methods:**\n\n- `process`: *T*\n- `validate`: *bool*\n- `get_metadata`: *dict[str,str]*\n\n\n## *extension* `Data`(Processable[str])\n\nMakes Data implement the Processable protocol\n\n    This extension allows Data objects to be processed\n    according to the Processable protocol, returning\n    string results.\n    \n\n\n## `process_items`[T](items: *list[A]*) → *list[T]*\n\nProcess a list of processable items\n\n    Args:\n        items: List of items implementing Processable protocol\n\n    Returns:\n        List of processed results\n\n    Examples:\n        >>> d1 = Data(\"hello\", \"test\")\n        >>> d2 = Data(\"world\", \"test2\")\n        >>> results = process_items([d1, d2])\n        >>> results\n        [\"HELLO\", \"WORLD\"]\n    \n\n\n## `gt`[A(__builtin__.Minus,__builtin__.Plus),B(__builtin__.Plus)](a: *A*, b: *A*, c: *B*, d: *B*) → *(A, A, B)*\n\nFunction that takes generic types"
  },
  {
    "path": "compiler/lib/test/doc-golden/bar.txt",
    "content": "bar - Bar module - defines shared types and utilities\n\nThis module provides common data structures and utilities\nthat are used across the application.\n\n\n\nclass Data(object)\n  A data container with metadata\n\n    This class holds arbitrary data along with metadata\n    about when it was created and last modified.\n\n    Examples:\n        >>> d = Data(\"hello\", \"test-data\")\n        >>> d.get_value()\n        \"hello\"\n    \n\n  Attributes:\n    value: str\n    label: str\n    count: int\n\n  Methods:\n    __init__(self, value: str, label: str)\n      Initialize data with value and label\n\n        Args:\n            value: The data value\n            label: A descriptive label\n        \n    get_value(self) -> str\n      Get the stored value\n\n        Returns:\n            The data value\n        \n    update(self, new_value: str)\n      Update the value\n\n        Args:\n            new_value: New value to store\n\n        Note:\n            This increments the access count\n        \n    get_info(self) -> str\n      Get formatted information about this data\n\n        Returns:\n            A string with label, value, and count\n        \n\nclass Container[T](object)\n  A generic container that can hold items of any type\n\n    This container maintains a list of items with various\n    operations for manipulation and querying.\n\n    Type Args:\n        T: The type of items stored in the container\n    \n\n  Attributes:\n    items: list[T]\n    name: str\n\n  Methods:\n    __init__(self, name: str)\n      Create an empty container\n\n        Args:\n            name: Container name for identification\n        \n    add(self, item: T)\n      Add an item to the container\n\n        Args:\n            item: Item to add\n\n        Raises:\n            ValueError: If container is full\n        \n    get_all(self) -> list[T]\n      Get all items\n\n        Returns:\n            List of all items in the container\n        \n    filter[U](self, predicate: (T) -> bool, transform: (T) -> U) -> list[U]\n      Filter and transform items\n\n        Args:\n            predicate: Function to test each item\n            transform: Function to transform matching items\n\n        Returns:\n            List of transformed items that match predicate\n\n        Examples:\n            >>> c = Container[int](\"numbers\")\n            >>> c.add(1)\n            >>> c.add(2)\n            >>> c.filter(lambda x: x > 1, lambda x: str(x))\n            [\"2\"]\n        \n    count(self) -> int\n      Get number of items in container\n\n        Returns:\n            Number of items\n        \n\nprocess_data(d: bar.Data) -> str\n  Process a data object and return summary\n\n    Args:\n        d: Data object to process\n\n    Returns:\n        Processed summary string\n\n    See Also:\n        Data.get_info: For detailed information\n    \n\ncombine_data(d1: bar.Data, d2: bar.Data) -> bar.Data\n  Combine two data objects\n\n    Args:\n        d1: First data object\n        d2: Second data object\n\n    Returns:\n        New Data object with combined values\n    \n\nactor DataProcessor()\n  Actor that processes Data objects\n\n    This actor maintains a queue of data objects\n    and processes them asynchronously.\n    \n\nsum_counts[T](items: list[T]) -> T\n  Sum a list of items that support addition\n\n    Args:\n        items: List of summable items\n\n    Returns:\n        Sum of all items\n\n    Raises:\n        ValueError: If list is empty\n    \n\nprotocol Processable[T]\n  Protocol for objects that can be processed\n\n    This protocol defines the interface for objects that\n    can be processed and transformed into a result of type T.\n\n    Type Args:\n        T: The type of the processing result\n    \n\n  Methods:\n    process: T\n    validate: bool\n    get_metadata: dict[str,str]\n\nextension Data(Processable[str])\n  Makes Data implement the Processable protocol\n\n    This extension allows Data objects to be processed\n    according to the Processable protocol, returning\n    string results.\n    \n\nprocess_items[T](items: list[A]) -> list[T]\n  Process a list of processable items\n\n    Args:\n        items: List of items implementing Processable protocol\n\n    Returns:\n        List of processed results\n\n    Examples:\n        >>> d1 = Data(\"hello\", \"test\")\n        >>> d2 = Data(\"world\", \"test2\")\n        >>> results = process_items([d1, d2])\n        >>> results\n        [\"HELLO\", \"WORLD\"]\n    \n\ngt(a: A, b: A, c: B, d: B) -> (A, A, B)\n  Function that takes generic types\n"
  },
  {
    "path": "compiler/lib/test/doc-golden/foo-color.txt",
    "content": "\u001b[1mfoo\u001b[0m - Foo module - demonstrates cross-module type usage\n\nThis module extensively uses types from the bar module\nto demonstrate documentation of cross-module references.\n\n\n\n\u001b[1mcreate_data\u001b[0m(value: \u001b[32mstr\u001b[0m) -> \u001b[32mbar.Data\u001b[0m\n  Create a new Data instance\n\n    Args:\n        value: Value for the data\n\n    Returns:\n        A new bar.Data instance with auto-generated label\n\n    Examples:\n        >>> d = create_data(\"test\")\n        >>> d.get_value()\n        \"test\"\n    \n\n\u001b[1mtransform_data\u001b[0m(d: \u001b[32mbar.Data\u001b[0m, f: \u001b[32m(str) -> str\u001b[0m) -> \u001b[32mbar.Data\u001b[0m\n  Transform data by applying function to its value\n\n    Args:\n        d: Data object to transform\n        f: Transformation function\n\n    Returns:\n        New bar.Data with transformed value\n\n    See Also:\n        bar.process_data: For simple processing\n        bar.combine_data: For combining multiple data objects\n    \n\n\u001b[1manalyze_multiple\u001b[0m(data_list: \u001b[32mlist[bar.Data]\u001b[0m) -> \u001b[32mdict[str, int]\u001b[0m\n  Analyze multiple data objects\n\n    Args:\n        data_list: List of bar.Data objects\n\n    Returns:\n        Statistics about the data\n\n    Raises:\n        ValueError: If list is empty\n    \n\n\u001b[36mclass\u001b[0m \u001b[1mDataManager\u001b[0m(object)\n  Manages a collection of bar.Data objects\n\n    This class provides high-level operations on collections\n    of Data objects from the bar module.\n    \n\n  \u001b[33mAttributes:\u001b[0m\n    storage: list[bar.Data]\n    default: bar.Data\n    name: str\n\n  \u001b[33mMethods:\u001b[0m\n    \u001b[1m__init__\u001b[0m(self, name: \u001b[32mstr\u001b[0m)\n      Initialize manager\n\n        Args:\n            name: Name for this manager\n        \n    \u001b[1madd_data\u001b[0m(self, d: \u001b[32mbar.Data\u001b[0m)\n      Add a data object to storage\n\n        Args:\n            d: bar.Data object to add\n\n        Raises:\n            ValueError: If storage is full\n        \n    \u001b[1mfind_by_label\u001b[0m(self, label: \u001b[32mstr\u001b[0m) -> \u001b[32m?bar.Data\u001b[0m\n      Find first data with matching label\n\n        Args:\n            label: Label to search for\n\n        Returns:\n            Matching bar.Data or None if not found\n        \n    \u001b[1mget_or_default\u001b[0m(self, label: \u001b[32mstr\u001b[0m) -> \u001b[32mbar.Data\u001b[0m\n      Get data by label or return default\n\n        Args:\n            label: Label to search for\n\n        Returns:\n            Found bar.Data or the default instance\n        \n    \u001b[1mtransform_all\u001b[0m(self, f: \u001b[32m(bar.Data) -> bar.Data\u001b[0m) -> \u001b[32mlist[bar.Data]\u001b[0m\n      Transform all stored data\n\n        Args:\n            f: Transformation function\n\n        Returns:\n            List of transformed bar.Data objects\n        \n\n\u001b[1mprocess_with_prefix\u001b[0m(d: \u001b[32mbar.Data\u001b[0m, prefix: \u001b[32mstr\u001b[0m) -> \u001b[32mbar.Data\u001b[0m\n  Process data with a prefix\n\n    Args:\n        d: Data to process\n        prefix: Prefix to add to data values\n\n    Returns:\n        New bar.Data with prefixed value\n    \n\n\u001b[36mactor\u001b[0m \u001b[1mDataHandler\u001b[0m(initial: \u001b[32mbar.Data\u001b[0m)\n  Actor that handles bar.Data objects\n\n    Args:\n        initial: Initial bar.Data to store\n    \n\n\u001b[1mapply_transformation\u001b[0m(d: \u001b[32mbar.Data\u001b[0m, transform: \u001b[32m(str) -> str\u001b[0m) -> \u001b[32mbar.Data\u001b[0m\n  Apply transformation to bar.Data value\n\n    Args:\n        d: Data to transform\n        transform: Function to apply to value\n\n    Returns:\n        New bar.Data with transformed value\n    \n\n\u001b[1mapply_to_list\u001b[0m(items: \u001b[32mlist[bar.Data]\u001b[0m, f: \u001b[32m(bar.Data) -> str\u001b[0m) -> \u001b[32mlist[str]\u001b[0m\n  Apply function to all items in list\n\n    Args:\n        items: List of bar.Data objects\n        f: Function to apply\n\n    Returns:\n        List of results\n    \n\n\u001b[1mprocess_nested\u001b[0m(data: \u001b[32mlist[(str, bar.Data)]\u001b[0m) -> \u001b[32mdict[str, list[bar.Data]]\u001b[0m\n  Process nested data structures\n\n    Args:\n        data: List of tuples containing keys and bar.Data\n\n    Returns:\n        Dictionary grouping bar.Data by key\n    \n\n\u001b[36mactor\u001b[0m \u001b[1mmain\u001b[0m(env: \u001b[32mEnv\u001b[0m)\n  Main actor demonstrating bar module usage\n"
  },
  {
    "path": "compiler/lib/test/doc-golden/foo.html",
    "content": "<!DOCTYPE html>\n<html lang=\"en\">\n<head>\n  <meta charset=\"UTF-8\">\n  <meta name=\"viewport\" content=\"width=device-width, initial-scale=1.0\">\n  <title>foo</title>\n  <style>\n    /* Light theme colors (default) */\n    :root {\n      --text-primary: #24292e;\n      --text-secondary: #6a737d;\n      --text-link: #0366d6;\n      --bg-primary: #ffffff;\n      --bg-secondary: #f6f8fa;\n      --border: #e1e4e8;\n      --code-bg: #f6f8fa;\n      --type-color: #6f42c1;\n      --keyword-color: #d73a49;\n      --generic-color: #e36209;\n      --generic-hover: #fb8532;\n      --shadow: rgba(27, 31, 35, 0.04);\n      --shadow-medium: rgba(27, 31, 35, 0.12);\n    }\n    \n    /* Dark theme colors (activated by OS preference) */\n    @media (prefers-color-scheme: dark) {\n      :root {\n        --text-primary: #c9d1d9;\n        --text-secondary: #8b949e;\n        --text-link: #58a6ff;\n        --bg-primary: #0d1117;\n        --bg-secondary: #161b22;\n        --border: #30363d;\n        --code-bg: #161b22;\n        --type-color: #d2a8ff;\n        --keyword-color: #ff7b72;\n        --generic-color: #ffa657;\n        --generic-hover: #ffb77c;\n        --shadow: rgba(0, 0, 0, 0.3);\n        --shadow-medium: rgba(0, 0, 0, 0.5);\n      }\n    }\n    \n    * { box-sizing: border-box; }\n    \n    body {\n      font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Helvetica, Arial, sans-serif;\n      font-size: 16px;\n      line-height: 1.5;\n      color: var(--text-primary);\n      background: var(--bg-primary);\n      margin: 0;\n      padding: 0;\n    }\n    \n    .container {\n      max-width: 960px;\n      margin: 0 auto;\n      padding: 2rem;\n    }\n    \n    /* Typography */\n    h1 {\n      font-size: 2rem;\n      font-weight: 600;\n      margin: 0 0 1rem 0;\n      padding-bottom: 0.3rem;\n      border-bottom: 1px solid var(--border);\n    }\n    \n    h2 {\n      font-size: 1.25rem;\n      font-weight: 600;\n      margin: 2.5rem 0 1rem 0;\n    }\n    \n    h3 {\n      font-size: 1rem;\n      font-weight: 600;\n      color: var(--text-secondary);\n      margin: 1.5rem 0 0.5rem 0;\n      text-transform: uppercase;\n      letter-spacing: 0.02em;\n    }\n    \n    /* Indent ATTRIBUTES/METHODS headers under classes/actors */\n    .declaration-block h3 {\n      margin-left: 2rem;\n    }\n    \n    p {\n      margin: 0 0 1rem 0;\n    }\n    \n    /* Code */\n    code {\n      font-family: 'SF Mono', Monaco, Consolas, 'Liberation Mono', 'Courier New', monospace;\n      font-size: 0.875em;\n      background: var(--code-bg);\n      padding: 0.2em 0.4em;\n      border-radius: 3px;\n      border: 1px solid var(--border);\n    }\n    \n    h2 code {\n      background: none;\n      padding: 0;\n      font-size: 1em;\n      border: none;\n    }\n    \n    /* Type coloring */\n    .type {\n      color: var(--type-color);\n    }\n    \n    /* Type links */\n    .type-link {\n      color: var(--type-color);\n      text-decoration: none;\n      border-bottom: 1px dotted var(--type-color);\n    }\n    \n    .type-link:hover {\n      text-decoration: none;\n      border-bottom: 1px solid var(--type-color);\n    }\n    \n    .keyword {\n      color: var(--keyword-color);\n      font-weight: 500;\n      font-size: 1rem;\n    }\n    \n    .param-name {\n      font-weight: 500;\n    }\n    \n    .default-value {\n      color: var(--text-secondary);\n    }\n    \n    /* Generic type parameters */\n    .generic-type {\n      color: var(--generic-color);\n      cursor: pointer;\n      transition: color 0.2s ease;\n      position: relative;\n      display: inline-block;\n    }\n    \n    .generic-type:hover,\n    .generic-type.highlight {\n      color: var(--generic-hover);\n      text-decoration: underline;\n      text-decoration-style: dotted;\n    }\n    \n    /* Tooltip for generic types - default position below */\n    .generic-type[data-tooltip]:hover::after {\n      content: attr(data-tooltip);\n      display: block;\n      position: absolute;\n      top: 100%;\n      left: 50%;\n      transform: translateX(-50%);\n      margin-top: 5px;\n      padding: 8px 12px;\n      background-color: rgba(0, 0, 0, 0.8);\n      color: white;\n      font-size: 0.75rem;\n      font-weight: normal;\n      white-space: pre-wrap;\n      max-width: 700px;\n      min-width: 200px;\n      text-align: left;\n      border-radius: 4px;\n      pointer-events: none;\n      opacity: 0;\n      animation: fadeIn 0.2s ease-in-out forwards;\n      z-index: 1000;\n    }\n    \n    /* Tooltip positioned above when not near top */\n    .generic-type[data-tooltip]:not(.tooltip-below):hover::after {\n      top: auto;\n      bottom: 100%;\n      margin-top: 0;\n      margin-bottom: 5px;\n    }\n    \n    @keyframes fadeIn {\n      from { opacity: 0; }\n      to { opacity: 1; }\n    }\n    \n    /* Documentation strings */\n    .docstring {\n      color: var(--text-secondary);\n      margin: 0.5rem 0 1.5rem 0;\n      padding-left: 1rem;\n    }\n    \n    .module-doc {\n      margin: 1rem 0 2rem 0;\n      color: var(--text-primary);\n      font-size: 1.1rem;\n      line-height: 1.6;\n    }\n    \n    /* Sections */\n    .section {\n      margin: 1.5rem 0;\n      padding-left: 2rem;\n    }\n    \n    /* Lists */\n    ul {\n      list-style: none;\n      padding: 0;\n      margin: 0;\n    }\n    \n    li {\n      margin: 0.5rem 0;\n    }\n    \n    /* Attribute items */\n    .attribute-item {\n      margin: 0.5rem 0;\n      padding-left: 1rem;\n      border-left: 3px solid var(--border);\n    }\n    \n    .attribute-item code {\n      background: none;\n      padding: 0;\n      border: none;\n    }\n    \n    /* Method items */\n    .method-item {\n      margin: 1rem 0;\n    }\n    \n    .method-signature {\n      font-family: 'SF Mono', Monaco, Consolas, monospace;\n      font-size: 0.875rem;\n      padding-left: 1rem;\n      border-left: 3px solid var(--border);\n    }\n    \n    .method-signature code {\n      background: none;\n      padding: 0;\n      border: none;\n    }\n    \n    .method-doc {\n      color: var(--text-secondary);\n      margin: 0.25rem 0 0 1.5rem;\n      font-size: 0.875rem;\n    }\n    \n    /* Attributes and methods sections */\n    .attributes, .methods {\n      margin: 1.5rem 0 1.5rem 2rem;\n    }\n    \n    /* Declaration blocks - no visual boxes, just spacing */\n    .declaration-block {\n      margin: 2rem 0;\n    }\n    \n    /* Module index styles */\n    .module-list {\n      list-style: none;\n      padding: 0;\n      margin: 0;\n    }\n    \n    .module-item {\n      margin: 0.5rem 0;\n      padding: 0.75rem 1rem;\n      background: var(--bg-secondary);\n      border-radius: 6px;\n      border: 1px solid var(--border);\n      transition: all 0.2s ease;\n    }\n    \n    .module-item:hover {\n      border-color: var(--text-link);\n      transform: translateY(-1px);\n    }\n    \n    .module-link {\n      text-decoration: none;\n      color: var(--text-link);\n      font-weight: 500;\n      display: block;\n    }\n    \n    .module-path {\n      font-family: 'SF Mono', Monaco, Consolas, monospace;\n      font-size: 0.875rem;\n    }\n    \n    .module-doc {\n      color: var(--text-secondary);\n      font-size: 0.875rem;\n      margin-top: 0.25rem;\n    }\n    \n    /* Smooth transitions for theme changes */\n    * {\n      transition: background-color 0.3s ease, color 0.3s ease, border-color 0.3s ease;\n    }\n    \n    /* Responsive */\n    @media (max-width: 768px) {\n      .container {\n        padding: 1rem;\n      }\n      h1 {\n        font-size: 1.75rem;\n      }\n      h2 {\n        font-size: 1.25rem;\n      }\n    }\n\n  </style>\n  <script>\n    document.addEventListener('DOMContentLoaded', function() {\n      const genericTypes = document.querySelectorAll('.generic-type');\n      \n      genericTypes.forEach(function(elem) {\n        elem.addEventListener('mouseenter', function() {\n          const typeName = elem.getAttribute('data-generic');\n          \n          // Check if tooltip would go off-screen at the top\n          const rect = elem.getBoundingClientRect();\n          const tooltipHeight = 200; // Approximate height\n          if (rect.top < tooltipHeight) {\n            elem.classList.add('tooltip-below');\n          } else {\n            elem.classList.remove('tooltip-below');\n          }\n          \n          // Get the scope attribute - all generic types should have this\n          const scope = elem.getAttribute('data-scope');\n          \n          // Only highlight elements with same type name AND same scope\n          document.querySelectorAll('.generic-type[data-generic=\"' + typeName + '\"][data-scope=\"' + scope + '\"]').forEach(function(t) {\n            t.classList.add('highlight');\n          });\n        });\n        \n        elem.addEventListener('mouseleave', function() {\n          const typeName = elem.getAttribute('data-generic');\n          document.querySelectorAll('.generic-type[data-generic=\"' + typeName + '\"].highlight').forEach(function(t) {\n            t.classList.remove('highlight');\n          });\n        });\n      });\n    });\n\n  </script>\n</head>\n<body>\n  <div class=\"container\">\n<h1>foo - Foo module - demonstrates cross-module type usage</h1>\n<div class=\"module-doc\">This module extensively uses types from the bar module<br>to demonstrate documentation of cross-module references.</div>\n<h2 class=\"type-context\"><code>create_data</code>(<span class=\"param-name\">value</span>: <span class=\"type\">str</span>) → <span class=\"type\"><a href=\"bar.html#class-Data\" class=\"type-link\">bar.Data</a></span></h2>\n<div class=\"docstring\">Create a new Data instance<br><br>    Args:<br>        value: Value for the data<br><br>    Returns:<br>        A new bar.Data instance with auto-generated label<br><br>    Examples:<br>        &gt;&gt;&gt; d = create_data(&quot;test&quot;)<br>        &gt;&gt;&gt; d.get_value()<br>        &quot;test&quot;<br>    </div>\n\n<h2 class=\"type-context\"><code>transform_data</code>(<span class=\"param-name\">d</span>: <span class=\"type\"><a href=\"bar.html#class-Data\" class=\"type-link\">bar.Data</a></span>, <span class=\"param-name\">f</span>: <span class=\"type\">(str) -> str</span>) → <span class=\"type\"><a href=\"bar.html#class-Data\" class=\"type-link\">bar.Data</a></span></h2>\n<div class=\"docstring\">Transform data by applying function to its value<br><br>    Args:<br>        d: Data object to transform<br>        f: Transformation function<br><br>    Returns:<br>        New bar.Data with transformed value<br><br>    See Also:<br>        bar.process_data: For simple processing<br>        bar.combine_data: For combining multiple data objects<br>    </div>\n\n<h2 class=\"type-context\"><code>analyze_multiple</code>(<span class=\"param-name\">data_list</span>: <span class=\"type\">[<a href=\"bar.html#class-Data\" class=\"type-link\">bar.Data</a>]</span>) → <span class=\"type\">{str: int}</span></h2>\n<div class=\"docstring\">Analyze multiple data objects<br><br>    Args:<br>        data_list: List of bar.Data objects<br><br>    Returns:<br>        Statistics about the data<br><br>    Raises:<br>        ValueError: If list is empty<br>    </div>\n\n<div class=\"declaration-block\">\n<h2 id=\"class-DataManager\" class=\"type-context\"><span class=\"keyword\">class</span> <code>DataManager</code>(<span class=\"type\">object</span>)</h2>\n<div class=\"docstring\">Manages a collection of bar.Data objects<br><br>    This class provides high-level operations on collections<br>    of Data objects from the bar module.<br>    </div>\n\n<h3>Attributes</h3>\n<div class=\"attributes\">\n<div class=\"attribute-item\"><code>storage</code>: <span class=\"type\">list[<a href=\"bar.html#class-Data\" class=\"type-link\">bar.Data</a>]</span></div>\n<div class=\"attribute-item\"><code>default</code>: <span class=\"type\"><a href=\"bar.html#class-Data\" class=\"type-link\">bar.Data</a></span></div>\n<div class=\"attribute-item\"><code>name</code>: <span class=\"type\">str</span></div>\n</div>\n\n<h3>Methods</h3>\n<div class=\"methods\">\n<div class=\"method-item\">\n<div class=\"method-signature\"><code>__init__</code>(<span class=\"param-name\">self</span>, <span class=\"param-name\">name</span>: <span class=\"type\">str</span>)</div>\n<div class=\"method-doc\">Initialize manager<br><br>        Args:<br>            name: Name for this manager<br>        </div>\n</div>\n<div class=\"method-item\">\n<div class=\"method-signature\"><code>add_data</code>(<span class=\"param-name\">self</span>, <span class=\"param-name\">d</span>: <span class=\"type\"><a href=\"bar.html#class-Data\" class=\"type-link\">bar.Data</a></span>)</div>\n<div class=\"method-doc\">Add a data object to storage<br><br>        Args:<br>            d: bar.Data object to add<br><br>        Raises:<br>            ValueError: If storage is full<br>        </div>\n</div>\n<div class=\"method-item\">\n<div class=\"method-signature\"><code>find_by_label</code>(<span class=\"param-name\">self</span>, <span class=\"param-name\">label</span>: <span class=\"type\">str</span>) → <span class=\"type\">?<a href=\"bar.html#class-Data\" class=\"type-link\">bar.Data</a></span></div>\n<div class=\"method-doc\">Find first data with matching label<br><br>        Args:<br>            label: Label to search for<br><br>        Returns:<br>            Matching bar.Data or None if not found<br>        </div>\n</div>\n<div class=\"method-item\">\n<div class=\"method-signature\"><code>get_or_default</code>(<span class=\"param-name\">self</span>, <span class=\"param-name\">label</span>: <span class=\"type\">str</span>) → <span class=\"type\"><a href=\"bar.html#class-Data\" class=\"type-link\">bar.Data</a></span></div>\n<div class=\"method-doc\">Get data by label or return default<br><br>        Args:<br>            label: Label to search for<br><br>        Returns:<br>            Found bar.Data or the default instance<br>        </div>\n</div>\n<div class=\"method-item\">\n<div class=\"method-signature\"><code>transform_all</code>(<span class=\"param-name\">self</span>, <span class=\"param-name\">f</span>: <span class=\"type\">(<a href=\"bar.html#class-Data\" class=\"type-link\">bar.Data</a>) -> <a href=\"bar.html#class-Data\" class=\"type-link\">bar.Data</a></span>) → <span class=\"type\">list[<a href=\"bar.html#class-Data\" class=\"type-link\">bar.Data</a>]</span></div>\n<div class=\"method-doc\">Transform all stored data<br><br>        Args:<br>            f: Transformation function<br><br>        Returns:<br>            List of transformed bar.Data objects<br>        </div>\n</div>\n</div>\n</div>\n\n<h2 class=\"type-context\"><code>process_with_prefix</code>(<span class=\"param-name\">d</span>: <span class=\"type\"><a href=\"bar.html#class-Data\" class=\"type-link\">bar.Data</a></span>, <span class=\"param-name\">prefix</span>: <span class=\"type\">str</span>) → <span class=\"type\"><a href=\"bar.html#class-Data\" class=\"type-link\">bar.Data</a></span></h2>\n<div class=\"docstring\">Process data with a prefix<br><br>    Args:<br>        d: Data to process<br>        prefix: Prefix to add to data values<br><br>    Returns:<br>        New bar.Data with prefixed value<br>    </div>\n\n<div class=\"declaration-block\">\n<h2 class=\"type-context\"><span class=\"keyword\">actor</span> <code>DataHandler</code>(<span class=\"param-name\">initial</span>: <span class=\"type\"><a href=\"bar.html#class-Data\" class=\"type-link\">bar.Data</a></span>)</h2>\n<div class=\"docstring\">Actor that handles bar.Data objects<br><br>    Args:<br>        initial: Initial bar.Data to store<br>    </div>\n\n<h3>Internal Attributes</h3>\n<div class=\"attributes\">\n<div class=\"attribute-item\"><code>current</code>: <span class=\"type\"><a href=\"bar.html#class-Data\" class=\"type-link\">bar.Data</a></span></div>\n<div class=\"attribute-item\"><code>history</code>: <span class=\"type\">list[<a href=\"bar.html#class-Data\" class=\"type-link\">bar.Data</a>]</span></div>\n<div class=\"attribute-item\"><code>processor</code>: <span class=\"type\">?<a href=\"bar.html#class-DataProcessor\" class=\"type-link\">bar.DataProcessor</a></span></div>\n</div>\n<h3>Methods</h3>\n<div class=\"methods\">\n<div class=\"method-item\">\n<div class=\"method-signature\"><code>update</code>(<span class=\"param-name\">new_data</span>: <span class=\"type\"><a href=\"bar.html#class-Data\" class=\"type-link\">bar.Data</a></span>)</div>\n<div class=\"method-doc\">Update current data<br><br>        Args:<br>            new_data: New bar.Data to set as current<br>        </div>\n</div>\n<div class=\"method-item\">\n<div class=\"method-signature\"><code>get_current</code>() → <span class=\"type\"><a href=\"bar.html#class-Data\" class=\"type-link\">bar.Data</a></span></div>\n<div class=\"method-doc\">Get current data<br><br>        Returns:<br>            Current bar.Data instance<br>        </div>\n</div>\n<div class=\"method-item\">\n<div class=\"method-signature\"><code>transform_with</code>(<span class=\"param-name\">f</span>: <span class=\"type\">(<a href=\"bar.html#class-Data\" class=\"type-link\">bar.Data</a>) -> <a href=\"bar.html#class-Data\" class=\"type-link\">bar.Data</a></span>) → <span class=\"type\"><a href=\"bar.html#class-Data\" class=\"type-link\">bar.Data</a></span></div>\n<div class=\"method-doc\">Transform current data<br><br>        Args:<br>            f: Transformation function<br><br>        Returns:<br>            Transformed bar.Data<br>        </div>\n</div>\n<div class=\"method-item\">\n<div class=\"method-signature\"><code>combine_with</code>(<span class=\"param-name\">other</span>: <span class=\"type\"><a href=\"bar.html#class-Data\" class=\"type-link\">bar.Data</a></span>) → <span class=\"type\"><a href=\"bar.html#class-Data\" class=\"type-link\">bar.Data</a></span></div>\n<div class=\"method-doc\">Combine current with another data<br><br>        Args:<br>            other: bar.Data to combine with<br><br>        Returns:<br>            Combined bar.Data using bar.combine_data<br>        </div>\n</div>\n<div class=\"method-item\">\n<div class=\"method-signature\"><code>send_to_processor</code>(<span class=\"param-name\">p</span>: <span class=\"type\"><a href=\"bar.html#class-DataProcessor\" class=\"type-link\">bar.DataProcessor</a></span>)</div>\n<div class=\"method-doc\">Send current data to a processor<br><br>        Args:<br>            p: bar.DataProcessor to send to<br>        </div>\n</div>\n<div class=\"method-item\">\n<div class=\"method-signature\"><code>get_history</code>() → <span class=\"type\">list[<a href=\"bar.html#class-Data\" class=\"type-link\">bar.Data</a>]</span></div>\n<div class=\"method-doc\">Get full history of data<br><br>        Returns:<br>            List of all bar.Data objects in history<br>        </div>\n</div>\n</div>\n</div>\n\n<h2 class=\"type-context\"><code>apply_transformation</code>(<span class=\"param-name\">d</span>: <span class=\"type\"><a href=\"bar.html#class-Data\" class=\"type-link\">bar.Data</a></span>, <span class=\"param-name\">transform</span>: <span class=\"type\">(str) -> str</span>) → <span class=\"type\"><a href=\"bar.html#class-Data\" class=\"type-link\">bar.Data</a></span></h2>\n<div class=\"docstring\">Apply transformation to bar.Data value<br><br>    Args:<br>        d: Data to transform<br>        transform: Function to apply to value<br><br>    Returns:<br>        New bar.Data with transformed value<br>    </div>\n\n<h2 class=\"type-context\"><code>apply_to_list</code>(<span class=\"param-name\">items</span>: <span class=\"type\">[<a href=\"bar.html#class-Data\" class=\"type-link\">bar.Data</a>]</span>, <span class=\"param-name\">f</span>: <span class=\"type\">(<a href=\"bar.html#class-Data\" class=\"type-link\">bar.Data</a>) -> str</span>) → <span class=\"type\">[str]</span></h2>\n<div class=\"docstring\">Apply function to all items in list<br><br>    Args:<br>        items: List of bar.Data objects<br>        f: Function to apply<br><br>    Returns:<br>        List of results<br>    </div>\n\n<h2 class=\"type-context\"><code>process_nested</code>(<span class=\"param-name\">data</span>: <span class=\"type\">[(str, <a href=\"bar.html#class-Data\" class=\"type-link\">bar.Data</a>)]</span>) → <span class=\"type\">{str: [<a href=\"bar.html#class-Data\" class=\"type-link\">bar.Data</a>]}</span></h2>\n<div class=\"docstring\">Process nested data structures<br><br>    Args:<br>        data: List of tuples containing keys and bar.Data<br><br>    Returns:<br>        Dictionary grouping bar.Data by key<br>    </div>\n\n<div class=\"declaration-block\">\n<h2 class=\"type-context\"><span class=\"keyword\">actor</span> <code>main</code>(<span class=\"param-name\">env</span>: <span class=\"type\">Env</span>)</h2>\n<div class=\"docstring\">Main actor demonstrating bar module usage</div>\n\n<h3>Public Constants</h3>\n<div class=\"attributes\">\n<div class=\"attribute-item\"><code>d1</code></div>\n<div class=\"attribute-item\"><code>d2</code></div>\n<div class=\"attribute-item\"><code>d3</code></div>\n<div class=\"attribute-item\"><code>data_list</code></div>\n<div class=\"attribute-item\"><code>long_values</code></div>\n<div class=\"attribute-item\"><code>manager</code></div>\n<div class=\"attribute-item\"><code>found</code></div>\n<div class=\"attribute-item\"><code>handler</code></div>\n<div class=\"attribute-item\"><code>processor</code></div>\n<div class=\"attribute-item\"><code>processed</code></div>\n<div class=\"attribute-item\"><code>transformed</code></div>\n<div class=\"attribute-item\"><code>items</code></div>\n<div class=\"attribute-item\"><code>grouped</code></div>\n<div class=\"attribute-item\"><code>processed_results</code></div>\n<div class=\"attribute-item\"><code>meta</code></div>\n</div>\n</div>\n  </div>\n</body>\n</html>\n"
  },
  {
    "path": "compiler/lib/test/doc-golden/foo.md",
    "content": "# `foo`: Foo module - demonstrates cross-module type usage\n\nThis module extensively uses types from the bar module\nto demonstrate documentation of cross-module references.\n\n\n\n## `create_data`(value: *str*) → *bar.Data*\n\nCreate a new Data instance\n\n    Args:\n        value: Value for the data\n\n    Returns:\n        A new bar.Data instance with auto-generated label\n\n    Examples:\n        >>> d = create_data(\"test\")\n        >>> d.get_value()\n        \"test\"\n    \n\n\n## `transform_data`(d: *bar.Data*, f: *(str) -> str*) → *bar.Data*\n\nTransform data by applying function to its value\n\n    Args:\n        d: Data object to transform\n        f: Transformation function\n\n    Returns:\n        New bar.Data with transformed value\n\n    See Also:\n        bar.process_data: For simple processing\n        bar.combine_data: For combining multiple data objects\n    \n\n\n## `analyze_multiple`(data_list: *list[bar.Data]*) → *dict[str, int]*\n\nAnalyze multiple data objects\n\n    Args:\n        data_list: List of bar.Data objects\n\n    Returns:\n        Statistics about the data\n\n    Raises:\n        ValueError: If list is empty\n    \n\n\n## *class* `DataManager`(object)\n\nManages a collection of bar.Data objects\n\n    This class provides high-level operations on collections\n    of Data objects from the bar module.\n    \n\n**Attributes:**\n\n- `storage`: *list[bar.Data]*\n- `default`: *bar.Data*\n- `name`: *str*\n\n**Methods:**\n\n- `__init__`(self, name: *str*)\n\n  Initialize manager\n\n        Args:\n            name: Name for this manager\n        \n- `add_data`(self, d: *bar.Data*)\n\n  Add a data object to storage\n\n        Args:\n            d: bar.Data object to add\n\n        Raises:\n            ValueError: If storage is full\n        \n- `find_by_label`(self, label: *str*) → *?bar.Data*\n\n  Find first data with matching label\n\n        Args:\n            label: Label to search for\n\n        Returns:\n            Matching bar.Data or None if not found\n        \n- `get_or_default`(self, label: *str*) → *bar.Data*\n\n  Get data by label or return default\n\n        Args:\n            label: Label to search for\n\n        Returns:\n            Found bar.Data or the default instance\n        \n- `transform_all`(self, f: *(bar.Data) -> bar.Data*) → *list[bar.Data]*\n\n  Transform all stored data\n\n        Args:\n            f: Transformation function\n\n        Returns:\n            List of transformed bar.Data objects\n        \n\n\n## `process_with_prefix`(d: *bar.Data*, prefix: *str*) → *bar.Data*\n\nProcess data with a prefix\n\n    Args:\n        d: Data to process\n        prefix: Prefix to add to data values\n\n    Returns:\n        New bar.Data with prefixed value\n    \n\n\n## *actor* `DataHandler`(initial: *bar.Data*)\n\nActor that handles bar.Data objects\n\n    Args:\n        initial: Initial bar.Data to store\n    \n\n\n## `apply_transformation`(d: *bar.Data*, transform: *(str) -> str*) → *bar.Data*\n\nApply transformation to bar.Data value\n\n    Args:\n        d: Data to transform\n        transform: Function to apply to value\n\n    Returns:\n        New bar.Data with transformed value\n    \n\n\n## `apply_to_list`(items: *list[bar.Data]*, f: *(bar.Data) -> str*) → *list[str]*\n\nApply function to all items in list\n\n    Args:\n        items: List of bar.Data objects\n        f: Function to apply\n\n    Returns:\n        List of results\n    \n\n\n## `process_nested`(data: *list[(str, bar.Data)]*) → *dict[str, list[bar.Data]]*\n\nProcess nested data structures\n\n    Args:\n        data: List of tuples containing keys and bar.Data\n\n    Returns:\n        Dictionary grouping bar.Data by key\n    \n\n\n## *actor* `main`(env)\n\nMain actor demonstrating bar module usage"
  },
  {
    "path": "compiler/lib/test/doc-golden/foo.txt",
    "content": "foo - Foo module - demonstrates cross-module type usage\n\nThis module extensively uses types from the bar module\nto demonstrate documentation of cross-module references.\n\n\n\ncreate_data(value: str) -> bar.Data\n  Create a new Data instance\n\n    Args:\n        value: Value for the data\n\n    Returns:\n        A new bar.Data instance with auto-generated label\n\n    Examples:\n        >>> d = create_data(\"test\")\n        >>> d.get_value()\n        \"test\"\n    \n\ntransform_data(d: bar.Data, f: (str) -> str) -> bar.Data\n  Transform data by applying function to its value\n\n    Args:\n        d: Data object to transform\n        f: Transformation function\n\n    Returns:\n        New bar.Data with transformed value\n\n    See Also:\n        bar.process_data: For simple processing\n        bar.combine_data: For combining multiple data objects\n    \n\nanalyze_multiple(data_list: list[bar.Data]) -> dict[str, int]\n  Analyze multiple data objects\n\n    Args:\n        data_list: List of bar.Data objects\n\n    Returns:\n        Statistics about the data\n\n    Raises:\n        ValueError: If list is empty\n    \n\nclass DataManager(object)\n  Manages a collection of bar.Data objects\n\n    This class provides high-level operations on collections\n    of Data objects from the bar module.\n    \n\n  Attributes:\n    storage: list[bar.Data]\n    default: bar.Data\n    name: str\n\n  Methods:\n    __init__(self, name: str)\n      Initialize manager\n\n        Args:\n            name: Name for this manager\n        \n    add_data(self, d: bar.Data)\n      Add a data object to storage\n\n        Args:\n            d: bar.Data object to add\n\n        Raises:\n            ValueError: If storage is full\n        \n    find_by_label(self, label: str) -> ?bar.Data\n      Find first data with matching label\n\n        Args:\n            label: Label to search for\n\n        Returns:\n            Matching bar.Data or None if not found\n        \n    get_or_default(self, label: str) -> bar.Data\n      Get data by label or return default\n\n        Args:\n            label: Label to search for\n\n        Returns:\n            Found bar.Data or the default instance\n        \n    transform_all(self, f: (bar.Data) -> bar.Data) -> list[bar.Data]\n      Transform all stored data\n\n        Args:\n            f: Transformation function\n\n        Returns:\n            List of transformed bar.Data objects\n        \n\nprocess_with_prefix(d: bar.Data, prefix: str) -> bar.Data\n  Process data with a prefix\n\n    Args:\n        d: Data to process\n        prefix: Prefix to add to data values\n\n    Returns:\n        New bar.Data with prefixed value\n    \n\nactor DataHandler(initial: bar.Data)\n  Actor that handles bar.Data objects\n\n    Args:\n        initial: Initial bar.Data to store\n    \n\napply_transformation(d: bar.Data, transform: (str) -> str) -> bar.Data\n  Apply transformation to bar.Data value\n\n    Args:\n        d: Data to transform\n        transform: Function to apply to value\n\n    Returns:\n        New bar.Data with transformed value\n    \n\napply_to_list(items: list[bar.Data], f: (bar.Data) -> str) -> list[str]\n  Apply function to all items in list\n\n    Args:\n        items: List of bar.Data objects\n        f: Function to apply\n\n    Returns:\n        List of results\n    \n\nprocess_nested(data: list[(str, bar.Data)]) -> dict[str, list[bar.Data]]\n  Process nested data structures\n\n    Args:\n        data: List of tuples containing keys and bar.Data\n\n    Returns:\n        Dictionary grouping bar.Data by key\n    \n\nactor main(env: Env)\n  Main actor demonstrating bar module usage\n"
  },
  {
    "path": "compiler/lib/test/parser_golden/alternating_quotes_error.golden",
    "content": "ERROR: [error Syntax error]: Missing closing '}' for expression\n     ╭──▶ test@1:17-1:18\n     │\n   1 │ \"a {'b {\"c {'d {e'}\"}'}\"\n     •                 ┬ \n     •                 ╰╸ Missing closing '}' for expression\n     •\n     │ Hint: Add a closing brace to complete the interpolation\n─────╯\n"
  },
  {
    "path": "compiler/lib/test/parser_golden/deep_nesting_error.golden",
    "content": "ERROR: [error Syntax error]: Invalid character '@' in format specifier\n     ╭──▶ test@1:23-1:24\n     │\n   1 │ \"a {\"b {\"c {\"d {\"e {f:@}\"}\"}\"}\"}\"}\"\n     •                       ┬ \n     •                       ╰╸ Invalid character '@' in format specifier\n     •\n     │ Note: Valid format specifiers use <, >, ^, +, -, #, 0, width, .precision, and type characters\n     │ Hint: Use a format specifier, e.g. '{name:<18}'\n─────╯\n"
  },
  {
    "path": "compiler/lib/test/parser_golden/error_at_end.golden",
    "content": "ERROR: [error Syntax error]: Missing closing '}' for expression\n     ╭──▶ test@1:10-1:11\n     │\n   1 │ \"at end {x\n     •          ┬\n     •          ╰╸ Missing closing '}' for expression\n     •\n     │ Hint: Add a closing brace to complete the interpolation\n─────╯\n"
  },
  {
    "path": "compiler/lib/test/parser_golden/error_at_start.golden",
    "content": "ERROR: [error Parse error]: unexpected \"at\"\n                     expecting ';', call arguments, slice/index expression, comma, end of line, if clause, or operator\n\n     ╭──▶ test@1:5-1:6\n     │\n   1 │ {x} at start\n     •     ┬ \n     •     ╰╸ unexpected \"at\"\n     •        expecting ';', call arguments, slice/index expression, comma, end of line, if clause, or operator\n     •        \n─────╯\n"
  },
  {
    "path": "compiler/lib/test/parser_golden/error_in_middle.golden",
    "content": "ERROR: [error Syntax error]: Invalid character '@' in format specifier\n     ╭──▶ test@1:11-1:12\n     │\n   1 │ \"start {x:@} end\"\n     •           ┬ \n     •           ╰╸ Invalid character '@' in format specifier\n     •\n     │ Note: Valid format specifiers use <, >, ^, +, -, #, 0, width, .precision, and type characters\n     │ Hint: Use a format specifier, e.g. '{name:<18}'\n─────╯\n"
  },
  {
    "path": "compiler/lib/test/parser_golden/escaped_brace_error.golden",
    "content": "PARSED: \"outer {broken %s\" % str(x)"
  },
  {
    "path": "compiler/lib/test/parser_golden/fstring_empty_expression.golden",
    "content": "ERROR: [error Syntax error]: Empty expression in string interpolation\n     ╭──▶ test@1:21-1:21\n     │\n   1 │ f\"Empty expression {}\"\n     •                      \n     •                     ╰╸ Empty expression in string interpolation\n     •\n     │ Hint: Add an expression between the braces, e.g. {name}\n─────╯\n"
  },
  {
    "path": "compiler/lib/test/parser_golden/fstring_empty_format_specifier.golden",
    "content": "ERROR: [error Syntax error]: Empty format specifier after ':'\n     ╭──▶ test@1:24-1:24\n     │\n   1 │ f\"Empty format spec {x:}\"\n     •                         \n     •                        ╰╸ Empty format specifier after ':'\n     •\n     │ Hint: Add a format specification or remove the colon\n─────╯\n"
  },
  {
    "path": "compiler/lib/test/parser_golden/fstring_invalid_alignment.golden",
    "content": "ERROR: [error Syntax error]: Invalid character '@' in format specifier\n     ╭──▶ test@1:9-1:10\n     │\n   1 │ f\"{name:@10}\"\n     •         ┬ \n     •         ╰╸ Invalid character '@' in format specifier\n     •\n     │ Note: Valid format specifiers use <, >, ^, +, -, #, 0, width, .precision, and type characters\n     │ Hint: Use a format specifier, e.g. '{name:<18}'\n─────╯\n"
  },
  {
    "path": "compiler/lib/test/parser_golden/fstring_invalid_format.golden",
    "content": "ERROR: [error Syntax error]: Invalid character '@' in format specifier\n     ╭──▶ test@1:34-1:35\n     │\n   1 │ f\"Invalid format specifier {name:@Z}\"\n     •                                  ┬ \n     •                                  ╰╸ Invalid character '@' in format specifier\n     •\n     │ Note: Valid format specifiers use <, >, ^, +, -, #, 0, width, .precision, and type characters\n     │ Hint: Use a format specifier, e.g. '{name:<18}'\n─────╯\n"
  },
  {
    "path": "compiler/lib/test/parser_golden/fstring_missing_expression.golden",
    "content": "ERROR: [error Syntax error]: Missing expression before format specifier\n     ╭──▶ test@1:23-1:23\n     │\n   1 │ f\"Missing expression {:10}\"\n     •                        \n     •                       ╰╸ Missing expression before format specifier\n     •\n     │ Hint: Add an expression before the colon, e.g. {value:10}\n─────╯\n"
  },
  {
    "path": "compiler/lib/test/parser_golden/fstring_missing_precision_digits_error.golden",
    "content": "ERROR: [error Syntax error]: Expected digits after '.' in format specifier\n     ╭──▶ test@1:38-1:38\n     │\n   1 │ f\"Missing precision digits {value:10.}\"\n     •                                       \n     •                                      ╰╸ Expected digits after '.' in format specifier\n     •\n     │ Hint: Add precision digits, e.g. .2f for 2 decimal places\n─────╯\n"
  },
  {
    "path": "compiler/lib/test/parser_golden/fstring_triple_double_6quotes.golden",
    "content": "ERROR: [error Syntax error]: Too many quote characters\n     ╭──▶ test@1:10-1:16\n     │\n   1 │ f\"\"\"x={x}\"\"\"\"\"\"\n     •          ┬─────\n     •          ╰╸ Too many quote characters\n     •\n     │ Note: Triple-quoted strings accept 3-5 quotes at the end\n     │ Hint: Using 4 quotes results in a string with 1 quote at the end, e.g. \"\"\"text\"\"\"\" -> text\"\n     │ Hint: Using 5 quotes results in a string with 2 quotes at the end, e.g. \"\"\"text\"\"\"\"\" -> text\"\"\n     │ Hint: Use escape sequences for quotes inside strings, e.g. \"\"\"text \\\"with quotes\\\"\"\" -> text \"with quotes\"\n─────╯\n"
  },
  {
    "path": "compiler/lib/test/parser_golden/fstring_triple_single_6quotes.golden",
    "content": "ERROR: [error Syntax error]: Too many quote characters\n     ╭──▶ test@1:10-1:16\n     │\n   1 │ f'''x={x}''''''\n     •          ┬─────\n     •          ╰╸ Too many quote characters\n     •\n     │ Note: Triple-quoted strings accept 3-5 quotes at the end\n     │ Hint: Using 4 quotes results in a string with 1 quote at the end, e.g. \"\"\"text\"\"\"\" -> text\"\n     │ Hint: Using 5 quotes results in a string with 2 quotes at the end, e.g. \"\"\"text\"\"\"\"\" -> text\"\"\n     │ Hint: Use escape sequences for quotes inside strings, e.g. \"\"\"text \\\"with quotes\\\"\"\" -> text \"with quotes\"\n─────╯\n"
  },
  {
    "path": "compiler/lib/test/parser_golden/fstring_unbalanced_format.golden",
    "content": "ERROR: [error Syntax error]: Empty format specifier after ':'\n     ╭──▶ test@1:27-1:27\n     │\n   1 │ f\"Unbalanced format {name:}:10}\"\n     •                            \n     •                           ╰╸ Empty format specifier after ':'\n     •\n     │ Hint: Add a format specification or remove the colon\n─────╯\n"
  },
  {
    "path": "compiler/lib/test/parser_golden/fstring_unclosed_brace.golden",
    "content": "ERROR: [error Syntax error]: Missing closing '}' for expression\n     ╭──▶ test@1:20-1:24\n     │\n   1 │ f\"Unclosed brace: {name\n     •                    ┬───\n     •                    ╰╸ Missing closing '}' for expression\n     •\n     │ Hint: Add a closing brace to complete the interpolation\n─────╯\n"
  },
  {
    "path": "compiler/lib/test/parser_golden/hex_incomplete_in_interpolation.golden",
    "content": "ERROR: [error Syntax error]: Incomplete hex character\n     ╭──▶ test@1:20-1:21\n     │\n   1 │ f\"value: {x} and \\x4\"\n     •                    ┬ \n     •                    ╰╸ Incomplete hex character\n     •\n     │ Note: Hex-escaped characters must be specified by two hexadecimal digits\n     │ Hint: Use two characters, e.g. \\x9a\n─────╯\n"
  },
  {
    "path": "compiler/lib/test/parser_golden/hex_incomplete_no_digits.golden",
    "content": "ERROR: [error Syntax error]: Incomplete hex character\n     ╭──▶ test@1:4-1:4\n     │\n   1 │ \"\\x\"\n     •     \n     •    ╰╸ Incomplete hex character\n     •\n     │ Note: Hex-escaped characters must be specified by two hexadecimal digits\n     │ Hint: Use two characters, e.g. \\x9a\n─────╯\n"
  },
  {
    "path": "compiler/lib/test/parser_golden/hex_incomplete_one_digit.golden",
    "content": "ERROR: [error Syntax error]: Incomplete hex character\n     ╭──▶ test@1:4-1:5\n     │\n   1 │ \"\\x4\"\n     •    ┬ \n     •    ╰╸ Incomplete hex character\n     •\n     │ Note: Hex-escaped characters must be specified by two hexadecimal digits\n     │ Hint: Use two characters, e.g. \\x9a\n─────╯\n"
  },
  {
    "path": "compiler/lib/test/parser_golden/hex_invalid_char.golden",
    "content": "ERROR: [error Syntax error]: Incomplete hex character\n     ╭──▶ test@1:4-1:5\n     │\n   1 │ \"\\xAG\"\n     •    ┬ \n     •    ╰╸ Incomplete hex character\n     •\n     │ Note: Hex-escaped characters must be specified by two hexadecimal digits\n     │ Hint: Use two characters, e.g. \\x9a\n─────╯\n"
  },
  {
    "path": "compiler/lib/test/parser_golden/invalid_after_align.golden",
    "content": "ERROR: [error Syntax error]: Invalid character '@' in format specifier\n     ╭──▶ test@1:15-1:15\n     │\n   1 │ \"value: {x:>10@}\"\n     •                \n     •               ╰╸ Invalid character '@' in format specifier\n     •\n     │ Note: Valid format specifiers use <, >, ^, +, -, #, 0, width, .precision, and type characters\n     │ Hint: Use a format specifier, e.g. '{name:<18}'\n─────╯\n"
  },
  {
    "path": "compiler/lib/test/parser_golden/invalid_after_precision.golden",
    "content": "ERROR: [error Syntax error]: Invalid character '@' in format specifier\n     ╭──▶ test@1:16-1:16\n     │\n   1 │ \"value: {x:10.2@}\"\n     •                 \n     •                ╰╸ Invalid character '@' in format specifier\n     •\n     │ Note: Valid format specifiers use <, >, ^, +, -, #, 0, width, .precision, and type characters\n     │ Hint: Use a format specifier, e.g. '{name:<18}'\n─────╯\n"
  },
  {
    "path": "compiler/lib/test/parser_golden/invalid_after_width.golden",
    "content": "ERROR: [error Syntax error]: Invalid character '@' in format specifier\n     ╭──▶ test@1:14-1:14\n     │\n   1 │ \"value: {x:10@}\"\n     •               \n     •              ╰╸ Invalid character '@' in format specifier\n     •\n     │ Note: Valid format specifiers use <, >, ^, +, -, #, 0, width, .precision, and type characters\n     │ Hint: Use a format specifier, e.g. '{name:<18}'\n─────╯\n"
  },
  {
    "path": "compiler/lib/test/parser_golden/invalid_in_type_spec.golden",
    "content": "ERROR: [error Syntax error]: Invalid character '@' in format specifier\n     ╭──▶ test@1:16-1:16\n     │\n   1 │ \"value: {x:10.2@f}\"\n     •                 \n     •                ╰╸ Invalid character '@' in format specifier\n     •\n     │ Note: Valid format specifiers use <, >, ^, +, -, #, 0, width, .precision, and type characters\n     │ Hint: Use a format specifier, e.g. '{name:<18}'\n─────╯\n"
  },
  {
    "path": "compiler/lib/test/parser_golden/mixed_quotes_unclosed.golden",
    "content": "ERROR: [error Syntax error]: Missing closing '}' for expression\n     ╭──▶ test@1:17-1:18\n     │\n   1 │ \"outer {'inner {x\n     •                 ┬\n     •                 ╰╸ Missing closing '}' for expression\n     •\n     │ Hint: Add a closing brace to complete the interpolation\n─────╯\n"
  },
  {
    "path": "compiler/lib/test/parser_golden/mixed_six_quotes_double.golden",
    "content": "ERROR: [error Parse error]: unexpected \"mi\"\n                     expecting \"\"\"\"\", \"'''\", '\"', ''', ';', call arguments, slice/index expression, comma, end of line, if clause, or operator\n\n     ╭──▶ test.act@1:11-1:12\n     │\n   1 │ a = \"\"\"\"\"\"mixed content with {interpolation}\"\"\"\"\"\"\n     •           ┬ \n     •           ╰╸ unexpected \"mi\"\n     •              expecting \"\"\"\"\", \"'''\", '\"', ''', ';', call arguments, slice/index expression, comma, end of line, if clause, or operator\n     •              \n─────╯\n"
  },
  {
    "path": "compiler/lib/test/parser_golden/module_actor_before_import.golden",
    "content": "ERROR: [error Parse error]: unexpected 'i'\n                     expecting \"@static\", \"@staticmethod\", \"action\", \"actor\", \"class\", \"def\", \"extension\", \"mut\", \"proc\", \"protocol\", \"pure\", '_', end of input, end of line, or statement\n\n     ╭──▶ test.act@3:1-3:2\n     │\n   3 │ import math\n     • ┬ \n     • ╰╸ unexpected 'i'\n     •    expecting \"@static\", \"@staticmethod\", \"action\", \"actor\", \"class\", \"def\", \"extension\", \"mut\", \"proc\", \"protocol\", \"pure\", '_', end of input, end of line, or statement\n     •    \n─────╯\n"
  },
  {
    "path": "compiler/lib/test/parser_golden/module_call_before_import.golden",
    "content": "ERROR: [error Syntax error]: Only declarations and assignments are allowed at the module top level\n     ╭──▶ test.act@1:1-1:15\n     │\n   1 │ print(\"hello\")\n     • ┬─────────────\n     • ╰╸ Only declarations and assignments are allowed at the module top level\n     •\n     │ Hint: Assign the value to a name or move runtime work into an actor or function\n─────╯\n"
  },
  {
    "path": "compiler/lib/test/parser_golden/module_class_before_import.golden",
    "content": "ERROR: [error Parse error]: unexpected 'i'\n                     expecting \"@static\", \"@staticmethod\", \"action\", \"actor\", \"class\", \"def\", \"extension\", \"mut\", \"proc\", \"protocol\", \"pure\", '_', end of input, end of line, or statement\n\n     ╭──▶ test.act@3:1-3:2\n     │\n   3 │ import math\n     • ┬ \n     • ╰╸ unexpected 'i'\n     •    expecting \"@static\", \"@staticmethod\", \"action\", \"actor\", \"class\", \"def\", \"extension\", \"mut\", \"proc\", \"protocol\", \"pure\", '_', end of input, end of line, or statement\n     •    \n─────╯\n"
  },
  {
    "path": "compiler/lib/test/parser_golden/module_dict_before_import.golden",
    "content": "ERROR: [error Syntax error]: Only declarations and assignments are allowed at the module top level\n     ╭──▶ test.act@1:1-1:17\n     │\n   1 │ {\"key\": \"value\"}\n     • ┬───────────────\n     • ╰╸ Only declarations and assignments are allowed at the module top level\n     •\n     │ Hint: Assign the value to a name or move runtime work into an actor or function\n─────╯\n"
  },
  {
    "path": "compiler/lib/test/parser_golden/module_for_before_import.golden",
    "content": "ERROR: [error Syntax error]: Only declarations and assignments are allowed at the module top level\n     ╭──▶ test.act@1:1-1:1\n     │\n   1 │ for i in range(10):\n     •  \n     • ╰╸ Only declarations and assignments are allowed at the module top level\n     •\n     │ Hint: Assign the value to a name or move runtime work into an actor or function\n─────╯\n"
  },
  {
    "path": "compiler/lib/test/parser_golden/module_func_before_import.golden",
    "content": "ERROR: [error Parse error]: unexpected 'i'\n                     expecting \"@static\", \"@staticmethod\", \"action\", \"actor\", \"class\", \"def\", \"extension\", \"mut\", \"proc\", \"protocol\", \"pure\", '_', end of input, end of line, or statement\n\n     ╭──▶ test.act@3:1-3:2\n     │\n   3 │ import math\n     • ┬ \n     • ╰╸ unexpected 'i'\n     •    expecting \"@static\", \"@staticmethod\", \"action\", \"actor\", \"class\", \"def\", \"extension\", \"mut\", \"proc\", \"protocol\", \"pure\", '_', end of input, end of line, or statement\n     •    \n─────╯\n"
  },
  {
    "path": "compiler/lib/test/parser_golden/module_if_before_import.golden",
    "content": "ERROR: [error Syntax error]: Only declarations and assignments are allowed at the module top level\n     ╭──▶ test.act@1:1-1:1\n     │\n   1 │ if True:\n     •  \n     • ╰╸ Only declarations and assignments are allowed at the module top level\n     •\n     │ Hint: Assign the value to a name or move runtime work into an actor or function\n─────╯\n"
  },
  {
    "path": "compiler/lib/test/parser_golden/module_list_before_import.golden",
    "content": "ERROR: [error Syntax error]: Only declarations and assignments are allowed at the module top level\n     ╭──▶ test.act@1:1-1:10\n     │\n   1 │ [1, 2, 3]\n     • ┬────────\n     • ╰╸ Only declarations and assignments are allowed at the module top level\n     •\n     │ Hint: Assign the value to a name or move runtime work into an actor or function\n─────╯\n"
  },
  {
    "path": "compiler/lib/test/parser_golden/module_number_before_import.golden",
    "content": "ERROR: [error Syntax error]: Only declarations and assignments are allowed at the module top level\n     ╭──▶ test.act@1:1-1:3\n     │\n   1 │ 42\n     • ┬─\n     • ╰╸ Only declarations and assignments are allowed at the module top level\n     •\n     │ Hint: Assign the value to a name or move runtime work into an actor or function\n─────╯\n"
  },
  {
    "path": "compiler/lib/test/parser_golden/module_var_before_import.golden",
    "content": "ERROR: [error Parse error]: unexpected 'i'\n                     expecting end of input, end of line, or statement\n\n     ╭──▶ test.act@2:1-2:2\n     │\n   2 │ import math\n     • ┬ \n     • ╰╸ unexpected 'i'\n     •    expecting end of input, end of line, or statement\n     •    \n─────╯\n"
  },
  {
    "path": "compiler/lib/test/parser_golden/multiline_format_error.golden",
    "content": "ERROR: [error Syntax error]: Invalid character '@' in format specifier\n     ╭──▶ test@2:11-2:12\n     │\n   2 │ Value: {x:@invalid}\n     •           ┬ \n     •           ╰╸ Invalid character '@' in format specifier\n     •\n     │ Note: Valid format specifiers use <, >, ^, +, -, #, 0, width, .precision, and type characters\n     │ Hint: Use a format specifier, e.g. '{name:<18}'\n─────╯\n"
  },
  {
    "path": "compiler/lib/test/parser_golden/multiline_nested_error.golden",
    "content": "ERROR: [error Syntax error]: Missing closing \"\n     ╭──▶ test@2:2-2:8\n     │\n   2 │ {\"inner\n     •  ┬─────\n     •  ╰╸ Missing closing \"\n     •\n     │ Hint: Add a closing quote (\") to match the opening one\n─────╯\n"
  },
  {
    "path": "compiler/lib/test/parser_golden/multiline_unclosed.golden",
    "content": "ERROR: [error Syntax error]: Missing closing '}' for expression\n     ╭──▶ test@2:9-2:10\n     │\n   2 │ Line 2 {x\n     •         ┬\n     •         ╰╸ Missing closing '}' for expression\n     •\n     │ Hint: Add a closing brace to complete the interpolation\n─────╯\n"
  },
  {
    "path": "compiler/lib/test/parser_golden/nested_bad_type_spec.golden",
    "content": "ERROR: [error Syntax error]: Invalid character '@' in format specifier\n     ╭──▶ test@1:20-1:20\n     │\n   1 │ \"outer {\"inner {x:5@}\"}\"\n     •                     \n     •                    ╰╸ Invalid character '@' in format specifier\n     •\n     │ Note: Valid format specifiers use <, >, ^, +, -, #, 0, width, .precision, and type characters\n     │ Hint: Use a format specifier, e.g. '{name:<18}'\n─────╯\n"
  },
  {
    "path": "compiler/lib/test/parser_golden/nested_empty_format.golden",
    "content": "ERROR: [error Syntax error]: Empty format specifier after ':'\n     ╭──▶ test@1:19-1:19\n     │\n   1 │ \"outer {\"inner {x:}\"}\"\n     •                    \n     •                   ╰╸ Empty format specifier after ':'\n     •\n     │ Hint: Add a format specification or remove the colon\n─────╯\n"
  },
  {
    "path": "compiler/lib/test/parser_golden/nested_empty_inner.golden",
    "content": "ERROR: [error Syntax error]: Empty expression in string interpolation\n     ╭──▶ test@1:17-1:17\n     │\n   1 │ \"outer {\"inner {}\"}\"\n     •                  \n     •                 ╰╸ Empty expression in string interpolation\n     •\n     │ Hint: Add an expression between the braces, e.g. {name}\n─────╯\n"
  },
  {
    "path": "compiler/lib/test/parser_golden/nested_invalid_align.golden",
    "content": "ERROR: [error Syntax error]: Invalid character '@' in format specifier\n     ╭──▶ test@1:19-1:20\n     │\n   1 │ \"outer {\"inner {x:@5}\"}\"\n     •                   ┬ \n     •                   ╰╸ Invalid character '@' in format specifier\n     •\n     │ Note: Valid format specifiers use <, >, ^, +, -, #, 0, width, .precision, and type characters\n     │ Hint: Use a format specifier, e.g. '{name:<18}'\n─────╯\n"
  },
  {
    "path": "compiler/lib/test/parser_golden/nested_invalid_format.golden",
    "content": "ERROR: [error Syntax error]: Invalid character '@' in format specifier\n     ╭──▶ test@1:19-1:20\n     │\n   1 │ \"outer {\"inner {x:@10}\"}\"\n     •                   ┬ \n     •                   ╰╸ Invalid character '@' in format specifier\n     •\n     │ Note: Valid format specifiers use <, >, ^, +, -, #, 0, width, .precision, and type characters\n     │ Hint: Use a format specifier, e.g. '{name:<18}'\n─────╯\n"
  },
  {
    "path": "compiler/lib/test/parser_golden/nested_unclosed_inner.golden",
    "content": "ERROR: [error Syntax error]: Missing closing '}' for expression\n     ╭──▶ test@1:9-1:20\n     │\n   1 │ \"outer {\"inner {x}\"\n     •         ┬──────────\n     •         ╰╸ Missing closing '}' for expression\n     •\n     │ Hint: Add a closing brace to complete the interpolation\n─────╯\n"
  },
  {
    "path": "compiler/lib/test/parser_golden/nested_unclosed_outer.golden",
    "content": "ERROR: [error Syntax error]: Missing closing \"\n     ╭──▶ test@1:9-1:15\n     │\n   1 │ \"outer {\"inner\n     •         ┬─────\n     •         ╰╸ Missing closing \"\n     •\n     │ Hint: Add a closing quote (\") to match the opening one\n─────╯\n"
  },
  {
    "path": "compiler/lib/test/parser_golden/newline_in_expr.golden",
    "content": "ERROR: [error Syntax error]: Missing closing '}' for expression\n     ╭──▶ test@1:10-1:11\n     │\n   1 │ \"value: {x\n     •          ┬\n     •          ╰╸ Missing closing '}' for expression\n     •\n     │ Hint: Add a closing brace to complete the interpolation\n─────╯\n"
  },
  {
    "path": "compiler/lib/test/parser_golden/octal_invalid_char.golden",
    "content": "PARSED: \"\\\\12G\""
  },
  {
    "path": "compiler/lib/test/parser_golden/octal_invalid_first_digit.golden",
    "content": "ERROR: [error Syntax error]: Unknown escape sequence\n     ╭──▶ test@1:4-1:4\n     │\n   1 │ \"\\8\"\n     •     \n     •    ╰╸ Unknown escape sequence\n     •\n     │ Note: Valid escape sequences: \\\\, \\\", \\', \\n, \\r, \\t, \\a, \\b, \\f, \\v, \\xHH, \\ooo, \\uHHHH, \\UHHHHHHHH\n─────╯\n"
  },
  {
    "path": "compiler/lib/test/parser_golden/octal_out_of_range.golden",
    "content": "ERROR: [error Syntax error]: Octal escape sequence out of range\n     ╭──▶ test@1:3-1:6\n     │\n   1 │ \"\\777\"\n     •   ┬── \n     •   ╰╸ Octal escape sequence out of range\n     •\n     │ Note: Octal values must be between \\000 and \\377\n─────╯\n"
  },
  {
    "path": "compiler/lib/test/parser_golden/octal_out_of_range_in_fstring.golden",
    "content": "ERROR: [error Syntax error]: Octal escape sequence out of range\n     ╭──▶ test@1:15-1:18\n     │\n   1 │ f\"value: {x} \\777\"\n     •               ┬── \n     •               ╰╸ Octal escape sequence out of range\n     •\n     │ Note: Octal values must be between \\000 and \\377\n─────╯\n"
  },
  {
    "path": "compiler/lib/test/parser_golden/raw_six_quotes.golden",
    "content": "ERROR: [error Parse error]: unexpected \"ra\"\n                     expecting \"r\"\", \"r\"\"\"\", \"r'\", \"r'''\", ';', call arguments, slice/index expression, comma, end of line, if clause, or operator\n\n     ╭──▶ test.act@1:12-1:13\n     │\n   1 │ a = r\"\"\"\"\"\"raw test\"\"\"\"\"\"\n     •            ┬ \n     •            ╰╸ unexpected \"ra\"\n     •               expecting \"r\"\", \"r\"\"\"\", \"r'\", \"r'''\", ';', call arguments, slice/index expression, comma, end of line, if clause, or operator\n     •               \n─────╯\n"
  },
  {
    "path": "compiler/lib/test/parser_golden/raw_triple_double_6quotes.golden",
    "content": "ERROR: [error Parse error]: unexpected \"\"\"\"\n                     expecting \"r\"\", \"r\"\"\"\", \"r'\", \"r'''\", ';', call arguments, slice/index expression, comma, end of line, if clause, or operator\n\n     ╭──▶ test@1:11-1:12\n     │\n   1 │ r\"\"\"raw\"\"\"\"\"\"\n     •           ┬ \n     •           ╰╸ unexpected \"\"\"\"\n     •              expecting \"r\"\", \"r\"\"\"\", \"r'\", \"r'''\", ';', call arguments, slice/index expression, comma, end of line, if clause, or operator\n     •              \n─────╯\n"
  },
  {
    "path": "compiler/lib/test/parser_golden/raw_triple_single_6quotes.golden",
    "content": "ERROR: [error Parse error]: unexpected \"''\"\n                     expecting \"r\"\", \"r\"\"\"\", \"r'\", \"r'''\", ';', call arguments, slice/index expression, comma, end of line, if clause, or operator\n\n     ╭──▶ test@1:11-1:12\n     │\n   1 │ r'''raw''''''\n     •           ┬ \n     •           ╰╸ unexpected \"''\"\n     •              expecting \"r\"\", \"r\"\"\"\", \"r'\", \"r'''\", ';', call arguments, slice/index expression, comma, end of line, if clause, or operator\n     •              \n─────╯\n"
  },
  {
    "path": "compiler/lib/test/parser_golden/seven_double_quotes.golden",
    "content": "ERROR: [error Parse error]: unexpected \"te\"\n                     expecting \"\"\"\"\", \"'''\", '\"', ''', ';', call arguments, slice/index expression, comma, end of line, if clause, or operator\n\n     ╭──▶ test.act@1:12-1:13\n     │\n   1 │ a = \"\"\"\"\"\"\"test\"\"\"\"\"\"\"\n     •            ┬ \n     •            ╰╸ unexpected \"te\"\n     •               expecting \"\"\"\"\", \"'''\", '\"', ''', ';', call arguments, slice/index expression, comma, end of line, if clause, or operator\n     •               \n─────╯\n"
  },
  {
    "path": "compiler/lib/test/parser_golden/six_double_quotes.golden",
    "content": "ERROR: [error Parse error]: unexpected \"te\"\n                     expecting \"\"\"\"\", \"'''\", '\"', ''', ';', call arguments, slice/index expression, comma, end of line, if clause, or operator\n\n     ╭──▶ test.act@1:11-1:12\n     │\n   1 │ a = \"\"\"\"\"\"test\"\"\"\"\"\"\n     •           ┬ \n     •           ╰╸ unexpected \"te\"\n     •              expecting \"\"\"\"\", \"'''\", '\"', ''', ';', call arguments, slice/index expression, comma, end of line, if clause, or operator\n     •              \n─────╯\n"
  },
  {
    "path": "compiler/lib/test/parser_golden/six_single_quotes.golden",
    "content": "ERROR: [error Parse error]: unexpected \"te\"\n                     expecting \"\"\"\"\", \"'''\", '\"', ''', ';', call arguments, slice/index expression, comma, end of line, if clause, or operator\n\n     ╭──▶ test.act@1:11-1:12\n     │\n   1 │ a = ''''''test''''''\n     •           ┬ \n     •           ╰╸ unexpected \"te\"\n     •              expecting \"\"\"\"\", \"'''\", '\"', ''', ';', call arguments, slice/index expression, comma, end of line, if clause, or operator\n     •              \n─────╯\n"
  },
  {
    "path": "compiler/lib/test/parser_golden/slice_format_error.golden",
    "content": "ERROR: [error Syntax error]: Invalid character '@' in format specifier\n     ╭──▶ test@1:19-1:20\n     │\n   1 │ \"slice: {arr[1:3]:@10}\"\n     •                   ┬ \n     •                   ╰╸ Invalid character '@' in format specifier\n     •\n     │ Note: Valid format specifiers use <, >, ^, +, -, #, 0, width, .precision, and type characters\n     │ Hint: Use a format specifier, e.g. '{name:<18}'\n─────╯\n"
  },
  {
    "path": "compiler/lib/test/parser_golden/slice_invalid_step.golden",
    "content": "ERROR: [error Parse error]: missing closing \"\n\n     ╭──▶ test@1:9-1:10\n     │\n   1 │ \"slice: {arr[:::\"\n     •         ┬ \n     •         ╰╸ missing closing \"\n     •            \n─────╯\n"
  },
  {
    "path": "compiler/lib/test/parser_golden/slice_missing_bracket.golden",
    "content": "ERROR: [error Syntax error]: Missing closing '}' for expression\n     ╭──▶ test@1:10-1:14\n     │\n   1 │ \"slice: {arr 1:3]}\"\n     •          ┬─── \n     •          ╰╸ Missing closing '}' for expression\n     •\n     │ Hint: Add a closing brace to complete the interpolation\n─────╯\n"
  },
  {
    "path": "compiler/lib/test/parser_golden/slice_nested_error.golden",
    "content": "ERROR: [error Parse error]: missing closing \"\n\n     ╭──▶ test@1:8-1:9\n     │\n   1 │ \"outer {arr[inner[}\"\n     •        ┬ \n     •        ╰╸ missing closing \"\n     •           \n─────╯\n"
  },
  {
    "path": "compiler/lib/test/parser_golden/slice_unclosed_bracket.golden",
    "content": "ERROR: [error Parse error]: missing closing \"\n\n     ╭──▶ test@1:9-1:10\n     │\n   1 │ \"slice: {arr[1:3\"\n     •         ┬ \n     •         ╰╸ missing closing \"\n     •            \n─────╯\n"
  },
  {
    "path": "compiler/lib/test/parser_golden/string_empty_expression.golden",
    "content": "ERROR: [error Syntax error]: Empty expression in string interpolation\n     ╭──▶ test@1:20-1:20\n     │\n   1 │ \"Empty expression {}\"\n     •                     \n     •                    ╰╸ Empty expression in string interpolation\n     •\n     │ Hint: Add an expression between the braces, e.g. {name}\n─────╯\n"
  },
  {
    "path": "compiler/lib/test/parser_golden/string_invalid_format.golden",
    "content": "ERROR: [error Syntax error]: Invalid character '@' in format specifier\n     ╭──▶ test@1:8-1:9\n     │\n   1 │ \"{name:@Z}\"\n     •        ┬ \n     •        ╰╸ Invalid character '@' in format specifier\n     •\n     │ Note: Valid format specifiers use <, >, ^, +, -, #, 0, width, .precision, and type characters\n     │ Hint: Use a format specifier, e.g. '{name:<18}'\n─────╯\n"
  },
  {
    "path": "compiler/lib/test/parser_golden/string_missing_expression.golden",
    "content": "ERROR: [error Syntax error]: Missing expression before format specifier\n     ╭──▶ test@1:22-1:22\n     │\n   1 │ \"Missing expression {:10}\"\n     •                       \n     •                      ╰╸ Missing expression before format specifier\n     •\n     │ Hint: Add an expression before the colon, e.g. {value:10}\n─────╯\n"
  },
  {
    "path": "compiler/lib/test/parser_golden/string_unclosed_brace.golden",
    "content": "ERROR: [error Syntax error]: Missing closing '}' for expression\n     ╭──▶ test@1:19-1:23\n     │\n   1 │ \"Unclosed brace: {name\n     •                   ┬───\n     •                   ╰╸ Missing closing '}' for expression\n     •\n     │ Hint: Add a closing brace to complete the interpolation\n─────╯\n"
  },
  {
    "path": "compiler/lib/test/parser_golden/tab_in_format.golden",
    "content": "ERROR: [error Syntax error]: Tab character not allowed in format specifier\n     ╭──▶ test@1:12-1:17\n     │\n   1 │ \"value: {x:    10}\"\n     •            ┬───────\n     •            ╰╸ Tab character not allowed in format specifier\n─────╯\n"
  },
  {
    "path": "compiler/lib/test/parser_golden/triple_double_10quotes.golden",
    "content": "ERROR: [error Syntax error]: Too many quote characters\n     ╭──▶ test@1:11-1:21\n     │\n   1 │ \"\"\"content\"\"\"\"\"\"\"\"\"\"\n     •           ┬─────────\n     •           ╰╸ Too many quote characters\n     •\n     │ Note: Triple-quoted strings accept 3-5 quotes at the end\n     │ Hint: Using 4 quotes results in a string with 1 quote at the end, e.g. \"\"\"text\"\"\"\" -> text\"\n     │ Hint: Using 5 quotes results in a string with 2 quotes at the end, e.g. \"\"\"text\"\"\"\"\" -> text\"\"\n     │ Hint: Use escape sequences for quotes inside strings, e.g. \"\"\"text \\\"with quotes\\\"\"\" -> text \"with quotes\"\n─────╯\n"
  },
  {
    "path": "compiler/lib/test/parser_golden/triple_double_6quotes.golden",
    "content": "ERROR: [error Syntax error]: Too many quote characters\n     ╭──▶ test@1:7-1:13\n     │\n   1 │ \"\"\"foo\"\"\"\"\"\"\n     •       ┬─────\n     •       ╰╸ Too many quote characters\n     •\n     │ Note: Triple-quoted strings accept 3-5 quotes at the end\n     │ Hint: Using 4 quotes results in a string with 1 quote at the end, e.g. \"\"\"text\"\"\"\" -> text\"\n     │ Hint: Using 5 quotes results in a string with 2 quotes at the end, e.g. \"\"\"text\"\"\"\"\" -> text\"\"\n     │ Hint: Use escape sequences for quotes inside strings, e.g. \"\"\"text \\\"with quotes\\\"\"\" -> text \"with quotes\"\n─────╯\n"
  },
  {
    "path": "compiler/lib/test/parser_golden/triple_double_7quotes.golden",
    "content": "ERROR: [error Syntax error]: Too many quote characters\n     ╭──▶ test@1:7-1:14\n     │\n   1 │ \"\"\"bar\"\"\"\"\"\"\"\n     •       ┬──────\n     •       ╰╸ Too many quote characters\n     •\n     │ Note: Triple-quoted strings accept 3-5 quotes at the end\n     │ Hint: Using 4 quotes results in a string with 1 quote at the end, e.g. \"\"\"text\"\"\"\" -> text\"\n     │ Hint: Using 5 quotes results in a string with 2 quotes at the end, e.g. \"\"\"text\"\"\"\"\" -> text\"\"\n     │ Hint: Use escape sequences for quotes inside strings, e.g. \"\"\"text \\\"with quotes\\\"\"\" -> text \"with quotes\"\n─────╯\n"
  },
  {
    "path": "compiler/lib/test/parser_golden/triple_double_8quotes.golden",
    "content": "ERROR: [error Syntax error]: Too many quote characters\n     ╭──▶ test@1:8-1:16\n     │\n   1 │ \"\"\"test\"\"\"\"\"\"\"\"\n     •        ┬───────\n     •        ╰╸ Too many quote characters\n     •\n     │ Note: Triple-quoted strings accept 3-5 quotes at the end\n     │ Hint: Using 4 quotes results in a string with 1 quote at the end, e.g. \"\"\"text\"\"\"\" -> text\"\n     │ Hint: Using 5 quotes results in a string with 2 quotes at the end, e.g. \"\"\"text\"\"\"\"\" -> text\"\"\n     │ Hint: Use escape sequences for quotes inside strings, e.g. \"\"\"text \\\"with quotes\\\"\"\" -> text \"with quotes\"\n─────╯\n"
  },
  {
    "path": "compiler/lib/test/parser_golden/triple_nested_unclosed.golden",
    "content": "ERROR: [error Syntax error]: Missing closing '}' for expression\n     ╭──▶ test@1:28-1:29\n     │\n   1 │ \"level1 {\"level2 {\"level3 {x\n     •                            ┬\n     •                            ╰╸ Missing closing '}' for expression\n     •\n     │ Hint: Add a closing brace to complete the interpolation\n─────╯\n"
  },
  {
    "path": "compiler/lib/test/parser_golden/triple_single_10quotes.golden",
    "content": "ERROR: [error Syntax error]: Too many quote characters\n     ╭──▶ test@1:11-1:21\n     │\n   1 │ '''content''''''''''\n     •           ┬─────────\n     •           ╰╸ Too many quote characters\n     •\n     │ Note: Triple-quoted strings accept 3-5 quotes at the end\n     │ Hint: Using 4 quotes results in a string with 1 quote at the end, e.g. \"\"\"text\"\"\"\" -> text\"\n     │ Hint: Using 5 quotes results in a string with 2 quotes at the end, e.g. \"\"\"text\"\"\"\"\" -> text\"\"\n     │ Hint: Use escape sequences for quotes inside strings, e.g. \"\"\"text \\\"with quotes\\\"\"\" -> text \"with quotes\"\n─────╯\n"
  },
  {
    "path": "compiler/lib/test/parser_golden/triple_single_6quotes.golden",
    "content": "ERROR: [error Syntax error]: Too many quote characters\n     ╭──▶ test@1:7-1:13\n     │\n   1 │ '''foo''''''\n     •       ┬─────\n     •       ╰╸ Too many quote characters\n     •\n     │ Note: Triple-quoted strings accept 3-5 quotes at the end\n     │ Hint: Using 4 quotes results in a string with 1 quote at the end, e.g. \"\"\"text\"\"\"\" -> text\"\n     │ Hint: Using 5 quotes results in a string with 2 quotes at the end, e.g. \"\"\"text\"\"\"\"\" -> text\"\"\n     │ Hint: Use escape sequences for quotes inside strings, e.g. \"\"\"text \\\"with quotes\\\"\"\" -> text \"with quotes\"\n─────╯\n"
  },
  {
    "path": "compiler/lib/test/parser_golden/triple_single_7quotes.golden",
    "content": "ERROR: [error Syntax error]: Too many quote characters\n     ╭──▶ test@1:7-1:14\n     │\n   1 │ '''bar'''''''\n     •       ┬──────\n     •       ╰╸ Too many quote characters\n     •\n     │ Note: Triple-quoted strings accept 3-5 quotes at the end\n     │ Hint: Using 4 quotes results in a string with 1 quote at the end, e.g. \"\"\"text\"\"\"\" -> text\"\n     │ Hint: Using 5 quotes results in a string with 2 quotes at the end, e.g. \"\"\"text\"\"\"\"\" -> text\"\"\n     │ Hint: Use escape sequences for quotes inside strings, e.g. \"\"\"text \\\"with quotes\\\"\"\" -> text \"with quotes\"\n─────╯\n"
  },
  {
    "path": "compiler/lib/test/parser_golden/triple_single_8quotes.golden",
    "content": "ERROR: [error Syntax error]: Too many quote characters\n     ╭──▶ test@1:8-1:16\n     │\n   1 │ '''test''''''''\n     •        ┬───────\n     •        ╰╸ Too many quote characters\n     •\n     │ Note: Triple-quoted strings accept 3-5 quotes at the end\n     │ Hint: Using 4 quotes results in a string with 1 quote at the end, e.g. \"\"\"text\"\"\"\" -> text\"\n     │ Hint: Using 5 quotes results in a string with 2 quotes at the end, e.g. \"\"\"text\"\"\"\"\" -> text\"\"\n     │ Hint: Use escape sequences for quotes inside strings, e.g. \"\"\"text \\\"with quotes\\\"\"\" -> text \"with quotes\"\n─────╯\n"
  },
  {
    "path": "compiler/lib/test/parser_golden/tristring_unclosed_brace.golden",
    "content": "ERROR: [error Syntax error]: Missing closing '}' for expression\n     ╭──▶ test@1:21-1:25\n     │\n   1 │ \"\"\"Unclosed brace: {name\n     •                     ┬───\n     •                     ╰╸ Missing closing '}' for expression\n     •\n     │ Hint: Add a closing brace to complete the interpolation\n─────╯\n"
  },
  {
    "path": "compiler/lib/test/parser_golden/unclosed_bytes_string.golden",
    "content": "ERROR: [error Syntax error]: Missing closing \"\n     ╭──▶ test.act@1:6-1:12\n     │\n   1 │ a = b\"hello\n     •      ┬─────\n     •      ╰╸ Missing closing \"\n     •\n     │ Hint: Add a closing quote (\") to match the opening one\n─────╯\n"
  },
  {
    "path": "compiler/lib/test/parser_golden/unclosed_bytes_string_single.golden",
    "content": "ERROR: [error Syntax error]: Missing closing '\n     ╭──▶ test.act@1:6-1:12\n     │\n   1 │ a = b'hello\n     •      ┬─────\n     •      ╰╸ Missing closing '\n     •\n     │ Hint: Add a closing quote (') to match the opening one\n─────╯\n"
  },
  {
    "path": "compiler/lib/test/parser_golden/unclosed_raw_bytes_string.golden",
    "content": "ERROR: [error Syntax error]: Missing closing \"\n     ╭──▶ test.act@1:7-1:13\n     │\n   1 │ a = rb\"hello\n     •       ┬─────\n     •       ╰╸ Missing closing \"\n     •\n     │ Hint: Add a closing quote (\") to match the opening one\n─────╯\n"
  },
  {
    "path": "compiler/lib/test/parser_golden/unclosed_raw_bytes_string_single.golden",
    "content": "ERROR: [error Syntax error]: Missing closing '\n     ╭──▶ test.act@1:7-1:13\n     │\n   1 │ a = rb'hello\n     •       ┬─────\n     •       ╰╸ Missing closing '\n     •\n     │ Hint: Add a closing quote (') to match the opening one\n─────╯\n"
  },
  {
    "path": "compiler/lib/test/parser_golden/unclosed_raw_string.golden",
    "content": "ERROR: [error Syntax error]: Missing closing \"\n     ╭──▶ test.act@1:6-1:12\n     │\n   1 │ a = r\"hello\n     •      ┬─────\n     •      ╰╸ Missing closing \"\n     •\n     │ Hint: Add a closing quote (\") to match the opening one\n─────╯\n"
  },
  {
    "path": "compiler/lib/test/parser_golden/unclosed_raw_string_single.golden",
    "content": "ERROR: [error Syntax error]: Missing closing '\n     ╭──▶ test.act@1:6-1:12\n     │\n   1 │ a = r'hello\n     •      ┬─────\n     •      ╰╸ Missing closing '\n     •\n     │ Hint: Add a closing quote (') to match the opening one\n─────╯\n"
  },
  {
    "path": "compiler/lib/test/parser_golden/unclosed_string.golden",
    "content": "ERROR: [error Syntax error]: Missing closing \"\n     ╭──▶ test.act@1:5-1:11\n     │\n   1 │ a = \"hello\n     •     ┬─────\n     •     ╰╸ Missing closing \"\n     •\n     │ Hint: Add a closing quote (\") to match the opening one\n─────╯\n"
  },
  {
    "path": "compiler/lib/test/parser_golden/unclosed_string_triple.golden",
    "content": "ERROR: [error Syntax error]: Missing closing \"\"\"\n     ╭──▶ test.act@2:2-2:5\n     │\n   2 │ a = \"\"\"hello\n     •  ┬── \n     •  ╰╸ Missing closing \"\"\"\n     •\n     │ Hint: Add a closing quote (\"\"\") to match the opening one\n─────╯\n"
  },
  {
    "path": "compiler/lib/test/parser_golden/unicode_format_error.golden",
    "content": "ERROR: [error Syntax error]: Invalid character '你' in format specifier\n     ╭──▶ test@1:11-1:12\n     │\n   1 │ \"你好 {name:你}\"\n     •             ┬─ \n     •             ╰╸ Invalid character '你' in format specifier\n     •\n     │ Note: Valid format specifiers use <, >, ^, +, -, #, 0, width, .precision, and type characters\n     │ Hint: Use a format specifier, e.g. '{name:<18}'\n─────╯\n"
  },
  {
    "path": "compiler/lib/test/parser_golden/unicode_long_in_fstring.golden",
    "content": "ERROR: [error Syntax error]: Incomplete universal character name\n     ╭──▶ test@1:11-1:18\n     │\n   1 │ f\"Hello \\U1234567\"\n     •           ┬────── \n     •           ╰╸ Incomplete universal character name\n     •\n     │ Note: Expected 8 hex digits, found 7\n─────╯\n"
  },
  {
    "path": "compiler/lib/test/parser_golden/unicode_long_incomplete.golden",
    "content": "ERROR: [error Syntax error]: Incomplete universal character name\n     ╭──▶ test@1:4-1:11\n     │\n   1 │ \"\\U1234567\"\n     •    ┬────── \n     •    ╰╸ Incomplete universal character name\n     •\n     │ Note: Expected 8 hex digits, found 7\n─────╯\n"
  },
  {
    "path": "compiler/lib/test/parser_golden/unicode_long_invalid_char.golden",
    "content": "ERROR: [error Syntax error]: Incomplete universal character name\n     ╭──▶ test@1:4-1:11\n     │\n   1 │ \"\\U1234567G\"\n     •    ┬────── \n     •    ╰╸ Incomplete universal character name\n     •\n     │ Note: Expected 8 hex digits, found 7\n─────╯\n"
  },
  {
    "path": "compiler/lib/test/parser_golden/unicode_long_no_digits.golden",
    "content": "ERROR: [error Syntax error]: Incomplete universal character name\n     ╭──▶ test@1:4-1:4\n     │\n   1 │ \"\\U\"\n     •     \n     •    ╰╸ Incomplete universal character name\n     •\n     │ Note: Expected 8 hex digits, found 0\n─────╯\n"
  },
  {
    "path": "compiler/lib/test/parser_golden/unicode_short_in_fstring.golden",
    "content": "ERROR: [error Syntax error]: Incomplete universal character name\n     ╭──▶ test@1:11-1:14\n     │\n   1 │ f\"Hello \\u123\"\n     •           ┬── \n     •           ╰╸ Incomplete universal character name\n     •\n     │ Note: Expected 4 hex digits, found 3\n─────╯\n"
  },
  {
    "path": "compiler/lib/test/parser_golden/unicode_short_incomplete.golden",
    "content": "ERROR: [error Syntax error]: Incomplete universal character name\n     ╭──▶ test@1:4-1:7\n     │\n   1 │ \"\\u123\"\n     •    ┬── \n     •    ╰╸ Incomplete universal character name\n     •\n     │ Note: Expected 4 hex digits, found 3\n─────╯\n"
  },
  {
    "path": "compiler/lib/test/parser_golden/unicode_short_invalid_char.golden",
    "content": "ERROR: [error Syntax error]: Incomplete universal character name\n     ╭──▶ test@1:4-1:7\n     │\n   1 │ \"\\u123G\"\n     •    ┬── \n     •    ╰╸ Incomplete universal character name\n     •\n     │ Note: Expected 4 hex digits, found 3\n─────╯\n"
  },
  {
    "path": "compiler/lib/test/parser_golden/unicode_short_no_digits.golden",
    "content": "ERROR: [error Syntax error]: Incomplete universal character name\n     ╭──▶ test@1:4-1:4\n     │\n   1 │ \"\\u\"\n     •     \n     •    ╰╸ Incomplete universal character name\n     •\n     │ Note: Expected 4 hex digits, found 0\n─────╯\n"
  },
  {
    "path": "compiler/lib/test/parser_golden/unknown_escape_in_fstring.golden",
    "content": "ERROR: [error Syntax error]: Unknown escape sequence\n     ╭──▶ test@1:14-1:14\n     │\n   1 │ f\"unknown: \\q\"\n     •               \n     •              ╰╸ Unknown escape sequence\n     •\n     │ Note: Valid escape sequences: \\\\, \\\", \\', \\n, \\r, \\t, \\a, \\b, \\f, \\v, \\xHH, \\ooo, \\uHHHH, \\UHHHHHHHH\n─────╯\n"
  },
  {
    "path": "compiler/lib/test/parser_golden/unknown_escape_p.golden",
    "content": "ERROR: [error Syntax error]: Unknown escape sequence\n     ╭──▶ test@1:4-1:4\n     │\n   1 │ \"\\p\"\n     •     \n     •    ╰╸ Unknown escape sequence\n     •\n     │ Note: Valid escape sequences: \\\\, \\\", \\', \\n, \\r, \\t, \\a, \\b, \\f, \\v, \\xHH, \\ooo, \\uHHHH, \\UHHHHHHHH\n─────╯\n"
  },
  {
    "path": "compiler/lib/test/parser_golden/unknown_escape_with_interpolation.golden",
    "content": "ERROR: [error Syntax error]: Unknown escape sequence\n     ╭──▶ test@1:16-1:16\n     │\n   1 │ f\"value: {x} \\k\"\n     •                 \n     •                ╰╸ Unknown escape sequence\n     •\n     │ Note: Valid escape sequences: \\\\, \\\", \\', \\n, \\r, \\t, \\a, \\b, \\f, \\v, \\xHH, \\ooo, \\uHHHH, \\UHHHHHHHH\n─────╯\n"
  },
  {
    "path": "compiler/lib/test/parser_golden/unknown_escape_z.golden",
    "content": "ERROR: [error Syntax error]: Unknown escape sequence\n     ╭──▶ test@1:4-1:4\n     │\n   1 │ \"\\z\"\n     •     \n     •    ╰╸ Unknown escape sequence\n     •\n     │ Note: Valid escape sequences: \\\\, \\\", \\', \\n, \\r, \\t, \\a, \\b, \\f, \\v, \\xHH, \\ooo, \\uHHHH, \\UHHHHHHHH\n─────╯\n"
  },
  {
    "path": "compiler/lib/test/src/bar.act",
    "content": "\"\"\"Bar module - defines shared types and utilities\n\nThis module provides common data structures and utilities\nthat are used across the application.\n\"\"\"\n\n# Module constants\nVERSION: str = \"1.0.0\"\n# Current version of the bar module\n\nMAX_ITEMS: int = 1000\n# Maximum number of items allowed in a container\n\n# Basic data class\nclass Data(object):\n    \"\"\"A data container with metadata\n\n    This class holds arbitrary data along with metadata\n    about when it was created and last modified.\n\n    Examples:\n        >>> d = Data(\"hello\", \"test-data\")\n        >>> d.get_value()\n        \"hello\"\n    \"\"\"\n    value: str\n    label: str\n    count: int\n\n    def __init__(self, value: str, label: str):\n        \"\"\"Initialize data with value and label\n\n        Args:\n            value: The data value\n            label: A descriptive label\n        \"\"\"\n        self.value = value\n        self.label = label\n        self.count = 0\n\n    def get_value(self) -> str:\n        \"\"\"Get the stored value\n\n        Returns:\n            The data value\n        \"\"\"\n        self.count += 1\n        return self.value\n\n    def update(self, new_value: str):\n        \"\"\"Update the value\n\n        Args:\n            new_value: New value to store\n\n        Note:\n            This increments the access count\n        \"\"\"\n        self.value = new_value\n        self.count += 1\n\n    def get_info(self) -> str:\n        \"\"\"Get formatted information about this data\n\n        Returns:\n            A string with label, value, and count\n        \"\"\"\n        return f\"{self.label}: {self.value} (accessed {self.count} times)\"\n\n# Generic container\nclass Container[T](object):\n    \"\"\"A generic container that can hold items of any type\n\n    This container maintains a list of items with various\n    operations for manipulation and querying.\n\n    Type Args:\n        T: The type of items stored in the container\n    \"\"\"\n    items: list[T]\n    name: str\n\n    def __init__(self, name: str):\n        \"\"\"Create an empty container\n\n        Args:\n            name: Container name for identification\n        \"\"\"\n        self.items = []\n        self.name = name\n\n    def add(self, item: T):\n        \"\"\"Add an item to the container\n\n        Args:\n            item: Item to add\n\n        Raises:\n            ValueError: If container is full\n        \"\"\"\n        if len(self.items) >= MAX_ITEMS:\n            raise ValueError(\"Container is full\")\n        self.items.append(item)\n\n    def get_all(self) -> list[T]:\n        \"\"\"Get all items\n\n        Returns:\n            List of all items in the container\n        \"\"\"\n        return self.items\n\n    def filter[U](self, predicate: (T) -> bool, transform: (T) -> U) -> list[U]:\n        \"\"\"Filter and transform items\n\n        Args:\n            predicate: Function to test each item\n            transform: Function to transform matching items\n\n        Returns:\n            List of transformed items that match predicate\n\n        Examples:\n            >>> c = Container[int](\"numbers\")\n            >>> c.add(1)\n            >>> c.add(2)\n            >>> c.filter(lambda x: x > 1, lambda x: str(x))\n            [\"2\"]\n        \"\"\"\n        result = []\n        for item in self.items:\n            if predicate(item):\n                result.append(transform(item))\n        return result\n\n    def count(self) -> int:\n        \"\"\"Get number of items in container\n\n        Returns:\n            Number of items\n        \"\"\"\n        return len(self.items)\n\n# Utility functions\ndef process_data(d: Data) -> str:\n    \"\"\"Process a data object and return summary\n\n    Args:\n        d: Data object to process\n\n    Returns:\n        Processed summary string\n\n    See Also:\n        Data.get_info: For detailed information\n    \"\"\"\n    return f\"Processed: {d.get_value()}\"\n\ndef combine_data(d1: Data, d2: Data) -> Data:\n    \"\"\"Combine two data objects\n\n    Args:\n        d1: First data object\n        d2: Second data object\n\n    Returns:\n        New Data object with combined values\n    \"\"\"\n    combined_value = d1.value + \" + \" + d2.value\n    combined_label = f\"{d1.label}/{d2.label}\"\n    return Data(combined_value, combined_label)\n\n# Actor that works with Data\nactor DataProcessor():\n    \"\"\"Actor that processes Data objects\n\n    This actor maintains a queue of data objects\n    and processes them asynchronously.\n    \"\"\"\n    var queue: list[Data] = []\n    var processed_count: int = 0\n\n    def enqueue(d: Data):\n        \"\"\"Add data to processing queue\n\n        Args:\n            d: Data object to process\n        \"\"\"\n        queue.append(d)\n\n    def process_next() -> ?Data:\n        \"\"\"Process next item in queue\n\n        Returns:\n            Processed data or None if queue empty\n        \"\"\"\n        if len(queue) > 0:\n            d = queue[0]\n            queue = queue[1:]\n            processed_count += 1\n            # Simulate processing\n            d.update(d.value.upper())\n            return d\n        return None\n\n    def get_stats() -> dict[str, int]:\n        \"\"\"Get processing statistics\n\n        Returns:\n            Dict with queue size and processed count\n        \"\"\"\n        return {\n            \"queued\": len(queue),\n            \"processed\": processed_count\n        }\n\n# Type constraint for documentation\ndef sum_counts[T(Plus)](items: list[T]) -> T:\n    \"\"\"Sum a list of items that support addition\n\n    Args:\n        items: List of summable items\n\n    Returns:\n        Sum of all items\n\n    Raises:\n        ValueError: If list is empty\n    \"\"\"\n    if len(items) == 0:\n        raise ValueError(\"Cannot sum empty list\")\n    result = items[0]\n    for i in range(1, len(items)):\n        result = result + items[i]\n    return result\n\n# Protocol definition\nprotocol Processable[T]:\n    \"\"\"Protocol for objects that can be processed\n\n    This protocol defines the interface for objects that\n    can be processed and transformed into a result of type T.\n\n    Type Args:\n        T: The type of the processing result\n    \"\"\"\n\n    process : () -> T\n    validate : () -> bool\n    get_metadata : () -> dict[str, str]\n\n# Extension to make Data implement Processable\nextension Data(Processable[str]):\n    \"\"\"Makes Data implement the Processable protocol\n\n    This extension allows Data objects to be processed\n    according to the Processable protocol, returning\n    string results.\n    \"\"\"\n\n    def process(self) -> str:\n        \"\"\"Process data by converting to uppercase\n\n        Returns:\n            Uppercase version of the data value\n        \"\"\"\n        return self.value.upper()\n\n    def validate(self) -> bool:\n        \"\"\"Check if data is non-empty\n\n        Returns:\n            True if data has content, False if empty\n        \"\"\"\n        return len(self.value) > 0\n\n    def get_metadata(self) -> dict[str, str]:\n        \"\"\"Get data metadata\n\n        Returns:\n            Metadata including label and access count\n        \"\"\"\n        return {\n            \"label\": self.label,\n            \"access_count\": str(self.count),\n            \"length\": str(len(self.value))\n        }\n\n# Function that uses the protocol\ndef process_items[T](items: list[Processable[T]]) -> list[T]:\n    \"\"\"Process a list of processable items\n\n    Args:\n        items: List of items implementing Processable protocol\n\n    Returns:\n        List of processed results\n\n    Examples:\n        >>> d1 = Data(\"hello\", \"test\")\n        >>> d2 = Data(\"world\", \"test2\")\n        >>> results = process_items([d1, d2])\n        >>> results\n        [\"HELLO\", \"WORLD\"]\n    \"\"\"\n    results = []\n    for item in items:\n        if item.validate():\n            results.append(item.process())\n    return results\n\ndef gt(a, b, c, d):\n    \"\"\"Function that takes generic types\"\"\"\n    return (a + b, a - b, c + d)\n"
  },
  {
    "path": "compiler/lib/test/src/class_init_attrs/init_actor.act",
    "content": "actor Act():\n    def foo():\n        return 1\n\nclass TestClass(object):\n    x: int\n    y: int\n\n    def __init__(self):\n        self.x = 1\n        a = Act()\n        self.y = a.foo()\n\nactor main(env):\n    t = TestClass()\n    env.exit(0)\n"
  },
  {
    "path": "compiler/lib/test/src/class_init_attrs/init_actor_call.act",
    "content": "actor Act():\n    def foo():\n        return 1\n\nclass TestClass(object):\n    x: int\n    y: int\n\n    def __init__(self, a):\n        self.x = 1\n        self.y = a.foo()\n\nactor main(env):\n    a = Act()\n    t = TestClass(a)\n    env.exit(0)\n"
  },
  {
    "path": "compiler/lib/test/src/class_init_attrs/init_after_loop.act",
    "content": "# Test case: Assignments after a loop that doesn't reference self\nclass TestClass(object):\n    x: int\n    y: int\n\n    def __init__(self):\n        # Loop that doesn't reference self - safe to continue past it\n        for i in range(10):\n            print(i)\n        # These assignments happen after the loop\n        self.x = 1\n        self.y = 2\n\ndef range(n: int) -> list[int]:\n    return []\n\ndef print(x: int) -> None:\n    pass\n\nactor main(env):\n    t = TestClass()\n    env.exit(0)"
  },
  {
    "path": "compiler/lib/test/src/class_init_attrs/init_after_statements.act",
    "content": "class TestClass(object):\n    x: int\n\n    def __init__(self):\n        print(\"hello\")\n        pass\n        self.x = 1\n\nactor main(env):\n    t = TestClass()\n    env.exit(0)\n"
  },
  {
    "path": "compiler/lib/test/src/class_init_attrs/init_after_while.act",
    "content": "# Test case: Assignments after a while loop that doesn't reference self\nclass TestClass(object):\n    x: int\n    y: int\n\n    def __init__(self):\n        count = 0\n        # While loop that doesn't reference self\n        while count < 5:\n            count = count + 1\n        # These assignments happen after the loop\n        self.x = 1\n        self.y = 2\n\nactor main(env):\n    t = TestClass()\n    env.exit(0)"
  },
  {
    "path": "compiler/lib/test/src/class_init_attrs/init_assert.act",
    "content": "# Test case: assert statement shouldn't stop initialization scanning\nclass TestClass(object):\n    value: int\n    result: int\n    \n    def __init__(self, x: int):\n        self.value = x\n        \n        # Assert shouldn't stop scanning if it doesn't reference self\n        assert x > 0, \"x must be positive\"\n        \n        # This should still be recognized as part of constructor\n        self.result = self.value * 2\n\nactor main(env):\n    t = TestClass(5)\n    env.exit(0)"
  },
  {
    "path": "compiler/lib/test/src/class_init_attrs/init_assert_with_self.act",
    "content": "# Test case: assert that references self should stop initialization scanning\nclass TestClass(object):\n    value: int\n    result: int\n    \n    def __init__(self, x: int):\n        self.value = x\n        \n        # Assert that references self should stop scanning\n        assert self.value > 0, \"value must be positive\"\n        \n        # This won't be recognized as initialized (self escaped in assert)\n        self.result = 42\n\nactor main(env):\n    t = TestClass(5)\n    env.exit(0)\n"
  },
  {
    "path": "compiler/lib/test/src/class_init_attrs/init_basic.act",
    "content": "class TestClass(object):\n    x: int\n\n    def __init__(self):\n        self.x = 1\n\nactor main(env):\n    t = TestClass()\n    env.exit(0)\n"
  },
  {
    "path": "compiler/lib/test/src/class_init_attrs/init_both_branches_with_raise.act",
    "content": "# Test case: both branches initialize, but one raises after\n# This SHOULD be valid - if branch initializes and completes normally\nclass TestClass(object):\n    x: int\n\n    def __init__(self):\n        condition = True\n        if condition:\n            self.x = 1\n        else:\n            self.x = 2\n            raise ValueError(\"After assignment\")\n\nactor main(env):\n    t = TestClass()\n    env.exit(0)"
  },
  {
    "path": "compiler/lib/test/src/class_init_attrs/init_conditional.act",
    "content": "class TestClass(object):\n    x: int\n    def __init__(self, cond: bool=True):\n        self.x = 1 if cond else 0\n\nactor main(env):\n    t = TestClass()\n    env.exit(0)\n"
  },
  {
    "path": "compiler/lib/test/src/class_init_attrs/init_constant_condition.act",
    "content": "# Test case: if/else with constant condition - both branches initialize\nclass TestClass(object):\n    x: int\n\n    def __init__(self):\n        if 1 == 1:  # Always true, but compiler doesn't know\n            self.x = 1\n        else:\n            self.x = 2\n\nactor main(env):\n    t = TestClass()\n    env.exit(0)"
  },
  {
    "path": "compiler/lib/test/src/class_init_attrs/init_delete.act",
    "content": "# Test case: delete statement shouldn't stop initialization scanning\nclass TestClass(object):\n    items: list[int]\n    temp: dict[str, int]\n    result: int\n    \n    def __init__(self):\n        self.items = [1, 2, 3, 4, 5]\n        self.temp = {\"a\": 1, \"b\": 2}\n        \n        del self.temp[\"a\"]  # Deleting dict item is OK\n        \n        # This should still be recognized as part of constructor\n        self.result = len(self.items)\n\ndef len(x: list[int]) -> int:\n    NotImplemented\n\nactor main(env):\n    t = TestClass()\n    env.exit(0)\n"
  },
  {
    "path": "compiler/lib/test/src/class_init_attrs/init_elif_raise_after_assignment.act",
    "content": "# Test case: elif branch assigns then raises - should succeed\n# The if and else branches complete normally with x initialized\nclass TestClass(object):\n    x: int\n    \n    def __init__(self, mode: int):\n        if mode == 1:\n            self.x = 1\n        elif mode == 2:\n            raise ValueError(\"After assignment in elif\")\n        else:\n            self.x = 3\n        \n        # Paths: if={x}, elif exits, else={x}\n        # Result: {x}\n\nactor main(env):\n    t = TestClass(1)\n    env.exit(0)\n"
  },
  {
    "path": "compiler/lib/test/src/class_init_attrs/init_except_raise_after_assignment.act",
    "content": "# Test case: except handler assigns then raises - should succeed\n# The try path completes normally with x initialized\nclass TestClass(object):\n    x: int\n    \n    def __init__(self):\n        try:\n            self.x = 1\n            might_raise()\n        except ValueError:\n            self.x = 2\n            raise Exception(\"After assignment in except\")\n        \n        # Paths: try={x}, except exits after assigning\n        # Only try path returns object, and it initializes x\n\ndef might_raise() -> None:\n    pass\n\nactor main(env):\n    t = TestClass()\n    env.exit(0)"
  },
  {
    "path": "compiler/lib/test/src/class_init_attrs/init_function_call.act",
    "content": "# Test case: function calls should be allowed in __init__\n\ndef compute_value(x: int) -> int:\n    return x * 2 + 10\n\nclass TestClass(object):\n    x: int\n    y: int\n    z: int\n    \n    def __init__(self, base: int):\n        # Call to function should be allowed\n        self.x = 3 + compute_value(compute_value(base))\n        \n        result = compute_value(5)\n        self.y = result\n        \n        # Multiple calls\n        self.z = compute_value(self.x) + compute_value(self.y)\n\nactor main(env):\n    t = TestClass(10)\n    print(t.x)  # Should be 30\n    print(t.y)  # Should be 20\n    print(t.z)  # Should be 80\n    env.exit(0)\n"
  },
  {
    "path": "compiler/lib/test/src/class_init_attrs/init_grandparent_call.act",
    "content": "class BaseA:\n    x: int\n    def __init__(self):\n        self.x = 1\n\nclass BaseB(BaseA):\n    y: int\n\nclass TestClass(BaseB):\n    def __init__(self):\n        BaseA.__init__(self)\n        self.y = 1\n\nactor main(env):\n    t = TestClass()\n    env.exit(0)\n"
  },
  {
    "path": "compiler/lib/test/src/class_init_attrs/init_inferred_only.act",
    "content": "class TestClass(object):\n    def __init__(self):\n        self.x = 1\n\nactor main(env):\n    t = TestClass()\n    env.exit(0)\n"
  },
  {
    "path": "compiler/lib/test/src/class_init_attrs/init_inherited.act",
    "content": "class Base(object):\n    x: int\n\nclass TestClass(Base):\n    def __init__(self):\n        self.x = 1\n\nactor main(env):\n    t = TestClass()\n    env.exit(0)\n"
  },
  {
    "path": "compiler/lib/test/src/class_init_attrs/init_loop_break.act",
    "content": "# Test case: break statement in loop shouldn't stop initialization scanning\nclass TestClass(object):\n    values: list[int]\n    result: int\n    \n    def __init__(self):\n        self.values = []\n        \n        # Loop with break shouldn't stop scanning\n        for i in range(10):\n            if i > 5:\n                break  # This should NOT stop constructor scanning\n            self.values.append(i)\n        \n        # This should still be recognized as part of constructor\n        self.result = len(self.values)\n\ndef range(n: int) -> list[int]:\n    NotImplemented\n\ndef len(x: list[int]) -> int:\n    NotImplemented\n\nactor main(env):\n    t = TestClass()\n    env.exit(0)"
  },
  {
    "path": "compiler/lib/test/src/class_init_attrs/init_loop_continue.act",
    "content": "# Test case: continue statement in loop shouldn't stop initialization scanning\nclass TestClass(object):\n    skipped: list[int]\n    processed: list[int]\n    total: int\n    \n    def __init__(self):\n        self.skipped = []\n        self.processed = []\n        \n        # Loop with continue shouldn't stop scanning\n        for i in range(10):\n            if i % 2 == 0:\n                self.skipped.append(i)\n                continue  # This should NOT stop constructor scanning\n            self.processed.append(i)\n        \n        # This should still be recognized as part of constructor\n        self.total = len(self.processed) + len(self.skipped)\n\ndef range(n: int) -> list[int]:\n    NotImplemented\n\ndef len(x: list[int]) -> int:\n    NotImplemented\n\nactor main(env):\n    t = TestClass()\n    env.exit(0)"
  },
  {
    "path": "compiler/lib/test/src/class_init_attrs/init_mixed_parent_self.act",
    "content": "class Base:\n    x: int\n    def __init__(self):\n        self.x = 1\n\nclass Derived(Base):\n    y: int\n    def __init__(self):\n        Base.__init__(self)\n        self.y = 2\n\nd = Derived()\n"
  },
  {
    "path": "compiler/lib/test/src/class_init_attrs/init_multiple.act",
    "content": "class TestClass(object):\n    x: int\n    y: str\n\n    def __init__(self):\n        self.x = 1\n        self.y = 'hello'\n\nactor main(env):\n    t = TestClass()\n    env.exit(0)\n"
  },
  {
    "path": "compiler/lib/test/src/class_init_attrs/init_multiple_except_handlers.act",
    "content": "class TestClass(object):\n    x: int\n    \n    def __init__(self):\n        try:\n            self.x = 1\n            might_raise()  # Could raise ValueError or Exception\n        except ValueError:\n            self.x = 2  # Handler 1 initializes x\n        except Exception:\n            self.x = 3  # Handler 2 also initializes x\n        \n        # All paths (try, handler1, handler2) initialize x\n\ndef might_raise() -> None:\n    pass\n\nactor main(env):\n    t = TestClass()\n    env.exit(0)\n"
  },
  {
    "path": "compiler/lib/test/src/class_init_attrs/init_nested_function.act",
    "content": "# Test case: nested function declarations shouldn't stop initialization\nclass TestClass(object):\n    value: int\n    result: int\n    \n    def __init__(self, x: int):\n        self.value = x\n        \n        # Nested function declaration shouldn't stop scanning\n        def helper(n: int) -> int:\n            return n * 2\n        \n        # This should still be recognized as part of constructor\n        self.result = helper(self.value)\n\nactor main(env):\n    t = TestClass(5)\n    env.exit(0)"
  },
  {
    "path": "compiler/lib/test/src/class_init_attrs/init_nested_function_call.act",
    "content": "# Test case: function calls should be allowed in __init__\n\nclass TestClass(object):\n    x: int\n    y: int\n    z: int\n\n    def __init__(self, base: int):\n        def compute_value(x: int) -> int:\n            return x * 2 + 10\n\n        # Call to function should be allowed\n        self.x = 3 + compute_value(compute_value(base))\n\n        # expressions are fine\n        result = compute_value(5)\n        self.y = result\n\n        # Multiple calls\n        self.z = compute_value(self.x) + compute_value(self.y)\n\nactor main(env):\n    t = TestClass(10)\n    print(t.x)  # Should be 30\n    print(t.y)  # Should be 20\n    print(t.z)  # Should be 80\n    env.exit(0)\n"
  },
  {
    "path": "compiler/lib/test/src/class_init_attrs/init_nested_if.act",
    "content": "# Test case: Nested if statements with all branches initializing attributes\nclass TestClass(object):\n    x: int\n    y: int\n    z: int\n    \n    def __init__(self, mode: int, submode: int):\n        # Complex nested if/elif/else where all paths initialize all attributes\n        if mode == 1:\n            if submode > 0:\n                self.x = 10\n                self.y = 20\n                self.z = 30\n            else:\n                self.x = 11\n                self.y = 21\n                self.z = 31\n        elif mode == 2:\n            self.x = 100\n            if submode == 0:\n                self.y = 200\n                self.z = 300\n            elif submode == 1:\n                self.y = 201\n                self.z = 301\n            else:\n                self.y = 202\n                self.z = 302\n        else:\n            # Default case\n            self.x = 0\n            self.y = 0\n            self.z = 0\n\nactor main(env):\n    t = TestClass(1, 5)\n    env.exit(0)\n"
  },
  {
    "path": "compiler/lib/test/src/class_init_attrs/init_nested_if_raise.act",
    "content": "class Rational(object):\n    def __init__(self, num: int, denom: int):\n        if denom == 0:\n            raise ValueError(\"Denominator in rational is zero\")\n        else:\n            if denom > 0:\n                self.num = num\n                self.denom = denom\n            else:\n                self.num = -num\n                self.denom = -denom\n\nactor main(env):\n    r = Rational(1, 2)\n    print(\"Rational created:\", r.num, \"/\", r.denom)\n    env.exit(0)\n"
  },
  {
    "path": "compiler/lib/test/src/class_init_attrs/init_no_init_uses_parent.act",
    "content": "class Base:\n    x: int\n    def __init__(self):\n        self.x = 1\n\nclass TestClass(Base):\n    pass\n\nactor main(env):\n    t = TestClass()\n    env.exit(0)\n"
  },
  {
    "path": "compiler/lib/test/src/class_init_attrs/init_notimpl_call.act",
    "content": "# Test case: Calling self methods with NotImplemented body is allowed\nclass TestClass(object):\n    x: int\n    y: int\n\n    def __init__(self):\n        # Calling a NotImplemented method on self should be allowed since it's\n        # implemented in C and thus trusted to do the right thing.\n        self.setup()\n        self.x = 1\n        self.y = 2\n\n    def setup(self):\n        NotImplemented\n\nactor main(env):\n    t = TestClass()\n    env.exit(0)\n"
  },
  {
    "path": "compiler/lib/test/src/class_init_attrs/init_notimplemented.act",
    "content": "class TestClass(object):\n    x: int\n    def __init__(self):\n        NotImplemented\n\nactor main(env):\n    t = TestClass()\n    env.exit(0)\n"
  },
  {
    "path": "compiler/lib/test/src/class_init_attrs/init_parent_call.act",
    "content": "class Base:\n    x: int\n    def __init__(self):\n        self.x = 1\n\nclass TestClass(Base):\n    def __init__(self):\n        Base.__init__(self)\n\nactor main(env):\n    t = TestClass()\n    env.exit(0)\n"
  },
  {
    "path": "compiler/lib/test/src/class_init_attrs/init_raise_after_assignment.act",
    "content": "# Test case: if/else where else branch has assignment followed by raise\n# This should SUCCEED - the if branch completes normally with x initialized,\n# and the else branch exits early (so it doesn't constrain initialization)\nclass TestClass(object):\n    x: int\n\n    def __init__(self):\n        if 1 == 1:  # Always true\n            self.x = 1\n        else:\n            self.x = 2\n            raise ValueError(\"This comes after assignment\")\n\nactor main(env):\n    t = TestClass()\n    env.exit(0)"
  },
  {
    "path": "compiler/lib/test/src/class_init_attrs/init_self_attr_access.act",
    "content": "# Test case: Accessing already-initialized attributes should be allowed\nclass TestClass(object):\n    x: int\n    y: int\n    z: int\n    \n    def __init__(self):\n        self.x = 10\n        self.y = self.x * 2  # OK: x is already initialized\n        self.z = self.x + self.y  # OK: both x and y are initialized\n\nactor main(env):\n    t = TestClass()\n    env.exit(0)"
  },
  {
    "path": "compiler/lib/test/src/class_init_attrs/init_self_attr_conditional.act",
    "content": "# Test case: Using initialized attributes in conditional branches\nclass TestClass(object):\n    base: int\n    value: int\n    doubled: int\n    \n    def __init__(self, mode: int):\n        self.base = 10\n        \n        if mode > 0:\n            self.value = self.base * mode  # OK: base is initialized\n        else:\n            self.value = self.base  # OK: base is initialized\n        \n        # At this point, both base and value are guaranteed initialized\n        self.doubled = self.value * 2  # OK: value is initialized from all paths\n\nactor main(env):\n    t = TestClass(5)\n    env.exit(0)"
  },
  {
    "path": "compiler/lib/test/src/class_init_attrs/init_self_attr_in_expr.act",
    "content": "# Test case: Using initialized attributes in complex expressions\nclass TestClass(object):\n    items: list[int]\n    total: int\n    average: float\n    description: str\n    \n    def __init__(self):\n        self.items = [1, 2, 3, 4, 5]\n        self.total = sum(self.items)  # OK: items is initialized\n        self.average = float(self.total) / float(len(self.items))  # OK: total and items initialized\n        self.description = \"Average is: \" + str(self.average)  # OK: average is initialized\n\ndef sum(items: list[int]) -> int:\n    total = 0\n    for i in items:\n        total = total + i\n    return total\n\ndef float(x: int) -> float:\n    NotImplemented\n\ndef len(items: list[int]) -> int:\n    NotImplemented\n\nactor main(env):\n    t = TestClass()\n    env.exit(0)"
  },
  {
    "path": "compiler/lib/test/src/class_init_attrs/init_self_attr_in_loop.act",
    "content": "# Test case: Using initialized attribute in a loop\nclass TestClass(object):\n    multiplier: int\n    values: list[int]\n    \n    def __init__(self):\n        self.multiplier = 2\n        self.values = []\n        \n        # Loop that uses initialized attribute\n        for i in range(5):\n            self.values.append(i * self.multiplier)  # OK: multiplier is initialized\n\ndef range(n: int) -> list[int]:\n    NotImplemented\n\nactor main(env):\n    t = TestClass()\n    env.exit(0)"
  },
  {
    "path": "compiler/lib/test/src/class_init_attrs/init_self_attr_reference.act",
    "content": "# Test case: References to self.attr should be allowed when attr is initialized\n\ndef compute(x: int) -> int:\n    return x * 2 + 10\n\nclass TestClass(object):\n    x: int\n    y: int\n    z: int\n    w: int\n    \n    def __init__(self):\n        # Initialize x first\n        self.x = 5\n        \n        # This should be allowed - self.x is already initialized\n        self.y = compute(self.x)\n        \n        # Multiple references to initialized attributes\n        self.z = self.x + self.y\n        \n        # Even in complex expressions\n        self.w = compute(self.x) + compute(self.y) + self.z\n\nactor main(env):\n    t = TestClass()\n    print(t.x)  # 5\n    print(t.y)  # 20\n    print(t.z)  # 25\n    print(t.w)  # 65\n    env.exit(0)"
  },
  {
    "path": "compiler/lib/test/src/class_init_attrs/init_try_else_combined.act",
    "content": "# Test case: try/else where all paths initialize everything\nclass TestClass(object):\n    x: int\n    y: int\n\n    def __init__(self):\n        try:\n            # This doesn't raise, so we continue to else\n            self.x = safe_operation()\n        except ValueError:\n            # Exception path: initialize both\n            self.x = 1\n            self.y = 2\n        else:\n            # No exception path: continues from try\n            # x is already set in try, now set y\n            self.y = 3\n        # Both paths initialize x and y!\n        # Path 1 (no exception): try sets x, else sets y\n        # Path 2 (exception): except sets both x and y\n\ndef safe_operation() -> int:\n    return 42\n\nactor main(env):\n    t = TestClass()\n    env.exit(0)"
  },
  {
    "path": "compiler/lib/test/src/class_init_attrs/init_try_except.act",
    "content": "class TestClass(object):\n    x: int\n    y: int\n\n    def __init__(self):\n        try:\n            self.x = risky_operation()\n            self.y = 2\n        except:\n            self.x = 1\n            self.y = 2\n\ndef risky_operation() -> int:\n    return 42\n\nactor main(env):\n    t = TestClass()\n    print(\"x =\", t.x, \"y =\", t.y)\n    env.exit(0)\n"
  },
  {
    "path": "compiler/lib/test/src/class_init_attrs/init_try_except_finally.act",
    "content": "# Test case: Complex try/except/finally with mixed initialization\nclass TestClass(object):\n    a: int\n    b: int\n    c: int\n    d: int\n    e: int\n    \n    def __init__(self, mode: int):\n        # Initialize before try\n        self.a = 1\n        \n        try:\n            if mode > 0:\n                self.b = 10\n                self.c = risky_op(mode)\n            else:\n                self.b = 11\n                self.c = 12\n        except:\n            # Exception handler must also init b and c\n            self.b = 0\n            self.c = 0\n        finally:\n            # Finally always runs\n            self.d = 100\n        \n        # After try/finally\n        self.e = self.a + self.b + self.c + self.d\n\ndef risky_op(x: int) -> int:\n    if x > 100:\n        raise ValueError(\"Too big!\")\n    return x * 2\n\nactor main(env):\n    t1 = TestClass(5)\n    print(\"Normal:\", t1.a, t1.b, t1.c, t1.d, t1.e)\n    env.exit(0)"
  },
  {
    "path": "compiler/lib/test/src/class_init_attrs/init_try_except_raise.act",
    "content": "# Test case: Try-except blocks\nclass TestClass(object):\n    x: int\n    y: int\n\n    def __init__(self):\n        try:\n            self.x = risky_operation()\n            self.y = 1\n        except ValueError:\n            # We're catching all errors and throwing our own. This will raise an\n            # error, so y will not be initialized but that's OK since we are\n            # terminating and not returning an object.\n            raise ValueError(\"An error occurred\")\n\ndef risky_operation() -> int:\n    return 42\n\nactor main(env):\n    t = TestClass()\n    env.exit(0)\n"
  },
  {
    "path": "compiler/lib/test/src/class_init_attrs/init_try_finally.act",
    "content": "# Test case: Finally block always executes so assignments there count\nclass TestClass(object):\n    x: int\n    y: int\n    \n    def __init__(self):\n        try:\n            self.x = risky_operation()\n            self.y = 1\n        finally:\n            self.x = 1\n            self.y = 2\n\ndef risky_operation() -> int:\n    return 42\n\nactor main(env):\n    t = TestClass()\n    print(\"x =\", t.x, \"y =\", t.y)\n    env.exit(0)\n"
  },
  {
    "path": "compiler/lib/test/src/class_init_attrs/init_try_inside_if.act",
    "content": "# Test case: try/except nested inside if/else\nclass TestClass(object):\n    x: int\n    \n    def __init__(self, mode: int):\n        if mode > 0:\n            try:\n                self.x = 1\n                might_raise()\n            except:\n                self.x = 2\n        else:\n            self.x = 3\n        \n        # All paths through if/else initialize x\n\ndef might_raise() -> None:\n    pass\n\nactor main(env):\n    t = TestClass(1)\n    env.exit(0)"
  },
  {
    "path": "compiler/lib/test/src/class_init_attrs/uninit_assert_uninit_attr.act",
    "content": "# Test case: assert that references uninitialized attribute should fail\nclass TestClass(object):\n    value: int\n    result: int\n    \n    def __init__(self, x: int):\n        self.value = x\n        \n        # Assert that references uninitialized self.result - should fail!\n        assert self.result > 0, \"result must be positive\"\n        \n        # This should NOT be recognized as initialized\n        self.result = 42\n\nactor main(env):\n    t = TestClass(5)\n    env.exit(0)"
  },
  {
    "path": "compiler/lib/test/src/class_init_attrs/uninit_augmented_assign.act",
    "content": "class TestClass(object):\n    x: int\n    \n    def __init__(self):\n        self.x += 1  # Should fail - x not initialized before augmented assignment\n"
  },
  {
    "path": "compiler/lib/test/src/class_init_attrs/uninit_basic.act",
    "content": "class TestClass(object):\n    x: int\n    def __init__(self):\n        pass\n\nactor main(env):\n    t = TestClass()\n    env.exit(0)\n"
  },
  {
    "path": "compiler/lib/test/src/class_init_attrs/uninit_basic_inferred.act",
    "content": "class TestClass(object):\n    def __init__(self):\n        if False:\n            self.x = 1  # Should fail - x not initialized before use\n\nactor main(env):\n    t = TestClass()\n    env.exit(0)\n"
  },
  {
    "path": "compiler/lib/test/src/class_init_attrs/uninit_elif_missing.act",
    "content": "# Test case: if-elif without else\nclass TestClass(object):\n    x: int\n    \n    def __init__(self, mode: int):\n        if mode == 1:\n            self.x = 1\n        elif mode == 2:\n            self.x = 2\n        # No else - x not initialized for other values\n\nactor main(env):\n    env.exit(0)"
  },
  {
    "path": "compiler/lib/test/src/class_init_attrs/uninit_for_loop.act",
    "content": "# Test case: Break/continue in loops affecting initialization\nclass TestClass(object):\n    x: int\n    y: int\n    \n    def __init__(self, items: list[int]):\n        self.x = 1\n        for item in items:\n            if item == 0:\n                break\n            self.y = item  # Might not execute if we break early or items is empty\n\nactor main(env):\n    t = TestClass([1, 2, 0, 3])  # y will be set to 2\n    env.exit(0)\n"
  },
  {
    "path": "compiler/lib/test/src/class_init_attrs/uninit_grandparent.act",
    "content": "class BaseA:\n    x: int\n\nclass BaseB(BaseA):\n    y: int\n\nclass TestClass(BaseB):\n    def __init__(self):\n        self.y = 1\n\nactor main(env):\n    t = TestClass()\n    env.exit(0)\n"
  },
  {
    "path": "compiler/lib/test/src/class_init_attrs/uninit_grandparent2.act",
    "content": "class BaseA:\n    x: int\n    def __init__(self):\n        self.x = 1\n\nclass BaseB(BaseA):\n    y: int\n\n    def __init__(self):\n        BaseA.__init__(self)\n        self.y = 1\n\nclass TestClass(BaseB):\n    def __init__(self):\n        BaseA.__init__(self)\n        # Should get a failure since y is not initialized\n\nactor main(env):\n    t = TestClass()\n    env.exit(0)\n"
  },
  {
    "path": "compiler/lib/test/src/class_init_attrs/uninit_inherited.act",
    "content": "class Base:\n    x: int\n\nclass TestClass(Base):\n    def __init__(self):\n        pass\n\nactor main(env):\n    t = TestClass()\n    env.exit(0)\n"
  },
  {
    "path": "compiler/lib/test/src/class_init_attrs/uninit_init_in_method.act",
    "content": "# Test case: Initialization in another method called from __init__\n# Should fail because we don't allow calling any methods in init constructor\nclass TestClass(object):\n    x: int\n    \n    def __init__(self):\n        self.setup()\n    \n    def setup(self):\n        self.x = 1\n\nactor main(env):\n    t = TestClass()\n    env.exit(0)\n"
  },
  {
    "path": "compiler/lib/test/src/class_init_attrs/uninit_loop_references_self.act",
    "content": "# Test case: Loop that references self - must stop scanning\nclass TestClass(object):\n    x: int\n    y: int\n\n    def __init__(self):\n        # Loop that references self - not safe to continue\n        for i in range(10):\n            process(self)  # Leaks self reference!\n        # These assignments are after the loop but we can't reach them\n        # because the loop leaked self\n        self.x = 1\n        self.y = 2\n\ndef range(n: int) -> list[int]:\n    return []\n\ndef process(obj: TestClass) -> None:\n    pass\n\nactor main(env):\n    t = TestClass()\n    env.exit(0)"
  },
  {
    "path": "compiler/lib/test/src/class_init_attrs/uninit_method_call.act",
    "content": "# Test case: Method calls on self should stop scanning. We are in the\n# constructor, so `self` is not initialized yet and we can't track down what the\n# method is doing exactly.\n\nclass TestClass(object):\n    x: int\n    y: int\n    counter: int\n\n    def __init__(self):\n        self.counter = 0\n        self.x = 1\n        self.helper()  # Method call on self - scanner should stop here\n        self.y = 2  # Not reached by scanner\n\n    mut def helper(self):\n        self.counter += 1\n\nactor main(env):\n    t = TestClass()\n    env.exit(0)\n"
  },
  {
    "path": "compiler/lib/test/src/class_init_attrs/uninit_method_call_assign.act",
    "content": "# Test case: Method calls on self should stop scanning. We are in the\n# constructor, so `self` is not initialized yet, the method has access to self,\n# but we can't track what it is doing exactly.\n# We *could* potentially allow pure methods...\n\nclass TestClass(object):\n    pi: int\n    x: int\n    y: int\n    counter: int\n    \n    def __init__(self):\n        self.counter = 0\n        self.x = 1\n        self.pi = self.pure_helper()\n        self.y = 2  # Not reached by scanner\n    \n    def pure_helper(self):\n        return 3.14\n\nactor main(env):\n    t = TestClass()\n    env.exit(0)\n"
  },
  {
    "path": "compiler/lib/test/src/class_init_attrs/uninit_method_reference.act",
    "content": "# Test case: Passing self.method as argument should stop initialization scanning\n# This should fails - self._on_event is a bound method that  captures self, so\n# it's considered a leak of self\nclass Callback(object):\n    def __init__(self, callback):\n        pass\n\nclass TestClass(object):\n    handler: Callback\n    value: int\n    \n    def __init__(self):\n        # This should work - we're just passing a method reference\n        # But currently the compiler sees self._on_event as leaking self\n        self.handler = Callback(self._on_event)\n        self.value = 42  # This won't be seen as initialized\n    \n    def _on_event(self):\n        pass\n\nactor main(env):\n    t = TestClass()\n    env.exit(0)\n"
  },
  {
    "path": "compiler/lib/test/src/class_init_attrs/uninit_nested_function_escape.act",
    "content": "# Test case: nested function that captures uninitialized self attributes\nclass TestClass(object):\n    value: int\n    result: int\n    \n    def __init__(self, x: int):\n        self.value = x\n        \n        # Nested function that captures self with uninitialized attribute\n        def get_result() -> int:\n            return self.result  # References uninitialized self.result!\n        \n        # Pass the function externally (self escapes via closure)\n        register(get_result)\n        \n        # This won't be recognized as initialized (self escaped)\n        self.result = 42\n\ndef register(f: () -> int):\n    pass\n\nactor main(env):\n    t = TestClass(5)\n    env.exit(0)"
  },
  {
    "path": "compiler/lib/test/src/class_init_attrs/uninit_nested_function_with_self.act",
    "content": "# Test case: nested function that captures self stops initialization scanning\nclass TestClass(object):\n    value: int\n    result: int\n    \n    def __init__(self, x: int):\n        self.value = x\n        \n        # Nested function that captures self - stops scanning\n        def get_value() -> int:\n            return self.value  # References self (even though value is initialized)\n        \n        # The nested function captured self, so we conservatively stop scanning\n        # This will NOT be seen as initialized\n        self.result = 42\n\nactor main(env):\n    t = TestClass(5)\n    env.exit(0)"
  },
  {
    "path": "compiler/lib/test/src/class_init_attrs/uninit_nested_if.act",
    "content": "# Test case: Nested if statements\nclass TestClass(object):\n    x: int\n    y: int\n    \n    def __init__(self, a: bool, b: bool):\n        if a:\n            if b:\n                self.x = 1\n                self.y = 1\n            else:\n                self.x = 2\n                # Missing y in this path\n        else:\n            self.x = 3\n            self.y = 3\n\nactor main(env):\n    env.exit(0)\n"
  },
  {
    "path": "compiler/lib/test/src/class_init_attrs/uninit_no_parent_init.act",
    "content": "class Base:\n    x: int\n\nclass TestClass(Base):\n    def __init__(self):\n        Base.__init__(self)\n\nactor main(env):\n    t = TestClass()\n    env.exit(0)\n"
  },
  {
    "path": "compiler/lib/test/src/class_init_attrs/uninit_notimpl_call_other.act",
    "content": "# Test case: Calling self methods with NotImplemented body is allowed but here\n# we also call .setup2() which is implemented here and it is NOT allowed, thus\n# we expect an error about self.y not being initialized.\nclass TestClass(object):\n    x: int\n    y: int\n\n    def __init__(self):\n        # Calling a NotImplemented method on self should be allowed since it's\n        # implemented in C and thus trusted to do the right thing.\n        self.setup()\n        self.x = 1\n        self.setup2()\n        self.y = 2\n\n    def setup(self):\n        NotImplemented\n\n    def setup2(self):\n        pass\n\nactor main(env):\n    t = TestClass()\n    env.exit(0)\n"
  },
  {
    "path": "compiler/lib/test/src/class_init_attrs/uninit_partial.act",
    "content": "class TestClass(object):\n    x: int\n    y: str\n    def __init__(self):\n        self.x = 1\n\nactor main(env):\n    t = TestClass()\n    env.exit(0)\n"
  },
  {
    "path": "compiler/lib/test/src/class_init_attrs/uninit_return_early.act",
    "content": "# Test case: Early return doesn't excuse initialization\nclass TestClass(object):\n    x: int\n    y: int\n    \n    def __init__(self, quick_exit: bool):\n        if quick_exit:\n            self.x = 0\n            return  # Early return - but y is still uninitialized!\n        else:\n            self.x = 1\n            self.y = 2\n\nactor main(env):\n    env.exit(0)"
  },
  {
    "path": "compiler/lib/test/src/class_init_attrs/uninit_self_attr_access.act",
    "content": "# Test case: Accessing uninitialized attribute should fail\nclass TestClass(object):\n    x: int\n    y: int\n    \n    def __init__(self):\n        self.x = self.y * 2  # ERROR: y is not initialized yet!\n        self.y = 10\n\nactor main(env):\n    t = TestClass()\n    env.exit(0)"
  },
  {
    "path": "compiler/lib/test/src/class_init_attrs/uninit_self_in_list.act",
    "content": "# Test case: Self references in data structures should stop scanning\n\ndef do_something(l):\n    return 1\n\nclass TestClass(object):\n    x: int\n    y: int\n\n    def __init__(self):\n        self.x = 1\n        \n        # Direct reference to self - stop scanning here\n        # We don't actually know if objects how objects is used or if it even is\n        # used, but that is untractable to analyze, so we stop analyzing at any\n        # point where self is referenced.\n        objects = [self, self]\n        # This won't be scanned, so y will be considered uninitialized\n        self.y = do_something(objects)\n\nactor main(env):\n    t = TestClass()\n    env.exit(0)\n"
  },
  {
    "path": "compiler/lib/test/src/class_init_attrs/uninit_self_reference.act",
    "content": "# Test case: Direct references to self should stop scanning\n# This ensures we don't pass incomplete objects around\n\ndef external_func(obj):\n    # This function might access obj which is not fully initialized when this\n    # function is called\n    return obj.x * 2\n\nclass TestClass(object):\n    x: int\n    y: int\n    z: int\n    \n    def __init__(self):\n        self.x = 1\n        \n        # This should stop scanning because we're passing self\n        result = external_func(self)  \n        \n        # These won't be scanned, so z will be reported as uninitialized\n        self.y = result\n        self.z = 3\n\nactor main(env):\n    t = TestClass()\n    env.exit(0)\n"
  },
  {
    "path": "compiler/lib/test/src/class_init_attrs/uninit_try_except.act",
    "content": "# Test case: Try-except blocks\nclass TestClass(object):\n    x: int\n    y: int\n\n    def __init__(self):\n        try:\n            self.x = risky_operation()\n            self.y = 1\n        except:\n            self.x = 0\n            # y not initialized in except block\n\ndef risky_operation() -> int:\n    return 42\n\nactor main(env):\n    t = TestClass()\n    env.exit(0)\n"
  },
  {
    "path": "compiler/lib/test/src/cps_andor.act",
    "content": "proc def p() -> bool:\n    return True\n\ndef f(b: bool) -> bool:\n    return b and p()\n\ndef g(b: bool) -> bool:\n    return b or p()\n"
  },
  {
    "path": "compiler/lib/test/src/cps_optchain.act",
    "content": "class Cls:\n    proc def f(self, msg: str):\n        pass\n\ndef maybe_log(c: ?Cls):\n    c?.f(\"boom\")\n"
  },
  {
    "path": "compiler/lib/test/src/cps_volatiles.act",
    "content": "proc def force_cps(arg: int):\n    return arg\n\ndef compute(aa: int) -> int:\n    xx = 1\n    try:\n        xx += force_cps(1)\n        aa += force_cps(1)\n    except ValueError:\n        pass\n    return xx + aa\n\nactor main(env):\n    v = compute(10)\n    if v == 13:\n        env.exit(0)\n    else:\n        print('Excpected 13, got', v)\n        env.exit(1)\n"
  },
  {
    "path": "compiler/lib/test/src/deact.act",
    "content": "actor Apa():\n    def setup(cb):\n        print(\"setup\")\n        cb(0)\n    def compute(cb):\n        print(\"compute\")\n        v = cb(1)\n        m = async cb(2)\n        return v*10\n    def notice(i):\n        print(\"notice\")\n        return i+1\n\n    setup(notice)\n    print(\"Apa\")\n\nactor Bepa():\n    def callback(i):\n        print(\"callback\", i)\n        return i+1\n    print(\"Bepa\")\n\nactor main(env):\n    def myproc(i):\n        print(\"myproc\", i)\n        if i == 2:\n            env.exit(0)\n        return i\n    a = Apa()\n    b = Bepa()\n    print(\"-----\")\n    a.setup(a.notice)\n    x = async a.compute(b.callback)\n    r = await x\n    print(\"r =\", r)\n    a.compute(myproc)\n    print(\"main\")\n"
  },
  {
    "path": "compiler/lib/test/src/deact_from_import.act",
    "content": "from deact import Apa\n\nactor Manager():\n    def create_decoder() -> StringDecoder:\n        decoder = StringDecoder(self.decode_callback)\n        return decoder\n\n    def create_apa() -> Apa:\n        apa = Apa()\n        return apa\n\n    def decode_callback(s: str) -> None:\n        pass\n\nactor main(env):\n    mgr = Manager()\n    decoder = mgr.create_decoder()\n    apa = mgr.create_apa()\n    env.exit(0)\n"
  },
  {
    "path": "compiler/lib/test/src/docstrings.act",
    "content": "\"\"\"Test module for docstring functionality with {braces}.\"\"\"\n\nimport math\n\n# Basic functionality tests\ndef test_function(x: int) -> int:\n    \"\"\"Test function with docstring.\"\"\"\n    return x * 2\n\ndef no_docstring_function(x: int) -> int:\n    return x * 3\n\nclass TestClass:\n    \"\"\"Test class with docstring.\"\"\"\n    def method(self, x: int) -> int:\n        return x + 1\n\nactor TestActor(name: str):\n    \"\"\"Test actor with docstring.\"\"\"\n    var name = name\n\nprotocol TestProtocol:\n    \"\"\"Test protocol with docstring.\"\"\"\n    test_method: (int) -> int\n\nextension TestClass(TestProtocol):\n    \"\"\"Extension with docstring.\"\"\"\n    def test_method(self, x: int) -> int:\n        return x * 10\n\n# Edge case tests\ndef function_with_non_first_string(x: int) -> int:\n    y = x + 1\n    \"Not a docstring\"\n    return y\n\ndef function_with_multiple_strings(x: int) -> int:\n    \"\"\"First string is docstring.\"\"\"\n    \"Second string is not\"\n    return x\n\ndef function_with_f_prefix_docstring() -> int:\n    f\"Not a docstring {1}\"\n    return 1\n\ndef function_with_single_quotes(x: int) -> int:\n    'Single quote docstring'\n    return x\n\ndef function_with_triple_single_quotes(x: int) -> int:\n    '''Triple quote docstring'''\n    return x\n\ndef function_with_mixed_quotes(x: int) -> int:\n    \"\"\"Mixed 'quotes' in docstring\"\"\"\n    return x\n\ndef function_with_braces_docstring():\n    \"\"\"Docstring with {braces} should not interpolate.\"\"\"\n    pass\n\ndef function_empty_docstring():\n    \"\"\"\"\"\"\n    pass\n\ndef function_with_control_flow():\n    if True:\n        \"Not a docstring\"\n    return 42\n\ndef function_just_docstring():\n    \"\"\"Just a docstring, no code.\"\"\"\n"
  },
  {
    "path": "compiler/lib/test/src/foo.act",
    "content": "\"\"\"Foo module - demonstrates cross-module type usage\n\nThis module extensively uses types from the bar module\nto demonstrate documentation of cross-module references.\n\"\"\"\n\nimport bar\n\n# Module constants\nDEFAULT_PREFIX: str = \"AUTO_\"\n# Default prefix for auto-generated labels\n\n# Functions using bar.Data\ndef create_data(value: str) -> bar.Data:\n    \"\"\"Create a new Data instance\n\n    Args:\n        value: Value for the data\n\n    Returns:\n        A new bar.Data instance with auto-generated label\n\n    Examples:\n        >>> d = create_data(\"test\")\n        >>> d.get_value()\n        \"test\"\n    \"\"\"\n    return bar.Data(value, DEFAULT_PREFIX + str(len(value)))\n\ndef transform_data(d: bar.Data, f: (str) -> str) -> bar.Data:\n    \"\"\"Transform data by applying function to its value\n\n    Args:\n        d: Data object to transform\n        f: Transformation function\n\n    Returns:\n        New bar.Data with transformed value\n\n    See Also:\n        bar.process_data: For simple processing\n        bar.combine_data: For combining multiple data objects\n    \"\"\"\n    new_value = f(d.get_value())\n    return bar.Data(new_value, d.label + \"_transformed\")\n\ndef analyze_multiple(data_list: list[bar.Data]) -> dict[str, int]:\n    \"\"\"Analyze multiple data objects\n\n    Args:\n        data_list: List of bar.Data objects\n\n    Returns:\n        Statistics about the data\n\n    Raises:\n        ValueError: If list is empty\n    \"\"\"\n    if len(data_list) == 0:\n        raise ValueError(\"Cannot analyze empty list\")\n\n    total_length = 0\n    total_accesses = 0\n\n    for d in data_list:\n        total_length += len(d.value)\n        total_accesses += d.count\n\n    return {\n        \"count\": len(data_list),\n        \"total_length\": total_length,\n        \"total_accesses\": total_accesses\n    }\n\n# Class that uses bar.Data\nclass DataManager(object):\n    \"\"\"Manages a collection of bar.Data objects\n\n    This class provides high-level operations on collections\n    of Data objects from the bar module.\n    \"\"\"\n    storage: list[bar.Data]\n    default: bar.Data\n    name: str\n\n    def __init__(self, name: str):\n        \"\"\"Initialize manager\n\n        Args:\n            name: Name for this manager\n        \"\"\"\n        self.storage = []\n        self.default = bar.Data(\"\", \"empty\")\n        self.name = name\n\n    def add_data(self, d: bar.Data):\n        \"\"\"Add a data object to storage\n\n        Args:\n            d: bar.Data object to add\n\n        Raises:\n            ValueError: If storage is full\n        \"\"\"\n        if len(self.storage) >= bar.MAX_ITEMS:\n            raise ValueError(\"Storage is full\")\n        self.storage.append(d)\n\n    def find_by_label(self, label: str) -> ?bar.Data:\n        \"\"\"Find first data with matching label\n\n        Args:\n            label: Label to search for\n\n        Returns:\n            Matching bar.Data or None if not found\n        \"\"\"\n        for item in self.storage:\n            if item.label == label:\n                return item\n        return None\n\n    def get_or_default(self, label: str) -> bar.Data:\n        \"\"\"Get data by label or return default\n\n        Args:\n            label: Label to search for\n\n        Returns:\n            Found bar.Data or the default instance\n        \"\"\"\n        found = self.find_by_label(label)\n        if found is not None:\n            return found\n        return self.default\n\n    def transform_all(self, f: (bar.Data) -> bar.Data) -> list[bar.Data]:\n        \"\"\"Transform all stored data\n\n        Args:\n            f: Transformation function\n\n        Returns:\n            List of transformed bar.Data objects\n        \"\"\"\n        result = []\n        for d in self.storage:\n            result.append(f(d))\n        return result\n\n# Function that works with bar types\ndef process_with_prefix(d: bar.Data, prefix: str) -> bar.Data:\n    \"\"\"Process data with a prefix\n\n    Args:\n        d: Data to process\n        prefix: Prefix to add to data values\n\n    Returns:\n        New bar.Data with prefixed value\n    \"\"\"\n    new_value = prefix + d.value\n    return bar.Data(new_value, d.label + \"_prefixed\")\n\n# Actor using bar types\nactor DataHandler(initial: bar.Data):\n    \"\"\"Actor that handles bar.Data objects\n\n    Args:\n        initial: Initial bar.Data to store\n    \"\"\"\n    var current: bar.Data = initial\n    var history: list[bar.Data] = [initial]\n    var processor: ?bar.DataProcessor = None\n\n    def update(new_data: bar.Data):\n        \"\"\"Update current data\n\n        Args:\n            new_data: New bar.Data to set as current\n        \"\"\"\n        current = new_data\n        history.append(new_data)\n\n    def get_current() -> bar.Data:\n        \"\"\"Get current data\n\n        Returns:\n            Current bar.Data instance\n        \"\"\"\n        return current\n\n    def transform_with(f: (bar.Data) -> bar.Data) -> bar.Data:\n        \"\"\"Transform current data\n\n        Args:\n            f: Transformation function\n\n        Returns:\n            Transformed bar.Data\n        \"\"\"\n        new_data = f(current)\n        update(new_data)\n        return new_data\n\n    def combine_with(other: bar.Data) -> bar.Data:\n        \"\"\"Combine current with another data\n\n        Args:\n            other: bar.Data to combine with\n\n        Returns:\n            Combined bar.Data using bar.combine_data\n        \"\"\"\n        combined = bar.combine_data(current, other)\n        update(combined)\n        return combined\n\n    def send_to_processor(p: bar.DataProcessor):\n        \"\"\"Send current data to a processor\n\n        Args:\n            p: bar.DataProcessor to send to\n        \"\"\"\n        processor = p\n        p.enqueue(current)\n\n    def get_history() -> list[bar.Data]:\n        \"\"\"Get full history of data\n\n        Returns:\n            List of all bar.Data objects in history\n        \"\"\"\n        return history\n\n# Higher-order functions with bar types\ndef apply_transformation(d: bar.Data, transform: (str) -> str) -> bar.Data:\n    \"\"\"Apply transformation to bar.Data value\n\n    Args:\n        d: Data to transform\n        transform: Function to apply to value\n\n    Returns:\n        New bar.Data with transformed value\n    \"\"\"\n    new_value = transform(d.value)\n    return bar.Data(new_value, d.label + \"_transformed\")\n\ndef apply_to_list(items: list[bar.Data], f: (bar.Data) -> str) -> list[str]:\n    \"\"\"Apply function to all items in list\n\n    Args:\n        items: List of bar.Data objects\n        f: Function to apply\n\n    Returns:\n        List of results\n    \"\"\"\n    result = []\n    for item in items:\n        result.append(f(item))\n    return result\n\n# Complex type signatures\ndef process_nested(data: list[(str, bar.Data)]) -> dict[str, list[bar.Data]]:\n    \"\"\"Process nested data structures\n\n    Args:\n        data: List of tuples containing keys and bar.Data\n\n    Returns:\n        Dictionary grouping bar.Data by key\n    \"\"\"\n    result: dict[str, list[bar.Data]] = {}\n    for key, d in data:\n        if key not in result:\n            result[key] = []\n        result[key].append(d)\n    return result\n\n# Main actor demonstrating usage\nactor main(env):\n    \"\"\"Main actor demonstrating bar module usage\"\"\"\n\n    # Create and use bar.Data\n    d1 = bar.Data(\"hello\", \"greeting\")\n    d2 = create_data(\"world\")\n    d3 = bar.combine_data(d1, d2)\n\n    print(\"Data 1:\", d1.get_info())\n    print(\"Data 2:\", d2.get_info())\n    print(\"Combined:\", d3.get_info())\n\n    # Use list instead of container for simplicity\n    data_list = [d1, d2, d3]\n\n    # Filter long values\n    long_values = []\n    for d in data_list:\n        if len(d.value) > 5:\n            long_values.append(d.value)\n    print(\"Long values:\", long_values)\n\n    # Use DataManager\n    manager = DataManager(\"test_manager\")\n    manager.add_data(d1)\n    manager.add_data(d2)\n\n    found = manager.find_by_label(\"greeting\")\n    if found is not None:\n        print(\"Found:\", found.get_value())\n\n    # Use actors\n    handler = DataHandler(d1)\n    handler.update(d2)\n    handler.combine_with(d3)\n\n    processor = bar.DataProcessor()\n    handler.send_to_processor(processor)\n\n    # Process some data\n    processor.enqueue(d1)\n    processor.enqueue(d2)\n    processed = processor.process_next()\n    if processed is not None:\n        print(\"Processed:\", processed.get_info())\n\n    print(\"Processor stats:\", processor.get_stats())\n\n    # Use transformation functions\n    transformed = process_with_prefix(d1, \"PREFIX_\")\n    print(\"Transformed:\", transformed.get_info())\n\n    # Complex operations\n    items = [(\"key1\", d1), (\"key2\", d2), (\"key1\", d3)]\n    grouped = process_nested(items)\n    print(\"Grouped count:\", len(grouped))\n\n    # Use protocol functionality\n    processed_results = bar.process_items([d1, d2, d3])\n    print(\"Processed via protocol:\", processed_results)\n\n    # Check metadata\n    meta = d1.get_metadata()\n    print(\"Metadata:\", meta)\n\n    env.exit(0)\n"
  },
  {
    "path": "compiler/lib/test/src/import_private.act",
    "content": "from import_private_a import *\n\nactor main(env):\n    print(__foo)\n    print(public_value)\n    env.exit(0)\n"
  },
  {
    "path": "compiler/lib/test/src/import_private_a.act",
    "content": "__foo: int = 1\npublic_value: int = 2\n"
  },
  {
    "path": "compiler/lib/test/src/import_private_qualified.act",
    "content": "import import_private_a\n\nactor main(env):\n    print(import_private_a.__foo)\n    env.exit(0)\n"
  },
  {
    "path": "compiler/lib/test/src/ints.act",
    "content": "int64_min: int = -9223372036854775808\nint64_max: int = 9223372036854775807\n\nint32_min: i32 = -2147483648\nint32_max: i32 = 2147483647\n\nint16_min: i16 = -32768\nint16_max: i16 = 32767\n\nint8_min: i8 = -128\nint8_max: i8 = 127\n\n\nuint64_min: u64 = 0\nuint64_max: u64 = 18446744073709551615\n\nuint32_min: u32 = 0\nuint32_max: u32 = 4294967295\n\nuint16_min: u16 = 0\nuint16_max: u16 = 65535\n\nuint8_min: u8 = 0\nuint8_max: u8 = 255\n\nbigint_small: bigint = 42\nbigint_neg_small: bigint = -1\nbigint_i64_max: bigint = 9223372036854775807\nbigint_i64_min: bigint = -9223372036854775808\nbigint_i64_underflow: bigint = -9223372036854775809\nbigint_u64_edge: bigint = bigint(18446744073709551615)\nbigint_u64_edge_minus1: bigint = bigint(18446744073709551614)\nbigint_u64_overflow: bigint = 18446744073709551616\n\nxint_i64_min_minus1 = -9223372036854775809\n"
  },
  {
    "path": "compiler/lib/test/src/lines.act",
    "content": "actor Apa():\n    apa = 2001\n    def setup(cb):\n        print(\"setup\")\n        cb(0)\n    apb = 2002\n    def compute(cb):\n        print(\"compute\")\n        v = cb(1)\n        m = async cb(2)\n        return v*10\n    def notice(i):\n        print(\"notice\")\n        return i+1\n\n    y = 123\n    setup(notice)\n    z = 1\n    print(\"Apa\")\n\nactor Bepa():\n    def callback(i):\n        print(\"callback\", i)\n        return i+1\n    print(\"Bepa\")\n\nactor main(env):\n    def myproc(i):\n        print(\"myproc\", i)\n        if i == 2:\n            env.exit(0)\n        return i\n    a = Apa()\n    b = Bepa()\n    print(\"-----\")\n    a.setup(a.notice)\n    x = async a.compute(b.callback)\n    r = await x\n    print(\"r =\", r)\n    a.compute(myproc)\n    print(\"main\")\n\n    # If/elif/else nested blocks\n    v = 0\n    if v == 0:\n        print(\"if branch\")\n        if v < 1:\n            print(\"nested if\")\n        elif v == -1:\n            print(\"nested elif\")\n        else:\n            print(\"nested else\")\n    elif v == 1:\n        print(\"outer elif\")\n    else:\n        print(\"outer else\")\n\n    # While with else, break/continue\n    i = 0\n    while i < 3:\n        i = i + 1\n        if i == 1:\n            print(\"continue path\")\n            continue\n        if i == 2:\n            print(\"break path\")\n            break\n        print(\"loop body\", i)\n    else:\n        print(\"while else\")\n\n    # For loop over literal list\n    for j in [1, 2, 3]:\n        if j == 2:\n            continue\n        print(\"for j\", j)\n\n    # Try / except / finally\n    try:\n        if v == 0:\n            raise ValueError(\"boom\")\n        print(\"unreached\")\n    except ValueError as e:\n        print(\"caught\", \"ValueError\")\n    finally:\n        print(\"finally\")\n\n    # After scheduling (not executed in tests, but exercises codegen)\n    after 1: myproc(0)\n\n    # pass statement and return None path in a local\n    def nop():\n        pass\n        return None\n    nop()\n"
  },
  {
    "path": "compiler/lib/test/src/syntax1.act",
    "content": "\"\"\"Module docstring for syntax1 test.\nThis tests docstring support across all language constructs.\n\"\"\"\n\nimport net\n\n# Test function definition with docstring (NDef)\ndef add(x: int, y: int) -> int:\n    \"\"\"Add two numbers together.\n\n    This function takes two integers and returns their sum.\n    \"\"\"\n    def foo():\n        \"\"\"A nested function that does nothing.\"\"\"\n        pass\n    return x + y\n\n# Test function with just signature (NSig would be in a protocol/class)\n# We'll test NSig in the protocol below\n\n# Test class with docstring (NClass)\nclass Calculator:\n    \"\"\"A calculator class with basic operations.\n\n    This class provides methods for arithmetic operations.\n    \"\"\"\n    def multiply(self, x: int, y: int) -> int:\n        \"\"\"Multiply two numbers.\n\n        Args:\n            x: First number\n            y: Second number\n\n        Returns:\n            The product of x and y\n        \"\"\"\n        return x * y\n    def divide(self, x: int, y: int) -> float:\n        \"\"\"Divide x by y.\"\"\"\n        return float(x) / float(y)\n\n# Test actor with docstring (NAct)\nactor Counter(name: str):\n    \"\"\"An actor that counts things.\n\n    This actor maintains a count and can increment it.\n    \"\"\"\n    var count = 0\n    var name = name\n    def increment():\n        \"\"\"Increment the counter by one.\"\"\"\n        count += 1\n    def get_count() -> int:\n        \"\"\"Get the current count value.\"\"\"\n        return count\n\n# Test protocol with docstring (NProto)\nprotocol Drawable:\n    \"\"\"Protocol for objects that can be drawn.\n\n    Any class implementing this protocol must provide a draw method.\n    \"\"\"\n    # This creates NSig entries for protocol methods\n    draw: () -> None\n    get_color: () -> str\n\n# Test extension with docstring (NExt)\nextension Calculator (Drawable):\n    \"\"\"Extension to make Calculator drawable.\n\n    This adds drawing capabilities to the Calculator class.\n    \"\"\"\n    def draw(self):\n        \"\"\"Draw the calculator.\"\"\"\n        print(\"Drawing a calculator\")\n    def get_color(self) -> str:\n        \"\"\"Get the calculator's color.\"\"\"\n        return \"black\"\n\n# Test top-level function without docstring\ndef subtract(x: int, y: int) -> int:\n    return x - y\n\n# Test nested functions with docstrings\ndef outer_function(x: int) -> int:\n    \"\"\"Outer function with a nested function inside.\"\"\"\n\n    def inner_function(y: int) -> int:\n        \"\"\"Inner function that adds to the outer parameter.\"\"\"\n        return x + y\n    return inner_function(10)\n"
  },
  {
    "path": "compiler/lib/test/src/test_discovery.act",
    "content": "import logging\nimport testing\n\nactor MathTester():\n    def add(a, b):\n        return a + b\n\n# Unit test\ndef _test_foo() -> None:\n    pass\n\n# Synchronous actor test\nactor _test_SimpleSyncTester():\n    m = MathTester()\n    print(\"SimpleSyncTester.test()\")\n    testing.assertEqual(m.add(1, 2), 3, \"1 + 2 = 3\")\n\nactor _SyncTester(t: testing.SyncT):\n    log = logging.Logger(t.log_handler)\n    m = MathTester()\n    log.info(\"SyncTester.test()\")\n    print(\"SyncTester.test()\")\n    testing.assertEqual(m.add(1, 2), 3, \"1 + 2 = 3\")\n\nactor _SyncTesterCore():\n    m = MathTester()\n    print(\"SimpleSyncTester.test()\")\n    testing.assertEqual(m.add(1, 2), 3, \"1 + 2 = 3\")\n\ndef _test_simple_sync():\n    s = _SyncTesterCore()\n\ndef _test_sync(t: testing.SyncT):\n    m = MathTester()\n    return str(m.add(1, 2))  # Should return \"3\"\n\nactor AsyncTester(t: testing.AsyncT):\n    log = logging.Logger(t.log_handler)\n    def test():\n        log.info(\"AsyncTester.test()\", {\"data\": \"test\"})\n        t.success()\n    after 0: test()\n\nactor EnvTester(t: testing.EnvT):\n    log = logging.Logger(t.log_handler)\n    def test():\n        log.info(\"EnvTester.test() wthreads:\", {\"nr_wthreads\": t.env.nr_wthreads})\n        print(\"EnvTester.test() wthreads:\", t.env.nr_wthreads)\n        t.success()\n    after 0: test()\n"
  },
  {
    "path": "compiler/lsp-server/Main.hs",
    "content": "{-# LANGUAGE DuplicateRecordFields #-}\n{-# LANGUAGE LambdaCase #-}\n{-# LANGUAGE OverloadedStrings #-}\n{-# LANGUAGE ScopedTypeVariables #-}\n{-# LANGUAGE TypeOperators #-}\n\nimport Control.Exception (AsyncException, SomeException, displayException, evaluate, finally, fromException, throwIO, try)\nimport Control.Concurrent (ThreadId, forkIO, killThread, threadDelay)\nimport Control.Concurrent.MVar (MVar, newEmptyMVar, takeMVar, tryPutMVar)\nimport Control.Monad (forM, forM_, forever, void, when)\nimport Control.Monad.IO.Class\nimport Data.Aeson (toJSON)\nimport Data.Char (ord)\nimport Data.List (find)\nimport Data.IORef\nimport qualified Data.HashMap.Strict as HM\nimport qualified Data.Map.Strict as M\nimport Data.Maybe (fromMaybe, listToMaybe)\nimport Data.Sequence (Seq, ViewL(..), (|>))\nimport qualified Data.Sequence as Seq\nimport qualified Data.Text as T\nimport qualified Data.Text.Encoding as TE\nimport GHC.Conc (getNumCapabilities)\nimport System.Directory (doesDirectoryExist)\nimport System.FilePath ((</>), takeExtension, takeFileName)\nimport qualified System.FSNotify as FS\nimport System.IO.Unsafe (unsafePerformIO)\n\nimport Language.LSP.Protocol.Message\nimport Language.LSP.Protocol.Types hiding (Diagnostic, Position)\nimport qualified Language.LSP.Protocol.Types as LSP\nimport Language.LSP.Server\n\nimport qualified Acton.BuildSpec as BuildSpec\nimport qualified Acton.Compile as Compile\nimport qualified Acton.CommandLineParser as C\nimport qualified Acton.Completion as Completion\nimport qualified Acton.Env as Env\nimport qualified Acton.SourceProvider as Source\nimport qualified Acton.Syntax as S\n\nimport Error.Diagnose (Diagnostic)\nimport Error.Diagnose.Diagnostic (reportsOf)\nimport Error.Diagnose.Report (Marker(..), Note(..), Report(Warn, Err))\nimport Error.Diagnose.Position (Position(..))\n\n\ntype OverlayMap = HM.HashMap FilePath Source.SourceSnapshot\ntype UriMap = HM.HashMap FilePath Uri\ntype BackgroundCompilerLockMap = HM.HashMap FilePath Compile.BackgroundCompilerLock\ntype BackgroundCompilerWarned = HM.HashMap FilePath ()\ntype CompletionStateMap = HM.HashMap FilePath CompletionState\ntype CompletionEnvCacheMap = HM.HashMap FilePath CompletionEnvCache\ntype ProjectBuildCacheMap = HM.HashMap FilePath ProjectBuildCache\ntype ProjectWatcherMap = HM.HashMap (FilePath, FilePath) ThreadId\n\ndata CompletionState = CompletionState\n  { completionEnv :: Env.Env0\n  , completionSearchPath :: [FilePath]\n  , completionModuleName :: S.ModName\n  , completionStateGen :: Int\n  }\n\ndata CompletionEnvCache = CompletionEnvCache\n  { cachedCompletionStateGen :: Int\n  , cachedCompletionImportKey :: String\n  , cachedCompletionEnv :: Env.Env0\n  }\n\ndata ProjectBuildCache = ProjectBuildCache\n  { cachedCompileContext :: Compile.CompileContext\n  , cachedProjectMap :: M.Map FilePath Compile.ProjCtx\n  , cachedGlobalTasks :: [Compile.GlobalTask]\n  , cachedRootPins :: M.Map String BuildSpec.PkgDep\n  , cachedImportKeys :: HM.HashMap FilePath String\n  }\n\ndata PlanOrigin = PlanFromCache | PlanFromDiscovery deriving (Eq, Show)\n\ndata LspProgress = LspProgress\n  { lspProgressToken :: ProgressToken\n  , lspProgressQueue :: IORef (Seq T.Text)\n  , lspProgressSignal :: MVar ()\n  , lspProgressWorker :: ThreadId\n  }\n\n-- | Debounce delay (microseconds) before recompiling on edits.\ndebounceMicros :: Int\ndebounceMicros = 200000\n\nprogressIntervalMicros :: Int\nprogressIntervalMicros = 250000\n\nprogressQueueLimit :: Int\nprogressQueueLimit = 100\n\n{-# NOINLINE overlaysRef #-}\n-- | Global in-memory buffer map used as a source overlay.\noverlaysRef :: IORef OverlayMap\noverlaysRef = unsafePerformIO (newIORef HM.empty)\n\n{-# NOINLINE uriByPathRef #-}\n-- | Map canonical paths to the client-provided URIs for diagnostics.\nuriByPathRef :: IORef UriMap\nuriByPathRef = unsafePerformIO (newIORef HM.empty)\n\n{-# NOINLINE backgroundCompilerLocksRef #-}\n-- | Map project roots to held background-compiler locks.\nbackgroundCompilerLocksRef :: IORef BackgroundCompilerLockMap\nbackgroundCompilerLocksRef = unsafePerformIO (newIORef HM.empty)\n\n{-# NOINLINE backgroundCompilerWarnedRef #-}\n-- | Remember which projects have already warned about another background compiler.\nbackgroundCompilerWarnedRef :: IORef BackgroundCompilerWarned\nbackgroundCompilerWarnedRef = unsafePerformIO (newIORef HM.empty)\n\n{-# NOINLINE completionStatesRef #-}\n-- | Latest successful front-end environment for member completion.\ncompletionStatesRef :: IORef CompletionStateMap\ncompletionStatesRef = unsafePerformIO (newIORef HM.empty)\n\n{-# NOINLINE completionEnvCacheRef #-}\ncompletionEnvCacheRef :: IORef CompletionEnvCacheMap\ncompletionEnvCacheRef = unsafePerformIO (newIORef HM.empty)\n\n{-# NOINLINE projectBuildCachesRef #-}\nprojectBuildCachesRef :: IORef ProjectBuildCacheMap\nprojectBuildCachesRef = unsafePerformIO (newIORef HM.empty)\n\n{-# NOINLINE projectWatchersRef #-}\nprojectWatchersRef :: IORef ProjectWatcherMap\nprojectWatchersRef = unsafePerformIO (newIORef HM.empty)\n\n{-# NOINLINE compileScheduler #-}\n-- | Shared compile scheduler for LSP events and back jobs.\ncompileScheduler :: Compile.CompileScheduler\ncompileScheduler = unsafePerformIO $ do\n  nCaps <- getNumCapabilities\n  let maxParallel = max 1 (if C.jobs lspGlobalOpts > 0 then C.jobs lspGlobalOpts else nCaps)\n  Compile.newCompileScheduler lspGlobalOpts maxParallel\n\n-- | Global compiler options for the LSP server (quiet, no color).\nlspGlobalOpts :: C.GlobalOptions\nlspGlobalOpts =\n  C.GlobalOptions\n    { color = C.Never\n    , quiet = True\n    , noProgress = True\n    , timing = False\n    , tty = False\n    , verbose = False\n    , verboseZig = False\n    , jobs = 0\n    }\n\n-- | Compile options for LSP runs (front passes only, no final build).\nlspCompileOpts :: C.CompileOptions\nlspCompileOpts =\n  Compile.defaultCompileOptions\n    { C.skip_build = True\n    , C.only_build = False\n    , C.test = False\n    }\n\n\n-- | SourceProvider that reads overlays first, then falls back to disk.\noverlaySourceProvider :: IORef OverlayMap -> Source.SourceProvider\noverlaySourceProvider ref =\n  let disk = Source.diskSourceProvider\n  in Source.SourceProvider\n       { Source.spReadOverlay = \\path -> HM.lookup path <$> readIORef ref\n       , Source.spReadFile = Source.spReadFile disk\n       , Source.spGetModTime = Source.spGetModTime disk\n       }\n\n-- | Update the in-memory overlay for a document.\nupdateOverlay :: FilePath -> T.Text -> IO ()\nupdateOverlay path txt =\n  let snap = Source.SourceSnapshot\n        { Source.ssText = T.unpack txt\n        , Source.ssBytes = TE.encodeUtf8 txt\n        , Source.ssIsOverlay = True\n        }\n  in atomicModifyIORef' overlaysRef $ \\m -> (HM.insert path snap m, ())\n\n-- | Remove a document overlay when it closes.\nremoveOverlay :: FilePath -> IO ()\nremoveOverlay path =\n  atomicModifyIORef' overlaysRef $ \\m -> (HM.delete path m, ())\n\n-- | Publish diagnostics for a file to the LSP client.\npublishDiagnosticsFor :: FilePath -> [LSP.Diagnostic] -> LspM () ()\npublishDiagnosticsFor path diags = do\n  uri <- liftIO $ lookupUri path\n  sendNotification SMethod_TextDocumentPublishDiagnostics (PublishDiagnosticsParams uri Nothing diags)\nrememberUri :: FilePath -> Uri -> IO ()\nrememberUri path uri =\n  atomicModifyIORef' uriByPathRef $ \\m -> (HM.insert path uri m, ())\n\nforgetUri :: FilePath -> IO ()\nforgetUri path =\n  atomicModifyIORef' uriByPathRef $ \\m -> (HM.delete path m, ())\n\nlookupUri :: FilePath -> IO Uri\nlookupUri path = do\n  m <- readIORef uriByPathRef\n  return (fromMaybe (filePathToUri path) (HM.lookup path m))\n\nensureBackgroundCompilerLock :: FilePath -> IO Bool\nensureBackgroundCompilerLock projRoot = do\n  locks <- readIORef backgroundCompilerLocksRef\n  case HM.lookup projRoot locks of\n    Just _ -> return True\n    Nothing -> do\n      mlock <- Compile.tryBackgroundCompilerLock projRoot\n      case mlock of\n        Nothing -> return False\n        Just lock -> do\n          atomicModifyIORef' backgroundCompilerLocksRef $ \\m -> (HM.insert projRoot lock m, ())\n          atomicModifyIORef' backgroundCompilerWarnedRef $ \\m -> (HM.delete projRoot m, ())\n          return True\n\nreleaseBackgroundCompilerLocks :: IO ()\nreleaseBackgroundCompilerLocks = do\n  locks <- readIORef backgroundCompilerLocksRef\n  forM_ (HM.elems locks) Compile.releaseBackgroundCompilerLock\n  writeIORef backgroundCompilerLocksRef HM.empty\n\nrememberCompletionStates :: Int -> Compile.CompilePlan -> Env.Env0 -> IO ()\nrememberCompletionStates gen plan env = do\n  entries <- forM (Compile.cpGlobalTasks plan) $ \\t -> do\n    let key = Compile.gtKey t\n        paths = Compile.gtPaths t\n        mn = Compile.tkMod key\n    path <- Compile.normalizePathSafe (Compile.srcFile paths mn)\n    return (path, CompletionState env (Compile.searchPath paths) mn gen)\n  atomicModifyIORef' completionStatesRef $ \\m ->\n    (foldr (uncurry HM.insert) m entries, ())\n\nlookupCompletionState :: FilePath -> IO (Maybe CompletionState)\nlookupCompletionState path = HM.lookup path <$> readIORef completionStatesRef\n\ncacheCompletionState :: FilePath -> CompletionState -> IO ()\ncacheCompletionState path state =\n  atomicModifyIORef' completionStatesRef $ \\m -> (HM.insert path state m, ())\n\nloadDiskCompletionState :: FilePath -> IO CompletionState\nloadDiskCompletionState path = do\n  paths <- Compile.findPaths path lspCompileOpts\n  env <- Env.initEnv (Compile.sysTypes paths) False\n  return CompletionState\n    { completionEnv = env\n    , completionSearchPath = Compile.searchPath paths\n    , completionModuleName = Compile.modName paths\n    , completionStateGen = 0\n    }\n\nloadCompletionStateFor :: FilePath -> IO (Maybe CompletionState)\nloadCompletionStateFor path = do\n  mstate <- lookupCompletionState path\n  case mstate of\n    Just state -> return (Just state)\n    Nothing -> do\n      res <- (try (loadDiskCompletionState path) :: IO (Either SomeException CompletionState))\n      case res of\n        Right state -> do\n          cacheCompletionState path state\n          return (Just state)\n        Left _ ->\n          return Nothing\n\ncacheCompilePlan :: Compile.CompilePlan -> IO ()\ncacheCompilePlan plan = do\n  importKeys <- globalTaskImportKeys (Compile.cpGlobalTasks plan)\n  let ctx = Compile.cpContext plan\n      rootProj = Compile.ccRootProj ctx\n      cache = ProjectBuildCache\n        { cachedCompileContext = ctx\n        , cachedProjectMap = Compile.cpProjMap plan\n        , cachedGlobalTasks = Compile.cpGlobalTasks plan\n        , cachedRootPins = Compile.cpRootPins plan\n        , cachedImportKeys = importKeys\n        }\n  atomicModifyIORef' projectBuildCachesRef $ \\m ->\n    (HM.insert rootProj cache m, ())\n  ensureProjectWatchers rootProj (M.keys (Compile.cpProjMap plan))\n\nglobalTaskImportKeys :: [Compile.GlobalTask] -> IO (HM.HashMap FilePath String)\nglobalTaskImportKeys tasks =\n  HM.fromList <$> mapM taskImportKeyEntry tasks\n\ntaskImportKeyEntry :: Compile.GlobalTask -> IO (FilePath, String)\ntaskImportKeyEntry task = do\n  path <- Compile.normalizePathSafe $\n    Compile.srcFile (Compile.gtPaths task) (Compile.tkMod (Compile.gtKey task))\n  return (path, taskImportKey task)\n\ntaskImportKey :: Compile.GlobalTask -> String\ntaskImportKey task =\n  show (Compile.importsOf (Compile.gtTask task))\n\ninvalidateProjectCache :: FilePath -> IO ()\ninvalidateProjectCache rootProj = do\n  atomicModifyIORef' projectBuildCachesRef $ \\m ->\n    (HM.delete rootProj m, ())\n  invalidateCompletionEnvCache\n\nensureProjectWatchers :: FilePath -> [FilePath] -> IO ()\nensureProjectWatchers rootProj roots =\n  forM_ roots $ \\watchedRoot -> do\n    let key = (rootProj, watchedRoot)\n    existing <- HM.lookup key <$> readIORef projectWatchersRef\n    case existing of\n      Just _ -> return ()\n      Nothing -> do\n        tid <- forkIO (watchProjectShape rootProj watchedRoot)\n        atomicModifyIORef' projectWatchersRef $ \\m ->\n          (HM.insert key tid m, ())\n\nwatchProjectShape :: FilePath -> FilePath -> IO ()\nwatchProjectShape rootProj watchedRoot =\n  FS.withManager $ \\mgr -> do\n    let srcRoot = watchedRoot </> \"src\"\n        invalidate _ = invalidateProjectCache rootProj\n        isActEvent ev = takeExtension (FS.eventPath ev) == \".act\"\n        isBuildActEvent ev = takeFileName (FS.eventPath ev) == \"Build.act\"\n    srcExists <- doesDirectoryExist srcRoot\n    when srcExists $\n      void $ FS.watchTree mgr srcRoot isActEvent invalidate\n    void $ FS.watchDir mgr watchedRoot isBuildActEvent invalidate\n    forever $ threadDelay maxBound\n\nprepareLspCompilePlan\n  :: Source.SourceProvider\n  -> C.GlobalOptions\n  -> C.CompileOptions\n  -> FilePath\n  -> LspM () (Either String (PlanOrigin, Compile.CompilePlan))\nprepareLspCompilePlan sp gopts opts path = do\n  planE <- liftIO ((try $ do\n    ctx <- Compile.prepareCompileContext opts [path]\n    path' <- Compile.normalizePathSafe path\n    mcache <- HM.lookup (Compile.ccRootProj ctx) <$> readIORef projectBuildCachesRef\n    case mcache of\n      Just cache\n        | Compile.ccBuildStamp (cachedCompileContext cache) == Compile.ccBuildStamp ctx -> do\n            mplan <- compilePlanFromCache ctx path' cache\n            case mplan of\n              Just plan -> return (PlanFromCache, plan)\n              Nothing -> freshPlan\n      _ -> freshPlan\n    ) :: IO (Either SomeException (PlanOrigin, Compile.CompilePlan)))\n  case planE of\n    Left err ->\n      case fromException err of\n        Just (Compile.ProjectError msg) -> return (Left msg)\n        Nothing -> return (Left (displayException err))\n    Right plan -> return (Right plan)\n  where\n    freshPlan = do\n      plan <- Compile.prepareCompilePlan sp gopts compileScheduler opts [path] False (Just [path])\n      cacheCompilePlan plan\n      return (PlanFromDiscovery, plan)\n\ncompilePlanFromCache :: Compile.CompileContext -> FilePath -> ProjectBuildCache -> IO (Maybe Compile.CompilePlan)\ncompilePlanFromCache ctx changedPath cache = do\n  refreshed <- refreshChangedGlobalTask changedPath (Compile.ccOpts ctx) cache\n  case refreshed of\n    Nothing -> return Nothing\n    Just (globalTasks, importKeys) -> do\n      neededTasks <- Compile.selectAffectedTasks globalTasks [changedPath]\n      let rootProj = Compile.ccRootProj ctx\n          rootTasks =\n            [ Compile.gtTask t\n            | t <- neededTasks\n            , Compile.tkProj (Compile.gtKey t) == rootProj\n            ]\n          cache' = cache\n            { cachedCompileContext = ctx\n            , cachedGlobalTasks = globalTasks\n            , cachedImportKeys = importKeys\n            }\n      atomicModifyIORef' projectBuildCachesRef $ \\m ->\n        (HM.insert rootProj cache' m, ())\n      return $ Just Compile.CompilePlan\n        { Compile.cpContext = ctx\n        , Compile.cpProjMap = cachedProjectMap cache\n        , Compile.cpGlobalTasks = globalTasks\n        , Compile.cpNeededTasks = neededTasks\n        , Compile.cpRootTasks = rootTasks\n        , Compile.cpRootPins = cachedRootPins cache\n        , Compile.cpIncremental = True\n        , Compile.cpAllowPrune = False\n        , Compile.cpChangedPaths = Just [changedPath]\n        , Compile.cpSrcFiles = [changedPath]\n        }\n\nrefreshChangedGlobalTask\n  :: FilePath\n  -> C.CompileOptions\n  -> ProjectBuildCache\n  -> IO (Maybe ([Compile.GlobalTask], HM.HashMap FilePath String))\nrefreshChangedGlobalTask changedPath opts cache =\n  case find isChanged (cachedGlobalTasks cache) of\n    Nothing -> return Nothing\n    Just old -> do\n      newTask <- Compile.readModuleTask\n        (overlaySourceProvider overlaysRef)\n        lspGlobalOpts\n        opts\n        (Compile.gtPaths old)\n        changedPath\n      let new = old { Compile.gtTask = newTask }\n          newKey = taskImportKey new\n      case HM.lookup changedPath (cachedImportKeys cache) of\n        Just oldKey | oldKey /= newKey ->\n          return Nothing\n        _ -> do\n          let tasks' =\n                [ if Compile.gtKey t == Compile.gtKey old then new else t\n                | t <- cachedGlobalTasks cache\n                ]\n              importKeys' = HM.insert changedPath newKey (cachedImportKeys cache)\n          return (Just (tasks', importKeys'))\n  where\n    isChanged t =\n      Compile.srcFile (Compile.gtPaths t) (Compile.tkMod (Compile.gtKey t)) == changedPath\n\nprogressToken :: Int -> FilePath -> ProgressToken\nprogressToken gen path =\n  ProgressToken (InR (T.pack (\"acton-lsp-\" ++ show gen ++ \"-\" ++ takeFileName path)))\n\nstartLspProgress :: Int -> FilePath -> LspM () LspProgress\nstartLspProgress gen path = do\n  env <- getLspEnv\n  queue <- liftIO $ newIORef Seq.empty\n  signal <- liftIO newEmptyMVar\n  let token = progressToken gen path\n      title = T.pack (\"Acton: \" ++ takeFileName path)\n      dequeue = atomicModifyIORef' queue $ \\msgs ->\n        case Seq.viewl msgs of\n          EmptyL -> (msgs, Nothing)\n          msg :< rest -> (rest, Just msg)\n      drain = do\n        mmsg <- dequeue\n        case mmsg of\n          Nothing -> return ()\n          Just msg -> do\n            runLspT env $ progressReportToken token msg Nothing\n            threadDelay progressIntervalMicros\n            drain\n      loop = forever $ takeMVar signal >> drain\n  worker <- liftIO $ forkIO loop\n  let progress = LspProgress token queue signal worker\n  void $ sendRequest SMethod_WindowWorkDoneProgressCreate\n    (WorkDoneProgressCreateParams token)\n    (\\_ -> pure ())\n  progressBegin progress title \"Preparing diagnostics and completion\"\n  return progress\n\nprogressBegin :: LspProgress -> T.Text -> T.Text -> LspM () ()\nprogressBegin progress title msg =\n  sendNotification SMethod_Progress $\n    ProgressParams (lspProgressToken progress) $\n      toJSON (WorkDoneProgressBegin AString title (Just False) (Just msg) Nothing)\n\nprogressReportToken :: ProgressToken -> T.Text -> Maybe Int -> LspM () ()\nprogressReportToken token msg pct =\n  sendNotification SMethod_Progress $\n    ProgressParams token $\n      toJSON (WorkDoneProgressReport AString (Just False) (Just msg) (fromIntegral <$> pct))\n\nprogressReport :: LspProgress -> T.Text -> Maybe Int -> LspM () ()\nprogressReport progress =\n  progressReportToken (lspProgressToken progress)\n\nclearProgressQueue :: LspProgress -> LspM () ()\nclearProgressQueue progress =\n  liftIO $ writeIORef (lspProgressQueue progress) Seq.empty\n\nprogressReportImmediate :: LspProgress -> T.Text -> Maybe Int -> LspM () ()\nprogressReportImmediate progress msg pct = do\n  clearProgressQueue progress\n  progressReport progress msg pct\n\nprogressReportQueued :: LspProgress -> T.Text -> LspM () ()\nprogressReportQueued progress msg =\n  liftIO $ do\n    atomicModifyIORef' (lspProgressQueue progress) $ \\msgs ->\n      let msgs' = msgs |> msg\n      in (dropOldestProgress msgs', ())\n    void $ tryPutMVar (lspProgressSignal progress) ()\n\ndropOldestProgress :: Seq T.Text -> Seq T.Text\ndropOldestProgress msgs =\n  Seq.drop (max 0 (Seq.length msgs - progressQueueLimit)) msgs\n\nprogressEnd :: LspProgress -> T.Text -> LspM () ()\nprogressEnd progress msg =\n  sendNotification SMethod_Progress $\n    ProgressParams (lspProgressToken progress) $\n      toJSON (WorkDoneProgressEnd AString (Just msg))\n\nfinishProgressOnce :: IORef Bool -> LspProgress -> T.Text -> LspM () ()\nfinishProgressOnce finished progress msg = do\n  alreadyFinished <- liftIO $\n    atomicModifyIORef' finished $ \\done -> (True, done)\n  when (not alreadyFinished) $ do\n    clearProgressQueue progress\n    liftIO $ killThread (lspProgressWorker progress)\n    progressEnd progress msg\n\nmoduleLabel :: Compile.GlobalTask -> String\nmoduleLabel task = Compile.modNameToString (Compile.tkMod (Compile.gtKey task))\n\nbackJobLabel :: Compile.BackJob -> String\nbackJobLabel job =\n  Compile.modNameToString (S.modname (Compile.biTypedMod (Compile.bjInput job)))\n\nfrontProgressMessage :: Compile.GlobalTask -> Compile.FrontPassProgress -> T.Text\nfrontProgressMessage task p =\n  T.pack $\n    passName (Compile.fppPass p) ++ \" \" ++ moduleLabel task ++ current\n  where\n    current =\n      case Compile.fppCurrent p of\n        Nothing -> \"\"\n        Just label -> \" (\" ++ label ++ \")\"\n    passName Compile.FrontPassKinds = \"Checking kinds for\"\n    passName Compile.FrontPassTypes = \"Typechecking\"\n\nbackProgressMessage :: Compile.BackJob -> Compile.BackJobResult -> T.Text\nbackProgressMessage job result =\n  T.pack $\n    case result of\n      Compile.BackJobOk{} -> \"Generated \" ++ backJobLabel job\n      Compile.BackJobFailed{} -> \"Codegen failed for \" ++ backJobLabel job\n\nwarnBackgroundCompilerLocked :: FilePath -> LspM () ()\nwarnBackgroundCompilerLocked projRoot = do\n  first <- liftIO $ atomicModifyIORef' backgroundCompilerWarnedRef $ \\m ->\n    if HM.member projRoot m\n      then (m, False)\n      else (HM.insert projRoot () m, True)\n  when first $\n    sendNotification SMethod_WindowShowMessage\n      (ShowMessageParams MessageType_Warning\n        (T.pack (\"Another long-running Acton compiler is already running in \" ++ projRoot ++\n                 \"; LSP compilation is disabled until it exits.\")))\n\n-- | Run an action only if the compile generation is current.\nwhenCurrentGen :: Int -> LspM () () -> LspM () ()\nwhenCurrentGen gen action = do\n  current <- liftIO $ readIORef (Compile.csGenRef compileScheduler)\n  when (current == gen) action\n\n-- | Notify the client of a compile error for the current generation.\nnotifyCompileError :: Int -> String -> LspM () ()\nnotifyCompileError gen msg =\n  whenCurrentGen gen $\n    sendNotification SMethod_WindowShowMessage\n      (ShowMessageParams MessageType_Error (T.pack msg))\n\n-- | Convert Acton positions to LSP ranges with zero-based offsets.\nreportRange :: Position -> Range\nreportRange (Position (bl, bc) (el, ec) _) =\n  let l0 = max 0 (bl - 1)\n      c0 = max 0 (bc - 1)\n      l1 = max 0 (el - 1)\n      c1 = max 0 (ec - 1)\n      endC = max c1 (c0 + 1)\n  in mkRange (fromIntegral l0) (fromIntegral c0) (fromIntegral l1) (fromIntegral endC)\n\n-- | Select a primary marker position for a diagnostic.\npickPosition :: [(Position, Marker msg)] -> Maybe Position\npickPosition markers =\n  case [pos | (pos, This _) <- markers] of\n    (p:_) -> Just p\n    [] -> fmap fst (listToMaybe markers)\n\n-- | Render notes and hints into a diagnostic message.\nnotesText :: [Note String] -> String\nnotesText [] = \"\"\nnotesText ns = \"\\n\" ++ unlines (map noteLine ns)\n  where\n    noteLine (Hint h) = \"Hint: \" ++ h\n    noteLine (Note n) = \"Note: \" ++ n\n\n-- | Translate an Acton report into an LSP diagnostic.\nreportToLsp :: Report String -> LSP.Diagnostic\nreportToLsp rep =\n  let (sev, msg, markers, notes) = case rep of\n        Err _ m ms ns -> (DiagnosticSeverity_Error, m, ms, ns)\n        Warn _ m ms ns -> (DiagnosticSeverity_Warning, m, ms, ns)\n      pos = pickPosition markers\n      range = maybe (mkRange 0 0 0 0) reportRange pos\n      fullMsg = T.pack (msg ++ notesText notes)\n  in LSP.Diagnostic\n       { _range = range\n       , _severity = Just sev\n       , _code = Nothing\n       , _codeDescription = Nothing\n       , _source = Just \"acton\"\n       , _message = fullMsg\n       , _tags = Nothing\n       , _relatedInformation = Nothing\n       , _data_ = Nothing\n       }\n\n-- | Convert Diagnose diagnostics to LSP diagnostics.\nlspDiagnosticsFrom :: [Diagnostic String] -> [LSP.Diagnostic]\nlspDiagnosticsFrom diags = concatMap (map reportToLsp . reportsOf) diags\n\n-- | Prepare a compile plan for a file, run it, and publish diagnostics.\nrunCompile :: Int -> FilePath -> LspM () ()\nrunCompile gen path = do\n  env <- getLspEnv\n  progress <- startLspProgress gen path\n  finished <- liftIO $ newIORef False\n  let finish = finishProgressOnce finished progress\n      body = do\n        let gopts = lspGlobalOpts\n            opts = lspCompileOpts\n            sp = overlaySourceProvider overlaysRef\n        rootProj <- liftIO $ resolveCompileRoot path opts\n        lockOk <- liftIO $ ensureBackgroundCompilerLock rootProj\n        if lockOk\n          then do\n            progressReportImmediate progress \"Running Acton front passes\" Nothing\n            ok <- runCompilePlanWithHooks gen rootProj path sp gopts opts progress\n            if ok\n              then finish \"Acton ready\"\n              else finish \"Acton failed\"\n          else do\n            progressReportImmediate progress \"Waiting for another Acton compiler for this project\" Nothing\n            whenCurrentGen gen $ warnBackgroundCompilerLocked rootProj\n            finish \"Acton blocked by another compiler\"\n  liftIO $\n    runLspT env body `finally` runLspT env (finish \"Acton stopped\")\n\n-- | Resolve the project root used for compile locking.\nresolveCompileRoot :: FilePath -> C.CompileOptions -> IO FilePath\nresolveCompileRoot path opts = do\n  mproj <- Compile.findProjectDir path\n  case mproj of\n    Just proj -> Compile.normalizePathSafe proj\n    Nothing -> do\n      paths <- Compile.findPaths path opts\n      Compile.normalizePathSafe (Compile.projPath paths)\n\n-- | Prepare and run a compile while holding the per-run project work lock.\nrunCompilePlanWithHooks :: Int -> FilePath -> FilePath -> Source.SourceProvider -> C.GlobalOptions -> C.CompileOptions -> LspProgress -> LspM () Bool\nrunCompilePlanWithHooks gen rootProj path sp gopts opts progress = do\n  env <- getLspEnv\n  let taskPath t = Compile.srcFile (Compile.gtPaths t) (Compile.tkMod (Compile.gtKey t))\n      publishFor t diags =\n        runLspT env $ whenCurrentGen gen $\n          publishDiagnosticsFor (taskPath t) diags\n      progressFor msg =\n        runLspT env $ whenCurrentGen gen $\n          progressReportImmediate progress msg Nothing\n      progressForQueued msg =\n        runLspT env $ whenCurrentGen gen $\n          progressReportQueued progress msg\n      hooks = Compile.defaultCompileHooks\n        { Compile.chOnDiagnostics = \\t _ diags ->\n            publishFor t (lspDiagnosticsFrom diags)\n        , Compile.chOnParseStart = \\t ->\n            progressForQueued (T.pack (\"Parsing \" ++ moduleLabel t))\n        , Compile.chOnParseDone = \\t _ ->\n            progressForQueued (T.pack (\"Parsed \" ++ moduleLabel t))\n        , Compile.chOnFrontStart = \\t ->\n            progressFor (T.pack (\"Checking \" ++ moduleLabel t))\n        , Compile.chOnFrontProgress = \\t p ->\n            progressForQueued (frontProgressMessage t p)\n        , Compile.chOnFrontResult = \\t _ ->\n            publishFor t [] >>\n            progressForQueued (T.pack (\"Checked \" ++ moduleLabel t))\n        , Compile.chOnBackStart = \\job ->\n            progressForQueued (T.pack (\"Generating \" ++ backJobLabel job))\n        , Compile.chOnBackDone = \\job result ->\n            progressForQueued (backProgressMessage job result)\n        , Compile.chOnInfo = \\_ -> return ()\n        }\n  progressReportImmediate progress \"Preparing Acton project\" Nothing\n  compileRes <- liftIO $\n    Compile.withProjectLock rootProj $\n      do\n        planE <- runLspT env $\n          prepareLspCompilePlan sp gopts opts path\n        case planE of\n          Left msg ->\n            return (Left msg)\n          Right (origin, plan) -> do\n            progressFor $\n              case origin of\n                PlanFromCache -> \"Acton cached project ready\"\n                PlanFromDiscovery -> \"Acton compile plan ready\"\n            runRes <- Compile.runCompilePlan sp gopts plan compileScheduler gen hooks\n            case runRes of\n              Left err ->\n                return (Left (Compile.compileFailureMessage err))\n              Right (envAcc, _) -> do\n                rememberCompletionStates gen plan envAcc\n                progressFor \"Completion ready\"\n                let opts' = Compile.ccOpts (Compile.cpContext plan)\n                backFailure <-\n                  if C.only_build opts'\n                    then return Nothing\n                    else Compile.backQueueWait (Compile.csBackQueue compileScheduler) gen\n                case backFailure of\n                  Just failure ->\n                    return (Left (Compile.backPassFailureMessage failure))\n                  Nothing ->\n                    return (Right ())\n  case compileRes of\n    Left msg -> notifyCompileError gen msg >> return False\n    Right () -> return True\n\n-- | Schedule a compile run with a debounce delay.\nscheduleCompile :: Int -> FilePath -> LspM () ()\nscheduleCompile delay path = do\n  env <- getLspEnv\n  void $ liftIO $ Compile.startCompile compileScheduler delay $ \\gen ->\n    runLspT env (runCompile gen path)\n\n-- | Convert an LSP position to a source offset. LSP columns are UTF-16 code\n-- units; parser/source offsets are Haskell character offsets.\npositionToOffset :: String -> LSP.Position -> Int\npositionToOffset src (LSP.Position line character) =\n  goLine (fromIntegral line) 0 src\n  where\n    targetCol = fromIntegral character\n\n    goLine 0 off rest = off + columnOffset targetCol rest\n    goLine _ off [] = off\n    goLine n off (c:cs)\n      | c == '\\n' = goLine (n - 1) (off + 1) cs\n      | otherwise = goLine n (off + 1) cs\n\n    columnOffset 0 _ = 0\n    columnOffset _ [] = 0\n    columnOffset col (c:cs)\n      | c == '\\n' = 0\n      | units > col = 0\n      | otherwise = 1 + columnOffset (col - units) cs\n      where units = if ord c > 0xffff then 2 else 1\n\ncompletionKindToLsp :: Completion.CompletionKind -> CompletionItemKind\ncompletionKindToLsp kind =\n  case kind of\n    Completion.CompletionField -> CompletionItemKind_Field\n    Completion.CompletionMethod -> CompletionItemKind_Method\n    Completion.CompletionProperty -> CompletionItemKind_Property\n    Completion.CompletionValue -> CompletionItemKind_Value\n    Completion.CompletionKeyword -> CompletionItemKind_Keyword\n\nlspCompletionItem :: Completion.Completion -> CompletionItem\nlspCompletionItem item =\n  CompletionItem\n    { _label = T.pack (Completion.completionLabel item)\n    , _labelDetails = Nothing\n    , _kind = Just (completionKindToLsp (Completion.completionKind item))\n    , _tags = Nothing\n    , _detail = T.pack <$> Completion.completionDetail item\n    , _documentation = Nothing\n    , _deprecated = Nothing\n    , _preselect = Nothing\n    , _sortText = Nothing\n    , _filterText = Nothing\n    , _insertText = completionInsertText item\n    , _insertTextFormat = completionInsertTextFormat item\n    , _insertTextMode = Nothing\n    , _textEdit = Nothing\n    , _textEditText = Nothing\n    , _additionalTextEdits = Nothing\n    , _commitCharacters = Nothing\n    , _command = completionCommand item\n    , _data_ = Nothing\n    }\n\ncompletionInsertText :: Completion.Completion -> Maybe T.Text\ncompletionInsertText item =\n  case Completion.completionKind item of\n    Completion.CompletionMethod ->\n      Just (T.pack (Completion.completionLabel item ++ \"($0)\"))\n    Completion.CompletionKeyword ->\n      Just (T.pack (Completion.completionLabel item ++ \"$0\"))\n    _ -> Nothing\n\ncompletionInsertTextFormat :: Completion.Completion -> Maybe InsertTextFormat\ncompletionInsertTextFormat item =\n  case Completion.completionKind item of\n    Completion.CompletionMethod -> Just InsertTextFormat_Snippet\n    Completion.CompletionKeyword -> Just InsertTextFormat_Snippet\n    _ -> Nothing\n\ncompletionCommand :: Completion.Completion -> Maybe Command\ncompletionCommand item =\n  case Completion.completionKind item of\n    Completion.CompletionMethod ->\n      Just Command\n        { _title = \"Trigger parameter hints\"\n        , _command = \"editor.action.triggerParameterHints\"\n        , _arguments = Nothing\n        }\n    _ -> Nothing\n\nforceLspCompletions :: [Completion.Completion] -> [Completion.Completion]\nforceLspCompletions items =\n  sum [ length (Completion.completionLabel item)\n      + maybe 0 length (Completion.completionDetail item)\n      + completionKindCode (Completion.completionKind item)\n      | item <- items\n      ] `seq` items\n\nforceLspSignatures :: [Completion.CallSignature] -> [Completion.CallSignature]\nforceLspSignatures sigs =\n  sum [ length (Completion.callSignatureLabel sig)\n      + Completion.callSignatureActiveParameter sig\n      + sum (map (length . Completion.signatureParameterLabel) (Completion.callSignatureParameters sig))\n      | sig <- sigs\n      ] `seq` sigs\n\nforceLspHover :: Maybe Completion.HoverInfo -> Maybe Completion.HoverInfo\nforceLspHover info =\n  case info of\n    Nothing -> Nothing\n    Just hover ->\n      length (Completion.hoverLabel hover)\n      + length (Completion.hoverDetail hover)\n      + maybe 0 length (Completion.hoverDocumentation hover) `seq` info\n\ncompletionKindCode :: Completion.CompletionKind -> Int\ncompletionKindCode kind =\n  case kind of\n    Completion.CompletionField -> 1\n    Completion.CompletionMethod -> 2\n    Completion.CompletionProperty -> 3\n    Completion.CompletionValue -> 4\n    Completion.CompletionKeyword -> 5\n\ntryLspIO :: IO a -> IO (Maybe a)\ntryLspIO action = do\n  res <- try action\n  case res of\n    Left err\n      | Just (_ :: AsyncException) <- fromException err ->\n          throwIO err\n      | otherwise ->\n          return Nothing\n    Right value -> return (Just value)\n\nsignatureHelpFor :: FilePath -> LSP.Position -> LspM () (SignatureHelp |? Null)\nsignatureHelpFor path pos = do\n  mstate <- liftIO $ loadCompletionStateFor path\n  case mstate of\n    Nothing -> return (InR Null)\n    Just state -> do\n      snapRes <- liftIO $\n        (try (Source.readSource (overlaySourceProvider overlaysRef) path) :: IO (Either IOError Source.SourceSnapshot))\n      case snapRes of\n        Left _ -> return (InR Null)\n        Right snap -> do\n          let src = Source.ssText snap\n              cursor = positionToOffset src pos\n          msigs <- liftIO $\n            tryLspIO $ do\n              env <- completionEnvFor state path src\n              evaluate (forceLspSignatures (Completion.callSignaturesWithEnv env src cursor))\n          return $\n            case msigs of\n              Just (sig:_) -> InL (lspSignatureHelp sig)\n              _ -> InR Null\n\nhoverFor :: FilePath -> LSP.Position -> LspM () (Hover |? Null)\nhoverFor path pos = do\n  mstate <- liftIO $ loadCompletionStateFor path\n  case mstate of\n    Nothing -> return (InR Null)\n    Just state -> do\n      snapRes <- liftIO $\n        (try (Source.readSource (overlaySourceProvider overlaysRef) path) :: IO (Either IOError Source.SourceSnapshot))\n      case snapRes of\n        Left _ -> return (InR Null)\n        Right snap -> do\n          let src = Source.ssText snap\n              cursor = positionToOffset src pos\n          minfo <- liftIO $\n            tryLspIO $ do\n              env <- completionEnvFor state path src\n              evaluate (forceLspHover (Completion.hoverInfoWithEnv env src cursor))\n          return $\n            case minfo of\n              Just (Just info) -> InL (lspHover info)\n              _ -> InR Null\n\nlspHover :: Completion.HoverInfo -> Hover\nlspHover info =\n  Hover\n    { _contents = InL MarkupContent\n        { _kind = MarkupKind_Markdown\n        , _value = T.pack (hoverMarkdown info)\n        }\n    , _range = Nothing\n    }\n  where\n    hoverMarkdown hover =\n      \"```acton\\n\"\n      ++ Completion.hoverDetail hover\n      ++ \"\\n```\"\n      ++ hoverDoc hover\n\n    hoverDoc hover =\n      case Completion.hoverDocumentation hover of\n        Nothing -> \"\"\n        Just doc -> \"\\n\\n\" ++ doc\n\nlspSignatureHelp :: Completion.CallSignature -> SignatureHelp\nlspSignatureHelp sig =\n  SignatureHelp\n    { _signatures = [lspSignatureInformation sig]\n    , _activeSignature = Just 0\n    , _activeParameter = active\n    }\n  where\n    params = Completion.callSignatureParameters sig\n    active =\n      if null params\n        then Nothing\n        else Just (InL (fromIntegral (Completion.callSignatureActiveParameter sig)))\n\nlspSignatureInformation :: Completion.CallSignature -> SignatureInformation\nlspSignatureInformation sig =\n  SignatureInformation\n    { _label = T.pack (Completion.callSignatureLabel sig)\n    , _documentation = Nothing\n    , _parameters = Just (map lspParameterInformation (Completion.callSignatureParameters sig))\n    , _activeParameter = active\n    }\n  where\n    params = Completion.callSignatureParameters sig\n    active =\n      if null params\n        then Nothing\n        else Just (InL (fromIntegral (Completion.callSignatureActiveParameter sig)))\n\nlspParameterInformation :: Completion.SignatureParameter -> ParameterInformation\nlspParameterInformation param =\n  ParameterInformation\n    { _label = InL (T.pack (Completion.signatureParameterLabel param))\n    , _documentation = Nothing\n    }\n\ncompletionEnvFor :: CompletionState -> FilePath -> String -> IO Env.Env0\ncompletionEnvFor state path src = do\n  importKey <- Completion.completionImportKey path src\n  mcache <- HM.lookup path <$> readIORef completionEnvCacheRef\n  case mcache of\n    Just cache\n      | cachedCompletionStateGen cache == completionStateGen state\n      , cachedCompletionImportKey cache == importKey ->\n          return (cachedCompletionEnv cache)\n    _ -> do\n      env <- Completion.prepareCompletionEnv\n        (completionEnv state)\n        (completionSearchPath state)\n        (completionModuleName state)\n        path\n        src\n      let cache = CompletionEnvCache\n            { cachedCompletionStateGen = completionStateGen state\n            , cachedCompletionImportKey = importKey\n            , cachedCompletionEnv = env\n            }\n      atomicModifyIORef' completionEnvCacheRef $ \\m ->\n        (HM.insert path cache m, ())\n      return env\n\ninvalidateCompletionEnvCache :: IO ()\ninvalidateCompletionEnvCache =\n  writeIORef completionEnvCacheRef HM.empty\n\ncompletionItemsFor :: FilePath -> LSP.Position -> LspM () [CompletionItem]\ncompletionItemsFor path pos = do\n  mstate <- liftIO $ loadCompletionStateFor path\n  case mstate of\n    Nothing -> return []\n    Just state -> do\n      snapRes <- liftIO $\n        (try (Source.readSource (overlaySourceProvider overlaysRef) path) :: IO (Either IOError Source.SourceSnapshot))\n      case snapRes of\n        Left _ -> return []\n        Right snap -> do\n          let src = Source.ssText snap\n              cursor = positionToOffset src pos\n          mitems <- liftIO $\n            tryLspIO $ do\n              env <- completionEnvFor state path src\n              let items =\n                    Completion.memberCompletionsWithEnv env src cursor ++\n                    Completion.argumentCompletionsWithEnv env src cursor\n              evaluate (forceLspCompletions items)\n          return (maybe [] (map lspCompletionItem) mitems)\n\n-- | Resolve and normalize a document URI to a file path.\nresolvePath :: Uri -> LspM () (Maybe FilePath)\nresolvePath uri =\n  case uriToFilePath uri of\n    Nothing -> return Nothing\n    Just path -> liftIO $ do\n      tryLspIO (Compile.normalizePathSafe path)\n\n-- | LSP notification handlers for open/change/close events.\nhandlers :: Handlers (LspM ())\nhandlers =\n  mconcat\n    [ notificationHandler SMethod_Initialized $ \\_ -> pure ()\n    , notificationHandler SMethod_WorkspaceDidChangeConfiguration $ \\_ -> pure ()\n    , requestHandler SMethod_TextDocumentCompletion $ \\(TRequestMessage _ _ _ params) respond -> do\n        let CompletionParams (TextDocumentIdentifier uri) pos _ _ _ = params\n        items <- resolvePath uri >>= \\case\n          Nothing -> return []\n          Just path -> completionItemsFor path pos\n        respond (Right (InL items))\n    , requestHandler SMethod_TextDocumentSignatureHelp $ \\(TRequestMessage _ _ _ params) respond -> do\n        let SignatureHelpParams (TextDocumentIdentifier uri) pos _ _ = params\n        help <- resolvePath uri >>= \\case\n          Nothing -> return (InR Null)\n          Just path -> signatureHelpFor path pos\n        respond (Right help)\n    , requestHandler SMethod_TextDocumentHover $ \\(TRequestMessage _ _ _ params) respond -> do\n        let HoverParams (TextDocumentIdentifier uri) pos _ = params\n        hover <- resolvePath uri >>= \\case\n          Nothing -> return (InR Null)\n          Just path -> hoverFor path pos\n        respond (Right hover)\n    , notificationHandler SMethod_TextDocumentDidOpen $ \\(TNotificationMessage _ _ (DidOpenTextDocumentParams doc)) -> do\n        let TextDocumentItem{_uri=uri,_text=txt} = doc\n        resolvePath uri >>= \\case\n          Nothing -> pure ()\n          Just path -> do\n            liftIO $ rememberUri path uri\n            liftIO $ updateOverlay path txt\n            scheduleCompile 0 path\n    , notificationHandler SMethod_TextDocumentDidChange $ \\(TNotificationMessage _ _ (DidChangeTextDocumentParams vdoc changes)) -> do\n        let VersionedTextDocumentIdentifier{_uri=uri} = vdoc\n        resolvePath uri >>= \\case\n          Nothing -> pure ()\n          Just path ->\n            case changes of\n              [] -> pure ()\n              cs -> do\n                let TextDocumentContentChangeEvent change = last cs\n                    txt = case change of\n                      InL TextDocumentContentChangePartial{_text=txt'} -> txt'\n                      InR TextDocumentContentChangeWholeDocument{_text=txt'} -> txt'\n                liftIO $ rememberUri path uri\n                liftIO $ updateOverlay path txt\n                scheduleCompile debounceMicros path\n    , notificationHandler SMethod_TextDocumentDidClose $ \\(TNotificationMessage _ _ (DidCloseTextDocumentParams (TextDocumentIdentifier uri))) -> do\n        resolvePath uri >>= \\case\n          Nothing -> pure ()\n          Just path -> do\n            liftIO $ removeOverlay path\n            publishDiagnosticsFor path []\n            liftIO $ forgetUri path\n    ]\n\n-- | Start the Acton LSP server with the configured handlers.\nmain :: IO Int\nmain =\n  runServer serverDef `finally` releaseBackgroundCompilerLocks\n  where\n    serverDef =\n      ServerDefinition\n        { parseConfig = const $ const $ Right ()\n        , onConfigChange = const $ pure ()\n        , defaultConfig = ()\n        , configSection = \"acton\"\n        , doInitialize = \\env _req -> pure $ Right env\n        , staticHandlers = \\_caps -> handlers\n        , interpretHandler = \\env -> Iso (runLspT env) liftIO\n        , options = defaultOptions\n            { optTextDocumentSync = Just syncOptions\n            , optCompletionTriggerCharacters = Just ['.', '(', ',']\n            , optSignatureHelpTriggerCharacters = Just ['(', ',']\n            , optSignatureHelpRetriggerCharacters = Just [',']\n            }\n        }\n    syncOptions = TextDocumentSyncOptions\n      { _openClose = Just True\n      , _change = Just TextDocumentSyncKind_Full\n      , _willSave = Nothing\n      , _willSaveWaitUntil = Nothing\n      , _save = Nothing\n      }\n"
  },
  {
    "path": "compiler/lsp-server/package.yaml.in",
    "content": "name:                lsp-server-acton\nversion: BUILD_VERSION\n# github:              \"/simple\"\nlicense:             BSD3\nauthor:              \"Johan Nordlander, Björn von Sydow, Kristian Larsson\"\nmaintainer:          \"example@example.com\"\ncopyright:           \"Data Ductus, Deutsche Telekom\"\n\n# Metadata used when publishing your package\n# synopsis:            Short description of your package\n# category:            Web\n\n# To avoid duplicated efforts in documentation and dealing with the\n# complications of embedding Haddock markup inside cabal files, it is\n# common to point users to the README.md file.\ndescription:         Please see the README on Github at <https://github.com/githubuser/simple#readme>\n\nexecutables:\n  lsp-server-acton:\n    main:                Main.hs\n    source-dirs:         .\n    dependencies:\n      - libacton\n      - async\n      - base >= 4.7 && < 5\n      - bytestring\n      - containers\n      - directory\n      - filepath\n      - fsnotify\n      - mtl\n      - megaparsec\n      - aeson\n      - unordered-containers\n      - diagnose\n      - lsp >= 2.7\n      - lsp-types\n      - text\n      - time\n    ghc-options:\n      - -threaded\n      - -rtsopts\n      - '\"-with-rtsopts=-N -A64M\"'\n    when:\n      - condition: os(linux)\n        ghc-options:\n          - -no-pie\n          - -optl-no-pie\n          - -pgml=../tools/ld-wrapper.sh\n"
  },
  {
    "path": "compiler/stack.yaml",
    "content": "# Resolver to choose a 'specific' stackage snapshot or a compiler version.\n# A snapshot resolver dictates the compiler version and the set of packages\n# to be used for project dependencies.\n\n# NOTE: do not forget to update homebrew/Formula/acton.rb with the version of\n# GHC that corresponds to the stack LTS release, like lts-18.28 -> ghc@8.10\nsnapshot: lts-22.34\n\n# User packages to be built.\n# Various formats can be used as shown in the example below.\n#\n# packages:\n# - some-directory\n# - https://example.com/foo/bar/baz-0.0.2.tar.gz\n# - location:\n#    git: https://github.com/commercialhaskell/stack.git\n#    commit: e7b331f14bcffb8367cd58fbfc8b40ec7642100a\n# - location: https://github.com/commercialhaskell/stack/commit/e7b331f14bcffb8367cd58fbfc8b40ec7642100a\n#   extra-dep: true\n#  subdirs:\n#  - auto-update\n#  - wai\n#\n# A package marked 'extra-dep: true' will only be built if demanded by a\n# non-dependency (i.e. a user package), and its test suites and benchmarks\n# will not be run. This is useful for tweaking upstream packages.\npackages:\n- diagnose\n- lib\n- acton\n- lsp-server\n# Dependency packages to be pulled from upstream that are not in the resolver\n# (e.g., acme-missiles-0.3)\n# extra-deps: []\nextra-deps:\n  - Cabal-3.10.3.0\n  - Cabal-syntax-3.10.3.0\n  - dir-traverse-0.2.3.0\n  - directory-1.3.8.5\n  - filepath-1.4.300.1\n  - lsp-2.7.0.0\n  - lsp-types-2.3.0.0\n  - parsec-3.1.17.0@sha256:8407cbd428d7f640a0fff8891bd2f7aca13cebe70a5e654856f8abec9a648b56\n  - process-1.6.19.0\n  - tasty-1.5.3\n  - unix-2.8.2.1\n\n# Override default flag values for local packages and extra-deps\n# flags: {}\n\n# Extra package databases containing global packages\n# extra-package-dbs: []\n\n# Control whether we use the GHC we find on the path\n# NOTE: this is disabled so we can use a stack GHC in local dev environments but\n# we rewrite this in our Homebrew recipe to use the system GHC. Do NOT remove\n# this line, regexp replace matches on it!\n# system-ghc: true\n\nghc-options:\n  \"$everything\": -fPIC\n"
  },
  {
    "path": "compiler/test/.gitignore",
    "content": "**/out\n"
  },
  {
    "path": "compiler/tests/Acton.hs",
    "content": "-- Copyright (C) 2019-2021 Data Ductus AB\n--\n-- Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:\n--\n-- 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.\n--\n-- 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.\n--\n-- 3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission.\n--\n-- THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS \"AS IS\" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n--\n\n{-# LANGUAGE RankNTypes, MultiParamTypeClasses, FlexibleInstances #-}\nmodule Acton where\n\nimport Control.Monad.Except\n\ndata ST s a     = ST a\n\ninstance Functor (ST s) where\n    fmap = undefined\n\ninstance Applicative (ST s) where\n    pure = undefined\n    (<*>) = undefined\n    \ninstance Monad (ST s) where\n    return = undefined\n    (>>=) = undefined\n\ninstance MonadError String (ST s) where\n    throwError = undefined\n    catchError = undefined\n\ndata Msg t      = Msg t\n\ndata Var s t    = Var t\n\ndata Async a b  = Async a b\n\ndata Actor a    = Actor a\n\n\n\n\nactor           :: (forall s . ST s t) -> Actor t\n_new            :: Actor a -> a -> ST s a\n\n_asyn           :: (a -> ST s b) -> Async a b\n_snd            :: Async a b -> a -> ST s (Msg b)\nawait           :: Msg a -> ST s a\n\nafter           :: Int -> ST s a -> ST s ()\n\nvar             :: a -> ST s (Var s a)\nreadv           :: Var s a -> ST s a\nwritev          :: Var s a -> a -> ST s ()\n\nprints          :: String -> ST s ()\npass            :: ST s ()\nmsg             :: a -> ST s (Msg a)\n\n\nactor a         = undefined\nawait m         = undefined\nafter t p       = undefined\n\nvar e           = undefined\nreadv v         = undefined\nwritev v e      = undefined\n\nprints s        = undefined\npass            = undefined\nmsg             = undefined\n\n_asyn p         = undefined\n_snd            = undefined\n_new            = undefined\n\npingpong        :: Int -> Actor (Async Int ())\npingpong i      = actor $ do\n                    count <- var 0\n                    let ping q = do\n                            c <- readv count\n                            writev count (c+1)\n                            prints (\"Ping \" ++ show (c*q))\n                            after 1 (pong c (-q))\n                        pong n q = do\n                            prints (\"Pong \" ++ show (n*q))\n                            after 2 (ping (-q))\n                    ping i\n                    return (_asyn ping)\n\nsession         :: Conn -> Async String () -> Actor (Async (String, Async Int ()) (), Async (String,String) (), Async () ())\nsession conn error_cb = actor $ do\n                message_id <- var 1\n                responder <- var Nothing\n                let get (path, reply_cb) = do\n                        m_id <- readv message_id\n                        _snd (deliver conn) (print_rpc m_id \"get\" (print_path path \"\"))\n                        writev responder $ Just $ \\text -> _snd reply_cb (xml_parse $ strip_path path $ strip_reply m_id \"data\" text)\n                    edit_config (path, value) = do\n                        m_id <- readv message_id\n                        _snd (deliver conn) (print_rpc m_id \"edit-config\" (print_path path $ xml_print value))\n                        writev responder $ Just $ \\text -> msg $ xml_parse_empty (strip_reply m_id \"ok\" text)\n                    abort () = do\n                        _snd (close conn) ()\n                        return ()\n                    _receive text = do\n                        r <- readv responder\n                        case r of\n                          Just resp -> resp text `catchError` \\ex -> _snd error_cb (show ex)\n                          _ -> undefined\n                        m_id <- readv message_id\n                        writev message_id (m_id + 1)\n                    _error what = do\n                        _snd error_cb what\n                        writev responder Nothing\n                _snd (receive_on conn) (_asyn _receive, _asyn _error)\n                return (_asyn get, _asyn edit_config, _asyn abort)\n\ndata Conn       = Conn\n\ndeliver         :: Conn -> Async String ()\nclose           :: Conn -> Async () ()\nreceive_on      :: Conn -> Async (Async String (), Async String ()) ()\n\n\ndeliver         = undefined\nclose           = undefined\nreceive_on      = undefined\n\nprint_rpc       :: Int -> String -> String -> String\nprint_path      :: String -> String -> String\nstrip_reply     :: Int -> String -> String -> String\nstrip_path      :: String -> String -> String\nxml_print       :: Show a => a -> String\nxml_parse       :: Read a => String -> a\nxml_parse_empty :: String -> ()\n\nprint_rpc       = undefined\nprint_path      = undefined\nstrip_reply     = undefined\nstrip_path      = undefined\nxml_print       = undefined\nxml_parse       = undefined\nxml_parse_empty = undefined\n\n"
  },
  {
    "path": "compiler/tests/ActonLevels.hs",
    "content": "-- Copyright (C) 2019-2021 Data Ductus AB\n--\n-- Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:\n--\n-- 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.\n--\n-- 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.\n--\n-- 3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission.\n--\n-- THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS \"AS IS\" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n--\n\n{-# LANGUAGE RankNTypes, MultiParamTypeClasses, FlexibleInstances #-}\nmodule ActonLevels where\n\nimport Control.Monad.Except\n\ndata ST s l a   = ST a\n\ninstance Functor (ST s l) where\n    fmap = undefined\n\ninstance Applicative (ST s l) where\n    pure = undefined\n    (<*>) = undefined\n    \ninstance Monad (ST s l) where\n    return = undefined\n    (>>=) = undefined\n\ninstance MonadError String (ST s l) where\n    throwError = undefined\n    catchError = undefined\n\ndata Msg l t    = Msg t\n\ndata Var s l t  = Var t             -- A Var mentions a level l simply to connect the type of methods sharing a state\n\ndata Async l a b = Async a b\n\ndata Actor a    = Actor a\n\nclass Less l l' where\n    less        :: l -> l' -> ()\n\nactor           :: (forall s . ST s l t) -> Actor t\n_new            :: Actor a -> a -> ST s l a\n\n_asyn           :: (a -> ST s l b) -> Async l a b\n_snd            :: Async l' a b -> a -> ST s l (Msg l' b)\nawait           :: Less l l' => Msg l' a -> ST s l a\n\nafter           :: Int -> ST s l a -> ST s l ()\n\nvar             :: a -> ST s l (Var s l a)\nreadv           :: Var s l a -> ST s l a\nwritev          :: Var s l a -> a -> ST s l ()\n\nprints          :: String -> ST s l ()\npass            :: ST s l ()\nmsg             :: a -> ST s l (Msg l' a)\n\n\nactor a         = undefined\nawait m         = undefined\nafter t p       = undefined\n\nvar e           = undefined\nreadv v         = undefined\nwritev v e      = undefined\n\nprints s        = undefined\npass            = undefined\nmsg             = undefined\n\n_asyn p         = undefined\n_snd            = undefined\n_new            = undefined\n\npingpong        :: Int -> Actor (Async l Int ())\npingpong i      = actor $ do\n                    count <- var 0\n                    let ping q = do\n                            c <- readv count\n                            writev count (c+1)\n                            prints (\"Ping \" ++ show (c*q))\n                            after 1 (pong c (-q))\n                        pong n q = do\n                            prints (\"Pong \" ++ show (n*q))\n                            after 2 (ping (-q))\n                    ping i\n                    return (_asyn ping)\n\nsession         :: (Less l_conn l_me) => Conn l_conn -> Async l_cb String () -> Actor (Async l_me (String, Async l_cb Int ()) (), Async l_me (String,String) (), Async l_me () ())\nsession conn error_cb = actor $ do\n                message_id <- var 1\n                responder <- var Nothing\n                let get (path, reply_cb) = do\n                        m_id <- readv message_id\n                        _snd (deliver conn) (print_rpc m_id \"get\" (print_path path \"\"))\n                        writev responder $ Just $ \\text -> _snd reply_cb (xml_parse $ strip_path path $ strip_reply m_id \"data\" text)\n                    edit_config (path, value) = do\n                        m_id <- readv message_id\n                        _snd (deliver conn) (print_rpc m_id \"edit-config\" (print_path path $ xml_print value))\n                        writev responder $ Just $ \\text -> msg $ xml_parse_empty (strip_reply m_id \"ok\" text)\n                    abort () = do\n                        _snd (close conn) ()\n                        return ()\n                    _receive text = do\n                        r <- readv responder\n                        case r of\n                          Just resp -> resp text `catchError` \\ex -> _snd error_cb (show ex)\n                          _ -> undefined\n                        m_id <- readv message_id\n                        writev message_id (m_id + 1)\n                    _error what = do\n                        _snd error_cb what\n                        writev responder Nothing\n                _snd (receive_on conn) (_asyn _receive, _asyn _error)\n                return (_asyn get, _asyn edit_config, _asyn abort)\n\ndata Conn l     = Conn\n\ndeliver         :: Conn l -> Async l String ()\nclose           :: Conn l -> Async l () ()\nreceive_on      :: (Less l l1, Less l l2) => Conn l -> Async l (Async l1 String (), Async l2 String ()) ()\n-- The Less constraints above make no obvious sense here, they are only added for testing purposes.\n\ndeliver         = undefined\nclose           = undefined\nreceive_on      = undefined\n\nprint_rpc       :: Int -> String -> String -> String\nprint_path      :: String -> String -> String\nstrip_reply     :: Int -> String -> String -> String\nstrip_path      :: String -> String -> String\nxml_print       :: Show a => a -> String\nxml_parse       :: Read a => String -> a\nxml_parse_empty :: String -> ()\n\nprint_rpc       = undefined\nprint_path      = undefined\nstrip_reply     = undefined\nstrip_path      = undefined\nxml_print       = undefined\nxml_parse       = undefined\nxml_parse_empty = undefined\n\n"
  },
  {
    "path": "compiler/tests/CPretty.hs",
    "content": "-- Copyright (C) 2019-2021 Data Ductus AB\n--\n-- Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:\n--\n-- 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.\n--\n-- 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.\n--\n-- 3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission.\n--\n-- THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS \"AS IS\" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n--\n\nmodule Tests.CPretty where\n\nimport Pretty\nimport Acton.Syntax\nimport Data.List\nimport Data.Maybe\nimport Acton.Printer\nimport Utils\nimport Prelude hiding ((<>))\n\ncprint m@Module{} = cpretty (CEnv True) m\n\ndata CEnv = CEnv {isglobal :: Bool}\n\nclass CPretty a where\n  cpretty :: CEnv -> a -> Doc\n\ninstance CPretty a => CPretty [a] where\n   cpretty env ss                       = vcat (map (cpretty env) ss)\n   \ninstance CPretty Module where\n   cpretty env (Module  _ _ ss)         =  text \"#pragma once\" $+$ blank $+$\n                                           text \"#include \\\"common.h\\\"\" $+$ blank $+$\n                                           vcat (map (structdecls . cpretty env . name) [\"list\",\"dict\",\"set\",\"str\",\n                                                \"int\",\"float\",\"complex\",\"bool\",\"Iterator\",\"Slice\"] ++\n                                                concat (concatMap (structs env) ss) ++\n                                                map (cpretty env) ss\n                                               )\n\nstructs env (Decl  _ ds)                = map strs ds\n  where strs (Class _ nm qs bs ss) \n                                        = [structdecls cnm, structdecls (cnm <> text \"$class\")] ++\n                                          case nm of\n                                             Name{} -> [structdecls (cnm <> text \"$opaque\")]\n                                             _ -> []\n           where cnm                    = cpretty env nm\n        strs _                          = []\nstructs _ _                             = []\n\n                     \ninstance CPretty Stmt where\n   cpretty env (Decl _ ds)              = vcat (map (cpretty env) ds)\n   cpretty env (Signature _ ns (TSchema _ _ (TFun _ f p _ r)) _)\n                                        = if (isglobal env)\n                                          then vcat (map (\\n -> resultTuple env r <+> cpretty env n<>parens (cprettyPosRow env p) <>semi) ns)\n                                          else vcat (map (\\n -> resultTuple env{isglobal=True} r <+> parens (text \"*\"<> cpretty env n)<>parens (cprettyPosRow env{isglobal=True} p) <>semi) ns)\n   cpretty env (Signature _ ns tsc  _)  = vcat (map (\\n ->cpretty env{isglobal=True} tsc<+> cpretty env n<>semi) ns)\n   cpretty env stmt                     = empty \n   \ninstance CPretty Decl where\n   cpretty env (Class _ nm qs bs ss)    = vcat (map ($+$ blank) [\n                                              text \"//\" <+> cnm <+> text (replicate 60 '/'),\n                                              witness_struct env{isglobal=False} cnm is,\n                                              class_struct env{isglobal=False} nm ms,\n                                              case nm of\n                                                  Name{} -> opaque_struct cnm ms\n                                                  _ -> fun_prototypes env nm ms\n                                           ])\n     where (ms,is)                      = partition isMeth ss\n           cnm                          = cpretty env nm\n      \n   cpretty env d                        = error (\"cpretty: unexpected Decl: \"++show d)\n\nisMeth (Signature _ _ sc _)             = isFunType (sctype sc)\n   where isFunType (TFun {})            = True\n         isFunType _                    = False\nisMeth _                                = False\n\n \ninstance CPretty TBind where\n   cpretty env  (TBind tv bs) = vcat (map (\\b -> cpretty env b<>pretty tv) bs)\n\ninstance CPretty TCon where\n   cpretty env (TC qn _)                = cpretty env qn\n\ninstance CPretty TSchema where\n    cpretty env (TSchema _ _ t)         = cpretty env t\n\ninstance CPretty Name where\n  cpretty env n@Internal{}              = text (nstr n)\n  cpretty env n\n      | nstr n==\"_Complex\"              = text \"_Complx\"\n      | nstr n==\"__complex__\"           = text \"__complx__\"\n      | isglobal env                    = text ('$' : nstr n)\n      | otherwise                       = text (nstr n)\n \n\ninstance CPretty ModName where\n    cpretty env (ModName ns)            = hsep $ punctuate (text \"$$\") (map (cpretty env) ns)\n    \ninstance CPretty QName where\n    cpretty env (QName mn n)            = cpretty env mn<>text \"$$\"<>cpretty env n\n    cpretty env (NoQ n)                 = cpretty env n\n    \ninstance CPretty Type where\n    cpretty env (TVar _ v)              = text \"$WORD\"\n    cpretty env (TCon  _ c)             = cpretty env c\n    cpretty env (TFun _ e p _ t)        = cpretty env t <+> parens (cprettyPosRow env p)\n    cpretty env (TTuple _ p _)          = parens (cprettyPosRow env p)\n    cpretty env (TUnion _ as)           = parens (vbarSep pretty as)\n      where vbarSep f                   = hsep . punctuate (space <> char '|') . map f\n    cpretty env (TOpt _ t)              = cpretty env t\n    cpretty env (TNone _)               = text \"void\"\n    cpretty env (TWild _)               = text \"_\"\n    cpretty env row                     = prettyKwdRow row\n\ncprettyPosRow env (TRow _ _ _ t TNil{}) = cpretty env t\ncprettyPosRow env (TRow _ _ _ t p)      = cpretty env t <> comma <+> cprettyPosRow env p\ncprettyPosRow env TNil{}                = empty\n\nstructdecls cnm                         = text \"struct\" <+> cnm <> semi $+$\n                                          text \"typedef struct\" <+> cnm <+> text \"*\" <> cnm <> semi $+$\n                                          blank\n\nwitness_struct env cnm is               = text \"struct\" <+> cnm <+> text \"{\" $+$\n                                          (nest 4 $ vcat ([--text \"char *$GCINFO;\",\n                                                           cnm <> text \"$class\" <+>text\"$class\"<>semi] ++\n                                                           [vcat (map (cpretty env) is)])) $+$\n                                           text \"};\"\n\nclass_struct                            ::  CEnv -> Name -> [Stmt] -> Doc\nclass_struct env nm ms                  = text \"struct\" <+> cpretty env{isglobal=True} nm<>text \"$class\" <+> text \"{\" $+$\n                                          (nest 4 $ text \"char *$GCINFO;\" $+$ vcat (map (cpretty env . addparSig nm) ms)) $+$\n                                          text \"};\"\n  where addparSig nm (Signature l ns (TSchema l2 qs (TFun l3 f p k r)) d)\n                                        =  Signature l ns (TSchema l2 qs (TFun l3 f (addFstElem nm p)  k r)) d\n\naddFstElem nm p                         = posRow (tCon (TC (NoQ nm) [])) p\n\nopaque_struct  cnm ms                   = text \"struct\" <+> cnm<>text \"$opaque\" <+> text \"{\" $+$\n                                          (nest 4 $ text \"char *$GCINFO;\" $+$\n                                          vcat [cnm <+> text \"proto\"<>semi,\n                                                text \"$WORD impl\"<>semi]) $+$\n                                          text \"};\" $+$ blank $+$\n                                          cnm<>text \"$opaque\" <+> cnm<>text \"$pack\"<>parens (cnm <+>text \"proto, $WORD impl\") <> semi $+$\n                                          blank\n\nfun_prototypes env nm ss                = vcat (map proto ss)\n  where proto (Signature _ ns (TSchema _ _ (TFun _ f p _ r)) _)\n                                        = vcat (map (\\n -> resultTuple env r <+> cpretty env nm<>cpretty env n<+>parens (cprettyPosRow env (addFstElem nm p)) <>semi) ns)\n\n\nresultTuple env (TTuple  _ r _)          = tup 0 r\n   where tup n (TNil _ _)                = text (\"$tup\"++show n++\"_t\")\n         tup n (TRow _ _ _ _ r)          = tup (n+1) r\n         tup _ r                         = error (\"cPrettyPosRow: unhandled tuple; row is \"++render(pretty r))\nresultTuple env t                        = cpretty env t\n"
  },
  {
    "path": "compiler/tests/ProtExtElim.hs",
    "content": "-- Copyright (C) 2019-2021 Data Ductus AB\n--\n-- Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:\n--\n-- 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.\n--\n-- 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.\n--\n-- 3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission.\n--\n-- THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS \"AS IS\" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n--\n\nmodule Tests.ProtExtElim where\n\nimport Data.Maybe\nimport Data.List\nimport Acton.Env\nimport Pretty\nimport Utils\nimport Acton.Syntax\n\n\n-- Transform a file containing protocol definitions, extensions and signatures.\n-- Intended use is to translate large parts of module __builtin__ to C.\ntransform m@(Module nm is stmts)        = Module nm is (map (Decl NoLoc . (:[])) (trans env ps) ++\n                                                        map (Decl NoLoc . (:[])) (concatMap (transExt env) es) ++\n                                                        trans env ss)\n  where (ps,cs,es,ss)                   = splitStmts stmts\n        -- ignore classes; builtin classes have handcrafted C code.\n        -- for now, no defs or actors.\n        env                             = newTransEnv (protocolsOf m)\n\n-----------------------------------------------------------------------------------------------------\n \ndata TransEnv                           = TransEnv {protocols :: [(Name,Decl)],\n                                                    decor :: Deco,\n                                                    fstpar :: Maybe Type,\n                                                    master :: Maybe TCon\n                                                   }\n                                                    \nnewTransEnv ps                          = TransEnv ps NoDec Nothing Nothing\n\nsplitStmts stmts                        = sp stmts [] [] [] []  -- protocols, classes, extensions, signatures\n  where sp [] ps cs es ss               = (reverse ps,reverse cs,reverse es,reverse ss)\n        sp (Decl _ ds : stmts ) ps cs es ss\n                                         = spdecl ds stmts ps cs es ss\n        sp (s@Signature{} : stmts) ps cs es ss\n                                        = sp stmts ps cs es (s  : ss)\n        spdecl [] stmts ps cs es ss     = sp stmts ps cs es ss\n        spdecl (p@Protocol{} : ds) stmts ps cs es ss\n                                        = spdecl ds stmts (p : ps) cs es ss\n        spdecl (c@Class{} : ds) stmts ps cs es ss\n                                        = spdecl ds stmts ps (c : cs) es ss\n        spdecl (e@Extension{} : ds) stmts ps cs es ss  -- ignore defs\n                                        = spdecl ds stmts ps cs (e : es) ss\n        spdecl (d@Def{} : ds) stmts ps cs es ss  \n                                        = spdecl ds stmts ps cs es ss\n                                        \nclass Transform a where\n    trans                               :: TransEnv -> a -> a\n\ninstance Transform a => Transform [a] where\n    trans env as                        = map (trans env) as\n   \ninstance Transform Module where\n    trans env (Module nm is ss)         = Module nm is $ trans env ss\n\ninstance Transform Stmt where\n    trans env (Decl loc ds)             = Decl loc $ trans env ds\n    trans env (Signature loc ns t d)    = Signature loc ns (trans env{decor=d} t) (if d == Static then NoDec else d) \n    trans env stmt                      = stmt\n\ninstance Transform Decl where\n    trans env (Protocol loc n qs bs ss) = case transParents tv bs of\n                                               [] -> Class loc n (tBind v:qs1) [] ss2\n                                               b:_ -> Class loc n  (tBind v:qs1) [trans env b] (addWitnesses env bs1 ss2)\n      where v                           = head (drop 15 tvarSupply Utils.\\\\ tybound qs)  -- we just prefer letters later in the alphabet for this type variable...\n            tv                          = tVar v\n            ss1                         = trans env{fstpar = Just tv} (addSigs (protocols env) bs ++ ss)\n            initSig                     = Signature NoLoc [name \"__init__\"] (monotype (tFun0 (map tCon (maybe [] (:[]) (master env) ++ws)) tNone)) Static\n            (qs1,ws)                    = transParams qs\n            ss2                         = initSig : addWitnesses env ws ss1   \n            cs                          = chains (protocols env) bs\n            bs1                         = transParents tv (if null cs then [] else map head (tail cs))\n    trans env d                         = d\n\ninstance Transform TSchema where\n    trans env (TSchema loc bs t)        = TSchema loc (trans env bs) (trans env t)\n                                              \ninstance Transform Type where\n    trans env (TVar loc (TV k (Name _ \"Self\")))\n                                        = fromJust (fstpar env)\n    trans env v@TVar{}                  = v\n    trans env (TTuple loc p k)          = TTuple loc (trans env p) (trans env k)\n    trans env (TFun loc fx p k r)       = TFun loc fx p1 (trans env k) (trans env r)\n       where p1                         = if decor env == Static\n                                          then trans env p\n                                          else maybe (trans env p) (flip posRow (trans env p)) (fstpar env)\n    trans env (TOpt loc t)              = TOpt loc $ trans env t\n    trans env (TRow loc k nm s r)       = TRow loc k nm (trans env s) (trans env r)\n--    trans env (TCon loc tc)             = maybe (TCon NoLoc (trans env tc)) (const (TExist NoLoc (trans env tc))) (lookup (noq (tcname tc)) (protocols env))\n--    trans env (TExist _ tc)             = TExist NoLoc (trans env tc)\n    trans env t                         = t\n\ninstance Transform TCon where\n    trans env (TC qn ts)                = TC (trans env qn) (trans env ts)\n\ninstance Transform TBind where\n    trans env (TBind tv tcs)            = TBind tv (trans env tcs)\n\ninstance Transform QName where\n    trans env (QName _ nm)              = NoQ nm\n    trans env qn                        = qn\n\ninstance Transform Name where\n    trans env nm                        = nm\n\n-- adds witnesses to superprotocols other than the first mentioned.\naddWitnesses env ws ss                  = map mkSig ws ++ ss\n  where mkSig tc                         = Signature NoLoc [name ('_' : nstr (noq (tcname tc)))] (monotype (tCon (trans env tc))) NoDec\n\ntransParents tv bs                      = map addP bs\n   where addP (TC qn ts)                = TC qn (tv : ts)\n\n-- transforms [A(Eq), B, C(Hashable)] into ([A,B,C],[Eq[A],Hashable[C]])\ntransParams                             :: QBinds -> (QBinds,[TCon])\ntransParams qs                          = trP qs [] []\n   where trP [] ws qs1                  = (reverse qs1,reverse ws)\n         trP (TBind tv cs:qs) ws qs1    = trP qs ([TC nm [tVar tv] | TC nm _ <- cs]++ws) (tBind tv : qs1) \n\n---------------------------------------------------------------------------------------------------------\n--\n-- To transform an extension we assume for the moment that only one protocol is mentioned.\n-- We find all ancestor protocols and replace this tree with linear chains with only single\n-- inheritance.\n--\n-- As an example, if the inheritance structure is\n--\n--  Sequence-> Sliceable -> Indexed\n--          |\n--          -> Collection -> Iterable\n--          |\n--          -> Plus\n--\n-- we form the three chains  Sequence->Sliceable->Indexed ,  Collection->Iterable ,  Plus,\n-- each of which will be transformed to one class definition.\n--\n-- transExt constructs the chains and calls transChain for each chain to build the class definition.\n---------------------------------------------------------------------------------------------------------\n\ntransExt                                :: TransEnv -> Decl -> [Decl]\ntransExt env e@(Extension l nm qs bs ss)\n         | length bs /= 1               = error \"For now, an extension must implement exactly one protocol\"\n         | otherwise                    = transChain Nothing env (head bs) e cs\n         where as                       = head bs : ancestors env (noq (tcname (head bs)))\n               cs                       = chains (protocols env) as\n\ntransChain                              :: Maybe Type -> TransEnv  -> TCon -> Decl -> [[TCon]] -> [Decl]\ntransChain _ _ _ _ []                   = []\ntransChain mb env b e (c : cs)          = c2{dname = c2nm, dbody = sigs} : transChain (Just witType) env{master = Just b} b e cs\n   where cn                             = noq (tcname (head c))\n         prot                           = fromJust (lookup cn (protocols env))\n         c1                             = trans env prot{qual = qual e ++ qual prot} \n         ts                             = trans env (tCon (mkTC (dqname e) (qual e)) : tcargs (head (bounds e)))\n         (_,ws)                         = transParams (qual e)\n         c2                             = substAll ts c1 \n         tc                             = head (bounds c2)\n         c2nm                           = Derived (dname c2) (noq (dqname e))\n         witType                        = maybe (tCon tc) id mb\n         sigs                           = maybe [] (\\(TCon _ (TC nm _))->[Signature NoLoc [name ('_':nstr (noq nm))] (monotype witType) NoDec]) mb\n                                          ++ nub (dbody c2) -- nub (addWitnesses env ws (dbody c2))\n\n\nsubstAll ts (Class l nm qs bs ss)       = Class l nm (nub $ map tBind (ufree ts)) [tc] (subst2 s ss)\n   where s                              = tVars qs `zip` ts\n         tc                             = subst2 s (mkTC (NoQ nm) qs)\n\n\naddSigs                                 :: [(Name,Decl)] -> [TCon] -> [Stmt]\naddSigs ps []                           = []\naddSigs ps (TC n qs : _)                = addSigs ps (subst2 s (bounds p)) ++ subst2 s methodSigs\n  where p                               = fromJust (lookup (noq n) ps)\n        s                               = tVars (qual p) `zip` qs\n        methodSigs                      = [sig | sig@(Signature _ _ sc _) <- dbody p, isFunSchema sc ] \n          where isFunSchema sc          = isFunType (sctype sc)\n                isFunType (TFun {})     = True\n                isFunType _             = False\n\nsubst2                                  :: Subst a => Substitution -> a -> a\nsubst2 s                                = subst s2 . subst s1\n  where (s1,s2)                         = partition (\\p -> null (ufree(snd p) `intersect` (ufree (dom s)))) (red s)\n        red []                          = []\n        red ((tv,TVar _ tv') : ps)\n            |tv == tv'                  = red ps\n        red (p:ps)                      = p : red ps\n\nmkTC nm qs                              = TC nm $ map (\\(TBind tv _) -> tVar tv) qs\n\ntVars qs                                = map (\\(TBind tv _) -> tv) qs\n \nprotocolsOf (Module _ _ ss)             = [(dname p,p) |  Decl _ ds <- ss, p@(Protocol{}) <- ds]\n\nparentsOf p                             = map (noq . tcname) (bounds p)\n\nancestors                               ::  TransEnv -> Name -> [TCon]\nancestors env n                         = ps ++ concatMap (ancestors env) (map (noq . tcname) ps)\n    where ps                            = bounds (fromJust (lookup n (protocols env)))\n  \nchains                                  :: [(Name,Decl)] -> [TCon] -> [[TCon]]\nchains ps []                            = []\nchains ps (b:bs)                        = cs : chains ps [ b | b@(TC qn ts) <- bs, qn `notElem` map tcname cs ]\n   where cs                             = fstParents ps b\n         fstParents ps b@(TC qn ts)     = case lookup (noq qn) ps of\n                                             Just (Protocol _ _ _ bs _) -> case bs of\n                                                                        [] -> [b]\n                                                                        p:_ -> b : fstParents ps p\n                                             Nothing -> error (\"cannot find protocol \"++show qn) \n "
  },
  {
    "path": "compiler/tests/TestTransform.hs",
    "content": "-- Copyright (C) 2019-2021 Data Ductus AB\n--\n-- Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:\n--\n-- 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.\n--\n-- 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.\n--\n-- 3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission.\n--\n-- THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS \"AS IS\" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n--\n\nimport qualified Acton.Parser as P\nimport System.Environment\nimport System.IO\nimport Pretty\nimport Acton.Printer\nimport Acton.Syntax\nimport Tests.ProtExtElim\nimport Tests.CPretty\nimport InterfaceFiles\n\n\nmain                  = do src <- readFile \"__builtin__.act\"\n                           m <- P.parseModule (ModName [name \"__builtin__\"]) \"__builtin__.act\" src Nothing\n                           let m1  = transform m\n                           putStrLn (render(cprint m1))\n\n\n"
  },
  {
    "path": "compiler/tests/actorring.act",
    "content": "# Copyright (C) 2019-2021 Data Ductus AB\n#\n# Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:\n#\n# 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.\n#\n# 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.\n#\n# 3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission.\n#\n# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS \"AS IS\" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n#\n\nno_actors = 5\ntotal_msgs = 20\n\nactor Act(i):\n    var count = 0\n    var rcv_dict = {}\n    var snd_dict = {}\n\n    def work(src, table):\n        if count < total_msgs:\n            count += 1\n            dst = (i + 1) % no_actors\n            rcv_dict[src] = rcv_dict.get(src,0) + 1\n            snd_dict[dst] = snd_dict.get(dst,0) + 1\n            print(\"Actor %d: count=%d, src=%d, dst=%d\" % (i,count,src,dst))\n            table[dst].work(i, table)\n\nactor Root(_ignore:Env):\n    table = []\n\n    for i in range(no_actors,None,None):\n        table.append(Act(i))\n\n    table[0].work(no_actors, table)\n"
  },
  {
    "path": "compiler/tests/controller.act",
    "content": "# Copyright (C) 2019-2021 Data Ductus AB\n#\n# Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:\n#\n# 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.\n#\n# 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.\n#\n# 3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission.\n#\n# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS \"AS IS\" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n#\n\nimport netconf\n\nactor Controller(env, address, port):\n    \n    var nc = None\n    var state = 'IDLE'\n    var setting = 0\n    \n    def restart(what):\n        if nc is not None:\n            nc.abort()\n            nc = None\n        print('Controller', str(address) + ':' + str(port), what)\n        netconf.connect(env, address, port, _established, _error)\n        state = 'IDLE'\n\n    def _established(sess):\n        if sess is not None:\n            nc = sess\n            after 10: _tick()\n        else:\n            restart('connection failure')\n    \n    def _tick():\n        if state == 'IDLE':\n            state = 'GET'\n            after 10: _tick()\n            nc.get('/oper/thevalue', _reply)\n        else:\n            restart('timeout')\n    \n    def _reply(newval):\n        if state == 'GET':\n            setting = compute(setting, newval)\n            nc.edit_config('/config/settings/thesetting', setting)\n            state = 'IDLE'\n        else:\n            restart('stray reply')\n            \n    def _error(what):\n        restart('NETCONF error: ' + what)\n\n    restart('initial')\n\n\ndef compute(setting, newval):\n    return (setting + newval) // 2\n\n"
  },
  {
    "path": "compiler/tests/counter.act",
    "content": "# Copyright (C) 2019-2021 Data Ductus AB\n#\n# Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:\n#\n# 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.\n#\n# 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.\n#\n# 3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission.\n#\n# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS \"AS IS\" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n#\n\nactor Counter():\n    var count = 0\n    def inc():\n        count = count + 1\n    def get():\n        return count\n\nactor main(env: Env):\n    c = Counter()\n    def _step():\n        print('inc')\n        c.inc()\n        x = c.get()\n        print('get = %d' % x)\n        after 1: _step()\n    _step()\n\n"
  },
  {
    "path": "compiler/tests/env.act",
    "content": "# Copyright (C) 2019-2021 Data Ductus AB\n#\n# Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:\n#\n# 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.\n#\n# 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.\n#\n# 3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission.\n#\n# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS \"AS IS\" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n#\n\nclass Env (struct):\n    open        : action(str, int, action(?Connection)->None) -> None\n\nclass Connection:\n    deliver     : action(data: str) -> None\n    close       : action() -> None\n    receive_on  : action(input: action(str)->None, error: action(str)->None) -> None\n\nactor _EnvActor ():\n    def do_open(str, int, on_success):\n        pass\n\nclass _Env (Env):\n    def __init__(self, actual):\n        self.actual = actual\n    def open(self, address: str, port: int, on_success):\n        self.actual.do_open(address, port, on_success)\n    # or, using a (tentative) notational shorthand:\n    # open = self.actual.open\n\n \n# struct Env;\n# typedef struct Env *Env;\n# struct Env$__class__;\n# typedef struct Env$__class__ *Env$__class__;\n# \n# struct Connection;\n# typedef struct Connection *Connection;\n# struct Connection$__class__;\n# typedef struct Connection$__class__ *Connection$__class__;\n# \n# struct Env {\n#     Env$__class__ __class__;\n#     $WORD __impl__;\n# };\n# struct Connection {\n#     Connection$__class__ __class__;\n#     $WORD __impl__;\n# };\n# struct Env$__class__ {\n#     char *$GCINFO;\n#     $Msg (*open)(Env$__class__, $WORD, $str, $int, $Clos);\n# };\n# struct Connection$__class__ {\n#     char *$GCINFO;\n#     $Msg (*deliver)(Connection$__class__, $WORD, $str);\n#     $Msg (*close)(Connection$__class__, $WORD);\n#     $Msg (*receive_on)(Connection$__class__, $WORD, $Clos, $Clos);\n# };\n"
  },
  {
    "path": "compiler/tests/env.c",
    "content": "/*\n * Copyright (C) 2019-2021 Data Ductus AB\n *\n * Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:\n *\n * 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.\n *\n * 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.\n *\n * 3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission.\n *\n * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS \"AS IS\" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n */\n\n#include \"rts.h\"\n\n// protocol Connection  ///////////////////////////////////////////////////////////////////////////////////\n\nstruct Connection;\ntypedef struct Connection *Connection;\nstruct ConnectionD___class__;\ntypedef struct ConnectionD___class__ *ConnectionD___class__;\n\nstruct Connection {\n    ConnectionD___class__ __class__;\n    $WORD __impl__;\n};\nstruct ConnectionD___class__ {\n    char *$GCINFO;\n    B_Msg (*deliver)(ConnectionD___class__, $WORD, B_str);\n    B_Msg (*close)(ConnectionD___class__, $WORD);\n    B_Msg (*receive_on)(ConnectionD___class__, $WORD, $function, $function);\n};\n\nConnection ConnectionD___pack__(ConnectionD___class__ __class__, $WORD __impl__) {\n    Connection conn = malloc(sizeof(struct Connection));\n    conn->__class__ = __class__;\n    conn->__impl__ = __impl__;\n    return conn;\n}\n\n// protocol Env  //////////////////////////////////////////////////////////////////////////////////////////\n\nstruct Env;\ntypedef struct Env *Env;\nstruct EnvD___class__;\ntypedef struct EnvD___class__ *EnvD___class__;\n\nstruct Env {\n    EnvD___class__ __class__;\n    $WORD __impl__;\n};\nstruct EnvD___class__ {\n    char *$GCINFO;\n    B_Msg (*open)(EnvD___class__, $WORD, B_str, B_int, $function);\n};\n\nEnv EnvD___pack__(EnvD___class__ __class__, $WORD __impl__) {\n    Env env = malloc(sizeof(struct Env));\n    env->__class__ = __class__;\n    env->__impl__ = __impl__;\n    return env;\n};\n\n// class TrueConnection ///////////////////////////////////////////////////////////////////////////////////\n\nstruct TrueConnection;\ntypedef struct TrueConnection *TrueConnection;\n\nstruct TrueConnection {\n    int socket;\n    $function input_callback;\n    $function error_callback;\n    // more...\n};\n\nB_Msg TrueConnection$deliver (ConnectionD___class__ cls, $WORD __impl__, B_str data) {\n    TrueConnection trueSelf = (TrueConnection)__impl__;\n    return NULL;\n}\n\nB_Msg TrueConnection$close (ConnectionD___class__ cls, $WORD __impl__) {\n    TrueConnection trueSelf = (TrueConnection)__impl__;\n    return NULL;\n}\n\nB_Msg TrueConnection$receive_on (ConnectionD___class__ cls, $WORD __impl__, $function input, $function error) {\n    TrueConnection trueSelf = (TrueConnection)__impl__;\n    return NULL;\n}\n\nstruct ConnectionD___class__ Connection___TrueConnection = {\n    .$GCINFO    = \"Connection\",\n    .deliver    = TrueConnection$deliver,\n    .close      = TrueConnection$close,\n    .receive_on = TrueConnection$receive_on\n};\n\n// class TrueEnv  /////////////////////////////////////////////////////////////////////////////////////////\n\nstruct TrueEnv;\ntypedef struct TrueEnv *TrueEnv;\n\nB_Msg TrueEnv$open(EnvD___class__ cls, $WORD __impl__, B_str address, B_int port, $function callback) {\n    TrueEnv self = (TrueEnv)__impl__;\n    \n    TrueConnection trueConn = /* create socket, etc, ... */ NULL;\n    Connection conn = ConnectionD___pack__(&Connection___TrueConnection, trueConn);\n    B_Msg m = /* ASYNC... */ NULL;\n    return m;\n}\n\nstruct EnvD___class__ Env___TrueEnv = {\n    .$GCINFO    = \"Env\",\n    .open       = TrueEnv$open\n};\n\nstruct TrueEnv {\n    // empty? Or selector_fd?\n};\n\n// main //////////////////////////////////////////////////////////////////////////////////////////////////\n\nint main() {\n    // ...\n    TrueEnv trueEnv = /* create whatever... */ NULL;\n    Env env = EnvD___pack__(&Env___TrueEnv, trueEnv);\n    // BOOTSTRAP($CONTINUATION(ROOT, 1, ($WORD)env));\n    // ... \n}"
  },
  {
    "path": "compiler/tests/netconf.act",
    "content": "# Copyright (C) 2019-2021 Data Ductus AB\n#\n# Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:\n#\n# 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.\n#\n# 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.\n#\n# 3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission.\n#\n# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS \"AS IS\" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n#\n\nimport xml\n\n\ndef connect(env, address, port, established_cb, error_cb):\n    env.open(address, port, lambda conn: established_cb(session(conn, error_cb)))\n\n\n\n    \nactor session(conn, error_cb):\n\n    var message_id = 1\n    var responder = None\n    \n    def get(path, reply_cb):\n        conn.deliver(print_rpc(message_id, 'get', print_path(path, '')))\n        responder = lambda text: reply_cb(xml.parse(strip_path(path, strip_reply(message_id, 'data', text))))\n    \n    def edit_config(path, value):\n        conn.deliver(print_rpc(message_id, 'edit-config', print_path(path, xml.print(value))))\n        responder = lambda text: xml.parse_empty(strip_reply(message_id, 'ok', text))\n\n    def abort():\n        conn.close()\n\n    def _receive(text):\n        try:\n            if responder:\n                responder(text)\n        except xml.ParseError as ex:\n            error_cb(str(ex))\n        except ValueError as ex:\n            error_cb(str(ex))\n        message_id += 1\n    \n    def _error(what):\n        error_cb(what)\n        responder = None\n    \n    conn.receive_on(_receive, _error)\n\n\n\n\n\ndef print_rpc(message_id, second_tag, inner):\n    strs = []\n    strs.append('<rpc xmlns=\"urn:ietf:params:xml:ns:netconf:base:1.1” message-id=\"' + str(message_id) + '\">')\n    strs.append('<' + second_tag + '>')\n    strs.append('</' + second_tag + '>')\n    strs.append('</rpc>')\n    return ''.join(strs)\n\ndef strip_reply(message_id, second_tag, text):\n    prefix = '<rpc-reply xmlns=\"urn:ietf:params:xml:ns:netconf:base:1.1\" message-id=\"' + str(message_id) + '\">'\n    suffix = '</rpc-reply>'\n    text = text.strip()\n    if text.startswith(prefix) and text.endswith(suffix):\n        text = text[len(prefix):-len(suffix)].strip()\n        prefix = '<' + second_tag + '>'\n        suffix = '</' + second_tag + '>'\n        if text.startswith(prefix) and text.endswith(suffix):\n            return text[len(prefix):-len(suffix)]\n        elif text == '<' + second_tag + '/>':\n            return ''\n    raise xml.ParseError\n\ndef print_path(path, inner):\n    elems = path.split('/')\n    if elems[0] != '':\n        raise ValueError\n    if elems[-1] == '':\n        elems.pop()\n    strs = []\n    for elem in elems[1:]:\n        strs.append('<' + elem + '>')\n    strs.append(inner)\n    for elem in elems[-1:0:-1]:\n        strs.append('</' + elem + '>')\n    return ''.join(strs)\n\ndef strip_path(path, text):\n    elems = path.split('/')\n    if elems[0] != '':\n        raise ValueError\n    if elems[-1] == '':\n        elems.pop()\n    for elem in elems[1:]:\n        text = text.strip()\n        prefix = '<' + elem + '>'\n        suffix = '</' + elem + '>'\n        if text.startswith(prefix) and text.endswith(suffix):\n            text = text[len(prefix):-len(suffix)]\n        else:\n            raise xml.ParseError\n    return text\n"
  },
  {
    "path": "compiler/tests/newtuple.act",
    "content": "# Copyright (C) 2019-2021 Data Ductus AB\n#\n# Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:\n#\n# 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.\n#\n# 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.\n#\n# 3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission.\n#\n# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS \"AS IS\" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n#\n\nt1 = (3,5)\nt2 = (3)\nt3 = (3,)\nt4 = (3,x=5)\nt5 = (*e,x=5,)\nt6 = (x=5,)\nt7 = (x=5,**t)\n\n(y,a = x) = e\n"
  },
  {
    "path": "compiler/tests/pingpong.act",
    "content": "# Copyright (C) 2019-2021 Data Ductus AB\n#\n# Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:\n#\n# 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.\n#\n# 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.\n#\n# 3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission.\n#\n# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS \"AS IS\" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n#\n\n\nactor Pingpong(env: Env):\n    var count = 0\n    i = int(env.argv[1])\n    def _ping():\n        count = count + i\n        print('%d Ping %8d' % (i,count))\n        after 1: _pong(-count)\n    def _pong(q):\n        print('%d      %8d Pong' % (i,q))\n        after 2: _ping()\n    _ping()\n\n"
  },
  {
    "path": "compiler/tests/records.act",
    "content": "# Copyright (C) 2019-2021 Data Ductus AB\n#\n# Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:\n#\n# 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.\n#\n# 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.\n#\n# 3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission.\n#\n# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS \"AS IS\" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n#\n\nr1 = {x : int}\nr2 = {x:int,y:bool}\nr3 = {x:int,y:bool,}\nr4 = {x:int,y:bool,**f(a)}\nr5 = {x:int,y:bool,**f(a),}\nr6 = {**f(x,y)}\nr7 = {a:b for a,b in g(t)}\nr8 = {a:b for a,b, in g(t)}\n"
  },
  {
    "path": "compiler/tests/test.act",
    "content": "# Copyright (C) 2019-2021 Data Ductus AB\n#\n# Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:\n#\n# 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.\n#\n# 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.\n#\n# 3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission.\n#\n# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS \"AS IS\" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n#\n\nx0 : (x: int, y: int)                                    # struct\nx1 : (x: int, y: A, **B)                                 # open struct; two fileds of the same type\nx2 : (int  | float)                                      # union\nx3 : ('str1' | 'str2' | int)                             # union with string literals\nx4 : (int,bool)                                          # tuple\nx5 : ?B12                                                # option type; type var\nx6 : Set[int]                                            # Class with type argument\nx7 : [A(Hashable), B, S(Mapping[A,B])] => (S)->dict[A,B] # Qualified/constrained type\nx8 : ((int) -> int,(b : bool),(int,int))                 # more complicated tuple\nx9 : act[X] (int,*A,b : bool,**B) -> set[int]            # function with effects and all kinds of parameters\n\nx10: action(int, *A, b: bool) -> Msg[int]\nx11: X(f: X(A)->B, a: [A]) -> [B]\n#x12: st[Y](int, list[Y,str]) -> str\n#x13: st(int, dict[int]) -> None\n#x14: mut[Y](int, list[Y,str]) -> str\n#x15: mut(int, dict[int]) -> None\n#x16: !Y(int, list[Y,str]) -> str\n#x17: !(int, dict[int]) -> None\n\na0 : (float,float) -> (float | 'division by zero')       # function without effects; union result\na1 : (str,*P,c : bool) -> None                           # function with * separation of pos and kwd parameters\na2 : (int) -> (int) -> int                               # higher order function\na3 : {int}                                               # set of ints (protocol)\na4 : [(float,bool)]                                      # list of tuples (protocol)\na5 : {{[int]}}                                           # more complicated set (protcol)\na6 : {[int]:(int) -> bool}                               # a dict (protocol)\na7 : (set[int],list[float],dict[{int},bool])             # tuple of mutable data structures\n\ny1 : (x: float, y: A, **B)                               # open struct\n#y2 : (**)                                                # open struct\ny3 : (**A)                                               # open struct\ny4 : (int, bool, *A)                                     # open tuple\n#y5 : (int, bool, *)                                      # open tuple\n#y6 : (*)                                                 # open tuple\ny7 : (*A)                                                # open tuple\ny8 : ()                                                  # empty tuple (should count as empty struct as well?)\n\nf0 : () -> int\nf1 : (int) -> bool\nf2 : (int,) -> int\nf3 : (int,bool) -> int\nf4 : (int,bool,) -> int\n#f5 : (int,bool,*) -> int\n#f6 : (int,bool,*,) -> int\nf7 : (int,bool,*A) -> int\nf8 : (int,bool,*A,) -> int\n#f9 : (*) -> int\n#f10 : (*,) -> int\nf11 : (*A) -> int\nf12 : (*A,) -> int\nf12a : (**A) -> bool\nf12b : (**A,) -> bool\n\nf13 : (x : float) -> int\nf14 : (x : float,) -> int\nf15 : (x : float, y : str) -> int\n#f16 : (x : float, y : str, **) -> int\nf17 : (x : float, y : str, **A) -> int\n#f18 : (x : float, y : str,**,) -> int\nf19 : (x : float, y : str,**A,) -> int\n\nf20 : (int, x : float) -> int\nf21 : (int, *A,x:float, **B,) -> int\nf22 : (,) -> int                                        # Should this really be allowed??\n\nz0 : (int,bool,*A,)\nz1 : (x : float)\nz2 : (x : (y : float,z : bool),**A,)\nz3 : [A]                                                # sequence that also could be the start of a qualified type\n\n\ndef elem [A(Eq), B(Ord)] (x:A, xs:[A]) -> B:        # function with explicit quant/qualifiers\n    pass\n\ndef f24():\n    pass\n    \ndef f25(a):\n    pass\n    \ndef f26(a,):\n    pass\n    \ndef f27(a,*b):\n#    a.0 = (7)\n#    a.*1 = (2,)\n    return ()\n    \ndef f28(a,*b,):\n    apa = (1,2,x=3,y='hello')\n    bepa = (1,2)\n    (cepa) = 3\n    (c,) = (4,)\n    (d,e) = a\n    \ndef f29(a,**b):\n    pass\n    \ndef f30(a,**b,):\n    pass\n    \ndef f31(a,*b,**c):\n    pass\n    \ndef f32(a,*b,**c,):\n    pass\n    \ndef f33(a,*b,c,**d):\n    pass\n    \ndef f34(a,*b:(int,*P),c,**d,):\n    pass\n\ndef f35(*a):\n    pass\n\ndef f35b(*a,):\n    pass\n\ndef f36(*a,**b:(x:int,**K)):\n    pass\n\ndef f37(*a,**b,):\n    pass\n\ndef f38(*a,b,**c):\n    pass\n\ndef f39(*a,b,**c,):\n    pass\n\ndef f40(**c):\n    pass\n\ndef f40b(**c,):\n    pass\n\n\nclass Apa:\n    @property\n    x : int\n    \n    def __init__(self):\n        self.x = 1\n\n    @staticmethod\n    def f(x):\n        pass\n\nif True:\n    while False:\n        pass\n\nprotocol Bepa [A] ():\n        \n    x : int\n    \n    @staticmethod\n    compare : (Self,Self) -> bool\n    \n    def compare(x:Self, y:Self) -> bool:\n        if True:\n            while False:\n                pass\n        return True\n    \n\n\nactor Test[T](v0:T):\n    def m(x):\n        pass\n\n\ndef f(z):\n    pass\n\nprotocol MyProto[A,B(Eq)] (Bepa[B]):\n    pass\n\nextension __builtin__.int (Eq):\n    pass\n\nprotocol MyIndexed[A,B]:                                 # just a protocol\n    __getit__ : (A) -> B\n\ng : [A] => ((A)->A, int, str) -> (int,str)               # explicit quantification\n\nh : [A] => ((A)->A, x:int, y:dict[int,str]) -> str       # mixing positional and keyword arguments\n\nff : (**A) -> bool\n"
  },
  {
    "path": "compiler/tests/test1.act",
    "content": "# Copyright (C) 2019-2021 Data Ductus AB\n#\n# Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:\n#\n# 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.\n#\n# 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.\n#\n# 3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission.\n#\n# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS \"AS IS\" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n#\n\ndef f0(x : ?int):\n    return x + 7 if x is not None else 0\n\ndef f1(x : ?(int)->int):\n    return x(7) if x is not None else 0\n\ndef f2(x : ?int):\n    return x is None\n\ndef f3(x : ?int):\n    return x == 7\n\ndef f4(x : ?int):\n    return x + 7 if x is not None else 0\n\ndef f5(x : ?int):\n    return x+1 if x is not None and x > 0 else 0\n\ndef f6(x : ?(?int)):\n    return (x + 7 if x is not None else 1) if x is not None else 0\n\ndef f7a(x : ?int):\n    return x == 7\n\n#def f9(x : str):\n#    return x == True       # Cannot solve: atom < T, T(Eq)\n\ndef f10(x : bool):\n    return 'A' if x else 'B'\n\ndef f11():\n    return 'A' 'B'\n\ndef f12(x : Exception):\n    return 1 if isinstance(x, NotImplementedError) else 2\n\ndef f13(x : atom):\n    return x if isinstance(x, int) else -1\n\ndef f14():\n    a = (1, False, \"hello\" + \"world\")\n\n    b0 = a.0\n    b1 = a.1\n    b2 = a.2\n\n    c0 = a.~0\n    c1 = a.~1\n    c2 = a.~2\n\n    x = (apa = 1, bepa = False, cepa = \"hello\" \"world\")\n\n    y0 = x.apa\n    y1 = x.bepa\n    y2 = x.cepa\n\n    z0 = x.~apa\n    z1 = x.~bepa\n    z2 = x.~cepa\n\n    (p0,p1,p2) = a\n    (apa=q0,bepa=q1,cepa=q2) = x\n\ndef f15(x):\n    return \"%d %%\" % x\n\ndef f16(x,y,z):\n    return \"%*f %s\" % (x,y,z)\n\ndef f17(x):\n    return \"%s %f\" % x\n"
  },
  {
    "path": "compiler/tests/test2.act",
    "content": "# Copyright (C) 2019-2021 Data Ductus AB\n#\n# Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:\n#\n# 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.\n#\n# 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.\n#\n# 3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission.\n#\n# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS \"AS IS\" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n#\n\ndef fff (a, b, c):\n  return len([a // c])\n\ndef abs(x : Number) -> Real:\n    return x.__abs__()\n\ndef all(it : Iterable[A]) -> bool:\n    for x in it:\n        if not x:\n            return False\n    return True\n\ndef any(it : Iterable[A]) -> bool:\n    for x in it:\n        if x:\n            return True\n    return False\n\ndef pow1 [A(Number)] (a: A, b: A) -> A:\n  return Number.__pow__(a,b)\n\npow2 : (int,int)->int\n\ndef pow2 (a, b):\n  return a**b\n\ndef rev1(seq : Sequence[A]) -> Iterator[A]:\n  return seq.__reversed__()\n\ndef rev2(seq):\n  return Sequence.__reversed__(seq)\n\ndef rev3(seq):\n  return seq.__reversed__()\n\ndef fake [A(Real)] () -> A:\n    raise ValueError(\"fake\")\n\ndef dflt():\n    x = fake()\n    y = fake()\n    return x/y > y\n\ndef genrec(n):\n    return genrec(n) + genrec(n-1)\n"
  },
  {
    "path": "compiler/tests/test3.act",
    "content": "# Copyright (C) 2019-2021 Data Ductus AB\n#\n# Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:\n#\n# 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.\n#\n# 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.\n#\n# 3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission.\n#\n# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS \"AS IS\" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n#\n\nactor Apa():\n    var v = 0\n    def m():\n        v = 0\n        b = Bepa()\n#        b.meth()\n        b.methods[0]()\n#        b.bepa()\n        return 23\n\nactor Bepa():\n    var w = 0\n#    bepa : action() -> None\n    def bepa():\n        w -= 1\n    methods : list[action()->None]\n    methods = []\n#    meth : action() -> None\n    meth = bepa\n    def cepa():\n        a = Apa()\n        x = await async a.m()\n"
  },
  {
    "path": "compiler/tests/test4.act",
    "content": "# Copyright (C) 2019-2021 Data Ductus AB\n#\n# Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:\n#\n# 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.\n#\n# 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.\n#\n# 3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission.\n#\n# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS \"AS IS\" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n#\n\ndef m1(a):\n    return a if a==a else a\n\nm2 : [A(Eq)] => (A) -> A\ndef m2(a):\n    return a\n\nx = m1(3)\ny = m2(4)\n\nactor Apa():\n    m3 : [A(Eq)] => (A) -> A\n    pure def m3(a):\n        return a\n    def m4(a):\n        return a\n\n\nclass Bepa():\n    m5 : [A(Eq)] => (A) -> A\n    def m5(self, a):\n        return a\n    def m6(self, a):\n        return a+1\n\n"
  },
  {
    "path": "compiler/tests/test5.act",
    "content": "# Copyright (C) 2019-2021 Data Ductus AB\n#\n# Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:\n#\n# 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.\n#\n# 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.\n#\n# 3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission.\n#\n# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS \"AS IS\" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n#\n\nprotocol Apa (Eq, Plus):\n    @staticmethod\n    apa : [C(Ord)] => (Self,Self,C) -> bool\n    @staticmethod\n    bepa : (Self,Self) -> bool\n    cepa : [C(Ord)] => (int,C) -> bool\n    def apa(a,b,c):\n        return a == b\n    def __add__(a,b):\n        return a\n\nextension bool (Apa):\n    def bepa(a,b):\n        return a == b\n    def __add__(a,b):\n        return b\n    def __eq__(a,b):\n        return False\n    def __ne__(a,b):\n        return not a==b\n    def cepa(self,i,c):\n        return False\n\nextension list[A(Eq)] (Apa):\n    def bepa(a,b):\n        return a == b\n    def __eq__(a,b):\n        if len(a) != len(b):\n            return False\n        for x,y in zip(a,b):\n            if x != y:\n                return False\n        return True\n    def __ne__(a,b):\n        return not a==b\n    def cepa(self,i,c):\n        return False\n\n\nprotocol What (Iterable[int], Real):\n    pass\n\nprotocol Who (Iterable[int], Ord):\n    pass\n\n\nextension int (What): pass\nextension int (Who): pass\n"
  },
  {
    "path": "compiler/tests/test6.act",
    "content": "def f1(x):\n    return x or \"default\"\n\ndef f2(x):\n    return x or 42\n\ndef f2b(x: int):\n    return x or 42\n\ndef f3(x: ?int):\n    return x or None\n\ndef f4(x: int, y: ?int):\n    return x or y\n\ndef f5(x, y):\n    return x or y\n\ndef f6(x, y):\n    return x and y/x\n\ndef f7(x):\n    return not x\n\ndef f8(x):\n    return x and True\n\ndef f9(x: str):\n    return x and True\n\ndef f10(x):\n    return x and 7 % x or 42\n\ndef g(x, y, z):\n    if x:\n        return 0\n    if not y:\n        return 1\n    if x and y:\n        return 2\n    if y or x:\n        return 3\n    if x or y and z:\n        return 4\n    return -1\n"
  },
  {
    "path": "compiler/tests/tuples.act",
    "content": "# Copyright (C) 2019-2021 Data Ductus AB\n#\n# Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:\n#\n# 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.\n#\n# 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.\n#\n# 3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission.\n#\n# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS \"AS IS\" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n#\n\nt1 = (3,6,'a')\nt2 = (4,*f(y))\n\n(a,x,*b) = (1,2,3,4,5)\n\ndef f():\n  s = 0\n  for i in (k*k for k in range(1,5)) : \n    s+=i\n  return 7,4+5,\n\n\nfor i in 3,4,*s:\n  pass"
  },
  {
    "path": "compiler/tools/ld-wrapper.sh",
    "content": "#!/usr/bin/env bash\nset -euo pipefail\n\nreal_linker=\"${ACTON_REAL_LD:-gcc}\"\nstate=\"static\"\narch=\"$(uname -m 2>/dev/null || true)\"\nallow_dynamic_glibc=false\ncase \"$arch\" in\n  aarch64|arm64|x86_64|amd64)\n    allow_dynamic_glibc=true\n    ;;\nesac\n\nargs=()\nargs+=(\"-Wl,-Bstatic\")\n\ngcc_lib_path() {\n  local lib=\"$1\"\n  local lib_path\n  lib_path=\"$(gcc -print-file-name=\"$lib\" 2>/dev/null || true)\"\n  if [[ -n \"$lib_path\" && \"$lib_path\" != \"$lib\" ]]; then\n    echo \"$lib_path\"\n    return 0\n  fi\n  return 1\n}\n\nadd_static_gcc_lib() {\n  local archive=\"$1\"\n  local fallback=\"$2\"\n  local archive_path\n  if archive_path=\"$(gcc_lib_path \"$archive\")\"; then\n    args+=(\"$archive_path\")\n  else\n    args+=(\"-l:$fallback\")\n  fi\n}\n\nnormalize_lib() {\n  local lib=\"$1\"\n  if [[ \"$lib\" == :lib* ]]; then\n    local name=\"${lib#:lib}\"\n    if [[ \"$name\" == *.so* ]]; then\n      echo \"${name%%.so*}\"\n      return\n    fi\n    if [[ \"$name\" == *.a ]]; then\n      echo \"${name%.a}\"\n      return\n    fi\n  fi\n  echo \"$lib\"\n}\n\nhandle_lib() {\n  local lib=\"$1\"\n  local lib_key\n  lib_key=\"$(normalize_lib \"$lib\")\"\n  if [[ \"$lib_key\" == \"z\" ]]; then\n    if [[ \"$state\" != \"static\" ]]; then\n      args+=(\"-Wl,-Bstatic\")\n      state=\"static\"\n    fi\n    add_static_gcc_lib libz.a libz.a\n    return\n  fi\n  if [[ \"$lib_key\" == \"gmp\" ]]; then\n    if [[ \"$state\" != \"static\" ]]; then\n      args+=(\"-Wl,-Bstatic\")\n      state=\"static\"\n    fi\n    add_static_gcc_lib libgmp.a libgmp.a\n    return\n  fi\n  if [[ \"$lib_key\" == \"stdc++\" ]]; then\n    if [[ \"$state\" != \"static\" ]]; then\n      args+=(\"-Wl,-Bstatic\")\n      state=\"static\"\n    fi\n    add_static_gcc_lib libstdc++.a libstdc++.a\n    add_static_gcc_lib libgcc_eh.a libgcc_eh.a\n    return\n  fi\n  if [[ \"$lib_key\" == \"tinfo\" ]]; then\n    if [[ \"$state\" != \"static\" ]]; then\n      args+=(\"-Wl,-Bstatic\")\n      state=\"static\"\n    fi\n    add_static_gcc_lib libtinfo.a libtinfo.a\n    return\n  fi\n  if [[ \"$allow_dynamic_glibc\" == true ]]; then\n    case \"$lib_key\" in\n      c|m|dl|pthread|rt|util)\n        if [[ \"$state\" != \"dynamic\" ]]; then\n          args+=(\"-Wl,-Bdynamic\")\n          state=\"dynamic\"\n        fi\n        args+=(\"-l${lib}\")\n        return\n        ;;\n    esac\n  fi\n  if [[ \"$lib_key\" == \"gcc_s\" ]]; then\n    if [[ \"$state\" != \"static\" ]]; then\n      args+=(\"-Wl,-Bstatic\")\n      state=\"static\"\n    fi\n    add_static_gcc_lib libgcc_eh.a libgcc_eh.a\n    return\n  fi\n  if [[ \"$state\" != \"static\" ]]; then\n    args+=(\"-Wl,-Bstatic\")\n    state=\"static\"\n  fi\n  args+=(\"-l${lib}\")\n}\n\nprocess_arg() {\n  local arg=\"$1\"\n  case \"$arg\" in\n    @*)\n      local rsp=\"${arg#@}\"\n      if [[ -f \"$rsp\" ]]; then\n        while IFS= read -r line; do\n          [[ -z \"$line\" ]] && continue\n          if [[ \"$line\" == \\\"*\\\" && \"$line\" == *\\\" ]]; then\n            line=\"${line:1:${#line}-2}\"\n            line=\"${line//\\\\\\\\/\\\\}\"\n            line=\"${line//\\\\\\\"/\\\"}\"\n          fi\n          process_arg \"$line\"\n        done < \"$rsp\"\n      else\n        args+=(\"$arg\")\n      fi\n      ;;\n    -Wl,*)\n      IFS=',' read -r -a wl_opts <<< \"${arg#-Wl,}\"\n      for opt in \"${wl_opts[@]}\"; do\n        case \"$opt\" in\n          -Bstatic|-Bdynamic)\n            ;;\n          -l*)\n            handle_lib \"${opt#-l}\"\n            ;;\n          -u\\ *)\n            args+=(\"-Wl,-u\" \"-Wl,${opt#-u }\")\n            ;;\n          *)\n            if [[ \"$opt\" == *\" \"* ]]; then\n              for part in $opt; do\n                args+=(\"-Wl,$part\")\n              done\n            else\n              args+=(\"-Wl,$opt\")\n            fi\n            ;;\n        esac\n      done\n      ;;\n    -l*)\n      handle_lib \"${arg#-l}\"\n      ;;\n    -Wl,-Bstatic|-Wl,-Bdynamic)\n      # Handled by this wrapper.\n      ;;\n    *)\n      args+=(\"$arg\")\n      ;;\n  esac\n}\n\nfor arg in \"$@\"; do\n  process_arg \"$arg\"\ndone\n\nif [[ \"$allow_dynamic_glibc\" == true && \"$state\" != \"dynamic\" ]]; then\n  args+=(\"-Wl,-Bdynamic\")\n  state=\"dynamic\"\nfi\n\nexec \"$real_linker\" \"${args[@]}\"\n"
  },
  {
    "path": "compiler/tools/zig-cc.sh",
    "content": "#!/usr/bin/env bash\nset -euo pipefail\n\nROOT=\"$(CDPATH= cd -- \"$(dirname -- \"$0\")/../..\" && pwd)\"\nZIG=\"${ROOT}/dist/zig/zig\"\n\nrun_zig_with_lock() {\n  if ! command -v flock >/dev/null 2>&1; then\n    echo \"flock is required for Linux Zig compiler wrapper serialization\" >&2\n    return 1\n  fi\n\n  local lock_root=\"${ZIG_GLOBAL_CACHE_DIR:-${TMPDIR:-/tmp}/acton-zig-global-cache}\"\n  mkdir -p \"$lock_root\"\n  flock \"$lock_root/acton-zig-cc.lock\" \"${ZIG}\" \"$@\"\n}\n\ngcc_lib_path() {\n  local lib=\"$1\"\n  local lib_path\n  lib_path=\"$(gcc -print-file-name=\"$lib\" 2>/dev/null || true)\"\n  if [[ -n \"$lib_path\" && \"$lib_path\" != \"$lib\" ]]; then\n    echo \"$lib_path\"\n    return 0\n  fi\n  return 1\n}\n\nadd_system_include_dirs() {\n  local multiarch\n  args+=(\"-idirafter\" \"/usr/include\")\n  multiarch=\"$(gcc -print-multiarch 2>/dev/null || true)\"\n  if [[ -n \"$multiarch\" && -d \"/usr/include/$multiarch\" ]]; then\n    args+=(\"-idirafter\" \"/usr/include/$multiarch\")\n  fi\n}\n\nadd_arch_feature_args() {\n  case \"${ZIG_ARCH}\" in\n    x86_64)\n      args+=(\"-Xclang\" \"-target-feature\" \"-Xclang\" \"+evex512\")\n      ;;\n  esac\n}\n\nrewrite_lib_arg() {\n  local arg=\"$1\"\n  local lib_path\n  case \"$arg\" in\n    -lgmp|-l:libgmp.a)\n      if lib_path=\"$(gcc_lib_path libgmp.a)\"; then\n        echo \"$lib_path\"\n      else\n        echo \"$arg\"\n      fi\n      ;;\n    -lz|-l:libz.a)\n      if lib_path=\"$(gcc_lib_path libz.a)\"; then\n        echo \"$lib_path\"\n      else\n        echo \"$arg\"\n      fi\n      ;;\n    -lstdc++|-l:libstdc++.a)\n      if lib_path=\"$(gcc_lib_path libstdc++.a)\"; then\n        echo \"$lib_path\"\n      else\n        echo \"$arg\"\n      fi\n      ;;\n    -ltinfo|-l:libtinfo.a)\n      if lib_path=\"$(gcc_lib_path libtinfo.a)\"; then\n        echo \"$lib_path\"\n      else\n        echo \"$arg\"\n      fi\n      ;;\n    *)\n      echo \"$arg\"\n      ;;\n  esac\n}\n\nprocess_arg() {\n  local arg=\"$1\"\n  case \"$arg\" in\n    @*)\n      local rsp=\"${arg#@}\"\n      if [[ -f \"$rsp\" ]]; then\n        local line\n        while IFS= read -r line || [[ -n \"$line\" ]]; do\n          [[ -z \"$line\" ]] && continue\n          if [[ \"$line\" == \\\"*\\\" && \"$line\" == *\\\" ]]; then\n            line=\"${line:1:${#line}-2}\"\n            line=\"${line//\\\\\\\\/\\\\}\"\n            line=\"${line//\\\\\\\"/\\\"}\"\n          fi\n          process_arg \"$line\"\n        done < \"$rsp\"\n      else\n        args+=(\"$(rewrite_lib_arg \"$arg\")\")\n      fi\n      ;;\n    *)\n      args+=(\"$(rewrite_lib_arg \"$arg\")\")\n      ;;\n  esac\n}\n\ncase \"$(uname -s)\" in\n  Linux)\n    ARCH=\"$(uname -m)\"\n    case \"${ARCH}\" in\n      x86_64) ZIG_ARCH=x86_64 ;;\n      aarch64|arm64) ZIG_ARCH=aarch64 ;;\n      *) echo \"Unsupported architecture for Linux: ${ARCH}\" >&2; exit 1 ;;\n    esac\n    GLIBC_VERSION=\"${ACTON_ZIG_GLIBC_VERSION:-2.31}\"\n    args=()\n    add_system_include_dirs\n    add_arch_feature_args\n    for arg in \"$@\"; do\n      process_arg \"$arg\"\n    done\n    run_zig_with_lock cc -target \"${ZIG_ARCH}-linux-gnu.${GLIBC_VERSION}\" \"${args[@]}\"\n    ;;\n  *)\n    exec \"${ZIG}\" cc \"$@\"\n    ;;\nesac\n"
  },
  {
    "path": "compiler/tools/zig-cxx.sh",
    "content": "#!/usr/bin/env bash\nset -euo pipefail\n\nROOT=\"$(CDPATH= cd -- \"$(dirname -- \"$0\")/../..\" && pwd)\"\nZIG=\"${ROOT}/dist/zig/zig\"\n\nrun_zig_with_lock() {\n  if ! command -v flock >/dev/null 2>&1; then\n    echo \"flock is required for Linux Zig compiler wrapper serialization\" >&2\n    return 1\n  fi\n\n  local lock_root=\"${ZIG_GLOBAL_CACHE_DIR:-${TMPDIR:-/tmp}/acton-zig-global-cache}\"\n  mkdir -p \"$lock_root\"\n  flock \"$lock_root/acton-zig-cc.lock\" \"${ZIG}\" \"$@\"\n}\n\ngcc_lib_path() {\n  local lib=\"$1\"\n  local lib_path\n  lib_path=\"$(gcc -print-file-name=\"$lib\" 2>/dev/null || true)\"\n  if [[ -n \"$lib_path\" && \"$lib_path\" != \"$lib\" ]]; then\n    echo \"$lib_path\"\n    return 0\n  fi\n  return 1\n}\n\nadd_system_include_dirs() {\n  local multiarch\n  args+=(\"-idirafter\" \"/usr/include\")\n  multiarch=\"$(gcc -print-multiarch 2>/dev/null || true)\"\n  if [[ -n \"$multiarch\" && -d \"/usr/include/$multiarch\" ]]; then\n    args+=(\"-idirafter\" \"/usr/include/$multiarch\")\n  fi\n}\n\nadd_arch_feature_args() {\n  case \"${ZIG_ARCH}\" in\n    x86_64)\n      args+=(\"-Xclang\" \"-target-feature\" \"-Xclang\" \"+evex512\")\n      ;;\n  esac\n}\n\nrewrite_lib_arg() {\n  local arg=\"$1\"\n  local lib_path\n  case \"$arg\" in\n    -lgmp|-l:libgmp.a)\n      if lib_path=\"$(gcc_lib_path libgmp.a)\"; then\n        echo \"$lib_path\"\n      else\n        echo \"$arg\"\n      fi\n      ;;\n    -lz|-l:libz.a)\n      if lib_path=\"$(gcc_lib_path libz.a)\"; then\n        echo \"$lib_path\"\n      else\n        echo \"$arg\"\n      fi\n      ;;\n    -lstdc++|-l:libstdc++.a)\n      if lib_path=\"$(gcc_lib_path libstdc++.a)\"; then\n        echo \"$lib_path\"\n      else\n        echo \"$arg\"\n      fi\n      ;;\n    -ltinfo|-l:libtinfo.a)\n      if lib_path=\"$(gcc_lib_path libtinfo.a)\"; then\n        echo \"$lib_path\"\n      else\n        echo \"$arg\"\n      fi\n      ;;\n    *)\n      echo \"$arg\"\n      ;;\n  esac\n}\n\nprocess_arg() {\n  local arg=\"$1\"\n  case \"$arg\" in\n    @*)\n      local rsp=\"${arg#@}\"\n      if [[ -f \"$rsp\" ]]; then\n        local line\n        while IFS= read -r line || [[ -n \"$line\" ]]; do\n          [[ -z \"$line\" ]] && continue\n          if [[ \"$line\" == \\\"*\\\" && \"$line\" == *\\\" ]]; then\n            line=\"${line:1:${#line}-2}\"\n            line=\"${line//\\\\\\\\/\\\\}\"\n            line=\"${line//\\\\\\\"/\\\"}\"\n          fi\n          process_arg \"$line\"\n        done < \"$rsp\"\n      else\n        args+=(\"$(rewrite_lib_arg \"$arg\")\")\n      fi\n      ;;\n    *)\n      args+=(\"$(rewrite_lib_arg \"$arg\")\")\n      ;;\n  esac\n}\n\ncase \"$(uname -s)\" in\n  Linux)\n    ARCH=\"$(uname -m)\"\n    case \"${ARCH}\" in\n      x86_64) ZIG_ARCH=x86_64 ;;\n      aarch64|arm64) ZIG_ARCH=aarch64 ;;\n      *) echo \"Unsupported architecture for Linux: ${ARCH}\" >&2; exit 1 ;;\n    esac\n    GLIBC_VERSION=\"${ACTON_ZIG_GLIBC_VERSION:-2.31}\"\n    args=()\n    add_system_include_dirs\n    add_arch_feature_args\n    for arg in \"$@\"; do\n      process_arg \"$arg\"\n    done\n    run_zig_with_lock c++ -target \"${ZIG_ARCH}-linux-gnu.${GLIBC_VERSION}\" \"${args[@]}\"\n    ;;\n  *)\n    exec \"${ZIG}\" c++ \"$@\"\n    ;;\nesac\n"
  },
  {
    "path": "completion/acton.bash-completion",
    "content": "source <(acton --bash-completion-script `which acton`)\n"
  },
  {
    "path": "debian/acton.bash-completion",
    "content": "source <(acton --bash-completion-script `which acton`)\n"
  },
  {
    "path": "debian/changelog.in",
    "content": "acton (VERSION) DEB_DIST; urgency=medium\n\n  * See CHANGELOG.md\n\n -- Kristian Larsson <kristian@spritelink.net>  Mon, 13 Sep 2021 22:06:08 +0200\n"
  },
  {
    "path": "debian/control",
    "content": "Source: acton\nSection: devel\nPriority: optional\nMaintainer: Kristian Larsson <kristian@spritelink.net>\nBuild-Depends:\n bash-completion,\n debhelper-compat (= 13),\n g++,\n haskell-stack,\n libgmp-dev,\n libncurses-dev,\n make,\n zlib1g-dev\nStandards-Version: 4.6.0\nHomepage: http://www.acton-lang.org\nRules-Requires-Root: no\n\nPackage: acton\nArchitecture: any\nDepends:\n libc6 (>= 2.27),\n ${shlibs:Depends},\n ${misc:Depends}\nDescription: Acton Programming Language\n An awesome programming language.\n"
  },
  {
    "path": "debian/copyright",
    "content": "Package created by Kristian Larsson (kll)\n on Sun, 12 Sep 2021 08:23:00 +0200.\n\nUpstream Author:\n\n    Johan Nordlander (nordlander)\n    Andrei Agapi (aagapi)\n    Kristian Larsson (kll)\n\nFiles: *\nCopyright:\n    2019-2021 Data Ductus AB\n    2019-2021 Deutsche Telekom AG\nLicense: BSD-3-clause\n\nLicense: BSD-3-clause\n  Copyright (C) 2019-2021 Data Ductus AB\n  Copyright (C) 2019-2021 Deutsche Telekom AG\n  \n  Redistribution and use in source and binary forms, with or without\n  modification, are permitted provided that the following conditions are met:\n  \n  1. Redistributions of source code must retain the above copyright notice, this\n  list of conditions and the following disclaimer.\n  \n  2. Redistributions in binary form must reproduce the above copyright notice,\n  this list of conditions and the following disclaimer in the documentation\n  and/or other materials provided with the distribution.\n  \n  3. Neither the name of the copyright holder nor the names of its contributors\n  may be used to endorse or promote products derived from this software without\n  specific prior written permission.\n  \n  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS \"AS IS\" AND\n  ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED\n  WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE\n  DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE\n  FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL\n  DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR\n  SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER\n  CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,\n  OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE\n  OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n"
  },
  {
    "path": "debian/rules",
    "content": "#!/usr/bin/make -f\n# See debhelper(7) (uncomment to enable)\n# output every command that modifies files on the build system.\nexport DH_VERBOSE = 1\n\n# see FEATURE AREAS in dpkg-buildflags(1)\n#export DEB_BUILD_MAINT_OPTIONS = hardening=+all\n\n# see ENVIRONMENT in dpkg-buildflags(1)\n# package maintainers to append CFLAGS\n#export DEB_CFLAGS_MAINT_APPEND  = -Wall -pedantic\n# package maintainers to append LDFLAGS\n#export DEB_LDFLAGS_MAINT_APPEND = -Wl,--as-needed\n\n\n%:\n\tdh $@ --parallel --with bash-completion\n\noverride_dh_auto_test:\n\t@echo \"Skipping tests\"\n\n# Do not strip\noverride_dh_strip:\n\t@echo \"Skipping strip\"\n\n# dwz in our CI package builder does not support DWARF v5 emitted by Zig 0.15.\noverride_dh_dwz:\n\t@echo \"Skipping dwz\"\n\n# Force a legacy-compatible .deb compression format.\n# Newer dpkg defaults may emit control.tar.zst, which Debian 11 cannot unpack.\noverride_dh_builddeb:\n\tdh_builddeb -- -Zxz --uniform-compression\n\n# dh_make generated override targets\n# This is example for Cmake (See https://bugs.debian.org/641051 )\n#override_dh_auto_configure:\n#\tdh_auto_configure -- \\\n#\t-DCMAKE_LIBRARY_PATH=$(DEB_HOST_MULTIARCH)\n"
  },
  {
    "path": "debian/watch",
    "content": "version=4\n\n# GitHub hosted projects\nopts=\"filenamemangle=s%(?:.*?)?v?(\\d[\\d.]*)\\.tar\\.gz%<project>-$1.tar.gz%\" \\\n   https://github.com/actonlang/acton/tags \\\n   (?:.*?/)?v?(\\d[\\d.]*)\\.tar\\.gz debian uupdate\n"
  },
  {
    "path": "docs/acton-dev-guide/.gitignore",
    "content": "book\n"
  },
  {
    "path": "docs/acton-dev-guide/README.md",
    "content": "# Acton Developer Guide\n\n## Writers Guide\n\n```sh\nmdbook serve\n```\n"
  },
  {
    "path": "docs/acton-dev-guide/book.toml",
    "content": "[book]\ntitle = \"Acton Developer Guide\"\nauthors = []\nlanguage = \"en\"\nmultilingual = false\npreferred-dark-theme = \"ayu\"\nsrc = \"src\"\nsite-url = \"/learn/acton-dev-guide/\"\ngit-repository-url = \"https://github.com/actonlang/acton\"\ngit-repository-icon = \"fa-github\"\nedit-url-template = \"https://github.com/actonlang/acton/edit/master/docs/acton-dev-guide/{path}\"\n\n[preprocessor.tabs]\n\n[preprocessor.svgbob]\ntext_width = 8.0\ntext_height = 16.0\nclass = \"bob\"\nfont_family = \"arial\"\nfont_size = 14\nstroke_width = 2.0\n# there's using css-variables from theme:\nstroke_color = \"var(--fg)\" # see default theme / variables.css\nbackground_color = \"transparent\" # also useful `var(--bg)`\n\n[preprocessor.admonish]\ncommand = \"mdbook-admonish\"\nassets_version = \"3.0.2\" # do not edit: managed by `mdbook-admonish install`\n\n[output.html]\nadditional-css = [\"svgbob.css\", \"theme/tabs.css\", \"./mdbook-admonish.css\", \"theme/sbscode.css\", \"theme/skill-slider.css\", \"theme/content-width.css\"]\nadditional-js = [\"theme/tabs.js\", \"theme/sbscode_copy.js\", \"theme/skill-slider.js\"]\n\n[output.html.fold]\nenable = true\n"
  },
  {
    "path": "docs/acton-dev-guide/mdbook-admonish.css",
    "content": "@charset \"UTF-8\";\n:is(.admonition) {\n  display: flow-root;\n  margin: 1.5625em 0;\n  padding: 0 1.2rem;\n  color: var(--fg);\n  page-break-inside: avoid;\n  background-color: var(--bg);\n  border: 0 solid black;\n  border-inline-start-width: 0.4rem;\n  border-radius: 0.2rem;\n  box-shadow: 0 0.2rem 1rem rgba(0, 0, 0, 0.05), 0 0 0.1rem rgba(0, 0, 0, 0.1);\n}\n@media print {\n  :is(.admonition) {\n    box-shadow: none;\n  }\n}\n:is(.admonition) > * {\n  box-sizing: border-box;\n}\n:is(.admonition) :is(.admonition) {\n  margin-top: 1em;\n  margin-bottom: 1em;\n}\n:is(.admonition) > .tabbed-set:only-child {\n  margin-top: 0;\n}\nhtml :is(.admonition) > :last-child {\n  margin-bottom: 1.2rem;\n}\n\na.admonition-anchor-link {\n  display: none;\n  position: absolute;\n  left: -1.2rem;\n  padding-right: 1rem;\n}\na.admonition-anchor-link:link, a.admonition-anchor-link:visited {\n  color: var(--fg);\n}\na.admonition-anchor-link:link:hover, a.admonition-anchor-link:visited:hover {\n  text-decoration: none;\n}\na.admonition-anchor-link::before {\n  content: \"§\";\n}\n\n:is(.admonition-title, summary.admonition-title) {\n  position: relative;\n  min-height: 4rem;\n  margin-block: 0;\n  margin-inline: -1.6rem -1.2rem;\n  padding-block: 0.8rem;\n  padding-inline: 4.4rem 1.2rem;\n  font-weight: 700;\n  background-color: rgba(68, 138, 255, 0.1);\n  print-color-adjust: exact;\n  -webkit-print-color-adjust: exact;\n  display: flex;\n}\n:is(.admonition-title, summary.admonition-title) p {\n  margin: 0;\n}\nhtml :is(.admonition-title, summary.admonition-title):last-child {\n  margin-bottom: 0;\n}\n:is(.admonition-title, summary.admonition-title)::before {\n  position: absolute;\n  top: 0.625em;\n  inset-inline-start: 1.6rem;\n  width: 2rem;\n  height: 2rem;\n  background-color: #448aff;\n  print-color-adjust: exact;\n  -webkit-print-color-adjust: exact;\n  mask-image: url('data:image/svg+xml;charset=utf-8,<svg xmlns=\"http://www.w3.org/2000/svg\" viewBox=\"0 0 24 24\"></svg>');\n  -webkit-mask-image: url('data:image/svg+xml;charset=utf-8,<svg xmlns=\"http://www.w3.org/2000/svg\" viewBox=\"0 0 24 24\"></svg>');\n  mask-repeat: no-repeat;\n  -webkit-mask-repeat: no-repeat;\n  mask-size: contain;\n  -webkit-mask-size: contain;\n  content: \"\";\n}\n:is(.admonition-title, summary.admonition-title):hover a.admonition-anchor-link {\n  display: initial;\n}\n\ndetails.admonition > summary.admonition-title::after {\n  position: absolute;\n  top: 0.625em;\n  inset-inline-end: 1.6rem;\n  height: 2rem;\n  width: 2rem;\n  background-color: currentcolor;\n  mask-image: var(--md-details-icon);\n  -webkit-mask-image: var(--md-details-icon);\n  mask-repeat: no-repeat;\n  -webkit-mask-repeat: no-repeat;\n  mask-size: contain;\n  -webkit-mask-size: contain;\n  content: \"\";\n  transform: rotate(0deg);\n  transition: transform 0.25s;\n}\ndetails[open].admonition > summary.admonition-title::after {\n  transform: rotate(90deg);\n}\n\n:root {\n  --md-details-icon: url(\"data:image/svg+xml;charset=utf-8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'><path d='M8.59 16.58 13.17 12 8.59 7.41 10 6l6 6-6 6-1.41-1.42Z'/></svg>\");\n}\n\n:root {\n  --md-admonition-icon--admonish-note: url(\"data:image/svg+xml;charset=utf-8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'><path d='M20.71 7.04c.39-.39.39-1.04 0-1.41l-2.34-2.34c-.37-.39-1.02-.39-1.41 0l-1.84 1.83 3.75 3.75M3 17.25V21h3.75L17.81 9.93l-3.75-3.75L3 17.25z'/></svg>\");\n  --md-admonition-icon--admonish-abstract: url(\"data:image/svg+xml;charset=utf-8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'><path d='M17 9H7V7h10m0 6H7v-2h10m-3 6H7v-2h7M12 3a1 1 0 0 1 1 1 1 1 0 0 1-1 1 1 1 0 0 1-1-1 1 1 0 0 1 1-1m7 0h-4.18C14.4 1.84 13.3 1 12 1c-1.3 0-2.4.84-2.82 2H5a2 2 0 0 0-2 2v14a2 2 0 0 0 2 2h14a2 2 0 0 0 2-2V5a2 2 0 0 0-2-2z'/></svg>\");\n  --md-admonition-icon--admonish-info: url(\"data:image/svg+xml;charset=utf-8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'><path d='M13 9h-2V7h2m0 10h-2v-6h2m-1-9A10 10 0 0 0 2 12a10 10 0 0 0 10 10 10 10 0 0 0 10-10A10 10 0 0 0 12 2z'/></svg>\");\n  --md-admonition-icon--admonish-tip: url(\"data:image/svg+xml;charset=utf-8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'><path d='M17.66 11.2c-.23-.3-.51-.56-.77-.82-.67-.6-1.43-1.03-2.07-1.66C13.33 7.26 13 4.85 13.95 3c-.95.23-1.78.75-2.49 1.32-2.59 2.08-3.61 5.75-2.39 8.9.04.1.08.2.08.33 0 .22-.15.42-.35.5-.23.1-.47.04-.66-.12a.58.58 0 0 1-.14-.17c-1.13-1.43-1.31-3.48-.55-5.12C5.78 10 4.87 12.3 5 14.47c.06.5.12 1 .29 1.5.14.6.41 1.2.71 1.73 1.08 1.73 2.95 2.97 4.96 3.22 2.14.27 4.43-.12 6.07-1.6 1.83-1.66 2.47-4.32 1.53-6.6l-.13-.26c-.21-.46-.77-1.26-.77-1.26m-3.16 6.3c-.28.24-.74.5-1.1.6-1.12.4-2.24-.16-2.9-.82 1.19-.28 1.9-1.16 2.11-2.05.17-.8-.15-1.46-.28-2.23-.12-.74-.1-1.37.17-2.06.19.38.39.76.63 1.06.77 1 1.98 1.44 2.24 2.8.04.14.06.28.06.43.03.82-.33 1.72-.93 2.27z'/></svg>\");\n  --md-admonition-icon--admonish-success: url(\"data:image/svg+xml;charset=utf-8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'><path d='m9 20.42-6.21-6.21 2.83-2.83L9 14.77l9.88-9.89 2.83 2.83L9 20.42z'/></svg>\");\n  --md-admonition-icon--admonish-question: url(\"data:image/svg+xml;charset=utf-8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'><path d='m15.07 11.25-.9.92C13.45 12.89 13 13.5 13 15h-2v-.5c0-1.11.45-2.11 1.17-2.83l1.24-1.26c.37-.36.59-.86.59-1.41a2 2 0 0 0-2-2 2 2 0 0 0-2 2H8a4 4 0 0 1 4-4 4 4 0 0 1 4 4 3.2 3.2 0 0 1-.93 2.25M13 19h-2v-2h2M12 2A10 10 0 0 0 2 12a10 10 0 0 0 10 10 10 10 0 0 0 10-10c0-5.53-4.5-10-10-10z'/></svg>\");\n  --md-admonition-icon--admonish-warning: url(\"data:image/svg+xml;charset=utf-8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'><path d='M13 14h-2V9h2m0 9h-2v-2h2M1 21h22L12 2 1 21z'/></svg>\");\n  --md-admonition-icon--admonish-failure: url(\"data:image/svg+xml;charset=utf-8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'><path d='M20 6.91 17.09 4 12 9.09 6.91 4 4 6.91 9.09 12 4 17.09 6.91 20 12 14.91 17.09 20 20 17.09 14.91 12 20 6.91z'/></svg>\");\n  --md-admonition-icon--admonish-danger: url(\"data:image/svg+xml;charset=utf-8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'><path d='M11 15H6l7-14v8h5l-7 14v-8z'/></svg>\");\n  --md-admonition-icon--admonish-bug: url(\"data:image/svg+xml;charset=utf-8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'><path d='M14 12h-4v-2h4m0 6h-4v-2h4m6-6h-2.81a5.985 5.985 0 0 0-1.82-1.96L17 4.41 15.59 3l-2.17 2.17a6.002 6.002 0 0 0-2.83 0L8.41 3 7 4.41l1.62 1.63C7.88 6.55 7.26 7.22 6.81 8H4v2h2.09c-.05.33-.09.66-.09 1v1H4v2h2v1c0 .34.04.67.09 1H4v2h2.81c1.04 1.79 2.97 3 5.19 3s4.15-1.21 5.19-3H20v-2h-2.09c.05-.33.09-.66.09-1v-1h2v-2h-2v-1c0-.34-.04-.67-.09-1H20V8z'/></svg>\");\n  --md-admonition-icon--admonish-example: url(\"data:image/svg+xml;charset=utf-8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'><path d='M7 13v-2h14v2H7m0 6v-2h14v2H7M7 7V5h14v2H7M3 8V5H2V4h2v4H3m-1 9v-1h3v4H2v-1h2v-.5H3v-1h1V17H2m2.25-7a.75.75 0 0 1 .75.75c0 .2-.08.39-.21.52L3.12 13H5v1H2v-.92L4 11H2v-1h2.25z'/></svg>\");\n  --md-admonition-icon--admonish-quote: url(\"data:image/svg+xml;charset=utf-8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'><path d='M14 17h3l2-4V7h-6v6h3M6 17h3l2-4V7H5v6h3l-2 4z'/></svg>\");\n}\n\n:is(.admonition):is(.admonish-note) {\n  border-color: #448aff;\n}\n\n:is(.admonish-note) > :is(.admonition-title, summary.admonition-title) {\n  background-color: rgba(68, 138, 255, 0.1);\n}\n:is(.admonish-note) > :is(.admonition-title, summary.admonition-title)::before {\n  background-color: #448aff;\n  mask-image: var(--md-admonition-icon--admonish-note);\n  -webkit-mask-image: var(--md-admonition-icon--admonish-note);\n  mask-repeat: no-repeat;\n  -webkit-mask-repeat: no-repeat;\n  mask-size: contain;\n  -webkit-mask-repeat: no-repeat;\n}\n\n:is(.admonition):is(.admonish-abstract, .admonish-summary, .admonish-tldr) {\n  border-color: #00b0ff;\n}\n\n:is(.admonish-abstract, .admonish-summary, .admonish-tldr) > :is(.admonition-title, summary.admonition-title) {\n  background-color: rgba(0, 176, 255, 0.1);\n}\n:is(.admonish-abstract, .admonish-summary, .admonish-tldr) > :is(.admonition-title, summary.admonition-title)::before {\n  background-color: #00b0ff;\n  mask-image: var(--md-admonition-icon--admonish-abstract);\n  -webkit-mask-image: var(--md-admonition-icon--admonish-abstract);\n  mask-repeat: no-repeat;\n  -webkit-mask-repeat: no-repeat;\n  mask-size: contain;\n  -webkit-mask-repeat: no-repeat;\n}\n\n:is(.admonition):is(.admonish-info, .admonish-todo) {\n  border-color: #00b8d4;\n}\n\n:is(.admonish-info, .admonish-todo) > :is(.admonition-title, summary.admonition-title) {\n  background-color: rgba(0, 184, 212, 0.1);\n}\n:is(.admonish-info, .admonish-todo) > :is(.admonition-title, summary.admonition-title)::before {\n  background-color: #00b8d4;\n  mask-image: var(--md-admonition-icon--admonish-info);\n  -webkit-mask-image: var(--md-admonition-icon--admonish-info);\n  mask-repeat: no-repeat;\n  -webkit-mask-repeat: no-repeat;\n  mask-size: contain;\n  -webkit-mask-repeat: no-repeat;\n}\n\n:is(.admonition):is(.admonish-tip, .admonish-hint, .admonish-important) {\n  border-color: #00bfa5;\n}\n\n:is(.admonish-tip, .admonish-hint, .admonish-important) > :is(.admonition-title, summary.admonition-title) {\n  background-color: rgba(0, 191, 165, 0.1);\n}\n:is(.admonish-tip, .admonish-hint, .admonish-important) > :is(.admonition-title, summary.admonition-title)::before {\n  background-color: #00bfa5;\n  mask-image: var(--md-admonition-icon--admonish-tip);\n  -webkit-mask-image: var(--md-admonition-icon--admonish-tip);\n  mask-repeat: no-repeat;\n  -webkit-mask-repeat: no-repeat;\n  mask-size: contain;\n  -webkit-mask-repeat: no-repeat;\n}\n\n:is(.admonition):is(.admonish-success, .admonish-check, .admonish-done) {\n  border-color: #00c853;\n}\n\n:is(.admonish-success, .admonish-check, .admonish-done) > :is(.admonition-title, summary.admonition-title) {\n  background-color: rgba(0, 200, 83, 0.1);\n}\n:is(.admonish-success, .admonish-check, .admonish-done) > :is(.admonition-title, summary.admonition-title)::before {\n  background-color: #00c853;\n  mask-image: var(--md-admonition-icon--admonish-success);\n  -webkit-mask-image: var(--md-admonition-icon--admonish-success);\n  mask-repeat: no-repeat;\n  -webkit-mask-repeat: no-repeat;\n  mask-size: contain;\n  -webkit-mask-repeat: no-repeat;\n}\n\n:is(.admonition):is(.admonish-question, .admonish-help, .admonish-faq) {\n  border-color: #64dd17;\n}\n\n:is(.admonish-question, .admonish-help, .admonish-faq) > :is(.admonition-title, summary.admonition-title) {\n  background-color: rgba(100, 221, 23, 0.1);\n}\n:is(.admonish-question, .admonish-help, .admonish-faq) > :is(.admonition-title, summary.admonition-title)::before {\n  background-color: #64dd17;\n  mask-image: var(--md-admonition-icon--admonish-question);\n  -webkit-mask-image: var(--md-admonition-icon--admonish-question);\n  mask-repeat: no-repeat;\n  -webkit-mask-repeat: no-repeat;\n  mask-size: contain;\n  -webkit-mask-repeat: no-repeat;\n}\n\n:is(.admonition):is(.admonish-warning, .admonish-caution, .admonish-attention) {\n  border-color: #ff9100;\n}\n\n:is(.admonish-warning, .admonish-caution, .admonish-attention) > :is(.admonition-title, summary.admonition-title) {\n  background-color: rgba(255, 145, 0, 0.1);\n}\n:is(.admonish-warning, .admonish-caution, .admonish-attention) > :is(.admonition-title, summary.admonition-title)::before {\n  background-color: #ff9100;\n  mask-image: var(--md-admonition-icon--admonish-warning);\n  -webkit-mask-image: var(--md-admonition-icon--admonish-warning);\n  mask-repeat: no-repeat;\n  -webkit-mask-repeat: no-repeat;\n  mask-size: contain;\n  -webkit-mask-repeat: no-repeat;\n}\n\n:is(.admonition):is(.admonish-failure, .admonish-fail, .admonish-missing) {\n  border-color: #ff5252;\n}\n\n:is(.admonish-failure, .admonish-fail, .admonish-missing) > :is(.admonition-title, summary.admonition-title) {\n  background-color: rgba(255, 82, 82, 0.1);\n}\n:is(.admonish-failure, .admonish-fail, .admonish-missing) > :is(.admonition-title, summary.admonition-title)::before {\n  background-color: #ff5252;\n  mask-image: var(--md-admonition-icon--admonish-failure);\n  -webkit-mask-image: var(--md-admonition-icon--admonish-failure);\n  mask-repeat: no-repeat;\n  -webkit-mask-repeat: no-repeat;\n  mask-size: contain;\n  -webkit-mask-repeat: no-repeat;\n}\n\n:is(.admonition):is(.admonish-danger, .admonish-error) {\n  border-color: #ff1744;\n}\n\n:is(.admonish-danger, .admonish-error) > :is(.admonition-title, summary.admonition-title) {\n  background-color: rgba(255, 23, 68, 0.1);\n}\n:is(.admonish-danger, .admonish-error) > :is(.admonition-title, summary.admonition-title)::before {\n  background-color: #ff1744;\n  mask-image: var(--md-admonition-icon--admonish-danger);\n  -webkit-mask-image: var(--md-admonition-icon--admonish-danger);\n  mask-repeat: no-repeat;\n  -webkit-mask-repeat: no-repeat;\n  mask-size: contain;\n  -webkit-mask-repeat: no-repeat;\n}\n\n:is(.admonition):is(.admonish-bug) {\n  border-color: #f50057;\n}\n\n:is(.admonish-bug) > :is(.admonition-title, summary.admonition-title) {\n  background-color: rgba(245, 0, 87, 0.1);\n}\n:is(.admonish-bug) > :is(.admonition-title, summary.admonition-title)::before {\n  background-color: #f50057;\n  mask-image: var(--md-admonition-icon--admonish-bug);\n  -webkit-mask-image: var(--md-admonition-icon--admonish-bug);\n  mask-repeat: no-repeat;\n  -webkit-mask-repeat: no-repeat;\n  mask-size: contain;\n  -webkit-mask-repeat: no-repeat;\n}\n\n:is(.admonition):is(.admonish-example) {\n  border-color: #7c4dff;\n}\n\n:is(.admonish-example) > :is(.admonition-title, summary.admonition-title) {\n  background-color: rgba(124, 77, 255, 0.1);\n}\n:is(.admonish-example) > :is(.admonition-title, summary.admonition-title)::before {\n  background-color: #7c4dff;\n  mask-image: var(--md-admonition-icon--admonish-example);\n  -webkit-mask-image: var(--md-admonition-icon--admonish-example);\n  mask-repeat: no-repeat;\n  -webkit-mask-repeat: no-repeat;\n  mask-size: contain;\n  -webkit-mask-repeat: no-repeat;\n}\n\n:is(.admonition):is(.admonish-quote, .admonish-cite) {\n  border-color: #9e9e9e;\n}\n\n:is(.admonish-quote, .admonish-cite) > :is(.admonition-title, summary.admonition-title) {\n  background-color: rgba(158, 158, 158, 0.1);\n}\n:is(.admonish-quote, .admonish-cite) > :is(.admonition-title, summary.admonition-title)::before {\n  background-color: #9e9e9e;\n  mask-image: var(--md-admonition-icon--admonish-quote);\n  -webkit-mask-image: var(--md-admonition-icon--admonish-quote);\n  mask-repeat: no-repeat;\n  -webkit-mask-repeat: no-repeat;\n  mask-size: contain;\n  -webkit-mask-repeat: no-repeat;\n}\n\n.navy :is(.admonition) {\n  background-color: var(--sidebar-bg);\n}\n\n.ayu :is(.admonition),\n.coal :is(.admonition) {\n  background-color: var(--theme-hover);\n}\n\n.rust :is(.admonition) {\n  background-color: var(--sidebar-bg);\n  color: var(--sidebar-fg);\n}\n.rust .admonition-anchor-link:link, .rust .admonition-anchor-link:visited {\n  color: var(--sidebar-fg);\n}\n"
  },
  {
    "path": "docs/acton-dev-guide/src/SUMMARY.md",
    "content": "# Summary\n\n- [Overview](index.md)\n- [Getting started](getting_started.md)\n  - [Repository layout](getting_started/repo_layout.md)\n  - [Build and run](getting_started/build.md)\n  - [Tests](getting_started/tests.md)\n  - [Debugging](getting_started/debugging.md)\n- [Compiler](compiler/index.md)\n  - [Incremental compilation](compiler/incremental_compilation.md)\n  - [Imports and environments](compiler/imports_and_envs.md)\n  - [Project dependencies](compiler/project_dependencies.md)\n  - [Test result cache](compiler/test_cache.md)\n  - [Passes](compiler/passes/index.md)\n    - [Parse](compiler/passes/parse.md)\n    - [Kinds check](compiler/passes/kinds.md)\n    - [Type check](compiler/passes/type_check.md)\n    - [Normalize](compiler/passes/normalize.md)\n    - [Deactorize](compiler/passes/deactorize.md)\n    - [CPS](compiler/passes/cps.md)\n    - [Lambda lift](compiler/passes/lambda_lift.md)\n    - [Boxing](compiler/passes/boxing.md)\n    - [Codegen](compiler/passes/codegen.md)\n- [Builtins](builtins/index.md)\n  - [Builtin types](builtins/types.md)\n  - [Builtin functions](builtins/functions.md)\n  - [FFI hooks](builtins/ffi.md)\n- [Runtime](runtime/index.md)\n  - [Scheduler](runtime/scheduler.md)\n  - [Actors](runtime/actors.md)\n  - [Memory and GC](runtime/memory.md)\n- [Tooling](tooling/index.md)\n  - [Testing harness](tooling/testing.md)\n- [Design notes](design/index.md)\n  - [Capabilities](design/capabilities.md)\n  - [Concurrency model](design/concurrency.md)\n"
  },
  {
    "path": "docs/acton-dev-guide/src/builtins/ffi.md",
    "content": "# FFI hooks\n\nExplain the interfaces between builtins and external C/Zig code.\nInclude the conventions for naming, memory ownership, and error handling.\n"
  },
  {
    "path": "docs/acton-dev-guide/src/builtins/functions.md",
    "content": "# Builtin functions\n\nDescribe how builtin functions are declared and connected to runtime code.\nCall out any special casing in the compiler or optimizer.\n"
  },
  {
    "path": "docs/acton-dev-guide/src/builtins/index.md",
    "content": "# Builtins\n\nThis section explains how builtins are modeled, where they live in the repository,\nand how they map to runtime implementations.\n"
  },
  {
    "path": "docs/acton-dev-guide/src/builtins/types.md",
    "content": "# Builtin types\n\nDocument how core types are defined, their runtime layout, and any compiler hooks.\nInclude guidance for adding or modifying a builtin type.\n"
  },
  {
    "path": "docs/acton-dev-guide/src/compiler/imports_and_envs.md",
    "content": "# Imports and Environments\n\nThis note explains how imports move through the compiler today. The important\ndistinction is that there are two related but different mechanisms:\n\n- graph discovery in `Acton.Compile`, which decides module ordering and cache\n  reuse\n- environment materialization in `Acton.Env`, which makes imported modules\n  available to kinds/type checking\n\nIf those two are conflated, it becomes hard to reason about missing imports,\nstale `.ty` reuse, or why a module can be present in the scheduler but still\nneed more imports loaded into the active environment.\n\n## Environment layers\n\nThere are three environment layers worth keeping separate when discussing the\ncompiler.\n\n### Base environment\n\n`Acton.Env.initEnv` constructs the base `Env0`. It always contains `prim`, and\nin normal compilation it also loads `__builtin__` from `__builtin__.ty`.\n\nThis base environment is not tied to any one module. It is the starting point\nfor later compilation work.\n\n### Shared module cache\n\nDuring a compile run, the scheduler keeps an accumulated environment snapshot of\nfinished modules. In `Acton.Compile.compileTasks`, each completed module extends\nthat snapshot with:\n\n```haskell\nActon.Env.addMod (tkMod mnDone) (frIfaceTE fr) (frDoc fr) envAcc\n```\n\nThis shared cache stores loaded module interfaces in `modules`. It does not\nstore the current module's local names, and it should not be thought of as \"the\ncurrent type-checker env\". It is a shared cache of interfaces that later tasks\nstart from.\n\n### Current-module import overlay\n\nWhen the compiler is about to kinds/type-check a module, it takes the shared\nsnapshot and overlays the module's imports onto it with `Acton.Env.mkEnv`.\n\n`mkEnv` does not add the current module's own declarations. It only processes\nthe module's `import` statements. Later, the type checker sets `thismod` and\ndefines the module's own top-level names in a more specialized environment used\nwithin the pass.\n\nSo the rough model is:\n\n1. start from the shared module cache\n2. load the imported modules needed for this module\n3. type-check the module and derive its interface\n4. add that interface back into the shared module cache\n\n## Scheduler discovery versus import loading\n\nThe scheduler in `Acton.Compile` does not eagerly materialize every imported\nmodule into the active environment.\n\nInstead it does header-first discovery:\n\n- `readModuleTask` reads the `.ty` header when possible and produces a cheap\n  `TyTask`\n- otherwise it parses the source and produces an `ActonTask`\n- `buildGlobalTasks` uses the task's direct imports to build provider edges\n\nThose provider edges only cover imports that can be resolved to modules inside\nthe discovered project graph. This is deliberate: they are scheduler edges, not\nthe full transitive import closure of the final type-checker environment.\n\nThis matters for standard library modules and any other imports that are not\nrepresented as in-graph provider tasks. Such modules still have to be made\navailable later through `Acton.Env`.\n\n## When `.ty` headers are read\n\nThe compiler reads `.ty` data in two different modes.\n\n### Header-only reads\n\nHeader reads are used for cheap decisions:\n\n- module freshness\n- direct import names for graph construction\n- module public and implementation hashes\n- per-name dependency hash snapshots\n- roots, tests, and docstrings\n\nThis is the path used by `readModuleTask` and the various cache lookups in\n`Acton.Compile`.\n\n### Full `.ty` reads\n\nFull reads are used when the compiler needs actual interface contents or the\ntyped module:\n\n- reusing an interface from a fresh cached module\n- implementation-hash refresh\n- codegen refresh\n\nReading a full `.ty` does not by itself reconstruct the import closure in the\nactive environment. It only gives the caller the stored interface and typed\nmodule payload.\n\n## How transitive imports become available\n\nThe transitive import closure is reconstructed through `Acton.Env.mkEnv`,\n`impModule`, `doImp`, and `subImp`.\n\nWhen a module imports another module:\n\n1. `mkEnv` walks the AST import list\n2. `impModule` delegates to `doImp`\n3. `doImp` finds the imported module's `.ty`\n4. `doImp` follows the imported module's recorded imports\n5. only then does it return the imported module interface\n\nThis is the mechanism that turns a direct import into a transitive environment\nclosure suitable for kinds and type checking.\n\nAn important invariant is that a cached direct module must still restore its own\nrecorded imports. The shared scheduler env stores interfaces in `modules`, but\nthat cache does not itself contain the imported module's import list. For that\nreason, `doImp` must still consult the cached module's `.ty` header and recurse\nthrough its recorded imports even when the direct module is already present in\n`modules`.\n\nWithout that step, the compiler can end up in a state where:\n\n- the direct module is present in the shared module cache\n- the direct module's transitive imports are not\n- later type checking sees the direct module but fails when its public interface\n  refers to a transitive dependency\n\n## Practical debugging rules\n\nWhen debugging import failures, it helps to ask which layer is failing:\n\n- Is the module missing from graph discovery? Then look at `readModuleTask`,\n  `.ty` headers, and `buildGlobalTasks`.\n- Is the module outside the project graph but still needed for type checking?\n  Then look at `mkEnv` and `doImp`.\n- Is a cached module present but its transitives missing? Then the issue is in\n  environment materialization, not scheduler ordering.\n- Is a full `.ty` being read but imports still not appearing? Then check\n  whether the caller is only decoding interface payload rather than invoking the\n  import loader.\n\n## Related pages\n\n- [Compiler overview](index.md)\n- [Incremental compilation](incremental_compilation.md)\n- [Type check](passes/type_check.md)\n"
  },
  {
    "path": "docs/acton-dev-guide/src/compiler/incremental_compilation.md",
    "content": "# Incremental Compilation\n\nSee also [Imports and environments](imports_and_envs.md) for the distinction\nbetween scheduler dependency discovery and the actual import closure loaded into\nthe type-checker environment.\n\nActon compiles a whole program by walking a dependency graph that spans the\nroot project and all of its dependencies. The scheduler in `Acton.Compile`\nbuilds this total graph, runs the front passes (parse, kinds, types) in\ntopological order, and queues back passes as soon as a module's front passes\nfinish. Front work gates downstream modules, while back jobs overlap ongoing\nfront work. The scheduler runs tasks concurrently with async jobs across worker\nthreads. In watch/LSP mode, each change event bumps a generation id, cancels\nin-flight tasks, and drops stale diagnostics or back jobs that still carry the\nold generation, so we can react to new changes without waiting for obsolete\nwork to finish.\n\nInterface files and content hashes tell the scheduler what work it can safely\nreuse. `.ty` interface headers store hashes and snapshots of dependencies and\ntheir hashes. It is cheap both to compute hashes and to read and compare them.\nIf the hashes show no relevant change, the compiler can skip parsing, type\nchecking, or back passes for large parts of the graph.\n\nAt the module level we store **moduleSrcBytesHash**, **modulePubHash**, and\n**moduleImplHash**. The source-bytes hash (**moduleSrcBytesHash**) is the\nSHA-256 of the raw source bytes and is used to decide whether a cached `.ty`\nheader is still valid; if it changes, we must re-parse the `.act` file and rerun\nfront passes for that module. Reading the file is done at GB/s on modern NVMe\nhardware and hashing is typically running at roughly the same speed on modern\nCPUs.\n\nThe public hash (**modulePubHash**) is derived from the module's public-name\n`pubHash` values (which already include any external signature dependencies).\nThe implementation hash (**moduleImplHash**) is derived from per-name\n`implHash` values; it is stored in the `.ty` header and written into generated\n`.c`/`.h` files as an \"Acton impl hash\" tag. If the tag is missing or\nmismatched, we rerun back passes even if no other hashes changed.\n\nHashing within a module is done per top-level name. A hashable unit is a `Def`,\n`Actor`, `Class`, `Protocol`, `Extension`, or any top-level value introduced by\na binding statement such as `a = 123` or `b, c = f()`. Entries are keyed by the\nlocal `Name`; external references are stored as `QName` (canonicalized to\n`GName` with `unalias`), and extensions use the derived name from\n`extensionName`. For now class/actor implementation hashes are coarse and cover\nthe entire body; per-method hashing can refine this later.\n\nEach unit has three hashes. **srcHash** is the hash of the kinds-checked AST for\nthat name (pretty-printed), and is the earliest signal that a single declaration\nchanged. We use the kinds-checked form because it is the first pass that\nnormalizes type-level syntax (implicit type arguments, canonical kind structure)\nwithout paying the cost of full type inference. Hashing the raw parsed AST would\nmake equivalent signatures hash differently and trigger needless rebuilds.\n**pubHash** is the hash of the unit's public interface (doc-free `NameInfo`)\ncombined with the public hashes of external declarations referenced by its type\nsignature. **implHash** is the hash of the unit's implementation combined with\nthe implementation hashes of external declarations referenced from the body.\nBecause we hash pretty-printed source, docstrings currently influence\n`implHash`; we can tighten the normalization later without changing the overall\nmodel.\n\nName hashes depend on `NameInfo`. The type checker environment (`teAll`) is\nauthoritative for user-facing declarations, but it does not include compiler-\ngenerated names (for example, protocol lowering emits classes such as\n`MinusD_Number`). The typed AST does include those generated names, so we derive\ntheir `NameInfo` with `QuickType.envOf`. Conversely, `envOf` omits `Protocol`\nand `Extension` entries because type inference translates them away. To cover\nboth, hashing uses the union of `teAll` and `QuickType.envOf` as its name-info\nmap, ensuring generated names appear in `.ty` and still keeping protocol and\nextension hashes intact.\n\nTo detect changes without recompiling, each per-name entry in `.ty` stores\ndependency snapshots. **pubDeps** is a list of `(QName, pubHash)` for external\ndeclarations referenced from the unit's type signature and from value-level\nuses, which is what triggers re-typechecking when a provider's public interface\nchanges. **implDeps** is a list of `(QName, implHash)` referenced from the body\nand is what triggers codegen and test invalidation. Only external dependencies\nare stored; local dependencies are folded into the computed hash during\ncompilation.\n\nMutually recursive groups are hashed as a unit to avoid fixed-point iteration.\nWe compute `selfPubHash`/`selfImplHash` for each unit, compute a `groupHash`\nfrom the sorted self-hashes plus all external dependency hashes of the group,\nand then finalize each unit as `H(selfHash || groupHash || unitKey)`.\n\nThe `.ty` header stays ordered for fast reads:\n\n```\nversion\nmoduleSrcBytesHash\nmodulePubHash\nmoduleImplHash\nimports\nnameHashInfo      -- per-name src/pub/impl hash + dep snapshots\nroots\ndocstring\nnameInfo\ntypedModule\n```\n\nA source change always re-runs front passes for that module. Downstream modules\ncompare recorded `pubDeps` against current provider hashes; any delta triggers\nre-typechecking. Separately, `implDeps` changes cause back passes and tests to\nrerun even when public hashes are stable. Missing or stale `.c`/`.h` outputs\nalso force back passes so codegen can recover. To see the decisions, run\n`acton build --verbose`; it prints stale reasons and per-name hash deltas. The\nsnippets below abbreviate hashes to 8 hex digits for readability.\n\n**Implementation-only change.** Before:\n\n```acton\n# a.act\ndef foo(x: int) -> int:\n    return x + 1\n\n# b.act\nimport a\n\ndef bar() -> int:\n    return a.foo(1)\n```\n\nAfter changing only the body of `foo`:\n\n```acton\n# a.act\ndef foo(x: int) -> int:\n    return x + 2\n```\n\n`srcHash(foo)` and `implHash(foo)` change while `pubHash(foo)` does not.\nDownstream modules keep their public hashes stable, so they do not re-typecheck\nbut they do rerun back passes:\n\n```text\n$ acton build --verbose\nBuilding project in /path/proj\nResolving dependencies (fetching if missing)...\n  Stale a: source changed\n  Hash deltas a: ~foo{src 12fa0b1c -> 3e3485be, impl 4bf97616 -> f736da16}\n   Finished type check of     /path/proj/a      0.004 s\n  Stale b: impl changes in a.foo 4bf97616 -> f736da16 (used by bar)\n   Finished compilation of    /path/proj/a      0.002 s\n   Finished compilation of    /path/proj/b      0.003 s\n```\n\n**Public signature change.** Before:\n\n```acton\n# a.act\ndef foo(x: int) -> int:\n    return x + 1\n\n# b.act\nimport a\n\ndef bar() -> int:\n    return a.foo(1)\n```\n\nAfter changing the signature of `foo`:\n\n```acton\n# a.act\ndef foo(x: int) -> float:\n    return float(x)\n\n# b.act\nimport a\n\ndef bar() -> float:\n    return a.foo(1)\n```\n\nHere `pubHash(foo)` changes, so `modulePubHash(a)` changes and any dependent\nthat recorded `a.foo` in `pubDeps` must re-typecheck:\n\n```text\n$ acton build --verbose\nBuilding project in /path/proj\nResolving dependencies (fetching if missing)...\n  Stale a: source changed\n  Hash deltas a: ~foo{src 2f1a8c9b -> 3a7bb6e1, pub 91c2efb8 -> 5e7d9b02, impl 11c0aa34 -> 6b3e42f1}\n   Finished type check of     /path/proj/a      0.004 s\n  Stale b: pub changes in a.foo 91c2efb8 -> 5e7d9b02 (used by bar)\n   Finished type check of     /path/proj/b      0.005 s\n   Finished compilation of    /path/proj/a      0.002 s\n   Finished compilation of    /path/proj/b      0.003 s\n```\n\n**Codegen-only staleness.** If generated output is missing or mismatched, we\nrerun back passes even when hashes are unchanged. For example, deleting the\noutputs forces codegen to refresh:\n\n```text\n$ rm out/types/b.c out/types/b.h\n$ acton build --verbose\nBuilding project in /path/proj\nResolving dependencies (fetching if missing)...\n  Stale b: generated code out of date {impl c missing -> 7aa13f90, h missing -> 7aa13f90}\n   Finished compilation of    /path/proj/b      0.003 s\n```\n\n**Non-propagating change.** Adding an unused import changes the module source\nbytes, so the module itself re-runs front passes, but downstream modules do\nnot re-typecheck because no public hashes changed:\n\n```acton\n# before (b.act)\nimport a\n\ndef bar() -> int:\n    return a.foo()\n\n# after (b.act)\nimport a\nimport testing  # unused\n\ndef bar() -> int:\n    return a.foo()\n```\n\nKnown limitations include the lack of incremental typechecking within a\nmodule, coarse class/actor impl hashes, and docstrings affecting `implHash`.\n"
  },
  {
    "path": "docs/acton-dev-guide/src/compiler/index.md",
    "content": "# Compiler\n\nThe compiler runs a fixed sequence of AST-to-AST transforms before finally\ngenerating C.  The main entry point is `compiler/acton/Main.hs`, which wires\nthe stages together via the `compiler/lib` modules listed below. All the real\nlogic are contained in these modules and are thus accessible and usable as a\nlibrary.\n\nThe same AST data type is used throughout all compiler passes, making it easy to\nread and understand what each transformation does.\n\nSee [Imports and environments](imports_and_envs.md) for how the scheduler,\n`.ty` headers, and the active type-checker environment fit together.\n\nSee [Project dependencies](project_dependencies.md) for how Acton package\ndependencies and zig dependencies are discovered, fetched, and emitted into the\ngenerated Zig build files.\n\nSee [Passes](passes/index.md) for the stage-by-stage pipeline and how front and\nback passes split the work.\n"
  },
  {
    "path": "docs/acton-dev-guide/src/compiler/passes/boxing.md",
    "content": "# Boxing\n\nImplementation lives in `compiler/lib/src/Acton/Boxing.hs`.\n\nValues in Acton are mostly boxed. The boxing pass can unbox values in certain situations, which can greatly improve performance by avoiding unnecessary boxing operations. The more we can unbox, the better, but it is at odds with generics and polymorphism.\n\n- Inserts explicit `Box`/`UnBox` nodes to model conversions between boxed runtime\n  objects and unboxed machine values.\n- Introduces unboxed temporaries for numeric primitives (ints/uints/floats) so\n  codegen can emit efficient C operations.\n- Rewrites selected builtin operations (arithmetic/comparisons, math functions,\n  and some builtin methods) to operate on unboxed values and then re-box results.\n\nThe pass keeps a map from boxed names to their unboxed counterparts in its\nenvironment and generates internal names using the `BoxPass` prefix. It also\npreserves boxed values where needed so later stages still see the expected\nsurface semantics.\n\n## Debugging\n\n```sh\nacton --box path/to/file.act\n```\n\n## Thoughts\n\n- Push unboxing further without changing the type system by operating late,\n  after type-checking and lowering, where the AST is simpler and richly typed.\n- Treat unboxable primitives (bounded ints, floats, bool) as unboxed in locals,\n  params, returns, and class fields, and only box/unbox at polymorphic\n  boundaries.\n- Keep polymorphic code boxed; allow monomorphic code to be unboxed, with boxing\n  inserted at call sites when crossing module boundaries or calling polymorphic\n  functions.\n- Extend the pass to cover classes and cross-module calls; current behavior is\n  limited to function bodies and initializers.\n"
  },
  {
    "path": "docs/acton-dev-guide/src/compiler/passes/codegen.md",
    "content": "# Codegen\n\nImplementation lives in `compiler/lib/src/Acton/CodeGen.hs`.\n"
  },
  {
    "path": "docs/acton-dev-guide/src/compiler/passes/cps.md",
    "content": "# CPS\n\nImplementation lives in `compiler/lib/src/Acton/CPS.hs`.\n"
  },
  {
    "path": "docs/acton-dev-guide/src/compiler/passes/deactorize.md",
    "content": "# Deactorize\n\nImplementation lives in `compiler/lib/src/Acton/Deactorizer.hs`.\n"
  },
  {
    "path": "docs/acton-dev-guide/src/compiler/passes/index.md",
    "content": "# Passes\n\nThe compiler runs a fixed sequence of AST-to-AST transforms before finally\ngenerating C. The main entry point is `compiler/acton/Main.hs`, which wires\nthe stages together via the `compiler/lib` modules listed below. All the real\nlogic is contained in these modules and is thus accessible and usable as a\nlibrary.\n\nThe same AST data type is used throughout all compiler passes, making it easy to\nread and understand what each transformation does.\n\n## Stages (in order)\n\n| Stage | Module | Description |\n| --- | --- | --- |\n| [Parse](parse.md) | `compiler/lib/src/Acton/Parser.hs` | |\n| [Kinds check](kinds.md) | `compiler/lib/src/Acton/Kinds.hs` | |\n| [Type check](type_check.md) | `compiler/lib/src/Acton/Types.hs`, `compiler/lib/src/Acton/TypeEnv.hs` | |\n| [Normalize](normalize.md) | `compiler/lib/src/Acton/Normalizer.hs` | |\n| [Deactorize](deactorize.md) | `compiler/lib/src/Acton/Deactorizer.hs` | |\n| [CPS](cps.md) | `compiler/lib/src/Acton/CPS.hs` | |\n| [Lambda lift](lambda_lift.md) | `compiler/lib/src/Acton/LambdaLifter.hs` | |\n| [Boxing](boxing.md) | `compiler/lib/src/Acton/Boxing.hs` | |\n| [Codegen](codegen.md) | `compiler/lib/src/Acton/CodeGen.hs` | |\n\nThe final C source is compiled and linked by the Zig build system.\n\nFor how imports are loaded before these passes run, see\n[Imports and environments](../imports_and_envs.md).\n\n## Front vs back passes\n\nThe pipeline is split into a front end and a back end. The scheduler runs all\nfront passes across the dependency graph first, then queues back-pass work once\ntype checking succeeds for a module.\n\nFront passes (1–3) are:\n- Parse\n- Kinds check\n- Type check\n\nThese passes produce all user-facing diagnostics, write the module interface\nheader (`.ty`), and compute public hashes used for incremental rebuilds. They\nalso define the cross-module dependency edges: a module can only start once its\nimports have completed the front passes.\n\nBack passes (4–9) are:\n- Normalize\n- Deactorize\n- CPS\n- Lambda lift\n- Boxing\n- Codegen\n\nThe back end consumes the typed module from the front end and emits C and header\nfiles (`.c`, `.h`). It does not introduce new user errors, so it can run after\nfront completion and even in the background. The CLI waits for all back jobs to\nfinish before invoking Zig; the LSP enqueues back jobs in the background and\ndoes not wait for them or run Zig.\n\nThe shared orchestration lives in `compiler/lib/src/Acton/Compile.hs` and is\nused by both `acton` and the LSP server.\n"
  },
  {
    "path": "docs/acton-dev-guide/src/compiler/passes/kinds.md",
    "content": "# Kinds check\n\nImplementation lives in `compiler/lib/src/Acton/Kinds.hs`.\n"
  },
  {
    "path": "docs/acton-dev-guide/src/compiler/passes/lambda_lift.md",
    "content": "# Lambda lift\n\nImplementation lives in `compiler/lib/src/Acton/LambdaLifter.hs`.\n"
  },
  {
    "path": "docs/acton-dev-guide/src/compiler/passes/normalize.md",
    "content": "# Normalize\n\nImplementation lives in `compiler/lib/src/Acton/Normalizer.hs`.\n"
  },
  {
    "path": "docs/acton-dev-guide/src/compiler/passes/parse.md",
    "content": "# Parse\n\nImplementation lives in `compiler/lib/src/Acton/Parser.hs`.\n\n- Parses `.act` source into the core AST (`Module`).\n- Uses the Haskell Megaparsec library\n- Tracks parse context (top-level, actor, loop, etc.) to enforce where\n  statements are allowed.\n- Attaches source locations so later stages can produce precise errors.\n\nThe entry point is `parseModule`, which takes a module name, filename, and file\ncontents, then returns the parsed `Module`. It also appends a trailing newline\nif the file is missing one to keep the parser consistent.\n\n## Debugging\n\nUse compiler flags to inspect the parser output:\n\n```sh\nacton --parse path/to/file.act\nacton --parse-ast path/to/file.act\n```\n\n## Tests\n\nThere are unit tests for the parser in ActonSpec.hs, in particular the string interpolation support is fairly well tested. Please add more tests.\n\n## Thoughts\n- It is hard to write a parser. It is even harder to write a parser with good error reporting... and once you do, it's probably not going to perform very well.\n- Our parser has some good error reporting, in particular around string interpolation. It can be improved in other areas. The aspiration as always is super friendly error messages.\n- TODO: When we encounter errors, the parser should be able to recover and continue parsing the rest of the file. We'd need to mark such nodes as Bad nodes (I think the Bad name is a good one) and also accumulate a list of errors instead of immediately reporting errors and exiting\n"
  },
  {
    "path": "docs/acton-dev-guide/src/compiler/passes/type_check.md",
    "content": "# Type check\n\nThe type checker follows a Hindley-Milner style and borrows the protocol model from Swift.\nImplementation lives in `compiler/lib/src/Acton/Types.hs` and `compiler/lib/src/Acton/TypeEnv.hs`.\n\nThe type checker runs on top of an import-augmented environment produced by\n`Acton.Env.mkEnv`, not directly on the scheduler's raw module graph. See\n[Imports and environments](../imports_and_envs.md) for the environment layers\nand how transitive imports are materialized from `.ty` files.\n"
  },
  {
    "path": "docs/acton-dev-guide/src/compiler/project_dependencies.md",
    "content": "# Project Dependencies\n\nActon has two different dependency layers during a build:\n\n- Acton package dependencies from `Build.act` `dependencies`\n- Zig package dependencies from `Build.act` `zig_dependencies`\n\nThey are related, but they do not participate in the build in the same way.\n\n## Discovery and fetch\n\nProject discovery in `Acton.Compile` only follows Acton package dependencies.\nThose edges determine the project graph used for module ordering, cache reuse,\nimport visibility, and type-check planning.\n\nZig dependencies are not Acton project edges. They do not contribute modules to\nthe import graph and they are not used for project discovery.\n\nFetch still needs them, though. For each reachable Acton project, the fetch\nphase downloads or copies both that project's package dependencies and its zig\ndependencies before later compile planning uses them.\n\n## Generated `build.zig` inputs\n\n`acton build` generates a `build.zig` and `build.zig.zon` for the current\nproject in `compiler/acton/Main.hs`.\n\nAt that point Acton combines:\n\n- direct package dependencies of the current project\n- transitive package dependencies reachable through package dependencies\n- direct zig dependencies of the current project\n- transitive zig dependencies from all reachable Acton projects\n\nTransitive zig dependencies are flattened into the consuming project's generated\nZig manifest because the generated build may need to link their declared\nartifacts directly.\n\n### Example: one wrapper package\n\nConceptually, a root project might look like this:\n\n```text\nroot\n└── package dep \"lmdb\" -> acton-lmdb\n    └── zig dep \"lmdb\" -> raw LMDB zig package\n```\n\nThat means the root project imports an Acton package named `lmdb`, while that\npackage in turn links against a zig package also declared as `lmdb`.\n\nThe generated root `build.zig.zon` needs both of them as sibling entries, so\nActon emits separate local names:\n\n```zig\n.dependencies = .{\n    .lmdb = .{ ... },             // Acton package dep\n    .acton_zig_lmdb = .{ ... },   // underlying zig dep\n},\n```\n\nThe Acton package keeps the user-facing name `lmdb`. The zig package gets a\ngenerated local alias because both entries live in the same Zig dependency\ntable.\n\n## Local Zig names\n\nZig dependency names are only local aliases inside one generated\n`build.zig.zon`. They are not global identities across the whole dependency\ntree.\n\nActon therefore keeps package dependency names unchanged and assigns internal\nnames to zig dependencies when rendering build metadata:\n\n- package dependencies keep their declared names\n- zig dependencies get generated names with an `acton_zig_` prefix\n- if multiple distinct zig dependencies would reuse the same local name, Acton\n  appends a numeric suffix\n\nThis means an Acton package dependency named `lmdb` can coexist with a zig\ndependency also declared as `lmdb`, and two different transitive zig packages\nthat both use the local name `shared` can still appear together in one\ngenerated manifest.\n\n### Example: colliding transitive zig names\n\nConsider this project graph:\n\n```text\nroot\n├── package dep \"dep_a\"\n│   └── zig dep \"shared\" -> zig_common\n├── package dep \"dep_b\"\n│   └── zig dep \"shared\" -> zig_common\n└── package dep \"dep_c\"\n    └── zig dep \"shared\" -> zig_other\n```\n\nAll three zig dependencies are named `shared` in their own local `Build.act`,\nbut once they are flattened into the root manifest they become siblings.\n\nThe generated root `build.zig.zon` therefore looks conceptually like:\n\n```zig\n.dependencies = .{\n    .dep_a = .{ ... },\n    .dep_b = .{ ... },\n    .dep_c = .{ ... },\n    .acton_zig_shared = .{ ... },     // zig_common\n    .acton_zig_shared_2 = .{ ... },   // zig_other\n},\n```\n\nThere is no `.acton_zig_shared_3`, because `dep_a` and `dep_b` refer to the\nsame zig package identity and are deduplicated before local names are assigned.\n\n## Deduplication\n\nBefore assigning local zig names, Acton deduplicates zig dependency references\nby resolved identity plus Zig build options.\n\nToday that identity is derived from whichever source locator is present:\n\n- rebased path plus options\n- content hash plus options\n- URL plus options\n\nWhen two references resolve to the same identity, Acton emits one local zig\ndependency entry and merges the requested artifact names. When the identities\ndiffer, both dependencies stay present and receive separate local aliases.\n\nSo collisions only matter among sibling entries in one generated\n`build.zig.zon`, and only after deduplication has decided whether two\nreferences are really the same package instance.\n\n### Example: same package, different options\n\nOptions are part of the zig dependency identity. So this conceptual tree:\n\n```text\nroot\n├── package dep \"tls_a\"\n│   └── zig dep \"mbedtls\" -> same package, options { .pic = true }\n└── package dep \"tls_b\"\n    └── zig dep \"mbedtls\" -> same package, options { .pic = false }\n```\n\nstill produces two sibling zig entries in the root `build.zig.zon`, because\nthe Zig build instances are not interchangeable:\n\n```zig\n.dependencies = .{\n    .tls_a = .{ ... },\n    .tls_b = .{ ... },\n    .acton_zig_mbedtls = .{ ... },     // options { .pic = true }\n    .acton_zig_mbedtls_2 = .{ ... },   // options { .pic = false }\n},\n```\n\n## Practical debugging rules\n\n- Import or type-check failures are usually about Acton package discovery, not\n  zig dependencies.\n- Linker or `b.dependency(...)` lookup failures are usually about generated\n  `build.zig` and `build.zig.zon` contents.\n- Root dependency pinning and `--dep` overrides apply to Acton package\n  dependencies, not zig dependencies.\n"
  },
  {
    "path": "docs/acton-dev-guide/src/compiler/test_cache.md",
    "content": "# Test result cache\n\nActon caches test results using per-name implementation hashes to decide when a\ntest must be rerun. The cache is stored in `out/test/cache.json` and is updated\nafter each `acton test` run.\n\n## Run context hash\n\nEach run computes a context hash that captures inputs that affect test behavior\nwithout changing source code:\n\n- compiler version (`acton` version string)\n- target triple\n- optimize mode\n- test mode (run/perf)\n- test runner arguments (iteration and timing limits)\n\nThe context hash is SHA-256 over the JSON-encoded context record.\n\n## Per-test hash\n\nEach test’s run hash is SHA-256 over:\n\n```\nimplHash || depsHash || contextHash\n```\n\nWhere `implHash` is the per-name implementation hash from the module’s `.ty`\nheader. `depsHash` is a hash of the test’s current implementation dependencies\n(`implDeps`), resolved to their latest impl hashes via the `.ty` headers on the\nsearch path. Test name resolution uses the `.ty` name hash map, and applies\nsimple fallbacks for generated actor wrappers:\n\n- try the test name as-is\n- if it ends in `_wrapper`, try the name without the suffix\n- if it begins with `_test_`, try the name without the prefix\n\nIf no implementation hash can be resolved, the test is always rerun.\n\n## Cache format\n\nThe cache file is JSON:\n\n```\n{\n  \"version\": 1,\n  \"context\": { ... },\n  \"tests\": {\n    \"module:testName\": {\n      \"runHash\": \"...\",\n      \"implHash\": \"...\",\n      \"result\": { ... }\n    }\n  }\n}\n```\n\nThe `result` payload mirrors the test runner’s result fields (success/exception,\nfailures/errors, iterations, and duration).\n\n## Behavior\n\n- If the cached run hash matches the newly computed run hash, the test is\n  normally skipped and its cached result is used.\n- Snapshot tests add one more guard: a cached result is only reused when the\n  `snapshots/output/...` file exists, the current expected snapshot file has\n  the same size as that output file, and the expected snapshot has an older\n  modification time. If the output file is missing, the expected file changed\n  or disappeared, or the metadata does not prove it is older than the last\n  produced output, the test is rerun.\n- With `--no-cache`, cached results are ignored and all selected tests are run.\n- Cached failures and errors still contribute to the overall test exit code.\n- By default, cached successes are hidden from output; cached failures/errors\n  are still shown. Use `--show-cached` to include cached successes.\n- Snapshot expected updates are written only for tests executed in the current run.\n- Snapshot outputs are written for reported tests (cached results reuse cached output).\n"
  },
  {
    "path": "docs/acton-dev-guide/src/design/capabilities.md",
    "content": "# Capabilities\n\nExplain the capability model, how it is represented in the compiler,\nand the invariants that enforce safety.\n"
  },
  {
    "path": "docs/acton-dev-guide/src/design/concurrency.md",
    "content": "# Concurrency model\n\nDocument the concurrency semantics the compiler assumes and the runtime enforces.\nInclude how scheduling and async boundaries interact with the type system.\n"
  },
  {
    "path": "docs/acton-dev-guide/src/design/index.md",
    "content": "# Design notes\n\nThis section captures rationale and tradeoffs behind major design choices.\nUse it for decisions that are not obvious from code alone.\n"
  },
  {
    "path": "docs/acton-dev-guide/src/getting_started/build.md",
    "content": "# Build and run\n\nThis repo builds the compiler (Haskell), runtime, and bundled deps into `dist/`.\n\n## Prereqs\n\n- `stack` for Haskell builds (compiler + LSP)\n- `make`, `curl`, `tar`, `xz` (used by the Makefile)\n- Zig is downloaded automatically into `dist/zig` (version pinned in `Makefile`)\n\n## Common targets\n\n```sh\nmake                    # build full distribution (compiler, runtime, deps)\nmake dist/bin/acton     # compiler + lsp-server-acton only (fast for compiler work)\nmake dist/bin/actonc    # compatibility symlink to acton\n```\n\n## Running local binaries\n\n```sh\ndist/bin/acton path/to/file.act\ndist/bin/acton build\ndist/bin/acton test\ndist/bin/actonc path/to/file.act   # compatibility alias\n```\n\n- Prefer `dist/bin/*` to avoid accidentally using a globally installed Acton.\n- `make clean` removes build outputs; `make clean-all` also removes the Zig cache.\n\n## Caching and build knobs\n\n- `ZIG_LOCAL_CACHE_DIR` controls Zig's cache location (defaults to `~/.cache/acton/zig-local-cache` when `HOME` is set).\n- `BUILD_RELEASE=1 make` stamps release versions; default builds get a timestamped version suffix.\n- On Linux, the Makefile uses Zig for the Stack/GHC C compiler path and pins the default glibc target to 2.31 for compatibility.\n- `ACTON_ZIG_GLIBC_VERSION` overrides the glibc version used for Stack/GHC linking on Linux.\n- Linux release builds should run in a builder with system static libraries no newer than the requested glibc target.\n"
  },
  {
    "path": "docs/acton-dev-guide/src/getting_started/debugging.md",
    "content": "# Debugging\n\nCapture the preferred debugging workflow for compiler and runtime changes.\nInclude tips for logging, tracing, and inspecting intermediate compiler artifacts.\n"
  },
  {
    "path": "docs/acton-dev-guide/src/getting_started/repo_layout.md",
    "content": "# Repository layout\n\nTop-level directories are grouped by subsystem and build outputs.\n\n| Path | Purpose |\n| --- | --- |\n| `compiler/` | Acton compiler & LSP (`acton`, `lsp-server-acton`). Written in Haskell. |\n| `base/` | Builtins, RTS, and standard library sources. |\n| `backend/` | Distributed RTS database backend. |\n| `builder/` | Zig build system helper definitions. |\n| `bin/` | Small helper binaries/scripts (e.g. `runacton`). |\n| `completion/` | Shell completion assets. |\n| `deps/` | Vendored third-party sources used by the build. |\n| `deps-download/` | Cached dependency tarballs (generated). |\n| `dist/` | Build output and bundled distribution (generated). |\n| `docs/` | Documentation, like this dev guide. |\n| `examples/` | Example programs and snippets. |\n| `test/` | Integration tests, runtime/db harness, stdlib tests. |\n| `utils/` | Misc tooling, scripts, and dev helpers. |\n| `ecolift/` | Lifting the Acton ecosystem for new language features. |\n| `debian/` | Debian packaging. |\n| `homebrew/` | Homebrew formulae. |\n| `slides/` | Presentation material. |\n| `workspace/` | Scratch notes and experiments (not part of build). |\n"
  },
  {
    "path": "docs/acton-dev-guide/src/getting_started/tests.md",
    "content": "# Tests\n\nThe top-level Makefile drives test execution and wires together compiler,\nstdlib, backend, and runtime suites.\n\n## Run everything\n\n```sh\nmake test\n```\n\nThis runs:\n- `stack test` for the compiler packages\n- stdlib tests (`make test-stdlib`)\n- backend tests (`make -C backend test`)\n- runtime/db tests (`make -C test`)\n\n## Targeted suites\n\n```sh\nmake test-compiler\nmake test-builtins\nmake test-stdlib\nmake test-rts\nmake test-backend\n```\n\n## Snapshot / acceptance tests\n\nSome compiler suites have explicit accept targets that update expected output:\n\n```sh\nmake test-incremental\nmake test-incremental-accept\nmake test-syntaxerrors\nmake test-syntaxerrors-accept\nmake test-typeerrors\nmake test-typeerrors-accept\n```\n\n`test-incremental*` requires `dist/bin/acton` (it is built automatically by the target).\n`test-rebuild*` remains as an alias for the incremental suite.\n\n## Project tests with acton\n\nRun tests for the current Acton project (expects a `Build.act` in the cwd):\n\n```sh\nacton test\n```\n\nExample output:\n\n```text\n$ acton test\nBuilding project in /path/to/project\n  Final compilation step\n   Finished final compilation step in   0.462 s\nTest results:\n  c.bar:                 OK:  445 runs in 50.160ms\n  c.foo:                 OK:  444 runs in 50.188ms\nAll 2 tests passed ( 0.528 s)\n```\n\nBy default, `acton test` shows only tests that ran in the current invocation;\ncached successes are hidden (cached failures/errors are still shown). Use\n`--show-cached` to include cached successes in the output. Use `--no-cache` to\nforce all selected tests to execute instead of reusing cached results.\n\n## Tips\n\n- Prefer `make test-compiler` when iterating on Haskell changes.\n- Use `dist/bin/acton test` for Acton project-level tests in other repos.\n"
  },
  {
    "path": "docs/acton-dev-guide/src/getting_started.md",
    "content": "# Getting started\n\nThis section collects practical instructions for setting up a development environment,\nbuilding the compiler, and running tests locally.\n"
  },
  {
    "path": "docs/acton-dev-guide/src/index.md",
    "content": "# Overview\n\nThis book is an internal reference for the Acton compiler, runtime, builtins and\ntooling.  It focuses on architecture, key invariants, and how to extend or debug\nthe system.\n\n## Who this is for\n\n- Contributors working on language, compiler, runtime etc\n- Maintainers of builtins and standard library\n- Anyone needing to understand internal behavior\n"
  },
  {
    "path": "docs/acton-dev-guide/src/runtime/actors.md",
    "content": "# Actors\n\nExplain runtime actor lifecycle, mailbox behavior, and supervision semantics.\nReference any integration points with the compiler.\n"
  },
  {
    "path": "docs/acton-dev-guide/src/runtime/index.md",
    "content": "# Runtime\n\nThis section covers the runtime system, scheduling model, and core services\nthat the compiler targets.\n"
  },
  {
    "path": "docs/acton-dev-guide/src/runtime/memory.md",
    "content": "# Memory and GC\n\nDescribe allocation strategy, garbage collection, and ownership conventions.\nInclude debugging tips for leaks or performance regressions.\n"
  },
  {
    "path": "docs/acton-dev-guide/src/runtime/scheduler.md",
    "content": "# Scheduler\n\nDocument the actor scheduler, queues, and fairness guarantees.\nInclude relevant configuration knobs and metrics.\n"
  },
  {
    "path": "docs/acton-dev-guide/src/tooling/index.md",
    "content": "# Tooling\n\nThis section documents developer-facing tools, scripts, and workflows\nused to build, test, and release Acton.\n"
  },
  {
    "path": "docs/acton-dev-guide/src/tooling/testing.md",
    "content": "# Testing harness\n\nDocument the internal test runner, fixtures, and any custom assertions.\nInclude guidance for adding new compiler or runtime tests.\n"
  },
  {
    "path": "docs/acton-dev-guide/svgbob.css",
    "content": " /* Ensure text is legible in all themes. */\nsvg text {\n  fill: var(--fg);\n}\n"
  },
  {
    "path": "docs/acton-dev-guide/theme/content-width.css",
    "content": "/* Wider content area for better side-by-side code display */\n\n/* Increase main content width and center it */\n.content main {\n    max-width: 900px !important;\n    margin: 0 auto !important;\n    padding: 0 15px;\n}\n\n/* Wider content on larger screens */\n@media (min-width: 1200px) {\n    .content main {\n        max-width: 950px !important;\n    }\n}\n\n@media (min-width: 1400px) {\n    .content main {\n        max-width: 1000px !important;\n    }\n}\n\n@media (min-width: 1600px) {\n    .content main {\n        max-width: 1050px !important;\n    }\n}\n\n/* Make code blocks in side-by-side tables use available space better */\n.side-by-side-code td:first-child {\n    width: 35%; /* Explanations/comments column */\n}\n\n.side-by-side-code td:last-child {\n    width: 65%; /* Code column - more space for code */\n}\n\n/* Adjust pre/code blocks to not add unnecessary padding in tables */\n.side-by-side-code pre {\n    margin: 0;\n    padding: 10px;\n}\n\n.side-by-side-code td {\n    padding: 12px;\n}\n\n/* For very wide screens, cap the side-by-side table width for readability */\n@media (min-width: 1600px) {\n    .side-by-side-code {\n        max-width: 1400px;\n        margin-left: auto;\n        margin-right: auto;\n    }\n}"
  },
  {
    "path": "docs/acton-dev-guide/theme/sbscode.css",
    "content": "/* Custom table styling for side-by-side documentation */\n.content table.side-by-side-code {\n    display: table;\n    width: 100%;\n    margin: 0;\n    border-collapse: collapse;\n    border: none;\n    background: none;\n    table-layout: fixed;\n}\n\n/* Dark theme support */\n.rust.light-theme .content table.side-by-side-code td:last-child {\n    background: var(--quote-bg);\n}\n\n.rust.dark-theme .content table.side-by-side-code td:last-child {\n    background: var(--quote-bg);\n}\n\n/* Ensure button contrast in both themes */\n.rust.light-theme .content table.side-by-side-code .buttons {\n    background: var(--bg);\n    color: var(--fg);\n}\n\n.rust.dark-theme .content table.side-by-side-code .buttons {\n    background: var(--bg);\n    color: var(--fg);\n}\n\n/* Remove default mdBook table styling */\n.content table.side-by-side-code tbody tr {\n    background: none !important;\n    border: none;\n}\n\n.content table.side-by-side-code td {\n    border: none;\n    padding: 0.5rem;\n    vertical-align: top;\n}\n\n/* Left column (prose) styling */\n.content table.side-by-side-code td:first-child {\n    width: 35%;\n    padding-right: 1.5rem;\n    color: var(--fg);\n}\n\n/* Right column (code) styling */\n.content table.side-by-side-code td:last-child {\n    width: 65%;\n    background: var(--quote-bg);\n    border-radius: 0;\n}\n\n/* Round only the top corners of the first row's code cell */\n.content table.side-by-side-code tr:first-child td:last-child {\n    border-top-left-radius: 4px;\n    border-top-right-radius: 4px;\n}\n\n/* Round only the bottom corners of the last row's code cell */\n.content table.side-by-side-code tr:last-child td:last-child {\n    border-bottom-left-radius: 4px;\n    border-bottom-right-radius: 4px;\n}\n\n/* Hide mdBook's default copy buttons in our special tables */\n.content table.side-by-side-code pre > .buttons {\n    display: none !important;\n}\n\n/* Code block styling */\n.content table.side-by-side-code td pre {\n    margin: 0;\n    padding: 0.5rem;\n    background: none;\n}\n\n.content table.side-by-side-code td code {\n    background: none;\n    padding: 0;\n}\n\n/* Ensure continuous code blocks */\n.content table.side-by-side-code tr + tr td:last-child {\n    padding-top: 0;\n}\n\n/* Hide empty prose cells */\n.content table.side-by-side-code td:first-child:empty {\n    padding: 0;\n    border: none;\n}\n\n/* Position the buttons container */\n.content table.side-by-side-code td:last-child {\n    position: relative;\n}\n\n/* Keep original mdBook button styling for our custom button */\n.content table.side-by-side-code .buttons {\n    position: absolute;\n    top: 0.5rem;\n    right: 0.5rem;\n    opacity: 0;\n    transition: opacity 0.2s;\n}\n\n.content table.side-by-side-code:hover .buttons {\n    opacity: 1;\n}\n"
  },
  {
    "path": "docs/acton-dev-guide/theme/sbscode_copy.js",
    "content": "document.addEventListener('DOMContentLoaded', () => {\n    // Select all side-by-side-code tables\n    const codeTables = document.querySelectorAll('table.side-by-side-code');\n\n    codeTables.forEach(table => {\n        // Get all code cells in this table\n        const codeCells = table.querySelectorAll('td:last-child');\n        if (codeCells.length === 0) return;\n\n        // Create button container div\n        const buttonDiv = document.createElement('div');\n        buttonDiv.className = 'buttons';\n\n        // Create copy button with mdBook's styling\n        const copyButton = document.createElement('button');\n        copyButton.className = 'fa fa-copy clip-button';\n        copyButton.setAttribute('title', 'Copy to clipboard');\n        copyButton.setAttribute('aria-label', 'Copy to clipboard');\n\n        // Add tooltip span\n        const tooltip = document.createElement('i');\n        tooltip.className = 'tooltiptext';\n        copyButton.appendChild(tooltip);\n\n        // Get all code blocks from all cells in this table\n        const getAllCode = () => {\n            const allCodeBlocks = table.querySelectorAll('td:last-child pre code');\n            return Array.from(allCodeBlocks)\n                .map(block => block.textContent)\n                .join('\\n');\n        };\n\n        // Add click handler\n        copyButton.addEventListener('click', async () => {\n            const code = getAllCode();\n            await navigator.clipboard.writeText(code);\n\n            // Visual feedback using tooltip\n            tooltip.textContent = 'Copied!';\n            setTimeout(() => {\n                tooltip.textContent = '';\n            }, 2000);\n        });\n\n        // Add the button to the container and container to the first code cell\n        buttonDiv.appendChild(copyButton);\n        codeCells[0].appendChild(buttonDiv);\n    });\n});\n"
  },
  {
    "path": "docs/acton-dev-guide/theme/skill-slider.css",
    "content": "/* Skill Slider Styles for Acton Guide */\n\n/* Skill control widget in menu bar */\n.skill-control-menu {\n    display: inline-flex;\n    align-items: center;\n    margin-right: 10px;\n}\n\n.skill-slider-wrapper {\n    display: flex;\n    align-items: center;\n    gap: 8px;\n}\n\n.skill-control-menu .skill-slider {\n    width: 60px;\n    -webkit-appearance: none;\n    height: 3px;\n    border-radius: 2px;\n    background: var(--scrollbar);\n    outline: none;\n    opacity: 0.7;\n    transition: opacity 0.2s;\n    cursor: pointer;\n}\n\n.skill-control-menu .skill-slider:hover {\n    opacity: 1;\n}\n\n.skill-control-menu .skill-slider::-webkit-slider-thumb {\n    -webkit-appearance: none;\n    appearance: none;\n    width: 12px;\n    height: 12px;\n    border-radius: 50%;\n    background: var(--icons);\n    cursor: pointer;\n}\n\n.skill-control-menu .skill-slider::-moz-range-thumb {\n    width: 12px;\n    height: 12px;\n    border-radius: 50%;\n    background: var(--icons);\n    cursor: pointer;\n    border: none;\n}\n\n.skill-control-menu .skill-label {\n    font-size: 10px;\n    text-transform: uppercase;\n    letter-spacing: 0.5px;\n    opacity: 0.8;\n    white-space: nowrap;\n    color: var(--icons);\n}\n\n/* Hide on very small screens */\n@media (max-width: 600px) {\n    .skill-control-menu {\n        display: none;\n    }\n}\n\n/* Content visibility based on skill level */\n.beginner-content,\n.advanced-content {\n    max-height: 0;\n    opacity: 0;\n    overflow: hidden;\n    transition: max-height 0.8s ease-out, opacity 0.6s ease-out, margin 0.6s ease-out;\n    margin: 0;\n}\n\n/* Beginner: show beginner extras */\nbody[data-skill=\"1\"] .beginner-content { \n    max-height: 2000px; /* Large enough for most content */\n    opacity: 1;\n    margin: 15px 0;\n}\n\n/* Standard: default, no extras */\n\n/* Advanced: show advanced extras */\nbody[data-skill=\"3\"] .advanced-content { \n    max-height: 2000px; /* Large enough for most content */\n    opacity: 1;\n    margin: 15px 0;\n}\n\n/* Inline skill content */\n.beginner-inline,\n.advanced-inline {\n    opacity: 0;\n    font-size: 0;\n    transition: opacity 0.5s ease-out, font-size 0.5s ease-out;\n}\n\nbody[data-skill=\"1\"] .beginner-inline { \n    opacity: 1;\n    font-size: inherit;\n}\nbody[data-skill=\"3\"] .advanced-inline { \n    opacity: 1;\n    font-size: inherit;\n}\n\n/* Visual indicators for skill content blocks */\n.beginner-content {\n    background: rgba(76, 175, 80, 0.1);\n    border-left: 4px solid #4caf50;\n    padding: 15px;\n    margin: 15px 0;\n    border-radius: 0 4px 4px 0;\n}\n\n\n.advanced-content {\n    background: rgba(33, 150, 243, 0.1);\n    border-left: 4px solid #2196f3;\n    padding: 15px;\n    margin: 15px 0;\n    border-radius: 0 4px 4px 0;\n}\n\n/* Skill level indicators in content */\n.beginner-content::before {\n    content: \"🌱 Beginner\";\n    display: block;\n    font-weight: bold;\n    margin-bottom: 10px;\n    color: #4caf50;\n}\n\n\n.advanced-content::before {\n    content: \"🚀 Advanced\";\n    display: block;\n    font-weight: bold;\n    margin-bottom: 10px;\n    color: #2196f3;\n}\n\n/* Enhanced side-by-side code table */\n.side-by-side-code {\n    width: 100%;\n    border-collapse: collapse;\n    margin: 25px 0;\n    background: transparent;\n    border-radius: 0;\n    overflow: visible;\n    box-shadow: none;\n}\n\n.side-by-side-code td {\n    padding: 20px;\n    vertical-align: top;\n    border-bottom: 1px solid var(--table-border-color);\n}\n\n.side-by-side-code tr:last-child td {\n    border-bottom: none;\n}\n\n.side-by-side-code td:first-child {\n    width: 35%;\n    background: var(--sidebar-bg);\n    border-right: 1px solid var(--table-border-color);\n    font-size: 0.95em;\n    line-height: 1.7;\n    color: var(--fg);\n}\n\n.side-by-side-code td:last-child {\n    width: 65%;\n    background: var(--code-bg);\n}\n\n/* Remove extra margins in code blocks inside tables */\n.side-by-side-code pre {\n    margin: 0;\n    background: transparent;\n    padding: 0;\n}\n\n.side-by-side-code code {\n    font-size: 0.9em;\n}\n\n/* On smaller screens, stack the cells */\n@media (max-width: 768px) {\n    .side-by-side-code td {\n        display: block;\n        width: 100% !important;\n    }\n    \n    .side-by-side-code td:first-child {\n        border-right: none;\n        border-bottom: 1px solid var(--table-border-color);\n    }\n    \n    .side-by-side-code tr:last-child td:first-child {\n        border-bottom: 1px solid var(--table-border-color);\n    }\n}\n\n/* Dark theme adjustments */\n\n.ayu .side-by-side-code td:first-child,\n.coal .side-by-side-code td:first-child,\n.navy .side-by-side-code td:first-child {\n    background: rgba(0, 0, 0, 0.2);\n}\n\n"
  },
  {
    "path": "docs/acton-dev-guide/theme/skill-slider.js",
    "content": "// Skill Slider JavaScript for Acton Guide\n\n(function() {\n    // Default skill level (1=beginner, 2=standard, 3=advanced)\n    const DEFAULT_SKILL = 2;\n    const STORAGE_KEY = 'acton-docs-skill-level';\n    \n    // Get saved skill level or use default\n    function getSavedSkillLevel() {\n        const saved = localStorage.getItem(STORAGE_KEY);\n        return saved ? parseInt(saved) : DEFAULT_SKILL;\n    }\n    \n    // Save skill level\n    function saveSkillLevel(level) {\n        localStorage.setItem(STORAGE_KEY, level);\n    }\n    \n    // Create skill slider widget for menu bar\n    function createSkillSlider() {\n        const widget = document.createElement('div');\n        widget.className = 'skill-control-menu';\n        widget.innerHTML = `\n            <div class=\"skill-slider-wrapper\">\n                <input type=\"range\" min=\"1\" max=\"3\" value=\"${getSavedSkillLevel()}\" class=\"skill-slider\" id=\"globalSkillSlider\" title=\"Documentation Detail Level\">\n                <span class=\"skill-label active\" data-level=\"${getSavedSkillLevel()}\"></span>\n            </div>\n        `;\n        return widget;\n    }\n    \n    // Update skill level\n    function updateSkillLevel(level) {\n        document.body.setAttribute('data-skill', level);\n        \n        // Update label text\n        const labels = ['', 'Beginner', 'Standard', 'Advanced'];\n        const activeLabel = document.querySelector('.skill-control-menu .skill-label');\n        if (activeLabel) {\n            activeLabel.textContent = labels[level];\n            activeLabel.setAttribute('data-level', level);\n        }\n        \n        // Save preference\n        saveSkillLevel(level);\n    }\n    \n    // Initialize on page load\n    function initialize() {\n        // Set initial skill level\n        const savedLevel = getSavedSkillLevel();\n        updateSkillLevel(savedLevel);\n        \n        // Check if slider already exists in menu bar\n        if (document.querySelector('.skill-control-menu')) return;\n        \n        // Find menu bar\n        const menuBar = document.querySelector('.menu-bar');\n        if (!menuBar) return;\n        \n        // Find the right section of menu bar (where theme picker is)\n        const rightButtons = menuBar.querySelector('.right-buttons');\n        if (!rightButtons) return;\n        \n        // Add skill slider widget before the theme button\n        const widget = createSkillSlider();\n        rightButtons.insertBefore(widget, rightButtons.firstChild);\n        \n        // Set up event listener\n        const slider = document.getElementById('globalSkillSlider');\n        if (slider) {\n            slider.addEventListener('input', (e) => {\n                updateSkillLevel(parseInt(e.target.value));\n            });\n        }\n        \n        // Update labels to show current state\n        updateSkillLevel(savedLevel);\n    }\n    \n    // Handle page navigation in mdBook\n    function handlePageChange() {\n        // Small delay to ensure DOM is ready\n        setTimeout(initialize, 100);\n    }\n    \n    // Initialize on first load\n    document.addEventListener('DOMContentLoaded', initialize);\n    \n    // Re-initialize on mdBook page changes\n    // mdBook uses AJAX for navigation, so we need to watch for changes\n    let lastUrl = location.href;\n    new MutationObserver(() => {\n        const url = location.href;\n        if (url !== lastUrl) {\n            lastUrl = url;\n            handlePageChange();\n        }\n    }).observe(document, {subtree: true, childList: true});\n    \n    // Also listen for popstate events\n    window.addEventListener('popstate', handlePageChange);\n})();"
  },
  {
    "path": "docs/acton-dev-guide/theme/tabs.css",
    "content": ".mdbook-tabs {\n    display: flex;\n}\n\n.mdbook-tab {\n    background-color: var(--table-alternate-bg);\n    padding: 0.5rem 1rem;\n    cursor: pointer;\n    border: none;\n    font-size: 1.6rem;\n    line-height: 1.45em;\n}\n\n.mdbook-tab.active {\n    background-color: var(--table-header-bg);\n    font-weight: bold;\n}\n\n.mdbook-tab-content {\n    padding: 1rem 0rem;\n}\n\n.mdbook-tab-content table {\n    margin: unset;\n}\n"
  },
  {
    "path": "docs/acton-dev-guide/theme/tabs.js",
    "content": "/**\n * Change active tab of tabs.\n *\n * @param {Element} container\n * @param {string} name\n */\nconst changeTab = (container, name) => {\n    for (const child of container.children) {\n        if (!(child instanceof HTMLElement)) {\n            continue;\n        }\n\n        if (child.classList.contains('mdbook-tabs')) {\n            for (const tab of child.children) {\n                if (!(tab instanceof HTMLElement)) {\n                    continue;\n                }\n\n                if (tab.dataset.tabname === name) {\n                    tab.classList.add('active');\n                } else {\n                    tab.classList.remove('active');\n                }\n            }\n        } else if (child.classList.contains('mdbook-tab-content')) {\n            if (child.dataset.tabname === name) {\n                child.classList.remove('hidden');\n            } else {\n                child.classList.add('hidden');\n            }\n        }\n    }\n};\n\ndocument.addEventListener('DOMContentLoaded', () => {\n    const tabs = document.querySelectorAll('.mdbook-tab');\n    for (const tab of tabs) {\n        tab.addEventListener('click', () => {\n            if (!(tab instanceof HTMLElement)) {\n                return;\n            }\n\n            if (!tab.parentElement || !tab.parentElement.parentElement) {\n                return;\n            }\n\n            const container = tab.parentElement.parentElement;\n            const name = tab.dataset.tabname;\n            const global = container.dataset.tabglobal;\n\n            changeTab(container, name);\n\n            if (global) {\n                localStorage.setItem(`mdbook-tabs-${global}`, name);\n\n                const globalContainers = document.querySelectorAll(\n                    `.mdbook-tabs-container[data-tabglobal=\"${global}\"]`\n                );\n                for (const globalContainer of globalContainers) {\n                    changeTab(globalContainer, name);\n                }\n            }\n        });\n    }\n\n    const containers = document.querySelectorAll('.mdbook-tabs-container[data-tabglobal]');\n    for (const container of containers) {\n        const global = container.dataset.tabglobal;\n\n        const name = localStorage.getItem(`mdbook-tabs-${global}`);\n        if (name && document.querySelector(`.mdbook-tab[data-tabname=${name}]`)) {\n            changeTab(container, name);\n        }\n    }\n});\n"
  },
  {
    "path": "docs/acton-guide/.gitignore",
    "content": "book\n"
  },
  {
    "path": "docs/acton-guide/LANGUAGE_REVIEW.md",
    "content": "# Scope\n\nReview of the current `docs/acton-guide` working tree, with focus on\n`src/language.md`, the new `src/language/*` pages, nearby `types`,\n`actors`, `protocols`, and `stdlib` splits, `src/SUMMARY.md`, and\n`theme/detail-toggles.css` where the new skill-level behavior affects how\nthe guide is read.\n\n# High-level Assessment\n\nThe rewrite is moving the guide toward a clearer, task-first structure.\nThe landing pages are more human-oriented than the old chapter stubs, and\nthe beginner/advanced layering is a real improvement in several places.\nThe main problems are in the seams: optional handling is split across two\nplaces without enough navigation context, the built-in vs standard\nlibrary boundary is still fuzzy, and the new skill-level UI is not fully\nusable on narrow screens.\n\n# Findings\n\n1. `docs/acton-guide/src/SUMMARY.md:32-35`, `docs/acton-guide/src/language/optionals_none.md`, and `docs/acton-guide/src/types/optionals.md` create a confusing split for optionals. Readers see both `Optionals and None` and `Optionals`, but only one of them is obviously the basic entry point. The two pages overlap enough that the hierarchy reads as duplication instead of a deliberate beginner-to-reference progression.\n\n2. `docs/acton-guide/src/stdlib.md:5-16` overstates what the new built-in/reference split contains. It says this section covers built-in definitions such as core types and built-in protocols, but the navigation only exposes protocols and imported modules. Core types still live under `docs/acton-guide/src/primitives.md` in the Language chapter, so the new stdlib landing page does not actually own the whole built-in surface it describes.\n\n3. `docs/acton-guide/theme/detail-toggles.css:60-65` makes the detail-level system inaccessible on mobile. The skill control is hidden below 600px, but beginner and advanced callouts are hidden by default and only revealed through that control. Because many of the rewritten language pages now put substantive explanation into those blocks, narrow-screen readers are locked to whatever skill level was last saved.\n\n4. `docs/acton-guide/src/primitives/tuples.md:7-22` introduces named-field tuple syntax without enough setup. The page jumps from positional tuple access to `point = (x=3, y=4)` and `point.x` with no explanation of whether this is a named tuple, row, or some other Acton-specific shape. That makes the built-in types chapter feel less self-contained than the rest of the new Language structure.\n\n# Remediation Plan\n\n1. Make the optionals path explicit in `SUMMARY.md` by distinguishing the beginner page from the type-system page, or collapse the overlap into one clearer sequence.\n2. Either add a built-ins landing page for core types or reword `stdlib.md` so it only claims ownership of what the nav actually exposes.\n3. Keep the skill selector reachable on narrow screens, or make the default page content sufficient without requiring the hidden control.\n4. Add a short introduction to named tuple/row syntax before using named-field tuple examples, or switch the example to plain tuple syntax until that concept is covered.\n"
  },
  {
    "path": "docs/acton-guide/README.md",
    "content": "# Acton Guide\n\n## Writers Guide\n\n``` sh\nmdbook serve\n```\n\nEach page should contain a single example and try to explain as few concepts as possible.\n"
  },
  {
    "path": "docs/acton-guide/RUST_BOOK_COMPARISON.md",
    "content": "# Rust Book Comparison\n\n## Scope\n\nThis comparison reviews the current `docs/acton-guide` working tree\nagainst the Rust book's beginner-to-reference arc, but it judges the two\nguides by topic shape and teaching progression rather than by literal\nchapter order.\n\nThe goal is to identify where the Acton guide already teaches the right\nidea, where it compresses several Rust-book ideas into one Acton-specific\nmodel, and where a learner would still need more scaffolding.\n\n## High-Level Assessment\n\nThe Acton guide is more task-oriented and runtime-model-first than the\nRust book. It does a good job covering everyday syntax, collections,\noptionals, exceptions, classes, protocols, actors, testing, and package\nworkflows. Its strongest trait is that it teaches the Acton model\ndirectly instead of forcing readers through a generic imperative primer.\n\nCompared with the Rust book, the weak point is continuity. Rust tends to\nbuild one mental model at a time and deepen it. The Acton guide often\nsplits related ideas across several pages or introduces Acton-specific\nruntime concerns before the reader has a stable data-modeling baseline.\nThe largest gaps are the lack of a dedicated simple-data-modeling path,\nthe absence of a pattern-matching chapter, the fragmented modules and\npackages story, and a thinner learner-facing treatment of\nhigher-order/iterator-style programming.\n\n## Common Programming Concepts\n\nActon covers the same baseline set as Rust's opening chapter: bindings\nand scope, built-in types, expressions, functions, comments, and control\nflow. This part of the guide is solid, and it makes a good beginner\nfoundation.\n\nThe key Acton difference is how mutability is framed. Rust introduces\n`mut` in a world of ownership and borrowing. Acton instead emphasizes\nconstant module bindings, actor-local `var`, and the fact that mutable\nstate belongs inside actors. That is the right Acton-specific move.\n\nThe main weakness is sequencing. Several examples already use\n`actor main(env)` and other runtime ideas while the reader is still\ndigesting ordinary programming concepts. The guide tells readers they do\nnot need to understand actors yet, but the examples still make actors\npart of the early mental load.\n\n## Structs and Data Modeling\n\nRust uses structs early to give beginners a named composite value and a\nplace to attach methods before moving into richer modeling. Acton does\nnot have a direct struct chapter.\n\nThe nearest pieces are tuples, named tuples, classes, and protocols.\nThat covers the feature space, but not the teaching arc. Named tuples\nappear as a convenience in the primitives section, while classes are\nintroduced later as the answer when a tuple becomes too anonymous.\n\nWhat is missing is a dedicated bridge from \"small anonymous value\" to\n\"named data shape\" to \"behavior-bearing object\". Without that bridge,\nthe guide leaves a gap between the tuple examples and the class-based\nmodeling chapter.\n\n## Enums and Pattern Matching\n\nRust's enums and `match` chapter has no direct Acton equivalent. Acton\ninstead teaches optionals and exceptions as the two main ways to model\nabsence and failure.\n\nThat is good coverage for the features Acton actually has, but it is not\na pattern-matching story. This should be treated as a language\ndifference, not as a missing Rust chapter to recreate mechanically.\n\nThe docs should be explicit that there is no Rust-style `match` arc here\nand that optionals, conditionals, and exceptions are the intended tools\nfor the nearby problems.\n\n## Packages, Crates, Modules, and Code Organization\n\nActon does cover modules, project structure, package management,\ndependency fetching, and repository dependency handling. The material is\npractical and clear about `src/`, `import`, pinned hashes, local\ndependencies, and override workflows.\n\nThe weakness is that the story is fragmented across `language`,\n`projects`, `modules`, `package_management`, and the `pkg/*` pages.\nRust book presents packages, crates, and modules as one continuous mental\nmodel. Acton's guide is more operational: it explains what to type and\nwhat the build system does, but it does not yet tie the whole sequence\ntogether from single-file program to module tree to dependency graph.\n\n## Common Collections\n\nActon covers lists, dictionaries, and sets well. The guide is strong on\nchoosing the right collection, showing the concrete APIs, and keeping\nthe type-safety story visible. Comprehensions and iteration examples are\nalso useful.\n\nThe gap is not basic coverage but conceptual bridging. The shared\nprotocol surface behind collections is mostly hidden in the reference\nmaterial, so readers see the concrete APIs before they see the shared\nmodel. Rust spends more time building a single story around collection\nAPIs; Acton would benefit from a stronger bridge from concrete\ncollection use to the underlying iterable/indexable/mapping protocols.\n\n## Error Handling\n\nActon has a clean split between absence and failure: optionals model\nordinary absence, and exceptions model real failures. That distinction\nis at least as clear as Rust's early `Option`/`Result` split.\n\nThe guide also covers narrowing, optional chaining, and forced\nunwrapping, which gives the reader several levels of sophistication. The\nweak spot is that the decision rule is spread across multiple pages, so\nthe reader sees the mechanics before the teaching story is fully\nsettled.\n\nWhat is missing is a sharper \"when do I return `?T`, when do I raise,\nand when do I force unwrap?\" rule. That choice should be front-loaded\nmore explicitly.\n\n## Generics, Traits, and Lifetimes\n\nActon has good coverage for generics and protocol constraints, and its\nbuilt-in protocol reference covers much of the same ground Rust traits\ndo. The guide also explains effects, which is a useful Acton-specific\nlayer that Rust book does not need in the same form.\n\nLifetimes are different. Rust needs a standalone lifetime story because\nownership and borrowing are core to the language. Acton does not need\nthat exact chapter, so this is not a missing feature in the same sense.\nWhat is missing is a beginner-facing explanation of the replacement\nmodel: actor ownership, explicit capability passing, and GC-backed\nobject lifetime remove the need for a borrow-checker style arc.\n\nIn other words, the guide has the pieces, but it does not yet connect\nthem into a concise \"why there is no Rust-style lifetime chapter here\"\nexplanation.\n\n## Testing\n\nActon's testing coverage is broader than the Rust book's. It goes beyond\nunit tests into actor tests, environment tests, snapshots, flaky tests,\nperformance, and stress testing. That breadth is valuable for the\nlanguage.\n\nThe tradeoff is that the core lesson is less visible. Rust introduces\ntesting as a straightforward habit. Acton should keep the unit-test path\nfront and center and treat the specialized test kinds as extensions of\nthat base model rather than as the first thing a newcomer has to sort\nthrough.\n\n## Functional Features\n\nRust's closures and iterators chapter has no direct Acton twin. Acton\ndoes have higher-order functions, comprehensions, and iteration over\ncollections, but the guide does not yet teach a coherent \"functional\nstyle\" arc.\n\nThe missing pedagogy is especially noticeable around closures, captured\nstate, and iterator pipelines. Some of that may be less central to Acton\nthan to Rust, but the current docs still leave the reader without a\nstrong conceptual bridge from \"a function is a value\" to \"here is how\nyou build reusable pipelines over data.\"\n\n## Concurrency\n\nThis is where Acton diverges most from Rust book, and that difference is\npart of the language design. Rust treats concurrency as a systems topic\nlayered on ownership and threads. Acton treats actors as the primary\nunit of mutable state and concurrency, so the guide naturally teaches\nasync calls, delayed work, cleanup, and capability boundaries as core\nlanguage ideas.\n\nThe coverage is good, but the teaching load is heavy. The reader has to\nabsorb state ownership, communication, and concurrency at the same\ntime. A little more framing around \"sequential inside an actor,\nconcurrent between actors\" would make the section easier to digest.\n\n## OOP Comparison\n\nRust uses its OOP comparison chapter to explain why objects,\nencapsulation, and inheritance are only part of the design space. Acton\nalready covers classes, initialization, inheritance, and protocols, and\nit generally steers readers away from overusing inheritance.\n\nThe gap is mostly rhetorical and structural. The guide explains the\npieces, but it does not yet stage the tradeoff as a focused comparison\nbetween class-based design, protocol-based design, and actor-based state\nownership. That would help readers coming from class-heavy languages\nunderstand why Acton's preferred abstractions differ.\n\n## Concrete Gaps\n\n- No dedicated pattern-matching story, so readers never get a Rust-style\n  `match` equivalent because the guide does not say whether one exists.\n- No single beginner path for \"small anonymous value -> named tuple ->\n  class\", even though the docs use all three ideas.\n- Modules, projects, and package dependencies are split across several\n  pages, which makes the code-organization story feel fragmented.\n- Higher-order functions are present, but closures and\n  iterator-style composition are not taught as a first-class learning\n  arc.\n- Lifetimes are not a real Acton chapter, but the docs do not yet\n  explain clearly enough why actor ownership and capabilities replace\n  the need for one.\n- Testing is broad and useful, but the basic unit-test workflow is\n  partially buried under specialized test categories.\n\n## Prioritized Remediation Plan\n\n1. Add a short data-modeling bridge that explains tuples, named tuples,\n   classes, and protocols as one progression.\n2. Add or rewrite an overview page for modules and package management\n   that links source layout, imports, and dependency resolution into one\n   mental model.\n3. Add a functional-programming overview that connects higher-order\n   functions, comprehensions, and iteration protocols, and states\n   plainly what Acton does not have compared with Rust closures and\n   iterators.\n4. Tighten the absence/failure story so the choice between optional\n   values, exceptions, and forced unwrapping is stated up front.\n5. Add a short note in the type or actor sections explaining that\n   Rust-style lifetimes are not a direct Acton concept because actor\n   ownership and capability passing solve a different problem.\n"
  },
  {
    "path": "docs/acton-guide/book.toml",
    "content": "[book]\ntitle = \"Acton Guide\"\nauthors = []\nlanguage = \"en\"\nmultilingual = false\npreferred-dark-theme = \"ayu\"\nsrc = \"src\"\nsite-url = \"/learn/acton-guide/\"\ngit-repository-url = \"https://github.com/actonlang/acton\"\ngit-repository-icon = \"fa-github\"\nedit-url-template = \"https://github.com/actonlang/acton/edit/master/docs/acton-guide/{path}\"\n\n[preprocessor.tabs]\n\n[preprocessor.svgbob]\ntext_width = 8.0\ntext_height = 16.0\nclass = \"bob\"\nfont_family = \"arial\"\nfont_size = 14\nstroke_width = 2.0\n# there's using css-variables from theme:\nstroke_color = \"var(--fg)\" # see default theme / variables.css\nbackground_color = \"transparent\" # also useful `var(--bg)`\n\n[preprocessor.admonish]\ncommand = \"mdbook-admonish\"\nassets_version = \"3.0.2\" # do not edit: managed by `mdbook-admonish install`\n\n[output.html]\nadditional-css = [\"svgbob.css\", \"theme/tabs.css\", \"./mdbook-admonish.css\", \"theme/acton-theme.css\", \"theme/sbscode.css\", \"theme/detail-toggles.css\", \"theme/guide-links.css\", \"theme/content-width.css\"]\nadditional-js = [\"theme/tabs.js\", \"theme/sbscode_copy.js\", \"theme/acton-theme.js\", \"theme/detail-toggles.js\", \"theme/guide-links.js\"]\n\n[output.html.fold]\nenable = true\n"
  },
  {
    "path": "docs/acton-guide/mdbook-admonish.css",
    "content": "@charset \"UTF-8\";\n:is(.admonition) {\n  display: flow-root;\n  margin: 1.5625em 0;\n  padding: 0 1.2rem;\n  color: var(--fg);\n  page-break-inside: avoid;\n  background-color: var(--bg);\n  border: 0 solid black;\n  border-inline-start-width: 0.4rem;\n  border-radius: 0.2rem;\n  box-shadow: 0 0.2rem 1rem rgba(0, 0, 0, 0.05), 0 0 0.1rem rgba(0, 0, 0, 0.1);\n}\n@media print {\n  :is(.admonition) {\n    box-shadow: none;\n  }\n}\n:is(.admonition) > * {\n  box-sizing: border-box;\n}\n:is(.admonition) :is(.admonition) {\n  margin-top: 1em;\n  margin-bottom: 1em;\n}\n:is(.admonition) > .tabbed-set:only-child {\n  margin-top: 0;\n}\nhtml :is(.admonition) > :last-child {\n  margin-bottom: 1.2rem;\n}\n\na.admonition-anchor-link {\n  display: none;\n  position: absolute;\n  left: -1.2rem;\n  padding-right: 1rem;\n}\na.admonition-anchor-link:link, a.admonition-anchor-link:visited {\n  color: var(--fg);\n}\na.admonition-anchor-link:link:hover, a.admonition-anchor-link:visited:hover {\n  text-decoration: none;\n}\na.admonition-anchor-link::before {\n  content: \"§\";\n}\n\n:is(.admonition-title, summary.admonition-title) {\n  position: relative;\n  min-height: 4rem;\n  margin-block: 0;\n  margin-inline: -1.6rem -1.2rem;\n  padding-block: 0.8rem;\n  padding-inline: 4.4rem 1.2rem;\n  font-weight: 700;\n  background-color: rgba(68, 138, 255, 0.1);\n  print-color-adjust: exact;\n  -webkit-print-color-adjust: exact;\n  display: flex;\n}\n:is(.admonition-title, summary.admonition-title) p {\n  margin: 0;\n}\nhtml :is(.admonition-title, summary.admonition-title):last-child {\n  margin-bottom: 0;\n}\n:is(.admonition-title, summary.admonition-title)::before {\n  position: absolute;\n  top: 0.625em;\n  inset-inline-start: 1.6rem;\n  width: 2rem;\n  height: 2rem;\n  background-color: #448aff;\n  print-color-adjust: exact;\n  -webkit-print-color-adjust: exact;\n  mask-image: url('data:image/svg+xml;charset=utf-8,<svg xmlns=\"http://www.w3.org/2000/svg\" viewBox=\"0 0 24 24\"></svg>');\n  -webkit-mask-image: url('data:image/svg+xml;charset=utf-8,<svg xmlns=\"http://www.w3.org/2000/svg\" viewBox=\"0 0 24 24\"></svg>');\n  mask-repeat: no-repeat;\n  -webkit-mask-repeat: no-repeat;\n  mask-size: contain;\n  -webkit-mask-size: contain;\n  content: \"\";\n}\n:is(.admonition-title, summary.admonition-title):hover a.admonition-anchor-link {\n  display: initial;\n}\n\ndetails.admonition > summary.admonition-title::after {\n  position: absolute;\n  top: 0.625em;\n  inset-inline-end: 1.6rem;\n  height: 2rem;\n  width: 2rem;\n  background-color: currentcolor;\n  mask-image: var(--md-details-icon);\n  -webkit-mask-image: var(--md-details-icon);\n  mask-repeat: no-repeat;\n  -webkit-mask-repeat: no-repeat;\n  mask-size: contain;\n  -webkit-mask-size: contain;\n  content: \"\";\n  transform: rotate(0deg);\n  transition: transform 0.25s;\n}\ndetails[open].admonition > summary.admonition-title::after {\n  transform: rotate(90deg);\n}\n\n:root {\n  --md-details-icon: url(\"data:image/svg+xml;charset=utf-8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'><path d='M8.59 16.58 13.17 12 8.59 7.41 10 6l6 6-6 6-1.41-1.42Z'/></svg>\");\n}\n\n:root {\n  --md-admonition-icon--admonish-note: url(\"data:image/svg+xml;charset=utf-8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'><path d='M20.71 7.04c.39-.39.39-1.04 0-1.41l-2.34-2.34c-.37-.39-1.02-.39-1.41 0l-1.84 1.83 3.75 3.75M3 17.25V21h3.75L17.81 9.93l-3.75-3.75L3 17.25z'/></svg>\");\n  --md-admonition-icon--admonish-abstract: url(\"data:image/svg+xml;charset=utf-8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'><path d='M17 9H7V7h10m0 6H7v-2h10m-3 6H7v-2h7M12 3a1 1 0 0 1 1 1 1 1 0 0 1-1 1 1 1 0 0 1-1-1 1 1 0 0 1 1-1m7 0h-4.18C14.4 1.84 13.3 1 12 1c-1.3 0-2.4.84-2.82 2H5a2 2 0 0 0-2 2v14a2 2 0 0 0 2 2h14a2 2 0 0 0 2-2V5a2 2 0 0 0-2-2z'/></svg>\");\n  --md-admonition-icon--admonish-info: url(\"data:image/svg+xml;charset=utf-8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'><path d='M13 9h-2V7h2m0 10h-2v-6h2m-1-9A10 10 0 0 0 2 12a10 10 0 0 0 10 10 10 10 0 0 0 10-10A10 10 0 0 0 12 2z'/></svg>\");\n  --md-admonition-icon--admonish-tip: url(\"data:image/svg+xml;charset=utf-8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'><path d='M17.66 11.2c-.23-.3-.51-.56-.77-.82-.67-.6-1.43-1.03-2.07-1.66C13.33 7.26 13 4.85 13.95 3c-.95.23-1.78.75-2.49 1.32-2.59 2.08-3.61 5.75-2.39 8.9.04.1.08.2.08.33 0 .22-.15.42-.35.5-.23.1-.47.04-.66-.12a.58.58 0 0 1-.14-.17c-1.13-1.43-1.31-3.48-.55-5.12C5.78 10 4.87 12.3 5 14.47c.06.5.12 1 .29 1.5.14.6.41 1.2.71 1.73 1.08 1.73 2.95 2.97 4.96 3.22 2.14.27 4.43-.12 6.07-1.6 1.83-1.66 2.47-4.32 1.53-6.6l-.13-.26c-.21-.46-.77-1.26-.77-1.26m-3.16 6.3c-.28.24-.74.5-1.1.6-1.12.4-2.24-.16-2.9-.82 1.19-.28 1.9-1.16 2.11-2.05.17-.8-.15-1.46-.28-2.23-.12-.74-.1-1.37.17-2.06.19.38.39.76.63 1.06.77 1 1.98 1.44 2.24 2.8.04.14.06.28.06.43.03.82-.33 1.72-.93 2.27z'/></svg>\");\n  --md-admonition-icon--admonish-success: url(\"data:image/svg+xml;charset=utf-8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'><path d='m9 20.42-6.21-6.21 2.83-2.83L9 14.77l9.88-9.89 2.83 2.83L9 20.42z'/></svg>\");\n  --md-admonition-icon--admonish-question: url(\"data:image/svg+xml;charset=utf-8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'><path d='m15.07 11.25-.9.92C13.45 12.89 13 13.5 13 15h-2v-.5c0-1.11.45-2.11 1.17-2.83l1.24-1.26c.37-.36.59-.86.59-1.41a2 2 0 0 0-2-2 2 2 0 0 0-2 2H8a4 4 0 0 1 4-4 4 4 0 0 1 4 4 3.2 3.2 0 0 1-.93 2.25M13 19h-2v-2h2M12 2A10 10 0 0 0 2 12a10 10 0 0 0 10 10 10 10 0 0 0 10-10c0-5.53-4.5-10-10-10z'/></svg>\");\n  --md-admonition-icon--admonish-warning: url(\"data:image/svg+xml;charset=utf-8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'><path d='M13 14h-2V9h2m0 9h-2v-2h2M1 21h22L12 2 1 21z'/></svg>\");\n  --md-admonition-icon--admonish-failure: url(\"data:image/svg+xml;charset=utf-8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'><path d='M20 6.91 17.09 4 12 9.09 6.91 4 4 6.91 9.09 12 4 17.09 6.91 20 12 14.91 17.09 20 20 17.09 14.91 12 20 6.91z'/></svg>\");\n  --md-admonition-icon--admonish-danger: url(\"data:image/svg+xml;charset=utf-8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'><path d='M11 15H6l7-14v8h5l-7 14v-8z'/></svg>\");\n  --md-admonition-icon--admonish-bug: url(\"data:image/svg+xml;charset=utf-8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'><path d='M14 12h-4v-2h4m0 6h-4v-2h4m6-6h-2.81a5.985 5.985 0 0 0-1.82-1.96L17 4.41 15.59 3l-2.17 2.17a6.002 6.002 0 0 0-2.83 0L8.41 3 7 4.41l1.62 1.63C7.88 6.55 7.26 7.22 6.81 8H4v2h2.09c-.05.33-.09.66-.09 1v1H4v2h2v1c0 .34.04.67.09 1H4v2h2.81c1.04 1.79 2.97 3 5.19 3s4.15-1.21 5.19-3H20v-2h-2.09c.05-.33.09-.66.09-1v-1h2v-2h-2v-1c0-.34-.04-.67-.09-1H20V8z'/></svg>\");\n  --md-admonition-icon--admonish-example: url(\"data:image/svg+xml;charset=utf-8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'><path d='M7 13v-2h14v2H7m0 6v-2h14v2H7M7 7V5h14v2H7M3 8V5H2V4h2v4H3m-1 9v-1h3v4H2v-1h2v-.5H3v-1h1V17H2m2.25-7a.75.75 0 0 1 .75.75c0 .2-.08.39-.21.52L3.12 13H5v1H2v-.92L4 11H2v-1h2.25z'/></svg>\");\n  --md-admonition-icon--admonish-quote: url(\"data:image/svg+xml;charset=utf-8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'><path d='M14 17h3l2-4V7h-6v6h3M6 17h3l2-4V7H5v6h3l-2 4z'/></svg>\");\n}\n\n:is(.admonition):is(.admonish-note) {\n  border-color: #448aff;\n}\n\n:is(.admonish-note) > :is(.admonition-title, summary.admonition-title) {\n  background-color: rgba(68, 138, 255, 0.1);\n}\n:is(.admonish-note) > :is(.admonition-title, summary.admonition-title)::before {\n  background-color: #448aff;\n  mask-image: var(--md-admonition-icon--admonish-note);\n  -webkit-mask-image: var(--md-admonition-icon--admonish-note);\n  mask-repeat: no-repeat;\n  -webkit-mask-repeat: no-repeat;\n  mask-size: contain;\n  -webkit-mask-repeat: no-repeat;\n}\n\n:is(.admonition):is(.admonish-abstract, .admonish-summary, .admonish-tldr) {\n  border-color: #00b0ff;\n}\n\n:is(.admonish-abstract, .admonish-summary, .admonish-tldr) > :is(.admonition-title, summary.admonition-title) {\n  background-color: rgba(0, 176, 255, 0.1);\n}\n:is(.admonish-abstract, .admonish-summary, .admonish-tldr) > :is(.admonition-title, summary.admonition-title)::before {\n  background-color: #00b0ff;\n  mask-image: var(--md-admonition-icon--admonish-abstract);\n  -webkit-mask-image: var(--md-admonition-icon--admonish-abstract);\n  mask-repeat: no-repeat;\n  -webkit-mask-repeat: no-repeat;\n  mask-size: contain;\n  -webkit-mask-repeat: no-repeat;\n}\n\n:is(.admonition):is(.admonish-info, .admonish-todo) {\n  border-color: #00b8d4;\n}\n\n:is(.admonish-info, .admonish-todo) > :is(.admonition-title, summary.admonition-title) {\n  background-color: rgba(0, 184, 212, 0.1);\n}\n:is(.admonish-info, .admonish-todo) > :is(.admonition-title, summary.admonition-title)::before {\n  background-color: #00b8d4;\n  mask-image: var(--md-admonition-icon--admonish-info);\n  -webkit-mask-image: var(--md-admonition-icon--admonish-info);\n  mask-repeat: no-repeat;\n  -webkit-mask-repeat: no-repeat;\n  mask-size: contain;\n  -webkit-mask-repeat: no-repeat;\n}\n\n:is(.admonition):is(.admonish-tip, .admonish-hint, .admonish-important) {\n  border-color: #00bfa5;\n}\n\n:is(.admonish-tip, .admonish-hint, .admonish-important) > :is(.admonition-title, summary.admonition-title) {\n  background-color: rgba(0, 191, 165, 0.1);\n}\n:is(.admonish-tip, .admonish-hint, .admonish-important) > :is(.admonition-title, summary.admonition-title)::before {\n  background-color: #00bfa5;\n  mask-image: var(--md-admonition-icon--admonish-tip);\n  -webkit-mask-image: var(--md-admonition-icon--admonish-tip);\n  mask-repeat: no-repeat;\n  -webkit-mask-repeat: no-repeat;\n  mask-size: contain;\n  -webkit-mask-repeat: no-repeat;\n}\n\n:is(.admonition):is(.admonish-success, .admonish-check, .admonish-done) {\n  border-color: #00c853;\n}\n\n:is(.admonish-success, .admonish-check, .admonish-done) > :is(.admonition-title, summary.admonition-title) {\n  background-color: rgba(0, 200, 83, 0.1);\n}\n:is(.admonish-success, .admonish-check, .admonish-done) > :is(.admonition-title, summary.admonition-title)::before {\n  background-color: #00c853;\n  mask-image: var(--md-admonition-icon--admonish-success);\n  -webkit-mask-image: var(--md-admonition-icon--admonish-success);\n  mask-repeat: no-repeat;\n  -webkit-mask-repeat: no-repeat;\n  mask-size: contain;\n  -webkit-mask-repeat: no-repeat;\n}\n\n:is(.admonition):is(.admonish-question, .admonish-help, .admonish-faq) {\n  border-color: #64dd17;\n}\n\n:is(.admonish-question, .admonish-help, .admonish-faq) > :is(.admonition-title, summary.admonition-title) {\n  background-color: rgba(100, 221, 23, 0.1);\n}\n:is(.admonish-question, .admonish-help, .admonish-faq) > :is(.admonition-title, summary.admonition-title)::before {\n  background-color: #64dd17;\n  mask-image: var(--md-admonition-icon--admonish-question);\n  -webkit-mask-image: var(--md-admonition-icon--admonish-question);\n  mask-repeat: no-repeat;\n  -webkit-mask-repeat: no-repeat;\n  mask-size: contain;\n  -webkit-mask-repeat: no-repeat;\n}\n\n:is(.admonition):is(.admonish-warning, .admonish-caution, .admonish-attention) {\n  border-color: #ff9100;\n}\n\n:is(.admonish-warning, .admonish-caution, .admonish-attention) > :is(.admonition-title, summary.admonition-title) {\n  background-color: rgba(255, 145, 0, 0.1);\n}\n:is(.admonish-warning, .admonish-caution, .admonish-attention) > :is(.admonition-title, summary.admonition-title)::before {\n  background-color: #ff9100;\n  mask-image: var(--md-admonition-icon--admonish-warning);\n  -webkit-mask-image: var(--md-admonition-icon--admonish-warning);\n  mask-repeat: no-repeat;\n  -webkit-mask-repeat: no-repeat;\n  mask-size: contain;\n  -webkit-mask-repeat: no-repeat;\n}\n\n:is(.admonition):is(.admonish-failure, .admonish-fail, .admonish-missing) {\n  border-color: #ff5252;\n}\n\n:is(.admonish-failure, .admonish-fail, .admonish-missing) > :is(.admonition-title, summary.admonition-title) {\n  background-color: rgba(255, 82, 82, 0.1);\n}\n:is(.admonish-failure, .admonish-fail, .admonish-missing) > :is(.admonition-title, summary.admonition-title)::before {\n  background-color: #ff5252;\n  mask-image: var(--md-admonition-icon--admonish-failure);\n  -webkit-mask-image: var(--md-admonition-icon--admonish-failure);\n  mask-repeat: no-repeat;\n  -webkit-mask-repeat: no-repeat;\n  mask-size: contain;\n  -webkit-mask-repeat: no-repeat;\n}\n\n:is(.admonition):is(.admonish-danger, .admonish-error) {\n  border-color: #ff1744;\n}\n\n:is(.admonish-danger, .admonish-error) > :is(.admonition-title, summary.admonition-title) {\n  background-color: rgba(255, 23, 68, 0.1);\n}\n:is(.admonish-danger, .admonish-error) > :is(.admonition-title, summary.admonition-title)::before {\n  background-color: #ff1744;\n  mask-image: var(--md-admonition-icon--admonish-danger);\n  -webkit-mask-image: var(--md-admonition-icon--admonish-danger);\n  mask-repeat: no-repeat;\n  -webkit-mask-repeat: no-repeat;\n  mask-size: contain;\n  -webkit-mask-repeat: no-repeat;\n}\n\n:is(.admonition):is(.admonish-bug) {\n  border-color: #f50057;\n}\n\n:is(.admonish-bug) > :is(.admonition-title, summary.admonition-title) {\n  background-color: rgba(245, 0, 87, 0.1);\n}\n:is(.admonish-bug) > :is(.admonition-title, summary.admonition-title)::before {\n  background-color: #f50057;\n  mask-image: var(--md-admonition-icon--admonish-bug);\n  -webkit-mask-image: var(--md-admonition-icon--admonish-bug);\n  mask-repeat: no-repeat;\n  -webkit-mask-repeat: no-repeat;\n  mask-size: contain;\n  -webkit-mask-repeat: no-repeat;\n}\n\n:is(.admonition):is(.admonish-example) {\n  border-color: #7c4dff;\n}\n\n:is(.admonish-example) > :is(.admonition-title, summary.admonition-title) {\n  background-color: rgba(124, 77, 255, 0.1);\n}\n:is(.admonish-example) > :is(.admonition-title, summary.admonition-title)::before {\n  background-color: #7c4dff;\n  mask-image: var(--md-admonition-icon--admonish-example);\n  -webkit-mask-image: var(--md-admonition-icon--admonish-example);\n  mask-repeat: no-repeat;\n  -webkit-mask-repeat: no-repeat;\n  mask-size: contain;\n  -webkit-mask-repeat: no-repeat;\n}\n\n:is(.admonition):is(.admonish-quote, .admonish-cite) {\n  border-color: #9e9e9e;\n}\n\n:is(.admonish-quote, .admonish-cite) > :is(.admonition-title, summary.admonition-title) {\n  background-color: rgba(158, 158, 158, 0.1);\n}\n:is(.admonish-quote, .admonish-cite) > :is(.admonition-title, summary.admonition-title)::before {\n  background-color: #9e9e9e;\n  mask-image: var(--md-admonition-icon--admonish-quote);\n  -webkit-mask-image: var(--md-admonition-icon--admonish-quote);\n  mask-repeat: no-repeat;\n  -webkit-mask-repeat: no-repeat;\n  mask-size: contain;\n  -webkit-mask-repeat: no-repeat;\n}\n\n.navy :is(.admonition) {\n  background-color: var(--sidebar-bg);\n}\n\n.ayu :is(.admonition),\n.coal :is(.admonition) {\n  background-color: var(--theme-hover);\n}\n\n.rust :is(.admonition) {\n  background-color: var(--sidebar-bg);\n  color: var(--sidebar-fg);\n}\n.rust .admonition-anchor-link:link, .rust .admonition-anchor-link:visited {\n  color: var(--sidebar-fg);\n}\n"
  },
  {
    "path": "docs/acton-guide/src/SUMMARY.md",
    "content": "# Summary\n\n- [Getting started](index.md)\n  - [Hello World](hello.md)\n  - [Installation](install.md)\n    - [Tip / Nightly](install_tip.md)\n  - [Acton scripts](hello/shebang.md)\n    <!-- - [Program Arguments](hello/args.md) -->\n  - [Acton Projects](projects.md)\n    <!-- - [Directory structure](projects/directory_structure.md) -->\n  - [Running Tests](hello/running_tests.md)\n- [Language](language.md)\n  - [Common programming concepts](language/common_programming_concepts.md)\n    - [Variables, constants, and scope](language/bindings_scope.md)\n    - [Built-in types and literals](primitives.md)\n      - [Integers](primitives/integers.md)\n      - [Floating-point numbers](primitives/float.md)\n      - [Complex numbers](primitives/complex.md)\n      - [Tuples](primitives/tuples.md)\n    - [Expressions and operators](language/expressions_operators.md)\n    - [Functions](functions.md)\n      - [Higher order functions](functions/higher_order.md)\n    - [Comments](language/comments.md)\n    - [Control flow](control_flow.md)\n      - [if / elif / else](control_flow/if_else.md)\n      - [for](control_flow/for.md)\n      - [while](control_flow/while.md)\n  - [Collections and everyday data](collections.md)\n    - [Lists](collections/lists.md)\n    - [Dictionaries](collections/dicts.md)\n    - [Sets](collections/sets.md)\n  - [Missing values and failures](language/missing_values_failures.md)\n    - [Optionals and `None`](language/optionals_none.md)\n    - [Optionals](types/optionals.md)\n    - [Errors and exceptions](language/errors_exceptions.md)\n  - [Modeling data and interfaces](language/modeling_data_interfaces.md)\n    - [Classes and objects](classes/intro.md)\n      - [Initialization](classes/initialization.md)\n      - [Inheritance](classes/inheritance.md)\n    - [Protocols](protocols/intro.md)\n      - [Method Dispatch](protocols/dispatch.md)\n  - [Organizing code](language/organizing_code.md)\n    - [Modules](modules.md)\n    - [Naming](naming.md)\n  - [Working with types](types/intro.md)\n    - [Explicit types](types/explicit.md)\n    - [Generics](types/generics.md)\n    - [Effects (`pure`, `mut`, `proc`, `action`)](types/effects.md)\n    - [Troubleshooting type errors](types/troubleshooting.md)\n  - [Actors & concurrency](language/state_concurrency.md)\n    - [Actors](actors.md)\n    - [Root Actor](actors/root.md)\n    - [Lifetime](actors/lifetime.md)\n    - [Attributes](actors/attributes.md)\n    - [`self` reference](actors/self.md)\n    - [Actor methods](functions/actor_methods.md)\n    - [Sync Method calls](actors/sync_method_call.md)\n    - [Async Method calls](actors/async_method_call.md)\n    - [Control flow in an async actor world](control_flow/actors.md)\n    - [after / sleep](control_flow/after_sleep.md)\n    - [Concurrency](actors/concurrency.md)\n    - [Cleanup](actors/cleanup.md)\n  - [Environment and capabilities](language/environment_capabilities.md)\n    - [Security](security.md)\n      - [Capabilities](security/capabilities.md)\n    - [Environment](environment.md)\n      - [Environment variables](environment/variables.md)\n      - [Reading stdin input](environment/stdin.md)\n      - [Interactive stdin input](environment/interactive_stdin.md)\n  \n- [Built-in & Standard Library](stdlib.md)\n  - [Built-in protocols](stdlib/builtin_protocols.md)\n    - [General protocols](stdlib/builtin_protocols/general.md)\n      - [Hashable](stdlib/builtin_protocols/hashable.md)\n    - [Numeric protocols](stdlib/builtin_protocols/numeric.md)\n    - [Collection protocols](stdlib/builtin_protocols/collection.md)\n  - [Standard Library](stdlib/standard_library.md)\n    - [math](stdlib/math.md)\n    - [re](stdlib/re.md)\n\n- [Testing](testing.md)\n  - [Unit tests](testing/unit_test.md)\n  - [Sync actor tests](testing/sync_actor_test.md)\n  - [Async actor tests](testing/async_actor_test.md)\n  - [Env tests](testing/env_test.md)\n  - [Snapshot testing](testing/snapshot.md)\n  - [Failures vs errors](testing/failures_errors.md)\n  - [Flaky tests](testing/flaky.md)\n  - [Performance testing](testing/performance.md)\n  - [Stress testing](testing/stress.md)\n  - [Perf comparison](testing/perf_record.md)\n- [Build System](compilation.md)\n  - [Incremental compilation](compilation/incremental.md)\n- [Package Management](package_management.md)\n  - [Package Index](pkg/package_index.md)\n  - [Fingerprint and Lineage](pkg/fingerprint.md)\n  - [Add Dependency](pkg/add_dependency.md)\n  - [Local Dependencies](pkg/local_dependencies.md)\n  - [Override Dependency](pkg/override_dependency.md)\n  - [Remove Dependency](pkg/remove_dependency.md)\n  - [Fetch Deps (Airplane mode)](pkg/fetch_dependencies.md)\n  - [Zig / C / C++ dependencies](zig_dependencies.md)\n- [Security and Trust](security/intro.md)\n- [Working with Zig / C / C++](working_with_zig.md)\n  - [Integrating a C library (zlib)](ext/integrating_c_library.md)\n- [Run Time System](rts.md)\n"
  },
  {
    "path": "docs/acton-guide/src/actors/async_method_call.md",
    "content": "# Async Method calls\n\nAsync calls let an actor tell another actor to do something without\nwaiting for a return value.\n\nA method call is asynchronous when the caller does not use the return\nvalue.\n\n<div class=\"beginner-content\">\n<p>An async call is closer to \"send this message\" than \"call this\nfunction and wait\".</p>\n</div>\n\n```python\nactor Worker(name):\n    def say(msg):\n        print(name, \"received:\", msg)\n\nactor main(env):\n    w1 = Worker(\"one\")\n    w2 = Worker(\"two\")\n\n    w1.say(\"hello\")\n    w2.say(\"world\")\n\n    def stop():\n        env.exit(0)\n    after 0.1: stop()\n```\n\nHere, `main` sends two messages and keeps going. It does not wait for\neither worker to return a value.\n\n## When to use async calls\n\n- use them for fire-and-forget work\n- use them when another actor should react independently\n- use them to avoid blocking the current actor on a result\n"
  },
  {
    "path": "docs/acton-guide/src/actors/attributes.md",
    "content": "# Actor Attributes & Constants\n\nActor attributes are used to store the state of an actor.\nThe important distinctions are whether an attribute is mutable state or\na constant, and whether it is private or public.\n\nAn actor can define three kinds of top-level attributes:\n\n- `var foo = ...` defines private mutable actor state\n- `_foo = ...` defines a private constant\n- `foo = ...` defines a public constant\n\n<div class=\"advanced-content\">\n<p>The important boundary is not just \"mutable or constant\", but also\n\"private or public\". <code>var</code> stays private because mutable\nactor state must not be exposed directly across actor boundaries. Plain\nconstant attributes can be read from other actors because they do not\ncreate shared mutable memory, and a leading <code>_</code> keeps such a\nconstant private to the actor.</p>\n\n<p>Actor constants are observed as constants. The top-level code in the\nactor body runs during actor creation, and a constant name may be\nassigned more than once while that final value is being established.\nOnce initialization is complete, the final binding is the constant\nvalue seen by methods and, for public constants, by other actors.</p>\n</div>\n\nFor example:\n```python\nactor Act():\n    var something = 40\n    _step = 2\n    fixed = 0\n    fixed = 1234\n    \n    def hello():\n        something += _step\n        print(\"Hello, I'm Act & value of 'something' is: \" + str(something))\n\nactor main(env):\n    actor1 = Act()\n    await async actor1.hello()\n    print(\"Externally visible constant: \", actor1.fixed)\n    # print(actor1.something)\n    # print(actor1._step)\n\n    env.exit(0)\n```\n\nHere, `something` is private mutable state, `_step` is a private\nconstant, and `fixed` is a public constant.\n\nThe repeated assignment to `fixed` happens during actor creation. The\nfinal binding, `1234`, is the constant value methods and other actors\nobserve after initialization has completed.\n\nInside the actor, all three kinds of attributes can be used directly\nfrom methods without writing `self.`.\n\nWithout `var`, an actor attribute is a constant. If the name starts\nwith `_`, that constant stays private to the actor. Without the leading\nunderscore, other actors can read the constant through an actor\nreference.\n\nIn this example, `main` can read `actor1.fixed`, but it cannot read\n`actor1.something` or `actor1._step`. The first is private mutable\nstate, and the second is a private constant.\n"
  },
  {
    "path": "docs/acton-guide/src/actors/cleanup.md",
    "content": "# Cleanup / Finalization\n\nIt is possible to run special code when an actor is about to be garbage\ncollected. This is mainly for actors that manage outside resources and\nneed a best-effort final step when they become unreachable.\n\nDefine an actor action called `__cleanup__` and the runtime will\nschedule it when garbage collection notices that the actor is no longer\nreachable. There is no hard guarantee when `__cleanup__` will run, and\nit can take more than one collection round before all finalizers are\nhandled.\n\n<div class=\"advanced-content\">\n<p>Cleanup hooks are intentionally weakly timed. They are useful for\nbest-effort resource cleanup at the boundary to the outside world, but\nthey are not a substitute for explicit shutdown protocols when a system\nneeds deterministic release or ordering.</p>\n</div>\n\nSource:\n```python\nactor Foo():\n    action def __cleanup__():\n        print(\"Cleaning up after myself...\")\n\nactor main(env):\n    for i in range(20):\n        Foo()\n\n    a = 1\n    for i in range(99999):\n        a += i\n\n    def _stop():\n        env.exit(0)\n    after 0.1: _stop()\n```\n\nOutput:\n```sh\nCleaning up after myself...\nCleaning up after myself...\nCleaning up after myself...\nCleaning up after myself...\nCleaning up after myself...\nCleaning up after myself...\nCleaning up after myself...\nCleaning up after myself...\nCleaning up after myself...\nCleaning up after myself...\nCleaning up after myself...\nCleaning up after myself...\nCleaning up after myself...\nCleaning up after myself...\nCleaning up after myself...\nCleaning up after myself...\nCleaning up after myself...\nCleaning up after myself...\nCleaning up after myself...\nCleaning up after myself...\n```\n"
  },
  {
    "path": "docs/acton-guide/src/actors/concurrency.md",
    "content": "# Actor concurrency\n\nMultiple actors can make progress concurrently. In this example, Foo\nand Bar both keep ticking while the root actor schedules shutdown.\n\n<div class=\"advanced-content\">\n<p>Concurrency here means the actors can make progress independently,\nnot that their outputs follow a fixed interleaving. The runtime may run\nthem in parallel on multiple workers, but the semantic guarantee is\nstill per-actor sequential execution rather than any global ordering\nbetween actors.</p>\n</div>\n\nSource:\n```python\nactor Counter(name):\n    var counter = 0\n\n    def periodic():\n        print(\"I am \" + name + \" and I have counted to \" + str(counter))\n        counter += 1\n\n        after 1: periodic()\n\n    periodic()\n\n\nactor main(env):\n    foo = Counter(\"Foo\")\n    bar = Counter(\"Bar\")\n\n    def exit():\n        env.exit(0)\n\n    after 10: exit()\n```\n\nCompile and run:\n```sh\nacton concurrency.act\n./concurrency\n```\n\nOutput:\n```sh\nI am Foo and I have counted to 0\nI am Bar and I have counted to 0\nI am Foo and I have counted to 1\nI am Bar and I have counted to 1\nI am Foo and I have counted to 2\nI am Bar and I have counted to 2\nI am Foo and I have counted to 3\nI am Bar and I have counted to 3\nI am Foo and I have counted to 4\nI am Bar and I have counted to 4\nI am Bar and I have counted to 5\nI am Foo and I have counted to 5\nI am Bar and I have counted to 6\nI am Foo and I have counted to 6\nI am Bar and I have counted to 7\nI am Foo and I have counted to 7\nI am Foo and I have counted to 8\nI am Bar and I have counted to 8\nI am Foo and I have counted to 9\nI am Bar and I have counted to 9\n```\n"
  },
  {
    "path": "docs/acton-guide/src/actors/lifetime.md",
    "content": "# Lifetime\n\nIn many languages, reaching the end of `main` ends the program. Acton is\ndifferent. Actors stay alive as long as another actor keeps a reference\nto them, and they sit idle until they receive more work. Actors without\nreferences can be garbage collected. The root actor stays alive until\nthe program exits.\n\nThat means a program like this will keep running even though the root\nactor body reaches its end. You must explicitly tell the runtime to stop\nthe actor world with `env.exit()`.\n\n<div class=\"advanced-content\">\n<p>Actor lifetime is reference-based. Non-root actors disappear when no\nlive actor keeps a reference to them, while the root actor persists\nuntil the program exits. This is why shutdown in Acton is explicit\nrather than an implicit fall-through from the end of <code>main</code>.</p>\n</div>\n\nSource:\n```python\nactor main(env):\n    print(\"Hello world!\")\n```\n\nCompile and run:\n```sh\nacton noexit.act\n```\n\nOutput:\n```sh\n$ ./noexit\n<you will never get your prompt back>\n```\n"
  },
  {
    "path": "docs/acton-guide/src/actors/root.md",
    "content": "# Root Actor\n\nEvery Acton program has a root actor. A binary executable must have\none, and by default Acton uses an actor named `main` when it has a\nroot-eligible signature. In ordinary programs that means a single\nenvironment parameter, usually written as `actor main(env):` or\nexplicitly as `actor main(env: Env):`. You can choose a different root\nwith `--root`.\n\nGiven this Acton program:\n```python\nactor main(env):\n    print(\"Hello World!\")\n    env.exit(0)\n```\n\nThe following acton commands will all produce the same output.\n```sh\nacton hello.act\nacton hello.act --root main\nacton hello.act --root hello.main\n```\n\nThe first invocation relies on the default rule of using an actor named\n`main`. The second explicitly selects `main` as the root actor. The\nthird uses a qualified name that includes both the module name and the\nactor name. Qualified names are useful when a project contains several\nactors that could otherwise be mistaken for the entrypoint.\n\nThe `env` parameter an actor reference to the builtin environment actor of type\n`Env`. The environment actor is constructed by the runtime system and passed to\nthe root actor when the program starts.\n\nA normal Acton program consists of many actors arranged in a tree. The\nroot actor is at the top of that tree and starts the rest of the program\ndirectly or indirectly. The Acton runtime bootstraps the root actor and\npasses it `Env`, which is the entrypoint for process arguments,\ncapabilities, standard input, environment variables, and program exit.\n\n<div class=\"advanced-content\">\n<p>The root actor is the boundary where process-level capabilities\nenter the actor world. That is why <code>main(env)</code> keeps showing\nup throughout the guide: it is both the conventional entrypoint and the\nplace where outside-world access begins.</p>\n</div>\n\n```bob\n              .────.\n             ( root )\n              `----'\n             /      \\\n            /        \\\n           V          V\n         .─.          .─.\n        ( A )        ( B )---+\n         `-'          `-'     \\\n        /  \\          |  \\     \\\n       /    \\         |   \\     \\\n      V      V        |    \\     \\\n    .─.      .─.      V     V     V\n   ( 1 )    ( 2 )    .─.    .─.    .─.\n    `─'      `─'    ( 3 )  ( 4 )  ( 5 )\n                     `─'    `─'    `─'\n```\n\nAny executable Acton program must have a root actor. Acton libraries\nthat are imported into another program do not.\n\nSee [Environment](../environment.md) for the practical guide to `Env`\nand the operations it makes available.\n"
  },
  {
    "path": "docs/acton-guide/src/actors/self.md",
    "content": "# `self`\n\n`self` is implicitly bound inside an actor. Use it when you need to pass\na reference to the current actor to another actor. Inside the actor,\n`self` is usually unnecessary.\n\n<div class=\"advanced-content\">\n<p><code>self</code> inside an actor is about identity and\ncommunication, not ordinary attribute access. Passing\n<code>self</code> hands out a callback path to the current actor, which\nmakes it central to request/reply and subscription-style protocols.</p>\n</div>\n\nSource:\n```python\nactor Pinger(ponger: Ponger):\n    def pong(message: str):\n        print(\"Pinger: Got pong:\", message)\n\n    print(\"Pinger: Sending ping to Ponger...\")\n    ponger.ping(self)\n\nactor Ponger():\n    def ping(pinger: Pinger):\n        print(\"Ponger: Got ping!\")\n        # Call back to the pinger\n        pinger.pong(\"Hello from Ponger!\")\n\n# Usage\nactor main(env):\n    ponger = Ponger()\n    pinger = Pinger(ponger)\n\n    env.exit(0)\n```\n\nOutput:\n```console\nPinger: Sending ping to Ponger...\nPonger: Got ping!\nPinger: Got pong: Hello from Ponger!\n```\n\nIn this example, `Pinger` passes `self` to `Ponger` when pinging, allowing the ponger to send a pong back.\n"
  },
  {
    "path": "docs/acton-guide/src/actors/sequential.md",
    "content": "# Actors are sequential\n\nWhile many actors can run concurrently, each actor is a sequential process and will only do one thing at a time. There are no threads nor POSIX processes in Acton, only actors. In order to scale beyond a single\n\nIn order to write Writing performant Acton programs This means an actor can only do one thing at a time and consequently, it is important not to block. All I/O in Acton is asynchronous.\n\n"
  },
  {
    "path": "docs/acton-guide/src/actors/sync_method_call.md",
    "content": "# Sync Method calls\n\nActon lets one actor call another actor synchronously when it needs a\nresult back immediately.\n\nA method call is synchronous when the caller uses the return value.\n\n<div class=\"beginner-content\">\n<p>A synchronous actor call feels like an ordinary function call: ask\nfor a result, wait, then continue.</p>\n</div>\n\n```python\nactor Calculator():\n    def square(n):\n        return n * n\n\nactor main(env):\n    calc = Calculator()\n\n    answer = calc.square(7)\n    print(\"The answer is\", answer)\n\n    env.exit(0)\n```\n\nHere, `main` waits for `calc.square(7)` to finish and then continues\nwith the returned value.\n\n<div class=\"advanced-content\">\n<p>Sync calls suspend the current actor until the other actor replies.\nAs systems grow, it is usually better to keep sync chains short and\npush longer work into asynchronous flows.</p>\n</div>\n\n## When to use sync calls\n\n- use them when a result is needed right away\n- prefer them for small, direct requests\n- be careful with long chains of sync actor-to-actor calls\n"
  },
  {
    "path": "docs/acton-guide/src/actors.md",
    "content": "# Actors\n\nActors are Acton's primary unit for state and concurrency.\n\nIf you are looking for the Acton answer to Rust-style lifetime\nconcerns, this is it: actors own mutable state, capabilities are passed\nexplicitly, and the runtime handles ordinary object lifetime.\n\n<div class=\"beginner-content\">\n<p>If classes feel like objects that own data, actors are a useful way\nto think about objects that own state and participate in concurrent\nwork. The actor body runs once when the actor starts; its methods run\nlater in response to calls.</p>\n</div>\n\nAn actor combines:\n\n- private state owned by one actor\n- sequential execution inside that actor\n- method-based communication with other actors\n- a place to put mutable program state\n\n```python\nactor Greeter(name):\n    print(\"starting\", name)\n\n    def hello():\n        print(\"hello from\", name)\n\nactor main(env):\n    greeter = Greeter(\"Acton\")\n    await async greeter.hello()\n\n    env.exit(0)\n```\n\nCode in the actor body runs once when the actor is created. That body is\nwhere initialization happens, and it may define methods that operate on\nthe actor's private state.\n\n<div class=\"advanced-content\">\n<p>Actors are also where several Acton-specific language pieces meet:\n<code>var</code>, <code>await</code>, <code>async</code>,\n<code>after</code>, capability passing, and effectful APIs. The main\nguarantee is actor-local sequentiality: state changes happen one\nhandled message at a time inside that actor.</p>\n</div>\n\n## What to read next\n\n- [Root Actor](actors/root.md) for the entrypoint pattern\n- [Lifetime](actors/lifetime.md) for how actors stay alive\n- [Attributes](actors/attributes.md) and [`self`](actors/self.md) for\n  actor state\n- [Actor methods](functions/actor_methods.md), [Sync Method\n  calls](actors/sync_method_call.md), and [Async Method\n  calls](actors/async_method_call.md) for communication\n- [Concurrency](actors/concurrency.md), [Control flow in an async actor\n  world](control_flow/actors.md), and [after / sleep](control_flow/after_sleep.md)\n  for concurrent behavior\n- [Cleanup](actors/cleanup.md) for best-effort finalization\n"
  },
  {
    "path": "docs/acton-guide/src/classes/inheritance.md",
    "content": "# Class inheritance\n\nInheritance lets one class specialize another.\n\nUse it when there is a real \"is a\" relationship between the two types.\nThe derived class inherits behavior from the base class and can add or\noverride methods of its own.\n\n<div class=\"advanced-content\">\n<p>Use inheritance sparingly. It couples representation, lifecycle, and\nmethod lookup, so a base class becomes part of the derived type's public\ncontract. When the shared need is only behavior, a protocol is often a\nbetter fit. When the shared need is only state reuse, composition is\noften clearer.</p>\n</div>\n\n```python\nclass Shape(object):\n    def area(self) -> float:\n        raise NotImplementedError(\"subclasses must implement area()\")\n\n\nclass Circle(Shape):\n    def __init__(self, radius):\n        self.radius = radius\n\n    def area(self):\n        return 3.14 * self.radius ** 2\n\n\nclass Square(Shape):\n    def __init__(self, side):\n        self.side = side\n\n    def area(self):\n        return self.side ** 2\n\n\nactor main(env):\n    circle = Circle(3.14)\n    square = Square(3.14)\n    print(circle.area() + square.area())\n    env.exit(0)\n```\n\nIn this example:\n\n- `Shape` defines a common interface\n- `Circle` and `Square` inherit from `Shape`\n- each subclass provides its own `area()` implementation\n- code written against `Shape` can still call `area()` on either value\n\n<div class=\"beginner-content\">\n<p>Read <code>class Circle(Shape):</code> as \"Circle is a kind of\nShape\". If that sentence feels wrong, inheritance is usually the wrong\ntool.</p>\n</div>\n"
  },
  {
    "path": "docs/acton-guide/src/classes/initialization.md",
    "content": "# Class initialization\n\nUse `__init__` to leave the object valid. Before `self` escapes, every\nrequired attribute must already be set.\n\nRead the rule as two steps:\n\n1. Build the object locally.\n2. Let `self` out only after construction is complete.\n\n<div class=\"beginner-content\">\n<p>Think of <code>__init__</code> as the boundary between \"not ready\"\nand \"ready\". If another function needs the object, wait until every\nrequired field is assigned.</p>\n</div>\n\n`self` escapes when you:\n\n- pass `self` to another function\n- call a method on `self`\n- capture a bound method such as `self.on_event`\n- return `self`\n- store `self` somewhere that outlives the constructor\n\n<div class=\"advanced-content\">\n<p>The important invariant is not \"all assignments happen early\" but\n\"<code>self</code> must not escape before the object is fully\ninitialized\". Once you read the rules that way, the branch, loop,\ncallback, and base-class cases all follow the same rule.</p>\n</div>\n\n## Build the object first\n\nDuring construction, use local variables for intermediate values and\nassign to attributes once the values are ready. If you read from an\nattribute before assigning it, the initialization order is wrong.\n\n```python\nclass Config(object):\n    def __init__(self, base_value: int):\n        self.base = base_value\n        self.doubled = self.base * 2\n        self.quadrupled = self.doubled * 2\n```\n\n## Let `self` out last\n\nOnce the object is complete, you can call helper methods or register the\ninstance with the rest of the system.\n\n```python\nclass BankAccount(object):\n    def __init__(self, owner: str, initial_deposit: float):\n        self.owner = owner\n        self.balance = initial_deposit\n        self.transaction_log = []\n\n        self.log_transaction(\"Account opened\")\n        register_account(self)\n        if initial_deposit > 10000:\n            flag_for_review(self)\n```\n\n## Control flow\n\nBranches and loops are fine as long as every normal path leaves the\nobject complete.\n\n### Branches\n\nConditional branches work when every branch that completes normally\ninitializes the same required attributes. Branches that `raise`\nexceptions do not need to finish construction.\n\n```python\nclass Rational(object):\n    num: int\n    denom: int\n\n    def __init__(self, num: int, denom: int):\n        if denom == 0:\n            raise ValueError(\"Denominator cannot be zero\")\n        if denom > 0:\n            self.num = num\n            self.denom = denom\n        else:\n            self.num = -num\n            self.denom = -denom\n```\n\n### Try/except\n\n`try`/`except` works the same way. The `else` branch is part of the\nnormal path, so it must also leave the object initialized.\n\n### Loops\n\nLoops are fine as long as they do not leak `self` before the object is\nready.\n\n```python\nclass Example(object):\n    def __init__(self, data: list[int]):\n        total = 0\n        for item in data:\n            total += item\n\n        self.values = data\n        self.computed = total\n\n        for item in data:\n            self.process(item)\n```\n\n## Common mistake\n\nPassing a method reference like `self.method` also makes `self` escape,\neven if the method is not called immediately.\n\n```python\nclass Handler(object):\n    callback: Callback\n    data: int\n\n    def __init__(self):\n        self.callback = Callback(self.on_event)\n        self.data = 42\n\n    def on_event(self):\n        pass\n```\n\n## Parent classes\n\nIf a base class owns state, initialize that state before exposing the\nderived object. Call the parent `__init__` as part of your own\nconstruction.\n\n```python\nclass Account(object):\n    account_id: str\n    created_date: str\n\n    def __init__(self, account_id: str):\n        self.account_id = account_id\n        self.created_date = current_date()\n\nclass BankAccount(Account):\n    owner: str\n    balance: float\n\n    def __init__(self, account_id: str, owner: str, initial_deposit: float):\n        Account.__init__(self, account_id)\n        self.owner = owner\n        self.balance = initial_deposit\n```\n"
  },
  {
    "path": "docs/acton-guide/src/classes/intro.md",
    "content": "# Classes and objects\n\nClasses let you name a concept, keep its data together, and attach the\nbehavior that belongs with that data. If a tuple or named tuple starts\nto feel too anonymous, a class is usually the next step.\n\nUse a class when a value should have:\n\n- a clear name instead of a bundle of positions\n- related pieces of data that travel together\n- methods that operate on that data\n- construction rules or invariants that matter to callers\n\n```python\nclass Circle(object):\n    def __init__(self, radius):\n        self.radius = radius\n\n    def diameter(self):\n        return self.radius * 2\n\nactor main(env):\n    circle = Circle(3.14)\n    print(circle.diameter())\n    env.exit(0)\n```\n\n## What a class gives you\n\nIn the example above:\n\n- `radius` is an attribute stored on each `Circle`\n- `diameter()` is a method that uses that attribute\n- `self` refers to the object the method is running on\n\n<div class=\"beginner-content\">\n<p>If a tuple starts to feel anonymous or unclear, that is usually a\nsign that the value wants to become a class. Inside methods,\n<code>self</code> is the current object, so <code>self.name</code> means\n\"this object's name\".</p>\n</div>\n\nAttributes are often introduced by assignments in `__init__`, but you\ncan also declare them explicitly in the class body when the shape should\nbe obvious up front.\n\n```python\nclass Person(object):\n    name: str\n\n    def __init__(self, name, age):\n        self.name = name\n        self.age = age\n```\n"
  },
  {
    "path": "docs/acton-guide/src/collections/dicts.md",
    "content": "# Dictionaries\n\nDictionaries map keys to values. They keep insertion order, so when you\niterate over a dictionary you get keys back in the order they were first\nadded.\n\n<div class=\"beginner-content\">\n<p>Use a dictionary when you want to look something up by name, id, or\nsome other key. If you keep searching through a list for a matching\nvalue, a dictionary is often the better shape.</p>\n</div>\n\n## Creating dictionaries\n\n```python\ncounts = {\"apples\": 2, \"bananas\": 4}\nempty_counts: dict[str, int] = {}\n```\n\nThe key type and value type are fixed for a given dictionary. When a\ndictionary is empty, give it a type if the surrounding code does not\nmake that obvious.\n\n## Looking up values\n\n```python\ncounts = {\"apples\": 2, \"bananas\": 4}\n\nprint(counts[\"apples\"])\nprint(counts.get(\"pears\"))\nprint(counts.get_def(\"pears\", 0))\nprint(\"apples\" in counts)\nprint(len(counts))\n```\n\nDirect indexing says the key must already exist. `get()` returns `None`\nwhen a key is missing. `get_def()` lets you provide a default value\ninstead of handling `None` later.\n\n<div class=\"advanced-content\">\n<p>`None` is a real value, so `get()` is best when missing keys are\nnormal and uninteresting. If `None` means something in your data,\n`get_def()` or an explicit membership test is clearer.</p>\n</div>\n\n## Updating entries\n\n```python\ncounts = {\"apples\": 2, \"bananas\": 4}\n\ncounts[\"bananas\"] = 5\ncounts[\"pears\"] = 1\ndel counts[\"apples\"]\n\nprint(counts)\n```\n\nAssigning to a key adds it if it is new or replaces the old value if it\nalready exists.\n\n## Removing entries\n\n```python\ncounts = {\"apples\": 2, \"bananas\": 4, \"pears\": 1}\n\nprint(counts.pop(\"bananas\"))\nprint(counts.pop_def(\"missing\", 0))\nprint(counts.popitem())\n```\n\n`pop()` removes a key and returns its value. `pop_def()` does the same\nthing with a fallback when the key is absent. `popitem()` removes and\nreturns one key/value pair.\n\n## Iterating over dictionaries\n\n```python\ncounts = {\"apples\": 2, \"bananas\": 4, \"pears\": 1}\n\nfor key in counts:\n    print(key)\n\nfor key, value in counts.items():\n    print(key, value)\n\nprint(list(counts.keys()))\nprint(list(counts.values()))\nprint(list(counts.items()))\n```\n\nIterating over a dictionary yields keys. Use `items()` when you need\nboth the key and the value.\n\n## Updating from other data\n\n```python\ncounts = {\"apples\": 2}\nmore_counts = {\"bananas\": 4, \"pears\": 1}\n\ncounts.update(more_counts.items())\ncounts.setdefault(\"apples\", 0)\ncounts.setdefault(\"grapes\", 3)\n```\n\n`update()` merges entries from another iterable of key/value pairs.\n`setdefault()` is useful when you want to add a missing key only once\nand keep the existing value otherwise.\n\n## Dictionary comprehensions\n\n```python\nwords = [\"hello\", \"world\", \"acton\"]\nlengths = {word: len(word) for word in words}\nfiltered = {word: len(word) for word in words if len(word) > 4}\nindexed = {i: word for (i, word) in enumerate(words)}\n```\n\nDictionary comprehensions are the concise way to build a dictionary\nfrom an iterable. They are useful when the new keys and values come\nfrom the old data directly.\n"
  },
  {
    "path": "docs/acton-guide/src/collections/lists.md",
    "content": "# Lists\n\nLists are ordered, mutable sequences. Use them when position matters or\nwhen you want to keep adding and removing items over time.\n\n<div class=\"beginner-content\">\n<p>Think of a list as a numbered row of slots. Slot <code>0</code> is\nthe first item, slot <code>1</code> is the second, and so on. A list\nholds one element type, so a <code>list[str]</code> is for strings\nonly.</p>\n</div>\n\n## Creating lists\n\n```python\nfruits = [\"apple\", \"banana\", \"orange\"]\ntasks: list[str] = []\nnumbers: list[int] = [1, 2, 3]\n```\n\nUse a literal when you already have values. Use an empty list when you\nplan to fill it later. If the compiler cannot infer the element type\nfrom context, add an annotation.\n\n<div class=\"advanced-content\">\n<p>Lists are dynamic arrays. Appending is cheap most of the time because\nstorage grows in chunks, not one item at a time.</p>\n</div>\n\n## Reading values\n\n```python\nitems = [\"first\", \"second\", \"third\", \"fourth\"]\n\nprint(items[0])\nprint(items[-1])\nprint(items[1:3])\nprint(len(items))\nprint(\"second\" in items)\nprint(items.index(\"third\"))\n```\n\nIndexing starts at `0`. Negative indexes count from the end. Slices use\nthe familiar `start:stop` form and include the start but exclude the\nstop.\n\n<div class=\"beginner-content\">\n<p>If you are coming from a one-based indexing language, the first item\nis still at position <code>0</code> here.</p>\n</div>\n\n## Updating lists\n\n```python\nitems = [\"first\", \"second\", \"third\"]\n\nitems.append(\"fourth\")\nitems.insert(1, \"new\")\nitems.extend([\"fifth\", \"sixth\"])\n\nprint(items)\nprint(items.pop())\nprint(items.pop(0))\ndel items[1]\n```\n\n`append()` adds one item to the end. `insert()` places an item at a\nspecific index. `extend()` adds several items from another iterable.\n`pop()` removes and returns an item, and `del items[i]` removes by\nindex without returning anything.\n\n<div class=\"advanced-content\">\n<p>Appends are amortized O(1). Inserting or deleting near the front of a\nlong list is O(n) because elements need to shift. `pop()` is O(1) at the\nend and O(n) at other positions.</p>\n</div>\n\n## Common utilities\n\n```python\nvalues = [9, 5, 123, 14, 1, 5]\n\nprint(sorted(values))\nvalues.reverse()\nprint(values)\nprint(values.count(5))\n\ncopy_of_values = values.copy()\nvalues.clear()\nprint(copy_of_values)\nprint(values)\n```\n\n`sorted()` returns a new list. `reverse()` changes the existing list in\nplace. `count()` scans the whole list and counts matches. `copy()` makes\na shallow copy, which is enough when the elements themselves are simple\nvalues.\n\n<div class=\"advanced-content\">\n<p>If the list contains mutable values, a shallow copy only duplicates\nthe outer list. The items inside are still shared.</p>\n</div>\n\n## Iterating over lists\n\n```python\nnames = [\"Ada\", \"Bjarne\", \"Grace\"]\n\nfor name in names:\n    print(name)\n\nfor i, name in enumerate(names):\n    print(i, name)\n```\n\nIteration gives you each item in order. Use `enumerate()` when you also\nneed the current index.\n\n## List comprehensions\n\n```python\nnumbers = [1, 2, 3, 4, 5]\nsquares = [n * n for n in numbers]\nevens = [n for n in numbers if n % 2 == 0]\n```\n\nList comprehensions are the compact way to build a new list from an\nexisting iterable. Read them as \"make a list of this expression for\neach item that matches the condition\".\n\n## Type safety\n\nAll items in a list must be of the same type. Mixing types like\n`[\"foo\", 1, True]` will not compile.\n\n```python\nstrings = [\"foo\", \"bar\", \"baz\"]\nnumbers = [1, 2, 3, 4, 5]\n```\n\nWhen a list is empty, give it a type if the surrounding code does not\nmake the element type obvious.\n"
  },
  {
    "path": "docs/acton-guide/src/collections/sets.md",
    "content": "# Sets\n\nSets store unique values. Use them when you care about membership or\ndeduplication more than order.\n\n<div class=\"beginner-content\">\n<p>A set is like a bag of distinct items. Adding the same value twice\ndoes not create a duplicate. If you only need to know whether something\nis present, a set usually fits better than a list.</p>\n</div>\n\n## Creating sets\n\n```python\ntags = {\"docs\", \"guide\", \"acton\"}\nempty_tags: set[str] = set()\n```\n\nUse `{...}` for a non-empty set. Use `set()` for an empty one, because\n`{}` means an empty dictionary.\n\n## Checking and updating\n\n```python\ntags = {\"docs\", \"guide\"}\n\nprint(\"docs\" in tags)\nprint(\"api\" not in tags)\n\ntags.add(\"api\")\ntags.add(\"docs\")\ntags.discard(\"guide\")\ntags.update({\"reference\", \"tutorial\"})\n\nprint(tags)\nprint(len(tags))\n```\n\n`add()` inserts one value. `discard()` removes a value if it is present\nand does nothing if it is not. `update()` adds values from another set\nor any iterable of values.\n\n## Removing values\n\n```python\ntags = {\"docs\", \"guide\", \"acton\"}\n\nprint(tags.pop())\nprint(tags)\n```\n\n`pop()` removes and returns one element. On an empty set it raises an\nexception, so check before calling it if the set may be empty.\n\n## Iteration and order\n\n```python\ntags = {\"docs\", \"guide\", \"acton\"}\n\nfor tag in tags:\n    print(tag)\n\nprint(sorted(tags))\n```\n\nSets do not preserve order. Do not rely on the printed order when the\nexact sequence matters. If you need stable display order, sort the set\nfirst.\n\n## Set comprehensions\n\n```python\nwords = [\"hello\", \"world\", \"hello\", \"acton\"]\nunique_words = {word for word in words}\nlong_words = {word.upper() for word in words if len(word) > 4}\nremainder_classes = {n % 3 for n in range(10)}\n```\n\nSet comprehensions are a compact way to build a set while automatically\nremoving duplicates.\n"
  },
  {
    "path": "docs/acton-guide/src/collections.md",
    "content": "# Collections and everyday data\n\nActon has three built-in collection types for everyday data:\n\n- [Lists](collections/lists.md) keep values in order and allow\n  duplicates.\n- [Dictionaries](collections/dicts.md) map keys to values.\n- [Sets](collections/sets.md) keep unique values and make membership\n  checks direct.\n\n<div class=\"beginner-content\">\n<p>If you are unsure where to start, choose by the question you want to\nanswer. Use a list when order matters, a dictionary when you need to\nlook things up by key, and a set when you mainly care about uniqueness\nor membership.</p>\n</div>\n\nUse this section when you need to keep many values together and work\nwith them as one logical value.\n\nCollections pair naturally with [higher order\nfunctions](functions/higher_order.md) and comprehensions. That is the\ncommon Acton path for turning one collection into another without\nspreading the transformation across several places.\n\nAll collection types are statically typed. A list has one element type,\na set has one element type, and a dictionary has one key type and one\nvalue type.\n"
  },
  {
    "path": "docs/acton-guide/src/compilation/incremental.md",
    "content": "# Content hash driven incremental compilation\n\nActon tracks changes at a finer level than whole modules so builds stay fast as your project grows. The compiler keeps multiple different hashes and uses them to decide what and how to recompile.\n\n## What gets hashed and tracked\n\n- **moduleSrcBytesHash**: hash of the raw bytes for a whole `.act` file. It is very cheap to read and hash a `.act` file from disk (GB/s). This is stored in the `.ty` file and is the authority for deciding whether a cached typed module still matches the source. Parsing is not incremental, it only supports re-parsing a complete module, which is also why a single hash for the entire `.act` module file makes sense.\n- **per-name srcHash**: hash of a name's source code. Since this is only the hash of the source code, it can be computed after the parser and before type checking in order to determine what functions we need to rerun through later passes, including type checking which is typically a relatively expensive pass. Note how the next pubHash and implHash are after type checking, so they cannot be used in order to determine if type-checking should be rerun for a function.\n- **per-name pubHash**: hash of a name's public interface (its type signature). Downstream modules only need to re-typecheck if a pubHash they depend on changes. The pubHash also contains the hashes of dependencies, and if those change, our pubHash will change, thus causing re-typecheck.\n- **per-name implHash**: hash of a name's implementation plus the impl hashes it depends on. If an implHash changes, we re-run back passes and tests.\n- **per-name pubDeps**: the public (type signature) hashes of other names that we depend on. If the hashes of any deps change, we must re-typecheck.\n- **per-name implsDeps**: the hashes of the implementation of other names that we depend on. If the hashes of any deps change, we must rerun back passes.\n\nMost names have both a pubHash and implHash. Some derived internal names only have implHash.\n\n## How `.ty` cache validity is decided\n\nEach module gets a cached typed interface file in `out/types/<module>.ty`.\nThat cache stores:\n\n- the module source content hash (`moduleSrcBytesHash`)\n- fast-path source metadata such as modification time, change time, and file size\n- file identity metadata where available, such as inode/device on POSIX\n- the compiler/cache schema version\n\nThe important rule is:\n\n- **content hash is the correctness authority**\n- **filesystem metadata is only a fast path**\n\nIn practice, Acton decides reuse like this:\n\n1. If the `.ty` file is missing, unreadable, or from an incompatible cache\n   schema version, Acton reparses the `.act` file and rebuilds the `.ty`.\n2. If the cached source metadata still matches the current source file and the\n   source mtime is strictly older than the `.ty` mtime, Acton reuses the `.ty`\n   header immediately without reading and hashing the source.\n3. If the metadata differs, or the source and `.ty` mtimes are equal, Acton\n   reads the `.act` file and compares its content hash to the stored\n   `moduleSrcBytesHash`.\n4. If the hash matches, the source content is unchanged, so Acton reuses the\n   cached `.ty` and refreshes the stored source metadata.\n5. If the hash differs, the source really changed, so Acton reparses and\n   recompiles that module.\n\nThis means harmless metadata drift, like a `touch`, checkout, restore, copy,\nor cross-machine sync, does not by itself force a front-end rebuild. It also\nmeans misleading timestamps cannot cause stale typed-module reuse, because\nActon falls back to the source content hash before trusting the cache.\n\nThe strict `source mtime < .ty mtime` check matters on filesystems with coarse\nmtime resolution. If a source edit and `.ty` write land in the same timestamp\ntick, equal mtimes are ambiguous: the source may already have changed even\nthough the cached source metadata still looks identical. Acton therefore treats\nequal source and `.ty` mtimes as a signal to hash the current source instead of\ntaking the metadata-only fast path.\n\n## What changes cause what work\n\n**Change function body, same signature**\n\n```\n# a.act\ndef apa() -> int:\n    return 1\n\ndef a() -> int:\n    return apa()\n```\n\n```\n# c.act\nimport a\nimport testing\n\ndef _test_foo() -> None:\n    testing.assertEqual(a.a(), 1)\n```\n\nIf you change `apa()` to return `2`, only the impl hashes change since the return type and overall type signature remains the same. `c` does not re-typecheck, but back passes and tests are re-run.\n\nExample `acton build --verbose` output (trimmed):\n\n```\nStale a: source changed\nStale c: impl changes in a.a (used by _test_foo)\n```\n\n**Change a signature**\n\nIf `a.a()` changes its return type, its pubHash changes. Any module that uses `a.a()` will re-run front passes.\n\n```\nStale c: pub changes in a.a (used by _test_foo)\n```\n\n**Add or remove an unused import**\n\nIf no name actually uses the import, per-name deps do not change, so nothing propagates. Changes are only computed and propagated for names that are actually in use, which also means that it is possible to create quite large and monolithic modules without paying a higher cost for longer compilation times of downstream dependents.\n\n## Code generation staleness\n\nGenerated C/H files embed the module impl hash. If the embedded hash differs from the current module impl hash, the compiler treats the generated code as out of date and regenerates it.\n\n## Tests and hashes\n\nTest results are cached by the per-name implHash (plus impl deps). Cached failures are still shown by default. Use `--show-cached` to include cached successes, or `--no-cache` to force reruns.\n\nFor more on tests, see the [Testing](testing.md) section.\n"
  },
  {
    "path": "docs/acton-guide/src/compilation.md",
    "content": "# Compilation\n\nActon is a compiled language and as such, outputs binary executables.\n\nWhile compiled languages are often associated with long compilation times that slow down development, Acton goes to great lengths to offer a great developer experience. Content hashing is used extensively to carefully invalidate and recompile only necessary parts, see [incremental compilation](compilation/incremental.md) for more details.\n\nIt is possible to influence the compilation process and the output in various ways.\n\n## Optimization modes\n\nActon defaults to `Debug` builds. Debug builds compile fast and include\ndebug symbols, which makes them the right default during development.\n\nFor release builds, use `acton build --release` to better optimize the\nfinal executable. For standalone files, use `acton --release foo.act`.\n\n`--release` and `--release=fast` select the fastest release mode.\n`--release=safe` enables release optimizations with safety checks.\n`--release=small` optimizes for a smaller binary size.\n\n## Optimized for native CPU features\n\nThe default target is somewhat conservative to ensure a reasonable amount of compatibility. On Linux, the default target is GNU Libc version 2.27 which makes it possible to run Acton programs on Ubuntu 18.04 and similar old operating systems. Similarly, a generic x86_64 CPU is assumed which means that newer extra CPU instruction sets are not used.\n\nTo compile an executable optimized for the local computer, use `--target native`. In many cases it can lead to a significant faster program, often running 30% to 100% faster.\n\n## Statically linked executables using musl for portability\n\nOn Linux, executable programs can be statically linked using the Musl C library, which maximizes portability as there are no runtime dependencies at all.\n\nTo compile an executable optimized for portability using musl on x86_64, use `--target x86_64-linux-musl`.\n\nA default compiled program is dynamically linked with GNU libc & friends\n```\n$ acton helloworld.act\nBuilding file helloworld.act\n  Compiling helloworld.act for release\n   Finished compilation in   0.013 s\n  Final compilation step\n   Finished final compilation step in   0.224 s\n$ ldd helloworld\n        linux-vdso.so.1 (0x00007fff2975b000)\n        libm.so.6 => /lib/x86_64-linux-gnu/libm.so.6 (0x00007f11f472a000)\n        libpthread.so.0 => /lib/x86_64-linux-gnu/libpthread.so.0 (0x00007f11f4725000)\n        libc.so.6 => /lib/x86_64-linux-gnu/libc.so.6 (0x00007f11f4544000)\n        libdl.so.2 => /lib/x86_64-linux-gnu/libdl.so.2 (0x00007f11f453f000)\n        /lib64/ld-linux-x86-64.so.2 (0x00007f11f4827000)\n$\n```\n\nA program linked statically towards Musl has no run time dependencies:\n\n```\n$ acton helloworld.act --target x86_64-linux-musl\nBuilding file helloworld.act\n  Compiling helloworld.act for release\n   Finished compilation in   0.013 s\n  Final compilation step\n   Finished final compilation step in   0.224 s\n$ ldd helloworld\n        not a dynamic executable\n$\n```\n\nAlthough untested, static linking with musl should work on other CPU architectures.\n\nMacOS does not support static compilation.\n\n## Cross-compilation\n\nActon supports cross-compilation, which means that it is possible to run develop on one computer, say a Linux computer with an x86-64 CPU but build an executable binary that can run on a MacOS computer.\n\nHere's such an example. We can see how per default, the output is an ELF binary for x86-64. By setting the `--target` argument, `acton` will instead produce an executable for a Mac.\n```\n$ acton --quiet helloworld.act\n$ file helloworld\nhelloworld: ELF 64-bit LSB executable, x86-64, version 1 (SYSV), dynamically linked, interpreter /lib64/ld-linux-x86-64.so.2, for GNU/Linux 2.0.0, with debug_info, not stripped\n$ acton --quiet helloworld.act --target x86_64-macos-none\n$ file helloworld\nhelloworld: Mach-O 64-bit x86_64 executable, flags:<NOUNDEFS|DYLDLINK|TWOLEVEL|PIE>\n```\n\nIt is not only possible to compile for other operating systems, but also for other CPU architectures. For example, use `--target aarch64-macos-any` to produce a binary executable for an Apple M1/M2 CPU.\n\n## Prebuilt libraries\n\nActon ships with prebuilt libraries for the local platforms default target, i.e. if you install Acton on a x86-64 Linux machine, it will have libraries prebuilt for x86_64-linux-gnu.2.27. The default target uses these prebuilt libraries which results in a fast build:\n```\n$ acton helloworld.act\nBuilding file helloworld.act\n  Compiling helloworld.act for release\n   Finished compilation in   0.013 s\n  Final compilation step\n   Finished final compilation step in   0.224 s\n$\n```\n\nWhen targeting something that is not the default target, the entire Acton system, including builtins, the run time system, the standard library and external library dependencies is built from source and can take a significant amount of time. The build process is highly parallelized and cached. For example, on an AMD 5950X with 16 cores / 32 threads, it takes around 7 seconds to do a complete rebuild for a small Acton program as can be seen here:\n```\n$ acton helloworld.act --target aarch64-macos-none\nBuilding file helloworld.act\n  Compiling helloworld.act for release\n   Finished compilation in   0.012 s\n  Final compilation step\n   Finished final compilation step in   6.847 s\n$\n```\n\n## Build cache\n\nIn an Acton project, there is a build cache, is is stored in a directory called `build-cache` in the project directory. The cache is always used for the project local files. If a non-default `--target` is being used, the built output of the Acton system is also stored in the cache, which means that it is only the first time around that it is slow. Any subsequent build is going to use the cache and run very fast. Like in this example, where the first invocation takes 6.120 seconds and the second one runs in 0.068 seconds.\n\n```\n$ acton new hello\nCreated project hello\nEnter your new project directory with:\n  cd hello\nCompile:\n  acton build\nRun:\n  ./out/bin/hello\n\nInitialized empty Git repository in /home/kll/hello/.git/\n$ cd hello/\n$ acton build --target native\nBuilding project in /home/kll/hello\n  Compiling hello.act for release\n   Finished compilation in   0.012 s\n  Final compilation step\n   Finished final compilation step in   6.120 s\n$ acton build --target native\nBuilding project in /home/kll/hello\n  Compiling hello.act for release\n   Already up to date, in    0.000 s\n  Final compilation step\n   Finished final compilation step in   0.068 s\n$\n```\n\nWhen compiling standalone .act files, there is no project and thus no persistent cache, so using a custom `--target` will always incur a penalty.\n"
  },
  {
    "path": "docs/acton-guide/src/control_flow/actors.md",
    "content": "# Control flow in an async actor world\n\nActon programs do not have only one simple top-to-bottom control flow.\n\nOnce an actor exists, it keeps living and reacting to incoming method\ncalls until it stops. That means control flow is closer to \"react to\nmessages over time\" than to \"run one main function and finish\nimmediately\".\n\n<div class=\"beginner-content\">\n<p>If you are new to this style, start with one actor and a few\nmethods. Then add async calls and delayed work once the basic message\nflow makes sense. Inside one actor, each message still runs\nsequentially; the new part is thinking about what messages may arrive\nnext.</p>\n</div>\n\n<div class=\"advanced-content\">\n<p>This reactive model means message order belongs to each actor's own\nmailbox and handling, not one global timeline for the whole program.\nThat same boundary is why callbacks, async calls, and actor lifetime\nfit together in Acton.</p>\n</div>\n\n## A mental model\n\nIt helps to think in terms of actors reacting:\n\n- an actor receives a method call\n- it handles that work sequentially\n- it may call other actors\n- it may schedule more work with `after`\n- then it becomes idle again until the next message arrives\n\nThis is why actor code often looks different from ordinary function\ncode. The interesting question is usually not just \"what happens\nnext?\", but also \"what happens later, and in response to what message?\"\n"
  },
  {
    "path": "docs/acton-guide/src/control_flow/after_sleep.md",
    "content": "# `after` and sleep\n\nUse `after` when work should happen later.\n\n`after 1: tick()` tells the runtime to schedule `tick()` to run about\none second later. Meanwhile, the actor is free to handle other\nmessages.\n\n<div class=\"beginner-content\">\n<p>If you would normally reach for <code>sleep()</code> in another\nlanguage, first ask whether what you really want is \"run this later\".\nIn Acton, that usually means <code>after</code>. Read\n<code>after 1: tick()</code> as \"schedule this call for later\", not\n\"pause here for one second\".</p>\n</div>\n\n```python\nactor main(env):\n    var count = 0\n\n    def tick():\n        print(\"tick\", count)\n        count += 1\n        if count >= 3:\n            env.exit(0)\n        else:\n            after 1: tick()\n\n    tick()\n```\n\n`after` is the normal tool for:\n\n- timeouts\n- retries\n- pacing repeated work\n- scheduling a follow-up action\n\n## Why not `sleep`?\n\nNormal actor code should avoid blocking waits. A delayed callback with\n`after` lets the actor go idle and react to other messages in the\nmeantime.\n\n<div class=\"advanced-content\">\n<p>There is a low-level sleep in the RTS for debugging and runtime\nwork, but it is not the idiomatic control tool for actor programs.\n<code>after</code> keeps the actor schedulable, and the callback sees\nwhatever state the actor has when that later message is handled.</p>\n</div>\n"
  },
  {
    "path": "docs/acton-guide/src/control_flow/for.md",
    "content": "# for\n\nUse `for ... in ...` to go through each value in something like a\nstring, tuple, or `range(...)`.\n\n```python\nactor main(env):\n    names = (\"Ada\", \"Grace\", \"Linus\")\n\n    for name in names:\n        print(\"Hello\", name)\n\n    for n in range(3):\n        print(\"n =\", n)\n\n    env.exit(0)\n```\n\n<div class=\"beginner-content\">\n<p>A <code>for</code> loop is the usual choice when you want to go\nthrough each item in a collection or repeat something a known number of\ntimes. The loop variable is a new local name that takes on each value in\nturn.</p>\n</div>\n\n`range(stop)` counts from `0` up to, but not including, `stop`.\n\n```python\nfor n in range(5):\n    print(n)\n```\n\nYou can also use `range(start, stop, step)`.\n\n```python\nfor n in range(2, 10, 2):\n    print(n)\n```\n\nThe loop variable is local to the loop body. A common pattern is to use\n`for` with a collection when the values matter, and `range(...)` when the\ncount matters.\n\n<div class=\"advanced-content\">\n<p>In Acton, <code>for</code> is usually the clearest way to consume an\niterable because it avoids manual index state and keeps the element type\nfront and center. When you need both the index and the value, prefer\n<code>enumerate(...)</code> over <code>range(...)</code>. Use\n<code>range(...)</code> when the numbers themselves matter, not as a\ndefault substitute for iterating a collection.</p>\n\n```python\nfor i, name in enumerate(names):\n    print(i, name)\n```\n</div>\n"
  },
  {
    "path": "docs/acton-guide/src/control_flow/if_else.md",
    "content": "# if / elif / else\n\nUse `if` to run code only when a condition is true.\n\nUse `elif` for more cases and `else` for the fallback case.\n\n```python\ndef describe(n):\n    if n < 0:\n        return \"negative\"\n    elif n > 0:\n        return \"positive\"\n    else:\n        return \"zero\"\n\nactor main(env):\n    print(describe(-7))\n    print(describe(0))\n    print(describe(5))\n    env.exit(0)\n```\n\nThe conditions in `if`, `elif`, and `while` are expressions that\nevaluate to `True` or `False`.\n\n```python\nn = 7\n\nif n % 2 == 0:\n    print(\"even\")\nelse:\n    print(\"odd\")\n```\n\n<div class=\"advanced-content\">\n<p>Conditionals compose with Acton's expression model, so guards often\nmix comparisons, membership tests, and short-circuiting in one place.\nOnce the branching logic starts encoding type or protocol decisions,\nhelper functions or explicit narrowing usually read better than a long\nladder.</p>\n</div>\n"
  },
  {
    "path": "docs/acton-guide/src/control_flow/while.md",
    "content": "# while\n\nUse `while` when you want to keep looping for as long as a condition\nstays true.\n\n```python\nactor main(env):\n    var remaining = 3\n\n    while remaining > 0:\n        print(\"remaining:\", remaining)\n        remaining -= 1\n\n    print(\"done\")\n    env.exit(0)\n```\n\n<div class=\"beginner-content\">\n<p>With <code>while</code>, make sure something in the loop body can\neventually make the condition false. If that condition depends on a\nchanging value in actor code, that value usually needs\n<code>var</code>.</p>\n</div>\n\n`while` is useful when the number of iterations is not the main point.\nWhat matters is the condition.\n\n```python\nactor main(env):\n    var retries = 5\n\n    while retries > 0:\n        print(\"trying...\")\n        retries -= 1\n\n    env.exit(0)\n```\n\nIf you already have a collection or a simple numeric range, a\n`for` loop is usually clearer than a `while` loop. Reach for `while`\nwhen the condition really is the center of the logic.\n\n<div class=\"advanced-content\">\n<p>A <code>while</code> loop makes state transitions explicit, which is\nuseful for retries and actor-local state machines. The tradeoff is that\nyou now own the loop invariant and termination condition, so it is more\nerror-prone than <code>for</code> when the iteration boundary is already\nknown.</p>\n</div>\n\nTypical uses include retry loops, waiting for a condition to change, and\nsmall state machines where each pass updates the state before checking\nagain.\n"
  },
  {
    "path": "docs/acton-guide/src/control_flow.md",
    "content": "# Control flow\n\nControl flow decides which code runs, when it runs, and how often it\nruns.\n\nActon does not have a Rust-style `match` expression. Use\n`if`/`elif`/`else` for branching, and combine that with optionals or\nexceptions when the question is about absence or failure.\n\nStart with these three everyday tools:\n\n- [`if` / `elif` / `else`](control_flow/if_else.md) for branching\n- [`for`](control_flow/for.md) for iterating over items\n- [`while`](control_flow/while.md) for repeating while a condition stays\n  true\n\nLoops also support a few extra tools:\n\n- `break` to stop the loop early\n- `continue` to skip to the next iteration\n- `else` to run code after a loop finishes normally, without a `break`\n\n<div class=\"beginner-content\">\n<p>If you are new to programming, start with <code>if</code>,\n<code>for</code>, and <code>while</code> and treat loop\n<code>else</code> as optional. Most code uses the first three tools far\nmore often.</p>\n</div>\n\n```python\nfor n in range(5):\n    if n == 2:\n        continue\n    if n == 4:\n        break\n    print(n)\nelse:\n    print(\"finished without break\")\n```\n\n<div class=\"advanced-content\">\n<p>Loop <code>else</code> is tied to <code>break</code>, not to \"zero\niterations\". It runs whenever the loop finishes normally, which makes it\nuseful for search-style logic but easy to misread if used casually.</p>\n</div>\n\nActon also has actor-specific control patterns such as\n[`after`](control_flow/after_sleep.md). Those matter once you start\nthinking about actors, timers, and concurrency.\n"
  },
  {
    "path": "docs/acton-guide/src/environment/interactive_stdin.md",
    "content": "# Interactive stdin\n\nInteractive programs do not usually want line-buffered input. A text\neditor, a terminal UI, or a game often needs individual key presses as\nthey happen.\n\nBy default, stdin is in canonical mode. That means the terminal buffers\ninput and usually handles line editing before your program sees\nanything. If you want raw key presses, switch stdin to non-canonical\nmode.\n\n```python\nactor main(env):\n    def interact(input):\n        print(\"Got some input:\", input)\n\n    # Set non-canonical mode so we get each key press directly.\n    env.set_stdin(canonical=False)\n    # Turn off terminal echo.\n    env.set_stdin(echo=False)\n    env.stdin_install(interact)\n```\n\nCanonical mode is the right default for ordinary command line tools.\nNon-canonical mode is for programs that need to manage the terminal\nthemselves.\n\nThe runtime copies the terminal settings on startup and restores them\non exit, so you do not need to restore echo manually in the common\ncase.\n\n<div class=\"advanced-content\">\n<p>Interactive stdin changes the terminal contract for the whole\nprocess, not just one helper function. That is why the runtime restores\nsettings on exit for you, and why these programs should be careful and\nintentional about when they enter non-canonical mode.</p>\n</div>\n\n## Common patterns\n\nSwitch to non-canonical mode only when you need it, and keep that code\nclose to the part that depends on raw input. That makes the terminal\nstate easier to reason about.\n\nDisable echo when raw input should not be shown back to the user, such\nas when reading passwords or handling single-key commands.\n"
  },
  {
    "path": "docs/acton-guide/src/environment/stdin.md",
    "content": "# Reading stdin input\n\nRead from stdin by installing a handler with `env.stdin_install`. The\nhandler receives data as it arrives. In the common text case, the data\nis decoded to `str`.\n\n```python\nactor main(env):\n    def interact(input):\n        print(\"Got some input:\", input)\n\n    env.stdin_install(interact)\n```\n\nYou can make the text decoding explicit by providing `on_stdin`,\n`encoding`, and `on_error`.\n\nWhen `encoding` is not set, Acton tries to discover the encoding from\n`LANG`. If nothing useful is found, it falls back to UTF-8.\n\n```python\nactor main(env):\n    def interact(input):\n        print(\"Got some input:\", input)\n\n    def on_stdin_error(err, data):\n        print(\"Some error with decoding the input data:\", err)\n        print(\"Raw bytes data:\", data)\n\n    env.stdin_install(on_stdin=interact, encoding=\"utf-8\",\n        on_error=on_stdin_error)\n```\n\nIf the data is binary, or if you want to delay decoding, install a\nbytes handler instead.\n\n```python\nactor main(env):\n    def interact(bytes_input):\n        # Decode only when this code is ready to decide how.\n        print(\"Got some input:\", bytes_input.decode())\n\n    env.stdin_install(on_stdin_bytes=interact)\n```\n\n<div class=\"advanced-content\">\n<p>The important distinction is between a decoded text stream and a raw\nbyte stream. If the input protocol is truly textual, the string path is\nusually right. If framing, binary payloads, or uncertain encodings\nmatter, keep the data as <code>bytes</code> until your own code decides\nhow to decode it.</p>\n</div>\n\n## Common patterns\n\nUse the text callback for ordinary command line input, especially when\nthe input is line-oriented or clearly textual.\n\nUse the bytes callback when the input may contain binary data, partial\nfragments of multibyte characters, or a protocol with its own framing\nrules.\n\nTreat decode errors as part of the interface. If the program expects\ntext, decide what to do when the bytes do not decode cleanly instead of\nletting that decision hide inside a helper.\n"
  },
  {
    "path": "docs/acton-guide/src/environment/variables.md",
    "content": "# Environment variables\n\nEnvironment variables are a common way to pass configuration into a\nprogram. Acton lets you read, set, and unset them through `env`.\n\nThe string-based helpers are the most convenient:\n\n- `env.getenv(name)` returns a `str` or `None`\n- `env.setenv(name, value)` stores a string value\n- `env.unsetenv(name)` removes a variable\n\nThey assume UTF-8 text, which is practical for most programs. When you\nneed exact byte-level control, use the byte-oriented variants instead:\n\n- `env.getenvb`\n- `env.setenvb`\n- `env.unsetenvb`\n\n<div class=\"advanced-content\">\n<p>The string helpers are deliberately opinionated. They make the common\ncase easy, but they also make the text boundary explicit. If your code\nneeds to preserve the original bytes, avoid round-tripping through\n<code>str</code> until you have chosen a decoding strategy yourself.</p>\n</div>\n\n```python\nactor main(env):\n    env_user = env.getenv(\"USER\")\n    if env_user is None:\n        env_user = \"unknown\"\n\n    print(\"User:\", env_user)\n\n    if env.getenv(\"FOO\") is None:\n        env.setenv(\"FOO\", \"bar\")\n\n    foo_env = env.getenv(\"FOO\")\n    if foo_env is not None:\n        print(\"FOO:\", foo_env)\n\n    env.unsetenv(\"LANG\")\n    env.exit(0)\n```\n\nOutput:\n```sh\nUser: myuser\nFOO: bar\n```\n\n## Common patterns\n\nRead a variable once, check whether it is missing, and choose a safe\ndefault. Do not assume configuration is always present.\n\nUse environment variables for configuration values that are naturally\ntextual, such as names, paths, flags, and addresses. If the value is\nbinary or needs exact decoding rules, use the byte-oriented APIs and\ndecode in your own code.\n\nWhen a program sets or unsets variables, it is changing process state,\nnot just a local dictionary. Keep that in mind when passing `env`\nthrough helpers.\n"
  },
  {
    "path": "docs/acton-guide/src/environment.md",
    "content": "# Environment\n\nThe environment is your program's practical link to the outside world.\nMost programs meet it first as the `env` argument passed to the root\nactor.\n\nThe root actor receives the builtin environment actor `Env` as its\n`env` parameter. `Env` is the runtime-provided handle for outside-world\naccess.\n\n```python\nactor main(env):\n    print(\"args:\", env.argv)\n    env.exit(0)\n```\n\n<div class=\"beginner-content\">\n<p>You can think of <code>env</code> as the handle your program receives\nfor talking to the world around it. It is passed into <code>main</code>;\nit is not a hidden global that every function can reach automatically.\nIf a helper only needs one small piece of that power, pass the smaller\npiece instead of the whole environment.</p>\n</div>\n\n`Env` provides, among other things:\n\n- `env.argv` for command-line arguments\n- `env.cap` for the root `WorldCap` capability\n- `env.getenv`, `env.setenv`, and `env.unsetenv` for environment\n  variables\n- `env.stdin_install`, `env.set_stdin`, `env.stdout_write`, and\n  `env.is_tty` for terminal and stdin handling\n- `env.exit(n)` to terminate the program\n\n- [Environment variables](environment/variables.md)\n- [Reading stdin input](environment/stdin.md)\n- [Interactive stdin input](environment/interactive_stdin.md)\n\nUse `env` when code needs process arguments, environment variables,\nstandard input, or terminal configuration. Pass it only to the code\nthat actually needs that access.\n\n<div class=\"advanced-content\">\n<p><code>env</code> is best understood as a bundle of process-level\ncapabilities, not as one ordinary argument. It carries authority over\nthings such as arguments, environment variables, standard input, and\nterminal configuration. If that whole bundle gets threaded through many\nlayers, those layers quietly become coupled to process concerns even\nwhen they only need one small part of it.</p>\n\n<p>In larger programs, treat the root actor as the place where broad\nauthority is received, then pass inward only the narrower capability or\nvalue a helper actually needs. That keeps APIs honest about what they\ndepend on, makes tests easier to fake, and prevents a small utility\nfrom accidentally gaining much wider access to the outside world than\nits job requires.</p>\n</div>\n"
  },
  {
    "path": "docs/acton-guide/src/ext/integrating_c_library.md",
    "content": "# Integrating a C library (zlib)\n\nThis is a guide to integrating C libraries in Acton code. We will use the zlib compression library, written in C, to build an Acton module that supports zlib compression and decompression.\n\nWe will only focus on the `inflate` and `deflate` functions in zlib. They are pure functions (meaning they only take some input and return some output, they do not have any side effects like writing to some shared state), that makes them easier to integrate than anything that does I/O. While zlib does expose functions to interact with files, we don't want to reimplement file related functionality since we already have this supported by the Acton stdlib.\n\n## Create new project\n\nLet's start by making a new Acton project, let's call it `acton-zlib`. New projects are created with an example \"Hello world\" app. Let's remove it and start from scratch.\n```console\nacton new acton-zlib\ncd acton-zlib\nrm src/*\n```\n\n## Acton's low level build system - the Zig build system\nThe Acton compiler parses .act source code, runs through all its compilation passes with type checking, CPS conversion, lambda lifting etc and finally produces C code. Internally, Acton then uses the Zig build system to compile the generated C code to libraries and finally binary executables.\n\nTo add a C library dependency, it first needs to be buildable using the Zig build system, which means that it needs a `build.zig` file, the config file for the Zig build, somewhat similar to the CMakeLists.txt of CMake. Some projects have already adopted a `build.zig` in the upstream repo, like PCRE2 and the Boehm-Demers-Weiser GC (both of which are used by Acton). In some cases, there are forks of projects with `build.zig` added. Otherwise you will need to write one for yourself, which is usually simpler than it might first seem.\n\n## Add the zlib C library as a Zig dependency\n\nIn the case of zlib, there is already [a repo available with a build.zig for zlib](https://github.com/allyourcodebase/zlib/). Navigate to the Tags page, find `1.3.1` and the link to the source files, i.e. `https://github.com/allyourcodebase/zlib/archive/refs/tags/1.3.1.tar.gz`.\n\nAdd it to our `acton-zlib` project:\n```console\nacton zig-pkg add https://github.com/allyourcodebase/zlib/archive/refs/tags/1.3.1.tar.gz zlib --artifact z\n```\n\nNote the `--artifact z` which is provided to instruct which library to link with. Headers from the zlib library, like `zlib.h`, will now become visible to C files in our project and the `z` library will be linked in with our executables. The easiest way to discover what the artifacts are called is by inspecting the `build.zig` file of the package. This particular zlib `build.zig` starts like this:\n\n```zig\nconst std = @import(\"std\");\n\npub fn build(b: *std.Build) void {\n    const upstream = b.dependency(\"zlib\", .{});\n    const lib = b.addStaticLibrary(.{\n        .name = \"z\",\n        .target = b.standardTargetOptions(.{}),\n        .optimize = b.standardOptimizeOption(.{}),\n    });\n    lib.linkLibC();\n    lib.addCSourceFiles(.{\n        .root = upstream.path(\"\"),\n        .files = &.{\n            \"adler32.c\",\n            \"crc32.c\",\n...\n```\n\nIt is the `.name` argument to `addStaticLibrary` that tells us the name of the artifact. Zig packages might expose multiple such artifacts, as is the case for [mbedtls](https://github.com/actonlang/mbedtls/blob/zig-build/build.zig).\n\n`acton zig-pkg add` will fetch the package from the provided URL and save the hash sum to `Build.act`, resulting in:\n```python\ndependencies = {}\n\nzig_dependencies = {\n  \"zlib\": (\n        url=\"https://github.com/allyourcodebase/zlib/archive/refs/tags/1.3.1.tar.gz\",\n        hash=\"122034ab2a12adf8016ffa76e48b4be3245ffd305193edba4d83058adbcfa749c107\",\n        artifacts=[\"z\"]\n    ),\n}\n```\n\n## Create zlib.act Acton module\n\nNext up we need to create the Acton `zlib` module. Open `src/zlib.act` and add a compress and decompress function:\n\n```python\npure def compress(data: bytes) -> bytes:\n    NotImplemented\n\npure def decompress(data: bytes) -> bytes:\n    NotImplemented\n```\n\nThe `NotImplemented` statement tells the compiler that the implementation is not written in Acton but rather external. When there is a `.ext.c` file, the compiler expects it to contain the implementations for the `NotImplemented` functions. Also note the explicit types. Normally the Acton compiler can infer types, but since there is no Acton code here, only C code, there is nothing to infer from.\n\nNow create `src/zlib.ext.c` which is where we will do the actual implementation of these functions. We need to add a `__ext_init__` function, which runs on module load by the Acton RTS, which must always exist. There is nothing to do in particular for zlib so let's just create an empty function, like so:\n\n```c\nvoid zlibQ___ext_init__() {}\n```\n\nNext, we need to fill in the C functions that map to the Acton functions `compress` and `decompress`. By invoking `acton build` we can get the compiler to generate a skeleton for these. We will also get a large error message, since there is no actual implementation:\n\n```console\nuser@host$ acton build\n... some large error message\n```\nIgnore the error and instead check the content of `out/types/zlib.c` and we will find the C functions we need, commented out:\n```\n#include \"rts/common.h\"\n#include \"out/types/zlib.h\"\n#include \"src/zlib.ext.c\"\nB_bytes zlibQ_compress (B_bytes data);\n/*\nB_bytes zlibQ_compress (B_bytes data) {\n    // NotImplemented\n}\n*/\nB_bytes zlibQ_decompress (B_bytes data);\n/*\nB_bytes zlibQ_decompress (B_bytes data) {\n    // NotImplemented\n}\n*/\nint zlibQ_done$ = 0;\nvoid zlibQ___init__ () {\n    if (zlibQ_done$) return;\n    zlibQ_done$ = 1;\n    zlibQ___ext_init__ ();\n}\n```\n\nCopy the commented-out skeleton into our own `src/zlib.ext.c`. Just in order to get something that compiles, let's just quickly let the functions return the input data. Since both input and output are `bytes`, this should now compile (and work at run time).\n```c\nB_bytes zlibQ_compress (B_bytes data) {\n    return data;\n}\nB_bytes zlibQ_decompress (B_bytes data) {\n    return data;\n}\n```\n\n```console\nuser@host:~/acton-zlib$ acton build\nBuilding project in /Users/user/acton-zlib\n  Compiling zlib.act for release\n   Finished compilation in   0.005 s\n  Compiling test_zlib.act for release\n   Finished compilation in   0.019 s\n  Final compilation step\nuser@host:~/acton-zlib$\n```\n\n## Add a test module\n\nBefore we implement the body of the compress and decompress functions, we can write a small test module which will tell us when we've succeeded. We use some pre-known test data (which we could get from another language implementation):\n```python\nimport testing\nimport zlib\n\ndef _test_roundtrip():\n    for x in range(100):\n        i = \"hello\".encode()\n        c = zlib.compress(i)\n        d = zlib.decompress(c)\n        testing.assertEqual(i, d)\n\ndef _test_compress():\n    for x in range(100):\n        i = \"hello\".encode()\n        c = zlib.compress(i)\n        testing.assertEqual(c, b'x\\x9c\\xcbH\\xcd\\xc9\\xc9\\x07')\n\ndef _test_decompress():\n    for x in range(1000):\n        c = b'x\\x9c\\xcbH\\xcd\\xc9\\xc9\\x07'\n        d = zlib.decompress(c)\n        testing.assertEqual(d, b'hello')\n```\n\nNote how we run a few test iterations to get slightly better timing measurements for performance testing. Run the test with `acton test`:\n\n```console\nuser@host:~/acton-zlib$ acton test\n\nTests - module test_zlib:\n  decompress:            FAIL:  195 runs in 50.728ms\n    testing.NotEqualError: Expected equal values but they are non-equal. A: b'x\\x9c\\xcbH\\xcd\\xc9\\xc9\\x07' B: b'hello'\n  compress:              FAIL:  197 runs in 50.886ms\n    testing.NotEqualError: Expected equal values but they are non-equal. A: b'hello' B: b'x\\x9c\\xcbH\\xcd\\xc9\\xc9\\x07'\n  roundtrip:             OK:  226 runs in 50.890ms\n\n2 out of 3 tests failed (26.354s)\n\nuser@host:~/acton-zlib$ \n```\n\nAs expected, the roundtrip test goes through, since we just return the input data while the compress and decompress tests fail.\n\n## Implement the compress function\n\nNow let's fill in the rest of the owl. Below is the body of the `zlibQ_compress` function. The bulk of this code is not particularly interesting to this guide as it has more to do with standard C usage of zlib, but a few things are worth noting.\n\n```c\nB_bytes zlibQ_compress(B_bytes data) {\n    if (data->nbytes == 0) {\n        return data;\n    }\n\n    // Prepare the zlib stream\n    int ret;\n    z_stream stream;\n    memset(&stream, 0, sizeof(stream));\n    ret = deflateInit(&stream, Z_DEFAULT_COMPRESSION);\n    if (ret != Z_OK) {\n        $RAISE((B_BaseException)$NEW(B_ValueError, to$str(\"Unable to compress data, init error: %d\", ret)));\n    }\n\n    // Set the input data\n    stream.avail_in = data->nbytes;\n    stream.next_in = (Bytef*)data->str;\n\n    // Allocate the output buffer using Acton's malloc\n    size_t output_size = deflateBound(&stream, data->nbytes);\n    Bytef* output_buffer = (Bytef*)acton_malloc_atomic(output_size);\n    stream.avail_out = output_size;\n    stream.next_out = output_buffer;\n\n    // Perform the deflate operation\n    ret = deflate(&stream, Z_FINISH);\n    if (ret != Z_STREAM_END) {\n        $RAISE((B_BaseException)$NEW(B_ValueError, $FORMAT(\"Unable to compress data, error: %d\", ret)));\n    }\n\n    // Clean up\n    deflateEnd(&stream);\n\n    return actBytesFromCStringNoCopy(output_buffer);\n}\n```\n\nMemory management is always top of mind when writing C, as it the case here. We can allocate memory via the Acton GC-heap malloc or just plain `malloc()` (the non-GC heap, to be explicit). Since `zlibQ_compress` is pure, we have no state leaking out of the function other than via its return value. All return values must be allocated on the Acton GC heap, so we know we must use `acton_malloc` for any value that we return. Any other local variables within the function can use classic malloc, as long as we make sure to explicitly free it up. For class or actor methods, any allocation for class or actor attributes must be performed using the Acton GC malloc, since there is no destructor or similar where a free can be inserted, so using classic malloc would be bound to leak. Also note that in this particular case, we know that the returned bytes value itself is not going to contain any pointers, so by using `acton_malloc_atomic` we can get a chunk of memory that will not be internally scanned by the GC, which saves a bit of time and thus improves GC performance. If we allocate structs that do carry pointers, they must use the normal `acton_malloc()`.\n\n`actBytesFromCStringNoCopy(output_buffer)` takes the `buffer` (already allocated via `acton_malloc_atomic()`) and wraps it up as a boxed value of the type `B_bytes` that we return.\n\nAlso note how we convert Zlib errors to Acton exceptions where necessary.\n\nRunning the test, the `compress` test now passes while roundtrip has stopped working (since decompress is not implemented yet):\n\n```console\nuser@host:~/acton-zlib$ acton test\nTests - module test_zlib:\n  decompress:            FAIL:  158 runs in 50.175ms\n    testing.NotEqualError: Expected equal values but they are non-equal. A: b'x\\x9c\\xcbH\\xcd\\xc9\\xc9\\x07' B: b'hello'\n  compress:              OK:  167 runs in 50.225ms\n  roundtrip:             FAIL:  147 runs in 50.266ms\n    testing.NotEqualError: Expected equal values but they are non-equal. A: b'hello' B: b'x\\x9c\\xcbH\\xcd\\xc9\\xc9\\x07'\n\n2 out of 3 tests failed (0.941s)\n\nuser@host:~/acton-zlib$ \n```\n\n## Implement the decompress function\n\nMuch like the compress function, the decompress function mostly relates to how zlib itself and its interface works. We use the same wrappers and transform errors to exceptions.\n\n```c\nB_bytes zlibQ_decompress(B_bytes data) {\n    if (data->nbytes == 0) {\n        return data;\n    }\n\n    // Prepare the zlib stream\n    int ret;\n    z_stream stream;\n    memset(&stream, 0, sizeof(stream));\n\n    ret = inflateInit(&stream);\n    if (ret != Z_OK) {\n        $RAISE((B_BaseException)$NEW(B_ValueError, $FORMAT(\"Unable to decompress data, init error: %d\", ret)));\n    }\n\n    // Set the input data\n    stream.avail_in = data->nbytes;\n    stream.next_in = (Bytef*)data->str;\n\n    // Allocate the output buffer using Acton's malloc\n    size_t output_size = 2 * data->nbytes; // Initial output buffer size\n    Bytef* output_buffer = (Bytef*)acton_malloc_atomic(output_size);\n    memset(output_buffer, 0, output_size);\n    stream.avail_out = output_size;\n    stream.next_out = output_buffer;\n\n    // Perform the inflate operation, increasing the output buffer size if needed\n    do {\n        ret = inflate(&stream, Z_NO_FLUSH);\n        if (ret == Z_BUF_ERROR) {\n            // Increase the output buffer size and continue decompressing\n            size_t new_output_size = output_size * 2;\n            output_buffer = (Bytef*)acton_realloc(output_buffer, new_output_size);\n            stream.avail_out = new_output_size - stream.total_out;\n            stream.next_out = output_buffer + stream.total_out;\n        } else if (ret != Z_OK) {\n            $RAISE((B_BaseException)$NEW(B_ValueError, $FORMAT(\"Unable to decompress data, error: %d\", ret)));\n        }\n    } while (ret == Z_BUF_ERROR);\n\n    // Clean up\n    inflateEnd(&stream);\n\n    return actBytesFromCStringNoCopy(output_buffer);\n}\n```\n\n## Final test\n\n```console\nuser@host:~/acton-zlib$ acton test\n\nTests - module test_zlib:\n  decompress:            OK:   42 runs in 51.065ms\n  compress:              OK:   25 runs in 50.032ms\n  roundtrip:             OK:   24 runs in 50.053ms\n\nAll 3 tests passed (0.738s)\n\nuser@host:~/acton-zlib$ \n```\n\nAnd with that, we're done! A simple wrapper around zlib, which is also available [on GitHub](https://github.com/actonlang/acton-zlib) if you want to study it further.\n"
  },
  {
    "path": "docs/acton-guide/src/functions/actor_methods.md",
    "content": "# Actor methods\n\nActor methods are declared inside an `actor` with `def`.\n\nAn actor method runs in the context of that actor and can access its\nprivate state.\n\n<div class=\"beginner-content\">\n<p>An actor method is like a normal method with one extra idea: it runs\ninside an actor that owns its own state and message flow. That is why a\nmethod like <code>compute</code> can use <code>secret</code> without\nreceiving it as an argument each time.</p>\n</div>\n\nLocal actor methods can call each other by name. Methods on other\nactors are called through that actor's reference.\n\n<div class=\"advanced-content\">\n<p>Because actors are sequential, local function calls and local method\ncalls run one step at a time inside that actor. Concurrency appears\nwhen actors call each other. Whether a remote call is sync or async\nchanges ordering and waiting behavior, not just syntax.</p>\n</div>\n\n```python\ndef multiply(a, b):\n    return a * b\n\nactor main(env):\n    var secret = 42\n\n    def compute(a):\n        return multiply(a, secret)\n\n    result = compute(3)\n    print(\"Result:\", result)\n    env.exit(0)\n```\n\nActor methods are public by default. Calls to other actors can be\n[synchronous](../actors/sync_method_call.md) or\n[asynchronous](../actors/async_method_call.md).\n"
  },
  {
    "path": "docs/acton-guide/src/functions/higher_order.md",
    "content": "# Higher order functions\n\nActon supports higher order functions, which means you can pass a\nfunction as an argument to another function and choose behavior at the\ncall site.\n\nThat is Acton's nearest equivalent to the reusable part of Rust's\nclosure and iterator story. Acton does not have a Rust-style closure or\niterator-adapter path to learn first; use higher-order functions,\ncomprehensions, and explicit iteration instead.\n\n<div class=\"beginner-content\">\n<p>A function can be treated like any other value. That makes it easy to\nreuse one loop, one validation path, or one calculation with different\nbehaviors plugged in.</p>\n</div>\n\n```python\ndef apply_twice(fun, value):\n    return fun(fun(value))\n\ndef double(n):\n    return 2 * n\n\ndef square(n):\n    return n * n\n\nactor main(env):\n    print(apply_twice(double, 3))\n    print(apply_twice(square, 2))\n    env.exit(0)\n```\n\nThis prints:\n\n```sh\n12\n16\n```\n\nUse this pattern when the operation is the thing that changes and the\noverall shape of the work stays the same.\n\n<div class=\"advanced-content\">\n<p>Higher order functions work best when the varying behavior is small,\nstateless, and easy to describe as \"apply this operation here\". That\nmakes them a good fit for callbacks, adapters, validation hooks, and\nsmall reusable transformation steps. Once the behavior needs evolving\nstate across calls, the design question changes: you are no longer just\npassing behavior, you are passing behavior plus state.</p>\n\n<p>At that point, an actor or a small object is often a better home than\ntrying to simulate closure-heavy code by threading more and more helper\narguments through every call. The same applies to collection work: if a\ntransformation is local and easy to read, a comprehension or short loop\nusually expresses it more clearly than a stack of tiny callback-style\nhelpers. Reach for higher order functions when they clarify the reusable\nvariation, not just because the language allows them.</p>\n</div>\n"
  },
  {
    "path": "docs/acton-guide/src/functions.md",
    "content": "# Functions\n\nFunctions package reusable logic behind a name. Declare a function with\n`def`.\n\nFunctions are values too, so you can pass behavior into another\nfunction when the call site should choose the variation. See\n[Higher order functions](functions/higher_order.md) for that pattern.\n\n```python\ndef clamp(n, low, high):\n    if n < low:\n        return low\n    if n > high:\n        return high\n    return n\n\nactor main(env):\n    print(clamp(3, 0, 5))\n    print(clamp(-2, 0, 5))\n    print(clamp(9, 0, 5))\n    env.exit(0)\n```\n\nFunction arguments are local names inside the function body.\n\n<div class=\"advanced-content\">\n<p>Type inference makes local helpers cheap to write, but it does not\nmake their types unimportant. As soon as a function is used across a\nmodule boundary, callers depend on whatever the compiler inferred for\nits arguments, return value, effects, and generic constraints. Those\nfacts are part of the callable contract even when no explicit signature\nappears in the source.</p>\n\n<p>That has a practical consequence: changing a function from\n<code>pure</code> to <code>proc</code>, tightening a generic bound, or\nmaking a result optional is not just an implementation tweak. It can\nforce changes at call sites. That is why public functions deserve a\nhigher bar than local helpers. It is often fine to let inference handle\nsmall local code, but API-facing functions should be read as typed\ninterfaces whether the signature is written down or not.</p>\n</div>\n\n## Arguments\n\nArguments are available only inside the function where they are defined.\nThat makes them useful for small, self-contained pieces of logic.\n\n<div class=\"beginner-content\">\n<p>Think of a function as a small named tool. You give it input values,\nit does some work, and it may give a result back. Calling a function is\njust another expression, so you can store or pass along its result.</p>\n\n<p>When the behavior itself should vary, pass a function instead of\nbranching in every caller. That keeps the shared work in one place.</p>\n</div>\n\n## Returning values\n\nUse `return` to send a value back to the caller.\n\n```python\ndef square(n):\n    return n * n\n```\n\nIf a function reaches the end without a `return`, the result is `None`.\n\n<div class=\"beginner-content\">\n<p><code>return</code> ends the function immediately. Any code after it\nin the same block does not run.</p>\n</div>\n\n```python\ndef greet(name):\n    print(\"Hello\", name)\n```\n\n## Practical guidance\n\n- Keep functions focused on one job.\n- Prefer returning values over printing inside helper functions.\n- Give functions names that describe what they compute or do.\n"
  },
  {
    "path": "docs/acton-guide/src/hello/args.md",
    "content": "# Program Arguments\n\nProgram arguments are available as the attribute `argv` on the `env` actor. `env.argv` is a list where the first element contains the name of the shell command and the second element being the first proper argument.\n\nWe can rewrite our program to print a user supplied name to greet rather than the world.\n\nSource:\n```python\nactor main(env):\n    print(\"Hello \" + env.argv[1] + \"!\")\n    env.exit(0)\n```\n\nCompile and run, with argument:\n```sh\nacton hello.act\n./hello Johan\n```\n\nOutput:\n```sh\nHello Johan!\n```\n"
  },
  {
    "path": "docs/acton-guide/src/hello/running_tests.md",
    "content": "# Running Tests\n\nWriting tests is an integral part of writing software. In an Acton project, you can run all the tests by issuing `acton test`:\n\n```console\nfoo@bar:~hello$ acton test\n\nTests - module hello:\n  foo:                   OK:  278 runs in 50.238ms\n\nAll 1 tests passed (23.491s)\n\nfoo@bar:~hello$ \n```\n\nSee the [Testing](/testing.md) section on how to write tests.\n"
  },
  {
    "path": "docs/acton-guide/src/hello/shebang.md",
    "content": "# Shebang\n\nWhile Acton is a compiled language and the `acton` compiler produces an executable binary, script style execution is also possible through the use of a shebang line.\n\nSource:\n```python\n#!/usr/bin/env runacton\n\nactor main(env):\n    print(\"Hello World!\")\n    env.exit(0)\n```\n\nEnsure the executable bit is set and run your .act file directly:\n```console\nchmod a+x hello.act\n./hello.act\n```\n\nOutput:\n```console\nHello World!\n```\n\n"
  },
  {
    "path": "docs/acton-guide/src/hello.md",
    "content": "# Hello World\n\nWe follow tradition and introduce Acton with the following minimal example\n\nSource:\n```python\n# This is a comment, which is ignored by the compiler.\n\n# An actor named 'main' is automatically discovered and recognized as the root \n# actor. Any .act file with a main actor will be compiled into a binary \n# executable and the main actor becomes the starting point.\nactor main(env):\n    print(\"Hello World!\")\n    env.exit(0)\n```\n\nCompile and run:\n```console\nacton hello.act\n./hello\n```\n\nOutput:\n```console\nHello World!\n```\n\n\n## Description\n\nWhen an Acton program runs, it really consits of a collection of actors that interact with each other. In the above example, we have just a single actor, which has been given the name `main` and that acts as the *root actor* of our system. The *root actor* of a system takes a parameter `env`, which represents the execution environment. `env` has methods for accessing command line arguments and carries a reference to the capabilities of the surrounding world, `WorldCap`, for accessing the environment, e.g. reading from and writing to keyboard/screen and files, working with sockets etc.\n"
  },
  {
    "path": "docs/acton-guide/src/index.md",
    "content": "```bob\n\n                                        A Guide to\n\n\n                  .---.                        .-.\n                 /     \\                       | |\n                /   _   \\          .----.   .--' '--.      .----.     .-..-----.\n               /   / \\   \\        / .--._\\  '--. .--'     / .--. \\    | / .---. \\\n              /   '---'   \\      / /           | |       / /    \\ \\   |  /    | |\n             /             \\    ( (            | |      ( (      ) )  | |     | |\n            /   .-------.   \\    \\ \\    __     | |  __   \\ \\    / /   | |     | |\n           /   /         \\   \\    \\ '--' /     \\ '-' /    \\ '--' /    | |     | |\n          '---'           `---'    '----'       '---'      '----'     '-'     '-'\n     \n\n\n       -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-\n\n```\n\nActon is a general-purpose programming language with a sharp focus on building\nrobust reactive systems from many cooperating actors. It is especially well\nsuited to distributed scale-out logic, where safety comes from combining\nactor-local state, explicit communication, and a static type system that checks\nthe shape of the program before it runs.\n\nActors are Acton's unit of state, concurrency, and communication: each actor\nruns sequentially, owns its state, and interacts with other actors through\nmethod calls, timers, callbacks, and async I/O. The actor model keeps mutation\nlocal and control flow direct while allowing many independent pieces of work to\nrun concurrently.\n\nThe language keeps familiar syntax while adding functional and object-oriented\nprogramming, type inference, capability-based security, and native compilation.\nIt is practical for everyday scripts and services, but its center of gravity is\nactor-heavy systems where correctness, explicit authority, and efficient\ncompiled code matter.\n"
  },
  {
    "path": "docs/acton-guide/src/install.md",
    "content": "# Installation\n\n{{#tabs }}\n{{#tab name=\"Debian / Ubuntu\" }}\nFor Debian derivative distributions that use .dpkg and the APT ecosystem. Add the Acton APT repo and install from there:\n```console\nsudo install -m 0755 -d /etc/apt/keyrings\nsudo wget -q -O /etc/apt/keyrings/acton.asc https://apt.acton-lang.io/acton.gpg\nsudo chmod a+r /etc/apt/keyrings/acton.asc\necho \"deb [signed-by=/etc/apt/keyrings/acton.asc] http://apt.acton-lang.io/ stable main\" | sudo tee -a /etc/apt/sources.list.d/acton.list\nsudo apt-get update\nsudo apt-get install -qy acton\n```\n{{#endtab }}\n{{#tab name=\"MacOS\" }}\n```console\nbrew install actonlang/acton/acton\n```\n{{#endtab }}\n{{#endtabs }}\n\n## Container image\n\nActon also publishes a container image for trying Acton without installing it\nlocally, running builds in CI, or pinning a reproducible toolchain for examples\nand tutorials. For day-to-day development, the native APT and Homebrew packages\nare usually more convenient.\n\nCheck the installed Acton version in the image:\n\n```console\ndocker run --rm ghcr.io/actonlang/acton:latest version\n```\n\nBuild the Acton project in the current directory:\n\n```console\ndocker run --rm -v \"$PWD\":/work -w /work ghcr.io/actonlang/acton:latest build\n```\n\nFor CI and long-lived examples, pin a version tag instead of using `latest`.\n"
  },
  {
    "path": "docs/acton-guide/src/install_tip.md",
    "content": "# Installation\n\nTip releases are built from the latest commit on the acton git repo main branch. They are built at least once a night, so can be thought of as nightlies but more up to date.\n\n{{#tabs }}\n{{#tab name=\"Debian / Ubuntu\" }}\nFor Debian derivative distributions that use .dpkg and the APT ecosystem. Add the Acton APT tip repo and install from there:\n```console\nsudo install -m 0755 -d /etc/apt/keyrings\nsudo wget -q -O /etc/apt/keyrings/acton.asc https://apt.acton-lang.io/acton.gpg\nsudo chmod a+r /etc/apt/keyrings/acton.asc\necho \"deb [signed-by=/etc/apt/keyrings/acton.asc] http://aptip.acton-lang.io/ tip main\" | sudo tee -a /etc/apt/sources.list.d/acton.list\nsudo apt-get update\nsudo apt-get install -qy acton\n```\n{{#endtab }}\n{{#tab name=\"Linux x86_64\" }}\nCopy and extract the distribution tarball. Download from https://github.com/actonlang/acton/releases/download/tip/acton-linux-x86_64-tip.tar.xz\n```console\ntar Jxf acton-linux-x86_64-tip.tar.xz\n```\n{{#endtab }}\n{{#tab name=\"Linux ARM64\" }}\nCopy and extract the distribution tarball. Download from https://github.com/actonlang/acton/releases/download/tip/acton-linux-aarch64-tip.tar.xz\n```console\ntar Jxf acton-linux-aarch64-tip.tar.xz\n```\n{{#endtab }}\n{{#tab name=\"MacOS x86_64\" }}\nCopy and extract the distribution tarball. Download from https://github.com/actonlang/acton/releases/download/tip/acton-macos-x86_64-tip.tar.xz\n```console\ntar Jxf acton-macos-x86_64-tip.tar.xz\n```\n{{#endtab }}\n{{#tab name=\"MacOS ARM64\" }}\nCopy and extract the distribution tarball. Download from https://github.com/actonlang/acton/releases/download/tip/acton-macos-aarch64-tip.tar.xz\n```console\ntar Jxf acton-macos-aarch64-tip.tar.xz\n```\n{{#endtab }}\n{{#endtabs }}\n"
  },
  {
    "path": "docs/acton-guide/src/language/bindings_scope.md",
    "content": "# Variables, constants, and scope\n\nNames let you store values and use them again later.\n\n<div class=\"beginner-content\">\n<p>Programmers often use <em>variable</em> to mean \"a named place where a\nvalue is stored\". In Acton, the more precise question is whether that\nname is a <em>constant</em> binding or a <em>mutable</em> one.</p>\n\n<p>A constant binding keeps the same value for its lifetime. A mutable\nbinding is one whose value may be updated later. In everyday English,\n<em>mutable</em> just means \"able to change\".</p>\n</div>\n\nWhere a name is defined determines where it can be used. This is called\nits *scope*.\n\n<div class=\"beginner-content\">\n<p>Scope means \"the part of the program where a name is visible\". A name\ndefined inside a function or method is only available there.\nModule-level names live across the module. Actor bodies have their own\nrules, which are covered below.</p>\n</div>\n\n```python\ngreeting = \"hello\"    # module-level constant\n\ndef show_local():\n    greeting = \"hi\"   # local name that shadows the module-level greeting\n    print(\"local greeting:\", greeting)\n\ndef show_global():\n    print(\"global greeting:\", greeting)\n\nactor main(env):\n    show_local()\n    show_global()\n\n    env.exit(0)\n```\n\nIn this example:\n\n- The module-level `greeting` is a constant.\n- The `greeting` inside `show_local` is a different local name.\n\n## Module-level names\n\nNames defined at module level are constants. They are useful for helper\nfunctions, reusable values, and definitions that the rest of the module\nshares.\n\n```python\nport = 9000\n\ndef address():\n    return \"127.0.0.1:\" + str(port)\n```\n\n<div class=\"beginner-content\">\n<p>Here <code>port</code> is a constant: after it is defined, you use it,\nbut you do not update it. That is a good default for names that describe\nconfiguration, helper values, and definitions shared across a module.</p>\n</div>\n\n## Local names\n\nNames defined inside a function or method are local to that body.\n\n```python\ndef greet(name):\n    message = \"Hello \" + name\n    print(message)\n```\n\nHere, `message` only exists inside `greet`.\n\n## Names in actors\n\nActon treats names at the top level of an actor body differently from\nnames inside a function or method.\n\n```python\nactor Counter():\n    var remaining = 3\n    label = \"counter\"\n    _unit = \"items\"\n\n    def tick():\n        print(label, remaining, _unit)\n        remaining -= 1\n```\n\nIn this example:\n\n- `remaining` is private mutable actor state.\n- `label` is a public constant attribute.\n- `_unit` is private to the actor because its name starts with `_`.\n\n<div class=\"beginner-content\">\n<p>Read <code>var</code> as \"this actor-local name will change over\ntime\". If you plan to update a value in actor code, make that explicit\nup front.</p>\n\n<p>A plain name at the top level of an actor body is not an ordinary\nlocal variable. It becomes a constant actor attribute instead. If the\nname starts with <code>_</code>, it stays private to the actor. Without\nthe leading underscore, other actors can read that constant through an\nactor reference.</p>\n</div>\n\n<div class=\"advanced-content\">\n<p>Acton keeps module-level bindings constant and pushes mutable shared\nstate into actors. That changes how you structure larger programs:\nrefactoring stateful logic usually means introducing an actor boundary,\nnot another mutable top-level name.</p>\n</div>\n\n## Shadowing\n\nShadowing means introducing a new local name with the same spelling as\nan existing one. The outer name still exists, but the inner one is the\none used in that scope.\n\n```python\nname = \"Acton\"\n\ndef show():\n    name = \"local\"\n    print(name)\n\nshow()\nprint(name)\n```\n\nHere, `show` introduces a local `name` that shadows the module-level\n`name`. Inside `show`, `name` means `\"local\"`. Outside `show`, it still\nmeans `\"Acton\"`.\n\nShadowing is sometimes useful, but overusing it makes code harder to\nread. Prefer distinct names when the two values mean different things.\n"
  },
  {
    "path": "docs/acton-guide/src/language/comments.md",
    "content": "# Comments\n\nUse `#` for comments.\n\nComments are for readers of the code. Use them to explain intent,\nassumptions, or surprising choices.\n\n```python\ndef area(width, height):\n    # Width and height are measured in meters.\n    return width * height\n\nactor main(env):\n    # Keep the greeting short because it is printed in a narrow terminal.\n    message = \"Hello\"\n    print(message)\n    env.exit(0)\n```\n\n<div class=\"beginner-content\">\n<p>A comment is ignored by the compiler. It is there only for people\nreading the source code. There is no separate block-comment syntax here;\nuse <code>#</code> on each line you want to comment.</p>\n</div>\n\n## What to comment\n\nUse comments for things the code does not make obvious:\n\n- why a check exists\n- units or external constraints\n- a temporary workaround\n- a non-obvious invariant\n\n## Practical guidance\n\n- Prefer comments that explain <em>why</em>, not comments that only\n  repeat what the code already says.\n- Keep comments close to the code they describe.\n- Update or remove comments when the code changes.\n"
  },
  {
    "path": "docs/acton-guide/src/language/common_programming_concepts.md",
    "content": "# Common programming concepts\n\nThis section covers the pieces you use in almost every Acton program:\nnames and scope, built-in types, expressions, functions, comments, and\ncontrol flow.\n\nThese pages are the foundation for the rest of the guide. Read them in\norder:\n\n1. [Variables, constants, and scope](bindings_scope.md)\n2. [Built-in types and literals](../primitives.md)\n3. [Expressions and operators](expressions_operators.md)\n4. [Functions](../functions.md)\n5. [Comments](comments.md)\n6. [Control flow](../control_flow.md)\n\nMost examples use `actor main(env):` as the entry point because Acton\nprograms run from a root actor. You do not need to understand actors in\ndepth yet to follow these pages, it will be explained later.\n"
  },
  {
    "path": "docs/acton-guide/src/language/environment_capabilities.md",
    "content": "# Environment and capabilities\n\nPrograms that talk to the outside world need explicit access. In\nActon, that access comes through the root `env` actor and through\ncapability references that are passed around like any other value.\n\n<div class=\"beginner-content\">\n<p>Most small programs start with <code>env</code> and end with\n<code>env.exit(0)</code>. That is normal. The important part is that\n<code>env</code> is passed in explicitly. When a function needs access\nto the outside world, give it the specific capability or environment\nreference it needs instead of assuming that access is always there.</p>\n</div>\n\nThis chapter covers the practical side of that model:\n\n- [Security](../security.md) explains why access is explicit.\n- [Environment](../environment.md) covers `env`, arguments, variables,\n  stdin, and terminal mode changes.\n\nUse this chapter when you need to:\n\n- read command line arguments\n- inspect or change environment variables\n- read from standard input\n- handle interactive terminal input\n- decide what authority a helper should receive\n\n<div class=\"advanced-content\">\n<p>Capability design is part of API design. When a helper takes a wide\nenvironment reference or a broad outside-world capability, that choice\nbecomes part of the helper's contract: callers must now trust it with\neverything that capability can do, not just the one operation the\ncurrent implementation happens to use.</p>\n\n<p>A narrower capability does more than look tidy. It limits authority,\nreduces the amount of code that must be audited when security matters,\nand makes substitution easier in tests or alternate runtimes. If a\nhelper only needs to open a TCP connection, that is the capability it\nshould receive. Anything wider increases coupling and makes accidental\nauthority leaks more likely over time.</p>\n</div>\n"
  },
  {
    "path": "docs/acton-guide/src/language/errors_exceptions.md",
    "content": "# Errors and exceptions\n\nUse exceptions when something is wrong and the current path should stop.\nRaise an exception with `raise`, and handle it with `try` and `except`.\n\n```python\ndef parse_port(text: str) -> int:\n    port = int(text)\n    if port < 0 or port > 65535:\n        raise ValueError(\"port must be between 0 and 65535\")\n    return port\n\nactor main(env):\n    for text in (\"8080\", \"70000\"):\n        try:\n            port = parse_port(text)\n        except ValueError as e:\n            print(\"invalid input:\", e)\n        else:\n            print(\"port:\", port)\n\n    env.exit(0)\n```\n\n<div class=\"beginner-content\">\n<p>Use an exception for a real error. If \"no result\" is expected and\nnormal, an optional value is often a better fit.</p>\n</div>\n\n## `try` structure\n\nA `try` statement can contain these parts:\n\n- `try` for the code that may fail\n- `except` for handling specific exception types\n- `else` for code that should run only when nothing failed\n- `finally` for cleanup that should happen either way\n\n```python\ntry:\n    value = parse_port(\"9000\")\nexcept ValueError as e:\n    print(\"bad input:\", e)\nelse:\n    print(\"ready to use:\", value)\nfinally:\n    print(\"done\")\n```\n\n`except` runs only for matching exceptions. `else` runs only when the\n`try` block completed without raising. `finally` runs whether the `try`\nblock succeeded or failed.\n\n<div class=\"beginner-content\">\n<p>Keep <code>try</code> blocks narrow so it stays obvious which\noperation can fail.</p>\n</div>\n\n<div class=\"advanced-content\">\n<p>Catch specific exceptions before broader ones, and keep exception\nhandling close to boundaries such as input parsing, file access, network\ncalls, and other integration points. Inside core logic, prefer domain\nvalues or optionals when the situation is expected rather than using\nexceptions as routine branching.</p>\n</div>\n"
  },
  {
    "path": "docs/acton-guide/src/language/expressions_operators.md",
    "content": "# Expressions and operators\n\nActon evaluates expressions to values. Operators combine values into new\nexpressions.\n\n## Common operators\n\n- Arithmetic: `+`, `-`, `*`, `/`, `//`, `%`, `**`\n- Comparison: `==`, `!=`, `<`, `<=`, `>`, `>=`\n- Boolean: `and`, `or`, `not`\n- Membership: `in`, `not in`\n\n```python\nactor main(env):\n    a = 10\n    b = 3\n    word = \"Acton\"\n    point = (3, 4)\n\n    print(\"sum:\", a + b)\n    print(\"product:\", a * b)\n    print(\"floor division:\", a // b)\n    print(\"remainder:\", a % b)\n    print(\"power:\", b ** 3)\n\n    print(\"comparison:\", a > b)\n    print(\"boolean:\", a > 0 and b > 0)\n    print(\"membership:\", \"ct\" in word)\n\n    print(\"indexing:\", word[0], point[1])\n    print(\"slicing:\", word[1:4])\n\n    env.exit(0)\n```\n\nMethod calls, function calls, indexing, and slicing are expressions too.\nThey all produce values.\n\n```python\nname = \"Acton\"\nfirst = name[0]\nupper = name.upper()\n```\n\n## Reading expressions\n\nRead an expression from the values upward. Start with the pieces that\nalready have values, then apply the operator or call.\n\n<div class=\"beginner-content\">\n<p>When reading an expression, start with the smallest parts that\nalready have values and then see how the operator or call combines them.\nIf you have to stop and think about precedence, add parentheses.</p>\n</div>\n\n## Precedence\n\nActon follows standard operator precedence rules. When in doubt, use\nparentheses to make intent explicit.\n\n```python\nx = 2 + 3 * 4      # 14\ny = (2 + 3) * 4    # 20\n```\n\n## Boolean logic\n\n`and` and `or` are useful when the right-hand side only makes sense if\nthe left-hand side has already passed a check.\n\n```python\nif user_is_known and user_is_enabled:\n    print(\"welcome\")\n```\n\n<div class=\"advanced-content\">\n<p><code>and</code> and <code>or</code> short-circuit. That means Acton\nonly evaluates the right-hand side when it is needed to determine the\nresult. That matters not just for speed, but for semantics: you can use\nshort-circuiting to guard operations that would otherwise fail or do\nunnecessary work. Calls, indexing, slicing, and later optional\noperations all participate in the same expression model.</p>\n\n```python\na = 0\n\nif a != 0 and 10 / a > 2:\n    print(\"large enough\")\n```\n</div>\n"
  },
  {
    "path": "docs/acton-guide/src/language/missing_values_failures.md",
    "content": "# Missing values and failures\n\nPrograms usually need to represent two different cases:\n\n- a value is genuinely absent\n- an operation failed and execution should stop or recover\n\nActon uses different tools for those cases. `None` and optional types\nmodel ordinary absence. Exceptions model failures.\n\n<div class=\"beginner-content\">\n<p>Use an optional when absence is part of the normal result. Use an\nexception when the operation could not finish as intended. A caller can\nbranch on an optional; an exception means the current path should stop\nunless it is explicitly handled.</p>\n</div>\n\nThere is no Rust-style `match` path for this in Acton. Use ordinary\nbranching, optional checks, and exception handling instead.\n\nStart here when you need to decide whether a function should return\n`None`, raise an exception, or let an expression keep propagating an\noptional result.\n\n<div class=\"advanced-content\">\n<p>Optional chaining and forced unwrapping are expression-level tools.\nThey do not replace the type system or exception handling; they make the\ncommon cases shorter. Keep absence in the type when it is expected, and\nreserve exceptions for broken assumptions, invalid input, and other\nfailures that should not be treated as routine control flow.</p>\n</div>\n\n- [Optionals and `None`](optionals_none.md) covers the basic meaning of\n  `None` and optional return values\n- [Optionals](../types/optionals.md) explains narrowing, optional\n  chaining, and forced unwrapping\n- [Errors and exceptions](errors_exceptions.md) covers `raise`,\n  `try`, `except`, `else`, and `finally`\n"
  },
  {
    "path": "docs/acton-guide/src/language/modeling_data_interfaces.md",
    "content": "# Modeling data and interfaces\n\nOnce functions and collections stop expressing a problem clearly, you\nusually need a more explicit model.\n\nIn Acton, that usually means moving through a simple progression:\n\n- tuples for small anonymous values\n- named tuples for small structured values with readable fields\n- classes for values with methods or invariants\n- protocols for shared behavior across unrelated types\n\n<div class=\"beginner-content\">\n<p>Start with a tuple when the value is small and anonymous. Move to a\nnamed tuple when the shape deserves field names but not behavior. Move\nto a class when the data needs methods, a constructor, or rules that\nshould stay close to the value. Use a protocol when the real question\nis whether several different types can be used in the same place.</p>\n</div>\n\nUse this section when you need to decide how a domain concept should be\nrepresented, how an object becomes valid, and how different types can\nshare the same behavior without sharing the same class.\n\n<div class=\"advanced-content\">\n<p>Classes and protocols solve different problems. Classes define the\nshape and lifecycle of a value. Protocols define an observed interface\nthat multiple concrete types can satisfy. That choice affects API shape,\ninitialization, dispatch, and type inference, not just code\norganization.</p>\n</div>\n\n- [Tuples](../primitives/tuples.md)\n- [Classes and objects](../classes/intro.md)\n- [Protocols](../protocols/intro.md)\n"
  },
  {
    "path": "docs/acton-guide/src/language/optionals_none.md",
    "content": "# Optionals and `None`\n\n`None` is the value Acton uses for \"nothing here\".\n\nAn optional type `?T` means a value is either a `T` or `None`.\nUse an optional when absence is part of the normal result.\n\n<div class=\"beginner-content\">\n<p>`?str` means \"a string or <code>None</code>\". `?int` means \"an\ninteger or <code>None</code>\". The `?` belongs to the type, not the\nvalue.</p>\n</div>\n\n```python\ndef lookup_name(users: dict[str, str], username: str) -> ?str:\n    if username in users:\n        return users[username]\n    return None\n\nactor main(env):\n    users = {\"alice\": \"Alice Andersson\"}\n\n    name = lookup_name(users, \"bob\")\n    if name is not None:\n        print(\"Found:\", name)\n        print(\"Upper:\", name.upper())\n    else:\n        print(\"No match\")\n\n    env.exit(0)\n```\n\nUse `is None` and `is not None` to check whether an optional is\npresent. When you want to use the value as non-optional, put that code\ninside the `is not None` branch.\n\n<div class=\"beginner-content\">\n<p>Write the check in the direction of the code that needs the value.\nDo not rely on an <code>if name is None</code> / <code>else</code>\nshape to make <code>name</code> non-optional in the <code>else</code>\nbranch.</p>\n</div>\n\nOptional values are common in lookups, parsing, and APIs that may or\nmay not find a result. `None` is not a general placeholder for every\nkind of empty value; use it when absence itself matters.\n"
  },
  {
    "path": "docs/acton-guide/src/language/organizing_code.md",
    "content": "# Organizing code\n\nAs a program grows, you need more than a single file full of functions.\nThe goal is not to create a deep tree of files. The goal is to make the\ncode easier to read, change, and import.\n\n<div class=\"beginner-content\">\n<p>Start by grouping related code together, then split it when it begins\nto serve more than one purpose. A practical first cut is often one\nmodule for parsing, one for domain logic, and one for I/O or startup\ncode. Keep local modules, project metadata, and external dependencies\nin one clear path rather than treating them as separate puzzles.</p>\n\n<p>You do not need a deep hierarchy early on. Small modules with clear\nnames are usually easier to work with than a large set of thin files\nwith vague responsibilities.</p>\n</div>\n\nThis section connects the local source tree, the project file, and the\npackage graph. Use it together with [Projects](../projects.md) and\n[Package Management](../package_management.md).\n\n<div class=\"advanced-content\">\n<p>In Acton, a module boundary is more than a foldering choice. Because\nmodule-level bindings are constant, a module behaves much more like a\nnamespace and API surface than like an object with hidden mutable\nruntime state. That means a good split changes both how people read the\nprogram and how the compiler sees it.</p>\n\n<p>A coherent module split narrows imports, isolates reasons to change,\nand makes the public surface smaller. It also improves the mechanical\nside of the toolchain: discovery, type checking, caching, and API\ndocumentation all work in terms of modules. Once a file becomes a real\nboundary that other code imports on purpose, its top-level names and\ndocstrings stop being decoration and start becoming part of the module's\ninterface.</p>\n</div>\n\nThis section is about the everyday structure around your code:\n\n- how to split code into modules\n- how to import names\n- how naming conventions make code easier to read\n\nRead next:\n\n- [Modules](../modules.md)\n- [Projects](../projects.md)\n- [Package Management](../package_management.md)\n- [Naming](../naming.md)\n"
  },
  {
    "path": "docs/acton-guide/src/language/state_concurrency.md",
    "content": "# Actors & concurrency\n\nActors are the center of Acton's model for mutable state and\nconcurrency. If you want to understand how Acton programs stay\nstructured as they grow, start here.\n\n<div class=\"beginner-content\">\n<p>Start with the basic <code>actor main(env)</code> pattern. The core\nmodel is simple: an actor owns state, handles one message at a time,\nand communicates with other actors by calling their methods.</p>\n</div>\n\nThis is also the closest Acton replacement for Rust-style lifetime\nthinking: actors own mutable state, capability references are passed\nexplicitly, and the runtime manages ordinary object lifetime.\n\n<div class=\"advanced-content\">\n<p>The important guarantee is local seriality: within one actor, state\nchanges are observed as if messages were handled one at a time. That is\nwhy <code>var</code> can hold mutable state without introducing the kind\nof shared-memory races that make threaded code hard to reason about.\nThe actor boundary is doing real work here: mutation stays local, while\nconcurrency appears only in the relationships between actors.</p>\n\n<p>Viewed that way, many Acton features are the same model in different\nforms. Sync and async calls, <code>await</code>, delayed callbacks with\n<code>after</code>, and lifecycle hooks all control when new work is\nplaced into an actor's mailbox and when another actor is allowed to make\nprogress. What Acton does not promise is one global timeline across the\nwhole program. Ordering is local to each actor unless your own protocol\nestablishes something stronger.</p>\n</div>\n\nThis section covers:\n\n- how actors own state and methods\n- how the root actor starts a program\n- how actors talk to each other\n- how delayed work and cleanup fit into actor code\n- how concurrency works without shared mutable memory\n\nRead these pages next:\n\n- [Actors](../actors.md)\n- [Root Actor](../actors/root.md)\n- [Lifetime](../actors/lifetime.md)\n- [Attributes](../actors/attributes.md)\n- [`self`](../actors/self.md)\n- [Actor methods](../functions/actor_methods.md)\n- [Sync Method calls](../actors/sync_method_call.md)\n- [Async Method calls](../actors/async_method_call.md)\n- [Control flow in an async actor world](../control_flow/actors.md)\n- [after / sleep](../control_flow/after_sleep.md)\n- [Concurrency](../actors/concurrency.md)\n- [Cleanup](../actors/cleanup.md)\n\nEffect annotations such as `pure`, `mut`, `proc`, and `action` are\ndocumented under [Working with types](../types/effects.md).\n"
  },
  {
    "path": "docs/acton-guide/src/language.md",
    "content": "# Language\n\nThis chapter is the core language guide and reference.\n\nIt is organized around common programming tasks rather than around a\ntaxonomy of language features. The early sections are the things most\npeople need first. The later sections go deeper into Acton-specific\nparts of the language such as actors, concurrency, and capabilities.\n\n## What to read first\n\nIf you are new to Acton, read in this order:\n\n1. [Common programming concepts](language/common_programming_concepts.md)\n2. [Collections and everyday data](collections.md)\n3. [Missing values and failures](language/missing_values_failures.md)\n4. [Modeling data and interfaces](language/modeling_data_interfaces.md)\n5. [Organizing code](language/organizing_code.md)\n6. [Working with types](types/intro.md)\n7. [Actors & concurrency](language/state_concurrency.md)\n8. [Environment and capabilities](language/environment_capabilities.md)\n\n## How to use this chapter as reference\n\n- Use the book's search when you want to find a specific feature,\n  keyword, or builtin quickly. This chapter is organized for reading and\n  programming tasks, not as a strict feature index.\n- Use section landing pages for overview.\n- Use subpages for details and examples.\n- Use the beginner and advanced callouts to choose the level of detail\n  you need.\n- For runtime and tooling behavior, see the chapters after Language\n  (Testing, Build System, Package Management, and RTS).\n"
  },
  {
    "path": "docs/acton-guide/src/modules.md",
    "content": "# Modules\n\nModules let you split a program into smaller named units. In a project,\nmodules live under `src/`, and subdirectories become part of the module\nname. For example, `src/a/b.act` is imported as `import a.b`.\n\nSee [Projects](projects.md) for how `acton build` discovers those files\nand [Package Management](package_management.md) for external\ndependencies that live alongside local modules.\n\nUse modules to group code by responsibility. A good module has a clear\njob. For example:\n\n- parsing and validation\n- domain logic and shared types\n- I/O, network access, or other side effects\n- startup and orchestration\n\n<div class=\"beginner-content\">\n<p>Start with one module per clear topic. If a file starts mixing\nunrelated ideas, move one topic into its own module. Keep the project\ntree and the module tree aligned so the file layout stays easy to\nfollow.</p>\n</div>\n\n## Import forms\n\nUse `import` when you want the module name itself:\n\n- `import time`\n- `import time as timmy`\n\nUse `from ... import ...` when you want specific names directly:\n\n- `from time import now`\n- `from time import now as rightnow`\n\n```python\nimport time\nimport time as timmy\nfrom time import now\nfrom time import now as rightnow\n\nactor main(env):\n    print(time.now())\n    print(timmy.now())\n    print(now())\n    print(rightnow())\n\n    env.exit(0)\n```\n\n<div class=\"beginner-content\">\n<p>Keep imports explicit, and use aliases only when they improve\nreadability or avoid a name clash.</p>\n</div>\n\n## Module-level code\n\nModule-level names are constants. Mutable program state belongs in\nactors, not in modules.\n\nThat means:\n\n- helper functions and constants fit naturally at module level\n- mutable variables do not\n- program startup logic should live in actors such as `main`\n\n```python\ndefault_timeout = 5\n\ndef timeout_seconds():\n    return default_timeout\n```\n\n<div class=\"advanced-content\">\n<p>Modules can also carry docstrings. Because module-level bindings are\nconstant, importing a module is closer to importing a namespace of\ndefinitions than shared mutable runtime state.</p>\n\n<p>That is why module boundaries work best when they are stable and\npurposeful. Prefer names that explain the boundary directly, and keep\nthe module surface small unless the file is intentionally acting as a\npublic API.</p>\n</div>\n\n## How to split code\n\nSplit a module when it starts doing too many different jobs.\n\nGood reasons to make a new module include:\n\n- a group of functions is reused from several places\n- a feature has a clear boundary, such as `parser`, `storage`, or\n  `protocol`\n- one part of the code changes for different reasons than the rest\n- the file has grown enough that imports and names are hard to scan\n\nAvoid creating modules just to make a tree look deep. A short, direct\nmodule path is usually easier to work with than a very fine-grained one.\n"
  },
  {
    "path": "docs/acton-guide/src/naming.md",
    "content": "# Naming\n\nActon has naming rules and conventions. Some are enforced by the\ncompiler, and some are conventions that keep larger programs readable.\n\n## Functions\n\nUse lower-case words with `_` between them.\n\n- `parse_user`\n- `load_config`\n- `send_report`\n\nFunction names should describe what the function does.\n\n## Actors and classes\n\nUse `PascalCase` with two or more alphanumeric characters.\n\n- `HttpServer`\n- `OrderBook`\n- `FileCache`\n\nDo not use a single upper-case letter for a class or actor name. Those\nnames are reserved for type variables.\n\n## Type variables\n\nType variables use a single upper-case letter, optionally followed by\ndigits.\n\n- `A`\n- `T1`\n\nUse them for generic code, not for ordinary domain concepts. If a name\ndescribes a real thing in the program, make it a normal type or actor\nname instead.\n\n## Modules and files\n\nModule names come from file paths, so filename choice matters. Use\nshort, lower-case names and let the import path reflect the structure of\n`src/`. For example, `src/a/b.act` is imported as `import a.b`.\n\nNaming is part of API design. In Acton, a module name, an imported\nsymbol, and a type name often appear together, so keeping them short and\npredictable reduces noise in the code. This matters even more once a\nproject has several modules and cross-module dependencies.\n\n## Private names\n\nA leading `_` is the usual marker for implementation details that\nshould not be treated as part of the public surface. Use it for names\nthat are only meant to be used inside one module or actor.\n\n## Practical guidance\n\n<div class=\"beginner-content\">\n<p>Good names make code easier to split into modules, and they make\nimports easier to read. If a name feels awkward at the call site, it is\nusually worth changing before the code grows.</p>\n</div>\n\n- Prefer names that describe what a thing is or does.\n- Use the same word for the same concept across modules.\n- Avoid abbreviations unless they are standard in your domain.\n- Make helper names specific enough that call sites read naturally.\n"
  },
  {
    "path": "docs/acton-guide/src/package_management.md",
    "content": "# Package Management\n\n`acton` offers integrated package management for adding library dependencies to\na project and installing application packages as local tools. Dependencies are\nautomatically fetched and validated at build time; applications are built from\nsource before their binaries are installed.\n\nActon pins dependencies by content, via a content hash, rather than by mutable\npackage version labels. Therefore, builds are entirely deterministic so that the\nsame compilation result can be reproduced on another machine.\n\nThe guiding principle behind Acton's package management is to strive for\ndeterminism, robustness, and safety. Dependencies are resolved at design time by\nthe package developer and written into `Build.act` as archive URLs plus content\nhashes. Later builds fetch those recorded archives and verify the hashes; they\ndo not pick newer compatible versions or rely on a name to mean the same thing\nforever.\n\nActon's public package index is a discovery index. Packages are hosted\nby their owners, and dependencies are recorded as URLs from which a\nspecific package archive can be downloaded. This is typically a tar.gz\nor zip archive from GitHub, GitLab, or a similar source hosting site.\nThe index helps find packages; `Build.act` records the exact archive and\nhash used by a project.\n\nThe public index is decentralized in the sense that package authors opt\nin from their own GitHub repositories. The index collects repositories\ntagged with an `acton-library` or `acton-app` topic and records their\nmetadata for search and resolution. `acton pkg` commands work with\nlibrary packages only: `acton pkg search` shows libraries and\n`acton pkg add` resolves libraries as dependencies. App packages are\ninstalled with `acton install`, which builds the selected repository in\nrelease mode and copies its binaries into `~/.acton/bin`. Install\nmanifests are kept under `~/.acton` so Acton can track which package owns\neach installed binary and remove those binaries again with\n`acton uninstall`.\n\nAll dependencies are fetched and included, linked statically, at compile time,\nso there are no runtime dependencies.\n\n## Project lineage fingerprint\n\nEach project must declare a **fingerprint** in `Build.act` to represent its lineage — the stable identity of the project across versions. This is separate from dependency content hashes:\n\n- Content hashes identify a specific version of a dependency.\n- Fingerprints identify the project itself and help Acton deduplicate dependencies and generate consistent build metadata.\n\nExample:\n```python\nname = \"myproject\"\nfingerprint = 0x1234abcd5678ef00\n```\n\n**How it behaves today**\n- `name` and `fingerprint` are required in every project.\n- Acton validates that the fingerprint matches the name’s lineage prefix.\n- If they don’t match or either is missing, the build fails with guidance on how to fix it.\n\nRenaming a project breaks lineage, so generate a new fingerprint for the new name. When you fork a project, also generate a new fingerprint so the fork has its own lineage.\n"
  },
  {
    "path": "docs/acton-guide/src/pkg/add_dependency.md",
    "content": "# Add Dependency\n\nAdd a dependency to your project by using `acton pkg add`. The usual\nflow is to refresh the public package index first:\n\n```console\nacton pkg update\n```\n\nThen add the dependency by package name:\n\n```console\nacton pkg add foo\n```\n\nYou can also provide a GitHub repository URL directly. The first\nargument is still the local dependency name:\n\nIn this case we add the example `foo` package as a dependency.\n```console\nacton pkg add foo --repo-url https://github.com/actonlang/foo --repo-ref main\n```\n\nThis will fetch the dependency and add it to the `dependencies` block in `Build.act`, resulting in something like:\n```python\ndependencies = {\n  \"foo\": (\n        repo_url=\"https://github.com/actonlang/foo\",\n        repo_ref=\"main\",\n        url=\"https://github.com/actonlang/foo/archive/0123456789abcdef0123456789abcdef01234567.zip\",\n        hash=\"1220cd47344f8a1e7fe86741c7b0257a63567b4c17ad583bddf690eedd672032abdd\",\n    ),\n}\n\nzig_dependencies = {}\n```\n\n```admonish\nIt is possible to edit `Build.act` by hand, but adding dependencies requires filling in the `hash` field, which is somewhat tricky.\n```\n\nThe `foo` package provides a single `foo` module with a `foo` function (that appropriately returns `foo`). We can now access it from our main actor:\n\n```python\nimport foo\n\nactor main(env):\n    print(foo.foo())\n    env.exit(0)\n```\n"
  },
  {
    "path": "docs/acton-guide/src/pkg/fetch_dependencies.md",
    "content": "# Fetch Dependencies / Enable Airplane Mode\n\nYou can fetch all the dependencies of a project by using `acton fetch`. It will download the dependencies specified in `Build.act` to the cache.\n\n`acton fetch` enables you to work offline (a.k.a **airplane mode**).\n"
  },
  {
    "path": "docs/acton-guide/src/pkg/fingerprint.md",
    "content": "# Fingerprint and lineage\n\nEach Acton project must declare a **fingerprint** in `Build.act`. The fingerprint represents the project’s **lineage** — a stable identity that stays the same across releases of the same project.\n\n```python\nname = \"myproject\"\nfingerprint = 0x1234abcd5678ef00\n```\n\n## What the fingerprint is\n\n- A 64-bit hex value (`0x...`).\n- The upper 32 bits are derived from the project name.\n- The lower 32 bits are random.\n- Acton uses this lineage to deduplicate dependencies and to generate consistent build metadata.\n\n## Rename vs fork\n\nRenaming a project breaks lineage, so generate a new fingerprint for the new name.\nForking a project also creates a new lineage, so generate a fresh fingerprint.\n\nIf Acton detects a mismatch, it will fail the build and tell you to generate a new fingerprint for the name.\n\n## Current behavior\n\n- `name` and `fingerprint` are required in every project.\n- Acton validates the lineage prefix derived from the name.\n- Missing or mismatched values fail the build with guidance.\n"
  },
  {
    "path": "docs/acton-guide/src/pkg/local_dependencies.md",
    "content": "# Local Dependencies\n\nIt is possible to use dependencies available via a local file system path by setting the `path` attribute. Edit `Build.act` and add or modify an existing dependency. Set the `path` attribute to a relative path, e.g.:\n\n```python\ndependencies = {\n  \"foo\": (\n        path=\"../foo\"\n    ),\n  \"local_lib\": (\n        path=\"deps/local_lib\"\n    ),\n}\n\nzig_dependencies = {}\n```\n\nThese are best used for dependencies located within the same git repository or similar. All users need to have the same relative path to the dependency so if the paths stretch over multiple repositories, the user needs to keep the paths aligned.\n\n```admonish\nYou can temporarily override the path to a dependency through the `--dep` argument, e.g. `acton build --dep foo=../foo`. This can be useful to fork a library and make local modifications to it before submitting them back upstream.\n```\n"
  },
  {
    "path": "docs/acton-guide/src/pkg/override_dependency.md",
    "content": "# Override the path to a dependency\n\nThe configuration in `Build.act` sets the path or url that is normally used for a dependency. It is possible to temporarily override the path through the `--dep` argument to `acton build`.\n\nLet's say we have the following configuration:\n\n```python\ndependencies = {\n  \"foo\": (\n        url=\"https://github.com/actonlang/foo/archive/refs/tags/v1.0.zip\",\n        hash=\"1220cd47344f8a1e7fe86741c7b0257a63567b4c17ad583bddf690eedd672032abdd\",\n    ),\n}\n\nzig_dependencies = {}\n```\n\nNow we want to make some modifications to the `foo` library, so we clone it to a local path. We can now build our project using `acton build --dep foo=../foo` to temporarily override the `foo` dependency to use the path `../foo` instead of the url in the configuration.\n"
  },
  {
    "path": "docs/acton-guide/src/pkg/package_index.md",
    "content": "# Package Index\n\nThe public package index is built from GitHub repository topics. A\nrepository can opt in as a library, an app, or both. The generated\nindex records this as a `kinds` list:\n\n- `acton-library` marks an importable library package.\n- `acton-app` marks an installable application package.\n\nUse `acton-library` for packages that other projects import and add as\ndependencies. These are the only packages used by `acton pkg add` and\nshown by `acton pkg search`.\n\nUse `acton-app` for projects that produce executable tools. App packages\nare installed with `acton install`, which builds the selected repository\nand copies its binaries into `~/.acton/bin`.\n\nAdd both topics when a repository provides useful importable modules and\nalso builds executable tools. `acton pkg` still uses only the library\nentry for dependency resolution.\n\n## Add your package\n\nTo have a package discovered by the public index:\n\n1. Put `Build.act` at the root of the repository.\n2. Declare the mandatory `name` and `fingerprint` fields in `Build.act`.\n3. Publish the repository on GitHub.\n4. Add the `acton-library` topic, the `acton-app` topic, or both.\n\nAfter the public index has refreshed, users can update their local copy:\n\n```console\nacton pkg update\n```\n\nLibraries can then be found with:\n\n```console\nacton pkg search PACKAGE\n```\n\nand added as dependencies with:\n\n```console\nacton pkg add PACKAGE\n```\n\nApps can be installed with:\n\n```console\nacton install PACKAGE\n```\n\nand removed with:\n\n```console\nacton uninstall PACKAGE\n```\n"
  },
  {
    "path": "docs/acton-guide/src/pkg/remove_dependency.md",
    "content": "# Remove Dependency\n\nYou can remove a dependency from your project with `acton pkg remove`:\n\n```console\nacton pkg remove foo\n```\n"
  },
  {
    "path": "docs/acton-guide/src/primitives/complex.md",
    "content": "# Complex numbers\n\nComplex numbers combine a real part and an imaginary part.\n\nCreate them with `complex.from_real_imag(real, imag)`.\n\n<div class=\"beginner-content\">\n<p>If you have not used complex numbers before, think of them as two\nfloating-point values with arithmetic rules built in. Most programs do\nnot need them, but they are useful in math-heavy domains.</p>\n</div>\n\n```python\nactor main(env):\n    a = complex.from_real_imag(1.0, 2.0)\n    b = complex.from_real_imag(3.0, 4.0)\n\n    print(\"sum:\", a + b)\n    print(\"product:\", a * b)\n    print(\"real part:\", a.real())\n    print(\"imag part:\", a.imag())\n    print(\"conjugate:\", a.conjugate())\n    print(\"magnitude:\", abs(a))\n\n    env.exit(0)\n```\n\n## Arithmetic\n\nComplex numbers support the usual arithmetic operations:\n\n- `+` and `-`\n- `*`\n- `/`\n- `**`\n\nThey also support equality testing with `==` and `!=`.\n\n```python\na = complex.from_real_imag(1.0, 2.0)\nb = complex.from_real_imag(1.0, 2.0)\n\nprint(a == b)\n```\n\n<div class=\"advanced-content\">\n<p>Complex numbers are part of Acton's numeric world and work with the\nsame floating-point realities as <code>float</code>: rounding and\nprecision limits still matter. Any algorithm that wants a notion of\nordering has to state it explicitly, such as by comparing magnitude,\nrather than relying on the usual ordered-number intuition.</p>\n</div>\n\n## Errors\n\nDivision by zero raises `ZeroDivisionError`.\n\n```python\nzero = complex.from_real_imag(0.0, 0.0)\n# a / zero\n```\n"
  },
  {
    "path": "docs/acton-guide/src/primitives/float.md",
    "content": "# Floating-point numbers\n\n`float` is Acton's 64-bit floating-point type.\n\nUse it for values with a fractional part, such as measurements, ratios,\nand scientific calculations.\n\n<div class=\"beginner-content\">\n<p>A decimal point usually means a <code>float</code> literal. Use\nfloats for measurements and ratios, and do not be surprised by small\nrounding artifacts in the last digits.</p>\n</div>\n\n```python\nactor main(env):\n    distance = 12.5\n    time = 4.0\n    speed = distance / time\n\n    print(\"speed:\", speed)\n    print(\"rounded:\", round(speed, 2))\n    print(\"formatted: %.2f\" % speed)\n\n    env.exit(0)\n```\n\nFloating-point arithmetic is approximate, not exact.\n\n```python\na = 0.1\nb = 0.2\nprint(a + b)\n```\n\n<div class=\"advanced-content\">\n<p>Floats trade exactness for range and speed. They are usually the\nright tool for physical measurements and approximate calculations, but\nnot for values where exact decimal behavior is required. Equality on\ncomputed floats is often brittle, so treat exact comparison with care\nonce values have gone through prior arithmetic.</p>\n</div>\n"
  },
  {
    "path": "docs/acton-guide/src/primitives/integers.md",
    "content": "# Integers\n\nIntegers are whole numbers such as `0`, `42`, and `-7`.\n\nActon has three groups of integer types:\n\n- `int` for the normal 64-bit signed integer type\n- `bigint` for integers that must grow beyond the `int` range\n- explicitly sized signed and unsigned integers such as `i32` and `u16`\n\n`bigint` lets values grow arbitrarily large ensuring correct program behavior\nwhen you are uncertain about the exact size needed. However, as `bigint` is\nsignificantly slower than the bounded integer types, do not default to `bigint`\nout of convenience.  For the vast majority of normal use cases, `int` is large\nenough and considerably faster. Use exact-width integers when you specifically\nneed their bit width.\n\n<div class=\"advanced-content\">\n<p>Bounded integer types can often be compiled in an unboxed form, which avoids\nboxing overhead and can make arithmetic much faster, several orders of\nmagnitude, than <code>bigint</code> in tight code. That is another reason to\nprefer <code>int</code> or an exact-width integer when the bounded range is the\nright fit, and reserve <code>bigint</code> for values that truly need arbitrary\nprecision.</p>\n</div>\n\n<div class=\"beginner-content\">\n<p>If you are not sure which integer type to use, start with\n<code>int</code>. Move to <code>bigint</code> when values may get very\nlarge, and use the exact-width types when you need to match a protocol,\nfile format, or external API.</p>\n</div>\n\n<table>\n    <tr>\n        <th>Type</th>\n        <th>Min</th>\n        <th>Max</th>\n    </tr>\n    <tr>\n        <td><pre>i8</pre></td>\n        <td>-128</td>\n        <td>127</td>\n    </tr>\n    <tr>\n        <td><pre>i16</pre></td>\n        <td>-32768</td>\n        <td>32767</td>\n    </tr>\n    <tr>\n        <td><pre>i32</pre></td>\n        <td>-2147483648</td>\n        <td>2147483647</td>\n    </tr>\n    <tr>\n        <td><pre>u1</pre></td>\n        <td>0</td>\n        <td>1</td>\n    </tr>\n    <tr>\n        <td><pre>u8</pre></td>\n        <td>0</td>\n        <td>255</td>\n    </tr>\n    <tr>\n        <td><pre>u16</pre></td>\n        <td>0</td>\n        <td>65535</td>\n    </tr>\n    <tr>\n        <td><pre>u32</pre></td>\n        <td>0</td>\n        <td>4294967295</td>\n    </tr>\n    <tr>\n        <td><pre>u64</pre></td>\n        <td>0</td>\n        <td>18446744073709551615</td>\n    </tr>\n    <tr>\n        <td><pre>int</pre></td>\n        <td>-9223372036854775808</td>\n        <td>9223372036854775807</td>\n    </tr>\n    <tr>\n        <td><pre>bigint</pre></td>\n        <td>arbitrary</td>\n        <td>arbitrary</td>\n    </tr>\n</table>\n\n## Basic use\n\n```python\nactor main(env):\n    count = 42\n    port = u16(5000)\n    huge = bigint(123456789012345678901234567890)\n\n    print(\"count:\", count)\n    print(\"port:\", port)\n    print(\"huge:\", huge)\n    print(\"widened:\", int(port))\n\n    env.exit(0)\n```\n\nUse `int` for everyday counting and arithmetic. Use `bigint` when a\nvalue may exceed the normal machine-sized range. Use exact-width types\nwhen the bit pattern matters.\n\n## Converting integers\n\nConvert by calling the target type as a constructor.\n\n```python\nint(42)\nbigint(42)\nu16(255)\n```\n\nWidening to a larger type is straightforward:\n\n```python\nsmall = u16(255)\nwidened = int(small)\n```\n\nConverting to a narrower type checks that the value fits:\n\n```python\nsafe = u16(12345)\n# u16(70000) would raise ValueError\n```\n\n<div class=\"advanced-content\">\n<p>Large integer literals are inferred by size. Values above the normal\n<code>int</code> range may infer as <code>u64</code> or\n<code>bigint</code>. When you care about the exact type, annotate it or\nuse an explicit constructor.</p>\n</div>\n"
  },
  {
    "path": "docs/acton-guide/src/primitives/scalars.md",
    "content": "# Scalars\n"
  },
  {
    "path": "docs/acton-guide/src/primitives/tuples.md",
    "content": "# Tuples\n\nTuples group a fixed number of values into one value.\n\nThe fields in a tuple can have different types.\n\nA tuple is a good first step for a small value with a fixed shape.\nWhen the shape needs names but still behaves like plain data, use a\nnamed tuple. When the value needs methods, invariants, or a lifecycle,\nmove to a class.\n\n<div class=\"beginner-content\">\n<p>A tuple has a fixed shape. If you need a small value with exactly two\nor three fields, a tuple is often a good fit. If you keep forgetting\nwhat <code>.0</code> and <code>.1</code> mean, switch to a named tuple\nso the fields explain themselves. If the data starts needing methods or\nconstruction rules, switch to a class.</p>\n</div>\n\n```python\nactor main(env):\n    pair = (\"Ada\", 36)\n    point = (x=3, y=4)\n\n    print(pair.0)\n    print(pair.1)\n    print(point.x)\n    print(point.y)\n\n    env.exit(0)\n```\n\nAccess positional tuple fields with `.0`, `.1`, and so on.\n\nNamed tuples use field names such as `.x` and `.y`.\n\n## Returning tuples from functions\n\nTuples are handy when a function naturally returns a small fixed group\nof values.\n\n```python\ndef parse_result():\n    return (ok=True, code=200)\n```\n\nActon can infer the tuple shape here from the returned value.\n\n<div class=\"advanced-content\">\n<p>Named tuples are the bridge between raw tuple positions and classes.\nThey keep the value lightweight while making the shape self-documenting.\nBecause the tuple shape is part of the type, changing field count or\nnames is an API change.</p>\n</div>\n"
  },
  {
    "path": "docs/acton-guide/src/primitives.md",
    "content": "# Built-in types and literals\n\nEvery value in Acton has a type.\n\nMany values can be written directly in source code. These are called\n*literals*.\n\n<div class=\"beginner-content\">\n<p><code>42</code>, <code>True</code>, and <code>\"hello\"</code> are all\nliterals: the value is written directly in the program instead of being\ncomputed somewhere else.</p>\n</div>\n\n## Common built-in types\n\n| Type | Example | Notes |\n| --- | --- | --- |\n| `int` | `42` | 64-bit signed integer |\n| `bigint` | `123456789012345678901234567890` | arbitrary-precision integer |\n| `i8`, `i16`, `i32`, `u1`, `u8`, `u16`, `u32`, `u64` | `u16(42)` | explicitly sized integers |\n| `float` | `3.14` | 64-bit floating-point number |\n| `complex` | `complex.from_real_imag(1.0, 2.0)` | complex number |\n| `bool` | `True` | `True` or `False` |\n| `str` | `\"hello\"` | Unicode text |\n| tuple | `(1, \"two\")` | fixed-size group of values |\n\n```python\nactor main(env):\n    whole = 42\n    huge = bigint(123456789012345678901234567890)\n    ratio = 3.5\n    truth = True\n    name = \"Acton\"\n    point = (x=3, y=4)\n    z = complex.from_real_imag(2.0, 3.0)\n\n    print(whole, huge, ratio, truth, name, point, z)\n    env.exit(0)\n```\n\n<div class=\"advanced-content\">\n<p>Integer literals are not all the same internally. Small whole-number\nliterals usually fit in <code>int</code>, while very large literals may\nneed <code>u64</code> or <code>bigint</code>. If the exact type matters,\nwrite it explicitly.</p>\n</div>\n\n## Choosing a type\n\nUse:\n\n- `int` for ordinary whole numbers\n- `bigint` when whole numbers may grow beyond the normal `int` range\n- `float` for fractional values\n- `bool` for yes/no conditions\n- `str` for text\n- tuples for small fixed-size groups of values\n\nReach for fixed-size integers when width or sign matters, and for\n`complex` when you need real and imaginary parts together.\n\nLists, dictionaries, and sets are covered in [Collections](collections.md).\n\n## More detail\n\n- [Integers](primitives/integers.md)\n- [Floating-point numbers](primitives/float.md)\n- [Complex numbers](primitives/complex.md)\n- [Tuples](primitives/tuples.md)\n"
  },
  {
    "path": "docs/acton-guide/src/projects/directory_structure.md",
    "content": "# Project directory structure\n\nThe directory layout of an Acton project follows a certain structure.\n\n```\n.\n├── Build.act\n├── out\n│   ├── bin\n│   │   └── foo\n│   └── types\n│       ├── foo.c\n│       ├── foo.h\n│       ├── foo.root.c\n│       └── foo.ty\n├── README.md\n└── src\n    └── foo.act\n```\n\nA `Build.act` file and the `src/` directory must be present in the project\nroot, otherwise it is not considered a project.\n\n`src/` is used for all source files of the project. Use subdirectories to create\nhierarchies of modules, for example `src/a/b.act` is imported in an Acton\nprogram as `import a.b`.\n\nOutput goes into `out/`, most importantly, executable binaries are placed in\n`out/bin`. The name of the binary is the name of the module which contains the\nspecified root actor.  In the example above, the root actor is `foo.main`, i.e.\nactor `main` in the module `foo` and consequently, the executable name is `foo`.\n\n`out/types` contains internal compiler output. In particular, `.ty` files are\ncached typed-module interfaces and `.c` / `.h` files are generated code derived\nfrom them. Acton validates and regenerates these files as needed, so they\nshould be treated as internal build artifacts. Don't touch them. All other\noutput files, like object files and archives, are placed out-of-tree in the\ncache directory (`~/.cache/acton/`).\n"
  },
  {
    "path": "docs/acton-guide/src/projects.md",
    "content": "# Acton Projects\n\nBesides compiling individual `.act` files, it is possible to organize Acton code into an **Acton Project**, which is suitable once you have more than one `.act` source code file.\n\nUse `acton` to create a new project called `foo`:\n```console\nacton new foo\n```\n\nOutput:\n```console\nCreated project foo\nEnter your new project directory with:\n  cd foo\nCompile:\n  acton build\nRun:\n  ./out/bin/foo\n```\n\n## Description\n\nUse `acton build` to build a project. The current working directory\nmust be the project directory or a sub-directory to the project\ndirectory. `acton` will discover all source files and compile them\naccording to dependency order.\n\nAdd a `main` actor to any source file directly under `src/` to produce an executable binary. For example, if `src/hello.act` contains a `main` actor, it will produce `out/bin/hello` using `main` as the root actor.\n\nProjects and modules work together: `src/` defines the local module\ntree, while `Build.act` defines the project identity and its external\ndependencies. See [Modules](modules.md) for local source layout and\n[Package Management](package_management.md) for remote dependencies and\noverride behavior.\n\n## Build configuration and lineage\n\nProjects must include a `Build.act` file. Two common fields are `name` and `fingerprint`, where the fingerprint captures the project’s **lineage**:\n\n```python\nname = \"hello\"\nfingerprint = 0x1234abcd5678ef00\n```\n\n`name` and `fingerprint` are required for Acton projects. Acton validates that the fingerprint matches the name’s lineage prefix. A mismatch indicates a rename or a fork, so the build fails and tells you to generate a new fingerprint for the new name. If either field is missing, the build fails with guidance to add it.\n"
  },
  {
    "path": "docs/acton-guide/src/protocols/dispatch.md",
    "content": "# Protocol method dispatch\n\nProtocol dispatch is about choosing which protocol implementation to\nuse.\n\nFor ordinary class methods, the answer is usually the method on the\nactual class. For protocol methods, the result depends on the type the\nprogram is observing at that point.\n\nHere are two classes, the base class `Point` and the derived class\n`Point3D`. Both implement `Eq`.\n\n```python\nclass Point(object):\n    def __init__(self, x: int, y: int):\n        self.x = x\n        self.y = y\n\nextension Point (Eq):\n    def __eq__(self, other):\n        return self.x == other.x and self.y == other.y\n\nclass Point3D(Point):\n    def __init__(self, x: int, y: int, z: int):\n        self.x = x\n        self.y = y\n        self.z = z\n\nextension Point3D (Eq):\n    def __eq__(self, other):\n        return self.x == other.x and self.y == other.y and self.z == other.z\n\ndef comparator(a: Point, b: Point) -> bool:\n    return a == b\n\nactor main(env):\n    p1 = Point3D(1, 2, 3)\n    p2 = Point3D(1, 2, 4)\n\n    print(p1 == p2)\n\n    print(comparator(p1, p2))\n\n    env.exit(0)\n```\n\nThe first comparison uses `Point3D` as the observed type, so it uses the\n`Eq` implementation for `Point3D`.\n\nThe second comparison goes through `comparator(a: Point, b: Point)`, so\nthe observed type has been forced to `Point`. That means protocol\ndispatch uses the `Eq` implementation for `Point`, which ignores `z`.\n\n<div class=\"beginner-content\">\n<p>If protocol dispatch feels surprising, first ask: what type is the\nprogram actually seeing here? If you annotate values as a base type too\nearly, you can force dispatch to use the base-type implementation.</p>\n</div>\n\nIn this case, the better API is usually a generic one that keeps the\nfull type:\n\n```python\ndef generic_comparator[A(Eq)](a: A, b: A):\n    return a == b\n```\n\n<div class=\"advanced-content\">\n<p>This is one reason generic constraints such as <code>[A(Eq)]</code>\noften produce better behavior than prematurely forcing values into a\nbase-class type. Protocol dispatch follows the observed type, so type\nannotations, container element types, and narrowing steps can all change\nbehavior without changing the value itself.</p>\n</div>\n\nThe same issue can appear when values are stored in a collection typed\nas the base class:\n\n```python\nactor main(env):\n    ref_point = Point3D(1, 2, 4)\n    p1 = Point3D(1, 2, 3)\n    p2 = Point3D(1, 2, 4)\n    my_points: list[Point] = [p1, p2]\n    for point in my_points:\n        if point == ref_point:\n            print(\"Found the reference (compared as Point)\", point)\n        if isinstance(point, Point3D) and point == ref_point:\n            print(\"Found the reference (compared as Point3D)\", point)\n```\n\nHere, `isinstance` narrows the observed type back to `Point3D`, so the\nmore specific protocol implementation is used again.\n\n## What to watch\n\n- If you annotate values as a base type too early, protocol dispatch\n  can use the base-type implementation.\n- If you want behavior to follow the concrete value, keep the type\n  generic for as long as possible.\n- If you need a more specific implementation after narrowing, use the\n  narrower type again before the protocol method call.\n"
  },
  {
    "path": "docs/acton-guide/src/protocols/intro.md",
    "content": "# Protocols\n\nProtocols describe behavior that different types can share.\n\nUse a protocol when your main question is \"what operations does this\nvalue support?\" rather than \"what class does it inherit from?\"\n\n```python\nprotocol Processable[T]:\n    process : () -> T\n\nclass Message(object):\n    def __init__(self, text):\n        self.text = text\n\nextension Message(Processable[str]):\n    def process(self):\n        return self.text.upper()\n```\n\nIn this example:\n\n- `Processable[T]` defines a capability\n- `Message` is an ordinary class\n- the `extension` says that `Message` implements that protocol\n\n<div class=\"beginner-content\">\n<p>Inheritance says one class is a kind of another class. A protocol\nsays a type supports a certain behavior, whether or not there is any\ninheritance relationship. Read\n<code>extension Message(Processable[str])</code> as \"Message implements\nthe Processable[str] protocol\".</p>\n</div>\n\nProtocols are useful at API boundaries because they let you depend on a\ncapability instead of a concrete class. Several unrelated types can\noffer the same behavior, and one type can offer several unrelated\nbehaviors.\n\n<div class=\"advanced-content\">\n<p>Protocols matter both for programming style and for type inference.\nThey let you describe the shape of an API without committing to a\nconcrete hierarchy. In Acton, protocols can also be implemented by\nextensions after a class is defined, which makes them useful for\nretrofitting shared behavior onto existing types.</p>\n</div>\n\n## Protocols in practice\n\n```python\nprotocol Printable:\n    print : () -> None\n\ndef render(item: Printable):\n    item.print()\n```\n\nHere, `render` only cares that the value can be printed. It does not\ncare which class the value comes from.\n\n## Protocols and generic constraints\n\nProtocols also show up in generic type signatures.\n\n```python\ndef bigger[A(Ord)](a: A, b: A) -> A:\n    if a > b:\n        return a\n    return b\n```\n\nHere, `A(Ord)` means the type `A` must implement the `Ord` protocol so\nthat `>` is available.\n\nBuilt-in protocols such as `Ord`, `Hashable`, `Iterable`, and `Mapping`\nare documented in the reference section under [Built-in\nprotocols](../stdlib/builtin_protocols.md).\n"
  },
  {
    "path": "docs/acton-guide/src/rts.md",
    "content": "# Run Time System\n\nThe Acton Run Time System is what sets up the environment in which an Acton program runs. It performs bootstrapping of the root actor. The worker threads that carry out actual execution of actor continuations are part of the RTS. It is the RTS that handles scheduling of actors and the timer queue. All I/O is handled between modules in the standard library in conjunction with the RTS.\n\n# Arguments\n\nIt is possible to configure the RTS through a number of arguments. All arguments to the RTS start with `--rts-`. Use `--rts-help` to see a list of all arguments:\n\n```sh\n$ acton examples/helloworld.act\nBuilding file examples/helloworld.act\n  Compiling helloworld.act for release\n   Finished compilation in   0.012 s\n  Final compilation step\n   Finished final compilation step in   0.198 s\n$ examples/helloworld --rts-help\nThe Acton RTS reads and consumes the following options and arguments. All\nother parameters are passed verbatim to the Acton application. Option\narguments can be passed either with --rts-option=ARG or --rts-option ARG\n\n  --rts-bt-dbg                      Interactively debug on SIGILL / SIGSEGV\n  --rts-debug                       RTS debug, requires program to be compiled with --optimize Debug\n  --rts-ddb-host=HOST               DDB hostname\n  --rts-ddb-port=PORT               DDB port [32000]\n  --rts-ddb-replication=FACTOR      DDB replication factor [3]\n  --rts-node-id=ID                  RTS node ID\n  --rts-rack-id=RACK                RTS rack ID\n  --rts-dc-id=DATACENTER            RTS datacenter ID\n  --rts-host=RTSHOST                RTS hostname\n  --rts-help                        Show this help\n  --rts-mon-log-path=PATH           Path to RTS mon stats log\n  --rts-mon-log-period=PERIOD       Periodicity of writing RTS mon stats log entry\n  --rts-mon-on-exit                 Print RTS mon stats to stdout on exit\n  --rts-mon-socket-path=PATH        Path to unix socket to expose RTS mon stats\n  --rts-no-bt                       Disable automatic backtrace\n  --rts-log-path=PATH               Path to RTS log\n  --rts-log-stderr                  Log to stderr in addition to log file\n  --rts-verbose                     Enable verbose RTS output\n  --rts-wthreads=COUNT              Number of worker threads [#CPU cores]\n\n$\n```\n\n# Worker threads\n\nPer default, the RTS starts as many worker threads as there are CPU threads available, although at least 4. This is optimized for server style workloads where it is presumed that the Acton program is the sole program consuming considerable resources. When there are 4 and more CPU threads available, the worker threads are pinned to each respective CPU thread.\n\nIt is possible to specify the number of worker threads with `--rts-wthreads=COUNT`.\n\nActor method continuations run to completion, which is why it is wise not to set this value too low. Per default a minimum of 4 threads are started even when there are fewer CPU threads available, which means the operating system will switch between the threads inducing context switching overhead.\n\n# Interactive debugging on crashes\n\nIf an Acton program crashes, `--rts-bt-dbg` is a convenient option for launching an interactive debugger. It is triggered on `SIGILL` / `SIGSEGV` and launches an interactive GDB session that allows for debugging the running program.\n\nActon programs do not normally crash with `SIGILL` / `SIGSEGV` but it possible either due to bugs in the compiler / RTS / builtins or more likely, for third party libraries that use C FFI, like for TLS, SSH, zlib or similar where a bug in the library triggers a crash on C level.\n"
  },
  {
    "path": "docs/acton-guide/src/security/capabilities.md",
    "content": "# Capabilities to access outside world\n\nAny useful program eventually needs to interact with the outside world.\nThat can mean reading files, opening sockets, or sending data to a\nremote host. In many languages those operations are always available to\nany code. In Acton they are explicit.\n\nThings outside the actor world are represented by actors and accessed\nthrough capability references. A capability is a reference that grants\npermission for a specific kind of operation. Without the reference, the\noperation is not available.\n\nFor example, `TCPConnection` needs a `TCPConnectCap` to connect to a\nremote host over TCP. The type system enforces that requirement. If the\nright capability is not available, the code does not compile.\n\n`TCPConnectCap` sits inside a capability hierarchy that starts at\n`WorldCap` and narrows from there:\n\n> WorldCap >> NetCap >> TCPCap >> TCPConnectCap\n\nThe root actor, typically `main()`, takes an `Env` reference as its\nfirst argument. `env.cap` is the root `WorldCap` capability for\naccessing the outside world.\n\n```python\nimport net\n\nactor main(env):\n\n    def on_connect(c):\n        c.close()\n\n    def on_receive(c, data):\n        pass\n\n    def on_error(c, msg):\n        print(\"Client ERR\", msg)\n\n    connect_cap = net.TCPConnectCap(net.TCPCap(net.NetCap(env.cap)))\n    client = net.TCPConnection(connect_cap, env.argv[1], int(env.argv[2]),\n        on_connect, on_receive, on_error)\n```\n\nThat structure matters because it lets the program choose how much\nauthority to hand out. A deeply nested helper, or a dependency of a\ndependency, can only do what its received capability allows.\n\n## Restrict and delegate\n\nWhen a function takes a capability argument, it should normally take\nthe narrowest capability it actually needs. If the code only needs to\nopen a TCP connection, pass `TCPConnectCap`. Do not pass `WorldCap`\njust because it is available.\n\nWhen you write a helper, ask what the helper really does. Give it only\nthe capability needed for that work. If a library asks for a wider\ncapability than the work requires, that is a design problem in the\nlibrary.\n\n<div class=\"advanced-content\">\n<p>The deeper design point is capability attenuation: code should pass\nalong narrower powers than it originally received whenever possible.\nThat keeps authority local, makes APIs easier to audit, and prevents a\nconvenient helper from quietly becoming a wide ambient escape hatch\ninto the outside world.</p>\n</div>\n\n## Capability-friendly interfaces\n\nCapability-friendly APIs are explicit about their authority boundaries.\nIf one part of a library logs to files and another part talks to a\nremote host, split those responsibilities or make the narrower paths\neasy to select.\n\nThe goal is not ceremony. The goal is to keep authority local and\nvisible. A capability that is not passed in cannot be used, and a\ncapability that is not passed on cannot escape further into the program.\n"
  },
  {
    "path": "docs/acton-guide/src/security/intro.md",
    "content": "# Security and Trust (or the lack thereof)\n\n\n\n"
  },
  {
    "path": "docs/acton-guide/src/security.md",
    "content": "# Security\n\nActon's security model starts from a simple rule: code can only use\nwhat it has a reference to.\n\nActors are isolated from each other. To call an actor, read from it, or\notherwise interact with it, code must already hold a reference to that\nactor. There is no ambient authority hiding behind a module import or a\nglobal variable.\n\nThat is close to the [object capability\nmodel](https://en.wikipedia.org/wiki/Object-capability_model).\n\n<div class=\"beginner-content\">\n<p>A useful mental model is: no ambient authority. If code can reach\nsomething, that access had to come from somewhere concrete. In\npractice, give each function or actor only the references it actually\nneeds. That keeps the code easy to reason about and makes accidental\naccess paths harder to create.</p>\n</div>\n\nBecause there are no mutable globals, reachable state is either:\n\n- local to the current actor\n- reachable through references that were explicitly passed in\n\n```python\nactor Vault():\n    def read():\n        print(\"secret\")\n\nactor Reader(vault):\n    def show():\n        await async vault.read()\n\nactor main(env):\n    vault = Vault()\n    reader = Reader(vault)\n    await async reader.show()\n    env.exit(0)\n```\n\n`Reader` can call `Vault` only because the reference was passed in\nexplicitly. If the reference is not available, the access is not\navailable.\n\n<div class=\"advanced-content\">\n<p>The key point is not only \"there are no mutable globals\". It is that\nauthority itself becomes something code can pass, withhold, or narrow.\nIf a function or actor never receives a filesystem, network, or process\ncapability, it cannot perform those actions by accident or by hidden\nconvention. That makes ordinary API boundaries double as security\nboundaries.</p>\n\n<p>This is why explicit capability passing matters so much in Acton. A\nreference is not just a way to reach a value; it is also the way\nauthority enters a piece of code. That applies equally to actor\nreferences inside the program and to outside-world capabilities such as\nfiles, networking, environment access, and terminal control.</p>\n</div>\n"
  },
  {
    "path": "docs/acton-guide/src/stdlib/builtin_protocols/collection.md",
    "content": "# Collection protocols\n\nThese protocols describe the shared APIs behind built-in collection\ntypes.\n\n<div class=\"beginner-content\">\n<p>These protocols describe behavior, not concrete storage. They let the\nlanguage talk about \"something indexable\" or \"something iterable\"\nwithout naming one specific collection type.</p>\n</div>\n\n## Core collection protocols\n\n- `Indexed[A(Eq), B]`: lookup, assignment, and deletion with `[]`\n- `Sliceable[A] (Indexed[int, A])`: slicing with `start:stop:step`\n- `Collection[A] (Iterable[A])`: construction from an iterable and\n  `len`\n- `Container[A(Eq)] (Collection[A])`: membership with `in` and `not in`\n\n## Specialized collection protocols\n\n- `Sequence[A] (Sliceable[A], Collection[A], Times[int])`: ordered,\n  sliceable collections with repetition and mutating operations such as\n  `append`, `insert`, and `reverse`\n- `Mapping[A(Eq), B] (Container[A], Indexed[A, B])`: key/value\n  collections with `get`, `pop`, `keys`, `values`, and `items`\n- `Set[A(Eq)] (Container[A], Ord, Logical, Minus)`: set operations,\n  ordering, membership, and mutating updates such as `add` and\n  `discard`\n\nBuilt-in types make use of these protocols:\n\n- `list[A]` implements `Sequence[A]`\n- `dict[A(Hashable), B]` implements `Mapping[A, B]`\n- `set[A(Hashable)]` implements `Set[A]`\n\n<div class=\"advanced-content\">\n<p>The protocol surface is sometimes looser than a concrete type's full\nrequirements. For example, <code>Mapping[A, B]</code> talks about\nkey/value behavior in general, while <code>dict</code> specifically\nrequires hashable keys.</p>\n</div>\n"
  },
  {
    "path": "docs/acton-guide/src/stdlib/builtin_protocols/general.md",
    "content": "# General protocols\n\nThese protocols cover iteration, comparison, operators, and hashing.\n\n## Iteration\n\n- `Iterable[A]`: values that can produce an iterator with `__iter__`\n  and can therefore be used in `for` loops and other iteration-based\n  APIs\n\n## Identity and comparison\n\n- `Identity`: identity comparison with `is` and `is not`\n- `Eq`: equality comparison with `==` and `!=`\n- `Ord (Eq)`: ordering with `<`, `<=`, `>`, and `>=`\n\n<div class=\"beginner-content\">\n<p>If you see a constraint such as <code>A(Ord)</code> in a type\nsignature, it means values of type <code>A</code> support ordering.</p>\n</div>\n\n## Operator families\n\n- `Logical`: `&`, `|`, `^`, and their in-place forms\n- `Plus`: `+`, `+=`, and `__zero__`\n- `Minus`: `-` and `-=`\n- `Times[A] (Plus)`: `*` and `*=`, with right-hand operand type `A`\n- `Div[A]`: `/` and `/=`, with result type `A`\n\n## Hashing\n\n- `Hashable (Eq)`: values that can feed data into a `hasher`; required\n  for dictionary keys and set elements\n\n<div class=\"beginner-content\">\n<p>If you see a constraint such as <code>A(Hashable)</code>, values of\ntype <code>A</code> can be used where hashing is required.</p>\n</div>\n\nSee [Hashable](hashable.md) for the full protocol reference and an\nimplementation example.\n"
  },
  {
    "path": "docs/acton-guide/src/stdlib/builtin_protocols/hashable.md",
    "content": "# Hashable\n\nThe `Hashable` protocol defines how values participate in hashing.\n\nIt is required for dictionary keys and set elements.\n\n<div class=\"beginner-content\">\n<p>If a collection needs to look up a value by hash, the value's type\nmust be hashable. That is why dictionary keys and set elements have this\nconstraint.</p>\n</div>\n\n## Protocol definition\n\n`Hashable` extends `Eq`, which means hashable values must also support\nequality:\n\n```python\nprotocol Hashable (Eq):\n    hash : (hasher) -> None\n```\n\nThe built-in helper functions are:\n\n```python\ndef hash(x: Hashable) -> u64\ndef seed_hash(seed: u64, x: Hashable) -> u64\n```\n\n## How hashing works\n\nHashing uses a two-part design:\n\n1. A `hasher` object accumulates hash input.\n2. A value's `hash` method feeds its data into that `hasher`.\n\nWhen you call `hash(x)`, Acton creates a `hasher`, asks `x` to feed its\nstate into it, and then finalizes the result as a `u64`.\n\n```python\np = Point(10, 20)\nh = hash(p)\nprint(\"hash:\", h)\n```\n\n## Implementing `Hashable`\n\nTo make a custom type hashable, define both equality and hashing so\nthey describe the same identity.\n\n```python\nclass Point:\n    x: int\n    y: int\n\n    def __init__(self, x: int, y: int):\n        self.x = x\n        self.y = y\n\nextension Point(Hashable):\n    def __eq__(self, other):\n        return self.x == other.x and self.y == other.y\n\n    def hash(self, h):\n        self.x.hash(h)\n        self.y.hash(h)\n```\n\nThe important rules are:\n\n1. Hash all fields used by equality.\n2. Hash them in a stable order.\n3. Do not leave out part of the value's identity.\n\nIf two values compare equal, they must feed the same data into the\nhasher.\n\n<div class=\"advanced-content\">\n<p><code>Hashable</code> follows equality, not the other way around. If\ntwo values compare equal but feed different data into the hasher, sets\nand dictionaries can behave incorrectly in subtle ways even though the\nprogram still typechecks.</p>\n</div>\n\n## Using hashable values in collections\n\nOnce a type implements `Hashable`, values of that type can be used in\nsets and as dictionary keys:\n\n```python\ndef test_hashable_point():\n    p1 = Point(1, 2)\n    p2 = Point(3, 4)\n    p3 = Point(1, 2)\n\n    points = {p1, p2, p3}\n    point_names = {p1: \"origin\", p2: \"destination\"}\n\n    print(\"unique points:\", len(points))\n    print(\"point names:\", point_names)\n```\n\n## Built-in types\n\nMany built-in value types implement `Hashable`, including:\n\n- `bool`\n- `int`, `bigint`, and the fixed-width integer types\n- `float`\n- `complex`\n- `str`\n- `bytes`\n\n`dict` and `set` use `Hashable` for their key or element types, but are\nnot themselves documented as `Hashable` here.\n"
  },
  {
    "path": "docs/acton-guide/src/stdlib/builtin_protocols/numeric.md",
    "content": "# Numeric protocols\n\nThese protocols describe the operations available on built-in numeric\ntypes.\n\n## Protocol hierarchy\n\n- `Number (Times[Self], Minus)`: core numeric behavior such as `+`,\n  `-`, `*`, `**`, unary `+` and `-`, `abs`, `real`, `imag`, and\n  `conjugate`\n- `Real (Number)`: float-style conversion and rounding operations such\n  as `__float__`, `trunc`, `floor`, `ceil`, and `round`\n- `RealFloat (Real)`: floating-point real numbers\n- `Rational (Real)`: values with `numerator` and `denominator`\n- `Integral (Rational, Logical)`: integer-style operations such as\n  `//`, `%`, shifts, bit operations, and indexing\n\n## Built-in implementations\n\n- `int`, `bigint`, and the fixed-width signed and unsigned integer types\n  implement `Integral`\n- `float` implements `RealFloat`\n- `complex` implements `Number`\n\nUse the narrowest constraint that matches the operations you need:\n\n<div class=\"beginner-content\">\n<p>Choose <code>Number</code> when you need ordinary arithmetic.\nChoose <code>Integral</code> when you need integer-only operations such\nas floor division, modulo, or bit shifts.</p>\n</div>\n\n```python\ndef square[A(Number)](x: A) -> A:\n    return x * x\n\ndef bucket[A(Integral)](x: A, size: A) -> A:\n    return x // size\n```\n\n<div class=\"advanced-content\">\n<p>Numeric constraints affect both operator availability and result\ntypes. For example, <code>Div[A]</code> separates the type of the result\nfrom the type of the operands, which is why integer division through\n<code>/</code> can return a different type than floor division through\n<code>//</code>.</p>\n</div>\n"
  },
  {
    "path": "docs/acton-guide/src/stdlib/builtin_protocols.md",
    "content": "# Built-in protocols\n\nBuilt-in protocols are defined in `__builtin__`.\n\nThey show up in generic constraints, operator behavior, and the APIs of\nbuilt-in collections. This section is reference material for the\nprotocols that come with the language.\n\n<div class=\"advanced-content\">\n<p>Built-in protocol constraints are part of the type system, not just\ndocumentation. They affect which operators are available, which generic\nfunctions typecheck, and how protocol methods are resolved.</p>\n</div>\n\nThe built-in protocols are grouped here as:\n\n- [General protocols](builtin_protocols/general.md) for iteration,\n  comparison, operators, and hashing\n- [Numeric protocols](builtin_protocols/numeric.md) for number-like\n  types\n- [Collection protocols](builtin_protocols/collection.md) for\n  collection-shaped APIs\n\n<div class=\"beginner-content\">\n<p>Read a header such as <code>protocol Ord (Eq)</code> as \"Ord\nextends Eq\". A type that implements <code>Ord</code> must also satisfy\nthe requirements of <code>Eq</code>.</p>\n</div>\n\nFor how protocols work as a language feature, read\n[Protocols](../protocols/intro.md).\n"
  },
  {
    "path": "docs/acton-guide/src/stdlib/math.md",
    "content": "# math\n\nThe `math` module provides the constant `pi` and common floating-point\nfunctions.\n\nSource:\n```python\nimport math\n\nactor main(env):\n    angle = math.pi / 4.0\n\n    print(math.sin(angle))\n    print(math.sqrt(9.0))\n\n    env.exit(0)\n```\n\n<div class=\"beginner-content\">\n<p>Import the module first with <code>import math</code>, then call its\nfunctions as <code>math.sqrt(...)</code>, <code>math.sin(...)</code>,\nand so on.</p>\n</div>\n\nThe module currently exposes:\n\n- `pi`\n- `sqrt`, `exp`, `log`\n- `sin`, `cos`, `tan`\n- `asin`, `acos`, `atan`\n- `sinh`, `cosh`, `tanh`\n- `asinh`, `acosh`, `atanh`\n\nThese functions take and return `float`.\n\n<div class=\"advanced-content\">\n<p>The module defines a <code>RealFuns</code> protocol and implements it\nfor <code>float</code>. The exported module functions delegate through\nthat protocol.</p>\n</div>\n"
  },
  {
    "path": "docs/acton-guide/src/stdlib/re.md",
    "content": "# re\n\nThe `re` module provides regular expression matching.\n\nSource:\n```python\nimport re\n\nactor main(env):\n    m = re.match(r\"(foo[a-z]+)\", \"bla bla foobar abc123\")\n    if m is not None:\n        print(\"Got a match:\", m.group[1])\n\n    env.exit(0)\n```\n\n<div class=\"beginner-content\">\n<p>Import the module with <code>import re</code>, then call functions\nsuch as <code>re.match(...)</code>.</p>\n</div>\n\n`re.match` also accepts an optional `start_pos` to begin scanning at a\nspecific index (defaults to 0).\n\nOutput:\n```sh\nGot a match: foobar\n```\n"
  },
  {
    "path": "docs/acton-guide/src/stdlib/standard_library.md",
    "content": "# Standard Library\n\nThis section documents modules that you import explicitly.\n\n<div class=\"beginner-content\">\n<p>Use <code>import</code> to bring a standard library module into\nscope.</p>\n</div>\n\nModules:\n\n- [math](math.md)\n- [re](re.md)\n"
  },
  {
    "path": "docs/acton-guide/src/stdlib.md",
    "content": "# Built-in & Standard Library\n\nThis part of the guide is reference material.\n\nActon has two closely related pieces here:\n\n- built-in definitions that are always available, such as core types and\n  built-in protocols\n- standard library modules that you import explicitly, such as `math`\n  and `re`\n\n<div class=\"beginner-content\">\n<p>Built-in names are part of the language environment. Standard library\nmodules are brought into scope with <code>import</code>.</p>\n</div>\n\nUse [Built-in protocols](stdlib/builtin_protocols.md) for the protocols\ndefined in `__builtin__`, including `Eq`, `Ord`, `Hashable`,\n`Iterable`, and `Mapping`.\n\n<div class=\"advanced-content\">\n<p>This split matches the implementation structure as well: built-in\nprotocols and core types live in <code>__builtin__</code>, while module\nAPIs such as <code>math</code> live in separate standard library\nmodules.</p>\n</div>\n\nUse [Standard Library](stdlib/standard_library.md) for imported modules.\n"
  },
  {
    "path": "docs/acton-guide/src/testing/async_actor_test.md",
    "content": "# Async actor tests\n\nSource:\n```python\nimport logging\nimport testing\n\nactor MathTester():\n    def add(a, b):\n        return a + b\n\nactor _AsyncTester(t: testing.AsyncT):\n    log = logging.Logger(t.log_handler)\n    def test():\n        log.info(\"AsyncTester.test() doing its thing\")\n        t.success()\n        # Provide output to .success to enable snapshot testing\n        #   t.success(\"some_output\")\n        # Or if things aren't going well, use .failure or .error\n        #   t.failure(ValueError(\"whopsy\"))\n        #   t.error(ValueError(\"whopsy\"))\n    after 0: test()\n```\n\nRun:\n```sh\nacton test\n```\n\nOutput:\n```sh\nBuilding project in /home/user/foo\n  Compiling example.act for release\n   Finished compilation in   0.028 s\n  Final compilation step\n   Finished final compilation step in   0.516 s\n\nTests - module example:\n  asyncact1:             OK: 1171 runs in 56.181ms\n\nAll 1 tests passed (0.695s)\n\n```\n\nIf a particular module is written to be called asynchronously, you will need to use asynchronous tests to test it.\n\n`testing.AsyncT` also provides:\n- `t.require(tag)` to skip a test when a required capability is not enabled via `acton test --tag TAG`\n- `t.skip(reason)` to explicitly skip the current test\n\nThe test discovery system finds asynchronous tests by looking for *actors* that take a `testing.AsyncT` parameter.\n\n*Snapshot testing* can be enabled by providing an output of type *str* to the `.success(output: ?str)` function. The Acton test framework will take care about recognizing the test as a snapshot test and comparing its output to the expected *snapshot value*.\n"
  },
  {
    "path": "docs/acton-guide/src/testing/env_test.md",
    "content": "# Env tests\n\nWhen you need to test functionality that accesses the environment, like files on disk or connect to something across the network, you need an env test. Do beware of errors related to test setup though, since you now depend on the external environment. TCP ports that you try to listen to might be already taken. Files that you assume exist might not be there.\n\nSource:\n```python\nimport logging\nimport testing\n\nactor _TestWithEnv(t: testing.EnvT):\n    log = logging.Logger(t.log_handler)\n    def test():\n        log.info(\"EnvTester.test() running, going to check with the env\", {\"worker_threads\": t.env.nr_wthreads})\n        t.success()\n        # Provide output to .success to enable snapshot testing\n        #   t.success(\"some_output\")\n        # Or if things aren't going well, use .failure or .error\n        #   t.failure(ValueError(\"whopsy\"))\n        #   t.error(ValueError(\"whopsy\"))\n    after 0: test()\n```\n\nRun:\n```sh\nacton test\n```\n\nOutput:\n```sh\nBuilding project in /home/user/foo\n  Compiling example.act for release\n   Finished compilation in   0.023 s\n  Final compilation step\n   Finished final compilation step in   0.484 s\n\nTests - module example:\n  envtest1:              OK: 1213 runs in 50.135ms\n\nAll 1 tests passed (0.689s)\n\n```\n\nThe test discovery system finds environment tests by looking for *actors* that take a `testing.EnvT` parameter.\n\n`testing.EnvT` also provides:\n- `t.require(tag)` to skip a test when a required capability is not enabled via `acton test --tag TAG`\n- `t.skip(reason)` to explicitly skip the current test\n\n*Snapshot testing* can be enabled by providing an output of type *str* to the `.success(output: ?str)` function. The Acton test framework will take care about recognizing the test as a snapshot test and comparing its output to the expected *snapshot value*.\n"
  },
  {
    "path": "docs/acton-guide/src/testing/failures_errors.md",
    "content": "# Failures vs errors\n\nTests can have tree different outcomes; success, failure and error.\n\n**Success** and **failure** are the two common cases where success is when the test meets the expected assertions and a failure is when it fails to meet a test assertion like `testing.assertEqual(1, 2)`. We also distinguish a third case for test **errors** which is when a test does not run as expected, hitting an unexpected exception. This could indicate a design issue or that the test environment is not as expected.\n\nAll test assertions raise exceptions inheriting from `AssertionError` which are considered **test failures**. Any other exception will be considered a **test error**.\n\nFor example, if a test attempts to retrieve `https://dummyjson.com/products/1` and check that the returned JSON looks a certain way, it would be a test failure if the returned JSON does not match the expected value. If we try to connect with an invalid URL, like `htp://` we would get a different exception and that would be considered a **test error**. It's probably a bad idea to try to connect to something on the Internet in a test, so avoid that and other sources of non-determinism when possible.\n\n# Unit tests\n\nSource:\n```python\nimport random\nimport testing\n\ndef _test_failure():\n    testing.assertEqual(1, 2)\n\ndef _test_flaky():\n    i = random.randint(0, 2)\n    if i == 0:\n        return\n    elif i == 1:\n        testing.assertEqual(1, 2)\n    else:\n        raise ValueError(\"Random failure\")\n\ndef _test_error() -> None:\n    # Now we could never use a unit test to fetch things from the Internet\n    # anyway, but it's just to show what the results look like\n    raise ValueError()\n\n```\n\nRun:\n```sh\nacton test\n```\n\nOutput:\n```sh\nBuilding project in /home/user/foo\n  Compiling example.act for release\n   Finished compilation in   0.020 s\n  Final compilation step\n   Finished final compilation step in   0.482 s\n\nTests - module example:\n  error:                 ERR: 454 errors out of  454 runs in 52.733ms\n    ValueError: \n  flaky:                 FLAKY FAIL: 231 failures out of  471 runs in 52.819ms\n    testing.NotEqualError: Expected equal values but they are non-equal. A: 1 B: 2\n  failure:               FAIL: 408 failures out of  408 runs in 52.837ms\n    testing.NotEqualError: Expected equal values but they are non-equal. A: 1 B: 2\n\n1 error and 2 failure out of 3 tests (0.691s)\n\n```\n\nUnit tests are a good starting point for testing small units of your program. Pure functions are deterministic and are thus preferable for tests over non-deterministic tests using actors. You are limited in what you can do though, since all called functions must be pure.\n"
  },
  {
    "path": "docs/acton-guide/src/testing/flaky.md",
    "content": "# Flaky tests\n\nFlaky tests are those that have different outcomes during different runs, i.e. they are not deterministic. To combat these, `acton test` will per default attempt to run tests multiple times to ensure that the result is the same. It runs as many test iterations as possible for at least 50ms. If a test is flaky, this will be displayed in the test output.\n\nSource:\n```python\nimport random\nimport testing\n\ndef _test_flaky():\n    i = random.randint(0, 2)\n    if i == 0:\n        return\n    elif i == 1:\n        testing.assertEqual(1, 2)\n    else:\n        raise ValueError(\"Random failure\")\n```\n\nRun:\n```sh\nacton test\n```\n\nOutput:\n```sh\nBuilding project in /home/user/foo\n  Compiling example.act for release\n   Finished compilation in   0.017 s\n  Final compilation step\n   Finished final compilation step in   0.453 s\n\nTests - module example:\n  flaky:                 FLAKY FAIL: 565 failures out of 1140 runs in 50.043ms\n    testing.NotEqualError: Expected equal values but they are non-equal. A: 1 B: 2\n\n1 out of 1 tests failed (0.625s)\n\n```\n\n```admonish\nNote how this test case is only made possible because the random module has incorrect effects. The type says it is pure while in reality, it is not. There is an issue to improve this by applying a proper effect to the random module, see https://github.com/actonlang/acton/issues/1729, after which this example needs to be rewritten.\n```\n"
  },
  {
    "path": "docs/acton-guide/src/testing/perf_record.md",
    "content": "# Performance comparisons\n\nWhen running in `performance mode` you can record a snapshot of performance using `acton test perf --record`. A `perf_data` file is written to disk with the stored performance data. Subsequent test runs will read this file and show a comparison. The difference is displayed as a percentage increase or decrease in time.\n\nSource:\n```python\nimport testing\n\ndef _test_simple():\n    a = 0\n    for i in range(99999):\n        a += i\n```\n\nRun:\n```sh\nacton test perf --record\nacton test perf\n```\n\nOutput:\n```sh\nBuilding project in /home/user/foo\n  Compiling example.act for release\n   Finished compilation in   0.017 s\n  Final compilation step\n   Finished final compilation step in   0.452 s\n\nTests - module example:\n  simple:                OK:  3.25ms            Avg:  4.16ms             7.38ms             122 runs in 1006.002ms\n\nAll 1 tests passed (1.565s)\n\nBuilding project in /home/user/foo\n  Compiling example.act for release\n   Already up to date, in    0.000 s\n  Final compilation step\n   Finished final compilation step in   0.116 s\n\nTests - module example:\n  simple:                OK:  3.23ms -0.50%     Avg:  4.17ms +0.19%      6.35ms -13.91%     119 runs in 1001.375ms\n\nAll 1 tests passed (1.215s)\n\n```\n(note that the output is rather wide, scroll horizontally to see the full output)\n"
  },
  {
    "path": "docs/acton-guide/src/testing/performance.md",
    "content": "# Performance testing\n\nIt is also possible to run tests in a *performance mode*, which uses the same basic test definitions (so you can run your tests both as logic test and for performance purposes) but alters the way in which the tests are run. In performance mode, only a single test will be run at a time unlike the normal mode in which many tests are typically run concurrently.\n\nTo get good numbers in performance mode, it's good if test functions run for at least a couple of milliseconds. With very short tests, very small differences lead to very large percentage differences.\n\nSource:\n```python\nimport testing\n\ndef _test_simple():\n    a = 0\n    for i in range(99999):\n        a += i\n```\n\nRun:\n```sh\nacton test perf\n```\n\nOutput:\n```sh\nBuilding project in /home/user/foo\n  Compiling example.act for release\n   Finished compilation in   0.016 s\n  Final compilation step\n   Finished final compilation step in   0.451 s\n\nTests - module example:\n  simple:                OK:  3.21ms            Avg:  4.20ms             5.11ms             106 runs in 1005.261ms\n\nAll 1 tests passed (1.571s)\n\n```\n(note that the output is rather wide, scroll horizontally to see the full output)\n\nSee [Stress testing](stress.md) for concurrency-focused stress runs.\n"
  },
  {
    "path": "docs/acton-guide/src/testing/snapshot.md",
    "content": "# Snapshot testing\n\nSnapshot tests compare a produced string with a stored expected value. You can produce snapshot output from unit/sync test functions by returning `str`, or from async/env tests by calling `t.success(\"...\")`.\n\n```python\nimport testing\n\ndef _test_rendered_profile() -> str:\n    return '{\"name\":\"Alice\",\"role\":\"admin\"}'\n```\n\nActon writes snapshot files in your project under `snapshots/output/<module>/<test_name>` (latest produced value) and `snapshots/expected/<module>/<test_name>` (expected value used for comparison). Test names in those paths use the display test name, so `_test_foo` becomes `foo`.\n\nWhen an expected snapshot differs (or is missing), running tests normally shows a mismatch:\n\n```sh\n$ acton test\nBuilding project in /home/user/example\n...\nTests - module main:\n   rendered_profile: FAIL           :  254 runs in 50.045ms\n    testing.NotEqualError: Test output does not match expected snapshot value.\n    @@ -1,1 +1,1 @@\n    -{\"name\":\"Alice\",\"role\":\"user\"}\n    +{\"name\":\"Alice\",\"role\":\"admin\"}\n\n1 out of 1 tests failed (0.244s)\n```\n\nWhen the new output is correct, accept it as the new expected value with:\n\n```sh\n$ acton test --accept\nBuilding project in /home/user/example\n...\nTests - module main:\n   rendered_profile: UPDATED        :  243 runs in 50.445ms\n\nAll 1 tests passed (0.246s)\n```\n\n`--accept` is the idiomatic flag (aliases: `--snapshot-update`, `--golden-update`).\n\nFor tests that produce snapshot output, `snapshots/output/...` is written on every run. That is intentional: it makes it easy to use external diff tools (`diff`, `vimdiff`, `meld`, etc.) against `snapshots/expected/...` without any extra export step.\n\nFor example, to inspect the current snapshot difference for the test above:\n\n```sh\ndiff -u snapshots/expected/main/rendered_profile snapshots/output/main/rendered_profile\n```\n\n## Common workflow\n\n1. Run `acton test`.\n2. If there is a snapshot mismatch, inspect it directly, for example:\n\n```sh\ndiff -u snapshots/expected/main/rendered_profile snapshots/output/main/rendered_profile\n```\n\n3. Accept changes with `acton test --accept`.\n4. Run `acton test` again to confirm everything passes.\n\nAn alternative workflow is to accept first, then inspect version-controlled snapshot changes with Git:\n\n1. Run `acton test --accept`.\n2. Review what changed with `git diff -- snapshots/expected`.\n3. Keep or revert changes before commit, then run `acton test`.\n"
  },
  {
    "path": "docs/acton-guide/src/testing/stress.md",
    "content": "# Stress testing\n\nStress testing is meant for concurrency bugs, especially race conditions in FFI / C integrations.\n\nRun it with:\n\n```sh\nacton test stress\n```\n\n## How stress mode runs\n\n- Runs one test function/actor at a time.\n- For that test, starts multiple concurrent workers of the same test in one process.\n- Worker count defaults to roughly `1.5 * nr_wthreads` so workers must share RTS worker threads.\n- Override it with `--stress-workers N` when you want a specific level of oversubscription.\n- Stress runs are always fresh (no test-result cache reuse).\n- By default, stress runs for up to 5 seconds per test (`--max-time 5000`).\n- Continuous mode is available with `--max-time 0`.\n- In continuous mode, `--max-iter` is unbounded unless you set it.\n- The default stress `--min-time` is 1 second unless overridden (used for calibration; stress run length is controlled by `--max-time`).\n\n## Worker scheduling\n\nStress workers are split into:\n\n- A no-drift cohort (at least 2 workers, scaling to roughly 25% of workers)\n- A staggered-drift cohort (small per-iteration microsecond offsets)\n\nThis combines synchronized overlap windows with evolving offsets over time.\n\n## Per-worker live stats\n\nIn an interactive terminal, stress mode shows one live status line per worker.\n\n- sync worker line: `wN sync RUN/DONE ... @ RATE/s cur=0us tot=0us`\n- drift worker line: `wN drift RUN/DONE ... @ RATE/s cur=DRIFTus tot=TOTALus`\n\nThe main test line also carries a compact worker summary:\n\n- total: `... RUNS runs in DURATIONms @ RATE/s`\n- worker mix: `workers=N (sync=S drift=D)`\n- iteration estimate, granularity and observed coverage: `iter~...ms coarse~...ms sweep=... calib=... cov=SEEN/TOTAL(PCTpct)`\n  - `iter~` is a moving estimate of one test iteration duration\n  - `coarse~` is the current phase coarseness (lower is finer)\n  - in continuous mode (`--max-time 0`), `coarse~` decreases stepwise over time as sweep depth increases\n  - `cov` is observed occupied phase bins at current coarseness (resets when coarseness is refined)\n\nExample:\n\n```txt\nracy_sum: RUN : 2400 runs in 1500.000ms @ 1600.0/s | workers=8 (sync=2 drift=6) iter~2.340ms coarse~0.037ms sweep=64 cov=37/64(57.8pct)\n```\n\nUse normal test flags to tune duration/iterations, for example:\n\n```sh\nacton test stress --max-time 30000 --min-iter 100\n```\n\nPin a higher worker count explicitly:\n\n```sh\nacton test stress --stress-workers 24 --max-time 30000\n```\n\nRun continuously until interrupted:\n\n```sh\nacton test stress --max-time 0\n```\n\nPress `Ctrl-C` to stop and print the partial stress result collected so far.\n"
  },
  {
    "path": "docs/acton-guide/src/testing/sync_actor_test.md",
    "content": "# Sync actor tests\n\nSource:\n```python\nimport logging\nimport testing\n\nactor MathTester():\n    def add(a, b):\n        return a + b\n\n# It is possible to call actors in tests too, in which case the test is an \n# \"actor test\" (the function gets a 'proc' effect inferred when calling actors).\ndef _test_syncact_simple():\n    m = MathTester()\n    testing.assertEqual(m.add(1, 2), 3)\n\n# Actors named prefixed with _tests_ are also considered tests\nactor _test_SyncTester():\n    m = MathTester()\n    testing.assertEqual(m.add(1, 2), 3)\n\n# Use any test actor name by taking a testing.SyncT as only parameter\nactor _SyncTester2(t: testing.SyncT):\n    log = logging.Logger(t.log_handler)\n    m = MathTester()\n    log.info(\"Calculating numbers..\")\n    testing.assertEqual(m.add(1, 2), 3)\n\n# The traditional function-based approach can also take a testing.SyncT arg\ndef _test_syncact(testing.SyncT):\n    \"\"\"A test using actors and synchronous control flow\"\"\"\n    # We make use of an actor as the central point for running our test logic.\n    s = _SyncTester(t)\n```\n\nRun:\n```sh\nacton test\n```\n\nOutput:\n```sh\nBuilding project in /home/user/foo\n  Compiling example.act for release\n   Finished compilation in   0.027 s\n  Final compilation step\n   Finished final compilation step in   0.526 s\n\nTests - module example:\n  SyncTester:            OK: 1029 runs in 50.015ms\n  SyncTester2:           OK: 1103 runs in 50.002ms\n  syncact:               OK: 1175 runs in 50.005ms\n  syncact_simple:        OK: 1231 runs in 50.014ms\n\nAll 4 tests passed (0.655s)\n\n```\n\nSince the Acton RTS is multi-threaded and actors are scheduled concurrently on worker threads, using actors imply a degree of non-determinism and so unlike unit tests, which are completely deterministic, actors tests are fundamentally non-deterministic. You can still write deterministic tests as long as you pay attention to how you construct your test results.\n\n`testing.SyncT` also provides:\n- `t.require(tag)` to skip a test when a required capability is not enabled via `acton test --tag TAG`\n- `t.skip(reason)` to explicitly skip the current test\n\nFor example, actor A might be scheduled before or after actor B so if the test relies on ordering of the output, it could fail or succeed intermittently. Interacting with the surrounding environment by reading files or communicating over the network introduces even more sources of non-determinism. Avoid it if you can. \n\nThe test discovery system finds synchronous tests through:\n- **Functions**: with names starting with `_test_` and signatures `proc() -> None` or `proc(testing.SyncT) -> None`\n- **Actors**: that take a `testing.SyncT` parameter (the `_test_` prefix is optional) or actors with names starting with `_test_` and no parameters\n\n*Snapshot testing* can be enabled by returning a *str*. This only works for test *functions*, not test *actors*. Use a wrapping function if you want snapshot testing. The Acton test framework will take care about recognizing the test as a snapshot test and comparing its output to the expected *snapshot value*.\n"
  },
  {
    "path": "docs/acton-guide/src/testing/unit_test.md",
    "content": "# Unit tests\n\nSource:\n```python\nimport testing\n\ndef _test_simple():\n    foo = 3+4\n    testing.assertEqual(7, foo)\n```\n\nRun:\n```sh\nacton test\n```\n\nOutput:\n```sh\nBuilding project in /home/user/foo\n  Compiling example.act for release\n   Finished compilation in   0.016 s\n  Final compilation step\n   Finished final compilation step in   0.442 s\n\nTests - module example:\n  simple:                OK: 1565 runs in 50.079ms\n\nAll 1 tests passed (0.600s)\n\n```\n\nUnit tests are a good starting point for testing small units of your program. Pure functions are deterministic and are thus preferable for tests over non-deterministic tests using actors. You are limited in what you can do though, since all called functions must be pure.\n\nThe test discovery finds unit tests based on the name starting with `_test_` and has a function signature of `mut() -> None` or `pure() -> None`.\n\n```admonish\nOnce effect analysis has been improved in the compiler to contain scope local effects, the test discovery will only consider `pure` functions to be unit tests. See https://github.com/actonlang/acton/issues/1632\n```\n\n*Snapshot testing* can be enabled by returning a *str*. The Acton test framework will take care about recognizing the test as a snapshot test and comparing its output to the expected *snapshot value*.\n"
  },
  {
    "path": "docs/acton-guide/src/testing.md",
    "content": "# Testing\n\nTesting your code is a really good idea! While Acton's type system allows interfaces to be precisely defined, it is imperative that the behavior of a function or actor is tested!\n\nTest functions and test actors are automatically discovered by the compiler. Run tests with `acton test`. Import the testing module and name your test functions or actors starting with `_test_`. The type signature should match the test intended test category. Use the assertion functions available in the testing module. Here is a simple unit test:\n\nSource:\n```python src/ut.act\nimport testing\n\ndef _test_simple():\n    testing.assertEqual(1, 1)\n```\n\nRun:\n```sh\nacton test\n```\n\nOutput:\n```sh\nBuilding project in /home/user/foo\n  Compiling example.act for release\n   Finished compilation in   0.016 s\n  Final compilation step\n   Finished final compilation step in   0.437 s\n\nTests - module example:\n  simple:                OK: 1523 runs in 50.001ms\n\nAll 1 tests passed (0.604s)\n\n```\n\nThere are 4 kinds of tests\n- **unit tests**\n  - small simple tests of pure functions\n- **synchronous actor tests**\n  - involving one or more actors, returning results synchronously\n- **asynchronous actor tests**\n  - involving actors but use asynchronous callbacks for return values\n- **environment tests**\n  - similar to async actor test in that a callback is used for the return value\n  - these tests have access to the full environment via the `env` argument and can thus communicate with the outside world\n    - this is a source of non-determinism so be mindful of this and try to avoid non-deterministic functions to the largest degree possible\n  \nWhen possible, strive to use unit tests rather than actor based tests and strive to avoid env tests.\n\nFor snapshot-based assertions, see [Snapshot testing](testing/snapshot.md).\n\n## Cached test results\n\nThe Acton test runner caches test results which means that repeated invokations of `acton test` might not actually (re)run tests. Cached failures and errors are still shown by default, so you never miss a failing test. Cached successes are hidden unless you pass `--show-cached`. Pass `--no-cache` to force all selected tests to run, even if cached results exist.\n\nThis means that the developer experience for test driven development is great even for project with a very large amount of tests as the content hash driven test runner only recompiles and reruns tests that are actually affected by a change.\n\nNote that test input need to be contained within .act source code files in order for the compiler to consider them part of the content hash. You cannot use external .txt files or similar as input to test functions, since the compiler won't consider those parts of the implementation. Also see [incremental compilation](compilation/incremental.md) for more details on content hashing and how it applies to testing.\n\nSnapshot tests are the main exception: even when the test code hash matches the cache, `acton test` still checks the expected snapshot file on disk against the cached `snapshots/output/...` metadata. If the output snapshot is missing, the expected file changed, or Acton cannot cheaply prove the expected file is older than the last produced output, the test is rerun instead of trusting the cached result.\n\n## Module Filtering\n\nYou can run tests from specific modules using the `--module` flag:\n\n```sh\nacton test --module foo --module bar\n```\n\nThis will only run tests from the `foo` and `bar` modules, skipping all other test modules.\n\n## Capability-gated tests\n\nSome tests depend on external capabilities (for example network services, hardware, or system setup). In tests that receive a test context argument (`t`), use `t.require(...)` and pass available capabilities with `--tag`:\n\n```python\nimport testing\n\ndef _test_external_service(t):\n    t.require(\"external-service\")\n    # test logic that depends on external-service being available\n```\n\nRun with capabilities:\n\n```sh\nacton test --tag external-service\n```\n\nIf the required capability is not enabled, the test is marked as skipped.\nCapabilities are runtime environment signals used by `t.require(...)`; they are not a pre-test selection/filter mechanism. This applies to test context objects like `SyncT`, `AsyncT`, and `EnvT`.\n\nYou can also skip explicitly:\n\n```python\ndef _test_todo(t):\n    t.skip(\"not implemented yet\")\n```\n"
  },
  {
    "path": "docs/acton-guide/src/types/effects.md",
    "content": "# Effects (`pure`, `mut`, `proc`, `action`)\n\nActon tracks effects as part of function and callable typing.\nAn effect marker tells you what the callable is allowed to do, so it is\npart of the type information you read and design with.\n\nThe four effect markers are:\n\n- `pure`: no side effects\n- `mut`: may update state\n- `proc`: functions that call actors\n- `action`: action or callback style code used heavily in actor APIs\n\n```python\npure def square(x: int) -> int:\n    return x * x\n\nclass Counter:\n    value: int\n\n    def __init__(self):\n        self.value = 0\n\n    mut def next(self) -> int:\n        self.value += 1\n        return self.value\n\nactor Greeter():\n    def hello(msg):\n        print(msg)\n\nproc def show_square(g: Greeter, x: int) -> None:\n    g.hello(\"square: \" + str(square(x)))\n\nactor main(env):\n    counter = Counter()\n    greeter = Greeter()\n\n    print(\"counter:\", counter.next())\n    n = square(7)\n    print(\"n:\", n)\n    show_square(greeter, 9)\n\n    action def stop() -> None:\n        env.exit(0)\n\n    after 0.1: stop()\n```\n\nIn this example:\n\n- `square` is `pure`\n- `Counter.next` is `mut`\n- `show_square` is `proc` because it calls an actor\n- `stop` is an `action`\n- the effect markers are part of the callable signatures, not notes\n\n## Effect inference\n\nIf you omit the effect marker, Acton infers it from the body.\n\nUse explicit annotations when you want an API to promise purity, make\nmutation clear, or document that a callback or actor-facing entrypoint\nhas a particular effect. The effect is part of the contract just like\nits argument and return types.\n\n<div class=\"beginner-content\">\n<p>A useful first habit is to keep calculations pure and push printing,\nI/O, and actor orchestration into a smaller layer of effectful code.\nRead <code>pure</code> as \"calculation only\", <code>mut</code> as \"may\nupdate state\", <code>proc</code> as \"calls actors\", and\n<code>action</code> as \"actor action or callback\".</p>\n\n<p>That division makes code easier to reason about. If a helper is pure,\nyou know it only depends on its inputs. If it is mut or proc, you know\nit may change state or interact with actors, which makes its API more\nspecific.</p>\n</div>\n\n## When the four effects show up\n\n- `pure` is common for ordinary calculations and helpers that should be\n  easy to reuse anywhere\n- `mut` is common on methods that update state or work with local\n  mutable data\n- `proc` is common for functions that orchestrate work by calling\n  actors\n- `action` often appears in actor methods, timers, cleanup hooks, and\n  callback types such as `action(str) -> None`\n\nEffects often explain why a signature looks the way it does. A function\nmay have a simple data type and still be effectful, and the effect marker\nis what tells you whether it stays in pure computation or crosses into\nstateful or actor-driven work.\n\n<div class=\"advanced-content\">\n<p>Effects also appear in inferred signatures. As your code gets more\ngeneric or callback-heavy, those effect annotations become part of how\nyou read and design APIs. In Acton, purity is a real constraint on what\na function may call, so effect annotations are part of the contract, not\njust commentary.</p>\n</div>\n\n## Practical guidance\n\n- Prefer `pure` for deterministic, test-friendly core logic.\n- Use `mut` when a callable really updates state.\n- Use `proc` for functions that orchestrate work by calling actors.\n- Expect `action` in actor APIs, timers, cleanup hooks, and callbacks.\n- Keep pure logic separated from actor-driven orchestration code.\n- Read the effect marker together with the argument and return types.\n\n<div class=\"advanced-content\">\n<p>A useful mental model is <code>pure &lt;= mut &lt;= proc</code>, with\n<code>action &lt;= proc</code> on a separate branch. That is why pure\ncode can be used where a mutating or procedural callable is accepted,\nand why actions participate in the broader effect system without being\nthe same thing as ordinary sequential procedures. When you design higher\norder APIs, the effect on the callback is as important as its argument\ntypes.</p>\n\n<p>In practice, this means you should choose the weakest effect that\ndescribes the callable accurately. That keeps more code reusable and\nleaves the effect system useful as the codebase grows.</p>\n</div>\n"
  },
  {
    "path": "docs/acton-guide/src/types/explicit.md",
    "content": "# Explicit types\n\nActon can infer many types, but explicit annotations are still useful.\nThey are the way to say \"this value must stay this shape\" when the code\nwould otherwise leave room for interpretation.\n\n```python\ndef repeat(text: str, count: int) -> str:\n    return text * count\n\ndescribe_port : (int) -> str\ndef describe_port(port):\n    return \"port \" + str(port)\n\nactor main(env):\n    port: int = 9000\n    print(repeat(\"ha\", 3))\n    print(describe_port(port))\n    env.exit(0)\n```\n\n<div class=\"beginner-content\">\n<p>Read <code>name: Type</code> as \"name has type Type\" and\n<code>-&gt; Type</code> as \"returns Type\". A separate signature line can\nbe easier to scan when the implementation is long or the signature is\npart of the public surface of a module.</p>\n</div>\n\nYou can annotate:\n\n- function parameters\n- return values\n- local names\n- class and actor attributes\n- separate signature lines for named APIs\n- effect markers on callables\n\n## When explicit types help\n\nWrite annotations when:\n\n- you want an API to be clear to readers\n- inference becomes hard to understand\n- you want the compiler to reject the wrong shape earlier\n- a value could otherwise be inferred more loosely than you want\n- you are defining a reusable helper and want its contract visible\n\n<div class=\"beginner-content\">\n<p>A useful default is to annotate the things other people will read\nfirst: public functions, methods, actor fields, and data structures.\nLeave short local expressions inferred unless the type is surprising or\nimportant to the code around it.</p>\n</div>\n\n<div class=\"advanced-content\">\n<p>Explicit annotations also control generalization. If inference would\nmake a helper more polymorphic than you want, a written signature can\npin the API down and keep later changes from widening it by accident.\nThat is especially useful for callback types, actor-facing entrypoints,\nand shared utility code where the signature is the real contract.</p>\n</div>\n"
  },
  {
    "path": "docs/acton-guide/src/types/generics.md",
    "content": "# Generics\n\nGenerics let you write code that works for many types without throwing\naway type safety. They are how you describe a pattern once and reuse it\nfor every concrete type that fits the pattern.\n\n## A simple generic function\n\n```python\ndef first[A](items: list[A]) -> A:\n    return items[0]\n\nactor main(env):\n    print(first([1, 2, 3]))\n    print(first([\"a\", \"b\", \"c\"]))\n    env.exit(0)\n```\n\n`[A]` introduces a type variable named `A`. In this function:\n\n- `items` is a `list[A]`\n- the return value is also `A`\n- calling `first` on a `list[int]` returns an `int`\n- calling it on a `list[str]` returns a `str`\n- the compiler checks each call with the concrete type it sees there\n\n<div class=\"beginner-content\">\n<p>If the brackets feel abstract at first, read them as \"for any type\nnamed A\". Each call picks a concrete type for <code>A</code>, so\n<code>first([1, 2, 3])</code> uses <code>int</code> while\n<code>first([\"a\"])</code> uses <code>str</code>. That is how one\ndefinition stays reusable without giving up compile-time checking.</p>\n</div>\n\n## Constrained generics\n\nSometimes a generic function needs more than \"any type\". It may require\nthat the type supports some operation or protocol.\n\n```python\ndef bigger[A(Ord)](a: A, b: A) -> A:\n    if a > b:\n        return a\n    return b\n```\n\nHere, `A(Ord)` means `A` must implement the `Ord` protocol so the\nfunction can compare `a` and `b`. The constraint is part of the type\ninformation, not an implementation detail. Without it, the compiler\nwould not know that `>` is valid for `A`.\n\n<div class=\"advanced-content\">\n<p>Acton can often infer generic parameters and protocol constraints for\nyou. Using <code>--sigs</code> is a good way to see what the compiler\nunderstood before you decide whether to write the generic signature\nexplicitly. That matters when a helper starts being reused widely,\nbecause the inferred constraints determine both flexibility and dispatch\nbehavior.</p>\n</div>\n\n## Generics on classes\n\nBuilt-in collection types use the same syntax.\n\n```python\nclass list[A] (object):\n    ...\n```\n\nThat means a `list[int]` and a `list[str]` have the same generic shape\nbut different element types.\n\nThe same idea applies to your own classes and records. If a container or\nwrapper stores values without caring which concrete type they are, make\nthat type parameter explicit.\n\n## When to add constraints\n\nAdd a constraint when a type parameter must support a particular\noperation:\n\n- comparison, as in `Ord`\n- equality or hashing, if the code depends on it\n- a protocol, if the function calls methods from that protocol\n\nDo not add a constraint just because it looks formal. The compiler only\nneeds the bounds that the body actually uses.\n"
  },
  {
    "path": "docs/acton-guide/src/types/intro.md",
    "content": "# Working with types\n\nActon is statically typed. The compiler checks types when your program\nis compiled, but it can infer many of them for you. In practice, that\nmeans you usually write the shape of the code and let the compiler fill\nin the rest.\n\nThis section explains how to work with that type system deliberately:\nhow to read inferred signatures, when to write explicit annotations, and\nhow generics, constraints, and effects show up in real code.\n\nActon does not have Rust-style lifetimes. Mutable state lives inside\nactors, access to the outside world is passed explicitly as capabilities,\nand ordinary object lifetime is handled by the runtime. See\n[Actors](../actors.md), [Lifetime](../actors/lifetime.md), and\n[Environment and capabilities](../language/environment_capabilities.md)\nfor the Acton model.\n\nOptional types are introduced earlier under\n[Missing values and failures](../language/missing_values_failures.md)\nbecause they come up quickly in everyday code, but they are also part of\nthe broader type story.\n\n```python\ndef describe(value):\n    if value > 0:\n        return \"positive\"\n    return \"zero or negative\"\n\nactor main(env):\n    n = 3\n    text = describe(n)\n    print(text)\n    env.exit(0)\n```\n\nIn this example, Acton can infer the types without any annotations.\n`n` is an `int`, `describe` returns `str`, and `text` is also a `str`.\nThat is often the most pleasant way to write small programs: start with\nplain code, then add annotations only where they improve clarity.\n\n<div class=\"beginner-content\">\n<p>You do not need to annotate every value. A small helper, a local\ntemporary, or a short private function can often stay inferred without\nhurting readability. Add types where they explain intent, not as\ndecorations.</p>\n</div>\n\n## Reading inferred signatures\n\nUse `--sigs` when you want the compiler to show the types it inferred.\n\n```sh\nacton types.act --sigs\n```\n\nIn a project, use `acton sig` when you want signatures by import path\ninstead of by source file path:\n\n```sh\nacton sig foo.bar\n```\n\nThe target is resolved like an import path. Acton first looks for a\nmodule named `foo.bar`. If that module does not exist, it treats the\ntarget as the public name `bar` inside module `foo` and prints only that\nsignature.\n\nThis is useful when a type error mentions an imported module or name,\nespecially one that comes from a dependency. `acton sig` uses the\nproject's normal build resolution, so it reads `Build.act`, honors\ndependency overrides such as `--dep name=path`, fetches missing\ndependencies, and compiles the module interfaces it needs before\nprinting the signatures. It does not perform the final executable build.\n\nFor example:\n\n```sh\nacton sig collections.list\nacton sig mylib.parser.parse\n```\n\n<div class=\"advanced-content\">\n<p>Acton's inferred signatures include more than argument and return\ntypes. You will see generic binders, protocol constraints, optional\ntypes, tuple rows, and effect markers. Reading a signature means\nreading both the data shape and the callable behavior. The compiler's\noutput is often the clearest summary of what an API actually promises,\nso <code>acton sig</code> and <code>--sigs</code> are useful first\nsteps before deciding whether to make that promise explicit.</p>\n</div>\n\nThis is especially useful when:\n\n- you want to understand what type a helper function ended up with\n- you are learning how generic constraints are written\n- you want to turn an inferred signature into an explicit API\n- you need to see effect markers or optionality in a callable type\n\n## What this section covers\n\n- [Explicit types](explicit.md) when you want to state an API, narrow a\n  local value, or make inference easier to follow\n- [Generics](generics.md) when one definition should work for many\n  concrete types without losing safety\n- [Effects (`pure`, `mut`, `proc`, `action`)](effects.md) when you want\n  to treat side effects as part of the type information\n- [Troubleshooting type errors](troubleshooting.md) when you want to\n  inspect imported signatures and compare them with an error\n- [Optionals](optionals.md) when you want the deeper type-system view of\n  values that may be absent\n"
  },
  {
    "path": "docs/acton-guide/src/types/optionals.md",
    "content": "# Optionals\n\nBefore you can use an optional `?T` value as a plain `T` value, Acton\nmust be able to see that the value is present.\n\n## Narrowing\n\n`if x is not None` narrows `x` from `?T` to `T` inside that branch. Use\nthis form when the following code needs the value itself, not a value\nthat may still be `None`.\n\n```python\ndef upper_or_none(text: ?str) -> ?str:\n    if text is not None:\n        return text.upper()\n    return None\n```\n\nInside the `if` branch, `text` is treated as `str`, so ordinary string\nmethods are available. `if isinstance(x, SomeClass)` can also narrow an\noptional value while refining the concrete class.\n\nActon currently narrows variable names, not arbitrary attributes or\nexpressions. When you need several guarded accesses, bind the\nintermediate value to a name and narrow that name explicitly.\n\n```python\nclass Residence():\n    def __init__(self, rooms: int, name: ?str = None):\n        self.rooms = rooms\n        self.name = name\n\nclass Person():\n    def __init__(self, name: str, residence: ?Residence):\n        self.name = name\n        self.residence = residence\n\ndef residence_name(person: ?Person) -> ?str:\n    if person is not None:\n        residence = person.residence\n        if residence is not None:\n            return residence.name\n    return None\n```\n\nEach access is guarded by a test that rules out `None` before the next\naccess.\n\n## Optional chaining\n\nOptional chaining is a shorter way to keep `None` flowing through a\nsingle expression.\n\n```python\ndef residence_name(person: ?Person) -> ?str:\n    return person?.residence?.name\n```\n\nThe chain above is the compact form of the explicit checks from the\nprevious section:\n\n```python\ndef residence_name(person: ?Person) -> ?str:\n    if person is not None:\n        residence = person.residence\n        if residence is not None:\n            return residence.name\n    return None\n```\n\nIf the value to the left of `?.` is `None`, the whole expression\nevaluates to `None`. If the value to the left of `?[...]` is `None`,\nindexing or slicing is skipped and the result is `None`.\n\nUse `?.` for attribute access and method calls, and `?[...]` for\nindexing and slicing.\n\n```python\ndef loud_residence_name(person: ?Person) -> ?str:\n    return person?.residence?.name?.upper()\n\ndef first_port(config: ?dict[str, list[int]]) -> ?int:\n    return config?.get(\"ports\")?[0]\n```\n\nThe result of an optional chain is still optional. For example,\n`person?.residence?.rooms` has type `?int`, not `int`.\n\nOptional chaining only affects the current expression. It does not\nnarrow the value for later statements, so use `is None` or `is not None`\nwhen you need to branch on the result.\n\n<div class=\"advanced-content\">\n<p>Optional chaining lifts each later access into optional context. Each\nstep only runs if the previous step produced a real value; otherwise the\nwhole expression settles to <code>None</code> immediately. That is why a\nchain is good for one-pass extraction of a nested value: it preserves\nabsence without forcing you to invent a sentinel or write a stack of\ntemporary checks just to carry <code>None</code> through the expression.</p>\n\n<p>That same property is also the limit of the feature. A chain tells\nyou only the final result, not which step failed or what should happen\nnext. Once you need branching, logging, recovery, or repeated use of an\nintermediate value, stop chaining and narrow explicitly with\n<code>is None</code> / <code>is not None</code>. Optional chaining is\nbest for compact extraction, not for complex control flow.</p>\n</div>\n\n## Forced unwrapping\n\nUse forced unwrapping when surrounding logic has already established\nthat an optional value is present. If that assumption is wrong, Acton\nraises `ValueError` instead of continuing with `None`.\n\nUse `!` on an optional value to get the non-optional value inside it. If\n`b` has type `?str`, then `b!` has type `str`.\n\n```python\ndef required_name(name: ?str) -> str:\n    return name!\n```\n\nYou can think of forced unwrapping as this check:\n\n```python\ndef unwrap[T](value: ?T) -> T:\n    if value is not None:\n        return value\n    raise ValueError(\"unexpected None value\")\n```\n\nYou do not normally write that helper yourself. The `!` syntax is the\nshort form of \"give me the value if it is present, otherwise raise\n`ValueError`\".\n\n`!.` applies the same idea inside attribute access and method calls, and\n`![...]` applies it inside indexing and slicing chains. They follow the\nsame shapes as `?.` and `?[...]`, but raise `ValueError` if the value to\nthe left is `None` instead of returning `None`.\n\n```python\ndef required_residence_name(person: ?Person) -> str:\n    return person!.residence!.name!.upper()\n```\n\nThis returns `str`, not `?str`. If `person`, `residence`, or `name` is\n`None`, evaluation stops and raises `ValueError`. The final `!.upper()`\nis a guarded method call: it only calls `upper()` after `name` has been\nunwrapped.\n\nYou can mix `?` and `!` in the same chain. Later steps still see the\nresult of earlier ones, so a later `!` will raise if an earlier step\nproduced `None`.\n\n```python\ndef first_port_required(config: ?dict[str, list[int]]) -> int:\n    return config!.get(\"ports\")![0]\n\ndef first_port_or_none(config: ?dict[str, list[int]]) -> ?int:\n    return config?.get(\"ports\")?[0]\n```\n\nUse forced unwrapping when absence indicates a bug or broken invariant\nand execution should stop immediately.\n\n<div class=\"advanced-content\">\n<p>Forced unwrapping is for invariants: states that should already have\nbeen proven by surrounding logic. It is the right tool when a missing\nvalue means the program state is wrong, not when absence is still part\nof the normal control flow.</p>\n</div>\n"
  },
  {
    "path": "docs/acton-guide/src/types/troubleshooting.md",
    "content": "# Troubleshooting type errors with signatures\n\nWhen a type error mentions a value from another module, first check the\ninterface that the compiler sees. `acton sig` prints inferred signatures\nby import path, so you can compare the error against the imported API\ninstead of searching for generated files or guessing from memory.\n\nUse this workflow:\n\n1. Read the type error and find the module or type name involved.\n2. Run `acton sig` for the smallest exact module or public name.\n3. Compare the available attributes and methods with the failing code.\n4. Fix the source and rebuild.\n\n## Example: singular vs plural attribute\n\nSuppose one module defines a contact value:\n\n```python\n# src/directory.act\nclass Contact(object):\n    display_name: str\n    email_addresses: list[str]\n\n    def __init__(self, display_name: str, email_addresses: list[str]):\n        self.display_name = display_name\n        self.email_addresses = email_addresses\n```\n\nAnother module imports the class and uses the right concept, but the\nwrong singular form of the attribute name:\n\n```python\n# src/main.act\nfrom directory import Contact\n\ndef email_count(contact: Contact) -> int:\n    return len(contact.email_address)\n```\n\nRunning `acton build` points at the attribute selection:\n\n```text\n[error]: Attribute not found email_address\n     +--> main.act@4:24-4:37\n     |\n   4 |     return len(contact.email_address)\n     :                        ^------------\n     :                        `- Attribute not found email_address\n-----+\n```\n\nThe error is in `main`, but the shape of `Contact` is defined in\n`directory`. Ask the compiler for the imported type:\n\n```sh\nacton sig directory.Contact\n```\n\n`acton sig` first looks for a module named `directory.Contact`. If no\nsuch module exists, it treats the target as the public name `Contact`\ninside module `directory`. The output shows the public interface for the\nclass:\n\n```python\nclass Contact (object, value):\n    G_init : () -> None\n    @property\n    display_name : str\n    @property\n    email_addresses : list[str]\n    __init__ : (display_name: str, email_addresses: list[str]) -> None\n```\n\nThe `@property` entries are the readable part for this error. They say\nthe class has `email_addresses`, not `email_address`. That is not\nobvious from the local `main.act` file, but it is clear from the\ncompiler-visible interface. The fix is in the selecting code:\n\n```python\ndef email_count(contact: Contact) -> int:\n    return len(contact.email_addresses)\n```\n\nThis same approach works for dependencies. If `directory` comes from a\npackage dependency, `acton sig directory.Contact` still uses the\nproject's normal build resolution: it reads `Build.act`, fetches missing\ndependencies, compiles the interface files it needs, and skips the final\nexecutable build.\n\nIf you are testing a local checkout of a dependency, pass the same\noverride you would pass to `acton build`:\n\n```sh\nacton sig --dep directory=../directory directory.Contact\n```\n\n## Example: selecting attributes on the wrong value\n\nSome type errors mention an \"unknown type\" even when the value has a\nknown expected type. This can happen when Acton checks a method body and\ncollects constraints from dot selections before it has simplified the\nwhole constraint set.\n\nThe important part is not the unknown type name alone. Read the whole\nerror and look for the known type that must satisfy those constraints.\n\nSuppose one module defines an item type, a context type, and a base class\nwhose method takes both:\n\n```python\n# pipeline.act\nclass WorkItem(object):\n    title: str\n    tags: set[str]\n    output_path: str\n\n    def __init__(self, title: str, tags: set[str], output_path: str):\n        self.title = title\n        self.tags = tags\n        self.output_path = output_path\n\nclass RunContext(object):\n    run_id: str\n    user: str\n\n    def __init__(self, run_id: str, user: str):\n        self.run_id = run_id\n        self.user = user\n\nclass Step(object):\n    def apply(self, item: WorkItem, ctx: RunContext):\n        raise NotImplementedError()\n```\n\nA subclass can omit the local annotations because the inherited method\nshape already gives `item` and `ctx` their expected types:\n\n```python\n# steps.act\nfrom pipeline import Step\n\nclass DraftStep(Step):\n    def apply(self, item, ctx):\n        print(\"processing {ctx.title}\")\n\n        if \"draft\" in ctx.tags:\n            return ctx.output_path\n\n        raise ValueError(\"not a draft\")\n```\n\nThe method uses `ctx.title`, `ctx.tags`, and `ctx.output_path`, but the\ninherited signature says `ctx` is a `pipeline.RunContext`. The resulting\nerror has a common \"simultaneous constraints\" shape:\n\n```text\n[error]: Cannot satisfy the following simultaneous constraints for the unknown types\n     +--> steps.act@4:5-10:1\n     |\n   4 | +>     def apply(self, item, ctx):\n   5 | |          print(\"processing {ctx.title}\")\n     : |                             ^--------\n     : |                             `- The type of the indicated expression (which we call t0) must have an attribute title with type t4; no such type is known.\n   6 | |\n   7 | |          if \"draft\" in ctx.tags:\n     : |             ^----------^-------\n     : |             |          |- The type of the indicated expression (which we call t0) must have an attribute tags with type t1; no such type is known.\n     : |             |          `- The type of the indicated expression (which we call t1) must be a subtype of t2\n     : |             |- The type of the indicated expression (inferred to be __builtin__.str) must be a subtype of t3\n     : |             `- The type of the indicated expression (which we call t2) must implement __builtin__.Container[t3]\n   8 | |              return ctx.output_path\n     : |                     ^--------------\n     : |                     `- The type of the indicated expression (which we call t0) must have an attribute output_path with type None; no such type is known.\n     : |                        The type of the indicated expression (which we call t4) must be a subclass of ?__builtin__.value\n   9 | |\n  10 | |>         raise ValueError(\"not a draft\")\n     : |\n     : `- pipeline.RunContext must be a subclass of t0\n-----+\n```\n\nDo not read this as \"Acton cannot infer the type of `ctx`\". In this\nexample, the inherited method signature already gives `ctx` the expected\ntype `pipeline.RunContext`. The unknown `t0` is the type variable that\ncollected the requirements introduced by the dot selections on `ctx`.\nThe final line says that `pipeline.RunContext` must satisfy those\ncollected requirements.\n\nThe next step is to inspect the exact known type named in the error:\n\n```sh\nacton sig pipeline.RunContext\n```\n\nThat is usually better than asking for the whole module, because a large\nmodule can produce a lot of unrelated output. The signature shows the\ncompiler-visible fields:\n\n```python\nclass RunContext (object, value):\n    @property\n    run_id : str\n    @property\n    user : str\n    __init__ : (run_id: str, user: str) -> None\n```\n\nNow compare the failing selections with the signature. The code asked\nfor `title`, `tags`, and `output_path`, but `RunContext` has only\n`run_id` and `user`. When none of the selected attributes are present,\nthe code may be selecting on the wrong value. In this example, those\nattributes belong to `WorkItem`, so inspect that type too:\n\n```sh\nacton sig pipeline.WorkItem\n```\n\nThe fix is not to add a redundant annotation to `ctx`. The fix is to use\nthe value that actually has the fields:\n\n```python\nclass DraftStep(Step):\n    def apply(self, item, ctx):\n        print(\"processing {item.title}\")\n\n        if \"draft\" in item.tags:\n            return item.output_path\n\n        raise ValueError(\"not a draft\")\n```\n\nThis pattern also appears with dependency types. If the known type comes\nfrom a dependency, still run `acton sig` for the exact public name shown\nin the error:\n\n```sh\nacton sig package.module.TypeName\n```\n\nIf you are using a local dependency override, pass the same override to\n`acton sig` that you pass to `acton build`:\n\n```sh\nacton sig --dep package=../package package.module.TypeName\n```\n\nThe compiler already sees the dependency signatures when it reports the\nerror. Running `acton sig` does not make those signatures visible to the\ncompiler; it makes them visible to you, so you can compare the API Acton\nis checking against the attributes and methods your code selects.\n"
  },
  {
    "path": "docs/acton-guide/src/working_with_zig.md",
    "content": "# Working with Zig / C / C++\n\nActon has C ABI compatibility which makes it trivial to call C functions and fairly simply to call Zig and C++ using C wrapping functions. If you want to integrate a library written in one of these languages, this page is for you.\n\nRegardless of the foreign language used, we need to consider a few things:\n- memory allocation, it must play well with the Acton GC\n  - You can allocate memory via classic `malloc` or via Acton GC malloc\n    - `acton_malloc` - normal malloc\n    - `acton_malloc_atomic` for allocations that are guaranteed to not contain pointers\n  - Better safe than sorry, use the GC-malloc when in doubt\n  - Always use Acton GC malloc for actor and class attributes and similar\n    - object and actor instances are garbage collected by the GC and there is no destructor function, so if you would have used class `malloc` there is no good place for the `free`\n  - Within pure functions, you can use class `malloc` - be sure to `free` the allocations before return of the function, even for error paths\n- thread safety, the Acton RTS is threaded and actors are concurrently executed by different threads\n  - in general, we strive to only keep data per actor and since an actor executes sequentially, we do not need thread safety measures like locks - just make sure you don't try to share data between actors \"under the hood\"\n  - libraries must not use global variables though\n- asynchronous I/O, the Acton RTS performs asynchronous I/O and any other library that performs I/O need to conform to this model\n"
  },
  {
    "path": "docs/acton-guide/src/zig_dependencies.md",
    "content": "# C / C++ / Zig dependencies\n\nMuch like dependencies on other Acton packages, an Acton project can depend on a Zig package which could be a C / C++ or Zig library, as long as it has a `build.zig` file.\n\n- `acton zig-pkg add URL NAME --artifact X --artifact Y`\n  - list the libraries you want to link with as artifacts\n- `acton zig-pkg remove NAME`\n\n~~~admonish example\n```\nacton zig-pkg add https://github.com/allyourcodebase/zlib/archive/refs/tags/1.3.1.tar.gz zlib --artifacts z\n```\n\n```json\n{\n    \"dependencies\": {},\n    \"zig_dependencies\": {\n        \"zlib\": {\n            \"url\": \"https://github.com/allyourcodebase/zlib/archive/refs/tags/1.3.1.tar.gz\",\n            \"hash\": \"122034ab2a12adf8016ffa76e48b4be3245ffd305193edba4d83058adbcfa749c107\",\n            \"artifacts\": [\n                \"z\"\n            ]\n        }\n    }\n}\n```\n\n~~~\n"
  },
  {
    "path": "docs/acton-guide/svgbob.css",
    "content": " /* Ensure text is legible in all themes. */\nsvg text {\n  fill: var(--fg);\n}\n"
  },
  {
    "path": "docs/acton-guide/theme/acton-theme.css",
    "content": "/* Acton visual theme for mdBook */\n\n:root {\n    --acton-yellow: #ffd42a;\n    --acton-yellow-soft: #fff3b4;\n    --acton-yellow-strong: #9c7412;\n    --acton-steel-950: #151617;\n    --acton-steel-900: #202326;\n    --acton-steel-800: #33373a;\n    --acton-steel-700: #454b4f;\n    --acton-steel-600: #5f666a;\n    --acton-steel-300: #c8cdd0;\n    --acton-steel-200: #dfe2e3;\n    --acton-steel-100: #eef0ef;\n    --acton-paper: #f7f8f6;\n}\n\n.light,\n.rust,\nhtml:not(.js) {\n    --bg: var(--acton-steel-100);\n    --fg: #191b1c;\n\n    --sidebar-bg: var(--acton-steel-900);\n    --sidebar-fg: var(--acton-steel-200);\n    --sidebar-non-existant: #858d92;\n    --sidebar-active: var(--acton-yellow);\n    --sidebar-spacer: rgba(255, 255, 255, 0.12);\n\n    --scrollbar: var(--acton-steel-600);\n\n    --icons: #d7dcde;\n    --icons-hover: #ffffff;\n\n    --links: #785600;\n    --inline-code-color: #5d4810;\n\n    --theme-popup-bg: var(--acton-steel-900);\n    --theme-popup-border: rgba(255, 255, 255, 0.16);\n    --theme-hover: rgba(255, 212, 42, 0.14);\n\n    --quote-bg: #fff7cf;\n    --quote-border: var(--acton-yellow);\n\n    --warning-border: var(--acton-yellow-strong);\n\n    --table-border-color: rgba(35, 38, 40, 0.16);\n    --table-header-bg: #dfe2e3;\n    --table-alternate-bg: rgba(255, 255, 255, 0.42);\n\n    --searchbar-border-color: rgba(255, 255, 255, 0.18);\n    --searchbar-bg: var(--acton-steel-950);\n    --searchbar-fg: var(--acton-paper);\n    --searchbar-shadow-color: rgba(255, 212, 42, 0.34);\n    --searchresults-header-fg: var(--acton-steel-600);\n    --searchresults-border-color: rgba(35, 38, 40, 0.16);\n    --searchresults-li-bg: #fff7cf;\n    --search-mark-bg: var(--acton-yellow-soft);\n\n    --color-scheme: light;\n\n    --copy-button-filter: invert(87%) sepia(8%) saturate(126%) hue-rotate(164deg) brightness(102%) contrast(90%);\n    --copy-button-filter-hover: invert(82%) sepia(80%) saturate(811%) hue-rotate(340deg) brightness(103%) contrast(102%);\n\n    --footnote-highlight: var(--acton-yellow-soft);\n    --overlay-bg: rgba(21, 22, 23, 0.34);\n\n    --acton-chrome-bg: var(--acton-steel-900);\n    --acton-chrome-fg: var(--acton-paper);\n    --acton-chrome-muted: var(--acton-steel-300);\n    --acton-panel-bg: rgba(247, 248, 246, 0.94);\n    --acton-code-bg: #f4f4f1;\n}\n\n.ayu,\n.coal,\n.navy {\n    --bg: var(--acton-steel-950);\n    --fg: #f2f3ef;\n\n    --sidebar-bg: #111213;\n    --sidebar-fg: var(--acton-steel-200);\n    --sidebar-non-existant: #727a80;\n    --sidebar-active: var(--acton-yellow);\n    --sidebar-spacer: rgba(255, 255, 255, 0.12);\n\n    --scrollbar: #858d92;\n\n    --icons: #d7dcde;\n    --icons-hover: #ffffff;\n\n    --links: var(--acton-yellow);\n    --inline-code-color: var(--acton-yellow);\n\n    --theme-popup-bg: #111213;\n    --theme-popup-border: rgba(255, 255, 255, 0.16);\n    --theme-hover: rgba(255, 212, 42, 0.14);\n\n    --quote-bg: rgba(255, 212, 42, 0.1);\n    --quote-border: rgba(255, 212, 42, 0.45);\n\n    --warning-border: var(--acton-yellow);\n\n    --table-border-color: rgba(255, 255, 255, 0.14);\n    --table-header-bg: var(--acton-steel-800);\n    --table-alternate-bg: rgba(255, 255, 255, 0.04);\n\n    --searchbar-border-color: rgba(255, 255, 255, 0.18);\n    --searchbar-bg: #111213;\n    --searchbar-fg: var(--acton-paper);\n    --searchbar-shadow-color: rgba(255, 212, 42, 0.34);\n    --searchresults-header-fg: var(--acton-steel-300);\n    --searchresults-border-color: rgba(255, 255, 255, 0.14);\n    --searchresults-li-bg: var(--acton-steel-800);\n    --search-mark-bg: #5d4810;\n\n    --color-scheme: dark;\n\n    --copy-button-filter: invert(87%) sepia(8%) saturate(126%) hue-rotate(164deg) brightness(102%) contrast(90%);\n    --copy-button-filter-hover: invert(82%) sepia(80%) saturate(811%) hue-rotate(340deg) brightness(103%) contrast(102%);\n\n    --footnote-highlight: #5d4810;\n    --overlay-bg: rgba(0, 0, 0, 0.42);\n\n    --acton-chrome-bg: #111213;\n    --acton-chrome-fg: var(--acton-paper);\n    --acton-chrome-muted: var(--acton-steel-300);\n    --acton-panel-bg: rgba(32, 35, 38, 0.9);\n    --acton-code-bg: #1a1c1d;\n}\n\n@media (prefers-color-scheme: dark) {\n    html:not(.js) {\n        --bg: var(--acton-steel-950);\n        --fg: #f2f3ef;\n        --sidebar-bg: #111213;\n        --sidebar-fg: var(--acton-steel-200);\n        --sidebar-active: var(--acton-yellow);\n        --theme-popup-bg: #111213;\n        --quote-bg: rgba(255, 212, 42, 0.1);\n        --quote-border: rgba(255, 212, 42, 0.45);\n        --table-border-color: rgba(255, 255, 255, 0.14);\n        --table-header-bg: var(--acton-steel-800);\n        --table-alternate-bg: rgba(255, 255, 255, 0.04);\n        --color-scheme: dark;\n        --acton-chrome-bg: #111213;\n        --acton-chrome-fg: var(--acton-paper);\n        --acton-chrome-muted: var(--acton-steel-300);\n        --acton-panel-bg: rgba(32, 35, 38, 0.9);\n        --acton-code-bg: #1a1c1d;\n    }\n}\n\nhtml {\n    background: var(--bg);\n}\n\n.page-wrapper {\n    min-height: 100vh;\n    background-color: var(--bg);\n    background-image: linear-gradient(120deg, rgba(255, 212, 42, 0.08), transparent 28rem);\n    background-repeat: no-repeat;\n    background-size: 100% 100vh;\n}\n\n#menu-bar {\n    align-items: center;\n    background: var(--acton-chrome-bg);\n    border-block-end-color: rgba(255, 255, 255, 0.12);\n    color: var(--acton-chrome-muted);\n    flex-wrap: nowrap;\n}\n\n#menu-bar.bordered {\n    border-block-end-color: rgba(255, 255, 255, 0.18);\n}\n\n.menu-bar,\n.menu-bar:visited,\n.menu-bar .icon-button,\n.menu-bar a i {\n    color: var(--acton-chrome-muted);\n}\n\n.menu-bar i:hover,\n.menu-bar .icon-button:hover {\n    color: var(--acton-chrome-fg);\n}\n\n.menu-title {\n    color: var(--acton-chrome-fg);\n    min-width: 0;\n    font-weight: 700;\n    letter-spacing: -0.03em;\n}\n\n.left-buttons {\n    align-self: stretch;\n    align-items: center;\n}\n\n.right-buttons {\n    display: flex;\n    align-items: center;\n    align-self: stretch;\n    margin: 0 15px 0 0;\n}\n\n.sidebar {\n    top: var(--menu-bar-height);\n    border-inline-end: 1px solid rgba(255, 255, 255, 0.12);\n    z-index: 100;\n}\n\n#sidebar-toggle-anchor:not(:checked) ~ .sidebar {\n    z-index: 100;\n    pointer-events: none;\n}\n\n#sidebar-toggle-anchor:checked ~ .page-wrapper {\n    margin-inline-start: 0 !important;\n    transform: none !important;\n}\n\n[dir=rtl] #sidebar-toggle-anchor:checked ~ .page-wrapper {\n    margin-inline-end: 0 !important;\n    transform: none !important;\n}\n\n@media only screen and (min-width: 620px) {\n    #sidebar-toggle-anchor:checked ~ .page-wrapper .content {\n        margin-inline-start: calc(var(--sidebar-width) + var(--sidebar-resize-indicator-width));\n    }\n}\n\n@media only screen and (max-width: 980px) {\n    .menu-title {\n        text-align: start;\n    }\n}\n\n@media only screen and (max-width: 760px) {\n    .menu-title {\n        display: none;\n    }\n}\n\n.sidebar a:hover,\n.sidebar a.active {\n    color: var(--acton-yellow);\n}\n\n.content main {\n    padding-top: 1rem;\n}\n\npre {\n    background: var(--acton-code-bg);\n    border: 1px solid var(--table-border-color);\n    border-left: 4px solid var(--acton-yellow);\n    border-radius: 8px;\n}\n\npre > code,\npre > code.hljs {\n    background: transparent;\n}\n\n:not(pre):not(a) > .hljs {\n    border-radius: 0.28em;\n    padding: 0.1em 0.28em;\n    background: rgba(255, 212, 42, 0.16);\n}\n\n.theme-popup {\n    color: var(--acton-chrome-fg);\n    box-shadow: 0 18px 45px rgba(0, 0, 0, 0.22);\n}\n\n.theme-popup .theme {\n    min-width: 132px;\n}\n"
  },
  {
    "path": "docs/acton-guide/theme/acton-theme.js",
    "content": "// Keep mdBook's theme menu focused on the Acton visual themes.\n\n(function() {\n    const THEME_LABELS = {\n        default_theme: \"Auto\",\n        light: \"Acton Light\",\n        ayu: \"Acton Dark\"\n    };\n    const LEGACY_THEME_MAP = {\n        rust: \"light\",\n        coal: \"ayu\",\n        navy: \"ayu\"\n    };\n\n    function migrateLegacyTheme() {\n        const saved = localStorage.getItem(\"mdbook-theme\");\n        const replacement = LEGACY_THEME_MAP[saved];\n\n        if (replacement) {\n            localStorage.setItem(\"mdbook-theme\", replacement);\n            document.documentElement.classList.remove(saved);\n            document.documentElement.classList.add(replacement);\n        }\n    }\n\n    function movePrintControl() {\n        const leftButtons = document.querySelector(\".menu-bar .left-buttons\");\n        const printButton = document.getElementById(\"print-button\");\n        const printLink = printButton ? printButton.closest(\"a\") : null;\n\n        if (!leftButtons || !printLink || printLink.parentElement === leftButtons) {\n            return;\n        }\n\n        printLink.classList.add(\"acton-print-control\");\n        leftButtons.appendChild(printLink);\n    }\n\n    function pruneThemeMenu() {\n        const themeList = document.getElementById(\"theme-list\");\n\n        if (!themeList) {\n            return;\n        }\n\n        for (const button of themeList.querySelectorAll(\"button.theme\")) {\n            const label = THEME_LABELS[button.id];\n            const item = button.closest(\"li\");\n\n            if (!label) {\n                if (item) {\n                    item.remove();\n                }\n                continue;\n            }\n\n            button.textContent = label;\n        }\n    }\n\n    function initialize() {\n        migrateLegacyTheme();\n        movePrintControl();\n        pruneThemeMenu();\n    }\n\n    initialize();\n    document.addEventListener(\"DOMContentLoaded\", initialize);\n})();\n"
  },
  {
    "path": "docs/acton-guide/theme/content-width.css",
    "content": "/* Wider content area for better side-by-side code display */\n\n/* Increase main content width and center it */\n.content main {\n    max-width: 900px !important;\n    margin: 0 auto !important;\n    padding: 0 15px;\n}\n\n/* Wider content on larger screens */\n@media (min-width: 1200px) {\n    .content main {\n        max-width: 950px !important;\n    }\n}\n\n@media (min-width: 1400px) {\n    .content main {\n        max-width: 1000px !important;\n    }\n}\n\n@media (min-width: 1600px) {\n    .content main {\n        max-width: 1050px !important;\n    }\n}\n\n/* Make code blocks in side-by-side tables use available space better */\n.side-by-side-code td:first-child {\n    width: 35%; /* Explanations/comments column */\n}\n\n.side-by-side-code td:last-child {\n    width: 65%; /* Code column - more space for code */\n}\n\n/* Adjust pre/code blocks to not add unnecessary padding in tables */\n.side-by-side-code pre {\n    margin: 0;\n    padding: 10px;\n}\n\n.side-by-side-code td {\n    padding: 12px;\n}\n\n/* For very wide screens, cap the side-by-side table width for readability */\n@media (min-width: 1600px) {\n    .side-by-side-code {\n        max-width: 1400px;\n        margin-left: auto;\n        margin-right: auto;\n    }\n}"
  },
  {
    "path": "docs/acton-guide/theme/detail-toggles.css",
    "content": "/* Detail-level controls for the Acton Guide */\n\n.skill-control-menu {\n    display: inline-flex;\n    align-items: center;\n    margin-left: 8px;\n}\n\n.detail-toggle-wrapper {\n    display: inline-flex;\n    align-items: center;\n    gap: 8px;\n}\n\n.detail-toggle {\n    display: inline-flex;\n    align-items: center;\n    justify-content: center;\n    gap: 7px;\n    min-height: 28px;\n    padding: 0 12px;\n    border-radius: 999px;\n    border: 1px solid var(--table-border-color);\n    background: var(--bg);\n    color: var(--fg);\n    cursor: pointer;\n    user-select: none;\n    white-space: nowrap;\n    font-size: 11px;\n    font-weight: 600;\n    text-transform: uppercase;\n    letter-spacing: 0.5px;\n    transition: background-color 0.15s ease, border-color 0.15s ease,\n        color 0.15s ease, opacity 0.15s ease;\n}\n\n.detail-toggle:hover {\n    opacity: 0.92;\n}\n\n.detail-toggle:focus-visible {\n    outline: 2px solid var(--icons);\n    outline-offset: 2px;\n}\n\n.detail-toggle-indicator {\n    position: relative;\n    display: inline-block;\n    width: 15px;\n    height: 15px;\n    border-radius: 999px;\n    border: 1px solid currentColor;\n    flex: 0 0 15px;\n}\n\n.detail-toggle-indicator::before {\n    position: absolute;\n    inset: 0;\n    display: flex;\n    align-items: center;\n    justify-content: center;\n    font-size: 10px;\n    line-height: 1;\n    font-weight: 700;\n}\n\n.detail-toggle[aria-pressed=\"false\"] .detail-toggle-indicator::before {\n    content: \"\";\n    width: 5px;\n    height: 5px;\n    inset: 50% auto auto 50%;\n    border-radius: 999px;\n    background: currentColor;\n    opacity: 0.45;\n    transform: translate(-50%, -50%);\n}\n\n.detail-toggle[aria-pressed=\"true\"] .detail-toggle-indicator::before {\n    content: \"✓\";\n}\n\n.detail-toggle-beginner {\n    background: rgba(76, 175, 80, 0.08);\n    border-color: rgba(76, 175, 80, 0.55);\n    color: #2e7d32;\n}\n\n.detail-toggle-advanced {\n    background: rgba(33, 150, 243, 0.08);\n    border-color: rgba(33, 150, 243, 0.55);\n    color: #1565c0;\n}\n\n.detail-toggle-beginner.is-active,\n.detail-toggle-beginner[aria-pressed=\"true\"] {\n    background: rgba(76, 175, 80, 0.2);\n    border-color: #4caf50;\n    color: #2e7d32;\n    box-shadow: inset 0 0 0 1px rgba(76, 175, 80, 0.12);\n}\n\n.detail-toggle-advanced.is-active,\n.detail-toggle-advanced[aria-pressed=\"true\"] {\n    background: rgba(33, 150, 243, 0.2);\n    border-color: #2196f3;\n    color: #1565c0;\n    box-shadow: inset 0 0 0 1px rgba(33, 150, 243, 0.12);\n}\n\n.ayu .detail-toggle-beginner,\n.coal .detail-toggle-beginner,\n.navy .detail-toggle-beginner {\n    color: #7bd67f;\n}\n\n.ayu .detail-toggle-advanced,\n.coal .detail-toggle-advanced,\n.navy .detail-toggle-advanced {\n    color: #78c4ff;\n}\n\n.ayu .detail-toggle-beginner.is-active,\n.coal .detail-toggle-beginner.is-active,\n.navy .detail-toggle-beginner.is-active,\n.ayu .detail-toggle-beginner[aria-pressed=\"true\"],\n.coal .detail-toggle-beginner[aria-pressed=\"true\"],\n.navy .detail-toggle-beginner[aria-pressed=\"true\"] {\n    color: #7bd67f;\n}\n\n.ayu .detail-toggle-advanced.is-active,\n.coal .detail-toggle-advanced.is-active,\n.navy .detail-toggle-advanced.is-active,\n.ayu .detail-toggle-advanced[aria-pressed=\"true\"],\n.coal .detail-toggle-advanced[aria-pressed=\"true\"],\n.navy .detail-toggle-advanced[aria-pressed=\"true\"] {\n    color: #78c4ff;\n}\n\n@media (max-width: 700px) {\n    .skill-control-menu {\n        margin-right: 6px;\n    }\n\n    .detail-toggle-wrapper {\n        gap: 6px;\n    }\n\n    .detail-toggle {\n        gap: 6px;\n        min-height: 24px;\n        padding: 0 10px;\n        font-size: 10px;\n        letter-spacing: 0.35px;\n    }\n\n    .detail-toggle-indicator {\n        width: 13px;\n        height: 13px;\n        flex-basis: 13px;\n        font-size: 9px;\n    }\n}\n\n/* Content visibility based on selected detail toggles */\n.beginner-content,\n.advanced-content {\n    display: none;\n    margin: 0;\n    padding: 0;\n    border: 0;\n}\n\nbody[data-show-beginner=\"true\"] .beginner-content {\n    display: block;\n    margin: 15px 0;\n}\n\nbody[data-show-advanced=\"true\"] .advanced-content {\n    display: block;\n    margin: 15px 0;\n}\n\n.beginner-inline,\n.advanced-inline {\n    display: none;\n}\n\nbody[data-show-beginner=\"true\"] .beginner-inline {\n    display: inline;\n}\n\nbody[data-show-advanced=\"true\"] .advanced-inline {\n    display: inline;\n}\n\n.beginner-content {\n    background: rgba(76, 175, 80, 0.1);\n    border-left: 4px solid #4caf50;\n    padding: 15px;\n    margin: 15px 0;\n    border-radius: 0 4px 4px 0;\n}\n\n.advanced-content {\n    background: rgba(33, 150, 243, 0.1);\n    border-left: 4px solid #2196f3;\n    padding: 15px;\n    margin: 15px 0;\n    border-radius: 0 4px 4px 0;\n}\n\n.beginner-content::before {\n    content: \"Beginner\";\n    display: block;\n    font-weight: bold;\n    margin-bottom: 10px;\n    color: #4caf50;\n}\n\n.advanced-content::before {\n    content: \"Advanced\";\n    display: block;\n    font-weight: bold;\n    margin-bottom: 10px;\n    color: #2196f3;\n}\n\n/* Enhanced side-by-side code table */\n.side-by-side-code {\n    width: 100%;\n    border-collapse: collapse;\n    margin: 25px 0;\n    background: transparent;\n    border-radius: 0;\n    overflow: visible;\n    box-shadow: none;\n}\n\n.side-by-side-code td {\n    padding: 20px;\n    vertical-align: top;\n    border-bottom: 1px solid var(--table-border-color);\n}\n\n.side-by-side-code tr:last-child td {\n    border-bottom: none;\n}\n\n.side-by-side-code td:first-child {\n    width: 35%;\n    background: var(--sidebar-bg);\n    border-right: 1px solid var(--table-border-color);\n    font-size: 0.95em;\n    line-height: 1.7;\n    color: var(--fg);\n}\n\n.side-by-side-code td:last-child {\n    width: 65%;\n    background: var(--code-bg);\n}\n\n.side-by-side-code pre {\n    margin: 0;\n    background: transparent;\n    padding: 0;\n}\n\n.side-by-side-code code {\n    font-size: 0.9em;\n}\n\n@media (max-width: 768px) {\n    .side-by-side-code td {\n        display: block;\n        width: 100% !important;\n    }\n\n    .side-by-side-code td:first-child {\n        border-right: none;\n        border-bottom: 1px solid var(--table-border-color);\n    }\n\n    .side-by-side-code tr:last-child td:first-child {\n        border-bottom: 1px solid var(--table-border-color);\n    }\n}\n\n.ayu .side-by-side-code td:first-child,\n.coal .side-by-side-code td:first-child,\n.navy .side-by-side-code td:first-child {\n    background: rgba(0, 0, 0, 0.2);\n}\n"
  },
  {
    "path": "docs/acton-guide/theme/detail-toggles.js",
    "content": "// Detail-level toggles for the Acton Guide\n\n(function() {\n    const DEFAULT_PREFERENCES = {\n        beginner: false,\n        advanced: false\n    };\n    const STORAGE_KEY = \"acton-docs-detail-preferences\";\n    const LEGACY_STORAGE_KEY = \"acton-docs-skill-level\";\n\n    function normalizePreferences(value) {\n        return {\n            beginner: Boolean(value && value.beginner),\n            advanced: Boolean(value && value.advanced)\n        };\n    }\n\n    function migrateLegacyPreference() {\n        const saved = localStorage.getItem(LEGACY_STORAGE_KEY);\n        if (!saved) {\n            return null;\n        }\n\n        const level = parseInt(saved, 10);\n        if (level === 1) {\n            return { beginner: true, advanced: false };\n        }\n        if (level === 3) {\n            return { beginner: false, advanced: true };\n        }\n        return { beginner: false, advanced: false };\n    }\n\n    function loadPreferences() {\n        const saved = localStorage.getItem(STORAGE_KEY);\n        if (saved) {\n            try {\n                return normalizePreferences(JSON.parse(saved));\n            } catch (_error) {\n                // Fall through to defaults and legacy migration.\n            }\n        }\n\n        const migrated = migrateLegacyPreference();\n        if (migrated) {\n            savePreferences(migrated);\n            return migrated;\n        }\n\n        return { ...DEFAULT_PREFERENCES };\n    }\n\n    function savePreferences(preferences) {\n        localStorage.setItem(\n            STORAGE_KEY,\n            JSON.stringify(normalizePreferences(preferences))\n        );\n    }\n\n    function applyPreferences(preferences) {\n        const normalized = normalizePreferences(preferences);\n        document.body.setAttribute(\n            \"data-show-beginner\",\n            normalized.beginner ? \"true\" : \"false\"\n        );\n        document.body.setAttribute(\n            \"data-show-advanced\",\n            normalized.advanced ? \"true\" : \"false\"\n        );\n    }\n\n    function syncControls(preferences) {\n        const beginnerToggle = document.getElementById(\"toggleBeginnerDetails\");\n        const advancedToggle = document.getElementById(\"toggleAdvancedDetails\");\n\n        if (beginnerToggle) {\n            beginnerToggle.setAttribute(\n                \"aria-pressed\",\n                preferences.beginner ? \"true\" : \"false\"\n            );\n            beginnerToggle.classList.toggle(\"is-active\", preferences.beginner);\n        }\n        if (advancedToggle) {\n            advancedToggle.setAttribute(\n                \"aria-pressed\",\n                preferences.advanced ? \"true\" : \"false\"\n            );\n            advancedToggle.classList.toggle(\"is-active\", preferences.advanced);\n        }\n    }\n\n    function currentPreferences() {\n        return {\n            beginner: document.body.getAttribute(\"data-show-beginner\") === \"true\",\n            advanced: document.body.getAttribute(\"data-show-advanced\") === \"true\"\n        };\n    }\n\n    function updatePreferences(preferences) {\n        const normalized = normalizePreferences(preferences);\n        applyPreferences(normalized);\n        syncControls(normalized);\n        savePreferences(normalized);\n    }\n\n    function createDetailControls() {\n        const widget = document.createElement(\"div\");\n        widget.className = \"skill-control-menu\";\n        widget.setAttribute(\"aria-label\", \"Documentation detail toggles\");\n        widget.innerHTML = `\n            <div class=\"detail-toggle-wrapper\">\n                <button\n                    type=\"button\"\n                    class=\"detail-toggle detail-toggle-beginner\"\n                    id=\"toggleBeginnerDetails\"\n                    aria-pressed=\"false\"\n                    title=\"Show beginner explanations\"\n                ><span class=\"detail-toggle-indicator\" aria-hidden=\"true\"></span><span>Beginner</span></button>\n                <button\n                    type=\"button\"\n                    class=\"detail-toggle detail-toggle-advanced\"\n                    id=\"toggleAdvancedDetails\"\n                    aria-pressed=\"false\"\n                    title=\"Show advanced details\"\n                ><span class=\"detail-toggle-indicator\" aria-hidden=\"true\"></span><span>Advanced</span></button>\n            </div>\n        `;\n        return widget;\n    }\n\n    function attachListeners() {\n        const beginnerToggle = document.getElementById(\"toggleBeginnerDetails\");\n        const advancedToggle = document.getElementById(\"toggleAdvancedDetails\");\n\n        if (beginnerToggle && !beginnerToggle.dataset.bound) {\n            beginnerToggle.addEventListener(\"click\", () => {\n                updatePreferences({\n                    ...currentPreferences(),\n                    beginner: !currentPreferences().beginner\n                });\n            });\n            beginnerToggle.dataset.bound = \"true\";\n        }\n\n        if (advancedToggle && !advancedToggle.dataset.bound) {\n            advancedToggle.addEventListener(\"click\", () => {\n                updatePreferences({\n                    ...currentPreferences(),\n                    advanced: !currentPreferences().advanced\n                });\n            });\n            advancedToggle.dataset.bound = \"true\";\n        }\n    }\n\n    function initialize() {\n        const preferences = loadPreferences();\n        applyPreferences(preferences);\n\n        const menuBar = document.querySelector(\".menu-bar\");\n        if (!menuBar) {\n            return;\n        }\n\n        const leftButtons = menuBar.querySelector(\".left-buttons\");\n        if (!leftButtons) {\n            return;\n        }\n\n        if (!document.querySelector(\".skill-control-menu\")) {\n            const widget = createDetailControls();\n            leftButtons.appendChild(widget);\n        }\n\n        syncControls(preferences);\n        attachListeners();\n    }\n\n    function handlePageChange() {\n        setTimeout(initialize, 100);\n    }\n\n    document.addEventListener(\"DOMContentLoaded\", initialize);\n\n    let lastUrl = location.href;\n    new MutationObserver(() => {\n        const url = location.href;\n        if (url !== lastUrl) {\n            lastUrl = url;\n            handlePageChange();\n        }\n    }).observe(document, { subtree: true, childList: true });\n\n    window.addEventListener(\"popstate\", handlePageChange);\n})();\n"
  },
  {
    "path": "docs/acton-guide/theme/guide-links.css",
    "content": "/* Cross-site navigation for the Acton Guide */\n\n.acton-site-links {\n    display: inline-flex;\n    align-items: stretch;\n    align-self: stretch;\n    gap: 2px;\n}\n\n.acton-site-link {\n    position: relative;\n    display: inline-flex;\n    align-items: center;\n    min-height: var(--menu-bar-height);\n    padding: 0 10px;\n    color: var(--acton-yellow, var(--sidebar-active));\n    font-size: 12px;\n    font-weight: 800;\n    letter-spacing: 0.08em;\n    text-decoration: none;\n    text-transform: uppercase;\n    white-space: nowrap;\n}\n\n.acton-site-link:hover {\n    color: var(--acton-chrome-fg, var(--icons-hover));\n    text-decoration: none;\n}\n\n.acton-site-link::after {\n    position: absolute;\n    right: 10px;\n    bottom: 0;\n    left: 10px;\n    height: 3px;\n    border-radius: 999px 999px 0 0;\n    background: transparent;\n    content: \"\";\n}\n\n.acton-site-link.is-active {\n    color: var(--acton-chrome-fg, var(--fg));\n}\n\n.acton-site-link.is-active::after {\n    background: var(--acton-yellow, var(--sidebar-active));\n}\n\n@media (max-width: 780px) {\n    .acton-site-links {\n        margin-left: 4px;\n        margin-right: 8px;\n    }\n\n    .acton-site-link {\n        padding: 0 7px;\n        font-size: 11px;\n        letter-spacing: 0.05em;\n    }\n\n    .acton-site-link::after {\n        right: 7px;\n        left: 7px;\n    }\n}\n\n@media (max-width: 600px) {\n    .acton-site-links {\n        display: none;\n    }\n}\n"
  },
  {
    "path": "docs/acton-guide/theme/guide-links.js",
    "content": "// Cross-site navigation for the Acton Guide.\n\n(function() {\n    const SITES = [\n        { label: \"Guide\", href: \"https://acton.guide/\", active: true },\n        { label: \"Play\", href: \"https://play.acton.guide/\" },\n        { label: \"Ask\", href: \"https://ask.acton.guide/\" }\n    ];\n\n    function createGuideLinks() {\n        const nav = document.createElement(\"nav\");\n        nav.className = \"acton-site-links\";\n        nav.setAttribute(\"aria-label\", \"Acton sites\");\n\n        for (const site of SITES) {\n            const link = document.createElement(\"a\");\n            link.className = \"acton-site-link\";\n            link.href = site.href;\n            link.textContent = site.label;\n\n            if (site.active) {\n                link.classList.add(\"is-active\");\n                link.setAttribute(\"aria-current\", \"page\");\n            }\n\n            nav.appendChild(link);\n        }\n\n        return nav;\n    }\n\n    function initialize() {\n        const menuBar = document.querySelector(\".menu-bar\");\n        const rightButtons = menuBar ? menuBar.querySelector(\".right-buttons\") : null;\n\n        if (!menuBar || !rightButtons || document.querySelector(\".acton-site-links\")) {\n            return;\n        }\n\n        const guideLinks = createGuideLinks();\n        rightButtons.appendChild(guideLinks);\n    }\n\n    function handlePageChange() {\n        setTimeout(initialize, 100);\n    }\n\n    document.addEventListener(\"DOMContentLoaded\", initialize);\n\n    let lastUrl = location.href;\n    new MutationObserver(() => {\n        const url = location.href;\n        if (url !== lastUrl) {\n            lastUrl = url;\n            handlePageChange();\n        }\n    }).observe(document, { subtree: true, childList: true });\n\n    window.addEventListener(\"popstate\", handlePageChange);\n})();\n"
  },
  {
    "path": "docs/acton-guide/theme/sbscode.css",
    "content": "/* Custom table styling for side-by-side documentation */\n.content table.side-by-side-code {\n    display: table;\n    width: 100%;\n    margin: 0;\n    border-collapse: collapse;\n    border: none;\n    background: none;\n    table-layout: fixed;\n}\n\n/* Dark theme support */\n.rust.light-theme .content table.side-by-side-code td:last-child {\n    background: var(--quote-bg);\n}\n\n.rust.dark-theme .content table.side-by-side-code td:last-child {\n    background: var(--quote-bg);\n}\n\n/* Ensure button contrast in both themes */\n.rust.light-theme .content table.side-by-side-code .buttons {\n    background: var(--bg);\n    color: var(--fg);\n}\n\n.rust.dark-theme .content table.side-by-side-code .buttons {\n    background: var(--bg);\n    color: var(--fg);\n}\n\n/* Remove default mdBook table styling */\n.content table.side-by-side-code tbody tr {\n    background: none !important;\n    border: none;\n}\n\n.content table.side-by-side-code td {\n    border: none;\n    padding: 0.5rem;\n    vertical-align: top;\n}\n\n/* Left column (prose) styling */\n.content table.side-by-side-code td:first-child {\n    width: 35%;\n    padding-right: 1.5rem;\n    color: var(--fg);\n}\n\n/* Right column (code) styling */\n.content table.side-by-side-code td:last-child {\n    width: 65%;\n    background: var(--quote-bg);\n    border-radius: 0;\n}\n\n/* Round only the top corners of the first row's code cell */\n.content table.side-by-side-code tr:first-child td:last-child {\n    border-top-left-radius: 4px;\n    border-top-right-radius: 4px;\n}\n\n/* Round only the bottom corners of the last row's code cell */\n.content table.side-by-side-code tr:last-child td:last-child {\n    border-bottom-left-radius: 4px;\n    border-bottom-right-radius: 4px;\n}\n\n/* Hide mdBook's default copy buttons in our special tables */\n.content table.side-by-side-code pre > .buttons {\n    display: none !important;\n}\n\n/* Code block styling */\n.content table.side-by-side-code td pre {\n    margin: 0;\n    padding: 0.5rem;\n    background: none;\n}\n\n.content table.side-by-side-code td code {\n    background: none;\n    padding: 0;\n}\n\n/* Ensure continuous code blocks */\n.content table.side-by-side-code tr + tr td:last-child {\n    padding-top: 0;\n}\n\n/* Hide empty prose cells */\n.content table.side-by-side-code td:first-child:empty {\n    padding: 0;\n    border: none;\n}\n\n/* Position the buttons container */\n.content table.side-by-side-code td:last-child {\n    position: relative;\n}\n\n/* Keep original mdBook button styling for our custom button */\n.content table.side-by-side-code .buttons {\n    position: absolute;\n    top: 0.5rem;\n    right: 0.5rem;\n    opacity: 0;\n    transition: opacity 0.2s;\n}\n\n.content table.side-by-side-code:hover .buttons {\n    opacity: 1;\n}\n"
  },
  {
    "path": "docs/acton-guide/theme/sbscode_copy.js",
    "content": "document.addEventListener('DOMContentLoaded', () => {\n    // Select all side-by-side-code tables\n    const codeTables = document.querySelectorAll('table.side-by-side-code');\n\n    codeTables.forEach(table => {\n        // Get all code cells in this table\n        const codeCells = table.querySelectorAll('td:last-child');\n        if (codeCells.length === 0) return;\n\n        // Create button container div\n        const buttonDiv = document.createElement('div');\n        buttonDiv.className = 'buttons';\n\n        // Create copy button with mdBook's styling\n        const copyButton = document.createElement('button');\n        copyButton.className = 'fa fa-copy clip-button';\n        copyButton.setAttribute('title', 'Copy to clipboard');\n        copyButton.setAttribute('aria-label', 'Copy to clipboard');\n\n        // Add tooltip span\n        const tooltip = document.createElement('i');\n        tooltip.className = 'tooltiptext';\n        copyButton.appendChild(tooltip);\n\n        // Get all code blocks from all cells in this table\n        const getAllCode = () => {\n            const allCodeBlocks = table.querySelectorAll('td:last-child pre code');\n            return Array.from(allCodeBlocks)\n                .map(block => block.textContent)\n                .join('\\n');\n        };\n\n        // Add click handler\n        copyButton.addEventListener('click', async () => {\n            const code = getAllCode();\n            await navigator.clipboard.writeText(code);\n\n            // Visual feedback using tooltip\n            tooltip.textContent = 'Copied!';\n            setTimeout(() => {\n                tooltip.textContent = '';\n            }, 2000);\n        });\n\n        // Add the button to the container and container to the first code cell\n        buttonDiv.appendChild(copyButton);\n        codeCells[0].appendChild(buttonDiv);\n    });\n});\n"
  },
  {
    "path": "docs/acton-guide/theme/tabs.css",
    "content": ".mdbook-tabs {\n    display: flex;\n}\n\n.mdbook-tab {\n    background-color: var(--table-alternate-bg);\n    padding: 0.5rem 1rem;\n    cursor: pointer;\n    border: none;\n    font-size: 1.6rem;\n    line-height: 1.45em;\n}\n\n.mdbook-tab.active {\n    background-color: var(--table-header-bg);\n    font-weight: bold;\n}\n\n.mdbook-tab-content {\n    padding: 1rem 0rem;\n}\n\n.mdbook-tab-content table {\n    margin: unset;\n}\n"
  },
  {
    "path": "docs/acton-guide/theme/tabs.js",
    "content": "/**\n * Change active tab of tabs.\n *\n * @param {Element} container\n * @param {string} name\n */\nconst changeTab = (container, name) => {\n    for (const child of container.children) {\n        if (!(child instanceof HTMLElement)) {\n            continue;\n        }\n\n        if (child.classList.contains('mdbook-tabs')) {\n            for (const tab of child.children) {\n                if (!(tab instanceof HTMLElement)) {\n                    continue;\n                }\n\n                if (tab.dataset.tabname === name) {\n                    tab.classList.add('active');\n                } else {\n                    tab.classList.remove('active');\n                }\n            }\n        } else if (child.classList.contains('mdbook-tab-content')) {\n            if (child.dataset.tabname === name) {\n                child.classList.remove('hidden');\n            } else {\n                child.classList.add('hidden');\n            }\n        }\n    }\n};\n\ndocument.addEventListener('DOMContentLoaded', () => {\n    const tabs = document.querySelectorAll('.mdbook-tab');\n    for (const tab of tabs) {\n        tab.addEventListener('click', () => {\n            if (!(tab instanceof HTMLElement)) {\n                return;\n            }\n\n            if (!tab.parentElement || !tab.parentElement.parentElement) {\n                return;\n            }\n\n            const container = tab.parentElement.parentElement;\n            const name = tab.dataset.tabname;\n            const global = container.dataset.tabglobal;\n\n            changeTab(container, name);\n\n            if (global) {\n                localStorage.setItem(`mdbook-tabs-${global}`, name);\n\n                const globalContainers = document.querySelectorAll(\n                    `.mdbook-tabs-container[data-tabglobal=\"${global}\"]`\n                );\n                for (const globalContainer of globalContainers) {\n                    changeTab(globalContainer, name);\n                }\n            }\n        });\n    }\n\n    const containers = document.querySelectorAll('.mdbook-tabs-container[data-tabglobal]');\n    for (const container of containers) {\n        const global = container.dataset.tabglobal;\n\n        const name = localStorage.getItem(`mdbook-tabs-${global}`);\n        if (name && document.querySelector(`.mdbook-tab[data-tabname=${name}]`)) {\n            changeTab(container, name);\n        }\n    }\n});\n"
  },
  {
    "path": "docs/dev.md",
    "content": "# Development Workflow n stuff\n\n## Changelog\n\nWe keep a `CHANGELOG.md`. It is good practice for PRs to contain a changelog\nentry for whatever they are updating. This is often forgotten and so in\npractice, we often update `CHANGELOG.md` in batches. When making a release,\ncarefully inspect the git log and update `CHANGELOG.md` accordingly. Match the\nstyle and tone in `CHANGELOG.md`. For long descriptive git commit messages or\nwhole branches with multiple commits, write a shorter summary. If the git commit\nmessages are very brief, inspect the code and attempt to sum it up.\n\n\n## Git workflow\n\n- authoritative git repository is https://github.com/actonlang/acton\n  - git clone git@github.com:actonlang/acton.git\n- `main` is the main branch\n- the `main` branch is protected, meaning no one can directly push commits to it\n- commits should happen on a branch, from which a Pull Request (PR) is created\n- the PR can then be merged to `main` via GitHub\n- all PRs should contain a changelog entry in `CHANGELOG.md` under the\n  `Unreleased` heading\n  - this is later used as the body of the release\n\n## Release workflow\n\nThere are two types of releases, \"version releases\" and the `tip` release.\n\n### Versioned release\n- this is like version `1.2.3`\n- create a new branch called `release-v` followed by the version number, like\n  `release-v1.2.3`\n- prepare `CHANGELOG.md` by placing the content currently under the `Unreleased`\n  heading under a version number, like version `1.2.3` instead\n- push branch to GitHub and open PR\n- once the PR is merged, a GitHub Action workflow will take over, create a tag\n  and proceed to build the final release build and upload as an artifact\n  - it will take the content from `CHANGELOG.md` and use as the GitHub Release\n    notes\n  - artifacts from the CI test jobs will be included in the Release as assets\n  - the Release is published at https://github.com/actonlang/acton/releases\n\n### `tip` release\n- this is the binary output from the last successful CI job on the `main`\n  branch\n  - somewhat like a nightly, just more frequent or less - depends on if there is\n    new content on the `main` branch or not\n  - `tip` will identify themselves with the base version number and the date\n    and time when it was built\n    - for example, if v0.4.0 was the last versioned release and a nightly is\n      built, it would be called 0.4.0.2021.08.05.09.27.14, i.e. it was built at\n      09:27:14 on the 5th of August 2021\n  - this is automatically built for every merge on `main`, no extra action is\n    required\n  - the output is stored as a pre-release in Github called `tip`\n    - new releases will overwrite older ones, i.e. only the latest build will be\n      available\n  - the release has a stable URL:\n    https://github.com/actonlang/acton/releases/tag/tip\n"
  },
  {
    "path": "docs/git-develop-workflow.md",
    "content": "# Git Workflow for the `develop` branch\n\nThe Acton repository primarily adheres to the triangular git workflow, where\nfeature branches are used to introduce all changes and these are merged to the\nmain branch through Pull Requests (PRs).\n\nThe `develop` branch is an exception. It is not a feature branch, rather it is\nlong lived. Development happens there for improvements to the compiler and other\nparts that might not be ready to merge in standalone and where it is still\nuseful for others to be able to see (and test) these improvements.\n\nLong lived branches come with certain challenges, in particular how to keep it\nup to date with the `main` branch. Here's a quick cheat sheet:\n\n## Merging things on `develop` branch to `main`\n\n- Before attempting to merge in the commits on `develop` into `main`, it is a\n  good idea to ensure it is up to date with the `main` branch\n  - We accomplish this through **rebasing**.\n  - First we have to make sure the local `main` branch is up to date with the\n    remote at GitHub.\n- After rebase, we need to force push (since we have rewritten the git log).\n- There might be conflicts during rebasing that need to be sorted out manually.\n\n```\ngit checkout main\ngit pull\ngit checkout develop\ngit rebase main\n# maybe sort out conflicts\ngit push --force develop\n```\n\n- Open a Pull Request on GitHub to merge `develop` into `main`\n- GitHub CI tests will run for the `develop` branch on GitHub and if it passes,\n  the PR can be merged\n  - If tests do not pass, chances are there is a test that needs to be marked as\n    not failing anymore or similar. Check CI test output or try running tests\n    locally!\n- If GitHub says there are conflicts during merge, do NOT attempt to solve them\n  in the web browser. Abort!\n  - Instead, repeat the above procedure. Ensure that you pull the main branch so\n    your local branch is up to date with the remove!\n- There is an option in the PR merge to remove the `develop` branch - deselect\n  this option since we want the `develop` branch to remain.\n\n## Updating local `develop` branch from GitHub remote\n\nIf person #1 runs the above workflow of rebasing the `develop` branch on `main`\nin order to bring it up to date, then others who use the `develop` branch will\nneed to update it as well. Since git history has been rewritten, some extra\nsteps need to be taken.\n\n- Ensure git merge only accepts fast forward merges!\n  - This ensures linear history on `develop` by avoiding merge commits\n  - Do this by adding config to your `~/.gitconfig`:\n```\n[pull]\n\tff = only\n```\n- To update your local `develop` branch with the remotes:\n```\ngit checkout develop\ngit pull --rebase --force\n```\n- Any local commits not yet pushed will be rebased upon the remote changes,\n  after this you can push them to the remote with: `git push`\n"
  },
  {
    "path": "docs/git-feature-workflow.md",
    "content": "# Git Workflow for feature branches\n\nThe Acton repository primarily adheres to the triangular git workflow, where\nfeature branches are used to introduce all changes and these are merged to the\nmain branch through Pull Requests (PRs).\n\nFeature branches are well suited to small fixes and well scoped out features\nwhere we know about the scope up front.\n\n## Starting work on a new feature / bug fix\n\n- You should branch out your feature branch from the `main` branch\n- First ensure your local `main` branch is up to date with the remote\n- Give your branch a good name\n  - If there is a GitHub issue for it, you can use the issue number as the\n    prefix, like if you are fixing a bug described in issue #1337, the branch\n    can be called `1337-fix-foobar-bug`\n  - Don't sweat it too much, you can always rename the branch later\n    - to rename, checkout the feature branch, then do `git branch -m\n      1337-fix-blargh-bug` to rename\n\nBranch out feature branch:\n```\ngit checkout main\ngit pull\ngit checkout -b 1337-fix-foobar-bug\n# do some changes\ngit commit ...\ngit push -u origin 1337-fix-foobar-bug\n```\n- Open a Pull Request on GitHub to merge your feature branch into `main`\n- GitHub CI tests will run for the branch on GitHub and if it passes, the PR can\n  be merged\n  - If tests do not pass, chances are there is a test that needs to be marked as\n    not failing anymore or similar. Check CI test output or try running tests\n    locally!\n- If GitHub says there are conflicts during merge, do NOT attempt to solve them\n  in the web browser. Abort!\n  - Fix conflicts by rebasing your feature branch on main, see below.\n  \n## Rebasing your local feature branch\n\n- If the `main` branch has had updates since you branched out your feature\n  branch, you might get a conflict when trying to merge your feature branch back\n  into `main`\n- Fix this by rebasing your feature branch on the new main\n\n```\ngit checkout main\ngit pull\ngit checkout 1337-fix-foobar-bug\ngit rebase main\n# sort out potential conflicts\ngit push --force origin 1337-fix-foobar-bug\n```\n\nThe last step of pushing the branch is sort of optional, but if you have already\nopened a PR as per the above workflow, then you will need to use `--force` when\npushing after a rebase, since you have rewritten git history.\n\n## Cleaning up old local feature branches\n\nOnce you have merged your feature branch(es) upstream, you can remove them\nlocally. First we pull down the `main` branch to ensure we see if things are\nmerged. We use `--prune` which also updates information about remote branches\nand in particular, will remove (prune!) them if they no longer exist.\n\n```\ngit checkout main\ngit pull --prune origin\n```\n\nNow you can go through your branches and remove them with `git branch -d\n1337-fix-foobar-bug`. If the branch is fully merged to `main`, there won't be\nany output, like so:\n\n```\nkll@Boxy:~/terastream/acton$ git branch -d regression-actor-method-call-not-async \nDeleted branch regression-actor-method-call-not-async (was 1a34a28).\nkll@Boxy:~/terastream/acton$ \n```\n\nIf the branch is not merged to `main` nor pushed to the remote, an error is\nraised:\n```\nkll@Boxy:~/terastream/acton$ git branch -d add-git-develop-workflow-cheat-sheet \nerror: The branch 'add-git-develop-workflow-cheat-sheet' is not fully merged.\nIf you are sure you want to delete it, run 'git branch -D add-git-develop-workflow-cheat-sheet'.\nkll@Boxy:~/terastream/acton$ \n```\n\nIf the branch is pushed to the remote but not yet merged to main, a warning will\nbe emitted:\n```\nkll@Boxy:~/terastream/acton$ git branch -d warnings-as-errors \nwarning: deleting branch 'warnings-as-errors' that has been merged to\n         'refs/remotes/origin/warnings-as-errors', but not yet merged to HEAD.\nDeleted branch warnings-as-errors (was 60703e6).\nkll@Boxy:~/terastream/acton$ \n```\n\nYou can then \"undo\" the branch removal by checking it out again, which will\ndefault to checking out what exists on the remote:\n```\nkll@Boxy:~/terastream/acton$ git checkout warnings-as-errors \nBranch 'warnings-as-errors' set up to track remote branch 'warnings-as-errors' from 'origin'.\nSwitched to a new branch 'warnings-as-errors'\nkll@Boxy:~/terastream/acton$ \n```\n"
  },
  {
    "path": "docs/run-example.py",
    "content": "#!/usr/bin/env python3\n\"\"\"Script to run Acton examples embedded in Markdown and update output\n\nWill find first source code example, run it and insert the output back into the\nMarkdown file. The document is expected to contain\n\"\"\"\n\nimport argparse\nimport os\nimport re\nimport subprocess\nimport tempfile\nimport time\n\n# TODO: This is the name of the language for the src block in the markdown file.\n# It should really be acton, but we don't get syntax hilighting with that\n# (nothing supports that), so using python for now\nSRCNAME='python'\n\ndef run_cmd(workdir, cmd):\n    current_dir = os.getcwd()\n    acton = os.path.join(current_dir, \"../dist/bin/acton\")\n    # Run acton in the specified working directory\n    os.environ[\"PATH\"] = os.path.join(current_dir, \"../dist/bin\") + \":\" + os.getenv(\"PATH\")\n    cp = subprocess.run(cmd, shell=True, cwd=workdir, capture_output=True, text=True)\n    # filter out color codes\n    output = re.sub(r'\\x1b\\[[0-9;]*m', '', cp.stdout)\n    output = re.sub(r'Building project in .*', 'Building project in /home/user/foo', output)\n    return output\n\ndef run(source, cmd=None):\n    cmd = cmd or \"acton build && out/bin/example\"\n    with tempfile.TemporaryDirectory() as tmpdirname:\n        print(f\"Got a temp dir: {tmpdirname}\")\n        try:\n            run_cmd(tmpdirname, \"acton new example\")\n            # stupid hack to get around some bug on macos where the newly\n            # created directory (by acton) is not visible to us, how?\n            time.sleep(0.1)\n            source_file = open(tmpdirname + \"/example/src/example.act\", \"w\")\n            source_file.write(source)\n            source_file.close()\n            output = run_cmd(os.path.join(tmpdirname, \"example\"), cmd)\n            return output\n        except Exception as exc:\n            print(exc)\n            print(f\"ERROR, check {tmpdirname}\")\n            time.sleep(60)\n\ndef get_source_from_md(content):\n    \"\"\"Extract Acton source code from Markdown document\n\n    We just get the first source block and it should look like:\n\n        Source:\n        ```acton\n        actor main....\n        ```\n\n    The starting \"Source:\" line is significant. The source block should\n    immediately follow it.\n    \"\"\"\n    look_for = '^Source:$'\n    source = \"\"\n    filename = None\n    for line in content:\n        if look_for == '^Source:$' and re.search(look_for, line):\n            look_for = f\"^```{SRCNAME}\"\n            continue\n\n        if look_for == f\"^```{SRCNAME}\":\n            if not re.search(look_for, line):\n                raise ValueError(f\"Didn't find source block, ```{SRCNAME} should follow the Source: line\")\n\n            m = re.match(r\"^```{SRCNAME} (.+)$\", line)\n            if m:\n                filename = m.group(1)\n            look_for = '^```$'\n            continue\n\n        if look_for == \"^```$\":\n            if re.search(look_for, line):\n                return source, filename\n            source += line\n\n    if look_for == '^Source:$':\n        raise ValueError(\"Didn't find source block, missing 'Source:' line\")\n\n\ndef get_run_from_md(content):\n    \"\"\"Extract Acton source code from Markdown document\n\n    We just get the first run block and it should look like:\n\n        Run:\n        ```sh\n        acton test\n        ```\n    \"\"\"\n    look_for = '^Run:$'\n    source = \"\"\n    for line in content:\n        if look_for == '^Run:$' and re.search(look_for, line):\n            look_for = f\"^```sh$\"\n            continue\n\n        if look_for == f\"^```sh$\":\n            if not re.search(look_for, line):\n                raise ValueError(f\"Didn't find source block, ```{SRCNAME} should follow the Source: line\")\n            look_for = '^```$'\n            continue\n\n        if look_for == \"^```$\":\n            if re.search(look_for, line):\n                return source\n            source += line\n\n\ndef write_output_to_md_content(output, md_content):\n    new = \"\"\n    look_for = '^Output:$'\n    for line in md_content:\n        if look_for == '^Output:$':\n            new += line\n            if re.search(look_for, line):\n                look_for = \"^```sh$\"\n                continue\n\n        elif look_for == \"^```sh$\":\n            new += line\n            if not re.search(look_for, line):\n                raise ValueError(\"Didn't find output block, ```sh should follow the Output: line\")\n            new += output\n            look_for = '^```$'\n            continue\n        elif look_for == \"^```$\":\n            if re.search(look_for, line):\n                new += line\n                look_for = None\n                continue\n        elif look_for is None:\n            new += line\n\n    if look_for == '^Output:$':\n        raise ValueError(\"Didn't find output block, missing 'Output:' line\")\n\n    return new\n\n\ndef write_md(fn, content):\n    with open(fn, \"w\") as f:\n        f.write(content)\n\n\ndef process(md):\n    f = open(md, \"r\")\n    md_content = f.readlines()\n    f.close()\n    #print(\"MARKDOWN:\")\n    #print(\"----------------------------------------------------\")\n    #print(\"\".join(md_content))\n    #print(\"----------------------------------------------------\")\n    source, src_file = get_source_from_md(md_content)\n    cmd = get_run_from_md(md_content)\n    #print(\"SOURCE:\")\n    #print(source)\n    output = run(source, cmd)\n    #print(\"OUTPUT:\")\n    #print(output)\n    new_md = write_output_to_md_content(output, md_content)\n\n    print(\"NEW MARKDOWN:\")\n    print(\"----------------------------------------------------\")\n    print(\"\".join(new_md))\n    print(\"----------------------------------------------------\")\n    write_md(md, new_md)\n\n\n\nif __name__ == '__main__':\n    parser = argparse.ArgumentParser()\n    parser.add_argument(\"md\", nargs=\"+\")\n\n    args = parser.parse_args()\n\n    for md in args.md:\n        process(md)\n"
  },
  {
    "path": "docs/triage.md",
    "content": "# Bug triage and prioritization\n\nThis isn't some hard line policy but rather a softer guideline on how to think\nwith regards to triaging and prioritizing of bugs in Acton.\n\n- silent errors\n  - we prioritize silent errors over those that emit explicit error messages\n  - for example, there was a bug that cause integer subtraction to give the\n    wrong results; 5-1 = 3 and stuff like that\n    - debugging this program is harder than when presented an explicit error\n- seg faults\n  - this causes a general feeling of brokenness and without a descriptive error\n    message, it is rather difficult to work around\n- things without workarounds\n  - with type errors it is often possible to work around by adding type\n    signatures or explicit type conversions, thus they have lower priority\n    compared to bugs that are not as simple to work around\n- other bugs\n"
  },
  {
    "path": "docs/tutorial/README.md",
    "content": "# Acton tutorial\n\n## Introduction\n \nActon is a general purpose programming language, designed to be useful\nfor a wide range of applications, from desktop applications to\nembedded and distributed systems. In a first approximation Acton can be\ndescribed as a seamless addition of a powerful new construct to an\nexisting language: Acton adds ***actors*** to ***Python***.\n \nThe aim of this document is to serve as a tutorial on Acton for a reader\nfamiliar with Python. The presentation is mainly through examples,\nchosen to illustrate both similarities and differences between the two\nlanguages. As befits a tutorial, the examples are short and simple,\nbut we hope that they are chosen in a way that helps the reader to see how the\nconcepts illustrated scale to more complex situations. \nWe also try to explain the considerations that has led the\nActon designers to deviate from Python, where this is the case. However,\nthe document is not a comprehensive description of the Acton language.\nIn fact, both the language definition and its implementation is\ncurrently under active development, so some minor aspects of what we \npresent here may be subject to change.\n \n \nWe recommend the reader to [download and install Acton](https://github.com/actonlang/acton#install-acton)\nand to play with the examples.\n\n## Background: Actors and Python\n \nBefore we turn to examples, we briefly discuss actors and Python and the\nreasons for basing Acton on this foundation.\n \n* The actor model for (concurrent) computation goes back to work by Carl\n  Hewitt around 1970 and has been influential ever since, even though\n  its direct impact on mainstream computation has been limited. However,\n  recent developments, where multi-core processors have become ubiquitous\n  and cloud computing is rapidly growing in importance, have put focus on\n  the shortcomings of mainstream tools and methodologies for concurrent\n  programming, based on shared memory and threads, requiring\n  synchronization and coordination using locks and similar tools. Many\n  observers have come to the conclusion that this methodology is\n  inadequate in the current and future computing landscape. \n   \n  Actors offer a promising approach to addressing this bottleneck by\n  providing a simpler programming model. The notion of actors provides\n  a conceptual framework, and concrete, actor-based languages and libraries\n  take different forms. For our purposes, we think of\n  an actor as an entity, which interacts with other actors only through\n  message-passing. An actor may encapsulate some private state, which\n  can be accessed and modified only through messages in its  ***interface***, a\n  description of the message forms that the actor can handle. Each actor\n  has a  ***mailbox***, i.e. a queue where incoming messages are stored,\n  waiting to be processed. In response to receipt of a message an actor\n  can perform some computation, send messages to other actors, create\n  new actors and update its state. Sending a message is an\n  asynchronous operation, i.e. the sender asks the runtime\n  system to supply the necessary service (delivering the message in\n  the receiver's mailbox) and can immediately proceed with its\n  processing of the current message. \n    \n  The runtime system guarantees that\n  an actor only serves one message at a time, but of course several\n  actors may be active in parallel. Therefore, actors can be used for\n  synchronization and coordination of concurrent activities. It turns\n  out that this simple and intuitive construct gives great power for\n  concurrent and distributed programming, and suggests a programming\n  style that naturally avoids common pitfalls.\n   \n  At the top level, an Acton program is an ensemble of actors.\n  In-between processing messages, actors are idle, just maintaining\n  their state. An intuitive view of an Acton system is therefore that it\n  alternates between being idle and being engaged in a burst of\n  activities in response to an incoming message. So, an Acton program is\n  a  ***reactive*** system. Also this notion has recently received a lot\n  of attention, as witnessed by the [Reactive Manifesto](https://www.reactivemanifesto.org).\n  \n  In some respects actors can appear to be quite similar to class\n  instances, which also maintain an internal state that can be\n  manipulated through method calls. However, there are also major\n  differences. We defer a fuller discussion of this to Example 3\nbelow.\n \n* A major design decision in Acton is therefore to adopt the actor \n  programming model as a base for the large-scale structure of\n  programs. It remains to embed this model in a concrete programming\n  language, either as a library or middleware package in an existing\n  language, or to design a new programming language. For reasons to \n  be discussed below, Acton is a new language, but is also very\n  closely related to Python.\n \n  Python has over many years acquired a large and enthousiastic user\n  base. Programmers appreciate its light-weight syntax based on\n  indentation and its native support for a variety of programming\n  styles, including imperative, functional and object-oriented idioms.\n  Acton capitalizes on this appeal by adopting Python syntax, making\n  Acton immediately accessible to the Python programmer for programming\n  in the small, i.e. defining functions and classes.\n \n  Part of the appeal of Python lies also in the lack of variable and\n  type declarations, accompanied by liberal polymorphism, dynamic\n  typing and an interactive interpreter environment. All of this enables\n  a quick development cycle, but it also implies that many errors in\n  Python programs are caught only at runtime. Acton follows Python in\n  the lack of declarations (it has the same syntax!), but adopts\n  a much stricter discipline of\n  static checks. In particular, Acton is statically typed with an\n  expressive type language and type inference. Also, scope rules are\n  modified to avoid runtime errors caused by uninitialized variables.\n  See Examples 1 and 2 for more detail.\n \nAt the syntax level, the addition of actors to the Python base just\nmeans a new keyword `actor` and a new form of compound statement,\n`actor Name(params): suite`, similar to class and function definitions.\nThus, in spite of the fact that Acton is a new language, it is\nsufficiently close to Python that Python programmers will comfortably\ntransition to Acton programming. We would even dare to conjecture that\nprogramming in Acton will come more natural than use of existing\nlibraries for programming with actors in Python. Also, many Python\nlibrary packages will also be valid Acton code.\n \nFor the Acton programmer, there is no notion of threads to consider\nand no need of locks, semaphores or other low-level synchronisation\nprimitives. Threads enter instead at the level of the runtime system,\nwhere a thread pool works on the collection of tasks formed by idle\nactors with non-empty mailboxes, each thread repeatedly picking an\nactor/message pair and executing the actor's message-processing code.\nThis implementation permits efficient utilization of multi-core\nprocessors. Also distribution of tasks across machines can be done\ntransparently.\n \nThe execution environment of an Acton program is also modelled by an\ninterface similar to that of an actor, i.e. we think of the external\nworld as an actor with which the program interacts. The interface to\nthis exterior world can vary greatly, depending on the type of\napplication and the computing environment, and an Acton installation may\noffer one or more interfaces, with supporting runtime system.\n\n ## Examples\n \nThe rest of this tutorial consists of a sequence of short examples. In\nconnection with some of them we discuss Acton design decisions and\ndifferences between Python and Acton.\n \n \nAs will become clear from the examples, Acton is a compiled language,\nas C or Java.\nPrograms are written to files which are compiled to produce executable files,\nwhich can be run. There is currently no interactive environment,\nwhere programs can be developed and tested in a read/eval/print loop.\n\n* [Hello World](example-0.md)\n* [Harmonic Number](example-1.md)\n* [Prime numbers](example-2.md)\n* [Actors vs Classes](example-3.md)\n"
  },
  {
    "path": "docs/tutorial/example-0.md",
    "content": "# Example 0 - Hello World\n\nWe follow tradition and introduce Acton programming with the following minimal example\n\n```py\nactor main(env):\n    print(\"Hello, World!\")\n```\n\nWe already mentioned that an executing Acton program consists of a\ncollection of interacting actors. Here we have just a single actor,\nwhich has been given the name `main`. By convention, the\n***root actor*** of a system takes a parameter `env` which\nrepresents the execution environment, i.e. `env` has fields and\nmethods for accessing command line arguments, reading from and writing\nto keyboard/screen and files, working with sockets etc. When the\nprogram is executed, the runtime system creates the root actor,\nhands it an `env` object and runs its initialization code, which here is\njust a single command, to print a message on screen.\n\nThe careful reader may ask why `print` is not a method of\n`env`. The answer is that we see `print` as a useful tool\nfor tracing program execution, and this should be\npossible without having to thread an `env` parameter to all subunits.\n\nTo compile the program, assuming that it is saved in\n`world.act`, the command is\n\n``` shell\n$ acton world.act --root main\n```\n\nThis creates an executable file `world` in the same directory,\nwhich can be run to see the familiar message.\n\nFinally, let's modify the program to greet not the world, but a name\ngiven on the command line:\n\n```py\nactor main(env):\n    print(\"Hello, \" + env.argv[1] + \"!\")\n```\n\nThe field `env.argv` is the list of command line arguments\n(with element 0 the name of the shell command, and element 1 the first proper\nargument).\n"
  },
  {
    "path": "docs/tutorial/example-1.md",
    "content": "# Example 1 - Harmonic numbers\n\nEven though the top level view of an Acton program is that of a\ncommunity of interacting actors, function and method definitions play\nmajor roles in a program; typically the bulk of the program text is a\ncollection of `def`'s. Here is a simple function\ndefinition, which is valid in both Python and Acton:\n\n```py\ndef harmonic(n):\n    sum = 0\n    for i in range(1,n+1):\n        sum += 1/float(i)\n    return sum\n```\n\nFor a given non-negative integer argument ***n***, `harmonic(n)` computes\nthe ***n***'th harmonic number, i.e. 1+1/2+1/3+ ... +1/***n***.\nWe can use this definition together with a simple actor that expects\nthe integer argument to `harmonic` on the command line:\n\n```py\nactor harmonicMain(env):\n    print(harmonic(int(argv.env[1])))\n```\n\nWe used the name `harmonicMain` for this actor just to emphasize\nthat there is no name convention for the root actor in Acton; instead\nits name is given to the compiler. So to compile and run this program\n(saved to `harmonic.act`) we do:\n\n```shell\n$ acton harmonic.act --root harmonicMain\n$ ./harmonic 2\n1.5\n$ ./harmonic 10000\n9.7876\n```\n\nLet's make the program a bit more interesting by making it\ninteractive, repeatedly inputting an integer from the user and\noutputting the corresponding harmonic number. We have to change the\nactor:\n\n```py\nactor harmonicMain2(env):\n    def response(input):\n        print(harmonic(int(input)))\n\n    env.stdin_install(response)\n```\n\nThis actor definition has two parts: first we have the definition of a\nlocal method `response`, which describes how the actor should react\nto one line of user `input`. Then follows the actor\ninitialization code, which simply installs `response` as a\ncallback in the environment.\n\nProgram execution starts by running the root actor's initialization\ncode. After that, the program is idle, waiting for\nuser input on `stdin`. When such\ninput arrives, the callback is executed, i.e. the input string is\nconverted to an integer, which is given as argument to\n`harmonic`, the result is printed and the program is again idle. \n\nThis program has obvious shortcomings: there is no prompt to the user,\nno check that the input is actually a string that can be converted to\nan integer, and no way to terminate the program except by some interrupting\nsignal. In spite of this, we leave the program as it is, with one\nfinal note.\nWe have implicitly assumed that both the function declaration and the\nactor declaration are in the same file. Of course, we could have the\nfunction declaration in a separate library file, say\n`functions.act`, and the actor in `main.act`. In that\ncase, we need to add a line at the beginning of the latter file,\nsaying\n\n```py\nimport functions\n```\n\nOur main reason for using function `harmonic` as an early\nexample is not the mathematics, but to use it to discuss the different type\ndisciplines and scope rules of the two languages. Acton adopts many\nstatic checks in order to find programming errors at compile\ntime rather than during execution. Some readers may prefer to proceed\nto the next example at a first reading and come back to the following\ndiscussion later.\n\n## Typing in Python and Acton\n\nBoth Python and Acton use types as a sanity check\non computations, but in very different ways.\n\nPython uses ***dynamic*** typing, i.e. type-checking occurs at runtime.\nAll values have their type attached, and before the interpreter attempts\nan operation, the types of operands are checked to be compatible with\nthe operation. To roughly see how this works, consider the call\n\n```py\nharmonic(3)\n```\n\nThe definition above ***binds*** the name `harmonic` to an\nobject of type `function`. This type means only that we may use the\nobject in a function call. Thus, parameter `n` is bound to the\ninteger 3, and the function body is executed. 3 will be added to 1, which is fine;\ninteger values can be added. The result is used as the second argument\nto `range`, which also is type-correct since the builtin function\n`range` has known type and expects integer arguments. In similar\nstyle types are checked at each step until we arrive at the final value\n1.8333333333333333. If we instead would try to compute \n\n```py\nharmonic(7.5)\n```\n\nThe interpreter will happily start the computation, but stop when it\nsees that the value 8.5 will be used as second argument to\n`range`. This does not make sense, so execution is interrupted\nand a `TypeError` exception is raised.\n\nActon, on the other hand, uses ***static*** typing, i.e. all types are\ninferred at compile time, starting from known types of all builtin\nfunctions and objects. The type inference algorithm analyzes the\nfunction definition and sees for example that `n+1` is second argument to\nthe builtin function `range`, which in Acton has the much more\ninformative type `(int,int) -> int`. (This is a slight\nsimplification; `range` actually takes ***three*** integer\narguments, where the optional third argument has default value 1.) Thus `n+1` must be an\n`int`, and hence `n` must also have type `int`. In a similar\nway it can conclude that the function result will be a `float`,\nand hence that `harmonic` has type\n`(int) -> float`, i.e. it is a function that takes\nan integer argument and produces a floating point result. We note that\nin a static typing discipline types are assigned to variables, not to values; type inference is done at\ncompile time and no values are yet computed. Acton also has a much\nmore expressive type language than Python. The more detailed type of\n`harmonic` in Acton makes it easy to infer already at compile time\nthat `harmonic(7.5)` is a type error. Thus a program containing\nthat application is rejected and we avoid a later runtime error.\n\nStatic typing also implies that there is no need for type-checking at\nruntime. This is a minor efficiency advantage, but in addition the extensive type\ninformation available at compile time gives a strong basis for\nproper compilation to machine code, a move that promises major \ngains in execution efficiency compared to Python's interpretation model.\n\n## Scope rules in Python and Acton\n\nTo discuss this, we consider a slight variant of this function. In fact, it is an\ninferior version, which we show only to be able to discuss the \ndifferent scope rules.\n\n```py\ndef harmonic2(n):\n    if n>=0:\n        sum = 0\n        for i in range(1,n+1):\n            sum += 1/float(i)\n    return sum\n```\n\nThis code could be the result of the following misguided\nthinking: harmonic numbers only make sense for non-negative ***n***, so we should\ncheck for that in the function body. However, the result is that\n***if*** the function is called with a negative argument, the\nvariable `sum` has not been assigned any value before it is returned. If\nwe try to compute `harmonic2(-1)`, the interpreter will note,\nbefore returning `sum`, that the variable is unbound and raise an\n`UnboundLocalError`. So, this function definition is valid\nPython and works as intended for non-negative arguments, but using it\nwith a negative argument results in an exception at runtime. The reader\nshould not be surprised to learn that this function definition is\nrejected by the Acton compiler. In this case the problem is not with\ntypes; instead the ***scope rules*** of Acton rule out the definition.\n\nScope rules define where in the program text names become bound\n(i.e. acquire meaning) and in which part of the program these bindings\nare valid. In Python, since `sum` does become bound in the body\n(the statement `sum = 0`), the variable is, surprisingly, in\nscope in the ***whole function body***, also after the `if` statement, in\nspite of the fact that execution of the binding statement may not have\nbeen executed (which is exactly what happens when ***n*** is negative).\n\nWe defer a detailed discussion of scope rules to section 3.3 below. Here we\njust note that in Acton `sum` will not be in\nscope in the `return` statement, for exactly the reasons hinted\nat above. In general, Acton adopts scope rules that rule out\nruntime errors because of unassigned variables. The problem with\n`harmonic2` \ncan be fixed by moving the initialisation of `sum` to before\nthe `if` statement, by adding an `else` clause that also\ndeclares `sum` or, preferably, by sticking to our first definition.\n\nIn summary, Example 1 shows two function definitions, which both are\nvalid in Python, but which may result in runtime errors when applied.\nActon avoids these problems, in one case by discovering type problems in\nan application of the function already at compile time, and in the other by\nrejecting the definition altogether, since it allows also type-correct\nuse to give a runtime error.\n\nOf course, we cannot expect to avoid runtime errors completely. Programs\nexecute in an environment where errors may be caused by external\nfactors: faulty sensors, failing networks, corrupt files, etc. But\nActon adopts the point of view that runtime errors which are caused not by the\nexternal world but by programming mistakes should be avoided as far as\npossible. Thus extensive static checks are performed at compile time.\n\nIn Python, numeric code is often best written using the [NumPy](https://numpy.org/) package.\nActon provides a package with some of the functionality of NumPy; to\nsee how this is used to express function `harmonic`, see [WIP].\n"
  },
  {
    "path": "docs/tutorial/example-2.md",
    "content": "# Example 2 - Prime numbers\n\nHere is another function definition, which is valid both in Python and\nActon:\n\n```py\ndef primesTo(n):\n    isPrime = [True] * n\n    isPrime[0] = False; isPrime[1] = False\n    for i in range(2,int(math.sqrt(float(n)))+1):\n        if isPrime[i]:\n            for k in range(i*i,n,i): isPrime[k] = False\n    return [i for i in range(2,n) if isPrime[i]]\n```\n\nThis function computes, for given ***n***, the list of all prime numbers\nsmaller than ***n***, so `primesTo(20)` is\n`[2, 3, 5, 7, 11, 13, 17, 19]`. The function uses the\nancient and remarkably efficient sieve algorithm discovered by the Greek\nmathematician Eratosthenes around 200 BC. On a typical laptop this\nfunction will compute the 78498 primes less than a million in a small\nfraction of a second.\n\nBut again we are more interested in the data structures used and their\ntypes. In the function body, `isPrime` is bound to a list of $n$\nBoolean values, i.e. the elements of the list are `True` or\n`False`. Like all lists in Python, `isPrime` will get the builtin type\n`list`. Also the function result is a `list`, but this time a list\nof integers. The type, however, cannot express this difference; \nthis is also just a `list`. We have here an example of\n***polymorphism***, i.e. a type of container which may contain elements\nof different types. In Python this polymorphism is unrestricted; even a\nsingle list can contain elements of many different types. As an example,\nwe can form the list `[3,\"hi\",lambda n: n*n]`, consisting\nof one integer, one string and one function.\n\nExamples where this freedom is essential, or even useful, are relatively\nscarce. On the other hand, it is easy to see that it may cause trouble:\nwhen we traverse a list we do not know the types of the values we\nencounter and hence not which operations we may meaningfully perform on\nthem. Acton does not allow full polymorphism, but adopts a more limited\nform which is both type-safe and has proven very useful\nin practice: ***parametric*** polymorphism. This means that we can have\nlists of integers, lists of strings, lists of lists of floats etc. but\nthat in a given list, all elements have the same type. Thus we have not\none all-encompassing type of lists, but a whole family of types\n`list[A]` where `A` is a ***type variable***, which can be\n***instantiated*** to an arbitrary type. So `isPrime` has type\n`list[bool]` and the function `primesTo` has type\n`(int) -> list[int]`. The function `primesTo`\nitself may be inserted as an element in a list of type\n`list[(int) -> list[int]]`. Type safety means that\nwhenever we encounter an element of such a list, we know that we can\napply it to an integer and get a list of integers as result.\n\nTo complete the example, here is an actor which accepts ***n*** on the command\nline and prints not all the primes but only the number of primes smaller than ***n***:\n\n```py\nactor main(env):\n   print(len(primesTo(int(env.argv[1]))))\n```\n\nTo find the number of primes, we use the function `len`, which\nin Acton as in Python computes the length of its argument. So, it\nwould seem that `len` har type `(list[A]) -> int`,\ni.e. it works independently of the type of elements of the list. This\nis indeed so, but it doesn't stop there. However, also in this case\nyou may want to come back to the rest of this discussion in a future reading.\n\nYou may recall that in\nPython, the function `len` can be applied not only to lists,\nbut also to strings, sets and dictionaries (and other classes, which\ndefine the method `__len__`). This is also the case in Acton,\nand requires a new concept to ensure safe static typing.\n\nWe need a general mechanism for\n***overloading***, i.e. allowing several functions, with separate\ndefinitions, to be denoted by the same name. In fact, we have already\nseen overloading in previous examples:\nwe have used + to denote addition both of `int`s and\n`float`s, quite different operations at the machine level. Many\nlanguages overload arithmetic operator symbols in ad hoc ways.\nWhat we look for is a general method to introduce new\noverloadings. \n\nThe general type of `len` in Acton is `(Collection[A]) -> int`,\nwhere `Collection` is a builtin ***protocol***. A protocol\nis a collection of ***type signatures***. In order to\n***implement*** the protocol a type must implement methods of the\nrequired signatures. The protocol `Collection` specifies two\nmethods, `__len__` and `__fromiter__`. So, all the\nbuiltin types `list[A]`, `set[A]`, `dict[A, B]`\nand `str` implement this protocol and thus we can compute lengths of\nobjects of these types. The type system, remarkably, allows overloading to be resolved\nat compile time, i.e. the compiled code invokes the correct instance\nof all overloaded functions at each occurrence.\n\nWe cannot here discuss protocols in depth. We just note that\nthe use of the word 'protocol' for this concept is taken from Swift. \nThe concept is also closely related to the notion of ***type classes*** in\nHaskell.\n"
  },
  {
    "path": "docs/tutorial/example-3.md",
    "content": "# Example 3: Actors vs classes\n\nWe now turn to classes and actors, which, as we have already mentioned, \nhave some similarities, but also major differences. We consider a \nclassical example of an object with state, the counter. \n\n![Counter](images/counter.png)\n \nThe counter allows three operations: its value can be `inc`reased\nby one (the ``button'' on top), `reset` to zero (the knob on the right) or\n`read` (the display). The use case for this particular variant of a counter is\nto keep track of the number of inc's performed since the counter was last reset.\n \nBelow are two valid Acton definitions, modelling the counter. The left\none is also a valid class definition in Python. We also show some\nsimple, typical use of the definitions.\n\n```py\nclass CounterC():                               actor CounterA(initval=0):\n                                           \n    def __init__(self,initval=0):                 var val = initval\n        self._val = initval                \n                                           \n    def inc(self):                                def inc():\n        self._val += 1                                val += 1\n                                           \n    def read(self):                               def read():\n        return self._val                              return val\n                                              \n    def reset(self):                              def reset():\n        self._val = 0                                 val = 0\n                                           \n\nactor main(env):                               actor main(env)             \n    c = CounterC(5)                                a = CounterA(5)\n    c.inc()                                        a.inc()\n    c.inc()                                        a.inc()\n    v = c.read()                                   v = a.read()\n    print(v) # prints 7                            print(v)  # prints 7\n                                           \n```\n \nWe see striking similarities and some minor differences between the two\ndefinitions:\n* Most strikingly, the definitions are used in exactly the same way: we\n  create a class instance/an actor with initial value 5, we increase its\n  value twice and finally read the counter value, which in both cases\n  will be 7.\n\n* The definitions of methods are almost\n  the same; the differences are the occurrences of `self` in the\n  class (and our choice of having an underscore in the name of the\n  instance variable).\n\n* There is no `__init__` method in the actor definition;\n  instead the optional initial value is a parameter to the actor name.\n  Thus parameters in an actor definition have another meaning than in a class\n  definition (where they denote superclasses).\n \n* The state variable `val` is explicitly declared in the actor definition,\n  introduced by the keyword `var`.\n \nThus, we can use both class and actor definitions to create objects with\nstate that can be manipulated and accessed through methods. But the\nsyntax and the similaritites tend to downplay the fundamental difference\nbetween the two concepts:\n\n* The method call `c.inc()` is essentially an ordinary function\n  call (with the receiving object as first parameter). A thread that\n  executes this call will transfer control to the function body, execute\n  the body, which will update the state variable, and continue.\n\n* The statement `a.inc()`, on the other hand, looks exactly the\n  same but denotes the sending of the message `inc()` to the\n  actor `a`. A thread executing the call will ask the runtime\n  system for this service and proceed immediately with the next\n  statement. The message will be queued and the actual increase of\n  `a`'s state will be done at some later point in time,\n  probably by some other thread.\n \nThis difference means that the actor `a` can be used as a member\nof the community of actors comprising a program, providing the service\nof a shared counter. It keeps track of the number of `inc`\nmessages received, for which it can be queried in a `read` message.\n \nThe class instance, on the other hand, can ***not*** be safely used in this\nway. Imagine that we could create class instance `c` and place it as a\ntop level member in a community of actors. Since the operation of\nincreasing the value of an integer variable is not thread-safe, it is\nconceivable that two concurrent threads, doing message processing for\nactors using the class instance, will execute `c.inc()` in\nparallel, both read the same `_val` and increase it by 1 before\nwriting back, with\nthe net result that the two calls will only increase the counter by one.\n \nThe conclusion is that classes and class instances do have a role to\nplay in Acton: instances can be used as (part of) the internal\nstate in actors, but not as replacement for actors. To illustrate this\npoint in an exaggerated way, the following would be a legitimate and\nsafe use of class `CounterC`:\n \n```py\nactor CounterA(initval = 0):\n\n    var c = CounterC(initval)\n\n    def inc():\n        c.inc()\n\n    def read():\n        return c.read()\n\n    def reset():\n        c.reset()\n```\n \nHere, there is no risk of multiple threads causing problems, since the\ncalls to `c`'s methods occur within the processing of an\nactor message. We certainly do not recommend this design, since the\nexample is too trivial. The internal\nstate of the actor is as easily modelled by an integer variable, so the\nuse of a class instance here seems to offer no advantage. For an\nexample where a class instance would be a natural choice as\nstate we can think of a sorted container (set, list or dictionary or\n...), i.e. a container which also supports an operation to retrieve its\nelements in sorted order. Here some form of binary search tree would be a\nnatural candidate to represent the state. More generally, any data\nstructure implemented as a class can be made thread-safe by wrapping\nit in an actor as indicated here.\n\n## On templates, instances and message passing\n \nA class declaration is a template for\nobjects. Every time we execute `c = CounterC()` we get a new\n***instance*** of the class `CounterC` with its own copy of\nthe state `_val`.\n \nThe situation is the same for actors. Executing `a  =\nCounterA()` creates a new actor instance of the \"actor class\"\n`CounterA` with its own copy of the\nstate `val`. However, following established terminology but\nmaybe a bit confusing at first, we refer also to the instance just as an actor.\n \nThe syntax for sending a message to an actor `b`,\nwhere `b` is an instance of actor (class) `B`, is\n`b.m(args)`, where `m` must be a method declared in `B`\nand `args` are suitable arguments. Thus, actor \n`a` can only send a message to actor\n`b`, if `a`  knows the name of \n`b`. This can be obtained in only two ways:\n\n* The name is obtained when `b` is created, as in \n  `b = CounterA()`. The name is completely opaque; there are no\n  operations that apply to it and it cannot be programmatically\n  constructed. Thus, if  `a`  actually created\n  `b`, then `a` knows the name of, and can send messages\n  to, `b`.\n\n* The only other way that `a` may know the name\n  is that it has received the name in a message, from an actor who\n  already knows `b`. That actor could possibly be `b`\n  itself, using the reserved word `self`.\n\nIf `a` sends two asynchronous\nmessages to `b`, the first message sent is guaranteed to be delivered\nbefore the second. But this is the only guarantee that Acton makes as\nto delivery order. If a third actor `c` also sends messages to\n`b`, nothing can be said about the arrival order between two\nmessages with distinct senders. To be a bit more concrete, consider a\ncommunity of worker actors that use a `CounterA` actor `a` to keep track\nhow many times a certain task has been performed. To this end, all the \nworkers call `a.inc()` each time they have completed the\ntask. We consider two scenarios:\n\n* A method call `a.read()` which is done when \n  the system is idle, will accurately report how many tasks have\n  been completed.\n\n* Regardless of the state of the system, if one of the workers\n  calls `a.read()`, the returned value will certainly include\n  all tasks completed and reported by that worker. For task\n  completions reported by other workers, we cannot say whether \n  tasks completed ``recently'' will have been counted or whether the\n  corresponding `a.inc()` messages remain in `a`'s\n  mailbox, to be processed after the reading of the counter.\n"
  },
  {
    "path": "docs/wrapping_c_libraries.md",
    "content": "# Wrapping C libraries in Acton\n\nThis document attempts to provide a brief introduction to using C for implementing functions and actors in Acton. The Acton stdlib is the only real use case where C is used. All other libraries and applications are implemented in pure Acton. Thus, this document is for those of you that intend to contribute to Acton's stdlib.\n\nActon is a compiled language and C is used as an intermediate representation. Acton programs are turned into C which in turn are compiled to machine code using a standard C compiler. This makes it conceptually straightforward to integrate C libraries into Acton; we \"just\" need to write C code that looks the way that the Acton compiler would have written it! The simplest way to achieve this is to first have the compiler generate some C code for us, which we can go ahead and modify to our hearts content.\n\nC can be used to implement a whole module or individual functions and methods. Regardless to which extent C is used, the modules interface needs to be specified in Acton so that the Acton compiler has a view of the interface with types. While Acton has an advanced type inferencer, it is not able to inspect C code and reverse engineer the types used. It can infer the type based on how the module might be used, but it is much safer and thus recommended to write a type signature for all functions implemented in C.\n\nAs an example, we will create our own `time.foo()` function, which will be a duplicate of the `time.time()` function.\n\nStart by writing the Acton declaration of the function in `stdlib/src/time.act`:\n```Acton\ndef foo() -> float:\n    \"\"\"Return the current real time\n    \"\"\"\n    return 3.14\n```\n\n`foo()` does not take any arguments and returns a float. We provide a short description of the function and write a dummy return statement. This is so that we may generate some boilerplate code.\n\nRun `acton --cgen stdlib/src/time.act` to generate C code. The `foo()` function will be called `time$$foo` and should look something like (may change with compiler version):\n```c\n$float time$$foo () {\n    $RealFloat w$232 = (($RealFloat)$RealFloat$float$new());\n    return (($float (*) ($RealFloat, $atom))w$232->$class->__fromatom__)(w$232, (($atom)to$float(3.14)));\n}\n```\n\nChange the code in `stdlib/src/time.act` to replace the function body with `NotImplemented`:\n```Acton\ndef foo() -> float:\n    \"\"\"Return the current real time\n    \"\"\"\n    NotImplemented\n```\nThis instructs the Acton compiler to not generate C code for this function if an external definition C file exists.\n\nNext, paste in the copied C code into the external C definition file `stdlib/src/time.ext.c`:\n```c\n$float time$$foo () {\n    $RealFloat w$232 = (($RealFloat)$RealFloat$float$new());\n    return (($float (*) ($RealFloat, $atom))w$232->$class->__fromatom__)(w$232, (($atom)to$float(3.14)));\n}\n```\n\nRecompile everything and write a test program that uses the new function:\n```Acton\nimport time\nactor main(env):\n    print(time.foo())\n    exit(0)\n```\n\nAnd it should print `3.14`! We can now go ahead and modify `stdlib/src/time.ext.c` to implement the actual functionality we want, like so:\n```\n$float time$$foo () {\n    struct timespec ts;\n    if (clock_gettime(CLOCK_REALTIME, &ts) == -1) {\n        $RAISE((($BaseException)$RuntimeError$new(to$str(\"Unable to get time\"))));\n    }\n    return to$float(ts.tv_sec + 0.000000001*ts.tv_nsec);\n}\n```\n\nActon values are boxed and are available in C as `$float`, `$int`, `$str` etc. You will need to convert your machine native values into Acton values.\n\n## Considerations\n\n- The Acton RTS runs multiple concurrent threads that run actors and as such it is of utmost importance that the C libraries used are thread safe.\n\n- All functions in Acton are run synchronously. Never ever ever perform I/O (which might never complete) or other similar operations, instead, model your C thing as an actor. Actor methods calls are always asynchronous and thus might never return. By design, there is no way to do blocking I/O in Acton, however, since you are writing things in C, there's enough rope to hang yourself (and your Acton system)...\n\n- Actors can be resumed if they die or are migrated from another compute node. If you keep state, make sure it survives a resumption (and implicitly the snapshotting of its state). There is a `__resume__` callback that can be used as a hook point to perform extra steps after an actor has been deserialized into memory.\n"
  },
  {
    "path": "ecolift/CLAUDE.md",
    "content": "# Acton Ecosystem Lift Process\n\nThis document describes the process for lifting the entire Acton ecosystem when introducing new language features or breaking changes.\n\n## Ecosystem Repositories\n\nbuiltin & stdlib are in this repo in the base/ directory.\n\nThe following repositories contain syntax highlighting and similar for editors / IDE and should be updated when the language has been changed:\n\n- [ ] git@github.com:actonlang/Acton.tmbundle.git\n- [ ] git@github.com:actonlang/acton-mode.git\n- [ ] git@github.com:actonlang/sublime-acton.git\n- [ ] git@github.com:actonlang/vim-acton.git\n- [ ] git@github.com:actonlang/vscode-acton.git\n\nThe following are Acton projects:\n\n- [ ] git@github.com:actonlang/acton-grpc.git\n- [ ] git@github.com:actonlang/acton-http2.git\n- [ ] git@github.com:actonlang/acton-snappy.git\n- [ ] git@github.com:actonlang/acton-zlib.git\n- [ ] git@github.com:orchestron-orchestrator/actmf.git\n- [ ] git@github.com:orchestron-orchestrator/acton-yang.git\n- [ ] git@github.com:orchestron-orchestrator/netcli.git\n- [ ] git@github.com:orchestron-orchestrator/netclics.git\n- [ ] git@github.com:orchestron-orchestrator/netconf.git\n- [ ] git@github.com:orchestron-orchestrator/orchestron.git\n- [ ] git@github.com:orchestron-orchestrator/sorespo.git\n- [ ] git@github.com:telemetrify-collector/telemetrify.git\n\n## General Process\n\nWe group together the remote git operations, so start by cloning all repositories, perform steps for each repository, then push all repositories at the end.\n\nThe ecosystem lift process consists of the following steps for each repository:\n\n1. **Clone the repository** (into the `repos/` directory) - done in batch\n   ```bash\n   cd ecolift/repos\n   git clone <repo-url>\n   cd <repo-name>\n   ```\n\n2. **Create a new branch**\n   ```bash\n   git checkout -b ecolift/<feature-name>\n   ```\n\n3. **Apply the language changes**\n   - Find .act files\n   - Update the code for the particular feature\n\n4. **Test the changes**\n   ```bash\n   acton build\n   acton test\n   ```\n\n5. **Commit**\n   ```bash\n   git add -u\n   git commit -m \"Adapt to <feature-name> in Acton\"\n   ```\n\n   the user can at this point review locally\n\n6. **Push and create a pull request**\n   ```bash\n   git push -u origin ecolift/<feature-name>\n   gh pr create --title \"Adapt to <feature-name> in Acton\" --body \"This PR updates the codebase to be compatible with <feature-name> in Acton\"\n   ```\n\n## Identifying Changes to Ecolift\n\nWhen performing an ecolift, the user requesting the ecolift should provide sufficient details about what changes need to be made. If the details are unclear, **prompt the user for more information** before proceeding.\n\n### Required Information from User\n\nThe user should provide one or more of the following:\n\n1. **Specific commit IDs** from the main acton repository that introduced the changes:\n   ```\n   Please provide the commit ID(s) that introduced this feature: abc123def\n   ```\n\n2. **Examples of the transformation** showing old vs new syntax:\n   ```\n   Old syntax: \"Hello \" + name + \"!\"\n   New syntax: f\"Hello {name}!\"\n   ```\n\n3. **Feature description** with concrete examples of what needs to change:\n   ```\n   Added comprehensions: transform loops like `for x in items: result.append(x*2)` \n   to `[x*2 for x in items]`\n   ```\n\n### If Information is Unclear\n\nIf the user's request lacks sufficient detail, ask clarifying questions:\n\n- \"Can you provide the commit ID(s) from the main acton repo that introduced this feature?\"\n- \"Can you show an example of the old syntax vs new syntax transformation?\"\n- \"What specific language constructs or patterns need to be updated?\"\n- \"Are there test cases in the main repo that demonstrate this change?\"\n\n### Using Provided Information\n\nOnce you have the necessary details:\n\n1. **Examine the referenced commits** to understand the full scope of changes\n2. **Study compiler test cases** that show transformation patterns\n3. **Look for examples** in the main repo's test files (`test/compiler/`, `test/stdlib_tests/`)\n4. **Extract transformation patterns** from the diffs and apply them systematically\n\n## Generated Files to Skip During Refactoring\n\nWhen refactoring projects during ecolift, skip these generated files:\n\n### General Rules\n- Skip any files that are generated by code generators (typically run via `make gen`)\n- Skip snapshot test files unless the expected output format itself changed\n- Focus refactoring efforts on handwritten source files\n\n### acton-yang Project\n- `src/yang/schema.act`\n- `test/test_data_classes/src/yang_basics.act`\n- `test/test_data_classes/src/yang_foo.act`\n- `test/test_data_classes/src/yang_foo_loose.act`\n- `test/test_data_classes/src/yang_one.act`\n- `test/test_data_source_roundtrip/src/xml_full_adata.act`\n- `test/test_data_source_roundtrip/src/xml_full_gdata.act`\n- All files in `golden/` directories\n\n## Feature-Specific Transformations\n\nA new Acton language feature wll almost certainly include tests in the\nactonlang/acton repository (the parent directory). When prompted to use a new\nfeature, try to find test cases for the new feature to get a better idea of how\nit works.\n\n### Example: F-strings\n\nWhen introducing f-strings to Acton, the transformation would involve:\n\n1. Identifying string formatting patterns like:\n   ```acton\n   \"Hello \" + name + \", you have \" + str(count) + \" messages\"\n   ```\n   or\n   ```acton\n   \"Hello %s\" % name\n   ```\n\n2. Converting to f-string syntax:\n   ```acton\n   f\"Hello {name}, you have {count} messages\"\n   ```\n\n   ```acton\n   f\"Hello {name}\"\n   ```\n\n### Example: Comprehensions\n\nWhen adding comprehensions, look for patterns like:\n```acton\nresult = []\nfor x in items:\n    if x > 0:\n        result.append(x * 2)\n```\n\nAnd convert to:\n```acton\nresult = [x * 2 for x in items if x > 0]\n```\n"
  },
  {
    "path": "ecolift/repos/.gitignore",
    "content": "# Ignore all cloned repositories\n*\n# But keep this file\n!.gitignore"
  },
  {
    "path": "ecolift/string_interpolation.md",
    "content": "# New interpolated strings\n\nAfter the string parser rewrite, Acton now supports interpolation in normal\nstrings plus many previous issues with f-strings have been fixed. The idiomatic\nActon style is now to use regular strings with interpolation.\n\n\n## basic concatenation\nreplace\n```acton\n\"Hello \" + name + \", you have \" + str(count) + \" messages\"\n```\nwith\n```acton\n\"Hello {name}, you have {count} messages\"\n```\n\n## % operator style\nreplace:\n```acton\n\"Hello %s\" % name\n```\n\nwith:\n```acton\n\"Hello {name}\"\n```\n\n## f-strings\n\nRemove the f prefix since it is optional and the idiomatic Acton style is to NOT use f-prefix.\n\nreplace:\n```acton\nf\"Hello {name}\"\n```\n\nwith:\n```acton\n\"Hello {name}\"\n```\n\n## Slice expressions\n\nThere were previously issues with slice expressions inside f-strings. Those have\nbeen addressed with the new parser, so we should stick to string interplation,\nnot concatenation.\n\nreplace:\n```acton\n\"Hello \" + name[:3]\n```\n\nwith:\n```acton\n\"Hello {name[:3]}\"\n```\n\n\n## Escaped quotes\n\nThere were previously issues with escaping quotes inside f-strings. Those issues\nhave been addressed with the new parser, so we can use different quote chars:\n\nreplace:\n```acton\nf\"\"\"Hello \\\"world\\\"!\"\"\"\n```\n\nwith:\n```acton\n\"\"\"Hello \"world\"!\"\"\"\n```\n\n## Escape curly braces\n\nSince normal strings now offer interpolation, curly braces have changed\nsemantically from literal braces to mean an expression that should be\ninterpolated. Thus, for existing code, we need to convert the string to a raw\nstring or escape the brace.\n\nreplace:\n```acton\n'Some JSON {\"a\": 1}'\n```\n\nwith:\n```acton\nr'Some JSON {\"a\": 1}'\n```\n\nif interpolation or string concatenation is used, then escape\n\nreplace:\n```acton\n'Name' + name + 'Some JSON {\"a\": 1}'\n```\n\nwith:\n```acton\n\"\"\"Name {name} Some JSON {{\"a\": 1}}\"\"\"\n```\n"
  },
  {
    "path": "examples/.acton",
    "content": ""
  },
  {
    "path": "examples/StringsAndBytes.act",
    "content": "actor main(env):\n\n   s = \"\\x48ello, world\"\n   print(s)\n\n   env.exit(0)\n\n"
  },
  {
    "path": "examples/abs.act",
    "content": "actor main(env):\n    x = -3\n    print(abs(x))\n    env.exit(0)\n"
  },
  {
    "path": "examples/average.act",
    "content": "def average(coll):\n    sum = 0\n    for s in coll:\n       sum += s\n    return sum.__float__()/float(len(coll))\n\nactor main(env):\n    s = [3.2, 4.5, 3.2, 0.5]\n    print(average(s))\n    t = [4, 6, 9, 14]\n    print(average(t))\n    u = [3, 4.4]                        # u has type list[float]\n    for i in map(int,u): print(i)\n    for x in map(float,u): print(x)\n    n : int\n    n = 3\n    v = [n, 4.4]                        # v has type list[atom]\n    for i in map(int,v): print(i)\n    for x in map(float,v): print(x)\n#   print(average(v))\n    env.exit(0)\n"
  },
  {
    "path": "examples/bsplit.act",
    "content": "import math\n\ndef bsplit(a,b):\n    if b-a == 1:\n        return (1,b)\n    else:\n        m = a + (b-a)//2\n        p1,q = bsplit(a,m)\n        p,q2 = bsplit(m,b)\n        p1 *= q2\n        p += p1\n        q *= q2\n        return (p,q)\n\ndef e(prec):\n     fp = float(prec)\n     n = int(3 * fp / math.log(fp) + 20)\n     p,q = bsplit(0,n)\n     p += q\n     p *= 10**prec\n     return p//q\n\n\nactor main(env):\n     print(e(10000))\n     env.exit(0)\n\n"
  },
  {
    "path": "examples/client.act",
    "content": "import net\n\nactor main(env):\n\n    def on_connect(c):\n        print(\"Client established connection to\", c.remote_address(), \"from\", c.local_address(), \"using IP version\", c.ip_version())\n        def conn_write(s):\n            c.write(s.encode())\n\n        env.stdin_install(conn_write)\n\n    def on_receive(c, data):\n        env.stdout_write(data.decode())\n\n    def on_error(c, msg):\n        print(\"Client ERR\", msg)\n        # Should do periodic back-off\n        c.reconnect()\n\n    if len(env.argv) != 3:\n        print(\"usage: client [HOST] [PORT]\")\n        env.exit(-1)\n\n    connect_cap = net.TCPConnectCap(net.TCPCap(net.NetCap(env.cap)))\n    client = net.TCPConnection(connect_cap, env.argv[1], int(env.argv[2]), on_connect, on_receive, on_error)\n"
  },
  {
    "path": "examples/count.act",
    "content": "# This is a simple illustration for demoing how the Acton RTS can persist its\n# run time state in the Acton distributed database backend. First start the\n# database:\n#\n#   ./server -p 32000 -m 34000 -s 127.0.0.1:34000\n#   ./server -p 32001 -m 34001 -s 127.0.0.1:34000\n#   ./server -p 32002 -m 34002 -s 127.0.0.1:34000\n#\n# Then compile and run this program. Abort its current invocation with ^C, then\n# restart the program and note how it will resume its state from the database\n# before counting further.\n#\n#   kll@Boxy:~/acton/examples$ ../acton --root main count.act\n#   kll@Boxy:~/acton/examples$ ./count --rts-ddb-host localhost --rts-verbose\n#   Acton RTS: using distributed database backend (DDB): localhost:32000\n#   Acton RTS: checking for previous actor state in DDB... done\n#   0\n#   1\n#   2\n#   3\n#   4\n#   ^C\n#   kll@Boxy:~/acton/examples$ ./count --rts-ddb-host localhost --rts-verbose\n#   Acton RTS: using distributed database backend (DDB): localhost:32000\n#   Acton RTS: checking for previous actor state in DDB... done\n#   Acton RTS: restoring actor state from DDB... done\n#   5\n#   6\n#   7\n#   8\n#   ^C\n#   kll@Boxy:~/acton/examples$ ./count --rts-ddb-host localhost --rts-verbose\n#\nactor main(env):\n    var i = 0;\n    var count_to = 0\n\n    if len(env.argv) > 2:\n        print(\"Usage: count COUNT\")\n        await async env.exit(1)\n\n    if len(env.argv) > 1:\n        count_to = int(env.argv[1])\n\n    def _work():\n        print(i)\n        if count_to > 0 and i == count_to:\n            env.exit(0)\n        i += 1\n        after 1: _work()\n\n    _work()\n"
  },
  {
    "path": "examples/counter.act",
    "content": "actor counter(initval):\n    var val = initval\n\n    def next():\n        val += 1\n        return val\n\nactor main(env):\n    ctr = counter(0)\n    n = ctr.next()\n    print(n)\n    env.exit(0)\n"
  },
  {
    "path": "examples/eq_list_dict.act",
    "content": "actor main(env):\n   a = [1,2,3]\n   if a == [1,2,3]:\n      print(\"Equal, correct\")\n   else:\n      print(\"Not equal, wrong\")\n\n   if a == [1,2]:\n      print(\"Equal, wrong\")\n   else:\n      print(\"Not equal, correct\")\n      \n   if a == [1,5,2]:\n      print(\"Equal, wrong\")\n   else:\n      print(\"Not equal, correct\")\n\n   if [3.5,7.2] == [3.5, 7.2]:\n      print(\"Equal, correct\")\n   else:\n      print(\"Not equal, wrong\")\n\n   if [a,a] == [[1,2,3],[1,2,3]]:\n         print(\"Equal, correct\")\n   else:\n      print(\"Not equal, wrong\")\n      \n   if [a,a] == [[1,2,3],[1,3]]:\n      print(\"Equal, wrong\")\n   else:\n      print(\"Not equal, correct\")\n\n   if [\"hello\", \"world\"]==[\"Hello\",\"word\"]:\n      print(\"Equal, wrong\")\n   else:\n      print(\"Not equal, correct\")\n\n   d1, d2 : dict[str,str]\n   d1 = {}\n   d1[\"Sweden\"] = \"Stockholm\"\n   d1[\"Norway\"] =\"Oslo\"\n   d1[\"Denmark\"] = \"Copenhagen\"\n   \n   d2 = {}\n   d2[\"Norway\"] =\"Oslo\"\n   d2[\"Denmark\"] = \"Copenhagen\"\n   d2[\"Sweden\"] = \"Stockholm\"\n\n   if d1==d2:\n      print(\"Equal, correct\")\n   else:\n      print(\"Not equal, wrong\")\n\n   d2[\"Finland\"] = \"Helsinki\"\n\n   if d1==d2:\n      print(\"Equal, wrong\")\n   else:\n      print(\"Not equal, correct\")\n\n   d3, d4 : dict[bool,dict[str,str]]\n   d3 = {}\n   d3[True] = d1\n   d3[False] = d2\n\n   d4 = {}\n   d4[False] = d2\n   d4[True] = d1\n\n   if d3==d4:\n      print(\"Equal, correct\")\n   else:\n      print(\"Not equal, wrong\")\n\n   d2[\"Estonia\"] = \"Tallinn\"\n\n   if d3==d4:\n      print(\"Equal, correct\")\n   else:\n      print(\"Not equal, wrong\")\n\n   print(\"now to Ord\")\n\n   if ([3,4,5] < [3,4,5,8]):\n      print(\"lt, correct\")\n   else:\n      print(\"Not lt, wrong\")\n\n   if ([3,4,5] < [3,4,6,8]):\n      print(\"lt, correct\")\n   else:\n      print(\"Not lt, wrong\")\n\n   if ([3,4,5,6,7] < [3,4,6,1,2,3,4]):\n      print(\"lt, correct\")\n   else:\n      print(\"Not lt, wrong\")\n\n   if ([3,4,5,6,7] <= [3,4,6,1,2,3,4]):\n      print(\"le, correct\")\n   else:\n      print(\"Not le, wrong\")\n\n   if ([3,4,6,1,2,3,4] > [3,4,5,6,7]):\n      print(\"gt, correct\")\n   else:\n      print(\"Not gt, wrong\")\n\n   if d1 < d2:\n      print(\"lt, correct\")\n   else:\n      print(\"Not lt, wrong\")\n\n   if d3 <= d4:\n      print(\"le, correct\")\n   else:\n      print(\"Not le, wrong\")\n      \n\n   env.exit(0)\n    \n   "
  },
  {
    "path": "examples/files.act",
    "content": "import file\n\nactor main(env):\n    # Get a reference to capability to read a file, by refining from WorldCap\n    f_cap = file.ReadFileCap(file.FileCap(env.cap))\n    f = file.ReadFile(f_cap, env.argv[1])\n    data = f.read()\n    print(data.decode())\n\n    env.exit(0)\n"
  },
  {
    "path": "examples/helloworld.act",
    "content": "actor main(env):\n    print(\"Hello, world!\")\n    env.exit(0)\n"
  },
  {
    "path": "examples/http_server.act",
    "content": "import net\nimport http\nimport logging\n\n# PolarSSL/mbedTLS self-signed test certificate\nCERT_PEM = \"\"\"-----BEGIN CERTIFICATE-----\nMIIDNzCCAh+gAwIBAgIBAjANBgkqhkiG9w0BAQsFADA7MQswCQYDVQQGEwJOTDER\nMA8GA1UECgwIUG9sYXJTU0wxGTAXBgNVBAMMEFBvbGFyU1NMIFRlc3QgQ0EwHhcN\nMTkwMjEwMTQ0NDA2WhcNMjkwMjEwMTQ0NDA2WjA0MQswCQYDVQQGEwJOTDERMA8G\nA1UECgwIUG9sYXJTU0wxEjAQBgNVBAMMCWxvY2FsaG9zdDCCASIwDQYJKoZIhvcN\nAQEBBQADggEPADCCAQoCggEBAMFNo93nzR3RBNdJcriZrA545Do8Ss86ExbQWuTN\nowCIp+4ea5anUrSQ7y1yej4kmvy2NKwk9XfgJmSMnLAofaHa6ozmyRyWvP7BBFKz\nNtSj+uGxdtiQwWG0ZlI2oiZTqqt0Xgd9GYLbKtgfoNkNHC1JZvdbJXNG6AuKT2kM\ntQCQ4dqCEGZ9rlQri2V5kaHiYcPNQEkI7mgM8YuG0ka/0LiqEQMef1aoGh5EGA8P\nhYvai0Re4hjGYi/HZo36Xdh98yeJKQHFkA4/J/EwyEoO79bex8cna8cFPXrEAjya\nHT4P6DSYW8tzS1KW2BGiLICIaTla0w+w3lkvEcf36hIBMJcCAwEAAaNNMEswCQYD\nVR0TBAIwADAdBgNVHQ4EFgQUpQXoZLjc32APUBJNYKhkr02LQ5MwHwYDVR0jBBgw\nFoAUtFrkpbPe0lL2udWmlQ/rPrzH/f8wDQYJKoZIhvcNAQELBQADggEBAC465FJh\nPqel7zJngHIHJrqj/wVAxGAFOTF396XKATGAp+HRCqJ81Ry60CNK1jDzk8dv6M6U\nHoS7RIFiM/9rXQCbJfiPD5xMTejZp5n5UYHAmxsxDaazfA5FuBhkfokKK6jD4Eq9\n1C94xGKb6X4/VkaPF7cqoBBw/bHxawXc0UEPjqayiBpCYU/rJoVZgLqFVP7Px3sv\na1nOrNx8rPPI1hJ+ZOg8maiPTxHZnBVLakSSLQy/sWeWyazO1RnrbxjrbgQtYKz0\ne3nwGpu1w13vfckFmUSBhHXH7AAS/HpKC4IH7G2GAk3+n8iSSN71sZzpxonQwVbo\npMZqLmbBm/7WPLc=\n-----END CERTIFICATE-----\n\"\"\"\n\nKEY_PEM = \"\"\"-----BEGIN RSA PRIVATE KEY-----\nMIIEpAIBAAKCAQEAwU2j3efNHdEE10lyuJmsDnjkOjxKzzoTFtBa5M2jAIin7h5r\nlqdStJDvLXJ6PiSa/LY0rCT1d+AmZIycsCh9odrqjObJHJa8/sEEUrM21KP64bF2\n2JDBYbRmUjaiJlOqq3ReB30Zgtsq2B+g2Q0cLUlm91slc0boC4pPaQy1AJDh2oIQ\nZn2uVCuLZXmRoeJhw81ASQjuaAzxi4bSRr/QuKoRAx5/VqgaHkQYDw+Fi9qLRF7i\nGMZiL8dmjfpd2H3zJ4kpAcWQDj8n8TDISg7v1t7HxydrxwU9esQCPJodPg/oNJhb\ny3NLUpbYEaIsgIhpOVrTD7DeWS8Rx/fqEgEwlwIDAQABAoIBAQCXR0S8EIHFGORZ\n++AtOg6eENxD+xVs0f1IeGz57Tjo3QnXX7VBZNdj+p1ECvhCE/G7XnkgU5hLZX+G\nZ0jkz/tqJOI0vRSdLBbipHnWouyBQ4e/A1yIJdlBtqXxJ1KE/ituHRbNc4j4kL8Z\n/r6pvwnTI0PSx2Eqs048YdS92LT6qAv4flbNDxMn2uY7s4ycS4Q8w1JXnCeaAnYm\nWYI5wxO+bvRELR2Mcz5DmVnL8jRyml6l6582bSv5oufReFIbyPZbQWlXgYnpu6He\nGTc7E1zKYQGG/9+DQUl/1vQuCPqQwny0tQoX2w5tdYpdMdVm+zkLtbajzdTviJJa\nTWzL6lt5AoGBAN86+SVeJDcmQJcv4Eq6UhtRr4QGMiQMz0Sod6ettYxYzMgxtw28\nCIrgpozCc+UaZJLo7UxvC6an85r1b2nKPCLQFaggJ0H4Q0J/sZOhBIXaoBzWxveK\nnupceKdVxGsFi8CDy86DBfiyFivfBj+47BbaQzPBj7C4rK7UlLjab2rDAoGBAN2u\nAM2gchoFiu4v1HFL8D7lweEpi6ZnMJjnEu/dEgGQJFjwdpLnPbsj4c75odQ4Gz8g\nsw9lao9VVzbusoRE/JGI4aTdO0pATXyG7eG1Qu+5Yc1YGXcCrliA2xM9xx+d7f+s\nmPzN+WIEg5GJDYZDjAzHG5BNvi/FfM1C9dOtjv2dAoGAF0t5KmwbjWHBhcVqO4Ic\nBVvN3BIlc1ue2YRXEDlxY5b0r8N4XceMgKmW18OHApZxfl8uPDauWZLXOgl4uepv\nwhZC3EuWrSyyICNhLY21Ah7hbIEBPF3L3ZsOwC+UErL+dXWLdB56Jgy3gZaBeW7b\nvDrEnocJbqCm7IukhXHOBK8CgYEAwqdHB0hqyNSzIOGY7v9abzB6pUdA3BZiQvEs\n3LjHVd4HPJ2x0N8CgrBIWOE0q8+0hSMmeE96WW/7jD3fPWwCR5zlXknxBQsfv0gP\n3BC5PR0Qdypz+d+9zfMf625kyit4T/hzwhDveZUzHnk1Cf+IG7Q+TOEnLnWAWBED\nISOWmrUCgYAFEmRxgwAc/u+D6t0syCwAYh6POtscq9Y0i9GyWk89NzgC4NdwwbBH\n4AgahOxIxXx2gxJnq3yfkJfIjwf0s2DyP0kY2y6Ua1OeomPeY9mrIS4tCuDQ6LrE\nTB6l9VGoxJL4fyHnZb8L5gGvnB1bbD8cL6YPaDiOhcRseC9vBiEuVg==\n-----END RSA PRIVATE KEY-----\n\"\"\"\n\n\nactor main(env):\n    logh = logging.Handler()\n    logh.add_sink(logging.ConsoleSink())\n    logh.set_output_level(logging.TRACE)\n    listen_cap = net.TCPListenCap(net.TCPCap(net.NetCap(env.cap)))\n\n    def on_accept(server):\n        server.cb_install(on_request, on_error)\n\n    def on_request(server, request, respond):\n        respond(200, {\"Content-Type\": \"text/plain\"}, \"Hello from the Acton HTTPS server\")\n\n    def on_error(server, error):\n        print(\"HTTPS server error:\", error)\n\n    http.TLSListener(\n        listen_cap,\n        \"127.0.0.1\",\n        8443,\n        CERT_PEM.encode(),\n        KEY_PEM.encode(),\n        on_accept,\n        log_handler=logh\n    )\n    print(\"HTTPS server listening on https://127.0.0.1:8443\")\n\n"
  },
  {
    "path": "examples/inter.act",
    "content": "# An interacive terminal program that increments and decrements a counter based\n# on user input. The program will exit when the user types 'q'. There is also a\n# periodic incrementation of the counter every 5 seconds.\n#\n# The actor based asynchronous I/O model of Acton makes it very natural to\n# express event-driven reactive programs like this that can react to user input\n# while not blocking on I/O, thus allowing for other tasks to be performed, in\n# this case the periodic incrementation of the counter.\n\nactor main(env: Env):\n    var count = 0\n\n    def interact(input):\n        if input == \"q\":\n            print(\"Quitting!\")\n            env.exit(0)\n        elif input == \"i\":\n            count += 1\n            print(\"Incrementing! Count is now:\", count)\n        elif input == \"d\":\n            count -= 1\n            print(\"Decrementing! Count is now:\", count)\n        else:\n            print(\"Unknown command:\", input)\n\n    # Set non-canonical mode, so we get each key stroke directly\n    env.set_stdin(canonical=False)\n    # Turn off terminal echo\n    env.set_stdin(echo=False)\n    env.stdin_install(interact)\n    print(\"Type 'q' to quit, 'i' to increment a counter and 'd' to decrement it.\")\n\n    def periodic():\n        count += 1\n        print(\"Periodic +1 increment. Count is now:\", count)\n        after 5: periodic()\n    after 1: periodic()\n"
  },
  {
    "path": "examples/print_time.act",
    "content": "import time\n\nactor main(env):\n    def f():\n        print(time.time())\n    f()\n    env.exit(0)\n"
  },
  {
    "path": "examples/reprtest.act",
    "content": "actor main(env):\n  print([\"abc\",\"def\"])\n  print([[\"abc\",\"def\"],[\"ghi\"]])\n  print(repr(\"kalle\"))\n  s = {\"abc\"}\n  s.add(\"def\")\n  print(s)\n  d = {}\n  for i in range(10):\n      d[i] = str(i)\n  print(d)\n  env.exit(0)\n  \n  "
  },
  {
    "path": "examples/server.act",
    "content": "import net\n\n\nactor Server(conn):\n    def on_receive(c, data):\n        print(\"Server Received some data:\", data, \" from:\", c)\n        if data == b\"PING\":\n            c.write(b\"PONG\")\n\n    def on_error(c, error):\n        print(\"There was an error:\", error, \" from:\", c)\n\nactor Listener(listen_cap, port):\n\n    def on_error(l, error):\n        print(\"There was an error with the TCPListener socket:\", error)\n\n    def on_accept(c):\n        s = Server(c)\n        c.cb_install(s.on_receive, s.on_error)\n\n    var server = net.TCPListener(listen_cap, \"0.0.0.0\", port, on_error, on_accept)\n\nactor main(env):\n    port = 12345\n\n    # Set up capability for listening with TCP\n    listen_cap = net.TCPListenCap(net.TCPCap(net.NetCap(env.cap)))\n\n    l = Listener(listen_cap, port)\n"
  },
  {
    "path": "examples/sieve.act",
    "content": "import math\n\ndef sieve(n):\n    isPrime = [True] * n\n    isPrime[0] = False; isPrime[1] = False\n    for i in range(2, int(math.sqrt(float(n)))+1):\n        if isPrime[i]:\n            for k in range(i*i,n,i): isPrime[k] = False\n\n    return isPrime\n\ncount : (list[bool]) -> int\ndef count(bs):\n    res = 0\n    for b in bs:\n        if b: res += 1\n    return res\n\n\ndef primesTo(n):\n    res = []\n    isPrime = sieve(n)\n    for i in range(2, n):\n        if isPrime[i]: res.append(i)\n    return res\n\n\nactor main(env):\n    if (len(env.argv) >= 2) and env.argv[1].isdecimal():\n        print(count(sieve(int(env.argv[1]))))\n    else:\n        print(\"Usage: sieve <positive integer>\")\n    env.exit(0)\n"
  },
  {
    "path": "examples/sumto.act",
    "content": "def sumto(n):\n    res = 0\n    for i in range(n):\n        res += i\n    return res\n    \nactor main(env):\n    if len(env.argv) >= 2:\n        target = int(env.argv[1])\n    else:\n        target = int(123)\n    print(sumto(int(target)))\n    env.exit(0)\n"
  },
  {
    "path": "examples/worker.act",
    "content": "actor worker(report):\n    report()\n   \nactor main(env):\n    def report():\n        print('Done!')\n        env.exit(0)\n\n    worker(report)\n    env.exit(0)\n"
  },
  {
    "path": "homebrew/Formula/acton.rb",
    "content": "class Acton < Formula\n  desc \"Delightful distributed programming language\"\n  homepage \"https://www.acton-lang.org\"\n  url \"https://github.com/actonlang/acton/archive/refs/tags/v0.0.0.tar.gz\"\n  sha256 \"0000000000000000000000000000000000000000000000000000000000000000\"\n  license \"BSD-3-Clause\"\n  head \"https://github.com/actonlang/acton.git\", branch: \"main\"\n\n  depends_on \"ghc@9.6\" => :build\n  depends_on \"haskell-stack\" => :build\n\n  def install\n    # Fix up stack config to not install project local GHC and use system GHC\n    # which is idiomatic for Homebrew. Disable GHC version check as we want to\n    # allow for minor version mismatches.\n    inreplace \"compiler/stack.yaml\", \"# system-ghc: true\", <<~EOS\n      system-ghc: true\n      install-ghc: false\n      allow-newer: true\n      skip-ghc-check: true\n    EOS\n\n    ENV[\"BUILD_RELEASE\"] = \"1\"\n    system \"make\"\n    bin.install \"dist/bin/acton\"\n    bin.install_symlink \"acton\" => \"actonc\"\n    bin.install \"dist/bin/actondb\"\n    bin.install \"dist/bin/runacton\"\n    prefix.install Dir[\"dist/*\"]\n    bash_completion.install \"completion/acton.bash-completion\"\n  end\n\n  test do\n    testapp = (testpath/\"hello.act\")\n    testapp.write <<~EOS\n      #!/usr/bin/env runacton\n      actor main(env):\n          print(\"Hello World!\")\n          env.exit(0)\n    EOS\n    testapp.chmod 0755\n    assert_equal \"Hello World!\\n\", shell_output(testapp)\n  end\nend\n"
  },
  {
    "path": "test/.acton",
    "content": "test\n"
  },
  {
    "path": "test/Makefile",
    "content": "MK_PATH:=$(abspath $(CURDIR)/..)\nACTON=\"../dist/bin/acton\" --quiet\nDDB_SERVER=../dist/bin/actondb\nTESTS= \\\n\t$(DDB_TESTS)\ntest:\n\t$(MAKE) $(TESTS)\n\n\nddb-tests:\n\t$(MAKE) $(DDB_TESTS)\n\nDDB_TESTS=test_db_app test_db_resume_tcp_server test_db_resume_tcp_client\n.PHONY: $(DDB_TESTS)\n\n.PHONY: tls-test-server\ntls-test-server:\n\t../dist/zig/zig cc -pthread -I../dist/deps/mbedtls/include -I../dist/deps/mbedtls/tests/include -I../dist/deps/mbedtls/library -Istdlib -DMBEDTLS_USER_CONFIG_FILE=\\\"tls_test_mbedtls_config.h\\\" -o stdlib/tls_test_server stdlib/tls_test_server.c ../dist/deps/mbedtls/tests/src/certs.c ../dist/deps/mbedtls/library/*.c\n\n# Starts up a database cluster, checks membership is ok before proceeding to run\n# a simple app. We do not really verify that the RTS uses the database - we\n# assume it does and would fail catastrohpically if it encounters an error.\ntest_db_app:\n\t$(ACTON) --db rts_db/ddb_test_app.act\n\t$(ACTON) --db rts_db/test_db_app.act\n\trts_db/test_db_app\n\ntest_db_resume_tcp_server:\n\t$(ACTON) --db rts_db/ddb_test_server.act\n\t$(ACTON) --db rts_db/test_tcp_server.act\n\trts_db/test_tcp_server\n\ntest_db_resume_tcp_client:\n\t$(ACTON) --db rts_db/ddb_test_server.act\n\t$(ACTON) --db rts_db/ddb_test_client.act\n\t$(ACTON) --db rts_db/test_tcp_client.act\n\trts_db/test_tcp_client\n\n\n# Expect 9 threads given 7 workers + main process + IO\nrts/wthreads1:\n\t$(ACTON) --root main $@.act\n\t./$@ --rts-wthreads 7 & PID=$$! && ps -o thcount $${PID} | tail -n1 | awk '{ print $$1 }' | grep \"^9$$\"\n"
  },
  {
    "path": "test/count.act",
    "content": "actor main(env):\n    var i = 0;\n    var count_to = int(env.argv[1])\n\n    def _work():\n        print(i)\n        if count_to and i == count_to:\n            await async env.exit(0)\n        i += 1\n        after 1: _work()\n\n    _work()\n"
  },
  {
    "path": "utils/actonmon",
    "content": "#!/usr/bin/env python3\n\n\nimport argparse\nfrom functools import partial\nfrom http.server import HTTPServer, BaseHTTPRequestHandler\nimport json\nimport socket\nimport time\n\n\n\nclass MonSock:\n    def __init__(self, address):\n        self.address = address\n        self.sock = None\n        self.buf = b\"\"\n\n    def connect(self):\n        self.sock = socket.socket(socket.AF_UNIX, socket.SOCK_STREAM)\n        try:\n            self.sock.connect(self.address)\n        except:\n            pass\n\n    def cmd(self, cmd, retries=5):\n        if self.sock is None:\n            self.connect()\n\n        # Simple netstrings implementation, which also assumes that there is\n        # only one response to our query\n        try:\n            self.sock.send(f\"{len(cmd)}:{cmd},\".encode('utf-8'))\n            while True:\n                try:\n                    colpos = self.buf.index(b':')\n                except ValueError as exc:\n                    # Not enough data, read some and try again\n                    recv = self.sock.recv(1024)\n                    if len(recv) == 0:\n                        raise ConnectionError(\"RTS hung up\")\n                    self.buf += recv\n                    continue\n                length = int(self.buf[0:colpos])\n                start = colpos + 1\n                end = start + length\n                if len(self.buf) < end:\n                    # Not enough data, read some and try again\n                    recv = self.sock.recv(1024)\n                    if len(recv) == 0:\n                        raise ConnectionError(\"RTS hung up\")\n                    self.buf += recv\n                    continue\n                res = self.buf[start:end]\n                self.buf = self.buf[end+1:] # +1 to skip the ,\n                return json.loads(res.decode(\"utf-8\"))\n        except Exception as exc:\n            self.connect()\n            if retries > 0:\n                return self.cmd(cmd, retries-1)\n            else:\n                raise ConnectionError(\"Unable to get data from acton rts\")\n\n\nclass PromHTTPRequestHandler(BaseHTTPRequestHandler):\n    def __init__(self, sock_addr, *args, **kwargs):\n        self.ms = MonSock(sock_addr)\n        # BaseHTTPRequestHandler calls do_GET **inside** __init__ !!!\n        # So we have to call super().__init__ after setting attributes.\n        super().__init__(*args, **kwargs)\n\n    def do_GET(self):\n        try:\n            data = self.ms.cmd(\"WTS\")\n        except ConnectionError:\n            self.send_response(503)\n            return\n\n        self.send_response(200)\n        self.end_headers()\n\n        total = {k: 0 for k in data['wt']['0']}\n\n        self.wfile.write(b'# HELP acton_rts_sleeps Number of times a thread went to sleep\\n')\n        self.wfile.write(b'# TYPE acton_rts_sleeps counter\\n')\n        for k,v in sorted(data['wt'].items(), key=lambda item: int(item[0])):\n            self.wfile.write(f'acton_rts_sleeps{{thread=\"{k}\"}} {v[\"sleeps\"]}\\n'.encode('utf-8'))\n\n        self.wfile.write(b'# HELP acton_rts_conts Execution time of continuations\\n')\n        self.wfile.write(b'# TYPE acton_rts_conts histogram\\n')\n        for k,v in sorted(data['wt'].items(), key=lambda item: int(item[0])):\n            total['conts_count'] += v['conts_count']\n            total['conts_sum'] += v['conts_sum']\n            total['conts_100ns'] += v['conts_100ns']\n            total['conts_1us'] += v['conts_1us']\n            total['conts_10us'] += v['conts_10us']\n            total['conts_100us'] += v['conts_100us']\n            total['conts_1ms'] += v['conts_1ms']\n            total['conts_10ms'] += v['conts_10ms']\n            total['conts_100ms'] += v['conts_100ms']\n            total['conts_1s'] += v['conts_1s']\n            total['conts_10s'] += v['conts_10s']\n            total['conts_100s'] += v['conts_100s']\n            total['conts_inf'] += v['conts_inf']\n\n            self.wfile.write(f'acton_rts_conts_bucket{{thread=\"{k}\",le=\"0.0000001\"}} {v[\"conts_100ns\"]}\\n'.encode('utf-8'))\n            self.wfile.write(f'acton_rts_conts_bucket{{thread=\"{k}\",le=\"0.000001\"}} {v[\"conts_1us\"]}\\n'.encode('utf-8'))\n            self.wfile.write(f'acton_rts_conts_bucket{{thread=\"{k}\",le=\"0.00001\"}} {v[\"conts_10us\"]}\\n'.encode('utf-8'))\n            self.wfile.write(f'acton_rts_conts_bucket{{thread=\"{k}\",le=\"0.0001\"}} {v[\"conts_100us\"]}\\n'.encode('utf-8'))\n            self.wfile.write(f'acton_rts_conts_bucket{{thread=\"{k}\",le=\"0.001\"}} {v[\"conts_1ms\"]}\\n'.encode('utf-8'))\n            self.wfile.write(f'acton_rts_conts_bucket{{thread=\"{k}\",le=\"0.01\"}} {v[\"conts_10ms\"]}\\n'.encode('utf-8'))\n            self.wfile.write(f'acton_rts_conts_bucket{{thread=\"{k}\",le=\"0.1\"}} {v[\"conts_100ms\"]}\\n'.encode('utf-8'))\n            self.wfile.write(f'acton_rts_conts_bucket{{thread=\"{k}\",le=\"1\"}} {v[\"conts_1s\"]}\\n'.encode('utf-8'))\n            self.wfile.write(f'acton_rts_conts_bucket{{thread=\"{k}\",le=\"10\"}} {v[\"conts_10s\"]}\\n'.encode('utf-8'))\n            self.wfile.write(f'acton_rts_conts_bucket{{thread=\"{k}\",le=\"100\"}} {v[\"conts_100s\"]}\\n'.encode('utf-8'))\n            self.wfile.write(f'acton_rts_conts_bucket{{thread=\"{k}\",le=\"+Inf\"}} {v[\"conts_inf\"]}\\n'.encode('utf-8'))\n            self.wfile.write(f'acton_rts_conts_sum{{thread=\"{k}\"}} {v[\"conts_sum\"]}\\n'.encode('utf-8'))\n            self.wfile.write(f'acton_rts_conts_count{{thread=\"{k}\"}} {v[\"conts_count\"]}\\n'.encode('utf-8'))\n\n        self.wfile.write(f'acton_rts_conts_bucket{{thread=\"sum\",le=\"0.0000001\"}} {total[\"conts_100ns\"]}\\n'.encode('utf-8'))\n        self.wfile.write(f'acton_rts_conts_bucket{{thread=\"sum\",le=\"0.000001\"}} {total[\"conts_1us\"]}\\n'.encode('utf-8'))\n        self.wfile.write(f'acton_rts_conts_bucket{{thread=\"sum\",le=\"0.00001\"}} {total[\"conts_10us\"]}\\n'.encode('utf-8'))\n        self.wfile.write(f'acton_rts_conts_bucket{{thread=\"sum\",le=\"0.0001\"}} {total[\"conts_100us\"]}\\n'.encode('utf-8'))\n        self.wfile.write(f'acton_rts_conts_bucket{{thread=\"sum\",le=\"0.001\"}} {total[\"conts_1ms\"]}\\n'.encode('utf-8'))\n        self.wfile.write(f'acton_rts_conts_bucket{{thread=\"sum\",le=\"0.01\"}} {total[\"conts_10ms\"]}\\n'.encode('utf-8'))\n        self.wfile.write(f'acton_rts_conts_bucket{{thread=\"sum\",le=\"0.1\"}} {total[\"conts_100ms\"]}\\n'.encode('utf-8'))\n        self.wfile.write(f'acton_rts_conts_bucket{{thread=\"sum\",le=\"1\"}} {total[\"conts_1s\"]}\\n'.encode('utf-8'))\n        self.wfile.write(f'acton_rts_conts_bucket{{thread=\"sum\",le=\"10\"}} {total[\"conts_10s\"]}\\n'.encode('utf-8'))\n        self.wfile.write(f'acton_rts_conts_bucket{{thread=\"sum\",le=\"100\"}} {total[\"conts_100s\"]}\\n'.encode('utf-8'))\n        self.wfile.write(f'acton_rts_conts_bucket{{thread=\"sum\",le=\"+Inf\"}} {total[\"conts_inf\"]}\\n'.encode('utf-8'))\n        self.wfile.write(f'acton_rts_conts_sum{{thread=\"sum\"}} {total[\"conts_sum\"]}\\n'.encode('utf-8'))\n        self.wfile.write(f'acton_rts_conts_count{{thread=\"sum\"}} {total[\"conts_count\"]}\\n'.encode('utf-8'))\n\n        self.wfile.write(b'# HELP acton_rts_bkeep Bookkeeping\\n')\n        self.wfile.write(b'# TYPE acton_rts_bkeep histogram\\n')\n        for k,v in sorted(data['wt'].items(), key=lambda item: int(item[0])):\n            total['bkeep_count'] += v['bkeep_count']\n            total['bkeep_sum'] += v['bkeep_sum']\n            total['bkeep_100ns'] += v['bkeep_100ns']\n            total['bkeep_1us'] += v['bkeep_1us']\n            total['bkeep_10us'] += v['bkeep_10us']\n            total['bkeep_100us'] += v['bkeep_100us']\n            total['bkeep_1ms'] += v['bkeep_1ms']\n            total['bkeep_10ms'] += v['bkeep_10ms']\n            total['bkeep_100ms'] += v['bkeep_100ms']\n            total['bkeep_1s'] += v['bkeep_1s']\n            total['bkeep_10s'] += v['bkeep_10s']\n            total['bkeep_100s'] += v['bkeep_100s']\n            total['bkeep_inf'] += v['bkeep_inf']\n\n            self.wfile.write(f'acton_rts_bkeep_bucket{{thread=\"{k}\",le=\"0.0000001\"}} {v[\"bkeep_100ns\"]}\\n'.encode('utf-8'))\n            self.wfile.write(f'acton_rts_bkeep_bucket{{thread=\"{k}\",le=\"0.000001\"}} {v[\"bkeep_1us\"]}\\n'.encode('utf-8'))\n            self.wfile.write(f'acton_rts_bkeep_bucket{{thread=\"{k}\",le=\"0.00001\"}} {v[\"bkeep_10us\"]}\\n'.encode('utf-8'))\n            self.wfile.write(f'acton_rts_bkeep_bucket{{thread=\"{k}\",le=\"0.0001\"}} {v[\"bkeep_100us\"]}\\n'.encode('utf-8'))\n            self.wfile.write(f'acton_rts_bkeep_bucket{{thread=\"{k}\",le=\"0.001\"}} {v[\"bkeep_1ms\"]}\\n'.encode('utf-8'))\n            self.wfile.write(f'acton_rts_bkeep_bucket{{thread=\"{k}\",le=\"0.01\"}} {v[\"bkeep_10ms\"]}\\n'.encode('utf-8'))\n            self.wfile.write(f'acton_rts_bkeep_bucket{{thread=\"{k}\",le=\"0.1\"}} {v[\"bkeep_100ms\"]}\\n'.encode('utf-8'))\n            self.wfile.write(f'acton_rts_bkeep_bucket{{thread=\"{k}\",le=\"1\"}} {v[\"bkeep_1s\"]}\\n'.encode('utf-8'))\n            self.wfile.write(f'acton_rts_bkeep_bucket{{thread=\"{k}\",le=\"10\"}} {v[\"bkeep_10s\"]}\\n'.encode('utf-8'))\n            self.wfile.write(f'acton_rts_bkeep_bucket{{thread=\"{k}\",le=\"100\"}} {v[\"bkeep_100s\"]}\\n'.encode('utf-8'))\n            self.wfile.write(f'acton_rts_bkeep_bucket{{thread=\"{k}\",le=\"+Inf\"}} {v[\"bkeep_inf\"]}\\n'.encode('utf-8'))\n            self.wfile.write(f'acton_rts_bkeep_sum{{thread=\"{k}\"}} {v[\"bkeep_sum\"]}\\n'.encode('utf-8'))\n            self.wfile.write(f'acton_rts_bkeep_count{{thread=\"{k}\"}} {v[\"bkeep_count\"]}\\n'.encode('utf-8'))\n\n        self.wfile.write(f'acton_rts_bkeep_bucket{{thread=\"sum\",le=\"0.0000001\"}} {total[\"bkeep_100ns\"]}\\n'.encode('utf-8'))\n        self.wfile.write(f'acton_rts_bkeep_bucket{{thread=\"sum\",le=\"0.000001\"}} {total[\"bkeep_1us\"]}\\n'.encode('utf-8'))\n        self.wfile.write(f'acton_rts_bkeep_bucket{{thread=\"sum\",le=\"0.00001\"}} {total[\"bkeep_10us\"]}\\n'.encode('utf-8'))\n        self.wfile.write(f'acton_rts_bkeep_bucket{{thread=\"sum\",le=\"0.0001\"}} {total[\"bkeep_100us\"]}\\n'.encode('utf-8'))\n        self.wfile.write(f'acton_rts_bkeep_bucket{{thread=\"sum\",le=\"0.001\"}} {total[\"bkeep_1ms\"]}\\n'.encode('utf-8'))\n        self.wfile.write(f'acton_rts_bkeep_bucket{{thread=\"sum\",le=\"0.01\"}} {total[\"bkeep_10ms\"]}\\n'.encode('utf-8'))\n        self.wfile.write(f'acton_rts_bkeep_bucket{{thread=\"sum\",le=\"0.1\"}} {total[\"bkeep_100ms\"]}\\n'.encode('utf-8'))\n        self.wfile.write(f'acton_rts_bkeep_bucket{{thread=\"sum\",le=\"1\"}} {total[\"bkeep_1s\"]}\\n'.encode('utf-8'))\n        self.wfile.write(f'acton_rts_bkeep_bucket{{thread=\"sum\",le=\"10\"}} {total[\"bkeep_10s\"]}\\n'.encode('utf-8'))\n        self.wfile.write(f'acton_rts_bkeep_bucket{{thread=\"sum\",le=\"100\"}} {total[\"bkeep_100s\"]}\\n'.encode('utf-8'))\n        self.wfile.write(f'acton_rts_bkeep_bucket{{thread=\"sum\",le=\"+Inf\"}} {total[\"bkeep_inf\"]}\\n'.encode('utf-8'))\n        self.wfile.write(f'acton_rts_bkeep_sum{{thread=\"sum\"}} {total[\"bkeep_sum\"]}\\n'.encode('utf-8'))\n        self.wfile.write(f'acton_rts_bkeep_count{{thread=\"sum\"}} {total[\"bkeep_count\"]}\\n'.encode('utf-8'))\n\n        self.wfile.write(b'# HELP acton_rts_dbc_ops_called DB Client operation called\\n')\n        self.wfile.write(b'# TYPE acton_rts_dbc_ops_called counter\\n')\n        for k,v in data['db_client'].items():\n            self.wfile.write(f'acton_rts_dbc_ops_called{{type=\"{k}\"}} {v[\"called\"]}\\n'.encode('utf-8'))\n\n        self.wfile.write(b'# HELP acton_rts_dbc_ops_completed DB Client operation completed\\n')\n        self.wfile.write(b'# TYPE acton_rts_dbc_ops_completed counter\\n')\n        for k,v in data['db_client'].items():\n            self.wfile.write(f'acton_rts_dbc_ops_completed{{type=\"{k}\"}} {v[\"completed\"]}\\n'.encode('utf-8'))\n\n        self.wfile.write(b'# HELP acton_rts_dbc_ops_success DB Client operation success\\n')\n        self.wfile.write(b'# TYPE acton_rts_dbc_ops_success counter\\n')\n        for k,v in data['db_client'].items():\n            self.wfile.write(f'acton_rts_dbc_ops_success{{type=\"{k}\"}} {v[\"success\"]}\\n'.encode('utf-8'))\n\n        self.wfile.write(b'# HELP acton_rts_dbc_ops_error DB Client operation errors\\n')\n        self.wfile.write(b'# TYPE acton_rts_dbc_ops_error counter\\n')\n        for k,v in data['db_client'].items():\n            self.wfile.write(f'acton_rts_dbc_ops_error{{type=\"{k}\"}} {v[\"error\"]}\\n'.encode('utf-8'))\n\n        self.wfile.write(b'# HELP acton_rts_dbc_ops_no_quorum DB Client operation no_quorum\\n')\n        self.wfile.write(b'# TYPE acton_rts_dbc_ops_no_quorum counter\\n')\n        for k,v in data['db_client'].items():\n            self.wfile.write(f'acton_rts_dbc_ops_no_quorum{{type=\"{k}\"}} {v[\"no_quorum\"]}\\n'.encode('utf-8'))\n\n        self.wfile.write(b'# HELP acton_rts_dbc_ops DB client operations\\n')\n        self.wfile.write(b'# TYPE acton_rts_dbc_ops histogram\\n')\n        for k,v in data['db_client'].items():\n            self.wfile.write(f'acton_rts_dbc_ops_bucket{{type=\"{k}\",le=\"0.0000001\"}} {v[\"time_100ns\"]}\\n'.encode('utf-8'))\n            self.wfile.write(f'acton_rts_dbc_ops_bucket{{type=\"{k}\",le=\"0.000001\"}} {v[\"time_1us\"]}\\n'.encode('utf-8'))\n            self.wfile.write(f'acton_rts_dbc_ops_bucket{{type=\"{k}\",le=\"0.00001\"}} {v[\"time_10us\"]}\\n'.encode('utf-8'))\n            self.wfile.write(f'acton_rts_dbc_ops_bucket{{type=\"{k}\",le=\"0.0001\"}} {v[\"time_100us\"]}\\n'.encode('utf-8'))\n            self.wfile.write(f'acton_rts_dbc_ops_bucket{{type=\"{k}\",le=\"0.001\"}} {v[\"time_1ms\"]}\\n'.encode('utf-8'))\n            self.wfile.write(f'acton_rts_dbc_ops_bucket{{type=\"{k}\",le=\"0.01\"}} {v[\"time_10ms\"]}\\n'.encode('utf-8'))\n            self.wfile.write(f'acton_rts_dbc_ops_bucket{{type=\"{k}\",le=\"0.1\"}} {v[\"time_100ms\"]}\\n'.encode('utf-8'))\n            self.wfile.write(f'acton_rts_dbc_ops_bucket{{type=\"{k}\",le=\"1\"}} {v[\"time_1s\"]}\\n'.encode('utf-8'))\n            self.wfile.write(f'acton_rts_dbc_ops_bucket{{type=\"{k}\",le=\"10\"}} {v[\"time_10s\"]}\\n'.encode('utf-8'))\n            self.wfile.write(f'acton_rts_dbc_ops_bucket{{type=\"{k}\",le=\"100\"}} {v[\"time_100s\"]}\\n'.encode('utf-8'))\n            self.wfile.write(f'acton_rts_dbc_ops_bucket{{type=\"{k}\",le=\"+Inf\"}} {v[\"time_inf\"]}\\n'.encode('utf-8'))\n            self.wfile.write(f'acton_rts_dbc_ops_sum{{type=\"{k}\"}} {v[\"time_sum\"]}\\n'.encode('utf-8'))\n            self.wfile.write(f'acton_rts_dbc_ops_count{{type=\"{k}\"}} {v[\"success\"]+v[\"error\"]}\\n'.encode('utf-8'))\n\n\ndef prompom(sock_addr, listen_addr='0.0.0.0', listen_port=8000):\n    ad = (listen_addr, listen_port)\n    print(f\"Serving stuff on {ad}\")\n\n    handler = partial(PromHTTPRequestHandler, sock_addr)\n    httpd = HTTPServer(ad, handler)\n    httpd.serve_forever()\n\n\ndef mon(address, interval, once):\n    ms = MonSock(address)\n    while True:\n        data = ms.cmd(\"WTS\")\n        print(f\"Program: {data['name']}  PID: {data['pid']}\")\n        print(\"WT#  State  Conts  Sleeps\")\n        print(\"--------------------------------------------------------------------------------\")\n        for k,v in sorted(data['wt'].items(), key=lambda item: int(item[0])):\n            print(f\"{k:>3}: {v['state']:>6} {v['conts_count']:6} {v['sleeps']:7}\")\n        if once:\n            break\n        time.sleep(interval)\n\n\ndef actors(address, interval, once):\n    ms = MonSock(address)\n    while True:\n        data = ms.cmd(\"actors\")\n        print(\"Actor#  RTS              Local  Status\")\n        print(\"--------------------------------------------------------------------------------\")\n        for k, v in data['actors'].items():\n            print(f\"{k:>6}: {v['rts']:16} {v['local']:6} {v['status']}\")\n\n        if once:\n            break\n        time.sleep(interval)\n\n\ndef rich_actors(address, interval, once):\n    from rich.live import Live\n    from rich.table import Table\n\n    ms = MonSock(address)\n\n    def generate_table() -> Table:\n        table = Table(title=\"Actors\")\n\n        table.add_column(\"ID\", style=\"cyan\", no_wrap=True)\n        table.add_column(\"RTS\", style=\"magenta\")\n        table.add_column(\"Local\", style=\"magenta\")\n        table.add_column(\"Status\")\n\n        while True:\n            try:\n                data = ms.cmd(\"actors\")\n                break\n            except ConnectionError:\n                time.sleep(0.5)\n\n        status_to_color = {\n            'running': 'green',\n            'migrating': 'orange',\n            'stopped': 'yellow'\n        }\n        for k,v in data['actors'].items():\n            table.add_row(k, v['rts'], v['local'], f\"[{status_to_color[v['status']]}]{v['status']}\")\n\n        return table\n\n    with Live(generate_table(), refresh_per_second=(1.0/interval)) as live:\n        while True:\n            time.sleep(interval)\n            live.update(generate_table())\n            if once:\n                break\n\n\ndef actdb_membership(address, interval, once):\n    ms = MonSock(address)\n    while True:\n        data = ms.cmd(\"membership\")\n        print(json.dumps(data))\n\n        if once:\n            break\n        time.sleep(interval)\n\n\ndef rich_actdb_membership(address, interval, once):\n    from rich.live import Live\n    from rich.table import Table\n\n    ms = MonSock(address)\n\n    def generate_table() -> Table:\n        table = Table(title=\"Distributed Acton Members\")\n\n        table.add_column(\"Node\", style=\"cyan\", no_wrap=True)\n        table.add_column(\"Type\", style=\"magenta\")\n        table.add_column(\"Status\")\n\n        while True:\n            try:\n                data = ms.cmd(\"membership\")\n                break\n            except ConnectionError:\n                time.sleep(0.5)\n\n        status_to_color = {\n            'live': 'green',\n            'dead': 'red',\n            'unknown': 'orange',\n            'prejoined': 'blue'\n        }\n        for k,v in data['nodes'].items():\n            table.add_row(k, v['type'], f\"[{status_to_color[v['status']]}]{v['status']}\")\n\n        return table\n\n    with Live(generate_table(), refresh_per_second=(1.0/interval)) as live:\n        while True:\n            time.sleep(interval)\n            live.update(generate_table())\n            if once:\n                break\n\n\ndef richmon(address, interval, once):\n    from rich.live import Live\n    from rich.table import Table\n\n    ms = MonSock(address)\n\n    def generate_table() -> Table:\n        table = Table(title=\"Acton RTS worker thread statistics\")\n\n        table.add_column(\"WT#\", style=\"cyan\", no_wrap=True)\n        table.add_column(\"State\", style=\"magenta\")\n        table.add_column(\"Sleeps\", justify=\"right\", style=\"green\")\n\n        table.add_column(\"Continuations\", justify=\"right\", style=\"green\")\n        table.add_column(\"Sum\", justify=\"right\", style=\"green\")\n        table.add_column(\"<100ns\", justify=\"right\", style=\"green\")\n        table.add_column(\"<1us\", justify=\"right\", style=\"green\")\n        table.add_column(\"<10us\", justify=\"right\", style=\"green\")\n        table.add_column(\"<100us\", justify=\"right\", style=\"green\")\n        table.add_column(\"<1ms\", justify=\"right\", style=\"green\")\n        table.add_column(\"<10ms\", justify=\"right\", style=\"green\")\n        table.add_column(\"<100ms\", justify=\"right\", style=\"green\")\n        table.add_column(\"<1s\", justify=\"right\", style=\"green\")\n        table.add_column(\"<10s\", justify=\"right\", style=\"green\")\n        table.add_column(\"<100s\", justify=\"right\", style=\"green\")\n        table.add_column(\"<+Inf\", justify=\"right\", style=\"green\")\n\n        table.add_column(\"bkeep\", justify=\"right\", style=\"green\")\n        table.add_column(\"Sum\", justify=\"right\", style=\"green\")\n        table.add_column(\"<100ns\", justify=\"right\", style=\"green\")\n        table.add_column(\"<1us\", justify=\"right\", style=\"green\")\n        table.add_column(\"<10us\", justify=\"right\", style=\"green\")\n        table.add_column(\"<100us\", justify=\"right\", style=\"green\")\n        table.add_column(\"<1ms\", justify=\"right\", style=\"green\")\n        table.add_column(\"<10ms\", justify=\"right\", style=\"green\")\n        table.add_column(\"<100ms\", justify=\"right\", style=\"green\")\n        table.add_column(\"<1s\", justify=\"right\", style=\"green\")\n        table.add_column(\"<10s\", justify=\"right\", style=\"green\")\n        table.add_column(\"<100s\", justify=\"right\", style=\"green\")\n        table.add_column(\"<+Inf\", justify=\"right\", style=\"green\")\n\n        while True:\n            try:\n                data = ms.cmd(\"WTS\")\n                break\n            except ConnectionError:\n                time.sleep(0.5)\n\n        total = {k: 0 for k in data['wt']['0']}\n\n        total = {\n            'sleeps': 0,\n\n            'conts_count': 0,\n            'conts_sum': 0,\n            'conts_100ns': 0,\n            'conts_1us': 0,\n            'conts_10us': 0,\n            'conts_100us': 0,\n            'conts_1ms': 0,\n            'conts_10ms': 0,\n            'conts_100ms': 0,\n            'conts_1s': 0,\n            'conts_10s': 0,\n            'conts_100s': 0,\n            'conts_inf': 0,\n\n            'bkeep_count': 0,\n            'bkeep_sum': 0,\n            'bkeep_100ns': 0,\n            'bkeep_1us': 0,\n            'bkeep_10us': 0,\n            'bkeep_100us': 0,\n            'bkeep_1ms': 0,\n            'bkeep_10ms': 0,\n            'bkeep_100ms': 0,\n            'bkeep_1s': 0,\n            'bkeep_10s': 0,\n            'bkeep_100s': 0,\n            'bkeep_inf': 0,\n        }\n\n        for k,v in sorted(data['wt'].items(), key=lambda item: int(item[0])):\n            if k not in table.columns:\n                total['sleeps'] += v['sleeps']\n\n                total['conts_count'] += v['conts_count']\n                total['conts_sum'] += v['conts_sum']\n                total['conts_100ns'] += v['conts_100ns']\n                total['conts_1us'] += v['conts_1us']\n                total['conts_10us'] += v['conts_10us']\n                total['conts_100us'] += v['conts_100us']\n                total['conts_1ms'] += v['conts_1ms']\n                total['conts_10ms'] += v['conts_10ms']\n                total['conts_100ms'] += v['conts_100ms']\n                total['conts_1s'] += v['conts_1s']\n                total['conts_10s'] += v['conts_10s']\n                total['conts_100s'] += v['conts_100s']\n                total['conts_inf'] += v['conts_inf']\n\n                total['bkeep_count'] += v['bkeep_count']\n                total['bkeep_sum'] += v['bkeep_sum']\n                total['bkeep_100ns'] += v['bkeep_100ns']\n                total['bkeep_1us'] += v['bkeep_1us']\n                total['bkeep_10us'] += v['bkeep_10us']\n                total['bkeep_100us'] += v['bkeep_100us']\n                total['bkeep_1ms'] += v['bkeep_1ms']\n                total['bkeep_10ms'] += v['bkeep_10ms']\n                total['bkeep_100ms'] += v['bkeep_100ms']\n                total['bkeep_1s'] += v['bkeep_1s']\n                total['bkeep_10s'] += v['bkeep_10s']\n                total['bkeep_100s'] += v['bkeep_100s']\n                total['bkeep_inf'] += v['bkeep_inf']\n\n                table.add_row(k,\n                              v['state'],\n                              str(v['sleeps']),\n\n                              str(v['conts_count']),\n                              str(v['conts_sum']),\n                              str(v['conts_100ns']),\n                              str(v['conts_1us']),\n                              str(v['conts_10us']),\n                              str(v['conts_100us']),\n                              str(v['conts_1ms']),\n                              str(v['conts_10ms']),\n                              str(v['conts_100ms']),\n                              str(v['conts_1s']),\n                              str(v['conts_10s']),\n                              str(v['conts_100s']),\n                              str(v['conts_inf']),\n\n                              str(v['bkeep_count']),\n                              str(v['bkeep_sum']),\n                              str(v['bkeep_100ns']),\n                              str(v['bkeep_1us']),\n                              str(v['bkeep_10us']),\n                              str(v['bkeep_100us']),\n                              str(v['bkeep_1ms']),\n                              str(v['bkeep_10ms']),\n                              str(v['bkeep_100ms']),\n                              str(v['bkeep_1s']),\n                              str(v['bkeep_10s']),\n                              str(v['bkeep_100s']),\n                              str(v['bkeep_inf'])\n\n                              )\n        table.add_row(\"SUM\",\n                        '',\n                        str(total['sleeps']),\n\n                        str(total['conts_count']),\n                        str(total['conts_sum']),\n                        str(total['conts_100ns']),\n                        str(total['conts_1us']),\n                        str(total['conts_10us']),\n                        str(total['conts_100us']),\n                        str(total['conts_1ms']),\n                        str(total['conts_10ms']),\n                        str(total['conts_100ms']),\n                        str(total['conts_1s']),\n                        str(total['conts_10s']),\n                        str(total['conts_100s']),\n                        str(total['conts_inf']),\n\n                        str(total['bkeep_count']),\n                        str(total['bkeep_sum']),\n                        str(total['bkeep_100ns']),\n                        str(total['bkeep_1us']),\n                        str(total['bkeep_10us']),\n                        str(total['bkeep_100us']),\n                        str(total['bkeep_1ms']),\n                        str(total['bkeep_10ms']),\n                        str(total['bkeep_100ms']),\n                        str(total['bkeep_1s']),\n                        str(total['bkeep_10s']),\n                        str(total['bkeep_100s']),\n                        str(total['bkeep_inf']),\n                        )\n\n        return table\n\n    with Live(generate_table(), refresh_per_second=(1.0/interval)) as live:\n        while True:\n            time.sleep(interval)\n            live.update(generate_table())\n            if once:\n                break\n\n\nif __name__ == '__main__':\n    parser = argparse.ArgumentParser()\n    parser.add_argument(\"socket\")\n    parser.add_argument(\"--interval\", type=float, default=0.5)\n    parser.add_argument(\"--rich\", action=\"store_true\")\n    parser.add_argument(\"--once\", action=\"store_true\", default=False)\n    parser.add_argument(\"--prom\", action=\"store_true\")\n    parser.add_argument(\"--actors\", action=\"store_true\")\n    parser.add_argument(\"--actdb-membership\", action=\"store_true\")\n\n    args = parser.parse_args()\n\n    if args.actors:\n        if args.rich:\n            rich_actors(args.socket, args.interval, args.once)\n        else:\n            actors(args.socket, args.interval, args.once)\n    elif args.actdb_membership:\n        if args.rich:\n            rich_actdb_membership(args.socket, args.interval, args.once)\n        else:\n            actdb_membership(args.socket, args.interval, args.once)\n    elif args.prom:\n        prompom(args.socket)\n    elif args.rich:\n        richmon(args.socket, args.interval, args.once)\n    else:\n        mon(args.socket, args.interval, args.once)\n"
  },
  {
    "path": "utils/changelog-find-missing-link-defs.py",
    "content": "#!/usr/bin/env python3\n# Script to find short link refs, like '[#123]' in CHANGELOG.md which we use for\n# issue and pull request references. Maintaining the list of link definitions at\n# the end of the doc is a sort of PITA which this script helps with.\n#\n# Usage:\n# kll@Boxy ~/acton$ utils/changelog-find-missing-link-defs.py\n# Missing link definitions:\n# [#315]: https://github.com/actonlang/acton/pull/315\n# [#431]: https://github.com/actonlang/acton/issues/431\n# [#512]: https://github.com/actonlang/acton/pull/512\n# [#514]: https://github.com/actonlang/acton/pull/514\n# [#527]: https://github.com/actonlang/acton/issues/527\n# ...\n#\n# Copy the output text and add to CHANGELOG.md\n#\n# Sort the output with: '<,'>!awk -F'[\\#\\\\]]' '{ print $2 \"\\t\" $0 }' | sort -n | cut -f 2\n\nimport re\nimport requests\n\ndef find_short_link_refs(lines):\n    res = {}\n    for line in lines:\n        m = re.search(r\"[^]](\\[#[0-9]+\\])[^:[\\(]\", line)\n        if m:\n            res[m.group(1)] = False\n    return res\n\ndef find_link_defs(lines):\n    res = {}\n    for line in lines:\n        m = re.search(r\"^(\\[#[0-9]+\\]): (.*)\", line)\n        if m:\n            res[m.group(1)] = m.group(2)\n    return res\n\ndef get_url(tag):\n    # We don't know if a particular number tag is a pull request or an issue.\n    # Github will automatically redirect us though, so we just go pull/{num} and\n    # then check the returned url if it says issue or pull.\n    num = re.sub(\"[^0-9]\", \"\", tag)\n    r = requests.get(f\"https://github.com/actonlang/acton/pull/{num}\")\n    return r.url\n\n\nf = open(\"CHANGELOG.md\")\nlines = f.readlines()\nf.close()\n\nlinks = find_short_link_refs(lines)\ndefs = find_link_defs(lines)\nmissing = sorted(set(links) - set(defs))\nprint(\"Missing link definitions:\")\nfor num in missing:\n    url = get_url(num)\n    print(f\"{num}: {url}\")\n"
  },
  {
    "path": "utils/lldb/README.md",
    "content": "Acton LLDB Plugin (Prototype)\n\nPython plugin to improve debugging of Acton programs in LLDB on macOS. Provides filtered/demangled backtraces, readable locals, and Acton‑aware pretty printing.\n\nCommands\n- `acton bt` — Filtered backtrace with Acton demangling and argument values\n  - Flags:\n    - `-a, --all` include hidden frames (RTS, system)\n    - `-f, --full` include all threads\n    - `--no-demangle` turn off demangling\n    - `--show-original` show original symbol next to demangled\n    - `--hide-regex REGEX` add extra hide regex (repeatable)\n    - `--clear-hides` clear previously added hide regexes\n    - `--color/--no-color` toggle ANSI colors for file:line\n    - `--no-arg-values` do not print argument values in bt\n- `acton locals` — In‑scope args/locals with demangled names and value summaries\n  - Flags:\n    - `--no-demangle`\n    - `--all` include statics, out‑of‑scope and artificial\n    - `--args-only` only show function arguments\n    - `--no-hide-meta` include meta/runtime variables (by default hides `$`/`__` vars, method tables, `$class`, and `C_cont`)\n- `acton demangle [name]` — Demangle a single name; if omitted, uses the selected frame function\n- `acton break <file.act>:<line>` — Set a breakpoint by Acton source location. Alias: `acton-bp`\n\nAliases\n- Hyphenated: `acton-bt`, `acton-locals`, `acton-demangle`\n- Dotted (if your LLDB accepts it): `acton.bt`, `acton.locals`, `acton.demangle`\n\nLoading\n1) One‑off inside LLDB:\n   - `(lldb) command script import /absolute/path/to/acton/utils/lldb/acton.py`\n   - Reload after edits with `-r`:\n     - `(lldb) command script import -r /absolute/path/to/acton/utils/lldb/acton.py`\n2) Auto‑load on startup (`~/.lldbinit`):\n   - `command script import /absolute/path/to/acton/utils/lldb/acton.py`\n\nSource breakpoints (Acton file:line)\n- Requires debug info that references `.act` files (build with `acton --debug`).\n- Examples:\n  - `(lldb) breakpoint set -f stackdemo.act -l 7`\n  - `(lldb) acton break stackdemo.act:7`\n- If no locations resolve, the helper prints source‑map hints based on compile units. You can map build paths to your checkout:\n  - `(lldb) settings set target.source-map /old/build/root /Users/me/src/acton`\n\nDemangling and name rewrites\n- Heuristics to improve readability:\n  - `Q_` → `.` (module separators)\n  - `D___` → `.` and `D_` → `.` (method separators)\n  - `G_` → `.` (generic/section)\n  - `$` → `.` (C identifiers like `to$int` → `to.int`)\n  - Drop `B_` prefix for builtins (e.g. `B_str` → `str`)\n  - Drop `U_` prefix for unboxed C locals and trim leading numeric index: `U_5v3` → `v3`\n  - Strip trailing `.local` synthesized from `G_local`\n\nValue summaries / pretty printing\n- Backtrace arguments and locals:\n  - Boxed values are stringified via `B_value.__str__` and printed. This covers objects/actors/classes (e.g. `<stackdemo.main object at 0x…>`), builtin numbers, etc.\n  - Strings (`B_str`) are read directly and printed quoted (UTF‑8, with escaping).\n  - Unboxed C types (e.g. `uint64_t`, `int64_t`) use LLDB’s native formatting.\n  - The CPS continuation arg `C_cont` is hidden by default in `acton locals` and excluded from bt arg lists.\n  - If stringification fails, we fall back to numeric conversions for simple builtins, then raw pointer.\n\nColors\n- By default, `acton bt` prints file:line with colors (file in cyan, line in yellow). Use `--no-color` or set `ACTON_LLDB_NO_COLOR=1` to disable.\n\nEnvironment overrides\n- `ACTON_LLDB_HIDE_REGEX` — comma‑separated regexes to hide symbol names\n- `ACTON_LLDB_NO_DEMANGLE` — disable demangling\n- `ACTON_LLDB_SHOW_ORIGINAL` — print original symbol next to demangled\n- `ACTON_LLDB_NO_COLOR` / `ACTON_LLDB_COLOR` — control colors\n- `ACTON_LLDB_NO_ARG_VALUES` — disable argument value printing in bt\n\nBatch usage examples\n- Quick one‑liner:\n  - `lldb examples/stackdemo -o 'command script import utils/lldb/acton.py' -o 'b stackdemo.act:7' -o 'run' -o 'acton locals' -o 'acton bt' --batch`\n- With module‑wide breakpoints:\n  - `lldb -o 'command script import utils/lldb/acton.py' -o 'br s -r \"stackdemoQ_.*\"' -o run -- examples/stackdemo`\n\nTroubleshooting\n- Ensure your binary has debug info pointing at `.act` files (compile with `acton --debug`).\n- If bt/locals do not show Acton files, check source‑map settings.\n- If value printing is slow or too verbose in bt, pass `--no-arg-values`.\n\nNotes\n- This is a prototype; the demangler is heuristic. We can refine as needed and later move these capabilities to a native C++ plugin for deeper integration.\n"
  },
  {
    "path": "utils/lldb/acton.py",
    "content": "\"\"\"\nActon LLDB plugin\n\nFeatures:\n- acton.bt: filtered backtrace with basic Acton demangling\n- acton.locals: print locals with Acton demangled names\n- acton.demangle: demangle a single symbol or the selected frame name\n\nLoad in LLDB:\n  (lldb) command script import /path/to/repo/utils/lldb/acton.py\n  (lldb) acton.bt\n\"\"\"\n\nfrom __future__ import annotations\n\nimport lldb  # type: ignore\nimport argparse\nimport os\nimport re\nfrom typing import List, Optional\n\n\n# ------------------------------\n# Config and defaults\n# ------------------------------\n\nDEFAULT_HIDE_FILE_SUBSTR = [\n    # \"/base/rts/\",\n    # \"/base/builtin/\",\n    \"/deps/\",\n]\n\nDEFAULT_HIDE_SYMBOL_REGEX = [\n    r\"^uv_\",  # libuv internals\n    r\"^pthread_\",\n    # r\"^__.*\",  # many system trampolines, but could also conflict perhaps? TODO: figure this out\n    r\"^_sigtramp$\",\n    r\"^start$\",\n    r\"^start_wqthread$\",\n]\n\nDEFAULT_HIDE_MODULE_SUBSTR = [\n    \"libsystem_\",\n    \"libdispatch\",\n    \"libdyld\",\n    \"libobjc.A.dylib\",\n    \"libc++.\",\n]\n\n\nclass Config:\n    def __init__(self) -> None:\n        self.hide_file_substrings: List[str] = list(DEFAULT_HIDE_FILE_SUBSTR)\n        self.hide_symbol_res: List[re.Pattern[str]] = [\n            re.compile(p) for p in DEFAULT_HIDE_SYMBOL_REGEX\n        ]\n        self.hide_module_substrings: List[str] = list(DEFAULT_HIDE_MODULE_SUBSTR)\n        self.enable_demangle: bool = True\n        self.show_original: bool = False\n        self.enable_color: bool = True\n        self.show_arg_values: bool = True\n\n\nCFG = Config()\n\n# ------------------------------\n# Demangler (heuristic)\n# ------------------------------\n\n_re_q_sep = re.compile(r\"Q_\")\n_re_d_magic = re.compile(r\"D___\")  # e.g. $ActorD___init__\n_re_d_sep = re.compile(r\"D_\")      # general Derived separator, e.g. mainD_foo -> main.foo\n_re_g_sep = re.compile(r\"G_\")\n\n\ndef demangle_acton(name: str) -> str:\n    \"\"\"Demangling of Acton/RTS symbol\n\n    - Replace module separators: 'Q_' -> '.' (e.g. actonQ_rtsQ_X -> acton.rts.X)\n    - Convert runtime method separators: 'D___' -> '.' (.__init__/__call__ etc.)\n    - Convert generic/section separators: 'G_' -> '.'\n    - Replace '$' with '.' to improve readability (e.g., to$int -> to.int)\n    - Trim leading '$' or common C prefixes (\"_\" on Darwin) while preserving name content.\n    \"\"\"\n    if not name:\n        return name\n\n    # Darwin symbols may be prefixed with '_'\n    if name.startswith(\"_\"):\n        name = name[1:]\n\n    # Quick return for plain C names, but still allow builtin/unboxed prefix stripping.\n    # Include 'U_' so we don't early-return for unboxed locals like U_5v3.\n    if (\"$\" not in name) and (\"Q_\" not in name) and (\"D___\" not in name) and (\"G_\" not in name) and (\"B_\" not in name) and (\"U_\" not in name):\n        return name\n\n    s = name\n    s = _re_q_sep.sub(\".\", s)\n    s = _re_d_magic.sub(\".\", s)\n    s = _re_d_sep.sub(\".\", s)\n    s = _re_g_sep.sub(\".\", s)\n    # Drop builtin prefix 'B_' (B_str -> str, B_dict -> dict, etc.)\n    s = re.sub(r\"\\bB_\", \"\", s)\n    # Drop unboxed prefix 'U_' used by codegen for C locals (U_5v3, U_tmp)\n    s = re.sub(r\"\\bU_\", \"\", s)\n    # After removing U_, drop any leading numeric index left by codegen: 5v3 -> v3, 6v4 -> v4\n    s = re.sub(r\"^\\d+([A-Za-z].*)$\", r\"\\1\", s)\n\n    # Drop trailing \".local\" produced from G_local (local method variant marker)\n    if s.endswith(\".local\"):\n        s = s[: -len(\".local\")]\n\n    # Remove possible duplicate dots created by substitutions\n    # s = re.sub(r\"\\.\\.+\", \".\", s)\n\n    # Trim leading dot if introduced\n    s = s[1:] if s.startswith(\".\") else s\n    return s\n\n\ndef maybe_demangle(name: str) -> str:\n    if not CFG.enable_demangle:\n        return name\n    try:\n        d = demangle_acton(name)\n        return d\n    except Exception:\n        return name\n\n\n# ------------------------------\n# Utilities\n# ------------------------------\n\ndef _frame_is_hidden(frame: lldb.SBFrame) -> bool:\n    # By file path\n    le = frame.GetLineEntry()\n    if le and le.IsValid():\n        fs = le.GetFileSpec()\n        if fs and fs.IsValid():\n            path = os.path.join(fs.GetDirectory() or \"\", fs.GetFilename() or \"\")\n            for part in CFG.hide_file_substrings:\n                if part in path:\n                    return True\n\n    # By module image\n    mod = frame.GetModule()\n    if mod and mod.IsValid():\n        mod_name = mod.GetFileSpec().GetFilename() or \"\"\n        for part in CFG.hide_module_substrings:\n            if part in mod_name:\n                return True\n\n    # By symbol name regex\n    sym_name = frame.GetFunctionName() or frame.GetSymbol().GetName() or \"\"\n    for rex in CFG.hide_symbol_res:\n        try:\n            if rex.search(sym_name or \"\"):\n                return True\n        except Exception:\n            # Ignore miscompiled regex\n            pass\n\n    return False\n\n\ndef _format_frame(idx: int, frame: lldb.SBFrame) -> str:\n    pc = frame.GetPCAddress()\n    load_addr = pc.GetLoadAddress(frame.GetThread().GetProcess().GetTarget())\n    fn = frame.GetDisplayFunctionName() or frame.GetFunctionName() or frame.GetSymbol().GetName() or \"?\"\n    demangled = maybe_demangle(fn)\n    args_str = _format_args(frame)\n    if CFG.show_original and demangled != fn:\n        name_part = f\"{demangled}{args_str} [{fn}]\"\n    else:\n        name_part = f\"{demangled}{args_str}\"\n\n    le = frame.GetLineEntry()\n    if le and le.IsValid():\n        fs = le.GetFileSpec()\n        filename = fs.GetFilename() or \"?\"\n        line_no = le.GetLine()\n        # Colorize file and line to match LLDB feel\n        loc = _fmt_file_line(filename, line_no)\n    else:\n        loc = \"?\"\n\n    return f\"#{idx:2d} 0x{load_addr:x} {name_part} at {loc}\"\n\n\ndef _iter_frames(only_visible: bool, thread: Optional[lldb.SBThread] = None):\n    if thread is None:\n        thread = lldb.debugger.GetSelectedTarget().process.GetSelectedThread()\n    if not thread or not thread.IsValid():\n        return []\n    frames = []\n    for f in thread:\n        if only_visible and _frame_is_hidden(f):\n            continue\n        frames.append(f)\n    return frames\n\n\n# ------------------------------\n# LLDB Commands\n# ------------------------------\n\ndef cmd_bt(debugger: lldb.SBDebugger, command: str, exe_ctx: lldb.SBExecutionContext, result: lldb.SBCommandReturnObject, _internal_dict=None) -> None:  # noqa: D401\n    \"\"\"acton.bt: Print a filtered backtrace with demangling.\n\n    Usage: acton.bt [-a|--all] [-f|--full] [--no-demangle] [--show-original]\n           [--hide-regex REGEX ...] [--clear-hides]\n\n    -a/--all: include hidden frames\n    -f/--full: include all threads (not just selected)\n    --no-demangle: disable demangling\n    --show-original: show original name alongside demangled\n    --hide-regex: add extra hide regex for symbol names (repeatable)\n    --clear-hides: clear all custom hide regexes\n    \"\"\"\n    try:\n        parser = argparse.ArgumentParser(prog=\"acton.bt\", add_help=False)\n        parser.add_argument(\"-a\", \"--all\", action=\"store_true\")\n        parser.add_argument(\"-f\", \"--full\", action=\"store_true\")\n        parser.add_argument(\"--no-demangle\", action=\"store_true\")\n        parser.add_argument(\"--show-original\", action=\"store_true\")\n        parser.add_argument(\"--hide-regex\", action=\"append\", default=[])\n        parser.add_argument(\"--clear-hides\", action=\"store_true\")\n        parser.add_argument(\"--color\", dest=\"color\", action=\"store_true\")\n        parser.add_argument(\"--no-color\", dest=\"no_color\", action=\"store_true\")\n        parser.add_argument(\"--no-arg-values\", action=\"store_true\", help=\"do not print argument values in bt\")\n\n        opts = parser.parse_args(shlex_split(command))\n    except SystemExit:\n        # argparse error; show help\n        result.PutCString(cmd_bt.__doc__ or \"\")\n        result.SetStatus(lldb.eReturnStatusFailed)\n        return\n\n    CFG.enable_demangle = not opts.no_demangle\n    CFG.show_original = bool(opts.show_original)\n    if opts.color:\n        CFG.enable_color = True\n    if opts.no_color:\n        CFG.enable_color = False\n    if opts.no_arg_values:\n        CFG.show_arg_values = False\n\n    if opts.clear_hides:\n        CFG.hide_symbol_res = []\n    for r in (opts.hide_regex or []):\n        try:\n            CFG.hide_symbol_res.append(re.compile(r))\n        except re.error as e:\n            result.PutCString(f\"Invalid regex '{r}': {e}\")\n\n    target = debugger.GetSelectedTarget()\n    proc = target.process\n    if not proc or not proc.IsValid():\n        result.PutCString(\"No process. Run or attach first.\")\n        result.SetStatus(lldb.eReturnStatusFailed)\n        return\n\n    threads = list(proc)\n    printed_any = False\n\n    def print_thread(th: lldb.SBThread):\n        nonlocal printed_any\n        header = f\"thread #{th.GetIndexID()}\"\n        result.PutCString(header)\n        frames = _iter_frames(not opts.all, th)\n        for idx, fr in enumerate(frames):\n            result.PutCString(_format_frame(idx, fr))\n        printed_any = True\n\n    if opts.full:\n        for th in threads:\n            print_thread(th)\n    else:\n        print_thread(proc.GetSelectedThread())\n\n    if not printed_any:\n        result.PutCString(\"No frames to display.\")\n\n\ndef cmd_locals(debugger: lldb.SBDebugger, command: str, exe_ctx: lldb.SBExecutionContext, result: lldb.SBCommandReturnObject, _internal_dict=None) -> None:  # noqa: D401\n    \"\"\"acton.locals: Print current frame locals with demangled names.\n\n    Usage: acton.locals [--no-demangle] [--all] [--args-only] [--no-hide-meta]\n\n    Defaults mimic `frame variable` more closely:\n    - show only in-scope arguments + locals\n    - exclude statics and artificial (compiler-generated) variables\n    \"\"\"\n    try:\n        parser = argparse.ArgumentParser(prog=\"acton.locals\", add_help=False)\n        parser.add_argument(\"--no-demangle\", action=\"store_true\")\n        parser.add_argument(\"--all\", action=\"store_true\", help=\"include statics, out-of-scope, artificial\")\n        parser.add_argument(\"--args-only\", action=\"store_true\", help=\"only show function arguments\")\n        parser.add_argument(\"--no-hide-meta\", action=\"store_true\", help=\"do not hide Acton meta vars (methods/class)\")\n        opts = parser.parse_args(shlex_split(command))\n    except SystemExit:\n        result.PutCString(cmd_locals.__doc__ or \"\")\n        result.SetStatus(lldb.eReturnStatusFailed)\n        return\n\n    frame = exe_ctx.GetFrame() if hasattr(exe_ctx, \"GetFrame\") else None\n    if not frame or not frame.IsValid():\n        result.PutCString(\"No selected frame.\")\n        result.SetStatus(lldb.eReturnStatusFailed)\n        return\n\n    demangle_on = CFG.enable_demangle and not opts.no_demangle\n\n    show_args = True\n    show_locals = not opts.args_only\n    show_statics = bool(opts.all)\n    in_scope_only = not opts.all\n\n    vals = frame.GetVariables(show_args, show_locals, show_statics, in_scope_only)\n\n    def is_meta_var(val: lldb.SBValue, dname: str, type_name: str) -> bool:\n        # Hide common Acton meta artifacts\n        raw = val.GetName() or \"\"\n        if hasattr(val, \"IsArtificial\") and val.IsArtificial():\n            return True\n        # Names that look like vtable/method tables\n        if dname.endswith(\".methods\") or dname.endswith(\".$class\") or dname.endswith(\".class\"):\n            return True\n        # Types that are class/method tables\n        if \"G_class\" in type_name or type_name.endswith(\".class\"):\n            return True\n        # Heuristic: internal $-prefixed or double-underscore names\n        if raw.startswith(\"$\") or raw.startswith(\"__\"):\n            return True\n        return False\n\n    printed = 0\n    def _label_from_gcinfo(v: lldb.SBValue) -> Optional[str]:\n        try:\n            base = v.Dereference() if v.TypeIsPointerType() else v\n            if not base or not base.IsValid():\n                return None\n            cls = base.GetChildMemberWithName(\"$class\")\n            if not cls or not cls.IsValid():\n                return None\n            cls_d = cls.Dereference() if cls.TypeIsPointerType() else cls\n            gc = cls_d.GetChildMemberWithName(\"$GCINFO\")\n            if not gc or not gc.IsValid():\n                return None\n            addr = gc.GetValueAsUnsigned()\n            if not addr:\n                return None\n            proc = v.GetTarget().GetProcess()\n            err = lldb.SBError()\n            s = proc.ReadCStringFromMemory(addr, 256, err)\n            if (err.Success() or not err.Fail()) and s:\n                return maybe_demangle(s)\n            return None\n        except Exception:\n            return None\n    for v in vals:\n        if not v or not v.IsValid():\n            continue\n        name = v.GetName() or \"?\"\n        # Hide CPS continuation argument in locals by default\n        if name == \"C_cont\" and not opts.no_hide_meta:\n            continue\n        dname = demangle_acton(name) if demangle_on else name\n        type_name = maybe_demangle(v.GetTypeName() or \"\")\n        if not type_name or type_name in (\"$WORD\", \"WORD\"):\n            lbl = _label_from_gcinfo(v)\n            if lbl:\n                type_name = lbl\n\n        if not opts.no_hide_meta and is_meta_var(v, dname, type_name):\n            continue\n\n        try:\n            # Prefer LLDB's summary providers (works in DAP), fallback to our eval-based summary\n            summary = v.GetSummary() or _acton_value_summary(v, exe_ctx) or v.GetValue() or \"\"\n        except Exception:\n            summary = v.GetValue() or \"\"\n        summary = (summary or \"\").strip()\n\n        if type_name:\n            line = f\"{dname}: {type_name} = {summary}\"\n        else:\n            line = f\"{dname} = {summary}\"\n        result.PutCString(line)\n        printed += 1\n\n    if printed == 0:\n        result.PutCString(\"(no in-scope arguments/locals)\")\n\n\ndef cmd_demangle(debugger: lldb.SBDebugger, command: str, exe_ctx: lldb.SBExecutionContext, result: lldb.SBCommandReturnObject, _internal_dict=None) -> None:  # noqa: D401\n    \"\"\"acton.demangle: Demangle a raw Acton/RTS name or the current frame.\n\n    Usage: acton.demangle [raw_name]\n           If no name is provided, demangle the selected frame function.\n    \"\"\"\n    raw = command.strip()\n    if not raw:\n        frame = exe_ctx.GetFrame() if hasattr(exe_ctx, \"GetFrame\") else None\n        if not frame or not frame.IsValid():\n            result.PutCString(\"No selected frame and no name provided.\")\n            result.SetStatus(lldb.eReturnStatusFailed)\n            return\n        raw = frame.GetDisplayFunctionName() or frame.GetFunctionName() or frame.GetSymbol().GetName() or \"\"\n    if not raw:\n        result.PutCString(\"No symbol name found.\")\n        result.SetStatus(lldb.eReturnStatusFailed)\n        return\n    result.PutCString(maybe_demangle(raw))\n\n\n# ------------------------------\n# Registration\n# ------------------------------\n\ndef __lldb_init_module(debugger: lldb.SBDebugger, _internal_dict) -> None:\n    # Group commands under 'acton'\n    # Register commands (multiple spellings for compatibility with LLDB parser)\n    # Dotted form (may be ambiguous on some LLDB builds)\n    _add_cmd(debugger, \"acton.bt\", cmd_bt, \"Filtered backtrace with Acton demangling\")\n    _add_cmd(debugger, \"acton.locals\", cmd_locals, \"Print locals with Acton demangled names\")\n    _add_cmd(debugger, \"acton.demangle\", cmd_demangle, \"Demangle a symbol or current frame\")\n    # Hyphenated aliases\n    _add_cmd(debugger, \"acton-bt\", cmd_bt, \"Filtered backtrace with Acton demangling\")\n    _add_cmd(debugger, \"acton-locals\", cmd_locals, \"Print locals with Acton demangled names\")\n    _add_cmd(debugger, \"acton-demangle\", cmd_demangle, \"Demangle a symbol or current frame\")\n    # Group command with subcommands: `acton bt|locals|demangle`\n    _add_cmd(debugger, \"acton\", cmd_root, \"Acton command group: bt | locals | demangle\")\n    # Breakpoint helper\n    _add_cmd(debugger, \"acton.break\", cmd_break, \"Set breakpoint at Acton file:line\")\n    _add_cmd(debugger, \"acton-bp\", cmd_break, \"Set breakpoint at Acton file:line\")\n\n    # Environment-driven config (optional)\n    _apply_env_overrides()\n\n    print(\"Acton LLDB plugin loaded. Commands: acton bt|locals|demangle; aliases: acton-bt, acton-locals, acton-demangle, acton.bt, acton.locals, acton.demangle\")\n    try:\n        _register_formatters()\n    except Exception:\n        # Keep plugin usable even if formatters fail to register\n        pass\n\n\ndef _add_cmd(debugger: lldb.SBDebugger, name: str, func, help_text: str) -> None:\n    # Register a Python function as an LLDB command.\n    # Keep this compatible with stock LLDB on macOS (no SBCommandPluginInterface).\n    # Use --overwrite so reloads work without manual settings tweaks.\n    debugger.HandleCommand(\n        f\"command script add --overwrite -f {__name__}.{func.__name__} {name}\"\n    )\n    # Note: LLDB doesn't expose a stable API to set rich help text here.\n    # The function's docstring is shown when you run `help {name}`.\n\n\ndef _apply_env_overrides() -> None:\n    # ACTON_LLDB_HIDE_REGEX: comma-separated regexes\n    rx = os.getenv(\"ACTON_LLDB_HIDE_REGEX\")\n    if rx:\n        for r in rx.split(\",\"):\n            r = r.strip()\n            if not r:\n                continue\n            try:\n                CFG.hide_symbol_res.append(re.compile(r))\n            except re.error:\n                pass\n    # ACTON_LLDB_NO_DEMANGLE: if set, disable demangling\n    if os.getenv(\"ACTON_LLDB_NO_DEMANGLE\"):\n        CFG.enable_demangle = False\n    # ACTON_LLDB_SHOW_ORIGINAL: if set, print original symbol alongside demangled\n    if os.getenv(\"ACTON_LLDB_SHOW_ORIGINAL\"):\n        CFG.show_original = True\n    if os.getenv(\"ACTON_LLDB_NO_COLOR\"):\n        CFG.enable_color = False\n    if os.getenv(\"ACTON_LLDB_COLOR\"):\n        CFG.enable_color = True\n    if os.getenv(\"ACTON_LLDB_NO_ARG_VALUES\"):\n        CFG.show_arg_values = False\n\n\n# ------------------------------\n# Data formatters (type summaries)\n# ------------------------------\n\ndef _expr_opts() -> lldb.SBExpressionOptions:\n    opts = lldb.SBExpressionOptions()\n    opts.SetIgnoreBreakpoints(True)\n    opts.SetUnwindOnError(True)\n    opts.SetLanguage(lldb.eLanguageTypeC)\n    return opts\n\n\ndef _read_cstring(valobj: lldb.SBValue, char_ptr_val: lldb.SBValue, max_len: int = 2048) -> Optional[str]:\n    try:\n        if not char_ptr_val or not char_ptr_val.IsValid():\n            return None\n        addr = char_ptr_val.GetValueAsUnsigned()\n        if not addr:\n            return None\n        process = valobj.GetTarget().GetProcess()\n        err = lldb.SBError()\n        s = process.ReadCStringFromMemory(addr, max_len, err)\n        if (err.Success() or not err.Fail()) and s is not None:\n            return s\n        return None\n    except Exception:\n        return None\n\n\ndef sum_B_str(valobj: lldb.SBValue, _internal_dict) -> Optional[str]:\n    \"\"\"Summary for B_str values: print quoted UTF-8 string.\"\"\"\n    try:\n        ty = valobj.GetTypeName() or \"\"\n        ptr = valobj.GetValue() or \"\"\n        # Prefer calling fromB_str to get a C string pointer\n        if ptr.startswith(\"0x\"):\n            expr = f\"(char*)fromB_str(({ty}){ptr})\"\n            sev = valobj.EvaluateExpression(expr, _expr_opts())\n            s = _read_cstring(valobj, sev)\n            if s is not None:\n                s = s.replace('\\\\', r'\\\\').replace('\"', r'\\\"')\n                return f'\"{s}\"'\n        # Fallback: read fields directly\n        base = valobj.Dereference() if valobj.TypeIsPointerType() else valobj\n        if not base or not base.IsValid():\n            return None\n        nb = base.GetChildMemberWithName(\"nbytes\")\n        sp = base.GetChildMemberWithName(\"str\")\n        if nb and nb.IsValid() and sp and sp.IsValid():\n            nbytes = nb.GetValueAsUnsigned()\n            addr = sp.GetValueAsUnsigned()\n            if nbytes and addr:\n                process = valobj.GetTarget().GetProcess()\n                err = lldb.SBError()\n                data = process.ReadMemory(addr, int(nbytes), err)\n                if (err.Success() or not err.Fail()) and data is not None:\n                    try:\n                        s = data.decode('utf-8', errors='replace')\n                        s = s.replace('\\\\', r'\\\\').replace('\"', r'\\\"')\n                        return f'\"{s}\"'\n                    except Exception:\n                        return None\n        return None\n    except Exception:\n        return None\n\n\ndef _summary_via___str__(valobj: lldb.SBValue) -> Optional[str]:\n    try:\n        ptr = valobj.GetValue() or \"\"\n        if not ptr.startswith(\"0x\"):\n            return None\n        # Dynamically dispatch via vtable: ((B_value)ptr)->$class->__str__((B_value)ptr)\n        expr = f\"(char*)fromB_str(((B_value){ptr})->$class->__str__(((B_value){ptr})))\"\n        sev = valobj.EvaluateExpression(expr, _expr_opts())\n        return _read_cstring(valobj, sev)\n    except Exception:\n        return None\n\n\ndef _summary_via_gcinfo(valobj: lldb.SBValue) -> Optional[str]:\n    try:\n        base = valobj.Dereference() if valobj.TypeIsPointerType() else valobj\n        if not base or not base.IsValid():\n            return None\n        cls = base.GetChildMemberWithName(\"$class\")\n        if cls and cls.IsValid():\n            cls_d = cls.Dereference() if cls.TypeIsPointerType() else cls\n            gc = cls_d.GetChildMemberWithName(\"$GCINFO\")\n            if gc and gc.IsValid():\n                gaddr = gc.GetValueAsUnsigned()\n                if gaddr:\n                    process = valobj.GetTarget().GetProcess()\n                    err = lldb.SBError()\n                    gstr = process.ReadCStringFromMemory(gaddr, 256, err)\n                    if (err.Success() or not err.Fail()) and gstr:\n                        label = maybe_demangle(gstr)\n                        ptr = valobj.GetValue() or \"?\"\n                        return f\"<{label} object at {ptr}>\"\n        return None\n    except Exception:\n        return None\n\n\ndef sum_B_value(valobj: lldb.SBValue, _internal_dict) -> Optional[str]:\n    \"\"\"Generic summary for Acton boxed values: use __str__ → fromB_str.\"\"\"\n    # Strings handled by sum_B_str; here we handle everything else\n    try:\n        ty = (valobj.GetTypeName() or \"\").strip()\n        if \"B_str\" in ty:\n            return None\n        # Fast paths for common builtins via their specific __str__\n        ptr = valobj.GetValue() or \"\"\n        if ptr.startswith(\"0x\"):\n            if \"B_int\" in ty:\n                # Try to read small integers directly from limbs for speed/robustness\n                try:\n                    base = valobj.Dereference() if valobj.TypeIsPointerType() else valobj\n                    vfield = base.GetChildMemberWithName(\"val\")\n                    if vfield and vfield.IsValid():\n                        sz = vfield.GetChildMemberWithName(\"size\")\n                        nfield = vfield.GetChildMemberWithName(\"n\")\n                        if sz and sz.IsValid() and nfield and nfield.IsValid():\n                            size = sz.GetValueAsSigned()\n                            naddr = nfield.GetValueAsUnsigned()\n                            if size == 0:\n                                return \"0\"\n                            if abs(size) == 1 and naddr:\n                                process = valobj.GetTarget().GetProcess()\n                                limb_err = lldb.SBError()\n                                limb_bytes = process.ReadMemory(naddr, 8, limb_err)\n                                if (limb_err.Success() or not limb_err.Fail()) and limb_bytes is not None and len(limb_bytes) == 8:\n                                    limb = int.from_bytes(limb_bytes, byteorder='little', signed=False)\n                                    return f\"{-limb if size < 0 else limb}\"\n                except Exception:\n                    pass\n                # Fallback via __str__ helper\n                expr = f\"(char*)fromB_str(B_intD___str__((B_int){ptr}))\"\n                sev = valobj.EvaluateExpression(expr, _expr_opts())\n                s = _read_cstring(valobj, sev)\n                if s is not None:\n                    return s\n            elif \"B_i64\" in ty:\n                expr = f\"(char*)fromB_str(B_i64D___str__((B_i64){ptr}))\"\n                sev = valobj.EvaluateExpression(expr, _expr_opts())\n                s = _read_cstring(valobj, sev)\n                if s is not None:\n                    return s\n            elif \"B_i32\" in ty:\n                expr = f\"(char*)fromB_str(B_i32D___str__((B_i32){ptr}))\"\n                sev = valobj.EvaluateExpression(expr, _expr_opts())\n                s = _read_cstring(valobj, sev)\n                if s is not None:\n                    return s\n            elif \"B_i16\" in ty:\n                expr = f\"(char*)fromB_str(B_i16D___str__((B_i16){ptr}))\"\n                sev = valobj.EvaluateExpression(expr, _expr_opts())\n                s = _read_cstring(valobj, sev)\n                if s is not None:\n                    return s\n            elif \"B_u64\" in ty:\n                expr = f\"(char*)fromB_str(B_u64D___str__((B_u64){ptr}))\"\n                sev = valobj.EvaluateExpression(expr, _expr_opts())\n                s = _read_cstring(valobj, sev)\n                if s is not None:\n                    return s\n            elif \"B_u32\" in ty:\n                expr = f\"(char*)fromB_str(B_u32D___str__((B_u32){ptr}))\"\n                sev = valobj.EvaluateExpression(expr, _expr_opts())\n                s = _read_cstring(valobj, sev)\n                if s is not None:\n                    return s\n            elif \"B_u16\" in ty:\n                expr = f\"(char*)fromB_str(B_u16D___str__((B_u16){ptr}))\"\n                sev = valobj.EvaluateExpression(expr, _expr_opts())\n                s = _read_cstring(valobj, sev)\n                if s is not None:\n                    return s\n            elif \"B_float\" in ty:\n                expr = f\"(char*)fromB_str(B_floatD___str__((B_float){ptr}))\"\n                sev = valobj.EvaluateExpression(expr, _expr_opts())\n                s = _read_cstring(valobj, sev)\n                if s is not None:\n                    return s\n            elif \"B_bool\" in ty:\n                # fromB_bool -> C int, but we keep unified path via __str__ to get \"True\"/\"False\"\n                expr = f\"(char*)fromB_str(B_boolD___str__((B_bool){ptr}))\"\n                sev = valobj.EvaluateExpression(expr, _expr_opts())\n                s = _read_cstring(valobj, sev)\n                if s is not None:\n                    return s\n        # Generic: try dynamic __str__ (may fail with unusual toolchains)\n        s = _summary_via___str__(valobj)\n        if s is not None:\n            return s\n        return _summary_via_gcinfo(valobj)\n    except Exception:\n        return None\n\n\ndef sum_user_value(valobj: lldb.SBValue, _internal_dict) -> Optional[str]:\n    \"\"\"Summary for user objects (e.g., stackdemoQ_main): use __str__ fallback.\"\"\"\n    try:\n        s = _summary_via___str__(valobj)\n        if s is not None:\n            return s\n        return _summary_via_gcinfo(valobj)\n    except Exception:\n        return None\n\n\ndef _register_formatters() -> None:\n    \"\"\"Register LLDB Python type summaries so `frame variable` and DAP show Acton values.\"\"\"\n    if os.getenv(\"ACTON_LLDB_NO_FORMATTERS\"):\n        return\n    dbg = lldb.debugger\n    # Define category (no enable yet to avoid 'empty category enabled' warning)\n    dbg.HandleCommand(\"type category define Acton\")\n    # Add summaries into the Acton category\n    dbg.HandleCommand(f\"type summary add -w Acton -F {__name__}.sum_B_str B_str\")\n    dbg.HandleCommand(f\"type summary add -w Acton -x -F {__name__}.sum_B_value '^B_.*$'\")\n    dbg.HandleCommand(f\"type summary add -w Acton -x -F {__name__}.sum_user_value '^[A-Za-z_][A-Za-z0-9_]*Q_.*$'\")\n    # Many Acton locals show as $WORD/WORD (generic value). Provide a generic summary for those.\n    dbg.HandleCommand(f\"type summary add -w Acton -F {__name__}.sum_WORD '$WORD'\")\n    dbg.HandleCommand(f\"type summary add -w Acton -F {__name__}.sum_WORD 'WORD'\")\n    dbg.HandleCommand(\"type category enable Acton\")\n    # Also install essential summaries in the default category so DAP shows them even if Acton is disabled\n    dbg.HandleCommand(f\"type summary add -F {__name__}.sum_B_str B_str\")\n    dbg.HandleCommand(f\"type summary add -x -F {__name__}.sum_B_value '^B_.*$'\")\n    dbg.HandleCommand(f\"type summary add -F {__name__}.sum_WORD '$WORD'\")\n    dbg.HandleCommand(f\"type summary add -F {__name__}.sum_WORD 'WORD'\")\n\n\ndef sum_WORD(valobj: lldb.SBValue, _internal_dict) -> Optional[str]:\n    \"\"\"Summary for generic Acton value type ($WORD/WORD) — treat as B_value pointer.\"\"\"\n    # TODO: we should be able to do better by following $class pointer and figuring out actual type\n    try:\n        s = _summary_via___str__(valobj)\n        if s:\n            return s\n        return _summary_via_gcinfo(valobj) or \"\"\n    except Exception:\n        return \"\"\n\n\n# ------------------------------\n# Small helpers\n# ------------------------------\n\ndef cmd_root(debugger: lldb.SBDebugger, command: str, exe_ctx: lldb.SBExecutionContext, result: lldb.SBCommandReturnObject, _internal_dict=None) -> None:\n    \"\"\"Acton command group.\n\n    Usage:\n      acton bt [options]\n      acton locals [options]\n      acton demangle [name]\n    \"\"\"\n    args = shlex_split(command)\n    if not args:\n        result.PutCString(cmd_root.__doc__ or \"\")\n        return\n    sub = args[0]\n    rest = \" \".join(args[1:])\n    if sub in (\"bt\",):\n        return cmd_bt(debugger, rest, exe_ctx, result)\n    if sub in (\"locals\",):\n        return cmd_locals(debugger, rest, exe_ctx, result)\n    if sub in (\"demangle\",):\n        return cmd_demangle(debugger, rest, exe_ctx, result)\n    if sub in (\"bp\", \"break\"):\n        return cmd_break(debugger, rest, exe_ctx, result)\n    result.PutCString(f\"Unknown subcommand '{sub}'. Try: bt, locals, demangle\")\n\ndef shlex_split(s: str) -> List[str]:\n    \"\"\"A minimal shlex split that tolerates LLDB inputs without importing shlex eagerly.\"\"\"\n    try:\n        import shlex\n\n        return shlex.split(s)\n    except Exception:\n        return s.split()\n\n# ------------------------------\n# Color helpers\n# ------------------------------\n\ndef _c(code: str, s: str) -> str:\n    if not CFG.enable_color:\n        return s\n    return f\"\\x1b[{code}m{s}\\x1b[0m\"\n\ndef _fmt_file_line(filename: str, line: int) -> str:\n    # Match LLDB bt-ish style: file in cyan/teal, line in yellow\n    return f\"{_c('36', filename)}:{_c('33', str(line))}\"\n\ndef _format_args(frame: lldb.SBFrame) -> str:\n    try:\n        args = frame.GetVariables(True,  # arguments\n                                  False, # locals\n                                  False, # statics\n                                  True)  # in_scope_only\n    except Exception:\n        return \"()\"\n\n    items: List[str] = []\n    for v in args:\n        try:\n            name = v.GetName() or \"?\"\n            if name == \"C_cont\":\n                continue\n            dname = demangle_acton(name)\n            if CFG.show_arg_values:\n                pretty = _acton_value_summary(v, lldb.SBExecutionContext(frame))\n                if pretty is not None:\n                    val = pretty\n                else:\n                    val = v.GetSummary() or v.GetValue()\n                if val is None:\n                    items.append(dname)\n                else:\n                    sval = str(val).strip()\n                    # keep brief; avoid long blobs/newlines\n                    if \"\\n\" in sval:\n                        sval = sval.split(\"\\n\", 1)[0] + \" …\"\n                    if len(sval) > 120:\n                        sval = sval[:117] + \"…\"\n                    items.append(f\"{dname}={sval}\")\n            else:\n                items.append(dname)\n        except Exception:\n            continue\n    return \"(\" + \", \".join(items) + \")\"\n\ndef _acton_value_summary(val: lldb.SBValue, exe_ctx: lldb.SBExecutionContext) -> Optional[str]:\n    try:\n        raw_name = val.GetName() or \"\"\n        # Unboxed values start with 'U' — skip boxed pretty-print\n        if raw_name.startswith(\"U\"):\n            return None\n        # Need a pointer value to the boxed object\n        ptr = val.GetValue() or \"\"\n        if not ptr.startswith(\"0x\"):\n            return None\n        frame = exe_ctx.GetFrame() if hasattr(exe_ctx, \"GetFrame\") else None\n        if not frame or not frame.IsValid():\n            return None\n        tyname = val.GetTypeName() or \"\"\n        process = frame.GetThread().GetProcess()\n\n        # Generic __str__ path early for non-strings: this covers actors/classes/self and\n        # most builtins (ints, floats, bools) uniformly. We keep a dedicated fast path\n        # for B_str below so strings still get quoted.\n        if \"B_str\" not in tyname:\n            try:\n                opts0 = lldb.SBExpressionOptions()\n                opts0.SetIgnoreBreakpoints(True)\n                opts0.SetUnwindOnError(True)\n                opts0.SetLanguage(lldb.eLanguageTypeC)\n                sev0 = frame.EvaluateExpression(f\"(B_str)B_valueD___str__((B_value){ptr})\", opts0)\n                if sev0 and sev0.IsValid() and (not sev0.GetError() or not sev0.GetError().Fail()):\n                    s_base0 = sev0.Dereference() if sev0.TypeIsPointerType() else sev0\n                    nb0 = s_base0.GetChildMemberWithName(\"nbytes\")\n                    sp0 = s_base0.GetChildMemberWithName(\"str\")\n                    if nb0 and nb0.IsValid() and sp0 and sp0.IsValid():\n                        nbytes0 = nb0.GetValueAsUnsigned()\n                        addr0 = sp0.GetValueAsUnsigned()\n                        if nbytes0 and addr0:\n                            err0 = lldb.SBError()\n                            data0 = process.ReadMemory(addr0, int(nbytes0), err0)\n                            if (err0.Success() or not err0.Fail()) and data0 is not None:\n                                try:\n                                    return data0.decode('utf-8', errors='replace')\n                                except Exception:\n                                    pass\n            except Exception:\n                pass\n        # Integers (boxed) — extract underlying value via from$*/fromB_*\n        int_expr = None\n        if \"B_int\" in tyname:\n            # Get B_str via B_int.__str__ and read bytes\n            opts = lldb.SBExpressionOptions()\n            opts.SetIgnoreBreakpoints(True)\n            opts.SetUnwindOnError(True)\n            opts.SetLanguage(lldb.eLanguageTypeC)\n            sev = frame.EvaluateExpression(f\"(B_str)B_intD___str__((B_int){ptr})\", opts)\n            if sev and sev.IsValid() and (not sev.GetError() or not sev.GetError().Fail()):\n                s_base = sev.Dereference() if sev.TypeIsPointerType() else sev\n                nb = s_base.GetChildMemberWithName(\"nbytes\")\n                sp = s_base.GetChildMemberWithName(\"str\")\n                if nb and nb.IsValid() and sp and sp.IsValid():\n                    nbytes = nb.GetValueAsUnsigned()\n                    addr = sp.GetValueAsUnsigned()\n                    if nbytes and addr:\n                        errn = lldb.SBError()\n                        data = process.ReadMemory(addr, int(nbytes), errn)\n                        if (errn.Success() or not errn.Fail()) and data is not None:\n                            try:\n                                return data.decode('utf-8', errors='replace')\n                            except Exception:\n                                pass\n            # Field-based quick path for small ints\n            base = val.Dereference() if val.TypeIsPointerType() else val\n            if base and base.IsValid():\n                vfield = base.GetChildMemberWithName(\"val\")\n                if vfield and vfield.IsValid():\n                    sz = vfield.GetChildMemberWithName(\"size\")\n                    nfield = vfield.GetChildMemberWithName(\"n\")\n                    if sz and sz.IsValid() and nfield and nfield.IsValid():\n                        size = sz.GetValueAsSigned()\n                        naddr = nfield.GetValueAsUnsigned()\n                        if size == 0:\n                            return \"0\"\n                        if abs(size) == 1 and naddr:\n                            limb_err = lldb.SBError()\n                            limb_bytes = process.ReadMemory(naddr, 8, limb_err)\n                            if (limb_err.Success() or not limb_err.Fail()) and limb_bytes is not None and len(limb_bytes) == 8:\n                                limb = int.from_bytes(limb_bytes, byteorder='little', signed=False)\n                                if size < 0:\n                                    return f\"-{limb}\"\n                                else:\n                                    return str(limb)\n            # Fallback: try to get numeric value if available (may fail due to '$' in name)\n            int_expr = f\"from$int((B_int){ptr})\"\n        elif \"B_i64\" in tyname:\n            int_expr = f\"fromB_i64((B_i64){ptr})\"\n        elif \"B_i32\" in tyname:\n            int_expr = f\"fromB_i32((B_i32){ptr})\"\n        elif \"B_i16\" in tyname:\n            int_expr = f\"fromB_i16((B_i16){ptr})\"\n        elif \"B_u64\" in tyname:\n            int_expr = f\"fromB_u64((B_u64){ptr})\"\n        elif \"B_u32\" in tyname:\n            int_expr = f\"fromB_u32((B_u32){ptr})\"\n        elif \"B_u16\" in tyname:\n            int_expr = f\"fromB_u16((B_u16){ptr})\"\n        if int_expr is not None:\n            opts = lldb.SBExpressionOptions()\n            opts.SetIgnoreBreakpoints(True)\n            opts.SetUnwindOnError(True)\n            opts.SetLanguage(lldb.eLanguageTypeC)\n            iev = frame.EvaluateExpression(int_expr, opts)\n            if iev and iev.IsValid() and (not iev.GetError() or not iev.GetError().Fail()):\n                ival = iev.GetValue()\n                if ival is not None:\n                    return str(ival)\n            # if failed, fall through\n\n        # Booleans\n        if \"B_bool\" in tyname:\n            opts = lldb.SBExpressionOptions()\n            opts.SetIgnoreBreakpoints(True)\n            opts.SetUnwindOnError(True)\n            opts.SetLanguage(lldb.eLanguageTypeC)\n            bev = frame.EvaluateExpression(f\"fromB_bool((B_bool){ptr})\", opts)\n            if bev and bev.IsValid() and (not bev.GetError() or not bev.GetError().Fail()):\n                bval = bev.GetValueAsUnsigned()\n                return \"True\" if bval else \"False\"\n\n        # Floats\n        if \"B_float\" in tyname:\n            opts = lldb.SBExpressionOptions()\n            opts.SetIgnoreBreakpoints(True)\n            opts.SetUnwindOnError(True)\n            opts.SetLanguage(lldb.eLanguageTypeC)\n            fev = frame.EvaluateExpression(f\"fromB_float((B_float){ptr})\", opts)\n            if fev and fev.IsValid() and (not fev.GetError() or not fev.GetError().Fail()):\n                fval = fev.GetValue()\n                if fval is not None:\n                    return str(fval)\n\n        # Special-case B_str: read bytes directly to avoid null-termination issues\n        if \"B_str\" in tyname:\n            base = val.Dereference() if val.TypeIsPointerType() else val\n            if not base or not base.IsValid():\n                return None\n            nb = base.GetChildMemberWithName(\"nbytes\")\n            sp = base.GetChildMemberWithName(\"str\")\n            if nb and nb.IsValid() and sp and sp.IsValid():\n                nbytes = nb.GetValueAsUnsigned()\n                addr = sp.GetValueAsUnsigned()\n                if nbytes and addr:\n                    err = lldb.SBError()\n                    data = process.ReadMemory(addr, int(nbytes), err)\n                    if err.Success() and data is not None:\n                        try:\n                            s = data.decode('utf-8', errors='replace')\n                            # Quote string values for clarity\n                            s = s.replace('\\\\', r'\\\\').replace('\"', r'\\\"')\n                            return f'\"{s}\"'\n                        except Exception:\n                            return None\n            # Fall through to generic path if direct read fails\n        # Generic path: get char* from __str__ quickly and read C-string\n        cexpr = f\"(char*)fromB_str(B_valueD___str__((B_value){ptr}))\"\n        opts = lldb.SBExpressionOptions()\n        opts.SetIgnoreBreakpoints(True)\n        opts.SetUnwindOnError(True)\n        # C works, and the target is compiled as C; allow summary providers\n        opts.SetLanguage(lldb.eLanguageTypeC)\n        cev = frame.EvaluateExpression(cexpr, opts)\n        if cev and cev.IsValid():\n            caddr = cev.GetValueAsUnsigned()\n            if caddr:\n                e3 = lldb.SBError()\n                cstr = process.ReadCStringFromMemory(caddr, 512, e3)\n                if (e3.Success() or not e3.Fail()) and cstr is not None:\n                    return cstr\n\n        # Last-resort fallback for objects (actors/classes): use $class->$GCINFO\n        try:\n            base = val.Dereference() if val.TypeIsPointerType() else val\n            if base and base.IsValid():\n                cls = base.GetChildMemberWithName(\"$class\")\n                if cls and cls.IsValid():\n                    cls_d = cls.Dereference() if cls.TypeIsPointerType() else cls\n                    gc = cls_d.GetChildMemberWithName(\"$GCINFO\")\n                    if gc and gc.IsValid():\n                        gaddr = gc.GetValueAsUnsigned()\n                        if gaddr:\n                            gerr = lldb.SBError()\n                            gstr = process.ReadCStringFromMemory(gaddr, 256, gerr)\n                            if (gerr.Success() or not gerr.Fail()) and gstr:\n                                label = maybe_demangle(gstr)\n                                return f\"<{label} object at {ptr}>\"\n        except Exception:\n            pass\n        return None\n    except Exception:\n        return None\n\n\ndef cmd_break(debugger: lldb.SBDebugger, command: str, exe_ctx: lldb.SBExecutionContext, result: lldb.SBCommandReturnObject, _internal_dict=None) -> None:\n    \"\"\"acton.break: Set a breakpoint at Acton file:line\n\n    Usage:\n      acton break test.act:37\n      acton break test.act 37\n\n    Notes:\n    - Requires DWARF with Acton file paths (acton --debug recommended)\n    - If it resolves to 0 locations, you may need a source-map.\n    \"\"\"\n    s = command.strip()\n    if not s:\n        result.PutCString(cmd_break.__doc__ or \"\")\n        result.SetStatus(lldb.eReturnStatusFailed)\n        return\n\n    file = None\n    line = None\n    if \":\" in s and not s.startswith(\":\"):\n        file, _, rest = s.partition(\":\")\n        try:\n            line = int(rest.strip())\n        except Exception:\n            pass\n    else:\n        parts = shlex_split(s)\n        if len(parts) == 2:\n            file, line_s = parts\n            try:\n                line = int(line_s)\n            except Exception:\n                line = None\n\n    if not file or not line:\n        result.PutCString(\"Usage: acton break <file.act>:<line> or acton break <file.act> <line>\")\n        result.SetStatus(lldb.eReturnStatusFailed)\n        return\n\n    target = debugger.GetSelectedTarget()\n    if not target or not target.IsValid():\n        result.PutCString(\"No target. Create or run a target first.\")\n        result.SetStatus(lldb.eReturnStatusFailed)\n        return\n\n    # Try to set breakpoint by file:line\n    fs = lldb.SBFileSpec()\n    fs.SetFilename(os.path.basename(file))\n    # If a directory was included, set it as well\n    dname = os.path.dirname(file)\n    if dname:\n        fs.SetDirectory(dname)\n    bp = target.BreakpointCreateByLocation(fs, int(line))\n\n    if bp and bp.IsValid() and bp.GetNumLocations() > 0:\n        result.PutCString(f\"Breakpoint {bp.GetID()}: {bp.GetNumLocations()} locations at {file}:{line}\")\n        return\n\n    # Fallback: try matching compile units with same basename to hint source-map\n    hinted = False\n    from_dirs = set()\n    for mod in target.module_iter():\n        for i in range(mod.GetNumCompileUnits()):\n            cu = mod.GetCompileUnitAtIndex(i)\n            cu_fs = cu.GetFileSpec()\n            if cu_fs and cu_fs.IsValid() and cu_fs.GetFilename() == os.path.basename(file):\n                from_dirs.add(cu_fs.GetDirectory())\n                hinted = True\n    if hinted and from_dirs:\n        for src_dir in sorted(from_dirs):\n            result.PutCString(\n                f\"Hint: DWARF references '{os.path.basename(file)}' under '{src_dir}'. If your sources live elsewhere, use:\\n\"\n                f\"  settings set target.source-map {src_dir} <your-project-root>\"\n            )\n\n    result.PutCString(f\"No locations resolved for {file}:{line}. Ensure the binary has debug info (acton --debug) and source-map is correct.\")\n    result.SetStatus(lldb.eReturnStatusFailed)\n"
  },
  {
    "path": "utils/update-changelog.sh",
    "content": "#!/usr/bin/env bash\n\nclaude --dangerously-skip-permissions 'Update CHANGELOG.md based on the git log. Review git commits from the latest versioned release git tag and make sure they are covered by an entry in the changelog. If it is not covered, check `git log -U` for the particular commit in order to understand what was done and why, then write an entry for CHANGELOG.md. Use the keepachangelog.com format. Keep the same tone and style already used in CHANGELOG.md - we want a brief, concice, technical no-nonsense tone. It is OK to intermingle examples - this is appreciated by users who can immediately understand the effects of a change'\n"
  },
  {
    "path": "version.mk",
    "content": "VERSION=0.27.0\n"
  },
  {
    "path": "workspace/MRO.hs",
    "content": "-- Copyright (C) 2019-2021 Data Ductus AB\n--\n-- Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:\n--\n-- 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.\n--\n-- 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.\n--\n-- 3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission.\n--\n-- THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS \"AS IS\" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n--\n\nmodule MRO where\n\ntype Name                       = String\ntype Bases                      = [Name]\ntype ClassDef                   = (Name,Bases)\ntype Graph                      = [ClassDef]\n\ntype WName                      = ([Maybe Name],Name)\ntype WBases                     = [WName]\ntype WClassDef                  = (Name,WBases)\ntype WGraph                     = [WClassDef]\n\n\n\n-- With witnesses:\n\nmro                             :: Graph -> IO ()\nmro graph                       = do mapM (putStrLn . uncurry showclass) graph\n                                     putStrLn \"----\"\n                                     mro' [] graph\n\nmro'                            :: WGraph -> Graph -> IO ()\nmro' lins []                    = return ()\nmro' lins ((c,bases):graph)     = case merge [] (map lin wbases ++ [wbases]) of\n                                    Right cs -> do\n                                        putStrLn (showlin c cs)\n                                        mro' ((c,cs):lins) graph\n                                    Left err -> putStrLn err\n  where\n    wbases                      = case bases of [] -> []; n:ns -> ([Nothing],n) : [ ([Just n],n) | n <- ns ]\n    \n    lin                         :: WName -> WBases\n    lin (is,n)                  = case lookup n lins of\n                                    Just la -> (is,n) : [ (is++w,x) | (w,x) <- la ]\n                                    Nothing -> error (\"Forward ref from \" ++ c ++ \" to \" ++ n)\n\n    merge                       :: WBases -> [WBases] -> Either String WBases\n    merge out lists\n      | null heads              = Right $ reverse out\n      | h:_ <- good             = merge (h:out) [ if snd hd == snd h then tl else hd:tl | (hd,tl) <- zip heads tails ]\n      | otherwise               = Left (\">>>>>> \" ++ showlin c (reverse out) ++ \n                                        \" ++ merge(\" ++ commasep id (map showlist lists) ++ \") <<<<<<<\")\n      where (heads,tails)       = unzip [ (hd,tl) | hd:tl <- lists ]\n            good                = [ h | h <- heads, all (snd h `notElem`) (map (map snd) tails) ]\n\nshowlin                         :: Name -> WBases -> String\nshowlin c cs                    = \"L(\" ++ c ++ \") = \" ++ showlist cs\n\nshowlist cs                     = \"[\" ++ commasep wshow cs ++ \"]\"\n\nwshow (w,x)                     = wsh w ++ \": \" ++ x\n  where wsh []                  = \"\"\n        wsh [n]                 = wsh' n\n        wsh (n:w)               = wsh' n ++ \".\" ++ wsh w\n        wsh' Nothing            = \"_\"\n        wsh' (Just n)           = n\n\ncommasep f []                   = \"\"\ncommasep f [x]                  = f x\ncommasep f (x:xs)               = f x ++ \", \" ++ commasep f xs\n\nshowclass c bases               = c ++ \"(\" ++ commasep id bases ++ \")\"\n\n\n-- Alternative formulation:\n\ntype Env                        = [WClassDef]\n\nlinearize                       :: Env -> ClassDef -> WClassDef\nlinearize env (c,bases)         = (c, merge [] $ map lin wbases ++ [wbases])\n  where \n    wbases                      = case bases of [] -> []; n:ns -> ([Nothing],n) : [ ([Just n],n) | n <- ns ]\n\n    lin                         :: WName -> [WName]\n    lin (w,a)                   = (w,a) : [ (w++w',x) | (w',x) <- la ]\n      where Just la             = lookup a env\n\n    merge                       :: [WName] -> [[WName]] -> [WName]\n    merge out lists\n      | null heads              = reverse out\n      | h:_ <- good             = merge (h:out) [ if equal hd h then tl else hd:tl | (hd,tl) <- zip heads tails ]\n      | otherwise               = error (\">>>>>> \" ++ showlin c (reverse out) ++ \n                                         \" ++ merge(\" ++ commasep id (map showlist lists) ++ \") <<<<<<<\")\n      where (heads,tails)       = unzip [ (hd,tl) | hd:tl <- lists ]\n            good                = [ h | h <- heads, all (absent h) tails ]\n    \n    equal                       :: WName -> WName -> Bool\n    equal (_,a) (_,b)           = a == b\n    \n    absent                      :: WName -> [WName] -> Bool\n    absent (_,h) tl             = h `notElem` map snd tl\n\nmro2                            :: Env -> Graph -> IO ()\nmro2 env []                     = mapM (putStrLn . uncurry showlin) (reverse env) >> return ()\nmro2 env (g:graph)              = mro2 (lmap:env) graph\n  where lmap                    = linearize env g\n\n\n\n-- Examples from https://www.python.org/download/releases/2.3/mro/\n\nex0 = [(\"O\",[]), (\"X\",[\"O\"]), (\"Y\",[\"O\"]), (\"A\",[\"X\",\"Y\"]), (\"B\",[\"Y\",\"X\"]), (\"C\",[\"A\",\"B\"])]               -- fails\n\nex1 = [(\"O\",[]), (\"F\",[\"O\"]), (\"E\",[\"O\"]), (\"D\",[\"O\"]), (\"C\",[\"D\",\"F\"]), (\"B\",[\"D\",\"E\"]), (\"A\",[\"B\",\"C\"])]  -- ok\n\nex2 = [(\"O\",[]), (\"F\",[\"O\"]), (\"E\",[\"O\"]), (\"D\",[\"O\"]), (\"C\",[\"D\",\"F\"]), (\"B\",[\"E\",\"D\"]), (\"A\",[\"B\",\"C\"])]  -- ok\n\nex3 = ex0                                                               -- fails\n\nex4 = [(\"O\",[]), (\"F\",[\"O\"]), (\"E\",[\"F\"]), (\"G\",[\"F\",\"E\"])]             -- fails\n\nex5 = [(\"O\",[]), (\"F\",[\"O\"]), (\"E\",[\"F\"]), (\"G\",[\"E\",\"F\"])]             -- ok\n\nex6 = [(\"O\",[]), (\"A\",[\"O\"]), (\"C\",[\"A\",\"A\"])]                          -- fails\n\nex7 = [(\"O\",[]), (\"A\",[\"O\"]), (\"B\",[\"O\"]), (\"C\",[\"O\"]), (\"D\",[\"O\"]), (\"E\",[\"O\"]), \n       (\"K1\",[\"A\",\"B\",\"C\"]), (\"K2\",[\"D\",\"B\",\"E\"]), (\"K3\",[\"D\",\"A\"]), \n       (\"Z\",[\"K1\",\"K2\",\"K3\"])]                                          -- ok\n\n\n\nex8a = [(\"A\",[]), (\"B\",[]), (\"C\",[]), (\"D\",[]), (\"E\",[]), (\"Z\",[]),\n        (\"K1\",[\"A\",\"B\",\"C\"]), (\"K2\",[\"D\",\"B\",\"E\"]), (\"K3\",[\"D\",\"A\"]), \n        (\"Z1\",[\"Z\",\"K1\"]), (\"Z2\",[\"Z\",\"K2\"]), (\"Z3\",[\"Z\",\"K3\"]),\n        (\"Z_tot\",[\"Z3\",\"Z2\",\"Z1\"])]                                     -- ok\n\nex8b = [(\"A\",[]), (\"B\",[]), (\"C\",[]), (\"D\",[]), (\"E\",[]), (\"Z\",[]),\n        (\"K1\",[\"A\",\"B\",\"C\"]), (\"K2\",[\"D\",\"B\",\"E\"]), (\"K3\",[\"D\",\"A\"]), \n        (\"Z1\",[\"Z\",\"K1\",\"K2\"]), (\"Z2\",[\"Z\",\"K3\"]),\n        (\"Z_tot\",[\"Z2\",\"Z1\"])]                                          -- fails\n\nex8c = [(\"A\",[]), (\"B\",[]), (\"C\",[]), (\"D\",[]), (\"E\",[]), (\"Z\",[]),\n        (\"K1\",[\"A\",\"B\",\"C\"]), (\"K2\",[\"D\",\"B\",\"E\"]), (\"K3\",[\"D\",\"A\"]), \n        (\"Z1\",[\"Z\",\"K1\",\"K3\"]), (\"Z2\",[\"Z\",\"K2\"]),\n        (\"Z_tot\",[\"Z2\",\"Z1\"])]                                          -- ok\n\nex8d = [(\"A\",[]), (\"B\",[]), (\"C\",[]), (\"D\",[]), (\"E\",[]), (\"Z\",[]),\n        (\"K1\",[\"A\",\"B\",\"C\"]), (\"K2\",[\"D\",\"B\",\"E\"]), (\"K3\",[\"D\",\"A\"]), \n        (\"Z1\",[\"Z\",\"K2\",\"K3\"]), (\"Z2\",[\"Z\",\"K1\"]), \n        (\"Z_tot\",[\"Z1\",\"Z2\"])]                                          -- fails\n\nex8e = [(\"A\",[]), (\"B\",[]), (\"C\",[]), (\"D\",[]), (\"E\",[]), (\"Z\",[]),\n        (\"K1\",[\"A\",\"B\",\"C\"]), (\"K2\",[\"D\",\"B\",\"E\"]), (\"K3\",[\"D\",\"A\"]), \n        (\"Z1\",[\"Z\",\"K1\"]), (\"Z2\",[\"Z\",\"K2\",\"K3\"]),\n        (\"Z_tot\",[\"Z2\",\"Z1\"])]                                          -- fails\n\nex8f = [(\"A\",[]), (\"B\",[]), (\"C\",[]), (\"D\",[]), (\"E\",[]), (\"Z\",[]),\n        (\"K1\",[\"A\",\"B\",\"C\"]), (\"K2\",[\"D\",\"B\",\"E\"]), (\"K3\",[\"D\",\"A\"]), \n        (\"Z1\",[\"Z\",\"K2\"]), (\"Z2\",[\"Z\",\"K1\",\"K3\"]),\n        (\"Z_tot\",[\"Z2\",\"Z1\"])]                                          -- ok\n\nex8g = [(\"A\",[]), (\"B\",[]), (\"C\",[]), (\"D\",[]), (\"E\",[]), (\"Z\",[]),\n        (\"K1\",[\"A\",\"B\",\"C\"]), (\"K2\",[\"D\",\"B\",\"E\"]), (\"K3\",[\"D\",\"A\"]), \n        (\"Z1\",[\"Z\",\"K3\"]), (\"Z2\",[\"Z\",\"K1\",\"K2\"]),\n        (\"Z_tot\",[\"Z2\",\"Z1\"])]                                          -- fails\n\n\nex8h = [(\"A\",[]), (\"B\",[]), (\"C\",[]), (\"D\",[]), (\"E\",[]), \n        (\"K1\",[\"A\",\"B\",\"C\"]), (\"K2\",[\"D\",\"B\",\"E\"]), (\"K3\",[\"D\",\"A\"]), \n        (\"Z1\",[\"K1\"]), (\"Z2\",[\"Z1\",\"K2\"]), (\"Z3\",[\"Z2\",\"K3\"])]          -- fails\n\nex8i = [(\"A\",[]), (\"B\",[]), (\"C\",[]), (\"D\",[]), (\"E\",[]), \n        (\"K1\",[\"A\",\"B\",\"C\"]), (\"K2\",[\"D\",\"B\",\"E\"]), (\"K3\",[\"D\",\"A\"]), \n        (\"Z1\",[\"K1\"]), (\"Z2\",[\"Z1\",\"K3\"]), (\"Z3\",[\"Z2\",\"K2\"])]          -- ok\n\nex8j = [(\"A\",[]), (\"B\",[]), (\"C\",[]), (\"D\",[]), (\"E\",[]), \n        (\"K1\",[\"A\",\"B\",\"C\"]), (\"K2\",[\"D\",\"B\",\"E\"]), (\"K3\",[\"D\",\"A\"]), \n        (\"Z1\",[\"K1\"]), (\"Z2\",[\"Z1\",\"K2\",\"K3\"])]                         -- ok\n\nex8k = [(\"A\",[]), (\"B\",[]), (\"C\",[]), (\"D\",[]), (\"E\",[]), \n        (\"K1\",[\"A\",\"B\",\"C\"]), (\"K2\",[\"D\",\"B\",\"E\"]), (\"K3\",[\"D\",\"A\"]), \n        (\"Z1\",[\"K3\"]), (\"Z2\",[\"Z1\",\"K2\"]), (\"Z3\",[\"Z2\",\"K1\"])]          -- ok\n\nex8l = [(\"A\",[]), (\"B\",[]), (\"C\",[]), (\"D\",[]), (\"E\",[]), \n        (\"K1\",[\"A\",\"B\",\"C\"]), (\"K2\",[\"D\",\"B\",\"E\"]), (\"K3\",[\"D\",\"A\"]), \n        (\"Z1\",[\"K2\",\"K3\"]), (\"Z3\",[\"Z1\",\"K1\"])]                         -- fails\n\nex8m = [(\"A\",[]), (\"B\",[]), (\"C\",[]), (\"D\",[]), (\"E\",[]), \n        (\"K1\",[\"A\",\"B\",\"C\"]), (\"K2\",[\"D\",\"B\",\"E\"]), (\"K3\",[\"D\",\"A\"]), \n        (\"Z1\",[\"K3\"]), (\"Z3\",[\"Z1\",\"K1\",\"K2\"])]                         -- ok\n\n\nex9a = [(\"Eq\",[]), (\"Ord\",[\"Eq\"]),\n        (\"a\",[\"Ord\"])]                              -- ok\n\nex9b = [(\"Eq\",[]), (\"Ord\",[\"Eq\"]),\n        (\"a\",[\"Eq\"]), (\"a1\",[\"Ord\",\"a\"])]           -- ok\n\nex9c = [(\"Eq\",[]), (\"Ord\",[\"Eq\"]),\n        (\"a\",[\"Ord\"]), (\"a1\",[\"Eq\",\"a\"])]           -- fails\n\n\nex10a = [(\"Rational\",[]), (\"Integer\",[\"Rational\"]), (\"tt\",[\"Integer\",\"Rational\"])]      -- ok\n\nex10b = [(\"Rational\",[]), (\"Integer\",[\"Rational\"]), (\"tt\",[\"Rational\",\"Integer\"])]      -- fails\n\n\nex10c = [(\"Rational\",[]), (\"Integer\",[\"Rational\"]), (\"tt\",[]),\n         (\"tt_IntRat\",[\"tt\",\"Integer\",\"Rational\"])]                                     -- ok\n\nex10d = [(\"Rational\",[]), (\"Integer\",[\"Rational\"]), (\"tt\",[]),\n         (\"tt_RatInt\",[\"tt\",\"Rational\",\"Integer\"])]                                     -- fails\n\n\nex10e = [(\"Rational\",[]), (\"Integer\",[\"Rational\"]), (\"tt\",[]),\n        (\"tt_Rational\",[\"tt\",\"Rational\"]), (\"tt_Integer\",[\"tt_Rational\",\"Integer\"])]    -- ok\n\nex10f = [(\"Rational\",[]), (\"Integer\",[\"Rational\"]), (\"tt\",[]),\n         (\"tt_Integer\",[\"tt\",\"Integer\"]), (\"tt_Rational\",[\"tt_Integer\",\"Rational\"])]    -- ok!\n\n\nex10x = [(\"Rational\",[]), (\"Integer\",[\"Rational\"]), (\"tt\",[]),\n         (\"tt_Integer\",[\"tt\",\"Integer\"]), (\"tt_Rational\",[\"tt\",\"Rational\"]),\n         (\"tt_tot\",[\"tt_Integer\",\"tt_Rational\"])]                                       -- ok\n\nex10y = [(\"Rational\",[]), (\"Integer\",[\"Rational\"]), (\"tt\",[]),\n         (\"tt_Integer\",[\"tt\",\"Integer\"]), (\"tt_Rational\",[\"tt\",\"Rational\"]),\n         (\"tt_tot\",[\"tt_Rational\",\"tt_Integer\"])]                                       -- ok\n\n\nex10g = [(\"Rational\",[]), (\"Integer\",[\"Rational\"]), (\"tt\",[\"Rational\"]),\n         (\"tt_Integer\",[\"tt\",\"Integer\"])]                                               -- ok\n\nex10h = [(\"Rational\",[]), (\"Integer\",[\"Rational\"]), (\"tt\",[\"Integer\"]),\n         (\"tt_Rational\",[\"tt\",\"Rational\"])]                                             -- ok!\n\n\nex11  = [(\"Rational\",[]), (\"Integer\",[\"Rational\"]), (\"Eq\",[]), (\"Ord\",[\"Eq\"]),\n         (\"tt\",[]),\n         (\"tt_1\",[\"tt\",\"Integer\",\"Rational\"]), \n         (\"tt_2\",[\"tt\",\"Ord\"]), \n         (\"tt_tot\",[\"tt_2\",\"tt_1\"])]                                                    -- ok\n\n\nex12a = [(\"Eq\",[]), (\"Ord\",[\"Eq\"]), (\"Apa\",[\"Eq\"]), (\"Bepa\",[\"Apa\",\"Ord\"])]             -- Bepa,Apa,Ord,Eq\n\nex12b = [(\"Eq\",[]), (\"Ord\",[\"Eq\"]), (\"Apa\",[\"Eq\"]), (\"Bepa\",[\"Ord\",\"Apa\"])]             -- Bepa,Ord,Apa,Eq\n\n\nex13a = [(\"Eq\",[]), (\"Ord\",[\"Eq\"]), (\"Hmm\",[\"Eq\"]), \n         (\"Apa\",[\"Ord\"]), (\"Bepa\",[\"Apa\",\"Hmm\"])]                                       -- Bepa,Apa,Ord,Hmm,Eq\n\nex13b = [(\"Eq\",[]), (\"Ord\",[\"Eq\"]), (\"Hmm\",[\"Eq\"]), \n         (\"Apa\",[\"Ord\"]), (\"Bepa\",[\"Apa\",\"Hmm\",\"Ord\"])]                                 -- Bepa,Apa,Hmm,Ord,Eq\n\n\nex14a = [(\"Apa\",[]), (\"Bepa\",[\"Apa\"]), (\"Cepa\",[\"Apa\"]), (\"Depa\",[\"Cepa\",\"Bepa\"])]      -- Depa,Cepa,Bepa,Apa\n\nex14b = [(\"Apa\",[]), (\"Bepa\",[\"Apa\"]), (\"Cepa\",[\"Apa\"]), (\"Depa\",[\"Cepa\",\"Bepa\"]),\n         (\"Xtra\",[\"Bepa\"]), (\"Epa\",[\"Depa\",\"Xtra\",\"Bepa\"])]                             -- Epa,Depa,Cepa,Xtra,Bepa,Apa\n\nex14c = [(\"Apa\",[]), (\"Bepa\",[\"Apa\"]), (\"Cepa\",[\"Apa\"]), (\"Depa\",[\"Cepa\",\"Bepa\"]),\n         (\"Xtra\",[\"Apa\"]), (\"Epa\",[\"Depa\",\"Xtra\",\"Cepa\"])]                              -- Epa,Depa,Xtra,Cepa,Bepa,Apa\n\nex15  = [(\"G\",[]), (\"F\",[]), (\"E\",[]),\n         (\"D\",[\"G\",\"F\"]), (\"C\",[\"F\"]), (\"B\",[\"E\",\"F\"]),\n         (\"A\",[\"B\",\"C\",\"D\"])]                                                           -- A,B,E,C,D,G,F\n         \nex16  = [(\"Eq\",[]), (\"Ord\",[\"Eq\"]), (\"Hmm\",[\"Eq\",\"Ord\"])]                               -- fails\n\n\n------------------------------------------------------------------------------------------------------------------------------------------------\n-- Desired extension semantics:\n\nex17a = [(\"A\",[]),                                                                      -- A\n         (\"B\",[\"A\"]),                                                                   -- B, A\n         (\"C\",[\"A\"]),                                                                   -- C, A\n         (\"D\",[\"C\",\"B\"]),                                                               -- D, C, B, A\n         (\"str_D\",[\"D\"])]                                                               -- str_D, D, C, B, A\n\nex17b = [(\"A\",[]),                                                                      -- A\n         (\"B\",[\"A\"]),                                                                   -- B, A\n         (\"C\",[\"A\"]),                                                                   -- C, A\n         (\"str_CB\",[\"C\",\"B\"])]                                                          -- str_CB, C, B, A\n\nex17c = [(\"A\",[]),                                                                      -- A\n         (\"B\",[\"A\"]),                                                                   -- B, A\n         (\"C\",[\"A\"]),                                                                   -- C, A\n         (\"str_A\",[\"A\"]),                                                               -- str_A, A\n         (\"str_B\",[\"str_A\",\"B\"]),                                                       -- str_B, str_A, B, A\n         (\"str_C\",[\"str_B\",\"str_A\",\"C\"])]                                               -- str_C, str_B, str_A, B, C, A\n\nex17d = [(\"A\",[]),                                                                      -- A\n         (\"B\",[\"A\"]),                                                                   -- B, A\n         (\"C\",[\"A\"]),                                                                   -- C, A\n         (\"str_B\",[\"B\"]),                                                               -- str_B, B, A                      <--- implicit A dep\n         (\"str_C\",[\"str_B\",\"C\"])]                                                       -- str_C, str_B, B, C, A\n\nex17e = [(\"A\",[]),                                                                      -- A\n         (\"B\",[\"A\"]),                                                                   -- B, A\n         (\"C\",[\"B\",\"A\"]),                                                               -- C, B, A\n         (\"str_A\",[\"A\"]),                                                               -- str_A, A\n         (\"str_B\",[\"str_A\",\"B\"]),                                                       -- str_B, str_A, B, A\n         (\"str_C\",[\"str_B\",\"str_A\",\"C\"])]                                               -- str_C, str_B, str_A, C, B, A\n\nex17f = [(\"A\",[]),                                                                      -- A\n         (\"B\",[\"A\"]),                                                                   -- B, A\n         (\"C\",[\"B\",\"A\"]),                                                               -- C, B, A\n         (\"str_B\",[\"B\"]),                                                               -- str_B, B, A\n         (\"str_C\",[\"str_B\",\"C\"])]                                                       -- str_C, str_B, C, B, A            <--- implicit A dep\n\n-- Conclusion: a single multi-extension left->right corresponds to *accumulating* extensions top->down.\n-- That is, later extensions cover earlier ones, but protocol methods (the method defaults) only \n-- apply for methods implemented in neither of the extensions.\n-----------------------------------------------------------------------------------------------------------------------------------------------\n\n\nex18  = [(\"A\",[]), (\"B\",[\"A\"]), (\"C\",[\"A\"]), \n         (\"str_A\",[\"A\"]),\n         (\"str_B\",[\"B\"]), \n         (\"str_C\",[\"C\"]), \n         (\"str_tot\",[\"str_C\",\"str_B\",\"str_A\"])]                                        -- str_tot,str_C,C,str_B,B,str_A,A  <--- bad, picks C before str_B...\n         \n\nex20a = [(\"A\",[]), (\"B\",[\"A\"]), (\"C\",[\"A\"]), (\"D\",[\"B\",\"C\"])]\n\nex20b = [(\"A\",[]), (\"B\",[\"A\"]), (\"C\",[\"A\"]), (\"D\",[\"B\",\"C\"]), (\"E\",[\"D\"])]\n\nex20c = [(\"A\",[]), (\"B\",[\"A\"]), (\"C\",[\"A\"]), (\"D\",[\"B\",\"C\"]), (\"E\",[]), (\"F\",[\"D\",\"E\"])]\n\n\n---------------\n\nex21a = [(\"Eq\",[]), (\"Ord\",[\"Eq\"]),\n         (\"Eq$set\",[\"Eq\"]), \n         (\"Ord$set\",[\"Ord\",\"Eq$set\"])]\n\nex21b = [(\"Eq\",[]), (\"Ord\",[\"Eq\"]),\n         (\"Eq$set\",[\"Eq\"]), \n         (\"Ord$set\",[\"Eq$set\",\"Ord\"])]\n\nex21c = [(\"Eq\",[]), (\"Ord\",[\"Eq\"]), (\"Container\",[]), (\"Set\",[\"Container\",\"Ord\"]),\n         (\"Eq$set\",[\"Eq\"]), \n         (\"Ord$set\",[\"Ord\",\"Eq$set\"]),\n         (\"Set$set\",[\"Set\",\"Ord$set\"])]\n\nex21d = [(\"Eq\",[]), (\"Ord\",[\"Eq\"]), (\"Container\",[]), (\"Set\",[\"Container\",\"Ord\"]),\n         (\"Eq$set\",[\"Eq\"]), \n         (\"Ord$set\",[\"Eq$set\",\"Ord\"]),\n         (\"Set$set\",[\"Ord$set\",\"Set\"])]\n\nex21e = [(\"Eq\",[]), (\"Ord\",[\"Eq\"]), (\"Container\",[]), (\"Set\",[\"Container\",\"Ord\"]),\n         (\"Ord$set\",[\"Ord\"]),\n         (\"Ord$set$2\",[\"Ord$set\",\"Ord\"])]                                               -- Succeeds... Acceptable? Or detect by a separate check?\n\nex22  = [(\"Eq\",[]), (\"Ord\",[\"Eq\"]), (\"Plus\",[]), (\"Minus\",[]), (\"Logical\",[]),\n         (\"Complex\",[\"Ord\",\"Plus\",\"Minus\"]),\n         (\"Real\",[\"Complex\"]), (\"Rational\",[\"Real\"]),\n         (\"Integral\",[\"Rational\",\"Logical\"])]                                           -- Rational,Real,Complex,Ord,Eq,Plus,Minus,Logical\n\n\n--   Indexed         Iterable\n--    |               |\n--    |               |\n--   Sliceable       Collection      Plus\n--    |               |               |\n--    |               |               |\n--   Sequence <-------- <--------------\n--    |\n--    |\n--   Sequence$list\n\nex23  = [(\"Plus\",[]), (\"Indexed\",[]), (\"Iterable\",[]),\n         (\"Sliceable\",[\"Indexed\"]), (\"Collection\",[\"Iterable\"]),\n         (\"Sequence\",[\"Sliceable\",\"Collection\",\"Plus\"]),\n         (\"Sequence$list\",[\"Sequence\"])]                        -- Sequence,Sliceable,Indexed,Collection,Iterable,Plus\n\n\n\n--   (Indexed)       Iterable                        Indexed\n--    |               |                               |\n--    |               |                               |\n--   (Sliceable)     Collection      Plus            Sliceable\n--    |               |               |               |\n--    |               |               |               |\n--   Sequence <-------- <--------------              Sliceable$list\n--    |                                               |\n--    |                                               |\n--   Sequence$list <-----------------------------------\n\nex24  = [(\"Plus\",[]), (\"Indexed\",[]), (\"Iterable\",[]),\n         (\"Sliceable\",[\"Indexed\"]), (\"Collection\",[\"Iterable\"]),\n         (\"Sequence\",[\"Sliceable\",\"Collection\",\"Plus\"]),\n         (\"Sliceable$list\",[\"Sliceable\"]),\n         (\"Sequence$list\",[\"Sliceable$list\",\"Sequence\"])]       -- Sliceable$list,Sequence,Sliceable,Indexed,Collection,Iterable,Plus\n\n\n\n--   (Indexed)       Iterable\n--    |               |\n--    |               |\n--   Sliceable       Collection      Plus            Indexed\n--    |               |               |               |\n--    |               |               |               |\n--   Sequence <-------- <--------------              Indexed$list\n--    |                                               |\n--    |                                               |\n--   Sequence$list <-----------------------------------\n\nex25  = [(\"Plus\",[]), (\"Indexed\",[]), (\"Iterable\",[]),\n         (\"Sliceable\",[\"Indexed\"]), (\"Collection\",[\"Iterable\"]),\n         (\"Sequence\",[\"Sliceable\",\"Collection\",\"Plus\"]),\n         (\"Indexed$list\",[\"Indexed\"]),\n         (\"Sequence$list\",[\"Indexed$list\",\"Sequence\"])]         -- Indexed$list,Sequence,Sliceable,Indexed,Collection,Iterable,Plus\n\n\n\n--                   Indexed         Iterable\n--                    |               |\n--                    |               |\n--   (Iterable)      Sliceable       Collection      Plus        \n--    |               |               |               |\n--    |               |               |               |\n--   (Collection)    Sequence <-------- <--------------          \n--    |               |\n--    |               |\n--   Container       Sequence$list                               \n--    |               |\n--    |               |\n--   Container$list <--\n\nex26  = [(\"Plus\",[]), (\"Indexed\",[]), (\"Iterable\",[]),\n         (\"Sliceable\",[\"Indexed\"]), (\"Collection\",[\"Iterable\"]),\n         (\"Sequence\",[\"Sliceable\",\"Collection\",\"Plus\"]),\n         (\"Container\",[\"Collection\"]),\n         (\"Sequence$list\",[\"Sequence\"]),\n         (\"Container$list\",[\"Sequence$list\",\"Container\"])]      -- Sequence$list,Sequence,Sliceable,Indexed,Container,Collection,Iterable,Plus\n"
  },
  {
    "path": "workspace/Plan-scribble.txt",
    "content": "Acton II (scribble)\n-------------------\n\nA. Language\n\n    * Syntax of types.\n\n        fun1 : (int) -> (float,float) -> str\n        fun2 : (int,int,bool) -> bool\n        fun3 : (int,int,bool) -> (int,int)\n        fun4 : ((int,int),bool) -> (int,int)\n        fun5 : ((int,int,bool)) -> (int,int)\n        fun6 : (int,(int,),bool) -> str\n        fun7 : () -> str\n    \n        dict1 : {str:(float,float)}\n        dict2 : {(int,str):apa}\n    \n        fun8 : (A,B) -> bool \\\\ ElementOf(A,B)\n    \n        fun9 : (A,B) -> {A:B} \\\\ Hashable(A)    \n        fun9 : (A,B) -> {A:B} \\ Hashable(A)    \n        fun9 : (A,B) -> {A:B} / Hashable(A)    \n\n        fun9 : apa(A) \\\\ Hashable(A)\n        def fun9(a,b):\n            return {a:b}\n\n        x = fun9([1,2,3],\"apa\")\n    \n        def fun2(x:int, y:int, z:bool) -> bool:\n            c = (a,b) = f(3)\n            return z\n        \n        type apa(A) = (A,B) -> {A:B}\n\n        f : (A) -> Apa(A) \\\\ Hashable(A)\n        g : (int) -> Apa(int)\n    \n        fun13 : (Apa(int),(int)->str) -> Apa(str)\n        fun14 : (Apa(A),(A)->B) -> Apa(B)\n    \n        fun15 : ((apa:[A],bepa:{int:A}), (A)->B) -> (apa:[A],bepa:{int:B})\n    \n        [1,2,3]         : [int]\n        {'x':1,'y':2}   : {str:int}\n        {1,2,3}         : {int}\n        \n        [1,2,3]         : frozenlist(int)\n        {'x':1,'y':2}   : frozendict(str,int)\n        {1,2,3}         : frozenset(int)\n\n        [1,2,3]         : list(int)\n        {'x':1,'y':2}   : dict(str,int)\n        {1,2,3}         : set(int)        \n\n        [1,2,3]         : A(int) \\\\ IsList(A)\n        {'x':1,'y':2}   : A(str,int) \\\\ IsDict(A)\n        {1,2,3}         : A(int) \\\\ IsSet(A)\n\n        list([1,2,3])   : list(int)\n        list(x)         : list(int)\n        list            : (A(B)) -> list(B) \\\\ IsList(A)\n        frozenlist      : (A(B)) -> frozenlist(B) \\\\ IsList(A)\n        frozenlist      : A(B) -> frozenlist(B) \\\\ IsList(A)\n\n        [1,2,3]         : list(int)\n        {'x':1,'y':2}   : dict(str,int)\n        {1,2,3}         : set(int)\n\n        [1,2,3]         : list(int)\n        {'x':1,'y':2}   : dict(str,int)\n        {1,2,3}         : set(int)        \n\n        ![1,2,3]        : list(int)\n        !{'x':1,'y':2}  : dict(str,int)\n        !{1,2,3}        : set(int)\n\n        mut([1,2,3])        : list(int)\n        mut({'x':1,'y':2})  : dict(str,int)\n        mut({1,2,3})        : set(int)\n        \n    struct(A):    \n        f : (A,int) -> bool\n        d : (A) -> bool\n        d : sync new (int) -> bool\n        \n        e : sync () -> None\n        \n\n    f : (a,b) -> ()\n    g : (a,b) -> None\n    \n    kalle : sync () -> None\n    \n    def kalle():\n        pass\n        \n    \n    class C():\n        def __init__(self, x, y):\n            self.x = x\n            self.y = y\n        def sum(self):\n            return self.x + self.y\n        \n#   instance Eq C:\n        def __eq__(self:C,other:C):\n            return self.x == other.x and self.y == other.y\n        def __ne__(self,other):\n            return self.x != None\n\n    class D(C):\n        def __init__(self, x,y,z):\n            C.__init__(self,x,y)\n            self.z = z\n            \n        def __eq__(self:D,other:D):\n            return self.z == other.z and C.__eq__(self,other)\n    \n    c : C = C(1,2)\n    d : D = D(1,2,3)\n    \n    c == c : bool           ---->       C.__eq__(c,c)\n    c == d : bool           ---->       C.__eq__(c,d)\n    d == d : bool           ---->       D.__eq__(d,d)\n    d == c : bool           ---->       C.__eq__(d,c)       --/-->      D.__eq__(d,c)\n    \n    \n    class Eq():\n        def __eq__(a,b):\n            a.x == b.x and a.y == b.y\n    \n    class Ord(Eq):\n        def __le__(a,b):\n            a.x <= b.x and a.y <= b.y\n    \n    struct Apa():\n        x: int\n        y: int\n    \n    \n    \n    kalle(*None)\n    \n    p : struct((int,str))\n    p.f((1,\"\"),7)\n    \n        def \n    \n        f(x)         : bool\n        f((1,\"\",pi)) : bool\n        \n        h           : (int,str,float) -> bool\n        h(1,\"\",pi)  : bool\n        \n        x   : (int,str,float)\n        \n        h(*x)\n\n        g       : (int) -> bool\n        g(7)    : bool\n        \n        \n        \n        x       : T     = (1,\"\",pi)\n        \n        \n        x,y = f(a,b,c)\n        \n        \n    * Named interfaces / tagged unions\n    \n        struct Apa[]:\n            pass\n\n        struct Bepa[A](Apa[A]):\n            b : A\n    \n        struct Cepa[A](Apa[A],Basetype):\n            c1 : str  = \"\"\n            c2 : Apa[A]\n    \n        struct Depa[A]:\n            pass\n        \n#        struct Epa[A] (Bepa[A],Cepa[A]):\n\n        x : Apa[int]\n        x = f(...)  \n        x = Bepa(2)\n        x = Bepa(b=2)\n    \n        if isinstance(x,Bepa):\n            b=x.b\n            return b\n        elif isinstance(x,Cepa):\n            if x.c1 == \"\" and isinstance(x.c2,Fepa):\n                return 0\n            else:\n                s = x.c1\n                a = x.c2\n                return ...\n        else:\n            ...\n    \n        return x.b if isinstance(x,Bepa) else (0 if x.c1==\"\" and isinstance(x.c2,Fepa) else ...) if isinstance(x,Cepa) else ...\n    \n    \n        lambda x: x.b       :  ((b:A,**R)) -> A\n    \n        ######### (c.f. Haskell)\n\n        data Apa a = Bepa a | Cepa {c1::String, c2::Apa a} | Depa\n\n        f (Bepa b)    v\n          | v > 0       = r+g\n          where r       = ...\n                g       = ...\n        f (Cepa \"\" 0) 6 = ...\n        f a           x = ...\n\n        f a x = case (a,x) of\n                    (Bepa b, _) -> ...\n                    (Cepa \"\" 0, 6) -> ...\n                    _  -> ...\n\n        ########### Proposal:\n        \n        struct Apa[A]:\n            case Bepa:\n                b : A\n            case Cepa:\n                c1 : str\n                c2 : Apa[A]\n            case Depa:\n                pass\n\n        x : Apa[int] = Bepa(4)\n        \n        switch x:\n            case Bepa(4):\n                ...\n            case Bepa(5):\n                ...\n            case Cepa(c1,c2):\n                ...\n            case Depa():\n                ...\n\n        ############## (Selection from tuples)\n\n        t = (1,\"\",false)\n\n        t[0]\n        t[1]\n        t[2]\n\n        def f(x,i):\n            t = (1,\"\",false)\n            return t.0\n            return t[0]\n            return t[i]\n            return x[i]\n\n\n\n\n\n\n\n\n        ##############  (Subtyping / type inheritance)\n\n        struct Basetype (Embryo):\n            base : str\n        \n        struct Apa[A]:\n            case Bepa:\n                x: A\n                y: int\n                z: A\n            case Cepa (Basetype):\n                c0: int\n                c1: str\n                c2: Apa[A]\n            case Depa:\n                b:int\n            case Epa:\n                s: str\n                r: Apa[str]\n                b: int\n            case Fepa:\n                pass\n        \n        struct Gepa[A] (Fepa[A])\n            f1: float\n            f2: bool\n            f3: A\n\n        struct Hepa[A] (Fepa[A]):\n            case Iepa:\n                i1: int\n                i2: (int),int)->int\n            case Jepa:\n                pass\n\n\n\n\n\n\n\n\n\n\n        ############ (The diamond problem)\n\n        module M:\n\n            struct A:\n                x: [int]\n\n        module N:\n            import M\n\n            struct A:\n                x: int\n\n            struct B:\n                y: str\n\n            struct C:\n                A\n                B\n                ma: M.A\n\n            v: C = ...\n    \n            v.x   v.b.x   v.ma.x   v.B.x     v.A.x    v.M.A.x\n\n            f(v)     g(v)    f(v.ma)\n    \n        def f(p):\n            print(p.x)\n\n        def f(p):\n            print(p.y)\n\n            struct A(T):\n                a: T\n    \n            struct B:\n                A(int)\n    \n            struct C:\n                A(str)\n    \n            struct D:\n                B\n                C\n    \n            d = D(a=3)\n    \n            b: B = d\n            b.a\n    \n            c: C = d\n            c.a == b.a == d.a\n    \n    * Pattern matching\n\n        ##### Clumsy:\n        \n        def f(Bepa(b)):\n            ....\n        def f(Cepa(\"\",Fepa)):\n            ...\n\n        ##### Nice:\n        \n        def f(a, x):\n            switch a, x:\n                case (Bepa(b),v) and v>b and fib(b) > 100000000 :\n                    ...\n                case Cepa(\"\",0), 6:\n                    ...\n                case Cepa(c1,c2), i:\n                    ...\n                case (Bepa(b),v):\n                    ...\n                else:\n                    ...\n    \n        def f(u):\n\n            var x : Apa(_)\n            y : str\n            z : Blaj({str})\n\n            x = Bepa(base=\"\",b=u)\n            x = Bepa(Fepa)\n            x = Cepa(\"\",Epa(\"huh\",Fepa))\n    \n            switch x:\n                case Bepa:\n                    b = x.b\n                    x.base      x.0.base\n                case Bepa(b):\n                    return b+23\n                case Cepa(c2=Fepa,c1=\"\"):\n                    return 0\n                case Cepa(s, a):\n                    return ...\n                else:\n\n            return b if x case Bepa(b) and b>0 else 0\n    \n            return x if f(x) else None\n    \n            if f(x):\n                return x\n            else:\n                return None\n\n    * Comprehension syntax\n    \n        for x,y in zip(\"abcdefghij\", range(10)):\n            print(x,y)\n\n        for x in \"abcdefghij\" and y in range(10):\n            print(x,y)\n    \n        return [ for x in \"abcdefghij\" and y in range(10): (x,y) ]\n\n        return [ for x in \"abcdefghij\": for y in range(10): (x,y) ]\n\n        return [ for x in range(10): if x%3==0: for y in range(x): (x,y) ]\n\n        for x in range(10): \n            if x%3==0: \n                for y in range(x): \n                    print(x,y)\n\n        return [ (x,y) for x in range(10) if x%3==0 for y in range(x) ]\n\n\n        some_struct = (a = 1, b = \"world\")\n        \n        fun_struct = (a = lambda x:x+1, b = lambda s:\"hello \"+s)\n\n        ( for (v=k) in some_struct: v = fun_struct.v(k) )    ==    (a = 2, b = \"hello world\")\n        ( v = fun_struct.v(k) for (v=k) in some_struct )     ==    (a = 2, b = \"hello world\")\n        \n        \n        some_struct = {'a' : 1, 'b' : \"world\")\n        \n        fun_struct = {'a' : lambda x:x+1, 'b' : lambda s:\"hello \"+s)\n\n        { for v,k in some_struct.items(): v: fun_struct.v(k) }    ==    {'a' : 2, 'b' : \"hello world\"}\n        { v: fun_struct.v(k) for v,k in some_struct.items() }     ==    {'a' : 2, 'b' : \"hello world\"}\n        \n####################\n\n    x : (a:int,b:bool)\n    y : (k:str,l:str)\n    \n    x = (a=1,b=True)\n    \n    def f(y):\n        return (v=4,**x, b=False, **y, k=\"\")\n    "
  },
  {
    "path": "workspace/Plan.txt",
    "content": "2021-02-02:\n\n    X Convert NameInfo envs to format of later passes\n    X Make CPSEnv and LiftEnv instances of Env\n    X Update CPS and Lifter passes to latest syntax\n    X Convert NameInfo envs in Normalize\n    X Convert NameInfo envs in CPS and Lifter as well                       2h      8h\n    X Make NormEnv an instance of Env                                       1h      1h\n    X Make GenEnv an instance of Env                                        1h      1h\n    X Let CPS make decisions based on true type                             1d      2d\n    X Ensure new vars in Normalize, CPS and Lifter are fully typed          2d      3d\n    X Revisit Lifter on classes (now restricted to top level)               1d      2d\n    X Generate custom $Clos subclasses in Lifter                            1d      2d\n    X Infer @property signatures based on __init__ assignments              2d      4d\n    X Type-convert plain classes as well                                    3h      6h\n    X Sample actor state ref'd within lambdas before closure conversion     1d      1d\n    X Introduce special constructor GName for unaliased names               4h      8h\n    X Fill out gaps in CodeGen                                              2d      5d\n    X Apply typeinfo in CodeGen to insert correct casts                     2d      4d\n    X Print generated C code with precedences                               2d      3d\n    X Typecheck and convert formatted string literals                       1d      2d\n    X Fully defer ASYNC/AWAIT wrapping to the deactorizer pass              1d      2d\n    X Integrate DB sources in build                                         1d      2d\n    X Set up dedicated rts thread for DB protocol daemon                    1d      2d\n    X Add serialization calls to rts                                        3h      8h\n    X Define Acton Environment type and implement IO loop in rts            1w      2w\n\n    X Build demo app                                                        2w      4w\n    X Presentation slides                                                   1w      1w\n    - Documentation/tutorial                                                1w      1w\n                                                                            4w      6w\n\n    - Sort out conversion from star params/args to tuples\n    - Sort out the pos/kwd parameter parsing ambiguity\n    - Implement pos/kwd and opt relaxation in Solver\n    - Implement Rest/RestI in rts\n    - Eliminate Star-elems in Normalizer\n    - Fix cps translation of effect-polymorphic functions\n    - Translate the root expression as a proper function\n    - Make global __builtin__ witnesses available to Solver\n    - Translate list comprehensions\n    / Handle the with statements\n    - Implement raise and try in the rts\n    - Allow error exceptions to be thrown in from within lub & glb\n    - Make NVar polymorphic but not qualified by inference \n      (c.f. the monomorphism restriction)\n    - Save the import list with each ty-file, fall back to ty-file\n      if source not found when chasing imports\n\n\nActon II\n--------\n\n@. Terminology:\n    world    - A cluster consisting of 1-N nodes, on a non-partitioning network.\n               in MMO server terms: \"an instance\" :)\n               Multiple worlds might communicate, but only through a developer-defined\n               interface using sockets.\n    node     - A single process contributing in a cluster.\n               The same physical hardware might run multiple node processes (even non-virtualized).\n\nFirst release prio marked as [1]\n\nA. Language\n    * Inheritance vs. delegation, examples and convenient syntax.\n    The current Acton language makes use of a limited form of actor inheritance, which leaves\n    several questions (such as access to overridden methods, or visibility of a parent's state\n    variables) unresolved. Define a set of typical examples of inheritance and explore whether\n    the same functionality can be obtained by replacing the super-actor with a local actor instance\n    (a delegate), which is explicitly invoked via its regular interface. Ensure that large sets\n    of the delegate's attributes can be conveniently reexported by the wrapping actor (perhaps\n    using the **var pattern and expression syntax). Then generalize the examples to multiple\n    delegates, and (if experiment is successful) remove actor inheritance from the language.\n\n    * Import with version hashes/tags\n    Choose a lexical syntax for version hashes/tags that \"blends\" well with Python's identifier\n    syntax (so that version-completed )\n\n    * Syntax of types.\n    Define a concrete syntax of type expressions, to replace the annotation terms in the current\n    Acton grammar. Stay as close to the general Python expression syntax as possible. Some natural\n    choices: (int,bool,str) for tuple types, (x=int,y=float) for anonymous struct types,\n    (int,bool,x=str,y=float)->None for function types, 'tag' for singleton string constant types,\n    int|'tag1'|'tag2' for union types, ?int for option types, single upper-case characters for\n    type variables, any other name for user-defined type constructors, mycon(int,A) for type\n    application, [int] for int lists, {str:int} for dicts, {str} for sets, etc. Things to resolve:\n    distinction between mutable and immutable lists, dicts and sets (use list(A), dict(A,B) and\n    set(B) for the mutable variants?), polymorphic rows (perhaps **R), qualified types (use at\n    all in concrete syntax?), effect annotations on functions (idea: ro sync (A)->B). To recall:\n    type constructors and variables constitute a namespace entirely distinct from the regular\n    terms, even though some constructor names (int, str, list, ...) also exist as valid terms\n    (mostly built-in conversion functions). Invent a syntax for type abbreviations (macros).\n\n    * Named strutcs / tagged variants\n    Propose a Pythonic construct for declaring immutable named structs (interfaces), that allows\n    multiple super-types (extension), explicit polymorphic type arguments, and preferably also\n    multiple sibling subtypes (tagged variants) to be expressed with little syntactic overhead.\n    Make each name a valid term constructor as well (possily excluding the basetype of variants).\n    Allow type recursion, and a mixture of positional and keyword (field name) arguments in the\n    term constructors. Important to sort out the exact rules that govern field name clashes.\n\n    * Pattern matching\n    Extend the language with a switch statement, that allows nested patterns of (tagged) structs,\n    tuples, lists, dicts, and atomic types. Allow variable binding, wildcard patterns and guard\n    expressions. Make the syntax \"pythonic\" and compatible with the tagged variant type declarations.\n    Also introduce an infix case expression that can match against a pattern and bind its variables\n    in any if-branch taken as a direct consequence of a positive match. Define the semantics of\n    pattern-matching in terms of a translation into a form that only uses tag tests (isinstance).\n\n    * Comprehension syntax\n    Try out an alternative syntax for list comprehensions: '[' COMP EXPR ']', where COMP is\n    'for' GEN ':' COMP | 'if' EXPR ':' COMP | /* empty */, and GEN is PAT 'in' EXPR. That is, a\n    grammar that mimics the intuitive form of nested statements. Also experiment with the concept\n    of \"zip\" comprehensions, where GEN can also be GEN 'and' GEN.\n\n    * Semantics of classes\n    Complete the formal semantics regarding classes and instances. Things to decide: support\n    mutation of the classes themselves? (no...) Make method lookup in base classes explicit?\n    How should the 'isinstance' operator be defined? Can classes inherit from lists/dicts/sets\n    (yes...)? From primitive or immutable types (no...)?\n\n    * Semantics of recursion\n    Revisit the formal semantics of recursive definitions and see if an explicit notion of\n    top-level bindings can be expressed, which would natively support recursion. If so, ensure\n    that recursion on other levels can be defined in terms of simple lifting to the top level.\n\n    * Semantics of break/continue\n    Formalize the control flow of loops with break/continue in terms of encodings using\n    exceptions, in order to firmly explain how these features interact.\n\nB. Type-system\n    * Encoding of the union type using rows\n    Define the meaning of union types, and the atomic types that can participate in a union, in\n    terms of rows (pretty much analogous to the way effects are expressed as rows). Consequence:\n    atomic types in positive (constructed) positions must become singleton rows with a polymorphic\n    tail, whereas the same types in negative positions must stand for singleton rows with empty\n    tails. Concrete atomic type names are thus mere short-hands for these singleton unions. Also\n    investigate whether the opt type can be encoded in a similar manner (as a union between atomic\n    type None and *any* other type), or whether sub-typing (back-tracking) must be deployed here.\n\n    * Inference of overloaded constructs using back-tracking\n    Define the set of overloaded constructs that Acton should support as a built-in set of\n    Qualified Types predicates, so that overloading resolution can be implemented as a back-\n    tracking constraint solver. Candidates: truth-value (of almost any type), conversion to/from\n    strings, equality, inequality, identity, attribute selection, indexing, and the overloading\n    required to allow positional function arguments to match named function parameters. Possibly:\n    the subtyping relation between named structs and classes, and the opt type as subtyping.\n    Also investigate which Python \"abstractions\" that are worth preserving (iterable, sequence,\n    dict view, hashable, context mgr, ...).\n\n    * Struct comprehensions\n    Explore the theory required to support struct comprehensions, i.e., abstractions over unknown\n    struct types in the form of a set of unknown types indexed by an unknown set of tags. Sort out\n    the details of the struct comprehension expression, as well as any consequences to type\n    inference.\n\n    * Subtyping or row polymorphism for extended named structs?\n    Evaluate the best way to encode nominal subtyping between user-defined structs and classes --\n    either using row-polymorphism as the internal representation (which is as fast as unification\n    but requires the compiler to insert type coercion operators at select program places), or by\n    direct subtype constraint solving (which requires weighted searching among the declared subtype\n    axioms but enables subtyping coercions wherever they are required).\n\n    * Deadlock avoidance analysis\n    Explore the possibility of performing a safe deadlock avoidance analysis at compile-time. Idea:\n    Extend the types of actor ids, actor methods and message handles with a (hidden) unique type\n    variable denoting the *depth* of the receiving actor. Generate inequality constraints at\n    inference time which guarantee that every synchronous call or await operation is directed to an\n    actor of strictly greater depth than the sender. Perform unification and constraint solving as\n    usual, ignoring the depth constraints. Since depth variables can only be unified with other\n    depth variables, the resulting depth constraints must remain a partial order. Use topological\n    sorting to determine whether this order is free of cycles, i.e., whether the synchronous call\n    chain of the original program is deadlock-free.\n\nC. Compiler\n    [1] * C back-end\n    Define an abstract syntax of (suitably constrained) C programs and replace the current Acton-\n    to-Python translator with a pass that generates C instead. Avoid the need to maintain type\n    information by approximating every primitive value or pointer to WORD. Map values of primitive\n    types to their C equivalents. Explore 64-bit words for tagging primitive values in unions.\n    Translate class definitions to (linked) method tables. Avoid the idea of terminating each\n    iteration by an exception.\n\n    [1] * C representation of data\n    Investigate what C representation to use for dicts, lists and sets. Check out what Python does\n    internally. See if list concatenation/extension can be made cheaper at run-time by means of\n    a concat constructor, hidden behind the iterator interface. Sync with the needs of (E).\n\n    [1] * Reinstalled CPS pass\n    Recover the abandoned CPS code and update it, especially regarding the formal semantics of\n    exceptions and break/continue. Redress it to work on the Acton AST, not Python. Ensure that\n    the decision points (to convert or not convert a function/call) are based solely on inferred\n    effects (no remnants of syntax-based short-cuts). Also convert the lambda-lifter and\n    closure-converter passes to use the proper Acton AST.\n\n    * More refined effect inference\n    Extend the current effect inference to capture mutation and sync/awaits calls at minimum,\n    possibly also async calls, actor creation and exception-throwing.\n\n    [1] * Unique name generation\n    Make an overhaul of all compiler passes to ensure they all generate unique names using a\n    global (monadic) name supply. (This means no more semi-clever use of source locations to\n    establish uniqueness!)\n\n    [1] * Binary interface files\n    Merge in Björn's code to use new (fast!) binary interface files format.\n\n    * New combinator parser\n    Replace the old LR parser generated by Happy with Björn's alternative based on Megaparsec\n    combinators. Linked to the unique name generation fix above, which will remove the need to\n    retain the old (and heavy) representation of SrcLocations.\n\n    * Retrofit the type-checker with witness translation to meet the demands of overloading\n    (and possibly subtype coercions).\n\n    * Complete the code that implements a redesigned tracking of type errors, where unification\n    failures only print the parts of a type that actually differ (git branch 'better-errors').\n\nD. Local RTS\n    [1]\n        Event-loop/reactor, 1 thread-per-logical-core\n            IO via kqueue/epoll/..., files/sockets/devices/...\n            Scheduler:\n                1. Timer queue\n                    Monotonic clock - (perf counter not steady)\n                    Via kqueue/(epoll timeout)\n                2. (Actor) ready queue\n                3. IO\n        Basic memory management:\n            Malloc wrapper (jemalloc?)\n            No GC\n        Investigate good-enough concurrent data structures (queues, task pool, hashtable, ...)\n            libcuckoo, liblfds, spinlock, mutex\n        Design of async Env\n            Table mapping events/connections to actor context\n            Env:\n                Socket data - std read/write user allocated buffers\n                (DNS lookup?)\n                Exit\n        Implementation of\n            ACTOR\n            MSG\n            CLOSURE\n            ASYNC\n                Post message to target actor queue + ready?\n                Return awaitable-handle\n            SYNC/AWAIT\n                Accepts awaitable-handle\n            POSTPONE\n                Add continuation to timer queue\n                Return cancelable-handle\n            CANCEL\n                Accept cancelable-handle\n        Exception handler stack (per message?)\n            PUSH/POP?\n    [2]\n        Memory management, slab allocator, local garbage-collector\n            Sharing message parameters across continuations?\n            Region-inference for locally used results...?\n        Investigate optimal lock-free shared data structures (queues, task pool, hashtable, ...)\n        Argument and result conventions for various execution contexts\n        Tagging and propagation of root events through method call chains\n        Access to compiled code in the form of dynamic C libraries\n\nE. Distributed RTS\n    Conversion from global ids to node id + local pointers (DHT + dynamic placement table?)\n    Conversion from local pointer to global id (globale table or embedded in heap data?)\n    Distributed garbage collection\n    Control message protocol between nodes (multicast/broadcast?)\n        CLI messages for inspection and control\n        Gossip protocol for spreading cluster membership knowledge\n        Dedicated thread for cluster protocol and persistence to disk?  I/O?\n\n    Check-pointing mechanism\n\n        After an actor has completed a mutating message call, a (diff-)snapshot is made and distributed.\n        Guidance to the snapshot content could probably be provided by the compiler.\n\n        Track state updates using custom functions at each checkpoint, or use run-time book-keeping machinery\n\n    Load-balancing based on actor connectivity graph and A * traffic load + B * cpu load + C * memory usage\n\nF. Code repository\n    Summary of the global module system design:\n    -   All Acton code is conceptually part of a global module structure, that allows unambiguous identification\n        of every Acton module in the world.\n    -   An Acton module definition has the following form, where a NAMEPATH is one or more module names\n        connected by a dot (and the indentation of DEFINITIONS is voluntary):\n\n            module NAMEPATH:\n                DEFINITIONS\n\n    -   A compilation unit is a file containing a module definition. The name and location of such a file\n        is irrelevant, it is the NAMEPATH of the contained module definition that determines the module's\n        place in the Acton module hierarchy.\n    -   On the top level, the Acton module system is partitioned into a set of namespaces:\n        *   The Acton standard library namespace, identified as 'acton', visible to all Acton developers.\n        *   One namespace for every user on every computer where the Acton development system is installed.\n            These namespaces are identified as 'localhost/USERNAME', and are only visible to the users on each\n            particular computer.\n        *   A set of namespaces on every internet-connected computer on which an Acton code server runs. These\n            namespaces are written 'DOMAIN.NAME/PATH' and are accessible by every Acton developer on the\n            internet who owns appropriate access credentials.\n    -   To cater for evolving code, each Acton namespace exposes a set of versions. A version is identified by\n        a human-friendly version tag, whose exact lexical structure is left unspecified for now.\n    -   An Acton development system maintains a local cache of namespace contents at different versions,\n        managed via explicit tool commands. The contents of this cache can also be queried and the result\n        listed as Acton source code.\n    -   A module is imported from a specific namespace and at an explicit version by prepending the import\n        statement with a custom \"decorator\":\n\n            @NAMESPACE!VERSION\n            import NAMEPATH\n\n    -   A module defined in a specific namespace and at an explicit version is written an analogous way:\n\n            @NAMESPACE!VERSION\n            module NAMEPATH:\n                DEFINITIONS\n\n        However, such a definition is only accepted by the Acton compiler if VERSION is either unused in\n        NAMESPACE, or VERSION exists and the new module definition is identical to the existing version.\n    -   When a set of modules are compiled at a new version, all other modules of the same namespace are\n        automatically lifted to the new version as well, but with their contents unchanged. This feature can\n        be disabled on the compiler command line for select modules, effectively deleting them from the\n        new version of the namespace.\n    -   A module can also be defined with an empty VERSION field:\n\n            @NAMESPACE\n            module NAMEPATH:\n                DEFINITIONS\n\n        This results in code being placed in NAMESPACE under an internally generated version string, that is\n        guaranteed to be unique.\n    -   Likewise, importing a module without specifying a version implicitly selects the latest version of\n        the referenced namespace that is available in the local namespace cache:\n\n            @NAMESPACE\n            import NAMEPATH\n\n        The compiled code is nevertheless stored with the selected namespace version spelled out, making it\n        insensitive to future version upgrades to the local namespace cache.\n    -   For completely undecorated module definitions and imports, the following defaults are used:\n    -   A module definition without a namespace decoration is equivalent to specifying the namespace\n        'localhost/USERNAME'.\n    -   An un-decorated import statement is resolved in the namespace 'localhost/USERNAME', provided the\n        imported module actually exists in the latest version of 'localhost/USERNAME'. Otherwise the 'acton'\n        namespace is assumed. In both cases, however, the module being compiled is stored in the local module\n        cache with the selected namespace explicitly written out.\n    -   It should be noted that the design above makes it fully possible to compile privately produced code\n        into a namespace that legally belongs to some external organization. This is not a security flaw,\n        as the important aspect is not what self-deceptions a developer chooses to believe, but to what\n        extent such deceptions can remain undetected by others. The Acton system takes serious measures to\n        prohibit the latter, although the details of how this is implemented will be deferred to a later\n        discussion.\n\n    A first implementation sketch:\n    ...\n\nG. CLI\n    Creating a running Acton \"world\" (bootstrap, references an actor def in the global module namespace)\n    Monitor/inspect a running instance (meta info like cpu load, mem usage, traffic, downtimes, io, etc...)\n    Commit new modules (compile and install into repo)\n    Inspect repo (at specific version)\n    Inspect and interact with live actors / run Acton code in sandbox\n\n    Add/remove cluster nodes\n        A new node is started in a \"stand-by\" mode, and then instructing the cluster to add the new node\n        Removing a node similarly: instructing the cluster to remove a specific node,\n        making the affected node to enter the same \"stand-by\" mode.\n\nH. Live code upgrade\n    Replacing the living code pointers (atomically or via a message \"wave\"), using\n        Should the \"wave\" perform it's update bottom-up?\n    aggregate of conversion functions (lifted to full state converter) if state types don't match\n\nI. Security architecture\n    Analysis...\n\n    When a world is started it is given a private key/cert.\n        This key acts as a CA when adding nodes to the cluster; they must pass a key exchange authentication.\n        BUT: the key must be distributed among all nodes. Is this regarded as \"safe\"?\n    A new node (to be added into a cluster) is started with a public key, matching the cluster's private key.\n\nJ. Libraries\n    Basic python:\n        Primitive types:\n            Now:\n                int (bounded to machine word length (64) or overrideable default)\n                bool\n                float64\n            When needed:\n                (u)int8/16/32/64/128\n                bigint/integer\n                float32\n        Data structures:\n            (frozen)list, (frozen)(sorted/ordered)set, (frozen)(sorted/ordered)dict, tuple, str (utf-8), bytes, bytearray, Decimal, BigFloat\n                klib\n                Representation of anonymous structs\n        Built-ins:\n            Now:\n                Data constructors:\n                    bool, bytes, bytearray, dict, float, int, list, set, str, tuple\n                Other:\n                    enumerate, format, hash, len, (print), range, round, sorted\n            When needed:\n                abs, all, any, ascii, bin, chr, divmod, filter, hex, isinstance, map, max, min, ord, pow, reversed, sum, zip\n            Probably not:\n                frozenset, complex, (.id), iter, next, object, oct, (property), (repr), slice, (super)\n        Source of time duration (monotonic) as python float64 seconds\n        Stopwatch -> float64 (s)\n        String support functions:\n            format, endswith, find, index, is(alnum/...), join, lower, partition, replace, split, startswith, strip, upper\n        Type classes:\n            ContextManager, Hashable, Ordered, Numeric, PrintParse(T1<->bytes/str) (Codec(T1<->T2))\n            Iterable > Sequence/Indexed\n            Keyed/Dictionary\n            TODO: Design standard typeclasses(-hierarchy)\n        Exceptions - (Those already known to the compiler)\n    [1] NETCONF client\n\t    utf-8 <-> bytes (stub encode/decode)\n        Struct/dict <-> XML string (parse/print-library) (convert existing python impl to acton)\n\t    socket, connection interfaces (inspired or modeled after asyncio)\n        IP address/port types\n\t    Cryptography functionality\n\t    ssh interface\n\n    [2] NETCONF server\n        NMDA RFC 8342\n        NETCONF push\n        NETCONF call home\n        tls interface (?)\n        DateTime (time of day, calendar and such)\n        Binary serialization of primitives etc (byte-order?)\n    Tracker\n    Multi-actor transactions\n    Transactional Causal Consistency with CRDTs (Shapiro's \"Cure\")\n    Sharding combinators\n    Optimized time-series actors\n    RESTconf server and client\n    Data serialization\n    Converted Python stdlibs\n\n    REST API server\n    Communication between two Acton worlds.\n    Higher-level protocol services (built upon the async socket IO)\n        http, sctp, etc.\n        These APIs are of course also asynchronous in nature.\n\n    Wrapped C libraries (ssl, ssh, ...)\n        Akin to swig-wrapped code.\n\nK. Examples\n    [1] The classic Demo1!\n    OCP\n    Kristian's core services\n    DT's link provisioning (our demo2++)\n    Time-series illustrative example\n\nL. Documentation\n    Tutorial\n    Language reference\n    CLI manual (including sysadmin guide)\n\nM. GUI\n    Blinkenlights\n\n    Web\n    Possibly started by using the CLI, e.g.: `acton web :8000`\n    The same as, or subset of, the read-only operations possible in the CLI, but more \"flashy\"\n        Live graphs possible\n    Intended for administrators/executives; not a mega visitor-capable web site.\n\nN. YANG compiler\n\n    Perform the two steps (yangc and actc) in one go.\n\nO. Installation\n    Make target for building an installer\n    Native MacOS, Ubuntu, RedHat & CentOS\n    No external dependencies!\n\nP. Performance tests\n    TBD\n\nQ. Open-source (verb!) the classic Acton code\n\nR. Automatic test environment\n    How install basic tools?\n    Yes.\n"
  },
  {
    "path": "workspace/Semantics.txt",
    "content": "########################################### Abstract syntax ############################################\n\nVariables:          x,y\nStatevars:          z\nType constants:     C\n\nLocations:          l\nActor refs:         a,b\nMessage tags:       m\n\nIntegers:           i\nFloats:             f\nStrings:            s\n\nExpressions:        E       ::=     x  |  z  |  V  |  (A)  |  lambda F: E  |  C  |\n                                    E(A)  |  E.n  |  E.x  |  E if E else E  |  E is E  |\n                                    await E  |  isinstance(E,C)  |  do S\n\nActuals:            A       ::=     E,A    |  *E,M   |  M  |  ***E\nMappings actuals:   M       ::=     x=E,M  |  **E  |  .\n\nFormals:            F       ::=     x,F  |  x=E,F  |  *x,K   |  K  |   ***x\nKeyword formals:    K       ::=     x,K  |  x=E,K  |  **x  |  .\n\nValues:             V,W     ::=     True  |  False  |  None  |  (R)  |\n                                    ---- Only intangible constructs below\n                                    CLOS(B;F):S  |  l  |  a  |  a.m  |  (C;B)  |\n                                    ACTOR(V)  |  ASYNC(a,V)  |  CLASS(C):B\n\nValue rows:         R       ::=     O,B                                             associative\nOrderings:          O       ::=     O,V    |  .                                     associative\nBindings:           B       ::=     B,x=V  |  B,C=V  |  .                           associative & commutative\\duplicates, disjoint C\n\nStatements:         S       ::=     E  |  x = E  |  (F) = E  |  D  |  return E  |\n                                    E.x = E  |  if E: S else S  |  while E: S  |\n                                    var z = E  |  z = E  |  after E: E'  |\n                                    raise E  |  try S Z else S finally S  |\n                                    pass  |  S; S                                   associative, with unit 'pass'\n\nDeclarations:       D       ::=     def x(F): S  |\n                                    actor x(F): S  |  \n                                    class C(C): M  |\n                                    D; D                                            associative & commutative & disjoint\n\nExcepts:            Z       ::=     except C as y: S Z  |  .\n\n---- Only intangible constructs below\n\nGlobal states:      G       ::=     a:<L|Q>  |  G,G                                 associative, commutative & disjoint\nLocal states:       L       ::=     z=V, L  |  l=V, L  |  .                         associative, commutative & disjoint\nQueues:             Q       ::=     m=E,Q  |  .                                     associative & disjoint\nHistories:          H       ::=     m=V,H  |  m=do raise V, H  |  .                 associative & disjoint\n\nE-in-E contexts:    EE      ::=     _.x  |  _(A)  |  E if _ else E  |  \n                                    V(O,_,A)  |  V(O,*_,M)  |  V(O,***_)  |  V(R,x=_,M)  |  V(R,**_)  |\n                                    (O,_,A)  |  (O,*_,M)  |  (O,***_)  |  (R,x=_,M)  |  (R,**_)  |\n                                    _ is E  |  V is _  |  await _  |  isinstance(_,C)\n\nE-in-S contexts:    SE      ::=     _  |  return _  |  x = _  |  (F) = _  |  if _: S else S  |\n                                    _.x = E  |  var z = _  |  z = _  |  raise _  |\n                                    after _: x(A)  |  after V: _\n                                    \nS-in-S contexts:    SS      ::=     _; S  |  try _ Z else S finally S\n\nE-in-Q contexts:    QE      ::=     H, m=_, Q\n\n\n####################################### Expression evaluation ##########################################\n\n***** B |- C(C') ********************\n\nB  |-  C(C)\n\nB,C=CLASS(C'):B'   |-  C(C1)                                                    if  B |- C'(C1)\n\n\n***** B |- L | E --> L' | E' *******\n\nB  |-  L  |  EE[E]          -->     L'  |  EE[E']                               if  B |- L | E --> L' | E'\n\nB  |-  L  |  do S           -->     L'  |  do S'                                if  B |- L | S --> L' | S'\n\nB  |-  L  |  E              -->     L  |  E'                                    if  B |- E --> E'\n\nB  |-  L,z=V  |  z          -->     L,z=V  |  V\n\nB  |-  L,l=(C;B')  |  l.x   -->     L,l=(C;B')  |  V                            if  B' |- x --> V\nB  |-  L,l=(C;B')  |  l.x   -->     L,l=(C;B')  |  CLOS(B2,y=l;F):S             if  x # B' and B |- C.x --> CLOS(B2;y,F):S and @classattr x\nB  |-  L,l=(C;B')  |  l.x   -->     L,l=(C;B')  |  V                            if  x # B' and B |- C.x --> V otherwise\n\nB  |-  L  |  C(R)           -->     L,l=(C;.)  |  do l._init_(R); return l      if  B = B1,C=CLASS(C'):B2  and  N |- C(object)\n\nB  |-  L,l=(C;B')  |  isinstance(l,C')    \n                            -->     L,l=(C;B')  |  True                         if  B |- C(C')\n                            -->     L,l=(C;B')  |  False                        if  not B |- C(C')\n\n\n***** B |- E --> E' ****************\n\nB  |-  E                    -->     E'                                          if  E --> E'\n\nB,x=V  |-  x                -->     V\n\nB  |-  lambda F: E          -->     CLOS(B;F): return E\n\nB  |-  (C;B').x             -->     V                                           if  B' |- x --> V\nB  |-  (C;B').x             -->     CLOS(B2,y=(C;B');F):S                       if  x # B' and B |- C.x --> CLOS(B2;y,F):S and @classattr x\nB  |-  (C;B').x             -->     V                                           if  x # B' and B |- C.x --> V otherwise\n\nB,C=CLASS(C'):B'  |-  C.x   -->     V                                           if  (B').x --> V\nB,C=CLASS(C'):B'  |-  C.x   -->     V                                           if  x # B' and B |- C'.x --> V\n\nB  |-  C(B')                -->     (C;B')                                      if  B = B1,C=CLASS(C'):B2  and  N |- C(struct)\n\nB  |-  isinstance((C;B'),C')-->     True                                        if  B |- C(C')\n                            -->     False                                       if  not B |- C(C')\n\n\n***** E --> E' *********************\n\nE1 if True else E2          -->     E1\nE1 if False else E2         -->     E2\n\ndo B; pass                  -->     None\ndo B; return V              -->     V                                           if  fc(V) # dc(B)\ndo B; raise V               -->     do raise V                                  if  fc(V) # dc(B)\n\nEE[do raise V]              -->     do raise V\n\n(O,*(O'),M)                 -->     (O,O',M)\n(O,B,**(B'))                -->     (O,B',B)                                    (The binding order...!)\n\nV(R)                        -->     do B; (F)=(R); S                            if  V = CLOS(B;F):S\n\n(V0,..,Vn,R).n              -->     Vn\n(R,x=V).x                   -->     V\n\nl is l                      -->     True\nl is l'                     -->     False                                       if  l != l'\n\na is a                      -->     True\na is b                      -->     False                                       if  a != b\n\n\n######################################## Statement execution ###########################################\n\n\n***** B |- L | S --> L' | S' *******\n\nB  |-  L  |  SS[S]          -->     L'  |  SS[S']                               if  B |- L | S --> L' | S'\n\nB  |-  L  |  SE[E]          -->     L'  |  SE[E']                               if  B |- L | E --> L' | E'\n\nB  |-  L  |  S              -->     L'  |  S'                                   if  L | S --> L' | S'\n\nB  |-  L  |  S              -->     L  |  S'                                    if  B |- S --> S'\n\n\n***** B |- S --> S' ****************\n\nB  |-  B'; S                -->     B'; S'                                      if  B,B' |- S --> S'\n\nB  |-  S                    -->     S'                                          if  S --> S'\n\nB  |-  D                    -->     B'                                          if  B,B' |- D ==> B'\n\n\n***** S --> S' *********************\n\nV; S                        -->     S\nreturn V; S                 -->     return V\nraise V; S                  -->     raise V\n\nif True: S1 else S2         -->     S1\nif False: S1 else S2        -->     S2\nwhile E: S                  -->     if E: S; while E: S else pass\n\n(x,F) = (V,O,B)             -->     x = V; (F) = (O,B)\n(x=E,F) = (None,O,B)        -->     x = E; (F) = (O,B)\n(x=E,F) = (V,O,B)           -->     x = V; (F) = (O,B)\n(*x,K) = (O,B)              -->     x = (O); (K) = (B)\n(***x) = (O,B)              -->     x = (O,B)\n(x,K) = (x=V,B)             -->     x = V; (K) = (B)\n(x=E,K) = (x=None,B)        -->     x = E; (K) = (B)\n(x=E,K) = (x=V,B)           -->     x = V; (K) = (B)\n(**x) = (B)                 -->     x = (B)\n() = ()                     -->     pass\n\nSE[do raise V]              -->     raise V\n\ntry B; S Z else S1 finally S2                       -->   B; try S Z else S1 finally S2\ntry return V Z else S1 finally S2                   -->   S2; return V\ntry pass Z else pass finally S2                     -->   S2\ntry pass Z else S1 finally S2                       -->   try S1 . else pass finally S2\ntry raise V except C as y: S Z else S1 finally S2   -->   try raise V Z else S1 finally S2          if  V = (C';B) and C != C'\ntry raise V except C as y: S Z else S1 finally S2   -->   try y=V; S . else pass finally S2         if  V = (C;B)\ntry raise V . else S1 finally S2                    -->   S2; raise V\n\n\n***** L | S --> L' | S' ************\n\nL  |  B; S                  -->     L'  |  B; S'                                    if  L | S --> L' | S'\n\nL  |  var z=V               -->     L,z=V  |  pass\nL,z=V  |  z = W             -->     L,z=W  |  pass\n\nL,l=(C;B)  |  l.x = V       -->     L,l=(C;B),x=V  |  pass                          if  x # B\nL,l=(C;B),x=W  |  l.x = V   -->     L,l=(C;B),x=V  |  pass\n\n\n***** B |- D ==> B *****************\n\nB  |-  def x(F): S          ==>     x = CLOS(B;F): S\nB  |-  actor x(F): S        ==>     x = ACTOR(CLOS(B;_self_,F):S)\nB  |-  class C(C'): M       ==>     C = CLASS(C'): B'                               if  B |- M ==> B'\nB  |-  D1; D2               ==>     B1; B2                                          if  B |- D1 ==> B1 and B |- D2 ==> B2\n\n\n***** B |- M ==> B *****************\n\nB  |-  x=y,M                ==>     x=V,B'                                          if  B |- x --> V and B |- M ==> B'\nB  |-  .                    ==>     .\n\n\n\n######################################### Global reduction #############################################\n\n\n***** B |- G --> G' ****************\n\nB  |-  G1, G2               -->     G1', G2                                         if  B |- G1 --> G1'\n\nB  |-  a:<L | QE[E]>        -->     a:<L' | QE[E']>                                 if  B |- L | E --> L' | E'\n\nB  |-  G                    -->     G'                                              if  G --> G'\n\n\n***** G --> G' *********************\n\na:<L | QE[ ASYNC(a,V)(R) ]>                               -->     a:<L | QE[ a.m ],m=V(R)>\na:<L | QE[ ASYNC(b,V)(R) ]>,  b:<L' | Q>                  -->     a:<L | QE[ b.m ]>,           b:<L' | Q,m=V(R)>\na:<L | QE[ ACTOR(V)(R) ]>                                 -->     a:<L | QE[ await b.m ]>,     b:< . | m=V(b,R)>\na:<L | QE[ await b.m ]>,      b:<L' | H,m=V,Q>            -->     a:<L | QE[ V ]>,             b:<L' | H,m=V,Q>\n\na:<L | QE[ await b.m ]>,      b:<L' | H,m=do raise V,Q>   -->     a:<L | QE[ do raise V ]>,    b:<L' | H,m=do raise V,Q>\n\n\n\n\nRecent decisions:\n- Mutable lists, dicts and sets are true class instances (although built-in)\n- Frozen lists, dicts and sets are true immutable class instances (although built-in)\n- Automatic coercion of mutable objects into immutable ones is abandoned for now (replaced by explicit conversion calls)\n- The 'protocol' and 'extension' declarations introduce static overloading, which gets translated into class declaration and explicit witness terms\n- Attribute selection can thus be overloaded, and supported on any type\n- Indexed selection and indexed update get translated to overloaded _getitem_ and _setitem_ calls, respectively\n- Built-in names int, float, str and bool are constructor/conversion functions, supporting multiple argument types via overloading\n- Class inheritance is single ancestor only (all other types of mix-ins are expressed as protocol adoption)\n- Classes are the only nominal types, and only these support the 'isinstance' primitive\n- Narrowing of the option type is done through ==None and !=None comparisons\n\n\n=========================================================================================================\n\nType inference:\n\n- Function arities always match\n- Short-hand positional arguments are preceeded by explicit keywords\n- Keyword arguments are in type order\n- Extra arguments are converted to explicit tupes/records\n- Missing arguments are replaced by explicit None values\n- Protocols and extensions are translated into classes\n- Overloaded names (global or attributes) are explicitly qualified by class\n- Binary and unary operators are replaced by their corresponding __op__ calls\n- Indexed and sliced expressions (Index/Slice) are replaced by __getitem__/__getslice__ calls\n- Assignments to indexed and sliced patterns (PIndex/PSlice) are replaced by __setitem__/__setslice__ calls\n\nNormalization:\n- All imported or built-in names are qualified by module, including those imported by 'from _ import'\n- All module aliases are replaced by their original module name\nX All parameters are positional\nX Parameter defaults are moved inside function definitions\n- Comprehensions are translated into loops\nX String literals are concatenated\n- Tuple (and list) patterns are replaced by a var pattern followed by explicit element assignments\n- For loops are replaced by while over iterators\n- With statemenmts are replaced by enter/exit prim calls + exception handling\nX The assert statement is replaced by a prim call ASSERT\n- The delete statement is replaced by (a sequence of) __delitem__ calls (for PIndex) or None assignments\nX Return without argument is replaced by return None\n- Incremental assignments are replaced by the corresponding __iop__ calls\n- The else branch of a while loop is replaced by an explicit if statement enclosing the loop\n\nDeactorization:\n\n- Every actor definition \n    \n    actor a(p): b\n\n  is translated into\n  \n    class _a():\n      def __init__(__self__,p):\n          b1                                deactorized b \\\\ bound b4\n      b2                                    deactorized b && bound b4\n    \n    class a():\n      def __init__(_this_,p):\n          _this_.__self__ = _a(p)           \n          b3                                bound(b) \\\\ decls \\\\ var\n      b4                                    stored b\n  \n  where\n  \n    - b1 contains all non-def statements in b, where each \"var z = e\" is replaced by \"__self__.z = e\"\n      and all local variables are referenced via __self__\n    \n    - b2 contains one \n    \n          def m(__self__,p):c1\n    \n      for each \"async def m(p):c\" in b, where c1 is c with all state and local names referenced via __self__\n    \n    - b3 contains one assignment\n    \n          _this_.x = _this_.__self__.x\n        \n      for every constant variable \"x\" defined in b\n    \n    - b4 contains one\n    \n          def m(_this_,p): return ASYNC(_this_.__self__, lambda: _this_.__self__.m(p))\n        \n      for each \"async def m(p):c\" in b\n\n- Every \"await e\" expression is translated into AWAIT(e)\n\nCPS transformation:\n\n- All potentially blocking functions receive continuations\n- All potentially blocking function calls are converted to tail calls that receive continuation arguments\n- All calls to continuation parameters are written as \"return CONT(cont,value)\"\n- Exception handlers are broken down into continuations and PUSH/POP calls\n- For loops are replaced by while over iterators\n\nLambda-lifting:\n\n- All function definitions are moved either to the top level or to the closest class\n- Functions lifted to the top level are closed via additional parameters\n- Functions lifted to a class are closed via additional self attributes\n- Top-level and method functions in non-calling contexts are replaced by closure constructions\n\nUNDECIDED:\n\n- Where is self-application (x.m(ps) --> x.m(x,ps)) performed?\n"
  },
  {
    "path": "workspace/Type-hierarchy.act",
    "content": "# Copyright (C) 2019-2021 Data Ductus AB\n#\n# Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:\n#\n# 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.\n#\n# 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.\n#\n# 3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission.\n#\n# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS \"AS IS\" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n#\n\n######################################### Type and class hierarchy ###############################################\n\nprotocol Eq:\n    @static\n    __eq__          : (Self,Self) -> bool\n    @static\n    __ne__          : (Self,Self) -> bool\n    \n    def __ne__(a,b):\n        return not (a == b)\n====>\n\"typeclass\" Eq[S]:\n    __eq__          : (S,S) -> bool\n    __ne__          : (S,S) -> bool\n\n    def __ne__(a,b):\n        return not (a == b)\n====>\nclass Eq[S]():\n    __eq__          : (S,S) -> bool\n    __ne__          : (S,S) -> bool\n\n    def __ne__(w,a,b):\n        return not w.__eq__(a,b)\n    \n-----------------------------------------------------------------\n\nclass Fruit (Eq):\n    def __eq__(a, b):\n        return a.weight == b.weight\n\nclass Apple (Fruit):\n    def __eq__(a, b):\n        return Fruit.__eq__(a,b) and a.appleness == b.appleness\n\nclass Orange (Fruit):\n    def __eq__(a, b):\n        return Fruit.__eq__(a,b) and a.orangeness == b.orangeness\n\na, b : Apple\na == b\nEq.__eq__(a,b)\nx, y : Orange\nx == y\nEq.__eq__(x,y)\nf1 : Fruit = a\nf2 : Fruit = x\nf1 == f2\na == x\nEq.__eq__(a,x)\n====>\nclass Fruit:\n    ...\n\"instance\" Eq[Fruit]:\n    def __eq__(a, b):\n        return a.weight == b.weight\nclass Apple (Fruit):\n    ...\n\"instance\" Eq[Apple]:\n    def __eq__(a, b):\n        return Fruit.__eq__(a,b) and a.appleness == b.appleness\nclass Orange (Fruit):\n    ...\n\"instance\" Eq[Orange]:\n    def __eq__(a, b):\n        return Fruit.__eq__(a,b) and a.orangeness == b.orangeness\n====>\nclass Fruit:\n    weight : int\n    \nclass Eq_Fruit[S(Fruit)] (Eq[S]):\n    def __eq__(w, a:S, b:S):\n        return Eq_int.__eq__(a.weight, b.weight)\n\nclass Apple (Fruit):\n    appleness : str\n\nclass Eq_Apple[S(Apple)] (Eq_Fruit[S]):\n    def __eq__(w, a:S, b:S):\n        return Eq_Fruit.__eq__(a,b) and Eq_str(a.appleness, b.appleness)\n\nclass Orange (Fruit):\n    orangeness : str\n\nclass Eq_Orange[S(Orange)] (Eq[S]):\n    def __eq__(w, a:S, b:S):\n        return Eq_Fruit.__eq__(a,b) and Eq_str(a.orangeness, b.orangeness)\n\na, b : Apple\nEq_Apple.__eq__(a,b)\nx, y : Orange\nEq_Orange.__eq__(x,y)\nf1 : Fruit = a\nf2 : Fruit = x\nEq_Fruit.__eq__(f1,f2)\nEq_Fruit.__eq__(a,x)\n\n-----------------------------------------------------------------\n\nprotocol Hashable (Eq):\n    __hash__        : () -> int\n====>\n\"typeclass\" (Eq[S]) => Hashable[S]:\n    __hash__        : (S) -> int\n====>\nclass Hashable[S] (Eq[S]):\n    __hash__        : (S) -> int\n\n-----------------------------------------------------------------\n\nclass Apa(Hashable):\n    x : int\n    def apa(self, y):\n        return self.hash() if y==0 else y\n    def hash(self):\n        return self.x + self.apa(1)\n\n====>\n\nclass Apa():\n    x : int\n    def apa(self, w:Hashable[Apa], y):\n        return w.hash(self) if y==0 else y\n\nclass Hashable_Apa (Hashable[Apa]):\n    def hash(w, self):\n        return self.x + self.apa(w,1)\n\n-----------------------------------------------------------------\n\nclass MyClass (Hashable):\n    attr1 : int\n    def __eq__(a, b):\n        return a.hash() == b.hash()\n    def hash(self):\n        return self.attr1\n    my_method: ()->int\n    def my_method(self):\n        return self.hash()\n        \nclass MySubClass (MyClass):\n    attr2 : int\n    def hash(self):\n        return fancy_hash(self.attr2)\n\nx, y : MySubClass\nz : MyClass = y\n\nx == y  -->  Eq.__eq__(x,y)  -->  MySubClass.hash(x) == MySubClass.hash(y)  -->  fancy_hash(x.attr2) == fancy_hash(y.attr2)\nx == z  -->  Eq.__eq__(x,z)  -->  MyClass.hash(x) == MyClass.hash(z)        -->  x.attr1 == z.attr1\n\ny.my_method()  -->  MySubClass.my_method(y)  -->  MySubClass.hash(y)  -->  fancy_hash(y.attr2)\nz.my_method()  -->  MySubClass.my_method(z)  -->  MyClass.hash(z)     -->  z.attr1\n\n====>\nclass MyClass:\n    def my_method(self):\n        return hash(self)\n\"instance\" Hashable[MyClass]:\n    def __hash__(self):\n        return self.attr1\n\"instance\" Eq[MyClass]:\n    def __eq__(a, b):\n        return hash(a) == hash(b)\nclass MySubClass (MyClass):\n    pass\n\"instance\" Hashable[MySubClass]:\n    def __hash__(self):\n        return fancy_hash(self.attr2)\n====>\n\nclass MyClass:\n    attr1 : int\n    my_method : (Hashable(Self))->int                   # Covariant in Self, since Hashable is a contravariant operator\n    def my_method(self, w:Hashable[Self]):              # Note: w:Hashable[MyClass] would render ny_method uninheritable in MySubClass\n        return w.hash(self)\n\nclass MySubClass (MyClass):\n    attr2 : int\n\nclass Hashable_MyClass[S(MyClass)] (Hashable[S]):\n    def __eq__(w, a:S, b:S):\n        return Eq_int.__eq__(w.hash(a), w.hash(b))\n    def hash(w, self:S):\n        return self.attr1\nclass Hashable_MySubClass[S(MySubClass)] (Hashable_MyClass[S]):\n    def hash(w, self:S):\n        return fancy_hash(self.attr2)\n\nx, y : MySubClass\nz : MyClass = y\n\nw0 : Hashable_MyClass\nw1 : Hashable_MySubClass\n\nx == y  -->  w1.__eq__(x,y)  -->  Hashable_MySubClass.hash(w1,x) == Hashable_MySubClass.hash(w1,y)  -->  fancy_hash(x.attr2) == fancy_hash(y.attr2)\nx == z  -->  w0.__eq__(x,z)  -->  Hashable_MyClass.hash(w0,x) == Hashable_MyClass.hash(w0,z)        -->  x.attr1 == z.attr1\n\ny.my_method()  -->  y.my_method(w1)  -->  MySubClass.my_method(y,w1)  -->  Hashable_MySubClass.hash(w1,y)  -->  fancy_hash(y.attr2)\nz.my_method()  -->  z.my_method(w2)  -->  MySubClass.my_method(z,w2)  -->  Hashable_MyClass.hash(w2,z)     -->  z.attr1\n\n# P1          ===     Obj(Self) [hash:Int, mymeth:Int, a1:Int]\n# Class(P1)   ===     [new:P1, hash:All(Self<P1)Self->Int, mymeth:All(Self<P1)Self->Int]\n# p1_class    ===     [new    = sigma(z:Class(P1)) obj(Self=P1) [hash = sigma(s:Self)z.hash(Self)(s), \n#                                                                mymeth = sigma(s:Self)z.mymeth(Self)(s), \n#                                                                a1 = sigma(s:Self)1],\n#                      hash   = lambda(Self<P1) lambda(s:Self) s.a1,\n#                      mymeth = lambda(Self<P1) lambda(s:Self) s.hash]\n#\n# P2          ===     Obj(Self) [hash:Int, mymeth:Int, a1:Int, a2:Int]\n# Class(P2)   ===     [new:P2, hash:All(Self<P2)Self->Int, mymeth:All(Self<P2)Self->Int]\n# p2_class    ===     [new    = sigma(z:Class(P2)) obj(Self=P2) [hash = sigma(s:Self)z.hash(Self)(s), \n#                                                                mymeth = sigma(s:Self)z.mymeth(Self)(s), \n#                                                                a1 = sigma(s:Self)1, \n#                                                                a2 = sigma(s:Self)2],\n#                      hash   = lambda(Self<P2) lambda(s:Self) fancy_hash(s.a2)\n#                      mymeth = p1_class.mymeth]\n\n-----------------------------------------------------------------\n    \nprotocol Ord (Eq):\n    @static\n    __lt__          : (Self,Self) -> bool\n    @static\n    __le__          : (Self,Self) -> bool\n    @static\n    __gt__          : (Self,Self) -> bool\n    @static\n    __ge__          : (Self,Self) -> bool\n\n    def __le__(a,b):\n        return a < b or a == b              # return Ord.__lt__(a,b) or Eq.__eq__(a,b)\n    def __gt__(a,b):\n        return b < a                        # return Ord.__lt__(b,a)\n    def __ge__(a,b):\n        return b <= a                       # return Ord.__le__(b,a)\n====>\n\"typeclass\" (Eq[S]) => Ord[S]:\n    __lt__          : (S,S) -> bool\n    __le__          : (S,S) -> bool\n    __gt__          : (S,S) -> bool\n    __ge__          : (S,S) -> bool\n\n    def __le__(a,b):\n        return a < b or a == b\n    def __gt__(a,b):\n        return b < a\n    def __ge__(a,b):\n        return b <= a\n====>\nclass Ord[S] (Eq[S]):\n    __lt__          : (S,S) -> bool\n    __le__          : (S,S) -> bool\n    __gt__          : (S,S) -> bool\n    __ge__          : (S,S) -> bool\n\n    def __le__(w,a,b):\n        return w.__lt__(a,b) or w.__eq__(a,b)\n    def __gt__(w,a,b):\n        return w.__lt__(b,a)\n    def __ge__(w,a,b):\n        return w.__le__(b,a)\n\n-----------------------------------------------------------------\n\nextension int (Eq):\n    def __eq__(a:int, b:int) -> bool:\n        return primeqint(a,b)\nextension int (Ord):\n    def __lt__(a:int, b:int) -> bool:\n        return primltint(a,b)\n    def __eq__(a:int, b:int) -> bool:             # Overrides int._eq_\n        return primeqint(a,b)\n====>\n\"instance\" Eq[int]:\n    def __eq__(a:int, b:int) -> bool:\n        return primeqint(a,b)\n\"instance\" Ord[int]:\n    def __lt__(a:int, b:int) -> bool:\n        return primltint(a,b)\n    def __eq__(a:int, b:int) -> bool:\n        return primeqint(a,b)\n====>\nclass Eq_int (Eq[int]):\n    def __eq__(w, a:int, b:int) -> bool:\n        return primeqint(a,b)\nclass Ord_int (Ord[int]):\n    def __lt__(w, a:int, b:int) -> bool:\n        return primltint(a,b)\nw1 : Eq[int] = Eq_int()\nw2 : Ord[int] = Ord_int()\n\n-----------------------------------------------------------------\n\nextension int (Ord):                                   # ALTERNATIVELY: A JOINT EXTENSION int (Ord) AND int (Eq)\n    def __eq__(a:int, b:int) -> bool:\n        return primeqint(a,b)\n    def __lt__(a:int, b:int) -> bool:\n        return primltint(a,b)\n====>\n\"instance\" Ord[int]:\n    def __eq__(a:int, b:int) -> bool:\n        return primeqint(a,b)\n    def __lt__(a:int, b:int) -> bool:\n        return primeqint(a,b)\n====>\nclass Ord_int (Ord[int]):\n    def __eq__(w, a:int, b:int) -> bool:\n        return primeqint(a,b)\n    def __lt__(w, a:int, b:int) -> bool:\n        return primeqint(a,b)\nw2 : Ord[int] = Ord_int()\nw1 : Eq[int] = w2\n\n-----------------------------------------------------------------\n\nprotocol SupportsInt:\n    __int__         : () -> int\n====>\n\"typeclass\" SupportsInt[S]:\n    __int__         : (S) -> int\n====>\nclass SupportsInt[S]():\n    __int__         : (S) -> int\n\n-----------------------------------------------------------------\n\nextension int (SupportsInt):\n    def __int__(self:int) -> int\n        return self\n====>\n\"instance\" SupportsInt[int]:\n    def __int__(self:int) -> int\n        return self\n====>\nclass SupportsInt_int (SupportsInt[int]):\n    def __int__(w, self:int) -> int\n        return self\n\n-----------------------------------------------------------------\n\nprotocol SupportsFloat:\n    __float__       : () -> float\n====>\n\"typeclass\" SupportsFloat[S]:\n    __float__       : (S) -> float\n====>\nclass SupportsFloat[S]():\n    __float__       : (S) -> float\n\n-----------------------------------------------------------------\n    \nprotocol SupportsComplex:\n    __complex__     : () -> complex\n====>\n\"typeclass\" SupportsComplex[S]:\n    __complex__     : (S) -> complex\n====>\nclass SupportsComplex[S]():\n    __complex__     : (S) -> complex\n\n-----------------------------------------------------------------\n\nprotocol SupportsBytes:\n    __bytes__       : () -> bytes\n====>\n\"typeclass\" SupportsBytes[S]:\n    __bytes__       : (S) -> bytes\n====>\nclass SupportsBytes[S]():\n    __bytes__       : (S) -> bytes\n\n-----------------------------------------------------------------\n\nprotocol Logical:\n    @static\n    __and__         : (Self,Self) -> Self\n    @static\n    __or__          : (Self,Self) -> Self\n    @static\n    __xor__         : (Self,Self) -> Self\n====>\n\"typeclass\" Logical[S]:\n    __and__         : (S,S) -> S\n    __or__          : (S,S) -> S\n    __xor__         : (S,S) -> S\n====>\nclass Logical[S]():\n    __and__         : (S,S) -> S\n    __or__          : (S,S) -> S\n    __xor__         : (S,S) -> S\n\n-----------------------------------------------------------------\n\nprotocol Plus:\n    @static\n    __add__         : (Self,Self) -> Self\n====>\n\"typeclass\" Plus[S]:\n    __add__         : (S,S) -> S\n====>\nclass Plus[S]():\n    __add__         : (S,S) -> S\n\n-----------------------------------------------------------------\n\nprotocol Minus:\n    @static\n    __sub__         : (Self,Self) -> Self\n====>\n\"typeclass\" Minus[S]:\n    __sub__         : (S,S) -> S\n====>\nclass Minus[S]():\n    __sub__         : (S,S) -> S\n\n-----------------------------------------------------------------\n\nprotocol Number (Ord, Plus, Minus):\n    __pos__         : () -> Self\n    __neg__         : () -> Self\n    @static\n    __mul__         : (Self,Self) -> Self\n    @static\n    __pow__         : (Self,Self) -> Self\n    def __sub__(a,b):\n        return a + (-b)\n====>\n\"typeclass\" (Ord[S], Plus[S], Minus[S]) => Number[S]:\n    __pos__         : (S) -> S\n    __neg__         : (S) -> S\n    __mul__         : (S,S) -> S\n    __pow__         : (S,S) -> S\n    def __sub__(a:S, b:S):\n        return __add__(a, __neg__(b))\n    \n====>\nclass Plus_Number[S] (Plus[S]):\n    _Number         : Number[S]\n    def __add__(w, a, b):\n        return w._Number.__add__(a, b)\nclass Minus_Number[S] (Minus[S]):\n    _Number         : Number[S]\n    def __sub__(w, a:S, b:S):                       # if __sub__ is NOT inherited from Minus\n        return w._Number.__sub__(a, b)\nclass Number[S] (Ord[S]):\n    _Plus           : Plus[S]\n    _Minus          : Minus[S]\n    __add__         : (S,S) -> S\n    __sub__         : (S,S) -> S\n    __pos__         : (S) -> S\n    __neg__         : (S) -> S\n    __mul__         : (S,S) -> S\n    __pow__         : (S,S) -> S\n    def __sub__(w, a, b):\n        return w.__add__(a, w.__neg__(b))\n\n\n-----------------------------------------------------------------\n\nextension int (Number):\n    def __pos__(self:int) -> int:\n        return self\n    def __neg__(self:int) -> int:\n        return primnegint(self)\n    def __add__(a:int, b:int) -> int:\n        return primaddint(a,b)\n    def __sub__(a:int, b:int) -> int:\n        return primaddint(a,b)\n    def __mul__(a:int, b:int) -> int:\n        return primmulint(a,b)\n    def __eq__(a:int, b:int) -> bool:\n        return primeqint(a,b)\n    def __lt__(a:int, b:int) -> bool:\n        return primltint(a,b)\n====>\n\"instance\" Number[int]:\n    def __pos__(self:int) -> int:\n        return self\n    def __neg__(self:int) -> int:\n        return primnegint(self)\n    def __add__(a:int, b:int) -> int:\n        return primaddint(a,b)\n    def __sub__(a:int, b:int) -> int:\n        return primaddint(a,b)\n    def __mul__(a:int, b:int) -> int:\n        return primmulint(a,b)\n    def __eq__(a:int, b:int) -> bool:\n        return primeqint(a,b)\n    def __lt__(a:int, b:int) -> bool:\n        return primltint(a,b)\n\n====>\nclass Plus_int (Plus_Number[int]):\n    def __add__(w, a:int, b:int) -> int:\n        return primaddint(a,b)\nclass Minus_int (Minus_Number[int]):\n    def __sub__(wit, a:int, b:int) -> int:\n        return primsubint(a,b)\n    # def __sub__(w, a:S, b:S):                                     # if not overridden, inherited from Minus_Number\n    #     return w._Number._Plus.__add__(a, w._Number.__neg__(b))\nclass Number_int (Number[int]):\n    def __init__(w):\n        w._Plus = Plus_int(w)\n        w._Minus = Minus_int(w)\n    def __pos__(e, self:int) -> int:\n        return self\n    def __neg__(w, self:int) -> int:\n        return primnegint(self)\n    def __mul__(w, a:int, b:int) -> int:\n        return primmulint(a,b)\n    def __eq__(w, a:int, b:int) -> bool:\n        return primeqint(a,b)\n    def __lt__(w, a:int, b:int) -> bool:\n        return primltint(a,b)\n\n-----------------------------------------------------------------\n\nprotocol SupportsAbs:\n    __abs__         : () -> Self\n====>\n\"typeclass\" SupportsAbs[S]:\n    __abs__         : (S) -> S\n====>\nclass SupportsAbs[S]():\n    __abs__         : (S) -> S\n\n-----------------------------------------------------------------\n\nprotocol Complex (Number, SupportsAbs, SupportsComplex):\n    @static\n    __fromcomplex__ : (complex) -> Self\n    @static\n    __div__         : (Self,Self) -> Self\n    real            : () -> Real\n    imag            : () -> Real\n    conjugate       : () -> Self\n====>\n\"typeclass\" (Number[S],SupportsAbs[S],SupportsComplex[S]) => Complex[S]:\n    __fromcomplex__ : (complex) -> S\n    __div__         : (S,S) -> S\n    real            : (S) -> EXISTS[T,Real[T]]\n    imag            : (S) -> EXISTS[T,Real[T]]\n    conjugate       : (S) -> S\n====>\nclass SupportsAbs_Complex[S] (SupportsAbs[S]):\n    _Complex        : Complex[S]\nclass SupportsComplex_Complex[S] (SupportsComplex[S]):\n    _Complex        : Complex[S]\nclass Complex[S] (Number[S]):\n    _SuppAbs        : SupportsAbs[S]\n    _SuppComplex    : SupportsComplex[S]\n\n    __fromcomplex__ : (complex) -> S\n    __div__         : (S,S) -> S\n    real            : (S) -> EXISTS[T,Real[T]]\n    imag            : (S) -> EXISTS[T,Real[T]]\n    conjugate       : (S) -> S\n\n-----------------------------------------------------------------\n\nprotocol SupportsRound:\n    __round__       : () -> int\n====>\n\"typeclass\" SupportsRound[S]:\n    __round__       : (S) -> int\n====>\nclass SupportsRound[S]():\n    __round__       : (S) -> int\n\n-----------------------------------------------------------------\n\nprotocol Real (Complex, SupportsRound, SupportsFloat):\n    @static\n    __fromfloat__   : (float) -> Self\n    __trunc__       : () -> Integral\n    __floor__       : () -> Integral\n    __ceil__        : () -> Integral\n    @static\n    __divmod__      : (Self,Self) -> (Self,Self) \n    @static\n    __floordiv__    : (Self,Self) -> Integral    \n    @static\n    __mod__         : (Self,Self) -> Self        \n\n    def __complex__(a):\n        return complex(float(a))\n    def real(a):\n        return fromfloat(float(a))\n    def imag(a):\n        return fromfloat(0.0)\n    def conjugate(a):\n        return a\n    def divmod(a,b):\n        return (a//b, a%b)\n====>\n\"typeclass\" (Complex[S],SupportsRound[S],SupportsFloat[S]) => Real[S]:\n    __fromfloat__   : (float) -> S\n    __trunc__       : (S) -> EXISTS[T,Intergral[T]]\n    __floor__       : (S) -> EXISTS[T,Intergral[T]]\n    __ceil__        : (S) -> EXISTS[T,Intergral[T]]\n    __divmod__      : (S,S) -> (S,S)\n    __floordiv__    : (S,S) -> EXISTS[T,Intergral[T]]\n    __mod__         : (S,S) -> S\n\n    def __complex__(a):\n        return complex(float(a))\n    def real(a):\n        return a\n    def imag(a):\n        return 0\n    def conjugate(a):\n        return a\n    def divmod(a,b):\n        return (a//b, a%b)\n====>\nclass Plus_Real[S] (Plus_Complex[S]):\n    _Real           : Real[S]\nclass Minus_Real[S] (Minus_Complex[S]):\n    _Real           : Real[S]\nclass SupportsAbs_Real[S] (SupportsAbs_Complex[S]):\n    _Real           : Real[S]\nclass SupportsComplex_Real[S] (SupportsComplex_Complex[S]):\n    _Real           : Real[S]\nclass SupportsRound_Real[S] (SupportsRound[S]):\n    _Real           : Real[S]\nclass SupportsFloat_Real[S] (SupportsFloat[S]):\n    _Real           : Real[S]\nclass Real[S] (Complex[S]):\n    _SuppRound      : SupportsRound[S]\n    _SuppFloat      : SupportsFloat[S]\n    \n    __fromfloat__   : (float) -> S\n    __trunc__       : (S) -> EXISTS[T,Intergral[T]]\n    __floor__       : (S) -> EXISTS[T,Intergral[T]]\n    __ceil__        : (S) -> EXISTS[T,Intergral[T]]\n    __divmod__      : (S,S) -> (S,S)\n    __floordiv__    : (S,S) -> EXISTS[T,Intergral[T]]\n    __mod__         : (S,S) -> S\n\n    def __complex__(w,a):\n        return w.__complex__(w.__float__(a))\n    def real(cls,_w,a):\n        return _w.__fromfloat__(cls.__float__(a))\n    def imag(cls,_w,a):\n        return _w.__fromfloat__(0.0)\n    def conjugate(cls,a):\n        return a\n    def divmod(cls,a,b):\n        return (cls.__floordiv__(a,b), cls.__mod__(a,b))\n\n-----------------------------------------------------------------\n\nprotocol Rational (Real):\n    numerator       : () -> Integral\n    denominator     : () -> Integral\n    \n    def __float__(a):\n        return numerator(a) / denominator(a)\n====>\n\"typeclass\" (Real[S]) => Rational[S]:\n    numerator       : (Integral[T]) => (S) -> T\n    denominator     : (Integral[T]) => (S) -> T\n\n    def __float__(a):\n        return numerator(a) / denominator(a)\n====>\nclass Plus_Rational[S] (Plus_Real[S]):\n    _Number         = Rational\nclass Minus_Rational[S] (Minus_Real[S]):\n    _Number         = Rational\nclass SupportsAbs_Rational[S] (SupportsAbs_Real[S]):\n    _Complex        = Rational\nclass SupportsComplex_Rational[S] (SupportsComplex_Real[S]):\n    _Complex        = Rational\nclass SupportsRound_Rational[S] (SupportsRound_Real[S]):\n    _Real           = Rational\nclass SupportsFLoat_Rational[S] (SupportsFLoat_Real[S])\n    _Real           = Rational\n\n    def __float__(cls,a):\n        Int = Integral_int\n        return Real_float.__div__(Int._SuppFloat.__float__(cls._Rational.numerator(Int,a)), \n                                  Int._SuppFloat.__float__(cls._Rational.denominator(Int,a)))\n\nclass Rational[S] (Real[S]):\n    _Plus           = Plus_Rational\n    _Minus          = Minus_Rational\n    _SuppAbs        = SupportsAbs_Rational\n    _SuppComplex    = SupportsComplex_Rational\n    _SuppRound      = SupportsRound_Rational\n    _SuppFloat      = SupportsFloat_Rational\n    \n    numerator       : (@Integral[T], S) -> T\n    denominator     : (@Integral[T], S) -> T\n    \n-----------------------------------------------------------------\n\nprotocol Integral (Rational,SupportsInt,Logical):\n    @static\n    __fromint__     : (int) -> Self\n    __index__       : () -> Self\n    @static\n    __lshift__      : (Self,Self) -> Self\n    @static\n    __rshift__      : (Self,Self) -> Self\n    __invert__      : () -> Self\n    \n    def __index__(a):\n        return int(a)\n    def __lshift__(a,b):\n        return fromint(int(a) << int(b))\n    def __invert__(a):\n        return fromint(~int(a))\n    def __float__(a):\n        return float(int(a))\n    def numerator(a):\n        return a\n    def denominator(a):\n        return 1\n====>\n\"typeclass\" (Rational[S],SupportsInt[S],Logical[S]) => Integral[S]:\n    __fromint__     : (int) -> S\n    __index__       : (S) -> S\n    __lshift__      : (S,S) -> S\n    __rshift__      : (S,S) -> S\n    __invert__      : (S) -> S\n\n    def __index__(a):\n        return int(a)\n    def __lshift__(a,b):\n        return fromint(int(a) << int(b))\n    def __float__(a):\n        return float(int(a))\n    def numerator(a):\n        return a\n    def denominator(a):\n        return 1\n====>\nclass Plus_Integral[S] (Plus_Rational[S]):\n    _Number         = Integral\nclass Minus_Integral[S] (Minus_Rational[S]):\n    _Number         = Integral\nclass SupportsAbs_Integral[S] (SupportsAbs_Rational[S]):\n    _Complex        = Integral\nclass SupportsComplex_Integral[S] (SupportsComplex_Rational[S]):\n    _Complex        = Integral\nclass SupportsRound_Integral[S] (SupportsRound_Rational[S]):\n    _Real           = Integral\nclass SupportsFLoat_Integral[S] (SupportsFLoat_Rational[S])\n    _Real           = Integral\nclass SupportsInt_Integral[S] (SupportsInt[S])\n    _Integral       = Integral\nclass Logical_Integral[S] (Logical[S])\n    _Integral       = Integral\nclass Integral[S] (Rational[S]):\n    _Plus           = Plus_Integral\n    _Minus          = Minus_Integral\n    _SuppAbs        = SupportsAbs_Integral\n    _SuppComplex    = SupportsComplex_Integral\n    _SuppRound      = SupportsRound_Integral\n    _SuppFloat      = SupportsFloat_Integral\n    _SuppInt        = SupportsInt_Integral\n    _Logical        = Logical_Integral\n    \n    @static\n    __fromint__     : (int) -> S\n    __index__       : (S) -> S\n    __lshift__      : (S,S) -> S\n    __rshift__      : (S,S) -> S\n    __invert__      : (S) -> S\n\n    def __index__(cls,a):\n        return cls._SuppInt.__int__(a)\n    def __lshift__(cls,a,b):\n        return cls.__fromint__(Integral_int.__lshift__(cls._SuppInt.__int__(a), cls._SuppInt.__int__(b)))\n    def __invert__(cls,a):\n        return cls.__fromint__(Integral_int.__invert__(cls._SuppInt.__int__(a)))\n    def __float__(cls,a):\n        return Integral_int._SuppFloat.__float__(cls._SuppInt.__int__(a))\n    def numerator(cls,_w,a):\n        return _w.__fromint__(cls.__SuppInt.__int__(a))\n    def denominator(cls,_w,a):\n        return _w.__fromint__(0)\n\n-----------------------------------------------------------------\n\nextension int (Integral):\n    def __fromint__(a):\n        return a\n    def __int__(self):\n        return self\n    def __and__(a,b):\n        return prinandint(a,b)\n====>    \n\"instance\" Integral[int]:\n    def __fromint__(a):\n        return a\n    def __int__(self):\n        return self\n    def __and__(a,b):\n        return prinandint(a,b)\n====>\nclass Plus_Rational_int (Plus_Rational[int]):\n    _Number         = Integral_int\nclass Minus_Rational_int (Minus_Rational[int]):\n    _Number         = Integral_int\nclass SupportsAbs_Integral_int (SupportsAbs_Integral[int]):\n    _Complex        = Integral_int\nclass SupportsComplex_Integral_int (SupportsComplex_Integral[int]):\n    _Complex        = Integral_int\nclass SupportsRound_Integral_int (SupportsRound_Integral[int]):\n    _Real           = Integral_int\nclass SupportsFloat_Integral_int (SupportsFloat_Integral[int]):\n    _Real           = Integral_int\nclass SupportsInt_Integral_int (SupportsInt_Integral[int]):\n    _Integral       = Integral_int\n    def __int__(cls,self):\n        return self\nclass Logical_Integral_int (Logical_Integral[int]):\n    _Integral       = Integral_int\n    def __and__(cls,a,b):\n        return prinandint(a,b)\nclass Integral_int (Integral[int]):\n    _Plus           = Plus_Integral_int\n    _Minus          = Minus_Integral_int\n    _SuppAbs        = SupportsAbs_Integral_int\n    _SuppComplex    = SupportsComplex_Integral_int\n    _SuppRound      = SupportsRound_Integral_int\n    _SuppFloat      = SupportsFloat_Integral_int\n    _SuppInt        = SupportsInt_Integral_int\n    _Logical        = Logical_Integral_int\n    def __fromint__(cls,a):\n        return a\n\n-----------------------------------------------------------------\n\nextension bool (Logical,Ord):\n    def __and__(a,b):\n        return b if a else False\n    def __eq__(a,b):\n        return primeqbool(a,b)\n    def __lt__(a,b):\n        return a == False and b == True\n====>\n\"instance\" Ord[bool]\n    def __eq__(a,b):\n        return primeqbool(a,b)\n    def __lt__(a,b):\n        return a == True and b == False\n\"instance\" Logical[bool]:\n    def __and__(a,b):\n        return b if a else False\n====>\nclass Ord_bool (Ord[bool]):\n    _Logical = Logical_bool\n    def __eq__(cls,a,b):\n        return primeqbool(a,b)\n    def __lt__(cls,a,b):\n        return cls.__eq__(a,True) and cls.__eq__(b,False)\nclass Logical_bool (Logical[bool]):\n    _Ord = Ord_bool\n    def __and__(a,b):\n        return b if a else False\n\n-----------------------------------------------------------------\n\nextension bool (Logical):\n    def __and__(a,b):\n        return b if a else False\nextension bool (Ord):\n    def __eq__(a,b):\n        return primeqbool(a,b)\n    def __lt__(a,b):\n        return a == False and b == True\n====>\n\"instance\" Ord[bool]\n    def __eq__(a,b):\n        return primeqbool(a,b)\n    def __lt__(a,b):\n        return a == True and b == False\n\"instance\" Logical[bool]:\n    def __and__(a,b):\n        return b if a else False\n====>\nclass Ord_bool (Ord[bool]):\n    def __eq__(cls,a,b):\n        return primeqbool(a,b)\n    def __lt__(cls,a,b):\n        return cls.__eq__(a,True) and cls.__eq__(b,False)\nclass Logical_bool (Logical[bool]):\n    def __and__(a,b):\n        return b if a else False\n\n-----------------------------------------------------------------\n\nprotocol IncrementalLogical[A] (Logical):\n    __iand__        : !(A) -> None\n    __ior__         : !(A) -> None\n    __ixor__        : !(A) -> None\n====>\n\"typeclass\" (Logical[S]) => IncrementalLogical[S,A]:\n    __iand__        : !(S,A) -> None\n    __ior__         : !(S,A) -> None\n    __ixor__        : !(S,A) -> None\n====>\nclass IncrementalLogical[S,A] (Logical[S])\n    __iand__        : !(S,A) -> None\n    __ior__         : !(S,A) -> None\n    __ixor__        : !(S,A) -> None\n\n-----------------------------------------------------------------\n\nprotocol IncrementalPlus[A] (Plus):\n    __iadd__        : !(A) -> None\n====>\n\"typeclass\" (Plus[S]) => IncrementalPlus[S,A]:\n    __iadd__        : !(S,A) -> None\n====>\nclass IncrementalPlus[S,A] (Plus[S]):\n    __iadd__        : !(S,A) -> None\n\n-----------------------------------------------------------------\n\nprotocol IncrementalMinus[A] (Minus):\n    __isub__        : !(A) -> None\n====>\n\"typeclass\" (Minus[S]) => IncrementalMinus[S,A]:\n    __isub__        : !(S,A) -> None\n====>\nclass IncrementalMinus[S,A] (Minus[S]):\n    __isub__        : !(S,A) -> None\n\n-----------------------------------------------------------------\n    \nprotocol Foldable[A]:\n    __fold__        : ((A,B)->B, B) -> B\n====>\n\"typeclass\" Foldable[S,A]:\n    __fold__        : (S, (A,B)->B, B) -> B\n====>\nclass Foldable[S,A]():\n    __fold__        : (S, (A,B)->B, B) -> B\n\n-----------------------------------------------------------------\n\n### The collection hierarchy (from typing.py)\n\nprotocol Iterable[A]:\n    __iter__        : () -> Iterator[A]\n====>\n\"typeclass\" Iterable[S,A]:\n    __iter__        : (S) -> Iterator[A]\n====>\nclass Iterable[S,A]():\n    __iter__        : (S) -> Iterator[A]\n\n-----------------------------------------------------------------\n\nclass Iterator[A] (Iterable[A]):                   # MUTUAL RECURSION BETWEEN TYPE AND PROTOCOL\n    __next__        : !() -> A\n    \n    def __iter__(self): return self\n====>\nclass Iterator[A]():\n    __next__        : !() -> A\n\"instance\" Iterable[Iterator[A],A]:\n    def __iter__(self): return self\n====>\nclass Iterator[A]():\n    __next__        : !() -> A\nclass Iterable_Iterator (Iterable[Iterator[A],A]):\n    def __iter__(cls,self): return self\n\n-----------------------------------------------------------------\n\nprotocol Reversible[A] (Iterable[A]):\n    __reversed__    : () -> Self\n====>\n\"typeclass\"  (Iterable[S,A]) => Reversible[S,A]:\n    __reversed__    : (S) -> S\n====>\nclass  Reversible[S,A] (Iterable[S,A]):\n    __reversed__    : (S) -> S\n\n-----------------------------------------------------------------\n\nprotocol Container[A]:\n    __contains__    : (A) -> bool\n====>\n\"typeclass\" Container[S,A]:\n    __contains__    : (S,A) -> bool\n====>\nclass Container[S,A]():\n    __contains__    : (S,A) -> bool\n\n-----------------------------------------------------------------\n\nprotocol Sized:\n    __len__         : () -> int\n====>\n\"typeclass\" Sized[S]:\n    __len__         : (S) -> int\n====>\nclass Sized[S]():\n    __len__         : (S) -> int\n\n-----------------------------------------------------------------\n\nprotocol Indexed[A,B]:\n    __getitem__     : (A) -> B\n====>\n\"typeclass\" Indexed[S,A,B]:\n    __getitem__     : (S,A) -> B\n====>\nclass Indexed[S,A,B]():\n    __getitem__     : (S,A) -> B\n\n-----------------------------------------------------------------\n\nprotocol Sliceable:\n    __getslice__    : (int?,int?,int?) -> Self\n====>\n\"typeclass\" Sliceable[S]:\n    __getslice__    : (S,int?,int?,int?) -> S\n====>\nclass Sliceable[S,A]():\n    __getslice__    : (S,int?,int?,int?) -> S\n\n-----------------------------------------------------------------\n\nprotocol Collection[A] (Container[A], Sized, Iterable[A]):\n    __fromiter__    : (Iterable[A]) -> Self\n====>\n\"typeclass\" (Container[S,A], Sized[S], Iterable[S,A]) => Collection[S,A]:\n    __fromiter__    : (Iterable[T,A]) => (T) -> S\n====>\nclass Sized_Collection[S,A] (Sized[S]):\n    _Collection     : @Collection[A]\nclass Iterable_Collection[S,A] (Iterable[S,A]):\n    _Collection     : @Collection[A]\nclass Collection[S,A] (Container[S,A]):\n    _Sized          : @Sized_Collection[S,A]\n    _Iterable       : @Iterable_Collection[S,A]\n\n    __fromiter__    : (@Iterable[A],T) -> S\n\n-----------------------------------------------------------------\n\nprotocol Set[A] (Collection[A], Ord, Logical, Minus):\n    isdisjoint      : (Set[A]) -> bool\n\n    def __le__(a: Self, b: Self):\n        if len(a) > len(b):\n            return False\n        for elem in a:\n            if elem not in b:\n                return False\n        return True\n    def __lt__(a: Self, b: Self):\n        if len(a) >= len(b):\n            return False\n        for elem in a:\n            if elem not in b:\n                return False\n        return True\n    def __eq__(a: Self, b: Self):\n        return len(a) == len(b) and a <= b\n    def __or__(a: Self, b: Self):\n        chain = [ e for s in [a,b] for e in s ]\n        return fromiter(chain)\n    def isdisjoint(self: Self, other: Set[A]):\n        for value in b:\n            if value in self:\n                return False\n        return True\n====>\n\"typeclass\" (Collection[S,A], Ord[S], Logical[S], Minus[S]) => Set[S,A]:\n    isdisjoint      : (Set[T,A]) => (S,T) -> bool\n\n    def __le__(a: S, b: S):\n        if len(a) > len(b):\n            return False\n        for elem in a:\n            if elem not in b:\n                return False\n        return True\n    def __lt__(a: S, b: S):\n        if len(a) >= len(b):\n            return False\n        for elem in a:\n            if elem not in b:\n                return False\n        return True\n    def __eq__(a: S, b: S):\n        return len(a) == len(b) and a <= b\n    def __or__(a: S, b: S):\n        chain = [ e for s in [a,b] for e in s ]\n        return fromiter(chain)\n    def (Set[T,A]) => isdisjoint(self: S, other: T):\n        for value in b:\n            if value in self:\n                return False\n        return True\n====>\nclass Sized_Set[S,A] (Sized_Collection[S]):\n    _Set            : @Set[S,A]\nclass Iterable_Set[S,A] (Iterable_Collection[S,A]):\n    _Set            : @Set[S,A]\nclass Ord_Set[S,A] (Ord[S]):\n    _Set            : @Set[S,A]\n    def __le__(cls, a:S, b:S):\n        if Ord_int.__gt__(cls._Set._Sized.__len__(a), cls._Set._Sized.__len__(b)):\n            return False\n        for elem in cls._Set._Iterable.__iter__(a):\n            if not cls._Set.__contains__(b,elem):\n                return False\n        return True\n    def __lt__(cls, a:S, b:S):\n        if Ord_int.__ge__(cls._Set._Sized.__len__(a), cls._Set._Sized.__len__(b)):\n            return False\n        for elem in cls._Set._Iterable.__iter__(a):\n            if not cls._Set.__contains__(b,elem):\n                return False\n        return True\n    def __eq__(cls, a: S, b: S):\n        return Eq_int.__eq__(cls._Set._Sized.__len__(a), cls._Set._Sized.__len__(b)) and cls.__le__(a,b)\nclass Logical_Set[S,A] (Logical[S]):\n    _Set            : @Set[S,A]\n    def __or__(cls, a: S, b: S):\n        chain = [ e for s in Iterable_list.__iter__([a,b]) for e in cls._Set._Iterable.__iter__(s) ]\n        return cls.__fromiter__(Iterable_list,chain)\nclass Minus_Set[S,A] (Minus[S]):\n    _Set            : @Set[S,A]\nclass Set[S,A] (Collection[S,A]):\n    _Sized          : @Sized_Set[S,A]\n    _Iterable       : @Iterable_Set[S,A]\n    _Ord            : @Ord_Set[S,A]\n    _Logical        : @Logical_Set[S,A]\n    _Minus          : @Minus_Set[S,A]\n    \n    isdisjoint      : (@Set[T,A],S,T) -> bool\n\n    def isdisjoint(cls:@Self, _q:@Set[T,A]), self:S, other:T):\n        for value in _q._Iterable.__iter__(other):\n            if cls.__contains__(value):\n                return False\n        return True\n\n-----------------------------------------------------------------\n\nextension Set[A (Hashable)] (Hashable):\n    def __hash__(self):\n        n = 12345\n        for k in self:\n            n += hash(k)\n        return n\n====>\n\"instance\" (Hashable[A], Set[S,A]) => Hashable[S]:\n    def __hash__(self):\n        n = 12345\n        for k in self:\n            n += hash(k)\n        return n\n====>\n\ndef Hashable_Set[S,A] (_qual: @Hashable[A], _Set: @Set[S,A]) -> @Hashable[S]:\n    \n    class Hashable_Set[S,A] (Hashable[S]):    \n        def __hash__(cls: class Self, self:S):\n            n = 12345\n            for k in _Set._Iterable.__iter__(self):\n                n += _qual.__hash__(k)\n            return n\n    \n    return Hashable_Set\n\n-----------------------------------------------------------------\n\nclass frozenset[A (Hashable)] (Set[A], Hashable):\n    _val        : frozendict[A,()]                          # HYPOTHETICAL!\n\n    def __contains__(self, a):\n        return a in self._val.keys()\n    def __fromiter__(items: Iterable[A]):\n        return frozenset(_val = { i:() for i in items })\n    def __len__(self):\n        return len(self._val)\n    def __iter__(self):\n        return iter(self._val.keys())\n====>\n\"qualified struct\" (Hashable[A]) => frozenset[A]:\n    _val        : frozendict[A,()]\n    \n\"instance\" (Hashable[A]) => Set[frozenset[A],A]:\n    def __contains__(self, a):\n        return a in self._val.keys()\n    def (Iterable[T,A]) => __fromiter__(items: T):\n        return frozenset(_val = { i:() for i in items })\n\n    def __len__(self):\n        return len(self._val)\n    def __iter__(self):\n        return iter(self._val.keys())\n\"instance\" (Hashable[A]) => Hashable[frozenset[A]]:\n    def __hash__(self): ...\n        n = 12345\n        for i in self._val.keys():\n            n += hash(i)\n        return n\n====>\nclass frozenset[A]():\n    _qual           = Hashable\n    _val            : frozendict[A,()]\n\ndef Set_frozenset[A](_qual: @Hashable[A]) -> @Set[frozenset[A],A]:\n    \n    class Sized_frozenset[A] (Sized_Set[frozenset[A],A]):\n        _Collection     = Set_frozenset\n        _Set            = Set_frozenset\n        def __len__(cls,self):\n            return len(self._val)\n    class Iterable_frozenset[A] (Iterable_Set[frozenset[A],A]):\n        _Collection     = Set_frozenset\n        _Set            = Set_frozenset\n        def __iter__(cls,self):\n            return iter(self._val.keys())\n    class Ord_frozenset[A] (Ord_Set[frozenset[A],A]):\n        _Set            = Set_frozenset\n    class Logical_frozenset[A] (Logical_Set[frozenset[A],A]):\n        _Set            = Set_frozenset\n    class Minus_frozenset[A] (Minus_Set[frozenset[A],A]):\n        _Set            = Set_frozenset\n    class Set_frozenset[A] (Set[frozenset[A],A]):\n        _Sized          = Sized_frozenset\n        _Iterable       = Iterable_frozenset\n        _Ord            = Ord_frozenset\n        _Logical        = Logical_frozenset\n        _Minus          = Minus_frozenset\n        def __contains__(cls,self,a):\n            return Mapping_frozendict.__contains__(self._val,a)\n        def __fromiter__(_qual: @Iterable[T,A], items: T):\n            return frozenset(_val = { i:() for i in _qual.__iter__(items) })\n\n    return Set_frozenset\n\n####### Minus_frozenset[A] < Minus_Set[frozenset[A],A] < Minus[frozenset[A]]\n## But assume frozensubset[A] < frozenset[A]\n## and Minus_frozensubset[A] < Minus_frozenset[A]\n## Can we inherit _sub_ from Minus_frozenset in Minus_frozensubset?\n## Minus_frozenset._sub_ : (frozenset[A],frozenset[A])->frozenset[A] </ Minus_frozensubset._sub_ : (frozensubset[A],frozensubset[A])->frozensubset[A]\n## Answer is NO!\n## But had we instead defined\n####### Minus_frozenset[A,S(frozenset[A])] < Minus_Set[S,A] < Minus[S]\n## and\n####### Minus_frozensubset[A,S(frosensubset[A])] < Minus_frozenset[A,S]\n## Then\n## Minus_frozenset._sub_ : [S(frozenset[A])]=>(S,S)->S < Minus_frozensubset._sub_ : [S(frozensubset[A])]=>(S,S)->S \n## I.e., Minus_frozenset._sub_ would be inheritable!\n## But then the question is of course how to implement a generic Minus_frozenset._sub_ with type (S,S)->S that works for all S < frozenset...\n## Conclusion: perhaps better stick to the non-inheritable version and ask all subclasses of frozenset for a reimplementation of _sub_\n\n## Can we direct the translation on basis of what the type of Minus_frozenset._sub_ is?\n## That is, if the inferred type is indeed [S(frozenset)]=>(S,S)->S, then the translation \n## Minus_frozenset[A,S(frozenset[A])] (Minus_Set[S,A]) is chosen and Minus_frozenset._sub_ is available to inherit\n## Otherwise then translation defaults to Minus_frozenset[A] (Minus_Set[frozenset[A],A])\n## Hmm, isn't this just translating the extension frozenset (Minus) on basis of the most general method types inferred?\n## Yes, it is!\n\n## Conclusion: how to translate extension declarations will be based on inferred types.\n## And whether a method can be inherited or not will also be determined entirely by the type-checker.\n\n\ndef Hashable_frozenset[A](_qual: @Hashable[A]) -> @Hashable[frozenset[A]]:\n    class Hashable_frozenset[A] (Hashable[frozenset[A]]):\n        def __hash__(cls, self): ...\n            n = 12345\n            for k in Mapping_frozendict._Iterable.__iter__(self._val):\n                n += _qual.__hash__(k)\n            return n\n    \n    return Hashable_frozenset\n\n---\n\nSized_frozenset_str = Sized_frozenset(Hashable_str)\nHashable_frozenset_str = Hashable_Set(Hashable_str, Set_frozenset_str)\n\n---\n\nx : frozenset[str]\nx = frozenset([\"apa\",\"bepa\"])\ny = hash(x)\nz = x.single()\n====>\nx : frozenset[str]\nx = frozenset([\"apa\",\"bepa\"])\ny = __hash__(x)\nz = x.single()\n====>\nx : frozenset[str]\nx = frozenset([\"apa\",\"bepa\"])\ny = Hashable_frozenset_str.__hash__(x)\nz = frozenset.single(x)\n\n---\n\nclass coloredset[A (Hashable)] (frozenset[A]):\n    color           : str\n    \n    def isblue(self):\n        return self.color == \"blue\"\n====>\n\"qualified struct\" (Hashable[A]) => coloredset[A] (frozenset[A])\n    color           : str\n    \n    def isblue(self):\n        return self.color == \"blue\"\n====>\nclass coloredset[A] (frozenset[A])\n    color           : str\n\n    def isblue      : () -> bool\n    def isblue(self:Self):\n        return self.color == \"blue\"\n\n-----------------------------------------------------------------\n\nprotocol MutableIndexed[A,B] (Indexed[A,B]):\n    __setitem__     : !(A,B) -> None\n    __delitem__     : !(A) -> None\n====>\n\"typeclass\" (Indexed[S,A,B]) => MutableIndexed[S,A,B]:\n    __setitem__     : !(S,A,B) -> None\n    __delitem__     : !(S,A) -> None\n====>\nclass MutableIndexed[S,A,B] (Indexed[S,A,B]):\n    __setitem__     : !(S,A,B) -> None\n    __delitem__     : !(S,A) -> None\n\n-----------------------------------------------------------------\n\nprotocol MutableSet[A] (Set[A], IncrementalLogical[Set[A]], IncrementalMinus[Set[A]]):\n    add             : !(A) -> None\n    pop             : !() -> A\n    clear           : !() -> None\n    \n    def clear(self: Self):\n        try:\n            while True:\n                self.pop()\n        except KeyError:\n            pass\n\n    def __ior__(self: Self, other: Set[A]):\n        for value in other:\n            self.add(value)\n====>\n\"typeclass\" (Set[S,A], IncrementalLogical[S,EXISTS[T,Set[T,A]], IncrementalMinus[S,EXISTS[T,Set[T,A]]) => MutableSet[S,A]:\n    add             : !(A,A) -> None\n    pop             : !(S) -> A\n    clear           : !(S) -> None\n    def clear(self: S):\n        try:\n            while True:\n                self.pop()\n        except KeyError:\n            pass\n    def __ior__(self: S, other: Set[A]):\n        for value in other:\n            self.add(value)\n====>\nclass Sized_MutableSet[S,A] (Sized_Set[S,A]):\n    _MutableSet         : MutableSet[S,A]\nclass Iterable_MutableSet[S,A] (Iterable_Set[S,A]):\n    _MutableSet         : MutableSet[S,A]\nclass Ord_MutableSet[S,A] (Ord_Set[S,A]):\n    _MutableSet         : MutableSet[S,A]\nclass Logical_MutableSet[S,A] (Logical_Set[S,A]):\n    _MutableSet         : MutableSet[S,A]\nclass Minus_MutableSet[S,A] (Minus_Set[S,A]):\n    _MutableSet         : MutableSet[S,A]\nclass IncrementalLogical_MutableSet[S,A] (IncrementalLogical[S,EXISTS[T,Set[T,A]]):\n    _MutableSet         : MutableSet[S,A]\n    def __ior__(cls,self: S, other: EXISTS[T,Set[T,A]):\n        for value in other._protocol._Iterable.__iter__(other._element):\n            cls._MutableSet.add(value)\nclass IncrementalMinus_MutableSet[S,A] (IncrementalMinus[S,EXISTS[T,Set[T,A]]):\n    _MutableSet         : MutableSet[S,A]\nclass MutableSet[S,A] (Set[S,A]):\n    _Sized              : Sized_MutableSet[S,A]\n    _Iterable           : Iterable_MutableSet[S,A]\n    _Ord                : Ord_MutableSet[S,A]\n    _Logical            : Logical_MutableSet[S,A]\n    _Minus              : Minus_MutableSet[S,A]\n    _IncrementalLogical : IncrementalLogical_MutableSet[S,A]\n    _IncrementalMinus   : IncrementalMinus_MutableSet[S,A]\n\n    add             : !(S,A) -> None\n    pop             : !(S) -> A\n    def clear(wit, self):\n        try:\n            while True:\n                wit.pop(self)\n        except KeyError:\n            pass\n\n\n-----------------------------------------------------------------\n\n# Type-based transformations:\n# \n# * Every protocol method not mentioning 'Self' is classified as an \"instance\" method\n# * A protocol method mentioning 'Self' is classified as a static method\n# * Every protocol \"instance\" method gets an extra first argument of type 'Self'\n# * Every protocol decl turns into a \"typeclass\" with an additional first type parameter 'Self'\n# * Every protocol base \"class\" turns into a \"typeclass\" ancestor (with 'Self' inserted first)\n# * In every type scheme: \n#   * Every type expression that is a protocol application is replaced by a new universally \n#     quantified variable and a corresponding protocol constraint in the schema constaint tuple\n#   * Every type variable with an explicit protocol bound has its bound moved to the schema constraint tuple\n#   * Nested types not occurring in type schemas of their own are treated as being part of the enclosing schema\n# * In every class or class:\n#   * Protocol bases turn into separate \"instance\" declarations for each protocol, with the declared struct/class\n#     inserted as the first protocol type argument\n#   * Every struct/class parameter with an explicit protocol bound has its bound moved into a constraint on the\n#     struct/class constructor function\n# * In every protocol extension:\n#   * Every base protocol turns into an \"instance\" declaration for a fresh type variable, with the protocol constraint\n#     on the new variable inserted as the first (last?) among the \"instance\" preconditions\n# * \n# * Protocols with overlapping method names are disallowed (loosen this?)\n# * Every selection expression mentioning a protocol \"instance\" method name generates the corresponding protocol constraint\n# * Every variable expression mentioning a static protocol method name generates the corresponding protocol constraint\n# * Constraint resolution and witness translation proceeds as in Haskell\n    \n# Superclass constraint (C) => means\n# \n# * Additional function parameter                      (in a function/method type scheme)\n# * Additional constructor parameter (and field)       (in a plain struct/class definition)\n# * Additional constructor parameter (and field)       (in an \"instance\" (=struct) definition)\n# * Additional \"instance\" existence requirement        (in a \"typeclass\" (=struct) definition)\n\n\n\n-----------------------------------------------------------------\n\nclass set[A (Hashable)] (object, MutableSet[A]):\n    def __len__(self): ...\n    def __contains__(self, a): ...\n    def __iter__(self): ...\n\n    def __eq__(self, other): ...\n    def __lt__(self, other): ...\n    def __or__(self, other): ...\n\n    def add(self, a): ...\n    def update(self, other): ...\n    def __ior__(self, other): ...\n    def copy(self): ...\n====>\n\"qualified class\" (Hashable[A]) => set[A]:\n    def __len__(self): ...\n    def __contains__(self, a): ...\n    def __iter__(self): ...\n\n    def __eq__(self, other): ...\n    def __lt__(self, other): ...\n    def __or__(self, other): ...\n\n    def add(self, a): ...\n    def update(self, other): ...\n    def __ior__(self, other): ...\n    def copy(self): ...\n\n\"instance\" (Hashable[A]) => MutableSet[set[A],A]:\n    ...\n====>\nclass set[A] (object):\n    _qual           : @Hashable[A]\n    ...\n\ndef MutableSet_set[A] (_qual: @Hashable[A]) -> @MutableSet[set[A],A]:\n    class MutableSet_set[A] (MutableSet[A]):\n        ...        \n    return MutableSet_set\n\n-----------------------------------------------------------------\n\n### More collections from typing.py\n\nprotocol Mapping[A,B] (Collection[A], Indexed[A,B]):\n    keys            : () -> Iterator[A]\n    values          : () -> Iterator[B]\n    items           : () -> Iterator[(A,B)]\n====>\n\"typeclass\" (Collection[S,A], Indexed[S,A,B]) => Mapping[S,A,B]:\n    keys            : (S) -> Iterator[A]\n    values          : (S) -> Iterator[B]\n    items           : (S) -> Iterator[(A,B)]\n====>\nclass Sized_Mapping[S,A,B] (Sized_Collection[S]):\n    _Collection     = Mapping\n    _Mapping        = Mapping\nclass Iterable_Mapping[S,A,B] (Iterable_Collection[S,A]):\n    _Collection     = Mapping\n    _Mapping        = Mapping\nclass Indexed_Mapping[S,A,B] (Indexed[S,A,B]):\n    _Mapping        = Mapping\nclass Mapping[S,A,B] (Collection[S,A]):\n    _Sized          = Sized_Mapping\n    _Iterable       = Iterable_Mapping\n    _Indexed        = Indexed_Mapping\n    \n    keys            : (S) -> Iterator[A]\n    values          : (S) -> Iterator[B]\n    items           : (S) -> Iterator[(A,B)]\n\n-----------------------------------------------------------------\n\nextension frozendict[A(Hashable),B] (Mapping[A,B]):\n    def keys(self):\n        ...\n    ...\n====>\n\"instance\" (Hashable[A]) => Mapping[frozendict[A,B],A,B]:\n    def keys(self):\n        ...\n    ...\n====>\ndef Mapping_frozendict[A,B] (_qual: @Hashable[A]) -> @Mapping[frozendict[A,B],A,B]:\n    \n    class Sized_Mapping_frozendict[A,B] (Sized_Mapping[frozendict[A,B],A,B]):\n        _Collection     = Mapping_frozendict\n        _Mapping        = Mapping_frozendict\n        ...\n    class Iterable_Mapping_frozendict[A,B] (Iterable_Mapping[frozendict[A,B],A,B]):\n        _Collection     = Mapping_frozendict\n        _Mapping        = Mapping_frozendict\n        ...\n    class Indexed_Mapping_frozendict[A,B] (Indexed_Mapping[frozendict[A,B],A,B]):\n        _Mapping        = Mapping_frozendict\n        ...\n    class Mapping_frozendict[A,B] (Mapping[frozendict[A,B],A,B]):\n        _Sized          = Sized_Mapping_frozendict\n        _Iterable       = Iterable_Mapping_frozendict\n        _Indexed        = Indexed_Mapping_frozendict\n\n        def keys(cls, self):\n            ...\n        ...\n        \n    return Mapping_frozendict\n\n---\n\nMapping_frozendict_str = Mapping_frozendict(Hashable_str)\n\n-----------------------------------------------------------------\n\nextension IO (VarMonad[MutableVar])\nextension ST[S] (VarMonad[MutableVar])\nextension State[S] (StateMonad[S])\nextension Env[E] (ReaderMonad[E])\nextension NetCircuit (Hard[NetSignal])\nextension SimCircuit (Hard[SimSignal])\nextension ListSet[A(Eq)] (Collection[A])\nextension TreeSet[A(Ord)] (Collection[A])\nextension A (Iso[A])            .........\nextension Foo (HasFoo[int])\nextension Sequence[A(Eq)] (Eq)\nextension tuple[A(Eq),B] (Foo)\nextension Sequence[A(MyShow)] (MyShow)\nextension Sequence[Char] (MyShow)\nextension A(Monad) (Functor)   .........\nextension StateT[S] (Monad)\nextension T(MonadT)[M(StateMonad[S])] (StateMonad[S])\nextension tuple[A(Eq),B(Eq)] (Eq)\nextension [A(Eq),B(Eq)] => tuple[A,B] (Eq)\nextension Tree[int] (Foo)\nextension Tree[bool] (Foo)\nextension F(Liftable)[A(Num)] (Num)\nextension Ratio[A(Num)] (Num)\nextension tuple[float,float] (Movable)\nextension T[int,A] (D)\nextension T[bool,A] (D)\nextension tuple[A,A] (Foo)\nextension [Sequence[Sequence[A]](C)] => Sequence[A] (C)  .........\nextension T[M](Monad) (Foo) .........\nextension [Sequence[Tree[A]](Eq)] => Tree[A(Eq)] (Eq) .........\n\nextension [A,B(Eq)] => Mapping[A,B] (Eq)\n\n-----------------------------------------------------------------\n\nextension Mapping[A, B(Eq)] (Eq):\n    def __eq__(a: Self, b: Self):\n        if len(a) != len(b):\n            return False\n        for i in a:\n            if i not in b:\n                return False\n            if a[i] /= b[i]:\n                return False\n        return True\n====>\n\"instance\" (Eq[B], Mapping[S,A,B]) => Eq[S]\n    def __eq__(a: S, b: S):\n        if len(a) != len(b):\n            return False\n        for i in a:\n            if i not in b:\n                return False\n            if a[i] /= b[i]:\n                return False\n        return True\n====>\ndef Eq_Mapping[S,A,B] (_qual: @Eq[B], _Mapping: @Mapping[S,A,B]) -> @Eq[S]:\n\n    class Eq_Mapping[S,A,B] (Eq[S])\n        def __eq__(cls, a: S, b: S):\n            if Eq_int.__ne__(_Mapping._Sized.__len__(a), _Mapping._Sized.__len__(b))\n                return False\n            for k in _Mapping._Iterable.__iter__(a):\n                if not _Mapping.__contains__(b,k):\n                    return False\n                if _qual.__ne__(_Mapping._Indexed.__getitem__(a,k), _Mapping._Indexed.__getitem__(b,k)):\n                    return False\n            return True\n    \n    return Eq_Mapping\n    \n---\n\ndef eqdict(a:frozendict[str,int], b:frozendict[str,int]) -> bool:\n    return a == b\n====>\ndef eqdict(a:frozendict[str,int], b:frozendict[str,int]) -> bool:\n    return a == b\n====>\ndef eqdict(a:frozendict[str,int], b:frozendict[str,int]) -> bool:\n    Eq_Mapping_frozendict_str_int = Eq_Mapping(Eq_int, Mapping_frozendict(Hashable_str)\n    return Eq_Mapping_frozendict_str_int.__eq__(a,b)\n\n-----------------------------------------------------------------\n\nprotocol MutableMapping[A,B] (Mapping[A,B], MutableIndexed[A,B]):\n    update          : !(Mapping[A,B]) -> None\n====>\n\"typeclass\" (Mapping[S,A,B], MutableIndexed[S,A,B]) => MutableMapping[S,A,B]:\n    update          : (Mapping[T,A,B]) => !(S,T) -> None\n====>\nclass Sized_MutableMapping[S,A,B] (Sized_Mapping[S]):\n    _MutableMapping = MutableMapping\nclass Iterable_MutableMapping[S,A,B] (Iterable_Mapping[S,A]):\n    _MutableMapping = MutableMapping\nclass Indexed_MutableMapping[S,A,B] (Indexed_Mapping[S,A,B]):\n    _MutableMapping = MutableMapping\nclass MutableIndexed_MutableMapping[S,A,B] (MutableIndexed[S,A,B]):\n    _MutableMapping = MutableMapping\nclass MutableMapping[S,A,B] (Mapping[S,A,B]):\n    _Sized          = Sized_MutableMapping\n    _Iterable       = Iterable_MutableMapping\n    _Indexed        = Indexed_MutableMapping\n    _MutableIndexed = MutableIndexed_MutableMapping\n    \n    update          : !(@Mapping[T,A,B],S,T) -> None\n\n-----------------------------------------------------------------\n\nprotocol Sequence[A] (Collection[A], Indexed[int,A], Reversible[A], Plus):\n    def __add__(self, other):       ...\n    def __contains__(self, key):    ...\n    def __iter__(self):             ...\n    def __reversed__(self):         ...\n====>\n\"typeclass\" (Collection[S,A], Indexed[S,int,A], Reversible[S,A], Plus[S]) => Sequence[S,A]:\n    def __add__(self, other):       ...\n    def __contains__(self, key):    ...\n    def __iter__(self):             ...\n    def __reversed__(self):         ...\n====>\nclass Sized_Sequence[S,A] (Sized_Collection[S]):\n    _Collection     = Sequence\n    _Sequence       = Sequence\n    def __contains__(cls, self, key): ...\nclass Iterable_Sequence[S,A] (Iterable_Collection[S,A]):\n    _Collection     = Sequence\n    _Sequence       = Sequence\n    def __iter__(cls, self): ...\nclass Indexed_Sequence[S,A] (Indexed[S,int,A]):\n    _Sequence       = Sequence\nclass Reversible_Sequence[S,A] (Reversible[S,A]):\n    _Sequence       = Sequence\n    def __reversed__(cls, self): ...\nclass Plus_Sequence[S,A] (Plus[S]):\n    _Sequence       = Sequence\n    def __add__(cls, self, other): ...\nclass Sequence[S,A] (Collection[S,A]):\n    _Sized          = Sized_Sequence\n    _Iterable       = Iterable_Sequence\n    _Indexed        = Indexed_Sequence\n    _Reversible     = Reversible_Sequence\n    _Plus           = Plus_Sequence\n\n-----------------------------------------------------------------\n\nextension Sequence[A (Eq)] (Eq):\n    def __eq__(a: Self, b: Self):\n        if len(a) != len(b):\n            return False\n        for i in range(0,len(a)):\n            if a[i] != b[i]:\n                return False\n        return True\n====>\n\"instance\" (Eq[A], Sequence[S,A]) => Eq[S]:\n    def __eq__(a: S, b: S):\n        if len(a) != len(b):\n            return False\n        for i in range(0,len(a)):\n            if a[i] != b[i]:\n                return False\n        return True\n====>\ndef Eq_Sequence[S,A] (_qual: @Eq[A], _Sequence: @Sequence[S,A]) -> Eq[S]:\n\n    class Eq_Sequence[S,A] (Eq[S]):\n        def __eq__(cls, a: S, b: S):                # OLD METHOD, SIGNATURE IS FIXED, CAN'T TAKE _qual AS A DIRECT ARGUMENT\n            if Eq_int.__ne__(cls._Sequence._Sized.__len__(a), cls._Sequence._Sized.__len__(b)):\n                return False\n            for i in Iterable_range.__iter__(range(0,cls._Sequence._Sized.__len__(a))):\n                if cls._qual.__ne__(cls._Sequence._Indexed.__getitem__(a,i), cls._Sequence._Indexed.__getitem__(b,i)):\n                    return False\n            return True\n\n    return Eq_Sequence\n\n-----------------------------------------------------------------\n\nextension Sequence[A (Eq)]:                                             # EXTENDED PROTOCOL WITH NEW METHODS AND TIGHTER PRE-CONDITION\n    index           : (A) -> int?       \n    count           : (A) -> int\n    \n    def index(self, val):\n        for i,x in enumerate(self):\n            if x == val:\n                return i\n        return None\n    def count(self, val):\n        c = 0\n        for x in self:\n            if x == val:\n                c += 1\n        return c\nf : [A(Eq),S(Sequence[A])] => (S,A) -> int                              # INFERRED\ndef f(s,a):\n    return s.count(a)\n====>\n\"typeclass\" (Eq[A], Sequence[S,A]) => Sequence_EXT[S,A]:\n    index           : (S,A) -> int?\n    count           : (S,A) -> int\n    def index(self, val):\n        for i,x in enumerate(self):\n            if x == val:\n                return i\n        return None\n    def count(self, val):\n        c = 0\n        for x in self:\n            if x == val:\n                c += 1\n        return c\nf : (Eq[A],Sequence[S,A], Sequence_EXT[S,A]) => (S,A) -> int            # INFERRED\nf : (Eq[A],Sequence[S,A]) => (S,A) -> int                               # CONTEXT-REDUCED (ALWAYS REDUCE AN EXTENDED PROTOCOL)\ndef f(s,a):\n    return s.count(a)\n====>\nclass Sequence_EXT[S,A]():\n    _Eq             : @Eq[A]\n    _Sequence       : @Sequence[S,A]\n    index           : (S,A) -> int?\n    count           : (S,A) -> int\n\n    def index(cls, self, val):\n        for i,x in enumerate(cls._Sequence._Iterable.__iter__(self)):\n            if cls._Eq.__eq__(x,val):\n                return i\n        return None\n    def count(cls, self, val):\n        c = 0\n        for x in cls._Sequence._Iterable.__iter__(self):\n            if cls._Eq.__eq__(x,val):\n                c += 1\n        return c\n\ndef f(_Sequence_EXT:@Sequence_EXT[S,A], s:S, a:A):\n    return _Sequence_EXT.count(s,a)\n\ndef f(_Eq:@Eq[A], _Sequence:@Sequence[S,A], s:S, a:A):\n    class Sequence_EXT1[S,A] (Sequence_EXT[S,A]):\n        _Eq       = _Eq\n        _Sequence = _Sequence\n    return _Sequence_EXT1.count(s,a)\n\n### OR ####\n\nclass Sequence_EXT[S,A]():\n    index           : (@Eq[A], @Sequence[S,A], S, A) -> int?            # NEW METHOD, SIGNATURE CAN BE ADAPTED\n    count           : (@Eq[A], @Sequence[S,A], S, A) -> int             # NEW METHOD, SIGNATURE CAN BE ADAPTED\n\n    def index(cls, _Eq: @Eq[A], _Sequence:@Sequence[S,A], self:S, val:A) -> int?:\n        for i,x in enumerate(_Sequence._Iterable.__iter__(self)):\n            if _Eq.__eq__(x,val):\n                return i\n        return None\n    def count(cls, _Eq: @Eq[A], _Sequence:@Sequence[S,A], self:S, val:A) -> int:\n        c = 0\n        for x in _Sequence._Iterable.__iter__(self):\n            if _Eq.__eq__(x,val):\n                c += 1\n        return c\n\ndef f(_Eq:@Eq[A], _Sequence:@Sequence[S,A], s:S, a:A):\n    return Sequence_EXT.count(_Eq,_Sequence,s,a)\n\n### OR ####\n\nclass Sequence_EXT[S,A]():\n    index           : (@Eq[A], @Sequence[S,A], S, A) -> int?\n    count           : (@Eq[A], @Sequence[S,A], S, A) -> int\n\ndef Sequence_EXT_Eq_Sequence(_Eq: @Eq[A], _Sequence:@Sequence[S,A]):\n    class Sequence_EXT[S,A]():\n        def index(cls, self:S, val:A) -> int?:\n            for i,x in enumerate(_Sequence._Iterable.__iter__(self)):\n                if _Eq.__eq__(x,val):\n                    return i\n            return None\n        def count(cls, self:S, val:A) -> int:\n            c = 0\n            for x in _Sequence._Iterable.__iter__(self):\n                if _Eq.__eq__(x,val):\n                    c += 1\n            return c\n    return Sequence_EXT_Eq_Sequence\n\ndef f(_Eq:@Eq[A], _Sequence:@Sequence[S,A], s:S, a:A):\n    Sequence_EXT = Sequence_EXT_Eq_Sequence(_Eq,_Sequence)\n    return Sequence_EXT.count(s,a)\n\n-----------------------------------------------------------------\n\nprotocol MutableSequence[A] (Sequence[A], MutableIndexed[int,A], IncrementalPlus[Sequence[A]]):\n    append          : !(A) -> None\n    __iadd__        : !(Sequence[A]) -> None\n    \n    def append(self, other):\n        ...\n    def __iadd__(self, other):\n        self.append(other)\n====>\n\"typeclass\" (Sequence[S,A], MutableIndexed[S,int,A], IncrementalPlus[S,Sequence[T,A]]) => MutableSequence[S,A]:\n    append          : !(S,A) -> None\n    __iadd__        : !(S,    Sequence[T,A]) -> None\n\n    def append(self, other):\n        ...\n    def __iadd__(self, other):\n        for v in other:\n            self.append(v)\n====>\nclass Sized_MutableSequence[S,A] (Sized_Sequence[S]):\n    _Collection         = MutableSequence\n    _Sequence           = MutableSequence\n    _MutableSequence    = MutableSequence\nclass Iterable_MutableSequence[S,A] (Iterable_Sequence[S,A]):\n    _Collection         = MutableSequence\n    _Sequence           = MutableSequence\n    _MutableSequence    = MutableSequence\nclass Indexed_MutableSequence[S,A] (Indexed_Sequence[S,int,A]):\n    _Sequence           = MutableSequence\n    _MutableSequence    = MutableSequence\nclass Reversible_MutableSequence[S,A] (Reversible_Sequence[S,A]):\n    _Sequence           = MutableSequence\n    _MutableSequence    = MutableSequence\nclass Plus_MutableSequence[S,A] (Plus[S]):\n    _Sequence           = MutableSequence\n    _MutableSequence    = MutableSequence\nclass MutableIndexed_MutableSequence[S,A] (MutableIndexed[S,int,A]):\n    _MutableSequence    = MutableSequence\nclass IncrementalPlus_MutableSequence[S,A] (IncrementalPlus[S,    Sequence[T,A]    ]):  #####################\n    _MutableSequence    = MutableSequence\n\n    __iadd__            : !(S,    Sequence[T,A]    ) -> None                             #####################\n\n    def __iadd__(self, other):\n        other_val : TTTTT = some_other.val\n        other_w : Sequence[TTTTT,A] = some_other.proto\n        for v in other_w._Iterable.__iter__(other_val):\n            self.append(v)\n\nclass MutableSequence[S,A] (Sequence[S,A]):\n    _Sized              = Sized_MutableSequence\n    _Iterable           = Iterable_MutableSequence\n    _Indexed            = Indexed_MutableSequence\n    _Reversible         = Reversible_MutableSequence\n    _Plus               = Plus_MutableSequence\n    _MutableIndexed     = MutableIndexed_MutableSequence\n    _IncrementalPlus    = IncrementalPlus_MutableSequence[S,A])\n\n    append              : !(S,A) -> None\n\n    def append(cls, self, val):\n        ...\n\n-----------------------------------------------------------------\n\nprotocol Apa:\n    def apa1(self):\n        return 1\n    def apa2(self):\n        return 2\nprotocol Bepa (Apa):\n    def apa1(self):\n        return 3\n    def bepa(self):\n        return 30 + self.apa2()\nprotocol Cepa (Apa):\n    def apa2(self):\n        return 4\n    def cepa(self):\n        return 40 + self.apa1()\nprotocol Depa (Cepa, Bepa):             # mro: Depa, Cepa, Bepa, Apa\n    def depa(self):\n        return (self.apa1(), self.apa2(), self.bepa(), self.cepa())\n====>\nclass Apa[S] ():\n    def apa1(wit,self):\n        return 1\n    def apa2(wit,self):\n        return 2\n\nclass Bepa[S] (Apa[S]):\n    def apa1(wit,self):\n        return 3\n    def bepa(wit,self):\n        return 30 + wit.apa2(self)\n\nclass Cepa[S] (Apa[S]):\n    def apa2(wit,self):\n        return 4\n    def cepa(wit,self):\n        return 40 + wit.apa1(self)\n\nclass Bepa_Depa[S] (Bepa[S]):\n    _Depa       : Depa[S]\n    def apa2(wit,self):\n        return wit._Depa.apa2(self)                     # DIAMOND PROBLEM RESOLUTION\n\nclass Depa[S] (Cepa[S]):\n    _Bepa       : Bepa[S]\n    def __init__(wit):\n        wit._Bepa = Bepa_Depa(wit)\n    def apa1(wit,self):                                 # DIAMOND PROBLEM RESOLUTION\n        return wit._Bepa.apa1(self)\n    def depa(wit,self):\n        return (wit.apa1(self), wit.apa2(self), wit._Bepa.bepa(self), wit.cepa(self))\n\n---------------------\n\nextension int (Depa):\n    pass\n====>\n\"instance\" Depa[int]:\n    pass\n====>\nwit  : Depa[int] = Depa()\nwitB : Bepa[int] = wit._Bepa\n\n7.depa() ====> \nwit.depa(7) ====> \nDepa.depa(wit,7) ====> \n(wit.apa1(7), wit.apa2(7), wit._Bepa.bepa(7), wit.cepa(7)) ====>\n(Bepa.apa1(wit,7), Cepa.apa2(wit,7), Bepa.bepa(witB,7), Cepa.cepa(wit,7)) ====>\n(3, 4, 30 + witB.apa2(7), 40 + wit.apa1(7)) ====>\n(3, 4, 30 + witB._Depa.apa2(7), 40 + wit._Bepa.apa1(7)) ====>\n(3, 4, 30 + wit.apa2(7), 40 + witB.apa1(7)) ====>\n(3, 4, 30 + Cepa.apa2(wit,7), 40 + Bepa.apa1(witB,7)) ====>\n(3, 4, 30 + 4, 40 + 3) ====>\n(3, 4, 34, 43)\n\n\n-----------------------------------------------------------------\n\nprotocol Apa:\n    def apa1(self):\n        return 1\n    def apa2(self):\n        return 2\nprotocol Bepa (Apa):\n    def apa1(self):\n        return 3\n    def bepa(self):\n        return 30 + self.apa2()\nprotocol Cepa (Apa):\n    def apa2(self):\n        return 4\n    def cepa(self):\n        return 40 + self.apa1()\nprotocol Depa (Cepa, Bepa):\n    def depa(self):\n        return (self.apa1(), self.apa2(), self.bepa(), self.cepa())\nprotocol Xtra (Apa):\n    def apa1(self):\n        return 5\n    def apa2(self):\n        return 6\nprotocol Epa1 (Depa,Xtra,Bepa):      # mro: Epa1,Depa,Cepa,Xtra,Bepa,Apa\n    pass\nprotocol Epa2 (Depa,Xtra,Cepa):      # mro: Epa2,Depa,Xtra,Cepa,Bepa,Apa\n    pass\n====>\nclass Apa[S] ():                    # apa1, apa2\n    def apa1(wit,self):\n        return 1\n    def apa2(wit,self):\n        return 2\n\nclass Bepa[S] (Apa[S]):             # apa1, apa2, bepa\n    def apa1(wit,self):\n        return 3\n    # apa2 = Apa.apa2\n    def bepa(wit,self):\n        return 30 + wit.apa2(self)\n\nclass Cepa[S] (Apa[S]):             # apa1, apa2, cepa\n    # apa1 = Apa.apa1\n    def apa2(wit,self):\n        return 4\n    def cepa(wit,self):\n        return 40 + wit.apa1(self)\n\nclass Bepa_Depa[S] (Bepa[S]):       # apa1, apa2, bepa\n    _Depa       : Depa[S]\n    # apa1 = Bepa.apa1\n    def apa2(wit,self):\n        return wit._Depa.apa2(self)                     # DIAMOND PROBLEM RESOLUTION\n    # bepa = Bepa.bepa\n\nclass Depa[S] (Cepa[S]):            # apa1, apa2, cepa, depa, bepa\n    _Bepa       : Bepa[S]\n    def __init__(wit):\n        wit._Bepa = Bepa_Depa(wit)\n    def apa1(wit,self):                                 # DIAMOND PROBLEM RESOLUTION\n        return wit._Bepa.apa1(self)\n    # apa2 = Cepa.apa2\n    # cepa = Cepa.cepa\n    def depa(wit,self):\n        return (wit.apa1(self), wit.apa2(self), wit.bepa(self), wit.cepa(self))\n    def bepa(wit,self):\n        return wit._Bepa.bepa(self)\n        \n# mro:      Depa        Cepa        Bepa        Apa\n#           -           -           apa1        (apa1)\n#           -           apa2        *-          (apa2)\n#           -           cepa\n#           depa\n#           -*                      bepa\n\n----\n\nclass Xtra[S] (Apa[S]):             # apa1, apa2\n    def apa1(wit,self):\n        return 5\n    def apa2(wit,self):\n        return 6\n\n----\n\nclass Xtra_Epa1[S] (Xtra[S]):       # apa1, apa2\n    _Exp1       : Epa1[S]\n    # apa1 = Xtra.apa1\n    def apa2(wit,self):\n        return wit._Exp1.apa1(self)\n\nclass Bepa_Epa1[S] (Bepa[S]):       # apa1, apa2, bepa\n    _Epa1       : Epa1[S]\n    def apa1(wit,self):\n        return wit._Epa1.apa1(self)\n    def apa2(wit,self):\n        return wit._Epa1.apa2(self)\n    # bepa = Bepa.bepa\n    \nclass Epa1[S] (Depa[S]):            # apa1, apa2, cepa, depa, bepa\n    _Xtra       : Xtra[S]\n    def __init__(wit):\n        wit._Bepa = Bepa_Epa1(wit)\n        wit._Xtra = Xtra_Epa1(wit)\n    def apa1(wit,self):\n        return wit._Xtra.apa1(self)\n    # apa2 = Cepa.apa2\n    # cepa = Depa.cepa\n    # depa = Depa.depa\n    # bepa = Depa.bepa\n    \n# mro:      Epa1      Depa      Cepa        Xtra        Bepa        Apa\n#           -*        -         -           apa1        *-          (apa1)\n#           -         -         apa2        *-          *-          (apa2)\n#           -         -         cepa\n#           -         depa\n#           -         -*                                bepa\n\n----\n\nclass Xtra_Epa2[S] (Xtra[S]):       # apa1, apa2\n    _Exp1       : Epa1[S]\n    # apa1 = Xtra.apa1\n    # apa2 = Xtra.apa2\n\nclass Bepa_Epa2[S] (Bepa[S]):       # apa1, apa2, bepa\n    _Epa1       : Epa1[S]\n    def apa1(wit,self):\n        return wit._Epa2.apa1(self)\n    def apa2(wit,self):\n        return wit._Epa2.apa2(self)\n    # bepa = Bepa.bepa\n    \nclass Epa2[S] (Depa[S]):            # apa1, apa2, cepa, depa, bepa\n    _Xtra       : Xtra[S]\n    def __init__(wit):\n        wit._Bepa = Bepa_Epa2(wit)\n        wit._Xtra = Xtra_Epa2(wit)\n    def apa1(wit,self):\n        return wit._Xtra.apa1(self)\n    def apa2(wit,self):\n        return wit._Xtra.apa2(self)\n    # cepa = Depa.cepa\n    # depa = Depa.depa\n    # bepa = Depa.bepa\n    \n# mro:      Epa2      Depa      Xtra        Cepa        Bepa        Apa\n#           -*        -         apa1        -           *-          (apa1)\n#           -*        -         apa2        -           *-          (apa2)\n#           -         -                     cepa\n#           -         depa\n#           -         -*                                bepa\n\n---------------------\n\nextension int (Depa):\n    pass\n====>\n\"instance\" Depa[int]:\n    pass\n====>\nwit  : Depa[int] = Depa()\nwitB : Bepa[int] = wit._Bepa\n\n7.depa() ====> \nwit.depa(7) ====> \nDepa.depa(wit,7) ====> \n(wit.apa1(7), wit.apa2(7), wit._Bepa.bepa(7), wit.cepa(7)) ====>\n(Bepa.apa1(wit,7), Cepa.apa2(wit,7), Bepa.bepa(witB,7), Cepa.cepa(wit,7)) ====>\n(3, 4, 30 + witB.apa2(7), 40 + wit.apa1(7)) ====>\n(3, 4, 30 + witB._Depa.apa2(7), 40 + wit._Bepa.apa1(7)) ====>\n(3, 4, 30 + wit.apa2(7), 40 + witB.apa1(7)) ====>\n(3, 4, 30 + Cepa.apa2(wit,7), 40 + Bepa.apa1(witB,7)) ====>\n(3, 4, 30 + 4, 40 + 3) ====>\n(3, 4, 34, 43)\n\n-------------------------------------------------------------------------------------------------------------------------------------------------------------\n-------------------------------------------------------------------------------------------------------------------------------------------------------------\n-------------------------------------------------------------------------------------------------------------------------------------------------------------\n-------------------------------------------------------------------------------------------------------------------------------------------------------------\n\nprotocol Apa:\n    def apa1(self):\n        return 1\n    def apa2(self):\n        return 2\n\nprotocol Bepa (Apa):\n    def apa1(self):\n        return 10\n    def bepa(self):\n        return self.apa2()\n\nprotocol Cepa (Apa):\n    def apa2(self):\n        return 20\n    def cepa(self):\n        return self.apa1()\n\n---\n\nprotocol Depa (Cepa,Bepa):\n    def depa(self):\n        return (self.cepa(), self.bepa())\n\nextension int (Depa):                       # Extension by multi inheritance protocol\n    def ipa(self):\n        return depa(self)\n\n---\n\nextension str (Cepa,Bepa):                  # Simultaneous multi extension\n    def epa(self):\n        return (self.cepa(), self.bepa())\n\n---\n\nextension str (Bepa):                       # First extension\n    pass\n\nextension str (Cepa):                       # Second extension. Hmm... should this really affect the str (Bepa) extension behavior? Yes, on the\n    def fepa(self):                         #                   grounds that it introduces a new behavior for str.apa2, on which str.bepa depends.\n        return (self.cepa(), self.bepa())\n\n---\n\nextension list[A] (Bepa):                   # First extension\n    pass\n\nextension list[A] (Cepa):\n    def fepa(self):                         # Second extension\n        return (self.cepa(), self.bepa())\n    \n\n# Witness translation goal: keep witnesses selection for Self and its type parameters open-ended in the OO way!\n# Achieve this via the \"self\" parameter of the translated protocol methods, here denoted \"w\" to distinguish it from the original \"self\"\n\n====================================================>           # Regular translation, avoiding class inheritance in translation of multiple base protocols\n\nclass Apa[S] ():\n    def apa1(w, self):\n        return 1\n    def apa2(w, self):\n        return 2\n\n        \nclass Bepa[S] ():\n\n    class Apa_wrapped[S] (Apa[S]):\n        _main   : Bepa[S]\n        def apa1(w, self):\n            return w._main.apa1(self)           # Overriding apa1 (= redirection to Bepa, in case of Apa sibling use or Bepa promotion to Apa)\n        # apa2 = Apa.apa1                       # Inheriting apa2\n\n    _Apa    : Apa[S]\n    def __init__(w):\n        w._Apa = Apa_wrapped(_main = w)\n        \n    def apa1(w, self):                      # Overriding apa1\n        return 10\n    def apa2(w, self):                      # \"Inheriting\" apa2 (= delegation to Apa, in case of either Bepa sibling use or official Bepa call)\n        return w._Apa.apa2(self)\n    def bepa(w, self):                      # Adding bepa\n        return w.apa2(self)\n\n            \nclass Cepa[S] ():\n\n    class Apa_wrapped[S] (Apa[S]):\n        _main   : Cepa[S]\n        # apa1 = Apa.apa1                       # Inheriting apa1\n        def apa2(w, self):\n            return w._main.apa2(self)           # Overriding apa2 (= redirection to Cepa, in case of Apa sibling use or Cepa promotion to Apa)\n\n    _Apa    : Apa[S]\n    def __init__(w):\n        w._Apa = Apa_wrapped(_main = w)\n\n    def apa1(w, self):                      # \"Inheriting\" apa1 (= delegation to Apa, in case of Cepa sibling use or official Cepa call)\n        return w._Apa.apa1(self)\n    def apa2(w, self):                      # Overriding apa2\n        return 20\n    def cepa(w, self):                      # Adding cepa\n        return w.apa1(self)\n\n--- extension int (Depa)\n\nclass Depa[S] ():\n    \n    class Bepa_wrapped[S] (Bepa[S]):\n        _main   : Depa[S]\n        # apa1 = Bepa.apa1                      # Inheriting apa1\n        def apa2(w, self):                      # Overriding apa2 (= redirection to Depa, in case of Bepa sibling use or Depa promotion to Bepa)\n            return w._main.apa2(self)\n        # bepa = Bepa.bepa                      # Inheriting bepa\n        \n    class Cepa_wrapped[S] (Cepa[S]):\n        _main   : Depa[S]\n        def apa1(w, self):                      # Overriding apa1 (= redirection to Depa, in case of Cepa sibling use or Depa promotion to Cepa)\n            return w._main.apa1(self)\n        # apa2 = Cepa.apa2                      # Inheriting apa2\n        # cepa = Cepa.cepa                      # Inheriting cepa\n    \n    _Bepa   : Bepa[S]\n    _Cepa   : Cepa[S]\n    def __init__(w):\n        w._Bepa = Bepa_wrapped(_main = w)\n        w._Cepa = Cepa_wrapped(_main = w)\n\n    def apa1(w, self):                      # \"Inheriting\" apa1 (= delegation to Bepa, in case of Depa sibling use or official Depa call)\n        return w._Bepa.apa1(self)\n    def bepa(w, self):                      # \"Inheriting\" bepa (= delegation to Bepa, in case of Depa sibling use or official Depa call)\n        return w._Bepa.bepa(self)\n    def apa2(w, self):                      # \"Inheriting\" apa2 (= delegation to Cepa, in case of Depa sibling use or official Depa call)\n        return w._Cepa.apa2(self)\n    def cepa(w, self):                      # \"Inheriting\" cepa (= delegation to Cepa, in case of Depa sibling use or official Depa call)\n        return w._Cepa.bepa(self)\n    def depa(w, self):                      # Adding depa\n        return w.cepa(self) + w.bepa(self)\n    \nclass Depa_int (Depa[int]):                 # Extension by multi inheritance protocol\n    def __init__(w):\n        Depa.__init__(w)\n    def ipa(w, self):\n        return w.depa(self)\n\n--- extension str (Cepa,Bepa)\n\nclass Cepa_Bepa_str ():                     # Simultaneous multi extension\n\n    class Bepa_wrapped (Bepa[str]):\n        _main   : Cepa_Bepa_str\n        # apa1 = Bepa.apa1                      # Inheriting apa1\n        def apa2(w, self):                      # Overriding apa2 (= redirection to Cepa_Bepa_str, in case of Bepa sibling use or Cepa_Bepa_str promotion to Bepa)\n            return w._main.apa2(self)\n        # bepa = Bepa.bepa                      # Inheriting bepa\n        \n    class Cepa_wrapped (Cepa[str]):\n        _main   : Cepa_Bepa_str\n        def apa1(w, self):                      # Overriding apa1 (= redirection to Cepa_Bepa_str, in case of Cepa sibling use or Cepa_Bepa_str promotion to Cepa)\n            return w._main.apa1(self)\n        # apa2 = Cepa.apa2                      # Inheriting apa2\n        # cepa = Cepa.cepa                      # Inheriting cepa\n    \n    _Bepa   : Bepa[str]\n    _Cepa   : Cepa[str]\n    def __init__(w):\n        w._Bepa = Bepa_wrapped(_main = w)\n        w._Cepa = Cepa_wrapped(_main = w)\n\n    def apa1(w, self):                      # \"Inheriting\" apa1 (= delegation to Bepa, in case of Cepa_Bepa_str sibling use or official Cepa_Bepa_str call)\n        return w._Bepa.apa1(self)\n    def bepa(w, self):                      # \"Inheriting\" bepa (= delegation to Bepa, in case of Cepa_Bepa_str sibling use or official Cepa_Bepa_str call)\n        return w._Bepa.bepa(self)\n    def apa2(w, self):                      # \"Inheriting\" apa2 (= delegation to Cepa, in case of Cepa_Bepa_str sibling use or official Cepa_Bepa_str call)\n        return w._Cepa.apa2(self)\n    def cepa(w, self):                      # \"Inheriting\" cepa (= delegation to Cepa, in case of Cepa_Bepa_str sibling use or official Cepa_Bepa_str call)\n        return w._Cepa.bepa(self)\n    def depa(w, self):                      # Adding depa\n        return w.cepa(self) + w.bepa(self)\n\n    def epa(w, self):\n        return w.cepa(self) + w.bepa(self)\n\n--- extension str (Bepa); extension str (Cepa)\n\nclass Bepa_str ():                          # First extension\n\n    class Bepa_wrapped (Bepa[str]):\n        _main   : Bepa_str\n        # apa1 = Bepa.apa1                      # Inheriting apa1\n        # apa2 = Bepa.apa2                      # Inheriting apa2\n        # bepa = Bepa.bepa                      # Inheriting bepa\n        \n    _Bepa   : Bepa[str]                     # NOTE: real str(Bepa) witness!\n    def __init__(w):\n        w._Bepa = Bepa_wrapped(_main = w)\n\n    def apa1(w, self):                      # \"Inheriting\" apa1 (= delegation to Bepa, in case of Bepa_str sibling use or official Bepa_str call)\n        return w._Bepa.apa1(self)\n    def apa2(w, self):                      # \"Inheriting\" apa2 (= delegation to Bepa, in case of Bepa_str sibling use or official Bepa_str call)\n        return w._Bepa.apa2(self)\n    def bepa(w, self):                      # \"Inheriting\" bepa (= delegation to Bepa, in case of Bepa_str sibling use or official Bepa_str call)\n        return w._Bepa.bepa(self)\n\nclass Cepa_Bepa_str (Bepa_str):             # Second extension\n\n    class Cepa_wrapped (Cepa[str]):\n        _main   : Cepa_Bepa_str\n        def apa1(w, self):                      # Overriding apa1 (= redirection to Cepa_Bepa_str, in case of Cepa sibling use or Cepa_Bepa_str promotion to Cepa)\n            return w._main.apa1(self)\n        # apa2 = Cepa.apa2                      # Inheriting apa2\n        # cepa = Cepa.cepa                      # Inheriting cepa\n    \n    _Cepa   : Cepa[str]                     # NOTE: real str(Cepa) witness!\n    def __init__(w):\n        Bepa_str.__init__(w)\n        w._Cepa = Cepa_wrapped(_main = w)\n\n    # apa1 = Bepa_str.apa1                  # Inheriting apa1\n    def apa2(w, self):                      # \"Inheriting\" apa2 (= delegation to Cepa, in case of Cepa_Bepa_str sibling use or official Cepa_Bepa_str call)\n        return w._Cepa.apa2(self)\n    # bepa = Bepa_str.bepa                  # Inheriting bepa\n    def cepa(w, self):                      # \"Inheriting\" cepa (= delegation to Cepa, in case of Cepa_Bepa_str sibling use or official Cepa_Bepa_str call)\n        return w._Cepa.bepa(self)\n    def fepa(w, self):                      # Adding depa\n        return w.cepa(self) + w.bepa(self)\n\n--- extension list[A] (Bepa); extension list[A] (Cepa)\n\nclass Bepa_list[A] ():                      # First extension\n\n    class Bepa_wrapped[A] (Bepa[list[A]]):\n        _main   : Bepa_list\n        # apa1 = Bepa.apa1                      # Inheriting apa1\n        # apa2 = Bepa.apa2                      # Inheriting apa2\n        # bepa = Bepa.bepa                      # Inheriting bepa\n        \n    _Bepa   : Bepa[list[A]]                 # NOTE: real list[A](Bepa) witness!\n    def __init__(w):\n        w._Bepa = Bepa_wrapped(_main = w)\n\n    def apa1(w, self):                      # \"Inheriting\" apa1 (= delegation to Bepa, in case of Bepa_list sibling use or official Bepa_list call)\n        return w._Bepa.apa1(self)\n    def apa2(w, self):                      # \"Inheriting\" apa2 (= delegation to Bepa, in case of Bepa_list sibling use or official Bepa_list call)\n        return w._Bepa.apa2(self)\n    def bepa(w, self):                      # \"Inheriting\" bepa (= delegation to Bepa, in case of Bepa_list sibling use or official Bepa_list call)\n        return w._Bepa.bepa(self)\n\nclass Cepa_Bepa_list[A] (Bepa_list[A]):     # Second extension\n\n    class Cepa_wrapped[A] (Cepa[list[A]]):\n        _main   : Cepa_Bepa_list[A]\n        def apa1(w, self):                      # Overriding apa1 (= redirection to Cepa_Bepa_list, in case of Cepa sibling use or Cepa_Bepa_list prom to Cepa)\n            return w._main.apa1(self)\n        # apa2 = Cepa.apa2                      # Inheriting apa2\n        # cepa = Cepa.cepa                      # Inheriting cepa\n    \n    _Cepa   : Cepa[list[A]]                 # NOTE: real str(Cepa) witness!\n    def __init__(w):\n        Bepa_list.__init__(w)\n        w._Cepa = Cepa_wrapped(_main = w)\n\n    # apa1 = Bepa_list.apa1                 # Inheriting apa1\n    def apa2(w, self):                      # \"Inheriting\" apa2 (= delegation to Cepa, in case of Cepa_Bepa_list sibling use or official Cepa_Bepa_list call)\n        return w._Cepa.apa2(self)\n    # bepa = Bepa_list.bepa                 # Inheriting bepa\n    def cepa(w, self):                      # \"Inheriting\" cepa (= delegation to Cepa, in case of Cepa_Bepa_list sibling use or official Cepa_Bepa_list call)\n        return w._Cepa.bepa(self)\n    def fepa(w, self):                      # Adding depa\n        return w.cepa(self) + w.bepa(self)\n\n--- extension set[A(Eq)] (Bepa); extension set[A(Ord)] (Cepa)\n\nclass Bepa_set[A] ():                      # First extension\n\n    class Bepa_wrapped[A] (Bepa[set[A]]):\n        _main   : Bepa_set[A]\n        _Eq_A   : Eq[A]\n        # apa1 = Bepa.apa1                      # Inheriting apa1\n        # apa2 = Bepa.apa2                      # Inheriting apa2\n        # bepa = Bepa.bepa                      # Inheriting bepa\n        \n    _Bepa   : Bepa[set[A]]                 # NOTE: real set[A](Bepa) witness!\n    def __init__(w, _Eq_A):\n        w._Bepa = Bepa_wrapped(_main = w, _Eq_A = _Eq_A)\n\n    def apa1(w, self):                      # \"Inheriting\" apa1 (= delegation to Bepa, in case of Bepa_set sibling use or official Bepa_set call)\n        return w._Bepa.apa1(self)\n    def apa2(w, self):                      # \"Inheriting\" apa2 (= delegation to Bepa, in case of Bepa_set sibling use or official Bepa_set call)\n        return w._Bepa.apa2(self)\n    def bepa(w, self):                      # \"Inheriting\" bepa (= delegation to Bepa, in case of Bepa_set sibling use or official Bepa_set call)\n        return w._Bepa.bepa(self)\n\nclass Cepa_Bepa_set[A] (Bepa_set[A]):       # Second extension\n\n    class Cepa_wrapped[A] (Cepa[set[A]]):\n        _main   : Cepa_Bepa_set[A]\n        _Ord_A  : Ord[A]\n        def apa1(w, self):                      # Overriding apa1 (= redirection to Cepa_Bepa_set, in case of Cepa sibling use or Cepa_Bepa_set prom to Cepa)\n            return w._main.apa1(self)\n        # apa2 = Cepa.apa2                      # Inheriting apa2\n        # cepa = Cepa.cepa                      # Inheriting cepa\n    \n    _Cepa   : Cepa[set[A]]                  # NOTE: real str(Cepa) witness!\n    def __init__(w, _Ord_A):\n        Bepa_set.__init__(w, _Eq_A = _Ord_A)\n        w._Cepa = Cepa_wrapped(_main = w, _Ord_A = _Ord_A)\n\n    # apa1 = Bepa_set.apa1                  # Inheriting apa1\n    def apa2(w, self):                      # \"Inheriting\" apa2 (= delegation to Cepa, in case of Cepa_Bepa_set sibling use or official Cepa_Bepa_set call)\n        return w._Cepa.apa2(self)\n    # bepa = Bepa_set.bepa                  # Inheriting bepa\n    def cepa(w, self):                      # \"Inheriting\" cepa (= delegation to Cepa, in case of Cepa_Bepa_set sibling use or official Cepa_Bepa_set call)\n        return w._Cepa.bepa(self)\n    def fepa(w, self):                      # Adding depa\n        return w.cepa(self) + w.bepa(self)\n\n\n====================================================>           # Utilizing single class inheritance....\n\nclass Apa[S] ():\n    def apa1(w, self):\n        return 1\n    def apa2(w, self):\n        return 2\n\nclass Bepa[S] (Apa[S]):\n    def apa1(w, self):\n        return 10\n    def bepa(w, self):\n        return w.apa2(self)\n\nclass Cepa[S] (Apa[S]):\n    # apa1 = Apa.apa1\n    def apa2(w, self):\n        return 20\n    def cepa(w, self):\n        return w.apa1(self)\n\nclass Bepa_Depa[S] (Bepa[S]):\n    _Depa   : Depa[S]\n    # apa1 = Bepa.apa1\n    def apa2(w, self):\n        return w._Depa.apa2(self)\n    # bepa = Bepa.bepa\n\n--- extension int (Depa)\n\nclass Depa[S] (Cepa[S]):\n    _Bepa   : Bepa[S]\n    def apa1(w, self):\n        return w._Bepa.apa1(self)\n    # apa2 = Cepa.apa2\n    # cepa = Cepa.cepa\n    def bepa(w, self):\n        return w._Bepa.bepa(self)\n    def depa(w, self):\n        return w.cepa(self) + w.bepa(self)\n\nclass Depa_int (Depa[int]):\n    def __init__(w):\n        w._Bepa = Bepa_Depa(w)\n    def ipa(w, self):\n        return w.depa(self)\n\n\n--- extension str (Cepa,Bepa)\n\nclass Cepa_Bepa_str (Cepa[str]):\n    \n    class Bepa_wrapped (Bepa[str]):\n        _main   : Cepa[str]\n        # apa1 = Bepa.apa2                      # Inheriting apa1\n        def apa2(w, self):                      # Overriding apa2 (= redirection to Cepa_Bepa_str, in case of Bepa sibling use or Cepa_Bepa_str promotion to Bepa)\n            return w._main.apa2(self)\n        # bepa = Bepa_str.bepa                  # Inheriting bepa\n    \n    _Bepa   : Bepa[str]                         # NOTE: real str(Bepa) witness!\n    def __init__(w):\n        w._Bepa = Bepa_wrapped(_main = w)\n    \n    def apa1(w, self):\n        retun w._Bepa.apa1(self)\n    # apa2 = Cepa.apa2\n    # cepa = Cepa.cepa\n    def bepa(w, self):\n        return w._Bepa.bepa(self)\n    def fepa(w, self):\n        return w.cepa(self) + w.bepa(self)\n\n--- extension str (Bepa); extension str (Cepa)\n\nclass Bepa_str (Bepa[str]):\n    # apa1 = Bepa.apa1                      # Inheriting apa1\n    # apa2 = Bepa.apa2                      # Inheriting apa2\n    # bepa = Bepa.bepa                      # Inheriting bepa\n    \nclass Cepa_Bepa_str (Cepa[str]):            # Encoding Cepa_Bepa_str (Cepa[str], Bepa[str])\n    \n    class Bepa_wrapped (Bepa_str):              # Forms inner baseclass (delegate), but comes before Cepa in the MRO\n        _main   : Cepa[str]\n        # apa1 = Bepa.apa2                      # Inheriting apa1\n        def apa2(w, self):                      # Overriding apa2 (= redirection to Cepa_Bepa_str, in case of Bepa_str sibling use or Cepa_Bepa_str promotion to Bepa)\n            return w._main.apa2(self)\n        # bepa = Bepa_str.bepa                  # Inheriting bepa\n        \n    _Bepa   : Bepa[str]                     # NOTE: real str(Bepa) witness!\n    def __init__(w):\n        w._Bepa = Bepa_wrapped(_main = w)\n    \n    def apa1(w, self):                      # \"Inheriting\" apa1 (= delegation to Bepa, in case of Cepa_Bepa_str sibling use or official Cepa_Bepa_str call)\n        retun w._Bepa.apa1(self)\n    # apa2 = Cepa.apa2                      # Inheriting apa2\n    # cepa = Cepa.cepa                      # Inheriting cepa\n    def bepa(w, self):                      # \"Inheriting\" bepa (= delegation to Bepa, in case of Cepa_Bepa_str sibling use or official Cepa_Bepa_str call)\n        return w._Bepa.bepa(self)\n    def fepa(w, self):\n        return w.cepa(self) + w.bepa(self)\n\n--- extension list[A] (Bepa); extension list[A] (Cepa)\n\nclass Bepa_list[A] (Bepa[list[A]]):\n    # apa1 = Bepa.apa1                      # Inheriting apa1\n    # apa2 = Bepa.apa2                      # Inheriting apa2\n    # bepa = Bepa.bepa                      # Inheriting bepa\n    \nclass Cepa_Bepa_list[A] (Cepa[list[A]]):    # Encoding Cepa_Bepa_list[A] (Cepa[list[A]], Bepa[list[A]])\n    \n    class Bepa_wrapped[A] (Bepa_list[A]):       # Forms inner baseclass (delegate), but comes before Cepa in the MRO\n        _main   : Cepa[list[A]]\n        # apa1 = Bepa.apa2                      # Inheriting apa1\n        def apa2(w, self):                      # Overriding apa2 (= redirection to Cepa_Bepa_list, if Bepa_list sibling use or Cepa_Bepa_list prom to Bepa)\n            return w._main.apa2(self)\n        # bepa = Bepa_list.bepa                 # Inheriting bepa\n        \n    _Bepa   : Bepa[list[A]]                 # NOTE: real list[A](Bepa) witness!\n    def __init__(w):\n        w._Bepa = Bepa_wrapped(_main = w)\n    \n    def apa1(w, self):                      # \"Inheriting\" apa1 (= delegation to Bepa, in case of Cepa_Bepa_list sibling use or official Cepa_Bepa_list call)\n        retun w._Bepa.apa1(self)\n    # apa2 = Cepa.apa2                      # Inheriting apa2\n    # cepa = Cepa.cepa                      # Inheriting cepa\n    def bepa(w, self):                      # \"Inheriting\" bepa (= delegation to Bepa, in case of Cepa_Bepa_list sibling use or official Cepa_Bepa_list call)\n        return w._Bepa.bepa(self)\n    def fepa(w, self):\n        return w.cepa(self) + w.bepa(self)\n\n--- extension set[A(Eq)] (Bepa); extension set[A(Ord)] (Cepa)\n\nclass Bepa_set[A] (Bepa[set[A]]):\n    _Eq_A   : Eq[A]\n    def __init__(w, _Eq_A):\n        w._Eq_A = _Eq_A\n    # apa1 = Bepa.apa1                      # Inheriting apa1\n    # apa2 = Bepa.apa2                      # Inheriting apa2\n    # bepa = Bepa.bepa                      # Inheriting bepa\n    \nclass Cepa_Bepa_set[A] (Cepa[set[A]]):    # Encoding Cepa_Bepa_set[A] (Cepa[set[A]], Bepa[set[A]])\n    \n    class Bepa_wrapped[A] (Bepa_set[A]):        # Forms inner baseclass (delegate), but comes before Cepa in the MRO\n        _main   : Cepa[set[A]]\n        # apa1 = Bepa.apa2                      # Inheriting apa1\n        def apa2(w, self):                      # Overriding apa2 (= redirection to Cepa_Bepa_set, if Bepa_set sibling use or Cepa_Bepa_set prom to Bepa)\n            return w._main.apa2(self)\n        # bepa = Bepa_set.bepa                 # Inheriting bepa\n        \n    _Bepa   : Bepa[set[A]]                 # NOTE: real set[A](Bepa) witness!\n    _Ord_A  : Ord[A]\n    def __init__(w, _Ord_A):\n        w._Bepa = Bepa_wrapped(_main = w, _Eq_A = _Ord_A)           # In general: _Eq_A = some_expr(_Ord_A)\n        w._Ord_A = _Ord_A\n    \n    def apa1(w, self):                      # \"Inheriting\" apa1 (= delegation to Bepa, in case of Cepa_Bepa_set sibling use or official Cepa_Bepa_set call)\n        retun w._Bepa.apa1(self)\n    # apa2 = Cepa.apa2                      # Inheriting apa2\n    # cepa = Cepa.cepa                      # Inheriting cepa\n    def bepa(w, self):                      # \"Inheriting\" bepa (= delegation to Bepa, in case of Cepa_Bepa_set sibling use or official Cepa_Bepa_set call)\n        return w._Bepa.bepa(self)\n    def fepa(w, self):\n        return w.cepa(self) + w.bepa(self)\n\n"
  },
  {
    "path": "workspace/Type-hierarchy.txt",
    "content": "Inheritance and overloading in Acton\n====================================\n\nThis note aims to describe a proposal for how to integrate the notions of class inheritance and function/method overloading in Acton. \n\nBy inheritance I mean the combination of the following ideas:\n- Classes (and other types) form a subtype hierarchy, and values of smaller types automatically count as values of their base types.\n- Classes defined by extension automatically include the code of their base classes, with the exception of overridden methods.\n- Methods invoked on 'self' reach code associated with the *actual* class of 'self', even when the calling method is an inherited one.\n\nBy overloading I mean the feature that a certain method/function name can have many different implementations in a program, and that the selection of which implementation to invoke is directed by static type information available at the call site. Being dynamically typed, Python doesn't offer this particular feature, and instead often employs multiple inheritance (inheritance from more than one base class) as a form of compensation. However, this approach leads to its own set of problems that we want to avoid in Acton.\n\nThe first problem is that generic operations get associated with individual objects, even when multiple objects are involved and the more correct view would be to associate the operation with the objects' common type. A typical example is the generic equality test ==, implemented in Python as a binary method __eq__ available on all objects. Ignoring for now the fact that higher-order types have no natural notion of equality, the primary problem of treating equality as a property of individual objects is that the relation becomes too localized. For example, x.__eq__(y) is in general a different test than y.__eq__(x), and the two forms may invoke entirely unrelated pieces of code in case x and y were instatiated from different classes. What is worse, the natural expectation that both operands of __eq__ exhibit the same set of attributes goes against well-known type-checking laws in the presence of inheritance, which renders static type safety problematic.\n\nThe second problem with Python's reliance on inheritance is the fact that the ancestry of a class is fixed once the class is defined. That is, mixing in an extra base class as an afterthought is not possible. This isn't just a problem that can be avoided by careful planning, as all mix-in classes of useful functionality might not even be concieved when a datatype is defined. In a statically typed setting, the drawback is accentuated in the presence of generics (parametric polymorphism), where the appropriateness of mix-in inheritance also might depend on whether a yet unknown type parameter supports a certain operation or not. A type system where overloading is separate from the inheritance hierarchy would not suffer from this problem.\n\nThirdly, there is no secret that multiple inheritance is tricky to implement, both in terms of the necessary static type analysis and the run-time machinery required. Many modern languages like Java, C#, Swift, Ruby and Scala abandon multiple inheritance in favor of a single inheritance hierarchy and the ability to overload classes using multiple interfaces/protocols/traits. Haskell has no notion of class inheritance, but provides an advanced system for overloading that is compatible with type inference and supports an efficient implementation. When I realized that Swift's protocol mechanism can be implemented like (and is probably based on) Haskell's overloading system, I felt the arguments tipping over in favor of abandoning multiple inheritance in Acton as well. If done right, the change would not even have to lead to much visible differences compared to existing Python programming practice.\n\nSo the basic idea of the proposal is inspired by Swift, where one declares *protocols* in addition to classes. I'm not sure about the best way to syntactically introduce protocols in Acton, but let's for the moment assume something akin to (abstract) class declarations. Here's how we could write some simple protocols to express hashability and equality:\n\n    protocol Hashable (Eq):\n        __hash__        : () -> int\n\n    protocol Eq:\n        @staticmethod\n        __eq__          : (Self,Self) -> bool\n        @staticmethod\n        __ne__          : (Self,Self) -> bool\n        \n        def __ne__(a,b):\n            return not (a == b)\n\nThe meaning is that a hashable type is a type with a method __hash__, and equality is supported by a type that offers the static methods __eq__ and __ne__. Hashable is furthermore defined as an extension of protocol Eq, which implies that any type wishing to implement protocol Hashable must also make sure it implements the Eq methods. Another detail is that protocols can offer default implementations of its methods, so that in this case, a type that wants to support protocol Eq doesn't have to implement method __ne__ unless it wishes to. We may say that such a type \"inherits\" the __ne__ method, although in this case the resolution of which method that gets called will be based on static type information rather than a dynamic class pointer.\n\nThe special type Self stands for the actual type that implements a particular protocol, so declaring both method arguments to be of type Self effectively says the arguments must have the same (unknown) type. Self can also be used inside classes, where it stands for the type where an attribute or method eventually ends up after being inherited. Self is thus a place-holder that implicitly moves with the class and protocol hierarchies, and its presence in contravariant argument positions should therefore trigger some concern regarding type safety. \n\nLike in Swift, this proposal restricts the Self type by only allowing contravariant occurrences inside static methods. We will also impose the rule that (contravariant) static methods can only be selected directly from classes that implement them, they are not accessible as attributes of the instances of such classes. Combined with the ability of the Acton type-checker to automatically insert the appropriate class in front of overloaded method names, these restrictions are sufficient to guarantee type safety while retaining the original convenience of Python's binary methods. That is, an expression x==y will not translate into x.__eq__(y) in Acton but to w.__eq__(x,y), where w is a class name generated by the compiler on basis of static type information.\n\nProtocols can be listed instead of base classes when classes are defined, and the resulting behavior stays similar to that of class inheritance except for the statically resolved overloading. As an example, let's see how equality can be defined for a class of Fruit and some specialization classes Apple and Orange.\n\n    class Fruit (Eq):\n        ...\n        def __eq__(a, b):\n            return a.weight == b.weight\n\n    class Apple (Fruit):\n        ...\n        def __eq__(a, b):\n            return Fruit.__eq__(a,b) and a.appleness == b.appleness\n\n    class Orange (Fruit):\n        ...\n        def __eq__(a, b):\n            return Fruit.__eq__(a,b) and a.orangeness == b.orangeness\n\nThe fact that __eq__ is a static method in all three classes is implied by the reference to protocol Eq. The specialized fruit attributes \"appleness\" and \"orangeness\" are left unspecified here, the important detail is that only apples possess appleness, and no fruit besides oranges exhibit the orangeness attribute.\n\nAssuming two variables x and y of type Apple, we can test for their apple-specific equality by writing\n\n    x == y\n    \nwhich gets translates to\n\n    Apple.__eq__(x, y)\n\non basis of the statically known types for x and y.\n\nSimilarly, testing u == v, where both u and v are of type Orange, results in the following translated code:\n\n    Orange.__eq__(u, v)\n\nHowever, should we promote any pair of these variables to type Fruit and then test for equality, we expect the comparison to only take the respective weights into account (as defined in class Fruit). That is, if we write\n\n    i : Fruit = x\n    j : Fruit = u\n    i == j\n\nthe last expression gets translated to\n\n    Fruit.__eq__(i, j)\n\nby the compiler. In fact, the same effect is achieved if we compare Apple x directly to Orange u, since the closest common supertype of these types is Fruit:\n\n    x == u   ====>   Fruit.__eq__(x, u)\n\nAny attempt to force the comparison of these variables using either the Apple.__eq__ or Orange.__eq__ methods will result in a static type error. That goes for the selection of __eq__ as an attribute of either a or x as well, since __eq__ is a contravariant static method which must therefore only be looked up by class.\n\nA more elaborate example looks as follows:\n\n    class MyClass (Hashable):\n        def __eq__(a, b):\n            return hash(a) == hash(b)\n        def hash(self):\n            return cheap_hash(self)\n        def my_method(self):\n            return hash(self)\n        \n    class MySubClass (MyClass):\n        def hash(self):\n            return expensive_hash(self)\n\nHere MyClass implements the Hashable protocol, and MySubClass in turn extends MyClass in the plain old class inheritance fashion. Both __eq__ and my_method call the overloaded method __hash__ (via Python's syntactic sugar hash(v) ====> v.__hash__()), and __hash__ is redefined in MySubClass. But while __eq__ is itself a protocol method selected by type, my_method is dynamically bound. We should thus expect to see some differences in the way calls to these methods are resolved.\n\nFirst let's assume some objects x and y that are true MySubClass instances, and a variable z that is an alias to y but promoted to type MyClass:\n\n    x = y = MySubClass()\n    z : MyClass = y\n\nAs in the Fruit example, the comparisons \n\n    x == y\n    x == z\n\nget translates on basis of static type information as before, and hence become\n\n    MySubClass.__eq__(x,y)\n    MyClass.__eq__(x,z)\n\nHowever, the calls\n\n    y.my_method()\n    z.my_method()\n\nare both dispatched dynamically on basis of the run-time class of y and z, and since this class is MySubClass in both cases, both calls behave the same at run-time:\n\n    y.my_method()    ====>    MySubClass.my_method(y)\n    z.my_method()    ====>    MySubClass.my_method(z)\n\nNow, inside both __eq__ and my_method, the calls to __hash__ (via hash) are resolved statically. But the static type in question is Self at these occurrences, and Self gets re-interpreted whenever a method is inherited in a subclass. Thus, the equality comparisons evolve as follows\n\n    MySubClass.__eq__(x,y)  ====>  ... MySubClass.__hash__(b) ...  ====>  ... expensive_hash(b) ...    (where b is y)\n    MyClass.__eq__(x,z)     ====>  ... MyClass.__hash__(b) ...     ====>  ... cheap_hash(b) ...        (where b is z)\n    \nwhereas the my_method calls become\n\n    MySubClass.my_method(y)  ====>  ... MySubClass.__hash__(b) ...  ====>  ... expensive_hash(b) ...   (where b is y)\n    MySubClass.my_method(z)  ====>  ... MySubClass.__hash__(b) ...  ====>  ... expensive_hash(b) ...   (where b is z)\n\nIn essence, the statically known type of an object is irrelevant when one of its dynamically bound methods is called, but absolutely crucial when the called method belongs to a protocol. I expect these principles to coincide for most practical purposes, and I'll argue that the subtle cases one can construct are at least not harder to understand than the the corner cases of multiple inheritance in Python. The advantages of the proposal show up in the absence of a diamond problem (protocols can never be implemented twice), the ease by which contravariant binary methods can be handled (and explored at different types), and the straightforward implementation technique one gets for free when the protocol notion is understood in terms of Haskell's type classes (more on this below).\n\nAnother distinct advantage of static overloading is that it also lends itself to incremental class adoptions. That is, all protocols a class can implement don't have to be listed when the class is defined; they can just as well be added later, in separate modules, and even without access to the original class implemenation. The key insight here is that type-based associations between a class and its various protocol implementations only exist within the compiler, there is no need to modify any existing class definition just because another such association is made.\n\nAgain drawing inspiration from Swift (and Haskell), here's a tentative syntax illustrating what an incremental protocol adoption can look like.\n\n    class SomeElaborateClass (SomeBaseClass, Eq, SomeBasicProtocol):\n        ...\n        \n    # Much later, in a module far away:\n\n    extension SomeElaborateClass (NewlyInventedProtocol):\n        def protocol_method_A(self):\n            ...\n        def protocol_method_B(x, y, z):\n            ...\n\nTo investigate the design a bit further, I've made an experimental \"implementation\" of parts of Python's numeric tower and abstract collection libraries (modules numbers and collections.abc). I won't comment on every detail in it, but there are a few points worth mentioning:\n\n- Struct types and immutability\n- Abstract classes (where *some* unimplemented signatures remain)\n- Overloaded class constructors/converters (unresolved, but see __fromint__, etc)\n- Global status of protocol names\n- Type argument syntax: list[int]\n- Type parameter binding syntax, with protocol/baseclass constraints: Sequence[A] or Sequence[A(Eq)]\n- Recursion between protocol and type\n- Extension of a protocol itself\n- Uniqueness of extensions (see int(Eq) and int(Ord) alternatives)\n- Join protocols (see Collection[A])\n- Protocols as types: either universal quant as in Haskell, or existential quant as in Swift (unresolved)\n- Inferring constrained types, or heavy defaulting? (unresolved)\n- Back to a nominal subtyping core, row polymorphism to handle tuple/record extensions only (and maybe unions)\n- The option type via subtyping\n- Associated types (future)\n- Mutability effects ignored when extending mutable to protocol (for example: iter() on a MutableSet should be monadic)\n- Notice Set, Mapping, Sequence extensions with additional constraint on type parameter\n- Appropriatness of SupportsX, Reversible, etc...?\n- Translation into plain classes...\n- Equivalent Haskell constructs...\n\n############################################################\n\nprotocol Eq:\n    @staticmethod\n    __eq__          : (Self,Self) -> bool\n    @staticmethod\n    __ne__          : (Self,Self) -> bool\n    \n    def __ne__(a,b):\n        return not (a == b)\n\nprotocol Ord (Eq):\n    @staticmethod\n    __lt__          : (Self,Self) -> bool\n    @staticmethod\n    __le__          : (Self,Self) -> bool\n    @staticmethod\n    __gt__          : (Self,Self) -> bool\n    @staticmethod\n    __ge__          : (Self,Self) -> bool\n\n    def __le__(a,b):\n        return a < b or a == b\n    def __gt__(a,b):\n        return b < a\n    def __ge__(a,b):\n        return b <= a\n\nextension int (Eq):                                 # ALTERNATIVE 1: SEPARATE EXTENSIONS\n    def __eq__(a:int, b:int) -> bool:               #\n        return primeqint(a,b)                       #\nextension int (Ord):                                #\n    def __lt__(a:int, b:int) -> bool:               #\n        return primltint(a,b)                       #\n\nextension int (Ord):                                # ALTERNATIVEL 2: A JOINT EXTENSION\n    def __eq__(a:int, b:int) -> bool:               #\n        return primeqint(a,b)                       #\n    def __lt__(a:int, b:int) -> bool:               #\n        return primltint(a,b)                       #\n\nprotocol Hashable (Eq):\n    __hash__        : () -> int\n\nprotocol SupportsInt:\n    __int__         : () -> int\n\nextension int (SupportsInt):\n    def __int__(self):\n        return self\n\nprotocol SupportsFloat:\n    __float__       : () -> float\n\nprotocol SupportsComplex:\n    __complex__     : () -> complex\n\nprotocol SupportsAbs:\n    __abs__         : () -> Self\n\nprotocol SupportsRound:\n    __round__       : () -> int\n\nprotocol Logical:\n    @staticmethod\n    __and__         : (Self,Self) -> Self\n    @staticmethod\n    __or__          : (Self,Self) -> Self\n    @staticmethod\n    __xor__         : (Self,Self) -> Self\n\nprotocol Plus:\n    @staticmethod\n    __add__         : (Self,Self) -> Self\n\nprotocol Minus:\n    @staticmethod\n    __sub__         : (Self,Self) -> Self\n\nprotocol Number (Ord, Plus, Minus):\n    __pos__         : () -> Self\n    __neg__         : () -> Self\n    @staticmethod\n    __mul__         : (Self,Self) -> Self\n    @staticmethod\n    __pow__         : (Self,Self) -> Self\n\nextension int (Number):\n    def __pos__(self):\n        return self\n    def __neg__(self):\n        return primnegint(self)\n    def __add__(a, b) -> int:\n        return primaddint(a,b)\n    def __sub__(a, b) -> int:\n        return primaddint(a,b)\n    def __mul__(a, b) -> int:\n        return primmulint(a,b)\n\nprotocol Complex (Number, SupportsAbs, SupportsComplex):\n    @staticmethod\n    __fromcomplex__ : (complex) -> Self\n    @staticmethod\n    __div__         : (Self,Self) -> Self\n    real            : () -> Real\n    imag            : () -> Real\n    conjugate       : () -> Self\n\nprotocol Real (Complex, SupportsRound, SupportsFloat):\n    @staticmethod\n    __fromfloat__   : (float) -> Self\n    __trunc__       : () -> Integral\n    __floor__       : () -> Integral\n    __ceil__        : () -> Integral\n    @staticmethod\n    __divmod__      : (Self,Self) -> (Self,Self) \n    @staticmethod\n    __floordiv__    : (Self,Self) -> Integral    \n    @staticmethod\n    __mod__         : (Self,Self) -> Self        \n\n    def __complex__(a):\n        return complex(float(a))\n    def real(a):\n        return fromfloat(float(a))\n    def imag(a):\n        return fromfloat(0.0)\n    def conjugate(a):\n        return a\n    def divmod(a,b):\n        return (a//b, a%b)\n\nprotocol Rational (Real):\n    numerator       : () -> Integral\n    denominator     : () -> Integral\n    \n    def __float__(a):\n        return numerator(a) / denominator(a)\n\nprotocol Integral (Rational,SupportsInt,Logical):\n    @staticmethod\n    __fromint__     : (int) -> Self\n    __index__       : () -> Self\n    @staticmethod\n    __lshift__      : (Self,Self) -> Self\n    @staticmethod\n    __rshift__      : (Self,Self) -> Self\n    __invert__      : () -> Self\n    \n    def __index__(a):\n        return int(a)\n    def __lshift__(a,b):\n        return fromint(int(a) << int(b))\n    def __invert__(a):\n        return fromint(~int(a))\n    def __float__(a):\n        return float(int(a))\n    def numerator(a):\n        return a\n    def denominator(a):\n        return 1\n\nextension int (Integral):\n    def __fromint__(a):\n        return a\n    def __int__(self):\n        return self\n    def __and__(a,b):\n        return prinandint(a,b)\n\nextension bool (Logical,Ord):\n    def __and__(a,b):\n        return b if a else False\n    def __eq__(a,b):\n        return primeqbool(a,b)\n    def __lt__(a,b):\n        return a == False and b == True\n\nprotocol IncrementalLogical[A] (Logical):\n    __iand__        : !(A) -> None\n    __ior__         : !(A) -> None\n    __ixor__        : !(A) -> None\n\nprotocol IncrementalPlus[A] (Plus):\n    __iadd__        : !(A) -> None\n\nprotocol IncrementalMinus[A] (Minus):\n    __isub__        : !(A) -> None\n\nprotocol Foldable[A]:\n    __fold__        : ((A,B)->B, B) -> B\n\nprotocol Iterable[A]:                               # MUTUAL RECURSION BETWEEN TYPE AND PROTOCOL\n    __iter__        : () -> Iterator[A]             #\n                                                    #\nstruct Iterator[A] (Iterable[A]):                   #\n    __next__        : !() -> A                      #\n                                                    #\n    def __iter__(self): return self                 #\n\nprotocol Reversible[A] (Iterable[A]):\n    __reversed__    : () -> Self\n\nprotocol Container[A]:\n    __contains__    : (A) -> bool\n\nprotocol Sized:\n    __len__         : () -> int\n\nprotocol Indexed[A,B]:\n    __getitem__     : (A) -> B\n\nprotocol Collection[A] (Container[A], Sized, Iterable[A]):\n    @staticmethod\n    __fromiter__    : (Iterable[A]) -> Self\n\nprotocol Set[A] (Collection[A], Ord, Logical, Minus):\n    isdisjoint      : (Set[A]) -> bool\n\n    def __le__(a: Self, b: Self):\n        if len(a) > len(b):\n            return False\n        for elem in a:\n            if elem not in b:\n                return False\n        return True\n    def __lt__(a: Self, b: Self):\n        if len(a) == len(b):\n            return False\n        return a <= b\n    def __eq__(a: Self, b: Self):\n        return len(a) == len(b) and a <= b\n    def __or__(a: Self, b: Self):\n        chain = [ e for s in [a,b] for e in s ]\n        return fromiter(chain)\n    def isdisjoint(self: Self, other: Set[A]):\n        for value in b:\n            if value in self:\n                return False\n        return True\n\nextension Set[A (Hashable)] (Hashable):\n    def __hash__(self):\n        n = 12345\n        for k in self:\n            n += hash(k)\n        return n\n\nstruct frozenset[A (Hashable)] (Set[A], Hashable):          # HYPOTHETICAL DEFINITION!\n    _val        : frozendict[A,()]\n\n    def __contains__(self, a):\n        return a in self._val.keys()\n    def __fromiter__(items: Iterable[A]):\n        return frozenset(_val = { i:() for i in items })\n    def __len__(self):\n        return len(self._val)\n    def __iter__(self):\n        return iter(self._val.keys())\n\nprotocol MutableSet[A] (Set[A], IncrementalLogical[Set[A]], IncrementalMinus[Set[A]]):\n    add             : !(A) -> None\n    pop             : !() -> A\n    clear           : !() -> None\n    update          : !(Set[A]) -> None\n    \n    def clear(self: Self):\n        try:\n            while True:\n                self.pop()\n        except KeyError:\n            pass\n\n    def __ior__(self: Self, other: Set[A]):\n        for value in other:\n            self.add(value)\n\nclass set[A (Hashable)] (MutableSet[A]):\n    def __len__(self): ...\n    def __contains__(self, a): ...\n    def __iter__(self): ...\n\n    def __eq__(self, other): ...\n    def __lt__(self, other): ...\n    def __or__(self, other): ...\n\n    def add(self, a): ...\n    def update(self, other): ...\n    def __ior__(self, other): ...\n    def copy(self): ...\n\nprotocol MutableIndexed[A,B] (Indexed[A,B]):\n    __setitem__     : !(A,B) -> None\n    __delitem__     : !(A) -> None\n\nprotocol Mapping[A,B] (Collection[A], Indexed[A,B]):\n    keys            : () -> Iterator[A]\n    values          : () -> Iterator[B]\n    items           : () -> Iterator[(A,B)]\n\nextension Mapping[A, B(Eq)] (Eq):\n    def __eq__(a: Self, b: Self):\n        if len(a) != len(b):\n            return False\n        for i in a:\n            if i not in b:\n                return False\n            if a[i] /= b[i]:\n                return False\n        return True\n\nprotocol MutableMapping[A,B] (Mapping[A,B], MutableIndexed[A,B]):\n    update          : !(Mapping[A,B]) -> None\n\nprotocol Sequence[A] (Collection[A], Indexed[int,A], Reversible[A], Plus):\n    def __add__(self, other):       ...\n    def __contains__(self, key):    ...\n    def __iter__(self):             ...\n    def __reversed__(self):         ...\n\nextension Sequence[A(Eq)] (Eq):\n    def __eq__(a: Self, b: Self):\n        if len(a) != len(b):\n            return False\n        for i in range(0,len(a)):\n            if a[i] != b[i]:\n                return False\n        return True\n\nextension Sequence[A (Eq)]:        \n    index           : (A) -> int?\n    count           : (A) -> int\n    \n    def index(self, val): ...\n    def count(self, val): ...\n\nprotocol MutableSequence[A] (Sequence[A], MutableIndexed[int,A], IncrementalPlus[Sequence[A]]):\n    append          : !(A) -> None\n    __iadd__        : !(Sequence[A]) -> None\n    \n    def append(self, other):\n        ...\n    def __iadd__(self, other):\n        self.append(other)\n\n"
  },
  {
    "path": "workspace/Typesystem.txt",
    "content": "TODO:\n    - Distinguishing required and available (defaulted) class/protocol attributes\n    - Check subtyping (not equality) among overridden methods in classes\n    - Witness translation\n    - Automatic lifting of 's' to str (subtyping?)\n    - Automatic lifting of int,... etc to (int|u) (subtyping?)\n    - Static deadlock detection\n    - Protocols as types, with existential quantification\n    - Struct cases (and pattern-matching)\n    - Type parameter variances\n    - Higher-order polymorphism\n    - Type macros / abstract types / associated types\n    - Kind correctness\n    - Read state effect (distinguish state effects per data structure?)\n    - Clean up row order (l-to-r or r-to-l)\n    - Read MPJ's Parametric Type Classes\n\n\nNOTES:\n    - Named structs are gone! Their equivalents are obtained by classes inheriting from \"struct\".\n    - Static methods in protocols must mention Self, or else they would be ambiguous (see translation into classes)\n    - Methods that mention Self in a negative position *must* be static in order to preserve type soundness\n    - Static methods (or just methods that mention Self negatively) must only be selected by class.\n    - The [q] part in class, protocol and extension is required, but can be left out (and inferred) in actor and def(s).\n    - Unambiguity in type schemes: for each [q]=>t it must hold that fv(q) <= fv(t)  (not checked here)\n    - Structs, classes and protocols have no ambiguity problems since q is always explicit there and the dom(q) are all in the resulting type.\n    - Consistency requirement on extensions not checked here (from Haskell): if  N |- t impl p  and  N |- p(p')  then  N |- t impl u'\n        - Alternatively: if  N |- t ~ extension(u)  and  N |- u < u'  then  N |- t ~ extension(u')\n        - Concretely: if   c:[q]=>extension(d[o])  and  d[q']=>protocol(d'[o'])  both exist in N\n                      then c:[q\"]=>extension(d'[o\"])  must also exist in N such that  [o/dom(q')]o' = phi(o\") and  N,q,[o/dom(qd)]q' |- q\"\n    - Acyclic subtype/protocol hierarchy not checked here\n    - Single subtype ancestry not checked here\n    - Protocol attributes must be globally unique (not checked here)\n    - Precondition to rule ImplExt: a unique (or best matching...) t(u) extension must exist in N (not checked here)\n    - Termination requirements on q in extension c[q](o) not checked here (allow growing terms except in protocol cycles)\n    - Self in the range of a substitution is forbidden but not checked here (maybe allow in covariant positions in the future)\n    - Python's @classmethods are gone! Absorbed by protocols.\n    - On class signatures:\n        \n                              Attribute         |     stored in class:  |    stored in instance:  |\n                            -----------------------------------------------------------------------\n                              of function type: |   <empty> (default)   |   @property             |\n                                                |   @static             |                         |\n                            -----------------------------------------------------------------------\n                              of ground type:   |   @static             |   @property (default)   |\n                            -----------------------------------------------------------------------\n    \n    - Protocol signatures can only use @static\n    \n    - Unused meta variables: d,i,s,I,J,P,U,Y\n\n\n***** Syntax ***************************************************************************************************************************************************\n\n        \nProtocol names:     P\nClass names:        C                                                                                   including int,bool,str,string literals,Msg,Ref,super\nType variables:     X                                                                                   includes Self\n\nTypes:              t,u     ::=     X  |  c  | EX(p)  |  e(r)->t  |  (r)  |  ?t  |  None                var, con, existential, fun, tuple/record, opt, void\nProtocols:          p       ::=     P[o]\nClasses:            c       ::=     C[o]                                                                including int,bool,str,string literals,Msg,Ref,super\nType orderings:     o       ::=     t,o  |  .                                                           associative\n\nRows:               r       ::=     h,k                                                                 associative\nHead rows:          h       ::=     t,h  |  *X  |  .                                                    associative\nKeyword rows:       k       ::=     x:t,k  |  **X  |  .                                                 associative, commutative\\duplicates\nEffects:            e       ::=     pure  |  mut[X]  |  act[X]  |  async  |  actor  |  X\nFunction contexts:  f       ::=     e[t]\n\nType schemas:       T       ::=     [q]=>t  |  t\nQua(l|nt)ifiers:    q       ::=     X(c,pi),q  |  .                                                     associative\nGoals:              g       ::=     t(c,pi),g  |  .                                                     associative\n\nEnvironments:       N       ::=     C:[q]=>(c;n)  |  P:[q]=>(pi;n)  |  w:[q]=>C(p)  |  w:q  |\n                                    x:T  |  z:t  |  x:#  |  z:#  |  N,N  |  .                           associative, commutative\\duplicates\n\nAttribute envs:     n       ::=     x:T  |  n,n  |  .                                                   associative, commutative\\duplicates\n\nWitness variables:  v\nWitness terms:      w       ::=     (subset of E)\n\n\n\n***** Judgments ************************************************************************************************************************************************\n\n\nN |- D : N'                 Declaration D generates bindings N' in environment N\n\nN |- w : c ~ n              Class type c exports attributes n, if instantiated with w\n\nN |- w : p ~ n              Protocol p exports attributes n, if instantiated with w\n\nN |- w : g                  Goal (constraint) g holds, as witnessed by w\n\nN |- w : t < t'             Type (schema) T is a subtype (schema) of T' in environment N, as witnessed by w\n\nN |- E : T | e              Expression E has type (scheme) T and effect e in environment N\n\nN |- F : r | N'             Formal F has type row r in environment N (if updated with N')\n\nN |- S : N' | f             Statement S generates bindings N' in environment N and function context f\n\nN |- X : N' | f             Except clause X generates bindings N' in environment N and function context f\n\nN |- S : t | e              Statement S returns values of type t with effect e in environment N\n\n\n\n***** N |- D : N' **********************************************************************************************************************************************\n\n\nN,v:q |- _ : c1 ~ n1     n not in n1     N |- M : n' ~> M'     n' in [q,Self(C[dom(q)]]=>(Self)->(n,n1)\n------------------------------------------------------------------------------------------------------- (Class)\nN |- class C[q](c1):n,M  :  C:[q]=>(mro(c1);n,n1)  ~>  !class C[q](c):(n,M')\n\n\nN,v:q |- wi : pi ~ ni / all i     n not in ni     N,v:q |- M : n' ~> M'     n' in [Self(P[dom(q)])]=>(Self)->(n,ni)\n------------------------------------------------------------------------------------------------------------------------------------- (Proto)\nN |- protocol P[q](pi):n,M  :  P:[q]=>(mro(pi);n,ni)  ~>  !class P[Self,q]():(n,(v')->[v'.v/v]M',def _init_(v',v):v'.i=pi(wi);v'.v=v)\n\n\nN,v:q |- w : p1 ~ n1     N,v:q |- _ : C[dom(q)] ~ n     N,v:q |- M : n' ~> M'     n' in [Self(C[dom(q)])]=>(Self)->(n1)\n----------------------------------------------------------------------------------------------------------------------------------------------- (Ext)\nN |- extension C[q](p1):M  :  P_C:[q]=>C(mro(p1))  ~>  !class P_C[q](P[C[dom(q)],o]):((v')->[v'.v/v]M',def _init_(v',v):p1._init_(v',w);v'.v=v)\n\n\nN' = N,v:q,bv(F,S):#,bz(S):#,_self_:Ref[X]      N' |- F : r | N1     N',N1 |- S : t | act[X]     X not in fv(N,q,r,t)\n--------------------------------------------------------------------------------------------------------------------- (Actor)\nN |- actor x[q](F):S  :  (x : [q]=>actor(r)->t)  ~>  actor x[dom(q)](v:q,F'):S'\n\n\nN' = N,v:q,bv(F,S):#      N' |- F : r | N1 | e      N',N1 |- S : t | e\n----------------------------------------------------------------------- (Def)\nN |- def x[q](F):S  :  (x : [q]=>e(r)->t)  ~>  def x[dom(q)](v:q,F'):S'\n\n\nN |- D1 : N1      N |- D2 : N2\n------------------------------ (Decls)\nN |- D1,D2 : N1,N2\n\n\n\n***** N |- w : c ~ n *******************************************************************************************************************************************\n\n\nN,C:[q]=>(c;n) |- w : [o/q]q\n----------------------------------- (SigC)\nN,C:[q]=>(c;n) |- w : C[o] ~ [o/q]n\n\n\n\n***** N |- w : p ~ n *******************************************************************************************************************************************\n\n\nN,P:[q]=>(pi;n) |- w : [o/q]q\n------------------------------------ (SigP)\nN,P:[q]=>(pi;n) |- w : P[o] ~ [o/q]n\n\n\n\n***** N |- w : g ***********************************************************************************************************************************************\n\n\nN,C:[q]=>(c;n) |- w : [o/q]q                            N,v:[q]=>C(p) |- w : [o/q]q\n-------------------------------------- (WitC)           ------------------------------------- (WitP)\nN,C:[q]=>(c;n) |- \\x:x : C[o] ([o/q]c)                  N,v:[q]=>C(p) |- v(w) : C[o] ([o/q]p)\n\nN,P:[q]=>(pi;n) |- w : t(P[o])\n------------------------------------------- (WitSub)\nN,P:[q]=>(pi;n) |- w.i : t([o/q]pi) / all i\n\nN |- w' : t < c    N |- w : t(pi),g                     N |- wi : t(pi) / all i     N |- w : g                     \n----------------------------------- (ConsC)             -------------------------------------- (ConsP)              ----------- (Cons0)\nN |- w : t(c,pi),g                                      N |- (wi,*w) : t(pi),g                                      N |- () : .\n\n\n-------------- (WitHyp)\nN,v:q |- v : q\n\nN |- w : t(c,pi),g                                      N |- w : t(c,pi),g                                          N |- w : t(c,pi),g\n------------------ (HypC)                               ------------------------ (HypP)                             --------------------- (Hyp1)\nN |- \\x:x : t < c                                       N |- w.i : t(pi) / all i                                    N |- w.*i : g / max i\n\n\n\n***** N |- w : t < t' ******************************************************************************************************************************************\n\n\n                                                                                    N |- w : t < t'    N |- w' : t' < t''\n----------------- (SubRefl)                                                         ------------------------------------- (SubTrans)\nN |- \\x:x : t < t                                                                   N |- \\x.w'(w(x)) : t < t''\n\n\nN |- w : t(p)                                                                       N,p:[q]=>(pi;r) |- w : [o/q]q\n------------------------- (SubPack)                                                 ---------------------------------------------------------------- (SubEX)\nN |- \\x:(w,x) : t < EX(p)                                                           N,p:[q]=>(pi;r) |- \\x:(x.0.i,x) : EX(P[o]) < EX([o/q]pi) / all i\n\n\nN |- w : (r') < (r)     N |- w' : t < t'    N |- e < e'                             N |- _self_ : Ref[X]\n------------------------------------------------------- (SubFun)                    ---------------------------------------------------- (SubAsync)\nN |- \\x:\\***y:w'(x(***w(y))) : e(r)->t < e'(r')->t'                                 N |- \\x:ASYNC(_self_,x) : act[X](r)->t < async(r)->t\n\n\n------------------ (SubPure)                                                        -------------------- (SubMut)\nN |- pure < mut[X]                                                                  N |- mut[X] < act[X]\n\n------------------------------------ (SubMsg)                                       ------------------------------- (SubNew)\nN |- async(r)->t < act[X](r)->Msg[t]                                                N |- actor(r)->t < act[X](r)->t\n\n\nN |- w : (k) < (r)                                                                  N |- w : t < t'     N |- w' : (r) < (r')\n------------------------------------- (SubOptP)                                     ------------------------------------------------------------ (SubRowP)\nN |- \\v:(None,***w(v)) : (k) < (?t,r)                                               N |- \\v: (\\x,***y: (w(x),***w'(y)) )(***v) : (t,r) < (t',r')\n\nN |- w : () < (k)                                                                   N |- w : t < t'     N |- w' : (k) < (k')\n--------------------------------------- (SubOptK)                                   --------------------------------------------------------------- (SubRowK)\nN |- \\v:(x=None,**w(v)) : () < (x:?t,k)                                             N |- \\v: (\\x,**y: (x=w(x),**w'(y)) )(**v) : (x:t,k) < (x:t',k')\n\nN |- w : t < t'     N |- w' : (r) < (k)\n----------------------------------------------------------- (SubShift)              ------------------- (SubStr)\nN |- \\v:(\\x,***y:(x=w(x),**w'(y)))(***v) : (t,r) < (x:t',k)                         N |- \\x:x : s < str\n\n\n------------------ (SubOpt)                                                         --------------------- (SubNone)     \nN |- \\x:x : t < ?t                                                                  N |- \\x:x : None < ?t\n\n\n\n***** N |- E : T | e *******************************************************************************************************************************************\n\n\nN |- E : t | e ~> E'     N |- w : t < t'     N |- e < e'                            N |- E : [q]=>t | e ~> E'     N |- w : [o/q]q\n-------------------------------------------------------- (Sub)                      --------------------------------------------- (Inst)\nN |- E : T' | e'  ~>  w(E')                                                         N |- E : [o/q]t | e  ~>  app(E,w)\n\n\n                                                                                    N |- _self_ : Ref[X]\n------------------------- (Var)                                                     ------------------------------------- (Read)\nN,x:t |- x : t | e  ~>  x                                                           N,z:t |- z : t | act[X]  ~>  _self_.z\n\n\nN |- E : (t,r) | e                      N |- E : (t,r) | e                          N |- E : (h,x:t,k) | e\n------------------ (SelHead)            ------------------- (SelTail)               ---------------------- (SelKwd...)\nN |- E.0 : t | e                        N |- E.*1 : (r) | e                         N |- E.x : t | e\n\n\nN |- E : t | e ~> E'    N |- t < c    N |- w : c ~ (x:T,n)   Self not in T-         N |- w : C[o] ~ (x:T,n)\n--------------------------------------------------------------------------- (Sel)   -------------------------------------------------------- (CSel)\nN |- E.x : [t/Self]T | e  ~>  app(E'.x, w)                                          N |- C.x : [C[o]/Self]addself(T) | e  ~>  app2nd(C.x, w)\n\nN |- E : t | e ~> E'    N |- w : t (p)    N |- w : p ~ (x:T,n)                      N |- w : C[o] (p)     N |- w : p ~ (x:T,n)\n-------------------------------------------------------------- (SelP)               --------------------------------------------- (CSelP)\nN |- E.x : [t/Self]T | e  ~>  app(w.x, E')                                          N |- C.x : [C[o]/Self]addself(T) | e  ~>  w.x\n\nN |- E : EX(p) | e ~> E'    N |- _ : p ~ (x:T,n)    Self not in T-                  N |- w : t (P[o])     N |- w : P[o] ~ (x:T,n)\n------------------------------------------------------------------ (SelP')          ------------------------------------------ (CSelP')\nN |- E.x : [EX(p)/Self]T | e  ~>  app(E'.0.x, E'.1) ...                             N |- P.x : [t/Self]addself(T) | e  ~>  w.x\n\n\n\nN' = N,bv(F):#,bz(N):#     N' |- F : r | N1     N',N1 |- E : t | e                  N |- E : e(r)->t | e     N |-> (A) : (r) | e\n------------------------------------------------------------------ (Lam)            -------------------------------------------- (App)\nN |- (lambda F: E) : e(r)->t | pure  ~>  lambda F: E'                               N |- E(A) : t | e\n\n\nN |- w : C[o] ~ (_init_:e(r)->None,n)\n---------------------------------------- (Cons)\nN |- C : e(r)->C[o] | pure  ~>  app(C,w)\n\n\nN |- E : bool | e     N |- E1 : t | e     N |- E2 : t | e                           N |- S : t | e\n--------------------------------------------------------- (If1)                     ----------------- (Do)                  -------------------- (None)\nN |- E1 if E else E2 : t | e                                                        N |- do S : t | e                       N |- None : None | e\n\n\nN |- E : t | e     N |- (A) : (r) | e                                               N |- E : (h) | e      N |- (M) : (k) | e\n------------------------------------- (ETup)                                        ---------------------------------------- (EStar1)\nN |- (E,A) : (t,r) | e                                                              N |- (*E,M) : (h,k) | e\n\nN |- E : t | e     N |- (M) : (k) | e                                               N |- E : (k) | e\n------------------------------------- (ERec)                                        -------------------- (EStar2)           ------------------ (ENull)\nN |- (x=E,M) : (x:t,k) | e                                                          N |- (**E) : (k) | e                    N |- (.) : (.) | e\n\n\nN |- E : Msg[t] | act[X]\n------------------------- (Await)\nN |- await E : t | act[X]\n\n\n\n***** N |- F : r | N *******************************************************************************************************************************************\n\n\nN |- x : t | N1      N,N1 |- F : r | N2                                             N |- x : (h) | N1       N,N1 |- K : k | N2\n--------------------------------------- (PatTup)                                    ------------------------------------------ (PatStar1)\nN |- x,F : t,r | N1,N2                                                              N |- *x,K : h,k | N1,N2\n\nN |- x : t | N1      N,N1 |- K : k | N2                                             N |- x : (k) | N1\n--------------------------------------- (PatRec)                                    ----------------- (PatStar2)\nN |- x,K : x:t,k | N1,N2                                                            N |- **x : k | N1\n\nN |- x : t | N1     N |- E : t | pure     N,N1 |- F : r | N2\n------------------------------------------------------------ (PatOpt)               -------------- (PatNull)\nN |- x=E,F : t,r | N1,N2                                                            N |- . : . | .\n\n\n-------------------- (Bind)                                                         ------------------ (Rebind)\nN,x:# |- x : t | x:T                                                                N,x:t |- x : t | .\n\n\n\n***** N |- S : N | f *******************************************************************************************************************************************\n\n\nN |- E : t | e                  N |- x : t | N'     N |- E : t | e                  N |- F : r | N'     N |- E : (r) | e\n------------------- (Run)       ---------------------------------- (AssignVar)      ------------------------------------ (AssignPat)\nN |- E  :  . | e[u]             N |- x = E  :  N' | e[u]                            N |- (F) = E  :  N' | e[u]\n\nN,N' |- D : N'                  N |- E : t | e[t]\n----------------- (Decl)        -------------------------- (Return)                 ------------------- (Pass)\nN |- D  :  N' | f               N |- return E  :  . | e[t]                          N |- pass  :  . | f\n\n\n\nN |- E1 : c | mut[X]    N |- _ : c ~ (@prop x:t,r)    N |- c < object[X]     N |- E2 : t | mut[X]\n------------------------------------------------------------------------------------------------- (Mut)\nN | E1.x = E2  :  . | mut[X][u]\n\n\nN |- E : bool | e     N |- S1 : N1 | f     N |- S2 : N2 | f                         N |- E : bool | e     N |- S : N' | f\n----------------------------------------------------------- (If2)                   ------------------------------------- (While)\nN |- if E: S1 else S2  :  N1&N2 | f                                                 N |- while E: S  :  . | f\n\n\nN,z:# |- E : t | mut[X]     N |- _self_ : Ref[X]                                    N,z:t |- E : t | mut[X]     N |- _self_ : Ref[X]\n------------------------------------------------ (State)                            ------------------------------------------------ (Write)\nN,z:# |- var z = E  :  z:t | mut[X]                                                 N,z:t |- z = E  :  . | mut[X]\n\n\nN |- E1 : int | act[X]     N |- _self_ : Ref[X]    N |- E2(A) : t | act[X]          N |- S : N1 | f     N,N1 |- S2 : N2 | f\n-------------------------------------------------------------------------- (After)  --------------------------------------- (Seq)\nN |- after E1: E2(A)  :  . | act[X][u]                                              N |- S1; S2  :  N1,N2 | f\n\n\nN |- S : N1 | f    N |- X : N2 | f     N |- S1 : N1' | f    N |- S2 : N2' | f                   N |- S : N' | e[t]     N |- e < e'\n----------------------------------------------------------------------------- (Try)             ---------------------------------- (SubFX)\nN |- try S X else S1 finally S2 : ((N1,N1')&N2),N2' | f                                         N |- S : N' | e'[t]\n\n\n***** N |- X : N | f *******************************************************************************************************************************************\n\n\nN,x:C[] |- S : N1 | f    N |- X : N2 | f                                            \n---------------------------------------- (Except1)                                  --------------- (Except0)\nN |- except C as x: S X : N1&N2 | f                                                 N |- . : N' | f\n\n\n***** N |- S : t | e *******************************************************************************************************************************************\n\n\nN |- S : N' | e[t]     btc(N') # ftc(t,e)     not thru(S)                           N |- S : N' | e[t]    N |- None < t     thru(S)\n--------------------------------------------------------- (Result)                  ----------------------------------------------- (Thru)\nN |- S : t | e                                                                      N |- S : t | e\n\n    thru(return E)                      = False\n    thru(raise E)                       = False\n    thru(while E: S)                    = thru(S)\n    thru(if E: S1 else S2)              = thru(S1) or thru(S2)\n    thru(S1; S2)                        = thru(S1) and thru(S2)\n    thru(try S X else S1 finally S2)    = (thru(S;S1) or thru(X)) and thru(S2)\n    thru(_)                             = True\n\n    thru(except c as x: S X)            = thru(S) or thru(X)\n    thru(.)                             = False\n\n\nN |- S : t | mut[X]    X not in fv(N,t)\n--------------------------------------- (RunST)\nN |- S : t | pure\n\n\n\n################################################################################################################################################################\n################################################################################################################################################################\n\n\nN,v:B(Ord) |- v._Eq_ : B(Eq)\n------------------------------------------------- (SubInst)\nN,v:B(Ord) |- \\y:y(v._Eq_) : [A(Eq)]=>t[A] < t[B]\n-------------------------------------------------------------- (SubGen)\nN |- \\x:\\v:(\\y:y(v._Eq_))(x)  : [A(Eq)]=>t[A] < [B(Ord)]=>t[B]\nN |- \\x:\\v:    x(v._Eq_)      : [A(Eq)]=>t[A] < [B(Ord)]=>t[B]\n\n\nN,v:A(Eq) |- \\a,b: Eq._eq_(a,b) : (A,A)->bool  ~>  \\a,b: v._eq_(a,b)\n------------------------------------------------------------------------- (Gen)\nN |- \\a,b: Eq._eq_(a,b) : [A(Eq)]=>(A,A)->bool  ~>  \\v':\\a,b: v'._eq_(a,b)         N |- \\x:\\v:x(v._Eq_) : [A(Eq)]=(A,A)->bool[A] < [B(Ord)]=>(B,B)->bool[B]\n----------------------------------------------------------------------------------------------------------------------------------------------------------- (Sub)\nN |- \\a,b: Eq._eq_(a,b) : [B(Ord)]=>(B,B)->bool  ~>  (\\x:\\v:x(v._Eq_))(\\v':\\a,b: v'._eq_(a,b))\nN |- \\a,b: Eq._eq_(a,b) : [B(Ord)]=>(B,B)->bool  ~>      \\v:(\\v':\\a,b: v'._eq_(a,b))(v._Eq_)\nN |- \\a,b: Eq._eq_(a,b) : [B(Ord)]=>(B,B)->bool  ~>      \\v:\\a,b: v._Eq_._eq_(a,b)\n\n###################################################################################\n\nclass Apa [X(Eq)]:\n    a : X\n    def _init_(self,a:X):                                           : [X(Eq), Self(Apa[X])] => (Self, X) -> None\n        self.a = a\n    def apa(self, y:X):                                             : [X(Eq), Self(Apa[X])] => (Self, X) -> bool\n        return Eq._eq_(self.a, y)\n\nclass Bepa [X(Ord)] (Apa[X]):       [X(Ord)]=>Bepa[X](Apa[X]) |-\n    b : X\n    def _init_(self, a:X, b:X):                                     : [X(Ord), Self(Bepa[X])] => (Self, X, X) -> None\n        Apa._init_(self,a)\n        self.b = b\n    def bepa(self, y:X):                                            : [X(Ord), Self(Bepa[X])] => (Self, X) -> bool\n        return self.apa(y) or Ord._lt_(self.b, y)\n        \n=====>\n\nclass Apa [X]:\n    a : X\n    def _init_(self, w:Eq[X], a:X):                                 : [X, S(Apa[X])] => (S, Eq[X], X) -> None\n        self.a = a\n    def apa(self, w:Eq[X], y:X):                                    : [X] => (Apa, Eq[X], X) -> bool\n        return w._eq_(self.a, y)\n\n\nclass Bepa [X] (Apa[X]):            id:[X]=>(Ord[X],Apa[X])->Bepa[X] |-\n    b : X\n    def _init_(self, w:Ord[X], a:X, b:X):                           : [X] => (Bepa, Ord[X], X, X) -> None\n        Apa._init_(self, _Ord_to_Eq(w), a)\n        self.b = b\n    def bepa(self, w:Ord[X], y:X):                                  : [X] => (Bepa, Ord[X], X) -> bool\n        return self.apa(_Ord_to_Eq(w), y) or w._lt_(self.b, y)\n\n###################################################################################\n\nprotocol Container[A(Eq)]:                      Container:[A(Eq)]=>(_contains_:(A)->bool) |-\n    _contains_ : (A) -> bool\n    def _contains_(self:Self, a:A):\n        return False\n\nprotocol Maximal[A(Ord)] (Container[A]):        ..., Maximal:[A(Ord)]=>(max:()->A), [A(Ord)]=>Maximal[A](Container[A]) |-\n    max : () -> A\n\nextension list[A(Ord)] (Maximal[A]):\n    def _contains_(self:Self, a:A):\n        for i in range(len(self)):\n            if Eq._eq_(self[i], a):\n                return True\n        return False\n    def max(self:Self):\n        m = None\n        for i in range(len(self)):\n            if Ord._lt_(m, self[i]):\n                m = self[i]\n        return m\n\n=====>\n\nclass Container[S,A]:                           Container:[S,A]=>(w1:Eq[A], _contains_:(S,A)->bool) |-\n    w1 : Eq[A]\n    _contains_ : (S, A) -> bool\n    def _contains_(wit:Self, self:S, a:A):\n        return False\n\nclass Maximal[S,A] (Container[S,A]):            ..., Maximal:[S,A]=>(w2:Ord[A], max:(S)->A), id:[S,A]=>(Container[S,A])->Maximal[S,A] |-\n    w2 : Ord[A]\n    max : (S, A) -> A\n\nclass Maximal_list[A] (Maximal[list[A],A]):\n    def _init_(wit:Self, w:Ord[A]):\n        wit.w1 = w\n        wit.w2 = w\n    def _contains_(wit:Self, self:S, a:A):\n        for i in range(len(self)):\n            if wit.w1._eq_(self[i], a):\n                return True\n        return False\n    def max(wit:Self, self:S):\n        m = None\n        for i in range(len(self)):\n            if wit.w2._lt_(m, self[i]):\n                m = self[i]\n        return m\n    \n\n###################################################################################\n\n\nCONV(cs) =\n    CONV(ds,cs)                     for ds in lbr(cs)\n    CONV(d,cs)                      for d in rbr(cs)\n    class nm(cs) tpar(cs) base(cs):\n      d : d tpar(d)                 for d in newrbr(cs) + last(cs)\n      def __init__(x,xs):           where x,xs = par(cs)\n        x.d = nm(d,ds,cs)(x,xs)     for d,ds in lbr(cs)\n        x.d = nm(d,cs)(x,xs)        for d in rbr(cs)\n        x.d = c                     for (d,c) in binds(cs)\n      ...\n\nbr(c)       =       { cs,c | cs in br(d) } U { d,c | d in ds }      if c(d,ds)\nlbr(c..)    =       br(d)                                           \nrbr(c..)    =       {ds}                                            \nnewrbr(c)   =       rbr(c)\nnewrbr(cs)  =       {}\n\nbr(c) = lbr(c..) = rbr(c..) = {}                                    otherwise\n\nc << d      =       if c(d',ds) and d' = d or d' << d\n\nnm(c)       =       _c\nnm(cs,ds)   =       nm(cs)nm(ds)\n\nbase(c)     =       (d[S,o])                                        if c[q](d[o],ds)\n            =       ()                                              otherwise\nbase(cs,c)  =       (nm(cs)[dom(q)])                                if tpar(c) = [q]\n\nlast(c)     =       {}\nlast(cs,c)  =       {c}\n\nbinds(c,cs) =       cs `zip` rh(cs)\n\nrh(cs,d,c)  =       rh(cs,c),c                                      if c << d\n            =       rh(cs,d),c                                      otherwise\nrh(cs)      =       cs\n\ntpar(cs,c)  =       [Self,q]                                        if c[q](...)\n\npar(d,c,cs) =       par(c,cs)                                       if c << d\n            =       d,par(c,cs)                                     otherwise\npar(xs)     =       cs\n\n################################################################\n\nA       B       C       D       E       F       G       H\n \\     .         \\     .         \\     .         \\     .\n  \\   .           \\   .           \\   .           \\   .\n    I               J               K               L\n     \\             .                 \\             .\n       \\         .                     \\         .\n         \\     .                         \\     .\n            M                               N\n             \\                             .\n                \\                       .\n                   \\                 .\n                      \\           .\n                         \\     .\n                            O\n\nA[X,Y]()     B[Z]()     C()     D()     E()     F()     G()     H()\n    I[X](A[X,int],B[str])   J[Z](C,D)      K(E,F)          L(G,H)\n            M[X](I[bool],J[(X,X)])                     N(K,L)\n                            O(M,N)\n\n-----------------------------------------------------------------\n\n# CONV(A)                                               lbr(A) = {}                 rbr(A) = {}\n    class A[X,Y]():                                     par(A) = A\n        def __init__(A):                                rh(.) = .\n            pass\n\n... B - G similarly ...\n\n# CONV(I)                                               lbr(I) = {}                 rbr(I) = {B}\n    # CONV(B,I)                                         lbr(B) = {}                 rbr(B) = {}\n        class B_I[X](B[str]):                           par(B,I) = B,par(I) = B,I\n            I : I\n            def __init__(B,I):                          rh(I) = I\n                B.I = I\n    class I[X](A[X,int]):                               par(I) = I\n        B : B[str]\n        def __init__(I):                                rh(.) = .\n            I.B = B_I(@X,I)\n\n# CONV(J)                                               lbr(J) = {}                 rbr(J) = {D}\n    # CONV(D,J)                                         lbr(D) = {}                 rbr(D) = {}\n        class D_J(D):                                   par(D,J) = D,par(J) = D,J\n            J : J\n            def __init__(D,J):                          rh(J) = J\n                D.J = J\n    class J(C):                                         par(J) = J\n        D : D\n        def __init__(J):                                rh(.) = .\n            J.D = D_J(D)\n\n# CONV(K)                                               lbr(K) = {}                 rbr(K) = {F}\n    # CONV(F,K)                                         lbr(F) = {}                 rbr(F) = {}\n        class F_K(F):                                   par(F,K) = F,par(K) = F,K\n            K : K\n            def __init__(F,K):                          rh(K) = K\n                F.K = K\n    class K(E):                                         par(K) = K\n        F : F\n        def __init__(K):                                rh(.) = .\n            K.F = F_K(K)\n\n# CONV(L)                                               lbr(L) = {}                 rbr(L) = {H}\n    # CONV(H,L)                                         lbr(H) = {}                 rbr(H) = {}\n        class H_L(H):                                   par(H,L) = H,par(L) = L\n            L : L\n            def __init__(H,L):                          rh(L) = L\n                H.L = L\n    class L(G):                                         par(L) = L\n        H : H\n        def __init__(L):                                rh(.) = .\n            L.H = H_L(L)\n\n# CONV(M)                                               lbr(M) = {B,I}              rbr(M) = {J}\n    # CONV(B,I,M)                                       lbr(B) = {}                 rbr(B) = {}\n        class B_I_M[X](B_I[bool]):                      par(B,I,M) = B,par(I,M) = B,par(M) = B,M\n            M : M\n            def __init__(B,M):                          rm(I,M) = rm(M),M = M,M\n                B.I = M\n                B.M = M\n    # CONV(J,M)                                         lbr(J) = {}                 rbr(J) = {D}\n        # CONF(D,J,M)                                   lbr(D) = {}                 rbr(D) = {}\n            class D_J_M[X](D_J[(X,X)]):                 par(D,J,M) = D,par(J,M) = D,J,par(M) = D,J,M\n                M : M\n                def __init__(D,J,M):                    rh(J,M) = rh(J),M = J,M\n                    D.J = J\n                    D.M = M\n        class J_M[X](J[(X,X)]):                         par(J,M) = J,par(M) = J,M\n            M : M\n            def __init__(J,M):                          rh(M) = M\n                J.D = D_J_M(J,M)\n                J.M = M\n    class M[X](I[bool]):                                par(M) = M\n        J : J\n        def __init__(M):                                rh(.) = .\n            M.B = B_I_M(@bool,M)\n            M.J = J_M(M)\n\n# CONV(N)                                               lbr(N) = {F,K}              rbr(N) = {L}\n    # CONV(F,K,N)                                       lbr(F) = {}                 rbr(F) = {}\n        class F_K_N(F_K):                               par(F,K,N) = F,par(K,N) = F,par(N) = F,N\n            N : N\n            def __init__(F,N):                          rh(K,N) = rn(N),N = N,N\n                F.K = N\n                F.N = N\n    # CONV(L_N)                                         lbr(L) = {}                 rbr(L) = {H}\n        # CONV(H,L,N)                                   lbr(H) = {}                 rbr(H) = {}\n            class H_L_N(H_L):                           par(H,L,N) = H,par(L,N) = H,L,par(N) = H,L,N\n                N : N\n                def __init__(H,L,N):                    rh(L,N) = rn(L),N = L,N\n                    H.L = L\n                    H.N = N\n        class L_N(L):                                   par(L,N) = L,par(N) = L,N\n            N : N\n            def __init__(L,N):                          rh(N) = N\n                L.H = H_L_N(L,N)\n                L.N = N\n    class N(K):                                         par(N) = N\n        L : L\n        def __init__(N):                                rh(.) = .\n            N.F = F_K_N(N)\n            N.L = L_N(N)\n\n\n# CONV(O)                                               lbr(O) = {B,I,M,O | J,M}    rbr(O) = {N}\n    # CONV(B,I,M,O)                                     lbr(B) = {}                 rbr(B) = {}\n        class B_I_M_O (B_I_M):                          par(B,I,M,O) = B,par(I,M,O) = B,par(M,O) = B,par(O) = B,O\n            O : O\n            def __init__(B,O):                          rh(I,M,O) = rh(I,O),O = rh(O),O,O = O,O,O \n                B.I = O\n                B.M = O\n                B.O = O\n    # CONV(J,M,O)                                       lbr(J) = {}                 rbr(J) = {D}\n        # CONV(D,J,M,O)                                 lbf(D) = {}                 rbr(D) = {}\n            class D_J_M_O(D_J_M):                       par(D,J,M,O) = D,par(J,M,O) = D,J,par(M,O) = D,J,par(O) = D,J,O\n                O : O\n                def __init__(D,J,O):                    rh(J,M,O) = rh(J,O),O = R(J),O,O = J,O,O\n                    D.J = J\n                    D.M = O\n                    D.O = O\n        class J_M_O(J_M):                               par(J,M,O) = J,par(M,O) = J,par(O) = J,O\n            O : O\n            def __init__(J,O):                          rh(M,O) = rh(O),O = O,O\n                J.D = D_J_M_O(J,O)\n                J.M = O\n                J.O = O\n    # CONV(N,O)                                         lbr(N) = {F,K}              rbr(N) = {L}\n        # CONV(F,K,N,O)                                 lbr(F) = {}                 rbr(F) = {}\n            class F_K_N_O(F_K_N):                       par(F,K,N,O) = F,par(K,N,O) = F,par(N,O) = F,N,par(O) = F,N,O\n                O : O\n                def __init__(F,N,O):                    rh(K,N,O) = rn(K,N),O = rn(N),N,O = N,N,O\n                    F.K = N\n                    F.N = N\n                    F.O = O\n        # CONV(L,N,O)                                   lbr(L) = {}                 rbr(L) = {H}\n            # CONV(H,L,N,O)                             lbr(H) = {}                 rbr(H) = {}\n                class H_L_N_O(H_L_N):                   par(H,L,N,O) = H,par(L,N,O) = H,L,par(N,O) = H,L,N,par(O) = H,L,N,O\n                    O : O\n                    def __init(H,L,N,O):                rh(L,N,O) = rn(L,N),O = rn(L),N,O = L,N,O\n                        H.L = L\n                        H.N = N\n                        H.O = O\n            class L_N_O(L_N):                           par(L,N,O) = L,par(N,O) = L,N,par(O) = L,N,O\n                O : O\n                def __init__(L,N,O):                    rh(N,O) = rh(N),O = N,O\n                    L.H = H_L_N_O(L,N,O)\n                    L.N = N\n                    L.O = O\n        class N_O(N):                                   par(N,O) = N,par(O) = N,O\n            O : O\n            def __init__(N,O):                          rh(O) = O\n                N.F = F_K_N_O(N,O)\n                N.L = L_N_O(N,O)\n                N.O = O\n    class O(M):                                         par(O) = O\n        N : N\n        def __init__(O):                                rh(.) = .\n            O.B = B_I_M_O(O)\n            O.J = J_M_O(O)\n            O.N = N_O(O)\n\n\n################################################################\n\nprotocol Eq:\n    @staticmethod\n    _eq_ : (Self,Self) -> bool\n\nprotocol Ord (Eq):\n    @staticmethod\n    _le_ : (Self,Self) -> bool\n    def _eq_(x,y):\n        return _le_(x,y) and _le_(y,x)\n\nprotocol Hmm (Eq):\n    def _eq_(x,y):\n        return False\n    \nclass Apa (Ord)\n    def _eq_(x,y):\n        return x.apa == y.apa or super._eq_(x,y)\n    def _le_(x,y):\n        return x.apa <= y.apa\n\nclass Bepa (Apa,Hmm,Ord):\n    def _le_(x,y):\n        return x.bepa <= y.bepa\n\nself,other : Bepa\nEq._eq_(self,other)\n\n==============>      mro: Bepa, Apa, Hmm, Ord, Eq\n\nclass Eq[S]:\n    _eq_ : (S,S) -> bool\n\nclass Ord[S] (Eq[S]):\n    _le_ : (S,S) -> bool\n    def _eq_(wit,x,y):\n        return wit._le_(x,y) and wit._le_(y,x)\n\nclass Hmm[S] (Eq[S]):\n    def _eq_(wit,x,y):\n        return False\n\nclass Apa ():\n    pass\nclass Ord_Apa[S(Apa)] (Ord[S]):                             # NOT class Ord_Apa[] (Ord[Apa]), which would preclude inheritance (in Bepa)\n    def _eq_(wit,x,y):\n        return x.apa == y.apa or super._eq_(x,y)            # super == super(Ord_Apa,cls), i.e., it passes on cls to Ord._eq_!\n    def _le_(wit,x,y):\n        return x.apa <= y.apa\n\nclass Bepa (Apa):\n    pass                                                    # NOTE: [S(Bepa)]=>Ord_Bepa[S] </ [S(Apa)]=>Ord_Apa[S]\nclass Hmm_Bepa[S(Bepa)] (Hmm[S]):\n    _Ord : Ord_Bepa\n    def __init__(wit):\n        wit._Ord = Ord_Bepa(wit)\n    def _eq_(wit,a,b):\n        return False\nclass Ord_Bepa[S(Bepa)] (Ord[S]):\n    _Hmm : Hmm_Bepa\n    _eq_ = Ord_Apa._eq_                                     # [S(Apa)]=>(S,S)->bool < [S(Bepa)]=>(S,S)->bool            ??????????????\n    def _le_(wit,x,y):\n        return x.bepa <= y.bepa\n\nself,other : Bepa\n\n_eq_(self,other) ==> \nOrd_Bepa._eq_(Ord_Bepa,self,other) ==> \nOrd_Apa._eq_(Ord_Bepa,self,other) ==> \n... Ord._eq_(Ord_Bepa,self,other) ==>\n... Ord_Bepa._le_(Ord_Bepa,self_other) and ... ==>\n... self.bepa <= y.bepa ...\n\n==============>\n\nstruct Eq_class;                                                            struct Ord_class;\ntypedef struct Eq_class *Eq_class;                                          typedef struct Ord_class *Ord_class;\n                                                                            $bool Ord$_eq_(Ord_class, $WORD, $WORD);\n\nstruct Eq_class {                                                           struct Ord_class { // extends Eq_class\n    $bool(*_eq_)(Eq_class,$WORD,$WORD);                                         $bool (*_eq_)(Ord_class,$WORD,$WORD);\n};                                                                              $bool (*_le_)(Ord_class,$WORD,$WORD);\n                                                                            };\n\n                                                                            $bool Ord$_eq_(Ord_class cls, $WORD x, $WORD y) {\n                                                                                return cls->_le_(cls,x,y) && cls->_le_(cls,y,x);\n                                                                            }\n\n/////\n\nstruct Apa;                                                                 struct Bepa;\ntypedef struct Apa *Apa;                                                    typedef struct Bepa *Bepa;\n\nstruct Apa {                                                                struct Bepa { // extends Apa\n    Apa_class __class__;                                                        Bepa_class __class__;\n    $int apa;                                                                   $int apa;\n};                                                                              $int bepa;\n                                                                            };\n\n/////\n\nstruct Ord_Apa;                                                             struct Ord_Bepa;\ntypedef struct Ord_Apa *Ord_Apa;                                            typedef struct Ord_Bepa *Ord_Bepa;\n$bool Apa$_eq_(Ord_Apa, Apa, Apa);                                          $bool Bepa$_le_(Ord_Bepa, Bepa, Bepa);\n$bool Apa$_le_(Ord_Apa, Apa, Apa);\n\nstruct Ord_Apa { // extends Ord_class                                       struct Ord_Bepa { // extends Ord_class\n    $bool (*_eq_)(Ord_Apa,Apa,Apa);                                             $bool (*_eq_)(Ord_Bepa,Bepa,Bepa);\n    $bool (*_le_)(Ord_Apa,Apa,Apa);                                             $bool (*_le_)(Ord_Bepa,Bepa,Bepa);\n    $bool (*Ord_Apa$super$_eq_)(Ord_Apa,Apa,Apa);                               $bool (*Ord_Apa$super$_eq_)(Ord_Bepa,Bepa,Bepa);\n} Ord_Apa = {                                                               } Ord_Bepa = {\n    Apa$_eq_,       // _eq_                                                     Apa$_eq_,       // _eq_\n    Apa$_le_,       // _le_                                                     Bepa$_le_,      // _le_\n    Ord$_eq_        // Ord_Apa$super$_eq_                                       Ord$_eq_        // Ord_Apa$super$_eq_\n};                                                                          };\n\n$bool Apa$_eq_(Ord_Apa cls, Apa x, Apa y) {\n    return x->apa==y->apa || cls->Ord_Apa$super$_eq_(cls,x,y);\n}\n$bool Apa$_le_(Ord_Apa cls, Apa x, Apa y) {                                 $bool Bepa$_le_(Ord_Bepa cls, Bepa x, Bepa x) {\n    return x->apa <= y->apa;                                                    return x->bepa <= y->bepa;\n}                                                                           }\n\n/////\n    \nBepa self;\nBepa other;\nw_Ord_Bepa = &Ord_Bepa;\n\nw_Ord_Bepa->_eq_(w_Ord_Bepa,self, other) ==> \nApa$_eq_(w_Ord_Bepa, self, other) ==> \n... w_Ord_Bepa->Ord_Apa$super$_eq_(w_Ord_Bepa, self, other)\n... Ord$_eq_(w_Ord_Bepa, self, other) ==>\n... w_Ord_Bepa->_le_(w_Ord_Bepa, self, other) and ... ==>\n... Bepa$_le_(w_Ord_Bepa, self, other) and ... ==>\n... self.bepa <= other.bepa ...\n\n########################\nprotocol Eq ()\nprotocol Ord (Eq)\nprotocol Rational ()\nprotocol Integer (Rational)\nclass tt ()\nextension tt (Integer,Rational)\nextension tt (Ord)\n---\nMRO(Eq)         = [Eq]\nMRO(Ord)        = [Ord,Eq]\nMRO(Rational)   = [Rational]\nMRO(Integer)    = [Integer,Rational]\nMRO(tt)         = [tt]\nMRO(tt_1)       = [tt_1,tt,Integer,Rational]\nMRO(tt_2)       = [tt_2,tt_1,tt,Integer,Rational,Ord,Eq]\n\nMRO(tt_1)       = [tt,Integer,Rational]\nMRO(tt_2)       = [tt,Ord,Eq]\n########################\n\n****************************************************************************************************************************************************************\n****************************************************************************************************************************************************************\n"
  },
  {
    "path": "workspace/anomaly_detector/acton_anomaly_detector2.py",
    "content": "'''\n@author: aagapi\n'''\n\nimport numpy as np\n\nimport pandas as pd\nfrom optparse import OptionParser\n\ndo_plots = True\nif do_plots:\n    import matplotlib.pyplot as plt\n    from statsmodels.tsa.seasonal import DecomposeResult\n\nimport sys\nsys.path.append('python_libs/stl/')\nfrom stl import decompose, forecast, naive, drift, mean, seasonal_naive\nimport datetime\n\nTRAIN_RATIO=0.75\n\nparser = OptionParser()\nparser.add_option(\"-x\", \"--input-file-x\", type=\"str\", dest=\"file_name_x\", default=None, help=\"Path to input file name X\")\nparser.add_option(\"-n\", \"--feature-name\", type=\"str\", dest=\"feature_name\", default=None, help=\"Input feature name\")\nparser.add_option(\"-o\", \"--output-dir\", type=\"str\", dest=\"output_dir\", default=None, help=\"Path to output dir for plots\")\nparser.add_option(\"-R\", \"--train-ratio\", dest=\"train_ratio\", type=\"float\", default=0.75, help=\"Train ratio\")\n\noptions, args = parser.parse_args()\n\nfile_name_x=options.file_name_x\nfeature=options.feature_name\noutput_dir=options.output_dir\nTRAIN_RATIO=options.train_ratio\n\nanomaly_examples = {\n                    'level_change' : ['ambient_temperature_system_failure.csv', 'ec2_cpu_utilization_825cc2.csv', 'ec2_cpu_utilization_ac20cd.csv', 'grok_asg_anomaly.csv', 'rds_cpu_utilization_cc0c53.csv', 'rds_cpu_utilization_e47b3b.csv'],\n                    'outliers' : ['ec2_cpu_utilization_fe7f93.csv', 'rogue_agent_key_hold.csv'],\n                    'seasonal' : ['Twitter_volume_GOOG.csv', 'art_daily_jumpsdown.csv', 'art_daily_jumpsup.csv', 'art_daily_nojump.csv', 'exchange-2_cpc_results.csv', 'exchange-2_cpm_results.csv', 'exchange-3_cpm_results.csv', 'nyc_taxi.csv', 'occupancy_6005.csv', 'occupancy_t4013.csv'],\n                    'trending' : ['ambient_temperature_system_failure.csv'],\n                    'variance_change' : ['exchange-3_cpm_results.csv']    \n    }\n\ndef plot_feature(observed_idx, observed, col_name):\n    fig, ax1 = plt.subplots(figsize=(12, 5))\n    plt.title('{} time plot'.format(col_name))\n    plt.plot(observed, color='b')\n    ax1.set_xlabel('time')\n    ax1.set_ylabel('{}'.format(col_name), color='k')\n    plt.legend(['{}'.format(col_name)], loc=(0.01, 0.95))\n    plt.savefig('%s/feature_plot_%s.png' % (output_dir, col_name))\n    plt.show()\n\ndef plot_decomp(trend, seasonal, resid, observed, period_averages, feature):\n    \n    decomp = DecomposeResult(seasonal=seasonal,\n                         trend=trend,\n                         resid=resid, \n                         observed=observed,\n                         period_averages=period_averages)\n    \n    decomp.plot()\n    plt.savefig('%s/decomp_%s.png' % (output_dir, feature))\n    plt.show()\n\ndef plot_forecast(observed, observed_short, observed_idx, observed_idx_short, trend, seasonal, resid, forecast_array, forecast_idx, feature):\n    plt.title('Forecast plot')\n    \n    plt.plot(observed_idx, observed, label='truth') ## '-'\n    plt.plot(observed_idx_short, observed_short, label='obs') ## '-'\n    plt.plot(observed_idx_short, trend, label='decomp.trend') ## ':'\n    plt.plot(forecast_idx, forecast_array, label='FCAST' ) ## '-'\n    plt.legend();    \n    plt.savefig('%s/forecast_%s.png' % (output_dir, feature))\n    plt.show()\n\ndef plot_forecast_and_anomalies(observed, observed_short, trend, seasonal, resid, forecast_array, forecast_idx, feature, anomalies, tag):\n    plt.title('Anomaly algorithm: %s'%(tag))\n    \n    plt.plot(observed_idx, observed, label='truth') ## '-'\n    plt.plot(observed_idx_short, observed_short, label='obs') ## '-'\n    plt.plot(observed_idx_short, trend, label='decomp.trend') ## ':'\n    plt.plot(forecast_idx, forecast_array, label='FCAST' ) ## '-'\n    \n    for (start, end) in anomalies:\n        print(start - forecast_idx[0], end - forecast_idx[0])\n        plt.plot(start, 10, end, 10, marker = 'o')\n\n    plt.legend();    \n    plt.savefig('%s/forecast_%s_%s.png' % (output_dir, feature, tag))\n\n    plt.show()\n\n\ndef arrays_to_dict(observed_idx, observed):\n    return {observed_idx[i]: observed[i] for i in range(len(observed_idx))}\n\ndf = pd.read_csv(file_name_x)\n\nif feature is None:\n    feature = file_name_x[(file_name_x.rfind('/')+1):file_name_x.rfind('.')]\n## print(feature)\n\n\nDEFAULT_EMA_SMOOTHING_FACTOR = 0.2\nDEFAULT_EMA_WINDOW_SIZE_PCT = 0.2\n# Percentage threshold on anomaly score below which is considered noises.\nDEFAULT_NOISE_PCT_THRESHOLD = 0.001\n\ndef denoise_scores(scores):\n    if scores:\n        maximal = max(scores.values())\n        if maximal:\n            for key in scores:\n                if scores[key] < DEFAULT_NOISE_PCT_THRESHOLD * maximal:\n                    scores[key] = 0\n    return scores\n\ndef compute_ema(smoothing_factor, points):\n    ema = []\n    if(len(points) > 0):\n        ema.append(points[0])\n    for i in range(1, len(points)):\n        ema.append(smoothing_factor * points[i] + (1 - smoothing_factor) * ema[i - 1])\n    return ema\n\ndef compute_anom_score_ema(lag_window_points, point, smoothing_factor):\n    ema = compute_ema(smoothing_factor, lag_window_points)[-1]\n    return abs(point - ema)\n\ndef ema_anomaly_detector(timestamps, values, smoothing_factor = DEFAULT_EMA_SMOOTHING_FACTOR, lag_window_size = None, use_lag_window = True):\n    \"\"\"\n    Compute anomaly scores based on an exponential moving average.\n    \"\"\"\n    \n    lag_window_size = lag_window_size if lag_window_size is not None else int(len(timestamps) * DEFAULT_EMA_WINDOW_SIZE_PCT)\n    anom_scores = {}\n\n    if use_lag_window:\n        stdev = np.std(values)\n        for i in range(len(timestamps)):\n            timestamp = timestamps[i]\n            value = values[i]\n\n            if i < lag_window_size:\n                anom_score = compute_anom_score_ema(values[:i + 1], value, smoothing_factor)\n            else:\n                anom_score = compute_anom_score_ema(values[i - lag_window_size: i + 1], value, smoothing_factor)\n            if stdev:\n                anom_scores[timestamp] = anom_score / stdev\n            else:\n                anom_scores[timestamp] = anom_score\n    else:\n        ema = compute_ema(smoothing_factor, values)\n        stdev = np.std(values)\n        for i in range(len(timestamps)):\n            timestamp = timestamps[i]\n            value = values[i]\n            anom_score = abs((value - ema[i]) / stdev) if stdev else value - ema[i]\n            anom_scores[timestamp] = anom_score\n\n    return denoise_scores(anom_scores)\n\ndef np_sign(arr):\n    \"\"\"  Stand-in for numpy sign()\"\"\"\n    signs = []\n    for i in range(len(arr)):\n        signs.append(1 if arr[i] > 0 else -1)\n    return np.array(signs)\n\ndef np_ones(size):\n    \"\"\"  Stand-in for numpy ones()\"\"\"\n    ones = []\n    for i in range(size):\n        ones.append(1)\n    return np.array(ones)\n\ndef np_argwhere(arr):\n    \"\"\"  Stand-in for numpy argwhere()\"\"\"\n    indices = []\n    for i in range(len(arr)):\n        if arr[i] > 0:\n            indices.append(i)\n    return np.array(indices)\n\ndef np_fmax_const(arr, const):\n    \"\"\" Stand-in for numpy fmax with a constant \"\"\"\n    values = []\n    for i in range(len(arr)):\n        values.append(arr[i] if arr[i] > const else const)\n    return np.array(values)\n\ndef np_convolve_valid(arr1, arr2):\n    \"\"\" Stand-in for numpy convolve with mode = valid (no extrapolation on edges) \"\"\"\n    flipped_arr2 = []\n    for i in range(len(arr2)):\n        flipped_arr2.append(arr2[len(arr2) - i - 1])\n    \n    if len(arr2) > len(arr1):\n        return np.array([])\n    \n    convolution = []\n    for index in range(len(arr1) - len(arr2) + 1):\n        sum = 0\n        for i in range(len(arr2)):\n            sum += arr1[index + i] * flipped_arr2[i]\n        convolution.append(sum)\n    \n    return np.array(convolution)    \n\ndef merge_ranges(ranges, max_gap):\n    \"\"\"\n        Merge ranges which are closer than max_gap\n    \"\"\"\n    merged_ranges = []\n    for range in ranges:\n        if merged_ranges:\n            curr_start, curr_end = range\n            # compare against last interval in merged_ranges\n            pre_start, pre_end = merged_ranges[-1]\n            if curr_start - pre_end < max_gap:\n                # merge current range with the last range in the list\n                merged_ranges[-1] = (pre_start, max(curr_end, pre_end))\n            else:\n                # append the new range to current one\n                merged_ranges.append(range)\n        else:\n            # no merged ranges - just add this one\n            merged_ranges.append(range)\n\n    return merged_ranges\n\n\ndef sign_test_anomaly_detector(x, y, k=24, alpha=0.05, offset=0.0, conf=0.01, gap=0):\n    if len(x) != len(y) or len(x) < k:\n        return list()\n\n    # our filter to convolve with - just counts\n    f = np_ones(k)\n\n    # Threshold below calculated as quantile function for a binomial distribution with:\n    #   - probability of success=0.5\n    #   - confidence level p=0.01\n    #   - window size = 24 (2 hours at 5 minutes intervals)\n    # == Smallest k such that Prob(X <= k) >= p\n    # == scipy.stats.binom.ppf(1 - 0.01, 24, 0.5) - 1\n    \n    qthresh = 17.0\n    \n    alpha1 = 1. + alpha\n    diff_array = x - offset\n    diff_array = diff_array - (alpha1 * y)\n\n    # this is 1 if bigger 0 otherwise\n    d = np_fmax_const(np_sign(diff_array), 0)\n#    d = np_fmax_const(np_sign(x - offset - (1. + alpha) * y), 0)\n#    d = np.fmax(np.sign(x - offset - (1. + alpha) * y), 0)\n\n    con = np_convolve_valid(d, f)\n#    con = np.convolve(f, d, mode='valid')\n\n    a = np_fmax_const(con - qthresh, 0)\n#    a = np.fmax(con - qthresh, 0)\n\n    ranges = []\n    for t in np_argwhere(a):\n        ranges.append((t, t + k))        \n\n    ranges = merge_ranges(ranges, gap)\n\n    return ranges\n\n\n## df['timestamp']=pd.to_datetime(df['timestamp'])\n## df = df.set_index('timestamp')\n\nobserved_idx = df['timestamp'].values\nobserved = df['value'].values\n\nif do_plots:\n    plot_feature(observed_idx, observed, feature)  \n\nperiod=int(24 * 60 / 5)\nloess_window = 0.8\n\n(trend, seasonal, resid, period_averages, phase) = decompose(observed, period=period, lo_window_frac=loess_window)\nif do_plots:\n    plot_decomp(trend, seasonal, resid, observed, period_averages, feature)\n\nno_periods=int(len(observed)/period)\nobserved_short = observed[:int(TRAIN_RATIO*no_periods)*period]\nobserved_idx_short = observed_idx[:int(TRAIN_RATIO*no_periods)*period]\nobserved_test = observed[int(TRAIN_RATIO*no_periods)*period:]\nobserved_idx_test = observed_idx[int(TRAIN_RATIO*no_periods)*period:]\n\n(trend, seasonal, resid, period_averages, phase) = decompose(observed_short, period=period, lo_window_frac=loess_window)\n(forecast_array, forecast_idx) = forecast(observed_short, observed_idx_short,\n                 trend, seasonal, resid, period_averages, phase,\n                 steps=len(observed_test), fc_func=drift,\n                 forecast_seasonal=True, correlate_phase=False)\n\nif do_plots:\n    plot_forecast(observed, observed_short, observed_idx, observed_idx_short, trend, seasonal, resid, forecast_array, forecast_idx, feature)\n\ndf_observed_dict=arrays_to_dict(observed_idx_test, observed_test)\nfcast_dict=arrays_to_dict(forecast_idx, forecast_array)\n\nanomaly_windows = sign_test_anomaly_detector(observed_test, forecast_array, k=24, alpha=0.2, offset=0.0, conf=0.01, gap=0)\nanomaly_timestamps = []\nfor (start, end) in anomaly_windows:\n   anomaly_timestamps.append((observed_idx_test[start], observed_idx_test[end])) \nprint('Detected anomaly windows:', anomaly_timestamps)\n\nif do_plots:\n    plot_forecast_and_anomalies(observed, observed_short, trend, seasonal, resid, forecast_array, forecast_idx, feature, anomaly_timestamps, 'anomaly_detector')\n\n## anomaly_scores = ema_anomaly_detector(observed_idx, observed)\n## print(anomaly_scores)\n\nif do_plots:\n    plt.close('all')\n    \n\n"
  },
  {
    "path": "workspace/anomaly_detector/acton_anomaly_detector3.py",
    "content": "'''\n@author: aagapi\n'''\n\nimport numpy as np\n\nimport pandas as pd\nfrom optparse import OptionParser\n\ndo_plots = True\nif do_plots:\n    import matplotlib.pyplot as plt\n    from statsmodels.tsa.seasonal import DecomposeResult\n\nimport sys\nsys.path.append('python_libs/stl/')\nfrom stl import decompose, forecast, naive, drift, mean, seasonal_naive\nimport datetime\n\nTRAIN_RATIO=0.75\n\nparser = OptionParser()\nparser.add_option(\"-x\", \"--input-file-x\", type=\"str\", dest=\"file_name_x\", default=None, help=\"Path to input file name X\")\nparser.add_option(\"-n\", \"--feature-name\", type=\"str\", dest=\"feature_name\", default=None, help=\"Input feature name\")\nparser.add_option(\"-o\", \"--output-dir\", type=\"str\", dest=\"output_dir\", default=None, help=\"Path to output dir for plots\")\nparser.add_option(\"-R\", \"--train-ratio\", dest=\"train_ratio\", type=\"float\", default=0.75, help=\"Train ratio\")\n\noptions, args = parser.parse_args()\n\nfile_name_x=options.file_name_x\nfeature=options.feature_name\noutput_dir=options.output_dir\nTRAIN_RATIO=options.train_ratio\n\nanomaly_examples = {\n                    'level_change' : ['ambient_temperature_system_failure.csv', 'ec2_cpu_utilization_825cc2.csv', 'ec2_cpu_utilization_ac20cd.csv', 'grok_asg_anomaly.csv', 'rds_cpu_utilization_cc0c53.csv', 'rds_cpu_utilization_e47b3b.csv'],\n                    'outliers' : ['ec2_cpu_utilization_fe7f93.csv', 'rogue_agent_key_hold.csv'],\n                    'seasonal' : ['Twitter_volume_GOOG.csv', 'art_daily_jumpsdown.csv', 'art_daily_jumpsup.csv', 'art_daily_nojump.csv', 'exchange-2_cpc_results.csv', 'exchange-2_cpm_results.csv', 'exchange-3_cpm_results.csv', 'nyc_taxi.csv', 'occupancy_6005.csv', 'occupancy_t4013.csv'],\n                    'trending' : ['ambient_temperature_system_failure.csv'],\n                    'variance_change' : ['exchange-3_cpm_results.csv']    \n    }\n\ndef plot_feature(observed_idx, observed, col_name):\n    fig, ax1 = plt.subplots(figsize=(12, 5))\n    plt.title('{} time plot'.format(col_name))\n    plt.plot(observed, color='b')\n    ax1.set_xlabel('time')\n    ax1.set_ylabel('{}'.format(col_name), color='k')\n    plt.legend(['{}'.format(col_name)], loc=(0.01, 0.95))\n    plt.savefig('%s/feature_plot_%s.png' % (output_dir, col_name))\n    plt.show()\n\ndef plot_decomp(trend, seasonal, resid, observed, period_averages, feature):\n    \n    decomp = DecomposeResult(seasonal=seasonal,\n                         trend=trend,\n                         resid=resid, \n                         observed=observed,\n                         period_averages=period_averages)\n    \n    decomp.plot()\n    plt.savefig('%s/decomp_%s.png' % (output_dir, feature))\n    plt.show()\n\ndef plot_forecast(observed, observed_short, observed_idx, observed_idx_short, trend, seasonal, resid, forecast_array, forecast_idx, feature):\n    plt.title('Forecast plot')\n    \n    plt.plot(observed_idx, observed, label='truth') ## '-'\n    plt.plot(observed_idx_short, observed_short, label='obs') ## '-'\n    plt.plot(observed_idx_short, trend, label='decomp.trend') ## ':'\n    plt.plot(forecast_idx, forecast_array, label='FCAST' ) ## '-'\n    plt.legend();    \n    plt.savefig('%s/forecast_%s.png' % (output_dir, feature))\n    plt.show()\n\ndef plot_forecast_and_anomalies(observed, observed_short, trend, seasonal, resid, forecast_array, forecast_idx, feature, anomalies, tag):\n    plt.title('Anomaly algorithm: %s'%(tag))\n    \n    plt.plot(observed_idx, observed, label='truth') ## '-'\n    plt.plot(observed_idx_short, observed_short, label='obs') ## '-'\n    plt.plot(observed_idx_short, trend, label='decomp.trend') ## ':'\n    plt.plot(forecast_idx, forecast_array, label='FCAST' ) ## '-'\n    \n    for (start, end) in anomalies:\n        print(start - forecast_idx[0], end - forecast_idx[0])\n        plt.plot(start, 10, end, 10, marker = 'o')\n\n    plt.legend();    \n    plt.savefig('%s/forecast_%s_%s.png' % (output_dir, feature, tag))\n\n    plt.show()\n\n\ndf = pd.read_csv(file_name_x)\n\nif feature is None:\n    feature = file_name_x[(file_name_x.rfind('/')+1):file_name_x.rfind('.')]\n## print(feature)\n\ndef np_sign(arr):\n    \"\"\"  Stand-in for numpy sign()\"\"\"\n    signs = []\n    for i in range(len(arr)):\n        signs.append(1 if arr[i] > 0 else -1)\n    return np.array(signs)\n\ndef np_ones(size):\n    \"\"\"  Stand-in for numpy ones()\"\"\"\n    ones = []\n    for i in range(size):\n        ones.append(1)\n    return np.array(ones)\n\ndef np_argwhere(arr):\n    \"\"\"  Stand-in for numpy argwhere()\"\"\"\n    indices = []\n    for i in range(len(arr)):\n        if arr[i] > 0:\n            indices.append(i)\n    return np.array(indices)\n\ndef np_fmax_const(arr, const):\n    \"\"\" Stand-in for numpy fmax with a constant \"\"\"\n    values = []\n    for i in range(len(arr)):\n        values.append(arr[i] if arr[i] > const else const)\n    return np.array(values)\n\ndef np_convolve_valid(arr1, arr2):\n    \"\"\" Stand-in for numpy convolve with mode = valid (no extrapolation on edges) \"\"\"\n    flipped_arr2 = []\n    for i in range(len(arr2)):\n        flipped_arr2.append(arr2[len(arr2) - i - 1])\n    \n    if len(arr2) > len(arr1):\n        return np.array([])\n    \n    convolution = []\n    for index in range(len(arr1) - len(arr2) + 1):\n        sum = 0\n        for i in range(len(arr2)):\n            sum += arr1[index + i] * flipped_arr2[i]\n        convolution.append(sum)\n    \n    return np.array(convolution)    \n\ndef merge_ranges(ranges, max_gap):\n    \"\"\"\n        Merge ranges which are closer than max_gap\n    \"\"\"\n    merged_ranges = []\n    for range in ranges:\n        if merged_ranges:\n            curr_start, curr_end = range\n            # compare against last interval in merged_ranges\n            pre_start, pre_end = merged_ranges[-1]\n            if curr_start - pre_end < max_gap:\n                # merge current range with the last range in the list\n                merged_ranges[-1] = (pre_start, max(curr_end, pre_end))\n            else:\n                # append the new range to current one\n                merged_ranges.append(range)\n        else:\n            # no merged ranges - just add this one\n            merged_ranges.append(range)\n\n    return merged_ranges\n\n\ndef sign_test_anomaly_detector(x, y, k=24, alpha=0.05, offset=0.0, conf=0.01, gap=0):\n    if len(x) != len(y) or len(x) < k:\n        return list()\n\n    # our filter to convolve with - just counts\n    f = np_ones(k)\n\n    # Threshold below calculated as quantile function for a binomial distribution with:\n    #   - probability of success=0.5\n    #   - confidence level p=0.01\n    #   - window size = 24 (2 hours at 5 minutes intervals)\n    # == Smallest k such that Prob(X <= k) >= p\n    # == scipy.stats.binom.ppf(1 - 0.01, 24, 0.5) - 1\n    \n    qthresh = 17.0\n    \n    alpha1 = 1. + alpha\n    diff_array = x - offset\n    diff_array = diff_array - (alpha1 * y)\n\n    # this is 1 if bigger 0 otherwise\n    d = np_fmax_const(np_sign(diff_array), 0)\n#    d = np_fmax_const(np_sign(x - offset - (1. + alpha) * y), 0)\n#    d = np.fmax(np.sign(x - offset - (1. + alpha) * y), 0)\n\n    con = np_convolve_valid(d, f)\n#    con = np.convolve(f, d, mode='valid')\n\n    a = np_fmax_const(con - qthresh, 0)\n#    a = np.fmax(con - qthresh, 0)\n\n    ranges = []\n    for t in np_argwhere(a):\n        ranges.append((t, t + k))        \n\n    ranges = merge_ranges(ranges, gap)\n\n    return ranges\n\n\n## df['timestamp']=pd.to_datetime(df['timestamp'])\n## df = df.set_index('timestamp')\n\nobserved_idx = df['timestamp'].values\nobserved = df['value'].values\n\nif do_plots:\n    plot_feature(observed_idx, observed, feature)  \n\nperiod=int(24 * 60 / 5)\nloess_window = 0.8\n\n(trend, seasonal, resid, period_averages, phase) = decompose(observed, period=period, lo_window_frac=loess_window)\nif do_plots:\n    plot_decomp(trend, seasonal, resid, observed, period_averages, feature)\n\nno_periods=int(len(observed)/period)\nobserved_short = observed[:int(TRAIN_RATIO*no_periods)*period]\nobserved_idx_short = observed_idx[:int(TRAIN_RATIO*no_periods)*period]\nobserved_test = observed[int(TRAIN_RATIO*no_periods)*period:]\nobserved_idx_test = observed_idx[int(TRAIN_RATIO*no_periods)*period:]\n\nprint('AnomalyDetector: Forecasting on window of size', len(observed_idx), ', [', observed_idx[0], ', ' , observed_idx[-1], ']')\n\n(trend, seasonal, resid, period_averages, phase) = decompose(observed_short, period=period, lo_window_frac=loess_window)\n(forecast_array, forecast_idx) = forecast(observed_short, observed_idx_short,\n                 trend, seasonal, resid, period_averages, phase,\n                 steps=len(observed_test), fc_func=drift,\n                 forecast_seasonal=True, correlate_phase=False)\n\nif do_plots:\n    plot_forecast(observed, observed_short, observed_idx, observed_idx_short, trend, seasonal, resid, forecast_array, forecast_idx, feature)\n\nanomaly_windows = sign_test_anomaly_detector(observed_test, forecast_array, k=24, alpha=0.2, offset=0.0, conf=0.01, gap=0)\nanomaly_timestamps = []\nfor (start, end) in anomaly_windows:\n   anomaly_timestamps.append((observed_idx_test[start], observed_idx_test[end])) \nprint('DETECTED ANOMALY WINDOWS:', anomaly_timestamps)\n\nif do_plots:\n    plot_forecast_and_anomalies(observed, observed_short, trend, seasonal, resid, forecast_array, forecast_idx, feature, anomaly_timestamps, 'anomaly_detector')\n\nif do_plots:\n    plt.close('all')\n    \n\n"
  },
  {
    "path": "workspace/anomaly_detector/acton_anomaly_detector_demo.py",
    "content": "'''\n@author: aagapi\n'''\n\nimport numpy as np\n\nimport pandas as pd\nfrom optparse import OptionParser\n\nimport sys\nsys.path.append('python_libs/stl/')\nfrom stl import decompose, forecast, naive, drift, mean, seasonal_naive\n\nTRAIN_RATIO=0.75\nDEFAULT_EMA_SMOOTHING_FACTOR = 0.2\nDEFAULT_EMA_WINDOW_SIZE_PCT = 0.2\n# Percentage threshold on anomaly score below which is considered noises.\nDEFAULT_NOISE_PCT_THRESHOLD = 0.001\n\nparser = OptionParser()\nparser.add_option(\"-x\", \"--input-file-x\", type=\"str\", dest=\"file_name_x\", default=None, help=\"Path to input file name X\")\nparser.add_option(\"-n\", \"--feature-name\", type=\"str\", dest=\"feature_name\", default=None, help=\"Input feature name\")\nparser.add_option(\"-o\", \"--output-dir\", type=\"str\", dest=\"output_dir\", default=None, help=\"Path to output dir for plots\")\nparser.add_option(\"-R\", \"--train-ratio\", dest=\"train_ratio\", type=\"float\", default=0.75, help=\"Train ratio\")\n\noptions, args = parser.parse_args()\n\nfile_name_x=options.file_name_x\nfeature=options.feature_name\noutput_dir=options.output_dir\nTRAIN_RATIO=options.train_ratio\n\ndef arrays_to_dict(observed_idx, observed):\n    return {observed_idx[i]: observed[i] for i in range(len(observed_idx))}\n\nif feature is None:\n    feature = file_name_x[(file_name_x.rfind('/')+1):file_name_x.rfind('.')]\n## print(feature)\n\ndef denoise_scores(scores):\n    if scores:\n        maximal = max(scores.values())\n        if maximal:\n            for key in scores:\n                if scores[key] < DEFAULT_NOISE_PCT_THRESHOLD * maximal:\n                    scores[key] = 0\n    return scores\n\ndef compute_ema(smoothing_factor, points):\n    ema = []\n    if(len(points) > 0):\n        ema.append(points[0])\n    for i in range(1, len(points)):\n        ema.append(smoothing_factor * points[i] + (1 - smoothing_factor) * ema[i - 1])\n    return ema\n\ndef compute_anom_score_ema(lag_window_points, point, smoothing_factor):\n    ema = compute_ema(smoothing_factor, lag_window_points)[-1]\n    return abs(point - ema)\n\ndef ema_anomaly_detector(timestamps, values, smoothing_factor = DEFAULT_EMA_SMOOTHING_FACTOR, lag_window_size = None, use_lag_window = True):\n    \"\"\"\n    Compute anomaly scores based on an exponential moving average.\n    \"\"\"\n    \n    lag_window_size = lag_window_size if lag_window_size is not None else int(len(timestamps) * DEFAULT_EMA_WINDOW_SIZE_PCT)\n    anom_scores = {}\n\n    if use_lag_window:\n        stdev = np.std(values)\n        for i in range(len(timestamps)):\n            timestamp = timestamps[i]\n            value = values[i]\n\n            if i < lag_window_size:\n                anom_score = compute_anom_score_ema(values[:i + 1], value, smoothing_factor)\n            else:\n                anom_score = compute_anom_score_ema(values[i - lag_window_size: i + 1], value, smoothing_factor)\n            if stdev:\n                anom_scores[timestamp] = anom_score / stdev\n            else:\n                anom_scores[timestamp] = anom_score\n    else:\n        ema = compute_ema(smoothing_factor, values)\n        stdev = np.std(values)\n        for i in range(len(timestamps)):\n            timestamp = timestamps[i]\n            value = values[i]\n            anom_score = abs((value - ema[i]) / stdev) if stdev else value - ema[i]\n            anom_scores[timestamp] = anom_score\n\n    return denoise_scores(anom_scores)\n\nclass Sensor(object):\n    def __init__(self, file_name_x, feature, anomaly_detector, read_window_size = 100, repeats=100, trend=0.0):\n        self.repeats = repeats\n        self.trend = trend\n        self.read_window_size = read_window_size\n        self.anomaly_detector = anomaly_detector\n        df = pd.read_csv(file_name_x)\n        self.observed_idx = df['timestamp'].values\n        self.observed = df['value'].values\n        self.first_ts = self.observed_idx[0]\n        self.last_ts = self.observed_idx[-1]\n        self.timestep = self.observed_idx[1] - self.observed_idx[0]\n\n    def fix_timestamps(self, observed_idx, add_lag):\n        return (observed_idx + add_lag)\n\n    def fix_trend(self, observed, repeat_count, trend):\n        fixed_observed = np.zeros(len(observed))\n        for i in range(len(observed)):\n            fixed_observed[i] = observed[i] + (repeat_count*len(observed)+i)*trend\n        return fixed_observed\n\n    def run(self):\n        for i in range(self.repeats):\n            observed_idx = self.fix_timestamps(self.observed_idx, i*(self.last_ts - self.first_ts + self.timestep))\n            if self.trend > 0:\n                self.observed = self.fix_trend(self.observed, i, self.trend)\n            num_windows = len(observed_idx) // self.read_window_size + (len(observed_idx) % self.read_window_size)\n\n            for j in range(num_windows):\n                observed_idx_w = observed_idx[j*self.read_window_size:(j+1)*self.read_window_size]\n                observed_w = self.observed[j*self.read_window_size:(j+1)*self.read_window_size]\n                print('Sensor: Sending window ', j, ' of repeat ', i, ', length=', len(observed_idx_w), len(observed_w))\n                self.anomaly_detector.update(observed_idx_w, observed_w)\n\nclass AnomalyDetector(object):\n    def __init__(self, period, loess_window, min_train_window_size=3000):\n        self.observed_idx = None\n        self.observed = None\n        self.min_train_window_size = min_train_window_size\n        self.period = period\n        self.loess_window = loess_window\n        \n    def update(self, observed_idx_w, observed_w):\n        # Append received window:\n        if self.observed is None:\n            assert self.observed_idx is None\n            self.observed_idx = observed_idx_w\n            self.observed = observed_w\n        else:\n            assert self.observed_idx is not None\n            self.observed_idx = np.append(self.observed_idx, observed_idx_w)\n            self.observed = np.append(self.observed, observed_w)\n        # Truncate training window to last min_train_window_size entries:\n        if len(self.observed_idx) > self.min_train_window_size:\n            self.observed_idx = self.observed_idx[-self.min_train_window_size:]\n            self.observed = self.observed[-self.min_train_window_size:]\n            print('AnomalyDetector: Forecasting on window of size', len(self.observed_idx), ', [', self.observed_idx[0], ', ' , self.observed_idx[-1], ']')\n            self.detect_anomalies(self.observed_idx, self.observed)\n\n    def detect_anomalies(self, observed_idx, observed):\n        no_periods=int(len(observed)/self.period)\n        observed_short = observed[:int(TRAIN_RATIO*no_periods)*self.period]\n        observed_idx_short = observed_idx[:int(TRAIN_RATIO*no_periods)*self.period]\n        (trend, seasonal, resid, period_averages, phase) = decompose(observed_short, period=self.period, lo_window_frac=self.loess_window)\n        (forecast_array, forecast_idx) = forecast(observed_short, observed_idx_short,\n                                                     trend, seasonal, resid, period_averages, phase,\n                                                     steps=(len(observed)-len(observed_short)), fc_func=drift,\n                                                     forecast_seasonal=True, correlate_phase=False)\n                \n        df_observed_dict=arrays_to_dict(observed_idx, observed)\n        fcast_dict=arrays_to_dict(forecast_idx, forecast_array)\n        \n        anomaly_scores = ema_anomaly_detector(observed_idx, observed)\n        print(anomaly_scores)\n\nanomaly_detector = AnomalyDetector(period=int(24 * 60 / 5), loess_window = 0.8, min_train_window_size=3000)\nsensor = Sensor(file_name_x, feature, anomaly_detector, read_window_size = 100, repeats=2, trend=0.0)\nsensor.run()\n\n\n\n\n\n"
  },
  {
    "path": "workspace/anomaly_detector/acton_anomaly_detector_demo2.py",
    "content": "'''\n@author: aagapi\n'''\n\nimport numpy as np\n\nimport pandas as pd\nfrom optparse import OptionParser\n\nimport sys\nsys.path.append('python_libs/stl/')\nfrom stl import decompose, forecast, naive, drift, mean, seasonal_naive\n\nTRAIN_RATIO=0.75\nDEFAULT_EMA_SMOOTHING_FACTOR = 0.2\nDEFAULT_EMA_WINDOW_SIZE_PCT = 0.2\n# Percentage threshold on anomaly score below which is considered noises.\nDEFAULT_NOISE_PCT_THRESHOLD = 0.001\n\nparser = OptionParser()\nparser.add_option(\"-x\", \"--input-file-x\", type=\"str\", dest=\"file_name_x\", default=None, help=\"Path to input file name X\")\nparser.add_option(\"-n\", \"--feature-name\", type=\"str\", dest=\"feature_name\", default=None, help=\"Input feature name\")\nparser.add_option(\"-o\", \"--output-dir\", type=\"str\", dest=\"output_dir\", default=None, help=\"Path to output dir for plots\")\nparser.add_option(\"-R\", \"--train-ratio\", dest=\"train_ratio\", type=\"float\", default=0.75, help=\"Train ratio\")\n\noptions, args = parser.parse_args()\n\nfile_name_x=options.file_name_x\nfeature=options.feature_name\noutput_dir=options.output_dir\nTRAIN_RATIO=options.train_ratio\n\nif feature is None:\n    feature = file_name_x[(file_name_x.rfind('/')+1):file_name_x.rfind('.')]\n## print(feature)\n\ndef np_sign(arr):\n    \"\"\"  Stand-in for numpy sign()\"\"\"\n    signs = []\n    for i in range(len(arr)):\n        signs.append(1 if arr[i] > 0 else -1)\n    return np.array(signs)\n\ndef np_ones(size):\n    \"\"\"  Stand-in for numpy ones()\"\"\"\n    ones = []\n    for i in range(size):\n        ones.append(1)\n    return np.array(ones)\n\ndef np_argwhere(arr):\n    \"\"\"  Stand-in for numpy argwhere()\"\"\"\n    indices = []\n    for i in range(len(arr)):\n        if arr[i] > 0:\n            indices.append(i)\n    return np.array(indices)\n\ndef np_fmax_const(arr, const):\n    \"\"\" Stand-in for numpy fmax with a constant \"\"\"\n    values = []\n    for i in range(len(arr)):\n        values.append(arr[i] if arr[i] > const else const)\n    return np.array(values)\n\ndef np_convolve_valid(arr1, arr2):\n    \"\"\" Stand-in for numpy convolve with mode = valid (no extrapolation on edges) \"\"\"\n    flipped_arr2 = []\n    for i in range(len(arr2)):\n        flipped_arr2.append(arr2[len(arr2) - i - 1])\n    \n    if len(arr2) > len(arr1):\n        return np.array([])\n    \n    convolution = []\n    for index in range(len(arr1) - len(arr2) + 1):\n        sum = 0\n        for i in range(len(arr2)):\n            sum += arr1[index + i] * flipped_arr2[i]\n        convolution.append(sum)\n    \n    return np.array(convolution)    \n\ndef merge_ranges(ranges, max_gap):\n    \"\"\"\n        Merge ranges which are closer than max_gap\n    \"\"\"\n    merged_ranges = []\n    for range in ranges:\n        if merged_ranges:\n            curr_start, curr_end = range\n            # compare against last interval in merged_ranges\n            pre_start, pre_end = merged_ranges[-1]\n            if curr_start - pre_end < max_gap:\n                # merge current range with the last range in the list\n                merged_ranges[-1] = (pre_start, max(curr_end, pre_end))\n            else:\n                # append the new range to current one\n                merged_ranges.append(range)\n        else:\n            # no merged ranges - just add this one\n            merged_ranges.append(range)\n\n    return merged_ranges\n\n\ndef sign_test_anomaly_detector(x, y, k, alpha, offset, conf, gap):\n    if len(x) != len(y) or len(x) < k:\n        return list()\n\n    # our filter to convolve with - just counts\n    f = np_ones(k)\n\n    # Threshold below calculated as quantile function for a binomial distribution with:\n    #   - probability of success=0.5\n    #   - confidence level p=0.01\n    #   - window size = 24 (2 hours at 5 minutes intervals)\n    # == Smallest k such that Prob(X <= k) >= p\n    # == scipy.stats.binom.ppf(1 - 0.01, 24, 0.5) - 1\n    \n    qthresh = 17.0\n    \n    alpha1 = 1. + alpha\n    diff_array = x - offset\n    diff_array = diff_array - (alpha1 * y)\n\n    # this is 1 if bigger 0 otherwise\n    d = np_fmax_const(np_sign(diff_array), 0)\n#    d = np_fmax_const(np_sign(x - offset - (1. + alpha) * y), 0)\n#    d = np.fmax(np.sign(x - offset - (1. + alpha) * y), 0)\n\n    con = np_convolve_valid(d, f)\n#    con = np.convolve(f, d, mode='valid')\n\n    a = np_fmax_const(con - qthresh, 0)\n#    a = np.fmax(con - qthresh, 0)\n\n    ranges = []\n    for t in np_argwhere(a):\n        ranges.append((t, t + k))        \n\n    ranges = merge_ranges(ranges, gap)\n\n    return ranges\n\nclass Sensor(object):\n    def __init__(self, file_name_x, feature, anomaly_detector, read_window_size, repeats, trend):\n        self.repeats = repeats\n        self.trend = trend\n        self.read_window_size = read_window_size\n        self.anomaly_detector = anomaly_detector\n        df = pd.read_csv(file_name_x)\n        self.observed_idx = df['timestamp'].values\n        self.observed = df['value'].values\n        print(len(self.observed))\n        self.first_ts = self.observed_idx[0]\n        self.last_ts = self.observed_idx[-1]\n        self.timestep = self.observed_idx[1] - self.observed_idx[0]\n\n    def fix_timestamps(self, observed_idx, add_lag):\n        return (observed_idx + add_lag)\n\n    def fix_trend(self, observed, repeat_count, trend):\n        fixed_observed = np.zeros(len(observed))\n        for i in range(len(observed)):\n            fixed_observed[i] = observed[i] + (repeat_count*len(observed)+i)*trend\n        return fixed_observed\n\n    def run(self):\n        for i in range(self.repeats):\n            observed_idx = self.fix_timestamps(self.observed_idx, i*(self.last_ts - self.first_ts + self.timestep))\n            if self.trend > 0:\n                self.observed = self.fix_trend(self.observed, i, self.trend)\n            num_windows = len(observed_idx) // self.read_window_size + (len(observed_idx) % self.read_window_size)\n\n            for j in range(num_windows):\n                observed_idx_w = observed_idx[j*self.read_window_size:(j+1)*self.read_window_size]\n                observed_w = self.observed[j*self.read_window_size:(j+1)*self.read_window_size]\n                print('Sensor: Sending window ', j, ' of repeat ', i, ', length=', len(observed_idx_w), len(observed_w))\n                self.anomaly_detector.update(observed_idx_w, observed_w)\n\nclass AnomalyDetector(object):\n    def __init__(self, period, loess_window, min_train_window_size):\n        self.observed_idx = None\n        self.observed = None\n        self.min_train_window_size = min_train_window_size\n        self.period = period\n        self.loess_window = loess_window\n        \n    def update(self, observed_idx_w, observed_w):\n        # Append received window:\n        if self.observed is None:\n            assert self.observed_idx is None\n            self.observed_idx = observed_idx_w\n            self.observed = observed_w\n        else:\n            assert self.observed_idx is not None\n            self.observed_idx = np.append(self.observed_idx, observed_idx_w)\n            self.observed = np.append(self.observed, observed_w)\n        # Truncate training window to last min_train_window_size entries:\n        if len(self.observed_idx) > self.min_train_window_size:\n            self.observed_idx = self.observed_idx[-self.min_train_window_size:]\n            self.observed = self.observed[-self.min_train_window_size:]\n            print('AnomalyDetector: Forecasting on window of size', len(self.observed_idx), ', [', self.observed_idx[0], ', ' , self.observed_idx[-1], ']')\n            self.detect_anomalies(self.observed_idx, self.observed)\n\n    def detect_anomalies(self, observed_idx, observed):\n        no_periods=int(len(observed)/self.period)\n        observed_short = observed[:int(TRAIN_RATIO*no_periods)*self.period]\n        observed_idx_short = observed_idx[:int(TRAIN_RATIO*no_periods)*self.period]\n        observed_test = observed[int(TRAIN_RATIO*no_periods)*self.period:]\n        observed_idx_test = observed_idx[int(TRAIN_RATIO*no_periods)*self.period:]\n        (trend, seasonal, resid, period_averages, phase) = decompose(observed_short, period=self.period, lo_window_frac=self.loess_window)\n        (forecast_array, forecast_idx) = forecast(observed_short, observed_idx_short,\n                                                     trend, seasonal, resid, period_averages, phase,\n                                                     steps=len(observed_test), fc_func=drift,\n                                                     forecast_seasonal=True, correlate_phase=False)\n\n        anomaly_windows = sign_test_anomaly_detector(observed_test, forecast_array, k=24, alpha=0.2, offset=0.0, conf=0.01, gap=0)\n        anomaly_timestamps = []\n        for (start, end) in anomaly_windows:\n            if end >= len(observed_idx_test):\n                end = len(observed_idx_test) - 1\n            anomaly_timestamps.append((observed_idx_test[start], observed_idx_test[end])) \n        print('DETECTED ANOMALY WINDOWS:', anomaly_timestamps)\n                \nanomaly_detector = AnomalyDetector(period=int(24 * 60 / 5), loess_window = 0.8, min_train_window_size=4032)\nsensor = Sensor(file_name_x, feature, anomaly_detector, read_window_size = 126, repeats=2, trend=0.0)\nsensor.run()\n\n\n\n\n\n"
  },
  {
    "path": "workspace/anomaly_detector/datasets/selected/level_change/ambient_temperature_system_failure.csv",
    "content": "timestamp,value\n2013-07-04 00:00:00,69.88083514\n2013-07-04 01:00:00,71.22022706\n2013-07-04 02:00:00,70.87780496\n2013-07-04 03:00:00,68.95939994\n2013-07-04 04:00:00,69.28355102\n2013-07-04 05:00:00,70.06096581\n2013-07-04 06:00:00,69.27976479\n2013-07-04 07:00:00,69.36960846\n2013-07-04 08:00:00,69.16671394\n2013-07-04 09:00:00,68.98608257\n2013-07-04 10:00:00,69.96506224\n2013-07-04 11:00:00,70.55619466\n2013-07-04 12:00:00,70.30750511\n2013-07-04 13:00:00,70.24625215\n2013-07-04 14:00:00,69.85490839\n2013-07-04 15:00:00,71.64329118\n2013-07-04 16:00:00,71.24565942\n2013-07-04 17:00:00,70.74509976\n2013-07-04 18:00:00,71.37329829\n2013-07-04 19:00:00,71.7957509\n2013-07-04 20:00:00,72.09160609999998\n2013-07-04 21:00:00,71.55307612\n2013-07-04 22:00:00,72.18769545\n2013-07-04 23:00:00,70.64995744\n2013-07-05 00:00:00,71.34274211\n2013-07-05 01:00:00,71.5867281\n2013-07-05 02:00:00,70.97700116\n2013-07-05 03:00:00,70.24388209\n2013-07-05 04:00:00,70.43282627\n2013-07-05 05:00:00,69.74896285\n2013-07-05 06:00:00,68.74938222\n2013-07-05 07:00:00,69.35162661\n2013-07-05 08:00:00,68.85314844\n2013-07-05 09:00:00,70.31790951\n2013-07-05 10:00:00,70.30055692\n2013-07-05 11:00:00,72.53056283\n2013-07-05 12:00:00,71.64320692\n2013-07-05 13:00:00,72.92223804\n2013-07-05 14:00:00,72.63758833\n2013-07-05 15:00:00,72.95903086\n2013-07-05 16:00:00,72.15222081\n2013-07-05 17:00:00,72.16607562\n2013-07-05 18:00:00,72.30558574\n2013-07-05 19:00:00,72.3823022\n2013-07-05 20:00:00,72.61234869\n2013-07-05 21:00:00,72.77599570000002\n2013-07-05 22:00:00,71.91696888\n2013-07-05 23:00:00,71.55368851\n2013-07-06 00:00:00,71.63096403\n2013-07-06 01:00:00,70.59673521\n2013-07-06 02:00:00,70.85248247\n2013-07-06 03:00:00,71.08476824\n2013-07-06 04:00:00,70.84723252\n2013-07-06 05:00:00,70.23242259999999\n2013-07-06 06:00:00,70.12823808\n2013-07-06 07:00:00,69.92923136\n2013-07-06 08:00:00,69.28574982\n2013-07-06 09:00:00,69.72638712\n2013-07-06 10:00:00,68.19010253\n2013-07-06 11:00:00,68.91679541\n2013-07-06 12:00:00,67.26820458\n2013-07-06 13:00:00,66.9649601\n2013-07-06 14:00:00,67.76538379\n2013-07-06 15:00:00,66.91858576\n2013-07-06 16:00:00,67.60522282\n2013-07-06 17:00:00,67.17661097\n2013-07-06 18:00:00,67.99254044\n2013-07-06 19:00:00,67.25818019\n2013-07-06 20:00:00,66.59407898\n2013-07-06 21:00:00,67.86855757\n2013-07-06 22:00:00,67.2922007\n2013-07-06 23:00:00,67.16337656\n2013-07-07 00:00:00,66.27568448\n2013-07-07 01:00:00,65.96858705\n2013-07-07 02:00:00,65.31642297\n2013-07-07 03:00:00,65.42912751\n2013-07-07 04:00:00,66.75098393\n2013-07-07 05:00:00,64.68391715\n2013-07-07 06:00:00,64.56520692\n2013-07-07 07:00:00,66.12965686\n2013-07-07 08:00:00,66.09613054\n2013-07-07 09:00:00,64.9748123\n2013-07-07 10:00:00,64.33478963\n2013-07-07 11:00:00,65.54142516\n2013-07-07 12:00:00,63.9130944\n2013-07-07 13:00:00,65.00924432\n2013-07-07 14:00:00,64.04781966\n2013-07-07 15:00:00,64.25831852\n2013-07-07 16:00:00,63.89332373\n2013-07-07 17:00:00,64.14310465\n2013-07-07 18:00:00,64.17594209\n2013-07-07 19:00:00,63.1570819\n2013-07-07 20:00:00,63.38689893\n2013-07-07 21:00:00,63.99038726\n2013-07-07 22:00:00,62.67478854\n2013-07-07 23:00:00,64.24663357\n2013-07-08 00:00:00,62.48078508\n2013-07-08 01:00:00,62.03055446\n2013-07-08 02:00:00,63.41156044\n2013-07-08 03:00:00,61.70510991\n2013-07-08 04:00:00,62.77513946\n2013-07-08 05:00:00,61.36447611\n2013-07-08 06:00:00,61.68984072\n2013-07-08 07:00:00,62.20048874\n2013-07-08 08:00:00,62.98280722\n2013-07-08 09:00:00,64.44813096\n2013-07-08 10:00:00,65.33294727\n2013-07-08 11:00:00,66.51294379\n2013-07-08 12:00:00,67.88554227\n2013-07-08 13:00:00,67.22250712\n2013-07-08 14:00:00,68.08885127\n2013-07-08 15:00:00,68.55257476\n2013-07-08 16:00:00,70.32033392\n2013-07-08 17:00:00,70.48553783\n2013-07-08 18:00:00,72.33830154\n2013-07-08 19:00:00,71.1908248\n2013-07-08 20:00:00,70.75989770000002\n2013-07-08 21:00:00,70.57075487\n2013-07-08 22:00:00,68.88572309999999\n2013-07-08 23:00:00,68.36836764\n2013-07-09 00:00:00,68.42198714\n2013-07-09 01:00:00,67.55824354\n2013-07-09 02:00:00,66.4884322\n2013-07-09 03:00:00,66.00939653\n2013-07-09 04:00:00,64.88258671\n2013-07-09 05:00:00,65.79409771\n2013-07-09 06:00:00,65.69617694\n2013-07-09 07:00:00,66.14773729\n2013-07-09 08:00:00,67.47861967\n2013-07-09 09:00:00,67.43966413\n2013-07-09 10:00:00,68.50079012\n2013-07-09 11:00:00,69.93367814\n2013-07-09 12:00:00,70.66856782\n2013-07-09 13:00:00,69.43364009999999\n2013-07-09 14:00:00,70.20645921\n2013-07-09 15:00:00,70.23002897\n2013-07-09 16:00:00,71.58361231\n2013-07-09 17:00:00,71.56436778\n2013-07-09 18:00:00,71.02917453\n2013-07-09 19:00:00,72.831066\n2013-07-09 20:00:00,71.13716811\n2013-07-09 21:00:00,69.72083178\n2013-07-09 22:00:00,69.17560647\n2013-07-09 23:00:00,69.31959282\n2013-07-10 00:00:00,68.81260454\n2013-07-10 01:00:00,68.55716829\n2013-07-10 02:00:00,67.73062887\n2013-07-10 03:00:00,67.80815335\n2013-07-10 04:00:00,66.93277621\n2013-07-10 05:00:00,65.84066557\n2013-07-10 06:00:00,66.15467548\n2013-07-10 07:00:00,65.78125301\n2013-07-10 08:00:00,67.33388757\n2013-07-10 09:00:00,67.3485843\n2013-07-10 10:00:00,69.75301970000001\n2013-07-10 11:00:00,69.90438916\n2013-07-10 12:00:00,70.59424483\n2013-07-10 13:00:00,70.05946788\n2013-07-10 14:00:00,71.02625542\n2013-07-10 15:00:00,71.56116588\n2013-07-10 16:00:00,70.98303947\n2013-07-10 17:00:00,71.78059711\n2013-07-10 18:00:00,73.40419990000002\n2013-07-10 19:00:00,71.60391994\n2013-07-10 20:00:00,70.48045714\n2013-07-10 21:00:00,69.48780075\n2013-07-10 22:00:00,69.37470081\n2013-07-10 23:00:00,68.66754682\n2013-07-11 00:00:00,69.05640228\n2013-07-11 01:00:00,69.28118591\n2013-07-11 02:00:00,68.00921159\n2013-07-11 03:00:00,68.57902651\n2013-07-11 04:00:00,66.49549932\n2013-07-11 05:00:00,66.7500451\n2013-07-11 06:00:00,66.42304923\n2013-07-11 07:00:00,67.52779448\n2013-07-11 08:00:00,67.89346899\n2013-07-11 09:00:00,69.1011507\n2013-07-11 10:00:00,70.51575503\n2013-07-11 11:00:00,71.51359764\n2013-07-11 12:00:00,70.78913828\n2013-07-11 13:00:00,70.92408975\n2013-07-11 14:00:00,71.43667911\n2013-07-11 15:00:00,72.77048744\n2013-07-11 16:00:00,72.18360109\n2013-07-11 17:00:00,72.2317116\n2013-07-11 18:00:00,72.14511125\n2013-07-11 19:00:00,72.66568122\n2013-07-11 20:00:00,71.74663208\n2013-07-11 21:00:00,71.47523835\n2013-07-11 22:00:00,70.17998073\n2013-07-11 23:00:00,70.01828427\n2013-07-12 00:00:00,69.63409091\n2013-07-12 01:00:00,69.24166979\n2013-07-12 02:00:00,69.44746561\n2013-07-12 03:00:00,69.56135461\n2013-07-12 04:00:00,67.43148423\n2013-07-12 05:00:00,67.27588501\n2013-07-12 06:00:00,67.64302314\n2013-07-12 07:00:00,67.11633221\n2013-07-12 08:00:00,68.58615434\n2013-07-12 09:00:00,68.54878335\n2013-07-12 10:00:00,69.78361434\n2013-07-12 11:00:00,70.13666468\n2013-07-12 12:00:00,71.79856679999997\n2013-07-12 13:00:00,72.95326709\n2013-07-12 14:00:00,73.38358272\n2013-07-12 15:00:00,72.72556855\n2013-07-12 16:00:00,74.27730941\n2013-07-12 17:00:00,73.58946213\n2013-07-12 18:00:00,73.07774519\n2013-07-12 19:00:00,74.52428051\n2013-07-12 20:00:00,72.52552383\n2013-07-12 21:00:00,72.64264374\n2013-07-12 22:00:00,73.47727338\n2013-07-12 23:00:00,72.37521094\n2013-07-13 00:00:00,71.20816904\n2013-07-13 01:00:00,72.23586399\n2013-07-13 02:00:00,71.09992340000002\n2013-07-13 03:00:00,70.95986451\n2013-07-13 04:00:00,70.25370091\n2013-07-13 05:00:00,71.29442554\n2013-07-13 06:00:00,70.37620145\n2013-07-13 07:00:00,70.33534302\n2013-07-13 08:00:00,68.96127518\n2013-07-13 09:00:00,68.67478951\n2013-07-13 10:00:00,68.68142551\n2013-07-13 11:00:00,70.09922792\n2013-07-13 12:00:00,69.29115996\n2013-07-13 13:00:00,69.14944184\n2013-07-13 14:00:00,69.38045679999999\n2013-07-13 15:00:00,68.32729437\n2013-07-13 16:00:00,68.71167009999999\n2013-07-13 17:00:00,69.43031387\n2013-07-13 18:00:00,69.12568539\n2013-07-13 19:00:00,69.40509502\n2013-07-13 20:00:00,68.64876516\n2013-07-13 21:00:00,67.68106913\n2013-07-13 22:00:00,69.16363194\n2013-07-13 23:00:00,68.19982138\n2013-07-14 00:00:00,68.1347302\n2013-07-14 01:00:00,67.28588699\n2013-07-14 02:00:00,67.77737459\n2013-07-14 03:00:00,68.40400085\n2013-07-14 04:00:00,68.12434843\n2013-07-14 05:00:00,66.62975642\n2013-07-14 06:00:00,67.75402118\n2013-07-14 07:00:00,67.19706687\n2013-07-14 08:00:00,66.19511529\n2013-07-14 09:00:00,67.03467174\n2013-07-14 10:00:00,66.39229109\n2013-07-14 11:00:00,66.98910128\n2013-07-14 12:00:00,66.70652022\n2013-07-14 13:00:00,65.89533219\n2013-07-14 14:00:00,66.15310629999999\n2013-07-14 15:00:00,65.94826687\n2013-07-14 16:00:00,66.18545065\n2013-07-14 17:00:00,65.956704\n2013-07-14 18:00:00,66.58099932\n2013-07-14 19:00:00,67.19124175\n2013-07-14 20:00:00,66.74457508\n2013-07-14 21:00:00,65.89869767\n2013-07-14 22:00:00,65.51804828\n2013-07-14 23:00:00,65.98471013\n2013-07-15 00:00:00,66.62908319\n2013-07-15 01:00:00,64.90780861\n2013-07-15 02:00:00,64.9498236\n2013-07-15 03:00:00,65.64024470000001\n2013-07-15 04:00:00,64.33322178\n2013-07-15 05:00:00,65.81400458\n2013-07-15 06:00:00,64.19811908\n2013-07-15 07:00:00,65.79277627\n2013-07-15 08:00:00,66.47022878\n2013-07-15 09:00:00,66.21114689\n2013-07-15 10:00:00,68.4034625\n2013-07-15 11:00:00,69.51708004\n2013-07-15 12:00:00,69.39746721\n2013-07-15 13:00:00,70.91288645\n2013-07-15 14:00:00,70.88878119\n2013-07-15 15:00:00,71.10972093\n2013-07-15 16:00:00,72.96756108\n2013-07-15 17:00:00,72.02770961\n2013-07-15 18:00:00,73.95202783\n2013-07-15 19:00:00,73.37599022\n2013-07-15 20:00:00,73.50769737\n2013-07-15 21:00:00,72.71914771\n2013-07-15 22:00:00,72.47419791\n2013-07-15 23:00:00,72.0845572\n2013-07-16 00:00:00,70.36089703\n2013-07-16 01:00:00,71.0505306\n2013-07-16 02:00:00,71.07182369\n2013-07-16 03:00:00,70.51372607\n2013-07-16 04:00:00,70.18259029999999\n2013-07-16 05:00:00,69.85543379\n2013-07-16 06:00:00,67.99007603\n2013-07-16 07:00:00,68.45766038\n2013-07-16 08:00:00,68.27103298\n2013-07-16 09:00:00,68.96138225\n2013-07-16 10:00:00,69.74436809\n2013-07-16 11:00:00,70.61571518\n2013-07-16 12:00:00,71.17846267\n2013-07-16 13:00:00,72.386747\n2013-07-16 14:00:00,72.41193764\n2013-07-16 15:00:00,73.68813485\n2013-07-16 16:00:00,73.74326223\n2013-07-16 17:00:00,73.75611822\n2013-07-16 18:00:00,74.32401543\n2013-07-16 19:00:00,73.86398591\n2013-07-16 20:00:00,73.78849309\n2013-07-16 21:00:00,73.00264849\n2013-07-16 22:00:00,72.04541547\n2013-07-16 23:00:00,71.08743709\n2013-07-17 00:00:00,71.9849653\n2013-07-17 01:00:00,71.11160009999998\n2013-07-17 02:00:00,70.99668759999999\n2013-07-17 03:00:00,69.26084472\n2013-07-17 04:00:00,69.52490512\n2013-07-17 05:00:00,68.65398309\n2013-07-17 06:00:00,68.44222186\n2013-07-17 07:00:00,68.98691712\n2013-07-17 08:00:00,68.12116394\n2013-07-17 09:00:00,70.27706087\n2013-07-17 10:00:00,69.46657012\n2013-07-17 11:00:00,70.32267213\n2013-07-17 12:00:00,71.8078395\n2013-07-17 13:00:00,72.06436516\n2013-07-17 14:00:00,72.48594731\n2013-07-17 15:00:00,72.35822858\n2013-07-17 16:00:00,74.73026071\n2013-07-17 17:00:00,74.45593333\n2013-07-17 18:00:00,75.42083051\n2013-07-17 19:00:00,74.93021109\n2013-07-17 20:00:00,73.46169520000002\n2013-07-17 21:00:00,73.44264061\n2013-07-17 22:00:00,73.59425862\n2013-07-17 23:00:00,72.56355591\n2013-07-18 00:00:00,71.67826483\n2013-07-18 01:00:00,72.61615717\n2013-07-18 02:00:00,70.46155106\n2013-07-18 03:00:00,70.68690223\n2013-07-18 04:00:00,71.27823432\n2013-07-18 05:00:00,70.31179231\n2013-07-18 06:00:00,69.53791299\n2013-07-18 07:00:00,70.39827926\n2013-07-18 08:00:00,69.63338286\n2013-07-18 09:00:00,69.47214598\n2013-07-18 10:00:00,71.46398548\n2013-07-18 11:00:00,72.41314268\n2013-07-18 12:00:00,70.9737679\n2013-07-18 13:00:00,72.40852176\n2013-07-18 14:00:00,73.89859399\n2013-07-18 15:00:00,73.99496326\n2013-07-18 16:00:00,74.54050584\n2013-07-18 17:00:00,74.01063854\n2013-07-18 18:00:00,76.39001911\n2013-07-18 19:00:00,75.69719107\n2013-07-18 20:00:00,75.38408868\n2013-07-18 21:00:00,74.12498598\n2013-07-18 22:00:00,75.41434918\n2013-07-18 23:00:00,74.69411987\n2013-07-19 00:00:00,73.07657971\n2013-07-19 01:00:00,73.16384917\n2013-07-19 02:00:00,73.505794\n2013-07-19 03:00:00,74.12699807\n2013-07-19 04:00:00,73.71152259\n2013-07-19 05:00:00,71.98042488\n2013-07-19 06:00:00,71.25116014\n2013-07-19 07:00:00,72.16027157\n2013-07-19 08:00:00,71.37306717\n2013-07-19 09:00:00,71.51790632\n2013-07-19 10:00:00,72.2737793\n2013-07-19 11:00:00,71.8167371\n2013-07-19 12:00:00,73.80696593\n2013-07-19 13:00:00,72.94734057\n2013-07-19 14:00:00,75.32774091\n2013-07-19 15:00:00,75.75888894\n2013-07-19 16:00:00,75.61622646\n2013-07-19 17:00:00,74.80626301\n2013-07-19 18:00:00,75.95162112\n2013-07-19 19:00:00,75.00414728\n2013-07-19 20:00:00,75.7922298\n2013-07-19 21:00:00,75.93662081\n2013-07-19 22:00:00,74.08191979\n2013-07-19 23:00:00,74.0239745\n2013-07-20 00:00:00,73.62518064\n2013-07-20 01:00:00,73.55238749\n2013-07-20 02:00:00,74.17438898\n2013-07-20 03:00:00,72.87160933\n2013-07-20 04:00:00,72.28482269\n2013-07-20 05:00:00,73.51122601\n2013-07-20 06:00:00,72.89366827\n2013-07-20 07:00:00,72.14791650000002\n2013-07-20 08:00:00,72.9557522\n2013-07-20 09:00:00,72.42186823\n2013-07-20 10:00:00,70.665252\n2013-07-20 11:00:00,71.61263958\n2013-07-20 12:00:00,69.74580737\n2013-07-20 13:00:00,71.39185449\n2013-07-20 14:00:00,70.82733191\n2013-07-20 15:00:00,69.32886638\n2013-07-20 16:00:00,70.65200484\n2013-07-20 17:00:00,70.26620516\n2013-07-20 18:00:00,69.04063432\n2013-07-20 19:00:00,68.41965745\n2013-07-20 20:00:00,68.8585241\n2013-07-20 21:00:00,68.36710746\n2013-07-20 22:00:00,68.83774585\n2013-07-20 23:00:00,68.30402817\n2013-07-21 00:00:00,69.3689329\n2013-07-21 01:00:00,68.08187826\n2013-07-21 02:00:00,67.60392999\n2013-07-21 03:00:00,67.44621031\n2013-07-21 04:00:00,67.54039145\n2013-07-21 05:00:00,67.80852224\n2013-07-21 06:00:00,66.38552342\n2013-07-21 07:00:00,66.67172095\n2013-07-21 08:00:00,65.91622406\n2013-07-21 09:00:00,65.67154675\n2013-07-21 10:00:00,65.72519189\n2013-07-21 11:00:00,66.79848157\n2013-07-21 12:00:00,65.43107747\n2013-07-21 13:00:00,66.88734467\n2013-07-21 14:00:00,65.94946794\n2013-07-21 15:00:00,65.28216492\n2013-07-21 16:00:00,66.6497085\n2013-07-21 17:00:00,66.3990687\n2013-07-21 18:00:00,65.00919878\n2013-07-21 19:00:00,65.06137224\n2013-07-21 20:00:00,65.62911927\n2013-07-21 21:00:00,66.37157503\n2013-07-21 22:00:00,64.5293161\n2013-07-21 23:00:00,66.33871216\n2013-07-22 00:00:00,65.29158087\n2013-07-22 01:00:00,65.17119986\n2013-07-22 02:00:00,65.36758419\n2013-07-22 03:00:00,64.55987145\n2013-07-22 04:00:00,64.65845259\n2013-07-22 05:00:00,64.86762829999999\n2013-07-22 06:00:00,63.6094313\n2013-07-22 07:00:00,64.96073316\n2013-07-22 08:00:00,65.43995404\n2013-07-22 09:00:00,67.07099988\n2013-07-22 10:00:00,66.67125763\n2013-07-22 11:00:00,67.64060287\n2013-07-22 12:00:00,68.62797459999999\n2013-07-22 13:00:00,70.2454449\n2013-07-22 14:00:00,69.70567339\n2013-07-22 15:00:00,70.36650487\n2013-07-22 16:00:00,72.27945276\n2013-07-22 17:00:00,72.71664316\n2013-07-22 18:00:00,71.84306091\n2013-07-22 19:00:00,71.53844637\n2013-07-22 20:00:00,71.55812139\n2013-07-22 21:00:00,70.76534571\n2013-07-22 22:00:00,71.14242657\n2013-07-22 23:00:00,70.71393712\n2013-07-23 00:00:00,69.58966371\n2013-07-23 01:00:00,69.02299462\n2013-07-23 02:00:00,68.95729279\n2013-07-23 03:00:00,68.14795876\n2013-07-23 04:00:00,67.48635522\n2013-07-23 05:00:00,66.52278589\n2013-07-23 06:00:00,66.81771127\n2013-07-23 07:00:00,66.25215878\n2013-07-23 08:00:00,68.14487953\n2013-07-23 09:00:00,68.75540328\n2013-07-23 10:00:00,68.54546326\n2013-07-23 11:00:00,68.65504344\n2013-07-23 12:00:00,69.96525521\n2013-07-23 13:00:00,70.93097625\n2013-07-23 14:00:00,70.67200225\n2013-07-23 15:00:00,72.45541594\n2013-07-23 16:00:00,72.75267236\n2013-07-23 17:00:00,72.98703117\n2013-07-23 18:00:00,73.15160594\n2013-07-23 19:00:00,73.18754221\n2013-07-23 20:00:00,71.04274096\n2013-07-23 21:00:00,71.54354038\n2013-07-23 22:00:00,71.74520109\n2013-07-23 23:00:00,70.94274876\n2013-07-24 00:00:00,69.74530422\n2013-07-24 01:00:00,69.52726729\n2013-07-24 02:00:00,70.32903161\n2013-07-24 03:00:00,70.03017299\n2013-07-24 04:00:00,68.87043296\n2013-07-24 05:00:00,68.92349639\n2013-07-24 06:00:00,68.10636443\n2013-07-24 07:00:00,68.55988567\n2013-07-24 08:00:00,67.85392905\n2013-07-24 09:00:00,68.35577512\n2013-07-24 10:00:00,69.70795831\n2013-07-24 11:00:00,70.53390858\n2013-07-24 12:00:00,69.78024465\n2013-07-24 13:00:00,71.51678733\n2013-07-24 14:00:00,72.03103759999998\n2013-07-24 15:00:00,73.40007449\n2013-07-24 16:00:00,73.8675255\n2013-07-24 17:00:00,72.66779455\n2013-07-24 18:00:00,72.85222389\n2013-07-24 19:00:00,73.11323349999998\n2013-07-24 20:00:00,72.2813031\n2013-07-24 21:00:00,72.61561106\n2013-07-24 22:00:00,71.61517817\n2013-07-24 23:00:00,72.75668787\n2013-07-25 00:00:00,71.14354005\n2013-07-25 01:00:00,70.8585056\n2013-07-25 02:00:00,70.89259768\n2013-07-25 03:00:00,70.85000882\n2013-07-25 04:00:00,71.4091997\n2013-07-25 05:00:00,70.257825\n2013-07-25 06:00:00,69.82174319\n2013-07-25 07:00:00,69.39311984\n2013-07-25 08:00:00,69.94923869\n2013-07-25 09:00:00,70.35977277\n2013-07-25 10:00:00,71.59751048\n2013-07-25 11:00:00,71.15990415\n2013-07-25 12:00:00,72.51273013\n2013-07-25 13:00:00,73.02999473\n2013-07-25 14:00:00,72.09791824\n2013-07-25 15:00:00,72.92583014\n2013-07-25 16:00:00,73.86938351\n2013-07-25 17:00:00,73.91377788\n2013-07-25 18:00:00,74.46991144\n2013-07-25 19:00:00,73.21314175\n2013-07-25 20:00:00,74.51203141\n2013-07-25 21:00:00,72.84294254\n2013-07-25 22:00:00,73.43276491\n2013-07-25 23:00:00,73.30466379999999\n2013-07-26 00:00:00,72.81092703\n2013-07-26 01:00:00,72.86473466\n2013-07-26 02:00:00,71.38222869\n2013-07-26 03:00:00,71.19623896\n2013-07-26 04:00:00,71.03955791\n2013-07-26 05:00:00,72.27910059999998\n2013-07-26 06:00:00,70.21785723\n2013-07-26 07:00:00,70.31733297\n2013-07-26 08:00:00,69.78868463\n2013-07-26 09:00:00,70.88145123\n2013-07-26 10:00:00,71.61930479\n2013-07-26 11:00:00,72.28509323\n2013-07-26 12:00:00,72.77202114\n2013-07-26 13:00:00,73.24703993\n2013-07-26 14:00:00,72.80712104\n2013-07-26 15:00:00,72.58748947\n2013-07-26 16:00:00,74.68417583\n2013-07-26 17:00:00,73.09200323\n2013-07-26 18:00:00,74.09006089\n2013-07-26 19:00:00,74.61862587\n2013-07-26 20:00:00,73.81911639\n2013-07-26 21:00:00,74.57014385\n2013-07-26 22:00:00,72.69101123\n2013-07-26 23:00:00,73.56142292\n2013-07-27 00:00:00,73.77909916\n2013-07-27 01:00:00,72.91239911\n2013-07-27 02:00:00,73.48633826\n2013-07-27 03:00:00,72.73447053\n2013-07-27 04:00:00,71.62959719\n2013-07-27 05:00:00,72.41051865\n2013-07-27 06:00:00,71.64829313\n2013-07-27 07:00:00,71.34815297\n2013-07-27 08:00:00,70.69776199\n2013-07-27 09:00:00,70.47033288\n2013-07-27 10:00:00,71.02517791\n2013-07-27 11:00:00,69.83488902\n2013-07-27 12:00:00,71.50090936\n2013-07-27 13:00:00,70.40361959\n2013-07-27 14:00:00,70.54399168\n2013-07-27 15:00:00,71.85746328\n2013-07-27 16:00:00,71.15225757\n2013-07-27 17:00:00,72.78516393\n2013-07-27 18:00:00,73.36070500000002\n2013-07-27 19:00:00,72.86473047\n2013-07-27 20:00:00,72.70608578\n2013-07-27 21:00:00,73.85915886\n2013-07-27 22:00:00,73.50507967\n2013-07-27 23:00:00,72.19240313\n2013-07-28 00:00:00,72.13995763\n2013-07-28 01:00:00,72.76124036\n2013-07-28 03:00:00,72.78238947\n2013-07-28 04:00:00,71.89290086\n2013-07-29 12:00:00,73.24344321\n2013-07-29 13:00:00,73.25408094\n2013-07-29 14:00:00,72.61221201\n2013-07-29 15:00:00,73.02852459\n2013-07-29 16:00:00,73.29062043\n2013-07-29 17:00:00,74.12192813\n2013-07-29 18:00:00,75.04218319\n2013-07-29 19:00:00,75.01049779\n2013-07-29 20:00:00,74.14262591\n2013-07-29 21:00:00,73.92443272\n2013-07-29 22:00:00,74.65910397\n2013-07-29 23:00:00,74.79811406\n2013-07-30 00:00:00,74.46700925\n2013-07-30 01:00:00,73.29755441\n2013-07-30 02:00:00,73.68345172\n2013-07-30 03:00:00,72.34692708\n2013-07-30 04:00:00,73.24426001\n2013-07-30 05:00:00,72.14957625\n2013-07-30 06:00:00,72.41976913\n2013-07-30 07:00:00,71.31132501\n2013-07-30 08:00:00,71.70322328\n2013-07-30 09:00:00,72.25103685\n2013-07-30 10:00:00,71.97716389\n2013-07-30 11:00:00,71.39886276\n2013-07-30 12:00:00,71.59695286\n2013-07-30 13:00:00,72.63410157\n2013-07-30 14:00:00,73.23961797\n2013-07-30 15:00:00,72.52081721\n2013-07-30 16:00:00,74.01598050000003\n2013-07-30 17:00:00,73.67468353\n2013-07-30 18:00:00,75.75032693\n2013-07-30 19:00:00,74.3638755\n2013-07-30 20:00:00,74.41574553\n2013-07-30 21:00:00,74.22077381\n2013-07-30 22:00:00,75.24461638\n2013-07-30 23:00:00,75.76683279\n2013-07-31 00:00:00,75.2599283\n2013-07-31 01:00:00,75.00430133\n2013-07-31 02:00:00,72.99868724\n2013-07-31 03:00:00,74.22813959\n2013-07-31 04:00:00,73.86242657\n2013-07-31 05:00:00,73.64995716\n2013-07-31 06:00:00,72.4157443\n2013-07-31 07:00:00,72.33008672\n2013-07-31 08:00:00,72.6550647\n2013-07-31 09:00:00,72.28311126\n2013-07-31 10:00:00,73.03449417\n2013-07-31 11:00:00,72.28032012\n2013-07-31 12:00:00,71.87820491\n2013-07-31 13:00:00,73.40155661\n2013-07-31 14:00:00,74.44122979\n2013-07-31 15:00:00,73.87635966\n2013-07-31 16:00:00,73.90784081\n2013-07-31 17:00:00,75.16955484\n2013-07-31 18:00:00,75.15953611\n2013-07-31 19:00:00,74.80214938\n2013-07-31 20:00:00,76.28002237\n2013-07-31 21:00:00,74.85748264\n2013-07-31 22:00:00,75.92805235\n2013-07-31 23:00:00,75.91643042\n2013-08-01 00:00:00,74.39653829999997\n2013-08-01 01:00:00,75.10901277\n2013-08-01 02:00:00,74.09065784\n2013-08-01 03:00:00,74.99478559\n2013-08-01 04:00:00,74.49008385\n2013-08-01 05:00:00,74.15968431\n2013-08-01 06:00:00,73.77074883\n2013-08-01 07:00:00,73.761944\n2013-08-01 08:00:00,72.39267309\n2013-08-01 09:00:00,72.65461782\n2013-08-01 10:00:00,71.85842391\n2013-08-01 11:00:00,72.90726702\n2013-08-01 12:00:00,72.74347127\n2013-08-01 13:00:00,73.80882616\n2013-08-01 14:00:00,74.02068569\n2013-08-01 15:00:00,74.93830342\n2013-08-01 16:00:00,73.482711\n2013-08-01 17:00:00,74.16997946\n2013-08-01 18:00:00,74.01751843\n2013-08-01 19:00:00,74.49814040000003\n2013-08-01 20:00:00,76.3120219\n2013-08-01 21:00:00,75.08484325\n2013-08-01 22:00:00,74.65943066\n2013-08-01 23:00:00,75.82212698\n2013-08-02 00:00:00,74.8569766\n2013-08-02 01:00:00,73.98785798\n2013-08-02 02:00:00,74.22412386\n2013-08-02 03:00:00,74.51575386\n2013-08-02 04:00:00,74.45778211\n2013-08-02 05:00:00,74.12643606\n2013-08-02 06:00:00,73.99954302\n2013-08-02 07:00:00,72.26824527\n2013-08-02 08:00:00,73.7764128\n2013-08-02 09:00:00,72.90101937\n2013-08-02 10:00:00,72.11776996\n2013-08-02 11:00:00,72.92499217\n2013-08-02 12:00:00,72.05187563\n2013-08-02 13:00:00,72.38437545\n2013-08-02 14:00:00,74.07630529\n2013-08-02 15:00:00,74.61920753\n2013-08-02 16:00:00,75.08524938\n2013-08-02 17:00:00,75.82866138\n2013-08-02 18:00:00,75.42713311\n2013-08-02 19:00:00,76.56950166\n2013-08-02 20:00:00,76.17963379\n2013-08-02 21:00:00,74.94074803\n2013-08-02 22:00:00,74.76418837\n2013-08-02 23:00:00,74.12540695\n2013-08-03 00:00:00,74.84051371\n2013-08-03 01:00:00,73.79928772\n2013-08-03 02:00:00,74.780247\n2013-08-03 03:00:00,72.82864301\n2013-08-03 04:00:00,72.48177255\n2013-08-03 05:00:00,73.27429509999997\n2013-08-03 06:00:00,73.26715622\n2013-08-03 07:00:00,72.74611472\n2013-08-03 08:00:00,71.30564248\n2013-08-03 09:00:00,70.79796992\n2013-08-03 10:00:00,70.8324548\n2013-08-03 11:00:00,71.36899796\n2013-08-03 12:00:00,71.30600481\n2013-08-03 13:00:00,69.95127986\n2013-08-03 14:00:00,71.11183674\n2013-08-03 15:00:00,71.24355108\n2013-08-03 16:00:00,71.16602046\n2013-08-03 17:00:00,69.5362003\n2013-08-03 18:00:00,71.21599291\n2013-08-03 19:00:00,70.94704371\n2013-08-03 20:00:00,71.14172451\n2013-08-03 21:00:00,70.94719413\n2013-08-03 22:00:00,70.28093351\n2013-08-03 23:00:00,69.95038298\n2013-08-04 00:00:00,70.06016939\n2013-08-04 01:00:00,68.72937535\n2013-08-04 02:00:00,68.31124754\n2013-08-04 03:00:00,67.59938455\n2013-08-04 04:00:00,69.23919313\n2013-08-04 05:00:00,68.70527934\n2013-08-04 06:00:00,67.30881248\n2013-08-04 07:00:00,67.29093890000001\n2013-08-04 08:00:00,67.01058194\n2013-08-04 09:00:00,67.11700116\n2013-08-04 10:00:00,67.17114622\n2013-08-04 11:00:00,64.8612751\n2013-08-04 12:00:00,66.1031092\n2013-08-04 13:00:00,64.70015253\n2013-08-04 14:00:00,65.97732586\n2013-08-04 15:00:00,64.83488246\n2013-08-04 16:00:00,65.16140029\n2013-08-04 17:00:00,65.86503497\n2013-08-04 18:00:00,67.73521012\n2013-08-04 19:00:00,68.12101336\n2013-08-04 20:00:00,68.68838431\n2013-08-04 21:00:00,67.73402197\n2013-08-04 22:00:00,68.42818207\n2013-08-04 23:00:00,68.16946111\n2013-08-05 00:00:00,67.49229937\n2013-08-05 01:00:00,66.98395449\n2013-08-05 02:00:00,68.04064964\n2013-08-05 03:00:00,66.62055167\n2013-08-05 04:00:00,66.64744323\n2013-08-05 05:00:00,66.08743294\n2013-08-05 06:00:00,67.22510503\n2013-08-05 07:00:00,66.43247979\n2013-08-05 08:00:00,66.57052361\n2013-08-05 09:00:00,68.05327519\n2013-08-05 10:00:00,67.67038945\n2013-08-05 11:00:00,69.17031869\n2013-08-05 12:00:00,68.89948983\n2013-08-05 13:00:00,70.00978672\n2013-08-05 14:00:00,69.82913552\n2013-08-05 15:00:00,70.9242198\n2013-08-05 16:00:00,71.27814633\n2013-08-05 17:00:00,72.15965785\n2013-08-05 18:00:00,72.97618331\n2013-08-05 19:00:00,72.66683797\n2013-08-05 20:00:00,73.69117746\n2013-08-05 21:00:00,72.80151077\n2013-08-05 22:00:00,71.85931396\n2013-08-05 23:00:00,72.23815016\n2013-08-06 00:00:00,70.95862334\n2013-08-06 01:00:00,72.4688891\n2013-08-06 02:00:00,71.66219799\n2013-08-06 03:00:00,71.86755979\n2013-08-06 04:00:00,70.7802684\n2013-08-06 05:00:00,70.99083764\n2013-08-06 06:00:00,69.15653193\n2013-08-06 07:00:00,69.08522976\n2013-08-06 08:00:00,69.75214256\n2013-08-06 09:00:00,69.46942493\n2013-08-06 10:00:00,68.77679875\n2013-08-06 11:00:00,70.22714587\n2013-08-06 12:00:00,71.01598435\n2013-08-06 13:00:00,72.44743344\n2013-08-06 14:00:00,72.06658701\n2013-08-06 15:00:00,72.98693668\n2013-08-06 16:00:00,73.69835469\n2013-08-06 17:00:00,73.75209157\n2013-08-06 18:00:00,74.55800629\n2013-08-06 19:00:00,72.35247916\n2013-08-06 20:00:00,65.26017655\n2013-08-06 21:00:00,74.76223447\n2013-08-06 22:00:00,73.49525372\n2013-08-06 23:00:00,73.36538505\n2013-08-07 00:00:00,72.5976732\n2013-08-07 01:00:00,72.99425699999998\n2013-08-07 02:00:00,72.85282429\n2013-08-07 03:00:00,72.74890938\n2013-08-07 04:00:00,72.12765994\n2013-08-07 05:00:00,71.09856805\n2013-08-07 06:00:00,71.23849804\n2013-08-07 07:00:00,70.27255592\n2013-08-07 08:00:00,70.88395870000002\n2013-08-07 09:00:00,71.39022061\n2013-08-07 10:00:00,70.52089931\n2013-08-07 11:00:00,71.25419744\n2013-08-07 12:00:00,72.68993228\n2013-08-07 13:00:00,72.61074543\n2013-08-07 14:00:00,72.43902889\n2013-08-07 15:00:00,73.58512146\n2013-08-07 16:00:00,73.89459624\n2013-08-07 17:00:00,72.95170937\n2013-08-07 18:00:00,74.07563886\n2013-08-07 19:00:00,73.6806514\n2013-08-07 20:00:00,72.89217355\n2013-08-07 21:00:00,73.32218412\n2013-08-07 22:00:00,73.24266369\n2013-08-07 23:00:00,72.14171440000001\n2013-08-08 00:00:00,72.30380183\n2013-08-08 01:00:00,72.89276841\n2013-08-08 02:00:00,71.56299973\n2013-08-08 03:00:00,72.39705979\n2013-08-08 04:00:00,72.00657008\n2013-08-08 05:00:00,71.32736169\n2013-08-08 06:00:00,70.82135373\n2013-08-08 07:00:00,70.1336473\n2013-08-08 08:00:00,70.0467162\n2013-08-08 09:00:00,70.06918582\n2013-08-08 10:00:00,70.79634920000002\n2013-08-08 11:00:00,70.91540196\n2013-08-08 12:00:00,71.67451047\n2013-08-08 13:00:00,72.18760774\n2013-08-08 14:00:00,72.1207947\n2013-08-08 15:00:00,72.51156743\n2013-08-08 16:00:00,72.23695024\n2013-08-08 17:00:00,71.87503532\n2013-08-08 18:00:00,72.49582348\n2013-08-08 19:00:00,72.35768598\n2013-08-08 20:00:00,73.93378927\n2013-08-08 21:00:00,73.98233814\n2013-08-08 22:00:00,73.59560241\n2013-08-08 23:00:00,71.98821679\n2013-08-09 00:00:00,72.32396967\n2013-08-09 01:00:00,71.6259057\n2013-08-09 02:00:00,71.72859842\n2013-08-09 03:00:00,70.70127666\n2013-08-09 04:00:00,71.00161546\n2013-08-09 05:00:00,70.81636614\n2013-08-09 06:00:00,70.72324263\n2013-08-09 07:00:00,70.3860912\n2013-08-09 08:00:00,68.77908287\n2013-08-09 09:00:00,70.22778904\n2013-08-09 10:00:00,69.87258414\n2013-08-09 11:00:00,70.44715736\n2013-08-09 12:00:00,71.08361107\n2013-08-09 13:00:00,71.23292042\n2013-08-09 14:00:00,72.16067996\n2013-08-09 15:00:00,71.86722192\n2013-08-09 16:00:00,72.16014273\n2013-08-09 17:00:00,72.99568483\n2013-08-09 18:00:00,73.27572883\n2013-08-09 19:00:00,73.49417662\n2013-08-09 20:00:00,74.21107376\n2013-08-09 21:00:00,72.54083404\n2013-08-09 22:00:00,73.21324868\n2013-08-09 23:00:00,72.58771726\n2013-08-10 00:00:00,73.50120424\n2013-08-10 01:00:00,72.09154651\n2013-08-10 02:00:00,71.09042019\n2013-08-10 03:00:00,71.23416619\n2013-08-10 04:00:00,70.63012271\n2013-08-10 05:00:00,69.77541726\n2013-08-10 06:00:00,69.28687677\n2013-08-10 07:00:00,70.44057715\n2013-08-10 08:00:00,69.28731334\n2013-08-10 09:00:00,69.93728934\n2013-08-10 10:00:00,69.3391448\n2013-08-10 11:00:00,69.13334157\n2013-08-10 12:00:00,68.65929831\n2013-08-10 13:00:00,68.18197506\n2013-08-10 14:00:00,67.84812498\n2013-08-10 15:00:00,69.37597782\n2013-08-10 16:00:00,69.10036669\n2013-08-10 17:00:00,68.8546449\n2013-08-10 18:00:00,67.85837277\n2013-08-10 19:00:00,68.46916703\n2013-08-10 20:00:00,68.17855534\n2013-08-10 21:00:00,69.21501077\n2013-08-10 22:00:00,68.96464737\n2013-08-10 23:00:00,67.87377682\n2013-08-11 00:00:00,67.72178625\n2013-08-11 01:00:00,68.58499733\n2013-08-11 02:00:00,68.44962111\n2013-08-11 03:00:00,67.14273776\n2013-08-11 04:00:00,67.07599947\n2013-08-11 05:00:00,68.29349922\n2013-08-11 06:00:00,66.78969926\n2013-08-11 07:00:00,65.82622549\n2013-08-11 08:00:00,66.59954318\n2013-08-11 09:00:00,65.01332031\n2013-08-11 10:00:00,65.90620917\n2013-08-11 11:00:00,65.84496837\n2013-08-11 12:00:00,64.92189809\n2013-08-11 13:00:00,65.58278655\n2013-08-11 14:00:00,65.55748205\n2013-08-11 15:00:00,65.59894884\n2013-08-11 16:00:00,64.94337424\n2013-08-11 17:00:00,64.74950254\n2013-08-11 18:00:00,64.84844096\n2013-08-11 19:00:00,65.83625843\n2013-08-11 20:00:00,66.03749482\n2013-08-11 21:00:00,65.38311565\n2013-08-11 22:00:00,65.99967447\n2013-08-11 23:00:00,64.36458794\n2013-08-12 00:00:00,65.07952767\n2013-08-12 01:00:00,65.29604166\n2013-08-12 02:00:00,65.20610988\n2013-08-12 03:00:00,63.96596281\n2013-08-12 04:00:00,64.72425165\n2013-08-12 05:00:00,65.40331196\n2013-08-12 06:00:00,65.42865101\n2013-08-12 07:00:00,64.09801612\n2013-08-12 08:00:00,63.80900879\n2013-08-12 09:00:00,64.54585931\n2013-08-12 10:00:00,66.95784817\n2013-08-12 11:00:00,66.61279611\n2013-08-12 12:00:00,67.94979306\n2013-08-12 13:00:00,66.39778915\n2013-08-12 14:00:00,66.77796074\n2013-08-12 15:00:00,67.1940435\n2013-08-12 16:00:00,68.38187061\n2013-08-12 17:00:00,67.12861534\n2013-08-12 18:00:00,67.17067346\n2013-08-12 19:00:00,68.43923628\n2013-08-12 20:00:00,66.57086417\n2013-08-12 21:00:00,67.78803691\n2013-08-12 22:00:00,67.2787936\n2013-08-12 23:00:00,67.87219243\n2013-08-13 00:00:00,67.50915846\n2013-08-13 01:00:00,67.66070149\n2013-08-13 02:00:00,65.93597991\n2013-08-13 03:00:00,65.72336823\n2013-08-13 04:00:00,65.72245666\n2013-08-13 05:00:00,66.11658266\n2013-08-13 06:00:00,65.32184413\n2013-08-13 07:00:00,65.71791971\n2013-08-13 08:00:00,65.47364884\n2013-08-13 09:00:00,66.64929047\n2013-08-13 10:00:00,66.55123544\n2013-08-13 11:00:00,67.79521779999999\n2013-08-13 12:00:00,68.14077842\n2013-08-13 13:00:00,69.79685244\n2013-08-13 14:00:00,70.34622184\n2013-08-13 15:00:00,69.32175382\n2013-08-13 16:00:00,69.89015017\n2013-08-13 17:00:00,71.58845383\n2013-08-13 18:00:00,71.86175982\n2013-08-13 19:00:00,72.7410679\n2013-08-13 20:00:00,71.90458946\n2013-08-13 21:00:00,71.28351048\n2013-08-13 22:00:00,70.09728390000001\n2013-08-13 23:00:00,69.27726512\n2013-08-14 00:00:00,68.92546699\n2013-08-14 01:00:00,68.55186335\n2013-08-14 02:00:00,67.65673848\n2013-08-14 03:00:00,68.32131351\n2013-08-14 04:00:00,68.12150858\n2013-08-14 05:00:00,66.5554972\n2013-08-14 06:00:00,66.38718242\n2013-08-14 07:00:00,66.99569939\n2013-08-14 08:00:00,65.87173899\n2013-08-14 09:00:00,67.22433388\n2013-08-14 10:00:00,68.40446699\n2013-08-14 11:00:00,68.74846629999999\n2013-08-14 12:00:00,69.32469028\n2013-08-14 13:00:00,71.15467576\n2013-08-14 14:00:00,71.05227306\n2013-08-14 15:00:00,70.83181931\n2013-08-14 16:00:00,70.91625104\n2013-08-14 17:00:00,72.39488293\n2013-08-14 18:00:00,71.98328520000003\n2013-08-14 19:00:00,72.37378341\n2013-08-14 20:00:00,71.80748327\n2013-08-14 21:00:00,72.54903002\n2013-08-14 22:00:00,71.18557043\n2013-08-14 23:00:00,70.6560059\n2013-08-15 00:00:00,71.42334777\n2013-08-15 01:00:00,69.34699767\n2013-08-15 02:00:00,70.73289851\n2013-08-15 03:00:00,68.5593425\n2013-08-15 04:00:00,69.75429868\n2013-08-15 05:00:00,69.42528082\n2013-08-15 06:00:00,68.78050479\n2013-08-15 07:00:00,67.57592345\n2013-08-15 08:00:00,67.31292692\n2013-08-15 09:00:00,68.61465054\n2013-08-15 10:00:00,68.93048832\n2013-08-15 11:00:00,70.42238762\n2013-08-15 12:00:00,70.84558646\n2013-08-15 13:00:00,71.06424324\n2013-08-15 14:00:00,72.69610401\n2013-08-15 15:00:00,72.32617126\n2013-08-15 16:00:00,72.22167626\n2013-08-15 17:00:00,73.21437055\n2013-08-15 18:00:00,73.15708957\n2013-08-15 19:00:00,73.49412607\n2013-08-15 20:00:00,72.3006671\n2013-08-15 21:00:00,73.86668101\n2013-08-15 22:00:00,72.6701852\n2013-08-15 23:00:00,72.7624445\n2013-08-16 00:00:00,72.76328752\n2013-08-16 01:00:00,71.3147316\n2013-08-16 02:00:00,71.43288687\n2013-08-16 03:00:00,70.82264418\n2013-08-16 04:00:00,70.66687081\n2013-08-16 05:00:00,70.43909465\n2013-08-16 06:00:00,69.81296825\n2013-08-16 07:00:00,69.69858982\n2013-08-16 08:00:00,68.34291749\n2013-08-16 09:00:00,69.78913221\n2013-08-16 10:00:00,69.04301127\n2013-08-16 11:00:00,71.2618595\n2013-08-16 12:00:00,71.53303086\n2013-08-16 13:00:00,71.2414772\n2013-08-16 14:00:00,73.36763803\n2013-08-16 15:00:00,73.57415941\n2013-08-16 16:00:00,72.24425435\n2013-08-16 17:00:00,74.26516471\n2013-08-16 18:00:00,72.92651196\n2013-08-16 19:00:00,74.39635211\n2013-08-16 20:00:00,74.11889706\n2013-08-16 21:00:00,72.19232832\n2013-08-16 22:00:00,73.73903840000001\n2013-08-16 23:00:00,72.2079627\n2013-08-17 00:00:00,72.96446399\n2013-08-17 01:00:00,72.47851039\n2013-08-17 02:00:00,71.26534459\n2013-08-17 03:00:00,70.53066333\n2013-08-17 04:00:00,71.25037104\n2013-08-17 05:00:00,70.43519581\n2013-08-17 06:00:00,70.42341332\n2013-08-17 07:00:00,70.79164337\n2013-08-17 08:00:00,68.95439433\n2013-08-17 09:00:00,70.34051981\n2013-08-17 10:00:00,69.80542162\n2013-08-17 11:00:00,68.64316206\n2013-08-17 12:00:00,69.38668045\n2013-08-17 13:00:00,68.78927469999999\n2013-08-17 14:00:00,68.83952616\n2013-08-17 15:00:00,67.63291116\n2013-08-17 16:00:00,68.40694416\n2013-08-17 17:00:00,69.14007715\n2013-08-17 18:00:00,69.11590587\n2013-08-17 19:00:00,68.03579823\n2013-08-17 20:00:00,69.27272007\n2013-08-17 21:00:00,68.75322294\n2013-08-17 22:00:00,69.56566049\n2013-08-17 23:00:00,68.17712131\n2013-08-18 00:00:00,67.79477436\n2013-08-18 01:00:00,67.49347171\n2013-08-18 02:00:00,67.79427593\n2013-08-18 03:00:00,67.70107774\n2013-08-18 04:00:00,67.26294021\n2013-08-18 05:00:00,66.86984441\n2013-08-18 06:00:00,66.14932783\n2013-08-18 07:00:00,66.42313039\n2013-08-18 08:00:00,67.0524877\n2013-08-18 09:00:00,65.34818634\n2013-08-18 10:00:00,65.89940057\n2013-08-18 11:00:00,66.64739688\n2013-08-18 12:00:00,66.64122284\n2013-08-18 13:00:00,64.79138473\n2013-08-18 14:00:00,65.90167301\n2013-08-18 15:00:00,65.74127604\n2013-08-18 16:00:00,65.45031794\n2013-08-18 17:00:00,66.16094532\n2013-08-18 18:00:00,65.7044379\n2013-08-18 19:00:00,64.77549911\n2013-08-18 20:00:00,66.10922106\n2013-08-18 21:00:00,64.65138267\n2013-08-18 22:00:00,64.63763005\n2013-08-18 23:00:00,64.86524307\n2013-08-19 00:00:00,64.67189696\n2013-08-19 01:00:00,64.46795885\n2013-08-19 02:00:00,65.91187512\n2013-08-19 03:00:00,64.34806529\n2013-08-19 04:00:00,63.99581812\n2013-08-19 05:00:00,65.39461929\n2013-08-19 06:00:00,64.65292546\n2013-08-19 07:00:00,63.25807837\n2013-08-19 08:00:00,63.73827199\n2013-08-19 09:00:00,64.48038308\n2013-08-19 10:00:00,65.99746656\n2013-08-19 11:00:00,66.25822123\n2013-08-19 12:00:00,68.10328147\n2013-08-19 13:00:00,67.8042515\n2013-08-19 14:00:00,69.4870625\n2013-08-19 15:00:00,70.03024494\n2013-08-19 16:00:00,70.29600481\n2013-08-19 17:00:00,71.04468694\n2013-08-19 18:00:00,72.07494806\n2013-08-19 19:00:00,71.92135771\n2013-08-19 20:00:00,72.83067187\n2013-08-19 21:00:00,71.98101498\n2013-08-19 22:00:00,69.32089454\n2013-08-19 23:00:00,70.13159511\n2013-08-20 00:00:00,70.00507257\n2013-08-20 01:00:00,69.43663186\n2013-08-20 02:00:00,68.94680541\n2013-08-20 03:00:00,67.39526388\n2013-08-20 04:00:00,66.86451228\n2013-08-20 05:00:00,67.61515255\n2013-08-20 06:00:00,67.50015115\n2013-08-20 07:00:00,67.06492539999999\n2013-08-20 08:00:00,66.18109356\n2013-08-20 09:00:00,67.67862944\n2013-08-20 10:00:00,67.28780716\n2013-08-20 11:00:00,68.64887048\n2013-08-20 12:00:00,68.03818943\n2013-08-20 13:00:00,69.43733797\n2013-08-20 14:00:00,69.42521625\n2013-08-20 15:00:00,70.34561943\n2013-08-20 16:00:00,70.30816394\n2013-08-20 17:00:00,70.8360583\n2013-08-20 18:00:00,71.1470857\n2013-08-20 19:00:00,71.57781772\n2013-08-20 20:00:00,72.19406331\n2013-08-20 21:00:00,72.28995087\n2013-08-20 22:00:00,71.14766239\n2013-08-20 23:00:00,69.76492572\n2013-08-21 00:00:00,69.91788048\n2013-08-21 01:00:00,69.25384854\n2013-08-21 02:00:00,67.70300258\n2013-08-21 03:00:00,67.34860655\n2013-08-21 04:00:00,67.03007179\n2013-08-21 05:00:00,67.02774425\n2013-08-21 06:00:00,66.79530391\n2013-08-21 07:00:00,65.29474687\n2013-08-21 08:00:00,66.61324069\n2013-08-21 09:00:00,66.79489002\n2013-08-21 10:00:00,66.72432203\n2013-08-21 11:00:00,66.81536983\n2013-08-21 12:00:00,67.17358633\n2013-08-21 13:00:00,67.63012369\n2013-08-21 14:00:00,67.48754605\n2013-08-21 15:00:00,67.33171806\n2013-08-21 16:00:00,69.7284424\n2013-08-21 17:00:00,69.89615603\n2013-08-21 18:00:00,68.99214926\n2013-08-21 19:00:00,70.03999165\n2013-08-21 20:00:00,70.55714223\n2013-08-21 21:00:00,70.17848707\n2013-08-21 22:00:00,68.21913112\n2013-08-21 23:00:00,68.40833713\n2013-08-22 00:00:00,68.94808523\n2013-08-22 01:00:00,67.38899521\n2013-08-22 02:00:00,68.05245103\n2013-08-22 03:00:00,67.21188517\n2013-08-22 04:00:00,65.70328183\n2013-08-22 05:00:00,67.16985267\n2013-08-22 06:00:00,66.55460769\n2013-08-22 07:00:00,65.72798535\n2013-08-22 08:00:00,65.75716876\n2013-08-22 09:00:00,67.16913702\n2013-08-22 10:00:00,67.21744752\n2013-08-22 11:00:00,68.42865711\n2013-08-22 12:00:00,67.939555\n2013-08-22 13:00:00,68.21272047\n2013-08-22 14:00:00,68.59771355\n2013-08-22 15:00:00,69.8746694\n2013-08-22 16:00:00,69.78932095\n2013-08-22 17:00:00,71.20599841\n2013-08-22 18:00:00,71.58253869\n2013-08-22 19:00:00,71.88959565\n2013-08-22 20:00:00,71.86056438\n2013-08-22 21:00:00,72.04256027\n2013-08-22 22:00:00,71.39573223\n2013-08-22 23:00:00,69.55668318\n2013-08-23 00:00:00,68.93024269\n2013-08-23 01:00:00,69.66341833\n2013-08-23 02:00:00,69.04101322\n2013-08-23 03:00:00,67.96747227\n2013-08-23 04:00:00,69.31576272\n2013-08-23 05:00:00,68.15040455\n2013-08-23 06:00:00,68.35613984\n2013-08-23 07:00:00,67.76316051\n2013-08-23 08:00:00,67.03590822\n2013-08-23 09:00:00,67.39406286\n2013-08-23 10:00:00,68.68188132\n2013-08-23 11:00:00,70.23539114\n2013-08-23 12:00:00,70.72213492\n2013-08-23 13:00:00,70.58200639\n2013-08-23 14:00:00,71.80797978\n2013-08-23 15:00:00,70.57872691\n2013-08-23 16:00:00,72.0077339\n2013-08-23 17:00:00,71.71571281\n2013-08-23 18:00:00,72.11695816\n2013-08-23 19:00:00,72.64909676\n2013-08-23 20:00:00,71.43282886\n2013-08-23 21:00:00,71.71418699\n2013-08-23 22:00:00,72.28243141\n2013-08-23 23:00:00,72.25217338\n2013-08-24 00:00:00,71.74318478\n2013-08-24 01:00:00,69.68874182\n2013-08-24 02:00:00,70.11075437\n2013-08-24 03:00:00,68.69315914\n2013-08-24 04:00:00,68.49395196\n2013-08-24 05:00:00,69.05769349\n2013-08-24 06:00:00,67.38563023\n2013-08-24 07:00:00,68.51017483\n2013-08-24 08:00:00,68.046038\n2013-08-24 09:00:00,66.69591868\n2013-08-24 10:00:00,67.0893911\n2013-08-24 11:00:00,66.22561571\n2013-08-24 12:00:00,66.50296546\n2013-08-24 13:00:00,65.29980537\n2013-08-24 14:00:00,65.44279328\n2013-08-24 15:00:00,65.87726412\n2013-08-24 16:00:00,65.57372439\n2013-08-24 17:00:00,65.68296557\n2013-08-24 18:00:00,66.93568163\n2013-08-24 19:00:00,66.69982543\n2013-08-24 20:00:00,65.99025408\n2013-08-24 21:00:00,65.93769573\n2013-08-24 22:00:00,67.04970768\n2013-08-24 23:00:00,66.73555970000001\n2013-08-25 00:00:00,66.23665366\n2013-08-25 01:00:00,66.23546935\n2013-08-25 02:00:00,66.85525388\n2013-08-25 03:00:00,65.44418785\n2013-08-25 04:00:00,66.70939032\n2013-08-25 05:00:00,64.88554717\n2013-08-25 06:00:00,64.35080723\n2013-08-25 07:00:00,64.38802527\n2013-08-25 08:00:00,64.40835278\n2013-08-25 09:00:00,64.42226129\n2013-08-25 10:00:00,64.05518099\n2013-08-25 11:00:00,64.71716427\n2013-08-25 12:00:00,64.45389357\n2013-08-25 13:00:00,64.50166125\n2013-08-25 14:00:00,64.01651861\n2013-08-25 15:00:00,62.85522295\n2013-08-25 16:00:00,64.23986264\n2013-08-25 17:00:00,63.38848875\n2013-08-25 18:00:00,63.39183252\n2013-08-25 19:00:00,65.20905227\n2013-08-25 20:00:00,64.94516739\n2013-08-25 21:00:00,64.25107982\n2013-08-25 22:00:00,64.17982393\n2013-08-25 23:00:00,64.38921578\n2013-08-26 00:00:00,64.49909975\n2013-08-26 01:00:00,65.09660852\n2013-08-26 02:00:00,63.40543705\n2013-08-26 03:00:00,63.83826011\n2013-08-26 04:00:00,63.68217925\n2013-08-26 05:00:00,63.32128642\n2013-08-26 06:00:00,63.45009249\n2013-08-26 07:00:00,63.58602877\n2013-08-26 08:00:00,62.73132759\n2013-08-26 09:00:00,64.6219447\n2013-08-26 10:00:00,65.04527027\n2013-08-26 11:00:00,65.66669249\n2013-08-26 12:00:00,66.04597893\n2013-08-26 13:00:00,66.92945334\n2013-08-26 14:00:00,68.27335848\n2013-08-26 15:00:00,68.03643251\n2013-08-26 16:00:00,68.32526303\n2013-08-26 17:00:00,69.45241625\n2013-08-26 18:00:00,69.292876\n2013-08-26 19:00:00,69.61637759\n2013-08-26 20:00:00,69.09830136\n2013-08-26 21:00:00,68.9295352\n2013-08-26 22:00:00,68.38166541\n2013-08-26 23:00:00,66.69776707\n2013-08-27 00:00:00,66.55923923\n2013-08-27 01:00:00,65.50421593\n2013-08-27 02:00:00,65.36283826\n2013-08-27 03:00:00,65.03631072\n2013-08-27 04:00:00,64.28289583\n2013-08-27 05:00:00,64.70837708\n2013-08-27 06:00:00,65.19959422\n2013-08-27 07:00:00,64.37599177\n2013-08-27 08:00:00,65.80010808\n2013-08-27 09:00:00,66.90052411\n2013-08-27 10:00:00,65.97556180000001\n2013-08-27 11:00:00,67.21755426\n2013-08-29 11:00:00,67.61970814\n2013-08-29 12:00:00,68.68919867\n2013-08-29 13:00:00,68.99230755\n2013-08-29 14:00:00,69.01270334\n2013-08-29 15:00:00,69.60076165\n2013-08-29 16:00:00,70.62180453\n2013-08-29 17:00:00,70.80389723\n2013-08-29 18:00:00,71.95049453\n2013-08-29 19:00:00,71.45525932\n2013-08-29 20:00:00,70.69089941\n2013-08-29 21:00:00,70.84845568\n2013-08-29 22:00:00,71.14711094\n2013-08-29 23:00:00,70.19670613\n2013-08-30 00:00:00,70.26757380000001\n2013-08-30 01:00:00,70.3477134\n2013-08-30 02:00:00,68.94715476\n2013-08-30 03:00:00,68.19452413\n2013-08-30 04:00:00,67.41217981\n2013-08-30 05:00:00,67.6915133\n2013-08-30 06:00:00,68.1326941\n2013-08-30 07:00:00,67.72304464\n2013-08-30 08:00:00,67.00024303\n2013-08-30 09:00:00,68.33122058\n2013-08-30 10:00:00,68.77081792\n2013-08-30 11:00:00,67.89464946\n2013-08-30 12:00:00,70.32897545\n2013-08-30 13:00:00,69.94984745\n2013-08-30 14:00:00,69.04940045\n2013-08-30 15:00:00,70.48680148\n2013-08-30 16:00:00,70.73164318\n2013-08-30 17:00:00,70.27130965\n2013-08-30 18:00:00,70.56771532\n2013-08-30 19:00:00,70.52348927\n2013-08-30 20:00:00,70.94288585\n2013-08-30 21:00:00,70.09622236\n2013-08-30 22:00:00,70.92253659999999\n2013-08-30 23:00:00,69.73699276\n2013-08-31 00:00:00,69.50362657\n2013-08-31 01:00:00,68.74107885\n2013-08-31 02:00:00,67.98350404\n2013-08-31 03:00:00,68.65775842\n2013-08-31 04:00:00,69.01901831\n2013-08-31 05:00:00,68.7557281\n2013-08-31 06:00:00,67.6440132\n2013-08-31 07:00:00,67.09824802\n2013-08-31 08:00:00,68.86076740000001\n2013-08-31 09:00:00,68.54857064\n2013-08-31 10:00:00,68.10020545\n2013-08-31 11:00:00,67.3162411\n2013-08-31 12:00:00,67.37946307\n2013-08-31 13:00:00,68.16976322\n2013-08-31 14:00:00,68.33976301\n2013-08-31 15:00:00,68.55040093\n2013-08-31 16:00:00,67.16532869\n2013-08-31 17:00:00,67.30479343\n2013-08-31 18:00:00,66.79372649\n2013-08-31 19:00:00,66.97126902\n2013-08-31 20:00:00,66.36018507\n2013-08-31 21:00:00,67.20420628\n2013-08-31 22:00:00,68.07608732\n2013-08-31 23:00:00,67.23191893\n2013-09-01 00:00:00,67.78175194\n2013-09-01 01:00:00,66.07614673\n2013-09-01 02:00:00,66.11011254\n2013-09-01 03:00:00,67.10977933\n2013-09-01 04:00:00,67.52951352\n2013-09-01 05:00:00,67.37827727\n2013-09-01 06:00:00,67.10470918\n2013-09-01 07:00:00,66.9472606\n2013-09-01 08:00:00,67.13996477\n2013-09-01 09:00:00,66.67085420000001\n2013-09-01 10:00:00,65.9378113\n2013-09-01 11:00:00,66.5151767\n2013-09-01 12:00:00,66.072041\n2013-09-01 13:00:00,66.3918316\n2013-09-01 14:00:00,65.43023923\n2013-09-01 15:00:00,65.6508534\n2013-09-01 16:00:00,66.13170688\n2013-09-01 17:00:00,65.63831743\n2013-09-01 18:00:00,65.95578224\n2013-09-01 19:00:00,67.36956957\n2013-09-01 20:00:00,67.02516809\n2013-09-01 21:00:00,66.72385597\n2013-09-01 22:00:00,67.25433659\n2013-09-01 23:00:00,68.06762583\n2013-09-02 00:00:00,68.2229547\n2013-09-02 01:00:00,66.04236184\n2013-09-02 02:00:00,66.95310877\n2013-09-02 03:00:00,66.30459021\n2013-09-02 04:00:00,66.61170465\n2013-09-02 05:00:00,64.69937871\n2013-09-02 06:00:00,66.21768604\n2013-09-02 07:00:00,65.95636186\n2013-09-02 08:00:00,65.97202741\n2013-09-02 09:00:00,67.53287993\n2013-09-02 10:00:00,67.49599206\n2013-09-02 11:00:00,67.72868098\n2013-09-02 12:00:00,68.32218023\n2013-09-02 13:00:00,68.08308598\n2013-09-02 14:00:00,68.607251\n2013-09-02 15:00:00,68.77487445\n2013-09-02 16:00:00,68.7696785\n2013-09-02 17:00:00,68.64186817\n2013-09-02 18:00:00,70.62377265\n2013-09-02 19:00:00,69.50433389\n2013-09-02 20:00:00,68.92231254\n2013-09-02 21:00:00,70.48760069\n2013-09-02 22:00:00,68.22783476\n2013-09-02 23:00:00,69.04882691\n2013-09-03 00:00:00,67.74723934\n2013-09-03 01:00:00,68.09114575\n2013-09-03 02:00:00,68.65891435\n2013-09-03 03:00:00,69.63167183\n2013-09-03 04:00:00,69.57087107\n2013-09-03 05:00:00,68.92351224\n2013-09-03 06:00:00,67.53393503\n2013-09-03 07:00:00,68.2712078\n2013-09-03 08:00:00,68.65631055\n2013-09-03 09:00:00,67.39411119\n2013-09-03 10:00:00,68.37006622\n2013-09-03 11:00:00,68.23821811\n2013-09-03 12:00:00,68.24746423\n2013-09-03 13:00:00,67.42129150000001\n2013-09-03 14:00:00,67.17151006\n2013-09-03 15:00:00,68.84601436\n2013-09-03 16:00:00,68.98532397\n2013-09-03 17:00:00,68.6852691\n2013-09-03 18:00:00,70.38096941\n2013-09-03 19:00:00,70.63271507\n2013-09-03 20:00:00,70.71181053\n2013-09-03 21:00:00,71.77605259\n2013-09-03 22:00:00,71.9902121\n2013-09-03 23:00:00,70.50334409\n2013-09-04 00:00:00,70.02106963\n2013-09-04 01:00:00,71.10226832\n2013-09-04 02:00:00,71.07281481\n2013-09-04 03:00:00,71.00298194\n2013-09-04 04:00:00,69.64750524\n2013-09-04 05:00:00,69.29922688\n2013-09-04 06:00:00,70.19295937\n2013-09-04 07:00:00,69.59298326\n2013-09-04 08:00:00,69.94483099\n2013-09-04 09:00:00,68.38753638\n2013-09-04 10:00:00,70.12778664\n2013-09-04 11:00:00,69.75996879\n2013-09-04 12:00:00,70.57663801\n2013-09-04 13:00:00,70.11459489\n2013-09-04 14:00:00,71.54936878\n2013-09-04 15:00:00,71.04470664\n2013-09-04 16:00:00,71.67149466\n2013-09-04 17:00:00,73.23762503\n2013-09-04 18:00:00,72.25962147\n2013-09-04 19:00:00,72.93900293\n2013-09-04 20:00:00,71.27122808\n2013-09-04 21:00:00,72.55002116\n2013-09-04 22:00:00,71.25225098\n2013-09-04 23:00:00,71.97747232\n2013-09-05 00:00:00,70.23719215\n2013-09-05 01:00:00,69.94606111\n2013-09-05 02:00:00,69.450805\n2013-09-05 03:00:00,69.93479403\n2013-09-05 04:00:00,69.0965309\n2013-09-05 05:00:00,68.97376954\n2013-09-05 06:00:00,70.04102824\n2013-09-05 07:00:00,69.54259642\n2013-09-05 08:00:00,69.85107284\n2013-09-05 09:00:00,69.61953454\n2013-09-05 10:00:00,69.99920276\n2013-09-05 11:00:00,70.41283415\n2013-09-05 12:00:00,72.11046261\n2013-09-05 13:00:00,72.80678003\n2013-09-05 14:00:00,72.51801434\n2013-09-05 15:00:00,72.69228723\n2013-09-05 16:00:00,72.16597707\n2013-09-05 17:00:00,73.99614903\n2013-09-05 18:00:00,72.82582702\n2013-09-05 19:00:00,74.24818259\n2013-09-05 20:00:00,74.69982523\n2013-09-05 21:00:00,75.16462698\n2013-09-05 22:00:00,74.48402123\n2013-09-05 23:00:00,72.97264305\n2013-09-06 00:00:00,72.49176792\n2013-09-06 01:00:00,73.77290611\n2013-09-06 02:00:00,73.53132409999998\n2013-09-06 03:00:00,72.73837497\n2013-09-06 04:00:00,71.88548201\n2013-09-06 05:00:00,71.52278755\n2013-09-06 06:00:00,71.76144938\n2013-09-06 07:00:00,72.45670094\n2013-09-06 08:00:00,71.89475031\n2013-09-06 09:00:00,70.52341229\n2013-09-06 10:00:00,71.2629687\n2013-09-06 11:00:00,72.8074479\n2013-09-06 12:00:00,73.80156306\n2013-09-06 13:00:00,73.52862948\n2013-09-06 14:00:00,72.90089441\n2013-09-06 15:00:00,73.17178042\n2013-09-06 16:00:00,73.42038306\n2013-09-06 17:00:00,73.47819457\n2013-09-06 18:00:00,73.96854139\n2013-09-06 19:00:00,74.39984284\n2013-09-06 20:00:00,74.13263209\n2013-09-06 21:00:00,73.66106497\n2013-09-06 22:00:00,74.42455034\n2013-09-06 23:00:00,73.88125989\n2013-09-07 00:00:00,72.88416225\n2013-09-07 01:00:00,72.53366149\n2013-09-07 02:00:00,72.28026919\n2013-09-07 03:00:00,73.5383584\n2013-09-07 04:00:00,72.97417623\n2013-09-07 05:00:00,72.80378043\n2013-09-07 06:00:00,71.11640175\n2013-09-07 07:00:00,71.8028968\n2013-09-07 08:00:00,71.74339169\n2013-09-07 09:00:00,71.89946776\n2013-09-07 10:00:00,71.37667995\n2013-09-07 11:00:00,70.97398196\n2013-09-07 12:00:00,71.3123657\n2013-09-07 13:00:00,71.86460893\n2013-09-07 14:00:00,71.16599578\n2013-09-07 15:00:00,71.37723976\n2013-09-07 16:00:00,71.36848881\n2013-09-07 17:00:00,70.78637361\n2013-09-07 18:00:00,71.11015784\n2013-09-07 19:00:00,71.85983966\n2013-09-07 20:00:00,70.95035881\n2013-09-07 21:00:00,72.65891354\n2013-09-07 22:00:00,72.33779272\n2013-09-07 23:00:00,70.61711298\n2013-09-08 00:00:00,71.01930095\n2013-09-08 01:00:00,71.63639202\n2013-09-08 02:00:00,71.32415634\n2013-09-08 03:00:00,70.5466809\n2013-09-08 04:00:00,70.97726886\n2013-09-08 05:00:00,69.7019157\n2013-09-08 06:00:00,70.36501785\n2013-09-08 07:00:00,69.28265658\n2013-09-08 08:00:00,68.52513155\n2013-09-08 09:00:00,68.91671905\n2013-09-08 10:00:00,68.90391361\n2013-09-08 11:00:00,69.25304945\n2013-09-08 12:00:00,69.20694068\n2013-09-08 13:00:00,68.4344154\n2013-09-08 14:00:00,69.13783219\n2013-09-08 15:00:00,67.78567323\n2013-09-08 16:00:00,68.87397161\n2013-09-08 17:00:00,68.04502775\n2013-09-08 18:00:00,67.81055256\n2013-09-08 19:00:00,68.99773267\n2013-09-08 20:00:00,68.99448259\n2013-09-08 21:00:00,67.84551049\n2013-09-08 22:00:00,68.86458993\n2013-09-08 23:00:00,67.97043986\n2013-09-09 00:00:00,66.92321439\n2013-09-09 01:00:00,68.59393936\n2013-09-09 02:00:00,66.62695158\n2013-09-09 03:00:00,67.75427493\n2013-09-09 04:00:00,66.66782263\n2013-09-09 05:00:00,67.46664892\n2013-09-09 06:00:00,67.60322003\n2013-09-09 07:00:00,67.66040956\n2013-09-09 08:00:00,66.65714613\n2013-09-09 09:00:00,68.75283581\n2013-09-09 10:00:00,69.19079475\n2013-09-09 11:00:00,70.45646119\n2013-09-09 12:00:00,70.93982761\n2013-09-09 13:00:00,69.63003292\n2013-09-09 14:00:00,71.41526516\n2013-09-09 15:00:00,71.55056424\n2013-09-09 16:00:00,71.90106522\n2013-09-09 17:00:00,71.69673606\n2013-09-09 18:00:00,71.04065657\n2013-09-09 19:00:00,71.73045012\n2013-09-09 20:00:00,72.76664681\n2013-09-16 12:00:00,72.69643979\n2013-09-16 13:00:00,72.80547371\n2013-09-16 14:00:00,72.91975931\n2013-09-16 15:00:00,72.26792976\n2013-09-16 16:00:00,72.85550390000002\n2013-09-16 17:00:00,72.96351653\n2013-09-16 18:00:00,72.77608689\n2013-09-16 19:00:00,74.71764725\n2013-09-16 20:00:00,75.18175232\n2013-09-16 21:00:00,74.68157666\n2013-09-16 22:00:00,75.03251294\n2013-09-16 23:00:00,74.89547613\n2013-09-17 00:00:00,72.88724781\n2013-09-17 01:00:00,74.04983548\n2013-09-17 02:00:00,73.82712414\n2013-09-17 03:00:00,72.79875638\n2013-09-17 04:00:00,71.99918837\n2013-09-17 05:00:00,72.17190677\n2013-09-17 06:00:00,71.25158302\n2013-09-17 07:00:00,71.28680525\n2013-09-17 08:00:00,71.38988043\n2013-09-17 09:00:00,72.24634579\n2013-09-17 10:00:00,71.59644925\n2013-09-17 11:00:00,72.90837738\n2013-09-17 12:00:00,73.24145352\n2013-09-17 13:00:00,73.06605307\n2013-09-17 14:00:00,72.64709801\n2013-09-17 15:00:00,73.15343178\n2013-09-17 16:00:00,72.96232879\n2013-09-17 17:00:00,72.52813486\n2013-09-17 18:00:00,73.81719904\n2013-09-17 19:00:00,74.02874448\n2013-09-17 20:00:00,73.79102864\n2013-09-17 21:00:00,73.25605739\n2013-09-17 22:00:00,73.05358423\n2013-09-17 23:00:00,73.77224906\n2013-09-18 00:00:00,72.8998969\n2013-09-18 01:00:00,72.24385814\n2013-09-18 02:00:00,71.33933531\n2013-09-18 03:00:00,72.29793377\n2013-09-18 04:00:00,70.34516442\n2013-09-18 05:00:00,71.13949198\n2013-09-18 06:00:00,70.16453648\n2013-09-18 07:00:00,71.11202658\n2013-09-18 08:00:00,70.4874724\n2013-09-18 09:00:00,70.71749668\n2013-09-18 10:00:00,69.89570423\n2013-09-18 11:00:00,71.68790348\n2013-09-18 12:00:00,71.37615947\n2013-09-18 13:00:00,71.74150703\n2013-09-18 14:00:00,73.20729802\n2013-09-18 15:00:00,72.89029189\n2013-09-18 16:00:00,72.30341978\n2013-09-18 17:00:00,72.6912123\n2013-09-18 18:00:00,72.34201351\n2013-09-18 19:00:00,74.49429294\n2013-09-18 20:00:00,73.25501422\n2013-09-18 21:00:00,74.13004256\n2013-09-18 22:00:00,73.68325892\n2013-09-18 23:00:00,72.11340117\n2013-09-19 00:00:00,72.31138231\n2013-09-19 01:00:00,71.29385993\n2013-09-19 02:00:00,71.93404046\n2013-09-19 03:00:00,71.67908598\n2013-09-19 04:00:00,71.48141177\n2013-09-19 05:00:00,70.85357689\n2013-09-19 06:00:00,69.45647733\n2013-09-19 07:00:00,70.12965246\n2013-09-19 08:00:00,69.02484940000001\n2013-09-19 09:00:00,69.00810205\n2013-09-19 10:00:00,67.59898139\n2013-09-19 11:00:00,67.55493576\n2013-09-19 12:00:00,67.40273072\n2013-09-19 13:00:00,67.39032649\n2013-09-19 14:00:00,68.09580201\n2013-09-19 15:00:00,67.39266673\n2013-09-19 16:00:00,68.36226835\n2013-09-19 17:00:00,68.40469903\n2013-09-19 18:00:00,67.83621597\n2013-09-19 19:00:00,69.19489788\n2013-09-19 20:00:00,68.49088179\n2013-09-19 21:00:00,68.33740959999999\n2013-09-19 22:00:00,68.76983220000001\n2013-09-19 23:00:00,68.4357686\n2013-09-20 00:00:00,68.74846768\n2013-09-20 01:00:00,68.95527404\n2013-09-20 02:00:00,68.2181708\n2013-09-20 03:00:00,69.12993292\n2013-09-20 04:00:00,68.4385586\n2013-09-20 05:00:00,69.06796416\n2013-09-20 06:00:00,68.30227174\n2013-09-20 07:00:00,68.64631402\n2013-09-20 08:00:00,68.88148079\n2013-09-20 09:00:00,68.90088305\n2013-09-20 10:00:00,69.65328565\n2013-09-20 11:00:00,68.86754593\n2013-09-20 12:00:00,68.42564703\n2013-09-20 13:00:00,69.09581068\n2013-09-20 14:00:00,69.44780599\n2013-09-20 15:00:00,68.42082002\n2013-09-20 16:00:00,68.83199074\n2013-09-20 17:00:00,69.55729317\n2013-09-20 18:00:00,68.83137434\n2013-09-20 19:00:00,70.02835926\n2013-09-20 20:00:00,71.07058978\n2013-09-20 21:00:00,71.28937940000002\n2013-09-20 22:00:00,70.10090101\n2013-09-20 23:00:00,71.68557803\n2013-09-21 00:00:00,69.88814945\n2013-09-21 01:00:00,70.42523491\n2013-09-21 02:00:00,69.44404702\n2013-09-21 03:00:00,70.1451179\n2013-09-21 04:00:00,69.48543471\n2013-09-21 05:00:00,69.63115874\n2013-09-21 06:00:00,70.00727727\n2013-09-21 07:00:00,69.16183248\n2013-09-21 08:00:00,68.43812628\n2013-09-21 09:00:00,68.65276698\n2013-09-21 10:00:00,68.15293671\n2013-09-21 11:00:00,69.64474901\n2013-09-21 12:00:00,69.0369617\n2013-09-21 13:00:00,68.59565354\n2013-09-21 14:00:00,69.91779386\n2013-09-21 15:00:00,68.59944984\n2013-09-21 16:00:00,68.66763575\n2013-09-21 17:00:00,68.79732688\n2013-09-21 18:00:00,69.52728032\n2013-09-21 19:00:00,69.14499021\n2013-09-21 20:00:00,69.36640493\n2013-09-21 21:00:00,69.32436477\n2013-09-21 22:00:00,70.04079998\n2013-09-21 23:00:00,70.32088532\n2013-09-22 00:00:00,70.68643574\n2013-09-22 01:00:00,69.41778612\n2013-09-22 02:00:00,69.52225613\n2013-09-22 03:00:00,69.97825566\n2013-09-22 04:00:00,69.84686459999999\n2013-09-22 05:00:00,69.94587165\n2013-09-22 06:00:00,68.70555692\n2013-09-22 07:00:00,68.59229114\n2013-09-22 08:00:00,69.9367965\n2013-09-22 09:00:00,69.07467717\n2013-09-22 10:00:00,68.77459707\n2013-09-22 11:00:00,68.96774462\n2013-09-22 12:00:00,69.51423059\n2013-09-22 13:00:00,69.60984678\n2013-09-22 14:00:00,68.45901476\n2013-09-22 15:00:00,68.66205887\n2013-09-22 16:00:00,69.07470807\n2013-09-22 17:00:00,68.98798244\n2013-09-22 18:00:00,70.4512398\n2013-09-22 19:00:00,69.1587948\n2013-09-22 20:00:00,70.02852311\n2013-09-22 21:00:00,70.30112967\n2013-09-22 22:00:00,71.02701721\n2013-09-22 23:00:00,70.44438138\n2013-09-23 00:00:00,71.21079549\n2013-09-23 01:00:00,70.08097943\n2013-09-23 02:00:00,70.01900785\n2013-09-23 03:00:00,71.31684052\n2013-09-23 04:00:00,69.49194049\n2013-09-23 05:00:00,70.71476009\n2013-09-23 06:00:00,70.30901685\n2013-09-23 07:00:00,69.92749715\n2013-09-23 08:00:00,69.28252505\n2013-09-23 09:00:00,70.51499697\n2013-09-23 10:00:00,69.17037572\n2013-09-23 11:00:00,69.67300935\n2013-09-23 12:00:00,70.98686733\n2013-09-23 13:00:00,72.71037561\n2013-09-23 14:00:00,72.84618043\n2013-09-23 15:00:00,71.49931817\n2013-09-23 16:00:00,71.82884072\n2013-09-23 17:00:00,71.96846019\n2013-09-23 18:00:00,72.38205511\n2013-09-23 19:00:00,73.10852105\n2013-09-23 20:00:00,72.50710177\n2013-09-23 21:00:00,71.36822279\n2013-09-23 22:00:00,71.73373415\n2013-09-23 23:00:00,70.39800507\n2013-09-24 00:00:00,71.02329854\n2013-09-24 01:00:00,70.42861121\n2013-09-24 02:00:00,71.29850242\n2013-09-24 03:00:00,70.41391036\n2013-09-24 04:00:00,69.83300525\n2013-09-24 05:00:00,70.04073494\n2013-09-24 06:00:00,69.2952676\n2013-09-24 07:00:00,69.80497056\n2013-09-24 08:00:00,70.47845996\n2013-09-24 09:00:00,68.87983862\n2013-09-24 10:00:00,70.82988977\n2013-09-24 11:00:00,71.7612628\n2013-09-24 12:00:00,71.23686153\n2013-09-24 13:00:00,72.17708088\n2013-09-24 14:00:00,73.52407232\n2013-09-24 15:00:00,73.43257426\n2013-09-24 16:00:00,71.96142812\n2013-09-24 17:00:00,72.06857704\n2013-09-24 18:00:00,72.80742737\n2013-09-24 19:00:00,74.18072649\n2013-09-24 20:00:00,72.6407991\n2013-09-24 21:00:00,72.49329287\n2013-09-24 22:00:00,73.37279171\n2013-09-24 23:00:00,72.84631814\n2013-09-25 00:00:00,73.74634464\n2013-09-25 01:00:00,73.08950487\n2013-09-25 02:00:00,73.12797789\n2013-09-25 03:00:00,72.85145065\n2013-09-25 04:00:00,71.78459362\n2013-09-25 05:00:00,71.96428662\n2013-09-25 06:00:00,70.98315976\n2013-09-25 07:00:00,72.09370496\n2013-09-25 08:00:00,70.47875896\n2013-09-25 09:00:00,71.15613714\n2013-09-25 10:00:00,71.79613981\n2013-09-25 11:00:00,70.53267958\n2013-09-25 12:00:00,70.92408688\n2013-09-25 13:00:00,71.07714472\n2013-09-25 14:00:00,72.12801602\n2013-09-25 15:00:00,73.76239725\n2013-09-25 16:00:00,73.50455944\n2013-09-25 17:00:00,74.06381073\n2013-09-25 18:00:00,75.84971566\n2013-09-25 19:00:00,74.917338\n2013-09-25 20:00:00,74.48204982\n2013-09-25 21:00:00,75.4754704\n2013-09-25 22:00:00,75.86633429\n2013-09-25 23:00:00,75.82692618\n2013-09-26 00:00:00,74.83518922\n2013-09-26 01:00:00,75.84170562\n2013-09-26 02:00:00,74.56152098\n2013-09-26 03:00:00,74.74597341\n2013-09-26 04:00:00,73.95196621\n2013-09-26 05:00:00,74.73785827\n2013-09-26 06:00:00,73.40944252\n2013-09-26 07:00:00,74.09665445\n2013-09-26 08:00:00,74.24341181\n2013-09-26 09:00:00,72.4241878\n2013-09-26 10:00:00,73.53577955\n2013-09-26 11:00:00,72.89263790000003\n2013-09-26 12:00:00,74.20179708\n2013-09-26 13:00:00,73.82891751\n2013-09-26 14:00:00,75.00384972\n2013-09-26 15:00:00,75.06654759999998\n2013-09-26 16:00:00,76.10375919\n2013-09-26 17:00:00,75.0111683\n2013-09-26 18:00:00,76.19220719\n2013-09-26 19:00:00,75.75430219\n2013-09-26 20:00:00,76.55201347\n2013-09-26 21:00:00,76.3420965\n2013-09-26 22:00:00,77.36149124\n2013-09-26 23:00:00,76.62602951\n2013-09-27 00:00:00,77.08086395\n2013-09-27 01:00:00,77.09614267\n2013-09-27 02:00:00,76.94079244\n2013-09-27 03:00:00,76.9216273\n2013-09-27 04:00:00,76.41395592\n2013-09-27 05:00:00,76.76728419\n2013-09-27 06:00:00,75.56516500000002\n2013-09-27 07:00:00,75.00316640000001\n2013-09-27 08:00:00,74.96022554\n2013-09-27 09:00:00,76.25958507\n2013-09-27 10:00:00,75.03195475\n2013-09-27 11:00:00,75.97741221\n2013-09-27 12:00:00,74.70847211\n2013-10-01 12:00:00,75.66428844\n2013-10-01 13:00:00,76.15183593\n2013-10-01 14:00:00,74.94798282\n2013-10-01 15:00:00,76.11749514\n2013-10-01 16:00:00,76.35342739\n2013-10-01 17:00:00,78.18999866\n2013-10-01 18:00:00,78.34183958\n2013-10-01 19:00:00,77.44052693\n2013-10-01 20:00:00,76.20708541\n2013-10-01 21:00:00,78.08998122\n2013-10-01 22:00:00,78.05491504\n2013-10-01 23:00:00,78.98542499\n2013-10-02 00:00:00,78.23875807\n2013-10-02 01:00:00,78.65871078\n2013-10-02 02:00:00,78.53164898\n2013-10-02 03:00:00,78.14277259999999\n2013-10-02 04:00:00,76.73686252\n2013-10-02 05:00:00,76.53612798\n2013-10-02 06:00:00,77.21543335\n2013-10-02 07:00:00,76.92976821\n2013-10-02 08:00:00,77.61334761\n2013-10-02 09:00:00,75.94869317\n2013-10-02 10:00:00,76.80988678\n2013-10-02 11:00:00,76.35617474\n2013-10-02 12:00:00,75.51487417\n2013-10-02 13:00:00,76.75914485\n2013-10-02 14:00:00,77.18231352\n2013-10-02 15:00:00,76.72424559\n2013-10-02 16:00:00,77.02058259\n2013-10-02 17:00:00,77.59412726\n2013-10-02 18:00:00,76.57737238\n2013-10-02 19:00:00,78.14370344\n2013-10-02 20:00:00,76.44863817\n2013-10-02 21:00:00,77.11808435\n2013-10-02 22:00:00,76.66444143\n2013-10-02 23:00:00,77.60066939\n2013-10-03 00:00:00,76.44893235\n2013-10-03 01:00:00,77.72893525\n2013-10-03 02:00:00,76.61186772\n2013-10-03 03:00:00,77.04302364\n2013-10-03 04:00:00,75.7689679\n2013-10-03 05:00:00,76.38938955\n2013-10-03 06:00:00,76.10096966\n2013-10-03 07:00:00,76.62421773\n2013-10-03 08:00:00,75.41072897\n2013-10-03 09:00:00,76.32543548\n2013-10-03 10:00:00,75.26776154\n2013-10-03 11:00:00,75.11220118\n2013-10-03 12:00:00,76.37061231\n2013-10-03 13:00:00,75.17527773\n2013-10-03 14:00:00,76.48020188\n2013-10-03 15:00:00,75.40371872\n2013-10-03 16:00:00,76.08145149\n2013-10-03 17:00:00,74.83978917\n2013-10-03 18:00:00,74.700469\n2013-10-03 19:00:00,75.46720555\n2013-10-03 20:00:00,74.52571486\n2013-10-03 21:00:00,75.50447062\n2013-10-03 22:00:00,76.68142877\n2013-10-03 23:00:00,77.07422539\n2013-10-04 00:00:00,76.62848003\n2013-10-04 01:00:00,75.65887074\n2013-10-04 02:00:00,76.78498097\n2013-10-04 03:00:00,76.97398833\n2013-10-04 04:00:00,76.81809786\n2013-10-04 05:00:00,76.18810762\n2013-10-04 06:00:00,75.14738658\n2013-10-04 07:00:00,74.60880026\n2013-10-04 08:00:00,74.71020506\n2013-10-04 09:00:00,74.33666665\n2013-10-04 10:00:00,75.89063588\n2013-10-04 11:00:00,74.92352501\n2013-10-04 12:00:00,76.25032166\n2013-10-04 13:00:00,76.76285447\n2013-10-04 14:00:00,76.43795622\n2013-10-04 15:00:00,75.84095165\n2013-10-04 16:00:00,76.30759992\n2013-10-04 17:00:00,76.37889288\n2013-10-04 18:00:00,74.50037961\n2013-10-04 19:00:00,75.46855478\n2013-10-04 20:00:00,76.23977529\n2013-10-04 21:00:00,75.60803745\n2013-10-04 22:00:00,75.53609477\n2013-10-04 23:00:00,76.15092858\n2013-10-05 00:00:00,77.04357167\n2013-10-05 01:00:00,76.83958927\n2013-10-05 02:00:00,75.35704476\n2013-10-05 03:00:00,75.26244693\n2013-10-05 04:00:00,75.67256245\n2013-10-05 05:00:00,74.97423465\n2013-10-05 06:00:00,74.68662683\n2013-10-05 07:00:00,74.67127682\n2013-10-05 08:00:00,75.30039984\n2013-10-05 09:00:00,75.41442640000002\n2013-10-05 10:00:00,75.77834261\n2013-10-05 11:00:00,76.30250549\n2013-10-05 12:00:00,76.08729308\n2013-10-05 13:00:00,76.17387791\n2013-10-05 14:00:00,74.59539903\n2013-10-05 15:00:00,74.8586202\n2013-10-05 16:00:00,76.15473545\n2013-10-05 17:00:00,76.73544665\n2013-10-05 18:00:00,76.81207028\n2013-10-05 19:00:00,76.76942959\n2013-10-05 20:00:00,76.0742703\n2013-10-05 21:00:00,77.67624752\n2013-10-05 22:00:00,77.20513301\n2013-10-05 23:00:00,78.30547509\n2013-10-06 00:00:00,76.57887568\n2013-10-06 01:00:00,76.88289528\n2013-10-06 02:00:00,77.48251447\n2013-10-06 03:00:00,76.38323965\n2013-10-06 04:00:00,76.26112886\n2013-10-06 05:00:00,77.83782089\n2013-10-06 06:00:00,77.81793736\n2013-10-06 07:00:00,76.88455309\n2013-10-06 08:00:00,77.29695705\n2013-10-06 09:00:00,75.7818161\n2013-10-06 10:00:00,77.23681223\n2013-10-06 11:00:00,77.65970467\n2013-10-06 12:00:00,76.47686703\n2013-10-06 13:00:00,76.45250409\n2013-10-06 14:00:00,76.44446488\n2013-10-06 15:00:00,75.338712\n2013-10-06 16:00:00,75.43988813\n2013-10-06 17:00:00,76.11375195\n2013-10-06 18:00:00,75.44361839\n2013-10-06 19:00:00,74.85664993\n2013-10-06 20:00:00,75.89981187\n2013-10-06 21:00:00,75.52638288\n2013-10-06 22:00:00,76.70454118\n2013-10-06 23:00:00,76.91841747\n2013-10-07 00:00:00,76.77395886\n2013-10-07 01:00:00,76.24255849\n2013-10-07 02:00:00,75.93339717\n2013-10-07 03:00:00,75.02163716\n2013-10-07 04:00:00,75.85554729\n2013-10-07 05:00:00,75.36964545\n2013-10-07 06:00:00,74.66467269\n2013-10-07 07:00:00,73.75869737\n2013-10-07 08:00:00,74.69866385\n2013-10-07 09:00:00,74.63334088\n2013-10-07 10:00:00,74.24988343\n2013-10-07 11:00:00,75.38338771\n2013-10-07 12:00:00,74.12097863\n2013-10-07 13:00:00,75.46608714\n2013-10-07 14:00:00,74.99673301\n2013-10-07 15:00:00,75.84411143\n2013-10-07 16:00:00,76.15467811\n2013-10-07 17:00:00,75.38180222\n2013-10-07 18:00:00,74.98612428\n2013-10-07 19:00:00,74.83290714\n2013-10-07 20:00:00,75.33838706\n2013-10-07 21:00:00,75.99301951\n2013-10-07 22:00:00,75.44383011\n2013-10-07 23:00:00,74.71510278\n2013-10-08 00:00:00,75.16393256\n2013-10-08 01:00:00,73.98772604\n2013-10-08 02:00:00,72.99713921\n2013-10-08 03:00:00,72.73963377\n2013-10-08 04:00:00,72.56210332\n2013-10-08 05:00:00,71.95415339\n2013-10-08 06:00:00,71.53772099\n2013-10-08 07:00:00,73.3846364\n2013-10-08 08:00:00,73.02911198\n2013-10-08 09:00:00,73.32056873\n2013-10-08 10:00:00,72.65757445\n2013-10-08 11:00:00,72.91058794\n2013-10-08 12:00:00,72.00144343\n2013-10-08 13:00:00,72.17948397\n2013-10-08 14:00:00,73.13684959999998\n2013-10-08 15:00:00,72.74243972\n2013-10-08 16:00:00,74.04314141\n2013-10-08 17:00:00,74.9362334\n2013-10-08 18:00:00,73.60819261\n2013-10-08 19:00:00,74.85510654\n2013-10-08 20:00:00,75.18349971\n2013-10-08 21:00:00,74.64847435\n2013-10-08 22:00:00,74.30749947\n2013-10-08 23:00:00,74.22020409\n2013-10-09 00:00:00,73.93927621\n2013-10-09 01:00:00,73.62134422\n2013-10-09 02:00:00,73.81914203\n2013-10-09 03:00:00,72.9684546\n2013-10-09 04:00:00,73.01285776\n2013-10-09 05:00:00,72.80505299\n2013-10-09 06:00:00,72.66330867\n2013-10-09 07:00:00,72.77940061\n2013-10-09 08:00:00,72.45267623\n2013-10-09 09:00:00,72.41013365\n2013-10-09 10:00:00,72.97620201\n2013-10-09 11:00:00,72.70599693\n2013-10-09 12:00:00,72.67329612\n2013-10-09 13:00:00,73.25471351\n2013-10-09 14:00:00,74.21758249\n2013-10-09 15:00:00,73.41679227\n2013-10-09 16:00:00,73.26801845\n2013-10-09 17:00:00,74.21654701\n2013-10-09 18:00:00,74.49963991\n2013-10-09 19:00:00,74.93839694\n2013-10-09 20:00:00,74.48590659999998\n2013-10-09 21:00:00,74.5249187\n2013-10-09 22:00:00,74.94497354\n2013-10-09 23:00:00,75.11312816\n2013-10-10 00:00:00,73.45479839\n2013-10-10 01:00:00,73.62753539\n2013-10-10 02:00:00,74.65356252\n2013-10-10 03:00:00,73.65569667\n2013-10-10 04:00:00,74.30833238\n2013-10-10 05:00:00,72.36883324\n2013-10-10 06:00:00,72.63029089\n2013-10-10 07:00:00,72.92216679\n2013-10-10 08:00:00,73.50841047\n2013-10-10 09:00:00,73.8940062\n2013-10-10 10:00:00,72.75520825\n2013-10-10 11:00:00,72.77342691\n2013-10-10 12:00:00,74.0173653\n2013-10-10 13:00:00,74.07999403\n2013-10-10 14:00:00,74.98348749\n2013-10-10 15:00:00,74.93166228\n2013-10-10 16:00:00,75.00032977\n2013-10-10 17:00:00,74.79545142\n2013-10-10 18:00:00,74.22649476\n2013-10-10 19:00:00,74.89181277\n2013-10-10 20:00:00,76.03381278\n2013-10-10 21:00:00,75.75160616\n2013-10-10 22:00:00,75.35499490000002\n2013-10-10 23:00:00,75.3520882\n2013-10-11 00:00:00,75.59122877\n2013-10-11 01:00:00,74.60615095\n2013-10-11 02:00:00,73.66657269\n2013-10-11 03:00:00,75.29576071\n2013-10-11 04:00:00,73.07467638\n2013-10-11 05:00:00,73.54096289\n2013-10-11 06:00:00,73.56748044\n2013-10-11 07:00:00,72.23943668\n2013-10-11 08:00:00,72.98971633\n2013-10-11 09:00:00,71.8624757\n2013-10-11 10:00:00,72.15907086\n2013-10-11 11:00:00,73.28710779\n2013-10-11 12:00:00,73.23267068\n2013-10-11 13:00:00,72.91831075\n2013-10-11 14:00:00,74.13951981\n2013-10-11 15:00:00,73.91840559\n2013-10-11 16:00:00,74.05658495\n2013-10-11 17:00:00,74.4819446\n2013-10-11 18:00:00,75.13591435\n2013-10-11 19:00:00,75.68312614\n2013-10-11 20:00:00,74.4794284\n2013-10-14 19:00:00,72.98303434\n2013-10-14 20:00:00,73.97904439\n2013-10-14 21:00:00,72.80960896\n2013-10-14 22:00:00,74.45908003\n2013-10-14 23:00:00,73.22449615\n2013-10-15 00:00:00,74.08849517\n2013-10-15 01:00:00,72.09427723\n2013-10-15 02:00:00,73.30412261\n2013-10-15 03:00:00,72.49226170000001\n2013-10-15 04:00:00,71.55592659\n2013-10-15 05:00:00,71.92880201\n2013-10-15 06:00:00,72.20455302\n2013-10-15 07:00:00,71.5729309\n2013-10-15 08:00:00,71.38455809\n2013-10-15 09:00:00,71.57838797\n2013-10-15 10:00:00,72.33092601\n2013-10-15 11:00:00,72.5020361\n2013-10-15 12:00:00,72.16890223\n2013-10-15 13:00:00,71.80124576\n2013-10-15 14:00:00,71.98653741\n2013-10-15 15:00:00,73.57829998\n2013-10-15 16:00:00,73.76993449\n2013-10-15 17:00:00,73.90520817\n2013-10-15 18:00:00,73.88052554\n2013-10-15 19:00:00,72.72460722\n2013-10-15 20:00:00,73.87825084\n2013-10-15 21:00:00,73.1538236\n2013-10-15 22:00:00,74.25507299\n2013-10-15 23:00:00,72.78303586\n2013-10-16 00:00:00,72.70043711\n2013-10-16 01:00:00,72.55484862\n2013-10-16 02:00:00,72.52805707\n2013-10-16 03:00:00,73.14618943\n2013-10-16 04:00:00,71.23182363\n2013-10-16 05:00:00,72.41740232\n2013-10-16 06:00:00,71.66301343\n2013-10-16 07:00:00,71.06682037\n2013-10-16 08:00:00,72.17174017\n2013-10-16 09:00:00,71.98736373\n2013-10-16 10:00:00,71.53260775\n2013-10-16 11:00:00,72.36545699\n2013-10-16 12:00:00,72.78437383\n2013-10-16 13:00:00,71.97296390000002\n2013-10-16 14:00:00,72.4644608\n2013-10-16 15:00:00,72.62455626\n2013-10-16 16:00:00,73.55532127\n2013-10-16 17:00:00,72.89143683\n2013-10-16 18:00:00,74.21730356\n2013-10-16 19:00:00,75.25147517\n2013-10-16 20:00:00,75.28003046\n2013-10-16 21:00:00,73.45611639\n2013-10-16 22:00:00,67.59220788\n2013-10-16 23:00:00,74.3959065\n2013-10-17 00:00:00,72.76152535\n2013-10-17 01:00:00,72.84667905\n2013-10-17 02:00:00,74.06782481\n2013-10-17 03:00:00,73.40328569\n2013-10-17 04:00:00,72.4928657\n2013-10-17 05:00:00,72.36963864\n2013-10-17 06:00:00,70.63012656\n2013-10-17 07:00:00,70.32611117\n2013-10-17 08:00:00,71.46025104\n2013-10-17 09:00:00,71.14590855\n2013-10-17 10:00:00,71.46817075\n2013-10-17 11:00:00,71.41876211\n2013-10-17 12:00:00,72.99363734\n2013-10-17 13:00:00,72.24666709\n2013-10-17 14:00:00,73.45167119\n2013-10-17 15:00:00,74.39956072\n2013-10-17 16:00:00,72.81416628\n2013-10-17 17:00:00,73.03240204\n2013-10-17 18:00:00,75.04333658\n2013-10-17 19:00:00,73.92938757\n2013-10-17 20:00:00,73.81507515\n2013-10-17 21:00:00,74.08455767\n2013-10-17 22:00:00,73.38180602\n2013-10-17 23:00:00,73.23701247\n2013-10-18 00:00:00,72.99037413\n2013-10-18 01:00:00,72.99012950000002\n2013-10-18 02:00:00,72.66562134\n2013-10-18 03:00:00,72.51950292\n2013-10-18 04:00:00,72.45390193\n2013-10-18 05:00:00,72.03998157\n2013-10-18 06:00:00,72.47195408\n2013-10-18 07:00:00,72.34968064\n2013-10-18 08:00:00,71.45220535\n2013-10-18 09:00:00,71.55743829999999\n2013-10-18 10:00:00,72.63790855\n2013-10-18 11:00:00,71.85849263\n2013-10-18 12:00:00,72.93395917\n2013-10-18 13:00:00,72.38591831\n2013-10-18 14:00:00,73.80702055\n2013-10-18 15:00:00,73.52710171\n2013-10-18 16:00:00,74.83471181\n2013-10-18 17:00:00,74.21326248\n2013-10-18 18:00:00,73.25223693\n2013-10-18 19:00:00,73.93628199999998\n2013-10-18 20:00:00,73.04669143\n2013-10-18 21:00:00,73.08417829999998\n2013-10-18 22:00:00,74.19287354\n2013-10-18 23:00:00,73.41808921\n2013-10-19 00:00:00,74.12963911\n2013-10-19 01:00:00,73.46278565\n2013-10-19 02:00:00,73.62789649\n2013-10-19 03:00:00,71.92833946\n2013-10-19 04:00:00,72.26119661\n2013-10-19 05:00:00,71.47946165\n2013-10-19 06:00:00,72.63321496\n2013-10-19 07:00:00,72.24354039\n2013-10-19 08:00:00,71.57056509\n2013-10-19 09:00:00,72.2797028\n2013-10-19 10:00:00,73.01911793\n2013-10-19 11:00:00,71.61445258\n2013-10-19 12:00:00,71.26409105\n2013-10-19 13:00:00,71.75373049\n2013-10-19 14:00:00,72.57075359\n2013-10-19 15:00:00,71.7959401\n2013-10-19 16:00:00,71.53861613\n2013-10-19 17:00:00,70.90022339\n2013-10-19 18:00:00,71.73254786\n2013-10-19 19:00:00,71.71309029999998\n2013-10-19 20:00:00,72.76010528\n2013-10-19 21:00:00,72.84417558\n2013-10-19 22:00:00,71.99223058\n2013-10-19 23:00:00,71.70725001\n2013-10-20 00:00:00,71.71438532\n2013-10-20 01:00:00,72.55191183\n2013-10-20 02:00:00,71.03928043\n2013-10-20 03:00:00,71.46046414\n2013-10-20 04:00:00,71.99130446\n2013-10-20 05:00:00,71.45046564\n2013-10-20 06:00:00,71.51504432\n2013-10-20 07:00:00,70.99280008\n2013-10-20 08:00:00,71.34776909\n2013-10-20 09:00:00,70.72845843\n2013-10-20 10:00:00,70.27507626\n2013-10-20 11:00:00,70.27111929\n2013-10-20 12:00:00,70.85408914\n2013-10-20 13:00:00,69.94855497\n2013-10-20 14:00:00,69.53492069\n2013-10-20 15:00:00,70.92058525\n2013-10-20 16:00:00,70.99850582\n2013-10-20 17:00:00,71.05686947\n2013-10-20 18:00:00,72.14843798\n2013-10-20 19:00:00,71.45617637\n2013-10-20 20:00:00,73.27200083\n2013-10-20 21:00:00,71.80063059\n2013-10-20 22:00:00,73.01762667\n2013-10-20 23:00:00,72.12768954\n2013-10-21 00:00:00,73.33199587\n2013-10-21 01:00:00,73.21702132\n2013-10-21 02:00:00,72.41071376\n2013-10-21 03:00:00,72.12548765\n2013-10-21 04:00:00,73.03066312\n2013-10-21 05:00:00,71.54792939\n2013-10-21 06:00:00,72.74034991\n2013-10-21 07:00:00,71.35108732\n2013-10-21 08:00:00,71.40181091\n2013-10-21 09:00:00,72.12977881\n2013-10-21 10:00:00,72.31327617\n2013-10-21 11:00:00,71.50759292\n2013-10-21 12:00:00,73.42790189\n2013-10-21 13:00:00,74.33787739\n2013-10-21 14:00:00,73.42943331\n2013-10-21 15:00:00,72.64800749999998\n2013-10-21 16:00:00,74.48313565\n2013-10-21 17:00:00,73.37484563\n2013-10-21 18:00:00,74.54468294\n2013-10-21 19:00:00,74.91468608\n2013-10-21 20:00:00,74.48188759\n2013-10-21 21:00:00,73.21984661\n2013-10-21 22:00:00,73.46717767\n2013-10-21 23:00:00,73.43538257\n2013-10-22 00:00:00,74.11014418\n2013-10-22 01:00:00,74.0856674\n2013-10-22 02:00:00,74.43241463\n2013-10-22 03:00:00,74.304057\n2013-10-22 04:00:00,73.43146696\n2013-10-22 05:00:00,72.49383421\n2013-10-22 06:00:00,73.03216682\n2013-10-22 07:00:00,71.83335039\n2013-10-22 08:00:00,71.01856015\n2013-10-22 09:00:00,72.21563105\n2013-10-22 10:00:00,72.48771792\n2013-10-22 11:00:00,72.7382649\n2013-10-22 12:00:00,73.60978997\n2013-10-22 13:00:00,73.74620023\n2013-10-22 14:00:00,73.23713965\n2013-10-22 15:00:00,73.4530571\n2013-10-22 16:00:00,73.92328043\n2013-10-22 17:00:00,75.18250744\n2013-10-22 18:00:00,74.02490252\n2013-10-22 19:00:00,75.3285915\n2013-10-22 20:00:00,74.66865644\n2013-10-22 21:00:00,74.14984749\n2013-10-22 22:00:00,74.89985381\n2013-10-22 23:00:00,75.30346611\n2013-10-23 00:00:00,73.91031296\n2013-10-23 01:00:00,73.93275037\n2013-10-23 02:00:00,73.16148058\n2013-10-23 03:00:00,73.52562326\n2013-10-23 04:00:00,72.47484370000002\n2013-10-23 05:00:00,72.49504420000002\n2013-10-23 06:00:00,71.61991048\n2013-10-23 07:00:00,73.22943968\n2013-10-23 08:00:00,71.58909683\n2013-10-23 09:00:00,71.81584418\n2013-10-23 10:00:00,71.34809224\n2013-10-23 11:00:00,72.96869218\n2013-10-23 12:00:00,72.55053234\n2013-10-23 13:00:00,72.57797464\n2013-10-23 14:00:00,74.69536550000002\n2013-10-23 15:00:00,74.1296061\n2013-10-23 16:00:00,73.94533205\n2013-10-23 17:00:00,74.07901132\n2013-10-23 18:00:00,75.05479911\n2013-10-23 19:00:00,74.85789892\n2013-10-23 20:00:00,76.0974356\n2013-10-23 21:00:00,75.60625767\n2013-10-23 22:00:00,76.460003\n2013-10-23 23:00:00,75.95853846\n2013-10-24 00:00:00,75.66920488\n2013-10-24 01:00:00,76.19819465\n2013-10-24 02:00:00,74.83838032\n2013-10-24 03:00:00,75.34256101\n2013-10-24 04:00:00,75.63691814\n2013-10-24 05:00:00,76.00126612\n2013-10-24 06:00:00,74.28973725\n2013-10-24 07:00:00,74.80605955\n2013-10-24 08:00:00,75.30172567\n2013-10-24 09:00:00,74.34735395\n2013-10-24 10:00:00,75.12651355\n2013-10-24 11:00:00,73.75813908\n2013-10-24 12:00:00,75.04085467\n2013-10-24 13:00:00,74.7295084\n2013-10-24 14:00:00,75.23496324\n2013-10-24 15:00:00,74.09558127\n2013-10-24 16:00:00,75.40924951\n2013-10-24 17:00:00,75.05840643\n2013-10-24 18:00:00,75.20790637\n2013-10-24 19:00:00,73.69135931\n2013-10-24 20:00:00,73.54196014\n2013-10-24 21:00:00,75.19082042\n2013-10-24 22:00:00,74.60746814\n2013-10-24 23:00:00,74.53993625\n2013-10-25 00:00:00,73.4168865\n2013-10-25 01:00:00,73.95852383\n2013-10-25 02:00:00,73.75006416\n2013-10-25 03:00:00,74.14389026\n2013-10-25 04:00:00,72.51791753\n2013-10-25 05:00:00,73.6608867\n2013-10-25 06:00:00,71.99874820000002\n2013-10-25 07:00:00,72.38400327\n2013-10-25 08:00:00,72.51858237\n2013-10-25 09:00:00,71.55343537\n2013-10-25 10:00:00,72.55778642\n2013-10-25 11:00:00,71.96670972\n2013-10-25 12:00:00,72.36781957\n2013-10-25 13:00:00,72.69666807\n2013-10-25 14:00:00,72.75559541\n2013-10-25 15:00:00,73.59062056\n2013-10-25 16:00:00,73.17199341\n2013-10-25 17:00:00,74.06972966\n2013-10-25 18:00:00,74.49830916\n2013-10-25 19:00:00,73.95696452\n2013-10-25 20:00:00,73.63058672\n2013-10-25 21:00:00,73.49661513\n2013-10-25 22:00:00,75.0238628\n2013-10-25 23:00:00,73.41067783\n2013-10-26 00:00:00,74.43789627\n2013-10-26 01:00:00,73.69728217\n2013-10-26 02:00:00,72.79073013\n2013-10-26 03:00:00,74.02303394\n2013-10-26 04:00:00,73.99547327\n2013-10-26 05:00:00,72.63698998\n2013-10-26 06:00:00,72.65022647\n2013-10-26 07:00:00,71.45778273\n2013-10-26 08:00:00,73.30880143\n2013-10-26 09:00:00,71.88486246\n2013-10-26 10:00:00,72.3666265\n2013-10-26 11:00:00,71.51972021\n2013-10-26 12:00:00,71.73511359\n2013-10-26 13:00:00,72.78641155\n2013-10-26 14:00:00,71.38856419\n2013-10-26 15:00:00,72.18526942\n2013-10-26 16:00:00,73.51448987\n2013-10-26 17:00:00,73.57199426\n2013-10-26 18:00:00,72.91075318\n2013-10-26 19:00:00,73.81514959\n2013-10-26 20:00:00,72.68504592\n2013-10-26 21:00:00,74.08911438\n2013-10-26 22:00:00,72.9589277\n2013-10-26 23:00:00,73.14610095\n2013-10-27 00:00:00,73.78917147\n2013-10-27 01:00:00,72.79764335\n2013-10-27 02:00:00,73.85796513\n2013-10-27 03:00:00,73.14750042\n2013-10-27 04:00:00,73.68655845\n2013-10-27 05:00:00,71.99772202\n2013-10-27 06:00:00,71.98066434\n2013-10-27 07:00:00,72.34138543\n2013-10-27 08:00:00,72.73493389\n2013-10-27 09:00:00,71.65669486\n2013-10-27 10:00:00,71.49563964\n2013-10-27 11:00:00,72.5480017\n2013-10-27 12:00:00,71.57221259\n2013-10-27 13:00:00,72.7741422\n2013-10-27 14:00:00,72.50897204\n2013-10-27 15:00:00,72.37165679\n2013-10-27 16:00:00,71.76151786\n2013-10-27 17:00:00,71.14297184\n2013-10-27 18:00:00,71.17422664\n2013-10-27 19:00:00,72.7253094\n2013-10-27 20:00:00,71.85317981\n2013-10-27 21:00:00,72.85663059\n2013-10-27 22:00:00,71.76247182\n2013-10-27 23:00:00,71.69635699999998\n2013-10-28 00:00:00,70.92483713\n2013-10-28 01:00:00,71.43725419\n2013-10-28 02:00:00,72.13600699999998\n2013-10-28 03:00:00,70.64687742\n2013-10-28 04:00:00,70.22032111\n2013-10-28 05:00:00,69.75235982\n2013-10-28 06:00:00,71.33829611\n2013-10-28 07:00:00,69.61769321\n2013-10-28 08:00:00,70.75591875\n2013-10-28 09:00:00,71.47646234\n2013-10-28 10:00:00,71.59381864\n2013-10-28 11:00:00,70.66816135\n2013-10-28 12:00:00,73.12430398\n2013-10-28 13:00:00,72.97024298\n2013-10-28 14:00:00,73.74160859999998\n2013-10-28 15:00:00,73.95406465\n2013-10-28 16:00:00,73.45808119\n2013-10-28 17:00:00,73.14484568\n2013-10-28 18:00:00,74.48764885\n2013-10-28 19:00:00,73.40434954\n2013-10-28 20:00:00,73.32924842\n2013-10-28 21:00:00,74.46460516\n2013-10-28 22:00:00,74.68612326\n2013-10-28 23:00:00,73.64400862\n2013-10-29 00:00:00,73.05155138\n2013-10-29 01:00:00,73.20917824\n2013-10-29 02:00:00,72.9686264\n2013-10-29 03:00:00,73.44971023\n2013-10-29 04:00:00,73.55495921\n2013-10-29 05:00:00,71.69592455\n2013-10-29 06:00:00,73.53646843\n2013-10-29 07:00:00,72.02971426\n2013-10-29 08:00:00,73.42081575\n2013-10-29 09:00:00,72.58490985\n2013-10-29 10:00:00,73.0300541\n2013-10-29 11:00:00,73.33546169\n2013-10-29 12:00:00,73.69525708\n2013-10-29 13:00:00,74.44248772\n2013-10-29 14:00:00,73.36288859\n2013-10-29 15:00:00,74.23441848\n2013-10-29 16:00:00,73.53614618\n2013-10-29 17:00:00,73.55358243\n2013-10-29 18:00:00,73.31606619\n2013-10-29 19:00:00,74.07121348\n2013-10-29 20:00:00,73.84322808\n2013-10-29 21:00:00,74.31880636\n2013-10-29 22:00:00,75.37365059999998\n2013-10-29 23:00:00,74.6158649\n2013-10-30 00:00:00,74.22361987\n2013-10-30 01:00:00,74.90183652\n2013-10-30 02:00:00,74.60288205\n2013-10-30 03:00:00,73.60468314\n2013-10-30 04:00:00,74.41600686\n2013-10-30 05:00:00,74.16088548\n2013-10-30 06:00:00,72.84884222\n2013-10-30 07:00:00,72.92107082\n2013-10-30 08:00:00,73.01604281\n2013-10-30 09:00:00,74.13143498\n2013-10-30 10:00:00,72.57848043\n2013-10-30 11:00:00,72.87188536\n2013-10-30 12:00:00,73.61682058\n2013-10-30 13:00:00,73.37016715\n2013-10-30 14:00:00,74.04450691\n2013-10-30 15:00:00,74.12361236\n2013-10-30 16:00:00,74.66328477\n2013-10-30 17:00:00,75.70737338\n2013-10-30 18:00:00,75.3545802\n2013-10-30 19:00:00,75.25614118\n2013-10-30 20:00:00,74.87355721\n2013-10-30 21:00:00,76.29745203\n2013-10-30 22:00:00,75.32289320000002\n2013-10-30 23:00:00,75.85634859999998\n2013-10-31 00:00:00,75.14595644\n2013-10-31 01:00:00,75.88962012\n2013-10-31 02:00:00,76.4180307\n2013-10-31 03:00:00,76.56197890000001\n2013-10-31 04:00:00,76.10597378\n2013-10-31 05:00:00,75.25141922\n2013-10-31 06:00:00,75.72435817\n2013-10-31 07:00:00,74.49878947\n2013-10-31 08:00:00,75.84183322\n2013-10-31 09:00:00,75.2866983\n2013-10-31 10:00:00,74.87398102\n2013-10-31 11:00:00,74.94194615\n2013-10-31 12:00:00,75.98035652\n2013-10-31 13:00:00,74.95842691\n2013-10-31 14:00:00,75.24512346\n2013-10-31 15:00:00,75.35692048\n2013-10-31 16:00:00,76.88500697\n2013-10-31 17:00:00,76.12766594\n2013-10-31 18:00:00,75.86319296\n2013-10-31 19:00:00,76.41346624\n2013-10-31 20:00:00,75.5347714\n2013-10-31 21:00:00,75.84580103\n2013-10-31 22:00:00,76.34558396\n2013-10-31 23:00:00,77.39292354\n2013-11-01 00:00:00,76.30796353\n2013-11-01 01:00:00,77.25259793\n2013-11-01 02:00:00,76.43178992\n2013-11-01 03:00:00,77.69772574\n2013-11-01 04:00:00,76.53784364\n2013-11-01 05:00:00,76.38649065\n2013-11-01 06:00:00,77.20675318\n2013-11-01 07:00:00,77.18738382\n2013-11-01 08:00:00,75.67736243\n2013-11-01 09:00:00,74.81300493\n2013-11-01 10:00:00,75.83696911\n2013-11-01 11:00:00,75.02326067\n2013-11-01 12:00:00,75.05073943\n2013-11-01 13:00:00,75.28745236\n2013-11-01 14:00:00,75.20319345\n2013-11-01 15:00:00,75.12528566\n2013-11-01 16:00:00,75.19924971\n2013-11-01 17:00:00,75.73098218\n2013-11-01 18:00:00,75.93704108\n2013-11-01 19:00:00,74.89355303\n2013-11-01 20:00:00,75.07774926\n2013-11-01 21:00:00,75.25618705\n2013-11-01 22:00:00,75.71797654\n2013-11-01 23:00:00,75.63395379\n2013-11-02 00:00:00,75.48381386\n2013-11-02 01:00:00,75.66762937\n2013-11-02 02:00:00,76.51474357\n2013-11-02 03:00:00,75.08953119\n2013-11-02 04:00:00,75.81216694\n2013-11-02 05:00:00,75.60610346\n2013-11-02 06:00:00,74.96367140000002\n2013-11-02 07:00:00,74.98121493\n2013-11-02 08:00:00,74.45643905\n2013-11-02 09:00:00,75.51516542\n2013-11-02 10:00:00,74.73560812\n2013-11-02 11:00:00,74.69915087\n2013-11-02 12:00:00,74.54298971\n2013-11-02 13:00:00,73.35219351\n2013-11-02 14:00:00,74.12383795\n2013-11-02 15:00:00,74.22554631\n2013-11-02 16:00:00,73.99079534\n2013-11-02 17:00:00,74.79507379\n2013-11-02 18:00:00,76.11205116\n2013-11-02 19:00:00,75.22593768\n2013-11-02 20:00:00,75.27953666\n2013-11-02 21:00:00,77.15937503\n2013-11-02 22:00:00,76.19111223\n2013-11-02 23:00:00,76.31079818\n2013-11-03 00:00:00,76.38206634\n2013-11-03 01:00:00,75.57825005\n2013-11-03 02:00:00,76.13455079999999\n2013-11-03 03:00:00,75.23603382\n2013-11-03 04:00:00,76.23782807\n2013-11-03 05:00:00,75.336605\n2013-11-03 06:00:00,74.36531352\n2013-11-03 07:00:00,73.71769524\n2013-11-03 08:00:00,74.074138\n2013-11-03 09:00:00,74.84189513\n2013-11-03 10:00:00,73.95914727\n2013-11-03 11:00:00,74.04130502\n2013-11-03 12:00:00,74.56437617\n2013-11-03 13:00:00,73.29808803\n2013-11-03 14:00:00,73.53188681\n2013-11-03 15:00:00,73.87759563\n2013-11-03 16:00:00,74.87971926\n2013-11-03 17:00:00,74.1892936\n2013-11-03 18:00:00,75.41399344\n2013-11-03 19:00:00,75.86744504\n2013-11-03 20:00:00,75.6150603\n2013-11-03 21:00:00,76.97153329\n2013-11-03 22:00:00,77.0894334\n2013-11-03 23:00:00,76.17299187\n2013-11-04 00:00:00,75.60827582\n2013-11-04 01:00:00,76.66746590000002\n2013-11-04 02:00:00,76.59056219\n2013-11-04 03:00:00,75.05998404\n2013-11-04 04:00:00,75.88379996\n2013-11-04 05:00:00,75.47865146\n2013-11-04 06:00:00,74.4588194\n2013-11-04 07:00:00,73.60738959\n2013-11-04 08:00:00,74.41420743\n2013-11-04 09:00:00,74.765766\n2013-11-04 10:00:00,74.16291232\n2013-11-04 11:00:00,74.19468656\n2013-11-04 12:00:00,74.43225537\n2013-11-04 13:00:00,74.24359177\n2013-11-04 14:00:00,74.55720475\n2013-11-04 15:00:00,75.76889616\n2013-11-04 16:00:00,75.5197806\n2013-11-04 17:00:00,74.72805694\n2013-11-04 18:00:00,75.06364679\n2013-11-04 19:00:00,75.92542961\n2013-11-04 20:00:00,75.03438753\n2013-11-04 21:00:00,75.53025670000002\n2013-11-04 22:00:00,76.20838186\n2013-11-04 23:00:00,75.88011467\n2013-11-05 00:00:00,75.25305005\n2013-11-05 01:00:00,76.16092035\n2013-11-05 02:00:00,74.87732367\n2013-11-05 03:00:00,75.70725229\n2013-11-05 04:00:00,74.62446294\n2013-11-05 05:00:00,73.93894725\n2013-11-05 06:00:00,75.39833336\n2013-11-05 07:00:00,73.67042395\n2013-11-05 08:00:00,74.78394113\n2013-11-05 09:00:00,75.36637593\n2013-11-05 10:00:00,75.62678541\n2013-11-05 11:00:00,75.54245470000002\n2013-11-05 12:00:00,75.56486359\n2013-11-05 13:00:00,75.40045594\n2013-11-05 14:00:00,75.72241656\n2013-11-05 15:00:00,75.38360735\n2013-11-05 16:00:00,74.96366192\n2013-11-05 17:00:00,75.15506847\n2013-11-05 18:00:00,76.44462418\n2013-11-05 19:00:00,76.14152676\n2013-11-05 20:00:00,77.7365963\n2013-11-05 21:00:00,75.94504175\n2013-11-05 22:00:00,77.66560315\n2013-11-05 23:00:00,77.14421695\n2013-11-06 00:00:00,77.14840943\n2013-11-06 01:00:00,76.57972961\n2013-11-06 02:00:00,75.67263157\n2013-11-06 03:00:00,75.55554775\n2013-11-06 04:00:00,76.02875358\n2013-11-06 05:00:00,75.83856917\n2013-11-06 06:00:00,76.72809013\n2013-11-06 07:00:00,76.8067863\n2013-11-06 08:00:00,76.14957763\n2013-11-06 09:00:00,74.72851186\n2013-11-06 10:00:00,76.79427945\n2013-11-06 11:00:00,75.54402995\n2013-11-06 12:00:00,75.62375922\n2013-11-06 13:00:00,75.66503039\n2013-11-06 14:00:00,76.1298699\n2013-11-06 15:00:00,75.2965713\n2013-11-06 16:00:00,75.65848549\n2013-11-06 17:00:00,75.77541647\n2013-11-06 18:00:00,75.7226112\n2013-11-06 19:00:00,75.17457270000001\n2013-11-06 20:00:00,76.75484571\n2013-11-06 21:00:00,76.17423765\n2013-11-06 22:00:00,76.11021976\n2013-11-06 23:00:00,77.62413958\n2013-11-07 00:00:00,76.47954412\n2013-11-07 01:00:00,77.95666612\n2013-11-07 02:00:00,77.26824525\n2013-11-07 03:00:00,76.93680905\n2013-11-07 04:00:00,77.33274264\n2013-11-07 05:00:00,75.89490524\n2013-11-07 06:00:00,76.97245983\n2013-11-07 07:00:00,76.44928327\n2013-11-07 08:00:00,76.38799696\n2013-11-07 09:00:00,76.09948105\n2013-11-07 10:00:00,76.81359962\n2013-11-07 11:00:00,75.10202225\n2013-11-07 12:00:00,75.6896651\n2013-11-07 13:00:00,76.31908661\n2013-11-07 14:00:00,76.23526528\n2013-11-07 15:00:00,75.71330856\n2013-11-07 16:00:00,75.27910715\n2013-11-07 17:00:00,75.6502543\n2013-11-07 18:00:00,76.21250234\n2013-11-07 19:00:00,77.10759799\n2013-11-07 20:00:00,76.93375995\n2013-11-07 21:00:00,75.77571222\n2013-11-07 22:00:00,75.93642846\n2013-11-07 23:00:00,75.42451794\n2013-11-08 00:00:00,75.74984119\n2013-11-08 01:00:00,75.72379288\n2013-11-08 02:00:00,76.19812769\n2013-11-08 03:00:00,76.40959723\n2013-11-08 04:00:00,76.17249971\n2013-11-08 05:00:00,74.18157735\n2013-11-08 06:00:00,75.54911204\n2013-11-08 07:00:00,74.92685622\n2013-11-08 08:00:00,74.06821774\n2013-11-08 09:00:00,74.6063132\n2013-11-08 10:00:00,74.59934737\n2013-11-08 11:00:00,74.57257027\n2013-11-08 12:00:00,75.80192985\n2013-11-08 13:00:00,75.58576634\n2013-11-08 14:00:00,75.80339835\n2013-11-08 15:00:00,74.95083817\n2013-11-08 16:00:00,74.30202352\n2013-11-08 17:00:00,74.30126215\n2013-11-08 18:00:00,74.56143904\n2013-11-08 19:00:00,74.80702056\n2013-11-08 20:00:00,73.81540339\n2013-11-08 21:00:00,74.46177933\n2013-11-08 22:00:00,73.33340389\n2013-11-08 23:00:00,73.13844142\n2013-11-09 00:00:00,74.43327812\n2013-11-09 01:00:00,73.55423309999998\n2013-11-09 02:00:00,74.72110603\n2013-11-09 03:00:00,73.50877487\n2013-11-09 04:00:00,74.83946496\n2013-11-09 05:00:00,73.55614636\n2013-11-09 06:00:00,73.07126074\n2013-11-09 07:00:00,72.82584529\n2013-11-09 08:00:00,72.95550534\n2013-11-09 09:00:00,73.64826422\n2013-11-09 10:00:00,73.4784976\n2013-11-09 11:00:00,73.16790935\n2013-11-09 12:00:00,72.25990891\n2013-11-09 13:00:00,73.22695232\n2013-11-09 14:00:00,73.36574509999998\n2013-11-09 15:00:00,72.78698119\n2013-11-09 16:00:00,73.23132790000003\n2013-11-09 17:00:00,73.06305918\n2013-11-09 18:00:00,73.23528333\n2013-11-09 19:00:00,73.95548531\n2013-11-09 20:00:00,73.98859537\n2013-11-09 21:00:00,73.18927798\n2013-11-09 22:00:00,73.48796428\n2013-11-09 23:00:00,73.23741435\n2013-11-10 00:00:00,74.54367695\n2013-11-10 01:00:00,73.43081550000002\n2013-11-10 02:00:00,74.74891586\n2013-11-10 03:00:00,74.75362909\n2013-11-10 04:00:00,72.86175442\n2013-11-10 05:00:00,72.73720269\n2013-11-10 06:00:00,73.3559507\n2013-11-10 07:00:00,73.39759537\n2013-11-10 08:00:00,73.14595598\n2013-11-10 09:00:00,73.76092178\n2013-11-10 10:00:00,72.25168702\n2013-11-10 11:00:00,73.13205651\n2013-11-10 12:00:00,72.08360267\n2013-11-10 13:00:00,72.07368375\n2013-11-10 14:00:00,72.61268471\n2013-11-10 15:00:00,73.72321874\n2013-11-10 16:00:00,73.72849169\n2013-11-10 17:00:00,73.13296089\n2013-11-10 18:00:00,72.65494358\n2013-11-10 19:00:00,72.32299088\n2013-11-10 20:00:00,73.55015881\n2013-11-10 21:00:00,73.72223486\n2013-11-10 22:00:00,72.25297108\n2013-11-10 23:00:00,72.31541006\n2013-11-11 00:00:00,72.76195068\n2013-11-11 01:00:00,73.76142519\n2013-11-11 02:00:00,73.10583663\n2013-11-11 03:00:00,73.50193935\n2013-11-11 04:00:00,73.49132918\n2013-11-11 05:00:00,72.41669997\n2013-11-11 06:00:00,73.04263579\n2013-11-11 07:00:00,72.31388627\n2013-11-11 08:00:00,71.53125555\n2013-11-11 09:00:00,72.51297974\n2013-11-11 10:00:00,73.05072318\n2013-11-11 11:00:00,72.93039079\n2013-11-11 12:00:00,72.68112696\n2013-11-11 13:00:00,74.10651227\n2013-11-11 14:00:00,73.20678582\n2013-11-11 15:00:00,73.97883407\n2013-11-11 16:00:00,74.29101178\n2013-11-11 17:00:00,75.92300396\n2013-11-11 18:00:00,75.09551863\n2013-11-11 19:00:00,74.50642676\n2013-11-11 20:00:00,75.29868809\n2013-11-11 21:00:00,74.81087057\n2013-11-11 22:00:00,75.04623283\n2013-11-11 23:00:00,75.27267490000001\n2013-11-12 00:00:00,74.35723061\n2013-11-12 01:00:00,75.59912555\n2013-11-12 02:00:00,75.38508019\n2013-11-12 03:00:00,74.01849770000003\n2013-11-12 04:00:00,74.67643353\n2013-11-12 05:00:00,74.23187951\n2013-11-12 06:00:00,73.23464912\n2013-11-12 07:00:00,72.9246375\n2013-11-12 08:00:00,73.50042577\n2013-11-12 09:00:00,73.9103724\n2013-11-12 10:00:00,73.36473041\n2013-11-12 11:00:00,74.56847369\n2013-11-12 12:00:00,73.01626683\n2013-11-12 13:00:00,74.58986064\n2013-11-12 14:00:00,74.79361415\n2013-11-12 15:00:00,74.62816075\n2013-11-12 16:00:00,73.48499084\n2013-11-12 17:00:00,74.83572629999998\n2013-11-12 18:00:00,75.71863379\n2013-11-12 19:00:00,74.10748463\n2013-11-12 20:00:00,76.18679389\n2013-11-12 21:00:00,75.68515368\n2013-11-12 22:00:00,75.95116314\n2013-11-12 23:00:00,75.27091748\n2013-11-13 00:00:00,75.10698746\n2013-11-13 01:00:00,75.50230648\n2013-11-13 02:00:00,74.96947424\n2013-11-13 03:00:00,74.66135819\n2013-11-13 04:00:00,74.16500932\n2013-11-13 05:00:00,73.61945248\n2013-11-13 06:00:00,73.04705436\n2013-11-13 07:00:00,73.10898413\n2013-11-13 08:00:00,73.14571961\n2013-11-13 09:00:00,73.13454489\n2013-11-13 10:00:00,73.63776206\n2013-11-13 11:00:00,72.51683568\n2013-11-13 12:00:00,74.15631949\n2013-11-13 13:00:00,73.16933890000001\n2013-11-13 14:00:00,74.42966035\n2013-11-13 15:00:00,73.93593742\n2013-11-13 16:00:00,74.0165059\n2013-11-13 17:00:00,75.64136409999998\n2013-11-13 18:00:00,75.49191161\n2013-11-13 19:00:00,74.71810201\n2013-11-13 20:00:00,75.30978555\n2013-11-13 21:00:00,75.66631972\n2013-11-13 22:00:00,76.3113897\n2013-11-13 23:00:00,75.93818590000002\n2013-11-14 00:00:00,75.28806128\n2013-11-14 01:00:00,74.04154576\n2013-11-14 02:00:00,75.03847755\n2013-11-14 03:00:00,74.23765297\n2013-11-14 04:00:00,74.41627738\n2013-11-14 05:00:00,72.52116762\n2013-11-14 06:00:00,72.25396537\n2013-11-14 07:00:00,73.35919816\n2013-11-14 08:00:00,73.3005709\n2013-11-14 09:00:00,71.94989116\n2013-11-14 10:00:00,72.70754191\n2013-11-14 11:00:00,73.57919806\n2013-11-14 12:00:00,73.71447163\n2013-11-14 13:00:00,73.20962568\n2013-11-14 14:00:00,73.60901764\n2013-11-14 15:00:00,73.39056823\n2013-11-14 16:00:00,74.84991329\n2013-11-14 17:00:00,75.29117938\n2013-11-14 18:00:00,75.05266772\n2013-11-14 19:00:00,73.87313966\n2013-11-14 20:00:00,73.88685052\n2013-11-14 21:00:00,75.32457686\n2013-11-14 22:00:00,74.52795985\n2013-11-14 23:00:00,74.50517038\n2013-11-15 00:00:00,75.28019509999999\n2013-11-15 01:00:00,73.39054569\n2013-11-15 02:00:00,73.61502322\n2013-11-15 03:00:00,73.40129594\n2013-11-15 04:00:00,72.71904624\n2013-11-15 05:00:00,73.04163914\n2013-11-15 06:00:00,71.66850691\n2013-11-15 07:00:00,72.44293549\n2013-11-15 08:00:00,72.77424531\n2013-11-15 09:00:00,71.02651442\n2013-11-15 10:00:00,72.46122501\n2013-11-15 11:00:00,72.053069\n2013-11-15 12:00:00,71.43164940000003\n2013-11-15 13:00:00,73.5399011\n2013-11-15 14:00:00,73.32159625\n2013-11-15 15:00:00,74.17128378\n2013-11-15 16:00:00,73.44249817\n2013-11-15 17:00:00,73.84389329999998\n2013-11-15 18:00:00,74.32478195\n2013-11-15 19:00:00,74.33059913\n2013-11-15 20:00:00,74.50938842\n2013-11-15 21:00:00,74.18876225\n2013-11-15 22:00:00,73.26010958\n2013-11-15 23:00:00,72.71542581\n2013-11-16 00:00:00,72.91699629\n2013-11-16 01:00:00,72.72921375\n2013-11-16 02:00:00,72.00496338\n2013-11-16 03:00:00,72.91473652\n2013-11-16 04:00:00,72.22070042\n2013-11-16 05:00:00,72.19057869\n2013-11-16 06:00:00,72.75354149\n2013-11-16 07:00:00,70.85140062\n2013-11-16 08:00:00,72.60434778\n2013-11-16 09:00:00,72.2513124\n2013-11-16 10:00:00,72.44304869\n2013-11-16 11:00:00,71.82902242\n2013-11-16 12:00:00,72.13432831\n2013-11-16 13:00:00,72.28302117\n2013-11-16 14:00:00,70.87841589\n2013-11-16 15:00:00,70.5596423\n2013-11-16 16:00:00,71.49929374\n2013-11-16 17:00:00,70.91004612\n2013-11-16 18:00:00,71.52840484\n2013-11-16 19:00:00,71.62859496\n2013-11-16 20:00:00,72.74468133\n2013-11-16 21:00:00,71.59071961\n2013-11-16 22:00:00,72.53877392\n2013-11-16 23:00:00,72.67710054\n2013-11-17 00:00:00,72.51924339\n2013-11-17 01:00:00,72.53149628\n2013-11-17 02:00:00,71.57898299\n2013-11-17 03:00:00,72.42367877\n2013-11-17 04:00:00,71.48775583\n2013-11-17 05:00:00,71.06116079\n2013-11-17 06:00:00,70.32136308\n2013-11-17 07:00:00,71.8799218\n2013-11-17 08:00:00,72.01945706\n2013-11-17 09:00:00,71.02801335\n2013-11-17 10:00:00,70.32011267\n2013-11-17 11:00:00,70.43736052\n2013-11-17 12:00:00,70.71326074\n2013-11-17 13:00:00,71.29496969\n2013-11-17 14:00:00,71.19238211\n2013-11-17 15:00:00,70.76197992\n2013-11-17 16:00:00,71.97783594\n2013-11-17 17:00:00,71.93428932\n2013-11-17 18:00:00,70.92727189\n2013-11-17 19:00:00,70.69309796\n2013-11-17 20:00:00,72.26337995\n2013-11-17 21:00:00,71.59257385\n2013-11-17 22:00:00,72.78595446\n2013-11-17 23:00:00,72.51893435\n2013-11-18 00:00:00,71.86984301\n2013-11-18 01:00:00,72.26094927\n2013-11-18 02:00:00,71.49387364\n2013-11-18 03:00:00,71.34440084\n2013-11-18 04:00:00,71.45222531\n2013-11-18 05:00:00,71.07687116\n2013-11-18 06:00:00,70.85817442\n2013-11-18 07:00:00,70.94781553\n2013-11-18 08:00:00,70.27853073\n2013-11-18 09:00:00,69.32489169\n2013-11-18 10:00:00,70.20579203\n2013-11-18 11:00:00,70.38921093\n2013-11-18 12:00:00,71.97995521\n2013-11-18 13:00:00,71.09700465\n2013-11-18 14:00:00,73.01321007\n2013-11-18 15:00:00,72.74733169\n2013-11-18 16:00:00,72.53910037\n2013-11-18 17:00:00,73.35960207\n2013-11-18 18:00:00,72.84142418\n2013-11-18 19:00:00,74.43420638\n2013-11-18 20:00:00,74.6164561\n2013-11-18 21:00:00,74.22528903\n2013-11-18 22:00:00,74.42442215\n2013-11-18 23:00:00,73.14775012\n2013-11-19 00:00:00,73.69107041\n2013-11-19 01:00:00,74.03109935\n2013-11-19 02:00:00,73.46135999\n2013-11-19 03:00:00,72.49412233\n2013-11-19 04:00:00,73.09658152\n2013-11-19 05:00:00,73.46536527\n2013-11-19 06:00:00,72.80605916\n2013-11-19 07:00:00,71.59932742\n2013-11-19 08:00:00,72.73375635\n2013-11-19 09:00:00,73.27079545\n2013-11-19 10:00:00,72.32538482\n2013-11-19 11:00:00,71.96557762\n2013-11-19 12:00:00,72.50861543\n2013-11-19 13:00:00,72.20848244\n2013-11-19 14:00:00,73.98532747\n2013-11-19 15:00:00,73.77910642\n2013-11-19 16:00:00,73.74309124\n2013-11-19 17:00:00,75.62033656\n2013-11-19 18:00:00,75.92989871\n2013-11-19 19:00:00,76.14345589\n2013-11-19 20:00:00,75.62712477\n2013-11-19 21:00:00,76.09385992\n2013-11-19 22:00:00,76.71081637\n2013-11-19 23:00:00,76.04933698\n2013-11-20 00:00:00,75.72755913\n2013-11-20 01:00:00,75.51638547\n2013-11-20 02:00:00,74.52746945\n2013-11-20 03:00:00,74.48053719\n2013-11-20 04:00:00,75.44810401\n2013-11-20 05:00:00,73.87105555\n2013-11-20 06:00:00,75.52376743\n2013-11-20 07:00:00,73.59258353\n2013-11-20 08:00:00,73.54086694\n2013-11-20 09:00:00,74.60328237\n2013-11-20 10:00:00,73.53405054\n2013-11-20 11:00:00,73.18585771\n2013-11-20 12:00:00,74.73396876\n2013-11-20 13:00:00,74.00301199\n2013-11-20 14:00:00,74.25992091\n2013-11-20 15:00:00,75.3819048\n2013-11-20 16:00:00,74.89925956\n2013-11-20 17:00:00,74.95695549\n2013-11-20 18:00:00,74.99328121\n2013-11-20 19:00:00,76.8861063\n2013-11-20 20:00:00,75.74120031\n2013-11-20 21:00:00,77.29515004\n2013-11-20 22:00:00,77.42615583\n2013-11-20 23:00:00,77.57042544\n2013-11-21 00:00:00,76.97148499\n2013-11-21 01:00:00,76.55304852\n2013-11-21 02:00:00,76.83218408\n2013-11-21 03:00:00,76.76691174\n2013-11-21 04:00:00,75.03003109\n2013-11-21 05:00:00,76.13262453\n2013-11-21 06:00:00,74.88298612\n2013-11-21 07:00:00,74.75528879999997\n2013-11-21 08:00:00,74.96824419\n2013-11-21 09:00:00,74.38032373\n2013-11-21 10:00:00,74.51502775\n2013-11-21 11:00:00,75.03807231\n2013-11-21 12:00:00,75.47315484\n2013-11-21 13:00:00,74.28147702\n2013-11-21 14:00:00,74.9158214\n2013-11-21 15:00:00,74.73332116\n2013-11-21 16:00:00,74.57659907\n2013-11-21 17:00:00,75.13741621\n2013-11-21 18:00:00,76.09123393\n2013-11-21 19:00:00,75.48996689\n2013-11-21 20:00:00,75.37277558\n2013-11-21 21:00:00,74.86375645\n2013-11-21 22:00:00,74.72416427\n2013-11-21 23:00:00,75.88303251\n2013-11-22 00:00:00,76.26881945\n2013-11-22 01:00:00,74.40797403\n2013-11-22 02:00:00,75.07100534\n2013-11-22 03:00:00,75.22936273\n2013-11-22 04:00:00,75.3850351\n2013-11-22 05:00:00,74.12951939\n2013-11-22 06:00:00,74.33830078\n2013-11-22 07:00:00,73.13110340000001\n2013-11-22 08:00:00,73.72892540000002\n2013-11-22 09:00:00,73.47971521\n2013-11-22 10:00:00,73.55503441\n2013-11-22 11:00:00,73.21770574\n2013-11-22 12:00:00,74.8002409\n2013-11-22 13:00:00,75.10424352\n2013-11-22 14:00:00,74.02504086\n2013-11-22 15:00:00,75.99705923\n2013-11-22 16:00:00,76.14728499\n2013-11-22 17:00:00,75.97342391\n2013-11-22 18:00:00,74.55135899\n2013-11-22 19:00:00,75.52513628\n2013-11-22 20:00:00,74.83841776\n2013-11-22 21:00:00,75.86804316\n2013-11-22 22:00:00,74.78322701\n2013-11-22 23:00:00,74.93730171\n2013-11-23 00:00:00,75.99533878\n2013-11-23 01:00:00,74.9811996\n2013-11-23 02:00:00,74.90004537\n2013-11-23 03:00:00,74.45881512\n2013-11-23 04:00:00,74.98859321\n2013-11-23 05:00:00,74.80551896\n2013-11-23 06:00:00,74.37725744\n2013-11-23 07:00:00,73.23877045\n2013-11-23 08:00:00,74.57228705\n2013-11-23 09:00:00,73.61937989\n2013-11-23 10:00:00,73.62510552\n2013-11-23 11:00:00,73.89538449\n2013-11-23 12:00:00,73.97705688\n2013-11-23 13:00:00,73.49598319\n2013-11-23 14:00:00,74.480482\n2013-11-23 15:00:00,74.05324671\n2013-11-23 16:00:00,72.99508362\n2013-11-23 17:00:00,74.06252472\n2013-11-23 18:00:00,74.31310832\n2013-11-23 19:00:00,73.86600895\n2013-11-23 20:00:00,74.72618679\n2013-11-23 21:00:00,74.87409105\n2013-11-23 22:00:00,75.16150552\n2013-11-23 23:00:00,75.24524494\n2013-11-24 00:00:00,76.06110472\n2013-11-24 01:00:00,76.04876445\n2013-11-24 02:00:00,75.92643826\n2013-11-24 03:00:00,75.30896496\n2013-11-24 04:00:00,73.85862031\n2013-11-24 05:00:00,74.35243191\n2013-11-24 06:00:00,73.22576335\n2013-11-24 07:00:00,73.89709736\n2013-11-24 08:00:00,73.45107827\n2013-11-24 09:00:00,74.28662864\n2013-11-24 10:00:00,73.11935916\n2013-11-24 11:00:00,73.61847392\n2013-11-24 12:00:00,73.95085216\n2013-11-24 13:00:00,73.81302278\n2013-11-24 14:00:00,74.47090026\n2013-11-24 15:00:00,73.99949512\n2013-11-24 16:00:00,74.01073568\n2013-11-24 17:00:00,74.48269327\n2013-11-24 18:00:00,74.99975789\n2013-11-24 19:00:00,75.51838405\n2013-11-24 20:00:00,74.91884001\n2013-11-24 21:00:00,76.19947972\n2013-11-24 22:00:00,76.37182291\n2013-11-24 23:00:00,75.88886956\n2013-11-25 00:00:00,75.8200126\n2013-11-25 01:00:00,75.09124497\n2013-11-25 02:00:00,76.15627384\n2013-11-25 03:00:00,74.91899343\n2013-11-25 04:00:00,74.96455081\n2013-11-25 05:00:00,73.92706103\n2013-11-25 06:00:00,74.79903613\n2013-11-25 07:00:00,73.3751018\n2013-11-25 08:00:00,73.59611961\n2013-11-25 09:00:00,73.62927662\n2013-11-25 10:00:00,74.00708949\n2013-11-25 11:00:00,73.65766251\n2013-11-25 12:00:00,75.03306974\n2013-11-25 13:00:00,75.04645886\n2013-11-25 14:00:00,75.24681613\n2013-11-25 15:00:00,75.70692895\n2013-11-25 16:00:00,74.67360854\n2013-11-25 17:00:00,74.61358909\n2013-11-25 18:00:00,74.491203\n2013-11-25 19:00:00,76.12426881\n2013-11-25 20:00:00,76.37678862\n2013-11-25 21:00:00,76.92387133\n2013-11-25 22:00:00,75.33838879\n2013-11-25 23:00:00,75.99550579\n2013-11-26 00:00:00,76.69138228\n2013-11-26 01:00:00,75.88567453\n2013-11-26 02:00:00,75.76685516\n2013-11-26 03:00:00,75.37412724\n2013-11-26 04:00:00,76.68765753\n2013-11-26 05:00:00,74.51443263\n2013-11-26 06:00:00,74.81803517\n2013-11-26 07:00:00,75.98462212\n2013-11-26 08:00:00,75.47773677\n2013-11-26 09:00:00,73.83422894\n2013-11-26 10:00:00,74.80800635\n2013-11-26 11:00:00,74.2813275\n2013-11-26 12:00:00,75.90857214\n2013-11-26 13:00:00,75.58094376\n2013-11-26 14:00:00,75.38129562\n2013-11-26 15:00:00,75.16651189\n2013-11-26 16:00:00,75.93238329\n2013-11-26 17:00:00,74.27644123\n2013-11-26 18:00:00,74.14545793\n2013-11-26 19:00:00,74.83272443\n2013-11-26 20:00:00,75.96087554\n2013-11-26 21:00:00,76.77265319\n2013-11-26 22:00:00,77.00068715\n2013-11-26 23:00:00,77.15745947\n2013-11-27 00:00:00,77.15974376\n2013-11-27 01:00:00,76.69033706\n2013-11-27 02:00:00,76.17756923\n2013-11-27 03:00:00,77.24837065\n2013-11-27 04:00:00,77.35430618\n2013-11-27 05:00:00,77.55637201\n2013-11-27 06:00:00,77.11772453\n2013-11-27 07:00:00,76.16169102\n2013-11-27 08:00:00,76.13252582\n2013-11-27 09:00:00,76.22151059999999\n2013-11-27 10:00:00,74.98788383\n2013-11-27 11:00:00,75.70819313\n2013-11-27 12:00:00,75.28208686\n2013-11-27 13:00:00,75.58863441\n2013-11-27 14:00:00,76.04015957\n2013-11-27 15:00:00,76.30194796\n2013-11-27 16:00:00,76.25516001\n2013-11-27 17:00:00,74.8667481\n2013-11-27 18:00:00,75.62370485\n2013-11-27 19:00:00,74.98800103\n2013-11-27 20:00:00,76.56855175\n2013-11-27 21:00:00,76.20402117\n2013-11-27 22:00:00,76.04503464\n2013-11-27 23:00:00,78.00863821\n2013-11-28 00:00:00,77.16791565\n2013-11-28 01:00:00,77.47286351\n2013-11-28 02:00:00,78.34299712\n2013-11-28 03:00:00,77.23397943\n2013-11-28 04:00:00,78.33064076\n2013-11-28 05:00:00,77.74235688\n2013-11-28 06:00:00,76.90841346\n2013-11-28 07:00:00,78.19122395\n2013-11-28 08:00:00,77.11531177\n2013-11-28 09:00:00,76.19078959\n2013-11-28 10:00:00,75.89108336\n2013-11-28 11:00:00,74.91135143\n2013-11-28 12:00:00,76.05428041\n2013-11-28 13:00:00,74.98413324\n2013-11-28 14:00:00,76.71790748\n2013-11-28 15:00:00,76.87780803\n2013-11-28 16:00:00,75.59376618\n2013-11-28 17:00:00,75.42355277\n2013-11-28 18:00:00,76.12701487\n2013-11-28 19:00:00,76.85731503\n2013-11-28 20:00:00,76.36303141\n2013-11-28 21:00:00,75.84007067\n2013-11-28 22:00:00,76.46922703\n2013-11-28 23:00:00,76.80884417\n2013-11-29 00:00:00,79.02591263\n2013-11-29 01:00:00,78.20757005\n2013-11-29 02:00:00,78.47792298\n2013-11-29 03:00:00,79.23633448\n2013-11-29 04:00:00,78.88770756\n2013-11-29 05:00:00,78.8953397\n2013-11-29 06:00:00,78.876609\n2013-11-29 07:00:00,77.56230513\n2013-11-29 08:00:00,76.59404839\n2013-11-29 09:00:00,76.94499489\n2013-11-29 10:00:00,78.49555784\n2013-11-29 11:00:00,76.94027286\n2013-11-29 12:00:00,77.88769599\n2013-11-29 13:00:00,77.17967275\n2013-11-29 14:00:00,77.53951629\n2013-11-29 15:00:00,76.83583058\n2013-11-29 16:00:00,77.38018752\n2013-11-29 17:00:00,78.10468211\n2013-11-29 18:00:00,77.14646568\n2013-11-29 19:00:00,76.97117206\n2013-11-29 20:00:00,77.84318487\n2013-11-29 21:00:00,76.66135240000001\n2013-11-29 22:00:00,78.15703794\n2013-11-29 23:00:00,77.46965922\n2013-11-30 00:00:00,77.88460537\n2013-11-30 01:00:00,77.65864458\n2013-11-30 02:00:00,78.70593097\n2013-11-30 03:00:00,78.50094859\n2013-11-30 04:00:00,77.02001536\n2013-11-30 05:00:00,78.09143757\n2013-11-30 06:00:00,76.72362831\n2013-11-30 07:00:00,76.45580209\n2013-11-30 08:00:00,77.02544955\n2013-11-30 09:00:00,78.11045131\n2013-11-30 10:00:00,76.35997079\n2013-11-30 11:00:00,76.89472925\n2013-11-30 12:00:00,77.04274751\n2013-11-30 13:00:00,77.94149348\n2013-11-30 14:00:00,77.75067472\n2013-11-30 15:00:00,77.55710197\n2013-11-30 16:00:00,76.86340194\n2013-11-30 17:00:00,78.53850778\n2013-11-30 18:00:00,78.37908378\n2013-11-30 19:00:00,78.81008775\n2013-11-30 20:00:00,77.73485863\n2013-11-30 21:00:00,77.83555944\n2013-11-30 22:00:00,78.56664962\n2013-11-30 23:00:00,78.4432628\n2013-12-01 00:00:00,78.58726082\n2013-12-01 01:00:00,77.53521019\n2013-12-01 02:00:00,77.63065448\n2013-12-01 03:00:00,78.12865125\n2013-12-01 04:00:00,77.86603288\n2013-12-01 05:00:00,77.44856207\n2013-12-01 06:00:00,76.98370721\n2013-12-01 07:00:00,75.4790699\n2013-12-01 08:00:00,75.33305301\n2013-12-01 09:00:00,75.89776898\n2013-12-01 10:00:00,76.60147615\n2013-12-01 11:00:00,74.71098020000002\n2013-12-01 12:00:00,75.3552543\n2013-12-01 13:00:00,74.87224431\n2013-12-01 14:00:00,75.9791723\n2013-12-01 15:00:00,75.47730656\n2013-12-01 16:00:00,75.2003445\n2013-12-01 17:00:00,76.27953207\n2013-12-01 18:00:00,76.45168292\n2013-12-01 19:00:00,76.07015052\n2013-12-01 20:00:00,75.73563349999998\n2013-12-01 21:00:00,77.0986277\n2013-12-01 22:00:00,76.35243379\n2013-12-01 23:00:00,76.91635076\n2013-12-02 00:00:00,75.41786731\n2013-12-02 01:00:00,76.54536726\n2013-12-02 02:00:00,75.59756303\n2013-12-02 03:00:00,74.89586951\n2013-12-02 04:00:00,75.43229909\n2013-12-02 05:00:00,74.50186087\n2013-12-02 06:00:00,74.80732462\n2013-12-02 07:00:00,73.08595318\n2013-12-02 08:00:00,73.80861958\n2013-12-02 09:00:00,73.38120847\n2013-12-02 10:00:00,74.42042248\n2013-12-02 11:00:00,75.53513849\n2013-12-02 12:00:00,75.09092686\n2013-12-02 13:00:00,75.56936508\n2013-12-02 14:00:00,74.90652388\n2013-12-02 15:00:00,74.082068\n2013-12-02 16:00:00,75.77601988\n2013-12-02 17:00:00,74.20052806\n2013-12-02 18:00:00,75.23398924\n2013-12-02 19:00:00,74.67382574\n2013-12-02 20:00:00,74.65542741\n2013-12-02 21:00:00,74.67489567\n2013-12-02 22:00:00,74.8350368\n2013-12-02 23:00:00,76.08893067\n2013-12-03 00:00:00,75.15278013\n2013-12-03 01:00:00,75.02923911\n2013-12-03 02:00:00,75.85895688\n2013-12-03 03:00:00,74.36103377\n2013-12-03 04:00:00,75.5156958\n2013-12-03 05:00:00,74.70868339\n2013-12-03 06:00:00,73.83262026\n2013-12-03 07:00:00,73.70124329\n2013-12-03 08:00:00,73.63678504\n2013-12-03 09:00:00,73.41637369\n2013-12-03 10:00:00,73.80197277\n2013-12-03 11:00:00,73.97767514\n2013-12-03 12:00:00,74.83469243\n2013-12-03 13:00:00,74.97139121\n2013-12-03 14:00:00,73.77486044\n2013-12-03 15:00:00,75.13503163\n2013-12-03 16:00:00,73.87999867\n2013-12-03 17:00:00,75.77548486\n2013-12-03 18:00:00,75.01213492\n2013-12-03 19:00:00,75.50478063\n2013-12-03 20:00:00,76.25258396\n2013-12-03 21:00:00,75.71050611\n2013-12-03 22:00:00,77.20657998\n2013-12-03 23:00:00,77.30399661\n2013-12-04 00:00:00,75.91202374\n2013-12-04 01:00:00,76.66853953\n2013-12-04 02:00:00,75.74567822\n2013-12-04 03:00:00,75.19938463\n2013-12-04 04:00:00,76.19384417\n2013-12-04 05:00:00,76.09302338\n2013-12-04 06:00:00,76.04003915\n2013-12-04 07:00:00,75.29326815\n2013-12-04 08:00:00,74.21052551\n2013-12-04 09:00:00,75.1991017\n2013-12-04 10:00:00,74.06782191\n2013-12-04 11:00:00,75.64687089\n2013-12-04 12:00:00,74.70819726\n2013-12-04 13:00:00,75.45305517\n2013-12-04 14:00:00,74.00072839\n2013-12-04 15:00:00,74.0555797\n2013-12-04 16:00:00,74.61075053\n2013-12-04 17:00:00,75.33297088\n2013-12-04 18:00:00,75.94712761\n2013-12-04 19:00:00,75.58518275\n2013-12-04 20:00:00,76.02023976\n2013-12-04 21:00:00,76.59701799\n2013-12-04 22:00:00,76.96921944\n2013-12-04 23:00:00,77.22393149\n2013-12-05 00:00:00,75.97207085\n2013-12-05 01:00:00,77.39107002\n2013-12-05 02:00:00,76.84450656\n2013-12-05 03:00:00,77.41677019\n2013-12-05 04:00:00,75.98938319\n2013-12-05 05:00:00,76.6635247\n2013-12-05 06:00:00,75.44756559999998\n2013-12-05 07:00:00,76.21819272\n2013-12-05 08:00:00,76.32008979\n2013-12-05 09:00:00,74.9409507\n2013-12-05 10:00:00,75.4784256\n2013-12-05 11:00:00,75.17090954\n2013-12-05 12:00:00,74.29941509\n2013-12-05 13:00:00,74.3062439\n2013-12-05 14:00:00,75.90126283\n2013-12-05 15:00:00,75.04716769\n2013-12-05 16:00:00,75.58599677\n2013-12-05 17:00:00,74.87807236\n2013-12-05 18:00:00,75.27313151\n2013-12-05 19:00:00,76.48370315\n2013-12-05 20:00:00,75.50998007\n2013-12-05 21:00:00,76.75086745\n2013-12-05 22:00:00,76.68483447\n2013-12-05 23:00:00,77.38495142\n2013-12-06 00:00:00,75.87360168\n2013-12-06 01:00:00,77.6556306\n2013-12-06 02:00:00,76.42670507\n2013-12-06 03:00:00,75.71056203\n2013-12-06 04:00:00,75.06068153\n2013-12-06 05:00:00,76.10503754\n2013-12-06 06:00:00,75.62420413\n2013-12-06 07:00:00,76.08456044\n2013-12-06 08:00:00,75.29375586\n2013-12-06 09:00:00,74.80440567\n2013-12-06 10:00:00,75.19512835\n2013-12-06 11:00:00,76.00205619\n2013-12-06 12:00:00,74.52998721\n2013-12-06 13:00:00,74.90420227\n2013-12-06 14:00:00,74.16669948\n2013-12-06 15:00:00,73.80445232\n2013-12-06 16:00:00,74.47552074\n2013-12-06 17:00:00,75.30827578\n2013-12-06 18:00:00,75.03218705\n2013-12-06 19:00:00,76.23218309999999\n2013-12-06 20:00:00,75.6839157\n2013-12-06 21:00:00,74.92143663\n2013-12-06 22:00:00,76.87342138\n2013-12-06 23:00:00,76.59855258\n2013-12-07 00:00:00,75.33861432\n2013-12-07 01:00:00,75.45218311\n2013-12-07 02:00:00,76.06290495\n2013-12-07 03:00:00,74.9575668\n2013-12-07 04:00:00,76.00917564\n2013-12-07 05:00:00,75.8543825\n2013-12-07 06:00:00,75.27205469\n2013-12-07 07:00:00,75.31174871\n2013-12-07 08:00:00,74.68013979999998\n2013-12-07 09:00:00,74.82785613\n2013-12-07 10:00:00,74.52306854\n2013-12-07 11:00:00,74.15590675\n2013-12-07 12:00:00,75.10514663\n2013-12-07 13:00:00,74.7545796\n2013-12-07 14:00:00,74.52277912\n2013-12-07 15:00:00,75.82423762\n2013-12-07 16:00:00,74.22414092\n2013-12-07 17:00:00,75.46409745\n2013-12-07 18:00:00,76.33578873\n2013-12-07 19:00:00,76.79710999\n2013-12-07 20:00:00,75.93536531\n2013-12-07 21:00:00,75.56283028\n2013-12-07 22:00:00,77.20560211\n2013-12-07 23:00:00,76.87039405\n2013-12-08 00:00:00,75.44604893\n2013-12-08 01:00:00,76.57429989\n2013-12-08 02:00:00,76.06483199\n2013-12-08 03:00:00,76.00964555\n2013-12-08 04:00:00,74.80675596\n2013-12-08 05:00:00,75.1980522\n2013-12-08 06:00:00,76.07994366\n2013-12-08 07:00:00,74.76370837\n2013-12-08 08:00:00,74.52201927\n2013-12-08 09:00:00,74.64224735\n2013-12-08 10:00:00,75.14042076\n2013-12-08 11:00:00,74.36953798\n2013-12-08 12:00:00,75.37965099\n2013-12-08 13:00:00,74.93759126\n2013-12-08 14:00:00,74.37191177\n2013-12-08 15:00:00,74.73159262\n2013-12-08 16:00:00,75.61318422\n2013-12-08 17:00:00,74.40147509\n2013-12-08 18:00:00,76.13732359999999\n2013-12-08 19:00:00,74.9962055\n2013-12-08 20:00:00,75.54659614\n2013-12-08 21:00:00,75.26882561\n2013-12-08 22:00:00,74.39856404\n2013-12-08 23:00:00,74.28786598\n2013-12-09 00:00:00,75.1690554\n2013-12-09 01:00:00,75.28609538\n2013-12-09 02:00:00,75.1906637\n2013-12-09 03:00:00,73.93566312\n2013-12-09 04:00:00,74.13405397\n2013-12-09 05:00:00,74.18672976\n2013-12-09 06:00:00,74.17864554\n2013-12-09 07:00:00,72.37641122\n2013-12-09 08:00:00,73.10689581\n2013-12-09 09:00:00,73.18092841\n2013-12-09 10:00:00,72.4431114\n2013-12-09 11:00:00,73.61399348\n2013-12-09 12:00:00,73.50101128\n2013-12-09 13:00:00,72.3008609\n2013-12-09 14:00:00,72.34904296\n2013-12-09 15:00:00,72.21993949\n2013-12-09 16:00:00,73.2791445\n2013-12-09 17:00:00,73.29098671\n2013-12-09 18:00:00,73.02860249\n2013-12-09 19:00:00,73.73807814\n2013-12-09 20:00:00,73.96940648\n2013-12-09 21:00:00,73.87529271\n2013-12-09 22:00:00,74.12690095\n2013-12-09 23:00:00,74.54068596\n2013-12-10 00:00:00,74.58730262\n2013-12-10 01:00:00,73.27195908\n2013-12-10 02:00:00,73.90958789\n2013-12-10 03:00:00,74.12705890000002\n2013-12-10 04:00:00,73.64989009\n2013-12-10 05:00:00,73.12019765\n2013-12-10 06:00:00,72.94981371\n2013-12-10 07:00:00,72.63017091\n2013-12-10 08:00:00,72.71613838\n2013-12-10 09:00:00,72.71722481\n2013-12-10 10:00:00,73.73304064\n2013-12-10 11:00:00,72.67712283\n2013-12-10 12:00:00,73.64547544\n2013-12-10 13:00:00,72.30699831\n2013-12-10 14:00:00,72.64327782\n2013-12-10 15:00:00,72.70649962\n2013-12-10 16:00:00,74.00551\n2013-12-10 17:00:00,73.59150747\n2013-12-10 18:00:00,74.36327747\n2013-12-10 19:00:00,73.43398151\n2013-12-10 20:00:00,73.34037954\n2013-12-10 21:00:00,72.49370372\n2013-12-10 22:00:00,73.36328308\n2013-12-10 23:00:00,73.75270216\n2013-12-11 00:00:00,74.07760056\n2013-12-11 01:00:00,74.13267133\n2013-12-11 02:00:00,73.55944399\n2013-12-11 03:00:00,72.82256754\n2013-12-11 04:00:00,72.55823579\n2013-12-11 05:00:00,72.94645319\n2013-12-11 06:00:00,73.85665686\n2013-12-11 07:00:00,72.43060965\n2013-12-11 08:00:00,73.64939159\n2013-12-11 09:00:00,72.18117166\n2013-12-11 10:00:00,72.68621701\n2013-12-11 11:00:00,73.38138872\n2013-12-11 12:00:00,72.59355339\n2013-12-11 13:00:00,73.08965494\n2013-12-11 14:00:00,72.15235240000001\n2013-12-11 15:00:00,74.58666641\n2013-12-11 16:00:00,75.02738785\n2013-12-11 17:00:00,74.62411392\n2013-12-11 18:00:00,75.34149751\n2013-12-11 19:00:00,75.31820223\n2013-12-11 20:00:00,74.99496694\n2013-12-11 21:00:00,75.14356488\n2013-12-11 22:00:00,75.35414616\n2013-12-11 23:00:00,75.60743795\n2013-12-12 00:00:00,75.11999997\n2013-12-12 01:00:00,74.84177433\n2013-12-12 02:00:00,75.34780841\n2013-12-12 03:00:00,74.96166134\n2013-12-12 04:00:00,76.02028875\n2013-12-12 05:00:00,74.99070572\n2013-12-12 06:00:00,74.54696679\n2013-12-12 07:00:00,75.24551555\n2013-12-12 08:00:00,74.58234736\n2013-12-12 09:00:00,73.27790479\n2013-12-12 10:00:00,73.75848662\n2013-12-12 11:00:00,73.72426779\n2013-12-12 12:00:00,73.40027014\n2013-12-12 13:00:00,74.42141665\n2013-12-12 14:00:00,74.09206973\n2013-12-12 15:00:00,76.13283725\n2013-12-12 16:00:00,76.27032048\n2013-12-12 17:00:00,76.22574288\n2013-12-12 18:00:00,76.19386187\n2013-12-12 19:00:00,75.38155998\n2013-12-12 20:00:00,75.54108786\n2013-12-12 21:00:00,75.44093455\n2013-12-12 22:00:00,75.98674438\n2013-12-12 23:00:00,76.37852170000002\n2013-12-13 00:00:00,76.24170509\n2013-12-13 01:00:00,76.07005174\n2013-12-13 02:00:00,76.18773069\n2013-12-13 03:00:00,74.54095745\n2013-12-13 04:00:00,75.9857027\n2013-12-13 05:00:00,75.70301054\n2013-12-13 06:00:00,75.97637738\n2013-12-13 07:00:00,73.99051999\n2013-12-13 08:00:00,74.25959878\n2013-12-13 09:00:00,74.06537538\n2013-12-13 10:00:00,73.497738\n2013-12-13 11:00:00,74.40930673\n2013-12-13 12:00:00,73.53465219\n2013-12-13 13:00:00,74.01325297\n2013-12-13 14:00:00,74.65517361\n2013-12-13 15:00:00,73.80252519999998\n2013-12-13 16:00:00,73.47288405\n2013-12-13 17:00:00,74.39571525\n2013-12-13 18:00:00,75.54122752\n2013-12-13 19:00:00,75.61996717\n2013-12-13 20:00:00,74.29673142\n2013-12-13 21:00:00,75.83949955\n2013-12-13 22:00:00,76.92758894\n2013-12-13 23:00:00,75.89869489\n2013-12-14 00:00:00,75.17568757\n2013-12-14 01:00:00,75.81093193\n2013-12-14 02:00:00,75.69196428\n2013-12-14 03:00:00,74.5128894\n2013-12-14 04:00:00,74.98113099\n2013-12-14 05:00:00,76.17734177\n2013-12-14 06:00:00,74.42758116\n2013-12-14 07:00:00,74.07682949\n2013-12-14 08:00:00,75.69932551\n2013-12-14 09:00:00,74.84695927\n2013-12-14 10:00:00,74.35760136\n2013-12-14 11:00:00,74.39803827\n2013-12-14 12:00:00,75.02743496\n2013-12-14 13:00:00,74.02252097\n2013-12-14 14:00:00,74.56358368\n2013-12-14 15:00:00,74.69963645\n2013-12-14 16:00:00,75.09767236\n2013-12-14 17:00:00,76.44727912\n2013-12-14 18:00:00,76.95586845\n2013-12-14 19:00:00,76.87810004\n2013-12-14 20:00:00,78.17639551\n2013-12-14 21:00:00,78.63037082\n2013-12-14 22:00:00,77.38397999\n2013-12-14 23:00:00,78.19047845\n2013-12-15 00:00:00,78.61378004\n2013-12-15 01:00:00,77.03252890000002\n2013-12-15 02:00:00,78.6107109\n2013-12-15 03:00:00,76.68094652\n2013-12-15 04:00:00,77.05003701\n2013-12-15 05:00:00,76.33040884\n2013-12-15 06:00:00,77.55881425\n2013-12-15 07:00:00,77.29425879\n2013-12-15 08:00:00,75.96598011\n2013-12-15 09:00:00,76.44504229\n2013-12-15 10:00:00,77.37936193\n2013-12-15 11:00:00,76.39378285\n2013-12-15 12:00:00,76.18731941\n2013-12-15 13:00:00,75.55839334\n2013-12-15 14:00:00,77.31227539\n2013-12-15 15:00:00,77.63696989\n2013-12-15 16:00:00,76.61057145\n2013-12-15 17:00:00,78.01573292\n2013-12-15 18:00:00,78.11484883\n2013-12-15 19:00:00,77.7134697\n2013-12-15 20:00:00,78.35903267\n2013-12-15 21:00:00,77.54037213\n2013-12-15 22:00:00,77.50429946\n2013-12-15 23:00:00,78.54151818\n2013-12-16 00:00:00,78.51850373\n2013-12-16 01:00:00,79.21046638\n2013-12-16 02:00:00,79.13826897\n2013-12-16 03:00:00,78.40306640000001\n2013-12-16 04:00:00,78.62008697\n2013-12-16 05:00:00,77.13148416\n2013-12-16 06:00:00,78.02477786\n2013-12-16 07:00:00,77.86136184\n2013-12-16 08:00:00,77.78773632\n2013-12-16 09:00:00,76.85925072\n2013-12-16 10:00:00,76.69516519\n2013-12-16 11:00:00,77.00482738\n2013-12-16 12:00:00,76.44663657\n2013-12-16 13:00:00,76.83346215\n2013-12-16 14:00:00,76.46349867\n2013-12-16 15:00:00,75.94666293\n2013-12-16 16:00:00,75.43675043\n2013-12-16 17:00:00,76.31010809\n2013-12-16 18:00:00,75.95438461\n2013-12-16 19:00:00,76.15312638\n2013-12-16 20:00:00,76.12036689\n2013-12-16 21:00:00,75.94597297\n2013-12-16 22:00:00,76.55225442\n2013-12-16 23:00:00,76.79808015\n2013-12-17 00:00:00,76.48918773\n2013-12-17 01:00:00,76.33896896\n2013-12-17 02:00:00,77.05310437\n2013-12-17 03:00:00,76.54734976\n2013-12-17 04:00:00,75.9568436\n2013-12-17 05:00:00,76.51240415\n2013-12-17 06:00:00,76.18995103\n2013-12-17 07:00:00,76.90449174\n2013-12-17 08:00:00,76.17663538\n2013-12-17 09:00:00,75.63774692\n2013-12-17 10:00:00,74.76111351\n2013-12-17 11:00:00,75.90421071\n2013-12-17 12:00:00,76.50791927\n2013-12-17 13:00:00,75.03569534\n2013-12-17 14:00:00,76.44788554\n2013-12-17 15:00:00,75.69349585\n2013-12-17 16:00:00,74.67369137\n2013-12-17 17:00:00,75.53230267\n2013-12-17 18:00:00,75.69028376\n2013-12-17 19:00:00,75.61612508\n2013-12-17 20:00:00,75.38417556\n2013-12-17 21:00:00,76.53118614\n2013-12-17 22:00:00,76.0893708\n2013-12-17 23:00:00,76.67098365\n2013-12-18 00:00:00,77.51409604\n2013-12-18 01:00:00,77.71518301\n2013-12-18 02:00:00,77.49253948\n2013-12-18 03:00:00,76.1495223\n2013-12-18 04:00:00,77.69271299\n2013-12-18 05:00:00,77.3078518\n2013-12-18 06:00:00,76.58823094\n2013-12-18 07:00:00,77.01356606\n2013-12-18 08:00:00,76.29867262\n2013-12-18 09:00:00,76.6226516\n2013-12-18 10:00:00,76.44608657\n2013-12-18 11:00:00,75.00817082\n2013-12-18 12:00:00,74.40000215\n2013-12-18 13:00:00,75.95158419\n2013-12-18 14:00:00,74.806774\n2013-12-18 15:00:00,76.18399877\n2013-12-18 16:00:00,75.65218318\n2013-12-18 17:00:00,75.92126892\n2013-12-18 18:00:00,74.56981993\n2013-12-18 19:00:00,74.55990289\n2013-12-18 20:00:00,74.70972542\n2013-12-18 21:00:00,75.87615507\n2013-12-18 22:00:00,75.79608847\n2013-12-18 23:00:00,74.99922907\n2013-12-19 00:00:00,75.24370674\n2013-12-19 01:00:00,76.28685920000002\n2013-12-19 02:00:00,76.86505572\n2013-12-19 03:00:00,75.77297344\n2013-12-19 04:00:00,75.97494123\n2013-12-19 05:00:00,74.90139316\n2013-12-19 06:00:00,74.02325849\n2013-12-19 07:00:00,75.06232298\n2013-12-19 08:00:00,74.98321538\n2013-12-19 09:00:00,75.28863521\n2013-12-19 10:00:00,74.94672097\n2013-12-19 11:00:00,73.86675878\n2013-12-19 12:00:00,73.71014444\n2013-12-19 13:00:00,74.90952525\n2013-12-19 14:00:00,74.84580286\n2013-12-19 15:00:00,75.602222\n2013-12-19 16:00:00,74.74889536\n2013-12-19 17:00:00,75.01816634\n2013-12-19 18:00:00,75.72022589\n2013-12-19 19:00:00,76.30473901\n2013-12-19 20:00:00,76.01042931\n2013-12-19 21:00:00,77.21635808\n2013-12-19 22:00:00,76.50729669\n2013-12-19 23:00:00,76.88382451\n2013-12-20 00:00:00,76.77573772\n2013-12-20 01:00:00,76.28321772\n2013-12-20 02:00:00,76.24950337\n2013-12-20 03:00:00,76.06611132\n2013-12-20 04:00:00,75.81287763\n2013-12-20 05:00:00,75.70166172\n2013-12-20 06:00:00,77.39653919999998\n2013-12-20 07:00:00,76.21575455\n2013-12-20 08:00:00,76.42174243\n2013-12-20 09:00:00,76.12429859999997\n2013-12-20 10:00:00,75.95841843\n2013-12-20 11:00:00,74.24349947\n2013-12-20 12:00:00,76.0751302\n2013-12-20 13:00:00,75.84588787\n2013-12-20 14:00:00,74.92850291\n2013-12-20 15:00:00,76.3109073\n2013-12-20 16:00:00,75.13722516\n2013-12-20 17:00:00,75.66403255\n2013-12-20 18:00:00,77.34278041\n2013-12-20 19:00:00,76.93423637\n2013-12-20 20:00:00,76.61857052\n2013-12-20 21:00:00,77.03286984\n2013-12-20 22:00:00,77.55962287\n2013-12-20 23:00:00,79.09188313\n2013-12-21 00:00:00,78.52068112\n2013-12-21 01:00:00,78.98608769\n2013-12-21 02:00:00,79.4198418\n2013-12-21 03:00:00,79.04463822\n2013-12-21 04:00:00,78.08950603\n2013-12-21 05:00:00,77.60666850000001\n2013-12-21 06:00:00,77.94600233\n2013-12-21 07:00:00,77.89349375\n2013-12-21 08:00:00,78.60456446\n2013-12-21 09:00:00,77.06658421\n2013-12-21 10:00:00,78.3217143\n2013-12-21 11:00:00,77.70983715\n2013-12-21 12:00:00,78.84426107\n2013-12-21 13:00:00,77.1455334\n2013-12-21 14:00:00,78.76918765\n2013-12-21 15:00:00,77.91774797\n2013-12-21 16:00:00,78.34500813\n2013-12-21 17:00:00,79.86106375\n2013-12-21 18:00:00,80.52026302\n2013-12-21 19:00:00,79.89687488\n2013-12-21 20:00:00,82.28923988\n2013-12-21 21:00:00,82.98986906\n2013-12-21 22:00:00,83.24788623\n2013-12-21 23:00:00,82.51965884\n2013-12-22 00:00:00,82.73680192\n2013-12-22 01:00:00,83.78099481\n2013-12-22 02:00:00,83.00863385\n2013-12-22 03:00:00,82.8156272\n2013-12-22 04:00:00,81.77474405\n2013-12-22 05:00:00,82.45427776\n2013-12-22 06:00:00,82.09190101\n2013-12-22 07:00:00,80.96998612\n2013-12-22 08:00:00,81.84802474\n2013-12-22 09:00:00,82.11075802\n2013-12-22 10:00:00,80.90724311\n2013-12-22 11:00:00,81.79664979\n2013-12-22 12:00:00,80.13996622\n2013-12-22 13:00:00,80.56010402\n2013-12-22 14:00:00,81.53097122\n2013-12-22 15:00:00,81.83006626\n2013-12-22 16:00:00,83.51163000000003\n2013-12-22 17:00:00,84.39093203\n2013-12-22 18:00:00,85.22768546\n2013-12-22 19:00:00,86.09488844\n2013-12-22 20:00:00,86.20418922\n2013-12-22 21:00:00,86.22321261\n2013-12-22 22:00:00,85.64943737\n2013-12-22 23:00:00,86.07470988\n2013-12-23 00:00:00,85.32616543\n2013-12-23 01:00:00,85.70599036\n2013-12-23 02:00:00,84.08697057\n2013-12-23 03:00:00,85.22227695\n2013-12-23 04:00:00,83.65396808\n2013-12-23 05:00:00,84.32899995\n2013-12-23 06:00:00,83.11824067\n2013-12-23 07:00:00,82.62728762\n2013-12-23 08:00:00,82.6222981\n2013-12-23 09:00:00,82.37343675\n2013-12-23 10:00:00,81.32311924\n2013-12-23 11:00:00,80.15369446\n2013-12-23 12:00:00,80.29698997\n2013-12-23 13:00:00,81.14245049\n2013-12-23 14:00:00,79.87450895\n2013-12-23 15:00:00,78.72789303\n2013-12-23 16:00:00,80.46954892\n2013-12-23 17:00:00,79.03221423\n2013-12-23 18:00:00,79.87953093\n2013-12-23 19:00:00,78.55827641\n2013-12-23 20:00:00,79.53990963\n2013-12-23 21:00:00,78.25863964\n2013-12-23 22:00:00,79.65429515\n2013-12-23 23:00:00,80.24362459999998\n2013-12-24 00:00:00,80.69153985\n2013-12-24 01:00:00,80.39914328\n2013-12-24 02:00:00,81.39129706\n2013-12-24 03:00:00,81.17088406\n2013-12-24 04:00:00,79.61617311\n2013-12-24 05:00:00,81.12807513\n2013-12-24 06:00:00,80.430862\n2013-12-24 07:00:00,80.02182976\n2013-12-24 08:00:00,79.86815899999998\n2013-12-24 09:00:00,80.57302099\n2013-12-24 10:00:00,78.64657966\n2013-12-24 11:00:00,77.52978652\n2013-12-24 12:00:00,77.83306033\n2013-12-24 13:00:00,77.05832672\n2013-12-24 14:00:00,77.19065966\n2013-12-24 15:00:00,78.12445799999998\n2013-12-24 16:00:00,78.72794247\n2013-12-24 17:00:00,78.00471004\n2013-12-24 18:00:00,77.76657966\n2013-12-24 19:00:00,77.67753604\n2013-12-24 20:00:00,78.95358338\n2013-12-24 21:00:00,78.36725003\n2013-12-24 22:00:00,78.6347335\n2013-12-24 23:00:00,79.85459920000002\n2013-12-25 00:00:00,78.54898156\n2013-12-25 01:00:00,79.24333333\n2013-12-25 02:00:00,80.04303671\n2013-12-25 03:00:00,78.27609712\n2013-12-25 04:00:00,79.68598902\n2013-12-25 05:00:00,77.91620784\n2013-12-25 06:00:00,79.18453247\n2013-12-25 07:00:00,77.94191184\n2013-12-25 08:00:00,77.08242193\n2013-12-25 09:00:00,77.14715291\n2013-12-25 10:00:00,77.62220228\n2013-12-25 11:00:00,78.39516049\n2013-12-25 12:00:00,76.84592783\n2013-12-25 13:00:00,78.29719758\n2013-12-25 14:00:00,77.61888521\n2013-12-25 15:00:00,77.00744034\n2013-12-25 16:00:00,77.76062769\n2013-12-25 17:00:00,77.05181008\n2013-12-25 18:00:00,77.0723302\n2013-12-25 19:00:00,78.46417804\n2013-12-25 20:00:00,77.42081363\n2013-12-25 21:00:00,77.808112\n2013-12-25 22:00:00,77.61400932\n2013-12-25 23:00:00,78.09598691\n2013-12-26 00:00:00,77.77116624\n2013-12-26 01:00:00,77.12786457\n2013-12-26 02:00:00,77.0909157\n2013-12-26 03:00:00,78.23972837\n2013-12-26 04:00:00,77.93250468\n2013-12-26 05:00:00,77.65365613\n2013-12-26 06:00:00,76.34552706\n2013-12-26 07:00:00,77.17220436\n2013-12-26 08:00:00,76.85489779\n2013-12-26 09:00:00,77.10917493\n2013-12-26 10:00:00,76.08132018\n2013-12-26 11:00:00,75.97126016\n2013-12-26 12:00:00,75.31930024\n2013-12-26 13:00:00,76.16500538\n2013-12-26 14:00:00,76.33505989\n2013-12-26 15:00:00,74.71455759\n2013-12-26 16:00:00,75.16889103\n2013-12-26 17:00:00,76.88840520000002\n2013-12-26 18:00:00,75.877899\n2013-12-26 19:00:00,76.41369568\n2013-12-26 20:00:00,76.51985988\n2013-12-26 21:00:00,76.32626701\n2013-12-26 22:00:00,76.75690732\n2013-12-26 23:00:00,77.20223204\n2013-12-27 00:00:00,76.54350997\n2013-12-27 01:00:00,77.01021977\n2013-12-27 02:00:00,77.28761998\n2013-12-27 03:00:00,77.13929934\n2013-12-27 04:00:00,75.83918057\n2013-12-27 05:00:00,77.4130038\n2013-12-27 06:00:00,75.63631529\n2013-12-27 07:00:00,76.80939855\n2013-12-27 08:00:00,77.20317007\n2013-12-27 09:00:00,75.9880975\n2013-12-27 10:00:00,75.60517409\n2013-12-27 11:00:00,76.4823878\n2013-12-27 12:00:00,76.08486147\n2013-12-27 13:00:00,75.05631746\n2013-12-27 14:00:00,75.71939344\n2013-12-27 15:00:00,75.49636047\n2013-12-27 16:00:00,75.55847428\n2013-12-27 17:00:00,75.78702171\n2013-12-27 18:00:00,75.42590876\n2013-12-27 19:00:00,76.5985245\n2013-12-27 20:00:00,75.35253788\n2013-12-27 21:00:00,75.52461588\n2013-12-27 22:00:00,75.27324876\n2013-12-27 23:00:00,76.24473974\n2013-12-28 00:00:00,76.39365772\n2013-12-28 01:00:00,76.14188495\n2013-12-28 02:00:00,76.01404616\n2013-12-28 03:00:00,76.24766604\n2013-12-28 04:00:00,74.60550738\n2013-12-28 05:00:00,75.27305911\n2013-12-28 06:00:00,75.76095709\n2013-12-28 07:00:00,75.18391571\n2013-12-28 08:00:00,74.39944531\n2013-12-28 09:00:00,74.93700505\n2013-12-28 10:00:00,74.62630625\n2013-12-28 11:00:00,74.52466577\n2013-12-28 12:00:00,75.20171861\n2013-12-28 13:00:00,75.59031954\n2013-12-28 14:00:00,74.99300208\n2013-12-28 15:00:00,75.12205049\n2013-12-28 16:00:00,74.8451182\n2013-12-28 17:00:00,75.5004353\n2013-12-28 18:00:00,75.78745907\n2013-12-28 19:00:00,76.80171084\n2013-12-28 20:00:00,76.89224059\n2013-12-28 21:00:00,76.57189936\n2013-12-28 22:00:00,76.05772001\n2013-12-28 23:00:00,76.30518585\n2013-12-29 00:00:00,75.67921558\n2013-12-29 01:00:00,75.65697105\n2013-12-29 02:00:00,76.36312409\n2013-12-29 03:00:00,76.36912771\n2013-12-29 04:00:00,75.98000468\n2013-12-29 05:00:00,74.95772326\n2013-12-29 06:00:00,75.4259806\n2013-12-29 07:00:00,75.84298448\n2013-12-29 08:00:00,74.33460196\n2013-12-29 09:00:00,75.25125208\n2013-12-29 10:00:00,75.28419137\n2013-12-29 11:00:00,73.97549299\n2013-12-29 12:00:00,73.77993441\n2013-12-29 13:00:00,74.11605842\n2013-12-29 14:00:00,75.41199782\n2013-12-29 15:00:00,75.88781183\n2013-12-29 16:00:00,75.34116597\n2013-12-29 17:00:00,74.87521094\n2013-12-29 18:00:00,76.97509822\n2013-12-29 19:00:00,76.83889695\n2013-12-29 20:00:00,76.92440774\n2013-12-29 21:00:00,77.32019076\n2013-12-29 22:00:00,77.67837913\n2013-12-29 23:00:00,76.02861347\n2013-12-30 00:00:00,75.57417604\n2013-12-30 01:00:00,75.79405442\n2013-12-30 02:00:00,76.64253253\n2013-12-30 03:00:00,76.35495023\n2013-12-30 04:00:00,76.05391238\n2013-12-30 05:00:00,75.76492651\n2013-12-30 06:00:00,75.53227413\n2013-12-30 07:00:00,75.96286731\n2013-12-30 08:00:00,76.43916795\n2013-12-30 09:00:00,75.79904062\n2013-12-30 10:00:00,75.53723344\n2013-12-30 11:00:00,74.76067835\n2013-12-30 12:00:00,74.8480328\n2013-12-30 13:00:00,76.23999342\n2013-12-30 14:00:00,75.11179225\n2013-12-30 15:00:00,74.94556814\n2013-12-30 16:00:00,75.55307362\n2013-12-30 17:00:00,76.83833799\n2013-12-30 18:00:00,75.59523206\n2013-12-30 19:00:00,76.31503423\n2013-12-30 20:00:00,77.53459374\n2013-12-30 21:00:00,76.0050383\n2013-12-30 22:00:00,77.68454433\n2013-12-30 23:00:00,77.72108111\n2013-12-31 00:00:00,77.51558001\n2013-12-31 01:00:00,78.44437589\n2013-12-31 02:00:00,77.97499028\n2013-12-31 03:00:00,76.46430922\n2013-12-31 04:00:00,77.99078395\n2013-12-31 05:00:00,76.65166801\n2013-12-31 06:00:00,76.38382148\n2013-12-31 07:00:00,77.98764166\n2013-12-31 08:00:00,76.02353562\n2013-12-31 09:00:00,76.85941302\n2013-12-31 10:00:00,77.02694156\n2013-12-31 11:00:00,77.4351667\n2013-12-31 12:00:00,75.742419\n2013-12-31 13:00:00,76.75512501\n2013-12-31 14:00:00,76.1618611\n2013-12-31 15:00:00,76.68101761\n2013-12-31 16:00:00,76.57323145\n2013-12-31 17:00:00,77.42705796\n2013-12-31 18:00:00,78.04219444\n2013-12-31 19:00:00,77.03500259\n2013-12-31 20:00:00,77.59435294\n2013-12-31 21:00:00,76.86767814\n2013-12-31 22:00:00,77.59032761\n2013-12-31 23:00:00,77.68816859\n2014-01-01 00:00:00,77.17536982\n2014-01-01 01:00:00,76.88160145\n2014-01-01 02:00:00,77.64735761\n2014-01-01 03:00:00,76.6094964\n2014-01-01 04:00:00,76.88619653\n2014-01-01 05:00:00,76.25204932\n2014-01-01 06:00:00,75.93757409\n2014-01-01 07:00:00,77.0866129\n2014-01-01 08:00:00,76.89226412\n2014-01-01 09:00:00,77.15228638\n2014-01-01 10:00:00,76.16837159999999\n2014-01-01 11:00:00,76.0309472\n2014-01-01 12:00:00,76.36542467\n2014-01-01 13:00:00,76.21666009999998\n2014-01-01 14:00:00,77.344746\n2014-01-01 15:00:00,77.17413937\n2014-01-01 16:00:00,77.7444573\n2014-01-01 17:00:00,77.80851622\n2014-01-01 18:00:00,76.95110006\n2014-01-01 19:00:00,77.37914862\n2014-01-01 20:00:00,77.64861189\n2014-01-01 21:00:00,77.57337175\n2014-01-01 22:00:00,77.64969323\n2014-01-01 23:00:00,77.28681311\n2014-01-02 00:00:00,77.62789588\n2014-01-02 01:00:00,76.37452465\n2014-01-02 02:00:00,76.89324349\n2014-01-02 03:00:00,75.84159632\n2014-01-02 04:00:00,76.54495496\n2014-01-02 05:00:00,75.54568718\n2014-01-02 06:00:00,75.61285500000002\n2014-01-02 07:00:00,75.77509947\n2014-01-02 08:00:00,76.86025712\n2014-01-02 09:00:00,76.75063266\n2014-01-02 10:00:00,76.65430247\n2014-01-02 11:00:00,76.07822982\n2014-01-02 12:00:00,75.64525857\n2014-01-02 13:00:00,75.6153839\n2014-01-02 14:00:00,75.63346999\n2014-01-02 15:00:00,75.45555433\n2014-01-02 16:00:00,75.36337466\n2014-01-02 17:00:00,76.62929369\n2014-01-02 18:00:00,76.02807317\n2014-01-02 19:00:00,76.95841456\n2014-01-02 20:00:00,77.16409297\n2014-01-02 21:00:00,77.50435808\n2014-01-02 22:00:00,76.45265121\n2014-01-02 23:00:00,76.48343837\n2014-01-03 00:00:00,75.53864608\n2014-01-03 01:00:00,75.63032548\n2014-01-03 02:00:00,75.41759869\n2014-01-03 03:00:00,75.98132744\n2014-01-03 04:00:00,73.93952186\n2014-01-03 05:00:00,74.72379503\n2014-01-03 06:00:00,74.41912965\n2014-01-03 07:00:00,73.57769606\n2014-01-03 08:00:00,73.39289962\n2014-01-03 09:00:00,73.40029958\n2014-01-03 10:00:00,73.15702733\n2014-01-03 11:00:00,73.14839463\n2014-01-03 12:00:00,73.56870109\n2014-01-03 13:00:00,74.24132001\n2014-01-03 14:00:00,73.74719451\n2014-01-03 15:00:00,75.18506859\n2014-01-03 16:00:00,75.62687166\n2014-01-03 17:00:00,75.05191762\n2014-01-03 18:00:00,75.03447509\n2014-01-03 19:00:00,76.67924387\n2014-01-03 20:00:00,75.85058042\n2014-01-03 21:00:00,76.26521877\n2014-01-03 22:00:00,76.40487485\n2014-01-03 23:00:00,76.20869095\n2014-01-04 00:00:00,75.78848542\n2014-01-04 01:00:00,75.78491462\n2014-01-04 02:00:00,74.35316083\n2014-01-04 03:00:00,73.2440553\n2014-01-04 04:00:00,74.52607513\n2014-01-04 05:00:00,72.70071992\n2014-01-04 06:00:00,72.55197957\n2014-01-04 07:00:00,72.76263888\n2014-01-04 08:00:00,74.03023695\n2014-01-04 09:00:00,72.1040175\n2014-01-04 10:00:00,72.46775852\n2014-01-04 11:00:00,72.42871912\n2014-01-04 12:00:00,72.52468151\n2014-01-04 13:00:00,73.11919307\n2014-01-04 14:00:00,72.88771617\n2014-01-04 15:00:00,73.79287601\n2014-01-04 16:00:00,72.8959554\n2014-01-04 17:00:00,73.45337227\n2014-01-04 18:00:00,74.06806234\n2014-01-04 19:00:00,75.77846693\n2014-01-04 20:00:00,75.23072963\n2014-01-04 21:00:00,75.61607375\n2014-01-04 22:00:00,74.98886104\n2014-01-04 23:00:00,75.7975775\n2014-01-05 00:00:00,74.59213146\n2014-01-05 01:00:00,74.133984\n2014-01-05 02:00:00,75.68401665\n2014-01-05 03:00:00,74.63891988\n2014-01-05 04:00:00,74.84522321\n2014-01-05 05:00:00,74.99541401\n2014-01-05 06:00:00,73.95833504\n2014-01-05 07:00:00,73.91074857\n2014-01-05 08:00:00,73.56416169\n2014-01-05 09:00:00,73.94257293\n2014-01-05 10:00:00,73.32290889\n2014-01-05 11:00:00,73.93627585\n2014-01-05 12:00:00,74.19905101\n2014-01-05 13:00:00,72.79990441\n2014-01-05 14:00:00,74.06666139\n2014-01-05 15:00:00,74.44944008\n2014-01-05 16:00:00,74.62982839\n2014-01-05 17:00:00,73.89403209\n2014-01-05 18:00:00,75.44283941\n2014-01-05 19:00:00,74.9532114\n2014-01-05 20:00:00,75.48287312\n2014-01-05 21:00:00,74.85663000000002\n2014-01-05 22:00:00,75.91564308\n2014-01-05 23:00:00,74.31605939\n2014-01-06 00:00:00,75.58963791\n2014-01-06 01:00:00,73.80836459\n2014-01-06 02:00:00,74.64795190000002\n2014-01-06 03:00:00,75.13418494\n2014-01-06 04:00:00,73.66916292\n2014-01-06 05:00:00,73.35199946\n2014-01-06 06:00:00,73.97781018\n2014-01-06 07:00:00,74.35526471\n2014-01-06 08:00:00,73.95431726\n2014-01-06 09:00:00,73.80845391\n2014-01-06 10:00:00,73.97871909\n2014-01-06 11:00:00,72.86942158\n2014-01-06 12:00:00,74.94885797\n2014-01-06 13:00:00,75.39944679999998\n2014-01-06 14:00:00,74.74238142\n2014-01-06 15:00:00,74.66350681\n2014-01-06 16:00:00,74.41156835\n2014-01-06 17:00:00,75.13358423\n2014-01-06 18:00:00,75.11834143\n2014-01-06 19:00:00,75.43622284\n2014-01-06 20:00:00,76.21395639\n2014-01-06 21:00:00,74.73751944\n2014-01-06 22:00:00,74.54551289\n2014-01-06 23:00:00,75.71630602\n2014-01-07 00:00:00,73.71800848\n2014-01-07 01:00:00,73.64882122\n2014-01-07 02:00:00,74.84681716\n2014-01-07 03:00:00,73.4509252\n2014-01-07 04:00:00,74.87858197\n2014-01-07 05:00:00,74.74808979\n2014-01-07 06:00:00,74.36531581\n2014-01-07 07:00:00,74.17844994\n2014-01-07 08:00:00,74.32707278\n2014-01-07 09:00:00,73.04205499\n2014-01-07 10:00:00,73.88036889\n2014-01-07 11:00:00,74.06747359999999\n2014-01-07 12:00:00,73.85181753\n2014-01-07 13:00:00,73.52105745\n2014-01-07 14:00:00,75.89900009\n2014-01-07 15:00:00,75.83602568\n2014-01-07 16:00:00,75.7488075\n2014-01-07 17:00:00,77.03472136\n2014-01-07 18:00:00,75.75358374\n2014-01-07 19:00:00,76.37330245\n2014-01-07 20:00:00,76.41021209\n2014-01-07 21:00:00,76.86214074\n2014-01-07 22:00:00,76.37969889\n2014-01-07 23:00:00,75.8606675\n2014-01-08 00:00:00,75.98763517\n2014-01-08 01:00:00,75.23598479\n2014-01-08 02:00:00,75.71067527\n2014-01-08 03:00:00,75.16753331\n2014-01-08 04:00:00,74.70772724\n2014-01-08 05:00:00,76.07797055\n2014-01-08 06:00:00,74.98527003\n2014-01-08 07:00:00,74.9606503\n2014-01-08 08:00:00,75.33628459999998\n2014-01-08 09:00:00,73.55344265\n2014-01-08 10:00:00,73.99107759\n2014-01-08 11:00:00,74.84672677\n2014-01-08 12:00:00,75.07497205\n2014-01-08 13:00:00,74.36771562\n2014-01-08 14:00:00,75.74259037\n2014-01-08 15:00:00,74.87882442\n2014-01-08 16:00:00,76.24095087\n2014-01-08 17:00:00,75.95860682\n2014-01-08 18:00:00,76.37186909\n2014-01-08 19:00:00,75.9443031\n2014-01-08 20:00:00,75.11146533\n2014-01-08 21:00:00,75.15274793\n2014-01-08 22:00:00,75.06549983\n2014-01-08 23:00:00,74.69714713\n2014-01-09 00:00:00,76.19664042\n2014-01-09 01:00:00,74.10948331\n2014-01-09 02:00:00,74.63482711\n2014-01-09 03:00:00,73.51138733\n2014-01-09 04:00:00,73.12606794\n2014-01-09 05:00:00,74.01271456\n2014-01-09 06:00:00,73.86542453\n2014-01-09 07:00:00,73.89712719\n2014-01-09 08:00:00,74.03537465\n2014-01-09 09:00:00,73.72201999\n2014-01-09 10:00:00,72.66948077\n2014-01-09 11:00:00,72.50391252\n2014-01-09 12:00:00,73.95811461\n2014-01-09 13:00:00,74.01521745\n2014-01-09 14:00:00,74.01596603\n2014-01-09 15:00:00,75.4479466\n2014-01-09 16:00:00,76.13073887\n2014-01-09 17:00:00,75.25463596\n2014-01-09 18:00:00,75.93286118\n2014-01-09 19:00:00,75.59193841\n2014-01-09 20:00:00,76.30709504\n2014-01-09 21:00:00,77.18425747\n2014-01-09 22:00:00,75.64246944\n2014-01-09 23:00:00,76.37537373\n2014-01-10 00:00:00,74.68720578\n2014-01-10 01:00:00,75.18990319\n2014-01-10 02:00:00,75.849666\n2014-01-10 03:00:00,75.14636897\n2014-01-10 04:00:00,73.90081676\n2014-01-10 05:00:00,74.73933733\n2014-01-10 06:00:00,73.74171083\n2014-01-10 07:00:00,74.46143239\n2014-01-10 08:00:00,73.4840964\n2014-01-10 09:00:00,73.03863545\n2014-01-10 10:00:00,74.07519737\n2014-01-10 11:00:00,72.93006063\n2014-01-10 12:00:00,73.18888994\n2014-01-10 13:00:00,73.95558633\n2014-01-10 14:00:00,75.22775409\n2014-01-10 15:00:00,75.05332699\n2014-01-10 16:00:00,75.36510048\n2014-01-10 17:00:00,76.11231412\n2014-01-10 18:00:00,75.58706498\n2014-01-10 19:00:00,76.06972961\n2014-01-10 20:00:00,75.32744105\n2014-01-10 21:00:00,76.06533695\n2014-01-10 22:00:00,75.66969997\n2014-01-10 23:00:00,76.2727697\n2014-01-11 00:00:00,75.50606319\n2014-01-11 01:00:00,75.37971925\n2014-01-11 02:00:00,74.86435121\n2014-01-11 03:00:00,75.92346681\n2014-01-11 04:00:00,75.81348126\n2014-01-11 05:00:00,75.53701836\n2014-01-11 06:00:00,74.23671001\n2014-01-11 07:00:00,75.16424971\n2014-01-11 08:00:00,74.30239478\n2014-01-11 09:00:00,74.59790374\n2014-01-11 10:00:00,73.58871356\n2014-01-11 11:00:00,73.01315859\n2014-01-11 12:00:00,72.58458265\n2014-01-11 13:00:00,73.95143473\n2014-01-11 14:00:00,73.97461465\n2014-01-11 15:00:00,74.56884896\n2014-01-11 16:00:00,75.03613111\n2014-01-11 17:00:00,75.56055848\n2014-01-11 18:00:00,75.62240148\n2014-01-11 19:00:00,77.67158003\n2014-01-11 20:00:00,77.56623639\n2014-01-11 21:00:00,77.61657097\n2014-01-11 22:00:00,77.69091215\n2014-01-11 23:00:00,77.65642064\n2014-01-12 00:00:00,76.58082694\n2014-01-12 01:00:00,76.82821008\n2014-01-12 02:00:00,77.44683206\n2014-01-12 03:00:00,77.63174648\n2014-01-12 04:00:00,76.76049719\n2014-01-12 05:00:00,76.10329035\n2014-01-12 06:00:00,75.93474711\n2014-01-12 07:00:00,76.39983542\n2014-01-12 08:00:00,75.07645543\n2014-01-12 09:00:00,76.25156678\n2014-01-12 10:00:00,75.59060727\n2014-01-12 11:00:00,75.83963106\n2014-01-12 12:00:00,75.22056579999997\n2014-01-12 13:00:00,74.85866283\n2014-01-12 14:00:00,75.53354519\n2014-01-12 15:00:00,75.71749619\n2014-01-12 16:00:00,77.69659197\n2014-01-12 17:00:00,78.08214012\n2014-01-12 18:00:00,78.95522712\n2014-01-12 19:00:00,79.64623758\n2014-01-12 20:00:00,81.37618811\n2014-01-12 21:00:00,80.96947535\n2014-01-12 22:00:00,80.30864114\n2014-01-12 23:00:00,80.18657579\n2014-01-13 00:00:00,78.47491514\n2014-01-13 01:00:00,78.96162765\n2014-01-13 02:00:00,79.1300713\n2014-01-13 03:00:00,78.39635208\n2014-01-13 04:00:00,79.85480600000002\n2014-01-13 05:00:00,77.98583629\n2014-01-13 06:00:00,78.35432954\n2014-01-13 07:00:00,78.66812563\n2014-01-13 08:00:00,79.03360146\n2014-01-13 09:00:00,77.31328955\n2014-01-13 10:00:00,77.73451371\n2014-01-13 11:00:00,77.69436304\n2014-01-13 12:00:00,77.79754628\n2014-01-13 13:00:00,77.22909454\n2014-01-13 14:00:00,78.35433755\n2014-01-13 15:00:00,78.03170789\n2014-01-13 16:00:00,76.63660126\n2014-01-13 17:00:00,76.57220626\n2014-01-13 18:00:00,77.76546817\n2014-01-13 19:00:00,77.38246298\n2014-01-13 20:00:00,76.69839827\n2014-01-13 21:00:00,76.3966038\n2014-01-13 22:00:00,78.2430965\n2014-01-13 23:00:00,77.18014447\n2014-01-14 00:00:00,76.98731733\n2014-01-14 01:00:00,76.802564\n2014-01-14 02:00:00,78.04845667\n2014-01-14 03:00:00,78.30808931\n2014-01-14 04:00:00,78.56024461\n2014-01-14 05:00:00,78.00986597\n2014-01-14 06:00:00,77.74735738\n2014-01-14 07:00:00,76.56851354\n2014-01-14 08:00:00,76.57631974\n2014-01-14 09:00:00,76.29506325\n2014-01-14 10:00:00,76.91856774\n2014-01-14 11:00:00,77.35300179999999\n2014-01-14 12:00:00,76.69395845\n2014-01-14 13:00:00,76.79314078\n2014-01-14 14:00:00,76.78184988\n2014-01-14 15:00:00,76.58378687\n2014-01-14 16:00:00,75.29365403\n2014-01-14 17:00:00,77.08526779\n2014-01-14 18:00:00,77.16331386\n2014-01-14 19:00:00,76.08578513\n2014-01-14 20:00:00,76.26928873\n2014-01-14 21:00:00,76.76325951\n2014-01-14 22:00:00,75.47553688\n2014-01-14 23:00:00,75.0534243\n2014-01-15 00:00:00,75.69341909\n2014-01-15 01:00:00,74.84655904\n2014-01-15 02:00:00,74.60828148\n2014-01-15 03:00:00,75.23334924\n2014-01-15 04:00:00,74.76757914\n2014-01-15 05:00:00,74.32699919\n2014-01-15 06:00:00,72.97529237\n2014-01-15 07:00:00,73.30416843\n2014-01-15 08:00:00,73.38232286\n2014-01-15 09:00:00,74.58791578\n2014-01-15 10:00:00,72.9067279\n2014-01-15 11:00:00,74.15335692\n2014-01-15 12:00:00,74.15977548\n2014-01-15 13:00:00,75.48000267\n2014-01-15 14:00:00,74.94602944\n2014-01-15 15:00:00,74.36597865\n2014-01-15 16:00:00,75.40107507\n2014-01-15 17:00:00,76.43324294\n2014-01-15 18:00:00,76.76879953\n2014-01-15 19:00:00,75.42099851\n2014-01-15 20:00:00,75.04376408\n2014-01-15 21:00:00,75.14537633\n2014-01-15 22:00:00,75.26255156\n2014-01-15 23:00:00,75.35976422\n2014-01-16 00:00:00,75.45234139\n2014-01-16 01:00:00,73.94180609\n2014-01-16 02:00:00,75.00647379\n2014-01-16 03:00:00,74.33106778\n2014-01-16 04:00:00,74.87396446\n2014-01-16 05:00:00,73.3379579\n2014-01-16 06:00:00,72.80256039\n2014-01-16 07:00:00,73.66597073\n2014-01-16 08:00:00,73.87172516\n2014-01-16 09:00:00,73.27324959\n2014-01-16 10:00:00,72.72014324\n2014-01-16 11:00:00,74.17992104\n2014-01-16 12:00:00,74.15880306\n2014-01-16 13:00:00,75.59329179999997\n2014-01-16 14:00:00,75.41968933\n2014-01-16 15:00:00,74.53134496\n2014-01-16 16:00:00,74.44982256\n2014-01-16 17:00:00,75.434016\n2014-01-16 18:00:00,75.62950104\n2014-01-16 19:00:00,75.34933235\n2014-01-16 20:00:00,75.201389\n2014-01-16 21:00:00,75.40868152\n2014-01-16 22:00:00,75.11984946\n2014-01-16 23:00:00,74.38931293\n2014-01-17 00:00:00,74.69809723\n2014-01-17 01:00:00,75.18846342\n2014-01-17 02:00:00,74.45343886\n2014-01-17 03:00:00,74.67691315\n2014-01-17 04:00:00,73.41217429\n2014-01-17 05:00:00,72.83454005\n2014-01-17 06:00:00,73.5939262\n2014-01-17 07:00:00,72.76406621\n2014-01-17 08:00:00,72.68778157\n2014-01-17 09:00:00,73.37875182\n2014-01-17 10:00:00,72.06183623\n2014-01-17 11:00:00,72.86400869\n2014-01-17 12:00:00,74.31198445\n2014-01-17 13:00:00,73.92421104\n2014-01-17 14:00:00,73.6834725\n2014-01-17 15:00:00,73.71034271\n2014-01-17 16:00:00,73.515123\n2014-01-17 17:00:00,74.65384045\n2014-01-17 18:00:00,74.59773769\n2014-01-17 19:00:00,74.96277198\n2014-01-17 20:00:00,74.62437982\n2014-01-17 21:00:00,73.58807814\n2014-01-17 22:00:00,74.27463197\n2014-01-17 23:00:00,73.46593712\n2014-01-18 00:00:00,73.37697331\n2014-01-18 01:00:00,74.28679774\n2014-01-18 02:00:00,74.60507656\n2014-01-18 03:00:00,73.56215036\n2014-01-18 04:00:00,74.11232577\n2014-01-18 05:00:00,73.97053959\n2014-01-18 06:00:00,72.77785049\n2014-01-18 07:00:00,72.57867332\n2014-01-18 08:00:00,73.50341351\n2014-01-18 09:00:00,73.17997554\n2014-01-18 10:00:00,73.07969608\n2014-01-18 11:00:00,72.86778282\n2014-01-18 12:00:00,72.97978227\n2014-01-18 13:00:00,72.06864306\n2014-01-18 14:00:00,73.46915696\n2014-01-18 15:00:00,72.73501198\n2014-01-18 16:00:00,73.06122541\n2014-01-18 17:00:00,73.9831845\n2014-01-18 18:00:00,74.44162889\n2014-01-18 19:00:00,74.04541228\n2014-01-18 20:00:00,74.99423532\n2014-01-18 21:00:00,76.25032982\n2014-01-18 22:00:00,75.29434003\n2014-01-18 23:00:00,74.45046834\n2014-01-19 00:00:00,75.03906858\n2014-01-19 01:00:00,75.11973678\n2014-01-19 02:00:00,73.60403299\n2014-01-19 03:00:00,73.44321638\n2014-01-19 04:00:00,73.43418914\n2014-01-19 05:00:00,73.23859587\n2014-01-19 06:00:00,73.7150373\n2014-01-19 07:00:00,73.89335646\n2014-01-19 08:00:00,73.87424506\n2014-01-19 09:00:00,72.96073809\n2014-01-19 10:00:00,72.61113449999998\n2014-01-19 11:00:00,71.38831163\n2014-01-19 12:00:00,72.09667227\n2014-01-19 13:00:00,72.43175322\n2014-01-19 14:00:00,73.43453663\n2014-01-19 15:00:00,71.85172628\n2014-01-19 16:00:00,73.33181218\n2014-01-19 17:00:00,73.98179005\n2014-01-19 18:00:00,75.60339242\n2014-01-19 19:00:00,74.84669634\n2014-01-19 20:00:00,75.66432669\n2014-01-19 21:00:00,75.41398766\n2014-01-19 22:00:00,75.62691835\n2014-01-19 23:00:00,76.12839652\n2014-01-20 00:00:00,75.24374402\n2014-01-20 01:00:00,74.25000295\n2014-01-20 02:00:00,74.76520353\n2014-01-20 03:00:00,74.88412726\n2014-01-20 04:00:00,74.70121296\n2014-01-20 05:00:00,73.93681762\n2014-01-20 06:00:00,74.25651103\n2014-01-20 07:00:00,73.57337828\n2014-01-20 08:00:00,72.94924405\n2014-01-20 09:00:00,73.73581362\n2014-01-20 10:00:00,73.57616849\n2014-01-20 11:00:00,73.09497078\n2014-01-20 12:00:00,74.97348441\n2014-01-20 13:00:00,74.48410538\n2014-01-20 14:00:00,74.37005879\n2014-01-20 15:00:00,74.89437525\n2014-01-20 16:00:00,75.36858942\n2014-01-20 17:00:00,75.51543606\n2014-01-20 18:00:00,75.93149966\n2014-01-20 19:00:00,76.80408083\n2014-01-20 20:00:00,76.08022555\n2014-01-20 21:00:00,74.81338988\n2014-01-20 22:00:00,75.92940133\n2014-01-20 23:00:00,75.50636120000001\n2014-01-21 00:00:00,74.14574816\n2014-01-21 01:00:00,74.86999088\n2014-01-21 02:00:00,75.32625215\n2014-01-21 03:00:00,73.74854939\n2014-01-21 04:00:00,74.07036021\n2014-01-21 05:00:00,74.04524108\n2014-01-21 06:00:00,74.05595233\n2014-01-21 07:00:00,74.2393244\n2014-01-21 08:00:00,73.90532239\n2014-01-21 09:00:00,73.53187021\n2014-01-21 10:00:00,73.96226531\n2014-01-21 11:00:00,73.20525326\n2014-01-21 12:00:00,74.60467618\n2014-01-21 13:00:00,74.24149076\n2014-01-21 14:00:00,75.28123022\n2014-01-21 15:00:00,74.40222479\n2014-01-21 16:00:00,74.19210633\n2014-01-21 17:00:00,75.87886303\n2014-01-21 18:00:00,75.23863029\n2014-01-21 19:00:00,74.96873237\n2014-01-21 20:00:00,76.10793148\n2014-01-21 21:00:00,75.36131634\n2014-01-21 22:00:00,75.90263465\n2014-01-21 23:00:00,75.50472037\n2014-01-22 00:00:00,74.28022956\n2014-01-22 01:00:00,72.97203667\n2014-01-22 02:00:00,72.67511800000003\n2014-01-22 03:00:00,73.47639463\n2014-01-22 04:00:00,73.39614473\n2014-01-22 05:00:00,72.10091024\n2014-01-22 06:00:00,71.8777649\n2014-01-22 07:00:00,72.55737568\n2014-01-22 08:00:00,72.98505223\n2014-01-22 09:00:00,73.73262672\n2014-01-22 10:00:00,72.69930722\n2014-01-22 11:00:00,73.01882828\n2014-01-22 12:00:00,72.80921712\n2014-01-22 13:00:00,73.65716599\n2014-01-22 14:00:00,74.68008894\n2014-01-22 15:00:00,74.65383035\n2014-01-22 16:00:00,73.90375633\n2014-01-22 17:00:00,74.95962081\n2014-01-22 18:00:00,74.72151271\n2014-01-22 19:00:00,76.1127814\n2014-01-22 20:00:00,76.27976034\n2014-01-22 21:00:00,75.43044158\n2014-01-22 22:00:00,74.81221712\n2014-01-22 23:00:00,75.29112173\n2014-01-23 00:00:00,74.11805047\n2014-01-23 01:00:00,73.08506057\n2014-01-23 02:00:00,73.71635914\n2014-01-23 03:00:00,72.75477351\n2014-01-23 04:00:00,73.06979399999999\n2014-01-23 05:00:00,73.43277483\n2014-01-23 06:00:00,72.12848145\n2014-01-23 07:00:00,72.30633866\n2014-01-23 08:00:00,72.55350882\n2014-01-23 09:00:00,72.43365278\n2014-01-23 10:00:00,72.16028829999998\n2014-01-23 11:00:00,71.87997676\n2014-01-23 12:00:00,72.30469043\n2014-01-23 13:00:00,72.90140272\n2014-01-23 14:00:00,73.52178365\n2014-01-23 15:00:00,74.33549357\n2014-01-23 16:00:00,75.39468245\n2014-01-23 17:00:00,74.07597525\n2014-01-23 18:00:00,75.35896953\n2014-01-23 19:00:00,76.20885954\n2014-01-23 20:00:00,75.47638239\n2014-01-23 21:00:00,74.560063\n2014-01-23 22:00:00,74.52753611\n2014-01-23 23:00:00,73.71689559999999\n2014-01-24 00:00:00,73.90866358\n2014-01-24 01:00:00,74.09748437\n2014-01-24 02:00:00,73.87374575\n2014-01-24 03:00:00,73.74883976\n2014-01-24 04:00:00,72.9320447\n2014-01-24 05:00:00,73.49330934\n2014-01-24 06:00:00,73.66155176\n2014-01-24 07:00:00,73.62855627\n2014-01-24 08:00:00,73.16522286\n2014-01-24 09:00:00,72.7479508\n2014-01-24 10:00:00,73.56592026\n2014-01-24 11:00:00,71.75263157\n2014-01-24 12:00:00,73.18039611\n2014-01-24 13:00:00,73.92384\n2014-01-24 14:00:00,73.80439905\n2014-01-24 15:00:00,73.73073979\n2014-01-24 16:00:00,73.80911621\n2014-01-24 17:00:00,73.53212237\n2014-01-24 18:00:00,75.18577049\n2014-01-24 19:00:00,75.01261659\n2014-01-24 20:00:00,75.04608932\n2014-01-24 21:00:00,73.33607329\n2014-01-24 22:00:00,73.1043253\n2014-01-24 23:00:00,74.10360046\n2014-01-25 00:00:00,73.78519774\n2014-01-25 01:00:00,71.71663594\n2014-01-25 02:00:00,72.13397159\n2014-01-25 03:00:00,71.51253422\n2014-01-25 04:00:00,72.46607477\n2014-01-25 05:00:00,70.94402108\n2014-01-25 06:00:00,72.61890668\n2014-01-25 07:00:00,70.73076574\n2014-01-25 08:00:00,72.48740311\n2014-01-25 09:00:00,70.83079397\n2014-01-25 10:00:00,71.04843529\n2014-01-25 11:00:00,70.71591042\n2014-01-25 12:00:00,70.79152507\n2014-01-25 13:00:00,70.65705161\n2014-01-25 14:00:00,71.61997893\n2014-01-25 15:00:00,71.01293809\n2014-01-25 16:00:00,71.73672317\n2014-01-25 17:00:00,72.73172553\n2014-01-25 18:00:00,71.46886416\n2014-01-25 19:00:00,71.86085423\n2014-01-25 20:00:00,73.11208905\n2014-01-25 21:00:00,72.20025328\n2014-01-25 22:00:00,72.23507842\n2014-01-25 23:00:00,72.0287567\n2014-01-26 00:00:00,71.82552414\n2014-01-26 01:00:00,72.33922968\n2014-01-26 02:00:00,71.85635252\n2014-01-26 03:00:00,70.5453744\n2014-01-26 04:00:00,70.37989579\n2014-01-26 05:00:00,70.37604173\n2014-01-26 06:00:00,70.77914323\n2014-01-26 07:00:00,70.19317971\n2014-01-26 08:00:00,70.24674398\n2014-01-26 09:00:00,71.35010374\n2014-01-26 10:00:00,69.99332028\n2014-01-26 11:00:00,71.14020035\n2014-01-26 12:00:00,69.67929351\n2014-01-26 13:00:00,69.35287097\n2014-01-26 14:00:00,70.07391138\n2014-01-26 15:00:00,70.16723295\n2014-01-26 16:00:00,70.29923518\n2014-01-26 17:00:00,70.53565511\n2014-01-26 18:00:00,71.79430755\n2014-01-26 19:00:00,71.82889986\n2014-01-26 20:00:00,72.54095975\n2014-01-26 21:00:00,71.58480523\n2014-01-26 22:00:00,73.13032124\n2014-01-26 23:00:00,72.19137711\n2014-01-27 00:00:00,72.69299224\n2014-01-27 01:00:00,72.52594748\n2014-01-27 02:00:00,72.1202739\n2014-01-27 03:00:00,71.63100933\n2014-01-27 04:00:00,72.32810907\n2014-01-27 05:00:00,71.35093709\n2014-01-27 06:00:00,72.35543488\n2014-01-27 07:00:00,72.9372165\n2014-01-27 08:00:00,71.70966262\n2014-01-27 09:00:00,72.032484\n2014-01-27 10:00:00,72.49053701\n2014-01-27 11:00:00,71.89054985\n2014-01-27 12:00:00,71.26701803\n2014-01-27 13:00:00,74.46663598\n2014-01-27 14:00:00,72.22220945\n2014-01-27 15:00:00,73.72378953\n2014-01-27 16:00:00,73.22172217\n2014-01-27 17:00:00,73.98717586\n2014-01-27 18:00:00,73.03814208\n2014-01-27 19:00:00,73.32673418\n2014-01-27 20:00:00,74.66952758\n2014-01-27 21:00:00,74.79814747\n2014-01-27 22:00:00,73.00862053\n2014-01-27 23:00:00,72.03939489\n2014-01-28 00:00:00,72.84926503\n2014-01-28 01:00:00,72.21653075\n2014-01-28 02:00:00,72.82207234\n2014-01-28 03:00:00,72.13937972\n2014-01-28 04:00:00,71.41855654\n2014-01-28 05:00:00,72.13106037\n2014-01-28 06:00:00,70.30742259\n2014-01-28 07:00:00,71.29753092\n2014-01-28 08:00:00,70.73465105\n2014-01-28 09:00:00,70.97773483\n2014-01-28 10:00:00,71.29569485\n2014-01-28 11:00:00,70.86865163\n2014-01-28 12:00:00,71.13147563\n2014-01-28 13:00:00,71.26149539\n2014-01-28 14:00:00,71.94856019\n2014-01-28 15:00:00,73.39954311\n2014-01-28 16:00:00,72.71250801\n2014-01-28 17:00:00,72.77672232\n2014-01-28 18:00:00,72.35599271\n2014-01-28 19:00:00,73.15618385\n2014-01-28 20:00:00,73.63572063\n2014-01-28 21:00:00,72.21822025\n2014-01-28 22:00:00,73.09245779\n2014-01-28 23:00:00,72.11831496\n2014-01-29 00:00:00,71.42071144\n2014-01-29 01:00:00,70.56138073\n2014-01-29 02:00:00,71.67378573\n2014-01-29 03:00:00,70.69482748\n2014-01-29 04:00:00,71.05763613\n2014-01-29 05:00:00,69.64124933\n2014-01-29 06:00:00,69.98065226\n2014-01-29 07:00:00,69.64774646\n2014-01-29 08:00:00,68.90916513\n2014-01-29 09:00:00,68.87238795\n2014-01-29 10:00:00,69.78818855\n2014-01-29 11:00:00,71.12277947\n2014-01-29 12:00:00,69.26547487\n2014-01-29 13:00:00,69.4026087\n2014-01-29 14:00:00,70.83920046\n2014-01-29 15:00:00,69.3426551\n2014-01-29 16:00:00,70.48650218\n2014-01-29 17:00:00,71.05859214\n2014-01-29 18:00:00,72.61395853\n2014-01-29 19:00:00,72.86434604\n2014-01-29 20:00:00,72.37767629\n2014-01-29 21:00:00,71.96930019\n2014-01-29 22:00:00,70.34552908\n2014-01-29 23:00:00,70.14337141\n2014-01-30 00:00:00,69.65669593\n2014-01-30 01:00:00,70.78838358\n2014-01-30 02:00:00,69.51059999\n2014-01-30 03:00:00,70.31048879\n2014-01-30 04:00:00,68.33312277\n2014-01-30 05:00:00,69.11285507\n2014-01-30 06:00:00,68.36206502\n2014-01-30 07:00:00,70.00255638\n2014-01-30 08:00:00,69.84002555\n2014-01-30 09:00:00,70.8745921\n2014-01-30 10:00:00,69.71342166\n2014-01-30 11:00:00,70.57222326\n2014-01-30 12:00:00,71.52531104\n2014-01-30 13:00:00,72.153684\n2014-01-30 14:00:00,71.81595951\n2014-01-30 15:00:00,72.36544447\n2014-01-30 16:00:00,72.4569589\n2014-01-30 17:00:00,74.33983452\n2014-01-30 18:00:00,72.53925557\n2014-01-30 19:00:00,73.62854553\n2014-01-30 20:00:00,74.16754767\n2014-01-30 21:00:00,72.13192721\n2014-01-30 22:00:00,72.59170057\n2014-01-30 23:00:00,73.23535767\n2014-01-31 00:00:00,71.19719727\n2014-01-31 01:00:00,72.61891747\n2014-01-31 02:00:00,70.88976393\n2014-01-31 03:00:00,71.45727319\n2014-01-31 04:00:00,70.03927892\n2014-01-31 05:00:00,71.28071130000002\n2014-01-31 06:00:00,70.26626228\n2014-01-31 07:00:00,70.99283914\n2014-01-31 08:00:00,72.32981714\n2014-01-31 09:00:00,73.11036920000002\n2014-01-31 10:00:00,71.65932377\n2014-01-31 11:00:00,71.69114293\n2014-01-31 12:00:00,73.06636241\n2014-01-31 13:00:00,72.80727072\n2014-01-31 14:00:00,73.03538763\n2014-01-31 15:00:00,74.79646198\n2014-01-31 16:00:00,74.73596869\n2014-01-31 17:00:00,74.52413086\n2014-01-31 18:00:00,75.13725636\n2014-01-31 19:00:00,75.51339861\n2014-01-31 20:00:00,74.97912619\n2014-01-31 21:00:00,75.16085571\n2014-01-31 22:00:00,73.94071425\n2014-01-31 23:00:00,74.6188033\n2014-02-01 00:00:00,74.59156686\n2014-02-01 01:00:00,73.28286835\n2014-02-01 02:00:00,74.00350054\n2014-02-01 03:00:00,72.69543879\n2014-02-01 04:00:00,71.81722439\n2014-02-01 05:00:00,71.22178031\n2014-02-01 06:00:00,70.71015231\n2014-02-01 07:00:00,71.85774564\n2014-02-01 08:00:00,72.71240816\n2014-02-01 09:00:00,70.8336897\n2014-02-01 10:00:00,70.79616568\n2014-02-01 11:00:00,71.21849014\n2014-02-01 12:00:00,70.71605474\n2014-02-01 13:00:00,70.86097936\n2014-02-01 14:00:00,70.84299733\n2014-02-01 15:00:00,71.92974532\n2014-02-01 16:00:00,71.79294961\n2014-02-01 17:00:00,71.10245254\n2014-02-01 18:00:00,71.47578673\n2014-02-01 19:00:00,73.06019458\n2014-02-01 20:00:00,71.57960823\n2014-02-01 21:00:00,72.00120605\n2014-02-01 22:00:00,71.53750218\n2014-02-01 23:00:00,71.07065184\n2014-02-02 00:00:00,70.44906285\n2014-02-02 01:00:00,71.26135473\n2014-02-02 02:00:00,71.33996454\n2014-02-02 03:00:00,71.30097322\n2014-02-02 04:00:00,69.9892031\n2014-02-02 05:00:00,70.48431814\n2014-02-02 06:00:00,70.00301726\n2014-02-02 07:00:00,70.80399895\n2014-02-02 08:00:00,69.16903154\n2014-02-02 09:00:00,70.23674187\n2014-02-02 10:00:00,70.13354079\n2014-02-02 11:00:00,70.15141027\n2014-02-02 12:00:00,69.00452108\n2014-02-02 13:00:00,69.71760276\n2014-02-02 14:00:00,70.12305221\n2014-02-02 15:00:00,69.76208503\n2014-02-02 16:00:00,69.90676189\n2014-02-02 17:00:00,70.43625119\n2014-02-02 18:00:00,71.23295217\n2014-02-02 19:00:00,71.99986698\n2014-02-02 20:00:00,72.88904636\n2014-02-02 21:00:00,72.65424564\n2014-02-02 22:00:00,71.64446397\n2014-02-02 23:00:00,72.49652262\n2014-02-03 00:00:00,72.19594917\n2014-02-03 01:00:00,71.27499667\n2014-02-03 02:00:00,71.54927665\n2014-02-03 03:00:00,71.37741336\n2014-02-03 04:00:00,70.96126394\n2014-02-03 05:00:00,70.86526769\n2014-02-03 06:00:00,69.51742692\n2014-02-03 07:00:00,70.23699729\n2014-02-03 08:00:00,70.25478592\n2014-02-03 09:00:00,69.54660274\n2014-02-03 10:00:00,71.28535022\n2014-02-03 11:00:00,71.76620383\n2014-02-03 12:00:00,73.1581291\n2014-02-03 13:00:00,72.81950243\n2014-02-03 14:00:00,73.94357122\n2014-02-03 15:00:00,73.31051239\n2014-02-03 16:00:00,75.01779737\n2014-02-03 17:00:00,73.79603192\n2014-02-03 18:00:00,74.03478298\n2014-02-03 19:00:00,74.89001392\n2014-02-03 20:00:00,74.20342727\n2014-02-03 21:00:00,75.47335894\n2014-02-03 22:00:00,74.35480145\n2014-02-03 23:00:00,73.90516246\n2014-02-04 00:00:00,74.27115536\n2014-02-04 01:00:00,72.83977840000001\n2014-02-04 02:00:00,72.75240643\n2014-02-04 03:00:00,72.32492459999997\n2014-02-04 04:00:00,73.52854801\n2014-02-04 05:00:00,72.4911934\n2014-02-04 06:00:00,72.27198579\n2014-02-04 07:00:00,71.4871934\n2014-02-04 08:00:00,72.12293771\n2014-02-04 09:00:00,72.29360612\n2014-02-04 10:00:00,72.86539996\n2014-02-04 11:00:00,71.36774996\n2014-02-04 12:00:00,73.26391824\n2014-02-04 13:00:00,73.68072512\n2014-02-04 14:00:00,72.61150204\n2014-02-04 15:00:00,73.07639687\n2014-02-04 16:00:00,74.24530254\n2014-02-04 17:00:00,74.49700643\n2014-02-04 18:00:00,75.69456912\n2014-02-04 19:00:00,74.47440675\n2014-02-04 20:00:00,74.34991774\n2014-02-04 21:00:00,73.98990175\n2014-02-04 22:00:00,73.49337021\n2014-02-04 23:00:00,74.69248458\n2014-02-05 00:00:00,72.92171344\n2014-02-05 01:00:00,73.9381704\n2014-02-05 02:00:00,73.26932063\n2014-02-05 03:00:00,72.89486303\n2014-02-05 04:00:00,71.82789886\n2014-02-05 05:00:00,71.50326635\n2014-02-05 06:00:00,72.43797863\n2014-02-05 07:00:00,71.49212101\n2014-02-05 08:00:00,71.97523749\n2014-02-05 09:00:00,72.25395073\n2014-02-05 10:00:00,72.56517449\n2014-02-05 11:00:00,71.83775883\n2014-02-05 12:00:00,73.44242506\n2014-02-05 13:00:00,74.27947284\n2014-02-05 14:00:00,72.99596329\n2014-02-05 15:00:00,74.10552743\n2014-02-05 16:00:00,73.61788608\n2014-02-05 17:00:00,73.31701516\n2014-02-05 18:00:00,73.01174645\n2014-02-05 19:00:00,74.31390131\n2014-02-05 20:00:00,73.22819982\n2014-02-05 21:00:00,73.72890646\n2014-02-05 22:00:00,72.94723977\n2014-02-05 23:00:00,73.8378393\n2014-02-06 00:00:00,72.12373833\n2014-02-06 01:00:00,72.04284098\n2014-02-06 02:00:00,72.25186859\n2014-02-06 03:00:00,73.09282493\n2014-02-06 04:00:00,71.36865067\n2014-02-06 05:00:00,71.49960342\n2014-02-06 06:00:00,70.32354612\n2014-02-06 07:00:00,70.39520632\n2014-02-06 08:00:00,71.16626768\n2014-02-06 09:00:00,70.02861579\n2014-02-06 10:00:00,71.96241743\n2014-02-06 11:00:00,72.38074162\n2014-02-06 12:00:00,71.76366871\n2014-02-06 13:00:00,71.43442294\n2014-02-06 14:00:00,72.96389766\n2014-02-06 15:00:00,72.40563890000001\n2014-02-06 16:00:00,73.24319119\n2014-02-06 17:00:00,74.49209885\n2014-02-06 18:00:00,75.67593984\n2014-02-06 19:00:00,76.29491541\n2014-02-06 20:00:00,74.47855616\n2014-02-06 21:00:00,73.97881601\n2014-02-06 22:00:00,74.2503925\n2014-02-06 23:00:00,73.65281821\n2014-02-07 00:00:00,73.5566298\n2014-02-07 01:00:00,74.55125277\n2014-02-07 02:00:00,73.17815807\n2014-02-07 03:00:00,73.99622426\n2014-02-07 04:00:00,72.16705646\n2014-02-07 05:00:00,72.45023357\n2014-02-07 06:00:00,73.06302806\n2014-02-07 07:00:00,72.0095\n2014-02-07 08:00:00,71.80741665\n2014-02-07 09:00:00,71.04467432\n2014-02-07 10:00:00,71.97005629\n2014-02-07 11:00:00,72.90941163\n2014-02-07 12:00:00,72.17063774\n2014-02-07 13:00:00,73.06947938\n2014-02-07 14:00:00,73.0341092\n2014-02-07 15:00:00,73.80953945\n2014-02-07 16:00:00,74.31038278\n2014-02-07 17:00:00,73.68024234\n2014-02-07 18:00:00,74.41363078\n2014-02-07 19:00:00,74.41119626\n2014-02-07 20:00:00,75.30582101\n2014-02-07 21:00:00,73.72231831\n2014-02-07 22:00:00,73.956886\n2014-02-07 23:00:00,74.57015739\n2014-02-08 00:00:00,74.38656607\n2014-02-08 01:00:00,73.40422925\n2014-02-08 02:00:00,74.70798308\n2014-02-08 03:00:00,74.45851269\n2014-02-08 04:00:00,73.61811087\n2014-02-08 05:00:00,72.61189448\n2014-02-08 06:00:00,72.51799386\n2014-02-08 07:00:00,72.23863682\n2014-02-08 08:00:00,72.24960786\n2014-02-08 09:00:00,72.36965218\n2014-02-08 10:00:00,73.01194094\n2014-02-08 11:00:00,71.62813647\n2014-02-08 12:00:00,73.08187593\n2014-02-08 13:00:00,72.56747177\n2014-02-08 14:00:00,72.40514197\n2014-02-08 15:00:00,71.49508201\n2014-02-08 16:00:00,72.94715866\n2014-02-08 17:00:00,72.921265\n2014-02-08 18:00:00,73.01400553\n2014-02-08 19:00:00,72.79306485\n2014-02-08 20:00:00,72.85442183\n2014-02-08 21:00:00,71.65525912\n2014-02-08 22:00:00,72.67823919\n2014-02-08 23:00:00,71.24393979999998\n2014-02-09 00:00:00,72.55938056\n2014-02-09 01:00:00,72.05872252\n2014-02-09 02:00:00,70.76837988\n2014-02-09 03:00:00,72.2572247\n2014-02-09 04:00:00,70.78523809\n2014-02-09 05:00:00,70.62316491\n2014-02-09 06:00:00,69.95124246\n2014-02-09 07:00:00,69.93090011\n2014-02-09 08:00:00,70.59418428\n2014-02-09 09:00:00,70.22278152\n2014-02-09 10:00:00,70.96283441\n2014-02-09 11:00:00,69.80899995\n2014-02-09 12:00:00,70.54885559\n2014-02-09 13:00:00,69.93109781\n2014-02-09 14:00:00,69.51149457\n2014-02-09 15:00:00,69.65236836\n2014-02-09 16:00:00,70.29518506\n2014-02-09 17:00:00,71.62899935\n2014-02-09 18:00:00,70.19075454\n2014-02-09 19:00:00,70.75169665\n2014-02-09 20:00:00,70.81184472\n2014-02-09 21:00:00,72.25826358\n2014-02-09 22:00:00,71.2385615\n2014-02-09 23:00:00,71.58482682\n2014-02-10 00:00:00,72.05545689\n2014-02-10 01:00:00,70.68437859\n2014-02-10 02:00:00,71.74562272\n2014-02-10 03:00:00,70.63016123\n2014-02-10 04:00:00,70.10605477\n2014-02-10 05:00:00,69.15085681\n2014-02-10 06:00:00,70.53897933\n2014-02-10 07:00:00,69.75848063\n2014-02-10 08:00:00,69.0311664\n2014-02-10 09:00:00,69.97462923\n2014-02-10 10:00:00,70.99730927\n2014-02-10 11:00:00,71.81090729\n2014-02-10 12:00:00,71.22813976\n2014-02-10 13:00:00,73.54807891\n2014-02-10 14:00:00,73.1994691\n2014-02-10 15:00:00,72.48376476\n2014-02-10 16:00:00,73.27048296\n2014-02-10 17:00:00,72.63291885\n2014-02-10 18:00:00,73.04230204\n2014-02-10 19:00:00,73.59851179\n2014-02-10 20:00:00,73.94426246\n2014-02-10 21:00:00,72.24379429999998\n2014-02-10 22:00:00,72.89933674\n2014-02-10 23:00:00,73.3069622\n2014-02-11 00:00:00,73.94052267\n2014-02-11 01:00:00,72.92628635\n2014-02-11 02:00:00,72.67838417\n2014-02-11 03:00:00,73.30959938\n2014-02-11 04:00:00,73.02655382\n2014-02-11 05:00:00,72.29872004\n2014-02-11 06:00:00,71.88552448\n2014-02-11 07:00:00,72.40495323\n2014-02-11 08:00:00,72.02464429\n2014-02-11 09:00:00,72.19614083\n2014-02-11 10:00:00,72.60597358\n2014-02-11 11:00:00,72.39294669\n2014-02-11 12:00:00,71.43716569\n2014-02-11 13:00:00,73.99604465\n2014-02-11 14:00:00,73.50943035\n2014-02-11 15:00:00,73.45291204\n2014-02-11 16:00:00,72.83513404\n2014-02-11 17:00:00,73.94819798\n2014-02-11 18:00:00,72.4788448\n2014-02-11 19:00:00,72.83570362\n2014-02-11 20:00:00,73.99025826\n2014-02-11 21:00:00,72.88226906\n2014-02-11 22:00:00,73.27645109\n2014-02-11 23:00:00,74.02768967\n2014-02-12 00:00:00,73.89558413\n2014-02-12 01:00:00,72.59262336\n2014-02-12 02:00:00,71.72471476\n2014-02-12 03:00:00,72.13704935\n2014-02-12 04:00:00,71.67420314\n2014-02-12 05:00:00,70.80216066\n2014-02-12 06:00:00,71.79116991\n2014-02-12 07:00:00,70.14151030000001\n2014-02-12 08:00:00,71.38580367\n2014-02-12 09:00:00,70.1927803\n2014-02-12 10:00:00,71.53122540000003\n2014-02-12 11:00:00,70.74462709\n2014-02-12 12:00:00,71.60956249\n2014-02-12 13:00:00,72.63429747\n2014-02-12 14:00:00,72.72337319\n2014-02-12 15:00:00,73.61530291\n2014-02-12 16:00:00,73.79199341\n2014-02-12 17:00:00,74.02452744\n2014-02-12 18:00:00,73.33443313\n2014-02-12 19:00:00,73.77239947\n2014-02-12 20:00:00,74.18795723\n2014-02-12 21:00:00,72.73057539\n2014-02-12 22:00:00,73.0460628\n2014-02-12 23:00:00,72.61851266\n2014-02-13 00:00:00,73.63047725\n2014-02-13 01:00:00,71.86090259999997\n2014-02-13 02:00:00,73.39534945\n2014-02-13 03:00:00,72.5265888\n2014-02-13 04:00:00,72.50012423\n2014-02-13 05:00:00,70.9921352\n2014-02-13 06:00:00,70.68379403\n2014-02-13 07:00:00,70.92225816\n2014-02-13 08:00:00,71.06859469\n2014-02-13 09:00:00,70.50557416\n2014-02-13 10:00:00,72.40911188\n2014-02-13 11:00:00,71.18403064\n2014-02-13 12:00:00,72.27270943\n2014-02-13 13:00:00,72.11898377\n2014-02-13 14:00:00,74.22012096\n2014-02-13 15:00:00,74.14513886\n2014-02-13 16:00:00,72.57257271\n2014-02-13 17:00:00,73.9980464\n2014-02-13 18:00:00,73.63505079999999\n2014-02-13 19:00:00,74.18442393\n2014-02-13 20:00:00,74.01379528\n2014-02-13 21:00:00,73.31100848\n2014-02-13 22:00:00,73.2449359\n2014-02-13 23:00:00,73.63799953\n2014-02-14 00:00:00,74.22768593\n2014-02-14 01:00:00,73.25438431\n2014-02-14 02:00:00,73.33046811\n2014-02-14 03:00:00,73.61255907\n2014-02-14 04:00:00,72.97745167\n2014-02-14 05:00:00,71.89748993\n2014-02-14 06:00:00,72.9483533\n2014-02-14 07:00:00,70.81534967\n2014-02-14 08:00:00,72.54651585\n2014-02-14 09:00:00,71.6016416\n2014-02-14 10:00:00,71.38492873\n2014-02-14 11:00:00,72.63654073\n2014-02-14 12:00:00,72.26304553\n2014-02-14 13:00:00,73.08441684\n2014-02-14 14:00:00,72.98119162\n2014-02-14 15:00:00,73.44090643\n2014-02-14 16:00:00,73.67536027\n2014-02-14 17:00:00,73.57106999\n2014-02-14 18:00:00,75.09120703\n2014-02-14 19:00:00,74.01718788\n2014-02-14 20:00:00,74.75368514\n2014-02-14 21:00:00,74.06098855\n2014-02-14 22:00:00,73.64913399\n2014-02-14 23:00:00,72.97725908\n2014-02-15 00:00:00,74.31242165\n2014-02-15 01:00:00,73.36846791\n2014-02-15 02:00:00,73.40601581\n2014-02-15 03:00:00,71.88177019\n2014-02-15 04:00:00,72.16843891\n2014-02-15 05:00:00,72.02037785\n2014-02-15 06:00:00,71.46429845\n2014-02-15 07:00:00,70.13150262\n2014-02-15 08:00:00,71.3592175\n2014-02-15 09:00:00,71.52512352\n2014-02-15 10:00:00,71.20384956\n2014-02-15 11:00:00,70.74443864\n2014-02-15 12:00:00,70.44676548\n2014-02-15 13:00:00,69.73276669\n2014-02-15 14:00:00,69.16754481\n2014-02-15 15:00:00,68.61762076\n2014-02-15 16:00:00,68.2700207\n2014-02-15 17:00:00,68.32512358\n2014-02-15 18:00:00,68.00591358\n2014-02-15 19:00:00,67.69518570000001\n2014-02-15 20:00:00,67.66314846\n2014-02-15 21:00:00,68.83888277\n2014-02-15 22:00:00,67.71317938\n2014-02-15 23:00:00,68.16526105\n2014-02-16 00:00:00,67.74392032\n2014-02-16 01:00:00,66.91077531\n2014-02-16 02:00:00,67.67449688\n2014-02-16 03:00:00,67.30731382\n2014-02-16 04:00:00,67.90404578\n2014-02-16 05:00:00,66.9816318\n2014-02-16 06:00:00,67.36349977\n2014-02-16 07:00:00,66.85608572\n2014-02-16 08:00:00,66.82867178\n2014-02-16 09:00:00,65.9175334\n2014-02-16 10:00:00,65.85412004\n2014-02-16 11:00:00,66.57327898\n2014-02-16 12:00:00,66.93439295\n2014-02-16 13:00:00,65.95981552\n2014-02-16 14:00:00,65.52567020000001\n2014-02-16 15:00:00,65.00654684\n2014-02-16 16:00:00,65.86116824\n2014-02-16 17:00:00,66.24895835\n2014-02-16 18:00:00,64.84240685\n2014-02-16 19:00:00,65.69994977\n2014-02-16 20:00:00,65.11922166\n2014-02-16 21:00:00,65.06927583\n2014-02-16 22:00:00,65.16381523\n2014-02-16 23:00:00,64.32817118\n2014-02-17 00:00:00,66.17891449\n2014-02-17 01:00:00,65.64161252\n2014-02-17 02:00:00,64.79075623\n2014-02-17 03:00:00,64.67428457\n2014-02-17 04:00:00,64.36980786\n2014-02-17 05:00:00,63.50098479\n2014-02-17 06:00:00,63.81534068\n2014-02-17 07:00:00,64.24808886\n2014-02-17 08:00:00,63.39175042\n2014-02-17 09:00:00,65.78667951\n2014-02-17 10:00:00,65.26018668\n2014-02-17 11:00:00,66.52420616\n2014-02-17 12:00:00,68.3216973\n2014-02-17 13:00:00,69.51920746\n2014-02-17 14:00:00,70.41798643\n2014-02-17 15:00:00,69.85636686\n2014-02-17 16:00:00,70.50368788\n2014-02-17 17:00:00,71.55722128\n2014-02-17 18:00:00,72.21400820000002\n2014-02-17 19:00:00,72.23486752\n2014-02-17 20:00:00,72.30190595\n2014-02-17 21:00:00,71.38697638\n2014-02-17 22:00:00,71.71658422\n2014-02-17 23:00:00,70.60328489\n2014-02-18 00:00:00,70.70527374\n2014-02-18 01:00:00,69.37279327\n2014-02-18 02:00:00,69.26929995\n2014-02-18 03:00:00,68.33325827\n2014-02-18 04:00:00,68.26287644\n2014-02-18 05:00:00,68.58490764\n2014-02-18 06:00:00,67.91159536\n2014-02-18 07:00:00,67.02506652\n2014-02-18 08:00:00,66.65870493\n2014-02-18 09:00:00,68.35154455\n2014-02-18 10:00:00,67.47621403\n2014-02-18 11:00:00,69.77932913\n2014-02-18 12:00:00,69.15476006\n2014-02-18 13:00:00,71.2527348\n2014-02-18 14:00:00,70.75971585\n2014-02-18 15:00:00,72.72805852\n2014-02-18 16:00:00,71.57641906\n2014-02-18 17:00:00,71.53146856\n2014-02-18 18:00:00,72.43892738\n2014-02-18 19:00:00,72.51358476\n2014-02-18 20:00:00,73.04307154\n2014-02-18 21:00:00,72.01489481\n2014-02-18 22:00:00,72.03402933\n2014-02-18 23:00:00,71.36277817\n2014-02-19 00:00:00,70.22442557\n2014-02-19 01:00:00,71.04606096\n2014-02-19 02:00:00,70.29642466\n2014-02-19 03:00:00,69.67691329\n2014-02-19 04:00:00,68.59571214\n2014-02-19 05:00:00,69.32304528\n2014-02-19 06:00:00,69.67748164\n2014-02-19 07:00:00,68.7353527\n2014-02-19 08:00:00,68.35921937\n2014-02-19 09:00:00,68.72795161\n2014-02-19 10:00:00,68.99210194\n2014-02-19 11:00:00,70.19905465\n2014-02-19 12:00:00,69.97929042\n2014-02-19 13:00:00,71.22263248\n2014-02-19 14:00:00,71.68970302\n2014-02-19 15:00:00,71.30018987\n2014-02-19 16:00:00,71.27840683\n2014-02-19 17:00:00,71.89062285\n2014-02-19 18:00:00,70.7418569\n2014-02-19 19:00:00,72.45036867\n2014-02-19 20:00:00,71.32687587\n2014-02-19 21:00:00,71.41737459999997\n2014-02-19 22:00:00,72.27479477\n2014-02-19 23:00:00,70.60398854\n2014-02-20 00:00:00,71.26949942\n2014-02-20 01:00:00,70.11901901\n2014-02-20 02:00:00,70.71862637\n2014-02-20 03:00:00,70.01345997\n2014-02-20 04:00:00,70.36792895\n2014-02-20 05:00:00,70.25181505\n2014-02-20 06:00:00,70.06343925\n2014-02-20 07:00:00,69.51877722\n2014-02-20 08:00:00,69.51143689\n2014-02-20 09:00:00,69.28431029\n2014-02-20 10:00:00,70.02917117\n2014-02-20 11:00:00,69.77788948\n2014-02-20 12:00:00,70.64429563\n2014-02-20 13:00:00,72.09907213\n2014-02-20 14:00:00,72.55900491\n2014-02-20 15:00:00,72.48953325\n2014-02-20 16:00:00,72.02762569\n2014-02-20 17:00:00,72.56107268\n2014-02-20 18:00:00,72.29252772\n2014-02-20 19:00:00,72.14536417\n2014-02-20 20:00:00,73.17633192\n2014-02-20 21:00:00,72.09881309\n2014-02-20 22:00:00,73.03183616\n2014-02-20 23:00:00,73.4095494\n2014-02-21 00:00:00,73.61055026\n2014-02-21 01:00:00,73.22469023\n2014-02-21 02:00:00,72.77238923\n2014-02-21 03:00:00,71.77678685\n2014-02-21 04:00:00,71.39870017\n2014-02-21 05:00:00,72.01672718\n2014-02-21 06:00:00,71.71709105\n2014-02-21 07:00:00,71.89082404\n2014-02-21 08:00:00,71.79162775\n2014-02-21 09:00:00,71.73870688\n2014-02-21 10:00:00,70.86190335\n2014-02-21 11:00:00,71.69377098\n2014-02-21 12:00:00,72.24965305\n2014-02-21 13:00:00,71.86440398\n2014-02-21 14:00:00,71.71570293\n2014-02-21 15:00:00,73.11333987\n2014-02-21 16:00:00,73.11595078\n2014-02-21 17:00:00,71.98594655\n2014-02-21 18:00:00,71.77056727\n2014-02-21 19:00:00,72.69503008\n2014-02-21 20:00:00,72.97101070000002\n2014-02-21 21:00:00,72.4740122\n2014-02-21 22:00:00,73.52059659\n2014-02-21 23:00:00,72.43691661\n2014-02-22 00:00:00,72.18066282\n2014-02-22 01:00:00,71.32459195\n2014-02-22 02:00:00,71.85583639\n2014-02-22 03:00:00,71.88074888\n2014-02-22 04:00:00,72.15361442\n2014-02-22 05:00:00,71.17776846\n2014-02-22 06:00:00,71.41359324\n2014-02-22 07:00:00,71.75202769\n2014-02-22 08:00:00,72.29547661\n2014-02-22 09:00:00,72.06697006\n2014-02-22 10:00:00,70.50858274\n2014-02-22 11:00:00,70.18441596\n2014-02-22 12:00:00,71.29025253\n2014-02-22 13:00:00,70.23647890000001\n2014-02-22 14:00:00,70.42527414\n2014-02-22 15:00:00,70.62841849\n2014-02-22 16:00:00,71.29022977\n2014-02-22 17:00:00,70.83192557\n2014-02-22 18:00:00,71.13549561\n2014-02-22 19:00:00,70.83738869\n2014-02-22 20:00:00,70.83849743\n2014-02-22 21:00:00,70.93245308\n2014-02-22 22:00:00,70.27290872\n2014-02-22 23:00:00,70.58817206\n2014-02-23 00:00:00,70.24057965\n2014-02-23 01:00:00,70.80419\n2014-02-23 02:00:00,69.80143685\n2014-02-23 03:00:00,69.31283198\n2014-02-23 04:00:00,69.35668517\n2014-02-23 05:00:00,69.13396209999999\n2014-02-23 06:00:00,70.44526682\n2014-02-23 07:00:00,70.20928733\n2014-02-23 08:00:00,69.93524085\n2014-02-23 09:00:00,69.29629038\n2014-02-23 10:00:00,68.45718549\n2014-02-23 11:00:00,69.36682524\n2014-02-23 12:00:00,69.78440146\n2014-02-23 13:00:00,70.05047118\n2014-02-23 14:00:00,69.94616047\n2014-02-23 15:00:00,69.58663804\n2014-02-23 16:00:00,69.26826291\n2014-02-23 17:00:00,70.67206672\n2014-02-23 18:00:00,69.77136750000001\n2014-02-23 19:00:00,70.36000475\n2014-02-23 20:00:00,71.22900600000001\n2014-02-23 21:00:00,71.01855228\n2014-02-23 22:00:00,71.67436488\n2014-02-23 23:00:00,71.98920306\n2014-02-24 00:00:00,71.41241783\n2014-02-24 01:00:00,70.21304108\n2014-02-24 02:00:00,70.46941197\n2014-02-24 03:00:00,71.81875355\n2014-02-24 04:00:00,70.75726396\n2014-02-24 05:00:00,70.35054453\n2014-02-24 06:00:00,71.46188706\n2014-02-24 07:00:00,70.98973616\n2014-02-24 08:00:00,69.85618346\n2014-02-24 09:00:00,70.33833311\n2014-02-24 10:00:00,70.64534116\n2014-02-24 11:00:00,71.59340431\n2014-02-24 12:00:00,72.81269719\n2014-02-24 13:00:00,71.4608208\n2014-02-24 14:00:00,72.85545543\n2014-02-24 15:00:00,73.05311023\n2014-02-24 16:00:00,73.92592685\n2014-02-24 17:00:00,74.95996905\n2014-02-24 18:00:00,75.94820959999998\n2014-02-24 19:00:00,75.75487779999997\n2014-02-24 20:00:00,74.81028192\n2014-02-24 21:00:00,73.54824379\n2014-02-24 22:00:00,75.07458015\n2014-02-24 23:00:00,73.30253287\n2014-02-25 00:00:00,74.89976587\n2014-02-25 01:00:00,74.93152766\n2014-02-25 02:00:00,73.08132323\n2014-02-25 03:00:00,74.38609616\n2014-02-25 04:00:00,73.555717\n2014-02-25 05:00:00,72.43144467\n2014-02-25 06:00:00,73.01942581\n2014-02-25 07:00:00,72.1483262\n2014-02-25 08:00:00,72.8103996\n2014-02-25 09:00:00,72.69220185\n2014-02-25 10:00:00,72.93948367\n2014-02-25 11:00:00,72.10962389\n2014-02-25 12:00:00,73.58615695\n2014-02-25 13:00:00,72.55872059\n2014-02-25 14:00:00,73.58393306\n2014-02-25 15:00:00,72.67472192\n2014-02-25 16:00:00,73.6832062\n2014-02-25 17:00:00,74.65712512\n2014-02-25 18:00:00,74.81826612\n2014-02-25 19:00:00,75.30493537\n2014-02-25 20:00:00,74.75955931\n2014-02-25 21:00:00,74.82300241\n2014-02-25 22:00:00,75.2020531\n2014-02-25 23:00:00,73.73854426\n2014-02-26 00:00:00,74.52699276\n2014-02-26 01:00:00,74.22793271\n2014-02-26 02:00:00,73.43795586\n2014-02-26 03:00:00,73.07056291\n2014-02-26 04:00:00,72.27324959999999\n2014-02-26 05:00:00,71.51947436\n2014-02-26 06:00:00,71.63920884\n2014-02-26 07:00:00,72.10054496\n2014-02-26 08:00:00,72.35798657\n2014-02-26 09:00:00,71.52260473\n2014-02-26 10:00:00,70.96393378\n2014-02-26 11:00:00,72.58154764\n2014-02-26 12:00:00,72.58419551\n2014-02-26 13:00:00,72.36171361\n2014-02-26 14:00:00,72.42998458\n2014-02-26 15:00:00,71.75716944\n2014-02-26 16:00:00,73.07326185\n2014-02-26 17:00:00,72.75507065\n2014-02-26 18:00:00,72.5752305\n2014-02-26 19:00:00,73.48040164\n2014-02-26 20:00:00,72.81148014\n2014-02-26 21:00:00,72.55668889\n2014-02-26 22:00:00,72.85158523\n2014-02-26 23:00:00,73.26970533\n2014-02-27 00:00:00,71.19146991\n2014-02-27 01:00:00,72.08289113\n2014-02-27 02:00:00,71.96350659\n2014-02-27 03:00:00,71.82605361\n2014-02-27 04:00:00,70.82030946\n2014-02-27 05:00:00,69.42550165\n2014-02-27 06:00:00,69.92242421\n2014-02-27 07:00:00,69.31438143\n2014-02-27 08:00:00,70.76033757\n2014-02-27 09:00:00,70.97100633\n2014-02-27 10:00:00,70.17113554\n2014-02-27 11:00:00,70.71432592\n2014-02-27 12:00:00,71.921708\n2014-02-27 13:00:00,72.00375809999998\n2014-02-27 14:00:00,71.78458459\n2014-02-27 15:00:00,72.65555112\n2014-02-27 16:00:00,72.58009757\n2014-02-27 17:00:00,73.05064890000001\n2014-02-27 18:00:00,74.54039587\n2014-02-27 19:00:00,75.18858469\n2014-02-27 20:00:00,74.27894519\n2014-02-27 21:00:00,74.26208079\n2014-02-27 22:00:00,73.23807909\n2014-02-27 23:00:00,73.87025742\n2014-02-28 00:00:00,73.43235603\n2014-02-28 01:00:00,72.37198523\n2014-02-28 02:00:00,73.92808884\n2014-02-28 03:00:00,73.25719839\n2014-02-28 04:00:00,72.53001535\n2014-02-28 05:00:00,71.63872957\n2014-02-28 06:00:00,72.28002048\n2014-02-28 07:00:00,71.72196102\n2014-02-28 08:00:00,70.39334093\n2014-02-28 09:00:00,70.10964532\n2014-02-28 10:00:00,70.65823648\n2014-02-28 11:00:00,71.51087208\n2014-02-28 12:00:00,72.44637778\n2014-02-28 13:00:00,71.51568524\n2014-02-28 14:00:00,72.7279092\n2014-02-28 15:00:00,72.29771123\n2014-02-28 16:00:00,71.52876516\n2014-02-28 17:00:00,72.59605592\n2014-02-28 18:00:00,72.01554663\n2014-02-28 19:00:00,72.97598217\n2014-02-28 20:00:00,71.20551\n2014-02-28 21:00:00,72.52524715\n2014-02-28 22:00:00,72.49802968\n2014-02-28 23:00:00,72.6226827\n2014-03-01 00:00:00,71.39694912\n2014-03-01 01:00:00,70.29320788\n2014-03-01 02:00:00,70.10398202\n2014-03-01 03:00:00,70.02121361\n2014-03-01 04:00:00,70.27777940000001\n2014-03-01 05:00:00,68.76433592\n2014-03-01 06:00:00,69.37923216\n2014-03-01 07:00:00,67.78520256\n2014-03-01 08:00:00,68.49976639\n2014-03-01 09:00:00,66.66557183\n2014-03-01 10:00:00,66.92889456\n2014-03-01 11:00:00,65.80440933\n2014-03-01 12:00:00,66.89565828\n2014-03-01 13:00:00,66.20627379\n2014-03-01 14:00:00,65.62264979\n2014-03-01 15:00:00,66.38603358\n2014-03-01 16:00:00,66.57722161\n2014-03-01 17:00:00,67.22633566\n2014-03-01 18:00:00,66.59760208\n2014-03-01 19:00:00,67.12154486\n2014-03-01 20:00:00,65.97349626\n2014-03-01 21:00:00,66.84503091\n2014-03-01 22:00:00,66.34569414\n2014-03-01 23:00:00,65.04830890000001\n2014-03-02 00:00:00,65.36668131\n2014-03-02 01:00:00,64.60285133\n2014-03-02 02:00:00,65.00628144\n2014-03-02 03:00:00,65.10276279\n2014-03-03 09:00:00,64.73752596\n2014-03-03 10:00:00,66.44422198\n2014-03-03 11:00:00,66.67119237\n2014-03-03 12:00:00,68.20387067\n2014-03-03 13:00:00,67.99377700000001\n2014-03-03 14:00:00,68.82246666\n2014-03-03 15:00:00,69.83201105\n2014-03-03 16:00:00,70.41675915\n2014-03-03 17:00:00,69.67662317\n2014-03-03 18:00:00,69.75960523\n2014-03-03 19:00:00,70.63902199\n2014-03-03 20:00:00,71.26261117\n2014-03-03 21:00:00,70.37991099999998\n2014-03-03 22:00:00,68.99746538\n2014-03-03 23:00:00,67.80571471\n2014-03-04 00:00:00,68.65145086\n2014-03-04 01:00:00,67.3954395\n2014-03-04 02:00:00,67.04867326\n2014-03-04 03:00:00,66.58482439\n2014-03-04 04:00:00,65.50344586\n2014-03-04 05:00:00,65.72809278\n2014-03-04 06:00:00,65.71347736\n2014-03-04 07:00:00,66.21746488\n2014-03-04 08:00:00,67.3270938\n2014-03-04 09:00:00,67.62303328\n2014-03-04 10:00:00,68.08086803\n2014-03-04 11:00:00,68.72680885\n2014-03-04 12:00:00,70.45355378\n2014-03-04 13:00:00,70.06613398\n2014-03-04 14:00:00,69.97752106\n2014-03-04 15:00:00,70.4927163\n2014-03-04 16:00:00,71.61681198\n2014-03-04 17:00:00,70.29198332\n2014-03-04 18:00:00,71.67066391\n2014-03-04 19:00:00,70.70533885\n2014-03-04 20:00:00,70.4300817\n2014-03-04 21:00:00,69.29157767\n2014-03-04 22:00:00,69.34063822\n2014-03-04 23:00:00,70.38420092\n2014-03-05 00:00:00,69.63034413\n2014-03-05 01:00:00,69.0398113\n2014-03-05 02:00:00,67.76196134\n2014-03-05 03:00:00,67.67675741\n2014-03-05 04:00:00,68.86005963\n2014-03-05 05:00:00,67.57048842\n2014-03-05 06:00:00,68.46335363\n2014-03-05 07:00:00,69.29349205\n2014-03-05 08:00:00,68.01547296\n2014-03-05 09:00:00,68.10090635\n2014-03-05 10:00:00,68.12754514\n2014-03-05 11:00:00,70.01662351\n2014-03-05 12:00:00,70.25863434\n2014-03-05 13:00:00,71.09608996\n2014-03-05 14:00:00,71.50280303\n2014-03-05 15:00:00,71.42488612\n2014-03-05 16:00:00,72.71167276\n2014-03-05 17:00:00,71.59459113\n2014-03-05 18:00:00,72.43328872\n2014-03-05 19:00:00,71.48709146\n2014-03-05 20:00:00,71.99469951\n2014-03-05 21:00:00,71.35471229\n2014-03-05 22:00:00,70.39110149\n2014-03-05 23:00:00,69.43812495\n2014-03-06 00:00:00,70.2584932\n2014-03-06 01:00:00,69.67190229\n2014-03-06 02:00:00,68.22337002\n2014-03-06 03:00:00,68.80799396\n2014-03-06 04:00:00,68.03247815\n2014-03-06 05:00:00,67.80972606\n2014-03-06 06:00:00,66.40552502\n2014-03-06 07:00:00,67.83509944\n2014-03-06 08:00:00,65.97248106\n2014-03-06 09:00:00,66.31911328\n2014-03-06 10:00:00,66.29172592\n2014-03-06 11:00:00,66.46979301\n2014-03-06 12:00:00,67.19727082\n2014-03-06 13:00:00,67.26610171\n2014-03-06 14:00:00,66.58963271\n2014-03-06 15:00:00,66.13565431\n2014-03-06 16:00:00,67.45824979\n2014-03-06 17:00:00,67.08281943\n2014-03-06 18:00:00,66.60154522\n2014-03-06 19:00:00,66.14435074\n2014-03-06 20:00:00,65.70970149\n2014-03-06 21:00:00,65.72663154\n2014-03-06 22:00:00,65.58931781\n2014-03-06 23:00:00,65.82957452\n2014-03-07 00:00:00,65.66945407\n2014-03-07 01:00:00,64.47296805\n2014-03-07 02:00:00,64.33275758\n2014-03-07 03:00:00,64.30729548\n2014-03-07 04:00:00,63.27916803\n2014-03-07 05:00:00,63.28661915\n2014-03-07 06:00:00,62.71784797\n2014-03-07 07:00:00,62.10356599\n2014-03-07 08:00:00,62.35873434\n2014-03-07 09:00:00,62.26844161\n2014-03-07 10:00:00,64.14762913\n2014-03-07 11:00:00,66.74519744\n2014-03-07 12:00:00,66.88478620000001\n2014-03-07 13:00:00,67.39191825\n2014-03-07 14:00:00,66.3784179\n2014-03-07 15:00:00,67.24728902\n2014-03-07 16:00:00,68.80478948\n2014-03-07 17:00:00,67.78706753\n2014-03-07 18:00:00,67.6234333\n2014-03-07 19:00:00,68.13243751\n2014-03-07 20:00:00,68.35249809\n2014-03-07 21:00:00,68.76098726\n2014-03-07 22:00:00,68.27847874\n2014-03-07 23:00:00,67.18038204\n2014-03-08 00:00:00,66.54164375\n2014-03-08 01:00:00,67.01120528\n2014-03-08 02:00:00,66.64272086\n2014-03-08 03:00:00,65.06151932\n2014-03-08 04:00:00,65.17996189\n2014-03-08 05:00:00,64.67925087\n2014-03-08 06:00:00,65.55120828\n2014-03-08 07:00:00,64.59678509\n2014-03-08 08:00:00,65.27563058\n2014-03-08 09:00:00,64.88539882\n2014-03-08 10:00:00,65.15421592\n2014-03-08 11:00:00,64.26521212\n2014-03-08 12:00:00,64.07879166\n2014-03-08 13:00:00,63.99581719\n2014-03-08 14:00:00,63.37198838\n2014-03-08 15:00:00,63.85857426\n2014-03-08 16:00:00,65.7786958\n2014-03-08 17:00:00,66.00473119\n2014-03-08 18:00:00,65.12337382\n2014-03-08 19:00:00,66.57607623\n2014-03-08 20:00:00,65.02660446\n2014-03-08 21:00:00,64.95266133\n2014-03-08 22:00:00,64.97658136\n2014-03-08 23:00:00,65.67719536\n2014-03-09 00:00:00,65.24741305\n2014-03-09 01:00:00,65.41542891\n2014-03-09 02:00:00,64.98877478\n2014-03-09 03:00:00,64.96988162\n2014-03-09 04:00:00,63.30792665\n2014-03-09 05:00:00,64.40463119\n2014-03-09 06:00:00,63.87984768\n2014-03-09 07:00:00,62.65054877\n2014-03-09 08:00:00,63.64803912\n2014-03-09 09:00:00,63.06377998\n2014-03-09 10:00:00,63.08252395\n2014-03-09 11:00:00,62.42757669\n2014-03-09 12:00:00,62.08987607\n2014-03-09 13:00:00,61.82403302\n2014-03-09 14:00:00,61.80836032\n2014-03-09 15:00:00,63.57034584\n2014-03-09 16:00:00,63.14298573\n2014-03-09 17:00:00,65.21301797\n2014-03-09 18:00:00,63.94421349\n2014-03-09 19:00:00,64.45766756\n2014-03-09 20:00:00,63.5914373\n2014-03-09 21:00:00,62.89815719\n2014-03-09 22:00:00,64.45257404\n2014-03-09 23:00:00,64.12681763\n2014-03-10 00:00:00,63.49055243\n2014-03-10 01:00:00,63.42430336\n2014-03-10 02:00:00,62.15728246\n2014-03-10 03:00:00,62.18439593\n2014-03-10 04:00:00,62.23825287\n2014-03-10 05:00:00,61.28489989\n2014-03-10 06:00:00,62.43160143\n2014-03-10 07:00:00,62.64010591\n2014-03-10 08:00:00,62.75477551\n2014-03-10 09:00:00,63.07107014\n2014-03-10 10:00:00,65.36263572\n2014-03-10 11:00:00,67.68834829\n2014-03-10 12:00:00,66.78938507\n2014-03-10 13:00:00,67.4030453\n2014-03-10 14:00:00,69.22223465\n2014-03-10 15:00:00,68.72906724\n2014-03-10 16:00:00,69.43623743\n2014-03-10 17:00:00,70.25809179999999\n2014-03-10 18:00:00,70.25948981\n2014-03-10 19:00:00,70.60726748\n2014-03-10 20:00:00,70.2063059\n2014-03-10 21:00:00,69.81033474\n2014-03-10 22:00:00,68.24486669\n2014-03-10 23:00:00,68.10978258\n2014-03-11 00:00:00,67.63116079\n2014-03-11 01:00:00,68.12898944\n2014-03-11 02:00:00,66.93579537\n2014-03-11 03:00:00,67.28183681\n2014-03-11 04:00:00,67.12842156\n2014-03-11 05:00:00,65.79175844\n2014-03-11 06:00:00,65.13144669\n2014-03-11 07:00:00,66.1775294\n2014-03-11 08:00:00,66.51384686\n2014-03-11 09:00:00,66.52764863\n2014-03-11 10:00:00,67.78500622\n2014-03-11 11:00:00,69.36668186\n2014-03-11 12:00:00,71.10686192\n2014-03-11 13:00:00,71.34507296\n2014-03-11 14:00:00,71.63930695\n2014-03-11 15:00:00,70.36000942\n2014-03-11 16:00:00,71.98604698\n2014-03-11 17:00:00,71.66471114\n2014-03-11 18:00:00,72.72998288\n2014-03-11 19:00:00,72.17540433\n2014-03-11 20:00:00,71.92709502\n2014-03-11 21:00:00,70.85195269\n2014-03-11 22:00:00,69.01463509\n2014-03-11 23:00:00,68.49462169\n2014-03-12 00:00:00,67.48580392\n2014-03-12 01:00:00,68.07698894\n2014-03-12 02:00:00,68.23106386\n2014-03-12 03:00:00,67.01328165\n2014-03-12 04:00:00,67.18611750000001\n2014-03-12 05:00:00,65.92239173\n2014-03-12 06:00:00,66.38206209\n2014-03-12 07:00:00,66.46286064\n2014-03-12 08:00:00,68.24047875\n2014-03-12 09:00:00,68.02786863\n2014-03-12 10:00:00,70.1038357\n2014-03-12 11:00:00,70.22659164\n2014-03-12 12:00:00,71.37680632\n2014-03-12 13:00:00,70.67512681\n2014-03-12 14:00:00,70.46297529\n2014-03-12 15:00:00,71.28157524\n2014-03-12 16:00:00,71.05593879999998\n2014-03-12 17:00:00,71.70627229\n2014-03-12 18:00:00,72.17357465\n2014-03-12 19:00:00,71.84544009\n2014-03-12 20:00:00,71.17415427\n2014-03-12 21:00:00,71.43730024\n2014-03-12 22:00:00,71.00435876\n2014-03-12 23:00:00,71.1510194\n2014-03-13 00:00:00,69.55935905\n2014-03-13 01:00:00,69.6460687\n2014-03-13 02:00:00,69.7364644\n2014-03-13 03:00:00,68.79399824\n2014-03-13 04:00:00,69.72507825\n2014-03-13 05:00:00,69.23149065\n2014-03-13 06:00:00,67.21438079\n2014-03-13 07:00:00,68.75934959\n2014-03-13 08:00:00,69.27054515\n2014-03-13 09:00:00,69.90997802\n2014-03-13 10:00:00,69.07299661\n2014-03-13 11:00:00,70.97799327\n2014-03-13 12:00:00,70.81341304\n2014-03-13 13:00:00,69.80737543\n2014-03-13 14:00:00,70.50417147\n2014-03-13 15:00:00,71.00976364\n2014-03-13 16:00:00,71.64484062\n2014-03-13 17:00:00,71.60940441\n2014-03-13 18:00:00,71.17635266\n2014-03-13 19:00:00,70.46962717\n2014-03-13 20:00:00,70.50548628\n2014-03-13 21:00:00,70.62289581\n2014-03-13 22:00:00,71.69910104\n2014-03-13 23:00:00,70.73907743\n2014-03-14 00:00:00,69.02175496\n2014-03-14 01:00:00,68.78503059\n2014-03-14 02:00:00,69.22496356\n2014-03-14 03:00:00,67.87748709\n2014-03-14 04:00:00,67.29471566\n2014-03-14 05:00:00,67.28621294\n2014-03-14 06:00:00,66.7890731\n2014-03-14 07:00:00,67.50432318\n2014-03-14 08:00:00,67.79009858\n2014-03-14 09:00:00,69.87567\n2014-03-14 10:00:00,70.21520038\n2014-03-14 11:00:00,71.18656942\n2014-03-14 12:00:00,71.67624154\n2014-03-14 13:00:00,71.22363341\n2014-03-14 14:00:00,70.43924193\n2014-03-14 15:00:00,70.36288978\n2014-03-14 16:00:00,70.79729744\n2014-03-14 17:00:00,70.23646361\n2014-03-14 18:00:00,71.73164608\n2014-03-14 19:00:00,70.94221602\n2014-03-14 20:00:00,70.53918108\n2014-03-14 21:00:00,70.54767727\n2014-03-14 22:00:00,70.90770815\n2014-03-14 23:00:00,69.78682182\n2014-03-15 00:00:00,70.91189536\n2014-03-15 01:00:00,70.07406754\n2014-03-15 02:00:00,69.59586543\n2014-03-15 03:00:00,69.60260984\n2014-03-15 04:00:00,68.27877452\n2014-03-15 05:00:00,69.45619825\n2014-03-15 06:00:00,68.44995951\n2014-03-15 07:00:00,69.73862286\n2014-03-15 08:00:00,68.94209701\n2014-03-15 09:00:00,68.18149599\n2014-03-15 10:00:00,68.76664235\n2014-03-15 11:00:00,67.45815017\n2014-03-15 12:00:00,67.66257636\n2014-03-15 13:00:00,67.77115437\n2014-03-15 14:00:00,67.69510921\n2014-03-15 15:00:00,68.11376092\n2014-03-15 16:00:00,68.40917826\n2014-03-15 17:00:00,68.68576669\n2014-03-15 18:00:00,68.70780771\n2014-03-15 19:00:00,68.52816028\n2014-03-15 20:00:00,67.29328776\n2014-03-15 21:00:00,67.71998071\n2014-03-15 22:00:00,66.43501296\n2014-03-15 23:00:00,67.6421382\n2014-03-16 00:00:00,67.50558169\n2014-03-16 01:00:00,66.63507662\n2014-03-16 02:00:00,66.03094617\n2014-03-16 03:00:00,66.85659507\n2014-03-16 04:00:00,65.17315838\n2014-03-16 05:00:00,65.21746396\n2014-03-16 06:00:00,66.28285507\n2014-03-16 07:00:00,65.42152866\n2014-03-16 08:00:00,64.94362409\n2014-03-16 09:00:00,64.89450895\n2014-03-16 10:00:00,64.55896017\n2014-03-16 11:00:00,63.75135279\n2014-03-16 12:00:00,64.59758157\n2014-03-16 13:00:00,64.12270321\n2014-03-16 14:00:00,63.49946799\n2014-03-16 15:00:00,64.70090581\n2014-03-16 16:00:00,63.79618368\n2014-03-16 17:00:00,64.00797024\n2014-03-16 18:00:00,64.72220608\n2014-03-16 19:00:00,62.87773689\n2014-03-16 20:00:00,63.82235957\n2014-03-16 21:00:00,63.75804636\n2014-03-16 22:00:00,63.15739889\n2014-03-16 23:00:00,63.44294756\n2014-03-17 00:00:00,62.12890913\n2014-03-17 01:00:00,61.82512301\n2014-03-17 02:00:00,61.83080286\n2014-03-17 03:00:00,63.16291422\n2014-03-17 04:00:00,61.25053172\n2014-03-17 05:00:00,61.01365104\n2014-03-17 06:00:00,61.21543911\n2014-03-17 07:00:00,62.37751935\n2014-03-17 08:00:00,62.92591945\n2014-03-17 09:00:00,64.87107009\n2014-03-17 10:00:00,64.86490926\n2014-03-17 11:00:00,66.04123541\n2014-03-17 12:00:00,67.6714638\n2014-03-17 13:00:00,68.92351552\n2014-03-17 14:00:00,67.95417072\n2014-03-17 15:00:00,69.769521\n2014-03-17 16:00:00,70.24593681\n2014-03-17 17:00:00,69.82130302\n2014-03-17 18:00:00,70.83974955\n2014-03-17 19:00:00,70.51174374\n2014-03-17 20:00:00,71.02364643\n2014-03-17 21:00:00,68.7052537\n2014-03-17 22:00:00,68.11165389\n2014-03-17 23:00:00,68.1166531\n2014-03-18 00:00:00,67.21496653\n2014-03-18 01:00:00,67.06224246\n2014-03-18 02:00:00,67.30972126\n2014-03-18 05:00:00,66.69399198\n2014-03-18 06:00:00,65.70506463\n2014-03-18 07:00:00,64.62101714\n2014-03-18 08:00:00,65.77618074\n2014-03-18 09:00:00,67.40523118\n2014-03-18 10:00:00,68.71941661\n2014-03-18 11:00:00,69.61966828\n2014-03-18 12:00:00,70.27366665\n2014-03-18 13:00:00,70.56337429\n2014-03-18 14:00:00,70.67077922\n2014-03-18 15:00:00,72.26734255\n2014-03-18 16:00:00,70.62328355\n2014-03-18 17:00:00,71.06334712\n2014-03-18 18:00:00,71.65028164\n2014-03-18 19:00:00,71.77769312\n2014-03-18 20:00:00,70.059985\n2014-03-18 21:00:00,70.75799228\n2014-03-18 22:00:00,69.98433493\n2014-03-18 23:00:00,68.84969949\n2014-03-19 00:00:00,69.74606796\n2014-03-19 01:00:00,69.53952356\n2014-03-19 02:00:00,67.523201\n2014-03-19 03:00:00,67.37990329\n2014-03-19 04:00:00,67.41747840000001\n2014-03-19 05:00:00,65.93843117\n2014-03-19 06:00:00,66.82475179\n2014-03-19 07:00:00,67.27135893\n2014-03-19 08:00:00,67.13357776\n2014-03-19 09:00:00,68.52772342\n2014-03-19 10:00:00,68.55982584\n2014-03-19 11:00:00,68.81377025\n2014-03-19 12:00:00,70.36173769\n2014-03-19 13:00:00,71.70237934\n2014-03-19 14:00:00,72.13491131\n2014-03-19 15:00:00,72.18835193\n2014-03-19 16:00:00,71.92595429\n2014-03-19 17:00:00,71.92725603\n2014-03-19 18:00:00,71.54807344\n2014-03-19 19:00:00,70.49187639\n2014-03-19 20:00:00,71.48653484\n2014-03-19 21:00:00,70.20635388\n2014-03-19 22:00:00,69.49279694\n2014-03-19 23:00:00,68.9205068\n2014-03-20 00:00:00,68.33056564\n2014-03-20 01:00:00,68.82533073\n2014-03-20 02:00:00,68.84005375\n2014-03-20 03:00:00,68.31437625\n2014-03-20 04:00:00,66.64807821\n2014-03-20 05:00:00,66.34454369\n2014-03-20 06:00:00,66.17310237\n2014-03-20 07:00:00,66.74208658\n2014-03-20 08:00:00,68.01627433\n2014-03-20 09:00:00,68.92086970000001\n2014-03-20 10:00:00,70.1290524\n2014-03-20 11:00:00,70.85226597\n2014-03-20 12:00:00,70.66374179\n2014-03-20 13:00:00,70.4602105\n2014-03-20 14:00:00,70.72339624\n2014-03-20 15:00:00,71.44960721\n2014-03-20 16:00:00,72.70811888\n2014-03-20 17:00:00,72.77820708\n2014-03-20 18:00:00,71.29761709\n2014-03-20 19:00:00,71.33906347\n2014-03-20 20:00:00,72.43172383\n2014-03-20 21:00:00,70.68626447\n2014-03-20 22:00:00,70.90794649\n2014-03-20 23:00:00,69.22547767\n2014-03-21 00:00:00,69.59225848\n2014-03-21 01:00:00,69.23210541\n2014-03-21 02:00:00,68.15528042\n2014-03-21 03:00:00,66.91203197\n2014-03-21 04:00:00,67.71558241\n2014-03-21 05:00:00,66.33452731\n2014-03-21 06:00:00,66.34030271\n2014-03-21 07:00:00,66.1824594\n2014-03-21 08:00:00,66.26386\n2014-03-21 09:00:00,68.22384891\n2014-03-21 10:00:00,69.16427797\n2014-03-21 11:00:00,69.10930036\n2014-03-21 12:00:00,70.81803261\n2014-03-21 13:00:00,70.01676069\n2014-03-21 14:00:00,70.90161589\n2014-03-21 15:00:00,71.64555322\n2014-03-21 16:00:00,71.70339358\n2014-03-21 17:00:00,71.27680445\n2014-03-21 18:00:00,70.63130618\n2014-03-21 19:00:00,70.97130269\n2014-03-21 20:00:00,71.71353903\n2014-03-21 21:00:00,69.9054085\n2014-03-21 22:00:00,69.66400387\n2014-03-21 23:00:00,69.16838511\n2014-03-22 00:00:00,69.69722981\n2014-03-22 01:00:00,69.15682991\n2014-03-22 02:00:00,68.72517924\n2014-03-22 03:00:00,68.35990386\n2014-03-22 04:00:00,67.18127785\n2014-03-22 05:00:00,67.94571484\n2014-03-22 06:00:00,66.71803036\n2014-03-22 07:00:00,65.66712074\n2014-03-22 08:00:00,66.84586991\n2014-03-22 09:00:00,66.29208118\n2014-03-22 10:00:00,66.88373267\n2014-03-22 11:00:00,65.19948254\n2014-03-22 12:00:00,65.58210550000001\n2014-03-22 13:00:00,64.70394655\n2014-03-22 14:00:00,66.22315748\n2014-03-22 15:00:00,64.88013387\n2014-03-22 16:00:00,65.55529857\n2014-03-22 17:00:00,64.64947474\n2014-03-22 18:00:00,64.68176215\n2014-03-22 19:00:00,64.80958215\n2014-03-22 20:00:00,65.33285671\n2014-03-22 21:00:00,64.36267745\n2014-03-22 22:00:00,64.11222793\n2014-03-22 23:00:00,65.11150875\n2014-03-23 00:00:00,65.33899224\n2014-03-23 01:00:00,65.61427437\n2014-03-23 02:00:00,63.77836909\n2014-03-23 03:00:00,63.70443845\n2014-03-23 04:00:00,63.46343576\n2014-03-23 05:00:00,63.6445251\n2014-03-23 06:00:00,65.44047774\n2014-03-23 07:00:00,63.66470663\n2014-03-23 08:00:00,64.32136806\n2014-03-23 09:00:00,64.17341\n2014-03-23 10:00:00,64.86387244\n2014-03-23 11:00:00,62.98320455\n2014-03-23 12:00:00,63.83170364\n2014-03-23 13:00:00,62.81085999\n2014-03-23 14:00:00,62.84699795\n2014-03-23 15:00:00,63.166335499999995\n2014-03-23 16:00:00,63.23431085\n2014-03-23 17:00:00,63.01982143\n2014-03-23 18:00:00,63.70769083\n2014-03-23 19:00:00,62.51382762\n2014-03-23 20:00:00,63.21955192\n2014-03-23 21:00:00,62.20602098\n2014-03-23 22:00:00,62.15285065\n2014-03-23 23:00:00,63.05547087\n2014-03-24 00:00:00,62.10293066\n2014-03-24 01:00:00,62.540844799999995\n2014-03-24 02:00:00,62.5503174\n2014-03-24 03:00:00,63.20486663\n2014-03-24 04:00:00,62.9317748\n2014-03-24 19:00:00,71.94336325\n2014-03-24 20:00:00,70.71564295\n2014-03-24 21:00:00,69.28811871\n2014-03-24 22:00:00,68.43786337\n2014-03-24 23:00:00,68.24934959\n2014-03-25 00:00:00,68.47135744\n2014-03-25 01:00:00,67.01776467\n2014-03-25 02:00:00,68.08328348\n2014-03-25 03:00:00,67.68747842\n2014-03-25 04:00:00,67.39799093\n2014-03-25 05:00:00,66.2691171\n2014-03-25 06:00:00,65.34304105\n2014-03-25 07:00:00,64.77433465\n2014-03-25 08:00:00,66.44792487\n2014-03-25 09:00:00,67.26279954\n2014-03-25 10:00:00,67.60152815\n2014-03-25 11:00:00,69.90530838\n2014-03-25 12:00:00,70.73996852\n2014-03-25 13:00:00,70.49826866\n2014-03-25 14:00:00,70.2611678\n2014-03-25 15:00:00,71.53832084\n2014-03-25 16:00:00,71.27033912\n2014-03-25 17:00:00,70.90025791\n2014-03-25 18:00:00,71.52148116\n2014-03-25 19:00:00,70.28414588\n2014-03-25 20:00:00,71.60015916\n2014-03-25 21:00:00,70.28728127\n2014-03-25 22:00:00,68.83984168\n2014-03-25 23:00:00,68.49777461\n2014-03-26 00:00:00,69.31375581\n2014-03-26 01:00:00,67.72785184\n2014-03-26 02:00:00,68.09933961\n2014-03-26 03:00:00,67.25783658\n2014-03-26 04:00:00,66.86402700000001\n2014-03-26 05:00:00,66.59775853\n2014-03-26 06:00:00,65.53304117\n2014-03-26 07:00:00,66.86270078\n2014-03-26 08:00:00,67.50801513\n2014-03-26 09:00:00,67.77407736\n2014-03-26 10:00:00,68.52400365\n2014-03-26 11:00:00,69.56611683\n2014-03-26 12:00:00,71.28961034\n2014-03-26 13:00:00,70.14062086\n2014-03-26 14:00:00,71.034825\n2014-03-26 15:00:00,71.44418165\n2014-03-26 16:00:00,70.78327368\n2014-03-26 17:00:00,70.66347191\n2014-03-26 18:00:00,69.90711596\n2014-03-26 19:00:00,70.24754496\n2014-03-26 20:00:00,71.0175816\n2014-03-26 21:00:00,71.11791992\n2014-03-26 22:00:00,69.28691532\n2014-03-26 23:00:00,69.27422586\n2014-03-27 00:00:00,70.19449054\n2014-03-27 01:00:00,68.77820054\n2014-03-27 02:00:00,68.18678053\n2014-03-27 03:00:00,68.85984403\n2014-03-27 04:00:00,67.73755512\n2014-03-27 05:00:00,67.49811369\n2014-03-27 06:00:00,66.73351538\n2014-03-27 07:00:00,65.96544261\n2014-03-27 08:00:00,66.93124294\n2014-03-27 09:00:00,69.07779412\n2014-03-27 10:00:00,69.22374151\n2014-03-27 11:00:00,69.4535237\n2014-03-27 12:00:00,72.22574727\n2014-03-27 13:00:00,72.32609476\n2014-03-27 14:00:00,72.0268521\n2014-03-27 15:00:00,71.58630641\n2014-03-27 16:00:00,70.57044597\n2014-03-27 17:00:00,71.2768215\n2014-03-27 18:00:00,71.55483881\n2014-03-27 19:00:00,72.03927682\n2014-03-27 20:00:00,71.48654663\n2014-03-27 21:00:00,70.86464227\n2014-03-27 22:00:00,69.35637651\n2014-03-27 23:00:00,69.61239792\n2014-03-28 00:00:00,68.43977756\n2014-03-28 01:00:00,68.1853957\n2014-03-28 02:00:00,67.29170594\n2014-03-28 03:00:00,68.42970414\n2014-03-28 04:00:00,67.05828335\n2014-03-28 05:00:00,66.50295007\n2014-03-28 06:00:00,67.00732027\n2014-03-28 07:00:00,65.42638245\n2014-03-28 08:00:00,67.67939638\n2014-03-28 09:00:00,67.02204681\n2014-03-28 10:00:00,68.54764706\n2014-03-28 11:00:00,69.4655308\n2014-03-28 12:00:00,70.43402561\n2014-03-28 13:00:00,71.9389561\n2014-03-28 14:00:00,70.81297494\n2014-03-28 15:00:00,70.81249572\n2014-03-28 16:00:00,70.15898776\n2014-03-28 17:00:00,71.64451052\n2014-03-28 18:00:00,70.19782359\n2014-03-28 19:00:00,70.58227035\n2014-03-28 20:00:00,71.2087204\n2014-03-28 21:00:00,70.20658031\n2014-03-28 22:00:00,71.01175909999998\n2014-03-28 23:00:00,68.85446017\n2014-03-29 00:00:00,69.98331416\n2014-03-29 01:00:00,68.46446529\n2014-03-29 02:00:00,68.73818002\n2014-03-29 03:00:00,69.062706\n2014-03-29 04:00:00,68.38697286\n2014-03-29 05:00:00,67.58387429\n2014-03-29 06:00:00,67.83077241\n2014-03-29 07:00:00,68.81423687\n2014-03-29 08:00:00,66.69042351\n2014-03-29 09:00:00,66.36840797\n2014-03-29 10:00:00,66.61346754\n2014-03-29 11:00:00,67.33922911\n2014-03-29 12:00:00,66.9322944\n2014-03-29 13:00:00,66.76955124\n2014-03-29 14:00:00,66.00830414\n2014-03-29 15:00:00,66.7799832\n2014-03-29 16:00:00,66.58172048\n2014-03-29 17:00:00,67.11698683\n2014-03-29 18:00:00,66.15598172\n2014-03-29 19:00:00,66.69489329\n2014-03-29 20:00:00,64.82380273\n2014-03-29 21:00:00,65.2430426\n2014-03-29 22:00:00,65.21164883\n2014-03-29 23:00:00,64.54188892\n2014-03-30 00:00:00,64.8747141\n2014-03-30 01:00:00,65.4966696\n2014-03-30 02:00:00,65.38109608\n2014-03-30 03:00:00,65.02897391\n2014-03-30 04:00:00,64.67595377\n2014-03-30 05:00:00,64.44424833\n2014-03-30 06:00:00,64.25219739\n2014-03-30 07:00:00,65.40018788\n2014-03-30 08:00:00,63.73067948\n2014-03-30 09:00:00,64.20889648\n2014-03-30 10:00:00,63.45681538\n2014-03-30 11:00:00,64.48807692\n2014-03-30 12:00:00,63.79730874\n2014-03-30 13:00:00,64.36082107\n2014-03-30 14:00:00,63.84830762\n2014-03-30 15:00:00,65.51296869\n2014-03-30 16:00:00,65.48389278\n2014-03-30 17:00:00,65.75005021\n2014-03-30 18:00:00,64.65810145\n2014-03-30 19:00:00,64.36282383\n2014-03-30 20:00:00,64.99007209\n2014-03-30 21:00:00,65.34666001\n2014-03-30 22:00:00,65.39531562\n2014-03-30 23:00:00,64.45329069\n2014-03-31 00:00:00,64.61712504\n2014-03-31 01:00:00,63.75428142\n2014-03-31 02:00:00,63.49502357\n2014-03-31 03:00:00,64.12967698\n2014-03-31 04:00:00,63.69871435\n2014-03-31 05:00:00,62.31748849\n2014-03-31 06:00:00,62.56249792\n2014-03-31 07:00:00,62.083133\n2014-03-31 08:00:00,64.28414943\n2014-03-31 09:00:00,63.94397227\n2014-03-31 10:00:00,65.76317725\n2014-03-31 11:00:00,67.38934556\n2014-03-31 12:00:00,66.79761934\n2014-03-31 13:00:00,67.51730856\n2014-03-31 14:00:00,69.42271076\n2014-03-31 15:00:00,69.86566479\n2014-03-31 16:00:00,69.47338876\n2014-03-31 17:00:00,70.95110588\n2014-03-31 18:00:00,71.56889705\n2014-03-31 19:00:00,70.99062865\n2014-03-31 20:00:00,70.60246289\n2014-03-31 21:00:00,68.00017618\n2014-03-31 22:00:00,68.25783759999999\n2014-03-31 23:00:00,68.63980318\n2014-04-01 00:00:00,68.32316289\n2014-04-01 01:00:00,66.43383631\n2014-04-01 02:00:00,67.18821052\n2014-04-01 03:00:00,67.27079193\n2014-04-01 04:00:00,65.27791142\n2014-04-01 05:00:00,64.67375005\n2014-04-01 06:00:00,63.96850495\n2014-04-01 07:00:00,64.60849643\n2014-04-01 08:00:00,65.56452156\n2014-04-01 09:00:00,66.5334125\n2014-04-01 10:00:00,68.23406291\n2014-04-01 11:00:00,68.56959033\n2014-04-01 12:00:00,69.70420104\n2014-04-01 13:00:00,69.63981849\n2014-04-01 14:00:00,70.22222824\n2014-04-01 15:00:00,70.31535411\n2014-04-01 16:00:00,71.95951248\n2014-04-01 17:00:00,71.24637137\n2014-04-01 18:00:00,71.58768312\n2014-04-01 19:00:00,70.42108950000002\n2014-04-01 20:00:00,71.20646965\n2014-04-01 21:00:00,70.61530009\n2014-04-01 22:00:00,70.06998582\n2014-04-01 23:00:00,69.29171113\n2014-04-02 00:00:00,67.85447566\n2014-04-02 01:00:00,68.24887826\n2014-04-02 02:00:00,68.76715290000001\n2014-04-02 03:00:00,68.21590455\n2014-04-02 04:00:00,66.42226253\n2014-04-02 05:00:00,67.39517591\n2014-04-02 06:00:00,65.36892099\n2014-04-02 07:00:00,66.25362724\n2014-04-02 08:00:00,66.59754547\n2014-04-02 09:00:00,67.72967658\n2014-04-02 10:00:00,68.48225745\n2014-04-02 11:00:00,69.92320652\n2014-04-02 12:00:00,70.58513885\n2014-04-02 13:00:00,71.41308851\n2014-04-02 14:00:00,70.3227835\n2014-04-02 15:00:00,71.11789389\n2014-04-02 16:00:00,69.47243025\n2014-04-02 17:00:00,70.89176392\n2014-04-02 18:00:00,71.46215140000002\n2014-04-02 19:00:00,71.40483009\n2014-04-02 20:00:00,72.2868221\n2014-04-02 21:00:00,69.7696442\n2014-04-02 22:00:00,69.85857394\n2014-04-02 23:00:00,70.29044092\n2014-04-03 00:00:00,69.18897735\n2014-04-03 01:00:00,68.25903615\n2014-04-03 02:00:00,69.48405619\n2014-04-03 03:00:00,69.03729828\n2014-04-03 04:00:00,68.99054634\n2014-04-03 05:00:00,66.96693467\n2014-04-03 06:00:00,67.79585605\n2014-04-03 07:00:00,67.30111228\n2014-04-03 08:00:00,68.06321777\n2014-04-03 09:00:00,68.92309559\n2014-04-10 15:00:00,69.95467957\n2014-04-10 16:00:00,69.99969109999999\n2014-04-10 17:00:00,70.46057561\n2014-04-10 18:00:00,69.69177635\n2014-04-10 19:00:00,71.01239837\n2014-04-10 20:00:00,69.3636139\n2014-04-10 21:00:00,69.23956202\n2014-04-10 22:00:00,69.02602271\n2014-04-10 23:00:00,67.66881974\n2014-04-11 00:00:00,66.9784945\n2014-04-11 01:00:00,66.1376634\n2014-04-11 02:00:00,65.64125076\n2014-04-11 03:00:00,64.99436157\n2014-04-11 04:00:00,64.15511608\n2014-04-11 05:00:00,62.70299143\n2014-04-11 06:00:00,63.83944116\n2014-04-11 07:00:00,62.44194873\n2014-04-11 08:00:00,62.37114409\n2014-04-11 09:00:00,65.37565585\n2014-04-11 10:00:00,65.96957647\n2014-04-11 11:00:00,66.59359265\n2014-04-11 12:00:00,68.33141592\n2014-04-11 13:00:00,68.92824643\n2014-04-11 14:00:00,69.4470812\n2014-04-11 15:00:00,70.69379188\n2014-04-11 16:00:00,68.80751333\n2014-04-11 17:00:00,69.77099451\n2014-04-11 18:00:00,69.4302069\n2014-04-11 19:00:00,69.69943799\n2014-04-11 20:00:00,68.39255358\n2014-04-11 21:00:00,69.67023519\n2014-04-11 22:00:00,68.57844056\n2014-04-11 23:00:00,67.05017892\n2014-04-12 00:00:00,68.53844670000001\n2014-04-12 01:00:00,66.58977222\n2014-04-12 02:00:00,66.4437355\n2014-04-12 03:00:00,66.63975574\n2014-04-12 04:00:00,65.35200151\n2014-04-12 05:00:00,66.56495507\n2014-04-12 06:00:00,64.62244069\n2014-04-12 07:00:00,64.9923665\n2014-04-12 08:00:00,63.97746263\n2014-04-12 09:00:00,64.18268808\n2014-04-12 10:00:00,64.55629521\n2014-04-12 11:00:00,63.96192594\n2014-04-12 12:00:00,63.56770877\n2014-04-12 13:00:00,63.45102885\n2014-04-12 14:00:00,62.75664373\n2014-04-12 15:00:00,61.88488434\n2014-04-12 16:00:00,61.97105163\n2014-04-12 17:00:00,62.03644725\n2014-04-12 18:00:00,62.85879831\n2014-04-12 19:00:00,61.75532146\n2014-04-12 20:00:00,60.33080311\n2014-04-12 21:00:00,61.31862007\n2014-04-12 22:00:00,61.26515428\n2014-04-12 23:00:00,59.564727100000006\n2014-04-13 00:00:00,59.92144785\n2014-04-13 01:00:00,60.09354127\n2014-04-13 02:00:00,59.92218636\n2014-04-13 03:00:00,58.86227492\n2014-04-13 04:00:00,58.77714115\n2014-04-13 05:00:00,59.41074654\n2014-04-13 06:00:00,57.84457312\n2014-04-13 07:00:00,58.38952164\n2014-04-13 08:00:00,59.12502309\n2014-04-13 09:00:00,57.45840559\n2014-04-13 10:00:00,58.23364994\n2014-04-13 11:00:00,58.73348655\n2014-04-13 12:00:00,58.97261213\n2014-04-13 13:00:00,60.25792529\n2014-04-13 14:00:00,59.15943501\n2014-04-13 15:00:00,60.26702164\n2014-04-13 16:00:00,59.20056905\n2014-04-13 17:00:00,59.42050888\n2014-04-13 18:00:00,59.61076035\n2014-04-13 19:00:00,59.375844799999996\n2014-04-13 20:00:00,60.45036956\n2014-04-13 21:00:00,60.38321276\n2014-04-13 22:00:00,59.91094693\n2014-04-13 23:00:00,60.28396361\n2014-04-14 00:00:00,58.83249363\n2014-04-14 01:00:00,60.184197\n2014-04-14 02:00:00,60.57384958\n2014-04-14 03:00:00,60.58416247\n2014-04-14 04:00:00,59.54132737\n2014-04-14 05:00:00,60.578911899999994\n2014-04-14 06:00:00,59.20245134\n2014-04-14 07:00:00,59.53629772\n2014-04-14 08:00:00,61.42760267\n2014-04-14 09:00:00,62.35052077\n2014-04-14 10:00:00,63.87302969\n2014-04-14 11:00:00,63.95474106\n2014-04-14 12:00:00,64.33255339\n2014-04-14 13:00:00,66.89048639\n2014-04-14 14:00:00,66.76290578\n2014-04-14 15:00:00,68.22765033\n2014-04-14 16:00:00,68.66217484\n2014-04-14 17:00:00,68.77584664\n2014-04-14 18:00:00,69.85149804\n2014-04-14 19:00:00,69.64134024\n2014-04-14 20:00:00,68.67883235\n2014-04-14 21:00:00,66.53906385\n2014-04-14 22:00:00,66.75587974\n2014-04-14 23:00:00,66.67419463\n2014-04-15 00:00:00,65.2054392\n2014-04-15 01:00:00,65.2363275\n2014-04-15 02:00:00,63.50605093\n2014-04-15 03:00:00,64.46464095\n2014-04-15 04:00:00,63.51738461\n2014-04-15 05:00:00,63.61950823\n2014-04-15 06:00:00,62.96296552\n2014-04-15 07:00:00,61.77349005\n2014-04-15 08:00:00,63.95443765\n2014-04-15 09:00:00,63.98985647\n2014-04-15 10:00:00,66.04334863\n2014-04-15 11:00:00,68.14218819999999\n2014-04-15 12:00:00,68.61566659\n2014-04-15 13:00:00,68.80427879999999\n2014-04-15 14:00:00,70.24867959\n2014-04-15 15:00:00,68.84215496\n2014-04-15 16:00:00,71.07422118\n2014-04-15 17:00:00,70.7975171\n2014-04-15 18:00:00,70.00379538\n2014-04-15 19:00:00,69.63818207\n2014-04-15 20:00:00,71.11138859\n2014-04-15 21:00:00,68.9745537\n2014-04-15 22:00:00,68.41451411\n2014-04-15 23:00:00,67.63084599\n2014-04-16 00:00:00,65.73481705\n2014-04-16 01:00:00,65.50434383\n2014-04-16 02:00:00,64.79166617\n2014-04-16 03:00:00,63.918387100000004\n2014-04-16 04:00:00,64.49704161\n2014-04-16 05:00:00,63.67515316\n2014-04-16 06:00:00,62.46829544\n2014-04-16 07:00:00,63.58707467\n2014-04-16 08:00:00,64.98478124\n2014-04-16 09:00:00,64.79823783\n2014-04-16 10:00:00,67.37766731\n2014-04-16 11:00:00,67.53637026\n2014-04-16 12:00:00,68.93675906\n2014-04-16 13:00:00,69.01582856\n2014-04-16 14:00:00,70.01135347\n2014-04-16 15:00:00,70.54341131\n2014-04-16 16:00:00,70.35620490000001\n2014-04-16 17:00:00,72.05054652\n2014-04-16 18:00:00,70.83587447\n2014-04-16 19:00:00,71.22103625\n2014-04-16 20:00:00,70.22217235\n2014-04-16 21:00:00,69.83271805\n2014-04-16 22:00:00,67.95233259\n2014-04-16 23:00:00,67.65108997\n2014-04-17 00:00:00,67.466994\n2014-04-17 01:00:00,65.22016644\n2014-04-17 02:00:00,65.24342103\n2014-04-17 03:00:00,64.62596906\n2014-04-17 04:00:00,63.67041499\n2014-04-17 05:00:00,64.21771116\n2014-04-17 06:00:00,62.40771234\n2014-04-17 07:00:00,64.25745568\n2014-04-17 08:00:00,63.78224775\n2014-04-17 09:00:00,65.71063960000001\n2014-04-17 10:00:00,66.77957199\n2014-04-17 11:00:00,68.38229729\n2014-04-17 12:00:00,68.29797018\n2014-04-17 13:00:00,70.41445853\n2014-04-17 14:00:00,68.73075749\n2014-04-17 15:00:00,70.53796369999998\n2014-04-17 16:00:00,69.84495909999998\n2014-04-17 17:00:00,69.92419335\n2014-04-17 18:00:00,70.06645502\n2014-04-17 19:00:00,70.01194478\n2014-04-17 20:00:00,70.75213902\n2014-04-17 21:00:00,70.23146023\n2014-04-17 22:00:00,68.89087654\n2014-04-17 23:00:00,68.74794199\n2014-04-18 00:00:00,68.6134614\n2014-04-18 01:00:00,67.80409959999999\n2014-04-18 02:00:00,66.81999556\n2014-04-18 03:00:00,66.76963018\n2014-04-18 04:00:00,65.69553058\n2014-04-18 05:00:00,65.73002042\n2014-04-18 06:00:00,65.04376513\n2014-04-18 07:00:00,64.66042336\n2014-04-18 08:00:00,66.66369506\n2014-04-18 09:00:00,66.91478029\n2014-04-18 10:00:00,68.35124962\n2014-04-18 11:00:00,68.53892428\n2014-04-18 12:00:00,69.18079834\n2014-04-18 13:00:00,70.04821235\n2014-04-18 14:00:00,69.09186246\n2014-04-18 15:00:00,70.13679966\n2014-04-18 16:00:00,68.64486802\n2014-04-18 17:00:00,69.10913357\n2014-04-18 18:00:00,69.34877115\n2014-04-18 19:00:00,70.06810868\n2014-04-18 20:00:00,69.68681363\n2014-04-18 21:00:00,69.28946496\n2014-04-18 22:00:00,68.10328878\n2014-04-18 23:00:00,68.52704977\n2014-04-19 00:00:00,67.80210719\n2014-04-19 01:00:00,66.29263566\n2014-04-19 02:00:00,66.15580573\n2014-04-19 03:00:00,65.50262029\n2014-04-19 04:00:00,65.67858252\n2014-04-19 05:00:00,66.76499604\n2014-04-19 06:00:00,65.38745208\n2014-04-19 07:00:00,64.95897072\n2014-04-19 08:00:00,64.77271857\n2014-04-19 09:00:00,64.36173315\n2014-04-19 10:00:00,65.1175339\n2014-04-19 11:00:00,64.06584001\n2014-04-19 12:00:00,63.84447255\n2014-04-19 13:00:00,63.69995847\n2014-04-19 14:00:00,64.95980589\n2014-04-19 15:00:00,64.54564962\n2014-04-19 16:00:00,64.92641544\n2014-04-19 17:00:00,64.05690668\n2014-04-19 18:00:00,65.14093075\n2014-04-19 19:00:00,65.37596399\n2014-04-19 20:00:00,64.49955643\n2014-04-19 21:00:00,64.61511022\n2014-04-19 22:00:00,64.38633566\n2014-04-19 23:00:00,64.6986036\n2014-04-20 00:00:00,63.69621365\n2014-04-20 01:00:00,63.46227468\n2014-04-20 02:00:00,61.73732749\n2014-04-20 03:00:00,62.88858987\n2014-04-20 04:00:00,62.02517391\n2014-04-20 05:00:00,61.32938908\n2014-04-20 06:00:00,61.58004254\n2014-04-20 07:00:00,60.95237553\n2014-04-20 08:00:00,60.85101193\n2014-04-20 09:00:00,59.91009200000001\n2014-04-20 10:00:00,60.32414667\n2014-04-20 11:00:00,61.24486641\n2014-04-20 12:00:00,59.66938197\n2014-04-20 13:00:00,61.12053222\n2014-04-20 14:00:00,61.88004071\n2014-04-20 15:00:00,60.49012871\n2014-04-20 16:00:00,61.00233827\n2014-04-20 17:00:00,61.765906799999996\n2014-04-20 18:00:00,60.26541206\n2014-04-20 19:00:00,60.71115886\n2014-04-20 20:00:00,60.52159375\n2014-04-20 21:00:00,61.72193037\n2014-04-20 22:00:00,60.84591691\n2014-04-20 23:00:00,60.77650542\n2014-04-21 00:00:00,60.2969507\n2014-04-21 01:00:00,60.50295653\n2014-04-21 02:00:00,60.86537483\n2014-04-21 03:00:00,60.31204125\n2014-04-21 04:00:00,59.84361371\n2014-04-21 05:00:00,60.93695396\n2014-04-21 06:00:00,61.29175138\n2014-04-21 07:00:00,61.35624139\n2014-04-21 08:00:00,62.51476508\n2014-04-21 09:00:00,62.43283694\n2014-04-21 10:00:00,64.91681271\n2014-04-21 11:00:00,65.39698618\n2014-04-21 12:00:00,65.915587\n2014-04-21 13:00:00,67.29050932\n2014-04-21 14:00:00,68.45738752\n2014-04-21 15:00:00,70.07377229\n2014-04-21 16:00:00,69.70332453\n2014-04-21 17:00:00,69.7202728\n2014-04-21 18:00:00,69.40144364\n2014-04-21 19:00:00,68.60855551\n2014-04-21 20:00:00,68.59433384\n2014-04-21 21:00:00,67.36680577\n2014-04-21 22:00:00,67.03274551\n2014-04-21 23:00:00,67.24095409\n2014-04-22 00:00:00,65.7964252\n2014-04-22 01:00:00,64.99226274\n2014-04-22 02:00:00,64.49559793\n2014-04-22 03:00:00,65.11700189\n2014-04-22 04:00:00,64.3213603\n2014-04-22 05:00:00,63.60761024\n2014-04-22 06:00:00,64.31240029\n2014-04-22 07:00:00,63.6046907\n2014-04-22 08:00:00,64.44609818\n2014-04-22 09:00:00,65.51557705\n2014-04-22 10:00:00,66.98431814\n2014-04-22 11:00:00,67.61193771\n2014-04-22 12:00:00,69.98132266\n2014-04-22 13:00:00,70.67558021\n2014-04-22 14:00:00,69.62883752\n2014-04-22 15:00:00,69.69713146\n2014-04-22 16:00:00,69.91198782\n2014-04-22 17:00:00,70.55887454\n2014-04-22 18:00:00,70.51507392\n2014-04-22 19:00:00,69.61686927\n2014-04-22 20:00:00,69.95093901\n2014-04-22 21:00:00,68.91740485\n2014-04-22 22:00:00,67.98366316\n2014-04-22 23:00:00,69.21152689\n2014-04-23 00:00:00,68.4994454\n2014-04-23 01:00:00,68.2065762\n2014-04-23 02:00:00,67.17531475\n2014-04-23 03:00:00,66.98745597\n2014-04-23 04:00:00,66.01118571\n2014-04-23 05:00:00,66.26108706\n2014-04-23 06:00:00,66.03229855\n2014-04-23 07:00:00,66.26457169\n2014-04-23 08:00:00,66.5901253\n2014-04-23 09:00:00,67.33860469\n2014-04-23 10:00:00,67.71813475\n2014-04-23 11:00:00,68.74407883\n2014-04-23 12:00:00,70.07146655\n2014-04-23 13:00:00,69.09664385\n2014-04-23 14:00:00,68.54085218\n2014-04-23 15:00:00,68.74793879\n2014-04-23 16:00:00,70.2110304\n2014-04-23 17:00:00,69.08812898\n2014-04-23 18:00:00,71.14090948\n2014-04-23 19:00:00,71.35406032\n2014-04-23 20:00:00,70.40898557\n2014-04-23 21:00:00,70.11680124\n2014-04-23 22:00:00,68.45657214\n2014-04-23 23:00:00,68.04369977\n2014-04-24 00:00:00,67.86825922\n2014-04-24 01:00:00,68.25265298\n2014-04-24 02:00:00,67.93389846\n2014-04-24 03:00:00,67.41557857\n2014-04-24 04:00:00,66.82858317\n2014-04-24 05:00:00,66.46827942\n2014-04-24 06:00:00,66.70529771\n2014-04-24 07:00:00,65.99333339\n2014-04-24 08:00:00,66.39954920000001\n2014-04-24 09:00:00,68.68937881\n2014-04-24 10:00:00,68.86981543\n2014-04-24 11:00:00,69.28930829\n2014-04-24 12:00:00,70.13701442\n2014-04-24 13:00:00,70.87920902\n2014-04-24 14:00:00,69.73387857\n2014-04-24 15:00:00,71.07672883\n2014-04-24 16:00:00,70.8997397\n2014-04-24 17:00:00,70.81721973\n2014-04-24 18:00:00,70.08894813\n2014-04-24 19:00:00,71.49812440000002\n2014-04-24 20:00:00,70.33872212\n2014-04-24 21:00:00,69.97998584\n2014-04-24 22:00:00,69.11046806\n2014-04-24 23:00:00,68.18636306\n2014-04-25 00:00:00,67.39351909\n2014-04-25 01:00:00,66.57525861\n2014-04-25 02:00:00,67.73318644\n2014-04-25 03:00:00,66.68982673\n2014-04-25 04:00:00,65.83218116\n2014-04-25 05:00:00,65.95237266\n2014-04-25 06:00:00,67.28099527\n2014-04-25 07:00:00,66.90419491\n2014-04-25 08:00:00,67.80676658\n2014-04-25 09:00:00,68.71115712\n2014-04-25 10:00:00,70.02939458\n2014-04-25 11:00:00,69.32625844\n2014-04-25 12:00:00,70.95509984\n2014-04-25 13:00:00,70.33649459\n2014-04-25 14:00:00,70.46790053\n2014-04-25 15:00:00,71.4753647\n2014-04-25 16:00:00,71.6850702\n2014-04-25 17:00:00,70.43496647\n2014-04-25 18:00:00,70.80912379\n2014-04-25 19:00:00,70.67649218\n2014-04-25 20:00:00,70.53630655\n2014-04-25 21:00:00,70.9107218\n2014-04-25 22:00:00,69.72934336\n2014-04-25 23:00:00,69.6017667\n2014-04-26 00:00:00,69.48880205\n2014-04-26 01:00:00,67.24793666\n2014-04-26 02:00:00,67.33153476\n2014-04-26 03:00:00,66.89338891\n2014-04-26 04:00:00,66.56130689\n2014-04-26 05:00:00,66.53741504\n2014-04-26 06:00:00,67.13725522\n2014-04-26 07:00:00,66.5594858\n2014-04-26 08:00:00,65.90565072\n2014-04-26 09:00:00,65.53921771\n2014-04-26 10:00:00,65.83948867\n2014-04-26 11:00:00,64.57393058\n2014-04-26 12:00:00,65.47092598\n2014-04-26 13:00:00,64.06228730000001\n2014-04-26 14:00:00,65.61321875\n2014-04-26 15:00:00,65.0033148\n2014-04-26 16:00:00,65.06987305\n2014-04-26 17:00:00,65.49571691\n2014-04-26 18:00:00,64.89058829999999\n2014-04-26 19:00:00,63.93327257\n2014-04-26 20:00:00,65.74230017\n2014-04-26 21:00:00,64.87334743\n2014-04-26 22:00:00,64.59101491\n2014-04-26 23:00:00,64.52446439\n2014-04-27 00:00:00,65.86073905\n2014-04-27 01:00:00,65.70163338\n2014-04-27 02:00:00,65.48002454\n2014-04-27 03:00:00,65.01981817\n2014-04-27 04:00:00,64.07651163\n2014-04-27 05:00:00,64.19020524\n2014-04-27 06:00:00,64.54513799\n2014-04-27 07:00:00,64.16276662\n2014-04-27 08:00:00,64.68808942\n2014-04-27 09:00:00,65.0067767\n2014-04-27 10:00:00,64.86726485\n2014-04-27 11:00:00,65.27562701\n2014-04-27 12:00:00,64.76188253\n2014-04-27 13:00:00,64.21479337\n2014-04-27 14:00:00,64.22497124\n2014-04-27 15:00:00,63.48983416\n2014-04-27 16:00:00,64.02881119\n2014-04-27 17:00:00,65.14115001\n2014-04-27 18:00:00,64.16580322\n2014-04-27 19:00:00,63.82552427\n2014-04-27 20:00:00,64.51645768\n2014-04-27 21:00:00,64.81548712\n2014-04-27 22:00:00,63.65811355\n2014-04-27 23:00:00,63.04274263\n2014-04-28 00:00:00,63.66900707\n2014-04-28 01:00:00,62.84663436\n2014-04-28 02:00:00,64.00274294\n2014-04-28 03:00:00,64.17028398\n2014-04-28 04:00:00,64.29074432\n2014-04-28 05:00:00,62.8534311\n2014-04-28 06:00:00,64.27748755\n2014-04-28 07:00:00,63.93818963\n2014-04-28 08:00:00,64.19242071\n2014-04-28 09:00:00,66.39555183\n2014-04-28 10:00:00,66.35592434\n2014-04-28 11:00:00,66.93708398\n2014-04-28 12:00:00,67.94603672\n2014-04-28 13:00:00,67.83616225\n2014-04-28 14:00:00,68.02972643\n2014-04-28 15:00:00,67.63528784\n2014-04-28 16:00:00,67.95345262\n2014-04-28 17:00:00,67.94164899\n2014-04-28 18:00:00,66.31355879\n2014-04-28 19:00:00,66.90239851\n2014-04-28 20:00:00,67.92545865\n2014-04-28 21:00:00,66.24886617\n2014-04-28 22:00:00,66.61769712\n2014-04-28 23:00:00,66.45853965\n2014-04-29 00:00:00,65.70015178\n2014-04-29 01:00:00,66.15509081\n2014-04-29 02:00:00,64.37093221\n2014-04-29 03:00:00,64.73766535\n2014-04-29 04:00:00,63.71676928\n2014-04-29 05:00:00,65.12909065\n2014-04-29 06:00:00,64.59083625\n2014-04-29 07:00:00,65.39479955\n2014-04-29 08:00:00,64.99259943\n2014-04-29 09:00:00,63.55132406\n2014-04-29 10:00:00,63.86318351\n2014-04-29 11:00:00,63.4598629\n2014-04-29 12:00:00,63.08150923\n2014-04-29 13:00:00,63.48047822\n2014-04-29 14:00:00,64.82342973\n2014-04-29 15:00:00,64.45813978\n2014-04-29 16:00:00,63.80209508\n2014-04-29 17:00:00,65.04887616\n2014-04-29 18:00:00,65.88072103\n2014-04-29 19:00:00,65.4814587\n2014-04-29 20:00:00,64.19984122\n2014-04-29 21:00:00,65.87838087\n2014-04-29 22:00:00,64.72572253\n2014-04-29 23:00:00,65.00936847\n2014-04-30 00:00:00,64.37972197\n2014-04-30 01:00:00,64.81705324\n2014-04-30 02:00:00,64.01853731\n2014-04-30 03:00:00,62.59835239\n2014-04-30 04:00:00,62.15358748\n2014-04-30 05:00:00,63.65464859\n2014-04-30 06:00:00,62.66869499\n2014-04-30 07:00:00,63.19330523\n2014-04-30 08:00:00,64.24502053\n2014-04-30 09:00:00,65.1453243\n2014-04-30 10:00:00,64.9329398\n2014-04-30 11:00:00,66.64151484\n2014-04-30 12:00:00,66.82120203\n2014-04-30 13:00:00,67.1960497\n2014-04-30 14:00:00,66.13772358\n2014-04-30 15:00:00,66.37318638\n2014-04-30 16:00:00,67.38361772\n2014-04-30 17:00:00,67.98871109999999\n2014-04-30 18:00:00,66.25593843\n2014-04-30 19:00:00,65.92849928\n2014-04-30 20:00:00,67.21492219\n2014-04-30 21:00:00,66.24671438\n2014-04-30 22:00:00,66.61478769\n2014-04-30 23:00:00,64.84814958\n2014-05-01 00:00:00,64.94889814\n2014-05-01 01:00:00,64.45625398\n2014-05-01 02:00:00,63.9798679\n2014-05-01 03:00:00,64.26732464\n2014-05-01 04:00:00,64.59177699\n2014-05-01 05:00:00,65.37702424\n2014-05-01 06:00:00,65.19211401\n2014-05-01 07:00:00,65.37953893\n2014-05-01 08:00:00,65.05709023\n2014-05-01 09:00:00,65.87109317\n2014-05-01 10:00:00,66.54947805\n2014-05-01 11:00:00,66.4332683\n2014-05-01 12:00:00,67.94196795\n2014-05-01 13:00:00,67.73779434\n2014-05-01 14:00:00,67.94409258\n2014-05-01 15:00:00,68.59569962\n2014-05-01 16:00:00,67.76281833\n2014-05-01 17:00:00,66.3713461\n2014-05-01 18:00:00,66.45491031\n2014-05-01 19:00:00,67.7664687\n2014-05-01 20:00:00,66.30486725\n2014-05-01 21:00:00,66.77500592\n2014-05-01 22:00:00,66.08791142\n2014-05-01 23:00:00,66.23633214\n2014-05-02 00:00:00,66.08952394\n2014-05-02 01:00:00,65.49363114\n2014-05-02 02:00:00,65.20911118\n2014-05-02 03:00:00,64.65270388\n2014-05-02 04:00:00,65.68346791\n2014-05-02 05:00:00,64.53848669\n2014-05-02 06:00:00,64.87436222\n2014-05-02 07:00:00,65.83693065\n2014-05-02 08:00:00,66.45562134\n2014-05-02 09:00:00,66.22132242\n2014-05-02 10:00:00,67.40617703\n2014-05-02 11:00:00,66.82972449\n2014-05-02 12:00:00,66.3484439\n2014-05-02 13:00:00,66.56058031\n2014-05-02 14:00:00,67.87466603\n2014-05-02 15:00:00,68.36875479999999\n2014-05-02 16:00:00,68.32191349\n2014-05-02 17:00:00,68.61482576\n2014-05-02 18:00:00,67.74306346\n2014-05-02 19:00:00,67.08645996\n2014-05-02 20:00:00,68.34330065\n2014-05-02 21:00:00,68.30007946\n2014-05-02 22:00:00,68.22785404\n2014-05-02 23:00:00,66.69875824\n2014-05-03 00:00:00,66.4911086\n2014-05-03 01:00:00,66.35595511\n2014-05-03 02:00:00,66.81821492\n2014-05-03 03:00:00,65.56948969\n2014-05-03 04:00:00,66.61559763\n2014-05-03 05:00:00,65.6976645\n2014-05-03 06:00:00,64.59377619\n2014-05-03 07:00:00,64.74378706\n2014-05-03 08:00:00,65.25902071\n2014-05-03 09:00:00,64.47503572\n2014-05-03 10:00:00,64.61145531\n2014-05-03 11:00:00,63.68596001\n2014-05-03 12:00:00,65.43821188\n2014-05-03 13:00:00,64.12205423\n2014-05-03 14:00:00,65.42301205\n2014-05-03 15:00:00,65.95634267\n2014-05-03 16:00:00,65.81969209\n2014-05-03 17:00:00,64.85601416\n2014-05-03 18:00:00,65.00620928\n2014-05-03 19:00:00,63.94392708\n2014-05-03 20:00:00,65.20208745\n2014-05-03 21:00:00,63.84740672\n2014-05-03 22:00:00,63.75022634\n2014-05-03 23:00:00,64.87600042\n2014-05-04 00:00:00,64.18060217\n2014-05-04 01:00:00,64.07250966\n2014-05-04 02:00:00,62.43332813\n2014-05-04 03:00:00,62.52641171\n2014-05-04 04:00:00,62.30957888\n2014-05-04 05:00:00,62.35436891\n2014-05-04 06:00:00,63.42459056\n2014-05-04 07:00:00,63.09408094\n2014-05-04 08:00:00,62.58243369\n2014-05-04 09:00:00,63.37961637\n2014-05-04 10:00:00,62.86781634\n2014-05-04 11:00:00,62.88417215\n2014-05-04 12:00:00,62.11991599\n2014-05-04 13:00:00,62.70773678\n2014-05-04 14:00:00,63.59298753\n2014-05-04 15:00:00,62.71663598\n2014-05-04 16:00:00,63.60890306\n2014-05-04 17:00:00,62.82802932\n2014-05-04 18:00:00,63.79858076\n2014-05-04 19:00:00,63.11692463\n2014-05-04 20:00:00,62.12890815\n2014-05-04 21:00:00,61.59769629\n2014-05-04 22:00:00,62.8583145\n2014-05-04 23:00:00,61.41615236\n2014-05-05 00:00:00,61.49160445\n2014-05-05 01:00:00,61.82814205\n2014-05-05 02:00:00,61.69737845\n2014-05-05 03:00:00,61.65254063\n2014-05-05 04:00:00,60.606883700000004\n2014-05-05 05:00:00,60.47320097\n2014-05-05 06:00:00,61.5530172\n2014-05-05 07:00:00,62.01910222\n2014-05-05 08:00:00,61.23608102\n2014-05-05 09:00:00,63.67999575\n2014-05-05 10:00:00,63.36326181\n2014-05-05 11:00:00,64.13721032\n2014-05-05 12:00:00,64.5332446\n2014-05-05 13:00:00,64.19481423\n2014-05-05 14:00:00,65.1361502\n2014-05-05 15:00:00,65.97596267\n2014-05-05 16:00:00,65.85552001\n2014-05-05 17:00:00,66.32755106\n2014-05-05 18:00:00,66.92969566\n2014-05-05 19:00:00,67.2613918\n2014-05-05 20:00:00,65.80789035\n2014-05-05 21:00:00,66.20385124\n2014-05-05 22:00:00,66.51044071\n2014-05-05 23:00:00,64.8207324\n2014-05-06 00:00:00,63.59220664\n2014-05-06 01:00:00,63.23531713\n2014-05-06 02:00:00,62.49046863\n2014-05-06 03:00:00,62.28369414\n2014-05-06 04:00:00,63.30749881\n2014-05-06 05:00:00,62.80276256\n2014-05-06 06:00:00,62.34187092\n2014-05-06 07:00:00,64.17473372\n2014-05-06 08:00:00,63.97093501\n2014-05-06 09:00:00,65.0523434\n2014-05-06 10:00:00,64.75464232\n2014-05-06 11:00:00,65.04876411\n2014-05-06 12:00:00,65.74920338\n2014-05-06 13:00:00,66.40186825\n2014-05-06 14:00:00,66.18664212\n2014-05-06 15:00:00,67.31747692\n2014-05-06 16:00:00,66.95425995\n2014-05-06 17:00:00,66.93790428\n2014-05-06 18:00:00,67.73969822\n2014-05-06 19:00:00,66.72610529\n2014-05-06 20:00:00,66.08638956\n2014-05-06 21:00:00,66.71634147\n2014-05-06 22:00:00,65.14686479999999\n2014-05-06 23:00:00,64.64265197\n2014-05-07 00:00:00,65.62693199\n2014-05-07 01:00:00,64.08219838\n2014-05-07 02:00:00,64.54200752\n2014-05-07 03:00:00,65.09258433\n2014-05-07 04:00:00,64.43853993\n2014-05-07 05:00:00,64.62081306\n2014-05-07 06:00:00,63.29588419\n2014-05-07 07:00:00,64.71917156\n2014-05-07 08:00:00,63.73179147\n2014-05-07 09:00:00,66.29709464\n2014-05-07 10:00:00,67.19427577\n2014-05-07 11:00:00,67.06897531\n2014-05-07 12:00:00,68.72099133\n2014-05-07 13:00:00,69.96068224\n2014-05-07 14:00:00,70.56685636\n2014-05-07 15:00:00,69.75004488\n2014-05-07 16:00:00,69.17335133\n2014-05-07 17:00:00,70.50844769\n2014-05-07 18:00:00,70.24540175\n2014-05-07 19:00:00,70.81293524\n2014-05-07 20:00:00,69.94704581\n2014-05-07 21:00:00,68.86682809\n2014-05-07 22:00:00,68.39329009\n2014-05-07 23:00:00,66.6067577\n2014-05-08 00:00:00,66.76001378\n2014-05-08 01:00:00,66.27637613\n2014-05-08 02:00:00,65.75512541\n2014-05-08 03:00:00,65.81007339\n2014-05-08 04:00:00,65.37270606\n2014-05-08 05:00:00,66.28889617\n2014-05-08 06:00:00,66.23410255\n2014-05-08 07:00:00,64.91234651\n2014-05-08 08:00:00,67.05133706\n2014-05-08 09:00:00,67.83863065\n2014-05-08 10:00:00,68.10943196\n2014-05-08 11:00:00,69.65642273\n2014-05-08 12:00:00,70.60573585\n2014-05-08 13:00:00,70.62927012\n2014-05-08 14:00:00,70.21115072\n2014-05-08 15:00:00,70.29113189\n2014-05-08 16:00:00,70.64550484\n2014-05-08 17:00:00,71.27645212\n2014-05-08 18:00:00,71.83727293\n2014-05-08 19:00:00,71.46726041\n2014-05-08 20:00:00,69.75939304\n2014-05-08 21:00:00,70.11417736\n2014-05-08 22:00:00,70.05504972\n2014-05-08 23:00:00,69.37027812\n2014-05-09 00:00:00,67.98228281\n2014-05-09 01:00:00,67.7865791\n2014-05-09 02:00:00,68.43446290000001\n2014-05-09 03:00:00,68.07785549\n2014-05-09 04:00:00,67.81285784\n2014-05-09 05:00:00,67.56774369\n2014-05-09 06:00:00,66.24760777\n2014-05-09 07:00:00,67.65004294\n2014-05-09 08:00:00,67.05143804\n2014-05-09 09:00:00,69.05576366\n2014-05-09 10:00:00,70.10149255\n2014-05-09 11:00:00,70.63274013\n2014-05-09 12:00:00,71.06084806\n2014-05-09 13:00:00,71.07378866\n2014-05-09 14:00:00,69.87334432\n2014-05-09 15:00:00,70.92486991\n2014-05-09 16:00:00,71.2245648\n2014-05-09 17:00:00,70.78867373\n2014-05-09 18:00:00,71.99197043\n2014-05-09 19:00:00,70.89590208\n2014-05-09 20:00:00,72.38733933\n2014-05-09 21:00:00,70.14675317\n2014-05-09 22:00:00,69.74583888\n2014-05-09 23:00:00,69.43160284\n2014-05-10 00:00:00,68.23254059\n2014-05-10 01:00:00,69.47792142\n2014-05-10 02:00:00,68.91530719\n2014-05-10 03:00:00,68.35492212\n2014-05-10 04:00:00,68.39336374\n2014-05-10 05:00:00,68.42272702\n2014-05-10 06:00:00,67.0775277\n2014-05-10 07:00:00,66.90356792\n2014-05-10 08:00:00,66.37013021\n2014-05-10 09:00:00,68.21760218\n2014-05-10 10:00:00,67.53453251\n2014-05-10 11:00:00,67.42839785\n2014-05-10 12:00:00,66.96098515\n2014-05-10 13:00:00,67.33616722\n2014-05-10 14:00:00,66.84359334\n2014-05-10 15:00:00,65.89084398\n2014-05-10 16:00:00,66.81261725\n2014-05-10 17:00:00,65.32919958\n2014-05-10 18:00:00,65.92892671\n2014-05-10 19:00:00,66.58894429\n2014-05-10 20:00:00,65.10538195\n2014-05-10 21:00:00,65.63011787\n2014-05-10 22:00:00,65.81492917\n2014-05-10 23:00:00,65.57018764\n2014-05-11 00:00:00,63.91974669\n2014-05-11 01:00:00,64.51176296\n2014-05-11 02:00:00,64.43387227\n2014-05-11 03:00:00,64.33383818\n2014-05-11 04:00:00,64.57554395\n2014-05-11 05:00:00,65.03499427\n2014-05-11 06:00:00,63.11467108\n2014-05-11 07:00:00,63.87061555\n2014-05-11 08:00:00,64.64784774\n2014-05-11 09:00:00,63.64523071\n2014-05-11 10:00:00,64.05141919\n2014-05-11 11:00:00,62.7828001\n2014-05-11 12:00:00,63.82347474\n2014-05-11 13:00:00,63.58691465\n2014-05-11 14:00:00,62.08829654\n2014-05-11 15:00:00,63.01928506\n2014-05-11 16:00:00,63.90711168\n2014-05-11 17:00:00,63.07839314\n2014-05-11 18:00:00,62.69840054\n2014-05-11 19:00:00,61.72789308\n2014-05-11 20:00:00,62.289274\n2014-05-11 21:00:00,63.08826676\n2014-05-11 22:00:00,61.55557216\n2014-05-11 23:00:00,63.00932675\n2014-05-12 00:00:00,62.18412627\n2014-05-12 01:00:00,62.39660826\n2014-05-12 02:00:00,61.14767562\n2014-05-12 03:00:00,61.13299926\n2014-05-12 04:00:00,62.20171526\n2014-05-12 05:00:00,61.03856972\n2014-05-12 06:00:00,62.82075925\n2014-05-12 07:00:00,62.287278799999996\n2014-05-12 08:00:00,61.74042901\n2014-05-12 09:00:00,64.34959977\n2014-05-12 10:00:00,66.00850439\n2014-05-12 11:00:00,65.98530817\n2014-05-12 12:00:00,67.03067426\n2014-05-12 13:00:00,68.11149661\n2014-05-12 14:00:00,68.18592974\n2014-05-12 15:00:00,69.09194409999999\n2014-05-12 16:00:00,70.46158593\n2014-05-12 17:00:00,68.55542525\n2014-05-12 18:00:00,68.18348692\n2014-05-12 19:00:00,68.79946301\n2014-05-12 20:00:00,68.94392853\n2014-05-12 21:00:00,68.37912217\n2014-05-12 22:00:00,68.03272736\n2014-05-12 23:00:00,66.7522962\n2014-05-13 00:00:00,65.70093962\n2014-05-13 01:00:00,65.23145055\n2014-05-13 02:00:00,65.58334605\n2014-05-13 03:00:00,64.43826513\n2014-05-13 04:00:00,64.76745107\n2014-05-13 05:00:00,63.63936741\n2014-05-13 06:00:00,64.99365642\n2014-05-13 07:00:00,65.42791053\n2014-05-13 08:00:00,64.54368408\n2014-05-13 09:00:00,65.7424681\n2014-05-13 10:00:00,68.2490268\n2014-05-13 11:00:00,68.81523729\n2014-05-13 12:00:00,69.61897566\n2014-05-13 13:00:00,69.27540087\n2014-05-13 14:00:00,69.46898521\n2014-05-13 15:00:00,70.39851654\n2014-05-13 16:00:00,70.72748205\n2014-05-13 17:00:00,70.07376172\n2014-05-13 18:00:00,70.43111508\n2014-05-13 19:00:00,69.18648323\n2014-05-13 20:00:00,69.33720712\n2014-05-13 21:00:00,68.52452572\n2014-05-13 22:00:00,68.66320083\n2014-05-13 23:00:00,67.39728285\n2014-05-14 00:00:00,68.3111207\n2014-05-14 01:00:00,67.1601394\n2014-05-14 02:00:00,66.97372975\n2014-05-14 03:00:00,66.48481188\n2014-05-14 04:00:00,64.8808456\n2014-05-14 05:00:00,64.70801495\n2014-05-14 06:00:00,64.5459563\n2014-05-14 07:00:00,65.67840491\n2014-05-14 08:00:00,65.05875661\n2014-05-14 09:00:00,67.03858825\n2014-05-14 10:00:00,69.05639384\n2014-05-14 11:00:00,68.99189609999999\n2014-05-14 12:00:00,69.97788528\n2014-05-14 13:00:00,70.175432\n2014-05-14 14:00:00,68.16664370000001\n2014-05-14 15:00:00,68.57300267\n2014-05-14 16:00:00,69.83526008\n2014-05-14 17:00:00,70.27480031\n2014-05-14 18:00:00,70.20609040000001\n2014-05-14 19:00:00,69.40921677\n2014-05-14 20:00:00,70.27798951\n2014-05-14 21:00:00,68.30333556\n2014-05-14 22:00:00,68.09324242\n2014-05-14 23:00:00,68.36429597\n2014-05-15 00:00:00,67.72416061\n2014-05-15 01:00:00,67.8085136\n2014-05-15 02:00:00,68.26962214\n2014-05-15 03:00:00,66.64600393\n2014-05-15 04:00:00,67.56801604\n2014-05-15 05:00:00,67.36462946\n2014-05-15 06:00:00,64.81152604\n2014-05-15 07:00:00,66.53328753\n2014-05-15 08:00:00,67.08670333\n2014-05-15 09:00:00,66.85800575\n2014-05-15 10:00:00,69.47031702\n2014-05-15 11:00:00,70.77703377\n2014-05-15 12:00:00,71.07003789\n2014-05-15 13:00:00,70.78202725\n2014-05-15 14:00:00,70.7083186\n2014-05-15 15:00:00,70.96353620000002\n2014-05-15 16:00:00,70.2180453\n2014-05-15 17:00:00,71.14732103\n2014-05-15 18:00:00,71.78243404\n2014-05-15 19:00:00,70.94431125\n2014-05-15 20:00:00,70.25408586\n2014-05-15 21:00:00,69.97385592\n2014-05-15 22:00:00,71.20814017\n2014-05-15 23:00:00,70.28109027\n2014-05-16 00:00:00,68.42534022\n2014-05-16 01:00:00,68.14026632\n2014-05-16 02:00:00,68.31516842\n2014-05-16 03:00:00,68.80554576\n2014-05-16 04:00:00,68.70805438\n2014-05-16 05:00:00,68.21126844\n2014-05-16 06:00:00,67.02311979\n2014-05-16 07:00:00,68.13634615\n2014-05-16 08:00:00,68.50810021\n2014-05-16 09:00:00,68.78472332\n2014-05-16 10:00:00,70.26313322\n2014-05-16 11:00:00,69.48894493\n2014-05-16 12:00:00,69.78809126\n2014-05-16 13:00:00,69.96723012\n2014-05-16 14:00:00,69.74249505\n2014-05-16 15:00:00,70.69057352\n2014-05-16 16:00:00,70.63243838\n2014-05-16 17:00:00,70.67548445\n2014-05-16 18:00:00,71.48839758\n2014-05-16 19:00:00,70.21791457\n2014-05-16 20:00:00,69.93428517\n2014-05-16 21:00:00,70.22321349\n2014-05-16 22:00:00,70.68873242\n2014-05-16 23:00:00,68.72204475\n2014-05-17 00:00:00,69.45225691\n2014-05-17 01:00:00,68.41224787\n2014-05-17 02:00:00,68.36748732\n2014-05-17 03:00:00,67.63648402\n2014-05-17 04:00:00,67.66201157\n2014-05-17 05:00:00,65.90307781\n2014-05-17 06:00:00,66.21437481\n2014-05-17 07:00:00,65.82644339\n2014-05-17 08:00:00,65.50506941\n2014-05-17 09:00:00,65.74501564\n2014-05-17 10:00:00,65.36640537\n2014-05-17 11:00:00,65.90704699\n2014-05-17 12:00:00,63.77248723\n2014-05-17 13:00:00,64.55949992\n2014-05-17 14:00:00,64.5256338\n2014-05-17 15:00:00,64.67400160000001\n2014-05-17 16:00:00,62.79405286\n2014-05-17 17:00:00,64.31443601\n2014-05-17 18:00:00,62.55982025\n2014-05-17 19:00:00,62.74968304\n2014-05-17 20:00:00,62.73063243\n2014-05-17 21:00:00,63.65406403\n2014-05-17 22:00:00,63.42070867\n2014-05-17 23:00:00,61.94114934\n2014-05-18 00:00:00,62.89319989\n2014-05-18 01:00:00,61.96136235\n2014-05-18 02:00:00,61.33631343\n2014-05-18 03:00:00,61.95426535\n2014-05-18 04:00:00,61.38195858\n2014-05-18 05:00:00,62.38443786\n2014-05-18 06:00:00,61.0947659\n2014-05-18 07:00:00,61.36331427\n2014-05-18 08:00:00,60.59300743\n2014-05-18 09:00:00,60.43062383\n2014-05-18 10:00:00,60.58242408\n2014-05-18 11:00:00,60.31117133\n2014-05-18 12:00:00,59.76775547\n2014-05-18 13:00:00,59.86404445\n2014-05-18 14:00:00,60.24787212\n2014-05-18 15:00:00,60.87471092\n2014-05-18 16:00:00,60.28561460000001\n2014-05-18 17:00:00,59.52889185\n2014-05-18 18:00:00,59.31666076\n2014-05-18 19:00:00,59.14006513\n2014-05-18 20:00:00,59.33578729\n2014-05-18 21:00:00,58.5039748\n2014-05-18 22:00:00,59.10760819\n2014-05-18 23:00:00,58.16034228\n2014-05-19 00:00:00,58.42363855\n2014-05-19 01:00:00,57.8619057\n2014-05-19 02:00:00,58.63929497\n2014-05-19 03:00:00,59.07469099\n2014-05-19 04:00:00,60.49092523\n2014-05-19 05:00:00,59.71185823\n2014-05-19 06:00:00,60.37589367\n2014-05-19 07:00:00,60.17109245\n2014-05-19 08:00:00,60.29668226\n2014-05-19 09:00:00,62.032778\n2014-05-19 10:00:00,63.30565358\n2014-05-19 11:00:00,66.46108503\n2014-05-19 12:00:00,68.26175947\n2014-05-19 13:00:00,70.71157984\n2014-05-19 14:00:00,71.27550282\n2014-05-19 15:00:00,72.16832368\n2014-05-19 16:00:00,71.18424703\n2014-05-19 17:00:00,72.14062818\n2014-05-19 18:00:00,71.21197512\n2014-05-19 19:00:00,69.21714746\n2014-05-19 20:00:00,68.35285951\n2014-05-19 21:00:00,65.94373646\n2014-05-19 22:00:00,63.16581259\n2014-05-19 23:00:00,63.4757356\n2014-05-20 00:00:00,63.46895245\n2014-05-20 01:00:00,61.42920712\n2014-05-20 02:00:00,61.67708270000001\n2014-05-20 03:00:00,61.78693595\n2014-05-20 04:00:00,60.88555024\n2014-05-20 05:00:00,61.49993807\n2014-05-20 06:00:00,61.05565421\n2014-05-20 07:00:00,61.47083928\n2014-05-20 08:00:00,62.30626718\n2014-05-20 09:00:00,62.87057976\n2014-05-20 10:00:00,63.400864500000004\n2014-05-20 11:00:00,67.54217170000001\n2014-05-20 12:00:00,69.71421777\n2014-05-20 13:00:00,69.51084605\n2014-05-20 14:00:00,71.30924261\n2014-05-20 15:00:00,71.54100964\n2014-05-20 16:00:00,72.16153754\n2014-05-20 17:00:00,70.88654096\n2014-05-20 18:00:00,70.91172121\n2014-05-20 19:00:00,72.16415303\n2014-05-20 20:00:00,70.52750726\n2014-05-20 21:00:00,67.87157133\n2014-05-20 22:00:00,68.33303676\n2014-05-20 23:00:00,66.90035458\n2014-05-21 00:00:00,66.99561858\n2014-05-21 01:00:00,65.40626786\n2014-05-21 02:00:00,64.32359927\n2014-05-21 03:00:00,63.56365044\n2014-05-21 04:00:00,64.11854793\n2014-05-21 05:00:00,62.70245453\n2014-05-21 06:00:00,62.74071071\n2014-05-21 07:00:00,64.71093807\n2014-05-21 08:00:00,65.83512160000001\n2014-05-21 09:00:00,66.70320421\n2014-05-21 10:00:00,68.58472225\n2014-05-21 11:00:00,71.45729537\n2014-05-21 12:00:00,71.66573622\n2014-05-21 13:00:00,72.395749\n2014-05-21 14:00:00,73.90430952\n2014-05-21 15:00:00,74.74593843\n2014-05-21 16:00:00,74.30063758\n2014-05-21 17:00:00,72.59432304\n2014-05-21 18:00:00,72.22398046\n2014-05-21 19:00:00,72.32603021\n2014-05-21 20:00:00,73.63394052\n2014-05-21 21:00:00,71.85085806\n2014-05-21 22:00:00,70.92319988\n2014-05-21 23:00:00,69.67101298\n2014-05-22 00:00:00,69.59055937\n2014-05-22 01:00:00,68.10096848\n2014-05-22 02:00:00,67.59063877\n2014-05-22 03:00:00,67.28802796\n2014-05-22 04:00:00,65.50415242\n2014-05-22 05:00:00,64.98749725\n2014-05-22 06:00:00,63.84289079999999\n2014-05-22 07:00:00,65.27590436\n2014-05-22 08:00:00,65.24654655\n2014-05-22 09:00:00,69.10167387\n2014-05-22 10:00:00,70.78848187\n2014-05-22 11:00:00,71.86870384\n2014-05-22 12:00:00,71.94794239\n2014-05-22 13:00:00,73.677598\n2014-05-22 14:00:00,72.98770276\n2014-05-22 15:00:00,74.42875737\n2014-05-22 16:00:00,72.64701052\n2014-05-22 17:00:00,73.13696747\n2014-05-22 18:00:00,72.89262523\n2014-05-22 19:00:00,71.9456771\n2014-05-22 20:00:00,72.75306445\n2014-05-22 21:00:00,72.16946467\n2014-05-22 22:00:00,70.85768581\n2014-05-22 23:00:00,68.89846747\n2014-05-23 00:00:00,69.76426088\n2014-05-23 01:00:00,67.22274865\n2014-05-23 02:00:00,66.84469742\n2014-05-23 03:00:00,65.7499409\n2014-05-23 04:00:00,65.72828867\n2014-05-23 05:00:00,64.56403526\n2014-05-23 06:00:00,64.82619471\n2014-05-23 07:00:00,65.55274567\n2014-05-23 08:00:00,66.27026002\n2014-05-23 09:00:00,68.11559824\n2014-05-23 10:00:00,69.89230339\n2014-05-23 11:00:00,70.85563315\n2014-05-23 12:00:00,72.70590985\n2014-05-23 13:00:00,73.19388671\n2014-05-23 14:00:00,71.69026293\n2014-05-23 15:00:00,71.85985178\n2014-05-23 16:00:00,73.21648743\n2014-05-23 17:00:00,72.87018134\n2014-05-23 18:00:00,72.78601953\n2014-05-23 19:00:00,72.3176002\n2014-05-23 20:00:00,72.96734992\n2014-05-23 21:00:00,72.9728198\n2014-05-23 22:00:00,71.42381462\n2014-05-23 23:00:00,71.5294155\n2014-05-24 00:00:00,70.53019592\n2014-05-24 01:00:00,67.44737298\n2014-05-24 02:00:00,68.10673337\n2014-05-24 03:00:00,66.54488604\n2014-05-24 04:00:00,65.99044378\n2014-05-24 05:00:00,65.57383653\n2014-05-24 06:00:00,63.7342402\n2014-05-24 07:00:00,64.60030306\n2014-05-24 08:00:00,63.81887969\n2014-05-24 09:00:00,62.53317986\n2014-05-24 10:00:00,62.63998719\n2014-05-24 11:00:00,63.36766655\n2014-05-24 12:00:00,62.24567585\n2014-05-24 13:00:00,62.11892222\n2014-05-24 14:00:00,60.93392081\n2014-05-24 15:00:00,60.93279727\n2014-05-24 16:00:00,61.2825587\n2014-05-24 17:00:00,61.86767484\n2014-05-24 18:00:00,61.09664628\n2014-05-24 19:00:00,62.27844332\n2014-05-24 20:00:00,61.90070789\n2014-05-24 21:00:00,62.39310154\n2014-05-24 22:00:00,62.30137458\n2014-05-24 23:00:00,62.56461867\n2014-05-25 00:00:00,62.72498472\n2014-05-25 01:00:00,61.83288929\n2014-05-25 02:00:00,61.81999904\n2014-05-25 03:00:00,61.63311346\n2014-05-25 04:00:00,62.64551718\n2014-05-25 05:00:00,62.36561658\n2014-05-25 06:00:00,60.95432355\n2014-05-25 07:00:00,62.2887861\n2014-05-25 08:00:00,61.79099234\n2014-05-25 09:00:00,61.2350892\n2014-05-25 10:00:00,61.70115537\n2014-05-25 11:00:00,62.50943034\n2014-05-25 12:00:00,61.01775642\n2014-05-25 13:00:00,62.17679039\n2014-05-25 14:00:00,62.78656524\n2014-05-25 15:00:00,61.01764809\n2014-05-25 16:00:00,62.19066364\n2014-05-25 17:00:00,62.3200289\n2014-05-25 18:00:00,61.24446489\n2014-05-25 19:00:00,61.04660004\n2014-05-25 20:00:00,62.45615333\n2014-05-25 21:00:00,60.84765432\n2014-05-25 22:00:00,62.16201772\n2014-05-25 23:00:00,61.47244327\n2014-05-26 00:00:00,62.07873026\n2014-05-26 01:00:00,61.76786\n2014-05-26 02:00:00,61.14309718\n2014-05-26 03:00:00,61.00938428\n2014-05-26 04:00:00,61.95202076\n2014-05-26 05:00:00,62.03764829\n2014-05-26 06:00:00,61.473338899999995\n2014-05-26 07:00:00,61.51732548\n2014-05-26 08:00:00,63.77163674\n2014-05-26 09:00:00,66.16135606\n2014-05-26 10:00:00,68.07227638\n2014-05-26 11:00:00,69.81799259\n2014-05-26 12:00:00,72.0269253\n2014-05-26 13:00:00,71.77669121\n2014-05-26 14:00:00,72.19859519\n2014-05-26 15:00:00,72.23311654\n2014-05-26 16:00:00,72.51360720000002\n2014-05-26 17:00:00,73.97990891\n2014-05-26 18:00:00,72.13547844\n2014-05-26 19:00:00,73.53223604\n2014-05-26 20:00:00,71.63600005\n2014-05-26 21:00:00,70.98695943\n2014-05-26 22:00:00,69.02377801\n2014-05-26 23:00:00,68.51109537\n2014-05-27 00:00:00,67.10193816\n2014-05-27 01:00:00,66.822098\n2014-05-27 02:00:00,65.9294706\n2014-05-27 03:00:00,67.12169762\n2014-05-27 04:00:00,65.4066128\n2014-05-27 05:00:00,64.94669438\n2014-05-27 06:00:00,64.01596424\n2014-05-27 07:00:00,63.637964399999994\n2014-05-27 08:00:00,64.58194931\n2014-05-27 09:00:00,66.86987932\n2014-05-27 10:00:00,70.10010407\n2014-05-27 11:00:00,71.53161261\n2014-05-27 12:00:00,72.17782106\n2014-05-27 13:00:00,72.68078037\n2014-05-27 14:00:00,71.96861391\n2014-05-27 15:00:00,72.11443201\n2014-05-27 16:00:00,73.00783047\n2014-05-27 17:00:00,73.08768457\n2014-05-27 18:00:00,71.32243816\n2014-05-27 19:00:00,71.49022791\n2014-05-27 20:00:00,71.8134752\n2014-05-27 21:00:00,69.75022022\n2014-05-27 22:00:00,69.68719735\n2014-05-27 23:00:00,68.98695874\n2014-05-28 00:00:00,68.63483818\n2014-05-28 01:00:00,67.0000815\n2014-05-28 02:00:00,66.52891628\n2014-05-28 03:00:00,67.65632279\n2014-05-28 04:00:00,65.74329837\n2014-05-28 05:00:00,66.24037883\n2014-05-28 06:00:00,64.78402266\n2014-05-28 07:00:00,65.6458741\n2014-05-28 08:00:00,67.47256826\n2014-05-28 09:00:00,68.03307954\n2014-05-28 10:00:00,70.45571697\n2014-05-28 11:00:00,72.37020644\n2014-05-28 12:00:00,72.17295622\n2014-05-28 13:00:00,72.04656545\n2014-05-28 14:00:00,71.82522648\n2014-05-28 15:00:00,72.58408858\n"
  },
  {
    "path": "workspace/anomaly_detector/datasets/selected/level_change/ec2_cpu_utilization_825cc2.csv",
    "content": "timestamp,value\n2014-04-10 00:04:00,91.958\n2014-04-10 00:09:00,94.79799999999999\n2014-04-10 00:14:00,92.208\n2014-04-10 00:19:00,93.72200000000001\n2014-04-10 00:24:00,93.042\n2014-04-10 00:29:00,92.958\n2014-04-10 00:34:00,95.708\n2014-04-10 00:39:00,95.25\n2014-04-10 00:44:00,94.458\n2014-04-10 00:49:00,92.75\n2014-04-10 00:54:00,94.208\n2014-04-10 00:59:00,92.75\n2014-04-10 01:04:00,94.376\n2014-04-10 01:09:00,92.792\n2014-04-10 01:14:00,91.666\n2014-04-10 01:19:00,87.542\n2014-04-10 01:24:00,90.75\n2014-04-10 01:29:00,91.65\n2014-04-10 01:34:00,90.06200000000004\n2014-04-10 01:39:00,93.416\n2014-04-10 01:44:00,89.904\n2014-04-10 01:49:00,90.542\n2014-04-10 01:54:00,90.62799999999999\n2014-04-10 01:59:00,91.166\n2014-04-10 02:04:00,90.5\n2014-04-10 02:09:00,89.166\n2014-04-10 02:14:00,90.292\n2014-04-10 02:19:00,90.208\n2014-04-10 02:24:00,93.626\n2014-04-10 02:29:00,93.624\n2014-04-10 02:34:00,93.756\n2014-04-10 02:39:00,93.542\n2014-04-10 02:44:00,92.042\n2014-04-10 02:49:00,90.93799999999999\n2014-04-10 02:54:00,91.376\n2014-04-10 02:59:00,92.666\n2014-04-10 03:04:00,94.42\n2014-04-10 03:09:00,95.584\n2014-04-10 03:19:00,90.62\n2014-04-10 03:24:00,93.478\n2014-04-10 03:29:00,94.126\n2014-04-10 03:34:00,93.338\n2014-04-10 03:39:00,93.458\n2014-04-10 03:44:00,92.166\n2014-04-10 03:49:00,91.584\n2014-04-10 03:54:00,94.33\n2014-04-10 03:59:00,95.084\n2014-04-10 04:04:00,93.958\n2014-04-10 04:09:00,94.714\n2014-04-10 04:14:00,92.23200000000001\n2014-04-10 04:19:00,95.2\n2014-04-10 04:24:00,92.458\n2014-04-10 04:29:00,94.444\n2014-04-10 04:34:00,86.736\n2014-04-10 04:39:00,93.072\n2014-04-10 04:44:00,95.876\n2014-04-10 04:49:00,93.994\n2014-04-10 04:54:00,94.104\n2014-04-10 04:59:00,93.75\n2014-04-10 05:04:00,90.852\n2014-04-10 05:09:00,89.584\n2014-04-10 05:14:00,94.542\n2014-04-10 05:19:00,91.97399999999999\n2014-04-10 05:24:00,93.0\n2014-04-10 05:29:00,92.262\n2014-04-10 05:34:00,93.25\n2014-04-10 05:39:00,93.624\n2014-04-10 05:44:00,93.436\n2014-04-10 05:49:00,92.774\n2014-04-10 05:54:00,91.624\n2014-04-10 05:59:00,93.042\n2014-04-10 06:04:00,91.542\n2014-04-10 06:09:00,93.74799999999999\n2014-04-10 06:14:00,93.042\n2014-04-10 06:19:00,92.8\n2014-04-10 06:24:00,90.11\n2014-04-10 06:29:00,94.64399999999999\n2014-04-10 06:34:00,90.542\n2014-04-10 06:39:00,93.292\n2014-04-10 06:44:00,91.14\n2014-04-10 06:49:00,91.126\n2014-04-10 06:54:00,91.5\n2014-04-10 06:59:00,95.042\n2014-04-10 07:04:00,95.712\n2014-04-10 07:09:00,91.506\n2014-04-10 07:14:00,94.9625\n2014-04-10 07:19:00,91.848\n2014-04-10 07:24:00,92.416\n2014-04-10 07:29:00,95.126\n2014-04-10 07:34:00,93.584\n2014-04-10 07:39:00,93.834\n2014-04-10 07:44:00,94.708\n2014-04-10 07:49:00,94.5\n2014-04-10 07:54:00,93.45200000000001\n2014-04-10 07:59:00,88.086\n2014-04-10 08:04:00,91.08\n2014-04-10 08:09:00,89.584\n2014-04-10 08:14:00,91.238\n2014-04-10 08:19:00,91.932\n2014-04-10 08:24:00,89.458\n2014-04-10 08:29:00,87.75\n2014-04-10 08:34:00,92.666\n2014-04-10 08:39:00,94.5\n2014-04-10 08:44:00,92.162\n2014-04-10 08:49:00,92.648\n2014-04-10 08:54:00,94.352\n2014-04-10 08:59:00,92.916\n2014-04-10 09:04:00,90.874\n2014-04-10 09:09:00,92.334\n2014-04-10 09:14:00,93.75\n2014-04-10 09:19:00,93.77\n2014-04-10 09:24:00,93.48\n2014-04-10 09:29:00,94.22\n2014-04-10 09:34:00,94.014\n2014-04-10 09:39:00,94.666\n2014-04-10 09:44:00,94.516\n2014-04-10 09:49:00,96.75\n2014-04-10 09:54:00,93.834\n2014-04-10 09:59:00,91.666\n2014-04-10 10:04:00,90.8\n2014-04-10 10:09:00,96.042\n2014-04-10 10:14:00,85.42200000000003\n2014-04-10 10:19:00,91.73\n2014-04-10 10:24:00,90.61\n2014-04-10 10:29:00,90.25\n2014-04-10 10:34:00,90.03399999999998\n2014-04-10 10:39:00,89.33200000000002\n2014-04-10 10:44:00,91.766\n2014-04-10 10:49:00,94.084\n2014-04-10 10:54:00,91.6525\n2014-04-10 10:59:00,93.75\n2014-04-10 11:04:00,93.71799999999999\n2014-04-10 11:09:00,94.11200000000001\n2014-04-10 11:14:00,93.46600000000001\n2014-04-10 11:19:00,95.416\n2014-04-10 11:24:00,94.5\n2014-04-10 11:29:00,96.67399999999999\n2014-04-10 11:34:00,93.212\n2014-04-10 11:39:00,91.166\n2014-04-10 11:44:00,93.678\n2014-04-10 11:49:00,93.55\n2014-04-10 11:54:00,93.374\n2014-04-10 11:59:00,95.554\n2014-04-10 12:04:00,94.292\n2014-04-10 12:09:00,90.164\n2014-04-10 12:14:00,88.75\n2014-04-10 12:19:00,92.458\n2014-04-10 12:24:00,96.21\n2014-04-10 12:29:00,91.646\n2014-04-10 12:34:00,94.792\n2014-04-10 12:39:00,92.53399999999999\n2014-04-10 12:44:00,89.084\n2014-04-10 12:49:00,91.75\n2014-04-10 12:54:00,92.75\n2014-04-10 12:59:00,89.568\n2014-04-10 13:04:00,90.65799999999999\n2014-04-10 13:09:00,88.024\n2014-04-10 13:14:00,91.542\n2014-04-10 13:19:00,94.25\n2014-04-10 13:24:00,94.124\n2014-04-10 13:29:00,91.708\n2014-04-10 13:34:00,92.584\n2014-04-10 13:39:00,92.63799999999999\n2014-04-10 13:44:00,93.794\n2014-04-10 13:49:00,96.514\n2014-04-10 13:54:00,95.20200000000001\n2014-04-10 13:59:00,96.18799999999999\n2014-04-10 14:04:00,89.3\n2014-04-10 14:09:00,90.74600000000001\n2014-04-10 14:14:00,88.25\n2014-04-10 14:19:00,88.834\n2014-04-10 14:24:00,89.834\n2014-04-10 14:29:00,93.5\n2014-04-10 14:34:00,95.5\n2014-04-10 14:39:00,89.542\n2014-04-10 14:44:00,89.052\n2014-04-10 14:49:00,87.454\n2014-04-10 14:54:00,86.876\n2014-04-10 14:59:00,86.958\n2014-04-10 15:04:00,89.928\n2014-04-10 15:09:00,90.5\n2014-04-10 15:14:00,90.124\n2014-04-10 15:19:00,90.58\n2014-04-10 15:24:00,92.0\n2014-04-10 15:29:00,88.708\n2014-04-10 15:34:00,89.962\n2014-04-10 15:39:00,92.50200000000001\n2014-04-10 15:44:00,94.0\n2014-04-10 15:49:00,94.804\n2014-04-10 15:54:00,89.542\n2014-04-10 15:59:00,94.0\n2014-04-10 16:04:00,94.292\n2014-04-10 16:09:00,93.916\n2014-04-10 16:14:00,91.458\n2014-04-10 16:19:00,92.14\n2014-04-10 16:24:00,93.208\n2014-04-10 16:29:00,96.292\n2014-04-10 16:34:00,90.666\n2014-04-10 16:39:00,89.458\n2014-04-10 16:44:00,95.292\n2014-04-10 16:49:00,95.626\n2014-04-10 16:54:00,93.0\n2014-04-10 16:59:00,93.75\n2014-04-10 17:04:00,95.292\n2014-04-10 17:09:00,95.208\n2014-04-10 17:14:00,95.542\n2014-04-10 17:19:00,93.0\n2014-04-10 17:24:00,92.236\n2014-04-10 17:29:00,94.25\n2014-04-10 17:34:00,92.28200000000001\n2014-04-10 17:39:00,94.714\n2014-04-10 17:44:00,94.126\n2014-04-10 17:49:00,96.25\n2014-04-10 17:54:00,93.834\n2014-04-10 17:59:00,94.46\n2014-04-10 18:04:00,95.542\n2014-04-10 18:09:00,98.042\n2014-04-10 18:14:00,95.766\n2014-04-10 18:19:00,93.458\n2014-04-10 18:24:00,92.85799999999999\n2014-04-10 18:29:00,95.584\n2014-04-10 18:34:00,93.12799999999999\n2014-04-10 18:39:00,91.88799999999999\n2014-04-10 18:44:00,92.984\n2014-04-10 18:49:00,94.32600000000001\n2014-04-10 18:54:00,95.876\n2014-04-10 18:59:00,93.584\n2014-04-10 19:04:00,95.15799999999999\n2014-04-10 19:09:00,95.416\n2014-04-10 19:14:00,93.166\n2014-04-10 19:19:00,96.25\n2014-04-10 19:24:00,93.376\n2014-04-10 19:29:00,93.084\n2014-04-10 19:34:00,93.146\n2014-04-10 19:39:00,95.596\n2014-04-10 19:44:00,94.336\n2014-04-10 19:49:00,91.458\n2014-04-10 19:54:00,93.292\n2014-04-10 19:59:00,95.126\n2014-04-10 20:04:00,92.976\n2014-04-10 20:09:00,94.32600000000001\n2014-04-10 20:14:00,89.538\n2014-04-10 20:19:00,92.12799999999999\n2014-04-10 20:24:00,94.14399999999999\n2014-04-10 20:29:00,89.488\n2014-04-10 20:34:00,90.314\n2014-04-10 20:39:00,95.0\n2014-04-10 20:44:00,93.208\n2014-04-10 20:49:00,94.042\n2014-04-10 20:54:00,92.626\n2014-04-10 20:59:00,95.398\n2014-04-10 21:04:00,93.52799999999999\n2014-04-10 21:09:00,93.5\n2014-04-10 21:14:00,95.63\n2014-04-10 21:19:00,93.292\n2014-04-10 21:24:00,95.292\n2014-04-10 21:29:00,95.01\n2014-04-10 21:34:00,92.384\n2014-04-10 21:39:00,93.75\n2014-04-10 21:44:00,96.124\n2014-04-10 21:49:00,93.42\n2014-04-10 21:54:00,91.854\n2014-04-10 21:59:00,90.5\n2014-04-10 22:04:00,92.666\n2014-04-10 22:09:00,93.956\n2014-04-10 22:14:00,91.792\n2014-04-10 22:19:00,95.0\n2014-04-10 22:24:00,95.626\n2014-04-10 22:29:00,95.084\n2014-04-10 22:34:00,94.834\n2014-04-10 22:39:00,95.566\n2014-04-10 22:44:00,94.454\n2014-04-10 22:49:00,95.0\n2014-04-10 22:54:00,93.334\n2014-04-10 22:59:00,94.10799999999999\n2014-04-10 23:04:00,93.596\n2014-04-10 23:09:00,92.92200000000001\n2014-04-10 23:14:00,92.414\n2014-04-10 23:19:00,92.478\n2014-04-10 23:24:00,92.22\n2014-04-10 23:29:00,93.876\n2014-04-10 23:34:00,95.58\n2014-04-10 23:39:00,95.166\n2014-04-10 23:44:00,94.5\n2014-04-10 23:49:00,95.04799999999999\n2014-04-10 23:54:00,93.42399999999999\n2014-04-10 23:59:00,93.01\n2014-04-11 00:04:00,93.774\n2014-04-11 00:09:00,95.704\n2014-04-11 00:14:00,95.21600000000001\n2014-04-11 00:19:00,93.572\n2014-04-11 00:24:00,92.056\n2014-04-11 00:29:00,93.904\n2014-04-11 00:34:00,95.792\n2014-04-11 00:39:00,93.374\n2014-04-11 00:44:00,91.666\n2014-04-11 00:49:00,95.708\n2014-04-11 00:54:00,93.042\n2014-04-11 00:59:00,96.0\n2014-04-11 01:04:00,95.10799999999999\n2014-04-11 01:09:00,93.77799999999999\n2014-04-11 01:14:00,91.71600000000001\n2014-04-11 01:19:00,91.666\n2014-04-11 01:24:00,95.75\n2014-04-11 01:29:00,97.042\n2014-04-11 01:34:00,93.624\n2014-04-11 01:39:00,93.4\n2014-04-11 01:44:00,89.75399999999998\n2014-04-11 01:49:00,94.334\n2014-04-11 01:54:00,96.522\n2014-04-11 01:59:00,93.516\n2014-04-11 02:04:00,95.25\n2014-04-11 02:09:00,95.914\n2014-04-11 02:14:00,97.084\n2014-04-11 02:19:00,94.91799999999999\n2014-04-11 02:24:00,93.766\n2014-04-11 02:29:00,96.056\n2014-04-11 02:34:00,96.376\n2014-04-11 02:39:00,96.166\n2014-04-11 02:44:00,94.166\n2014-04-11 02:49:00,96.49600000000001\n2014-04-11 02:54:00,95.042\n2014-04-11 02:59:00,95.584\n2014-04-11 03:04:00,96.726\n2014-04-11 03:09:00,96.056\n2014-04-11 03:14:00,95.17200000000001\n2014-04-11 03:19:00,93.876\n2014-04-11 03:24:00,95.958\n2014-04-11 03:29:00,95.708\n2014-04-11 03:34:00,94.008\n2014-04-11 03:39:00,92.084\n2014-04-11 03:44:00,96.932\n2014-04-11 03:49:00,92.79\n2014-04-11 03:54:00,94.006\n2014-04-11 03:59:00,94.874\n2014-04-11 04:04:00,93.126\n2014-04-11 04:09:00,95.834\n2014-04-11 04:14:00,93.624\n2014-04-11 04:19:00,95.554\n2014-04-11 04:24:00,95.758\n2014-04-11 04:29:00,95.402\n2014-04-11 04:34:00,93.916\n2014-04-11 04:39:00,98.042\n2014-04-11 04:44:00,93.29\n2014-04-11 04:49:00,92.792\n2014-04-11 04:54:00,97.374\n2014-04-11 04:59:00,97.374\n2014-04-11 05:04:00,96.38600000000001\n2014-04-11 05:09:00,95.584\n2014-04-11 05:14:00,96.618\n2014-04-11 05:19:00,94.5\n2014-04-11 05:24:00,93.792\n2014-04-11 05:29:00,96.084\n2014-04-11 05:34:00,97.584\n2014-04-11 05:39:00,97.21600000000001\n2014-04-11 05:44:00,92.916\n2014-04-11 05:49:00,97.042\n2014-04-11 05:54:00,97.166\n2014-04-11 05:59:00,94.852\n2014-04-11 06:04:00,92.626\n2014-04-11 06:09:00,96.916\n2014-04-11 06:14:00,95.416\n2014-04-11 06:19:00,92.77\n2014-04-11 06:24:00,93.626\n2014-04-11 06:29:00,95.708\n2014-04-11 06:34:00,94.52799999999999\n2014-04-11 06:39:00,93.56200000000001\n2014-04-11 06:44:00,94.102\n2014-04-11 06:49:00,93.986\n2014-04-11 06:54:00,94.584\n2014-04-11 06:59:00,92.22399999999999\n2014-04-11 07:04:00,92.958\n2014-04-11 07:09:00,93.042\n2014-04-11 07:14:00,88.542\n2014-04-11 07:19:00,92.042\n2014-04-11 07:24:00,94.542\n2014-04-11 07:29:00,95.958\n2014-04-11 07:34:00,96.876\n2014-04-11 07:39:00,94.708\n2014-04-11 07:44:00,94.0\n2014-04-11 07:49:00,93.958\n2014-04-11 07:54:00,95.34200000000001\n2014-04-11 07:59:00,91.304\n2014-04-11 08:04:00,92.352\n2014-04-11 08:09:00,90.41\n2014-04-11 08:14:00,92.476\n2014-04-11 08:19:00,94.71600000000001\n2014-04-11 08:24:00,94.542\n2014-04-11 08:29:00,93.042\n2014-04-11 08:34:00,91.292\n2014-04-11 08:39:00,95.604\n2014-04-11 08:44:00,96.78200000000001\n2014-04-11 08:49:00,96.458\n2014-04-11 08:54:00,94.916\n2014-04-11 08:59:00,92.916\n2014-04-11 09:04:00,92.416\n2014-04-11 09:09:00,96.428\n2014-04-11 09:14:00,95.374\n2014-04-11 09:19:00,93.10600000000001\n2014-04-11 09:24:00,91.39\n2014-04-11 09:29:00,93.374\n2014-04-11 09:34:00,92.744\n2014-04-11 09:39:00,96.12\n2014-04-11 09:44:00,95.542\n2014-04-11 09:49:00,96.4\n2014-04-11 09:54:00,94.24600000000001\n2014-04-11 09:59:00,93.13\n2014-04-11 10:04:00,92.404\n2014-04-11 10:09:00,96.166\n2014-04-11 10:14:00,93.594\n2014-04-11 10:19:00,89.416\n2014-04-11 10:24:00,94.084\n2014-04-11 10:29:00,94.524\n2014-04-11 10:34:00,94.492\n2014-04-11 10:39:00,93.584\n2014-04-11 10:44:00,92.958\n2014-04-11 10:49:00,92.75\n2014-04-11 10:54:00,93.416\n2014-04-11 10:59:00,94.75\n2014-04-11 11:04:00,93.67200000000001\n2014-04-11 11:09:00,93.374\n2014-04-11 11:14:00,95.12200000000001\n2014-04-11 11:19:00,92.666\n2014-04-11 11:24:00,95.666\n2014-04-11 11:29:00,96.834\n2014-04-11 11:34:00,94.256\n2014-04-11 11:39:00,93.39399999999999\n2014-04-11 11:44:00,94.126\n2014-04-11 11:49:00,96.17200000000001\n2014-04-11 11:54:00,93.7\n2014-04-11 11:59:00,93.064\n2014-04-11 12:04:00,96.0\n2014-04-11 12:09:00,95.436\n2014-04-11 12:14:00,95.98\n2014-04-11 12:19:00,94.53399999999999\n2014-04-11 12:24:00,87.5\n2014-04-11 12:29:00,91.208\n2014-04-11 12:34:00,93.39200000000001\n2014-04-11 12:39:00,91.524\n2014-04-11 12:44:00,93.83200000000001\n2014-04-11 12:49:00,90.66799999999999\n2014-04-11 12:54:00,92.25\n2014-04-11 12:59:00,93.99600000000001\n2014-04-11 13:04:00,91.5\n2014-04-11 13:09:00,92.816\n2014-04-11 13:14:00,91.148\n2014-04-11 13:19:00,89.06200000000004\n2014-04-11 13:24:00,91.1\n2014-04-11 13:29:00,93.0\n2014-04-11 13:34:00,87.834\n2014-04-11 13:39:00,90.584\n2014-04-11 13:44:00,92.624\n2014-04-11 13:49:00,89.292\n2014-04-11 13:54:00,91.416\n2014-04-11 13:59:00,91.624\n2014-04-11 14:04:00,88.5\n2014-04-11 14:09:00,91.5\n2014-04-11 14:14:00,93.126\n2014-04-11 14:19:00,91.536\n2014-04-11 14:24:00,92.89200000000001\n2014-04-11 14:29:00,89.35\n2014-04-11 14:34:00,88.584\n2014-04-11 14:39:00,89.52799999999998\n2014-04-11 14:44:00,89.042\n2014-04-11 14:49:00,92.55\n2014-04-11 14:54:00,90.712\n2014-04-11 14:59:00,92.208\n2014-04-11 15:04:00,93.084\n2014-04-11 15:09:00,90.82\n2014-04-11 15:14:00,88.542\n2014-04-11 15:19:00,89.75\n2014-04-11 15:24:00,96.708\n2014-04-11 15:29:00,93.75\n2014-04-11 15:34:00,92.458\n2014-04-11 15:39:00,94.53399999999999\n2014-04-11 15:44:00,95.454\n2014-04-11 15:49:00,92.084\n2014-04-11 15:54:00,92.584\n2014-04-11 15:59:00,90.124\n2014-04-11 16:04:00,88.48200000000001\n2014-04-11 16:09:00,89.376\n2014-04-11 16:14:00,90.626\n2014-04-11 16:19:00,86.064\n2014-04-11 16:24:00,89.012\n2014-04-11 16:29:00,87.656\n2014-04-11 16:34:00,91.634\n2014-04-11 16:39:00,87.08\n2014-04-11 16:44:00,88.958\n2014-04-11 16:49:00,90.084\n2014-04-11 16:54:00,92.126\n2014-04-11 16:59:00,93.624\n2014-04-11 17:04:00,88.416\n2014-04-11 17:09:00,90.75\n2014-04-11 17:14:00,90.104\n2014-04-11 17:19:00,90.5\n2014-04-11 17:24:00,88.916\n2014-04-11 17:29:00,88.666\n2014-04-11 17:34:00,90.39399999999999\n2014-04-11 17:39:00,92.666\n2014-04-11 17:44:00,92.75\n2014-04-11 17:49:00,90.334\n2014-04-11 17:54:00,92.25\n2014-04-11 17:59:00,97.084\n2014-04-11 18:04:00,93.012\n2014-04-11 18:09:00,94.212\n2014-04-11 18:14:00,95.61200000000001\n2014-04-11 18:19:00,95.834\n2014-04-11 18:24:00,96.084\n2014-04-11 18:29:00,93.75399999999999\n2014-04-11 18:34:00,95.042\n2014-04-11 18:39:00,95.75\n2014-04-11 18:44:00,95.834\n2014-04-11 18:49:00,96.292\n2014-04-11 18:54:00,95.91799999999999\n2014-04-11 18:59:00,95.334\n2014-04-11 19:04:00,93.292\n2014-04-11 19:09:00,95.376\n2014-04-11 19:14:00,95.626\n2014-04-11 19:19:00,96.67399999999999\n2014-04-11 19:24:00,92.43\n2014-04-11 19:29:00,93.542\n2014-04-11 19:34:00,94.958\n2014-04-11 19:39:00,96.416\n2014-04-11 19:44:00,96.818\n2014-04-11 19:49:00,94.074\n2014-04-11 19:54:00,94.98\n2014-04-11 19:59:00,97.25\n2014-04-11 20:04:00,94.96\n2014-04-11 20:09:00,96.708\n2014-04-11 20:14:00,95.374\n2014-04-11 20:19:00,94.376\n2014-04-11 20:24:00,93.086\n2014-04-11 20:29:00,93.458\n2014-04-11 20:34:00,94.958\n2014-04-11 20:39:00,95.71799999999999\n2014-04-11 20:44:00,95.14200000000001\n2014-04-11 20:49:00,95.494\n2014-04-11 20:54:00,93.792\n2014-04-11 20:59:00,95.376\n2014-04-11 21:04:00,92.14399999999999\n2014-04-11 21:09:00,93.46600000000001\n2014-04-11 21:14:00,94.64200000000001\n2014-04-11 21:19:00,93.89399999999999\n2014-04-11 21:24:00,93.542\n2014-04-11 21:29:00,94.208\n2014-04-11 21:34:00,91.166\n2014-04-11 21:39:00,90.126\n2014-04-11 21:44:00,95.618\n2014-04-11 21:49:00,91.71\n2014-04-11 21:54:00,94.014\n2014-04-11 21:59:00,93.958\n2014-04-11 22:04:00,90.75\n2014-04-11 22:09:00,93.708\n2014-04-11 22:14:00,89.78399999999998\n2014-04-11 22:19:00,92.874\n2014-04-11 22:24:00,91.184\n2014-04-11 22:29:00,94.916\n2014-04-11 22:34:00,89.666\n2014-04-11 22:39:00,90.458\n2014-04-11 22:44:00,90.084\n2014-04-11 22:49:00,91.04799999999999\n2014-04-11 22:54:00,90.792\n2014-04-11 22:59:00,90.626\n2014-04-11 23:04:00,88.708\n2014-04-11 23:09:00,92.33\n2014-04-11 23:14:00,91.292\n2014-04-11 23:19:00,93.416\n2014-04-11 23:24:00,90.5\n2014-04-11 23:29:00,89.874\n2014-04-11 23:34:00,91.124\n2014-04-11 23:39:00,91.584\n2014-04-11 23:44:00,94.708\n2014-04-11 23:49:00,91.5\n2014-04-11 23:54:00,91.446\n2014-04-11 23:59:00,90.708\n2014-04-12 00:04:00,93.32799999999999\n2014-04-12 00:09:00,90.86399999999999\n2014-04-12 00:14:00,96.836\n2014-04-12 00:19:00,94.402\n2014-04-12 00:24:00,95.47\n2014-04-12 00:29:00,94.416\n2014-04-12 00:34:00,96.176\n2014-04-12 00:39:00,95.792\n2014-04-12 00:44:00,92.2\n2014-04-12 00:49:00,95.962\n2014-04-12 00:54:00,96.79799999999999\n2014-04-12 00:59:00,91.95200000000001\n2014-04-12 01:04:00,91.148\n2014-04-12 01:09:00,96.458\n2014-04-12 01:14:00,95.042\n2014-04-12 01:19:00,95.458\n2014-04-12 01:24:00,95.162\n2014-04-12 01:29:00,92.084\n2014-04-12 01:34:00,96.97\n2014-04-12 01:39:00,97.042\n2014-04-12 01:44:00,94.25\n2014-04-12 01:49:00,97.042\n2014-04-12 01:54:00,94.916\n2014-04-12 01:59:00,95.126\n2014-04-12 02:04:00,95.21\n2014-04-12 02:09:00,96.666\n2014-04-12 02:14:00,95.63\n2014-04-12 02:19:00,95.18799999999999\n2014-04-12 02:24:00,94.416\n2014-04-12 02:29:00,95.78\n2014-04-12 02:34:00,96.958\n2014-04-12 02:39:00,94.07600000000001\n2014-04-12 02:44:00,96.334\n2014-04-12 02:49:00,96.074\n2014-04-12 02:54:00,95.708\n2014-04-12 02:59:00,95.3\n2014-04-12 03:04:00,92.126\n2014-04-12 03:09:00,94.57600000000001\n2014-04-12 03:14:00,94.67399999999999\n2014-04-12 03:19:00,94.084\n2014-04-12 03:24:00,94.834\n2014-04-12 03:29:00,97.126\n2014-04-12 03:34:00,97.792\n2014-04-12 03:39:00,97.458\n2014-04-12 03:44:00,96.208\n2014-04-12 03:49:00,96.916\n2014-04-12 03:54:00,96.792\n2014-04-12 03:59:00,95.212\n2014-04-12 04:04:00,97.42\n2014-04-12 04:09:00,95.094\n2014-04-12 04:14:00,95.306\n2014-04-12 04:19:00,96.24600000000001\n2014-04-12 04:24:00,94.57600000000001\n2014-04-12 04:29:00,94.5\n2014-04-12 04:34:00,95.916\n2014-04-12 04:39:00,96.25\n2014-04-12 04:44:00,96.376\n2014-04-12 04:49:00,95.61399999999999\n2014-04-12 04:54:00,93.96799999999999\n2014-04-12 04:59:00,96.88\n2014-04-12 05:04:00,96.132\n2014-04-12 05:09:00,96.166\n2014-04-12 05:14:00,95.846\n2014-04-12 05:19:00,95.54799999999999\n2014-04-12 05:24:00,94.0\n2014-04-12 05:29:00,93.584\n2014-04-12 05:34:00,97.676\n2014-04-12 05:39:00,95.75\n2014-04-12 05:44:00,95.416\n2014-04-12 05:49:00,92.626\n2014-04-12 05:54:00,97.626\n2014-04-12 05:59:00,95.166\n2014-04-12 06:04:00,93.292\n2014-04-12 06:09:00,92.052\n2014-04-12 06:14:00,92.39200000000001\n2014-04-12 06:19:00,93.24799999999999\n2014-04-12 06:24:00,90.458\n2014-04-12 06:29:00,93.022\n2014-04-12 06:34:00,93.084\n2014-04-12 06:39:00,93.334\n2014-04-12 06:44:00,94.208\n2014-04-12 06:49:00,89.666\n2014-04-12 06:54:00,94.708\n2014-04-12 06:59:00,92.772\n2014-04-12 07:04:00,94.774\n2014-04-12 07:09:00,96.5\n2014-04-12 07:14:00,95.042\n2014-04-12 07:19:00,92.584\n2014-04-12 07:24:00,93.33\n2014-04-12 07:29:00,96.042\n2014-04-12 07:34:00,93.5\n2014-04-12 07:39:00,95.708\n2014-04-12 07:44:00,95.126\n2014-04-12 07:49:00,96.0\n2014-04-12 07:54:00,93.916\n2014-04-12 07:59:00,94.708\n2014-04-12 08:04:00,95.334\n2014-04-12 08:09:00,97.17\n2014-04-12 08:14:00,95.604\n2014-04-12 08:19:00,95.64399999999999\n2014-04-12 08:24:00,93.238\n2014-04-12 08:29:00,95.72\n2014-04-12 08:34:00,95.708\n2014-04-12 08:39:00,96.416\n2014-04-12 08:44:00,95.708\n2014-04-12 08:49:00,95.584\n2014-04-12 08:54:00,96.726\n2014-04-12 08:59:00,96.714\n2014-04-12 09:04:00,95.23200000000001\n2014-04-12 09:09:00,94.426\n2014-04-12 09:14:00,93.626\n2014-04-12 09:19:00,95.958\n2014-04-12 09:24:00,94.666\n2014-04-12 09:29:00,93.596\n2014-04-12 09:34:00,93.334\n2014-04-12 09:39:00,94.292\n2014-04-12 09:44:00,95.208\n2014-04-12 09:49:00,96.416\n2014-04-12 09:54:00,94.17200000000001\n2014-04-12 09:59:00,94.87\n2014-04-12 10:04:00,93.5\n2014-04-12 10:09:00,91.458\n2014-04-12 10:14:00,91.292\n2014-04-12 10:19:00,92.916\n2014-04-12 10:24:00,95.334\n2014-04-12 10:29:00,94.208\n2014-04-12 10:34:00,96.292\n2014-04-12 10:39:00,94.416\n2014-04-12 10:44:00,92.97399999999999\n2014-04-12 10:49:00,94.25\n2014-04-12 10:54:00,97.708\n2014-04-12 10:59:00,95.096\n2014-04-12 11:04:00,95.406\n2014-04-12 11:09:00,94.572\n2014-04-12 11:14:00,95.494\n2014-04-12 11:19:00,94.208\n2014-04-12 11:24:00,94.124\n2014-04-12 11:29:00,95.046\n2014-04-12 11:34:00,96.584\n2014-04-12 11:39:00,94.432\n2014-04-12 11:44:00,96.43\n2014-04-12 11:49:00,97.042\n2014-04-12 11:54:00,96.31200000000001\n2014-04-12 11:59:00,95.292\n2014-04-12 12:04:00,94.042\n2014-04-12 12:09:00,96.78\n2014-04-12 12:14:00,95.666\n2014-04-12 12:19:00,95.0\n2014-04-12 12:24:00,94.67200000000001\n2014-04-12 12:29:00,95.75\n2014-04-12 12:34:00,96.834\n2014-04-12 12:39:00,95.876\n2014-04-12 12:44:00,95.834\n2014-04-12 12:49:00,95.958\n2014-04-12 12:54:00,93.03\n2014-04-12 12:59:00,93.042\n2014-04-12 13:04:00,96.166\n2014-04-12 13:09:00,96.0\n2014-04-12 13:14:00,96.334\n2014-04-12 13:19:00,95.126\n2014-04-12 13:24:00,94.25\n2014-04-12 13:29:00,93.334\n2014-04-12 13:34:00,95.124\n2014-04-12 13:39:00,95.626\n2014-04-12 13:44:00,95.542\n2014-04-12 13:49:00,96.126\n2014-04-12 13:54:00,92.71799999999999\n2014-04-12 13:59:00,96.292\n2014-04-12 14:04:00,94.916\n2014-04-12 14:09:00,96.416\n2014-04-12 14:14:00,92.166\n2014-04-12 14:19:00,93.666\n2014-04-12 14:24:00,95.292\n2014-04-12 14:29:00,95.25\n2014-04-12 14:34:00,94.334\n2014-04-12 14:39:00,93.126\n2014-04-12 14:44:00,96.876\n2014-04-12 14:49:00,94.458\n2014-04-12 14:54:00,93.958\n2014-04-12 14:59:00,96.376\n2014-04-12 15:04:00,92.766\n2014-04-12 15:09:00,95.49\n2014-04-12 15:14:00,92.45200000000001\n2014-04-12 15:19:00,92.126\n2014-04-12 15:24:00,95.06200000000001\n2014-04-12 15:29:00,95.064\n2014-04-12 15:34:00,92.75\n2014-04-12 15:39:00,94.854\n2014-04-12 15:44:00,96.81200000000001\n2014-04-12 15:49:00,93.456\n2014-04-12 15:54:00,94.49600000000001\n2014-04-12 15:59:00,94.63799999999999\n2014-04-12 16:04:00,94.874\n2014-04-12 16:09:00,94.876\n2014-04-12 16:14:00,93.084\n2014-04-12 16:19:00,94.666\n2014-04-12 16:24:00,94.868\n2014-04-12 16:29:00,95.126\n2014-04-12 16:34:00,91.542\n2014-04-12 16:39:00,88.97200000000002\n2014-04-12 16:44:00,91.788\n2014-04-12 16:49:00,93.126\n2014-04-12 16:54:00,93.956\n2014-04-12 16:59:00,94.334\n2014-04-12 17:04:00,93.238\n2014-04-12 17:09:00,94.042\n2014-04-12 17:14:00,97.25\n2014-04-12 17:19:00,93.876\n2014-04-12 17:24:00,97.382\n2014-04-12 17:29:00,96.664\n2014-04-12 17:34:00,97.00399999999999\n2014-04-12 17:39:00,96.876\n2014-04-12 17:44:00,95.042\n2014-04-12 17:49:00,95.458\n2014-04-12 17:54:00,96.792\n2014-04-12 17:59:00,93.042\n2014-04-12 18:04:00,96.64200000000001\n2014-04-12 18:09:00,95.436\n2014-04-12 18:14:00,95.31200000000001\n2014-04-12 18:19:00,94.5\n2014-04-12 18:24:00,94.78200000000001\n2014-04-12 18:29:00,94.65\n2014-04-12 18:34:00,89.28399999999998\n2014-04-12 18:39:00,90.51\n2014-04-12 18:44:00,91.334\n2014-04-12 18:49:00,95.166\n2014-04-12 18:54:00,94.292\n2014-04-12 18:59:00,93.834\n2014-04-12 19:04:00,95.542\n2014-04-12 19:09:00,94.794\n2014-04-12 19:14:00,95.01799999999999\n2014-04-12 19:19:00,94.876\n2014-04-12 19:24:00,96.084\n2014-04-12 19:29:00,95.042\n2014-04-12 19:34:00,93.584\n2014-04-12 19:39:00,95.66799999999999\n2014-04-12 19:44:00,95.666\n2014-04-12 19:49:00,95.042\n2014-04-12 19:54:00,95.70200000000001\n2014-04-12 19:59:00,94.912\n2014-04-12 20:04:00,94.512\n2014-04-12 20:09:00,94.542\n2014-04-12 20:14:00,93.204\n2014-04-12 20:19:00,96.506\n2014-04-12 20:24:00,93.88\n2014-04-12 20:29:00,95.70200000000001\n2014-04-12 20:34:00,93.666\n2014-04-12 20:39:00,91.834\n2014-04-12 20:44:00,95.572\n2014-04-12 20:49:00,94.334\n2014-04-12 20:54:00,95.542\n2014-04-12 20:59:00,96.084\n2014-04-12 21:04:00,95.334\n2014-04-12 21:09:00,94.376\n2014-04-12 21:14:00,92.24799999999999\n2014-04-12 21:19:00,95.626\n2014-04-12 21:24:00,93.624\n2014-04-12 21:29:00,92.38\n2014-04-12 21:34:00,92.374\n2014-04-12 21:39:00,95.708\n2014-04-12 21:44:00,94.586\n2014-04-12 21:49:00,92.586\n2014-04-12 21:54:00,91.458\n2014-04-12 21:59:00,95.292\n2014-04-12 22:04:00,96.0\n2014-04-12 22:09:00,96.708\n2014-04-12 22:14:00,91.708\n2014-04-12 22:19:00,93.772\n2014-04-12 22:24:00,96.734\n2014-04-12 22:29:00,94.416\n2014-04-12 22:34:00,94.0\n2014-04-12 22:39:00,95.54\n2014-04-12 22:44:00,95.166\n2014-04-12 22:49:00,95.58\n2014-04-12 22:54:00,96.41799999999999\n2014-04-12 22:59:00,92.85600000000001\n2014-04-12 23:04:00,94.604\n2014-04-12 23:09:00,91.876\n2014-04-12 23:14:00,92.708\n2014-04-12 23:19:00,94.416\n2014-04-12 23:24:00,92.402\n2014-04-12 23:29:00,96.624\n2014-04-12 23:34:00,96.584\n2014-04-12 23:39:00,94.666\n2014-04-12 23:44:00,96.042\n2014-04-12 23:49:00,93.97200000000001\n2014-04-12 23:54:00,99.118\n2014-04-12 23:59:00,95.042\n2014-04-13 00:04:00,95.318\n2014-04-13 00:09:00,96.126\n2014-04-13 00:14:00,94.34\n2014-04-13 00:19:00,95.85\n2014-04-13 00:24:00,94.042\n2014-04-13 00:29:00,94.0\n2014-04-13 00:34:00,93.542\n2014-04-13 00:39:00,96.666\n2014-04-13 00:44:00,97.292\n2014-04-13 00:49:00,95.75\n2014-04-13 00:54:00,96.416\n2014-04-13 00:59:00,95.52799999999999\n2014-04-13 01:04:00,96.13600000000001\n2014-04-13 01:09:00,95.148\n2014-04-13 01:14:00,93.51799999999999\n2014-04-13 01:19:00,94.458\n2014-04-13 01:24:00,96.042\n2014-04-13 01:29:00,95.874\n2014-04-13 01:34:00,95.598\n2014-04-13 01:39:00,96.042\n2014-04-13 01:44:00,95.75\n2014-04-13 01:49:00,93.166\n2014-04-13 01:54:00,97.176\n2014-04-13 01:59:00,93.874\n2014-04-13 02:04:00,93.666\n2014-04-13 02:09:00,96.39\n2014-04-13 02:14:00,94.124\n2014-04-13 02:19:00,93.736\n2014-04-13 02:24:00,95.708\n2014-04-13 02:29:00,96.166\n2014-04-13 02:34:00,95.708\n2014-04-13 02:39:00,95.666\n2014-04-13 02:44:00,96.208\n2014-04-13 02:49:00,95.166\n2014-04-13 02:54:00,96.64200000000001\n2014-04-13 02:59:00,96.666\n2014-04-13 03:04:00,93.624\n2014-04-13 03:09:00,94.5\n2014-04-13 03:14:00,95.396\n2014-04-13 03:19:00,92.774\n2014-04-13 03:24:00,94.958\n2014-04-13 03:29:00,94.916\n2014-04-13 03:34:00,94.334\n2014-04-13 03:39:00,95.94\n2014-04-13 03:44:00,92.35600000000001\n2014-04-13 03:49:00,96.75\n2014-04-13 03:54:00,95.542\n2014-04-13 03:59:00,95.126\n2014-04-13 04:04:00,95.21\n2014-04-13 04:09:00,93.88799999999999\n2014-04-13 04:14:00,93.012\n2014-04-13 04:19:00,95.292\n2014-04-13 04:24:00,94.0\n2014-04-13 04:29:00,95.042\n2014-04-13 04:34:00,94.124\n2014-04-13 04:39:00,89.916\n2014-04-13 04:44:00,94.13799999999999\n2014-04-13 04:49:00,95.084\n2014-04-13 04:54:00,94.816\n2014-04-13 04:59:00,95.814\n2014-04-13 05:04:00,93.794\n2014-04-13 05:09:00,92.14200000000001\n2014-04-13 05:14:00,92.348\n2014-04-13 05:19:00,96.01\n2014-04-13 05:24:00,94.708\n2014-04-13 05:29:00,94.75\n2014-04-13 05:34:00,93.834\n2014-04-13 05:39:00,97.042\n2014-04-13 05:44:00,94.874\n2014-04-13 05:49:00,93.65\n2014-04-13 05:54:00,93.94\n2014-04-13 05:59:00,95.46600000000001\n2014-04-13 06:04:00,96.538\n2014-04-13 06:09:00,94.542\n2014-04-13 06:14:00,92.19200000000001\n2014-04-13 06:19:00,95.37200000000001\n2014-04-13 06:24:00,94.584\n2014-04-13 06:29:00,97.036\n2014-04-13 06:34:00,93.084\n2014-04-13 06:39:00,94.4\n2014-04-13 06:44:00,92.402\n2014-04-13 06:49:00,94.82\n2014-04-13 06:54:00,92.354\n2014-04-13 06:59:00,91.814\n2014-04-13 07:04:00,87.958\n2014-04-13 07:09:00,93.206\n2014-04-13 07:14:00,94.902\n2014-04-13 07:19:00,88.834\n2014-04-13 07:24:00,90.666\n2014-04-13 07:29:00,90.584\n2014-04-13 07:34:00,92.374\n2014-04-13 07:39:00,93.5\n2014-04-13 07:44:00,92.376\n2014-04-13 07:49:00,85.818\n2014-04-13 07:54:00,91.72\n2014-04-13 07:59:00,89.25\n2014-04-13 08:04:00,91.166\n2014-04-13 08:09:00,90.5\n2014-04-13 08:14:00,90.916\n2014-04-13 08:19:00,90.584\n2014-04-13 08:24:00,93.292\n2014-04-13 08:29:00,93.876\n2014-04-13 08:34:00,92.126\n2014-04-13 08:39:00,90.292\n2014-04-13 08:44:00,91.63600000000001\n2014-04-13 08:49:00,91.21\n2014-04-13 08:54:00,93.156\n2014-04-13 08:59:00,90.084\n2014-04-13 09:04:00,88.416\n2014-04-13 09:09:00,90.042\n2014-04-13 09:14:00,90.126\n2014-04-13 09:19:00,88.584\n2014-04-13 09:24:00,90.626\n2014-04-13 09:29:00,89.834\n2014-04-13 09:34:00,92.334\n2014-04-13 09:39:00,88.084\n2014-04-13 09:44:00,94.964\n2014-04-13 09:49:00,94.416\n2014-04-13 09:54:00,89.666\n2014-04-13 09:59:00,90.084\n2014-04-13 10:04:00,87.292\n2014-04-13 10:09:00,93.834\n2014-04-13 10:14:00,92.0\n2014-04-13 10:19:00,91.11\n2014-04-13 10:24:00,88.07\n2014-04-13 10:29:00,90.542\n2014-04-13 10:34:00,93.834\n2014-04-13 10:39:00,92.542\n2014-04-13 10:44:00,90.126\n2014-04-13 10:49:00,90.708\n2014-04-13 10:54:00,91.084\n2014-04-13 10:59:00,91.708\n2014-04-13 11:04:00,92.124\n2014-04-13 11:09:00,90.958\n2014-04-13 11:14:00,90.626\n2014-04-13 11:19:00,90.5\n2014-04-13 11:24:00,92.75\n2014-04-13 11:29:00,93.44\n2014-04-13 11:34:00,95.262\n2014-04-13 11:39:00,92.208\n2014-04-13 11:44:00,93.338\n2014-04-13 11:49:00,94.292\n2014-04-13 11:54:00,94.836\n2014-04-13 11:59:00,94.624\n2014-04-13 12:04:00,93.166\n2014-04-13 12:09:00,96.376\n2014-04-13 12:14:00,93.824\n2014-04-13 12:19:00,95.542\n2014-04-13 12:24:00,94.584\n2014-04-13 12:29:00,93.24\n2014-04-13 12:34:00,93.094\n2014-04-13 12:39:00,94.458\n2014-04-13 12:44:00,92.416\n2014-04-13 12:49:00,92.97\n2014-04-13 12:54:00,98.07799999999999\n2014-04-13 12:59:00,94.17200000000001\n2014-04-13 13:04:00,93.006\n2014-04-13 13:09:00,93.956\n2014-04-13 13:14:00,95.126\n2014-04-13 13:19:00,93.36\n2014-04-13 13:24:00,91.708\n2014-04-13 13:29:00,94.542\n2014-04-13 13:34:00,93.11\n2014-04-13 13:39:00,93.916\n2014-04-13 13:44:00,93.792\n2014-04-13 13:49:00,94.82\n2014-04-13 13:54:00,95.654\n2014-04-13 13:59:00,94.47\n2014-04-13 14:04:00,93.772\n2014-04-13 14:09:00,95.458\n2014-04-13 14:14:00,94.416\n2014-04-13 14:19:00,94.29799999999999\n2014-04-13 14:24:00,91.84200000000001\n2014-04-13 14:29:00,94.79799999999999\n2014-04-13 14:34:00,96.28\n2014-04-13 14:39:00,95.042\n2014-04-13 14:44:00,95.25\n2014-04-13 14:49:00,96.376\n2014-04-13 14:54:00,95.208\n2014-04-13 14:59:00,93.478\n2014-04-13 15:04:00,94.586\n2014-04-13 15:09:00,93.62200000000001\n2014-04-13 15:14:00,93.834\n2014-04-13 15:19:00,94.834\n2014-04-13 15:24:00,93.652\n2014-04-13 15:29:00,93.762\n2014-04-13 15:34:00,92.762\n2014-04-13 15:39:00,94.584\n2014-04-13 15:44:00,92.792\n2014-04-13 15:49:00,94.084\n2014-04-13 15:54:00,92.766\n2014-04-13 15:59:00,94.916\n2014-04-13 16:04:00,93.8\n2014-04-13 16:09:00,93.124\n2014-04-13 16:14:00,93.208\n2014-04-13 16:19:00,94.624\n2014-04-13 16:24:00,97.166\n2014-04-13 16:29:00,96.208\n2014-04-13 16:34:00,93.56200000000001\n2014-04-13 16:39:00,93.34\n2014-04-13 16:44:00,94.19200000000001\n2014-04-13 16:49:00,95.042\n2014-04-13 16:54:00,93.834\n2014-04-13 16:59:00,95.374\n2014-04-13 17:04:00,95.87200000000001\n2014-04-13 17:09:00,97.166\n2014-04-13 17:14:00,93.822\n2014-04-13 17:19:00,94.992\n2014-04-13 17:24:00,93.542\n2014-04-13 17:29:00,96.48\n2014-04-13 17:34:00,94.542\n2014-04-13 17:39:00,94.462\n2014-04-13 17:44:00,94.82799999999999\n2014-04-13 17:49:00,94.958\n2014-04-13 17:54:00,95.834\n2014-04-13 17:59:00,96.626\n2014-04-13 18:04:00,95.334\n2014-04-13 18:09:00,94.584\n2014-04-13 18:14:00,92.63\n2014-04-13 18:19:00,97.55799999999999\n2014-04-13 18:24:00,96.294\n2014-04-13 18:29:00,94.916\n2014-04-13 18:34:00,94.458\n2014-04-13 18:39:00,93.936\n2014-04-13 18:44:00,95.126\n2014-04-13 18:49:00,95.5\n2014-04-13 18:54:00,94.69200000000001\n2014-04-13 18:59:00,95.086\n2014-04-13 19:04:00,94.542\n2014-04-13 19:09:00,95.626\n2014-04-13 19:14:00,94.084\n2014-04-13 19:19:00,97.584\n2014-04-13 19:24:00,94.30799999999999\n2014-04-13 19:29:00,93.92\n2014-04-13 19:34:00,94.134\n2014-04-13 19:39:00,93.67200000000001\n2014-04-13 19:44:00,95.27799999999999\n2014-04-13 19:49:00,95.102\n2014-04-13 19:54:00,93.916\n2014-04-13 19:59:00,94.60600000000001\n2014-04-13 20:04:00,94.16799999999999\n2014-04-13 20:09:00,95.75\n2014-04-13 20:14:00,94.678\n2014-04-13 20:19:00,95.166\n2014-04-13 20:24:00,95.18\n2014-04-13 20:29:00,94.376\n2014-04-13 20:34:00,92.958\n2014-04-13 20:39:00,95.084\n2014-04-13 20:44:00,95.126\n2014-04-13 20:49:00,93.96\n2014-04-13 20:54:00,93.584\n2014-04-13 20:59:00,94.156\n2014-04-13 21:09:00,93.99\n2014-04-13 21:14:00,93.274\n2014-04-13 21:19:00,94.162\n2014-04-13 21:24:00,94.0\n2014-04-13 21:29:00,95.0\n2014-04-13 21:34:00,96.584\n2014-04-13 21:39:00,92.75\n2014-04-13 21:44:00,94.458\n2014-04-13 21:49:00,97.29\n2014-04-13 21:54:00,93.75\n2014-04-13 21:59:00,94.666\n2014-04-13 22:04:00,95.08200000000001\n2014-04-13 22:09:00,93.714\n2014-04-13 22:14:00,93.89399999999999\n2014-04-13 22:19:00,93.96600000000001\n2014-04-13 22:24:00,96.238\n2014-04-13 22:29:00,94.006\n2014-04-13 22:34:00,94.99600000000001\n2014-04-13 22:39:00,96.0\n2014-04-13 22:44:00,93.416\n2014-04-13 22:49:00,94.19\n2014-04-13 22:54:00,97.694\n2014-04-13 22:59:00,95.834\n2014-04-13 23:04:00,92.50200000000001\n2014-04-13 23:09:00,94.86200000000001\n2014-04-13 23:14:00,95.62799999999999\n2014-04-13 23:19:00,95.15\n2014-04-13 23:24:00,93.75\n2014-04-13 23:29:00,94.166\n2014-04-13 23:34:00,94.374\n2014-04-13 23:39:00,96.508\n2014-04-13 23:44:00,94.92399999999999\n2014-04-13 23:49:00,95.584\n2014-04-13 23:54:00,93.054\n2014-04-13 23:59:00,93.666\n2014-04-14 00:04:00,93.126\n2014-04-14 00:09:00,92.958\n2014-04-14 00:14:00,91.542\n2014-04-14 00:19:00,92.00399999999999\n2014-04-14 00:24:00,95.166\n2014-04-14 00:29:00,93.666\n2014-04-14 00:34:00,92.804\n2014-04-14 00:39:00,93.75\n2014-04-14 00:44:00,94.596\n2014-04-14 00:49:00,95.208\n2014-04-14 00:54:00,93.916\n2014-04-14 00:59:00,93.334\n2014-04-14 01:04:00,93.708\n2014-04-14 01:09:00,93.292\n2014-04-14 01:14:00,93.162\n2014-04-14 01:19:00,96.00399999999999\n2014-04-14 01:24:00,95.85799999999999\n2014-04-14 01:29:00,93.708\n2014-04-14 01:34:00,94.928\n2014-04-14 01:39:00,95.566\n2014-04-14 01:44:00,95.374\n2014-04-14 01:49:00,96.396\n2014-04-14 01:54:00,97.084\n2014-04-14 01:59:00,95.042\n2014-04-14 02:04:00,94.584\n2014-04-14 02:09:00,97.374\n2014-04-14 02:14:00,96.124\n2014-04-14 02:19:00,93.708\n2014-04-14 02:24:00,94.5\n2014-04-14 02:29:00,95.32\n2014-04-14 02:34:00,94.292\n2014-04-14 02:39:00,94.758\n2014-04-14 02:44:00,93.708\n2014-04-14 02:49:00,94.5\n2014-04-14 02:54:00,94.792\n2014-04-14 02:59:00,92.542\n2014-04-14 03:04:00,93.97\n2014-04-14 03:09:00,96.626\n2014-04-14 03:14:00,96.792\n2014-04-14 03:19:00,92.274\n2014-04-14 03:24:00,93.666\n2014-04-14 03:29:00,96.834\n2014-04-14 03:34:00,94.82799999999999\n2014-04-14 03:39:00,96.914\n2014-04-14 03:44:00,92.916\n2014-04-14 03:49:00,93.292\n2014-04-14 03:54:00,95.76799999999999\n2014-04-14 03:59:00,95.646\n2014-04-14 04:04:00,94.148\n2014-04-14 04:09:00,93.648\n2014-04-14 04:14:00,96.098\n2014-04-14 04:19:00,94.792\n2014-04-14 04:24:00,93.916\n2014-04-14 04:29:00,93.292\n2014-04-14 04:34:00,94.334\n2014-04-14 04:39:00,95.28200000000001\n2014-04-14 04:44:00,94.874\n2014-04-14 04:49:00,95.834\n2014-04-14 04:54:00,94.792\n2014-04-14 04:59:00,95.626\n2014-04-14 05:04:00,96.666\n2014-04-14 05:09:00,96.0\n2014-04-14 05:14:00,95.708\n2014-04-14 05:19:00,94.46799999999999\n2014-04-14 05:24:00,94.208\n2014-04-14 05:29:00,94.292\n2014-04-14 05:34:00,97.77\n2014-04-14 05:39:00,97.24799999999999\n2014-04-14 05:44:00,96.87200000000001\n2014-04-14 05:49:00,92.90799999999999\n2014-04-14 05:54:00,94.38600000000001\n2014-04-14 05:59:00,95.822\n2014-04-14 06:04:00,93.708\n2014-04-14 06:09:00,93.73200000000001\n2014-04-14 06:14:00,93.978\n2014-04-14 06:19:00,95.376\n2014-04-14 06:24:00,93.12799999999999\n2014-04-14 06:29:00,94.166\n2014-04-14 06:34:00,97.24799999999999\n2014-04-14 06:39:00,94.626\n2014-04-14 06:44:00,97.26\n2014-04-14 06:49:00,95.376\n2014-04-14 06:54:00,94.542\n2014-04-14 06:59:00,97.874\n2014-04-14 07:04:00,93.456\n2014-04-14 07:09:00,94.5\n2014-04-14 07:14:00,96.708\n2014-04-14 07:19:00,94.304\n2014-04-14 07:24:00,93.932\n2014-04-14 07:29:00,93.16799999999999\n2014-04-14 07:34:00,96.42399999999999\n2014-04-14 07:39:00,95.6\n2014-04-14 07:44:00,95.084\n2014-04-14 07:49:00,96.13600000000001\n2014-04-14 07:54:00,95.416\n2014-04-14 07:59:00,93.42399999999999\n2014-04-14 08:04:00,94.63600000000001\n2014-04-14 08:09:00,95.084\n2014-04-14 08:14:00,94.958\n2014-04-14 08:19:00,94.292\n2014-04-14 08:24:00,94.708\n2014-04-14 08:29:00,96.46799999999999\n2014-04-14 08:34:00,95.958\n2014-04-14 08:39:00,94.416\n2014-04-14 08:44:00,93.25\n2014-04-14 08:49:00,94.416\n2014-04-14 08:54:00,94.626\n2014-04-14 08:59:00,94.85\n2014-04-14 09:04:00,92.294\n2014-04-14 09:09:00,95.5\n2014-04-14 09:14:00,94.042\n2014-04-14 09:19:00,93.508\n2014-04-14 09:24:00,92.77\n2014-04-14 09:29:00,92.63\n2014-04-14 09:34:00,94.86200000000001\n2014-04-14 09:39:00,93.666\n2014-04-14 09:44:00,94.53399999999999\n2014-04-14 09:49:00,94.25\n2014-04-14 09:54:00,96.124\n2014-04-14 09:59:00,93.334\n2014-04-14 10:04:00,96.53\n2014-04-14 10:09:00,91.958\n2014-04-14 10:14:00,93.708\n2014-04-14 10:19:00,95.958\n2014-04-14 10:24:00,94.5\n2014-04-14 10:29:00,95.708\n2014-04-14 10:34:00,93.166\n2014-04-14 10:39:00,91.458\n2014-04-14 10:44:00,96.32799999999999\n2014-04-14 10:49:00,94.184\n2014-04-14 10:54:00,96.182\n2014-04-14 10:59:00,91.9\n2014-04-14 11:04:00,92.542\n2014-04-14 11:09:00,94.22\n2014-04-14 11:14:00,94.416\n2014-04-14 11:19:00,98.212\n2014-04-14 11:24:00,94.546\n2014-04-14 11:29:00,93.334\n2014-04-14 11:34:00,93.88\n2014-04-14 11:39:00,92.868\n2014-04-14 11:44:00,95.306\n2014-04-14 11:49:00,93.876\n2014-04-14 11:54:00,94.712\n2014-04-14 11:59:00,93.876\n2014-04-14 12:04:00,95.876\n2014-04-14 12:09:00,96.708\n2014-04-14 12:14:00,95.334\n2014-04-14 12:19:00,93.57600000000001\n2014-04-14 12:24:00,94.292\n2014-04-14 12:29:00,94.25\n2014-04-14 12:34:00,93.26\n2014-04-14 12:39:00,94.072\n2014-04-14 12:44:00,94.0\n2014-04-14 12:49:00,94.334\n2014-04-14 12:54:00,94.662\n2014-04-14 12:59:00,96.96600000000001\n2014-04-14 13:04:00,93.626\n2014-04-14 13:09:00,93.874\n2014-04-14 13:14:00,95.5\n2014-04-14 13:19:00,94.874\n2014-04-14 13:24:00,95.416\n2014-04-14 13:29:00,93.75\n2014-04-14 13:34:00,93.126\n2014-04-14 13:39:00,94.0\n2014-04-14 13:44:00,91.708\n2014-04-14 13:49:00,92.46799999999999\n2014-04-14 13:54:00,96.376\n2014-04-14 13:59:00,93.12\n2014-04-14 14:04:00,90.60600000000001\n2014-04-14 14:09:00,94.958\n2014-04-14 14:14:00,94.916\n2014-04-14 14:19:00,98.208\n2014-04-14 14:24:00,94.50399999999999\n2014-04-14 14:29:00,93.126\n2014-04-14 14:34:00,95.542\n2014-04-14 14:39:00,94.166\n2014-04-14 14:44:00,94.25\n2014-04-14 14:49:00,95.292\n2014-04-14 14:54:00,96.916\n2014-04-14 14:59:00,93.5\n2014-04-14 15:04:00,96.25\n2014-04-14 15:09:00,96.0\n2014-04-14 15:14:00,94.384\n2014-04-14 15:19:00,96.084\n2014-04-14 15:24:00,94.384\n2014-04-14 15:29:00,95.042\n2014-04-14 15:34:00,95.436\n2014-04-14 15:39:00,96.25\n2014-04-14 15:44:00,96.416\n2014-04-14 15:49:00,96.876\n2014-04-14 15:54:00,94.0\n2014-04-14 15:59:00,93.47\n2014-04-14 16:04:00,95.22399999999999\n2014-04-14 16:09:00,94.084\n2014-04-14 16:14:00,93.792\n2014-04-14 16:19:00,95.5\n2014-04-14 16:24:00,93.792\n2014-04-14 16:29:00,92.47399999999999\n2014-04-14 16:34:00,93.834\n2014-04-14 16:39:00,92.37200000000001\n2014-04-14 16:44:00,94.958\n2014-04-14 16:49:00,94.542\n2014-04-14 16:54:00,93.208\n2014-04-14 16:59:00,94.48200000000001\n2014-04-14 17:04:00,93.19200000000001\n2014-04-14 17:09:00,93.64200000000001\n2014-04-14 17:14:00,92.964\n2014-04-14 17:19:00,94.814\n2014-04-14 17:24:00,95.178\n2014-04-14 17:29:00,94.5\n2014-04-14 17:34:00,95.58200000000001\n2014-04-14 17:39:00,96.204\n2014-04-14 17:44:00,95.834\n2014-04-14 17:49:00,93.208\n2014-04-14 17:54:00,93.00200000000001\n2014-04-14 17:59:00,92.958\n2014-04-14 18:04:00,96.272\n2014-04-14 18:09:00,95.404\n2014-04-14 18:14:00,93.792\n2014-04-14 18:19:00,95.042\n2014-04-14 18:24:00,96.334\n2014-04-14 18:29:00,97.874\n2014-04-14 18:34:00,95.75\n2014-04-14 18:39:00,93.522\n2014-04-14 18:44:00,93.198\n2014-04-14 18:49:00,95.208\n2014-04-14 18:54:00,92.5\n2014-04-14 18:59:00,93.24799999999999\n2014-04-14 19:04:00,93.584\n2014-04-14 19:09:00,94.36399999999999\n2014-04-14 19:14:00,93.36200000000001\n2014-04-14 19:19:00,94.21600000000001\n2014-04-14 19:24:00,93.96\n2014-04-14 19:29:00,94.57\n2014-04-14 19:34:00,93.446\n2014-04-14 19:39:00,93.27\n2014-04-14 19:44:00,93.23200000000001\n2014-04-14 19:49:00,95.5\n2014-04-14 19:54:00,94.374\n2014-04-14 19:59:00,93.116\n2014-04-14 20:04:00,93.402\n2014-04-14 20:09:00,92.44\n2014-04-14 20:14:00,93.75200000000001\n2014-04-14 20:19:00,91.792\n2014-04-14 20:24:00,95.0\n2014-04-14 20:29:00,94.166\n2014-04-14 20:34:00,94.208\n2014-04-14 20:39:00,92.75\n2014-04-14 20:44:00,94.5\n2014-04-14 20:49:00,92.86399999999999\n2014-04-14 20:54:00,95.916\n2014-04-14 20:59:00,90.27600000000001\n2014-04-14 21:04:00,93.22\n2014-04-14 21:09:00,97.042\n2014-04-14 21:14:00,95.4\n2014-04-14 21:19:00,92.542\n2014-04-14 21:24:00,93.12200000000001\n2014-04-14 21:29:00,94.59200000000001\n2014-04-14 21:34:00,93.882\n2014-04-14 21:39:00,94.0\n2014-04-14 21:44:00,93.084\n2014-04-14 21:49:00,95.292\n2014-04-14 21:54:00,98.46600000000001\n2014-04-14 21:59:00,94.99600000000001\n2014-04-14 22:04:00,95.632\n2014-04-14 22:09:00,96.78200000000001\n2014-04-14 22:14:00,95.57799999999999\n2014-04-14 22:19:00,92.87\n2014-04-14 22:24:00,96.208\n2014-04-14 22:29:00,91.792\n2014-04-14 22:34:00,95.166\n2014-04-14 22:39:00,95.584\n2014-04-14 22:44:00,94.874\n2014-04-14 22:49:00,95.876\n2014-04-14 22:54:00,96.334\n2014-04-14 22:59:00,92.916\n2014-04-14 23:04:00,95.542\n2014-04-14 23:09:00,94.416\n2014-04-14 23:14:00,92.834\n2014-04-14 23:19:00,93.958\n2014-04-14 23:24:00,93.266\n2014-04-14 23:29:00,95.25\n2014-04-14 23:34:00,95.14200000000001\n2014-04-14 23:39:00,94.306\n2014-04-14 23:44:00,95.792\n2014-04-14 23:49:00,94.916\n2014-04-14 23:54:00,93.198\n2014-04-14 23:59:00,94.376\n2014-04-15 00:04:00,95.46\n2014-04-15 00:09:00,95.956\n2014-04-15 00:14:00,95.682\n2014-04-15 00:19:00,93.21799999999999\n2014-04-15 00:24:00,94.584\n2014-04-15 00:29:00,96.584\n2014-04-15 00:34:00,96.458\n2014-04-15 00:39:00,93.792\n2014-04-15 00:44:00,93.084\n2014-04-15 00:49:00,93.792\n2014-04-15 00:54:00,94.75\n2014-04-15 00:59:00,91.94200000000001\n2014-04-15 01:04:00,94.334\n2014-04-15 01:09:00,92.92\n2014-04-15 01:14:00,93.958\n2014-04-15 01:19:00,91.478\n2014-04-15 01:24:00,94.708\n2014-04-15 01:29:00,93.62799999999999\n2014-04-15 01:34:00,91.75\n2014-04-15 01:39:00,93.834\n2014-04-15 01:44:00,94.39399999999999\n2014-04-15 01:49:00,92.834\n2014-04-15 01:54:00,95.852\n2014-04-15 01:59:00,94.406\n2014-04-15 02:04:00,93.584\n2014-04-15 02:09:00,92.25\n2014-04-15 02:14:00,96.764\n2014-04-15 02:19:00,96.772\n2014-04-15 02:24:00,93.584\n2014-04-15 02:29:00,93.5\n2014-04-15 02:34:00,93.792\n2014-04-15 02:39:00,95.964\n2014-04-15 02:44:00,93.81\n2014-04-15 02:49:00,95.556\n2014-04-15 02:54:00,92.96600000000001\n2014-04-15 02:59:00,93.85799999999999\n2014-04-15 03:04:00,95.354\n2014-04-15 03:09:00,92.40799999999999\n2014-04-15 03:14:00,93.084\n2014-04-15 03:19:00,95.124\n2014-04-15 03:24:00,97.042\n2014-04-15 03:29:00,93.762\n2014-04-15 03:34:00,94.458\n2014-04-15 03:39:00,95.792\n2014-04-15 03:44:00,93.792\n2014-04-15 03:49:00,95.81200000000001\n2014-04-15 03:54:00,94.126\n2014-04-15 03:59:00,93.75\n2014-04-15 04:04:00,90.25\n2014-04-15 04:09:00,97.708\n2014-04-15 04:14:00,95.21799999999999\n2014-04-15 04:19:00,95.48\n2014-04-15 04:24:00,92.916\n2014-04-15 04:29:00,94.874\n2014-04-15 04:34:00,93.376\n2014-04-15 04:39:00,92.084\n2014-04-15 04:44:00,95.456\n2014-04-15 04:49:00,95.542\n2014-04-15 04:54:00,93.75\n2014-04-15 04:59:00,92.32799999999999\n2014-04-15 05:04:00,95.042\n2014-04-15 05:09:00,95.74600000000001\n2014-04-15 05:14:00,94.92200000000001\n2014-04-15 05:19:00,94.53200000000001\n2014-04-15 05:24:00,96.336\n2014-04-15 05:29:00,93.584\n2014-04-15 05:34:00,94.176\n2014-04-15 05:39:00,94.25\n2014-04-15 05:44:00,96.512\n2014-04-15 05:49:00,92.708\n2014-04-15 05:54:00,94.666\n2014-04-15 05:59:00,92.458\n2014-04-15 06:04:00,95.03399999999999\n2014-04-15 06:09:00,93.5\n2014-04-15 06:14:00,92.346\n2014-04-15 06:19:00,91.454\n2014-04-15 06:24:00,92.0\n2014-04-15 06:29:00,92.0\n2014-04-15 06:34:00,93.698\n2014-04-15 06:39:00,94.208\n2014-04-15 06:44:00,93.824\n2014-04-15 06:49:00,88.376\n2014-04-15 06:54:00,94.0\n2014-04-15 06:59:00,91.166\n2014-04-15 07:04:00,91.514\n2014-04-15 07:09:00,90.02799999999998\n2014-04-15 07:14:00,88.97399999999998\n2014-04-15 07:19:00,95.29799999999999\n2014-04-15 07:24:00,93.726\n2014-04-15 07:29:00,91.542\n2014-04-15 07:34:00,92.416\n2014-04-15 07:39:00,95.47\n2014-04-15 07:44:00,97.542\n2014-04-15 07:49:00,92.552\n2014-04-15 07:54:00,93.416\n2014-04-15 07:59:00,89.87\n2014-04-15 08:04:00,92.41\n2014-04-15 08:09:00,91.73\n2014-04-15 08:14:00,93.624\n2014-04-15 08:19:00,93.134\n2014-04-15 08:24:00,92.334\n2014-04-15 08:29:00,94.376\n2014-04-15 08:34:00,94.07799999999999\n2014-04-15 08:39:00,93.042\n2014-04-15 08:44:00,93.958\n2014-04-15 08:49:00,94.124\n2014-04-15 08:54:00,91.458\n2014-04-15 08:59:00,93.376\n2014-04-15 09:04:00,94.25\n2014-04-15 09:09:00,95.834\n2014-04-15 09:14:00,94.564\n2014-04-15 09:19:00,93.25\n2014-04-15 09:24:00,94.348\n2014-04-15 09:29:00,97.18799999999999\n2014-04-15 09:34:00,95.11399999999999\n2014-04-15 09:39:00,95.958\n2014-04-15 09:44:00,95.708\n2014-04-15 09:49:00,91.83\n2014-04-15 09:54:00,93.584\n2014-04-15 09:59:00,93.166\n2014-04-15 10:04:00,92.708\n2014-04-15 10:09:00,93.042\n2014-04-15 10:14:00,95.084\n2014-04-15 10:19:00,97.042\n2014-04-15 10:24:00,93.958\n2014-04-15 10:29:00,94.124\n2014-04-15 10:34:00,92.416\n2014-04-15 10:39:00,95.166\n2014-04-15 10:44:00,93.084\n2014-04-15 10:49:00,95.43\n2014-04-15 10:54:00,93.904\n2014-04-15 10:59:00,94.054\n2014-04-15 11:04:00,93.334\n2014-04-15 11:09:00,93.05799999999999\n2014-04-15 11:14:00,93.92\n2014-04-15 11:19:00,94.208\n2014-04-15 11:24:00,95.806\n2014-04-15 11:29:00,90.75\n2014-04-15 11:34:00,93.584\n2014-04-15 11:39:00,93.334\n2014-04-15 11:44:00,94.292\n2014-04-15 11:49:00,95.272\n2014-04-15 11:54:00,93.958\n2014-04-15 11:59:00,90.75\n2014-04-15 12:04:00,95.446\n2014-04-15 12:09:00,93.73200000000001\n2014-04-15 12:14:00,91.162\n2014-04-15 12:19:00,92.19\n2014-04-15 12:24:00,93.87\n2014-04-15 12:29:00,92.91799999999999\n2014-04-15 12:34:00,93.208\n2014-04-15 12:39:00,92.792\n2014-04-15 12:44:00,96.75\n2014-04-15 12:49:00,93.374\n2014-04-15 12:54:00,94.35799999999999\n2014-04-15 12:59:00,93.27\n2014-04-15 13:04:00,93.54\n2014-04-15 13:09:00,93.024\n2014-04-15 13:14:00,95.166\n2014-04-15 13:19:00,95.04\n2014-04-15 13:24:00,93.904\n2014-04-15 13:29:00,93.834\n2014-04-15 13:34:00,94.406\n2014-04-15 13:39:00,94.376\n2014-04-15 13:44:00,95.334\n2014-04-15 13:49:00,95.084\n2014-04-15 13:54:00,89.958\n2014-04-15 13:59:00,91.1\n2014-04-15 14:04:00,93.822\n2014-04-15 14:09:00,93.60799999999999\n2014-04-15 14:14:00,90.50399999999999\n2014-04-15 14:19:00,88.384\n2014-04-15 14:24:00,91.124\n2014-04-15 14:29:00,93.542\n2014-04-15 14:34:00,86.728\n2014-04-15 14:39:00,91.44\n2014-04-15 14:44:00,93.17200000000001\n2014-04-15 14:49:00,92.634\n2014-04-15 14:54:00,95.804\n2014-04-15 14:59:00,92.916\n2014-04-15 15:04:00,89.948\n2014-04-15 15:09:00,92.834\n2014-04-15 15:14:00,91.666\n2014-04-15 15:19:00,92.0\n2014-04-15 15:24:00,89.92\n2014-04-15 15:29:00,94.024\n2014-04-15 15:34:00,91.876\n2014-04-15 15:39:00,92.042\n2014-04-15 15:44:00,76.874\n2014-04-15 15:49:00,86.124\n2014-04-15 15:54:00,84.626\n2014-04-15 15:59:00,82.374\n2014-04-15 16:04:00,85.52799999999998\n2014-04-15 16:09:00,90.23\n2014-04-15 16:14:00,90.458\n2014-04-15 16:19:00,90.584\n2014-04-15 16:24:00,91.626\n2014-04-15 16:29:00,90.0\n2014-04-15 16:34:00,93.404\n2014-04-15 16:39:00,95.766\n2014-04-15 16:44:00,93.76799999999999\n2014-04-15 16:49:00,89.292\n2014-04-15 16:54:00,54.958\n2014-04-15 16:59:00,54.7775\n2014-04-15 17:04:00,90.03200000000002\n2014-04-15 17:09:00,93.18\n2014-04-15 17:14:00,88.178\n2014-04-15 17:19:00,87.99799999999998\n2014-04-15 17:24:00,87.986\n2014-04-15 17:29:00,87.542\n2014-04-15 17:34:00,89.084\n2014-04-15 17:39:00,89.876\n2014-04-15 17:44:00,87.044\n2014-04-15 17:49:00,88.0\n2014-04-15 17:54:00,88.49799999999998\n2014-04-15 17:59:00,89.322\n2014-04-15 18:04:00,88.166\n2014-04-15 18:09:00,92.916\n2014-04-15 18:14:00,87.626\n2014-04-15 18:19:00,89.072\n2014-04-15 18:24:00,85.238\n2014-04-15 18:29:00,89.756\n2014-04-15 18:34:00,87.666\n2014-04-15 18:39:00,89.626\n2014-04-15 18:44:00,90.292\n2014-04-15 18:49:00,87.74600000000002\n2014-04-15 18:54:00,85.458\n2014-04-15 18:59:00,88.0\n2014-04-15 19:04:00,88.958\n2014-04-15 19:09:00,92.60600000000001\n2014-04-15 19:14:00,76.982\n2014-04-15 19:19:00,92.262\n2014-04-15 19:24:00,86.552\n2014-04-15 19:29:00,88.042\n2014-04-15 19:34:00,88.334\n2014-04-15 19:39:00,90.696\n2014-04-15 19:44:00,87.89399999999998\n2014-04-15 19:49:00,93.85\n2014-04-15 19:54:00,91.348\n2014-04-15 19:59:00,91.626\n2014-04-15 20:04:00,89.084\n2014-04-15 20:09:00,90.98200000000001\n2014-04-15 20:14:00,90.98200000000001\n2014-04-15 20:19:00,92.18799999999999\n2014-04-15 20:24:00,90.25\n2014-04-15 20:29:00,93.166\n2014-04-15 20:34:00,93.75\n2014-04-15 20:39:00,89.584\n2014-04-15 20:44:00,91.708\n2014-04-15 20:49:00,89.12\n2014-04-15 20:54:00,91.618\n2014-04-15 20:59:00,91.266\n2014-04-15 21:04:00,94.084\n2014-04-15 21:09:00,94.5\n2014-04-15 21:14:00,93.708\n2014-04-15 21:19:00,92.708\n2014-04-15 21:24:00,93.662\n2014-04-15 21:29:00,91.652\n2014-04-15 21:34:00,93.75200000000001\n2014-04-15 21:39:00,91.07600000000001\n2014-04-15 21:44:00,92.508\n2014-04-15 21:49:00,93.64\n2014-04-15 21:54:00,93.584\n2014-04-15 21:59:00,92.124\n2014-04-15 22:04:00,90.166\n2014-04-15 22:09:00,94.484\n2014-04-15 22:14:00,92.148\n2014-04-15 22:19:00,93.486\n2014-04-15 22:24:00,94.56\n2014-04-15 22:29:00,91.458\n2014-04-15 22:34:00,91.0\n2014-04-15 22:39:00,91.876\n2014-04-15 22:44:00,90.042\n2014-04-15 22:49:00,93.626\n2014-04-15 22:54:00,93.666\n2014-04-15 22:59:00,95.166\n2014-04-15 23:04:00,92.59\n2014-04-15 23:09:00,94.042\n2014-04-15 23:14:00,87.708\n2014-04-15 23:19:00,92.78200000000001\n2014-04-15 23:24:00,91.514\n2014-04-15 23:29:00,88.834\n2014-04-15 23:34:00,90.964\n2014-04-15 23:39:00,91.084\n2014-04-15 23:44:00,90.15799999999999\n2014-04-15 23:49:00,88.958\n2014-04-15 23:54:00,91.896\n2014-04-15 23:59:00,92.916\n2014-04-16 00:04:00,91.348\n2014-04-16 00:09:00,92.75\n2014-04-16 00:14:00,93.704\n2014-04-16 00:19:00,93.292\n2014-04-16 00:24:00,93.916\n2014-04-16 00:29:00,92.126\n2014-04-16 00:34:00,93.084\n2014-04-16 00:39:00,93.454\n2014-04-16 00:44:00,91.292\n2014-04-16 00:49:00,94.25\n2014-04-16 00:54:00,91.542\n2014-04-16 00:59:00,93.292\n2014-04-16 01:04:00,92.63\n2014-04-16 01:09:00,94.39200000000001\n2014-04-16 01:14:00,90.292\n2014-04-16 01:19:00,94.292\n2014-04-16 01:24:00,93.57\n2014-04-16 01:29:00,91.876\n2014-04-16 01:34:00,91.376\n2014-04-16 01:39:00,92.65799999999999\n2014-04-16 01:44:00,90.666\n2014-04-16 01:49:00,92.5\n2014-04-16 01:54:00,92.042\n2014-04-16 01:59:00,92.5\n2014-04-16 02:04:00,93.208\n2014-04-16 02:09:00,95.34\n2014-04-16 02:14:00,93.962\n2014-04-16 02:19:00,93.55799999999999\n2014-04-16 02:24:00,90.08200000000001\n2014-04-16 02:29:00,90.344\n2014-04-16 02:34:00,92.506\n2014-04-16 02:39:00,90.89399999999999\n2014-04-16 02:44:00,91.416\n2014-04-16 02:49:00,90.374\n2014-04-16 02:54:00,92.166\n2014-04-16 02:59:00,91.632\n2014-04-16 03:04:00,92.416\n2014-04-16 03:09:00,98.292\n2014-04-16 03:14:00,92.124\n2014-04-16 03:19:00,91.416\n2014-04-16 03:24:00,91.458\n2014-04-16 03:29:00,58.461999999999996\n2014-04-16 03:34:00,24.432\n2014-04-16 03:39:00,24.624000000000002\n2014-04-16 03:44:00,23.994\n2014-04-16 03:49:00,24.291999999999998\n2014-04-16 03:54:00,25.208000000000002\n2014-04-16 03:59:00,24.541999999999998\n2014-04-16 04:04:00,18.7225\n2014-04-16 04:09:00,35.93199999999999\n2014-04-16 04:14:00,24.638\n2014-04-16 04:19:00,23.59\n2014-04-16 04:24:00,24.608\n2014-04-16 04:29:00,24.204\n2014-04-16 04:34:00,24.294\n2014-04-16 04:39:00,24.82\n2014-04-16 04:44:00,24.584\n2014-04-16 04:49:00,24.584\n2014-04-16 04:54:00,25.375999999999998\n2014-04-16 04:59:00,25.124000000000002\n2014-04-16 05:04:00,24.951999999999998\n2014-04-16 05:09:00,36.461999999999996\n2014-04-16 05:14:00,24.651999999999997\n2014-04-16 05:19:00,25.048000000000002\n2014-04-16 05:24:00,25.32\n2014-04-16 05:29:00,25.166\n2014-04-16 05:34:00,24.791999999999998\n2014-04-16 05:39:00,25.334\n2014-04-16 05:44:00,24.875999999999998\n2014-04-16 05:49:00,24.708000000000002\n2014-04-16 05:54:00,25.75\n2014-04-16 05:59:00,25.5\n2014-04-16 06:04:00,25.416\n2014-04-16 06:09:00,36.334\n2014-04-16 06:14:00,25.334\n2014-04-16 06:19:00,25.108\n2014-04-16 06:24:00,25.32\n2014-04-16 06:29:00,25.401999999999997\n2014-04-16 06:34:00,24.666\n2014-04-16 06:39:00,25.208000000000002\n2014-04-16 06:44:00,25.122\n2014-04-16 06:49:00,25.25\n2014-04-16 06:54:00,25.541999999999998\n2014-04-16 06:59:00,25.584\n2014-04-16 07:04:00,25.334\n2014-04-16 07:09:00,36.67\n2014-04-16 07:14:00,25.108\n2014-04-16 07:19:00,24.976\n2014-04-16 07:24:00,25.274\n2014-04-16 07:29:00,24.842\n2014-04-16 07:34:00,24.541999999999998\n2014-04-16 07:39:00,25.0\n2014-04-16 07:44:00,24.916\n2014-04-16 07:49:00,24.516\n2014-04-16 07:54:00,25.25\n2014-04-16 07:59:00,25.204\n2014-04-16 08:04:00,24.8\n2014-04-16 08:09:00,36.0\n2014-04-16 08:14:00,25.291999999999998\n2014-04-16 08:19:00,25.166\n2014-04-16 08:24:00,25.375999999999998\n2014-04-16 08:29:00,24.874000000000002\n2014-04-16 08:34:00,24.541999999999998\n2014-04-16 08:39:00,25.041999999999998\n2014-04-16 08:44:00,24.666\n2014-04-16 08:49:00,24.791999999999998\n2014-04-16 08:54:00,25.45\n2014-04-16 08:59:00,25.214000000000002\n2014-04-16 09:04:00,24.916\n2014-04-16 09:09:00,36.166\n2014-04-16 09:14:00,24.958000000000002\n2014-04-16 09:19:00,24.666\n2014-04-16 09:24:00,24.624000000000002\n2014-04-16 09:29:00,25.125999999999998\n2014-04-16 09:34:00,25.125999999999998\n2014-04-16 09:39:00,24.916\n2014-04-16 09:44:00,25.25\n2014-04-16 09:49:00,24.834\n2014-04-16 09:54:00,25.666\n2014-04-16 09:59:00,25.364\n2014-04-16 10:04:00,24.791999999999998\n2014-04-16 10:09:00,36.626\n2014-04-16 10:14:00,24.484\n2014-04-16 10:19:00,24.94\n2014-04-16 10:24:00,24.726\n2014-04-16 10:29:00,26.458000000000002\n2014-04-16 10:34:00,24.916\n2014-04-16 10:39:00,25.272\n2014-04-16 10:44:00,25.166\n2014-04-16 10:49:00,24.75\n2014-04-16 10:54:00,25.334\n2014-04-16 10:59:00,25.625999999999998\n2014-04-16 11:04:00,25.081999999999997\n2014-04-16 11:09:00,35.876\n2014-04-16 11:14:00,24.916\n2014-04-16 11:19:00,24.991999999999997\n2014-04-16 11:24:00,25.484\n2014-04-16 11:29:00,25.084\n2014-04-16 11:34:00,24.791999999999998\n2014-04-16 11:39:00,25.084\n2014-04-16 11:44:00,25.374000000000002\n2014-04-16 11:49:00,24.75\n2014-04-16 11:54:00,25.416\n2014-04-16 11:59:00,25.334\n2014-04-16 12:04:00,25.041999999999998\n2014-04-16 12:09:00,35.854\n2014-04-16 12:14:00,24.625999999999998\n2014-04-16 12:19:00,25.11\n2014-04-16 12:24:00,24.97\n2014-04-16 12:29:00,24.94\n2014-04-16 12:34:00,24.666\n2014-04-16 12:39:00,24.708000000000002\n2014-04-16 12:44:00,25.125999999999998\n2014-04-16 12:49:00,25.25\n2014-04-16 12:54:00,25.416\n2014-04-16 12:59:00,25.691999999999997\n2014-04-16 13:04:00,26.0425\n2014-04-16 13:09:00,36.385999999999996\n2014-04-16 13:14:00,24.726\n2014-04-16 13:19:00,24.706\n2014-04-16 13:24:00,24.76\n2014-04-16 13:29:00,23.756\n2014-04-16 13:34:00,24.334\n2014-04-16 13:39:00,24.416\n2014-04-16 13:44:00,24.916\n2014-04-16 13:49:00,24.291999999999998\n2014-04-16 13:54:00,25.026\n2014-04-16 13:59:00,24.334\n2014-04-16 14:04:00,24.284000000000002\n2014-04-16 14:09:00,36.166\n2014-04-16 14:14:00,24.081999999999997\n2014-04-16 14:19:00,85.266\n2014-04-16 14:24:00,94.834\n2014-04-16 14:29:00,92.162\n2014-04-16 14:34:00,94.4\n2014-04-16 14:39:00,94.334\n2014-04-16 14:44:00,93.882\n2014-04-16 14:49:00,91.75\n2014-04-16 14:54:00,92.208\n2014-04-16 14:59:00,93.374\n2014-04-16 15:04:00,88.626\n2014-04-16 15:09:00,90.874\n2014-04-16 15:14:00,91.25\n2014-04-16 15:19:00,92.374\n2014-04-16 15:24:00,85.958\n2014-04-16 15:29:00,86.75\n2014-04-16 15:34:00,85.584\n2014-04-16 15:39:00,84.958\n2014-04-16 15:44:00,85.25\n2014-04-16 15:49:00,87.25\n2014-04-16 15:54:00,87.132\n2014-04-16 15:59:00,94.1\n2014-04-16 16:04:00,89.208\n2014-04-16 16:09:00,93.584\n2014-04-16 16:14:00,92.292\n2014-04-16 16:19:00,89.196\n2014-04-16 16:24:00,90.25\n2014-04-16 16:29:00,90.95200000000001\n2014-04-16 16:34:00,91.4\n2014-04-16 16:39:00,93.182\n2014-04-16 16:44:00,89.512\n2014-04-16 16:49:00,88.648\n2014-04-16 16:54:00,88.87799999999999\n2014-04-16 16:59:00,87.006\n2014-04-16 17:04:00,93.53200000000001\n2014-04-16 17:09:00,93.072\n2014-04-16 17:14:00,80.63\n2014-04-16 17:19:00,91.72200000000001\n2014-04-16 17:24:00,92.194\n2014-04-16 17:29:00,90.94\n2014-04-16 17:34:00,89.666\n2014-04-16 17:39:00,94.292\n2014-04-16 17:44:00,92.626\n2014-04-16 17:49:00,93.376\n2014-04-16 17:54:00,91.87200000000001\n2014-04-16 17:59:00,90.48200000000001\n2014-04-16 18:04:00,92.91\n2014-04-16 18:09:00,92.124\n2014-04-16 18:14:00,91.208\n2014-04-16 18:19:00,91.292\n2014-04-16 18:24:00,92.902\n2014-04-16 18:29:00,93.042\n2014-04-16 18:34:00,90.5\n2014-04-16 18:39:00,91.036\n2014-04-16 18:44:00,89.208\n2014-04-16 18:49:00,89.376\n2014-04-16 18:54:00,89.98200000000001\n2014-04-16 18:59:00,90.042\n2014-04-16 19:04:00,88.5\n2014-04-16 19:09:00,90.176\n2014-04-16 19:14:00,87.396\n2014-04-16 19:19:00,84.584\n2014-04-16 19:24:00,92.166\n2014-04-16 19:29:00,92.5\n2014-04-16 19:34:00,89.874\n2014-04-16 19:39:00,89.416\n2014-04-16 19:44:00,91.51\n2014-04-16 19:49:00,93.5\n2014-04-16 19:54:00,91.876\n2014-04-16 19:59:00,92.676\n2014-04-16 20:04:00,89.044\n2014-04-16 20:09:00,94.208\n2014-04-16 20:14:00,91.70200000000001\n2014-04-16 20:19:00,90.556\n2014-04-16 20:24:00,85.61200000000002\n2014-04-16 20:29:00,89.02\n2014-04-16 20:34:00,84.78\n2014-04-16 20:39:00,87.806\n2014-04-16 20:44:00,89.874\n2014-04-16 20:49:00,87.792\n2014-04-16 20:54:00,90.666\n2014-04-16 20:59:00,88.67399999999998\n2014-04-16 21:04:00,87.124\n2014-04-16 21:09:00,88.958\n2014-04-16 21:14:00,90.374\n2014-04-16 21:19:00,90.916\n2014-04-16 21:24:00,87.75\n2014-04-16 21:29:00,90.792\n2014-04-16 21:34:00,82.0\n2014-04-16 21:39:00,92.806\n2014-04-16 21:44:00,85.82799999999997\n2014-04-16 21:49:00,90.632\n2014-04-16 21:54:00,92.44\n2014-04-16 21:59:00,87.626\n2014-04-16 22:04:00,87.75\n2014-04-16 22:09:00,95.22399999999999\n2014-04-16 22:14:00,91.182\n2014-04-16 22:19:00,89.52600000000002\n2014-04-16 22:24:00,84.686\n2014-04-16 22:29:00,89.01799999999999\n2014-04-16 22:34:00,83.664\n2014-04-16 22:39:00,93.134\n2014-04-16 22:44:00,90.25\n2014-04-16 22:49:00,86.584\n2014-04-16 22:54:00,87.792\n2014-04-16 22:59:00,85.292\n2014-04-16 23:04:00,88.95200000000001\n2014-04-16 23:09:00,89.542\n2014-04-16 23:14:00,93.084\n2014-04-16 23:19:00,88.958\n2014-04-16 23:24:00,92.542\n2014-04-16 23:29:00,88.458\n2014-04-16 23:34:00,87.166\n2014-04-16 23:39:00,86.876\n2014-04-16 23:44:00,86.166\n2014-04-16 23:49:00,88.376\n2014-04-16 23:54:00,85.25200000000002\n2014-04-16 23:59:00,88.846\n2014-04-17 00:04:00,90.416\n2014-04-17 00:09:00,95.0\n2014-04-17 00:14:00,90.75\n2014-04-17 00:19:00,91.626\n2014-04-17 00:24:00,88.792\n2014-04-17 00:29:00,85.75\n2014-04-17 00:34:00,88.96799999999998\n2014-04-17 00:39:00,86.792\n2014-04-17 00:44:00,85.584\n2014-04-17 00:49:00,88.624\n2014-04-17 00:54:00,87.916\n2014-04-17 00:59:00,89.28399999999998\n2014-04-17 01:04:00,87.52799999999998\n2014-04-17 01:09:00,93.796\n2014-04-17 01:14:00,91.766\n2014-04-17 01:19:00,83.63\n2014-04-17 01:24:00,93.132\n2014-04-17 01:29:00,86.456\n2014-04-17 01:34:00,83.584\n2014-04-17 01:39:00,92.26799999999999\n2014-04-17 01:44:00,87.958\n2014-04-17 01:49:00,86.25\n2014-04-17 01:54:00,88.274\n2014-04-17 01:59:00,87.42\n2014-04-17 02:04:00,86.542\n2014-04-17 02:09:00,88.126\n2014-04-17 02:14:00,92.958\n2014-04-17 02:19:00,92.17200000000001\n2014-04-17 02:24:00,91.166\n2014-04-17 02:29:00,92.416\n2014-04-17 02:34:00,87.564\n2014-04-17 02:39:00,91.34200000000001\n2014-04-17 02:44:00,83.626\n2014-04-17 02:49:00,86.124\n2014-04-17 02:54:00,89.742\n2014-04-17 02:59:00,87.292\n2014-04-17 03:04:00,85.79\n2014-04-17 03:09:00,88.786\n2014-04-17 03:14:00,94.08\n2014-04-17 03:19:00,91.492\n2014-04-17 03:24:00,84.56\n2014-04-17 03:29:00,88.836\n2014-04-17 03:34:00,89.124\n2014-04-17 03:39:00,85.686\n2014-04-17 03:44:00,85.584\n2014-04-17 03:49:00,84.96\n2014-04-17 03:54:00,86.94\n2014-04-17 03:59:00,86.708\n2014-04-17 04:04:00,86.626\n2014-04-17 04:09:00,88.434\n2014-04-17 04:14:00,88.08\n2014-04-17 04:19:00,88.756\n2014-04-17 04:24:00,90.166\n2014-04-17 04:29:00,88.0\n2014-04-17 04:34:00,90.708\n2014-04-17 04:39:00,88.708\n2014-04-17 04:44:00,84.792\n2014-04-17 04:49:00,87.374\n2014-04-17 04:54:00,85.208\n2014-04-17 04:59:00,88.292\n2014-04-17 05:04:00,88.208\n2014-04-17 05:09:00,95.416\n2014-04-17 05:14:00,92.5\n2014-04-17 05:19:00,91.916\n2014-04-17 05:24:00,88.10600000000002\n2014-04-17 05:29:00,87.698\n2014-04-17 05:34:00,86.56200000000004\n2014-04-17 05:39:00,87.11200000000002\n2014-04-17 05:44:00,87.256\n2014-04-17 05:49:00,85.916\n2014-04-17 05:54:00,93.63799999999999\n2014-04-17 05:59:00,89.58\n2014-04-17 06:04:00,88.05\n2014-04-17 06:09:00,86.068\n2014-04-17 06:14:00,93.22399999999999\n2014-04-17 06:19:00,93.416\n2014-04-17 06:24:00,89.25\n2014-04-17 06:29:00,85.39200000000002\n2014-04-17 06:34:00,88.458\n2014-04-17 06:39:00,90.25\n2014-04-17 06:44:00,86.63600000000002\n2014-04-17 06:49:00,87.16799999999998\n2014-04-17 06:54:00,82.292\n2014-04-17 06:59:00,88.824\n2014-04-17 07:04:00,89.162\n2014-04-17 07:09:00,91.45\n2014-04-17 07:14:00,88.514\n2014-04-17 07:19:00,85.104\n2014-04-17 07:24:00,89.17200000000004\n2014-04-17 07:29:00,92.484\n2014-04-17 07:34:00,88.25\n2014-04-17 07:39:00,85.876\n2014-04-17 07:44:00,88.24600000000002\n2014-04-17 07:49:00,87.244\n2014-04-17 07:54:00,88.738\n2014-04-17 07:59:00,90.46600000000001\n2014-04-17 08:04:00,91.37\n2014-04-17 08:09:00,93.042\n2014-04-17 08:14:00,92.72399999999999\n2014-04-17 08:19:00,88.834\n2014-04-17 08:24:00,87.198\n2014-04-17 08:29:00,86.5\n2014-04-17 08:34:00,86.75\n2014-04-17 08:39:00,84.208\n2014-04-17 08:44:00,85.0\n2014-04-17 08:49:00,87.838\n2014-04-17 08:54:00,90.834\n2014-04-17 08:59:00,86.374\n2014-04-17 09:04:00,87.126\n2014-04-17 09:09:00,88.208\n2014-04-17 09:14:00,88.39\n2014-04-17 09:19:00,90.444\n2014-04-17 09:24:00,88.80799999999998\n2014-04-17 09:29:00,89.5\n2014-04-17 09:34:00,90.126\n2014-04-17 09:39:00,91.25\n2014-04-17 09:44:00,87.708\n2014-04-17 09:49:00,89.584\n2014-04-17 09:54:00,86.324\n2014-04-17 09:59:00,88.626\n2014-04-17 10:04:00,86.28\n2014-04-17 10:09:00,90.542\n2014-04-17 10:14:00,87.874\n2014-04-17 10:19:00,85.874\n2014-04-17 10:24:00,91.818\n2014-04-17 10:29:00,91.542\n2014-04-17 10:34:00,92.47200000000001\n2014-04-17 10:39:00,86.72399999999998\n2014-04-17 10:44:00,90.044\n2014-04-17 10:49:00,91.666\n2014-04-17 10:54:00,85.25\n2014-04-17 10:59:00,87.02799999999998\n2014-04-17 11:04:00,89.708\n2014-04-17 11:09:00,89.666\n2014-04-17 11:14:00,89.708\n2014-04-17 11:19:00,89.734\n2014-04-17 11:24:00,89.75\n2014-04-17 11:29:00,87.712\n2014-04-17 11:34:00,88.25\n2014-04-17 11:39:00,91.166\n2014-04-17 11:44:00,88.084\n2014-04-17 11:49:00,89.834\n2014-04-17 11:54:00,85.542\n2014-04-17 11:59:00,88.208\n2014-04-17 12:04:00,91.25\n2014-04-17 12:09:00,90.416\n2014-04-17 12:14:00,89.834\n2014-04-17 12:19:00,89.586\n2014-04-17 12:24:00,88.958\n2014-04-17 12:29:00,90.626\n2014-04-17 12:34:00,90.634\n2014-04-17 12:39:00,88.79\n2014-04-17 12:44:00,88.042\n2014-04-17 12:49:00,86.666\n2014-04-17 12:54:00,83.792\n2014-04-17 12:59:00,86.542\n2014-04-17 13:04:00,89.82799999999996\n2014-04-17 13:09:00,87.62200000000001\n2014-04-17 13:14:00,89.166\n2014-04-17 13:19:00,90.0\n2014-04-17 13:24:00,88.374\n2014-04-17 13:29:00,92.334\n2014-04-17 13:34:00,93.208\n2014-04-17 13:39:00,88.0\n2014-04-17 13:44:00,87.012\n2014-04-17 13:49:00,89.0\n2014-04-17 13:54:00,86.626\n2014-04-17 13:59:00,87.584\n2014-04-17 14:04:00,84.292\n2014-04-17 14:09:00,90.916\n2014-04-17 14:14:00,89.458\n2014-04-17 14:19:00,91.5\n2014-04-17 14:24:00,91.89200000000001\n2014-04-17 14:29:00,89.598\n2014-04-17 14:34:00,91.792\n2014-04-17 14:39:00,86.084\n2014-04-17 14:44:00,83.33200000000002\n2014-04-17 14:49:00,87.458\n2014-04-17 14:54:00,85.75\n2014-04-17 14:59:00,89.708\n2014-04-17 15:04:00,87.416\n2014-04-17 15:09:00,95.346\n2014-04-17 15:14:00,92.426\n2014-04-17 15:19:00,88.416\n2014-04-17 15:24:00,87.334\n2014-04-17 15:29:00,87.01799999999999\n2014-04-17 15:34:00,90.67200000000001\n2014-04-17 15:39:00,88.33\n2014-04-17 15:44:00,86.75\n2014-04-17 15:49:00,86.124\n2014-04-17 15:54:00,92.916\n2014-04-17 15:59:00,93.182\n2014-04-17 16:04:00,95.0\n2014-04-17 16:09:00,95.584\n2014-04-17 16:14:00,93.834\n2014-04-17 16:19:00,93.374\n2014-04-17 16:24:00,93.042\n2014-04-17 16:29:00,91.792\n2014-04-17 16:34:00,87.626\n2014-04-17 16:39:00,91.75\n2014-04-17 16:44:00,85.69\n2014-04-17 16:49:00,89.26\n2014-04-17 16:54:00,86.164\n2014-04-17 16:59:00,89.334\n2014-04-17 17:04:00,91.84\n2014-04-17 17:09:00,94.0\n2014-04-17 17:14:00,91.25\n2014-04-17 17:19:00,93.0\n2014-04-17 17:24:00,92.25\n2014-04-17 17:29:00,92.914\n2014-04-17 17:34:00,92.5\n2014-04-17 17:39:00,92.958\n2014-04-17 17:44:00,92.958\n2014-04-17 17:49:00,88.43799999999996\n2014-04-17 17:54:00,88.22399999999998\n2014-04-17 17:59:00,92.166\n2014-04-17 18:04:00,93.958\n2014-04-17 18:09:00,92.916\n2014-04-17 18:14:00,93.74\n2014-04-17 18:19:00,92.042\n2014-04-17 18:24:00,92.208\n2014-04-17 18:29:00,94.738\n2014-04-17 18:34:00,94.6\n2014-04-17 18:39:00,91.708\n2014-04-17 18:44:00,92.22399999999999\n2014-04-17 18:49:00,92.542\n2014-04-17 18:54:00,93.32600000000001\n2014-04-17 18:59:00,92.77600000000001\n2014-04-17 19:04:00,88.484\n2014-04-17 19:09:00,93.40799999999999\n2014-04-17 19:14:00,95.12799999999999\n2014-04-17 19:19:00,92.46\n2014-04-17 19:24:00,90.958\n2014-04-17 19:29:00,89.824\n2014-04-17 19:34:00,89.92200000000004\n2014-04-17 19:39:00,89.00399999999998\n2014-04-17 19:44:00,89.25\n2014-04-17 19:49:00,88.626\n2014-04-17 19:54:00,94.51799999999999\n2014-04-17 19:59:00,93.898\n2014-04-17 20:04:00,91.764\n2014-04-17 20:09:00,93.16799999999999\n2014-04-17 20:14:00,89.11399999999998\n2014-04-17 20:19:00,93.07600000000001\n2014-04-17 20:24:00,91.014\n2014-04-17 20:29:00,91.07799999999999\n2014-04-17 20:34:00,94.792\n2014-04-17 20:39:00,93.33200000000001\n2014-04-17 20:44:00,93.88\n2014-04-17 20:49:00,94.124\n2014-04-17 20:54:00,94.542\n2014-04-17 20:59:00,92.126\n2014-04-17 21:04:00,92.166\n2014-04-17 21:09:00,94.458\n2014-04-17 21:14:00,92.25\n2014-04-17 21:19:00,92.834\n2014-04-17 21:24:00,91.428\n2014-04-17 21:29:00,93.292\n2014-04-17 21:34:00,91.792\n2014-04-17 21:39:00,92.666\n2014-04-17 21:44:00,95.042\n2014-04-17 21:49:00,92.25\n2014-04-17 21:54:00,90.916\n2014-04-17 21:59:00,93.88\n2014-04-17 22:04:00,92.124\n2014-04-17 22:09:00,95.042\n2014-04-17 22:14:00,92.542\n2014-04-17 22:19:00,91.042\n2014-04-17 22:24:00,92.75\n2014-04-17 22:29:00,90.416\n2014-04-17 22:34:00,94.084\n2014-04-17 22:39:00,92.166\n2014-04-17 22:44:00,91.208\n2014-04-17 22:49:00,91.916\n2014-04-17 22:54:00,90.916\n2014-04-17 22:59:00,93.43\n2014-04-17 23:04:00,92.874\n2014-04-17 23:09:00,96.262\n2014-04-17 23:14:00,93.37799999999999\n2014-04-17 23:19:00,92.45\n2014-04-17 23:24:00,93.19\n2014-04-17 23:29:00,93.98200000000001\n2014-04-17 23:34:00,93.26\n2014-04-17 23:39:00,90.75\n2014-04-17 23:44:00,92.064\n2014-04-17 23:49:00,94.866\n2014-04-17 23:54:00,93.162\n2014-04-17 23:59:00,93.34\n2014-04-18 00:04:00,92.64200000000001\n2014-04-18 00:09:00,94.834\n2014-04-18 00:14:00,91.666\n2014-04-18 00:19:00,91.584\n2014-04-18 00:24:00,92.666\n2014-04-18 00:29:00,93.618\n2014-04-18 00:34:00,94.568\n2014-04-18 00:39:00,93.334\n2014-04-18 00:44:00,94.166\n2014-04-18 00:49:00,92.584\n2014-04-18 00:54:00,94.95\n2014-04-18 00:59:00,91.64399999999999\n2014-04-18 01:04:00,87.874\n2014-04-18 01:09:00,92.494\n2014-04-18 01:14:00,90.96799999999999\n2014-04-18 01:19:00,92.374\n2014-04-18 01:24:00,93.042\n2014-04-18 01:29:00,92.542\n2014-04-18 01:34:00,93.624\n2014-04-18 01:39:00,92.458\n2014-04-18 01:44:00,94.21\n2014-04-18 01:49:00,89.834\n2014-04-18 01:54:00,89.656\n2014-04-18 01:59:00,94.116\n2014-04-18 02:04:00,90.084\n2014-04-18 02:09:00,94.772\n2014-04-18 02:14:00,91.376\n2014-04-18 02:19:00,93.126\n2014-04-18 02:24:00,92.90799999999999\n2014-04-18 02:29:00,91.684\n2014-04-18 02:34:00,90.708\n2014-04-18 02:39:00,92.94\n2014-04-18 02:44:00,88.042\n2014-04-18 02:49:00,89.666\n2014-04-18 02:54:00,89.208\n2014-04-18 02:59:00,94.03399999999999\n2014-04-18 03:04:00,90.432\n2014-04-18 03:09:00,94.0\n2014-04-18 03:14:00,92.61200000000001\n2014-04-18 03:19:00,94.19\n2014-04-18 03:24:00,92.766\n2014-04-18 03:29:00,95.134\n2014-04-18 03:34:00,89.98\n2014-04-18 03:39:00,88.916\n2014-04-18 03:44:00,88.792\n2014-04-18 03:49:00,89.448\n2014-04-18 03:54:00,90.042\n2014-04-18 03:59:00,90.334\n2014-04-18 04:04:00,87.662\n2014-04-18 04:09:00,91.42200000000001\n2014-04-18 04:14:00,91.848\n2014-04-18 04:19:00,94.458\n2014-04-18 04:24:00,91.876\n2014-04-18 04:29:00,93.698\n2014-04-18 04:34:00,93.07\n2014-04-18 04:39:00,91.574\n2014-04-18 04:44:00,90.738\n2014-04-18 04:49:00,90.544\n2014-04-18 04:54:00,90.428\n2014-04-18 04:59:00,92.626\n2014-04-18 05:04:00,88.0\n2014-04-18 05:09:00,93.292\n2014-04-18 05:14:00,92.916\n2014-04-18 05:19:00,92.374\n2014-04-18 05:24:00,92.958\n2014-04-18 05:29:00,90.542\n2014-04-18 05:34:00,93.5\n2014-04-18 05:39:00,91.916\n2014-04-18 05:44:00,90.60799999999999\n2014-04-18 05:49:00,92.208\n2014-04-18 05:54:00,90.208\n2014-04-18 05:59:00,91.85600000000001\n2014-04-18 06:04:00,90.334\n2014-04-18 06:09:00,94.71600000000001\n2014-04-18 06:14:00,91.376\n2014-04-18 06:19:00,90.458\n2014-04-18 06:24:00,93.352\n2014-04-18 06:29:00,88.428\n2014-04-18 06:34:00,92.084\n2014-04-18 06:39:00,92.75\n2014-04-18 06:44:00,91.708\n2014-04-18 06:49:00,92.124\n2014-04-18 06:54:00,93.084\n2014-04-18 06:59:00,95.542\n2014-04-18 07:04:00,86.208\n2014-04-18 07:09:00,95.416\n2014-04-18 07:14:00,91.916\n2014-04-18 07:19:00,87.084\n2014-04-18 07:24:00,84.488\n2014-04-18 07:29:00,89.416\n2014-04-18 07:34:00,85.208\n2014-04-18 07:39:00,90.0\n2014-04-18 07:44:00,83.29\n2014-04-18 07:49:00,89.366\n2014-04-18 07:54:00,88.454\n2014-04-18 07:59:00,89.682\n2014-04-18 08:04:00,89.258\n2014-04-18 08:09:00,94.708\n2014-04-18 08:14:00,92.458\n2014-04-18 08:19:00,86.988\n2014-04-18 08:24:00,87.64200000000002\n2014-04-18 08:29:00,89.75\n2014-04-18 08:34:00,88.426\n2014-04-18 08:39:00,85.208\n2014-04-18 08:44:00,88.916\n2014-04-18 08:49:00,83.75\n2014-04-18 08:54:00,89.986\n2014-04-18 08:59:00,89.78\n2014-04-18 09:04:00,90.572\n2014-04-18 09:09:00,95.63600000000001\n2014-04-18 09:14:00,91.97399999999999\n2014-04-18 09:19:00,87.876\n2014-04-18 09:24:00,84.584\n2014-04-18 09:29:00,89.0\n2014-04-18 09:34:00,86.626\n2014-04-18 09:39:00,85.334\n2014-04-18 09:44:00,88.666\n2014-04-18 09:49:00,89.772\n2014-04-18 09:54:00,87.516\n2014-04-18 09:59:00,90.374\n2014-04-18 10:04:00,87.458\n2014-04-18 10:09:00,93.876\n2014-04-18 10:14:00,92.208\n2014-04-18 10:19:00,86.52600000000002\n2014-04-18 10:24:00,92.604\n2014-04-18 10:29:00,92.0\n2014-04-18 10:34:00,89.584\n2014-04-18 10:39:00,88.53\n2014-04-18 10:44:00,89.23\n2014-04-18 10:49:00,87.042\n2014-04-18 10:54:00,87.454\n2014-04-18 10:59:00,87.126\n2014-04-18 11:04:00,87.646\n2014-04-18 11:09:00,88.666\n2014-04-18 11:14:00,92.84\n2014-04-18 11:19:00,89.208\n2014-04-18 11:24:00,89.084\n2014-04-18 11:29:00,94.292\n2014-04-18 11:34:00,92.376\n2014-04-18 11:39:00,88.874\n2014-04-18 11:44:00,87.416\n2014-04-18 11:49:00,87.24\n2014-04-18 11:54:00,86.17200000000004\n2014-04-18 11:59:00,85.626\n2014-04-18 12:04:00,87.416\n2014-04-18 12:09:00,91.084\n2014-04-18 12:14:00,90.664\n2014-04-18 12:19:00,92.376\n2014-04-18 12:24:00,93.02\n2014-04-18 12:29:00,89.23\n2014-04-18 12:34:00,86.876\n2014-04-18 12:39:00,87.042\n2014-04-18 12:44:00,86.48\n2014-04-18 12:49:00,87.126\n2014-04-18 12:54:00,84.792\n2014-04-18 12:59:00,87.416\n2014-04-18 13:04:00,85.75\n2014-04-18 13:09:00,92.75\n2014-04-18 13:14:00,89.834\n2014-04-18 13:19:00,90.33\n2014-04-18 13:24:00,91.35\n2014-04-18 13:29:00,91.774\n2014-04-18 13:34:00,86.626\n2014-04-18 13:39:00,90.0\n2014-04-18 13:44:00,88.134\n2014-04-18 13:49:00,90.96799999999999\n2014-04-18 13:54:00,88.042\n2014-04-18 13:59:00,85.626\n2014-04-18 14:04:00,84.042\n2014-04-18 14:09:00,94.874\n2014-04-18 14:14:00,90.75\n2014-04-18 14:19:00,92.792\n2014-04-18 14:24:00,86.288\n2014-04-18 14:29:00,88.75\n2014-04-18 14:34:00,87.416\n2014-04-18 14:39:00,90.51\n2014-04-18 14:44:00,90.876\n2014-04-18 14:49:00,89.756\n2014-04-18 14:54:00,88.09200000000001\n2014-04-18 14:59:00,87.916\n2014-04-18 15:04:00,87.124\n2014-04-18 15:09:00,92.5\n2014-04-18 15:14:00,93.458\n2014-04-18 15:19:00,87.792\n2014-04-18 15:24:00,87.0\n2014-04-18 15:29:00,85.334\n2014-04-18 15:34:00,88.458\n2014-04-18 15:39:00,90.374\n2014-04-18 15:44:00,85.594\n2014-04-18 15:49:00,88.916\n2014-04-18 15:54:00,85.166\n2014-04-18 15:59:00,90.292\n2014-04-18 16:04:00,88.042\n2014-04-18 16:09:00,87.292\n2014-04-18 16:14:00,89.49600000000002\n2014-04-18 16:19:00,93.042\n2014-04-18 16:24:00,91.25\n2014-04-18 16:29:00,92.334\n2014-04-18 16:34:00,87.75\n2014-04-18 16:39:00,88.098\n2014-04-18 16:44:00,86.876\n2014-04-18 16:49:00,87.416\n2014-04-18 16:54:00,88.01\n2014-04-18 16:59:00,86.75\n2014-04-18 17:04:00,87.792\n2014-04-18 17:09:00,87.374\n2014-04-18 17:14:00,91.75\n2014-04-18 17:19:00,92.416\n2014-04-18 17:24:00,90.042\n2014-04-18 17:29:00,86.75\n2014-04-18 17:34:00,89.682\n2014-04-18 17:39:00,86.934\n2014-04-18 17:44:00,87.834\n2014-04-18 17:49:00,86.5\n2014-04-18 17:54:00,88.0\n2014-04-18 17:59:00,86.62799999999999\n2014-04-18 18:04:00,87.794\n2014-04-18 18:09:00,91.15799999999999\n2014-04-18 18:14:00,90.73\n2014-04-18 18:19:00,92.874\n2014-04-18 18:24:00,86.916\n2014-04-18 18:29:00,85.626\n2014-04-18 18:34:00,90.742\n2014-04-18 18:39:00,90.67399999999999\n2014-04-18 18:44:00,86.936\n2014-04-18 18:49:00,84.958\n2014-04-18 18:54:00,89.792\n2014-04-18 18:59:00,87.25\n2014-04-18 19:04:00,88.594\n2014-04-18 19:09:00,92.186\n2014-04-18 19:14:00,91.042\n2014-04-18 19:19:00,90.118\n2014-04-18 19:24:00,92.1\n2014-04-18 19:29:00,91.458\n2014-04-18 19:34:00,92.792\n2014-04-18 19:39:00,90.516\n2014-04-18 19:44:00,89.564\n2014-04-18 19:49:00,89.488\n2014-04-18 19:54:00,92.23\n2014-04-18 19:59:00,91.876\n2014-04-18 20:04:00,86.744\n2014-04-18 20:09:00,94.124\n2014-04-18 20:14:00,93.334\n2014-04-18 20:19:00,91.376\n2014-04-18 20:24:00,87.626\n2014-04-18 20:29:00,86.5\n2014-04-18 20:34:00,87.60799999999998\n2014-04-18 20:39:00,87.708\n2014-04-18 20:44:00,86.542\n2014-04-18 20:49:00,87.3\n2014-04-18 20:54:00,87.914\n2014-04-18 20:59:00,87.626\n2014-04-18 21:04:00,87.416\n2014-04-18 21:09:00,90.376\n2014-04-18 21:14:00,90.69200000000001\n2014-04-18 21:19:00,93.042\n2014-04-18 21:24:00,87.446\n2014-04-18 21:29:00,89.792\n2014-04-18 21:34:00,87.874\n2014-04-18 21:39:00,86.416\n2014-04-18 21:44:00,86.876\n2014-04-18 21:49:00,87.126\n2014-04-18 21:54:00,87.898\n2014-04-18 21:59:00,88.084\n2014-04-18 22:04:00,92.584\n2014-04-18 22:09:00,92.944\n2014-04-18 22:14:00,95.014\n2014-04-18 22:19:00,88.42\n2014-04-18 22:24:00,88.042\n2014-04-18 22:29:00,87.666\n2014-04-18 22:34:00,87.542\n2014-04-18 22:39:00,86.084\n2014-04-18 22:44:00,87.708\n2014-04-18 22:49:00,88.292\n2014-04-18 22:54:00,85.256\n2014-04-18 22:59:00,87.708\n2014-04-18 23:04:00,90.75\n2014-04-18 23:09:00,92.88\n2014-04-18 23:14:00,92.258\n2014-04-18 23:19:00,93.286\n2014-04-18 23:24:00,92.584\n2014-04-18 23:29:00,90.48200000000001\n2014-04-18 23:34:00,87.584\n2014-04-18 23:39:00,86.75399999999998\n2014-04-18 23:44:00,87.042\n2014-04-18 23:49:00,86.916\n2014-04-18 23:54:00,86.542\n2014-04-18 23:59:00,89.334\n2014-04-19 00:04:00,86.67399999999998\n2014-04-19 00:09:00,93.624\n2014-04-19 00:14:00,92.25\n2014-04-19 00:19:00,91.124\n2014-04-19 00:24:00,88.666\n2014-04-19 00:29:00,85.5\n2014-04-19 00:34:00,91.152\n2014-04-19 00:39:00,87.458\n2014-04-19 00:44:00,84.458\n2014-04-19 00:49:00,91.916\n2014-04-19 00:54:00,89.166\n2014-04-19 00:59:00,87.708\n2014-04-19 01:04:00,87.876\n2014-04-19 01:09:00,89.458\n2014-04-19 01:14:00,92.47\n2014-04-19 01:19:00,91.126\n2014-04-19 01:24:00,89.584\n2014-04-19 01:29:00,87.0\n2014-04-19 01:34:00,88.25\n2014-04-19 01:39:00,86.958\n2014-04-19 01:44:00,87.25\n2014-04-19 01:49:00,87.584\n2014-04-19 01:54:00,86.584\n2014-04-19 01:59:00,90.75\n2014-04-19 02:04:00,89.042\n2014-04-19 02:09:00,94.124\n2014-04-19 02:14:00,91.208\n2014-04-19 02:19:00,91.084\n2014-04-19 02:24:00,89.166\n2014-04-19 02:29:00,87.916\n2014-04-19 02:34:00,88.05799999999998\n2014-04-19 02:39:00,85.626\n2014-04-19 02:44:00,86.708\n2014-04-19 02:49:00,86.416\n2014-04-19 02:54:00,88.758\n2014-04-19 02:59:00,87.916\n2014-04-19 03:04:00,88.25\n2014-04-19 03:09:00,86.82799999999996\n2014-04-19 03:14:00,93.042\n2014-04-19 03:19:00,92.79799999999999\n2014-04-19 03:24:00,85.958\n2014-04-19 03:29:00,86.292\n2014-04-19 03:34:00,88.088\n2014-04-19 03:39:00,85.788\n2014-04-19 03:44:00,90.084\n2014-04-19 03:49:00,86.834\n2014-04-19 03:54:00,86.834\n2014-04-19 03:59:00,86.25200000000002\n2014-04-19 04:04:00,87.126\n2014-04-19 04:09:00,94.0\n2014-04-19 04:14:00,92.792\n2014-04-19 04:19:00,86.708\n2014-04-19 04:24:00,87.296\n2014-04-19 04:29:00,85.708\n2014-04-19 04:34:00,86.166\n2014-04-19 04:39:00,87.584\n2014-04-19 04:44:00,88.126\n2014-04-19 04:49:00,84.32600000000002\n2014-04-19 04:54:00,90.354\n2014-04-19 04:59:00,87.572\n2014-04-19 05:04:00,88.166\n2014-04-19 05:09:00,93.834\n2014-04-19 05:14:00,90.708\n2014-04-19 05:19:00,91.708\n2014-04-19 05:24:00,89.458\n2014-04-19 05:29:00,86.874\n2014-04-19 05:34:00,86.764\n2014-04-19 05:39:00,84.834\n2014-04-19 05:44:00,88.458\n2014-04-19 05:49:00,85.876\n2014-04-19 05:54:00,88.584\n2014-04-19 05:59:00,90.542\n2014-04-19 06:04:00,88.666\n2014-04-19 06:09:00,89.376\n2014-04-19 06:14:00,93.916\n2014-04-19 06:19:00,91.428\n2014-04-19 06:24:00,86.666\n2014-04-19 06:29:00,86.916\n2014-04-19 06:34:00,87.334\n2014-04-19 06:39:00,90.76799999999999\n2014-04-19 06:44:00,86.376\n2014-04-19 06:49:00,87.542\n2014-04-19 06:54:00,87.25\n2014-04-19 06:59:00,87.584\n2014-04-19 07:04:00,87.084\n2014-04-19 07:09:00,87.57600000000002\n2014-04-19 07:14:00,90.458\n2014-04-19 07:19:00,93.838\n2014-04-19 07:24:00,89.458\n2014-04-19 07:29:00,89.834\n2014-04-19 07:34:00,87.75\n2014-04-19 07:39:00,86.334\n2014-04-19 07:44:00,88.334\n2014-04-19 07:49:00,85.984\n2014-04-19 07:54:00,88.18\n2014-04-19 07:59:00,87.556\n2014-04-19 08:04:00,87.72200000000002\n2014-04-19 08:09:00,88.75\n2014-04-19 08:14:00,92.916\n2014-04-19 08:19:00,93.126\n2014-04-19 08:24:00,87.666\n2014-04-19 08:29:00,89.542\n2014-04-19 08:34:00,87.584\n2014-04-19 08:39:00,87.542\n2014-04-19 08:44:00,86.376\n2014-04-19 08:49:00,87.458\n2014-04-19 08:54:00,87.916\n2014-04-19 08:59:00,88.126\n2014-04-19 09:04:00,87.25\n2014-04-19 09:09:00,88.792\n2014-04-19 09:14:00,93.416\n2014-04-19 09:19:00,92.334\n2014-04-19 09:24:00,84.584\n2014-04-19 09:29:00,89.094\n2014-04-19 09:34:00,89.35799999999998\n2014-04-19 09:39:00,87.792\n2014-04-19 09:44:00,90.792\n2014-04-19 09:49:00,87.75\n2014-04-19 09:54:00,87.958\n2014-04-19 09:59:00,87.792\n2014-04-19 10:04:00,88.834\n2014-04-19 10:09:00,92.75\n2014-04-19 10:14:00,92.834\n2014-04-19 10:19:00,88.126\n2014-04-19 10:24:00,87.166\n2014-04-19 10:29:00,87.834\n2014-04-19 10:34:00,85.758\n2014-04-19 10:39:00,88.876\n2014-04-19 10:44:00,86.666\n2014-04-19 10:49:00,87.25\n2014-04-19 10:54:00,86.758\n2014-04-19 10:59:00,87.1\n2014-04-19 11:04:00,87.322\n2014-04-19 11:09:00,95.876\n2014-04-19 11:14:00,90.126\n2014-04-19 11:19:00,88.126\n2014-04-19 11:24:00,87.458\n2014-04-19 11:29:00,86.834\n2014-04-19 11:34:00,87.88600000000002\n2014-04-19 11:39:00,84.79799999999999\n2014-04-19 11:44:00,85.208\n2014-04-19 11:49:00,89.958\n2014-04-19 11:54:00,84.376\n2014-04-19 11:59:00,92.916\n2014-04-19 12:04:00,91.75\n2014-04-19 12:09:00,93.334\n2014-04-19 12:14:00,93.166\n2014-04-19 12:19:00,86.416\n2014-04-19 12:24:00,86.708\n2014-04-19 12:29:00,89.834\n2014-04-19 12:34:00,83.874\n2014-04-19 12:39:00,90.334\n2014-04-19 12:44:00,85.81\n2014-04-19 12:49:00,89.514\n2014-04-19 12:54:00,88.21799999999998\n2014-04-19 12:59:00,87.584\n2014-04-19 13:04:00,88.0\n2014-04-19 13:09:00,93.056\n2014-04-19 13:14:00,91.24600000000001\n2014-04-19 13:19:00,89.376\n2014-04-19 13:24:00,85.834\n2014-04-19 13:29:00,89.0\n2014-04-19 13:34:00,86.9\n2014-04-19 13:39:00,87.37\n2014-04-19 13:44:00,86.0\n2014-04-19 13:49:00,86.04799999999999\n2014-04-19 13:54:00,90.81200000000001\n2014-04-19 13:59:00,86.292\n2014-04-19 14:04:00,87.0\n2014-04-19 14:09:00,91.08\n2014-04-19 14:14:00,92.126\n2014-04-19 14:19:00,92.54\n2014-04-19 14:24:00,86.734\n2014-04-19 14:29:00,88.52\n2014-04-19 14:34:00,90.916\n2014-04-19 14:39:00,86.416\n2014-04-19 14:44:00,86.91799999999998\n2014-04-19 14:49:00,88.376\n2014-04-19 14:54:00,89.61\n2014-04-19 14:59:00,87.35600000000002\n2014-04-19 15:04:00,87.166\n2014-04-19 15:09:00,89.292\n2014-04-19 15:14:00,93.084\n2014-04-19 15:19:00,92.75\n2014-04-19 15:24:00,85.992\n2014-04-19 15:29:00,87.75\n2014-04-19 15:34:00,86.02799999999998\n2014-04-19 15:39:00,90.542\n2014-04-19 15:44:00,87.25\n2014-04-19 15:49:00,87.708\n2014-04-19 15:54:00,87.958\n2014-04-19 15:59:00,88.084\n2014-04-19 16:04:00,88.37200000000001\n2014-04-19 16:09:00,90.292\n2014-04-19 16:14:00,93.084\n2014-04-19 16:19:00,94.416\n2014-04-19 16:24:00,88.126\n2014-04-19 16:29:00,85.666\n2014-04-19 16:34:00,89.542\n2014-04-19 16:39:00,87.302\n2014-04-19 16:44:00,86.708\n2014-04-19 16:49:00,87.208\n2014-04-19 16:54:00,87.876\n2014-04-19 16:59:00,87.83\n2014-04-19 17:04:00,87.626\n2014-04-19 17:09:00,87.916\n2014-04-19 17:14:00,93.458\n2014-04-19 17:19:00,90.624\n2014-04-19 17:24:00,85.33\n2014-04-19 17:29:00,89.042\n2014-04-19 17:34:00,89.072\n2014-04-19 17:39:00,87.542\n2014-04-19 17:44:00,86.874\n2014-04-19 17:49:00,87.792\n2014-04-19 17:54:00,85.762\n2014-04-19 17:59:00,87.52600000000002\n2014-04-19 18:04:00,86.17200000000004\n2014-04-19 18:09:00,93.0\n2014-04-19 18:14:00,90.542\n2014-04-19 18:19:00,92.99799999999999\n2014-04-19 18:24:00,88.45\n2014-04-19 18:29:00,91.146\n2014-04-19 18:34:00,85.07600000000002\n2014-04-19 18:39:00,84.75\n2014-04-19 18:44:00,91.416\n2014-04-19 18:49:00,91.59\n2014-04-19 18:54:00,87.916\n2014-04-19 18:59:00,87.208\n2014-04-19 19:04:00,87.196\n2014-04-19 19:09:00,95.124\n2014-04-19 19:14:00,94.042\n2014-04-19 19:19:00,89.458\n2014-04-19 19:24:00,85.75\n2014-04-19 19:29:00,91.124\n2014-04-19 19:34:00,87.834\n2014-04-19 19:39:00,87.792\n2014-04-19 19:44:00,87.374\n2014-04-19 19:49:00,87.064\n2014-04-19 19:54:00,87.846\n2014-04-19 19:59:00,88.416\n2014-04-19 20:04:00,88.834\n2014-04-19 20:09:00,90.39\n2014-04-19 20:14:00,92.584\n2014-04-19 20:19:00,92.288\n2014-04-19 20:24:00,86.5\n2014-04-19 20:29:00,83.5\n2014-04-19 20:34:00,88.10600000000002\n2014-04-19 20:39:00,89.916\n2014-04-19 20:44:00,89.834\n2014-04-19 20:49:00,86.88600000000002\n2014-04-19 20:54:00,88.166\n2014-04-19 20:59:00,85.916\n2014-04-19 21:04:00,88.44\n2014-04-19 21:09:00,91.542\n2014-04-19 21:14:00,90.416\n2014-04-19 21:19:00,92.708\n2014-04-19 21:24:00,88.166\n2014-04-19 21:29:00,92.292\n2014-04-19 21:34:00,87.0\n2014-04-19 21:39:00,91.584\n2014-04-19 21:44:00,86.834\n2014-04-19 21:49:00,87.07\n2014-04-19 21:54:00,84.792\n2014-04-19 21:59:00,91.91799999999999\n2014-04-19 22:04:00,88.208\n2014-04-19 22:09:00,89.5\n2014-04-19 22:14:00,91.802\n2014-04-19 22:19:00,94.67399999999999\n2014-04-19 22:24:00,87.958\n2014-04-19 22:29:00,90.542\n2014-04-19 22:34:00,88.042\n2014-04-19 22:39:00,87.166\n2014-04-19 22:44:00,86.916\n2014-04-19 22:49:00,86.708\n2014-04-19 22:54:00,85.792\n2014-04-19 22:59:00,87.708\n2014-04-19 23:04:00,88.876\n2014-04-19 23:09:00,91.0\n2014-04-19 23:14:00,92.34200000000001\n2014-04-19 23:19:00,93.82799999999999\n2014-04-19 23:24:00,90.084\n2014-04-19 23:29:00,87.73\n2014-04-19 23:34:00,88.302\n2014-04-19 23:39:00,89.834\n2014-04-19 23:44:00,86.084\n2014-04-19 23:49:00,87.88799999999998\n2014-04-19 23:54:00,87.34200000000001\n2014-04-19 23:59:00,88.708\n2014-04-20 00:04:00,84.874\n2014-04-20 00:09:00,93.458\n2014-04-20 00:14:00,92.834\n2014-04-20 00:19:00,93.166\n2014-04-20 00:24:00,92.292\n2014-04-20 00:29:00,88.624\n2014-04-20 00:34:00,87.384\n2014-04-20 00:39:00,87.542\n2014-04-20 00:44:00,86.834\n2014-04-20 00:49:00,87.208\n2014-04-20 00:54:00,87.458\n2014-04-20 00:59:00,85.458\n2014-04-20 01:04:00,87.79\n2014-04-20 01:09:00,89.374\n2014-04-20 01:14:00,88.5\n2014-04-20 01:19:00,91.124\n2014-04-20 01:24:00,90.5\n2014-04-20 01:29:00,87.958\n2014-04-20 01:34:00,90.584\n2014-04-20 01:39:00,90.27\n2014-04-20 01:44:00,87.834\n2014-04-20 01:49:00,87.374\n2014-04-20 01:54:00,84.708\n2014-04-20 01:59:00,89.584\n2014-04-20 02:04:00,88.208\n2014-04-20 02:09:00,90.834\n2014-04-20 02:14:00,91.042\n2014-04-20 02:19:00,92.25\n2014-04-20 02:24:00,88.416\n2014-04-20 02:29:00,88.374\n2014-04-20 02:34:00,88.126\n2014-04-20 02:39:00,89.384\n2014-04-20 02:44:00,86.916\n2014-04-20 02:49:00,87.584\n2014-04-20 02:54:00,87.25\n2014-04-20 02:59:00,89.25\n2014-04-20 03:04:00,87.708\n2014-04-20 03:09:00,92.792\n2014-04-20 03:14:00,90.512\n2014-04-20 03:19:00,92.084\n2014-04-20 03:24:00,89.88600000000002\n2014-04-20 03:29:00,88.0\n2014-04-20 03:34:00,88.24799999999998\n2014-04-20 03:39:00,86.876\n2014-04-20 03:44:00,86.88600000000002\n2014-04-20 03:49:00,86.542\n2014-04-20 03:54:00,85.042\n2014-04-20 03:59:00,91.626\n2014-04-20 04:04:00,87.066\n2014-04-20 04:09:00,90.152\n2014-04-20 04:14:00,92.89399999999999\n2014-04-20 04:19:00,94.432\n2014-04-20 04:24:00,90.626\n2014-04-20 04:29:00,85.5\n2014-04-20 04:34:00,87.376\n2014-04-20 04:39:00,88.37\n2014-04-20 04:44:00,87.624\n2014-04-20 04:49:00,88.286\n2014-04-20 04:54:00,90.75\n2014-04-20 04:59:00,86.0\n2014-04-20 05:04:00,88.208\n2014-04-20 05:09:00,89.334\n2014-04-20 05:14:00,95.084\n2014-04-20 05:19:00,93.85\n2014-04-20 05:24:00,89.712\n2014-04-20 05:29:00,88.126\n2014-04-20 05:34:00,86.506\n2014-04-20 05:39:00,87.416\n2014-04-20 05:44:00,87.084\n2014-04-20 05:49:00,86.958\n2014-04-20 05:54:00,89.084\n2014-04-20 05:59:00,88.154\n2014-04-20 06:04:00,87.666\n2014-04-20 06:09:00,95.932\n2014-04-20 06:14:00,94.624\n2014-04-20 06:19:00,92.166\n2014-04-20 06:24:00,90.09\n2014-04-20 06:29:00,87.62\n2014-04-20 06:34:00,87.584\n2014-04-20 06:39:00,87.876\n2014-04-20 06:44:00,87.25\n2014-04-20 06:49:00,86.85799999999998\n2014-04-20 06:54:00,85.374\n2014-04-20 06:59:00,91.542\n2014-04-20 07:04:00,87.74799999999998\n2014-04-20 07:09:00,90.166\n2014-04-20 07:14:00,92.916\n2014-04-20 07:19:00,88.876\n2014-04-20 07:24:00,87.588\n2014-04-20 07:29:00,90.834\n2014-04-20 07:34:00,89.166\n2014-04-20 07:39:00,88.042\n2014-04-20 07:44:00,87.874\n2014-04-20 07:49:00,87.38\n2014-04-20 07:54:00,88.792\n2014-04-20 07:59:00,88.166\n2014-04-20 08:04:00,88.0\n2014-04-20 08:09:00,93.834\n2014-04-20 08:14:00,92.334\n2014-04-20 08:19:00,91.084\n2014-04-20 08:24:00,87.792\n2014-04-20 08:29:00,87.67399999999998\n2014-04-20 08:34:00,87.624\n2014-04-20 08:39:00,88.084\n2014-04-20 08:44:00,87.042\n2014-04-20 08:49:00,86.52799999999998\n2014-04-20 08:54:00,86.116\n2014-04-20 08:59:00,87.958\n2014-04-20 09:04:00,89.416\n2014-04-20 09:09:00,90.964\n2014-04-20 09:14:00,93.258\n2014-04-20 09:19:00,90.096\n2014-04-20 09:24:00,88.584\n2014-04-20 09:29:00,87.75\n2014-04-20 09:34:00,86.584\n2014-04-20 09:39:00,87.25\n2014-04-20 09:44:00,87.32799999999996\n2014-04-20 09:49:00,86.96\n2014-04-20 09:54:00,88.6\n2014-04-20 09:59:00,88.39200000000002\n2014-04-20 10:04:00,87.76\n2014-04-20 10:09:00,93.084\n2014-04-20 10:14:00,93.584\n2014-04-20 10:19:00,90.708\n2014-04-20 10:24:00,87.25\n2014-04-20 10:29:00,87.208\n2014-04-20 10:34:00,87.666\n2014-04-20 10:39:00,88.042\n2014-04-20 10:44:00,87.416\n2014-04-20 10:49:00,86.87799999999999\n2014-04-20 10:54:00,87.666\n2014-04-20 10:59:00,86.208\n2014-04-20 11:04:00,88.292\n2014-04-20 11:09:00,89.666\n2014-04-20 11:14:00,92.334\n2014-04-20 11:19:00,93.166\n2014-04-20 11:24:00,87.596\n2014-04-20 11:29:00,87.834\n2014-04-20 11:34:00,86.834\n2014-04-20 11:39:00,87.462\n2014-04-20 11:44:00,87.126\n2014-04-20 11:49:00,86.916\n2014-04-20 11:54:00,88.25\n2014-04-20 11:59:00,88.5\n2014-04-20 12:04:00,87.916\n2014-04-20 12:09:00,92.25\n2014-04-20 12:14:00,94.2\n2014-04-20 12:19:00,90.208\n2014-04-20 12:24:00,88.792\n2014-04-20 12:29:00,85.792\n2014-04-20 12:34:00,87.0\n2014-04-20 12:39:00,88.0\n2014-04-20 12:44:00,86.75399999999998\n2014-04-20 12:49:00,90.916\n2014-04-20 12:54:00,88.542\n2014-04-20 12:59:00,87.414\n2014-04-20 13:04:00,87.708\n2014-04-20 13:09:00,88.584\n2014-04-20 13:14:00,93.5\n2014-04-20 13:19:00,92.624\n2014-04-20 13:24:00,85.786\n2014-04-20 13:29:00,88.824\n2014-04-20 13:34:00,87.334\n2014-04-20 13:39:00,87.042\n2014-04-20 13:44:00,89.456\n2014-04-20 13:49:00,86.916\n2014-04-20 13:54:00,88.374\n2014-04-20 13:59:00,88.206\n2014-04-20 14:04:00,87.958\n2014-04-20 14:09:00,90.67200000000001\n2014-04-20 14:14:00,91.624\n2014-04-20 14:19:00,92.0\n2014-04-20 14:24:00,89.414\n2014-04-20 14:29:00,92.0\n2014-04-20 14:34:00,89.916\n2014-04-20 14:39:00,87.626\n2014-04-20 14:44:00,87.03200000000002\n2014-04-20 14:49:00,86.852\n2014-04-20 14:54:00,87.198\n2014-04-20 14:59:00,86.792\n2014-04-20 15:04:00,89.792\n2014-04-20 15:09:00,90.124\n2014-04-20 15:14:00,91.792\n2014-04-20 15:19:00,92.25\n2014-04-20 15:24:00,85.916\n2014-04-20 15:29:00,88.126\n2014-04-20 15:34:00,87.916\n2014-04-20 15:39:00,86.334\n2014-04-20 15:44:00,87.792\n2014-04-20 15:49:00,89.084\n2014-04-20 15:54:00,87.824\n2014-04-20 15:59:00,88.75\n2014-04-20 16:04:00,87.458\n2014-04-20 16:09:00,90.042\n2014-04-20 16:14:00,89.214\n2014-04-20 16:19:00,90.75\n2014-04-20 16:24:00,89.458\n2014-04-20 16:29:00,89.0\n2014-04-20 16:34:00,87.126\n2014-04-20 16:39:00,90.43\n2014-04-20 16:44:00,87.458\n2014-04-20 16:49:00,87.334\n2014-04-20 16:54:00,85.834\n2014-04-20 16:59:00,90.916\n2014-04-20 17:04:00,88.25\n2014-04-20 17:09:00,95.416\n2014-04-20 17:14:00,93.97\n2014-04-20 17:19:00,88.5\n2014-04-20 17:24:00,87.846\n2014-04-20 17:29:00,86.21799999999998\n2014-04-20 17:34:00,89.66\n2014-04-20 17:39:00,87.244\n2014-04-20 17:44:00,88.868\n2014-04-20 17:49:00,87.564\n2014-04-20 17:54:00,87.006\n2014-04-20 17:59:00,93.902\n2014-04-20 18:04:00,87.944\n2014-04-20 18:09:00,94.986\n2014-04-20 18:14:00,93.072\n2014-04-20 18:19:00,91.36399999999999\n2014-04-20 18:24:00,87.792\n2014-04-20 18:29:00,92.458\n2014-04-20 18:34:00,86.75399999999998\n2014-04-20 18:39:00,88.0\n2014-04-20 18:44:00,87.49600000000002\n2014-04-20 18:49:00,87.294\n2014-04-20 18:54:00,88.354\n2014-04-20 18:59:00,87.876\n2014-04-20 19:04:00,86.876\n2014-04-20 19:09:00,92.374\n2014-04-20 19:14:00,92.042\n2014-04-20 19:19:00,91.5\n2014-04-20 19:24:00,87.834\n2014-04-20 19:29:00,88.084\n2014-04-20 19:34:00,90.75\n2014-04-20 19:39:00,87.916\n2014-04-20 19:44:00,87.626\n2014-04-20 19:49:00,87.36\n2014-04-20 19:54:00,89.22\n2014-04-20 19:59:00,88.96\n2014-04-20 20:04:00,88.166\n2014-04-20 20:09:00,88.958\n2014-04-20 20:14:00,95.5\n2014-04-20 20:19:00,91.792\n2014-04-20 20:24:00,88.584\n2014-04-20 20:29:00,87.83\n2014-04-20 20:34:00,88.25\n2014-04-20 20:39:00,88.958\n2014-04-20 20:44:00,86.874\n2014-04-20 20:49:00,87.208\n2014-04-20 20:54:00,89.126\n2014-04-20 20:59:00,87.792\n2014-04-20 21:04:00,86.5\n2014-04-20 21:09:00,88.084\n2014-04-20 21:14:00,93.132\n2014-04-20 21:19:00,93.588\n2014-04-20 21:24:00,92.916\n2014-04-20 21:29:00,90.056\n2014-04-20 21:34:00,87.014\n2014-04-20 21:39:00,88.166\n2014-04-20 21:44:00,88.43\n2014-04-20 21:49:00,87.334\n2014-04-20 21:54:00,88.542\n2014-04-20 21:59:00,88.834\n2014-04-20 22:04:00,89.124\n2014-04-20 22:09:00,93.354\n2014-04-20 22:14:00,92.792\n2014-04-20 22:19:00,89.208\n2014-04-20 22:24:00,88.25\n2014-04-20 22:29:00,87.958\n2014-04-20 22:34:00,87.834\n2014-04-20 22:39:00,89.044\n2014-04-20 22:44:00,87.11399999999998\n2014-04-20 22:49:00,87.208\n2014-04-20 22:54:00,89.042\n2014-04-20 22:59:00,87.584\n2014-04-20 23:04:00,86.75\n2014-04-20 23:09:00,89.958\n2014-04-20 23:14:00,94.44200000000001\n2014-04-20 23:19:00,93.084\n2014-04-20 23:24:00,92.75\n2014-04-20 23:29:00,89.116\n2014-04-20 23:34:00,87.42\n2014-04-20 23:39:00,87.25\n2014-04-20 23:44:00,87.74\n2014-04-20 23:49:00,87.46600000000002\n2014-04-20 23:54:00,89.37799999999999\n2014-04-20 23:59:00,88.126\n2014-04-21 00:04:00,88.208\n2014-04-21 00:09:00,94.124\n2014-04-21 00:14:00,93.006\n2014-04-21 00:19:00,91.666\n2014-04-21 00:24:00,87.916\n2014-04-21 00:29:00,87.458\n2014-04-21 00:34:00,87.584\n2014-04-21 00:39:00,88.412\n2014-04-21 00:44:00,85.62\n2014-04-21 00:49:00,88.396\n2014-04-21 00:54:00,84.584\n2014-04-21 00:59:00,90.042\n2014-04-21 01:04:00,89.17399999999998\n2014-04-21 01:09:00,91.572\n2014-04-21 01:14:00,91.334\n2014-04-21 01:19:00,94.63799999999999\n2014-04-21 01:24:00,87.398\n2014-04-21 01:29:00,87.74600000000002\n2014-04-21 01:34:00,91.334\n2014-04-21 01:39:00,87.834\n2014-04-21 01:44:00,87.958\n2014-04-21 01:49:00,87.75399999999998\n2014-04-21 01:54:00,89.042\n2014-04-21 01:59:00,88.124\n2014-04-21 02:04:00,88.626\n2014-04-21 02:09:00,90.834\n2014-04-21 02:14:00,92.208\n2014-04-21 02:19:00,91.916\n2014-04-21 02:24:00,88.876\n2014-04-21 02:29:00,88.708\n2014-04-21 02:34:00,91.916\n2014-04-21 02:39:00,88.87799999999999\n2014-04-21 02:44:00,87.54\n2014-04-21 02:49:00,87.084\n2014-04-21 02:54:00,88.334\n2014-04-21 02:59:00,88.0\n2014-04-21 03:04:00,88.166\n2014-04-21 03:09:00,90.54799999999999\n2014-04-21 03:14:00,92.792\n2014-04-21 03:19:00,94.376\n2014-04-21 03:24:00,90.124\n2014-04-21 03:29:00,88.042\n2014-04-21 03:34:00,86.834\n2014-04-21 03:39:00,86.75\n2014-04-21 03:44:00,86.69200000000002\n2014-04-21 03:49:00,87.25\n2014-04-21 03:54:00,87.792\n2014-04-21 03:59:00,87.416\n2014-04-21 04:04:00,90.84200000000001\n2014-04-21 04:09:00,87.95\n2014-04-21 04:14:00,91.906\n2014-04-21 04:19:00,91.5\n2014-04-21 04:24:00,91.834\n2014-04-21 04:29:00,89.708\n2014-04-21 04:34:00,90.368\n2014-04-21 04:39:00,92.654\n2014-04-21 04:44:00,87.292\n2014-04-21 04:49:00,87.126\n2014-04-21 04:54:00,85.196\n2014-04-21 04:59:00,90.96799999999999\n2014-04-21 05:04:00,86.876\n2014-04-21 05:09:00,90.042\n2014-04-21 05:14:00,90.874\n2014-04-21 05:19:00,92.396\n2014-04-21 05:24:00,94.212\n2014-04-21 05:29:00,89.82799999999996\n2014-04-21 05:34:00,88.166\n2014-04-21 05:39:00,87.834\n2014-04-21 05:44:00,87.626\n2014-04-21 05:49:00,87.958\n2014-04-21 05:54:00,89.704\n2014-04-21 05:59:00,88.84200000000001\n2014-04-21 06:04:00,88.962\n2014-04-21 06:09:00,91.5\n2014-04-21 06:14:00,89.626\n2014-04-21 06:19:00,91.792\n2014-04-21 06:24:00,93.376\n2014-04-21 06:29:00,90.458\n2014-04-21 06:34:00,90.322\n2014-04-21 06:39:00,89.804\n2014-04-21 06:44:00,87.374\n2014-04-21 06:49:00,87.876\n2014-04-21 06:54:00,89.712\n2014-04-21 06:59:00,88.916\n2014-04-21 07:04:00,87.958\n2014-04-21 07:09:00,89.626\n2014-04-21 07:14:00,91.376\n2014-04-21 07:19:00,88.0\n2014-04-21 07:24:00,88.588\n2014-04-21 07:29:00,91.586\n2014-04-21 07:34:00,89.708\n2014-04-21 07:39:00,87.876\n2014-04-21 07:44:00,87.25\n2014-04-21 07:49:00,88.91\n2014-04-21 07:54:00,86.86\n2014-04-21 07:59:00,91.904\n2014-04-21 08:04:00,88.62200000000001\n2014-04-21 08:09:00,91.25\n2014-04-21 08:14:00,92.27\n2014-04-21 08:19:00,94.666\n2014-04-21 08:24:00,91.124\n2014-04-21 08:29:00,89.124\n2014-04-21 08:34:00,88.542\n2014-04-21 08:39:00,86.88799999999998\n2014-04-21 08:44:00,86.584\n2014-04-21 08:49:00,89.334\n2014-04-21 08:54:00,90.05\n2014-04-21 08:59:00,88.73\n2014-04-21 09:04:00,87.334\n2014-04-21 09:09:00,92.208\n2014-04-21 09:14:00,94.416\n2014-04-21 09:19:00,89.0\n2014-04-21 09:24:00,88.126\n2014-04-21 09:29:00,87.458\n2014-04-21 09:34:00,87.11200000000002\n2014-04-21 09:39:00,88.876\n2014-04-21 09:44:00,87.25\n2014-04-21 09:49:00,87.666\n2014-04-21 09:54:00,88.686\n2014-04-21 09:59:00,84.89200000000002\n2014-04-21 10:04:00,89.634\n2014-04-21 10:09:00,95.666\n2014-04-21 10:14:00,93.25\n2014-04-21 10:19:00,93.916\n2014-04-21 10:24:00,94.55799999999999\n2014-04-21 10:29:00,90.86\n2014-04-21 10:34:00,94.568\n2014-04-21 10:39:00,96.34\n2014-04-21 10:44:00,93.584\n2014-04-21 10:49:00,91.876\n2014-04-21 10:54:00,93.584\n2014-04-21 10:59:00,92.57600000000001\n2014-04-21 11:04:00,92.022\n2014-04-21 11:09:00,92.458\n2014-04-21 11:14:00,91.428\n2014-04-21 11:19:00,91.208\n2014-04-21 11:24:00,91.334\n2014-04-21 11:29:00,90.874\n2014-04-21 11:34:00,94.12799999999999\n2014-04-21 11:39:00,93.334\n2014-04-21 11:44:00,93.792\n2014-04-21 11:49:00,91.95200000000001\n2014-04-21 11:54:00,94.208\n2014-04-21 11:59:00,94.126\n2014-04-21 12:04:00,92.916\n2014-04-21 12:09:00,94.166\n2014-04-21 12:14:00,93.292\n2014-04-21 12:19:00,93.624\n2014-04-21 12:24:00,93.75\n2014-04-21 12:29:00,92.666\n2014-04-21 12:34:00,91.75\n2014-04-21 12:39:00,93.04799999999999\n2014-04-21 12:44:00,93.374\n2014-04-21 12:49:00,94.0\n2014-04-21 12:54:00,94.542\n2014-04-21 12:59:00,92.0\n2014-04-21 13:04:00,94.0\n2014-04-21 13:09:00,94.916\n2014-04-21 13:14:00,92.9\n2014-04-21 13:19:00,94.124\n2014-04-21 13:24:00,92.60600000000001\n2014-04-21 13:29:00,92.958\n2014-04-21 13:34:00,94.042\n2014-04-21 13:39:00,93.334\n2014-04-21 13:44:00,92.124\n2014-04-21 13:49:00,92.5\n2014-04-21 13:54:00,94.25\n2014-04-21 13:59:00,90.208\n2014-04-21 14:04:00,92.448\n2014-04-21 14:09:00,91.936\n2014-04-21 14:14:00,92.124\n2014-04-21 14:19:00,91.0\n2014-04-21 14:24:00,90.834\n2014-04-21 14:29:00,90.834\n2014-04-21 14:34:00,91.5\n2014-04-21 14:39:00,88.166\n2014-04-21 14:44:00,91.876\n2014-04-21 14:49:00,91.416\n2014-04-21 14:54:00,92.708\n2014-04-21 14:59:00,92.584\n2014-04-21 15:04:00,92.916\n2014-04-21 15:09:00,95.0\n2014-04-21 15:14:00,93.584\n2014-04-21 15:19:00,94.084\n2014-04-21 15:24:00,92.458\n2014-04-21 15:29:00,91.76\n2014-04-21 15:34:00,92.5\n2014-04-21 15:39:00,91.176\n2014-04-21 15:44:00,93.334\n2014-04-21 15:49:00,91.166\n2014-04-21 15:54:00,92.75\n2014-04-21 15:59:00,89.584\n2014-04-21 16:04:00,91.0\n2014-04-21 16:09:00,95.64200000000001\n2014-04-21 16:14:00,90.416\n2014-04-21 16:19:00,92.084\n2014-04-21 16:24:00,93.084\n2014-04-21 16:29:00,90.334\n2014-04-21 16:34:00,88.056\n2014-04-21 16:39:00,93.834\n2014-04-21 16:44:00,92.376\n2014-04-21 16:49:00,92.916\n2014-04-21 16:54:00,91.10600000000001\n2014-04-21 16:59:00,92.458\n2014-04-21 17:04:00,92.958\n2014-04-21 17:09:00,93.834\n2014-04-21 17:14:00,93.084\n2014-04-21 17:19:00,91.916\n2014-04-21 17:24:00,92.208\n2014-04-21 17:29:00,93.666\n2014-04-21 17:34:00,93.416\n2014-04-21 17:39:00,93.75\n2014-04-21 17:44:00,93.32799999999999\n2014-04-21 17:49:00,92.126\n2014-04-21 17:54:00,93.584\n2014-04-21 17:59:00,91.05\n2014-04-21 18:04:00,92.166\n2014-04-21 18:09:00,94.666\n2014-04-21 18:14:00,92.416\n2014-04-21 18:19:00,92.25\n2014-04-21 18:24:00,88.666\n2014-04-21 18:29:00,89.124\n2014-04-21 18:34:00,90.584\n2014-04-21 18:39:00,93.624\n2014-04-21 18:44:00,91.25\n2014-04-21 18:49:00,93.624\n2014-04-21 18:54:00,95.57799999999999\n2014-04-21 18:59:00,92.958\n2014-04-21 19:04:00,92.792\n2014-04-21 19:09:00,94.542\n2014-04-21 19:14:00,91.584\n2014-04-21 19:19:00,92.792\n2014-04-21 19:24:00,94.124\n2014-04-21 19:29:00,87.958\n2014-04-21 19:34:00,92.0\n2014-04-21 19:39:00,94.5\n2014-04-21 19:44:00,93.334\n2014-04-21 19:49:00,92.208\n2014-04-21 19:54:00,92.22200000000001\n2014-04-21 19:59:00,93.208\n2014-04-21 20:04:00,94.958\n2014-04-21 20:09:00,93.78\n2014-04-21 20:14:00,92.916\n2014-04-21 20:19:00,93.1\n2014-04-21 20:24:00,94.584\n2014-04-21 20:29:00,91.916\n2014-04-21 20:34:00,93.0\n2014-04-21 20:39:00,92.708\n2014-04-21 20:44:00,91.4\n2014-04-21 20:49:00,91.70200000000001\n2014-04-21 20:54:00,93.0\n2014-04-21 20:59:00,92.338\n2014-04-21 21:04:00,91.876\n2014-04-21 21:09:00,95.084\n2014-04-21 21:14:00,93.916\n2014-04-21 21:19:00,88.958\n2014-04-21 21:24:00,90.3\n2014-04-21 21:29:00,93.416\n2014-04-21 21:34:00,91.126\n2014-04-21 21:39:00,92.874\n2014-04-21 21:44:00,92.28\n2014-04-21 21:49:00,92.542\n2014-04-21 21:54:00,93.416\n2014-04-21 21:59:00,90.86200000000001\n2014-04-21 22:04:00,82.75\n2014-04-21 22:09:00,91.124\n2014-04-21 22:14:00,90.25\n2014-04-21 22:19:00,91.042\n2014-04-21 22:24:00,90.046\n2014-04-21 22:29:00,86.51\n2014-04-21 22:34:00,86.484\n2014-04-21 22:39:00,89.208\n2014-04-21 22:44:00,89.084\n2014-04-21 22:49:00,87.93\n2014-04-21 22:54:00,86.666\n2014-04-21 22:59:00,91.084\n2014-04-21 23:04:00,90.448\n2014-04-21 23:09:00,94.334\n2014-04-21 23:14:00,89.708\n2014-04-21 23:19:00,87.958\n2014-04-21 23:24:00,92.458\n2014-04-21 23:29:00,91.292\n2014-04-21 23:34:00,90.334\n2014-04-21 23:39:00,88.166\n2014-04-21 23:44:00,89.41\n2014-04-21 23:49:00,90.554\n2014-04-21 23:54:00,89.83200000000002\n2014-04-21 23:59:00,88.458\n2014-04-22 00:04:00,87.374\n2014-04-22 00:09:00,93.834\n2014-04-22 00:14:00,91.124\n2014-04-22 00:19:00,90.15799999999999\n2014-04-22 00:24:00,89.17\n2014-04-22 00:29:00,88.05\n2014-04-22 00:34:00,87.81200000000004\n2014-04-22 00:39:00,89.46\n2014-04-22 00:44:00,87.602\n2014-04-22 00:49:00,87.46\n2014-04-22 00:54:00,88.916\n2014-04-22 00:59:00,87.084\n2014-04-22 01:04:00,88.152\n2014-04-22 01:09:00,93.696\n2014-04-22 01:14:00,85.08\n2014-04-22 01:19:00,85.958\n2014-04-22 01:24:00,88.624\n2014-04-22 01:29:00,88.084\n2014-04-22 01:34:00,87.208\n2014-04-22 01:39:00,88.376\n2014-04-22 01:44:00,90.292\n2014-04-22 01:49:00,89.792\n2014-04-22 01:54:00,91.896\n2014-04-22 01:59:00,90.5\n2014-04-22 02:04:00,87.292\n2014-04-22 02:09:00,92.05\n2014-04-22 02:14:00,90.662\n2014-04-22 02:19:00,89.764\n2014-04-22 02:24:00,89.0\n2014-04-22 02:29:00,84.666\n2014-04-22 02:34:00,88.5\n2014-04-22 02:39:00,86.75\n2014-04-22 02:44:00,86.458\n2014-04-22 02:49:00,88.208\n2014-04-22 02:54:00,86.25\n2014-04-22 02:59:00,87.346\n2014-04-22 03:04:00,87.584\n2014-04-22 03:09:00,89.208\n2014-04-22 03:14:00,84.376\n2014-04-22 03:19:00,79.166\n2014-04-22 03:24:00,88.416\n2014-04-22 03:29:00,91.954\n2014-04-22 03:34:00,94.75\n2014-04-22 03:39:00,95.458\n2014-04-22 03:44:00,93.958\n2014-04-22 03:49:00,92.708\n2014-04-22 03:54:00,94.37\n2014-04-22 03:59:00,94.428\n2014-04-22 04:04:00,96.166\n2014-04-22 04:09:00,93.042\n2014-04-22 04:14:00,89.042\n2014-04-22 04:19:00,89.626\n2014-04-22 04:24:00,89.542\n2014-04-22 04:29:00,89.5\n2014-04-22 04:34:00,83.166\n2014-04-22 04:39:00,94.542\n2014-04-22 04:44:00,95.208\n2014-04-22 04:49:00,93.75\n2014-04-22 04:54:00,92.542\n2014-04-22 04:59:00,94.75\n2014-04-22 05:04:00,95.0\n2014-04-22 05:09:00,95.75\n2014-04-22 05:14:00,92.238\n2014-04-22 05:19:00,95.0\n2014-04-22 05:24:00,96.586\n2014-04-22 05:29:00,93.376\n2014-04-22 05:34:00,94.416\n2014-04-22 05:39:00,96.042\n2014-04-22 05:44:00,90.916\n2014-04-22 05:49:00,88.834\n2014-04-22 05:54:00,88.084\n2014-04-22 05:59:00,86.28399999999998\n2014-04-22 06:04:00,89.916\n2014-04-22 06:09:00,92.208\n2014-04-22 06:14:00,92.0\n2014-04-22 06:19:00,92.042\n2014-04-22 06:24:00,88.682\n2014-04-22 06:29:00,95.126\n2014-04-22 06:34:00,92.458\n2014-04-22 06:39:00,94.084\n2014-04-22 06:44:00,94.75\n2014-04-22 06:49:00,93.374\n2014-04-22 06:54:00,95.958\n2014-04-22 06:59:00,95.37799999999999\n2014-04-22 07:04:00,94.624\n2014-04-22 07:09:00,93.916\n2014-04-22 07:14:00,95.72\n2014-04-22 07:19:00,94.014\n2014-04-22 07:24:00,95.458\n2014-04-22 07:29:00,93.91\n2014-04-22 07:34:00,95.53399999999999\n2014-04-22 07:39:00,94.208\n2014-04-22 07:44:00,92.64\n2014-04-22 07:49:00,95.458\n2014-04-22 07:54:00,91.458\n2014-04-22 07:59:00,95.876\n2014-04-22 08:04:00,94.542\n2014-04-22 08:09:00,92.084\n2014-04-22 08:14:00,93.69\n2014-04-22 08:19:00,93.834\n2014-04-22 08:24:00,94.5\n2014-04-22 08:29:00,92.292\n2014-04-22 08:34:00,95.916\n2014-04-22 08:39:00,96.042\n2014-04-22 08:44:00,95.584\n2014-04-22 08:49:00,96.5\n2014-04-22 08:54:00,94.708\n2014-04-22 08:59:00,94.166\n2014-04-22 09:04:00,88.376\n2014-04-22 09:09:00,92.624\n2014-04-22 09:14:00,93.0\n2014-04-22 09:19:00,94.334\n2014-04-22 09:24:00,91.584\n2014-04-22 09:29:00,92.584\n2014-04-22 09:34:00,93.242\n2014-04-22 09:39:00,93.834\n2014-04-22 09:44:00,93.666\n2014-04-22 09:49:00,93.126\n2014-04-22 09:54:00,94.708\n2014-04-22 09:59:00,92.37\n2014-04-22 10:04:00,91.542\n2014-04-22 10:09:00,96.792\n2014-04-22 10:14:00,91.794\n2014-04-22 10:19:00,93.584\n2014-04-22 10:24:00,94.61\n2014-04-22 10:29:00,94.27799999999999\n2014-04-22 10:34:00,91.25\n2014-04-22 10:39:00,93.75\n2014-04-22 10:44:00,92.916\n2014-04-22 10:49:00,94.542\n2014-04-22 10:54:00,90.626\n2014-04-22 10:59:00,91.292\n2014-04-22 11:04:00,94.958\n2014-04-22 11:09:00,97.874\n2014-04-22 11:14:00,95.914\n2014-04-22 11:19:00,94.47200000000001\n2014-04-22 11:24:00,96.124\n2014-04-22 11:29:00,96.416\n2014-04-22 11:34:00,95.88799999999999\n2014-04-22 11:39:00,96.666\n2014-04-22 11:44:00,96.292\n2014-04-22 11:49:00,91.414\n2014-04-22 11:54:00,91.486\n2014-04-22 11:59:00,96.664\n2014-04-22 12:04:00,95.0\n2014-04-22 12:09:00,97.0\n2014-04-22 12:14:00,96.624\n2014-04-22 12:19:00,96.166\n2014-04-22 12:24:00,95.286\n2014-04-22 12:29:00,96.376\n2014-04-22 12:34:00,93.666\n2014-04-22 12:39:00,92.806\n2014-04-22 12:44:00,95.36\n2014-04-22 12:49:00,95.186\n2014-04-22 12:54:00,95.25\n2014-04-22 12:59:00,89.75\n2014-04-22 13:04:00,95.96600000000001\n2014-04-22 13:09:00,96.99\n2014-04-22 13:14:00,97.084\n2014-04-22 13:19:00,95.58200000000001\n2014-04-22 13:24:00,95.792\n2014-04-22 13:29:00,95.166\n2014-04-22 13:34:00,94.334\n2014-04-22 13:39:00,91.84200000000001\n2014-04-22 13:44:00,96.166\n2014-04-22 13:49:00,95.64\n2014-04-22 13:54:00,95.956\n2014-04-22 13:59:00,95.542\n2014-04-22 14:04:00,92.458\n2014-04-22 14:09:00,97.708\n2014-04-22 14:14:00,94.416\n2014-04-22 14:19:00,93.334\n2014-04-22 14:24:00,91.792\n2014-04-22 14:29:00,89.916\n2014-04-22 14:34:00,88.916\n2014-04-22 14:39:00,93.458\n2014-04-22 14:44:00,92.11\n2014-04-22 14:49:00,90.27799999999999\n2014-04-22 14:54:00,92.5\n2014-04-22 14:59:00,91.166\n2014-04-22 15:04:00,92.052\n2014-04-22 15:09:00,93.42\n2014-04-22 15:14:00,89.084\n2014-04-22 15:19:00,93.0\n2014-04-22 15:24:00,91.666\n2014-04-22 15:29:00,89.5\n2014-04-22 15:34:00,89.546\n2014-04-22 15:39:00,91.666\n2014-04-22 15:44:00,93.27799999999999\n2014-04-22 15:49:00,95.97200000000001\n2014-04-22 15:54:00,93.946\n2014-04-22 15:59:00,95.376\n2014-04-22 16:04:00,92.62\n2014-04-22 16:09:00,94.464\n2014-04-22 16:14:00,95.566\n2014-04-22 16:19:00,94.714\n2014-04-22 16:24:00,95.626\n2014-04-22 16:29:00,93.508\n2014-04-22 16:34:00,92.56200000000001\n2014-04-22 16:39:00,92.876\n2014-04-22 16:44:00,94.15799999999999\n2014-04-22 16:49:00,93.02\n2014-04-22 16:54:00,92.292\n2014-04-22 16:59:00,87.874\n2014-04-22 17:04:00,90.166\n2014-04-22 17:09:00,91.834\n2014-04-22 17:14:00,89.126\n2014-04-22 17:19:00,84.124\n2014-04-22 17:24:00,85.958\n2014-04-22 17:29:00,84.624\n2014-04-22 17:34:00,89.792\n2014-04-22 17:39:00,91.936\n2014-04-22 17:44:00,88.834\n2014-04-22 17:49:00,91.292\n2014-04-22 17:54:00,91.876\n2014-04-22 17:59:00,91.666\n2014-04-22 18:04:00,92.666\n2014-04-22 18:09:00,96.292\n2014-04-22 18:14:00,88.458\n2014-04-22 18:19:00,90.292\n2014-04-22 18:24:00,92.042\n2014-04-22 18:29:00,93.5\n2014-04-22 18:34:00,92.042\n2014-04-22 18:39:00,91.54\n2014-04-22 18:44:00,91.822\n2014-04-22 18:49:00,92.48\n2014-04-22 18:54:00,92.57600000000001\n2014-04-22 18:59:00,90.334\n2014-04-22 19:04:00,89.874\n2014-04-22 19:09:00,92.948\n2014-04-22 19:14:00,92.274\n2014-04-22 19:19:00,91.44200000000001\n2014-04-22 19:24:00,92.25\n2014-04-22 19:29:00,91.792\n2014-04-22 19:34:00,90.616\n2014-04-22 19:39:00,92.946\n2014-04-22 19:44:00,89.166\n2014-04-22 19:49:00,90.374\n2014-04-22 19:54:00,93.126\n2014-04-22 19:59:00,89.266\n2014-04-22 20:04:00,90.542\n2014-04-22 20:09:00,93.5\n2014-04-22 20:14:00,92.166\n2014-04-22 20:19:00,92.53\n2014-04-22 20:24:00,91.198\n2014-04-22 20:29:00,91.17\n2014-04-22 20:34:00,91.834\n2014-04-22 20:39:00,87.334\n2014-04-22 20:44:00,91.584\n2014-04-22 20:49:00,91.57\n2014-04-22 20:54:00,89.458\n2014-04-22 20:59:00,93.876\n2014-04-22 21:04:00,90.0\n2014-04-22 21:09:00,94.958\n2014-04-22 21:14:00,90.08200000000001\n2014-04-22 21:19:00,91.77799999999999\n2014-04-22 21:24:00,91.84200000000001\n2014-04-22 21:29:00,83.13\n2014-04-22 21:34:00,88.5\n2014-04-22 21:39:00,91.542\n2014-04-22 21:44:00,91.292\n2014-04-22 21:49:00,92.374\n2014-04-22 21:54:00,91.208\n2014-04-22 21:59:00,87.916\n2014-04-22 22:04:00,91.708\n2014-04-22 22:09:00,94.874\n2014-04-22 22:14:00,89.834\n2014-04-22 22:19:00,91.25\n2014-04-22 22:24:00,92.25\n2014-04-22 22:29:00,91.708\n2014-04-22 22:34:00,90.416\n2014-04-22 22:39:00,93.126\n2014-04-22 22:44:00,90.166\n2014-04-22 22:49:00,90.084\n2014-04-22 22:54:00,92.876\n2014-04-22 22:59:00,91.042\n2014-04-22 23:04:00,92.316\n2014-04-22 23:09:00,95.954\n2014-04-22 23:14:00,93.126\n2014-04-22 23:19:00,92.05\n2014-04-22 23:24:00,90.876\n2014-04-22 23:29:00,91.416\n2014-04-22 23:34:00,90.79\n2014-04-22 23:39:00,93.416\n2014-04-22 23:44:00,91.00200000000001\n2014-04-22 23:49:00,94.958\n2014-04-22 23:54:00,93.208\n2014-04-22 23:59:00,91.458\n2014-04-23 00:04:00,93.37799999999999\n2014-04-23 00:09:00,94.042\n2014-04-23 00:14:00,91.416\n2014-04-23 00:19:00,89.88799999999998\n2014-04-23 00:24:00,91.084\n2014-04-23 00:29:00,90.084\n2014-04-23 00:34:00,88.876\n2014-04-23 00:39:00,88.876\n2014-04-23 00:44:00,92.374\n2014-04-23 00:49:00,88.584\n2014-04-23 00:54:00,89.666\n2014-04-23 00:59:00,94.5\n2014-04-23 01:04:00,92.042\n2014-04-23 01:09:00,95.084\n2014-04-23 01:14:00,93.458\n2014-04-23 01:19:00,95.084\n2014-04-23 01:24:00,93.166\n2014-04-23 01:29:00,94.084\n2014-04-23 01:34:00,92.792\n2014-04-23 01:39:00,91.5\n2014-04-23 01:44:00,95.042\n2014-04-23 01:49:00,95.916\n2014-04-23 01:54:00,93.042\n2014-04-23 01:59:00,92.75\n2014-04-23 02:04:00,92.62799999999999\n2014-04-23 02:09:00,95.25\n2014-04-23 02:14:00,95.12200000000001\n2014-04-23 02:19:00,93.116\n2014-04-23 02:24:00,89.072\n2014-04-23 02:29:00,90.0\n2014-04-23 02:34:00,93.25\n2014-04-23 02:39:00,90.666\n2014-04-23 02:44:00,91.334\n2014-04-23 02:49:00,88.958\n2014-04-23 02:54:00,89.75\n2014-04-23 02:59:00,90.334\n2014-04-23 03:04:00,91.624\n2014-04-23 03:09:00,94.626\n2014-04-23 03:14:00,89.458\n2014-04-23 03:19:00,89.92\n2014-04-23 03:24:00,90.546\n2014-04-23 03:29:00,92.084\n2014-04-23 03:34:00,90.416\n2014-04-23 03:39:00,92.834\n2014-04-23 03:44:00,88.25\n2014-04-23 03:49:00,89.376\n2014-04-23 03:54:00,92.042\n2014-04-23 03:59:00,91.042\n2014-04-23 04:04:00,93.344\n2014-04-23 04:09:00,93.0\n2014-04-23 04:14:00,90.666\n2014-04-23 04:19:00,92.584\n2014-04-23 04:24:00,90.5\n2014-04-23 04:29:00,88.5\n2014-04-23 04:34:00,92.794\n2014-04-23 04:39:00,87.65799999999999\n2014-04-23 04:44:00,85.99600000000002\n2014-04-23 04:49:00,90.678\n2014-04-23 04:54:00,90.166\n2014-04-23 04:59:00,91.5\n2014-04-23 05:04:00,89.00200000000002\n2014-04-23 05:09:00,93.584\n2014-04-23 05:14:00,89.0\n2014-04-23 05:19:00,89.416\n2014-04-23 05:24:00,88.334\n2014-04-23 05:29:00,90.09200000000001\n2014-04-23 05:34:00,92.0\n2014-04-23 05:39:00,89.436\n2014-04-23 05:44:00,87.084\n2014-04-23 05:49:00,91.61\n2014-04-23 05:54:00,90.068\n2014-04-23 05:59:00,87.80799999999998\n2014-04-23 06:04:00,90.75\n2014-04-23 06:09:00,90.416\n2014-04-23 06:14:00,89.042\n2014-04-23 06:19:00,87.0\n2014-04-23 06:24:00,89.584\n2014-04-23 06:29:00,90.584\n2014-04-23 06:34:00,90.458\n2014-04-23 06:39:00,90.66799999999999\n2014-04-23 06:44:00,88.042\n2014-04-23 06:49:00,90.0\n2014-04-23 06:54:00,88.084\n2014-04-23 06:59:00,89.708\n2014-04-23 07:04:00,89.792\n2014-04-23 07:09:00,92.376\n2014-04-23 07:14:00,89.584\n2014-04-23 07:19:00,89.834\n2014-04-23 07:24:00,86.71799999999998\n2014-04-23 07:29:00,86.166\n2014-04-23 07:34:00,85.446\n2014-04-23 07:39:00,88.25\n2014-04-23 07:44:00,87.344\n2014-04-23 07:49:00,91.124\n2014-04-23 07:54:00,90.334\n2014-04-23 07:59:00,81.0\n2014-04-23 08:04:00,82.0\n2014-04-23 08:09:00,92.708\n2014-04-23 08:14:00,93.042\n2014-04-23 08:19:00,94.626\n2014-04-23 08:24:00,93.084\n2014-04-23 08:29:00,94.334\n2014-04-23 08:34:00,92.584\n2014-04-23 08:39:00,92.584\n2014-04-23 08:44:00,93.916\n2014-04-23 08:49:00,92.7\n2014-04-23 08:54:00,94.0\n2014-04-23 08:59:00,93.184\n2014-04-23 09:04:00,93.514\n2014-04-23 09:09:00,96.666\n2014-04-23 09:14:00,92.5\n2014-04-23 09:19:00,93.09200000000001\n2014-04-23 09:24:00,94.55799999999999\n2014-04-23 09:29:00,92.416\n2014-04-23 09:34:00,93.874\n2014-04-23 09:39:00,92.542\n2014-04-23 09:44:00,94.208\n2014-04-23 09:49:00,94.334\n2014-04-23 09:54:00,92.084\n2014-04-23 09:59:00,92.666\n2014-04-23 10:04:00,93.876\n2014-04-23 10:09:00,95.126\n2014-04-23 10:14:00,94.666\n2014-04-23 10:19:00,93.208\n2014-04-23 10:24:00,91.802\n2014-04-23 10:29:00,91.742\n2014-04-23 10:34:00,93.9\n2014-04-23 10:39:00,92.604\n2014-04-23 10:44:00,93.126\n2014-04-23 10:49:00,95.208\n2014-04-23 10:54:00,93.084\n2014-04-23 10:59:00,92.666\n2014-04-23 11:04:00,93.236\n2014-04-23 11:09:00,94.088\n2014-04-23 11:14:00,93.666\n2014-04-23 11:19:00,95.29\n2014-04-23 11:24:00,93.102\n2014-04-23 11:29:00,93.666\n2014-04-23 11:34:00,95.208\n2014-04-23 11:39:00,94.416\n2014-04-23 11:44:00,95.166\n2014-04-23 11:49:00,92.834\n2014-04-23 11:54:00,94.792\n2014-04-23 11:59:00,92.854\n2014-04-23 12:04:00,95.03200000000001\n2014-04-23 12:09:00,96.75\n2014-04-23 12:14:00,95.68\n2014-04-23 12:19:00,95.584\n2014-04-23 12:24:00,95.0\n2014-04-23 12:29:00,94.584\n2014-04-23 12:34:00,93.042\n2014-04-23 12:39:00,92.584\n2014-04-23 12:44:00,95.208\n2014-04-23 12:49:00,93.78\n2014-04-23 12:54:00,96.512\n2014-04-23 12:59:00,95.1\n2014-04-23 13:04:00,94.626\n2014-04-23 13:09:00,95.72200000000001\n2014-04-23 13:14:00,95.334\n2014-04-23 13:19:00,97.042\n2014-04-23 13:24:00,95.876\n2014-04-23 13:29:00,94.376\n2014-04-23 13:34:00,92.126\n2014-04-23 13:39:00,94.124\n2014-04-23 13:44:00,94.618\n2014-04-23 13:49:00,93.604\n2014-04-23 13:54:00,94.61\n2014-04-23 13:59:00,93.09\n2014-04-23 14:04:00,92.292\n2014-04-23 14:09:00,95.916\n2014-04-23 14:14:00,93.0\n2014-04-23 14:19:00,93.75\n2014-04-23 14:24:00,95.124\n2014-04-23 14:29:00,91.264\n2014-04-23 14:34:00,93.75\n2014-04-23 14:39:00,94.334\n2014-04-23 14:44:00,93.75\n2014-04-23 14:49:00,93.792\n2014-04-23 14:54:00,94.626\n2014-04-23 14:59:00,94.292\n2014-04-23 15:04:00,94.75\n2014-04-23 15:09:00,94.75\n2014-04-23 15:14:00,94.876\n2014-04-23 15:19:00,93.23200000000001\n2014-04-23 15:24:00,94.58\n2014-04-23 15:29:00,94.834\n2014-04-23 15:34:00,94.31200000000001\n2014-04-23 15:39:00,95.708\n2014-04-23 15:44:00,95.08\n2014-04-23 15:49:00,95.666\n2014-04-23 15:54:00,95.084\n2014-04-23 15:59:00,93.542\n2014-04-23 16:04:00,97.038\n2014-04-23 16:09:00,96.462\n2014-04-23 16:14:00,93.68799999999999\n2014-04-23 16:19:00,94.816\n2014-04-23 16:24:00,95.834\n2014-04-23 16:29:00,92.916\n2014-04-23 16:34:00,94.584\n2014-04-23 16:39:00,93.208\n2014-04-23 16:44:00,94.042\n2014-04-23 16:49:00,93.75\n2014-04-23 16:54:00,96.584\n2014-04-23 16:59:00,94.626\n2014-04-23 17:04:00,95.916\n2014-04-23 17:09:00,95.084\n2014-04-23 17:14:00,94.916\n2014-04-23 17:19:00,94.124\n2014-04-23 17:24:00,93.792\n2014-04-23 17:29:00,95.006\n2014-04-23 17:34:00,94.458\n2014-04-23 17:39:00,93.126\n2014-04-23 17:44:00,95.25\n2014-04-23 17:49:00,94.25\n2014-04-23 17:54:00,94.624\n2014-04-23 17:59:00,93.904\n2014-04-23 18:04:00,94.18799999999999\n2014-04-23 18:09:00,95.208\n2014-04-23 18:14:00,93.666\n2014-04-23 18:19:00,96.292\n2014-04-23 18:24:00,96.012\n2014-04-23 18:29:00,94.006\n2014-04-23 18:34:00,94.63\n2014-04-23 18:39:00,94.0\n2014-04-23 18:44:00,94.792\n2014-04-23 18:49:00,94.416\n2014-04-23 18:54:00,93.166\n2014-04-23 18:59:00,95.792\n2014-04-23 19:04:00,94.536\n2014-04-23 19:09:00,94.416\n2014-04-23 19:14:00,94.208\n2014-04-23 19:19:00,95.292\n2014-04-23 19:24:00,93.542\n2014-04-23 19:29:00,92.84200000000001\n2014-04-23 19:34:00,93.584\n2014-04-23 19:39:00,93.084\n2014-04-23 19:44:00,93.792\n2014-04-23 19:49:00,93.624\n2014-04-23 19:54:00,92.17399999999999\n2014-04-23 19:59:00,95.626\n2014-04-23 20:04:00,92.834\n2014-04-23 20:09:00,97.416\n2014-04-23 20:14:00,94.32799999999999\n2014-04-23 20:19:00,93.958\n2014-04-23 20:24:00,94.814\n2014-04-23 20:29:00,94.95\n2014-04-23 20:34:00,92.404\n2014-04-23 20:39:00,94.552\n2014-04-23 20:44:00,94.19\n2014-04-23 20:49:00,94.458\n2014-04-23 20:54:00,93.126\n2014-04-23 20:59:00,95.126\n2014-04-23 21:04:00,93.208\n2014-04-23 21:09:00,97.0\n2014-04-23 21:14:00,95.166\n2014-04-23 21:19:00,94.334\n2014-04-23 21:24:00,95.5\n2014-04-23 21:29:00,95.708\n2014-04-23 21:34:00,94.376\n2014-04-23 21:39:00,93.374\n2014-04-23 21:44:00,94.376\n2014-04-23 21:49:00,95.024\n2014-04-23 21:54:00,96.33\n2014-04-23 21:59:00,94.0\n2014-04-23 22:04:00,93.61\n2014-04-23 22:09:00,97.084\n2014-04-23 22:14:00,95.24600000000001\n2014-04-23 22:19:00,95.584\n2014-04-23 22:24:00,94.75\n2014-04-23 22:29:00,96.338\n2014-04-23 22:34:00,95.626\n2014-04-23 22:39:00,93.75\n2014-04-23 22:44:00,95.876\n2014-04-23 22:49:00,94.49\n2014-04-23 22:54:00,95.182\n2014-04-23 22:59:00,92.27600000000001\n2014-04-23 23:04:00,93.07600000000001\n2014-04-23 23:09:00,99.04\n2014-04-23 23:14:00,93.666\n2014-04-23 23:19:00,94.49799999999999\n2014-04-23 23:24:00,93.682\n2014-04-23 23:29:00,94.666\n2014-04-23 23:34:00,96.334\n2014-04-23 23:39:00,94.59200000000001\n2014-04-23 23:44:00,92.666\n2014-04-23 23:49:00,95.084\n2014-04-23 23:54:00,95.236\n2014-04-23 23:59:00,96.374\n2014-04-24 00:04:00,95.042\n2014-04-24 00:09:00,96.584\n"
  },
  {
    "path": "workspace/anomaly_detector/datasets/selected/level_change/ec2_cpu_utilization_ac20cd.csv",
    "content": "timestamp,value\n2014-04-02 14:29:00,42.652\n2014-04-02 14:34:00,41.361999999999995\n2014-04-02 14:39:00,43.408\n2014-04-02 14:44:00,40.262\n2014-04-02 14:49:00,40.328\n2014-04-02 14:54:00,42.652\n2014-04-02 14:59:00,39.836\n2014-04-02 15:04:00,42.57\n2014-04-02 15:09:00,45.211999999999996\n2014-04-02 15:14:00,41.15\n2014-04-02 15:19:00,42.91\n2014-04-02 15:24:00,43.756\n2014-04-02 15:29:00,38.522\n2014-04-02 15:34:00,42.488\n2014-04-02 15:39:00,41.268\n2014-04-02 15:44:00,42.136\n2014-04-02 15:49:00,42.066\n2014-04-02 15:54:00,43.544\n2014-04-02 15:59:00,38.404\n2014-04-02 16:04:00,42.018\n2014-04-02 16:09:00,44.872\n2014-04-02 16:14:00,40.658\n2014-04-02 16:19:00,42.276\n2014-04-02 16:24:00,43.052\n2014-04-02 16:29:00,43.56800000000001\n2014-04-02 16:34:00,38.356\n2014-04-02 16:39:00,39.788000000000004\n2014-04-02 16:44:00,41.83\n2014-04-02 16:49:00,39.038000000000004\n2014-04-02 16:54:00,42.184\n2014-04-02 16:59:00,41.76\n2014-04-02 17:04:00,43.99\n2014-04-02 17:09:00,41.476000000000006\n2014-04-02 17:14:00,39.236\n2014-04-02 17:19:00,41.798\n2014-04-02 17:24:00,39.722\n2014-04-02 17:29:00,40.61\n2014-04-02 17:34:00,44.413999999999994\n2014-04-02 17:39:00,38.404\n2014-04-02 17:44:00,41.982\n2014-04-02 17:49:00,42.066\n2014-04-02 17:54:00,42.33600000000001\n2014-04-02 17:59:00,41.01\n2014-04-02 18:04:00,43.122\n2014-04-02 18:09:00,39.954\n2014-04-02 18:14:00,40.516\n2014-04-02 18:19:00,45.396\n2014-04-02 18:24:00,38.188\n2014-04-02 18:29:00,42.536\n2014-04-02 18:34:00,38.882\n2014-04-02 18:39:00,40.766\n2014-04-02 18:44:00,40.4\n2014-04-02 18:49:00,41.808\n2014-04-02 18:54:00,42.324\n2014-04-02 18:59:00,44.152\n2014-04-02 19:04:00,40.234\n2014-04-02 19:09:00,40.891999999999996\n2014-04-02 19:14:00,41.494\n2014-04-02 19:19:00,40.61\n2014-04-02 19:24:00,42.483999999999995\n2014-04-02 19:29:00,38.774\n2014-04-02 19:34:00,45.14\n2014-04-02 19:39:00,40.122\n2014-04-02 19:44:00,41.01\n2014-04-02 19:49:00,43.708\n2014-04-02 19:54:00,40.61\n2014-04-02 19:59:00,43.49800000000001\n2014-04-02 20:04:00,42.606\n2014-04-02 20:09:00,46.361999999999995\n2014-04-02 20:14:00,40.306\n2014-04-02 20:19:00,46.478\n2014-04-02 20:24:00,38.808\n2014-04-02 20:29:00,41.878\n2014-04-02 20:34:00,44.254\n2014-04-02 20:39:00,41.57\n2014-04-02 20:44:00,39.205999999999996\n2014-04-02 20:49:00,40.482\n2014-04-02 20:54:00,43.593999999999994\n2014-04-02 20:59:00,41.808\n2014-04-02 21:04:00,40.751999999999995\n2014-04-02 21:09:00,46.31399999999999\n2014-04-02 21:14:00,38.99\n2014-04-02 21:19:00,41.666000000000004\n2014-04-02 21:24:00,39.39\n2014-04-02 21:29:00,40.812\n2014-04-02 21:34:00,42.20399999999999\n2014-04-02 21:39:00,44.95399999999999\n2014-04-02 21:44:00,41.55\n2014-04-02 21:49:00,42.09\n2014-04-02 21:54:00,42.178000000000004\n2014-04-02 21:59:00,43.24\n2014-04-02 22:04:00,38.27\n2014-04-02 22:09:00,42.206\n2014-04-02 22:14:00,44.15600000000001\n2014-04-02 22:19:00,41.332\n2014-04-02 22:24:00,42.276\n2014-04-02 22:29:00,41.15\n2014-04-02 22:34:00,41.648\n2014-04-02 22:39:00,41.298\n2014-04-02 22:44:00,38.616\n2014-04-02 22:49:00,41.15\n2014-04-02 22:54:00,44.718\n2014-04-02 22:59:00,41.924\n2014-04-02 23:04:00,42.042\n2014-04-02 23:09:00,42.536\n2014-04-02 23:14:00,45.163999999999994\n2014-04-02 23:19:00,39.141999999999996\n2014-04-02 23:24:00,41.0\n2014-04-02 23:29:00,40.576\n2014-04-02 23:34:00,44.233999999999995\n2014-04-02 23:39:00,42.816\n2014-04-02 23:44:00,41.31399999999999\n2014-04-02 23:49:00,40.156\n2014-04-02 23:54:00,45.684\n2014-04-02 23:59:00,39.508\n2014-04-03 00:04:00,42.36\n2014-04-03 00:09:00,46.882\n2014-04-03 00:14:00,40.188\n2014-04-03 00:19:00,40.576\n2014-04-03 00:24:00,41.924\n2014-04-03 00:29:00,40.68\n2014-04-03 00:34:00,39.152\n2014-04-03 00:39:00,45.0\n2014-04-03 00:44:00,38.898\n2014-04-03 00:49:00,41.69\n2014-04-03 00:54:00,43.56800000000001\n2014-04-03 00:59:00,42.23\n2014-04-03 01:04:00,42.3\n2014-04-03 01:09:00,44.328\n2014-04-03 01:14:00,40.172\n2014-04-03 01:19:00,41.292\n2014-04-03 01:24:00,44.812\n2014-04-03 01:29:00,43.17\n2014-04-03 01:34:00,42.7\n2014-04-03 01:39:00,45.716\n2014-04-03 01:44:00,39.202\n2014-04-03 01:49:00,41.571999999999996\n2014-04-03 01:54:00,44.163999999999994\n2014-04-03 01:59:00,40.798\n2014-04-03 02:04:00,42.066\n2014-04-03 02:09:00,43.708\n2014-04-03 02:14:00,41.22\n2014-04-03 02:19:00,41.394\n2014-04-03 02:24:00,41.996\n2014-04-03 02:29:00,40.102\n2014-04-03 02:34:00,42.37\n2014-04-03 02:39:00,38.858000000000004\n2014-04-03 02:44:00,42.16\n2014-04-03 02:49:00,41.422\n2014-04-03 02:54:00,43.146\n2014-04-03 02:59:00,40.54\n2014-04-03 03:04:00,43.988\n2014-04-03 03:09:00,41.12600000000001\n2014-04-03 03:14:00,40.868\n2014-04-03 03:19:00,46.478\n2014-04-03 03:24:00,41.76\n2014-04-03 03:29:00,43.538000000000004\n2014-04-03 03:34:00,44.013999999999996\n2014-04-03 03:39:00,44.40600000000001\n2014-04-03 03:44:00,38.25\n2014-04-03 03:49:00,41.022\n2014-04-03 03:54:00,43.926\n2014-04-03 03:59:00,39.578\n2014-04-03 04:04:00,43.63800000000001\n2014-04-03 04:09:00,44.578\n2014-04-03 04:14:00,38.92\n2014-04-03 04:19:00,40.538000000000004\n2014-04-03 04:24:00,43.49800000000001\n2014-04-03 04:29:00,39.468\n2014-04-03 04:34:00,39.366\n2014-04-03 04:39:00,42.49800000000001\n2014-04-03 04:44:00,38.826\n2014-04-03 04:49:00,41.181999999999995\n2014-04-03 04:54:00,42.86600000000001\n2014-04-03 04:59:00,40.931999999999995\n2014-04-03 05:04:00,42.538000000000004\n2014-04-03 05:09:00,47.37\n2014-04-03 05:14:00,38.81\n2014-04-03 05:19:00,45.114\n2014-04-03 05:24:00,45.438\n2014-04-03 05:29:00,42.864\n2014-04-03 05:34:00,44.738\n2014-04-03 05:39:00,46.43\n2014-04-03 05:44:00,41.028\n2014-04-03 05:49:00,40.361999999999995\n2014-04-03 05:54:00,46.26600000000001\n2014-04-03 05:59:00,39.342\n2014-04-03 06:04:00,44.24800000000001\n2014-04-03 06:09:00,42.63\n2014-04-03 06:14:00,42.77\n2014-04-03 06:19:00,43.943999999999996\n2014-04-03 06:24:00,40.774\n2014-04-03 06:29:00,43.728\n2014-04-03 06:34:00,48.756\n2014-04-03 06:39:00,41.29\n2014-04-03 06:44:00,41.571999999999996\n2014-04-03 06:49:00,42.262\n2014-04-03 06:54:00,45.6\n2014-04-03 06:59:00,41.15\n2014-04-03 07:04:00,44.302\n2014-04-03 07:09:00,41.972\n2014-04-03 07:14:00,42.324\n2014-04-03 07:19:00,43.028\n2014-04-03 07:24:00,44.648\n2014-04-03 07:29:00,43.403999999999996\n2014-04-03 07:34:00,38.052\n2014-04-03 07:39:00,41.338\n2014-04-03 07:44:00,40.602\n2014-04-03 07:49:00,40.61\n2014-04-03 07:54:00,42.18\n2014-04-03 07:59:00,40.446\n2014-04-03 08:04:00,45.188\n2014-04-03 08:09:00,44.132\n2014-04-03 08:14:00,41.644\n2014-04-03 08:19:00,39.24800000000001\n2014-04-03 08:24:00,42.042\n2014-04-03 08:29:00,40.364000000000004\n2014-04-03 08:34:00,42.181999999999995\n2014-04-03 08:39:00,38.79\n2014-04-03 08:44:00,42.04\n2014-04-03 08:49:00,43.38\n2014-04-03 08:54:00,41.08\n2014-04-03 08:59:00,40.68\n2014-04-03 09:04:00,41.878\n2014-04-03 09:09:00,46.488\n2014-04-03 09:14:00,38.028\n2014-04-03 09:19:00,40.916\n2014-04-03 09:24:00,40.821999999999996\n2014-04-03 09:29:00,41.864\n2014-04-03 09:34:00,41.456\n2014-04-03 09:39:00,44.803999999999995\n2014-04-03 09:44:00,38.99\n2014-04-03 09:49:00,40.57\n2014-04-03 09:54:00,45.163999999999994\n2014-04-03 09:59:00,38.316\n2014-04-03 10:04:00,42.111999999999995\n2014-04-03 10:09:00,42.488\n2014-04-03 10:14:00,38.592\n2014-04-03 10:19:00,40.492\n2014-04-03 10:24:00,41.74800000000001\n2014-04-03 10:29:00,43.286\n2014-04-03 10:34:00,41.69\n2014-04-03 10:39:00,45.702\n2014-04-03 10:44:00,38.85\n2014-04-03 10:49:00,38.592\n2014-04-03 10:54:00,42.066\n2014-04-03 10:59:00,43.093999999999994\n2014-04-03 11:04:00,40.442\n2014-04-03 11:09:00,45.282\n2014-04-03 11:14:00,38.826\n2014-04-03 11:19:00,41.948\n2014-04-03 11:24:00,37.746\n2014-04-03 11:29:00,40.282\n2014-04-03 11:34:00,43.98\n2014-04-03 11:39:00,43.176\n2014-04-03 11:44:00,38.99800000000001\n2014-04-03 11:49:00,43.146\n2014-04-03 11:54:00,42.816\n2014-04-03 11:59:00,40.47\n2014-04-03 12:04:00,43.192\n2014-04-03 12:09:00,41.666000000000004\n2014-04-03 12:14:00,38.756\n2014-04-03 12:19:00,40.22\n2014-04-03 12:24:00,40.564\n2014-04-03 12:29:00,41.62\n2014-04-03 12:34:00,39.108000000000004\n2014-04-03 12:39:00,42.018\n2014-04-03 12:44:00,38.49800000000001\n2014-04-03 12:49:00,43.04600000000001\n2014-04-03 12:54:00,39.954\n2014-04-03 12:59:00,43.226000000000006\n2014-04-03 13:04:00,42.348\n2014-04-03 13:09:00,41.456\n2014-04-03 13:14:00,39.508\n2014-04-03 13:19:00,41.032\n2014-04-03 13:24:00,40.634\n2014-04-03 13:29:00,41.994\n2014-04-03 13:34:00,45.798\n2014-04-03 13:39:00,39.624\n2014-04-03 13:44:00,42.37600000000001\n2014-04-03 13:49:00,40.634\n2014-04-03 13:54:00,41.31399999999999\n2014-04-03 13:59:00,40.634\n2014-04-03 14:04:00,42.84\n2014-04-03 14:09:00,40.306\n2014-04-03 14:14:00,40.564\n2014-04-03 14:19:00,40.704\n2014-04-03 14:24:00,42.16\n2014-04-03 14:29:00,39.264\n2014-04-03 14:34:00,44.178000000000004\n2014-04-03 14:39:00,38.494\n2014-04-03 14:44:00,41.961999999999996\n2014-04-03 14:49:00,40.586\n2014-04-03 14:54:00,43.732\n2014-04-03 14:59:00,39.32\n2014-04-03 15:04:00,42.556000000000004\n2014-04-03 15:09:00,40.821999999999996\n2014-04-03 15:14:00,43.403999999999996\n2014-04-03 15:19:00,43.333999999999996\n2014-04-03 15:24:00,42.02\n2014-04-03 15:29:00,39.414\n2014-04-03 15:34:00,42.736000000000004\n2014-04-03 15:39:00,42.19600000000001\n2014-04-03 15:44:00,38.99\n2014-04-03 15:49:00,40.821999999999996\n2014-04-03 15:54:00,42.324\n2014-04-03 15:59:00,40.592\n2014-04-03 16:04:00,42.846000000000004\n2014-04-03 16:09:00,46.784\n2014-04-03 16:14:00,36.784\n2014-04-03 16:19:00,40.936\n2014-04-03 16:24:00,41.832\n2014-04-03 16:29:00,43.672\n2014-04-03 16:34:00,39.08\n2014-04-03 16:39:00,41.582\n2014-04-03 16:44:00,39.442\n2014-04-03 16:49:00,42.018\n2014-04-03 16:54:00,40.736\n2014-04-03 16:59:00,42.394\n2014-04-03 17:04:00,40.04\n2014-04-03 17:09:00,44.373999999999995\n2014-04-03 17:14:00,41.803999999999995\n2014-04-03 17:19:00,39.236\n2014-04-03 17:24:00,40.446\n2014-04-03 17:29:00,42.442\n2014-04-03 17:34:00,40.452\n2014-04-03 17:39:00,45.418\n2014-04-03 17:44:00,38.076\n2014-04-03 17:49:00,40.798\n2014-04-03 17:54:00,43.602\n2014-04-03 17:59:00,39.574\n2014-04-03 18:04:00,40.69\n2014-04-03 18:09:00,43.968\n2014-04-03 18:14:00,41.198\n2014-04-03 18:19:00,43.15\n2014-04-03 18:24:00,42.23\n2014-04-03 18:29:00,44.56\n2014-04-03 18:34:00,40.422\n2014-04-03 18:39:00,41.01\n2014-04-03 18:44:00,38.544000000000004\n2014-04-03 18:49:00,40.438\n2014-04-03 18:54:00,42.29\n2014-04-03 18:59:00,40.576\n2014-04-03 19:04:00,41.262\n2014-04-03 19:09:00,44.15600000000001\n2014-04-03 19:14:00,42.724\n2014-04-03 19:19:00,36.73\n2014-04-03 19:24:00,45.47\n2014-04-03 19:29:00,38.56800000000001\n2014-04-03 19:34:00,44.062\n2014-04-03 19:39:00,41.552\n2014-04-03 19:44:00,41.256\n2014-04-03 19:49:00,43.544\n2014-04-03 19:54:00,42.816\n2014-04-03 19:59:00,42.91\n2014-04-03 20:04:00,41.15\n2014-04-03 20:09:00,40.846\n2014-04-03 20:14:00,42.211999999999996\n2014-04-03 20:19:00,41.808\n2014-04-03 20:24:00,43.192\n2014-04-03 20:29:00,41.738\n2014-04-03 20:34:00,38.934\n2014-04-03 20:39:00,40.816\n2014-04-03 20:44:00,40.542\n2014-04-03 20:49:00,43.48\n2014-04-03 20:54:00,42.02\n2014-04-03 20:59:00,43.33600000000001\n2014-04-03 21:04:00,37.5\n2014-04-03 21:09:00,42.456\n2014-04-03 21:14:00,40.64\n2014-04-03 21:19:00,42.418\n2014-04-03 21:24:00,42.20399999999999\n2014-04-03 21:29:00,42.35\n2014-04-03 21:34:00,42.136\n2014-04-03 21:39:00,40.14\n2014-04-03 21:44:00,39.742\n2014-04-03 21:49:00,40.63800000000001\n2014-04-03 21:54:00,42.488\n2014-04-03 21:59:00,39.28\n2014-04-03 22:04:00,31.381999999999998\n2014-04-03 22:09:00,34.85\n2014-04-03 22:14:00,34.594\n2014-04-03 22:19:00,38.286\n2014-04-03 22:24:00,32.794000000000004\n2014-04-03 22:29:00,31.408\n2014-04-03 22:34:00,33.251999999999995\n2014-04-03 22:39:00,33.364000000000004\n2014-04-03 22:44:00,33.268\n2014-04-03 22:49:00,34.226\n2014-04-03 22:54:00,36.666\n2014-04-03 22:59:00,36.566\n2014-04-03 23:04:00,30.634\n2014-04-03 23:09:00,35.728\n2014-04-03 23:14:00,35.025999999999996\n2014-04-03 23:19:00,36.292\n2014-04-03 23:24:00,30.09800000000001\n2014-04-03 23:29:00,33.346\n2014-04-03 23:34:00,33.334\n2014-04-03 23:39:00,33.874\n2014-04-03 23:44:00,37.982\n2014-04-03 23:49:00,28.616\n2014-04-03 23:54:00,36.198\n2014-04-03 23:59:00,32.296\n2014-04-04 00:04:00,36.266\n2014-04-04 00:09:00,34.742\n2014-04-04 00:14:00,35.516\n2014-04-04 00:19:00,31.41\n2014-04-04 00:24:00,35.868\n2014-04-04 00:29:00,32.888000000000005\n2014-04-04 00:34:00,33.45\n2014-04-04 00:39:00,33.122\n2014-04-04 00:44:00,33.356\n2014-04-04 00:49:00,35.0\n2014-04-04 00:54:00,32.888000000000005\n2014-04-04 00:59:00,33.258\n2014-04-04 01:04:00,34.87\n2014-04-04 01:09:00,37.536\n2014-04-04 01:14:00,32.534\n2014-04-04 01:19:00,33.216\n2014-04-04 01:24:00,37.834\n2014-04-04 01:29:00,25.25800000000001\n2014-04-04 01:34:00,2.7\n2014-04-04 01:39:00,2.6060000000000003\n2014-04-04 01:44:00,2.77\n2014-04-04 01:49:00,2.5980000000000003\n2014-04-04 01:54:00,4.352\n2014-04-04 01:59:00,2.77\n2014-04-04 02:04:00,2.722\n2014-04-04 02:09:00,4.132\n2014-04-04 02:14:00,2.7\n2014-04-04 02:19:00,2.676\n2014-04-04 02:24:00,2.7939999999999996\n2014-04-04 02:29:00,2.582\n2014-04-04 02:34:00,2.676\n2014-04-04 02:39:00,2.512\n2014-04-04 02:44:00,2.7239999999999998\n2014-04-04 02:49:00,2.676\n2014-04-04 02:54:00,4.414\n2014-04-04 02:59:00,2.84\n2014-04-04 03:04:00,2.912\n2014-04-04 03:09:00,6.22\n2014-04-04 03:14:00,2.7239999999999998\n2014-04-04 03:19:00,2.8160000000000003\n2014-04-04 03:24:00,2.6060000000000003\n2014-04-04 03:29:00,2.7239999999999998\n2014-04-04 03:34:00,2.6060000000000003\n2014-04-04 03:39:00,2.7\n2014-04-04 03:44:00,2.7239999999999998\n2014-04-04 03:49:00,2.596\n2014-04-04 03:54:00,4.352\n2014-04-04 03:59:00,2.77\n2014-04-04 04:04:00,2.8160000000000003\n2014-04-04 04:09:00,4.038\n2014-04-04 04:14:00,2.7939999999999996\n2014-04-04 04:19:00,2.7239999999999998\n2014-04-04 04:24:00,2.722\n2014-04-04 04:29:00,2.7680000000000002\n2014-04-04 04:34:00,2.77\n2014-04-04 04:39:00,2.6060000000000003\n2014-04-04 04:44:00,2.668\n2014-04-04 04:49:00,2.662\n2014-04-04 04:54:00,4.4\n2014-04-04 04:59:00,2.7560000000000002\n2014-04-04 05:04:00,2.84\n2014-04-04 05:09:00,4.342\n2014-04-04 05:14:00,2.7460000000000004\n2014-04-04 05:19:00,2.6060000000000003\n2014-04-04 05:24:00,2.63\n2014-04-04 05:29:00,2.8160000000000003\n2014-04-04 05:34:00,2.6439999999999997\n2014-04-04 05:39:00,2.734\n2014-04-04 05:44:00,2.7\n2014-04-04 05:49:00,2.7\n2014-04-04 05:54:00,4.414\n2014-04-04 05:59:00,2.6519999999999997\n2014-04-04 06:04:00,2.888\n2014-04-04 06:09:00,4.084\n2014-04-04 06:14:00,2.7460000000000004\n2014-04-04 06:19:00,2.6519999999999997\n2014-04-04 06:24:00,2.63\n2014-04-04 06:29:00,2.6519999999999997\n2014-04-04 06:34:00,2.5580000000000003\n2014-04-04 06:39:00,2.7\n2014-04-04 06:44:00,2.7939999999999996\n2014-04-04 06:49:00,2.464\n2014-04-04 06:54:00,4.188\n2014-04-04 06:59:00,2.71\n2014-04-04 07:04:00,2.792\n2014-04-04 07:09:00,4.388\n2014-04-04 07:14:00,2.77\n2014-04-04 07:19:00,2.852\n2014-04-04 07:24:00,2.7\n2014-04-04 07:29:00,2.888\n2014-04-04 07:34:00,2.7460000000000004\n2014-04-04 07:39:00,2.676\n2014-04-04 07:44:00,2.84\n2014-04-04 07:49:00,2.77\n2014-04-04 07:54:00,4.46\n2014-04-04 07:59:00,2.958\n2014-04-04 08:04:00,2.9819999999999998\n2014-04-04 08:09:00,4.32\n2014-04-04 08:14:00,3.1260000000000003\n2014-04-04 08:19:00,2.7239999999999998\n2014-04-04 08:24:00,2.7939999999999996\n2014-04-04 08:29:00,2.6060000000000003\n2014-04-04 08:34:00,2.55\n2014-04-04 08:39:00,2.568\n2014-04-04 08:44:00,2.84\n2014-04-04 08:49:00,2.6060000000000003\n2014-04-04 08:54:00,4.32\n2014-04-04 08:59:00,2.77\n2014-04-04 09:04:00,2.9819999999999998\n2014-04-04 09:09:00,4.39\n2014-04-04 09:14:00,3.556\n2014-04-04 09:19:00,3.3819999999999997\n2014-04-04 09:24:00,3.486\n2014-04-04 09:29:00,3.568\n2014-04-04 09:34:00,3.38\n2014-04-04 09:39:00,3.122\n2014-04-04 09:44:00,3.3560000000000003\n2014-04-04 09:49:00,3.5439999999999996\n2014-04-04 09:54:00,5.234\n2014-04-04 09:59:00,3.51\n2014-04-04 10:04:00,3.512\n2014-04-04 10:09:00,5.046\n2014-04-04 10:14:00,3.6860000000000004\n2014-04-04 10:19:00,3.522\n2014-04-04 10:24:00,3.804\n2014-04-04 10:29:00,3.802\n2014-04-04 10:34:00,3.946\n2014-04-04 10:39:00,3.78\n2014-04-04 10:44:00,3.968\n2014-04-04 10:49:00,3.742\n2014-04-04 10:54:00,5.916\n2014-04-04 10:59:00,3.6860000000000004\n2014-04-04 11:04:00,3.568\n2014-04-04 11:09:00,5.2120000000000015\n2014-04-04 11:14:00,3.498\n2014-04-04 11:19:00,3.262\n2014-04-04 11:24:00,3.286\n2014-04-04 11:29:00,3.85\n2014-04-04 11:34:00,3.92\n2014-04-04 11:39:00,3.592\n2014-04-04 11:44:00,3.404\n2014-04-04 11:49:00,3.1919999999999997\n2014-04-04 11:54:00,5.093999999999999\n2014-04-04 11:59:00,3.3339999999999996\n2014-04-04 12:04:00,3.616\n2014-04-04 12:09:00,5.376\n2014-04-04 12:14:00,3.5439999999999996\n2014-04-04 12:19:00,3.592\n2014-04-04 12:24:00,3.24\n2014-04-04 12:29:00,3.38\n2014-04-04 12:34:00,2.7239999999999998\n2014-04-04 12:39:00,2.7460000000000004\n2014-04-04 12:44:00,2.676\n2014-04-04 12:49:00,2.582\n2014-04-04 12:54:00,4.954\n2014-04-04 12:59:00,3.332\n2014-04-04 13:04:00,3.428\n2014-04-04 13:09:00,4.954\n2014-04-04 13:14:00,3.38\n2014-04-04 13:19:00,3.45\n2014-04-04 13:24:00,3.1919999999999997\n2014-04-04 13:29:00,3.3339999999999996\n2014-04-04 13:34:00,3.122\n2014-04-04 13:39:00,3.1460000000000004\n2014-04-04 13:44:00,3.404\n2014-04-04 13:49:00,2.9339999999999997\n2014-04-04 13:54:00,5.188\n2014-04-04 13:59:00,3.45\n2014-04-04 14:04:00,2.7239999999999998\n2014-04-04 14:09:00,4.32\n2014-04-04 14:14:00,3.5439999999999996\n2014-04-04 14:19:00,3.1919999999999997\n2014-04-04 14:24:00,3.216\n2014-04-04 14:29:00,3.522\n2014-04-04 14:34:00,2.7\n2014-04-04 14:39:00,3.498\n2014-04-04 14:44:00,3.522\n2014-04-04 14:49:00,3.216\n2014-04-04 14:54:00,4.812\n2014-04-04 14:59:00,2.7939999999999996\n2014-04-04 15:04:00,2.958\n2014-04-04 15:09:00,4.132\n2014-04-04 15:14:00,2.7680000000000002\n2014-04-04 15:19:00,2.63\n2014-04-04 15:24:00,2.6060000000000003\n2014-04-04 15:29:00,2.536\n2014-04-04 15:34:00,2.6060000000000003\n2014-04-04 15:39:00,2.6919999999999997\n2014-04-04 15:44:00,2.568\n2014-04-04 15:49:00,56.854\n2014-04-04 15:54:00,38.874\n2014-04-04 15:59:00,34.202\n2014-04-04 16:04:00,35.961999999999996\n2014-04-04 16:09:00,34.46\n2014-04-04 16:14:00,32.726\n2014-04-04 16:19:00,35.0\n2014-04-04 16:24:00,31.08\n2014-04-04 16:29:00,34.32\n2014-04-04 16:34:00,34.084\n2014-04-04 16:39:00,31.268\n2014-04-04 16:44:00,33.18\n2014-04-04 16:49:00,35.046\n2014-04-04 16:54:00,32.91\n2014-04-04 16:59:00,32.808\n2014-04-04 17:04:00,34.366\n2014-04-04 17:09:00,36.476\n2014-04-04 17:14:00,34.084\n2014-04-04 17:19:00,33.004\n2014-04-04 17:24:00,35.211999999999996\n2014-04-04 17:29:00,30.58\n2014-04-04 17:34:00,33.498000000000005\n2014-04-04 17:39:00,35.62\n2014-04-04 17:44:00,32.84\n2014-04-04 17:49:00,32.37\n2014-04-04 17:54:00,35.192\n2014-04-04 17:59:00,34.632\n2014-04-04 18:04:00,35.938\n2014-04-04 18:09:00,36.738\n2014-04-04 18:14:00,34.062\n2014-04-04 18:19:00,31.971999999999998\n2014-04-04 18:24:00,32.018\n2014-04-04 18:29:00,33.146\n2014-04-04 18:34:00,35.821999999999996\n2014-04-04 18:39:00,35.376\n2014-04-04 18:44:00,31.644000000000002\n2014-04-04 18:49:00,33.122\n2014-04-04 18:54:00,35.262\n2014-04-04 18:59:00,38.31\n2014-04-04 19:04:00,31.15\n2014-04-04 19:09:00,36.672\n2014-04-04 19:14:00,31.524\n2014-04-04 19:19:00,33.356\n2014-04-04 19:24:00,33.474000000000004\n2014-04-04 19:29:00,33.344\n2014-04-04 19:34:00,36.032\n2014-04-04 19:39:00,36.086\n2014-04-04 19:44:00,34.59\n2014-04-04 19:49:00,30.564\n2014-04-04 19:54:00,36.244\n2014-04-04 19:59:00,34.972\n2014-04-04 20:04:00,33.192\n2014-04-04 20:09:00,37.864000000000004\n2014-04-04 20:14:00,30.218000000000004\n2014-04-04 20:19:00,33.216\n2014-04-04 20:24:00,33.098\n2014-04-04 20:29:00,35.732\n2014-04-04 20:34:00,32.442\n2014-04-04 20:39:00,32.512\n2014-04-04 20:44:00,32.016\n2014-04-04 20:49:00,33.554\n2014-04-04 20:54:00,35.4\n2014-04-04 20:59:00,33.13\n2014-04-04 21:04:00,33.38\n2014-04-04 21:09:00,36.554\n2014-04-04 21:14:00,35.211999999999996\n2014-04-04 21:19:00,32.218\n2014-04-04 21:24:00,34.596\n2014-04-04 21:29:00,31.984\n2014-04-04 21:34:00,33.722\n2014-04-04 21:39:00,35.54\n2014-04-04 21:44:00,31.448\n2014-04-04 21:49:00,33.284\n2014-04-04 21:54:00,34.882\n2014-04-04 21:59:00,33.522\n2014-04-04 22:04:00,33.198\n2014-04-04 22:09:00,36.268\n2014-04-04 22:14:00,36.431999999999995\n2014-04-04 22:19:00,31.268\n2014-04-04 22:24:00,33.052\n2014-04-04 22:29:00,33.082\n2014-04-04 22:34:00,32.91\n2014-04-04 22:39:00,35.22\n2014-04-04 22:44:00,32.65\n2014-04-04 22:49:00,33.802\n2014-04-04 22:54:00,32.746\n2014-04-04 22:59:00,33.24\n2014-04-04 23:04:00,33.262\n2014-04-04 23:09:00,36.62\n2014-04-04 23:14:00,34.01\n2014-04-04 23:19:00,34.766\n2014-04-04 23:24:00,34.976\n2014-04-04 23:29:00,33.498000000000005\n2014-04-04 23:34:00,35.774\n2014-04-04 23:39:00,34.906\n2014-04-04 23:44:00,30.986\n2014-04-04 23:49:00,36.15\n2014-04-04 23:54:00,35.42800000000001\n2014-04-04 23:59:00,37.394\n2014-04-05 00:04:00,35.046\n2014-04-05 00:09:00,39.644\n2014-04-05 00:14:00,31.738000000000003\n2014-04-05 00:19:00,33.472\n2014-04-05 00:24:00,33.356\n2014-04-05 00:29:00,35.798\n2014-04-05 00:34:00,30.564\n2014-04-05 00:39:00,37.394\n2014-04-05 00:44:00,34.014\n2014-04-05 00:49:00,31.314\n2014-04-05 00:54:00,34.882\n2014-04-05 00:59:00,33.404\n2014-04-05 01:04:00,35.306\n2014-04-05 01:09:00,35.492\n2014-04-05 01:14:00,36.361999999999995\n2014-04-05 01:19:00,30.506\n2014-04-05 01:24:00,33.216\n2014-04-05 01:29:00,35.986\n2014-04-05 01:34:00,36.784\n2014-04-05 01:39:00,31.186\n2014-04-05 01:44:00,33.952\n2014-04-05 01:49:00,33.85\n2014-04-05 01:54:00,35.61\n2014-04-05 01:59:00,34.16\n2014-04-05 02:04:00,38.896\n2014-04-05 02:09:00,32.418\n2014-04-05 02:14:00,35.211999999999996\n2014-04-05 02:19:00,32.746\n2014-04-05 02:24:00,32.16\n2014-04-05 02:29:00,33.616\n2014-04-05 02:34:00,33.474000000000004\n2014-04-05 02:39:00,35.54400000000001\n2014-04-05 02:44:00,31.62\n2014-04-05 02:49:00,36.384\n2014-04-05 02:54:00,34.484\n2014-04-05 02:59:00,36.22\n2014-04-05 03:04:00,33.428000000000004\n2014-04-05 03:09:00,39.132\n2014-04-05 03:14:00,31.526\n2014-04-05 03:19:00,33.262\n2014-04-05 03:24:00,33.45\n2014-04-05 03:29:00,33.65\n2014-04-05 03:34:00,39.554\n2014-04-05 03:39:00,30.055999999999997\n2014-04-05 03:44:00,35.938\n2014-04-05 03:49:00,31.502\n2014-04-05 03:54:00,35.525999999999996\n2014-04-05 03:59:00,33.616\n2014-04-05 04:04:00,33.826\n2014-04-05 04:09:00,38.31\n2014-04-05 04:14:00,38.278\n2014-04-05 04:19:00,35.868\n2014-04-05 04:24:00,31.268\n2014-04-05 04:29:00,33.968\n2014-04-05 04:34:00,33.68\n2014-04-05 04:39:00,33.356\n2014-04-05 04:44:00,35.066\n2014-04-05 04:49:00,31.342\n2014-04-05 04:54:00,36.268\n2014-04-05 04:59:00,32.536\n2014-04-05 05:04:00,33.028\n2014-04-05 05:09:00,38.616\n2014-04-05 05:14:00,32.404\n2014-04-05 05:19:00,35.164\n2014-04-05 05:24:00,31.408\n2014-04-05 05:29:00,34.624\n2014-04-05 05:34:00,32.3\n2014-04-05 05:39:00,34.988\n2014-04-05 05:44:00,35.284\n2014-04-05 05:49:00,33.356\n2014-04-05 05:54:00,36.878\n2014-04-05 05:59:00,31.41\n2014-04-05 06:04:00,36.596\n2014-04-05 06:09:00,31.714000000000002\n2014-04-05 06:14:00,33.234\n2014-04-05 06:19:00,33.098\n2014-04-05 06:24:00,36.644\n2014-04-05 06:29:00,32.464\n2014-04-05 06:34:00,33.24\n2014-04-05 06:39:00,34.414\n2014-04-05 06:44:00,32.348\n2014-04-05 06:49:00,35.68\n2014-04-05 06:54:00,35.44\n2014-04-05 06:59:00,34.062\n2014-04-05 07:04:00,33.216\n2014-04-05 07:09:00,34.972\n2014-04-05 07:14:00,34.672\n2014-04-05 07:19:00,31.83\n2014-04-05 07:24:00,35.17\n2014-04-05 07:29:00,31.478\n2014-04-05 07:34:00,36.21\n2014-04-05 07:39:00,36.854\n2014-04-05 07:44:00,31.15\n2014-04-05 07:49:00,34.436\n2014-04-05 07:54:00,33.874\n2014-04-05 07:59:00,35.07\n2014-04-05 08:04:00,34.006\n2014-04-05 08:09:00,36.566\n2014-04-05 08:14:00,34.882\n2014-04-05 08:19:00,33.254\n2014-04-05 08:24:00,38.896\n2014-04-05 08:29:00,27.676\n2014-04-05 08:34:00,33.344\n2014-04-05 08:39:00,33.286\n2014-04-05 08:44:00,33.424\n2014-04-05 08:49:00,33.24\n2014-04-05 08:54:00,36.948\n2014-04-05 08:59:00,36.582\n2014-04-05 09:04:00,33.604\n2014-04-05 09:09:00,37.652\n2014-04-05 09:14:00,31.031999999999996\n2014-04-05 09:19:00,33.31\n2014-04-05 09:24:00,35.188\n2014-04-05 09:29:00,31.456\n2014-04-05 09:34:00,34.906\n2014-04-05 09:39:00,32.442\n2014-04-05 09:44:00,33.732\n2014-04-05 09:49:00,35.916\n2014-04-05 09:54:00,39.578\n2014-04-05 09:59:00,31.61\n2014-04-05 10:04:00,33.312\n2014-04-05 10:09:00,34.93\n2014-04-05 10:14:00,35.891999999999996\n2014-04-05 10:19:00,34.972\n2014-04-05 10:24:00,37.864000000000004\n2014-04-05 10:29:00,31.302\n2014-04-05 10:34:00,33.482\n2014-04-05 10:39:00,35.938\n2014-04-05 10:44:00,30.634\n2014-04-05 10:49:00,33.111999999999995\n2014-04-05 10:54:00,36.461999999999996\n2014-04-05 10:59:00,33.686\n2014-04-05 11:04:00,31.338\n2014-04-05 11:09:00,37.816\n2014-04-05 11:14:00,33.358000000000004\n2014-04-05 11:19:00,33.076\n2014-04-05 11:24:00,34.226\n2014-04-05 11:29:00,35.352\n2014-04-05 11:34:00,30.421999999999997\n2014-04-05 11:39:00,33.896\n2014-04-05 11:44:00,33.616\n2014-04-05 11:49:00,33.356\n2014-04-05 11:54:00,34.976\n2014-04-05 11:59:00,33.262\n2014-04-05 12:04:00,35.238\n2014-04-05 12:09:00,33.506\n2014-04-05 12:14:00,36.08\n2014-04-05 12:19:00,30.164\n2014-04-05 12:24:00,35.961999999999996\n2014-04-05 12:29:00,33.31\n2014-04-05 12:34:00,35.14\n2014-04-05 12:39:00,31.644000000000002\n2014-04-05 12:44:00,33.592\n2014-04-05 12:49:00,34.224000000000004\n2014-04-05 12:54:00,33.732\n2014-04-05 12:59:00,35.0\n2014-04-05 13:04:00,33.912\n2014-04-05 13:09:00,33.376\n2014-04-05 13:14:00,33.404\n2014-04-05 13:19:00,34.53\n2014-04-05 13:24:00,37.148\n2014-04-05 13:29:00,33.568000000000005\n2014-04-05 13:34:00,35.564\n2014-04-05 13:39:00,32.078\n2014-04-05 13:44:00,35.14\n2014-04-05 13:49:00,32.218\n2014-04-05 13:54:00,35.164\n2014-04-05 13:59:00,36.455999999999996\n2014-04-05 14:04:00,30.25800000000001\n2014-04-05 14:09:00,34.554\n2014-04-05 14:14:00,33.251999999999995\n2014-04-05 14:19:00,37.196\n2014-04-05 14:24:00,33.146\n2014-04-05 14:29:00,35.168\n2014-04-05 14:34:00,34.068000000000005\n2014-04-05 14:39:00,30.491999999999997\n2014-04-05 14:44:00,33.474000000000004\n2014-04-05 14:49:00,35.83\n2014-04-05 14:54:00,36.41\n2014-04-05 14:59:00,36.174\n2014-04-05 15:04:00,38.028\n2014-04-05 15:09:00,35.914\n2014-04-05 15:14:00,32.205999999999996\n2014-04-05 15:19:00,35.868\n2014-04-05 15:24:00,30.68\n2014-04-05 15:29:00,33.65\n2014-04-05 15:34:00,35.59\n2014-04-05 15:39:00,34.672\n2014-04-05 15:44:00,35.094\n2014-04-05 15:49:00,32.238\n2014-04-05 15:54:00,35.124\n2014-04-05 15:59:00,33.374\n2014-04-05 16:04:00,36.83\n2014-04-05 16:09:00,31.244\n2014-04-05 16:14:00,36.192\n2014-04-05 16:19:00,34.63\n2014-04-05 16:24:00,31.971999999999998\n2014-04-05 16:29:00,35.14\n2014-04-05 16:34:00,31.78\n2014-04-05 16:39:00,33.004\n2014-04-05 16:44:00,33.522\n2014-04-05 16:49:00,35.806\n2014-04-05 16:54:00,33.814\n2014-04-05 16:59:00,34.226\n2014-04-05 17:04:00,31.502\n2014-04-05 17:09:00,34.86\n2014-04-05 17:14:00,34.93\n2014-04-05 17:19:00,35.89\n2014-04-05 17:24:00,33.464\n2014-04-05 17:29:00,36.244\n2014-04-05 17:34:00,30.464000000000002\n2014-04-05 17:39:00,34.202\n2014-04-05 17:44:00,33.78\n2014-04-05 17:49:00,33.334\n2014-04-05 17:54:00,35.046\n2014-04-05 17:59:00,35.4\n2014-04-05 18:04:00,33.076\n2014-04-05 18:09:00,35.13\n2014-04-05 18:14:00,34.896\n2014-04-05 18:19:00,35.774\n2014-04-05 18:24:00,33.826\n2014-04-05 18:29:00,36.384\n2014-04-05 18:34:00,32.794000000000004\n2014-04-05 18:39:00,34.436\n2014-04-05 18:44:00,31.974\n2014-04-05 18:49:00,33.146\n2014-04-05 18:54:00,36.056\n2014-04-05 18:59:00,36.808\n2014-04-05 19:04:00,33.99\n2014-04-05 19:09:00,32.152\n2014-04-05 19:14:00,34.742\n2014-04-05 19:19:00,32.111999999999995\n2014-04-05 19:24:00,33.292\n2014-04-05 19:29:00,38.028\n2014-04-05 19:34:00,33.146\n2014-04-05 19:39:00,33.874\n2014-04-05 19:44:00,34.132\n2014-04-05 19:49:00,33.732\n2014-04-05 19:54:00,35.844\n2014-04-05 19:59:00,32.205999999999996\n2014-04-05 20:04:00,35.306\n2014-04-05 20:09:00,33.286\n2014-04-05 20:14:00,33.286\n2014-04-05 20:19:00,33.448\n2014-04-05 20:24:00,33.286\n2014-04-05 20:29:00,34.366\n2014-04-05 20:34:00,35.306\n2014-04-05 20:39:00,32.536\n2014-04-05 20:44:00,33.568000000000005\n2014-04-05 20:49:00,33.404\n2014-04-05 20:54:00,35.0\n2014-04-05 20:59:00,33.474000000000004\n2014-04-05 21:04:00,36.338\n2014-04-05 21:09:00,31.784000000000002\n2014-04-05 21:14:00,33.64\n2014-04-05 21:19:00,35.391999999999996\n2014-04-05 21:24:00,31.198\n2014-04-05 21:29:00,33.522\n2014-04-05 21:34:00,33.498000000000005\n2014-04-05 21:39:00,35.774\n2014-04-05 21:44:00,33.262\n2014-04-05 21:49:00,31.892\n2014-04-05 21:54:00,35.234\n2014-04-05 21:59:00,33.356\n2014-04-05 22:04:00,33.568000000000005\n2014-04-05 22:09:00,37.452\n2014-04-05 22:14:00,33.498000000000005\n2014-04-05 22:19:00,31.338\n2014-04-05 22:24:00,37.176\n2014-04-05 22:29:00,32.218\n2014-04-05 22:34:00,33.334\n2014-04-05 22:39:00,33.38\n2014-04-05 22:44:00,35.54\n2014-04-05 22:49:00,32.512\n2014-04-05 22:54:00,36.972\n2014-04-05 22:59:00,34.53\n2014-04-05 23:04:00,32.388000000000005\n2014-04-05 23:09:00,35.024\n2014-04-05 23:14:00,35.42800000000001\n2014-04-05 23:19:00,31.174\n2014-04-05 23:24:00,34.812\n2014-04-05 23:29:00,35.99800000000001\n2014-04-05 23:34:00,33.878\n2014-04-05 23:39:00,35.352\n2014-04-05 23:44:00,34.554\n2014-04-05 23:49:00,34.132\n2014-04-05 23:54:00,32.63\n2014-04-05 23:59:00,33.498000000000005\n2014-04-06 00:04:00,33.45\n2014-04-06 00:09:00,34.718\n2014-04-06 00:14:00,35.282\n2014-04-06 00:19:00,32.442\n2014-04-06 00:24:00,32.348\n2014-04-06 00:29:00,33.38\n2014-04-06 00:34:00,35.891999999999996\n2014-04-06 00:39:00,33.592\n2014-04-06 00:44:00,35.306\n2014-04-06 00:49:00,31.362\n2014-04-06 00:54:00,36.361999999999995\n2014-04-06 00:59:00,31.886\n2014-04-06 01:04:00,34.635999999999996\n2014-04-06 01:09:00,39.688\n2014-04-06 01:14:00,32.244\n2014-04-06 01:19:00,34.508\n2014-04-06 01:24:00,34.016\n2014-04-06 01:29:00,32.5\n2014-04-06 01:34:00,34.108000000000004\n2014-04-06 01:39:00,36.714\n2014-04-06 01:44:00,32.3\n2014-04-06 01:49:00,33.756\n2014-04-06 01:54:00,35.564\n2014-04-06 01:59:00,33.802\n2014-04-06 02:04:00,36.86\n2014-04-06 02:09:00,36.476\n2014-04-06 02:14:00,31.572\n2014-04-06 02:19:00,33.428000000000004\n2014-04-06 02:24:00,33.461999999999996\n2014-04-06 02:29:00,33.326\n2014-04-06 02:34:00,33.146\n2014-04-06 02:39:00,36.294000000000004\n2014-04-06 02:44:00,29.976\n2014-04-06 02:49:00,35.54\n2014-04-06 02:54:00,34.444\n2014-04-06 02:59:00,34.788000000000004\n2014-04-06 03:04:00,34.718\n2014-04-06 03:09:00,38.094\n2014-04-06 03:14:00,32.84\n2014-04-06 03:19:00,36.571999999999996\n2014-04-06 03:24:00,32.288000000000004\n2014-04-06 03:29:00,33.592\n2014-04-06 03:34:00,35.646\n2014-04-06 03:39:00,36.796\n2014-04-06 03:44:00,33.31\n2014-04-06 03:49:00,31.59\n2014-04-06 03:54:00,36.596\n2014-04-06 03:59:00,37.368\n2014-04-06 04:04:00,33.821999999999996\n2014-04-06 04:09:00,35.07\n2014-04-06 04:14:00,35.422\n2014-04-06 04:19:00,31.16\n2014-04-06 04:24:00,33.288000000000004\n2014-04-06 04:29:00,35.188\n2014-04-06 04:34:00,32.488\n2014-04-06 04:39:00,32.042\n2014-04-06 04:44:00,35.352\n2014-04-06 04:49:00,31.3\n2014-04-06 04:54:00,34.976\n2014-04-06 04:59:00,36.056\n2014-04-06 05:04:00,33.638000000000005\n2014-04-06 05:09:00,39.39\n2014-04-06 05:14:00,31.866\n2014-04-06 05:19:00,35.21\n2014-04-06 05:24:00,31.612\n2014-04-06 05:29:00,33.544000000000004\n2014-04-06 05:34:00,33.628\n2014-04-06 05:39:00,36.008\n2014-04-06 05:44:00,33.076\n2014-04-06 05:49:00,31.962\n2014-04-06 05:54:00,36.361999999999995\n2014-04-06 05:59:00,34.554\n2014-04-06 06:04:00,33.522\n2014-04-06 06:09:00,38.33\n2014-04-06 06:14:00,36.08\n2014-04-06 06:19:00,33.92\n2014-04-06 06:24:00,31.996\n2014-04-06 06:29:00,34.624\n2014-04-06 06:34:00,34.272\n2014-04-06 06:39:00,33.85\n2014-04-06 06:44:00,35.894\n2014-04-06 06:49:00,33.262\n2014-04-06 06:54:00,39.062\n2014-04-06 06:59:00,32.146\n2014-04-06 07:04:00,31.91\n2014-04-06 07:09:00,34.928000000000004\n2014-04-06 07:14:00,37.63\n2014-04-06 07:19:00,32.816\n2014-04-06 07:24:00,33.544000000000004\n2014-04-06 07:29:00,33.58\n2014-04-06 07:34:00,35.53\n2014-04-06 07:39:00,32.9\n2014-04-06 07:44:00,36.69\n2014-04-06 07:49:00,34.27\n2014-04-06 07:54:00,36.15\n2014-04-06 07:59:00,35.376\n2014-04-06 08:04:00,33.99\n2014-04-06 08:09:00,35.164\n2014-04-06 08:14:00,35.118\n2014-04-06 08:19:00,32.394\n2014-04-06 08:24:00,35.47\n2014-04-06 08:29:00,31.924\n2014-04-06 08:34:00,36.338\n2014-04-06 08:39:00,30.854\n2014-04-06 08:44:00,35.25\n2014-04-06 08:49:00,36.384\n2014-04-06 08:54:00,35.891999999999996\n2014-04-06 08:59:00,33.344\n2014-04-06 09:04:00,35.958\n2014-04-06 09:09:00,36.216\n2014-04-06 09:14:00,34.048\n2014-04-06 09:19:00,36.144\n2014-04-06 09:24:00,32.652\n2014-04-06 09:29:00,32.582\n2014-04-06 09:34:00,33.944\n2014-04-06 09:39:00,34.332\n2014-04-06 09:44:00,35.542\n2014-04-06 09:49:00,37.018\n2014-04-06 09:54:00,33.474000000000004\n2014-04-06 09:59:00,34.05\n2014-04-06 10:04:00,37.676\n2014-04-06 10:09:00,36.4\n2014-04-06 10:14:00,33.896\n2014-04-06 10:19:00,35.376\n2014-04-06 10:24:00,31.264\n2014-04-06 10:29:00,33.428000000000004\n2014-04-06 10:34:00,33.19\n2014-04-06 10:39:00,34.578\n2014-04-06 10:44:00,34.854\n2014-04-06 10:49:00,37.63\n2014-04-06 10:54:00,30.445999999999998\n2014-04-06 10:59:00,36.054\n2014-04-06 11:04:00,34.672\n2014-04-06 11:09:00,36.455999999999996\n2014-04-06 11:14:00,34.73\n2014-04-06 11:19:00,34.084\n2014-04-06 11:24:00,31.471999999999998\n2014-04-06 11:29:00,33.498000000000005\n2014-04-06 11:34:00,36.314\n2014-04-06 11:39:00,32.558\n2014-04-06 11:44:00,35.188\n2014-04-06 11:49:00,36.571999999999996\n2014-04-06 11:54:00,31.971999999999998\n2014-04-06 11:59:00,33.38\n2014-04-06 12:04:00,33.638000000000005\n2014-04-06 12:09:00,34.948\n2014-04-06 12:14:00,33.262\n2014-04-06 12:19:00,35.146\n2014-04-06 12:24:00,35.258\n2014-04-06 12:29:00,29.741999999999997\n2014-04-06 12:34:00,33.498000000000005\n2014-04-06 12:39:00,33.321999999999996\n2014-04-06 12:44:00,36.384\n2014-04-06 12:49:00,33.028\n2014-04-06 12:54:00,37.042\n2014-04-06 12:59:00,32.63\n2014-04-06 13:04:00,32.09\n2014-04-06 13:09:00,37.672\n2014-04-06 13:14:00,30.938000000000002\n2014-04-06 13:19:00,33.192\n2014-04-06 13:24:00,33.286\n2014-04-06 13:29:00,35.586\n2014-04-06 13:34:00,35.634\n2014-04-06 13:39:00,35.14\n2014-04-06 13:44:00,33.756\n2014-04-06 13:49:00,33.156\n2014-04-06 13:54:00,35.118\n2014-04-06 13:59:00,36.93\n2014-04-06 14:04:00,30.0\n2014-04-06 14:09:00,35.036\n2014-04-06 14:14:00,34.718\n2014-04-06 14:19:00,32.184\n2014-04-06 14:24:00,35.821999999999996\n2014-04-06 14:29:00,37.958\n2014-04-06 14:34:00,31.464000000000002\n2014-04-06 14:39:00,33.522\n2014-04-06 14:44:00,33.39\n2014-04-06 14:49:00,35.774\n2014-04-06 14:54:00,33.718\n2014-04-06 14:59:00,32.042\n2014-04-06 15:04:00,35.306\n2014-04-06 15:09:00,32.726\n2014-04-06 15:14:00,33.544000000000004\n2014-04-06 15:19:00,33.24\n2014-04-06 15:24:00,35.961999999999996\n2014-04-06 15:29:00,33.428000000000004\n2014-04-06 15:34:00,36.571999999999996\n2014-04-06 15:39:00,33.474000000000004\n2014-04-06 15:44:00,31.031999999999996\n2014-04-06 15:49:00,33.204\n2014-04-06 15:54:00,36.314\n2014-04-06 15:59:00,34.89\n2014-04-06 16:04:00,35.62\n2014-04-06 16:09:00,33.004\n2014-04-06 16:14:00,34.694\n2014-04-06 16:19:00,31.712\n2014-04-06 16:24:00,33.122\n2014-04-06 16:29:00,36.198\n2014-04-06 16:34:00,32.436\n2014-04-06 16:39:00,31.362\n2014-04-06 16:44:00,33.428000000000004\n2014-04-06 16:49:00,33.216\n2014-04-06 16:54:00,36.15\n2014-04-06 16:59:00,32.184\n2014-04-06 17:04:00,33.58\n2014-04-06 17:09:00,36.972\n2014-04-06 17:14:00,31.596\n2014-04-06 17:19:00,37.286\n2014-04-06 17:24:00,31.901999999999997\n2014-04-06 17:29:00,34.648\n2014-04-06 17:34:00,32.418\n2014-04-06 17:39:00,35.854\n2014-04-06 17:44:00,31.854\n2014-04-06 17:49:00,33.428000000000004\n2014-04-06 17:54:00,35.146\n2014-04-06 17:59:00,33.404\n2014-04-06 18:04:00,34.906\n2014-04-06 18:09:00,38.396\n2014-04-06 18:14:00,28.92\n2014-04-06 18:19:00,33.46\n2014-04-06 18:24:00,33.686\n2014-04-06 18:29:00,33.498000000000005\n2014-04-06 18:34:00,35.75199999999999\n2014-04-06 18:39:00,36.571999999999996\n2014-04-06 18:44:00,30.206\n2014-04-06 18:49:00,33.474000000000004\n2014-04-06 18:54:00,37.632\n2014-04-06 18:59:00,30.728\n2014-04-06 19:04:00,33.568000000000005\n2014-04-06 19:09:00,35.122\n2014-04-06 19:14:00,35.211999999999996\n2014-04-06 19:19:00,32.582\n2014-04-06 19:24:00,32.184\n2014-04-06 19:29:00,33.498000000000005\n2014-04-06 19:34:00,36.501999999999995\n2014-04-06 19:39:00,33.96\n2014-04-06 19:44:00,36.244\n2014-04-06 19:49:00,32.888000000000005\n2014-04-06 19:54:00,32.536\n2014-04-06 19:59:00,34.836\n2014-04-06 20:04:00,32.076\n2014-04-06 20:09:00,35.118\n2014-04-06 20:14:00,34.806\n2014-04-06 20:19:00,37.84\n2014-04-06 20:24:00,31.388\n2014-04-06 20:29:00,33.391999999999996\n2014-04-06 20:34:00,34.86\n2014-04-06 20:39:00,31.634\n2014-04-06 20:44:00,33.708\n2014-04-06 20:49:00,33.286\n2014-04-06 20:54:00,36.784\n2014-04-06 20:59:00,31.76\n2014-04-06 21:04:00,33.568000000000005\n2014-04-06 21:09:00,36.55\n2014-04-06 21:14:00,32.3\n2014-04-06 21:19:00,35.868\n2014-04-06 21:24:00,32.7\n2014-04-06 21:29:00,32.724000000000004\n2014-04-06 21:34:00,35.058\n2014-04-06 21:39:00,37.944\n2014-04-06 21:44:00,32.558\n2014-04-06 21:49:00,33.484\n2014-04-06 21:54:00,37.16\n2014-04-06 21:59:00,34.084\n2014-04-06 22:04:00,31.01\n2014-04-06 22:09:00,35.188\n2014-04-06 22:14:00,33.65\n2014-04-06 22:19:00,34.514\n2014-04-06 22:24:00,33.896\n2014-04-06 22:29:00,31.552\n2014-04-06 22:34:00,33.404\n2014-04-06 22:39:00,33.24\n2014-04-06 22:44:00,35.896\n2014-04-06 22:49:00,30.68\n2014-04-06 22:54:00,36.275999999999996\n2014-04-06 22:59:00,34.02\n2014-04-06 23:04:00,31.604\n2014-04-06 23:09:00,34.93\n2014-04-06 23:14:00,33.474000000000004\n2014-04-06 23:19:00,33.498000000000005\n2014-04-06 23:24:00,33.24\n2014-04-06 23:29:00,36.816\n2014-04-06 23:34:00,33.356\n2014-04-06 23:39:00,31.408\n2014-04-06 23:44:00,33.708\n2014-04-06 23:49:00,33.31\n2014-04-06 23:54:00,34.958\n2014-04-06 23:59:00,36.244\n2014-04-07 00:04:00,35.282\n2014-04-07 00:09:00,34.272\n2014-04-07 00:14:00,32.275999999999996\n2014-04-07 00:19:00,38.42\n2014-04-07 00:24:00,30.658\n2014-04-07 00:29:00,33.31\n2014-04-07 00:34:00,34.954\n2014-04-07 00:39:00,35.282\n2014-04-07 00:44:00,32.676\n2014-04-07 00:49:00,33.17\n2014-04-07 00:54:00,34.87\n2014-04-07 00:59:00,33.662\n2014-04-07 01:04:00,37.794000000000004\n2014-04-07 01:09:00,30.73\n2014-04-07 01:14:00,33.662\n2014-04-07 01:19:00,36.948\n2014-04-07 01:24:00,32.205999999999996\n2014-04-07 01:29:00,33.286\n2014-04-07 01:34:00,35.492\n2014-04-07 01:39:00,31.924\n2014-04-07 01:44:00,33.78\n2014-04-07 01:49:00,33.38\n2014-04-07 01:54:00,35.274\n2014-04-07 01:59:00,35.254\n2014-04-07 02:04:00,33.896\n2014-04-07 02:09:00,33.004\n2014-04-07 02:14:00,33.256\n2014-04-07 02:19:00,33.368\n2014-04-07 02:24:00,36.052\n2014-04-07 02:29:00,34.624\n2014-04-07 02:34:00,33.71\n2014-04-07 02:39:00,34.154\n2014-04-07 02:44:00,30.892\n2014-04-07 02:49:00,33.17\n2014-04-07 02:54:00,35.078\n2014-04-07 02:59:00,33.53\n2014-04-07 03:04:00,36.996\n2014-04-07 03:09:00,31.54\n2014-04-07 03:14:00,33.544000000000004\n2014-04-07 03:19:00,34.624\n2014-04-07 03:24:00,36.472\n2014-04-07 03:29:00,35.961999999999996\n2014-04-07 03:34:00,32.762\n2014-04-07 03:39:00,33.424\n2014-04-07 03:44:00,32.512\n2014-04-07 03:49:00,33.404\n2014-04-07 03:54:00,35.118\n2014-04-07 03:59:00,33.641999999999996\n2014-04-07 04:04:00,35.61\n2014-04-07 04:09:00,35.674\n2014-04-07 04:14:00,33.726\n2014-04-07 04:19:00,34.812\n2014-04-07 04:24:00,34.955999999999996\n2014-04-07 04:29:00,33.568000000000005\n2014-04-07 04:34:00,35.046\n2014-04-07 04:39:00,31.654\n2014-04-07 04:44:00,33.848\n2014-04-07 04:49:00,37.09\n2014-04-07 04:54:00,30.938000000000002\n2014-04-07 04:59:00,33.428000000000004\n2014-04-07 05:04:00,35.306\n2014-04-07 05:09:00,32.846\n2014-04-07 05:14:00,33.732\n2014-04-07 05:19:00,33.1\n2014-04-07 05:24:00,35.824\n2014-04-07 05:29:00,33.78\n2014-04-07 05:34:00,39.356\n2014-04-07 05:39:00,31.174\n2014-04-07 05:44:00,34.312\n2014-04-07 05:49:00,33.616\n2014-04-07 05:54:00,36.01\n2014-04-07 05:59:00,37.111999999999995\n2014-04-07 06:04:00,30.68\n2014-04-07 06:09:00,35.376\n2014-04-07 06:14:00,36.442\n2014-04-07 06:19:00,31.314\n2014-04-07 06:24:00,35.868\n2014-04-07 06:29:00,33.408\n2014-04-07 06:34:00,33.742\n2014-04-07 06:39:00,35.024\n2014-04-07 06:44:00,34.038000000000004\n2014-04-07 06:49:00,35.564\n2014-04-07 06:54:00,33.498000000000005\n2014-04-07 06:59:00,33.99\n2014-04-07 07:04:00,35.868\n2014-04-07 07:09:00,32.86\n2014-04-07 07:14:00,35.746\n2014-04-07 07:19:00,35.41\n2014-04-07 07:24:00,35.024\n2014-04-07 07:29:00,33.686\n2014-04-07 07:34:00,33.99\n2014-04-07 07:39:00,34.108000000000004\n2014-04-07 07:44:00,35.188\n2014-04-07 07:49:00,33.931999999999995\n2014-04-07 07:54:00,35.891999999999996\n2014-04-07 07:59:00,31.125999999999998\n2014-04-07 08:04:00,35.622\n2014-04-07 08:09:00,35.704\n2014-04-07 08:14:00,33.492\n2014-04-07 08:19:00,33.24\n2014-04-07 08:24:00,36.494\n2014-04-07 08:29:00,30.342\n2014-04-07 08:34:00,33.262\n2014-04-07 08:39:00,33.474000000000004\n2014-04-07 08:44:00,36.338\n2014-04-07 08:49:00,31.174\n2014-04-07 08:54:00,38.78\n2014-04-07 08:59:00,34.34\n2014-04-07 09:04:00,36.501999999999995\n2014-04-07 09:09:00,36.268\n2014-04-07 09:14:00,34.788000000000004\n2014-04-07 09:19:00,36.742\n2014-04-07 09:24:00,32.646\n2014-04-07 09:29:00,36.292\n2014-04-07 09:34:00,34.508\n2014-04-07 09:39:00,34.062\n2014-04-07 09:44:00,35.282\n2014-04-07 09:49:00,34.68\n2014-04-07 09:54:00,39.104\n2014-04-07 09:59:00,34.154\n2014-04-07 10:04:00,36.292\n2014-04-07 10:09:00,37.88800000000001\n2014-04-07 10:14:00,33.796\n2014-04-07 10:19:00,36.338\n2014-04-07 10:24:00,34.32\n2014-04-07 10:29:00,35.658\n2014-04-07 10:34:00,34.694\n2014-04-07 10:39:00,36.162\n2014-04-07 10:44:00,34.508\n2014-04-07 10:49:00,31.456\n2014-04-07 10:54:00,35.3\n2014-04-07 10:59:00,33.45\n2014-04-07 11:04:00,33.28\n2014-04-07 11:09:00,35.328\n2014-04-07 11:14:00,37.275999999999996\n2014-04-07 11:19:00,34.672\n2014-04-07 11:24:00,31.76\n2014-04-07 11:29:00,33.356\n2014-04-07 11:34:00,33.686\n2014-04-07 11:39:00,33.972\n2014-04-07 11:44:00,33.874\n2014-04-07 11:49:00,36.326\n2014-04-07 11:54:00,32.324\n2014-04-07 11:59:00,34.078\n2014-04-07 12:04:00,33.428000000000004\n2014-04-07 12:09:00,35.046\n2014-04-07 12:14:00,33.358000000000004\n2014-04-07 12:19:00,35.14\n2014-04-07 12:24:00,33.708\n2014-04-07 12:29:00,33.944\n2014-04-07 12:34:00,33.92\n2014-04-07 12:39:00,33.38\n2014-04-07 12:44:00,37.652\n2014-04-07 12:49:00,29.378\n2014-04-07 12:54:00,35.33\n2014-04-07 12:59:00,34.906\n2014-04-07 13:04:00,32.356\n2014-04-07 13:09:00,34.988\n2014-04-07 13:14:00,35.328\n2014-04-07 13:19:00,31.392\n2014-04-07 13:24:00,34.455999999999996\n2014-04-07 13:29:00,38.208\n2014-04-07 13:34:00,35.61\n2014-04-07 13:49:00,28.225\n2014-04-07 13:54:00,35.78800000000001\n2014-04-07 13:59:00,33.498000000000005\n2014-04-07 14:04:00,34.32\n2014-04-07 14:09:00,38.262\n2014-04-07 14:14:00,33.004\n2014-04-07 14:19:00,30.872\n2014-04-07 14:24:00,34.014\n2014-04-07 14:29:00,34.906\n2014-04-07 14:34:00,35.164\n2014-04-07 14:39:00,36.111999999999995\n2014-04-07 14:44:00,32.958\n2014-04-07 14:49:00,32.3\n2014-04-07 14:54:00,35.422\n2014-04-07 14:59:00,33.732\n2014-04-07 15:04:00,33.494\n2014-04-07 15:09:00,39.814\n2014-04-07 15:14:00,30.118000000000002\n2014-04-07 15:19:00,34.296\n2014-04-07 15:24:00,34.414\n2014-04-07 15:29:00,35.47400000000001\n2014-04-07 15:34:00,35.14\n2014-04-07 15:39:00,37.324\n2014-04-07 15:44:00,32.934\n2014-04-07 15:49:00,34.586\n2014-04-07 15:54:00,36.578\n2014-04-07 15:59:00,37.632\n2014-04-07 16:04:00,31.59800000000001\n2014-04-07 16:09:00,38.63800000000001\n2014-04-07 16:14:00,34.014\n2014-04-07 16:19:00,34.062\n2014-04-07 16:24:00,33.896\n2014-04-07 16:29:00,35.774\n2014-04-07 16:34:00,32.51\n2014-04-07 16:39:00,38.756\n2014-04-07 16:44:00,29.43\n2014-04-07 16:49:00,33.978\n2014-04-07 16:54:00,35.796\n2014-04-07 16:59:00,35.282\n2014-04-07 17:04:00,34.6\n2014-04-07 17:09:00,32.922\n2014-04-07 17:14:00,33.616\n2014-04-07 17:19:00,33.38\n2014-04-07 17:24:00,34.32\n2014-04-07 17:29:00,32.63\n2014-04-07 17:34:00,37.501999999999995\n2014-04-07 17:39:00,31.15\n2014-04-07 17:44:00,33.826\n2014-04-07 17:49:00,33.568000000000005\n2014-04-07 17:54:00,35.054\n2014-04-07 17:59:00,32.228\n2014-04-07 18:04:00,34.9\n2014-04-07 18:09:00,33.662\n2014-04-07 18:14:00,33.24\n2014-04-07 18:19:00,30.605999999999998\n2014-04-07 18:24:00,32.135999999999996\n2014-04-07 18:29:00,32.254\n2014-04-07 18:34:00,34.202\n2014-04-07 18:39:00,30.278000000000002\n2014-04-07 18:44:00,32.558\n2014-04-07 18:49:00,32.184\n2014-04-07 18:54:00,34.32\n2014-04-07 18:59:00,38.324\n2014-04-07 19:04:00,29.624000000000002\n2014-04-07 19:09:00,34.038000000000004\n2014-04-07 19:14:00,34.251999999999995\n2014-04-07 19:19:00,30.406\n2014-04-07 19:24:00,32.066\n2014-04-07 19:29:00,31.971999999999998\n2014-04-07 19:34:00,32.778\n2014-04-07 19:39:00,36.01\n2014-04-07 19:44:00,29.248\n2014-04-07 19:49:00,33.896\n2014-04-07 19:54:00,32.37\n2014-04-07 19:59:00,32.16\n2014-04-07 20:04:00,32.7\n2014-04-07 20:09:00,36.738\n2014-04-07 20:14:00,33.356\n2014-04-07 20:19:00,32.17\n2014-04-07 20:24:00,33.008\n2014-04-07 20:29:00,34.144\n2014-04-07 20:34:00,34.21\n2014-04-07 20:39:00,28.261999999999997\n2014-04-07 20:44:00,32.234\n2014-04-07 20:49:00,32.418\n2014-04-07 20:54:00,33.944\n2014-04-07 20:59:00,34.118\n2014-04-07 21:04:00,30.756\n2014-04-07 21:09:00,35.024\n2014-04-07 21:14:00,30.846\n2014-04-07 21:19:00,34.578\n2014-04-07 21:24:00,29.414\n2014-04-07 21:29:00,33.99\n2014-04-07 21:34:00,30.336\n2014-04-07 21:39:00,32.676\n2014-04-07 21:44:00,33.708\n2014-04-07 21:49:00,31.01\n2014-04-07 21:54:00,33.826\n2014-04-07 21:59:00,34.436\n2014-04-07 22:04:00,32.512\n2014-04-07 22:09:00,32.135999999999996\n2014-04-07 22:14:00,34.812\n2014-04-07 22:19:00,33.544000000000004\n2014-04-07 22:24:00,36.22\n2014-04-07 22:29:00,32.848\n2014-04-07 22:34:00,33.146\n2014-04-07 22:39:00,32.275999999999996\n2014-04-07 22:44:00,32.205999999999996\n2014-04-07 22:49:00,32.536\n2014-04-07 22:54:00,34.508\n2014-04-07 22:59:00,36.361999999999995\n2014-04-07 23:04:00,29.201999999999998\n2014-04-07 23:09:00,34.578\n2014-04-07 23:14:00,34.93\n2014-04-07 23:19:00,33.662\n2014-04-07 23:24:00,33.592\n2014-04-07 23:29:00,34.226\n2014-04-07 23:34:00,30.81\n2014-04-07 23:39:00,36.99800000000001\n2014-04-07 23:44:00,28.464000000000002\n2014-04-07 23:49:00,33.082\n2014-04-07 23:54:00,36.104\n2014-04-07 23:59:00,31.314\n2014-04-08 00:04:00,32.906\n2014-04-08 00:09:00,33.99\n2014-04-08 00:14:00,35.492\n2014-04-08 00:19:00,33.968\n2014-04-08 00:24:00,34.326\n2014-04-08 00:29:00,29.32800000000001\n2014-04-08 00:34:00,32.676\n2014-04-08 00:39:00,32.816\n2014-04-08 00:44:00,32.982\n2014-04-08 00:49:00,32.77\n2014-04-08 00:54:00,36.198\n2014-04-08 00:59:00,31.901999999999997\n2014-04-08 01:04:00,31.15\n2014-04-08 01:09:00,34.525999999999996\n2014-04-08 01:14:00,36.314\n2014-04-08 01:19:00,34.578\n2014-04-08 01:24:00,34.226\n2014-04-08 01:29:00,33.384\n2014-04-08 01:34:00,32.838\n2014-04-08 01:39:00,33.896\n2014-04-08 01:44:00,31.596\n2014-04-08 01:49:00,32.512\n2014-04-08 01:54:00,38.514\n2014-04-08 01:59:00,33.036\n2014-04-08 02:04:00,30.491999999999997\n2014-04-08 02:09:00,37.77\n2014-04-08 02:14:00,31.15\n2014-04-08 02:19:00,32.275999999999996\n2014-04-08 02:24:00,34.132\n2014-04-08 02:29:00,33.028\n2014-04-08 02:34:00,32.23\n2014-04-08 02:39:00,32.272\n2014-04-08 02:44:00,35.75199999999999\n2014-04-08 02:49:00,28.57800000000001\n2014-04-08 02:54:00,36.08\n2014-04-08 02:59:00,30.564\n2014-04-08 03:04:00,32.275999999999996\n2014-04-08 03:09:00,33.568000000000005\n2014-04-08 03:14:00,32.122\n2014-04-08 03:19:00,33.24\n2014-04-08 03:24:00,32.348\n2014-04-08 03:29:00,37.864000000000004\n2014-04-08 03:34:00,28.215999999999998\n2014-04-08 03:39:00,32.482\n2014-04-08 03:44:00,32.808\n2014-04-08 03:49:00,31.968000000000004\n2014-04-08 03:54:00,33.874\n2014-04-08 03:59:00,34.648\n2014-04-08 04:04:00,33.616\n2014-04-08 04:09:00,32.966\n2014-04-08 04:14:00,33.758\n2014-04-08 04:19:00,34.108000000000004\n2014-04-08 04:24:00,32.111999999999995\n2014-04-08 04:29:00,34.554\n2014-04-08 04:34:00,30.42\n2014-04-08 04:39:00,32.3\n2014-04-08 04:44:00,33.896\n2014-04-08 04:49:00,31.174\n2014-04-08 04:54:00,36.178000000000004\n2014-04-08 04:59:00,33.146\n2014-04-08 05:04:00,34.954\n2014-04-08 05:09:00,31.198\n2014-04-08 05:14:00,32.244\n2014-04-08 05:19:00,36.762\n2014-04-08 05:24:00,33.146\n2014-04-08 05:29:00,30.491999999999997\n2014-04-08 05:34:00,32.888000000000005\n2014-04-08 05:39:00,32.888000000000005\n2014-04-08 05:44:00,32.84\n2014-04-08 05:49:00,35.094\n2014-04-08 05:54:00,33.45\n2014-04-08 05:59:00,31.714000000000002\n2014-04-08 06:04:00,31.494\n2014-04-08 06:09:00,33.92\n2014-04-08 06:14:00,32.324\n2014-04-08 06:19:00,33.906\n2014-04-08 06:24:00,31.691999999999997\n2014-04-08 06:29:00,33.955999999999996\n2014-04-08 06:34:00,35.054\n2014-04-08 06:39:00,30.866\n2014-04-08 06:44:00,31.362\n2014-04-08 06:49:00,33.99\n2014-04-08 06:54:00,31.83\n2014-04-08 06:59:00,32.348\n2014-04-08 07:04:00,32.394\n2014-04-08 07:09:00,33.896\n2014-04-08 07:14:00,33.662\n2014-04-08 07:19:00,35.422\n2014-04-08 07:24:00,27.712\n2014-04-08 07:29:00,32.52\n2014-04-08 07:34:00,33.926\n2014-04-08 07:39:00,34.32\n2014-04-08 07:44:00,34.46\n2014-04-08 07:49:00,31.362\n2014-04-08 07:54:00,32.396\n2014-04-08 07:59:00,32.51\n2014-04-08 08:04:00,32.558\n2014-04-08 08:09:00,33.592\n2014-04-08 08:14:00,34.318000000000005\n2014-04-08 08:19:00,30.281999999999996\n2014-04-08 08:24:00,32.09\n2014-04-08 08:29:00,33.16\n2014-04-08 08:34:00,31.154\n2014-04-08 08:39:00,34.038000000000004\n2014-04-08 08:44:00,30.25800000000001\n2014-04-08 08:49:00,31.984\n2014-04-08 08:54:00,36.704\n2014-04-08 08:59:00,30.752\n2014-04-08 09:04:00,31.031999999999996\n2014-04-08 09:09:00,37.018\n2014-04-08 09:14:00,33.99\n2014-04-08 09:19:00,34.39\n2014-04-08 09:24:00,34.436\n2014-04-08 09:29:00,34.628\n2014-04-08 09:34:00,38.076\n2014-04-08 09:39:00,32.476\n2014-04-08 09:44:00,34.52\n2014-04-08 09:49:00,34.672\n2014-04-08 09:54:00,36.784\n2014-04-08 09:59:00,34.272\n2014-04-08 10:04:00,36.455999999999996\n2014-04-08 10:09:00,38.304\n2014-04-08 10:14:00,32.418\n2014-04-08 10:19:00,33.638000000000005\n2014-04-08 10:24:00,34.138000000000005\n2014-04-08 10:29:00,33.662\n2014-04-08 10:34:00,39.296\n2014-04-08 10:39:00,32.394\n2014-04-08 10:44:00,36.052\n2014-04-08 10:49:00,33.38\n2014-04-08 10:54:00,35.774\n2014-04-08 10:59:00,36.59\n2014-04-08 11:04:00,32.512\n2014-04-08 11:09:00,37.004\n2014-04-08 11:14:00,34.302\n2014-04-08 11:19:00,34.954\n2014-04-08 11:24:00,35.024\n2014-04-08 11:29:00,33.732\n2014-04-08 11:34:00,34.53\n2014-04-08 11:39:00,30.962\n2014-04-08 11:44:00,33.85\n2014-04-08 11:49:00,31.104\n2014-04-08 11:54:00,36.431999999999995\n2014-04-08 11:59:00,29.904\n2014-04-08 12:04:00,34.666\n2014-04-08 12:09:00,32.032\n2014-04-08 12:14:00,32.418\n2014-04-08 12:19:00,35.908\n2014-04-08 12:24:00,31.00800000000001\n2014-04-08 12:29:00,32.394\n2014-04-08 12:34:00,34.014\n2014-04-08 12:39:00,32.746\n2014-04-08 12:44:00,29.75800000000001\n2014-04-08 12:49:00,32.036\n2014-04-08 12:54:00,33.944\n2014-04-08 12:59:00,33.24\n2014-04-08 13:04:00,33.004\n2014-04-08 13:09:00,31.644000000000002\n2014-04-08 13:14:00,32.524\n2014-04-08 13:19:00,32.122\n2014-04-08 13:24:00,33.638000000000005\n2014-04-08 13:29:00,38.544000000000004\n2014-04-08 13:34:00,29.484\n2014-04-08 13:39:00,32.724000000000004\n2014-04-08 13:44:00,34.266\n2014-04-08 13:49:00,32.102\n2014-04-08 13:54:00,34.154\n2014-04-08 13:59:00,32.418\n2014-04-08 14:04:00,34.788000000000004\n2014-04-08 14:09:00,33.334\n2014-04-08 14:14:00,31.291999999999998\n2014-04-08 14:19:00,36.864000000000004\n2014-04-08 14:24:00,33.16\n2014-04-08 14:29:00,32.248000000000005\n2014-04-08 14:34:00,34.178000000000004\n2014-04-08 14:39:00,32.794000000000004\n2014-04-08 14:44:00,33.732\n2014-04-08 14:49:00,31.234\n2014-04-08 14:54:00,34.374\n2014-04-08 14:59:00,32.318000000000005\n2014-04-08 15:04:00,34.39\n2014-04-08 15:09:00,37.3\n2014-04-08 15:14:00,29.691999999999997\n2014-04-08 15:19:00,32.135999999999996\n2014-04-08 15:24:00,36.032\n2014-04-08 15:29:00,30.892\n2014-04-08 15:34:00,34.508\n2014-04-08 15:39:00,30.798000000000002\n2014-04-08 15:44:00,32.606\n2014-04-08 15:49:00,32.37\n2014-04-08 15:54:00,36.972\n2014-04-08 15:59:00,32.135999999999996\n2014-04-08 16:04:00,36.431999999999995\n2014-04-08 16:09:00,34.554\n2014-04-08 16:14:00,31.572\n2014-04-08 16:19:00,33.85\n2014-04-08 16:24:00,32.042\n2014-04-08 16:29:00,31.878\n2014-04-08 16:34:00,32.205999999999996\n2014-04-08 16:39:00,34.812\n2014-04-08 16:44:00,34.53\n2014-04-08 16:49:00,33.248000000000005\n2014-04-08 16:54:00,32.275999999999996\n2014-04-08 16:59:00,32.348\n2014-04-08 17:04:00,32.342\n2014-04-08 17:09:00,33.896\n2014-04-08 17:14:00,32.63\n2014-04-08 17:19:00,32.418\n2014-04-08 17:24:00,36.738\n2014-04-08 17:29:00,34.474000000000004\n2014-04-08 17:34:00,31.72\n2014-04-08 17:39:00,32.958\n2014-04-08 17:44:00,32.652\n2014-04-08 17:49:00,32.3\n2014-04-08 17:54:00,35.898\n2014-04-08 17:59:00,32.21\n2014-04-08 18:04:00,32.562\n2014-04-08 18:09:00,35.455999999999996\n2014-04-08 18:14:00,33.99\n2014-04-08 18:19:00,39.484\n2014-04-08 18:24:00,28.592\n2014-04-08 18:29:00,36.292\n2014-04-08 18:34:00,35.496\n2014-04-08 18:39:00,31.031999999999996\n2014-04-08 18:44:00,34.598\n2014-04-08 18:49:00,30.305999999999997\n2014-04-08 18:54:00,33.83\n2014-04-08 18:59:00,34.754\n2014-04-08 19:04:00,29.851999999999997\n2014-04-08 19:09:00,37.018\n2014-04-08 19:14:00,28.99\n2014-04-08 19:19:00,32.032\n2014-04-08 19:24:00,32.692\n2014-04-08 19:29:00,32.23\n2014-04-08 19:34:00,32.824\n2014-04-08 19:39:00,37.95\n2014-04-08 19:44:00,29.178\n2014-04-08 19:49:00,31.104\n2014-04-08 19:54:00,33.708\n2014-04-08 19:59:00,32.23\n2014-04-08 20:04:00,34.798\n2014-04-08 20:09:00,32.382\n2014-04-08 20:14:00,33.912\n2014-04-08 20:19:00,33.714\n2014-04-08 20:24:00,29.53\n2014-04-08 20:29:00,32.278\n2014-04-08 20:34:00,34.63\n2014-04-08 20:39:00,30.046\n2014-04-08 20:44:00,33.568000000000005\n2014-04-08 20:49:00,32.066\n2014-04-08 20:54:00,35.728\n2014-04-08 20:59:00,32.536\n2014-04-08 21:04:00,35.14\n2014-04-08 21:09:00,35.044000000000004\n2014-04-08 21:14:00,31.378\n2014-04-08 21:19:00,35.07\n2014-04-08 21:24:00,34.014\n2014-04-08 21:29:00,38.885999999999996\n2014-04-08 21:34:00,34.046\n2014-04-08 21:39:00,34.635999999999996\n2014-04-08 21:44:00,34.668\n2014-04-08 21:49:00,35.4\n2014-04-08 21:54:00,36.784\n2014-04-08 21:59:00,32.788000000000004\n2014-04-08 22:04:00,34.216\n2014-04-08 22:09:00,36.071999999999996\n2014-04-08 22:14:00,34.054\n2014-04-08 22:19:00,36.628\n2014-04-08 22:24:00,37.51\n2014-04-08 22:29:00,30.752\n2014-04-08 22:34:00,33.638000000000005\n2014-04-08 22:39:00,33.356\n2014-04-08 22:44:00,33.474000000000004\n2014-04-08 22:49:00,33.474000000000004\n2014-04-08 22:54:00,38.656\n2014-04-08 22:59:00,32.644\n2014-04-08 23:04:00,32.91\n2014-04-08 23:09:00,35.838\n2014-04-08 23:14:00,34.288000000000004\n2014-04-08 23:19:00,35.68\n2014-04-08 23:24:00,37.794000000000004\n2014-04-08 23:29:00,32.614000000000004\n2014-04-08 23:34:00,34.718\n2014-04-08 23:39:00,34.718\n2014-04-08 23:44:00,35.868\n2014-04-08 23:49:00,32.724000000000004\n2014-04-08 23:54:00,38.11\n2014-04-08 23:59:00,32.512\n2014-04-09 00:04:00,34.272\n2014-04-09 00:09:00,35.65\n2014-04-09 00:14:00,34.148\n2014-04-09 00:19:00,35.246\n2014-04-09 00:24:00,33.036\n2014-04-09 00:29:00,36.32\n2014-04-09 00:34:00,34.742\n2014-04-09 00:39:00,35.282\n2014-04-09 00:44:00,32.178000000000004\n2014-04-09 00:49:00,33.826\n2014-04-09 00:54:00,35.916\n2014-04-09 00:59:00,36.361999999999995\n2014-04-09 01:04:00,36.174\n2014-04-09 01:09:00,33.568000000000005\n2014-04-09 01:14:00,33.94\n2014-04-09 01:19:00,33.756\n2014-04-09 01:24:00,34.014\n2014-04-09 01:29:00,34.3\n2014-04-09 01:34:00,35.894\n2014-04-09 01:39:00,39.374\n2014-04-09 01:44:00,31.27\n2014-04-09 01:49:00,34.202\n2014-04-09 01:54:00,35.938\n2014-04-09 01:59:00,34.196\n2014-04-09 02:04:00,36.431999999999995\n2014-04-09 02:09:00,34.976\n2014-04-09 02:14:00,35.72\n2014-04-09 02:19:00,38.262\n2014-04-09 02:24:00,30.854\n2014-04-09 02:29:00,33.508\n2014-04-09 02:34:00,33.576\n2014-04-09 02:39:00,36.134\n2014-04-09 02:44:00,31.842\n2014-04-09 02:49:00,33.57\n2014-04-09 02:54:00,35.076\n2014-04-09 02:59:00,33.61\n2014-04-09 03:04:00,33.874\n2014-04-09 03:09:00,36.52\n2014-04-09 03:14:00,32.724000000000004\n2014-04-09 03:19:00,40.868\n2014-04-09 03:24:00,33.028\n2014-04-09 03:29:00,32.205999999999996\n2014-04-09 03:34:00,34.836\n2014-04-09 03:39:00,34.584\n2014-04-09 03:44:00,34.848\n2014-04-09 03:49:00,35.36400000000001\n2014-04-09 03:54:00,35.0\n2014-04-09 03:59:00,35.616\n2014-04-09 04:04:00,32.09\n2014-04-09 04:09:00,36.01\n2014-04-09 04:14:00,37.264\n2014-04-09 04:19:00,34.396\n2014-04-09 04:24:00,35.774\n2014-04-09 04:29:00,36.666\n2014-04-09 04:34:00,32.135999999999996\n2014-04-09 04:39:00,34.524\n2014-04-09 04:44:00,32.001999999999995\n2014-04-09 04:49:00,33.906\n2014-04-09 04:54:00,35.634\n2014-04-09 04:59:00,35.32\n2014-04-09 05:04:00,36.668\n2014-04-09 05:09:00,35.656\n2014-04-09 05:14:00,34.044000000000004\n2014-04-09 05:19:00,35.798\n2014-04-09 05:24:00,31.901999999999997\n2014-04-09 05:29:00,35.188\n2014-04-09 05:34:00,33.24\n2014-04-09 05:39:00,33.944\n2014-04-09 05:44:00,36.208\n2014-04-09 05:49:00,34.32\n2014-04-09 05:54:00,34.042\n2014-04-09 05:59:00,33.802\n2014-04-09 06:04:00,34.446\n2014-04-09 06:09:00,37.13800000000001\n2014-04-09 06:14:00,33.186\n2014-04-09 06:19:00,34.976\n2014-04-09 06:24:00,37.354\n2014-04-09 06:29:00,33.78\n2014-04-09 06:34:00,36.15\n2014-04-09 06:39:00,33.732\n2014-04-09 06:44:00,32.246\n2014-04-09 06:49:00,33.874\n2014-04-09 06:54:00,35.704\n2014-04-09 06:59:00,35.282\n2014-04-09 07:04:00,35.61\n2014-04-09 07:09:00,35.846\n2014-04-09 07:14:00,34.226\n2014-04-09 07:19:00,35.438\n2014-04-09 07:24:00,35.186\n2014-04-09 07:29:00,32.0\n2014-04-09 07:34:00,34.17\n2014-04-09 07:39:00,34.544000000000004\n2014-04-09 07:44:00,34.29\n2014-04-09 07:49:00,36.738\n2014-04-09 07:54:00,34.504\n2014-04-09 07:59:00,34.882\n2014-04-09 08:04:00,32.582\n2014-04-09 08:09:00,35.81800000000001\n2014-04-09 08:14:00,34.364000000000004\n2014-04-09 08:19:00,34.178000000000004\n2014-04-09 08:24:00,35.564\n2014-04-09 08:29:00,35.564\n2014-04-09 08:34:00,34.062\n2014-04-09 08:39:00,35.99800000000001\n2014-04-09 08:44:00,33.498000000000005\n2014-04-09 08:49:00,33.24\n2014-04-09 08:54:00,36.902\n2014-04-09 08:59:00,33.45\n2014-04-09 09:04:00,34.39\n2014-04-09 09:09:00,36.062\n2014-04-09 09:14:00,35.705999999999996\n2014-04-09 09:19:00,38.85\n2014-04-09 09:24:00,32.184\n2014-04-09 09:29:00,34.296\n2014-04-09 09:34:00,36.048\n2014-04-09 09:39:00,33.624\n2014-04-09 09:44:00,34.702\n2014-04-09 09:49:00,37.596\n2014-04-09 09:54:00,33.098\n2014-04-09 09:59:00,34.624\n2014-04-09 10:04:00,36.048\n2014-04-09 10:09:00,38.968\n2014-04-09 10:14:00,33.216\n2014-04-09 10:19:00,36.478\n2014-04-09 10:24:00,32.071999999999996\n2014-04-09 10:29:00,34.36\n2014-04-09 10:34:00,33.96\n2014-04-09 10:39:00,34.09\n2014-04-09 10:44:00,36.668\n2014-04-09 10:49:00,32.222\n2014-04-09 10:54:00,39.536\n2014-04-09 10:59:00,31.022\n2014-04-09 11:04:00,34.251999999999995\n2014-04-09 11:09:00,38.92\n2014-04-09 11:14:00,34.558\n2014-04-09 11:19:00,33.796\n2014-04-09 11:24:00,38.944\n2014-04-09 11:29:00,29.57800000000001\n2014-04-09 11:34:00,36.174\n2014-04-09 11:39:00,33.45\n2014-04-09 11:44:00,35.211999999999996\n2014-04-09 11:49:00,34.648\n2014-04-09 11:54:00,38.194\n2014-04-09 11:59:00,32.111999999999995\n2014-04-09 12:04:00,34.742\n2014-04-09 12:09:00,38.38\n2014-04-09 12:14:00,32.348\n2014-04-09 12:19:00,38.262\n2014-04-09 12:24:00,32.816\n2014-04-09 12:29:00,36.431999999999995\n2014-04-09 12:34:00,32.066\n2014-04-09 12:39:00,34.138000000000005\n2014-04-09 12:44:00,34.46\n2014-04-09 12:49:00,34.53\n2014-04-09 12:54:00,35.394\n2014-04-09 12:59:00,38.99\n2014-04-09 13:04:00,27.041999999999998\n2014-04-09 13:09:00,34.882\n2014-04-09 13:14:00,33.052\n2014-04-09 13:19:00,37.37\n2014-04-09 13:24:00,35.08\n2014-04-09 13:29:00,34.698\n2014-04-09 13:34:00,32.821999999999996\n2014-04-09 13:39:00,32.135999999999996\n2014-04-09 13:44:00,35.85800000000001\n2014-04-09 13:49:00,30.204\n2014-04-09 13:54:00,35.042\n2014-04-09 13:59:00,32.71\n2014-04-09 14:04:00,35.178000000000004\n2014-04-09 14:09:00,32.816\n2014-04-09 14:14:00,34.272\n2014-04-09 14:19:00,31.526\n2014-04-09 14:24:00,35.846\n2014-04-09 14:29:00,33.31\n2014-04-09 14:34:00,36.832\n2014-04-09 14:39:00,29.718000000000004\n2014-04-09 14:44:00,34.508\n2014-04-09 14:49:00,35.47\n2014-04-09 14:54:00,37.722\n2014-04-09 14:59:00,34.36\n2014-04-09 15:04:00,35.916\n2014-04-09 15:09:00,34.108000000000004\n2014-04-09 15:14:00,34.372\n2014-04-09 15:19:00,37.14\n2014-04-09 15:24:00,36.714\n2014-04-09 15:29:00,32.786\n2014-04-09 15:34:00,35.694\n2014-04-09 15:39:00,32.254\n2014-04-09 15:44:00,34.436\n2014-04-09 15:49:00,34.108000000000004\n2014-04-09 15:54:00,35.938\n2014-04-09 15:59:00,36.501999999999995\n2014-04-09 16:04:00,36.114000000000004\n2014-04-09 16:09:00,37.738\n2014-04-09 16:14:00,34.742\n2014-04-09 16:19:00,31.66800000000001\n2014-04-09 16:24:00,35.242\n2014-04-09 16:29:00,34.054\n2014-04-09 16:34:00,35.64\n2014-04-09 16:39:00,34.658\n2014-04-09 16:44:00,34.194\n2014-04-09 16:49:00,35.188\n2014-04-09 16:54:00,35.846\n2014-04-09 16:59:00,35.54\n2014-04-09 17:04:00,38.152\n2014-04-09 17:09:00,32.91\n2014-04-09 17:14:00,34.668\n2014-04-09 17:19:00,36.15\n2014-04-09 17:24:00,35.798\n2014-04-09 17:29:00,38.708\n2014-04-09 17:34:00,33.836\n2014-04-09 17:39:00,37.444\n2014-04-09 17:44:00,33.122\n2014-04-09 17:49:00,34.508\n2014-04-09 17:54:00,39.178000000000004\n2014-04-09 17:59:00,32.126\n2014-04-09 18:04:00,34.664\n2014-04-09 18:09:00,39.508\n2014-04-09 18:14:00,31.478\n2014-04-09 18:19:00,36.09\n2014-04-09 18:24:00,36.232\n2014-04-09 18:29:00,34.6\n2014-04-09 18:34:00,37.135999999999996\n2014-04-09 18:39:00,34.264\n2014-04-09 18:44:00,33.802\n2014-04-09 18:49:00,33.186\n2014-04-09 18:54:00,37.356\n2014-04-09 18:59:00,35.37\n2014-04-09 19:04:00,33.826\n2014-04-09 19:09:00,35.704\n2014-04-09 19:14:00,36.032\n2014-04-09 19:19:00,32.111999999999995\n2014-04-09 19:24:00,38.192\n2014-04-09 19:29:00,32.464\n2014-04-09 19:34:00,34.178000000000004\n2014-04-09 19:39:00,34.414\n2014-04-09 19:44:00,36.272\n2014-04-09 19:49:00,32.361999999999995\n2014-04-09 19:54:00,35.588\n2014-04-09 19:59:00,35.492\n2014-04-09 20:04:00,32.652\n2014-04-09 20:09:00,37.762\n2014-04-09 20:14:00,31.052\n2014-04-09 20:19:00,35.891999999999996\n2014-04-09 20:24:00,31.69\n2014-04-09 20:29:00,33.602\n2014-04-09 20:34:00,37.49\n2014-04-09 20:39:00,33.616\n2014-04-09 20:44:00,33.674\n2014-04-09 20:49:00,33.806\n2014-04-09 20:54:00,38.92\n2014-04-09 20:59:00,32.018\n2014-04-09 21:04:00,34.836\n2014-04-09 21:09:00,35.14\n2014-04-09 21:14:00,34.38\n2014-04-09 21:19:00,35.54\n2014-04-09 21:24:00,31.362\n2014-04-09 21:29:00,35.328\n2014-04-09 21:34:00,33.052\n2014-04-09 21:39:00,35.34\n2014-04-09 21:44:00,32.95\n2014-04-09 21:49:00,35.961999999999996\n2014-04-09 21:54:00,34.172\n2014-04-09 21:59:00,34.826\n2014-04-09 22:04:00,35.4\n2014-04-09 22:09:00,34.608000000000004\n2014-04-09 22:14:00,35.16\n2014-04-09 22:19:00,37.348\n2014-04-09 22:24:00,34.436\n2014-04-09 22:29:00,31.268\n2014-04-09 22:34:00,34.036\n2014-04-09 22:39:00,34.826\n2014-04-09 22:44:00,33.708\n2014-04-09 22:49:00,35.046\n2014-04-09 22:54:00,37.794000000000004\n2014-04-09 22:59:00,31.644000000000002\n2014-04-09 23:04:00,34.236\n2014-04-09 23:09:00,39.624\n2014-04-09 23:14:00,34.178000000000004\n2014-04-09 23:19:00,36.8\n2014-04-09 23:24:00,34.976\n2014-04-09 23:29:00,32.184\n2014-04-09 23:34:00,34.226\n2014-04-09 23:39:00,34.014\n2014-04-09 23:44:00,33.99\n2014-04-09 23:49:00,33.896\n2014-04-09 23:54:00,37.512\n2014-04-09 23:59:00,35.54\n2014-04-10 00:04:00,29.976\n2014-04-10 00:09:00,35.47\n2014-04-10 00:14:00,37.864000000000004\n2014-04-10 00:19:00,37.284\n2014-04-10 00:24:00,31.901999999999997\n2014-04-10 00:29:00,35.478\n2014-04-10 00:34:00,35.934\n2014-04-10 00:39:00,36.032\n2014-04-10 00:44:00,33.334\n2014-04-10 00:49:00,38.732\n2014-04-10 00:54:00,31.644000000000002\n2014-04-10 00:59:00,34.6\n2014-04-10 01:04:00,36.854\n2014-04-10 01:09:00,35.821999999999996\n2014-04-10 01:14:00,34.226\n2014-04-10 01:19:00,39.906\n2014-04-10 01:24:00,30.83\n2014-04-10 01:29:00,34.418\n2014-04-10 01:34:00,37.135999999999996\n2014-04-10 01:39:00,32.134\n2014-04-10 01:44:00,34.836\n2014-04-10 01:49:00,36.455999999999996\n2014-04-10 01:54:00,37.746\n2014-04-10 01:59:00,31.421999999999997\n2014-04-10 02:04:00,34.32\n2014-04-10 02:09:00,35.891999999999996\n2014-04-10 02:14:00,34.11\n2014-04-10 02:19:00,40.728\n2014-04-10 02:24:00,32.652\n2014-04-10 02:29:00,35.564\n2014-04-10 02:34:00,33.968\n2014-04-10 02:39:00,33.802\n2014-04-10 02:44:00,36.374\n2014-04-10 02:49:00,36.154\n2014-04-10 02:54:00,33.73\n2014-04-10 02:59:00,33.474000000000004\n2014-04-10 03:04:00,36.08\n2014-04-10 03:09:00,35.628\n2014-04-10 03:14:00,35.61\n2014-04-10 03:19:00,35.516\n2014-04-10 03:24:00,35.094\n2014-04-10 03:29:00,34.622\n2014-04-10 03:34:00,34.512\n2014-04-10 03:39:00,34.79\n2014-04-10 03:44:00,36.644\n2014-04-10 03:49:00,34.484\n2014-04-10 03:54:00,32.91\n2014-04-10 03:59:00,35.61\n2014-04-10 04:04:00,33.404\n2014-04-10 04:09:00,35.374\n2014-04-10 04:14:00,35.458\n2014-04-10 04:19:00,31.784000000000002\n2014-04-10 04:24:00,33.532\n2014-04-10 04:29:00,35.066\n2014-04-10 04:34:00,38.49800000000001\n2014-04-10 04:39:00,31.44\n2014-04-10 04:44:00,35.28800000000001\n2014-04-10 04:49:00,32.324\n2014-04-10 04:54:00,35.455999999999996\n2014-04-10 04:59:00,37.141999999999996\n2014-04-10 05:04:00,34.794000000000004\n2014-04-10 05:09:00,36.76\n2014-04-10 05:14:00,34.178000000000004\n2014-04-10 05:19:00,33.436\n2014-04-10 05:24:00,36.114000000000004\n2014-04-10 05:29:00,34.302\n2014-04-10 05:34:00,38.968\n2014-04-10 05:39:00,33.098\n2014-04-10 05:44:00,34.226\n2014-04-10 05:49:00,33.812\n2014-04-10 05:54:00,35.7\n2014-04-10 05:59:00,34.058\n2014-04-10 06:04:00,35.586\n2014-04-10 06:09:00,36.338\n2014-04-10 06:14:00,33.192\n2014-04-10 06:19:00,35.14\n2014-04-10 06:24:00,36.666\n2014-04-10 06:29:00,33.31\n2014-04-10 06:34:00,35.164\n2014-04-10 06:39:00,34.624\n2014-04-10 06:44:00,32.12\n2014-04-10 06:49:00,33.638000000000005\n2014-04-10 06:54:00,35.4\n2014-04-10 06:59:00,33.232\n2014-04-10 07:04:00,33.766\n2014-04-10 07:09:00,40.188\n2014-04-10 07:14:00,29.201999999999998\n2014-04-10 07:19:00,33.328\n2014-04-10 07:24:00,33.122\n2014-04-10 07:29:00,37.864000000000004\n2014-04-10 07:34:00,37.77\n2014-04-10 07:39:00,33.275999999999996\n2014-04-10 07:44:00,32.77\n2014-04-10 07:49:00,33.78\n2014-04-10 07:54:00,38.0\n2014-04-10 07:59:00,31.596\n2014-04-10 08:04:00,33.78\n2014-04-10 08:09:00,36.698\n2014-04-10 08:14:00,32.85\n2014-04-10 08:19:00,39.135999999999996\n2014-04-10 08:24:00,34.202\n2014-04-10 08:29:00,34.014\n2014-04-10 08:34:00,33.332\n2014-04-10 08:39:00,33.436\n2014-04-10 08:44:00,35.434\n2014-04-10 08:49:00,31.941999999999997\n2014-04-10 08:54:00,37.936\n2014-04-10 08:59:00,33.99\n2014-04-10 09:04:00,36.83\n2014-04-10 09:09:00,34.422\n2014-04-10 09:14:00,33.812\n2014-04-10 09:19:00,35.328\n2014-04-10 09:24:00,31.996\n2014-04-10 09:29:00,33.802\n2014-04-10 09:34:00,34.394\n2014-04-10 09:39:00,34.586\n2014-04-10 09:44:00,34.402\n2014-04-10 09:49:00,37.3\n2014-04-10 09:54:00,34.474000000000004\n2014-04-10 09:59:00,33.098\n2014-04-10 10:04:00,35.47\n2014-04-10 10:09:00,39.342\n2014-04-10 10:14:00,34.86\n2014-04-10 10:19:00,34.546\n2014-04-10 10:24:00,33.321999999999996\n2014-04-10 10:29:00,33.05\n2014-04-10 10:34:00,32.09\n2014-04-10 10:39:00,33.344\n2014-04-10 10:44:00,34.088\n2014-04-10 10:49:00,34.062\n2014-04-10 10:54:00,38.216\n2014-04-10 10:59:00,30.54\n2014-04-10 11:04:00,33.356\n2014-04-10 11:09:00,39.154\n2014-04-10 11:14:00,33.356\n2014-04-10 11:19:00,34.158\n2014-04-10 11:24:00,34.604\n2014-04-10 11:29:00,33.064\n2014-04-10 11:34:00,33.135999999999996\n2014-04-10 11:39:00,34.226\n2014-04-10 11:44:00,34.718\n2014-04-10 11:49:00,28.572\n2014-04-10 11:54:00,37.464\n2014-04-10 11:59:00,31.822\n2014-04-10 12:04:00,34.24\n2014-04-10 12:09:00,37.718\n2014-04-10 12:14:00,34.6\n2014-04-10 12:19:00,33.616\n2014-04-10 12:24:00,33.544000000000004\n2014-04-10 12:29:00,35.424\n2014-04-10 12:34:00,32.032\n2014-04-10 12:39:00,33.756\n2014-04-10 12:44:00,33.31\n2014-04-10 12:49:00,33.492\n2014-04-10 12:54:00,36.361999999999995\n2014-04-10 12:59:00,32.205999999999996\n2014-04-10 13:04:00,36.62\n2014-04-10 13:09:00,32.132\n2014-04-10 13:14:00,34.226\n2014-04-10 13:19:00,33.968\n2014-04-10 13:24:00,36.62\n2014-04-10 13:29:00,36.564\n2014-04-10 13:34:00,35.022\n2014-04-10 13:39:00,32.248000000000005\n2014-04-10 13:44:00,34.148\n2014-04-10 13:49:00,33.17\n2014-04-10 13:54:00,35.986\n2014-04-10 13:59:00,33.38\n2014-04-10 14:04:00,35.144\n2014-04-10 14:09:00,36.714\n2014-04-10 14:14:00,31.784000000000002\n2014-04-10 14:19:00,33.686\n2014-04-10 14:24:00,33.122\n2014-04-10 14:29:00,34.578\n2014-04-10 14:34:00,34.894\n2014-04-10 14:39:00,36.218\n2014-04-10 14:44:00,36.77\n2014-04-10 14:49:00,31.22\n2014-04-10 14:54:00,35.086\n2014-04-10 14:59:00,35.576\n2014-04-10 15:04:00,33.666\n2014-04-10 15:09:00,37.88800000000001\n2014-04-10 15:14:00,36.398\n2014-04-10 15:19:00,33.0\n2014-04-10 15:24:00,32.698\n2014-04-10 15:29:00,33.662\n2014-04-10 15:34:00,34.108000000000004\n2014-04-10 15:39:00,37.522\n2014-04-10 15:44:00,33.802\n2014-04-10 15:49:00,32.018\n2014-04-10 15:54:00,36.056\n2014-04-10 15:59:00,33.286\n2014-04-10 16:04:00,36.04\n2014-04-10 16:09:00,38.342\n2014-04-10 16:14:00,36.571999999999996\n2014-04-10 16:19:00,32.518\n2014-04-10 16:24:00,34.32\n2014-04-10 16:29:00,36.808\n2014-04-10 16:34:00,31.808000000000003\n2014-04-10 16:39:00,37.16\n2014-04-10 16:44:00,37.135999999999996\n2014-04-10 16:49:00,33.99\n2014-04-10 16:54:00,38.052\n2014-04-10 16:59:00,34.46\n2014-04-10 17:04:00,34.53\n2014-04-10 17:09:00,35.961999999999996\n2014-04-10 17:14:00,41.01\n2014-04-10 17:19:00,28.794\n2014-04-10 17:24:00,34.624\n2014-04-10 17:29:00,35.622\n2014-04-10 17:34:00,37.824\n2014-04-10 17:39:00,37.42\n2014-04-10 17:44:00,34.226\n2014-04-10 17:49:00,36.571999999999996\n2014-04-10 17:54:00,38.92\n2014-04-10 17:59:00,32.076\n2014-04-10 18:04:00,36.902\n2014-04-10 18:09:00,34.202\n2014-04-10 18:14:00,34.681999999999995\n2014-04-10 18:19:00,36.036\n2014-04-10 18:24:00,33.192\n2014-04-10 18:29:00,34.976\n2014-04-10 18:34:00,35.798\n2014-04-10 18:39:00,37.214\n2014-04-10 18:44:00,38.512\n2014-04-10 18:49:00,32.614000000000004\n2014-04-10 18:54:00,39.63800000000001\n2014-04-10 18:59:00,34.122\n2014-04-10 19:04:00,33.452\n2014-04-10 19:09:00,36.571999999999996\n2014-04-10 19:14:00,39.32\n2014-04-10 19:19:00,32.046\n2014-04-10 19:24:00,34.436\n2014-04-10 19:29:00,34.718\n2014-04-10 19:34:00,34.635999999999996\n2014-04-10 19:39:00,36.455999999999996\n2014-04-10 19:44:00,38.45\n2014-04-10 19:49:00,29.962\n2014-04-10 19:54:00,37.522\n2014-04-10 19:59:00,35.234\n2014-04-10 20:04:00,34.882\n2014-04-10 20:09:00,36.525999999999996\n2014-04-10 20:14:00,36.596\n2014-04-10 20:19:00,40.436\n2014-04-10 20:24:00,31.118000000000002\n2014-04-10 20:29:00,34.178000000000004\n2014-04-10 20:34:00,36.49\n2014-04-10 20:39:00,32.442\n2014-04-10 20:44:00,34.508\n2014-04-10 20:49:00,36.286\n2014-04-10 20:54:00,35.916\n2014-04-10 20:59:00,33.63\n2014-04-10 21:04:00,34.47\n2014-04-10 21:09:00,35.986\n2014-04-10 21:14:00,34.474000000000004\n2014-04-10 21:19:00,35.982\n2014-04-10 21:24:00,37.978\n2014-04-10 21:29:00,28.968000000000004\n2014-04-10 21:34:00,35.188\n2014-04-10 21:39:00,32.53\n2014-04-10 21:44:00,33.498000000000005\n2014-04-10 21:49:00,35.326\n2014-04-10 21:54:00,32.7\n2014-04-10 21:59:00,33.262\n2014-04-10 22:04:00,36.501999999999995\n2014-04-10 22:09:00,35.234\n2014-04-10 22:14:00,38.24\n2014-04-10 22:19:00,31.125999999999998\n2014-04-10 22:24:00,36.178000000000004\n2014-04-10 22:29:00,32.042\n2014-04-10 22:34:00,33.732\n2014-04-10 22:39:00,33.17\n2014-04-10 22:44:00,33.826\n2014-04-10 22:49:00,33.498000000000005\n2014-04-10 22:54:00,35.211999999999996\n2014-04-10 22:59:00,40.492\n2014-04-10 23:04:00,30.47\n2014-04-10 23:09:00,37.324\n2014-04-10 23:14:00,33.052\n2014-04-10 23:19:00,33.262\n2014-04-10 23:24:00,33.376\n2014-04-10 23:29:00,36.338\n2014-04-10 23:34:00,34.132\n2014-04-10 23:39:00,32.864000000000004\n2014-04-10 23:44:00,34.202\n2014-04-10 23:49:00,34.39\n2014-04-10 23:54:00,36.238\n2014-04-10 23:59:00,38.63800000000001\n2014-04-11 00:04:00,30.44\n2014-04-11 00:09:00,39.718\n2014-04-11 00:14:00,34.0\n2014-04-11 00:19:00,33.34\n2014-04-11 00:24:00,35.658\n2014-04-11 00:29:00,31.8\n2014-04-11 00:34:00,33.876\n2014-04-11 00:39:00,37.488\n2014-04-11 00:44:00,29.94\n2014-04-11 00:49:00,35.961999999999996\n2014-04-11 00:54:00,33.336\n2014-04-11 00:59:00,33.802\n2014-04-11 01:04:00,35.938\n2014-04-11 01:09:00,34.836\n2014-04-11 01:14:00,35.564\n2014-04-11 01:19:00,39.904\n2014-04-11 01:24:00,29.372\n2014-04-11 01:29:00,33.92\n2014-04-11 01:34:00,33.99\n2014-04-11 01:39:00,36.808\n2014-04-11 01:44:00,33.908\n2014-04-11 01:49:00,33.514\n2014-04-11 01:54:00,35.296\n2014-04-11 01:59:00,40.54\n2014-04-11 02:04:00,33.298\n2014-04-11 02:09:00,35.516\n2014-04-11 02:14:00,36.282\n2014-04-11 02:19:00,31.362\n2014-04-11 02:24:00,33.946\n2014-04-11 02:29:00,33.78\n2014-04-11 02:34:00,35.634\n2014-04-11 02:39:00,32.694\n2014-04-11 02:44:00,32.954\n2014-04-11 02:49:00,33.85\n2014-04-11 02:54:00,36.198\n2014-04-11 02:59:00,38.63800000000001\n2014-04-11 03:04:00,31.746\n2014-04-11 03:09:00,37.135999999999996\n2014-04-11 03:14:00,35.68\n2014-04-11 03:19:00,34.508\n2014-04-11 03:24:00,34.442\n2014-04-11 03:29:00,33.764\n2014-04-11 03:34:00,34.384\n2014-04-11 03:39:00,34.496\n2014-04-11 03:44:00,35.708\n2014-04-11 03:49:00,32.824\n2014-04-11 03:54:00,38.874\n2014-04-11 03:59:00,31.08\n2014-04-11 04:04:00,33.722\n2014-04-11 04:09:00,35.328\n2014-04-11 04:14:00,36.69\n2014-04-11 04:19:00,37.16\n2014-04-11 04:24:00,34.554\n2014-04-11 04:29:00,36.62\n2014-04-11 04:34:00,35.0\n2014-04-11 04:39:00,30.938000000000002\n2014-04-11 04:44:00,33.472\n2014-04-11 04:49:00,35.95\n2014-04-11 04:54:00,34.214\n2014-04-11 04:59:00,33.662\n2014-04-11 05:04:00,34.694\n2014-04-11 05:09:00,37.816\n2014-04-11 05:14:00,34.624\n2014-04-11 05:19:00,35.634\n2014-04-11 05:24:00,34.3\n2014-04-11 05:29:00,33.874\n2014-04-11 05:34:00,36.478\n2014-04-11 05:39:00,32.16\n2014-04-11 05:44:00,33.81\n2014-04-11 05:49:00,34.028\n2014-04-11 05:54:00,35.516\n2014-04-11 05:59:00,34.296\n2014-04-11 06:04:00,32.464\n2014-04-11 06:09:00,34.718\n2014-04-11 06:14:00,37.07\n2014-04-11 06:19:00,35.4\n2014-04-11 06:24:00,31.646\n2014-04-11 06:29:00,33.404\n2014-04-11 06:34:00,33.711999999999996\n2014-04-11 06:39:00,35.07\n2014-04-11 06:44:00,34.824\n2014-04-11 06:49:00,31.971999999999998\n2014-04-11 06:54:00,35.098\n2014-04-11 06:59:00,33.944\n2014-04-11 07:04:00,35.586\n2014-04-11 07:09:00,33.28\n2014-04-11 07:14:00,34.718\n2014-04-11 07:19:00,34.648\n2014-04-11 07:24:00,34.836\n2014-04-11 07:29:00,33.376\n2014-04-11 07:34:00,34.624\n2014-04-11 07:39:00,34.07\n2014-04-11 07:44:00,33.616\n2014-04-11 07:49:00,37.352\n2014-04-11 07:54:00,30.63\n2014-04-11 07:59:00,32.698\n2014-04-11 08:04:00,35.504\n2014-04-11 08:09:00,36.996\n2014-04-11 08:14:00,33.738\n2014-04-11 08:19:00,35.54\n2014-04-11 08:24:00,32.536\n2014-04-11 08:29:00,32.254\n2014-04-11 08:34:00,34.186\n2014-04-11 08:39:00,33.052\n2014-04-11 08:44:00,36.15\n2014-04-11 08:49:00,32.228\n2014-04-11 08:54:00,38.492\n2014-04-11 08:59:00,34.694\n2014-04-11 09:04:00,34.154\n2014-04-11 09:09:00,38.242\n2014-04-11 09:14:00,36.202\n2014-04-11 09:19:00,34.238\n2014-04-11 09:24:00,30.916\n2014-04-11 09:29:00,33.24\n2014-04-11 09:34:00,35.492\n2014-04-11 09:39:00,35.024\n2014-04-11 09:44:00,32.066\n2014-04-11 09:49:00,33.802\n2014-04-11 09:54:00,36.69\n2014-04-11 09:59:00,36.032\n2014-04-11 10:04:00,36.254\n2014-04-11 10:09:00,40.188\n2014-04-11 10:14:00,28.94400000000001\n2014-04-11 10:19:00,33.85\n2014-04-11 10:24:00,33.732\n2014-04-11 10:29:00,33.278\n2014-04-11 10:34:00,33.53\n2014-04-11 10:39:00,36.046\n2014-04-11 10:44:00,33.18\n2014-04-11 10:49:00,32.644\n2014-04-11 10:54:00,37.244\n2014-04-11 10:59:00,30.76\n2014-04-11 11:04:00,33.772\n2014-04-11 11:09:00,39.424\n2014-04-11 11:14:00,33.028\n2014-04-11 11:19:00,35.164\n2014-04-11 11:24:00,31.76\n2014-04-11 11:29:00,33.278\n2014-04-11 11:34:00,33.756\n2014-04-11 11:39:00,35.798\n2014-04-11 11:44:00,33.404\n2014-04-11 11:49:00,35.446\n2014-04-11 11:54:00,35.602\n2014-04-11 11:59:00,34.66\n2014-04-11 12:04:00,34.874\n2014-04-11 12:09:00,33.568000000000005\n2014-04-11 12:14:00,33.474000000000004\n2014-04-11 12:19:00,35.258\n2014-04-11 12:24:00,35.4\n2014-04-11 12:29:00,34.65\n2014-04-11 12:34:00,35.4\n2014-04-11 12:39:00,36.736\n2014-04-11 12:44:00,33.202\n2014-04-11 12:49:00,34.135999999999996\n2014-04-11 12:54:00,35.868\n2014-04-11 12:59:00,33.568000000000005\n2014-04-11 13:04:00,33.638000000000005\n2014-04-11 13:09:00,37.418\n2014-04-11 13:14:00,32.934\n2014-04-11 13:19:00,33.052\n2014-04-11 13:24:00,33.262\n2014-04-11 13:29:00,33.654\n2014-04-11 13:34:00,33.874\n2014-04-11 13:39:00,34.108000000000004\n2014-04-11 13:44:00,33.78\n2014-04-11 13:49:00,34.436\n2014-04-11 13:54:00,37.184\n2014-04-11 13:59:00,32.464\n2014-04-11 14:04:00,35.634\n2014-04-11 14:09:00,34.6\n2014-04-11 14:14:00,33.616\n2014-04-11 14:19:00,33.99\n2014-04-11 14:24:00,33.756\n2014-04-11 14:29:00,36.59\n2014-04-11 14:34:00,35.406\n2014-04-11 14:39:00,31.291999999999998\n2014-04-11 14:44:00,33.348\n2014-04-11 14:49:00,34.12\n2014-04-11 14:54:00,37.111999999999995\n2014-04-11 14:59:00,31.471999999999998\n2014-04-11 15:04:00,34.014\n2014-04-11 15:09:00,38.052\n2014-04-11 15:14:00,32.042\n2014-04-11 15:19:00,34.718\n2014-04-11 15:24:00,35.152\n2014-04-11 15:29:00,33.85\n2014-04-11 15:34:00,33.498000000000005\n2014-04-11 15:39:00,34.53\n2014-04-11 15:44:00,34.414\n2014-04-11 15:49:00,36.15\n2014-04-11 15:54:00,34.176\n2014-04-11 15:59:00,34.05\n2014-04-11 16:04:00,34.558\n2014-04-11 16:09:00,40.184\n2014-04-11 16:14:00,31.996\n2014-04-11 16:19:00,33.31\n2014-04-11 16:24:00,35.856\n2014-04-11 16:29:00,35.461999999999996\n2014-04-11 16:34:00,33.818000000000005\n2014-04-11 16:39:00,33.568000000000005\n2014-04-11 16:44:00,34.976\n2014-04-11 16:49:00,32.652\n2014-04-11 16:54:00,38.24\n2014-04-11 16:59:00,33.78\n2014-04-11 17:04:00,32.86\n2014-04-11 17:09:00,35.564\n2014-04-11 17:14:00,34.226\n2014-04-11 17:19:00,35.548\n2014-04-11 17:24:00,37.324\n2014-04-11 17:29:00,34.484\n2014-04-11 17:34:00,35.046\n2014-04-11 17:39:00,34.472\n2014-04-11 17:44:00,34.648\n2014-04-11 17:49:00,35.466\n2014-04-11 17:54:00,36.384\n2014-04-11 17:59:00,34.952\n2014-04-11 18:04:00,32.898\n2014-04-11 18:09:00,37.464\n2014-04-11 18:14:00,36.104\n2014-04-11 18:19:00,34.726\n2014-04-11 18:24:00,34.088\n2014-04-11 18:29:00,37.418\n2014-04-11 18:34:00,32.09\n2014-04-11 18:39:00,33.216\n2014-04-11 18:44:00,34.588\n2014-04-11 18:49:00,34.568000000000005\n2014-04-11 18:54:00,38.076\n2014-04-11 18:59:00,37.696\n2014-04-11 19:04:00,34.288000000000004\n2014-04-11 19:09:00,34.211999999999996\n2014-04-11 19:14:00,36.598\n2014-04-11 19:19:00,31.502\n2014-04-11 19:24:00,34.025999999999996\n2014-04-11 19:29:00,37.63\n2014-04-11 19:34:00,34.248000000000005\n2014-04-11 19:39:00,34.976\n2014-04-11 19:44:00,34.672\n2014-04-11 19:49:00,35.658\n2014-04-11 19:54:00,35.086\n2014-04-11 19:59:00,34.064\n2014-04-11 20:04:00,36.878\n2014-04-11 20:09:00,35.634\n2014-04-11 20:14:00,32.174\n2014-04-11 20:19:00,34.178000000000004\n2014-04-11 20:24:00,34.092\n2014-04-11 20:29:00,37.866\n2014-04-11 20:34:00,34.366\n2014-04-11 20:39:00,34.414\n2014-04-11 20:44:00,34.446\n2014-04-11 20:49:00,34.308\n2014-04-11 20:54:00,36.314\n2014-04-11 20:59:00,41.948\n2014-04-11 21:04:00,29.788\n2014-04-11 21:09:00,38.522\n2014-04-11 21:14:00,34.33\n2014-04-11 21:19:00,34.37\n2014-04-11 21:24:00,34.226\n2014-04-11 21:29:00,36.82\n2014-04-11 21:34:00,32.536\n2014-04-11 21:39:00,34.788000000000004\n2014-04-11 21:44:00,37.018\n2014-04-11 21:49:00,33.356\n2014-04-11 21:54:00,34.882\n2014-04-11 21:59:00,38.592\n2014-04-11 22:04:00,35.188\n2014-04-11 22:09:00,38.404\n2014-04-11 22:14:00,36.738\n2014-04-11 22:19:00,37.03\n2014-04-11 22:24:00,35.48\n2014-04-11 22:29:00,32.782\n2014-04-11 22:34:00,39.39\n2014-04-11 22:39:00,31.976\n2014-04-11 22:44:00,34.35\n2014-04-11 22:49:00,34.742\n2014-04-11 22:54:00,36.08\n2014-04-11 22:59:00,35.338\n2014-04-11 23:04:00,35.508\n2014-04-11 23:09:00,34.278\n2014-04-11 23:14:00,33.178000000000004\n2014-04-11 23:19:00,34.836\n2014-04-11 23:24:00,35.47\n2014-04-11 23:29:00,36.86\n2014-04-11 23:34:00,34.998000000000005\n2014-04-11 23:39:00,35.24800000000001\n2014-04-11 23:44:00,34.69\n2014-04-11 23:49:00,34.614000000000004\n2014-04-11 23:54:00,38.202\n2014-04-11 23:59:00,31.674\n2014-04-12 00:04:00,35.696\n2014-04-12 00:09:00,37.184\n2014-04-12 00:14:00,31.514\n2014-04-12 00:19:00,36.01\n2014-04-12 00:24:00,33.498000000000005\n2014-04-12 00:29:00,37.536\n2014-04-12 00:34:00,36.1\n2014-04-12 00:39:00,34.38\n2014-04-12 00:44:00,35.586\n2014-04-12 00:49:00,33.732\n2014-04-12 00:54:00,38.756\n2014-04-12 00:59:00,33.708\n2014-04-12 01:04:00,32.455999999999996\n2014-04-12 01:09:00,36.338\n2014-04-12 01:14:00,33.906\n2014-04-12 01:19:00,35.098\n2014-04-12 01:24:00,33.122\n2014-04-12 01:29:00,33.86\n2014-04-12 01:34:00,39.296\n2014-04-12 01:39:00,30.118000000000002\n2014-04-12 01:44:00,34.566\n2014-04-12 01:49:00,34.484\n2014-04-12 01:54:00,37.746\n2014-04-12 01:59:00,35.24800000000001\n2014-04-12 02:04:00,32.816\n2014-04-12 02:09:00,36.08\n2014-04-12 02:14:00,34.414\n2014-04-12 02:19:00,36.294000000000004\n2014-04-12 02:24:00,32.622\n2014-04-12 02:29:00,38.99\n2014-04-12 02:34:00,33.816\n2014-04-12 02:39:00,37.042\n2014-04-12 02:44:00,36.174\n2014-04-12 02:49:00,34.562\n2014-04-12 02:54:00,36.22\n2014-04-12 02:59:00,37.23\n2014-04-12 03:04:00,35.912\n2014-04-12 03:09:00,35.128\n2014-04-12 03:14:00,34.286\n2014-04-12 03:19:00,34.224000000000004\n2014-04-12 03:24:00,33.748000000000005\n2014-04-12 03:29:00,35.916\n2014-04-12 03:34:00,32.63\n2014-04-12 03:39:00,34.196\n2014-04-12 03:44:00,35.422\n2014-04-12 03:49:00,32.652\n2014-04-12 03:54:00,37.876\n2014-04-12 03:59:00,33.404\n2014-04-12 04:04:00,32.32\n2014-04-12 04:09:00,36.104\n2014-04-12 04:14:00,35.106\n2014-04-12 04:19:00,35.216\n2014-04-12 04:24:00,35.204\n2014-04-12 04:29:00,34.836\n2014-04-12 04:34:00,32.152\n2014-04-12 04:39:00,34.084\n2014-04-12 04:44:00,36.174\n2014-04-12 04:49:00,32.536\n2014-04-12 04:54:00,36.034\n2014-04-12 04:59:00,36.644\n2014-04-12 05:04:00,30.088\n2014-04-12 05:09:00,35.314\n2014-04-12 05:14:00,33.942\n2014-04-12 05:19:00,33.58\n2014-04-12 05:24:00,33.262\n2014-04-12 05:29:00,38.43\n2014-04-12 05:34:00,31.314\n2014-04-12 05:39:00,33.24\n2014-04-12 05:44:00,34.211999999999996\n2014-04-12 05:49:00,33.79\n2014-04-12 05:54:00,34.992\n2014-04-12 05:59:00,33.262\n2014-04-12 06:04:00,36.478\n2014-04-12 06:09:00,34.27\n2014-04-12 06:14:00,35.306\n2014-04-12 06:19:00,31.561999999999998\n2014-04-12 06:24:00,33.874\n2014-04-12 06:29:00,35.516\n2014-04-12 06:34:00,34.272\n2014-04-12 06:39:00,37.652\n2014-04-12 06:44:00,32.384\n2014-04-12 06:49:00,33.568000000000005\n2014-04-12 06:54:00,36.714\n2014-04-12 06:59:00,33.826\n2014-04-12 07:04:00,32.226\n2014-04-12 07:09:00,36.275999999999996\n2014-04-12 07:14:00,34.85\n2014-04-12 07:19:00,35.282\n2014-04-12 07:24:00,32.09\n2014-04-12 07:29:00,34.062\n2014-04-12 07:34:00,34.836\n2014-04-12 07:39:00,34.508\n2014-04-12 07:44:00,36.268\n2014-04-12 07:49:00,34.016\n2014-04-12 07:54:00,35.3\n2014-04-12 07:59:00,32.606\n2014-04-12 08:04:00,33.85\n2014-04-12 08:09:00,36.234\n2014-04-12 08:14:00,35.068000000000005\n2014-04-12 08:19:00,31.791999999999998\n2014-04-12 08:24:00,33.961999999999996\n2014-04-12 08:29:00,34.812\n2014-04-12 08:34:00,35.118\n2014-04-12 08:39:00,33.15\n2014-04-12 08:44:00,32.184\n2014-04-12 08:49:00,34.194\n2014-04-12 08:54:00,35.61\n2014-04-12 08:59:00,33.098\n2014-04-12 09:04:00,33.57\n2014-04-12 09:09:00,36.204\n2014-04-12 09:14:00,32.056\n2014-04-12 09:19:00,31.666\n2014-04-12 09:24:00,36.62\n2014-04-12 09:29:00,31.596\n2014-04-12 09:34:00,33.498000000000005\n2014-04-12 09:39:00,35.938\n2014-04-12 09:44:00,31.62\n2014-04-12 09:49:00,34.53\n2014-04-12 09:54:00,34.312\n2014-04-12 09:59:00,33.302\n2014-04-12 10:04:00,33.78\n2014-04-12 10:09:00,38.99\n2014-04-12 10:14:00,29.754\n2014-04-12 10:19:00,33.616\n2014-04-12 10:24:00,34.672\n2014-04-12 10:29:00,33.802\n2014-04-12 10:34:00,35.564\n2014-04-12 10:39:00,33.874\n2014-04-12 10:44:00,35.99800000000001\n2014-04-12 10:49:00,31.988000000000003\n2014-04-12 10:54:00,35.211999999999996\n2014-04-12 10:59:00,33.522\n2014-04-12 11:04:00,37.324\n2014-04-12 11:09:00,32.606\n2014-04-12 11:14:00,35.891999999999996\n2014-04-12 11:19:00,31.76\n2014-04-12 11:24:00,33.556\n2014-04-12 11:29:00,33.426\n2014-04-12 11:34:00,33.522\n2014-04-12 11:39:00,34.648\n2014-04-12 11:44:00,31.886\n2014-04-12 11:49:00,37.016\n2014-04-12 11:54:00,30.554000000000002\n2014-04-12 11:59:00,32.88\n2014-04-12 12:04:00,33.326\n2014-04-12 12:09:00,34.718\n2014-04-12 12:14:00,36.032\n2014-04-12 12:19:00,29.624000000000002\n2014-04-12 12:24:00,33.17\n2014-04-12 12:29:00,34.202\n2014-04-12 12:34:00,37.24800000000001\n2014-04-12 12:39:00,30.61\n2014-04-12 12:44:00,35.571999999999996\n2014-04-12 12:49:00,31.666\n2014-04-12 12:54:00,36.292\n2014-04-12 12:59:00,31.76\n2014-04-12 13:04:00,33.356\n2014-04-12 13:09:00,36.004\n2014-04-12 13:14:00,36.464\n2014-04-12 13:19:00,32.728\n2014-04-12 13:24:00,31.448\n2014-04-12 13:29:00,33.896\n2014-04-12 13:34:00,32.3\n2014-04-12 13:39:00,34.248000000000005\n2014-04-12 13:44:00,33.656\n2014-04-12 13:49:00,34.906\n2014-04-12 13:54:00,32.536\n2014-04-12 13:59:00,32.424\n2014-04-12 14:04:00,33.03\n2014-04-12 14:09:00,38.238\n2014-04-12 14:14:00,29.108\n2014-04-12 14:19:00,35.086\n2014-04-12 14:24:00,30.778000000000002\n2014-04-12 14:29:00,32.676\n2014-04-12 14:34:00,35.774\n2014-04-12 14:39:00,34.342\n2014-04-12 14:44:00,32.108000000000004\n2014-04-12 14:49:00,37.496\n2014-04-12 14:54:00,30.351999999999997\n2014-04-12 14:59:00,33.27\n2014-04-12 15:04:00,34.766\n2014-04-12 15:09:00,35.846\n2014-04-12 15:14:00,34.718\n2014-04-12 15:19:00,32.066\n2014-04-12 15:24:00,35.108000000000004\n2014-04-12 15:29:00,30.978\n2014-04-12 15:34:00,33.818000000000005\n2014-04-12 15:39:00,36.152\n2014-04-12 15:44:00,31.55\n2014-04-12 15:49:00,36.838\n2014-04-12 15:54:00,31.22\n2014-04-12 15:59:00,32.558\n2014-04-12 16:04:00,33.24\n2014-04-12 16:09:00,34.08\n2014-04-12 16:14:00,32.934\n2014-04-12 16:19:00,33.122\n2014-04-12 16:24:00,35.74800000000001\n2014-04-12 16:29:00,34.154\n2014-04-12 16:34:00,31.45\n2014-04-12 16:39:00,32.488\n2014-04-12 16:44:00,32.794000000000004\n2014-04-12 16:49:00,32.864000000000004\n2014-04-12 16:54:00,34.884\n2014-04-12 16:59:00,33.146\n2014-04-12 17:04:00,37.275999999999996\n2014-04-12 17:09:00,33.616\n2014-04-12 17:14:00,30.32800000000001\n2014-04-12 17:19:00,32.864000000000004\n2014-04-12 17:24:00,33.076\n2014-04-12 17:29:00,32.84\n2014-04-12 17:34:00,35.292\n2014-04-12 17:39:00,32.606\n2014-04-12 17:44:00,31.912\n2014-04-12 17:49:00,35.141999999999996\n2014-04-12 17:54:00,32.738\n2014-04-12 17:59:00,32.84\n2014-04-12 18:04:00,36.032\n2014-04-12 18:09:00,33.78\n2014-04-12 18:14:00,33.544000000000004\n2014-04-12 18:19:00,33.37\n2014-04-12 18:24:00,34.32\n2014-04-12 18:29:00,32.394\n2014-04-12 18:34:00,37.816\n2014-04-12 18:39:00,38.522\n2014-04-12 18:44:00,33.404\n2014-04-12 18:49:00,36.268\n2014-04-12 18:54:00,32.84\n2014-04-12 18:59:00,35.282\n2014-04-12 19:04:00,34.038000000000004\n2014-04-12 19:09:00,37.132\n2014-04-12 19:14:00,35.774\n2014-04-12 19:19:00,31.305999999999997\n2014-04-12 19:24:00,33.251999999999995\n2014-04-12 19:29:00,33.54\n2014-04-12 19:34:00,34.062\n2014-04-12 19:39:00,35.492\n2014-04-12 19:44:00,36.972\n2014-04-12 19:49:00,30.212\n2014-04-12 19:54:00,35.821999999999996\n2014-04-12 19:59:00,33.868\n2014-04-12 20:04:00,34.282\n2014-04-12 20:09:00,38.75\n2014-04-12 20:14:00,37.18\n2014-04-12 20:19:00,30.704\n2014-04-12 20:24:00,33.92\n2014-04-12 20:29:00,36.431999999999995\n2014-04-12 20:34:00,31.314\n2014-04-12 20:39:00,34.384\n2014-04-12 20:44:00,36.361999999999995\n2014-04-12 20:49:00,33.662\n2014-04-12 20:54:00,34.436\n2014-04-12 20:59:00,33.662\n2014-04-12 21:04:00,33.568000000000005\n2014-04-12 21:09:00,39.111999999999995\n2014-04-12 21:14:00,32.934\n2014-04-12 21:19:00,31.666\n2014-04-12 21:24:00,35.33\n2014-04-12 21:29:00,32.404\n2014-04-12 21:34:00,33.944\n2014-04-12 21:39:00,34.578\n2014-04-12 21:44:00,36.104\n2014-04-12 21:49:00,31.574\n2014-04-12 21:54:00,34.654\n2014-04-12 21:59:00,33.846\n2014-04-12 22:04:00,34.2\n2014-04-12 22:09:00,34.272\n2014-04-12 22:14:00,34.02\n2014-04-12 22:19:00,35.838\n2014-04-12 22:24:00,31.834\n2014-04-12 22:29:00,34.014\n2014-04-12 22:34:00,33.874\n2014-04-12 22:39:00,33.04\n2014-04-12 22:44:00,34.316\n2014-04-12 22:49:00,37.7\n2014-04-12 22:54:00,33.916\n2014-04-12 22:59:00,31.901999999999997\n2014-04-12 23:04:00,34.726\n2014-04-12 23:09:00,35.306\n2014-04-12 23:14:00,33.826\n2014-04-12 23:19:00,34.32\n2014-04-12 23:24:00,38.662\n2014-04-12 23:29:00,33.334\n2014-04-12 23:34:00,38.286\n2014-04-12 23:39:00,31.526\n2014-04-12 23:44:00,34.624\n2014-04-12 23:49:00,33.976\n2014-04-12 23:54:00,35.662\n2014-04-12 23:59:00,35.916\n2014-04-13 00:04:00,33.334\n2014-04-13 00:09:00,36.431999999999995\n2014-04-13 00:14:00,33.544000000000004\n2014-04-13 00:19:00,35.61199999999999\n2014-04-13 00:24:00,37.746\n2014-04-13 00:29:00,33.24\n2014-04-13 00:34:00,31.706\n2014-04-13 00:39:00,34.772\n2014-04-13 00:44:00,32.92\n2014-04-13 00:49:00,34.014\n2014-04-13 00:54:00,37.864000000000004\n2014-04-13 00:59:00,31.526\n2014-04-13 01:04:00,34.108000000000004\n2014-04-13 01:09:00,36.244\n2014-04-13 01:14:00,38.431999999999995\n2014-04-13 01:19:00,33.156\n2014-04-13 01:24:00,36.37\n2014-04-13 01:29:00,31.268\n2014-04-13 01:34:00,34.954\n2014-04-13 01:39:00,34.288000000000004\n2014-04-13 01:44:00,33.498000000000005\n2014-04-13 01:49:00,34.718\n2014-04-13 01:54:00,34.428000000000004\n2014-04-13 01:59:00,38.705999999999996\n2014-04-13 02:04:00,31.08\n2014-04-13 02:09:00,36.738\n2014-04-13 02:14:00,33.704\n2014-04-13 02:19:00,34.058\n2014-04-13 02:24:00,33.534\n2014-04-13 02:29:00,33.522\n2014-04-13 02:34:00,34.484\n2014-04-13 02:39:00,34.391999999999996\n2014-04-13 02:44:00,31.924\n2014-04-13 02:49:00,33.775999999999996\n2014-04-13 02:54:00,37.586\n2014-04-13 02:59:00,30.97\n2014-04-13 03:04:00,33.672\n2014-04-13 03:09:00,41.034\n2014-04-13 03:14:00,34.17\n2014-04-13 03:19:00,33.474000000000004\n2014-04-13 03:24:00,34.73\n2014-04-13 03:29:00,35.164\n2014-04-13 03:34:00,36.62\n2014-04-13 03:39:00,36.654\n2014-04-13 03:44:00,29.95\n2014-04-13 03:49:00,33.46\n2014-04-13 03:54:00,35.304\n2014-04-13 03:59:00,34.672\n2014-04-13 04:04:00,37.442\n2014-04-13 04:09:00,34.6\n2014-04-13 04:14:00,36.256\n2014-04-13 04:19:00,32.536\n2014-04-13 04:24:00,36.22\n2014-04-13 04:29:00,33.44\n2014-04-13 04:34:00,31.666\n2014-04-13 04:39:00,33.17\n2014-04-13 04:44:00,33.756\n2014-04-13 04:49:00,35.0\n2014-04-13 04:54:00,33.638000000000005\n2014-04-13 04:59:00,34.86\n2014-04-13 05:04:00,34.308\n2014-04-13 05:09:00,33.146\n2014-04-13 05:14:00,36.174\n2014-04-13 05:19:00,35.198\n2014-04-13 05:24:00,34.866\n2014-04-13 05:29:00,31.738000000000003\n2014-04-13 05:34:00,35.33\n2014-04-13 05:39:00,31.802\n2014-04-13 05:44:00,33.262\n2014-04-13 05:49:00,33.146\n2014-04-13 05:54:00,34.976\n2014-04-13 05:59:00,33.592\n2014-04-13 06:04:00,35.082\n2014-04-13 06:09:00,36.455999999999996\n2014-04-13 06:14:00,32.092\n2014-04-13 06:19:00,34.366\n2014-04-13 06:24:00,35.586\n2014-04-13 06:29:00,32.828\n2014-04-13 06:34:00,34.984\n2014-04-13 06:39:00,32.096\n2014-04-13 06:44:00,31.526\n2014-04-13 06:49:00,35.516\n2014-04-13 06:54:00,31.996\n2014-04-13 06:59:00,34.46\n2014-04-13 07:04:00,30.774\n2014-04-13 07:09:00,34.788000000000004\n2014-04-13 07:14:00,34.04\n2014-04-13 07:19:00,34.722\n2014-04-13 07:24:00,35.798\n2014-04-13 07:29:00,34.6\n2014-04-13 07:34:00,30.798000000000002\n2014-04-13 07:39:00,33.326\n2014-04-13 07:44:00,34.46\n2014-04-13 07:49:00,36.232\n2014-04-13 07:54:00,36.478\n2014-04-13 07:59:00,33.556\n2014-04-13 08:04:00,33.216\n2014-04-13 08:09:00,34.46\n2014-04-13 08:14:00,35.376\n2014-04-13 08:19:00,30.212\n2014-04-13 08:24:00,36.056\n2014-04-13 08:29:00,29.27\n2014-04-13 08:34:00,32.814\n2014-04-13 08:39:00,32.652\n2014-04-13 08:44:00,32.942\n2014-04-13 08:49:00,33.416\n2014-04-13 08:54:00,37.56\n2014-04-13 08:59:00,36.158\n2014-04-13 09:04:00,30.658\n2014-04-13 09:09:00,35.891999999999996\n2014-04-13 09:14:00,34.226\n2014-04-13 09:19:00,33.122\n2014-04-13 09:24:00,34.84\n2014-04-13 09:29:00,30.822\n2014-04-13 09:34:00,34.968\n2014-04-13 09:39:00,32.275999999999996\n2014-04-13 09:44:00,35.774\n2014-04-13 09:49:00,30.54\n2014-04-13 09:54:00,34.75\n2014-04-13 09:59:00,35.188\n2014-04-13 10:04:00,31.338\n2014-04-13 10:09:00,37.254\n2014-04-13 10:14:00,35.468\n2014-04-13 10:19:00,31.49\n2014-04-13 10:24:00,32.978\n2014-04-13 10:29:00,37.635999999999996\n2014-04-13 10:34:00,28.204\n2014-04-13 10:39:00,32.676\n2014-04-13 10:44:00,32.934\n2014-04-13 10:49:00,33.82\n2014-04-13 10:54:00,33.382\n2014-04-13 10:59:00,35.0\n2014-04-13 11:04:00,31.201999999999998\n2014-04-13 11:09:00,34.702\n2014-04-13 11:14:00,37.412\n2014-04-13 11:19:00,33.544000000000004\n2014-04-13 11:24:00,34.014\n2014-04-13 11:29:00,33.8\n2014-04-13 11:34:00,32.111999999999995\n2014-04-13 11:39:00,33.99\n2014-04-13 11:44:00,34.824\n2014-04-13 11:49:00,33.708\n2014-04-13 11:54:00,34.624\n2014-04-13 11:59:00,33.888000000000005\n2014-04-13 12:04:00,39.994\n2014-04-13 12:09:00,33.498000000000005\n2014-04-13 12:14:00,31.54\n2014-04-13 12:19:00,32.79\n2014-04-13 12:24:00,32.982\n2014-04-13 12:29:00,32.652\n2014-04-13 12:34:00,35.282\n2014-04-13 12:39:00,32.418\n2014-04-13 12:44:00,31.76\n2014-04-13 12:49:00,34.624\n2014-04-13 12:54:00,33.428000000000004\n2014-04-13 12:59:00,33.334\n2014-04-13 13:04:00,32.764\n2014-04-13 13:09:00,37.374\n2014-04-13 13:14:00,31.921999999999997\n2014-04-13 13:19:00,31.76\n2014-04-13 13:24:00,35.492\n2014-04-13 13:29:00,35.516\n2014-04-13 13:34:00,34.578\n2014-04-13 13:39:00,34.62\n2014-04-13 13:44:00,32.096\n2014-04-13 13:49:00,32.018\n2014-04-13 13:54:00,36.314\n2014-04-13 13:59:00,31.478\n2014-04-13 14:04:00,35.586\n2014-04-13 14:09:00,32.8\n2014-04-13 14:14:00,33.95\n2014-04-13 14:19:00,35.824\n2014-04-13 14:24:00,38.874\n2014-04-13 14:29:00,36.054\n2014-04-13 14:34:00,33.262\n2014-04-13 14:39:00,33.544000000000004\n2014-04-13 14:44:00,33.568000000000005\n2014-04-13 14:49:00,33.45\n2014-04-13 14:54:00,34.882\n2014-04-13 14:59:00,33.474000000000004\n2014-04-13 15:04:00,36.596\n2014-04-13 15:09:00,33.001999999999995\n2014-04-13 15:14:00,32.582\n2014-04-13 15:19:00,37.6\n2014-04-13 15:24:00,33.438\n2014-04-13 15:29:00,33.292\n2014-04-13 15:34:00,35.942\n2014-04-13 15:39:00,33.484\n2014-04-13 15:44:00,33.004\n2014-04-13 15:49:00,33.514\n2014-04-13 15:54:00,35.306\n2014-04-13 15:59:00,34.32\n2014-04-13 16:04:00,34.766\n2014-04-13 16:09:00,33.076\n2014-04-13 16:14:00,34.282\n2014-04-13 16:19:00,33.592\n2014-04-13 16:24:00,32.275999999999996\n2014-04-13 16:29:00,38.852\n2014-04-13 16:34:00,32.882\n2014-04-13 16:39:00,33.216\n2014-04-13 16:44:00,34.234\n2014-04-13 16:49:00,32.582\n2014-04-13 16:54:00,35.282\n2014-04-13 16:59:00,36.948\n2014-04-13 17:04:00,31.471999999999998\n2014-04-13 17:09:00,33.614000000000004\n2014-04-13 17:14:00,34.4\n2014-04-13 17:19:00,35.008\n2014-04-13 17:24:00,33.07\n2014-04-13 17:29:00,35.116\n2014-04-13 17:34:00,34.452\n2014-04-13 17:39:00,31.39\n2014-04-13 17:44:00,33.512\n2014-04-13 17:49:00,33.47\n2014-04-13 17:54:00,37.746\n2014-04-13 17:59:00,31.69\n2014-04-13 18:04:00,33.67\n2014-04-13 18:09:00,36.208\n2014-04-13 18:14:00,32.042\n2014-04-13 18:19:00,37.298\n2014-04-13 18:24:00,30.32800000000001\n2014-04-13 18:29:00,35.846\n2014-04-13 18:34:00,37.566\n2014-04-13 18:39:00,33.04\n2014-04-13 18:44:00,34.641999999999996\n2014-04-13 18:49:00,32.124\n2014-04-13 18:54:00,35.352\n2014-04-13 18:59:00,34.536\n2014-04-13 19:04:00,32.464\n2014-04-13 19:09:00,37.348\n2014-04-13 19:14:00,31.384\n2014-04-13 19:19:00,34.718\n2014-04-13 19:24:00,34.342\n2014-04-13 19:29:00,35.164\n2014-04-13 19:34:00,35.328\n2014-04-13 19:39:00,34.86\n2014-04-13 19:44:00,37.288000000000004\n2014-04-13 19:49:00,31.072\n2014-04-13 19:54:00,36.032\n2014-04-13 19:59:00,33.394\n2014-04-13 20:04:00,33.004\n2014-04-13 20:09:00,35.418\n2014-04-13 20:14:00,35.47\n2014-04-13 20:19:00,31.055999999999997\n2014-04-13 20:24:00,33.098\n2014-04-13 20:29:00,33.31\n2014-04-13 20:34:00,33.248000000000005\n2014-04-13 20:39:00,35.961999999999996\n2014-04-13 20:44:00,32.744\n2014-04-13 20:49:00,31.528000000000002\n2014-04-13 20:54:00,34.624\n2014-04-13 20:59:00,34.788000000000004\n2014-04-13 21:04:00,32.568000000000005\n2014-04-13 21:09:00,35.004\n2014-04-13 21:14:00,34.52\n2014-04-13 21:19:00,34.014\n2014-04-13 21:24:00,32.464\n2014-04-13 21:29:00,32.042\n2014-04-13 21:34:00,34.038000000000004\n2014-04-13 21:39:00,34.566\n2014-04-13 21:44:00,35.282\n2014-04-13 21:49:00,34.664\n2014-04-13 21:54:00,39.236\n2014-04-13 21:59:00,28.338\n2014-04-13 22:04:00,33.494\n2014-04-13 22:09:00,34.766\n2014-04-13 22:14:00,34.648\n2014-04-13 22:19:00,31.738000000000003\n2014-04-13 22:24:00,35.282\n2014-04-13 22:29:00,32.394\n2014-04-13 22:34:00,32.536\n2014-04-13 22:39:00,34.766\n2014-04-13 22:44:00,32.57\n2014-04-13 22:49:00,33.424\n2014-04-13 22:54:00,37.184\n2014-04-13 22:59:00,32.864000000000004\n2014-04-13 23:04:00,33.944\n2014-04-13 23:09:00,33.954\n2014-04-13 23:14:00,33.884\n2014-04-13 23:19:00,33.18\n2014-04-13 23:24:00,33.17\n2014-04-13 23:29:00,35.282\n2014-04-13 23:34:00,32.344\n2014-04-13 23:39:00,33.406\n2014-04-13 23:44:00,34.906\n2014-04-13 23:49:00,31.94400000000001\n2014-04-13 23:54:00,36.078\n2014-04-13 23:59:00,33.814\n2014-04-14 00:04:00,34.396\n2014-04-14 00:09:00,35.0\n2014-04-14 00:14:00,33.38\n2014-04-14 00:19:00,37.126\n2014-04-14 00:24:00,33.391999999999996\n2014-04-14 00:29:00,36.666\n2014-04-14 00:34:00,31.726\n2014-04-14 00:39:00,34.406\n2014-04-14 00:44:00,32.794000000000004\n2014-04-14 00:49:00,34.006\n2014-04-14 00:54:00,36.666\n2014-04-14 00:59:00,32.36\n2014-04-14 01:04:00,33.635999999999996\n2014-04-14 01:09:00,37.135999999999996\n2014-04-14 01:14:00,31.932\n2014-04-14 01:19:00,34.648\n2014-04-14 01:24:00,32.242\n2014-04-14 01:29:00,33.404\n2014-04-14 01:34:00,36.211999999999996\n2014-04-14 01:39:00,39.306\n2014-04-14 01:44:00,34.828\n2014-04-14 01:49:00,31.314\n2014-04-14 01:54:00,35.308\n2014-04-14 01:59:00,33.498000000000005\n2014-04-14 02:04:00,34.788000000000004\n2014-04-14 02:09:00,33.72\n2014-04-14 02:14:00,36.996\n2014-04-14 02:19:00,30.938000000000002\n2014-04-14 02:24:00,32.746\n2014-04-14 02:29:00,34.46\n2014-04-14 02:34:00,33.984\n2014-04-14 02:39:00,35.656\n2014-04-14 02:44:00,34.436\n2014-04-14 02:49:00,31.15\n2014-04-14 02:54:00,35.586\n2014-04-14 02:59:00,33.608000000000004\n2014-04-14 03:04:00,34.694\n2014-04-14 03:09:00,34.906\n2014-04-14 03:14:00,38.356\n2014-04-14 03:19:00,32.652\n2014-04-14 03:24:00,33.076\n2014-04-14 03:29:00,37.606\n2014-04-14 03:34:00,32.711999999999996\n2014-04-14 03:39:00,34.705999999999996\n2014-04-14 03:44:00,37.12\n2014-04-14 03:49:00,31.714000000000002\n2014-04-14 03:54:00,36.784\n2014-04-14 03:59:00,33.708\n2014-04-14 04:04:00,38.24\n2014-04-14 04:09:00,33.92\n2014-04-14 04:14:00,35.452\n2014-04-14 04:19:00,31.62\n2014-04-14 04:24:00,33.592\n2014-04-14 04:29:00,34.812\n2014-04-14 04:34:00,33.838\n2014-04-14 04:39:00,35.236\n2014-04-14 04:44:00,29.978\n2014-04-14 04:49:00,33.094\n2014-04-14 04:54:00,35.946\n2014-04-14 04:59:00,33.522\n2014-04-14 05:04:00,33.304\n2014-04-14 05:09:00,35.082\n2014-04-14 05:14:00,33.562\n2014-04-14 05:19:00,34.484\n2014-04-14 05:24:00,38.286\n2014-04-14 05:29:00,32.102\n2014-04-14 05:34:00,32.37\n2014-04-14 05:39:00,33.896\n2014-04-14 05:44:00,34.244\n2014-04-14 05:49:00,33.78\n2014-04-14 05:54:00,35.078\n2014-04-14 05:59:00,35.35\n2014-04-14 06:04:00,31.808000000000003\n2014-04-14 06:09:00,35.258\n2014-04-14 06:14:00,34.806\n2014-04-14 06:19:00,32.264\n2014-04-14 06:24:00,37.184\n2014-04-14 06:29:00,32.43\n2014-04-14 06:34:00,35.504\n2014-04-14 06:39:00,31.244\n2014-04-14 06:44:00,33.896\n2014-04-14 06:49:00,34.788000000000004\n2014-04-14 06:54:00,34.098\n2014-04-14 06:59:00,34.132\n2014-04-14 07:04:00,35.821999999999996\n2014-04-14 07:09:00,35.692\n2014-04-14 07:14:00,36.354\n2014-04-14 07:19:00,35.094\n2014-04-14 07:24:00,33.6\n2014-04-14 07:29:00,34.718\n2014-04-14 07:34:00,32.496\n2014-04-14 07:39:00,35.798\n2014-04-14 07:44:00,32.135999999999996\n2014-04-14 07:49:00,33.31\n2014-04-14 07:54:00,37.536\n2014-04-14 07:59:00,31.031999999999996\n2014-04-14 08:04:00,33.802\n2014-04-14 08:09:00,37.63\n2014-04-14 08:14:00,37.254\n2014-04-14 08:19:00,31.13\n2014-04-14 08:24:00,33.286\n2014-04-14 08:29:00,33.046\n2014-04-14 08:34:00,33.122\n2014-04-14 08:39:00,38.391999999999996\n2014-04-14 08:44:00,30.281999999999996\n2014-04-14 08:49:00,32.205999999999996\n2014-04-14 08:54:00,35.14\n2014-04-14 08:59:00,36.22\n2014-04-14 09:04:00,33.592\n2014-04-14 09:09:00,35.762\n2014-04-14 09:14:00,36.858000000000004\n2014-04-14 09:19:00,32.111999999999995\n2014-04-14 09:24:00,37.69\n2014-04-14 09:29:00,29.79\n2014-04-14 09:34:00,33.916\n2014-04-14 09:39:00,33.998000000000005\n2014-04-14 09:44:00,36.164\n2014-04-14 09:49:00,32.128\n2014-04-14 09:54:00,35.872\n2014-04-14 09:59:00,33.782\n2014-04-14 10:04:00,37.418\n2014-04-14 10:09:00,34.93\n2014-04-14 10:14:00,33.644\n2014-04-14 10:19:00,32.464\n2014-04-14 10:24:00,35.66\n2014-04-14 10:29:00,31.162\n2014-04-14 10:34:00,33.338\n2014-04-14 10:39:00,35.472\n2014-04-14 10:44:00,32.676\n2014-04-14 10:49:00,32.794000000000004\n2014-04-14 10:54:00,34.882\n2014-04-14 10:59:00,35.354\n2014-04-14 11:04:00,32.14\n2014-04-14 11:09:00,34.882\n2014-04-14 11:14:00,35.738\n2014-04-14 11:19:00,34.558\n2014-04-14 11:24:00,33.896\n2014-04-14 11:29:00,30.938000000000002\n2014-04-14 11:34:00,33.256\n2014-04-14 11:39:00,33.594\n2014-04-14 11:44:00,33.628\n2014-04-14 11:49:00,34.406\n2014-04-14 11:54:00,41.056000000000004\n2014-04-14 11:59:00,32.618\n2014-04-14 12:04:00,32.008\n2014-04-14 12:09:00,35.39\n2014-04-14 12:14:00,33.094\n2014-04-14 12:19:00,37.488\n2014-04-14 12:24:00,31.98\n2014-04-14 12:29:00,34.882\n2014-04-14 12:34:00,35.846\n2014-04-14 12:39:00,31.614\n2014-04-14 12:44:00,31.901999999999997\n2014-04-14 12:49:00,36.15\n2014-04-14 12:54:00,34.554\n2014-04-14 12:59:00,33.262\n2014-04-14 13:04:00,33.21\n2014-04-14 13:09:00,34.578\n2014-04-14 13:14:00,36.292\n2014-04-14 13:19:00,32.724000000000004\n2014-04-14 13:24:00,32.408\n2014-04-14 13:29:00,33.034\n2014-04-14 13:34:00,34.354\n2014-04-14 13:39:00,33.638000000000005\n2014-04-14 13:44:00,33.428000000000004\n2014-04-14 13:49:00,33.192\n2014-04-14 13:54:00,38.204\n2014-04-14 13:59:00,29.682\n2014-04-14 14:04:00,33.662\n2014-04-14 14:09:00,36.76\n2014-04-14 14:14:00,33.616\n2014-04-14 14:19:00,35.088\n2014-04-14 14:24:00,32.821999999999996\n2014-04-14 14:29:00,33.654\n2014-04-14 14:34:00,33.052\n2014-04-14 14:39:00,35.566\n2014-04-14 14:44:00,32.961999999999996\n2014-04-14 14:49:00,31.744\n2014-04-14 14:54:00,35.208\n2014-04-14 14:59:00,33.216\n2014-04-14 15:04:00,33.548\n2014-04-14 15:09:00,40.058\n2014-04-14 15:14:00,30.07\n2014-04-14 15:19:00,35.6\n2014-04-14 15:24:00,35.868\n2014-04-14 15:29:00,31.754\n2014-04-14 15:34:00,33.722\n2014-04-14 15:39:00,34.062\n2014-04-14 15:44:00,35.47\n2014-04-14 15:49:00,31.244\n2014-04-14 15:54:00,35.728\n2014-04-14 15:59:00,34.46\n2014-04-14 16:04:00,34.342\n2014-04-14 16:09:00,33.052\n2014-04-14 16:14:00,32.982\n2014-04-14 16:19:00,32.57\n2014-04-14 16:24:00,34.742\n2014-04-14 16:29:00,30.986\n2014-04-14 16:34:00,32.806\n2014-04-14 16:39:00,33.156\n2014-04-14 16:44:00,33.004\n2014-04-14 16:49:00,32.408\n2014-04-14 16:54:00,35.61\n2014-04-14 16:59:00,33.544000000000004\n2014-04-14 17:04:00,31.01\n2014-04-14 17:09:00,34.146\n2014-04-14 17:14:00,35.422\n2014-04-14 17:19:00,30.234\n2014-04-14 17:24:00,36.22\n2014-04-14 17:29:00,32.7\n2014-04-14 17:34:00,35.211999999999996\n2014-04-14 17:39:00,31.362\n2014-04-14 17:44:00,34.32\n2014-04-14 17:49:00,31.502\n2014-04-14 17:54:00,34.508\n2014-04-14 17:59:00,32.63\n2014-04-14 18:04:00,32.94\n2014-04-14 18:09:00,35.728\n2014-04-14 18:14:00,39.954\n2014-04-14 18:19:00,30.488000000000003\n2014-04-14 18:24:00,32.63\n2014-04-14 18:29:00,32.738\n2014-04-14 18:34:00,33.78\n2014-04-14 18:39:00,32.924\n2014-04-14 18:44:00,35.188\n2014-04-14 18:49:00,34.902\n2014-04-14 18:54:00,32.418\n2014-04-14 18:59:00,32.794000000000004\n2014-04-14 19:04:00,34.248000000000005\n2014-04-14 19:09:00,33.028\n2014-04-14 19:14:00,35.352\n2014-04-14 19:19:00,32.602\n2014-04-14 19:24:00,34.812\n2014-04-14 19:29:00,30.564\n2014-04-14 19:34:00,33.274\n2014-04-14 19:39:00,33.461999999999996\n2014-04-14 19:44:00,33.028\n2014-04-14 19:49:00,32.668\n2014-04-14 19:54:00,34.316\n2014-04-14 19:59:00,33.004\n2014-04-14 20:04:00,36.902\n2014-04-14 20:09:00,32.544000000000004\n2014-04-14 20:14:00,30.658\n2014-04-14 20:19:00,32.84\n2014-04-14 20:24:00,35.352\n2014-04-14 20:29:00,34.436\n2014-04-14 20:34:00,32.934\n2014-04-14 20:39:00,33.076\n2014-04-14 20:44:00,32.622\n2014-04-14 20:49:00,35.986\n2014-04-14 20:54:00,31.198\n2014-04-14 20:59:00,35.164\n2014-04-14 21:04:00,30.372\n2014-04-14 21:09:00,37.018\n2014-04-14 21:14:00,32.91\n2014-04-14 21:19:00,32.606\n2014-04-14 21:24:00,34.554\n2014-04-14 21:29:00,32.016\n2014-04-14 21:34:00,31.854\n2014-04-14 21:39:00,33.944\n2014-04-14 21:44:00,33.132\n2014-04-14 21:49:00,32.746\n2014-04-14 21:54:00,34.466\n2014-04-14 21:59:00,32.806\n2014-04-14 22:04:00,33.076\n2014-04-14 22:09:00,34.436\n2014-04-14 22:14:00,35.306\n2014-04-14 22:19:00,32.088\n2014-04-14 22:24:00,33.5\n2014-04-14 22:29:00,32.814\n2014-04-14 22:34:00,33.244\n2014-04-14 22:39:00,32.746\n2014-04-14 22:44:00,32.802\n2014-04-14 22:49:00,32.724000000000004\n2014-04-14 22:54:00,34.308\n2014-04-14 22:59:00,34.562\n2014-04-14 23:04:00,32.376\n2014-04-14 23:09:00,35.916\n2014-04-14 23:14:00,31.62\n2014-04-14 23:19:00,35.262\n2014-04-14 23:24:00,34.571999999999996\n2014-04-14 23:29:00,33.334\n2014-04-14 23:34:00,35.492\n2014-04-14 23:39:00,31.76\n2014-04-14 23:44:00,52.6125\n2014-04-15 00:04:00,55.394\n2014-04-15 00:09:00,34.154\n2014-04-15 00:14:00,32.254\n2014-04-15 00:19:00,33.602\n2014-04-15 00:24:00,34.692\n2014-04-15 00:29:00,32.09\n2014-04-15 00:34:00,31.886\n2014-04-15 00:39:00,37.742\n2014-04-15 00:44:00,30.908\n2014-04-15 00:49:00,88.20200000000001\n2014-04-15 00:54:00,99.552\n2014-04-15 00:59:00,98.944\n2014-04-15 01:04:00,98.816\n2014-04-15 01:09:00,98.42399999999999\n2014-04-15 01:14:00,98.73\n2014-04-15 01:19:00,98.544\n2014-04-15 01:24:00,98.49799999999999\n2014-04-15 01:29:00,98.238\n2014-04-15 01:34:00,98.92\n2014-04-15 01:39:00,99.62\n2014-04-15 01:44:00,99.39\n2014-04-15 01:49:00,99.014\n2014-04-15 01:54:00,98.49799999999999\n2014-04-15 01:59:00,99.06200000000001\n2014-04-15 02:04:00,99.25\n2014-04-15 02:09:00,99.52799999999999\n2014-04-15 02:14:00,99.226\n2014-04-15 02:19:00,99.272\n2014-04-15 02:24:00,98.72399999999999\n2014-04-15 02:29:00,99.554\n2014-04-15 02:34:00,98.706\n2014-04-15 02:39:00,99.414\n2014-04-15 02:44:00,99.53\n2014-04-15 02:49:00,99.20200000000001\n2014-04-15 02:54:00,98.91799999999999\n2014-04-15 02:59:00,99.436\n2014-04-15 03:04:00,99.414\n2014-04-15 03:09:00,98.73200000000001\n2014-04-15 03:14:00,99.46\n2014-04-15 03:19:00,99.52799999999999\n2014-04-15 03:24:00,99.57799999999999\n2014-04-15 03:29:00,99.434\n2014-04-15 03:34:00,98.904\n2014-04-15 03:39:00,98.756\n2014-04-15 03:44:00,99.088\n2014-04-15 03:49:00,99.226\n2014-04-15 03:54:00,99.318\n2014-04-15 03:59:00,98.99\n2014-04-15 04:04:00,99.24799999999999\n2014-04-15 04:09:00,99.27\n2014-04-15 04:14:00,99.414\n2014-04-15 04:19:00,98.49799999999999\n2014-04-15 04:24:00,98.896\n2014-04-15 04:29:00,99.20200000000001\n2014-04-15 04:34:00,99.436\n2014-04-15 04:39:00,98.616\n2014-04-15 04:44:00,98.63799999999999\n2014-04-15 04:49:00,99.38799999999999\n2014-04-15 04:54:00,98.428\n2014-04-15 04:59:00,99.32\n2014-04-15 05:04:00,99.296\n2014-04-15 05:09:00,99.366\n2014-04-15 05:14:00,99.038\n2014-04-15 05:19:00,99.484\n2014-04-15 05:24:00,99.67\n2014-04-15 05:29:00,99.296\n2014-04-15 05:34:00,99.20200000000001\n2014-04-15 05:39:00,99.436\n2014-04-15 05:44:00,98.896\n2014-04-15 05:49:00,99.53399999999999\n2014-04-15 05:54:00,99.46\n2014-04-15 05:59:00,99.038\n2014-04-15 06:04:00,99.038\n2014-04-15 06:09:00,99.39200000000001\n2014-04-15 06:14:00,99.178\n2014-04-15 06:19:00,99.20200000000001\n2014-04-15 06:24:00,98.904\n2014-04-15 06:29:00,98.85\n2014-04-15 06:34:00,99.06200000000001\n2014-04-15 06:39:00,98.756\n2014-04-15 06:44:00,99.3\n2014-04-15 06:49:00,99.25\n2014-04-15 06:54:00,99.044\n2014-04-15 06:59:00,98.522\n2014-04-15 07:04:00,98.706\n2014-04-15 07:09:00,99.508\n2014-04-15 07:14:00,99.39\n2014-04-15 07:19:00,99.414\n2014-04-15 07:24:00,99.53\n2014-04-15 07:29:00,99.36399999999999\n2014-04-15 07:34:00,99.042\n2014-04-15 07:39:00,99.27\n2014-04-15 07:44:00,99.436\n2014-04-15 07:49:00,99.132\n2014-04-15 07:54:00,99.32\n2014-04-15 07:59:00,99.24799999999999\n2014-04-15 08:04:00,99.038\n2014-04-15 08:09:00,98.9\n2014-04-15 08:14:00,99.508\n2014-04-15 08:19:00,99.436\n2014-04-15 08:24:00,99.412\n2014-04-15 08:29:00,98.522\n2014-04-15 08:34:00,99.46\n2014-04-15 08:39:00,99.014\n2014-04-15 08:44:00,98.45\n2014-04-15 08:49:00,99.414\n2014-04-15 08:54:00,99.458\n2014-04-15 08:59:00,98.806\n2014-04-15 09:04:00,98.182\n2014-04-15 09:09:00,99.08200000000001\n2014-04-15 09:14:00,98.82600000000001\n2014-04-15 09:19:00,99.34200000000001\n2014-04-15 09:24:00,99.574\n2014-04-15 09:29:00,99.18\n2014-04-15 09:34:00,99.508\n2014-04-15 09:39:00,99.436\n2014-04-15 09:44:00,99.67200000000001\n2014-04-15 09:49:00,99.316\n2014-04-15 09:54:00,98.89399999999999\n2014-04-15 09:59:00,99.32\n2014-04-15 10:04:00,99.67200000000001\n2014-04-15 10:09:00,99.366\n2014-04-15 10:14:00,99.27\n2014-04-15 10:19:00,99.3\n2014-04-15 10:24:00,98.49799999999999\n2014-04-15 10:29:00,98.89399999999999\n2014-04-15 10:34:00,99.53\n2014-04-15 10:39:00,99.39\n2014-04-15 10:44:00,98.96799999999999\n2014-04-15 10:49:00,99.742\n2014-04-15 10:54:00,99.318\n2014-04-15 10:59:00,99.508\n2014-04-15 11:04:00,98.63799999999999\n2014-04-15 11:09:00,99.272\n2014-04-15 11:14:00,99.484\n2014-04-15 11:19:00,99.57799999999999\n2014-04-15 11:24:00,98.82600000000001\n2014-04-15 11:29:00,98.426\n2014-04-15 11:34:00,98.47399999999999\n2014-04-15 11:39:00,99.34200000000001\n2014-04-15 11:44:00,99.67200000000001\n2014-04-15 11:49:00,99.436\n2014-04-15 11:54:00,98.556\n2014-04-15 11:59:00,98.38\n2014-04-15 12:04:00,99.414\n2014-04-15 12:09:00,98.756\n2014-04-15 12:14:00,99.46\n2014-04-15 12:19:00,99.484\n2014-04-15 12:24:00,99.046\n2014-04-15 12:29:00,99.272\n2014-04-15 12:34:00,98.288\n2014-04-15 12:39:00,99.414\n2014-04-15 12:44:00,99.554\n2014-04-15 12:49:00,99.226\n2014-04-15 12:54:00,99.67200000000001\n2014-04-15 12:59:00,99.178\n2014-04-15 13:04:00,98.97200000000001\n2014-04-15 13:09:00,99.598\n2014-04-15 13:14:00,98.66799999999999\n2014-04-15 13:19:00,99.338\n2014-04-15 13:24:00,99.27\n2014-04-15 13:29:00,98.92\n2014-04-15 13:34:00,99.06200000000001\n2014-04-15 13:39:00,99.132\n2014-04-15 13:44:00,99.506\n2014-04-15 13:49:00,99.414\n2014-04-15 13:54:00,99.32\n2014-04-15 13:59:00,99.624\n2014-04-15 14:04:00,98.802\n2014-04-15 14:09:00,99.554\n2014-04-15 14:14:00,98.82600000000001\n2014-04-15 14:19:00,98.78\n2014-04-15 14:24:00,98.964\n2014-04-15 14:29:00,99.20200000000001\n2014-04-15 14:34:00,98.714\n2014-04-15 14:39:00,99.458\n2014-04-15 14:44:00,99.104\n2014-04-15 14:49:00,98.92\n2014-04-15 14:54:00,98.68799999999999\n2014-04-15 14:59:00,99.32\n2014-04-15 15:04:00,99.11\n2014-04-15 15:09:00,98.756\n2014-04-15 15:14:00,98.708\n2014-04-15 15:19:00,98.92\n2014-04-15 15:24:00,99.036\n2014-04-15 15:29:00,99.412\n2014-04-15 15:34:00,98.874\n2014-04-15 15:39:00,99.05799999999999\n2014-04-15 15:44:00,99.53\n2014-04-15 15:49:00,99.25200000000001\n2014-04-15 15:54:00,99.272\n2014-04-15 15:59:00,99.154\n2014-04-15 16:04:00,99.274\n2014-04-15 16:09:00,98.944\n2014-04-15 16:14:00,98.522\n2014-04-15 16:19:00,99.39\n2014-04-15 16:24:00,99.508\n2014-04-15 16:29:00,98.96799999999999\n2014-04-15 16:34:00,99.71799999999999\n2014-04-15 16:39:00,99.20200000000001\n2014-04-15 16:44:00,99.39\n2014-04-15 16:49:00,98.686\n2014-04-15 16:54:00,98.63799999999999\n2014-04-15 16:59:00,98.64\n2014-04-15 17:04:00,99.24799999999999\n2014-04-15 17:09:00,99.226\n2014-04-15 17:14:00,99.24799999999999\n2014-04-15 17:19:00,99.366\n2014-04-15 17:24:00,99.484\n2014-04-15 17:29:00,99.39\n2014-04-15 17:34:00,99.32\n2014-04-15 17:39:00,99.436\n2014-04-15 17:44:00,99.27600000000001\n2014-04-15 17:49:00,98.99\n2014-04-15 17:54:00,98.92200000000001\n2014-04-15 17:59:00,99.24799999999999\n2014-04-15 18:04:00,99.226\n2014-04-15 18:09:00,98.874\n2014-04-15 18:14:00,99.624\n2014-04-15 18:19:00,98.75399999999999\n2014-04-15 18:24:00,99.29799999999999\n2014-04-15 18:29:00,99.20200000000001\n2014-04-15 18:34:00,99.414\n2014-04-15 18:39:00,99.20200000000001\n2014-04-15 18:44:00,99.39\n2014-04-15 18:49:00,98.82600000000001\n2014-04-15 18:54:00,99.04\n2014-04-15 18:59:00,98.99\n2014-04-15 19:04:00,99.366\n2014-04-15 19:09:00,99.38600000000001\n2014-04-15 19:14:00,98.38\n2014-04-15 19:19:00,99.038\n2014-04-15 19:24:00,99.34200000000001\n2014-04-15 19:29:00,99.436\n2014-04-15 19:34:00,99.366\n2014-04-15 19:39:00,99.154\n2014-04-15 19:44:00,99.10799999999999\n2014-04-15 19:49:00,99.084\n2014-04-15 19:54:00,99.154\n2014-04-15 19:59:00,98.92\n2014-04-15 20:04:00,98.78\n2014-04-15 20:09:00,98.802\n2014-04-15 20:14:00,99.39\n2014-04-15 20:19:00,99.272\n2014-04-15 20:24:00,99.46\n2014-04-15 20:29:00,99.178\n2014-04-15 20:34:00,98.662\n2014-04-15 20:39:00,99.272\n2014-04-15 20:44:00,99.20200000000001\n2014-04-15 20:49:00,99.39\n2014-04-15 20:54:00,98.706\n2014-04-15 20:59:00,99.24600000000001\n2014-04-15 21:04:00,99.132\n2014-04-15 21:09:00,98.944\n2014-04-15 21:14:00,99.436\n2014-04-15 21:19:00,98.648\n2014-04-15 21:24:00,98.756\n2014-04-15 21:29:00,99.204\n2014-04-15 21:34:00,99.132\n2014-04-15 21:39:00,99.296\n2014-04-15 21:44:00,99.178\n2014-04-15 21:49:00,99.508\n2014-04-15 21:54:00,98.874\n2014-04-15 21:59:00,98.99\n2014-04-15 22:04:00,99.10799999999999\n2014-04-15 22:09:00,99.152\n2014-04-15 22:14:00,99.13\n2014-04-15 22:19:00,99.13\n2014-04-15 22:24:00,99.554\n2014-04-15 22:29:00,98.286\n2014-04-15 22:34:00,98.286\n2014-04-15 22:39:00,99.624\n2014-04-15 22:44:00,98.848\n2014-04-15 22:49:00,98.88600000000001\n2014-04-15 22:54:00,98.626\n2014-04-15 22:59:00,98.82600000000001\n2014-04-15 23:04:00,98.334\n2014-04-15 23:09:00,99.038\n2014-04-15 23:14:00,99.226\n2014-04-15 23:19:00,99.436\n2014-04-15 23:24:00,99.32\n2014-04-15 23:29:00,99.50399999999999\n2014-04-15 23:34:00,99.624\n2014-04-15 23:39:00,98.756\n2014-04-15 23:44:00,99.32\n2014-04-15 23:49:00,99.414\n2014-04-15 23:54:00,98.544\n2014-04-15 23:59:00,99.67200000000001\n2014-04-16 00:04:00,99.11200000000001\n2014-04-16 00:09:00,97.98200000000001\n2014-04-16 00:14:00,98.522\n2014-04-16 00:19:00,98.31\n2014-04-16 00:24:00,98.334\n2014-04-16 00:29:00,99.53\n2014-04-16 00:34:00,99.43799999999999\n2014-04-16 00:39:00,99.20200000000001\n2014-04-16 00:44:00,98.59200000000001\n2014-04-16 00:49:00,99.088\n2014-04-16 00:54:00,99.32\n2014-04-16 00:59:00,99.156\n2014-04-16 01:04:00,99.24799999999999\n2014-04-16 01:09:00,99.57799999999999\n2014-04-16 01:14:00,98.616\n2014-04-16 01:19:00,97.72399999999999\n2014-04-16 01:24:00,98.78\n2014-04-16 01:29:00,98.404\n2014-04-16 01:34:00,99.6\n2014-04-16 01:39:00,99.036\n2014-04-16 01:44:00,99.67200000000001\n2014-04-16 01:49:00,99.624\n2014-04-16 01:54:00,99.39\n2014-04-16 01:59:00,99.014\n2014-04-16 02:04:00,99.178\n2014-04-16 02:09:00,99.176\n2014-04-16 02:14:00,99.038\n2014-04-16 02:19:00,98.73200000000001\n2014-04-16 02:24:00,98.6\n2014-04-16 02:29:00,99.084\n2014-04-16 02:34:00,99.36399999999999\n2014-04-16 02:39:00,99.24799999999999\n2014-04-16 02:44:00,99.32\n2014-04-16 02:49:00,99.486\n2014-04-16 02:54:00,98.756\n2014-04-16 02:59:00,98.99\n2014-04-16 03:04:00,99.552\n2014-04-16 03:09:00,99.014\n2014-04-16 03:14:00,98.544\n2014-04-16 03:19:00,99.53\n2014-04-16 03:24:00,99.296\n2014-04-16 03:29:00,98.92\n2014-04-16 03:34:00,99.206\n2014-04-16 03:39:00,98.896\n2014-04-16 03:44:00,98.772\n2014-04-16 03:49:00,99.41\n2014-04-16 03:54:00,99.39\n2014-04-16 03:59:00,98.896\n2014-04-16 04:04:00,99.014\n2014-04-16 04:09:00,99.34200000000001\n2014-04-16 04:14:00,99.10600000000001\n2014-04-16 04:19:00,99.162\n2014-04-16 04:24:00,99.10799999999999\n2014-04-16 04:29:00,99.132\n2014-04-16 04:34:00,98.85\n2014-04-16 04:39:00,98.73200000000001\n2014-04-16 04:44:00,99.014\n2014-04-16 04:49:00,98.92399999999999\n2014-04-16 04:54:00,99.038\n2014-04-16 04:59:00,99.038\n2014-04-16 05:04:00,98.82600000000001\n2014-04-16 05:09:00,99.274\n2014-04-16 05:14:00,98.944\n2014-04-16 05:19:00,98.992\n2014-04-16 05:24:00,99.346\n2014-04-16 05:29:00,98.726\n2014-04-16 05:34:00,99.34200000000001\n2014-04-16 05:39:00,98.286\n2014-04-16 05:44:00,98.96799999999999\n2014-04-16 05:49:00,98.35600000000001\n2014-04-16 05:54:00,99.228\n2014-04-16 05:59:00,99.436\n2014-04-16 06:04:00,99.36\n2014-04-16 06:09:00,99.39\n2014-04-16 06:14:00,98.588\n2014-04-16 06:19:00,99.06200000000001\n2014-04-16 06:24:00,99.414\n2014-04-16 06:29:00,99.226\n2014-04-16 06:34:00,98.81\n2014-04-16 06:39:00,99.20200000000001\n2014-04-16 06:44:00,99.20200000000001\n2014-04-16 06:49:00,99.24799999999999\n2014-04-16 06:54:00,98.896\n2014-04-16 06:59:00,98.662\n2014-04-16 07:04:00,99.038\n2014-04-16 07:09:00,99.24799999999999\n2014-04-16 07:14:00,98.758\n2014-04-16 07:19:00,98.334\n2014-04-16 07:24:00,98.20200000000001\n2014-04-16 07:29:00,99.01799999999999\n2014-04-16 07:34:00,99.084\n2014-04-16 07:39:00,99.39\n2014-04-16 07:44:00,98.546\n2014-04-16 07:49:00,99.03399999999999\n2014-04-16 07:54:00,99.304\n2014-04-16 07:59:00,98.662\n2014-04-16 08:04:00,99.038\n2014-04-16 08:09:00,99.296\n2014-04-16 08:14:00,98.59200000000001\n2014-04-16 08:19:00,98.31\n2014-04-16 08:24:00,98.896\n2014-04-16 08:29:00,98.63799999999999\n2014-04-16 08:34:00,99.316\n2014-04-16 08:39:00,99.22399999999999\n2014-04-16 08:44:00,98.896\n2014-04-16 08:49:00,99.366\n2014-04-16 08:54:00,99.226\n2014-04-16 08:59:00,99.24799999999999\n2014-04-16 09:04:00,97.8\n2014-04-16 09:09:00,99.06200000000001\n2014-04-16 09:14:00,99.344\n2014-04-16 09:19:00,98.85\n2014-04-16 09:24:00,99.132\n2014-04-16 09:29:00,99.20200000000001\n2014-04-16 09:34:00,99.412\n2014-04-16 09:39:00,99.2\n2014-04-16 09:44:00,99.694\n2014-04-16 09:49:00,99.06200000000001\n2014-04-16 09:54:00,99.436\n2014-04-16 09:59:00,98.47399999999999\n2014-04-16 10:04:00,98.764\n2014-04-16 10:09:00,99.014\n2014-04-16 10:14:00,98.96799999999999\n2014-04-16 10:19:00,99.04\n2014-04-16 10:24:00,98.052\n2014-04-16 10:29:00,99.05799999999999\n2014-04-16 10:34:00,98.802\n2014-04-16 10:39:00,98.59200000000001\n2014-04-16 10:44:00,97.27600000000001\n2014-04-16 10:49:00,98.286\n2014-04-16 10:54:00,99.27\n2014-04-16 10:59:00,98.788\n2014-04-16 11:04:00,97.98200000000001\n2014-04-16 11:09:00,98.83\n2014-04-16 11:14:00,98.49600000000001\n2014-04-16 11:19:00,98.712\n2014-04-16 11:24:00,99.46\n2014-04-16 11:29:00,98.686\n2014-04-16 11:34:00,98.664\n2014-04-16 11:39:00,99.296\n2014-04-16 11:44:00,98.428\n2014-04-16 11:49:00,99.296\n2014-04-16 11:54:00,99.154\n2014-04-16 11:59:00,99.038\n2014-04-16 12:04:00,99.34200000000001\n2014-04-16 12:09:00,99.084\n2014-04-16 12:14:00,99.014\n2014-04-16 12:19:00,99.366\n2014-04-16 12:24:00,98.82600000000001\n2014-04-16 12:29:00,98.42399999999999\n2014-04-16 12:34:00,98.69\n2014-04-16 12:39:00,99.132\n2014-04-16 12:44:00,98.96799999999999\n2014-04-16 12:49:00,98.944\n2014-04-16 12:54:00,98.92\n2014-04-16 12:59:00,99.484\n2014-04-16 13:04:00,99.366\n2014-04-16 13:09:00,98.756\n2014-04-16 13:14:00,98.756\n2014-04-16 13:19:00,99.04\n2014-04-16 13:24:00,98.38\n2014-04-16 13:29:00,99.226\n2014-04-16 13:34:00,98.78\n2014-04-16 13:39:00,98.89399999999999\n2014-04-16 13:44:00,98.74\n2014-04-16 13:49:00,98.47399999999999\n2014-04-16 13:54:00,98.572\n2014-04-16 13:59:00,99.084\n2014-04-16 14:04:00,97.488\n2014-04-16 14:09:00,99.226\n2014-04-16 14:14:00,98.99\n2014-04-16 14:19:00,99.296\n2014-04-16 14:24:00,99.06200000000001\n2014-04-16 14:29:00,99.434\n2014-04-16 14:34:00,99.132\n2014-04-16 14:39:00,99.24799999999999\n2014-04-16 14:44:00,98.552\n2014-04-16 14:49:00,99.22200000000001\n"
  },
  {
    "path": "workspace/anomaly_detector/datasets/selected/level_change/grok_asg_anomaly.csv",
    "content": "timestamp,value\n2014-01-16 00:00:00,33.5573\n2014-01-16 00:05:00,33.446\n2014-01-16 00:10:00,33.4447\n2014-01-16 00:15:00,33.3333\n2014-01-16 00:20:00,33.4447\n2014-01-16 00:25:00,33.4447\n2014-01-16 00:30:00,33.446\n2014-01-16 00:35:00,33.4427\n2014-01-16 00:40:00,33.3333\n2014-01-16 00:45:00,33.554\n2014-01-16 00:50:00,33.3333\n2014-01-16 00:55:00,33.4427\n2014-01-16 01:00:00,33.4427\n2014-01-16 01:05:00,33.5573\n2014-01-16 01:10:00,33.3333\n2014-01-16 01:15:00,33.4447\n2014-01-16 01:20:00,33.446\n2014-01-16 01:25:00,33.3333\n2014-01-16 01:30:00,33.5553\n2014-01-16 01:35:00,33.3333\n2014-01-16 01:40:00,33.6647\n2014-01-16 01:45:00,33.3333\n2014-01-16 01:50:00,33.3333\n2014-01-16 01:55:00,33.5587\n2014-01-16 02:00:00,33.5587\n2014-01-16 02:05:00,33.3333\n2014-01-16 02:10:00,33.4447\n2014-01-16 02:15:00,33.4427\n2014-01-16 02:20:00,33.3333\n2014-01-16 02:25:00,33.554\n2014-01-16 02:30:00,33.3333\n2014-01-16 02:35:00,33.4447\n2014-01-16 02:40:00,33.4447\n2014-01-16 02:45:00,33.446\n2014-01-16 02:50:00,33.4427\n2014-01-16 02:55:00,33.3333\n2014-01-16 03:00:00,33.5587\n2014-01-16 03:05:00,35.222\n2014-01-16 03:10:00,33.3333\n2014-01-16 03:15:00,33.3333\n2014-01-16 03:20:00,33.5553\n2014-01-16 03:25:00,33.3333\n2014-01-16 03:30:00,35.2507\n2014-01-16 03:35:00,33.3333\n2014-01-16 03:40:00,33.4447\n2014-01-16 03:45:00,33.4447\n2014-01-16 03:50:00,33.4447\n2014-01-16 03:55:00,33.4447\n2014-01-16 04:00:00,33.554\n2014-01-16 04:05:00,33.3333\n2014-01-16 04:10:00,33.4427\n2014-01-16 04:15:00,33.4447\n2014-01-16 04:20:00,33.5573\n2014-01-16 04:25:00,33.3333\n2014-01-16 04:30:00,33.4427\n2014-01-16 04:35:00,33.4447\n2014-01-16 04:40:00,33.4427\n2014-01-16 04:45:00,33.446\n2014-01-16 04:50:00,33.3333\n2014-01-16 04:55:00,33.4427\n2014-01-16 05:00:00,33.4427\n2014-01-16 05:05:00,33.5573\n2014-01-16 05:10:00,33.3333\n2014-01-16 05:15:00,33.446\n2014-01-16 05:20:00,33.446\n2014-01-16 05:25:00,33.4447\n2014-01-16 05:30:00,33.446\n2014-01-16 05:35:00,33.3333\n2014-01-16 05:40:00,33.554\n2014-01-16 05:45:00,33.3333\n2014-01-16 05:50:00,33.5553\n2014-01-16 05:55:00,33.3333\n2014-01-16 06:00:00,33.554\n2014-01-16 06:05:00,33.3333\n2014-01-16 06:10:00,33.5553\n2014-01-16 06:15:00,33.3333\n2014-01-16 06:20:00,33.3333\n2014-01-16 06:25:00,33.5553\n2014-01-16 06:30:00,33.3333\n2014-01-16 06:35:00,33.4447\n2014-01-16 06:40:00,33.4427\n2014-01-16 06:45:00,33.4447\n2014-01-16 06:50:00,33.446\n2014-01-16 06:55:00,33.3333\n2014-01-16 07:00:00,33.556\n2014-01-16 07:05:00,33.446\n2014-01-16 07:10:00,33.4447\n2014-01-16 07:15:00,33.3333\n2014-01-16 07:20:00,33.446\n2014-01-16 07:25:00,33.4427\n2014-01-16 07:30:00,33.4447\n2014-01-16 07:35:00,33.446\n2014-01-16 07:40:00,33.446\n2014-01-16 07:45:00,33.3333\n2014-01-16 07:50:00,33.554\n2014-01-16 07:55:00,33.3333\n2014-01-16 08:00:00,33.5553\n2014-01-16 08:05:00,33.4447\n2014-01-16 08:10:00,33.5573\n2014-01-16 08:15:00,33.3333\n2014-01-16 08:20:00,33.4447\n2014-01-16 08:25:00,33.4427\n2014-01-16 08:30:00,33.3333\n2014-01-16 08:35:00,33.556\n2014-01-16 08:40:00,33.3333\n2014-01-16 08:45:00,33.446\n2014-01-16 08:50:00,33.446\n2014-01-16 08:55:00,33.3333\n2014-01-16 09:00:00,33.5573\n2014-01-16 09:05:00,33.446\n2014-01-16 09:10:00,33.4427\n2014-01-16 09:15:00,33.3333\n2014-01-16 09:20:00,33.5587\n2014-01-16 09:25:00,33.3333\n2014-01-16 09:30:00,33.556\n2014-01-16 09:35:00,33.3333\n2014-01-16 09:40:00,33.3333\n2014-01-16 09:45:00,33.5573\n2014-01-16 09:50:00,33.3333\n2014-01-16 09:55:00,33.554\n2014-01-16 10:00:00,33.3333\n2014-01-16 10:05:00,33.556\n2014-01-16 10:10:00,33.3333\n2014-01-16 10:15:00,33.554\n2014-01-16 10:20:00,33.3333\n2014-01-16 10:25:00,33.3333\n2014-01-16 10:30:00,33.5587\n2014-01-16 10:35:00,33.3333\n2014-01-16 10:40:00,33.556\n2014-01-16 10:45:00,33.3333\n2014-01-16 10:50:00,33.3333\n2014-01-16 10:55:00,33.672\n2014-01-16 11:00:00,33.554\n2014-01-16 11:05:00,33.3333\n2014-01-16 11:10:00,33.4427\n2014-01-16 11:15:00,34.7767\n2014-01-16 11:20:00,34.452\n2014-01-16 11:25:00,34.2133\n2014-01-16 11:30:00,33.4427\n2014-01-16 11:35:00,33.4427\n2014-01-16 11:40:00,33.3333\n2014-01-16 11:45:00,33.4447\n2014-01-16 11:50:00,33.4427\n2014-01-16 11:55:00,33.4447\n2014-01-16 12:00:00,33.552\n2014-01-16 12:05:00,33.4447\n2014-01-16 12:10:00,33.3333\n2014-01-16 12:15:00,33.552\n2014-01-16 12:20:00,33.3333\n2014-01-16 12:25:00,33.5573\n2014-01-16 12:30:00,33.3333\n2014-01-16 12:35:00,33.3333\n2014-01-16 12:40:00,33.554\n2014-01-16 12:45:00,33.3333\n2014-01-16 12:50:00,33.554\n2014-01-16 12:55:00,33.3333\n2014-01-16 13:00:00,33.552\n2014-01-16 13:05:00,33.3333\n2014-01-16 13:10:00,33.552\n2014-01-16 13:15:00,33.3333\n2014-01-16 13:20:00,33.4427\n2014-01-16 13:25:00,33.4447\n2014-01-16 13:30:00,33.446\n2014-01-16 13:35:00,33.4427\n2014-01-16 13:40:00,33.3333\n2014-01-16 13:45:00,33.4447\n2014-01-16 13:50:00,33.446\n2014-01-16 13:55:00,33.4427\n2014-01-16 14:00:00,33.4447\n2014-01-16 14:05:00,33.4447\n2014-01-16 14:10:00,33.4427\n2014-01-16 14:15:00,33.8887\n2014-01-16 14:20:00,33.8833\n2014-01-16 14:25:00,33.3333\n2014-01-16 14:30:00,33.5573\n2014-01-16 14:35:00,33.3333\n2014-01-16 14:40:00,33.4447\n2014-01-16 14:45:00,33.446\n2014-01-16 14:50:00,33.446\n2014-01-16 14:55:00,33.446\n2014-01-16 15:00:00,33.4427\n2014-01-16 15:05:00,33.4427\n2014-01-16 15:10:00,33.446\n2014-01-16 15:15:00,33.3333\n2014-01-16 15:20:00,33.4447\n2014-01-16 15:25:00,33.4427\n2014-01-16 15:30:00,33.446\n2014-01-16 15:35:00,33.446\n2014-01-16 15:40:00,33.3333\n2014-01-16 15:45:00,33.5573\n2014-01-16 15:50:00,33.3333\n2014-01-16 15:55:00,33.446\n2014-01-16 16:00:00,33.446\n2014-01-16 16:05:00,33.446\n2014-01-16 16:10:00,33.4427\n2014-01-16 16:15:00,33.446\n2014-01-16 16:20:00,33.4447\n2014-01-16 16:25:00,33.3333\n2014-01-16 16:30:00,33.5587\n2014-01-16 16:35:00,33.3333\n2014-01-16 16:40:00,33.4447\n2014-01-16 16:45:00,33.4427\n2014-01-16 16:50:00,33.3333\n2014-01-16 16:55:00,33.552\n2014-01-16 17:00:00,33.4447\n2014-01-16 17:05:00,33.4427\n2014-01-16 17:10:00,33.3333\n2014-01-16 17:15:00,33.5573\n2014-01-16 17:20:00,33.3333\n2014-01-16 17:25:00,33.556\n2014-01-16 17:30:00,33.3333\n2014-01-16 17:35:00,33.3333\n2014-01-16 17:40:00,33.668\n2014-01-16 17:45:00,33.3333\n2014-01-16 17:50:00,33.5553\n2014-01-16 17:55:00,33.3333\n2014-01-16 18:00:00,33.552\n2014-01-16 18:05:00,33.3333\n2014-01-16 18:10:00,33.556\n2014-01-16 18:15:00,33.3333\n2014-01-16 18:20:00,33.556\n2014-01-16 18:25:00,33.3333\n2014-01-16 18:30:00,33.4447\n2014-01-16 18:35:00,33.4427\n2014-01-16 18:40:00,9.090910000000001\n2014-01-16 18:45:00,28.8093\n2014-01-16 18:50:00,33.3333\n2014-01-16 18:55:00,33.4427\n2014-01-16 19:00:00,35.3187\n2014-01-16 19:05:00,34.3413\n2014-01-16 19:10:00,35.1113\n2014-01-16 19:15:00,33.446\n2014-01-16 19:20:00,33.446\n2014-01-16 19:25:00,33.3333\n2014-01-16 19:30:00,33.5553\n2014-01-16 19:35:00,33.3333\n2014-01-16 19:40:00,33.4427\n2014-01-16 19:45:00,33.4447\n2014-01-16 19:50:00,33.4427\n2014-01-16 19:55:00,33.4447\n2014-01-16 20:00:00,33.552\n2014-01-16 20:05:00,33.3333\n2014-01-16 20:10:00,33.4447\n2014-01-16 20:15:00,33.4447\n2014-01-16 20:20:00,33.446\n2014-01-16 20:25:00,34.2313\n2014-01-16 20:30:00,33.5553\n2014-01-16 20:35:00,33.3333\n2014-01-16 20:40:00,33.4447\n2014-01-16 20:45:00,33.4427\n2014-01-16 20:50:00,33.4447\n2014-01-16 20:55:00,33.4447\n2014-01-16 21:00:00,33.4447\n2014-01-16 21:05:00,33.4447\n2014-01-16 21:10:00,33.4427\n2014-01-16 21:15:00,33.4427\n2014-01-16 21:20:00,33.3333\n2014-01-16 21:25:00,33.4427\n2014-01-16 21:30:00,33.4427\n2014-01-16 21:35:00,33.4427\n2014-01-16 21:40:00,33.4447\n2014-01-16 21:45:00,33.3333\n2014-01-16 21:50:00,33.554\n2014-01-16 21:55:00,33.3333\n2014-01-16 22:00:00,33.5573\n2014-01-16 22:05:00,33.3333\n2014-01-16 22:10:00,33.5553\n2014-01-16 22:15:00,33.3333\n2014-01-16 22:20:00,33.4427\n2014-01-16 22:25:00,33.4427\n2014-01-16 22:30:00,33.3333\n2014-01-16 22:35:00,33.5573\n2014-01-16 22:40:00,33.446\n2014-01-16 22:45:00,33.4447\n2014-01-16 22:50:00,33.446\n2014-01-16 22:55:00,33.3333\n2014-01-16 23:00:00,33.5587\n2014-01-16 23:05:00,33.4447\n2014-01-16 23:10:00,33.4447\n2014-01-16 23:15:00,33.4427\n2014-01-16 23:20:00,33.446\n2014-01-16 23:25:00,33.3333\n2014-01-16 23:30:00,33.554\n2014-01-16 23:35:00,33.3333\n2014-01-16 23:40:00,35.6707\n2014-01-16 23:45:00,33.4427\n2014-01-16 23:50:00,33.4447\n2014-01-16 23:55:00,33.446\n2014-01-17 00:00:00,33.552\n2014-01-17 00:05:00,33.3333\n2014-01-17 00:10:00,33.554\n2014-01-17 00:15:00,33.3333\n2014-01-17 00:20:00,33.4447\n2014-01-17 00:25:00,33.446\n2014-01-17 00:30:00,33.3333\n2014-01-17 00:35:00,33.556\n2014-01-17 00:40:00,33.3333\n2014-01-17 00:45:00,33.5573\n2014-01-17 00:50:00,33.3333\n2014-01-17 00:55:00,33.3333\n2014-01-17 01:00:00,33.5573\n2014-01-17 01:05:00,33.554\n2014-01-17 01:10:00,33.3333\n2014-01-17 01:15:00,33.5553\n2014-01-17 01:20:00,33.3333\n2014-01-17 01:25:00,33.3333\n2014-01-17 01:30:00,33.554\n2014-01-17 01:35:00,33.3333\n2014-01-17 01:40:00,34.124\n2014-01-17 01:45:00,37.664\n2014-01-17 01:50:00,37.8887\n2014-01-17 01:55:00,37.6533\n2014-01-17 02:00:00,34.3427\n2014-01-17 02:05:00,33.3333\n2014-01-17 02:10:00,33.556\n2014-01-17 02:15:00,33.3333\n2014-01-17 02:20:00,37.6687\n2014-01-17 02:25:00,38.5593\n2014-01-17 02:30:00,38.328\n2014-01-17 02:35:00,33.6647\n2014-01-17 02:40:00,33.3333\n2014-01-17 02:45:00,33.4427\n2014-01-17 02:50:00,33.446\n2014-01-17 02:55:00,33.4447\n2014-01-17 03:00:00,33.4447\n2014-01-17 03:05:00,35.588\n2014-01-17 03:10:00,33.3333\n2014-01-17 03:15:00,33.554\n2014-01-17 03:20:00,33.3333\n2014-01-17 03:25:00,35.3333\n2014-01-17 03:30:00,33.5553\n2014-01-17 03:35:00,33.3333\n2014-01-17 03:40:00,33.554\n2014-01-17 03:45:00,33.3333\n2014-01-17 03:50:00,33.556\n2014-01-17 03:55:00,33.4447\n2014-01-17 04:00:00,33.5573\n2014-01-17 04:05:00,33.3333\n2014-01-17 04:10:00,33.446\n2014-01-17 04:15:00,33.446\n2014-01-17 04:20:00,33.3333\n2014-01-17 04:25:00,33.4447\n2014-01-17 04:30:00,33.446\n2014-01-17 04:35:00,33.4447\n2014-01-17 04:40:00,33.4447\n2014-01-17 04:45:00,33.446\n2014-01-17 04:50:00,33.3333\n2014-01-17 04:55:00,33.4447\n2014-01-17 05:00:00,33.554\n2014-01-17 05:05:00,33.446\n2014-01-17 05:10:00,33.3333\n2014-01-17 05:15:00,33.446\n2014-01-17 05:20:00,33.4427\n2014-01-17 05:25:00,33.4447\n2014-01-17 05:30:00,33.446\n2014-01-17 05:35:00,33.3333\n2014-01-17 05:40:00,33.554\n2014-01-17 05:45:00,33.3333\n2014-01-17 05:50:00,33.4427\n2014-01-17 05:55:00,33.4447\n2014-01-17 06:00:00,33.5573\n2014-01-17 06:05:00,33.3333\n2014-01-17 06:10:00,33.4427\n2014-01-17 06:15:00,33.4447\n2014-01-17 06:20:00,33.3333\n2014-01-17 06:25:00,33.556\n2014-01-17 06:30:00,33.3333\n2014-01-17 06:35:00,33.4447\n2014-01-17 06:40:00,33.4447\n2014-01-17 06:45:00,33.3333\n2014-01-17 06:50:00,33.556\n2014-01-17 06:55:00,33.3333\n2014-01-17 07:00:00,33.554\n2014-01-17 07:05:00,33.3333\n2014-01-17 07:10:00,33.554\n2014-01-17 07:15:00,33.3333\n2014-01-17 07:20:00,33.4427\n2014-01-17 07:25:00,33.446\n2014-01-17 07:30:00,33.3333\n2014-01-17 07:35:00,33.5573\n2014-01-17 07:40:00,33.4427\n2014-01-17 07:45:00,33.556\n2014-01-17 07:50:00,33.3333\n2014-01-17 07:55:00,33.3333\n2014-01-17 08:00:00,33.5573\n2014-01-17 08:05:00,33.556\n2014-01-17 08:10:00,33.3333\n2014-01-17 08:15:00,33.554\n2014-01-17 08:20:00,33.3333\n2014-01-17 08:25:00,33.3333\n2014-01-17 08:30:00,33.554\n2014-01-17 08:35:00,33.3333\n2014-01-17 08:40:00,33.5553\n2014-01-17 08:45:00,33.3333\n2014-01-17 08:50:00,33.4427\n2014-01-17 08:55:00,33.4427\n2014-01-17 09:00:00,33.4447\n2014-01-17 09:05:00,33.446\n2014-01-17 09:10:00,33.4447\n2014-01-17 09:15:00,33.446\n2014-01-17 09:20:00,33.446\n2014-01-17 09:25:00,33.3333\n2014-01-17 09:30:00,33.446\n2014-01-17 09:35:00,33.4427\n2014-01-17 09:40:00,33.4447\n2014-01-17 09:45:00,33.4447\n2014-01-17 09:50:00,33.4447\n2014-01-17 09:55:00,33.4427\n2014-01-17 10:00:00,33.4447\n2014-01-17 10:05:00,33.4427\n2014-01-17 10:10:00,33.4447\n2014-01-17 10:15:00,33.4427\n2014-01-17 10:20:00,33.3333\n2014-01-17 10:25:00,33.4427\n2014-01-17 10:30:00,33.4447\n2014-01-17 10:35:00,33.4447\n2014-01-17 10:40:00,33.4447\n2014-01-17 10:45:00,33.4447\n2014-01-17 10:50:00,33.4427\n2014-01-17 10:55:00,33.3333\n2014-01-17 11:00:00,33.5573\n2014-01-17 11:05:00,33.4447\n2014-01-17 11:10:00,33.446\n2014-01-17 11:15:00,33.3333\n2014-01-17 11:20:00,33.4447\n2014-01-17 11:25:00,33.4447\n2014-01-17 11:30:00,33.4427\n2014-01-17 11:35:00,33.446\n2014-01-17 11:40:00,33.3333\n2014-01-17 11:45:00,33.556\n2014-01-17 11:50:00,33.3333\n2014-01-17 11:55:00,33.556\n2014-01-17 12:00:00,33.4447\n2014-01-17 12:05:00,33.4447\n2014-01-17 12:10:00,33.446\n2014-01-17 12:15:00,33.4427\n2014-01-17 12:20:00,33.3333\n2014-01-17 12:25:00,33.4427\n2014-01-17 12:30:00,33.4427\n2014-01-17 12:35:00,33.4427\n2014-01-17 12:40:00,33.4427\n2014-01-17 12:45:00,33.3333\n2014-01-17 12:50:00,33.552\n2014-01-17 12:55:00,33.3333\n2014-01-17 13:00:00,33.5553\n2014-01-17 13:05:00,33.4427\n2014-01-17 13:10:00,33.3333\n2014-01-17 13:15:00,33.5553\n2014-01-17 13:20:00,33.3333\n2014-01-17 13:25:00,35.6633\n2014-01-17 13:30:00,33.4447\n2014-01-17 13:35:00,33.4427\n2014-01-17 13:40:00,33.446\n2014-01-17 13:45:00,33.4447\n2014-01-17 13:50:00,33.3333\n2014-01-17 13:55:00,33.4447\n2014-01-17 14:00:00,33.556\n2014-01-17 14:05:00,33.446\n2014-01-17 14:10:00,33.3333\n2014-01-17 14:15:00,33.4447\n2014-01-17 14:20:00,33.4447\n2014-01-17 14:25:00,33.446\n2014-01-17 14:30:00,33.4447\n2014-01-17 14:35:00,33.3333\n2014-01-17 14:40:00,33.5573\n2014-01-17 14:45:00,33.3333\n2014-01-17 14:50:00,33.4447\n2014-01-17 14:55:00,33.4447\n2014-01-17 15:00:00,33.554\n2014-01-17 15:05:00,33.3333\n2014-01-17 15:10:00,33.4427\n2014-01-17 15:15:00,33.4427\n2014-01-17 15:20:00,33.4427\n2014-01-17 15:25:00,33.4427\n2014-01-17 15:30:00,33.4447\n2014-01-17 15:35:00,33.5553\n2014-01-17 15:40:00,33.3333\n2014-01-17 15:45:00,33.4447\n2014-01-17 15:50:00,33.4447\n2014-01-17 15:55:00,33.446\n2014-01-17 16:00:00,33.4427\n2014-01-17 16:05:00,33.556\n2014-01-17 16:10:00,33.3333\n2014-01-17 16:15:00,33.556\n2014-01-17 16:20:00,33.3333\n2014-01-17 16:25:00,33.3333\n2014-01-17 16:30:00,33.5573\n2014-01-17 16:35:00,33.3333\n2014-01-17 16:40:00,33.5573\n2014-01-17 16:45:00,33.3333\n2014-01-17 16:50:00,33.4427\n2014-01-17 16:55:00,33.4447\n2014-01-17 17:00:00,33.5573\n2014-01-17 17:05:00,33.3333\n2014-01-17 17:10:00,33.4427\n2014-01-17 17:15:00,33.4447\n2014-01-17 17:20:00,33.4447\n2014-01-17 17:25:00,33.4447\n2014-01-17 17:30:00,33.4447\n2014-01-17 17:35:00,33.3333\n2014-01-17 17:40:00,33.446\n2014-01-17 17:45:00,33.4427\n2014-01-17 17:50:00,33.4447\n2014-01-17 17:55:00,33.446\n2014-01-17 18:00:00,33.4447\n2014-01-17 18:05:00,33.4447\n2014-01-17 18:10:00,33.446\n2014-01-17 18:15:00,33.5573\n2014-01-17 18:20:00,33.4427\n2014-01-17 18:25:00,33.3333\n2014-01-17 18:30:00,33.446\n2014-01-17 18:35:00,33.4447\n2014-01-17 18:40:00,33.4447\n2014-01-17 18:45:00,33.3333\n2014-01-17 18:50:00,33.5553\n2014-01-17 18:55:00,33.3333\n2014-01-17 19:00:00,33.556\n2014-01-17 19:05:00,33.3333\n2014-01-17 19:10:00,33.554\n2014-01-17 19:15:00,36.6713\n2014-01-17 19:20:00,34.778\n2014-01-17 19:25:00,33.3333\n2014-01-17 19:30:00,33.5553\n2014-01-17 19:35:00,33.3333\n2014-01-17 19:40:00,33.5587\n2014-01-17 19:45:00,33.3333\n2014-01-17 19:50:00,33.4427\n2014-01-17 19:55:00,33.4447\n2014-01-17 20:00:00,33.5553\n2014-01-17 20:05:00,33.3333\n2014-01-17 20:10:00,33.3333\n2014-01-17 20:15:00,33.556\n2014-01-17 20:20:00,33.3333\n2014-01-17 20:25:00,33.556\n2014-01-17 20:30:00,33.3333\n2014-01-17 20:35:00,33.4447\n2014-01-17 20:40:00,33.446\n2014-01-17 20:45:00,33.4447\n2014-01-17 20:50:00,33.446\n2014-01-17 20:55:00,33.3333\n2014-01-17 21:00:00,33.5553\n2014-01-17 21:05:00,33.446\n2014-01-17 21:10:00,33.4427\n2014-01-17 21:15:00,33.3333\n2014-01-17 21:20:00,33.446\n2014-01-17 21:25:00,33.446\n2014-01-17 21:30:00,33.446\n2014-01-17 21:35:00,33.4447\n2014-01-17 21:40:00,33.446\n2014-01-17 21:45:00,33.3333\n2014-01-17 21:50:00,33.4427\n2014-01-17 21:55:00,33.4447\n2014-01-17 22:00:00,33.556\n2014-01-17 22:05:00,33.3333\n2014-01-17 22:10:00,33.4447\n2014-01-17 22:15:00,33.446\n2014-01-17 22:20:00,33.4427\n2014-01-17 22:25:00,33.4447\n2014-01-17 22:30:00,33.3333\n2014-01-17 22:35:00,34.8907\n2014-01-17 22:40:00,35.5727\n2014-01-17 22:45:00,33.446\n2014-01-17 22:50:00,33.3333\n2014-01-17 22:55:00,33.4447\n2014-01-17 23:00:00,33.5573\n2014-01-17 23:05:00,33.4447\n2014-01-17 23:10:00,33.4447\n2014-01-17 23:15:00,33.3333\n2014-01-17 23:20:00,33.4447\n2014-01-17 23:25:00,33.4447\n2014-01-17 23:30:00,33.4447\n2014-01-17 23:35:00,33.446\n2014-01-17 23:40:00,33.4447\n2014-01-17 23:45:00,33.3333\n2014-01-17 23:50:00,33.4447\n2014-01-17 23:55:00,33.4427\n2014-01-18 00:00:00,33.556\n2014-01-18 00:05:00,33.3333\n2014-01-18 00:10:00,33.556\n2014-01-18 00:15:00,33.3333\n2014-01-18 00:20:00,33.446\n2014-01-18 00:25:00,33.446\n2014-01-18 00:30:00,33.3333\n2014-01-18 00:35:00,33.5573\n2014-01-18 00:40:00,33.3333\n2014-01-18 00:45:00,33.554\n2014-01-18 00:50:00,33.3333\n2014-01-18 00:55:00,33.3333\n2014-01-18 01:00:00,33.554\n2014-01-18 01:05:00,33.5573\n2014-01-18 01:10:00,33.3333\n2014-01-18 01:15:00,33.4447\n2014-01-18 01:20:00,33.4447\n2014-01-18 01:25:00,33.4447\n2014-01-18 01:30:00,33.7833\n2014-01-18 01:35:00,33.5587\n2014-01-18 01:40:00,33.3333\n2014-01-18 01:45:00,33.4447\n2014-01-18 01:50:00,33.4447\n2014-01-18 01:55:00,33.3333\n2014-01-18 02:00:00,33.5573\n2014-01-18 02:05:00,33.5573\n2014-01-18 02:10:00,33.3333\n2014-01-18 02:15:00,33.3333\n2014-01-18 02:20:00,33.554\n2014-01-18 02:25:00,33.3333\n2014-01-18 02:30:00,33.5587\n2014-01-18 02:35:00,33.3333\n2014-01-18 02:40:00,33.446\n2014-01-18 02:45:00,33.4447\n2014-01-18 02:50:00,33.4427\n2014-01-18 02:55:00,33.554\n2014-01-18 03:00:00,33.554\n2014-01-18 03:05:00,35.1113\n2014-01-18 03:10:00,33.4447\n2014-01-18 03:15:00,33.4447\n2014-01-18 03:20:00,33.3333\n2014-01-18 03:25:00,35.1947\n2014-01-18 03:30:00,33.4427\n2014-01-18 03:35:00,33.4427\n2014-01-18 03:40:00,33.3333\n2014-01-18 03:45:00,33.4427\n2014-01-18 03:50:00,33.4427\n2014-01-18 03:55:00,33.4447\n2014-01-18 04:00:00,33.5573\n2014-01-18 04:05:00,34.5553\n2014-01-18 04:10:00,35.328\n2014-01-18 04:15:00,34.774\n2014-01-18 04:20:00,34.6613\n2014-01-18 04:25:00,33.556\n2014-01-18 04:30:00,33.3333\n2014-01-18 04:35:00,33.3333\n2014-01-18 04:40:00,33.67\n2014-01-18 04:45:00,33.3333\n2014-01-18 04:50:00,33.4447\n2014-01-18 04:55:00,33.4447\n2014-01-18 05:00:00,33.554\n2014-01-18 05:05:00,33.3333\n2014-01-18 05:10:00,33.4447\n2014-01-18 05:15:00,33.4447\n2014-01-18 05:20:00,33.3333\n2014-01-18 05:25:00,33.554\n2014-01-18 05:30:00,33.3333\n2014-01-18 05:35:00,33.446\n2014-01-18 05:40:00,33.446\n2014-01-18 05:45:00,33.4447\n2014-01-18 05:50:00,33.4447\n2014-01-18 05:55:00,33.3333\n2014-01-18 06:00:00,33.552\n2014-01-18 06:05:00,33.4427\n2014-01-18 06:10:00,33.446\n2014-01-18 06:15:00,33.3333\n2014-01-18 06:20:00,33.4447\n2014-01-18 06:25:00,33.4447\n2014-01-18 06:30:00,33.4447\n2014-01-18 06:35:00,33.446\n2014-01-18 06:40:00,33.446\n2014-01-18 06:45:00,33.3333\n2014-01-18 06:50:00,33.446\n2014-01-18 06:55:00,33.4447\n2014-01-18 07:00:00,33.5573\n2014-01-18 07:05:00,33.4427\n2014-01-18 07:10:00,33.3333\n2014-01-18 07:15:00,33.4427\n2014-01-18 07:20:00,33.4447\n2014-01-18 07:25:00,33.446\n2014-01-18 07:30:00,33.3333\n2014-01-18 07:35:00,33.5573\n2014-01-18 07:40:00,33.3333\n2014-01-18 07:45:00,33.4447\n2014-01-18 07:50:00,33.4447\n2014-01-18 07:55:00,33.3333\n2014-01-18 08:00:00,33.5553\n2014-01-18 08:05:00,33.4447\n2014-01-18 08:10:00,33.446\n2014-01-18 08:15:00,33.4447\n2014-01-18 08:20:00,33.4447\n2014-01-18 08:25:00,33.3333\n2014-01-18 08:30:00,33.554\n2014-01-18 08:35:00,33.3333\n2014-01-18 08:40:00,33.446\n2014-01-18 08:45:00,33.4427\n2014-01-18 08:50:00,33.3333\n2014-01-18 08:55:00,33.5573\n2014-01-18 09:00:00,33.4447\n2014-01-18 09:05:00,33.4447\n2014-01-18 09:10:00,33.3333\n2014-01-18 09:15:00,33.552\n2014-01-18 09:20:00,33.3333\n2014-01-18 09:25:00,33.4427\n2014-01-18 09:30:00,33.4427\n2014-01-18 09:35:00,33.3333\n2014-01-18 09:40:00,33.5553\n2014-01-18 09:45:00,33.3333\n2014-01-18 09:50:00,33.6647\n2014-01-18 09:55:00,33.4427\n2014-01-18 10:00:00,33.554\n2014-01-18 10:05:00,33.3333\n2014-01-18 10:10:00,33.446\n2014-01-18 10:15:00,33.4427\n2014-01-18 10:20:00,33.3333\n2014-01-18 10:25:00,33.552\n2014-01-18 10:30:00,33.3333\n2014-01-18 10:35:00,33.4447\n2014-01-18 10:40:00,33.446\n2014-01-18 10:45:00,33.3333\n2014-01-18 10:50:00,33.554\n2014-01-18 10:55:00,33.3333\n2014-01-18 11:00:00,33.5573\n2014-01-18 11:05:00,33.3333\n2014-01-18 11:10:00,33.5587\n2014-01-18 11:15:00,33.3333\n2014-01-18 11:20:00,33.4427\n2014-01-18 11:25:00,33.4427\n2014-01-18 11:30:00,33.4447\n2014-01-18 11:35:00,33.4427\n2014-01-18 11:40:00,33.3333\n2014-01-18 11:45:00,33.4447\n2014-01-18 11:50:00,33.4447\n2014-01-18 11:55:00,33.4427\n2014-01-18 12:00:00,33.4427\n2014-01-18 12:05:00,33.4447\n2014-01-18 12:10:00,33.4427\n2014-01-18 12:15:00,33.4447\n2014-01-18 12:20:00,33.4427\n2014-01-18 12:25:00,33.3333\n2014-01-18 12:30:00,33.552\n2014-01-18 12:35:00,33.3333\n2014-01-18 12:40:00,33.446\n2014-01-18 12:45:00,33.446\n2014-01-18 12:50:00,33.446\n2014-01-18 12:55:00,33.446\n2014-01-18 13:00:00,33.4427\n2014-01-18 13:05:00,33.4447\n2014-01-18 13:10:00,33.4447\n2014-01-18 13:15:00,33.4447\n2014-01-18 13:20:00,33.446\n2014-01-18 13:25:00,33.3333\n2014-01-18 13:30:00,33.4427\n2014-01-18 13:35:00,33.4447\n2014-01-18 13:40:00,33.4427\n2014-01-18 13:45:00,33.4447\n2014-01-18 13:50:00,33.3333\n2014-01-18 13:55:00,33.4427\n2014-01-18 14:00:00,33.5573\n2014-01-18 14:05:00,33.4447\n2014-01-18 14:10:00,33.4447\n2014-01-18 14:15:00,33.4427\n2014-01-18 14:20:00,33.4447\n2014-01-18 14:25:00,33.446\n2014-01-18 14:30:00,33.446\n2014-01-18 14:35:00,33.4447\n2014-01-18 14:40:00,33.446\n2014-01-18 14:45:00,33.3333\n2014-01-18 14:50:00,33.556\n2014-01-18 14:55:00,33.446\n2014-01-18 15:00:00,33.5573\n2014-01-18 15:05:00,33.4447\n2014-01-18 15:10:00,33.3333\n2014-01-18 15:15:00,33.554\n2014-01-18 15:20:00,33.3333\n2014-01-18 15:25:00,33.4427\n2014-01-18 15:30:00,33.4447\n2014-01-18 15:35:00,33.446\n2014-01-18 15:40:00,33.4447\n2014-01-18 15:45:00,33.3333\n2014-01-18 15:50:00,33.4447\n2014-01-18 15:55:00,33.446\n2014-01-18 16:00:00,33.5553\n2014-01-18 16:05:00,33.3333\n2014-01-18 16:10:00,33.4427\n2014-01-18 16:15:00,33.4447\n2014-01-18 16:20:00,37.214\n2014-01-18 16:25:00,33.446\n2014-01-18 16:30:00,33.4447\n2014-01-18 16:35:00,33.4447\n2014-01-18 16:40:00,33.3333\n2014-01-18 16:45:00,33.5553\n2014-01-18 16:50:00,33.3333\n2014-01-18 16:55:00,33.4447\n2014-01-18 17:00:00,33.446\n2014-01-18 17:05:00,33.554\n2014-01-18 17:10:00,33.3333\n2014-01-18 17:15:00,33.4447\n2014-01-18 17:20:00,33.4447\n2014-01-18 17:25:00,33.4427\n2014-01-18 17:30:00,33.4447\n2014-01-18 17:35:00,33.4447\n2014-01-18 17:40:00,33.3333\n2014-01-18 17:45:00,33.446\n2014-01-18 17:50:00,33.4447\n2014-01-18 17:55:00,33.4447\n2014-01-18 18:00:00,33.5553\n2014-01-18 18:05:00,33.3333\n2014-01-18 18:10:00,33.446\n2014-01-18 18:15:00,33.4447\n2014-01-18 18:20:00,33.4447\n2014-01-18 18:25:00,33.4447\n2014-01-18 18:30:00,33.446\n2014-01-18 18:35:00,33.3333\n2014-01-18 18:40:00,33.4447\n2014-01-18 18:45:00,33.4427\n2014-01-18 18:50:00,33.4427\n2014-01-18 18:55:00,33.446\n2014-01-18 19:00:00,33.4447\n2014-01-18 19:05:00,33.4427\n2014-01-18 19:10:00,33.4447\n2014-01-18 19:15:00,33.4447\n2014-01-18 19:20:00,33.4447\n2014-01-18 19:25:00,33.4447\n2014-01-18 19:30:00,33.3333\n2014-01-18 19:35:00,33.4447\n2014-01-18 19:40:00,33.4447\n2014-01-18 19:45:00,33.4447\n2014-01-18 19:50:00,33.4447\n2014-01-18 19:55:00,33.3333\n2014-01-18 20:00:00,33.5573\n2014-01-18 20:05:00,33.4447\n2014-01-18 20:10:00,33.4447\n2014-01-18 20:15:00,33.3333\n2014-01-18 20:20:00,33.5573\n2014-01-18 20:25:00,33.3333\n2014-01-18 20:30:00,33.4427\n2014-01-18 20:35:00,33.446\n2014-01-18 20:40:00,33.4447\n2014-01-18 20:45:00,33.4447\n2014-01-18 20:50:00,33.3333\n2014-01-18 20:55:00,33.4447\n2014-01-18 21:00:00,33.4447\n2014-01-18 21:05:00,33.554\n2014-01-18 21:10:00,28.5714\n2014-01-18 21:15:00,33.4447\n2014-01-18 21:20:00,33.4447\n2014-01-18 21:25:00,33.3333\n2014-01-18 21:30:00,33.5587\n2014-01-18 21:35:00,33.3333\n2014-01-18 21:40:00,33.556\n2014-01-18 21:45:00,33.3333\n2014-01-18 21:50:00,33.3333\n2014-01-18 21:55:00,33.5573\n2014-01-18 22:00:00,33.556\n2014-01-18 22:05:00,33.3333\n2014-01-18 22:10:00,33.3333\n2014-01-18 22:15:00,33.5553\n2014-01-18 22:20:00,33.3333\n2014-01-18 22:25:00,33.554\n2014-01-18 22:30:00,33.3333\n2014-01-18 22:35:00,33.446\n2014-01-18 22:40:00,33.4447\n2014-01-18 22:45:00,33.3333\n2014-01-18 22:50:00,33.5573\n2014-01-18 22:55:00,33.3333\n2014-01-18 23:00:00,33.556\n2014-01-18 23:05:00,33.3333\n2014-01-18 23:10:00,34.344\n2014-01-18 23:15:00,36.2207\n2014-01-18 23:20:00,36.1113\n2014-01-18 23:25:00,33.4447\n2014-01-18 23:30:00,33.4447\n2014-01-18 23:35:00,33.6633\n2014-01-18 23:40:00,38.1267\n2014-01-18 23:45:00,33.9913\n2014-01-18 23:50:00,33.3333\n2014-01-18 23:55:00,33.4447\n2014-01-19 00:00:00,33.556\n2014-01-19 00:05:00,33.4447\n2014-01-19 00:10:00,33.3333\n2014-01-19 00:15:00,33.4447\n2014-01-19 00:20:00,33.556\n2014-01-19 00:25:00,33.5573\n2014-01-19 00:30:00,33.4447\n2014-01-19 00:35:00,33.3333\n2014-01-19 00:40:00,33.5553\n2014-01-19 00:45:00,35.756\n2014-01-19 00:50:00,39.91\n2014-01-19 00:55:00,35.5487\n2014-01-19 01:00:00,33.6667\n2014-01-19 01:05:00,33.554\n2014-01-19 01:10:00,33.3333\n2014-01-19 01:15:00,33.3333\n2014-01-19 01:20:00,33.554\n2014-01-19 01:25:00,33.3333\n2014-01-19 01:30:00,33.4427\n2014-01-19 01:35:00,33.4427\n2014-01-19 01:40:00,33.4427\n2014-01-19 01:45:00,33.4447\n2014-01-19 01:50:00,33.3333\n2014-01-19 01:55:00,33.4427\n2014-01-19 02:00:00,33.5573\n2014-01-19 02:05:00,33.4447\n2014-01-19 02:10:00,33.3333\n2014-01-19 02:15:00,33.4427\n2014-01-19 02:20:00,33.4447\n2014-01-19 02:25:00,33.4447\n2014-01-19 02:30:00,33.4447\n2014-01-19 02:35:00,33.446\n2014-01-19 02:40:00,33.3333\n2014-01-19 02:45:00,33.4447\n2014-01-19 02:50:00,33.4427\n2014-01-19 02:55:00,33.4447\n2014-01-19 03:00:00,33.446\n2014-01-19 03:05:00,35.1113\n2014-01-19 03:10:00,33.446\n2014-01-19 03:15:00,33.4447\n2014-01-19 03:20:00,33.4447\n2014-01-19 03:25:00,35.2227\n2014-01-19 03:30:00,33.4447\n2014-01-19 03:35:00,33.4447\n2014-01-19 03:40:00,33.4447\n2014-01-19 03:45:00,33.3333\n2014-01-19 03:50:00,33.4447\n2014-01-19 03:55:00,33.4447\n2014-01-19 04:00:00,33.554\n2014-01-19 04:05:00,33.3333\n2014-01-19 04:10:00,33.4447\n2014-01-19 04:15:00,33.446\n2014-01-19 04:20:00,33.3333\n2014-01-19 04:25:00,33.556\n2014-01-19 04:30:00,33.3333\n2014-01-19 04:35:00,33.5573\n2014-01-19 04:40:00,33.3333\n2014-01-19 04:45:00,33.3333\n2014-01-19 04:50:00,33.5573\n2014-01-19 04:55:00,33.3333\n2014-01-19 05:00:00,33.554\n2014-01-19 05:05:00,33.446\n2014-01-19 05:10:00,33.4447\n2014-01-19 05:15:00,33.3333\n2014-01-19 05:20:00,33.554\n2014-01-19 05:25:00,33.3333\n2014-01-19 05:30:00,33.4427\n2014-01-19 05:35:00,33.446\n2014-01-19 05:40:00,33.3333\n2014-01-19 05:45:00,33.5573\n2014-01-19 05:50:00,33.3333\n2014-01-19 05:55:00,33.4427\n2014-01-19 06:00:00,33.4447\n2014-01-19 06:05:00,33.5573\n2014-01-19 06:10:00,33.3333\n2014-01-19 06:15:00,33.4447\n2014-01-19 06:20:00,33.446\n2014-01-19 06:25:00,33.3333\n2014-01-19 06:30:00,33.5573\n2014-01-19 06:35:00,33.3333\n2014-01-19 06:40:00,33.554\n2014-01-19 06:45:00,33.3333\n2014-01-19 06:50:00,33.3333\n2014-01-19 06:55:00,33.5573\n2014-01-19 07:00:00,33.554\n2014-01-19 07:05:00,33.3333\n2014-01-19 07:10:00,33.4427\n2014-01-19 07:15:00,33.4447\n2014-01-19 07:20:00,33.3333\n2014-01-19 07:25:00,35.1113\n2014-01-19 07:30:00,36.9867\n2014-01-19 07:35:00,37.114000000000004\n2014-01-19 07:40:00,33.556\n2014-01-19 07:45:00,33.3333\n2014-01-19 07:50:00,33.4427\n2014-01-19 07:55:00,33.4447\n2014-01-19 08:00:00,33.554\n2014-01-19 08:05:00,33.3333\n2014-01-19 08:10:00,33.446\n2014-01-19 08:15:00,33.446\n2014-01-19 08:20:00,33.3333\n2014-01-19 08:25:00,33.556\n2014-01-19 08:30:00,23.0769\n2014-01-19 08:35:00,33.556\n2014-01-19 08:40:00,33.3333\n2014-01-19 08:45:00,33.4447\n2014-01-19 08:50:00,33.4447\n2014-01-19 08:55:00,33.3333\n2014-01-19 09:00:00,33.5573\n2014-01-19 09:05:00,33.4427\n2014-01-19 09:10:00,33.446\n2014-01-19 09:15:00,33.3333\n2014-01-19 09:20:00,33.5573\n2014-01-19 09:25:00,33.3333\n2014-01-19 09:30:00,33.446\n2014-01-19 09:35:00,33.4447\n2014-01-19 09:40:00,33.3333\n2014-01-19 09:45:00,33.554\n2014-01-19 09:50:00,33.3333\n2014-01-19 09:55:00,33.4447\n2014-01-19 10:00:00,33.554\n2014-01-19 10:05:00,33.554\n2014-01-19 10:10:00,33.3333\n2014-01-19 10:15:00,33.4427\n2014-01-19 10:20:00,33.4447\n2014-01-19 10:25:00,33.446\n2014-01-19 10:30:00,33.446\n2014-01-19 10:35:00,33.3333\n2014-01-19 10:40:00,33.4447\n2014-01-19 10:45:00,33.446\n2014-01-19 10:50:00,33.4427\n2014-01-19 10:55:00,33.5553\n2014-01-19 11:00:00,33.5587\n2014-01-19 11:05:00,33.3333\n2014-01-19 11:10:00,33.4427\n2014-01-19 11:15:00,33.4447\n2014-01-19 11:20:00,33.3333\n2014-01-19 11:25:00,33.5553\n2014-01-19 11:30:00,28.5714\n2014-01-19 11:35:00,33.4427\n2014-01-19 11:40:00,33.4447\n2014-01-19 11:45:00,33.5573\n2014-01-19 11:50:00,33.3333\n2014-01-19 11:55:00,33.3333\n2014-01-19 12:00:00,33.556\n2014-01-19 12:05:00,33.554\n2014-01-19 12:10:00,34.0033\n2014-01-19 12:15:00,33.446\n2014-01-19 12:20:00,33.4427\n2014-01-19 12:25:00,33.3333\n2014-01-19 12:30:00,33.5573\n2014-01-19 12:35:00,33.3333\n2014-01-19 12:40:00,33.4427\n2014-01-19 12:45:00,33.4447\n2014-01-19 12:50:00,33.4427\n2014-01-19 12:55:00,33.4447\n2014-01-19 13:00:00,33.4447\n2014-01-19 13:05:00,33.4447\n2014-01-19 13:10:00,33.4447\n2014-01-19 13:15:00,33.446\n2014-01-19 13:20:00,33.3333\n2014-01-19 13:25:00,33.5573\n2014-01-19 13:30:00,38.0187\n2014-01-19 13:35:00,37.3347\n2014-01-19 13:40:00,37.222\n2014-01-19 13:45:00,38.1107\n2014-01-19 13:50:00,37.8893\n2014-01-19 13:55:00,38.222\n2014-01-19 14:00:00,34.1093\n2014-01-19 14:05:00,37.444\n2014-01-19 14:10:00,33.8893\n2014-01-19 14:15:00,33.4447\n2014-01-19 14:20:00,33.4447\n2014-01-19 14:25:00,33.3333\n2014-01-19 14:30:00,36.5713\n2014-01-19 14:35:00,37.116\n2014-01-19 14:40:00,36.1007\n2014-01-19 14:45:00,35.8967\n2014-01-19 14:50:00,36.5493\n2014-01-19 14:55:00,36.3373\n2014-01-19 15:00:00,35.6673\n2014-01-19 15:05:00,35.7787\n2014-01-19 15:10:00,36.1113\n2014-01-19 15:15:00,35.44\n2014-01-19 15:20:00,33.5573\n2014-01-19 15:25:00,33.3333\n2014-01-19 15:30:00,33.5553\n2014-01-19 15:35:00,33.3333\n2014-01-19 15:40:00,33.446\n2014-01-19 15:45:00,33.4447\n2014-01-19 15:50:00,33.3333\n2014-01-19 15:55:00,33.554\n2014-01-19 16:00:00,33.4427\n2014-01-19 16:05:00,33.4447\n2014-01-19 16:10:00,33.3333\n2014-01-19 16:15:00,33.5553\n2014-01-19 16:20:00,33.3333\n2014-01-19 16:25:00,33.5573\n2014-01-19 16:30:00,33.3333\n2014-01-19 16:35:00,33.4447\n2014-01-19 16:40:00,33.4447\n2014-01-19 16:45:00,33.3333\n2014-01-19 16:50:00,33.5573\n2014-01-19 16:55:00,33.3333\n2014-01-19 17:00:00,33.5573\n2014-01-19 17:05:00,33.3333\n2014-01-19 17:10:00,33.554\n2014-01-19 17:15:00,33.3333\n2014-01-19 17:20:00,33.4427\n2014-01-19 17:25:00,33.4427\n2014-01-19 17:30:00,33.446\n2014-01-19 17:35:00,33.4447\n2014-01-19 17:40:00,33.3333\n2014-01-19 17:45:00,33.4427\n2014-01-19 17:50:00,33.446\n2014-01-19 17:55:00,33.446\n2014-01-19 18:00:00,33.4447\n2014-01-19 18:05:00,33.554\n2014-01-19 18:10:00,33.3333\n2014-01-19 18:15:00,33.4447\n2014-01-19 18:20:00,33.4447\n2014-01-19 18:25:00,33.4447\n2014-01-19 18:30:00,33.4427\n2014-01-19 18:35:00,33.3333\n2014-01-19 18:40:00,33.4447\n2014-01-19 18:45:00,37.7947\n2014-01-19 18:50:00,38.556\n2014-01-19 18:55:00,36.9907\n2014-01-19 19:00:00,33.5573\n2014-01-19 19:05:00,33.3333\n2014-01-19 19:10:00,36.2333\n2014-01-19 19:15:00,38.8913\n2014-01-19 19:20:00,38.1007\n2014-01-19 19:25:00,33.446\n2014-01-19 19:30:00,33.4447\n2014-01-19 19:35:00,33.4447\n2014-01-19 19:40:00,33.4447\n2014-01-19 19:45:00,33.3333\n2014-01-19 19:50:00,33.4447\n2014-01-19 19:55:00,33.446\n2014-01-19 20:00:00,33.6653\n2014-01-19 20:05:00,33.3333\n2014-01-19 20:10:00,33.4427\n2014-01-19 20:15:00,33.4447\n2014-01-19 20:20:00,33.4447\n2014-01-19 20:25:00,33.446\n2014-01-19 20:30:00,33.3333\n2014-01-19 20:35:00,33.4427\n2014-01-19 20:40:00,33.4427\n2014-01-19 20:45:00,33.4447\n2014-01-19 20:50:00,33.4447\n2014-01-19 20:55:00,33.3333\n2014-01-19 21:00:00,33.5573\n2014-01-19 21:05:00,33.4427\n2014-01-19 21:10:00,33.5587\n2014-01-19 21:15:00,33.3333\n2014-01-19 21:20:00,33.5553\n2014-01-19 21:25:00,33.3333\n2014-01-19 21:30:00,33.4447\n2014-01-19 21:35:00,33.446\n2014-01-19 21:40:00,33.3333\n2014-01-19 21:45:00,33.5573\n2014-01-19 21:50:00,33.3333\n2014-01-19 21:55:00,33.554\n2014-01-19 22:00:00,33.3333\n2014-01-19 22:05:00,33.5573\n2014-01-19 22:10:00,33.3333\n2014-01-19 22:15:00,33.5553\n2014-01-19 22:20:00,33.3333\n2014-01-19 22:25:00,33.3333\n2014-01-19 22:30:00,23.3354\n2014-01-19 22:35:00,33.3333\n2014-01-19 22:40:00,33.554\n2014-01-19 22:45:00,33.3333\n2014-01-19 22:50:00,33.4427\n2014-01-19 22:55:00,33.4447\n2014-01-19 23:00:00,33.5587\n2014-01-19 23:05:00,33.3333\n2014-01-19 23:10:00,33.446\n2014-01-19 23:15:00,33.4447\n2014-01-19 23:20:00,33.3333\n2014-01-19 23:25:00,33.5573\n2014-01-19 23:30:00,33.3333\n2014-01-19 23:35:00,33.446\n2014-01-19 23:40:00,33.4447\n2014-01-19 23:45:00,33.4447\n2014-01-19 23:50:00,33.3333\n2014-01-19 23:55:00,33.446\n2014-01-20 00:00:00,33.5573\n2014-01-20 00:05:00,33.4427\n2014-01-20 00:10:00,33.5553\n2014-01-20 00:15:00,33.5573\n2014-01-20 00:20:00,33.3333\n2014-01-20 00:25:00,33.4447\n2014-01-20 00:30:00,33.4447\n2014-01-20 00:35:00,33.3333\n2014-01-20 00:40:00,33.556\n2014-01-20 00:45:00,33.3333\n2014-01-20 00:50:00,33.446\n2014-01-20 00:55:00,33.4427\n2014-01-20 01:00:00,33.556\n2014-01-20 01:05:00,33.3333\n2014-01-20 01:10:00,33.552\n2014-01-20 01:15:00,33.3333\n2014-01-20 01:20:00,33.3333\n2014-01-20 01:25:00,33.552\n2014-01-20 01:30:00,33.3333\n2014-01-20 01:35:00,33.552\n2014-01-20 01:40:00,33.3333\n2014-01-20 01:45:00,33.4447\n2014-01-20 01:50:00,33.4447\n2014-01-20 01:55:00,33.3333\n2014-01-20 02:00:00,33.556\n2014-01-20 02:05:00,33.4447\n2014-01-20 02:10:00,33.446\n2014-01-20 02:15:00,33.446\n2014-01-20 02:20:00,33.4427\n2014-01-20 02:25:00,33.4427\n2014-01-20 02:30:00,33.4447\n2014-01-20 02:35:00,33.3333\n2014-01-20 02:40:00,33.4427\n2014-01-20 02:45:00,33.4447\n2014-01-20 02:50:00,33.4447\n2014-01-20 02:55:00,33.4447\n2014-01-20 03:00:00,33.554\n2014-01-20 03:05:00,33.3333\n2014-01-20 03:10:00,33.556\n2014-01-20 03:15:00,33.3333\n2014-01-20 03:20:00,35.2227\n2014-01-20 03:25:00,33.3333\n2014-01-20 03:30:00,33.4427\n2014-01-20 03:35:00,33.4447\n2014-01-20 03:40:00,35.2207\n2014-01-20 03:45:00,33.3333\n2014-01-20 03:50:00,33.5587\n2014-01-20 03:55:00,33.3333\n2014-01-20 04:00:00,23.3315\n2014-01-20 04:05:00,37.5\n2014-01-20 04:10:00,33.5573\n2014-01-20 04:15:00,33.3333\n2014-01-20 04:20:00,33.4447\n2014-01-20 04:25:00,33.4427\n2014-01-20 04:30:00,33.3333\n2014-01-20 04:35:00,33.554\n2014-01-20 04:40:00,33.3333\n2014-01-20 04:45:00,33.5553\n2014-01-20 04:50:00,33.3333\n2014-01-20 04:55:00,33.3333\n2014-01-20 05:00:00,28.81\n2014-01-20 05:05:00,33.556\n2014-01-20 05:10:00,33.3333\n2014-01-20 05:15:00,33.3333\n2014-01-20 05:20:00,33.5553\n2014-01-20 05:25:00,33.4447\n2014-01-20 05:30:00,33.4427\n2014-01-20 05:35:00,33.3333\n2014-01-20 05:40:00,33.5573\n2014-01-20 05:45:00,33.3333\n2014-01-20 05:50:00,33.4447\n2014-01-20 05:55:00,33.4447\n2014-01-20 06:00:00,33.6667\n2014-01-20 06:05:00,33.4447\n2014-01-20 06:10:00,33.4447\n2014-01-20 06:15:00,33.4447\n2014-01-20 06:20:00,33.3333\n2014-01-20 06:25:00,33.446\n2014-01-20 06:30:00,35.8336\n2014-01-20 06:35:00,33.4447\n2014-01-20 06:40:00,33.446\n2014-01-20 06:45:00,35.7143\n2014-01-20 06:50:00,33.4447\n2014-01-20 06:55:00,33.4447\n2014-01-20 07:00:00,35.9521\n2014-01-20 07:05:00,30.7692\n2014-01-20 07:10:00,33.4447\n2014-01-20 07:15:00,33.4427\n2014-01-20 07:20:00,35.8336\n2014-01-20 07:25:00,33.4447\n2014-01-20 07:30:00,33.3333\n2014-01-20 07:35:00,35.9543\n2014-01-20 07:40:00,30.7692\n2014-01-20 07:45:00,33.4447\n2014-01-20 07:50:00,33.4427\n2014-01-20 07:55:00,33.6667\n2014-01-20 08:00:00,33.554\n2014-01-20 08:05:00,35.7143\n2014-01-20 08:10:00,30.7692\n2014-01-20 08:15:00,33.4427\n2014-01-20 08:20:00,33.3333\n2014-01-20 08:25:00,35.9557\n2014-01-20 08:30:00,30.7692\n2014-01-20 08:35:00,33.556\n2014-01-20 08:40:00,33.3333\n2014-01-20 08:45:00,35.7143\n2014-01-20 08:50:00,35.9507\n2014-01-20 08:55:00,33.3333\n2014-01-20 09:00:00,33.5553\n2014-01-20 09:05:00,35.8336\n2014-01-20 09:10:00,31.0262\n2014-01-20 09:15:00,33.3333\n2014-01-20 09:20:00,33.446\n2014-01-20 09:25:00,33.4447\n2014-01-20 09:30:00,35.7143\n2014-01-20 09:35:00,33.615\n2014-01-20 09:40:00,33.3333\n2014-01-20 09:45:00,33.4447\n2014-01-20 09:50:00,35.835\n2014-01-20 09:55:00,33.3333\n2014-01-20 10:00:00,33.446\n2014-01-20 10:05:00,33.446\n2014-01-20 10:10:00,35.8336\n2014-01-20 10:15:00,30.8954\n2014-01-20 10:20:00,33.4447\n2014-01-20 10:25:00,33.3333\n2014-01-20 10:30:00,35.835\n2014-01-20 10:35:00,33.4742\n2014-01-20 10:40:00,33.446\n2014-01-20 10:45:00,33.4447\n2014-01-20 10:50:00,35.835\n2014-01-20 10:55:00,30.7692\n2014-01-20 11:00:00,33.4427\n2014-01-20 11:05:00,33.4427\n2014-01-20 11:10:00,35.8336\n2014-01-20 11:15:00,30.7692\n2014-01-20 11:20:00,33.4447\n2014-01-20 11:25:00,33.3333\n2014-01-20 11:30:00,35.8336\n2014-01-20 11:35:00,30.8954\n2014-01-20 11:40:00,33.4447\n2014-01-20 11:45:00,33.4447\n2014-01-20 11:50:00,35.7143\n2014-01-20 11:55:00,30.8977\n2014-01-20 12:00:00,33.554\n2014-01-20 12:05:00,33.446\n2014-01-20 12:10:00,35.9543\n2014-01-20 12:15:00,30.7692\n2014-01-20 12:20:00,33.4447\n2014-01-20 12:25:00,33.4447\n2014-01-20 12:30:00,35.7143\n2014-01-20 12:35:00,31.0277\n2014-01-20 12:40:00,33.3333\n2014-01-20 12:45:00,33.552\n2014-01-20 12:50:00,35.7143\n2014-01-20 12:55:00,30.7692\n2014-01-20 13:00:00,33.556\n2014-01-20 13:05:00,33.554\n2014-01-20 13:10:00,35.7143\n2014-01-20 13:15:00,30.7692\n2014-01-20 13:20:00,33.5573\n2014-01-20 13:25:00,33.3333\n2014-01-20 13:30:00,35.8336\n2014-01-20 13:35:00,30.7692\n2014-01-20 13:40:00,33.4427\n2014-01-20 13:45:00,33.4447\n2014-01-20 13:50:00,35.7143\n2014-01-20 13:55:00,35.9507\n2014-01-20 14:00:00,33.4725\n2014-01-20 14:05:00,33.4447\n2014-01-20 14:10:00,35.7143\n2014-01-20 14:15:00,35.9507\n2014-01-20 14:20:00,33.3333\n2014-01-20 14:25:00,33.446\n2014-01-20 14:30:00,35.8336\n2014-01-20 14:35:00,35.8314\n2014-01-20 14:40:00,33.4447\n2014-01-20 14:45:00,33.3333\n2014-01-20 14:50:00,35.835\n2014-01-20 14:55:00,35.8336\n2014-01-20 15:00:00,33.6092\n2014-01-20 15:05:00,33.3333\n2014-01-20 15:10:00,33.554\n2014-01-20 15:15:00,35.7143\n2014-01-20 15:20:00,33.4742\n2014-01-20 15:25:00,33.4447\n2014-01-20 15:30:00,33.4447\n2014-01-20 15:35:00,35.8314\n2014-01-20 15:40:00,33.3333\n2014-01-20 15:45:00,33.446\n2014-01-20 15:50:00,33.4427\n2014-01-20 15:55:00,35.835\n2014-01-20 16:00:00,33.4725\n2014-01-20 16:05:00,33.554\n2014-01-20 16:10:00,33.3333\n2014-01-20 16:15:00,35.8314\n2014-01-20 16:20:00,30.8977\n2014-01-20 16:25:00,33.3333\n2014-01-20 16:30:00,33.556\n2014-01-20 16:35:00,33.3333\n2014-01-20 16:40:00,35.8314\n2014-01-20 16:45:00,33.4725\n2014-01-20 16:50:00,33.446\n2014-01-20 16:55:00,33.4427\n2014-01-20 17:00:00,35.8336\n2014-01-20 17:05:00,30.8992\n2014-01-20 17:10:00,33.4427\n2014-01-20 17:15:00,33.4447\n2014-01-20 17:20:00,35.8314\n2014-01-20 17:25:00,30.7692\n2014-01-20 17:30:00,33.4447\n2014-01-20 17:35:00,33.4447\n2014-01-20 17:40:00,35.9486\n2014-01-20 17:45:00,30.7692\n2014-01-20 17:50:00,33.4447\n2014-01-20 17:55:00,33.446\n2014-01-20 18:00:00,35.9529\n2014-01-20 18:05:00,30.7692\n2014-01-20 18:10:00,33.446\n2014-01-20 18:15:00,33.446\n2014-01-20 18:20:00,35.7143\n2014-01-20 18:25:00,35.8336\n2014-01-20 18:30:00,33.3333\n2014-01-20 18:35:00,33.5587\n2014-01-20 18:40:00,35.7143\n2014-01-20 18:45:00,35.7143\n2014-01-20 18:50:00,33.554\n2014-01-20 18:55:00,33.3333\n2014-01-20 19:00:00,35.9529\n2014-01-20 19:05:00,30.8977\n2014-01-20 19:10:00,36.5487\n2014-01-20 19:15:00,35.7893\n2014-01-20 19:20:00,33.446\n2014-01-20 19:25:00,35.8336\n2014-01-20 19:30:00,33.3333\n2014-01-20 19:35:00,35.6667\n2014-01-20 19:40:00,33.3333\n2014-01-20 19:45:00,35.8336\n2014-01-20 19:50:00,33.75\n2014-01-20 19:55:00,36.4447\n2014-01-20 20:00:00,33.554\n2014-01-20 20:05:00,35.7143\n2014-01-20 20:10:00,30.8977\n2014-01-20 20:15:00,33.3333\n2014-01-20 20:20:00,33.5553\n2014-01-20 20:25:00,35.7143\n2014-01-20 20:30:00,30.7692\n2014-01-20 20:35:00,33.4427\n2014-01-20 20:40:00,33.3333\n2014-01-20 20:45:00,35.9507\n2014-01-20 20:50:00,30.7692\n2014-01-20 20:55:00,33.4427\n2014-01-20 21:00:00,33.4447\n2014-01-20 21:05:00,35.9557\n2014-01-20 21:10:00,30.7692\n2014-01-20 21:15:00,33.5573\n2014-01-20 21:20:00,33.3333\n2014-01-20 21:25:00,35.7143\n2014-01-20 21:30:00,31.0254\n2014-01-20 21:35:00,33.3333\n2014-01-20 21:40:00,33.4447\n2014-01-20 21:45:00,35.8314\n2014-01-20 21:50:00,31.5338\n2014-01-20 21:55:00,33.4427\n2014-01-20 22:00:00,33.4447\n2014-01-20 22:05:00,35.8336\n2014-01-20 22:10:00,30.8954\n2014-01-20 22:15:00,33.4427\n2014-01-20 22:20:00,33.3333\n2014-01-20 22:25:00,35.835\n2014-01-20 22:30:00,30.8954\n2014-01-20 22:35:00,33.446\n2014-01-20 22:40:00,33.4447\n2014-01-20 22:45:00,35.8314\n2014-01-20 22:50:00,30.7692\n2014-01-20 22:55:00,33.4447\n2014-01-20 23:00:00,33.554\n2014-01-20 23:05:00,35.8314\n2014-01-20 23:10:00,30.7692\n2014-01-20 23:15:00,33.446\n2014-01-20 23:20:00,33.446\n2014-01-20 23:25:00,35.8336\n2014-01-20 23:30:00,30.8992\n2014-01-20 23:35:00,33.3333\n2014-01-20 23:40:00,33.556\n2014-01-20 23:45:00,35.7143\n2014-01-20 23:50:00,34.0167\n2014-01-20 23:55:00,33.8873\n2014-01-21 00:00:00,33.554\n2014-01-21 00:05:00,35.7143\n2014-01-21 00:10:00,31.0238\n2014-01-21 00:15:00,33.3333\n2014-01-21 00:20:00,33.446\n2014-01-21 00:25:00,35.835\n2014-01-21 00:30:00,33.3333\n2014-01-21 00:35:00,33.554\n2014-01-21 00:40:00,33.3333\n2014-01-21 00:45:00,35.8314\n2014-01-21 00:50:00,33.3333\n2014-01-21 00:55:00,33.3333\n2014-01-21 01:00:00,33.552\n2014-01-21 01:05:00,35.9486\n2014-01-21 01:10:00,35.7143\n2014-01-21 01:15:00,33.3333\n2014-01-21 01:20:00,33.5573\n2014-01-21 01:25:00,35.7143\n2014-01-21 01:30:00,31.0277\n2014-01-21 01:35:00,33.3333\n2014-01-21 01:40:00,33.4427\n2014-01-21 01:45:00,33.446\n2014-01-21 01:50:00,33.3333\n2014-01-21 01:55:00,35.9521\n2014-01-21 02:00:00,35.835\n2014-01-21 02:05:00,35.835\n2014-01-21 02:10:00,30.7692\n2014-01-21 02:15:00,33.6092\n2014-01-21 02:20:00,33.3333\n2014-01-21 02:25:00,33.4427\n2014-01-21 02:30:00,33.446\n2014-01-21 02:35:00,33.4447\n2014-01-21 02:40:00,33.446\n2014-01-21 02:45:00,35.7143\n2014-01-21 02:50:00,35.835\n2014-01-21 02:55:00,30.8977\n2014-01-21 03:00:00,33.6133\n2014-01-21 03:05:00,36.9153\n2014-01-21 03:10:00,33.3333\n2014-01-21 03:15:00,33.446\n2014-01-21 03:20:00,33.446\n2014-01-21 03:25:00,35.7143\n2014-01-21 03:30:00,35.9486\n2014-01-21 03:35:00,30.7692\n2014-01-21 03:40:00,33.47\n2014-01-21 03:45:00,33.4447\n2014-01-21 03:50:00,33.4427\n2014-01-21 03:55:00,35.8314\n2014-01-21 04:00:00,33.5587\n2014-01-21 04:05:00,35.8314\n2014-01-21 04:10:00,35.8314\n2014-01-21 04:15:00,30.7692\n2014-01-21 04:20:00,33.554\n2014-01-21 04:25:00,33.3333\n2014-01-21 04:30:00,33.446\n2014-01-21 04:35:00,35.8336\n2014-01-21 04:40:00,35.835\n2014-01-21 04:45:00,35.835\n2014-01-21 04:50:00,30.8954\n2014-01-21 04:55:00,33.4447\n2014-01-21 05:00:00,33.4447\n2014-01-21 05:05:00,33.4427\n2014-01-21 05:10:00,35.8336\n2014-01-21 05:15:00,35.8336\n2014-01-21 05:20:00,35.7143\n2014-01-21 05:25:00,30.8992\n2014-01-21 05:30:00,33.4427\n2014-01-21 05:35:00,33.446\n2014-01-21 05:40:00,33.4447\n2014-01-21 05:45:00,33.4447\n2014-01-21 05:50:00,35.7143\n2014-01-21 05:55:00,35.9507\n2014-01-21 06:00:00,30.8977\n2014-01-21 06:05:00,30.8992\n2014-01-21 06:10:00,33.3333\n2014-01-21 06:15:00,33.554\n2014-01-21 06:20:00,33.3333\n2014-01-21 06:25:00,33.4427\n2014-01-21 06:30:00,33.4427\n2014-01-21 06:35:00,35.7143\n2014-01-21 06:40:00,36.07\n2014-01-21 06:45:00,30.7692\n2014-01-21 06:50:00,33.4725\n2014-01-21 06:55:00,33.3333\n2014-01-21 07:00:00,33.554\n2014-01-21 07:05:00,33.4447\n2014-01-21 07:10:00,35.835\n2014-01-21 07:15:00,35.7143\n2014-01-21 07:20:00,35.9529\n2014-01-21 07:25:00,33.47\n2014-01-21 07:30:00,33.3333\n2014-01-21 07:35:00,33.556\n2014-01-21 07:40:00,33.3333\n2014-01-21 07:45:00,35.9543\n2014-01-21 07:50:00,35.7143\n2014-01-21 07:55:00,35.7143\n2014-01-21 08:00:00,31.0262\n2014-01-21 08:05:00,33.3333\n2014-01-21 08:10:00,33.4725\n2014-01-21 08:15:00,33.3333\n2014-01-21 08:20:00,33.4427\n2014-01-21 08:25:00,33.4427\n2014-01-21 08:30:00,33.4427\n2014-01-21 08:35:00,35.835\n2014-01-21 08:40:00,35.7143\n2014-01-21 08:45:00,30.8992\n2014-01-21 08:50:00,33.4725\n2014-01-21 08:55:00,33.4427\n2014-01-21 09:00:00,33.4447\n2014-01-21 09:05:00,33.4427\n2014-01-21 09:10:00,33.4447\n2014-01-21 09:15:00,35.8336\n2014-01-21 09:20:00,35.7143\n2014-01-21 09:25:00,35.7143\n2014-01-21 09:30:00,30.8977\n2014-01-21 09:35:00,33.4447\n2014-01-21 09:40:00,33.4427\n2014-01-21 09:45:00,33.3333\n2014-01-21 09:50:00,33.554\n2014-01-21 09:55:00,35.7143\n2014-01-21 10:00:00,35.9557\n2014-01-21 10:05:00,30.7692\n2014-01-21 10:10:00,33.4725\n2014-01-21 10:15:00,33.3333\n2014-01-21 10:20:00,33.4427\n2014-01-21 10:25:00,33.4447\n2014-01-21 10:30:00,33.3333\n2014-01-21 10:35:00,35.9529\n2014-01-21 10:40:00,37.3814\n2014-01-21 10:45:00,45.6229\n2014-01-21 10:50:00,35.8685\n2014-01-21 10:55:00,33.4447\n2014-01-21 11:00:00,33.556\n2014-01-21 11:05:00,33.3333\n2014-01-21 11:10:00,33.554\n2014-01-21 11:15:00,35.7143\n2014-01-21 11:20:00,35.7143\n2014-01-21 11:25:00,35.8314\n2014-01-21 11:30:00,30.7692\n2014-01-21 11:35:00,33.556\n2014-01-21 11:40:00,33.4427\n2014-01-21 11:45:00,33.5573\n2014-01-21 11:50:00,33.446\n2014-01-21 11:55:00,35.7143\n2014-01-21 12:00:00,35.9543\n2014-01-21 12:05:00,35.835\n2014-01-21 12:10:00,30.7692\n2014-01-21 12:15:00,33.3333\n2014-01-21 12:20:00,33.5573\n2014-01-21 12:25:00,33.3333\n2014-01-21 12:30:00,33.4427\n2014-01-21 12:35:00,35.8336\n2014-01-21 12:40:00,35.8336\n2014-01-21 12:45:00,35.7143\n2014-01-21 12:50:00,30.7692\n2014-01-21 12:55:00,33.4742\n2014-01-21 13:00:00,33.5553\n2014-01-21 13:05:00,33.3333\n2014-01-21 13:10:00,33.4447\n2014-01-21 13:15:00,33.4427\n2014-01-21 13:20:00,35.8336\n2014-01-21 13:25:00,35.835\n2014-01-21 13:30:00,30.7692\n2014-01-21 13:35:00,33.47\n2014-01-21 13:40:00,33.3333\n2014-01-21 13:45:00,33.4447\n2014-01-21 13:50:00,33.446\n2014-01-21 13:55:00,35.7143\n2014-01-21 14:00:00,35.9507\n2014-01-21 14:05:00,35.7143\n2014-01-21 14:10:00,30.8992\n2014-01-21 14:15:00,33.3333\n2014-01-21 14:20:00,33.5573\n2014-01-21 14:25:00,33.3333\n2014-01-21 14:30:00,33.4427\n2014-01-21 14:35:00,35.835\n2014-01-21 14:40:00,35.7143\n2014-01-21 14:45:00,31.0254\n2014-01-21 14:50:00,33.3333\n2014-01-21 14:55:00,33.446\n2014-01-21 15:00:00,33.4447\n2014-01-21 15:05:00,33.554\n2014-01-21 15:10:00,33.3333\n2014-01-21 15:15:00,35.8314\n2014-01-21 15:20:00,35.8314\n2014-01-21 15:25:00,35.7143\n2014-01-21 15:30:00,31.0238\n2014-01-21 15:35:00,34.2153\n2014-01-21 15:40:00,33.5573\n2014-01-21 15:45:00,33.3333\n2014-01-21 15:50:00,35.7143\n2014-01-21 15:55:00,36.0721\n2014-01-21 16:00:00,35.9557\n2014-01-21 16:05:00,30.7692\n2014-01-21 16:10:00,33.3333\n2014-01-21 16:15:00,33.4427\n2014-01-21 16:20:00,33.3333\n2014-01-21 16:25:00,33.554\n2014-01-21 16:30:00,33.3333\n2014-01-21 16:35:00,35.8314\n2014-01-21 16:40:00,35.8336\n2014-01-21 16:45:00,30.7692\n2014-01-21 16:50:00,33.556\n2014-01-21 16:55:00,33.3333\n2014-01-21 17:00:00,33.556\n2014-01-21 17:05:00,33.3333\n2014-01-21 17:10:00,35.8336\n2014-01-21 17:15:00,35.7143\n2014-01-21 17:20:00,35.8336\n2014-01-21 17:25:00,33.4725\n2014-01-21 17:30:00,33.446\n2014-01-21 17:35:00,35.4613\n2014-01-21 17:40:00,38.2036\n2014-01-21 17:45:00,33.5593\n2014-01-21 17:50:00,35.8336\n2014-01-21 17:55:00,35.8314\n2014-01-21 18:00:00,35.8336\n2014-01-21 18:05:00,33.4725\n2014-01-21 18:10:00,33.446\n2014-01-21 18:15:00,33.554\n2014-01-21 18:20:00,33.3333\n2014-01-21 18:25:00,33.5573\n2014-01-21 18:30:00,35.7143\n2014-01-21 18:35:00,35.835\n2014-01-21 18:40:00,30.8977\n2014-01-21 18:45:00,33.3333\n2014-01-21 18:50:00,33.556\n2014-01-21 18:55:00,33.3333\n2014-01-21 19:00:00,33.556\n2014-01-21 19:05:00,36.3193\n2014-01-21 19:10:00,35.8336\n2014-01-21 19:15:00,30.8977\n2014-01-21 19:20:00,33.4725\n2014-01-21 19:25:00,33.4427\n2014-01-21 19:30:00,35.7143\n2014-01-21 19:35:00,33.554\n2014-01-21 19:40:00,33.3333\n2014-01-21 19:45:00,35.7143\n2014-01-21 19:50:00,35.8314\n2014-01-21 19:55:00,35.7143\n2014-01-21 20:00:00,31.0277\n2014-01-21 20:05:00,33.3333\n2014-01-21 20:10:00,33.4427\n2014-01-21 20:15:00,33.3333\n2014-01-21 20:20:00,33.552\n2014-01-21 20:25:00,33.3333\n2014-01-21 20:30:00,33.4427\n2014-01-21 20:35:00,35.8336\n2014-01-21 20:40:00,35.7143\n2014-01-21 20:45:00,31.0254\n2014-01-21 20:50:00,33.3333\n2014-01-21 20:55:00,33.4447\n2014-01-21 21:00:00,35.9543\n2014-01-21 21:05:00,33.3333\n2014-01-21 21:10:00,33.3333\n2014-01-21 21:15:00,33.554\n2014-01-21 21:20:00,35.7143\n2014-01-21 21:25:00,35.9507\n2014-01-21 21:30:00,35.7143\n2014-01-21 21:35:00,33.4742\n2014-01-21 21:40:00,33.4427\n2014-01-21 21:45:00,33.3333\n2014-01-21 21:50:00,33.4447\n2014-01-21 21:55:00,33.4447\n2014-01-21 22:00:00,35.9507\n2014-01-21 22:05:00,35.7143\n2014-01-21 22:10:00,35.8336\n2014-01-21 22:15:00,30.7692\n2014-01-21 22:20:00,33.4447\n2014-01-21 22:25:00,33.4447\n2014-01-21 22:30:00,33.4447\n2014-01-21 22:35:00,33.4447\n2014-01-21 22:40:00,35.7143\n2014-01-21 22:45:00,35.835\n2014-01-21 22:50:00,35.7143\n2014-01-21 22:55:00,35.8336\n2014-01-21 23:00:00,30.8992\n2014-01-21 23:05:00,33.6117\n2014-01-21 23:10:00,35.7143\n2014-01-21 23:15:00,33.4447\n2014-01-21 23:20:00,33.4427\n2014-01-21 23:25:00,33.4447\n2014-01-21 23:30:00,35.8336\n2014-01-21 23:35:00,35.7143\n2014-01-21 23:40:00,30.8954\n2014-01-21 23:45:00,33.4447\n2014-01-21 23:50:00,33.446\n2014-01-21 23:55:00,33.4427\n2014-01-22 00:00:00,33.775999999999996\n2014-01-22 00:05:00,39.0314\n2014-01-22 00:10:00,37.145\n2014-01-22 00:15:00,35.7143\n2014-01-22 00:20:00,30.8977\n2014-01-22 00:25:00,33.47\n2014-01-22 00:30:00,33.4447\n2014-01-22 00:35:00,33.4447\n2014-01-22 00:40:00,33.3333\n2014-01-22 00:45:00,35.835\n2014-01-22 00:50:00,35.8336\n2014-01-22 00:55:00,35.8314\n2014-01-22 01:00:00,35.9543\n2014-01-22 01:05:00,30.7692\n2014-01-22 01:10:00,33.4725\n2014-01-22 01:15:00,33.446\n2014-01-22 01:20:00,33.4447\n2014-01-22 01:25:00,33.446\n2014-01-22 01:30:00,35.7143\n2014-01-22 01:35:00,35.9529\n2014-01-22 01:40:00,35.7143\n2014-01-22 01:45:00,30.8977\n2014-01-22 01:50:00,33.4447\n2014-01-22 01:55:00,30.7692\n2014-01-22 02:00:00,33.554\n2014-01-22 02:05:00,33.4447\n2014-01-22 02:10:00,35.8336\n2014-01-22 02:15:00,35.7143\n2014-01-22 02:20:00,37.51\n2014-01-22 02:25:00,30.7692\n2014-01-22 02:30:00,33.556\n2014-01-22 02:35:00,33.3333\n2014-01-22 02:40:00,33.4447\n2014-01-22 02:45:00,33.446\n2014-01-22 02:50:00,35.7143\n2014-01-22 02:55:00,31.0238\n2014-01-22 03:00:00,30.7692\n2014-01-22 03:05:00,33.6667\n2014-01-22 03:10:00,33.3333\n2014-01-22 03:15:00,33.554\n2014-01-22 03:20:00,34.9727\n2014-01-22 03:25:00,33.554\n2014-01-22 03:30:00,35.7143\n2014-01-22 03:35:00,35.8336\n2014-01-22 03:40:00,34.6169\n2014-01-22 03:45:00,35.2227\n2014-01-22 03:50:00,33.3333\n2014-01-22 03:55:00,33.3333\n2014-01-22 04:00:00,33.5573\n2014-01-22 04:05:00,35.9529\n2014-01-22 04:10:00,35.7143\n2014-01-22 04:15:00,35.835\n2014-01-22 04:20:00,33.4725\n2014-01-22 04:25:00,33.3333\n2014-01-22 04:30:00,33.554\n2014-01-22 04:35:00,35.104\n2014-01-22 04:40:00,35.1187\n2014-01-22 04:45:00,37.7307\n2014-01-22 04:50:00,37.4943\n2014-01-22 04:55:00,32.7008\n2014-01-22 05:00:00,34.1625\n2014-01-22 05:05:00,33.4447\n2014-01-22 05:10:00,33.3333\n2014-01-22 05:15:00,33.4447\n2014-01-22 05:20:00,35.8314\n2014-01-22 05:25:00,35.8314\n2014-01-22 05:30:00,35.7143\n2014-01-22 05:35:00,30.7692\n2014-01-22 05:40:00,33.47\n2014-01-22 05:45:00,33.446\n2014-01-22 05:50:00,33.5593\n2014-01-22 05:55:00,33.3333\n2014-01-22 06:00:00,33.5553\n2014-01-22 06:05:00,33.4447\n2014-01-22 06:10:00,35.8336\n2014-01-22 06:15:00,35.7143\n2014-01-22 06:20:00,30.8977\n2014-01-22 06:25:00,33.47\n2014-01-22 06:30:00,33.4447\n2014-01-22 06:35:00,33.446\n2014-01-22 06:40:00,33.3333\n2014-01-22 06:45:00,33.556\n2014-01-22 06:50:00,35.7143\n2014-01-22 06:55:00,35.7143\n2014-01-22 07:00:00,30.8977\n2014-01-22 07:05:00,33.5587\n2014-01-22 07:10:00,33.3333\n2014-01-22 07:15:00,33.3333\n2014-01-22 07:20:00,33.556\n2014-01-22 07:25:00,33.3333\n2014-01-22 07:30:00,35.9507\n2014-01-22 07:35:00,35.7143\n2014-01-22 07:40:00,33.4742\n2014-01-22 07:45:00,33.4447\n2014-01-22 07:50:00,33.3333\n2014-01-22 07:55:00,33.5573\n2014-01-22 08:00:00,33.4447\n2014-01-22 08:05:00,35.835\n2014-01-22 08:10:00,35.7143\n2014-01-22 08:15:00,31.0277\n2014-01-22 08:20:00,33.3333\n2014-01-22 08:25:00,33.446\n2014-01-22 08:30:00,33.4447\n2014-01-22 08:35:00,33.446\n2014-01-22 08:40:00,35.7143\n2014-01-22 08:45:00,35.8336\n2014-01-22 08:50:00,35.835\n2014-01-22 08:55:00,33.4725\n2014-01-22 09:00:00,33.4447\n2014-01-22 09:05:00,33.556\n2014-01-22 09:10:00,33.3333\n2014-01-22 09:15:00,33.4447\n2014-01-22 09:20:00,35.8336\n2014-01-22 09:25:00,35.7143\n2014-01-22 09:30:00,35.9486\n2014-01-22 09:35:00,33.3333\n2014-01-22 09:40:00,33.554\n2014-01-22 09:45:00,33.3333\n2014-01-22 09:50:00,33.3333\n2014-01-22 09:55:00,33.556\n2014-01-22 10:00:00,35.9507\n2014-01-22 10:05:00,35.7143\n2014-01-22 10:10:00,30.7692\n2014-01-22 10:15:00,33.4725\n2014-01-22 10:20:00,33.3333\n2014-01-22 10:25:00,31.0238\n2014-01-22 10:30:00,33.3333\n2014-01-22 10:35:00,33.3333\n2014-01-22 10:40:00,35.9521\n2014-01-22 10:45:00,35.7143\n2014-01-22 10:50:00,35.8336\n2014-01-22 10:55:00,33.3333\n2014-01-22 11:00:00,33.5587\n2014-01-22 11:05:00,33.4427\n2014-01-22 11:10:00,33.4447\n2014-01-22 11:15:00,33.3333\n2014-01-22 11:20:00,35.835\n2014-01-22 11:25:00,35.8314\n2014-01-22 11:30:00,35.835\n2014-01-22 11:35:00,33.3333\n2014-01-22 11:40:00,33.4427\n2014-01-22 11:45:00,33.3333\n2014-01-22 11:50:00,33.4447\n2014-01-22 11:55:00,35.835\n2014-01-22 12:00:00,35.9529\n2014-01-22 12:05:00,30.7692\n2014-01-22 12:10:00,30.8992\n2014-01-22 12:15:00,33.4427\n2014-01-22 12:20:00,33.4427\n2014-01-22 12:25:00,33.3333\n2014-01-22 12:30:00,33.3333\n2014-01-22 12:35:00,33.6633\n2014-01-22 12:40:00,35.835\n2014-01-22 12:45:00,35.8336\n2014-01-22 12:50:00,35.8336\n2014-01-22 12:55:00,30.7692\n2014-01-22 13:00:00,33.554\n2014-01-22 13:05:00,33.4447\n2014-01-22 13:10:00,33.4427\n2014-01-22 13:15:00,33.3333\n2014-01-22 13:20:00,33.4447\n2014-01-22 13:25:00,35.8336\n2014-01-22 13:30:00,35.8336\n2014-01-22 13:35:00,33.4725\n2014-01-22 13:40:00,33.3333\n2014-01-22 13:45:00,33.4447\n2014-01-22 13:50:00,33.4427\n2014-01-22 13:55:00,33.446\n2014-01-22 14:00:00,36.3114\n2014-01-22 14:05:00,35.7143\n2014-01-22 14:10:00,30.8992\n2014-01-22 14:15:00,33.4725\n2014-01-22 14:20:00,34.8987\n2014-01-22 14:25:00,33.3333\n2014-01-22 14:30:00,37.2679\n2014-01-22 14:35:00,35.8314\n2014-01-22 14:40:00,35.7143\n2014-01-22 14:45:00,35.8314\n2014-01-22 14:50:00,30.7692\n2014-01-22 14:55:00,33.4725\n2014-01-22 15:00:00,33.556\n2014-01-22 15:05:00,30.8992\n2014-01-22 15:10:00,33.3333\n2014-01-22 15:15:00,33.4447\n2014-01-22 15:20:00,35.8336\n2014-01-22 15:25:00,35.7143\n2014-01-22 15:30:00,33.6092\n2014-01-22 15:35:00,41.3333\n2014-01-22 15:40:00,33.554\n2014-01-22 15:45:00,33.3333\n2014-01-22 15:50:00,33.3333\n2014-01-22 15:55:00,35.9507\n2014-01-22 16:00:00,35.9507\n2014-01-22 16:05:00,30.7692\n2014-01-22 16:10:00,33.3333\n2014-01-22 16:15:00,33.554\n2014-01-22 16:20:00,33.3333\n2014-01-22 16:25:00,33.5553\n2014-01-22 16:30:00,35.7143\n2014-01-22 16:35:00,35.8314\n2014-01-22 16:40:00,31.0262\n2014-01-22 16:45:00,33.3333\n2014-01-22 16:50:00,33.4447\n2014-01-22 16:55:00,33.3333\n2014-01-22 17:00:00,33.556\n2014-01-22 17:05:00,33.3333\n2014-01-22 17:10:00,35.9543\n2014-01-22 17:15:00,35.7143\n2014-01-22 17:20:00,36.0693\n2014-01-22 17:25:00,30.7692\n2014-01-22 17:30:00,33.4742\n2014-01-22 17:35:00,34.5633\n2014-01-22 17:40:00,35.104\n2014-01-22 17:45:00,31.0254\n2014-01-22 17:50:00,35.7143\n2014-01-22 17:55:00,35.8336\n2014-01-22 18:00:00,35.7143\n2014-01-22 18:05:00,35.9521\n2014-01-22 18:10:00,30.7692\n2014-01-22 18:15:00,33.6108\n2014-01-22 18:20:00,33.3333\n2014-01-22 18:25:00,33.3333\n2014-01-22 18:30:00,33.5553\n2014-01-22 18:35:00,33.3333\n2014-01-22 18:40:00,35.8314\n2014-01-22 18:45:00,35.7143\n2014-01-22 18:50:00,30.8954\n2014-01-22 18:55:00,33.4447\n2014-01-22 19:00:00,33.5573\n2014-01-22 19:05:00,33.3333\n2014-01-22 19:10:00,33.4742\n2014-01-22 19:15:00,35.8336\n2014-01-22 19:20:00,35.7143\n2014-01-22 19:25:00,35.8314\n2014-01-22 19:30:00,30.7692\n2014-01-22 19:35:00,33.4725\n2014-01-22 19:40:00,35.8336\n2014-01-22 19:45:00,33.4427\n2014-01-22 19:50:00,33.3333\n2014-01-22 19:55:00,33.4447\n2014-01-22 20:00:00,33.5573\n2014-01-22 20:05:00,35.8336\n2014-01-22 20:10:00,35.7143\n2014-01-22 20:15:00,35.835\n2014-01-22 20:20:00,33.4742\n2014-01-22 20:25:00,35.8336\n2014-01-22 20:30:00,33.4447\n2014-01-22 20:35:00,33.3333\n2014-01-22 20:40:00,33.5553\n2014-01-22 20:45:00,35.7143\n2014-01-22 20:50:00,35.7143\n2014-01-22 20:55:00,30.8954\n2014-01-22 21:00:00,33.4742\n2014-01-22 21:05:00,33.446\n2014-01-22 21:10:00,33.4427\n2014-01-22 21:15:00,33.4447\n2014-01-22 21:20:00,35.7143\n2014-01-22 21:25:00,35.9521\n2014-01-22 21:30:00,35.7143\n2014-01-22 21:35:00,30.7692\n2014-01-22 21:40:00,33.47\n2014-01-22 21:45:00,33.3333\n2014-01-22 21:50:00,33.5573\n2014-01-22 21:55:00,33.3333\n2014-01-22 22:00:00,35.9521\n2014-01-22 22:05:00,35.7143\n2014-01-22 22:10:00,35.9543\n2014-01-22 22:15:00,35.7143\n2014-01-22 22:20:00,30.7692\n2014-01-22 22:25:00,33.5553\n2014-01-22 22:30:00,33.3333\n2014-01-22 22:35:00,33.5587\n2014-01-22 22:40:00,33.3333\n2014-01-22 22:45:00,33.3333\n2014-01-22 22:50:00,35.835\n2014-01-22 22:55:00,35.7143\n2014-01-22 23:00:00,35.9507\n2014-01-22 23:05:00,30.8992\n2014-01-22 23:10:00,33.47\n2014-01-22 23:15:00,33.3333\n2014-01-22 23:20:00,33.5573\n2014-01-22 23:25:00,35.7143\n2014-01-22 23:30:00,33.446\n2014-01-22 23:35:00,35.8336\n2014-01-22 23:40:00,35.7143\n2014-01-22 23:45:00,30.8954\n2014-01-22 23:50:00,33.3333\n2014-01-22 23:55:00,33.446\n2014-01-23 00:00:00,33.554\n2014-01-23 00:05:00,33.446\n2014-01-23 00:10:00,33.4447\n2014-01-23 00:15:00,35.8314\n2014-01-23 00:20:00,35.8314\n2014-01-23 00:25:00,30.8992\n2014-01-23 00:30:00,33.3333\n2014-01-23 00:35:00,33.5573\n2014-01-23 00:40:00,33.3333\n2014-01-23 00:45:00,33.4447\n2014-01-23 00:50:00,35.835\n2014-01-23 00:55:00,35.7143\n2014-01-23 01:00:00,35.9507\n2014-01-23 01:05:00,33.4742\n2014-01-23 01:10:00,33.4427\n2014-01-23 01:15:00,33.3333\n2014-01-23 01:20:00,33.5573\n2014-01-23 01:25:00,33.3333\n2014-01-23 01:30:00,35.9507\n2014-01-23 01:35:00,35.7143\n2014-01-23 01:40:00,31.0254\n2014-01-23 01:45:00,33.446\n2014-01-23 01:50:00,33.4447\n2014-01-23 01:55:00,33.446\n2014-01-23 02:00:00,33.6092\n2014-01-23 02:05:00,33.3333\n2014-01-23 02:10:00,35.8336\n2014-01-23 02:15:00,35.835\n2014-01-23 02:20:00,35.8336\n2014-01-23 02:25:00,33.47\n2014-01-23 02:30:00,33.3333\n2014-01-23 02:35:00,33.556\n2014-01-23 02:40:00,33.3333\n2014-01-23 02:45:00,35.7143\n2014-01-23 02:50:00,35.835\n2014-01-23 02:55:00,35.7143\n2014-01-23 03:00:00,31.0262\n2014-01-23 03:05:00,35.5933\n2014-01-23 03:10:00,35.835\n2014-01-23 03:15:00,33.4427\n2014-01-23 03:20:00,35.2207\n2014-01-23 03:25:00,33.4447\n2014-01-23 03:30:00,35.835\n2014-01-23 03:35:00,35.7143\n2014-01-23 03:40:00,30.7692\n2014-01-23 03:45:00,33.4742\n2014-01-23 03:50:00,30.8954\n2014-01-23 03:55:00,33.446\n2014-01-23 04:00:00,35.54\n2014-01-23 04:05:00,33.446\n2014-01-23 04:10:00,35.9507\n2014-01-23 04:15:00,35.7143\n2014-01-23 04:20:00,30.8992\n2014-01-23 04:25:00,33.4427\n2014-01-23 04:30:00,33.554\n2014-01-23 04:35:00,33.446\n2014-01-23 04:40:00,33.3333\n2014-01-23 04:45:00,35.835\n2014-01-23 04:50:00,35.8336\n2014-01-23 04:55:00,35.835\n2014-01-23 05:00:00,33.47\n2014-01-23 05:05:00,33.446\n2014-01-23 05:10:00,34.6667\n2014-01-23 05:15:00,33.4447\n2014-01-23 05:20:00,34.786\n2014-01-23 05:25:00,35.7143\n2014-01-23 05:30:00,35.835\n2014-01-23 05:35:00,30.8954\n2014-01-23 05:40:00,33.4725\n2014-01-23 05:45:00,33.4427\n2014-01-23 05:50:00,33.3333\n2014-01-23 05:55:00,33.4447\n2014-01-23 06:00:00,35.9507\n2014-01-23 06:05:00,35.8336\n2014-01-23 06:10:00,35.7143\n2014-01-23 06:15:00,30.8977\n2014-01-23 06:20:00,33.4725\n2014-01-23 06:25:00,33.4447\n2014-01-23 06:30:00,33.4447\n2014-01-23 06:35:00,33.3333\n2014-01-23 06:40:00,33.5573\n2014-01-23 06:45:00,35.7143\n2014-01-23 06:50:00,35.7143\n2014-01-23 06:55:00,35.8336\n2014-01-23 07:00:00,30.8977\n2014-01-23 07:05:00,33.4427\n2014-01-23 07:10:00,33.4447\n2014-01-23 07:15:00,33.446\n2014-01-23 07:20:00,33.3333\n2014-01-23 07:25:00,35.9507\n2014-01-23 07:30:00,35.7143\n2014-01-23 07:35:00,35.7143\n2014-01-23 07:40:00,33.4742\n2014-01-23 07:45:00,33.3333\n2014-01-23 07:50:00,33.5573\n2014-01-23 07:55:00,33.3333\n2014-01-23 08:00:00,33.554\n2014-01-23 08:05:00,35.7143\n2014-01-23 08:10:00,36.1864\n2014-01-23 08:15:00,32.0477\n2014-01-23 08:20:00,33.4725\n2014-01-23 08:25:00,35.8314\n2014-01-23 08:30:00,33.3333\n2014-01-23 08:35:00,33.4447\n2014-01-23 08:40:00,33.4427\n2014-01-23 08:45:00,35.7143\n2014-01-23 08:50:00,35.9543\n2014-01-23 08:55:00,35.7143\n2014-01-23 09:00:00,35.9543\n2014-01-23 09:05:00,35.0\n2014-01-23 09:10:00,37.8727\n2014-01-23 09:15:00,38.1107\n2014-01-23 09:20:00,35.2353\n2014-01-23 09:25:00,33.4447\n2014-01-23 09:30:00,35.8336\n2014-01-23 09:35:00,40.5943\n2014-01-23 09:40:00,41.8871\n2014-01-23 09:45:00,34.1054\n2014-01-23 09:50:00,33.3333\n2014-01-23 09:55:00,33.4447\n2014-01-23 10:00:00,35.8336\n2014-01-23 10:05:00,33.552\n2014-01-23 10:10:00,35.7143\n2014-01-23 10:15:00,35.835\n2014-01-23 10:20:00,35.835\n2014-01-23 10:25:00,30.7692\n2014-01-23 10:30:00,33.446\n2014-01-23 10:35:00,33.3333\n2014-01-23 10:40:00,30.8977\n2014-01-23 10:45:00,33.446\n2014-01-23 10:50:00,35.7143\n2014-01-23 10:55:00,35.9529\n2014-01-23 11:00:00,31.0238\n2014-01-23 11:05:00,33.3333\n2014-01-23 11:10:00,33.4447\n2014-01-23 11:15:00,33.446\n2014-01-23 11:20:00,33.3333\n2014-01-23 11:25:00,33.47\n2014-01-23 11:30:00,35.7143\n2014-01-23 11:35:00,30.7692\n2014-01-23 11:40:00,33.6092\n2014-01-23 11:45:00,33.3333\n2014-01-23 11:50:00,33.554\n2014-01-23 11:55:00,33.3333\n2014-01-23 12:00:00,33.554\n2014-01-23 12:05:00,35.7143\n2014-01-23 12:10:00,35.8314\n2014-01-23 12:15:00,33.3333\n2014-01-23 12:20:00,33.3333\n2014-01-23 12:25:00,35.9507\n2014-01-23 12:30:00,33.3333\n2014-01-23 12:35:00,33.446\n2014-01-23 12:40:00,33.4447\n2014-01-23 12:45:00,35.8314\n2014-01-23 12:50:00,35.7143\n2014-01-23 12:55:00,30.7692\n2014-01-23 13:00:00,33.6092\n2014-01-23 13:05:00,33.4427\n2014-01-23 13:10:00,33.4447\n2014-01-23 13:15:00,33.3333\n2014-01-23 13:20:00,35.8314\n2014-01-23 13:25:00,35.8336\n2014-01-23 13:30:00,35.9543\n2014-01-23 13:35:00,33.3333\n2014-01-23 13:40:00,33.446\n2014-01-23 13:45:00,33.3333\n2014-01-23 13:50:00,33.4447\n2014-01-23 13:55:00,35.835\n2014-01-23 14:00:00,35.8336\n2014-01-23 14:05:00,35.835\n2014-01-23 14:10:00,30.8977\n2014-01-23 14:15:00,33.4725\n2014-01-23 14:20:00,33.3333\n2014-01-23 14:25:00,33.5573\n2014-01-23 14:30:00,33.3333\n2014-01-23 14:35:00,33.4447\n2014-01-23 14:40:00,35.835\n2014-01-23 14:45:00,35.7143\n2014-01-23 14:50:00,35.9529\n2014-01-23 14:55:00,30.7692\n2014-01-23 15:00:00,33.554\n2014-01-23 15:05:00,33.3333\n2014-01-23 15:10:00,33.552\n2014-01-23 15:15:00,33.3333\n2014-01-23 15:20:00,35.8314\n2014-01-23 15:25:00,35.8336\n2014-01-23 15:30:00,35.7143\n2014-01-23 15:35:00,30.8954\n2014-01-23 15:40:00,33.3333\n2014-01-23 15:45:00,33.556\n2014-01-23 15:50:00,33.3333\n2014-01-23 15:55:00,33.446\n2014-01-23 16:00:00,33.4447\n2014-01-23 16:05:00,35.9543\n2014-01-23 16:10:00,35.7143\n2014-01-23 16:15:00,30.8992\n2014-01-23 16:20:00,33.4725\n2014-01-23 16:25:00,33.3333\n2014-01-23 16:30:00,33.5553\n2014-01-23 16:35:00,33.3333\n2014-01-23 16:40:00,33.554\n2014-01-23 16:45:00,35.7143\n2014-01-23 16:50:00,35.9529\n2014-01-23 16:55:00,30.7692\n2014-01-23 17:00:00,33.6117\n2014-01-23 17:05:00,33.3333\n2014-01-23 17:10:00,33.5573\n2014-01-23 17:15:00,33.3333\n2014-01-23 17:20:00,33.446\n2014-01-23 17:25:00,35.8336\n2014-01-23 17:30:00,35.8336\n2014-01-23 17:35:00,30.7692\n2014-01-23 17:40:00,33.3333\n2014-01-23 17:45:00,33.446\n2014-01-23 17:50:00,33.4447\n2014-01-23 17:55:00,33.4447\n2014-01-23 18:00:00,35.8314\n2014-01-23 18:05:00,35.835\n2014-01-23 18:10:00,35.8336\n2014-01-23 18:15:00,30.8992\n2014-01-23 18:20:00,33.3333\n2014-01-23 18:25:00,33.4447\n2014-01-23 18:30:00,33.4447\n2014-01-23 18:35:00,33.4427\n2014-01-23 18:40:00,33.446\n2014-01-23 18:45:00,35.7143\n2014-01-23 18:50:00,35.8336\n2014-01-23 18:55:00,35.8336\n2014-01-23 19:00:00,33.6117\n2014-01-23 19:05:00,33.3333\n2014-01-23 19:10:00,33.446\n2014-01-23 19:15:00,33.446\n2014-01-23 19:20:00,33.446\n2014-01-23 19:25:00,35.8314\n2014-01-23 19:30:00,35.7143\n2014-01-23 19:35:00,35.9521\n2014-01-23 19:40:00,30.7692\n2014-01-23 19:45:00,33.4447\n2014-01-23 19:50:00,33.5573\n2014-01-23 19:55:00,33.3333\n2014-01-23 20:00:00,33.5573\n2014-01-23 20:05:00,33.3333\n2014-01-23 20:10:00,44.4864\n2014-01-23 20:15:00,35.835\n2014-01-23 20:20:00,30.8977\n2014-01-23 20:25:00,33.3333\n2014-01-23 20:30:00,33.446\n2014-01-23 20:35:00,33.4447\n2014-01-23 20:40:00,33.446\n2014-01-23 20:45:00,35.7143\n2014-01-23 20:50:00,35.8336\n2014-01-23 20:55:00,35.8336\n2014-01-23 21:00:00,33.6092\n2014-01-23 21:05:00,33.4427\n2014-01-23 21:10:00,33.3333\n2014-01-23 21:15:00,33.4427\n2014-01-23 21:20:00,33.4447\n2014-01-23 21:25:00,33.446\n2014-01-23 21:30:00,35.7143\n2014-01-23 21:35:00,35.8336\n2014-01-23 21:40:00,35.8336\n2014-01-23 21:45:00,33.3333\n2014-01-23 21:50:00,33.4427\n2014-01-23 21:55:00,33.3333\n2014-01-23 22:00:00,33.554\n2014-01-23 22:05:00,35.7143\n2014-01-23 22:10:00,33.446\n2014-01-23 22:15:00,33.3333\n2014-01-23 22:20:00,35.9543\n2014-01-23 22:25:00,35.7143\n2014-01-23 22:30:00,35.7143\n2014-01-23 22:35:00,33.615\n2014-01-23 22:40:00,33.3333\n2014-01-23 22:45:00,33.554\n2014-01-23 22:50:00,33.3333\n2014-01-23 22:55:00,33.4427\n2014-01-23 23:00:00,33.5573\n2014-01-23 23:05:00,33.446\n2014-01-23 23:10:00,35.8314\n2014-01-23 23:15:00,35.835\n2014-01-23 23:20:00,35.8336\n2014-01-23 23:25:00,30.7692\n2014-01-23 23:30:00,33.4725\n2014-01-23 23:35:00,33.4725\n2014-01-23 23:40:00,33.4447\n2014-01-23 23:45:00,33.4447\n2014-01-23 23:50:00,33.3333\n2014-01-23 23:55:00,33.446\n2014-01-24 00:00:00,33.5553\n2014-01-24 00:05:00,35.8336\n2014-01-24 00:10:00,35.7143\n2014-01-24 00:15:00,35.8336\n2014-01-24 00:20:00,30.8977\n2014-01-24 00:25:00,33.4725\n2014-01-24 00:30:00,33.4447\n2014-01-24 00:35:00,33.4427\n2014-01-24 00:40:00,33.3333\n2014-01-24 00:45:00,33.5587\n2014-01-24 00:50:00,33.3333\n2014-01-24 00:55:00,33.3333\n2014-01-24 01:00:00,35.9557\n2014-01-24 01:05:00,35.9543\n2014-01-24 01:10:00,35.7143\n2014-01-24 01:15:00,30.7692\n2014-01-24 01:20:00,33.554\n2014-01-24 01:25:00,33.3333\n2014-01-24 01:30:00,33.552\n2014-01-24 01:35:00,33.3333\n2014-01-24 01:40:00,33.5573\n2014-01-24 01:45:00,33.3333\n2014-01-24 01:50:00,35.552\n2014-01-24 01:55:00,38.3343\n2014-01-24 02:00:00,38.575\n2014-01-24 02:05:00,37.85\n2014-01-24 02:10:00,36.7843\n2014-01-24 02:15:00,30.8977\n2014-01-24 02:20:00,33.3333\n2014-01-24 02:25:00,33.554\n2014-01-24 02:30:00,33.3333\n2014-01-24 02:35:00,33.554\n2014-01-24 02:40:00,33.3333\n2014-01-24 02:45:00,33.3333\n2014-01-24 02:50:00,35.9543\n2014-01-24 02:55:00,35.7143\n2014-01-24 03:00:00,35.9557\n2014-01-24 03:05:00,32.0408\n2014-01-24 03:10:00,33.3333\n2014-01-24 03:15:00,33.446\n2014-01-24 03:20:00,33.4447\n2014-01-24 03:25:00,33.3333\n2014-01-24 03:30:00,33.554\n2014-01-24 03:35:00,33.3333\n2014-01-24 03:40:00,35.9543\n2014-01-24 03:45:00,35.7143\n2014-01-24 03:50:00,35.8336\n2014-01-24 03:55:00,35.835\n2014-01-24 04:00:00,35.9543\n2014-01-24 04:05:00,33.3333\n2014-01-24 04:10:00,33.4447\n2014-01-24 04:15:00,33.446\n2014-01-24 04:20:00,33.4447\n2014-01-24 04:25:00,33.446\n2014-01-24 04:30:00,33.3333\n2014-01-24 04:35:00,35.8336\n2014-01-24 04:40:00,35.835\n2014-01-24 04:45:00,35.8314\n2014-01-24 04:50:00,30.8977\n2014-01-24 04:55:00,33.3333\n2014-01-24 05:00:00,33.6067\n2014-01-24 05:05:00,33.4447\n2014-01-24 05:10:00,33.446\n2014-01-24 05:15:00,33.3333\n2014-01-24 05:20:00,33.554\n2014-01-24 05:25:00,33.3333\n2014-01-24 05:30:00,33.4447\n2014-01-24 05:35:00,33.4427\n2014-01-24 05:40:00,33.3333\n2014-01-24 05:45:00,33.554\n2014-01-24 05:50:00,35.7143\n2014-01-24 05:55:00,35.7143\n2014-01-24 06:00:00,35.9507\n2014-01-24 06:05:00,35.9543\n2014-01-24 06:10:00,35.7143\n2014-01-24 06:15:00,35.7143\n2014-01-24 06:20:00,35.9521\n2014-01-24 06:25:00,35.7143\n2014-01-24 06:30:00,35.8314\n2014-01-24 06:35:00,35.7143\n2014-01-24 06:40:00,35.7143\n2014-01-24 06:45:00,31.1523\n2014-01-24 06:50:00,35.7143\n2014-01-24 06:55:00,30.8954\n2014-01-24 07:00:00,30.7692\n2014-01-24 07:05:00,33.6108\n2014-01-24 07:10:00,30.7692\n2014-01-24 07:15:00,33.446\n2014-01-24 07:20:00,33.4447\n2014-01-24 07:25:00,33.3333\n2014-01-24 07:30:00,33.552\n2014-01-24 07:35:00,33.3333\n2014-01-24 07:40:00,33.446\n2014-01-24 07:45:00,33.4447\n2014-01-24 07:50:00,33.4427\n2014-01-24 07:55:00,33.4447\n2014-01-24 08:00:00,35.8336\n2014-01-24 08:05:00,35.8336\n2014-01-24 08:10:00,35.8336\n2014-01-24 08:15:00,35.835\n2014-01-24 08:20:00,35.8336\n2014-01-24 08:25:00,30.7692\n2014-01-24 08:30:00,35.8336\n2014-01-24 08:35:00,35.8314\n2014-01-24 08:40:00,35.7143\n2014-01-24 08:45:00,35.835\n2014-01-24 08:50:00,30.7692\n2014-01-24 08:55:00,31.0262\n2014-01-24 09:00:00,33.4725\n2014-01-24 09:05:00,33.4447\n2014-01-24 09:10:00,33.3333\n2014-01-24 09:15:00,35.8314\n2014-01-24 09:20:00,33.3333\n2014-01-24 09:25:00,33.556\n2014-01-24 09:30:00,33.3333\n2014-01-24 09:35:00,33.6653\n2014-01-24 09:40:00,33.3333\n2014-01-24 09:45:00,33.3333\n2014-01-24 09:50:00,33.554\n2014-01-24 09:55:00,33.3333\n2014-01-24 10:00:00,33.5573\n2014-01-24 10:05:00,33.3333\n2014-01-24 10:10:00,33.554\n2014-01-24 10:15:00,33.3333\n2014-01-24 10:20:00,33.554\n2014-01-24 10:25:00,33.3333\n2014-01-24 10:30:00,30.7692\n2014-01-24 10:35:00,35.9507\n2014-01-24 10:40:00,35.7143\n2014-01-24 10:45:00,35.835\n2014-01-24 10:50:00,35.8336\n2014-01-24 10:55:00,35.8336\n2014-01-24 11:00:00,35.8314\n2014-01-24 11:05:00,35.8314\n2014-01-24 11:10:00,35.8336\n2014-01-24 11:15:00,35.835\n2014-01-24 11:20:00,35.8336\n2014-01-24 11:25:00,35.7143\n2014-01-24 11:30:00,35.8314\n2014-01-24 11:35:00,35.8336\n2014-01-24 11:40:00,35.8336\n2014-01-24 11:45:00,35.8314\n2014-01-24 11:50:00,35.835\n2014-01-24 11:55:00,35.7143\n2014-01-24 12:00:00,35.9543\n2014-01-24 12:05:00,35.8336\n2014-01-24 12:10:00,35.835\n2014-01-24 12:15:00,35.7143\n2014-01-24 12:20:00,35.835\n2014-01-24 12:25:00,35.835\n2014-01-24 12:30:00,35.7143\n2014-01-24 12:35:00,35.9543\n2014-01-24 12:40:00,35.8336\n2014-01-24 12:45:00,35.8314\n2014-01-24 12:50:00,35.7143\n2014-01-24 12:55:00,30.7692\n2014-01-24 13:00:00,31.0238\n2014-01-24 13:05:00,33.3333\n2014-01-24 13:10:00,34.4407\n2014-01-24 13:15:00,33.4447\n2014-01-24 13:20:00,33.4447\n2014-01-24 13:25:00,33.4447\n2014-01-24 13:30:00,33.4427\n2014-01-24 13:35:00,33.3333\n2014-01-24 13:40:00,33.4447\n2014-01-24 13:45:00,33.446\n2014-01-24 13:50:00,33.3333\n2014-01-24 13:55:00,35.9521\n2014-01-24 14:00:00,35.8336\n2014-01-24 14:05:00,35.835\n2014-01-24 14:10:00,35.7143\n2014-01-24 14:15:00,35.9507\n2014-01-24 14:20:00,35.7143\n2014-01-24 14:25:00,35.8336\n2014-01-24 14:30:00,35.8314\n2014-01-24 14:35:00,35.7143\n2014-01-24 14:40:00,35.9543\n2014-01-24 14:45:00,35.7143\n2014-01-24 14:50:00,30.7692\n2014-01-24 14:55:00,30.8992\n2014-01-24 15:00:00,33.4725\n2014-01-24 15:05:00,33.3333\n2014-01-24 15:10:00,33.4725\n2014-01-24 15:15:00,33.4427\n2014-01-24 15:20:00,33.3333\n2014-01-24 15:25:00,33.5587\n2014-01-24 15:30:00,33.3333\n2014-01-24 15:35:00,33.9987\n2014-01-24 15:40:00,33.3333\n2014-01-24 15:45:00,33.3333\n2014-01-24 15:50:00,33.556\n2014-01-24 15:55:00,33.3333\n2014-01-24 16:00:00,33.5587\n2014-01-24 16:05:00,33.3333\n2014-01-24 16:10:00,33.556\n2014-01-24 16:15:00,33.3333\n2014-01-24 16:20:00,35.9486\n2014-01-24 16:25:00,35.7143\n2014-01-24 16:30:00,35.7143\n2014-01-24 16:35:00,35.9543\n2014-01-24 16:40:00,35.7143\n2014-01-24 16:45:00,36.07\n2014-01-24 16:50:00,35.7143\n2014-01-24 16:55:00,30.8992\n2014-01-24 17:00:00,35.8314\n2014-01-24 17:05:00,30.8992\n2014-01-24 17:10:00,30.7692\n2014-01-24 17:15:00,33.3333\n2014-01-24 17:20:00,33.4725\n2014-01-24 17:25:00,33.3333\n2014-01-24 17:30:00,34.4353\n2014-01-24 17:35:00,33.5553\n2014-01-24 17:40:00,33.3333\n2014-01-24 17:45:00,33.446\n2014-01-24 17:50:00,33.4447\n2014-01-24 17:55:00,33.3333\n2014-01-24 18:00:00,33.6092\n2014-01-24 18:05:00,33.4427\n2014-01-24 18:10:00,30.8992\n2014-01-24 18:15:00,35.7143\n2014-01-24 18:20:00,35.835\n2014-01-24 18:25:00,37.1507\n2014-01-24 18:30:00,35.8336\n2014-01-24 18:35:00,35.8336\n2014-01-24 18:40:00,35.7143\n2014-01-24 18:45:00,31.0254\n2014-01-24 18:50:00,30.7692\n2014-01-24 18:55:00,33.47\n2014-01-24 19:00:00,33.446\n2014-01-24 19:05:00,33.4447\n2014-01-24 19:10:00,33.3333\n2014-01-24 19:15:00,33.4447\n2014-01-24 19:20:00,33.4447\n2014-01-24 19:25:00,33.4447\n2014-01-24 19:30:00,33.4447\n2014-01-24 19:35:00,33.3333\n2014-01-24 19:40:00,33.446\n2014-01-24 19:45:00,33.446\n2014-01-24 19:50:00,33.446\n2014-01-24 19:55:00,35.7143\n2014-01-24 20:00:00,33.6667\n2014-01-24 20:05:00,35.8336\n2014-01-24 20:10:00,35.8336\n2014-01-24 20:15:00,35.7143\n2014-01-24 20:20:00,35.9543\n2014-01-24 20:25:00,35.7143\n2014-01-24 20:30:00,35.8314\n2014-01-24 20:35:00,35.7143\n2014-01-24 20:40:00,35.7143\n2014-01-24 20:45:00,31.0238\n2014-01-24 20:50:00,30.7692\n2014-01-24 20:55:00,30.8992\n2014-01-24 21:00:00,30.8977\n2014-01-24 21:05:00,31.0254\n2014-01-24 21:10:00,33.3333\n2014-01-24 21:15:00,33.4427\n2014-01-24 21:20:00,33.4427\n2014-01-24 21:25:00,33.3333\n2014-01-24 21:30:00,33.446\n2014-01-24 21:35:00,33.4447\n2014-01-24 21:40:00,33.4447\n2014-01-24 21:45:00,33.4447\n2014-01-24 21:50:00,33.4447\n2014-01-24 21:55:00,33.3333\n2014-01-24 22:00:00,33.5573\n2014-01-24 22:05:00,33.4447\n2014-01-24 22:10:00,33.446\n2014-01-24 22:15:00,33.3333\n2014-01-24 22:20:00,33.4447\n2014-01-24 22:25:00,33.4427\n2014-01-24 22:30:00,33.3333\n2014-01-24 22:35:00,35.9529\n2014-01-24 22:40:00,35.7143\n2014-01-24 22:45:00,35.8314\n2014-01-24 22:50:00,35.8314\n2014-01-24 22:55:00,35.7143\n2014-01-24 23:00:00,35.9486\n2014-01-24 23:05:00,33.47\n2014-01-24 23:10:00,35.8336\n2014-01-24 23:15:00,30.7692\n2014-01-24 23:20:00,31.0254\n2014-01-24 23:25:00,30.7692\n2014-01-24 23:30:00,33.4725\n2014-01-24 23:35:00,33.4447\n2014-01-24 23:40:00,33.3333\n2014-01-24 23:45:00,33.5573\n2014-01-24 23:50:00,33.3333\n2014-01-24 23:55:00,33.4427\n2014-01-25 00:00:00,33.4447\n2014-01-25 00:05:00,33.5553\n2014-01-25 00:10:00,33.3333\n2014-01-25 00:15:00,35.8336\n2014-01-25 00:20:00,33.4447\n2014-01-25 00:25:00,35.835\n2014-01-25 00:30:00,35.8336\n2014-01-25 00:35:00,35.7143\n2014-01-25 00:40:00,33.47\n2014-01-25 00:45:00,33.4725\n2014-01-25 00:50:00,36.8014\n2014-01-25 00:55:00,35.7143\n2014-01-25 01:00:00,35.9557\n2014-01-25 01:05:00,30.7692\n2014-01-25 01:10:00,31.0262\n2014-01-25 01:15:00,33.3333\n2014-01-25 01:20:00,33.47\n2014-01-25 01:25:00,33.4447\n2014-01-25 01:30:00,33.3333\n2014-01-25 01:35:00,33.4427\n2014-01-25 01:40:00,33.4447\n2014-01-25 01:45:00,33.4427\n2014-01-25 01:50:00,33.4447\n2014-01-25 01:55:00,33.3333\n2014-01-25 02:00:00,33.554\n2014-01-25 02:05:00,35.835\n2014-01-25 02:10:00,35.8314\n2014-01-25 02:15:00,35.8314\n2014-01-25 02:20:00,35.7143\n2014-01-25 02:25:00,35.835\n2014-01-25 02:30:00,33.47\n2014-01-25 02:35:00,35.8336\n2014-01-25 02:40:00,30.8992\n2014-01-25 02:45:00,30.7692\n2014-01-25 02:50:00,33.4725\n2014-01-25 02:55:00,33.47\n2014-01-25 03:00:00,33.6092\n2014-01-25 03:05:00,33.3333\n2014-01-25 03:10:00,33.446\n2014-01-25 03:15:00,35.222\n2014-01-25 03:20:00,33.556\n2014-01-25 03:25:00,33.3333\n2014-01-25 03:30:00,35.8336\n2014-01-25 03:35:00,33.3333\n2014-01-25 03:40:00,35.082\n2014-01-25 03:45:00,35.8314\n2014-01-25 03:50:00,35.7143\n2014-01-25 03:55:00,35.9543\n2014-01-25 04:00:00,35.835\n2014-01-25 04:05:00,35.8336\n2014-01-25 04:10:00,35.7143\n2014-01-25 04:15:00,35.9543\n2014-01-25 04:20:00,30.7692\n2014-01-25 04:25:00,30.8977\n2014-01-25 04:30:00,33.4725\n2014-01-25 04:35:00,33.3333\n2014-01-25 04:40:00,33.6673\n2014-01-25 04:45:00,33.3333\n2014-01-25 04:50:00,33.3333\n2014-01-25 04:55:00,33.5587\n2014-01-25 05:00:00,33.5573\n2014-01-25 05:05:00,33.3333\n2014-01-25 05:10:00,30.7692\n2014-01-25 05:15:00,33.552\n2014-01-25 05:20:00,33.3333\n2014-01-25 05:25:00,33.556\n2014-01-25 05:30:00,35.7143\n2014-01-25 05:35:00,35.7143\n2014-01-25 05:40:00,35.9557\n2014-01-25 05:45:00,35.7143\n2014-01-25 05:50:00,35.9529\n2014-01-25 05:55:00,35.8314\n2014-01-25 06:00:00,35.9521\n2014-01-25 06:05:00,30.7692\n2014-01-25 06:10:00,30.8992\n2014-01-25 06:15:00,30.8977\n2014-01-25 06:20:00,33.3333\n2014-01-25 06:25:00,35.8336\n2014-01-25 06:30:00,33.3333\n2014-01-25 06:35:00,33.446\n2014-01-25 06:40:00,33.446\n2014-01-25 06:45:00,33.446\n2014-01-25 06:50:00,33.3333\n2014-01-25 06:55:00,33.4447\n2014-01-25 07:00:00,35.9529\n2014-01-25 07:05:00,35.8314\n2014-01-25 07:10:00,35.7143\n2014-01-25 07:15:00,35.8336\n2014-01-25 07:20:00,35.8314\n2014-01-25 07:25:00,35.8314\n2014-01-25 07:30:00,35.8314\n2014-01-25 07:35:00,35.7143\n2014-01-25 07:40:00,35.8336\n2014-01-25 07:45:00,30.8954\n2014-01-25 07:50:00,30.7692\n2014-01-25 07:55:00,31.0262\n2014-01-25 08:00:00,33.4725\n2014-01-25 08:05:00,33.4742\n2014-01-25 08:10:00,33.4447\n2014-01-25 08:15:00,33.446\n2014-01-25 08:20:00,33.4447\n2014-01-25 08:25:00,33.4427\n2014-01-25 08:30:00,33.3333\n2014-01-25 08:35:00,31.0238\n2014-01-25 08:40:00,33.3333\n2014-01-25 08:45:00,33.3333\n2014-01-25 08:50:00,35.9543\n2014-01-25 08:55:00,35.7143\n2014-01-25 09:00:00,35.9543\n2014-01-25 09:05:00,35.7143\n2014-01-25 09:10:00,35.9507\n2014-01-25 09:15:00,35.7143\n2014-01-25 09:20:00,35.835\n2014-01-25 09:25:00,30.7692\n2014-01-25 09:30:00,30.7692\n2014-01-25 09:35:00,31.0215\n2014-01-25 09:40:00,33.3333\n2014-01-25 09:45:00,33.446\n2014-01-25 09:50:00,33.446\n2014-01-25 09:55:00,33.3333\n2014-01-25 10:00:00,33.556\n2014-01-25 10:05:00,33.446\n2014-01-25 10:10:00,33.4447\n2014-01-25 10:15:00,33.3333\n2014-01-25 10:20:00,33.4427\n2014-01-25 10:25:00,33.4447\n2014-01-25 10:30:00,33.4427\n2014-01-25 10:35:00,33.4447\n2014-01-25 10:40:00,33.4427\n2014-01-25 10:45:00,35.7143\n2014-01-25 10:50:00,35.8314\n2014-01-25 10:55:00,35.835\n2014-01-25 11:00:00,35.9543\n2014-01-25 11:05:00,35.7143\n2014-01-25 11:10:00,35.8314\n2014-01-25 11:15:00,30.8977\n2014-01-25 11:20:00,33.3333\n2014-01-25 11:25:00,33.4725\n2014-01-25 11:30:00,33.3333\n2014-01-25 11:35:00,33.3333\n2014-01-25 11:40:00,33.5573\n2014-01-25 11:45:00,33.3333\n2014-01-25 11:50:00,33.5553\n2014-01-25 11:55:00,33.3333\n2014-01-25 12:00:00,34.4433\n2014-01-25 12:05:00,35.7143\n2014-01-25 12:10:00,35.9529\n2014-01-25 12:15:00,35.7143\n2014-01-25 12:20:00,35.9507\n2014-01-25 12:25:00,35.7143\n2014-01-25 12:30:00,35.9507\n2014-01-25 12:35:00,35.7143\n2014-01-25 12:40:00,30.7692\n2014-01-25 12:45:00,33.6117\n2014-01-25 12:50:00,33.3333\n2014-01-25 12:55:00,33.446\n2014-01-25 13:00:00,33.4447\n2014-01-25 13:05:00,33.556\n2014-01-25 13:10:00,33.7813\n2014-01-25 13:15:00,33.4447\n2014-01-25 13:20:00,33.4447\n2014-01-25 13:25:00,33.3333\n2014-01-25 13:30:00,33.5573\n2014-01-25 13:35:00,33.3333\n2014-01-25 13:40:00,35.8314\n2014-01-25 13:45:00,35.8336\n2014-01-25 13:50:00,35.835\n2014-01-25 13:55:00,35.8336\n2014-01-25 14:00:00,35.835\n2014-01-25 14:05:00,35.8336\n2014-01-25 14:10:00,30.8954\n2014-01-25 14:15:00,30.7692\n2014-01-25 14:20:00,33.3333\n2014-01-25 14:25:00,33.4742\n2014-01-25 14:30:00,33.4742\n2014-01-25 14:35:00,33.4447\n2014-01-25 14:40:00,33.3333\n2014-01-25 14:45:00,33.4447\n2014-01-25 14:50:00,33.4447\n2014-01-25 14:55:00,33.556\n2014-01-25 15:00:00,33.4427\n2014-01-25 15:05:00,33.6647\n2014-01-25 15:10:00,33.3333\n2014-01-25 15:15:00,33.4447\n2014-01-25 15:20:00,33.446\n2014-01-25 15:25:00,35.7143\n2014-01-25 15:30:00,35.9529\n2014-01-25 15:35:00,38.5714\n2014-01-25 15:40:00,39.0357\n2014-01-25 15:45:00,35.8336\n2014-01-25 15:50:00,35.8336\n2014-01-25 15:55:00,35.8336\n2014-01-25 16:00:00,35.8314\n2014-01-25 16:05:00,35.8314\n2014-01-25 16:10:00,30.8992\n2014-01-25 16:15:00,30.8977\n2014-01-25 16:20:00,33.4742\n2014-01-25 16:25:00,33.4447\n2014-01-25 16:30:00,35.8314\n2014-01-25 16:35:00,33.3333\n2014-01-25 16:40:00,33.4427\n2014-01-25 16:45:00,33.4427\n2014-01-25 16:50:00,33.446\n2014-01-25 16:55:00,33.446\n2014-01-25 17:00:00,33.4447\n2014-01-25 17:05:00,33.446\n2014-01-25 17:10:00,35.7143\n2014-01-25 17:15:00,33.5587\n2014-01-25 17:20:00,35.7143\n2014-01-25 17:25:00,35.8336\n2014-01-25 17:30:00,35.835\n2014-01-25 17:35:00,39.5043\n2014-01-25 17:40:00,31.0215\n2014-01-25 17:45:00,35.7143\n2014-01-25 17:50:00,35.835\n2014-01-25 17:55:00,35.7143\n2014-01-25 18:00:00,35.9543\n2014-01-25 18:05:00,30.7692\n2014-01-25 18:10:00,33.6092\n2014-01-25 18:15:00,33.3333\n2014-01-25 18:20:00,33.446\n2014-01-25 18:25:00,33.4447\n2014-01-25 18:30:00,33.3333\n2014-01-25 18:35:00,34.3313\n2014-01-25 18:40:00,34.3333\n2014-01-25 18:45:00,33.5573\n2014-01-25 18:50:00,34.7813\n2014-01-25 18:55:00,36.1864\n2014-01-25 19:00:00,35.8314\n2014-01-25 19:05:00,31.0277\n2014-01-25 19:10:00,35.7143\n2014-01-25 19:15:00,35.835\n2014-01-25 19:20:00,40.3379\n2014-01-25 19:25:00,30.7692\n2014-01-25 19:30:00,30.8954\n2014-01-25 19:35:00,33.3333\n2014-01-25 19:40:00,33.4427\n2014-01-25 19:45:00,35.8314\n2014-01-25 19:50:00,33.4447\n2014-01-25 19:55:00,33.3333\n2014-01-25 20:00:00,33.554\n2014-01-25 20:05:00,33.4447\n2014-01-25 20:10:00,33.446\n2014-01-25 20:15:00,33.3333\n2014-01-25 20:20:00,33.47\n2014-01-25 20:25:00,33.4742\n2014-01-25 20:30:00,35.7143\n2014-01-25 20:35:00,35.9557\n2014-01-25 20:40:00,38.9414\n2014-01-25 20:45:00,35.8314\n2014-01-25 20:50:00,35.8336\n2014-01-25 20:55:00,30.7692\n2014-01-25 21:00:00,31.0238\n2014-01-25 21:05:00,30.7692\n2014-01-25 21:10:00,33.47\n2014-01-25 21:15:00,33.3333\n2014-01-25 21:20:00,33.4427\n2014-01-25 21:25:00,33.4447\n2014-01-25 21:30:00,33.446\n2014-01-25 21:35:00,33.3333\n2014-01-25 21:40:00,33.4427\n2014-01-25 21:45:00,33.446\n2014-01-25 21:50:00,33.4447\n2014-01-25 21:55:00,33.446\n2014-01-25 22:00:00,33.4447\n2014-01-25 22:05:00,35.835\n2014-01-25 22:10:00,39.405\n2014-01-25 22:15:00,35.835\n2014-01-25 22:20:00,35.7143\n2014-01-25 22:25:00,35.8336\n2014-01-25 22:30:00,35.835\n2014-01-25 22:35:00,35.7143\n2014-01-25 22:40:00,31.0238\n2014-01-25 22:45:00,30.7692\n2014-01-25 22:50:00,33.4725\n2014-01-25 22:55:00,33.4742\n2014-01-25 23:00:00,33.5573\n2014-01-25 23:05:00,33.3333\n2014-01-25 23:10:00,33.4447\n2014-01-25 23:15:00,33.4447\n2014-01-25 23:20:00,33.3333\n2014-01-25 23:25:00,35.9529\n2014-01-25 23:30:00,33.3333\n2014-01-25 23:35:00,33.5587\n2014-01-25 23:40:00,35.7143\n2014-01-25 23:45:00,35.835\n2014-01-25 23:50:00,39.8614\n2014-01-25 23:55:00,35.8336\n2014-01-26 00:00:00,35.9521\n2014-01-26 00:05:00,35.8314\n2014-01-26 00:10:00,35.7143\n2014-01-26 00:15:00,35.9543\n2014-01-26 00:20:00,30.7692\n2014-01-26 00:25:00,30.8977\n2014-01-26 00:30:00,30.8954\n2014-01-26 00:35:00,33.3333\n2014-01-26 00:40:00,33.5553\n2014-01-26 00:45:00,33.3333\n2014-01-26 00:50:00,30.7692\n2014-01-26 00:55:00,35.9529\n2014-01-26 01:00:00,33.5573\n2014-01-26 01:05:00,33.3333\n2014-01-26 01:10:00,33.5587\n2014-01-26 01:15:00,33.3333\n2014-01-26 01:20:00,33.3333\n2014-01-26 01:25:00,33.6067\n2014-01-26 01:30:00,36.13\n2014-01-26 01:35:00,37.1429\n2014-01-26 01:40:00,35.7143\n2014-01-26 01:45:00,35.9507\n2014-01-26 01:50:00,35.7143\n2014-01-26 01:55:00,35.7143\n2014-01-26 02:00:00,35.9543\n2014-01-26 02:05:00,35.9507\n2014-01-26 02:10:00,30.7692\n2014-01-26 02:15:00,31.0254\n2014-01-26 02:20:00,33.3333\n2014-01-26 02:25:00,33.4427\n2014-01-26 02:30:00,33.5573\n2014-01-26 02:35:00,33.3333\n2014-01-26 02:40:00,33.5573\n2014-01-26 02:45:00,33.3333\n2014-01-26 02:50:00,33.3333\n2014-01-26 02:55:00,33.6687\n2014-01-26 03:00:00,33.5573\n2014-01-26 03:05:00,33.3333\n2014-01-26 03:10:00,37.5879\n2014-01-26 03:15:00,39.7621\n2014-01-26 03:20:00,37.705\n2014-01-26 03:25:00,30.7692\n2014-01-26 03:30:00,35.835\n2014-01-26 03:35:00,35.8314\n2014-01-26 03:40:00,30.7692\n2014-01-26 03:45:00,30.8992\n2014-01-26 03:50:00,30.7692\n2014-01-26 03:55:00,33.615\n2014-01-26 04:00:00,33.3333\n2014-01-26 04:05:00,33.4447\n2014-01-26 04:10:00,33.3333\n2014-01-26 04:15:00,33.5553\n2014-01-26 04:20:00,35.7143\n2014-01-26 04:25:00,33.3333\n2014-01-26 04:30:00,35.9543\n2014-01-26 04:35:00,33.3333\n2014-01-26 04:40:00,33.5553\n2014-01-26 04:45:00,33.3333\n2014-01-26 04:50:00,33.3333\n2014-01-26 04:55:00,38.9314\n2014-01-26 05:00:00,34.1127\n2014-01-26 05:05:00,33.3333\n2014-01-26 05:10:00,35.8336\n2014-01-26 05:15:00,35.835\n2014-01-26 05:20:00,35.835\n2014-01-26 05:25:00,35.835\n2014-01-26 05:30:00,30.7692\n2014-01-26 05:35:00,35.9529\n2014-01-26 05:40:00,35.7143\n2014-01-26 05:45:00,30.7692\n2014-01-26 05:50:00,33.6108\n2014-01-26 05:55:00,33.3333\n2014-01-26 06:00:00,33.556\n2014-01-26 06:05:00,33.3333\n2014-01-26 06:10:00,33.556\n2014-01-26 06:15:00,33.3333\n2014-01-26 06:20:00,33.3333\n2014-01-26 06:25:00,33.5553\n2014-01-26 06:30:00,33.3333\n2014-01-26 06:35:00,35.872\n2014-01-26 06:40:00,35.556\n2014-01-26 06:45:00,33.446\n2014-01-26 06:50:00,33.4447\n2014-01-26 06:55:00,33.3333\n2014-01-26 07:00:00,35.9557\n2014-01-26 07:05:00,35.9521\n2014-01-26 07:10:00,35.7143\n2014-01-26 07:15:00,35.7143\n2014-01-26 07:20:00,35.9543\n2014-01-26 07:25:00,30.7692\n2014-01-26 07:30:00,35.835\n2014-01-26 07:35:00,33.3333\n2014-01-26 07:40:00,30.7692\n2014-01-26 07:45:00,31.0238\n2014-01-26 07:50:00,33.3333\n2014-01-26 07:55:00,33.4427\n2014-01-26 08:00:00,30.8977\n2014-01-26 08:05:00,33.552\n2014-01-26 08:10:00,33.3333\n2014-01-26 08:15:00,35.22400000000001\n2014-01-26 08:20:00,36.1093\n2014-01-26 08:25:00,33.4447\n2014-01-26 08:30:00,33.446\n2014-01-26 08:35:00,35.7143\n2014-01-26 08:40:00,35.835\n2014-01-26 08:45:00,36.3114\n2014-01-26 08:50:00,36.3079\n2014-01-26 08:55:00,35.8314\n2014-01-26 09:00:00,35.835\n2014-01-26 09:05:00,35.835\n2014-01-26 09:10:00,35.8314\n2014-01-26 09:15:00,30.8977\n2014-01-26 09:20:00,35.8336\n2014-01-26 09:25:00,35.7143\n2014-01-26 09:30:00,30.8992\n2014-01-26 09:35:00,33.4742\n2014-01-26 09:40:00,33.4725\n2014-01-26 09:45:00,33.446\n2014-01-26 09:50:00,33.4447\n2014-01-26 09:55:00,33.8887\n2014-01-26 10:00:00,38.46\n2014-01-26 10:05:00,33.556\n2014-01-26 10:10:00,33.3333\n2014-01-26 10:15:00,33.3333\n2014-01-26 10:20:00,33.5573\n2014-01-26 10:25:00,33.3333\n2014-01-26 10:30:00,35.8336\n2014-01-26 10:35:00,35.7143\n2014-01-26 10:40:00,35.8314\n2014-01-26 10:45:00,35.8336\n2014-01-26 10:50:00,35.7143\n2014-01-26 10:55:00,35.835\n2014-01-26 11:00:00,35.9521\n2014-01-26 11:05:00,35.7143\n2014-01-26 11:10:00,30.7692\n2014-01-26 11:15:00,33.4725\n2014-01-26 11:20:00,33.4447\n2014-01-26 11:25:00,33.4427\n2014-01-26 11:30:00,33.3333\n2014-01-26 11:35:00,33.4447\n2014-01-26 11:40:00,37.8707\n2014-01-26 11:45:00,33.446\n2014-01-26 11:50:00,33.446\n2014-01-26 11:55:00,33.4447\n2014-01-26 12:00:00,33.5553\n2014-01-26 12:05:00,35.7143\n2014-01-26 12:10:00,35.835\n2014-01-26 12:15:00,35.8336\n2014-01-26 12:20:00,35.8314\n2014-01-26 12:25:00,35.7143\n2014-01-26 12:30:00,35.835\n2014-01-26 12:35:00,31.0238\n2014-01-26 12:40:00,33.4725\n2014-01-26 12:45:00,33.4427\n2014-01-26 12:50:00,33.3333\n2014-01-26 12:55:00,33.552\n2014-01-26 13:00:00,33.446\n2014-01-26 13:05:00,33.4427\n2014-01-26 13:10:00,33.3333\n2014-01-26 13:15:00,33.5573\n2014-01-26 13:20:00,36.3313\n2014-01-26 13:25:00,34.8893\n2014-01-26 13:30:00,33.47\n2014-01-26 13:35:00,33.446\n2014-01-26 13:40:00,35.9507\n2014-01-26 13:45:00,35.7143\n2014-01-26 13:50:00,35.8336\n2014-01-26 13:55:00,35.7143\n2014-01-26 14:00:00,35.9543\n2014-01-26 14:05:00,35.7143\n2014-01-26 14:10:00,35.9543\n2014-01-26 14:15:00,30.7692\n2014-01-26 14:20:00,33.3333\n2014-01-26 14:25:00,33.556\n2014-01-26 14:30:00,33.3333\n2014-01-26 14:35:00,33.5553\n2014-01-26 14:40:00,33.3333\n2014-01-26 14:45:00,33.446\n2014-01-26 14:50:00,33.4447\n2014-01-26 14:55:00,33.3333\n2014-01-26 15:00:00,35.455999999999996\n2014-01-26 15:05:00,36.11\n2014-01-26 15:10:00,33.3333\n2014-01-26 15:15:00,33.3333\n2014-01-26 15:20:00,35.9529\n2014-01-26 15:25:00,35.8314\n2014-01-26 15:30:00,35.8336\n2014-01-26 15:35:00,37.8621\n2014-01-26 15:40:00,38.2136\n2014-01-26 15:45:00,30.8954\n2014-01-26 15:50:00,36.8986\n2014-01-26 15:55:00,30.7692\n2014-01-26 16:00:00,33.6133\n2014-01-26 16:05:00,33.6133\n2014-01-26 16:10:00,33.3333\n2014-01-26 16:15:00,33.3333\n2014-01-26 16:20:00,33.5553\n2014-01-26 16:25:00,33.3333\n2014-01-26 16:30:00,33.5553\n2014-01-26 16:35:00,33.3333\n2014-01-26 16:40:00,34.3347\n2014-01-26 16:45:00,36.984\n2014-01-26 16:50:00,33.3333\n2014-01-26 16:55:00,35.9507\n2014-01-26 17:00:00,33.4427\n2014-01-26 17:05:00,35.8336\n2014-01-26 17:10:00,35.7143\n2014-01-26 17:15:00,35.9521\n2014-01-26 17:20:00,35.7143\n2014-01-26 17:25:00,35.835\n2014-01-26 17:30:00,35.835\n2014-01-26 17:35:00,35.7143\n2014-01-26 17:40:00,35.835\n2014-01-26 17:45:00,35.7143\n2014-01-26 17:50:00,30.8977\n2014-01-26 17:55:00,33.4725\n2014-01-26 18:00:00,33.446\n2014-01-26 18:05:00,33.4427\n2014-01-26 18:10:00,33.446\n2014-01-26 18:15:00,33.4447\n2014-01-26 18:20:00,33.4447\n2014-01-26 18:25:00,37.906\n2014-01-26 18:30:00,33.556\n2014-01-26 18:35:00,33.3333\n2014-01-26 18:40:00,35.7143\n2014-01-26 18:45:00,35.9543\n2014-01-26 18:50:00,35.7143\n2014-01-26 18:55:00,35.835\n2014-01-26 19:00:00,35.835\n2014-01-26 19:05:00,35.9543\n2014-01-26 19:10:00,35.7143\n2014-01-26 19:15:00,35.835\n2014-01-26 19:20:00,35.8336\n2014-01-26 19:25:00,30.8954\n2014-01-26 19:30:00,33.4742\n2014-01-26 19:35:00,33.3333\n2014-01-26 19:40:00,33.446\n2014-01-26 19:45:00,33.4447\n2014-01-26 19:50:00,33.4447\n2014-01-26 19:55:00,33.4447\n2014-01-26 20:00:00,33.4447\n2014-01-26 20:05:00,38.111999999999995\n2014-01-26 20:10:00,33.5553\n2014-01-26 20:15:00,33.3333\n2014-01-26 20:20:00,33.5573\n2014-01-26 20:25:00,33.3333\n2014-01-26 20:30:00,33.4427\n2014-01-26 20:35:00,35.8336\n2014-01-26 20:40:00,35.7143\n2014-01-26 20:45:00,35.8314\n2014-01-26 20:50:00,35.835\n2014-01-26 20:55:00,35.8336\n2014-01-26 21:00:00,35.8314\n2014-01-26 21:05:00,35.8314\n2014-01-26 21:10:00,35.8336\n2014-01-26 21:15:00,30.8977\n2014-01-26 21:20:00,30.7692\n2014-01-26 21:25:00,31.0277\n2014-01-26 21:30:00,33.3333\n2014-01-26 21:35:00,33.4725\n2014-01-26 21:40:00,33.4742\n2014-01-26 21:45:00,37.908\n2014-01-26 21:50:00,33.5573\n2014-01-26 21:55:00,33.3333\n2014-01-26 22:00:00,33.7525\n2014-01-26 22:05:00,33.3333\n2014-01-26 22:10:00,33.4427\n2014-01-26 22:15:00,33.4447\n2014-01-26 22:20:00,33.4447\n2014-01-26 22:25:00,33.4447\n2014-01-26 22:30:00,33.3333\n2014-01-26 22:35:00,35.8336\n2014-01-26 22:40:00,35.8314\n2014-01-26 22:45:00,35.8314\n2014-01-26 22:50:00,35.7143\n2014-01-26 22:55:00,35.7143\n2014-01-26 23:00:00,35.9507\n2014-01-26 23:05:00,39.5279\n2014-01-26 23:10:00,30.7692\n2014-01-26 23:15:00,30.8992\n2014-01-26 23:20:00,33.3333\n2014-01-26 23:25:00,33.4447\n2014-01-26 23:30:00,33.5593\n2014-01-26 23:35:00,33.3333\n2014-01-26 23:40:00,33.6092\n2014-01-26 23:45:00,33.3333\n2014-01-26 23:50:00,30.7692\n2014-01-26 23:55:00,33.446\n2014-01-27 00:00:00,33.556\n2014-01-27 00:05:00,33.3333\n2014-01-27 00:10:00,33.5587\n2014-01-27 00:15:00,35.7143\n2014-01-27 00:20:00,35.7143\n2014-01-27 00:25:00,35.9507\n2014-01-27 00:30:00,35.7143\n2014-01-27 00:35:00,35.8314\n2014-01-27 00:40:00,35.8336\n2014-01-27 00:45:00,38.465\n2014-01-27 00:50:00,36.7871\n2014-01-27 00:55:00,30.7692\n2014-01-27 01:00:00,31.0215\n2014-01-27 01:05:00,30.7692\n2014-01-27 01:10:00,33.4742\n2014-01-27 01:15:00,30.7692\n2014-01-27 01:20:00,33.554\n2014-01-27 01:25:00,33.3333\n2014-01-27 01:30:00,33.4447\n2014-01-27 01:35:00,33.4447\n2014-01-27 01:40:00,33.3333\n2014-01-27 01:45:00,33.5573\n2014-01-27 01:50:00,33.3333\n2014-01-27 01:55:00,33.4427\n2014-01-27 02:00:00,33.5587\n2014-01-27 02:05:00,33.4447\n2014-01-27 02:10:00,35.7143\n2014-01-27 02:15:00,35.8314\n2014-01-27 02:20:00,35.8336\n2014-01-27 02:25:00,38.465\n2014-01-27 02:30:00,36.7679\n2014-01-27 02:35:00,35.7143\n2014-01-27 02:40:00,35.8336\n2014-01-27 02:45:00,35.7143\n2014-01-27 02:50:00,35.9543\n2014-01-27 02:55:00,30.7692\n2014-01-27 03:00:00,33.6133\n2014-01-27 03:05:00,33.3333\n2014-01-27 03:10:00,33.5573\n2014-01-27 03:15:00,33.3333\n2014-01-27 03:20:00,33.4447\n2014-01-27 03:25:00,33.4447\n2014-01-27 03:30:00,33.3333\n2014-01-27 03:35:00,35.1953\n2014-01-27 03:40:00,35.2207\n2014-01-27 03:45:00,33.3333\n2014-01-27 03:50:00,33.446\n2014-01-27 03:55:00,35.835\n2014-01-27 04:00:00,35.9543\n2014-01-27 04:05:00,38.5921\n2014-01-27 04:10:00,36.5479\n2014-01-27 04:15:00,35.9529\n2014-01-27 04:20:00,35.7143\n2014-01-27 04:25:00,35.9529\n2014-01-27 04:30:00,35.7143\n2014-01-27 04:35:00,30.7692\n2014-01-27 04:40:00,31.0238\n2014-01-27 04:45:00,30.7692\n2014-01-27 04:50:00,33.6133\n2014-01-27 04:55:00,33.3333\n2014-01-27 05:00:00,33.5553\n2014-01-27 05:05:00,33.3333\n2014-01-27 05:10:00,33.552\n2014-01-27 05:15:00,33.3333\n2014-01-27 05:20:00,33.446\n2014-01-27 05:25:00,33.4427\n2014-01-27 05:30:00,33.3333\n2014-01-27 05:35:00,33.554\n2014-01-27 05:40:00,36.0714\n2014-01-27 05:45:00,39.3814\n2014-01-27 05:50:00,36.3093\n2014-01-27 05:55:00,35.7143\n2014-01-27 06:00:00,35.9507\n2014-01-27 06:05:00,35.7143\n2014-01-27 06:10:00,35.9529\n2014-01-27 06:15:00,35.7143\n2014-01-27 06:20:00,30.8954\n2014-01-27 06:25:00,33.4725\n2014-01-27 06:30:00,33.3333\n2014-01-27 06:35:00,33.3333\n2014-01-27 06:40:00,33.4447\n2014-01-27 06:45:00,33.4427\n2014-01-27 06:50:00,33.4447\n2014-01-27 06:55:00,33.446\n2014-01-27 07:00:00,33.4427\n2014-01-27 07:05:00,33.4427\n2014-01-27 07:10:00,33.4447\n2014-01-27 07:15:00,33.4427\n2014-01-27 07:20:00,33.3333\n2014-01-27 07:25:00,40.005\n2014-01-27 07:30:00,36.7879\n2014-01-27 07:35:00,35.9507\n2014-01-27 07:40:00,35.7143\n2014-01-27 07:45:00,35.9543\n2014-01-27 07:50:00,35.7143\n2014-01-27 07:55:00,35.7143\n2014-01-27 08:00:00,35.9529\n2014-01-27 08:05:00,35.9486\n2014-01-27 08:10:00,35.7143\n2014-01-27 08:15:00,35.7143\n2014-01-27 08:20:00,35.9507\n2014-01-27 08:25:00,30.7692\n2014-01-27 08:30:00,33.47\n2014-01-27 08:35:00,33.4725\n2014-01-27 08:40:00,33.4447\n2014-01-27 08:45:00,33.4447\n2014-01-27 08:50:00,33.4447\n2014-01-27 08:55:00,33.4427\n2014-01-27 09:00:00,34.0007\n2014-01-27 09:05:00,37.4633\n2014-01-27 09:10:00,33.4427\n2014-01-27 09:15:00,33.4447\n2014-01-27 09:20:00,35.7143\n2014-01-27 09:25:00,35.9529\n2014-01-27 09:30:00,35.7143\n2014-01-27 09:35:00,35.8314\n2014-01-27 09:40:00,30.8977\n2014-01-27 09:45:00,35.8314\n2014-01-27 09:50:00,30.7692\n2014-01-27 09:55:00,33.3333\n2014-01-27 10:00:00,33.6133\n2014-01-27 10:05:00,33.4447\n2014-01-27 10:10:00,33.4427\n2014-01-27 10:15:00,33.4447\n2014-01-27 10:20:00,33.446\n2014-01-27 10:25:00,33.4447\n2014-01-27 10:30:00,33.4447\n2014-01-27 10:35:00,33.3333\n2014-01-27 10:40:00,35.0167\n2014-01-27 10:45:00,38.9286\n2014-01-27 10:50:00,35.8336\n2014-01-27 10:55:00,35.835\n2014-01-27 11:00:00,35.9543\n2014-01-27 11:05:00,35.7143\n2014-01-27 11:10:00,35.8336\n2014-01-27 11:15:00,30.8954\n2014-01-27 11:20:00,30.8977\n2014-01-27 11:25:00,33.4742\n2014-01-27 11:30:00,33.3333\n2014-01-27 11:35:00,33.4427\n2014-01-27 11:40:00,33.4427\n2014-01-27 11:45:00,33.4447\n2014-01-27 11:50:00,33.4447\n2014-01-27 11:55:00,33.3333\n2014-01-27 12:00:00,33.5573\n2014-01-27 12:05:00,33.5553\n2014-01-27 12:10:00,33.3333\n2014-01-27 12:15:00,33.4447\n2014-01-27 12:20:00,37.28\n2014-01-27 12:25:00,37.9586\n2014-01-27 12:30:00,35.835\n2014-01-27 12:35:00,35.7143\n2014-01-27 12:40:00,30.8954\n2014-01-27 12:45:00,30.7692\n2014-01-27 12:50:00,33.4725\n2014-01-27 12:55:00,33.446\n2014-01-27 13:00:00,33.554\n2014-01-27 13:05:00,33.3333\n2014-01-27 13:10:00,33.4447\n2014-01-27 13:15:00,33.4427\n2014-01-27 13:20:00,35.7143\n2014-01-27 13:25:00,35.9507\n2014-01-27 13:30:00,35.7143\n2014-01-27 13:35:00,35.835\n2014-01-27 13:40:00,35.7143\n2014-01-27 13:45:00,35.7143\n2014-01-27 13:50:00,35.9543\n2014-01-27 13:55:00,30.7692\n2014-01-27 14:00:00,33.4385\n2014-01-27 14:05:00,35.0233\n2014-01-27 14:10:00,33.47\n2014-01-27 14:15:00,33.4427\n2014-01-27 14:20:00,33.4427\n2014-01-27 14:25:00,33.4427\n2014-01-27 14:30:00,33.4447\n2014-01-27 14:35:00,33.3333\n2014-01-27 14:40:00,33.4447\n2014-01-27 14:45:00,33.446\n2014-01-27 14:50:00,33.3333\n2014-01-27 14:55:00,35.9507\n2014-01-27 15:00:00,35.8314\n2014-01-27 15:05:00,35.835\n2014-01-27 15:10:00,35.7143\n2014-01-27 15:15:00,35.9543\n2014-01-27 15:20:00,35.7143\n2014-01-27 15:25:00,35.835\n2014-01-27 15:30:00,35.8314\n2014-01-27 15:35:00,30.7692\n2014-01-27 15:40:00,34.3631\n2014-01-27 15:45:00,34.0167\n2014-01-27 15:50:00,33.4742\n2014-01-27 15:55:00,33.3333\n2014-01-27 16:00:00,33.554\n2014-01-27 16:05:00,33.3333\n2014-01-27 16:10:00,33.554\n2014-01-27 16:15:00,33.3333\n2014-01-27 16:20:00,33.4447\n2014-01-27 16:25:00,33.4447\n2014-01-27 16:30:00,33.3333\n2014-01-27 16:35:00,33.556\n2014-01-27 16:40:00,33.3333\n2014-01-27 16:45:00,35.7143\n2014-01-27 16:50:00,35.9486\n2014-01-27 16:55:00,35.7143\n2014-01-27 17:00:00,35.9507\n2014-01-27 17:05:00,35.7143\n2014-01-27 17:10:00,35.9543\n2014-01-27 17:15:00,35.7143\n2014-01-27 17:20:00,39.3857\n2014-01-27 17:25:00,35.8336\n2014-01-27 17:30:00,31.0238\n2014-01-27 17:35:00,30.7692\n2014-01-27 17:40:00,33.3333\n2014-01-27 17:45:00,33.6133\n2014-01-27 17:50:00,33.3333\n2014-01-27 17:55:00,33.554\n2014-01-27 18:00:00,33.4725\n2014-01-27 18:05:00,33.5587\n2014-01-27 18:10:00,33.3333\n2014-01-27 18:15:00,33.446\n2014-01-27 18:20:00,33.4447\n2014-01-27 18:25:00,33.3333\n2014-01-27 18:30:00,33.5553\n2014-01-27 18:35:00,33.3333\n2014-01-27 18:40:00,33.4427\n2014-01-27 18:45:00,33.4447\n2014-01-27 18:50:00,33.4447\n2014-01-27 18:55:00,33.4427\n2014-01-27 19:00:00,38.0007\n2014-01-27 19:05:00,33.4447\n2014-01-27 19:10:00,33.446\n2014-01-27 19:15:00,35.7143\n2014-01-27 19:20:00,35.8336\n2014-01-27 19:25:00,35.835\n2014-01-27 19:30:00,35.7143\n2014-01-27 19:35:00,35.9507\n2014-01-27 19:40:00,35.7143\n2014-01-27 19:45:00,35.9529\n2014-01-27 19:50:00,35.7143\n2014-01-27 19:55:00,30.7692\n2014-01-27 20:00:00,31.0215\n2014-01-27 20:05:00,30.7692\n2014-01-27 20:10:00,33.4742\n2014-01-27 20:15:00,33.3333\n2014-01-27 20:20:00,33.554\n2014-01-27 20:25:00,33.3333\n2014-01-27 20:30:00,33.556\n2014-01-27 20:35:00,34.0\n2014-01-27 20:40:00,37.2153\n2014-01-27 20:45:00,33.4427\n2014-01-27 20:50:00,33.3333\n2014-01-27 20:55:00,33.6633\n2014-01-27 21:00:00,33.4427\n2014-01-27 21:05:00,35.835\n2014-01-27 21:10:00,35.9486\n2014-01-27 21:15:00,35.835\n2014-01-27 21:20:00,35.8336\n2014-01-27 21:25:00,35.835\n2014-01-27 21:30:00,38.0771\n2014-01-27 21:35:00,38.2229\n2014-01-27 21:40:00,35.8336\n2014-01-27 21:45:00,35.7143\n2014-01-27 21:50:00,35.8336\n2014-01-27 21:55:00,33.4725\n2014-01-27 22:00:00,31.0238\n2014-01-27 22:05:00,30.7692\n2014-01-27 22:10:00,33.4725\n2014-01-27 22:15:00,34.8633\n2014-01-27 22:20:00,38.4343\n2014-01-27 22:25:00,33.4447\n2014-01-27 22:30:00,33.4427\n2014-01-27 22:35:00,33.446\n2014-01-27 22:40:00,33.3333\n2014-01-27 22:45:00,33.5573\n2014-01-27 22:50:00,33.3333\n2014-01-27 22:55:00,33.4447\n2014-01-27 23:00:00,35.8336\n2014-01-27 23:05:00,35.835\n2014-01-27 23:10:00,35.7143\n2014-01-27 23:15:00,35.8314\n2014-01-27 23:20:00,35.8336\n2014-01-27 23:25:00,35.8336\n2014-01-27 23:30:00,35.7143\n2014-01-27 23:35:00,35.8336\n2014-01-27 23:40:00,30.7692\n2014-01-27 23:45:00,30.8977\n2014-01-27 23:50:00,33.4742\n2014-01-27 23:55:00,37.326\n2014-01-28 00:00:00,33.556\n2014-01-28 00:05:00,33.4447\n2014-01-28 00:10:00,33.4447\n2014-01-28 00:15:00,33.3333\n2014-01-28 00:20:00,33.4427\n2014-01-28 00:25:00,33.4447\n2014-01-28 00:30:00,33.4427\n2014-01-28 00:35:00,33.4447\n2014-01-28 00:40:00,33.4447\n2014-01-28 00:45:00,33.3333\n2014-01-28 00:50:00,33.446\n2014-01-28 00:55:00,35.3427\n2014-01-28 01:00:00,35.9543\n2014-01-28 01:05:00,35.7143\n2014-01-28 01:10:00,35.835\n2014-01-28 01:15:00,35.8336\n2014-01-28 01:20:00,35.7143\n2014-01-28 01:25:00,35.9529\n2014-01-28 01:30:00,35.7143\n2014-01-28 01:35:00,35.8314\n2014-01-28 01:40:00,35.8314\n2014-01-28 01:45:00,30.7692\n2014-01-28 01:50:00,33.47\n2014-01-28 01:55:00,33.4725\n2014-01-28 02:00:00,36.332\n2014-01-28 02:05:00,35.2167\n2014-01-28 02:10:00,33.3333\n2014-01-28 02:15:00,33.4447\n2014-01-28 02:20:00,33.4447\n2014-01-28 02:25:00,33.4427\n2014-01-28 02:30:00,33.4427\n2014-01-28 02:35:00,33.3333\n2014-01-28 02:40:00,33.4427\n2014-01-28 02:45:00,33.4447\n2014-01-28 02:50:00,33.4447\n2014-01-28 02:55:00,33.446\n2014-01-28 03:00:00,35.8336\n2014-01-28 03:05:00,35.8336\n2014-01-28 03:10:00,37.7386\n2014-01-28 03:15:00,35.8336\n2014-01-28 03:20:00,37.5914\n2014-01-28 03:25:00,35.8314\n2014-01-28 03:30:00,35.7143\n2014-01-28 03:35:00,35.835\n2014-01-28 03:40:00,30.7692\n2014-01-28 03:45:00,30.8977\n2014-01-28 03:50:00,33.4725\n2014-01-28 03:55:00,33.3333\n2014-01-28 04:00:00,33.5553\n2014-01-28 04:05:00,33.446\n2014-01-28 04:10:00,33.4427\n2014-01-28 04:15:00,35.3333\n2014-01-28 04:20:00,35.9893\n2014-01-28 04:25:00,33.4427\n2014-01-28 04:30:00,33.4447\n2014-01-28 04:35:00,33.4447\n2014-01-28 04:40:00,33.4427\n2014-01-28 04:45:00,33.4447\n2014-01-28 04:50:00,35.8336\n2014-01-28 04:55:00,35.835\n2014-01-28 05:00:00,35.9543\n2014-01-28 05:05:00,35.7143\n2014-01-28 05:10:00,35.8314\n2014-01-28 05:15:00,35.8314\n2014-01-28 05:20:00,35.7143\n2014-01-28 05:25:00,35.8314\n2014-01-28 05:30:00,30.7692\n2014-01-28 05:35:00,31.0262\n2014-01-28 05:40:00,30.7692\n2014-01-28 05:45:00,30.8977\n2014-01-28 05:50:00,30.8977\n2014-01-28 05:55:00,33.3333\n2014-01-28 06:00:00,33.6108\n2014-01-28 06:05:00,33.4427\n2014-01-28 06:10:00,33.4447\n2014-01-28 06:15:00,34.7613\n2014-01-28 06:20:00,35.1227\n2014-01-28 06:25:00,33.3333\n2014-01-28 06:30:00,33.5573\n2014-01-28 06:35:00,33.3333\n2014-01-28 06:40:00,35.835\n2014-01-28 06:45:00,35.8336\n2014-01-28 06:50:00,35.7143\n2014-01-28 06:55:00,35.9529\n2014-01-28 07:00:00,35.8336\n2014-01-28 07:05:00,35.8336\n2014-01-28 07:10:00,35.8336\n2014-01-28 07:15:00,30.8992\n2014-01-28 07:20:00,30.7692\n2014-01-28 07:25:00,33.6067\n2014-01-28 07:30:00,33.3333\n2014-01-28 07:35:00,33.4742\n2014-01-28 07:40:00,33.3333\n2014-01-28 07:45:00,33.3333\n2014-01-28 07:50:00,37.4447\n2014-01-28 07:55:00,34.0\n2014-01-28 08:00:00,33.5553\n2014-01-28 08:05:00,33.4447\n2014-01-28 08:10:00,33.4447\n2014-01-28 08:15:00,33.4447\n2014-01-28 08:20:00,33.3333\n2014-01-28 08:25:00,33.552\n2014-01-28 08:30:00,35.8314\n2014-01-28 08:35:00,35.8336\n2014-01-28 08:40:00,35.8336\n2014-01-28 08:45:00,35.7143\n2014-01-28 08:50:00,35.9521\n2014-01-28 08:55:00,30.7692\n2014-01-28 09:00:00,31.0277\n2014-01-28 09:05:00,30.8954\n2014-01-28 09:10:00,33.4725\n2014-01-28 09:15:00,33.3333\n2014-01-28 09:20:00,33.446\n2014-01-28 09:25:00,33.3333\n2014-01-28 09:30:00,33.4447\n2014-01-28 09:35:00,33.4447\n2014-01-28 09:40:00,33.4447\n2014-01-28 09:45:00,33.4427\n2014-01-28 09:50:00,33.3333\n2014-01-28 09:55:00,38.004\n2014-01-28 10:00:00,35.9557\n2014-01-28 10:05:00,35.7143\n2014-01-28 10:10:00,35.9507\n2014-01-28 10:15:00,35.7143\n2014-01-28 10:20:00,35.9529\n2014-01-28 10:25:00,35.7143\n2014-01-28 10:30:00,35.7143\n2014-01-28 10:35:00,31.0254\n2014-01-28 10:40:00,30.7692\n2014-01-28 10:45:00,33.4725\n2014-01-28 10:50:00,33.4447\n2014-01-28 10:55:00,33.446\n2014-01-28 11:00:00,35.0007\n2014-01-28 11:05:00,34.8893\n2014-01-28 11:10:00,33.4427\n2014-01-28 11:15:00,33.4447\n2014-01-28 11:20:00,33.446\n2014-01-28 11:25:00,33.3333\n2014-01-28 11:30:00,33.4447\n2014-01-28 11:35:00,35.8314\n2014-01-28 11:40:00,36.0714\n2014-01-28 11:45:00,36.5493\n2014-01-28 11:50:00,38.4457\n2014-01-28 11:55:00,39.1786\n2014-01-28 12:00:00,42.1307\n2014-01-28 12:05:00,35.7143\n2014-01-28 12:10:00,35.9543\n2014-01-28 12:15:00,30.7692\n2014-01-28 12:20:00,30.8954\n2014-01-28 12:25:00,33.3333\n2014-01-28 12:30:00,33.3333\n2014-01-28 12:35:00,33.554\n2014-01-28 12:40:00,33.3333\n2014-01-28 12:45:00,33.4447\n2014-01-28 12:50:00,33.4447\n2014-01-28 12:55:00,33.4427\n2014-01-28 13:00:00,33.4447\n2014-01-28 13:05:00,33.446\n2014-01-28 13:10:00,33.4427\n2014-01-28 13:15:00,33.4427\n2014-01-28 13:20:00,33.446\n2014-01-28 13:25:00,33.3333\n2014-01-28 13:30:00,35.8314\n2014-01-28 13:35:00,35.835\n2014-01-28 13:40:00,35.835\n2014-01-28 13:45:00,37.1507\n2014-01-28 13:50:00,37.0143\n2014-01-28 13:55:00,37.985\n2014-01-28 14:00:00,39.0207\n2014-01-28 14:05:00,41.7907\n2014-01-28 14:10:00,37.9671\n2014-01-28 14:15:00,36.1964\n2014-01-28 14:20:00,35.8336\n2014-01-28 14:25:00,35.7143\n2014-01-28 14:30:00,35.9543\n2014-01-28 14:35:00,35.7143\n2014-01-28 14:40:00,35.835\n2014-01-28 14:45:00,30.8977\n2014-01-28 14:50:00,30.8954\n2014-01-28 14:55:00,33.3333\n2014-01-28 15:00:00,33.6108\n2014-01-28 15:05:00,33.4447\n2014-01-28 15:10:00,33.4427\n2014-01-28 15:15:00,33.3333\n2014-01-28 15:20:00,33.446\n2014-01-28 15:25:00,33.4447\n2014-01-28 15:30:00,33.3333\n2014-01-28 15:35:00,33.5573\n2014-01-28 15:40:00,33.3333\n2014-01-28 15:45:00,33.5553\n2014-01-28 15:50:00,33.3333\n2014-01-28 15:55:00,33.3333\n2014-01-28 16:00:00,33.554\n2014-01-28 16:05:00,34.554\n2014-01-28 16:10:00,36.78\n2014-01-28 16:15:00,35.8336\n2014-01-28 16:20:00,35.8336\n2014-01-28 16:25:00,35.8314\n2014-01-28 16:30:00,35.7143\n2014-01-28 16:35:00,35.8314\n2014-01-28 16:40:00,35.7143\n2014-01-28 16:45:00,35.8336\n2014-01-28 16:50:00,35.8314\n2014-01-28 16:55:00,35.7143\n2014-01-28 17:00:00,35.9486\n2014-01-28 17:05:00,35.8314\n2014-01-28 17:10:00,30.8992\n2014-01-28 17:15:00,30.7692\n2014-01-28 17:20:00,33.6092\n2014-01-28 17:25:00,33.3333\n2014-01-28 17:30:00,33.5573\n2014-01-28 17:35:00,33.3333\n2014-01-28 17:40:00,33.3333\n2014-01-28 17:45:00,33.5553\n2014-01-28 17:50:00,33.3333\n2014-01-28 17:55:00,33.4447\n2014-01-28 18:00:00,33.446\n2014-01-28 18:05:00,33.5553\n2014-01-28 18:10:00,33.8887\n2014-01-28 18:15:00,37.33\n2014-01-28 18:20:00,35.9507\n2014-01-28 18:25:00,35.7143\n2014-01-28 18:30:00,35.9543\n2014-01-28 18:35:00,37.9764\n2014-01-28 18:40:00,38.0957\n2014-01-28 18:45:00,35.8314\n2014-01-28 18:50:00,35.8314\n2014-01-28 18:55:00,35.8314\n2014-01-28 19:00:00,30.8977\n2014-01-28 19:05:00,30.8954\n2014-01-28 19:10:00,33.47\n2014-01-28 19:15:00,33.4725\n2014-01-28 19:20:00,33.3333\n2014-01-28 19:25:00,33.446\n2014-01-28 19:30:00,33.446\n2014-01-28 19:35:00,33.4447\n2014-01-28 19:40:00,33.4447\n2014-01-28 19:45:00,33.3333\n2014-01-28 19:50:00,33.5573\n2014-01-28 19:55:00,33.446\n2014-01-28 20:00:00,33.554\n2014-01-28 20:05:00,33.3333\n2014-01-28 20:10:00,33.5587\n2014-01-28 20:15:00,33.5553\n2014-01-28 20:20:00,40.5943\n2014-01-28 20:25:00,35.9521\n2014-01-28 20:30:00,35.7143\n2014-01-28 20:35:00,35.9507\n2014-01-28 20:40:00,35.7143\n2014-01-28 20:45:00,35.835\n2014-01-28 20:50:00,35.8336\n2014-01-28 20:55:00,35.8314\n2014-01-28 21:00:00,30.8977\n2014-01-28 21:05:00,35.835\n2014-01-28 21:10:00,30.7692\n2014-01-28 21:15:00,30.8977\n2014-01-28 21:20:00,33.4742\n2014-01-28 21:25:00,33.3333\n2014-01-28 21:30:00,33.4427\n2014-01-28 21:35:00,33.4427\n2014-01-28 21:40:00,33.4447\n2014-01-28 21:45:00,33.4427\n2014-01-28 21:50:00,33.3333\n2014-01-28 21:55:00,33.446\n2014-01-28 22:00:00,34.001999999999995\n2014-01-28 22:05:00,33.8873\n2014-01-28 22:10:00,33.6687\n2014-01-28 22:15:00,33.4447\n2014-01-28 22:20:00,33.8887\n2014-01-28 22:25:00,39.9893\n2014-01-28 22:30:00,36.0679\n2014-01-28 22:35:00,36.675\n2014-01-28 22:40:00,35.8336\n2014-01-28 22:45:00,35.8336\n2014-01-28 22:50:00,35.8336\n2014-01-28 22:55:00,35.8336\n2014-01-28 23:00:00,35.8336\n2014-01-28 23:05:00,35.7143\n2014-01-28 23:10:00,35.835\n2014-01-28 23:15:00,35.8336\n2014-01-28 23:20:00,30.7692\n2014-01-28 23:25:00,33.4742\n2014-01-28 23:30:00,33.47\n2014-01-28 23:35:00,33.4447\n2014-01-28 23:40:00,33.4447\n2014-01-28 23:45:00,33.4427\n2014-01-28 23:50:00,33.3333\n2014-01-28 23:55:00,33.4447\n2014-01-29 00:00:00,33.5573\n2014-01-29 00:05:00,33.446\n2014-01-29 00:10:00,33.3333\n2014-01-29 00:15:00,33.556\n2014-01-29 00:20:00,33.3333\n2014-01-29 00:25:00,37.1229\n2014-01-29 00:30:00,39.3043\n2014-01-29 00:35:00,39.6579\n2014-01-29 00:40:00,32.6018\n2014-01-29 00:45:00,1.334\n2014-01-29 00:50:00,0.996\n2014-01-29 00:55:00,1.006\n2014-01-29 01:00:00,0.6659999999999999\n2014-01-29 01:05:00,0.0\n2014-01-29 01:10:00,0.33399999999999996\n2014-01-29 01:15:00,0.0\n2014-01-29 01:20:00,0.33399999999999996\n2014-01-29 01:25:00,0.0\n2014-01-29 01:30:00,0.0\n2014-01-29 01:35:00,0.32799999999999996\n2014-01-29 01:40:00,0.0\n2014-01-29 01:45:00,0.33399999999999996\n2014-01-29 01:50:00,0.0\n2014-01-29 01:55:00,0.0\n2014-01-29 02:00:00,0.32799999999999996\n2014-01-29 02:05:00,0.33799999999999997\n2014-01-29 02:10:00,0.0\n2014-01-29 02:15:00,0.32799999999999996\n2014-01-29 02:20:00,0.0\n2014-01-29 02:25:00,0.0\n2014-01-29 02:30:00,10.008\n2014-01-29 02:35:00,3.9619999999999997\n2014-01-29 02:40:00,0.0\n2014-01-29 02:45:00,0.0\n2014-01-29 02:50:00,0.32799999999999996\n2014-01-29 02:55:00,0.0\n2014-01-29 03:00:00,0.33399999999999996\n2014-01-29 03:05:00,0.0\n2014-01-29 03:10:00,0.33399999999999996\n2014-01-29 03:15:00,0.0\n2014-01-29 03:20:00,0.33799999999999997\n2014-01-29 03:25:00,0.0\n2014-01-29 03:30:00,0.33399999999999996\n2014-01-29 03:35:00,5.084\n2014-01-29 03:40:00,0.33399999999999996\n2014-01-29 03:45:00,0.0\n2014-01-29 03:50:00,0.33399999999999996\n2014-01-29 03:55:00,0.0\n2014-01-29 04:00:00,0.32799999999999996\n2014-01-29 04:05:00,0.0\n2014-01-29 04:10:00,0.33799999999999997\n2014-01-29 04:15:00,0.6559999999999999\n2014-01-29 04:20:00,3.034\n2014-01-29 04:25:00,0.0\n2014-01-29 04:30:00,14.014000000000001\n2014-01-29 04:35:00,0.0\n2014-01-29 04:40:00,0.0\n2014-01-29 04:45:00,0.33799999999999997\n2014-01-29 04:50:00,0.0\n2014-01-29 04:55:00,0.33799999999999997\n2014-01-29 05:00:00,0.0\n2014-01-29 05:05:00,0.33399999999999996\n2014-01-29 05:10:00,0.0\n2014-01-29 05:15:00,0.33399999999999996\n2014-01-29 05:20:00,0.0\n2014-01-29 05:25:00,0.0\n2014-01-29 05:30:00,0.32799999999999996\n2014-01-29 05:35:00,0.0\n2014-01-29 05:40:00,0.32799999999999996\n2014-01-29 05:45:00,0.0\n2014-01-29 05:50:00,0.0\n2014-01-29 05:55:00,0.6659999999999999\n2014-01-29 06:00:00,0.33399999999999996\n2014-01-29 06:05:00,0.0\n2014-01-29 06:10:00,0.0\n2014-01-29 06:15:00,0.32799999999999996\n2014-01-29 06:20:00,0.0\n2014-01-29 06:25:00,2.63\n2014-01-29 06:30:00,11.03\n2014-01-29 06:35:00,0.32799999999999996\n2014-01-29 06:40:00,0.0\n2014-01-29 06:45:00,0.33399999999999996\n2014-01-29 06:50:00,0.0\n2014-01-29 06:55:00,0.0\n2014-01-29 07:00:00,0.33799999999999997\n2014-01-29 07:05:00,0.33399999999999996\n2014-01-29 07:10:00,0.0\n2014-01-29 07:15:00,0.0\n2014-01-29 07:20:00,0.33399999999999996\n2014-01-29 07:25:00,0.0\n2014-01-29 07:30:00,0.33799999999999997\n2014-01-29 07:35:00,0.0\n2014-01-29 07:40:00,0.33399999999999996\n2014-01-29 07:45:00,0.0\n2014-01-29 07:50:00,0.0\n2014-01-29 07:55:00,0.33399999999999996\n2014-01-29 08:00:00,0.0\n2014-01-29 08:05:00,0.33399999999999996\n2014-01-29 08:10:00,0.0\n2014-01-29 08:15:00,0.33399999999999996\n2014-01-29 08:20:00,0.0\n2014-01-29 08:25:00,12.014000000000001\n2014-01-29 08:30:00,1.64\n2014-01-29 08:35:00,0.0\n2014-01-29 08:40:00,0.4225\n2014-01-29 08:45:00,0.0\n2014-01-29 08:50:00,0.32799999999999996\n2014-01-29 08:55:00,0.0\n2014-01-29 09:00:00,0.33399999999999996\n2014-01-29 09:05:00,0.0\n2014-01-29 09:10:00,0.33399999999999996\n2014-01-29 09:15:00,0.0\n2014-01-29 09:20:00,0.33799999999999997\n2014-01-29 09:25:00,0.0\n2014-01-29 09:30:00,0.0\n2014-01-29 09:35:00,0.33399999999999996\n2014-01-29 09:40:00,0.0\n2014-01-29 09:45:00,0.33799999999999997\n2014-01-29 09:50:00,0.0\n2014-01-29 09:55:00,0.32799999999999996\n2014-01-29 10:00:00,0.0\n2014-01-29 10:05:00,0.32799999999999996\n2014-01-29 10:10:00,0.0\n2014-01-29 10:15:00,0.33799999999999997\n2014-01-29 10:20:00,2.0340000000000003\n2014-01-29 10:25:00,11.652000000000001\n2014-01-29 10:30:00,0.0\n2014-01-29 10:35:00,0.32799999999999996\n2014-01-29 10:40:00,0.0\n2014-01-29 10:45:00,0.32799999999999996\n2014-01-29 10:50:00,0.0\n2014-01-29 10:55:00,0.0\n2014-01-29 11:00:00,0.33399999999999996\n2014-01-29 11:05:00,0.33399999999999996\n2014-01-29 11:10:00,0.0\n2014-01-29 11:15:00,0.0\n2014-01-29 11:20:00,0.33799999999999997\n2014-01-29 11:25:00,0.0\n2014-01-29 11:30:00,0.32799999999999996\n2014-01-29 11:35:00,0.0\n2014-01-29 11:40:00,0.33399999999999996\n2014-01-29 11:45:00,0.0\n2014-01-29 11:50:00,0.0\n2014-01-29 11:55:00,0.33399999999999996\n2014-01-29 12:00:00,0.33799999999999997\n2014-01-29 12:05:00,0.0\n2014-01-29 12:10:00,0.0\n2014-01-29 12:15:00,0.33399999999999996\n2014-01-29 12:20:00,10.39\n2014-01-29 12:25:00,3.3339999999999996\n2014-01-29 12:30:00,0.33399999999999996\n2014-01-29 12:35:00,0.0\n2014-01-29 12:40:00,0.0\n2014-01-29 12:45:00,0.33399999999999996\n2014-01-29 12:50:00,0.0\n2014-01-29 12:55:00,0.33399999999999996\n2014-01-29 13:00:00,0.0\n2014-01-29 13:05:00,0.4175\n2014-01-29 13:10:00,0.0\n2014-01-29 13:15:00,0.33399999999999996\n2014-01-29 13:20:00,0.0\n2014-01-29 13:25:00,0.0\n2014-01-29 13:30:00,0.33799999999999997\n2014-01-29 13:35:00,0.0\n2014-01-29 13:40:00,0.33399999999999996\n2014-01-29 13:45:00,0.0\n2014-01-29 13:50:00,0.0\n2014-01-29 13:55:00,0.32799999999999996\n2014-01-29 14:00:00,0.33399999999999996\n2014-01-29 14:05:00,0.0\n2014-01-29 14:10:00,0.0\n2014-01-29 14:15:00,1.69\n2014-01-29 14:20:00,12.328\n2014-01-29 14:25:00,0.33799999999999997\n2014-01-29 14:30:00,0.0\n2014-01-29 14:35:00,0.33399999999999996\n2014-01-29 14:40:00,0.0\n2014-01-29 14:45:00,0.33399999999999996\n2014-01-29 14:50:00,0.0\n2014-01-29 14:55:00,0.0\n2014-01-29 15:00:00,0.33399999999999996\n2014-01-29 15:05:00,0.32799999999999996\n2014-01-29 15:10:00,0.0\n2014-01-29 15:15:00,0.32799999999999996\n2014-01-29 15:20:00,0.33399999999999996\n2014-01-29 15:25:00,0.0\n2014-01-29 15:30:00,0.33399999999999996\n2014-01-29 15:35:00,0.0\n2014-01-29 15:40:00,0.33399999999999996\n2014-01-29 15:45:00,2.34\n2014-01-29 15:50:00,0.32799999999999996\n2014-01-29 15:55:00,0.0\n2014-01-29 16:00:00,0.33799999999999997\n2014-01-29 16:05:00,0.0\n2014-01-29 16:10:00,0.32799999999999996\n2014-01-29 16:15:00,6.662000000000001\n2014-01-29 16:20:00,6.95\n2014-01-29 16:25:00,0.0\n2014-01-29 16:30:00,0.33799999999999997\n2014-01-29 16:35:00,0.0\n2014-01-29 16:40:00,0.32799999999999996\n2014-01-29 16:45:00,0.0\n2014-01-29 16:50:00,0.33399999999999996\n2014-01-29 16:55:00,0.0\n2014-01-29 17:00:00,0.33399999999999996\n2014-01-29 17:05:00,0.0\n2014-01-29 17:10:00,0.33799999999999997\n2014-01-29 17:15:00,0.0\n2014-01-29 17:20:00,0.0\n2014-01-29 17:25:00,0.32799999999999996\n2014-01-29 17:30:00,0.0\n2014-01-29 17:35:00,0.32799999999999996\n2014-01-29 17:40:00,0.0\n2014-01-29 17:45:00,0.33799999999999997\n2014-01-29 17:50:00,0.0\n2014-01-29 17:55:00,0.0\n2014-01-29 18:00:00,0.33399999999999996\n2014-01-29 18:05:00,0.33399999999999996\n2014-01-29 18:10:00,0.0\n2014-01-29 18:15:00,1.64\n2014-01-29 18:20:00,11.995999999999999\n2014-01-29 18:25:00,0.33399999999999996\n2014-01-29 18:30:00,0.0\n2014-01-29 18:35:00,0.33399999999999996\n2014-01-29 18:40:00,0.0\n2014-01-29 18:45:00,0.0\n2014-01-29 18:50:00,0.33399999999999996\n2014-01-29 18:55:00,0.0\n2014-01-29 19:00:00,0.33399999999999996\n2014-01-29 19:05:00,0.0\n2014-01-29 19:10:00,0.33399999999999996\n2014-01-29 19:15:00,0.0\n2014-01-29 19:20:00,0.33799999999999997\n2014-01-29 19:25:00,0.0\n2014-01-29 19:30:00,0.0\n2014-01-29 19:35:00,0.33799999999999997\n2014-01-29 19:40:00,0.0\n2014-01-29 19:45:00,0.33399999999999996\n2014-01-29 19:50:00,0.0\n2014-01-29 19:55:00,0.33399999999999996\n2014-01-29 20:00:00,0.0\n2014-01-29 20:05:00,0.33399999999999996\n2014-01-29 20:10:00,0.0\n2014-01-29 20:15:00,0.33399999999999996\n2014-01-29 20:20:00,13.34\n2014-01-29 20:25:00,0.32799999999999996\n2014-01-29 20:30:00,0.0\n2014-01-29 20:35:00,0.33399999999999996\n2014-01-29 20:40:00,0.0\n2014-01-29 20:45:00,0.0\n2014-01-29 20:50:00,0.33399999999999996\n2014-01-29 20:55:00,0.0\n2014-01-29 21:00:00,0.32799999999999996\n2014-01-29 21:05:00,0.0\n2014-01-29 21:10:00,0.33799999999999997\n2014-01-29 21:15:00,0.0\n2014-01-29 21:20:00,0.33399999999999996\n2014-01-29 21:25:00,0.0\n2014-01-29 21:30:00,0.33399999999999996\n2014-01-29 21:35:00,0.0\n2014-01-29 21:40:00,0.33399999999999996\n2014-01-29 21:45:00,0.0\n2014-01-29 21:50:00,0.33799999999999997\n2014-01-29 21:55:00,0.0\n2014-01-29 22:00:00,0.41\n2014-01-29 22:05:00,0.0\n2014-01-29 22:10:00,0.4225\n2014-01-29 22:15:00,2.0\n2014-01-29 22:20:00,11.662\n2014-01-29 22:25:00,0.0\n2014-01-29 22:30:00,0.32799999999999996\n2014-01-29 22:35:00,0.0\n2014-01-29 22:40:00,0.33799999999999997\n2014-01-29 22:45:00,0.0\n2014-01-29 22:50:00,0.0\n2014-01-29 22:55:00,0.33399999999999996\n2014-01-29 23:00:00,0.32799999999999996\n2014-01-29 23:05:00,0.0\n2014-01-29 23:10:00,0.0\n2014-01-29 23:15:00,0.33799999999999997\n2014-01-29 23:20:00,0.0\n2014-01-29 23:25:00,0.32799999999999996\n2014-01-29 23:30:00,0.0\n2014-01-29 23:35:00,0.33399999999999996\n2014-01-29 23:40:00,0.0\n2014-01-29 23:45:00,0.0\n2014-01-29 23:50:00,0.33399999999999996\n2014-01-29 23:55:00,0.0\n2014-01-30 00:00:00,0.33399999999999996\n2014-01-30 00:05:00,0.0\n2014-01-30 00:10:00,0.32799999999999996\n2014-01-30 00:15:00,0.0\n2014-01-30 00:20:00,13.68\n2014-01-30 00:25:00,0.33399999999999996\n2014-01-30 00:30:00,0.0\n2014-01-30 00:35:00,0.6679999999999999\n2014-01-30 00:40:00,0.0\n2014-01-30 00:45:00,0.32799999999999996\n2014-01-30 00:50:00,0.0\n2014-01-30 00:55:00,0.0\n2014-01-30 01:00:00,0.4225\n2014-01-30 01:05:00,0.0\n2014-01-30 01:10:00,0.0\n2014-01-30 01:15:00,0.0\n2014-01-30 01:20:00,0.33399999999999996\n2014-01-30 01:25:00,0.0\n2014-01-30 01:30:00,0.32799999999999996\n2014-01-30 01:35:00,0.0\n2014-01-30 01:40:00,0.0\n2014-01-30 01:45:00,0.33399999999999996\n2014-01-30 01:50:00,0.33399999999999996\n2014-01-30 01:55:00,0.0\n2014-01-30 02:00:00,0.32799999999999996\n2014-01-30 02:05:00,0.0\n2014-01-30 02:10:00,0.32799999999999996\n2014-01-30 02:15:00,5.612\n2014-01-30 02:20:00,8.056000000000001\n2014-01-30 02:25:00,0.0\n2014-01-30 02:30:00,0.32799999999999996\n2014-01-30 02:35:00,0.0\n2014-01-30 02:40:00,0.0\n2014-01-30 02:45:00,0.33399999999999996\n2014-01-30 02:50:00,0.0\n2014-01-30 02:55:00,0.33399999999999996\n2014-01-30 03:00:00,0.32799999999999996\n2014-01-30 03:05:00,4.918\n2014-01-30 03:10:00,0.32799999999999996\n2014-01-30 03:15:00,0.0\n2014-01-30 03:20:00,0.0\n2014-01-30 03:25:00,0.33399999999999996\n2014-01-30 03:30:00,0.0\n2014-01-30 03:35:00,0.32799999999999996\n2014-01-30 03:40:00,0.0\n2014-01-30 03:45:00,0.33399999999999996\n2014-01-30 03:50:00,0.0\n2014-01-30 03:55:00,0.0\n2014-01-30 04:00:00,0.33799999999999997\n2014-01-30 04:05:00,0.0\n2014-01-30 04:10:00,0.32799999999999996\n2014-01-30 04:15:00,13.652000000000001\n2014-01-30 04:20:00,0.0\n2014-01-30 04:25:00,0.33399999999999996\n2014-01-30 04:30:00,0.0\n2014-01-30 04:35:00,0.32799999999999996\n2014-01-30 04:40:00,0.0\n2014-01-30 04:45:00,0.0\n2014-01-30 04:50:00,0.32799999999999996\n2014-01-30 04:55:00,0.0\n2014-01-30 05:00:00,0.33799999999999997\n2014-01-30 05:05:00,0.0\n2014-01-30 05:10:00,0.33799999999999997\n2014-01-30 05:15:00,0.0\n2014-01-30 05:20:00,0.33799999999999997\n2014-01-30 05:25:00,0.0\n2014-01-30 05:30:00,0.0\n2014-01-30 05:35:00,0.32799999999999996\n2014-01-30 05:40:00,0.0\n2014-01-30 05:45:00,0.33799999999999997\n2014-01-30 05:50:00,0.0\n2014-01-30 05:55:00,0.0\n2014-01-30 06:00:00,0.32799999999999996\n2014-01-30 06:05:00,0.32799999999999996\n2014-01-30 06:10:00,11.612\n2014-01-30 06:15:00,2.0\n2014-01-30 06:20:00,0.0\n2014-01-30 06:25:00,0.33399999999999996\n2014-01-30 06:30:00,0.0\n2014-01-30 06:35:00,0.33799999999999997\n2014-01-30 06:40:00,0.0\n2014-01-30 06:45:00,0.0\n2014-01-30 06:50:00,0.33399999999999996\n2014-01-30 06:55:00,0.0\n2014-01-30 07:00:00,0.33799999999999997\n2014-01-30 07:05:00,0.0\n2014-01-30 07:10:00,0.33799999999999997\n2014-01-30 07:15:00,0.0\n2014-01-30 07:20:00,0.33399999999999996\n2014-01-30 07:25:00,0.0\n2014-01-30 07:30:00,0.33399999999999996\n2014-01-30 07:35:00,0.0\n2014-01-30 07:40:00,0.0\n2014-01-30 07:45:00,0.33399999999999996\n2014-01-30 07:50:00,0.0\n2014-01-30 07:55:00,0.33399999999999996\n2014-01-30 08:00:00,0.0\n2014-01-30 08:05:00,13.968\n2014-01-30 08:10:00,0.0\n2014-01-30 08:15:00,0.0\n2014-01-30 08:20:00,0.32799999999999996\n2014-01-30 08:25:00,0.0\n2014-01-30 08:30:00,0.33799999999999997\n2014-01-30 08:35:00,0.0\n2014-01-30 08:40:00,0.33399999999999996\n2014-01-30 08:45:00,0.0\n2014-01-30 08:50:00,0.0\n2014-01-30 08:55:00,0.33399999999999996\n2014-01-30 09:00:00,0.33799999999999997\n2014-01-30 09:05:00,0.0\n2014-01-30 09:10:00,0.0\n2014-01-30 09:15:00,0.32799999999999996\n2014-01-30 09:20:00,0.0\n2014-01-30 09:25:00,0.33399999999999996\n2014-01-30 09:30:00,0.0\n2014-01-30 09:35:00,0.0\n2014-01-30 09:40:00,0.32799999999999996\n2014-01-30 09:45:00,0.0\n2014-01-30 09:50:00,0.33799999999999997\n2014-01-30 09:55:00,6.95\n2014-01-30 10:00:00,6.666\n2014-01-30 10:05:00,0.33399999999999996\n2014-01-30 10:10:00,0.0\n2014-01-30 10:15:00,0.32799999999999996\n2014-01-30 10:20:00,0.0\n2014-01-30 10:25:00,0.0\n2014-01-30 10:30:00,0.32799999999999996\n2014-01-30 10:35:00,0.0\n2014-01-30 10:40:00,0.32799999999999996\n2014-01-30 10:45:00,0.0\n2014-01-30 10:50:00,0.33399999999999996\n2014-01-30 10:55:00,0.0\n2014-01-30 11:00:00,0.33799999999999997\n2014-01-30 11:05:00,0.0\n2014-01-30 11:10:00,0.0\n2014-01-30 11:15:00,0.33799999999999997\n2014-01-30 11:20:00,0.0\n2014-01-30 11:25:00,0.33799999999999997\n2014-01-30 11:30:00,0.0\n2014-01-30 11:35:00,0.32799999999999996\n2014-01-30 11:40:00,0.0\n2014-01-30 11:45:00,0.0\n2014-01-30 11:50:00,14.036\n2014-01-30 11:55:00,0.0\n2014-01-30 12:00:00,0.33799999999999997\n2014-01-30 12:05:00,0.0\n2014-01-30 12:10:00,0.33799999999999997\n2014-01-30 12:15:00,0.0\n2014-01-30 12:20:00,2.372\n2014-01-30 12:25:00,0.33799999999999997\n2014-01-30 12:30:00,0.0\n2014-01-30 12:35:00,0.672\n2014-01-30 12:40:00,0.0\n2014-01-30 12:45:00,0.32799999999999996\n2014-01-30 12:50:00,0.0\n2014-01-30 12:55:00,0.0\n2014-01-30 13:00:00,0.32799999999999996\n2014-01-30 13:05:00,0.33799999999999997\n2014-01-30 13:10:00,0.0\n2014-01-30 13:15:00,0.0\n2014-01-30 13:20:00,0.33799999999999997\n2014-01-30 13:25:00,0.0\n2014-01-30 13:30:00,0.33799999999999997\n2014-01-30 13:35:00,0.0\n2014-01-30 13:40:00,3.7239999999999998\n2014-01-30 13:45:00,10.328\n2014-01-30 13:50:00,0.0\n2014-01-30 13:55:00,0.33799999999999997\n2014-01-30 14:00:00,0.0\n2014-01-30 14:05:00,0.33799999999999997\n2014-01-30 14:10:00,0.32799999999999996\n2014-01-30 14:15:00,0.0\n2014-01-30 14:20:00,0.33799999999999997\n2014-01-30 14:25:00,0.0\n2014-01-30 14:30:00,5.296\n2014-01-30 14:35:00,1.016\n2014-01-30 14:40:00,0.0\n2014-01-30 14:45:00,0.0\n2014-01-30 14:50:00,0.32799999999999996\n2014-01-30 14:55:00,0.0\n2014-01-30 15:00:00,0.32799999999999996\n2014-01-30 15:05:00,0.0\n2014-01-30 15:10:00,0.41\n2014-01-30 15:15:00,0.0\n2014-01-30 15:20:00,0.33399999999999996\n2014-01-30 15:25:00,0.0\n2014-01-30 15:30:00,0.33399999999999996\n2014-01-30 15:35:00,10.334000000000001\n2014-01-30 15:40:00,3.2880000000000003\n2014-01-30 15:45:00,0.0\n2014-01-30 15:50:00,0.32799999999999996\n2014-01-30 15:55:00,0.0\n2014-01-30 16:00:00,0.33799999999999997\n2014-01-30 16:05:00,0.0\n2014-01-30 16:10:00,0.33799999999999997\n2014-01-30 16:15:00,0.0\n2014-01-30 16:20:00,0.0\n2014-01-30 16:25:00,0.672\n2014-01-30 16:30:00,0.0\n2014-01-30 16:35:00,0.0\n2014-01-30 16:40:00,0.33399999999999996\n2014-01-30 16:45:00,0.0\n2014-01-30 16:50:00,0.33399999999999996\n2014-01-30 16:55:00,0.0\n2014-01-30 17:00:00,0.32799999999999996\n2014-01-30 17:05:00,0.0\n2014-01-30 17:10:00,0.33799999999999997\n2014-01-30 17:15:00,0.0\n2014-01-30 17:20:00,0.32799999999999996\n2014-01-30 17:25:00,0.0\n2014-01-30 17:30:00,0.0\n2014-01-30 17:35:00,0.33399999999999996\n2014-01-30 17:40:00,7.34\n2014-01-30 17:45:00,6.284\n2014-01-30 17:50:00,0.32799999999999996\n2014-01-30 17:55:00,0.0\n2014-01-30 18:00:00,0.33399999999999996\n2014-01-30 18:05:00,0.0\n2014-01-30 18:10:00,0.41\n2014-01-30 18:15:00,0.0\n2014-01-30 18:20:00,0.33799999999999997\n2014-01-30 18:25:00,0.0\n2014-01-30 18:30:00,0.33399999999999996\n2014-01-30 18:35:00,0.0\n2014-01-30 18:40:00,0.0\n2014-01-30 18:45:00,0.33399999999999996\n2014-01-30 18:50:00,0.0\n2014-01-30 18:55:00,0.32799999999999996\n2014-01-30 19:00:00,0.0\n2014-01-30 19:05:00,0.33399999999999996\n2014-01-30 19:10:00,0.0\n2014-01-30 19:15:00,0.33399999999999996\n2014-01-30 19:20:00,5.716\n2014-01-30 19:25:00,0.0\n2014-01-30 19:30:00,0.33399999999999996\n2014-01-30 19:35:00,0.0\n2014-01-30 19:40:00,0.32799999999999996\n2014-01-30 19:45:00,0.0\n2014-01-30 19:50:00,0.0\n2014-01-30 19:55:00,0.32799999999999996\n2014-01-30 20:00:00,0.33799999999999997\n2014-01-30 20:05:00,0.0\n2014-01-30 20:10:00,0.0\n2014-01-30 20:15:00,0.33799999999999997\n2014-01-30 20:20:00,0.0\n2014-01-30 20:25:00,0.33799999999999997\n2014-01-30 20:30:00,0.0\n2014-01-30 20:35:00,0.33399999999999996\n2014-01-30 20:40:00,3.2880000000000003\n2014-01-30 20:45:00,0.0\n2014-01-30 20:50:00,0.33799999999999997\n2014-01-30 20:55:00,0.0\n2014-01-30 21:00:00,0.33399999999999996\n2014-01-30 21:05:00,0.0\n2014-01-30 21:10:00,0.32799999999999996\n2014-01-30 21:15:00,0.0\n2014-01-30 21:20:00,0.4175\n2014-01-30 21:25:00,8.322000000000001\n2014-01-30 21:30:00,0.0\n2014-01-30 21:35:00,0.41\n2014-01-30 21:40:00,0.0\n2014-01-30 21:45:00,0.33799999999999997\n2014-01-30 21:50:00,0.0\n2014-01-30 21:55:00,0.0\n2014-01-30 22:00:00,0.4175\n2014-01-30 22:05:00,0.33399999999999996\n2014-01-30 22:10:00,0.0\n2014-01-30 22:15:00,0.0\n2014-01-30 22:20:00,0.33799999999999997\n2014-01-30 22:25:00,0.0\n2014-01-30 22:30:00,0.33799999999999997\n2014-01-30 22:35:00,0.0\n2014-01-30 22:40:00,0.0\n2014-01-30 22:45:00,0.0\n2014-01-30 22:50:00,0.0\n2014-01-30 22:55:00,0.32799999999999996\n2014-01-30 23:00:00,0.33399999999999996\n2014-01-30 23:05:00,0.0\n2014-01-30 23:10:00,0.0\n2014-01-30 23:15:00,0.33399999999999996\n2014-01-30 23:20:00,0.0\n2014-01-30 23:25:00,0.32799999999999996\n2014-01-30 23:30:00,0.0\n2014-01-30 23:35:00,0.0\n2014-01-30 23:40:00,0.33399999999999996\n2014-01-30 23:45:00,0.0\n2014-01-30 23:50:00,0.33399999999999996\n2014-01-30 23:55:00,0.0\n2014-01-31 00:00:00,0.33799999999999997\n2014-01-31 00:05:00,0.0\n2014-01-31 00:10:00,0.32799999999999996\n2014-01-31 00:15:00,0.0\n2014-01-31 00:20:00,0.6659999999999999\n2014-01-31 00:25:00,0.0\n2014-01-31 00:30:00,0.0\n2014-01-31 00:35:00,0.33799999999999997\n2014-01-31 00:40:00,0.0\n2014-01-31 00:45:00,0.33399999999999996\n2014-01-31 00:50:00,0.0\n2014-01-31 00:55:00,0.0\n2014-01-31 01:00:00,0.33799999999999997\n2014-01-31 01:05:00,0.32799999999999996\n2014-01-31 01:10:00,0.0\n2014-01-31 01:15:00,0.32799999999999996\n2014-01-31 01:20:00,0.0\n2014-01-31 01:25:00,0.0\n2014-01-31 01:30:00,0.33399999999999996\n2014-01-31 01:35:00,0.0\n2014-01-31 01:40:00,0.4175\n2014-01-31 01:45:00,0.0\n2014-01-31 01:50:00,0.0\n2014-01-31 01:55:00,0.32799999999999996\n2014-01-31 02:00:00,0.33399999999999996\n2014-01-31 02:05:00,0.0\n2014-01-31 02:10:00,0.0\n2014-01-31 02:15:00,0.33399999999999996\n2014-01-31 02:20:00,0.0\n2014-01-31 02:25:00,0.33399999999999996\n2014-01-31 02:30:00,0.0\n2014-01-31 02:35:00,0.33399999999999996\n2014-01-31 02:40:00,0.0\n2014-01-31 02:45:00,0.0\n2014-01-31 02:50:00,0.33799999999999997\n2014-01-31 02:55:00,0.0\n2014-01-31 03:00:00,0.32799999999999996\n2014-01-31 03:05:00,0.0\n2014-01-31 03:10:00,0.33799999999999997\n2014-01-31 03:15:00,0.0\n2014-01-31 03:20:00,0.33799999999999997\n2014-01-31 03:25:00,0.0\n2014-01-31 03:30:00,0.33799999999999997\n2014-01-31 03:35:00,0.0\n2014-01-31 03:40:00,5.246\n2014-01-31 03:45:00,0.0\n2014-01-31 03:50:00,0.4175\n2014-01-31 03:55:00,0.0\n2014-01-31 04:00:00,0.33399999999999996\n2014-01-31 04:05:00,0.0\n2014-01-31 04:10:00,0.33399999999999996\n2014-01-31 04:15:00,0.0\n2014-01-31 04:20:00,0.32799999999999996\n2014-01-31 04:25:00,0.0\n2014-01-31 04:30:00,0.0\n2014-01-31 04:35:00,0.33399999999999996\n2014-01-31 04:40:00,0.0\n2014-01-31 04:45:00,0.32799999999999996\n2014-01-31 04:50:00,0.0\n2014-01-31 04:55:00,0.33399999999999996\n2014-01-31 05:00:00,0.33799999999999997\n2014-01-31 05:05:00,0.0\n2014-01-31 05:10:00,0.0\n2014-01-31 05:15:00,0.33399999999999996\n2014-01-31 05:20:00,0.0\n2014-01-31 05:25:00,0.33399999999999996\n2014-01-31 05:30:00,0.0\n2014-01-31 05:35:00,0.32799999999999996\n2014-01-31 05:40:00,0.0\n2014-01-31 05:45:00,0.0\n2014-01-31 05:50:00,0.33799999999999997\n2014-01-31 05:55:00,0.0\n2014-01-31 06:00:00,0.4175\n2014-01-31 06:05:00,0.0\n2014-01-31 06:10:00,0.33399999999999996\n2014-01-31 06:15:00,0.0\n2014-01-31 06:20:00,0.33799999999999997\n2014-01-31 06:25:00,0.0\n2014-01-31 06:30:00,0.33799999999999997\n2014-01-31 06:35:00,0.0\n2014-01-31 06:40:00,0.33799999999999997\n2014-01-31 06:45:00,0.0\n2014-01-31 06:50:00,0.0\n2014-01-31 06:55:00,0.32799999999999996\n2014-01-31 07:00:00,0.33399999999999996\n2014-01-31 07:05:00,0.0\n2014-01-31 07:10:00,0.0\n2014-01-31 07:15:00,0.33799999999999997\n2014-01-31 07:20:00,0.0\n2014-01-31 07:25:00,0.33399999999999996\n2014-01-31 07:30:00,0.0\n2014-01-31 07:35:00,0.32799999999999996\n2014-01-31 07:40:00,1.334\n2014-01-31 07:45:00,0.0\n2014-01-31 07:50:00,0.33799999999999997\n2014-01-31 07:55:00,0.0\n2014-01-31 08:00:00,0.33799999999999997\n2014-01-31 08:05:00,0.0\n2014-01-31 08:10:00,0.0\n2014-01-31 08:15:00,0.0\n2014-01-31 08:20:00,0.0\n2014-01-31 08:25:00,0.32799999999999996\n2014-01-31 08:30:00,0.0\n2014-01-31 08:35:00,0.4225\n2014-01-31 08:40:00,11.62\n2014-01-31 08:45:00,11.718\n2014-01-31 08:50:00,5.318\n2014-01-31 08:55:00,0.33399999999999996\n2014-01-31 09:00:00,0.32799999999999996\n2014-01-31 09:05:00,0.0\n2014-01-31 09:10:00,0.0\n2014-01-31 09:15:00,0.4175\n2014-01-31 09:20:00,0.0\n2014-01-31 09:25:00,0.32799999999999996\n2014-01-31 09:30:00,0.0\n2014-01-31 09:35:00,0.33399999999999996\n2014-01-31 09:40:00,0.0\n2014-01-31 09:45:00,0.0\n2014-01-31 09:50:00,0.33399999999999996\n2014-01-31 09:55:00,0.0\n2014-01-31 10:00:00,0.33399999999999996\n2014-01-31 10:05:00,0.0\n2014-01-31 10:10:00,0.33399999999999996\n2014-01-31 10:15:00,0.0\n2014-01-31 10:20:00,0.0\n2014-01-31 10:25:00,0.32799999999999996\n2014-01-31 10:30:00,4.215\n2014-01-31 10:35:00,0.0\n2014-01-31 10:40:00,0.32799999999999996\n2014-01-31 10:45:00,0.0\n2014-01-31 10:50:00,0.33399999999999996\n2014-01-31 10:55:00,0.0\n2014-01-31 11:00:00,0.33399999999999996\n2014-01-31 11:05:00,0.0\n2014-01-31 11:10:00,0.0\n2014-01-31 11:15:00,0.0\n2014-01-31 11:20:00,0.0\n2014-01-31 11:25:00,0.6679999999999999\n2014-01-31 11:30:00,0.0\n2014-01-31 11:35:00,0.4175\n2014-01-31 11:40:00,0.0\n2014-01-31 11:45:00,0.32799999999999996\n2014-01-31 11:50:00,0.0\n2014-01-31 11:55:00,0.0\n2014-01-31 12:00:00,0.32799999999999996\n2014-01-31 12:05:00,0.33399999999999996\n2014-01-31 12:10:00,0.0\n2014-01-31 12:15:00,0.0\n2014-01-31 12:20:00,0.32799999999999996\n2014-01-31 12:25:00,0.0\n2014-01-31 12:30:00,0.33399999999999996\n2014-01-31 12:35:00,0.0\n2014-01-31 12:40:00,0.0\n2014-01-31 12:45:00,0.33799999999999997\n2014-01-31 12:50:00,0.0\n2014-01-31 12:55:00,0.4175\n2014-01-31 13:00:00,0.0\n2014-01-31 13:05:00,0.33399999999999996\n2014-01-31 13:10:00,0.0\n2014-01-31 13:15:00,0.33399999999999996\n2014-01-31 13:20:00,0.0\n2014-01-31 13:25:00,0.0\n2014-01-31 13:30:00,0.33399999999999996\n2014-01-31 13:35:00,0.0\n2014-01-31 13:40:00,0.33399999999999996\n2014-01-31 13:45:00,0.0\n2014-01-31 13:50:00,0.0\n2014-01-31 13:55:00,0.33799999999999997\n2014-01-31 14:00:00,0.41\n2014-01-31 14:05:00,0.0\n2014-01-31 14:10:00,0.33399999999999996\n2014-01-31 14:15:00,0.0\n2014-01-31 14:20:00,0.0\n2014-01-31 14:25:00,0.32799999999999996\n2014-01-31 14:30:00,0.0\n2014-01-31 14:35:00,0.33399999999999996\n2014-01-31 14:40:00,0.0\n2014-01-31 14:45:00,0.0\n2014-01-31 14:50:00,0.33399999999999996\n2014-01-31 14:55:00,0.0\n2014-01-31 15:00:00,0.33799999999999997\n2014-01-31 15:05:00,0.0\n2014-01-31 15:10:00,0.33799999999999997\n2014-01-31 15:15:00,0.0\n2014-01-31 15:20:00,0.4225\n2014-01-31 15:25:00,0.0\n2014-01-31 15:30:00,0.32799999999999996\n2014-01-31 15:35:00,0.0\n2014-01-31 15:40:00,0.0\n2014-01-31 15:45:00,0.33399999999999996\n2014-01-31 15:50:00,0.0\n2014-01-31 15:55:00,0.33799999999999997\n2014-01-31 16:00:00,0.0\n2014-01-31 16:05:00,0.33799999999999997\n2014-01-31 16:10:00,0.0\n2014-01-31 16:15:00,0.32799999999999996\n2014-01-31 16:20:00,0.0\n2014-01-31 16:25:00,0.33399999999999996\n2014-01-31 16:30:00,0.0\n2014-01-31 16:35:00,0.0\n2014-01-31 16:40:00,0.33399999999999996\n2014-01-31 16:45:00,0.0\n2014-01-31 16:50:00,0.41\n2014-01-31 16:55:00,0.0\n2014-01-31 17:00:00,0.33399999999999996\n2014-01-31 17:05:00,0.0\n2014-01-31 17:10:00,0.33399999999999996\n2014-01-31 17:15:00,0.0\n2014-01-31 17:20:00,0.33799999999999997\n2014-01-31 17:25:00,0.0\n2014-01-31 17:30:00,0.0\n2014-01-31 17:35:00,0.33399999999999996\n2014-01-31 17:40:00,0.0\n2014-01-31 17:45:00,0.33799999999999997\n2014-01-31 17:50:00,0.0\n2014-01-31 17:55:00,2.7060000000000004\n2014-01-31 18:00:00,0.33799999999999997\n2014-01-31 18:05:00,0.0\n2014-01-31 18:10:00,0.33799999999999997\n2014-01-31 18:15:00,0.0\n2014-01-31 18:20:00,0.0\n2014-01-31 18:25:00,0.32799999999999996\n2014-01-31 18:30:00,0.0\n2014-01-31 18:35:00,0.33799999999999997\n2014-01-31 18:40:00,0.0\n2014-01-31 18:45:00,0.0\n2014-01-31 18:50:00,0.33799999999999997\n2014-01-31 18:55:00,0.0\n2014-01-31 19:00:00,0.33799999999999997\n2014-01-31 19:05:00,0.0\n2014-01-31 19:10:00,0.33399999999999996\n2014-01-31 19:15:00,0.0\n2014-01-31 19:20:00,0.33799999999999997\n2014-01-31 19:25:00,0.0\n2014-01-31 19:30:00,0.0\n2014-01-31 19:35:00,0.32799999999999996\n2014-01-31 19:40:00,0.0\n2014-01-31 19:45:00,0.0\n2014-01-31 19:50:00,0.41\n2014-01-31 19:55:00,0.0\n2014-01-31 20:00:00,0.33799999999999997\n2014-01-31 20:05:00,0.0\n2014-01-31 20:10:00,0.33399999999999996\n2014-01-31 20:15:00,0.0\n2014-01-31 20:20:00,0.33799999999999997\n2014-01-31 20:25:00,0.0\n2014-01-31 20:30:00,0.0\n2014-01-31 20:35:00,0.0\n2014-01-31 20:40:00,0.0\n2014-01-31 20:45:00,0.33399999999999996\n2014-01-31 20:50:00,0.0\n2014-01-31 20:55:00,0.33799999999999997\n2014-01-31 21:00:00,0.0\n2014-01-31 21:05:00,1.646\n2014-01-31 21:10:00,0.0\n2014-01-31 21:15:00,0.0\n2014-01-31 21:20:00,0.672\n2014-01-31 21:25:00,0.0\n2014-01-31 21:30:00,0.33399999999999996\n2014-01-31 21:35:00,0.0\n2014-01-31 21:40:00,0.33399999999999996\n2014-01-31 21:45:00,0.0\n2014-01-31 21:50:00,0.0\n2014-01-31 21:55:00,0.33799999999999997\n2014-01-31 22:00:00,0.33799999999999997\n2014-01-31 22:05:00,0.0\n2014-01-31 22:10:00,0.0\n2014-01-31 22:15:00,0.32799999999999996\n2014-01-31 22:20:00,0.0\n2014-01-31 22:25:00,0.0\n2014-01-31 22:30:00,0.0\n2014-01-31 22:35:00,0.0\n2014-01-31 22:40:00,0.33399999999999996\n2014-01-31 22:45:00,0.0\n2014-01-31 22:50:00,0.33399999999999996\n2014-01-31 22:55:00,0.0\n2014-01-31 23:00:00,0.33399999999999996\n2014-01-31 23:05:00,0.0\n2014-01-31 23:10:00,0.32799999999999996\n2014-01-31 23:15:00,0.0\n2014-01-31 23:20:00,0.32799999999999996\n2014-01-31 23:25:00,0.0\n2014-01-31 23:30:00,0.33399999999999996\n2014-01-31 23:35:00,0.0\n2014-01-31 23:40:00,0.0\n2014-01-31 23:45:00,0.32799999999999996\n2014-01-31 23:50:00,0.0\n2014-01-31 23:55:00,0.33799999999999997\n2014-02-01 00:00:00,0.0\n2014-02-01 00:05:00,0.33399999999999996\n2014-02-01 00:10:00,0.0\n2014-02-01 00:15:00,0.33399999999999996\n2014-02-01 00:20:00,0.0\n2014-02-01 00:25:00,0.32799999999999996\n2014-02-01 00:30:00,0.0\n2014-02-01 00:35:00,0.0\n2014-02-01 00:40:00,0.33799999999999997\n2014-02-01 00:45:00,0.0\n2014-02-01 00:50:00,0.0\n2014-02-01 00:55:00,0.0\n2014-02-01 01:00:00,0.33399999999999996\n"
  },
  {
    "path": "workspace/anomaly_detector/datasets/selected/level_change/rds_cpu_utilization_cc0c53.csv",
    "content": "timestamp,value\n2014-02-14 14:30:00,6.456\n2014-02-14 14:35:00,5.816\n2014-02-14 14:40:00,6.268\n2014-02-14 14:45:00,5.816\n2014-02-14 14:50:00,5.862\n2014-02-14 14:55:00,6.246\n2014-02-14 15:00:00,6.648\n2014-02-14 15:05:00,6.4479999999999995\n2014-02-14 15:10:00,6.46\n2014-02-14 15:15:00,5.834\n2014-02-14 15:20:00,6.232\n2014-02-14 15:25:00,6.064\n2014-02-14 15:30:00,6.0520000000000005\n2014-02-14 15:35:00,5.834\n2014-02-14 15:40:00,6.4639999999999995\n2014-02-14 15:45:00,5.622000000000001\n2014-02-14 15:50:00,6.2379999999999995\n2014-02-14 15:55:00,6.06\n2014-02-14 16:00:00,6.04\n2014-02-14 16:05:00,5.837999999999999\n2014-02-14 16:10:00,6.024\n2014-02-14 16:15:00,5.86\n2014-02-14 16:20:00,6.432\n2014-02-14 16:25:00,6.6720000000000015\n2014-02-14 16:30:00,6.0520000000000005\n2014-02-14 16:35:00,5.63\n2014-02-14 16:40:00,6.226\n2014-02-14 16:45:00,6.06\n2014-02-14 16:50:00,5.85\n2014-02-14 16:55:00,6.022\n2014-02-14 17:00:00,6.058\n2014-02-14 17:05:00,5.622000000000001\n2014-02-14 17:10:00,6.268\n2014-02-14 17:15:00,6.454\n2014-02-14 17:20:00,7.066\n2014-02-14 17:25:00,5.856\n2014-02-14 17:30:00,6.254\n2014-02-14 17:35:00,6.024\n2014-02-14 17:40:00,6.278\n2014-02-14 17:45:00,5.834\n2014-02-14 17:50:00,5.843999999999999\n2014-02-14 17:55:00,5.834\n2014-02-14 18:00:00,6.053999999999999\n2014-02-14 18:05:00,6.226\n2014-02-14 18:10:00,5.6160000000000005\n2014-02-14 18:15:00,5.64\n2014-02-14 18:20:00,6.03\n2014-02-14 18:25:00,5.864\n2014-02-14 18:30:00,7.27\n2014-02-14 18:35:00,6.018\n2014-02-14 18:40:00,6.2620000000000005\n2014-02-14 18:45:00,5.8420000000000005\n2014-02-14 18:50:00,5.85\n2014-02-14 18:55:00,6.046\n2014-02-14 19:00:00,6.044\n2014-02-14 19:05:00,5.827999999999999\n2014-02-14 19:10:00,6.476\n2014-02-14 19:15:00,6.046\n2014-02-14 19:20:00,6.04\n2014-02-14 19:25:00,6.0420000000000025\n2014-02-14 19:30:00,7.104\n2014-02-14 19:35:00,6.246\n2014-02-14 19:40:00,6.2379999999999995\n2014-02-14 19:45:00,5.8660000000000005\n2014-02-14 19:50:00,6.044\n2014-02-14 19:55:00,5.834\n2014-02-14 20:00:00,6.25\n2014-02-14 20:05:00,5.834\n2014-02-14 20:10:00,6.2139999999999995\n2014-02-14 20:15:00,5.8420000000000005\n2014-02-14 20:20:00,6.474\n2014-02-14 20:25:00,6.642\n2014-02-14 20:30:00,6.058\n2014-02-14 20:35:00,5.814\n2014-02-14 20:40:00,6.058\n2014-02-14 20:45:00,5.824\n2014-02-14 20:50:00,6.04\n2014-02-14 20:55:00,6.022\n2014-02-14 21:00:00,5.85\n2014-02-14 21:05:00,6.0360000000000005\n2014-02-14 21:10:00,6.056\n2014-02-14 21:15:00,5.622000000000001\n2014-02-14 21:20:00,7.266\n2014-02-14 21:25:00,6.074\n2014-02-14 21:30:00,6.024\n2014-02-14 21:35:00,5.862\n2014-02-14 21:40:00,6.44\n2014-02-14 21:45:00,6.0520000000000005\n2014-02-14 21:50:00,6.246\n2014-02-14 21:55:00,6.2860000000000005\n2014-02-14 22:00:00,6.0520000000000005\n2014-02-14 22:05:00,6.013999999999999\n2014-02-14 22:10:00,6.257999999999999\n2014-02-14 22:15:00,5.837999999999999\n2014-02-14 22:20:00,6.2379999999999995\n2014-02-14 22:25:00,6.072\n2014-02-14 22:30:00,6.85\n2014-02-14 22:35:00,6.476\n2014-02-14 22:40:00,6.257999999999999\n2014-02-14 22:45:00,6.48\n2014-02-14 22:50:00,5.398\n2014-02-14 22:55:00,6.044\n2014-02-14 23:00:00,6.0820000000000025\n2014-02-14 23:05:00,5.834\n2014-02-14 23:10:00,6.63\n2014-02-14 23:15:00,6.6979999999999995\n2014-02-14 23:20:00,6.004\n2014-02-14 23:25:00,5.654\n2014-02-14 23:30:00,6.266\n2014-02-14 23:35:00,5.62\n2014-02-14 23:40:00,6.2479999999999976\n2014-02-14 23:45:00,5.62\n2014-02-14 23:50:00,6.028\n2014-02-14 23:55:00,5.9460000000000015\n2014-02-15 00:00:00,6.232\n2014-02-15 00:05:00,5.81\n2014-02-15 00:10:00,6.297999999999999\n2014-02-15 00:15:00,7.09\n2014-02-15 00:20:00,6.666\n2014-02-15 00:25:00,6.046\n2014-02-15 00:30:00,6.226\n2014-02-15 00:35:00,5.862\n2014-02-15 00:40:00,6.263999999999999\n2014-02-15 00:45:00,5.816\n2014-02-15 00:50:00,6.062\n2014-02-15 00:55:00,6.068\n2014-02-15 01:00:00,6.044\n2014-02-15 01:05:00,5.827999999999999\n2014-02-15 01:10:00,7.883999999999999\n2014-02-15 01:15:00,6.077999999999999\n2014-02-15 01:20:00,6.2520000000000024\n2014-02-15 01:25:00,5.834\n2014-02-15 01:30:00,5.8320000000000025\n2014-02-15 01:35:00,6.03\n2014-02-15 01:40:00,6.224\n2014-02-15 01:45:00,5.862\n2014-02-15 01:50:00,6.232\n2014-02-15 01:55:00,6.2479999999999976\n2014-02-15 02:00:00,6.266\n2014-02-15 02:05:00,7.334\n2014-02-15 02:10:00,6.6739999999999995\n2014-02-15 02:15:00,6.0360000000000005\n2014-02-15 02:20:00,6.2379999999999995\n2014-02-15 02:25:00,6.047999999999999\n2014-02-15 02:30:00,6.09\n2014-02-15 02:35:00,5.816\n2014-02-15 02:40:00,6.2860000000000005\n2014-02-15 02:45:00,5.834\n2014-02-15 02:50:00,6.04\n2014-02-15 02:55:00,6.0360000000000005\n2014-02-15 03:00:00,6.2360000000000015\n2014-02-15 03:05:00,5.834\n2014-02-15 03:10:00,6.03\n2014-02-15 03:15:00,5.848\n2014-02-15 03:20:00,6.037999999999999\n2014-02-15 03:25:00,7.114\n2014-02-15 03:30:00,6.86\n2014-02-15 03:35:00,5.8420000000000005\n2014-02-15 03:40:00,6.2620000000000005\n2014-02-15 03:45:00,6.06\n2014-02-15 03:50:00,6.2360000000000015\n2014-02-15 03:55:00,6.282\n2014-02-15 04:00:00,6.438\n2014-02-15 04:05:00,6.04\n2014-02-15 04:10:00,6.2\n2014-02-15 04:15:00,6.07\n2014-02-15 04:20:00,6.044\n2014-02-15 04:25:00,6.046\n2014-02-15 04:30:00,6.024\n2014-02-15 04:35:00,5.862\n2014-02-15 04:40:00,6.044\n2014-02-15 04:45:00,6.05\n2014-02-15 04:50:00,6.044\n2014-02-15 04:55:00,6.018\n2014-02-15 05:00:00,5.867999999999999\n2014-02-15 05:05:00,6.04\n2014-02-15 05:10:00,6.257999999999999\n2014-02-15 05:15:00,5.837999999999999\n2014-02-15 05:20:00,5.827999999999999\n2014-02-15 05:25:00,6.022\n2014-02-15 05:30:00,6.087999999999999\n2014-02-15 05:35:00,5.834\n2014-02-15 05:40:00,5.837999999999999\n2014-02-15 05:45:00,6.046\n2014-02-15 05:50:00,6.6679999999999975\n2014-02-15 05:55:00,6.234\n2014-02-15 06:00:00,5.87\n2014-02-15 06:05:00,6.028\n2014-02-15 06:10:00,6.058\n2014-02-15 06:15:00,6.0420000000000025\n2014-02-15 06:20:00,6.26\n2014-02-15 06:25:00,6.024\n2014-02-15 06:30:00,6.266\n2014-02-15 06:35:00,6.224\n2014-02-15 06:40:00,6.074\n2014-02-15 06:45:00,6.04\n2014-02-15 06:50:00,6.2520000000000024\n2014-02-15 06:55:00,6.25\n2014-02-15 07:00:00,6.04\n2014-02-15 07:05:00,6.04\n2014-02-15 07:10:00,6.25\n2014-02-15 07:15:00,6.04\n2014-02-15 07:20:00,6.257999999999999\n2014-02-15 07:25:00,6.0420000000000025\n2014-02-15 07:30:00,6.044\n2014-02-15 07:35:00,5.816\n2014-02-15 07:40:00,6.284\n2014-02-15 07:45:00,5.602\n2014-02-15 07:50:00,6.266\n2014-02-15 07:55:00,6.86\n2014-02-15 08:00:00,5.803999999999999\n2014-02-15 08:05:00,6.436\n2014-02-15 08:10:00,6.65\n2014-02-15 08:15:00,5.228\n2014-02-15 08:20:00,5.846\n2014-02-15 08:25:00,6.0420000000000025\n2014-02-15 08:30:00,6.047999999999999\n2014-02-15 08:35:00,5.63\n2014-02-15 08:40:00,6.4460000000000015\n2014-02-15 08:45:00,5.86\n2014-02-15 08:50:00,6.2520000000000024\n2014-02-15 08:55:00,6.23\n2014-02-15 09:00:00,6.077999999999999\n2014-02-15 09:05:00,6.2520000000000024\n2014-02-15 09:10:00,6.232\n2014-02-15 09:15:00,6.44\n2014-02-15 09:20:00,6.058\n2014-02-15 09:25:00,6.2479999999999976\n2014-02-15 09:30:00,6.047999999999999\n2014-02-15 09:35:00,6.046\n2014-02-15 09:40:00,6.228\n2014-02-15 09:45:00,6.068\n2014-02-15 09:50:00,6.058\n2014-02-15 09:55:00,6.0420000000000025\n2014-02-15 10:00:00,6.2379999999999995\n2014-02-15 10:05:00,5.648\n2014-02-15 10:10:00,6.85\n2014-02-15 10:15:00,5.81\n2014-02-15 10:20:00,6.058\n2014-02-15 10:25:00,6.06\n2014-02-15 10:30:00,6.047999999999999\n2014-02-15 10:35:00,5.827999999999999\n2014-02-15 10:40:00,5.8420000000000005\n2014-02-15 10:45:00,6.222\n2014-02-15 10:50:00,6.053999999999999\n2014-02-15 10:55:00,6.46\n2014-02-15 11:00:00,6.228\n2014-02-15 11:05:00,6.046\n2014-02-15 11:10:00,7.106\n2014-02-15 11:15:00,6.068\n2014-02-15 11:20:00,6.644\n2014-02-15 11:25:00,6.454\n2014-02-15 11:30:00,6.478\n2014-02-15 11:35:00,6.25\n2014-02-15 11:40:00,6.644\n2014-02-15 11:45:00,6.2520000000000024\n2014-02-15 11:50:00,6.482\n2014-02-15 11:55:00,6.2620000000000005\n2014-02-15 12:00:00,6.416\n2014-02-15 12:05:00,6.064\n2014-02-15 12:10:00,6.44\n2014-02-15 12:15:00,6.2520000000000024\n2014-02-15 12:20:00,6.444\n2014-02-15 12:25:00,6.4579999999999975\n2014-02-15 12:30:00,7.062\n2014-02-15 12:35:00,6.224\n2014-02-15 12:40:00,6.666\n2014-02-15 12:45:00,6.282\n2014-02-15 12:50:00,6.416\n2014-02-15 12:55:00,6.478\n2014-02-15 13:00:00,6.644\n2014-02-15 13:05:00,6.25\n2014-02-15 13:10:00,6.45\n2014-02-15 13:15:00,6.263999999999999\n2014-02-15 13:20:00,7.27\n2014-02-15 13:25:00,6.04\n2014-02-15 13:30:00,6.46\n2014-02-15 13:35:00,6.454\n2014-02-15 13:40:00,6.452000000000001\n2014-02-15 13:45:00,6.222\n2014-02-15 13:50:00,6.26\n2014-02-15 13:55:00,6.49\n2014-02-15 14:00:00,6.472\n2014-02-15 14:05:00,6.4620000000000015\n2014-02-15 14:10:00,6.888\n2014-02-15 14:15:00,6.23\n2014-02-15 14:20:00,6.912000000000001\n2014-02-15 14:25:00,5.8320000000000025\n2014-02-15 14:30:00,6.0420000000000025\n2014-02-15 14:35:00,6.432\n2014-02-15 14:40:00,6.478\n2014-02-15 14:45:00,6.272\n2014-02-15 14:50:00,6.232\n2014-02-15 14:55:00,6.688\n2014-02-15 15:00:00,6.4460000000000015\n2014-02-15 15:05:00,6.468\n2014-02-15 15:10:00,6.48\n2014-02-15 15:15:00,6.0420000000000025\n2014-02-15 15:20:00,7.056\n2014-02-15 15:25:00,6.47\n2014-02-15 15:30:00,6.2860000000000005\n2014-02-15 15:35:00,6.034\n2014-02-15 15:40:00,6.472\n2014-02-15 15:45:00,6.0420000000000025\n2014-02-15 15:50:00,6.2479999999999976\n2014-02-15 15:55:00,6.254\n2014-02-15 16:00:00,6.426\n2014-02-15 16:05:00,5.834\n2014-02-15 16:10:00,6.472\n2014-02-15 16:15:00,5.816\n2014-02-15 16:20:00,6.27\n2014-02-15 16:25:00,6.256\n2014-02-15 16:30:00,6.85\n2014-02-15 16:35:00,6.282\n2014-02-15 16:40:00,6.2479999999999976\n2014-02-15 16:45:00,6.0360000000000005\n2014-02-15 16:50:00,6.016\n2014-02-15 16:55:00,6.07\n2014-02-15 17:00:00,6.25\n2014-02-15 17:05:00,6.0420000000000025\n2014-02-15 17:10:00,6.442\n2014-02-15 17:15:00,6.706\n2014-02-15 17:20:00,6.01\n2014-02-15 17:25:00,6.074\n2014-02-15 17:30:00,6.2520000000000024\n2014-02-15 17:35:00,5.834\n2014-02-15 17:40:00,6.228\n2014-02-15 17:45:00,5.648\n2014-02-15 17:50:00,6.2520000000000024\n2014-02-15 17:55:00,6.0420000000000025\n2014-02-15 18:00:00,7.5\n2014-02-15 18:05:00,5.822\n2014-02-15 18:10:00,6.44\n2014-02-15 18:15:00,6.0420000000000025\n2014-02-15 18:20:00,6.218\n2014-02-15 18:25:00,6.244\n2014-02-15 18:30:00,6.2479999999999976\n2014-02-15 18:35:00,6.0420000000000025\n2014-02-15 18:40:00,6.256\n2014-02-15 18:45:00,6.86\n2014-02-15 18:50:00,6.4220000000000015\n2014-02-15 18:55:00,6.0520000000000005\n2014-02-15 19:00:00,6.274\n2014-02-15 19:05:00,5.83\n2014-02-15 19:10:00,6.46\n2014-02-15 19:15:00,6.226\n2014-02-15 19:20:00,6.926\n2014-02-15 19:25:00,5.617999999999999\n2014-02-15 19:30:00,6.266\n2014-02-15 19:35:00,5.81\n2014-02-15 19:40:00,6.077999999999999\n2014-02-15 19:45:00,5.834\n2014-02-15 19:50:00,5.814\n2014-02-15 19:55:00,6.044\n2014-02-15 20:00:00,5.843999999999999\n2014-02-15 20:05:00,5.8320000000000025\n2014-02-15 20:10:00,6.2520000000000024\n2014-02-15 20:15:00,7.08\n2014-02-15 20:20:00,5.8320000000000025\n2014-02-15 20:25:00,5.814\n2014-02-15 20:30:00,5.846\n2014-02-15 20:35:00,5.834\n2014-02-15 20:40:00,6.642\n2014-02-15 20:45:00,5.86\n2014-02-15 20:50:00,6.03\n2014-02-15 20:55:00,6.276\n2014-02-15 21:00:00,6.028\n2014-02-15 21:05:00,6.046\n2014-02-15 21:10:00,6.276\n2014-02-15 21:15:00,6.904\n2014-02-15 21:20:00,6.648\n2014-02-15 21:25:00,5.654\n2014-02-15 21:30:00,6.44\n2014-02-15 21:35:00,5.8660000000000005\n2014-02-15 21:40:00,6.246\n2014-02-15 21:45:00,5.837999999999999\n2014-02-15 21:50:00,5.9979999999999976\n2014-02-15 21:55:00,5.862\n2014-02-15 22:00:00,6.6720000000000015\n2014-02-15 22:05:00,7.63667\n2014-02-15 22:10:00,6.034\n2014-02-15 22:15:00,5.648\n2014-02-15 22:20:00,6.0120000000000005\n2014-02-15 22:25:00,5.8320000000000025\n2014-02-15 22:30:00,6.024\n2014-02-15 22:35:00,5.862\n2014-02-15 22:40:00,6.044\n2014-02-15 22:45:00,6.0420000000000025\n2014-02-15 22:50:00,6.266\n2014-02-15 22:55:00,6.022\n2014-02-15 23:00:00,6.086\n2014-02-15 23:05:00,6.034\n2014-02-15 23:10:00,6.2479999999999976\n2014-02-15 23:15:00,7.5020000000000024\n2014-02-15 23:20:00,6.2520000000000024\n2014-02-15 23:25:00,6.026\n2014-02-15 23:30:00,6.07\n2014-02-15 23:35:00,5.834\n2014-02-15 23:40:00,6.05\n2014-02-15 23:45:00,6.0420000000000025\n2014-02-15 23:50:00,6.024\n2014-02-15 23:55:00,5.756\n2014-02-16 00:00:00,7.43\n2014-02-16 00:05:00,6.686\n2014-02-16 00:10:00,6.228\n2014-02-16 00:15:00,6.28\n2014-02-16 00:20:00,6.044\n2014-02-16 00:25:00,6.246\n2014-02-16 00:30:00,6.2479999999999976\n2014-02-16 00:35:00,6.0420000000000025\n2014-02-16 00:40:00,6.472\n2014-02-16 00:45:00,6.04\n2014-02-16 00:50:00,6.028\n2014-02-16 00:55:00,6.2520000000000024\n2014-02-16 01:00:00,6.224\n2014-02-16 01:05:00,5.837999999999999\n2014-02-16 01:10:00,6.63\n2014-02-16 01:15:00,6.0420000000000025\n2014-02-16 01:20:00,6.228\n2014-02-16 01:25:00,6.05\n2014-02-16 01:30:00,6.506\n2014-02-16 01:35:00,7.268\n2014-02-16 01:40:00,6.072\n2014-02-16 01:45:00,5.834\n2014-02-16 01:50:00,6.0520000000000005\n2014-02-16 01:55:00,6.046\n2014-02-16 02:00:00,6.028\n2014-02-16 02:05:00,5.852\n2014-02-16 02:10:00,6.016\n2014-02-16 02:15:00,6.874\n2014-02-16 02:20:00,6.864\n2014-02-16 02:25:00,6.047999999999999\n2014-02-16 02:30:00,5.837999999999999\n2014-02-16 02:35:00,5.8660000000000005\n2014-02-16 02:40:00,6.044\n2014-02-16 02:45:00,5.624\n2014-02-16 02:50:00,6.044\n2014-02-16 02:55:00,6.0420000000000025\n2014-02-16 03:00:00,6.2520000000000024\n2014-02-16 03:05:00,7.058\n2014-02-16 03:10:00,6.9179999999999975\n2014-02-16 03:15:00,6.032\n2014-02-16 03:20:00,5.816\n2014-02-16 03:25:00,6.066\n2014-02-16 03:30:00,5.843999999999999\n2014-02-16 03:35:00,5.816\n2014-02-16 03:40:00,6.682\n2014-02-16 03:45:00,5.19\n2014-02-16 03:50:00,5.86\n2014-02-16 03:55:00,6.046\n2014-02-16 04:00:00,6.0520000000000005\n2014-02-16 04:05:00,5.6320000000000014\n2014-02-16 04:10:00,6.018\n2014-02-16 04:15:00,5.63\n2014-02-16 04:20:00,6.066\n2014-02-16 04:25:00,6.25\n2014-02-16 04:30:00,6.024\n2014-02-16 04:35:00,6.0420000000000025\n2014-02-16 04:40:00,6.228\n2014-02-16 04:45:00,5.6579999999999995\n2014-02-16 04:50:00,6.24\n2014-02-16 04:55:00,5.856\n2014-02-16 05:00:00,6.228\n2014-02-16 05:05:00,5.626\n2014-02-16 05:10:00,6.016\n2014-02-16 05:15:00,5.834\n2014-02-16 05:20:00,6.2520000000000024\n2014-02-16 05:25:00,5.612\n2014-02-16 05:30:00,5.877999999999999\n2014-02-16 05:35:00,5.834\n2014-02-16 05:40:00,6.0520000000000005\n2014-02-16 05:45:00,5.83\n2014-02-16 05:50:00,5.843999999999999\n2014-02-16 05:55:00,6.0420000000000025\n2014-02-16 06:00:00,6.044\n2014-02-16 06:05:00,5.827999999999999\n2014-02-16 06:10:00,6.044\n2014-02-16 06:15:00,5.626\n2014-02-16 06:20:00,6.046\n2014-02-16 06:25:00,5.8320000000000025\n2014-02-16 06:30:00,6.04\n2014-02-16 06:35:00,5.816\n2014-02-16 06:40:00,6.058\n2014-02-16 06:45:00,5.834\n2014-02-16 06:50:00,6.024\n2014-02-16 06:55:00,6.0420000000000025\n2014-02-16 07:00:00,6.256\n2014-02-16 07:05:00,5.626\n2014-02-16 07:10:00,6.2520000000000024\n2014-02-16 07:15:00,6.232\n2014-02-16 07:20:00,7.09\n2014-02-16 07:25:00,5.398\n2014-02-16 07:30:00,5.864\n2014-02-16 07:35:00,5.803999999999999\n2014-02-16 07:40:00,6.2860000000000005\n2014-02-16 07:45:00,5.834\n2014-02-16 07:50:00,6.03\n2014-02-16 07:55:00,7.122000000000001\n2014-02-16 08:00:00,6.436\n2014-02-16 08:05:00,6.046\n2014-02-16 08:10:00,6.004\n2014-02-16 08:15:00,5.837999999999999\n2014-02-16 08:20:00,6.278\n2014-02-16 08:25:00,5.834\n2014-02-16 08:30:00,6.876\n2014-02-16 08:35:00,5.1960000000000015\n2014-02-16 08:40:00,6.268\n2014-02-16 08:45:00,5.81\n2014-02-16 08:50:00,6.268\n2014-02-16 08:55:00,6.0360000000000005\n2014-02-16 09:00:00,6.2860000000000005\n2014-02-16 09:05:00,5.834\n2014-02-16 09:10:00,6.82\n2014-02-16 09:15:00,6.0520000000000005\n2014-02-16 09:20:00,6.266\n2014-02-16 09:25:00,6.0420000000000025\n2014-02-16 09:30:00,6.2479999999999976\n2014-02-16 09:35:00,6.23\n2014-02-16 09:40:00,6.4879999999999995\n2014-02-16 09:45:00,5.608\n2014-02-16 09:50:00,6.266\n2014-02-16 09:55:00,6.456\n2014-02-16 10:00:00,6.05\n2014-02-16 10:05:00,5.862\n2014-02-16 10:10:00,6.263999999999999\n2014-02-16 10:15:00,5.816\n2014-02-16 10:20:00,7.104\n2014-02-16 10:25:00,5.44\n2014-02-16 10:30:00,5.808\n2014-02-16 10:35:00,6.034\n2014-02-16 10:40:00,6.6720000000000015\n2014-02-16 10:45:00,5.822\n2014-02-16 10:50:00,6.412000000000001\n2014-02-16 10:55:00,6.4860000000000015\n2014-02-16 11:00:00,6.436\n2014-02-16 11:05:00,6.877999999999999\n2014-02-16 11:10:00,6.256\n2014-02-16 11:15:00,6.438\n2014-02-16 11:20:00,6.077999999999999\n2014-02-16 11:25:00,6.256\n2014-02-16 11:30:00,6.662000000000001\n2014-02-16 11:35:00,6.0420000000000025\n2014-02-16 11:40:00,6.6679999999999975\n2014-02-16 11:45:00,6.23\n2014-02-16 11:50:00,6.2479999999999976\n2014-02-16 11:55:00,6.278\n2014-02-16 12:00:00,6.4460000000000015\n2014-02-16 12:05:00,6.2620000000000005\n2014-02-16 12:10:00,6.722\n2014-02-16 12:15:00,6.858\n2014-02-16 12:20:00,6.294\n2014-02-16 12:25:00,6.23\n2014-02-16 12:30:00,6.274\n2014-02-16 12:35:00,6.257999999999999\n2014-02-16 12:40:00,6.688\n2014-02-16 12:45:00,6.257999999999999\n2014-02-16 12:50:00,6.706\n2014-02-16 12:55:00,6.4579999999999975\n2014-02-16 13:00:00,6.4639999999999995\n2014-02-16 13:05:00,6.874\n2014-02-16 13:10:00,6.872000000000001\n2014-02-16 13:15:00,6.0420000000000025\n2014-02-16 13:20:00,6.6679999999999975\n2014-02-16 13:25:00,6.25\n2014-02-16 13:30:00,6.2520000000000024\n2014-02-16 13:35:00,6.0420000000000025\n2014-02-16 13:40:00,6.228\n2014-02-16 13:45:00,6.064\n2014-02-16 13:50:00,6.2360000000000015\n2014-02-16 13:55:00,6.47\n2014-02-16 14:00:00,6.436\n2014-02-16 14:05:00,6.064\n2014-02-16 14:10:00,6.436\n2014-02-16 14:15:00,6.072\n2014-02-16 14:20:00,7.29\n2014-02-16 14:25:00,6.0420000000000025\n2014-02-16 14:30:00,6.6720000000000015\n2014-02-16 14:35:00,6.024\n2014-02-16 14:40:00,6.5020000000000024\n2014-02-16 14:45:00,6.46\n2014-02-16 14:50:00,6.2479999999999976\n2014-02-16 14:55:00,6.436\n2014-02-16 15:00:00,6.4979999999999976\n2014-02-16 15:05:00,6.232\n2014-02-16 15:10:00,7.5120000000000005\n2014-02-16 15:15:00,6.2620000000000005\n2014-02-16 15:20:00,6.2860000000000005\n2014-02-16 15:25:00,6.23\n2014-02-16 15:30:00,6.266\n2014-02-16 15:35:00,6.06\n2014-02-16 15:40:00,6.476\n2014-02-16 15:45:00,6.25\n2014-02-16 15:50:00,6.644\n2014-02-16 15:55:00,6.4639999999999995\n2014-02-16 16:00:00,6.706\n2014-02-16 16:05:00,6.874\n2014-02-16 16:10:00,6.03\n2014-02-16 16:15:00,6.234\n2014-02-16 16:20:00,6.6720000000000015\n2014-02-16 16:25:00,7.077999999999999\n2014-02-16 16:30:00,6.468\n2014-02-16 16:35:00,6.25\n2014-02-16 16:40:00,6.444\n2014-02-16 16:45:00,6.25\n2014-02-16 16:50:00,6.46\n2014-02-16 16:55:00,6.666\n2014-02-16 17:00:00,6.2120000000000015\n2014-02-16 17:05:00,6.278\n2014-02-16 17:10:00,6.4220000000000015\n2014-02-16 17:15:00,5.862\n2014-02-16 17:20:00,6.04\n2014-02-16 17:25:00,6.222\n2014-02-16 17:30:00,7.1339999999999995\n2014-02-16 17:35:00,5.827999999999999\n2014-02-16 17:40:00,6.044\n2014-02-16 17:45:00,6.022\n2014-02-16 17:50:00,5.867999999999999\n2014-02-16 17:55:00,6.037999999999999\n2014-02-16 18:00:00,6.2520000000000024\n2014-02-16 18:05:00,5.834\n2014-02-16 18:10:00,7.6560000000000015\n2014-02-16 18:15:00,5.228\n2014-02-16 18:20:00,6.232\n2014-02-16 18:25:00,6.074\n2014-02-16 18:30:00,6.436\n2014-02-16 18:35:00,6.0360000000000005\n2014-02-16 18:40:00,6.228\n2014-02-16 18:45:00,6.068\n2014-02-16 18:50:00,6.04\n2014-02-16 18:55:00,6.224\n2014-02-16 19:00:00,6.254\n2014-02-16 19:05:00,6.482\n2014-02-16 19:10:00,5.602\n2014-02-16 19:15:00,7.114\n2014-02-16 19:20:00,6.244\n2014-02-16 19:25:00,6.022\n2014-02-16 19:30:00,6.086\n2014-02-16 19:35:00,5.81\n2014-02-16 19:40:00,6.257999999999999\n2014-02-16 19:45:00,5.834\n2014-02-16 19:50:00,6.044\n2014-02-16 19:55:00,6.0420000000000025\n2014-02-16 20:00:00,6.047999999999999\n2014-02-16 20:05:00,5.834\n2014-02-16 20:10:00,6.228\n2014-02-16 20:15:00,6.86\n2014-02-16 20:20:00,5.816\n2014-02-16 20:25:00,6.4579999999999975\n2014-02-16 20:30:00,7.126\n2014-02-16 20:35:00,5.626\n2014-02-16 20:40:00,6.006\n2014-02-16 20:45:00,5.862\n2014-02-16 20:50:00,6.05\n2014-02-16 20:55:00,5.834\n2014-02-16 21:00:00,6.056\n2014-02-16 21:05:00,6.02\n2014-02-16 21:10:00,6.062\n2014-02-16 21:15:00,6.064\n2014-02-16 21:20:00,6.0420000000000025\n2014-02-16 21:25:00,6.68\n2014-02-16 21:30:00,7.08\n2014-02-16 21:35:00,5.814\n2014-02-16 21:40:00,6.077999999999999\n2014-02-16 21:45:00,6.006\n2014-02-16 21:50:00,5.864\n2014-02-16 21:55:00,5.834\n2014-02-16 22:00:00,6.4579999999999975\n2014-02-16 22:05:00,5.82\n2014-02-16 22:10:00,6.91\n2014-02-16 22:15:00,6.44\n2014-02-16 22:20:00,6.086\n2014-02-16 22:25:00,6.037999999999999\n2014-02-16 22:30:00,6.053999999999999\n2014-02-16 22:35:00,6.0420000000000025\n2014-02-16 22:40:00,6.03\n2014-02-16 22:45:00,6.064\n2014-02-16 22:50:00,6.044\n2014-02-16 22:55:00,6.0420000000000025\n2014-02-16 23:00:00,6.2520000000000024\n2014-02-16 23:05:00,6.0420000000000025\n2014-02-16 23:10:00,6.2479999999999976\n2014-02-16 23:15:00,6.024\n2014-02-16 23:20:00,6.272\n2014-02-16 23:25:00,7.51\n2014-02-16 23:30:00,6.278\n2014-02-16 23:35:00,6.064\n2014-02-16 23:40:00,6.2520000000000024\n2014-02-16 23:45:00,5.816\n2014-02-16 23:50:00,6.256\n2014-02-16 23:55:00,6.166\n2014-02-17 00:00:00,6.354\n2014-02-17 00:05:00,7.318\n2014-02-17 00:10:00,6.43\n2014-02-17 00:15:00,6.0420000000000025\n2014-02-17 00:20:00,6.256\n2014-02-17 00:25:00,6.0420000000000025\n2014-02-17 00:30:00,6.2520000000000024\n2014-02-17 00:35:00,5.837999999999999\n2014-02-17 00:40:00,6.2379999999999995\n2014-02-17 00:45:00,5.862\n2014-02-17 00:50:00,6.044\n2014-02-17 00:55:00,6.25\n2014-02-17 01:00:00,6.047999999999999\n2014-02-17 01:05:00,5.837999999999999\n2014-02-17 01:10:00,6.438\n2014-02-17 01:15:00,5.8320000000000025\n2014-02-17 01:20:00,6.03\n2014-02-17 01:25:00,6.053999999999999\n2014-02-17 01:30:00,7.528\n2014-02-17 01:35:00,5.8420000000000005\n2014-02-17 01:40:00,6.056\n2014-02-17 01:45:00,5.8420000000000005\n2014-02-17 01:50:00,6.016\n2014-02-17 01:55:00,5.8660000000000005\n2014-02-17 02:00:00,6.0520000000000005\n2014-02-17 02:05:00,6.01\n2014-02-17 02:10:00,6.0520000000000005\n2014-02-17 02:15:00,5.63\n2014-02-17 02:20:00,7.7\n2014-02-17 02:25:00,6.244\n2014-02-17 02:30:00,6.246\n2014-02-17 02:35:00,5.638\n2014-02-17 02:40:00,6.297999999999999\n2014-02-17 02:45:00,6.032\n2014-02-17 02:50:00,6.2520000000000024\n2014-02-17 02:55:00,6.022\n2014-02-17 03:00:00,6.482\n2014-02-17 03:05:00,6.06\n2014-02-17 03:10:00,6.2520000000000024\n2014-02-17 03:15:00,7.077999999999999\n2014-02-17 03:20:00,6.654\n2014-02-17 03:25:00,6.068\n2014-02-17 03:30:00,6.044\n2014-02-17 03:35:00,5.834\n2014-02-17 03:40:00,6.25\n2014-02-17 03:45:00,6.452000000000001\n2014-02-17 03:50:00,5.626\n2014-02-17 03:55:00,6.018\n2014-02-17 04:00:00,6.0820000000000025\n2014-02-17 04:05:00,6.024\n2014-02-17 04:10:00,6.096\n2014-02-17 04:15:00,5.837999999999999\n2014-02-17 04:20:00,6.263999999999999\n2014-02-17 04:25:00,5.814\n2014-02-17 04:30:00,6.086\n2014-02-17 04:35:00,5.8420000000000005\n2014-02-17 04:40:00,6.028\n2014-02-17 04:45:00,5.816\n2014-02-17 04:50:00,5.8839999999999995\n2014-02-17 04:55:00,6.246\n2014-02-17 05:00:00,6.204\n2014-02-17 05:05:00,5.86\n2014-02-17 05:10:00,6.016\n2014-02-17 05:15:00,6.028\n2014-02-17 05:20:00,6.7120000000000015\n2014-02-17 05:25:00,5.837999999999999\n2014-02-17 05:30:00,6.478\n2014-02-17 05:35:00,5.814\n2014-02-17 05:40:00,6.297999999999999\n2014-02-17 05:45:00,6.0420000000000025\n2014-02-17 05:50:00,6.2479999999999976\n2014-02-17 05:55:00,6.034\n2014-02-17 06:00:00,6.228\n2014-02-17 06:05:00,6.05\n2014-02-17 06:10:00,6.494\n2014-02-17 06:15:00,5.816\n2014-02-17 06:20:00,6.077999999999999\n2014-02-17 06:25:00,6.04\n2014-02-17 06:30:00,6.228\n2014-02-17 06:35:00,5.856\n2014-02-17 06:40:00,6.04\n2014-02-17 06:45:00,6.034\n2014-02-17 06:50:00,6.046\n2014-02-17 06:55:00,5.834\n2014-02-17 07:00:00,6.2479999999999976\n2014-02-17 07:05:00,6.046\n2014-02-17 07:10:00,6.0360000000000005\n2014-02-17 07:15:00,6.05\n2014-02-17 07:20:00,5.85\n2014-02-17 07:25:00,6.044\n2014-02-17 07:30:00,6.016\n2014-02-17 07:35:00,5.834\n2014-02-17 07:40:00,6.044\n2014-02-17 07:45:00,6.04\n2014-02-17 07:50:00,6.228\n2014-02-17 07:55:00,7.29\n2014-02-17 08:00:00,6.412000000000001\n2014-02-17 08:05:00,6.064\n2014-02-17 08:10:00,6.23\n2014-02-17 08:15:00,6.234\n2014-02-17 08:20:00,6.087999999999999\n2014-02-17 08:25:00,6.047999999999999\n2014-02-17 08:30:00,6.228\n2014-02-17 08:35:00,6.022\n2014-02-17 08:40:00,6.282\n2014-02-17 08:45:00,6.228\n2014-02-17 08:50:00,6.2620000000000005\n2014-02-17 08:55:00,6.0420000000000025\n2014-02-17 09:00:00,6.022\n2014-02-17 09:05:00,6.064\n2014-02-17 09:10:00,6.452000000000001\n2014-02-17 09:15:00,5.814\n2014-02-17 09:20:00,5.867999999999999\n2014-02-17 09:25:00,6.0420000000000025\n2014-02-17 09:30:00,6.0120000000000005\n2014-02-17 09:35:00,5.64\n2014-02-17 09:40:00,6.03\n2014-02-17 09:45:00,5.852\n2014-02-17 09:50:00,5.9979999999999976\n2014-02-17 09:55:00,6.074\n2014-02-17 10:00:00,5.824\n2014-02-17 10:05:00,5.836\n2014-02-17 10:10:00,6.246\n2014-02-17 10:15:00,5.8320000000000025\n2014-02-17 10:20:00,6.2520000000000024\n2014-02-17 10:25:00,6.664\n2014-02-17 10:30:00,6.04\n2014-02-17 10:35:00,6.046\n2014-02-17 10:40:00,6.2620000000000005\n2014-02-17 10:45:00,6.0420000000000025\n2014-02-17 10:50:00,6.044\n2014-02-17 10:55:00,6.026\n2014-02-17 11:00:00,6.26\n2014-02-17 11:05:00,6.25\n2014-02-17 11:10:00,6.684\n2014-02-17 11:15:00,5.8420000000000005\n2014-02-17 11:20:00,5.834\n2014-02-17 11:25:00,6.242000000000001\n2014-02-17 11:30:00,6.024\n2014-02-17 11:35:00,5.648\n2014-02-17 11:40:00,6.4639999999999995\n2014-02-17 11:45:00,5.816\n2014-02-17 11:50:00,6.053999999999999\n2014-02-17 11:55:00,5.862\n2014-02-17 12:00:00,6.05\n2014-02-17 12:05:00,5.812\n2014-02-17 12:10:00,6.468\n2014-02-17 12:15:00,6.2620000000000005\n2014-02-17 12:20:00,5.87\n2014-02-17 12:25:00,5.834\n2014-02-17 12:30:00,6.044\n2014-02-17 12:35:00,5.827999999999999\n2014-02-17 12:40:00,6.0360000000000005\n2014-02-17 12:45:00,5.856\n2014-02-17 12:50:00,6.2520000000000024\n2014-02-17 12:55:00,6.2520000000000024\n2014-02-17 13:00:00,6.43\n2014-02-17 13:05:00,6.6679999999999975\n2014-02-17 13:10:00,6.2479999999999976\n2014-02-17 13:15:00,6.0420000000000025\n2014-02-17 13:20:00,6.26\n2014-02-17 13:25:00,6.03\n2014-02-17 13:30:00,6.028\n2014-02-17 13:35:00,6.064\n2014-02-17 13:40:00,6.04\n2014-02-17 13:45:00,6.0420000000000025\n2014-02-17 13:50:00,6.02\n2014-02-17 13:55:00,6.07\n2014-02-17 14:00:00,6.044\n2014-02-17 14:05:00,6.0420000000000025\n2014-02-17 14:10:00,6.468\n2014-02-17 14:15:00,6.46\n2014-02-17 14:20:00,6.004\n2014-02-17 14:25:00,6.074\n2014-02-17 14:30:00,6.03\n2014-02-17 14:35:00,6.05\n2014-02-17 14:40:00,6.07\n2014-02-17 14:45:00,5.822\n2014-02-17 14:50:00,6.03\n2014-02-17 14:55:00,6.07\n2014-02-17 15:00:00,6.4460000000000015\n2014-02-17 15:05:00,6.482\n2014-02-17 15:10:00,6.2360000000000015\n2014-02-17 15:15:00,5.834\n2014-02-17 15:20:00,6.228\n2014-02-17 15:25:00,6.234\n2014-02-17 15:30:00,6.257999999999999\n2014-02-17 15:35:00,5.816\n2014-02-17 15:40:00,6.66\n2014-02-17 15:45:00,5.856\n2014-02-17 15:50:00,6.26\n2014-02-17 15:55:00,6.2139999999999995\n2014-02-17 16:00:00,6.0820000000000025\n2014-02-17 16:05:00,6.046\n2014-02-17 16:10:00,6.6679999999999975\n2014-02-17 16:15:00,6.4479999999999995\n2014-02-17 16:20:00,6.047999999999999\n2014-02-17 16:25:00,5.816\n2014-02-17 16:30:00,6.086\n2014-02-17 16:35:00,5.8260000000000005\n2014-02-17 16:40:00,6.04\n2014-02-17 16:45:00,5.83\n2014-02-17 16:50:00,6.056\n2014-02-17 16:55:00,6.047999999999999\n2014-02-17 17:00:00,5.846\n2014-02-17 17:05:00,5.834\n2014-02-17 17:10:00,6.876\n2014-02-17 17:15:00,6.442\n2014-02-17 17:20:00,6.053999999999999\n2014-02-17 17:25:00,5.63\n2014-02-17 17:30:00,6.2520000000000024\n2014-02-17 17:35:00,5.824\n2014-02-17 17:40:00,6.024\n2014-02-17 17:45:00,6.022\n2014-02-17 17:50:00,6.053999999999999\n2014-02-17 17:55:00,6.046\n2014-02-17 18:00:00,6.412000000000001\n2014-02-17 18:05:00,6.692\n2014-02-17 18:10:00,6.68\n2014-02-17 18:15:00,5.827999999999999\n2014-02-17 18:20:00,6.2520000000000024\n2014-02-17 18:25:00,5.82\n2014-02-17 18:30:00,6.278\n2014-02-17 18:35:00,5.834\n2014-02-17 18:40:00,6.263999999999999\n2014-02-17 18:45:00,5.836\n2014-02-17 18:50:00,6.058\n2014-02-17 18:55:00,5.84\n2014-02-17 19:00:00,5.992000000000001\n2014-02-17 19:05:00,5.848\n2014-02-17 19:10:00,7.532\n2014-02-17 19:15:00,5.827999999999999\n2014-02-17 19:20:00,6.044\n2014-02-17 19:25:00,5.8320000000000025\n2014-02-17 19:30:00,6.044\n2014-02-17 19:35:00,5.626\n2014-02-17 19:40:00,6.234\n2014-02-17 19:45:00,5.862\n2014-02-17 19:50:00,5.8420000000000005\n2014-02-17 19:55:00,5.827999999999999\n2014-02-17 20:00:00,5.8420000000000005\n2014-02-17 20:05:00,6.034\n2014-02-17 20:10:00,5.81\n2014-02-17 20:15:00,5.837999999999999\n2014-02-17 20:20:00,5.85\n2014-02-17 20:25:00,6.242000000000001\n2014-02-17 20:30:00,6.0\n2014-02-17 20:35:00,6.892\n2014-02-17 20:40:00,6.4460000000000015\n2014-02-17 20:45:00,6.074\n2014-02-17 20:50:00,5.82\n2014-02-17 20:55:00,5.837999999999999\n2014-02-17 21:00:00,6.877999999999999\n2014-02-17 21:05:00,6.452000000000001\n2014-02-17 21:10:00,6.024\n2014-02-17 21:15:00,6.0360000000000005\n2014-02-17 21:20:00,6.024\n2014-02-17 21:25:00,6.2860000000000005\n2014-02-17 21:30:00,7.104\n2014-02-17 21:35:00,6.016\n2014-02-17 21:40:00,6.077999999999999\n2014-02-17 21:45:00,6.034\n2014-02-17 21:50:00,6.25\n2014-02-17 21:55:00,6.0420000000000025\n2014-02-17 22:00:00,6.1979999999999995\n2014-02-17 22:05:00,6.068\n2014-02-17 22:10:00,6.056\n2014-02-17 22:15:00,5.83\n2014-02-17 22:20:00,6.018\n2014-02-17 22:25:00,5.862\n2014-02-17 22:30:00,6.0520000000000005\n2014-02-17 22:35:00,5.83\n2014-02-17 22:40:00,7.084\n2014-02-17 22:45:00,6.25\n2014-02-17 22:50:00,6.0520000000000005\n2014-02-17 22:55:00,5.834\n2014-02-17 23:00:00,6.024\n2014-02-17 23:05:00,5.626\n2014-02-17 23:10:00,6.22\n2014-02-17 23:15:00,5.62\n2014-02-17 23:20:00,6.0120000000000005\n2014-02-17 23:25:00,5.837999999999999\n2014-02-17 23:30:00,7.084\n2014-02-17 23:35:00,6.25\n2014-02-17 23:40:00,6.256\n2014-02-17 23:45:00,5.827999999999999\n2014-02-17 23:50:00,6.2520000000000024\n2014-02-17 23:55:00,6.176\n2014-02-18 00:00:00,6.1\n2014-02-18 00:05:00,6.69\n2014-02-18 00:10:00,7.06\n2014-02-18 00:15:00,6.07\n2014-02-18 00:20:00,6.024\n2014-02-18 00:25:00,5.843999999999999\n2014-02-18 00:30:00,6.287999999999999\n2014-02-18 00:35:00,5.827999999999999\n2014-02-18 00:40:00,6.062\n2014-02-18 00:45:00,5.816\n2014-02-18 00:50:00,6.0760000000000005\n2014-02-18 00:55:00,6.04\n2014-02-18 01:00:00,6.044\n2014-02-18 01:05:00,6.04\n2014-02-18 01:10:00,7.88\n2014-02-18 01:15:00,5.854\n2014-02-18 01:20:00,6.026\n2014-02-18 01:25:00,6.4860000000000015\n2014-02-18 01:30:00,5.4220000000000015\n2014-02-18 01:35:00,6.04\n2014-02-18 01:40:00,6.03\n2014-02-18 01:45:00,5.862\n2014-02-18 01:50:00,5.824\n2014-02-18 01:55:00,5.834\n2014-02-18 02:00:00,6.206\n2014-02-18 02:05:00,5.852\n2014-02-18 02:10:00,6.2520000000000024\n2014-02-18 02:15:00,6.016\n2014-02-18 02:20:00,7.76\n2014-02-18 02:25:00,6.44\n2014-02-18 02:30:00,6.297999999999999\n2014-02-18 02:35:00,5.814\n2014-02-18 02:40:00,6.278\n2014-02-18 02:45:00,6.04\n2014-02-18 02:50:00,6.04\n2014-02-18 02:55:00,6.028\n2014-02-18 03:00:00,7.3279999999999985\n2014-02-18 03:05:00,6.6679999999999975\n2014-02-18 03:10:00,6.0520000000000005\n2014-02-18 03:15:00,6.0420000000000025\n2014-02-18 03:20:00,6.0420000000000025\n2014-02-18 03:25:00,6.044\n2014-02-18 03:30:00,6.056\n2014-02-18 03:35:00,5.834\n2014-02-18 03:40:00,6.047999999999999\n2014-02-18 03:45:00,5.812\n2014-02-18 03:50:00,6.09\n2014-02-18 03:55:00,6.026\n2014-02-18 04:00:00,5.85\n2014-02-18 04:05:00,6.034\n2014-02-18 04:10:00,6.024\n2014-02-18 04:15:00,5.862\n2014-02-18 04:20:00,6.02\n2014-02-18 04:25:00,5.862\n2014-02-18 04:30:00,6.037999999999999\n2014-02-18 04:35:00,5.827999999999999\n2014-02-18 04:40:00,6.044\n2014-02-18 04:45:00,6.024\n2014-02-18 04:50:00,6.08\n2014-02-18 04:55:00,6.022\n2014-02-18 05:00:00,6.077999999999999\n2014-02-18 05:05:00,5.8320000000000025\n2014-02-18 05:10:00,6.436\n2014-02-18 05:15:00,6.064\n2014-02-18 05:20:00,6.04\n2014-02-18 05:25:00,7.0520000000000005\n2014-02-18 05:30:00,5.606\n2014-02-18 05:35:00,6.064\n2014-02-18 05:40:00,6.2360000000000015\n2014-02-18 05:45:00,6.496\n2014-02-18 05:50:00,5.426\n2014-02-18 05:55:00,6.438\n2014-02-18 06:00:00,6.074\n2014-02-18 06:05:00,6.04\n2014-02-18 06:10:00,6.218\n2014-02-18 06:15:00,5.862\n2014-02-18 06:20:00,6.04\n2014-02-18 06:25:00,6.218\n2014-02-18 06:30:00,6.058\n2014-02-18 06:35:00,5.837999999999999\n2014-02-18 06:40:00,6.0820000000000025\n2014-02-18 06:45:00,5.8320000000000025\n2014-02-18 06:50:00,6.044\n2014-02-18 06:55:00,6.254\n2014-02-18 07:00:00,6.0120000000000005\n2014-02-18 07:05:00,5.83\n2014-02-18 07:10:00,6.4639999999999995\n2014-02-18 07:15:00,5.816\n2014-02-18 07:20:00,6.08\n2014-02-18 07:25:00,5.827999999999999\n2014-02-18 07:30:00,6.044\n2014-02-18 07:35:00,5.8020000000000005\n2014-02-18 07:40:00,6.4460000000000015\n2014-02-18 07:45:00,6.068\n2014-02-18 07:50:00,6.024\n2014-02-18 07:55:00,6.9079999999999995\n2014-02-18 08:00:00,6.652\n2014-02-18 08:05:00,6.077999999999999\n2014-02-18 08:10:00,6.2520000000000024\n2014-02-18 08:15:00,6.4620000000000015\n2014-02-18 08:20:00,6.037999999999999\n2014-02-18 08:25:00,5.827999999999999\n2014-02-18 08:30:00,6.276\n2014-02-18 08:35:00,5.834\n2014-02-18 08:40:00,6.007999999999999\n2014-02-18 08:45:00,6.074\n2014-02-18 08:50:00,6.022\n2014-02-18 08:55:00,6.07\n2014-02-18 09:00:00,6.044\n2014-02-18 09:05:00,5.63\n2014-02-18 09:10:00,6.2520000000000024\n2014-02-18 09:15:00,5.82\n2014-02-18 09:20:00,6.044\n2014-02-18 09:25:00,6.46\n2014-02-18 09:30:00,6.044\n2014-02-18 09:35:00,5.622000000000001\n2014-02-18 09:40:00,6.056\n2014-02-18 09:45:00,5.816\n2014-02-18 09:50:00,6.062\n2014-02-18 09:55:00,6.046\n2014-02-18 10:00:00,5.85\n2014-02-18 10:05:00,6.4579999999999975\n2014-02-18 10:10:00,6.6679999999999975\n2014-02-18 10:15:00,5.81\n2014-02-18 10:20:00,6.08\n2014-02-18 10:25:00,5.834\n2014-02-18 10:30:00,5.843999999999999\n2014-02-18 10:35:00,5.834\n2014-02-18 10:40:00,5.834\n2014-02-18 10:45:00,5.626\n2014-02-18 10:50:00,6.024\n2014-02-18 10:55:00,6.032\n2014-02-18 11:00:00,6.266\n2014-02-18 11:05:00,5.836\n2014-02-18 11:10:00,5.836\n2014-02-18 11:15:00,5.827999999999999\n2014-02-18 11:20:00,6.468\n2014-02-18 11:25:00,5.62\n2014-02-18 11:30:00,6.2379999999999995\n2014-02-18 11:35:00,6.06\n2014-02-18 11:40:00,6.232\n2014-02-18 11:45:00,6.064\n2014-02-18 11:50:00,6.2520000000000024\n2014-02-18 11:55:00,6.25\n2014-02-18 12:00:00,6.2079999999999975\n2014-02-18 12:05:00,5.862\n2014-02-18 12:10:00,6.682\n2014-02-18 12:15:00,6.244\n2014-02-18 12:20:00,6.0120000000000005\n2014-02-18 12:25:00,6.25\n2014-02-18 12:30:00,6.024\n2014-02-18 12:35:00,5.81\n2014-02-18 12:40:00,6.297999999999999\n2014-02-18 12:45:00,5.836\n2014-02-18 12:50:00,5.836\n2014-02-18 12:55:00,6.246\n2014-02-18 13:00:00,6.642\n2014-02-18 13:05:00,6.037999999999999\n2014-02-18 13:10:00,6.266\n2014-02-18 13:15:00,5.816\n2014-02-18 13:20:00,6.053999999999999\n2014-02-18 13:25:00,5.824\n2014-02-18 13:30:00,6.058\n2014-02-18 13:35:00,5.63\n2014-02-18 13:40:00,6.02\n2014-02-18 13:45:00,6.044\n2014-02-18 13:50:00,6.0420000000000025\n2014-02-18 13:55:00,5.834\n2014-02-18 14:00:00,6.46\n2014-02-18 14:05:00,6.026\n2014-02-18 14:10:00,6.432\n2014-02-18 14:15:00,5.856\n2014-02-18 14:20:00,6.2520000000000024\n2014-02-18 14:25:00,6.0420000000000025\n2014-02-18 14:30:00,6.228\n2014-02-18 14:35:00,6.05\n2014-02-18 14:40:00,6.297999999999999\n2014-02-18 14:45:00,6.0360000000000005\n2014-02-18 14:50:00,6.263999999999999\n2014-02-18 14:55:00,6.4579999999999975\n2014-02-18 15:00:00,5.59\n2014-02-18 15:05:00,5.86\n2014-02-18 15:10:00,6.228\n2014-02-18 15:15:00,5.834\n2014-02-18 15:20:00,6.856\n2014-02-18 15:25:00,6.064\n2014-02-18 15:30:00,6.024\n2014-02-18 15:35:00,5.848\n2014-02-18 15:40:00,6.037999999999999\n2014-02-18 15:45:00,6.07\n2014-02-18 15:50:00,5.8420000000000005\n2014-02-18 15:55:00,6.0420000000000025\n2014-02-18 16:00:00,6.0520000000000005\n2014-02-18 16:05:00,5.827999999999999\n2014-02-18 16:10:00,6.044\n2014-02-18 16:15:00,5.834\n2014-02-18 16:20:00,6.876\n2014-02-18 16:25:00,5.62\n2014-02-18 16:30:00,6.4639999999999995\n2014-02-18 16:35:00,6.016\n2014-02-18 16:40:00,6.3020000000000005\n2014-02-18 16:45:00,6.4579999999999975\n2014-02-18 16:50:00,5.626\n2014-02-18 16:55:00,6.0360000000000005\n2014-02-18 17:00:00,6.044\n2014-02-18 17:05:00,6.25\n2014-02-18 17:10:00,6.0420000000000025\n2014-02-18 17:15:00,6.244\n2014-02-18 17:20:00,6.676\n2014-02-18 17:25:00,6.046\n2014-02-18 17:30:00,5.84\n2014-02-18 17:35:00,6.0360000000000005\n2014-02-18 17:40:00,6.46\n2014-02-18 17:45:00,6.04\n2014-02-18 17:50:00,6.2520000000000024\n2014-02-18 17:55:00,6.222\n2014-02-18 18:00:00,6.29\n2014-02-18 18:05:00,6.254\n2014-02-18 18:10:00,7.084\n2014-02-18 18:15:00,6.0420000000000025\n2014-02-18 18:20:00,6.2479999999999976\n2014-02-18 18:25:00,6.037999999999999\n2014-02-18 18:30:00,6.26\n2014-02-18 18:35:00,6.046\n2014-02-18 18:40:00,6.228\n2014-02-18 18:45:00,5.856\n2014-02-18 18:50:00,6.0520000000000005\n2014-02-18 18:55:00,5.834\n2014-02-18 19:00:00,6.46\n2014-02-18 19:05:00,6.016\n2014-02-18 19:10:00,7.54\n2014-02-18 19:15:00,5.816\n2014-02-18 19:20:00,6.09\n2014-02-18 19:25:00,5.834\n2014-02-18 19:30:00,6.0\n2014-02-18 19:35:00,5.837999999999999\n2014-02-18 19:40:00,6.058\n2014-02-18 19:45:00,5.822\n2014-02-18 19:50:00,6.022\n2014-02-18 19:55:00,6.064\n2014-02-18 20:00:00,6.022\n2014-02-18 20:05:00,5.856\n2014-02-18 20:10:00,6.436\n2014-02-18 20:15:00,5.862\n2014-02-18 20:20:00,6.0520000000000005\n2014-02-18 20:25:00,6.876\n2014-02-18 20:30:00,6.414\n2014-02-18 20:35:00,6.07\n2014-02-18 20:40:00,6.016\n2014-02-18 20:45:00,5.837999999999999\n2014-02-18 20:50:00,6.07\n2014-02-18 20:55:00,5.808\n2014-02-18 21:00:00,6.086\n2014-02-18 21:05:00,5.816\n2014-02-18 21:10:00,6.276\n2014-02-18 21:15:00,6.044\n2014-02-18 21:20:00,6.053999999999999\n2014-02-18 21:25:00,7.266\n2014-02-18 21:30:00,6.2920000000000025\n2014-02-18 21:35:00,6.03\n2014-02-18 21:40:00,5.814\n2014-02-18 21:45:00,5.862\n2014-02-18 21:50:00,5.827999999999999\n2014-02-18 21:55:00,6.037999999999999\n2014-02-18 22:00:00,6.04\n2014-02-18 22:05:00,5.834\n2014-02-18 22:10:00,6.876\n2014-02-18 22:15:00,6.642\n2014-02-18 22:20:00,6.053999999999999\n2014-02-18 22:25:00,6.05\n2014-02-18 22:30:00,6.044\n2014-02-18 22:35:00,5.834\n2014-02-18 22:40:00,6.228\n2014-02-18 22:45:00,5.837999999999999\n2014-02-18 22:50:00,6.01\n2014-02-18 22:55:00,6.69\n2014-02-18 23:00:00,6.0420000000000025\n2014-02-18 23:05:00,6.877999999999999\n2014-02-18 23:10:00,6.6679999999999975\n2014-02-18 23:15:00,5.837999999999999\n2014-02-18 23:20:00,6.22\n2014-02-18 23:25:00,6.4579999999999975\n2014-02-18 23:30:00,6.026\n2014-02-18 23:35:00,5.8660000000000005\n2014-02-18 23:40:00,6.256\n2014-02-18 23:45:00,5.837999999999999\n2014-02-18 23:50:00,6.0520000000000005\n2014-02-18 23:55:00,5.978\n2014-02-19 00:00:00,6.1560000000000015\n2014-02-19 00:05:00,5.834\n2014-02-19 00:10:00,6.228\n2014-02-19 00:15:00,7.114\n2014-02-19 00:20:00,6.644\n2014-02-19 00:25:00,6.064\n2014-02-19 00:30:00,6.2520000000000024\n2014-02-19 00:35:00,6.0420000000000025\n2014-02-19 00:40:00,6.2520000000000024\n2014-02-19 00:45:00,6.024\n2014-02-19 00:50:00,6.29\n2014-02-19 00:55:00,6.022\n2014-02-19 01:00:00,6.888\n2014-02-19 01:05:00,5.232\n2014-02-19 01:10:00,6.6679999999999975\n2014-02-19 01:15:00,5.834\n2014-02-19 01:20:00,6.68\n2014-02-19 01:25:00,7.272\n2014-02-19 01:30:00,6.077999999999999\n2014-02-19 01:35:00,5.816\n2014-02-19 01:40:00,6.3\n2014-02-19 01:45:00,5.82\n2014-02-19 01:50:00,5.872000000000001\n2014-02-19 01:55:00,6.224\n2014-02-19 02:00:00,6.068\n2014-02-19 02:05:00,5.862\n2014-02-19 02:10:00,6.206\n2014-02-19 02:15:00,6.902\n2014-02-19 02:20:00,6.646\n2014-02-19 02:25:00,5.816\n2014-02-19 02:30:00,6.062\n2014-02-19 02:35:00,5.837999999999999\n2014-02-19 02:40:00,6.053999999999999\n2014-02-19 02:45:00,5.84\n2014-02-19 02:50:00,6.056\n2014-02-19 02:55:00,6.25\n2014-02-19 03:00:00,6.2520000000000024\n2014-02-19 03:05:00,6.0420000000000025\n2014-02-19 03:10:00,6.228\n2014-02-19 03:15:00,6.046\n2014-02-19 03:20:00,6.02\n2014-02-19 03:25:00,6.068\n2014-02-19 03:30:00,6.6579999999999995\n2014-02-19 03:35:00,7.296\n2014-02-19 03:40:00,6.228\n2014-02-19 03:45:00,5.856\n2014-02-19 03:50:00,6.2520000000000024\n2014-02-19 03:55:00,5.834\n2014-02-19 04:00:00,6.41\n2014-02-19 04:05:00,5.848\n2014-02-19 04:10:00,6.228\n2014-02-19 04:15:00,5.8660000000000005\n2014-02-19 04:20:00,6.044\n2014-02-19 04:25:00,6.034\n2014-02-19 04:30:00,6.022\n2014-02-19 04:35:00,5.862\n2014-02-19 04:40:00,6.254\n2014-02-19 04:45:00,5.8420000000000005\n2014-02-19 04:50:00,5.816\n2014-02-19 04:55:00,6.07\n2014-02-19 05:00:00,6.03\n2014-02-19 05:05:00,6.48\n2014-02-19 05:10:00,5.402\n2014-02-19 05:15:00,5.856\n2014-02-19 05:20:00,6.044\n2014-02-19 05:25:00,6.2520000000000024\n2014-02-19 05:30:00,6.2520000000000024\n2014-02-19 05:35:00,5.83\n2014-02-19 05:40:00,6.232\n2014-02-19 05:45:00,6.0420000000000025\n2014-02-19 05:50:00,6.024\n2014-02-19 05:55:00,6.25\n2014-02-19 06:00:00,6.04\n2014-02-19 06:05:00,6.25\n2014-02-19 06:10:00,6.0360000000000005\n2014-02-19 06:15:00,6.24\n2014-02-19 06:20:00,6.6679999999999975\n2014-02-19 06:25:00,5.624\n2014-02-19 06:30:00,6.044\n2014-02-19 06:35:00,5.836\n2014-02-19 06:40:00,6.0420000000000025\n2014-02-19 06:45:00,5.834\n2014-02-19 06:50:00,6.0420000000000025\n2014-02-19 06:55:00,6.0420000000000025\n2014-02-19 07:00:00,6.664\n2014-02-19 07:05:00,5.837999999999999\n2014-02-19 07:10:00,6.6339999999999995\n2014-02-19 07:15:00,5.222\n2014-02-19 07:20:00,6.05\n2014-02-19 07:25:00,5.827999999999999\n2014-02-19 07:30:00,6.047999999999999\n2014-02-19 07:35:00,5.83\n2014-02-19 07:40:00,5.836\n2014-02-19 07:45:00,6.018\n2014-02-19 07:50:00,6.077999999999999\n2014-02-19 07:55:00,7.0820000000000025\n2014-02-19 08:00:00,7.2520000000000024\n2014-02-19 08:05:00,5.42\n2014-02-19 08:10:00,6.266\n2014-02-19 08:15:00,5.816\n2014-02-19 08:20:00,6.257999999999999\n2014-02-19 08:25:00,5.8420000000000005\n2014-02-19 08:30:00,6.266\n2014-02-19 08:35:00,6.037999999999999\n2014-02-19 08:40:00,6.244\n2014-02-19 08:45:00,5.834\n2014-02-19 08:50:00,6.044\n2014-02-19 08:55:00,6.256\n2014-02-19 09:00:00,6.044\n2014-02-19 09:05:00,6.4579999999999975\n2014-02-19 09:10:00,6.0360000000000005\n2014-02-19 09:15:00,6.0420000000000025\n2014-02-19 09:20:00,6.25\n2014-02-19 09:25:00,5.834\n2014-02-19 09:30:00,6.047999999999999\n2014-02-19 09:35:00,5.62\n2014-02-19 09:40:00,6.256\n2014-02-19 09:45:00,5.626\n2014-02-19 09:50:00,6.2360000000000015\n2014-02-19 09:55:00,6.4639999999999995\n2014-02-19 10:00:00,5.6339999999999995\n2014-02-19 10:05:00,6.49\n2014-02-19 10:10:00,6.026\n2014-02-19 10:15:00,5.64\n2014-02-19 10:20:00,6.077999999999999\n2014-02-19 10:25:00,5.83\n2014-02-19 10:30:00,6.254\n2014-02-19 10:35:00,6.032\n2014-02-19 10:40:00,6.228\n2014-02-19 10:45:00,6.05\n2014-02-19 10:50:00,6.037999999999999\n2014-02-19 10:55:00,6.2860000000000005\n2014-02-19 11:00:00,6.044\n2014-02-19 11:05:00,6.25\n2014-02-19 11:10:00,6.0520000000000005\n2014-02-19 11:15:00,5.816\n2014-02-19 11:20:00,6.058\n2014-02-19 11:25:00,6.0420000000000025\n2014-02-19 11:30:00,7.254\n2014-02-19 11:35:00,5.834\n2014-02-19 11:40:00,6.2520000000000024\n2014-02-19 11:45:00,6.032\n2014-02-19 11:50:00,5.834\n2014-02-19 11:55:00,6.244\n2014-02-19 12:00:00,6.648\n2014-02-19 12:05:00,6.07\n2014-02-19 12:10:00,6.062\n2014-02-19 12:15:00,5.834\n2014-02-19 12:20:00,6.2520000000000024\n2014-02-19 12:25:00,5.82\n2014-02-19 12:30:00,6.4479999999999995\n2014-02-19 12:35:00,5.44\n2014-02-19 12:40:00,6.016\n2014-02-19 12:45:00,5.856\n2014-02-19 12:50:00,6.024\n2014-02-19 12:55:00,6.492000000000001\n2014-02-19 13:00:00,5.85\n2014-02-19 13:05:00,5.834\n2014-02-19 13:10:00,6.44\n2014-02-19 13:15:00,5.836\n2014-02-19 13:20:00,5.876\n2014-02-19 13:25:00,5.836\n2014-02-19 13:30:00,6.02\n2014-02-19 13:35:00,6.49\n2014-02-19 13:40:00,5.992000000000001\n2014-02-19 13:45:00,6.282\n2014-02-19 13:50:00,6.228\n2014-02-19 13:55:00,6.25\n2014-02-19 14:00:00,6.066\n2014-02-19 14:05:00,6.022\n2014-02-19 14:10:00,6.888\n2014-02-19 14:15:00,5.827999999999999\n2014-02-19 14:20:00,6.26\n2014-02-19 14:25:00,6.0420000000000025\n2014-02-19 14:30:00,6.046\n2014-02-19 14:35:00,5.827999999999999\n2014-02-19 14:40:00,6.226\n2014-02-19 14:45:00,5.837999999999999\n2014-02-19 14:50:00,6.066\n2014-02-19 14:55:00,6.0420000000000025\n2014-02-19 15:00:00,6.4620000000000015\n2014-02-19 15:05:00,5.626\n2014-02-19 15:10:00,6.46\n2014-02-19 15:15:00,6.224\n2014-02-19 15:20:00,5.4460000000000015\n2014-02-19 15:25:00,6.867999999999999\n2014-02-19 15:30:00,6.04\n2014-02-19 15:35:00,5.8420000000000005\n2014-02-19 15:40:00,6.016\n2014-02-19 15:45:00,5.86\n2014-02-19 15:50:00,6.02\n2014-02-19 15:55:00,6.072\n2014-02-19 16:00:00,6.256\n2014-02-19 16:05:00,5.82\n2014-02-19 16:10:00,6.91\n2014-02-19 16:15:00,5.834\n2014-02-19 16:20:00,6.256\n2014-02-19 16:25:00,6.032\n2014-02-19 16:30:00,6.02\n2014-02-19 16:35:00,5.8660000000000005\n2014-02-19 16:40:00,6.0520000000000005\n2014-02-19 16:45:00,5.626\n2014-02-19 16:50:00,6.232\n2014-02-19 16:55:00,5.827999999999999\n2014-02-19 17:00:00,5.996\n2014-02-19 17:05:00,6.074\n2014-02-19 17:10:00,7.098\n2014-02-19 17:15:00,5.834\n2014-02-19 17:20:00,6.2479999999999976\n2014-02-19 17:25:00,5.81\n2014-02-19 17:30:00,5.85\n2014-02-19 17:35:00,5.836\n2014-02-19 17:40:00,6.032\n2014-02-19 17:45:00,5.598\n2014-02-19 17:50:00,6.474\n2014-02-19 17:55:00,6.694\n2014-02-19 18:00:00,5.602\n2014-02-19 18:05:00,5.862\n2014-02-19 18:10:00,6.2520000000000024\n2014-02-19 18:15:00,6.0420000000000025\n2014-02-19 18:20:00,6.8839999999999995\n2014-02-19 18:25:00,6.627999999999999\n2014-02-19 18:30:00,5.428\n2014-02-19 18:35:00,6.046\n2014-02-19 18:40:00,5.8260000000000005\n2014-02-19 18:45:00,6.04\n2014-02-19 18:50:00,6.456\n2014-02-19 18:55:00,6.228\n2014-02-19 19:00:00,6.058\n2014-02-19 19:05:00,6.0420000000000025\n2014-02-19 19:10:00,6.224\n2014-02-19 19:15:00,6.077999999999999\n2014-02-19 19:20:00,7.272\n2014-02-19 19:25:00,6.07\n2014-02-19 19:30:00,6.05\n2014-02-19 19:35:00,6.0420000000000025\n2014-02-19 19:40:00,6.2520000000000024\n2014-02-19 19:45:00,5.8420000000000005\n2014-02-19 19:50:00,6.018\n2014-02-19 19:55:00,6.07\n2014-02-19 20:00:00,6.0420000000000025\n2014-02-19 20:05:00,6.452000000000001\n2014-02-19 20:10:00,6.867999999999999\n2014-02-19 20:15:00,5.63\n2014-02-19 20:20:00,6.474\n2014-02-19 20:25:00,5.82\n2014-02-19 20:30:00,6.062\n2014-02-19 20:35:00,5.843999999999999\n2014-02-19 20:40:00,6.3020000000000005\n2014-02-19 20:45:00,5.834\n2014-02-19 20:50:00,5.843999999999999\n2014-02-19 20:55:00,6.0420000000000025\n2014-02-19 21:00:00,6.032\n2014-02-19 21:05:00,5.816\n2014-02-19 21:10:00,6.7\n2014-02-19 21:15:00,6.644\n2014-02-19 21:20:00,6.2379999999999995\n2014-02-19 21:25:00,6.06\n2014-02-19 21:30:00,6.2520000000000024\n2014-02-19 21:35:00,6.034\n2014-02-19 21:40:00,6.2479999999999976\n2014-02-19 21:45:00,6.24\n2014-02-19 21:50:00,6.228\n2014-02-19 21:55:00,6.072\n2014-02-19 22:00:00,6.2520000000000024\n2014-02-19 22:05:00,6.0420000000000025\n2014-02-19 22:10:00,6.256\n2014-02-19 22:15:00,5.827999999999999\n2014-02-19 22:20:00,7.5020000000000024\n2014-02-19 22:25:00,6.0420000000000025\n2014-02-19 22:30:00,5.816\n2014-02-19 22:35:00,6.24\n2014-02-19 22:40:00,6.024\n2014-02-19 22:45:00,6.282\n2014-02-19 22:50:00,5.848\n2014-02-19 22:55:00,6.0360000000000005\n2014-02-19 23:00:00,6.02\n2014-02-19 23:05:00,7.086\n2014-02-19 23:10:00,6.428\n2014-02-19 23:15:00,5.856\n2014-02-19 23:20:00,5.836\n2014-02-19 23:25:00,6.222\n2014-02-19 23:30:00,6.074\n2014-02-19 23:35:00,5.834\n2014-02-19 23:40:00,5.846\n2014-02-19 23:45:00,6.046\n2014-02-19 23:50:00,6.032\n2014-02-19 23:55:00,6.416\n2014-02-20 00:00:00,6.96\n2014-02-20 00:05:00,6.627999999999999\n2014-02-20 00:10:00,6.2860000000000005\n2014-02-20 00:15:00,6.0420000000000025\n2014-02-20 00:20:00,6.047999999999999\n2014-02-20 00:25:00,6.0420000000000025\n2014-02-20 00:30:00,6.2360000000000015\n2014-02-20 00:35:00,7.3020000000000005\n2014-02-20 00:40:00,6.5020000000000024\n2014-02-20 00:45:00,5.82\n2014-02-20 00:50:00,6.058\n2014-02-20 00:55:00,6.234\n2014-02-20 01:00:00,6.032\n2014-02-20 01:05:00,5.8320000000000025\n2014-02-20 01:10:00,6.224\n2014-02-20 01:15:00,7.492000000000001\n2014-02-20 01:20:00,6.46\n2014-02-20 01:25:00,5.834\n2014-02-20 01:30:00,6.0420000000000025\n2014-02-20 01:35:00,5.604\n2014-02-20 01:40:00,6.05\n2014-02-20 01:45:00,5.8320000000000025\n2014-02-20 01:50:00,6.056\n2014-02-20 01:55:00,5.81\n2014-02-20 02:00:00,6.074\n2014-02-20 02:05:00,6.25\n2014-02-20 02:10:00,7.274\n2014-02-20 02:15:00,6.046\n2014-02-20 02:20:00,6.04\n2014-02-20 02:25:00,6.0420000000000025\n2014-02-20 02:30:00,6.46\n2014-02-20 02:35:00,5.827999999999999\n2014-02-20 02:40:00,6.016\n2014-02-20 02:45:00,6.244\n2014-02-20 02:50:00,6.03\n2014-02-20 02:55:00,6.254\n2014-02-20 03:00:00,6.246\n2014-02-20 03:05:00,7.3279999999999985\n2014-02-20 03:10:00,6.846\n2014-02-20 03:15:00,5.834\n2014-02-20 03:20:00,5.8320000000000025\n2014-02-20 03:25:00,6.018\n2014-02-20 03:30:00,6.086\n2014-02-20 03:35:00,5.827999999999999\n2014-02-20 03:40:00,6.257999999999999\n2014-02-20 03:45:00,5.837999999999999\n2014-02-20 03:50:00,6.0\n2014-02-20 03:55:00,6.066\n2014-02-20 04:00:00,6.2479999999999976\n2014-02-20 04:05:00,5.814\n2014-02-20 04:10:00,6.058\n2014-02-20 04:15:00,5.834\n2014-02-20 04:20:00,6.0120000000000005\n2014-02-20 04:25:00,5.864\n2014-02-20 04:30:00,5.843999999999999\n2014-02-20 04:35:00,5.81\n2014-02-20 04:40:00,5.854\n2014-02-20 04:45:00,6.0420000000000025\n2014-02-20 04:50:00,6.04\n2014-02-20 04:55:00,6.254\n2014-02-20 05:00:00,6.0420000000000025\n2014-02-20 05:05:00,6.0520000000000005\n2014-02-20 05:10:00,6.044\n2014-02-20 05:15:00,6.0420000000000025\n2014-02-20 05:20:00,6.204\n2014-02-20 05:25:00,5.862\n2014-02-20 05:30:00,6.044\n2014-02-20 05:35:00,5.834\n2014-02-20 05:40:00,6.0360000000000005\n2014-02-20 05:45:00,5.626\n2014-02-20 05:50:00,6.024\n2014-02-20 05:55:00,6.022\n2014-02-20 06:00:00,6.08\n2014-02-20 06:05:00,5.837999999999999\n2014-02-20 06:10:00,6.022\n2014-02-20 06:15:00,5.856\n2014-02-20 06:20:00,6.0520000000000005\n2014-02-20 06:25:00,5.83\n2014-02-20 06:30:00,6.04\n2014-02-20 06:35:00,5.81\n2014-02-20 06:40:00,6.0520000000000005\n2014-02-20 06:45:00,5.862\n2014-02-20 06:50:00,6.024\n2014-02-20 06:55:00,6.022\n2014-02-20 07:00:00,6.064\n2014-02-20 07:05:00,6.07\n2014-02-20 07:10:00,6.2520000000000024\n2014-02-20 07:15:00,6.016\n2014-02-20 07:20:00,6.27\n2014-02-20 07:25:00,6.2860000000000005\n2014-02-20 07:30:00,6.016\n2014-02-20 07:35:00,5.848\n2014-02-20 07:40:00,6.263999999999999\n2014-02-20 07:45:00,5.8320000000000025\n2014-02-20 07:50:00,6.032\n2014-02-20 07:55:00,7.077999999999999\n2014-02-20 08:00:00,6.2479999999999976\n2014-02-20 08:05:00,6.024\n2014-02-20 08:10:00,6.284\n2014-02-20 08:15:00,5.83\n2014-02-20 08:20:00,6.6679999999999975\n2014-02-20 08:25:00,6.04\n2014-02-20 08:30:00,6.044\n2014-02-20 08:35:00,6.0420000000000025\n2014-02-20 08:40:00,6.232\n2014-02-20 08:45:00,6.0420000000000025\n2014-02-20 08:50:00,6.044\n2014-02-20 08:55:00,6.254\n2014-02-20 09:00:00,6.224\n2014-02-20 09:05:00,6.064\n2014-02-20 09:10:00,6.26\n2014-02-20 09:15:00,6.018\n2014-02-20 09:20:00,6.474\n2014-02-20 09:25:00,6.246\n2014-02-20 09:30:00,6.024\n2014-02-20 09:35:00,5.837999999999999\n2014-02-20 09:40:00,6.0820000000000025\n2014-02-20 09:45:00,6.016\n2014-02-20 09:50:00,6.27\n2014-02-20 09:55:00,6.068\n2014-02-20 10:00:00,6.642\n2014-02-20 10:05:00,5.856\n2014-02-20 10:10:00,6.263999999999999\n2014-02-20 10:15:00,5.814\n2014-02-20 10:20:00,6.0820000000000025\n2014-02-20 10:25:00,5.8260000000000005\n2014-02-20 10:30:00,6.232\n2014-02-20 10:35:00,5.836\n2014-02-20 10:40:00,6.096\n2014-02-20 10:45:00,5.814\n2014-02-20 10:50:00,6.05\n2014-02-20 10:55:00,6.0420000000000025\n2014-02-20 11:00:00,5.992000000000001\n2014-02-20 11:05:00,6.478\n2014-02-20 11:10:00,6.266\n2014-02-20 11:15:00,5.834\n2014-02-20 11:20:00,6.23\n2014-02-20 11:25:00,6.05\n2014-02-20 11:30:00,6.29\n2014-02-20 11:35:00,5.834\n2014-02-20 11:40:00,6.4639999999999995\n2014-02-20 11:45:00,6.02\n2014-02-20 11:50:00,6.034\n2014-02-20 11:55:00,6.064\n2014-02-20 12:00:00,6.2479999999999976\n2014-02-20 12:05:00,5.837999999999999\n2014-02-20 12:10:00,6.846\n2014-02-20 12:15:00,5.856\n2014-02-20 12:20:00,6.016\n2014-02-20 12:25:00,6.04\n2014-02-20 12:30:00,6.046\n2014-02-20 12:35:00,6.044\n2014-02-20 12:40:00,6.047999999999999\n2014-02-20 12:45:00,6.0420000000000025\n2014-02-20 12:50:00,6.6720000000000015\n2014-02-20 12:55:00,6.0360000000000005\n2014-02-20 13:00:00,5.6339999999999995\n2014-02-20 13:05:00,6.046\n2014-02-20 13:10:00,6.2520000000000024\n2014-02-20 13:15:00,5.834\n2014-02-20 13:20:00,6.044\n2014-02-20 13:25:00,5.834\n2014-02-20 13:30:00,6.852\n2014-02-20 13:35:00,5.8260000000000005\n2014-02-20 13:40:00,6.44\n2014-02-20 13:45:00,5.636\n2014-02-20 13:50:00,6.058\n2014-02-20 13:55:00,6.246\n2014-02-20 14:00:00,7.27\n2014-02-20 14:05:00,5.83\n2014-02-20 14:10:00,6.228\n2014-02-20 14:15:00,6.0360000000000005\n2014-02-20 14:20:00,6.256\n2014-02-20 14:25:00,6.04\n2014-02-20 14:30:00,6.452000000000001\n2014-02-20 14:35:00,6.04\n2014-02-20 14:40:00,6.04\n2014-02-20 14:45:00,6.04\n2014-02-20 14:50:00,6.0420000000000025\n2014-02-20 14:55:00,6.03\n2014-02-20 15:00:00,6.2479999999999976\n2014-02-20 15:05:00,6.67\n2014-02-20 15:10:00,6.016\n2014-02-20 15:15:00,5.862\n2014-02-20 15:20:00,6.044\n2014-02-20 15:25:00,5.814\n2014-02-20 15:30:00,6.0820000000000025\n2014-02-20 15:35:00,6.05\n2014-02-20 15:40:00,6.02\n2014-02-20 15:45:00,5.848\n2014-02-20 15:50:00,5.827999999999999\n2014-02-20 15:55:00,6.0420000000000025\n2014-02-20 16:00:00,6.86\n2014-02-20 16:05:00,5.626\n2014-02-20 16:10:00,6.263999999999999\n2014-02-20 16:15:00,5.608\n2014-02-20 16:20:00,6.242000000000001\n2014-02-20 16:25:00,6.068\n2014-02-20 16:30:00,6.25\n2014-02-20 16:35:00,6.016\n2014-02-20 16:40:00,6.266\n2014-02-20 16:45:00,6.02\n2014-02-20 16:50:00,6.058\n2014-02-20 16:55:00,6.2479999999999976\n2014-02-20 17:00:00,6.044\n2014-02-20 17:05:00,6.874\n2014-02-20 17:10:00,6.232\n2014-02-20 17:15:00,5.827999999999999\n2014-02-20 17:20:00,6.256\n2014-02-20 17:25:00,6.0360000000000005\n2014-02-20 17:30:00,6.226\n2014-02-20 17:35:00,5.843999999999999\n2014-02-20 17:40:00,6.29\n2014-02-20 17:45:00,6.03\n2014-02-20 17:50:00,6.266\n2014-02-20 17:55:00,6.25\n2014-02-20 18:00:00,6.228\n2014-02-20 18:05:00,6.064\n2014-02-20 18:10:00,6.642\n2014-02-20 18:15:00,7.117999999999999\n2014-02-20 18:20:00,6.2520000000000024\n2014-02-20 18:25:00,6.046\n2014-02-20 18:30:00,6.232\n2014-02-20 18:35:00,6.074\n2014-02-20 18:40:00,6.232\n2014-02-20 18:45:00,6.077999999999999\n2014-02-20 18:50:00,6.228\n2014-02-20 18:55:00,6.046\n2014-02-20 19:00:00,6.614\n2014-02-20 19:05:00,6.694\n2014-02-20 19:10:00,6.266\n2014-02-20 19:15:00,5.837999999999999\n2014-02-20 19:20:00,6.25\n2014-02-20 19:25:00,5.816\n2014-02-20 19:30:00,6.303999999999999\n2014-02-20 19:35:00,5.834\n2014-02-20 19:40:00,6.024\n2014-02-20 19:45:00,6.06\n2014-02-20 19:50:00,5.843999999999999\n2014-02-20 19:55:00,5.827999999999999\n2014-02-20 20:00:00,6.436\n2014-02-20 20:05:00,5.837999999999999\n2014-02-20 20:10:00,6.077999999999999\n2014-02-20 20:15:00,5.834\n2014-02-20 20:20:00,7.066\n2014-02-20 20:25:00,5.856\n2014-02-20 20:30:00,6.228\n2014-02-20 20:35:00,5.636\n2014-02-20 20:40:00,6.058\n2014-02-20 20:45:00,5.834\n2014-02-20 20:50:00,5.626\n2014-02-20 20:55:00,6.034\n2014-02-20 21:00:00,6.02\n2014-02-20 21:05:00,6.046\n2014-02-20 21:10:00,7.2920000000000025\n2014-02-20 21:15:00,6.24\n2014-02-20 21:20:00,6.257999999999999\n2014-02-20 21:25:00,6.0360000000000005\n2014-02-20 21:30:00,6.02\n2014-02-20 21:35:00,6.0420000000000025\n2014-02-20 21:40:00,6.22\n2014-02-20 21:45:00,5.843999999999999\n2014-02-20 21:50:00,6.256\n2014-02-20 21:55:00,6.0420000000000025\n2014-02-20 22:00:00,7.084\n2014-02-20 22:05:00,6.257999999999999\n2014-02-20 22:10:00,6.268\n2014-02-20 22:15:00,6.026\n2014-02-20 22:20:00,5.836\n2014-02-20 22:25:00,6.0420000000000025\n2014-02-20 22:30:00,6.024\n2014-02-20 22:35:00,5.848\n2014-02-20 22:40:00,6.024\n2014-02-20 22:45:00,6.0420000000000025\n2014-02-20 22:50:00,5.836\n2014-02-20 22:55:00,6.0420000000000025\n2014-02-20 23:00:00,6.2360000000000015\n2014-02-20 23:05:00,5.856\n2014-02-20 23:10:00,7.2920000000000025\n2014-02-20 23:15:00,6.046\n2014-02-20 23:20:00,6.024\n2014-02-20 23:25:00,5.837999999999999\n2014-02-20 23:30:00,6.034\n2014-02-20 23:35:00,5.856\n2014-02-20 23:40:00,6.028\n2014-02-20 23:45:00,6.0420000000000025\n2014-02-20 23:50:00,6.024\n2014-02-20 23:55:00,6.19\n2014-02-21 00:00:00,6.152\n2014-02-21 00:05:00,5.816\n2014-02-21 00:10:00,6.077999999999999\n2014-02-21 00:15:00,7.0760000000000005\n2014-02-21 00:20:00,6.44\n2014-02-21 00:25:00,5.843999999999999\n2014-02-21 00:30:00,6.064\n2014-02-21 00:35:00,5.848\n2014-02-21 00:40:00,6.287999999999999\n2014-02-21 00:45:00,5.626\n2014-02-21 00:50:00,6.0520000000000005\n2014-02-21 00:55:00,5.8320000000000025\n2014-02-21 01:00:00,6.874\n2014-02-21 01:05:00,6.6720000000000015\n2014-02-21 01:10:00,6.4639999999999995\n2014-02-21 01:15:00,5.834\n2014-02-21 01:20:00,5.796\n2014-02-21 01:25:00,6.056\n2014-02-21 01:30:00,5.85\n2014-02-21 01:35:00,5.834\n2014-02-21 01:40:00,7.098\n2014-02-21 01:45:00,6.86\n2014-02-21 01:50:00,6.2520000000000024\n2014-02-21 01:55:00,5.8420000000000005\n2014-02-21 02:00:00,6.024\n2014-02-21 02:05:00,5.856\n2014-02-21 02:10:00,6.232\n2014-02-21 02:15:00,6.037999999999999\n2014-02-21 02:20:00,6.024\n2014-02-21 02:25:00,6.23\n2014-02-21 02:30:00,6.29\n2014-02-21 02:35:00,7.2620000000000005\n2014-02-21 02:40:00,6.246\n2014-02-21 02:45:00,5.862\n2014-02-21 02:50:00,6.0360000000000005\n2014-02-21 02:55:00,6.0420000000000025\n2014-02-21 03:00:00,6.05\n2014-02-21 03:05:00,5.83\n2014-02-21 03:10:00,7.5020000000000024\n2014-02-21 03:15:00,6.024\n2014-02-21 03:20:00,5.87\n2014-02-21 03:25:00,5.83\n2014-02-21 03:30:00,6.0420000000000025\n2014-02-21 03:35:00,5.822\n2014-02-21 03:40:00,5.7920000000000025\n2014-02-21 03:45:00,5.6579999999999995\n2014-02-21 03:50:00,6.02\n2014-02-21 03:55:00,5.824\n2014-02-21 04:00:00,5.82\n2014-02-21 04:05:00,5.83\n2014-02-21 04:10:00,6.044\n2014-02-21 04:15:00,5.608\n2014-02-21 04:20:00,6.2860000000000005\n2014-02-21 04:25:00,5.626\n2014-02-21 04:30:00,5.816\n2014-02-21 04:35:00,5.626\n2014-02-21 04:40:00,6.228\n2014-02-21 04:45:00,5.86\n2014-02-21 04:50:00,6.0\n2014-02-21 04:55:00,5.862\n2014-02-21 05:00:00,6.037999999999999\n2014-02-21 05:05:00,5.622000000000001\n2014-02-21 05:10:00,6.0420000000000025\n2014-02-21 05:15:00,5.626\n2014-02-21 05:20:00,5.834\n2014-02-21 05:25:00,6.046\n2014-02-21 05:30:00,5.822\n2014-02-21 05:35:00,5.8260000000000005\n2014-02-21 05:40:00,6.0120000000000005\n2014-02-21 05:45:00,5.654\n2014-02-21 05:50:00,6.004\n2014-02-21 05:55:00,5.862\n2014-02-21 06:00:00,6.028\n2014-02-21 06:05:00,5.834\n2014-02-21 06:10:00,6.2520000000000024\n2014-02-21 06:15:00,6.0420000000000025\n2014-02-21 06:20:00,6.044\n2014-02-21 06:25:00,6.037999999999999\n2014-02-21 06:30:00,6.03\n2014-02-21 06:35:00,5.856\n2014-02-21 06:40:00,6.028\n2014-02-21 06:45:00,5.843999999999999\n2014-02-21 06:50:00,6.058\n2014-02-21 06:55:00,5.834\n2014-02-21 07:00:00,6.2520000000000024\n2014-02-21 07:05:00,6.04\n2014-02-21 07:10:00,6.044\n2014-02-21 07:15:00,5.83\n2014-02-21 07:20:00,6.044\n2014-02-21 07:25:00,5.834\n2014-02-21 07:30:00,6.044\n2014-02-21 07:35:00,5.608\n2014-02-21 07:40:00,6.077999999999999\n2014-02-21 07:45:00,5.808\n2014-02-21 07:50:00,5.6579999999999995\n2014-02-21 07:55:00,6.874\n2014-02-21 08:00:00,6.202000000000001\n2014-02-21 08:05:00,5.86\n2014-02-21 08:10:00,6.0420000000000025\n2014-02-21 08:15:00,5.626\n2014-02-21 08:20:00,5.6320000000000014\n2014-02-21 08:25:00,6.46\n2014-02-21 08:30:00,6.0420000000000025\n2014-02-21 08:35:00,6.026\n2014-02-21 08:40:00,6.2\n2014-02-21 08:45:00,5.6579999999999995\n2014-02-21 08:50:00,5.84\n2014-02-21 08:55:00,6.044\n2014-02-21 09:00:00,6.044\n2014-02-21 09:05:00,5.622000000000001\n2014-02-21 09:10:00,6.46\n2014-02-21 09:15:00,5.624\n2014-02-21 09:20:00,6.2479999999999976\n2014-02-21 09:25:00,6.0420000000000025\n2014-02-21 09:30:00,6.26\n2014-02-21 09:35:00,6.032\n2014-02-21 09:40:00,6.04\n2014-02-21 09:45:00,5.822\n2014-02-21 09:50:00,6.2520000000000024\n2014-02-21 09:55:00,5.827999999999999\n2014-02-21 10:00:00,6.222\n2014-02-21 10:05:00,5.816\n2014-02-21 10:10:00,6.494\n2014-02-21 10:15:00,6.0420000000000025\n2014-02-21 10:20:00,6.0360000000000005\n2014-02-21 10:25:00,6.037999999999999\n2014-02-21 10:30:00,6.0\n2014-02-21 10:35:00,5.87\n2014-02-21 10:40:00,6.2520000000000024\n2014-02-21 10:45:00,5.837999999999999\n2014-02-21 10:50:00,6.044\n2014-02-21 10:55:00,5.837999999999999\n2014-02-21 11:00:00,6.257999999999999\n2014-02-21 11:05:00,6.4460000000000015\n2014-02-21 11:10:00,6.0420000000000025\n2014-02-21 11:15:00,5.834\n2014-02-21 11:20:00,6.044\n2014-02-21 11:25:00,5.834\n2014-02-21 11:30:00,6.044\n2014-02-21 11:35:00,5.822\n2014-02-21 11:40:00,6.04\n2014-02-21 11:45:00,5.834\n2014-02-21 11:50:00,6.05\n2014-02-21 11:55:00,6.03\n2014-02-21 12:00:00,6.0520000000000005\n2014-02-21 12:05:00,5.827999999999999\n2014-02-21 12:10:00,6.25\n2014-02-21 12:15:00,5.834\n2014-02-21 12:20:00,6.2379999999999995\n2014-02-21 12:25:00,6.07\n2014-02-21 12:30:00,6.436\n2014-02-21 12:35:00,6.2860000000000005\n2014-02-21 12:40:00,6.256\n2014-02-21 12:45:00,6.046\n2014-02-21 12:50:00,6.24\n2014-02-21 12:55:00,6.2520000000000024\n2014-02-21 13:00:00,6.02\n2014-02-21 13:05:00,5.8660000000000005\n2014-02-21 13:10:00,6.02\n2014-02-21 13:15:00,6.44\n2014-02-21 13:20:00,6.077999999999999\n2014-02-21 13:25:00,6.0420000000000025\n2014-02-21 13:30:00,6.26\n2014-02-21 13:35:00,6.46\n2014-02-21 13:40:00,6.228\n2014-02-21 13:45:00,5.862\n2014-02-21 13:50:00,6.016\n2014-02-21 13:55:00,6.04\n2014-02-21 14:00:00,6.6679999999999975\n2014-02-21 14:05:00,5.21\n2014-02-21 14:10:00,5.84\n2014-02-21 14:15:00,6.2520000000000024\n2014-02-21 14:20:00,5.836\n2014-02-21 14:25:00,5.814\n2014-02-21 14:30:00,5.88\n2014-02-21 14:35:00,6.666\n2014-02-21 14:40:00,5.834\n2014-02-21 14:45:00,5.606\n2014-02-21 14:50:00,6.244\n2014-02-21 14:55:00,5.622000000000001\n2014-02-21 15:00:00,6.228\n2014-02-21 15:05:00,6.46\n2014-02-21 15:10:00,6.442\n2014-02-21 15:15:00,5.626\n2014-02-21 15:20:00,6.047999999999999\n2014-02-21 15:25:00,6.0420000000000025\n2014-02-21 15:30:00,6.0420000000000025\n2014-02-21 15:35:00,5.822\n2014-02-21 15:40:00,6.2520000000000024\n2014-02-21 15:45:00,6.0420000000000025\n2014-02-21 15:50:00,6.024\n2014-02-21 15:55:00,6.04\n2014-02-21 16:00:00,6.0520000000000005\n2014-02-21 16:05:00,6.0420000000000025\n2014-02-21 16:10:00,6.6679999999999975\n2014-02-21 16:15:00,5.834\n2014-02-21 16:20:00,5.846\n2014-02-21 16:25:00,5.837999999999999\n2014-02-21 16:30:00,6.044\n2014-02-21 16:35:00,5.8320000000000025\n2014-02-21 16:40:00,6.044\n2014-02-21 16:45:00,5.608\n2014-02-21 16:50:00,6.062\n2014-02-21 16:55:00,5.862\n2014-02-21 17:00:00,5.834\n2014-02-21 17:05:00,5.834\n2014-02-21 17:10:00,6.0\n2014-02-21 17:15:00,5.652\n2014-02-21 17:20:00,6.852\n2014-02-21 17:25:00,6.05\n2014-02-21 17:30:00,5.87\n2014-02-21 17:35:00,5.814\n2014-02-21 17:40:00,5.87\n2014-02-21 17:45:00,5.803999999999999\n2014-02-21 17:50:00,6.074\n2014-02-21 17:55:00,5.8420000000000005\n2014-02-21 18:00:00,6.05\n2014-02-21 18:05:00,5.822\n2014-02-21 18:10:00,6.02\n2014-02-21 18:15:00,5.652\n2014-02-21 18:20:00,6.032\n2014-02-21 18:25:00,5.86\n2014-02-21 18:30:00,7.087999999999999\n2014-02-21 18:35:00,5.626\n2014-02-21 18:40:00,6.044\n2014-02-21 18:45:00,5.834\n2014-02-21 18:50:00,6.228\n2014-02-21 18:55:00,5.834\n2014-02-21 19:00:00,6.0420000000000025\n2014-02-21 19:05:00,6.45\n2014-02-21 19:10:00,6.876\n2014-02-21 19:15:00,6.0420000000000025\n2014-02-21 19:20:00,6.46\n2014-02-21 19:25:00,5.606\n2014-02-21 19:30:00,6.074\n2014-02-21 19:35:00,6.0420000000000025\n2014-02-21 19:40:00,6.232\n2014-02-21 19:45:00,6.028\n2014-02-21 19:50:00,6.077999999999999\n2014-02-21 19:55:00,6.037999999999999\n2014-02-21 20:00:00,7.268\n2014-02-21 20:05:00,5.8660000000000005\n2014-02-21 20:10:00,6.2520000000000024\n2014-02-21 20:15:00,5.834\n2014-02-21 20:20:00,6.04\n2014-02-21 20:25:00,6.0420000000000025\n2014-02-21 20:30:00,7.087999999999999\n2014-02-21 20:35:00,5.834\n2014-02-21 20:40:00,6.044\n2014-02-21 20:45:00,5.626\n2014-02-21 20:50:00,6.044\n2014-02-21 20:55:00,6.04\n2014-02-21 21:00:00,5.836\n2014-02-21 21:05:00,5.626\n2014-02-21 21:10:00,6.858\n2014-02-21 21:15:00,6.25\n2014-02-21 21:20:00,5.836\n2014-02-21 21:25:00,6.047999999999999\n2014-02-21 21:30:00,5.6\n2014-02-21 21:35:00,5.834\n2014-02-21 21:40:00,5.836\n2014-02-21 21:45:00,5.822\n2014-02-21 21:50:00,5.806\n2014-02-21 21:55:00,6.022\n2014-02-21 22:00:00,5.874\n2014-02-21 22:05:00,6.466\n2014-02-21 22:10:00,6.854\n2014-02-21 22:15:00,5.834\n2014-02-21 22:20:00,6.228\n2014-02-21 22:25:00,6.07\n2014-02-21 22:30:00,6.044\n2014-02-21 22:35:00,5.822\n2014-02-21 22:40:00,6.226\n2014-02-21 22:45:00,5.862\n2014-02-21 22:50:00,6.004\n2014-02-21 22:55:00,6.282\n2014-02-21 23:00:00,5.822\n2014-02-21 23:05:00,5.843999999999999\n2014-02-21 23:10:00,6.287999999999999\n2014-02-21 23:15:00,6.876\n2014-02-21 23:20:00,6.25\n2014-02-21 23:25:00,5.816\n2014-02-21 23:30:00,5.864\n2014-02-21 23:35:00,5.624\n2014-02-21 23:40:00,6.044\n2014-02-21 23:45:00,5.6160000000000005\n2014-02-21 23:50:00,6.05\n2014-02-21 23:55:00,5.77\n2014-02-22 00:00:00,6.356\n2014-02-22 00:05:00,6.876\n2014-02-22 00:10:00,6.047999999999999\n2014-02-22 00:15:00,5.816\n2014-02-22 00:20:00,5.877999999999999\n2014-02-22 00:25:00,5.622000000000001\n2014-02-22 00:30:00,6.02\n2014-02-22 00:35:00,5.626\n2014-02-22 00:40:00,6.044\n2014-02-22 00:45:00,5.808\n2014-02-22 00:50:00,6.077999999999999\n2014-02-22 00:55:00,6.026\n2014-02-22 01:00:00,6.8820000000000014\n2014-02-22 01:05:00,6.6679999999999975\n2014-02-22 01:10:00,6.21\n2014-02-22 01:15:00,6.476\n2014-02-22 01:20:00,5.87\n2014-02-22 01:25:00,6.02\n2014-02-22 01:30:00,6.29\n2014-02-22 01:35:00,5.624\n2014-02-22 01:40:00,6.224\n2014-02-22 01:45:00,5.834\n2014-02-22 01:50:00,6.044\n2014-02-22 01:55:00,5.837999999999999\n2014-02-22 02:00:00,6.232\n2014-02-22 02:05:00,5.604\n2014-02-22 02:10:00,6.068\n2014-02-22 02:15:00,6.278\n2014-02-22 02:20:00,6.876\n2014-02-22 02:25:00,5.8420000000000005\n2014-02-22 02:30:00,5.816\n2014-02-22 02:35:00,5.654\n2014-02-22 02:40:00,6.0520000000000005\n2014-02-22 02:45:00,5.82\n2014-02-22 02:50:00,5.867999999999999\n2014-02-22 02:55:00,6.0420000000000025\n2014-02-22 03:00:00,6.682\n2014-02-22 03:05:00,6.6579999999999995\n2014-02-22 03:10:00,6.02\n2014-02-22 03:15:00,5.86\n2014-02-22 03:20:00,6.04\n2014-02-22 03:25:00,6.0360000000000005\n2014-02-22 03:30:00,6.256\n2014-02-22 03:35:00,5.834\n2014-02-22 03:40:00,6.256\n2014-02-22 03:45:00,5.837999999999999\n2014-02-22 03:50:00,6.2479999999999976\n2014-02-22 03:55:00,6.04\n2014-02-22 04:00:00,6.426\n2014-02-22 04:05:00,5.827999999999999\n2014-02-22 04:10:00,6.257999999999999\n2014-02-22 04:15:00,6.018\n2014-02-22 04:20:00,6.086\n2014-02-22 04:25:00,6.04\n2014-02-22 04:30:00,6.2520000000000024\n2014-02-22 04:35:00,5.834\n2014-02-22 04:40:00,6.047999999999999\n2014-02-22 04:45:00,6.0360000000000005\n2014-02-22 04:50:00,6.047999999999999\n2014-02-22 04:55:00,6.0420000000000025\n2014-02-22 05:00:00,5.84\n2014-02-22 05:05:00,5.6160000000000005\n2014-02-22 05:10:00,6.44\n2014-02-22 05:15:00,5.862\n2014-02-22 05:20:00,6.044\n2014-02-22 05:25:00,5.814\n2014-02-22 05:30:00,6.077999999999999\n2014-02-22 05:35:00,5.614\n2014-02-22 05:40:00,6.024\n2014-02-22 05:45:00,6.07\n2014-02-22 05:50:00,5.82\n2014-02-22 05:55:00,5.8660000000000005\n2014-02-22 06:00:00,5.836\n2014-02-22 06:05:00,6.026\n2014-02-22 06:10:00,6.077999999999999\n2014-02-22 06:15:00,5.834\n2014-02-22 06:20:00,6.044\n2014-02-22 06:25:00,6.0360000000000005\n2014-02-22 06:30:00,6.8839999999999995\n2014-02-22 06:35:00,6.0420000000000025\n2014-02-22 06:40:00,6.434\n2014-02-22 06:45:00,6.074\n2014-02-22 06:50:00,6.2520000000000024\n2014-02-22 06:55:00,6.02\n2014-02-22 07:00:00,6.29\n2014-02-22 07:05:00,6.037999999999999\n2014-02-22 07:10:00,6.228\n2014-02-22 07:15:00,5.834\n2014-02-22 07:20:00,6.2479999999999976\n2014-02-22 07:25:00,6.232\n2014-02-22 07:30:00,6.058\n2014-02-22 07:35:00,5.862\n2014-02-22 07:40:00,6.04\n2014-02-22 07:45:00,5.827999999999999\n2014-02-22 07:50:00,6.044\n2014-02-22 07:55:00,6.854\n2014-02-22 08:00:00,6.287999999999999\n2014-02-22 08:05:00,6.032\n2014-02-22 08:10:00,5.604\n2014-02-22 08:15:00,6.0420000000000025\n2014-02-22 08:20:00,5.83\n2014-02-22 08:25:00,5.814\n2014-02-22 08:30:00,6.08\n2014-02-22 08:35:00,5.626\n2014-02-22 08:40:00,6.0420000000000025\n2014-02-22 08:45:00,5.624\n2014-02-22 08:50:00,6.05\n2014-02-22 08:55:00,5.837999999999999\n2014-02-22 09:00:00,6.2520000000000024\n2014-02-22 09:05:00,6.037999999999999\n2014-02-22 09:10:00,6.46\n2014-02-22 09:15:00,5.8320000000000025\n2014-02-22 09:20:00,6.2520000000000024\n2014-02-22 09:25:00,6.0420000000000025\n2014-02-22 09:30:00,6.2379999999999995\n2014-02-22 09:35:00,5.862\n2014-02-22 09:40:00,6.047999999999999\n2014-02-22 09:45:00,6.0420000000000025\n2014-02-22 09:50:00,6.044\n2014-02-22 09:55:00,5.83\n2014-02-22 10:00:00,6.232\n2014-02-22 10:05:00,5.862\n2014-02-22 10:10:00,6.652\n2014-02-22 10:15:00,5.626\n2014-02-22 10:20:00,6.05\n2014-02-22 10:25:00,5.834\n2014-02-22 10:30:00,6.02\n2014-02-22 10:35:00,5.626\n2014-02-22 10:40:00,6.09\n2014-02-22 10:45:00,5.614\n2014-02-22 10:50:00,6.044\n2014-02-22 10:55:00,6.0420000000000025\n2014-02-22 11:00:00,5.836\n2014-02-22 11:05:00,6.428\n2014-02-22 11:10:00,6.077999999999999\n2014-02-22 11:15:00,5.834\n2014-02-22 11:20:00,5.836\n2014-02-22 11:25:00,6.022\n2014-02-22 11:30:00,6.29\n2014-02-22 11:35:00,5.834\n2014-02-22 11:40:00,6.4639999999999995\n2014-02-22 11:45:00,5.837999999999999\n2014-02-22 11:50:00,6.0420000000000025\n2014-02-22 11:55:00,6.0420000000000025\n2014-02-22 12:00:00,6.044\n2014-02-22 12:05:00,6.226\n2014-02-22 12:10:00,6.474\n2014-02-22 12:15:00,5.83\n2014-02-22 12:20:00,6.022\n2014-02-22 12:25:00,5.816\n2014-02-22 12:30:00,6.0820000000000025\n2014-02-22 12:35:00,5.816\n2014-02-22 12:40:00,6.2860000000000005\n2014-02-22 12:45:00,5.827999999999999\n2014-02-22 12:50:00,5.824\n2014-02-22 12:55:00,5.862\n2014-02-22 13:00:00,6.044\n2014-02-22 13:05:00,6.254\n2014-02-22 13:10:00,6.204\n2014-02-22 13:15:00,5.654\n2014-02-22 13:20:00,5.84\n2014-02-22 13:25:00,6.018\n2014-02-22 13:30:00,6.29\n2014-02-22 13:35:00,5.834\n2014-02-22 13:40:00,6.46\n2014-02-22 13:45:00,5.834\n2014-02-22 13:50:00,6.877999999999999\n2014-02-22 13:55:00,6.037999999999999\n2014-02-22 14:00:00,5.824\n2014-02-22 14:05:00,5.83\n2014-02-22 14:10:00,6.0520000000000005\n2014-02-22 14:15:00,5.8320000000000025\n2014-02-22 14:20:00,6.8839999999999995\n2014-02-22 14:25:00,5.834\n2014-02-22 14:30:00,6.044\n2014-02-22 14:35:00,5.6\n2014-02-22 14:40:00,6.284\n2014-02-22 14:45:00,5.83\n2014-02-22 14:50:00,5.836\n2014-02-22 14:55:00,6.0420000000000025\n2014-02-22 15:00:00,5.834\n2014-02-22 15:05:00,5.822\n2014-02-22 15:10:00,6.024\n2014-02-22 15:15:00,6.694\n2014-02-22 15:20:00,6.044\n2014-02-22 15:25:00,5.827999999999999\n2014-02-22 15:30:00,6.024\n2014-02-22 15:35:00,5.4179999999999975\n2014-02-22 15:40:00,6.2520000000000024\n2014-02-22 15:45:00,6.03\n2014-02-22 15:50:00,5.834\n2014-02-22 15:55:00,5.834\n2014-02-22 16:00:00,6.044\n2014-02-22 16:05:00,6.034\n2014-02-22 16:10:00,6.864\n2014-02-22 16:15:00,6.0420000000000025\n2014-02-22 16:20:00,6.044\n2014-02-22 16:25:00,5.824\n2014-02-22 16:30:00,5.834\n2014-02-22 16:35:00,5.834\n2014-02-22 16:40:00,6.436\n2014-02-22 16:45:00,5.834\n2014-02-22 16:50:00,6.016\n2014-02-22 16:55:00,6.0420000000000025\n2014-02-22 17:00:00,6.2479999999999976\n2014-02-22 17:05:00,5.8320000000000025\n2014-02-22 17:10:00,6.228\n2014-02-22 17:15:00,5.834\n2014-02-22 17:20:00,6.648\n2014-02-22 17:25:00,6.02\n2014-02-22 17:30:00,6.062\n2014-02-22 17:35:00,5.8420000000000005\n2014-02-22 17:40:00,6.0820000000000025\n2014-02-22 17:45:00,6.026\n2014-02-22 17:50:00,5.87\n2014-02-22 17:55:00,6.25\n2014-02-22 18:00:00,6.028\n2014-02-22 18:05:00,5.626\n2014-02-22 18:10:00,6.25\n2014-02-22 18:15:00,5.83\n2014-02-22 18:20:00,5.796\n2014-02-22 18:25:00,6.494\n2014-02-22 18:30:00,6.44\n2014-02-22 18:35:00,5.654\n2014-02-22 18:40:00,6.044\n2014-02-22 18:45:00,5.834\n2014-02-22 18:50:00,5.822\n2014-02-22 18:55:00,5.862\n2014-02-22 19:00:00,6.85\n2014-02-22 19:05:00,6.024\n2014-02-22 19:10:00,6.282\n2014-02-22 19:15:00,6.0420000000000025\n2014-02-22 19:20:00,6.222\n2014-02-22 19:25:00,6.0420000000000025\n2014-02-22 19:30:00,6.044\n2014-02-22 19:35:00,6.0420000000000025\n2014-02-22 19:40:00,6.044\n2014-02-22 19:45:00,6.028\n2014-02-22 19:50:00,6.0360000000000005\n2014-02-22 19:55:00,6.037999999999999\n2014-02-22 20:00:00,6.024\n2014-02-22 20:05:00,5.862\n2014-02-22 20:10:00,6.044\n2014-02-22 20:15:00,5.834\n2014-02-22 20:20:00,6.022\n2014-02-22 20:25:00,5.806\n2014-02-22 20:30:00,6.062\n2014-02-22 20:35:00,6.0360000000000005\n2014-02-22 20:40:00,6.894\n2014-02-22 20:45:00,6.0420000000000025\n2014-02-22 20:50:00,6.028\n2014-02-22 20:55:00,5.8420000000000005\n2014-02-22 21:00:00,6.087999999999999\n2014-02-22 21:05:00,6.876\n2014-02-22 21:10:00,6.654\n2014-02-22 21:15:00,5.652\n2014-02-22 21:20:00,5.834\n2014-02-22 21:25:00,5.822\n2014-02-22 21:30:00,5.816\n2014-02-22 21:35:00,6.024\n2014-02-22 21:40:00,6.296\n2014-02-22 21:45:00,6.028\n2014-02-22 21:50:00,6.074\n2014-02-22 21:55:00,6.0360000000000005\n2014-02-22 22:00:00,6.256\n2014-02-22 22:05:00,5.827999999999999\n2014-02-22 22:10:00,6.648\n2014-02-22 22:15:00,6.6960000000000015\n2014-02-22 22:20:00,6.232\n2014-02-22 22:25:00,5.834\n2014-02-22 22:30:00,6.024\n2014-02-22 22:35:00,5.827999999999999\n2014-02-22 22:40:00,6.25\n2014-02-22 22:45:00,5.626\n2014-02-22 22:50:00,6.03\n2014-02-22 22:55:00,6.064\n2014-02-22 23:00:00,5.816\n2014-02-22 23:05:00,5.872000000000001\n2014-02-22 23:10:00,6.016\n2014-02-22 23:15:00,5.834\n2014-02-22 23:20:00,6.47\n2014-02-22 23:25:00,6.6679999999999975\n2014-02-22 23:30:00,5.836\n2014-02-22 23:35:00,5.834\n2014-02-22 23:40:00,5.803999999999999\n2014-02-22 23:45:00,5.843999999999999\n2014-02-22 23:50:00,6.077999999999999\n2014-02-22 23:55:00,5.774\n2014-02-23 00:00:00,6.162000000000001\n2014-02-23 00:05:00,5.83\n2014-02-23 00:10:00,6.256\n2014-02-23 00:15:00,6.0360000000000005\n2014-02-23 00:20:00,6.644\n2014-02-23 00:25:00,6.904\n2014-02-23 00:30:00,6.018\n2014-02-23 00:35:00,5.822\n2014-02-23 00:40:00,7.916\n2014-02-23 00:45:00,5.83\n2014-02-23 00:50:00,6.044\n2014-02-23 00:55:00,5.834\n2014-02-23 01:00:00,5.836\n2014-02-23 01:05:00,5.834\n2014-02-23 01:10:00,6.46\n2014-02-23 01:15:00,5.612\n2014-02-23 01:20:00,5.88\n2014-02-23 01:25:00,6.0360000000000005\n2014-02-23 01:30:00,6.2520000000000024\n2014-02-23 01:35:00,6.642\n2014-02-23 01:40:00,7.102\n2014-02-23 01:45:00,5.862\n2014-02-23 01:50:00,6.004\n2014-02-23 01:55:00,6.05\n2014-02-23 02:00:00,6.2620000000000005\n2014-02-23 02:05:00,5.827999999999999\n2014-02-23 02:10:00,6.263999999999999\n2014-02-23 02:15:00,7.0820000000000025\n2014-02-23 02:20:00,6.25\n2014-02-23 02:25:00,5.834\n2014-02-23 02:30:00,6.0420000000000025\n2014-02-23 02:35:00,5.822\n2014-02-23 02:40:00,6.024\n2014-02-23 02:45:00,5.626\n2014-02-23 02:50:00,6.0020000000000024\n2014-02-23 02:55:00,5.862\n2014-02-23 03:00:00,5.62\n2014-02-23 03:05:00,5.6320000000000014\n2014-02-23 03:10:00,7.087999999999999\n2014-02-23 03:15:00,6.442\n2014-02-23 03:20:00,5.87\n2014-02-23 03:25:00,5.827999999999999\n2014-02-23 03:30:00,5.836\n2014-02-23 03:35:00,5.626\n2014-02-23 03:40:00,6.2520000000000024\n2014-02-23 03:45:00,5.626\n2014-02-23 03:50:00,5.836\n2014-02-23 03:55:00,5.822\n2014-02-23 04:00:00,6.64\n2014-02-23 04:05:00,5.606\n2014-02-23 04:10:00,6.294\n2014-02-23 04:15:00,6.0360000000000005\n2014-02-23 04:20:00,6.228\n2014-02-23 04:25:00,6.0420000000000025\n2014-02-23 04:30:00,6.2520000000000024\n2014-02-23 04:35:00,5.834\n2014-02-23 04:40:00,6.2520000000000024\n2014-02-23 04:45:00,5.82\n2014-02-23 04:50:00,6.058\n2014-02-23 04:55:00,6.066\n2014-02-23 05:00:00,6.232\n2014-02-23 05:05:00,5.862\n2014-02-23 05:10:00,6.028\n2014-02-23 05:15:00,5.862\n2014-02-23 05:20:00,6.024\n2014-02-23 05:25:00,5.6579999999999995\n2014-02-23 05:30:00,6.232\n2014-02-23 05:35:00,5.204\n2014-02-23 05:40:00,6.4579999999999975\n2014-02-23 05:45:00,5.834\n2014-02-23 05:50:00,5.836\n2014-02-23 05:55:00,6.0420000000000025\n2014-02-23 06:00:00,6.024\n2014-02-23 06:05:00,5.862\n2014-02-23 06:10:00,6.0420000000000025\n2014-02-23 06:15:00,5.626\n2014-02-23 06:20:00,5.794\n2014-02-23 06:25:00,5.8660000000000005\n2014-02-23 06:30:00,6.2520000000000024\n2014-02-23 06:35:00,6.026\n2014-02-23 06:40:00,6.2860000000000005\n2014-02-23 06:45:00,5.834\n2014-02-23 06:50:00,6.044\n2014-02-23 06:55:00,6.05\n2014-02-23 07:00:00,6.204\n2014-02-23 07:05:00,5.848\n2014-02-23 07:10:00,5.867999999999999\n2014-02-23 07:15:00,6.0360000000000005\n2014-02-23 07:20:00,6.046\n2014-02-23 07:25:00,5.808\n2014-02-23 07:30:00,6.046\n2014-02-23 07:35:00,5.65\n2014-02-23 07:40:00,6.25\n2014-02-23 07:45:00,6.016\n2014-02-23 07:50:00,6.077999999999999\n2014-02-23 07:55:00,7.074\n2014-02-23 08:00:00,6.2520000000000024\n2014-02-23 08:05:00,5.614\n2014-02-23 08:10:00,6.44\n2014-02-23 08:15:00,5.862\n2014-02-23 08:20:00,6.044\n2014-02-23 08:25:00,6.024\n2014-02-23 08:30:00,6.058\n2014-02-23 08:35:00,5.834\n2014-02-23 08:40:00,6.0520000000000005\n2014-02-23 08:45:00,5.834\n2014-02-23 08:50:00,6.03\n2014-02-23 08:55:00,6.0420000000000025\n2014-02-23 09:00:00,6.2520000000000024\n2014-02-23 09:05:00,5.827999999999999\n2014-02-23 09:10:00,6.044\n2014-02-23 09:15:00,5.61\n2014-02-23 09:20:00,6.02\n2014-02-23 09:25:00,5.614\n2014-02-23 09:30:00,5.836\n2014-02-23 09:35:00,5.827999999999999\n2014-02-23 09:40:00,6.044\n2014-02-23 09:45:00,5.414\n2014-02-23 09:50:00,6.25\n2014-02-23 09:55:00,6.0420000000000025\n2014-02-23 10:00:00,6.044\n2014-02-23 10:05:00,5.626\n2014-02-23 10:10:00,6.256\n2014-02-23 10:15:00,6.034\n2014-02-23 10:20:00,6.044\n2014-02-23 10:25:00,6.44\n2014-02-23 10:30:00,6.062\n2014-02-23 10:35:00,6.074\n2014-02-23 10:40:00,6.062\n2014-02-23 10:45:00,5.62\n2014-02-23 10:50:00,6.044\n2014-02-23 10:55:00,6.032\n2014-02-23 11:00:00,5.834\n2014-02-23 11:05:00,6.0420000000000025\n2014-02-23 11:10:00,6.6679999999999975\n2014-02-23 11:15:00,5.83\n2014-02-23 11:20:00,5.846\n2014-02-23 11:25:00,6.022\n2014-02-23 11:30:00,5.867999999999999\n2014-02-23 11:35:00,5.82\n2014-02-23 11:40:00,5.867999999999999\n2014-02-23 11:45:00,5.8260000000000005\n2014-02-23 11:50:00,6.044\n2014-02-23 11:55:00,5.834\n2014-02-23 12:00:00,6.044\n2014-02-23 12:05:00,5.834\n2014-02-23 12:10:00,6.026\n2014-02-23 12:15:00,6.25\n2014-02-23 12:20:00,5.843999999999999\n2014-02-23 12:25:00,5.82\n2014-02-23 12:30:00,6.0520000000000005\n2014-02-23 12:35:00,5.6320000000000014\n2014-02-23 12:40:00,6.0760000000000005\n2014-02-23 12:45:00,5.83\n2014-02-23 12:50:00,6.05\n2014-02-23 12:55:00,6.0420000000000025\n2014-02-23 13:00:00,5.816\n2014-02-23 13:05:00,6.037999999999999\n2014-02-23 13:10:00,6.87\n2014-02-23 13:15:00,5.2120000000000015\n2014-02-23 13:20:00,6.05\n2014-02-23 13:25:00,5.83\n2014-02-23 13:30:00,6.0360000000000005\n2014-02-23 13:35:00,5.834\n2014-02-23 13:40:00,6.25\n2014-02-23 13:45:00,5.837999999999999\n2014-02-23 13:50:00,6.2520000000000024\n2014-02-23 13:55:00,6.016\n2014-02-23 14:00:00,6.0820000000000025\n2014-02-23 14:05:00,5.834\n2014-02-23 14:10:00,6.044\n2014-02-23 14:15:00,6.2520000000000024\n2014-02-23 14:20:00,6.0520000000000005\n2014-02-23 14:25:00,6.662000000000001\n2014-02-23 14:30:00,6.2479999999999976\n2014-02-23 14:35:00,6.0360000000000005\n2014-02-23 14:40:00,6.6579999999999995\n2014-02-23 14:45:00,5.228\n2014-02-23 14:50:00,5.796\n2014-02-23 14:55:00,6.05\n2014-02-23 15:00:00,6.266\n2014-02-23 15:05:00,6.274\n2014-02-23 15:10:00,6.256\n2014-02-23 15:15:00,5.816\n2014-02-23 15:20:00,6.058\n2014-02-23 15:25:00,5.654\n2014-02-23 15:30:00,6.226\n2014-02-23 15:35:00,5.624\n2014-02-23 15:40:00,6.022\n2014-02-23 15:45:00,5.8660000000000005\n2014-02-23 15:50:00,5.814\n2014-02-23 15:55:00,5.62\n2014-02-23 16:00:00,6.2479999999999976\n2014-02-23 16:05:00,5.816\n2014-02-23 16:10:00,6.3020000000000005\n2014-02-23 16:15:00,5.834\n2014-02-23 16:20:00,6.0420000000000025\n2014-02-23 16:25:00,6.664\n2014-02-23 16:30:00,6.056\n2014-02-23 16:35:00,5.626\n2014-02-23 16:40:00,5.824\n2014-02-23 16:45:00,6.024\n2014-02-23 16:50:00,6.062\n2014-02-23 16:55:00,6.07\n2014-02-23 17:00:00,6.2520000000000024\n2014-02-23 17:05:00,6.44\n2014-02-23 17:10:00,5.6160000000000005\n2014-02-23 17:15:00,6.053999999999999\n2014-02-23 17:20:00,7.102\n2014-02-23 17:25:00,6.046\n2014-02-23 17:30:00,6.044\n2014-02-23 17:35:00,5.834\n2014-02-23 17:40:00,6.23\n2014-02-23 17:45:00,5.827999999999999\n2014-02-23 17:50:00,6.2520000000000024\n2014-02-23 17:55:00,6.0420000000000025\n2014-02-23 18:00:00,6.2360000000000015\n2014-02-23 18:05:00,6.912000000000001\n2014-02-23 18:10:00,6.46\n2014-02-23 18:15:00,5.834\n2014-02-23 18:20:00,6.23\n2014-02-23 18:25:00,6.0420000000000025\n2014-02-23 18:30:00,6.0420000000000025\n2014-02-23 18:35:00,5.8260000000000005\n2014-02-23 18:40:00,6.644\n2014-02-23 18:45:00,5.862\n2014-02-23 18:50:00,6.8420000000000005\n2014-02-23 18:55:00,5.834\n2014-02-23 19:00:00,6.46\n2014-02-23 19:05:00,5.8260000000000005\n2014-02-23 19:10:00,6.23\n2014-02-23 19:15:00,6.05\n2014-02-23 19:20:00,7.3420000000000005\n2014-02-23 19:25:00,5.626\n2014-02-23 19:30:00,6.024\n2014-02-23 19:35:00,5.822\n2014-02-23 19:40:00,6.03\n2014-02-23 19:45:00,5.83\n2014-02-23 19:50:00,6.242000000000001\n2014-02-23 19:55:00,6.064\n2014-02-23 20:00:00,6.053999999999999\n2014-02-23 20:05:00,5.834\n2014-02-23 20:10:00,6.232\n2014-02-23 20:15:00,5.6160000000000005\n2014-02-23 20:20:00,5.836\n2014-02-23 20:25:00,7.087999999999999\n2014-02-23 20:30:00,5.836\n2014-02-23 20:35:00,5.803999999999999\n2014-02-23 20:40:00,6.077999999999999\n2014-02-23 20:45:00,5.606\n2014-02-23 20:50:00,6.074\n2014-02-23 20:55:00,5.624\n2014-02-23 21:00:00,6.25\n2014-02-23 21:05:00,5.816\n2014-02-23 21:10:00,5.864\n2014-02-23 21:15:00,5.82\n2014-02-23 21:20:00,5.6560000000000015\n2014-02-23 21:25:00,5.827999999999999\n2014-02-23 21:30:00,6.0020000000000024\n2014-02-23 21:35:00,6.282\n2014-02-23 21:40:00,7.07\n2014-02-23 21:45:00,6.074\n2014-02-23 21:50:00,6.024\n2014-02-23 21:55:00,6.07\n2014-02-23 22:00:00,6.2520000000000024\n2014-02-23 22:05:00,6.454\n2014-02-23 22:10:00,5.626\n2014-02-23 22:15:00,5.834\n2014-02-23 22:20:00,6.676\n2014-02-23 22:25:00,6.46\n2014-02-23 22:30:00,6.044\n2014-02-23 22:35:00,5.834\n2014-02-23 22:40:00,6.257999999999999\n2014-02-23 22:45:00,5.834\n2014-02-23 22:50:00,5.836\n2014-02-23 22:55:00,6.0120000000000005\n2014-02-23 23:00:00,6.468\n2014-02-23 23:05:00,6.902\n2014-02-23 23:10:00,6.0420000000000025\n2014-02-23 23:15:00,5.822\n2014-02-23 23:20:00,5.824\n2014-02-23 23:25:00,5.8660000000000005\n2014-02-23 23:30:00,6.024\n2014-02-23 23:35:00,6.25\n2014-02-23 23:40:00,5.617999999999999\n2014-02-23 23:45:00,5.626\n2014-02-23 23:50:00,6.256\n2014-02-23 23:55:00,5.774\n2014-02-24 00:00:00,6.1560000000000015\n2014-02-24 00:05:00,6.037999999999999\n2014-02-24 00:10:00,6.047999999999999\n2014-02-24 00:15:00,5.834\n2014-02-24 00:20:00,6.886\n2014-02-24 00:25:00,6.65\n2014-02-24 00:30:00,6.2520000000000024\n2014-02-24 00:35:00,5.803999999999999\n2014-02-24 00:40:00,6.263999999999999\n2014-02-24 00:45:00,5.827999999999999\n2014-02-24 00:50:00,6.2520000000000024\n2014-02-24 00:55:00,6.25\n2014-02-24 01:00:00,6.02\n2014-02-24 01:05:00,5.827999999999999\n2014-02-24 01:10:00,6.6679999999999975\n2014-02-24 01:15:00,5.834\n2014-02-24 01:20:00,6.2520000000000024\n2014-02-24 01:25:00,6.87\n2014-02-24 01:30:00,6.4639999999999995\n2014-02-24 01:35:00,5.622000000000001\n2014-02-24 01:40:00,6.2520000000000024\n2014-02-24 01:45:00,5.818\n2014-02-24 01:50:00,6.058\n2014-02-24 01:55:00,6.0420000000000025\n2014-02-24 02:00:00,6.044\n2014-02-24 02:05:00,5.827999999999999\n2014-02-24 02:10:00,6.02\n2014-02-24 02:15:00,6.466\n2014-02-24 02:20:00,6.706\n2014-02-24 02:25:00,6.0420000000000025\n2014-02-24 02:30:00,5.836\n2014-02-24 02:35:00,5.814\n2014-02-24 02:40:00,5.87\n2014-02-24 02:45:00,5.827999999999999\n2014-02-24 02:50:00,5.836\n2014-02-24 02:55:00,5.837999999999999\n2014-02-24 03:00:00,6.89\n2014-02-24 03:05:00,6.877999999999999\n2014-02-24 03:10:00,6.25\n2014-02-24 03:15:00,6.0420000000000025\n2014-02-24 03:20:00,5.836\n2014-02-24 03:25:00,5.827999999999999\n2014-02-24 03:30:00,5.836\n2014-02-24 03:35:00,5.834\n2014-02-24 03:40:00,5.787999999999999\n2014-02-24 03:45:00,5.654\n2014-02-24 03:50:00,6.01\n2014-02-24 03:55:00,5.862\n2014-02-24 04:00:00,5.834\n2014-02-24 04:05:00,5.806\n2014-02-24 04:10:00,5.87\n2014-02-24 04:15:00,5.614\n2014-02-24 04:20:00,6.044\n2014-02-24 04:25:00,5.626\n2014-02-24 04:30:00,5.84\n2014-02-24 04:35:00,5.837999999999999\n2014-02-24 04:40:00,6.044\n2014-02-24 04:45:00,5.596\n2014-02-24 04:50:00,5.867999999999999\n2014-02-24 04:55:00,6.0420000000000025\n2014-02-24 05:00:00,5.808\n2014-02-24 05:05:00,5.617999999999999\n2014-02-24 05:10:00,5.843999999999999\n2014-02-24 05:15:00,5.606\n2014-02-24 05:20:00,6.694\n2014-02-24 05:25:00,5.843999999999999\n2014-02-24 05:30:00,6.0820000000000025\n2014-02-24 05:35:00,5.834\n2014-02-24 05:40:00,6.03\n2014-02-24 05:45:00,5.834\n2014-02-24 05:50:00,5.8320000000000025\n2014-02-24 05:55:00,5.816\n2014-02-24 06:00:00,5.862\n2014-02-24 06:05:00,5.834\n2014-02-24 06:10:00,6.047999999999999\n2014-02-24 06:15:00,5.816\n2014-02-24 06:20:00,5.87\n2014-02-24 06:25:00,5.834\n2014-02-24 06:30:00,6.0520000000000005\n2014-02-24 06:35:00,5.622000000000001\n2014-02-24 06:40:00,6.256\n2014-02-24 06:45:00,5.626\n2014-02-24 06:50:00,6.2520000000000024\n2014-02-24 06:55:00,6.034\n2014-02-24 07:00:00,6.024\n2014-02-24 07:05:00,5.862\n2014-02-24 07:10:00,6.4579999999999975\n2014-02-24 07:15:00,5.827999999999999\n2014-02-24 07:20:00,6.0420000000000025\n2014-02-24 07:25:00,5.834\n2014-02-24 07:30:00,6.438\n2014-02-24 07:35:00,6.0420000000000025\n2014-02-24 07:40:00,6.047999999999999\n2014-02-24 07:45:00,6.034\n2014-02-24 07:50:00,6.2520000000000024\n2014-02-24 07:55:00,7.29\n2014-02-24 08:00:00,6.226\n2014-02-24 08:05:00,5.862\n2014-02-24 08:10:00,6.4479999999999995\n2014-02-24 08:15:00,6.074\n2014-02-24 08:20:00,6.028\n2014-02-24 08:25:00,6.01\n2014-02-24 08:30:00,5.864\n2014-02-24 08:35:00,5.837999999999999\n2014-02-24 08:40:00,6.047999999999999\n2014-02-24 08:45:00,5.816\n2014-02-24 08:50:00,5.874\n2014-02-24 08:55:00,6.0420000000000025\n2014-02-24 09:00:00,6.02\n2014-02-24 09:05:00,5.816\n2014-02-24 09:10:00,6.077999999999999\n2014-02-24 09:15:00,6.0420000000000025\n2014-02-24 09:20:00,6.028\n2014-02-24 09:25:00,5.626\n2014-02-24 09:30:00,6.244\n2014-02-24 09:35:00,5.62\n2014-02-24 09:40:00,6.044\n2014-02-24 09:45:00,5.834\n2014-02-24 09:50:00,5.808\n2014-02-24 09:55:00,6.07\n2014-02-24 10:00:00,5.836\n2014-02-24 10:05:00,5.834\n2014-02-24 10:10:00,6.024\n2014-02-24 10:15:00,6.226\n2014-02-24 10:20:00,5.85\n2014-02-24 10:25:00,5.843999999999999\n2014-02-24 10:30:00,6.287999999999999\n2014-02-24 10:35:00,5.837999999999999\n2014-02-24 10:40:00,6.056\n2014-02-24 10:45:00,5.624\n2014-02-24 10:50:00,6.024\n2014-02-24 10:55:00,5.86\n2014-02-24 11:00:00,6.044\n2014-02-24 11:05:00,5.624\n2014-02-24 11:10:00,6.02\n2014-02-24 11:15:00,6.056\n2014-02-24 11:20:00,6.2860000000000005\n2014-02-24 11:25:00,6.0420000000000025\n2014-02-24 11:30:00,6.6339999999999995\n2014-02-24 11:35:00,6.074\n2014-02-24 11:40:00,6.024\n2014-02-24 11:45:00,5.65\n2014-02-24 11:50:00,6.226\n2014-02-24 11:55:00,6.0420000000000025\n2014-02-24 12:00:00,6.0420000000000025\n2014-02-24 12:05:00,6.874\n2014-02-24 12:10:00,5.602\n2014-02-24 12:15:00,5.862\n2014-02-24 12:20:00,6.044\n2014-02-24 12:25:00,5.83\n2014-02-24 12:30:00,6.0360000000000005\n2014-02-24 12:35:00,5.834\n2014-02-24 12:40:00,6.226\n2014-02-24 12:45:00,6.474\n2014-02-24 12:50:00,6.018\n2014-02-24 12:55:00,5.862\n2014-02-24 13:00:00,6.04\n2014-02-24 13:05:00,6.454\n2014-02-24 13:10:00,5.394\n2014-02-24 13:15:00,5.862\n2014-02-24 13:20:00,5.836\n2014-02-24 13:25:00,6.6679999999999975\n2014-02-24 13:30:00,6.0420000000000025\n2014-02-24 13:35:00,5.622000000000001\n2014-02-24 13:40:00,6.2520000000000024\n2014-02-24 13:45:00,5.614\n2014-02-24 13:50:00,6.2120000000000015\n2014-02-24 13:55:00,6.06\n2014-02-24 14:00:00,6.2520000000000024\n2014-02-24 14:05:00,5.816\n2014-02-24 14:10:00,6.702000000000001\n2014-02-24 14:15:00,6.47\n2014-02-24 14:20:00,5.837999999999999\n2014-02-24 14:25:00,6.0420000000000025\n2014-02-24 14:30:00,6.23\n2014-02-24 14:35:00,5.83\n2014-02-24 14:40:00,6.2520000000000024\n2014-02-24 14:45:00,5.834\n2014-02-24 14:50:00,6.224\n2014-02-24 14:55:00,5.816\n2014-02-24 15:00:00,6.2379999999999995\n2014-02-24 15:05:00,5.648\n2014-02-24 15:10:00,6.234\n2014-02-24 15:15:00,5.856\n2014-02-24 15:20:00,5.836\n2014-02-24 15:25:00,5.61\n2014-02-24 15:30:00,6.232\n2014-02-24 15:35:00,5.848\n2014-02-24 15:40:00,6.92\n2014-02-24 15:45:00,5.6\n2014-02-24 15:50:00,5.87\n2014-02-24 15:55:00,5.626\n2014-02-24 16:00:00,6.044\n2014-02-24 16:05:00,5.834\n2014-02-24 16:10:00,6.88\n2014-02-24 16:15:00,5.81\n2014-02-24 16:20:00,5.872000000000001\n2014-02-24 16:25:00,5.837999999999999\n2014-02-24 16:30:00,6.016\n2014-02-24 16:35:00,5.814\n2014-02-24 16:40:00,6.074\n2014-02-24 16:45:00,5.414\n2014-02-24 16:50:00,6.232\n2014-02-24 16:55:00,6.074\n2014-02-24 17:00:00,6.0420000000000025\n2014-02-24 17:05:00,6.876\n2014-02-24 17:10:00,6.436\n2014-02-24 17:15:00,5.803999999999999\n2014-02-24 17:20:00,6.037999999999999\n2014-02-24 17:25:00,5.6579999999999995\n2014-02-24 17:30:00,6.2520000000000024\n2014-02-24 17:35:00,5.4179999999999975\n2014-02-24 17:40:00,6.2479999999999976\n2014-02-24 17:45:00,5.834\n2014-02-24 17:50:00,6.026\n2014-02-24 17:55:00,6.0420000000000025\n2014-02-24 18:00:00,6.044\n2014-02-24 18:05:00,6.032\n2014-02-24 18:10:00,7.044\n2014-02-24 18:15:00,5.8660000000000005\n2014-02-24 18:20:00,6.864\n2014-02-24 18:25:00,5.218\n2014-02-24 18:30:00,5.796\n2014-02-24 18:35:00,5.843999999999999\n2014-02-24 18:40:00,6.29\n2014-02-24 18:45:00,5.834\n2014-02-24 18:50:00,5.8420000000000005\n2014-02-24 18:55:00,6.0420000000000025\n2014-02-24 19:00:00,5.836\n2014-02-24 19:05:00,5.816\n2014-02-24 19:10:00,6.07\n2014-02-24 19:15:00,5.626\n2014-02-24 19:20:00,6.053999999999999\n2014-02-24 19:25:00,5.808\n2014-02-24 19:30:00,6.91\n2014-02-24 19:35:00,6.0420000000000025\n2014-02-24 19:40:00,6.047999999999999\n2014-02-24 19:45:00,5.822\n2014-02-24 19:50:00,5.816\n2014-02-24 19:55:00,5.4179999999999975\n2014-02-24 20:00:00,6.666\n2014-02-24 20:05:00,6.872000000000001\n2014-02-24 20:10:00,6.047999999999999\n2014-02-24 20:15:00,5.818\n2014-02-24 20:20:00,6.2860000000000005\n2014-02-24 20:25:00,6.022\n2014-02-24 20:30:00,6.08\n2014-02-24 20:35:00,5.816\n2014-02-24 20:40:00,6.294\n2014-02-24 20:45:00,5.822\n2014-02-24 20:50:00,6.05\n2014-02-24 20:55:00,6.0360000000000005\n2014-02-24 21:00:00,6.46\n2014-02-24 21:05:00,6.454\n2014-02-24 21:10:00,6.037999999999999\n2014-02-24 21:15:00,5.816\n2014-02-24 21:20:00,6.09\n2014-02-24 21:25:00,6.0420000000000025\n2014-02-24 21:30:00,5.812\n2014-02-24 21:35:00,6.044\n2014-02-24 21:40:00,6.2479999999999976\n2014-02-24 21:45:00,6.016\n2014-02-24 21:50:00,6.257999999999999\n2014-02-24 21:55:00,6.068\n2014-02-24 22:00:00,5.836\n2014-02-24 22:05:00,7.3\n2014-02-24 22:10:00,6.228\n2014-02-24 22:15:00,5.836\n2014-02-24 22:20:00,6.024\n2014-02-24 22:25:00,5.8660000000000005\n2014-02-24 22:30:00,6.228\n2014-02-24 22:35:00,5.66\n2014-02-24 22:40:00,5.996\n2014-02-24 22:45:00,5.862\n2014-02-24 22:50:00,6.024\n2014-02-24 22:55:00,5.848\n2014-02-24 23:00:00,6.2920000000000025\n2014-02-24 23:05:00,6.88\n2014-02-24 23:10:00,6.046\n2014-02-24 23:15:00,5.626\n2014-02-24 23:20:00,5.8420000000000005\n2014-02-24 23:25:00,6.0360000000000005\n2014-02-24 23:30:00,5.836\n2014-02-24 23:35:00,5.614\n2014-02-24 23:40:00,6.876\n2014-02-24 23:45:00,6.46\n2014-02-24 23:50:00,5.836\n2014-02-24 23:55:00,5.756\n2014-02-25 00:00:00,6.192\n2014-02-25 00:05:00,6.0420000000000025\n2014-02-25 00:10:00,7.474\n2014-02-25 00:15:00,5.834\n2014-02-25 00:20:00,6.006\n2014-02-25 00:25:00,6.0520000000000005\n2014-02-25 00:30:00,6.077999999999999\n2014-02-25 00:35:00,5.834\n2014-02-25 00:40:00,5.818\n2014-02-25 00:45:00,6.022\n2014-02-25 00:50:00,6.053999999999999\n2014-02-25 00:55:00,5.444\n2014-02-25 01:00:00,6.2520000000000024\n2014-02-25 01:05:00,5.604\n2014-02-25 01:10:00,6.914\n2014-02-25 01:15:00,6.867999999999999\n2014-02-25 01:20:00,5.812\n2014-02-25 01:25:00,5.824\n2014-02-25 01:30:00,6.224\n2014-02-25 01:35:00,5.83\n2014-02-25 01:40:00,6.2520000000000024\n2014-02-25 01:45:00,6.022\n2014-02-25 01:50:00,6.077999999999999\n2014-02-25 01:55:00,5.837999999999999\n2014-02-25 02:00:00,6.226\n2014-02-25 02:05:00,5.8320000000000025\n2014-02-25 02:10:00,6.612\n2014-02-25 02:15:00,7.108\n2014-02-25 02:20:00,6.018\n2014-02-25 02:25:00,6.0360000000000005\n2014-02-25 02:30:00,6.024\n2014-02-25 02:35:00,5.608\n2014-02-25 02:40:00,6.062\n2014-02-25 02:45:00,5.834\n2014-02-25 02:50:00,5.8320000000000025\n2014-02-25 02:55:00,6.0360000000000005\n2014-02-25 03:00:00,6.028\n2014-02-25 03:05:00,5.8420000000000005\n2014-02-25 03:10:00,7.2860000000000005\n2014-02-25 03:15:00,5.834\n2014-02-25 03:20:00,6.016\n2014-02-25 03:25:00,5.4179999999999975\n2014-02-25 03:30:00,6.256\n2014-02-25 03:35:00,5.827999999999999\n2014-02-25 03:40:00,5.834\n2014-02-25 03:45:00,5.827999999999999\n2014-02-25 03:50:00,5.822\n2014-02-25 03:55:00,6.034\n2014-02-25 04:00:00,6.26\n2014-02-25 04:05:00,5.834\n2014-02-25 04:10:00,6.044\n2014-02-25 04:15:00,6.0360000000000005\n2014-02-25 04:20:00,6.022\n2014-02-25 04:25:00,6.077999999999999\n2014-02-25 04:30:00,5.836\n2014-02-25 04:35:00,6.0420000000000025\n2014-02-25 04:40:00,6.024\n2014-02-25 04:45:00,5.816\n2014-02-25 04:50:00,6.087999999999999\n2014-02-25 04:55:00,5.63\n2014-02-25 05:00:00,6.018\n2014-02-25 05:05:00,5.8260000000000005\n2014-02-25 05:10:00,5.814\n2014-02-25 05:15:00,6.2379999999999995\n2014-02-25 05:20:00,5.627999999999999\n2014-02-25 05:25:00,6.026\n2014-02-25 05:30:00,6.044\n2014-02-25 05:35:00,5.626\n2014-02-25 05:40:00,6.046\n2014-02-25 05:45:00,5.827999999999999\n2014-02-25 05:50:00,5.816\n2014-02-25 05:55:00,6.07\n2014-02-25 06:00:00,5.836\n2014-02-25 06:05:00,5.834\n2014-02-25 06:10:00,6.0420000000000025\n2014-02-25 06:15:00,5.626\n2014-02-25 06:20:00,6.044\n2014-02-25 06:25:00,6.0420000000000025\n2014-02-25 06:30:00,6.044\n2014-02-25 06:35:00,5.626\n2014-02-25 06:40:00,6.016\n2014-02-25 06:45:00,5.626\n2014-02-25 06:50:00,5.87\n2014-02-25 06:55:00,6.0420000000000025\n2014-02-25 07:00:00,6.4639999999999995\n2014-02-25 07:05:00,6.0360000000000005\n2014-02-25 07:15:00,25.1033\n2014-02-25 07:20:00,17.186\n2014-02-25 07:25:00,14.452\n2014-02-25 07:30:00,13.968\n2014-02-25 07:35:00,13.352\n2014-02-25 07:40:00,15.6433\n2014-02-25 07:45:00,14.4533\n2014-02-25 07:50:00,15.42\n2014-02-25 07:55:00,18.3333\n2014-02-25 08:00:00,16.19\n2014-02-25 08:05:00,15.0\n2014-02-25 08:10:00,15.07\n2014-02-25 08:15:00,15.0\n2014-02-25 08:20:00,15.0867\n2014-02-25 08:25:00,13.9333\n2014-02-25 08:30:00,15.0033\n2014-02-25 08:35:00,14.4533\n2014-02-25 08:40:00,15.0\n2014-02-25 08:45:00,13.9067\n2014-02-25 08:50:00,15.1433\n2014-02-25 08:55:00,14.4433\n2014-02-25 09:00:00,15.5567\n2014-02-25 09:05:00,14.4433\n2014-02-25 09:10:00,15.55\n2014-02-25 09:15:00,14.4733\n2014-02-25 09:20:00,14.8833\n2014-02-25 09:25:00,13.9333\n2014-02-25 09:30:00,16.1133\n2014-02-25 09:35:00,13.8867\n2014-02-25 09:40:00,15.0\n2014-02-25 09:45:00,13.27\n2014-02-25 09:50:00,15.5567\n2014-02-25 09:55:00,14.4433\n2014-02-25 10:00:00,15.0\n2014-02-25 10:05:00,13.8867\n2014-02-25 10:10:00,15.0\n2014-02-25 10:15:00,14.4733\n2014-02-25 10:20:00,15.5567\n2014-02-25 10:25:00,14.4433\n2014-02-25 10:30:00,15.0\n2014-02-25 10:35:00,14.3567\n2014-02-25 10:40:00,15.5567\n2014-02-25 10:45:00,14.4433\n2014-02-25 10:50:00,15.5567\n2014-02-25 10:55:00,14.5\n2014-02-25 11:00:00,15.0\n2014-02-25 11:05:00,14.4733\n2014-02-25 11:10:00,16.11\n2014-02-25 11:15:00,14.4833\n2014-02-25 11:20:00,12.925\n2014-02-25 11:25:00,13.9267\n2014-02-25 11:30:00,15.5567\n2014-02-25 11:35:00,14.4433\n2014-02-25 11:40:00,15.0867\n2014-02-25 11:45:00,13.8867\n2014-02-25 11:50:00,14.4433\n2014-02-25 11:55:00,14.3333\n2014-02-25 12:00:00,15.0\n2014-02-25 12:05:00,14.4567\n2014-02-25 12:10:00,15.5567\n2014-02-25 12:15:00,13.9533\n2014-02-25 12:20:00,15.0\n2014-02-25 12:25:00,13.8867\n2014-02-25 12:30:00,15.0\n2014-02-25 12:35:00,13.89\n2014-02-25 12:40:00,14.8733\n2014-02-25 12:45:00,14.4433\n2014-02-25 12:50:00,15.6433\n2014-02-25 12:55:00,13.97\n2014-02-25 13:00:00,15.0567\n2014-02-25 13:05:00,13.8867\n2014-02-25 13:10:00,15.0\n2014-02-25 13:15:00,13.9333\n2014-02-25 13:20:00,15.5567\n2014-02-25 13:25:00,13.9333\n2014-02-25 13:30:00,15.0\n2014-02-25 13:35:00,13.9333\n2014-02-25 13:40:00,15.6133\n2014-02-25 13:45:00,11.6467\n2014-02-25 13:50:00,15.0867\n2014-02-25 13:55:00,13.8867\n2014-02-25 14:00:00,15.0\n2014-02-25 14:05:00,14.4433\n2014-02-25 14:10:00,15.0\n2014-02-25 14:15:00,13.8867\n2014-02-25 14:20:00,14.9933\n2014-02-25 14:25:00,13.8867\n2014-02-25 14:30:00,15.5567\n2014-02-25 14:35:00,14.4433\n2014-02-25 14:40:00,15.0\n2014-02-25 14:45:00,13.8867\n2014-02-25 14:50:00,15.0567\n2014-02-25 14:55:00,13.8267\n2014-02-25 15:00:00,15.1267\n2014-02-25 15:05:00,13.9067\n2014-02-25 15:10:00,14.8733\n2014-02-25 15:15:00,12.22\n2014-02-25 15:20:00,13.2333\n2014-02-25 15:25:00,14.4733\n2014-02-25 15:30:00,15.0\n2014-02-25 15:35:00,13.9333\n2014-02-25 15:40:00,14.4433\n2014-02-25 15:45:00,14.3733\n2014-02-25 15:50:00,15.0\n2014-02-25 15:55:00,14.4433\n2014-02-25 16:00:00,15.0033\n2014-02-25 16:05:00,13.8267\n2014-02-25 16:10:00,13.3367\n2014-02-25 16:15:00,13.9267\n2014-02-25 16:20:00,15.6333\n2014-02-25 16:25:00,14.4833\n2014-02-25 16:30:00,14.93\n2014-02-25 16:35:00,14.4833\n2014-02-25 16:40:00,15.0\n2014-02-25 16:45:00,13.9067\n2014-02-25 16:50:00,15.5567\n2014-02-25 16:55:00,14.4433\n2014-02-25 17:00:00,15.0567\n2014-02-25 17:05:00,14.4433\n2014-02-25 17:10:00,15.5567\n2014-02-25 17:15:00,12.22\n2014-02-25 17:20:00,15.1433\n2014-02-25 17:25:00,14.5133\n2014-02-25 17:30:00,15.5567\n2014-02-25 17:35:00,14.4\n2014-02-25 17:40:00,15.0\n2014-02-25 17:45:00,14.5\n2014-02-25 17:50:00,15.0\n2014-02-25 17:55:00,14.4433\n2014-02-25 18:00:00,15.5567\n2014-02-25 18:05:00,14.4433\n2014-02-25 18:10:00,13.89\n2014-02-25 18:15:00,13.8867\n2014-02-25 18:20:00,15.1967\n2014-02-25 18:25:00,13.8867\n2014-02-25 18:30:00,15.0\n2014-02-25 18:35:00,14.4433\n2014-02-25 18:40:00,15.0567\n2014-02-25 18:45:00,14.3967\n2014-02-25 18:50:00,15.5567\n2014-02-25 18:55:00,14.4433\n2014-02-25 19:00:00,15.0\n2014-02-25 19:05:00,13.9067\n2014-02-25 19:10:00,15.5567\n2014-02-25 19:15:00,13.7767\n2014-02-25 19:20:00,15.07\n2014-02-25 19:25:00,14.3333\n2014-02-25 19:30:00,14.4433\n2014-02-25 19:35:00,13.8867\n2014-02-25 19:40:00,13.3333\n2014-02-25 19:45:00,14.4433\n2014-02-25 19:50:00,15.42\n2014-02-25 19:55:00,13.9067\n2014-02-25 20:00:00,15.55\n2014-02-25 20:05:00,14.4433\n2014-02-25 20:10:00,16.1067\n2014-02-25 20:15:00,14.4433\n2014-02-25 20:20:00,13.75\n2014-02-25 20:25:00,14.4433\n2014-02-25 20:30:00,15.0\n2014-02-25 20:35:00,14.4433\n2014-02-25 20:40:00,15.6433\n2014-02-25 20:45:00,13.8867\n2014-02-25 20:50:00,14.9367\n2014-02-25 20:55:00,13.8867\n2014-02-25 21:00:00,15.0567\n2014-02-25 21:05:00,13.9333\n2014-02-25 21:10:00,15.55\n2014-02-25 21:15:00,13.8867\n2014-02-25 21:20:00,15.1433\n2014-02-25 21:25:00,14.4433\n2014-02-25 21:30:00,15.42\n2014-02-25 21:35:00,15.0\n2014-02-25 21:40:00,14.4433\n2014-02-25 21:45:00,13.9267\n2014-02-25 21:50:00,15.0867\n2014-02-25 21:55:00,14.4433\n2014-02-25 22:00:00,15.5567\n2014-02-25 22:05:00,15.0\n2014-02-25 22:10:00,15.0\n2014-02-25 22:15:00,13.9333\n2014-02-25 22:20:00,15.0\n2014-02-25 22:25:00,14.3433\n2014-02-25 22:30:00,15.0\n2014-02-25 22:35:00,13.8867\n2014-02-25 22:40:00,15.08\n2014-02-25 22:45:00,14.4733\n2014-02-25 22:50:00,13.94\n2014-02-25 22:55:00,13.8867\n2014-02-25 23:00:00,14.9467\n2014-02-25 23:05:00,13.92\n2014-02-25 23:10:00,15.0\n2014-02-25 23:15:00,14.4433\n2014-02-25 23:20:00,15.5567\n2014-02-25 23:25:00,13.9167\n2014-02-25 23:30:00,14.3267\n2014-02-25 23:35:00,13.8867\n2014-02-25 23:40:00,15.0867\n2014-02-25 23:45:00,13.8867\n2014-02-25 23:50:00,15.0\n2014-02-25 23:55:00,13.39\n2014-02-26 00:00:00,15.15\n2014-02-26 00:05:00,14.4433\n2014-02-26 00:10:00,15.5567\n2014-02-26 00:15:00,14.4433\n2014-02-26 00:20:00,14.9933\n2014-02-26 00:25:00,13.9333\n2014-02-26 00:30:00,14.4433\n2014-02-26 00:35:00,13.9067\n2014-02-26 00:40:00,15.0633\n2014-02-26 00:45:00,14.3333\n2014-02-26 00:50:00,15.0\n2014-02-26 00:55:00,13.8867\n2014-02-26 01:00:00,15.5567\n2014-02-26 01:05:00,12.2233\n2014-02-26 01:10:00,15.0\n2014-02-26 01:15:00,16.15\n2014-02-26 01:20:00,15.0\n2014-02-26 01:25:00,13.9333\n2014-02-26 01:30:00,15.0567\n2014-02-26 01:35:00,13.9067\n2014-02-26 01:40:00,15.08\n2014-02-26 01:45:00,13.9067\n2014-02-26 01:50:00,14.8633\n2014-02-26 01:55:00,14.4433\n2014-02-26 02:00:00,12.105\n2014-02-26 02:05:00,13.8867\n2014-02-26 02:10:00,15.1433\n2014-02-26 02:15:00,14.4433\n2014-02-26 02:20:00,15.9767\n2014-02-26 02:25:00,14.4433\n2014-02-26 02:30:00,14.9367\n2014-02-26 02:35:00,14.5267\n2014-02-26 02:40:00,15.07\n2014-02-26 02:45:00,13.9067\n2014-02-26 02:50:00,15.0\n2014-02-26 02:55:00,13.94\n2014-02-26 03:00:00,15.0\n2014-02-26 03:05:00,13.3333\n2014-02-26 03:10:00,15.0\n2014-02-26 03:15:00,11.7067\n2014-02-26 03:20:00,15.0\n2014-02-26 03:25:00,14.3433\n2014-02-26 03:30:00,15.42\n2014-02-26 03:35:00,13.8867\n2014-02-26 03:40:00,14.5\n2014-02-26 03:45:00,14.4433\n2014-02-26 03:50:00,15.0\n2014-02-26 03:55:00,13.8867\n2014-02-26 04:00:00,15.0\n2014-02-26 04:05:00,13.8867\n2014-02-26 04:10:00,15.01\n2014-02-26 04:15:00,14.4433\n2014-02-26 04:20:00,16.1133\n2014-02-26 04:25:00,14.4433\n2014-02-26 04:30:00,15.0867\n2014-02-26 04:35:00,14.49\n2014-02-26 04:40:00,15.0\n2014-02-26 04:45:00,14.4433\n2014-02-26 04:50:00,15.0\n2014-02-26 04:55:00,13.33\n2014-02-26 05:00:00,15.0\n2014-02-26 05:05:00,14.3433\n2014-02-26 05:10:00,15.0\n2014-02-26 05:15:00,14.4533\n2014-02-26 05:20:00,15.0033\n2014-02-26 05:25:00,14.4433\n2014-02-26 05:30:00,15.0\n2014-02-26 05:35:00,13.89\n2014-02-26 05:40:00,14.39\n2014-02-26 05:45:00,13.3333\n2014-02-26 05:50:00,15.42\n2014-02-26 05:55:00,14.4933\n2014-02-26 06:00:00,15.08\n2014-02-26 06:05:00,14.3433\n2014-02-26 06:10:00,14.9467\n2014-02-26 06:15:00,13.9567\n2014-02-26 06:20:00,14.8667\n2014-02-26 06:25:00,15.0\n2014-02-26 06:30:00,14.4433\n2014-02-26 06:35:00,13.8867\n2014-02-26 06:40:00,15.0\n2014-02-26 06:45:00,13.3333\n2014-02-26 06:50:00,15.0\n2014-02-26 06:55:00,14.4433\n2014-02-26 07:00:00,15.0\n2014-02-26 07:05:00,13.36\n2014-02-26 07:10:00,13.3675\n2014-02-26 07:15:00,13.85\n2014-02-26 07:20:00,15.0\n2014-02-26 07:25:00,15.0\n2014-02-26 07:30:00,15.62\n2014-02-26 07:35:00,14.49\n2014-02-26 07:40:00,15.0\n2014-02-26 07:45:00,13.8867\n2014-02-26 07:50:00,15.0\n2014-02-26 07:55:00,16.6667\n2014-02-26 08:00:00,14.9467\n2014-02-26 08:05:00,13.8867\n2014-02-26 08:10:00,14.4433\n2014-02-26 08:15:00,14.4433\n2014-02-26 08:20:00,15.5567\n2014-02-26 08:25:00,14.5\n2014-02-26 08:30:00,15.5567\n2014-02-26 08:35:00,13.8333\n2014-02-26 08:40:00,13.3425\n2014-02-26 08:45:00,13.8867\n2014-02-26 08:50:00,14.8633\n2014-02-26 08:55:00,13.9633\n2014-02-26 09:00:00,14.4433\n2014-02-26 09:05:00,13.7867\n2014-02-26 09:10:00,15.0\n2014-02-26 09:15:00,13.9367\n2014-02-26 09:20:00,15.01\n2014-02-26 09:25:00,14.37\n2014-02-26 09:30:00,15.07\n2014-02-26 09:35:00,14.49\n2014-02-26 09:40:00,15.0\n2014-02-26 09:45:00,13.8033\n2014-02-26 09:50:00,13.2925\n2014-02-26 09:55:00,13.8267\n2014-02-26 10:00:00,15.0\n2014-02-26 10:05:00,12.9025\n2014-02-26 10:10:00,15.0\n2014-02-26 10:15:00,14.5267\n2014-02-26 10:20:00,14.5\n2014-02-26 10:25:00,13.8867\n2014-02-26 10:30:00,13.4275\n2014-02-26 10:35:00,14.36\n2014-02-26 10:40:00,15.0\n2014-02-26 10:45:00,12.9525\n2014-02-26 10:50:00,14.8733\n2014-02-26 10:55:00,13.3633\n2014-02-26 11:00:00,14.3167\n2014-02-26 11:05:00,13.8867\n2014-02-26 11:10:00,15.0033\n2014-02-26 11:15:00,12.915\n2014-02-26 11:20:00,15.62\n2014-02-26 11:25:00,13.8867\n2014-02-26 11:30:00,17.22\n2014-02-26 11:35:00,13.8867\n2014-02-26 11:40:00,15.4833\n2014-02-26 11:45:00,13.9333\n2014-02-26 11:50:00,14.9467\n2014-02-26 11:55:00,13.8867\n2014-02-26 12:00:00,15.0\n2014-02-26 12:05:00,14.4433\n2014-02-26 12:10:00,15.5567\n2014-02-26 12:15:00,14.4433\n2014-02-26 12:20:00,15.6433\n2014-02-26 12:25:00,13.9267\n2014-02-26 12:30:00,12.9175\n2014-02-26 12:35:00,14.4433\n2014-02-26 12:40:00,14.4433\n2014-02-26 12:45:00,13.4167\n2014-02-26 12:50:00,14.49\n2014-02-26 12:55:00,13.8867\n2014-02-26 13:00:00,15.0\n2014-02-26 13:05:00,14.4433\n2014-02-26 13:10:00,15.0\n2014-02-26 13:15:00,13.8867\n2014-02-26 13:20:00,12.975\n2014-02-26 13:25:00,13.9267\n2014-02-26 13:30:00,15.0\n2014-02-26 13:35:00,13.9333\n2014-02-26 13:40:00,15.42\n2014-02-26 13:45:00,12.22\n2014-02-26 13:50:00,15.5567\n2014-02-26 13:55:00,15.0\n2014-02-26 14:00:00,16.19\n2014-02-26 14:05:00,14.4733\n2014-02-26 14:10:00,15.5567\n2014-02-26 14:15:00,13.8867\n2014-02-26 14:20:00,15.6333\n2014-02-26 14:25:00,14.3333\n2014-02-26 14:30:00,15.08\n2014-02-26 14:35:00,13.9267\n2014-02-26 14:40:00,14.4433\n2014-02-26 14:45:00,13.7767\n2014-02-26 14:50:00,15.0567\n2014-02-26 14:55:00,13.9067\n2014-02-26 15:00:00,15.0\n2014-02-26 15:05:00,11.6667\n2014-02-26 15:10:00,15.08\n2014-02-26 15:15:00,14.4433\n2014-02-26 15:20:00,15.42\n2014-02-26 15:25:00,15.0\n2014-02-26 15:30:00,15.5567\n2014-02-26 15:35:00,12.7767\n2014-02-26 15:40:00,15.5567\n2014-02-26 15:45:00,14.4433\n2014-02-26 15:50:00,15.5567\n2014-02-26 15:55:00,13.8867\n2014-02-26 16:00:00,15.0\n2014-02-26 16:05:00,13.9267\n2014-02-26 16:10:00,15.0\n2014-02-26 16:15:00,13.8867\n2014-02-26 16:20:00,15.0633\n2014-02-26 16:25:00,15.0\n2014-02-26 16:30:00,15.0567\n2014-02-26 16:35:00,14.4433\n2014-02-26 16:40:00,15.5567\n2014-02-26 16:45:00,14.4433\n2014-02-26 16:50:00,14.4433\n2014-02-26 16:55:00,13.8867\n2014-02-26 17:00:00,14.5233\n2014-02-26 17:05:00,14.3333\n2014-02-26 17:10:00,15.5567\n2014-02-26 17:15:00,14.4433\n2014-02-26 17:20:00,15.5667\n2014-02-26 17:25:00,14.4433\n2014-02-26 17:30:00,15.0\n2014-02-26 17:35:00,14.3333\n2014-02-26 17:40:00,15.43\n2014-02-26 17:45:00,13.4367\n2014-02-26 17:50:00,14.8733\n2014-02-26 17:55:00,13.25\n2014-02-26 18:00:00,15.5667\n2014-02-26 18:05:00,13.9333\n2014-02-26 18:10:00,15.5567\n2014-02-26 18:15:00,13.8867\n2014-02-26 18:20:00,15.0\n2014-02-26 18:25:00,15.0\n2014-02-26 18:30:00,16.11\n2014-02-26 18:35:00,13.8867\n2014-02-26 18:40:00,14.4433\n2014-02-26 18:45:00,13.3333\n2014-02-26 18:50:00,15.0033\n2014-02-26 18:55:00,13.8867\n2014-02-26 19:00:00,15.08\n2014-02-26 19:05:00,13.8867\n2014-02-26 19:10:00,14.8733\n2014-02-26 19:15:00,12.7033\n2014-02-26 19:20:00,16.1133\n2014-02-26 19:25:00,12.22\n2014-02-26 19:30:00,15.5567\n2014-02-26 19:35:00,14.4433\n2014-02-26 19:40:00,15.42\n2014-02-26 19:45:00,12.915\n2014-02-26 19:50:00,15.0\n2014-02-26 19:55:00,13.9267\n2014-02-26 20:00:00,15.0\n2014-02-26 20:05:00,12.22\n2014-02-26 20:10:00,15.5567\n2014-02-26 20:15:00,13.8867\n2014-02-26 20:20:00,15.06\n2014-02-26 20:25:00,14.4433\n2014-02-26 20:30:00,16.1133\n2014-02-26 20:35:00,14.4633\n2014-02-26 20:40:00,15.5567\n2014-02-26 20:45:00,14.4433\n2014-02-26 20:50:00,15.0\n2014-02-26 20:55:00,14.4433\n2014-02-26 21:00:00,14.88\n2014-02-26 21:05:00,13.8867\n2014-02-26 21:10:00,15.5567\n2014-02-26 21:15:00,14.5\n2014-02-26 21:20:00,16.1767\n2014-02-26 21:25:00,14.89\n2014-02-26 21:30:00,16.1133\n2014-02-26 21:35:00,14.4433\n2014-02-26 21:40:00,15.6133\n2014-02-26 21:45:00,13.89\n2014-02-26 21:50:00,15.0\n2014-02-26 21:55:00,14.4833\n2014-02-26 22:00:00,15.08\n2014-02-26 22:05:00,13.8867\n2014-02-26 22:10:00,15.55\n2014-02-26 22:15:00,15.0767\n2014-02-26 22:20:00,16.1133\n2014-02-26 22:25:00,14.4433\n2014-02-26 22:30:00,15.01\n2014-02-26 22:35:00,14.4833\n2014-02-26 22:40:00,15.6533\n2014-02-26 22:45:00,14.4433\n2014-02-26 22:50:00,15.6433\n2014-02-26 22:55:00,13.9467\n2014-02-26 23:00:00,15.0\n2014-02-26 23:05:00,13.9267\n2014-02-26 23:10:00,15.43\n2014-02-26 23:15:00,14.4433\n2014-02-26 23:20:00,15.5567\n2014-02-26 23:25:00,14.49\n2014-02-26 23:30:00,15.6333\n2014-02-26 23:35:00,13.75\n2014-02-26 23:40:00,14.1675\n2014-02-26 23:45:00,13.9267\n2014-02-26 23:50:00,15.0\n2014-02-26 23:55:00,14.4433\n2014-02-27 00:00:00,16.1533\n2014-02-27 00:05:00,15.0\n2014-02-27 00:10:00,15.5567\n2014-02-27 00:15:00,14.4433\n2014-02-27 00:20:00,14.9933\n2014-02-27 00:25:00,14.4433\n2014-02-27 00:30:00,15.5567\n2014-02-27 00:35:00,14.3433\n2014-02-27 00:40:00,14.3733\n2014-02-27 00:45:00,16.695\n2014-02-27 00:50:00,19.165\n2014-02-27 00:55:00,12.1367\n2014-02-27 01:00:00,14.8733\n2014-02-27 01:05:00,14.4433\n2014-02-27 01:10:00,14.9367\n2014-02-27 01:15:00,14.4433\n2014-02-27 01:20:00,16.1067\n2014-02-27 01:25:00,15.0567\n2014-02-27 01:30:00,15.5567\n2014-02-27 01:35:00,14.4467\n2014-02-27 01:40:00,15.5567\n2014-02-27 01:45:00,15.0\n2014-02-27 01:50:00,15.0033\n2014-02-27 01:55:00,13.8867\n2014-02-27 02:00:00,15.01\n2014-02-27 02:05:00,14.3433\n2014-02-27 02:10:00,15.01\n2014-02-27 02:15:00,14.4833\n2014-02-27 02:20:00,15.5567\n2014-02-27 02:25:00,15.0\n2014-02-27 02:30:00,15.5567\n2014-02-27 02:35:00,14.4433\n2014-02-27 02:40:00,15.0\n2014-02-27 02:45:00,14.4433\n2014-02-27 02:50:00,13.76\n2014-02-27 02:55:00,14.3433\n2014-02-27 03:00:00,15.55\n2014-02-27 03:05:00,14.4833\n2014-02-27 03:10:00,15.62\n2014-02-27 03:15:00,14.4433\n2014-02-27 03:20:00,14.8733\n2014-02-27 03:25:00,13.91\n2014-02-27 03:30:00,13.75\n2014-02-27 03:35:00,14.4433\n2014-02-27 03:40:00,15.62\n2014-02-27 03:45:00,15.0\n2014-02-27 03:50:00,15.6333\n2014-02-27 03:55:00,13.7867\n2014-02-27 04:00:00,15.0567\n2014-02-27 04:05:00,13.9267\n2014-02-27 04:10:00,15.07\n2014-02-27 04:15:00,14.49\n2014-02-27 04:20:00,16.1133\n2014-02-27 04:25:00,14.4433\n2014-02-27 04:30:00,14.9467\n2014-02-27 04:35:00,13.8867\n2014-02-27 04:40:00,15.5567\n2014-02-27 04:45:00,14.39\n2014-02-27 04:50:00,15.0\n2014-02-27 04:55:00,14.89\n2014-02-27 05:00:00,15.01\n2014-02-27 05:05:00,13.9333\n2014-02-27 05:10:00,15.0\n2014-02-27 05:15:00,14.49\n2014-02-27 05:20:00,15.0\n2014-02-27 05:25:00,13.24\n2014-02-27 05:30:00,15.0\n2014-02-27 05:35:00,14.3333\n2014-02-27 05:40:00,14.9467\n2014-02-27 05:45:00,13.9267\n2014-02-27 05:50:00,15.0567\n2014-02-27 05:55:00,13.8867\n2014-02-27 06:00:00,15.0633\n2014-02-27 06:05:00,14.49\n2014-02-27 06:10:00,15.5667\n2014-02-27 06:15:00,13.8867\n2014-02-27 06:20:00,13.75\n2014-02-27 06:25:00,13.37\n2014-02-27 06:30:00,15.0\n2014-02-27 06:35:00,13.8867\n2014-02-27 06:40:00,15.0867\n2014-02-27 06:45:00,13.2633\n2014-02-27 06:50:00,14.4433\n2014-02-27 06:55:00,13.4167\n2014-02-27 07:00:00,15.0033\n2014-02-27 07:05:00,13.8867\n2014-02-27 07:10:00,15.55\n2014-02-27 07:15:00,13.8867\n2014-02-27 07:20:00,15.0\n2014-02-27 07:25:00,13.9067\n2014-02-27 07:30:00,15.0867\n2014-02-27 07:35:00,13.9067\n2014-02-27 07:40:00,14.8667\n2014-02-27 07:45:00,12.9125\n2014-02-27 07:50:00,14.9367\n2014-02-27 07:55:00,16.64\n2014-02-27 08:00:00,15.5533\n2014-02-27 08:05:00,15.02\n2014-02-27 08:10:00,15.0567\n2014-02-27 08:15:00,11.1233\n2014-02-27 08:20:00,14.5\n2014-02-27 08:25:00,13.78\n2014-02-27 08:30:00,14.4433\n2014-02-27 08:35:00,11.6467\n2014-02-27 08:40:00,12.78\n2014-02-27 08:45:00,13.9\n2014-02-27 08:50:00,14.9933\n2014-02-27 08:55:00,14.4833\n2014-02-27 09:00:00,14.88\n2014-02-27 09:05:00,13.8867\n2014-02-27 09:10:00,14.8633\n2014-02-27 09:15:00,13.27\n2014-02-27 09:20:00,12.2233\n2014-02-27 09:25:00,13.89\n2014-02-27 09:30:00,15.5567\n2014-02-27 09:35:00,13.7867\n2014-02-27 09:40:00,14.5\n2014-02-27 09:45:00,12.22\n2014-02-27 09:50:00,15.0\n2014-02-27 09:55:00,14.4433\n2014-02-27 10:00:00,15.0567\n2014-02-27 10:05:00,13.8867\n2014-02-27 10:10:00,14.9933\n2014-02-27 10:15:00,13.3333\n2014-02-27 10:20:00,15.0567\n2014-02-27 10:25:00,14.4433\n2014-02-27 10:30:00,15.0967\n2014-02-27 10:35:00,14.5\n2014-02-27 10:40:00,15.0\n2014-02-27 10:45:00,13.8867\n2014-02-27 10:50:00,14.8633\n2014-02-27 10:55:00,14.4733\n2014-02-27 11:00:00,14.4433\n2014-02-27 11:05:00,13.8867\n2014-02-27 11:10:00,15.0\n2014-02-27 11:15:00,13.7867\n2014-02-27 11:20:00,12.81\n2014-02-27 11:25:00,14.4433\n2014-02-27 11:30:00,15.0567\n2014-02-27 11:35:00,13.38\n2014-02-27 11:40:00,12.8333\n2014-02-27 11:45:00,12.2967\n2014-02-27 11:50:00,15.6267\n2014-02-27 11:55:00,13.38\n2014-02-27 12:00:00,15.07\n2014-02-27 12:05:00,13.9467\n2014-02-27 12:10:00,14.8733\n2014-02-27 12:15:00,13.27\n2014-02-27 12:20:00,14.4433\n2014-02-27 12:25:00,14.3333\n2014-02-27 12:30:00,12.28\n2014-02-27 12:35:00,13.9267\n2014-02-27 12:40:00,14.4433\n2014-02-27 12:45:00,13.9333\n2014-02-27 12:50:00,15.01\n2014-02-27 12:55:00,13.9333\n2014-02-27 13:00:00,14.3167\n2014-02-27 13:05:00,13.9267\n2014-02-27 13:10:00,15.0\n2014-02-27 13:15:00,14.4433\n2014-02-27 13:20:00,15.5567\n2014-02-27 13:25:00,13.3333\n2014-02-27 13:30:00,14.8633\n2014-02-27 13:35:00,13.8867\n2014-02-27 13:40:00,12.8267\n2014-02-27 13:45:00,13.8267\n2014-02-27 13:50:00,14.4467\n2014-02-27 13:55:00,13.8867\n2014-02-27 14:00:00,14.4433\n2014-02-27 14:05:00,13.9533\n2014-02-27 14:10:00,15.0567\n2014-02-27 14:15:00,13.8867\n2014-02-27 14:20:00,15.5567\n2014-02-27 14:25:00,14.49\n2014-02-27 14:30:00,13.385\n2014-02-27 14:35:00,14.3733\n2014-02-27 14:40:00,15.08\n2014-02-27 14:45:00,14.3733\n2014-02-27 14:50:00,15.0\n2014-02-27 14:55:00,14.3733\n2014-02-27 15:00:00,15.0567\n2014-02-27 15:05:00,14.4733\n2014-02-27 15:10:00,15.0\n2014-02-27 15:15:00,13.8867\n2014-02-27 15:20:00,14.4433\n2014-02-27 15:25:00,13.9067\n2014-02-27 15:30:00,15.42\n2014-02-27 15:35:00,13.7967\n2014-02-27 15:40:00,15.5567\n2014-02-27 15:45:00,14.3333\n2014-02-27 15:50:00,15.5567\n2014-02-27 15:55:00,14.4433\n2014-02-27 16:00:00,15.4133\n2014-02-27 16:05:00,14.35\n2014-02-27 16:10:00,12.78\n2014-02-27 16:15:00,13.9333\n2014-02-27 16:20:00,15.0\n2014-02-27 16:25:00,14.4433\n2014-02-27 16:30:00,15.5567\n2014-02-27 16:35:00,15.03\n2014-02-27 16:40:00,15.4133\n2014-02-27 16:45:00,14.4533\n2014-02-27 16:50:00,15.5567\n2014-02-27 16:55:00,15.0\n2014-02-27 17:00:00,14.88\n2014-02-27 17:05:00,14.4433\n2014-02-27 17:10:00,16.1233\n2014-02-27 17:15:00,14.4433\n2014-02-27 17:20:00,16.05\n2014-02-27 17:25:00,16.1133\n2014-02-27 17:30:00,16.6633\n2014-02-27 17:35:00,14.4633\n2014-02-27 17:40:00,15.0\n2014-02-27 17:45:00,14.4433\n2014-02-27 17:50:00,15.5567\n2014-02-27 17:55:00,15.0\n2014-02-27 18:00:00,16.1133\n2014-02-27 18:05:00,14.49\n2014-02-27 18:10:00,14.5767\n2014-02-27 18:15:00,14.4833\n2014-02-27 18:20:00,14.8733\n2014-02-27 18:25:00,13.7867\n2014-02-27 18:30:00,15.0\n2014-02-27 18:35:00,13.8867\n2014-02-27 18:40:00,14.92\n2014-02-27 18:45:00,13.8333\n2014-02-27 18:50:00,15.08\n2014-02-27 18:55:00,13.97\n2014-02-27 19:00:00,15.0\n2014-02-27 19:05:00,13.8867\n2014-02-27 19:10:00,16.1133\n2014-02-27 19:15:00,14.3433\n2014-02-27 19:20:00,15.6133\n2014-02-27 19:25:00,14.4733\n2014-02-27 19:30:00,15.0\n2014-02-27 19:35:00,13.9333\n2014-02-27 19:40:00,14.93\n2014-02-27 19:45:00,14.4433\n2014-02-27 19:50:00,15.6967\n2014-02-27 19:55:00,13.85\n2014-02-27 20:00:00,15.5567\n2014-02-27 20:05:00,14.4433\n2014-02-27 20:10:00,15.5567\n2014-02-27 20:15:00,14.5\n2014-02-27 20:20:00,15.42\n2014-02-27 20:25:00,13.8333\n2014-02-27 20:30:00,15.5567\n2014-02-27 20:35:00,14.49\n2014-02-27 20:40:00,15.5567\n2014-02-27 20:45:00,15.0\n2014-02-27 20:50:00,15.0\n2014-02-27 20:55:00,13.9267\n2014-02-27 21:00:00,15.5567\n2014-02-27 21:05:00,14.4633\n2014-02-27 21:10:00,15.0\n2014-02-27 21:15:00,13.7867\n2014-02-27 21:20:00,15.0\n2014-02-27 21:25:00,15.5567\n2014-02-27 21:30:00,16.1133\n2014-02-27 21:35:00,14.4433\n2014-02-27 21:40:00,15.1433\n2014-02-27 21:45:00,13.9067\n2014-02-27 21:50:00,15.56\n2014-02-27 21:55:00,13.8867\n2014-02-27 22:00:00,15.0\n2014-02-27 22:05:00,13.9333\n2014-02-27 22:10:00,15.5567\n2014-02-27 22:15:00,14.89\n2014-02-27 22:20:00,15.6333\n2014-02-27 22:25:00,14.5267\n2014-02-27 22:30:00,14.4433\n2014-02-27 22:35:00,13.8867\n2014-02-27 22:40:00,15.0\n2014-02-27 22:45:00,13.9267\n2014-02-27 22:50:00,12.9575\n2014-02-27 22:55:00,13.8033\n2014-02-27 23:00:00,15.0\n2014-02-27 23:05:00,13.9333\n2014-02-27 23:10:00,15.0\n2014-02-27 23:15:00,14.4433\n2014-02-27 23:20:00,16.11\n2014-02-27 23:25:00,15.02\n2014-02-27 23:30:00,15.5567\n2014-02-27 23:35:00,14.4733\n2014-02-27 23:40:00,15.6133\n2014-02-27 23:45:00,14.49\n2014-02-27 23:50:00,13.6475\n2014-02-27 23:55:00,14.38\n2014-02-28 00:00:00,16.1467\n2014-02-28 00:05:00,14.4433\n2014-02-28 00:10:00,16.1133\n2014-02-28 00:15:00,14.94\n2014-02-28 00:20:00,15.6433\n2014-02-28 00:25:00,15.0667\n2014-02-28 00:30:00,15.55\n2014-02-28 00:35:00,14.4433\n2014-02-28 00:40:00,15.0\n2014-02-28 00:45:00,14.4433\n2014-02-28 00:50:00,15.5567\n2014-02-28 00:55:00,15.0\n2014-02-28 01:00:00,15.0\n2014-02-28 01:05:00,15.0\n2014-02-28 01:10:00,15.5567\n2014-02-28 01:15:00,15.0\n2014-02-28 01:20:00,15.5567\n2014-02-28 01:25:00,13.8867\n2014-02-28 01:30:00,15.5667\n2014-02-28 01:35:00,13.9333\n2014-02-28 01:40:00,15.55\n2014-02-28 01:45:00,13.8867\n2014-02-28 01:50:00,15.0\n2014-02-28 01:55:00,13.8867\n2014-02-28 02:00:00,15.0633\n2014-02-28 02:05:00,13.8333\n2014-02-28 02:10:00,15.42\n2014-02-28 02:15:00,14.4733\n2014-02-28 02:20:00,15.5567\n2014-02-28 02:25:00,13.9467\n2014-02-28 02:30:00,14.8733\n2014-02-28 02:35:00,12.1933\n2014-02-28 02:40:00,14.3733\n2014-02-28 02:45:00,13.8867\n2014-02-28 02:50:00,15.0\n2014-02-28 02:55:00,13.87\n2014-02-28 03:00:00,12.7767\n2014-02-28 03:05:00,13.9333\n2014-02-28 03:10:00,15.0\n2014-02-28 03:15:00,14.52\n2014-02-28 03:20:00,14.4467\n2014-02-28 03:25:00,14.4433\n2014-02-28 03:30:00,15.5567\n2014-02-28 03:35:00,12.26\n2014-02-28 03:40:00,15.1333\n2014-02-28 03:45:00,15.0\n2014-02-28 03:50:00,15.5567\n2014-02-28 03:55:00,13.36\n2014-02-28 04:00:00,14.4433\n2014-02-28 04:05:00,13.9333\n2014-02-28 04:10:00,15.0\n2014-02-28 04:15:00,13.4125\n2014-02-28 04:20:00,14.8733\n2014-02-28 04:25:00,13.3333\n2014-02-28 04:30:00,14.32\n2014-02-28 04:35:00,14.4733\n2014-02-28 04:40:00,15.4133\n2014-02-28 04:45:00,13.9067\n2014-02-28 04:50:00,15.55\n2014-02-28 04:55:00,13.9267\n2014-02-28 05:00:00,15.0\n2014-02-28 05:05:00,13.9267\n2014-02-28 05:10:00,15.0\n2014-02-28 05:15:00,13.3333\n2014-02-28 05:20:00,15.0033\n2014-02-28 05:25:00,13.8867\n2014-02-28 05:30:00,15.0\n2014-02-28 05:35:00,13.3333\n2014-02-28 05:40:00,14.8733\n2014-02-28 05:45:00,14.4433\n2014-02-28 05:50:00,15.0567\n2014-02-28 05:55:00,13.8867\n2014-02-28 06:00:00,15.0467\n2014-02-28 06:05:00,13.9067\n2014-02-28 06:10:00,15.0567\n2014-02-28 06:15:00,14.4433\n2014-02-28 06:20:00,15.0\n2014-02-28 06:25:00,13.9533\n2014-02-28 06:30:00,13.785\n2014-02-28 06:35:00,14.49\n2014-02-28 06:40:00,15.4833\n2014-02-28 06:45:00,12.1467\n2014-02-28 06:50:00,15.1333\n2014-02-28 06:55:00,14.4433\n2014-02-28 07:00:00,15.5567\n2014-02-28 07:05:00,14.3433\n2014-02-28 07:10:00,15.5567\n2014-02-28 07:15:00,13.9067\n2014-02-28 07:20:00,15.0033\n2014-02-28 07:25:00,13.9733\n2014-02-28 07:30:00,14.8667\n2014-02-28 07:35:00,13.8867\n2014-02-28 07:40:00,15.07\n2014-02-28 07:45:00,13.3333\n2014-02-28 07:50:00,15.5567\n2014-02-28 07:55:00,17.2667\n2014-02-28 08:00:00,15.5567\n2014-02-28 08:05:00,13.9267\n2014-02-28 08:10:00,15.5567\n2014-02-28 08:15:00,13.9333\n2014-02-28 08:20:00,15.4833\n2014-02-28 08:25:00,14.4433\n2014-02-28 08:30:00,15.6433\n2014-02-28 08:35:00,13.7867\n2014-02-28 08:40:00,15.6967\n2014-02-28 08:45:00,14.3933\n2014-02-28 08:50:00,15.08\n2014-02-28 08:55:00,13.8867\n2014-02-28 09:00:00,15.62\n2014-02-28 09:05:00,15.0\n2014-02-28 09:10:00,15.5567\n2014-02-28 09:15:00,15.0\n2014-02-28 09:20:00,15.0\n2014-02-28 09:25:00,14.3333\n2014-02-28 09:30:00,12.78\n2014-02-28 09:35:00,13.8867\n2014-02-28 09:40:00,15.0567\n2014-02-28 09:45:00,14.3433\n2014-02-28 09:50:00,15.0\n2014-02-28 09:55:00,14.4433\n2014-02-28 10:00:00,15.42\n2014-02-28 10:05:00,13.8867\n2014-02-28 10:10:00,15.5567\n2014-02-28 10:15:00,15.0467\n2014-02-28 10:20:00,15.42\n2014-02-28 10:25:00,13.9333\n2014-02-28 10:30:00,14.5\n2014-02-28 10:35:00,14.3333\n2014-02-28 10:40:00,16.1133\n2014-02-28 10:45:00,14.4633\n2014-02-28 10:50:00,14.92\n2014-02-28 10:55:00,13.97\n2014-02-28 11:00:00,15.5567\n2014-02-28 11:05:00,15.0\n2014-02-28 11:10:00,14.9933\n2014-02-28 11:15:00,14.3333\n2014-02-28 11:20:00,12.78\n2014-02-28 11:25:00,13.9333\n2014-02-28 11:30:00,15.6433\n2014-02-28 11:35:00,14.4433\n2014-02-28 11:40:00,14.8733\n2014-02-28 11:45:00,13.8867\n2014-02-28 11:50:00,15.4667\n2014-02-28 11:55:00,13.8867\n2014-02-28 12:00:00,15.5567\n2014-02-28 12:05:00,13.9333\n2014-02-28 12:10:00,15.1033\n2014-02-28 12:15:00,14.4433\n2014-02-28 12:20:00,16.11\n2014-02-28 12:25:00,14.3333\n2014-02-28 12:30:00,15.0567\n2014-02-28 12:35:00,13.8867\n2014-02-28 12:40:00,15.6533\n2014-02-28 12:45:00,14.9667\n2014-02-28 12:50:00,15.5567\n2014-02-28 12:55:00,13.9733\n2014-02-28 13:00:00,15.07\n2014-02-28 13:05:00,15.02\n2014-02-28 13:10:00,16.17\n2014-02-28 13:15:00,14.5267\n2014-02-28 13:20:00,15.0867\n2014-02-28 13:25:00,14.4433\n2014-02-28 13:30:00,15.4133\n2014-02-28 13:35:00,14.4433\n2014-02-28 13:40:00,15.5667\n2014-02-28 13:45:00,12.2133\n2014-02-28 13:50:00,12.0825\n2014-02-28 13:55:00,14.3333\n2014-02-28 14:00:00,15.0\n2014-02-28 14:05:00,14.4633\n2014-02-28 14:10:00,15.5567\n2014-02-28 14:15:00,14.4833\n2014-02-28 14:20:00,15.4767\n2014-02-28 14:25:00,13.9433\n2014-02-28 14:30:00,15.5567\n"
  },
  {
    "path": "workspace/anomaly_detector/datasets/selected/level_change/rds_cpu_utilization_e47b3b.csv",
    "content": "timestamp,value\n2014-04-10 00:02:00,14.012\n2014-04-10 00:07:00,13.334000000000001\n2014-04-10 00:12:00,15.0\n2014-04-10 00:17:00,13.998\n2014-04-10 00:22:00,14.332\n2014-04-10 00:27:00,15.002\n2014-04-10 00:32:00,13.984000000000002\n2014-04-10 00:37:00,14.674000000000001\n2014-04-10 00:42:00,14.668\n2014-04-10 00:47:00,13.665999999999999\n2014-04-10 00:52:00,13.334000000000001\n2014-04-10 00:57:00,15.046\n2014-04-10 01:02:00,13.332\n2014-04-10 01:07:00,15.0\n2014-04-10 01:12:00,15.0\n2014-04-10 01:17:00,14.368\n2014-04-10 01:22:00,13.665999999999999\n2014-04-10 01:27:00,15.332\n2014-04-10 01:32:00,14.334000000000001\n2014-04-10 01:37:00,14.335999999999999\n2014-04-10 01:42:00,14.0\n2014-04-10 01:47:00,14.332\n2014-04-10 01:52:00,13.332\n2014-04-10 01:57:00,14.998\n2014-04-10 02:02:00,13.665999999999999\n2014-04-10 02:07:00,13.67\n2014-04-10 02:12:00,14.668\n2014-04-10 02:17:00,14.334000000000001\n2014-04-10 02:22:00,14.304\n2014-04-10 02:27:00,15.038\n2014-04-10 02:32:00,13.665999999999999\n2014-04-10 02:37:00,14.334000000000001\n2014-04-10 02:42:00,14.0\n2014-04-10 02:47:00,14.665999999999999\n2014-04-10 02:52:00,13.0\n2014-04-10 02:57:00,14.334000000000001\n2014-04-10 03:02:00,14.658\n2014-04-10 03:07:00,14.0\n2014-04-10 03:12:00,14.318\n2014-04-10 03:17:00,14.277999999999999\n2014-04-10 03:22:00,14.706\n2014-04-10 03:27:00,14.334000000000001\n2014-04-10 03:32:00,14.0\n2014-04-10 03:37:00,14.694\n2014-04-10 03:42:00,14.334000000000001\n2014-04-10 03:47:00,14.002\n2014-04-10 03:52:00,13.716\n2014-04-10 03:57:00,13.962\n2014-04-10 04:02:00,13.998\n2014-04-10 04:07:00,14.002\n2014-04-10 04:12:00,14.0\n2014-04-10 04:17:00,13.332\n2014-04-10 04:22:00,14.335999999999999\n2014-04-10 04:27:00,13.708\n2014-04-10 04:32:00,13.998\n2014-04-10 04:37:00,13.664000000000001\n2014-04-10 04:42:00,13.665999999999999\n2014-04-10 04:47:00,13.958\n2014-04-10 04:52:00,13.716\n2014-04-10 04:57:00,14.306\n2014-04-10 05:02:00,13.332\n2014-04-10 05:07:00,13.618\n2014-04-10 05:12:00,13.665999999999999\n2014-04-10 05:17:00,14.0\n2014-04-10 05:22:00,14.0\n2014-04-10 05:27:00,13.334000000000001\n2014-04-10 05:32:00,13.998\n2014-04-10 05:37:00,14.0\n2014-04-10 05:42:00,14.668\n2014-04-10 05:47:00,13.665999999999999\n2014-04-10 05:52:00,13.668\n2014-04-10 05:57:00,14.332\n2014-04-10 06:02:00,14.334000000000001\n2014-04-10 06:07:00,13.335999999999999\n2014-04-10 06:12:00,13.665999999999999\n2014-04-10 06:17:00,13.994000000000002\n2014-04-10 06:22:00,14.056\n2014-04-10 06:27:00,14.636\n2014-04-10 06:32:00,14.384\n2014-04-10 06:37:00,13.308\n2014-04-10 06:42:00,14.334000000000001\n2014-04-10 06:47:00,13.334000000000001\n2014-04-10 06:52:00,14.366\n2014-04-10 06:57:00,14.0\n2014-04-10 07:02:00,14.0\n2014-04-10 07:07:00,13.668\n2014-04-10 07:12:00,14.0\n2014-04-10 07:17:00,13.74\n2014-04-10 07:22:00,13.968\n2014-04-10 07:27:00,13.665999999999999\n2014-04-10 07:32:00,14.0\n2014-04-10 07:37:00,13.33\n2014-04-10 07:42:00,14.0\n2014-04-10 07:47:00,13.952\n2014-04-10 07:52:00,16.0\n2014-04-10 07:57:00,14.0\n2014-04-10 08:02:00,13.344000000000001\n2014-04-10 08:07:00,13.668\n2014-04-10 08:12:00,14.0\n2014-04-10 08:17:00,13.334000000000001\n2014-04-10 08:22:00,14.668\n2014-04-10 08:27:00,14.084000000000001\n2014-04-10 08:32:00,13.645999999999999\n2014-04-10 08:37:00,13.334000000000001\n2014-04-10 08:42:00,14.0\n2014-04-10 08:47:00,13.0\n2014-04-10 08:52:00,13.665999999999999\n2014-04-10 08:57:00,14.334000000000001\n2014-04-10 09:02:00,13.665999999999999\n2014-04-10 09:07:00,14.29\n2014-04-10 09:12:00,14.0\n2014-04-10 09:17:00,13.386\n2014-04-10 09:22:00,14.0\n2014-04-10 09:27:00,13.658\n2014-04-10 09:32:00,13.318\n2014-04-10 09:37:00,13.665999999999999\n2014-04-10 09:42:00,13.34\n2014-04-10 09:47:00,13.334000000000001\n2014-04-10 09:52:00,13.665999999999999\n2014-04-10 09:57:00,12.998\n2014-04-10 10:02:00,14.332\n2014-04-10 10:07:00,13.668\n2014-04-10 10:12:00,13.665999999999999\n2014-04-10 10:17:00,13.332\n2014-04-10 10:22:00,13.322000000000001\n2014-04-10 10:27:00,13.668\n2014-04-10 10:32:00,14.0\n2014-04-10 10:37:00,13.332\n2014-04-10 10:42:00,14.0\n2014-04-10 10:47:00,13.286\n2014-04-10 10:52:00,12.998\n2014-04-10 10:57:00,13.665999999999999\n2014-04-10 11:02:00,13.665999999999999\n2014-04-10 11:07:00,13.334000000000001\n2014-04-10 11:12:00,13.69\n2014-04-10 11:17:00,13.286\n2014-04-10 11:22:00,14.334000000000001\n2014-04-10 11:27:00,12.99\n2014-04-10 11:32:00,13.722000000000001\n2014-04-10 11:37:00,13.308\n2014-04-10 11:42:00,13.332\n2014-04-10 11:47:00,13.665999999999999\n2014-04-10 11:52:00,13.022\n2014-04-10 11:57:00,13.952\n2014-04-10 12:02:00,12.992\n2014-04-10 12:07:00,13.704\n2014-04-10 12:12:00,13.665999999999999\n2014-04-10 12:17:00,13.38\n2014-04-10 12:22:00,14.315999999999999\n2014-04-10 12:27:00,14.0\n2014-04-10 12:32:00,14.0\n2014-04-10 12:37:00,14.332\n2014-04-10 12:42:00,13.332\n2014-04-10 12:47:00,13.99\n2014-04-10 12:52:00,13.714\n2014-04-10 12:57:00,13.962\n2014-04-10 13:02:00,13.334000000000001\n2014-04-10 13:07:00,14.0\n2014-04-10 13:12:00,13.024000000000001\n2014-04-10 13:17:00,14.306\n2014-04-10 13:22:00,13.34\n2014-04-10 13:27:00,13.974\n2014-04-10 13:32:00,14.04\n2014-04-10 13:37:00,14.0\n2014-04-10 13:42:00,13.962\n2014-04-10 13:47:00,14.0\n2014-04-10 13:52:00,13.332\n2014-04-10 13:57:00,14.364\n2014-04-10 14:02:00,12.65\n2014-04-10 14:07:00,13.33\n2014-04-10 14:12:00,13.35\n2014-04-10 14:17:00,13.998\n2014-04-10 14:22:00,13.332\n2014-04-10 14:27:00,14.665999999999999\n2014-04-10 14:32:00,14.0\n2014-04-10 14:37:00,14.002\n2014-04-10 14:42:00,12.655999999999999\n2014-04-10 14:47:00,14.335999999999999\n2014-04-10 14:52:00,13.06\n2014-04-10 14:57:00,14.324000000000002\n2014-04-10 15:02:00,12.984000000000002\n2014-04-10 15:07:00,13.335999999999999\n2014-04-10 15:12:00,13.332\n2014-04-10 15:17:00,13.988\n2014-04-10 15:22:00,13.332\n2014-04-10 15:27:00,14.334000000000001\n2014-04-10 15:32:00,13.31\n2014-04-10 15:37:00,14.332\n2014-04-10 15:42:00,13.998\n2014-04-10 15:47:00,13.668\n2014-04-10 15:52:00,13.332\n2014-04-10 15:57:00,14.368\n2014-04-10 16:02:00,13.332\n2014-04-10 16:07:00,15.33\n2014-04-10 16:12:00,13.332\n2014-04-10 16:17:00,13.668\n2014-04-10 16:22:00,14.0\n2014-04-10 16:27:00,14.63\n2014-04-10 16:32:00,13.706\n2014-04-10 16:37:00,13.0\n2014-04-10 16:42:00,14.0\n2014-04-10 16:47:00,13.334000000000001\n2014-04-10 16:52:00,13.33\n2014-04-10 16:57:00,13.332\n2014-04-10 17:02:00,13.665999999999999\n2014-04-10 17:07:00,13.665999999999999\n2014-04-10 17:12:00,13.332\n2014-04-10 17:17:00,12.962\n2014-04-10 17:22:00,14.674000000000001\n2014-04-10 17:27:00,14.0\n2014-04-10 17:32:00,14.0\n2014-04-10 17:37:00,14.002\n2014-04-10 17:42:00,14.0\n2014-04-10 17:47:00,13.046\n2014-04-10 17:52:00,13.672\n2014-04-10 17:57:00,14.0\n2014-04-10 18:02:00,13.322000000000001\n2014-04-10 18:07:00,13.332\n2014-04-10 18:12:00,13.332\n2014-04-10 18:17:00,13.334000000000001\n2014-04-10 18:22:00,14.0\n2014-04-10 18:27:00,14.034\n2014-04-10 18:32:00,13.665999999999999\n2014-04-10 18:37:00,13.964\n2014-04-10 18:42:00,13.332\n2014-04-10 18:47:00,13.334000000000001\n2014-04-10 18:52:00,13.332\n2014-04-10 18:57:00,13.655999999999999\n2014-04-10 19:02:00,13.665999999999999\n2014-04-10 19:07:00,13.0\n2014-04-10 19:12:00,14.345999999999998\n2014-04-10 19:17:00,12.668\n2014-04-10 19:22:00,13.665999999999999\n2014-04-10 19:27:00,13.325999999999999\n2014-04-10 19:32:00,13.978\n2014-04-10 19:37:00,13.668\n2014-04-10 19:42:00,14.334000000000001\n2014-04-10 19:47:00,13.964\n2014-04-10 19:52:00,13.704\n2014-04-10 19:57:00,14.0\n2014-04-10 20:02:00,13.665999999999999\n2014-04-10 20:07:00,13.345999999999998\n2014-04-10 20:12:00,13.69\n2014-04-10 20:17:00,12.645999999999999\n2014-04-10 20:22:00,13.668\n2014-04-10 20:27:00,13.0\n2014-04-10 20:32:00,13.332\n2014-04-10 20:37:00,13.964\n2014-04-10 20:42:00,14.334000000000001\n2014-04-10 20:47:00,13.29\n2014-04-10 20:52:00,13.332\n2014-04-10 20:57:00,14.334000000000001\n2014-04-10 21:02:00,12.998\n2014-04-10 21:07:00,13.334000000000001\n2014-04-10 21:12:00,14.334000000000001\n2014-04-10 21:17:00,14.102\n2014-04-10 21:22:00,14.017999999999999\n2014-04-10 21:27:00,14.28\n2014-04-10 21:32:00,13.95\n2014-04-10 21:37:00,13.67\n2014-04-10 21:42:00,14.0\n2014-04-10 21:47:00,12.665999999999999\n2014-04-10 21:52:00,14.0\n2014-04-10 21:57:00,13.665999999999999\n2014-04-10 22:02:00,13.332\n2014-04-10 22:07:00,13.665999999999999\n2014-04-10 22:12:00,13.044\n2014-04-10 22:17:00,13.308\n2014-04-10 22:22:00,13.665999999999999\n2014-04-10 22:27:00,14.0\n2014-04-10 22:32:00,13.665999999999999\n2014-04-10 22:37:00,14.014000000000001\n2014-04-10 22:42:00,14.668\n2014-04-10 22:47:00,13.665999999999999\n2014-04-10 22:52:00,13.332\n2014-04-10 22:57:00,15.334000000000001\n2014-04-10 23:02:00,13.332\n2014-04-10 23:07:00,14.334000000000001\n2014-04-10 23:12:00,14.0\n2014-04-10 23:17:00,13.668\n2014-04-10 23:22:00,14.0\n2014-04-10 23:27:00,14.0\n2014-04-10 23:32:00,12.998\n2014-04-10 23:37:00,14.0\n2014-04-10 23:42:00,12.998\n2014-04-10 23:47:00,14.017999999999999\n2014-04-10 23:52:00,12.998\n2014-04-10 23:57:00,14.165999999999999\n2014-04-11 00:02:00,13.0\n2014-04-11 00:07:00,14.335999999999999\n2014-04-11 00:12:00,13.665999999999999\n2014-04-11 00:17:00,13.668\n2014-04-11 00:22:00,13.998\n2014-04-11 00:27:00,14.332\n2014-04-11 00:32:00,12.998\n2014-04-11 00:37:00,13.334000000000001\n2014-04-11 00:42:00,13.665999999999999\n2014-04-11 00:47:00,13.335999999999999\n2014-04-11 00:52:00,13.665999999999999\n2014-04-11 00:57:00,14.302\n2014-04-11 01:02:00,12.998\n2014-04-11 01:07:00,14.332\n2014-04-11 01:12:00,13.665999999999999\n2014-04-11 01:17:00,13.335999999999999\n2014-04-11 01:22:00,13.332\n2014-04-11 01:27:00,13.642000000000001\n2014-04-11 01:32:00,13.665999999999999\n2014-04-11 01:37:00,13.612\n2014-04-11 01:42:00,13.966\n2014-04-11 01:47:00,13.664000000000001\n2014-04-11 01:52:00,14.334000000000001\n2014-04-11 01:57:00,14.668\n2014-04-11 02:02:00,14.012\n2014-04-11 02:07:00,13.665999999999999\n2014-04-11 02:12:00,14.312000000000001\n2014-04-11 02:17:00,13.334000000000001\n2014-04-11 02:22:00,14.0\n2014-04-11 02:27:00,13.634\n2014-04-11 02:32:00,13.665999999999999\n2014-04-11 02:37:00,14.347999999999999\n2014-04-11 02:42:00,14.318\n2014-04-11 02:47:00,13.708\n2014-04-11 02:52:00,14.334000000000001\n2014-04-11 02:57:00,13.652000000000001\n2014-04-11 03:02:00,14.0\n2014-04-11 03:07:00,13.0\n2014-04-11 03:12:00,13.665999999999999\n2014-04-11 03:17:00,12.665999999999999\n2014-04-11 03:22:00,13.665999999999999\n2014-04-11 03:27:00,14.334000000000001\n2014-04-11 03:32:00,14.0\n2014-04-11 03:37:00,14.334000000000001\n2014-04-11 03:42:00,14.0\n2014-04-11 03:47:00,13.668\n2014-04-11 03:52:00,14.0\n2014-04-11 03:57:00,13.665999999999999\n2014-04-11 04:02:00,13.665999999999999\n2014-04-11 04:07:00,13.334000000000001\n2014-04-11 04:12:00,13.665999999999999\n2014-04-11 04:17:00,13.626\n2014-04-11 04:22:00,13.665999999999999\n2014-04-11 04:27:00,13.665999999999999\n2014-04-11 04:32:00,13.665999999999999\n2014-04-11 04:37:00,13.0\n2014-04-11 04:42:00,14.0\n2014-04-11 04:47:00,13.334000000000001\n2014-04-11 04:52:00,14.655999999999999\n2014-04-11 04:57:00,13.665999999999999\n2014-04-11 05:02:00,13.332\n2014-04-11 05:07:00,13.662\n2014-04-11 05:12:00,13.345999999999998\n2014-04-11 05:17:00,13.392000000000001\n2014-04-11 05:22:00,13.65\n2014-04-11 05:27:00,13.665999999999999\n2014-04-11 05:32:00,12.998\n2014-04-11 05:37:00,13.334000000000001\n2014-04-11 05:42:00,13.665999999999999\n2014-04-11 05:47:00,13.334000000000001\n2014-04-11 05:52:00,13.332\n2014-04-11 05:57:00,13.665999999999999\n2014-04-11 06:02:00,13.644\n2014-04-11 06:07:00,13.0\n2014-04-11 06:12:00,13.332\n2014-04-11 06:17:00,13.655999999999999\n2014-04-11 06:22:00,13.332\n2014-04-11 06:27:00,13.665999999999999\n2014-04-11 06:32:00,14.048\n2014-04-11 06:37:00,13.974\n2014-04-11 06:42:00,13.665999999999999\n2014-04-11 06:47:00,14.0\n2014-04-11 06:52:00,14.0\n2014-04-11 06:57:00,13.328\n2014-04-11 07:02:00,13.332\n2014-04-11 07:07:00,12.662\n2014-04-11 07:12:00,13.716\n2014-04-11 07:17:00,13.64\n2014-04-11 07:22:00,13.332\n2014-04-11 07:27:00,13.665999999999999\n2014-04-11 07:32:00,13.332\n2014-04-11 07:37:00,13.324000000000002\n2014-04-11 07:42:00,13.972000000000001\n2014-04-11 07:47:00,13.042\n2014-04-11 07:52:00,15.31\n2014-04-11 07:57:00,14.332\n2014-04-11 08:02:00,13.665999999999999\n2014-04-11 08:07:00,13.334000000000001\n2014-04-11 08:12:00,14.0\n2014-04-11 08:17:00,13.0\n2014-04-11 08:22:00,14.334000000000001\n2014-04-11 08:27:00,13.628\n2014-04-11 08:32:00,13.704\n2014-04-11 08:37:00,13.668\n2014-04-11 08:42:00,13.332\n2014-04-11 08:47:00,13.668\n2014-04-11 08:52:00,14.0\n2014-04-11 08:57:00,13.332\n2014-04-11 09:02:00,13.686\n2014-04-11 09:07:00,13.302\n2014-04-11 09:12:00,13.665999999999999\n2014-04-11 09:17:00,13.334000000000001\n2014-04-11 09:22:00,13.665999999999999\n2014-04-11 09:27:00,14.0\n2014-04-11 09:32:00,13.332\n2014-04-11 09:37:00,13.364\n2014-04-11 09:42:00,13.968\n2014-04-11 09:47:00,12.668\n2014-04-11 09:52:00,13.332\n2014-04-11 09:57:00,14.052\n2014-04-11 10:02:00,13.366\n2014-04-11 10:07:00,12.968\n2014-04-11 10:12:00,13.672\n2014-04-11 10:17:00,13.334000000000001\n2014-04-11 10:22:00,14.0\n2014-04-11 10:27:00,13.0\n2014-04-11 10:32:00,14.027999999999999\n2014-04-11 10:37:00,13.296\n2014-04-11 10:42:00,14.022\n2014-04-11 10:47:00,12.972000000000001\n2014-04-11 10:52:00,13.35\n2014-04-11 10:57:00,14.0\n2014-04-11 11:02:00,13.0\n2014-04-11 11:07:00,14.29\n2014-04-11 11:12:00,13.366\n2014-04-11 11:17:00,14.0\n2014-04-11 11:22:00,13.665999999999999\n2014-04-11 11:27:00,14.325999999999999\n2014-04-11 11:32:00,13.01\n2014-04-11 11:37:00,13.994000000000002\n2014-04-11 11:42:00,13.332\n2014-04-11 11:47:00,13.67\n2014-04-11 11:52:00,13.334000000000001\n2014-04-11 11:57:00,13.668\n2014-04-11 12:02:00,13.332\n2014-04-11 12:07:00,14.0\n2014-04-11 12:12:00,13.315999999999999\n2014-04-11 12:17:00,14.304\n2014-04-11 12:22:00,13.332\n2014-04-11 12:27:00,14.0\n2014-04-11 12:32:00,13.0\n2014-04-11 12:37:00,14.332\n2014-04-11 12:42:00,13.322000000000001\n2014-04-11 12:47:00,13.668\n2014-04-11 12:52:00,13.677999999999999\n2014-04-11 12:57:00,14.0\n2014-04-11 13:02:00,13.015999999999998\n2014-04-11 13:07:00,14.002\n2014-04-11 13:12:00,13.665999999999999\n2014-04-11 13:17:00,14.0\n2014-04-11 13:22:00,13.665999999999999\n2014-04-11 13:27:00,14.315999999999999\n2014-04-11 13:32:00,12.668\n2014-04-11 13:37:00,13.668\n2014-04-11 13:42:00,13.332\n2014-04-11 13:47:00,13.334000000000001\n2014-04-11 13:52:00,13.35\n2014-04-11 13:57:00,13.665999999999999\n2014-04-11 14:02:00,12.982000000000001\n2014-04-11 14:07:00,13.668\n2014-04-11 14:12:00,14.0\n2014-04-11 14:17:00,13.335999999999999\n2014-04-11 14:22:00,13.015999999999998\n2014-04-11 14:27:00,13.655999999999999\n2014-04-11 14:32:00,13.334000000000001\n2014-04-11 14:37:00,14.334000000000001\n2014-04-11 14:42:00,13.65\n2014-04-11 14:47:00,13.0\n2014-04-11 14:52:00,13.665999999999999\n2014-04-11 14:57:00,13.665999999999999\n2014-04-11 15:02:00,13.332\n2014-04-11 15:07:00,13.63\n2014-04-11 15:12:00,14.368\n2014-04-11 15:17:00,12.665999999999999\n2014-04-11 15:22:00,13.332\n2014-04-11 15:27:00,13.665999999999999\n2014-04-11 15:32:00,13.665999999999999\n2014-04-11 15:37:00,13.334000000000001\n2014-04-11 15:42:00,13.332\n2014-04-11 15:47:00,13.415999999999999\n2014-04-11 15:52:00,13.3\n2014-04-11 15:57:00,13.332\n2014-04-11 16:02:00,13.984000000000002\n2014-04-11 16:07:00,13.0\n2014-04-11 16:12:00,14.334000000000001\n2014-04-11 16:17:00,13.665999999999999\n2014-04-11 16:22:00,14.0\n2014-04-11 16:27:00,13.328\n2014-04-11 16:32:00,13.668\n2014-04-11 16:37:00,13.0\n2014-04-11 16:42:00,14.0\n2014-04-11 16:47:00,13.0\n2014-04-11 16:52:00,13.702\n2014-04-11 16:57:00,13.974\n2014-04-11 17:02:00,13.332\n2014-04-11 17:07:00,14.002\n2014-04-11 17:12:00,13.332\n2014-04-11 17:17:00,12.628\n2014-04-11 17:22:00,13.665999999999999\n2014-04-11 17:27:00,13.992\n2014-04-11 17:32:00,13.665999999999999\n2014-04-11 17:37:00,13.665999999999999\n2014-04-11 17:42:00,13.665999999999999\n2014-04-11 17:47:00,12.962\n2014-04-11 17:52:00,13.332\n2014-04-11 17:57:00,14.0\n2014-04-11 18:02:00,14.664000000000001\n2014-04-11 18:07:00,14.334000000000001\n2014-04-11 18:12:00,13.665999999999999\n2014-04-11 18:17:00,13.335999999999999\n2014-04-11 18:22:00,13.0\n2014-04-11 18:27:00,14.0\n2014-04-11 18:32:00,12.988\n2014-04-11 18:37:00,13.334000000000001\n2014-04-11 18:42:00,13.644\n2014-04-11 18:47:00,13.634\n2014-04-11 18:52:00,12.664000000000001\n2014-04-11 18:57:00,14.29\n2014-04-11 19:02:00,12.998\n2014-04-11 19:07:00,13.67\n2014-04-11 19:12:00,13.378\n2014-04-11 19:17:00,13.626\n2014-04-11 19:22:00,13.332\n2014-04-11 19:27:00,14.334000000000001\n2014-04-11 19:32:00,13.044\n2014-04-11 19:37:00,13.636\n2014-04-11 19:42:00,13.334000000000001\n2014-04-11 19:47:00,13.702\n2014-04-11 19:52:00,12.677999999999999\n2014-04-11 19:57:00,13.998\n2014-04-11 20:02:00,12.998\n2014-04-11 20:07:00,13.334000000000001\n2014-04-11 20:12:00,13.664000000000001\n2014-04-11 20:17:00,14.388\n2014-04-11 20:22:00,14.05\n2014-04-11 20:27:00,13.634\n2014-04-11 20:32:00,13.332\n2014-04-11 20:37:00,12.958\n2014-04-11 20:42:00,13.334000000000001\n2014-04-11 20:47:00,14.0\n2014-04-11 20:52:00,14.0\n2014-04-11 20:57:00,13.677999999999999\n2014-04-11 21:02:00,14.0\n2014-04-11 21:07:00,13.0\n2014-04-11 21:12:00,14.0\n2014-04-11 21:17:00,13.332\n2014-04-11 21:22:00,14.334000000000001\n2014-04-11 21:27:00,13.68\n2014-04-11 21:32:00,13.998\n2014-04-11 21:37:00,13.334000000000001\n2014-04-11 21:42:00,14.0\n2014-04-11 21:47:00,13.0\n2014-04-11 21:52:00,13.718\n2014-04-11 21:57:00,13.674000000000001\n2014-04-11 22:02:00,13.634\n2014-04-11 22:07:00,13.334000000000001\n2014-04-11 22:12:00,14.668\n2014-04-11 22:17:00,13.665999999999999\n2014-04-11 22:22:00,13.39\n2014-04-11 22:27:00,13.306\n2014-04-11 22:32:00,14.0\n2014-04-11 22:37:00,13.354000000000001\n2014-04-11 22:42:00,14.372\n2014-04-11 22:47:00,13.334000000000001\n2014-04-11 22:52:00,13.645999999999999\n2014-04-11 22:57:00,13.332\n2014-04-11 23:02:00,14.005999999999998\n2014-04-11 23:07:00,13.334000000000001\n2014-04-11 23:12:00,14.664000000000001\n2014-04-11 23:17:00,13.334000000000001\n2014-04-11 23:22:00,14.0\n2014-04-11 23:27:00,13.665999999999999\n2014-04-11 23:32:00,13.332\n2014-04-11 23:37:00,13.668\n2014-04-11 23:42:00,13.35\n2014-04-11 23:47:00,13.0\n2014-04-11 23:52:00,14.0\n2014-04-11 23:57:00,13.526\n2014-04-12 00:02:00,13.332\n2014-04-12 00:07:00,13.0\n2014-04-12 00:12:00,13.665999999999999\n2014-04-12 00:17:00,13.0\n2014-04-12 00:22:00,13.998\n2014-04-12 00:27:00,13.372\n2014-04-12 00:32:00,14.0\n2014-04-12 00:37:00,13.0\n2014-04-12 00:42:00,13.332\n2014-04-12 00:47:00,13.665999999999999\n2014-04-12 00:52:00,13.674000000000001\n2014-04-12 00:57:00,13.332\n2014-04-12 01:02:00,13.0\n2014-04-12 01:07:00,13.665999999999999\n2014-04-12 01:12:00,14.334000000000001\n2014-04-12 01:17:00,13.0\n2014-04-12 01:22:00,13.665999999999999\n2014-04-12 01:27:00,13.322000000000001\n2014-04-12 01:32:00,13.665999999999999\n2014-04-12 01:37:00,13.0\n2014-04-12 01:42:00,14.334000000000001\n2014-04-12 01:47:00,13.0\n2014-04-12 01:52:00,14.334000000000001\n2014-04-12 01:57:00,14.0\n2014-04-12 02:02:00,13.34\n2014-04-12 02:07:00,13.332\n2014-04-12 02:12:00,13.0\n2014-04-12 02:17:00,13.334000000000001\n2014-04-12 02:22:00,14.0\n2014-04-12 02:27:00,14.668\n2014-04-12 02:32:00,13.665999999999999\n2014-04-12 02:37:00,14.334000000000001\n2014-04-12 02:42:00,13.655999999999999\n2014-04-12 02:47:00,13.0\n2014-04-12 02:52:00,13.998\n2014-04-12 02:57:00,14.332\n2014-04-12 03:02:00,12.665999999999999\n2014-04-12 03:07:00,13.594000000000001\n2014-04-12 03:12:00,13.665999999999999\n2014-04-12 03:17:00,13.665999999999999\n2014-04-12 03:22:00,12.998\n2014-04-12 03:27:00,14.668\n2014-04-12 03:32:00,13.015999999999998\n2014-04-12 03:37:00,14.002\n2014-04-12 03:42:00,12.985999999999999\n2014-04-12 03:47:00,14.334000000000001\n2014-04-12 03:52:00,13.0\n2014-04-12 03:57:00,14.335999999999999\n2014-04-12 04:02:00,12.998\n2014-04-12 04:07:00,13.708\n2014-04-12 04:12:00,13.296\n2014-04-12 04:17:00,14.332\n2014-04-12 04:22:00,12.998\n2014-04-12 04:27:00,13.668\n2014-04-12 04:32:00,13.665999999999999\n2014-04-12 04:37:00,13.64\n2014-04-12 04:42:00,13.332\n2014-04-12 04:47:00,14.034\n2014-04-12 04:52:00,12.665999999999999\n2014-04-12 04:57:00,14.334000000000001\n2014-04-12 05:02:00,13.332\n2014-04-12 05:07:00,13.335999999999999\n2014-04-12 05:12:00,13.668\n2014-04-12 05:17:00,13.335999999999999\n2014-04-12 05:22:00,13.716\n2014-04-12 05:27:00,13.274000000000001\n2014-04-12 05:32:00,13.032\n2014-04-12 05:37:00,13.332\n2014-04-12 05:42:00,13.665999999999999\n2014-04-12 05:47:00,13.0\n2014-04-12 05:52:00,13.665999999999999\n2014-04-12 05:57:00,13.332\n2014-04-12 06:02:00,13.332\n2014-04-12 06:07:00,13.332\n2014-04-12 06:12:00,14.318\n2014-04-12 06:17:00,13.29\n2014-04-12 06:22:00,12.998\n2014-04-12 06:27:00,14.0\n2014-04-12 06:32:00,13.332\n2014-04-12 06:37:00,13.334000000000001\n2014-04-12 06:42:00,14.0\n2014-04-12 06:47:00,14.332\n2014-04-12 06:52:00,14.0\n2014-04-12 06:57:00,13.634\n2014-04-12 07:02:00,13.37\n2014-04-12 07:07:00,13.38\n2014-04-12 07:12:00,13.665999999999999\n2014-04-12 07:17:00,13.0\n2014-04-12 07:22:00,14.05\n2014-04-12 07:27:00,12.972000000000001\n2014-04-12 07:32:00,12.998\n2014-04-12 07:37:00,13.655999999999999\n2014-04-12 07:42:00,13.332\n2014-04-12 07:47:00,13.665999999999999\n2014-04-12 07:52:00,14.0\n2014-04-12 07:57:00,16.0\n2014-04-12 08:02:00,13.665999999999999\n2014-04-12 08:07:00,13.334000000000001\n2014-04-12 08:12:00,13.734000000000002\n2014-04-12 08:17:00,13.308\n2014-04-12 08:22:00,13.332\n2014-04-12 08:27:00,13.665999999999999\n2014-04-12 08:32:00,13.332\n2014-04-12 08:37:00,13.668\n2014-04-12 08:42:00,13.665999999999999\n2014-04-12 08:47:00,13.334000000000001\n2014-04-12 08:52:00,13.65\n2014-04-12 08:57:00,13.724\n2014-04-12 09:02:00,14.334000000000001\n2014-04-12 09:07:00,13.052\n2014-04-12 09:12:00,14.0\n2014-04-12 09:17:00,13.0\n2014-04-12 09:22:00,14.33\n2014-04-12 09:27:00,13.332\n2014-04-12 09:32:00,13.332\n2014-04-12 09:37:00,14.014000000000001\n2014-04-12 09:42:00,13.665999999999999\n2014-04-12 09:47:00,13.0\n2014-04-12 09:52:00,12.998\n2014-04-12 09:57:00,13.665999999999999\n2014-04-12 10:02:00,14.0\n2014-04-12 10:07:00,13.334000000000001\n2014-04-12 10:12:00,13.668\n2014-04-12 10:17:00,13.334000000000001\n2014-04-12 10:22:00,13.332\n2014-04-12 10:27:00,13.718\n2014-04-12 10:32:00,13.665999999999999\n2014-04-12 10:37:00,13.334000000000001\n2014-04-12 10:42:00,14.002\n2014-04-12 10:47:00,13.0\n2014-04-12 10:52:00,13.995999999999999\n2014-04-12 10:57:00,13.998\n2014-04-12 11:02:00,13.655999999999999\n2014-04-12 11:07:00,14.328\n2014-04-12 11:12:00,13.332\n2014-04-12 11:17:00,13.334000000000001\n2014-04-12 11:22:00,12.998\n2014-04-12 11:27:00,13.334000000000001\n2014-04-12 11:32:00,13.332\n2014-04-12 11:37:00,13.665999999999999\n2014-04-12 11:42:00,13.332\n2014-04-12 11:47:00,13.334000000000001\n2014-04-12 11:52:00,13.332\n2014-04-12 11:57:00,13.665999999999999\n2014-04-12 12:02:00,12.665999999999999\n2014-04-12 12:07:00,13.334000000000001\n2014-04-12 12:12:00,13.712\n2014-04-12 12:17:00,14.3\n2014-04-12 12:22:00,13.06\n2014-04-12 12:27:00,13.597999999999999\n2014-04-12 12:32:00,13.668\n2014-04-12 12:37:00,13.716\n2014-04-12 12:42:00,13.332\n2014-04-12 12:47:00,13.335999999999999\n2014-04-12 12:52:00,13.315999999999999\n2014-04-12 12:57:00,14.0\n2014-04-12 13:02:00,12.998\n2014-04-12 13:07:00,13.37\n2014-04-12 13:12:00,13.315999999999999\n2014-04-12 13:17:00,14.0\n2014-04-12 13:22:00,12.664000000000001\n2014-04-12 13:27:00,13.658\n2014-04-12 13:32:00,13.315999999999999\n2014-04-12 13:37:00,13.002\n2014-04-12 13:42:00,13.665999999999999\n2014-04-12 13:47:00,13.334000000000001\n2014-04-12 13:52:00,14.046\n2014-04-12 13:57:00,13.008\n2014-04-12 14:02:00,13.665999999999999\n2014-04-12 14:07:00,13.67\n2014-04-12 14:12:00,13.38\n2014-04-12 14:17:00,13.64\n2014-04-12 14:22:00,12.994000000000002\n2014-04-12 14:27:00,12.995999999999999\n2014-04-12 14:32:00,14.017999999999999\n2014-04-12 14:37:00,14.002\n2014-04-12 14:42:00,13.338\n2014-04-12 14:47:00,13.0\n2014-04-12 14:52:00,13.332\n2014-04-12 14:57:00,13.665999999999999\n2014-04-12 15:02:00,13.015999999999998\n2014-04-12 15:07:00,13.334000000000001\n2014-04-12 15:12:00,14.0\n2014-04-12 15:17:00,14.0\n2014-04-12 15:22:00,13.332\n2014-04-12 15:27:00,13.29\n2014-04-12 15:32:00,13.368\n2014-04-12 15:37:00,13.668\n2014-04-12 15:42:00,13.344000000000001\n2014-04-12 15:47:00,13.668\n2014-04-12 15:52:00,13.665999999999999\n2014-04-12 15:57:00,13.332\n2014-04-12 16:02:00,14.334000000000001\n2014-04-12 16:07:00,13.665999999999999\n2014-04-12 16:12:00,14.0\n2014-04-12 16:17:00,13.332\n2014-04-12 16:22:00,12.975999999999999\n2014-04-12 16:27:00,14.0\n2014-04-12 16:32:00,13.665999999999999\n2014-04-12 16:37:00,13.0\n2014-04-12 16:42:00,14.0\n2014-04-12 16:47:00,13.332\n2014-04-12 16:52:00,13.344000000000001\n2014-04-12 16:57:00,13.665999999999999\n2014-04-12 17:02:00,12.984000000000002\n2014-04-12 17:07:00,14.002\n2014-04-12 17:12:00,14.0\n2014-04-12 17:17:00,13.334000000000001\n2014-04-12 17:22:00,13.0\n2014-04-12 17:27:00,14.0\n2014-04-12 17:32:00,12.984000000000002\n2014-04-12 17:37:00,12.662\n2014-04-12 17:42:00,13.665999999999999\n2014-04-12 17:47:00,13.664000000000001\n2014-04-12 17:52:00,12.998\n2014-04-12 17:57:00,14.0\n2014-04-12 18:02:00,13.665999999999999\n2014-04-12 18:07:00,13.335999999999999\n2014-04-12 18:12:00,13.665999999999999\n2014-04-12 18:17:00,13.0\n2014-04-12 18:22:00,13.332\n2014-04-12 18:27:00,14.368\n2014-04-12 18:32:00,14.0\n2014-04-12 18:37:00,13.334000000000001\n2014-04-12 18:42:00,13.31\n2014-04-12 18:47:00,13.668\n2014-04-12 18:52:00,13.332\n2014-04-12 18:57:00,13.662\n2014-04-12 19:02:00,14.0\n2014-04-12 19:07:00,13.334000000000001\n2014-04-12 19:12:00,14.334000000000001\n2014-04-12 19:17:00,13.0\n2014-04-12 19:22:00,13.665999999999999\n2014-04-12 19:27:00,13.334000000000001\n2014-04-12 19:32:00,12.998\n2014-04-12 19:37:00,13.668\n2014-04-12 19:42:00,13.335999999999999\n2014-04-12 19:47:00,13.668\n2014-04-12 19:52:00,12.665999999999999\n2014-04-12 19:57:00,15.334000000000001\n2014-04-12 20:02:00,13.665999999999999\n2014-04-12 20:07:00,13.334000000000001\n2014-04-12 20:12:00,13.332\n2014-04-12 20:17:00,14.0\n2014-04-12 20:22:00,13.372\n2014-04-12 20:27:00,13.968\n2014-04-12 20:32:00,12.998\n2014-04-12 20:37:00,13.668\n2014-04-12 20:42:00,13.665999999999999\n2014-04-12 20:47:00,13.68\n2014-04-12 20:52:00,13.332\n2014-04-12 20:57:00,14.665999999999999\n2014-04-12 21:02:00,12.968\n2014-04-12 21:07:00,14.0\n2014-04-12 21:12:00,12.966\n2014-04-12 21:17:00,14.0\n2014-04-12 21:22:00,13.665999999999999\n2014-04-12 21:27:00,14.334000000000001\n2014-04-12 21:32:00,12.998\n2014-04-12 21:37:00,13.67\n2014-04-12 21:42:00,13.665999999999999\n2014-04-12 21:47:00,13.37\n2014-04-12 21:52:00,13.665999999999999\n2014-04-12 21:57:00,14.332\n2014-04-12 22:02:00,13.0\n2014-04-12 22:07:00,14.342\n2014-04-12 22:12:00,13.665999999999999\n2014-04-12 22:17:00,14.046\n2014-04-12 22:22:00,13.294\n2014-04-12 22:27:00,14.0\n2014-04-12 22:32:00,12.664000000000001\n2014-04-12 22:37:00,13.002\n2014-04-12 22:42:00,13.652000000000001\n2014-04-12 22:47:00,13.668\n2014-04-12 22:52:00,13.332\n2014-04-12 22:57:00,14.322000000000001\n2014-04-12 23:02:00,13.332\n2014-04-12 23:07:00,13.334000000000001\n2014-04-12 23:12:00,13.665999999999999\n2014-04-12 23:17:00,13.668\n2014-04-12 23:22:00,13.334000000000001\n2014-04-12 23:27:00,13.665999999999999\n2014-04-12 23:32:00,14.0\n2014-04-12 23:37:00,13.334000000000001\n2014-04-12 23:42:00,14.71\n2014-04-12 23:47:00,12.665999999999999\n2014-04-12 23:52:00,13.06\n2014-04-12 23:57:00,13.834000000000001\n2014-04-13 00:02:00,12.998\n2014-04-13 00:07:00,13.38\n2014-04-13 00:12:00,13.312000000000001\n2014-04-13 00:17:00,12.99\n2014-04-13 00:22:00,13.665999999999999\n2014-04-13 00:27:00,14.0\n2014-04-13 00:32:00,14.334000000000001\n2014-04-13 00:37:00,13.334000000000001\n2014-04-13 00:42:00,13.012\n2014-04-13 00:47:00,13.334000000000001\n2014-04-13 00:52:00,13.665999999999999\n2014-04-13 00:57:00,13.665999999999999\n2014-04-13 01:02:00,13.665999999999999\n2014-04-13 01:07:00,13.334000000000001\n2014-04-13 01:12:00,14.35\n2014-04-13 01:17:00,14.0\n2014-04-13 01:22:00,13.722000000000001\n2014-04-13 01:27:00,13.968\n2014-04-13 01:32:00,13.332\n2014-04-13 01:37:00,13.332\n2014-04-13 01:42:00,13.334000000000001\n2014-04-13 01:47:00,13.334000000000001\n2014-04-13 01:52:00,13.665999999999999\n2014-04-13 01:57:00,13.626\n2014-04-13 02:02:00,13.665999999999999\n2014-04-13 02:07:00,13.702\n2014-04-13 02:12:00,13.665999999999999\n2014-04-13 02:17:00,14.334000000000001\n2014-04-13 02:22:00,13.665999999999999\n2014-04-13 02:27:00,13.332\n2014-04-13 02:32:00,14.0\n2014-04-13 02:37:00,12.665999999999999\n2014-04-13 02:42:00,14.0\n2014-04-13 02:47:00,13.334000000000001\n2014-04-13 02:52:00,13.334000000000001\n2014-04-13 02:57:00,14.0\n2014-04-13 03:02:00,13.382\n2014-04-13 03:07:00,13.026\n2014-04-13 03:12:00,14.665999999999999\n2014-04-13 03:17:00,14.0\n2014-04-13 03:22:00,13.332\n2014-04-13 03:27:00,13.968\n2014-04-13 03:32:00,13.665999999999999\n2014-04-13 03:37:00,13.0\n2014-04-13 03:42:00,14.0\n2014-04-13 03:47:00,13.372\n2014-04-13 03:52:00,13.294\n2014-04-13 03:57:00,14.302\n2014-04-13 04:02:00,12.984000000000002\n2014-04-13 04:07:00,13.668\n2014-04-13 04:12:00,13.655999999999999\n2014-04-13 04:17:00,12.962\n2014-04-13 04:22:00,14.0\n2014-04-13 04:27:00,13.362\n2014-04-13 04:32:00,13.294\n2014-04-13 04:37:00,13.334000000000001\n2014-04-13 04:42:00,13.668\n2014-04-13 04:47:00,13.0\n2014-04-13 04:52:00,13.332\n2014-04-13 04:57:00,13.706\n2014-04-13 05:02:00,13.294\n2014-04-13 05:07:00,13.665999999999999\n2014-04-13 05:12:00,13.0\n2014-04-13 05:17:00,14.0\n2014-04-13 05:22:00,12.665999999999999\n2014-04-13 05:27:00,13.334000000000001\n2014-04-13 05:32:00,12.664000000000001\n2014-04-13 05:37:00,13.67\n2014-04-13 05:42:00,13.665999999999999\n2014-04-13 05:47:00,13.37\n2014-04-13 05:52:00,12.665999999999999\n2014-04-13 05:57:00,14.002\n2014-04-13 06:02:00,13.665999999999999\n2014-04-13 06:07:00,13.335999999999999\n2014-04-13 06:12:00,13.665999999999999\n2014-04-13 06:17:00,13.002\n2014-04-13 06:22:00,13.665999999999999\n2014-04-13 06:27:00,13.665999999999999\n2014-04-13 06:32:00,12.998\n2014-04-13 06:37:00,14.374\n2014-04-13 06:42:00,13.665999999999999\n2014-04-13 06:47:00,13.706\n2014-04-13 06:52:00,76.23\n2014-04-13 06:57:00,65.835\n2014-04-13 07:02:00,21.666\n2014-04-13 07:07:00,17.668\n2014-04-13 07:12:00,16.668\n2014-04-13 07:17:00,16.666\n2014-04-13 07:22:00,15.668\n2014-04-13 07:27:00,17.0\n2014-04-13 07:32:00,15.665999999999999\n2014-04-13 07:37:00,16.296\n2014-04-13 07:42:00,16.336\n2014-04-13 07:47:00,16.668\n2014-04-13 07:52:00,17.334\n2014-04-13 07:57:00,18.334\n2014-04-13 08:02:00,16.652\n2014-04-13 08:07:00,16.0\n2014-04-13 08:12:00,16.738\n2014-04-13 08:17:00,16.62\n2014-04-13 08:22:00,16.336\n2014-04-13 08:27:00,16.668\n2014-04-13 08:32:00,16.012\n2014-04-13 08:37:00,16.0\n2014-04-13 08:42:00,17.018\n2014-04-13 08:47:00,16.334\n2014-04-13 08:52:00,16.392\n2014-04-13 08:57:00,15.958\n2014-04-13 09:02:00,17.0\n2014-04-13 09:07:00,16.334\n2014-04-13 09:12:00,17.0\n2014-04-13 09:17:00,17.0\n2014-04-13 09:22:00,16.334\n2014-04-13 09:27:00,16.334\n2014-04-13 09:32:00,17.012\n2014-04-13 09:37:00,16.334\n2014-04-13 09:42:00,16.32\n2014-04-13 09:47:00,16.334\n2014-04-13 09:52:00,16.668\n2014-04-13 09:57:00,16.666\n2014-04-13 10:02:00,16.392\n2014-04-13 10:07:00,16.298\n2014-04-13 10:12:00,16.334\n2014-04-13 10:17:00,16.666\n2014-04-13 10:22:00,16.67\n2014-04-13 10:27:00,16.334\n2014-04-13 10:32:00,16.336\n2014-04-13 10:37:00,16.666\n2014-04-13 10:42:00,16.666\n2014-04-13 10:47:00,16.042\n2014-04-13 10:52:00,16.334\n2014-04-13 10:57:00,16.334\n2014-04-13 11:02:00,16.336\n2014-04-13 11:07:00,16.988\n2014-04-13 11:12:00,16.666\n2014-04-13 11:17:00,16.0\n2014-04-13 11:22:00,16.668\n2014-04-13 11:27:00,16.656\n2014-04-13 11:32:00,16.352\n2014-04-13 11:37:00,16.002\n2014-04-13 11:42:00,16.668\n2014-04-13 11:47:00,16.0\n2014-04-13 11:52:00,16.002\n2014-04-13 11:57:00,17.0\n2014-04-13 12:02:00,16.336\n2014-04-13 12:07:00,16.666\n2014-04-13 12:12:00,16.0\n2014-04-13 12:17:00,15.998\n2014-04-13 12:22:00,16.334\n2014-04-13 12:27:00,16.0\n2014-04-13 12:32:00,16.666\n2014-04-13 12:37:00,15.63\n2014-04-13 12:42:00,17.392\n2014-04-13 12:47:00,17.33\n2014-04-13 12:52:00,16.0\n2014-04-13 12:57:00,16.668\n2014-04-13 13:02:00,16.605999999999998\n2014-04-13 13:07:00,16.38\n2014-04-13 13:12:00,17.668\n2014-04-13 13:17:00,15.668\n2014-04-13 13:22:00,16.668\n2014-04-13 13:27:00,15.655999999999999\n2014-04-13 13:32:00,16.65\n2014-04-13 13:37:00,16.332\n2014-04-13 13:42:00,16.666\n2014-04-13 13:47:00,15.998\n2014-04-13 13:52:00,16.67\n2014-04-13 13:57:00,17.002\n2014-04-13 14:02:00,16.317999999999998\n2014-04-13 14:07:00,16.332\n2014-04-13 14:12:00,16.334\n2014-04-13 14:17:00,17.0\n2014-04-13 14:22:00,15.668\n2014-04-13 14:27:00,17.334\n2014-04-13 14:32:00,16.668\n2014-04-13 14:37:00,16.666\n2014-04-13 14:42:00,16.002\n2014-04-13 14:47:00,17.0\n2014-04-13 14:52:00,15.684000000000001\n2014-04-13 14:57:00,17.0\n2014-04-13 15:02:00,16.018\n2014-04-13 15:07:00,16.666\n2014-04-13 15:12:00,16.0\n2014-04-13 15:17:00,17.046\n2014-04-13 15:22:00,15.958\n2014-04-13 15:27:00,16.31\n2014-04-13 15:32:00,17.0\n2014-04-13 15:37:00,17.0\n2014-04-13 15:42:00,16.0\n2014-04-13 15:47:00,17.384\n2014-04-13 15:52:00,16.288\n2014-04-13 15:57:00,16.666\n2014-04-13 16:02:00,16.334\n2014-04-13 16:07:00,17.0\n2014-04-13 16:12:00,16.002\n2014-04-13 16:17:00,17.0\n2014-04-13 16:22:00,16.334\n2014-04-13 16:27:00,17.668\n2014-04-13 16:32:00,16.724\n2014-04-13 16:37:00,15.954\n2014-04-13 16:42:00,17.0\n2014-04-13 16:47:00,16.666\n2014-04-13 16:52:00,15.665999999999999\n2014-04-13 16:57:00,17.332\n2014-04-13 17:02:00,16.668\n2014-04-13 17:07:00,16.7\n2014-04-13 17:12:00,17.332\n2014-04-13 17:17:00,16.0\n2014-04-13 17:22:00,17.334\n2014-04-13 17:27:00,17.044\n2014-04-13 17:32:00,16.724\n2014-04-13 17:37:00,16.29\n2014-04-13 17:42:00,17.0\n2014-04-13 17:47:00,16.052\n2014-04-13 17:52:00,17.0\n2014-04-13 17:57:00,17.0\n2014-04-13 18:02:00,16.317999999999998\n2014-04-13 18:07:00,16.998\n2014-04-13 18:12:00,16.998\n2014-04-13 18:17:00,17.002\n2014-04-13 18:22:00,16.0\n2014-04-13 18:27:00,16.378\n2014-04-13 18:32:00,16.622\n2014-04-13 18:37:00,15.634\n2014-04-13 18:42:00,16.684\n2014-04-13 18:47:00,16.0\n2014-04-13 18:52:00,15.984000000000002\n2014-04-13 18:57:00,17.038\n2014-04-13 19:02:00,16.332\n2014-04-13 19:07:00,15.668\n2014-04-13 19:12:00,17.002\n2014-04-13 19:17:00,15.668\n2014-04-13 19:22:00,16.334\n2014-04-13 19:27:00,16.332\n2014-04-13 19:32:00,16.334\n2014-04-13 19:37:00,16.977999999999998\n2014-04-13 19:42:00,16.666\n2014-04-13 19:47:00,16.0\n2014-04-13 19:52:00,16.055999999999994\n2014-04-13 19:57:00,16.29\n2014-04-13 20:02:00,16.666\n2014-04-13 20:07:00,15.334000000000001\n2014-04-13 20:12:00,16.68\n2014-04-13 20:17:00,16.336\n2014-04-13 20:22:00,17.352\n2014-04-13 20:27:00,16.666\n2014-04-13 20:32:00,16.334\n2014-04-13 20:37:00,15.99\n2014-04-13 20:42:00,16.334\n2014-04-13 20:47:00,15.998\n2014-04-13 20:52:00,16.674\n2014-04-13 20:57:00,16.285999999999998\n2014-04-13 21:02:00,16.674\n2014-04-13 21:07:00,16.0\n2014-04-13 21:12:00,16.334\n2014-04-13 21:17:00,16.666\n2014-04-13 21:22:00,17.0\n2014-04-13 21:27:00,16.706\n2014-04-13 21:32:00,16.302\n2014-04-13 21:37:00,16.0\n2014-04-13 21:42:00,16.666\n2014-04-13 21:47:00,16.332\n2014-04-13 21:52:00,16.668\n2014-04-13 21:57:00,17.002\n2014-04-13 22:02:00,16.064\n2014-04-13 22:07:00,16.95\n2014-04-13 22:12:00,15.665999999999999\n2014-04-13 22:17:00,16.666\n2014-04-13 22:22:00,16.355999999999998\n2014-04-13 22:27:00,17.328\n2014-04-13 22:32:00,16.68\n2014-04-13 22:37:00,16.666\n2014-04-13 22:42:00,16.998\n2014-04-13 22:47:00,16.666\n2014-04-13 22:52:00,16.006\n2014-04-13 22:57:00,16.715999999999998\n2014-04-13 23:02:00,15.63\n2014-04-13 23:07:00,16.666\n2014-04-13 23:12:00,18.334\n2014-04-13 23:17:00,16.666\n2014-04-13 23:22:00,16.666\n2014-04-13 23:27:00,16.046\n2014-04-13 23:32:00,16.285999999999998\n2014-04-13 23:37:00,16.332\n2014-04-13 23:42:00,16.0\n2014-04-13 23:47:00,17.0\n2014-04-13 23:52:00,16.0\n2014-04-13 23:57:00,16.436\n2014-04-14 00:02:00,15.668\n2014-04-14 00:07:00,17.0\n2014-04-14 00:12:00,16.334\n2014-04-14 00:17:00,17.0\n2014-04-14 00:22:00,16.336\n2014-04-14 00:27:00,16.666\n2014-04-14 00:32:00,16.332\n2014-04-14 00:37:00,16.332\n2014-04-14 00:42:00,16.355999999999998\n2014-04-14 00:47:00,17.0\n2014-04-14 00:52:00,16.002\n2014-04-14 00:57:00,17.01\n2014-04-14 01:02:00,15.38\n2014-04-14 01:07:00,16.282\n2014-04-14 01:12:00,17.334\n2014-04-14 01:17:00,17.0\n2014-04-14 01:22:00,16.002\n2014-04-14 01:27:00,16.666\n2014-04-14 01:32:00,17.016\n2014-04-14 01:37:00,17.0\n2014-04-14 01:42:00,16.334\n2014-04-14 01:47:00,16.372\n2014-04-14 01:52:00,16.332\n2014-04-14 01:57:00,16.666\n2014-04-14 02:02:00,16.334\n2014-04-14 02:07:00,16.998\n2014-04-14 02:12:00,17.0\n2014-04-14 02:17:00,16.334\n2014-04-14 02:22:00,16.97\n2014-04-14 02:27:00,16.666\n2014-04-14 02:32:00,16.336\n2014-04-14 02:37:00,17.0\n2014-04-14 02:42:00,16.334\n2014-04-14 02:47:00,15.664000000000001\n2014-04-14 02:52:00,16.668\n2014-04-14 02:57:00,16.334\n2014-04-14 03:02:00,16.0\n2014-04-14 03:07:00,16.044\n2014-04-14 03:12:00,17.294\n2014-04-14 03:17:00,16.0\n2014-04-14 03:22:00,17.0\n2014-04-14 03:27:00,16.334\n2014-04-14 03:32:00,17.332\n2014-04-14 03:37:00,15.72\n2014-04-14 03:42:00,16.666\n2014-04-14 03:47:00,15.668\n2014-04-14 03:52:00,16.336\n2014-04-14 03:57:00,16.334\n2014-04-14 04:02:00,16.33\n2014-04-14 04:07:00,16.334\n2014-04-14 04:12:00,16.317999999999998\n2014-04-14 04:17:00,16.372\n2014-04-14 04:22:00,16.666\n2014-04-14 04:27:00,16.666\n2014-04-14 04:32:00,16.668\n2014-04-14 04:37:00,15.334000000000001\n2014-04-14 04:42:00,17.0\n2014-04-14 04:47:00,16.042\n2014-04-14 04:52:00,16.652\n2014-04-14 04:57:00,16.002\n2014-04-14 05:02:00,16.002\n2014-04-14 05:07:00,16.334\n2014-04-14 05:12:00,16.664\n2014-04-14 05:17:00,16.334\n2014-04-14 05:22:00,16.334\n2014-04-14 05:27:00,16.336\n2014-04-14 05:32:00,16.666\n2014-04-14 05:37:00,15.968\n2014-04-14 05:42:00,16.99\n2014-04-14 05:47:00,16.332\n2014-04-14 05:52:00,15.668\n2014-04-14 05:57:00,16.332\n2014-04-14 06:02:00,16.378\n2014-04-14 06:07:00,16.95\n2014-04-14 06:12:00,16.652\n2014-04-14 06:17:00,16.666\n2014-04-14 06:22:00,16.336\n2014-04-14 06:27:00,16.666\n2014-04-14 06:32:00,16.715999999999998\n2014-04-14 06:37:00,16.288\n2014-04-14 06:42:00,16.666\n2014-04-14 06:47:00,16.666\n2014-04-14 06:52:00,16.334\n2014-04-14 06:57:00,17.3\n2014-04-14 07:02:00,16.336\n2014-04-14 07:07:00,16.666\n2014-04-14 07:12:00,16.666\n2014-04-14 07:17:00,16.044\n2014-04-14 07:22:00,16.284000000000002\n2014-04-14 07:27:00,16.666\n2014-04-14 07:32:00,16.332\n2014-04-14 07:37:00,17.0\n2014-04-14 07:42:00,16.342\n2014-04-14 07:47:00,16.332\n2014-04-14 07:52:00,16.334\n2014-04-14 07:57:00,19.0\n2014-04-14 08:02:00,15.668\n2014-04-14 08:07:00,17.0\n2014-04-14 08:12:00,16.052\n2014-04-14 08:17:00,16.316\n2014-04-14 08:22:00,16.334\n2014-04-14 08:27:00,16.666\n2014-04-14 08:32:00,16.666\n2014-04-14 08:37:00,16.666\n2014-04-14 08:42:00,16.656\n2014-04-14 08:47:00,16.666\n2014-04-14 08:52:00,16.0\n2014-04-14 08:57:00,16.666\n2014-04-14 09:02:00,16.668\n2014-04-14 09:07:00,16.666\n2014-04-14 09:12:00,16.334\n2014-04-14 09:17:00,16.332\n2014-04-14 09:22:00,16.664\n2014-04-14 09:27:00,17.334\n2014-04-14 09:32:00,16.002\n2014-04-14 09:37:00,16.666\n2014-04-14 09:42:00,17.04\n2014-04-14 09:47:00,16.288\n2014-04-14 09:52:00,16.682000000000002\n2014-04-14 09:57:00,16.334\n2014-04-14 10:02:00,16.648\n2014-04-14 10:07:00,16.002\n2014-04-14 10:12:00,17.35\n2014-04-14 10:17:00,16.0\n2014-04-14 10:22:00,16.666\n2014-04-14 10:27:00,18.332\n2014-04-14 10:32:00,16.336\n2014-04-14 10:37:00,16.0\n2014-04-14 10:42:00,16.998\n2014-04-14 10:47:00,16.0\n2014-04-14 10:52:00,16.334\n2014-04-14 10:57:00,16.998\n2014-04-14 11:02:00,16.336\n2014-04-14 11:07:00,16.668\n2014-04-14 11:12:00,16.666\n2014-04-14 11:17:00,16.666\n2014-04-14 11:22:00,17.0\n2014-04-14 11:27:00,16.622\n2014-04-14 11:32:00,16.714000000000002\n2014-04-14 11:37:00,16.332\n2014-04-14 11:42:00,16.358\n2014-04-14 11:47:00,15.964\n2014-04-14 11:52:00,16.64\n2014-04-14 11:57:00,16.002\n2014-04-14 12:02:00,17.0\n2014-04-14 12:07:00,16.332\n2014-04-14 12:12:00,16.336\n2014-04-14 12:17:00,16.324\n2014-04-14 12:22:00,16.692\n2014-04-14 12:27:00,16.372\n2014-04-14 12:32:00,16.928\n2014-04-14 12:37:00,15.665999999999999\n2014-04-14 12:42:00,17.0\n2014-04-14 12:47:00,16.002\n2014-04-14 12:52:00,16.658\n2014-04-14 12:57:00,16.668\n2014-04-14 13:02:00,17.0\n2014-04-14 13:07:00,16.334\n2014-04-14 13:12:00,16.668\n2014-04-14 13:17:00,15.668\n2014-04-14 13:22:00,16.998\n2014-04-14 13:27:00,16.352\n2014-04-14 13:32:00,16.284000000000002\n2014-04-14 13:37:00,16.334\n2014-04-14 13:42:00,17.062\n2014-04-14 13:47:00,15.964\n2014-04-14 13:52:00,15.962\n2014-04-14 13:57:00,17.33\n2014-04-14 14:02:00,16.002\n2014-04-14 14:07:00,16.334\n2014-04-14 14:12:00,16.336\n2014-04-14 14:17:00,16.33\n2014-04-14 14:22:00,17.332\n2014-04-14 14:27:00,16.052\n2014-04-14 14:32:00,16.336\n2014-04-14 14:37:00,16.334\n2014-04-14 14:42:00,16.674\n2014-04-14 14:47:00,16.0\n2014-04-14 14:52:00,16.668\n2014-04-14 14:57:00,16.372\n2014-04-14 15:02:00,16.332\n2014-04-14 15:07:00,16.332\n2014-04-14 15:12:00,16.336\n2014-04-14 15:17:00,16.668\n2014-04-14 15:22:00,16.66\n2014-04-14 15:27:00,16.666\n2014-04-14 15:32:00,17.334\n2014-04-14 15:37:00,15.668\n2014-04-14 15:42:00,17.014\n2014-04-14 15:47:00,16.334\n2014-04-14 15:52:00,16.336\n2014-04-14 15:57:00,16.668\n2014-04-14 16:02:00,16.668\n2014-04-14 16:07:00,16.368\n2014-04-14 16:12:00,17.69\n2014-04-14 16:17:00,16.028\n2014-04-14 16:22:00,16.285999999999998\n2014-04-14 16:27:00,16.336\n2014-04-14 16:32:00,16.656\n2014-04-14 16:37:00,15.998\n2014-04-14 16:42:00,16.666\n2014-04-14 16:47:00,16.332\n2014-04-14 16:52:00,17.334\n2014-04-14 16:57:00,17.044\n2014-04-14 17:02:00,15.616\n2014-04-14 17:07:00,16.666\n2014-04-14 17:12:00,16.334\n2014-04-14 17:17:00,16.7\n2014-04-14 17:22:00,16.334\n2014-04-14 17:27:00,16.666\n2014-04-14 17:32:00,16.332\n2014-04-14 17:37:00,16.332\n2014-04-14 17:42:00,16.317999999999998\n2014-04-14 17:47:00,16.666\n2014-04-14 17:52:00,15.68\n2014-04-14 17:57:00,17.0\n2014-04-14 18:02:00,16.296\n2014-04-14 18:07:00,16.666\n2014-04-14 18:12:00,16.0\n2014-04-14 18:17:00,17.006\n2014-04-14 18:22:00,16.034000000000002\n2014-04-14 18:27:00,16.662\n2014-04-14 18:32:00,16.0\n2014-04-14 18:37:00,16.666\n2014-04-14 18:42:00,16.668\n2014-04-14 18:47:00,16.328\n2014-04-14 18:52:00,16.332\n2014-04-14 18:57:00,16.962\n2014-04-14 19:02:00,15.668\n2014-04-14 19:07:00,17.0\n2014-04-14 19:12:00,16.666\n2014-04-14 19:17:00,17.334\n2014-04-14 19:22:00,15.668\n2014-04-14 19:27:00,17.332\n2014-04-14 19:32:00,16.332\n2014-04-14 19:37:00,16.332\n2014-04-14 19:42:00,17.332\n2014-04-14 19:47:00,15.674000000000001\n2014-04-14 19:52:00,16.668\n2014-04-14 19:57:00,16.666\n2014-04-14 20:02:00,16.342\n2014-04-14 20:07:00,16.99\n2014-04-14 20:12:00,16.666\n2014-04-14 20:17:00,17.0\n2014-04-14 20:22:00,16.336\n2014-04-14 20:27:00,16.656\n2014-04-14 20:32:00,16.018\n2014-04-14 20:37:00,16.332\n2014-04-14 20:42:00,16.334\n2014-04-14 20:47:00,16.334\n2014-04-14 20:52:00,15.668\n2014-04-14 20:57:00,16.334\n2014-04-14 21:02:00,16.704\n2014-04-14 21:07:00,16.0\n2014-04-14 21:12:00,16.65\n2014-04-14 21:17:00,16.65\n2014-04-14 21:22:00,17.0\n2014-04-14 21:27:00,16.668\n2014-04-14 21:32:00,17.332\n2014-04-14 21:37:00,15.665999999999999\n2014-04-14 21:42:00,17.0\n2014-04-14 21:47:00,15.334000000000001\n2014-04-14 21:52:00,16.002\n2014-04-14 21:57:00,16.002\n2014-04-14 22:02:00,16.32\n2014-04-14 22:07:00,16.334\n2014-04-14 22:12:00,17.0\n2014-04-14 22:17:00,16.666\n2014-04-14 22:22:00,16.686\n2014-04-14 22:27:00,16.0\n2014-04-14 22:32:00,16.0\n2014-04-14 22:37:00,16.0\n2014-04-14 22:42:00,16.322\n2014-04-14 22:47:00,16.664\n2014-04-14 22:52:00,16.336\n2014-04-14 22:57:00,16.0\n2014-04-14 23:02:00,16.666\n2014-04-14 23:07:00,16.0\n2014-04-14 23:12:00,16.65\n2014-04-14 23:17:00,16.002\n2014-04-14 23:22:00,16.334\n2014-04-14 23:27:00,16.332\n2014-04-14 23:32:00,17.0\n2014-04-14 23:37:00,16.332\n2014-04-14 23:42:00,16.668\n2014-04-14 23:47:00,16.708\n2014-04-14 23:52:00,16.666\n2014-04-14 23:57:00,16.03\n2014-04-15 00:02:00,15.952\n2014-04-15 00:07:00,16.666\n2014-04-15 00:12:00,17.0\n2014-04-15 00:17:00,16.64\n2014-04-15 00:22:00,16.65\n2014-04-15 00:27:00,17.384\n2014-04-15 00:32:00,16.002\n2014-04-15 00:37:00,16.334\n2014-04-15 00:42:00,16.332\n2014-04-15 00:47:00,16.002\n2014-04-15 00:52:00,16.305999999999994\n2014-04-15 00:57:00,16.715999999999998\n2014-04-15 01:02:00,15.956\n2014-04-15 01:07:00,17.668\n2014-04-15 01:12:00,17.334\n2014-04-15 01:17:00,16.666\n2014-04-15 01:22:00,15.668\n2014-04-15 01:27:00,16.666\n2014-04-15 01:32:00,16.668\n2014-04-15 01:37:00,15.998\n2014-04-15 01:42:00,16.666\n2014-04-15 01:47:00,16.332\n2014-04-15 01:52:00,16.334\n2014-04-15 01:57:00,17.317999999999998\n2014-04-15 02:02:00,16.334\n2014-04-15 02:07:00,17.334\n2014-04-15 02:12:00,16.666\n2014-04-15 02:17:00,17.374000000000002\n2014-04-15 02:22:00,16.666\n2014-04-15 02:27:00,16.998\n2014-04-15 02:32:00,15.718\n2014-04-15 02:37:00,16.996\n2014-04-15 02:42:00,16.954\n2014-04-15 02:47:00,16.382\n2014-04-15 02:52:00,16.328\n2014-04-15 02:57:00,17.308\n2014-04-15 03:02:00,16.002\n2014-04-15 03:07:00,17.334\n2014-04-15 03:12:00,16.668\n2014-04-15 03:17:00,16.63\n2014-04-15 03:22:00,18.668\n2014-04-15 03:27:00,17.332\n2014-04-15 03:32:00,15.665999999999999\n2014-04-15 03:37:00,17.002\n2014-04-15 03:42:00,16.334\n2014-04-15 03:47:00,16.334\n2014-04-15 03:52:00,15.99\n2014-04-15 03:57:00,16.708\n2014-04-15 04:02:00,16.29\n2014-04-15 04:07:00,15.33\n2014-04-15 04:12:00,16.336\n2014-04-15 04:17:00,16.002\n2014-04-15 04:22:00,16.334\n2014-04-15 04:27:00,16.668\n2014-04-15 04:32:00,16.666\n2014-04-15 04:37:00,15.998\n2014-04-15 04:42:00,16.334\n2014-04-15 04:47:00,16.0\n2014-04-15 04:52:00,16.34\n2014-04-15 04:57:00,17.046\n2014-04-15 05:02:00,16.602\n2014-04-15 05:07:00,16.332\n2014-04-15 05:12:00,17.332\n2014-04-15 05:17:00,15.668\n2014-04-15 05:22:00,17.0\n2014-04-15 05:27:00,16.334\n2014-04-15 05:32:00,16.334\n2014-04-15 05:37:00,16.664\n2014-04-15 05:42:00,16.68\n2014-04-15 05:47:00,16.332\n2014-04-15 05:52:00,17.018\n2014-04-15 05:57:00,16.666\n2014-04-15 06:02:00,16.998\n2014-04-15 06:07:00,16.046\n2014-04-15 06:12:00,16.616\n2014-04-15 06:17:00,17.0\n2014-04-15 06:22:00,16.668\n2014-04-15 06:27:00,16.668\n2014-04-15 06:32:00,17.0\n2014-04-15 06:37:00,16.0\n2014-04-15 06:42:00,17.0\n2014-04-15 06:47:00,16.334\n2014-04-15 06:52:00,16.334\n2014-04-15 06:57:00,16.666\n2014-04-15 07:02:00,16.668\n2014-04-15 07:07:00,16.656\n2014-04-15 07:12:00,16.666\n2014-04-15 07:17:00,16.334\n2014-04-15 07:22:00,16.668\n2014-04-15 07:27:00,16.298\n2014-04-15 07:32:00,15.984000000000002\n2014-04-15 07:37:00,16.666\n2014-04-15 07:42:00,16.656\n2014-04-15 07:47:00,16.038\n2014-04-15 07:52:00,16.622\n2014-04-15 07:57:00,18.668\n2014-04-15 08:02:00,16.334\n2014-04-15 08:07:00,16.666\n2014-04-15 08:12:00,16.334\n2014-04-15 08:17:00,16.372\n2014-04-15 08:22:00,16.618\n2014-04-15 08:27:00,16.666\n2014-04-15 08:32:00,16.336\n2014-04-15 08:37:00,16.378\n2014-04-15 08:42:00,16.622\n2014-04-15 08:47:00,16.328\n2014-04-15 08:52:00,15.668\n2014-04-15 08:57:00,16.332\n2014-04-15 09:02:00,16.002\n2014-04-15 09:07:00,17.332\n2014-04-15 09:12:00,16.05\n2014-04-15 09:17:00,16.282\n2014-04-15 09:22:00,15.984000000000002\n2014-04-15 09:27:00,17.334\n2014-04-15 09:32:00,15.716\n2014-04-15 09:37:00,16.652\n2014-04-15 09:42:00,16.666\n2014-04-15 09:47:00,16.338\n2014-04-15 09:52:00,16.666\n2014-04-15 09:57:00,16.666\n2014-04-15 10:02:00,16.022000000000002\n2014-04-15 10:07:00,16.332\n2014-04-15 10:12:00,16.656\n2014-04-15 10:17:00,16.362000000000002\n2014-04-15 10:22:00,16.332\n2014-04-15 10:27:00,17.668\n2014-04-15 10:32:00,15.674000000000001\n2014-04-15 10:37:00,17.0\n2014-04-15 10:42:00,16.334\n2014-04-15 10:47:00,16.372\n2014-04-15 10:52:00,16.0\n2014-04-15 10:57:00,17.334\n2014-04-15 11:02:00,16.336\n2014-04-15 11:07:00,16.968\n2014-04-15 11:12:00,17.0\n2014-04-15 11:17:00,16.666\n2014-04-15 11:22:00,16.652\n2014-04-15 11:27:00,17.424\n2014-04-15 11:32:00,16.285999999999998\n2014-04-15 11:37:00,16.668\n2014-04-15 11:42:00,16.666\n2014-04-15 11:47:00,16.334\n2014-04-15 11:52:00,16.668\n2014-04-15 11:57:00,16.668\n2014-04-15 12:02:00,16.666\n2014-04-15 12:07:00,15.995999999999999\n2014-04-15 12:12:00,16.336\n2014-04-15 12:17:00,16.334\n2014-04-15 12:22:00,16.662\n2014-04-15 12:27:00,17.0\n2014-04-15 12:32:00,16.002\n2014-04-15 12:37:00,16.386\n2014-04-15 12:42:00,16.668\n2014-04-15 12:47:00,16.0\n2014-04-15 12:52:00,16.666\n2014-04-15 12:57:00,16.334\n2014-04-15 13:02:00,17.002\n2014-04-15 13:07:00,16.988\n2014-04-15 13:12:00,17.018\n2014-04-15 13:17:00,16.296\n2014-04-15 13:22:00,17.0\n2014-04-15 13:27:00,16.002\n2014-04-15 13:32:00,16.666\n2014-04-15 13:37:00,16.044\n2014-04-15 13:42:00,16.284000000000002\n2014-04-15 13:47:00,16.666\n2014-04-15 13:52:00,16.666\n2014-04-15 13:57:00,16.666\n2014-04-15 14:02:00,17.022000000000002\n2014-04-15 14:07:00,16.334\n2014-04-15 14:12:00,17.334\n2014-04-15 14:17:00,16.332\n2014-04-15 14:22:00,16.334\n2014-04-15 14:27:00,16.0\n2014-04-15 14:32:00,16.002\n2014-04-15 14:37:00,16.0\n2014-04-15 14:42:00,17.012\n2014-04-15 14:47:00,16.352\n2014-04-15 14:52:00,16.668\n2014-04-15 14:57:00,16.998\n2014-04-15 15:02:00,15.99\n2014-04-15 15:07:00,16.334\n2014-04-15 15:12:00,16.332\n2014-04-15 15:17:00,16.666\n2014-04-15 15:22:00,16.334\n2014-04-15 15:27:00,16.38\n2014-04-15 15:32:00,16.666\n2014-04-15 15:37:00,17.042\n2014-04-15 15:42:00,17.375999999999998\n2014-04-15 15:47:00,16.038\n2014-04-15 15:52:00,16.285999999999998\n2014-04-15 15:57:00,16.704\n2014-04-15 16:02:00,17.282\n2014-04-15 16:07:00,16.332\n2014-04-15 16:12:00,17.002\n2014-04-15 16:17:00,16.666\n2014-04-15 16:22:00,17.328\n2014-04-15 16:27:00,16.334\n2014-04-15 16:32:00,16.336\n2014-04-15 16:37:00,16.334\n2014-04-15 16:42:00,16.334\n2014-04-15 16:47:00,15.968\n2014-04-15 16:52:00,18.0\n2014-04-15 16:57:00,16.002\n2014-04-15 17:02:00,16.666\n2014-04-15 17:07:00,16.04\n2014-04-15 17:12:00,16.336\n2014-04-15 17:17:00,15.706\n2014-04-15 17:22:00,16.288\n2014-04-15 17:27:00,16.334\n2014-04-15 17:32:00,17.334\n2014-04-15 17:37:00,16.332\n2014-04-15 17:42:00,16.998\n2014-04-15 17:47:00,16.0\n2014-04-15 17:52:00,16.336\n2014-04-15 17:57:00,17.322\n2014-04-15 18:02:00,16.0\n2014-04-15 18:07:00,16.666\n2014-04-15 18:12:00,16.308\n2014-04-15 18:17:00,17.666\n2014-04-15 18:22:00,16.334\n2014-04-15 18:27:00,16.66\n2014-04-15 18:32:00,16.334\n2014-04-15 18:37:00,16.666\n2014-04-15 18:42:00,16.722\n2014-04-15 18:47:00,16.282\n2014-04-15 18:52:00,16.656\n2014-04-15 18:57:00,17.0\n2014-04-15 19:02:00,16.724\n2014-04-15 19:07:00,17.29\n2014-04-15 19:12:00,16.334\n2014-04-15 19:17:00,16.712\n2014-04-15 19:22:00,16.634\n2014-04-15 19:27:00,17.044\n2014-04-15 19:32:00,15.952\n2014-04-15 19:37:00,17.0\n2014-04-15 19:42:00,15.668\n2014-04-15 19:47:00,16.666\n2014-04-15 19:52:00,16.0\n2014-04-15 19:57:00,17.328\n2014-04-15 20:02:00,16.048\n2014-04-15 20:07:00,16.61\n2014-04-15 20:12:00,17.332\n2014-04-15 20:17:00,17.0\n2014-04-15 20:22:00,16.977999999999998\n2014-04-15 20:27:00,16.666\n2014-04-15 20:32:00,16.0\n2014-04-15 20:37:00,16.662\n2014-04-15 20:42:00,16.715999999999998\n2014-04-15 20:47:00,16.282\n2014-04-15 20:52:00,16.002\n2014-04-15 20:57:00,17.364\n2014-04-15 21:02:00,16.35\n2014-04-15 21:07:00,17.328\n2014-04-15 21:12:00,17.02\n2014-04-15 21:17:00,16.666\n2014-04-15 21:22:00,16.334\n2014-04-15 21:27:00,16.334\n2014-04-15 21:32:00,16.348\n2014-04-15 21:37:00,17.0\n2014-04-15 21:42:00,17.0\n2014-04-15 21:47:00,16.666\n2014-04-15 21:52:00,15.985999999999999\n2014-04-15 21:57:00,16.664\n2014-04-15 22:02:00,16.308\n2014-04-15 22:07:00,16.712\n2014-04-15 22:12:00,16.998\n2014-04-15 22:17:00,16.954\n2014-04-15 22:22:00,16.718\n2014-04-15 22:27:00,16.666\n2014-04-15 22:32:00,16.336\n2014-04-15 22:37:00,15.7\n2014-04-15 22:42:00,17.0\n2014-04-15 22:47:00,16.332\n2014-04-15 22:52:00,16.666\n2014-04-15 22:57:00,16.332\n2014-04-15 23:02:00,16.998\n2014-04-15 23:07:00,16.0\n2014-04-15 23:12:00,17.0\n2014-04-15 23:17:00,16.334\n2014-04-15 23:22:00,17.317999999999998\n2014-04-15 23:27:00,16.998\n2014-04-15 23:32:00,16.668\n2014-04-15 23:37:00,16.666\n2014-04-15 23:42:00,16.334\n2014-04-15 23:47:00,16.284000000000002\n2014-04-15 23:52:00,17.0\n2014-04-15 23:57:00,16.894000000000002\n2014-04-16 00:02:00,17.332\n2014-04-16 00:07:00,16.372\n2014-04-16 00:12:00,17.278\n2014-04-16 00:17:00,16.372\n2014-04-16 00:22:00,16.284000000000002\n2014-04-16 00:27:00,16.372\n2014-04-16 00:32:00,16.668\n2014-04-16 00:37:00,16.666\n2014-04-16 00:42:00,15.99\n2014-04-16 00:47:00,16.706\n2014-04-16 00:52:00,16.622\n2014-04-16 00:57:00,16.666\n2014-04-16 01:02:00,16.998\n2014-04-16 01:07:00,16.0\n2014-04-16 01:12:00,17.668\n2014-04-16 01:17:00,16.72\n2014-04-16 01:22:00,16.668\n2014-04-16 01:27:00,16.668\n2014-04-16 01:32:00,17.332\n2014-04-16 01:37:00,16.666\n2014-04-16 01:42:00,16.99\n2014-04-16 01:47:00,16.332\n2014-04-16 01:52:00,16.336\n2014-04-16 01:57:00,16.38\n2014-04-16 02:02:00,16.95\n2014-04-16 02:07:00,16.334\n2014-04-16 02:12:00,16.684\n2014-04-16 02:17:00,17.332\n2014-04-16 02:22:00,16.666\n2014-04-16 02:27:00,17.0\n2014-04-16 02:32:00,16.944000000000006\n2014-04-16 02:37:00,16.378\n2014-04-16 02:42:00,16.652\n2014-04-16 02:47:00,17.0\n2014-04-16 02:52:00,15.668\n2014-04-16 02:57:00,17.0\n2014-04-16 03:02:00,16.334\n2014-04-16 03:07:00,17.33\n2014-04-16 03:12:00,16.666\n2014-04-16 03:17:00,17.334\n2014-04-16 03:22:00,16.324\n2014-04-16 03:27:00,17.05\n2014-04-16 03:32:00,16.284000000000002\n2014-04-16 03:37:00,16.666\n2014-04-16 03:42:00,16.0\n2014-04-16 03:47:00,16.332\n2014-04-16 03:52:00,16.317999999999998\n2014-04-16 03:57:00,17.666\n2014-04-16 04:02:00,15.664000000000001\n2014-04-16 04:07:00,16.332\n2014-04-16 04:12:00,16.334\n2014-04-16 04:17:00,15.998\n2014-04-16 04:22:00,15.672\n2014-04-16 04:27:00,16.666\n2014-04-16 04:32:00,16.0\n2014-04-16 04:37:00,16.668\n2014-04-16 04:42:00,15.684000000000001\n2014-04-16 04:47:00,16.666\n2014-04-16 04:52:00,17.648\n2014-04-16 04:57:00,16.666\n2014-04-16 05:02:00,16.332\n2014-04-16 05:07:00,16.666\n2014-04-16 05:12:00,16.0\n2014-04-16 05:17:00,15.998\n2014-04-16 05:22:00,16.332\n2014-04-16 05:27:00,16.666\n2014-04-16 05:32:00,16.334\n2014-04-16 05:37:00,16.994\n2014-04-16 05:42:00,16.03\n2014-04-16 05:47:00,16.712\n2014-04-16 05:52:00,15.934000000000001\n2014-04-16 05:57:00,16.702\n2014-04-16 06:02:00,16.0\n2014-04-16 06:07:00,16.296\n2014-04-16 06:12:00,16.998\n2014-04-16 06:17:00,15.668\n2014-04-16 06:22:00,16.666\n2014-04-16 06:27:00,16.002\n2014-04-16 06:32:00,16.666\n2014-04-16 06:37:00,16.038\n2014-04-16 06:42:00,16.95\n2014-04-16 06:47:00,16.332\n2014-04-16 06:52:00,16.666\n2014-04-16 06:57:00,16.718\n2014-04-16 07:02:00,16.668\n2014-04-16 07:07:00,16.334\n2014-04-16 07:12:00,16.334\n2014-04-16 07:17:00,15.958\n2014-04-16 07:22:00,16.39\n2014-04-16 07:27:00,16.622\n2014-04-16 07:32:00,16.668\n2014-04-16 07:37:00,15.668\n2014-04-16 07:42:00,17.002\n2014-04-16 07:47:00,16.38\n2014-04-16 07:52:00,15.952\n2014-04-16 07:57:00,18.668\n2014-04-16 08:02:00,16.317999999999998\n2014-04-16 08:07:00,16.386\n2014-04-16 08:12:00,16.668\n2014-04-16 08:17:00,16.332\n2014-04-16 08:22:00,16.336\n2014-04-16 08:27:00,16.668\n2014-04-16 08:32:00,16.312\n2014-04-16 08:37:00,16.006\n2014-04-16 08:42:00,17.0\n2014-04-16 08:47:00,16.332\n2014-04-16 08:52:00,16.39\n2014-04-16 08:57:00,16.962\n2014-04-16 09:02:00,16.002\n2014-04-16 09:07:00,16.332\n2014-04-16 09:12:00,17.33\n2014-04-16 09:17:00,15.665999999999999\n2014-04-16 09:22:00,16.668\n2014-04-16 09:27:00,16.998\n2014-04-16 09:32:00,16.002\n2014-04-16 09:37:00,16.666\n2014-04-16 09:42:00,16.652\n2014-04-16 09:47:00,16.372\n2014-04-16 09:52:00,16.002\n2014-04-16 09:57:00,16.666\n2014-04-16 10:02:00,16.998\n2014-04-16 10:07:00,16.332\n2014-04-16 10:12:00,16.332\n2014-04-16 10:17:00,17.0\n2014-04-16 10:22:00,16.014\n2014-04-16 10:27:00,17.0\n2014-04-16 10:32:00,16.666\n2014-04-16 10:37:00,15.998\n2014-04-16 10:42:00,16.0\n2014-04-16 10:47:00,16.666\n2014-04-16 10:52:00,16.332\n2014-04-16 10:57:00,17.0\n2014-04-16 11:02:00,16.332\n2014-04-16 11:07:00,17.0\n2014-04-16 11:12:00,17.334\n2014-04-16 11:17:00,17.0\n2014-04-16 11:22:00,16.32\n2014-04-16 11:27:00,17.334\n2014-04-16 11:32:00,16.002\n2014-04-16 11:37:00,17.0\n2014-04-16 11:42:00,17.028\n2014-04-16 11:47:00,16.63\n2014-04-16 11:52:00,16.668\n2014-04-16 11:57:00,17.04\n2014-04-16 12:02:00,15.665999999999999\n2014-04-16 12:07:00,16.332\n2014-04-16 12:12:00,17.0\n2014-04-16 12:17:00,16.334\n2014-04-16 12:22:00,17.666\n2014-04-16 12:27:00,17.0\n2014-04-16 12:32:00,16.336\n2014-04-16 12:37:00,16.72\n2014-04-16 12:42:00,16.998\n2014-04-16 12:47:00,16.628\n2014-04-16 12:52:00,17.0\n2014-04-16 12:57:00,16.998\n2014-04-16 13:02:00,16.684\n2014-04-16 13:07:00,16.998\n2014-04-16 13:12:00,16.312\n2014-04-16 13:17:00,17.0\n2014-04-16 13:22:00,17.686\n2014-04-16 13:27:00,16.38\n2014-04-16 13:32:00,16.285999999999998\n2014-04-16 13:37:00,16.724\n2014-04-16 13:42:00,17.0\n2014-04-16 13:47:00,16.332\n2014-04-16 13:52:00,17.0\n2014-04-16 13:57:00,17.002\n2014-04-16 14:02:00,17.0\n2014-04-16 14:07:00,16.998\n2014-04-16 14:12:00,16.668\n2014-04-16 14:17:00,16.334\n2014-04-16 14:22:00,16.6675\n2014-04-16 14:27:00,17.5\n2014-04-16 14:32:00,15.8325\n2014-04-16 14:37:00,16.6625\n2014-04-16 14:42:00,17.0825\n2014-04-16 14:47:00,17.0825\n2014-04-16 14:52:00,16.32\n2014-04-16 14:57:00,17.915\n2014-04-16 15:02:00,16.6675\n2014-04-16 15:07:00,17.0825\n2014-04-16 15:12:00,17.515\n2014-04-16 15:17:00,17.5\n2014-04-16 15:22:00,17.5025\n2014-04-16 15:27:00,17.8\n2014-04-16 15:32:00,16.25\n2014-04-16 15:37:00,17.4875\n2014-04-16 15:42:00,16.195\n2014-04-16 15:47:00,17.5\n2014-04-16 15:52:00,17.0825\n2014-04-16 15:57:00,17.5\n2014-04-16 16:02:00,15.8325\n2014-04-16 16:07:00,17.085\n2014-04-16 16:12:00,17.0825\n2014-04-16 16:17:00,17.9175\n2014-04-16 16:22:00,16.6675\n2014-04-16 16:27:00,17.5\n2014-04-16 16:32:00,17.5\n2014-04-16 16:37:00,17.0775\n2014-04-16 16:42:00,16.605\n2014-04-16 16:47:00,17.55\n2014-04-16 16:52:00,17.4975\n2014-04-16 16:57:00,18.245\n2014-04-16 17:02:00,17.4875\n2014-04-16 17:07:00,17.9175\n2014-04-16 17:12:00,16.6675\n2014-04-16 17:17:00,17.5\n2014-04-16 17:22:00,16.2525\n2014-04-16 17:27:00,17.02\n2014-04-16 17:32:00,17.435\n2014-04-16 17:37:00,16.665\n2014-04-16 17:42:00,17.085\n2014-04-16 17:47:00,19.085\n2014-04-16 17:52:00,17.0825\n2014-04-16 17:57:00,17.0825\n2014-04-16 18:02:00,16.6675\n2014-04-16 18:07:00,17.5\n2014-04-16 18:12:00,16.6675\n2014-04-16 18:17:00,17.0825\n2014-04-16 18:22:00,16.27\n2014-04-16 18:27:00,18.2625\n2014-04-16 18:32:00,15.925\n2014-04-16 18:37:00,17.605\n2014-04-16 18:42:00,17.0975\n2014-04-16 18:47:00,17.02\n2014-04-16 18:52:00,17.0825\n2014-04-16 18:57:00,17.5\n2014-04-16 19:02:00,16.2525\n2014-04-16 19:07:00,17.5\n2014-04-16 19:12:00,17.5475\n2014-04-16 19:17:00,17.495\n2014-04-16 19:22:00,16.2525\n2014-04-16 19:27:00,17.96\n2014-04-16 19:32:00,16.225\n2014-04-16 19:37:00,16.765\n2014-04-16 19:42:00,16.6525\n2014-04-16 19:47:00,16.665\n2014-04-16 19:52:00,16.2525\n2014-04-16 19:57:00,18.3325\n2014-04-16 20:02:00,16.2525\n2014-04-16 20:07:00,17.5\n2014-04-16 20:12:00,17.08\n2014-04-16 20:17:00,17.5\n2014-04-16 20:22:00,17.5\n2014-04-16 20:27:00,17.915\n2014-04-16 20:32:00,16.2525\n2014-04-16 20:37:00,17.085\n2014-04-16 20:42:00,17.0825\n2014-04-16 20:47:00,17.195\n2014-04-16 20:52:00,16.25\n2014-04-16 20:57:00,17.5\n2014-04-16 21:02:00,15.8325\n2014-04-16 21:07:00,17.0825\n2014-04-16 21:12:00,17.91\n2014-04-16 21:17:00,17.5\n2014-04-16 21:22:00,16.25\n2014-04-16 21:27:00,17.9175\n2014-04-16 21:32:00,16.25\n2014-04-16 21:37:00,16.7725\n2014-04-16 21:42:00,17.0825\n2014-04-16 21:47:00,17.0375\n2014-04-16 21:52:00,16.6675\n2014-04-16 21:57:00,17.9175\n2014-04-16 22:02:00,15.835\n2014-04-16 22:07:00,17.8\n2014-04-16 22:12:00,17.9375\n2014-04-16 22:17:00,17.5\n2014-04-16 22:22:00,17.905\n2014-04-16 22:27:00,17.4975\n2014-04-16 22:32:00,16.6675\n2014-04-16 22:37:00,17.5025\n2014-04-16 22:42:00,16.25\n2014-04-16 22:47:00,17.0825\n2014-04-16 22:52:00,16.67\n2014-04-16 22:57:00,18.3325\n2014-04-16 23:02:00,16.25\n2014-04-16 23:07:00,16.6275\n2014-04-16 23:12:00,17.0825\n2014-04-16 23:17:00,17.5\n2014-04-16 23:22:00,16.25\n2014-04-16 23:27:00,17.5\n2014-04-16 23:32:00,16.6675\n2014-04-16 23:37:00,17.5\n2014-04-16 23:42:00,17.9225\n2014-04-16 23:47:00,16.71\n2014-04-16 23:52:00,16.67\n2014-04-16 23:57:00,17.8275\n2014-04-17 00:02:00,16.665\n2014-04-17 00:07:00,18.335\n2014-04-17 00:12:00,17.0825\n2014-04-17 00:17:00,18.385\n2014-04-17 00:22:00,16.23\n2014-04-17 00:27:00,17.4975\n2014-04-17 00:32:00,16.655\n2014-04-17 00:37:00,17.4975\n2014-04-17 00:42:00,16.6675\n2014-04-17 00:47:00,16.6675\n2014-04-17 00:52:00,16.665\n2014-04-17 00:57:00,17.5025\n2014-04-17 01:02:00,16.2525\n2014-04-17 01:07:00,17.085\n2014-04-17 01:12:00,17.5025\n2014-04-17 01:17:00,17.5025\n2014-04-17 01:22:00,16.6675\n2014-04-17 01:27:00,18.3325\n2014-04-17 01:32:00,16.665\n2014-04-17 01:37:00,17.4975\n2014-04-17 01:42:00,17.59\n2014-04-17 01:47:00,17.0825\n2014-04-17 01:52:00,16.6675\n2014-04-17 01:57:00,18.3325\n2014-04-17 02:02:00,16.34\n2014-04-17 02:07:00,17.085\n2014-04-17 02:12:00,16.6675\n2014-04-17 02:17:00,17.5\n2014-04-17 02:22:00,16.6675\n2014-04-17 02:27:00,18.335\n2014-04-17 02:32:00,17.0825\n2014-04-17 02:37:00,17.5\n2014-04-17 02:42:00,17.0825\n2014-04-17 02:47:00,17.0275\n2014-04-17 02:52:00,16.6675\n2014-04-17 02:57:00,18.33\n2014-04-17 03:02:00,16.2675\n2014-04-17 03:07:00,17.0375\n2014-04-17 03:12:00,17.5\n2014-04-17 03:17:00,16.3825\n2014-04-17 03:22:00,15.835\n2014-04-17 03:27:00,17.085\n2014-04-17 03:32:00,17.4575\n2014-04-17 03:37:00,17.5\n2014-04-17 03:42:00,17.05\n2014-04-17 03:47:00,18.335\n2014-04-17 03:52:00,15.8075\n2014-04-17 03:57:00,17.4875\n2014-04-17 04:02:00,16.35\n2014-04-17 04:07:00,16.665\n2014-04-17 04:12:00,16.665\n2014-04-17 04:17:00,17.02\n2014-04-17 04:22:00,16.6675\n2014-04-17 04:27:00,17.89\n2014-04-17 04:32:00,16.2675\n2014-04-17 04:37:00,17.5\n2014-04-17 04:42:00,16.2525\n2014-04-17 04:47:00,16.66\n2014-04-17 04:52:00,16.19\n2014-04-17 04:57:00,17.515\n2014-04-17 05:02:00,16.9925\n2014-04-17 05:07:00,17.1875\n2014-04-17 05:12:00,16.665\n2014-04-17 05:17:00,17.5\n2014-04-17 05:22:00,16.25\n2014-04-17 05:27:00,16.61\n2014-04-17 05:32:00,17.085\n2014-04-17 05:37:00,17.5\n2014-04-17 05:42:00,16.6675\n2014-04-17 05:47:00,17.8775\n2014-04-17 05:52:00,15.7775\n2014-04-17 05:57:00,17.5\n2014-04-17 06:02:00,17.9175\n2014-04-17 06:07:00,17.5075\n2014-04-17 06:12:00,17.5\n2014-04-17 06:17:00,17.03\n2014-04-17 06:22:00,16.6875\n2014-04-17 06:27:00,17.5025\n2014-04-17 06:32:00,16.25\n2014-04-17 06:37:00,17.48\n2014-04-17 06:42:00,16.25\n2014-04-17 06:47:00,17.0825\n2014-04-17 06:52:00,17.5225\n2014-04-17 06:57:00,17.5\n2014-04-17 07:02:00,17.0925\n2014-04-17 07:07:00,16.6675\n2014-04-17 07:12:00,17.0825\n2014-04-17 07:17:00,17.555\n2014-04-17 07:22:00,17.0825\n2014-04-17 07:27:00,17.915\n2014-04-17 07:32:00,16.275\n2014-04-17 07:37:00,17.9175\n2014-04-17 07:42:00,16.7575\n2014-04-17 07:47:00,17.0275\n2014-04-17 07:52:00,16.665\n2014-04-17 07:57:00,19.16\n2014-04-17 08:02:00,16.675\n2014-04-17 08:07:00,17.5\n2014-04-17 08:12:00,17.175\n2014-04-17 08:17:00,17.085\n2014-04-17 08:22:00,15.8275\n2014-04-17 08:27:00,18.335\n2014-04-17 08:32:00,16.6675\n2014-04-17 08:37:00,16.6675\n2014-04-17 08:42:00,17.1725\n2014-04-17 08:47:00,17.0825\n2014-04-17 08:52:00,16.6675\n2014-04-17 08:57:00,17.5\n2014-04-17 09:02:00,17.0275\n2014-04-17 09:07:00,17.0825\n2014-04-17 09:12:00,16.6675\n2014-04-17 09:17:00,17.4925\n2014-04-17 09:22:00,15.7925\n2014-04-17 09:27:00,17.5\n2014-04-17 09:32:00,16.25\n2014-04-17 09:37:00,17.5\n2014-04-17 09:42:00,16.25\n2014-04-17 09:47:00,17.0825\n2014-04-17 09:52:00,16.2675\n2014-04-17 09:57:00,17.9175\n2014-04-17 10:02:00,16.25\n2014-04-17 10:07:00,17.0825\n2014-04-17 10:12:00,17.4975\n2014-04-17 10:17:00,17.085\n2014-04-17 10:22:00,16.6675\n2014-04-17 10:27:00,17.4375\n2014-04-17 10:32:00,16.6675\n2014-04-17 10:37:00,17.9175\n2014-04-17 10:42:00,16.25\n2014-04-17 10:47:00,16.6675\n2014-04-17 10:52:00,16.665\n2014-04-17 10:57:00,17.915\n2014-04-17 11:02:00,16.6675\n2014-04-17 11:07:00,18.3325\n2014-04-17 11:12:00,16.665\n2014-04-17 11:17:00,17.0275\n2014-04-17 11:22:00,16.6675\n2014-04-17 11:27:00,17.1875\n2014-04-17 11:32:00,16.665\n2014-04-17 11:37:00,17.445\n2014-04-17 11:42:00,17.0825\n2014-04-17 11:47:00,17.9175\n2014-04-17 11:52:00,16.665\n2014-04-17 11:57:00,17.915\n2014-04-17 12:02:00,16.6675\n2014-04-17 12:07:00,17.5\n2014-04-17 12:12:00,18.3325\n2014-04-17 12:17:00,17.0375\n2014-04-17 12:22:00,16.6675\n2014-04-17 12:27:00,17.4975\n2014-04-17 12:32:00,16.6675\n2014-04-17 12:37:00,17.5\n2014-04-17 12:42:00,16.2525\n2014-04-17 12:47:00,16.665\n2014-04-17 12:52:00,15.835\n2014-04-17 12:57:00,18.335\n2014-04-17 13:02:00,16.6675\n2014-04-17 13:07:00,17.0825\n2014-04-17 13:12:00,16.64\n2014-04-17 13:17:00,18.335\n2014-04-17 13:22:00,16.6675\n2014-04-17 13:27:00,17.5\n2014-04-17 13:32:00,16.6675\n2014-04-17 13:37:00,17.085\n2014-04-17 13:42:00,16.2375\n2014-04-17 13:47:00,17.0425\n2014-04-17 13:52:00,16.6675\n2014-04-17 13:57:00,17.5\n2014-04-17 14:02:00,17.0825\n2014-04-17 14:07:00,17.9175\n2014-04-17 14:12:00,16.25\n2014-04-17 14:17:00,17.0825\n2014-04-17 14:22:00,17.0825\n2014-04-17 14:27:00,17.5\n2014-04-17 14:32:00,17.0825\n2014-04-17 14:37:00,17.0825\n2014-04-17 14:42:00,16.2525\n2014-04-17 14:47:00,17.0825\n2014-04-17 14:52:00,16.2525\n2014-04-17 14:57:00,17.5\n2014-04-17 15:02:00,16.665\n2014-04-17 15:07:00,17.0775\n2014-04-17 15:12:00,17.0825\n2014-04-17 15:17:00,18.335\n2014-04-17 15:22:00,16.6675\n2014-04-17 15:27:00,18.03\n2014-04-17 15:32:00,17.0825\n2014-04-17 15:37:00,16.665\n2014-04-17 15:42:00,17.0825\n2014-04-17 15:47:00,17.5\n2014-04-17 15:52:00,15.835\n2014-04-17 15:57:00,18.3325\n2014-04-17 16:02:00,16.6675\n2014-04-17 16:07:00,17.085\n2014-04-17 16:12:00,17.085\n2014-04-17 16:17:00,17.085\n2014-04-17 16:22:00,16.665\n2014-04-17 16:27:00,17.87\n2014-04-17 16:32:00,16.6675\n2014-04-17 16:37:00,16.6675\n2014-04-17 16:42:00,17.0825\n2014-04-17 16:47:00,16.66\n2014-04-17 16:52:00,16.5975\n2014-04-17 16:57:00,17.91\n2014-04-17 17:02:00,16.665\n2014-04-17 17:07:00,18.0075\n2014-04-17 17:12:00,17.0825\n2014-04-17 17:17:00,16.6625\n2014-04-17 17:22:00,16.6675\n2014-04-17 17:27:00,18.3325\n2014-04-17 17:32:00,16.25\n2014-04-17 17:37:00,17.0825\n2014-04-17 17:42:00,16.25\n2014-04-17 17:47:00,17.9175\n2014-04-17 17:52:00,16.2675\n2014-04-17 17:57:00,18.3325\n2014-04-17 18:02:00,17.065\n2014-04-17 18:07:00,17.0825\n2014-04-17 18:12:00,17.915\n2014-04-17 18:17:00,17.5\n2014-04-17 18:22:00,17.1825\n2014-04-17 18:27:00,17.5\n2014-04-17 18:32:00,17.0825\n2014-04-17 18:37:00,16.57\n2014-04-17 18:42:00,16.6825\n2014-04-17 18:47:00,18.7475\n2014-04-17 18:52:00,16.25\n2014-04-17 18:57:00,17.9175\n2014-04-17 19:02:00,16.665\n2014-04-17 19:07:00,17.235\n2014-04-17 19:12:00,17.915\n2014-04-17 19:17:00,17.9175\n2014-04-17 19:22:00,16.6675\n2014-04-17 19:27:00,17.5\n2014-04-17 19:32:00,17.0825\n2014-04-17 19:37:00,16.665\n2014-04-17 19:42:00,16.6675\n2014-04-17 19:47:00,17.0425\n2014-04-17 19:52:00,17.08\n2014-04-17 19:57:00,17.4975\n2014-04-17 20:02:00,17.0825\n2014-04-17 20:07:00,18.34\n2014-04-17 20:12:00,17.0825\n2014-04-17 20:17:00,17.0825\n2014-04-17 20:22:00,16.3425\n2014-04-17 20:27:00,17.5025\n2014-04-17 20:32:00,16.6525\n2014-04-17 20:37:00,17.495\n2014-04-17 20:42:00,17.0825\n2014-04-17 20:47:00,16.6275\n2014-04-17 20:52:00,16.6675\n2014-04-17 20:57:00,18.275\n2014-04-17 21:02:00,16.665\n2014-04-17 21:07:00,18.75\n2014-04-17 21:12:00,17.4975\n2014-04-17 21:17:00,18.3325\n2014-04-17 21:22:00,17.0825\n2014-04-17 21:27:00,18.335\n2014-04-17 21:32:00,16.6825\n2014-04-17 21:37:00,17.5\n2014-04-17 21:42:00,17.4375\n2014-04-17 21:47:00,17.5\n2014-04-17 21:52:00,16.25\n2014-04-17 21:57:00,18.3325\n2014-04-17 22:02:00,16.6675\n2014-04-17 22:07:00,17.0825\n2014-04-17 22:12:00,16.6675\n2014-04-17 22:17:00,16.6675\n2014-04-17 22:22:00,17.175\n2014-04-17 22:27:00,17.0825\n2014-04-17 22:32:00,17.0825\n2014-04-17 22:37:00,17.9225\n2014-04-17 22:42:00,17.56\n2014-04-17 22:47:00,17.925\n2014-04-17 22:52:00,17.5\n2014-04-17 22:57:00,17.5025\n2014-04-17 23:02:00,16.6675\n2014-04-17 23:07:00,18.015\n2014-04-17 23:12:00,17.085\n2014-04-17 23:17:00,18.2175\n2014-04-17 23:22:00,16.6675\n2014-04-17 23:27:00,17.915\n2014-04-17 23:32:00,17.0825\n2014-04-17 23:37:00,17.085\n2014-04-17 23:42:00,17.0825\n2014-04-17 23:47:00,16.6675\n2014-04-17 23:52:00,16.26\n2014-04-17 23:57:00,18.06\n2014-04-18 00:02:00,16.25\n2014-04-18 00:07:00,18.3325\n2014-04-18 00:12:00,17.0825\n2014-04-18 00:17:00,17.5\n2014-04-18 00:22:00,16.6675\n2014-04-18 00:27:00,17.915\n2014-04-18 00:32:00,16.2525\n2014-04-18 00:37:00,17.5\n2014-04-18 00:42:00,16.25\n2014-04-18 00:47:00,17.0825\n2014-04-18 00:52:00,17.0825\n2014-04-18 00:57:00,17.5025\n2014-04-18 01:02:00,17.0825\n2014-04-18 01:07:00,18.335\n2014-04-18 01:12:00,18.2875\n2014-04-18 01:17:00,17.5\n2014-04-18 01:22:00,16.6675\n2014-04-18 01:27:00,17.4875\n2014-04-18 01:32:00,16.6675\n2014-04-18 01:37:00,17.0825\n2014-04-18 01:42:00,17.4975\n2014-04-18 01:47:00,16.665\n2014-04-18 01:52:00,16.25\n2014-04-18 01:57:00,18.295\n2014-04-18 02:02:00,16.665\n2014-04-18 02:07:00,17.0825\n2014-04-18 02:12:00,17.0825\n2014-04-18 02:17:00,17.5\n2014-04-18 02:22:00,17.5075\n2014-04-18 02:27:00,17.915\n2014-04-18 02:32:00,16.665\n2014-04-18 02:37:00,17.9175\n2014-04-18 02:42:00,16.6675\n2014-04-18 02:47:00,17.5\n2014-04-18 02:52:00,17.0475\n2014-04-18 02:57:00,17.4975\n2014-04-18 03:02:00,17.0825\n2014-04-18 03:07:00,17.535\n2014-04-18 03:12:00,17.9175\n2014-04-18 03:17:00,17.5\n2014-04-18 03:22:00,17.515\n2014-04-18 03:27:00,17.5\n2014-04-18 03:32:00,16.2525\n2014-04-18 03:37:00,17.9175\n2014-04-18 03:42:00,17.0825\n2014-04-18 03:47:00,17.0825\n2014-04-18 03:52:00,17.4975\n2014-04-18 03:57:00,17.0775\n2014-04-18 04:02:00,16.6675\n2014-04-18 04:07:00,17.3975\n2014-04-18 04:12:00,16.665\n2014-04-18 04:17:00,17.5\n2014-04-18 04:22:00,16.2525\n2014-04-18 04:27:00,17.96\n2014-04-18 04:32:00,16.25\n2014-04-18 04:37:00,17.9175\n2014-04-18 04:42:00,16.665\n2014-04-18 04:47:00,17.0825\n2014-04-18 04:52:00,17.0825\n2014-04-18 04:57:00,17.5\n2014-04-18 05:02:00,16.25\n2014-04-18 05:07:00,17.0825\n2014-04-18 05:12:00,17.0825\n2014-04-18 05:17:00,17.5025\n2014-04-18 05:22:00,16.665\n2014-04-18 05:27:00,17.915\n2014-04-18 05:32:00,16.675\n2014-04-18 05:37:00,17.5\n2014-04-18 05:42:00,16.665\n2014-04-18 05:47:00,17.5\n2014-04-18 05:52:00,16.6675\n2014-04-18 05:57:00,17.5025\n2014-04-18 06:02:00,17.09\n2014-04-18 06:07:00,17.485\n2014-04-18 06:12:00,17.0825\n2014-04-18 06:17:00,17.915\n2014-04-18 06:22:00,16.2525\n2014-04-18 06:27:00,17.5\n2014-04-18 06:32:00,17.0625\n2014-04-18 06:37:00,17.085\n2014-04-18 06:42:00,17.0975\n2014-04-18 06:47:00,16.665\n2014-04-18 06:52:00,16.2525\n2014-04-18 06:57:00,17.915\n2014-04-18 07:02:00,16.25\n2014-04-18 07:07:00,17.5\n2014-04-18 07:12:00,17.4825\n2014-04-18 07:17:00,17.035\n2014-04-18 07:22:00,15.835\n2014-04-18 07:27:00,17.4875\n2014-04-18 07:32:00,17.0825\n2014-04-18 07:37:00,16.6675\n2014-04-18 07:42:00,17.6\n2014-04-18 07:47:00,16.71\n2014-04-18 07:52:00,17.0825\n2014-04-18 07:57:00,20.0\n2014-04-18 08:02:00,17.085\n2014-04-18 08:07:00,17.915\n2014-04-18 08:12:00,16.6675\n2014-04-18 08:17:00,17.8625\n2014-04-18 08:22:00,16.6675\n2014-04-18 08:27:00,17.5\n2014-04-18 08:32:00,17.08\n2014-04-18 08:37:00,16.665\n2014-04-18 08:42:00,17.085\n2014-04-18 08:47:00,17.5\n2014-04-18 08:52:00,16.19\n2014-04-18 08:57:00,17.4625\n2014-04-18 09:02:00,16.6675\n2014-04-18 09:07:00,17.085\n2014-04-18 09:12:00,16.6675\n2014-04-18 09:17:00,17.5\n2014-04-18 09:22:00,16.26\n2014-04-18 09:27:00,17.9175\n2014-04-18 09:32:00,16.25\n2014-04-18 09:37:00,17.32\n2014-04-18 09:42:00,17.0975\n2014-04-18 09:47:00,17.5025\n2014-04-18 09:52:00,16.6825\n2014-04-18 09:57:00,17.9175\n2014-04-18 10:02:00,16.655\n2014-04-18 10:07:00,17.0375\n2014-04-18 10:12:00,17.915\n2014-04-18 10:17:00,17.5\n2014-04-18 10:22:00,16.6825\n2014-04-18 10:27:00,17.5025\n2014-04-18 10:32:00,17.0825\n2014-04-18 10:37:00,17.915\n2014-04-18 10:42:00,17.62\n2014-04-18 10:47:00,17.085\n2014-04-18 10:52:00,16.6675\n2014-04-18 10:57:00,17.9175\n2014-04-18 11:02:00,16.2525\n2014-04-18 11:07:00,18.3325\n2014-04-18 11:12:00,16.6675\n2014-04-18 11:17:00,17.0825\n2014-04-18 11:22:00,16.6675\n2014-04-18 11:27:00,17.5025\n2014-04-18 11:32:00,16.6675\n2014-04-18 11:37:00,17.9175\n2014-04-18 11:42:00,16.7575\n2014-04-18 11:47:00,17.5\n2014-04-18 11:52:00,16.34\n2014-04-18 11:57:00,18.33\n2014-04-18 12:02:00,16.19\n2014-04-18 12:07:00,17.8025\n2014-04-18 12:12:00,17.08\n2014-04-18 12:17:00,17.1825\n2014-04-18 12:22:00,16.25\n2014-04-18 12:27:00,18.3325\n2014-04-18 12:32:00,16.2525\n2014-04-18 12:37:00,17.085\n2014-04-18 12:42:00,16.665\n2014-04-18 12:47:00,16.625\n2014-04-18 12:52:00,17.0825\n2014-04-18 12:57:00,17.5\n2014-04-18 13:02:00,15.835\n2014-04-18 13:07:00,17.5\n2014-04-18 13:12:00,16.2525\n2014-04-18 13:17:00,17.5575\n2014-04-18 13:22:00,17.0825\n2014-04-18 13:27:00,17.8525\n2014-04-18 13:32:00,15.8325\n2014-04-18 13:37:00,17.145\n2014-04-18 13:42:00,17.0825\n2014-04-18 13:47:00,16.665\n2014-04-18 13:52:00,17.0825\n2014-04-18 13:57:00,17.9175\n2014-04-18 14:02:00,16.2525\n2014-04-18 14:07:00,17.5\n2014-04-18 14:12:00,17.0825\n2014-04-18 14:17:00,17.5\n2014-04-18 14:22:00,17.085\n2014-04-18 14:27:00,17.91\n2014-04-18 14:32:00,16.25\n2014-04-18 14:37:00,17.5\n2014-04-18 14:42:00,16.665\n2014-04-18 14:47:00,17.0825\n2014-04-18 14:52:00,16.665\n2014-04-18 14:57:00,17.915\n2014-04-18 15:02:00,16.25\n2014-04-18 15:07:00,16.665\n2014-04-18 15:12:00,16.6675\n2014-04-18 15:17:00,17.915\n2014-04-18 15:22:00,17.0825\n2014-04-18 15:27:00,17.445\n2014-04-18 15:32:00,16.2325\n2014-04-18 15:37:00,17.5925\n2014-04-18 15:42:00,16.25\n2014-04-18 15:47:00,17.0825\n2014-04-18 15:52:00,17.0825\n2014-04-18 15:57:00,17.1975\n2014-04-18 16:02:00,16.665\n2014-04-18 16:07:00,16.6675\n2014-04-18 16:12:00,17.08\n2014-04-18 16:17:00,16.25\n2014-04-18 16:22:00,17.5\n2014-04-18 16:27:00,17.5\n2014-04-18 16:32:00,16.2525\n2014-04-18 16:37:00,17.085\n2014-04-18 16:42:00,16.61\n2014-04-18 16:47:00,17.0825\n2014-04-18 16:52:00,16.665\n2014-04-18 16:57:00,17.5\n2014-04-18 17:02:00,17.5\n2014-04-18 17:07:00,17.915\n2014-04-18 17:12:00,17.0825\n2014-04-18 17:17:00,17.9175\n2014-04-18 17:22:00,16.2475\n2014-04-18 17:27:00,17.085\n2014-04-18 17:32:00,16.25\n2014-04-18 17:37:00,17.5\n2014-04-18 17:42:00,17.1875\n2014-04-18 17:47:00,17.0825\n2014-04-18 17:52:00,17.5\n2014-04-18 17:57:00,17.19\n2014-04-18 18:02:00,17.5225\n2014-04-18 18:07:00,18.3325\n2014-04-18 18:12:00,16.6675\n2014-04-18 18:17:00,16.25\n2014-04-18 18:22:00,16.25\n2014-04-18 18:27:00,18.035\n2014-04-18 18:32:00,16.6675\n2014-04-18 18:37:00,17.4525\n2014-04-18 18:42:00,16.2525\n2014-04-18 18:47:00,17.0825\n2014-04-18 18:52:00,16.2525\n2014-04-18 18:57:00,17.0725\n2014-04-18 19:02:00,17.0275\n2014-04-18 19:07:00,16.6675\n2014-04-18 19:12:00,16.64\n2014-04-18 19:17:00,17.5\n2014-04-18 19:22:00,17.0975\n2014-04-18 19:27:00,17.855\n2014-04-18 19:32:00,16.25\n2014-04-18 19:37:00,16.665\n2014-04-18 19:42:00,16.6675\n2014-04-18 19:47:00,17.0825\n2014-04-18 19:52:00,16.23\n2014-04-18 19:57:00,19.2575\n2014-04-18 20:02:00,16.2525\n2014-04-18 20:07:00,17.9175\n2014-04-18 20:12:00,17.085\n2014-04-18 20:17:00,17.145\n2014-04-18 20:22:00,17.085\n2014-04-18 20:27:00,17.9175\n2014-04-18 20:32:00,16.34\n2014-04-18 20:37:00,17.5\n2014-04-18 20:42:00,17.0825\n2014-04-18 20:47:00,17.0825\n2014-04-18 20:52:00,17.0825\n2014-04-18 20:57:00,17.5\n2014-04-18 21:02:00,16.6825\n2014-04-18 21:07:00,17.5\n2014-04-18 21:12:00,16.665\n2014-04-18 21:17:00,17.5\n2014-04-18 21:22:00,16.2325\n2014-04-18 21:27:00,18.335\n2014-04-18 21:32:00,16.665\n2014-04-18 21:37:00,17.09\n2014-04-18 21:42:00,17.4375\n2014-04-18 21:47:00,17.0825\n2014-04-18 21:52:00,16.7575\n2014-04-18 21:57:00,17.4375\n2014-04-18 22:02:00,15.845\n2014-04-18 22:07:00,17.925\n2014-04-18 22:12:00,16.25\n2014-04-18 22:17:00,17.5\n2014-04-18 22:22:00,17.045\n2014-04-18 22:27:00,18.3325\n2014-04-18 22:32:00,17.0825\n2014-04-18 22:37:00,17.5\n2014-04-18 22:42:00,16.6125\n2014-04-18 22:47:00,17.085\n2014-04-18 22:52:00,15.835\n2014-04-18 22:57:00,17.5025\n2014-04-18 23:02:00,17.0825\n2014-04-18 23:07:00,17.915\n2014-04-18 23:12:00,17.085\n2014-04-18 23:17:00,18.33\n2014-04-18 23:22:00,16.25\n2014-04-18 23:27:00,25.11\n2014-04-18 23:32:00,26.665\n2014-04-18 23:37:00,27.405\n2014-04-18 23:42:00,28.475\n2014-04-18 23:47:00,27.9175\n2014-04-18 23:52:00,27.085\n2014-04-18 23:57:00,29.73\n2014-04-19 00:02:00,27.5\n2014-04-19 00:07:00,28.75\n2014-04-19 00:12:00,28.75\n2014-04-19 00:17:00,29.165\n2014-04-19 00:22:00,26.665\n2014-04-19 00:27:00,27.4975\n2014-04-19 00:32:00,28.3325\n2014-04-19 00:37:00,27.0825\n2014-04-19 00:42:00,27.635\n2014-04-19 00:47:00,27.6525\n2014-04-19 00:52:00,27.4975\n2014-04-19 00:57:00,27.5\n2014-04-19 01:02:00,27.9175\n2014-04-19 01:07:00,27.92\n2014-04-19 01:12:00,29.225\n2014-04-19 01:17:00,28.75\n2014-04-19 01:22:00,29.1675\n2014-04-19 01:27:00,28.3325\n2014-04-19 01:32:00,28.3325\n2014-04-19 01:37:00,27.9175\n2014-04-19 01:42:00,27.0825\n2014-04-19 01:47:00,27.045\n2014-04-19 01:52:00,27.5\n2014-04-19 01:57:00,27.4975\n2014-04-19 02:02:00,27.0475\n2014-04-19 02:07:00,27.9175\n2014-04-19 02:12:00,26.6675\n2014-04-19 02:17:00,29.5875\n2014-04-19 02:22:00,27.5\n2014-04-19 02:27:00,28.75\n2014-04-19 02:32:00,28.875\n2014-04-19 02:37:00,27.0825\n2014-04-19 02:42:00,27.915\n2014-04-19 02:47:00,28.32\n2014-04-19 02:52:00,26.25\n2014-04-19 02:57:00,28.335\n2014-04-19 03:02:00,26.64\n2014-04-19 03:07:00,27.085\n2014-04-19 03:12:00,26.225\n2014-04-19 03:17:00,28.7475\n2014-04-19 03:22:00,27.88\n2014-04-19 03:27:00,28.7525\n2014-04-19 03:32:00,28.75\n2014-04-19 03:37:00,28.75\n2014-04-19 03:42:00,28.3325\n2014-04-19 03:47:00,28.3325\n2014-04-19 03:52:00,26.39\n2014-04-19 03:57:00,29.1225\n2014-04-19 04:02:00,27.5\n2014-04-19 04:07:00,25.9725\n2014-04-19 04:12:00,27.085\n2014-04-19 04:17:00,27.24\n2014-04-19 04:22:00,27.085\n2014-04-19 04:27:00,27.5\n2014-04-19 04:32:00,27.5\n2014-04-19 04:37:00,26.6425\n2014-04-19 04:42:00,26.2475\n2014-04-19 04:47:00,27.0825\n2014-04-19 04:52:00,26.25\n2014-04-19 04:57:00,28.75\n2014-04-19 05:02:00,27.3975\n2014-04-19 05:07:00,27.9175\n2014-04-19 05:12:00,28.3325\n2014-04-19 05:17:00,27.9175\n2014-04-19 05:22:00,28.05\n2014-04-19 05:27:00,28.33\n2014-04-19 05:32:00,26.6675\n2014-04-19 05:37:00,27.9125\n2014-04-19 05:42:00,26.665\n2014-04-19 05:47:00,27.9175\n2014-04-19 05:52:00,27.0925\n2014-04-19 05:57:00,29.585\n2014-04-19 06:02:00,27.225\n2014-04-19 06:07:00,28.335\n2014-04-19 06:12:00,26.6675\n2014-04-19 06:17:00,29.5825\n2014-04-19 06:22:00,27.6425\n2014-04-19 06:27:00,29.585\n2014-04-19 06:32:00,26.665\n2014-04-19 06:37:00,28.33\n2014-04-19 06:42:00,28.2325\n2014-04-19 06:47:00,27.0825\n2014-04-19 06:52:00,27.0825\n2014-04-19 06:57:00,27.8675\n2014-04-19 07:02:00,26.2525\n2014-04-19 07:07:00,27.5\n2014-04-19 07:12:00,28.3325\n2014-04-19 07:17:00,27.4425\n2014-04-19 07:22:00,26.6475\n2014-04-19 07:27:00,27.9175\n2014-04-19 07:32:00,26.2475\n2014-04-19 07:37:00,28.3325\n2014-04-19 07:42:00,27.4975\n2014-04-19 07:47:00,27.5\n2014-04-19 07:52:00,28.335\n2014-04-19 07:57:00,28.7525\n2014-04-19 08:02:00,27.0825\n2014-04-19 08:07:00,26.6675\n2014-04-19 08:12:00,28.75\n2014-04-19 08:17:00,30.0025\n2014-04-19 08:22:00,28.335\n2014-04-19 08:27:00,29.22\n2014-04-19 08:32:00,27.4975\n2014-04-19 08:37:00,29.165\n2014-04-19 08:42:00,27.065\n2014-04-19 08:47:00,28.75\n2014-04-19 08:52:00,28.3325\n2014-04-19 08:57:00,28.3275\n2014-04-19 09:02:00,27.605\n2014-04-19 09:07:00,27.9175\n2014-04-19 09:12:00,28.75\n2014-04-19 09:17:00,28.6475\n2014-04-19 09:22:00,26.6675\n2014-04-19 09:27:00,27.5025\n2014-04-19 09:32:00,28.3325\n2014-04-19 09:37:00,28.8475\n2014-04-19 09:42:00,26.7725\n2014-04-19 09:47:00,29.5825\n2014-04-19 09:52:00,26.6675\n2014-04-19 09:57:00,27.8925\n2014-04-19 10:02:00,27.0825\n2014-04-19 10:07:00,29.165\n2014-04-19 10:12:00,27.915\n2014-04-19 10:17:00,27.915\n2014-04-19 10:22:00,28.3325\n2014-04-19 10:27:00,28.3325\n2014-04-19 10:32:00,27.915\n2014-04-19 10:37:00,27.0825\n2014-04-19 10:42:00,28.3325\n2014-04-19 10:47:00,28.3325\n2014-04-19 10:52:00,27.0825\n2014-04-19 10:57:00,28.335\n2014-04-19 11:02:00,27.5\n2014-04-19 11:07:00,28.7475\n2014-04-19 11:12:00,28.8625\n2014-04-19 11:17:00,29.27\n2014-04-19 11:22:00,27.0825\n2014-04-19 11:27:00,28.7475\n2014-04-19 11:32:00,28.75\n2014-04-19 11:37:00,28.3325\n2014-04-19 11:42:00,27.9175\n2014-04-19 11:47:00,28.75\n2014-04-19 11:52:00,27.085\n2014-04-19 11:57:00,28.75\n2014-04-19 12:02:00,27.915\n2014-04-19 12:07:00,27.96\n2014-04-19 12:12:00,28.335\n2014-04-19 12:17:00,27.915\n2014-04-19 12:22:00,27.915\n2014-04-19 12:27:00,30.0\n2014-04-19 12:32:00,25.835\n2014-04-19 12:37:00,27.4975\n2014-04-19 12:42:00,28.7275\n2014-04-19 12:47:00,27.0825\n2014-04-19 12:52:00,27.0825\n2014-04-19 12:57:00,29.165\n2014-04-19 13:02:00,26.665\n2014-04-19 13:07:00,28.75\n2014-04-19 13:12:00,26.7975\n2014-04-19 13:17:00,28.335\n2014-04-19 13:22:00,27.085\n2014-04-19 13:27:00,27.47\n2014-04-19 13:32:00,28.3325\n2014-04-19 13:37:00,28.335\n2014-04-19 13:42:00,27.5025\n2014-04-19 13:47:00,28.335\n2014-04-19 13:52:00,26.2525\n2014-04-19 13:57:00,29.1675\n2014-04-19 14:02:00,27.0825\n2014-04-19 14:07:00,27.9175\n2014-04-19 14:12:00,29.1675\n2014-04-19 14:17:00,28.7525\n2014-04-19 14:22:00,27.5025\n2014-04-19 14:27:00,27.915\n2014-04-19 14:32:00,26.565\n2014-04-19 14:37:00,28.7525\n2014-04-19 14:42:00,27.435\n2014-04-19 14:47:00,28.3325\n2014-04-19 14:52:00,28.3325\n2014-04-19 14:57:00,27.5025\n2014-04-19 15:02:00,28.7475\n2014-04-19 15:07:00,28.75\n2014-04-19 15:12:00,27.915\n2014-04-19 15:17:00,29.9975\n2014-04-19 15:22:00,27.0825\n2014-04-19 15:27:00,27.915\n2014-04-19 15:32:00,27.915\n2014-04-19 15:37:00,27.9175\n2014-04-19 15:42:00,27.5\n2014-04-19 15:47:00,27.4975\n2014-04-19 15:52:00,27.4975\n2014-04-19 15:57:00,27.085\n2014-04-19 16:02:00,27.915\n2014-04-19 16:07:00,27.655\n2014-04-19 16:12:00,28.3325\n2014-04-19 16:17:00,29.5825\n2014-04-19 16:22:00,27.915\n2014-04-19 16:27:00,28.91\n2014-04-19 16:32:00,26.6675\n2014-04-19 16:37:00,28.75\n2014-04-19 16:42:00,27.88\n2014-04-19 16:47:00,27.5\n2014-04-19 16:52:00,27.5\n2014-04-19 16:57:00,28.75\n2014-04-19 17:02:00,26.6775\n2014-04-19 17:07:00,27.455\n2014-04-19 17:12:00,28.75\n2014-04-19 17:17:00,28.335\n2014-04-19 17:22:00,27.4975\n2014-04-19 17:27:00,29.5725\n2014-04-19 17:32:00,25.8325\n2014-04-19 17:37:00,27.0725\n2014-04-19 17:42:00,27.4975\n2014-04-19 17:47:00,28.65\n2014-04-19 17:52:00,27.9175\n2014-04-19 17:57:00,27.88\n2014-04-19 18:02:00,28.23\n2014-04-19 18:07:00,27.9175\n2014-04-19 18:12:00,27.6425\n2014-04-19 18:17:00,29.585\n2014-04-19 18:22:00,27.6575\n2014-04-19 18:27:00,30.1025\n2014-04-19 18:32:00,27.6475\n2014-04-19 18:37:00,27.5\n2014-04-19 18:42:00,28.76\n2014-04-19 18:47:00,28.495\n2014-04-19 18:52:00,26.225\n2014-04-19 18:57:00,29.1675\n2014-04-19 19:02:00,27.9\n2014-04-19 19:07:00,28.2975\n2014-04-19 19:12:00,29.4825\n2014-04-19 19:17:00,28.38\n2014-04-19 19:22:00,29.165\n2014-04-19 19:27:00,28.3225\n2014-04-19 19:32:00,26.6675\n2014-04-19 19:37:00,28.76\n2014-04-19 19:42:00,26.6675\n2014-04-19 19:47:00,27.905\n2014-04-19 19:52:00,26.25\n2014-04-19 19:57:00,28.75\n2014-04-19 20:02:00,26.5625\n2014-04-19 20:07:00,28.75\n2014-04-19 20:12:00,27.915\n2014-04-19 20:17:00,27.6425\n2014-04-19 20:22:00,27.5\n2014-04-19 20:27:00,28.335\n2014-04-19 20:32:00,26.98\n2014-04-19 20:37:00,28.225\n2014-04-19 20:42:00,27.0825\n2014-04-19 20:47:00,27.9175\n2014-04-19 20:52:00,27.4975\n2014-04-19 20:57:00,28.3325\n2014-04-19 21:02:00,27.5\n2014-04-19 21:07:00,31.5225\n2014-04-19 21:12:00,28.4375\n2014-04-19 21:17:00,29.1675\n2014-04-19 21:22:00,27.915\n2014-04-19 21:27:00,29.3225\n2014-04-19 21:32:00,28.335\n2014-04-19 21:37:00,27.0825\n2014-04-19 21:42:00,28.3325\n2014-04-19 21:47:00,27.9175\n2014-04-19 21:52:00,26.25\n2014-04-19 21:57:00,27.5\n2014-04-19 22:02:00,27.38\n2014-04-19 22:07:00,29.1675\n2014-04-19 22:12:00,27.915\n2014-04-19 22:17:00,29.89\n2014-04-19 22:22:00,27.0825\n2014-04-19 22:27:00,27.5\n2014-04-19 22:32:00,27.64\n2014-04-19 22:37:00,27.915\n2014-04-19 22:42:00,27.5\n2014-04-19 22:47:00,28.7525\n2014-04-19 22:52:00,27.4575\n2014-04-19 22:57:00,27.4975\n2014-04-19 23:02:00,28.0575\n2014-04-19 23:07:00,29.585\n2014-04-19 23:12:00,29.1675\n2014-04-19 23:17:00,27.92\n2014-04-19 23:22:00,27.9175\n2014-04-19 23:27:00,27.5025\n2014-04-19 23:32:00,27.0825\n2014-04-19 23:37:00,27.9175\n2014-04-19 23:42:00,27.215\n2014-04-19 23:47:00,27.9175\n2014-04-19 23:52:00,27.9175\n2014-04-19 23:57:00,28.685\n2014-04-20 00:02:00,27.0675\n2014-04-20 00:07:00,28.335\n2014-04-20 00:12:00,27.915\n2014-04-20 00:17:00,28.75\n2014-04-20 00:22:00,27.5\n2014-04-20 00:27:00,29.5825\n2014-04-20 00:32:00,27.085\n2014-04-20 00:37:00,28.485\n2014-04-20 00:42:00,27.8125\n2014-04-20 00:47:00,27.9125\n2014-04-20 00:52:00,28.75\n2014-04-20 00:57:00,28.3325\n2014-04-20 01:02:00,26.665\n2014-04-20 01:07:00,28.7525\n2014-04-20 01:12:00,29.1675\n2014-04-20 01:17:00,28.69\n2014-04-20 01:22:00,28.3325\n2014-04-20 01:27:00,28.49\n2014-04-20 01:32:00,27.5\n2014-04-20 01:37:00,27.8225\n2014-04-20 01:42:00,28.315\n2014-04-20 01:47:00,27.9175\n2014-04-20 01:52:00,27.085\n2014-04-20 01:57:00,29.3225\n2014-04-20 02:02:00,27.5\n2014-04-20 02:07:00,28.7525\n2014-04-20 02:12:00,27.3975\n2014-04-20 02:17:00,29.1675\n2014-04-20 02:22:00,27.915\n2014-04-20 02:27:00,28.4875\n2014-04-20 02:32:00,29.1675\n2014-04-20 02:37:00,28.3325\n2014-04-20 02:42:00,27.0825\n2014-04-20 02:47:00,27.49\n2014-04-20 02:52:00,28.0575\n2014-04-20 02:57:00,27.92\n2014-04-20 03:02:00,27.0675\n2014-04-20 03:07:00,30.7625\n2014-04-20 03:12:00,28.7675\n2014-04-20 03:17:00,28.74\n2014-04-20 03:22:00,28.365\n2014-04-20 03:27:00,28.75\n2014-04-20 03:32:00,29.1775\n2014-04-20 03:37:00,27.82\n2014-04-20 03:42:00,30.12\n2014-04-20 03:47:00,30.0675\n2014-04-20 03:52:00,28.3325\n2014-04-20 03:57:00,30.0\n2014-04-20 04:02:00,26.6575\n2014-04-20 04:07:00,30.0\n2014-04-20 04:12:00,27.5\n2014-04-20 04:17:00,28.75\n2014-04-20 04:22:00,27.915\n2014-04-20 04:27:00,28.75\n2014-04-20 04:32:00,27.915\n2014-04-20 04:37:00,29.1675\n2014-04-20 04:42:00,27.9075\n2014-04-20 04:47:00,28.75\n2014-04-20 04:52:00,27.4975\n2014-04-20 04:57:00,28.75\n2014-04-20 05:02:00,28.75\n2014-04-20 05:07:00,27.5\n2014-04-20 05:12:00,27.4975\n2014-04-20 05:17:00,28.7525\n2014-04-20 05:22:00,26.6675\n2014-04-20 05:27:00,29.1225\n2014-04-20 05:32:00,27.4975\n2014-04-20 05:37:00,27.5\n2014-04-20 05:42:00,28.75\n2014-04-20 05:47:00,28.335\n2014-04-20 05:52:00,27.4975\n2014-04-20 05:57:00,29.1675\n2014-04-20 06:02:00,26.98\n2014-04-20 06:07:00,28.7525\n2014-04-20 06:12:00,28.75\n2014-04-20 06:17:00,28.49\n2014-04-20 06:22:00,27.085\n2014-04-20 06:27:00,29.4675\n2014-04-20 06:32:00,27.0825\n2014-04-20 06:37:00,28.445\n2014-04-20 06:42:00,28.365\n2014-04-20 06:47:00,27.9175\n2014-04-20 06:52:00,27.895\n2014-04-20 06:57:00,29.6225\n2014-04-20 07:02:00,27.9\n2014-04-20 07:07:00,28.335\n2014-04-20 07:12:00,27.0925\n2014-04-20 07:17:00,27.2325\n2014-04-20 07:22:00,27.915\n2014-04-20 07:27:00,27.5\n2014-04-20 07:32:00,28.3325\n2014-04-20 07:37:00,27.5\n2014-04-20 07:42:00,27.925\n2014-04-20 07:47:00,27.9175\n2014-04-20 07:52:00,27.0675\n2014-04-20 07:57:00,32.5\n2014-04-20 08:02:00,27.5\n2014-04-20 08:07:00,27.9175\n2014-04-20 08:12:00,28.75\n2014-04-20 08:17:00,28.38\n2014-04-20 08:22:00,27.915\n2014-04-20 08:27:00,28.4875\n2014-04-20 08:32:00,27.365\n2014-04-20 08:37:00,28.335\n2014-04-20 08:42:00,29.1675\n2014-04-20 08:47:00,28.175\n2014-04-20 08:52:00,27.9175\n2014-04-20 08:57:00,28.8325\n2014-04-20 09:02:00,27.375\n2014-04-20 09:07:00,27.9175\n2014-04-20 09:12:00,28.645\n2014-04-20 09:17:00,27.5025\n2014-04-20 09:22:00,27.5\n2014-04-20 09:27:00,29.165\n2014-04-20 09:32:00,27.9175\n2014-04-20 09:37:00,28.335\n2014-04-20 09:42:00,27.4975\n2014-04-20 09:47:00,27.9175\n2014-04-20 09:52:00,27.9175\n2014-04-20 09:57:00,27.915\n2014-04-20 10:02:00,28.365\n2014-04-20 10:07:00,26.63\n2014-04-20 10:12:00,28.75\n2014-04-20 10:17:00,27.9175\n2014-04-20 10:22:00,27.4975\n2014-04-20 10:27:00,27.9625\n2014-04-20 10:32:00,28.475\n2014-04-20 10:37:00,28.335\n2014-04-20 10:42:00,27.915\n2014-04-20 10:47:00,28.7475\n2014-04-20 10:52:00,27.5\n2014-04-20 10:57:00,28.7475\n2014-04-20 11:02:00,27.53\n2014-04-20 11:07:00,28.3325\n2014-04-20 11:12:00,28.3325\n2014-04-20 11:17:00,29.1675\n2014-04-20 11:22:00,27.0575\n2014-04-20 11:27:00,29.1675\n2014-04-20 11:32:00,28.005\n2014-04-20 11:37:00,27.45\n2014-04-20 11:42:00,28.2375\n2014-04-20 11:47:00,27.5025\n2014-04-20 11:52:00,27.5025\n2014-04-20 11:57:00,29.1625\n2014-04-20 12:02:00,27.915\n2014-04-20 12:07:00,27.5025\n2014-04-20 12:12:00,27.2225\n2014-04-20 12:17:00,28.7525\n2014-04-20 12:22:00,27.08\n2014-04-20 12:27:00,27.5\n2014-04-20 12:32:00,27.5\n2014-04-20 12:37:00,28.75\n2014-04-20 12:42:00,27.5075\n2014-04-20 12:47:00,28.75\n2014-04-20 12:52:00,27.5075\n2014-04-20 12:57:00,28.75\n2014-04-20 13:02:00,27.0825\n2014-04-20 13:07:00,27.645\n2014-04-20 13:12:00,28.3325\n2014-04-20 13:17:00,27.9175\n2014-04-20 13:22:00,28.05\n2014-04-20 13:27:00,27.915\n2014-04-20 13:32:00,26.6675\n2014-04-20 13:37:00,28.7525\n2014-04-20 13:42:00,27.5\n2014-04-20 13:47:00,27.5\n2014-04-20 13:52:00,27.9175\n2014-04-20 13:57:00,27.915\n2014-04-20 14:02:00,28.475\n2014-04-20 14:07:00,29.155\n2014-04-20 14:12:00,27.0825\n2014-04-20 14:17:00,28.335\n2014-04-20 14:22:00,28.335\n2014-04-20 14:27:00,27.5\n2014-04-20 14:32:00,27.915\n2014-04-20 14:37:00,27.9175\n2014-04-20 14:42:00,27.915\n2014-04-20 14:47:00,27.5\n2014-04-20 14:52:00,27.5\n2014-04-20 14:57:00,29.1675\n2014-04-20 15:02:00,26.665\n2014-04-20 15:07:00,29.1675\n2014-04-20 15:12:00,28.295\n2014-04-20 15:17:00,27.9175\n2014-04-20 15:22:00,27.5\n2014-04-20 15:27:00,30.4175\n2014-04-20 15:32:00,27.5\n2014-04-20 15:37:00,28.7525\n2014-04-20 15:42:00,29.1675\n2014-04-20 15:47:00,28.75\n2014-04-20 15:52:00,28.2\n2014-04-20 15:57:00,28.715\n2014-04-20 16:02:00,28.75\n2014-04-20 16:07:00,27.9125\n2014-04-20 16:12:00,28.7525\n2014-04-20 16:17:00,29.1625\n2014-04-20 16:22:00,27.5\n2014-04-20 16:27:00,29.1675\n2014-04-20 16:32:00,27.915\n2014-04-20 16:37:00,29.33\n2014-04-20 16:42:00,27.6425\n2014-04-20 16:47:00,28.3375\n2014-04-20 16:52:00,27.5025\n2014-04-20 16:57:00,29.165\n2014-04-20 17:02:00,28.1925\n2014-04-20 17:07:00,29.58\n2014-04-20 17:12:00,28.3325\n2014-04-20 17:17:00,27.9175\n2014-04-20 17:22:00,27.08\n2014-04-20 17:27:00,28.7475\n2014-04-20 17:32:00,28.3325\n2014-04-20 17:37:00,27.59\n2014-04-20 17:42:00,28.3325\n2014-04-20 17:47:00,27.445\n2014-04-20 17:52:00,27.5\n2014-04-20 17:57:00,28.3325\n2014-04-20 18:02:00,28.75\n2014-04-20 18:07:00,29.1675\n2014-04-20 18:12:00,29.1675\n2014-04-20 18:17:00,27.9175\n2014-04-20 18:22:00,27.0825\n2014-04-20 18:27:00,29.215\n2014-04-20 18:32:00,26.8\n2014-04-20 18:37:00,28.4275\n2014-04-20 18:42:00,28.3325\n2014-04-20 18:47:00,28.3225\n2014-04-20 18:52:00,27.5025\n2014-04-20 18:57:00,29.165\n2014-04-20 19:02:00,27.4825\n2014-04-20 19:07:00,29.9975\n2014-04-20 19:12:00,27.5\n2014-04-20 19:17:00,27.915\n2014-04-20 19:22:00,28.3325\n2014-04-20 19:27:00,27.815\n2014-04-20 19:32:00,27.5\n2014-04-20 19:37:00,27.5\n2014-04-20 19:42:00,28.3325\n2014-04-20 19:47:00,27.5\n2014-04-20 19:52:00,27.085\n2014-04-20 19:57:00,29.165\n2014-04-20 20:02:00,27.915\n2014-04-20 20:07:00,29.89\n2014-04-20 20:12:00,27.4975\n2014-04-20 20:17:00,28.335\n2014-04-20 20:22:00,27.4825\n2014-04-20 20:27:00,27.47\n2014-04-20 20:32:00,27.94\n2014-04-20 20:37:00,28.335\n2014-04-20 20:42:00,27.5\n2014-04-20 20:47:00,27.815\n2014-04-20 20:52:00,28.8975\n2014-04-20 20:57:00,29.165\n2014-04-20 21:02:00,26.6675\n2014-04-20 21:07:00,29.5825\n2014-04-20 21:12:00,27.4975\n2014-04-20 21:17:00,27.9175\n2014-04-20 21:22:00,27.915\n2014-04-20 21:27:00,29.42\n2014-04-20 21:32:00,28.36\n2014-04-20 21:37:00,28.335\n2014-04-20 21:42:00,28.75\n2014-04-20 21:47:00,27.6425\n2014-04-20 21:52:00,27.5025\n2014-04-20 21:57:00,28.75\n2014-04-20 22:02:00,27.0825\n2014-04-20 22:07:00,29.5825\n2014-04-20 22:12:00,28.755\n2014-04-20 22:17:00,28.7525\n2014-04-20 22:22:00,29.165\n2014-04-20 22:27:00,29.745\n2014-04-20 22:32:00,27.4975\n2014-04-20 22:37:00,29.1675\n2014-04-20 22:42:00,27.4975\n2014-04-20 22:47:00,27.9175\n2014-04-20 22:52:00,28.3325\n2014-04-20 22:57:00,28.49\n2014-04-20 23:02:00,27.9175\n2014-04-20 23:07:00,26.6675\n2014-04-20 23:12:00,27.4975\n2014-04-20 23:17:00,28.3325\n2014-04-20 23:22:00,28.3225\n2014-04-20 23:27:00,28.7525\n2014-04-20 23:32:00,27.0825\n2014-04-20 23:37:00,27.0825\n2014-04-20 23:42:00,28.3325\n2014-04-20 23:47:00,27.5\n2014-04-20 23:52:00,28.3325\n2014-04-20 23:57:00,29.045\n2014-04-21 00:02:00,26.565\n2014-04-21 00:07:00,29.8325\n2014-04-21 00:12:00,28.3325\n2014-04-21 00:17:00,28.3325\n2014-04-21 00:22:00,27.5\n2014-04-21 00:27:00,27.9175\n2014-04-21 00:32:00,27.925\n2014-04-21 00:37:00,27.5\n2014-04-21 00:42:00,28.725\n2014-04-21 00:47:00,28.7475\n2014-04-21 00:52:00,26.67\n2014-04-21 00:57:00,29.5825\n2014-04-21 01:02:00,27.0825\n2014-04-21 01:07:00,27.9175\n2014-04-21 01:12:00,29.5825\n2014-04-21 01:17:00,27.915\n2014-04-21 01:22:00,26.635\n2014-04-21 01:27:00,29.5825\n2014-04-21 01:32:00,30.0025\n2014-04-21 01:37:00,27.915\n2014-04-21 01:42:00,28.3325\n2014-04-21 01:47:00,27.915\n2014-04-21 01:52:00,27.5\n2014-04-21 01:57:00,28.7475\n2014-04-21 02:02:00,26.7725\n2014-04-21 02:07:00,27.6475\n2014-04-21 02:12:00,28.3325\n2014-04-21 02:17:00,27.5\n2014-04-21 02:22:00,28.75\n2014-04-21 02:27:00,29.3225\n2014-04-21 02:32:00,29.585\n2014-04-21 02:37:00,28.335\n2014-04-21 02:42:00,28.06\n2014-04-21 02:47:00,28.3325\n2014-04-21 02:52:00,27.085\n2014-04-21 02:57:00,29.155\n2014-04-21 03:02:00,27.4825\n2014-04-21 03:07:00,27.9175\n2014-04-21 03:12:00,28.3325\n2014-04-21 03:17:00,27.8075\n2014-04-21 03:22:00,28.3325\n2014-04-21 03:27:00,28.7675\n2014-04-21 03:32:00,27.915\n2014-04-21 03:37:00,28.8575\n2014-04-21 03:42:00,27.5\n2014-04-21 03:47:00,27.9175\n2014-04-21 03:52:00,28.75\n2014-04-21 03:57:00,28.75\n2014-04-21 04:02:00,28.335\n2014-04-21 04:07:00,28.75\n2014-04-21 04:12:00,27.4975\n2014-04-21 04:17:00,28.335\n2014-04-21 04:22:00,27.485\n2014-04-21 04:27:00,30.0525\n2014-04-21 04:32:00,27.4975\n2014-04-21 04:37:00,29.1675\n2014-04-21 04:42:00,27.885\n2014-04-21 04:47:00,27.9175\n2014-04-21 04:52:00,28.3325\n2014-04-21 04:57:00,28.3325\n2014-04-21 05:02:00,27.4775\n2014-04-21 05:07:00,29.165\n2014-04-21 05:12:00,27.4975\n2014-04-21 05:17:00,29.1675\n2014-04-21 05:22:00,27.645\n2014-04-21 05:27:00,27.5\n2014-04-21 05:32:00,27.5\n2014-04-21 05:37:00,29.07\n2014-04-21 05:42:00,28.3325\n2014-04-21 05:47:00,29.17\n2014-04-21 05:52:00,27.5\n2014-04-21 05:57:00,28.3325\n2014-04-21 06:02:00,27.08\n2014-04-21 06:07:00,27.6425\n2014-04-21 06:12:00,27.4975\n2014-04-21 06:17:00,28.3325\n2014-04-21 06:22:00,27.49\n2014-04-21 06:27:00,28.07\n2014-04-21 06:32:00,27.9175\n2014-04-21 06:37:00,27.9175\n2014-04-21 06:42:00,27.5175\n2014-04-21 06:47:00,29.165\n2014-04-21 06:52:00,27.0925\n2014-04-21 06:57:00,29.0575\n2014-04-21 07:02:00,28.3325\n2014-04-21 07:07:00,27.5\n2014-04-21 07:12:00,28.75\n2014-04-21 07:17:00,27.5\n2014-04-21 07:22:00,27.1975\n2014-04-21 07:27:00,28.75\n2014-04-21 07:32:00,27.5\n2014-04-21 07:37:00,27.915\n2014-04-21 07:42:00,28.7475\n2014-04-21 07:47:00,27.9175\n2014-04-21 07:52:00,28.295\n2014-04-21 07:57:00,28.75\n2014-04-21 08:02:00,26.8\n2014-04-21 08:07:00,28.3325\n2014-04-21 08:12:00,28.475\n2014-04-21 08:17:00,27.0825\n2014-04-21 08:22:00,27.915\n2014-04-21 08:27:00,29.065\n2014-04-21 08:32:00,27.2175\n2014-04-21 08:37:00,28.2875\n2014-04-21 08:42:00,28.64\n2014-04-21 08:47:00,27.9175\n2014-04-21 08:52:00,28.3325\n2014-04-21 08:57:00,27.915\n2014-04-21 09:02:00,26.6675\n2014-04-21 09:07:00,27.0425\n2014-04-21 09:12:00,27.4875\n2014-04-21 09:17:00,27.0875\n2014-04-21 09:22:00,27.0825\n2014-04-21 09:27:00,29.99\n2014-04-21 09:32:00,26.6675\n2014-04-21 09:37:00,28.275\n2014-04-21 09:42:00,28.335\n2014-04-21 09:47:00,27.085\n2014-04-21 09:52:00,27.1875\n2014-04-21 09:57:00,29.5825\n2014-04-21 10:02:00,28.3575\n2014-04-21 10:07:00,28.7225\n2014-04-21 10:12:00,29.585\n2014-04-21 10:17:00,27.9175\n2014-04-21 10:22:00,27.485\n2014-04-21 10:27:00,29.585\n2014-04-21 10:32:00,27.8075\n2014-04-21 10:37:00,27.0825\n2014-04-21 10:42:00,28.7525\n2014-04-21 10:47:00,27.5\n2014-04-21 10:52:00,27.5\n2014-04-21 10:57:00,28.335\n2014-04-21 11:02:00,26.25\n2014-04-21 11:07:00,27.495\n2014-04-21 11:12:00,27.64\n2014-04-21 11:17:00,29.1675\n2014-04-21 11:22:00,28.19\n2014-04-21 11:27:00,28.7525\n2014-04-21 11:32:00,27.915\n2014-04-21 11:37:00,28.75\n2014-04-21 11:42:00,27.5\n2014-04-21 11:47:00,28.6475\n2014-04-21 11:52:00,27.5\n2014-04-21 11:57:00,29.1675\n2014-04-21 12:02:00,27.47\n2014-04-21 12:07:00,28.345\n2014-04-21 12:12:00,29.165\n2014-04-21 12:17:00,27.0825\n2014-04-21 12:22:00,27.9125\n2014-04-21 12:27:00,28.3325\n2014-04-21 12:32:00,27.0825\n2014-04-21 12:37:00,29.575\n2014-04-21 12:42:00,28.0575\n2014-04-21 12:47:00,27.9175\n2014-04-21 12:52:00,25.8325\n2014-04-21 12:57:00,28.72\n2014-04-21 13:02:00,28.3325\n2014-04-21 13:07:00,27.9175\n2014-04-21 13:12:00,28.75\n2014-04-21 13:17:00,27.5\n2014-04-21 13:22:00,27.4975\n2014-04-21 13:27:00,29.1625\n2014-04-21 13:32:00,27.0825\n2014-04-21 13:37:00,28.8975\n2014-04-21 13:42:00,27.5\n2014-04-21 13:47:00,27.5\n2014-04-21 13:52:00,28.335\n2014-04-21 13:57:00,29.5825\n2014-04-21 14:02:00,27.1\n2014-04-21 14:07:00,29.615\n2014-04-21 14:12:00,28.3325\n2014-04-21 14:17:00,27.9075\n2014-04-21 14:22:00,27.915\n2014-04-21 14:27:00,28.75\n2014-04-21 14:32:00,27.915\n2014-04-21 14:37:00,30.0\n2014-04-21 14:42:00,27.085\n2014-04-21 14:47:00,28.3325\n2014-04-21 14:52:00,27.39\n2014-04-21 14:57:00,28.3325\n2014-04-21 15:02:00,27.0825\n2014-04-21 15:07:00,29.5925\n2014-04-21 15:12:00,27.5\n2014-04-21 15:17:00,28.7475\n2014-04-21 15:22:00,27.47\n2014-04-21 15:27:00,28.335\n2014-04-21 15:32:00,27.4975\n2014-04-21 15:37:00,27.9175\n2014-04-21 15:42:00,28.335\n2014-04-21 15:47:00,28.75\n2014-04-21 15:52:00,27.085\n2014-04-21 15:57:00,29.1675\n2014-04-21 16:02:00,27.0825\n2014-04-21 16:07:00,28.75\n2014-04-21 16:12:00,28.335\n2014-04-21 16:17:00,27.5\n2014-04-21 16:22:00,27.5025\n2014-04-21 16:27:00,28.75\n2014-04-21 16:32:00,27.94\n2014-04-21 16:37:00,28.75\n2014-04-21 16:42:00,29.1675\n2014-04-21 16:47:00,27.5\n2014-04-21 16:52:00,27.5\n2014-04-21 16:57:00,29.5825\n2014-04-21 17:02:00,27.4975\n2014-04-21 17:07:00,28.7525\n2014-04-21 17:12:00,27.4975\n2014-04-21 17:17:00,27.4975\n2014-04-21 17:22:00,27.4975\n2014-04-21 17:27:00,28.3325\n2014-04-21 17:32:00,28.75\n2014-04-21 17:37:00,28.01\n2014-04-21 17:42:00,27.5\n2014-04-21 17:47:00,26.6575\n2014-04-21 17:52:00,28.0475\n2014-04-21 17:57:00,29.07\n2014-04-21 18:02:00,27.0675\n2014-04-21 18:07:00,28.71\n2014-04-21 18:12:00,28.6\n2014-04-21 18:17:00,29.1675\n2014-04-21 18:22:00,28.75\n2014-04-21 18:27:00,28.49\n2014-04-21 18:32:00,27.9175\n2014-04-21 18:37:00,27.455\n2014-04-21 18:42:00,27.5025\n2014-04-21 18:47:00,28.7475\n2014-04-21 18:52:00,26.6425\n2014-04-21 18:57:00,28.365\n2014-04-21 19:02:00,27.9175\n2014-04-21 19:07:00,28.335\n2014-04-21 19:12:00,29.1675\n2014-04-21 19:17:00,27.4975\n2014-04-21 19:22:00,27.055\n2014-04-21 19:27:00,29.165\n2014-04-21 19:32:00,27.08\n2014-04-21 19:37:00,27.4975\n2014-04-21 19:42:00,27.5\n2014-04-21 19:47:00,28.3325\n2014-04-21 19:52:00,27.0825\n2014-04-21 19:57:00,28.75\n2014-04-21 20:02:00,27.5\n2014-04-21 20:07:00,27.0825\n2014-04-21 20:12:00,27.5\n2014-04-21 20:17:00,29.1625\n2014-04-21 20:22:00,27.065\n2014-04-21 20:27:00,30.12\n2014-04-21 20:32:00,28.3575\n2014-04-21 20:37:00,28.345\n2014-04-21 20:42:00,28.3325\n2014-04-21 20:47:00,28.75\n2014-04-21 20:52:00,26.25\n2014-04-21 20:57:00,29.1675\n2014-04-21 21:02:00,27.5\n2014-04-21 21:07:00,27.9275\n2014-04-21 21:12:00,28.3325\n2014-04-21 21:17:00,28.335\n2014-04-21 21:22:00,27.9175\n2014-04-21 21:27:00,28.33\n2014-04-21 21:32:00,26.67\n2014-04-21 21:37:00,27.9175\n2014-04-21 21:42:00,27.4175\n2014-04-21 21:47:00,28.3325\n2014-04-21 21:52:00,26.665\n2014-04-21 21:57:00,29.74\n2014-04-21 22:02:00,27.0825\n2014-04-21 22:07:00,27.8875\n2014-04-21 22:12:00,27.2175\n2014-04-21 22:17:00,28.7475\n2014-04-21 22:22:00,27.9175\n2014-04-21 22:27:00,29.9975\n2014-04-21 22:32:00,28.79\n2014-04-21 22:37:00,28.3325\n2014-04-21 22:42:00,28.75\n2014-04-21 22:47:00,27.5025\n2014-04-21 22:52:00,27.915\n2014-04-21 22:57:00,28.7475\n2014-04-21 23:02:00,26.6675\n2014-04-21 23:07:00,29.17\n2014-04-21 23:12:00,31.7125\n2014-04-21 23:17:00,28.335\n2014-04-21 23:22:00,28.75\n2014-04-21 23:27:00,27.5\n2014-04-21 23:32:00,27.085\n2014-04-21 23:37:00,28.75\n2014-04-21 23:42:00,27.5\n2014-04-21 23:47:00,28.3325\n2014-04-21 23:52:00,28.75\n2014-04-21 23:57:00,28.4875\n2014-04-22 00:02:00,27.9075\n2014-04-22 00:07:00,28.75\n2014-04-22 00:12:00,27.5\n2014-04-22 00:17:00,28.3325\n2014-04-22 00:22:00,27.4825\n2014-04-22 00:27:00,28.7475\n2014-04-22 00:32:00,28.3325\n2014-04-22 00:37:00,27.5\n2014-04-22 00:42:00,27.0825\n2014-04-22 00:47:00,26.6675\n2014-04-22 00:52:00,27.8125\n2014-04-22 00:57:00,29.1275\n2014-04-22 01:02:00,29.165\n2014-04-22 01:07:00,28.3325\n2014-04-22 01:12:00,29.635\n2014-04-22 01:17:00,29.165\n2014-04-22 01:22:00,27.0825\n2014-04-22 01:27:00,28.705\n2014-04-22 01:32:00,27.9175\n2014-04-22 01:37:00,27.5\n2014-04-22 01:42:00,27.9\n2014-04-22 01:47:00,28.75\n2014-04-22 01:52:00,26.6675\n2014-04-22 01:57:00,28.75\n2014-04-22 02:02:00,25.4175\n2014-04-22 02:07:00,27.5\n2014-04-22 02:12:00,28.3325\n2014-04-22 02:17:00,27.9175\n2014-04-22 02:22:00,28.4725\n2014-04-22 02:27:00,28.3325\n2014-04-22 02:32:00,27.48\n2014-04-22 02:37:00,29.17\n2014-04-22 02:42:00,29.1675\n2014-04-22 02:47:00,27.5\n2014-04-22 02:52:00,26.6675\n2014-04-22 02:57:00,27.9175\n2014-04-22 03:02:00,27.0825\n2014-04-22 03:07:00,28.75\n2014-04-22 03:12:00,29.1675\n2014-04-22 03:17:00,29.165\n2014-04-22 03:22:00,27.9175\n2014-04-22 03:27:00,27.915\n2014-04-22 03:32:00,27.4975\n2014-04-22 03:37:00,28.7525\n2014-04-22 03:42:00,27.4975\n2014-04-22 03:47:00,30.4175\n2014-04-22 03:52:00,26.675\n2014-04-22 03:57:00,29.9975\n2014-04-22 04:02:00,27.5\n2014-04-22 04:07:00,27.9175\n2014-04-22 04:12:00,29.3475\n2014-04-22 04:17:00,28.29\n2014-04-22 04:22:00,29.1675\n2014-04-22 04:27:00,28.335\n2014-04-22 04:32:00,28.0575\n2014-04-22 04:37:00,28.235\n2014-04-22 04:42:00,26.6675\n2014-04-22 04:47:00,28.745\n2014-04-22 04:52:00,28.4675\n2014-04-22 04:57:00,28.3325\n2014-04-22 05:02:00,26.635\n2014-04-22 05:07:00,28.905\n2014-04-22 05:12:00,27.5075\n2014-04-22 05:17:00,27.085\n2014-04-22 05:22:00,28.3325\n2014-04-22 05:27:00,27.915\n2014-04-22 05:32:00,27.0825\n2014-04-22 05:37:00,28.7475\n2014-04-22 05:42:00,27.0825\n2014-04-22 05:47:00,27.5\n2014-04-22 05:52:00,28.335\n2014-04-22 05:57:00,27.915\n2014-04-22 06:02:00,27.5975\n2014-04-22 06:07:00,29.165\n2014-04-22 06:12:00,26.9875\n2014-04-22 06:17:00,27.5\n2014-04-22 06:22:00,28.345\n2014-04-22 06:27:00,28.7475\n2014-04-22 06:32:00,27.895\n2014-04-22 06:37:00,28.3375\n2014-04-22 06:42:00,27.5\n2014-04-22 06:47:00,27.6475\n2014-04-22 06:52:00,27.5\n2014-04-22 06:57:00,28.3325\n2014-04-22 07:02:00,27.085\n2014-04-22 07:07:00,29.1675\n2014-04-22 07:12:00,27.0925\n2014-04-22 07:17:00,27.5\n2014-04-22 07:22:00,27.1\n2014-04-22 07:27:00,28.75\n2014-04-22 07:32:00,27.0575\n2014-04-22 07:37:00,27.1425\n2014-04-22 07:42:00,28.3325\n2014-04-22 07:47:00,27.5\n2014-04-22 07:52:00,26.6675\n2014-04-22 07:57:00,30.8325\n2014-04-22 08:02:00,27.0725\n2014-04-22 08:07:00,29.1675\n2014-04-22 08:12:00,28.3175\n2014-04-22 08:17:00,27.0825\n2014-04-22 08:22:00,27.9175\n2014-04-22 08:27:00,28.33\n2014-04-22 08:32:00,25.835\n2014-04-22 08:37:00,28.7525\n2014-04-22 08:42:00,26.25\n2014-04-22 08:47:00,27.44\n2014-04-22 08:52:00,27.5\n2014-04-22 08:57:00,28.75\n2014-04-22 09:02:00,27.085\n2014-04-22 09:07:00,28.335\n2014-04-22 09:12:00,28.2325\n2014-04-22 09:17:00,27.6475\n2014-04-22 09:22:00,26.2475\n2014-04-22 09:27:00,28.75\n2014-04-22 09:32:00,27.085\n2014-04-22 09:37:00,27.815\n2014-04-22 09:42:00,28.335\n2014-04-22 09:47:00,27.49\n2014-04-22 09:52:00,28.3325\n2014-04-22 09:57:00,27.9175\n2014-04-22 10:02:00,28.3325\n2014-04-22 10:07:00,27.9175\n2014-04-22 10:12:00,28.3325\n2014-04-22 10:17:00,27.5\n2014-04-22 10:22:00,26.2525\n2014-04-22 10:27:00,29.5825\n2014-04-22 10:32:00,27.0825\n2014-04-22 10:37:00,29.2725\n2014-04-22 10:42:00,28.75\n2014-04-22 10:47:00,27.5\n2014-04-22 10:52:00,27.4575\n2014-04-22 10:57:00,28.4925\n2014-04-22 11:02:00,27.9175\n2014-04-22 11:07:00,28.7475\n2014-04-22 11:12:00,30.0\n2014-04-22 11:17:00,28.335\n2014-04-22 11:22:00,28.75\n2014-04-22 11:27:00,21.245\n2014-04-22 11:32:00,18.3325\n2014-04-22 11:37:00,17.5\n2014-04-22 11:42:00,17.5\n2014-04-22 11:47:00,17.9175\n2014-04-22 11:52:00,16.25\n2014-04-22 11:57:00,18.4375\n2014-04-22 12:02:00,16.6675\n2014-04-22 12:07:00,16.66\n2014-04-22 12:12:00,16.25\n2014-04-22 12:17:00,17.5\n2014-04-22 12:22:00,17.5\n2014-04-22 12:27:00,17.5\n2014-04-22 12:32:00,15.835\n2014-04-22 12:37:00,17.0825\n2014-04-22 12:42:00,16.7725\n2014-04-22 12:47:00,16.665\n2014-04-22 12:52:00,16.6525\n2014-04-22 12:57:00,17.5\n2014-04-22 13:02:00,16.25\n2014-04-22 13:07:00,17.5\n2014-04-22 13:12:00,16.6675\n2014-04-22 13:17:00,18.335\n2014-04-22 13:22:00,16.665\n2014-04-22 13:27:00,17.5\n2014-04-22 13:32:00,17.0825\n2014-04-22 13:37:00,17.0825\n2014-04-22 13:42:00,16.6675\n2014-04-22 13:47:00,17.0825\n2014-04-22 13:52:00,16.6675\n2014-04-22 13:57:00,18.3325\n2014-04-22 14:02:00,16.2525\n2014-04-22 14:07:00,17.9525\n2014-04-22 14:12:00,17.4975\n2014-04-22 14:17:00,17.0825\n2014-04-22 14:22:00,17.0825\n2014-04-22 14:27:00,17.915\n2014-04-22 14:32:00,16.2525\n2014-04-22 14:37:00,17.55\n2014-04-22 14:42:00,17.0825\n2014-04-22 14:47:00,17.0825\n2014-04-22 14:52:00,15.84\n2014-04-22 14:57:00,17.9025\n2014-04-22 15:02:00,17.0825\n2014-04-22 15:07:00,17.975\n2014-04-22 15:12:00,17.0825\n2014-04-22 15:17:00,17.0825\n2014-04-22 15:22:00,17.0825\n2014-04-22 15:27:00,17.085\n2014-04-22 15:32:00,16.25\n2014-04-22 15:37:00,17.9175\n2014-04-22 15:42:00,16.5775\n2014-04-22 15:47:00,17.035\n2014-04-22 15:52:00,17.09\n2014-04-22 15:57:00,17.085\n2014-04-22 16:02:00,16.6675\n2014-04-22 16:07:00,17.92\n2014-04-22 16:12:00,17.0275\n2014-04-22 16:17:00,17.8075\n2014-04-22 16:22:00,16.6675\n2014-04-22 16:27:00,17.5025\n2014-04-22 16:32:00,16.665\n2014-04-22 16:37:00,17.0825\n2014-04-22 16:42:00,16.6675\n2014-04-22 16:47:00,17.9175\n2014-04-22 16:52:00,15.835\n2014-04-22 16:57:00,17.9025\n2014-04-22 17:02:00,17.065\n2014-04-22 17:07:00,17.085\n2014-04-22 17:12:00,16.6675\n2014-04-22 17:17:00,17.0825\n2014-04-22 17:22:00,16.6875\n2014-04-22 17:27:00,17.9725\n2014-04-22 17:32:00,17.0825\n2014-04-22 17:37:00,18.39\n2014-04-22 17:42:00,16.5775\n2014-04-22 17:47:00,17.0825\n2014-04-22 17:52:00,16.6875\n2014-04-22 17:57:00,17.3925\n2014-04-22 18:02:00,17.085\n2014-04-22 18:07:00,16.6675\n2014-04-22 18:12:00,16.6675\n2014-04-22 18:17:00,17.5\n2014-04-22 18:22:00,17.5\n2014-04-22 18:27:00,18.33\n2014-04-22 18:32:00,17.085\n2014-04-22 18:37:00,18.3225\n2014-04-22 18:42:00,17.0825\n2014-04-22 18:47:00,17.135\n2014-04-22 18:52:00,16.68\n2014-04-22 18:57:00,17.5\n2014-04-22 19:02:00,16.6675\n2014-04-22 19:07:00,17.5\n2014-04-22 19:12:00,17.0825\n2014-04-22 19:17:00,17.9175\n2014-04-22 19:22:00,16.665\n2014-04-22 19:27:00,17.5\n2014-04-22 19:32:00,17.0825\n2014-04-22 19:37:00,17.9725\n2014-04-22 19:42:00,17.0825\n2014-04-22 19:47:00,17.9175\n2014-04-22 19:52:00,16.2525\n2014-04-22 19:57:00,17.915\n2014-04-22 20:02:00,16.665\n2014-04-22 20:07:00,17.1825\n2014-04-22 20:12:00,16.25\n2014-04-22 20:17:00,18.335\n2014-04-22 20:22:00,16.9925\n2014-04-22 20:27:00,18.335\n2014-04-22 20:32:00,15.835\n2014-04-22 20:37:00,17.5\n2014-04-22 20:42:00,16.665\n2014-04-22 20:47:00,17.5\n2014-04-22 20:52:00,16.665\n2014-04-22 20:57:00,17.5\n2014-04-22 21:02:00,17.0825\n2014-04-22 21:07:00,17.915\n2014-04-22 21:12:00,17.0825\n2014-04-22 21:17:00,17.9175\n2014-04-22 21:22:00,16.26\n2014-04-22 21:27:00,17.0825\n2014-04-22 21:32:00,17.0825\n2014-04-22 21:37:00,17.0825\n2014-04-22 21:42:00,17.4975\n2014-04-22 21:47:00,17.0825\n2014-04-22 21:52:00,16.25\n2014-04-22 21:57:00,18.3325\n2014-04-22 22:02:00,16.2525\n2014-04-22 22:07:00,17.9525\n2014-04-22 22:12:00,17.0825\n2014-04-22 22:17:00,17.98\n2014-04-22 22:22:00,17.085\n2014-04-22 22:27:00,17.915\n2014-04-22 22:32:00,16.2525\n2014-04-22 22:37:00,17.9175\n2014-04-22 22:42:00,16.665\n2014-04-22 22:47:00,17.0825\n2014-04-22 22:52:00,16.25\n2014-04-22 22:57:00,18.3325\n2014-04-22 23:02:00,17.0825\n2014-04-22 23:07:00,17.9175\n2014-04-22 23:12:00,17.5\n2014-04-22 23:17:00,17.9175\n2014-04-22 23:22:00,15.835\n2014-04-22 23:27:00,17.085\n2014-04-22 23:32:00,16.6675\n2014-04-22 23:37:00,17.0825\n2014-04-22 23:42:00,16.665\n2014-04-22 23:47:00,17.5\n2014-04-22 23:52:00,16.2675\n2014-04-22 23:57:00,17.91\n2014-04-23 00:02:00,19.5825\n2014-04-23 00:07:00,17.14\n2014-04-23 00:12:00,17.915\n2014-04-23 00:17:00,17.915\n2014-04-23 00:22:00,15.835\n2014-04-23 00:27:00,17.085\n2014-04-23 00:32:00,17.0825\n2014-04-23 00:37:00,17.0825\n2014-04-23 00:42:00,16.25\n2014-04-23 00:47:00,17.9125\n2014-04-23 00:52:00,16.2525\n2014-04-23 00:57:00,17.9175\n2014-04-23 01:02:00,17.5\n2014-04-23 01:07:00,17.0825\n2014-04-23 01:12:00,18.7475\n2014-04-23 01:17:00,17.5\n2014-04-23 01:22:00,16.2525\n2014-04-23 01:27:00,17.9175\n2014-04-23 01:32:00,16.23\n2014-04-23 01:37:00,17.0825\n2014-04-23 01:42:00,17.0825\n2014-04-23 01:47:00,16.665\n2014-04-23 01:52:00,17.085\n2014-04-23 01:57:00,17.085\n2014-04-23 02:02:00,16.6825\n2014-04-23 02:07:00,18.3325\n2014-04-23 02:12:00,16.665\n2014-04-23 02:17:00,17.915\n2014-04-23 02:22:00,17.0825\n2014-04-23 02:27:00,17.96\n2014-04-23 02:32:00,16.6675\n2014-04-23 02:37:00,16.665\n2014-04-23 02:42:00,16.605\n2014-04-23 02:47:00,17.0275\n2014-04-23 02:52:00,17.08\n2014-04-23 02:57:00,17.0825\n2014-04-23 03:02:00,15.835\n2014-04-23 03:07:00,17.5\n2014-04-23 03:12:00,17.0825\n2014-04-23 03:17:00,16.665\n2014-04-23 03:22:00,17.0825\n2014-04-23 03:27:00,17.5\n2014-04-23 03:32:00,17.0825\n2014-04-23 03:37:00,17.5\n2014-04-23 03:42:00,17.0275\n2014-04-23 03:47:00,17.9175\n2014-04-23 03:52:00,16.2525\n2014-04-23 03:57:00,17.915\n2014-04-23 04:02:00,16.6675\n2014-04-23 04:07:00,17.0825\n2014-04-23 04:12:00,17.1825\n2014-04-23 04:17:00,16.665\n2014-04-23 04:22:00,16.25\n2014-04-23 04:27:00,17.5\n2014-04-23 04:32:00,15.8325\n2014-04-23 04:37:00,17.0825\n2014-04-23 04:42:00,16.25\n2014-04-23 04:47:00,17.9175\n2014-04-23 04:52:00,16.2525\n2014-04-23 04:57:00,18.01\n2014-04-23 05:02:00,17.105\n2014-04-23 05:07:00,16.25\n2014-04-23 05:12:00,17.085\n2014-04-23 05:17:00,16.665\n2014-04-23 05:22:00,16.69\n2014-04-23 05:27:00,17.0825\n2014-04-23 05:32:00,16.755\n2014-04-23 05:37:00,17.0825\n2014-04-23 05:42:00,16.6675\n2014-04-23 05:47:00,17.5\n2014-04-23 05:52:00,16.6975\n2014-04-23 05:57:00,17.9175\n2014-04-23 06:02:00,16.6675\n2014-04-23 06:07:00,16.665\n2014-04-23 06:12:00,16.6675\n2014-04-23 06:17:00,17.5\n2014-04-23 06:22:00,16.6675\n2014-04-23 06:27:00,18.34\n2014-04-23 06:32:00,16.25\n2014-04-23 06:37:00,17.0825\n2014-04-23 06:42:00,17.4975\n2014-04-23 06:47:00,16.6675\n2014-04-23 06:52:00,16.6675\n2014-04-23 06:57:00,17.915\n2014-04-23 07:02:00,16.6675\n2014-04-23 07:07:00,17.5\n2014-04-23 07:12:00,16.6675\n2014-04-23 07:17:00,17.5\n2014-04-23 07:22:00,16.2525\n2014-04-23 07:27:00,17.945\n2014-04-23 07:32:00,16.1825\n2014-04-23 07:37:00,16.6675\n2014-04-23 07:42:00,17.065\n2014-04-23 07:47:00,17.5\n2014-04-23 07:52:00,16.2525\n2014-04-23 07:57:00,20.835\n2014-04-23 08:02:00,16.6675\n2014-04-23 08:07:00,17.085\n2014-04-23 08:12:00,16.6675\n2014-04-23 08:17:00,17.5025\n2014-04-23 08:22:00,16.6825\n2014-04-23 08:27:00,17.98\n2014-04-23 08:32:00,16.665\n2014-04-23 08:37:00,16.6675\n2014-04-23 08:42:00,17.0825\n2014-04-23 08:47:00,17.0825\n2014-04-23 08:52:00,16.6975\n2014-04-23 08:57:00,17.9175\n2014-04-23 09:02:00,16.6675\n2014-04-23 09:07:00,17.0825\n2014-04-23 09:12:00,16.665\n2014-04-23 09:17:00,17.1875\n2014-04-23 09:22:00,16.2525\n2014-04-23 09:27:00,17.0825\n2014-04-23 09:32:00,16.25\n2014-04-23 09:37:00,17.5\n2014-04-23 09:42:00,16.265\n2014-04-23 09:47:00,17.5\n2014-04-23 09:52:00,16.2525\n2014-04-23 09:57:00,17.9175\n2014-04-23 10:02:00,16.2525\n2014-04-23 10:07:00,17.9175\n2014-04-23 10:12:00,16.34\n2014-04-23 10:17:00,17.5\n2014-04-23 10:22:00,16.6675\n2014-04-23 10:27:00,17.5\n2014-04-23 10:32:00,16.64\n2014-04-23 10:37:00,17.0775\n2014-04-23 10:42:00,16.6375\n2014-04-23 10:47:00,17.9175\n2014-04-23 10:52:00,16.25\n2014-04-23 10:57:00,17.5025\n2014-04-23 11:02:00,16.6675\n2014-04-23 11:07:00,18.3325\n2014-04-23 11:12:00,17.0825\n2014-04-23 11:17:00,17.4975\n2014-04-23 11:22:00,17.5\n2014-04-23 11:27:00,17.925\n2014-04-23 11:32:00,16.705\n2014-04-23 11:37:00,17.5075\n2014-04-23 11:42:00,17.0825\n2014-04-23 11:47:00,17.8825\n2014-04-23 11:52:00,16.25\n2014-04-23 11:57:00,17.9175\n2014-04-23 12:02:00,17.0825\n2014-04-23 12:07:00,17.0825\n2014-04-23 12:12:00,17.0825\n2014-04-23 12:17:00,17.015\n2014-04-23 12:22:00,16.6675\n2014-04-23 12:27:00,17.445\n2014-04-23 12:32:00,16.25\n2014-04-23 12:37:00,17.9175\n2014-04-23 12:42:00,18.3325\n2014-04-23 12:47:00,17.5\n2014-04-23 12:52:00,16.2525\n2014-04-23 12:57:00,18.335\n2014-04-23 13:02:00,16.6675\n2014-04-23 13:07:00,17.9175\n2014-04-23 13:12:00,16.26\n2014-04-23 13:17:00,17.4975\n2014-04-23 13:22:00,16.6675\n2014-04-23 13:27:00,17.085\n2014-04-23 13:32:00,16.6675\n2014-04-23 13:37:00,17.0825\n2014-04-23 13:42:00,16.655\n2014-04-23 13:47:00,17.5875\n2014-04-23 13:52:00,16.26\n2014-04-23 13:57:00,17.9175\n2014-04-23 14:02:00,16.605\n2014-04-23 14:07:00,17.5025\n2014-04-23 14:12:00,17.915\n2014-04-23 14:17:00,17.5\n2014-04-23 14:22:00,17.0775\n2014-04-23 14:27:00,17.915\n2014-04-23 14:32:00,16.2525\n2014-04-23 14:37:00,17.915\n2014-04-23 14:42:00,16.6825\n2014-04-23 14:47:00,17.6125\n2014-04-23 14:52:00,16.2525\n2014-04-23 14:57:00,17.9175\n2014-04-23 15:02:00,16.28\n2014-04-23 15:07:00,18.335\n2014-04-23 15:12:00,16.25\n2014-04-23 15:17:00,17.0825\n2014-04-23 15:22:00,16.23\n2014-04-23 15:27:00,17.0375\n2014-04-23 15:32:00,16.67\n2014-04-23 15:37:00,17.4625\n2014-04-23 15:42:00,16.25\n2014-04-23 15:47:00,17.6125\n2014-04-23 15:52:00,16.665\n2014-04-23 15:57:00,17.085\n2014-04-23 16:02:00,16.9925\n2014-04-23 16:07:00,18.3325\n2014-04-23 16:12:00,17.075\n2014-04-23 16:17:00,17.9175\n2014-04-23 16:22:00,16.68\n2014-04-23 16:27:00,17.9175\n2014-04-23 16:32:00,16.6475\n2014-04-23 16:37:00,17.0825\n2014-04-23 16:42:00,17.0825\n2014-04-23 16:47:00,17.0825\n2014-04-23 16:52:00,15.835\n2014-04-23 16:57:00,17.9925\n2014-04-23 17:02:00,16.6675\n2014-04-23 17:07:00,17.0825\n2014-04-23 17:12:00,16.25\n2014-04-23 17:17:00,17.5\n2014-04-23 17:22:00,15.8325\n2014-04-23 17:27:00,17.9175\n2014-04-23 17:32:00,16.6675\n2014-04-23 17:37:00,17.0825\n2014-04-23 17:42:00,16.25\n2014-04-23 17:47:00,17.5\n2014-04-23 17:52:00,16.2525\n2014-04-23 17:57:00,17.5\n2014-04-23 18:02:00,16.665\n2014-04-23 18:07:00,17.0825\n2014-04-23 18:12:00,17.0825\n2014-04-23 18:17:00,17.8075\n2014-04-23 18:22:00,16.6675\n2014-04-23 18:27:00,18.3325\n2014-04-23 18:32:00,16.765\n2014-04-23 18:37:00,16.665\n2014-04-23 18:42:00,17.0825\n2014-04-23 18:47:00,17.0825\n2014-04-23 18:52:00,17.085\n2014-04-23 18:57:00,18.3325\n2014-04-23 19:02:00,16.25\n2014-04-23 19:07:00,17.5\n2014-04-23 19:12:00,17.5\n2014-04-23 19:17:00,17.5\n2014-04-23 19:22:00,17.4975\n2014-04-23 19:27:00,17.5\n2014-04-23 19:32:00,16.6675\n2014-04-23 19:37:00,17.6675\n2014-04-23 19:42:00,16.6675\n2014-04-23 19:47:00,17.5\n2014-04-23 19:52:00,17.0825\n2014-04-23 19:57:00,17.5\n2014-04-23 20:02:00,17.07\n2014-04-23 20:07:00,17.0375\n2014-04-23 20:12:00,16.6675\n2014-04-23 20:17:00,17.615\n2014-04-23 20:22:00,16.665\n2014-04-23 20:27:00,17.9175\n2014-04-23 20:32:00,17.4975\n2014-04-23 20:37:00,17.085\n2014-04-23 20:42:00,17.0825\n2014-04-23 20:47:00,17.445\n2014-04-23 20:52:00,16.2525\n2014-04-23 20:57:00,17.0375\n2014-04-23 21:02:00,15.9225\n2014-04-23 21:07:00,18.22\n2014-04-23 21:12:00,16.575\n2014-04-23 21:17:00,17.0825\n2014-04-23 21:22:00,16.6675\n2014-04-23 21:27:00,17.87\n2014-04-23 21:32:00,16.25\n2014-04-23 21:37:00,17.4925\n2014-04-23 21:42:00,17.0825\n2014-04-23 21:47:00,16.6675\n2014-04-23 21:52:00,16.25\n2014-04-23 21:57:00,17.085\n2014-04-23 22:02:00,17.1825\n2014-04-23 22:07:00,17.135\n2014-04-23 22:12:00,17.5\n2014-04-23 22:17:00,18.34\n2014-04-23 22:22:00,16.2525\n2014-04-23 22:27:00,17.9175\n2014-04-23 22:32:00,16.2525\n2014-04-23 22:37:00,16.665\n2014-04-23 22:42:00,17.08\n2014-04-23 22:47:00,17.0825\n2014-04-23 22:52:00,15.8325\n2014-04-23 22:57:00,17.9175\n2014-04-23 23:02:00,16.6475\n2014-04-23 23:07:00,17.9175\n2014-04-23 23:12:00,17.08\n2014-04-23 23:17:00,17.9175\n2014-04-23 23:22:00,16.665\n2014-04-23 23:27:00,17.605\n2014-04-23 23:32:00,15.835\n2014-04-23 23:37:00,17.09\n2014-04-23 23:42:00,17.08\n2014-04-23 23:47:00,17.0825\n2014-04-23 23:52:00,16.2525\n2014-04-23 23:57:00,18.005\n"
  },
  {
    "path": "workspace/anomaly_detector/datasets/selected/outliers/ec2_cpu_utilization_fe7f93.csv",
    "content": "timestamp,value\n2014-02-14 14:27:00,2.296\n2014-02-14 14:32:00,2.144\n2014-02-14 14:37:00,2.274\n2014-02-14 14:42:00,2.066\n2014-02-14 14:47:00,2.35\n2014-02-14 14:52:00,2.136\n2014-02-14 14:57:00,2.366\n2014-02-14 15:02:00,2.252\n2014-02-14 15:07:00,2.4\n2014-02-14 15:12:00,2.18\n2014-02-14 15:17:00,2.352\n2014-02-14 15:22:00,3.4339999999999997\n2014-02-14 15:27:00,2.43\n2014-02-14 15:32:00,2.0340000000000003\n2014-02-14 15:37:00,2.296\n2014-02-14 15:42:00,2.052\n2014-02-14 15:47:00,2.314\n2014-02-14 15:52:00,2.07\n2014-02-14 15:57:00,2.4\n2014-02-14 16:02:00,2.07\n2014-02-14 16:07:00,3.588\n2014-02-14 16:12:00,2.1919999999999997\n2014-02-14 16:17:00,2.3\n2014-02-14 16:22:00,2.134\n2014-02-14 16:27:00,2.2840000000000003\n2014-02-14 16:32:00,2.12\n2014-02-14 16:37:00,2.35\n2014-02-14 16:42:00,2.166\n2014-02-14 16:47:00,2.314\n2014-02-14 16:52:00,2.186\n2014-02-14 16:57:00,2.33\n2014-02-14 17:02:00,2.108\n2014-02-14 17:07:00,2.3280000000000003\n2014-02-14 17:12:00,3.4339999999999997\n2014-02-14 17:17:00,2.424\n2014-02-14 17:22:00,2.158\n2014-02-14 17:27:00,2.342\n2014-02-14 17:32:00,2.056\n2014-02-14 17:37:00,2.376\n2014-02-14 17:42:00,2.106\n2014-02-14 17:47:00,2.408\n2014-02-14 17:52:00,2.156\n2014-02-14 17:57:00,2.464\n2014-02-14 18:02:00,2.224\n2014-02-14 18:07:00,2.428\n2014-02-14 18:12:00,2.234\n2014-02-14 18:17:00,2.408\n2014-02-14 18:22:00,3.372\n2014-02-14 18:27:00,2.318\n2014-02-14 18:32:00,2.166\n2014-02-14 18:37:00,2.386\n2014-02-14 18:42:00,2.138\n2014-02-14 18:47:00,2.336\n2014-02-14 18:52:00,2.23\n2014-02-14 18:57:00,2.452\n2014-02-14 19:02:00,2.15\n2014-02-14 19:07:00,2.386\n2014-02-14 19:12:00,2.234\n2014-02-14 19:17:00,2.7319999999999998\n2014-02-14 19:22:00,2.9160000000000004\n2014-02-14 19:27:00,2.246\n2014-02-14 19:32:00,2.084\n2014-02-14 19:37:00,2.248\n2014-02-14 19:42:00,2.096\n2014-02-14 19:47:00,2.266\n2014-02-14 19:52:00,2.504\n2014-02-14 19:57:00,52.26600000000001\n2014-02-14 20:02:00,54.806000000000004\n2014-02-14 20:07:00,55.736000000000004\n2014-02-14 20:12:00,11.058\n2014-02-14 20:17:00,20.215999999999998\n2014-02-14 20:22:00,71.306\n2014-02-14 20:27:00,55.49800000000001\n2014-02-14 20:32:00,25.366\n2014-02-14 20:37:00,6.994\n2014-02-14 20:42:00,5.034\n2014-02-14 20:47:00,5.45\n2014-02-14 20:52:00,5.4\n2014-02-14 20:57:00,5.65\n2014-02-14 21:02:00,7.992000000000001\n2014-02-14 21:07:00,5.42\n2014-02-14 21:12:00,7.8020000000000005\n2014-02-14 21:17:00,5.666\n2014-02-14 21:22:00,5.164\n2014-02-14 21:27:00,7.2\n2014-02-14 21:32:00,5.082\n2014-02-14 21:37:00,5.546\n2014-02-14 21:42:00,5.282\n2014-02-14 21:47:00,5.566\n2014-02-14 21:52:00,4.002\n2014-02-14 21:57:00,3.512\n2014-02-14 22:02:00,1.98\n2014-02-14 22:07:00,2.278\n2014-02-14 22:12:00,2.016\n2014-02-14 22:17:00,3.5239999999999996\n2014-02-14 22:22:00,2.0340000000000003\n2014-02-14 22:27:00,2.25\n2014-02-14 22:32:00,2.068\n2014-02-14 22:37:00,2.3040000000000003\n2014-02-14 22:42:00,2.092\n2014-02-14 22:47:00,2.332\n2014-02-14 22:52:00,2.124\n2014-02-14 22:57:00,53.692\n2014-02-14 23:02:00,51.466\n2014-02-14 23:07:00,51.85\n2014-02-14 23:12:00,5.372000000000001\n2014-02-14 23:17:00,3.002\n2014-02-14 23:22:00,3.984\n2014-02-14 23:27:00,3.2460000000000004\n2014-02-14 23:32:00,4.7\n2014-02-14 23:37:00,2.864\n2014-02-14 23:42:00,2.426\n2014-02-14 23:47:00,3.112\n2014-02-14 23:52:00,2.84\n2014-02-14 23:57:00,3.0839999999999996\n2014-02-15 00:02:00,3.556\n2014-02-15 00:07:00,2.0340000000000003\n2014-02-15 00:12:00,2.064\n2014-02-15 00:17:00,3.534\n2014-02-15 00:22:00,2.27\n2014-02-15 00:27:00,2.292\n2014-02-15 00:32:00,2.09\n2014-02-15 00:37:00,2.234\n2014-02-15 00:42:00,4.73\n2014-02-15 00:47:00,2.634\n2014-02-15 00:52:00,2.766\n2014-02-15 00:57:00,2.7\n2014-02-15 01:02:00,2.728\n2014-02-15 01:07:00,2.616\n2014-02-15 01:12:00,2.474\n2014-02-15 01:17:00,3.79\n2014-02-15 01:22:00,2.458\n2014-02-15 01:27:00,2.4219999999999997\n2014-02-15 01:32:00,2.434\n2014-02-15 01:37:00,2.452\n2014-02-15 01:42:00,2.2880000000000003\n2014-02-15 01:47:00,2.5780000000000003\n2014-02-15 01:52:00,2.396\n2014-02-15 01:57:00,2.7680000000000002\n2014-02-15 02:02:00,2.346\n2014-02-15 02:07:00,2.464\n2014-02-15 02:12:00,3.5580000000000003\n2014-02-15 02:17:00,2.36\n2014-02-15 02:22:00,2.2159999999999997\n2014-02-15 02:27:00,2.292\n2014-02-15 02:32:00,2.1519999999999997\n2014-02-15 02:37:00,2.334\n2014-02-15 02:42:00,2.166\n2014-02-15 02:47:00,2.3680000000000003\n2014-02-15 02:52:00,2.052\n2014-02-15 02:57:00,2.342\n2014-02-15 03:02:00,2.386\n2014-02-15 03:07:00,2.318\n2014-02-15 03:12:00,2.08\n2014-02-15 03:17:00,2.766\n2014-02-15 03:22:00,2.898\n2014-02-15 03:27:00,2.2\n2014-02-15 03:32:00,2.086\n2014-02-15 03:37:00,2.25\n2014-02-15 03:42:00,2.066\n2014-02-15 03:47:00,2.168\n2014-02-15 03:52:00,2.08\n2014-02-15 03:57:00,2.266\n2014-02-15 04:02:00,2.084\n2014-02-15 04:07:00,2.218\n2014-02-15 04:12:00,2.148\n2014-02-15 04:17:00,3.5060000000000002\n2014-02-15 04:22:00,2.182\n2014-02-15 04:27:00,2.2359999999999998\n2014-02-15 04:32:00,2.1319999999999997\n2014-02-15 04:37:00,2.3\n2014-02-15 04:42:00,2.086\n2014-02-15 04:47:00,2.202\n2014-02-15 04:52:00,2.064\n2014-02-15 04:57:00,2.296\n2014-02-15 05:02:00,2.08\n2014-02-15 05:07:00,2.2640000000000002\n2014-02-15 05:12:00,3.352\n2014-02-15 05:17:00,2.334\n2014-02-15 05:22:00,1.9980000000000002\n2014-02-15 05:27:00,2.26\n2014-02-15 05:32:00,1.9880000000000002\n2014-02-15 05:37:00,2.184\n2014-02-15 05:42:00,1.996\n2014-02-15 05:47:00,2.2159999999999997\n2014-02-15 05:52:00,2.0\n2014-02-15 05:57:00,2.198\n2014-02-15 06:02:00,1.966\n2014-02-15 06:07:00,2.164\n2014-02-15 06:12:00,3.298\n2014-02-15 06:17:00,2.18\n2014-02-15 06:22:00,1.984\n2014-02-15 06:27:00,2.258\n2014-02-15 06:32:00,1.952\n2014-02-15 06:37:00,2.184\n2014-02-15 06:42:00,1.984\n2014-02-15 06:47:00,2.22\n2014-02-15 06:52:00,1.9580000000000002\n2014-02-15 06:57:00,2.234\n2014-02-15 07:02:00,2.1319999999999997\n2014-02-15 07:07:00,2.2640000000000002\n2014-02-15 07:12:00,2.0\n2014-02-15 07:17:00,2.218\n2014-02-15 07:22:00,3.378\n2014-02-15 07:27:00,2.292\n2014-02-15 07:32:00,2.0780000000000003\n2014-02-15 07:37:00,2.542\n2014-02-15 07:42:00,2.0180000000000002\n2014-02-15 07:47:00,2.144\n2014-02-15 07:52:00,2.048\n2014-02-15 07:57:00,2.296\n2014-02-15 08:02:00,2.164\n2014-02-15 08:07:00,2.366\n2014-02-15 08:12:00,2.114\n2014-02-15 08:17:00,3.61\n2014-02-15 08:22:00,2.05\n2014-02-15 08:27:00,2.376\n2014-02-15 08:32:00,2.066\n2014-02-15 08:37:00,2.18\n2014-02-15 08:42:00,2.068\n2014-02-15 08:47:00,2.214\n2014-02-15 08:52:00,2.048\n2014-02-15 08:57:00,2.356\n2014-02-15 09:02:00,2.108\n2014-02-15 09:07:00,2.3\n2014-02-15 09:12:00,2.044\n2014-02-15 09:17:00,2.312\n2014-02-15 09:22:00,3.318\n2014-02-15 09:27:00,2.258\n2014-02-15 09:32:00,2.002\n2014-02-15 09:37:00,2.2119999999999997\n2014-02-15 09:42:00,2.044\n2014-02-15 09:47:00,2.244\n2014-02-15 09:52:00,2.062\n2014-02-15 09:57:00,2.332\n2014-02-15 10:02:00,2.05\n2014-02-15 10:07:00,2.298\n2014-02-15 10:12:00,3.3\n2014-02-15 10:17:00,2.302\n2014-02-15 10:22:00,2.036\n2014-02-15 10:27:00,2.2840000000000003\n2014-02-15 10:32:00,2.1519999999999997\n2014-02-15 10:37:00,2.2840000000000003\n2014-02-15 10:42:00,2.164\n2014-02-15 10:47:00,2.25\n2014-02-15 10:52:00,2.126\n2014-02-15 10:57:00,2.326\n2014-02-15 11:02:00,2.134\n2014-02-15 11:07:00,2.316\n2014-02-15 11:12:00,2.114\n2014-02-15 11:17:00,3.5660000000000003\n2014-02-15 11:22:00,2.11\n2014-02-15 11:27:00,2.17\n2014-02-15 11:32:00,1.9240000000000002\n2014-02-15 11:37:00,2.1180000000000003\n2014-02-15 11:42:00,2.042\n2014-02-15 11:47:00,2.1719999999999997\n2014-02-15 11:52:00,1.944\n2014-02-15 11:57:00,2.292\n2014-02-15 12:02:00,2.0\n2014-02-15 12:07:00,2.17\n2014-02-15 12:12:00,3.218\n2014-02-15 12:17:00,2.146\n2014-02-15 12:22:00,1.946\n2014-02-15 12:27:00,2.158\n2014-02-15 12:32:00,1.94\n2014-02-15 12:37:00,2.202\n2014-02-15 12:42:00,1.98\n2014-02-15 12:47:00,2.194\n2014-02-15 12:52:00,1.95\n2014-02-15 12:57:00,2.246\n2014-02-15 13:02:00,2.052\n2014-02-15 13:07:00,2.266\n2014-02-15 13:12:00,1.984\n2014-02-15 13:17:00,3.528\n2014-02-15 13:22:00,1.996\n2014-02-15 13:27:00,2.214\n2014-02-15 13:32:00,2.03\n2014-02-15 13:37:00,2.2159999999999997\n2014-02-15 13:42:00,2.0140000000000002\n2014-02-15 13:47:00,2.1959999999999997\n2014-02-15 13:52:00,2.064\n2014-02-15 13:57:00,2.262\n2014-02-15 14:02:00,2.06\n2014-02-15 14:07:00,2.306\n2014-02-15 14:12:00,1.982\n2014-02-15 14:17:00,3.4339999999999997\n2014-02-15 14:22:00,1.946\n2014-02-15 14:27:00,2.1519999999999997\n2014-02-15 14:32:00,1.886\n2014-02-15 14:37:00,2.102\n2014-02-15 14:42:00,1.93\n2014-02-15 14:47:00,2.244\n2014-02-15 14:52:00,1.956\n2014-02-15 14:57:00,2.234\n2014-02-15 15:02:00,1.994\n2014-02-15 15:07:00,2.158\n2014-02-15 15:12:00,1.98\n2014-02-15 15:17:00,3.446\n2014-02-15 15:22:00,2.0\n2014-02-15 15:27:00,2.23\n2014-02-15 15:32:00,1.952\n2014-02-15 15:37:00,2.222\n2014-02-15 15:42:00,1.974\n2014-02-15 15:47:00,2.242\n2014-02-15 15:52:00,1.974\n2014-02-15 15:57:00,2.258\n2014-02-15 16:02:00,1.9880000000000002\n2014-02-15 16:07:00,2.202\n2014-02-15 16:12:00,2.046\n2014-02-15 16:17:00,2.244\n2014-02-15 16:22:00,3.302\n2014-02-15 16:27:00,2.2359999999999998\n2014-02-15 16:32:00,1.942\n2014-02-15 16:37:00,2.15\n2014-02-15 16:42:00,2.07\n2014-02-15 16:47:00,2.334\n2014-02-15 16:52:00,2.01\n2014-02-15 16:57:00,2.242\n2014-02-15 17:02:00,1.996\n2014-02-15 17:07:00,2.186\n2014-02-15 17:12:00,2.002\n2014-02-15 17:17:00,3.4560000000000004\n2014-02-15 17:22:00,2.03\n2014-02-15 17:27:00,2.2159999999999997\n2014-02-15 17:32:00,2.052\n2014-02-15 17:37:00,2.15\n2014-02-15 17:42:00,2.048\n2014-02-15 17:47:00,2.234\n2014-02-15 17:52:00,2.062\n2014-02-15 17:57:00,2.276\n2014-02-15 18:02:00,2.0340000000000003\n2014-02-15 18:07:00,2.226\n2014-02-15 18:12:00,3.29\n2014-02-15 18:17:00,2.218\n2014-02-15 18:22:00,2.06\n2014-02-15 18:27:00,2.226\n2014-02-15 18:32:00,2.062\n2014-02-15 18:37:00,2.3080000000000003\n2014-02-15 18:42:00,2.052\n2014-02-15 18:47:00,2.23\n2014-02-15 18:52:00,2.066\n2014-02-15 18:57:00,2.238\n2014-02-15 19:02:00,2.04\n2014-02-15 19:07:00,2.2\n2014-02-15 19:12:00,2.064\n2014-02-15 19:17:00,2.3\n2014-02-15 19:22:00,3.322\n2014-02-15 19:27:00,2.208\n2014-02-15 19:32:00,1.922\n2014-02-15 19:37:00,2.134\n2014-02-15 19:42:00,1.9780000000000002\n2014-02-15 19:47:00,2.158\n2014-02-15 19:52:00,2.0140000000000002\n2014-02-15 19:57:00,2.266\n2014-02-15 20:02:00,2.18\n2014-02-15 20:07:00,2.2640000000000002\n2014-02-15 20:12:00,2.082\n2014-02-15 20:17:00,3.64\n2014-02-15 20:22:00,2.072\n2014-02-15 20:27:00,2.2359999999999998\n2014-02-15 20:32:00,2.1180000000000003\n2014-02-15 20:37:00,2.326\n2014-02-15 20:42:00,2.056\n2014-02-15 20:47:00,2.2680000000000002\n2014-02-15 20:52:00,2.164\n2014-02-15 20:57:00,2.346\n2014-02-15 21:02:00,37.134\n2014-02-15 21:07:00,61.11600000000001\n2014-02-15 21:12:00,52.378\n2014-02-15 21:17:00,12.267999999999999\n2014-02-15 21:22:00,2.802\n2014-02-15 21:27:00,4.034\n2014-02-15 21:32:00,3.0660000000000003\n2014-02-15 21:37:00,4.794\n2014-02-15 21:42:00,2.96\n2014-02-15 21:47:00,2.722\n2014-02-15 21:52:00,2.912\n2014-02-15 21:57:00,4.3\n2014-02-15 22:02:00,3.7460000000000004\n2014-02-15 22:07:00,2.4459999999999997\n2014-02-15 22:12:00,2.05\n2014-02-15 22:17:00,3.5839999999999996\n2014-02-15 22:22:00,2.116\n2014-02-15 22:27:00,2.33\n2014-02-15 22:32:00,2.136\n2014-02-15 22:37:00,2.35\n2014-02-15 22:42:00,2.2159999999999997\n2014-02-15 22:47:00,2.366\n2014-02-15 22:52:00,2.182\n2014-02-15 22:57:00,2.362\n2014-02-15 23:02:00,2.226\n2014-02-15 23:07:00,3.656\n2014-02-15 23:12:00,2.252\n2014-02-15 23:17:00,2.3819999999999997\n2014-02-15 23:22:00,2.2\n2014-02-15 23:27:00,2.3819999999999997\n2014-02-15 23:32:00,2.206\n2014-02-15 23:37:00,2.392\n2014-02-15 23:42:00,2.334\n2014-02-15 23:47:00,2.316\n2014-02-15 23:52:00,2.134\n2014-02-15 23:57:00,2.334\n2014-02-16 00:02:00,2.1180000000000003\n2014-02-16 00:07:00,2.35\n2014-02-16 00:12:00,2.234\n2014-02-16 00:17:00,2.334\n2014-02-16 00:22:00,3.5660000000000003\n2014-02-16 00:27:00,2.31\n2014-02-16 00:32:00,2.14\n2014-02-16 00:37:00,2.36\n2014-02-16 00:42:00,2.106\n2014-02-16 00:47:00,2.272\n2014-02-16 00:52:00,2.162\n2014-02-16 00:57:00,2.412\n2014-02-16 01:02:00,2.116\n2014-02-16 01:07:00,2.318\n2014-02-16 01:12:00,3.5260000000000002\n2014-02-16 01:17:00,2.414\n2014-02-16 01:22:00,2.22\n2014-02-16 01:27:00,2.412\n2014-02-16 01:32:00,2.12\n2014-02-16 01:37:00,2.376\n2014-02-16 01:42:00,2.124\n2014-02-16 01:47:00,2.426\n2014-02-16 01:52:00,2.2880000000000003\n2014-02-16 01:57:00,2.318\n2014-02-16 02:02:00,2.116\n2014-02-16 02:07:00,2.3\n2014-02-16 02:12:00,3.3760000000000003\n2014-02-16 02:17:00,2.334\n2014-02-16 02:22:00,2.05\n2014-02-16 02:27:00,2.3280000000000003\n2014-02-16 02:32:00,2.1\n2014-02-16 02:37:00,2.366\n2014-02-16 02:42:00,2.164\n2014-02-16 02:47:00,2.334\n2014-02-16 02:52:00,2.114\n2014-02-16 02:57:00,2.396\n2014-02-16 03:02:00,2.12\n2014-02-16 03:07:00,2.336\n2014-02-16 03:12:00,2.2\n2014-02-16 03:17:00,2.266\n2014-02-16 03:22:00,3.742\n2014-02-16 03:27:00,2.396\n2014-02-16 03:32:00,2.084\n2014-02-16 03:37:00,2.338\n2014-02-16 03:42:00,2.122\n2014-02-16 03:47:00,2.334\n2014-02-16 03:52:00,2.33\n2014-02-16 03:57:00,2.404\n2014-02-16 04:02:00,2.052\n2014-02-16 04:07:00,2.2840000000000003\n2014-02-16 04:12:00,2.1180000000000003\n2014-02-16 04:17:00,2.2640000000000002\n2014-02-16 04:22:00,3.43\n2014-02-16 04:27:00,2.3\n2014-02-16 04:32:00,2.096\n2014-02-16 04:37:00,2.336\n2014-02-16 04:42:00,2.072\n2014-02-16 04:47:00,2.234\n2014-02-16 04:52:00,2.17\n2014-02-16 04:57:00,2.3680000000000003\n2014-02-16 05:02:00,2.05\n2014-02-16 05:07:00,2.342\n2014-02-16 05:12:00,3.38\n2014-02-16 05:17:00,2.3280000000000003\n2014-02-16 05:22:00,2.102\n2014-02-16 05:27:00,2.334\n2014-02-16 05:32:00,2.066\n2014-02-16 05:37:00,2.2\n2014-02-16 05:42:00,2.094\n2014-02-16 05:47:00,2.424\n2014-02-16 05:52:00,2.08\n2014-02-16 05:57:00,2.28\n2014-02-16 06:02:00,2.096\n2014-02-16 06:07:00,3.634\n2014-02-16 06:12:00,2.05\n2014-02-16 06:17:00,2.184\n2014-02-16 06:22:00,2.0980000000000003\n2014-02-16 06:27:00,2.2840000000000003\n2014-02-16 06:32:00,2.12\n2014-02-16 06:37:00,2.336\n2014-02-16 06:42:00,2.102\n2014-02-16 06:47:00,2.302\n2014-02-16 06:52:00,2.146\n2014-02-16 06:57:00,2.378\n2014-02-16 07:02:00,2.15\n2014-02-16 07:07:00,2.352\n2014-02-16 07:12:00,3.46\n2014-02-16 07:17:00,2.292\n2014-02-16 07:22:00,2.08\n2014-02-16 07:27:00,2.252\n2014-02-16 07:32:00,2.144\n2014-02-16 07:37:00,2.6439999999999997\n2014-02-16 07:42:00,2.062\n2014-02-16 07:47:00,2.162\n2014-02-16 07:52:00,1.936\n2014-02-16 07:57:00,2.1959999999999997\n2014-02-16 08:02:00,1.996\n2014-02-16 08:07:00,2.254\n2014-02-16 08:12:00,1.932\n2014-02-16 08:17:00,2.1719999999999997\n2014-02-16 08:22:00,3.2260000000000004\n2014-02-16 08:27:00,2.116\n2014-02-16 08:32:00,1.98\n2014-02-16 08:37:00,2.1959999999999997\n2014-02-16 08:42:00,1.95\n2014-02-16 08:47:00,2.208\n2014-02-16 08:52:00,1.9340000000000002\n2014-02-16 08:57:00,2.296\n2014-02-16 09:02:00,2.002\n2014-02-16 09:07:00,2.162\n2014-02-16 09:12:00,3.2680000000000002\n2014-02-16 09:17:00,2.26\n2014-02-16 09:22:00,2.006\n2014-02-16 09:27:00,2.168\n2014-02-16 09:32:00,2.234\n2014-02-16 09:37:00,2.166\n2014-02-16 09:42:00,2.016\n2014-02-16 09:47:00,2.066\n2014-02-16 09:52:00,1.9980000000000002\n2014-02-16 09:57:00,2.2159999999999997\n2014-02-16 10:02:00,1.962\n2014-02-16 10:07:00,2.146\n2014-02-16 10:12:00,1.966\n2014-02-16 10:17:00,3.44\n2014-02-16 10:22:00,1.946\n2014-02-16 10:27:00,2.138\n2014-02-16 10:32:00,1.994\n2014-02-16 10:37:00,2.156\n2014-02-16 10:42:00,1.944\n2014-02-16 10:47:00,2.26\n2014-02-16 10:52:00,1.984\n2014-02-16 10:57:00,2.25\n2014-02-16 11:02:00,2.02\n2014-02-16 11:07:00,2.234\n2014-02-16 11:12:00,2.066\n2014-02-16 11:17:00,3.67\n2014-02-16 11:22:00,2.016\n2014-02-16 11:27:00,2.202\n2014-02-16 11:32:00,2.01\n2014-02-16 11:37:00,2.126\n2014-02-16 11:42:00,1.916\n2014-02-16 11:47:00,2.116\n2014-02-16 11:52:00,1.936\n2014-02-16 11:57:00,2.1519999999999997\n2014-02-16 12:02:00,2.05\n2014-02-16 12:07:00,2.1519999999999997\n2014-02-16 12:12:00,2.012\n2014-02-16 12:17:00,2.116\n2014-02-16 12:22:00,3.298\n2014-02-16 12:27:00,2.116\n2014-02-16 12:32:00,2.01\n2014-02-16 12:37:00,2.252\n2014-02-16 12:42:00,1.936\n2014-02-16 12:47:00,2.182\n2014-02-16 12:52:00,2.016\n2014-02-16 12:57:00,2.346\n2014-02-16 13:02:00,1.984\n2014-02-16 13:07:00,2.202\n2014-02-16 13:12:00,3.3339999999999996\n2014-02-16 13:17:00,2.23\n2014-02-16 13:22:00,2.0180000000000002\n2014-02-16 13:27:00,2.102\n2014-02-16 13:32:00,1.966\n2014-02-16 13:37:00,2.168\n2014-02-16 13:42:00,1.9340000000000002\n2014-02-16 13:47:00,2.116\n2014-02-16 13:52:00,1.9340000000000002\n2014-02-16 13:57:00,2.2\n2014-02-16 14:02:00,2.032\n2014-02-16 14:07:00,2.18\n2014-02-16 14:12:00,3.266\n2014-02-16 14:17:00,2.248\n2014-02-16 14:22:00,2.046\n2014-02-16 14:27:00,2.396\n2014-02-16 14:32:00,1.9180000000000001\n2014-02-16 14:37:00,2.136\n2014-02-16 14:42:00,2.032\n2014-02-16 14:47:00,2.166\n2014-02-16 14:52:00,1.996\n2014-02-16 14:57:00,2.1519999999999997\n2014-02-16 15:02:00,1.996\n2014-02-16 15:07:00,2.1\n2014-02-16 15:12:00,1.98\n2014-02-16 15:17:00,3.4739999999999998\n2014-02-16 15:22:00,1.99\n2014-02-16 15:27:00,2.116\n2014-02-16 15:32:00,1.944\n2014-02-16 15:37:00,2.1919999999999997\n2014-02-16 15:42:00,1.996\n2014-02-16 15:47:00,2.1959999999999997\n2014-02-16 15:52:00,1.956\n2014-02-16 15:57:00,2.214\n2014-02-16 16:02:00,2.022\n2014-02-16 16:07:00,2.142\n2014-02-16 16:12:00,1.9240000000000002\n2014-02-16 16:17:00,3.45\n2014-02-16 16:22:00,1.886\n2014-02-16 16:27:00,2.124\n2014-02-16 16:32:00,1.956\n2014-02-16 16:37:00,2.1919999999999997\n2014-02-16 16:42:00,1.9380000000000002\n2014-02-16 16:47:00,2.154\n2014-02-16 16:52:00,1.906\n2014-02-16 16:57:00,2.15\n2014-02-16 17:02:00,2.0\n2014-02-16 17:07:00,3.4\n2014-02-16 17:12:00,2.036\n2014-02-16 17:17:00,2.182\n2014-02-16 17:22:00,1.868\n2014-02-16 17:27:00,2.242\n2014-02-16 17:32:00,2.04\n2014-02-16 17:37:00,2.136\n2014-02-16 17:42:00,2.0340000000000003\n2014-02-16 17:47:00,2.244\n2014-02-16 17:52:00,1.956\n2014-02-16 17:57:00,2.112\n2014-02-16 18:02:00,1.966\n2014-02-16 18:07:00,2.084\n2014-02-16 18:12:00,1.9180000000000001\n2014-02-16 18:17:00,2.062\n2014-02-16 18:22:00,3.236\n2014-02-16 18:27:00,2.112\n2014-02-16 18:32:00,2.016\n2014-02-16 18:37:00,2.13\n2014-02-16 18:42:00,1.962\n2014-02-16 18:47:00,2.148\n2014-02-16 18:52:00,1.95\n2014-02-16 18:57:00,2.334\n2014-02-16 19:02:00,1.9340000000000002\n2014-02-16 19:07:00,2.096\n2014-02-16 19:12:00,2.02\n2014-02-16 19:17:00,2.1\n2014-02-16 19:22:00,3.1919999999999997\n2014-02-16 19:27:00,2.062\n2014-02-16 19:32:00,1.8940000000000001\n2014-02-16 19:37:00,2.088\n2014-02-16 19:42:00,1.966\n2014-02-16 19:47:00,2.134\n2014-02-16 19:52:00,1.9680000000000002\n2014-02-16 19:57:00,2.2159999999999997\n2014-02-16 20:02:00,1.94\n2014-02-16 20:07:00,2.142\n2014-02-16 20:12:00,1.9980000000000002\n2014-02-16 20:17:00,3.35\n2014-02-16 20:22:00,2.064\n2014-02-16 20:27:00,2.042\n2014-02-16 20:32:00,1.916\n2014-02-16 20:37:00,2.124\n2014-02-16 20:42:00,1.854\n2014-02-16 20:47:00,2.046\n2014-02-16 20:52:00,1.8940000000000001\n2014-02-16 20:57:00,2.11\n2014-02-16 21:02:00,1.8840000000000001\n2014-02-16 21:07:00,2.114\n2014-02-16 21:12:00,1.9240000000000002\n2014-02-16 21:17:00,2.074\n2014-02-16 21:22:00,3.218\n2014-02-16 21:27:00,2.086\n2014-02-16 21:32:00,1.8840000000000001\n2014-02-16 21:37:00,2.108\n2014-02-16 21:42:00,1.9880000000000002\n2014-02-16 21:47:00,2.0340000000000003\n2014-02-16 21:52:00,1.896\n2014-02-16 21:57:00,3.4160000000000004\n2014-02-16 22:02:00,1.9180000000000001\n2014-02-16 22:07:00,2.11\n2014-02-16 22:12:00,1.854\n2014-02-16 22:17:00,2.036\n2014-02-16 22:22:00,3.162\n2014-02-16 22:27:00,2.03\n2014-02-16 22:32:00,1.8980000000000001\n2014-02-16 22:37:00,2.0\n2014-02-16 22:42:00,1.864\n2014-02-16 22:47:00,2.046\n2014-02-16 22:52:00,1.93\n2014-02-16 22:57:00,2.106\n2014-02-16 23:02:00,2.02\n2014-02-16 23:07:00,2.016\n2014-02-16 23:12:00,3.1460000000000004\n2014-02-16 23:17:00,2.05\n2014-02-16 23:22:00,1.8159999999999998\n2014-02-16 23:27:00,2.046\n2014-02-16 23:32:00,1.834\n2014-02-16 23:37:00,2.096\n2014-02-16 23:42:00,1.8619999999999999\n2014-02-16 23:47:00,2.0540000000000003\n2014-02-16 23:52:00,1.91\n2014-02-16 23:57:00,2.1719999999999997\n2014-02-17 00:02:00,1.986\n2014-02-17 00:07:00,2.1519999999999997\n2014-02-17 00:12:00,1.986\n2014-02-17 00:17:00,3.532\n2014-02-17 00:22:00,1.854\n2014-02-17 00:27:00,2.144\n2014-02-17 00:32:00,1.8719999999999999\n2014-02-17 00:37:00,2.036\n2014-02-17 00:42:00,1.864\n2014-02-17 00:47:00,2.042\n2014-02-17 00:52:00,1.8459999999999999\n2014-02-17 00:57:00,2.142\n2014-02-17 01:02:00,1.84\n2014-02-17 01:07:00,3.338\n2014-02-17 01:12:00,1.806\n2014-02-17 01:17:00,2.032\n2014-02-17 01:22:00,1.8159999999999998\n2014-02-17 01:27:00,2.116\n2014-02-17 01:32:00,2.0340000000000003\n2014-02-17 01:37:00,2.0340000000000003\n2014-02-17 01:42:00,1.8659999999999999\n2014-02-17 01:47:00,1.996\n2014-02-17 01:52:00,1.886\n2014-02-17 01:57:00,2.1519999999999997\n2014-02-17 02:02:00,1.902\n2014-02-17 02:07:00,2.16\n2014-02-17 02:12:00,1.906\n2014-02-17 02:17:00,3.352\n2014-02-17 02:22:00,2.002\n2014-02-17 02:27:00,2.186\n2014-02-17 02:32:00,1.974\n2014-02-17 02:37:00,2.1919999999999997\n2014-02-17 02:42:00,2.11\n2014-02-17 02:47:00,2.092\n2014-02-17 02:52:00,1.916\n2014-02-17 02:57:00,2.2\n2014-02-17 03:02:00,4.534\n2014-02-17 03:07:00,2.716\n2014-02-17 03:12:00,3.9739999999999998\n2014-02-17 03:17:00,2.576\n2014-02-17 03:22:00,2.366\n2014-02-17 03:27:00,2.398\n2014-02-17 03:32:00,2.166\n2014-02-17 03:37:00,2.332\n2014-02-17 03:42:00,2.07\n2014-02-17 03:47:00,2.346\n2014-02-17 03:52:00,2.17\n2014-02-17 03:57:00,2.324\n2014-02-17 04:02:00,2.106\n2014-02-17 04:07:00,2.2840000000000003\n2014-02-17 04:12:00,3.49\n2014-02-17 04:17:00,2.29\n2014-02-17 04:22:00,2.224\n2014-02-17 04:27:00,2.674\n2014-02-17 04:32:00,2.134\n2014-02-17 04:37:00,4.624\n2014-02-17 04:42:00,2.424\n2014-02-17 04:47:00,2.358\n2014-02-17 04:52:00,2.204\n2014-02-17 04:57:00,2.464\n2014-02-17 05:02:00,2.2319999999999998\n2014-02-17 05:07:00,2.374\n2014-02-17 05:12:00,6.09\n2014-02-17 05:17:00,2.872\n2014-02-17 05:22:00,2.62\n2014-02-17 05:27:00,2.7\n2014-02-17 05:32:00,2.6660000000000004\n2014-02-17 05:37:00,2.8339999999999996\n2014-02-17 05:42:00,6.412000000000001\n2014-02-17 05:47:00,60.19\n2014-02-17 05:52:00,54.0\n2014-02-17 05:57:00,48.916000000000004\n2014-02-17 06:02:00,8.41\n2014-02-17 06:07:00,67.94800000000001\n2014-02-17 06:12:00,53.922\n2014-02-17 06:17:00,63.722\n2014-02-17 06:22:00,61.076\n2014-02-17 06:27:00,53.794\n2014-02-17 06:32:00,44.36600000000001\n2014-02-17 06:37:00,61.794\n2014-02-17 06:42:00,56.262\n2014-02-17 06:47:00,55.512\n2014-02-17 06:52:00,57.26600000000001\n2014-02-17 06:57:00,54.302\n2014-02-17 07:02:00,35.436\n2014-02-17 07:07:00,66.044\n2014-02-17 07:12:00,55.62600000000001\n2014-02-17 07:17:00,20.18\n2014-02-17 07:22:00,19.206\n2014-02-17 07:27:00,72.376\n2014-02-17 07:32:00,53.284\n2014-02-17 07:37:00,25.74\n2014-02-17 07:42:00,8.932\n2014-02-17 07:47:00,67.426\n2014-02-17 07:52:00,53.762\n2014-02-17 07:57:00,43.284\n2014-02-17 08:02:00,8.716000000000001\n2014-02-17 08:07:00,3.446\n2014-02-17 08:12:00,3.3339999999999996\n2014-02-17 08:17:00,4.598\n2014-02-17 08:22:00,3.298\n2014-02-17 08:27:00,3.1839999999999997\n2014-02-17 08:32:00,3.33\n2014-02-17 08:37:00,3.1660000000000004\n2014-02-17 08:42:00,3.33\n2014-02-17 08:47:00,3.1319999999999997\n2014-02-17 08:52:00,3.284\n2014-02-17 08:57:00,6.55\n2014-02-17 09:02:00,8.916\n2014-02-17 09:07:00,3.068\n2014-02-17 09:12:00,3.0639999999999996\n2014-02-17 09:17:00,4.364\n2014-02-17 09:22:00,3.0460000000000003\n2014-02-17 09:27:00,3.092\n2014-02-17 09:32:00,3.05\n2014-02-17 09:37:00,2.984\n2014-02-17 09:42:00,3.13\n2014-02-17 09:47:00,2.998\n2014-02-17 09:52:00,3.054\n2014-02-17 09:57:00,3.168\n2014-02-17 10:02:00,3.176\n2014-02-17 10:07:00,3.1839999999999997\n2014-02-17 10:12:00,4.314\n2014-02-17 10:17:00,3.048\n2014-02-17 10:22:00,3.0660000000000003\n2014-02-17 10:27:00,3.234\n2014-02-17 10:32:00,3.142\n2014-02-17 10:37:00,3.08\n2014-02-17 10:42:00,3.0639999999999996\n2014-02-17 10:47:00,3.016\n2014-02-17 10:52:00,3.2\n2014-02-17 10:57:00,3.0839999999999996\n2014-02-17 11:02:00,3.2319999999999998\n2014-02-17 11:07:00,3.2\n2014-02-17 11:12:00,3.1660000000000004\n2014-02-17 11:17:00,5.9\n2014-02-17 11:22:00,8.872\n2014-02-17 11:27:00,10.222000000000001\n2014-02-17 11:32:00,11.1\n2014-02-17 11:37:00,12.0\n2014-02-17 11:42:00,72.78399999999998\n2014-02-17 11:47:00,55.62\n2014-02-17 11:52:00,28.182\n2014-02-17 11:57:00,3.15\n2014-02-17 12:02:00,3.1639999999999997\n2014-02-17 12:07:00,3.016\n2014-02-17 12:12:00,3.218\n2014-02-17 12:17:00,4.436\n2014-02-17 12:22:00,3.148\n2014-02-17 12:27:00,3.0660000000000003\n2014-02-17 12:32:00,3.1660000000000004\n2014-02-17 12:37:00,3.1839999999999997\n2014-02-17 12:42:00,3.214\n2014-02-17 12:47:00,3.182\n2014-02-17 12:52:00,3.2319999999999998\n2014-02-17 12:57:00,3.13\n2014-02-17 13:02:00,3.3139999999999996\n2014-02-17 13:07:00,3.182\n2014-02-17 13:12:00,3.1660000000000004\n2014-02-17 13:17:00,4.346\n2014-02-17 13:22:00,3.284\n2014-02-17 13:27:00,3.2319999999999998\n2014-02-17 13:32:00,3.116\n2014-02-17 13:37:00,3.05\n2014-02-17 13:42:00,3.234\n2014-02-17 13:47:00,3.1660000000000004\n2014-02-17 13:52:00,3.18\n2014-02-17 13:57:00,3.1839999999999997\n2014-02-17 14:02:00,3.182\n2014-02-17 14:07:00,3.95\n2014-02-17 14:12:00,68.16199999999999\n2014-02-17 14:17:00,56.242\n2014-02-17 14:22:00,45.324\n2014-02-17 14:27:00,4.0\n2014-02-17 14:32:00,4.806\n2014-02-17 14:37:00,5.966\n2014-02-17 14:42:00,5.85\n2014-02-17 14:47:00,4.416\n2014-02-17 14:52:00,4.096\n2014-02-17 14:57:00,3.968\n2014-02-17 15:02:00,3.98\n2014-02-17 15:07:00,3.9339999999999997\n2014-02-17 15:12:00,5.834\n2014-02-17 15:17:00,5.2139999999999995\n2014-02-17 15:22:00,3.06\n2014-02-17 15:27:00,3.216\n2014-02-17 15:32:00,3.3339999999999996\n2014-02-17 15:37:00,3.234\n2014-02-17 15:42:00,3.466\n2014-02-17 15:47:00,3.25\n2014-02-17 15:52:00,3.45\n2014-02-17 15:57:00,3.522\n2014-02-17 16:02:00,3.31\n2014-02-17 16:07:00,4.518\n2014-02-17 16:12:00,3.614\n2014-02-17 16:17:00,3.1239999999999997\n2014-02-17 16:22:00,3.0980000000000003\n2014-02-17 16:27:00,3.08\n2014-02-17 16:32:00,3.238\n2014-02-17 16:37:00,3.196\n2014-02-17 16:42:00,3.25\n2014-02-17 16:47:00,3.2\n2014-02-17 16:52:00,3.134\n2014-02-17 16:57:00,3.128\n2014-02-17 17:02:00,3.286\n2014-02-17 17:07:00,3.266\n2014-02-17 17:12:00,3.228\n2014-02-17 17:17:00,4.216\n2014-02-17 17:22:00,3.4160000000000004\n2014-02-17 17:27:00,3.034\n2014-02-17 17:32:00,3.25\n2014-02-17 17:37:00,3.3819999999999997\n2014-02-17 17:42:00,3.322\n2014-02-17 17:47:00,3.1260000000000003\n2014-02-17 17:52:00,4.362\n2014-02-17 17:57:00,4.082\n2014-02-17 18:02:00,4.332\n2014-02-17 18:07:00,4.2360000000000015\n2014-02-17 18:12:00,8.783999999999999\n2014-02-17 18:17:00,5.504\n2014-02-17 18:22:00,3.952\n2014-02-17 18:27:00,4.244\n2014-02-17 18:32:00,4.184\n2014-02-17 18:37:00,4.3660000000000005\n2014-02-17 18:42:00,4.314\n2014-02-17 18:47:00,4.296\n2014-02-17 18:52:00,5.68\n2014-02-17 18:57:00,3.19\n2014-02-17 19:02:00,3.0660000000000003\n2014-02-17 19:07:00,2.984\n2014-02-17 19:12:00,4.442\n2014-02-17 19:17:00,3.114\n2014-02-17 19:22:00,3.0839999999999996\n2014-02-17 19:27:00,3.016\n2014-02-17 19:32:00,3.198\n2014-02-17 19:37:00,3.0980000000000003\n2014-02-17 19:42:00,3.182\n2014-02-17 19:47:00,3.116\n2014-02-17 19:52:00,3.2319999999999998\n2014-02-17 19:57:00,3.1519999999999997\n2014-02-17 20:02:00,3.3160000000000003\n2014-02-17 20:07:00,4.412\n2014-02-17 20:12:00,3.252\n2014-02-17 20:17:00,3.242\n2014-02-17 20:22:00,3.1839999999999997\n2014-02-17 20:27:00,3.15\n2014-02-17 20:32:00,3.4360000000000004\n2014-02-17 20:37:00,3.2939999999999996\n2014-02-17 20:42:00,3.282\n2014-02-17 20:47:00,3.45\n2014-02-17 20:52:00,3.298\n2014-02-17 20:57:00,3.2319999999999998\n2014-02-17 21:02:00,3.266\n2014-02-17 21:07:00,3.2880000000000003\n2014-02-17 21:12:00,4.426\n2014-02-17 21:17:00,3.116\n2014-02-17 21:22:00,3.3139999999999996\n2014-02-17 21:27:00,3.1519999999999997\n2014-02-17 21:32:00,3.25\n2014-02-17 21:37:00,3.196\n2014-02-17 21:42:00,3.25\n2014-02-17 21:47:00,3.198\n2014-02-17 21:52:00,3.1660000000000004\n2014-02-17 21:57:00,4.632\n2014-02-17 22:02:00,3.214\n2014-02-17 22:07:00,3.2680000000000002\n2014-02-17 22:12:00,3.11\n2014-02-17 22:17:00,4.396\n2014-02-17 22:22:00,3.366\n2014-02-17 22:27:00,3.29\n2014-02-17 22:32:00,3.074\n2014-02-17 22:37:00,3.216\n2014-02-17 22:42:00,3.048\n2014-02-17 22:47:00,3.1839999999999997\n2014-02-17 22:52:00,3.05\n2014-02-17 22:57:00,3.218\n2014-02-17 23:02:00,3.0660000000000003\n2014-02-17 23:07:00,3.05\n2014-02-17 23:12:00,3.28\n2014-02-17 23:17:00,4.59\n2014-02-17 23:22:00,64.638\n2014-02-17 23:27:00,52.118\n2014-02-17 23:32:00,44.85\n2014-02-17 23:37:00,3.734\n2014-02-17 23:42:00,4.184\n2014-02-17 23:47:00,5.0\n2014-02-17 23:52:00,9.294\n2014-02-17 23:57:00,7.38\n2014-02-18 00:02:00,37.984\n2014-02-18 00:07:00,62.838\n2014-02-18 00:12:00,53.72\n2014-02-18 00:17:00,15.466\n2014-02-18 00:22:00,4.25\n2014-02-18 00:27:00,5.6160000000000005\n2014-02-18 00:32:00,2.766\n2014-02-18 00:37:00,8.582\n2014-02-18 00:42:00,4.3\n2014-02-18 00:47:00,4.532\n2014-02-18 00:52:00,19.874000000000002\n2014-02-18 00:57:00,68.75399999999999\n2014-02-18 01:02:00,53.20399999999999\n2014-02-18 01:07:00,23.215999999999998\n2014-02-18 01:12:00,2.698\n2014-02-18 01:17:00,2.5340000000000003\n2014-02-18 01:22:00,3.7960000000000003\n2014-02-18 01:27:00,2.45\n2014-02-18 01:32:00,2.6180000000000003\n2014-02-18 01:37:00,2.5580000000000003\n2014-02-18 01:42:00,2.34\n2014-02-18 01:47:00,8.766\n2014-02-18 01:52:00,6.1339999999999995\n2014-02-18 01:57:00,4.566\n2014-02-18 02:02:00,10.948\n2014-02-18 02:07:00,6.916\n2014-02-18 02:12:00,11.527999999999999\n2014-02-18 02:17:00,5.372000000000001\n2014-02-18 02:22:00,3.076\n2014-02-18 02:27:00,3.072\n2014-02-18 02:32:00,6.2479999999999976\n2014-02-18 02:37:00,3.2880000000000003\n2014-02-18 02:42:00,3.076\n2014-02-18 02:47:00,2.912\n2014-02-18 02:52:00,4.9319999999999995\n2014-02-18 02:57:00,11.84\n2014-02-18 03:02:00,6.9879999999999995\n2014-02-18 03:07:00,9.3\n2014-02-18 03:12:00,4.598\n2014-02-18 03:17:00,5.85\n2014-02-18 03:22:00,4.1819999999999995\n2014-02-18 03:27:00,2.7\n2014-02-18 03:32:00,2.8280000000000003\n2014-02-18 03:37:00,2.5839999999999996\n2014-02-18 03:42:00,2.6060000000000003\n2014-02-18 03:47:00,2.54\n2014-02-18 03:52:00,2.522\n2014-02-18 03:57:00,2.592\n2014-02-18 04:02:00,2.516\n2014-02-18 04:07:00,2.634\n2014-02-18 04:12:00,6.66\n2014-02-18 04:17:00,4.516\n2014-02-18 04:22:00,7.182\n2014-02-18 04:27:00,3.734\n2014-02-18 04:32:00,4.81\n2014-02-18 04:37:00,3.716\n2014-02-18 04:42:00,5.73\n2014-02-18 04:47:00,3.55\n2014-02-18 04:52:00,3.766\n2014-02-18 04:57:00,3.628\n2014-02-18 05:02:00,3.75\n2014-02-18 05:07:00,5.1160000000000005\n2014-02-18 05:12:00,5.4220000000000015\n2014-02-18 05:17:00,3.1260000000000003\n2014-02-18 05:22:00,4.404\n2014-02-18 05:27:00,2.9139999999999997\n2014-02-18 05:32:00,2.9219999999999997\n2014-02-18 05:37:00,3.826\n2014-02-18 05:42:00,6.932\n2014-02-18 05:47:00,6.95\n2014-02-18 05:52:00,5.184\n2014-02-18 05:57:00,15.56\n2014-02-18 06:02:00,72.22\n2014-02-18 06:07:00,54.06399999999999\n2014-02-18 06:12:00,34.296\n2014-02-18 06:17:00,6.54\n2014-02-18 06:22:00,55.95\n2014-02-18 06:27:00,51.332\n2014-02-18 06:32:00,56.05\n2014-02-18 06:37:00,8.068\n2014-02-18 06:42:00,3.83\n2014-02-18 06:47:00,6.4460000000000015\n2014-02-18 06:52:00,4.086\n2014-02-18 06:57:00,15.548\n2014-02-18 07:02:00,3.716\n2014-02-18 07:07:00,6.376\n2014-02-18 07:12:00,3.466\n2014-02-18 07:17:00,3.142\n2014-02-18 07:22:00,3.42\n2014-02-18 07:27:00,3.122\n2014-02-18 07:32:00,3.342\n2014-02-18 07:37:00,2.8\n2014-02-18 07:42:00,3.208\n2014-02-18 07:47:00,2.85\n2014-02-18 07:52:00,3.17\n2014-02-18 07:57:00,2.766\n2014-02-18 08:02:00,3.014\n2014-02-18 08:07:00,2.54\n2014-02-18 08:12:00,4.1339999999999995\n2014-02-18 08:17:00,2.392\n2014-02-18 08:22:00,2.8760000000000003\n2014-02-18 08:27:00,2.9339999999999997\n2014-02-18 08:32:00,2.734\n2014-02-18 08:37:00,2.324\n2014-02-18 08:42:00,2.6719999999999997\n2014-02-18 08:47:00,2.238\n2014-02-18 08:52:00,2.64\n2014-02-18 08:57:00,2.3680000000000003\n2014-02-18 09:02:00,2.56\n2014-02-18 09:07:00,14.752\n2014-02-18 09:12:00,4.5360000000000005\n2014-02-18 09:17:00,3.472\n2014-02-18 09:22:00,3.2760000000000002\n2014-02-18 09:27:00,2.6180000000000003\n2014-02-18 09:32:00,3.13\n2014-02-18 09:37:00,4.484\n2014-02-18 09:42:00,4.1080000000000005\n2014-02-18 09:47:00,14.654000000000002\n2014-02-18 09:52:00,13.984000000000002\n2014-02-18 09:57:00,11.2\n2014-02-18 10:02:00,14.372\n2014-02-18 10:07:00,19.977999999999998\n2014-02-18 10:12:00,8.656\n2014-02-18 10:17:00,9.716000000000001\n2014-02-18 10:22:00,29.114\n2014-02-18 10:27:00,23.831999999999997\n2014-02-18 10:32:00,3.5839999999999996\n2014-02-18 10:37:00,3.04\n2014-02-18 10:42:00,3.45\n2014-02-18 10:47:00,3.04\n2014-02-18 10:52:00,3.4760000000000004\n2014-02-18 10:57:00,3.034\n2014-02-18 11:02:00,3.5\n2014-02-18 11:07:00,3.0239999999999996\n2014-02-18 11:12:00,4.788\n2014-02-18 11:17:00,2.972\n2014-02-18 11:22:00,3.444\n2014-02-18 11:27:00,2.966\n2014-02-18 11:32:00,3.318\n2014-02-18 11:37:00,2.83\n2014-02-18 11:42:00,3.36\n2014-02-18 11:47:00,2.766\n2014-02-18 11:52:00,3.2939999999999996\n2014-02-18 11:57:00,2.8339999999999996\n2014-02-18 12:02:00,3.29\n2014-02-18 12:07:00,2.988\n2014-02-18 12:12:00,3.234\n2014-02-18 12:17:00,4.084\n2014-02-18 12:22:00,3.258\n2014-02-18 12:27:00,2.7939999999999996\n2014-02-18 12:32:00,3.326\n2014-02-18 12:37:00,2.75\n2014-02-18 12:42:00,3.2680000000000002\n2014-02-18 12:47:00,2.7939999999999996\n2014-02-18 12:52:00,3.2760000000000002\n2014-02-18 12:57:00,2.79\n2014-02-18 13:02:00,3.29\n2014-02-18 13:07:00,4.19\n2014-02-18 13:12:00,3.29\n2014-02-18 13:17:00,2.8280000000000003\n2014-02-18 13:22:00,3.49\n2014-02-18 13:27:00,2.7880000000000003\n2014-02-18 13:32:00,3.3\n2014-02-18 13:37:00,2.782\n2014-02-18 13:42:00,3.2939999999999996\n2014-02-18 13:47:00,2.79\n2014-02-18 13:52:00,3.3\n2014-02-18 13:57:00,2.862\n2014-02-18 14:02:00,3.3160000000000003\n2014-02-18 14:07:00,2.86\n2014-02-18 14:12:00,4.56\n2014-02-18 14:17:00,2.806\n2014-02-18 14:22:00,3.25\n2014-02-18 14:27:00,2.852\n2014-02-18 14:32:00,3.266\n2014-02-18 14:37:00,2.772\n2014-02-18 14:42:00,3.2560000000000002\n2014-02-18 14:47:00,2.762\n2014-02-18 14:52:00,3.306\n2014-02-18 14:57:00,2.8480000000000003\n2014-02-18 15:02:00,3.3160000000000003\n2014-02-18 15:07:00,3.154\n2014-02-18 15:12:00,5.587999999999999\n2014-02-18 15:17:00,8.876\n2014-02-18 15:22:00,3.45\n2014-02-18 15:27:00,2.708\n2014-02-18 15:32:00,3.012\n2014-02-18 15:37:00,2.622\n2014-02-18 15:42:00,2.992\n2014-02-18 15:47:00,2.5660000000000003\n2014-02-18 15:52:00,2.958\n2014-02-18 15:57:00,2.574\n2014-02-18 16:02:00,2.908\n2014-02-18 16:07:00,2.5580000000000003\n2014-02-18 16:12:00,2.958\n2014-02-18 16:17:00,3.912\n2014-02-18 16:22:00,2.9419999999999997\n2014-02-18 16:27:00,2.5660000000000003\n2014-02-18 16:32:00,2.9339999999999997\n2014-02-18 16:37:00,2.576\n2014-02-18 16:42:00,2.9339999999999997\n2014-02-18 16:47:00,2.576\n2014-02-18 16:52:00,2.9419999999999997\n2014-02-18 16:57:00,2.6239999999999997\n2014-02-18 17:02:00,2.938\n2014-02-18 17:07:00,2.596\n2014-02-18 17:12:00,2.924\n2014-02-18 17:17:00,2.526\n2014-02-18 17:22:00,4.266\n2014-02-18 17:27:00,2.536\n2014-02-18 17:32:00,2.88\n2014-02-18 17:37:00,2.492\n2014-02-18 17:42:00,2.9419999999999997\n2014-02-18 17:47:00,2.5580000000000003\n2014-02-18 17:52:00,2.904\n2014-02-18 17:57:00,2.6060000000000003\n2014-02-18 18:02:00,2.86\n2014-02-18 18:07:00,2.542\n2014-02-18 18:12:00,4.188\n2014-02-18 18:17:00,2.556\n2014-02-18 18:22:00,2.9760000000000004\n2014-02-18 18:27:00,2.636\n2014-02-18 18:32:00,2.9539999999999997\n2014-02-18 18:37:00,2.6\n2014-02-18 18:42:00,3.008\n2014-02-18 18:47:00,9.908\n2014-02-18 18:52:00,70.77199999999998\n2014-02-18 18:57:00,50.81399999999999\n2014-02-18 19:02:00,32.36\n2014-02-18 19:07:00,4.206\n2014-02-18 19:12:00,5.284\n2014-02-18 19:17:00,4.45\n2014-02-18 19:22:00,3.89\n2014-02-18 19:27:00,5.2\n2014-02-18 19:32:00,3.508\n2014-02-18 19:37:00,3.194\n2014-02-18 19:42:00,3.6239999999999997\n2014-02-18 19:47:00,3.25\n2014-02-18 19:52:00,3.6919999999999997\n2014-02-18 19:57:00,4.3\n2014-02-18 20:02:00,2.978\n2014-02-18 20:07:00,2.648\n2014-02-18 20:12:00,4.263999999999999\n2014-02-18 20:17:00,2.6260000000000003\n2014-02-18 20:22:00,2.984\n2014-02-18 20:27:00,2.6260000000000003\n2014-02-18 20:32:00,2.938\n2014-02-18 20:37:00,2.53\n2014-02-18 20:42:00,2.94\n2014-02-18 20:47:00,2.5580000000000003\n2014-02-18 20:52:00,2.95\n2014-02-18 20:57:00,2.642\n2014-02-18 21:02:00,2.9419999999999997\n2014-02-18 21:07:00,2.608\n2014-02-18 21:12:00,2.8539999999999996\n2014-02-18 21:17:00,3.7880000000000003\n2014-02-18 21:22:00,2.884\n2014-02-18 21:27:00,2.504\n2014-02-18 21:32:00,2.94\n2014-02-18 21:37:00,2.576\n2014-02-18 21:42:00,2.95\n2014-02-18 21:47:00,2.55\n2014-02-18 21:52:00,2.9339999999999997\n2014-02-18 21:57:00,4.26\n2014-02-18 22:02:00,2.9419999999999997\n2014-02-18 22:07:00,3.9160000000000004\n2014-02-18 22:12:00,3.0\n2014-02-18 22:17:00,2.658\n2014-02-18 22:22:00,2.984\n2014-02-18 22:27:00,2.5839999999999996\n2014-02-18 22:32:00,3.0\n2014-02-18 22:37:00,2.6260000000000003\n2014-02-18 22:42:00,2.966\n2014-02-18 22:47:00,2.642\n2014-02-18 22:52:00,2.9960000000000004\n2014-02-18 22:57:00,43.42\n2014-02-18 23:02:00,57.066\n2014-02-18 23:07:00,55.431999999999995\n2014-02-18 23:12:00,14.45\n2014-02-18 23:17:00,5.202000000000001\n2014-02-18 23:22:00,5.36\n2014-02-18 23:27:00,3.99\n2014-02-18 23:32:00,5.65\n2014-02-18 23:37:00,3.65\n2014-02-18 23:42:00,3.9619999999999997\n2014-02-18 23:47:00,3.674\n2014-02-18 23:52:00,4.018\n2014-02-18 23:57:00,4.73\n2014-02-19 00:02:00,24.5\n2014-02-19 00:07:00,65.648\n2014-02-19 00:12:00,52.961999999999996\n2014-02-19 00:17:00,20.7\n2014-02-19 00:22:00,59.458\n2014-02-19 00:27:00,55.826\n2014-02-19 00:32:00,54.9\n2014-02-19 00:37:00,5.59\n2014-02-19 00:42:00,9.64\n2014-02-19 00:47:00,2.932\n2014-02-19 00:52:00,3.6839999999999997\n2014-02-19 00:57:00,3.366\n2014-02-19 01:02:00,9.038\n2014-02-19 01:07:00,6.584\n2014-02-19 01:12:00,5.098\n2014-02-19 01:17:00,3.4819999999999998\n2014-02-19 01:22:00,4.684\n2014-02-19 01:27:00,3.576\n2014-02-19 01:32:00,6.858\n2014-02-19 01:37:00,2.9760000000000004\n2014-02-19 01:42:00,2.938\n2014-02-19 01:47:00,7.6720000000000015\n2014-02-19 01:52:00,6.1160000000000005\n2014-02-19 01:57:00,4.94\n2014-02-19 02:02:00,6.034\n2014-02-19 02:07:00,5.688\n2014-02-19 02:12:00,4.368\n2014-02-19 02:17:00,3.266\n2014-02-19 02:22:00,5.058\n2014-02-19 02:27:00,3.5\n2014-02-19 02:32:00,3.826\n2014-02-19 02:37:00,4.598\n2014-02-19 02:42:00,2.9419999999999997\n2014-02-19 02:47:00,2.592\n2014-02-19 02:52:00,3.034\n2014-02-19 02:57:00,2.678\n2014-02-19 03:02:00,3.0380000000000003\n2014-02-19 03:07:00,2.6239999999999997\n2014-02-19 03:12:00,3.05\n2014-02-19 03:17:00,2.678\n2014-02-19 03:22:00,5.846\n2014-02-19 03:27:00,2.6919999999999997\n2014-02-19 03:32:00,12.204\n2014-02-19 03:37:00,2.642\n2014-02-19 03:42:00,3.138\n2014-02-19 03:47:00,2.76\n2014-02-19 03:52:00,3.4\n2014-02-19 03:57:00,4.65\n2014-02-19 04:02:00,3.2260000000000004\n2014-02-19 04:07:00,2.71\n2014-02-19 04:12:00,3.11\n2014-02-19 04:17:00,2.734\n2014-02-19 04:22:00,4.434\n2014-02-19 04:27:00,2.6919999999999997\n2014-02-19 04:32:00,3.0860000000000003\n2014-02-19 04:37:00,2.7\n2014-02-19 04:42:00,3.1060000000000003\n2014-02-19 04:47:00,2.65\n2014-02-19 04:52:00,3.028\n2014-02-19 04:57:00,2.722\n2014-02-19 05:02:00,5.127999999999999\n2014-02-19 05:07:00,3.28\n2014-02-19 05:12:00,4.053999999999999\n2014-02-19 05:17:00,10.356\n2014-02-19 05:22:00,71.154\n2014-02-19 05:27:00,52.05\n2014-02-19 05:32:00,31.184\n2014-02-19 05:37:00,3.408\n2014-02-19 05:42:00,5.416\n2014-02-19 05:47:00,3.4619999999999997\n2014-02-19 05:52:00,3.718\n2014-02-19 05:57:00,5.0760000000000005\n2014-02-19 06:02:00,3.3360000000000003\n2014-02-19 06:07:00,4.774\n2014-02-19 06:12:00,3.742\n2014-02-19 06:17:00,4.76\n2014-02-19 06:22:00,5.356\n2014-02-19 06:27:00,2.736\n2014-02-19 06:32:00,3.156\n2014-02-19 06:37:00,2.69\n2014-02-19 06:42:00,3.0839999999999996\n2014-02-19 06:47:00,2.6239999999999997\n2014-02-19 06:52:00,3.034\n2014-02-19 06:57:00,2.658\n2014-02-19 07:02:00,5.504\n2014-02-19 07:07:00,43.20399999999999\n2014-02-19 07:12:00,66.858\n2014-02-19 07:17:00,51.542\n2014-02-19 07:22:00,16.36\n2014-02-19 07:27:00,3.492\n2014-02-19 07:32:00,4.766\n2014-02-19 07:37:00,3.424\n2014-02-19 07:42:00,3.6839999999999997\n2014-02-19 07:47:00,5.042\n2014-02-19 07:52:00,3.358\n2014-02-19 07:57:00,3.202\n2014-02-19 08:02:00,3.6260000000000003\n2014-02-19 08:07:00,3.342\n2014-02-19 08:12:00,5.084\n2014-02-19 08:17:00,3.1839999999999997\n2014-02-19 08:22:00,3.6260000000000003\n2014-02-19 08:27:00,3.234\n2014-02-19 08:32:00,3.66\n2014-02-19 08:37:00,3.25\n2014-02-19 08:42:00,4.462\n2014-02-19 08:47:00,2.546\n2014-02-19 08:52:00,2.9160000000000004\n2014-02-19 08:57:00,2.6\n2014-02-19 09:02:00,2.926\n2014-02-19 09:07:00,2.5340000000000003\n2014-02-19 09:12:00,2.966\n2014-02-19 09:17:00,3.234\n2014-02-19 09:22:00,4.298\n2014-02-19 09:27:00,4.95\n2014-02-19 09:32:00,3.076\n2014-02-19 09:37:00,2.608\n2014-02-19 09:42:00,3.008\n2014-02-19 09:47:00,8.094\n2014-02-19 09:52:00,3.0260000000000002\n2014-02-19 09:57:00,2.642\n2014-02-19 10:02:00,2.978\n2014-02-19 10:07:00,3.8760000000000003\n2014-02-19 10:12:00,2.928\n2014-02-19 10:17:00,2.572\n2014-02-19 10:22:00,2.95\n2014-02-19 10:27:00,2.5180000000000002\n2014-02-19 10:32:00,2.9339999999999997\n2014-02-19 10:37:00,2.526\n2014-02-19 10:42:00,2.8760000000000003\n2014-02-19 10:47:00,2.542\n2014-02-19 10:52:00,2.9\n2014-02-19 10:57:00,2.576\n2014-02-19 11:02:00,2.8939999999999997\n2014-02-19 11:07:00,2.6\n2014-02-19 11:12:00,2.966\n2014-02-19 11:17:00,2.5839999999999996\n2014-02-19 11:22:00,4.216\n2014-02-19 11:27:00,2.5839999999999996\n2014-02-19 11:32:00,2.968\n2014-02-19 11:37:00,2.55\n2014-02-19 11:42:00,2.924\n2014-02-19 11:47:00,2.55\n2014-02-19 11:52:00,2.9160000000000004\n2014-02-19 11:57:00,2.594\n2014-02-19 12:02:00,2.93\n2014-02-19 12:07:00,2.5660000000000003\n2014-02-19 12:12:00,3.008\n2014-02-19 12:17:00,3.928\n2014-02-19 12:22:00,3.0\n2014-02-19 12:27:00,2.5660000000000003\n2014-02-19 12:32:00,2.9739999999999998\n2014-02-19 12:37:00,2.5780000000000003\n2014-02-19 12:42:00,2.968\n2014-02-19 12:47:00,2.582\n2014-02-19 12:52:00,2.992\n2014-02-19 12:57:00,2.65\n2014-02-19 13:02:00,2.97\n2014-02-19 13:07:00,2.6060000000000003\n2014-02-19 13:12:00,2.9939999999999998\n2014-02-19 13:17:00,2.58\n2014-02-19 13:22:00,4.3\n2014-02-19 13:27:00,2.61\n2014-02-19 13:32:00,2.9760000000000004\n2014-02-19 13:37:00,2.5839999999999996\n2014-02-19 13:42:00,2.9339999999999997\n2014-02-19 13:47:00,2.57\n2014-02-19 13:52:00,2.988\n2014-02-19 13:57:00,2.76\n2014-02-19 14:02:00,3.008\n2014-02-19 14:07:00,2.5660000000000003\n2014-02-19 14:12:00,2.92\n2014-02-19 14:17:00,2.556\n2014-02-19 14:22:00,4.32\n2014-02-19 14:27:00,2.48\n2014-02-19 14:32:00,2.8539999999999996\n2014-02-19 14:37:00,4.716\n2014-02-19 14:42:00,9.85\n2014-02-19 14:47:00,3.7439999999999998\n2014-02-19 14:52:00,5.41\n2014-02-19 14:57:00,4.158\n2014-02-19 15:02:00,6.0420000000000025\n2014-02-19 15:07:00,3.7960000000000003\n2014-02-19 15:12:00,4.0680000000000005\n2014-02-19 15:17:00,7.7079999999999975\n2014-02-19 15:22:00,4.226\n2014-02-19 15:27:00,5.184\n2014-02-19 15:32:00,3.1\n2014-02-19 15:37:00,2.66\n2014-02-19 15:42:00,3.16\n2014-02-19 15:47:00,2.642\n2014-02-19 15:52:00,3.1260000000000003\n2014-02-19 15:57:00,2.6860000000000004\n2014-02-19 16:02:00,3.108\n2014-02-19 16:07:00,2.674\n2014-02-19 16:12:00,4.3919999999999995\n2014-02-19 16:17:00,2.64\n2014-02-19 16:22:00,3.068\n2014-02-19 16:27:00,2.6519999999999997\n2014-02-19 16:32:00,3.1\n2014-02-19 16:37:00,2.698\n2014-02-19 16:42:00,3.092\n2014-02-19 16:47:00,2.716\n2014-02-19 16:52:00,3.1039999999999996\n2014-02-19 16:57:00,2.688\n2014-02-19 17:02:00,3.0660000000000003\n2014-02-19 17:07:00,2.67\n2014-02-19 17:12:00,3.108\n2014-02-19 17:17:00,3.966\n2014-02-19 17:22:00,3.0839999999999996\n2014-02-19 17:27:00,2.674\n2014-02-19 17:32:00,3.112\n2014-02-19 17:37:00,2.698\n2014-02-19 17:42:00,3.108\n2014-02-19 17:47:00,42.76600000000001\n2014-02-19 17:52:00,57.81\n2014-02-19 17:57:00,53.39\n2014-02-19 18:02:00,11.304\n2014-02-19 18:07:00,3.42\n2014-02-19 18:12:00,4.916\n2014-02-19 18:17:00,5.2\n2014-02-19 18:22:00,7.963999999999999\n2014-02-19 18:27:00,3.7\n2014-02-19 18:32:00,4.26\n2014-02-19 18:37:00,3.6660000000000004\n2014-02-19 18:42:00,4.3660000000000005\n2014-02-19 18:47:00,3.95\n2014-02-19 18:52:00,27.95\n2014-02-19 18:57:00,66.324\n2014-02-19 19:02:00,53.57\n2014-02-19 19:07:00,23.281999999999996\n2014-02-19 19:12:00,5.648\n2014-02-19 19:17:00,6.257999999999999\n2014-02-19 19:22:00,4.752\n2014-02-19 19:27:00,5.608\n2014-02-19 19:32:00,4.598\n2014-02-19 19:37:00,3.8339999999999996\n2014-02-19 19:42:00,4.54\n2014-02-19 19:47:00,4.1\n2014-02-19 19:52:00,4.374\n2014-02-19 19:57:00,4.4060000000000015\n2014-02-19 20:02:00,3.66\n2014-02-19 20:07:00,2.826\n2014-02-19 20:12:00,3.176\n2014-02-19 20:17:00,2.722\n2014-02-19 20:22:00,4.484\n2014-02-19 20:27:00,2.7260000000000004\n2014-02-19 20:32:00,3.174\n2014-02-19 20:37:00,2.708\n2014-02-19 20:42:00,3.1839999999999997\n2014-02-19 20:47:00,5.242000000000001\n2014-02-19 20:52:00,3.3760000000000003\n2014-02-19 20:57:00,3.06\n2014-02-19 21:02:00,3.4\n2014-02-19 21:07:00,8.73\n2014-02-19 21:12:00,5.936\n2014-02-19 21:17:00,3.97\n2014-02-19 21:22:00,4.846\n2014-02-19 21:27:00,3.466\n2014-02-19 21:32:00,5.886\n2014-02-19 21:37:00,3.4019999999999997\n2014-02-19 21:42:00,3.96\n2014-02-19 21:47:00,3.634\n2014-02-19 21:52:00,4.408\n2014-02-19 21:57:00,6.476\n2014-02-19 22:02:00,3.0839999999999996\n2014-02-19 22:07:00,2.734\n2014-02-19 22:12:00,4.434\n2014-02-19 22:17:00,2.77\n2014-02-19 22:22:00,3.108\n2014-02-19 22:27:00,2.676\n2014-02-19 22:32:00,3.158\n2014-02-19 22:37:00,2.7260000000000004\n2014-02-19 22:42:00,3.142\n2014-02-19 22:47:00,2.708\n2014-02-19 22:52:00,3.234\n2014-02-19 22:57:00,4.7360000000000015\n2014-02-19 23:02:00,59.083999999999996\n2014-02-19 23:07:00,52.916000000000004\n2014-02-19 23:12:00,52.61600000000001\n2014-02-19 23:17:00,6.6160000000000005\n2014-02-19 23:22:00,4.592\n2014-02-19 23:27:00,5.066\n2014-02-19 23:32:00,4.71\n2014-02-19 23:37:00,5.88\n2014-02-19 23:42:00,4.302\n2014-02-19 23:47:00,4.013999999999999\n2014-02-19 23:52:00,6.4639999999999995\n2014-02-19 23:57:00,4.238\n2014-02-20 00:02:00,4.6339999999999995\n2014-02-20 00:07:00,5.507999999999999\n2014-02-20 00:12:00,3.216\n2014-02-20 00:17:00,4.4860000000000015\n2014-02-20 00:22:00,3.1839999999999997\n2014-02-20 00:27:00,2.728\n2014-02-20 00:32:00,3.21\n2014-02-20 00:37:00,2.742\n2014-02-20 00:42:00,3.21\n2014-02-20 00:47:00,3.3160000000000003\n2014-02-20 00:52:00,27.965999999999998\n2014-02-20 00:57:00,65.554\n2014-02-20 01:02:00,53.722\n2014-02-20 01:07:00,20.334\n2014-02-20 01:12:00,5.896\n2014-02-20 01:17:00,6.976\n2014-02-20 01:22:00,3.15\n2014-02-20 01:27:00,7.058\n2014-02-20 01:32:00,4.078\n2014-02-20 01:37:00,4.3839999999999995\n2014-02-20 01:42:00,58.62600000000001\n2014-02-20 01:47:00,55.31399999999999\n2014-02-20 01:52:00,49.668\n2014-02-20 01:57:00,3.324\n2014-02-20 02:02:00,3.81\n2014-02-20 02:07:00,4.0360000000000005\n2014-02-20 02:12:00,4.3180000000000005\n2014-02-20 02:17:00,14.5\n2014-02-20 02:22:00,6.1160000000000005\n2014-02-20 02:27:00,6.742000000000001\n2014-02-20 02:32:00,4.434\n2014-02-20 02:37:00,5.756\n2014-02-20 02:42:00,4.11\n2014-02-20 02:47:00,3.68\n2014-02-20 02:52:00,4.042\n2014-02-20 02:57:00,3.7260000000000004\n2014-02-20 03:02:00,5.216\n2014-02-20 03:07:00,2.5340000000000003\n2014-02-20 03:12:00,2.908\n2014-02-20 03:17:00,3.68\n2014-02-20 03:22:00,2.8080000000000003\n2014-02-20 03:27:00,2.342\n2014-02-20 03:32:00,2.8080000000000003\n2014-02-20 03:37:00,2.314\n2014-02-20 03:42:00,2.73\n2014-02-20 03:47:00,2.2359999999999998\n2014-02-20 03:52:00,2.6460000000000004\n2014-02-20 03:57:00,2.26\n2014-02-20 04:02:00,2.676\n2014-02-20 04:07:00,2.24\n2014-02-20 04:12:00,3.904\n2014-02-20 04:17:00,2.178\n2014-02-20 04:22:00,2.5839999999999996\n2014-02-20 04:27:00,2.492\n2014-02-20 04:32:00,2.7\n2014-02-20 04:37:00,2.242\n2014-02-20 04:42:00,2.696\n2014-02-20 04:47:00,2.184\n2014-02-20 04:52:00,2.6180000000000003\n2014-02-20 04:57:00,2.2880000000000003\n2014-02-20 05:02:00,2.734\n2014-02-20 05:07:00,4.9\n2014-02-20 05:12:00,4.524\n2014-02-20 05:17:00,2.7760000000000002\n2014-02-20 05:22:00,3.1839999999999997\n2014-02-20 05:27:00,2.786\n2014-02-20 05:32:00,3.158\n2014-02-20 05:37:00,4.628\n2014-02-20 05:42:00,3.21\n2014-02-20 05:47:00,2.762\n2014-02-20 05:52:00,3.19\n2014-02-20 05:57:00,2.72\n2014-02-20 06:02:00,3.11\n2014-02-20 06:07:00,2.616\n2014-02-20 06:12:00,25.566\n2014-02-20 06:17:00,68.38600000000001\n2014-02-20 06:22:00,56.542\n2014-02-20 06:27:00,23.2\n2014-02-20 06:32:00,4.418\n2014-02-20 06:37:00,5.13\n2014-02-20 06:42:00,4.762\n2014-02-20 06:47:00,5.654\n2014-02-20 06:52:00,8.7\n2014-02-20 06:57:00,3.918\n2014-02-20 07:02:00,4.55\n2014-02-20 07:07:00,5.26\n2014-02-20 07:12:00,6.234\n2014-02-20 07:17:00,4.592\n2014-02-20 07:22:00,3.176\n2014-02-20 07:27:00,2.674\n2014-02-20 07:32:00,3.108\n2014-02-20 07:37:00,2.6180000000000003\n2014-02-20 07:42:00,2.99\n2014-02-20 07:47:00,2.8080000000000003\n2014-02-20 07:52:00,2.8339999999999996\n2014-02-20 07:57:00,2.42\n2014-02-20 08:02:00,2.738\n2014-02-20 08:07:00,2.292\n2014-02-20 08:12:00,2.6719999999999997\n2014-02-20 08:17:00,3.5460000000000003\n2014-02-20 08:22:00,2.6260000000000003\n2014-02-20 08:27:00,2.184\n2014-02-20 08:32:00,2.6\n2014-02-20 08:37:00,2.2\n2014-02-20 08:42:00,2.572\n2014-02-20 08:47:00,2.2\n2014-02-20 08:52:00,2.596\n2014-02-20 08:57:00,2.27\n2014-02-20 09:02:00,2.608\n2014-02-20 09:07:00,2.2159999999999997\n2014-02-20 09:12:00,3.85\n2014-02-20 09:17:00,2.634\n2014-02-20 09:22:00,2.694\n2014-02-20 09:27:00,2.32\n2014-02-20 09:32:00,2.488\n2014-02-20 09:37:00,2.066\n2014-02-20 09:42:00,2.44\n2014-02-20 09:47:00,2.06\n2014-02-20 09:52:00,2.384\n2014-02-20 09:57:00,2.1\n2014-02-20 10:02:00,5.1339999999999995\n2014-02-20 10:07:00,2.734\n2014-02-20 10:12:00,3.156\n2014-02-20 10:17:00,2.71\n2014-02-20 10:22:00,4.376\n2014-02-20 10:27:00,2.608\n2014-02-20 10:32:00,2.958\n2014-02-20 10:37:00,2.4659999999999997\n2014-02-20 10:42:00,2.8739999999999997\n2014-02-20 10:47:00,2.576\n2014-02-20 10:52:00,2.9160000000000004\n2014-02-20 10:57:00,2.4659999999999997\n2014-02-20 11:02:00,2.7760000000000002\n2014-02-20 11:07:00,2.342\n2014-02-20 11:12:00,2.722\n2014-02-20 11:17:00,3.55\n2014-02-20 11:22:00,2.722\n2014-02-20 11:27:00,2.302\n2014-02-20 11:32:00,2.758\n2014-02-20 11:37:00,2.324\n2014-02-20 11:42:00,2.766\n2014-02-20 11:47:00,2.266\n2014-02-20 11:52:00,8.866\n2014-02-20 11:57:00,2.7239999999999998\n2014-02-20 12:02:00,3.1180000000000003\n2014-02-20 12:07:00,2.6660000000000004\n2014-02-20 12:12:00,3.05\n2014-02-20 12:17:00,3.9139999999999997\n2014-02-20 12:22:00,2.878\n2014-02-20 12:27:00,2.4219999999999997\n2014-02-20 12:32:00,2.7260000000000004\n2014-02-20 12:37:00,2.352\n2014-02-20 12:42:00,2.742\n2014-02-20 12:47:00,6.7620000000000005\n2014-02-20 12:52:00,7.28\n2014-02-20 12:57:00,2.97\n2014-02-20 13:02:00,3.216\n2014-02-20 13:07:00,2.786\n2014-02-20 13:12:00,4.322\n2014-02-20 13:17:00,2.524\n2014-02-20 13:22:00,2.842\n2014-02-20 13:27:00,2.45\n2014-02-20 13:32:00,2.764\n2014-02-20 13:37:00,2.35\n2014-02-20 13:42:00,2.7039999999999997\n2014-02-20 13:47:00,2.292\n2014-02-20 13:52:00,2.708\n2014-02-20 13:57:00,2.2840000000000003\n2014-02-20 14:02:00,2.674\n2014-02-20 14:07:00,3.534\n2014-02-20 14:12:00,2.592\n2014-02-20 14:17:00,2.166\n2014-02-20 14:22:00,2.658\n2014-02-20 14:27:00,2.25\n2014-02-20 14:32:00,2.634\n2014-02-20 14:37:00,2.2840000000000003\n2014-02-20 14:42:00,2.5839999999999996\n2014-02-20 14:47:00,2.33\n2014-02-20 14:52:00,7.284\n2014-02-20 14:57:00,2.8339999999999996\n2014-02-20 15:02:00,3.1719999999999997\n2014-02-20 15:07:00,2.6839999999999997\n2014-02-20 15:12:00,4.32\n2014-02-20 15:17:00,2.548\n2014-02-20 15:22:00,2.9\n2014-02-20 15:27:00,2.458\n2014-02-20 15:32:00,2.8080000000000003\n2014-02-20 15:37:00,2.376\n2014-02-20 15:42:00,2.7760000000000002\n2014-02-20 15:47:00,2.3040000000000003\n2014-02-20 15:52:00,2.7539999999999996\n2014-02-20 15:57:00,2.324\n2014-02-20 16:02:00,25.3\n2014-02-20 16:07:00,64.79\n2014-02-20 16:12:00,52.52\n2014-02-20 16:17:00,20.168\n2014-02-20 16:22:00,4.73\n2014-02-20 16:27:00,4.1339999999999995\n2014-02-20 16:32:00,3.634\n2014-02-20 16:37:00,4.772\n2014-02-20 16:42:00,3.338\n2014-02-20 16:47:00,2.636\n2014-02-20 16:52:00,3.44\n2014-02-20 16:57:00,3.01\n2014-02-20 17:02:00,3.2939999999999996\n2014-02-20 17:07:00,3.764\n2014-02-20 17:12:00,3.716\n2014-02-20 17:17:00,2.016\n2014-02-20 17:22:00,2.424\n2014-02-20 17:27:00,2.026\n2014-02-20 17:32:00,2.35\n2014-02-20 17:37:00,2.026\n2014-02-20 17:42:00,2.366\n2014-02-20 17:47:00,1.99\n2014-02-20 17:52:00,2.384\n2014-02-20 17:57:00,2.146\n2014-02-20 18:02:00,2.394\n2014-02-20 18:07:00,2.0340000000000003\n2014-02-20 18:12:00,3.612\n2014-02-20 18:17:00,2.0780000000000003\n2014-02-20 18:22:00,2.418\n2014-02-20 18:27:00,2.094\n2014-02-20 18:32:00,2.484\n2014-02-20 18:37:00,2.184\n2014-02-20 18:42:00,2.5580000000000003\n2014-02-20 18:47:00,2.178\n2014-02-20 18:52:00,2.4659999999999997\n2014-02-20 18:57:00,2.184\n2014-02-20 19:02:00,2.46\n2014-02-20 19:07:00,2.106\n2014-02-20 19:12:00,3.594\n2014-02-20 19:17:00,41.716\n2014-02-20 19:22:00,57.114\n2014-02-20 19:27:00,53.19600000000001\n2014-02-20 19:32:00,9.984\n2014-02-20 19:37:00,2.716\n2014-02-20 19:42:00,4.144\n2014-02-20 19:47:00,2.9160000000000004\n2014-02-20 19:52:00,5.034\n2014-02-20 19:57:00,2.6060000000000003\n2014-02-20 20:02:00,2.762\n2014-02-20 20:07:00,2.658\n2014-02-20 20:12:00,4.35\n2014-02-20 20:17:00,2.7939999999999996\n2014-02-20 20:22:00,3.05\n2014-02-20 20:27:00,3.8939999999999997\n2014-02-20 20:32:00,2.256\n2014-02-20 20:37:00,1.922\n2014-02-20 20:42:00,2.25\n2014-02-20 20:47:00,1.91\n2014-02-20 20:52:00,2.224\n2014-02-20 20:57:00,2.654\n2014-02-20 21:02:00,2.978\n2014-02-20 21:07:00,4.334\n2014-02-20 21:12:00,2.972\n2014-02-20 21:17:00,2.59\n2014-02-20 21:22:00,3.156\n2014-02-20 21:27:00,2.884\n2014-02-20 21:32:00,3.522\n2014-02-20 21:37:00,3.134\n2014-02-20 21:42:00,3.016\n2014-02-20 21:47:00,3.096\n2014-02-20 21:52:00,3.4939999999999998\n2014-02-20 21:57:00,4.64\n2014-02-20 22:02:00,4.2780000000000005\n2014-02-20 22:07:00,1.9240000000000002\n2014-02-20 22:12:00,2.234\n2014-02-20 22:17:00,1.9680000000000002\n2014-02-20 22:22:00,58.508\n2014-02-20 22:27:00,51.88399999999999\n2014-02-20 22:32:00,47.733999999999995\n2014-02-20 22:37:00,3.7319999999999998\n2014-02-20 22:42:00,2.434\n2014-02-20 22:47:00,2.104\n2014-02-20 22:52:00,2.438\n2014-02-20 22:57:00,2.134\n2014-02-20 23:02:00,2.356\n2014-02-20 23:07:00,3.3160000000000003\n2014-02-20 23:12:00,2.36\n2014-02-20 23:17:00,2.01\n2014-02-20 23:22:00,2.39\n2014-02-20 23:27:00,2.076\n2014-02-20 23:32:00,2.356\n2014-02-20 23:37:00,2.0380000000000003\n2014-02-20 23:42:00,2.4219999999999997\n2014-02-20 23:47:00,2.2159999999999997\n2014-02-20 23:52:00,2.364\n2014-02-20 23:57:00,38.08\n2014-02-21 00:02:00,60.402\n2014-02-21 00:07:00,52.478\n2014-02-21 00:12:00,13.094000000000001\n2014-02-21 00:17:00,2.388\n2014-02-21 00:22:00,3.716\n2014-02-21 00:27:00,1.9680000000000002\n2014-02-21 00:32:00,2.316\n2014-02-21 00:37:00,1.916\n2014-02-21 00:42:00,2.256\n2014-02-21 00:47:00,2.01\n2014-02-21 00:52:00,3.9339999999999997\n2014-02-21 00:57:00,64.882\n2014-02-21 01:02:00,52.378\n2014-02-21 01:07:00,59.606\n2014-02-21 01:12:00,63.968\n2014-02-21 01:17:00,53.13\n2014-02-21 01:22:00,18.994\n2014-02-21 01:27:00,2.694\n2014-02-21 01:32:00,4.816\n2014-02-21 01:37:00,2.546\n2014-02-21 01:42:00,3.042\n2014-02-21 01:47:00,2.846\n2014-02-21 01:52:00,3.094\n2014-02-21 01:57:00,6.25\n2014-02-21 02:02:00,3.216\n2014-02-21 02:07:00,3.9339999999999997\n2014-02-21 02:12:00,3.24\n2014-02-21 02:17:00,5.846\n2014-02-21 02:22:00,3.0060000000000002\n2014-02-21 02:27:00,2.484\n2014-02-21 02:32:00,3.156\n2014-02-21 02:37:00,2.9\n2014-02-21 02:42:00,3.216\n2014-02-21 02:47:00,4.716\n2014-02-21 02:52:00,2.2840000000000003\n2014-02-21 02:57:00,1.992\n2014-02-21 03:02:00,2.24\n2014-02-21 03:07:00,2.654\n2014-02-21 03:12:00,27.636\n2014-02-21 03:17:00,64.304\n2014-02-21 03:22:00,52.55\n2014-02-21 03:27:00,18.668\n2014-02-21 03:32:00,2.988\n2014-02-21 03:37:00,3.74\n2014-02-21 03:42:00,3.138\n2014-02-21 03:47:00,4.474\n2014-02-21 03:52:00,3.0439999999999996\n2014-02-21 03:57:00,2.41\n2014-02-21 04:02:00,3.0239999999999996\n2014-02-21 04:07:00,2.7060000000000004\n2014-02-21 04:12:00,4.303999999999999\n2014-02-21 04:17:00,3.87\n2014-02-21 04:22:00,2.21\n2014-02-21 04:27:00,1.9340000000000002\n2014-02-21 04:32:00,2.266\n2014-02-21 04:37:00,1.944\n2014-02-21 04:42:00,2.266\n2014-02-21 04:47:00,1.944\n2014-02-21 04:52:00,2.24\n2014-02-21 04:57:00,2.056\n2014-02-21 05:02:00,2.326\n2014-02-21 05:07:00,2.022\n2014-02-21 05:12:00,3.556\n2014-02-21 05:17:00,1.996\n2014-02-21 05:22:00,2.326\n2014-02-21 05:27:00,2.046\n2014-02-21 05:32:00,2.366\n2014-02-21 05:37:00,4.71\n2014-02-21 05:42:00,2.908\n2014-02-21 05:47:00,2.62\n2014-02-21 05:52:00,3.068\n2014-02-21 05:57:00,2.6460000000000004\n2014-02-21 06:02:00,3.0039999999999996\n2014-02-21 06:07:00,2.55\n2014-02-21 06:12:00,2.85\n2014-02-21 06:17:00,58.95399999999999\n2014-02-21 06:22:00,52.166000000000004\n2014-02-21 06:27:00,53.15\n2014-02-21 06:32:00,2.676\n2014-02-21 06:37:00,2.23\n2014-02-21 06:42:00,2.596\n2014-02-21 06:47:00,2.158\n2014-02-21 06:52:00,2.55\n2014-02-21 06:57:00,2.234\n2014-02-21 07:02:00,2.5839999999999996\n2014-02-21 07:07:00,2.21\n2014-02-21 07:12:00,2.758\n2014-02-21 07:17:00,3.3160000000000003\n2014-02-21 07:22:00,2.6239999999999997\n2014-02-21 07:27:00,2.254\n2014-02-21 07:32:00,3.5460000000000003\n2014-02-21 07:37:00,66.858\n2014-02-21 07:42:00,53.03\n2014-02-21 07:47:00,37.994\n2014-02-21 07:52:00,3.208\n2014-02-21 07:57:00,3.846\n2014-02-21 08:02:00,3.7239999999999998\n2014-02-21 08:07:00,2.8160000000000003\n2014-02-21 08:12:00,4.8839999999999995\n2014-02-21 08:17:00,2.6\n2014-02-21 08:22:00,9.154\n2014-02-21 08:27:00,3.2939999999999996\n2014-02-21 08:32:00,3.758\n2014-02-21 08:37:00,6.5360000000000005\n2014-02-21 08:42:00,3.092\n2014-02-21 08:47:00,2.6919999999999997\n2014-02-21 08:52:00,6.8839999999999995\n2014-02-21 08:57:00,2.722\n2014-02-21 09:02:00,3.02\n2014-02-21 09:07:00,3.838\n2014-02-21 09:12:00,5.516\n2014-02-21 09:17:00,3.042\n2014-02-21 09:22:00,2.9760000000000004\n2014-02-21 09:27:00,4.466\n2014-02-21 09:32:00,3.136\n2014-02-21 09:37:00,2.638\n2014-02-21 09:42:00,2.9760000000000004\n2014-02-21 09:47:00,2.4859999999999998\n2014-02-21 09:52:00,2.842\n2014-02-21 09:57:00,2.45\n2014-02-21 10:02:00,2.772\n2014-02-21 10:07:00,2.366\n2014-02-21 10:12:00,3.9960000000000004\n2014-02-21 10:17:00,2.32\n2014-02-21 10:22:00,2.654\n2014-02-21 10:27:00,2.1919999999999997\n2014-02-21 10:32:00,2.658\n2014-02-21 10:37:00,2.25\n2014-02-21 10:42:00,2.658\n2014-02-21 10:47:00,2.2159999999999997\n2014-02-21 10:52:00,2.6260000000000003\n2014-02-21 10:57:00,2.258\n2014-02-21 11:02:00,2.61\n2014-02-21 11:07:00,2.1959999999999997\n2014-02-21 11:12:00,2.562\n2014-02-21 11:17:00,3.534\n2014-02-21 11:22:00,2.66\n2014-02-21 11:27:00,2.292\n2014-02-21 11:32:00,2.55\n2014-02-21 11:37:00,2.1919999999999997\n2014-02-21 11:42:00,2.5340000000000003\n2014-02-21 11:47:00,2.184\n2014-02-21 11:52:00,2.476\n2014-02-21 11:57:00,2.202\n2014-02-21 12:02:00,2.556\n2014-02-21 12:07:00,2.228\n2014-02-21 12:12:00,6.666\n2014-02-21 12:17:00,2.694\n2014-02-21 12:22:00,3.09\n2014-02-21 12:27:00,2.634\n2014-02-21 12:32:00,2.86\n2014-02-21 12:37:00,2.492\n2014-02-21 12:42:00,2.78\n2014-02-21 12:47:00,2.354\n2014-02-21 12:52:00,2.694\n2014-02-21 12:57:00,2.342\n2014-02-21 13:02:00,2.576\n2014-02-21 13:07:00,2.158\n2014-02-21 13:12:00,3.838\n2014-02-21 13:17:00,2.1959999999999997\n2014-02-21 13:22:00,2.59\n2014-02-21 13:27:00,2.184\n2014-02-21 13:32:00,2.524\n2014-02-21 13:37:00,2.19\n2014-02-21 13:42:00,5.0760000000000005\n2014-02-21 13:47:00,2.742\n2014-02-21 13:52:00,3.1919999999999997\n2014-02-21 13:57:00,2.758\n2014-02-21 14:02:00,3.016\n2014-02-21 14:07:00,2.5580000000000003\n2014-02-21 14:12:00,2.924\n2014-02-21 14:17:00,5.28\n2014-02-21 14:22:00,4.508\n2014-02-21 14:27:00,2.7260000000000004\n2014-02-21 14:32:00,9.226\n2014-02-21 14:37:00,4.808\n2014-02-21 14:42:00,3.134\n2014-02-21 14:47:00,2.65\n2014-02-21 14:52:00,3.008\n2014-02-21 14:57:00,2.582\n2014-02-21 15:02:00,2.842\n2014-02-21 15:07:00,2.384\n2014-02-21 15:12:00,2.784\n2014-02-21 15:17:00,3.634\n2014-02-21 15:22:00,2.73\n2014-02-21 15:27:00,2.312\n2014-02-21 15:32:00,2.576\n2014-02-21 15:37:00,2.146\n2014-02-21 15:42:00,2.5780000000000003\n2014-02-21 15:47:00,2.16\n2014-02-21 15:52:00,2.5580000000000003\n2014-02-21 15:57:00,2.226\n2014-02-21 16:02:00,2.592\n2014-02-21 16:07:00,2.242\n2014-02-21 16:12:00,2.622\n2014-02-21 16:17:00,3.67\n2014-02-21 16:22:00,2.634\n2014-02-21 16:27:00,2.258\n2014-02-21 16:32:00,2.594\n2014-02-21 16:37:00,38.366\n2014-02-21 16:42:00,60.4\n2014-02-21 16:47:00,52.62600000000001\n2014-02-21 16:52:00,13.936\n2014-02-21 16:57:00,2.964\n2014-02-21 17:02:00,4.226\n2014-02-21 17:07:00,4.33\n2014-02-21 17:12:00,3.24\n2014-02-21 17:17:00,4.676\n2014-02-21 17:22:00,2.838\n2014-02-21 17:27:00,2.938\n2014-02-21 17:32:00,3.122\n2014-02-21 17:37:00,2.8139999999999996\n2014-02-21 17:42:00,4.328\n2014-02-21 17:47:00,2.056\n2014-02-21 17:52:00,2.39\n2014-02-21 17:57:00,2.23\n2014-02-21 18:02:00,2.456\n2014-02-21 18:07:00,2.0780000000000003\n2014-02-21 18:12:00,2.6\n2014-02-21 18:17:00,3.194\n2014-02-21 18:22:00,2.412\n2014-02-21 18:27:00,2.106\n2014-02-21 18:32:00,2.412\n2014-02-21 18:37:00,2.1519999999999997\n2014-02-21 18:42:00,2.494\n2014-02-21 18:47:00,2.22\n2014-02-21 18:52:00,2.484\n2014-02-21 18:57:00,2.206\n2014-02-21 19:02:00,2.484\n2014-02-21 19:07:00,2.266\n2014-02-21 19:12:00,3.9160000000000004\n2014-02-21 19:17:00,2.128\n2014-02-21 19:22:00,2.516\n2014-02-21 19:27:00,2.14\n2014-02-21 19:32:00,2.428\n2014-02-21 19:37:00,2.162\n2014-02-21 19:42:00,2.444\n2014-02-21 19:47:00,2.156\n2014-02-21 19:52:00,2.494\n2014-02-21 19:57:00,2.234\n2014-02-21 20:02:00,2.444\n2014-02-21 20:07:00,2.256\n2014-02-21 20:12:00,3.734\n2014-02-21 20:17:00,2.106\n2014-02-21 20:22:00,2.384\n2014-02-21 20:27:00,2.088\n2014-02-21 20:32:00,2.388\n2014-02-21 20:37:00,2.112\n2014-02-21 20:42:00,2.406\n2014-02-21 20:47:00,2.14\n2014-02-21 20:52:00,2.412\n2014-02-21 20:57:00,2.166\n2014-02-21 21:02:00,2.418\n2014-02-21 21:07:00,2.134\n2014-02-21 21:12:00,3.766\n2014-02-21 21:17:00,2.084\n2014-02-21 21:22:00,3.15\n2014-02-21 21:27:00,3.55\n2014-02-21 21:32:00,2.34\n2014-02-21 21:37:00,2.026\n2014-02-21 21:42:00,2.344\n2014-02-21 21:47:00,2.09\n2014-02-21 21:52:00,2.362\n2014-02-21 21:57:00,3.762\n2014-02-21 22:02:00,2.294\n2014-02-21 22:07:00,2.0340000000000003\n2014-02-21 22:12:00,2.29\n2014-02-21 22:17:00,2.022\n2014-02-21 22:22:00,4.276\n2014-02-21 22:27:00,2.028\n2014-02-21 22:32:00,2.3\n2014-02-21 22:37:00,2.056\n2014-02-21 22:42:00,25.524\n2014-02-21 22:47:00,64.19800000000001\n2014-02-21 22:52:00,52.666000000000004\n2014-02-21 22:57:00,25.48\n2014-02-21 23:02:00,70.672\n2014-02-21 23:07:00,53.742\n2014-02-21 23:12:00,28.498\n2014-02-21 23:17:00,5.766\n2014-02-21 23:22:00,3.05\n2014-02-21 23:27:00,2.4619999999999997\n2014-02-21 23:32:00,4.024\n2014-02-21 23:37:00,67.204\n2014-02-21 23:42:00,53.141999999999996\n2014-02-21 23:47:00,42.571999999999996\n2014-02-21 23:52:00,57.86\n2014-02-21 23:57:00,75.24600000000002\n2014-02-22 00:02:00,99.66799999999999\n2014-02-22 00:07:00,70.582\n2014-02-22 00:12:00,28.51\n2014-02-22 00:17:00,2.45\n2014-02-22 00:22:00,2.884\n2014-02-22 00:27:00,38.874\n2014-02-22 00:32:00,61.258\n2014-02-22 00:37:00,53.483999999999995\n2014-02-22 00:42:00,29.218000000000004\n2014-02-22 00:47:00,4.508\n2014-02-22 00:52:00,3.8960000000000004\n2014-02-22 00:57:00,3.266\n2014-02-22 01:02:00,5.343999999999999\n2014-02-22 01:07:00,2.8760000000000003\n2014-02-22 01:12:00,3.322\n2014-02-22 01:17:00,3.134\n2014-02-22 01:22:00,4.7\n2014-02-22 01:27:00,14.384\n2014-02-22 01:32:00,8.658\n2014-02-22 01:37:00,4.75\n2014-02-22 01:42:00,4.684\n2014-02-22 01:47:00,5.374\n2014-02-22 01:52:00,4.708\n2014-02-22 01:57:00,5.7620000000000005\n2014-02-22 02:02:00,4.334\n2014-02-22 02:07:00,3.784\n2014-02-22 02:12:00,4.34\n2014-02-22 02:17:00,5.27\n2014-02-22 02:22:00,4.092\n2014-02-22 02:27:00,5.148\n2014-02-22 02:32:00,3.55\n2014-02-22 02:37:00,3.15\n2014-02-22 02:42:00,4.684\n2014-02-22 02:47:00,2.242\n2014-02-22 02:52:00,2.596\n2014-02-22 02:57:00,2.344\n2014-02-22 03:02:00,2.64\n2014-02-22 03:07:00,2.384\n2014-02-22 03:12:00,2.616\n2014-02-22 03:17:00,2.5\n2014-02-22 03:22:00,3.81\n2014-02-22 03:27:00,2.244\n2014-02-22 03:32:00,2.522\n2014-02-22 03:37:00,2.206\n2014-02-22 03:42:00,2.478\n2014-02-22 03:47:00,2.184\n2014-02-22 03:52:00,2.49\n2014-02-22 03:57:00,2.278\n2014-02-22 04:02:00,2.512\n2014-02-22 04:07:00,3.4960000000000004\n2014-02-22 04:12:00,2.516\n2014-02-22 04:17:00,2.2840000000000003\n2014-02-22 04:22:00,2.572\n2014-02-22 04:27:00,2.3\n2014-02-22 04:32:00,2.59\n2014-02-22 04:37:00,2.21\n2014-02-22 04:42:00,2.45\n2014-02-22 04:47:00,2.006\n2014-02-22 04:52:00,2.306\n2014-02-22 04:57:00,2.044\n2014-02-22 05:02:00,2.34\n2014-02-22 05:07:00,2.1\n2014-02-22 05:12:00,2.374\n2014-02-22 05:17:00,2.126\n2014-02-22 05:22:00,3.642\n2014-02-22 05:27:00,2.09\n2014-02-22 05:32:00,2.372\n2014-02-22 05:37:00,2.134\n2014-02-22 05:42:00,2.356\n2014-02-22 05:47:00,2.026\n2014-02-22 05:52:00,2.35\n2014-02-22 05:57:00,2.056\n2014-02-22 06:02:00,2.258\n2014-02-22 06:07:00,3.3819999999999997\n2014-02-22 06:12:00,2.29\n2014-02-22 06:17:00,2.004\n2014-02-22 06:22:00,2.306\n2014-02-22 06:27:00,2.04\n2014-02-22 06:32:00,2.334\n2014-02-22 06:37:00,2.072\n2014-02-22 06:42:00,2.322\n2014-02-22 06:47:00,2.056\n2014-02-22 06:52:00,2.334\n2014-02-22 06:57:00,2.154\n2014-02-22 07:02:00,2.366\n2014-02-22 07:07:00,2.09\n2014-02-22 07:12:00,2.31\n2014-02-22 07:17:00,3.312\n2014-02-22 07:22:00,2.326\n2014-02-22 07:27:00,2.05\n2014-02-22 07:32:00,2.384\n2014-02-22 07:37:00,2.094\n2014-02-22 07:42:00,2.406\n2014-02-22 07:47:00,2.094\n2014-02-22 07:52:00,2.39\n2014-02-22 07:57:00,2.158\n2014-02-22 08:02:00,2.412\n2014-02-22 08:07:00,3.1439999999999997\n2014-02-22 08:12:00,2.7439999999999998\n2014-02-22 08:17:00,2.112\n2014-02-22 08:22:00,2.4\n2014-02-22 08:27:00,2.138\n2014-02-22 08:32:00,2.44\n2014-02-22 08:37:00,2.134\n2014-02-22 08:42:00,2.434\n2014-02-22 08:47:00,2.14\n2014-02-22 08:52:00,2.4659999999999997\n2014-02-22 08:57:00,2.278\n2014-02-22 09:02:00,2.456\n2014-02-22 09:07:00,2.366\n2014-02-22 09:12:00,3.528\n2014-02-22 09:17:00,2.488\n2014-02-22 09:22:00,2.36\n2014-02-22 09:27:00,2.046\n2014-02-22 09:32:00,2.36\n2014-02-22 09:37:00,2.05\n2014-02-22 09:42:00,2.366\n2014-02-22 09:47:00,2.06\n2014-02-22 09:52:00,2.362\n2014-02-22 09:57:00,2.066\n2014-02-22 10:02:00,2.34\n2014-02-22 10:07:00,2.072\n2014-02-22 10:12:00,2.34\n2014-02-22 10:17:00,2.5380000000000003\n2014-02-22 10:22:00,3.18\n2014-02-22 10:27:00,2.076\n2014-02-22 10:32:00,2.296\n2014-02-22 10:37:00,2.026\n2014-02-22 10:42:00,2.35\n2014-02-22 10:47:00,2.056\n2014-02-22 10:52:00,2.5340000000000003\n2014-02-22 10:57:00,2.05\n2014-02-22 11:02:00,2.338\n2014-02-22 11:07:00,2.006\n2014-02-22 11:12:00,3.5439999999999996\n2014-02-22 11:17:00,2.006\n2014-02-22 11:22:00,2.326\n2014-02-22 11:27:00,2.084\n2014-02-22 11:32:00,2.378\n2014-02-22 11:37:00,2.122\n2014-02-22 11:42:00,2.39\n2014-02-22 11:47:00,2.094\n2014-02-22 11:52:00,2.388\n2014-02-22 11:57:00,2.166\n2014-02-22 12:02:00,2.4\n2014-02-22 12:07:00,2.156\n2014-02-22 12:12:00,3.698\n2014-02-22 12:17:00,2.11\n2014-02-22 12:22:00,2.4\n2014-02-22 12:27:00,2.128\n2014-02-22 12:32:00,2.412\n2014-02-22 12:37:00,2.116\n2014-02-22 12:42:00,2.394\n2014-02-22 12:47:00,2.122\n2014-02-22 12:52:00,2.444\n2014-02-22 12:57:00,2.194\n2014-02-22 13:02:00,2.428\n2014-02-22 13:07:00,2.128\n2014-02-22 13:12:00,2.378\n2014-02-22 13:17:00,2.0780000000000003\n2014-02-22 13:22:00,3.716\n2014-02-22 13:27:00,2.096\n2014-02-22 13:32:00,2.428\n2014-02-22 13:37:00,2.102\n2014-02-22 13:42:00,2.388\n2014-02-22 13:47:00,2.074\n2014-02-22 13:52:00,2.34\n2014-02-22 13:57:00,2.1180000000000003\n2014-02-22 14:02:00,2.39\n2014-02-22 14:07:00,2.102\n2014-02-22 14:12:00,2.384\n2014-02-22 14:17:00,3.388\n2014-02-22 14:22:00,2.4\n2014-02-22 14:27:00,2.05\n2014-02-22 14:32:00,2.356\n2014-02-22 14:37:00,2.056\n2014-02-22 14:42:00,2.356\n2014-02-22 14:47:00,2.09\n2014-02-22 14:52:00,2.35\n2014-02-22 14:57:00,2.166\n2014-02-22 15:02:00,2.434\n2014-02-22 15:07:00,2.16\n2014-02-22 15:12:00,2.412\n2014-02-22 15:17:00,2.138\n2014-02-22 15:22:00,3.728\n2014-02-22 15:27:00,2.122\n2014-02-22 15:32:00,2.384\n2014-02-22 15:37:00,2.11\n2014-02-22 15:42:00,2.418\n2014-02-22 15:47:00,2.116\n2014-02-22 15:52:00,2.4\n2014-02-22 15:57:00,2.166\n2014-02-22 16:02:00,2.338\n2014-02-22 16:07:00,2.088\n2014-02-22 16:12:00,2.266\n2014-02-22 16:17:00,3.3160000000000003\n2014-02-22 16:22:00,2.444\n2014-02-22 16:27:00,1.91\n2014-02-22 16:32:00,2.208\n2014-02-22 16:37:00,1.942\n2014-02-22 16:42:00,2.2119999999999997\n2014-02-22 16:47:00,1.9380000000000002\n2014-02-22 16:52:00,2.2159999999999997\n2014-02-22 16:57:00,1.976\n2014-02-22 17:02:00,2.256\n2014-02-22 17:07:00,1.984\n2014-02-22 17:12:00,2.272\n2014-02-22 17:17:00,1.966\n2014-02-22 17:22:00,3.6239999999999997\n2014-02-22 17:27:00,2.032\n2014-02-22 17:32:00,2.266\n2014-02-22 17:37:00,1.96\n2014-02-22 17:42:00,2.25\n2014-02-22 17:47:00,1.956\n2014-02-22 17:52:00,2.272\n2014-02-22 17:57:00,2.028\n2014-02-22 18:02:00,2.276\n2014-02-22 18:07:00,2.01\n2014-02-22 18:12:00,2.2880000000000003\n2014-02-22 18:17:00,3.2239999999999998\n2014-02-22 18:22:00,2.306\n2014-02-22 18:27:00,2.056\n2014-02-22 18:32:00,2.246\n2014-02-22 18:37:00,2.004\n2014-02-22 18:42:00,2.306\n2014-02-22 18:47:00,2.044\n2014-02-22 18:52:00,2.356\n2014-02-22 18:57:00,2.134\n2014-02-22 19:02:00,2.366\n2014-02-22 19:07:00,2.116\n2014-02-22 19:12:00,2.3680000000000003\n2014-02-22 19:17:00,3.35\n2014-02-22 19:22:00,2.366\n2014-02-22 19:27:00,2.096\n2014-02-22 19:32:00,2.326\n2014-02-22 19:37:00,2.0340000000000003\n2014-02-22 19:42:00,2.316\n2014-02-22 19:47:00,2.022\n2014-02-22 19:52:00,2.356\n2014-02-22 19:57:00,2.084\n2014-02-22 20:02:00,2.3\n2014-02-22 20:07:00,2.084\n2014-02-22 20:12:00,2.35\n2014-02-22 20:17:00,2.31\n2014-02-22 20:22:00,2.25\n2014-02-22 20:27:00,1.984\n2014-02-22 20:32:00,2.2640000000000002\n2014-02-22 20:37:00,2.044\n2014-02-22 20:42:00,2.356\n2014-02-22 20:47:00,2.062\n2014-02-22 20:52:00,2.344\n2014-02-22 20:57:00,2.0780000000000003\n2014-02-22 21:02:00,2.29\n2014-02-22 21:07:00,2.04\n2014-02-22 21:12:00,2.508\n2014-02-22 21:17:00,1.966\n2014-02-22 21:22:00,2.256\n2014-02-22 21:27:00,2.006\n2014-02-22 21:32:00,2.266\n2014-02-22 21:37:00,1.984\n2014-02-22 21:42:00,2.316\n2014-02-22 21:47:00,2.05\n2014-02-22 21:52:00,2.408\n2014-02-22 21:57:00,3.5\n2014-02-22 22:02:00,2.2159999999999997\n2014-02-22 22:07:00,1.956\n2014-02-22 22:12:00,2.228\n2014-02-22 22:17:00,1.952\n2014-02-22 22:22:00,3.572\n2014-02-22 22:27:00,1.8940000000000001\n2014-02-22 22:32:00,2.2119999999999997\n2014-02-22 22:37:00,1.96\n2014-02-22 22:42:00,2.2\n2014-02-22 22:47:00,1.972\n2014-02-22 22:52:00,2.2119999999999997\n2014-02-22 22:57:00,2.028\n2014-02-22 23:02:00,2.234\n2014-02-22 23:07:00,1.9680000000000002\n2014-02-22 23:12:00,3.6\n2014-02-22 23:17:00,2.006\n2014-02-22 23:22:00,2.286\n2014-02-22 23:27:00,2.0380000000000003\n2014-02-22 23:32:00,2.3\n2014-02-22 23:37:00,1.9880000000000002\n2014-02-22 23:42:00,2.262\n2014-02-22 23:47:00,2.012\n2014-02-22 23:52:00,2.322\n2014-02-22 23:57:00,2.106\n2014-02-23 00:02:00,2.332\n2014-02-23 00:07:00,2.022\n2014-02-23 00:12:00,2.278\n2014-02-23 00:17:00,3.33\n2014-02-23 00:22:00,2.262\n2014-02-23 00:27:00,2.0380000000000003\n2014-02-23 00:32:00,2.28\n2014-02-23 00:37:00,2.026\n2014-02-23 00:42:00,2.3\n2014-02-23 00:47:00,2.05\n2014-02-23 00:52:00,2.334\n2014-02-23 00:57:00,2.126\n2014-02-23 01:02:00,2.394\n2014-02-23 01:07:00,2.144\n2014-02-23 01:12:00,3.64\n2014-02-23 01:17:00,2.05\n2014-02-23 01:22:00,2.312\n2014-02-23 01:27:00,2.052\n2014-02-23 01:32:00,2.312\n2014-02-23 01:37:00,2.06\n2014-02-23 01:42:00,2.29\n2014-02-23 01:47:00,1.956\n2014-02-23 01:52:00,2.2880000000000003\n2014-02-23 01:57:00,2.108\n2014-02-23 02:02:00,2.338\n2014-02-23 02:07:00,2.066\n2014-02-23 02:12:00,2.378\n2014-02-23 02:17:00,2.106\n2014-02-23 02:22:00,3.6660000000000004\n2014-02-23 02:27:00,2.112\n2014-02-23 02:32:00,2.406\n2014-02-23 02:37:00,2.15\n2014-02-23 02:42:00,2.378\n2014-02-23 02:47:00,2.062\n2014-02-23 02:52:00,2.3\n2014-02-23 02:57:00,2.182\n2014-02-23 03:02:00,2.4659999999999997\n2014-02-23 03:07:00,3.3160000000000003\n2014-02-23 03:12:00,2.266\n2014-02-23 03:17:00,1.9880000000000002\n2014-02-23 03:22:00,2.2\n2014-02-23 03:27:00,1.93\n2014-02-23 03:32:00,2.238\n2014-02-23 03:37:00,1.9340000000000002\n2014-02-23 03:42:00,2.2\n2014-02-23 03:47:00,1.966\n2014-02-23 03:52:00,2.224\n2014-02-23 03:57:00,2.088\n2014-02-23 04:02:00,2.3\n2014-02-23 04:07:00,2.0340000000000003\n2014-02-23 04:12:00,2.2840000000000003\n2014-02-23 04:17:00,3.27\n2014-02-23 04:22:00,2.244\n2014-02-23 04:27:00,1.9780000000000002\n2014-02-23 04:32:00,2.2119999999999997\n2014-02-23 04:37:00,2.052\n2014-02-23 04:42:00,2.2880000000000003\n2014-02-23 04:47:00,2.022\n2014-02-23 04:52:00,2.2840000000000003\n2014-02-23 04:57:00,2.05\n2014-02-23 05:02:00,2.258\n2014-02-23 05:07:00,2.01\n2014-02-23 05:12:00,3.58\n2014-02-23 05:17:00,1.994\n2014-02-23 05:22:00,2.246\n2014-02-23 05:27:00,1.996\n2014-02-23 05:32:00,2.294\n2014-02-23 05:37:00,2.0180000000000002\n2014-02-23 05:42:00,2.3040000000000003\n2014-02-23 05:47:00,2.002\n2014-02-23 05:52:00,2.296\n2014-02-23 05:57:00,2.088\n2014-02-23 06:02:00,2.344\n2014-02-23 06:07:00,2.174\n2014-02-23 06:12:00,3.55\n2014-02-23 06:17:00,2.0\n2014-02-23 06:22:00,2.234\n2014-02-23 06:27:00,1.994\n2014-02-23 06:32:00,2.2880000000000003\n2014-02-23 06:37:00,2.024\n2014-02-23 06:42:00,2.274\n2014-02-23 06:47:00,2.0380000000000003\n2014-02-23 06:52:00,2.2880000000000003\n2014-02-23 06:57:00,2.122\n2014-02-23 07:02:00,2.3\n2014-02-23 07:07:00,2.094\n2014-02-23 07:12:00,2.338\n2014-02-23 07:17:00,3.384\n2014-02-23 07:22:00,2.366\n2014-02-23 07:27:00,2.084\n2014-02-23 07:32:00,2.316\n2014-02-23 07:37:00,2.028\n2014-02-23 07:42:00,2.388\n2014-02-23 07:47:00,1.9340000000000002\n2014-02-23 07:52:00,2.228\n2014-02-23 07:57:00,1.994\n2014-02-23 08:02:00,2.194\n2014-02-23 08:07:00,1.9340000000000002\n2014-02-23 08:12:00,2.156\n2014-02-23 08:17:00,3.1660000000000004\n2014-02-23 08:22:00,2.162\n2014-02-23 08:27:00,1.916\n2014-02-23 08:32:00,2.2119999999999997\n2014-02-23 08:37:00,1.944\n2014-02-23 08:42:00,2.246\n2014-02-23 08:47:00,1.976\n2014-02-23 08:52:00,2.266\n2014-02-23 08:57:00,2.0\n2014-02-23 09:02:00,2.184\n2014-02-23 09:07:00,1.9240000000000002\n2014-02-23 09:12:00,2.176\n2014-02-23 09:17:00,3.582\n2014-02-23 09:22:00,2.2840000000000003\n2014-02-23 09:27:00,1.906\n2014-02-23 09:32:00,2.184\n2014-02-23 09:37:00,1.9\n2014-02-23 09:42:00,2.178\n2014-02-23 09:47:00,1.95\n2014-02-23 09:52:00,2.2159999999999997\n2014-02-23 09:57:00,2.0\n2014-02-23 10:02:00,2.194\n2014-02-23 10:07:00,1.966\n2014-02-23 10:12:00,2.2\n2014-02-23 10:17:00,3.272\n2014-02-23 10:22:00,2.234\n2014-02-23 10:27:00,2.0380000000000003\n2014-02-23 10:32:00,2.296\n2014-02-23 10:37:00,2.016\n2014-02-23 10:42:00,2.228\n2014-02-23 10:47:00,2.0\n2014-02-23 10:52:00,2.316\n2014-02-23 10:57:00,2.072\n2014-02-23 11:02:00,2.2840000000000003\n2014-02-23 11:07:00,2.04\n2014-02-23 11:12:00,2.326\n2014-02-23 11:17:00,2.088\n2014-02-23 11:22:00,3.65\n2014-02-23 11:27:00,1.972\n2014-02-23 11:32:00,2.2159999999999997\n2014-02-23 11:37:00,1.966\n2014-02-23 11:42:00,2.2159999999999997\n2014-02-23 11:47:00,1.9680000000000002\n2014-02-23 11:52:00,2.246\n2014-02-23 11:57:00,2.05\n2014-02-23 12:02:00,2.2840000000000003\n2014-02-23 12:07:00,2.002\n2014-02-23 12:12:00,3.5660000000000003\n2014-02-23 12:17:00,1.962\n2014-02-23 12:22:00,2.258\n2014-02-23 12:27:00,2.0180000000000002\n2014-02-23 12:32:00,1.92\n2014-02-23 12:37:00,1.9380000000000002\n2014-02-23 12:42:00,2.184\n2014-02-23 12:47:00,1.838\n2014-02-23 12:52:00,2.242\n2014-02-23 12:57:00,1.9880000000000002\n2014-02-23 13:02:00,2.2\n2014-02-23 13:07:00,1.984\n2014-02-23 13:12:00,2.208\n2014-02-23 13:17:00,1.854\n2014-02-23 13:22:00,3.56\n2014-02-23 13:27:00,1.984\n2014-02-23 13:32:00,2.278\n2014-02-23 13:37:00,1.952\n2014-02-23 13:42:00,2.384\n2014-02-23 13:47:00,1.9780000000000002\n2014-02-23 13:52:00,2.164\n2014-02-23 13:57:00,2.184\n2014-02-23 14:02:00,2.294\n2014-02-23 14:07:00,2.026\n2014-02-23 14:12:00,2.258\n2014-02-23 14:17:00,3.3080000000000003\n2014-02-23 14:22:00,2.25\n2014-02-23 14:27:00,1.8459999999999999\n2014-02-23 14:32:00,2.068\n2014-02-23 14:37:00,2.144\n2014-02-23 14:42:00,2.27\n2014-02-23 14:47:00,1.944\n2014-02-23 14:52:00,2.234\n2014-02-23 14:57:00,2.05\n2014-02-23 15:02:00,2.266\n2014-02-23 15:07:00,1.9\n2014-02-23 15:12:00,2.366\n2014-02-23 15:17:00,3.3\n2014-02-23 15:22:00,2.234\n2014-02-23 15:27:00,1.984\n2014-02-23 15:32:00,2.244\n2014-02-23 15:37:00,1.962\n2014-02-23 15:42:00,2.234\n2014-02-23 15:47:00,1.9340000000000002\n2014-02-23 15:52:00,2.19\n2014-02-23 15:57:00,2.088\n2014-02-23 16:02:00,2.306\n2014-02-23 16:07:00,2.0340000000000003\n2014-02-23 16:12:00,2.2119999999999997\n2014-02-23 16:17:00,3.2880000000000003\n2014-02-23 16:22:00,2.184\n2014-02-23 16:27:00,1.9280000000000002\n2014-02-23 16:32:00,2.2\n2014-02-23 16:37:00,1.946\n2014-02-23 16:42:00,2.238\n2014-02-23 16:47:00,1.93\n2014-02-23 16:52:00,2.3080000000000003\n2014-02-23 16:57:00,1.966\n2014-02-23 17:02:00,2.146\n2014-02-23 17:07:00,1.9140000000000001\n2014-02-23 17:12:00,3.486\n2014-02-23 17:17:00,1.8780000000000001\n2014-02-23 17:22:00,2.15\n2014-02-23 17:27:00,1.9\n2014-02-23 17:32:00,2.166\n2014-02-23 17:37:00,1.912\n2014-02-23 17:42:00,2.1919999999999997\n2014-02-23 17:47:00,1.8619999999999999\n2014-02-23 17:52:00,2.3080000000000003\n2014-02-23 17:57:00,2.0\n2014-02-23 18:02:00,2.238\n2014-02-23 18:07:00,3.304\n2014-02-23 18:12:00,2.184\n2014-02-23 18:17:00,2.094\n2014-02-23 18:22:00,2.194\n2014-02-23 18:27:00,1.9380000000000002\n2014-02-23 18:32:00,2.15\n2014-02-23 18:37:00,2.062\n2014-02-23 18:42:00,2.2840000000000003\n2014-02-23 18:47:00,2.0340000000000003\n2014-02-23 18:52:00,2.3040000000000003\n2014-02-23 18:57:00,2.0780000000000003\n2014-02-23 19:02:00,2.2159999999999997\n2014-02-23 19:07:00,2.0\n2014-02-23 19:12:00,2.234\n2014-02-23 19:17:00,3.2560000000000002\n2014-02-23 19:22:00,2.2640000000000002\n2014-02-23 19:27:00,1.984\n2014-02-23 19:32:00,2.224\n2014-02-23 19:37:00,1.994\n2014-02-23 19:42:00,2.296\n2014-02-23 19:47:00,1.954\n2014-02-23 19:52:00,2.234\n2014-02-23 19:57:00,2.036\n2014-02-23 20:02:00,2.246\n2014-02-23 20:07:00,2.022\n2014-02-23 20:12:00,2.28\n2014-02-23 20:17:00,2.084\n2014-02-23 20:22:00,3.6660000000000004\n2014-02-23 20:27:00,2.084\n2014-02-23 20:32:00,2.366\n2014-02-23 20:37:00,2.134\n2014-02-23 20:42:00,2.472\n2014-02-23 20:47:00,2.028\n2014-02-23 20:52:00,2.166\n2014-02-23 20:57:00,1.92\n2014-02-23 21:02:00,2.154\n2014-02-23 21:07:00,1.972\n2014-02-23 21:12:00,3.5\n2014-02-23 21:17:00,1.966\n2014-02-23 21:22:00,2.206\n2014-02-23 21:27:00,1.956\n2014-02-23 21:32:00,2.204\n2014-02-23 21:37:00,1.996\n2014-02-23 21:42:00,2.242\n2014-02-23 21:47:00,1.96\n2014-02-23 21:52:00,2.228\n2014-02-23 21:57:00,3.4960000000000004\n2014-02-23 22:02:00,2.176\n2014-02-23 22:07:00,1.94\n2014-02-23 22:12:00,3.552\n2014-02-23 22:17:00,1.94\n2014-02-23 22:22:00,2.248\n2014-02-23 22:27:00,1.996\n2014-02-23 22:32:00,2.276\n2014-02-23 22:37:00,2.046\n2014-02-23 22:42:00,2.262\n2014-02-23 22:47:00,2.022\n2014-02-23 22:52:00,2.254\n2014-02-23 22:57:00,2.0540000000000003\n2014-02-23 23:02:00,2.234\n2014-02-23 23:07:00,1.962\n2014-02-23 23:12:00,3.53\n2014-02-23 23:17:00,1.946\n2014-02-23 23:22:00,2.222\n2014-02-23 23:27:00,1.984\n2014-02-23 23:32:00,2.2680000000000002\n2014-02-23 23:37:00,1.9780000000000002\n2014-02-23 23:42:00,2.3\n2014-02-23 23:47:00,2.084\n2014-02-23 23:52:00,2.356\n2014-02-23 23:57:00,2.1319999999999997\n2014-02-24 00:02:00,2.2840000000000003\n2014-02-24 00:07:00,2.084\n2014-02-24 00:12:00,3.5660000000000003\n2014-02-24 00:17:00,2.066\n2014-02-24 00:22:00,2.266\n2014-02-24 00:27:00,2.128\n2014-02-24 00:32:00,2.444\n2014-02-24 00:37:00,2.0780000000000003\n2014-02-24 00:42:00,2.46\n2014-02-24 00:47:00,1.966\n2014-02-24 00:52:00,2.238\n2014-02-24 00:57:00,2.002\n2014-02-24 01:02:00,2.222\n2014-02-24 01:07:00,1.972\n2014-02-24 01:12:00,3.478\n2014-02-24 01:17:00,1.95\n2014-02-24 01:22:00,2.2\n2014-02-24 01:27:00,2.012\n2014-02-24 01:32:00,2.204\n2014-02-24 01:37:00,1.966\n2014-02-24 01:42:00,2.204\n2014-02-24 01:47:00,1.9780000000000002\n2014-02-24 01:52:00,2.238\n2014-02-24 01:57:00,1.972\n2014-02-24 02:02:00,2.21\n2014-02-24 02:07:00,2.022\n2014-02-24 02:12:00,3.536\n2014-02-24 02:17:00,1.966\n2014-02-24 02:22:00,2.23\n2014-02-24 02:27:00,2.0340000000000003\n2014-02-24 02:32:00,2.3040000000000003\n2014-02-24 02:37:00,2.04\n2014-02-24 02:42:00,2.326\n2014-02-24 02:47:00,2.05\n2014-02-24 02:52:00,2.318\n2014-02-24 02:57:00,2.122\n2014-02-24 03:02:00,2.374\n2014-02-24 03:07:00,2.122\n2014-02-24 03:12:00,2.362\n2014-02-24 03:17:00,3.616\n2014-02-24 03:22:00,2.346\n2014-02-24 03:27:00,2.1\n2014-02-24 03:32:00,2.362\n2014-02-24 03:37:00,2.126\n2014-02-24 03:42:00,2.35\n2014-02-24 03:47:00,2.084\n2014-02-24 03:52:00,2.334\n2014-02-24 03:57:00,2.136\n2014-02-24 04:02:00,2.366\n2014-02-24 04:07:00,2.1\n2014-02-24 04:12:00,2.362\n2014-02-24 04:17:00,3.3160000000000003\n2014-02-24 04:22:00,2.434\n2014-02-24 04:27:00,2.016\n2014-02-24 04:32:00,2.234\n2014-02-24 04:37:00,1.9880000000000002\n2014-02-24 04:42:00,2.31\n2014-02-24 04:47:00,2.046\n2014-02-24 04:52:00,2.2880000000000003\n2014-02-24 04:57:00,2.106\n2014-02-24 05:02:00,2.338\n2014-02-24 05:07:00,2.094\n2014-02-24 05:12:00,5.3660000000000005\n2014-02-24 05:17:00,3.884\n2014-02-24 05:22:00,3.0\n2014-02-24 05:27:00,2.5839999999999996\n2014-02-24 05:32:00,2.8280000000000003\n2014-02-24 05:37:00,2.346\n2014-02-24 05:42:00,2.6660000000000004\n2014-02-24 05:47:00,2.166\n2014-02-24 05:52:00,2.472\n2014-02-24 05:57:00,2.246\n2014-02-24 06:02:00,2.526\n2014-02-24 06:07:00,2.134\n2014-02-24 06:12:00,2.45\n2014-02-24 06:17:00,3.424\n2014-02-24 06:22:00,3.116\n2014-02-24 06:27:00,6.108\n2014-02-24 06:32:00,3.718\n2014-02-24 06:37:00,3.2\n2014-02-24 06:42:00,3.486\n2014-02-24 06:47:00,3.114\n2014-02-24 06:52:00,3.3339999999999996\n2014-02-24 06:57:00,2.99\n2014-02-24 07:02:00,3.3339999999999996\n2014-02-24 07:07:00,4.364\n2014-02-24 07:12:00,2.488\n2014-02-24 07:17:00,3.4\n2014-02-24 07:22:00,2.44\n2014-02-24 07:27:00,2.112\n2014-02-24 07:32:00,2.484\n2014-02-24 07:37:00,2.122\n2014-02-24 07:42:00,2.4619999999999997\n2014-02-24 07:47:00,2.188\n2014-02-24 07:52:00,2.728\n2014-02-24 07:57:00,3.0839999999999996\n2014-02-24 08:02:00,4.934\n2014-02-24 08:07:00,2.0380000000000003\n2014-02-24 08:12:00,3.6660000000000004\n2014-02-24 08:17:00,2.0180000000000002\n2014-02-24 08:22:00,2.366\n2014-02-24 08:27:00,2.074\n2014-02-24 08:32:00,2.434\n2014-02-24 08:37:00,2.09\n2014-02-24 08:42:00,2.41\n2014-02-24 08:47:00,2.072\n2014-02-24 08:52:00,2.372\n2014-02-24 08:57:00,2.136\n2014-02-24 09:02:00,2.316\n2014-02-24 09:07:00,2.0340000000000003\n2014-02-24 09:12:00,3.3\n2014-02-24 09:17:00,2.35\n2014-02-24 09:22:00,2.158\n2014-02-24 09:27:00,1.8880000000000001\n2014-02-24 09:32:00,2.234\n2014-02-24 09:37:00,1.972\n2014-02-24 09:42:00,2.294\n2014-02-24 09:47:00,2.046\n2014-02-24 09:52:00,2.254\n2014-02-24 09:57:00,2.066\n2014-02-24 10:02:00,2.224\n2014-02-24 10:07:00,2.044\n2014-02-24 10:12:00,3.5460000000000003\n2014-02-24 10:17:00,2.1180000000000003\n2014-02-24 10:22:00,2.2\n2014-02-24 10:27:00,2.022\n2014-02-24 10:32:00,2.278\n2014-02-24 10:37:00,1.954\n2014-02-24 10:42:00,2.166\n2014-02-24 10:47:00,1.9080000000000001\n2014-02-24 10:52:00,2.16\n2014-02-24 10:57:00,1.986\n2014-02-24 11:02:00,2.208\n2014-02-24 11:07:00,1.966\n2014-02-24 11:12:00,2.2119999999999997\n2014-02-24 11:17:00,3.2680000000000002\n2014-02-24 11:22:00,2.238\n2014-02-24 11:27:00,1.99\n2014-02-24 11:32:00,2.276\n2014-02-24 11:37:00,2.024\n2014-02-24 11:42:00,2.282\n2014-02-24 11:47:00,1.9780000000000002\n2014-02-24 11:52:00,2.2119999999999997\n2014-02-24 11:57:00,2.012\n2014-02-24 12:02:00,3.182\n2014-02-24 12:07:00,1.8940000000000001\n2014-02-24 12:12:00,2.112\n2014-02-24 12:17:00,3.2060000000000004\n2014-02-24 12:22:00,2.136\n2014-02-24 12:27:00,1.9340000000000002\n2014-02-24 12:32:00,2.1959999999999997\n2014-02-24 12:37:00,1.99\n2014-02-24 12:42:00,2.31\n2014-02-24 12:47:00,2.022\n2014-02-24 12:52:00,2.222\n2014-02-24 12:57:00,2.016\n2014-02-24 13:02:00,2.19\n2014-02-24 13:07:00,2.01\n2014-02-24 13:12:00,2.2880000000000003\n2014-02-24 13:17:00,3.266\n2014-02-24 13:22:00,2.222\n2014-02-24 13:27:00,1.95\n2014-02-24 13:32:00,2.228\n2014-02-24 13:37:00,1.9780000000000002\n2014-02-24 13:42:00,2.1959999999999997\n2014-02-24 13:47:00,1.966\n2014-02-24 13:52:00,2.204\n2014-02-24 13:57:00,2.05\n2014-02-24 14:02:00,2.28\n2014-02-24 14:07:00,2.0380000000000003\n2014-02-24 14:12:00,2.246\n2014-02-24 14:17:00,3.34\n2014-02-24 14:22:00,2.26\n2014-02-24 14:27:00,2.012\n2014-02-24 14:32:00,2.262\n2014-02-24 14:37:00,2.022\n2014-02-24 14:42:00,2.266\n2014-02-24 14:47:00,2.0180000000000002\n2014-02-24 14:52:00,5.016\n2014-02-24 14:57:00,4.518\n2014-02-24 15:02:00,2.938\n2014-02-24 15:07:00,2.542\n2014-02-24 15:12:00,3.616\n2014-02-24 15:17:00,2.926\n2014-02-24 15:22:00,2.674\n2014-02-24 15:27:00,2.244\n2014-02-24 15:32:00,2.588\n2014-02-24 15:37:00,2.188\n2014-02-24 15:42:00,2.522\n2014-02-24 15:47:00,2.146\n2014-02-24 15:52:00,2.542\n2014-02-24 15:57:00,2.226\n2014-02-24 16:02:00,2.54\n2014-02-24 16:07:00,2.202\n2014-02-24 16:12:00,2.5340000000000003\n2014-02-24 16:17:00,3.536\n2014-02-24 16:22:00,2.65\n2014-02-24 16:27:00,2.31\n2014-02-24 16:32:00,2.61\n2014-02-24 16:37:00,2.226\n2014-02-24 16:42:00,2.4819999999999998\n2014-02-24 16:47:00,2.138\n2014-02-24 16:52:00,2.434\n2014-02-24 16:57:00,2.166\n2014-02-24 17:02:00,2.44\n2014-02-24 17:07:00,2.128\n2014-02-24 17:12:00,2.384\n2014-02-24 17:17:00,3.412\n2014-02-24 17:22:00,2.384\n2014-02-24 17:27:00,2.062\n2014-02-24 17:32:00,2.322\n2014-02-24 17:37:00,2.012\n2014-02-24 17:42:00,2.2840000000000003\n2014-02-24 17:47:00,1.974\n2014-02-24 17:52:00,2.21\n2014-02-24 17:57:00,2.006\n2014-02-24 18:02:00,2.238\n2014-02-24 18:07:00,1.99\n2014-02-24 18:12:00,3.6\n2014-02-24 18:17:00,42.896\n2014-02-24 18:22:00,57.976000000000006\n2014-02-24 18:27:00,52.316\n2014-02-24 18:32:00,38.57\n2014-02-24 18:37:00,65.18\n2014-02-24 18:42:00,53.65\n2014-02-24 18:47:00,21.678\n2014-02-24 18:52:00,6.65\n2014-02-24 18:57:00,6.9620000000000015\n2014-02-24 19:02:00,3.926\n2014-02-24 19:07:00,4.3660000000000005\n2014-02-24 19:12:00,3.8139999999999996\n2014-02-24 19:17:00,6.1320000000000014\n2014-02-24 19:22:00,3.176\n2014-02-24 19:27:00,39.684\n2014-02-24 19:32:00,60.812\n2014-02-24 19:37:00,53.176\n2014-02-24 19:42:00,17.308\n2014-02-24 19:47:00,2.806\n2014-02-24 19:52:00,3.2739999999999996\n2014-02-24 19:57:00,4.008\n2014-02-24 20:02:00,3.2260000000000004\n2014-02-24 20:07:00,4.646\n2014-02-24 20:12:00,2.972\n2014-02-24 20:17:00,11.07\n2014-02-24 20:22:00,70.866\n2014-02-24 20:27:00,55.216\n2014-02-24 20:32:00,37.156\n2014-02-24 20:37:00,3.884\n2014-02-24 20:42:00,5.278\n2014-02-24 20:47:00,3.9\n2014-02-24 20:52:00,4.1\n2014-02-24 20:57:00,5.182\n2014-02-24 21:02:00,3.516\n2014-02-24 21:07:00,3.5060000000000002\n2014-02-24 21:12:00,5.034\n2014-02-24 21:17:00,3.3819999999999997\n2014-02-24 21:22:00,11.67\n2014-02-24 21:27:00,3.35\n2014-02-24 21:32:00,3.582\n2014-02-24 21:37:00,2.9339999999999997\n2014-02-24 21:42:00,3.266\n2014-02-24 21:47:00,2.984\n2014-02-24 21:52:00,3.284\n2014-02-24 21:57:00,4.6419999999999995\n2014-02-24 22:02:00,3.0060000000000002\n2014-02-24 22:07:00,3.5239999999999996\n2014-02-24 22:12:00,4.202\n2014-02-24 22:17:00,3.136\n2014-02-24 22:22:00,3.842\n2014-02-24 22:27:00,5.16\n2014-02-24 22:32:00,2.274\n2014-02-24 22:37:00,1.8659999999999999\n2014-02-24 22:42:00,2.144\n2014-02-24 22:47:00,1.8780000000000001\n2014-02-24 22:52:00,2.164\n2014-02-24 22:57:00,1.916\n2014-02-24 23:02:00,2.2159999999999997\n2014-02-24 23:07:00,39.134\n2014-02-24 23:12:00,59.983999999999995\n2014-02-24 23:17:00,52.19\n2014-02-24 23:22:00,14.19\n2014-02-24 23:27:00,2.512\n2014-02-24 23:32:00,3.938\n2014-02-24 23:37:00,2.8\n2014-02-24 23:42:00,4.466\n2014-02-24 23:47:00,2.63\n2014-02-24 23:52:00,2.556\n2014-02-24 23:57:00,2.762\n2014-02-25 00:02:00,2.806\n2014-02-25 00:07:00,3.5580000000000003\n2014-02-25 00:12:00,2.7939999999999996\n2014-02-25 00:17:00,2.344\n2014-02-25 00:22:00,3.7119999999999997\n2014-02-25 00:27:00,66.52199999999999\n2014-02-25 00:32:00,53.16\n2014-02-25 00:37:00,37.916\n2014-02-25 00:42:00,25.234\n2014-02-25 00:47:00,65.58800000000001\n2014-02-25 00:52:00,53.49\n2014-02-25 00:57:00,19.35\n2014-02-25 01:02:00,4.584\n2014-02-25 01:07:00,2.35\n2014-02-25 01:12:00,4.15\n2014-02-25 01:17:00,2.568\n2014-02-25 01:22:00,2.822\n2014-02-25 01:27:00,5.358\n2014-02-25 01:32:00,57.931999999999995\n2014-02-25 01:37:00,54.013999999999996\n2014-02-25 01:42:00,49.032\n2014-02-25 01:47:00,4.734\n2014-02-25 01:52:00,2.6060000000000003\n2014-02-25 01:57:00,2.404\n2014-02-25 02:02:00,2.95\n2014-02-25 02:07:00,2.6060000000000003\n2014-02-25 02:12:00,6.872000000000001\n2014-02-25 02:17:00,2.55\n2014-02-25 02:22:00,3.742\n2014-02-25 02:27:00,2.966\n2014-02-25 02:32:00,2.924\n2014-02-25 02:37:00,41.288000000000004\n2014-02-25 02:42:00,63.56\n2014-02-25 02:47:00,55.118\n2014-02-25 02:52:00,14.95\n2014-02-25 02:57:00,3.326\n2014-02-25 03:02:00,8.72\n2014-02-25 03:07:00,5.864\n2014-02-25 03:12:00,4.534\n2014-02-25 03:17:00,5.0360000000000005\n2014-02-25 03:22:00,5.6\n2014-02-25 03:27:00,5.416\n2014-02-25 03:32:00,3.89\n2014-02-25 03:37:00,3.532\n2014-02-25 03:42:00,4.316\n2014-02-25 03:47:00,3.668\n2014-02-25 03:52:00,4.216\n2014-02-25 03:57:00,4.81\n2014-02-25 04:02:00,3.1639999999999997\n2014-02-25 04:07:00,4.1419999999999995\n2014-02-25 04:12:00,2.33\n2014-02-25 04:17:00,3.2880000000000003\n2014-02-25 04:22:00,2.266\n2014-02-25 04:27:00,1.9240000000000002\n2014-02-25 04:32:00,2.26\n2014-02-25 04:37:00,1.972\n2014-02-25 04:42:00,2.4659999999999997\n2014-02-25 04:47:00,2.01\n2014-02-25 04:52:00,2.306\n2014-02-25 04:57:00,2.1\n2014-02-25 05:02:00,2.35\n2014-02-25 05:07:00,2.01\n2014-02-25 05:12:00,2.266\n2014-02-25 05:17:00,3.216\n2014-02-25 05:22:00,2.162\n2014-02-25 05:27:00,1.9180000000000001\n2014-02-25 05:32:00,2.1959999999999997\n2014-02-25 05:37:00,1.954\n2014-02-25 05:42:00,2.166\n2014-02-25 05:47:00,1.9880000000000002\n2014-02-25 05:52:00,2.204\n2014-02-25 05:57:00,2.016\n2014-02-25 06:02:00,2.188\n2014-02-25 06:07:00,1.9340000000000002\n2014-02-25 06:12:00,2.2\n2014-02-25 06:17:00,1.912\n2014-02-25 06:22:00,6.596\n2014-02-25 06:27:00,2.55\n2014-02-25 06:32:00,3.2260000000000004\n2014-02-25 06:37:00,2.51\n2014-02-25 06:42:00,2.766\n2014-02-25 06:47:00,2.334\n2014-02-25 06:52:00,2.8080000000000003\n2014-02-25 06:57:00,4.808\n2014-02-25 07:02:00,5.438\n2014-02-25 07:07:00,3.4219999999999997\n2014-02-25 07:12:00,3.262\n2014-02-25 07:17:00,2.416\n2014-02-25 07:22:00,2.68\n2014-02-25 07:27:00,2.262\n2014-02-25 07:32:00,2.61\n2014-02-25 07:37:00,2.108\n2014-02-25 07:42:00,2.4659999999999997\n2014-02-25 07:47:00,2.102\n2014-02-25 07:52:00,2.414\n2014-02-25 07:57:00,2.12\n2014-02-25 08:02:00,2.434\n2014-02-25 08:07:00,2.116\n2014-02-25 08:12:00,2.508\n2014-02-25 08:17:00,2.2159999999999997\n2014-02-25 08:22:00,3.762\n2014-02-25 08:27:00,2.134\n2014-02-25 08:32:00,2.378\n2014-02-25 08:37:00,2.094\n2014-02-25 08:42:00,2.44\n2014-02-25 08:47:00,2.134\n2014-02-25 08:52:00,2.362\n2014-02-25 08:57:00,2.072\n2014-02-25 09:02:00,2.35\n2014-02-25 09:07:00,2.0\n2014-02-25 09:12:00,2.258\n2014-02-25 09:17:00,2.344\n2014-02-25 09:22:00,3.484\n2014-02-25 09:27:00,2.072\n2014-02-25 09:32:00,2.184\n2014-02-25 09:37:00,1.8519999999999999\n2014-02-25 09:42:00,2.2159999999999997\n2014-02-25 09:47:00,5.478\n2014-02-25 09:52:00,3.054\n2014-02-25 09:57:00,2.65\n2014-02-25 10:02:00,2.866\n2014-02-25 10:07:00,2.384\n2014-02-25 10:12:00,3.9339999999999997\n2014-02-25 10:17:00,2.184\n2014-02-25 10:22:00,2.456\n2014-02-25 10:27:00,2.0340000000000003\n2014-02-25 10:32:00,2.366\n2014-02-25 10:37:00,1.954\n2014-02-25 10:42:00,2.34\n2014-02-25 10:47:00,2.0\n2014-02-25 10:52:00,2.356\n2014-02-25 10:57:00,2.096\n2014-02-25 11:02:00,2.378\n2014-02-25 11:07:00,2.022\n2014-02-25 11:12:00,3.688\n2014-02-25 11:17:00,2.106\n2014-02-25 11:22:00,2.3280000000000003\n2014-02-25 11:27:00,2.016\n2014-02-25 11:32:00,2.266\n2014-02-25 11:37:00,1.9780000000000002\n2014-02-25 11:42:00,2.226\n2014-02-25 11:47:00,2.006\n2014-02-25 11:52:00,2.294\n2014-02-25 11:57:00,1.954\n2014-02-25 12:02:00,2.166\n2014-02-25 12:07:00,1.9340000000000002\n2014-02-25 12:12:00,2.21\n2014-02-25 12:17:00,3.266\n2014-02-25 12:22:00,2.178\n2014-02-25 12:27:00,1.94\n2014-02-25 12:32:00,2.16\n2014-02-25 12:37:00,1.922\n2014-02-25 12:42:00,2.178\n2014-02-25 12:47:00,1.93\n2014-02-25 12:52:00,2.164\n2014-02-25 12:57:00,1.994\n2014-02-25 13:02:00,2.246\n2014-02-25 13:07:00,1.854\n2014-02-25 13:12:00,3.438\n2014-02-25 13:17:00,2.084\n2014-02-25 13:22:00,2.198\n2014-02-25 13:27:00,1.834\n2014-02-25 13:32:00,2.096\n2014-02-25 13:37:00,1.874\n2014-02-25 13:42:00,2.148\n2014-02-25 13:47:00,1.95\n2014-02-25 13:52:00,2.184\n2014-02-25 13:57:00,2.004\n2014-02-25 14:02:00,2.222\n2014-02-25 14:07:00,1.9780000000000002\n2014-02-25 14:12:00,3.592\n2014-02-25 14:17:00,1.984\n2014-02-25 14:22:00,5.666\n2014-02-25 14:27:00,2.568\n2014-02-25 14:32:00,2.9339999999999997\n2014-02-25 14:37:00,2.542\n2014-02-25 14:42:00,2.7539999999999996\n2014-02-25 14:47:00,2.346\n2014-02-25 14:52:00,2.61\n2014-02-25 14:57:00,2.2840000000000003\n2014-02-25 15:02:00,2.5340000000000003\n2014-02-25 15:07:00,2.094\n2014-02-25 15:12:00,2.44\n2014-02-25 15:17:00,3.42\n2014-02-25 15:22:00,2.456\n2014-02-25 15:27:00,2.184\n2014-02-25 15:32:00,2.5839999999999996\n2014-02-25 15:37:00,2.134\n2014-02-25 15:42:00,2.494\n2014-02-25 15:47:00,2.156\n2014-02-25 15:52:00,2.438\n2014-02-25 15:57:00,2.1519999999999997\n2014-02-25 16:02:00,2.36\n2014-02-25 16:07:00,1.99\n2014-02-25 16:12:00,2.278\n2014-02-25 16:17:00,2.04\n2014-02-25 16:22:00,3.614\n2014-02-25 16:27:00,2.072\n2014-02-25 16:32:00,2.378\n2014-02-25 16:37:00,2.06\n2014-02-25 16:42:00,2.238\n2014-02-25 16:47:00,2.1\n2014-02-25 16:52:00,2.1180000000000003\n2014-02-25 16:57:00,1.95\n2014-02-25 17:02:00,2.062\n2014-02-25 17:07:00,3.154\n2014-02-25 17:12:00,2.066\n2014-02-25 17:17:00,1.824\n2014-02-25 17:22:00,2.07\n2014-02-25 17:27:00,1.8459999999999999\n2014-02-25 17:32:00,2.092\n2014-02-25 17:37:00,1.838\n2014-02-25 17:42:00,2.1\n2014-02-25 17:47:00,1.95\n2014-02-25 17:52:00,2.15\n2014-02-25 17:57:00,2.0340000000000003\n2014-02-25 18:02:00,2.204\n2014-02-25 18:07:00,1.896\n2014-02-25 18:12:00,2.146\n2014-02-25 18:17:00,3.196\n2014-02-25 18:22:00,2.176\n2014-02-25 18:27:00,1.9080000000000001\n2014-02-25 18:32:00,2.188\n2014-02-25 18:37:00,7.58\n2014-02-25 18:42:00,2.89\n2014-02-25 18:47:00,2.484\n2014-02-25 18:52:00,2.7239999999999998\n2014-02-25 18:57:00,2.338\n2014-02-25 19:02:00,2.572\n2014-02-25 19:07:00,2.178\n2014-02-25 19:12:00,3.79\n2014-02-25 19:17:00,2.146\n2014-02-25 19:22:00,2.3680000000000003\n2014-02-25 19:27:00,1.962\n2014-02-25 19:32:00,2.318\n2014-02-25 19:37:00,2.0\n2014-02-25 19:42:00,2.334\n2014-02-25 19:47:00,2.06\n2014-02-25 19:52:00,2.334\n2014-02-25 19:57:00,2.076\n2014-02-25 20:02:00,2.3\n2014-02-25 20:07:00,2.056\n2014-02-25 20:12:00,3.574\n2014-02-25 20:17:00,1.972\n2014-02-25 20:22:00,2.174\n2014-02-25 20:27:00,1.95\n2014-02-25 20:32:00,2.178\n2014-02-25 20:37:00,1.95\n2014-02-25 20:42:00,2.2159999999999997\n2014-02-25 20:47:00,2.044\n2014-02-25 20:52:00,2.088\n2014-02-25 20:57:00,1.922\n2014-02-25 21:02:00,2.15\n2014-02-25 21:07:00,1.8459999999999999\n2014-02-25 21:12:00,2.092\n2014-02-25 21:17:00,1.868\n2014-02-25 21:22:00,3.346\n2014-02-25 21:27:00,1.8780000000000001\n2014-02-25 21:32:00,2.154\n2014-02-25 21:37:00,2.006\n2014-02-25 21:42:00,2.2640000000000002\n2014-02-25 21:47:00,1.9780000000000002\n2014-02-25 21:52:00,2.184\n2014-02-25 21:57:00,3.5\n2014-02-25 22:02:00,2.222\n2014-02-25 22:07:00,1.946\n2014-02-25 22:12:00,3.514\n2014-02-25 22:17:00,1.99\n2014-02-25 22:22:00,2.226\n2014-02-25 22:27:00,1.94\n2014-02-25 22:32:00,2.23\n2014-02-25 22:37:00,1.9780000000000002\n2014-02-25 22:42:00,2.25\n2014-02-25 22:47:00,2.0\n2014-02-25 22:52:00,2.218\n2014-02-25 22:57:00,2.5839999999999996\n2014-02-25 23:02:00,2.1719999999999997\n2014-02-25 23:07:00,1.966\n2014-02-25 23:12:00,2.366\n2014-02-25 23:17:00,1.944\n2014-02-25 23:22:00,3.458\n2014-02-25 23:27:00,1.942\n2014-02-25 23:32:00,24.912\n2014-02-25 23:37:00,64.252\n2014-02-25 23:42:00,52.263999999999996\n2014-02-25 23:47:00,19.456\n2014-02-25 23:52:00,2.878\n2014-02-25 23:57:00,6.037999999999999\n2014-02-26 00:02:00,3.1239999999999997\n2014-02-26 00:07:00,4.34\n2014-02-26 00:12:00,2.984\n2014-02-26 00:17:00,4.24\n2014-02-26 00:22:00,2.562\n2014-02-26 00:27:00,2.61\n2014-02-26 00:32:00,3.054\n2014-02-26 00:37:00,2.762\n2014-02-26 00:42:00,4.168\n2014-02-26 00:47:00,1.84\n2014-02-26 00:52:00,2.11\n2014-02-26 00:57:00,1.984\n2014-02-26 01:02:00,2.1719999999999997\n2014-02-26 01:07:00,1.95\n2014-02-26 01:12:00,2.188\n2014-02-26 01:17:00,1.9340000000000002\n2014-02-26 01:22:00,3.542\n2014-02-26 01:27:00,9.542\n2014-02-26 01:32:00,70.018\n2014-02-26 01:37:00,52.104\n2014-02-26 01:42:00,29.064\n2014-02-26 01:47:00,2.6180000000000003\n2014-02-26 01:52:00,3.9160000000000004\n2014-02-26 01:57:00,2.866\n2014-02-26 02:02:00,4.666\n2014-02-26 02:07:00,3.984\n2014-02-26 02:12:00,2.52\n2014-02-26 02:17:00,2.912\n2014-02-26 02:22:00,2.9160000000000004\n2014-02-26 02:27:00,2.772\n2014-02-26 02:32:00,5.03\n2014-02-26 02:37:00,1.8159999999999998\n2014-02-26 02:42:00,2.164\n2014-02-26 02:47:00,1.834\n2014-02-26 02:52:00,2.112\n2014-02-26 02:57:00,1.96\n2014-02-26 03:02:00,2.136\n2014-02-26 03:07:00,2.026\n2014-02-26 03:12:00,6.14\n2014-02-26 03:17:00,2.516\n2014-02-26 03:22:00,4.666\n2014-02-26 03:27:00,2.376\n2014-02-26 03:32:00,4.284\n2014-02-26 03:37:00,2.5340000000000003\n2014-02-26 03:42:00,6.1160000000000005\n2014-02-26 03:47:00,2.9160000000000004\n2014-02-26 03:52:00,2.384\n2014-02-26 03:57:00,2.064\n2014-02-26 04:02:00,2.394\n2014-02-26 04:07:00,2.0380000000000003\n2014-02-26 04:12:00,58.33600000000001\n2014-02-26 04:17:00,52.784\n2014-02-26 04:22:00,51.782\n2014-02-26 04:27:00,27.965999999999998\n2014-02-26 04:32:00,52.083999999999996\n2014-02-26 04:37:00,16.528\n2014-02-26 04:42:00,3.384\n2014-02-26 04:47:00,4.532\n2014-02-26 04:52:00,2.864\n2014-02-26 04:57:00,2.5839999999999996\n2014-02-26 05:02:00,3.196\n2014-02-26 05:07:00,2.738\n2014-02-26 05:12:00,6.316\n2014-02-26 05:17:00,2.8360000000000003\n2014-02-26 05:22:00,4.706\n2014-02-26 05:27:00,2.75\n2014-02-26 05:32:00,3.094\n2014-02-26 05:37:00,2.516\n2014-02-26 05:42:00,2.75\n2014-02-26 05:47:00,2.37\n2014-02-26 05:52:00,2.8080000000000003\n2014-02-26 05:57:00,9.357999999999999\n2014-02-26 06:02:00,2.9760000000000004\n2014-02-26 06:07:00,42.943999999999996\n2014-02-26 06:12:00,57.251999999999995\n2014-02-26 06:17:00,55.483999999999995\n2014-02-26 06:22:00,10.908\n2014-02-26 06:27:00,2.7239999999999998\n2014-02-26 06:32:00,59.86600000000001\n2014-02-26 06:37:00,53.63800000000001\n2014-02-26 06:42:00,49.391999999999996\n2014-02-26 06:47:00,2.54\n2014-02-26 06:52:00,2.806\n2014-02-26 06:57:00,2.736\n2014-02-26 07:02:00,2.984\n2014-02-26 07:07:00,6.056\n2014-02-26 07:12:00,3.1\n2014-02-26 07:17:00,5.3820000000000014\n2014-02-26 07:22:00,3.134\n2014-02-26 07:27:00,4.508\n2014-02-26 07:32:00,2.7560000000000002\n2014-02-26 07:37:00,2.334\n2014-02-26 07:42:00,3.0780000000000003\n2014-02-26 07:47:00,2.844\n2014-02-26 07:52:00,4.584\n2014-02-26 07:57:00,1.8659999999999999\n2014-02-26 08:02:00,2.096\n2014-02-26 08:07:00,1.896\n2014-02-26 08:12:00,2.08\n2014-02-26 08:17:00,2.7539999999999996\n2014-02-26 08:22:00,2.504\n2014-02-26 08:27:00,1.8219999999999998\n2014-02-26 08:32:00,2.012\n2014-02-26 08:37:00,1.808\n2014-02-26 08:42:00,2.0540000000000003\n2014-02-26 08:47:00,1.8659999999999999\n2014-02-26 08:52:00,2.084\n2014-02-26 08:57:00,1.946\n2014-02-26 09:02:00,2.11\n2014-02-26 09:07:00,1.896\n2014-02-26 09:12:00,2.126\n2014-02-26 09:17:00,3.556\n2014-02-26 09:22:00,2.48\n2014-02-26 09:27:00,2.0380000000000003\n2014-02-26 09:32:00,2.166\n2014-02-26 09:37:00,1.95\n2014-02-26 09:42:00,2.2\n2014-02-26 09:47:00,2.8339999999999996\n2014-02-26 09:52:00,2.378\n2014-02-26 09:57:00,2.106\n2014-02-26 10:02:00,2.016\n2014-02-26 10:07:00,1.85\n2014-02-26 10:12:00,2.13\n2014-02-26 10:17:00,3.1660000000000004\n2014-02-26 10:22:00,2.182\n2014-02-26 10:27:00,1.808\n2014-02-26 10:32:00,2.092\n2014-02-26 10:37:00,1.9080000000000001\n2014-02-26 10:42:00,2.154\n2014-02-26 10:47:00,1.916\n2014-02-26 10:52:00,2.13\n2014-02-26 10:57:00,1.962\n2014-02-26 11:02:00,2.188\n2014-02-26 11:07:00,1.972\n2014-02-26 11:12:00,3.484\n2014-02-26 11:17:00,1.9080000000000001\n2014-02-26 11:22:00,2.146\n2014-02-26 11:27:00,1.946\n2014-02-26 11:32:00,2.2\n2014-02-26 11:37:00,1.9\n2014-02-26 11:42:00,2.23\n2014-02-26 11:47:00,1.9780000000000002\n2014-02-26 11:52:00,2.26\n2014-02-26 11:57:00,2.062\n2014-02-26 12:02:00,2.2840000000000003\n2014-02-26 12:07:00,2.0540000000000003\n2014-02-26 12:12:00,2.246\n2014-02-26 12:17:00,3.18\n2014-02-26 12:22:00,2.096\n2014-02-26 12:27:00,7.716\n2014-02-26 12:32:00,2.988\n2014-02-26 12:37:00,2.556\n2014-02-26 12:42:00,2.69\n2014-02-26 12:47:00,2.2840000000000003\n2014-02-26 12:52:00,2.428\n2014-02-26 12:57:00,2.108\n2014-02-26 13:02:00,2.29\n2014-02-26 13:07:00,1.956\n2014-02-26 13:12:00,3.514\n2014-02-26 13:17:00,1.944\n2014-02-26 13:22:00,2.272\n2014-02-26 13:27:00,2.056\n2014-02-26 13:32:00,2.238\n2014-02-26 13:37:00,1.9280000000000002\n2014-02-26 13:42:00,2.2119999999999997\n2014-02-26 13:47:00,1.906\n2014-02-26 13:52:00,2.146\n2014-02-26 13:57:00,2.0340000000000003\n2014-02-26 14:02:00,2.226\n2014-02-26 14:07:00,2.028\n2014-02-26 14:12:00,2.272\n2014-02-26 14:17:00,3.2880000000000003\n2014-02-26 14:22:00,2.234\n2014-02-26 14:27:00,2.062\n2014-02-26 14:32:00,2.326\n2014-02-26 14:37:00,2.022\n2014-02-26 14:42:00,2.2119999999999997\n2014-02-26 14:47:00,2.004\n2014-02-26 14:52:00,2.274\n2014-02-26 14:57:00,2.094\n2014-02-26 15:02:00,2.2880000000000003\n2014-02-26 15:07:00,2.0780000000000003\n2014-02-26 15:12:00,2.322\n2014-02-26 15:17:00,3.372\n2014-02-26 15:22:00,2.246\n2014-02-26 15:27:00,2.012\n2014-02-26 15:32:00,2.298\n2014-02-26 15:37:00,2.138\n2014-02-26 15:42:00,2.096\n2014-02-26 15:47:00,1.8780000000000001\n2014-02-26 15:52:00,2.106\n2014-02-26 15:57:00,1.944\n2014-02-26 16:02:00,2.108\n2014-02-26 16:07:00,1.926\n2014-02-26 16:12:00,2.13\n2014-02-26 16:17:00,3.2039999999999997\n2014-02-26 16:22:00,2.122\n2014-02-26 16:27:00,1.9\n2014-02-26 16:32:00,2.154\n2014-02-26 16:37:00,2.7880000000000003\n2014-02-26 16:42:00,2.0540000000000003\n2014-02-26 16:47:00,1.8\n2014-02-26 16:52:00,2.062\n2014-02-26 16:57:00,1.98\n2014-02-26 17:02:00,2.154\n2014-02-26 17:07:00,1.912\n2014-02-26 17:12:00,3.484\n2014-02-26 17:17:00,1.9280000000000002\n2014-02-26 17:22:00,2.142\n2014-02-26 17:27:00,2.01\n2014-02-26 17:32:00,2.2159999999999997\n2014-02-26 17:37:00,47.066\n2014-02-26 17:42:00,60.746\n2014-02-26 17:47:00,52.141999999999996\n2014-02-26 17:52:00,12.93\n2014-02-26 17:57:00,3.168\n2014-02-26 18:02:00,4.466\n2014-02-26 18:07:00,3.24\n2014-02-26 18:12:00,4.984\n2014-02-26 18:17:00,3.9960000000000004\n2014-02-26 18:22:00,3.068\n2014-02-26 18:27:00,2.772\n2014-02-26 18:32:00,3.1660000000000004\n2014-02-26 18:37:00,4.102\n2014-02-26 18:42:00,2.324\n2014-02-26 18:47:00,2.006\n2014-02-26 18:52:00,2.306\n2014-02-26 18:57:00,2.094\n2014-02-26 19:02:00,2.362\n2014-02-26 19:07:00,44.396\n2014-02-26 19:12:00,56.25\n2014-02-26 19:17:00,56.333999999999996\n2014-02-26 19:22:00,9.376\n2014-02-26 19:27:00,3.202\n2014-02-26 19:32:00,4.724\n2014-02-26 19:37:00,3.366\n2014-02-26 19:42:00,5.2860000000000005\n2014-02-26 19:47:00,2.806\n2014-02-26 19:52:00,2.984\n2014-02-26 19:57:00,3.0580000000000003\n2014-02-26 20:02:00,3.234\n2014-02-26 20:07:00,2.8739999999999997\n2014-02-26 20:12:00,3.99\n2014-02-26 20:17:00,3.388\n2014-02-26 20:22:00,2.524\n2014-02-26 20:27:00,2.15\n2014-02-26 20:32:00,2.5\n2014-02-26 20:37:00,2.24\n2014-02-26 20:42:00,2.49\n2014-02-26 20:47:00,2.194\n2014-02-26 20:52:00,2.4659999999999997\n2014-02-26 20:57:00,2.134\n2014-02-26 21:02:00,2.41\n2014-02-26 21:07:00,3.34\n2014-02-26 21:12:00,2.356\n2014-02-26 21:17:00,2.116\n2014-02-26 21:22:00,2.38\n2014-02-26 21:27:00,2.072\n2014-02-26 21:32:00,2.316\n2014-02-26 21:37:00,1.9280000000000002\n2014-02-26 21:42:00,2.198\n2014-02-26 21:47:00,1.99\n2014-02-26 21:52:00,2.226\n2014-02-26 21:57:00,3.464\n2014-02-26 22:02:00,2.2119999999999997\n2014-02-26 22:07:00,1.8880000000000001\n2014-02-26 22:12:00,3.4160000000000004\n2014-02-26 22:17:00,1.922\n2014-02-26 22:22:00,2.134\n2014-02-26 22:27:00,1.906\n2014-02-26 22:32:00,2.9\n2014-02-26 22:37:00,66.906\n2014-02-26 22:42:00,52.794\n2014-02-26 22:47:00,37.718\n2014-02-26 22:52:00,2.8280000000000003\n2014-02-26 22:57:00,3.216\n2014-02-26 23:02:00,3.728\n2014-02-26 23:07:00,2.6260000000000003\n2014-02-26 23:12:00,4.688\n2014-02-26 23:17:00,3.7\n2014-02-26 23:22:00,2.908\n2014-02-26 23:27:00,2.7060000000000004\n2014-02-26 23:32:00,2.9160000000000004\n2014-02-26 23:37:00,5.086\n2014-02-26 23:42:00,5.066\n2014-02-26 23:47:00,2.6660000000000004\n2014-02-26 23:52:00,3.866\n2014-02-26 23:57:00,66.266\n2014-02-27 00:02:00,52.61600000000001\n2014-02-27 00:07:00,40.452\n2014-02-27 00:12:00,4.644\n2014-02-27 00:17:00,3.674\n2014-02-27 00:22:00,3.948\n2014-02-27 00:27:00,4.04\n2014-02-27 00:32:00,9.638\n2014-02-27 00:37:00,3.292\n2014-02-27 00:42:00,3.35\n2014-02-27 00:47:00,2.72\n2014-02-27 00:52:00,3.49\n2014-02-27 00:57:00,2.99\n2014-02-27 01:02:00,3.27\n2014-02-27 01:07:00,4.306\n2014-02-27 01:12:00,3.7319999999999998\n2014-02-27 01:17:00,42.461999999999996\n2014-02-27 01:22:00,56.483999999999995\n2014-02-27 01:27:00,52.342\n2014-02-27 01:32:00,8.79\n2014-02-27 01:37:00,4.206\n2014-02-27 01:42:00,25.656\n2014-02-27 01:47:00,65.598\n2014-02-27 01:52:00,52.583999999999996\n2014-02-27 01:57:00,21.136\n2014-02-27 02:02:00,3.4619999999999997\n2014-02-27 02:07:00,5.4239999999999995\n2014-02-27 02:12:00,3.48\n2014-02-27 02:17:00,4.758\n2014-02-27 02:22:00,3.136\n2014-02-27 02:27:00,2.7239999999999998\n2014-02-27 02:32:00,3.574\n2014-02-27 02:37:00,3.134\n2014-02-27 02:42:00,4.71\n2014-02-27 02:47:00,2.4\n2014-02-27 02:52:00,2.628\n2014-02-27 02:57:00,2.376\n2014-02-27 03:02:00,2.728\n2014-02-27 03:07:00,2.376\n2014-02-27 03:12:00,2.8760000000000003\n2014-02-27 03:17:00,3.6039999999999996\n2014-02-27 03:22:00,2.572\n2014-02-27 03:27:00,2.2680000000000002\n2014-02-27 03:32:00,2.596\n2014-02-27 03:37:00,2.3040000000000003\n2014-02-27 03:42:00,2.7060000000000004\n2014-02-27 03:47:00,2.4\n2014-02-27 03:52:00,2.688\n2014-02-27 03:57:00,2.4219999999999997\n2014-02-27 04:02:00,2.7060000000000004\n2014-02-27 04:07:00,2.39\n2014-02-27 04:12:00,2.676\n2014-02-27 04:17:00,3.634\n2014-02-27 04:22:00,7.612\n2014-02-27 04:27:00,2.6719999999999997\n2014-02-27 04:32:00,3.028\n2014-02-27 04:37:00,2.622\n2014-02-27 04:42:00,3.48\n2014-02-27 04:47:00,2.96\n2014-02-27 04:52:00,3.234\n2014-02-27 04:57:00,2.74\n2014-02-27 05:02:00,3.1660000000000004\n2014-02-27 05:07:00,4.684\n2014-02-27 05:12:00,3.292\n2014-02-27 05:17:00,2.886\n2014-02-27 05:22:00,3.24\n2014-02-27 05:27:00,5.052\n2014-02-27 05:32:00,3.792\n2014-02-27 05:37:00,2.7119999999999997\n2014-02-27 05:42:00,3.08\n2014-02-27 05:47:00,2.592\n2014-02-27 05:52:00,2.7560000000000002\n2014-02-27 05:57:00,11.998\n2014-02-27 06:02:00,3.088\n2014-02-27 06:07:00,5.1339999999999995\n2014-02-27 06:12:00,2.984\n2014-02-27 06:17:00,4.374\n2014-02-27 06:22:00,2.716\n2014-02-27 06:27:00,2.322\n2014-02-27 06:32:00,2.572\n2014-02-27 06:37:00,2.194\n2014-02-27 06:42:00,2.4\n2014-02-27 06:47:00,1.974\n2014-02-27 06:52:00,2.316\n2014-02-27 06:57:00,2.106\n2014-02-27 07:02:00,2.41\n2014-02-27 07:07:00,3.326\n2014-02-27 07:12:00,2.366\n2014-02-27 07:17:00,2.06\n2014-02-27 07:22:00,2.256\n2014-02-27 07:27:00,1.944\n2014-02-27 07:32:00,2.228\n2014-02-27 07:37:00,2.006\n2014-02-27 07:42:00,2.21\n2014-02-27 07:47:00,1.9880000000000002\n2014-02-27 07:52:00,2.23\n2014-02-27 07:57:00,1.9780000000000002\n2014-02-27 08:02:00,2.1719999999999997\n2014-02-27 08:07:00,2.004\n2014-02-27 08:12:00,2.204\n2014-02-27 08:17:00,3.222\n2014-02-27 08:22:00,2.2159999999999997\n2014-02-27 08:27:00,2.006\n2014-02-27 08:32:00,2.2159999999999997\n2014-02-27 08:37:00,1.946\n2014-02-27 08:42:00,2.15\n2014-02-27 08:47:00,1.922\n2014-02-27 08:52:00,2.178\n2014-02-27 08:57:00,1.962\n2014-02-27 09:02:00,2.226\n2014-02-27 09:07:00,1.984\n2014-02-27 09:12:00,2.166\n2014-02-27 09:17:00,2.306\n2014-02-27 09:22:00,3.4339999999999997\n2014-02-27 09:27:00,1.8940000000000001\n2014-02-27 09:32:00,2.146\n2014-02-27 09:37:00,1.9380000000000002\n2014-02-27 09:42:00,2.146\n2014-02-27 09:47:00,1.886\n2014-02-27 09:52:00,2.188\n2014-02-27 09:57:00,1.944\n2014-02-27 10:02:00,2.15\n2014-02-27 10:07:00,5.584\n2014-02-27 10:12:00,3.1260000000000003\n2014-02-27 10:17:00,4.064\n2014-02-27 10:22:00,3.1639999999999997\n2014-02-27 10:27:00,2.72\n2014-02-27 10:32:00,2.98\n2014-02-27 10:37:00,2.526\n2014-02-27 10:42:00,2.842\n2014-02-27 10:47:00,2.424\n2014-02-27 10:52:00,2.8280000000000003\n2014-02-27 10:57:00,2.33\n2014-02-27 11:02:00,2.65\n2014-02-27 11:07:00,2.36\n2014-02-27 11:12:00,2.616\n2014-02-27 11:17:00,2.434\n2014-02-27 11:22:00,3.6519999999999997\n2014-02-27 11:27:00,2.166\n2014-02-27 11:32:00,2.484\n2014-02-27 11:37:00,2.116\n2014-02-27 11:42:00,2.38\n2014-02-27 11:47:00,2.11\n2014-02-27 11:52:00,2.358\n2014-02-27 11:57:00,2.022\n2014-02-27 12:02:00,3.452\n2014-02-27 12:07:00,3.15\n2014-02-27 12:12:00,3.302\n2014-02-27 12:17:00,4.2219999999999995\n2014-02-27 12:22:00,3.342\n2014-02-27 12:27:00,3.114\n2014-02-27 12:32:00,3.312\n2014-02-27 12:37:00,3.096\n2014-02-27 12:42:00,3.134\n2014-02-27 12:47:00,3.088\n2014-02-27 12:52:00,3.322\n2014-02-27 12:57:00,3.1460000000000004\n2014-02-27 13:02:00,4.216\n2014-02-27 13:07:00,1.854\n2014-02-27 13:12:00,8.15\n2014-02-27 13:17:00,9.666\n2014-02-27 13:22:00,4.1\n2014-02-27 13:27:00,3.6660000000000004\n2014-02-27 13:32:00,6.084\n2014-02-27 13:37:00,3.6860000000000004\n2014-02-27 13:42:00,4.058\n2014-02-27 13:47:00,3.6319999999999997\n2014-02-27 13:52:00,3.8360000000000003\n2014-02-27 13:57:00,3.4939999999999998\n2014-02-27 14:02:00,3.4939999999999998\n2014-02-27 14:07:00,3.342\n2014-02-27 14:12:00,3.6439999999999997\n2014-02-27 14:17:00,3.234\n2014-02-27 14:22:00,6.2479999999999976\n2014-02-27 14:27:00,2.076\n2014-02-27 14:32:00,3.55\n2014-02-27 14:37:00,2.67\n2014-02-27 14:42:00,2.884\n2014-02-27 14:47:00,2.694\n2014-02-27 14:52:00,5.8\n2014-02-27 14:57:00,3.4419999999999997\n2014-02-27 15:02:00,3.892\n2014-02-27 15:07:00,6.376\n2014-02-27 15:12:00,3.4760000000000004\n2014-02-27 15:17:00,3.34\n2014-02-27 15:22:00,3.784\n2014-02-27 15:27:00,3.06\n2014-02-27 15:32:00,4.46\n2014-02-27 15:37:00,2.126\n2014-02-27 15:42:00,2.49\n2014-02-27 15:47:00,2.16\n2014-02-27 15:52:00,3.6860000000000004\n2014-02-27 15:57:00,2.306\n2014-02-27 16:02:00,2.716\n2014-02-27 16:07:00,46.01600000000001\n2014-02-27 16:12:00,78.81\n2014-02-27 16:17:00,42.742\n2014-02-27 16:22:00,11.05\n2014-02-27 16:27:00,4.102\n2014-02-27 16:32:00,5.224\n2014-02-27 16:37:00,4.0760000000000005\n2014-02-27 16:42:00,6.428\n2014-02-27 16:47:00,3.342\n2014-02-27 16:52:00,4.662\n2014-02-27 16:57:00,7.4\n2014-02-27 17:02:00,5.816\n2014-02-27 17:07:00,9.17\n2014-02-27 17:12:00,8.634\n2014-02-27 17:17:00,2.634\n2014-02-27 17:22:00,3.034\n2014-02-27 17:27:00,2.612\n2014-02-27 17:32:00,3.022\n2014-02-27 17:37:00,4.816\n2014-02-27 17:42:00,3.326\n2014-02-27 17:47:00,2.892\n2014-02-27 17:52:00,3.4739999999999998\n2014-02-27 17:57:00,2.892\n2014-02-27 18:02:00,3.3\n2014-02-27 18:07:00,2.85\n2014-02-27 18:12:00,4.408\n2014-02-27 18:17:00,2.592\n2014-02-27 18:22:00,2.9760000000000004\n2014-02-27 18:27:00,2.568\n2014-02-27 18:32:00,3.008\n2014-02-27 18:37:00,2.6460000000000004\n2014-02-27 18:42:00,3.1719999999999997\n2014-02-27 18:47:00,2.734\n2014-02-27 18:52:00,3.108\n2014-02-27 18:57:00,2.7439999999999998\n2014-02-27 19:02:00,3.0980000000000003\n2014-02-27 19:07:00,2.716\n2014-02-27 19:12:00,4.336\n2014-02-27 19:17:00,48.676\n2014-02-27 19:22:00,76.5\n2014-02-27 19:27:00,38.446\n2014-02-27 19:32:00,3.7739999999999996\n2014-02-27 19:37:00,4.334\n2014-02-27 19:42:00,3.918\n2014-02-27 19:47:00,5.4079999999999995\n2014-02-27 19:52:00,3.818\n2014-02-27 19:57:00,3.15\n2014-02-27 20:02:00,3.702\n2014-02-27 20:07:00,3.46\n2014-02-27 20:12:00,3.8739999999999997\n2014-02-27 20:17:00,6.484\n2014-02-27 20:22:00,3.062\n2014-02-27 20:27:00,2.656\n2014-02-27 20:32:00,3.034\n2014-02-27 20:37:00,2.6439999999999997\n2014-02-27 20:42:00,3.056\n2014-02-27 20:47:00,5.31\n2014-02-27 20:52:00,3.0180000000000002\n2014-02-27 20:57:00,2.742\n2014-02-27 21:02:00,3.016\n2014-02-27 21:07:00,2.592\n2014-02-27 21:12:00,2.9760000000000004\n2014-02-27 21:17:00,44.63\n2014-02-27 21:22:00,79.72399999999998\n2014-02-27 21:27:00,41.583999999999996\n2014-02-27 21:32:00,3.8\n2014-02-27 21:37:00,4.3660000000000005\n2014-02-27 21:42:00,3.884\n2014-02-27 21:47:00,5.4\n2014-02-27 21:52:00,3.7439999999999998\n2014-02-27 21:57:00,4.566\n2014-02-27 22:02:00,3.516\n2014-02-27 22:07:00,3.1439999999999997\n2014-02-27 22:12:00,3.6\n2014-02-27 22:17:00,3.216\n2014-02-27 22:22:00,5.843999999999999\n2014-02-27 22:27:00,2.592\n2014-02-27 22:32:00,3.0260000000000002\n2014-02-27 22:37:00,2.5860000000000003\n2014-02-27 22:42:00,2.9960000000000004\n2014-02-27 22:47:00,2.5660000000000003\n2014-02-27 22:52:00,31.938000000000002\n2014-02-27 22:57:00,82.89\n2014-02-27 23:02:00,45.174\n2014-02-27 23:07:00,3.952\n2014-02-27 23:12:00,6.138\n2014-02-27 23:17:00,3.516\n2014-02-27 23:22:00,3.742\n2014-02-27 23:27:00,5.377999999999999\n2014-02-27 23:32:00,3.4\n2014-02-27 23:37:00,3.188\n2014-02-27 23:42:00,3.6660000000000004\n2014-02-27 23:47:00,3.234\n2014-02-27 23:52:00,4.882\n2014-02-27 23:57:00,2.592\n2014-02-28 00:02:00,2.958\n2014-02-28 00:07:00,3.87\n2014-02-28 00:12:00,3.114\n2014-02-28 00:17:00,2.6919999999999997\n2014-02-28 00:22:00,3.05\n2014-02-28 00:27:00,2.642\n2014-02-28 00:32:00,3.042\n2014-02-28 00:37:00,2.67\n2014-02-28 00:42:00,3.122\n2014-02-28 00:47:00,2.634\n2014-02-28 00:52:00,3.076\n2014-02-28 00:57:00,2.722\n2014-02-28 01:02:00,3.096\n2014-02-28 01:07:00,2.736\n2014-02-28 01:12:00,4.478\n2014-02-28 01:17:00,2.8\n2014-02-28 01:22:00,3.1839999999999997\n2014-02-28 01:27:00,43.1\n2014-02-28 01:32:00,79.084\n2014-02-28 01:37:00,42.141999999999996\n2014-02-28 01:42:00,3.89\n2014-02-28 01:47:00,4.466\n2014-02-28 01:52:00,4.008\n2014-02-28 01:57:00,3.508\n2014-02-28 02:02:00,5.85\n2014-02-28 02:07:00,3.052\n2014-02-28 02:12:00,3.6260000000000003\n2014-02-28 02:17:00,7.3439999999999985\n2014-02-28 02:22:00,5.562\n2014-02-28 02:27:00,5.726\n2014-02-28 02:32:00,3.542\n2014-02-28 02:37:00,2.9\n2014-02-28 02:42:00,9.866\n2014-02-28 02:47:00,4.342\n2014-02-28 02:52:00,5.584\n2014-02-28 02:57:00,4.46\n2014-02-28 03:02:00,6.757999999999999\n2014-02-28 03:07:00,4.342\n2014-02-28 03:12:00,4.15\n2014-02-28 03:17:00,5.142\n2014-02-28 03:22:00,4.558\n2014-02-28 03:27:00,3.966\n2014-02-28 03:32:00,5.532\n2014-02-28 03:37:00,2.9019999999999997\n2014-02-28 03:42:00,3.35\n2014-02-28 03:47:00,2.926\n2014-02-28 03:52:00,3.3080000000000003\n2014-02-28 03:57:00,2.95\n2014-02-28 04:02:00,3.4419999999999997\n2014-02-28 04:07:00,2.9339999999999997\n2014-02-28 04:12:00,4.7\n2014-02-28 04:17:00,3.016\n2014-02-28 04:22:00,3.3939999999999997\n2014-02-28 04:27:00,3.1180000000000003\n2014-02-28 04:32:00,16.6\n2014-02-28 04:37:00,2.9760000000000004\n2014-02-28 04:42:00,3.358\n2014-02-28 04:47:00,2.95\n2014-02-28 04:52:00,3.4419999999999997\n2014-02-28 04:57:00,3.05\n2014-02-28 05:02:00,3.408\n2014-02-28 05:07:00,13.734000000000002\n2014-02-28 05:12:00,91.00200000000001\n2014-02-28 05:17:00,56.193999999999996\n2014-02-28 05:22:00,12.765999999999998\n2014-02-28 05:27:00,4.606\n2014-02-28 05:32:00,8.766\n2014-02-28 05:37:00,3.502\n2014-02-28 05:42:00,6.1\n2014-02-28 05:47:00,3.25\n2014-02-28 05:52:00,3.846\n2014-02-28 05:57:00,3.742\n2014-02-28 06:02:00,3.984\n2014-02-28 06:07:00,4.684\n2014-02-28 06:12:00,3.21\n2014-02-28 06:17:00,4.024\n2014-02-28 06:22:00,3.252\n2014-02-28 06:27:00,2.778\n2014-02-28 06:32:00,3.2060000000000004\n2014-02-28 06:37:00,2.752\n2014-02-28 06:42:00,3.168\n2014-02-28 06:47:00,2.784\n2014-02-28 06:52:00,3.19\n2014-02-28 06:57:00,2.734\n2014-02-28 07:02:00,3.116\n2014-02-28 07:07:00,2.7\n2014-02-28 07:12:00,4.513999999999999\n2014-02-28 07:17:00,2.676\n2014-02-28 07:22:00,3.134\n2014-02-28 07:27:00,2.658\n2014-02-28 07:32:00,3.092\n2014-02-28 07:37:00,2.688\n2014-02-28 07:42:00,3.14\n2014-02-28 07:47:00,2.76\n2014-02-28 07:52:00,3.1839999999999997\n2014-02-28 07:57:00,2.766\n2014-02-28 08:02:00,3.17\n2014-02-28 08:07:00,2.9160000000000004\n2014-02-28 08:12:00,6.734\n2014-02-28 08:17:00,2.742\n2014-02-28 08:22:00,6.166\n2014-02-28 08:27:00,2.95\n2014-02-28 08:32:00,3.3339999999999996\n2014-02-28 08:37:00,2.784\n2014-02-28 08:42:00,3.266\n2014-02-28 08:47:00,2.7739999999999996\n2014-02-28 08:52:00,3.242\n2014-02-28 08:57:00,2.7939999999999996\n2014-02-28 09:02:00,3.1919999999999997\n2014-02-28 09:07:00,4.624\n2014-02-28 09:12:00,3.1660000000000004\n2014-02-28 09:17:00,3.1239999999999997\n2014-02-28 09:22:00,3.1239999999999997\n2014-02-28 09:27:00,2.6919999999999997\n2014-02-28 09:32:00,3.158\n2014-02-28 09:37:00,2.694\n2014-02-28 09:42:00,3.1260000000000003\n2014-02-28 09:47:00,5.058\n2014-02-28 09:52:00,3.076\n2014-02-28 09:57:00,2.708\n2014-02-28 10:02:00,3.1239999999999997\n2014-02-28 10:07:00,2.728\n2014-02-28 10:12:00,3.134\n2014-02-28 10:17:00,3.9939999999999998\n2014-02-28 10:22:00,3.0839999999999996\n2014-02-28 10:27:00,2.65\n2014-02-28 10:32:00,3.0780000000000003\n2014-02-28 10:37:00,2.71\n2014-02-28 10:42:00,3.1\n2014-02-28 10:47:00,5.332000000000002\n2014-02-28 10:52:00,3.142\n2014-02-28 10:57:00,2.734\n2014-02-28 11:02:00,3.142\n2014-02-28 11:07:00,2.738\n2014-02-28 11:12:00,3.13\n2014-02-28 11:17:00,3.858\n2014-02-28 11:22:00,2.77\n2014-02-28 11:27:00,2.344\n2014-02-28 11:32:00,2.594\n2014-02-28 11:37:00,2.208\n2014-02-28 11:42:00,2.516\n2014-02-28 11:47:00,2.1\n2014-02-28 11:52:00,2.46\n2014-02-28 11:57:00,2.13\n2014-02-28 12:02:00,2.536\n2014-02-28 12:07:00,2.094\n2014-02-28 12:12:00,2.426\n2014-02-28 12:17:00,3.3160000000000003\n2014-02-28 12:22:00,2.384\n2014-02-28 12:27:00,2.04\n2014-02-28 12:32:00,2.444\n2014-02-28 12:37:00,2.116\n2014-02-28 12:42:00,2.418\n2014-02-28 12:47:00,2.08\n2014-02-28 12:52:00,2.412\n2014-02-28 12:57:00,2.096\n2014-02-28 13:02:00,2.42\n2014-02-28 13:07:00,3.366\n2014-02-28 13:12:00,2.39\n2014-02-28 13:17:00,4.94\n2014-02-28 13:22:00,5.766\n2014-02-28 13:27:00,2.6660000000000004\n2014-02-28 13:32:00,3.014\n2014-02-28 13:37:00,2.548\n2014-02-28 13:42:00,2.75\n2014-02-28 13:47:00,2.354\n2014-02-28 13:52:00,2.6\n2014-02-28 13:57:00,2.262\n2014-02-28 14:02:00,2.456\n2014-02-28 14:07:00,2.0980000000000003\n2014-02-28 14:12:00,2.376\n2014-02-28 14:17:00,2.426\n2014-02-28 14:22:00,3.252\n"
  },
  {
    "path": "workspace/anomaly_detector/datasets/selected/outliers/rogue_agent_key_hold.csv",
    "content": "timestamp,value\r\n2014-07-06 20:10:00,0.06453452400000001\r\n2014-07-06 20:15:00,0.064295318\r\n2014-07-06 20:20:00,0.063879838\r\n2014-07-06 20:25:00,0.065691833\r\n2014-07-06 20:35:00,0.056301242\r\n2014-07-06 20:40:00,0.067750636\r\n2014-07-06 20:45:00,0.0\r\n2014-07-06 20:55:00,0.06528790799999999\r\n2014-07-06 21:00:00,0.063178539\r\n2014-07-06 21:05:00,0.0\r\n2014-07-06 21:10:00,0.0\r\n2014-07-06 21:15:00,0.0\r\n2014-07-07 16:15:00,0.06593207599999999\r\n2014-07-07 16:20:00,0.068277308\r\n2014-07-07 16:25:00,0.0\r\n2014-07-07 16:35:00,0.062787234\r\n2014-07-07 16:40:00,0.06657756599999999\r\n2014-07-07 16:45:00,0.077044715\r\n2014-07-07 16:50:00,0.075116301\r\n2014-07-07 16:55:00,0.07199654\r\n2014-07-07 17:00:00,0.0\r\n2014-07-07 17:05:00,0.0\r\n2014-07-07 17:25:00,0.061142873\r\n2014-07-07 17:30:00,0.0\r\n2014-07-07 17:35:00,0.04943192\r\n2014-07-07 17:45:00,0.071269501\r\n2014-07-07 17:50:00,0.064887449\r\n2014-07-07 17:55:00,0.079126387\r\n2014-07-07 18:00:00,0.079692364\r\n2014-07-07 18:05:00,0.064561804\r\n2014-07-07 18:10:00,0.076985488\r\n2014-07-07 18:15:00,0.07198525900000001\r\n2014-07-07 18:20:00,0.066090552\r\n2014-07-07 18:25:00,0.06469324900000001\r\n2014-07-07 18:30:00,0.064608783\r\n2014-07-07 18:35:00,0.067478103\r\n2014-07-07 18:40:00,0.069862932\r\n2014-07-07 18:45:00,0.06589513\r\n2014-07-07 18:50:00,0.06522446700000001\r\n2014-07-07 18:55:00,0.058982897\r\n2014-07-07 19:00:00,0.0\r\n2014-07-07 19:30:00,0.0\r\n2014-07-07 20:10:00,0.0\r\n2014-07-07 20:15:00,0.07537598200000001\r\n2014-07-07 20:20:00,0.06833768700000001\r\n2014-07-07 20:25:00,0.077055882\r\n2014-07-07 20:30:00,0.08510286800000001\r\n2014-07-07 20:35:00,0.074617078\r\n2014-07-07 20:40:00,0.073783769\r\n2014-07-07 20:45:00,0.067219689\r\n2014-07-07 20:50:00,0.082650582\r\n2014-07-07 20:55:00,0.071369655\r\n2014-07-07 21:00:00,0.074396641\r\n2014-07-07 21:05:00,0.11970953\r\n2014-07-07 21:10:00,0.06731445700000001\r\n2014-07-07 21:15:00,0.072558182\r\n2014-07-07 21:20:00,0.06728508700000001\r\n2014-07-07 21:25:00,0.070712037\r\n2014-07-07 21:30:00,0.064641756\r\n2014-07-07 21:35:00,0.073068096\r\n2014-07-07 21:40:00,0.07057474799999999\r\n2014-07-07 21:45:00,0.066541138\r\n2014-07-07 21:50:00,0.07096640900000001\r\n2014-07-07 21:55:00,0.072068935\r\n2014-07-07 22:00:00,0.068014095\r\n2014-07-07 22:05:00,0.069069546\r\n2014-07-07 22:10:00,0.066306158\r\n2014-07-07 22:15:00,0.071656362\r\n2014-07-07 22:20:00,0.070537682\r\n2014-07-07 22:25:00,0.069981819\r\n2014-07-07 22:30:00,0.063712692\r\n2014-07-07 22:35:00,0.07592906599999999\r\n2014-07-07 22:40:00,0.068992963\r\n2014-07-07 22:45:00,0.073445647\r\n2014-07-07 22:50:00,0.07052242\r\n2014-07-07 22:55:00,0.226947951\r\n2014-07-07 23:00:00,0.0770232\r\n2014-07-07 23:05:00,0.072146928\r\n2014-07-07 23:10:00,0.070184442\r\n2014-07-07 23:15:00,0.071785589\r\n2014-07-07 23:20:00,0.07143490799999999\r\n2014-07-07 23:25:00,0.065622919\r\n2014-07-07 23:30:00,0.081242128\r\n2014-07-07 23:35:00,0.093692864\r\n2014-07-07 23:40:00,0.090847328\r\n2014-07-07 23:45:00,0.086801539\r\n2014-07-07 23:50:00,0.072789827\r\n2014-07-07 23:55:00,0.07527392299999999\r\n2014-07-08 00:00:00,0.0\r\n2014-07-08 00:05:00,0.074694667\r\n2014-07-08 00:10:00,0.070129173\r\n2014-07-08 00:20:00,0.080410458\r\n2014-07-08 00:25:00,0.067807492\r\n2014-07-08 00:30:00,0.08191316400000001\r\n2014-07-08 00:35:00,0.0\r\n2014-07-08 00:40:00,0.112033203\r\n2014-07-08 00:45:00,0.089263947\r\n2014-07-08 00:50:00,0.07131035200000001\r\n2014-07-08 00:55:00,0.073491377\r\n2014-07-08 01:00:00,0.062912334\r\n2014-07-08 01:05:00,0.060903851\r\n2014-07-08 01:10:00,0.055824222\r\n2014-07-08 01:15:00,0.062922219\r\n2014-07-08 01:20:00,0.07722562599999999\r\n2014-07-08 01:25:00,0.083142297\r\n2014-07-08 01:30:00,0.07844424900000001\r\n2014-07-08 01:35:00,0.07028794299999999\r\n2014-07-08 01:40:00,0.067850363\r\n2014-07-08 16:20:00,0.066507083\r\n2014-07-08 16:25:00,0.072771192\r\n2014-07-08 16:30:00,0.058495297\r\n2014-07-08 16:35:00,0.057057806\r\n2014-07-08 16:40:00,0.058605791\r\n2014-07-08 16:45:00,0.058052596\r\n2014-07-08 16:50:00,0.051507674\r\n2014-07-08 17:00:00,0.0\r\n2014-07-08 17:05:00,0.0\r\n2014-07-08 17:20:00,0.069990465\r\n2014-07-08 17:25:00,0.081846427\r\n2014-07-08 17:30:00,0.06884088599999999\r\n2014-07-08 17:35:00,0.065170985\r\n2014-07-08 17:40:00,0.0\r\n2014-07-08 17:50:00,0.07462521400000001\r\n2014-07-08 17:55:00,0.068300284\r\n2014-07-08 18:00:00,0.065351057\r\n2014-07-08 18:05:00,0.068766445\r\n2014-07-08 18:10:00,0.06544404200000001\r\n2014-07-08 18:15:00,0.073886382\r\n2014-07-08 18:20:00,0.072648136\r\n2014-07-08 18:25:00,0.070162658\r\n2014-07-08 18:30:00,0.078440291\r\n2014-07-08 18:35:00,0.080437172\r\n2014-07-08 18:40:00,0.074335158\r\n2014-07-08 18:45:00,0.070396356\r\n2014-07-08 18:50:00,0.068971142\r\n2014-07-08 18:55:00,0.06825881\r\n2014-07-08 19:00:00,0.07241175400000001\r\n2014-07-08 19:05:00,0.0\r\n2014-07-08 19:10:00,0.083314965\r\n2014-07-08 19:15:00,0.0\r\n2014-07-08 19:25:00,0.0\r\n2014-07-08 19:35:00,0.07265456099999999\r\n2014-07-08 19:40:00,0.070770578\r\n2014-07-08 19:45:00,0.06535992\r\n2014-07-08 19:50:00,0.06516216700000001\r\n2014-07-08 19:55:00,0.072056066\r\n2014-07-08 20:00:00,0.085815709\r\n2014-07-08 20:05:00,0.101067175\r\n2014-07-08 20:10:00,0.102269133\r\n2014-07-08 20:20:00,0.07337235\r\n2014-07-08 20:25:00,0.086461415\r\n2014-07-08 20:40:00,0.122939428\r\n2014-07-08 21:05:00,0.648676709\r\n2014-07-08 21:10:00,0.085586475\r\n2014-07-08 21:15:00,0.070694787\r\n2014-07-08 21:20:00,0.095611246\r\n2014-07-08 21:55:00,0.0\r\n2014-07-08 22:00:00,0.06963178099999999\r\n2014-07-08 22:05:00,0.0\r\n2014-07-08 22:15:00,0.065337805\r\n2014-07-08 22:20:00,0.069423449\r\n2014-07-08 22:25:00,0.089264929\r\n2014-07-08 22:30:00,0.066457554\r\n2014-07-08 22:35:00,0.0\r\n2014-07-08 22:40:00,0.0\r\n2014-07-08 22:50:00,0.07276004400000001\r\n2014-07-08 22:55:00,0.077930063\r\n2014-07-08 23:00:00,0.08089861599999999\r\n2014-07-08 23:05:00,0.0901801\r\n2014-07-08 23:10:00,0.096584395\r\n2014-07-08 23:15:00,0.0\r\n2014-07-08 23:20:00,0.0\r\n2014-07-08 23:25:00,0.073069589\r\n2014-07-08 23:30:00,0.07526831099999999\r\n2014-07-08 23:35:00,0.080200333\r\n2014-07-08 23:40:00,0.081870055\r\n2014-07-08 23:45:00,0.066538187\r\n2014-07-08 23:50:00,0.06486616\r\n2014-07-09 16:20:00,0.078202243\r\n2014-07-09 16:25:00,0.08467332\r\n2014-07-09 16:30:00,0.077211048\r\n2014-07-09 16:35:00,0.072798011\r\n2014-07-09 16:40:00,0.061893388\r\n2014-07-09 16:45:00,0.084999126\r\n2014-07-09 16:50:00,0.06060981400000001\r\n2014-07-09 16:55:00,0.05830139700000001\r\n2014-07-09 17:00:00,0.068059045\r\n2014-07-09 17:05:00,0.0\r\n2014-07-09 17:15:00,0.06533578799999999\r\n2014-07-09 17:20:00,0.06522328299999999\r\n2014-07-09 17:25:00,0.06660350400000001\r\n2014-07-09 17:30:00,0.064493822\r\n2014-07-09 17:35:00,0.063759473\r\n2014-07-09 17:40:00,0.0\r\n2014-07-09 17:45:00,0.078130967\r\n2014-07-09 17:50:00,0.065035345\r\n2014-07-09 17:55:00,0.07328794799999999\r\n2014-07-09 18:00:00,0.078835874\r\n2014-07-09 18:05:00,0.061821222\r\n2014-07-09 18:10:00,0.058587455\r\n2014-07-09 18:15:00,0.072103732\r\n2014-07-09 18:20:00,0.06053375\r\n2014-07-09 18:25:00,0.07560126\r\n2014-07-09 18:30:00,0.06640715900000001\r\n2014-07-09 18:35:00,0.066940445\r\n2014-07-09 18:40:00,0.067622642\r\n2014-07-09 18:45:00,0.06494316\r\n2014-07-09 18:50:00,0.07410472\r\n2014-07-09 18:55:00,0.0\r\n2014-07-09 19:25:00,0.0\r\n2014-07-09 19:45:00,0.076853483\r\n2014-07-09 19:50:00,0.075200748\r\n2014-07-09 19:55:00,0.07226239599999999\r\n2014-07-09 20:00:00,0.07267715599999999\r\n2014-07-09 20:05:00,0.0\r\n2014-07-09 20:10:00,0.074125749\r\n2014-07-09 20:15:00,0.071203032\r\n2014-07-09 20:20:00,0.076607068\r\n2014-07-09 20:25:00,0.0\r\n2014-07-09 20:30:00,0.0\r\n2014-07-09 20:40:00,0.072540702\r\n2014-07-09 20:45:00,0.0\r\n2014-07-09 20:50:00,0.0\r\n2014-07-09 21:00:00,0.072589764\r\n2014-07-09 21:05:00,0.073043263\r\n2014-07-09 21:10:00,0.071478658\r\n2014-07-09 21:15:00,0.06925759\r\n2014-07-09 21:20:00,0.074117643\r\n2014-07-09 21:25:00,0.083657749\r\n2014-07-09 21:30:00,0.100010991\r\n2014-07-09 21:35:00,0.08167639900000001\r\n2014-07-09 21:40:00,0.06905876\r\n2014-07-09 21:45:00,0.076641826\r\n2014-07-09 21:50:00,0.065264078\r\n2014-07-09 21:55:00,0.06151601900000001\r\n2014-07-09 22:00:00,0.064245564\r\n2014-07-09 22:05:00,0.067416084\r\n2014-07-09 22:10:00,0.065174883\r\n2014-07-09 22:15:00,0.063981892\r\n2014-07-09 22:20:00,0.070781631\r\n2014-07-09 22:25:00,0.07091886\r\n2014-07-09 22:30:00,0.072767741\r\n2014-07-09 22:35:00,0.06628128400000001\r\n2014-07-09 22:40:00,0.068282272\r\n2014-07-09 22:45:00,0.072731916\r\n2014-07-09 22:50:00,0.531583598\r\n2014-07-09 22:55:00,0.0\r\n2014-07-10 20:05:00,0.06758560000000001\r\n2014-07-10 20:10:00,0.069346799\r\n2014-07-10 20:15:00,0.069808377\r\n2014-07-10 20:20:00,0.064024417\r\n2014-07-10 20:25:00,0.059894006\r\n2014-07-10 20:30:00,0.0\r\n2014-07-10 20:35:00,0.052889268\r\n2014-07-10 20:40:00,0.069996505\r\n2014-07-10 20:45:00,0.090819702\r\n2014-07-10 20:50:00,0.092357278\r\n2014-07-10 20:55:00,0.073224392\r\n2014-07-10 21:00:00,0.074288471\r\n2014-07-10 21:05:00,0.08014450599999999\r\n2014-07-10 21:10:00,0.096451795\r\n2014-07-10 21:15:00,0.08249667299999999\r\n2014-07-10 21:20:00,0.06315431\r\n2014-07-10 21:25:00,0.062846261\r\n2014-07-10 21:30:00,0.067098234\r\n2014-07-10 21:35:00,0.070040669\r\n2014-07-10 21:40:00,0.151596686\r\n2014-07-10 21:45:00,0.075223056\r\n2014-07-10 21:50:00,0.07014687\r\n2014-07-10 21:55:00,0.06984607\r\n2014-07-10 22:00:00,0.0\r\n2014-07-10 22:05:00,0.067074281\r\n2014-07-10 22:10:00,0.069360377\r\n2014-07-10 22:15:00,0.06914248\r\n2014-07-10 22:20:00,0.070213866\r\n2014-07-10 22:25:00,0.076050628\r\n2014-07-10 22:30:00,0.086771271\r\n2014-07-10 22:35:00,0.072209089\r\n2014-07-10 22:45:00,0.063050624\r\n2014-07-10 22:50:00,0.07327640099999999\r\n2014-07-10 22:55:00,0.07553544\r\n2014-07-10 23:00:00,0.071689969\r\n2014-07-10 23:05:00,0.070439837\r\n2014-07-10 23:10:00,0.063566086\r\n2014-07-10 23:15:00,0.059849366\r\n2014-07-10 23:20:00,0.061594495\r\n2014-07-10 23:25:00,0.066851831\r\n2014-07-10 23:30:00,0.062975055\r\n2014-07-10 23:35:00,0.06460803700000001\r\n2014-07-10 23:40:00,0.061033292\r\n2014-07-10 23:45:00,0.06339773900000001\r\n2014-07-10 23:50:00,0.059772211\r\n2014-07-10 23:55:00,0.068874465\r\n2014-07-11 00:00:00,0.082920038\r\n2014-07-11 00:05:00,0.08584952400000001\r\n2014-07-11 00:10:00,0.0\r\n2014-07-11 00:15:00,0.0\r\n2014-07-11 00:35:00,0.117173433\r\n2014-07-11 00:40:00,0.05802717\r\n2014-07-11 00:45:00,0.0\r\n2014-07-11 01:20:00,0.0\r\n2014-07-11 01:30:00,0.110067689\r\n2014-07-11 01:35:00,0.113982558\r\n2014-07-11 01:40:00,0.0\r\n2014-07-11 01:45:00,0.0\r\n2014-07-11 01:50:00,0.0\r\n2014-07-11 01:55:00,0.0\r\n2014-07-11 02:00:00,0.0\r\n2014-07-11 02:05:00,0.0\r\n2014-07-11 02:10:00,0.0\r\n2014-07-11 02:15:00,0.0\r\n2014-07-11 02:20:00,0.0\r\n2014-07-11 02:25:00,0.0\r\n2014-07-11 02:30:00,0.0\r\n2014-07-11 02:35:00,0.0\r\n2014-07-11 02:40:00,0.0\r\n2014-07-11 02:45:00,0.0\r\n2014-07-11 02:50:00,0.0\r\n2014-07-11 02:55:00,0.0\r\n2014-07-11 03:00:00,0.0\r\n2014-07-11 03:05:00,0.0\r\n2014-07-11 03:10:00,0.0\r\n2014-07-11 03:15:00,0.0\r\n2014-07-11 03:20:00,0.0\r\n2014-07-11 03:25:00,0.0\r\n2014-07-11 03:35:00,0.0\r\n2014-07-11 03:40:00,0.0\r\n2014-07-11 03:45:00,0.0\r\n2014-07-11 03:50:00,0.0\r\n2014-07-11 07:30:00,0.03192997\r\n2014-07-11 07:35:00,0.0\r\n2014-07-11 07:40:00,0.0\r\n2014-07-11 07:45:00,0.0\r\n2014-07-11 07:50:00,0.0\r\n2014-07-11 07:55:00,0.0\r\n2014-07-11 08:00:00,0.0\r\n2014-07-11 08:05:00,0.0\r\n2014-07-11 08:10:00,0.0\r\n2014-07-11 08:15:00,0.0\r\n2014-07-11 08:20:00,0.0\r\n2014-07-11 08:25:00,0.0\r\n2014-07-11 08:35:00,0.0\r\n2014-07-11 08:40:00,0.0\r\n2014-07-11 08:45:00,0.0\r\n2014-07-11 08:50:00,0.0\r\n2014-07-11 08:55:00,0.0\r\n2014-07-11 09:00:00,0.0\r\n2014-07-11 09:05:00,0.0\r\n2014-07-11 09:10:00,0.0\r\n2014-07-11 09:15:00,0.0\r\n2014-07-11 09:20:00,0.0\r\n2014-07-11 09:25:00,0.0\r\n2014-07-11 09:30:00,0.0\r\n2014-07-11 09:35:00,0.0\r\n2014-07-11 09:40:00,0.0\r\n2014-07-11 09:45:00,0.0\r\n2014-07-11 09:50:00,0.0\r\n2014-07-11 09:55:00,0.0\r\n2014-07-11 10:00:00,0.0\r\n2014-07-11 10:05:00,0.0\r\n2014-07-11 10:10:00,0.0\r\n2014-07-11 10:15:00,0.0\r\n2014-07-11 10:20:00,0.0\r\n2014-07-11 10:30:00,0.0\r\n2014-07-11 10:35:00,0.0\r\n2014-07-11 10:40:00,0.0\r\n2014-07-11 10:45:00,0.0\r\n2014-07-11 10:50:00,0.0\r\n2014-07-11 10:55:00,0.0\r\n2014-07-11 11:00:00,0.0\r\n2014-07-11 11:05:00,0.0\r\n2014-07-11 11:10:00,0.0\r\n2014-07-11 11:15:00,0.0\r\n2014-07-11 11:20:00,0.0\r\n2014-07-11 11:25:00,0.0\r\n2014-07-11 11:30:00,0.0\r\n2014-07-11 11:35:00,0.0\r\n2014-07-11 11:40:00,0.0\r\n2014-07-11 11:45:00,0.0\r\n2014-07-11 11:50:00,0.0\r\n2014-07-11 11:55:00,0.0\r\n2014-07-11 12:00:00,0.0\r\n2014-07-11 12:05:00,0.0\r\n2014-07-11 12:10:00,0.0\r\n2014-07-11 12:15:00,0.0\r\n2014-07-11 12:20:00,0.0\r\n2014-07-11 12:25:00,0.0\r\n2014-07-11 12:30:00,0.0\r\n2014-07-11 12:35:00,0.0\r\n2014-07-11 12:45:00,0.0\r\n2014-07-11 12:50:00,0.0\r\n2014-07-11 12:55:00,0.0\r\n2014-07-11 13:00:00,0.0\r\n2014-07-11 13:05:00,0.0\r\n2014-07-11 13:10:00,0.0\r\n2014-07-11 13:15:00,0.0\r\n2014-07-11 13:20:00,0.0\r\n2014-07-11 13:25:00,0.0\r\n2014-07-11 13:30:00,0.0\r\n2014-07-11 13:35:00,0.0\r\n2014-07-11 13:40:00,0.0\r\n2014-07-11 13:45:00,0.0\r\n2014-07-11 13:50:00,0.0\r\n2014-07-11 13:55:00,0.0\r\n2014-07-11 14:00:00,0.0\r\n2014-07-11 14:05:00,0.0\r\n2014-07-11 14:10:00,0.0\r\n2014-07-11 14:15:00,0.0\r\n2014-07-11 14:20:00,0.0\r\n2014-07-11 14:25:00,0.0\r\n2014-07-11 14:30:00,0.0\r\n2014-07-11 14:35:00,0.0\r\n2014-07-11 14:45:00,0.0\r\n2014-07-11 14:50:00,0.0\r\n2014-07-11 14:55:00,0.0\r\n2014-07-11 15:00:00,0.0\r\n2014-07-11 15:05:00,0.0\r\n2014-07-11 15:10:00,0.0\r\n2014-07-11 15:15:00,0.0\r\n2014-07-11 15:20:00,0.0\r\n2014-07-11 16:10:00,0.09863162\r\n2014-07-11 16:15:00,0.08272386\r\n2014-07-11 16:20:00,0.085230736\r\n2014-07-11 16:25:00,0.06826363\r\n2014-07-11 16:30:00,0.082736923\r\n2014-07-11 16:35:00,0.073087134\r\n2014-07-11 16:40:00,0.06398754\r\n2014-07-11 16:45:00,0.07573959200000001\r\n2014-07-11 16:50:00,0.06987537\r\n2014-07-11 16:55:00,0.069682799\r\n2014-07-11 17:00:00,0.073080403\r\n2014-07-11 17:05:00,0.0\r\n2014-07-11 17:15:00,0.894877604\r\n2014-07-11 17:20:00,0.08934301300000001\r\n2014-07-11 17:25:00,0.065345519\r\n2014-07-11 17:30:00,0.067827237\r\n2014-07-11 17:35:00,0.0\r\n2014-07-11 18:10:00,0.07592336599999999\r\n2014-07-11 18:15:00,0.063932613\r\n2014-07-11 18:20:00,0.08958878199999999\r\n2014-07-11 18:25:00,0.085891063\r\n2014-07-11 18:30:00,0.067534644\r\n2014-07-11 18:35:00,0.07018377599999999\r\n2014-07-11 18:40:00,0.069429169\r\n2014-07-11 18:45:00,0.073223894\r\n2014-07-11 18:50:00,0.066217605\r\n2014-07-11 18:55:00,0.062421981\r\n2014-07-11 19:00:00,0.07063684\r\n2014-07-11 19:05:00,0.068916717\r\n2014-07-11 19:10:00,0.064045422\r\n2014-07-11 19:15:00,0.06963963\r\n2014-07-11 19:20:00,0.070939419\r\n2014-07-11 19:25:00,0.06970957900000001\r\n2014-07-11 19:30:00,0.068598365\r\n2014-07-11 19:35:00,0.0\r\n2014-07-11 20:10:00,0.0\r\n2014-07-11 20:20:00,0.063635359\r\n2014-07-11 20:25:00,0.06422909\r\n2014-07-11 20:30:00,0.070774645\r\n2014-07-11 20:35:00,0.068035847\r\n2014-07-11 20:40:00,0.071887277\r\n2014-07-11 20:45:00,0.066371174\r\n2014-07-11 20:50:00,0.073693152\r\n2014-07-11 20:55:00,0.074337182\r\n2014-07-11 21:00:00,0.081452785\r\n2014-07-11 21:05:00,0.080226873\r\n2014-07-11 21:10:00,0.075866301\r\n2014-07-11 21:15:00,0.082649088\r\n2014-07-11 21:20:00,0.067151591\r\n2014-07-11 21:25:00,0.071230778\r\n2014-07-11 21:30:00,0.064547304\r\n2014-07-11 21:35:00,0.058622577\r\n2014-07-11 21:40:00,0.061547310999999987\r\n2014-07-11 21:45:00,0.062709794\r\n2014-07-11 21:50:00,0.076483583\r\n2014-07-11 21:55:00,0.066729108\r\n2014-07-11 22:00:00,0.070420094\r\n2014-07-11 22:05:00,0.087912241\r\n2014-07-11 22:10:00,0.0\r\n2014-07-11 22:15:00,0.065736168\r\n2014-07-11 22:20:00,0.070528229\r\n2014-07-11 22:25:00,0.07141012599999999\r\n2014-07-11 22:30:00,0.0\r\n2014-07-11 22:35:00,0.071144378\r\n2014-07-11 22:40:00,0.07158130900000001\r\n2014-07-11 22:45:00,0.081845461\r\n2014-07-11 22:50:00,0.077930015\r\n2014-07-11 22:55:00,0.077977317\r\n2014-07-11 23:00:00,0.086169364\r\n2014-07-11 23:05:00,0.083144763\r\n2014-07-11 23:10:00,0.058807518\r\n2014-07-11 23:15:00,0.082003931\r\n2014-07-11 23:20:00,0.07838690799999999\r\n2014-07-11 23:25:00,0.072364739\r\n2014-07-11 23:30:00,0.075285607\r\n2014-07-11 23:35:00,0.076338906\r\n2014-07-11 23:40:00,0.069559493\r\n2014-07-11 23:45:00,0.079055729\r\n2014-07-11 23:50:00,0.064776535\r\n2014-07-11 23:55:00,0.0\r\n2014-07-12 00:00:00,0.06512030099999999\r\n2014-07-12 00:05:00,0.081144121\r\n2014-07-12 00:10:00,0.069493738\r\n2014-07-12 00:15:00,0.07132172\r\n2014-07-12 00:20:00,0.08174910099999999\r\n2014-07-12 00:25:00,0.08094678200000001\r\n2014-07-12 00:30:00,0.043550134\r\n2014-07-12 00:35:00,0.071189478\r\n2014-07-12 00:40:00,0.07651633299999999\r\n2014-07-12 00:45:00,0.07223233700000001\r\n2014-07-12 00:50:00,0.07577371299999999\r\n2014-07-12 00:55:00,0.072497933\r\n2014-07-12 01:00:00,0.078945033\r\n2014-07-12 01:05:00,0.066033045\r\n2014-07-12 01:10:00,0.071879928\r\n2014-07-12 01:15:00,0.064920046\r\n2014-07-12 01:20:00,0.07239877900000001\r\n2014-07-12 01:25:00,0.061562998\r\n2014-07-12 01:30:00,0.075128839\r\n2014-07-12 18:10:00,0.07235504799999999\r\n2014-07-12 18:15:00,0.07390092\r\n2014-07-12 18:20:00,0.064606555\r\n2014-07-12 18:25:00,0.063249826\r\n2014-07-12 18:30:00,0.079823196\r\n2014-07-12 18:35:00,0.0\r\n2014-07-14 16:10:00,0.066142584\r\n2014-07-14 16:15:00,0.082683495\r\n2014-07-14 16:20:00,0.121088107\r\n2014-07-14 16:25:00,0.078241639\r\n2014-07-14 16:30:00,0.11917909\r\n2014-07-14 16:35:00,0.082868306\r\n2014-07-14 16:40:00,0.077474031\r\n2014-07-14 16:45:00,0.076853245\r\n2014-07-14 16:50:00,0.06721400200000001\r\n2014-07-14 16:55:00,0.0\r\n2014-07-14 17:00:00,0.0\r\n2014-07-14 17:05:00,0.06624467099999999\r\n2014-07-14 17:10:00,0.076446056\r\n2014-07-14 17:15:00,0.0832685\r\n2014-07-14 17:20:00,0.084635518\r\n2014-07-14 17:25:00,0.070059102\r\n2014-07-14 17:30:00,0.0\r\n2014-07-14 17:35:00,0.0843253\r\n2014-07-14 17:40:00,0.090023782\r\n2014-07-14 17:45:00,0.086879535\r\n2014-07-14 17:50:00,0.096119506\r\n2014-07-14 17:55:00,0.087577124\r\n2014-07-14 18:15:00,0.0\r\n2014-07-14 18:20:00,0.0\r\n2014-07-14 18:25:00,0.0\r\n2014-07-14 18:30:00,0.0\r\n2014-07-14 18:35:00,0.0\r\n2014-07-14 18:40:00,0.0\r\n2014-07-14 18:45:00,0.0\r\n2014-07-14 18:50:00,0.0\r\n2014-07-14 18:55:00,0.0\r\n2014-07-14 19:00:00,0.0\r\n2014-07-14 19:05:00,0.0\r\n2014-07-14 19:10:00,0.0\r\n2014-07-14 19:15:00,0.0\r\n2014-07-14 19:20:00,0.0\r\n2014-07-14 19:25:00,0.0\r\n2014-07-14 19:30:00,0.0\r\n2014-07-14 19:40:00,0.0\r\n2014-07-14 19:45:00,0.099778858\r\n2014-07-14 19:50:00,0.0\r\n2014-07-14 19:55:00,0.0\r\n2014-07-14 20:00:00,0.0\r\n2014-07-14 20:05:00,0.0\r\n2014-07-14 20:10:00,0.109809041\r\n2014-07-14 20:15:00,0.0\r\n2014-07-14 20:20:00,0.0\r\n2014-07-14 20:30:00,0.08800430599999999\r\n2014-07-14 20:35:00,0.0\r\n2014-07-14 20:40:00,0.0\r\n2014-07-14 20:45:00,0.0\r\n2014-07-14 20:50:00,0.0\r\n2014-07-14 20:55:00,0.0\r\n2014-07-14 21:00:00,0.0\r\n2014-07-14 21:05:00,0.085474809\r\n2014-07-14 21:10:00,0.0\r\n2014-07-14 21:15:00,0.0\r\n2014-07-14 21:20:00,0.0\r\n2014-07-14 21:25:00,0.0\r\n2014-07-14 21:30:00,0.0\r\n2014-07-14 21:35:00,0.0\r\n2014-07-14 21:40:00,0.0\r\n2014-07-14 21:45:00,0.0\r\n2014-07-14 21:50:00,0.0\r\n2014-07-14 21:55:00,0.0\r\n2014-07-14 22:00:00,0.0\r\n2014-07-14 22:05:00,0.0\r\n2014-07-14 22:10:00,0.0\r\n2014-07-14 22:15:00,0.0\r\n2014-07-14 22:20:00,0.0\r\n2014-07-14 22:25:00,0.0\r\n2014-07-14 22:30:00,0.0\r\n2014-07-14 22:35:00,0.0\r\n2014-07-14 22:40:00,0.0\r\n2014-07-14 22:45:00,0.0\r\n2014-07-14 22:50:00,0.0\r\n2014-07-14 22:55:00,0.0\r\n2014-07-14 23:00:00,0.0\r\n2014-07-14 23:05:00,0.0\r\n2014-07-14 23:10:00,0.0\r\n2014-07-14 23:15:00,0.0\r\n2014-07-14 23:20:00,0.0\r\n2014-07-14 23:25:00,0.0\r\n2014-07-14 23:30:00,0.0\r\n2014-07-14 23:35:00,0.0\r\n2014-07-14 23:40:00,0.0\r\n2014-07-14 23:45:00,0.0\r\n2014-07-14 23:50:00,0.0\r\n2014-07-14 23:55:00,0.0\r\n2014-07-15 00:00:00,0.0\r\n2014-07-15 00:05:00,0.113392589\r\n2014-07-15 00:10:00,0.153085695\r\n2014-07-15 00:15:00,0.0\r\n2014-07-15 00:20:00,0.0\r\n2014-07-15 00:25:00,0.0\r\n2014-07-15 00:30:00,0.08191084900000001\r\n2014-07-15 00:35:00,0.0\r\n2014-07-15 00:40:00,0.0\r\n2014-07-15 00:45:00,0.0\r\n2014-07-15 00:50:00,0.0\r\n2014-07-15 00:55:00,0.0\r\n2014-07-15 01:00:00,0.0\r\n2014-07-15 01:05:00,0.0\r\n2014-07-15 01:10:00,0.0\r\n2014-07-15 01:15:00,0.0\r\n2014-07-15 01:20:00,0.0\r\n2014-07-15 01:25:00,0.0\r\n2014-07-15 01:30:00,0.0\r\n2014-07-15 01:35:00,0.0\r\n2014-07-15 01:40:00,0.0\r\n2014-07-15 01:45:00,0.0\r\n2014-07-15 01:50:00,0.0\r\n2014-07-15 01:55:00,0.0\r\n2014-07-15 02:00:00,0.0\r\n2014-07-15 02:05:00,0.0\r\n2014-07-15 02:10:00,0.0\r\n2014-07-15 02:15:00,0.0\r\n2014-07-15 02:20:00,0.0\r\n2014-07-15 02:25:00,0.0\r\n2014-07-15 02:30:00,0.0\r\n2014-07-15 02:35:00,0.0\r\n2014-07-15 02:40:00,0.0\r\n2014-07-15 02:45:00,0.0\r\n2014-07-15 02:50:00,0.0\r\n2014-07-15 02:55:00,0.0\r\n2014-07-15 03:00:00,0.0\r\n2014-07-15 03:05:00,0.0\r\n2014-07-15 03:10:00,0.0\r\n2014-07-15 03:15:00,0.0\r\n2014-07-15 03:20:00,0.0\r\n2014-07-15 03:25:00,0.0\r\n2014-07-15 03:30:00,0.0\r\n2014-07-15 03:35:00,0.0\r\n2014-07-15 03:40:00,0.0\r\n2014-07-15 03:45:00,0.0\r\n2014-07-15 03:50:00,0.0\r\n2014-07-15 03:55:00,0.0\r\n2014-07-15 04:00:00,0.0\r\n2014-07-15 04:05:00,0.0\r\n2014-07-15 04:10:00,0.0\r\n2014-07-15 04:15:00,0.0\r\n2014-07-15 04:20:00,0.0\r\n2014-07-15 04:25:00,0.0\r\n2014-07-15 04:30:00,0.0\r\n2014-07-15 04:35:00,0.0\r\n2014-07-15 04:40:00,0.0\r\n2014-07-15 04:45:00,0.0\r\n2014-07-15 04:50:00,0.0\r\n2014-07-15 04:55:00,0.0\r\n2014-07-15 05:00:00,0.0\r\n2014-07-15 05:05:00,0.0\r\n2014-07-15 05:10:00,0.0\r\n2014-07-15 05:15:00,0.0\r\n2014-07-15 05:20:00,0.0\r\n2014-07-15 05:25:00,0.0\r\n2014-07-15 05:30:00,0.0\r\n2014-07-15 05:35:00,0.0\r\n2014-07-15 05:40:00,0.0\r\n2014-07-15 05:45:00,0.0\r\n2014-07-15 05:50:00,0.0\r\n2014-07-15 05:55:00,0.0\r\n2014-07-15 06:00:00,0.0\r\n2014-07-15 06:05:00,0.0\r\n2014-07-15 06:10:00,0.0\r\n2014-07-15 06:15:00,0.0\r\n2014-07-15 06:20:00,0.0\r\n2014-07-15 06:25:00,0.0\r\n2014-07-15 06:30:00,0.0\r\n2014-07-15 06:35:00,0.0\r\n2014-07-15 06:40:00,0.0\r\n2014-07-15 06:45:00,0.0\r\n2014-07-15 06:50:00,0.0\r\n2014-07-15 06:55:00,0.0\r\n2014-07-15 07:00:00,0.0\r\n2014-07-15 07:05:00,0.0\r\n2014-07-15 07:10:00,0.0\r\n2014-07-15 07:15:00,0.0\r\n2014-07-15 07:20:00,0.0\r\n2014-07-15 07:25:00,0.0\r\n2014-07-15 07:30:00,0.0\r\n2014-07-15 07:35:00,0.0\r\n2014-07-15 07:40:00,0.0\r\n2014-07-15 07:45:00,0.0\r\n2014-07-15 07:50:00,0.0\r\n2014-07-15 07:55:00,0.0\r\n2014-07-15 08:00:00,0.0\r\n2014-07-15 08:05:00,0.0\r\n2014-07-15 08:10:00,0.0\r\n2014-07-15 08:15:00,0.0\r\n2014-07-15 08:20:00,0.0\r\n2014-07-15 08:25:00,0.0\r\n2014-07-15 08:30:00,0.0\r\n2014-07-15 08:35:00,0.0\r\n2014-07-15 08:40:00,0.0\r\n2014-07-15 08:45:00,0.0\r\n2014-07-15 08:50:00,0.0\r\n2014-07-15 08:55:00,0.0\r\n2014-07-15 09:00:00,0.0\r\n2014-07-15 09:05:00,0.0\r\n2014-07-15 09:10:00,0.0\r\n2014-07-15 09:15:00,0.0\r\n2014-07-15 09:20:00,0.0\r\n2014-07-15 09:25:00,0.0\r\n2014-07-15 09:30:00,0.0\r\n2014-07-15 09:35:00,0.0\r\n2014-07-15 09:40:00,0.0\r\n2014-07-15 09:45:00,0.0\r\n2014-07-15 09:50:00,0.0\r\n2014-07-15 09:55:00,0.0\r\n2014-07-15 10:05:00,0.074724019\r\n2014-07-15 10:40:00,0.081010018\r\n2014-07-15 10:45:00,0.072983488\r\n2014-07-15 10:50:00,0.08618763900000001\r\n2014-07-15 10:55:00,0.081845165\r\n2014-07-15 11:20:00,0.087103692\r\n2014-07-15 11:25:00,0.084364615\r\n2014-07-15 11:30:00,0.095506993\r\n2014-07-15 11:35:00,0.065466642\r\n2014-07-15 11:40:00,0.089246559\r\n2014-07-15 11:45:00,0.067008018\r\n2014-07-15 11:55:00,0.091611182\r\n2014-07-15 12:00:00,0.078721786\r\n2014-07-15 12:05:00,0.0\r\n2014-07-15 12:10:00,0.082381546\r\n2014-07-15 12:15:00,0.116034985\r\n2014-07-15 12:20:00,0.0\r\n2014-07-15 12:25:00,0.084316413\r\n2014-07-15 12:30:00,0.08645440900000001\r\n2014-07-15 12:35:00,0.085921212\r\n2014-07-15 12:40:00,0.0\r\n2014-07-15 12:45:00,0.078981244\r\n2014-07-15 12:50:00,0.071727986\r\n2014-07-15 12:55:00,0.08374694\r\n2014-07-15 13:00:00,0.127655029\r\n2014-07-15 13:05:00,0.07211113799999999\r\n2014-07-15 13:10:00,0.070604499\r\n2014-07-15 13:15:00,0.070273212\r\n2014-07-15 13:20:00,0.068471751\r\n2014-07-15 13:25:00,0.086299364\r\n2014-07-15 13:30:00,0.0\r\n2014-07-15 13:35:00,0.0\r\n2014-07-15 13:40:00,0.077449515\r\n2014-07-15 13:45:00,0.067616585\r\n2014-07-15 13:50:00,0.078807843\r\n2014-07-15 13:55:00,0.07274336299999999\r\n2014-07-15 14:00:00,0.0\r\n2014-07-15 14:05:00,0.0\r\n2014-07-15 14:10:00,0.0\r\n2014-07-15 14:15:00,0.0\r\n2014-07-15 14:25:00,0.080492813\r\n2014-07-15 14:30:00,0.07925586700000001\r\n2014-07-15 14:35:00,0.099784017\r\n2014-07-15 14:40:00,0.094524997\r\n2014-07-15 14:45:00,0.0\r\n2014-07-15 14:50:00,0.0\r\n2014-07-15 14:55:00,0.0\r\n2014-07-15 15:00:00,0.148122787\r\n2014-07-15 15:05:00,0.089310208\r\n2014-07-15 15:10:00,0.072272571\r\n2014-07-15 15:15:00,0.076298205\r\n2014-07-15 15:20:00,0.072686692\r\n2014-07-15 15:25:00,0.08762771800000001\r\n2014-07-15 15:30:00,0.09528804\r\n2014-07-15 15:35:00,0.08145366400000001\r\n2014-07-15 15:40:00,0.079814911\r\n2014-07-15 15:45:00,0.094125643\r\n2014-07-15 15:50:00,0.083192171\r\n2014-07-15 15:55:00,0.08591253300000001\r\n2014-07-15 16:00:00,0.084625536\r\n2014-07-15 16:05:00,0.082236197\r\n2014-07-15 16:10:00,0.08890311199999999\r\n2014-07-15 16:15:00,0.085081768\r\n2014-07-15 16:20:00,0.079566366\r\n2014-07-15 16:25:00,0.073478292\r\n2014-07-15 16:30:00,0.072119777\r\n2014-07-15 16:35:00,0.08529961\r\n2014-07-15 16:45:00,0.0\r\n2014-07-15 16:50:00,0.0\r\n2014-07-15 16:55:00,0.0\r\n2014-07-15 17:00:00,0.0\r\n2014-07-15 17:05:00,0.0\r\n2014-07-15 17:10:00,0.0\r\n2014-07-15 17:15:00,0.0\r\n2014-07-15 17:20:00,0.0\r\n2014-07-15 17:25:00,0.078008972\r\n2014-07-15 17:30:00,0.111104952\r\n2014-07-15 17:35:00,0.087882042\r\n2014-07-15 17:40:00,0.068434081\r\n2014-07-15 17:45:00,0.0\r\n2014-07-15 17:50:00,0.0\r\n2014-07-15 17:55:00,0.114406149\r\n2014-07-15 18:00:00,0.063544533\r\n2014-07-15 18:05:00,0.0\r\n2014-07-15 18:10:00,0.0\r\n2014-07-15 18:15:00,0.06955913\r\n2014-07-15 18:20:00,0.069773555\r\n2014-07-15 18:25:00,0.068620113\r\n2014-07-15 18:30:00,0.07671086099999999\r\n2014-07-15 18:35:00,0.07475174400000001\r\n2014-07-15 18:40:00,0.07469165900000001\r\n2014-07-15 18:45:00,0.080636783\r\n2014-07-15 18:50:00,0.073058015\r\n2014-07-15 18:55:00,0.069489793\r\n2014-07-15 19:00:00,0.072557135\r\n2014-07-15 19:05:00,0.073479031\r\n2014-07-15 19:10:00,0.071080778\r\n2014-07-15 19:15:00,0.071638993\r\n2014-07-15 19:20:00,0.07121422\r\n2014-07-15 19:25:00,0.075122619\r\n2014-07-15 19:30:00,0.08179059\r\n2014-07-15 19:35:00,0.071841574\r\n2014-07-15 19:40:00,0.137128337\r\n2014-07-15 19:45:00,0.0\r\n2014-07-15 19:50:00,0.0\r\n2014-07-15 19:55:00,0.0\r\n2014-07-15 20:05:00,0.06297117299999999\r\n2014-07-15 20:10:00,0.0\r\n2014-07-15 20:15:00,0.0\r\n2014-07-15 20:25:00,0.0\r\n2014-07-15 20:30:00,0.0\r\n2014-07-15 20:35:00,0.0\r\n2014-07-15 20:40:00,0.0\r\n2014-07-15 20:45:00,0.0\r\n2014-07-15 20:50:00,0.0\r\n2014-07-15 20:55:00,0.0\r\n2014-07-15 21:00:00,0.0\r\n2014-07-15 21:05:00,0.0\r\n2014-07-15 21:10:00,0.0\r\n2014-07-15 21:15:00,0.0\r\n2014-07-15 21:20:00,0.0\r\n2014-07-15 21:25:00,0.0\r\n2014-07-15 21:30:00,0.0\r\n2014-07-15 21:35:00,0.0\r\n2014-07-15 21:40:00,0.0\r\n2014-07-15 21:45:00,0.0\r\n2014-07-15 21:50:00,0.0\r\n2014-07-15 21:55:00,0.0\r\n2014-07-15 22:00:00,0.0\r\n2014-07-15 22:05:00,0.0\r\n2014-07-15 22:10:00,0.0\r\n2014-07-15 22:15:00,0.0\r\n2014-07-15 22:20:00,0.0\r\n2014-07-15 22:25:00,0.0\r\n2014-07-15 22:30:00,0.0\r\n2014-07-15 22:35:00,0.0\r\n2014-07-15 22:40:00,0.0\r\n2014-07-15 22:45:00,0.0\r\n2014-07-15 22:50:00,0.0\r\n2014-07-15 22:55:00,0.0\r\n2014-07-15 23:00:00,0.0\r\n2014-07-15 23:05:00,0.0\r\n2014-07-15 23:10:00,0.0\r\n2014-07-15 23:15:00,0.0\r\n2014-07-15 23:20:00,0.0\r\n2014-07-15 23:25:00,0.0\r\n2014-07-15 23:30:00,0.08347703\r\n2014-07-15 23:35:00,0.0\r\n2014-07-15 23:40:00,0.0\r\n2014-07-15 23:45:00,0.0\r\n2014-07-15 23:50:00,0.0\r\n2014-07-15 23:55:00,0.0\r\n2014-07-16 00:00:00,0.0\r\n2014-07-16 00:05:00,0.0\r\n2014-07-16 00:10:00,0.0\r\n2014-07-16 00:15:00,0.0\r\n2014-07-16 00:20:00,0.0\r\n2014-07-16 00:25:00,0.0\r\n2014-07-16 00:30:00,0.0\r\n2014-07-16 00:35:00,0.0\r\n2014-07-16 00:40:00,0.0\r\n2014-07-16 00:45:00,0.0\r\n2014-07-16 00:50:00,0.0\r\n2014-07-16 00:55:00,0.0\r\n2014-07-16 01:00:00,0.0\r\n2014-07-16 01:05:00,0.0\r\n2014-07-16 01:10:00,0.0\r\n2014-07-16 01:15:00,0.0\r\n2014-07-16 01:20:00,0.0\r\n2014-07-16 01:25:00,0.0\r\n2014-07-16 01:30:00,0.0\r\n2014-07-16 01:35:00,0.0\r\n2014-07-16 01:40:00,0.0\r\n2014-07-16 01:45:00,0.0\r\n2014-07-16 01:50:00,0.0\r\n2014-07-16 01:55:00,0.0\r\n2014-07-16 02:00:00,0.0\r\n2014-07-16 02:05:00,0.0\r\n2014-07-16 02:10:00,0.0\r\n2014-07-16 02:15:00,0.0\r\n2014-07-16 02:20:00,0.0\r\n2014-07-16 02:25:00,0.0\r\n2014-07-16 02:30:00,0.0\r\n2014-07-16 02:35:00,0.0\r\n2014-07-16 02:40:00,0.0\r\n2014-07-16 02:45:00,0.0\r\n2014-07-16 02:50:00,0.0\r\n2014-07-16 02:55:00,0.0\r\n2014-07-16 03:00:00,0.0\r\n2014-07-16 03:05:00,0.0\r\n2014-07-16 03:10:00,0.0\r\n2014-07-16 03:15:00,0.0\r\n2014-07-16 03:20:00,0.0\r\n2014-07-16 03:25:00,0.0\r\n2014-07-16 03:30:00,0.0\r\n2014-07-16 03:35:00,0.0\r\n2014-07-16 03:40:00,0.0\r\n2014-07-16 03:45:00,0.0\r\n2014-07-16 03:50:00,0.0\r\n2014-07-16 03:55:00,0.0\r\n2014-07-16 04:00:00,0.0\r\n2014-07-16 04:05:00,0.0\r\n2014-07-16 04:10:00,0.0\r\n2014-07-16 04:15:00,0.0\r\n2014-07-16 04:20:00,0.0\r\n2014-07-16 04:25:00,0.0\r\n2014-07-16 04:30:00,0.0\r\n2014-07-16 04:35:00,0.0\r\n2014-07-16 04:40:00,0.0\r\n2014-07-16 04:45:00,0.0\r\n2014-07-16 04:50:00,0.0\r\n2014-07-16 04:55:00,0.0\r\n2014-07-16 05:00:00,0.0\r\n2014-07-16 05:05:00,0.0\r\n2014-07-16 05:10:00,0.0\r\n2014-07-16 05:15:00,0.0\r\n2014-07-16 05:20:00,0.0\r\n2014-07-16 05:25:00,0.0\r\n2014-07-16 05:30:00,0.0\r\n2014-07-16 05:35:00,0.0\r\n2014-07-16 05:40:00,0.0\r\n2014-07-16 05:45:00,0.0\r\n2014-07-16 05:50:00,0.0\r\n2014-07-16 05:55:00,0.0\r\n2014-07-16 06:00:00,0.0\r\n2014-07-16 06:05:00,0.0\r\n2014-07-16 06:10:00,0.0\r\n2014-07-16 06:15:00,0.0\r\n2014-07-16 06:20:00,0.0\r\n2014-07-16 06:25:00,0.0\r\n2014-07-16 06:30:00,0.0\r\n2014-07-16 06:35:00,0.0\r\n2014-07-16 06:40:00,0.0\r\n2014-07-16 06:45:00,0.0\r\n2014-07-16 06:50:00,0.0\r\n2014-07-16 06:55:00,0.0\r\n2014-07-16 07:00:00,0.0\r\n2014-07-16 07:05:00,0.0\r\n2014-07-16 07:10:00,0.0\r\n2014-07-16 07:15:00,0.0\r\n2014-07-16 07:20:00,0.0\r\n2014-07-16 07:25:00,0.0\r\n2014-07-16 07:30:00,0.0\r\n2014-07-16 07:35:00,0.0\r\n2014-07-16 07:40:00,0.0\r\n2014-07-16 07:45:00,0.0\r\n2014-07-16 07:50:00,0.0\r\n2014-07-16 07:55:00,0.0\r\n2014-07-16 08:00:00,0.0\r\n2014-07-16 08:05:00,0.0\r\n2014-07-16 08:10:00,0.0\r\n2014-07-16 08:15:00,0.0\r\n2014-07-16 08:20:00,0.0\r\n2014-07-16 08:25:00,0.0\r\n2014-07-16 08:30:00,0.0\r\n2014-07-16 08:35:00,0.0\r\n2014-07-16 08:40:00,0.0\r\n2014-07-16 08:45:00,0.0\r\n2014-07-16 08:50:00,0.0\r\n2014-07-16 08:55:00,0.0\r\n2014-07-16 09:00:00,0.0\r\n2014-07-16 09:05:00,0.0\r\n2014-07-16 09:10:00,0.0\r\n2014-07-16 09:15:00,0.0\r\n2014-07-16 09:20:00,0.0\r\n2014-07-16 09:25:00,0.0\r\n2014-07-16 09:30:00,0.0\r\n2014-07-16 09:35:00,0.0\r\n2014-07-16 09:40:00,0.0\r\n2014-07-16 09:45:00,0.0\r\n2014-07-16 09:50:00,0.0\r\n2014-07-16 09:55:00,0.0\r\n2014-07-16 10:00:00,0.0\r\n2014-07-16 10:05:00,0.0\r\n2014-07-16 10:10:00,0.0\r\n2014-07-16 10:15:00,0.0\r\n2014-07-16 10:20:00,0.076638222\r\n2014-07-16 10:25:00,0.0\r\n2014-07-16 10:30:00,0.0\r\n2014-07-16 10:35:00,0.0\r\n2014-07-16 10:40:00,0.0\r\n2014-07-16 10:45:00,0.0\r\n2014-07-16 10:50:00,0.0\r\n2014-07-16 10:55:00,0.0\r\n2014-07-16 11:00:00,0.0\r\n2014-07-16 11:05:00,0.0\r\n2014-07-16 11:10:00,0.0\r\n2014-07-16 11:15:00,0.0\r\n2014-07-16 11:20:00,0.0\r\n2014-07-16 11:25:00,0.0\r\n2014-07-16 11:30:00,0.0\r\n2014-07-16 11:35:00,0.0\r\n2014-07-16 11:40:00,0.0\r\n2014-07-16 11:45:00,0.0\r\n2014-07-16 11:50:00,0.0\r\n2014-07-16 11:55:00,0.0\r\n2014-07-16 12:00:00,0.0\r\n2014-07-16 12:05:00,0.0\r\n2014-07-16 12:10:00,0.0\r\n2014-07-16 12:15:00,0.0\r\n2014-07-16 12:20:00,0.0\r\n2014-07-16 12:25:00,0.0\r\n2014-07-16 12:30:00,0.0\r\n2014-07-16 12:35:00,0.0\r\n2014-07-16 12:40:00,0.0\r\n2014-07-16 12:45:00,0.0\r\n2014-07-16 12:50:00,0.0\r\n2014-07-16 12:55:00,0.0\r\n2014-07-16 13:00:00,0.0\r\n2014-07-16 13:05:00,0.0\r\n2014-07-16 13:10:00,0.0\r\n2014-07-16 13:15:00,0.0\r\n2014-07-16 13:20:00,0.0\r\n2014-07-16 13:25:00,0.0\r\n2014-07-16 13:30:00,0.0\r\n2014-07-16 13:35:00,0.0\r\n2014-07-16 13:40:00,0.0\r\n2014-07-16 13:45:00,0.0\r\n2014-07-16 13:50:00,0.0\r\n2014-07-16 13:55:00,0.0\r\n2014-07-16 14:00:00,0.0\r\n2014-07-16 14:05:00,0.0\r\n2014-07-16 14:10:00,0.0\r\n2014-07-16 14:15:00,0.0\r\n2014-07-16 14:20:00,0.0\r\n2014-07-16 14:25:00,0.0\r\n2014-07-16 14:30:00,0.0\r\n2014-07-16 14:35:00,0.0\r\n2014-07-16 14:40:00,0.0\r\n2014-07-16 14:45:00,0.0\r\n2014-07-16 14:50:00,0.0\r\n2014-07-16 14:55:00,0.0\r\n2014-07-16 15:00:00,0.0\r\n2014-07-16 15:05:00,0.0\r\n2014-07-16 15:10:00,0.0\r\n2014-07-16 15:15:00,0.0\r\n2014-07-16 15:20:00,0.0\r\n2014-07-16 15:25:00,0.0\r\n2014-07-16 15:30:00,0.0\r\n2014-07-16 15:35:00,0.0\r\n2014-07-16 15:40:00,0.0\r\n2014-07-16 15:45:00,0.0\r\n2014-07-16 15:50:00,0.0\r\n2014-07-16 15:55:00,0.0\r\n2014-07-16 16:00:00,0.0\r\n2014-07-16 16:05:00,0.0\r\n2014-07-16 16:10:00,0.0\r\n2014-07-16 16:15:00,0.0\r\n2014-07-16 16:20:00,0.0\r\n2014-07-16 16:25:00,0.0\r\n2014-07-16 16:30:00,0.0\r\n2014-07-16 16:35:00,0.0\r\n2014-07-16 16:40:00,0.0\r\n2014-07-16 16:45:00,0.0\r\n2014-07-16 16:50:00,0.0\r\n2014-07-16 16:55:00,0.0\r\n2014-07-16 17:00:00,0.0\r\n2014-07-16 17:05:00,0.0\r\n2014-07-16 17:10:00,0.0\r\n2014-07-16 17:15:00,0.0\r\n2014-07-16 17:20:00,0.0\r\n2014-07-16 17:25:00,0.0\r\n2014-07-16 17:30:00,0.0\r\n2014-07-16 17:35:00,0.0\r\n2014-07-16 17:40:00,0.0\r\n2014-07-16 17:45:00,0.0\r\n2014-07-16 17:50:00,0.0\r\n2014-07-16 17:55:00,0.0\r\n2014-07-16 18:00:00,0.0\r\n2014-07-16 18:05:00,0.0\r\n2014-07-16 18:10:00,0.0\r\n2014-07-16 18:15:00,0.0\r\n2014-07-16 18:20:00,0.0\r\n2014-07-16 18:25:00,0.0\r\n2014-07-16 18:30:00,0.0\r\n2014-07-16 18:35:00,0.0\r\n2014-07-16 18:40:00,0.117964904\r\n2014-07-16 18:45:00,0.0\r\n2014-07-16 18:55:00,0.103039529\r\n2014-07-16 19:05:00,0.06518697700000001\r\n2014-07-16 19:10:00,0.0\r\n2014-07-16 19:20:00,0.0\r\n2014-07-16 19:25:00,0.0\r\n2014-07-16 19:30:00,0.0\r\n2014-07-16 19:35:00,0.0\r\n2014-07-16 19:40:00,0.0\r\n2014-07-16 19:45:00,0.0\r\n2014-07-16 19:50:00,0.0\r\n2014-07-16 19:55:00,0.0\r\n2014-07-16 20:00:00,0.0\r\n2014-07-16 20:05:00,0.0\r\n2014-07-16 20:10:00,0.0\r\n2014-07-16 20:15:00,0.0\r\n2014-07-16 20:20:00,0.0\r\n2014-07-16 20:25:00,0.0\r\n2014-07-16 20:30:00,0.0\r\n2014-07-16 20:35:00,0.0\r\n2014-07-16 20:40:00,0.0\r\n2014-07-16 20:45:00,0.0\r\n2014-07-16 20:50:00,0.0\r\n2014-07-16 20:55:00,0.0\r\n2014-07-16 21:00:00,0.0\r\n2014-07-16 21:05:00,0.0\r\n2014-07-16 21:10:00,0.0\r\n2014-07-16 21:15:00,0.0\r\n2014-07-16 21:20:00,0.0\r\n2014-07-16 21:25:00,0.0\r\n2014-07-16 21:30:00,0.0\r\n2014-07-16 21:35:00,0.0\r\n2014-07-16 21:40:00,0.0\r\n2014-07-16 21:45:00,0.0\r\n2014-07-16 21:50:00,0.0\r\n2014-07-16 21:55:00,0.0\r\n2014-07-16 22:00:00,0.0\r\n2014-07-16 22:05:00,0.0\r\n2014-07-16 22:10:00,0.0\r\n2014-07-16 22:15:00,0.0\r\n2014-07-16 22:20:00,0.0\r\n2014-07-16 22:25:00,0.0\r\n2014-07-16 22:30:00,0.0\r\n2014-07-16 22:35:00,0.0\r\n2014-07-16 22:40:00,0.0\r\n2014-07-16 22:45:00,0.0\r\n2014-07-16 22:50:00,0.0\r\n2014-07-16 22:55:00,0.0\r\n2014-07-16 23:00:00,0.0\r\n2014-07-16 23:05:00,0.0\r\n2014-07-16 23:10:00,0.0\r\n2014-07-16 23:15:00,0.0\r\n2014-07-16 23:20:00,0.0\r\n2014-07-16 23:25:00,0.0\r\n2014-07-16 23:30:00,0.0\r\n2014-07-16 23:35:00,0.0\r\n2014-07-16 23:40:00,0.0\r\n2014-07-16 23:45:00,0.0\r\n2014-07-16 23:50:00,0.0\r\n2014-07-16 23:55:00,0.0\r\n2014-07-17 00:00:00,0.0\r\n2014-07-17 00:05:00,0.0\r\n2014-07-17 00:10:00,0.0\r\n2014-07-17 00:15:00,0.0\r\n2014-07-17 00:20:00,0.0\r\n2014-07-17 00:25:00,0.0\r\n2014-07-17 00:30:00,0.0\r\n2014-07-17 00:35:00,0.0\r\n2014-07-17 00:40:00,0.0\r\n2014-07-17 00:45:00,0.0\r\n2014-07-17 00:50:00,0.0\r\n2014-07-17 00:55:00,0.0\r\n2014-07-17 01:00:00,0.0\r\n2014-07-17 01:05:00,0.0\r\n2014-07-17 01:15:00,0.0\r\n2014-07-17 01:20:00,0.0\r\n2014-07-17 01:25:00,0.0\r\n2014-07-17 01:30:00,0.0\r\n2014-07-17 01:35:00,0.0\r\n2014-07-17 01:40:00,0.0\r\n2014-07-17 01:45:00,0.0\r\n2014-07-17 01:50:00,0.0\r\n2014-07-17 01:55:00,0.0\r\n2014-07-17 02:00:00,0.0\r\n2014-07-17 02:05:00,0.0\r\n2014-07-17 02:10:00,0.0\r\n2014-07-17 02:15:00,0.0\r\n2014-07-17 02:20:00,0.0\r\n2014-07-17 02:25:00,0.0\r\n2014-07-17 02:30:00,0.0\r\n2014-07-17 02:35:00,0.0\r\n2014-07-17 02:40:00,0.0\r\n2014-07-17 02:45:00,0.0\r\n2014-07-17 02:50:00,0.0\r\n2014-07-17 02:55:00,0.0\r\n2014-07-17 03:00:00,0.0\r\n2014-07-17 03:05:00,0.0\r\n2014-07-17 03:10:00,0.0\r\n2014-07-17 03:15:00,0.0\r\n2014-07-17 03:20:00,0.0\r\n2014-07-17 03:25:00,0.0\r\n2014-07-17 03:30:00,0.0\r\n2014-07-17 03:35:00,0.0\r\n2014-07-17 03:40:00,0.0\r\n2014-07-17 03:45:00,0.0\r\n2014-07-17 03:50:00,0.0\r\n2014-07-17 03:55:00,0.0\r\n2014-07-17 04:00:00,0.0\r\n2014-07-17 04:05:00,0.0\r\n2014-07-17 04:10:00,0.0\r\n2014-07-17 04:15:00,0.0\r\n2014-07-17 04:20:00,0.0\r\n2014-07-17 04:25:00,0.0\r\n2014-07-17 04:30:00,0.0\r\n2014-07-17 04:35:00,0.0\r\n2014-07-17 04:40:00,0.0\r\n2014-07-17 04:45:00,0.0\r\n2014-07-17 04:50:00,0.0\r\n2014-07-17 04:55:00,0.0\r\n2014-07-17 05:00:00,0.0\r\n2014-07-17 05:05:00,0.0\r\n2014-07-17 05:10:00,0.0\r\n2014-07-17 05:15:00,0.0\r\n2014-07-17 05:20:00,0.0\r\n2014-07-17 05:25:00,0.0\r\n2014-07-17 05:30:00,0.0\r\n2014-07-17 05:35:00,0.0\r\n2014-07-17 05:40:00,0.0\r\n2014-07-17 05:45:00,0.0\r\n2014-07-17 05:50:00,0.0\r\n2014-07-17 05:55:00,0.0\r\n2014-07-17 06:00:00,0.0\r\n2014-07-17 06:05:00,0.0\r\n2014-07-17 06:10:00,0.0\r\n2014-07-17 06:15:00,0.0\r\n2014-07-17 06:20:00,0.0\r\n2014-07-17 06:25:00,0.0\r\n2014-07-17 06:30:00,0.0\r\n2014-07-17 06:35:00,0.0\r\n2014-07-17 06:40:00,0.0\r\n2014-07-17 06:45:00,0.0\r\n2014-07-17 06:50:00,0.0\r\n2014-07-17 06:55:00,0.0\r\n2014-07-17 07:00:00,0.0\r\n2014-07-17 07:05:00,0.0\r\n2014-07-17 07:10:00,0.0\r\n2014-07-17 07:15:00,0.0\r\n2014-07-17 07:20:00,0.0\r\n2014-07-17 07:25:00,0.0\r\n2014-07-17 07:30:00,0.0\r\n2014-07-17 07:35:00,0.0\r\n2014-07-17 07:40:00,0.0\r\n2014-07-17 07:45:00,0.0\r\n2014-07-17 07:50:00,0.0\r\n2014-07-17 07:55:00,0.0\r\n2014-07-17 08:00:00,0.0\r\n2014-07-17 08:05:00,0.0\r\n2014-07-17 08:10:00,0.0\r\n2014-07-17 08:15:00,0.0\r\n2014-07-17 08:20:00,0.0\r\n2014-07-17 08:25:00,0.0\r\n2014-07-17 08:30:00,0.077423356\r\n2014-07-17 08:35:00,0.098985658\r\n2014-07-17 08:40:00,0.0\r\n2014-07-17 08:50:00,0.0\r\n2014-07-17 08:55:00,0.0\r\n2014-07-17 09:00:00,0.0\r\n2014-07-17 09:05:00,0.0\r\n2014-07-17 09:10:00,0.0\r\n2014-07-17 09:15:00,0.0\r\n2014-07-17 09:20:00,0.0\r\n2014-07-17 09:25:00,0.0\r\n2014-07-17 09:30:00,0.0\r\n2014-07-17 09:35:00,0.0\r\n2014-07-17 09:40:00,0.0\r\n2014-07-17 09:45:00,0.0\r\n2014-07-17 09:50:00,0.0\r\n2014-07-17 09:55:00,0.0\r\n2014-07-17 10:00:00,0.0\r\n2014-07-17 10:05:00,0.0\r\n2014-07-17 10:10:00,0.0\r\n2014-07-17 10:15:00,0.0\r\n2014-07-17 10:20:00,0.0\r\n2014-07-17 10:25:00,0.0\r\n2014-07-17 10:30:00,0.0\r\n2014-07-17 10:35:00,0.0\r\n2014-07-17 10:40:00,0.0\r\n2014-07-17 10:45:00,0.0\r\n2014-07-17 10:50:00,0.0\r\n2014-07-17 10:55:00,0.0\r\n2014-07-17 11:00:00,0.0\r\n2014-07-17 11:05:00,0.0\r\n2014-07-17 11:10:00,0.075698766\r\n2014-07-17 11:15:00,0.0\r\n2014-07-17 11:20:00,0.0\r\n2014-07-17 11:25:00,0.0\r\n2014-07-17 11:30:00,0.0\r\n2014-07-17 11:35:00,0.0\r\n2014-07-17 11:45:00,0.0\r\n2014-07-17 11:50:00,0.0\r\n2014-07-17 12:00:00,0.0\r\n2014-07-17 12:05:00,0.0\r\n2014-07-17 12:10:00,0.099804997\r\n2014-07-17 12:15:00,0.154392838\r\n2014-07-17 12:20:00,0.0\r\n2014-07-17 12:25:00,0.0\r\n2014-07-17 12:30:00,0.100179557\r\n2014-07-17 12:35:00,0.096398302\r\n2014-07-17 12:40:00,0.080038962\r\n2014-07-17 12:45:00,0.145575047\r\n2014-07-17 12:50:00,0.079540943\r\n2014-07-17 12:55:00,0.122484446\r\n2014-07-17 13:00:00,0.092316898\r\n2014-07-17 13:05:00,0.181797504\r\n2014-07-17 13:10:00,0.181043005\r\n2014-07-17 13:15:00,0.167886972\r\n2014-07-17 13:20:00,0.185409403\r\n2014-07-17 13:25:00,0.16096556199999998\r\n2014-07-17 13:30:00,0.213152885\r\n2014-07-17 16:30:00,0.256532192\r\n2014-07-17 21:30:00,0.0\r\n2014-07-18 03:30:00,0.0\r\n2014-07-18 06:40:00,0.0\r\n2014-07-18 06:45:00,0.0\r\n2014-07-18 06:50:00,0.0\r\n2014-07-18 06:55:00,0.075918346\r\n2014-07-18 07:00:00,0.088902824\r\n2014-07-18 07:05:00,0.0\r\n2014-07-18 07:10:00,0.0\r\n2014-07-18 07:15:00,0.0\r\n2014-07-18 07:20:00,0.0\r\n2014-07-18 07:25:00,0.0\r\n2014-07-18 08:35:00,0.07629801900000001\r\n2014-07-18 08:40:00,0.078025562\r\n2014-07-18 08:45:00,0.129002392\r\n2014-07-18 08:50:00,0.0\r\n2014-07-18 08:55:00,0.0\r\n2014-07-18 09:00:00,0.0\r\n2014-07-18 09:05:00,0.0\r\n2014-07-18 09:10:00,0.0\r\n2014-07-18 09:15:00,0.0\r\n2014-07-18 09:20:00,0.0\r\n2014-07-18 09:25:00,0.0\r\n2014-07-18 09:30:00,0.0\r\n2014-07-18 09:35:00,0.0\r\n2014-07-18 09:40:00,0.0\r\n2014-07-18 09:45:00,0.0\r\n2014-07-18 09:50:00,0.0\r\n2014-07-18 09:55:00,0.0\r\n2014-07-18 10:00:00,0.0\r\n2014-07-18 10:55:00,0.0\r\n2014-07-18 11:00:00,0.0\r\n2014-07-18 11:05:00,0.0\r\n2014-07-18 11:10:00,0.0\r\n2014-07-18 11:15:00,0.0\r\n2014-07-18 11:20:00,0.0\r\n2014-07-18 11:25:00,0.0\r\n2014-07-18 11:30:00,0.0\r\n2014-07-18 11:50:00,0.0\r\n2014-07-18 11:55:00,0.0\r\n2014-07-18 12:00:00,0.0\r\n2014-07-18 12:05:00,0.0\r\n2014-07-18 12:10:00,0.0\r\n2014-07-18 12:15:00,0.0\r\n2014-07-18 12:20:00,0.0\r\n2014-07-18 12:25:00,0.0\r\n2014-07-18 12:30:00,0.0\r\n2014-07-18 12:35:00,0.0\r\n2014-07-18 12:40:00,0.0\r\n2014-07-18 12:50:00,0.0\r\n2014-07-18 12:55:00,0.0\r\n2014-07-18 13:00:00,0.0\r\n2014-07-18 13:05:00,0.0\r\n2014-07-18 13:10:00,0.0\r\n2014-07-18 13:30:00,0.0\r\n2014-07-20 05:35:00,0.08837019900000001\r\n2014-07-20 05:40:00,0.078759973\r\n2014-07-20 05:45:00,0.083010178\r\n2014-07-20 05:50:00,0.08861694699999999\r\n2014-07-20 05:55:00,0.085390379\r\n2014-07-20 06:00:00,0.083756364\r\n2014-07-20 06:05:00,0.125853002\r\n2014-07-20 06:10:00,0.086653279\r\n2014-07-20 06:15:00,0.064589664\r\n2014-07-20 06:20:00,0.081922395\r\n2014-07-20 06:25:00,0.081532863\r\n2014-07-20 06:30:00,0.079646328\r\n2014-07-20 06:35:00,0.090795596\r\n2014-07-20 06:40:00,0.075009891\r\n2014-07-20 06:45:00,0.083280383\r\n2014-07-20 06:50:00,0.067865371\r\n2014-07-20 06:55:00,0.071016709\r\n2014-07-20 07:00:00,0.065320139\r\n2014-07-20 07:05:00,0.081546221\r\n2014-07-20 07:10:00,0.08385719400000001\r\n2014-07-20 07:15:00,0.08925564300000001\r\n2014-07-20 07:20:00,0.06688303\r\n2014-07-20 07:25:00,0.064959883\r\n2014-07-20 07:30:00,0.06097663\r\n2014-07-20 07:35:00,0.059792013\r\n2014-07-20 07:40:00,0.078348523\r\n2014-07-20 07:45:00,0.077374113\r\n2014-07-20 07:50:00,0.07966400900000001\r\n2014-07-20 07:55:00,0.08777109300000001\r\n2014-07-20 08:00:00,0.076440345\r\n2014-07-20 08:05:00,0.08259113400000001\r\n2014-07-20 08:10:00,0.07116006\r\n2014-07-20 08:15:00,0.091661677\r\n2014-07-20 08:20:00,0.084915466\r\n2014-07-20 08:25:00,0.081899181\r\n2014-07-20 08:30:00,0.082369635\r\n2014-07-20 08:35:00,0.087235705\r\n2014-07-21 11:20:00,0.071238098\r\n2014-07-21 11:25:00,0.08691614800000001\r\n2014-07-21 11:30:00,0.073151928\r\n2014-07-21 11:35:00,0.075275989\r\n2014-07-21 11:40:00,0.079913506\r\n2014-07-21 11:45:00,0.079200711\r\n2014-07-21 11:50:00,0.102046473\r\n2014-07-21 11:55:00,0.072009265\r\n2014-07-21 12:00:00,0.0\r\n2014-07-21 12:05:00,0.093747727\r\n2014-07-21 12:10:00,0.07192952700000001\r\n2014-07-21 12:15:00,0.092240284\r\n2014-07-21 12:20:00,0.08607551699999999\r\n2014-07-21 12:25:00,0.103967011\r\n2014-07-21 12:30:00,0.0\r\n2014-07-21 12:35:00,0.0\r\n2014-07-21 12:40:00,0.0\r\n2014-07-21 12:45:00,0.086884194\r\n2014-07-21 12:50:00,0.117275238\r\n2014-07-21 12:55:00,0.0\r\n2014-07-21 13:00:00,0.0\r\n2014-07-21 13:20:00,0.081546437\r\n2014-07-21 13:25:00,0.0\r\n2014-07-21 13:30:00,0.0\r\n2014-07-21 13:35:00,0.0\r\n2014-07-21 13:40:00,0.0\r\n2014-07-22 02:00:00,0.082676935\r\n2014-07-22 02:05:00,0.07217667700000001\r\n2014-07-22 02:10:00,0.1026359\r\n2014-07-22 02:15:00,0.068788141\r\n2014-07-22 02:20:00,0.076415445\r\n2014-07-22 02:25:00,0.069610348\r\n2014-07-22 02:30:00,0.074864876\r\n2014-07-22 02:35:00,0.063544522\r\n2014-07-22 02:40:00,0.099381566\r\n2014-07-22 02:45:00,0.0\r\n2014-07-22 02:50:00,0.066098839\r\n2014-07-22 02:55:00,0.077184598\r\n2014-07-22 03:00:00,0.067246207\r\n2014-07-22 03:05:00,0.0\r\n2014-07-22 03:10:00,0.07331007\r\n2014-07-22 03:15:00,0.07823991799999999\r\n2014-07-22 03:20:00,0.074598854\r\n2014-07-22 03:25:00,0.074727423\r\n2014-07-22 03:30:00,0.106285294\r\n2014-07-22 03:35:00,0.071302036\r\n2014-07-22 03:40:00,0.069261506\r\n2014-07-22 03:45:00,0.071043954\r\n2014-07-22 03:50:00,0.07251629\r\n2014-07-22 03:55:00,0.081079956\r\n2014-07-22 04:00:00,0.072769252\r\n2014-07-22 04:35:00,0.086065877\r\n2014-07-22 04:40:00,0.08397303099999999\r\n2014-07-22 04:45:00,0.080356677\r\n2014-07-22 04:50:00,0.087925255\r\n2014-07-22 04:55:00,0.07977986299999999\r\n2014-07-22 05:00:00,0.0\r\n2014-07-22 05:05:00,0.0\r\n2014-07-22 05:10:00,0.087990178\r\n2014-07-22 05:15:00,0.08447536900000001\r\n2014-07-22 05:20:00,0.105537585\r\n2014-07-22 05:25:00,0.083881527\r\n2014-07-22 05:30:00,0.087496805\r\n2014-07-22 05:35:00,0.073710733\r\n2014-07-22 05:40:00,0.066292941\r\n2014-07-22 05:45:00,0.06467717\r\n2014-07-22 05:50:00,0.07062594700000001\r\n2014-07-22 05:55:00,0.069643898\r\n2014-07-22 06:00:00,0.066808108\r\n2014-07-22 06:05:00,0.074006823\r\n2014-07-22 06:10:00,0.09600998\r\n2014-07-22 06:15:00,0.070130505\r\n2014-07-22 06:20:00,0.08710951800000001\r\n2014-07-22 06:25:00,0.067063945\r\n2014-07-22 06:30:00,0.089206405\r\n2014-07-22 06:35:00,0.062315247\r\n2014-07-22 06:40:00,0.071898393\r\n2014-07-22 06:45:00,0.081883682\r\n2014-07-22 06:50:00,0.077740383\r\n2014-07-22 06:55:00,0.101794004\r\n2014-07-22 07:00:00,0.075867248\r\n2014-07-22 07:05:00,0.078512921\r\n2014-07-22 07:10:00,0.087242691\r\n2014-07-22 07:15:00,0.068022267\r\n2014-07-22 07:20:00,0.065473058\r\n2014-07-22 07:25:00,0.07113723200000001\r\n2014-07-22 07:30:00,0.091192008\r\n2014-07-22 07:35:00,0.08384286099999999\r\n2014-07-22 07:40:00,0.084881976\r\n2014-07-22 07:45:00,0.069177867\r\n2014-07-22 07:50:00,0.065212768\r\n2014-07-22 07:55:00,0.06537169\r\n2014-07-22 08:00:00,0.0\r\n2014-07-22 08:05:00,0.0\r\n2014-07-22 08:15:00,0.066673024\r\n2014-07-22 08:20:00,0.081489706\r\n2014-07-22 08:25:00,0.087758636\r\n2014-07-22 08:30:00,0.07695827200000001\r\n2014-07-22 08:35:00,0.081872515\r\n2014-07-22 08:40:00,0.06749843400000001\r\n2014-07-22 08:45:00,0.077520247\r\n2014-07-22 08:50:00,0.07340019\r\n2014-07-22 08:55:00,0.077518924\r\n2014-07-22 09:00:00,0.077860681\r\n2014-07-22 09:05:00,0.081376882\r\n2014-07-22 09:10:00,0.078736668\r\n2014-07-22 09:15:00,0.081914268\r\n2014-07-22 09:20:00,0.084949445\r\n2014-07-22 09:25:00,0.085251038\r\n2014-07-22 09:30:00,0.08794400000000001\r\n2014-07-22 09:35:00,0.087185803\r\n2014-07-22 09:40:00,0.08670235\r\n2014-07-22 09:45:00,0.079396967\r\n2014-07-22 09:50:00,0.064100263\r\n2014-07-22 09:55:00,0.0\r\n2014-07-22 10:00:00,0.0\r\n2014-07-22 10:05:00,0.0\r\n2014-07-22 10:10:00,0.0\r\n2014-07-22 10:15:00,0.075937231\r\n2014-07-22 10:20:00,0.063441813\r\n2014-07-22 10:25:00,0.08886477699999999\r\n2014-07-22 10:30:00,0.0\r\n2014-07-22 10:35:00,0.0\r\n2014-07-22 10:40:00,0.0\r\n2014-07-22 10:45:00,0.0\r\n2014-07-22 10:50:00,0.0\r\n2014-07-22 10:55:00,0.0\r\n2014-07-22 11:00:00,0.066337222\r\n2014-07-22 11:05:00,0.08218078599999999\r\n2014-07-22 11:10:00,0.0\r\n2014-07-22 11:20:00,0.082968481\r\n2014-07-22 11:25:00,0.094356045\r\n2014-07-22 11:30:00,0.08977174800000001\r\n2014-07-22 11:35:00,0.095347788\r\n2014-07-22 11:40:00,0.08870353199999999\r\n2014-07-22 11:45:00,0.079930566\r\n2014-07-22 11:50:00,0.099499519\r\n2014-07-22 11:55:00,0.093424884\r\n2014-07-22 12:00:00,0.078719417\r\n2014-07-22 12:05:00,0.074829279\r\n2014-07-22 12:10:00,0.075621686\r\n2014-07-22 12:15:00,0.081784352\r\n2014-07-22 12:20:00,0.080311402\r\n2014-07-22 12:25:00,0.094215231\r\n2014-07-22 12:30:00,0.098539943\r\n2014-07-22 12:35:00,0.063090687\r\n2014-07-22 12:40:00,0.349751279\r\n2014-07-23 07:20:00,0.078692155\r\n2014-07-23 07:25:00,0.0\r\n2014-07-23 07:30:00,0.097602643\r\n2014-07-23 07:35:00,0.079580865\r\n2014-07-23 07:40:00,0.076324244\r\n2014-07-23 07:45:00,0.08432425699999999\r\n2014-07-23 07:50:00,0.065346726\r\n2014-07-23 07:55:00,0.064352295\r\n2014-07-23 08:00:00,0.061049436\r\n2014-07-23 08:05:00,0.06098353400000001\r\n2014-07-23 08:10:00,0.062208184000000014\r\n2014-07-23 08:15:00,0.065034564\r\n2014-07-23 08:20:00,0.072705949\r\n2014-07-23 08:25:00,0.066192\r\n2014-07-23 08:30:00,0.06410224099999999\r\n2014-07-23 08:35:00,0.06770680400000001\r\n2014-07-23 08:40:00,0.061213848\r\n2014-07-23 08:45:00,0.0636799\r\n2014-07-23 08:50:00,0.06978205400000001\r\n2014-07-23 08:55:00,0.066042146\r\n2014-07-23 09:05:00,0.083272074\r\n2014-07-23 09:10:00,0.06986912599999999\r\n2014-07-23 09:15:00,0.089911461\r\n2014-07-23 09:20:00,0.0\r\n2014-07-23 09:25:00,0.0\r\n2014-07-23 09:30:00,0.0\r\n2014-07-23 09:35:00,0.0\r\n2014-07-23 09:40:00,0.0\r\n2014-07-23 09:45:00,0.0\r\n2014-07-23 09:50:00,0.0\r\n2014-07-23 09:55:00,0.0\r\n2014-07-23 10:05:00,0.0\r\n2014-07-23 10:10:00,0.070423741\r\n2014-07-23 10:15:00,0.073670626\r\n2014-07-23 10:20:00,0.0\r\n2014-07-23 10:25:00,0.066148576\r\n2014-07-23 10:30:00,0.067378998\r\n2014-07-23 10:35:00,0.059605674\r\n2014-07-23 10:40:00,0.064556568\r\n2014-07-23 10:45:00,0.064033921\r\n2014-07-23 10:50:00,0.076436295\r\n2014-07-23 10:55:00,0.068352964\r\n2014-07-23 11:00:00,0.087604841\r\n2014-07-23 11:05:00,0.065447872\r\n2014-07-23 11:10:00,0.068623924\r\n2014-07-23 11:15:00,0.073543434\r\n2014-07-23 11:20:00,0.078354799\r\n2014-07-23 11:25:00,0.073093331\r\n2014-07-23 11:30:00,0.061083667\r\n2014-07-23 11:35:00,0.076646452\r\n2014-07-23 11:40:00,0.068090503\r\n2014-07-23 11:45:00,0.081139378\r\n2014-07-23 11:50:00,0.8950121529999999\r\n2014-07-23 11:55:00,0.084473344\r\n2014-07-23 12:00:00,0.069972732\r\n2014-07-23 12:05:00,0.07644509099999999\r\n2014-07-23 12:10:00,0.08279169900000001\r\n2014-07-23 12:15:00,0.096352205\r\n2014-07-23 12:20:00,0.07790807599999999\r\n2014-07-23 12:25:00,0.075705942\r\n2014-07-23 12:30:00,0.07219347599999999\r\n2014-07-23 12:35:00,0.064731841\r\n2014-07-23 12:40:00,0.076889346\r\n2014-07-23 12:45:00,0.06270653\r\n2014-07-23 12:50:00,0.06578236400000001\r\n2014-07-23 12:55:00,0.070512584\r\n2014-07-23 13:00:00,0.065273208\r\n2014-07-23 13:05:00,0.06391691099999999\r\n2014-07-23 13:10:00,0.062644989\r\n2014-07-23 13:15:00,0.066731398\r\n2014-07-23 13:20:00,0.063483177\r\n2014-07-23 13:25:00,0.073762227\r\n2014-07-23 13:30:00,0.09574565\r\n2014-07-23 13:35:00,0.063987507\r\n2014-07-23 13:40:00,0.0\r\n2014-07-23 13:45:00,0.061681696\r\n2014-07-23 13:50:00,0.067545557\r\n2014-07-23 13:55:00,0.36199113\r\n2014-07-23 14:00:00,0.06789997099999999\r\n2014-07-23 14:05:00,0.06809734099999999\r\n2014-07-23 14:10:00,0.06805268099999999\r\n2014-07-23 14:15:00,0.067784277\r\n2014-07-23 14:20:00,0.07164703900000001\r\n2014-07-23 14:25:00,0.072229549\r\n2014-07-23 14:30:00,0.071906585\r\n2014-07-23 14:35:00,0.067114268\r\n2014-07-23 14:40:00,0.099018082\r\n2014-07-23 14:45:00,0.610788546\r\n2014-07-23 14:50:00,0.073930318\r\n2014-07-23 14:55:00,0.0\r\n2014-07-23 15:00:00,0.07169031599999999\r\n2014-07-23 15:05:00,0.077011813\r\n2014-07-23 15:10:00,0.067765429\r\n2014-07-23 15:15:00,0.07217746400000001\r\n2014-07-23 15:20:00,0.067513486\r\n2014-07-23 15:25:00,0.064085774\r\n2014-07-23 15:30:00,0.06260954099999999\r\n2014-07-23 15:35:00,0.061791321\r\n2014-07-23 16:50:00,0.072957139\r\n2014-07-23 16:55:00,0.07063700099999999\r\n2014-07-23 17:00:00,0.075139932\r\n2014-07-23 17:05:00,0.088852105\r\n2014-07-23 17:10:00,0.082308069\r\n2014-07-23 17:15:00,0.074726225\r\n2014-07-23 17:20:00,0.079228689\r\n2014-07-23 17:25:00,0.067461448\r\n2014-07-23 17:30:00,0.07496677\r\n2014-07-23 17:35:00,0.076553275\r\n2014-07-23 17:40:00,0.064552832\r\n2014-07-23 17:45:00,0.068947534\r\n2014-07-23 17:50:00,0.067166564\r\n2014-07-23 17:55:00,0.07933624\r\n2014-07-23 18:00:00,0.074044645\r\n2014-07-23 18:05:00,0.0\r\n2014-07-23 18:10:00,0.0\r\n2014-07-23 18:15:00,0.065402345\r\n2014-07-23 18:20:00,0.092749881\r\n2014-07-23 18:25:00,0.096656305\r\n2014-07-23 18:30:00,0.098988258\r\n2014-07-23 18:35:00,0.101811358\r\n2014-07-23 18:40:00,0.093130313\r\n2014-07-23 18:45:00,0.092407793\r\n2014-07-23 18:50:00,0.0\r\n2014-07-23 18:55:00,0.061650065\r\n2014-07-23 19:15:00,0.0\r\n2014-07-23 19:20:00,0.092823676\r\n2014-07-23 19:25:00,0.074424922\r\n2014-07-23 19:30:00,0.0\r\n2014-07-23 19:35:00,0.07226751599999999\r\n2014-07-23 19:40:00,0.0\r\n2014-07-23 19:45:00,0.0\r\n2014-07-23 19:50:00,0.0\r\n2014-07-23 19:55:00,0.08830370900000001\r\n2014-07-23 20:00:00,0.063548088\r\n2014-07-23 20:05:00,0.0\r\n2014-07-23 20:10:00,0.0\r\n2014-07-23 20:15:00,0.0\r\n2014-07-23 20:20:00,0.0\r\n2014-07-24 05:55:00,0.06313646099999999\r\n2014-07-24 06:00:00,0.072994453\r\n2014-07-24 06:05:00,0.07012359\r\n2014-07-24 06:10:00,0.108550088\r\n2014-07-24 06:15:00,0.0\r\n2014-07-24 06:25:00,0.069650797\r\n2014-07-24 06:30:00,0.094860491\r\n2014-07-24 06:35:00,0.065317447\r\n2014-07-24 06:40:00,0.09187328\r\n2014-07-24 06:45:00,0.101925869\r\n2014-07-24 06:50:00,0.104564421\r\n2014-07-24 06:55:00,0.080665497\r\n2014-07-24 07:00:00,0.101051966\r\n2014-07-24 07:05:00,0.0\r\n2014-07-24 07:10:00,0.0\r\n2014-07-24 07:15:00,0.07473769400000001\r\n2014-07-24 07:20:00,0.069878197\r\n2014-07-24 08:45:00,0.0\r\n2014-07-24 08:50:00,0.0\r\n2014-07-24 08:55:00,0.0\r\n2014-07-24 09:00:00,0.0\r\n2014-07-24 09:05:00,0.0\r\n2014-07-24 09:10:00,0.0\r\n2014-07-24 09:15:00,0.0\r\n2014-07-24 09:20:00,0.0\r\n2014-07-24 09:25:00,0.0\r\n2014-07-24 09:30:00,0.0\r\n2014-07-24 09:35:00,0.0\r\n2014-07-24 09:40:00,0.0\r\n2014-07-24 09:45:00,0.062455331\r\n2014-07-24 09:50:00,0.070857845\r\n2014-07-24 09:55:00,0.068090968\r\n2014-07-24 10:00:00,0.079217003\r\n2014-07-24 10:05:00,0.057993155\r\n2014-07-24 10:10:00,0.06279552\r\n2014-07-24 10:15:00,0.063083849\r\n2014-07-24 10:20:00,0.064707347\r\n2014-07-24 10:25:00,0.061793969\r\n2014-07-24 10:30:00,0.057134586\r\n2014-07-24 10:35:00,0.066382056\r\n2014-07-24 10:40:00,0.06570248599999999\r\n2014-07-24 10:45:00,0.07583788400000001\r\n2014-07-24 10:50:00,0.07132485200000001\r\n2014-07-24 10:55:00,0.072924837\r\n2014-07-24 11:00:00,0.068822214\r\n2014-07-24 11:05:00,0.067517329\r\n2014-07-24 11:10:00,0.072035726\r\n2014-07-24 11:15:00,0.069037403\r\n2014-07-24 11:20:00,0.064108242\r\n2014-07-24 11:25:00,0.060951365\r\n2014-07-24 11:30:00,0.067261475\r\n2014-07-24 11:35:00,0.06399500000000001\r\n2014-07-24 11:40:00,0.114735047\r\n2014-07-24 11:45:00,0.0\r\n2014-07-24 11:50:00,0.062882542\r\n2014-07-24 11:55:00,0.077318974\r\n2014-07-24 12:00:00,0.069855268\r\n2014-07-24 12:05:00,0.055725676\r\n2014-07-24 12:10:00,0.093738198\r\n2014-07-24 12:20:00,0.068159761\r\n2014-07-24 12:25:00,0.076422071\r\n2014-07-24 12:30:00,0.07587888200000001\r\n2014-07-24 12:35:00,0.071253913\r\n2014-07-24 12:40:00,0.077756844\r\n2014-07-24 12:45:00,0.06360170700000001\r\n2014-07-24 12:50:00,0.10324349\r\n2014-07-24 12:55:00,0.059044135\r\n2014-07-24 13:00:00,0.065392214\r\n2014-07-24 13:05:00,0.074960282\r\n2014-07-24 13:10:00,0.085893458\r\n2014-07-24 13:15:00,0.084598799\r\n2014-07-24 13:20:00,0.063798883\r\n2014-07-24 13:25:00,0.068831275\r\n2014-07-24 13:30:00,0.524246935\r\n2014-07-24 13:35:00,0.087101771\r\n2014-07-24 13:40:00,0.065787391\r\n2014-07-24 13:45:00,0.06919821\r\n2014-07-24 13:50:00,0.07065954299999999\r\n2014-07-24 13:55:00,0.06117666\r\n2014-07-24 14:00:00,0.078157515\r\n2014-07-24 14:05:00,0.067612386\r\n2014-07-24 14:10:00,0.089919632\r\n2014-07-24 14:15:00,0.097439289\r\n2014-07-24 14:20:00,0.066014404\r\n2014-07-24 14:25:00,0.08573717300000001\r\n2014-07-24 14:30:00,0.06489059900000001\r\n2014-07-24 14:35:00,0.06850619\r\n2014-07-24 14:40:00,0.06691381\r\n2014-07-24 14:45:00,0.062846575\r\n2014-07-24 14:50:00,0.074442913\r\n2014-07-24 14:55:00,0.085791861\r\n2014-07-24 15:00:00,0.066712354\r\n2014-07-24 15:05:00,0.071112197\r\n2014-07-24 15:10:00,0.060056244\r\n2014-07-24 15:15:00,0.070031968\r\n2014-07-24 15:20:00,0.095845057\r\n2014-07-24 15:25:00,0.06619569900000001\r\n2014-07-24 15:30:00,0.081358772\r\n2014-07-24 15:35:00,0.068662967\r\n2014-07-24 15:40:00,0.108670118\r\n2014-07-24 15:45:00,0.091656786\r\n2014-07-24 15:50:00,0.099634248\r\n2014-07-24 15:55:00,0.11856300000000003\r\n2014-07-24 16:00:00,0.058717608\r\n2014-07-24 16:05:00,0.0\r\n2014-07-24 16:10:00,0.0\r\n2014-07-24 16:15:00,0.0\r\n2014-07-24 18:45:00,0.0\r\n2014-07-24 18:50:00,0.0\r\n2014-07-24 18:55:00,0.060939679\r\n2014-07-24 19:00:00,0.073384077\r\n2014-07-24 19:05:00,0.0\r\n2014-07-24 19:10:00,0.0\r\n2014-07-24 19:15:00,0.0\r\n2014-07-24 19:20:00,0.066576387\r\n2014-07-24 19:25:00,0.06964247\r\n2014-07-24 19:30:00,0.063509709\r\n2014-07-24 19:35:00,0.06448430599999999\r\n2014-07-24 19:40:00,0.061242839\r\n2014-07-24 19:45:00,0.064032585\r\n2014-07-25 04:25:00,0.067142889\r\n2014-07-25 04:35:00,0.068054505\r\n2014-07-25 04:40:00,0.066956947\r\n2014-07-25 04:45:00,0.06847438900000001\r\n2014-07-25 04:50:00,0.092548565\r\n2014-07-25 04:55:00,0.06987181099999999\r\n2014-07-25 05:00:00,0.072714345\r\n2014-07-25 05:05:00,0.07117198\r\n2014-07-25 05:10:00,0.07489518099999999\r\n2014-07-25 05:15:00,0.08371131400000001\r\n2014-07-25 05:20:00,0.07240345299999999\r\n2014-07-25 05:25:00,0.080385259\r\n2014-07-25 05:30:00,0.078046892\r\n2014-07-25 05:35:00,0.078197638\r\n2014-07-25 05:40:00,0.07752671900000001\r\n2014-07-25 05:45:00,0.075176188\r\n2014-07-25 05:50:00,0.077734212\r\n2014-07-25 05:55:00,0.066790509\r\n2014-07-25 06:00:00,0.073448632\r\n2014-07-25 06:05:00,0.078631616\r\n2014-07-25 06:10:00,0.078642825\r\n2014-07-25 06:15:00,0.071975314\r\n2014-07-25 06:20:00,0.068929185\r\n2014-07-25 06:25:00,0.06820836400000001\r\n2014-07-25 06:30:00,0.06526570400000001\r\n2014-07-25 06:35:00,0.065391185\r\n2014-07-25 06:40:00,0.321492891\r\n2014-07-25 06:45:00,0.093553322\r\n2014-07-25 06:50:00,0.08904257199999999\r\n2014-07-25 06:55:00,0.075370373\r\n2014-07-25 07:00:00,0.080041643\r\n2014-07-25 07:05:00,0.073008225\r\n2014-07-25 07:10:00,0.080206812\r\n2014-07-25 07:15:00,0.0\r\n2014-07-25 07:20:00,0.0\r\n2014-07-25 07:25:00,0.0\r\n2014-07-25 07:30:00,0.0\r\n2014-07-25 07:35:00,0.0\r\n2014-07-25 07:40:00,0.0\r\n2014-07-25 07:45:00,0.0\r\n2014-07-25 07:50:00,0.0\r\n2014-07-25 07:55:00,0.078838386\r\n2014-07-25 08:00:00,0.099511194\r\n2014-07-25 08:05:00,0.09507214\r\n2014-07-25 08:10:00,0.07767202\r\n2014-07-25 08:15:00,0.074637525\r\n2014-07-25 08:20:00,0.070592141\r\n2014-07-25 08:25:00,0.06513331900000001\r\n2014-07-25 08:30:00,0.069692447\r\n2014-07-25 08:35:00,0.094646682\r\n2014-07-25 08:40:00,0.0\r\n2014-07-25 08:45:00,0.08524335\r\n2014-07-25 08:50:00,0.077485182\r\n2014-07-25 08:55:00,0.0\r\n"
  },
  {
    "path": "workspace/anomaly_detector/datasets/selected/seasonal/Twitter_volume_GOOG.csv",
    "content": "timestamp,value\n2015-02-26 21:42:53,35\n2015-02-26 21:47:53,41\n2015-02-26 21:52:53,32\n2015-02-26 21:57:53,36\n2015-02-26 22:02:53,32\n2015-02-26 22:07:53,25\n2015-02-26 22:12:53,33\n2015-02-26 22:17:53,20\n2015-02-26 22:22:53,38\n2015-02-26 22:27:53,28\n2015-02-26 22:32:53,28\n2015-02-26 22:37:53,27\n2015-02-26 22:42:53,30\n2015-02-26 22:47:53,31\n2015-02-26 22:52:53,38\n2015-02-26 22:57:53,35\n2015-02-26 23:02:53,33\n2015-02-26 23:07:53,24\n2015-02-26 23:12:53,28\n2015-02-26 23:17:53,20\n2015-02-26 23:22:53,35\n2015-02-26 23:27:53,29\n2015-02-26 23:32:53,24\n2015-02-26 23:37:53,24\n2015-02-26 23:42:53,33\n2015-02-26 23:47:53,36\n2015-02-26 23:52:53,18\n2015-02-26 23:57:53,28\n2015-02-27 00:02:53,20\n2015-02-27 00:07:53,59\n2015-02-27 00:12:53,41\n2015-02-27 00:17:53,97\n2015-02-27 00:22:53,61\n2015-02-27 00:27:53,105\n2015-02-27 00:32:53,52\n2015-02-27 00:37:53,30\n2015-02-27 00:42:53,23\n2015-02-27 00:47:53,26\n2015-02-27 00:52:53,43\n2015-02-27 00:57:53,24\n2015-02-27 01:02:53,41\n2015-02-27 01:07:53,24\n2015-02-27 01:12:53,33\n2015-02-27 01:17:53,20\n2015-02-27 01:22:53,21\n2015-02-27 01:27:53,34\n2015-02-27 01:32:53,39\n2015-02-27 01:37:53,41\n2015-02-27 01:42:53,48\n2015-02-27 01:47:53,28\n2015-02-27 01:52:53,32\n2015-02-27 01:57:53,26\n2015-02-27 02:02:53,18\n2015-02-27 02:07:53,17\n2015-02-27 02:12:53,25\n2015-02-27 02:17:53,25\n2015-02-27 02:22:53,32\n2015-02-27 02:27:53,94\n2015-02-27 02:32:53,39\n2015-02-27 02:37:53,23\n2015-02-27 02:42:53,73\n2015-02-27 02:47:53,31\n2015-02-27 02:52:53,30\n2015-02-27 02:57:53,35\n2015-02-27 03:02:53,23\n2015-02-27 03:07:53,49\n2015-02-27 03:12:53,187\n2015-02-27 03:17:53,203\n2015-02-27 03:22:53,175\n2015-02-27 03:27:53,112\n2015-02-27 03:32:53,22\n2015-02-27 03:37:53,24\n2015-02-27 03:42:53,12\n2015-02-27 03:47:53,26\n2015-02-27 03:52:53,16\n2015-02-27 03:57:53,14\n2015-02-27 04:02:53,19\n2015-02-27 04:07:53,21\n2015-02-27 04:12:53,18\n2015-02-27 04:17:53,12\n2015-02-27 04:22:53,25\n2015-02-27 04:27:53,17\n2015-02-27 04:32:53,21\n2015-02-27 04:37:53,18\n2015-02-27 04:42:53,22\n2015-02-27 04:47:53,23\n2015-02-27 04:52:53,26\n2015-02-27 04:57:53,33\n2015-02-27 05:02:53,26\n2015-02-27 05:07:53,16\n2015-02-27 05:12:53,15\n2015-02-27 05:17:53,7\n2015-02-27 05:22:53,14\n2015-02-27 05:27:53,11\n2015-02-27 05:32:53,31\n2015-02-27 05:37:53,15\n2015-02-27 05:42:53,15\n2015-02-27 05:47:53,15\n2015-02-27 05:52:53,25\n2015-02-27 05:57:53,34\n2015-02-27 06:02:53,20\n2015-02-27 06:07:53,15\n2015-02-27 06:12:53,16\n2015-02-27 06:17:53,18\n2015-02-27 06:22:53,6\n2015-02-27 06:27:53,10\n2015-02-27 06:32:53,20\n2015-02-27 06:37:53,14\n2015-02-27 06:42:53,11\n2015-02-27 06:47:53,27\n2015-02-27 06:52:53,7\n2015-02-27 06:57:53,21\n2015-02-27 07:02:53,16\n2015-02-27 07:07:53,20\n2015-02-27 07:12:53,11\n2015-02-27 07:17:53,11\n2015-02-27 07:22:53,21\n2015-02-27 07:27:53,16\n2015-02-27 07:32:53,16\n2015-02-27 07:37:53,16\n2015-02-27 07:42:53,18\n2015-02-27 07:47:53,10\n2015-02-27 07:52:53,13\n2015-02-27 07:57:53,21\n2015-02-27 08:02:53,18\n2015-02-27 08:07:53,11\n2015-02-27 08:12:53,17\n2015-02-27 08:17:53,19\n2015-02-27 08:22:53,8\n2015-02-27 08:27:53,14\n2015-02-27 08:32:53,18\n2015-02-27 08:37:53,13\n2015-02-27 08:42:53,16\n2015-02-27 08:47:53,18\n2015-02-27 08:52:53,8\n2015-02-27 08:57:53,17\n2015-02-27 09:02:53,28\n2015-02-27 09:07:53,14\n2015-02-27 09:12:53,14\n2015-02-27 09:17:53,16\n2015-02-27 09:22:53,9\n2015-02-27 09:27:53,20\n2015-02-27 09:32:53,17\n2015-02-27 09:37:53,13\n2015-02-27 09:42:53,22\n2015-02-27 09:47:53,19\n2015-02-27 09:52:53,19\n2015-02-27 09:57:53,30\n2015-02-27 10:02:53,12\n2015-02-27 10:07:53,13\n2015-02-27 10:12:53,13\n2015-02-27 10:17:53,12\n2015-02-27 10:22:53,13\n2015-02-27 10:27:53,61\n2015-02-27 10:32:53,12\n2015-02-27 10:37:53,19\n2015-02-27 10:42:53,34\n2015-02-27 10:47:53,25\n2015-02-27 10:52:53,19\n2015-02-27 10:57:53,14\n2015-02-27 11:02:53,17\n2015-02-27 11:07:53,33\n2015-02-27 11:12:53,19\n2015-02-27 11:17:53,11\n2015-02-27 11:22:53,9\n2015-02-27 11:27:53,14\n2015-02-27 11:32:53,22\n2015-02-27 11:37:53,9\n2015-02-27 11:42:53,21\n2015-02-27 11:47:53,24\n2015-02-27 11:52:53,10\n2015-02-27 11:57:53,15\n2015-02-27 12:02:53,19\n2015-02-27 12:07:53,30\n2015-02-27 12:12:53,36\n2015-02-27 12:17:53,21\n2015-02-27 12:22:53,24\n2015-02-27 12:27:53,24\n2015-02-27 12:32:53,21\n2015-02-27 12:37:53,14\n2015-02-27 12:42:53,22\n2015-02-27 12:47:53,24\n2015-02-27 12:52:53,20\n2015-02-27 12:57:53,20\n2015-02-27 13:02:53,20\n2015-02-27 13:07:53,14\n2015-02-27 13:12:53,19\n2015-02-27 13:17:53,11\n2015-02-27 13:22:53,12\n2015-02-27 13:27:53,25\n2015-02-27 13:32:53,15\n2015-02-27 13:37:53,17\n2015-02-27 13:42:53,10\n2015-02-27 13:47:53,20\n2015-02-27 13:52:53,14\n2015-02-27 13:57:53,20\n2015-02-27 14:02:53,14\n2015-02-27 14:07:53,21\n2015-02-27 14:12:53,15\n2015-02-27 14:17:53,31\n2015-02-27 14:22:53,29\n2015-02-27 14:27:53,34\n2015-02-27 14:32:53,30\n2015-02-27 14:37:53,26\n2015-02-27 14:42:53,21\n2015-02-27 14:47:53,30\n2015-02-27 14:52:53,24\n2015-02-27 14:57:53,47\n2015-02-27 15:02:53,21\n2015-02-27 15:07:53,30\n2015-02-27 15:12:53,27\n2015-02-27 15:17:53,18\n2015-02-27 15:22:53,40\n2015-02-27 15:27:53,18\n2015-02-27 15:32:53,20\n2015-02-27 15:37:53,23\n2015-02-27 15:42:53,14\n2015-02-27 15:47:53,20\n2015-02-27 15:52:53,22\n2015-02-27 15:57:53,28\n2015-02-27 16:02:53,18\n2015-02-27 16:07:53,19\n2015-02-27 16:12:53,27\n2015-02-27 16:17:53,30\n2015-02-27 16:22:53,23\n2015-02-27 16:27:53,17\n2015-02-27 16:32:53,24\n2015-02-27 16:37:53,18\n2015-02-27 16:42:53,27\n2015-02-27 16:47:53,42\n2015-02-27 16:52:53,22\n2015-02-27 16:57:53,100\n2015-02-27 17:02:53,67\n2015-02-27 17:07:53,43\n2015-02-27 17:12:53,43\n2015-02-27 17:17:53,24\n2015-02-27 17:22:53,22\n2015-02-27 17:27:53,43\n2015-02-27 17:32:53,39\n2015-02-27 17:37:53,37\n2015-02-27 17:42:53,41\n2015-02-27 17:47:53,25\n2015-02-27 17:52:53,24\n2015-02-27 17:57:53,63\n2015-02-27 18:02:53,80\n2015-02-27 18:07:53,48\n2015-02-27 18:12:53,58\n2015-02-27 18:17:53,52\n2015-02-27 18:22:53,44\n2015-02-27 18:27:53,68\n2015-02-27 18:32:53,58\n2015-02-27 18:37:53,112\n2015-02-27 18:42:53,77\n2015-02-27 18:47:53,46\n2015-02-27 18:52:53,202\n2015-02-27 18:57:53,105\n2015-02-27 19:02:53,60\n2015-02-27 19:07:53,61\n2015-02-27 19:12:53,55\n2015-02-27 19:17:53,34\n2015-02-27 19:22:53,35\n2015-02-27 19:27:53,61\n2015-02-27 19:32:53,47\n2015-02-27 19:37:53,30\n2015-02-27 19:42:53,37\n2015-02-27 19:47:53,41\n2015-02-27 19:52:53,54\n2015-02-27 19:57:53,35\n2015-02-27 20:02:53,39\n2015-02-27 20:07:53,54\n2015-02-27 20:12:53,116\n2015-02-27 20:17:53,77\n2015-02-27 20:22:53,75\n2015-02-27 20:27:53,90\n2015-02-27 20:32:53,70\n2015-02-27 20:37:53,41\n2015-02-27 20:42:53,24\n2015-02-27 20:47:53,40\n2015-02-27 20:52:53,26\n2015-02-27 20:57:53,36\n2015-02-27 21:02:53,36\n2015-02-27 21:07:53,31\n2015-02-27 21:12:53,34\n2015-02-27 21:17:53,40\n2015-02-27 21:22:53,30\n2015-02-27 21:27:53,70\n2015-02-27 21:32:53,40\n2015-02-27 21:37:53,36\n2015-02-27 21:42:53,31\n2015-02-27 21:47:53,42\n2015-02-27 21:52:53,31\n2015-02-27 21:57:53,32\n2015-02-27 22:02:53,24\n2015-02-27 22:07:53,32\n2015-02-27 22:12:53,32\n2015-02-27 22:17:53,33\n2015-02-27 22:22:53,27\n2015-02-27 22:27:53,31\n2015-02-27 22:32:53,25\n2015-02-27 22:37:53,24\n2015-02-27 22:42:53,21\n2015-02-27 22:47:53,25\n2015-02-27 22:52:53,13\n2015-02-27 22:57:53,27\n2015-02-27 23:02:53,37\n2015-02-27 23:07:53,20\n2015-02-27 23:12:53,17\n2015-02-27 23:17:53,18\n2015-02-27 23:22:53,20\n2015-02-27 23:27:53,24\n2015-02-27 23:32:53,27\n2015-02-27 23:37:53,58\n2015-02-27 23:42:53,80\n2015-02-27 23:47:53,51\n2015-02-27 23:52:53,42\n2015-02-27 23:57:53,39\n2015-02-28 00:02:53,28\n2015-02-28 00:07:53,27\n2015-02-28 00:12:53,22\n2015-02-28 00:17:53,21\n2015-02-28 00:22:53,20\n2015-02-28 00:27:53,35\n2015-02-28 00:32:53,25\n2015-02-28 00:37:53,16\n2015-02-28 00:42:53,15\n2015-02-28 00:47:53,22\n2015-02-28 00:52:53,104\n2015-02-28 00:57:53,18\n2015-02-28 01:02:53,13\n2015-02-28 01:07:53,16\n2015-02-28 01:12:53,14\n2015-02-28 01:17:53,20\n2015-02-28 01:22:53,17\n2015-02-28 01:27:53,25\n2015-02-28 01:32:53,16\n2015-02-28 01:37:53,13\n2015-02-28 01:42:53,12\n2015-02-28 01:47:53,12\n2015-02-28 01:52:53,21\n2015-02-28 01:57:53,13\n2015-02-28 02:02:53,24\n2015-02-28 02:07:53,20\n2015-02-28 02:12:53,12\n2015-02-28 02:17:53,12\n2015-02-28 02:22:53,13\n2015-02-28 02:27:53,15\n2015-02-28 02:32:53,12\n2015-02-28 02:37:53,16\n2015-02-28 02:42:53,13\n2015-02-28 02:47:53,15\n2015-02-28 02:52:53,10\n2015-02-28 02:57:53,16\n2015-02-28 03:02:53,14\n2015-02-28 03:07:53,12\n2015-02-28 03:12:53,7\n2015-02-28 03:17:53,15\n2015-02-28 03:22:53,13\n2015-02-28 03:27:53,11\n2015-02-28 03:32:53,8\n2015-02-28 03:37:53,6\n2015-02-28 03:42:53,15\n2015-02-28 03:47:53,9\n2015-02-28 03:52:53,7\n2015-02-28 03:57:53,11\n2015-02-28 04:02:53,9\n2015-02-28 04:07:53,12\n2015-02-28 04:12:53,6\n2015-02-28 04:17:53,8\n2015-02-28 04:22:53,4\n2015-02-28 04:27:53,10\n2015-02-28 04:32:53,14\n2015-02-28 04:37:53,12\n2015-02-28 04:42:53,25\n2015-02-28 04:47:53,14\n2015-02-28 04:52:53,8\n2015-02-28 04:57:53,14\n2015-02-28 05:02:53,7\n2015-02-28 05:07:53,22\n2015-02-28 05:12:53,23\n2015-02-28 05:17:53,9\n2015-02-28 05:22:53,27\n2015-02-28 05:27:53,11\n2015-02-28 05:32:53,8\n2015-02-28 05:37:53,19\n2015-02-28 05:42:53,20\n2015-02-28 05:47:53,7\n2015-02-28 05:52:53,16\n2015-02-28 05:57:53,9\n2015-02-28 06:02:53,15\n2015-02-28 06:07:53,10\n2015-02-28 06:12:53,20\n2015-02-28 06:17:53,9\n2015-02-28 06:22:53,11\n2015-02-28 06:27:53,8\n2015-02-28 06:32:53,17\n2015-02-28 06:37:53,32\n2015-02-28 06:42:53,4\n2015-02-28 06:47:53,7\n2015-02-28 06:52:53,9\n2015-02-28 06:57:53,12\n2015-02-28 07:02:53,5\n2015-02-28 07:07:53,5\n2015-02-28 07:12:53,7\n2015-02-28 07:17:53,10\n2015-02-28 07:22:53,10\n2015-02-28 07:27:53,12\n2015-02-28 07:32:53,11\n2015-02-28 07:37:53,6\n2015-02-28 07:42:53,6\n2015-02-28 07:47:53,10\n2015-02-28 07:52:53,15\n2015-02-28 07:57:53,13\n2015-02-28 08:02:53,8\n2015-02-28 08:07:53,10\n2015-02-28 08:12:53,12\n2015-02-28 08:17:53,6\n2015-02-28 08:22:53,10\n2015-02-28 08:27:53,8\n2015-02-28 08:32:53,9\n2015-02-28 08:37:53,12\n2015-02-28 08:42:53,5\n2015-02-28 08:47:53,6\n2015-02-28 08:52:53,7\n2015-02-28 08:57:53,14\n2015-02-28 09:02:53,4\n2015-02-28 09:07:53,15\n2015-02-28 09:12:53,21\n2015-02-28 09:17:53,17\n2015-02-28 09:22:53,6\n2015-02-28 09:27:53,11\n2015-02-28 09:32:53,5\n2015-02-28 09:37:53,3\n2015-02-28 09:42:53,7\n2015-02-28 09:47:53,7\n2015-02-28 09:52:53,3\n2015-02-28 09:57:53,15\n2015-02-28 10:02:53,8\n2015-02-28 10:07:53,8\n2015-02-28 10:12:53,7\n2015-02-28 10:17:53,4\n2015-02-28 10:22:53,22\n2015-02-28 10:27:53,8\n2015-02-28 10:32:53,10\n2015-02-28 10:37:53,14\n2015-02-28 10:42:53,17\n2015-02-28 10:47:53,13\n2015-02-28 10:52:53,9\n2015-02-28 10:57:53,13\n2015-02-28 11:02:53,33\n2015-02-28 11:07:53,25\n2015-02-28 11:12:53,15\n2015-02-28 11:17:53,8\n2015-02-28 11:22:53,9\n2015-02-28 11:27:53,11\n2015-02-28 11:32:53,8\n2015-02-28 11:37:53,4\n2015-02-28 11:42:53,6\n2015-02-28 11:47:53,7\n2015-02-28 11:52:53,6\n2015-02-28 11:57:53,22\n2015-02-28 12:02:53,17\n2015-02-28 12:07:53,13\n2015-02-28 12:12:53,13\n2015-02-28 12:17:53,19\n2015-02-28 12:22:53,31\n2015-02-28 12:27:53,23\n2015-02-28 12:32:53,13\n2015-02-28 12:37:53,21\n2015-02-28 12:42:53,12\n2015-02-28 12:47:53,11\n2015-02-28 12:52:53,15\n2015-02-28 12:57:53,13\n2015-02-28 13:02:53,10\n2015-02-28 13:07:53,12\n2015-02-28 13:12:53,16\n2015-02-28 13:17:53,14\n2015-02-28 13:22:53,18\n2015-02-28 13:27:53,17\n2015-02-28 13:32:53,8\n2015-02-28 13:37:53,8\n2015-02-28 13:42:53,13\n2015-02-28 13:47:53,9\n2015-02-28 13:52:53,12\n2015-02-28 13:57:53,25\n2015-02-28 14:02:53,17\n2015-02-28 14:07:53,15\n2015-02-28 14:12:53,24\n2015-02-28 14:17:53,17\n2015-02-28 14:22:53,17\n2015-02-28 14:27:53,23\n2015-02-28 14:32:53,17\n2015-02-28 14:37:53,15\n2015-02-28 14:42:53,18\n2015-02-28 14:47:53,14\n2015-02-28 14:52:53,22\n2015-02-28 14:57:53,22\n2015-02-28 15:02:53,26\n2015-02-28 15:07:53,18\n2015-02-28 15:12:53,36\n2015-02-28 15:17:53,15\n2015-02-28 15:22:53,19\n2015-02-28 15:27:53,24\n2015-02-28 15:32:53,12\n2015-02-28 15:37:53,13\n2015-02-28 15:42:53,17\n2015-02-28 15:47:53,14\n2015-02-28 15:52:53,20\n2015-02-28 15:57:53,16\n2015-02-28 16:02:53,20\n2015-02-28 16:07:53,7\n2015-02-28 16:12:53,32\n2015-02-28 16:17:53,16\n2015-02-28 16:22:53,15\n2015-02-28 16:27:53,28\n2015-02-28 16:32:53,19\n2015-02-28 16:37:53,10\n2015-02-28 16:42:53,21\n2015-02-28 16:47:53,21\n2015-02-28 16:52:53,20\n2015-02-28 16:57:53,25\n2015-02-28 17:02:53,16\n2015-02-28 17:07:53,18\n2015-02-28 17:12:53,10\n2015-02-28 17:17:53,11\n2015-02-28 17:22:53,46\n2015-02-28 17:27:53,8\n2015-02-28 17:32:53,31\n2015-02-28 17:37:53,22\n2015-02-28 17:42:53,11\n2015-02-28 17:47:53,14\n2015-02-28 17:52:53,8\n2015-02-28 17:57:53,23\n2015-02-28 18:02:53,19\n2015-02-28 18:07:53,20\n2015-02-28 18:12:53,17\n2015-02-28 18:17:53,19\n2015-02-28 18:22:53,11\n2015-02-28 18:27:53,16\n2015-02-28 18:32:53,16\n2015-02-28 18:37:53,9\n2015-02-28 18:42:53,14\n2015-02-28 18:47:53,16\n2015-02-28 18:52:53,6\n2015-02-28 18:57:53,32\n2015-02-28 19:02:53,30\n2015-02-28 19:07:53,39\n2015-02-28 19:12:53,30\n2015-02-28 19:17:53,27\n2015-02-28 19:22:53,16\n2015-02-28 19:27:53,17\n2015-02-28 19:32:53,20\n2015-02-28 19:37:53,27\n2015-02-28 19:42:53,20\n2015-02-28 19:47:53,21\n2015-02-28 19:52:53,22\n2015-02-28 19:57:53,25\n2015-02-28 20:02:53,19\n2015-02-28 20:07:53,21\n2015-02-28 20:12:53,20\n2015-02-28 20:17:53,13\n2015-02-28 20:22:53,14\n2015-02-28 20:27:53,13\n2015-02-28 20:32:53,19\n2015-02-28 20:37:53,16\n2015-02-28 20:42:53,13\n2015-02-28 20:47:53,14\n2015-02-28 20:52:53,23\n2015-02-28 20:57:53,21\n2015-02-28 21:02:53,11\n2015-02-28 21:07:53,25\n2015-02-28 21:12:53,8\n2015-02-28 21:17:53,11\n2015-02-28 21:22:53,13\n2015-02-28 21:27:53,21\n2015-02-28 21:32:53,10\n2015-02-28 21:37:53,12\n2015-02-28 21:42:53,14\n2015-02-28 21:47:53,17\n2015-02-28 21:52:53,19\n2015-02-28 21:57:53,23\n2015-02-28 22:02:53,13\n2015-02-28 22:07:53,14\n2015-02-28 22:12:53,19\n2015-02-28 22:17:53,10\n2015-02-28 22:22:53,12\n2015-02-28 22:27:53,7\n2015-02-28 22:32:53,11\n2015-02-28 22:37:53,10\n2015-02-28 22:42:53,9\n2015-02-28 22:47:53,14\n2015-02-28 22:52:53,13\n2015-02-28 22:57:53,17\n2015-02-28 23:02:53,24\n2015-02-28 23:07:53,5\n2015-02-28 23:12:53,9\n2015-02-28 23:17:53,20\n2015-02-28 23:22:53,11\n2015-02-28 23:27:53,16\n2015-02-28 23:32:53,7\n2015-02-28 23:37:53,18\n2015-02-28 23:42:53,7\n2015-02-28 23:47:53,3\n2015-02-28 23:52:53,12\n2015-02-28 23:57:53,10\n2015-03-01 00:02:53,13\n2015-03-01 00:07:53,16\n2015-03-01 00:12:53,9\n2015-03-01 00:17:53,5\n2015-03-01 00:22:53,10\n2015-03-01 00:27:53,7\n2015-03-01 00:32:53,5\n2015-03-01 00:37:53,9\n2015-03-01 00:42:53,13\n2015-03-01 00:47:53,14\n2015-03-01 00:52:53,9\n2015-03-01 00:57:53,8\n2015-03-01 01:02:53,12\n2015-03-01 01:07:53,4\n2015-03-01 01:12:53,11\n2015-03-01 01:17:53,11\n2015-03-01 01:22:53,11\n2015-03-01 01:27:53,18\n2015-03-01 01:32:53,6\n2015-03-01 01:37:53,5\n2015-03-01 01:42:53,8\n2015-03-01 01:47:53,9\n2015-03-01 01:52:53,5\n2015-03-01 01:57:53,15\n2015-03-01 02:02:53,13\n2015-03-01 02:07:53,6\n2015-03-01 02:12:53,14\n2015-03-01 02:17:53,7\n2015-03-01 02:22:53,1\n2015-03-01 02:27:53,8\n2015-03-01 02:32:53,9\n2015-03-01 02:37:53,5\n2015-03-01 02:42:53,6\n2015-03-01 02:47:53,10\n2015-03-01 02:52:53,6\n2015-03-01 02:57:53,6\n2015-03-01 03:02:53,10\n2015-03-01 03:07:53,16\n2015-03-01 03:12:53,8\n2015-03-01 03:17:53,9\n2015-03-01 03:22:53,5\n2015-03-01 03:27:53,16\n2015-03-01 03:32:53,6\n2015-03-01 03:37:53,10\n2015-03-01 03:42:53,11\n2015-03-01 03:47:53,6\n2015-03-01 03:52:53,16\n2015-03-01 03:57:53,14\n2015-03-01 04:02:53,7\n2015-03-01 04:07:53,7\n2015-03-01 04:12:53,7\n2015-03-01 04:17:53,11\n2015-03-01 04:22:53,4\n2015-03-01 04:27:53,7\n2015-03-01 04:32:53,9\n2015-03-01 04:37:53,5\n2015-03-01 04:42:53,12\n2015-03-01 04:47:53,6\n2015-03-01 04:52:53,11\n2015-03-01 04:57:53,12\n2015-03-01 05:02:53,6\n2015-03-01 05:07:53,4\n2015-03-01 05:12:53,5\n2015-03-01 05:17:53,4\n2015-03-01 05:22:53,7\n2015-03-01 05:27:53,22\n2015-03-01 05:32:53,4\n2015-03-01 05:37:53,6\n2015-03-01 05:42:53,6\n2015-03-01 05:47:53,9\n2015-03-01 05:52:53,3\n2015-03-01 05:57:53,3\n2015-03-01 06:02:53,7\n2015-03-01 06:07:53,12\n2015-03-01 06:12:53,6\n2015-03-01 06:17:53,5\n2015-03-01 06:22:53,2\n2015-03-01 06:27:53,13\n2015-03-01 06:32:53,7\n2015-03-01 06:37:53,14\n2015-03-01 06:42:53,15\n2015-03-01 06:47:53,4\n2015-03-01 06:52:53,10\n2015-03-01 06:57:53,8\n2015-03-01 07:02:53,8\n2015-03-01 07:07:53,4\n2015-03-01 07:12:53,16\n2015-03-01 07:17:53,5\n2015-03-01 07:22:53,5\n2015-03-01 07:27:53,5\n2015-03-01 07:32:53,9\n2015-03-01 07:37:53,13\n2015-03-01 07:42:53,0\n2015-03-01 07:47:53,2\n2015-03-01 07:52:53,5\n2015-03-01 07:57:53,7\n2015-03-01 08:02:53,11\n2015-03-01 08:07:53,9\n2015-03-01 08:12:53,6\n2015-03-01 08:17:53,15\n2015-03-01 08:22:53,11\n2015-03-01 08:27:53,3\n2015-03-01 08:32:53,8\n2015-03-01 08:37:53,7\n2015-03-01 08:42:53,3\n2015-03-01 08:47:53,5\n2015-03-01 08:52:53,7\n2015-03-01 08:57:53,14\n2015-03-01 09:02:53,5\n2015-03-01 09:07:53,5\n2015-03-01 09:12:53,9\n2015-03-01 09:17:53,3\n2015-03-01 09:22:53,6\n2015-03-01 09:27:53,6\n2015-03-01 09:32:53,8\n2015-03-01 09:37:53,10\n2015-03-01 09:42:53,12\n2015-03-01 09:47:53,9\n2015-03-01 09:52:53,16\n2015-03-01 09:57:53,17\n2015-03-01 10:02:53,7\n2015-03-01 10:07:53,11\n2015-03-01 10:12:53,14\n2015-03-01 10:17:53,11\n2015-03-01 10:22:53,5\n2015-03-01 10:27:53,12\n2015-03-01 10:32:53,10\n2015-03-01 10:37:53,14\n2015-03-01 10:42:53,13\n2015-03-01 10:47:53,22\n2015-03-01 10:52:53,16\n2015-03-01 10:57:53,13\n2015-03-01 11:02:53,4\n2015-03-01 11:07:53,13\n2015-03-01 11:12:53,12\n2015-03-01 11:17:53,6\n2015-03-01 11:22:53,16\n2015-03-01 11:27:53,10\n2015-03-01 11:32:53,4\n2015-03-01 11:37:53,11\n2015-03-01 11:42:53,7\n2015-03-01 11:47:53,7\n2015-03-01 11:52:53,81\n2015-03-01 11:57:53,41\n2015-03-01 12:02:53,27\n2015-03-01 12:07:53,12\n2015-03-01 12:12:53,15\n2015-03-01 12:17:53,7\n2015-03-01 12:22:53,9\n2015-03-01 12:27:53,9\n2015-03-01 12:32:53,21\n2015-03-01 12:37:53,4\n2015-03-01 12:42:53,11\n2015-03-01 12:47:53,14\n2015-03-01 12:52:53,18\n2015-03-01 12:57:53,12\n2015-03-01 13:02:53,8\n2015-03-01 13:07:53,6\n2015-03-01 13:12:53,7\n2015-03-01 13:17:53,13\n2015-03-01 13:22:53,7\n2015-03-01 13:27:53,8\n2015-03-01 13:32:53,8\n2015-03-01 13:37:53,12\n2015-03-01 13:42:53,18\n2015-03-01 13:47:53,24\n2015-03-01 13:52:53,12\n2015-03-01 13:57:53,12\n2015-03-01 14:02:53,6\n2015-03-01 14:07:53,17\n2015-03-01 14:12:53,19\n2015-03-01 14:17:53,14\n2015-03-01 14:22:53,17\n2015-03-01 14:27:53,12\n2015-03-01 14:32:53,17\n2015-03-01 14:37:53,12\n2015-03-01 14:42:53,13\n2015-03-01 14:47:53,15\n2015-03-01 14:52:53,11\n2015-03-01 14:57:53,19\n2015-03-01 15:02:53,10\n2015-03-01 15:07:53,10\n2015-03-01 15:12:53,12\n2015-03-01 15:17:53,10\n2015-03-01 15:22:53,20\n2015-03-01 15:27:53,13\n2015-03-01 15:32:53,11\n2015-03-01 15:37:53,14\n2015-03-01 15:42:53,15\n2015-03-01 15:47:53,9\n2015-03-01 15:52:53,17\n2015-03-01 15:57:53,14\n2015-03-01 16:02:53,16\n2015-03-01 16:07:53,23\n2015-03-01 16:12:53,11\n2015-03-01 16:17:53,8\n2015-03-01 16:22:53,20\n2015-03-01 16:27:53,12\n2015-03-01 16:32:53,13\n2015-03-01 16:37:53,26\n2015-03-01 16:42:53,18\n2015-03-01 16:47:53,16\n2015-03-01 16:52:53,10\n2015-03-01 16:57:53,8\n2015-03-01 17:02:53,11\n2015-03-01 17:07:53,16\n2015-03-01 17:12:53,18\n2015-03-01 17:17:53,12\n2015-03-01 17:22:53,20\n2015-03-01 17:27:53,17\n2015-03-01 17:32:53,17\n2015-03-01 17:37:53,21\n2015-03-01 17:42:53,14\n2015-03-01 17:47:53,20\n2015-03-01 17:52:53,12\n2015-03-01 17:57:53,26\n2015-03-01 18:02:53,8\n2015-03-01 18:07:53,16\n2015-03-01 18:12:53,8\n2015-03-01 18:17:53,11\n2015-03-01 18:22:53,13\n2015-03-01 18:27:53,21\n2015-03-01 18:32:53,14\n2015-03-01 18:37:53,11\n2015-03-01 18:42:53,11\n2015-03-01 18:47:53,17\n2015-03-01 18:52:53,10\n2015-03-01 18:57:53,11\n2015-03-01 19:02:53,18\n2015-03-01 19:07:53,17\n2015-03-01 19:12:53,18\n2015-03-01 19:17:53,14\n2015-03-01 19:22:53,9\n2015-03-01 19:27:53,10\n2015-03-01 19:32:53,7\n2015-03-01 19:37:53,6\n2015-03-01 19:42:53,5\n2015-03-01 19:47:53,11\n2015-03-01 19:52:53,5\n2015-03-01 19:57:53,14\n2015-03-01 20:02:53,13\n2015-03-01 20:07:53,13\n2015-03-01 20:12:53,15\n2015-03-01 20:17:53,12\n2015-03-01 20:22:53,8\n2015-03-01 20:27:53,8\n2015-03-01 20:32:53,16\n2015-03-01 20:37:53,15\n2015-03-01 20:42:53,10\n2015-03-01 20:47:53,7\n2015-03-01 20:52:53,5\n2015-03-01 20:57:53,16\n2015-03-01 21:02:53,17\n2015-03-01 21:07:53,10\n2015-03-01 21:12:53,26\n2015-03-01 21:17:53,6\n2015-03-01 21:22:53,11\n2015-03-01 21:27:53,20\n2015-03-01 21:32:53,24\n2015-03-01 21:37:53,7\n2015-03-01 21:42:53,13\n2015-03-01 21:47:53,7\n2015-03-01 21:52:53,10\n2015-03-01 21:57:53,8\n2015-03-01 22:02:53,8\n2015-03-01 22:07:53,9\n2015-03-01 22:12:53,8\n2015-03-01 22:17:53,9\n2015-03-01 22:22:53,15\n2015-03-01 22:27:53,8\n2015-03-01 22:32:53,10\n2015-03-01 22:37:53,15\n2015-03-01 22:42:53,7\n2015-03-01 22:47:53,12\n2015-03-01 22:52:53,5\n2015-03-01 22:57:53,11\n2015-03-01 23:02:53,7\n2015-03-01 23:07:53,8\n2015-03-01 23:12:53,11\n2015-03-01 23:17:53,14\n2015-03-01 23:22:53,14\n2015-03-01 23:27:53,20\n2015-03-01 23:32:53,16\n2015-03-01 23:37:53,16\n2015-03-01 23:42:53,10\n2015-03-01 23:47:53,9\n2015-03-01 23:52:53,9\n2015-03-01 23:57:53,7\n2015-03-02 00:02:53,14\n2015-03-02 00:07:53,14\n2015-03-02 00:12:53,9\n2015-03-02 00:17:53,13\n2015-03-02 00:22:53,7\n2015-03-02 00:27:53,7\n2015-03-02 00:32:53,5\n2015-03-02 00:37:53,13\n2015-03-02 00:42:53,11\n2015-03-02 00:47:53,7\n2015-03-02 00:52:53,9\n2015-03-02 00:57:53,9\n2015-03-02 01:02:53,15\n2015-03-02 01:07:53,6\n2015-03-02 01:12:53,9\n2015-03-02 01:17:53,5\n2015-03-02 01:22:53,12\n2015-03-02 01:27:53,10\n2015-03-02 01:32:53,10\n2015-03-02 01:37:53,10\n2015-03-02 01:42:53,15\n2015-03-02 01:47:53,12\n2015-03-02 01:52:53,17\n2015-03-02 01:57:53,14\n2015-03-02 02:02:53,9\n2015-03-02 02:07:53,9\n2015-03-02 02:12:53,7\n2015-03-02 02:17:53,11\n2015-03-02 02:22:53,11\n2015-03-02 02:27:53,7\n2015-03-02 02:32:53,7\n2015-03-02 02:37:53,12\n2015-03-02 02:42:53,6\n2015-03-02 02:47:53,12\n2015-03-02 02:52:53,6\n2015-03-02 02:57:53,12\n2015-03-02 03:02:53,10\n2015-03-02 03:07:53,6\n2015-03-02 03:12:53,12\n2015-03-02 03:17:53,11\n2015-03-02 03:22:53,8\n2015-03-02 03:27:53,8\n2015-03-02 03:32:53,10\n2015-03-02 03:37:53,11\n2015-03-02 03:42:53,5\n2015-03-02 03:47:53,3\n2015-03-02 03:52:53,8\n2015-03-02 03:57:53,7\n2015-03-02 04:02:53,13\n2015-03-02 04:07:53,5\n2015-03-02 04:12:53,10\n2015-03-02 04:17:53,6\n2015-03-02 04:22:53,32\n2015-03-02 04:27:53,17\n2015-03-02 04:32:53,19\n2015-03-02 04:37:53,16\n2015-03-02 04:42:53,14\n2015-03-02 04:47:53,9\n2015-03-02 04:52:53,5\n2015-03-02 04:57:53,7\n2015-03-02 05:02:53,9\n2015-03-02 05:07:53,9\n2015-03-02 05:12:53,17\n2015-03-02 05:17:53,12\n2015-03-02 05:22:53,8\n2015-03-02 05:27:53,15\n2015-03-02 05:32:53,15\n2015-03-02 05:37:53,1\n2015-03-02 05:42:53,11\n2015-03-02 05:47:53,5\n2015-03-02 05:52:53,8\n2015-03-02 05:57:53,13\n2015-03-02 06:02:53,7\n2015-03-02 06:07:53,8\n2015-03-02 06:12:53,1\n2015-03-02 06:17:53,8\n2015-03-02 06:22:53,12\n2015-03-02 06:27:53,8\n2015-03-02 06:32:53,5\n2015-03-02 06:37:53,15\n2015-03-02 06:42:53,6\n2015-03-02 06:47:53,9\n2015-03-02 06:52:53,10\n2015-03-02 06:57:53,20\n2015-03-02 07:02:53,9\n2015-03-02 07:07:53,7\n2015-03-02 07:12:53,19\n2015-03-02 07:17:53,17\n2015-03-02 07:22:53,7\n2015-03-02 07:27:53,24\n2015-03-02 07:32:53,5\n2015-03-02 07:37:53,10\n2015-03-02 07:42:53,11\n2015-03-02 07:47:53,9\n2015-03-02 07:52:53,14\n2015-03-02 07:57:53,6\n2015-03-02 08:02:53,10\n2015-03-02 08:07:53,20\n2015-03-02 08:12:53,8\n2015-03-02 08:17:53,4\n2015-03-02 08:22:53,7\n2015-03-02 08:27:53,10\n2015-03-02 08:32:53,6\n2015-03-02 08:37:53,7\n2015-03-02 08:42:53,18\n2015-03-02 08:47:53,21\n2015-03-02 08:52:53,21\n2015-03-02 08:57:53,70\n2015-03-02 09:02:53,6\n2015-03-02 09:07:53,9\n2015-03-02 09:12:53,9\n2015-03-02 09:17:53,21\n2015-03-02 09:22:53,13\n2015-03-02 09:27:53,11\n2015-03-02 09:32:53,13\n2015-03-02 09:37:53,11\n2015-03-02 09:42:53,5\n2015-03-02 09:47:53,6\n2015-03-02 09:52:53,10\n2015-03-02 09:57:53,14\n2015-03-02 10:02:53,13\n2015-03-02 10:07:53,21\n2015-03-02 10:12:53,10\n2015-03-02 10:17:53,13\n2015-03-02 10:22:53,11\n2015-03-02 10:27:53,6\n2015-03-02 10:32:53,14\n2015-03-02 10:37:53,10\n2015-03-02 10:42:53,15\n2015-03-02 10:47:53,9\n2015-03-02 10:52:53,11\n2015-03-02 10:57:53,22\n2015-03-02 11:02:53,21\n2015-03-02 11:07:53,10\n2015-03-02 11:12:53,11\n2015-03-02 11:17:53,22\n2015-03-02 11:22:53,9\n2015-03-02 11:27:53,13\n2015-03-02 11:32:53,11\n2015-03-02 11:37:53,12\n2015-03-02 11:42:53,8\n2015-03-02 11:47:53,12\n2015-03-02 11:52:53,17\n2015-03-02 11:57:53,22\n2015-03-02 12:02:53,24\n2015-03-02 12:07:53,14\n2015-03-02 12:12:53,30\n2015-03-02 12:17:53,19\n2015-03-02 12:22:53,13\n2015-03-02 12:27:53,15\n2015-03-02 12:32:53,18\n2015-03-02 12:37:53,31\n2015-03-02 12:42:53,25\n2015-03-02 12:47:53,29\n2015-03-02 12:52:53,29\n2015-03-02 12:57:53,35\n2015-03-02 13:02:53,40\n2015-03-02 13:07:53,28\n2015-03-02 13:12:53,22\n2015-03-02 13:17:53,19\n2015-03-02 13:22:53,23\n2015-03-02 13:27:53,16\n2015-03-02 13:32:53,17\n2015-03-02 13:37:53,18\n2015-03-02 13:42:53,40\n2015-03-02 13:47:53,28\n2015-03-02 13:52:53,29\n2015-03-02 13:57:53,35\n2015-03-02 14:02:53,27\n2015-03-02 14:07:53,15\n2015-03-02 14:12:53,29\n2015-03-02 14:17:53,23\n2015-03-02 14:22:53,19\n2015-03-02 14:27:53,13\n2015-03-02 14:32:53,17\n2015-03-02 14:37:53,19\n2015-03-02 14:42:53,23\n2015-03-02 14:47:53,20\n2015-03-02 14:52:53,25\n2015-03-02 14:57:53,35\n2015-03-02 15:02:53,46\n2015-03-02 15:07:53,66\n2015-03-02 15:12:53,72\n2015-03-02 15:17:53,52\n2015-03-02 15:22:53,40\n2015-03-02 15:27:53,42\n2015-03-02 15:32:53,39\n2015-03-02 15:37:53,32\n2015-03-02 15:42:53,28\n2015-03-02 15:47:53,36\n2015-03-02 15:52:53,37\n2015-03-02 15:57:53,30\n2015-03-02 16:02:53,19\n2015-03-02 16:07:53,31\n2015-03-02 16:12:53,28\n2015-03-02 16:17:53,59\n2015-03-02 16:22:53,50\n2015-03-02 16:27:53,35\n2015-03-02 16:32:53,33\n2015-03-02 16:37:53,31\n2015-03-02 16:42:53,47\n2015-03-02 16:47:53,36\n2015-03-02 16:52:53,31\n2015-03-02 16:57:53,39\n2015-03-02 17:02:53,48\n2015-03-02 17:07:53,42\n2015-03-02 17:12:53,33\n2015-03-02 17:17:53,25\n2015-03-02 17:22:53,28\n2015-03-02 17:27:53,24\n2015-03-02 17:32:53,54\n2015-03-02 17:37:53,32\n2015-03-02 17:42:53,25\n2015-03-02 17:47:53,17\n2015-03-02 17:52:53,21\n2015-03-02 17:57:53,46\n2015-03-02 18:02:53,42\n2015-03-02 18:07:53,21\n2015-03-02 18:12:53,28\n2015-03-02 18:17:53,53\n2015-03-02 18:22:53,26\n2015-03-02 18:27:53,31\n2015-03-02 18:32:53,28\n2015-03-02 18:37:53,39\n2015-03-02 18:42:53,25\n2015-03-02 18:47:53,20\n2015-03-02 18:52:53,40\n2015-03-02 18:57:53,37\n2015-03-02 19:02:53,61\n2015-03-02 19:07:53,53\n2015-03-02 19:12:53,33\n2015-03-02 19:17:53,40\n2015-03-02 19:22:53,61\n2015-03-02 19:27:53,49\n2015-03-02 19:32:53,51\n2015-03-02 19:37:53,43\n2015-03-02 19:42:53,41\n2015-03-02 19:47:53,27\n2015-03-02 19:52:53,47\n2015-03-02 19:57:53,47\n2015-03-02 20:02:53,72\n2015-03-02 20:07:53,40\n2015-03-02 20:12:53,37\n2015-03-02 20:17:53,33\n2015-03-02 20:22:53,51\n2015-03-02 20:27:53,49\n2015-03-02 20:32:53,32\n2015-03-02 20:37:53,42\n2015-03-02 20:42:53,30\n2015-03-02 20:47:53,33\n2015-03-02 20:52:53,29\n2015-03-02 20:57:53,35\n2015-03-02 21:02:53,30\n2015-03-02 21:07:53,20\n2015-03-02 21:12:53,32\n2015-03-02 21:17:53,25\n2015-03-02 21:22:53,52\n2015-03-02 21:27:53,55\n2015-03-02 21:32:53,32\n2015-03-02 21:37:53,17\n2015-03-02 21:42:53,25\n2015-03-02 21:47:53,33\n2015-03-02 21:52:53,22\n2015-03-02 21:57:53,19\n2015-03-02 22:02:53,28\n2015-03-02 22:07:53,30\n2015-03-02 22:12:53,26\n2015-03-02 22:17:53,20\n2015-03-02 22:22:53,21\n2015-03-02 22:27:53,20\n2015-03-02 22:32:53,15\n2015-03-02 22:37:53,26\n2015-03-02 22:42:53,38\n2015-03-02 22:47:53,26\n2015-03-02 22:52:53,22\n2015-03-02 22:57:53,26\n2015-03-02 23:02:53,18\n2015-03-02 23:07:53,16\n2015-03-02 23:12:53,10\n2015-03-02 23:17:53,33\n2015-03-02 23:22:53,21\n2015-03-02 23:27:53,20\n2015-03-02 23:32:53,11\n2015-03-02 23:37:53,15\n2015-03-02 23:42:53,11\n2015-03-02 23:47:53,21\n2015-03-02 23:52:53,22\n2015-03-02 23:57:53,24\n2015-03-03 00:02:53,27\n2015-03-03 00:07:53,18\n2015-03-03 00:12:53,14\n2015-03-03 00:17:53,47\n2015-03-03 00:22:53,21\n2015-03-03 00:27:53,30\n2015-03-03 00:32:53,22\n2015-03-03 00:37:53,17\n2015-03-03 00:42:53,18\n2015-03-03 00:47:53,28\n2015-03-03 00:52:53,26\n2015-03-03 00:57:53,22\n2015-03-03 01:02:53,19\n2015-03-03 01:07:53,47\n2015-03-03 01:12:53,21\n2015-03-03 01:17:53,18\n2015-03-03 01:22:53,18\n2015-03-03 01:27:53,26\n2015-03-03 01:32:53,14\n2015-03-03 01:37:53,12\n2015-03-03 01:42:53,13\n2015-03-03 01:47:53,16\n2015-03-03 01:52:53,33\n2015-03-03 01:57:53,21\n2015-03-03 02:02:53,12\n2015-03-03 02:07:53,15\n2015-03-03 02:12:53,10\n2015-03-03 02:17:53,22\n2015-03-03 02:22:53,10\n2015-03-03 02:27:53,24\n2015-03-03 02:32:53,33\n2015-03-03 02:37:53,25\n2015-03-03 02:42:53,16\n2015-03-03 02:47:53,23\n2015-03-03 02:52:53,22\n2015-03-03 02:57:53,14\n2015-03-03 03:02:53,14\n2015-03-03 03:07:53,15\n2015-03-03 03:12:53,23\n2015-03-03 03:17:53,13\n2015-03-03 03:22:53,14\n2015-03-03 03:27:53,20\n2015-03-03 03:32:53,15\n2015-03-03 03:37:53,20\n2015-03-03 03:42:53,9\n2015-03-03 03:47:53,15\n2015-03-03 03:52:53,16\n2015-03-03 03:57:53,22\n2015-03-03 04:02:53,16\n2015-03-03 04:07:53,21\n2015-03-03 04:12:53,23\n2015-03-03 04:17:53,18\n2015-03-03 04:22:53,14\n2015-03-03 04:27:53,9\n2015-03-03 04:32:53,9\n2015-03-03 04:37:53,8\n2015-03-03 04:42:53,6\n2015-03-03 04:47:53,12\n2015-03-03 04:52:53,16\n2015-03-03 04:57:53,14\n2015-03-03 05:02:53,12\n2015-03-03 05:07:53,8\n2015-03-03 05:12:53,6\n2015-03-03 05:17:53,5\n2015-03-03 05:22:53,8\n2015-03-03 05:27:53,15\n2015-03-03 05:32:53,12\n2015-03-03 05:37:53,15\n2015-03-03 05:42:53,8\n2015-03-03 05:47:53,11\n2015-03-03 05:52:53,8\n2015-03-03 05:57:53,14\n2015-03-03 06:02:53,8\n2015-03-03 06:07:53,13\n2015-03-03 06:12:53,7\n2015-03-03 06:17:53,13\n2015-03-03 06:22:53,16\n2015-03-03 06:27:53,10\n2015-03-03 06:32:53,8\n2015-03-03 06:37:53,6\n2015-03-03 06:42:53,18\n2015-03-03 06:47:53,13\n2015-03-03 06:52:53,9\n2015-03-03 06:57:53,21\n2015-03-03 07:02:53,9\n2015-03-03 07:07:53,5\n2015-03-03 07:12:53,18\n2015-03-03 07:17:53,12\n2015-03-03 07:22:53,5\n2015-03-03 07:27:53,12\n2015-03-03 07:32:53,15\n2015-03-03 07:37:53,6\n2015-03-03 07:42:53,20\n2015-03-03 07:47:53,16\n2015-03-03 07:52:53,14\n2015-03-03 07:57:53,8\n2015-03-03 08:02:53,9\n2015-03-03 08:07:53,13\n2015-03-03 08:12:53,7\n2015-03-03 08:17:53,11\n2015-03-03 08:22:53,7\n2015-03-03 08:27:53,12\n2015-03-03 08:32:53,18\n2015-03-03 08:37:53,15\n2015-03-03 08:42:53,17\n2015-03-03 08:47:53,15\n2015-03-03 08:52:53,15\n2015-03-03 08:57:53,19\n2015-03-03 09:02:53,14\n2015-03-03 09:07:53,13\n2015-03-03 09:12:53,10\n2015-03-03 09:17:53,11\n2015-03-03 09:22:53,12\n2015-03-03 09:27:53,21\n2015-03-03 09:32:53,9\n2015-03-03 09:37:53,8\n2015-03-03 09:42:53,10\n2015-03-03 09:47:53,15\n2015-03-03 09:52:53,14\n2015-03-03 09:57:53,23\n2015-03-03 10:02:53,14\n2015-03-03 10:07:53,7\n2015-03-03 10:12:53,10\n2015-03-03 10:17:53,15\n2015-03-03 10:22:53,9\n2015-03-03 10:27:53,20\n2015-03-03 10:32:53,14\n2015-03-03 10:37:53,14\n2015-03-03 10:42:53,15\n2015-03-03 10:47:53,6\n2015-03-03 10:52:53,7\n2015-03-03 10:57:53,29\n2015-03-03 11:02:53,11\n2015-03-03 11:07:53,19\n2015-03-03 11:12:53,18\n2015-03-03 11:17:53,12\n2015-03-03 11:22:53,11\n2015-03-03 11:27:53,13\n2015-03-03 11:32:53,12\n2015-03-03 11:37:53,13\n2015-03-03 11:42:53,25\n2015-03-03 11:47:53,18\n2015-03-03 11:52:53,22\n2015-03-03 11:57:53,18\n2015-03-03 12:02:53,14\n2015-03-03 12:07:53,19\n2015-03-03 12:12:53,17\n2015-03-03 12:17:53,11\n2015-03-03 12:22:53,24\n2015-03-03 12:27:53,20\n2015-03-03 12:32:53,17\n2015-03-03 12:37:53,18\n2015-03-03 12:42:53,18\n2015-03-03 12:47:53,24\n2015-03-03 12:52:53,22\n2015-03-03 12:57:53,38\n2015-03-03 13:02:53,14\n2015-03-03 13:07:53,20\n2015-03-03 13:12:53,12\n2015-03-03 13:17:53,22\n2015-03-03 13:22:53,26\n2015-03-03 13:27:53,30\n2015-03-03 13:32:53,18\n2015-03-03 13:37:53,30\n2015-03-03 13:42:53,23\n2015-03-03 13:47:53,29\n2015-03-03 13:52:53,20\n2015-03-03 13:57:53,25\n2015-03-03 14:02:53,29\n2015-03-03 14:07:53,42\n2015-03-03 14:12:53,36\n2015-03-03 14:17:53,43\n2015-03-03 14:22:53,28\n2015-03-03 14:27:53,29\n2015-03-03 14:32:53,28\n2015-03-03 14:37:53,38\n2015-03-03 14:42:53,34\n2015-03-03 14:47:53,30\n2015-03-03 14:52:53,29\n2015-03-03 14:57:53,25\n2015-03-03 15:02:53,20\n2015-03-03 15:07:53,30\n2015-03-03 15:12:53,30\n2015-03-03 15:17:53,18\n2015-03-03 15:22:53,20\n2015-03-03 15:27:53,25\n2015-03-03 15:32:53,28\n2015-03-03 15:37:53,19\n2015-03-03 15:42:53,23\n2015-03-03 15:47:53,20\n2015-03-03 15:52:53,11\n2015-03-03 15:57:53,25\n2015-03-03 16:02:53,42\n2015-03-03 16:07:53,28\n2015-03-03 16:12:53,26\n2015-03-03 16:17:53,23\n2015-03-03 16:22:53,23\n2015-03-03 16:27:53,34\n2015-03-03 16:32:53,26\n2015-03-03 16:37:53,25\n2015-03-03 16:42:53,20\n2015-03-03 16:47:53,21\n2015-03-03 16:52:53,34\n2015-03-03 16:57:53,31\n2015-03-03 17:02:53,59\n2015-03-03 17:07:53,35\n2015-03-03 17:12:53,45\n2015-03-03 17:17:53,34\n2015-03-03 17:22:53,28\n2015-03-03 17:27:53,26\n2015-03-03 17:32:53,24\n2015-03-03 17:37:53,21\n2015-03-03 17:42:53,26\n2015-03-03 17:47:53,17\n2015-03-03 17:52:53,19\n2015-03-03 17:57:53,27\n2015-03-03 18:02:53,23\n2015-03-03 18:07:53,23\n2015-03-03 18:12:53,35\n2015-03-03 18:17:53,18\n2015-03-03 18:22:53,33\n2015-03-03 18:27:53,25\n2015-03-03 18:32:53,26\n2015-03-03 18:37:53,32\n2015-03-03 18:42:53,39\n2015-03-03 18:47:53,22\n2015-03-03 18:52:53,28\n2015-03-03 18:57:53,71\n2015-03-03 19:02:53,41\n2015-03-03 19:07:53,37\n2015-03-03 19:12:53,27\n2015-03-03 19:17:53,30\n2015-03-03 19:22:53,21\n2015-03-03 19:27:53,25\n2015-03-03 19:32:53,30\n2015-03-03 19:37:53,32\n2015-03-03 19:42:53,31\n2015-03-03 19:47:53,30\n2015-03-03 19:52:53,26\n2015-03-03 19:57:53,35\n2015-03-03 20:02:53,27\n2015-03-03 20:07:53,21\n2015-03-03 20:12:53,13\n2015-03-03 20:17:53,16\n2015-03-03 20:22:53,23\n2015-03-03 20:27:53,16\n2015-03-03 20:32:53,15\n2015-03-03 20:37:53,24\n2015-03-03 20:42:53,43\n2015-03-03 20:47:53,42\n2015-03-03 20:52:53,38\n2015-03-03 20:57:53,55\n2015-03-03 21:02:53,44\n2015-03-03 21:07:53,21\n2015-03-03 21:12:53,23\n2015-03-03 21:17:53,19\n2015-03-03 21:22:53,41\n2015-03-03 21:27:53,53\n2015-03-03 21:32:53,46\n2015-03-03 21:37:53,31\n2015-03-03 21:42:53,38\n2015-03-03 21:47:53,22\n2015-03-03 21:52:53,22\n2015-03-03 21:57:53,22\n2015-03-03 22:02:53,23\n2015-03-03 22:07:53,26\n2015-03-03 22:12:53,23\n2015-03-03 22:17:53,30\n2015-03-03 22:22:53,22\n2015-03-03 22:27:53,19\n2015-03-03 22:32:53,26\n2015-03-03 22:37:53,17\n2015-03-03 22:42:53,34\n2015-03-03 22:47:53,18\n2015-03-03 22:52:53,27\n2015-03-03 22:57:53,35\n2015-03-03 23:02:53,17\n2015-03-03 23:07:53,13\n2015-03-03 23:12:53,19\n2015-03-03 23:17:53,22\n2015-03-03 23:22:53,24\n2015-03-03 23:27:53,22\n2015-03-03 23:32:53,21\n2015-03-03 23:37:53,31\n2015-03-03 23:42:53,39\n2015-03-03 23:47:53,21\n2015-03-03 23:52:53,17\n2015-03-03 23:57:53,22\n2015-03-04 00:02:53,20\n2015-03-04 00:07:53,21\n2015-03-04 00:12:53,17\n2015-03-04 00:17:53,15\n2015-03-04 00:22:53,13\n2015-03-04 00:27:53,15\n2015-03-04 00:32:53,18\n2015-03-04 00:37:53,14\n2015-03-04 00:42:53,8\n2015-03-04 00:47:53,7\n2015-03-04 00:52:53,14\n2015-03-04 00:57:53,26\n2015-03-04 01:02:53,11\n2015-03-04 01:07:53,15\n2015-03-04 01:12:53,11\n2015-03-04 01:17:53,13\n2015-03-04 01:22:53,20\n2015-03-04 01:27:53,20\n2015-03-04 01:32:53,13\n2015-03-04 01:37:53,15\n2015-03-04 01:42:53,7\n2015-03-04 01:47:53,7\n2015-03-04 01:52:53,16\n2015-03-04 01:57:53,10\n2015-03-04 02:02:53,20\n2015-03-04 02:07:53,13\n2015-03-04 02:12:53,15\n2015-03-04 02:17:53,7\n2015-03-04 02:22:53,12\n2015-03-04 02:27:53,26\n2015-03-04 02:32:53,25\n2015-03-04 02:37:53,20\n2015-03-04 02:42:53,6\n2015-03-04 02:47:53,6\n2015-03-04 02:52:53,7\n2015-03-04 02:57:53,18\n2015-03-04 03:02:53,8\n2015-03-04 03:07:53,25\n2015-03-04 03:12:53,23\n2015-03-04 03:17:53,13\n2015-03-04 03:22:53,10\n2015-03-04 03:27:53,23\n2015-03-04 03:32:53,6\n2015-03-04 03:37:53,11\n2015-03-04 03:42:53,2\n2015-03-04 03:47:53,8\n2015-03-04 03:52:53,8\n2015-03-04 03:57:53,25\n2015-03-04 04:02:53,13\n2015-03-04 04:07:53,15\n2015-03-04 04:12:53,15\n2015-03-04 04:17:53,10\n2015-03-04 04:22:53,10\n2015-03-04 04:27:53,22\n2015-03-04 04:32:53,17\n2015-03-04 04:37:53,11\n2015-03-04 04:42:53,16\n2015-03-04 04:47:53,20\n2015-03-04 04:52:53,23\n2015-03-04 04:57:53,25\n2015-03-04 05:02:53,14\n2015-03-04 05:07:53,6\n2015-03-04 05:12:53,12\n2015-03-04 05:17:53,14\n2015-03-04 05:22:53,8\n2015-03-04 05:27:53,7\n2015-03-04 05:32:53,17\n2015-03-04 05:37:53,12\n2015-03-04 05:42:53,7\n2015-03-04 05:47:53,14\n2015-03-04 05:52:53,16\n2015-03-04 05:57:53,18\n2015-03-04 06:02:53,22\n2015-03-04 06:07:53,6\n2015-03-04 06:12:53,4\n2015-03-04 06:17:53,7\n2015-03-04 06:22:53,9\n2015-03-04 06:27:53,14\n2015-03-04 06:32:53,9\n2015-03-04 06:37:53,10\n2015-03-04 06:42:53,16\n2015-03-04 06:47:53,6\n2015-03-04 06:52:53,7\n2015-03-04 06:57:53,19\n2015-03-04 07:02:53,9\n2015-03-04 07:07:53,10\n2015-03-04 07:12:53,24\n2015-03-04 07:17:53,8\n2015-03-04 07:22:53,12\n2015-03-04 07:27:53,15\n2015-03-04 07:32:53,6\n2015-03-04 07:37:53,16\n2015-03-04 07:42:53,12\n2015-03-04 07:47:53,9\n2015-03-04 07:52:53,11\n2015-03-04 07:57:53,8\n2015-03-04 08:02:53,12\n2015-03-04 08:07:53,4\n2015-03-04 08:12:53,7\n2015-03-04 08:17:53,17\n2015-03-04 08:22:53,10\n2015-03-04 08:27:53,34\n2015-03-04 08:32:53,18\n2015-03-04 08:37:53,12\n2015-03-04 08:42:53,11\n2015-03-04 08:47:53,15\n2015-03-04 08:52:53,31\n2015-03-04 08:57:53,46\n2015-03-04 09:02:53,82\n2015-03-04 09:07:53,45\n2015-03-04 09:12:53,20\n2015-03-04 09:17:53,21\n2015-03-04 09:22:53,15\n2015-03-04 09:27:53,20\n2015-03-04 09:32:53,21\n2015-03-04 09:37:53,24\n2015-03-04 09:42:53,18\n2015-03-04 09:47:53,30\n2015-03-04 09:52:53,20\n2015-03-04 09:57:53,31\n2015-03-04 10:02:53,27\n2015-03-04 10:07:53,25\n2015-03-04 10:12:53,55\n2015-03-04 10:17:53,47\n2015-03-04 10:22:53,29\n2015-03-04 10:27:53,30\n2015-03-04 10:32:53,24\n2015-03-04 10:37:53,30\n2015-03-04 10:42:53,32\n2015-03-04 10:47:53,11\n2015-03-04 10:52:53,30\n2015-03-04 10:57:53,35\n2015-03-04 11:02:53,31\n2015-03-04 11:07:53,17\n2015-03-04 11:12:53,16\n2015-03-04 11:17:53,16\n2015-03-04 11:22:53,19\n2015-03-04 11:27:53,22\n2015-03-04 11:32:53,33\n2015-03-04 11:37:53,23\n2015-03-04 11:42:53,18\n2015-03-04 11:47:53,31\n2015-03-04 11:52:53,22\n2015-03-04 11:57:53,19\n2015-03-04 12:02:53,12\n2015-03-04 12:07:53,14\n2015-03-04 12:12:53,27\n2015-03-04 12:17:53,21\n2015-03-04 12:22:53,22\n2015-03-04 12:27:53,20\n2015-03-04 12:32:53,26\n2015-03-04 12:37:53,14\n2015-03-04 12:42:53,18\n2015-03-04 12:47:53,36\n2015-03-04 12:52:53,15\n2015-03-04 12:57:53,27\n2015-03-04 13:02:53,19\n2015-03-04 13:07:53,16\n2015-03-04 13:12:53,26\n2015-03-04 13:17:53,16\n2015-03-04 13:22:53,20\n2015-03-04 13:27:53,23\n2015-03-04 13:32:53,24\n2015-03-04 13:37:53,27\n2015-03-04 13:42:53,33\n2015-03-04 13:47:53,30\n2015-03-04 13:52:53,11\n2015-03-04 13:57:53,30\n2015-03-04 14:02:53,28\n2015-03-04 14:07:53,19\n2015-03-04 14:12:53,21\n2015-03-04 14:17:53,26\n2015-03-04 14:22:53,184\n2015-03-04 14:27:53,144\n2015-03-04 14:32:53,89\n2015-03-04 14:37:53,59\n2015-03-04 14:42:53,56\n2015-03-04 14:47:53,45\n2015-03-04 14:52:53,56\n2015-03-04 14:57:53,71\n2015-03-04 15:02:53,44\n2015-03-04 15:07:53,67\n2015-03-04 15:12:53,58\n2015-03-04 15:17:53,58\n2015-03-04 15:22:53,49\n2015-03-04 15:27:53,40\n2015-03-04 15:32:53,46\n2015-03-04 15:37:53,46\n2015-03-04 15:42:53,36\n2015-03-04 15:47:53,42\n2015-03-04 15:52:53,39\n2015-03-04 15:57:53,33\n2015-03-04 16:02:53,48\n2015-03-04 16:07:53,70\n2015-03-04 16:12:53,56\n2015-03-04 16:17:53,41\n2015-03-04 16:22:53,38\n2015-03-04 16:27:53,54\n2015-03-04 16:32:53,31\n2015-03-04 16:37:53,32\n2015-03-04 16:42:53,38\n2015-03-04 16:47:53,36\n2015-03-04 16:52:53,37\n2015-03-04 16:57:53,33\n2015-03-04 17:02:53,29\n2015-03-04 17:07:53,42\n2015-03-04 17:12:53,38\n2015-03-04 17:17:53,31\n2015-03-04 17:22:53,20\n2015-03-04 17:27:53,32\n2015-03-04 17:32:53,29\n2015-03-04 17:37:53,35\n2015-03-04 17:42:53,36\n2015-03-04 17:47:53,29\n2015-03-04 17:52:53,31\n2015-03-04 17:57:53,50\n2015-03-04 18:02:53,19\n2015-03-04 18:07:53,36\n2015-03-04 18:12:53,25\n2015-03-04 18:17:53,19\n2015-03-04 18:22:53,21\n2015-03-04 18:27:53,26\n2015-03-04 18:32:53,19\n2015-03-04 18:37:53,28\n2015-03-04 18:42:53,21\n2015-03-04 18:47:53,35\n2015-03-04 18:52:53,33\n2015-03-04 18:57:53,51\n2015-03-04 19:02:53,36\n2015-03-04 19:07:53,21\n2015-03-04 19:12:53,33\n2015-03-04 19:17:53,29\n2015-03-04 19:22:53,29\n2015-03-04 19:27:53,48\n2015-03-04 19:32:53,30\n2015-03-04 19:37:53,42\n2015-03-04 19:42:53,21\n2015-03-04 19:47:53,28\n2015-03-04 19:52:53,37\n2015-03-04 19:57:53,43\n2015-03-04 20:02:53,31\n2015-03-04 20:07:53,24\n2015-03-04 20:12:53,24\n2015-03-04 20:17:53,31\n2015-03-04 20:22:53,19\n2015-03-04 20:27:53,29\n2015-03-04 20:32:53,36\n2015-03-04 20:37:53,29\n2015-03-04 20:42:53,27\n2015-03-04 20:47:53,21\n2015-03-04 20:52:53,22\n2015-03-04 20:57:53,37\n2015-03-04 21:02:53,28\n2015-03-04 21:07:53,16\n2015-03-04 21:12:53,21\n2015-03-04 21:17:53,28\n2015-03-04 21:22:53,25\n2015-03-04 21:27:53,28\n2015-03-04 21:32:53,21\n2015-03-04 21:37:53,8\n2015-03-04 21:42:53,26\n2015-03-04 21:47:53,21\n2015-03-04 21:52:53,26\n2015-03-04 21:57:53,20\n2015-03-04 22:02:53,17\n2015-03-04 22:07:53,19\n2015-03-04 22:12:53,16\n2015-03-04 22:17:53,14\n2015-03-04 22:22:53,16\n2015-03-04 22:27:53,23\n2015-03-04 22:32:53,16\n2015-03-04 22:37:53,12\n2015-03-04 22:42:53,14\n2015-03-04 22:47:53,12\n2015-03-04 22:52:53,17\n2015-03-04 22:57:53,17\n2015-03-04 23:02:53,26\n2015-03-04 23:07:53,19\n2015-03-04 23:12:53,14\n2015-03-04 23:17:53,27\n2015-03-04 23:22:53,16\n2015-03-04 23:27:53,35\n2015-03-04 23:32:53,21\n2015-03-04 23:37:53,24\n2015-03-04 23:42:53,12\n2015-03-04 23:47:53,15\n2015-03-04 23:52:53,12\n2015-03-04 23:57:53,22\n2015-03-05 00:02:53,17\n2015-03-05 00:07:53,17\n2015-03-05 00:12:53,20\n2015-03-05 00:17:53,11\n2015-03-05 00:22:53,9\n2015-03-05 00:27:53,24\n2015-03-05 00:32:53,21\n2015-03-05 00:37:53,18\n2015-03-05 00:42:53,16\n2015-03-05 00:47:53,17\n2015-03-05 00:52:53,22\n2015-03-05 00:57:53,23\n2015-03-05 01:02:53,15\n2015-03-05 01:07:53,19\n2015-03-05 01:12:53,16\n2015-03-05 01:17:53,24\n2015-03-05 01:22:53,19\n2015-03-05 01:27:53,14\n2015-03-05 01:32:53,7\n2015-03-05 01:37:53,12\n2015-03-05 01:42:53,19\n2015-03-05 01:47:53,14\n2015-03-05 01:52:53,22\n2015-03-05 01:57:53,15\n2015-03-05 02:02:53,17\n2015-03-05 02:07:53,19\n2015-03-05 02:12:53,18\n2015-03-05 02:17:53,16\n2015-03-05 02:22:53,14\n2015-03-05 02:27:53,21\n2015-03-05 02:32:53,27\n2015-03-05 02:37:53,20\n2015-03-05 02:42:53,15\n2015-03-05 02:47:53,18\n2015-03-05 02:52:53,17\n2015-03-05 02:57:53,14\n2015-03-05 03:02:53,10\n2015-03-05 03:07:53,19\n2015-03-05 03:12:53,24\n2015-03-05 03:17:53,11\n2015-03-05 03:22:53,9\n2015-03-05 03:27:53,27\n2015-03-05 03:32:53,14\n2015-03-05 03:37:53,6\n2015-03-05 03:42:53,17\n2015-03-05 03:47:53,11\n2015-03-05 03:52:53,10\n2015-03-05 03:57:53,18\n2015-03-05 04:02:53,34\n2015-03-05 04:07:53,18\n2015-03-05 04:12:53,24\n2015-03-05 04:17:53,22\n2015-03-05 04:22:53,18\n2015-03-05 04:27:53,7\n2015-03-05 04:32:53,24\n2015-03-05 04:37:53,17\n2015-03-05 04:42:53,20\n2015-03-05 04:47:53,26\n2015-03-05 04:52:53,21\n2015-03-05 04:57:53,21\n2015-03-05 05:02:53,21\n2015-03-05 05:07:53,22\n2015-03-05 05:12:53,27\n2015-03-05 05:17:53,14\n2015-03-05 05:22:53,15\n2015-03-05 05:27:53,18\n2015-03-05 05:32:53,4\n2015-03-05 05:37:53,25\n2015-03-05 05:42:53,21\n2015-03-05 05:47:53,21\n2015-03-05 05:52:53,17\n2015-03-05 05:57:53,12\n2015-03-05 06:02:53,15\n2015-03-05 06:07:53,9\n2015-03-05 06:12:53,10\n2015-03-05 06:17:53,9\n2015-03-05 06:22:53,17\n2015-03-05 06:27:53,9\n2015-03-05 06:32:53,15\n2015-03-05 06:37:53,13\n2015-03-05 06:42:53,14\n2015-03-05 06:47:53,10\n2015-03-05 06:52:53,19\n2015-03-05 06:57:53,8\n2015-03-05 07:02:53,15\n2015-03-05 07:07:53,15\n2015-03-05 07:12:53,14\n2015-03-05 07:17:53,20\n2015-03-05 07:22:53,25\n2015-03-05 07:27:53,23\n2015-03-05 07:32:53,19\n2015-03-05 07:37:53,13\n2015-03-05 07:42:53,16\n2015-03-05 07:47:53,12\n2015-03-05 07:52:53,12\n2015-03-05 07:57:53,23\n2015-03-05 08:02:53,15\n2015-03-05 08:07:53,22\n2015-03-05 08:12:53,18\n2015-03-05 08:17:53,21\n2015-03-05 08:22:53,16\n2015-03-05 08:27:53,13\n2015-03-05 08:32:53,19\n2015-03-05 08:37:53,22\n2015-03-05 08:42:53,18\n2015-03-05 08:47:53,11\n2015-03-05 08:52:53,7\n2015-03-05 08:57:53,27\n2015-03-05 09:02:53,12\n2015-03-05 09:07:53,11\n2015-03-05 09:12:53,16\n2015-03-05 09:17:53,22\n2015-03-05 09:22:53,16\n2015-03-05 09:27:53,35\n2015-03-05 09:32:53,26\n2015-03-05 09:37:53,10\n2015-03-05 09:42:53,25\n2015-03-05 09:47:53,20\n2015-03-05 09:52:53,24\n2015-03-05 09:57:53,26\n2015-03-05 10:02:53,16\n2015-03-05 10:07:53,22\n2015-03-05 10:12:53,15\n2015-03-05 10:17:53,15\n2015-03-05 10:22:53,15\n2015-03-05 10:27:53,14\n2015-03-05 10:32:53,14\n2015-03-05 10:37:53,16\n2015-03-05 10:42:53,14\n2015-03-05 10:47:53,14\n2015-03-05 10:52:53,5\n2015-03-05 10:57:53,27\n2015-03-05 11:02:53,19\n2015-03-05 11:07:53,19\n2015-03-05 11:12:53,17\n2015-03-05 11:17:53,33\n2015-03-05 11:22:53,30\n2015-03-05 11:27:53,16\n2015-03-05 11:32:53,21\n2015-03-05 11:37:53,13\n2015-03-05 11:42:53,15\n2015-03-05 11:47:53,18\n2015-03-05 11:52:53,13\n2015-03-05 11:57:53,13\n2015-03-05 12:02:53,16\n2015-03-05 12:07:53,12\n2015-03-05 12:12:53,12\n2015-03-05 12:17:53,23\n2015-03-05 12:22:53,34\n2015-03-05 12:27:53,14\n2015-03-05 12:32:53,25\n2015-03-05 12:37:53,20\n2015-03-05 12:42:53,15\n2015-03-05 12:47:53,24\n2015-03-05 12:52:53,52\n2015-03-05 12:57:53,82\n2015-03-05 13:02:53,92\n2015-03-05 13:07:53,106\n2015-03-05 13:12:53,103\n2015-03-05 13:17:53,86\n2015-03-05 13:22:53,88\n2015-03-05 13:27:53,75\n2015-03-05 13:32:53,41\n2015-03-05 13:37:53,20\n2015-03-05 13:42:53,67\n2015-03-05 13:47:53,26\n2015-03-05 13:52:53,30\n2015-03-05 13:57:53,33\n2015-03-05 14:02:53,16\n2015-03-05 14:07:53,16\n2015-03-05 14:12:53,21\n2015-03-05 14:17:53,18\n2015-03-05 14:22:53,21\n2015-03-05 14:27:53,18\n2015-03-05 14:32:53,16\n2015-03-05 14:37:53,20\n2015-03-05 14:42:53,28\n2015-03-05 14:47:53,24\n2015-03-05 14:52:53,24\n2015-03-05 14:57:53,76\n2015-03-05 15:02:53,52\n2015-03-05 15:07:53,54\n2015-03-05 15:12:53,56\n2015-03-05 15:17:53,41\n2015-03-05 15:22:53,43\n2015-03-05 15:27:53,38\n2015-03-05 15:32:53,42\n2015-03-05 15:37:53,33\n2015-03-05 15:42:53,27\n2015-03-05 15:47:53,31\n2015-03-05 15:52:53,32\n2015-03-05 15:57:53,46\n2015-03-05 16:02:53,36\n2015-03-05 16:07:53,26\n2015-03-05 16:12:53,36\n2015-03-05 16:17:53,40\n2015-03-05 16:22:53,39\n2015-03-05 16:27:53,50\n2015-03-05 16:32:53,51\n2015-03-05 16:37:53,35\n2015-03-05 16:42:53,29\n2015-03-05 16:47:53,35\n2015-03-05 16:52:53,28\n2015-03-05 16:57:53,23\n2015-03-05 17:02:53,31\n2015-03-05 17:07:53,33\n2015-03-05 17:12:53,32\n2015-03-05 17:17:53,39\n2015-03-05 17:22:53,24\n2015-03-05 17:27:53,27\n2015-03-05 17:32:53,40\n2015-03-05 17:37:53,24\n2015-03-05 17:42:53,27\n2015-03-05 17:47:53,44\n2015-03-05 17:52:53,40\n2015-03-05 17:57:53,29\n2015-03-05 18:02:53,26\n2015-03-05 18:07:53,25\n2015-03-05 18:12:53,24\n2015-03-05 18:17:53,12\n2015-03-05 18:22:53,21\n2015-03-05 18:27:53,27\n2015-03-05 18:32:53,31\n2015-03-05 18:37:53,22\n2015-03-05 18:42:53,24\n2015-03-05 18:47:53,28\n2015-03-05 18:52:53,20\n2015-03-05 18:57:53,29\n2015-03-05 19:02:53,25\n2015-03-05 19:07:53,15\n2015-03-05 19:12:53,28\n2015-03-05 19:17:53,29\n2015-03-05 19:22:53,28\n2015-03-05 19:27:53,30\n2015-03-05 19:32:53,21\n2015-03-05 19:37:53,16\n2015-03-05 19:42:53,26\n2015-03-05 19:47:53,37\n2015-03-05 19:52:53,39\n2015-03-05 19:57:53,24\n2015-03-05 20:02:53,28\n2015-03-05 20:07:53,23\n2015-03-05 20:12:53,43\n2015-03-05 20:17:53,52\n2015-03-05 20:22:53,90\n2015-03-05 20:27:53,49\n2015-03-05 20:32:53,45\n2015-03-05 20:37:53,78\n2015-03-05 20:42:53,53\n2015-03-05 20:47:53,49\n2015-03-05 20:52:53,35\n2015-03-05 20:57:53,51\n2015-03-05 21:02:53,34\n2015-03-05 21:07:53,33\n2015-03-05 21:12:53,29\n2015-03-05 21:17:53,32\n2015-03-05 21:22:53,40\n2015-03-05 21:27:53,40\n2015-03-05 21:32:53,27\n2015-03-05 21:37:53,20\n2015-03-05 21:42:53,32\n2015-03-05 21:47:53,40\n2015-03-05 21:52:53,35\n2015-03-05 21:57:53,75\n2015-03-05 22:02:53,31\n2015-03-05 22:07:53,24\n2015-03-05 22:12:53,21\n2015-03-05 22:17:53,24\n2015-03-05 22:22:53,26\n2015-03-05 22:27:53,19\n2015-03-05 22:32:53,15\n2015-03-05 22:37:53,23\n2015-03-05 22:42:53,29\n2015-03-05 22:47:53,20\n2015-03-05 22:52:53,34\n2015-03-05 22:57:53,26\n2015-03-05 23:02:53,17\n2015-03-05 23:07:53,14\n2015-03-05 23:12:53,27\n2015-03-05 23:17:53,21\n2015-03-05 23:22:53,32\n2015-03-05 23:27:53,40\n2015-03-05 23:32:53,53\n2015-03-05 23:37:53,28\n2015-03-05 23:42:53,23\n2015-03-05 23:47:53,23\n2015-03-05 23:52:53,29\n2015-03-05 23:57:53,30\n2015-03-06 00:02:53,38\n2015-03-06 00:07:53,34\n2015-03-06 00:12:53,28\n2015-03-06 00:17:53,21\n2015-03-06 00:22:53,19\n2015-03-06 00:27:53,18\n2015-03-06 00:32:53,25\n2015-03-06 00:37:53,20\n2015-03-06 00:42:53,28\n2015-03-06 00:47:53,20\n2015-03-06 00:52:53,30\n2015-03-06 00:57:53,33\n2015-03-06 01:02:53,17\n2015-03-06 01:07:53,9\n2015-03-06 01:12:53,28\n2015-03-06 01:17:53,8\n2015-03-06 01:22:53,21\n2015-03-06 01:27:53,18\n2015-03-06 01:32:53,25\n2015-03-06 01:37:53,22\n2015-03-06 01:42:53,17\n2015-03-06 01:47:53,60\n2015-03-06 01:52:53,40\n2015-03-06 01:57:53,36\n2015-03-06 02:02:53,13\n2015-03-06 02:07:53,19\n2015-03-06 02:12:53,20\n2015-03-06 02:17:53,21\n2015-03-06 02:22:53,30\n2015-03-06 02:27:53,30\n2015-03-06 02:32:53,29\n2015-03-06 02:37:53,17\n2015-03-06 02:42:53,24\n2015-03-06 02:47:53,14\n2015-03-06 02:52:53,21\n2015-03-06 02:57:53,18\n2015-03-06 03:02:53,21\n2015-03-06 03:07:53,15\n2015-03-06 03:12:53,31\n2015-03-06 03:17:53,22\n2015-03-06 03:22:53,13\n2015-03-06 03:27:53,21\n2015-03-06 03:32:53,19\n2015-03-06 03:37:53,9\n2015-03-06 03:42:53,25\n2015-03-06 03:47:53,19\n2015-03-06 03:52:53,13\n2015-03-06 03:57:53,51\n2015-03-06 04:02:53,13\n2015-03-06 04:07:53,16\n2015-03-06 04:12:53,31\n2015-03-06 04:17:53,7\n2015-03-06 04:22:53,15\n2015-03-06 04:27:53,15\n2015-03-06 04:32:53,15\n2015-03-06 04:37:53,16\n2015-03-06 04:42:53,11\n2015-03-06 04:47:53,8\n2015-03-06 04:52:53,15\n2015-03-06 04:57:53,31\n2015-03-06 05:02:53,9\n2015-03-06 05:07:53,8\n2015-03-06 05:12:53,12\n2015-03-06 05:17:53,9\n2015-03-06 05:22:53,18\n2015-03-06 05:27:53,14\n2015-03-06 05:32:53,12\n2015-03-06 05:37:53,12\n2015-03-06 05:42:53,13\n2015-03-06 05:47:53,6\n2015-03-06 05:52:53,9\n2015-03-06 05:57:53,20\n2015-03-06 06:02:53,13\n2015-03-06 06:07:53,10\n2015-03-06 06:12:53,12\n2015-03-06 06:17:53,14\n2015-03-06 06:22:53,12\n2015-03-06 06:27:53,13\n2015-03-06 06:32:53,15\n2015-03-06 06:37:53,10\n2015-03-06 06:42:53,20\n2015-03-06 06:47:53,8\n2015-03-06 06:52:53,15\n2015-03-06 06:57:53,23\n2015-03-06 07:02:53,12\n2015-03-06 07:07:53,10\n2015-03-06 07:12:53,26\n2015-03-06 07:17:53,7\n2015-03-06 07:22:53,5\n2015-03-06 07:27:53,18\n2015-03-06 07:32:53,3\n2015-03-06 07:37:53,12\n2015-03-06 07:42:53,9\n2015-03-06 07:47:53,7\n2015-03-06 07:52:53,9\n2015-03-06 07:57:53,21\n2015-03-06 08:02:53,11\n2015-03-06 08:07:53,35\n2015-03-06 08:12:53,15\n2015-03-06 08:17:53,11\n2015-03-06 08:22:53,11\n2015-03-06 08:27:53,17\n2015-03-06 08:32:53,8\n2015-03-06 08:37:53,10\n2015-03-06 08:42:53,7\n2015-03-06 08:47:53,12\n2015-03-06 08:52:53,15\n2015-03-06 08:57:53,22\n2015-03-06 09:02:53,12\n2015-03-06 09:07:53,17\n2015-03-06 09:12:53,11\n2015-03-06 09:17:53,17\n2015-03-06 09:22:53,13\n2015-03-06 09:27:53,15\n2015-03-06 09:32:53,10\n2015-03-06 09:37:53,9\n2015-03-06 09:42:53,13\n2015-03-06 09:47:53,5\n2015-03-06 09:52:53,12\n2015-03-06 09:57:53,13\n2015-03-06 10:02:53,10\n2015-03-06 10:07:53,15\n2015-03-06 10:12:53,11\n2015-03-06 10:17:53,12\n2015-03-06 10:22:53,15\n2015-03-06 10:27:53,9\n2015-03-06 10:32:53,16\n2015-03-06 10:37:53,9\n2015-03-06 10:42:53,15\n2015-03-06 10:47:53,13\n2015-03-06 10:52:53,22\n2015-03-06 10:57:53,17\n2015-03-06 11:02:53,20\n2015-03-06 11:07:53,13\n2015-03-06 11:12:53,12\n2015-03-06 11:17:53,17\n2015-03-06 11:22:53,17\n2015-03-06 11:27:53,18\n2015-03-06 11:32:53,5\n2015-03-06 11:37:53,5\n2015-03-06 11:42:53,13\n2015-03-06 11:47:53,18\n2015-03-06 11:52:53,22\n2015-03-06 11:57:53,19\n2015-03-06 12:02:53,8\n2015-03-06 12:07:53,16\n2015-03-06 12:12:53,28\n2015-03-06 12:17:53,13\n2015-03-06 12:22:53,29\n2015-03-06 12:27:53,22\n2015-03-06 12:32:53,13\n2015-03-06 12:37:53,22\n2015-03-06 12:42:53,24\n2015-03-06 12:47:53,19\n2015-03-06 12:52:53,17\n2015-03-06 12:57:53,26\n2015-03-06 13:02:53,22\n2015-03-06 13:07:53,25\n2015-03-06 13:12:53,14\n2015-03-06 13:17:53,18\n2015-03-06 13:22:53,13\n2015-03-06 13:27:53,29\n2015-03-06 13:32:53,16\n2015-03-06 13:37:53,36\n2015-03-06 13:42:53,49\n2015-03-06 13:47:53,27\n2015-03-06 13:52:53,36\n2015-03-06 13:57:53,34\n2015-03-06 14:02:53,25\n2015-03-06 14:07:53,29\n2015-03-06 14:12:53,31\n2015-03-06 14:17:53,21\n2015-03-06 14:22:53,38\n2015-03-06 14:27:53,18\n2015-03-06 14:32:53,23\n2015-03-06 14:37:53,27\n2015-03-06 14:42:53,15\n2015-03-06 14:47:53,14\n2015-03-06 14:52:53,17\n2015-03-06 14:57:53,20\n2015-03-06 15:02:53,18\n2015-03-06 15:07:53,35\n2015-03-06 15:12:53,27\n2015-03-06 15:17:53,31\n2015-03-06 15:22:53,25\n2015-03-06 15:27:53,37\n2015-03-06 15:32:53,21\n2015-03-06 15:37:53,18\n2015-03-06 15:42:53,24\n2015-03-06 15:47:53,28\n2015-03-06 15:52:53,21\n2015-03-06 15:57:53,27\n2015-03-06 16:02:53,23\n2015-03-06 16:07:53,17\n2015-03-06 16:12:53,17\n2015-03-06 16:17:53,24\n2015-03-06 16:22:53,20\n2015-03-06 16:27:53,46\n2015-03-06 16:32:53,25\n2015-03-06 16:37:53,44\n2015-03-06 16:42:53,22\n2015-03-06 16:47:53,17\n2015-03-06 16:52:53,23\n2015-03-06 16:57:53,28\n2015-03-06 17:02:53,20\n2015-03-06 17:07:53,25\n2015-03-06 17:12:53,21\n2015-03-06 17:17:53,19\n2015-03-06 17:22:53,24\n2015-03-06 17:27:53,32\n2015-03-06 17:32:53,20\n2015-03-06 17:37:53,15\n2015-03-06 17:42:53,22\n2015-03-06 17:47:53,34\n2015-03-06 17:52:53,16\n2015-03-06 17:57:53,18\n2015-03-06 18:02:53,24\n2015-03-06 18:07:53,16\n2015-03-06 18:12:53,9\n2015-03-06 18:17:53,16\n2015-03-06 18:22:53,23\n2015-03-06 18:27:53,27\n2015-03-06 18:32:53,29\n2015-03-06 18:37:53,16\n2015-03-06 18:42:53,19\n2015-03-06 18:47:53,20\n2015-03-06 18:52:53,57\n2015-03-06 18:57:53,63\n2015-03-06 19:02:53,41\n2015-03-06 19:07:53,37\n2015-03-06 19:12:53,16\n2015-03-06 19:17:53,15\n2015-03-06 19:22:53,13\n2015-03-06 19:27:53,19\n2015-03-06 19:32:53,18\n2015-03-06 19:37:53,31\n2015-03-06 19:42:53,24\n2015-03-06 19:47:53,20\n2015-03-06 19:52:53,20\n2015-03-06 19:57:53,30\n2015-03-06 20:02:53,23\n2015-03-06 20:07:53,12\n2015-03-06 20:12:53,22\n2015-03-06 20:17:53,14\n2015-03-06 20:22:53,23\n2015-03-06 20:27:53,20\n2015-03-06 20:32:53,56\n2015-03-06 20:37:53,112\n2015-03-06 20:42:53,69\n2015-03-06 20:47:53,51\n2015-03-06 20:52:53,61\n2015-03-06 20:57:53,65\n2015-03-06 21:02:53,29\n2015-03-06 21:07:53,36\n2015-03-06 21:12:53,29\n2015-03-06 21:17:53,49\n2015-03-06 21:22:53,47\n2015-03-06 21:27:53,42\n2015-03-06 21:32:53,41\n2015-03-06 21:37:53,27\n2015-03-06 21:42:53,28\n2015-03-06 21:47:53,21\n2015-03-06 21:52:53,30\n2015-03-06 21:57:53,27\n2015-03-06 22:02:53,18\n2015-03-06 22:07:53,22\n2015-03-06 22:12:53,18\n2015-03-06 22:17:53,34\n2015-03-06 22:22:53,28\n2015-03-06 22:27:53,37\n2015-03-06 22:32:53,20\n2015-03-06 22:37:53,26\n2015-03-06 22:42:53,26\n2015-03-06 22:47:53,60\n2015-03-06 22:52:53,37\n2015-03-06 22:57:53,34\n2015-03-06 23:02:53,25\n2015-03-06 23:07:53,22\n2015-03-06 23:12:53,21\n2015-03-06 23:17:53,25\n2015-03-06 23:22:53,14\n2015-03-06 23:27:53,17\n2015-03-06 23:32:53,24\n2015-03-06 23:37:53,38\n2015-03-06 23:42:53,25\n2015-03-06 23:47:53,29\n2015-03-06 23:52:53,32\n2015-03-06 23:57:53,36\n2015-03-07 00:02:53,18\n2015-03-07 00:07:53,17\n2015-03-07 00:12:53,20\n2015-03-07 00:17:53,18\n2015-03-07 00:22:53,14\n2015-03-07 00:27:53,34\n2015-03-07 00:32:53,25\n2015-03-07 00:37:53,9\n2015-03-07 00:42:53,15\n2015-03-07 00:47:53,9\n2015-03-07 00:52:53,6\n2015-03-07 00:57:53,9\n2015-03-07 01:02:53,24\n2015-03-07 01:07:53,9\n2015-03-07 01:12:53,13\n2015-03-07 01:17:53,10\n2015-03-07 01:22:53,22\n2015-03-07 01:27:53,9\n2015-03-07 01:32:53,9\n2015-03-07 01:37:53,20\n2015-03-07 01:42:53,20\n2015-03-07 01:47:53,13\n2015-03-07 01:52:53,13\n2015-03-07 01:57:53,22\n2015-03-07 02:02:53,15\n2015-03-07 02:07:53,8\n2015-03-07 02:12:53,11\n2015-03-07 02:17:53,21\n2015-03-07 02:22:53,11\n2015-03-07 02:27:53,16\n2015-03-07 02:32:53,17\n2015-03-07 02:37:53,21\n2015-03-07 02:42:53,22\n2015-03-07 02:47:53,11\n2015-03-07 02:52:53,14\n2015-03-07 02:57:53,12\n2015-03-07 03:02:53,11\n2015-03-07 03:07:53,7\n2015-03-07 03:12:53,15\n2015-03-07 03:17:53,12\n2015-03-07 03:22:53,10\n2015-03-07 03:27:53,9\n2015-03-07 03:32:53,5\n2015-03-07 03:37:53,4\n2015-03-07 03:42:53,9\n2015-03-07 03:47:53,12\n2015-03-07 03:52:53,13\n2015-03-07 03:57:53,13\n2015-03-07 04:02:53,6\n2015-03-07 04:07:53,25\n2015-03-07 04:12:53,3\n2015-03-07 04:17:53,13\n2015-03-07 04:22:53,7\n2015-03-07 04:27:53,8\n2015-03-07 04:32:53,7\n2015-03-07 04:37:53,12\n2015-03-07 04:42:53,6\n2015-03-07 04:47:53,5\n2015-03-07 04:52:53,6\n2015-03-07 04:57:53,15\n2015-03-07 05:02:53,22\n2015-03-07 05:07:53,16\n2015-03-07 05:12:53,12\n2015-03-07 05:17:53,6\n2015-03-07 05:22:53,14\n2015-03-07 05:27:53,7\n2015-03-07 05:32:53,13\n2015-03-07 05:37:53,17\n2015-03-07 05:42:53,5\n2015-03-07 05:47:53,13\n2015-03-07 05:52:53,15\n2015-03-07 05:57:53,12\n2015-03-07 06:02:53,16\n2015-03-07 06:07:53,7\n2015-03-07 06:12:53,11\n2015-03-07 06:17:53,8\n2015-03-07 06:22:53,15\n2015-03-07 06:27:53,11\n2015-03-07 06:32:53,10\n2015-03-07 06:37:53,10\n2015-03-07 06:42:53,6\n2015-03-07 06:47:53,8\n2015-03-07 06:52:53,11\n2015-03-07 06:57:53,13\n2015-03-07 07:02:53,15\n2015-03-07 07:07:53,11\n2015-03-07 07:12:53,9\n2015-03-07 07:17:53,10\n2015-03-07 07:22:53,10\n2015-03-07 07:27:53,11\n2015-03-07 07:32:53,15\n2015-03-07 07:37:53,13\n2015-03-07 07:42:53,16\n2015-03-07 07:47:53,9\n2015-03-07 07:52:53,8\n2015-03-07 07:57:53,11\n2015-03-07 08:02:53,4\n2015-03-07 08:07:53,18\n2015-03-07 08:12:53,2\n2015-03-07 08:17:53,9\n2015-03-07 08:22:53,11\n2015-03-07 08:27:53,9\n2015-03-07 08:32:53,12\n2015-03-07 08:37:53,12\n2015-03-07 08:42:53,16\n2015-03-07 08:47:53,14\n2015-03-07 08:52:53,5\n2015-03-07 08:57:53,21\n2015-03-07 09:02:53,11\n2015-03-07 09:07:53,12\n2015-03-07 09:12:53,9\n2015-03-07 09:17:53,9\n2015-03-07 09:22:53,6\n2015-03-07 09:27:53,4\n2015-03-07 09:32:53,8\n2015-03-07 09:37:53,11\n2015-03-07 09:42:53,9\n2015-03-07 09:47:53,16\n2015-03-07 09:52:53,11\n2015-03-07 09:57:53,10\n2015-03-07 10:02:53,14\n2015-03-07 10:07:53,10\n2015-03-07 10:12:53,9\n2015-03-07 10:17:53,6\n2015-03-07 10:22:53,6\n2015-03-07 10:27:53,6\n2015-03-07 10:32:53,5\n2015-03-07 10:37:53,10\n2015-03-07 10:42:53,4\n2015-03-07 10:47:53,11\n2015-03-07 10:52:53,3\n2015-03-07 10:57:53,8\n2015-03-07 11:02:53,8\n2015-03-07 11:07:53,8\n2015-03-07 11:12:53,4\n2015-03-07 11:17:53,9\n2015-03-07 11:22:53,15\n2015-03-07 11:27:53,9\n2015-03-07 11:32:53,17\n2015-03-07 11:37:53,34\n2015-03-07 11:42:53,13\n2015-03-07 11:47:53,8\n2015-03-07 11:52:53,5\n2015-03-07 11:57:53,12\n2015-03-07 12:02:53,14\n2015-03-07 12:07:53,8\n2015-03-07 12:12:53,13\n2015-03-07 12:17:53,13\n2015-03-07 12:22:53,7\n2015-03-07 12:27:53,7\n2015-03-07 12:32:53,13\n2015-03-07 12:37:53,19\n2015-03-07 12:42:53,29\n2015-03-07 12:47:53,9\n2015-03-07 12:52:53,13\n2015-03-07 12:57:53,11\n2015-03-07 13:02:53,9\n2015-03-07 13:07:53,13\n2015-03-07 13:12:53,9\n2015-03-07 13:17:53,8\n2015-03-07 13:22:53,15\n2015-03-07 13:27:53,12\n2015-03-07 13:32:53,12\n2015-03-07 13:37:53,7\n2015-03-07 13:42:53,9\n2015-03-07 13:47:53,12\n2015-03-07 13:52:53,14\n2015-03-07 13:57:53,17\n2015-03-07 14:02:53,6\n2015-03-07 14:07:53,13\n2015-03-07 14:12:53,15\n2015-03-07 14:17:53,1\n2015-03-07 14:22:53,9\n2015-03-07 14:27:53,26\n2015-03-07 14:32:53,8\n2015-03-07 14:37:53,13\n2015-03-07 14:42:53,12\n2015-03-07 14:47:53,18\n2015-03-07 14:52:53,6\n2015-03-07 14:57:53,11\n2015-03-07 15:02:53,7\n2015-03-07 15:07:53,9\n2015-03-07 15:12:53,5\n2015-03-07 15:17:53,11\n2015-03-07 15:22:53,11\n2015-03-07 15:27:53,16\n2015-03-07 15:32:53,7\n2015-03-07 15:37:53,12\n2015-03-07 15:42:53,13\n2015-03-07 15:47:53,15\n2015-03-07 15:52:53,26\n2015-03-07 15:57:53,22\n2015-03-07 16:02:53,14\n2015-03-07 16:07:53,11\n2015-03-07 16:12:53,12\n2015-03-07 16:17:53,16\n2015-03-07 16:22:53,18\n2015-03-07 16:27:53,10\n2015-03-07 16:32:53,12\n2015-03-07 16:37:53,13\n2015-03-07 16:42:53,14\n2015-03-07 16:47:53,14\n2015-03-07 16:52:53,8\n2015-03-07 16:57:53,18\n2015-03-07 17:02:53,14\n2015-03-07 17:07:53,10\n2015-03-07 17:12:53,14\n2015-03-07 17:17:53,7\n2015-03-07 17:22:53,23\n2015-03-07 17:27:53,12\n2015-03-07 17:32:53,13\n2015-03-07 17:37:53,18\n2015-03-07 17:42:53,18\n2015-03-07 17:47:53,12\n2015-03-07 17:52:53,18\n2015-03-07 17:57:53,19\n2015-03-07 18:02:53,18\n2015-03-07 18:07:53,21\n2015-03-07 18:12:53,10\n2015-03-07 18:17:53,13\n2015-03-07 18:22:53,6\n2015-03-07 18:27:53,17\n2015-03-07 18:32:53,13\n2015-03-07 18:37:53,6\n2015-03-07 18:42:53,12\n2015-03-07 18:47:53,13\n2015-03-07 18:52:53,25\n2015-03-07 18:57:53,16\n2015-03-07 19:02:53,9\n2015-03-07 19:07:53,6\n2015-03-07 19:12:53,12\n2015-03-07 19:17:53,7\n2015-03-07 19:22:53,11\n2015-03-07 19:27:53,22\n2015-03-07 19:32:53,9\n2015-03-07 19:37:53,15\n2015-03-07 19:42:53,7\n2015-03-07 19:47:53,10\n2015-03-07 19:52:53,16\n2015-03-07 19:57:53,24\n2015-03-07 20:02:53,15\n2015-03-07 20:07:53,18\n2015-03-07 20:12:53,16\n2015-03-07 20:17:53,9\n2015-03-07 20:22:53,19\n2015-03-07 20:27:53,10\n2015-03-07 20:32:53,13\n2015-03-07 20:37:53,8\n2015-03-07 20:42:53,16\n2015-03-07 20:47:53,10\n2015-03-07 20:52:53,11\n2015-03-07 20:57:53,30\n2015-03-07 21:02:53,24\n2015-03-07 21:07:53,25\n2015-03-07 21:12:53,39\n2015-03-07 21:17:53,16\n2015-03-07 21:22:53,15\n2015-03-07 21:27:53,11\n2015-03-07 21:32:53,13\n2015-03-07 21:37:53,20\n2015-03-07 21:42:53,11\n2015-03-07 21:47:53,15\n2015-03-07 21:52:53,15\n2015-03-07 21:57:53,16\n2015-03-07 22:02:53,19\n2015-03-07 22:07:53,12\n2015-03-07 22:12:53,9\n2015-03-07 22:17:53,10\n2015-03-07 22:22:53,16\n2015-03-07 22:27:53,11\n2015-03-07 22:32:53,11\n2015-03-07 22:37:53,5\n2015-03-07 22:42:53,6\n2015-03-07 22:47:53,12\n2015-03-07 22:52:53,13\n2015-03-07 22:57:53,25\n2015-03-07 23:02:53,6\n2015-03-07 23:07:53,11\n2015-03-07 23:12:53,16\n2015-03-07 23:17:53,9\n2015-03-07 23:22:53,16\n2015-03-07 23:27:53,23\n2015-03-07 23:32:53,14\n2015-03-07 23:37:53,8\n2015-03-07 23:42:53,9\n2015-03-07 23:47:53,14\n2015-03-07 23:52:53,18\n2015-03-07 23:57:53,12\n2015-03-08 00:02:53,8\n2015-03-08 00:07:53,18\n2015-03-08 00:12:53,9\n2015-03-08 00:17:53,15\n2015-03-08 00:22:53,12\n2015-03-08 00:27:53,8\n2015-03-08 00:32:53,12\n2015-03-08 00:37:53,4\n2015-03-08 00:42:53,15\n2015-03-08 00:47:53,10\n2015-03-08 00:52:53,16\n2015-03-08 00:57:53,9\n2015-03-08 01:02:53,12\n2015-03-08 01:07:53,13\n2015-03-08 01:12:53,7\n2015-03-08 01:17:53,17\n2015-03-08 01:22:53,5\n2015-03-08 01:27:53,7\n2015-03-08 01:32:53,7\n2015-03-08 01:37:53,7\n2015-03-08 01:42:53,10\n2015-03-08 01:47:53,17\n2015-03-08 01:52:53,9\n2015-03-08 01:57:53,10\n2015-03-08 02:02:53,4\n2015-03-08 02:07:53,4\n2015-03-08 02:12:53,9\n2015-03-08 02:17:53,14\n2015-03-08 02:22:53,5\n2015-03-08 02:27:53,21\n2015-03-08 02:32:53,18\n2015-03-08 02:37:53,16\n2015-03-08 02:42:53,8\n2015-03-08 02:47:53,14\n2015-03-08 02:52:53,6\n2015-03-08 02:57:53,12\n2015-03-08 03:02:53,8\n2015-03-08 03:07:53,11\n2015-03-08 03:12:53,13\n2015-03-08 03:17:53,7\n2015-03-08 03:22:53,16\n2015-03-08 03:27:53,2\n2015-03-08 03:32:53,8\n2015-03-08 03:37:53,8\n2015-03-08 03:42:53,8\n2015-03-08 03:47:53,6\n2015-03-08 03:52:53,12\n2015-03-08 03:57:53,9\n2015-03-08 04:02:53,6\n2015-03-08 04:07:53,7\n2015-03-08 04:12:53,6\n2015-03-08 04:17:53,7\n2015-03-08 04:22:53,10\n2015-03-08 04:27:53,15\n2015-03-08 04:32:53,27\n2015-03-08 04:37:53,7\n2015-03-08 04:42:53,2\n2015-03-08 04:47:53,20\n2015-03-08 04:52:53,4\n2015-03-08 04:57:53,11\n2015-03-08 05:02:53,3\n2015-03-08 05:07:53,6\n2015-03-08 05:12:53,4\n2015-03-08 05:17:53,2\n2015-03-08 05:22:53,20\n2015-03-08 05:27:53,10\n2015-03-08 05:32:53,9\n2015-03-08 05:37:53,4\n2015-03-08 05:42:53,10\n2015-03-08 05:47:53,7\n2015-03-08 05:52:53,4\n2015-03-08 05:57:53,13\n2015-03-08 06:02:53,10\n2015-03-08 06:07:53,6\n2015-03-08 06:12:53,14\n2015-03-08 06:17:53,18\n2015-03-08 06:22:53,9\n2015-03-08 06:27:53,13\n2015-03-08 06:32:53,3\n2015-03-08 06:37:53,3\n2015-03-08 06:42:53,5\n2015-03-08 06:47:53,7\n2015-03-08 06:52:53,5\n2015-03-08 06:57:53,10\n2015-03-08 07:02:53,4\n2015-03-08 07:07:53,5\n2015-03-08 07:12:53,7\n2015-03-08 07:17:53,9\n2015-03-08 07:22:53,11\n2015-03-08 07:27:53,7\n2015-03-08 07:32:53,7\n2015-03-08 07:37:53,16\n2015-03-08 07:42:53,5\n2015-03-08 07:47:53,2\n2015-03-08 07:52:53,8\n2015-03-08 07:57:53,10\n2015-03-08 08:02:53,7\n2015-03-08 08:07:53,10\n2015-03-08 08:12:53,10\n2015-03-08 08:17:53,7\n2015-03-08 08:22:53,14\n2015-03-08 08:27:53,19\n2015-03-08 08:32:53,6\n2015-03-08 08:37:53,12\n2015-03-08 08:42:53,9\n2015-03-08 08:47:53,4\n2015-03-08 08:52:53,5\n2015-03-08 08:57:53,14\n2015-03-08 09:02:53,9\n2015-03-08 09:07:53,18\n2015-03-08 09:12:53,8\n2015-03-08 09:17:53,6\n2015-03-08 09:22:53,11\n2015-03-08 09:27:53,13\n2015-03-08 09:32:53,7\n2015-03-08 09:37:53,21\n2015-03-08 09:42:53,8\n2015-03-08 09:47:53,15\n2015-03-08 09:52:53,11\n2015-03-08 09:57:53,9\n2015-03-08 10:02:53,11\n2015-03-08 10:07:53,1\n2015-03-08 10:12:53,7\n2015-03-08 10:17:53,15\n2015-03-08 10:22:53,8\n2015-03-08 10:27:53,9\n2015-03-08 10:32:53,4\n2015-03-08 10:37:53,11\n2015-03-08 10:42:53,8\n2015-03-08 10:47:53,3\n2015-03-08 10:52:53,11\n2015-03-08 10:57:53,13\n2015-03-08 11:02:53,4\n2015-03-08 11:07:53,19\n2015-03-08 11:12:53,6\n2015-03-08 11:17:53,7\n2015-03-08 11:22:53,8\n2015-03-08 11:27:53,5\n2015-03-08 11:32:53,11\n2015-03-08 11:37:53,3\n2015-03-08 11:42:53,8\n2015-03-08 11:47:53,16\n2015-03-08 11:52:53,13\n2015-03-08 11:57:53,27\n2015-03-08 12:02:53,13\n2015-03-08 12:07:53,12\n2015-03-08 12:12:53,10\n2015-03-08 12:17:53,15\n2015-03-08 12:22:53,14\n2015-03-08 12:27:53,16\n2015-03-08 12:32:53,9\n2015-03-08 12:37:53,10\n2015-03-08 12:42:53,21\n2015-03-08 12:47:53,12\n2015-03-08 12:52:53,18\n2015-03-08 12:57:53,21\n2015-03-08 13:02:53,20\n2015-03-08 13:07:53,13\n2015-03-08 13:12:53,10\n2015-03-08 13:17:53,10\n2015-03-08 13:22:53,9\n2015-03-08 13:27:53,14\n2015-03-08 13:32:53,17\n2015-03-08 13:37:53,18\n2015-03-08 13:42:53,19\n2015-03-08 13:47:53,17\n2015-03-08 13:52:53,14\n2015-03-08 13:57:53,12\n2015-03-08 14:02:53,15\n2015-03-08 14:07:53,16\n2015-03-08 14:12:53,15\n2015-03-08 14:17:53,24\n2015-03-08 14:22:53,12\n2015-03-08 14:27:53,13\n2015-03-08 14:32:53,14\n2015-03-08 14:37:53,16\n2015-03-08 14:42:53,22\n2015-03-08 14:47:53,11\n2015-03-08 14:52:53,11\n2015-03-08 14:57:53,14\n2015-03-08 15:02:53,29\n2015-03-08 15:07:53,31\n2015-03-08 15:12:53,32\n2015-03-08 15:17:53,15\n2015-03-08 15:22:53,19\n2015-03-08 15:27:53,22\n2015-03-08 15:32:53,20\n2015-03-08 15:37:53,26\n2015-03-08 15:42:53,21\n2015-03-08 15:47:53,28\n2015-03-08 15:52:53,34\n2015-03-08 15:57:53,30\n2015-03-08 16:02:53,27\n2015-03-08 16:07:53,28\n2015-03-08 16:12:53,36\n2015-03-08 16:17:53,15\n2015-03-08 16:22:53,7\n2015-03-08 16:27:53,20\n2015-03-08 16:32:53,19\n2015-03-08 16:37:53,9\n2015-03-08 16:42:53,19\n2015-03-08 16:47:53,13\n2015-03-08 16:52:53,13\n2015-03-08 16:57:53,21\n2015-03-08 17:02:53,35\n2015-03-08 17:07:53,152\n2015-03-08 17:12:53,57\n2015-03-08 17:17:53,57\n2015-03-08 17:22:53,56\n2015-03-08 17:27:53,49\n2015-03-08 17:32:53,43\n2015-03-08 17:37:53,34\n2015-03-08 17:42:53,25\n2015-03-08 17:47:53,32\n2015-03-08 17:52:53,46\n2015-03-08 17:57:53,35\n2015-03-08 18:02:53,38\n2015-03-08 18:07:53,42\n2015-03-08 18:12:53,55\n2015-03-08 18:17:53,49\n2015-03-08 18:22:53,38\n2015-03-08 18:27:53,32\n2015-03-08 18:32:53,33\n2015-03-08 18:37:53,32\n2015-03-08 18:42:53,15\n2015-03-08 18:47:53,27\n2015-03-08 18:52:53,23\n2015-03-08 18:57:53,25\n2015-03-08 19:02:53,22\n2015-03-08 19:07:53,21\n2015-03-08 19:12:53,35\n2015-03-08 19:17:53,49\n2015-03-08 19:22:53,25\n2015-03-08 19:27:53,27\n2015-03-08 19:32:53,14\n2015-03-08 19:37:53,18\n2015-03-08 19:42:53,18\n2015-03-08 19:47:53,12\n2015-03-08 19:52:53,35\n2015-03-08 19:57:53,42\n2015-03-08 20:02:53,37\n2015-03-08 20:07:53,20\n2015-03-08 20:12:53,48\n2015-03-08 20:17:53,73\n2015-03-08 20:22:53,53\n2015-03-08 20:27:53,31\n2015-03-08 20:32:53,37\n2015-03-08 20:37:53,28\n2015-03-08 20:42:53,39\n2015-03-08 20:47:53,26\n2015-03-08 20:52:53,22\n2015-03-08 20:57:53,23\n2015-03-08 21:02:53,20\n2015-03-08 21:07:53,23\n2015-03-08 21:12:53,26\n2015-03-08 21:17:53,28\n2015-03-08 21:22:53,25\n2015-03-08 21:27:53,23\n2015-03-08 21:32:53,20\n2015-03-08 21:37:53,17\n2015-03-08 21:42:53,19\n2015-03-08 21:47:53,23\n2015-03-08 21:52:53,11\n2015-03-08 21:57:53,14\n2015-03-08 22:02:53,25\n2015-03-08 22:07:53,14\n2015-03-08 22:12:53,18\n2015-03-08 22:17:53,16\n2015-03-08 22:22:53,18\n2015-03-08 22:27:53,12\n2015-03-08 22:32:53,14\n2015-03-08 22:37:53,13\n2015-03-08 22:42:53,14\n2015-03-08 22:47:53,13\n2015-03-08 22:52:53,12\n2015-03-08 22:57:53,12\n2015-03-08 23:02:53,10\n2015-03-08 23:07:53,7\n2015-03-08 23:12:53,19\n2015-03-08 23:17:53,14\n2015-03-08 23:22:53,12\n2015-03-08 23:27:53,6\n2015-03-08 23:32:53,10\n2015-03-08 23:37:53,7\n2015-03-08 23:42:53,10\n2015-03-08 23:47:53,12\n2015-03-08 23:52:53,17\n2015-03-08 23:57:53,13\n2015-03-09 00:02:53,15\n2015-03-09 00:07:53,9\n2015-03-09 00:12:53,5\n2015-03-09 00:17:53,4\n2015-03-09 00:22:53,23\n2015-03-09 00:27:53,7\n2015-03-09 00:32:53,15\n2015-03-09 00:37:53,11\n2015-03-09 00:42:53,8\n2015-03-09 00:47:53,8\n2015-03-09 00:52:53,13\n2015-03-09 00:57:53,13\n2015-03-09 01:02:53,2\n2015-03-09 01:07:53,12\n2015-03-09 01:12:53,11\n2015-03-09 01:17:53,8\n2015-03-09 01:22:53,12\n2015-03-09 01:27:53,11\n2015-03-09 01:32:53,12\n2015-03-09 01:37:53,79\n2015-03-09 01:42:53,42\n2015-03-09 01:47:53,31\n2015-03-09 01:52:53,31\n2015-03-09 01:57:53,25\n2015-03-09 02:02:53,20\n2015-03-09 02:07:53,17\n2015-03-09 02:12:53,17\n2015-03-09 02:17:53,13\n2015-03-09 02:22:53,11\n2015-03-09 02:27:53,15\n2015-03-09 02:32:53,24\n2015-03-09 02:37:53,22\n2015-03-09 02:42:53,23\n2015-03-09 02:47:53,26\n2015-03-09 02:52:53,11\n2015-03-09 02:57:53,16\n2015-03-09 03:02:53,22\n2015-03-09 03:07:53,13\n2015-03-09 03:12:53,12\n2015-03-09 03:17:53,14\n2015-03-09 03:22:53,17\n2015-03-09 03:27:53,8\n2015-03-09 03:32:53,8\n2015-03-09 03:37:53,11\n2015-03-09 03:42:53,14\n2015-03-09 03:47:53,13\n2015-03-09 03:52:53,15\n2015-03-09 03:57:53,10\n2015-03-09 04:02:53,23\n2015-03-09 04:07:53,21\n2015-03-09 04:12:53,5\n2015-03-09 04:17:53,15\n2015-03-09 04:22:53,18\n2015-03-09 04:27:53,15\n2015-03-09 04:32:53,9\n2015-03-09 04:37:53,10\n2015-03-09 04:42:53,8\n2015-03-09 04:47:53,9\n2015-03-09 04:52:53,14\n2015-03-09 04:57:53,17\n2015-03-09 05:02:53,6\n2015-03-09 05:07:53,13\n2015-03-09 05:12:53,17\n2015-03-09 05:17:53,14\n2015-03-09 05:22:53,12\n2015-03-09 05:27:53,7\n2015-03-09 05:32:53,4\n2015-03-09 05:37:53,12\n2015-03-09 05:42:53,9\n2015-03-09 05:47:53,9\n2015-03-09 05:52:53,5\n2015-03-09 05:57:53,10\n2015-03-09 06:02:53,8\n2015-03-09 06:07:53,12\n2015-03-09 06:12:53,22\n2015-03-09 06:17:53,4\n2015-03-09 06:22:53,18\n2015-03-09 06:27:53,28\n2015-03-09 06:32:53,57\n2015-03-09 06:37:53,14\n2015-03-09 06:42:53,16\n2015-03-09 06:47:53,10\n2015-03-09 06:52:53,15\n2015-03-09 06:57:53,15\n2015-03-09 07:02:53,20\n2015-03-09 07:07:53,14\n2015-03-09 07:12:53,17\n2015-03-09 07:17:53,16\n2015-03-09 07:22:53,6\n2015-03-09 07:27:53,8\n2015-03-09 07:32:53,11\n2015-03-09 07:37:53,11\n2015-03-09 07:42:53,14\n2015-03-09 07:47:53,19\n2015-03-09 07:52:53,6\n2015-03-09 07:57:53,9\n2015-03-09 08:02:53,12\n2015-03-09 08:07:53,13\n2015-03-09 08:12:53,11\n2015-03-09 08:17:53,10\n2015-03-09 08:22:53,10\n2015-03-09 08:27:53,9\n2015-03-09 08:32:53,4\n2015-03-09 08:37:53,7\n2015-03-09 08:42:53,13\n2015-03-09 08:47:53,15\n2015-03-09 08:52:53,8\n2015-03-09 08:57:53,15\n2015-03-09 09:02:53,14\n2015-03-09 09:07:53,13\n2015-03-09 09:12:53,7\n2015-03-09 09:17:53,5\n2015-03-09 09:22:53,14\n2015-03-09 09:27:53,9\n2015-03-09 09:32:53,9\n2015-03-09 09:37:53,12\n2015-03-09 09:42:53,7\n2015-03-09 09:47:53,12\n2015-03-09 09:52:53,12\n2015-03-09 09:57:53,10\n2015-03-09 10:02:53,4\n2015-03-09 10:07:53,13\n2015-03-09 10:12:53,19\n2015-03-09 10:17:53,13\n2015-03-09 10:22:53,10\n2015-03-09 10:27:53,12\n2015-03-09 10:32:53,10\n2015-03-09 10:37:53,18\n2015-03-09 10:42:53,18\n2015-03-09 10:47:53,17\n2015-03-09 10:52:53,13\n2015-03-09 10:57:53,82\n2015-03-09 11:02:53,11\n2015-03-09 11:07:53,6\n2015-03-09 11:12:53,10\n2015-03-09 11:17:53,13\n2015-03-09 11:22:53,10\n2015-03-09 11:27:53,11\n2015-03-09 11:32:53,13\n2015-03-09 11:37:53,16\n2015-03-09 11:42:53,19\n2015-03-09 11:47:53,18\n2015-03-09 11:52:53,36\n2015-03-09 11:57:53,19\n2015-03-09 12:02:53,15\n2015-03-09 12:07:53,9\n2015-03-09 12:12:53,22\n2015-03-09 12:17:53,16\n2015-03-09 12:22:53,16\n2015-03-09 12:27:53,11\n2015-03-09 12:32:53,13\n2015-03-09 12:37:53,10\n2015-03-09 12:42:53,19\n2015-03-09 12:47:53,22\n2015-03-09 12:52:53,15\n2015-03-09 12:57:53,24\n2015-03-09 13:02:53,17\n2015-03-09 13:07:53,33\n2015-03-09 13:12:53,20\n2015-03-09 13:17:53,17\n2015-03-09 13:22:53,15\n2015-03-09 13:27:53,28\n2015-03-09 13:32:53,20\n2015-03-09 13:37:53,33\n2015-03-09 13:42:53,18\n2015-03-09 13:47:53,29\n2015-03-09 13:52:53,20\n2015-03-09 13:57:53,27\n2015-03-09 14:02:53,21\n2015-03-09 14:07:53,17\n2015-03-09 14:12:53,20\n2015-03-09 14:17:53,14\n2015-03-09 14:22:53,14\n2015-03-09 14:27:53,23\n2015-03-09 14:32:53,21\n2015-03-09 14:37:53,39\n2015-03-09 14:42:53,40\n2015-03-09 14:47:53,19\n2015-03-09 14:52:53,21\n2015-03-09 14:57:53,14\n2015-03-09 15:02:53,20\n2015-03-09 15:07:53,23\n2015-03-09 15:12:53,32\n2015-03-09 15:17:53,26\n2015-03-09 15:22:53,21\n2015-03-09 15:27:53,14\n2015-03-09 15:32:53,26\n2015-03-09 15:37:53,25\n2015-03-09 15:42:53,30\n2015-03-09 15:47:53,15\n2015-03-09 15:52:53,20\n2015-03-09 15:57:53,21\n2015-03-09 16:02:53,24\n2015-03-09 16:07:53,26\n2015-03-09 16:12:53,28\n2015-03-09 16:17:53,33\n2015-03-09 16:22:53,33\n2015-03-09 16:27:53,44\n2015-03-09 16:32:53,39\n2015-03-09 16:37:53,33\n2015-03-09 16:42:53,39\n2015-03-09 16:47:53,35\n2015-03-09 16:52:53,20\n2015-03-09 16:57:53,21\n2015-03-09 17:02:53,18\n2015-03-09 17:07:53,29\n2015-03-09 17:12:53,30\n2015-03-09 17:17:53,18\n2015-03-09 17:22:53,27\n2015-03-09 17:27:53,33\n2015-03-09 17:32:53,25\n2015-03-09 17:37:53,27\n2015-03-09 17:42:53,26\n2015-03-09 17:47:53,23\n2015-03-09 17:52:53,32\n2015-03-09 17:57:53,38\n2015-03-09 18:02:53,22\n2015-03-09 18:07:53,19\n2015-03-09 18:12:53,20\n2015-03-09 18:17:53,24\n2015-03-09 18:22:53,31\n2015-03-09 18:27:53,25\n2015-03-09 18:32:53,27\n2015-03-09 18:37:53,25\n2015-03-09 18:42:53,35\n2015-03-09 18:47:53,21\n2015-03-09 18:52:53,24\n2015-03-09 18:57:53,26\n2015-03-09 19:02:53,22\n2015-03-09 19:07:53,18\n2015-03-09 19:12:53,26\n2015-03-09 19:17:53,22\n2015-03-09 19:22:53,20\n2015-03-09 19:27:53,28\n2015-03-09 19:32:53,30\n2015-03-09 19:37:53,35\n2015-03-09 19:42:53,39\n2015-03-09 19:47:53,16\n2015-03-09 19:52:53,12\n2015-03-09 19:57:53,29\n2015-03-09 20:02:53,20\n2015-03-09 20:07:53,19\n2015-03-09 20:12:53,26\n2015-03-09 20:17:53,21\n2015-03-09 20:22:53,29\n2015-03-09 20:27:53,23\n2015-03-09 20:32:53,19\n2015-03-09 20:37:53,23\n2015-03-09 20:42:53,25\n2015-03-09 20:47:53,24\n2015-03-09 20:52:53,11\n2015-03-09 20:57:53,34\n2015-03-09 21:02:53,26\n2015-03-09 21:07:53,23\n2015-03-09 21:12:53,12\n2015-03-09 21:17:53,20\n2015-03-09 21:22:53,22\n2015-03-09 21:27:53,14\n2015-03-09 21:32:53,9\n2015-03-09 21:37:53,7\n2015-03-09 21:42:53,20\n2015-03-09 21:47:53,19\n2015-03-09 21:52:53,19\n2015-03-09 21:57:53,19\n2015-03-09 22:02:53,18\n2015-03-09 22:07:53,18\n2015-03-09 22:12:53,13\n2015-03-09 22:17:53,20\n2015-03-09 22:22:53,16\n2015-03-09 22:27:53,23\n2015-03-09 22:32:53,14\n2015-03-09 22:37:53,13\n2015-03-09 22:42:53,17\n2015-03-09 22:47:53,29\n2015-03-09 22:52:53,37\n2015-03-09 22:57:53,17\n2015-03-09 23:02:53,22\n2015-03-09 23:07:53,30\n2015-03-09 23:12:53,20\n2015-03-09 23:17:53,47\n2015-03-09 23:22:53,23\n2015-03-09 23:27:53,23\n2015-03-09 23:32:53,18\n2015-03-09 23:37:53,24\n2015-03-09 23:42:53,20\n2015-03-09 23:47:53,10\n2015-03-09 23:52:53,15\n2015-03-09 23:57:53,22\n2015-03-10 00:02:53,14\n2015-03-10 00:07:53,14\n2015-03-10 00:12:53,7\n2015-03-10 00:17:53,25\n2015-03-10 00:22:53,18\n2015-03-10 00:27:53,11\n2015-03-10 00:32:53,11\n2015-03-10 00:37:53,18\n2015-03-10 00:42:53,14\n2015-03-10 00:47:53,16\n2015-03-10 00:52:53,21\n2015-03-10 00:57:53,13\n2015-03-10 01:02:53,11\n2015-03-10 01:07:53,10\n2015-03-10 01:12:53,11\n2015-03-10 01:17:53,19\n2015-03-10 01:22:53,9\n2015-03-10 01:27:53,16\n2015-03-10 01:32:53,7\n2015-03-10 01:37:53,17\n2015-03-10 01:42:53,29\n2015-03-10 01:47:53,11\n2015-03-10 01:52:53,15\n2015-03-10 01:57:53,9\n2015-03-10 02:02:53,15\n2015-03-10 02:07:53,11\n2015-03-10 02:12:53,25\n2015-03-10 02:17:53,25\n2015-03-10 02:22:53,23\n2015-03-10 02:27:53,21\n2015-03-10 02:32:53,20\n2015-03-10 02:37:53,21\n2015-03-10 02:42:53,14\n2015-03-10 02:47:53,11\n2015-03-10 02:52:53,11\n2015-03-10 02:57:53,11\n2015-03-10 03:02:53,17\n2015-03-10 03:07:53,13\n2015-03-10 03:12:53,13\n2015-03-10 03:17:53,13\n2015-03-10 03:22:53,20\n2015-03-10 03:27:53,8\n2015-03-10 03:32:53,10\n2015-03-10 03:37:53,13\n2015-03-10 03:42:53,9\n2015-03-10 03:47:53,10\n2015-03-10 03:52:53,15\n2015-03-10 03:57:53,5\n2015-03-10 04:02:53,5\n2015-03-10 04:07:53,5\n2015-03-10 04:12:53,9\n2015-03-10 04:17:53,14\n2015-03-10 04:22:53,18\n2015-03-10 04:27:53,15\n2015-03-10 04:32:53,10\n2015-03-10 04:37:53,9\n2015-03-10 04:42:53,32\n2015-03-10 04:47:53,34\n2015-03-10 04:52:53,25\n2015-03-10 04:57:53,20\n2015-03-10 05:02:53,13\n2015-03-10 05:07:53,15\n2015-03-10 05:12:53,7\n2015-03-10 05:17:53,7\n2015-03-10 05:22:53,12\n2015-03-10 05:27:53,16\n2015-03-10 05:32:53,10\n2015-03-10 05:37:53,28\n2015-03-10 05:42:53,12\n2015-03-10 05:47:53,7\n2015-03-10 05:52:53,5\n2015-03-10 05:57:53,18\n2015-03-10 06:02:53,15\n2015-03-10 06:07:53,13\n2015-03-10 06:12:53,15\n2015-03-10 06:17:53,8\n2015-03-10 06:22:53,13\n2015-03-10 06:27:53,12\n2015-03-10 06:32:53,9\n2015-03-10 06:37:53,8\n2015-03-10 06:42:53,14\n2015-03-10 06:47:53,20\n2015-03-10 06:52:53,12\n2015-03-10 06:57:53,12\n2015-03-10 07:02:53,12\n2015-03-10 07:07:53,3\n2015-03-10 07:12:53,21\n2015-03-10 07:17:53,11\n2015-03-10 07:22:53,15\n2015-03-10 07:27:53,7\n2015-03-10 07:32:53,9\n2015-03-10 07:37:53,15\n2015-03-10 07:42:53,14\n2015-03-10 07:47:53,11\n2015-03-10 07:52:53,10\n2015-03-10 07:57:53,15\n2015-03-10 08:02:53,9\n2015-03-10 08:07:53,17\n2015-03-10 08:12:53,10\n2015-03-10 08:17:53,9\n2015-03-10 08:22:53,12\n2015-03-10 08:27:53,8\n2015-03-10 08:32:53,17\n2015-03-10 08:37:53,13\n2015-03-10 08:42:53,11\n2015-03-10 08:47:53,10\n2015-03-10 08:52:53,10\n2015-03-10 08:57:53,19\n2015-03-10 09:02:53,29\n2015-03-10 09:07:53,13\n2015-03-10 09:12:53,28\n2015-03-10 09:17:53,19\n2015-03-10 09:22:53,15\n2015-03-10 09:27:53,6\n2015-03-10 09:32:53,15\n2015-03-10 09:37:53,17\n2015-03-10 09:42:53,13\n2015-03-10 09:47:53,5\n2015-03-10 09:52:53,10\n2015-03-10 09:57:53,17\n2015-03-10 10:02:53,16\n2015-03-10 10:07:53,18\n2015-03-10 10:12:53,9\n2015-03-10 10:17:53,13\n2015-03-10 10:22:53,10\n2015-03-10 10:27:53,11\n2015-03-10 10:32:53,11\n2015-03-10 10:37:53,16\n2015-03-10 10:42:53,11\n2015-03-10 10:47:53,2\n2015-03-10 10:52:53,11\n2015-03-10 10:57:53,13\n2015-03-10 11:02:53,13\n2015-03-10 11:07:53,8\n2015-03-10 11:12:53,22\n2015-03-10 11:17:53,14\n2015-03-10 11:22:53,15\n2015-03-10 11:27:53,20\n2015-03-10 11:32:53,16\n2015-03-10 11:37:53,14\n2015-03-10 11:42:53,22\n2015-03-10 11:47:53,10\n2015-03-10 11:52:53,12\n2015-03-10 11:57:53,23\n2015-03-10 12:02:53,14\n2015-03-10 12:07:53,9\n2015-03-10 12:12:53,17\n2015-03-10 12:17:53,10\n2015-03-10 12:22:53,22\n2015-03-10 12:27:53,14\n2015-03-10 12:32:53,17\n2015-03-10 12:37:53,10\n2015-03-10 12:42:53,16\n2015-03-10 12:47:53,32\n2015-03-10 12:52:53,18\n2015-03-10 12:57:53,20\n2015-03-10 13:02:53,21\n2015-03-10 13:07:53,23\n2015-03-10 13:12:53,22\n2015-03-10 13:17:53,11\n2015-03-10 13:22:53,26\n2015-03-10 13:27:53,23\n2015-03-10 13:32:53,17\n2015-03-10 13:37:53,11\n2015-03-10 13:42:53,10\n2015-03-10 13:47:53,9\n2015-03-10 13:52:53,21\n2015-03-10 13:57:53,28\n2015-03-10 14:02:53,24\n2015-03-10 14:07:53,21\n2015-03-10 14:12:53,26\n2015-03-10 14:17:53,24\n2015-03-10 14:22:53,34\n2015-03-10 14:27:53,20\n2015-03-10 14:32:53,17\n2015-03-10 14:37:53,20\n2015-03-10 14:42:53,22\n2015-03-10 14:47:53,36\n2015-03-10 14:52:53,22\n2015-03-10 14:57:53,28\n2015-03-10 15:02:53,27\n2015-03-10 15:07:53,16\n2015-03-10 15:12:53,17\n2015-03-10 15:17:53,19\n2015-03-10 15:22:53,15\n2015-03-10 15:27:53,17\n2015-03-10 15:32:53,21\n2015-03-10 15:37:53,27\n2015-03-10 15:42:53,37\n2015-03-10 15:47:53,23\n2015-03-10 15:52:53,22\n2015-03-10 15:57:53,21\n2015-03-10 16:02:53,33\n2015-03-10 16:07:53,24\n2015-03-10 16:12:53,25\n2015-03-10 16:17:53,15\n2015-03-10 16:22:53,23\n2015-03-10 16:27:53,28\n2015-03-10 16:32:53,29\n2015-03-10 16:37:53,33\n2015-03-10 16:42:53,19\n2015-03-10 16:47:53,22\n2015-03-10 16:52:53,12\n2015-03-10 16:57:53,25\n2015-03-10 17:02:53,25\n2015-03-10 17:07:53,41\n2015-03-10 17:12:53,27\n2015-03-10 17:17:53,23\n2015-03-10 17:22:53,14\n2015-03-10 17:27:53,35\n2015-03-10 17:32:53,38\n2015-03-10 17:37:53,26\n2015-03-10 17:42:53,36\n2015-03-10 17:47:53,30\n2015-03-10 17:52:53,15\n2015-03-10 17:57:53,20\n2015-03-10 18:02:53,23\n2015-03-10 18:07:53,29\n2015-03-10 18:12:53,26\n2015-03-10 18:17:53,23\n2015-03-10 18:22:53,29\n2015-03-10 18:27:53,31\n2015-03-10 18:32:53,36\n2015-03-10 18:37:53,13\n2015-03-10 18:42:53,20\n2015-03-10 18:47:53,29\n2015-03-10 18:52:53,27\n2015-03-10 18:57:53,38\n2015-03-10 19:02:53,16\n2015-03-10 19:07:53,30\n2015-03-10 19:12:53,32\n2015-03-10 19:17:53,22\n2015-03-10 19:22:53,17\n2015-03-10 19:27:53,16\n2015-03-10 19:32:53,20\n2015-03-10 19:37:53,19\n2015-03-10 19:42:53,17\n2015-03-10 19:47:53,46\n2015-03-10 19:52:53,17\n2015-03-10 19:57:53,32\n2015-03-10 20:02:53,18\n2015-03-10 20:07:53,17\n2015-03-10 20:12:53,18\n2015-03-10 20:17:53,17\n2015-03-10 20:22:53,17\n2015-03-10 20:27:53,29\n2015-03-10 20:32:53,29\n2015-03-10 20:37:53,38\n2015-03-10 20:42:53,30\n2015-03-10 20:47:53,26\n2015-03-10 20:52:53,19\n2015-03-10 20:57:53,27\n2015-03-10 21:02:53,20\n2015-03-10 21:07:53,23\n2015-03-10 21:12:53,14\n2015-03-10 21:17:53,23\n2015-03-10 21:22:53,29\n2015-03-10 21:27:53,38\n2015-03-10 21:32:53,24\n2015-03-10 21:37:53,33\n2015-03-10 21:42:53,48\n2015-03-10 21:47:53,18\n2015-03-10 21:52:53,23\n2015-03-10 21:57:53,27\n2015-03-10 22:02:53,28\n2015-03-10 22:07:53,25\n2015-03-10 22:12:53,20\n2015-03-10 22:17:53,40\n2015-03-10 22:22:53,26\n2015-03-10 22:27:53,17\n2015-03-10 22:32:53,23\n2015-03-10 22:37:53,15\n2015-03-10 22:42:53,23\n2015-03-10 22:47:53,21\n2015-03-10 22:52:53,16\n2015-03-10 22:57:53,18\n2015-03-10 23:02:53,22\n2015-03-10 23:07:53,15\n2015-03-10 23:12:53,17\n2015-03-10 23:17:53,19\n2015-03-10 23:22:53,29\n2015-03-10 23:27:53,21\n2015-03-10 23:32:53,18\n2015-03-10 23:37:53,15\n2015-03-10 23:42:53,12\n2015-03-10 23:47:53,15\n2015-03-10 23:52:53,15\n2015-03-10 23:57:53,22\n2015-03-11 00:02:53,14\n2015-03-11 00:07:53,10\n2015-03-11 00:12:53,21\n2015-03-11 00:17:53,19\n2015-03-11 00:22:53,9\n2015-03-11 00:27:53,16\n2015-03-11 00:32:53,17\n2015-03-11 00:37:53,15\n2015-03-11 00:42:53,19\n2015-03-11 00:47:53,12\n2015-03-11 00:52:53,13\n2015-03-11 00:57:53,10\n2015-03-11 01:02:53,19\n2015-03-11 01:07:53,10\n2015-03-11 01:12:53,16\n2015-03-11 01:17:53,17\n2015-03-11 01:22:53,13\n2015-03-11 01:27:53,23\n2015-03-11 01:32:53,7\n2015-03-11 01:37:53,14\n2015-03-11 01:42:53,16\n2015-03-11 01:47:53,15\n2015-03-11 01:52:53,18\n2015-03-11 01:57:53,17\n2015-03-11 02:02:53,16\n2015-03-11 02:07:53,5\n2015-03-11 02:12:53,11\n2015-03-11 02:17:53,17\n2015-03-11 02:22:53,5\n2015-03-11 02:27:53,16\n2015-03-11 02:32:53,13\n2015-03-11 02:37:53,17\n2015-03-11 02:42:53,23\n2015-03-11 02:47:53,11\n2015-03-11 02:52:53,12\n2015-03-11 02:57:53,22\n2015-03-11 03:02:53,18\n2015-03-11 03:07:53,8\n2015-03-11 03:12:53,9\n2015-03-11 03:17:53,12\n2015-03-11 03:22:53,12\n2015-03-11 03:27:53,10\n2015-03-11 03:32:53,22\n2015-03-11 03:37:53,21\n2015-03-11 03:42:53,22\n2015-03-11 03:47:53,17\n2015-03-11 03:52:53,14\n2015-03-11 03:57:53,9\n2015-03-11 04:02:53,4\n2015-03-11 04:07:53,9\n2015-03-11 04:12:53,9\n2015-03-11 04:17:53,14\n2015-03-11 04:22:53,17\n2015-03-11 04:27:53,8\n2015-03-11 04:32:53,13\n2015-03-11 04:37:53,11\n2015-03-11 04:42:53,11\n2015-03-11 04:47:53,12\n2015-03-11 04:52:53,6\n2015-03-11 04:57:53,18\n2015-03-11 05:02:53,8\n2015-03-11 05:07:53,12\n2015-03-11 05:12:53,13\n2015-03-11 05:17:53,24\n2015-03-11 05:22:53,5\n2015-03-11 05:27:53,5\n2015-03-11 05:32:53,8\n2015-03-11 05:37:53,12\n2015-03-11 05:42:53,14\n2015-03-11 05:47:53,6\n2015-03-11 05:52:53,5\n2015-03-11 05:57:53,13\n2015-03-11 06:02:53,13\n2015-03-11 06:07:53,5\n2015-03-11 06:12:53,5\n2015-03-11 06:17:53,7\n2015-03-11 06:22:53,12\n2015-03-11 06:27:53,3\n2015-03-11 06:32:53,10\n2015-03-11 06:37:53,21\n2015-03-11 06:42:53,13\n2015-03-11 06:47:53,10\n2015-03-11 06:52:53,4\n2015-03-11 06:57:53,4\n2015-03-11 07:02:53,0\n2015-03-11 07:07:53,0\n2015-03-11 07:12:53,0\n2015-03-11 07:17:53,0\n2015-03-11 07:22:53,0\n2015-03-11 07:27:53,0\n2015-03-11 07:32:53,0\n2015-03-11 07:37:53,0\n2015-03-11 07:42:53,0\n2015-03-11 07:47:53,0\n2015-03-11 07:52:53,0\n2015-03-11 07:57:53,0\n2015-03-11 08:02:53,0\n2015-03-11 08:07:53,0\n2015-03-11 08:12:53,0\n2015-03-11 08:17:53,0\n2015-03-11 08:22:53,0\n2015-03-11 08:27:53,0\n2015-03-11 08:32:53,0\n2015-03-11 08:37:53,0\n2015-03-11 08:42:53,0\n2015-03-11 08:47:53,0\n2015-03-11 08:52:53,0\n2015-03-11 08:57:53,0\n2015-03-11 09:02:53,0\n2015-03-11 09:07:53,0\n2015-03-11 09:12:53,10\n2015-03-11 09:17:53,13\n2015-03-11 09:22:53,16\n2015-03-11 09:27:53,11\n2015-03-11 09:32:53,9\n2015-03-11 09:37:53,15\n2015-03-11 09:42:53,10\n2015-03-11 09:47:53,11\n2015-03-11 09:52:53,15\n2015-03-11 09:57:53,10\n2015-03-11 10:02:53,18\n2015-03-11 10:07:53,13\n2015-03-11 10:12:53,20\n2015-03-11 10:17:53,23\n2015-03-11 10:22:53,15\n2015-03-11 10:27:53,24\n2015-03-11 10:32:53,21\n2015-03-11 10:37:53,20\n2015-03-11 10:42:53,26\n2015-03-11 10:47:53,12\n2015-03-11 10:52:53,17\n2015-03-11 10:57:53,18\n2015-03-11 11:02:53,30\n2015-03-11 11:07:53,29\n2015-03-11 11:12:53,17\n2015-03-11 11:17:53,17\n2015-03-11 11:22:53,25\n2015-03-11 11:27:53,33\n2015-03-11 11:32:53,18\n2015-03-11 11:37:53,28\n2015-03-11 11:42:53,18\n2015-03-11 11:47:53,19\n2015-03-11 11:52:53,16\n2015-03-11 11:57:53,27\n2015-03-11 12:02:53,19\n2015-03-11 12:07:53,22\n2015-03-11 12:12:53,23\n2015-03-11 12:17:53,22\n2015-03-11 12:22:53,14\n2015-03-11 12:27:53,35\n2015-03-11 12:32:53,21\n2015-03-11 12:37:53,22\n2015-03-11 12:42:53,23\n2015-03-11 12:47:53,19\n2015-03-11 12:52:53,24\n2015-03-11 12:57:53,24\n2015-03-11 13:02:53,27\n2015-03-11 13:07:53,27\n2015-03-11 13:12:53,31\n2015-03-11 13:17:53,18\n2015-03-11 13:22:53,15\n2015-03-11 13:27:53,122\n2015-03-11 13:32:53,74\n2015-03-11 13:37:53,59\n2015-03-11 13:42:53,41\n2015-03-11 13:47:53,42\n2015-03-11 13:52:53,40\n2015-03-11 13:57:53,44\n2015-03-11 14:02:53,44\n2015-03-11 14:07:53,29\n2015-03-11 14:12:53,47\n2015-03-11 14:17:53,32\n2015-03-11 14:22:53,35\n2015-03-11 14:27:53,36\n2015-03-11 14:32:53,30\n2015-03-11 14:37:53,28\n2015-03-11 14:42:53,20\n2015-03-11 14:47:53,18\n2015-03-11 14:52:53,27\n2015-03-11 14:57:53,25\n2015-03-11 15:02:53,33\n2015-03-11 15:07:53,24\n2015-03-11 15:12:53,32\n2015-03-11 15:17:53,30\n2015-03-11 15:22:53,16\n2015-03-11 15:27:53,28\n2015-03-11 15:32:53,23\n2015-03-11 15:37:53,28\n2015-03-11 15:42:53,29\n2015-03-11 15:47:53,35\n2015-03-11 15:52:53,29\n2015-03-11 15:57:53,38\n2015-03-11 16:02:53,37\n2015-03-11 16:07:53,31\n2015-03-11 16:12:53,29\n2015-03-11 16:17:53,17\n2015-03-11 16:22:53,31\n2015-03-11 16:27:53,30\n2015-03-11 16:32:53,34\n2015-03-11 16:37:53,34\n2015-03-11 16:42:53,23\n2015-03-11 16:47:53,23\n2015-03-11 16:52:53,39\n2015-03-11 16:57:53,29\n2015-03-11 17:02:53,29\n2015-03-11 17:07:53,27\n2015-03-11 17:12:53,31\n2015-03-11 17:17:53,28\n2015-03-11 17:22:53,12\n2015-03-11 17:27:53,37\n2015-03-11 17:32:53,27\n2015-03-11 17:37:53,40\n2015-03-11 17:42:53,30\n2015-03-11 17:47:53,50\n2015-03-11 17:52:53,56\n2015-03-11 17:57:53,64\n2015-03-11 18:02:53,49\n2015-03-11 18:07:53,59\n2015-03-11 18:12:53,48\n2015-03-11 18:17:53,34\n2015-03-11 18:22:53,29\n2015-03-11 18:27:53,30\n2015-03-11 18:32:53,39\n2015-03-11 18:37:53,89\n2015-03-11 18:42:53,56\n2015-03-11 18:47:53,42\n2015-03-11 18:52:53,46\n2015-03-11 18:57:53,47\n2015-03-11 19:02:53,36\n2015-03-11 19:07:53,35\n2015-03-11 19:12:53,20\n2015-03-11 19:17:53,19\n2015-03-11 19:22:53,29\n2015-03-11 19:27:53,29\n2015-03-11 19:32:53,36\n2015-03-11 19:37:53,22\n2015-03-11 19:42:53,54\n2015-03-11 19:47:53,41\n2015-03-11 19:52:53,30\n2015-03-11 19:57:53,36\n2015-03-11 20:02:53,40\n2015-03-11 20:07:53,43\n2015-03-11 20:12:53,28\n2015-03-11 20:17:53,43\n2015-03-11 20:22:53,24\n2015-03-11 20:27:53,27\n2015-03-11 20:32:53,28\n2015-03-11 20:37:53,19\n2015-03-11 20:42:53,39\n2015-03-11 20:47:53,56\n2015-03-11 20:52:53,36\n2015-03-11 20:57:53,36\n2015-03-11 21:02:53,28\n2015-03-11 21:07:53,33\n2015-03-11 21:12:53,34\n2015-03-11 21:17:53,23\n2015-03-11 21:22:53,16\n2015-03-11 21:27:53,27\n2015-03-11 21:32:53,24\n2015-03-11 21:37:53,27\n2015-03-11 21:42:53,23\n2015-03-11 21:47:53,24\n2015-03-11 21:52:53,18\n2015-03-11 21:57:53,39\n2015-03-11 22:02:53,18\n2015-03-11 22:07:53,12\n2015-03-11 22:12:53,24\n2015-03-11 22:17:53,39\n2015-03-11 22:22:53,34\n2015-03-11 22:27:53,32\n2015-03-11 22:32:53,32\n2015-03-11 22:37:53,18\n2015-03-11 22:42:53,22\n2015-03-11 22:47:53,17\n2015-03-11 22:52:53,21\n2015-03-11 22:57:53,27\n2015-03-11 23:02:53,21\n2015-03-11 23:07:53,22\n2015-03-11 23:12:53,12\n2015-03-11 23:17:53,22\n2015-03-11 23:22:53,11\n2015-03-11 23:27:53,17\n2015-03-11 23:32:53,20\n2015-03-11 23:37:53,16\n2015-03-11 23:42:53,17\n2015-03-11 23:47:53,13\n2015-03-11 23:52:53,16\n2015-03-11 23:57:53,50\n2015-03-12 00:02:53,21\n2015-03-12 00:07:53,29\n2015-03-12 00:12:53,31\n2015-03-12 00:17:53,25\n2015-03-12 00:22:53,19\n2015-03-12 00:27:53,17\n2015-03-12 00:32:53,15\n2015-03-12 00:37:53,22\n2015-03-12 00:42:53,15\n2015-03-12 00:47:53,9\n2015-03-12 00:52:53,15\n2015-03-12 00:57:53,21\n2015-03-12 01:02:53,22\n2015-03-12 01:07:53,7\n2015-03-12 01:12:53,21\n2015-03-12 01:17:53,18\n2015-03-12 01:22:53,17\n2015-03-12 01:27:53,15\n2015-03-12 01:32:53,14\n2015-03-12 01:37:53,15\n2015-03-12 01:42:53,13\n2015-03-12 01:47:53,12\n2015-03-12 01:52:53,28\n2015-03-12 01:57:53,24\n2015-03-12 02:02:53,8\n2015-03-12 02:07:53,15\n2015-03-12 02:12:53,12\n2015-03-12 02:17:53,16\n2015-03-12 02:22:53,18\n2015-03-12 02:27:53,18\n2015-03-12 02:32:53,9\n2015-03-12 02:37:53,10\n2015-03-12 02:42:53,23\n2015-03-12 02:47:53,14\n2015-03-12 02:52:53,19\n2015-03-12 02:57:53,14\n2015-03-12 03:02:53,17\n2015-03-12 03:07:53,13\n2015-03-12 03:12:53,3\n2015-03-12 03:17:53,6\n2015-03-12 03:22:53,19\n2015-03-12 03:27:53,9\n2015-03-12 03:32:53,6\n2015-03-12 03:37:53,11\n2015-03-12 03:42:53,14\n2015-03-12 03:47:53,14\n2015-03-12 03:52:53,11\n2015-03-12 03:57:53,16\n2015-03-12 04:02:53,14\n2015-03-12 04:07:53,14\n2015-03-12 04:12:53,22\n2015-03-12 04:17:53,7\n2015-03-12 04:22:53,21\n2015-03-12 04:27:53,17\n2015-03-12 04:32:53,7\n2015-03-12 04:37:53,7\n2015-03-12 04:42:53,9\n2015-03-12 04:47:53,15\n2015-03-12 04:52:53,10\n2015-03-12 04:57:53,21\n2015-03-12 05:02:53,11\n2015-03-12 05:07:53,7\n2015-03-12 05:12:53,6\n2015-03-12 05:17:53,15\n2015-03-12 05:22:53,8\n2015-03-12 05:27:53,1\n2015-03-12 05:32:53,0\n2015-03-12 05:37:53,2\n2015-03-12 05:42:53,13\n2015-03-12 05:47:53,7\n2015-03-12 05:52:53,6\n2015-03-12 05:57:53,16\n2015-03-12 06:02:53,9\n2015-03-12 06:07:53,21\n2015-03-12 06:12:53,12\n2015-03-12 06:17:53,13\n2015-03-12 06:22:53,4\n2015-03-12 06:27:53,12\n2015-03-12 06:32:53,9\n2015-03-12 06:37:53,15\n2015-03-12 06:42:53,8\n2015-03-12 06:47:53,15\n2015-03-12 06:52:53,13\n2015-03-12 06:57:53,14\n2015-03-12 07:02:53,9\n2015-03-12 07:07:53,15\n2015-03-12 07:12:53,10\n2015-03-12 07:17:53,8\n2015-03-12 07:22:53,8\n2015-03-12 07:27:53,20\n2015-03-12 07:32:53,21\n2015-03-12 07:37:53,20\n2015-03-12 07:42:53,11\n2015-03-12 07:47:53,9\n2015-03-12 07:52:53,11\n2015-03-12 07:57:53,18\n2015-03-12 08:02:53,20\n2015-03-12 08:07:53,13\n2015-03-12 08:12:53,10\n2015-03-12 08:17:53,11\n2015-03-12 08:22:53,13\n2015-03-12 08:27:53,12\n2015-03-12 08:32:53,11\n2015-03-12 08:37:53,19\n2015-03-12 08:42:53,15\n2015-03-12 08:47:53,18\n2015-03-12 08:52:53,10\n2015-03-12 08:57:53,14\n2015-03-12 09:02:53,27\n2015-03-12 09:07:53,50\n2015-03-12 09:12:53,24\n2015-03-12 09:17:53,11\n2015-03-12 09:22:53,2\n2015-03-12 09:27:53,4\n2015-03-12 09:32:53,9\n2015-03-12 09:37:53,9\n2015-03-12 09:42:53,15\n2015-03-12 09:47:53,11\n2015-03-12 09:52:53,9\n2015-03-12 09:57:53,19\n2015-03-12 10:02:53,22\n2015-03-12 10:07:53,23\n2015-03-12 10:12:53,11\n2015-03-12 10:17:53,25\n2015-03-12 10:22:53,25\n2015-03-12 10:27:53,19\n2015-03-12 10:32:53,20\n2015-03-12 10:37:53,23\n2015-03-12 10:42:53,23\n2015-03-12 10:47:53,16\n2015-03-12 10:52:53,17\n2015-03-12 10:57:53,21\n2015-03-12 11:02:53,22\n2015-03-12 11:07:53,14\n2015-03-12 11:12:53,18\n2015-03-12 11:17:53,17\n2015-03-12 11:22:53,23\n2015-03-12 11:27:53,16\n2015-03-12 11:32:53,25\n2015-03-12 11:37:53,20\n2015-03-12 11:42:53,23\n2015-03-12 11:47:53,14\n2015-03-12 11:52:53,25\n2015-03-12 11:57:53,19\n2015-03-12 12:02:53,21\n2015-03-12 12:07:53,18\n2015-03-12 12:12:53,14\n2015-03-12 12:17:53,11\n2015-03-12 12:22:53,17\n2015-03-12 12:27:53,26\n2015-03-12 12:32:53,35\n2015-03-12 12:37:53,25\n2015-03-12 12:42:53,19\n2015-03-12 12:47:53,14\n2015-03-12 12:52:53,23\n2015-03-12 12:57:53,30\n2015-03-12 13:02:53,38\n2015-03-12 13:07:53,21\n2015-03-12 13:12:53,12\n2015-03-12 13:17:53,29\n2015-03-12 13:22:53,20\n2015-03-12 13:27:53,29\n2015-03-12 13:32:53,27\n2015-03-12 13:37:53,13\n2015-03-12 13:42:53,14\n2015-03-12 13:47:53,23\n2015-03-12 13:52:53,19\n2015-03-12 13:57:53,20\n2015-03-12 14:02:53,37\n2015-03-12 14:07:53,27\n2015-03-12 14:12:53,29\n2015-03-12 14:17:53,29\n2015-03-12 14:22:53,33\n2015-03-12 14:27:53,30\n2015-03-12 14:32:53,35\n2015-03-12 14:37:53,29\n2015-03-12 14:42:53,26\n2015-03-12 14:47:53,29\n2015-03-12 14:52:53,27\n2015-03-12 14:57:53,37\n2015-03-12 15:02:53,30\n2015-03-12 15:07:53,25\n2015-03-12 15:12:53,29\n2015-03-12 15:17:53,24\n2015-03-12 15:22:53,24\n2015-03-12 15:27:53,27\n2015-03-12 15:32:53,34\n2015-03-12 15:37:53,17\n2015-03-12 15:42:53,25\n2015-03-12 15:47:53,17\n2015-03-12 15:52:53,30\n2015-03-12 15:57:53,34\n2015-03-12 16:02:53,23\n2015-03-12 16:07:53,26\n2015-03-12 16:12:53,29\n2015-03-12 16:17:53,32\n2015-03-12 16:22:53,33\n2015-03-12 16:27:53,28\n2015-03-12 16:32:53,30\n2015-03-12 16:37:53,37\n2015-03-12 16:42:53,27\n2015-03-12 16:47:53,18\n2015-03-12 16:52:53,33\n2015-03-12 16:57:53,20\n2015-03-12 17:02:53,31\n2015-03-12 17:07:53,40\n2015-03-12 17:12:53,67\n2015-03-12 17:17:53,44\n2015-03-12 17:22:53,44\n2015-03-12 17:27:53,35\n2015-03-12 17:32:53,27\n2015-03-12 17:37:53,28\n2015-03-12 17:42:53,36\n2015-03-12 17:47:53,23\n2015-03-12 17:52:53,18\n2015-03-12 17:57:53,29\n2015-03-12 18:02:53,21\n2015-03-12 18:07:53,16\n2015-03-12 18:12:53,29\n2015-03-12 18:17:53,20\n2015-03-12 18:22:53,27\n2015-03-12 18:27:53,33\n2015-03-12 18:32:53,26\n2015-03-12 18:37:53,32\n2015-03-12 18:42:53,27\n2015-03-12 18:47:53,24\n2015-03-12 18:52:53,25\n2015-03-12 18:57:53,30\n2015-03-12 19:02:53,34\n2015-03-12 19:07:53,20\n2015-03-12 19:12:53,25\n2015-03-12 19:17:53,23\n2015-03-12 19:22:53,15\n2015-03-12 19:27:53,30\n2015-03-12 19:32:53,21\n2015-03-12 19:37:53,21\n2015-03-12 19:42:53,26\n2015-03-12 19:47:53,26\n2015-03-12 19:52:53,29\n2015-03-12 19:57:53,39\n2015-03-12 20:02:53,34\n2015-03-12 20:07:53,28\n2015-03-12 20:12:53,21\n2015-03-12 20:17:53,16\n2015-03-12 20:22:53,36\n2015-03-12 20:27:53,25\n2015-03-12 20:32:53,19\n2015-03-12 20:37:53,24\n2015-03-12 20:42:53,14\n2015-03-12 20:47:53,16\n2015-03-12 20:52:53,27\n2015-03-12 20:57:53,17\n2015-03-12 21:02:53,24\n2015-03-12 21:07:53,15\n2015-03-12 21:12:53,12\n2015-03-12 21:17:53,17\n2015-03-12 21:22:53,21\n2015-03-12 21:27:53,22\n2015-03-12 21:32:53,14\n2015-03-12 21:37:53,12\n2015-03-12 21:42:53,33\n2015-03-12 21:47:53,18\n2015-03-12 21:52:53,24\n2015-03-12 21:57:53,20\n2015-03-12 22:02:53,27\n2015-03-12 22:07:53,21\n2015-03-12 22:12:53,26\n2015-03-12 22:17:53,21\n2015-03-12 22:22:53,32\n2015-03-12 22:27:53,26\n2015-03-12 22:32:53,18\n2015-03-12 22:37:53,14\n2015-03-12 22:42:53,18\n2015-03-12 22:47:53,16\n2015-03-12 22:52:53,17\n2015-03-12 22:57:53,13\n2015-03-12 23:02:53,13\n2015-03-12 23:07:53,10\n2015-03-12 23:12:53,17\n2015-03-12 23:17:53,11\n2015-03-12 23:22:53,7\n2015-03-12 23:27:53,17\n2015-03-12 23:32:53,14\n2015-03-12 23:37:53,24\n2015-03-12 23:42:53,15\n2015-03-12 23:47:53,15\n2015-03-12 23:52:53,9\n2015-03-12 23:57:53,14\n2015-03-13 00:02:53,8\n2015-03-13 00:07:53,15\n2015-03-13 00:12:53,11\n2015-03-13 00:17:53,11\n2015-03-13 00:22:53,8\n2015-03-13 00:27:53,15\n2015-03-13 00:32:53,15\n2015-03-13 00:37:53,12\n2015-03-13 00:42:53,6\n2015-03-13 00:47:53,8\n2015-03-13 00:52:53,10\n2015-03-13 00:57:53,20\n2015-03-13 01:02:53,15\n2015-03-13 01:07:53,16\n2015-03-13 01:12:53,33\n2015-03-13 01:17:53,11\n2015-03-13 01:22:53,24\n2015-03-13 01:27:53,12\n2015-03-13 01:32:53,10\n2015-03-13 01:37:53,12\n2015-03-13 01:42:53,12\n2015-03-13 01:47:53,15\n2015-03-13 01:52:53,16\n2015-03-13 01:57:53,5\n2015-03-13 02:02:53,29\n2015-03-13 02:07:53,12\n2015-03-13 02:12:53,7\n2015-03-13 02:17:53,54\n2015-03-13 02:22:53,56\n2015-03-13 02:27:53,31\n2015-03-13 02:32:53,25\n2015-03-13 02:37:53,22\n2015-03-13 02:42:53,22\n2015-03-13 02:47:53,19\n2015-03-13 02:52:53,10\n2015-03-13 02:57:53,30\n2015-03-13 03:02:53,10\n2015-03-13 03:07:53,20\n2015-03-13 03:12:53,31\n2015-03-13 03:17:53,6\n2015-03-13 03:22:53,12\n2015-03-13 03:27:53,20\n2015-03-13 03:32:53,18\n2015-03-13 03:37:53,15\n2015-03-13 03:42:53,15\n2015-03-13 03:47:53,12\n2015-03-13 03:52:53,19\n2015-03-13 03:57:53,13\n2015-03-13 04:02:53,5\n2015-03-13 04:07:53,13\n2015-03-13 04:12:53,12\n2015-03-13 04:17:53,14\n2015-03-13 04:22:53,8\n2015-03-13 04:27:53,21\n2015-03-13 04:32:53,19\n2015-03-13 04:37:53,9\n2015-03-13 04:42:53,13\n2015-03-13 04:47:53,13\n2015-03-13 04:52:53,11\n2015-03-13 04:57:53,12\n2015-03-13 05:02:53,9\n2015-03-13 05:07:53,20\n2015-03-13 05:12:53,17\n2015-03-13 05:17:53,15\n2015-03-13 05:22:53,2\n2015-03-13 05:27:53,14\n2015-03-13 05:32:53,4\n2015-03-13 05:37:53,18\n2015-03-13 05:42:53,9\n2015-03-13 05:47:53,7\n2015-03-13 05:52:53,18\n2015-03-13 05:57:53,12\n2015-03-13 06:02:53,18\n2015-03-13 06:07:53,7\n2015-03-13 06:12:53,10\n2015-03-13 06:17:53,10\n2015-03-13 06:22:53,16\n2015-03-13 06:27:53,10\n2015-03-13 06:32:53,4\n2015-03-13 06:37:53,11\n2015-03-13 06:42:53,11\n2015-03-13 06:47:53,16\n2015-03-13 06:52:53,21\n2015-03-13 06:57:53,11\n2015-03-13 07:02:53,6\n2015-03-13 07:07:53,12\n2015-03-13 07:12:53,15\n2015-03-13 07:17:53,4\n2015-03-13 07:22:53,12\n2015-03-13 07:27:53,8\n2015-03-13 07:32:53,7\n2015-03-13 07:37:53,18\n2015-03-13 07:42:53,7\n2015-03-13 07:47:53,15\n2015-03-13 07:52:53,18\n2015-03-13 07:57:53,10\n2015-03-13 08:02:53,14\n2015-03-13 08:07:53,9\n2015-03-13 08:12:53,14\n2015-03-13 08:17:53,17\n2015-03-13 08:22:53,13\n2015-03-13 08:27:53,13\n2015-03-13 08:32:53,14\n2015-03-13 08:37:53,16\n2015-03-13 08:42:53,9\n2015-03-13 08:47:53,15\n2015-03-13 08:52:53,13\n2015-03-13 08:57:53,11\n2015-03-13 09:02:53,10\n2015-03-13 09:07:53,16\n2015-03-13 09:12:53,12\n2015-03-13 09:17:53,15\n2015-03-13 09:22:53,11\n2015-03-13 09:27:53,15\n2015-03-13 09:32:53,13\n2015-03-13 09:37:53,5\n2015-03-13 09:42:53,21\n2015-03-13 09:47:53,19\n2015-03-13 09:52:53,16\n2015-03-13 09:57:53,19\n2015-03-13 10:02:53,7\n2015-03-13 10:07:53,6\n2015-03-13 10:12:53,25\n2015-03-13 10:17:53,12\n2015-03-13 10:22:53,13\n2015-03-13 10:27:53,15\n2015-03-13 10:32:53,11\n2015-03-13 10:37:53,8\n2015-03-13 10:42:53,25\n2015-03-13 10:47:53,20\n2015-03-13 10:52:53,21\n2015-03-13 10:57:53,10\n2015-03-13 11:02:53,14\n2015-03-13 11:07:53,12\n2015-03-13 11:12:53,24\n2015-03-13 11:17:53,11\n2015-03-13 11:22:53,32\n2015-03-13 11:27:53,16\n2015-03-13 11:32:53,17\n2015-03-13 11:37:53,15\n2015-03-13 11:42:53,16\n2015-03-13 11:47:53,21\n2015-03-13 11:52:53,15\n2015-03-13 11:57:53,19\n2015-03-13 12:02:53,15\n2015-03-13 12:07:53,12\n2015-03-13 12:12:53,20\n2015-03-13 12:17:53,26\n2015-03-13 12:22:53,26\n2015-03-13 12:27:53,17\n2015-03-13 12:32:53,31\n2015-03-13 12:37:53,24\n2015-03-13 12:42:53,24\n2015-03-13 12:47:53,25\n2015-03-13 12:52:53,23\n2015-03-13 12:57:53,26\n2015-03-13 13:02:53,24\n2015-03-13 13:07:53,25\n2015-03-13 13:12:53,30\n2015-03-13 13:17:53,25\n2015-03-13 13:22:53,18\n2015-03-13 13:27:53,32\n2015-03-13 13:32:53,21\n2015-03-13 13:37:53,23\n2015-03-13 13:42:53,19\n2015-03-13 13:47:53,30\n2015-03-13 13:52:53,31\n2015-03-13 13:57:53,30\n2015-03-13 14:02:53,28\n2015-03-13 14:07:53,19\n2015-03-13 14:12:53,18\n2015-03-13 14:17:53,33\n2015-03-13 14:22:53,34\n2015-03-13 14:27:53,37\n2015-03-13 14:32:53,38\n2015-03-13 14:37:53,41\n2015-03-13 14:42:53,36\n2015-03-13 14:47:53,28\n2015-03-13 14:52:53,27\n2015-03-13 14:57:53,31\n2015-03-13 15:02:53,23\n2015-03-13 15:07:53,27\n2015-03-13 15:12:53,18\n2015-03-13 15:17:53,19\n2015-03-13 15:22:53,25\n2015-03-13 15:27:53,29\n2015-03-13 15:32:53,23\n2015-03-13 15:37:53,23\n2015-03-13 15:42:53,38\n2015-03-13 15:47:53,32\n2015-03-13 15:52:53,24\n2015-03-13 15:57:53,33\n2015-03-13 16:02:53,47\n2015-03-13 16:07:53,28\n2015-03-13 16:12:53,44\n2015-03-13 16:17:53,30\n2015-03-13 16:22:53,31\n2015-03-13 16:27:53,36\n2015-03-13 16:32:53,23\n2015-03-13 16:37:53,22\n2015-03-13 16:42:53,23\n2015-03-13 16:47:53,21\n2015-03-13 16:52:53,23\n2015-03-13 16:57:53,37\n2015-03-13 17:02:53,21\n2015-03-13 17:07:53,25\n2015-03-13 17:12:53,36\n2015-03-13 17:17:53,20\n2015-03-13 17:22:53,31\n2015-03-13 17:27:53,18\n2015-03-13 17:32:53,20\n2015-03-13 17:37:53,22\n2015-03-13 17:42:53,21\n2015-03-13 17:47:53,17\n2015-03-13 17:52:53,73\n2015-03-13 17:57:53,25\n2015-03-13 18:02:53,42\n2015-03-13 18:07:53,31\n2015-03-13 18:12:53,34\n2015-03-13 18:17:53,40\n2015-03-13 18:22:53,13\n2015-03-13 18:27:53,24\n2015-03-13 18:32:53,30\n2015-03-13 18:37:53,32\n2015-03-13 18:42:53,26\n2015-03-13 18:47:53,27\n2015-03-13 18:52:53,32\n2015-03-13 18:57:53,23\n2015-03-13 19:02:53,40\n2015-03-13 19:07:53,50\n2015-03-13 19:12:53,75\n2015-03-13 19:17:53,61\n2015-03-13 19:22:53,43\n2015-03-13 19:27:53,52\n2015-03-13 19:32:53,55\n2015-03-13 19:37:53,56\n2015-03-13 19:42:53,43\n2015-03-13 19:47:53,38\n2015-03-13 19:52:53,49\n2015-03-13 19:57:53,134\n2015-03-13 20:02:53,54\n2015-03-13 20:07:53,68\n2015-03-13 20:12:53,276\n2015-03-13 20:17:53,157\n2015-03-13 20:22:53,452\n2015-03-13 20:27:53,295\n2015-03-13 20:32:53,94\n2015-03-13 20:37:53,224\n2015-03-13 20:42:53,94\n2015-03-13 20:47:53,227\n2015-03-13 20:52:53,78\n2015-03-13 20:57:53,411\n2015-03-13 21:02:53,327\n2015-03-13 21:07:53,210\n2015-03-13 21:12:53,141\n2015-03-13 21:17:53,73\n2015-03-13 21:22:53,128\n2015-03-13 21:27:53,268\n2015-03-13 21:32:53,29\n2015-03-13 21:37:53,14\n2015-03-13 21:42:53,17\n2015-03-13 21:47:53,18\n2015-03-13 21:52:53,16\n2015-03-13 21:57:53,26\n2015-03-13 22:02:53,27\n2015-03-13 22:07:53,15\n2015-03-13 22:12:53,21\n2015-03-13 22:17:53,16\n2015-03-13 22:22:53,16\n2015-03-13 22:27:53,33\n2015-03-13 22:32:53,27\n2015-03-13 22:37:53,14\n2015-03-13 22:42:53,13\n2015-03-13 22:47:53,34\n2015-03-13 22:52:53,21\n2015-03-13 22:57:53,31\n2015-03-13 23:02:53,14\n2015-03-13 23:07:53,20\n2015-03-13 23:12:53,27\n2015-03-13 23:17:53,31\n2015-03-13 23:22:53,22\n2015-03-13 23:27:53,21\n2015-03-13 23:32:53,9\n2015-03-13 23:37:53,23\n2015-03-13 23:42:53,22\n2015-03-13 23:47:53,9\n2015-03-13 23:52:53,23\n2015-03-13 23:57:53,11\n2015-03-14 00:02:53,22\n2015-03-14 00:07:53,13\n2015-03-14 00:12:53,15\n2015-03-14 00:17:53,11\n2015-03-14 00:22:53,11\n2015-03-14 00:27:53,11\n2015-03-14 00:32:53,14\n2015-03-14 00:37:53,21\n2015-03-14 00:42:53,9\n2015-03-14 00:47:53,15\n2015-03-14 00:52:53,12\n2015-03-14 00:57:53,10\n2015-03-14 01:02:53,12\n2015-03-14 01:07:53,19\n2015-03-14 01:12:53,15\n2015-03-14 01:17:53,12\n2015-03-14 01:22:53,12\n2015-03-14 01:27:53,12\n2015-03-14 01:32:53,7\n2015-03-14 01:37:53,9\n2015-03-14 01:42:53,10\n2015-03-14 01:47:53,12\n2015-03-14 01:52:53,21\n2015-03-14 01:57:53,12\n2015-03-14 02:02:53,16\n2015-03-14 02:07:53,13\n2015-03-14 02:12:53,7\n2015-03-14 02:17:53,12\n2015-03-14 02:22:53,24\n2015-03-14 02:27:53,11\n2015-03-14 02:32:53,15\n2015-03-14 02:37:53,10\n2015-03-14 02:42:53,8\n2015-03-14 02:47:53,7\n2015-03-14 02:52:53,8\n2015-03-14 02:57:53,20\n2015-03-14 03:02:53,12\n2015-03-14 03:07:53,12\n2015-03-14 03:12:53,7\n2015-03-14 03:17:53,4\n2015-03-14 03:22:53,5\n2015-03-14 03:27:53,5\n2015-03-14 03:32:53,20\n2015-03-14 03:37:53,17\n2015-03-14 03:42:53,15\n2015-03-14 03:47:53,12\n2015-03-14 03:52:53,8\n2015-03-14 03:57:53,12\n2015-03-14 04:02:53,11\n2015-03-14 04:07:53,7\n2015-03-14 04:12:53,10\n2015-03-14 04:17:53,10\n2015-03-14 04:22:53,13\n2015-03-14 04:27:53,8\n2015-03-14 04:32:53,10\n2015-03-14 04:37:53,3\n2015-03-14 04:42:53,14\n2015-03-14 04:47:53,11\n2015-03-14 04:52:53,8\n2015-03-14 04:57:53,14\n2015-03-14 05:02:53,12\n2015-03-14 05:07:53,6\n2015-03-14 05:12:53,6\n2015-03-14 05:17:53,1\n2015-03-14 05:22:53,10\n2015-03-14 05:27:53,7\n2015-03-14 05:32:53,15\n2015-03-14 05:37:53,8\n2015-03-14 05:42:53,7\n2015-03-14 05:47:53,14\n2015-03-14 05:52:53,8\n2015-03-14 05:57:53,5\n2015-03-14 06:02:53,17\n2015-03-14 06:07:53,8\n2015-03-14 06:12:53,7\n2015-03-14 06:17:53,4\n2015-03-14 06:22:53,8\n2015-03-14 06:27:53,5\n2015-03-14 06:32:53,6\n2015-03-14 06:37:53,3\n2015-03-14 06:42:53,10\n2015-03-14 06:47:53,8\n2015-03-14 06:52:53,10\n2015-03-14 06:57:53,13\n2015-03-14 07:02:53,9\n2015-03-14 07:07:53,7\n2015-03-14 07:12:53,6\n2015-03-14 07:17:53,10\n2015-03-14 07:22:53,3\n2015-03-14 07:27:53,7\n2015-03-14 07:32:53,8\n2015-03-14 07:37:53,5\n2015-03-14 07:42:53,5\n2015-03-14 07:47:53,7\n2015-03-14 07:52:53,9\n2015-03-14 07:57:53,7\n2015-03-14 08:02:53,9\n2015-03-14 08:07:53,11\n2015-03-14 08:12:53,4\n2015-03-14 08:17:53,4\n2015-03-14 08:22:53,5\n2015-03-14 08:27:53,6\n2015-03-14 08:32:53,4\n2015-03-14 08:37:53,4\n2015-03-14 08:42:53,10\n2015-03-14 08:47:53,3\n2015-03-14 08:52:53,9\n2015-03-14 08:57:53,6\n2015-03-14 09:02:53,8\n2015-03-14 09:07:53,4\n2015-03-14 09:12:53,10\n2015-03-14 09:17:53,6\n2015-03-14 09:22:53,10\n2015-03-14 09:27:53,6\n2015-03-14 09:32:53,5\n2015-03-14 09:37:53,8\n2015-03-14 09:42:53,6\n2015-03-14 09:47:53,4\n2015-03-14 09:52:53,11\n2015-03-14 09:57:53,7\n2015-03-14 10:02:53,8\n2015-03-14 10:07:53,9\n2015-03-14 10:12:53,7\n2015-03-14 10:17:53,3\n2015-03-14 10:22:53,2\n2015-03-14 10:27:53,8\n2015-03-14 10:32:53,10\n2015-03-14 10:37:53,14\n2015-03-14 10:42:53,10\n2015-03-14 10:47:53,4\n2015-03-14 10:52:53,4\n2015-03-14 10:57:53,6\n2015-03-14 11:02:53,4\n2015-03-14 11:07:53,6\n2015-03-14 11:12:53,6\n2015-03-14 11:17:53,7\n2015-03-14 11:22:53,18\n2015-03-14 11:27:53,14\n2015-03-14 11:32:53,19\n2015-03-14 11:37:53,6\n2015-03-14 11:42:53,5\n2015-03-14 11:47:53,9\n2015-03-14 11:52:53,9\n2015-03-14 11:57:53,9\n2015-03-14 12:02:53,14\n2015-03-14 12:07:53,7\n2015-03-14 12:12:53,4\n2015-03-14 12:17:53,9\n2015-03-14 12:22:53,10\n2015-03-14 12:27:53,5\n2015-03-14 12:32:53,7\n2015-03-14 12:37:53,8\n2015-03-14 12:42:53,7\n2015-03-14 12:47:53,9\n2015-03-14 12:52:53,11\n2015-03-14 12:57:53,18\n2015-03-14 13:02:53,26\n2015-03-14 13:07:53,14\n2015-03-14 13:12:53,10\n2015-03-14 13:17:53,18\n2015-03-14 13:22:53,16\n2015-03-14 13:27:53,18\n2015-03-14 13:32:53,31\n2015-03-14 13:37:53,13\n2015-03-14 13:42:53,17\n2015-03-14 13:47:53,16\n2015-03-14 13:52:53,10\n2015-03-14 13:57:53,12\n2015-03-14 14:02:53,10\n2015-03-14 14:07:53,10\n2015-03-14 14:12:53,8\n2015-03-14 14:17:53,21\n2015-03-14 14:22:53,10\n2015-03-14 14:27:53,9\n2015-03-14 14:32:53,10\n2015-03-14 14:37:53,19\n2015-03-14 14:42:53,9\n2015-03-14 14:47:53,17\n2015-03-14 14:52:53,11\n2015-03-14 14:57:53,10\n2015-03-14 15:02:53,10\n2015-03-14 15:07:53,13\n2015-03-14 15:12:53,9\n2015-03-14 15:17:53,11\n2015-03-14 15:22:53,11\n2015-03-14 15:27:53,9\n2015-03-14 15:32:53,7\n2015-03-14 15:37:53,10\n2015-03-14 15:42:53,11\n2015-03-14 15:47:53,6\n2015-03-14 15:52:53,23\n2015-03-14 15:57:53,12\n2015-03-14 16:02:53,16\n2015-03-14 16:07:53,22\n2015-03-14 16:12:53,25\n2015-03-14 16:17:53,24\n2015-03-14 16:22:53,178\n2015-03-14 16:27:53,287\n2015-03-14 16:32:53,164\n2015-03-14 16:37:53,135\n2015-03-14 16:42:53,111\n2015-03-14 16:47:53,78\n2015-03-14 16:52:53,68\n2015-03-14 16:57:53,65\n2015-03-14 17:02:53,66\n2015-03-14 17:07:53,50\n2015-03-14 17:12:53,52\n2015-03-14 17:17:53,57\n2015-03-14 17:22:53,47\n2015-03-14 17:27:53,34\n2015-03-14 17:32:53,47\n2015-03-14 17:37:53,30\n2015-03-14 17:42:53,30\n2015-03-14 17:47:53,35\n2015-03-14 17:52:53,39\n2015-03-14 17:57:53,165\n2015-03-14 18:02:53,264\n2015-03-14 18:07:53,28\n2015-03-14 18:12:53,36\n2015-03-14 18:17:53,41\n2015-03-14 18:22:53,35\n2015-03-14 18:27:53,28\n2015-03-14 18:32:53,16\n2015-03-14 18:37:53,23\n2015-03-14 18:42:53,23\n2015-03-14 18:47:53,20\n2015-03-14 18:52:53,20\n2015-03-14 18:57:53,21\n2015-03-14 19:02:53,32\n2015-03-14 19:07:53,21\n2015-03-14 19:12:53,23\n2015-03-14 19:17:53,14\n2015-03-14 19:22:53,26\n2015-03-14 19:27:53,11\n2015-03-14 19:32:53,24\n2015-03-14 19:37:53,19\n2015-03-14 19:42:53,14\n2015-03-14 19:47:53,240\n2015-03-14 19:52:53,92\n2015-03-14 19:57:53,29\n2015-03-14 20:02:53,34\n2015-03-14 20:07:53,16\n2015-03-14 20:12:53,14\n2015-03-14 20:17:53,20\n2015-03-14 20:22:53,14\n2015-03-14 20:27:53,13\n2015-03-14 20:32:53,18\n2015-03-14 20:37:53,22\n2015-03-14 20:42:53,12\n2015-03-14 20:47:53,25\n2015-03-14 20:52:53,10\n2015-03-14 20:57:53,13\n2015-03-14 21:02:53,20\n2015-03-14 21:07:53,19\n2015-03-14 21:12:53,12\n2015-03-14 21:17:53,18\n2015-03-14 21:22:53,16\n2015-03-14 21:27:53,30\n2015-03-14 21:32:53,17\n2015-03-14 21:37:53,11\n2015-03-14 21:42:53,36\n2015-03-14 21:47:53,14\n2015-03-14 21:52:53,19\n2015-03-14 21:57:53,13\n2015-03-14 22:02:53,19\n2015-03-14 22:07:53,22\n2015-03-14 22:12:53,21\n2015-03-14 22:17:53,19\n2015-03-14 22:22:53,16\n2015-03-14 22:27:53,12\n2015-03-14 22:32:53,15\n2015-03-14 22:37:53,20\n2015-03-14 22:42:53,16\n2015-03-14 22:47:53,12\n2015-03-14 22:52:53,13\n2015-03-14 22:57:53,17\n2015-03-14 23:02:53,13\n2015-03-14 23:07:53,7\n2015-03-14 23:12:53,12\n2015-03-14 23:17:53,19\n2015-03-14 23:22:53,6\n2015-03-14 23:27:53,11\n2015-03-14 23:32:53,12\n2015-03-14 23:37:53,18\n2015-03-14 23:42:53,15\n2015-03-14 23:47:53,9\n2015-03-14 23:52:53,14\n2015-03-14 23:57:53,10\n2015-03-15 00:02:53,13\n2015-03-15 00:07:53,12\n2015-03-15 00:12:53,14\n2015-03-15 00:17:53,12\n2015-03-15 00:22:53,4\n2015-03-15 00:27:53,7\n2015-03-15 00:32:53,5\n2015-03-15 00:37:53,14\n2015-03-15 00:42:53,4\n2015-03-15 00:47:53,13\n2015-03-15 00:52:53,13\n2015-03-15 00:57:53,11\n2015-03-15 01:02:53,10\n2015-03-15 01:07:53,15\n2015-03-15 01:12:53,13\n2015-03-15 01:17:53,7\n2015-03-15 01:22:53,4\n2015-03-15 01:27:53,6\n2015-03-15 01:32:53,10\n2015-03-15 01:37:53,11\n2015-03-15 01:42:53,8\n2015-03-15 01:47:53,11\n2015-03-15 01:52:53,4\n2015-03-15 01:57:53,14\n2015-03-15 02:02:53,10\n2015-03-15 02:07:53,8\n2015-03-15 02:12:53,10\n2015-03-15 02:17:53,11\n2015-03-15 02:22:53,8\n2015-03-15 02:27:53,8\n2015-03-15 02:32:53,7\n2015-03-15 02:37:53,8\n2015-03-15 02:42:53,4\n2015-03-15 02:47:53,12\n2015-03-15 02:52:53,13\n2015-03-15 02:57:53,13\n2015-03-15 03:02:53,10\n2015-03-15 03:07:53,12\n2015-03-15 03:12:53,9\n2015-03-15 03:17:53,12\n2015-03-15 03:22:53,7\n2015-03-15 03:27:53,8\n2015-03-15 03:32:53,20\n2015-03-15 03:37:53,5\n2015-03-15 03:42:53,16\n2015-03-15 03:47:53,12\n2015-03-15 03:52:53,7\n2015-03-15 03:57:53,8\n2015-03-15 04:02:53,10\n2015-03-15 04:07:53,16\n2015-03-15 04:12:53,7\n2015-03-15 04:17:53,7\n2015-03-15 04:22:53,13\n2015-03-15 04:27:53,10\n2015-03-15 04:32:53,5\n2015-03-15 04:37:53,6\n2015-03-15 04:42:53,10\n2015-03-15 04:47:53,7\n2015-03-15 04:52:53,14\n2015-03-15 04:57:53,5\n2015-03-15 05:02:53,7\n2015-03-15 05:07:53,3\n2015-03-15 05:12:53,8\n2015-03-15 05:17:53,6\n2015-03-15 05:22:53,9\n2015-03-15 05:27:53,11\n2015-03-15 05:32:53,11\n2015-03-15 05:37:53,5\n2015-03-15 05:42:53,3\n2015-03-15 05:47:53,5\n2015-03-15 05:52:53,4\n2015-03-15 05:57:53,15\n2015-03-15 06:02:53,7\n2015-03-15 06:07:53,8\n2015-03-15 06:12:53,5\n2015-03-15 06:17:53,4\n2015-03-15 06:22:53,8\n2015-03-15 06:27:53,5\n2015-03-15 06:32:53,11\n2015-03-15 06:37:53,14\n2015-03-15 06:42:53,5\n2015-03-15 06:47:53,5\n2015-03-15 06:52:53,11\n2015-03-15 06:57:53,12\n2015-03-15 07:02:53,4\n2015-03-15 07:07:53,12\n2015-03-15 07:12:53,9\n2015-03-15 07:17:53,2\n2015-03-15 07:22:53,10\n2015-03-15 07:27:53,6\n2015-03-15 07:32:53,2\n2015-03-15 07:37:53,8\n2015-03-15 07:42:53,11\n2015-03-15 07:47:53,7\n2015-03-15 07:52:53,6\n2015-03-15 07:57:53,11\n2015-03-15 08:02:53,2\n2015-03-15 08:07:53,8\n2015-03-15 08:12:53,7\n2015-03-15 08:17:53,6\n2015-03-15 08:22:53,9\n2015-03-15 08:27:53,7\n2015-03-15 08:32:53,2\n2015-03-15 08:37:53,8\n2015-03-15 08:42:53,7\n2015-03-15 08:47:53,15\n2015-03-15 08:52:53,5\n2015-03-15 08:57:53,32\n2015-03-15 09:02:53,29\n2015-03-15 09:07:53,29\n2015-03-15 09:12:53,15\n2015-03-15 09:17:53,14\n2015-03-15 09:22:53,21\n2015-03-15 09:27:53,26\n2015-03-15 09:32:53,18\n2015-03-15 09:37:53,17\n2015-03-15 09:42:53,24\n2015-03-15 09:47:53,18\n2015-03-15 09:52:53,9\n2015-03-15 09:57:53,10\n2015-03-15 10:02:53,9\n2015-03-15 10:07:53,9\n2015-03-15 10:12:53,22\n2015-03-15 10:17:53,12\n2015-03-15 10:22:53,12\n2015-03-15 10:27:53,13\n2015-03-15 10:32:53,10\n2015-03-15 10:37:53,9\n2015-03-15 10:42:53,9\n2015-03-15 10:47:53,5\n2015-03-15 10:52:53,13\n2015-03-15 10:57:53,5\n2015-03-15 11:02:53,13\n2015-03-15 11:07:53,6\n2015-03-15 11:12:53,9\n2015-03-15 11:17:53,10\n2015-03-15 11:22:53,10\n2015-03-15 11:27:53,9\n2015-03-15 11:32:53,6\n2015-03-15 11:37:53,15\n2015-03-15 11:42:53,7\n2015-03-15 11:47:53,7\n2015-03-15 11:52:53,24\n2015-03-15 11:57:53,29\n2015-03-15 12:02:53,21\n2015-03-15 12:07:53,14\n2015-03-15 12:12:53,12\n2015-03-15 12:17:53,11\n2015-03-15 12:22:53,9\n2015-03-15 12:27:53,15\n2015-03-15 12:32:53,11\n2015-03-15 12:37:53,10\n2015-03-15 12:42:53,7\n2015-03-15 12:47:53,3\n2015-03-15 12:52:53,10\n2015-03-15 12:57:53,12\n2015-03-15 13:02:53,6\n2015-03-15 13:07:53,15\n2015-03-15 13:12:53,12\n2015-03-15 13:17:53,12\n2015-03-15 13:22:53,2\n2015-03-15 13:27:53,8\n2015-03-15 13:32:53,9\n2015-03-15 13:37:53,5\n2015-03-15 13:42:53,11\n2015-03-15 13:47:53,7\n2015-03-15 13:52:53,5\n2015-03-15 13:57:53,13\n2015-03-15 14:02:53,17\n2015-03-15 14:07:53,20\n2015-03-15 14:12:53,12\n2015-03-15 14:17:53,8\n2015-03-15 14:22:53,3\n2015-03-15 14:27:53,14\n2015-03-15 14:32:53,10\n2015-03-15 14:37:53,9\n2015-03-15 14:42:53,15\n2015-03-15 14:47:53,4\n2015-03-15 14:52:53,4\n2015-03-15 14:57:53,13\n2015-03-15 15:02:53,11\n2015-03-15 15:07:53,14\n2015-03-15 15:12:53,4\n2015-03-15 15:17:53,8\n2015-03-15 15:22:53,11\n2015-03-15 15:27:53,12\n2015-03-15 15:32:53,9\n2015-03-15 15:37:53,13\n2015-03-15 15:42:53,13\n2015-03-15 15:47:53,24\n2015-03-15 15:52:53,12\n2015-03-15 15:57:53,12\n2015-03-15 16:02:53,13\n2015-03-15 16:07:53,14\n2015-03-15 16:12:53,12\n2015-03-15 16:17:53,6\n2015-03-15 16:22:53,11\n2015-03-15 16:27:53,15\n2015-03-15 16:32:53,10\n2015-03-15 16:37:53,15\n2015-03-15 16:42:53,13\n2015-03-15 16:47:53,18\n2015-03-15 16:52:53,21\n2015-03-15 16:57:53,24\n2015-03-15 17:02:53,13\n2015-03-15 17:07:53,18\n2015-03-15 17:12:53,15\n2015-03-15 17:17:53,17\n2015-03-15 17:22:53,10\n2015-03-15 17:27:53,11\n2015-03-15 17:32:53,12\n2015-03-15 17:37:53,10\n2015-03-15 17:42:53,10\n2015-03-15 17:47:53,12\n2015-03-15 17:52:53,12\n2015-03-15 17:57:53,12\n2015-03-15 18:02:53,18\n2015-03-15 18:07:53,13\n2015-03-15 18:12:53,16\n2015-03-15 18:17:53,12\n2015-03-15 18:22:53,11\n2015-03-15 18:27:53,17\n2015-03-15 18:32:53,7\n2015-03-15 18:37:53,19\n2015-03-15 18:42:53,7\n2015-03-15 18:47:53,22\n2015-03-15 18:52:53,17\n2015-03-15 18:57:53,22\n2015-03-15 19:02:53,30\n2015-03-15 19:07:53,13\n2015-03-15 19:12:53,16\n2015-03-15 19:17:53,17\n2015-03-15 19:22:53,12\n2015-03-15 19:27:53,10\n2015-03-15 19:32:53,16\n2015-03-15 19:37:53,20\n2015-03-15 19:42:53,17\n2015-03-15 19:47:53,21\n2015-03-15 19:52:53,16\n2015-03-15 19:57:53,12\n2015-03-15 20:02:53,23\n2015-03-15 20:07:53,38\n2015-03-15 20:12:53,23\n2015-03-15 20:17:53,31\n2015-03-15 20:22:53,58\n2015-03-15 20:27:53,50\n2015-03-15 20:32:53,51\n2015-03-15 20:37:53,80\n2015-03-15 20:42:53,90\n2015-03-15 20:47:53,80\n2015-03-15 20:52:53,91\n2015-03-15 20:57:53,57\n2015-03-15 21:02:53,62\n2015-03-15 21:07:53,91\n2015-03-15 21:12:53,99\n2015-03-15 21:17:53,72\n2015-03-15 21:22:53,75\n2015-03-15 21:27:53,80\n2015-03-15 21:32:53,74\n2015-03-15 21:37:53,36\n2015-03-15 21:42:53,50\n2015-03-15 21:47:53,57\n2015-03-15 21:52:53,70\n2015-03-15 21:57:53,23\n2015-03-15 22:02:53,19\n2015-03-15 22:07:53,13\n2015-03-15 22:12:53,25\n2015-03-15 22:17:53,20\n2015-03-15 22:22:53,14\n2015-03-15 22:27:53,14\n2015-03-15 22:32:53,24\n2015-03-15 22:37:53,22\n2015-03-15 22:42:53,26\n2015-03-15 22:47:53,30\n2015-03-15 22:52:53,17\n2015-03-15 22:57:53,19\n2015-03-15 23:02:53,9\n2015-03-15 23:07:53,9\n2015-03-15 23:12:53,7\n2015-03-15 23:17:53,8\n2015-03-15 23:22:53,8\n2015-03-15 23:27:53,9\n2015-03-15 23:32:53,9\n2015-03-15 23:37:53,11\n2015-03-15 23:42:53,8\n2015-03-15 23:47:53,9\n2015-03-15 23:52:53,10\n2015-03-15 23:57:53,6\n2015-03-16 00:02:53,14\n2015-03-16 00:07:53,13\n2015-03-16 00:12:53,11\n2015-03-16 00:17:53,3\n2015-03-16 00:22:53,6\n2015-03-16 00:27:53,10\n2015-03-16 00:32:53,8\n2015-03-16 00:37:53,10\n2015-03-16 00:42:53,7\n2015-03-16 00:47:53,2\n2015-03-16 00:52:53,7\n2015-03-16 00:57:53,13\n2015-03-16 01:02:53,29\n2015-03-16 01:07:53,17\n2015-03-16 01:12:53,12\n2015-03-16 01:17:53,13\n2015-03-16 01:22:53,18\n2015-03-16 01:27:53,27\n2015-03-16 01:32:53,22\n2015-03-16 01:37:53,29\n2015-03-16 01:42:53,12\n2015-03-16 01:47:53,14\n2015-03-16 01:52:53,10\n2015-03-16 01:57:53,18\n2015-03-16 02:02:53,11\n2015-03-16 02:07:53,16\n2015-03-16 02:12:53,9\n2015-03-16 02:17:53,17\n2015-03-16 02:22:53,13\n2015-03-16 02:27:53,7\n2015-03-16 02:32:53,10\n2015-03-16 02:37:53,14\n2015-03-16 02:42:53,8\n2015-03-16 02:47:53,13\n2015-03-16 02:52:53,6\n2015-03-16 02:57:53,5\n2015-03-16 03:02:53,9\n2015-03-16 03:07:53,9\n2015-03-16 03:12:53,6\n2015-03-16 03:17:53,12\n2015-03-16 03:22:53,10\n2015-03-16 03:27:53,13\n2015-03-16 03:32:53,4\n2015-03-16 03:37:53,7\n2015-03-16 03:42:53,14\n2015-03-16 03:47:53,15\n2015-03-16 03:52:53,7\n2015-03-16 03:57:53,11\n2015-03-16 04:02:53,13\n2015-03-16 04:07:53,11\n2015-03-16 04:12:53,10\n2015-03-16 04:17:53,5\n2015-03-16 04:22:53,2\n2015-03-16 04:27:53,7\n2015-03-16 04:32:53,8\n2015-03-16 04:37:53,9\n2015-03-16 04:42:53,11\n2015-03-16 04:47:53,7\n2015-03-16 04:52:53,9\n2015-03-16 04:57:53,7\n2015-03-16 05:02:53,4\n2015-03-16 05:07:53,13\n2015-03-16 05:12:53,5\n2015-03-16 05:17:53,1\n2015-03-16 05:22:53,10\n2015-03-16 05:27:53,6\n2015-03-16 05:32:53,11\n2015-03-16 05:37:53,3\n2015-03-16 05:42:53,8\n2015-03-16 05:47:53,16\n2015-03-16 05:52:53,2\n2015-03-16 05:57:53,9\n2015-03-16 06:02:53,8\n2015-03-16 06:07:53,8\n2015-03-16 06:12:53,5\n2015-03-16 06:17:53,10\n2015-03-16 06:22:53,17\n2015-03-16 06:27:53,7\n2015-03-16 06:32:53,7\n2015-03-16 06:37:53,10\n2015-03-16 06:42:53,5\n2015-03-16 06:47:53,4\n2015-03-16 06:52:53,8\n2015-03-16 06:57:53,15\n2015-03-16 07:02:53,8\n2015-03-16 07:07:53,7\n2015-03-16 07:12:53,5\n2015-03-16 07:17:53,11\n2015-03-16 07:22:53,4\n2015-03-16 07:27:53,12\n2015-03-16 07:32:53,7\n2015-03-16 07:37:53,3\n2015-03-16 07:42:53,6\n2015-03-16 07:47:53,5\n2015-03-16 07:52:53,7\n2015-03-16 07:57:53,7\n2015-03-16 08:02:53,8\n2015-03-16 08:07:53,6\n2015-03-16 08:12:53,4\n2015-03-16 08:17:53,13\n2015-03-16 08:22:53,14\n2015-03-16 08:27:53,5\n2015-03-16 08:32:53,7\n2015-03-16 08:37:53,21\n2015-03-16 08:42:53,7\n2015-03-16 08:47:53,10\n2015-03-16 08:52:53,9\n2015-03-16 08:57:53,8\n2015-03-16 09:02:53,5\n2015-03-16 09:07:53,15\n2015-03-16 09:12:53,12\n2015-03-16 09:17:53,13\n2015-03-16 09:22:53,18\n2015-03-16 09:27:53,21\n2015-03-16 09:32:53,8\n2015-03-16 09:37:53,9\n2015-03-16 09:42:53,16\n2015-03-16 09:47:53,7\n2015-03-16 09:52:53,9\n2015-03-16 09:57:53,13\n2015-03-16 10:02:53,8\n2015-03-16 10:07:53,10\n2015-03-16 10:12:53,5\n2015-03-16 10:17:53,7\n2015-03-16 10:22:53,13\n2015-03-16 10:27:53,10\n2015-03-16 10:32:53,6\n2015-03-16 10:37:53,22\n2015-03-16 10:42:53,12\n2015-03-16 10:47:53,16\n2015-03-16 10:52:53,16\n2015-03-16 10:57:53,14\n2015-03-16 11:02:53,8\n2015-03-16 11:07:53,13\n2015-03-16 11:12:53,4\n2015-03-16 11:17:53,6\n2015-03-16 11:22:53,11\n2015-03-16 11:27:53,20\n2015-03-16 11:32:53,5\n2015-03-16 11:37:53,4\n2015-03-16 11:42:53,12\n2015-03-16 11:47:53,11\n2015-03-16 11:52:53,19\n2015-03-16 11:57:53,17\n2015-03-16 12:02:53,18\n2015-03-16 12:07:53,8\n2015-03-16 12:12:53,14\n2015-03-16 12:17:53,16\n2015-03-16 12:22:53,20\n2015-03-16 12:27:53,26\n2015-03-16 12:32:53,38\n2015-03-16 12:37:53,52\n2015-03-16 12:42:53,6\n2015-03-16 12:47:53,11\n2015-03-16 12:52:53,16\n2015-03-16 12:57:53,29\n2015-03-16 13:02:53,22\n2015-03-16 13:07:53,23\n2015-03-16 13:12:53,18\n2015-03-16 13:17:53,16\n2015-03-16 13:22:53,10\n2015-03-16 13:27:53,23\n2015-03-16 13:32:53,17\n2015-03-16 13:37:53,19\n2015-03-16 13:42:53,26\n2015-03-16 13:47:53,23\n2015-03-16 13:52:53,13\n2015-03-16 13:57:53,19\n2015-03-16 14:02:53,14\n2015-03-16 14:07:53,23\n2015-03-16 14:12:53,15\n2015-03-16 14:17:53,24\n2015-03-16 14:22:53,25\n2015-03-16 14:27:53,17\n2015-03-16 14:32:53,15\n2015-03-16 14:37:53,13\n2015-03-16 14:42:53,19\n2015-03-16 14:47:53,14\n2015-03-16 14:52:53,26\n2015-03-16 14:57:53,22\n2015-03-16 15:02:53,18\n2015-03-16 15:07:53,11\n2015-03-16 15:12:53,16\n2015-03-16 15:17:53,20\n2015-03-16 15:22:53,28\n2015-03-16 15:27:53,25\n2015-03-16 15:32:53,21\n2015-03-16 15:37:53,24\n2015-03-16 15:42:53,20\n2015-03-16 15:47:53,21\n2015-03-16 15:52:53,29\n2015-03-16 15:57:53,45\n2015-03-16 16:02:53,19\n2015-03-16 16:07:53,26\n2015-03-16 16:12:53,19\n2015-03-16 16:17:53,23\n2015-03-16 16:22:53,15\n2015-03-16 16:27:53,19\n2015-03-16 16:32:53,20\n2015-03-16 16:37:53,16\n2015-03-16 16:42:53,25\n2015-03-16 16:47:53,13\n2015-03-16 16:52:53,30\n2015-03-16 16:57:53,29\n2015-03-16 17:02:53,36\n2015-03-16 17:07:53,21\n2015-03-16 17:12:53,24\n2015-03-16 17:17:53,52\n2015-03-16 17:22:53,63\n2015-03-16 17:27:53,61\n2015-03-16 17:32:53,43\n2015-03-16 17:37:53,41\n2015-03-16 17:42:53,37\n2015-03-16 17:47:53,21\n2015-03-16 17:52:53,22\n2015-03-16 17:57:53,52\n2015-03-16 18:02:53,41\n2015-03-16 18:07:53,54\n2015-03-16 18:12:53,35\n2015-03-16 18:17:53,28\n2015-03-16 18:22:53,26\n2015-03-16 18:27:53,33\n2015-03-16 18:32:53,19\n2015-03-16 18:37:53,20\n2015-03-16 18:42:53,22\n2015-03-16 18:47:53,35\n2015-03-16 18:52:53,28\n2015-03-16 18:57:53,28\n2015-03-16 19:02:53,23\n2015-03-16 19:07:53,22\n2015-03-16 19:12:53,22\n2015-03-16 19:17:53,19\n2015-03-16 19:22:53,15\n2015-03-16 19:27:53,34\n2015-03-16 19:32:53,25\n2015-03-16 19:37:53,27\n2015-03-16 19:42:53,23\n2015-03-16 19:47:53,16\n2015-03-16 19:52:53,25\n2015-03-16 19:57:53,17\n2015-03-16 20:02:53,19\n2015-03-16 20:07:53,26\n2015-03-16 20:12:53,34\n2015-03-16 20:17:53,17\n2015-03-16 20:22:53,22\n2015-03-16 20:27:53,34\n2015-03-16 20:32:53,24\n2015-03-16 20:37:53,19\n2015-03-16 20:42:53,32\n2015-03-16 20:47:53,34\n2015-03-16 20:52:53,22\n2015-03-16 20:57:53,20\n2015-03-16 21:02:53,17\n2015-03-16 21:07:53,15\n2015-03-16 21:12:53,21\n2015-03-16 21:17:53,11\n2015-03-16 21:22:53,17\n2015-03-16 21:27:53,54\n2015-03-16 21:32:53,26\n2015-03-16 21:37:53,37\n2015-03-16 21:42:53,32\n2015-03-16 21:47:53,20\n2015-03-16 21:52:53,31\n2015-03-16 21:57:53,27\n2015-03-16 22:02:53,22\n2015-03-16 22:07:53,17\n2015-03-16 22:12:53,24\n2015-03-16 22:17:53,18\n2015-03-16 22:22:53,21\n2015-03-16 22:27:53,29\n2015-03-16 22:32:53,19\n2015-03-16 22:37:53,24\n2015-03-16 22:42:53,21\n2015-03-16 22:47:53,12\n2015-03-16 22:52:53,18\n2015-03-16 22:57:53,22\n2015-03-16 23:02:53,19\n2015-03-16 23:07:53,11\n2015-03-16 23:12:53,13\n2015-03-16 23:17:53,12\n2015-03-16 23:22:53,25\n2015-03-16 23:27:53,11\n2015-03-16 23:32:53,20\n2015-03-16 23:37:53,22\n2015-03-16 23:42:53,20\n2015-03-16 23:47:53,13\n2015-03-16 23:52:53,17\n2015-03-16 23:57:53,18\n2015-03-17 00:02:53,29\n2015-03-17 00:07:53,15\n2015-03-17 00:12:53,11\n2015-03-17 00:17:53,19\n2015-03-17 00:22:53,14\n2015-03-17 00:27:53,14\n2015-03-17 00:32:53,18\n2015-03-17 00:37:53,7\n2015-03-17 00:42:53,23\n2015-03-17 00:47:53,22\n2015-03-17 00:52:53,15\n2015-03-17 00:57:53,36\n2015-03-17 01:02:53,17\n2015-03-17 01:07:53,21\n2015-03-17 01:12:53,34\n2015-03-17 01:17:53,18\n2015-03-17 01:22:53,19\n2015-03-17 01:27:53,20\n2015-03-17 01:32:53,22\n2015-03-17 01:37:53,16\n2015-03-17 01:42:53,21\n2015-03-17 01:47:53,19\n2015-03-17 01:52:53,31\n2015-03-17 01:57:53,17\n2015-03-17 02:02:53,12\n2015-03-17 02:07:53,10\n2015-03-17 02:12:53,11\n2015-03-17 02:17:53,15\n2015-03-17 02:22:53,10\n2015-03-17 02:27:53,17\n2015-03-17 02:32:53,16\n2015-03-17 02:37:53,20\n2015-03-17 02:42:53,33\n2015-03-17 02:47:53,12\n2015-03-17 02:52:53,3\n2015-03-17 02:57:53,6\n2015-03-17 03:02:53,16\n2015-03-17 03:07:53,8\n2015-03-17 03:12:53,8\n2015-03-17 03:17:53,11\n2015-03-17 03:22:53,10\n2015-03-17 03:27:53,17\n2015-03-17 03:32:53,18\n2015-03-17 03:37:53,20\n2015-03-17 03:42:53,11\n2015-03-17 03:47:53,8\n2015-03-17 03:52:53,11\n2015-03-17 03:57:53,9\n2015-03-17 04:02:53,16\n2015-03-17 04:07:53,27\n2015-03-17 04:12:53,17\n2015-03-17 04:17:53,14\n2015-03-17 04:22:53,6\n2015-03-17 04:27:53,11\n2015-03-17 04:32:53,13\n2015-03-17 04:37:53,9\n2015-03-17 04:42:53,14\n2015-03-17 04:47:53,19\n2015-03-17 04:52:53,13\n2015-03-17 04:57:53,19\n2015-03-17 05:02:53,10\n2015-03-17 05:07:53,14\n2015-03-17 05:12:53,18\n2015-03-17 05:17:53,13\n2015-03-17 05:22:53,10\n2015-03-17 05:27:53,14\n2015-03-17 05:32:53,11\n2015-03-17 05:37:53,7\n2015-03-17 05:42:53,16\n2015-03-17 05:47:53,12\n2015-03-17 05:52:53,12\n2015-03-17 05:57:53,23\n2015-03-17 06:02:53,16\n2015-03-17 06:07:53,19\n2015-03-17 06:12:53,22\n2015-03-17 06:17:53,5\n2015-03-17 06:22:53,18\n2015-03-17 06:27:53,17\n2015-03-17 06:32:53,7\n2015-03-17 06:37:53,13\n2015-03-17 06:42:53,14\n2015-03-17 06:47:53,14\n2015-03-17 06:52:53,14\n2015-03-17 06:57:53,12\n2015-03-17 07:02:53,11\n2015-03-17 07:07:53,20\n2015-03-17 07:12:53,12\n2015-03-17 07:17:53,12\n2015-03-17 07:22:53,8\n2015-03-17 07:27:53,11\n2015-03-17 07:32:53,8\n2015-03-17 07:37:53,3\n2015-03-17 07:42:53,13\n2015-03-17 07:47:53,10\n2015-03-17 07:52:53,15\n2015-03-17 07:57:53,16\n2015-03-17 08:02:53,17\n2015-03-17 08:07:53,17\n2015-03-17 08:12:53,16\n2015-03-17 08:17:53,23\n2015-03-17 08:22:53,14\n2015-03-17 08:27:53,7\n2015-03-17 08:32:53,4\n2015-03-17 08:37:53,10\n2015-03-17 08:42:53,14\n2015-03-17 08:47:53,11\n2015-03-17 08:52:53,11\n2015-03-17 08:57:53,15\n2015-03-17 09:02:53,12\n2015-03-17 09:07:53,19\n2015-03-17 09:12:53,17\n2015-03-17 09:17:53,22\n2015-03-17 09:22:53,14\n2015-03-17 09:27:53,18\n2015-03-17 09:32:53,15\n2015-03-17 09:37:53,15\n2015-03-17 09:42:53,21\n2015-03-17 09:47:53,27\n2015-03-17 09:52:53,11\n2015-03-17 09:57:53,11\n2015-03-17 10:02:53,18\n2015-03-17 10:07:53,9\n2015-03-17 10:12:53,14\n2015-03-17 10:17:53,27\n2015-03-17 10:22:53,12\n2015-03-17 10:27:53,14\n2015-03-17 10:32:53,14\n2015-03-17 10:37:53,27\n2015-03-17 10:42:53,12\n2015-03-17 10:47:53,15\n2015-03-17 10:52:53,11\n2015-03-17 10:57:53,22\n2015-03-17 11:02:53,19\n2015-03-17 11:07:53,27\n2015-03-17 11:12:53,15\n2015-03-17 11:17:53,15\n2015-03-17 11:22:53,25\n2015-03-17 11:27:53,36\n2015-03-17 11:32:53,18\n2015-03-17 11:37:53,8\n2015-03-17 11:42:53,13\n2015-03-17 11:47:53,14\n2015-03-17 11:52:53,18\n2015-03-17 11:57:53,20\n2015-03-17 12:02:53,18\n2015-03-17 12:07:53,22\n2015-03-17 12:12:53,18\n2015-03-17 12:17:53,15\n2015-03-17 12:22:53,11\n2015-03-17 12:27:53,22\n2015-03-17 12:32:53,20\n2015-03-17 12:37:53,30\n2015-03-17 12:42:53,18\n2015-03-17 12:47:53,20\n2015-03-17 12:52:53,16\n2015-03-17 12:57:53,22\n2015-03-17 13:02:53,28\n2015-03-17 13:07:53,21\n2015-03-17 13:12:53,16\n2015-03-17 13:17:53,21\n2015-03-17 13:22:53,28\n2015-03-17 13:27:53,17\n2015-03-17 13:32:53,23\n2015-03-17 13:37:53,20\n2015-03-17 13:42:53,13\n2015-03-17 13:47:53,26\n2015-03-17 13:52:53,26\n2015-03-17 13:57:53,46\n2015-03-17 14:02:53,41\n2015-03-17 14:07:53,38\n2015-03-17 14:12:53,37\n2015-03-17 14:17:53,30\n2015-03-17 14:22:53,37\n2015-03-17 14:27:53,30\n2015-03-17 14:32:53,35\n2015-03-17 14:37:53,61\n2015-03-17 14:42:53,86\n2015-03-17 14:47:53,38\n2015-03-17 14:52:53,43\n2015-03-17 14:57:53,42\n2015-03-17 15:02:53,46\n2015-03-17 15:07:53,39\n2015-03-17 15:12:53,39\n2015-03-17 15:17:53,51\n2015-03-17 15:22:53,45\n2015-03-17 15:27:53,53\n2015-03-17 15:32:53,52\n2015-03-17 15:37:53,37\n2015-03-17 15:42:53,43\n2015-03-17 15:47:53,35\n2015-03-17 15:52:53,38\n2015-03-17 15:57:53,31\n2015-03-17 16:02:53,45\n2015-03-17 16:07:53,24\n2015-03-17 16:12:53,43\n2015-03-17 16:17:53,52\n2015-03-17 16:22:53,34\n2015-03-17 16:27:53,32\n2015-03-17 16:32:53,44\n2015-03-17 16:37:53,28\n2015-03-17 16:42:53,27\n2015-03-17 16:47:53,27\n2015-03-17 16:52:53,33\n2015-03-17 16:57:53,30\n2015-03-17 17:02:53,26\n2015-03-17 17:07:53,52\n2015-03-17 17:12:53,53\n2015-03-17 17:17:53,37\n2015-03-17 17:22:53,37\n2015-03-17 17:27:53,35\n2015-03-17 17:32:53,29\n2015-03-17 17:37:53,35\n2015-03-17 17:42:53,31\n2015-03-17 17:47:53,27\n2015-03-17 17:52:53,28\n2015-03-17 17:57:53,34\n2015-03-17 18:02:53,29\n2015-03-17 18:07:53,22\n2015-03-17 18:12:53,30\n2015-03-17 18:17:53,18\n2015-03-17 18:22:53,26\n2015-03-17 18:27:53,39\n2015-03-17 18:32:53,33\n2015-03-17 18:37:53,22\n2015-03-17 18:42:53,53\n2015-03-17 18:47:53,100\n2015-03-17 18:52:53,78\n2015-03-17 18:57:53,52\n2015-03-17 19:02:53,51\n2015-03-17 19:07:53,52\n2015-03-17 19:12:53,52\n2015-03-17 19:17:53,43\n2015-03-17 19:22:53,41\n2015-03-17 19:27:53,49\n2015-03-17 19:32:53,41\n2015-03-17 19:37:53,57\n2015-03-17 19:42:53,49\n2015-03-17 19:47:53,48\n2015-03-17 19:52:53,34\n2015-03-17 19:57:53,37\n2015-03-17 20:02:53,34\n2015-03-17 20:07:53,22\n2015-03-17 20:12:53,44\n2015-03-17 20:17:53,69\n2015-03-17 20:22:53,46\n2015-03-17 20:27:53,24\n2015-03-17 20:32:53,23\n2015-03-17 20:37:53,17\n2015-03-17 20:42:53,21\n2015-03-17 20:47:53,23\n2015-03-17 20:52:53,26\n2015-03-17 20:57:53,24\n2015-03-17 21:02:53,36\n2015-03-17 21:07:53,31\n2015-03-17 21:12:53,37\n2015-03-17 21:17:53,23\n2015-03-17 21:22:53,23\n2015-03-17 21:27:53,33\n2015-03-17 21:32:53,64\n2015-03-17 21:37:53,65\n2015-03-17 21:42:53,30\n2015-03-17 21:47:53,30\n2015-03-17 21:52:53,29\n2015-03-17 21:57:53,24\n2015-03-17 22:02:53,43\n2015-03-17 22:07:53,26\n2015-03-17 22:12:53,24\n2015-03-17 22:17:53,15\n2015-03-17 22:22:53,19\n2015-03-17 22:27:53,26\n2015-03-17 22:32:53,38\n2015-03-17 22:37:53,44\n2015-03-17 22:42:53,26\n2015-03-17 22:47:53,22\n2015-03-17 22:52:53,24\n2015-03-17 22:57:53,16\n2015-03-17 23:02:53,17\n2015-03-17 23:07:53,11\n2015-03-17 23:12:53,41\n2015-03-17 23:17:53,18\n2015-03-17 23:22:53,30\n2015-03-17 23:27:53,45\n2015-03-17 23:32:53,29\n2015-03-17 23:37:53,26\n2015-03-17 23:42:53,12\n2015-03-17 23:47:53,19\n2015-03-17 23:52:53,17\n2015-03-17 23:57:53,30\n2015-03-18 00:02:53,21\n2015-03-18 00:07:53,17\n2015-03-18 00:12:53,20\n2015-03-18 00:17:53,19\n2015-03-18 00:22:53,19\n2015-03-18 00:27:53,15\n2015-03-18 00:32:53,11\n2015-03-18 00:37:53,14\n2015-03-18 00:42:53,15\n2015-03-18 00:47:53,11\n2015-03-18 00:52:53,20\n2015-03-18 00:57:53,16\n2015-03-18 01:02:53,16\n2015-03-18 01:07:53,16\n2015-03-18 01:12:53,5\n2015-03-18 01:17:53,12\n2015-03-18 01:22:53,17\n2015-03-18 01:27:53,22\n2015-03-18 01:32:53,9\n2015-03-18 01:37:53,11\n2015-03-18 01:42:53,20\n2015-03-18 01:47:53,16\n2015-03-18 01:52:53,15\n2015-03-18 01:57:53,20\n2015-03-18 02:02:53,25\n2015-03-18 02:07:53,15\n2015-03-18 02:12:53,15\n2015-03-18 02:17:53,9\n2015-03-18 02:22:53,9\n2015-03-18 02:27:53,9\n2015-03-18 02:32:53,19\n2015-03-18 02:37:53,11\n2015-03-18 02:42:53,9\n2015-03-18 02:47:53,12\n2015-03-18 02:52:53,14\n2015-03-18 02:57:53,16\n2015-03-18 03:02:53,18\n2015-03-18 03:07:53,13\n2015-03-18 03:12:53,16\n2015-03-18 03:17:53,15\n2015-03-18 03:22:53,13\n2015-03-18 03:27:53,18\n2015-03-18 03:32:53,18\n2015-03-18 03:37:53,19\n2015-03-18 03:42:53,21\n2015-03-18 03:47:53,9\n2015-03-18 03:52:53,12\n2015-03-18 03:57:53,17\n2015-03-18 04:02:53,5\n2015-03-18 04:07:53,14\n2015-03-18 04:12:53,9\n2015-03-18 04:17:53,10\n2015-03-18 04:22:53,7\n2015-03-18 04:27:53,21\n2015-03-18 04:32:53,6\n2015-03-18 04:37:53,12\n2015-03-18 04:42:53,7\n2015-03-18 04:47:53,8\n2015-03-18 04:52:53,9\n2015-03-18 04:57:53,19\n2015-03-18 05:02:53,6\n2015-03-18 05:07:53,15\n2015-03-18 05:12:53,8\n2015-03-18 05:17:53,7\n2015-03-18 05:22:53,65\n2015-03-18 05:27:53,47\n2015-03-18 05:32:53,27\n2015-03-18 05:37:53,21\n2015-03-18 05:42:53,26\n2015-03-18 05:47:53,8\n2015-03-18 05:52:53,15\n2015-03-18 05:57:53,14\n2015-03-18 06:02:53,16\n2015-03-18 06:07:53,7\n2015-03-18 06:12:53,16\n2015-03-18 06:17:53,6\n2015-03-18 06:22:53,12\n2015-03-18 06:27:53,11\n2015-03-18 06:32:53,18\n2015-03-18 06:37:53,17\n2015-03-18 06:42:53,18\n2015-03-18 06:47:53,13\n2015-03-18 06:52:53,12\n2015-03-18 06:57:53,13\n2015-03-18 07:02:53,14\n2015-03-18 07:07:53,11\n2015-03-18 07:12:53,7\n2015-03-18 07:17:53,10\n2015-03-18 07:22:53,15\n2015-03-18 07:27:53,15\n2015-03-18 07:32:53,20\n2015-03-18 07:37:53,26\n2015-03-18 07:42:53,16\n2015-03-18 07:47:53,10\n2015-03-18 07:52:53,14\n2015-03-18 07:57:53,15\n2015-03-18 08:02:53,18\n2015-03-18 08:07:53,10\n2015-03-18 08:12:53,13\n2015-03-18 08:17:53,9\n2015-03-18 08:22:53,16\n2015-03-18 08:27:53,23\n2015-03-18 08:32:53,21\n2015-03-18 08:37:53,18\n2015-03-18 08:42:53,15\n2015-03-18 08:47:53,11\n2015-03-18 08:52:53,15\n2015-03-18 08:57:53,17\n2015-03-18 09:02:53,16\n2015-03-18 09:07:53,16\n2015-03-18 09:12:53,18\n2015-03-18 09:17:53,16\n2015-03-18 09:22:53,17\n2015-03-18 09:27:53,19\n2015-03-18 09:32:53,15\n2015-03-18 09:37:53,19\n2015-03-18 09:42:53,21\n2015-03-18 09:47:53,16\n2015-03-18 09:52:53,18\n2015-03-18 09:57:53,14\n2015-03-18 10:02:53,13\n2015-03-18 10:07:53,23\n2015-03-18 10:12:53,30\n2015-03-18 10:17:53,20\n2015-03-18 10:22:53,14\n2015-03-18 10:27:53,27\n2015-03-18 10:32:53,12\n2015-03-18 10:37:53,27\n2015-03-18 10:42:53,23\n2015-03-18 10:47:53,35\n2015-03-18 10:52:53,19\n2015-03-18 10:57:53,20\n2015-03-18 11:02:53,24\n2015-03-18 11:07:53,23\n2015-03-18 11:12:53,17\n2015-03-18 11:17:53,17\n2015-03-18 11:22:53,15\n2015-03-18 11:27:53,23\n2015-03-18 11:32:53,22\n2015-03-18 11:37:53,22\n2015-03-18 11:42:53,15\n2015-03-18 11:47:53,21\n2015-03-18 11:52:53,21\n2015-03-18 11:57:53,45\n2015-03-18 12:02:53,17\n2015-03-18 12:07:53,9\n2015-03-18 12:12:53,13\n2015-03-18 12:17:53,11\n2015-03-18 12:22:53,16\n2015-03-18 12:27:53,21\n2015-03-18 12:32:53,22\n2015-03-18 12:37:53,20\n2015-03-18 12:42:53,27\n2015-03-18 12:47:53,16\n2015-03-18 12:52:53,22\n2015-03-18 12:57:53,22\n2015-03-18 13:02:53,26\n2015-03-18 13:07:53,12\n2015-03-18 13:12:53,15\n2015-03-18 13:17:53,26\n2015-03-18 13:22:53,21\n2015-03-18 13:27:53,17\n2015-03-18 13:32:53,11\n2015-03-18 13:37:53,27\n2015-03-18 13:42:53,29\n2015-03-18 13:47:53,44\n2015-03-18 13:52:53,38\n2015-03-18 13:57:53,36\n2015-03-18 14:02:53,28\n2015-03-18 14:07:53,30\n2015-03-18 14:12:53,18\n2015-03-18 14:17:53,26\n2015-03-18 14:22:53,26\n2015-03-18 14:27:53,35\n2015-03-18 14:32:53,29\n2015-03-18 14:37:53,28\n2015-03-18 14:42:53,29\n2015-03-18 14:47:53,24\n2015-03-18 14:52:53,32\n2015-03-18 14:57:53,27\n2015-03-18 15:02:53,26\n2015-03-18 15:07:53,48\n2015-03-18 15:12:53,40\n2015-03-18 15:17:53,41\n2015-03-18 15:22:53,47\n2015-03-18 15:27:53,53\n2015-03-18 15:32:53,32\n2015-03-18 15:37:53,29\n2015-03-18 15:42:53,36\n2015-03-18 15:47:53,40\n2015-03-18 15:52:53,19\n2015-03-18 15:57:53,89\n2015-03-18 16:02:53,73\n2015-03-18 16:07:53,48\n2015-03-18 16:12:53,37\n2015-03-18 16:17:53,37\n2015-03-18 16:22:53,25\n2015-03-18 16:27:53,38\n2015-03-18 16:32:53,24\n2015-03-18 16:37:53,24\n2015-03-18 16:42:53,38\n2015-03-18 16:47:53,26\n2015-03-18 16:52:53,20\n2015-03-18 16:57:53,31\n2015-03-18 17:02:53,29\n2015-03-18 17:07:53,22\n2015-03-18 17:12:53,37\n2015-03-18 17:17:53,25\n2015-03-18 17:22:53,27\n2015-03-18 17:27:53,46\n2015-03-18 17:32:53,39\n2015-03-18 17:37:53,31\n2015-03-18 17:42:53,32\n2015-03-18 17:47:53,27\n2015-03-18 17:52:53,34\n2015-03-18 17:57:53,61\n2015-03-18 18:02:53,61\n2015-03-18 18:07:53,42\n2015-03-18 18:12:53,32\n2015-03-18 18:17:53,33\n2015-03-18 18:22:53,39\n2015-03-18 18:27:53,41\n2015-03-18 18:32:53,31\n2015-03-18 18:37:53,24\n2015-03-18 18:42:53,31\n2015-03-18 18:47:53,20\n2015-03-18 18:52:53,50\n2015-03-18 18:57:53,37\n2015-03-18 19:02:53,37\n2015-03-18 19:07:53,31\n2015-03-18 19:12:53,31\n2015-03-18 19:17:53,26\n2015-03-18 19:22:53,22\n2015-03-18 19:27:53,32\n2015-03-18 19:32:53,34\n2015-03-18 19:37:53,26\n2015-03-18 19:42:53,24\n2015-03-18 19:47:53,28\n2015-03-18 19:52:53,24\n2015-03-18 19:57:53,34\n2015-03-18 20:02:53,19\n2015-03-18 20:07:53,21\n2015-03-18 20:12:53,30\n2015-03-18 20:17:53,28\n2015-03-18 20:22:53,25\n2015-03-18 20:27:53,16\n2015-03-18 20:32:53,21\n2015-03-18 20:37:53,32\n2015-03-18 20:42:53,24\n2015-03-18 20:47:53,18\n2015-03-18 20:52:53,10\n2015-03-18 20:57:53,27\n2015-03-18 21:02:53,22\n2015-03-18 21:07:53,22\n2015-03-18 21:12:53,43\n2015-03-18 21:17:53,55\n2015-03-18 21:22:53,48\n2015-03-18 21:27:53,25\n2015-03-18 21:32:53,38\n2015-03-18 21:37:53,27\n2015-03-18 21:42:53,35\n2015-03-18 21:47:53,62\n2015-03-18 21:52:53,70\n2015-03-18 21:57:53,47\n2015-03-18 22:02:53,14\n2015-03-18 22:07:53,31\n2015-03-18 22:12:53,25\n2015-03-18 22:17:53,16\n2015-03-18 22:22:53,29\n2015-03-18 22:27:53,31\n2015-03-18 22:32:53,29\n2015-03-18 22:37:53,25\n2015-03-18 22:42:53,45\n2015-03-18 22:47:53,29\n2015-03-18 22:52:53,19\n2015-03-18 22:57:53,36\n2015-03-18 23:02:53,27\n2015-03-18 23:07:53,23\n2015-03-18 23:12:53,19\n2015-03-18 23:17:53,18\n2015-03-18 23:22:53,15\n2015-03-18 23:27:53,29\n2015-03-18 23:32:53,17\n2015-03-18 23:37:53,30\n2015-03-18 23:42:53,47\n2015-03-18 23:47:53,35\n2015-03-18 23:52:53,14\n2015-03-18 23:57:53,24\n2015-03-19 00:02:53,28\n2015-03-19 00:07:53,22\n2015-03-19 00:12:53,36\n2015-03-19 00:17:53,15\n2015-03-19 00:22:53,20\n2015-03-19 00:27:53,36\n2015-03-19 00:32:53,25\n2015-03-19 00:37:53,18\n2015-03-19 00:42:53,23\n2015-03-19 00:47:53,22\n2015-03-19 00:52:53,22\n2015-03-19 00:57:53,15\n2015-03-19 01:02:53,10\n2015-03-19 01:07:53,22\n2015-03-19 01:12:53,23\n2015-03-19 01:17:53,13\n2015-03-19 01:22:53,22\n2015-03-19 01:27:53,22\n2015-03-19 01:32:53,14\n2015-03-19 01:37:53,29\n2015-03-19 01:42:53,24\n2015-03-19 01:47:53,25\n2015-03-19 01:52:53,19\n2015-03-19 01:57:53,29\n2015-03-19 02:02:53,25\n2015-03-19 02:07:53,18\n2015-03-19 02:12:53,22\n2015-03-19 02:17:53,33\n2015-03-19 02:22:53,18\n2015-03-19 02:27:53,24\n2015-03-19 02:32:53,24\n2015-03-19 02:37:53,17\n2015-03-19 02:42:53,15\n2015-03-19 02:47:53,18\n2015-03-19 02:52:53,21\n2015-03-19 02:57:53,27\n2015-03-19 03:02:53,24\n2015-03-19 03:07:53,6\n2015-03-19 03:12:53,9\n2015-03-19 03:17:53,22\n2015-03-19 03:22:53,11\n2015-03-19 03:27:53,12\n2015-03-19 03:32:53,22\n2015-03-19 03:37:53,12\n2015-03-19 03:42:53,15\n2015-03-19 03:47:53,23\n2015-03-19 03:52:53,13\n2015-03-19 03:57:53,23\n2015-03-19 04:02:53,8\n2015-03-19 04:07:53,7\n2015-03-19 04:12:53,16\n2015-03-19 04:17:53,9\n2015-03-19 04:22:53,9\n2015-03-19 04:27:53,10\n2015-03-19 04:32:53,11\n2015-03-19 04:37:53,8\n2015-03-19 04:42:53,14\n2015-03-19 04:47:53,13\n2015-03-19 04:52:53,15\n2015-03-19 04:57:53,11\n2015-03-19 05:02:53,5\n2015-03-19 05:07:53,12\n2015-03-19 05:12:53,15\n2015-03-19 05:17:53,11\n2015-03-19 05:22:53,18\n2015-03-19 05:27:53,5\n2015-03-19 05:32:53,5\n2015-03-19 05:37:53,7\n2015-03-19 05:42:53,10\n2015-03-19 05:47:53,18\n2015-03-19 05:52:53,9\n2015-03-19 05:57:53,8\n2015-03-19 06:02:53,21\n2015-03-19 06:07:53,5\n2015-03-19 06:12:53,18\n2015-03-19 06:17:53,6\n2015-03-19 06:22:53,7\n2015-03-19 06:27:53,11\n2015-03-19 06:32:53,5\n2015-03-19 06:37:53,17\n2015-03-19 06:42:53,8\n2015-03-19 06:47:53,9\n2015-03-19 06:52:53,7\n2015-03-19 06:57:53,10\n2015-03-19 07:02:53,7\n2015-03-19 07:07:53,2\n2015-03-19 07:12:53,7\n2015-03-19 07:17:53,5\n2015-03-19 07:22:53,11\n2015-03-19 07:27:53,6\n2015-03-19 07:32:53,7\n2015-03-19 07:37:53,10\n2015-03-19 07:42:53,9\n2015-03-19 07:47:53,20\n2015-03-19 07:52:53,30\n2015-03-19 07:57:53,18\n2015-03-19 08:02:53,38\n2015-03-19 08:07:53,20\n2015-03-19 08:12:53,22\n2015-03-19 08:17:53,14\n2015-03-19 08:22:53,18\n2015-03-19 08:27:53,42\n2015-03-19 08:32:53,17\n2015-03-19 08:37:53,11\n2015-03-19 08:42:53,24\n2015-03-19 08:47:53,12\n2015-03-19 08:52:53,14\n2015-03-19 08:57:53,23\n2015-03-19 09:02:53,19\n2015-03-19 09:07:53,11\n2015-03-19 09:12:53,13\n2015-03-19 09:17:53,18\n2015-03-19 09:22:53,13\n2015-03-19 09:27:53,15\n2015-03-19 09:32:53,9\n2015-03-19 09:37:53,14\n2015-03-19 09:42:53,10\n2015-03-19 09:47:53,29\n2015-03-19 09:52:53,29\n2015-03-19 09:57:53,23\n2015-03-19 10:02:53,24\n2015-03-19 10:07:53,23\n2015-03-19 10:12:53,20\n2015-03-19 10:17:53,17\n2015-03-19 10:22:53,20\n2015-03-19 10:27:53,16\n2015-03-19 10:32:53,20\n2015-03-19 10:37:53,18\n2015-03-19 10:42:53,15\n2015-03-19 10:47:53,21\n2015-03-19 10:52:53,18\n2015-03-19 10:57:53,22\n2015-03-19 11:02:53,25\n2015-03-19 11:07:53,22\n2015-03-19 11:12:53,12\n2015-03-19 11:17:53,19\n2015-03-19 11:22:53,16\n2015-03-19 11:27:53,17\n2015-03-19 11:32:53,19\n2015-03-19 11:37:53,20\n2015-03-19 11:42:53,21\n2015-03-19 11:47:53,8\n2015-03-19 11:52:53,18\n2015-03-19 11:57:53,26\n2015-03-19 12:02:53,21\n2015-03-19 12:07:53,29\n2015-03-19 12:12:53,25\n2015-03-19 12:17:53,24\n2015-03-19 12:22:53,34\n2015-03-19 12:27:53,15\n2015-03-19 12:32:53,13\n2015-03-19 12:37:53,21\n2015-03-19 12:42:53,25\n2015-03-19 12:47:53,17\n2015-03-19 12:52:53,19\n2015-03-19 12:57:53,39\n2015-03-19 13:02:53,28\n2015-03-19 13:07:53,53\n2015-03-19 13:12:53,47\n2015-03-19 13:17:53,45\n2015-03-19 13:22:53,55\n2015-03-19 13:27:53,42\n2015-03-19 13:32:53,43\n2015-03-19 13:37:53,41\n2015-03-19 13:42:53,32\n2015-03-19 13:47:53,40\n2015-03-19 13:52:53,29\n2015-03-19 13:57:53,47\n2015-03-19 14:02:53,50\n2015-03-19 14:07:53,44\n2015-03-19 14:12:53,46\n2015-03-19 14:17:53,32\n2015-03-19 14:22:53,35\n2015-03-19 14:27:53,52\n2015-03-19 14:32:53,39\n2015-03-19 14:37:53,34\n2015-03-19 14:42:53,41\n2015-03-19 14:47:53,35\n2015-03-19 14:52:53,51\n2015-03-19 14:57:53,35\n2015-03-19 15:02:53,44\n2015-03-19 15:07:53,32\n2015-03-19 15:12:53,27\n2015-03-19 15:17:53,28\n2015-03-19 15:22:53,29\n2015-03-19 15:27:53,32\n2015-03-19 15:32:53,38\n2015-03-19 15:37:53,27\n2015-03-19 15:42:53,22\n2015-03-19 15:47:53,48\n2015-03-19 15:52:53,33\n2015-03-19 15:57:53,62\n2015-03-19 16:02:53,36\n2015-03-19 16:07:53,25\n2015-03-19 16:12:53,33\n2015-03-19 16:17:53,28\n2015-03-19 16:22:53,31\n2015-03-19 16:27:53,28\n2015-03-19 16:32:53,26\n2015-03-19 16:37:53,50\n2015-03-19 16:42:53,30\n2015-03-19 16:47:53,36\n2015-03-19 16:52:53,52\n2015-03-19 16:57:53,46\n2015-03-19 17:02:53,44\n2015-03-19 17:07:53,41\n2015-03-19 17:12:53,56\n2015-03-19 17:17:53,48\n2015-03-19 17:22:53,33\n2015-03-19 17:27:53,33\n2015-03-19 17:32:53,32\n2015-03-19 17:37:53,33\n2015-03-19 17:42:53,33\n2015-03-19 17:47:53,26\n2015-03-19 17:52:53,23\n2015-03-19 17:57:53,15\n2015-03-19 18:02:53,37\n2015-03-19 18:07:53,47\n2015-03-19 18:12:53,27\n2015-03-19 18:17:53,25\n2015-03-19 18:22:53,34\n2015-03-19 18:27:53,27\n2015-03-19 18:32:53,39\n2015-03-19 18:37:53,38\n2015-03-19 18:42:53,26\n2015-03-19 18:47:53,22\n2015-03-19 18:52:53,37\n2015-03-19 18:57:53,41\n2015-03-19 19:02:53,35\n2015-03-19 19:07:53,24\n2015-03-19 19:12:53,25\n2015-03-19 19:17:53,35\n2015-03-19 19:22:53,20\n2015-03-19 19:27:53,31\n2015-03-19 19:32:53,32\n2015-03-19 19:37:53,40\n2015-03-19 19:42:53,38\n2015-03-19 19:47:53,43\n2015-03-19 19:52:53,35\n2015-03-19 19:57:53,46\n2015-03-19 20:02:53,59\n2015-03-19 20:07:53,58\n2015-03-19 20:12:53,29\n2015-03-19 20:17:53,12\n2015-03-19 20:22:53,34\n2015-03-19 20:27:53,31\n2015-03-19 20:32:53,21\n2015-03-19 20:37:53,44\n2015-03-19 20:42:53,14\n2015-03-19 20:47:53,23\n2015-03-19 20:52:53,26\n2015-03-19 20:57:53,34\n2015-03-19 21:02:53,33\n2015-03-19 21:07:53,26\n2015-03-19 21:12:53,23\n2015-03-19 21:17:53,15\n2015-03-19 21:22:53,18\n2015-03-19 21:27:53,36\n2015-03-19 21:32:53,17\n2015-03-19 21:37:53,18\n2015-03-19 21:42:53,27\n2015-03-19 21:47:53,28\n2015-03-19 21:52:53,20\n2015-03-19 21:57:53,21\n2015-03-19 22:02:53,20\n2015-03-19 22:07:53,17\n2015-03-19 22:12:53,13\n2015-03-19 22:17:53,33\n2015-03-19 22:22:53,18\n2015-03-19 22:27:53,40\n2015-03-19 22:32:53,28\n2015-03-19 22:37:53,22\n2015-03-19 22:42:53,17\n2015-03-19 22:47:53,27\n2015-03-19 22:52:53,21\n2015-03-19 22:57:53,26\n2015-03-19 23:02:53,28\n2015-03-19 23:07:53,25\n2015-03-19 23:12:53,16\n2015-03-19 23:17:53,16\n2015-03-19 23:22:53,26\n2015-03-19 23:27:53,17\n2015-03-19 23:32:53,38\n2015-03-19 23:37:53,37\n2015-03-19 23:42:53,33\n2015-03-19 23:47:53,22\n2015-03-19 23:52:53,25\n2015-03-19 23:57:53,20\n2015-03-20 00:02:53,21\n2015-03-20 00:07:53,16\n2015-03-20 00:12:53,40\n2015-03-20 00:17:53,40\n2015-03-20 00:22:53,30\n2015-03-20 00:27:53,20\n2015-03-20 00:32:53,17\n2015-03-20 00:37:53,30\n2015-03-20 00:42:53,23\n2015-03-20 00:47:53,12\n2015-03-20 00:52:53,18\n2015-03-20 00:57:53,33\n2015-03-20 01:02:53,15\n2015-03-20 01:07:53,30\n2015-03-20 01:12:53,27\n2015-03-20 01:17:53,18\n2015-03-20 01:22:53,27\n2015-03-20 01:27:53,21\n2015-03-20 01:32:53,20\n2015-03-20 01:37:53,27\n2015-03-20 01:42:53,29\n2015-03-20 01:47:53,20\n2015-03-20 01:52:53,32\n2015-03-20 01:57:53,27\n2015-03-20 02:02:53,26\n2015-03-20 02:07:53,24\n2015-03-20 02:12:53,13\n2015-03-20 02:17:53,11\n2015-03-20 02:22:53,15\n2015-03-20 02:27:53,15\n2015-03-20 02:32:53,10\n2015-03-20 02:37:53,23\n2015-03-20 02:42:53,9\n2015-03-20 02:47:53,13\n2015-03-20 02:52:53,14\n2015-03-20 02:57:53,30\n2015-03-20 03:02:53,19\n2015-03-20 03:07:53,20\n2015-03-20 03:12:53,19\n2015-03-20 03:17:53,81\n2015-03-20 03:22:53,34\n2015-03-20 03:27:53,32\n2015-03-20 03:32:53,13\n2015-03-20 03:37:53,16\n2015-03-20 03:42:53,12\n2015-03-20 03:47:53,11\n2015-03-20 03:52:53,7\n2015-03-20 03:57:53,12\n2015-03-20 04:02:53,14\n2015-03-20 04:07:53,7\n2015-03-20 04:12:53,7\n2015-03-20 04:17:53,8\n2015-03-20 04:22:53,18\n2015-03-20 04:27:53,25\n2015-03-20 04:32:53,14\n2015-03-20 04:37:53,15\n2015-03-20 04:42:53,12\n2015-03-20 04:47:53,15\n2015-03-20 04:52:53,12\n2015-03-20 04:57:53,18\n2015-03-20 05:02:53,9\n2015-03-20 05:07:53,17\n2015-03-20 05:12:53,14\n2015-03-20 05:17:53,7\n2015-03-20 05:22:53,12\n2015-03-20 05:27:53,12\n2015-03-20 05:32:53,5\n2015-03-20 05:37:53,7\n2015-03-20 05:42:53,9\n2015-03-20 05:47:53,15\n2015-03-20 05:52:53,11\n2015-03-20 05:57:53,26\n2015-03-20 06:02:53,15\n2015-03-20 06:07:53,14\n2015-03-20 06:12:53,20\n2015-03-20 06:17:53,14\n2015-03-20 06:22:53,7\n2015-03-20 06:27:53,8\n2015-03-20 06:32:53,9\n2015-03-20 06:37:53,12\n2015-03-20 06:42:53,8\n2015-03-20 06:47:53,11\n2015-03-20 06:52:53,9\n2015-03-20 06:57:53,11\n2015-03-20 07:02:53,15\n2015-03-20 07:07:53,5\n2015-03-20 07:12:53,22\n2015-03-20 07:17:53,23\n2015-03-20 07:22:53,19\n2015-03-20 07:27:53,26\n2015-03-20 07:32:53,13\n2015-03-20 07:37:53,9\n2015-03-20 07:42:53,9\n2015-03-20 07:47:53,6\n2015-03-20 07:52:53,13\n2015-03-20 07:57:53,15\n2015-03-20 08:02:53,16\n2015-03-20 08:07:53,12\n2015-03-20 08:12:53,27\n2015-03-20 08:17:53,12\n2015-03-20 08:22:53,9\n2015-03-20 08:27:53,16\n2015-03-20 08:32:53,11\n2015-03-20 08:37:53,10\n2015-03-20 08:42:53,8\n2015-03-20 08:47:53,20\n2015-03-20 08:52:53,13\n2015-03-20 08:57:53,21\n2015-03-20 09:02:53,21\n2015-03-20 09:07:53,25\n2015-03-20 09:12:53,14\n2015-03-20 09:17:53,12\n2015-03-20 09:22:53,11\n2015-03-20 09:27:53,12\n2015-03-20 09:32:53,21\n2015-03-20 09:37:53,14\n2015-03-20 09:42:53,17\n2015-03-20 09:47:53,16\n2015-03-20 09:52:53,22\n2015-03-20 09:57:53,20\n2015-03-20 10:02:53,13\n2015-03-20 10:07:53,11\n2015-03-20 10:12:53,17\n2015-03-20 10:17:53,15\n2015-03-20 10:22:53,14\n2015-03-20 10:27:53,18\n2015-03-20 10:32:53,19\n2015-03-20 10:37:53,8\n2015-03-20 10:42:53,12\n2015-03-20 10:47:53,13\n2015-03-20 10:52:53,18\n2015-03-20 10:57:53,16\n2015-03-20 11:02:53,11\n2015-03-20 11:07:53,12\n2015-03-20 11:12:53,10\n2015-03-20 11:17:53,14\n2015-03-20 11:22:53,19\n2015-03-20 11:27:53,16\n2015-03-20 11:32:53,13\n2015-03-20 11:37:53,21\n2015-03-20 11:42:53,20\n2015-03-20 11:47:53,21\n2015-03-20 11:52:53,19\n2015-03-20 11:57:53,26\n2015-03-20 12:02:53,17\n2015-03-20 12:07:53,25\n2015-03-20 12:12:53,33\n2015-03-20 12:17:53,21\n2015-03-20 12:22:53,17\n2015-03-20 12:27:53,27\n2015-03-20 12:32:53,15\n2015-03-20 12:37:53,12\n2015-03-20 12:42:53,36\n2015-03-20 12:47:53,19\n2015-03-20 12:52:53,22\n2015-03-20 12:57:53,27\n2015-03-20 13:02:53,19\n2015-03-20 13:07:53,20\n2015-03-20 13:12:53,21\n2015-03-20 13:17:53,25\n2015-03-20 13:22:53,30\n2015-03-20 13:27:53,16\n2015-03-20 13:32:53,19\n2015-03-20 13:37:53,35\n2015-03-20 13:42:53,33\n2015-03-20 13:47:53,34\n2015-03-20 13:52:53,29\n2015-03-20 13:57:53,53\n2015-03-20 14:02:53,39\n2015-03-20 14:07:53,30\n2015-03-20 14:12:53,34\n2015-03-20 14:17:53,30\n2015-03-20 14:22:53,58\n2015-03-20 14:27:53,41\n2015-03-20 14:32:53,18\n2015-03-20 14:37:53,24\n2015-03-20 14:42:53,29\n2015-03-20 14:47:53,31\n2015-03-20 14:52:53,15\n2015-03-20 14:57:53,45\n2015-03-20 15:02:53,33\n2015-03-20 15:07:53,23\n2015-03-20 15:12:53,31\n2015-03-20 15:17:53,33\n2015-03-20 15:22:53,38\n2015-03-20 15:27:53,22\n2015-03-20 15:32:53,38\n2015-03-20 15:37:53,33\n2015-03-20 15:42:53,40\n2015-03-20 15:47:53,28\n2015-03-20 15:52:53,23\n2015-03-20 15:57:53,64\n2015-03-20 16:02:53,47\n2015-03-20 16:07:53,34\n2015-03-20 16:12:53,24\n2015-03-20 16:17:53,29\n2015-03-20 16:22:53,30\n2015-03-20 16:27:53,54\n2015-03-20 16:32:53,42\n2015-03-20 16:37:53,31\n2015-03-20 16:42:53,43\n2015-03-20 16:47:53,41\n2015-03-20 16:52:53,78\n2015-03-20 16:57:53,59\n2015-03-20 17:02:53,38\n2015-03-20 17:07:53,41\n2015-03-20 17:12:53,24\n2015-03-20 17:17:53,70\n2015-03-20 17:22:53,67\n2015-03-20 17:27:53,40\n2015-03-20 17:32:53,31\n2015-03-20 17:37:53,40\n2015-03-20 17:42:53,94\n2015-03-20 17:47:53,30\n2015-03-20 17:52:53,23\n2015-03-20 17:57:53,28\n2015-03-20 18:02:53,40\n2015-03-20 18:07:53,42\n2015-03-20 18:12:53,53\n2015-03-20 18:17:53,55\n2015-03-20 18:22:53,45\n2015-03-20 18:27:53,55\n2015-03-20 18:32:53,50\n2015-03-20 18:37:53,50\n2015-03-20 18:42:53,48\n2015-03-20 18:47:53,51\n2015-03-20 18:52:53,24\n2015-03-20 18:57:53,22\n2015-03-20 19:02:53,32\n2015-03-20 19:07:53,26\n2015-03-20 19:12:53,42\n2015-03-20 19:17:53,34\n2015-03-20 19:22:53,43\n2015-03-20 19:27:53,33\n2015-03-20 19:32:53,29\n2015-03-20 19:37:53,33\n2015-03-20 19:42:53,28\n2015-03-20 19:47:53,27\n2015-03-20 19:52:53,29\n2015-03-20 19:57:53,35\n2015-03-20 20:02:53,38\n2015-03-20 20:07:53,36\n2015-03-20 20:12:53,43\n2015-03-20 20:17:53,36\n2015-03-20 20:22:53,34\n2015-03-20 20:27:53,19\n2015-03-20 20:32:53,21\n2015-03-20 20:37:53,25\n2015-03-20 20:42:53,20\n2015-03-20 20:47:53,16\n2015-03-20 20:52:53,38\n2015-03-20 20:57:53,23\n2015-03-20 21:02:53,26\n2015-03-20 21:07:53,21\n2015-03-20 21:12:53,31\n2015-03-20 21:17:53,27\n2015-03-20 21:22:53,25\n2015-03-20 21:27:53,32\n2015-03-20 21:32:53,19\n2015-03-20 21:37:53,38\n2015-03-20 21:42:53,33\n2015-03-20 21:47:53,30\n2015-03-20 21:52:53,26\n2015-03-20 21:57:53,45\n2015-03-20 22:02:53,36\n2015-03-20 22:07:53,27\n2015-03-20 22:12:53,25\n2015-03-20 22:17:53,21\n2015-03-20 22:22:53,22\n2015-03-20 22:27:53,17\n2015-03-20 22:32:53,22\n2015-03-20 22:37:53,15\n2015-03-20 22:42:53,25\n2015-03-20 22:47:53,18\n2015-03-20 22:52:53,26\n2015-03-20 22:57:53,16\n2015-03-20 23:02:53,14\n2015-03-20 23:07:53,11\n2015-03-20 23:12:53,24\n2015-03-20 23:17:53,24\n2015-03-20 23:22:53,17\n2015-03-20 23:27:53,27\n2015-03-20 23:32:53,31\n2015-03-20 23:37:53,26\n2015-03-20 23:42:53,22\n2015-03-20 23:47:53,24\n2015-03-20 23:52:53,25\n2015-03-20 23:57:53,46\n2015-03-21 00:02:53,47\n2015-03-21 00:07:53,50\n2015-03-21 00:12:53,29\n2015-03-21 00:17:53,35\n2015-03-21 00:22:53,55\n2015-03-21 00:27:53,54\n2015-03-21 00:32:53,62\n2015-03-21 00:37:53,30\n2015-03-21 00:42:53,44\n2015-03-21 00:47:53,21\n2015-03-21 00:52:53,17\n2015-03-21 00:57:53,22\n2015-03-21 01:02:53,21\n2015-03-21 01:07:53,14\n2015-03-21 01:12:53,16\n2015-03-21 01:17:53,26\n2015-03-21 01:22:53,28\n2015-03-21 01:27:53,20\n2015-03-21 01:32:53,26\n2015-03-21 01:37:53,14\n2015-03-21 01:42:53,19\n2015-03-21 01:47:53,15\n2015-03-21 01:52:53,24\n2015-03-21 01:57:53,24\n2015-03-21 02:02:53,22\n2015-03-21 02:07:53,14\n2015-03-21 02:12:53,19\n2015-03-21 02:17:53,12\n2015-03-21 02:22:53,19\n2015-03-21 02:27:53,11\n2015-03-21 02:32:53,24\n2015-03-21 02:37:53,12\n2015-03-21 02:42:53,21\n2015-03-21 02:47:53,8\n2015-03-21 02:52:53,13\n2015-03-21 02:57:53,9\n2015-03-21 03:02:53,11\n2015-03-21 03:07:53,12\n2015-03-21 03:12:53,14\n2015-03-21 03:17:53,11\n2015-03-21 03:22:53,13\n2015-03-21 03:27:53,10\n2015-03-21 03:32:53,12\n2015-03-21 03:37:53,5\n2015-03-21 03:42:53,9\n2015-03-21 03:47:53,12\n2015-03-21 03:52:53,15\n2015-03-21 03:57:53,12\n2015-03-21 04:02:53,7\n2015-03-21 04:07:53,7\n2015-03-21 04:12:53,19\n2015-03-21 04:17:53,10\n2015-03-21 04:22:53,12\n2015-03-21 04:27:53,9\n2015-03-21 04:32:53,5\n2015-03-21 04:37:53,13\n2015-03-21 04:42:53,9\n2015-03-21 04:47:53,9\n2015-03-21 04:52:53,17\n2015-03-21 04:57:53,17\n2015-03-21 05:02:53,8\n2015-03-21 05:07:53,1\n2015-03-21 05:12:53,8\n2015-03-21 05:17:53,14\n2015-03-21 05:22:53,12\n2015-03-21 05:27:53,9\n2015-03-21 05:32:53,4\n2015-03-21 05:37:53,6\n2015-03-21 05:42:53,6\n2015-03-21 05:47:53,12\n2015-03-21 05:52:53,10\n2015-03-21 05:57:53,9\n2015-03-21 06:02:53,18\n2015-03-21 06:07:53,5\n2015-03-21 06:12:53,9\n2015-03-21 06:17:53,17\n2015-03-21 06:22:53,16\n2015-03-21 06:27:53,17\n2015-03-21 06:32:53,12\n2015-03-21 06:37:53,5\n2015-03-21 06:42:53,12\n2015-03-21 06:47:53,8\n2015-03-21 06:52:53,12\n2015-03-21 06:57:53,17\n2015-03-21 07:02:53,7\n2015-03-21 07:07:53,19\n2015-03-21 07:12:53,13\n2015-03-21 07:17:53,11\n2015-03-21 07:22:53,14\n2015-03-21 07:27:53,28\n2015-03-21 07:32:53,9\n2015-03-21 07:37:53,4\n2015-03-21 07:42:53,12\n2015-03-21 07:47:53,13\n2015-03-21 07:52:53,12\n2015-03-21 07:57:53,6\n2015-03-21 08:02:53,10\n2015-03-21 08:07:53,14\n2015-03-21 08:12:53,19\n2015-03-21 08:17:53,11\n2015-03-21 08:22:53,14\n2015-03-21 08:27:53,16\n2015-03-21 08:32:53,20\n2015-03-21 08:37:53,22\n2015-03-21 08:42:53,20\n2015-03-21 08:47:53,10\n2015-03-21 08:52:53,18\n2015-03-21 08:57:53,18\n2015-03-21 09:02:53,15\n2015-03-21 09:07:53,15\n2015-03-21 09:12:53,10\n2015-03-21 09:17:53,13\n2015-03-21 09:22:53,5\n2015-03-21 09:27:53,11\n2015-03-21 09:32:53,7\n2015-03-21 09:37:53,13\n2015-03-21 09:42:53,10\n2015-03-21 09:47:53,5\n2015-03-21 09:52:53,10\n2015-03-21 09:57:53,13\n2015-03-21 10:02:53,9\n2015-03-21 10:07:53,9\n2015-03-21 10:12:53,22\n2015-03-21 10:17:53,14\n2015-03-21 10:22:53,4\n2015-03-21 10:27:53,9\n2015-03-21 10:32:53,8\n2015-03-21 10:37:53,4\n2015-03-21 10:42:53,3\n2015-03-21 10:47:53,3\n2015-03-21 10:52:53,5\n2015-03-21 10:57:53,16\n2015-03-21 11:02:53,8\n2015-03-21 11:07:53,12\n2015-03-21 11:12:53,7\n2015-03-21 11:17:53,7\n2015-03-21 11:22:53,4\n2015-03-21 11:27:53,5\n2015-03-21 11:32:53,14\n2015-03-21 11:37:53,6\n2015-03-21 11:42:53,20\n2015-03-21 11:47:53,9\n2015-03-21 11:52:53,9\n2015-03-21 11:57:53,16\n2015-03-21 12:02:53,10\n2015-03-21 12:07:53,9\n2015-03-21 12:12:53,13\n2015-03-21 12:17:53,11\n2015-03-21 12:22:53,16\n2015-03-21 12:27:53,11\n2015-03-21 12:32:53,9\n2015-03-21 12:37:53,13\n2015-03-21 12:42:53,17\n2015-03-21 12:47:53,11\n2015-03-21 12:52:53,1\n2015-03-21 12:57:53,11\n2015-03-21 13:02:53,14\n2015-03-21 13:07:53,5\n2015-03-21 13:12:53,12\n2015-03-21 13:17:53,11\n2015-03-21 13:22:53,5\n2015-03-21 13:27:53,15\n2015-03-21 13:32:53,21\n2015-03-21 13:37:53,9\n2015-03-21 13:42:53,15\n2015-03-21 13:47:53,15\n2015-03-21 13:52:53,13\n2015-03-21 13:57:53,10\n2015-03-21 14:02:53,15\n2015-03-21 14:07:53,12\n2015-03-21 14:12:53,11\n2015-03-21 14:17:53,14\n2015-03-21 14:22:53,10\n2015-03-21 14:27:53,5\n2015-03-21 14:32:53,13\n2015-03-21 14:37:53,14\n2015-03-21 14:42:53,7\n2015-03-21 14:47:53,17\n2015-03-21 14:52:53,20\n2015-03-21 14:57:53,23\n2015-03-21 15:02:53,16\n2015-03-21 15:07:53,21\n2015-03-21 15:12:53,24\n2015-03-21 15:17:53,11\n2015-03-21 15:22:53,18\n2015-03-21 15:27:53,17\n2015-03-21 15:32:53,7\n2015-03-21 15:37:53,19\n2015-03-21 15:42:53,17\n2015-03-21 15:47:53,17\n2015-03-21 15:52:53,5\n2015-03-21 15:57:53,13\n2015-03-21 16:02:53,17\n2015-03-21 16:07:53,24\n2015-03-21 16:12:53,11\n2015-03-21 16:17:53,11\n2015-03-21 16:22:53,11\n2015-03-21 16:27:53,10\n2015-03-21 16:32:53,16\n2015-03-21 16:37:53,16\n2015-03-21 16:42:53,26\n2015-03-21 16:47:53,24\n2015-03-21 16:52:53,12\n2015-03-21 16:57:53,13\n2015-03-21 17:02:53,18\n2015-03-21 17:07:53,8\n2015-03-21 17:12:53,12\n2015-03-21 17:17:53,5\n2015-03-21 17:22:53,19\n2015-03-21 17:27:53,14\n2015-03-21 17:32:53,17\n2015-03-21 17:37:53,16\n2015-03-21 17:42:53,24\n2015-03-21 17:47:53,21\n2015-03-21 17:52:53,9\n2015-03-21 17:57:53,22\n2015-03-21 18:02:53,10\n2015-03-21 18:07:53,9\n2015-03-21 18:12:53,15\n2015-03-21 18:17:53,8\n2015-03-21 18:22:53,14\n2015-03-21 18:27:53,9\n2015-03-21 18:32:53,10\n2015-03-21 18:37:53,15\n2015-03-21 18:42:53,11\n2015-03-21 18:47:53,20\n2015-03-21 18:52:53,13\n2015-03-21 18:57:53,26\n2015-03-21 19:02:53,19\n2015-03-21 19:07:53,16\n2015-03-21 19:12:53,10\n2015-03-21 19:17:53,15\n2015-03-21 19:22:53,9\n2015-03-21 19:27:53,11\n2015-03-21 19:32:53,15\n2015-03-21 19:37:53,20\n2015-03-21 19:42:53,26\n2015-03-21 19:47:53,15\n2015-03-21 19:52:53,17\n2015-03-21 19:57:53,20\n2015-03-21 20:02:53,9\n2015-03-21 20:07:53,9\n2015-03-21 20:12:53,22\n2015-03-21 20:17:53,13\n2015-03-21 20:22:53,10\n2015-03-21 20:27:53,14\n2015-03-21 20:32:53,11\n2015-03-21 20:37:53,17\n2015-03-21 20:42:53,9\n2015-03-21 20:47:53,11\n2015-03-21 20:52:53,18\n2015-03-21 20:57:53,15\n2015-03-21 21:02:53,6\n2015-03-21 21:07:53,11\n2015-03-21 21:12:53,3\n2015-03-21 21:17:53,7\n2015-03-21 21:22:53,13\n2015-03-21 21:27:53,15\n2015-03-21 21:32:53,8\n2015-03-21 21:37:53,10\n2015-03-21 21:42:53,20\n2015-03-21 21:47:53,12\n2015-03-21 21:52:53,17\n2015-03-21 21:57:53,14\n2015-03-21 22:02:53,14\n2015-03-21 22:07:53,3\n2015-03-21 22:12:53,14\n2015-03-21 22:17:53,1\n2015-03-21 22:22:53,9\n2015-03-21 22:27:53,15\n2015-03-21 22:32:53,10\n2015-03-21 22:37:53,4\n2015-03-21 22:42:53,9\n2015-03-21 22:47:53,12\n2015-03-21 22:52:53,11\n2015-03-21 22:57:53,17\n2015-03-21 23:02:53,14\n2015-03-21 23:07:53,9\n2015-03-21 23:12:53,12\n2015-03-21 23:17:53,12\n2015-03-21 23:22:53,6\n2015-03-21 23:27:53,4\n2015-03-21 23:32:53,13\n2015-03-21 23:37:53,10\n2015-03-21 23:42:53,9\n2015-03-21 23:47:53,20\n2015-03-21 23:52:53,9\n2015-03-21 23:57:53,14\n2015-03-22 00:02:53,15\n2015-03-22 00:07:53,14\n2015-03-22 00:12:53,2\n2015-03-22 00:17:53,8\n2015-03-22 00:22:53,9\n2015-03-22 00:27:53,8\n2015-03-22 00:32:53,7\n2015-03-22 00:37:53,7\n2015-03-22 00:42:53,7\n2015-03-22 00:47:53,15\n2015-03-22 00:52:53,8\n2015-03-22 00:57:53,6\n2015-03-22 01:02:53,6\n2015-03-22 01:07:53,5\n2015-03-22 01:12:53,7\n2015-03-22 01:17:53,8\n2015-03-22 01:22:53,10\n2015-03-22 01:27:53,15\n2015-03-22 01:32:53,10\n2015-03-22 01:37:53,7\n2015-03-22 01:42:53,4\n2015-03-22 01:47:53,7\n2015-03-22 01:52:53,7\n2015-03-22 01:57:53,16\n2015-03-22 02:02:53,3\n2015-03-22 02:07:53,5\n2015-03-22 02:12:53,5\n2015-03-22 02:17:53,5\n2015-03-22 02:22:53,6\n2015-03-22 02:27:53,11\n2015-03-22 02:32:53,8\n2015-03-22 02:37:53,2\n2015-03-22 02:42:53,5\n2015-03-22 02:47:53,4\n2015-03-22 02:52:53,12\n2015-03-22 02:57:53,5\n2015-03-22 03:02:53,17\n2015-03-22 03:07:53,3\n2015-03-22 03:12:53,4\n2015-03-22 03:17:53,5\n2015-03-22 03:22:53,8\n2015-03-22 03:27:53,15\n2015-03-22 03:32:53,7\n2015-03-22 03:37:53,4\n2015-03-22 03:42:53,14\n2015-03-22 03:47:53,3\n2015-03-22 03:52:53,3\n2015-03-22 03:57:53,3\n2015-03-22 04:02:53,6\n2015-03-22 04:07:53,1\n2015-03-22 04:12:53,1\n2015-03-22 04:17:53,10\n2015-03-22 04:22:53,3\n2015-03-22 04:27:53,6\n2015-03-22 04:32:53,3\n2015-03-22 04:37:53,3\n2015-03-22 04:42:53,7\n2015-03-22 04:47:53,10\n2015-03-22 04:52:53,11\n2015-03-22 04:57:53,4\n2015-03-22 05:02:53,2\n2015-03-22 05:07:53,4\n2015-03-22 05:12:53,3\n2015-03-22 05:17:53,3\n2015-03-22 05:22:53,8\n2015-03-22 05:27:53,2\n2015-03-22 05:32:53,4\n2015-03-22 05:37:53,7\n2015-03-22 05:42:53,7\n2015-03-22 05:47:53,3\n2015-03-22 05:52:53,3\n2015-03-22 05:57:53,13\n2015-03-22 06:02:53,7\n2015-03-22 06:07:53,16\n2015-03-22 06:12:53,5\n2015-03-22 06:17:53,7\n2015-03-22 06:22:53,5\n2015-03-22 06:27:53,4\n2015-03-22 06:32:53,6\n2015-03-22 06:37:53,4\n2015-03-22 06:42:53,5\n2015-03-22 06:47:53,6\n2015-03-22 06:52:53,1\n2015-03-22 06:57:53,4\n2015-03-22 07:02:53,7\n2015-03-22 07:07:53,5\n2015-03-22 07:12:53,5\n2015-03-22 07:17:53,2\n2015-03-22 07:22:53,3\n2015-03-22 07:27:53,1\n2015-03-22 07:32:53,0\n2015-03-22 07:37:53,9\n2015-03-22 07:42:53,10\n2015-03-22 07:47:53,11\n2015-03-22 07:52:53,8\n2015-03-22 07:57:53,7\n2015-03-22 08:02:53,7\n2015-03-22 08:07:53,9\n2015-03-22 08:12:53,11\n2015-03-22 08:17:53,2\n2015-03-22 08:22:53,14\n2015-03-22 08:27:53,6\n2015-03-22 08:32:53,4\n2015-03-22 08:37:53,6\n2015-03-22 08:42:53,6\n2015-03-22 08:47:53,6\n2015-03-22 08:52:53,6\n2015-03-22 08:57:53,18\n2015-03-22 09:02:53,2\n2015-03-22 09:07:53,6\n2015-03-22 09:12:53,6\n2015-03-22 09:17:53,8\n2015-03-22 09:22:53,10\n2015-03-22 09:27:53,8\n2015-03-22 09:32:53,8\n2015-03-22 09:37:53,2\n2015-03-22 09:42:53,8\n2015-03-22 09:47:53,10\n2015-03-22 09:52:53,4\n2015-03-22 09:57:53,6\n2015-03-22 10:02:53,11\n2015-03-22 10:07:53,5\n2015-03-22 10:12:53,2\n2015-03-22 10:17:53,6\n2015-03-22 10:22:53,4\n2015-03-22 10:27:53,5\n2015-03-22 10:32:53,2\n2015-03-22 10:37:53,0\n2015-03-22 10:42:53,8\n2015-03-22 10:47:53,6\n2015-03-22 10:52:53,13\n2015-03-22 10:57:53,7\n2015-03-22 11:02:53,7\n2015-03-22 11:07:53,20\n2015-03-22 11:12:53,15\n2015-03-22 11:17:53,33\n2015-03-22 11:22:53,49\n2015-03-22 11:27:53,25\n2015-03-22 11:32:53,6\n2015-03-22 11:37:53,5\n2015-03-22 11:42:53,2\n2015-03-22 11:47:53,8\n2015-03-22 11:52:53,7\n2015-03-22 11:57:53,4\n2015-03-22 12:02:53,5\n2015-03-22 12:07:53,4\n2015-03-22 12:12:53,2\n2015-03-22 12:17:53,15\n2015-03-22 12:22:53,47\n2015-03-22 12:27:53,6\n2015-03-22 12:32:53,7\n2015-03-22 12:37:53,3\n2015-03-22 12:42:53,14\n2015-03-22 12:47:53,6\n2015-03-22 12:52:53,7\n2015-03-22 12:57:53,10\n2015-03-22 13:02:53,5\n2015-03-22 13:07:53,13\n2015-03-22 13:12:53,9\n2015-03-22 13:17:53,5\n2015-03-22 13:22:53,6\n2015-03-22 13:27:53,5\n2015-03-22 13:32:53,2\n2015-03-22 13:37:53,51\n2015-03-22 13:42:53,10\n2015-03-22 13:47:53,7\n2015-03-22 13:52:53,7\n2015-03-22 13:57:53,7\n2015-03-22 14:02:53,14\n2015-03-22 14:07:53,10\n2015-03-22 14:12:53,10\n2015-03-22 14:17:53,23\n2015-03-22 14:22:53,13\n2015-03-22 14:27:53,19\n2015-03-22 14:32:53,5\n2015-03-22 14:37:53,20\n2015-03-22 14:42:53,10\n2015-03-22 14:47:53,9\n2015-03-22 14:52:53,9\n2015-03-22 14:57:53,12\n2015-03-22 15:02:53,7\n2015-03-22 15:07:53,19\n2015-03-22 15:12:53,12\n2015-03-22 15:17:53,8\n2015-03-22 15:22:53,8\n2015-03-22 15:27:53,38\n2015-03-22 15:32:53,21\n2015-03-22 15:37:53,8\n2015-03-22 15:42:53,14\n2015-03-22 15:47:53,20\n2015-03-22 15:52:53,11\n2015-03-22 15:57:53,9\n2015-03-22 16:02:53,17\n2015-03-22 16:07:53,9\n2015-03-22 16:12:53,9\n2015-03-22 16:17:53,20\n2015-03-22 16:22:53,16\n2015-03-22 16:27:53,15\n2015-03-22 16:32:53,17\n2015-03-22 16:37:53,17\n2015-03-22 16:42:53,12\n2015-03-22 16:47:53,9\n2015-03-22 16:52:53,8\n2015-03-22 16:57:53,15\n2015-03-22 17:02:53,11\n2015-03-22 17:07:53,13\n2015-03-22 17:12:53,13\n2015-03-22 17:17:53,14\n2015-03-22 17:22:53,15\n2015-03-22 17:27:53,14\n2015-03-22 17:32:53,21\n2015-03-22 17:37:53,9\n2015-03-22 17:42:53,10\n2015-03-22 17:47:53,14\n2015-03-22 17:52:53,4\n2015-03-22 17:57:53,13\n2015-03-22 18:02:53,14\n2015-03-22 18:07:53,12\n2015-03-22 18:12:53,15\n2015-03-22 18:17:53,7\n2015-03-22 18:22:53,8\n2015-03-22 18:27:53,12\n2015-03-22 18:32:53,11\n2015-03-22 18:37:53,15\n2015-03-22 18:42:53,9\n2015-03-22 18:47:53,14\n2015-03-22 18:52:53,7\n2015-03-22 18:57:53,14\n2015-03-22 19:02:53,12\n2015-03-22 19:07:53,8\n2015-03-22 19:12:53,67\n2015-03-22 19:17:53,5\n2015-03-22 19:22:53,8\n2015-03-22 19:27:53,11\n2015-03-22 19:32:53,3\n2015-03-22 19:37:53,13\n2015-03-22 19:42:53,20\n2015-03-22 19:47:53,9\n2015-03-22 19:52:53,13\n2015-03-22 19:57:53,12\n2015-03-22 20:02:53,31\n2015-03-22 20:07:53,21\n2015-03-22 20:12:53,27\n2015-03-22 20:17:53,18\n2015-03-22 20:22:53,25\n2015-03-22 20:27:53,20\n2015-03-22 20:32:53,28\n2015-03-22 20:37:53,20\n2015-03-22 20:42:53,25\n2015-03-22 20:47:53,20\n2015-03-22 20:52:53,16\n2015-03-22 20:57:53,21\n2015-03-22 21:02:53,67\n2015-03-22 21:07:53,23\n2015-03-22 21:12:53,32\n2015-03-22 21:17:53,19\n2015-03-22 21:22:53,26\n2015-03-22 21:27:53,18\n2015-03-22 21:32:53,21\n2015-03-22 21:37:53,25\n2015-03-22 21:42:53,15\n2015-03-22 21:47:53,12\n2015-03-22 21:52:53,9\n2015-03-22 21:57:53,14\n2015-03-22 22:02:53,18\n2015-03-22 22:07:53,9\n2015-03-22 22:12:53,11\n2015-03-22 22:17:53,14\n2015-03-22 22:22:53,9\n2015-03-22 22:27:53,30\n2015-03-22 22:32:53,32\n2015-03-22 22:37:53,6\n2015-03-22 22:42:53,12\n2015-03-22 22:47:53,9\n2015-03-22 22:52:53,50\n2015-03-22 22:57:53,9\n2015-03-22 23:02:53,9\n2015-03-22 23:07:53,6\n2015-03-22 23:12:53,14\n2015-03-22 23:17:53,9\n2015-03-22 23:22:53,53\n2015-03-22 23:27:53,17\n2015-03-22 23:32:53,9\n2015-03-22 23:37:53,5\n2015-03-22 23:42:53,6\n2015-03-22 23:47:53,9\n2015-03-22 23:52:53,13\n2015-03-22 23:57:53,11\n2015-03-23 00:02:53,12\n2015-03-23 00:07:53,10\n2015-03-23 00:12:53,11\n2015-03-23 00:17:53,4\n2015-03-23 00:22:53,8\n2015-03-23 00:27:53,4\n2015-03-23 00:32:53,9\n2015-03-23 00:37:53,7\n2015-03-23 00:42:53,9\n2015-03-23 00:47:53,18\n2015-03-23 00:52:53,7\n2015-03-23 00:57:53,9\n2015-03-23 01:02:53,6\n2015-03-23 01:07:53,12\n2015-03-23 01:12:53,11\n2015-03-23 01:17:53,7\n2015-03-23 01:22:53,13\n2015-03-23 01:27:53,6\n2015-03-23 01:32:53,7\n2015-03-23 01:37:53,53\n2015-03-23 01:42:53,4\n2015-03-23 01:47:53,46\n2015-03-23 01:52:53,7\n2015-03-23 01:57:53,10\n2015-03-23 02:02:53,9\n2015-03-23 02:07:53,2\n2015-03-23 02:12:53,14\n2015-03-23 02:17:53,16\n2015-03-23 02:22:53,5\n2015-03-23 02:27:53,1\n2015-03-23 02:32:53,14\n2015-03-23 02:37:53,7\n2015-03-23 02:42:53,7\n2015-03-23 02:47:53,7\n2015-03-23 02:52:53,7\n2015-03-23 02:57:53,7\n2015-03-23 03:02:53,13\n2015-03-23 03:07:53,5\n2015-03-23 03:12:53,4\n2015-03-23 03:17:53,4\n2015-03-23 03:22:53,7\n2015-03-23 03:27:53,11\n2015-03-23 03:32:53,7\n2015-03-23 03:37:53,0\n2015-03-23 03:42:53,10\n2015-03-23 03:47:53,7\n2015-03-23 03:52:53,8\n2015-03-23 03:57:53,8\n2015-03-23 04:02:53,3\n2015-03-23 04:07:53,3\n2015-03-23 04:12:53,11\n2015-03-23 04:17:53,4\n2015-03-23 04:22:53,15\n2015-03-23 04:27:53,13\n2015-03-23 04:32:53,10\n2015-03-23 04:37:53,13\n2015-03-23 04:42:53,8\n2015-03-23 04:47:53,3\n2015-03-23 04:52:53,19\n2015-03-23 04:57:53,50\n2015-03-23 05:02:53,7\n2015-03-23 05:07:53,4\n2015-03-23 05:12:53,15\n2015-03-23 05:17:53,1\n2015-03-23 05:22:53,7\n2015-03-23 05:27:53,6\n2015-03-23 05:32:53,10\n2015-03-23 05:37:53,5\n2015-03-23 05:42:53,13\n2015-03-23 05:47:53,4\n2015-03-23 05:52:53,47\n2015-03-23 05:57:53,14\n2015-03-23 06:02:53,5\n2015-03-23 06:07:53,7\n2015-03-23 06:12:53,7\n2015-03-23 06:17:53,10\n2015-03-23 06:22:53,11\n2015-03-23 06:27:53,5\n2015-03-23 06:32:53,4\n2015-03-23 06:37:53,5\n2015-03-23 06:42:53,13\n2015-03-23 06:47:53,2\n2015-03-23 06:52:53,5\n2015-03-23 06:57:53,12\n2015-03-23 07:02:53,15\n2015-03-23 07:07:53,10\n2015-03-23 07:12:53,6\n2015-03-23 07:17:53,7\n2015-03-23 07:22:53,9\n2015-03-23 07:27:53,22\n2015-03-23 07:32:53,3\n2015-03-23 07:37:53,8\n2015-03-23 07:42:53,8\n2015-03-23 07:47:53,11\n2015-03-23 07:52:53,11\n2015-03-23 07:57:53,12\n2015-03-23 08:02:53,9\n2015-03-23 08:07:53,10\n2015-03-23 08:12:53,10\n2015-03-23 08:17:53,16\n2015-03-23 08:22:53,8\n2015-03-23 08:27:53,10\n2015-03-23 08:32:53,4\n2015-03-23 08:37:53,8\n2015-03-23 08:42:53,14\n2015-03-23 08:47:53,8\n2015-03-23 08:52:53,20\n2015-03-23 08:57:53,16\n2015-03-23 09:02:53,12\n2015-03-23 09:07:53,14\n2015-03-23 09:12:53,52\n2015-03-23 09:17:53,21\n2015-03-23 09:22:53,7\n2015-03-23 09:27:53,10\n2015-03-23 09:32:53,10\n2015-03-23 09:37:53,15\n2015-03-23 09:42:53,50\n2015-03-23 09:47:53,14\n2015-03-23 09:52:53,20\n2015-03-23 09:57:53,21\n2015-03-23 10:02:53,17\n2015-03-23 10:07:53,26\n2015-03-23 10:12:53,10\n2015-03-23 10:17:53,20\n2015-03-23 10:22:53,21\n2015-03-23 10:27:53,12\n2015-03-23 10:32:53,16\n2015-03-23 10:37:53,8\n2015-03-23 10:42:53,13\n2015-03-23 10:47:53,14\n2015-03-23 10:52:53,15\n2015-03-23 10:57:53,13\n2015-03-23 11:02:53,17\n2015-03-23 11:07:53,22\n2015-03-23 11:12:53,21\n2015-03-23 11:17:53,18\n2015-03-23 11:22:53,18\n2015-03-23 11:27:53,16\n2015-03-23 11:32:53,13\n2015-03-23 11:37:53,13\n2015-03-23 11:42:53,8\n2015-03-23 11:47:53,8\n2015-03-23 11:52:53,16\n2015-03-23 11:57:53,66\n2015-03-23 12:02:53,18\n2015-03-23 12:07:53,17\n2015-03-23 12:12:53,10\n2015-03-23 12:17:53,14\n2015-03-23 12:22:53,10\n2015-03-23 12:27:53,19\n2015-03-23 12:32:53,15\n2015-03-23 12:37:53,13\n2015-03-23 12:42:53,11\n2015-03-23 12:47:53,15\n2015-03-23 12:52:53,9\n2015-03-23 12:57:53,20\n2015-03-23 13:02:53,35\n2015-03-23 13:07:53,29\n2015-03-23 13:12:53,14\n2015-03-23 13:17:53,18\n2015-03-23 13:22:53,28\n2015-03-23 13:27:53,40\n2015-03-23 13:32:53,22\n2015-03-23 13:37:53,13\n2015-03-23 13:42:53,24\n2015-03-23 13:47:53,21\n2015-03-23 13:52:53,22\n2015-03-23 13:57:53,24\n2015-03-23 14:02:53,29\n2015-03-23 14:07:53,26\n2015-03-23 14:12:53,25\n2015-03-23 14:17:53,37\n2015-03-23 14:22:53,16\n2015-03-23 14:27:53,29\n2015-03-23 14:32:53,24\n2015-03-23 14:37:53,41\n2015-03-23 14:42:53,32\n2015-03-23 14:47:53,21\n2015-03-23 14:52:53,30\n2015-03-23 14:57:53,32\n2015-03-23 15:02:53,76\n2015-03-23 15:07:53,32\n2015-03-23 15:12:53,27\n2015-03-23 15:17:53,25\n2015-03-23 15:22:53,21\n2015-03-23 15:27:53,42\n2015-03-23 15:32:53,27\n2015-03-23 15:37:53,66\n2015-03-23 15:42:53,28\n2015-03-23 15:47:53,29\n2015-03-23 15:52:53,25\n2015-03-23 15:57:53,51\n2015-03-23 16:02:53,28\n2015-03-23 16:07:53,34\n2015-03-23 16:12:53,20\n2015-03-23 16:17:53,14\n2015-03-23 16:22:53,31\n2015-03-23 16:27:53,28\n2015-03-23 16:32:53,28\n2015-03-23 16:37:53,27\n2015-03-23 16:42:53,21\n2015-03-23 16:47:53,29\n2015-03-23 16:52:53,25\n2015-03-23 16:57:53,37\n2015-03-23 17:02:53,17\n2015-03-23 17:07:53,27\n2015-03-23 17:12:53,26\n2015-03-23 17:17:53,31\n2015-03-23 17:22:53,25\n2015-03-23 17:27:53,25\n2015-03-23 17:32:53,22\n2015-03-23 17:37:53,32\n2015-03-23 17:42:53,20\n2015-03-23 17:47:53,55\n2015-03-23 17:52:53,27\n2015-03-23 17:57:53,36\n2015-03-23 18:02:53,25\n2015-03-23 18:07:53,19\n2015-03-23 18:12:53,85\n2015-03-23 18:17:53,65\n2015-03-23 18:22:53,37\n2015-03-23 18:27:53,38\n2015-03-23 18:32:53,47\n2015-03-23 18:37:53,34\n2015-03-23 18:42:53,28\n2015-03-23 18:47:53,33\n2015-03-23 18:52:53,30\n2015-03-23 18:57:53,30\n2015-03-23 19:02:53,46\n2015-03-23 19:07:53,31\n2015-03-23 19:12:53,22\n2015-03-23 19:17:53,36\n2015-03-23 19:22:53,28\n2015-03-23 19:27:53,17\n2015-03-23 19:32:53,41\n2015-03-23 19:37:53,15\n2015-03-23 19:42:53,19\n2015-03-23 19:47:53,16\n2015-03-23 19:52:53,30\n2015-03-23 19:57:53,29\n2015-03-23 20:02:53,29\n2015-03-23 20:07:53,59\n2015-03-23 20:12:53,21\n2015-03-23 20:17:53,30\n2015-03-23 20:22:53,23\n2015-03-23 20:27:53,23\n2015-03-23 20:32:53,25\n2015-03-23 20:37:53,29\n2015-03-23 20:42:53,17\n2015-03-23 20:47:53,18\n2015-03-23 20:52:53,12\n2015-03-23 20:57:53,35\n2015-03-23 21:02:53,19\n2015-03-23 21:07:53,16\n2015-03-23 21:12:53,16\n2015-03-23 21:17:53,24\n2015-03-23 21:22:53,18\n2015-03-23 21:27:53,13\n2015-03-23 21:32:53,16\n2015-03-23 21:37:53,25\n2015-03-23 21:42:53,29\n2015-03-23 21:47:53,28\n2015-03-23 21:52:53,32\n2015-03-23 21:57:53,26\n2015-03-23 22:02:53,19\n2015-03-23 22:07:53,25\n2015-03-23 22:12:53,11\n2015-03-23 22:17:53,16\n2015-03-23 22:22:53,12\n2015-03-23 22:27:53,14\n2015-03-23 22:32:53,16\n2015-03-23 22:37:53,19\n2015-03-23 22:42:53,56\n2015-03-23 22:47:53,26\n2015-03-23 22:52:53,15\n2015-03-23 22:57:53,24\n2015-03-23 23:02:53,28\n2015-03-23 23:07:53,24\n2015-03-23 23:12:53,23\n2015-03-23 23:17:53,26\n2015-03-23 23:22:53,22\n2015-03-23 23:27:53,28\n2015-03-23 23:32:53,16\n2015-03-23 23:37:53,19\n2015-03-23 23:42:53,12\n2015-03-23 23:47:53,17\n2015-03-23 23:52:53,16\n2015-03-23 23:57:53,16\n2015-03-24 00:02:53,25\n2015-03-24 00:07:53,13\n2015-03-24 00:12:53,22\n2015-03-24 00:17:53,13\n2015-03-24 00:22:53,14\n2015-03-24 00:27:53,11\n2015-03-24 00:32:53,12\n2015-03-24 00:37:53,17\n2015-03-24 00:42:53,9\n2015-03-24 00:47:53,142\n2015-03-24 00:52:53,85\n2015-03-24 00:57:53,26\n2015-03-24 01:02:53,19\n2015-03-24 01:07:53,11\n2015-03-24 01:12:53,50\n2015-03-24 01:17:53,14\n2015-03-24 01:22:53,22\n2015-03-24 01:27:53,7\n2015-03-24 01:32:53,7\n2015-03-24 01:37:53,7\n2015-03-24 01:42:53,12\n2015-03-24 01:47:53,17\n2015-03-24 01:52:53,7\n2015-03-24 01:57:53,15\n2015-03-24 02:02:53,50\n2015-03-24 02:07:53,28\n2015-03-24 02:12:53,5\n2015-03-24 02:17:53,10\n2015-03-24 02:22:53,4\n2015-03-24 02:27:53,11\n2015-03-24 02:32:53,7\n2015-03-24 02:37:53,12\n2015-03-24 02:42:53,16\n2015-03-24 02:47:53,10\n2015-03-24 02:52:53,5\n2015-03-24 02:57:53,7\n2015-03-24 03:02:53,11\n2015-03-24 03:07:53,7\n2015-03-24 03:12:53,19\n2015-03-24 03:17:53,20\n2015-03-24 03:22:53,51\n2015-03-24 03:27:53,4\n2015-03-24 03:32:53,5\n2015-03-24 03:37:53,16\n2015-03-24 03:42:53,13\n2015-03-24 03:47:53,12\n2015-03-24 03:52:53,22\n2015-03-24 03:57:53,16\n2015-03-24 04:02:53,10\n2015-03-24 04:07:53,11\n2015-03-24 04:12:53,13\n2015-03-24 04:17:53,17\n2015-03-24 04:22:53,6\n2015-03-24 04:27:53,11\n2015-03-24 04:32:53,11\n2015-03-24 04:37:53,6\n2015-03-24 04:42:53,7\n2015-03-24 04:47:53,15\n2015-03-24 04:52:53,6\n2015-03-24 04:57:53,15\n2015-03-24 05:02:53,12\n2015-03-24 05:07:53,3\n2015-03-24 05:12:53,50\n2015-03-24 05:17:53,8\n2015-03-24 05:22:53,14\n2015-03-24 05:27:53,7\n2015-03-24 05:32:53,44\n2015-03-24 05:37:53,3\n2015-03-24 05:42:53,1\n2015-03-24 05:47:53,6\n2015-03-24 05:52:53,10\n2015-03-24 05:57:53,12\n2015-03-24 06:02:53,22\n2015-03-24 06:07:53,6\n2015-03-24 06:12:53,6\n2015-03-24 06:17:53,7\n2015-03-24 06:22:53,9\n2015-03-24 06:27:53,11\n2015-03-24 06:32:53,11\n2015-03-24 06:37:53,6\n2015-03-24 06:42:53,4\n2015-03-24 06:47:53,11\n2015-03-24 06:52:53,2\n2015-03-24 06:57:53,12\n2015-03-24 07:02:53,6\n2015-03-24 07:07:53,10\n2015-03-24 07:12:53,4\n2015-03-24 07:17:53,15\n2015-03-24 07:22:53,18\n2015-03-24 07:27:53,9\n2015-03-24 07:32:53,13\n2015-03-24 07:37:53,12\n2015-03-24 07:42:53,10\n2015-03-24 07:47:53,12\n2015-03-24 07:52:53,6\n2015-03-24 07:57:53,51\n2015-03-24 08:02:53,10\n2015-03-24 08:07:53,10\n2015-03-24 08:12:53,13\n2015-03-24 08:17:53,27\n2015-03-24 08:22:53,13\n2015-03-24 08:27:53,13\n2015-03-24 08:32:53,14\n2015-03-24 08:37:53,12\n2015-03-24 08:42:53,4\n2015-03-24 08:47:53,49\n2015-03-24 08:52:53,14\n2015-03-24 08:57:53,20\n2015-03-24 09:02:53,14\n2015-03-24 09:07:53,18\n2015-03-24 09:12:53,12\n2015-03-24 09:17:53,9\n2015-03-24 09:22:53,14\n2015-03-24 09:27:53,7\n2015-03-24 09:32:53,14\n2015-03-24 09:37:53,13\n2015-03-24 09:42:53,15\n2015-03-24 09:47:53,19\n2015-03-24 09:52:53,12\n2015-03-24 09:57:53,12\n2015-03-24 10:02:53,22\n2015-03-24 10:07:53,19\n2015-03-24 10:12:53,10\n2015-03-24 10:17:53,20\n2015-03-24 10:22:53,17\n2015-03-24 10:27:53,10\n2015-03-24 10:32:53,9\n2015-03-24 10:37:53,15\n2015-03-24 10:42:53,17\n2015-03-24 10:47:53,17\n2015-03-24 10:52:53,11\n2015-03-24 10:57:53,14\n2015-03-24 11:02:53,19\n2015-03-24 11:07:53,17\n2015-03-24 11:12:53,12\n2015-03-24 11:17:53,4\n2015-03-24 11:22:53,10\n2015-03-24 11:27:53,17\n2015-03-24 11:32:53,23\n2015-03-24 11:37:53,16\n2015-03-24 11:42:53,25\n2015-03-24 11:47:53,7\n2015-03-24 11:52:53,25\n2015-03-24 11:57:53,24\n2015-03-24 12:02:53,16\n2015-03-24 12:07:53,20\n2015-03-24 12:12:53,10\n2015-03-24 12:17:53,18\n2015-03-24 12:22:53,52\n2015-03-24 12:27:53,22\n2015-03-24 12:32:53,10\n2015-03-24 12:37:53,8\n2015-03-24 12:42:53,13\n2015-03-24 12:47:53,18\n2015-03-24 12:52:53,64\n2015-03-24 12:57:53,94\n2015-03-24 13:02:53,77\n2015-03-24 13:07:53,65\n2015-03-24 13:12:53,61\n2015-03-24 13:17:53,82\n2015-03-24 13:22:53,34\n2015-03-24 13:27:53,31\n2015-03-24 13:32:53,31\n2015-03-24 13:37:53,18\n2015-03-24 13:42:53,28\n2015-03-24 13:47:53,24\n2015-03-24 13:52:53,20\n2015-03-24 13:57:53,37\n2015-03-24 14:02:53,24\n2015-03-24 14:07:53,27\n2015-03-24 14:12:53,23\n2015-03-24 14:17:53,36\n2015-03-24 14:22:53,15\n2015-03-24 14:27:53,39\n2015-03-24 14:32:53,27\n2015-03-24 14:37:53,33\n2015-03-24 14:42:53,28\n2015-03-24 14:47:53,24\n2015-03-24 14:52:53,36\n2015-03-24 14:57:53,44\n2015-03-24 15:02:53,20\n2015-03-24 15:07:53,48\n2015-03-24 15:12:53,43\n2015-03-24 15:17:53,29\n2015-03-24 15:22:53,35\n2015-03-24 15:27:53,30\n2015-03-24 15:32:53,46\n2015-03-24 15:37:53,29\n2015-03-24 15:42:53,18\n2015-03-24 15:47:53,29\n2015-03-24 15:52:53,46\n2015-03-24 15:57:53,20\n2015-03-24 16:02:53,26\n2015-03-24 16:07:53,101\n2015-03-24 16:12:53,35\n2015-03-24 16:17:53,32\n2015-03-24 16:22:53,28\n2015-03-24 16:27:53,30\n2015-03-24 16:32:53,45\n2015-03-24 16:37:53,61\n2015-03-24 16:42:53,50\n2015-03-24 16:47:53,60\n2015-03-24 16:52:53,54\n2015-03-24 16:57:53,61\n2015-03-24 17:02:53,45\n2015-03-24 17:07:53,37\n2015-03-24 17:12:53,34\n2015-03-24 17:17:53,35\n2015-03-24 17:22:53,23\n2015-03-24 17:27:53,39\n2015-03-24 17:32:53,38\n2015-03-24 17:37:53,67\n2015-03-24 17:42:53,47\n2015-03-24 17:47:53,41\n2015-03-24 17:52:53,41\n2015-03-24 17:57:53,49\n2015-03-24 18:02:53,51\n2015-03-24 18:07:53,18\n2015-03-24 18:12:53,39\n2015-03-24 18:17:53,22\n2015-03-24 18:22:53,31\n2015-03-24 18:27:53,21\n2015-03-24 18:32:53,35\n2015-03-24 18:37:53,28\n2015-03-24 18:42:53,35\n2015-03-24 18:47:53,75\n2015-03-24 18:52:53,79\n2015-03-24 18:57:53,65\n2015-03-24 19:02:53,51\n2015-03-24 19:07:53,41\n2015-03-24 19:12:53,49\n2015-03-24 19:17:53,28\n2015-03-24 19:22:53,41\n2015-03-24 19:27:53,31\n2015-03-24 19:32:53,34\n2015-03-24 19:37:53,26\n2015-03-24 19:42:53,35\n2015-03-24 19:47:53,33\n2015-03-24 19:52:53,26\n2015-03-24 19:57:53,33\n2015-03-24 20:02:53,40\n2015-03-24 20:07:53,32\n2015-03-24 20:12:53,22\n2015-03-24 20:17:53,31\n2015-03-24 20:22:53,31\n2015-03-24 20:27:53,31\n2015-03-24 20:32:53,21\n2015-03-24 20:37:53,30\n2015-03-24 20:42:53,17\n2015-03-24 20:47:53,22\n2015-03-24 20:52:53,16\n2015-03-24 20:57:53,20\n2015-03-24 21:02:53,21\n2015-03-24 21:07:53,23\n2015-03-24 21:12:53,32\n2015-03-24 21:17:53,25\n2015-03-24 21:22:53,64\n2015-03-24 21:27:53,28\n2015-03-24 21:32:53,27\n2015-03-24 21:37:53,17\n2015-03-24 21:42:53,16\n2015-03-24 21:47:53,27\n2015-03-24 21:52:53,18\n2015-03-24 21:57:53,26\n2015-03-24 22:02:53,19\n2015-03-24 22:07:53,15\n2015-03-24 22:12:53,29\n2015-03-24 22:17:53,23\n2015-03-24 22:22:53,22\n2015-03-24 22:27:53,21\n2015-03-24 22:32:53,14\n2015-03-24 22:37:53,11\n2015-03-24 22:42:53,12\n2015-03-24 22:47:53,17\n2015-03-24 22:52:53,12\n2015-03-24 22:57:53,28\n2015-03-24 23:02:53,20\n2015-03-24 23:07:53,31\n2015-03-24 23:12:53,15\n2015-03-24 23:17:53,24\n2015-03-24 23:22:53,24\n2015-03-24 23:27:53,56\n2015-03-24 23:32:53,26\n2015-03-24 23:37:53,11\n2015-03-24 23:42:53,23\n2015-03-24 23:47:53,25\n2015-03-24 23:52:53,53\n2015-03-24 23:57:53,34\n2015-03-25 00:02:53,29\n2015-03-25 00:07:53,19\n2015-03-25 00:12:53,22\n2015-03-25 00:17:53,7\n2015-03-25 00:22:53,19\n2015-03-25 00:27:53,16\n2015-03-25 00:32:53,25\n2015-03-25 00:37:53,14\n2015-03-25 00:42:53,13\n2015-03-25 00:47:53,19\n2015-03-25 00:52:53,25\n2015-03-25 00:57:53,16\n2015-03-25 01:02:53,20\n2015-03-25 01:07:53,9\n2015-03-25 01:12:53,15\n2015-03-25 01:17:53,28\n2015-03-25 01:22:53,13\n2015-03-25 01:27:53,15\n2015-03-25 01:32:53,9\n2015-03-25 01:37:53,12\n2015-03-25 01:42:53,5\n2015-03-25 01:47:53,14\n2015-03-25 01:52:53,13\n2015-03-25 01:57:53,19\n2015-03-25 02:02:53,14\n2015-03-25 02:07:53,18\n2015-03-25 02:12:53,10\n2015-03-25 02:17:53,12\n2015-03-25 02:22:53,56\n2015-03-25 02:27:53,64\n2015-03-25 02:32:53,25\n2015-03-25 02:37:53,26\n2015-03-25 02:42:53,69\n2015-03-25 02:47:53,13\n2015-03-25 02:52:53,17\n2015-03-25 02:57:53,11\n2015-03-25 03:02:53,13\n2015-03-25 03:07:53,27\n2015-03-25 03:12:53,16\n2015-03-25 03:17:53,22\n2015-03-25 03:22:53,23\n2015-03-25 03:27:53,14\n2015-03-25 03:32:53,15\n2015-03-25 03:37:53,20\n2015-03-25 03:42:53,16\n2015-03-25 03:47:53,22\n2015-03-25 03:52:53,12\n2015-03-25 03:57:53,13\n2015-03-25 04:02:53,12\n2015-03-25 04:07:53,11\n2015-03-25 04:12:53,11\n2015-03-25 04:17:53,10\n2015-03-25 04:22:53,9\n2015-03-25 04:27:53,49\n2015-03-25 04:32:53,6\n2015-03-25 04:37:53,4\n2015-03-25 04:42:53,1\n2015-03-25 04:47:53,5\n2015-03-25 04:52:53,8\n2015-03-25 04:57:53,11\n2015-03-25 05:02:53,7\n2015-03-25 05:07:53,6\n2015-03-25 05:12:53,12\n2015-03-25 05:17:53,11\n2015-03-25 05:22:53,8\n2015-03-25 05:27:53,12\n2015-03-25 05:32:53,24\n2015-03-25 05:37:53,15\n2015-03-25 05:42:53,11\n2015-03-25 05:47:53,16\n2015-03-25 05:52:53,6\n2015-03-25 05:57:53,55\n2015-03-25 06:02:53,12\n2015-03-25 06:07:53,21\n2015-03-25 06:12:53,6\n2015-03-25 06:17:53,14\n2015-03-25 06:22:53,9\n2015-03-25 06:27:53,8\n2015-03-25 06:32:53,12\n2015-03-25 06:37:53,50\n2015-03-25 06:42:53,11\n2015-03-25 06:47:53,10\n2015-03-25 06:52:53,10\n2015-03-25 06:57:53,27\n2015-03-25 07:02:53,11\n2015-03-25 07:07:53,8\n2015-03-25 07:12:53,10\n2015-03-25 07:17:53,10\n2015-03-25 07:22:53,36\n2015-03-25 07:27:53,10\n2015-03-25 07:32:53,5\n2015-03-25 07:37:53,6\n2015-03-25 07:42:53,13\n2015-03-25 07:47:53,15\n2015-03-25 07:52:53,14\n2015-03-25 07:57:53,7\n2015-03-25 08:02:53,17\n2015-03-25 08:07:53,10\n2015-03-25 08:12:53,7\n2015-03-25 08:17:53,11\n2015-03-25 08:22:53,9\n2015-03-25 08:27:53,11\n2015-03-25 08:32:53,7\n2015-03-25 08:37:53,7\n2015-03-25 08:42:53,11\n2015-03-25 08:47:53,17\n2015-03-25 08:52:53,18\n2015-03-25 08:57:53,14\n2015-03-25 09:02:53,15\n2015-03-25 09:07:53,46\n2015-03-25 09:12:53,16\n2015-03-25 09:17:53,6\n2015-03-25 09:22:53,55\n2015-03-25 09:27:53,110\n2015-03-25 09:32:53,15\n2015-03-25 09:37:53,12\n2015-03-25 09:42:53,9\n2015-03-25 09:47:53,29\n2015-03-25 09:52:53,25\n2015-03-25 09:57:53,27\n2015-03-25 10:02:53,10\n2015-03-25 10:07:53,13\n2015-03-25 10:12:53,12\n2015-03-25 10:17:53,12\n2015-03-25 10:22:53,12\n2015-03-25 10:27:53,10\n2015-03-25 10:32:53,22\n2015-03-25 10:37:53,11\n2015-03-25 10:42:53,24\n2015-03-25 10:47:53,12\n2015-03-25 10:52:53,15\n2015-03-25 10:57:53,22\n2015-03-25 11:02:53,15\n2015-03-25 11:07:53,14\n2015-03-25 11:12:53,10\n2015-03-25 11:17:53,14\n2015-03-25 11:22:53,10\n2015-03-25 11:27:53,43\n2015-03-25 11:32:53,38\n2015-03-25 11:37:53,45\n2015-03-25 11:42:53,56\n2015-03-25 11:47:53,52\n2015-03-25 11:52:53,19\n2015-03-25 11:57:53,51\n2015-03-25 12:02:53,49\n2015-03-25 12:07:53,28\n2015-03-25 12:12:53,30\n2015-03-25 12:17:53,33\n2015-03-25 12:22:53,19\n2015-03-25 12:27:53,26\n2015-03-25 12:32:53,24\n2015-03-25 12:37:53,14\n2015-03-25 12:42:53,27\n2015-03-25 12:47:53,22\n2015-03-25 12:52:53,23\n2015-03-25 12:57:53,28\n2015-03-25 13:02:53,56\n2015-03-25 13:07:53,26\n2015-03-25 13:12:53,20\n2015-03-25 13:17:53,15\n2015-03-25 13:22:53,24\n2015-03-25 13:27:53,32\n2015-03-25 13:32:53,30\n2015-03-25 13:37:53,33\n2015-03-25 13:42:53,25\n2015-03-25 13:47:53,21\n2015-03-25 13:52:53,29\n2015-03-25 13:57:53,30\n2015-03-25 14:02:53,18\n2015-03-25 14:07:53,17\n2015-03-25 14:12:53,17\n2015-03-25 14:17:53,19\n2015-03-25 14:22:53,25\n2015-03-25 14:27:53,20\n2015-03-25 14:32:53,56\n2015-03-25 14:37:53,21\n2015-03-25 14:42:53,34\n2015-03-25 14:47:53,43\n2015-03-25 14:52:53,53\n2015-03-25 14:57:53,42\n2015-03-25 15:02:53,47\n2015-03-25 15:07:53,19\n2015-03-25 15:12:53,32\n2015-03-25 15:17:53,30\n2015-03-25 15:22:53,27\n2015-03-25 15:27:53,38\n2015-03-25 15:32:53,30\n2015-03-25 15:37:53,51\n2015-03-25 15:42:53,35\n2015-03-25 15:47:53,30\n2015-03-25 15:52:53,31\n2015-03-25 15:57:53,47\n2015-03-25 16:02:53,36\n2015-03-25 16:07:53,32\n2015-03-25 16:12:53,39\n2015-03-25 16:17:53,26\n2015-03-25 16:22:53,25\n2015-03-25 16:27:53,34\n2015-03-25 16:32:53,34\n2015-03-25 16:37:53,31\n2015-03-25 16:42:53,34\n2015-03-25 16:47:53,24\n2015-03-25 16:52:53,64\n2015-03-25 16:57:53,28\n2015-03-25 17:02:53,48\n2015-03-25 17:07:53,25\n2015-03-25 17:12:53,69\n2015-03-25 17:17:53,29\n2015-03-25 17:22:53,32\n2015-03-25 17:27:53,40\n2015-03-25 17:32:53,22\n2015-03-25 17:37:53,17\n2015-03-25 17:42:53,27\n2015-03-25 17:47:53,29\n2015-03-25 17:52:53,27\n2015-03-25 17:57:53,40\n2015-03-25 18:02:53,32\n2015-03-25 18:07:53,21\n2015-03-25 18:12:53,34\n2015-03-25 18:17:53,35\n2015-03-25 18:22:53,34\n2015-03-25 18:27:53,52\n2015-03-25 18:32:53,79\n2015-03-25 18:37:53,45\n2015-03-25 18:42:53,46\n2015-03-25 18:47:53,32\n2015-03-25 18:52:53,54\n2015-03-25 18:57:53,35\n2015-03-25 19:02:53,79\n2015-03-25 19:07:53,27\n2015-03-25 19:12:53,27\n2015-03-25 19:17:53,49\n2015-03-25 19:22:53,28\n2015-03-25 19:27:53,30\n2015-03-25 19:32:53,18\n2015-03-25 19:37:53,34\n2015-03-25 19:42:53,80\n2015-03-25 19:47:53,38\n2015-03-25 19:52:53,120\n2015-03-25 19:57:53,51\n2015-03-25 20:02:53,40\n2015-03-25 20:07:53,39\n2015-03-25 20:12:53,35\n2015-03-25 20:17:53,35\n2015-03-25 20:22:53,44\n2015-03-25 20:27:53,83\n2015-03-25 20:32:53,36\n2015-03-25 20:37:53,31\n2015-03-25 20:42:53,20\n2015-03-25 20:47:53,66\n2015-03-25 20:52:53,28\n2015-03-25 20:57:53,52\n2015-03-25 21:02:53,38\n2015-03-25 21:07:53,34\n2015-03-25 21:12:53,34\n2015-03-25 21:17:53,56\n2015-03-25 21:22:53,56\n2015-03-25 21:27:53,41\n2015-03-25 21:32:53,30\n2015-03-25 21:37:53,44\n2015-03-25 21:42:53,41\n2015-03-25 21:47:53,33\n2015-03-25 21:52:53,25\n2015-03-25 21:57:53,49\n2015-03-25 22:02:53,31\n2015-03-25 22:07:53,22\n2015-03-25 22:12:53,23\n2015-03-25 22:17:53,14\n2015-03-25 22:22:53,47\n2015-03-25 22:27:53,59\n2015-03-25 22:32:53,18\n2015-03-25 22:37:53,33\n2015-03-25 22:42:53,13\n2015-03-25 22:47:53,16\n2015-03-25 22:52:53,26\n2015-03-25 22:57:53,37\n2015-03-25 23:02:53,28\n2015-03-25 23:07:53,25\n2015-03-25 23:12:53,31\n2015-03-25 23:17:53,20\n2015-03-25 23:22:53,18\n2015-03-25 23:27:53,25\n2015-03-25 23:32:53,26\n2015-03-25 23:37:53,34\n2015-03-25 23:42:53,28\n2015-03-25 23:47:53,23\n2015-03-25 23:52:53,17\n2015-03-25 23:57:53,25\n2015-03-26 00:02:53,56\n2015-03-26 00:07:53,29\n2015-03-26 00:12:53,32\n2015-03-26 00:17:53,20\n2015-03-26 00:22:53,12\n2015-03-26 00:27:53,19\n2015-03-26 00:32:53,26\n2015-03-26 00:37:53,39\n2015-03-26 00:42:53,24\n2015-03-26 00:47:53,25\n2015-03-26 00:52:53,56\n2015-03-26 00:57:53,23\n2015-03-26 01:02:53,22\n2015-03-26 01:07:53,23\n2015-03-26 01:12:53,20\n2015-03-26 01:17:53,20\n2015-03-26 01:22:53,28\n2015-03-26 01:27:53,22\n2015-03-26 01:32:53,7\n2015-03-26 01:37:53,19\n2015-03-26 01:42:53,15\n2015-03-26 01:47:53,13\n2015-03-26 01:52:53,12\n2015-03-26 01:57:53,21\n2015-03-26 02:02:53,17\n2015-03-26 02:07:53,14\n2015-03-26 02:12:53,48\n2015-03-26 02:17:53,64\n2015-03-26 02:22:53,25\n2015-03-26 02:27:53,17\n2015-03-26 02:32:53,19\n2015-03-26 02:37:53,24\n2015-03-26 02:42:53,17\n2015-03-26 02:47:53,35\n2015-03-26 02:52:53,23\n2015-03-26 02:57:53,18\n2015-03-26 03:02:53,26\n2015-03-26 03:07:53,50\n2015-03-26 03:12:53,34\n2015-03-26 03:17:53,64\n2015-03-26 03:22:53,32\n2015-03-26 03:27:53,32\n2015-03-26 03:32:53,21\n2015-03-26 03:37:53,21\n2015-03-26 03:42:53,8\n2015-03-26 03:47:53,17\n2015-03-26 03:52:53,11\n2015-03-26 03:57:53,17\n2015-03-26 04:02:53,22\n2015-03-26 04:07:53,12\n2015-03-26 04:12:53,8\n2015-03-26 04:17:53,13\n2015-03-26 04:22:53,12\n2015-03-26 04:27:53,15\n2015-03-26 04:32:53,8\n2015-03-26 04:37:53,14\n2015-03-26 04:42:53,12\n2015-03-26 04:47:53,10\n2015-03-26 04:52:53,8\n2015-03-26 04:57:53,13\n2015-03-26 05:02:53,15\n2015-03-26 05:07:53,10\n2015-03-26 05:12:53,6\n2015-03-26 05:17:53,12\n2015-03-26 05:22:53,28\n2015-03-26 05:27:53,15\n2015-03-26 05:32:53,13\n2015-03-26 05:37:53,14\n2015-03-26 05:42:53,8\n2015-03-26 05:47:53,9\n2015-03-26 05:52:53,20\n2015-03-26 05:57:53,4\n2015-03-26 06:02:53,12\n2015-03-26 06:07:53,4\n2015-03-26 06:12:53,6\n2015-03-26 06:17:53,15\n2015-03-26 06:22:53,14\n2015-03-26 06:27:53,14\n2015-03-26 06:32:53,44\n2015-03-26 06:37:53,13\n2015-03-26 06:42:53,6\n2015-03-26 06:47:53,15\n2015-03-26 06:52:53,14\n2015-03-26 06:57:53,16\n2015-03-26 07:02:53,7\n2015-03-26 07:07:53,5\n2015-03-26 07:12:53,12\n2015-03-26 07:17:53,27\n2015-03-26 07:22:53,20\n2015-03-26 07:27:53,16\n2015-03-26 07:32:53,18\n2015-03-26 07:37:53,10\n2015-03-26 07:42:53,50\n2015-03-26 07:47:53,11\n2015-03-26 07:52:53,12\n2015-03-26 07:57:53,12\n2015-03-26 08:02:53,13\n2015-03-26 08:07:53,31\n2015-03-26 08:12:53,28\n2015-03-26 08:17:53,19\n2015-03-26 08:22:53,22\n2015-03-26 08:27:53,14\n2015-03-26 08:32:53,29\n2015-03-26 08:37:53,8\n2015-03-26 08:42:53,16\n2015-03-26 08:47:53,14\n2015-03-26 08:52:53,11\n2015-03-26 08:57:53,15\n2015-03-26 09:02:53,16\n2015-03-26 09:07:53,10\n2015-03-26 09:12:53,16\n2015-03-26 09:17:53,14\n2015-03-26 09:22:53,13\n2015-03-26 09:27:53,19\n2015-03-26 09:32:53,8\n2015-03-26 09:37:53,13\n2015-03-26 09:42:53,10\n2015-03-26 09:47:53,13\n2015-03-26 09:52:53,27\n2015-03-26 09:57:53,37\n2015-03-26 10:02:53,28\n2015-03-26 10:07:53,20\n2015-03-26 10:12:53,27\n2015-03-26 10:17:53,47\n2015-03-26 10:22:53,23\n2015-03-26 10:27:53,21\n2015-03-26 10:32:53,20\n2015-03-26 10:37:53,18\n2015-03-26 10:42:53,20\n2015-03-26 10:47:53,25\n2015-03-26 10:52:53,16\n2015-03-26 10:57:53,17\n2015-03-26 11:02:53,18\n2015-03-26 11:07:53,17\n2015-03-26 11:12:53,13\n2015-03-26 11:17:53,17\n2015-03-26 11:22:53,10\n2015-03-26 11:27:53,26\n2015-03-26 11:32:53,13\n2015-03-26 11:37:53,22\n2015-03-26 11:42:53,28\n2015-03-26 11:47:53,34\n2015-03-26 11:52:53,37\n2015-03-26 11:57:53,20\n2015-03-26 12:02:53,16\n2015-03-26 12:07:53,20\n2015-03-26 12:12:53,25\n2015-03-26 12:17:53,32\n2015-03-26 12:22:53,19\n2015-03-26 12:27:53,33\n2015-03-26 12:32:53,20\n2015-03-26 12:37:53,11\n2015-03-26 12:42:53,18\n2015-03-26 12:47:53,31\n2015-03-26 12:52:53,23\n2015-03-26 12:57:53,26\n2015-03-26 13:02:53,31\n2015-03-26 13:07:53,15\n2015-03-26 13:12:53,25\n2015-03-26 13:17:53,22\n2015-03-26 13:22:53,42\n2015-03-26 13:27:53,34\n2015-03-26 13:32:53,49\n2015-03-26 13:37:53,27\n2015-03-26 13:42:53,26\n2015-03-26 13:47:53,79\n2015-03-26 13:52:53,33\n2015-03-26 13:57:53,26\n2015-03-26 14:02:53,35\n2015-03-26 14:07:53,38\n2015-03-26 14:12:53,18\n2015-03-26 14:17:53,19\n2015-03-26 14:22:53,30\n2015-03-26 14:27:53,33\n2015-03-26 14:32:53,28\n2015-03-26 14:37:53,26\n2015-03-26 14:42:53,35\n2015-03-26 14:47:53,33\n2015-03-26 14:52:53,29\n2015-03-26 14:57:53,27\n2015-03-26 15:02:53,51\n2015-03-26 15:07:53,31\n2015-03-26 15:12:53,41\n2015-03-26 15:17:53,40\n2015-03-26 15:22:53,37\n2015-03-26 15:27:53,39\n2015-03-26 15:32:53,34\n2015-03-26 15:37:53,35\n2015-03-26 15:42:53,65\n2015-03-26 15:47:53,24\n2015-03-26 15:52:53,22\n2015-03-26 15:57:53,26\n2015-03-26 16:02:53,37\n2015-03-26 16:07:53,37\n2015-03-26 16:12:53,93\n2015-03-26 16:17:53,82\n2015-03-26 16:22:53,30\n2015-03-26 16:27:53,32\n2015-03-26 16:32:53,32\n2015-03-26 16:37:53,30\n2015-03-26 16:42:53,28\n2015-03-26 16:47:53,23\n2015-03-26 16:52:53,21\n2015-03-26 16:57:53,40\n2015-03-26 17:02:53,25\n2015-03-26 17:07:53,25\n2015-03-26 17:12:53,23\n2015-03-26 17:17:53,22\n2015-03-26 17:22:53,29\n2015-03-26 17:27:53,25\n2015-03-26 17:32:53,34\n2015-03-26 17:37:53,53\n2015-03-26 17:42:53,18\n2015-03-26 17:47:53,38\n2015-03-26 17:52:53,29\n2015-03-26 17:57:53,40\n2015-03-26 18:02:53,46\n2015-03-26 18:07:53,24\n2015-03-26 18:12:53,28\n2015-03-26 18:17:53,25\n2015-03-26 18:22:53,38\n2015-03-26 18:27:53,88\n2015-03-26 18:32:53,35\n2015-03-26 18:37:53,28\n2015-03-26 18:42:53,23\n2015-03-26 18:47:53,32\n2015-03-26 18:52:53,24\n2015-03-26 18:57:53,28\n2015-03-26 19:02:53,29\n2015-03-26 19:07:53,25\n2015-03-26 19:12:53,20\n2015-03-26 19:17:53,17\n2015-03-26 19:22:53,22\n2015-03-26 19:27:53,16\n2015-03-26 19:32:53,11\n2015-03-26 19:37:53,20\n2015-03-26 19:42:53,16\n2015-03-26 19:47:53,19\n2015-03-26 19:52:53,12\n2015-03-26 19:57:53,27\n2015-03-26 20:02:53,10\n2015-03-26 20:07:53,20\n2015-03-26 20:12:53,25\n2015-03-26 20:17:53,11\n2015-03-26 20:22:53,15\n2015-03-26 20:27:53,22\n2015-03-26 20:32:53,32\n2015-03-26 20:37:53,30\n2015-03-26 20:42:53,24\n2015-03-26 20:47:53,30\n2015-03-26 20:52:53,13\n2015-03-26 20:57:53,19\n2015-03-26 21:02:53,24\n2015-03-26 21:07:53,17\n2015-03-26 21:12:53,21\n2015-03-26 21:17:53,55\n2015-03-26 21:22:53,20\n2015-03-26 21:27:53,26\n2015-03-26 21:32:53,23\n2015-03-26 21:37:53,31\n2015-03-26 21:42:53,19\n2015-03-26 21:47:53,23\n2015-03-26 21:52:53,17\n2015-03-26 21:57:53,25\n2015-03-26 22:02:53,12\n2015-03-26 22:07:53,18\n2015-03-26 22:12:53,11\n2015-03-26 22:17:53,18\n2015-03-26 22:22:53,13\n2015-03-26 22:27:53,22\n2015-03-26 22:32:53,16\n2015-03-26 22:37:53,12\n2015-03-26 22:42:53,21\n2015-03-26 22:47:53,19\n2015-03-26 22:52:53,18\n2015-03-26 22:57:53,24\n2015-03-26 23:02:53,14\n2015-03-26 23:07:53,25\n2015-03-26 23:12:53,25\n2015-03-26 23:17:53,13\n2015-03-26 23:22:53,13\n2015-03-26 23:27:53,20\n2015-03-26 23:32:53,16\n2015-03-26 23:37:53,13\n2015-03-26 23:42:53,70\n2015-03-26 23:47:53,26\n2015-03-26 23:52:53,20\n2015-03-26 23:57:53,32\n2015-03-27 00:02:53,22\n2015-03-27 00:07:53,10\n2015-03-27 00:12:53,44\n2015-03-27 00:17:53,16\n2015-03-27 00:22:53,11\n2015-03-27 00:27:53,20\n2015-03-27 00:32:53,9\n2015-03-27 00:37:53,12\n2015-03-27 00:42:53,51\n2015-03-27 00:47:53,8\n2015-03-27 00:52:53,14\n2015-03-27 00:57:53,15\n2015-03-27 01:02:53,23\n2015-03-27 01:07:53,12\n2015-03-27 01:12:53,9\n2015-03-27 01:17:53,14\n2015-03-27 01:22:53,11\n2015-03-27 01:27:53,19\n2015-03-27 01:32:53,14\n2015-03-27 01:37:53,33\n2015-03-27 01:42:53,18\n2015-03-27 01:47:53,20\n2015-03-27 01:52:53,9\n2015-03-27 01:57:53,19\n2015-03-27 02:02:53,21\n2015-03-27 02:07:53,16\n2015-03-27 02:12:53,17\n2015-03-27 02:17:53,15\n2015-03-27 02:22:53,6\n2015-03-27 02:27:53,14\n2015-03-27 02:32:53,22\n2015-03-27 02:37:53,25\n2015-03-27 02:42:53,11\n2015-03-27 02:47:53,12\n2015-03-27 02:52:53,13\n2015-03-27 02:57:53,23\n2015-03-27 03:02:53,4\n2015-03-27 03:07:53,13\n2015-03-27 03:12:53,8\n2015-03-27 03:17:53,11\n2015-03-27 03:22:53,12\n2015-03-27 03:27:53,9\n2015-03-27 03:32:53,14\n2015-03-27 03:37:53,12\n2015-03-27 03:42:53,4\n2015-03-27 03:47:53,19\n2015-03-27 03:52:53,16\n2015-03-27 03:57:53,49\n2015-03-27 04:02:53,1\n2015-03-27 04:07:53,13\n2015-03-27 04:12:53,46\n2015-03-27 04:17:53,9\n2015-03-27 04:22:53,9\n2015-03-27 04:27:53,14\n2015-03-27 04:32:53,5\n2015-03-27 04:37:53,10\n2015-03-27 04:42:53,8\n2015-03-27 04:47:53,8\n2015-03-27 04:52:53,8\n2015-03-27 04:57:53,10\n2015-03-27 05:02:53,7\n2015-03-27 05:07:53,9\n2015-03-27 05:12:53,4\n2015-03-27 05:17:53,10\n2015-03-27 05:22:53,9\n2015-03-27 05:27:53,5\n2015-03-27 05:32:53,8\n2015-03-27 05:37:53,22\n2015-03-27 05:42:53,12\n2015-03-27 05:47:53,14\n2015-03-27 05:52:53,13\n2015-03-27 05:57:53,12\n2015-03-27 06:02:53,4\n2015-03-27 06:07:53,6\n2015-03-27 06:12:53,9\n2015-03-27 06:17:53,6\n2015-03-27 06:22:53,5\n2015-03-27 06:27:53,5\n2015-03-27 06:32:53,17\n2015-03-27 06:37:53,7\n2015-03-27 06:42:53,16\n2015-03-27 06:47:53,7\n2015-03-27 06:52:53,5\n2015-03-27 06:57:53,7\n2015-03-27 07:02:53,10\n2015-03-27 07:07:53,2\n2015-03-27 07:12:53,8\n2015-03-27 07:17:53,57\n2015-03-27 07:22:53,5\n2015-03-27 07:27:53,6\n2015-03-27 07:32:53,13\n2015-03-27 07:37:53,8\n2015-03-27 07:42:53,11\n2015-03-27 07:47:53,5\n2015-03-27 07:52:53,11\n2015-03-27 07:57:53,14\n2015-03-27 08:02:53,7\n2015-03-27 08:07:53,6\n2015-03-27 08:12:53,11\n2015-03-27 08:17:53,11\n2015-03-27 08:22:53,13\n2015-03-27 08:27:53,16\n2015-03-27 08:32:53,6\n2015-03-27 08:37:53,17\n2015-03-27 08:42:53,12\n2015-03-27 08:47:53,14\n2015-03-27 08:52:53,7\n2015-03-27 08:57:53,13\n2015-03-27 09:02:53,16\n2015-03-27 09:07:53,7\n2015-03-27 09:12:53,11\n2015-03-27 09:17:53,10\n2015-03-27 09:22:53,12\n2015-03-27 09:27:53,16\n2015-03-27 09:32:53,8\n2015-03-27 09:37:53,9\n2015-03-27 09:42:53,6\n2015-03-27 09:47:53,16\n2015-03-27 09:52:53,12\n2015-03-27 09:57:53,15\n2015-03-27 10:02:53,11\n2015-03-27 10:07:53,14\n2015-03-27 10:12:53,8\n2015-03-27 10:17:53,12\n2015-03-27 10:22:53,3\n2015-03-27 10:27:53,7\n2015-03-27 10:32:53,15\n2015-03-27 10:37:53,11\n2015-03-27 10:42:53,9\n2015-03-27 10:47:53,8\n2015-03-27 10:52:53,17\n2015-03-27 10:57:53,45\n2015-03-27 11:02:53,14\n2015-03-27 11:07:53,10\n2015-03-27 11:12:53,18\n2015-03-27 11:17:53,10\n2015-03-27 11:22:53,6\n2015-03-27 11:27:53,12\n2015-03-27 11:32:53,49\n2015-03-27 11:37:53,14\n2015-03-27 11:42:53,18\n2015-03-27 11:47:53,13\n2015-03-27 11:52:53,11\n2015-03-27 11:57:53,25\n2015-03-27 12:02:53,18\n2015-03-27 12:07:53,17\n2015-03-27 12:12:53,14\n2015-03-27 12:17:53,10\n2015-03-27 12:22:53,21\n2015-03-27 12:27:53,19\n2015-03-27 12:32:53,12\n2015-03-27 12:37:53,13\n2015-03-27 12:42:53,18\n2015-03-27 12:47:53,12\n2015-03-27 12:52:53,13\n2015-03-27 12:57:53,23\n2015-03-27 13:02:53,20\n2015-03-27 13:07:53,18\n2015-03-27 13:12:53,24\n2015-03-27 13:17:53,21\n2015-03-27 13:22:53,25\n2015-03-27 13:27:53,19\n2015-03-27 13:32:53,20\n2015-03-27 13:37:53,17\n2015-03-27 13:42:53,17\n2015-03-27 13:47:53,18\n2015-03-27 13:52:53,26\n2015-03-27 13:57:53,24\n2015-03-27 14:02:53,17\n2015-03-27 14:07:53,15\n2015-03-27 14:12:53,18\n2015-03-27 14:17:53,24\n2015-03-27 14:22:53,63\n2015-03-27 14:27:53,21\n2015-03-27 14:32:53,16\n2015-03-27 14:37:53,64\n2015-03-27 14:42:53,19\n2015-03-27 14:47:53,25\n2015-03-27 14:52:53,28\n2015-03-27 14:57:53,26\n2015-03-27 15:02:53,18\n2015-03-27 15:07:53,18\n2015-03-27 15:12:53,10\n2015-03-27 15:17:53,29\n2015-03-27 15:22:53,24\n2015-03-27 15:27:53,26\n2015-03-27 15:32:53,13\n2015-03-27 15:37:53,29\n2015-03-27 15:42:53,35\n2015-03-27 15:47:53,29\n2015-03-27 15:52:53,23\n2015-03-27 15:57:53,32\n2015-03-27 16:02:53,33\n2015-03-27 16:07:53,26\n2015-03-27 16:12:53,28\n2015-03-27 16:17:53,28\n2015-03-27 16:22:53,49\n2015-03-27 16:27:53,25\n2015-03-27 16:32:53,18\n2015-03-27 16:37:53,26\n2015-03-27 16:42:53,25\n2015-03-27 16:47:53,34\n2015-03-27 16:52:53,60\n2015-03-27 16:57:53,26\n2015-03-27 17:02:53,31\n2015-03-27 17:07:53,36\n2015-03-27 17:12:53,24\n2015-03-27 17:17:53,20\n2015-03-27 17:22:53,35\n2015-03-27 17:27:53,19\n2015-03-27 17:32:53,22\n2015-03-27 17:37:53,13\n2015-03-27 17:42:53,17\n2015-03-27 17:47:53,21\n2015-03-27 17:52:53,18\n2015-03-27 17:57:53,21\n2015-03-27 18:02:53,16\n2015-03-27 18:07:53,12\n2015-03-27 18:12:53,14\n2015-03-27 18:17:53,53\n2015-03-27 18:22:53,12\n2015-03-27 18:27:53,12\n2015-03-27 18:32:53,18\n2015-03-27 18:37:53,17\n2015-03-27 18:42:53,20\n2015-03-27 18:47:53,11\n2015-03-27 18:52:53,15\n2015-03-27 18:57:53,33\n2015-03-27 19:02:53,16\n2015-03-27 19:07:53,12\n2015-03-27 19:12:53,29\n2015-03-27 19:17:53,21\n2015-03-27 19:22:53,21\n2015-03-27 19:27:53,25\n2015-03-27 19:32:53,27\n2015-03-27 19:37:53,18\n2015-03-27 19:42:53,23\n2015-03-27 19:47:53,17\n2015-03-27 19:52:53,56\n2015-03-27 19:57:53,22\n2015-03-27 20:02:53,19\n2015-03-27 20:07:53,19\n2015-03-27 20:12:53,18\n2015-03-27 20:17:53,31\n2015-03-27 20:22:53,35\n2015-03-27 20:27:53,20\n2015-03-27 20:32:53,10\n2015-03-27 20:37:53,18\n2015-03-27 20:42:53,16\n2015-03-27 20:47:53,19\n2015-03-27 20:52:53,22\n2015-03-27 20:57:53,31\n2015-03-27 21:02:53,23\n2015-03-27 21:07:53,13\n2015-03-27 21:12:53,11\n2015-03-27 21:17:53,17\n2015-03-27 21:22:53,22\n2015-03-27 21:27:53,18\n2015-03-27 21:32:53,17\n2015-03-27 21:37:53,9\n2015-03-27 21:42:53,10\n2015-03-27 21:47:53,40\n2015-03-27 21:52:53,17\n2015-03-27 21:57:53,55\n2015-03-27 22:02:53,12\n2015-03-27 22:07:53,47\n2015-03-27 22:12:53,21\n2015-03-27 22:17:53,25\n2015-03-27 22:22:53,11\n2015-03-27 22:27:53,21\n2015-03-27 22:32:53,27\n2015-03-27 22:37:53,12\n2015-03-27 22:42:53,6\n2015-03-27 22:47:53,26\n2015-03-27 22:52:53,7\n2015-03-27 22:57:53,13\n2015-03-27 23:02:53,8\n2015-03-27 23:07:53,32\n2015-03-27 23:12:53,15\n2015-03-27 23:17:53,13\n2015-03-27 23:22:53,18\n2015-03-27 23:27:53,15\n2015-03-27 23:32:53,14\n2015-03-27 23:37:53,11\n2015-03-27 23:42:53,11\n2015-03-27 23:47:53,17\n2015-03-27 23:52:53,6\n2015-03-27 23:57:53,25\n2015-03-28 00:02:53,27\n2015-03-28 00:07:53,12\n2015-03-28 00:12:53,13\n2015-03-28 00:17:53,25\n2015-03-28 00:22:53,14\n2015-03-28 00:27:53,13\n2015-03-28 00:32:53,7\n2015-03-28 00:37:53,13\n2015-03-28 00:42:53,14\n2015-03-28 00:47:53,15\n2015-03-28 00:52:53,7\n2015-03-28 00:57:53,10\n2015-03-28 01:02:53,21\n2015-03-28 01:07:53,11\n2015-03-28 01:12:53,25\n2015-03-28 01:17:53,33\n2015-03-28 01:22:53,8\n2015-03-28 01:27:53,9\n2015-03-28 01:32:53,5\n2015-03-28 01:37:53,11\n2015-03-28 01:42:53,7\n2015-03-28 01:47:53,12\n2015-03-28 01:52:53,3\n2015-03-28 01:57:53,16\n2015-03-28 02:02:53,10\n2015-03-28 02:07:53,3\n2015-03-28 02:12:53,17\n2015-03-28 02:17:53,14\n2015-03-28 02:22:53,14\n2015-03-28 02:27:53,11\n2015-03-28 02:32:53,6\n2015-03-28 02:37:53,16\n2015-03-28 02:42:53,10\n2015-03-28 02:47:53,12\n2015-03-28 02:52:53,16\n2015-03-28 02:57:53,25\n2015-03-28 03:02:53,10\n2015-03-28 03:07:53,15\n2015-03-28 03:12:53,12\n2015-03-28 03:17:53,18\n2015-03-28 03:22:53,18\n2015-03-28 03:27:53,8\n2015-03-28 03:32:53,11\n2015-03-28 03:37:53,14\n2015-03-28 03:42:53,10\n2015-03-28 03:47:53,20\n2015-03-28 03:52:53,14\n2015-03-28 03:57:53,12\n2015-03-28 04:02:53,17\n2015-03-28 04:07:53,7\n2015-03-28 04:12:53,7\n2015-03-28 04:17:53,48\n2015-03-28 04:22:53,11\n2015-03-28 04:27:53,73\n2015-03-28 04:32:53,115\n2015-03-28 04:37:53,110\n2015-03-28 04:42:53,105\n2015-03-28 04:47:53,36\n2015-03-28 04:52:53,86\n2015-03-28 04:57:53,86\n2015-03-28 05:02:53,109\n2015-03-28 05:07:53,76\n2015-03-28 05:12:53,77\n2015-03-28 05:17:53,80\n2015-03-28 05:22:53,64\n2015-03-28 05:27:53,115\n2015-03-28 05:32:53,152\n2015-03-28 05:37:53,174\n2015-03-28 05:42:53,154\n2015-03-28 05:47:53,199\n2015-03-28 05:52:53,123\n2015-03-28 05:57:53,204\n2015-03-28 06:02:53,88\n2015-03-28 06:07:53,27\n2015-03-28 06:12:53,8\n2015-03-28 06:17:53,5\n2015-03-28 06:22:53,11\n2015-03-28 06:27:53,12\n2015-03-28 06:32:53,18\n2015-03-28 06:37:53,13\n2015-03-28 06:42:53,3\n2015-03-28 06:47:53,6\n2015-03-28 06:52:53,10\n2015-03-28 06:57:53,20\n2015-03-28 07:02:53,14\n2015-03-28 07:07:53,18\n2015-03-28 07:12:53,15\n2015-03-28 07:17:53,13\n2015-03-28 07:22:53,16\n2015-03-28 07:27:53,4\n2015-03-28 07:32:53,43\n2015-03-28 07:37:53,9\n2015-03-28 07:42:53,6\n2015-03-28 07:47:53,8\n2015-03-28 07:52:53,4\n2015-03-28 07:57:53,6\n2015-03-28 08:02:53,5\n2015-03-28 08:07:53,18\n2015-03-28 08:12:53,10\n2015-03-28 08:17:53,2\n2015-03-28 08:22:53,5\n2015-03-28 08:27:53,5\n2015-03-28 08:32:53,11\n2015-03-28 08:37:53,12\n2015-03-28 08:42:53,7\n2015-03-28 08:47:53,8\n2015-03-28 08:52:53,12\n2015-03-28 08:57:53,18\n2015-03-28 09:02:53,10\n2015-03-28 09:07:53,14\n2015-03-28 09:12:53,8\n2015-03-28 09:17:53,10\n2015-03-28 09:22:53,11\n2015-03-28 09:27:53,12\n2015-03-28 09:32:53,46\n2015-03-28 09:37:53,8\n2015-03-28 09:42:53,6\n2015-03-28 09:47:53,6\n2015-03-28 09:52:53,13\n2015-03-28 09:57:53,13\n2015-03-28 10:02:53,7\n2015-03-28 10:07:53,8\n2015-03-28 10:12:53,8\n2015-03-28 10:17:53,7\n2015-03-28 10:22:53,8\n2015-03-28 10:27:53,8\n2015-03-28 10:32:53,14\n2015-03-28 10:37:53,5\n2015-03-28 10:42:53,9\n2015-03-28 10:47:53,6\n2015-03-28 10:52:53,49\n2015-03-28 10:57:53,12\n2015-03-28 11:02:53,8\n2015-03-28 11:07:53,15\n2015-03-28 11:12:53,14\n2015-03-28 11:17:53,2\n2015-03-28 11:22:53,11\n2015-03-28 11:27:53,8\n2015-03-28 11:32:53,7\n2015-03-28 11:37:53,7\n2015-03-28 11:42:53,5\n2015-03-28 11:47:53,3\n2015-03-28 11:52:53,14\n2015-03-28 11:57:53,52\n2015-03-28 12:02:53,6\n2015-03-28 12:07:53,9\n2015-03-28 12:12:53,15\n2015-03-28 12:17:53,12\n2015-03-28 12:22:53,17\n2015-03-28 12:27:53,8\n2015-03-28 12:32:53,19\n2015-03-28 12:37:53,19\n2015-03-28 12:42:53,21\n2015-03-28 12:47:53,8\n2015-03-28 12:52:53,19\n2015-03-28 12:57:53,14\n2015-03-28 13:02:53,11\n2015-03-28 13:07:53,8\n2015-03-28 13:12:53,32\n2015-03-28 13:17:53,14\n2015-03-28 13:22:53,7\n2015-03-28 13:27:53,24\n2015-03-28 13:32:53,12\n2015-03-28 13:37:53,5\n2015-03-28 13:42:53,20\n2015-03-28 13:47:53,15\n2015-03-28 13:52:53,12\n2015-03-28 13:57:53,20\n2015-03-28 14:02:53,19\n2015-03-28 14:07:53,8\n2015-03-28 14:12:53,5\n2015-03-28 14:17:53,12\n2015-03-28 14:22:53,15\n2015-03-28 14:27:53,18\n2015-03-28 14:32:53,53\n2015-03-28 14:37:53,6\n2015-03-28 14:42:53,17\n2015-03-28 14:47:53,16\n2015-03-28 14:52:53,43\n2015-03-28 14:57:53,16\n2015-03-28 15:02:53,15\n2015-03-28 15:07:53,24\n2015-03-28 15:12:53,23\n2015-03-28 15:17:53,14\n2015-03-28 15:22:53,19\n2015-03-28 15:27:53,13\n2015-03-28 15:32:53,8\n2015-03-28 15:37:53,14\n2015-03-28 15:42:53,20\n2015-03-28 15:47:53,11\n2015-03-28 15:52:53,25\n2015-03-28 15:57:53,27\n2015-03-28 16:02:53,18\n2015-03-28 16:07:53,23\n2015-03-28 16:12:53,32\n2015-03-28 16:17:53,20\n2015-03-28 16:22:53,17\n2015-03-28 16:27:53,15\n2015-03-28 16:32:53,8\n2015-03-28 16:37:53,12\n2015-03-28 16:42:53,12\n2015-03-28 16:47:53,11\n2015-03-28 16:52:53,11\n2015-03-28 16:57:53,18\n2015-03-28 17:02:53,46\n2015-03-28 17:07:53,11\n2015-03-28 17:12:53,10\n2015-03-28 17:17:53,20\n2015-03-28 17:22:53,9\n2015-03-28 17:27:53,15\n2015-03-28 17:32:53,10\n2015-03-28 17:37:53,10\n2015-03-28 17:42:53,29\n2015-03-28 17:47:53,21\n2015-03-28 17:52:53,15\n2015-03-28 17:57:53,11\n2015-03-28 18:02:53,22\n2015-03-28 18:07:53,51\n2015-03-28 18:12:53,12\n2015-03-28 18:17:53,11\n2015-03-28 18:22:53,5\n2015-03-28 18:27:53,6\n2015-03-28 18:32:53,7\n2015-03-28 18:37:53,6\n2015-03-28 18:42:53,6\n2015-03-28 18:47:53,15\n2015-03-28 18:52:53,6\n2015-03-28 18:57:53,16\n2015-03-28 19:02:53,12\n2015-03-28 19:07:53,12\n2015-03-28 19:12:53,4\n2015-03-28 19:17:53,13\n2015-03-28 19:22:53,7\n2015-03-28 19:27:53,47\n2015-03-28 19:32:53,11\n2015-03-28 19:37:53,12\n2015-03-28 19:42:53,12\n2015-03-28 19:47:53,15\n2015-03-28 19:52:53,12\n2015-03-28 19:57:53,22\n2015-03-28 20:02:53,7\n2015-03-28 20:07:53,5\n2015-03-28 20:12:53,8\n2015-03-28 20:17:53,5\n2015-03-28 20:22:53,8\n2015-03-28 20:27:53,7\n2015-03-28 20:32:53,35\n2015-03-28 20:37:53,3\n2015-03-28 20:42:53,16\n2015-03-28 20:47:53,7\n2015-03-28 20:52:53,15\n2015-03-28 20:57:53,24\n2015-03-28 21:02:53,18\n2015-03-28 21:07:53,15\n2015-03-28 21:12:53,28\n2015-03-28 21:17:53,11\n2015-03-28 21:22:53,13\n2015-03-28 21:27:53,3\n2015-03-28 21:32:53,8\n2015-03-28 21:37:53,45\n2015-03-28 21:42:53,14\n2015-03-28 21:47:53,4\n2015-03-28 21:52:53,10\n2015-03-28 21:57:53,8\n2015-03-28 22:02:53,8\n2015-03-28 22:07:53,9\n2015-03-28 22:12:53,10\n2015-03-28 22:17:53,5\n2015-03-28 22:22:53,6\n2015-03-28 22:27:53,14\n2015-03-28 22:32:53,17\n2015-03-28 22:37:53,27\n2015-03-28 22:42:53,16\n2015-03-28 22:47:53,19\n2015-03-28 22:52:53,15\n2015-03-28 22:57:53,13\n2015-03-28 23:02:53,17\n2015-03-28 23:07:53,8\n2015-03-28 23:12:53,6\n2015-03-28 23:17:53,13\n2015-03-28 23:22:53,20\n2015-03-28 23:27:53,10\n2015-03-28 23:32:53,8\n2015-03-28 23:37:53,7\n2015-03-28 23:42:53,13\n2015-03-28 23:47:53,20\n2015-03-28 23:52:53,22\n2015-03-28 23:57:53,18\n2015-03-29 00:02:53,13\n2015-03-29 00:07:53,49\n2015-03-29 00:12:53,10\n2015-03-29 00:17:53,9\n2015-03-29 00:22:53,9\n2015-03-29 00:27:53,6\n2015-03-29 00:32:53,13\n2015-03-29 00:37:53,14\n2015-03-29 00:42:53,43\n2015-03-29 00:47:53,11\n2015-03-29 00:52:53,5\n2015-03-29 00:57:53,24\n2015-03-29 01:02:53,14\n2015-03-29 01:07:53,7\n2015-03-29 01:12:53,15\n2015-03-29 01:17:53,4\n2015-03-29 01:22:53,8\n2015-03-29 01:27:53,9\n2015-03-29 01:32:53,8\n2015-03-29 01:37:53,6\n2015-03-29 01:42:53,12\n2015-03-29 01:47:53,6\n2015-03-29 01:52:53,12\n2015-03-29 01:57:53,10\n2015-03-29 02:02:53,9\n2015-03-29 02:07:53,8\n2015-03-29 02:12:53,20\n2015-03-29 02:17:53,2\n2015-03-29 02:22:53,5\n2015-03-29 02:27:53,11\n2015-03-29 02:32:53,4\n2015-03-29 02:37:53,8\n2015-03-29 02:42:53,7\n2015-03-29 02:47:53,8\n2015-03-29 02:52:53,2\n2015-03-29 02:57:53,6\n2015-03-29 03:02:53,4\n2015-03-29 03:07:53,12\n2015-03-29 03:12:53,16\n2015-03-29 03:17:53,8\n2015-03-29 03:22:53,8\n2015-03-29 03:27:53,3\n2015-03-29 03:32:53,7\n2015-03-29 03:37:53,5\n2015-03-29 03:42:53,5\n2015-03-29 03:47:53,4\n2015-03-29 03:52:53,9\n2015-03-29 03:57:53,37\n2015-03-29 04:02:53,10\n2015-03-29 04:07:53,13\n2015-03-29 04:12:53,7\n2015-03-29 04:17:53,1\n2015-03-29 04:22:53,7\n2015-03-29 04:27:53,44\n2015-03-29 04:32:53,5\n2015-03-29 04:37:53,3\n2015-03-29 04:42:53,11\n2015-03-29 04:47:53,4\n2015-03-29 04:52:53,3\n2015-03-29 04:57:53,5\n2015-03-29 05:02:53,7\n2015-03-29 05:07:53,9\n2015-03-29 05:12:53,3\n2015-03-29 05:17:53,7\n2015-03-29 05:22:53,5\n2015-03-29 05:27:53,15\n2015-03-29 05:32:53,6\n2015-03-29 05:37:53,3\n2015-03-29 05:42:53,1\n2015-03-29 05:47:53,7\n2015-03-29 05:52:53,5\n2015-03-29 05:57:53,10\n2015-03-29 06:02:53,5\n2015-03-29 06:07:53,2\n2015-03-29 06:12:53,8\n2015-03-29 06:17:53,4\n2015-03-29 06:22:53,3\n2015-03-29 06:27:53,4\n2015-03-29 06:32:53,9\n2015-03-29 06:37:53,3\n2015-03-29 06:42:53,12\n2015-03-29 06:47:53,42\n2015-03-29 06:52:53,3\n2015-03-29 06:57:53,4\n2015-03-29 07:02:53,9\n2015-03-29 07:07:53,9\n2015-03-29 07:12:53,8\n2015-03-29 07:17:53,2\n2015-03-29 07:22:53,5\n2015-03-29 07:27:53,13\n2015-03-29 07:32:53,11\n2015-03-29 07:37:53,5\n2015-03-29 07:42:53,4\n2015-03-29 07:47:53,1\n2015-03-29 07:52:53,6\n2015-03-29 07:57:53,7\n2015-03-29 08:02:53,6\n2015-03-29 08:07:53,5\n2015-03-29 08:12:53,4\n2015-03-29 08:17:53,8\n2015-03-29 08:22:53,8\n2015-03-29 08:27:53,5\n2015-03-29 08:32:53,4\n2015-03-29 08:37:53,1\n2015-03-29 08:42:53,3\n2015-03-29 08:47:53,9\n2015-03-29 08:52:53,5\n2015-03-29 08:57:53,4\n2015-03-29 09:02:53,8\n2015-03-29 09:07:53,53\n2015-03-29 09:12:53,6\n2015-03-29 09:17:53,11\n2015-03-29 09:22:53,6\n2015-03-29 09:27:53,4\n2015-03-29 09:32:53,6\n2015-03-29 09:37:53,0\n2015-03-29 09:42:53,4\n2015-03-29 09:47:53,4\n2015-03-29 09:52:53,6\n2015-03-29 09:57:53,4\n2015-03-29 10:02:53,1\n2015-03-29 10:07:53,3\n2015-03-29 10:12:53,8\n2015-03-29 10:17:53,5\n2015-03-29 10:22:53,6\n2015-03-29 10:27:53,43\n2015-03-29 10:32:53,5\n2015-03-29 10:37:53,2\n2015-03-29 10:42:53,5\n2015-03-29 10:47:53,11\n2015-03-29 10:52:53,6\n2015-03-29 10:57:53,9\n2015-03-29 11:02:53,9\n2015-03-29 11:07:53,3\n2015-03-29 11:12:53,4\n2015-03-29 11:17:53,4\n2015-03-29 11:22:53,3\n2015-03-29 11:27:53,6\n2015-03-29 11:32:53,0\n2015-03-29 11:37:53,43\n2015-03-29 11:42:53,7\n2015-03-29 11:47:53,15\n2015-03-29 11:52:53,10\n2015-03-29 11:57:53,10\n2015-03-29 12:02:53,2\n2015-03-29 12:07:53,21\n2015-03-29 12:12:53,2\n2015-03-29 12:17:53,5\n2015-03-29 12:22:53,7\n2015-03-29 12:27:53,5\n2015-03-29 12:32:53,7\n2015-03-29 12:37:53,17\n2015-03-29 12:42:53,10\n2015-03-29 12:47:53,16\n2015-03-29 12:52:53,7\n2015-03-29 12:57:53,7\n2015-03-29 13:02:53,8\n2015-03-29 13:07:53,7\n2015-03-29 13:12:53,7\n2015-03-29 13:17:53,11\n2015-03-29 13:22:53,0\n2015-03-29 13:27:53,5\n2015-03-29 13:32:53,6\n2015-03-29 13:37:53,2\n2015-03-29 13:42:53,6\n2015-03-29 13:47:53,7\n2015-03-29 13:52:53,11\n2015-03-29 13:57:53,24\n2015-03-29 14:02:53,45\n2015-03-29 14:07:53,59\n2015-03-29 14:12:53,16\n2015-03-29 14:17:53,18\n2015-03-29 14:22:53,13\n2015-03-29 14:27:53,11\n2015-03-29 14:32:53,5\n2015-03-29 14:37:53,14\n2015-03-29 14:42:53,8\n2015-03-29 14:47:53,8\n2015-03-29 14:52:53,8\n2015-03-29 14:57:53,23\n2015-03-29 15:02:53,10\n2015-03-29 15:07:53,10\n2015-03-29 15:12:53,12\n2015-03-29 15:17:53,11\n2015-03-29 15:22:53,14\n2015-03-29 15:27:53,16\n2015-03-29 15:32:53,9\n2015-03-29 15:37:53,8\n2015-03-29 15:42:53,14\n2015-03-29 15:47:53,15\n2015-03-29 15:52:53,10\n2015-03-29 15:57:53,13\n2015-03-29 16:02:53,17\n2015-03-29 16:07:53,10\n2015-03-29 16:12:53,15\n2015-03-29 16:17:53,11\n2015-03-29 16:22:53,12\n2015-03-29 16:27:53,21\n2015-03-29 16:32:53,10\n2015-03-29 16:37:53,39\n2015-03-29 16:42:53,26\n2015-03-29 16:47:53,19\n2015-03-29 16:52:53,14\n2015-03-29 16:57:53,15\n2015-03-29 17:02:53,15\n2015-03-29 17:07:53,17\n2015-03-29 17:12:53,12\n2015-03-29 17:17:53,13\n2015-03-29 17:22:53,16\n2015-03-29 17:27:53,11\n2015-03-29 17:32:53,15\n2015-03-29 17:37:53,45\n2015-03-29 17:42:53,16\n2015-03-29 17:47:53,14\n2015-03-29 17:52:53,17\n2015-03-29 17:57:53,30\n2015-03-29 18:02:53,21\n2015-03-29 18:07:53,11\n2015-03-29 18:12:53,7\n2015-03-29 18:17:53,11\n2015-03-29 18:22:53,15\n2015-03-29 18:27:53,16\n2015-03-29 18:32:53,15\n2015-03-29 18:37:53,10\n2015-03-29 18:42:53,17\n2015-03-29 18:47:53,11\n2015-03-29 18:52:53,6\n2015-03-29 18:57:53,14\n2015-03-29 19:02:53,15\n2015-03-29 19:07:53,9\n2015-03-29 19:12:53,11\n2015-03-29 19:17:53,7\n2015-03-29 19:22:53,59\n2015-03-29 19:27:53,12\n2015-03-29 19:32:53,8\n2015-03-29 19:37:53,11\n2015-03-29 19:42:53,12\n2015-03-29 19:47:53,18\n2015-03-29 19:52:53,10\n2015-03-29 19:57:53,12\n2015-03-29 20:02:53,29\n2015-03-29 20:07:53,10\n2015-03-29 20:12:53,12\n2015-03-29 20:17:53,15\n2015-03-29 20:22:53,11\n2015-03-29 20:27:53,12\n2015-03-29 20:32:53,19\n2015-03-29 20:37:53,11\n2015-03-29 20:42:53,16\n2015-03-29 20:47:53,12\n2015-03-29 20:52:53,8\n2015-03-29 20:57:53,15\n2015-03-29 21:02:53,11\n2015-03-29 21:07:53,18\n2015-03-29 21:12:53,5\n2015-03-29 21:17:53,13\n2015-03-29 21:22:53,14\n2015-03-29 21:27:53,8\n2015-03-29 21:32:53,8\n2015-03-29 21:37:53,13\n2015-03-29 21:42:53,8\n2015-03-29 21:47:53,42\n2015-03-29 21:52:53,5\n2015-03-29 21:57:53,15\n2015-03-29 22:02:53,7\n2015-03-29 22:07:53,10\n2015-03-29 22:12:53,9\n2015-03-29 22:17:53,18\n2015-03-29 22:22:53,12\n2015-03-29 22:27:53,20\n2015-03-29 22:32:53,12\n2015-03-29 22:37:53,13\n2015-03-29 22:42:53,24\n2015-03-29 22:47:53,15\n2015-03-29 22:52:53,10\n2015-03-29 22:57:53,10\n2015-03-29 23:02:53,12\n2015-03-29 23:07:53,13\n2015-03-29 23:12:53,5\n2015-03-29 23:17:53,6\n2015-03-29 23:22:53,11\n2015-03-29 23:27:53,17\n2015-03-29 23:32:53,9\n2015-03-29 23:37:53,12\n2015-03-29 23:42:53,27\n2015-03-29 23:47:53,12\n2015-03-29 23:52:53,23\n2015-03-29 23:57:53,9\n2015-03-30 00:02:53,8\n2015-03-30 00:07:53,52\n2015-03-30 00:12:53,25\n2015-03-30 00:17:53,10\n2015-03-30 00:22:53,18\n2015-03-30 00:27:53,45\n2015-03-30 00:32:53,8\n2015-03-30 00:37:53,7\n2015-03-30 00:42:53,13\n2015-03-30 00:47:53,19\n2015-03-30 00:52:53,12\n2015-03-30 00:57:53,7\n2015-03-30 01:02:53,7\n2015-03-30 01:07:53,15\n2015-03-30 01:12:53,9\n2015-03-30 01:17:53,15\n2015-03-30 01:22:53,22\n2015-03-30 01:27:53,12\n2015-03-30 01:32:53,9\n2015-03-30 01:37:53,8\n2015-03-30 01:42:53,5\n2015-03-30 01:47:53,11\n2015-03-30 01:52:53,3\n2015-03-30 01:57:53,10\n2015-03-30 02:02:53,8\n2015-03-30 02:07:53,3\n2015-03-30 02:12:53,9\n2015-03-30 02:17:53,6\n2015-03-30 02:22:53,6\n2015-03-30 02:27:53,15\n2015-03-30 02:32:53,50\n2015-03-30 02:37:53,10\n2015-03-30 02:42:53,14\n2015-03-30 02:47:53,11\n2015-03-30 02:52:53,17\n2015-03-30 02:57:53,9\n2015-03-30 03:02:53,11\n2015-03-30 03:07:53,4\n2015-03-30 03:12:53,13\n2015-03-30 03:17:53,4\n2015-03-30 03:22:53,10\n2015-03-30 03:27:53,6\n2015-03-30 03:32:53,13\n2015-03-30 03:37:53,51\n2015-03-30 03:42:53,8\n2015-03-30 03:47:53,10\n2015-03-30 03:52:53,10\n2015-03-30 03:57:53,6\n2015-03-30 04:02:53,3\n2015-03-30 04:07:53,7\n2015-03-30 04:12:53,6\n2015-03-30 04:17:53,4\n2015-03-30 04:22:53,6\n2015-03-30 04:27:53,6\n2015-03-30 04:32:53,9\n2015-03-30 04:37:53,11\n2015-03-30 04:42:53,47\n2015-03-30 04:47:53,11\n2015-03-30 04:52:53,12\n2015-03-30 04:57:53,17\n2015-03-30 05:02:53,18\n2015-03-30 05:07:53,11\n2015-03-30 05:12:53,8\n2015-03-30 05:17:53,6\n2015-03-30 05:22:53,98\n2015-03-30 05:27:53,4\n2015-03-30 05:32:53,4\n2015-03-30 05:37:53,10\n2015-03-30 05:42:53,7\n2015-03-30 05:47:53,14\n2015-03-30 05:52:53,4\n2015-03-30 05:57:53,16\n2015-03-30 06:02:53,4\n2015-03-30 06:07:53,8\n2015-03-30 06:12:53,12\n2015-03-30 06:17:53,2\n2015-03-30 06:22:53,14\n2015-03-30 06:27:53,12\n2015-03-30 06:32:53,13\n2015-03-30 06:37:53,23\n2015-03-30 06:42:53,3\n2015-03-30 06:47:53,15\n2015-03-30 06:52:53,7\n2015-03-30 06:57:53,17\n2015-03-30 07:02:53,53\n2015-03-30 07:07:53,18\n2015-03-30 07:12:53,5\n2015-03-30 07:17:53,9\n2015-03-30 07:22:53,2\n2015-03-30 07:27:53,11\n2015-03-30 07:32:53,8\n2015-03-30 07:37:53,8\n2015-03-30 07:42:53,16\n2015-03-30 07:47:53,22\n2015-03-30 07:52:53,8\n2015-03-30 07:57:53,12\n2015-03-30 08:02:53,9\n2015-03-30 08:07:53,8\n2015-03-30 08:12:53,12\n2015-03-30 08:17:53,9\n2015-03-30 08:22:53,4\n2015-03-30 08:27:53,6\n2015-03-30 08:32:53,12\n2015-03-30 08:37:53,6\n2015-03-30 08:42:53,8\n2015-03-30 08:47:53,12\n2015-03-30 08:52:53,8\n2015-03-30 08:57:53,13\n2015-03-30 09:02:53,3\n2015-03-30 09:07:53,9\n2015-03-30 09:12:53,11\n2015-03-30 09:17:53,11\n2015-03-30 09:22:53,9\n2015-03-30 09:27:53,14\n2015-03-30 09:32:53,10\n2015-03-30 09:37:53,7\n2015-03-30 09:42:53,54\n2015-03-30 09:47:53,13\n2015-03-30 09:52:53,8\n2015-03-30 09:57:53,15\n2015-03-30 10:02:53,10\n2015-03-30 10:07:53,10\n2015-03-30 10:12:53,15\n2015-03-30 10:17:53,15\n2015-03-30 10:22:53,13\n2015-03-30 10:27:53,14\n2015-03-30 10:32:53,8\n2015-03-30 10:37:53,44\n2015-03-30 10:42:53,9\n2015-03-30 10:47:53,13\n2015-03-30 10:52:53,7\n2015-03-30 10:57:53,10\n2015-03-30 11:02:53,7\n2015-03-30 11:07:53,4\n2015-03-30 11:12:53,8\n2015-03-30 11:17:53,12\n2015-03-30 11:22:53,5\n2015-03-30 11:27:53,14\n2015-03-30 11:32:53,13\n2015-03-30 11:37:53,10\n2015-03-30 11:42:53,7\n2015-03-30 11:47:53,17\n2015-03-30 11:52:53,2\n2015-03-30 11:57:53,15\n2015-03-30 12:02:53,19\n2015-03-30 12:07:53,9\n2015-03-30 12:12:53,7\n2015-03-30 12:17:53,12\n2015-03-30 12:22:53,8\n2015-03-30 12:27:53,51\n2015-03-30 12:32:53,10\n2015-03-30 12:37:53,12\n2015-03-30 12:42:53,14\n2015-03-30 12:47:53,13\n2015-03-30 12:52:53,25\n2015-03-30 12:57:53,26\n2015-03-30 13:02:53,22\n2015-03-30 13:07:53,12\n2015-03-30 13:12:53,22\n2015-03-30 13:17:53,11\n2015-03-30 13:22:53,11\n2015-03-30 13:27:53,12\n2015-03-30 13:32:53,11\n2015-03-30 13:37:53,13\n2015-03-30 13:42:53,15\n2015-03-30 13:47:53,15\n2015-03-30 13:52:53,27\n2015-03-30 13:57:53,15\n2015-03-30 14:02:53,13\n2015-03-30 14:07:53,23\n2015-03-30 14:12:53,12\n2015-03-30 14:17:53,47\n2015-03-30 14:22:53,15\n2015-03-30 14:27:53,18\n2015-03-30 14:32:53,15\n2015-03-30 14:37:53,23\n2015-03-30 14:42:53,21\n2015-03-30 14:47:53,22\n2015-03-30 14:52:53,25\n2015-03-30 14:57:53,23\n2015-03-30 15:02:53,10\n2015-03-30 15:07:53,6\n2015-03-30 15:12:53,21\n2015-03-30 15:17:53,69\n2015-03-30 15:22:53,20\n2015-03-30 15:27:53,23\n2015-03-30 15:32:53,32\n2015-03-30 15:37:53,29\n2015-03-30 15:42:53,12\n2015-03-30 15:47:53,19\n2015-03-30 15:52:53,15\n2015-03-30 15:57:53,36\n2015-03-30 16:02:53,24\n2015-03-30 16:07:53,34\n2015-03-30 16:12:53,19\n2015-03-30 16:17:53,24\n2015-03-30 16:22:53,31\n2015-03-30 16:27:53,33\n2015-03-30 16:32:53,15\n2015-03-30 16:37:53,17\n2015-03-30 16:42:53,25\n2015-03-30 16:47:53,27\n2015-03-30 16:52:53,31\n2015-03-30 16:57:53,34\n2015-03-30 17:02:53,22\n2015-03-30 17:07:53,16\n2015-03-30 17:12:53,18\n2015-03-30 17:17:53,30\n2015-03-30 17:22:53,28\n2015-03-30 17:27:53,27\n2015-03-30 17:32:53,28\n2015-03-30 17:37:53,30\n2015-03-30 17:42:53,17\n2015-03-30 17:47:53,19\n2015-03-30 17:52:53,18\n2015-03-30 17:57:53,22\n2015-03-30 18:02:53,41\n2015-03-30 18:07:53,35\n2015-03-30 18:12:53,43\n2015-03-30 18:17:53,27\n2015-03-30 18:22:53,19\n2015-03-30 18:27:53,19\n2015-03-30 18:32:53,12\n2015-03-30 18:37:53,19\n2015-03-30 18:42:53,20\n2015-03-30 18:47:53,58\n2015-03-30 18:52:53,24\n2015-03-30 18:57:53,27\n2015-03-30 19:02:53,38\n2015-03-30 19:07:53,26\n2015-03-30 19:12:53,22\n2015-03-30 19:17:53,28\n2015-03-30 19:22:53,15\n2015-03-30 19:27:53,39\n2015-03-30 19:32:53,43\n2015-03-30 19:37:53,19\n2015-03-30 19:42:53,22\n2015-03-30 19:47:53,23\n2015-03-30 19:52:53,26\n2015-03-30 19:57:53,27\n2015-03-30 20:02:53,27\n2015-03-30 20:07:53,26\n2015-03-30 20:12:53,33\n2015-03-30 20:17:53,20\n2015-03-30 20:22:53,12\n2015-03-30 20:27:53,20\n2015-03-30 20:32:53,20\n2015-03-30 20:37:53,19\n2015-03-30 20:42:53,9\n2015-03-30 20:47:53,12\n2015-03-30 20:52:53,18\n2015-03-30 20:57:53,29\n2015-03-30 21:02:53,14\n2015-03-30 21:07:53,14\n2015-03-30 21:12:53,19\n2015-03-30 21:17:53,8\n2015-03-30 21:22:53,12\n2015-03-30 21:27:53,18\n2015-03-30 21:32:53,53\n2015-03-30 21:37:53,21\n2015-03-30 21:42:53,21\n2015-03-30 21:47:53,15\n2015-03-30 21:52:53,12\n2015-03-30 21:57:53,23\n2015-03-30 22:02:53,15\n2015-03-30 22:07:53,15\n2015-03-30 22:12:53,38\n2015-03-30 22:17:53,30\n2015-03-30 22:22:53,14\n2015-03-30 22:27:53,20\n2015-03-30 22:32:53,26\n2015-03-30 22:37:53,10\n2015-03-30 22:42:53,19\n2015-03-30 22:47:53,15\n2015-03-30 22:52:53,10\n2015-03-30 22:57:53,19\n2015-03-30 23:02:53,11\n2015-03-30 23:07:53,51\n2015-03-30 23:12:53,50\n2015-03-30 23:17:53,34\n2015-03-30 23:22:53,32\n2015-03-30 23:27:53,21\n2015-03-30 23:32:53,20\n2015-03-30 23:37:53,15\n2015-03-30 23:42:53,17\n2015-03-30 23:47:53,17\n2015-03-30 23:52:53,15\n2015-03-30 23:57:53,34\n2015-03-31 00:02:53,25\n2015-03-31 00:07:53,15\n2015-03-31 00:12:53,21\n2015-03-31 00:17:53,17\n2015-03-31 00:22:53,23\n2015-03-31 00:27:53,14\n2015-03-31 00:32:53,18\n2015-03-31 00:37:53,18\n2015-03-31 00:42:53,10\n2015-03-31 00:47:53,9\n2015-03-31 00:52:53,16\n2015-03-31 00:57:53,56\n2015-03-31 01:02:53,12\n2015-03-31 01:07:53,18\n2015-03-31 01:12:53,14\n2015-03-31 01:17:53,13\n2015-03-31 01:22:53,7\n2015-03-31 01:27:53,48\n2015-03-31 01:32:53,8\n2015-03-31 01:37:53,20\n2015-03-31 01:42:53,11\n2015-03-31 01:47:53,16\n2015-03-31 01:52:53,11\n2015-03-31 01:57:53,16\n2015-03-31 02:02:53,11\n2015-03-31 02:07:53,17\n2015-03-31 02:12:53,9\n2015-03-31 02:17:53,13\n2015-03-31 02:22:53,13\n2015-03-31 02:27:53,12\n2015-03-31 02:32:53,20\n2015-03-31 02:37:53,11\n2015-03-31 02:42:53,11\n2015-03-31 02:47:53,11\n2015-03-31 02:52:53,12\n2015-03-31 02:57:53,14\n2015-03-31 03:02:53,21\n2015-03-31 03:07:53,7\n2015-03-31 03:12:53,12\n2015-03-31 03:17:53,10\n2015-03-31 03:22:53,8\n2015-03-31 03:27:53,6\n2015-03-31 03:32:53,14\n2015-03-31 03:37:53,12\n2015-03-31 03:42:53,5\n2015-03-31 03:47:53,43\n2015-03-31 03:52:53,16\n2015-03-31 03:57:53,10\n2015-03-31 04:02:53,10\n2015-03-31 04:07:53,15\n2015-03-31 04:12:53,12\n2015-03-31 04:17:53,12\n2015-03-31 04:22:53,59\n2015-03-31 04:27:53,9\n2015-03-31 04:32:53,10\n2015-03-31 04:37:53,10\n2015-03-31 04:42:53,15\n2015-03-31 04:47:53,24\n2015-03-31 04:52:53,4\n2015-03-31 04:57:53,9\n2015-03-31 05:02:53,15\n2015-03-31 05:07:53,9\n2015-03-31 05:12:53,8\n2015-03-31 05:17:53,10\n2015-03-31 05:22:53,8\n2015-03-31 05:27:53,10\n2015-03-31 05:32:53,14\n2015-03-31 05:37:53,10\n2015-03-31 05:42:53,8\n2015-03-31 05:47:53,9\n2015-03-31 05:52:53,14\n2015-03-31 05:57:53,28\n2015-03-31 06:02:53,15\n2015-03-31 06:07:53,15\n2015-03-31 06:12:53,46\n2015-03-31 06:17:53,14\n2015-03-31 06:22:53,13\n2015-03-31 06:27:53,14\n2015-03-31 06:32:53,8\n2015-03-31 06:37:53,15\n2015-03-31 06:42:53,6\n2015-03-31 06:47:53,19\n2015-03-31 06:52:53,8\n2015-03-31 06:57:53,23\n2015-03-31 07:02:53,17\n2015-03-31 07:07:53,25\n2015-03-31 07:12:53,7\n2015-03-31 07:17:53,11\n2015-03-31 07:22:53,18\n2015-03-31 07:27:53,21\n2015-03-31 07:32:53,11\n2015-03-31 07:37:53,12\n2015-03-31 07:42:53,13\n2015-03-31 07:47:53,15\n2015-03-31 07:52:53,43\n2015-03-31 07:57:53,9\n2015-03-31 08:02:53,13\n2015-03-31 08:07:53,11\n2015-03-31 08:12:53,3\n2015-03-31 08:17:53,20\n2015-03-31 08:22:53,11\n2015-03-31 08:27:53,13\n2015-03-31 08:32:53,14\n2015-03-31 08:37:53,7\n2015-03-31 08:42:53,9\n2015-03-31 08:47:53,43\n2015-03-31 08:52:53,7\n2015-03-31 08:57:53,25\n2015-03-31 09:02:53,17\n2015-03-31 09:07:53,18\n2015-03-31 09:12:53,8\n2015-03-31 09:17:53,9\n2015-03-31 09:22:53,13\n2015-03-31 09:27:53,12\n2015-03-31 09:32:53,12\n2015-03-31 09:37:53,16\n2015-03-31 09:42:53,19\n2015-03-31 09:47:53,15\n2015-03-31 09:52:53,18\n2015-03-31 09:57:53,26\n2015-03-31 10:02:53,13\n2015-03-31 10:07:53,18\n2015-03-31 10:12:53,28\n2015-03-31 10:17:53,9\n2015-03-31 10:22:53,22\n2015-03-31 10:27:53,6\n2015-03-31 10:32:53,9\n2015-03-31 10:37:53,33\n2015-03-31 10:42:53,12\n2015-03-31 10:47:53,13\n2015-03-31 10:52:53,26\n2015-03-31 10:57:53,26\n2015-03-31 11:02:53,23\n2015-03-31 11:07:53,18\n2015-03-31 11:12:53,23\n2015-03-31 11:17:53,12\n2015-03-31 11:22:53,45\n2015-03-31 11:27:53,37\n2015-03-31 11:32:53,26\n2015-03-31 11:37:53,12\n2015-03-31 11:42:53,16\n2015-03-31 11:47:53,31\n2015-03-31 11:52:53,17\n2015-03-31 11:57:53,19\n2015-03-31 12:02:53,39\n2015-03-31 12:07:53,34\n2015-03-31 12:12:53,24\n2015-03-31 12:17:53,26\n2015-03-31 12:22:53,16\n2015-03-31 12:27:53,16\n2015-03-31 12:32:53,18\n2015-03-31 12:37:53,25\n2015-03-31 12:42:53,32\n2015-03-31 12:47:53,27\n2015-03-31 12:52:53,20\n2015-03-31 12:57:53,16\n2015-03-31 13:02:53,16\n2015-03-31 13:07:53,23\n2015-03-31 13:12:53,25\n2015-03-31 13:17:53,32\n2015-03-31 13:22:53,26\n2015-03-31 13:27:53,20\n2015-03-31 13:32:53,31\n2015-03-31 13:37:53,23\n2015-03-31 13:42:53,23\n2015-03-31 13:47:53,14\n2015-03-31 13:52:53,17\n2015-03-31 13:57:53,51\n2015-03-31 14:02:53,11\n2015-03-31 14:07:53,21\n2015-03-31 14:12:53,14\n2015-03-31 14:17:53,24\n2015-03-31 14:22:53,24\n2015-03-31 14:27:53,19\n2015-03-31 14:32:53,27\n2015-03-31 14:37:53,27\n2015-03-31 14:42:53,29\n2015-03-31 14:47:53,31\n2015-03-31 14:52:53,37\n2015-03-31 14:57:53,36\n2015-03-31 15:02:53,38\n2015-03-31 15:07:53,34\n2015-03-31 15:12:53,27\n2015-03-31 15:17:53,27\n2015-03-31 15:22:53,37\n2015-03-31 15:27:53,36\n2015-03-31 15:32:53,35\n2015-03-31 15:37:53,40\n2015-03-31 15:42:53,28\n2015-03-31 15:47:53,28\n2015-03-31 15:52:53,37\n2015-03-31 15:57:53,15\n2015-03-31 16:02:53,29\n2015-03-31 16:07:53,35\n2015-03-31 16:12:53,28\n2015-03-31 16:17:53,28\n2015-03-31 16:22:53,35\n2015-03-31 16:27:53,44\n2015-03-31 16:32:53,36\n2015-03-31 16:37:53,50\n2015-03-31 16:42:53,59\n2015-03-31 16:47:53,61\n2015-03-31 16:52:53,72\n2015-03-31 16:57:53,58\n2015-03-31 17:02:53,73\n2015-03-31 17:07:53,88\n2015-03-31 17:12:53,73\n2015-03-31 17:17:53,66\n2015-03-31 17:22:53,64\n2015-03-31 17:27:53,57\n2015-03-31 17:32:53,41\n2015-03-31 17:37:53,32\n2015-03-31 17:42:53,45\n2015-03-31 17:47:53,37\n2015-03-31 17:52:53,42\n2015-03-31 17:57:53,59\n2015-03-31 18:02:53,44\n2015-03-31 18:07:53,39\n2015-03-31 18:12:53,35\n2015-03-31 18:17:53,47\n2015-03-31 18:22:53,35\n2015-03-31 18:27:53,44\n2015-03-31 18:32:53,56\n2015-03-31 18:37:53,43\n2015-03-31 18:42:53,28\n2015-03-31 18:47:53,67\n2015-03-31 18:52:53,29\n2015-03-31 18:57:53,34\n2015-03-31 19:02:53,33\n2015-03-31 19:07:53,24\n2015-03-31 19:12:53,52\n2015-03-31 19:17:53,60\n2015-03-31 19:22:53,53\n2015-03-31 19:27:53,44\n2015-03-31 19:32:53,54\n2015-03-31 19:37:53,35\n2015-03-31 19:42:53,60\n2015-03-31 19:47:53,34\n2015-03-31 19:52:53,48\n2015-03-31 19:57:53,46\n2015-03-31 20:02:53,41\n2015-03-31 20:07:53,34\n2015-03-31 20:12:53,33\n2015-03-31 20:17:53,41\n2015-03-31 20:22:53,40\n2015-03-31 20:27:53,30\n2015-03-31 20:32:53,42\n2015-03-31 20:37:53,37\n2015-03-31 20:42:53,46\n2015-03-31 20:47:53,33\n2015-03-31 20:52:53,39\n2015-03-31 20:57:53,23\n2015-03-31 21:02:53,23\n2015-03-31 21:07:53,38\n2015-03-31 21:12:53,27\n2015-03-31 21:17:53,28\n2015-03-31 21:22:53,31\n2015-03-31 21:27:53,101\n2015-03-31 21:32:53,58\n2015-03-31 21:37:53,53\n2015-03-31 21:42:53,37\n2015-03-31 21:47:53,28\n2015-03-31 21:52:53,41\n2015-03-31 21:57:53,49\n2015-03-31 22:02:53,26\n2015-03-31 22:07:53,33\n2015-03-31 22:12:53,41\n2015-03-31 22:17:53,23\n2015-03-31 22:22:53,42\n2015-03-31 22:27:53,27\n2015-03-31 22:32:53,55\n2015-03-31 22:37:53,39\n2015-03-31 22:42:53,28\n2015-03-31 22:47:53,20\n2015-03-31 22:52:53,28\n2015-03-31 22:57:53,33\n2015-03-31 23:02:53,29\n2015-03-31 23:07:53,25\n2015-03-31 23:12:53,23\n2015-03-31 23:17:53,22\n2015-03-31 23:22:53,29\n2015-03-31 23:27:53,37\n2015-03-31 23:32:53,16\n2015-03-31 23:37:53,23\n2015-03-31 23:42:53,44\n2015-03-31 23:47:53,26\n2015-03-31 23:52:53,30\n2015-03-31 23:57:53,42\n2015-04-01 00:02:53,22\n2015-04-01 00:07:53,31\n2015-04-01 00:12:53,22\n2015-04-01 00:17:53,18\n2015-04-01 00:22:53,32\n2015-04-01 00:27:53,38\n2015-04-01 00:32:53,20\n2015-04-01 00:37:53,21\n2015-04-01 00:42:53,22\n2015-04-01 00:47:53,23\n2015-04-01 00:52:53,17\n2015-04-01 00:57:53,28\n2015-04-01 01:02:53,79\n2015-04-01 01:07:53,93\n2015-04-01 01:12:53,63\n2015-04-01 01:17:53,45\n2015-04-01 01:22:53,52\n2015-04-01 01:27:53,37\n2015-04-01 01:32:53,46\n2015-04-01 01:37:53,31\n2015-04-01 01:42:53,30\n2015-04-01 01:47:53,38\n2015-04-01 01:52:53,30\n2015-04-01 01:57:53,29\n2015-04-01 02:02:53,33\n2015-04-01 02:07:53,25\n2015-04-01 02:12:53,26\n2015-04-01 02:17:53,24\n2015-04-01 02:22:53,30\n2015-04-01 02:27:53,52\n2015-04-01 02:32:53,33\n2015-04-01 02:37:53,22\n2015-04-01 02:42:53,21\n2015-04-01 02:47:53,19\n2015-04-01 02:52:53,21\n2015-04-01 02:57:53,35\n2015-04-01 03:02:53,26\n2015-04-01 03:07:53,20\n2015-04-01 03:12:53,27\n2015-04-01 03:17:53,17\n2015-04-01 03:22:53,34\n2015-04-01 03:27:53,23\n2015-04-01 03:32:53,24\n2015-04-01 03:37:53,15\n2015-04-01 03:42:53,23\n2015-04-01 03:47:53,19\n2015-04-01 03:52:53,24\n2015-04-01 03:57:53,187\n2015-04-01 04:02:53,244\n2015-04-01 04:07:53,179\n2015-04-01 04:12:53,121\n2015-04-01 04:17:53,136\n2015-04-01 04:22:53,112\n2015-04-01 04:27:53,100\n2015-04-01 04:32:53,103\n2015-04-01 04:37:53,98\n2015-04-01 04:42:53,100\n2015-04-01 04:47:53,83\n2015-04-01 04:52:53,77\n2015-04-01 04:57:53,70\n2015-04-01 05:02:53,88\n2015-04-01 05:07:53,67\n2015-04-01 05:12:53,73\n2015-04-01 05:17:53,53\n2015-04-01 05:22:53,60\n2015-04-01 05:27:53,53\n2015-04-01 05:32:53,89\n2015-04-01 05:37:53,71\n2015-04-01 05:42:53,63\n2015-04-01 05:47:53,110\n2015-04-01 05:52:53,215\n2015-04-01 05:57:53,69\n2015-04-01 06:02:53,55\n2015-04-01 06:07:53,63\n2015-04-01 06:12:53,56\n2015-04-01 06:17:53,67\n2015-04-01 06:22:53,73\n2015-04-01 06:27:53,49\n2015-04-01 06:32:53,134\n2015-04-01 06:37:53,206\n2015-04-01 06:42:53,156\n2015-04-01 06:47:53,140\n2015-04-01 06:52:53,105\n2015-04-01 06:57:53,96\n2015-04-01 07:02:53,97\n2015-04-01 07:07:53,91\n2015-04-01 07:12:53,99\n2015-04-01 07:17:53,79\n2015-04-01 07:22:53,72\n2015-04-01 07:27:53,55\n2015-04-01 07:32:53,71\n2015-04-01 07:37:53,60\n2015-04-01 07:42:53,74\n2015-04-01 07:47:53,62\n2015-04-01 07:52:53,88\n2015-04-01 07:57:53,66\n2015-04-01 08:02:53,72\n2015-04-01 08:07:53,62\n2015-04-01 08:12:53,73\n2015-04-01 08:17:53,82\n2015-04-01 08:22:53,70\n2015-04-01 08:27:53,64\n2015-04-01 08:32:53,44\n2015-04-01 08:37:53,62\n2015-04-01 08:42:53,55\n2015-04-01 08:47:53,52\n2015-04-01 08:52:53,72\n2015-04-01 08:57:53,63\n2015-04-01 09:02:53,71\n2015-04-01 09:07:53,47\n2015-04-01 09:12:53,59\n2015-04-01 09:17:53,44\n2015-04-01 09:22:53,41\n2015-04-01 09:27:53,54\n2015-04-01 09:32:53,67\n2015-04-01 09:37:53,59\n2015-04-01 09:42:53,50\n2015-04-01 09:47:53,40\n2015-04-01 09:52:53,49\n2015-04-01 09:57:53,42\n2015-04-01 10:02:53,44\n2015-04-01 10:07:53,73\n2015-04-01 10:12:53,44\n2015-04-01 10:17:53,36\n2015-04-01 10:22:53,61\n2015-04-01 10:27:53,41\n2015-04-01 10:32:53,51\n2015-04-01 10:37:53,40\n2015-04-01 10:42:53,39\n2015-04-01 10:47:53,36\n2015-04-01 10:52:53,48\n2015-04-01 10:57:53,47\n2015-04-01 11:02:53,57\n2015-04-01 11:07:53,48\n2015-04-01 11:12:53,56\n2015-04-01 11:17:53,50\n2015-04-01 11:22:53,31\n2015-04-01 11:27:53,63\n2015-04-01 11:32:53,44\n2015-04-01 11:37:53,49\n2015-04-01 11:42:53,57\n2015-04-01 11:47:53,54\n2015-04-01 11:52:53,52\n2015-04-01 11:57:53,59\n2015-04-01 12:02:53,45\n2015-04-01 12:07:53,41\n2015-04-01 12:12:53,54\n2015-04-01 12:17:53,36\n2015-04-01 12:22:53,50\n2015-04-01 12:27:53,55\n2015-04-01 12:32:53,52\n2015-04-01 12:37:53,53\n2015-04-01 12:42:53,52\n2015-04-01 12:47:53,62\n2015-04-01 12:52:53,48\n2015-04-01 12:57:53,56\n2015-04-01 13:02:53,61\n2015-04-01 13:07:53,58\n2015-04-01 13:12:53,53\n2015-04-01 13:17:53,36\n2015-04-01 13:22:53,42\n2015-04-01 13:27:53,96\n2015-04-01 13:32:53,86\n2015-04-01 13:37:53,68\n2015-04-01 13:42:53,59\n2015-04-01 13:47:53,55\n2015-04-01 13:52:53,43\n2015-04-01 13:57:53,94\n2015-04-01 14:02:53,100\n2015-04-01 14:07:53,62\n2015-04-01 14:12:53,64\n2015-04-01 14:17:53,60\n2015-04-01 14:22:53,77\n2015-04-01 14:27:53,74\n2015-04-01 14:32:53,61\n2015-04-01 14:37:53,65\n2015-04-01 14:42:53,48\n2015-04-01 14:47:53,53\n2015-04-01 14:52:53,59\n2015-04-01 14:57:53,57\n2015-04-01 15:02:53,57\n2015-04-01 15:07:53,58\n2015-04-01 15:12:53,46\n2015-04-01 15:17:53,45\n2015-04-01 15:22:53,45\n2015-04-01 15:27:53,46\n2015-04-01 15:32:53,49\n2015-04-01 15:37:53,42\n2015-04-01 15:42:53,65\n2015-04-01 15:47:53,52\n2015-04-01 15:52:53,47\n2015-04-01 15:57:53,63\n2015-04-01 16:02:53,49\n2015-04-01 16:07:53,58\n2015-04-01 16:12:53,55\n2015-04-01 16:17:53,42\n2015-04-01 16:22:53,68\n2015-04-01 16:27:53,38\n2015-04-01 16:32:53,49\n2015-04-01 16:37:53,41\n2015-04-01 16:42:53,61\n2015-04-01 16:47:53,39\n2015-04-01 16:52:53,41\n2015-04-01 16:57:53,45\n2015-04-01 17:02:53,46\n2015-04-01 17:07:53,38\n2015-04-01 17:12:53,37\n2015-04-01 17:17:53,41\n2015-04-01 17:22:53,39\n2015-04-01 17:27:53,53\n2015-04-01 17:32:53,42\n2015-04-01 17:37:53,53\n2015-04-01 17:42:53,56\n2015-04-01 17:47:53,45\n2015-04-01 17:52:53,45\n2015-04-01 17:57:53,48\n2015-04-01 18:02:53,44\n2015-04-01 18:07:53,30\n2015-04-01 18:12:53,51\n2015-04-01 18:17:53,60\n2015-04-01 18:22:53,35\n2015-04-01 18:27:53,34\n2015-04-01 18:32:53,43\n2015-04-01 18:37:53,45\n2015-04-01 18:42:53,42\n2015-04-01 18:47:53,36\n2015-04-01 18:52:53,31\n2015-04-01 18:57:53,36\n2015-04-01 19:02:53,34\n2015-04-01 19:07:53,30\n2015-04-01 19:12:53,218\n2015-04-01 19:17:53,465\n2015-04-01 19:22:53,174\n2015-04-01 19:27:53,172\n2015-04-01 19:32:53,100\n2015-04-01 19:37:53,103\n2015-04-01 19:42:53,90\n2015-04-01 19:47:53,76\n2015-04-01 19:52:53,98\n2015-04-01 19:57:53,69\n2015-04-01 20:02:53,67\n2015-04-01 20:07:53,68\n2015-04-01 20:12:53,59\n2015-04-01 20:17:53,44\n2015-04-01 20:22:53,40\n2015-04-01 20:27:53,50\n2015-04-01 20:32:53,38\n2015-04-01 20:37:53,47\n2015-04-01 20:42:53,48\n2015-04-01 20:47:53,51\n2015-04-01 20:52:53,46\n2015-04-01 20:57:53,58\n2015-04-01 21:02:53,48\n2015-04-01 21:07:53,238\n2015-04-01 21:12:53,160\n2015-04-01 21:17:53,59\n2015-04-01 21:22:53,40\n2015-04-01 21:27:53,62\n2015-04-01 21:32:53,40\n2015-04-01 21:37:53,31\n2015-04-01 21:42:53,40\n2015-04-01 21:47:53,29\n2015-04-01 21:52:53,41\n2015-04-01 21:57:53,41\n2015-04-01 22:02:53,57\n2015-04-01 22:07:53,35\n2015-04-01 22:12:53,33\n2015-04-01 22:17:53,39\n2015-04-01 22:22:53,23\n2015-04-01 22:27:53,35\n2015-04-01 22:32:53,45\n2015-04-01 22:37:53,30\n2015-04-01 22:42:53,32\n2015-04-01 22:47:53,21\n2015-04-01 22:52:53,22\n2015-04-01 22:57:53,34\n2015-04-01 23:02:53,22\n2015-04-01 23:07:53,22\n2015-04-01 23:12:53,33\n2015-04-01 23:17:53,22\n2015-04-01 23:22:53,34\n2015-04-01 23:27:53,41\n2015-04-01 23:32:53,15\n2015-04-01 23:37:53,16\n2015-04-01 23:42:53,18\n2015-04-01 23:47:53,21\n2015-04-01 23:52:53,19\n2015-04-01 23:57:53,25\n2015-04-02 00:02:53,26\n2015-04-02 00:07:53,18\n2015-04-02 00:12:53,24\n2015-04-02 00:17:53,10\n2015-04-02 00:22:53,22\n2015-04-02 00:27:53,21\n2015-04-02 00:32:53,22\n2015-04-02 00:37:53,15\n2015-04-02 00:42:53,19\n2015-04-02 00:47:53,17\n2015-04-02 00:52:53,22\n2015-04-02 00:57:53,38\n2015-04-02 01:02:53,27\n2015-04-02 01:07:53,14\n2015-04-02 01:12:53,19\n2015-04-02 01:17:53,13\n2015-04-02 01:22:53,24\n2015-04-02 01:27:53,20\n2015-04-02 01:32:53,25\n2015-04-02 01:37:53,20\n2015-04-02 01:42:53,30\n2015-04-02 01:47:53,24\n2015-04-02 01:52:53,14\n2015-04-02 01:57:53,20\n2015-04-02 02:02:53,19\n2015-04-02 02:07:53,15\n2015-04-02 02:12:53,22\n2015-04-02 02:17:53,21\n2015-04-02 02:22:53,18\n2015-04-02 02:27:53,22\n2015-04-02 02:32:53,32\n2015-04-02 02:37:53,19\n2015-04-02 02:42:53,17\n2015-04-02 02:47:53,30\n2015-04-02 02:52:53,23\n2015-04-02 02:57:53,29\n2015-04-02 03:02:53,32\n2015-04-02 03:07:53,26\n2015-04-02 03:12:53,40\n2015-04-02 03:17:53,33\n2015-04-02 03:22:53,19\n2015-04-02 03:27:53,30\n2015-04-02 03:32:53,26\n2015-04-02 03:37:53,23\n2015-04-02 03:42:53,36\n2015-04-02 03:47:53,45\n2015-04-02 03:52:53,29\n2015-04-02 03:57:53,38\n2015-04-02 04:02:53,16\n2015-04-02 04:07:53,16\n2015-04-02 04:12:53,20\n2015-04-02 04:17:53,15\n2015-04-02 04:22:53,13\n2015-04-02 04:27:53,20\n2015-04-02 04:32:53,18\n2015-04-02 04:37:53,16\n2015-04-02 04:42:53,20\n2015-04-02 04:47:53,16\n2015-04-02 04:52:53,20\n2015-04-02 04:57:53,20\n2015-04-02 05:02:53,13\n2015-04-02 05:07:53,20\n2015-04-02 05:12:53,17\n2015-04-02 05:17:53,23\n2015-04-02 05:22:53,13\n2015-04-02 05:27:53,12\n2015-04-02 05:32:53,13\n2015-04-02 05:37:53,11\n2015-04-02 05:42:53,14\n2015-04-02 05:47:53,14\n2015-04-02 05:52:53,16\n2015-04-02 05:57:53,13\n2015-04-02 06:02:53,21\n2015-04-02 06:07:53,20\n2015-04-02 06:12:53,11\n2015-04-02 06:17:53,9\n2015-04-02 06:22:53,15\n2015-04-02 06:27:53,22\n2015-04-02 06:32:53,27\n2015-04-02 06:37:53,9\n2015-04-02 06:42:53,11\n2015-04-02 06:47:53,10\n2015-04-02 06:52:53,12\n2015-04-02 06:57:53,17\n2015-04-02 07:02:53,11\n2015-04-02 07:07:53,16\n2015-04-02 07:12:53,7\n2015-04-02 07:17:53,17\n2015-04-02 07:22:53,23\n2015-04-02 07:27:53,9\n2015-04-02 07:32:53,23\n2015-04-02 07:37:53,10\n2015-04-02 07:42:53,20\n2015-04-02 07:47:53,13\n2015-04-02 07:52:53,13\n2015-04-02 07:57:53,15\n2015-04-02 08:02:53,17\n2015-04-02 08:07:53,11\n2015-04-02 08:12:53,12\n2015-04-02 08:17:53,11\n2015-04-02 08:22:53,18\n2015-04-02 08:27:53,9\n2015-04-02 08:32:53,15\n2015-04-02 08:37:53,17\n2015-04-02 08:42:53,14\n2015-04-02 08:47:53,10\n2015-04-02 08:52:53,26\n2015-04-02 08:57:53,16\n2015-04-02 09:02:53,16\n2015-04-02 09:07:53,16\n2015-04-02 09:12:53,11\n2015-04-02 09:17:53,13\n2015-04-02 09:22:53,26\n2015-04-02 09:27:53,13\n2015-04-02 09:32:53,16\n2015-04-02 09:37:53,19\n2015-04-02 09:42:53,11\n2015-04-02 09:47:53,13\n2015-04-02 09:52:53,8\n2015-04-02 09:57:53,20\n2015-04-02 10:02:53,20\n2015-04-02 10:07:53,13\n2015-04-02 10:12:53,25\n2015-04-02 10:17:53,7\n2015-04-02 10:22:53,6\n2015-04-02 10:27:53,20\n2015-04-02 10:32:53,12\n2015-04-02 10:37:53,7\n2015-04-02 10:42:53,18\n2015-04-02 10:47:53,18\n2015-04-02 10:52:53,15\n2015-04-02 10:57:53,13\n2015-04-02 11:02:53,16\n2015-04-02 11:07:53,8\n2015-04-02 11:12:53,11\n2015-04-02 11:17:53,21\n2015-04-02 11:22:53,15\n2015-04-02 11:27:53,6\n2015-04-02 11:32:53,14\n2015-04-02 11:37:53,16\n2015-04-02 11:42:53,11\n2015-04-02 11:47:53,13\n2015-04-02 11:52:53,15\n2015-04-02 11:57:53,52\n2015-04-02 12:02:53,38\n2015-04-02 12:07:53,17\n2015-04-02 12:12:53,20\n2015-04-02 12:17:53,25\n2015-04-02 12:22:53,33\n2015-04-02 12:27:53,11\n2015-04-02 12:32:53,31\n2015-04-02 12:37:53,31\n2015-04-02 12:42:53,30\n2015-04-02 12:47:53,34\n2015-04-02 12:52:53,24\n2015-04-02 12:57:53,27\n2015-04-02 13:02:53,19\n2015-04-02 13:07:53,26\n2015-04-02 13:12:53,18\n2015-04-02 13:17:53,30\n2015-04-02 13:22:53,24\n2015-04-02 13:27:53,27\n2015-04-02 13:32:53,36\n2015-04-02 13:37:53,22\n2015-04-02 13:42:53,21\n2015-04-02 13:47:53,15\n2015-04-02 13:52:53,25\n2015-04-02 13:57:53,29\n2015-04-02 14:02:53,22\n2015-04-02 14:07:53,23\n2015-04-02 14:12:53,37\n2015-04-02 14:17:53,20\n2015-04-02 14:22:53,25\n2015-04-02 14:27:53,9\n2015-04-02 14:32:53,27\n2015-04-02 14:37:53,35\n2015-04-02 14:42:53,35\n2015-04-02 14:47:53,33\n2015-04-02 14:52:53,31\n2015-04-02 14:57:53,46\n2015-04-02 15:02:53,36\n2015-04-02 15:07:53,33\n2015-04-02 15:12:53,38\n2015-04-02 15:17:53,20\n2015-04-02 15:22:53,27\n2015-04-02 15:27:53,22\n2015-04-02 15:32:53,23\n2015-04-02 15:37:53,33\n2015-04-02 15:42:53,47\n2015-04-02 15:47:53,30\n2015-04-02 15:52:53,17\n2015-04-02 15:57:53,30\n2015-04-02 16:02:53,17\n2015-04-02 16:07:53,24\n2015-04-02 16:12:53,28\n2015-04-02 16:17:53,18\n2015-04-02 16:22:53,27\n2015-04-02 16:27:53,19\n2015-04-02 16:32:53,20\n2015-04-02 16:37:53,15\n2015-04-02 16:42:53,19\n2015-04-02 16:47:53,36\n2015-04-02 16:52:53,42\n2015-04-02 16:57:53,40\n2015-04-02 17:02:53,34\n2015-04-02 17:07:53,25\n2015-04-02 17:12:53,32\n2015-04-02 17:17:53,14\n2015-04-02 17:22:53,23\n2015-04-02 17:27:53,26\n2015-04-02 17:32:53,17\n2015-04-02 17:37:53,19\n2015-04-02 17:42:53,20\n2015-04-02 17:47:53,16\n2015-04-02 17:52:53,18\n2015-04-02 17:57:53,31\n2015-04-02 18:02:53,26\n2015-04-02 18:07:53,20\n2015-04-02 18:12:53,15\n2015-04-02 18:17:53,23\n2015-04-02 18:22:53,22\n2015-04-02 18:27:53,13\n2015-04-02 18:32:53,20\n2015-04-02 18:37:53,19\n2015-04-02 18:42:53,25\n2015-04-02 18:47:53,22\n2015-04-02 18:52:53,21\n2015-04-02 18:57:53,27\n2015-04-02 19:02:53,45\n2015-04-02 19:07:53,79\n2015-04-02 19:12:53,45\n2015-04-02 19:17:53,39\n2015-04-02 19:22:53,28\n2015-04-02 19:27:53,43\n2015-04-02 19:32:53,41\n2015-04-02 19:37:53,26\n2015-04-02 19:42:53,27\n2015-04-02 19:47:53,23\n2015-04-02 19:52:53,22\n2015-04-02 19:57:53,20\n2015-04-02 20:02:53,29\n2015-04-02 20:07:53,17\n2015-04-02 20:12:53,25\n2015-04-02 20:17:53,24\n2015-04-02 20:22:53,50\n2015-04-02 20:27:53,28\n2015-04-02 20:32:53,21\n2015-04-02 20:37:53,28\n2015-04-02 20:42:53,20\n2015-04-02 20:47:53,25\n2015-04-02 20:52:53,28\n2015-04-02 20:57:53,26\n2015-04-02 21:02:53,28\n2015-04-02 21:07:53,13\n2015-04-02 21:12:53,15\n2015-04-02 21:17:53,36\n2015-04-02 21:22:53,29\n2015-04-02 21:27:53,27\n2015-04-02 21:32:53,21\n2015-04-02 21:37:53,28\n2015-04-02 21:42:53,16\n2015-04-02 21:47:53,20\n2015-04-02 21:52:53,16\n2015-04-02 21:57:53,27\n2015-04-02 22:02:53,19\n2015-04-02 22:07:53,17\n2015-04-02 22:12:53,12\n2015-04-02 22:17:53,20\n2015-04-02 22:22:53,16\n2015-04-02 22:27:53,12\n2015-04-02 22:32:53,20\n2015-04-02 22:37:53,12\n2015-04-02 22:42:53,14\n2015-04-02 22:47:53,17\n2015-04-02 22:52:53,14\n2015-04-02 22:57:53,20\n2015-04-02 23:02:53,13\n2015-04-02 23:07:53,15\n2015-04-02 23:12:53,21\n2015-04-02 23:17:53,12\n2015-04-02 23:22:53,21\n2015-04-02 23:27:53,13\n2015-04-02 23:32:53,14\n2015-04-02 23:37:53,17\n2015-04-02 23:42:53,15\n2015-04-02 23:47:53,17\n2015-04-02 23:52:53,18\n2015-04-02 23:57:53,16\n2015-04-03 00:02:53,18\n2015-04-03 00:07:53,22\n2015-04-03 00:12:53,13\n2015-04-03 00:17:53,7\n2015-04-03 00:22:53,11\n2015-04-03 00:27:53,16\n2015-04-03 00:32:53,23\n2015-04-03 00:37:53,11\n2015-04-03 00:42:53,13\n2015-04-03 00:47:53,10\n2015-04-03 00:52:53,15\n2015-04-03 00:57:53,19\n2015-04-03 01:02:53,9\n2015-04-03 01:07:53,14\n2015-04-03 01:12:53,15\n2015-04-03 01:17:53,11\n2015-04-03 01:22:53,12\n2015-04-03 01:27:53,7\n2015-04-03 01:32:53,7\n2015-04-03 01:37:53,12\n2015-04-03 01:42:53,13\n2015-04-03 01:47:53,13\n2015-04-03 01:52:53,15\n2015-04-03 01:57:53,14\n2015-04-03 02:02:53,21\n2015-04-03 02:07:53,16\n2015-04-03 02:12:53,36\n2015-04-03 02:17:53,10\n2015-04-03 02:22:53,3\n2015-04-03 02:27:53,10\n2015-04-03 02:32:53,9\n2015-04-03 02:37:53,8\n2015-04-03 02:42:53,9\n2015-04-03 02:47:53,9\n2015-04-03 02:52:53,14\n2015-04-03 02:57:53,5\n2015-04-03 03:02:53,6\n2015-04-03 03:07:53,6\n2015-04-03 03:12:53,14\n2015-04-03 03:17:53,6\n2015-04-03 03:22:53,11\n2015-04-03 03:27:53,15\n2015-04-03 03:32:53,10\n2015-04-03 03:37:53,14\n2015-04-03 03:42:53,13\n2015-04-03 03:47:53,5\n2015-04-03 03:52:53,11\n2015-04-03 03:57:53,28\n2015-04-03 04:02:53,11\n2015-04-03 04:07:53,5\n2015-04-03 04:12:53,14\n2015-04-03 04:17:53,8\n2015-04-03 04:22:53,11\n2015-04-03 04:27:53,14\n2015-04-03 04:32:53,7\n2015-04-03 04:37:53,14\n2015-04-03 04:42:53,5\n2015-04-03 04:47:53,10\n2015-04-03 04:52:53,11\n2015-04-03 04:57:53,10\n2015-04-03 05:02:53,4\n2015-04-03 05:07:53,5\n2015-04-03 05:12:53,4\n2015-04-03 05:17:53,11\n2015-04-03 05:22:53,8\n2015-04-03 05:27:53,10\n2015-04-03 05:32:53,6\n2015-04-03 05:37:53,10\n2015-04-03 05:42:53,18\n2015-04-03 05:47:53,12\n2015-04-03 05:52:53,8\n2015-04-03 05:57:53,13\n2015-04-03 06:02:53,8\n2015-04-03 06:07:53,8\n2015-04-03 06:12:53,7\n2015-04-03 06:17:53,20\n2015-04-03 06:22:53,9\n2015-04-03 06:27:53,9\n2015-04-03 06:32:53,13\n2015-04-03 06:37:53,5\n2015-04-03 06:42:53,12\n2015-04-03 06:47:53,10\n2015-04-03 06:52:53,13\n2015-04-03 06:57:53,19\n2015-04-03 07:02:53,2\n2015-04-03 07:07:53,8\n2015-04-03 07:12:53,4\n2015-04-03 07:17:53,5\n2015-04-03 07:22:53,14\n2015-04-03 07:27:53,10\n2015-04-03 07:32:53,7\n2015-04-03 07:37:53,7\n2015-04-03 07:42:53,7\n2015-04-03 07:47:53,8\n2015-04-03 07:52:53,8\n2015-04-03 07:57:53,13\n2015-04-03 08:02:53,17\n2015-04-03 08:07:53,33\n2015-04-03 08:12:53,8\n2015-04-03 08:17:53,10\n2015-04-03 08:22:53,7\n2015-04-03 08:27:53,9\n2015-04-03 08:32:53,14\n2015-04-03 08:37:53,10\n2015-04-03 08:42:53,4\n2015-04-03 08:47:53,7\n2015-04-03 08:52:53,5\n2015-04-03 08:57:53,16\n2015-04-03 09:02:53,12\n2015-04-03 09:07:53,10\n2015-04-03 09:12:53,8\n2015-04-03 09:17:53,11\n2015-04-03 09:22:53,8\n2015-04-03 09:27:53,11\n2015-04-03 09:32:53,10\n2015-04-03 09:37:53,7\n2015-04-03 09:42:53,5\n2015-04-03 09:47:53,8\n2015-04-03 09:52:53,10\n2015-04-03 09:57:53,10\n2015-04-03 10:02:53,12\n2015-04-03 10:07:53,6\n2015-04-03 10:12:53,6\n2015-04-03 10:17:53,9\n2015-04-03 10:22:53,16\n2015-04-03 10:27:53,12\n2015-04-03 10:32:53,7\n2015-04-03 10:37:53,14\n2015-04-03 10:42:53,8\n2015-04-03 10:47:53,10\n2015-04-03 10:52:53,8\n2015-04-03 10:57:53,19\n2015-04-03 11:02:53,16\n2015-04-03 11:07:53,25\n2015-04-03 11:12:53,14\n2015-04-03 11:17:53,12\n2015-04-03 11:22:53,17\n2015-04-03 11:27:53,14\n2015-04-03 11:32:53,8\n2015-04-03 11:37:53,11\n2015-04-03 11:42:53,15\n2015-04-03 11:47:53,10\n2015-04-03 11:52:53,3\n2015-04-03 11:57:53,17\n2015-04-03 12:02:53,15\n2015-04-03 12:07:53,17\n2015-04-03 12:12:53,11\n2015-04-03 12:17:53,24\n2015-04-03 12:22:53,14\n2015-04-03 12:27:53,17\n2015-04-03 12:32:53,24\n2015-04-03 12:37:53,17\n2015-04-03 12:42:53,9\n2015-04-03 12:47:53,15\n2015-04-03 12:52:53,9\n2015-04-03 12:57:53,13\n2015-04-03 13:02:53,17\n2015-04-03 13:07:53,12\n2015-04-03 13:12:53,13\n2015-04-03 13:17:53,20\n2015-04-03 13:22:53,15\n2015-04-03 13:27:53,21\n2015-04-03 13:32:53,30\n2015-04-03 13:37:53,20\n2015-04-03 13:42:53,20\n2015-04-03 13:47:53,34\n2015-04-03 13:52:53,18\n2015-04-03 13:57:53,32\n2015-04-03 14:02:53,13\n2015-04-03 14:07:53,21\n2015-04-03 14:12:53,19\n2015-04-03 14:17:53,26\n2015-04-03 14:22:53,19\n2015-04-03 14:27:53,19\n2015-04-03 14:32:53,9\n2015-04-03 14:37:53,22\n2015-04-03 14:42:53,24\n2015-04-03 14:47:53,18\n2015-04-03 14:52:53,24\n2015-04-03 14:57:53,26\n2015-04-03 15:02:53,27\n2015-04-03 15:07:53,22\n2015-04-03 15:12:53,21\n2015-04-03 15:17:53,8\n2015-04-03 15:22:53,11\n2015-04-03 15:27:53,26\n2015-04-03 15:32:53,11\n2015-04-03 15:37:53,14\n2015-04-03 15:42:53,23\n2015-04-03 15:47:53,13\n2015-04-03 15:52:53,22\n2015-04-03 15:57:53,18\n2015-04-03 16:02:53,18\n2015-04-03 16:07:53,18\n2015-04-03 16:12:53,15\n2015-04-03 16:17:53,16\n2015-04-03 16:22:53,10\n2015-04-03 16:27:53,16\n2015-04-03 16:32:53,12\n2015-04-03 16:37:53,15\n2015-04-03 16:42:53,17\n2015-04-03 16:47:53,13\n2015-04-03 16:52:53,14\n2015-04-03 16:57:53,13\n2015-04-03 17:02:53,21\n2015-04-03 17:07:53,8\n2015-04-03 17:12:53,10\n2015-04-03 17:17:53,14\n2015-04-03 17:22:53,21\n2015-04-03 17:27:53,14\n2015-04-03 17:32:53,16\n2015-04-03 17:37:53,12\n2015-04-03 17:42:53,13\n2015-04-03 17:47:53,9\n2015-04-03 17:52:53,33\n2015-04-03 17:57:53,25\n2015-04-03 18:02:53,15\n2015-04-03 18:07:53,8\n2015-04-03 18:12:53,39\n2015-04-03 18:17:53,11\n2015-04-03 18:22:53,23\n2015-04-03 18:27:53,10\n2015-04-03 18:32:53,13\n2015-04-03 18:37:53,11\n2015-04-03 18:42:53,16\n2015-04-03 18:47:53,10\n2015-04-03 18:52:53,15\n2015-04-03 18:57:53,26\n2015-04-03 19:02:53,12\n2015-04-03 19:07:53,9\n2015-04-03 19:12:53,18\n2015-04-03 19:17:53,22\n2015-04-03 19:22:53,23\n2015-04-03 19:27:53,14\n2015-04-03 19:32:53,14\n2015-04-03 19:37:53,10\n2015-04-03 19:42:53,15\n2015-04-03 19:47:53,19\n2015-04-03 19:52:53,17\n2015-04-03 19:57:53,16\n2015-04-03 20:02:53,19\n2015-04-03 20:07:53,10\n2015-04-03 20:12:53,23\n2015-04-03 20:17:53,24\n2015-04-03 20:22:53,21\n2015-04-03 20:27:53,13\n2015-04-03 20:32:53,20\n2015-04-03 20:37:53,18\n2015-04-03 20:42:53,23\n2015-04-03 20:47:53,17\n2015-04-03 20:52:53,15\n2015-04-03 20:57:53,20\n2015-04-03 21:02:53,14\n2015-04-03 21:07:53,14\n2015-04-03 21:12:53,17\n2015-04-03 21:17:53,19\n2015-04-03 21:22:53,20\n2015-04-03 21:27:53,20\n2015-04-03 21:32:53,10\n2015-04-03 21:37:53,5\n2015-04-03 21:42:53,13\n2015-04-03 21:47:53,16\n2015-04-03 21:52:53,13\n2015-04-03 21:57:53,26\n2015-04-03 22:02:53,9\n2015-04-03 22:07:53,11\n2015-04-03 22:12:53,12\n2015-04-03 22:17:53,17\n2015-04-03 22:22:53,5\n2015-04-03 22:27:53,8\n2015-04-03 22:32:53,20\n2015-04-03 22:37:53,18\n2015-04-03 22:42:53,25\n2015-04-03 22:47:53,12\n2015-04-03 22:52:53,8\n2015-04-03 22:57:53,16\n2015-04-03 23:02:53,12\n2015-04-03 23:07:53,9\n2015-04-03 23:12:53,3\n2015-04-03 23:17:53,9\n2015-04-03 23:22:53,13\n2015-04-03 23:27:53,14\n2015-04-03 23:32:53,9\n2015-04-03 23:37:53,14\n2015-04-03 23:42:53,14\n2015-04-03 23:47:53,9\n2015-04-03 23:52:53,12\n2015-04-03 23:57:53,22\n2015-04-04 00:02:53,7\n2015-04-04 00:07:53,16\n2015-04-04 00:12:53,16\n2015-04-04 00:17:53,4\n2015-04-04 00:22:53,9\n2015-04-04 00:27:53,6\n2015-04-04 00:32:53,10\n2015-04-04 00:37:53,4\n2015-04-04 00:42:53,5\n2015-04-04 00:47:53,13\n2015-04-04 00:52:53,4\n2015-04-04 00:57:53,7\n2015-04-04 01:02:53,3\n2015-04-04 01:07:53,10\n2015-04-04 01:12:53,8\n2015-04-04 01:17:53,11\n2015-04-04 01:22:53,9\n2015-04-04 01:27:53,17\n2015-04-04 01:32:53,15\n2015-04-04 01:37:53,14\n2015-04-04 01:42:53,16\n2015-04-04 01:47:53,13\n2015-04-04 01:52:53,5\n2015-04-04 01:57:53,13\n2015-04-04 02:02:53,7\n2015-04-04 02:07:53,13\n2015-04-04 02:12:53,5\n2015-04-04 02:17:53,12\n2015-04-04 02:22:53,2\n2015-04-04 02:27:53,6\n2015-04-04 02:32:53,2\n2015-04-04 02:37:53,4\n2015-04-04 02:42:53,8\n2015-04-04 02:47:53,17\n2015-04-04 02:52:53,12\n2015-04-04 02:57:53,23\n2015-04-04 03:02:53,8\n2015-04-04 03:07:53,2\n2015-04-04 03:12:53,9\n2015-04-04 03:17:53,12\n2015-04-04 03:22:53,16\n2015-04-04 03:27:53,23\n2015-04-04 03:32:53,12\n2015-04-04 03:37:53,8\n2015-04-04 03:42:53,11\n2015-04-04 03:47:53,6\n2015-04-04 03:52:53,10\n2015-04-04 03:57:53,10\n2015-04-04 04:02:53,12\n2015-04-04 04:07:53,10\n2015-04-04 04:12:53,5\n2015-04-04 04:17:53,8\n2015-04-04 04:22:53,8\n2015-04-04 04:27:53,10\n2015-04-04 04:32:53,6\n2015-04-04 04:37:53,4\n2015-04-04 04:42:53,2\n2015-04-04 04:47:53,6\n2015-04-04 04:52:53,4\n2015-04-04 04:57:53,6\n2015-04-04 05:02:53,9\n2015-04-04 05:07:53,5\n2015-04-04 05:12:53,12\n2015-04-04 05:17:53,13\n2015-04-04 05:22:53,5\n2015-04-04 05:27:53,3\n2015-04-04 05:32:53,12\n2015-04-04 05:37:53,4\n2015-04-04 05:42:53,3\n2015-04-04 05:47:53,10\n2015-04-04 05:52:53,5\n2015-04-04 05:57:53,10\n2015-04-04 06:02:53,6\n2015-04-04 06:07:53,6\n2015-04-04 06:12:53,2\n2015-04-04 06:17:53,10\n2015-04-04 06:22:53,7\n2015-04-04 06:27:53,1\n2015-04-04 06:32:53,4\n2015-04-04 06:37:53,17\n2015-04-04 06:42:53,7\n2015-04-04 06:47:53,5\n2015-04-04 06:52:53,10\n2015-04-04 06:57:53,10\n2015-04-04 07:02:53,26\n2015-04-04 07:07:53,16\n2015-04-04 07:12:53,7\n2015-04-04 07:17:53,13\n2015-04-04 07:22:53,12\n2015-04-04 07:27:53,16\n2015-04-04 07:32:53,9\n2015-04-04 07:37:53,8\n2015-04-04 07:42:53,8\n2015-04-04 07:47:53,17\n2015-04-04 07:52:53,15\n2015-04-04 07:57:53,11\n2015-04-04 08:02:53,12\n2015-04-04 08:07:53,9\n2015-04-04 08:12:53,10\n2015-04-04 08:17:53,9\n2015-04-04 08:22:53,8\n2015-04-04 08:27:53,18\n2015-04-04 08:32:53,12\n2015-04-04 08:37:53,12\n2015-04-04 08:42:53,8\n2015-04-04 08:47:53,15\n2015-04-04 08:52:53,6\n2015-04-04 08:57:53,17\n2015-04-04 09:02:53,12\n2015-04-04 09:07:53,8\n2015-04-04 09:12:53,11\n2015-04-04 09:17:53,12\n2015-04-04 09:22:53,13\n2015-04-04 09:27:53,14\n2015-04-04 09:32:53,12\n2015-04-04 09:37:53,9\n2015-04-04 09:42:53,11\n2015-04-04 09:47:53,6\n2015-04-04 09:52:53,8\n2015-04-04 09:57:53,7\n2015-04-04 10:02:53,7\n2015-04-04 10:07:53,1\n2015-04-04 10:12:53,4\n2015-04-04 10:17:53,12\n2015-04-04 10:22:53,15\n2015-04-04 10:27:53,8\n2015-04-04 10:32:53,17\n2015-04-04 10:37:53,5\n2015-04-04 10:42:53,8\n2015-04-04 10:47:53,12\n2015-04-04 10:52:53,11\n2015-04-04 10:57:53,7\n2015-04-04 11:02:53,7\n2015-04-04 11:07:53,6\n2015-04-04 11:12:53,7\n2015-04-04 11:17:53,9\n2015-04-04 11:22:53,6\n2015-04-04 11:27:53,9\n2015-04-04 11:32:53,8\n2015-04-04 11:37:53,9\n2015-04-04 11:42:53,7\n2015-04-04 11:47:53,1\n2015-04-04 11:52:53,16\n2015-04-04 11:57:53,9\n2015-04-04 12:02:53,11\n2015-04-04 12:07:53,14\n2015-04-04 12:12:53,3\n2015-04-04 12:17:53,6\n2015-04-04 12:22:53,6\n2015-04-04 12:27:53,4\n2015-04-04 12:32:53,6\n2015-04-04 12:37:53,9\n2015-04-04 12:42:53,8\n2015-04-04 12:47:53,17\n2015-04-04 12:52:53,12\n2015-04-04 12:57:53,12\n2015-04-04 13:02:53,10\n2015-04-04 13:07:53,8\n2015-04-04 13:12:53,4\n2015-04-04 13:17:53,11\n2015-04-04 13:22:53,14\n2015-04-04 13:27:53,5\n2015-04-04 13:32:53,5\n2015-04-04 13:37:53,8\n2015-04-04 13:42:53,9\n2015-04-04 13:47:53,11\n2015-04-04 13:52:53,17\n2015-04-04 13:57:53,14\n2015-04-04 14:02:53,25\n2015-04-04 14:07:53,13\n2015-04-04 14:12:53,7\n2015-04-04 14:17:53,11\n2015-04-04 14:22:53,17\n2015-04-04 14:27:53,14\n2015-04-04 14:32:53,5\n2015-04-04 14:37:53,16\n2015-04-04 14:42:53,11\n2015-04-04 14:47:53,8\n2015-04-04 14:52:53,17\n2015-04-04 14:57:53,11\n2015-04-04 15:02:53,22\n2015-04-04 15:07:53,26\n2015-04-04 15:12:53,8\n2015-04-04 15:17:53,18\n2015-04-04 15:22:53,14\n2015-04-04 15:27:53,5\n2015-04-04 15:32:53,15\n2015-04-04 15:37:53,8\n2015-04-04 15:42:53,10\n2015-04-04 15:47:53,25\n2015-04-04 15:52:53,28\n2015-04-04 15:57:53,12\n2015-04-04 16:02:53,9\n2015-04-04 16:07:53,15\n2015-04-04 16:12:53,19\n2015-04-04 16:17:53,12\n2015-04-04 16:22:53,14\n2015-04-04 16:27:53,12\n2015-04-04 16:32:53,12\n2015-04-04 16:37:53,11\n2015-04-04 16:42:53,17\n2015-04-04 16:47:53,18\n2015-04-04 16:52:53,17\n2015-04-04 16:57:53,27\n2015-04-04 17:02:53,20\n2015-04-04 17:07:53,18\n2015-04-04 17:12:53,10\n2015-04-04 17:17:53,14\n2015-04-04 17:22:53,18\n2015-04-04 17:27:53,10\n2015-04-04 17:32:53,6\n2015-04-04 17:37:53,11\n2015-04-04 17:42:53,8\n2015-04-04 17:47:53,8\n2015-04-04 17:52:53,17\n2015-04-04 17:57:53,23\n2015-04-04 18:02:53,41\n2015-04-04 18:07:53,25\n2015-04-04 18:12:53,19\n2015-04-04 18:17:53,23\n2015-04-04 18:22:53,18\n2015-04-04 18:27:53,27\n2015-04-04 18:32:53,13\n2015-04-04 18:37:53,17\n2015-04-04 18:42:53,8\n2015-04-04 18:47:53,13\n2015-04-04 18:52:53,26\n2015-04-04 18:57:53,18\n2015-04-04 19:02:53,13\n2015-04-04 19:07:53,11\n2015-04-04 19:12:53,15\n2015-04-04 19:17:53,14\n2015-04-04 19:22:53,8\n2015-04-04 19:27:53,13\n2015-04-04 19:32:53,4\n2015-04-04 19:37:53,6\n2015-04-04 19:42:53,20\n2015-04-04 19:47:53,8\n2015-04-04 19:52:53,5\n2015-04-04 19:57:53,6\n2015-04-04 20:02:53,6\n2015-04-04 20:07:53,8\n2015-04-04 20:12:53,11\n2015-04-04 20:17:53,28\n2015-04-04 20:22:53,11\n2015-04-04 20:27:53,16\n2015-04-04 20:32:53,23\n2015-04-04 20:37:53,14\n2015-04-04 20:42:53,6\n2015-04-04 20:47:53,6\n2015-04-04 20:52:53,6\n2015-04-04 20:57:53,9\n2015-04-04 21:02:53,7\n2015-04-04 21:07:53,7\n2015-04-04 21:12:53,7\n2015-04-04 21:17:53,9\n2015-04-04 21:22:53,6\n2015-04-04 21:27:53,8\n2015-04-04 21:32:53,4\n2015-04-04 21:37:53,6\n2015-04-04 21:42:53,7\n2015-04-04 21:47:53,16\n2015-04-04 21:52:53,8\n2015-04-04 21:57:53,7\n2015-04-04 22:02:53,6\n2015-04-04 22:07:53,9\n2015-04-04 22:12:53,4\n2015-04-04 22:17:53,5\n2015-04-04 22:22:53,12\n2015-04-04 22:27:53,6\n2015-04-04 22:32:53,12\n2015-04-04 22:37:53,16\n2015-04-04 22:42:53,18\n2015-04-04 22:47:53,12\n2015-04-04 22:52:53,15\n2015-04-04 22:57:53,15\n2015-04-04 23:02:53,12\n2015-04-04 23:07:53,14\n2015-04-04 23:12:53,13\n2015-04-04 23:17:53,6\n2015-04-04 23:22:53,6\n2015-04-04 23:27:53,10\n2015-04-04 23:32:53,8\n2015-04-04 23:37:53,8\n2015-04-04 23:42:53,6\n2015-04-04 23:47:53,8\n2015-04-04 23:52:53,5\n2015-04-04 23:57:53,10\n2015-04-05 00:02:53,10\n2015-04-05 00:07:53,2\n2015-04-05 00:12:53,10\n2015-04-05 00:17:53,9\n2015-04-05 00:22:53,11\n2015-04-05 00:27:53,5\n2015-04-05 00:32:53,23\n2015-04-05 00:37:53,20\n2015-04-05 00:42:53,9\n2015-04-05 00:47:53,15\n2015-04-05 00:52:53,14\n2015-04-05 00:57:53,23\n2015-04-05 01:02:53,16\n2015-04-05 01:07:53,6\n2015-04-05 01:12:53,13\n2015-04-05 01:17:53,10\n2015-04-05 01:22:53,11\n2015-04-05 01:27:53,15\n2015-04-05 01:32:53,13\n2015-04-05 01:37:53,18\n2015-04-05 01:42:53,6\n2015-04-05 01:47:53,9\n2015-04-05 01:52:53,10\n2015-04-05 01:57:53,8\n2015-04-05 02:02:53,3\n2015-04-05 02:07:53,5\n2015-04-05 02:12:53,6\n2015-04-05 02:17:53,6\n2015-04-05 02:22:53,5\n2015-04-05 02:27:53,6\n2015-04-05 02:32:53,4\n2015-04-05 02:37:53,8\n2015-04-05 02:42:53,63\n2015-04-05 02:47:53,96\n2015-04-05 02:52:53,64\n2015-04-05 02:57:53,34\n2015-04-05 03:02:53,39\n2015-04-05 03:07:53,39\n2015-04-05 03:12:53,40\n2015-04-05 03:17:53,16\n2015-04-05 03:22:53,18\n2015-04-05 03:27:53,23\n2015-04-05 03:32:53,24\n2015-04-05 03:37:53,21\n2015-04-05 03:42:53,17\n2015-04-05 03:47:53,26\n2015-04-05 03:52:53,7\n2015-04-05 03:57:53,16\n2015-04-05 04:02:53,7\n2015-04-05 04:07:53,9\n2015-04-05 04:12:53,12\n2015-04-05 04:17:53,7\n2015-04-05 04:22:53,14\n2015-04-05 04:27:53,18\n2015-04-05 04:32:53,14\n2015-04-05 04:37:53,35\n2015-04-05 04:42:53,37\n2015-04-05 04:47:53,19\n2015-04-05 04:52:53,21\n2015-04-05 04:57:53,27\n2015-04-05 05:02:53,10\n2015-04-05 05:07:53,10\n2015-04-05 05:12:53,20\n2015-04-05 05:17:53,11\n2015-04-05 05:22:53,9\n2015-04-05 05:27:53,11\n2015-04-05 05:32:53,17\n2015-04-05 05:37:53,13\n2015-04-05 05:42:53,13\n2015-04-05 05:47:53,11\n2015-04-05 05:52:53,7\n2015-04-05 05:57:53,22\n2015-04-05 06:02:53,13\n2015-04-05 06:07:53,11\n2015-04-05 06:12:53,12\n2015-04-05 06:17:53,9\n2015-04-05 06:22:53,5\n2015-04-05 06:27:53,14\n2015-04-05 06:32:53,9\n2015-04-05 06:37:53,12\n2015-04-05 06:42:53,8\n2015-04-05 06:47:53,12\n2015-04-05 06:52:53,5\n2015-04-05 06:57:53,15\n2015-04-05 07:02:53,15\n2015-04-05 07:07:53,15\n2015-04-05 07:12:53,22\n2015-04-05 07:17:53,13\n2015-04-05 07:22:53,10\n2015-04-05 07:27:53,23\n2015-04-05 07:32:53,11\n2015-04-05 07:37:53,31\n2015-04-05 07:42:53,18\n2015-04-05 07:47:53,12\n2015-04-05 07:52:53,10\n2015-04-05 07:57:53,4\n2015-04-05 08:02:53,12\n2015-04-05 08:07:53,7\n2015-04-05 08:12:53,11\n2015-04-05 08:17:53,11\n2015-04-05 08:22:53,15\n2015-04-05 08:27:53,5\n2015-04-05 08:32:53,8\n2015-04-05 08:37:53,2\n2015-04-05 08:42:53,4\n2015-04-05 08:47:53,14\n2015-04-05 08:52:53,14\n2015-04-05 08:57:53,7\n2015-04-05 09:02:53,14\n2015-04-05 09:07:53,15\n2015-04-05 09:12:53,12\n2015-04-05 09:17:53,10\n2015-04-05 09:22:53,8\n2015-04-05 09:27:53,13\n2015-04-05 09:32:53,16\n2015-04-05 09:37:53,12\n2015-04-05 09:42:53,11\n2015-04-05 09:47:53,12\n2015-04-05 09:52:53,8\n2015-04-05 09:57:53,7\n2015-04-05 10:02:53,49\n2015-04-05 10:07:53,12\n2015-04-05 10:12:53,6\n2015-04-05 10:17:53,18\n2015-04-05 10:22:53,9\n2015-04-05 10:27:53,8\n2015-04-05 10:32:53,13\n2015-04-05 10:37:53,3\n2015-04-05 10:42:53,10\n2015-04-05 10:47:53,6\n2015-04-05 10:52:53,17\n2015-04-05 10:57:53,21\n2015-04-05 11:02:53,6\n2015-04-05 11:07:53,12\n2015-04-05 11:12:53,13\n2015-04-05 11:17:53,7\n2015-04-05 11:22:53,7\n2015-04-05 11:27:53,10\n2015-04-05 11:32:53,10\n2015-04-05 11:37:53,7\n2015-04-05 11:42:53,13\n2015-04-05 11:47:53,8\n2015-04-05 11:52:53,13\n2015-04-05 11:57:53,12\n2015-04-05 12:02:53,10\n2015-04-05 12:07:53,16\n2015-04-05 12:12:53,30\n2015-04-05 12:17:53,14\n2015-04-05 12:22:53,14\n2015-04-05 12:27:53,15\n2015-04-05 12:32:53,21\n2015-04-05 12:37:53,36\n2015-04-05 12:42:53,36\n2015-04-05 12:47:53,36\n2015-04-05 12:52:53,14\n2015-04-05 12:57:53,38\n2015-04-05 13:02:53,38\n2015-04-05 13:07:53,17\n2015-04-05 13:12:53,18\n2015-04-05 13:17:53,22\n2015-04-05 13:22:53,16\n2015-04-05 13:27:53,30\n2015-04-05 13:32:53,25\n2015-04-05 13:37:53,29\n2015-04-05 13:42:53,17\n2015-04-05 13:47:53,11\n2015-04-05 13:52:53,10\n2015-04-05 13:57:53,16\n2015-04-05 14:02:53,28\n2015-04-05 14:07:53,26\n2015-04-05 14:12:53,48\n2015-04-05 14:17:53,18\n2015-04-05 14:22:53,19\n2015-04-05 14:27:53,18\n2015-04-05 14:32:53,18\n2015-04-05 14:37:53,16\n2015-04-05 14:42:53,22\n2015-04-05 14:47:53,18\n2015-04-05 14:52:53,23\n2015-04-05 14:57:53,19\n2015-04-05 15:02:53,27\n2015-04-05 15:07:53,33\n2015-04-05 15:12:53,19\n2015-04-05 15:17:53,15\n2015-04-05 15:22:53,13\n2015-04-05 15:27:53,21\n2015-04-05 15:32:53,10\n2015-04-05 15:37:53,20\n2015-04-05 15:42:53,15\n2015-04-05 15:47:53,113\n2015-04-05 15:52:53,201\n2015-04-05 15:57:53,161\n2015-04-05 16:02:53,15\n2015-04-05 16:07:53,16\n2015-04-05 16:12:53,22\n2015-04-05 16:17:53,19\n2015-04-05 16:22:53,22\n2015-04-05 16:27:53,83\n2015-04-05 16:32:53,89\n2015-04-05 16:37:53,12\n2015-04-05 16:42:53,13\n2015-04-05 16:47:53,10\n2015-04-05 16:52:53,12\n2015-04-05 16:57:53,13\n2015-04-05 17:02:53,18\n2015-04-05 17:07:53,14\n2015-04-05 17:12:53,9\n2015-04-05 17:17:53,16\n2015-04-05 17:22:53,11\n2015-04-05 17:27:53,3\n2015-04-05 17:32:53,23\n2015-04-05 17:37:53,54\n2015-04-05 17:42:53,28\n2015-04-05 17:47:53,6\n2015-04-05 17:52:53,7\n2015-04-05 17:57:53,18\n2015-04-05 18:02:53,13\n2015-04-05 18:07:53,6\n2015-04-05 18:12:53,12\n2015-04-05 18:17:53,10\n2015-04-05 18:22:53,10\n2015-04-05 18:27:53,13\n2015-04-05 18:32:53,24\n2015-04-05 18:37:53,11\n2015-04-05 18:42:53,10\n2015-04-05 18:47:53,13\n2015-04-05 18:52:53,12\n2015-04-05 18:57:53,22\n2015-04-05 19:02:53,21\n2015-04-05 19:07:53,12\n2015-04-05 19:12:53,14\n2015-04-05 19:17:53,10\n2015-04-05 19:22:53,12\n2015-04-05 19:27:53,8\n2015-04-05 19:32:53,17\n2015-04-05 19:37:53,14\n2015-04-05 19:42:53,17\n2015-04-05 19:47:53,13\n2015-04-05 19:52:53,11\n2015-04-05 19:57:53,23\n2015-04-05 20:02:53,14\n2015-04-05 20:07:53,13\n2015-04-05 20:12:53,15\n2015-04-05 20:17:53,9\n2015-04-05 20:22:53,12\n2015-04-05 20:27:53,11\n2015-04-05 20:32:53,6\n2015-04-05 20:37:53,14\n2015-04-05 20:42:53,19\n2015-04-05 20:47:53,7\n2015-04-05 20:52:53,19\n2015-04-05 20:57:53,19\n2015-04-05 21:02:53,31\n2015-04-05 21:07:53,15\n2015-04-05 21:12:53,12\n2015-04-05 21:17:53,15\n2015-04-05 21:22:53,9\n2015-04-05 21:27:53,8\n2015-04-05 21:32:53,12\n2015-04-05 21:37:53,7\n2015-04-05 21:42:53,6\n2015-04-05 21:47:53,14\n2015-04-05 21:52:53,10\n2015-04-05 21:57:53,9\n2015-04-05 22:02:53,15\n2015-04-05 22:07:53,6\n2015-04-05 22:12:53,13\n2015-04-05 22:17:53,4\n2015-04-05 22:22:53,10\n2015-04-05 22:27:53,12\n2015-04-05 22:32:53,22\n2015-04-05 22:37:53,13\n2015-04-05 22:42:53,11\n2015-04-05 22:47:53,14\n2015-04-05 22:52:53,12\n2015-04-05 22:57:53,23\n2015-04-05 23:02:53,19\n2015-04-05 23:07:53,12\n2015-04-05 23:12:53,16\n2015-04-05 23:17:53,16\n2015-04-05 23:22:53,9\n2015-04-05 23:27:53,14\n2015-04-05 23:32:53,9\n2015-04-05 23:37:53,10\n2015-04-05 23:42:53,9\n2015-04-05 23:47:53,16\n2015-04-05 23:52:53,18\n2015-04-05 23:57:53,18\n2015-04-06 00:02:53,9\n2015-04-06 00:07:53,7\n2015-04-06 00:12:53,9\n2015-04-06 00:17:53,12\n2015-04-06 00:22:53,13\n2015-04-06 00:27:53,14\n2015-04-06 00:32:53,12\n2015-04-06 00:37:53,8\n2015-04-06 00:42:53,44\n2015-04-06 00:47:53,24\n2015-04-06 00:52:53,28\n2015-04-06 00:57:53,19\n2015-04-06 01:02:53,17\n2015-04-06 01:07:53,16\n2015-04-06 01:12:53,13\n2015-04-06 01:17:53,9\n2015-04-06 01:22:53,12\n2015-04-06 01:27:53,14\n2015-04-06 01:32:53,9\n2015-04-06 01:37:53,8\n2015-04-06 01:42:53,9\n2015-04-06 01:47:53,12\n2015-04-06 01:52:53,23\n2015-04-06 01:57:53,16\n2015-04-06 02:02:53,6\n2015-04-06 02:07:53,20\n2015-04-06 02:12:53,12\n2015-04-06 02:17:53,6\n2015-04-06 02:22:53,7\n2015-04-06 02:27:53,13\n2015-04-06 02:32:53,6\n2015-04-06 02:37:53,12\n2015-04-06 02:42:53,9\n2015-04-06 02:47:53,5\n2015-04-06 02:52:53,10\n2015-04-06 02:57:53,11\n2015-04-06 03:02:53,10\n2015-04-06 03:07:53,9\n2015-04-06 03:12:53,12\n2015-04-06 03:17:53,11\n2015-04-06 03:22:53,12\n2015-04-06 03:27:53,14\n2015-04-06 03:32:53,9\n2015-04-06 03:37:53,9\n2015-04-06 03:42:53,10\n2015-04-06 03:47:53,11\n2015-04-06 03:52:53,5\n2015-04-06 03:57:53,7\n2015-04-06 04:02:53,11\n2015-04-06 04:07:53,14\n2015-04-06 04:12:53,13\n2015-04-06 04:17:53,7\n2015-04-06 04:22:53,9\n2015-04-06 04:27:53,4\n2015-04-06 04:32:53,5\n2015-04-06 04:37:53,5\n2015-04-06 04:42:53,8\n2015-04-06 04:47:53,6\n2015-04-06 04:52:53,6\n2015-04-06 04:57:53,9\n2015-04-06 05:02:53,4\n2015-04-06 05:07:53,5\n2015-04-06 05:12:53,5\n2015-04-06 05:17:53,7\n2015-04-06 05:22:53,4\n2015-04-06 05:27:53,12\n2015-04-06 05:32:53,4\n2015-04-06 05:37:53,7\n2015-04-06 05:42:53,7\n2015-04-06 05:47:53,4\n2015-04-06 05:52:53,14\n2015-04-06 05:57:53,5\n2015-04-06 06:02:53,9\n2015-04-06 06:07:53,7\n2015-04-06 06:12:53,9\n2015-04-06 06:17:53,7\n2015-04-06 06:22:53,6\n2015-04-06 06:27:53,11\n2015-04-06 06:32:53,13\n2015-04-06 06:37:53,2\n2015-04-06 06:42:53,3\n2015-04-06 06:47:53,9\n2015-04-06 06:52:53,9\n2015-04-06 06:57:53,6\n2015-04-06 07:02:53,14\n2015-04-06 07:07:53,14\n2015-04-06 07:12:53,10\n2015-04-06 07:17:53,9\n2015-04-06 07:22:53,7\n2015-04-06 07:27:53,12\n2015-04-06 07:32:53,12\n2015-04-06 07:37:53,9\n2015-04-06 07:42:53,11\n2015-04-06 07:47:53,11\n2015-04-06 07:52:53,6\n2015-04-06 07:57:53,15\n2015-04-06 08:02:53,14\n2015-04-06 08:07:53,10\n2015-04-06 08:12:53,6\n2015-04-06 08:17:53,12\n2015-04-06 08:22:53,9\n2015-04-06 08:27:53,22\n2015-04-06 08:32:53,23\n2015-04-06 08:37:53,14\n2015-04-06 08:42:53,15\n2015-04-06 08:47:53,3\n2015-04-06 08:52:53,8\n2015-04-06 08:57:53,12\n2015-04-06 09:02:53,11\n2015-04-06 09:07:53,6\n2015-04-06 09:12:53,8\n2015-04-06 09:17:53,10\n2015-04-06 09:22:53,10\n2015-04-06 09:27:53,6\n2015-04-06 09:32:53,14\n2015-04-06 09:37:53,7\n2015-04-06 09:42:53,7\n2015-04-06 09:47:53,9\n2015-04-06 09:52:53,3\n2015-04-06 09:57:53,9\n2015-04-06 10:02:53,5\n2015-04-06 10:07:53,7\n2015-04-06 10:12:53,5\n2015-04-06 10:17:53,5\n2015-04-06 10:22:53,8\n2015-04-06 10:27:53,17\n2015-04-06 10:32:53,10\n2015-04-06 10:37:53,8\n2015-04-06 10:42:53,11\n2015-04-06 10:47:53,3\n2015-04-06 10:52:53,12\n2015-04-06 10:57:53,6\n2015-04-06 11:02:53,7\n2015-04-06 11:07:53,19\n2015-04-06 11:12:53,9\n2015-04-06 11:17:53,11\n2015-04-06 11:22:53,10\n2015-04-06 11:27:53,12\n2015-04-06 11:32:53,21\n2015-04-06 11:37:53,26\n2015-04-06 11:42:53,28\n2015-04-06 11:47:53,16\n2015-04-06 11:52:53,6\n2015-04-06 11:57:53,9\n2015-04-06 12:02:53,10\n2015-04-06 12:07:53,12\n2015-04-06 12:12:53,13\n2015-04-06 12:17:53,16\n2015-04-06 12:22:53,27\n2015-04-06 12:27:53,29\n2015-04-06 12:32:53,21\n2015-04-06 12:37:53,14\n2015-04-06 12:42:53,19\n2015-04-06 12:47:53,12\n2015-04-06 12:52:53,16\n2015-04-06 12:57:53,19\n2015-04-06 13:02:53,10\n2015-04-06 13:07:53,14\n2015-04-06 13:12:53,19\n2015-04-06 13:17:53,15\n2015-04-06 13:22:53,22\n2015-04-06 13:27:53,16\n2015-04-06 13:32:53,23\n2015-04-06 13:37:53,17\n2015-04-06 13:42:53,26\n2015-04-06 13:47:53,33\n2015-04-06 13:52:53,23\n2015-04-06 13:57:53,30\n2015-04-06 14:02:53,16\n2015-04-06 14:07:53,20\n2015-04-06 14:12:53,19\n2015-04-06 14:17:53,17\n2015-04-06 14:22:53,19\n2015-04-06 14:27:53,16\n2015-04-06 14:32:53,20\n2015-04-06 14:37:53,17\n2015-04-06 14:42:53,28\n2015-04-06 14:47:53,30\n2015-04-06 14:52:53,47\n2015-04-06 14:57:53,40\n2015-04-06 15:02:53,15\n2015-04-06 15:07:53,29\n2015-04-06 15:12:53,22\n2015-04-06 15:17:53,27\n2015-04-06 15:22:53,17\n2015-04-06 15:27:53,14\n2015-04-06 15:32:53,14\n2015-04-06 15:37:53,31\n2015-04-06 15:42:53,44\n2015-04-06 15:47:53,26\n2015-04-06 15:52:53,43\n2015-04-06 15:57:53,23\n2015-04-06 16:02:53,32\n2015-04-06 16:07:53,25\n2015-04-06 16:12:53,13\n2015-04-06 16:17:53,13\n2015-04-06 16:22:53,14\n2015-04-06 16:27:53,19\n2015-04-06 16:32:53,30\n2015-04-06 16:37:53,27\n2015-04-06 16:42:53,32\n2015-04-06 16:47:53,14\n2015-04-06 16:52:53,23\n2015-04-06 16:57:53,29\n2015-04-06 17:02:53,28\n2015-04-06 17:07:53,23\n2015-04-06 17:12:53,23\n2015-04-06 17:17:53,16\n2015-04-06 17:22:53,17\n2015-04-06 17:27:53,34\n2015-04-06 17:32:53,23\n2015-04-06 17:37:53,15\n2015-04-06 17:42:53,19\n2015-04-06 17:47:53,28\n2015-04-06 17:52:53,28\n2015-04-06 17:57:53,20\n2015-04-06 18:02:53,15\n2015-04-06 18:07:53,26\n2015-04-06 18:12:53,31\n2015-04-06 18:17:53,56\n2015-04-06 18:22:53,48\n2015-04-06 18:27:53,44\n2015-04-06 18:32:53,28\n2015-04-06 18:37:53,18\n2015-04-06 18:42:53,111\n2015-04-06 18:47:53,120\n2015-04-06 18:52:53,22\n2015-04-06 18:57:53,27\n2015-04-06 19:02:53,44\n2015-04-06 19:07:53,28\n2015-04-06 19:12:53,54\n2015-04-06 19:17:53,70\n2015-04-06 19:22:53,28\n2015-04-06 19:27:53,31\n2015-04-06 19:32:53,24\n2015-04-06 19:37:53,23\n2015-04-06 19:42:53,27\n2015-04-06 19:47:53,37\n2015-04-06 19:52:53,35\n2015-04-06 19:57:53,38\n2015-04-06 20:02:53,42\n2015-04-06 20:07:53,42\n2015-04-06 20:12:53,54\n2015-04-06 20:17:53,49\n2015-04-06 20:22:53,41\n2015-04-06 20:27:53,53\n2015-04-06 20:32:53,73\n2015-04-06 20:37:53,52\n2015-04-06 20:42:53,105\n2015-04-06 20:47:53,52\n2015-04-06 20:52:53,50\n2015-04-06 20:57:53,21\n2015-04-06 21:02:53,43\n2015-04-06 21:07:53,25\n2015-04-06 21:12:53,22\n2015-04-06 21:17:53,35\n2015-04-06 21:22:53,39\n2015-04-06 21:27:53,43\n2015-04-06 21:32:53,35\n2015-04-06 21:37:53,27\n2015-04-06 21:42:53,22\n2015-04-06 21:47:53,18\n2015-04-06 21:52:53,25\n2015-04-06 21:57:53,41\n2015-04-06 22:02:53,69\n2015-04-06 22:07:53,51\n2015-04-06 22:12:53,47\n2015-04-06 22:17:53,77\n2015-04-06 22:22:53,53\n2015-04-06 22:27:53,61\n2015-04-06 22:32:53,55\n2015-04-06 22:37:53,53\n2015-04-06 22:42:53,43\n2015-04-06 22:47:53,56\n2015-04-06 22:52:53,39\n2015-04-06 22:57:53,46\n2015-04-06 23:02:53,27\n2015-04-06 23:07:53,25\n2015-04-06 23:12:53,22\n2015-04-06 23:17:53,21\n2015-04-06 23:22:53,43\n2015-04-06 23:27:53,26\n2015-04-06 23:32:53,16\n2015-04-06 23:37:53,26\n2015-04-06 23:42:53,17\n2015-04-06 23:47:53,15\n2015-04-06 23:52:53,16\n2015-04-06 23:57:53,20\n2015-04-07 00:02:53,24\n2015-04-07 00:07:53,13\n2015-04-07 00:12:53,28\n2015-04-07 00:17:53,26\n2015-04-07 00:22:53,23\n2015-04-07 00:27:53,12\n2015-04-07 00:32:53,30\n2015-04-07 00:37:53,29\n2015-04-07 00:42:53,19\n2015-04-07 00:47:53,9\n2015-04-07 00:52:53,7\n2015-04-07 00:57:53,18\n2015-04-07 01:02:53,10\n2015-04-07 01:07:53,21\n2015-04-07 01:12:53,65\n2015-04-07 01:17:53,48\n2015-04-07 01:22:53,24\n2015-04-07 01:27:53,15\n2015-04-07 01:32:53,22\n2015-04-07 01:37:53,22\n2015-04-07 01:42:53,13\n2015-04-07 01:47:53,20\n2015-04-07 01:52:53,9\n2015-04-07 01:57:53,9\n2015-04-07 02:02:53,5\n2015-04-07 02:07:53,6\n2015-04-07 02:12:53,7\n2015-04-07 02:17:53,14\n2015-04-07 02:22:53,16\n2015-04-07 02:27:53,23\n2015-04-07 02:32:53,10\n2015-04-07 02:37:53,17\n2015-04-07 02:42:53,9\n2015-04-07 02:47:53,8\n2015-04-07 02:52:53,10\n2015-04-07 02:57:53,20\n2015-04-07 03:02:53,16\n2015-04-07 03:07:53,12\n2015-04-07 03:12:53,16\n2015-04-07 03:17:53,14\n2015-04-07 03:22:53,10\n2015-04-07 03:27:53,21\n2015-04-07 03:32:53,8\n2015-04-07 03:37:53,24\n2015-04-07 03:42:53,14\n2015-04-07 03:47:53,25\n2015-04-07 03:52:53,70\n2015-04-07 03:57:53,39\n2015-04-07 04:02:53,33\n2015-04-07 04:07:53,19\n2015-04-07 04:12:53,13\n2015-04-07 04:17:53,19\n2015-04-07 04:22:53,12\n2015-04-07 04:27:53,13\n2015-04-07 04:32:53,12\n2015-04-07 04:37:53,15\n2015-04-07 04:42:53,17\n2015-04-07 04:47:53,23\n2015-04-07 04:52:53,9\n2015-04-07 04:57:53,33\n2015-04-07 05:02:53,19\n2015-04-07 05:07:53,18\n2015-04-07 05:12:53,15\n2015-04-07 05:17:53,18\n2015-04-07 05:22:53,15\n2015-04-07 05:27:53,7\n2015-04-07 05:32:53,17\n2015-04-07 05:37:53,8\n2015-04-07 05:42:53,8\n2015-04-07 05:47:53,15\n2015-04-07 05:52:53,15\n2015-04-07 05:57:53,19\n2015-04-07 06:02:53,12\n2015-04-07 06:07:53,12\n2015-04-07 06:12:53,23\n2015-04-07 06:17:53,9\n2015-04-07 06:22:53,14\n2015-04-07 06:27:53,10\n2015-04-07 06:32:53,14\n2015-04-07 06:37:53,13\n2015-04-07 06:42:53,13\n2015-04-07 06:47:53,8\n2015-04-07 06:52:53,10\n2015-04-07 06:57:53,13\n2015-04-07 07:02:53,15\n2015-04-07 07:07:53,11\n2015-04-07 07:12:53,10\n2015-04-07 07:17:53,17\n2015-04-07 07:22:53,22\n2015-04-07 07:27:53,11\n2015-04-07 07:32:53,17\n2015-04-07 07:37:53,7\n2015-04-07 07:42:53,10\n2015-04-07 07:47:53,22\n2015-04-07 07:52:53,9\n2015-04-07 07:57:53,19\n2015-04-07 08:02:53,9\n2015-04-07 08:07:53,27\n2015-04-07 08:12:53,26\n2015-04-07 08:17:53,35\n2015-04-07 08:22:53,21\n2015-04-07 08:27:53,19\n2015-04-07 08:32:53,26\n2015-04-07 08:37:53,15\n2015-04-07 08:42:53,18\n2015-04-07 08:47:53,16\n2015-04-07 08:52:53,18\n2015-04-07 08:57:53,16\n2015-04-07 09:02:53,9\n2015-04-07 09:07:53,9\n2015-04-07 09:12:53,6\n2015-04-07 09:17:53,26\n2015-04-07 09:22:53,8\n2015-04-07 09:27:53,15\n2015-04-07 09:32:53,10\n2015-04-07 09:37:53,17\n2015-04-07 09:42:53,12\n2015-04-07 09:47:53,43\n2015-04-07 09:52:53,17\n2015-04-07 09:57:53,19\n2015-04-07 10:02:53,13\n2015-04-07 10:07:53,10\n2015-04-07 10:12:53,19\n2015-04-07 10:17:53,15\n2015-04-07 10:22:53,10\n2015-04-07 10:27:53,21\n2015-04-07 10:32:53,11\n2015-04-07 10:37:53,12\n2015-04-07 10:42:53,12\n2015-04-07 10:47:53,19\n2015-04-07 10:52:53,15\n2015-04-07 10:57:53,24\n2015-04-07 11:02:53,15\n2015-04-07 11:07:53,9\n2015-04-07 11:12:53,21\n2015-04-07 11:17:53,11\n2015-04-07 11:22:53,15\n2015-04-07 11:27:53,20\n2015-04-07 11:32:53,16\n2015-04-07 11:37:53,12\n2015-04-07 11:42:53,14\n2015-04-07 11:47:53,20\n2015-04-07 11:52:53,21\n2015-04-07 11:57:53,18\n2015-04-07 12:02:53,18\n2015-04-07 12:07:53,12\n2015-04-07 12:12:53,19\n2015-04-07 12:17:53,27\n2015-04-07 12:22:53,16\n2015-04-07 12:27:53,27\n2015-04-07 12:32:53,11\n2015-04-07 12:37:53,8\n2015-04-07 12:42:53,29\n2015-04-07 12:47:53,21\n2015-04-07 12:52:53,31\n2015-04-07 12:57:53,23\n2015-04-07 13:02:53,25\n2015-04-07 13:07:53,31\n2015-04-07 13:12:53,20\n2015-04-07 13:17:53,19\n2015-04-07 13:22:53,30\n2015-04-07 13:27:53,33\n2015-04-07 13:32:53,27\n2015-04-07 13:37:53,31\n2015-04-07 13:42:53,23\n2015-04-07 13:47:53,25\n2015-04-07 13:52:53,25\n2015-04-07 13:57:53,32\n2015-04-07 14:02:53,32\n2015-04-07 14:07:53,16\n2015-04-07 14:12:53,22\n2015-04-07 14:17:53,17\n2015-04-07 14:22:53,30\n2015-04-07 14:27:53,18\n2015-04-07 14:32:53,22\n2015-04-07 14:37:53,29\n2015-04-07 14:42:53,21\n2015-04-07 14:47:53,24\n2015-04-07 14:52:53,27\n2015-04-07 14:57:53,27\n2015-04-07 15:02:53,33\n2015-04-07 15:07:53,45\n2015-04-07 15:12:53,35\n2015-04-07 15:17:53,35\n2015-04-07 15:22:53,30\n2015-04-07 15:27:53,34\n2015-04-07 15:32:53,36\n2015-04-07 15:37:53,67\n2015-04-07 15:42:53,60\n2015-04-07 15:47:53,31\n2015-04-07 15:52:53,36\n2015-04-07 15:57:53,54\n2015-04-07 16:02:53,70\n2015-04-07 16:07:53,31\n2015-04-07 16:12:53,26\n2015-04-07 16:17:53,36\n2015-04-07 16:22:53,27\n2015-04-07 16:27:53,34\n2015-04-07 16:32:53,35\n2015-04-07 16:37:53,36\n2015-04-07 16:42:53,22\n2015-04-07 16:47:53,40\n2015-04-07 16:52:53,28\n2015-04-07 16:57:53,20\n2015-04-07 17:02:53,30\n2015-04-07 17:07:53,34\n2015-04-07 17:12:53,34\n2015-04-07 17:17:53,69\n2015-04-07 17:22:53,27\n2015-04-07 17:27:53,48\n2015-04-07 17:32:53,30\n2015-04-07 17:37:53,22\n2015-04-07 17:42:53,30\n2015-04-07 17:47:53,34\n2015-04-07 17:52:53,30\n2015-04-07 17:57:53,31\n2015-04-07 18:02:53,30\n2015-04-07 18:07:53,41\n2015-04-07 18:12:53,27\n2015-04-07 18:17:53,28\n2015-04-07 18:22:53,29\n2015-04-07 18:27:53,37\n2015-04-07 18:32:53,22\n2015-04-07 18:37:53,30\n2015-04-07 18:42:53,27\n2015-04-07 18:47:53,28\n2015-04-07 18:52:53,23\n2015-04-07 18:57:53,26\n2015-04-07 19:02:53,20\n2015-04-07 19:07:53,26\n2015-04-07 19:12:53,34\n2015-04-07 19:17:53,15\n2015-04-07 19:22:53,19\n2015-04-07 19:27:53,16\n2015-04-07 19:32:53,23\n2015-04-07 19:37:53,29\n2015-04-07 19:42:53,38\n2015-04-07 19:47:53,23\n2015-04-07 19:52:53,28\n2015-04-07 19:57:53,16\n2015-04-07 20:02:53,25\n2015-04-07 20:07:53,20\n2015-04-07 20:12:53,24\n2015-04-07 20:17:53,28\n2015-04-07 20:22:53,30\n2015-04-07 20:27:53,23\n2015-04-07 20:32:53,30\n2015-04-07 20:37:53,31\n2015-04-07 20:42:53,24\n2015-04-07 20:47:53,16\n2015-04-07 20:52:53,62\n2015-04-07 20:57:53,62\n2015-04-07 21:02:53,47\n2015-04-07 21:07:53,44\n2015-04-07 21:12:53,44\n2015-04-07 21:17:53,38\n2015-04-07 21:22:53,39\n2015-04-07 21:27:53,18\n2015-04-07 21:32:53,25\n2015-04-07 21:37:53,21\n2015-04-07 21:42:53,17\n2015-04-07 21:47:53,24\n2015-04-07 21:52:53,17\n2015-04-07 21:57:53,32\n2015-04-07 22:02:53,26\n2015-04-07 22:07:53,12\n2015-04-07 22:12:53,16\n2015-04-07 22:17:53,16\n2015-04-07 22:22:53,24\n2015-04-07 22:27:53,15\n2015-04-07 22:32:53,20\n2015-04-07 22:37:53,19\n2015-04-07 22:42:53,16\n2015-04-07 22:47:53,26\n2015-04-07 22:52:53,27\n2015-04-07 22:57:53,8\n2015-04-07 23:02:53,26\n2015-04-07 23:07:53,17\n2015-04-07 23:12:53,16\n2015-04-07 23:17:53,14\n2015-04-07 23:22:53,18\n2015-04-07 23:27:53,60\n2015-04-07 23:32:53,19\n2015-04-07 23:37:53,19\n2015-04-07 23:42:53,15\n2015-04-07 23:47:53,14\n2015-04-07 23:52:53,19\n2015-04-07 23:57:53,10\n2015-04-08 00:02:53,23\n2015-04-08 00:07:53,21\n2015-04-08 00:12:53,14\n2015-04-08 00:17:53,11\n2015-04-08 00:22:53,15\n2015-04-08 00:27:53,21\n2015-04-08 00:32:53,18\n2015-04-08 00:37:53,16\n2015-04-08 00:42:53,17\n2015-04-08 00:47:53,5\n2015-04-08 00:52:53,9\n2015-04-08 00:57:53,12\n2015-04-08 01:02:53,14\n2015-04-08 01:07:53,16\n2015-04-08 01:12:53,12\n2015-04-08 01:17:53,14\n2015-04-08 01:22:53,14\n2015-04-08 01:27:53,13\n2015-04-08 01:32:53,20\n2015-04-08 01:37:53,19\n2015-04-08 01:42:53,13\n2015-04-08 01:47:53,14\n2015-04-08 01:52:53,13\n2015-04-08 01:57:53,27\n2015-04-08 02:02:53,21\n2015-04-08 02:07:53,16\n2015-04-08 02:12:53,7\n2015-04-08 02:17:53,8\n2015-04-08 02:22:53,6\n2015-04-08 02:27:53,11\n2015-04-08 02:32:53,10\n2015-04-08 02:37:53,17\n2015-04-08 02:42:53,16\n2015-04-08 02:47:53,6\n2015-04-08 02:52:53,21\n2015-04-08 02:57:53,14\n2015-04-08 03:02:53,11\n2015-04-08 03:07:53,12\n2015-04-08 03:12:53,11\n2015-04-08 03:17:53,14\n2015-04-08 03:22:53,10\n2015-04-08 03:27:53,15\n2015-04-08 03:32:53,7\n2015-04-08 03:37:53,10\n2015-04-08 03:42:53,5\n2015-04-08 03:47:53,7\n2015-04-08 03:52:53,13\n2015-04-08 03:57:53,21\n2015-04-08 04:02:53,25\n2015-04-08 04:07:53,17\n2015-04-08 04:12:53,9\n2015-04-08 04:17:53,11\n2015-04-08 04:22:53,10\n2015-04-08 04:27:53,23\n2015-04-08 04:32:53,12\n2015-04-08 04:37:53,11\n2015-04-08 04:42:53,15\n2015-04-08 04:47:53,9\n2015-04-08 04:52:53,17\n2015-04-08 04:57:53,13\n2015-04-08 05:02:53,12\n2015-04-08 05:07:53,9\n2015-04-08 05:12:53,23\n2015-04-08 05:17:53,20\n2015-04-08 05:22:53,12\n2015-04-08 05:27:53,7\n2015-04-08 05:32:53,9\n2015-04-08 05:37:53,9\n2015-04-08 05:42:53,3\n2015-04-08 05:47:53,10\n2015-04-08 05:52:53,12\n2015-04-08 05:57:53,9\n2015-04-08 06:02:53,11\n2015-04-08 06:07:53,11\n2015-04-08 06:12:53,21\n2015-04-08 06:17:53,17\n2015-04-08 06:22:53,14\n2015-04-08 06:27:53,15\n2015-04-08 06:32:53,11\n2015-04-08 06:37:53,10\n2015-04-08 06:42:53,9\n2015-04-08 06:47:53,14\n2015-04-08 06:52:53,10\n2015-04-08 06:57:53,14\n2015-04-08 07:02:53,11\n2015-04-08 07:07:53,14\n2015-04-08 07:12:53,8\n2015-04-08 07:17:53,17\n2015-04-08 07:22:53,11\n2015-04-08 07:27:53,24\n2015-04-08 07:32:53,19\n2015-04-08 07:37:53,9\n2015-04-08 07:42:53,14\n2015-04-08 07:47:53,18\n2015-04-08 07:52:53,14\n2015-04-08 07:57:53,6\n2015-04-08 08:02:53,12\n2015-04-08 08:07:53,17\n2015-04-08 08:12:53,8\n2015-04-08 08:17:53,13\n2015-04-08 08:22:53,6\n2015-04-08 08:27:53,13\n2015-04-08 08:32:53,18\n2015-04-08 08:37:53,14\n2015-04-08 08:42:53,16\n2015-04-08 08:47:53,16\n2015-04-08 08:52:53,23\n2015-04-08 08:57:53,11\n2015-04-08 09:02:53,17\n2015-04-08 09:07:53,13\n2015-04-08 09:12:53,6\n2015-04-08 09:17:53,6\n2015-04-08 09:22:53,24\n2015-04-08 09:27:53,12\n2015-04-08 09:32:53,11\n2015-04-08 09:37:53,11\n2015-04-08 09:42:53,12\n2015-04-08 09:47:53,10\n2015-04-08 09:52:53,18\n2015-04-08 09:57:53,22\n2015-04-08 10:02:53,8\n2015-04-08 10:07:53,5\n2015-04-08 10:12:53,10\n2015-04-08 10:17:53,16\n2015-04-08 10:22:53,11\n2015-04-08 10:27:53,16\n2015-04-08 10:32:53,8\n2015-04-08 10:37:53,11\n2015-04-08 10:42:53,13\n2015-04-08 10:47:53,16\n2015-04-08 10:52:53,16\n2015-04-08 10:57:53,10\n2015-04-08 11:02:53,17\n2015-04-08 11:07:53,12\n2015-04-08 11:12:53,15\n2015-04-08 11:17:53,10\n2015-04-08 11:22:53,5\n2015-04-08 11:27:53,15\n2015-04-08 11:32:53,22\n2015-04-08 11:37:53,22\n2015-04-08 11:42:53,26\n2015-04-08 11:47:53,19\n2015-04-08 11:52:53,16\n2015-04-08 11:57:53,19\n2015-04-08 12:02:53,23\n2015-04-08 12:07:53,17\n2015-04-08 12:12:53,14\n2015-04-08 12:17:53,18\n2015-04-08 12:22:53,12\n2015-04-08 12:27:53,13\n2015-04-08 12:32:53,25\n2015-04-08 12:37:53,28\n2015-04-08 12:42:53,32\n2015-04-08 12:47:53,22\n2015-04-08 12:52:53,22\n2015-04-08 12:57:53,29\n2015-04-08 13:02:53,19\n2015-04-08 13:07:53,20\n2015-04-08 13:12:53,21\n2015-04-08 13:17:53,16\n2015-04-08 13:22:53,23\n2015-04-08 13:27:53,15\n2015-04-08 13:32:53,23\n2015-04-08 13:37:53,17\n2015-04-08 13:42:53,29\n2015-04-08 13:47:53,18\n2015-04-08 13:52:53,27\n2015-04-08 13:57:53,23\n2015-04-08 14:02:53,23\n2015-04-08 14:07:53,14\n2015-04-08 14:12:53,23\n2015-04-08 14:17:53,28\n2015-04-08 14:22:53,19\n2015-04-08 14:27:53,36\n2015-04-08 14:32:53,23\n2015-04-08 14:37:53,21\n2015-04-08 14:42:53,30\n2015-04-08 14:47:53,18\n2015-04-08 14:52:53,20\n2015-04-08 14:57:53,28\n2015-04-08 15:02:53,25\n2015-04-08 15:07:53,19\n2015-04-08 15:12:53,21\n2015-04-08 15:17:53,22\n2015-04-08 15:22:53,29\n2015-04-08 15:27:53,32\n2015-04-08 15:32:53,23\n2015-04-08 15:37:53,22\n2015-04-08 15:42:53,25\n2015-04-08 15:47:53,25\n2015-04-08 15:52:53,33\n2015-04-08 15:57:53,31\n2015-04-08 16:02:53,24\n2015-04-08 16:07:53,24\n2015-04-08 16:12:53,36\n2015-04-08 16:17:53,23\n2015-04-08 16:22:53,24\n2015-04-08 16:27:53,44\n2015-04-08 16:32:53,41\n2015-04-08 16:37:53,41\n2015-04-08 16:42:53,47\n2015-04-08 16:47:53,21\n2015-04-08 16:52:53,25\n2015-04-08 16:57:53,30\n2015-04-08 17:02:53,45\n2015-04-08 17:07:53,33\n2015-04-08 17:12:53,30\n2015-04-08 17:17:53,17\n2015-04-08 17:22:53,25\n2015-04-08 17:27:53,33\n2015-04-08 17:32:53,23\n2015-04-08 17:37:53,34\n2015-04-08 17:42:53,25\n2015-04-08 17:47:53,38\n2015-04-08 17:52:53,52\n2015-04-08 17:57:53,40\n2015-04-08 18:02:53,37\n2015-04-08 18:07:53,33\n2015-04-08 18:12:53,29\n2015-04-08 18:17:53,28\n2015-04-08 18:22:53,29\n2015-04-08 18:27:53,23\n2015-04-08 18:32:53,26\n2015-04-08 18:37:53,27\n2015-04-08 18:42:53,16\n2015-04-08 18:47:53,25\n2015-04-08 18:52:53,33\n2015-04-08 18:57:53,28\n2015-04-08 19:02:53,36\n2015-04-08 19:07:53,36\n2015-04-08 19:12:53,37\n2015-04-08 19:17:53,22\n2015-04-08 19:22:53,29\n2015-04-08 19:27:53,26\n2015-04-08 19:32:53,21\n2015-04-08 19:37:53,36\n2015-04-08 19:42:53,17\n2015-04-08 19:47:53,28\n2015-04-08 19:52:53,23\n2015-04-08 19:57:53,42\n2015-04-08 20:02:53,31\n2015-04-08 20:07:53,38\n2015-04-08 20:12:53,18\n2015-04-08 20:17:53,26\n2015-04-08 20:22:53,14\n2015-04-08 20:27:53,28\n2015-04-08 20:32:53,21\n2015-04-08 20:37:53,18\n2015-04-08 20:42:53,21\n2015-04-08 20:47:53,26\n2015-04-08 20:52:53,31\n2015-04-08 20:57:53,33\n2015-04-08 21:02:53,23\n2015-04-08 21:07:53,25\n2015-04-08 21:12:53,21\n2015-04-08 21:17:53,22\n2015-04-08 21:22:53,26\n2015-04-08 21:27:53,23\n2015-04-08 21:32:53,28\n2015-04-08 21:37:53,17\n2015-04-08 21:42:53,30\n2015-04-08 21:47:53,18\n2015-04-08 21:52:53,17\n2015-04-08 21:57:53,16\n2015-04-08 22:02:53,18\n2015-04-08 22:07:53,15\n2015-04-08 22:12:53,24\n2015-04-08 22:17:53,18\n2015-04-08 22:22:53,10\n2015-04-08 22:27:53,20\n2015-04-08 22:32:53,22\n2015-04-08 22:37:53,15\n2015-04-08 22:42:53,20\n2015-04-08 22:47:53,14\n2015-04-08 22:52:53,18\n2015-04-08 22:57:53,56\n2015-04-08 23:02:53,34\n2015-04-08 23:07:53,26\n2015-04-08 23:12:53,19\n2015-04-08 23:17:53,19\n2015-04-08 23:22:53,21\n2015-04-08 23:27:53,17\n2015-04-08 23:32:53,27\n2015-04-08 23:37:53,17\n2015-04-08 23:42:53,15\n2015-04-08 23:47:53,14\n2015-04-08 23:52:53,18\n2015-04-08 23:57:53,12\n2015-04-09 00:02:53,22\n2015-04-09 00:07:53,12\n2015-04-09 00:12:53,17\n2015-04-09 00:17:53,15\n2015-04-09 00:22:53,20\n2015-04-09 00:27:53,21\n2015-04-09 00:32:53,22\n2015-04-09 00:37:53,13\n2015-04-09 00:42:53,23\n2015-04-09 00:47:53,16\n2015-04-09 00:52:53,28\n2015-04-09 00:57:53,20\n2015-04-09 01:02:53,18\n2015-04-09 01:07:53,13\n2015-04-09 01:12:53,24\n2015-04-09 01:17:53,21\n2015-04-09 01:22:53,20\n2015-04-09 01:27:53,18\n2015-04-09 01:32:53,13\n2015-04-09 01:37:53,15\n2015-04-09 01:42:53,18\n2015-04-09 01:47:53,22\n2015-04-09 01:52:53,18\n2015-04-09 01:57:53,19\n2015-04-09 02:02:53,16\n2015-04-09 02:07:53,11\n2015-04-09 02:12:53,22\n2015-04-09 02:17:53,16\n2015-04-09 02:22:53,15\n2015-04-09 02:27:53,27\n2015-04-09 02:32:53,3\n2015-04-09 02:37:53,11\n2015-04-09 02:42:53,14\n2015-04-09 02:47:53,6\n2015-04-09 02:52:53,31\n2015-04-09 02:57:53,33\n2015-04-09 03:02:53,35\n2015-04-09 03:07:53,23\n2015-04-09 03:12:53,16\n2015-04-09 03:17:53,11\n2015-04-09 03:22:53,11\n2015-04-09 03:27:53,15\n2015-04-09 03:32:53,16\n2015-04-09 03:37:53,13\n2015-04-09 03:42:53,12\n2015-04-09 03:47:53,17\n2015-04-09 03:52:53,13\n2015-04-09 03:57:53,8\n2015-04-09 04:02:53,7\n2015-04-09 04:07:53,13\n2015-04-09 04:12:53,13\n2015-04-09 04:17:53,13\n2015-04-09 04:22:53,10\n2015-04-09 04:27:53,15\n2015-04-09 04:32:53,8\n2015-04-09 04:37:53,9\n2015-04-09 04:42:53,13\n2015-04-09 04:47:53,17\n2015-04-09 04:52:53,17\n2015-04-09 04:57:53,12\n2015-04-09 05:02:53,12\n2015-04-09 05:07:53,10\n2015-04-09 05:12:53,13\n2015-04-09 05:17:53,7\n2015-04-09 05:22:53,15\n2015-04-09 05:27:53,17\n2015-04-09 05:32:53,15\n2015-04-09 05:37:53,30\n2015-04-09 05:42:53,16\n2015-04-09 05:47:53,3\n2015-04-09 05:52:53,13\n2015-04-09 05:57:53,15\n2015-04-09 06:02:53,8\n2015-04-09 06:07:53,11\n2015-04-09 06:12:53,11\n2015-04-09 06:17:53,14\n2015-04-09 06:22:53,16\n2015-04-09 06:27:53,13\n2015-04-09 06:32:53,5\n2015-04-09 06:37:53,8\n2015-04-09 06:42:53,10\n2015-04-09 06:47:53,6\n2015-04-09 06:52:53,17\n2015-04-09 06:57:53,16\n2015-04-09 07:02:53,10\n2015-04-09 07:07:53,5\n2015-04-09 07:12:53,17\n2015-04-09 07:17:53,17\n2015-04-09 07:22:53,25\n2015-04-09 07:27:53,17\n2015-04-09 07:32:53,13\n2015-04-09 07:37:53,7\n2015-04-09 07:42:53,20\n2015-04-09 07:47:53,9\n2015-04-09 07:52:53,19\n2015-04-09 07:57:53,12\n2015-04-09 08:02:53,18\n2015-04-09 08:07:53,17\n2015-04-09 08:12:53,12\n2015-04-09 08:17:53,16\n2015-04-09 08:22:53,9\n2015-04-09 08:27:53,9\n2015-04-09 08:32:53,16\n2015-04-09 08:37:53,10\n2015-04-09 08:42:53,14\n2015-04-09 08:47:53,21\n2015-04-09 08:52:53,23\n2015-04-09 08:57:53,16\n2015-04-09 09:02:53,17\n2015-04-09 09:07:53,13\n2015-04-09 09:12:53,12\n2015-04-09 09:17:53,14\n2015-04-09 09:22:53,7\n2015-04-09 09:27:53,11\n2015-04-09 09:32:53,6\n2015-04-09 09:37:53,11\n2015-04-09 09:42:53,14\n2015-04-09 09:47:53,9\n2015-04-09 09:52:53,9\n2015-04-09 09:57:53,17\n2015-04-09 10:02:53,8\n2015-04-09 10:07:53,7\n2015-04-09 10:12:53,19\n2015-04-09 10:17:53,10\n2015-04-09 10:22:53,13\n2015-04-09 10:27:53,13\n2015-04-09 10:32:53,6\n2015-04-09 10:37:53,14\n2015-04-09 10:42:53,10\n2015-04-09 10:47:53,11\n2015-04-09 10:52:53,11\n2015-04-09 10:57:53,17\n2015-04-09 11:02:53,10\n2015-04-09 11:07:53,11\n2015-04-09 11:12:53,23\n2015-04-09 11:17:53,24\n2015-04-09 11:22:53,14\n2015-04-09 11:27:53,10\n2015-04-09 11:32:53,6\n2015-04-09 11:37:53,12\n2015-04-09 11:42:53,11\n2015-04-09 11:47:53,11\n2015-04-09 11:52:53,10\n2015-04-09 11:57:53,18\n2015-04-09 12:02:53,22\n2015-04-09 12:07:53,16\n2015-04-09 12:12:53,15\n2015-04-09 12:17:53,16\n2015-04-09 12:22:53,21\n2015-04-09 12:27:53,11\n2015-04-09 12:32:53,13\n2015-04-09 12:37:53,17\n2015-04-09 12:42:53,12\n2015-04-09 12:47:53,17\n2015-04-09 12:52:53,27\n2015-04-09 12:57:53,17\n2015-04-09 13:02:53,37\n2015-04-09 13:07:53,27\n2015-04-09 13:12:53,52\n2015-04-09 13:17:53,25\n2015-04-09 13:22:53,23\n2015-04-09 13:27:53,26\n2015-04-09 13:32:53,18\n2015-04-09 13:37:53,18\n2015-04-09 13:42:53,13\n2015-04-09 13:47:53,15\n2015-04-09 13:52:53,12\n2015-04-09 13:57:53,14\n2015-04-09 14:02:53,30\n2015-04-09 14:07:53,24\n2015-04-09 14:12:53,34\n2015-04-09 14:17:53,36\n2015-04-09 14:22:53,33\n2015-04-09 14:27:53,31\n2015-04-09 14:32:53,18\n2015-04-09 14:37:53,16\n2015-04-09 14:42:53,33\n2015-04-09 14:47:53,22\n2015-04-09 14:52:53,22\n2015-04-09 14:57:53,33\n2015-04-09 15:02:53,27\n2015-04-09 15:07:53,26\n2015-04-09 15:12:53,25\n2015-04-09 15:17:53,14\n2015-04-09 15:22:53,20\n2015-04-09 15:27:53,22\n2015-04-09 15:32:53,22\n2015-04-09 15:37:53,27\n2015-04-09 15:42:53,40\n2015-04-09 15:47:53,25\n2015-04-09 15:52:53,35\n2015-04-09 15:57:53,31\n2015-04-09 16:02:53,26\n2015-04-09 16:07:53,40\n2015-04-09 16:12:53,19\n2015-04-09 16:17:53,28\n2015-04-09 16:22:53,25\n2015-04-09 16:27:53,28\n2015-04-09 16:32:53,16\n2015-04-09 16:37:53,13\n2015-04-09 16:42:53,17\n2015-04-09 16:47:53,36\n2015-04-09 16:52:53,23\n2015-04-09 16:57:53,36\n2015-04-09 17:02:53,27\n2015-04-09 17:07:53,24\n2015-04-09 17:12:53,15\n2015-04-09 17:17:53,19\n2015-04-09 17:22:53,29\n2015-04-09 17:27:53,37\n2015-04-09 17:32:53,23\n2015-04-09 17:37:53,26\n2015-04-09 17:42:53,20\n2015-04-09 17:47:53,23\n2015-04-09 17:52:53,16\n2015-04-09 17:57:53,20\n2015-04-09 18:02:53,21\n2015-04-09 18:07:53,26\n2015-04-09 18:12:53,23\n2015-04-09 18:17:53,23\n2015-04-09 18:22:53,14\n2015-04-09 18:27:53,29\n2015-04-09 18:32:53,22\n2015-04-09 18:37:53,29\n2015-04-09 18:42:53,26\n2015-04-09 18:47:53,39\n2015-04-09 18:52:53,22\n2015-04-09 18:57:53,25\n2015-04-09 19:02:53,33\n2015-04-09 19:07:53,28\n2015-04-09 19:12:53,15\n2015-04-09 19:17:53,23\n2015-04-09 19:22:53,17\n2015-04-09 19:27:53,21\n2015-04-09 19:32:53,23\n2015-04-09 19:37:53,18\n2015-04-09 19:42:53,13\n2015-04-09 19:47:53,17\n2015-04-09 19:52:53,21\n2015-04-09 19:57:53,25\n2015-04-09 20:02:53,51\n2015-04-09 20:07:53,39\n2015-04-09 20:12:53,45\n2015-04-09 20:17:53,22\n2015-04-09 20:22:53,27\n2015-04-09 20:27:53,19\n2015-04-09 20:32:53,32\n2015-04-09 20:37:53,22\n2015-04-09 20:42:53,27\n2015-04-09 20:47:53,20\n2015-04-09 20:52:53,23\n2015-04-09 20:57:53,24\n2015-04-09 21:02:53,12\n2015-04-09 21:07:53,17\n2015-04-09 21:12:53,26\n2015-04-09 21:17:53,8\n2015-04-09 21:22:53,20\n2015-04-09 21:27:53,28\n2015-04-09 21:32:53,33\n2015-04-09 21:37:53,46\n2015-04-09 21:42:53,20\n2015-04-09 21:47:53,14\n2015-04-09 21:52:53,11\n2015-04-09 21:57:53,16\n2015-04-09 22:02:53,24\n2015-04-09 22:07:53,32\n2015-04-09 22:12:53,44\n2015-04-09 22:17:53,24\n2015-04-09 22:22:53,22\n2015-04-09 22:27:53,14\n2015-04-09 22:32:53,22\n2015-04-09 22:37:53,22\n2015-04-09 22:42:53,19\n2015-04-09 22:47:53,22\n2015-04-09 22:52:53,17\n2015-04-09 22:57:53,15\n2015-04-09 23:02:53,17\n2015-04-09 23:07:53,20\n2015-04-09 23:12:53,8\n2015-04-09 23:17:53,24\n2015-04-09 23:22:53,26\n2015-04-09 23:27:53,15\n2015-04-09 23:32:53,15\n2015-04-09 23:37:53,12\n2015-04-09 23:42:53,12\n2015-04-09 23:47:53,8\n2015-04-09 23:52:53,14\n2015-04-09 23:57:53,17\n2015-04-10 00:02:53,18\n2015-04-10 00:07:53,36\n2015-04-10 00:12:53,21\n2015-04-10 00:17:53,18\n2015-04-10 00:22:53,25\n2015-04-10 00:27:53,21\n2015-04-10 00:32:53,23\n2015-04-10 00:37:53,21\n2015-04-10 00:42:53,17\n2015-04-10 00:47:53,15\n2015-04-10 00:52:53,13\n2015-04-10 00:57:53,23\n2015-04-10 01:02:53,9\n2015-04-10 01:07:53,9\n2015-04-10 01:12:53,16\n2015-04-10 01:17:53,16\n2015-04-10 01:22:53,8\n2015-04-10 01:27:53,18\n2015-04-10 01:32:53,15\n2015-04-10 01:37:53,19\n2015-04-10 01:42:53,14\n2015-04-10 01:47:53,13\n2015-04-10 01:52:53,15\n2015-04-10 01:57:53,15\n2015-04-10 02:02:53,13\n2015-04-10 02:07:53,12\n2015-04-10 02:12:53,10\n2015-04-10 02:17:53,8\n2015-04-10 02:22:53,11\n2015-04-10 02:27:53,18\n2015-04-10 02:32:53,20\n2015-04-10 02:37:53,16\n2015-04-10 02:42:53,20\n2015-04-10 02:47:53,14\n2015-04-10 02:52:53,18\n2015-04-10 02:57:53,23\n2015-04-10 03:02:53,29\n2015-04-10 03:07:53,13\n2015-04-10 03:12:53,10\n2015-04-10 03:17:53,7\n2015-04-10 03:22:53,5\n2015-04-10 03:27:53,12\n2015-04-10 03:32:53,11\n2015-04-10 03:37:53,14\n2015-04-10 03:42:53,15\n2015-04-10 03:47:53,4\n2015-04-10 03:52:53,3\n2015-04-10 03:57:53,26\n2015-04-10 04:02:53,11\n2015-04-10 04:07:53,11\n2015-04-10 04:12:53,11\n2015-04-10 04:17:53,6\n2015-04-10 04:22:53,11\n2015-04-10 04:27:53,8\n2015-04-10 04:32:53,23\n2015-04-10 04:37:53,13\n2015-04-10 04:42:53,20\n2015-04-10 04:47:53,11\n2015-04-10 04:52:53,5\n2015-04-10 04:57:53,13\n2015-04-10 05:02:53,5\n2015-04-10 05:07:53,8\n2015-04-10 05:12:53,46\n2015-04-10 05:17:53,34\n2015-04-10 05:22:53,38\n2015-04-10 05:27:53,18\n2015-04-10 05:32:53,32\n2015-04-10 05:37:53,18\n2015-04-10 05:42:53,15\n2015-04-10 05:47:53,23\n2015-04-10 05:52:53,23\n2015-04-10 05:57:53,12\n2015-04-10 06:02:53,11\n2015-04-10 06:07:53,21\n2015-04-10 06:12:53,16\n2015-04-10 06:17:53,7\n2015-04-10 06:22:53,11\n2015-04-10 06:27:53,9\n2015-04-10 06:32:53,8\n2015-04-10 06:37:53,10\n2015-04-10 06:42:53,13\n2015-04-10 06:47:53,10\n2015-04-10 06:52:53,7\n2015-04-10 06:57:53,10\n2015-04-10 07:02:53,35\n2015-04-10 07:07:53,17\n2015-04-10 07:12:53,22\n2015-04-10 07:17:53,12\n2015-04-10 07:22:53,18\n2015-04-10 07:27:53,15\n2015-04-10 07:32:53,11\n2015-04-10 07:37:53,14\n2015-04-10 07:42:53,11\n2015-04-10 07:47:53,5\n2015-04-10 07:52:53,16\n2015-04-10 07:57:53,17\n2015-04-10 08:02:53,19\n2015-04-10 08:07:53,20\n2015-04-10 08:12:53,14\n2015-04-10 08:17:53,13\n2015-04-10 08:22:53,9\n2015-04-10 08:27:53,7\n2015-04-10 08:32:53,8\n2015-04-10 08:37:53,15\n2015-04-10 08:42:53,12\n2015-04-10 08:47:53,16\n2015-04-10 08:52:53,14\n2015-04-10 08:57:53,17\n2015-04-10 09:02:53,22\n2015-04-10 09:07:53,23\n2015-04-10 09:12:53,13\n2015-04-10 09:17:53,16\n2015-04-10 09:22:53,12\n2015-04-10 09:27:53,25\n2015-04-10 09:32:53,35\n2015-04-10 09:37:53,23\n2015-04-10 09:42:53,24\n2015-04-10 09:47:53,32\n2015-04-10 09:52:53,16\n2015-04-10 09:57:53,29\n2015-04-10 10:02:53,22\n2015-04-10 10:07:53,12\n2015-04-10 10:12:53,16\n2015-04-10 10:17:53,9\n2015-04-10 10:22:53,3\n2015-04-10 10:27:53,12\n2015-04-10 10:32:53,14\n2015-04-10 10:37:53,33\n2015-04-10 10:42:53,13\n2015-04-10 10:47:53,14\n2015-04-10 10:52:53,12\n2015-04-10 10:57:53,20\n2015-04-10 11:02:53,22\n2015-04-10 11:07:53,15\n2015-04-10 11:12:53,17\n2015-04-10 11:17:53,11\n2015-04-10 11:22:53,12\n2015-04-10 11:27:53,16\n2015-04-10 11:32:53,15\n2015-04-10 11:37:53,12\n2015-04-10 11:42:53,16\n2015-04-10 11:47:53,11\n2015-04-10 11:52:53,13\n2015-04-10 11:57:53,18\n2015-04-10 12:02:53,19\n2015-04-10 12:07:53,15\n2015-04-10 12:12:53,17\n2015-04-10 12:17:53,9\n2015-04-10 12:22:53,16\n2015-04-10 12:27:53,15\n2015-04-10 12:32:53,19\n2015-04-10 12:37:53,18\n2015-04-10 12:42:53,19\n2015-04-10 12:47:53,13\n2015-04-10 12:52:53,18\n2015-04-10 12:57:53,20\n2015-04-10 13:02:53,13\n2015-04-10 13:07:53,17\n2015-04-10 13:12:53,14\n2015-04-10 13:17:53,20\n2015-04-10 13:22:53,19\n2015-04-10 13:27:53,25\n2015-04-10 13:32:53,11\n2015-04-10 13:37:53,16\n2015-04-10 13:42:53,18\n2015-04-10 13:47:53,26\n2015-04-10 13:52:53,10\n2015-04-10 13:57:53,17\n2015-04-10 14:02:53,34\n2015-04-10 14:07:53,29\n2015-04-10 14:12:53,24\n2015-04-10 14:17:53,11\n2015-04-10 14:22:53,18\n2015-04-10 14:27:53,12\n2015-04-10 14:32:53,9\n2015-04-10 14:37:53,18\n2015-04-10 14:42:53,21\n2015-04-10 14:47:53,19\n2015-04-10 14:52:53,19\n2015-04-10 14:57:53,28\n2015-04-10 15:02:53,27\n2015-04-10 15:07:53,18\n2015-04-10 15:12:53,27\n2015-04-10 15:17:53,18\n2015-04-10 15:22:53,20\n2015-04-10 15:27:53,18\n2015-04-10 15:32:53,21\n2015-04-10 15:37:53,17\n2015-04-10 15:42:53,23\n2015-04-10 15:47:53,28\n2015-04-10 15:52:53,18\n2015-04-10 15:57:53,29\n2015-04-10 16:02:53,18\n2015-04-10 16:07:53,19\n2015-04-10 16:12:53,25\n2015-04-10 16:17:53,10\n2015-04-10 16:22:53,20\n2015-04-10 16:27:53,26\n2015-04-10 16:32:53,16\n2015-04-10 16:37:53,12\n2015-04-10 16:42:53,14\n2015-04-10 16:47:53,18\n2015-04-10 16:52:53,20\n2015-04-10 16:57:53,24\n2015-04-10 17:02:53,17\n2015-04-10 17:07:53,30\n2015-04-10 17:12:53,19\n2015-04-10 17:17:53,11\n2015-04-10 17:22:53,18\n2015-04-10 17:27:53,18\n2015-04-10 17:32:53,16\n2015-04-10 17:37:53,19\n2015-04-10 17:42:53,17\n2015-04-10 17:47:53,11\n2015-04-10 17:52:53,20\n2015-04-10 17:57:53,21\n2015-04-10 18:02:53,23\n2015-04-10 18:07:53,31\n2015-04-10 18:12:53,28\n2015-04-10 18:17:53,35\n2015-04-10 18:22:53,52\n2015-04-10 18:27:53,25\n2015-04-10 18:32:53,16\n2015-04-10 18:37:53,18\n2015-04-10 18:42:53,15\n2015-04-10 18:47:53,18\n2015-04-10 18:52:53,18\n2015-04-10 18:57:53,35\n2015-04-10 19:02:53,30\n2015-04-10 19:07:53,17\n2015-04-10 19:12:53,26\n2015-04-10 19:17:53,13\n2015-04-10 19:22:53,21\n2015-04-10 19:27:53,33\n2015-04-10 19:32:53,26\n2015-04-10 19:37:53,17\n2015-04-10 19:42:53,21\n2015-04-10 19:47:53,13\n2015-04-10 19:52:53,14\n2015-04-10 19:57:53,33\n2015-04-10 20:02:53,48\n2015-04-10 20:07:53,31\n2015-04-10 20:12:53,19\n2015-04-10 20:17:53,20\n2015-04-10 20:22:53,14\n2015-04-10 20:27:53,19\n2015-04-10 20:32:53,11\n2015-04-10 20:37:53,12\n2015-04-10 20:42:53,25\n2015-04-10 20:47:53,25\n2015-04-10 20:52:53,21\n2015-04-10 20:57:53,21\n2015-04-10 21:02:53,26\n2015-04-10 21:07:53,17\n2015-04-10 21:12:53,10\n2015-04-10 21:17:53,16\n2015-04-10 21:22:53,17\n2015-04-10 21:27:53,14\n2015-04-10 21:32:53,16\n2015-04-10 21:37:53,7\n2015-04-10 21:42:53,21\n2015-04-10 21:47:53,30\n2015-04-10 21:52:53,23\n2015-04-10 21:57:53,24\n2015-04-10 22:02:53,18\n2015-04-10 22:07:53,17\n2015-04-10 22:12:53,15\n2015-04-10 22:17:53,17\n2015-04-10 22:22:53,15\n2015-04-10 22:27:53,24\n2015-04-10 22:32:53,22\n2015-04-10 22:37:53,16\n2015-04-10 22:42:53,20\n2015-04-10 22:47:53,15\n2015-04-10 22:52:53,16\n2015-04-10 22:57:53,26\n2015-04-10 23:02:53,21\n2015-04-10 23:07:53,19\n2015-04-10 23:12:53,14\n2015-04-10 23:17:53,26\n2015-04-10 23:22:53,17\n2015-04-10 23:27:53,15\n2015-04-10 23:32:53,13\n2015-04-10 23:37:53,10\n2015-04-10 23:42:53,10\n2015-04-10 23:47:53,13\n2015-04-10 23:52:53,9\n2015-04-10 23:57:53,10\n2015-04-11 00:02:53,8\n2015-04-11 00:07:53,8\n2015-04-11 00:12:53,13\n2015-04-11 00:17:53,8\n2015-04-11 00:22:53,14\n2015-04-11 00:27:53,11\n2015-04-11 00:32:53,18\n2015-04-11 00:37:53,6\n2015-04-11 00:42:53,12\n2015-04-11 00:47:53,9\n2015-04-11 00:52:53,19\n2015-04-11 00:57:53,18\n2015-04-11 01:02:53,11\n2015-04-11 01:07:53,9\n2015-04-11 01:12:53,9\n2015-04-11 01:17:53,5\n2015-04-11 01:22:53,6\n2015-04-11 01:27:53,8\n2015-04-11 01:32:53,9\n2015-04-11 01:37:53,7\n2015-04-11 01:42:53,16\n2015-04-11 01:47:53,11\n2015-04-11 01:52:53,4\n2015-04-11 01:57:53,11\n2015-04-11 02:02:53,25\n2015-04-11 02:07:53,9\n2015-04-11 02:12:53,4\n2015-04-11 02:17:53,8\n2015-04-11 02:22:53,13\n2015-04-11 02:27:53,8\n2015-04-11 02:32:53,6\n2015-04-11 02:37:53,10\n2015-04-11 02:42:53,15\n2015-04-11 02:47:53,14\n2015-04-11 02:52:53,4\n2015-04-11 02:57:53,8\n2015-04-11 03:02:53,7\n2015-04-11 03:07:53,8\n2015-04-11 03:12:53,14\n2015-04-11 03:17:53,16\n2015-04-11 03:22:53,12\n2015-04-11 03:27:53,9\n2015-04-11 03:32:53,15\n2015-04-11 03:37:53,8\n2015-04-11 03:42:53,3\n2015-04-11 03:47:53,5\n2015-04-11 03:52:53,6\n2015-04-11 03:57:53,10\n2015-04-11 04:02:53,16\n2015-04-11 04:07:53,14\n2015-04-11 04:12:53,12\n2015-04-11 04:17:53,7\n2015-04-11 04:22:53,9\n2015-04-11 04:27:53,8\n2015-04-11 04:32:53,4\n2015-04-11 04:37:53,7\n2015-04-11 04:42:53,4\n2015-04-11 04:47:53,10\n2015-04-11 04:52:53,9\n2015-04-11 04:57:53,5\n2015-04-11 05:02:53,10\n2015-04-11 05:07:53,8\n2015-04-11 05:12:53,10\n2015-04-11 05:17:53,16\n2015-04-11 05:22:53,4\n2015-04-11 05:27:53,3\n2015-04-11 05:32:53,5\n2015-04-11 05:37:53,10\n2015-04-11 05:42:53,16\n2015-04-11 05:47:53,4\n2015-04-11 05:52:53,5\n2015-04-11 05:57:53,8\n2015-04-11 06:02:53,8\n2015-04-11 06:07:53,10\n2015-04-11 06:12:53,4\n2015-04-11 06:17:53,6\n2015-04-11 06:22:53,8\n2015-04-11 06:27:53,4\n2015-04-11 06:32:53,5\n2015-04-11 06:37:53,3\n2015-04-11 06:42:53,14\n2015-04-11 06:47:53,9\n2015-04-11 06:52:53,3\n2015-04-11 06:57:53,5\n2015-04-11 07:02:53,5\n2015-04-11 07:07:53,5\n2015-04-11 07:12:53,5\n2015-04-11 07:17:53,13\n2015-04-11 07:22:53,2\n2015-04-11 07:27:53,7\n2015-04-11 07:32:53,13\n2015-04-11 07:37:53,4\n2015-04-11 07:42:53,12\n2015-04-11 07:47:53,10\n2015-04-11 07:52:53,10\n2015-04-11 07:57:53,3\n2015-04-11 08:02:53,13\n2015-04-11 08:07:53,10\n2015-04-11 08:12:53,6\n2015-04-11 08:17:53,6\n2015-04-11 08:22:53,3\n2015-04-11 08:27:53,9\n2015-04-11 08:32:53,4\n2015-04-11 08:37:53,16\n2015-04-11 08:42:53,8\n2015-04-11 08:47:53,5\n2015-04-11 08:52:53,11\n2015-04-11 08:57:53,18\n2015-04-11 09:02:53,8\n2015-04-11 09:07:53,12\n2015-04-11 09:12:53,13\n2015-04-11 09:17:53,11\n2015-04-11 09:22:53,9\n2015-04-11 09:27:53,2\n2015-04-11 09:32:53,6\n2015-04-11 09:37:53,8\n2015-04-11 09:42:53,3\n2015-04-11 09:47:53,4\n2015-04-11 09:52:53,10\n2015-04-11 09:57:53,5\n2015-04-11 10:02:53,5\n2015-04-11 10:07:53,10\n2015-04-11 10:12:53,4\n2015-04-11 10:17:53,10\n2015-04-11 10:22:53,6\n2015-04-11 10:27:53,8\n2015-04-11 10:32:53,8\n2015-04-11 10:37:53,14\n2015-04-11 10:42:53,6\n2015-04-11 10:47:53,8\n2015-04-11 10:52:53,15\n2015-04-11 10:57:53,7\n2015-04-11 11:02:53,8\n2015-04-11 11:07:53,11\n2015-04-11 11:12:53,8\n2015-04-11 11:17:53,7\n2015-04-11 11:22:53,5\n2015-04-11 11:27:53,13\n2015-04-11 11:32:53,27\n2015-04-11 11:37:53,17\n2015-04-11 11:42:53,9\n2015-04-11 11:47:53,4\n2015-04-11 11:52:53,25\n2015-04-11 11:57:53,21\n2015-04-11 12:02:53,13\n2015-04-11 12:07:53,14\n2015-04-11 12:12:53,8\n2015-04-11 12:17:53,8\n2015-04-11 12:22:53,19\n2015-04-11 12:27:53,7\n2015-04-11 12:32:53,8\n2015-04-11 12:37:53,16\n2015-04-11 12:42:53,10\n2015-04-11 12:47:53,7\n2015-04-11 12:52:53,12\n2015-04-11 12:57:53,13\n2015-04-11 13:02:53,13\n2015-04-11 13:07:53,13\n2015-04-11 13:12:53,12\n2015-04-11 13:17:53,12\n2015-04-11 13:22:53,8\n2015-04-11 13:27:53,9\n2015-04-11 13:32:53,5\n2015-04-11 13:37:53,11\n2015-04-11 13:42:53,11\n2015-04-11 13:47:53,12\n2015-04-11 13:52:53,15\n2015-04-11 13:57:53,14\n2015-04-11 14:02:53,14\n2015-04-11 14:07:53,12\n2015-04-11 14:12:53,12\n2015-04-11 14:17:53,13\n2015-04-11 14:22:53,12\n2015-04-11 14:27:53,18\n2015-04-11 14:32:53,14\n2015-04-11 14:37:53,17\n2015-04-11 14:42:53,14\n2015-04-11 14:47:53,16\n2015-04-11 14:52:53,10\n2015-04-11 14:57:53,14\n2015-04-11 15:02:53,19\n2015-04-11 15:07:53,15\n2015-04-11 15:12:53,8\n2015-04-11 15:17:53,10\n2015-04-11 15:22:53,10\n2015-04-11 15:27:53,10\n2015-04-11 15:32:53,13\n2015-04-11 15:37:53,8\n2015-04-11 15:42:53,16\n2015-04-11 15:47:53,13\n2015-04-11 15:52:53,15\n2015-04-11 15:57:53,11\n2015-04-11 16:02:53,6\n2015-04-11 16:07:53,10\n2015-04-11 16:12:53,13\n2015-04-11 16:17:53,13\n2015-04-11 16:22:53,12\n2015-04-11 16:27:53,8\n2015-04-11 16:32:53,9\n2015-04-11 16:37:53,6\n2015-04-11 16:42:53,14\n2015-04-11 16:47:53,9\n2015-04-11 16:52:53,6\n2015-04-11 16:57:53,10\n2015-04-11 17:02:53,17\n2015-04-11 17:07:53,10\n2015-04-11 17:12:53,23\n2015-04-11 17:17:53,3\n2015-04-11 17:22:53,8\n2015-04-11 17:27:53,11\n2015-04-11 17:32:53,15\n2015-04-11 17:37:53,9\n2015-04-11 17:42:53,10\n2015-04-11 17:47:53,12\n2015-04-11 17:52:53,12\n2015-04-11 17:57:53,15\n2015-04-11 18:02:53,17\n2015-04-11 18:07:53,17\n2015-04-11 18:12:53,12\n2015-04-11 18:17:53,11\n2015-04-11 18:22:53,11\n2015-04-11 18:27:53,20\n2015-04-11 18:32:53,21\n2015-04-11 18:37:53,8\n2015-04-11 18:42:53,13\n2015-04-11 18:47:53,14\n2015-04-11 18:52:53,8\n2015-04-11 18:57:53,13\n2015-04-11 19:02:53,16\n2015-04-11 19:07:53,4\n2015-04-11 19:12:53,22\n2015-04-11 19:17:53,20\n2015-04-11 19:22:53,19\n2015-04-11 19:27:53,14\n2015-04-11 19:32:53,9\n2015-04-11 19:37:53,5\n2015-04-11 19:42:53,3\n2015-04-11 19:47:53,33\n2015-04-11 19:52:53,23\n2015-04-11 19:57:53,24\n2015-04-11 20:02:53,15\n2015-04-11 20:07:53,8\n2015-04-11 20:12:53,13\n2015-04-11 20:17:53,12\n2015-04-11 20:22:53,11\n2015-04-11 20:27:53,17\n2015-04-11 20:32:53,9\n2015-04-11 20:37:53,7\n2015-04-11 20:42:53,6\n2015-04-11 20:47:53,12\n2015-04-11 20:52:53,7\n2015-04-11 20:57:53,28\n2015-04-11 21:02:53,10\n2015-04-11 21:07:53,25\n2015-04-11 21:12:53,12\n2015-04-11 21:17:53,19\n2015-04-11 21:22:53,8\n2015-04-11 21:27:53,10\n2015-04-11 21:32:53,8\n2015-04-11 21:37:53,15\n2015-04-11 21:42:53,7\n2015-04-11 21:47:53,7\n2015-04-11 21:52:53,10\n2015-04-11 21:57:53,13\n2015-04-11 22:02:53,2\n2015-04-11 22:07:53,7\n2015-04-11 22:12:53,7\n2015-04-11 22:17:53,17\n2015-04-11 22:22:53,5\n2015-04-11 22:27:53,11\n2015-04-11 22:32:53,25\n2015-04-11 22:37:53,19\n2015-04-11 22:42:53,6\n2015-04-11 22:47:53,9\n2015-04-11 22:52:53,6\n2015-04-11 22:57:53,7\n2015-04-11 23:02:53,9\n2015-04-11 23:07:53,3\n2015-04-11 23:12:53,6\n2015-04-11 23:17:53,14\n2015-04-11 23:22:53,5\n2015-04-11 23:27:53,12\n2015-04-11 23:32:53,8\n2015-04-11 23:37:53,8\n2015-04-11 23:42:53,5\n2015-04-11 23:47:53,8\n2015-04-11 23:52:53,2\n2015-04-11 23:57:53,9\n2015-04-12 00:02:53,7\n2015-04-12 00:07:53,16\n2015-04-12 00:12:53,12\n2015-04-12 00:17:53,10\n2015-04-12 00:22:53,8\n2015-04-12 00:27:53,11\n2015-04-12 00:32:53,12\n2015-04-12 00:37:53,13\n2015-04-12 00:42:53,8\n2015-04-12 00:47:53,17\n2015-04-12 00:52:53,14\n2015-04-12 00:57:53,10\n2015-04-12 01:02:53,7\n2015-04-12 01:07:53,4\n2015-04-12 01:12:53,14\n2015-04-12 01:17:53,7\n2015-04-12 01:22:53,5\n2015-04-12 01:27:53,7\n2015-04-12 01:32:53,9\n2015-04-12 01:37:53,5\n2015-04-12 01:42:53,7\n2015-04-12 01:47:53,2\n2015-04-12 01:52:53,11\n2015-04-12 01:57:53,15\n2015-04-12 02:02:53,7\n2015-04-12 02:07:53,1\n2015-04-12 02:12:53,3\n2015-04-12 02:17:53,8\n2015-04-12 02:22:53,1\n2015-04-12 02:27:53,12\n2015-04-12 02:32:53,1\n2015-04-12 02:37:53,9\n2015-04-12 02:42:53,27\n2015-04-12 02:47:53,4\n2015-04-12 02:52:53,5\n2015-04-12 02:57:53,6\n2015-04-12 03:02:53,4\n2015-04-12 03:07:53,10\n2015-04-12 03:12:53,8\n2015-04-12 03:17:53,7\n2015-04-12 03:22:53,6\n2015-04-12 03:27:53,12\n2015-04-12 03:32:53,6\n2015-04-12 03:37:53,4\n2015-04-12 03:42:53,11\n2015-04-12 03:47:53,3\n2015-04-12 03:52:53,6\n2015-04-12 03:57:53,10\n2015-04-12 04:02:53,8\n2015-04-12 04:07:53,4\n2015-04-12 04:12:53,6\n2015-04-12 04:17:53,9\n2015-04-12 04:22:53,3\n2015-04-12 04:27:53,9\n2015-04-12 04:32:53,6\n2015-04-12 04:37:53,7\n2015-04-12 04:42:53,11\n2015-04-12 04:47:53,14\n2015-04-12 04:52:53,7\n2015-04-12 04:57:53,7\n2015-04-12 05:02:53,22\n2015-04-12 05:07:53,13\n2015-04-12 05:12:53,12\n2015-04-12 05:17:53,13\n2015-04-12 05:22:53,15\n2015-04-12 05:27:53,11\n2015-04-12 05:32:53,11\n2015-04-12 05:37:53,10\n2015-04-12 05:42:53,8\n2015-04-12 05:47:53,12\n2015-04-12 05:52:53,17\n2015-04-12 05:57:53,15\n2015-04-12 06:02:53,4\n2015-04-12 06:07:53,31\n2015-04-12 06:12:53,11\n2015-04-12 06:17:53,6\n2015-04-12 06:22:53,6\n2015-04-12 06:27:53,8\n2015-04-12 06:32:53,7\n2015-04-12 06:37:53,12\n2015-04-12 06:42:53,9\n2015-04-12 06:47:53,19\n2015-04-12 06:52:53,7\n2015-04-12 06:57:53,5\n2015-04-12 07:02:53,10\n2015-04-12 07:07:53,8\n2015-04-12 07:12:53,2\n2015-04-12 07:17:53,9\n2015-04-12 07:22:53,4\n2015-04-12 07:27:53,3\n2015-04-12 07:32:53,12\n2015-04-12 07:37:53,5\n2015-04-12 07:42:53,6\n2015-04-12 07:47:53,5\n2015-04-12 07:52:53,6\n2015-04-12 07:57:53,11\n2015-04-12 08:02:53,8\n2015-04-12 08:07:53,2\n2015-04-12 08:12:53,4\n2015-04-12 08:17:53,10\n2015-04-12 08:22:53,5\n2015-04-12 08:27:53,13\n2015-04-12 08:32:53,1\n2015-04-12 08:37:53,15\n2015-04-12 08:42:53,14\n2015-04-12 08:47:53,7\n2015-04-12 08:52:53,2\n2015-04-12 08:57:53,3\n2015-04-12 09:02:53,6\n2015-04-12 09:07:53,8\n2015-04-12 09:12:53,7\n2015-04-12 09:17:53,12\n2015-04-12 09:22:53,8\n2015-04-12 09:27:53,5\n2015-04-12 09:32:53,10\n2015-04-12 09:37:53,7\n2015-04-12 09:42:53,9\n2015-04-12 09:47:53,5\n2015-04-12 09:52:53,5\n2015-04-12 09:57:53,17\n2015-04-12 10:02:53,6\n2015-04-12 10:07:53,5\n2015-04-12 10:12:53,9\n2015-04-12 10:17:53,2\n2015-04-12 10:22:53,9\n2015-04-12 10:27:53,6\n2015-04-12 10:32:53,9\n2015-04-12 10:37:53,5\n2015-04-12 10:42:53,9\n2015-04-12 10:47:53,9\n2015-04-12 10:52:53,5\n2015-04-12 10:57:53,15\n2015-04-12 11:02:53,10\n2015-04-12 11:07:53,7\n2015-04-12 11:12:53,3\n2015-04-12 11:17:53,3\n2015-04-12 11:22:53,2\n2015-04-12 11:27:53,5\n2015-04-12 11:32:53,5\n2015-04-12 11:37:53,4\n2015-04-12 11:42:53,5\n2015-04-12 11:47:53,9\n2015-04-12 11:52:53,2\n2015-04-12 11:57:53,1\n2015-04-12 12:02:53,6\n2015-04-12 12:07:53,10\n2015-04-12 12:12:53,5\n2015-04-12 12:17:53,14\n2015-04-12 12:22:53,7\n2015-04-12 12:27:53,5\n2015-04-12 12:32:53,6\n2015-04-12 12:37:53,6\n2015-04-12 12:42:53,5\n2015-04-12 12:47:53,5\n2015-04-12 12:52:53,5\n2015-04-12 12:57:53,10\n2015-04-12 13:02:53,4\n2015-04-12 13:07:53,5\n2015-04-12 13:12:53,2\n2015-04-12 13:17:53,7\n2015-04-12 13:22:53,27\n2015-04-12 13:27:53,11\n2015-04-12 13:32:53,7\n2015-04-12 13:37:53,3\n2015-04-12 13:42:53,11\n2015-04-12 13:47:53,9\n2015-04-12 13:52:53,4\n2015-04-12 13:57:53,6\n2015-04-12 14:02:53,8\n2015-04-12 14:07:53,7\n2015-04-12 14:12:53,6\n2015-04-12 14:17:53,9\n2015-04-12 14:22:53,12\n2015-04-12 14:27:53,12\n2015-04-12 14:32:53,14\n2015-04-12 14:37:53,9\n2015-04-12 14:42:53,9\n2015-04-12 14:47:53,11\n2015-04-12 14:52:53,11\n2015-04-12 14:57:53,14\n2015-04-12 15:02:53,18\n2015-04-12 15:07:53,9\n2015-04-12 15:12:53,6\n2015-04-12 15:17:53,4\n2015-04-12 15:22:53,10\n2015-04-12 15:27:53,11\n2015-04-12 15:32:53,7\n2015-04-12 15:37:53,10\n2015-04-12 15:42:53,15\n2015-04-12 15:47:53,13\n2015-04-12 15:52:53,5\n2015-04-12 15:57:53,12\n2015-04-12 16:02:53,13\n2015-04-12 16:07:53,11\n2015-04-12 16:12:53,14\n2015-04-12 16:17:53,26\n2015-04-12 16:22:53,9\n2015-04-12 16:27:53,14\n2015-04-12 16:32:53,16\n2015-04-12 16:37:53,18\n2015-04-12 16:42:53,5\n2015-04-12 16:47:53,5\n2015-04-12 16:52:53,7\n2015-04-12 16:57:53,8\n2015-04-12 17:02:53,6\n2015-04-12 17:07:53,17\n2015-04-12 17:12:53,8\n2015-04-12 17:17:53,12\n2015-04-12 17:22:53,9\n2015-04-12 17:27:53,18\n2015-04-12 17:32:53,8\n2015-04-12 17:37:53,15\n2015-04-12 17:42:53,11\n2015-04-12 17:47:53,7\n2015-04-12 17:52:53,5\n2015-04-12 17:57:53,8\n2015-04-12 18:02:53,12\n2015-04-12 18:07:53,12\n2015-04-12 18:12:53,15\n2015-04-12 18:17:53,8\n2015-04-12 18:22:53,8\n2015-04-12 18:27:53,14\n2015-04-12 18:32:53,11\n2015-04-12 18:37:53,16\n2015-04-12 18:42:53,8\n2015-04-12 18:47:53,6\n2015-04-12 18:52:53,8\n2015-04-12 18:57:53,7\n2015-04-12 19:02:53,13\n2015-04-12 19:07:53,5\n2015-04-12 19:12:53,11\n2015-04-12 19:17:53,8\n2015-04-12 19:22:53,9\n2015-04-12 19:27:53,13\n2015-04-12 19:32:53,13\n2015-04-12 19:37:53,8\n2015-04-12 19:42:53,12\n2015-04-12 19:47:53,7\n2015-04-12 19:52:53,7\n2015-04-12 19:57:53,11\n2015-04-12 20:02:53,10\n2015-04-12 20:07:53,6\n2015-04-12 20:12:53,9\n2015-04-12 20:17:53,8\n2015-04-12 20:22:53,12\n2015-04-12 20:27:53,12\n2015-04-12 20:32:53,5\n2015-04-12 20:37:53,4\n2015-04-12 20:42:53,6\n2015-04-12 20:47:53,6\n2015-04-12 20:52:53,11\n2015-04-12 20:57:53,8\n2015-04-12 21:02:53,7\n2015-04-12 21:07:53,11\n2015-04-12 21:12:53,8\n2015-04-12 21:17:53,16\n2015-04-12 21:22:53,10\n2015-04-12 21:27:53,13\n2015-04-12 21:32:53,8\n2015-04-12 21:37:53,21\n2015-04-12 21:42:53,25\n2015-04-12 21:47:53,26\n2015-04-12 21:52:53,22\n2015-04-12 21:57:53,20\n2015-04-12 22:02:53,20\n2015-04-12 22:07:53,19\n2015-04-12 22:12:53,14\n2015-04-12 22:17:53,22\n2015-04-12 22:22:53,38\n2015-04-12 22:27:53,15\n2015-04-12 22:32:53,9\n2015-04-12 22:37:53,15\n2015-04-12 22:42:53,9\n2015-04-12 22:47:53,12\n2015-04-12 22:52:53,16\n2015-04-12 22:57:53,13\n2015-04-12 23:02:53,16\n2015-04-12 23:07:53,9\n2015-04-12 23:12:53,12\n2015-04-12 23:17:53,10\n2015-04-12 23:22:53,13\n2015-04-12 23:27:53,11\n2015-04-12 23:32:53,16\n2015-04-12 23:37:53,19\n2015-04-12 23:42:53,29\n2015-04-12 23:47:53,20\n2015-04-12 23:52:53,16\n2015-04-12 23:57:53,13\n2015-04-13 00:02:53,16\n2015-04-13 00:07:53,13\n2015-04-13 00:12:53,16\n2015-04-13 00:17:53,7\n2015-04-13 00:22:53,7\n2015-04-13 00:27:53,12\n2015-04-13 00:32:53,8\n2015-04-13 00:37:53,11\n2015-04-13 00:42:53,21\n2015-04-13 00:47:53,13\n2015-04-13 00:52:53,6\n2015-04-13 00:57:53,9\n2015-04-13 01:02:53,14\n2015-04-13 01:07:53,11\n2015-04-13 01:12:53,12\n2015-04-13 01:17:53,7\n2015-04-13 01:22:53,9\n2015-04-13 01:27:53,9\n2015-04-13 01:32:53,7\n2015-04-13 01:37:53,6\n2015-04-13 01:42:53,9\n2015-04-13 01:47:53,7\n2015-04-13 01:52:53,6\n2015-04-13 01:57:53,11\n2015-04-13 02:02:53,5\n2015-04-13 02:07:53,12\n2015-04-13 02:12:53,6\n2015-04-13 02:17:53,19\n2015-04-13 02:22:53,11\n2015-04-13 02:27:53,11\n2015-04-13 02:32:53,11\n2015-04-13 02:37:53,12\n2015-04-13 02:42:53,9\n2015-04-13 02:47:53,11\n2015-04-13 02:52:53,17\n2015-04-13 02:57:53,10\n2015-04-13 03:02:53,11\n2015-04-13 03:07:53,10\n2015-04-13 03:12:53,10\n2015-04-13 03:17:53,5\n2015-04-13 03:22:53,13\n2015-04-13 03:27:53,9\n2015-04-13 03:32:53,9\n2015-04-13 03:37:53,17\n2015-04-13 03:42:53,12\n2015-04-13 03:47:53,9\n2015-04-13 03:52:53,17\n2015-04-13 03:57:53,10\n2015-04-13 04:02:53,10\n2015-04-13 04:07:53,7\n2015-04-13 04:12:53,8\n2015-04-13 04:17:53,5\n2015-04-13 04:22:53,4\n2015-04-13 04:27:53,6\n2015-04-13 04:32:53,11\n2015-04-13 04:37:53,15\n2015-04-13 04:42:53,15\n2015-04-13 04:47:53,6\n2015-04-13 04:52:53,8\n2015-04-13 04:57:53,5\n2015-04-13 05:02:53,5\n2015-04-13 05:07:53,3\n2015-04-13 05:12:53,6\n2015-04-13 05:17:53,8\n2015-04-13 05:22:53,7\n2015-04-13 05:27:53,2\n2015-04-13 05:32:53,5\n2015-04-13 05:37:53,7\n2015-04-13 05:42:53,2\n2015-04-13 05:47:53,2\n2015-04-13 05:52:53,7\n2015-04-13 05:57:53,7\n2015-04-13 06:02:53,8\n2015-04-13 06:07:53,14\n2015-04-13 06:12:53,8\n2015-04-13 06:17:53,8\n2015-04-13 06:22:53,5\n2015-04-13 06:27:53,7\n2015-04-13 06:32:53,10\n2015-04-13 06:37:53,5\n2015-04-13 06:42:53,4\n2015-04-13 06:47:53,3\n2015-04-13 06:52:53,9\n2015-04-13 06:57:53,5\n2015-04-13 07:02:53,12\n2015-04-13 07:07:53,10\n2015-04-13 07:12:53,5\n2015-04-13 07:17:53,8\n2015-04-13 07:22:53,10\n2015-04-13 07:27:53,9\n2015-04-13 07:32:53,5\n2015-04-13 07:37:53,6\n2015-04-13 07:42:53,9\n2015-04-13 07:47:53,6\n2015-04-13 07:52:53,9\n2015-04-13 07:57:53,18\n2015-04-13 08:02:53,13\n2015-04-13 08:07:53,14\n2015-04-13 08:12:53,10\n2015-04-13 08:17:53,17\n2015-04-13 08:22:53,12\n2015-04-13 08:27:53,12\n2015-04-13 08:32:53,13\n2015-04-13 08:37:53,12\n2015-04-13 08:42:53,14\n2015-04-13 08:47:53,8\n2015-04-13 08:52:53,15\n2015-04-13 08:57:53,9\n2015-04-13 09:02:53,9\n2015-04-13 09:07:53,17\n2015-04-13 09:12:53,10\n2015-04-13 09:17:53,14\n2015-04-13 09:22:53,9\n2015-04-13 09:27:53,17\n2015-04-13 09:32:53,16\n2015-04-13 09:37:53,12\n2015-04-13 09:42:53,11\n2015-04-13 09:47:53,6\n2015-04-13 09:52:53,15\n2015-04-13 09:57:53,11\n2015-04-13 10:02:53,11\n2015-04-13 10:07:53,9\n2015-04-13 10:12:53,11\n2015-04-13 10:17:53,10\n2015-04-13 10:22:53,11\n2015-04-13 10:27:53,10\n2015-04-13 10:32:53,6\n2015-04-13 10:37:53,4\n2015-04-13 10:42:53,12\n2015-04-13 10:47:53,8\n2015-04-13 10:52:53,5\n2015-04-13 10:57:53,13\n2015-04-13 11:02:53,12\n2015-04-13 11:07:53,11\n2015-04-13 11:12:53,13\n2015-04-13 11:17:53,15\n2015-04-13 11:22:53,9\n2015-04-13 11:27:53,17\n2015-04-13 11:32:53,21\n2015-04-13 11:37:53,6\n2015-04-13 11:42:53,10\n2015-04-13 11:47:53,5\n2015-04-13 11:52:53,20\n2015-04-13 11:57:53,16\n2015-04-13 12:02:53,11\n2015-04-13 12:07:53,17\n2015-04-13 12:12:53,10\n2015-04-13 12:17:53,12\n2015-04-13 12:22:53,20\n2015-04-13 12:27:53,10\n2015-04-13 12:32:53,9\n2015-04-13 12:37:53,12\n2015-04-13 12:42:53,13\n2015-04-13 12:47:53,7\n2015-04-13 12:52:53,4\n2015-04-13 12:57:53,16\n2015-04-13 13:02:53,26\n2015-04-13 13:07:53,13\n2015-04-13 13:12:53,18\n2015-04-13 13:17:53,10\n2015-04-13 13:22:53,12\n2015-04-13 13:27:53,11\n2015-04-13 13:32:53,13\n2015-04-13 13:37:53,12\n2015-04-13 13:42:53,11\n2015-04-13 13:47:53,15\n2015-04-13 13:52:53,25\n2015-04-13 13:57:53,35\n2015-04-13 14:02:53,31\n2015-04-13 14:07:53,29\n2015-04-13 14:12:53,35\n2015-04-13 14:17:53,34\n2015-04-13 14:22:53,31\n2015-04-13 14:27:53,20\n2015-04-13 14:32:53,20\n2015-04-13 14:37:53,30\n2015-04-13 14:42:53,34\n2015-04-13 14:47:53,25\n2015-04-13 14:52:53,36\n2015-04-13 14:57:53,34\n2015-04-13 15:02:53,36\n2015-04-13 15:07:53,39\n2015-04-13 15:12:53,29\n2015-04-13 15:17:53,29\n2015-04-13 15:22:53,34\n2015-04-13 15:27:53,30\n2015-04-13 15:32:53,34\n2015-04-13 15:37:53,32\n2015-04-13 15:42:53,32\n2015-04-13 15:47:53,32\n2015-04-13 15:52:53,34\n2015-04-13 15:57:53,40\n2015-04-13 16:02:53,34\n2015-04-13 16:07:53,54\n2015-04-13 16:12:53,84\n2015-04-13 16:17:53,71\n2015-04-13 16:22:53,42\n2015-04-13 16:27:53,39\n2015-04-13 16:32:53,46\n2015-04-13 16:37:53,32\n2015-04-13 16:42:53,30\n2015-04-13 16:47:53,28\n2015-04-13 16:52:53,33\n2015-04-13 16:57:53,34\n2015-04-13 17:02:53,29\n2015-04-13 17:07:53,38\n2015-04-13 17:12:53,41\n2015-04-13 17:17:53,28\n2015-04-13 17:22:53,29\n2015-04-13 17:27:53,40\n2015-04-13 17:32:53,37\n2015-04-13 17:37:53,37\n2015-04-13 17:42:53,41\n2015-04-13 17:47:53,37\n2015-04-13 17:52:53,36\n2015-04-13 17:57:53,38\n2015-04-13 18:02:53,39\n2015-04-13 18:07:53,29\n2015-04-13 18:12:53,26\n2015-04-13 18:17:53,26\n2015-04-13 18:22:53,31\n2015-04-13 18:27:53,34\n2015-04-13 18:32:53,23\n2015-04-13 18:37:53,27\n2015-04-13 18:42:53,33\n2015-04-13 18:47:53,43\n2015-04-13 18:52:53,31\n2015-04-13 18:57:53,31\n2015-04-13 19:02:53,40\n2015-04-13 19:07:53,38\n2015-04-13 19:12:53,36\n2015-04-13 19:17:53,36\n2015-04-13 19:22:53,22\n2015-04-13 19:27:53,21\n2015-04-13 19:32:53,35\n2015-04-13 19:37:53,36\n2015-04-13 19:42:53,28\n2015-04-13 19:47:53,32\n2015-04-13 19:52:53,12\n2015-04-13 19:57:53,30\n2015-04-13 20:02:53,23\n2015-04-13 20:07:53,32\n2015-04-13 20:12:53,44\n2015-04-13 20:17:53,36\n2015-04-13 20:22:53,32\n2015-04-13 20:27:53,30\n2015-04-13 20:32:53,32\n2015-04-13 20:37:53,30\n2015-04-13 20:42:53,42\n2015-04-13 20:47:53,29\n2015-04-13 20:52:53,28\n2015-04-13 20:57:53,28\n2015-04-13 21:02:53,32\n2015-04-13 21:07:53,37\n2015-04-13 21:12:53,38\n2015-04-13 21:17:53,32\n2015-04-13 21:22:53,31\n2015-04-13 21:27:53,30\n2015-04-13 21:32:53,4\n2015-04-13 21:37:53,10\n2015-04-13 21:42:53,22\n2015-04-13 21:47:53,15\n2015-04-13 21:52:53,11\n2015-04-13 21:57:53,16\n2015-04-13 22:02:53,25\n2015-04-13 22:07:53,11\n2015-04-13 22:12:53,24\n2015-04-13 22:17:53,16\n2015-04-13 22:22:53,9\n2015-04-13 22:27:53,8\n2015-04-13 22:32:53,21\n2015-04-13 22:37:53,14\n2015-04-13 22:42:53,21\n2015-04-13 22:47:53,10\n2015-04-13 22:52:53,12\n2015-04-13 22:57:53,22\n2015-04-13 23:02:53,18\n2015-04-13 23:07:53,7\n2015-04-13 23:12:53,4\n2015-04-13 23:17:53,12\n2015-04-13 23:22:53,9\n2015-04-13 23:27:53,13\n2015-04-13 23:32:53,18\n2015-04-13 23:37:53,10\n2015-04-13 23:42:53,9\n2015-04-13 23:47:53,14\n2015-04-13 23:52:53,11\n2015-04-13 23:57:53,26\n2015-04-14 00:02:53,11\n2015-04-14 00:07:53,10\n2015-04-14 00:12:53,7\n2015-04-14 00:17:53,11\n2015-04-14 00:22:53,11\n2015-04-14 00:27:53,10\n2015-04-14 00:32:53,12\n2015-04-14 00:37:53,8\n2015-04-14 00:42:53,14\n2015-04-14 00:47:53,12\n2015-04-14 00:52:53,14\n2015-04-14 00:57:53,25\n2015-04-14 01:02:53,24\n2015-04-14 01:07:53,13\n2015-04-14 01:12:53,11\n2015-04-14 01:17:53,20\n2015-04-14 01:22:53,11\n2015-04-14 01:27:53,10\n2015-04-14 01:32:53,9\n2015-04-14 01:37:53,12\n2015-04-14 01:42:53,7\n2015-04-14 01:47:53,11\n2015-04-14 01:52:53,14\n2015-04-14 01:57:53,12\n2015-04-14 02:02:53,14\n2015-04-14 02:07:53,16\n2015-04-14 02:12:53,18\n2015-04-14 02:17:53,13\n2015-04-14 02:22:53,10\n2015-04-14 02:27:53,8\n2015-04-14 02:32:53,9\n2015-04-14 02:37:53,22\n2015-04-14 02:42:53,30\n2015-04-14 02:47:53,23\n2015-04-14 02:52:53,20\n2015-04-14 02:57:53,18\n2015-04-14 03:02:53,21\n2015-04-14 03:07:53,8\n2015-04-14 03:12:53,20\n2015-04-14 03:17:53,22\n2015-04-14 03:22:53,18\n2015-04-14 03:27:53,10\n2015-04-14 03:32:53,14\n2015-04-14 03:37:53,9\n2015-04-14 03:42:53,9\n2015-04-14 03:47:53,10\n2015-04-14 03:52:53,17\n2015-04-14 03:57:53,17\n2015-04-14 04:02:53,15\n2015-04-14 04:07:53,19\n2015-04-14 04:12:53,17\n2015-04-14 04:17:53,21\n2015-04-14 04:22:53,20\n2015-04-14 04:27:53,11\n2015-04-14 04:32:53,22\n2015-04-14 04:37:53,27\n2015-04-14 04:42:53,16\n2015-04-14 04:47:53,18\n2015-04-14 04:52:53,9\n2015-04-14 04:57:53,14\n2015-04-14 05:02:53,16\n2015-04-14 05:07:53,14\n2015-04-14 05:12:53,14\n2015-04-14 05:17:53,16\n2015-04-14 05:22:53,16\n2015-04-14 05:27:53,16\n2015-04-14 05:32:53,12\n2015-04-14 05:37:53,12\n2015-04-14 05:42:53,11\n2015-04-14 05:47:53,11\n2015-04-14 05:52:53,13\n2015-04-14 05:57:53,16\n2015-04-14 06:02:53,8\n2015-04-14 06:07:53,11\n2015-04-14 06:12:53,7\n2015-04-14 06:17:53,9\n2015-04-14 06:22:53,7\n2015-04-14 06:27:53,18\n2015-04-14 06:32:53,8\n2015-04-14 06:37:53,8\n2015-04-14 06:42:53,8\n2015-04-14 06:47:53,13\n2015-04-14 06:52:53,9\n2015-04-14 06:57:53,16\n2015-04-14 07:02:53,10\n2015-04-14 07:07:53,11\n2015-04-14 07:12:53,17\n2015-04-14 07:17:53,10\n2015-04-14 07:22:53,11\n2015-04-14 07:27:53,13\n2015-04-14 07:32:53,11\n2015-04-14 07:37:53,13\n2015-04-14 07:42:53,15\n2015-04-14 07:47:53,14\n2015-04-14 07:52:53,21\n2015-04-14 07:57:53,10\n2015-04-14 08:02:53,19\n2015-04-14 08:07:53,20\n2015-04-14 08:12:53,22\n2015-04-14 08:17:53,19\n2015-04-14 08:22:53,13\n2015-04-14 08:27:53,13\n2015-04-14 08:32:53,13\n2015-04-14 08:37:53,19\n2015-04-14 08:42:53,18\n2015-04-14 08:47:53,12\n2015-04-14 08:52:53,12\n2015-04-14 08:57:53,30\n2015-04-14 09:02:53,32\n2015-04-14 09:07:53,21\n2015-04-14 09:12:53,22\n2015-04-14 09:17:53,18\n2015-04-14 09:22:53,17\n2015-04-14 09:27:53,13\n2015-04-14 09:32:53,20\n2015-04-14 09:37:53,12\n2015-04-14 09:42:53,17\n2015-04-14 09:47:53,12\n2015-04-14 09:52:53,14\n2015-04-14 09:57:53,14\n2015-04-14 10:02:53,10\n2015-04-14 10:07:53,13\n2015-04-14 10:12:53,7\n2015-04-14 10:17:53,14\n2015-04-14 10:22:53,9\n2015-04-14 10:27:53,6\n2015-04-14 10:32:53,9\n2015-04-14 10:37:53,18\n2015-04-14 10:42:53,13\n2015-04-14 10:47:53,12\n2015-04-14 10:52:53,4\n2015-04-14 10:57:53,30\n2015-04-14 11:02:53,19\n2015-04-14 11:07:53,18\n2015-04-14 11:12:53,13\n2015-04-14 11:17:53,24\n2015-04-14 11:22:53,14\n2015-04-14 11:27:53,16\n2015-04-14 11:32:53,23\n2015-04-14 11:37:53,18\n2015-04-14 11:42:53,29\n2015-04-14 11:47:53,14\n2015-04-14 11:52:53,11\n2015-04-14 11:57:53,14\n2015-04-14 12:02:53,26\n2015-04-14 12:07:53,19\n2015-04-14 12:12:53,18\n2015-04-14 12:17:53,15\n2015-04-14 12:22:53,28\n2015-04-14 12:27:53,17\n2015-04-14 12:32:53,15\n2015-04-14 12:37:53,16\n2015-04-14 12:42:53,13\n2015-04-14 12:47:53,24\n2015-04-14 12:52:53,25\n2015-04-14 12:57:53,32\n2015-04-14 13:02:53,38\n2015-04-14 13:07:53,32\n2015-04-14 13:12:53,31\n2015-04-14 13:17:53,35\n2015-04-14 13:22:53,36\n2015-04-14 13:27:53,56\n2015-04-14 13:32:53,35\n2015-04-14 13:37:53,32\n2015-04-14 13:42:53,28\n2015-04-14 13:47:53,26\n2015-04-14 13:52:53,32\n2015-04-14 13:57:53,27\n2015-04-14 14:02:53,27\n2015-04-14 14:07:53,39\n2015-04-14 14:12:53,31\n2015-04-14 14:17:53,22\n2015-04-14 14:22:53,30\n2015-04-14 14:27:53,26\n2015-04-14 14:32:53,78\n2015-04-14 14:37:53,57\n2015-04-14 14:42:53,54\n2015-04-14 14:47:53,29\n2015-04-14 14:52:53,37\n2015-04-14 14:57:53,33\n2015-04-14 15:02:53,31\n2015-04-14 15:07:53,50\n2015-04-14 15:12:53,32\n2015-04-14 15:17:53,38\n2015-04-14 15:22:53,23\n2015-04-14 15:27:53,38\n2015-04-14 15:32:53,36\n2015-04-14 15:37:53,39\n2015-04-14 15:42:53,38\n2015-04-14 15:47:53,37\n2015-04-14 15:52:53,44\n2015-04-14 15:57:53,40\n2015-04-14 16:02:53,28\n2015-04-14 16:07:53,26\n2015-04-14 16:12:53,31\n2015-04-14 16:17:53,29\n2015-04-14 16:22:53,38\n2015-04-14 16:27:53,39\n2015-04-14 16:32:53,23\n2015-04-14 16:37:53,28\n2015-04-14 16:42:53,27\n2015-04-14 16:47:53,31\n2015-04-14 16:52:53,17\n2015-04-14 16:57:53,30\n2015-04-14 17:02:53,20\n2015-04-14 17:07:53,12\n2015-04-14 17:12:53,44\n2015-04-14 17:17:53,50\n2015-04-14 17:22:53,27\n2015-04-14 17:27:53,37\n2015-04-14 17:32:53,31\n2015-04-14 17:37:53,30\n2015-04-14 17:42:53,19\n2015-04-14 17:47:53,47\n2015-04-14 17:52:53,30\n2015-04-14 17:57:53,23\n2015-04-14 18:02:53,21\n2015-04-14 18:07:53,33\n2015-04-14 18:12:53,29\n2015-04-14 18:17:53,45\n2015-04-14 18:22:53,26\n2015-04-14 18:27:53,30\n2015-04-14 18:32:53,22\n2015-04-14 18:37:53,30\n2015-04-14 18:42:53,29\n2015-04-14 18:47:53,31\n2015-04-14 18:52:53,39\n2015-04-14 18:57:53,65\n2015-04-14 19:02:53,23\n2015-04-14 19:07:53,29\n2015-04-14 19:12:53,26\n2015-04-14 19:17:53,24\n2015-04-14 19:22:53,22\n2015-04-14 19:27:53,33\n2015-04-14 19:32:53,36\n2015-04-14 19:37:53,38\n2015-04-14 19:42:53,34\n2015-04-14 19:47:53,43\n2015-04-14 19:52:53,39\n2015-04-14 19:57:53,52\n2015-04-14 20:02:53,41\n2015-04-14 20:07:53,18\n2015-04-14 20:12:53,37\n2015-04-14 20:17:53,32\n2015-04-14 20:22:53,44\n2015-04-14 20:27:53,36\n2015-04-14 20:32:53,25\n2015-04-14 20:37:53,101\n2015-04-14 20:42:53,45\n2015-04-14 20:47:53,57\n2015-04-14 20:52:53,40\n2015-04-14 20:57:53,53\n2015-04-14 21:02:53,25\n2015-04-14 21:07:53,26\n2015-04-14 21:12:53,21\n2015-04-14 21:17:53,29\n2015-04-14 21:22:53,28\n2015-04-14 21:27:53,40\n2015-04-14 21:32:53,24\n2015-04-14 21:37:53,17\n2015-04-14 21:42:53,16\n2015-04-14 21:47:53,25\n2015-04-14 21:52:53,36\n2015-04-14 21:57:53,23\n2015-04-14 22:02:53,20\n2015-04-14 22:07:53,21\n2015-04-14 22:12:53,31\n2015-04-14 22:17:53,27\n2015-04-14 22:22:53,21\n2015-04-14 22:27:53,33\n2015-04-14 22:32:53,31\n2015-04-14 22:37:53,22\n2015-04-14 22:42:53,17\n2015-04-14 22:47:53,17\n2015-04-14 22:52:53,23\n2015-04-14 22:57:53,22\n2015-04-14 23:02:53,15\n2015-04-14 23:07:53,15\n2015-04-14 23:12:53,23\n2015-04-14 23:17:53,13\n2015-04-14 23:22:53,10\n2015-04-14 23:27:53,25\n2015-04-14 23:32:53,19\n2015-04-14 23:37:53,19\n2015-04-14 23:42:53,17\n2015-04-14 23:47:53,20\n2015-04-14 23:52:53,20\n2015-04-14 23:57:53,11\n2015-04-15 00:02:53,22\n2015-04-15 00:07:53,14\n2015-04-15 00:12:53,17\n2015-04-15 00:17:53,15\n2015-04-15 00:22:53,11\n2015-04-15 00:27:53,13\n2015-04-15 00:32:53,19\n2015-04-15 00:37:53,20\n2015-04-15 00:42:53,25\n2015-04-15 00:47:53,16\n2015-04-15 00:52:53,15\n2015-04-15 00:57:53,24\n2015-04-15 01:02:53,19\n2015-04-15 01:07:53,14\n2015-04-15 01:12:53,55\n2015-04-15 01:17:53,29\n2015-04-15 01:22:53,16\n2015-04-15 01:27:53,18\n2015-04-15 01:32:53,26\n2015-04-15 01:37:53,16\n2015-04-15 01:42:53,23\n2015-04-15 01:47:53,16\n2015-04-15 01:52:53,28\n2015-04-15 01:57:53,20\n2015-04-15 02:02:53,24\n2015-04-15 02:07:53,21\n2015-04-15 02:12:53,35\n2015-04-15 02:17:53,38\n2015-04-15 02:22:53,54\n2015-04-15 02:27:53,30\n2015-04-15 02:32:53,35\n2015-04-15 02:37:53,19\n2015-04-15 02:42:53,29\n2015-04-15 02:47:53,32\n2015-04-15 02:52:53,14\n2015-04-15 02:57:53,17\n2015-04-15 03:02:53,26\n2015-04-15 03:07:53,18\n2015-04-15 03:12:53,19\n2015-04-15 03:17:53,9\n2015-04-15 03:22:53,15\n2015-04-15 03:27:53,11\n2015-04-15 03:32:53,21\n2015-04-15 03:37:53,13\n2015-04-15 03:42:53,12\n2015-04-15 03:47:53,17\n2015-04-15 03:52:53,22\n2015-04-15 03:57:53,16\n2015-04-15 04:02:53,18\n2015-04-15 04:07:53,13\n2015-04-15 04:12:53,16\n2015-04-15 04:17:53,21\n2015-04-15 04:22:53,27\n2015-04-15 04:27:53,17\n2015-04-15 04:32:53,8\n2015-04-15 04:37:53,11\n2015-04-15 04:42:53,22\n2015-04-15 04:47:53,9\n2015-04-15 04:52:53,14\n2015-04-15 04:57:53,16\n2015-04-15 05:02:53,13\n2015-04-15 05:07:53,20\n2015-04-15 05:12:53,5\n2015-04-15 05:17:53,15\n2015-04-15 05:22:53,18\n2015-04-15 05:27:53,20\n2015-04-15 05:32:53,10\n2015-04-15 05:37:53,17\n2015-04-15 05:42:53,15\n2015-04-15 05:47:53,8\n2015-04-15 05:52:53,16\n2015-04-15 05:57:53,47\n2015-04-15 06:02:53,31\n2015-04-15 06:07:53,17\n2015-04-15 06:12:53,21\n2015-04-15 06:17:53,24\n2015-04-15 06:22:53,16\n2015-04-15 06:27:53,29\n2015-04-15 06:32:53,10\n2015-04-15 06:37:53,22\n2015-04-15 06:42:53,37\n2015-04-15 06:47:53,16\n2015-04-15 06:52:53,22\n2015-04-15 06:57:53,19\n2015-04-15 07:02:53,15\n2015-04-15 07:07:53,18\n2015-04-15 07:12:53,26\n2015-04-15 07:17:53,23\n2015-04-15 07:22:53,25\n2015-04-15 07:27:53,17\n2015-04-15 07:32:53,16\n2015-04-15 07:37:53,14\n2015-04-15 07:42:53,12\n2015-04-15 07:47:53,27\n2015-04-15 07:52:53,10\n2015-04-15 07:57:53,11\n2015-04-15 08:02:53,12\n2015-04-15 08:07:53,12\n2015-04-15 08:12:53,18\n2015-04-15 08:17:53,25\n2015-04-15 08:22:53,14\n2015-04-15 08:27:53,12\n2015-04-15 08:32:53,19\n2015-04-15 08:37:53,19\n2015-04-15 08:42:53,14\n2015-04-15 08:47:53,19\n2015-04-15 08:52:53,16\n2015-04-15 08:57:53,22\n2015-04-15 09:02:53,18\n2015-04-15 09:07:53,21\n2015-04-15 09:12:53,17\n2015-04-15 09:17:53,27\n2015-04-15 09:22:53,13\n2015-04-15 09:27:53,15\n2015-04-15 09:32:53,18\n2015-04-15 09:37:53,18\n2015-04-15 09:42:53,15\n2015-04-15 09:47:53,18\n2015-04-15 09:52:53,20\n2015-04-15 09:57:53,14\n2015-04-15 10:02:53,42\n2015-04-15 10:07:53,92\n2015-04-15 10:12:53,61\n2015-04-15 10:17:53,35\n2015-04-15 10:22:53,64\n2015-04-15 10:27:53,87\n2015-04-15 10:32:53,71\n2015-04-15 10:37:53,60\n2015-04-15 10:42:53,60\n2015-04-15 10:47:53,40\n2015-04-15 10:52:53,47\n2015-04-15 10:57:53,36\n2015-04-15 11:02:53,41\n2015-04-15 11:07:53,46\n2015-04-15 11:12:53,53\n2015-04-15 11:17:53,60\n2015-04-15 11:22:53,55\n2015-04-15 11:27:53,32\n2015-04-15 11:32:53,71\n2015-04-15 11:37:53,58\n2015-04-15 11:42:53,36\n2015-04-15 11:47:53,26\n2015-04-15 11:52:53,43\n2015-04-15 11:57:53,47\n2015-04-15 12:02:53,37\n2015-04-15 12:07:53,35\n2015-04-15 12:12:53,36\n2015-04-15 12:17:53,24\n2015-04-15 12:22:53,41\n2015-04-15 12:27:53,40\n2015-04-15 12:32:53,36\n2015-04-15 12:37:53,38\n2015-04-15 12:42:53,37\n2015-04-15 12:47:53,38\n2015-04-15 12:52:53,34\n2015-04-15 12:57:53,44\n2015-04-15 13:02:53,26\n2015-04-15 13:07:53,34\n2015-04-15 13:12:53,53\n2015-04-15 13:17:53,38\n2015-04-15 13:22:53,38\n2015-04-15 13:27:53,37\n2015-04-15 13:32:53,60\n2015-04-15 13:37:53,43\n2015-04-15 13:42:53,30\n2015-04-15 13:47:53,26\n2015-04-15 13:52:53,40\n2015-04-15 13:57:53,62\n2015-04-15 14:02:53,54\n2015-04-15 14:07:53,69\n2015-04-15 14:12:53,48\n2015-04-15 14:17:53,48\n2015-04-15 14:22:53,60\n2015-04-15 14:27:53,47\n2015-04-15 14:32:53,43\n2015-04-15 14:37:53,36\n2015-04-15 14:42:53,61\n2015-04-15 14:47:53,59\n2015-04-15 14:52:53,56\n2015-04-15 14:57:53,52\n2015-04-15 15:02:53,46\n2015-04-15 15:07:53,29\n2015-04-15 15:12:53,48\n2015-04-15 15:17:53,41\n2015-04-15 15:22:53,34\n2015-04-15 15:27:53,55\n2015-04-15 15:32:53,49\n2015-04-15 15:37:53,39\n2015-04-15 15:42:53,36\n2015-04-15 15:47:53,54\n2015-04-15 15:52:53,43\n2015-04-15 15:57:53,67\n2015-04-15 16:02:53,62\n2015-04-15 16:07:53,44\n2015-04-15 16:12:53,44\n2015-04-15 16:17:53,52\n2015-04-15 16:22:53,57\n2015-04-15 16:27:53,39\n2015-04-15 16:32:53,38\n2015-04-15 16:37:53,38\n2015-04-15 16:42:53,32\n2015-04-15 16:47:53,26\n2015-04-15 16:52:53,29\n2015-04-15 16:57:53,61\n2015-04-15 17:02:53,42\n2015-04-15 17:07:53,38\n2015-04-15 17:12:53,41\n2015-04-15 17:17:53,30\n2015-04-15 17:22:53,23\n2015-04-15 17:27:53,35\n2015-04-15 17:32:53,24\n2015-04-15 17:37:53,36\n2015-04-15 17:42:53,23\n2015-04-15 17:47:53,27\n2015-04-15 17:52:53,30\n2015-04-15 17:57:53,59\n2015-04-15 18:02:53,40\n2015-04-15 18:07:53,26\n2015-04-15 18:12:53,30\n2015-04-15 18:17:53,28\n2015-04-15 18:22:53,31\n2015-04-15 18:27:53,39\n2015-04-15 18:32:53,24\n2015-04-15 18:37:53,31\n2015-04-15 18:42:53,29\n2015-04-15 18:47:53,30\n2015-04-15 18:52:53,28\n2015-04-15 18:57:53,33\n2015-04-15 19:02:53,23\n2015-04-15 19:07:53,26\n2015-04-15 19:12:53,20\n2015-04-15 19:17:53,31\n2015-04-15 19:22:53,14\n2015-04-15 19:27:53,18\n2015-04-15 19:32:53,31\n2015-04-15 19:37:53,17\n2015-04-15 19:42:53,23\n2015-04-15 19:47:53,30\n2015-04-15 19:52:53,24\n2015-04-15 19:57:53,44\n2015-04-15 20:02:53,35\n2015-04-15 20:07:53,27\n2015-04-15 20:12:53,24\n2015-04-15 20:17:53,25\n2015-04-15 20:22:53,30\n2015-04-15 20:27:53,23\n2015-04-15 20:32:53,25\n2015-04-15 20:37:53,31\n2015-04-15 20:42:53,21\n2015-04-15 20:47:53,33\n2015-04-15 20:52:53,37\n2015-04-15 20:57:53,27\n2015-04-15 21:02:53,22\n2015-04-15 21:07:53,39\n2015-04-15 21:12:53,39\n2015-04-15 21:17:53,52\n2015-04-15 21:22:53,42\n2015-04-15 21:27:53,32\n2015-04-15 21:32:53,32\n2015-04-15 21:37:53,25\n2015-04-15 21:42:53,29\n2015-04-15 21:47:53,26\n2015-04-15 21:52:53,22\n2015-04-15 21:57:53,28\n2015-04-15 22:02:53,26\n2015-04-15 22:07:53,25\n2015-04-15 22:12:53,19\n2015-04-15 22:17:53,26\n2015-04-15 22:22:53,13\n2015-04-15 22:27:53,30\n2015-04-15 22:32:53,27\n2015-04-15 22:37:53,25\n2015-04-15 22:42:53,14\n2015-04-15 22:47:53,14\n2015-04-15 22:52:53,17\n2015-04-15 22:57:53,23\n2015-04-15 23:02:53,21\n2015-04-15 23:07:53,14\n2015-04-15 23:12:53,20\n2015-04-15 23:17:53,26\n2015-04-15 23:22:53,17\n2015-04-15 23:27:53,20\n2015-04-15 23:32:53,13\n2015-04-15 23:37:53,23\n2015-04-15 23:42:53,24\n2015-04-15 23:47:53,34\n2015-04-15 23:52:53,22\n2015-04-15 23:57:53,15\n2015-04-16 00:02:53,22\n2015-04-16 00:07:53,17\n2015-04-16 00:12:53,20\n2015-04-16 00:17:53,16\n2015-04-16 00:22:53,24\n2015-04-16 00:27:53,12\n2015-04-16 00:32:53,15\n2015-04-16 00:37:53,22\n2015-04-16 00:42:53,16\n2015-04-16 00:47:53,15\n2015-04-16 00:52:53,8\n2015-04-16 00:57:53,33\n2015-04-16 01:02:53,17\n2015-04-16 01:07:53,18\n2015-04-16 01:12:53,10\n2015-04-16 01:17:53,16\n2015-04-16 01:22:53,14\n2015-04-16 01:27:53,7\n2015-04-16 01:32:53,17\n2015-04-16 01:37:53,8\n2015-04-16 01:42:53,11\n2015-04-16 01:47:53,10\n2015-04-16 01:52:53,20\n2015-04-16 01:57:53,35\n2015-04-16 02:02:53,20\n2015-04-16 02:07:53,8\n2015-04-16 02:12:53,21\n2015-04-16 02:17:53,15\n2015-04-16 02:22:53,20\n2015-04-16 02:27:53,20\n2015-04-16 02:32:53,14\n2015-04-16 02:37:53,20\n2015-04-16 02:42:53,24\n2015-04-16 02:47:53,17\n2015-04-16 02:52:53,13\n2015-04-16 02:57:53,23\n2015-04-16 03:02:53,21\n2015-04-16 03:07:53,11\n2015-04-16 03:12:53,10\n2015-04-16 03:17:53,13\n2015-04-16 03:22:53,17\n2015-04-16 03:27:53,19\n2015-04-16 03:32:53,9\n2015-04-16 03:37:53,17\n2015-04-16 03:42:53,10\n2015-04-16 03:47:53,8\n2015-04-16 03:52:53,12\n2015-04-16 03:57:53,15\n2015-04-16 04:02:53,13\n2015-04-16 04:07:53,10\n2015-04-16 04:12:53,7\n2015-04-16 04:17:53,9\n2015-04-16 04:22:53,9\n2015-04-16 04:27:53,11\n2015-04-16 04:32:53,19\n2015-04-16 04:37:53,9\n2015-04-16 04:42:53,8\n2015-04-16 04:47:53,10\n2015-04-16 04:52:53,8\n2015-04-16 04:57:53,13\n2015-04-16 05:02:53,8\n2015-04-16 05:07:53,17\n2015-04-16 05:12:53,5\n2015-04-16 05:17:53,14\n2015-04-16 05:22:53,12\n2015-04-16 05:27:53,12\n2015-04-16 05:32:53,9\n2015-04-16 05:37:53,15\n2015-04-16 05:42:53,24\n2015-04-16 05:47:53,18\n2015-04-16 05:52:53,23\n2015-04-16 05:57:53,19\n2015-04-16 06:02:53,14\n2015-04-16 06:07:53,16\n2015-04-16 06:12:53,28\n2015-04-16 06:17:53,22\n2015-04-16 06:22:53,23\n2015-04-16 06:27:53,26\n2015-04-16 06:32:53,19\n2015-04-16 06:37:53,22\n2015-04-16 06:42:53,20\n2015-04-16 06:47:53,21\n2015-04-16 06:52:53,23\n2015-04-16 06:57:53,15\n2015-04-16 07:02:53,16\n2015-04-16 07:07:53,17\n2015-04-16 07:12:53,14\n2015-04-16 07:17:53,13\n2015-04-16 07:22:53,14\n2015-04-16 07:27:53,10\n2015-04-16 07:32:53,17\n2015-04-16 07:37:53,12\n2015-04-16 07:42:53,22\n2015-04-16 07:47:53,19\n2015-04-16 07:52:53,15\n2015-04-16 07:57:53,18\n2015-04-16 08:02:53,12\n2015-04-16 08:07:53,17\n2015-04-16 08:12:53,16\n2015-04-16 08:17:53,22\n2015-04-16 08:22:53,15\n2015-04-16 08:27:53,18\n2015-04-16 08:32:53,12\n2015-04-16 08:37:53,18\n2015-04-16 08:42:53,16\n2015-04-16 08:47:53,18\n2015-04-16 08:52:53,11\n2015-04-16 08:57:53,13\n2015-04-16 09:02:53,13\n2015-04-16 09:07:53,11\n2015-04-16 09:12:53,13\n2015-04-16 09:17:53,14\n2015-04-16 09:22:53,17\n2015-04-16 09:27:53,29\n2015-04-16 09:32:53,23\n2015-04-16 09:37:53,25\n2015-04-16 09:42:53,11\n2015-04-16 09:47:53,25\n2015-04-16 09:52:53,21\n2015-04-16 09:57:53,20\n2015-04-16 10:02:53,15\n2015-04-16 10:07:53,18\n2015-04-16 10:12:53,30\n2015-04-16 10:17:53,13\n2015-04-16 10:22:53,16\n2015-04-16 10:27:53,19\n2015-04-16 10:32:53,27\n2015-04-16 10:37:53,24\n2015-04-16 10:42:53,18\n2015-04-16 10:47:53,12\n2015-04-16 10:52:53,24\n2015-04-16 10:57:53,19\n2015-04-16 11:02:53,29\n2015-04-16 11:07:53,31\n2015-04-16 11:12:53,18\n2015-04-16 11:17:53,19\n2015-04-16 11:22:53,11\n2015-04-16 11:27:53,20\n2015-04-16 11:32:53,12\n2015-04-16 11:37:53,14\n2015-04-16 11:42:53,12\n2015-04-16 11:47:53,11\n2015-04-16 11:52:53,10\n2015-04-16 11:57:53,24\n2015-04-16 12:02:53,22\n2015-04-16 12:07:53,23\n2015-04-16 12:12:53,21\n2015-04-16 12:17:53,13\n2015-04-16 12:22:53,20\n2015-04-16 12:27:53,24\n2015-04-16 12:32:53,9\n2015-04-16 12:37:53,15\n2015-04-16 12:42:53,24\n2015-04-16 12:47:53,22\n2015-04-16 12:52:53,17\n2015-04-16 12:57:53,31\n2015-04-16 13:02:53,39\n2015-04-16 13:07:53,18\n2015-04-16 13:12:53,41\n2015-04-16 13:17:53,35\n2015-04-16 13:22:53,44\n2015-04-16 13:27:53,32\n2015-04-16 13:32:53,34\n2015-04-16 13:37:53,28\n2015-04-16 13:42:53,34\n2015-04-16 13:47:53,44\n2015-04-16 13:52:53,40\n2015-04-16 13:57:53,31\n2015-04-16 14:02:53,43\n2015-04-16 14:07:53,27\n2015-04-16 14:12:53,33\n2015-04-16 14:17:53,40\n2015-04-16 14:22:53,34\n2015-04-16 14:27:53,22\n2015-04-16 14:32:53,30\n2015-04-16 14:37:53,30\n2015-04-16 14:42:53,26\n2015-04-16 14:47:53,40\n2015-04-16 14:52:53,34\n2015-04-16 14:57:53,27\n2015-04-16 15:02:53,29\n2015-04-16 15:07:53,21\n2015-04-16 15:12:53,22\n2015-04-16 15:17:53,21\n2015-04-16 15:22:53,36\n2015-04-16 15:27:53,26\n2015-04-16 15:32:53,19\n2015-04-16 15:37:53,24\n2015-04-16 15:42:53,30\n2015-04-16 15:47:53,29\n2015-04-16 15:52:53,17\n2015-04-16 15:57:53,41\n2015-04-16 16:02:53,20\n2015-04-16 16:07:53,28\n2015-04-16 16:12:53,36\n2015-04-16 16:17:53,30\n2015-04-16 16:22:53,42\n2015-04-16 16:27:53,29\n2015-04-16 16:32:53,24\n2015-04-16 16:37:53,23\n2015-04-16 16:42:53,27\n2015-04-16 16:47:53,23\n2015-04-16 16:52:53,27\n2015-04-16 16:57:53,28\n2015-04-16 17:02:53,26\n2015-04-16 17:07:53,37\n2015-04-16 17:12:53,42\n2015-04-16 17:17:53,31\n2015-04-16 17:22:53,27\n2015-04-16 17:27:53,34\n2015-04-16 17:32:53,22\n2015-04-16 17:37:53,38\n2015-04-16 17:42:53,24\n2015-04-16 17:47:53,26\n2015-04-16 17:52:53,25\n2015-04-16 17:57:53,32\n2015-04-16 18:02:53,31\n2015-04-16 18:07:53,30\n2015-04-16 18:12:53,24\n2015-04-16 18:17:53,29\n2015-04-16 18:22:53,35\n2015-04-16 18:27:53,36\n2015-04-16 18:32:53,20\n2015-04-16 18:37:53,22\n2015-04-16 18:42:53,36\n2015-04-16 18:47:53,43\n2015-04-16 18:52:53,39\n2015-04-16 18:57:53,46\n2015-04-16 19:02:53,23\n2015-04-16 19:07:53,23\n2015-04-16 19:12:53,30\n2015-04-16 19:17:53,25\n2015-04-16 19:22:53,26\n2015-04-16 19:27:53,17\n2015-04-16 19:32:53,14\n2015-04-16 19:37:53,15\n2015-04-16 19:42:53,53\n2015-04-16 19:47:53,28\n2015-04-16 19:52:53,29\n2015-04-16 19:57:53,40\n2015-04-16 20:02:53,34\n2015-04-16 20:07:53,18\n2015-04-16 20:12:53,22\n2015-04-16 20:17:53,23\n2015-04-16 20:22:53,31\n2015-04-16 20:27:53,21\n2015-04-16 20:32:53,21\n2015-04-16 20:37:53,26\n2015-04-16 20:42:53,29\n2015-04-16 20:47:53,26\n2015-04-16 20:52:53,21\n2015-04-16 20:57:53,25\n2015-04-16 21:02:53,86\n2015-04-16 21:07:53,76\n2015-04-16 21:12:53,43\n2015-04-16 21:17:53,43\n2015-04-16 21:22:53,62\n2015-04-16 21:27:53,41\n2015-04-16 21:32:53,36\n2015-04-16 21:37:53,46\n2015-04-16 21:42:53,28\n2015-04-16 21:47:53,25\n2015-04-16 21:52:53,20\n2015-04-16 21:57:53,30\n2015-04-16 22:02:53,44\n2015-04-16 22:07:53,21\n2015-04-16 22:12:53,18\n2015-04-16 22:17:53,27\n2015-04-16 22:22:53,25\n2015-04-16 22:27:53,18\n2015-04-16 22:32:53,42\n2015-04-16 22:37:53,30\n2015-04-16 22:42:53,28\n2015-04-16 22:47:53,22\n2015-04-16 22:52:53,26\n2015-04-16 22:57:53,29\n2015-04-16 23:02:53,18\n2015-04-16 23:07:53,18\n2015-04-16 23:12:53,20\n2015-04-16 23:17:53,30\n2015-04-16 23:22:53,16\n2015-04-16 23:27:53,25\n2015-04-16 23:32:53,19\n2015-04-16 23:37:53,15\n2015-04-16 23:42:53,19\n2015-04-16 23:47:53,21\n2015-04-16 23:52:53,25\n2015-04-16 23:57:53,20\n2015-04-17 00:02:53,23\n2015-04-17 00:07:53,21\n2015-04-17 00:12:53,17\n2015-04-17 00:17:53,17\n2015-04-17 00:22:53,24\n2015-04-17 00:27:53,22\n2015-04-17 00:32:53,28\n2015-04-17 00:37:53,14\n2015-04-17 00:42:53,11\n2015-04-17 00:47:53,8\n2015-04-17 00:52:53,25\n2015-04-17 00:57:53,22\n2015-04-17 01:02:53,22\n2015-04-17 01:07:53,14\n2015-04-17 01:12:53,14\n2015-04-17 01:17:53,14\n2015-04-17 01:22:53,13\n2015-04-17 01:27:53,14\n2015-04-17 01:32:53,14\n2015-04-17 01:37:53,19\n2015-04-17 01:42:53,15\n2015-04-17 01:47:53,20\n2015-04-17 01:52:53,14\n2015-04-17 01:57:53,26\n2015-04-17 02:02:53,13\n2015-04-17 02:07:53,16\n2015-04-17 02:12:53,20\n2015-04-17 02:17:53,24\n2015-04-17 02:22:53,17\n2015-04-17 02:27:53,14\n2015-04-17 02:32:53,12\n2015-04-17 02:37:53,15\n2015-04-17 02:42:53,15\n2015-04-17 02:47:53,14\n2015-04-17 02:52:53,12\n2015-04-17 02:57:53,17\n2015-04-17 03:02:53,18\n2015-04-17 03:07:53,9\n2015-04-17 03:12:53,7\n2015-04-17 03:17:53,9\n2015-04-17 03:22:53,9\n2015-04-17 03:27:53,20\n2015-04-17 03:32:53,11\n2015-04-17 03:37:53,10\n2015-04-17 03:42:53,11\n2015-04-17 03:47:53,15\n2015-04-17 03:52:53,8\n2015-04-17 03:57:53,31\n2015-04-17 04:02:53,24\n2015-04-17 04:07:53,12\n2015-04-17 04:12:53,14\n2015-04-17 04:17:53,6\n2015-04-17 04:22:53,27\n2015-04-17 04:27:53,31\n2015-04-17 04:32:53,25\n2015-04-17 04:37:53,12\n2015-04-17 04:42:53,15\n2015-04-17 04:47:53,18\n2015-04-17 04:52:53,14\n2015-04-17 04:57:53,25\n2015-04-17 05:02:53,13\n2015-04-17 05:07:53,16\n2015-04-17 05:12:53,14\n2015-04-17 05:17:53,9\n2015-04-17 05:22:53,13\n2015-04-17 05:27:53,13\n2015-04-17 05:32:53,9\n2015-04-17 05:37:53,16\n2015-04-17 05:42:53,17\n2015-04-17 05:47:53,10\n2015-04-17 05:52:53,9\n2015-04-17 05:57:53,15\n2015-04-17 06:02:53,12\n2015-04-17 06:07:53,16\n2015-04-17 06:12:53,7\n2015-04-17 06:17:53,35\n2015-04-17 06:22:53,17\n2015-04-17 06:27:53,15\n2015-04-17 06:32:53,22\n2015-04-17 06:37:53,14\n2015-04-17 06:42:53,14\n2015-04-17 06:47:53,9\n2015-04-17 06:52:53,13\n2015-04-17 06:57:53,10\n2015-04-17 07:02:53,16\n2015-04-17 07:07:53,26\n2015-04-17 07:12:53,8\n2015-04-17 07:17:53,10\n2015-04-17 07:22:53,15\n2015-04-17 07:27:53,22\n2015-04-17 07:32:53,21\n2015-04-17 07:37:53,14\n2015-04-17 07:42:53,22\n2015-04-17 07:47:53,16\n2015-04-17 07:52:53,22\n2015-04-17 07:57:53,10\n2015-04-17 08:02:53,21\n2015-04-17 08:07:53,10\n2015-04-17 08:12:53,12\n2015-04-17 08:17:53,12\n2015-04-17 08:22:53,22\n2015-04-17 08:27:53,10\n2015-04-17 08:32:53,12\n2015-04-17 08:37:53,20\n2015-04-17 08:42:53,10\n2015-04-17 08:47:53,132\n2015-04-17 08:52:53,6\n2015-04-17 08:57:53,20\n2015-04-17 09:02:53,10\n2015-04-17 09:07:53,24\n2015-04-17 09:12:53,14\n2015-04-17 09:17:53,15\n2015-04-17 09:22:53,13\n2015-04-17 09:27:53,19\n2015-04-17 09:32:53,11\n2015-04-17 09:37:53,10\n2015-04-17 09:42:53,10\n2015-04-17 09:47:53,130\n2015-04-17 09:52:53,15\n2015-04-17 09:57:53,17\n2015-04-17 10:02:53,13\n2015-04-17 10:07:53,21\n2015-04-17 10:12:53,16\n2015-04-17 10:17:53,9\n2015-04-17 10:22:53,8\n2015-04-17 10:27:53,13\n2015-04-17 10:32:53,11\n2015-04-17 10:37:53,15\n2015-04-17 10:42:53,18\n2015-04-17 10:47:53,11\n2015-04-17 10:52:53,11\n2015-04-17 10:57:53,22\n2015-04-17 11:02:53,20\n2015-04-17 11:07:53,30\n2015-04-17 11:12:53,18\n2015-04-17 11:17:53,18\n2015-04-17 11:22:53,14\n2015-04-17 11:27:53,25\n2015-04-17 11:32:53,12\n2015-04-17 11:37:53,6\n2015-04-17 11:42:53,15\n2015-04-17 11:47:53,8\n2015-04-17 11:52:53,13\n2015-04-17 11:57:53,19\n2015-04-17 12:02:53,20\n2015-04-17 12:07:53,11\n2015-04-17 12:12:53,18\n2015-04-17 12:17:53,19\n2015-04-17 12:22:53,8\n2015-04-17 12:27:53,19\n2015-04-17 12:32:53,18\n2015-04-17 12:37:53,17\n2015-04-17 12:42:53,26\n2015-04-17 12:47:53,25\n2015-04-17 12:52:53,24\n2015-04-17 12:57:53,29\n2015-04-17 13:02:53,36\n2015-04-17 13:07:53,30\n2015-04-17 13:12:53,22\n2015-04-17 13:17:53,14\n2015-04-17 13:22:53,20\n2015-04-17 13:27:53,14\n2015-04-17 13:32:53,22\n2015-04-17 13:37:53,22\n2015-04-17 13:42:53,23\n2015-04-17 13:47:53,24\n2015-04-17 13:52:53,27\n2015-04-17 13:57:53,20\n2015-04-17 14:02:53,25\n2015-04-17 14:07:53,36\n2015-04-17 14:12:53,27\n2015-04-17 14:17:53,26\n2015-04-17 14:22:53,23\n2015-04-17 14:27:53,32\n2015-04-17 14:32:53,26\n2015-04-17 14:37:53,23\n2015-04-17 14:42:53,33\n2015-04-17 14:47:53,33\n2015-04-17 14:52:53,29\n2015-04-17 14:57:53,31\n2015-04-17 15:02:53,27\n2015-04-17 15:07:53,25\n2015-04-17 15:12:53,28\n2015-04-17 15:17:53,27\n2015-04-17 15:22:53,26\n2015-04-17 15:27:53,42\n2015-04-17 15:32:53,37\n2015-04-17 15:37:53,37\n2015-04-17 15:42:53,30\n2015-04-17 15:47:53,31\n2015-04-17 15:52:53,28\n2015-04-17 15:57:53,37\n2015-04-17 16:02:53,36\n2015-04-17 16:07:53,14\n2015-04-17 16:12:53,21\n2015-04-17 16:17:53,18\n2015-04-17 16:22:53,17\n2015-04-17 16:27:53,26\n2015-04-17 16:32:53,18\n2015-04-17 16:37:53,22\n2015-04-17 16:42:53,9\n2015-04-17 16:47:53,23\n2015-04-17 16:52:53,22\n2015-04-17 16:57:53,31\n2015-04-17 17:02:53,19\n2015-04-17 17:07:53,17\n2015-04-17 17:12:53,15\n2015-04-17 17:17:53,33\n2015-04-17 17:22:53,18\n2015-04-17 17:27:53,26\n2015-04-17 17:32:53,19\n2015-04-17 17:37:53,47\n2015-04-17 17:42:53,26\n2015-04-17 17:47:53,19\n2015-04-17 17:52:53,27\n2015-04-17 17:57:53,23\n2015-04-17 18:02:53,28\n2015-04-17 18:07:53,21\n2015-04-17 18:12:53,22\n2015-04-17 18:17:53,31\n2015-04-17 18:22:53,26\n2015-04-17 18:27:53,37\n2015-04-17 18:32:53,19\n2015-04-17 18:37:53,5\n2015-04-17 18:42:53,32\n2015-04-17 18:47:53,42\n2015-04-17 18:52:53,28\n2015-04-17 18:57:53,25\n2015-04-17 19:02:53,28\n2015-04-17 19:07:53,26\n2015-04-17 19:12:53,25\n2015-04-17 19:17:53,24\n2015-04-17 19:22:53,15\n2015-04-17 19:27:53,14\n2015-04-17 19:32:53,22\n2015-04-17 19:37:53,22\n2015-04-17 19:42:53,28\n2015-04-17 19:47:53,45\n2015-04-17 19:52:53,38\n2015-04-17 19:57:53,40\n2015-04-17 20:02:53,27\n2015-04-17 20:07:53,22\n2015-04-17 20:12:53,23\n2015-04-17 20:17:53,21\n2015-04-17 20:22:53,18\n2015-04-17 20:27:53,29\n2015-04-17 20:32:53,12\n2015-04-17 20:37:53,26\n2015-04-17 20:42:53,11\n2015-04-17 20:47:53,15\n2015-04-17 20:52:53,33\n2015-04-17 20:57:53,19\n2015-04-17 21:02:53,12\n2015-04-17 21:07:53,21\n2015-04-17 21:12:53,21\n2015-04-17 21:17:53,12\n2015-04-17 21:22:53,16\n2015-04-17 21:27:53,13\n2015-04-17 21:32:53,9\n2015-04-17 21:37:53,14\n2015-04-17 21:42:53,20\n2015-04-17 21:47:53,13\n2015-04-17 21:52:53,11\n2015-04-17 21:57:53,16\n2015-04-17 22:02:53,17\n2015-04-17 22:07:53,18\n2015-04-17 22:12:53,24\n2015-04-17 22:17:53,8\n2015-04-17 22:22:53,10\n2015-04-17 22:27:53,15\n2015-04-17 22:32:53,15\n2015-04-17 22:37:53,9\n2015-04-17 22:42:53,4\n2015-04-17 22:47:53,18\n2015-04-17 22:52:53,9\n2015-04-17 22:57:53,17\n2015-04-17 23:02:53,19\n2015-04-17 23:07:53,10\n2015-04-17 23:12:53,5\n2015-04-17 23:17:53,9\n2015-04-17 23:22:53,3\n2015-04-17 23:27:53,20\n2015-04-17 23:32:53,14\n2015-04-17 23:37:53,17\n2015-04-17 23:42:53,15\n2015-04-17 23:47:53,19\n2015-04-17 23:52:53,10\n2015-04-17 23:57:53,23\n2015-04-18 00:02:53,15\n2015-04-18 00:07:53,11\n2015-04-18 00:12:53,9\n2015-04-18 00:17:53,13\n2015-04-18 00:22:53,14\n2015-04-18 00:27:53,13\n2015-04-18 00:32:53,13\n2015-04-18 00:37:53,10\n2015-04-18 00:42:53,13\n2015-04-18 00:47:53,7\n2015-04-18 00:52:53,11\n2015-04-18 00:57:53,25\n2015-04-18 01:02:53,13\n2015-04-18 01:07:53,12\n2015-04-18 01:12:53,15\n2015-04-18 01:17:53,11\n2015-04-18 01:22:53,11\n2015-04-18 01:27:53,8\n2015-04-18 01:32:53,14\n2015-04-18 01:37:53,12\n2015-04-18 01:42:53,10\n2015-04-18 01:47:53,8\n2015-04-18 01:52:53,19\n2015-04-18 01:57:53,10\n2015-04-18 02:02:53,15\n2015-04-18 02:07:53,14\n2015-04-18 02:12:53,13\n2015-04-18 02:17:53,10\n2015-04-18 02:22:53,12\n2015-04-18 02:27:53,6\n2015-04-18 02:32:53,8\n2015-04-18 02:37:53,12\n2015-04-18 02:42:53,9\n2015-04-18 02:47:53,10\n2015-04-18 02:52:53,14\n2015-04-18 02:57:53,7\n2015-04-18 03:02:53,19\n2015-04-18 03:07:53,8\n2015-04-18 03:12:53,3\n2015-04-18 03:17:53,8\n2015-04-18 03:22:53,3\n2015-04-18 03:27:53,19\n2015-04-18 03:32:53,8\n2015-04-18 03:37:53,9\n2015-04-18 03:42:53,12\n2015-04-18 03:47:53,12\n2015-04-18 03:52:53,9\n2015-04-18 03:57:53,12\n2015-04-18 04:02:53,19\n2015-04-18 04:07:53,18\n2015-04-18 04:12:53,15\n2015-04-18 04:17:53,9\n2015-04-18 04:22:53,8\n2015-04-18 04:27:53,14\n2015-04-18 04:32:53,5\n2015-04-18 04:37:53,8\n2015-04-18 04:42:53,10\n2015-04-18 04:47:53,7\n2015-04-18 04:52:53,5\n2015-04-18 04:57:53,9\n2015-04-18 05:02:53,16\n2015-04-18 05:07:53,13\n2015-04-18 05:12:53,13\n2015-04-18 05:17:53,9\n2015-04-18 05:22:53,5\n2015-04-18 05:27:53,14\n2015-04-18 05:32:53,7\n2015-04-18 05:37:53,10\n2015-04-18 05:42:53,9\n2015-04-18 05:47:53,12\n2015-04-18 05:52:53,10\n2015-04-18 05:57:53,19\n2015-04-18 06:02:53,14\n2015-04-18 06:07:53,5\n2015-04-18 06:12:53,7\n2015-04-18 06:17:53,7\n2015-04-18 06:22:53,8\n2015-04-18 06:27:53,8\n2015-04-18 06:32:53,10\n2015-04-18 06:37:53,9\n2015-04-18 06:42:53,4\n2015-04-18 06:47:53,5\n2015-04-18 06:52:53,5\n2015-04-18 06:57:53,4\n2015-04-18 07:02:53,3\n2015-04-18 07:07:53,4\n2015-04-18 07:12:53,9\n2015-04-18 07:17:53,4\n2015-04-18 07:22:53,1\n2015-04-18 07:27:53,5\n2015-04-18 07:32:53,4\n2015-04-18 07:37:53,15\n2015-04-18 07:42:53,5\n2015-04-18 07:47:53,7\n2015-04-18 07:52:53,9\n2015-04-18 07:57:53,7\n2015-04-18 08:02:53,12\n2015-04-18 08:07:53,7\n2015-04-18 08:12:53,6\n2015-04-18 08:17:53,5\n2015-04-18 08:22:53,7\n2015-04-18 08:27:53,7\n2015-04-18 08:32:53,4\n2015-04-18 08:37:53,12\n2015-04-18 08:42:53,7\n2015-04-18 08:47:53,5\n2015-04-18 08:52:53,10\n2015-04-18 08:57:53,19\n2015-04-18 09:02:53,6\n2015-04-18 09:07:53,8\n2015-04-18 09:12:53,4\n2015-04-18 09:17:53,6\n2015-04-18 09:22:53,5\n2015-04-18 09:27:53,10\n2015-04-18 09:32:53,8\n2015-04-18 09:37:53,6\n2015-04-18 09:42:53,9\n2015-04-18 09:47:53,6\n2015-04-18 09:52:53,5\n2015-04-18 09:57:53,13\n2015-04-18 10:02:53,15\n2015-04-18 10:07:53,5\n2015-04-18 10:12:53,4\n2015-04-18 10:17:53,16\n2015-04-18 10:22:53,9\n2015-04-18 10:27:53,17\n2015-04-18 10:32:53,7\n2015-04-18 10:37:53,8\n2015-04-18 10:42:53,9\n2015-04-18 10:47:53,5\n2015-04-18 10:52:53,6\n2015-04-18 10:57:53,9\n2015-04-18 11:02:53,2\n2015-04-18 11:07:53,10\n2015-04-18 11:12:53,11\n2015-04-18 11:17:53,14\n2015-04-18 11:22:53,8\n2015-04-18 11:27:53,11\n2015-04-18 11:32:53,11\n2015-04-18 11:37:53,7\n2015-04-18 11:42:53,9\n2015-04-18 11:47:53,7\n2015-04-18 11:52:53,5\n2015-04-18 11:57:53,9\n2015-04-18 12:02:53,19\n2015-04-18 12:07:53,11\n2015-04-18 12:12:53,5\n2015-04-18 12:17:53,7\n2015-04-18 12:22:53,15\n2015-04-18 12:27:53,7\n2015-04-18 12:32:53,6\n2015-04-18 12:37:53,5\n2015-04-18 12:42:53,7\n2015-04-18 12:47:53,7\n2015-04-18 12:52:53,14\n2015-04-18 12:57:53,15\n2015-04-18 13:02:53,10\n2015-04-18 13:07:53,11\n2015-04-18 13:12:53,17\n2015-04-18 13:17:53,8\n2015-04-18 13:22:53,7\n2015-04-18 13:27:53,5\n2015-04-18 13:32:53,7\n2015-04-18 13:37:53,17\n2015-04-18 13:42:53,12\n2015-04-18 13:47:53,13\n2015-04-18 13:52:53,14\n2015-04-18 13:57:53,16\n2015-04-18 14:02:53,16\n2015-04-18 14:07:53,17\n2015-04-18 14:12:53,13\n2015-04-18 14:17:53,9\n2015-04-18 14:22:53,10\n2015-04-18 14:27:53,10\n2015-04-18 14:32:53,23\n2015-04-18 14:37:53,13\n2015-04-18 14:42:53,11\n2015-04-18 14:47:53,22\n2015-04-18 14:52:53,18\n2015-04-18 14:57:53,16\n2015-04-18 15:02:53,16\n2015-04-18 15:07:53,17\n2015-04-18 15:12:53,12\n2015-04-18 15:17:53,11\n2015-04-18 15:22:53,25\n2015-04-18 15:27:53,7\n2015-04-18 15:32:53,15\n2015-04-18 15:37:53,11\n2015-04-18 15:42:53,15\n2015-04-18 15:47:53,18\n2015-04-18 15:52:53,12\n2015-04-18 15:57:53,13\n2015-04-18 16:02:53,17\n2015-04-18 16:07:53,14\n2015-04-18 16:12:53,14\n2015-04-18 16:17:53,32\n2015-04-18 16:22:53,26\n2015-04-18 16:27:53,18\n2015-04-18 16:32:53,13\n2015-04-18 16:37:53,20\n2015-04-18 16:42:53,16\n2015-04-18 16:47:53,15\n2015-04-18 16:52:53,16\n2015-04-18 16:57:53,10\n2015-04-18 17:02:53,10\n2015-04-18 17:07:53,19\n2015-04-18 17:12:53,17\n2015-04-18 17:17:53,14\n2015-04-18 17:22:53,18\n2015-04-18 17:27:53,18\n2015-04-18 17:32:53,10\n2015-04-18 17:37:53,15\n2015-04-18 17:42:53,8\n2015-04-18 17:47:53,7\n2015-04-18 17:52:53,7\n2015-04-18 17:57:53,12\n2015-04-18 18:02:53,13\n2015-04-18 18:07:53,17\n2015-04-18 18:12:53,18\n2015-04-18 18:17:53,18\n2015-04-18 18:22:53,7\n2015-04-18 18:27:53,13\n2015-04-18 18:32:53,20\n2015-04-18 18:37:53,11\n2015-04-18 18:42:53,5\n2015-04-18 18:47:53,20\n2015-04-18 18:52:53,6\n2015-04-18 18:57:53,12\n2015-04-18 19:02:53,21\n2015-04-18 19:07:53,10\n2015-04-18 19:12:53,9\n2015-04-18 19:17:53,5\n2015-04-18 19:22:53,9\n2015-04-18 19:27:53,12\n2015-04-18 19:32:53,28\n2015-04-18 19:37:53,11\n2015-04-18 19:42:53,13\n2015-04-18 19:47:53,20\n2015-04-18 19:52:53,12\n2015-04-18 19:57:53,10\n2015-04-18 20:02:53,14\n2015-04-18 20:07:53,7\n2015-04-18 20:12:53,11\n2015-04-18 20:17:53,9\n2015-04-18 20:22:53,9\n2015-04-18 20:27:53,8\n2015-04-18 20:32:53,9\n2015-04-18 20:37:53,8\n2015-04-18 20:42:53,9\n2015-04-18 20:47:53,8\n2015-04-18 20:52:53,6\n2015-04-18 20:57:53,10\n2015-04-18 21:02:53,14\n2015-04-18 21:07:53,10\n2015-04-18 21:12:53,9\n2015-04-18 21:17:53,8\n2015-04-18 21:22:53,7\n2015-04-18 21:27:53,6\n2015-04-18 21:32:53,10\n2015-04-18 21:37:53,13\n2015-04-18 21:42:53,7\n2015-04-18 21:47:53,2\n2015-04-18 21:52:53,7\n2015-04-18 21:57:53,9\n2015-04-18 22:02:53,7\n2015-04-18 22:07:53,6\n2015-04-18 22:12:53,6\n2015-04-18 22:17:53,8\n2015-04-18 22:22:53,6\n2015-04-18 22:27:53,7\n2015-04-18 22:32:53,7\n2015-04-18 22:37:53,5\n2015-04-18 22:42:53,6\n2015-04-18 22:47:53,3\n2015-04-18 22:52:53,11\n2015-04-18 22:57:53,9\n2015-04-18 23:02:53,7\n2015-04-18 23:07:53,6\n2015-04-18 23:12:53,11\n2015-04-18 23:17:53,18\n2015-04-18 23:22:53,11\n2015-04-18 23:27:53,8\n2015-04-18 23:32:53,8\n2015-04-18 23:37:53,8\n2015-04-18 23:42:53,13\n2015-04-18 23:47:53,15\n2015-04-18 23:52:53,9\n2015-04-18 23:57:53,13\n2015-04-19 00:02:53,10\n2015-04-19 00:07:53,8\n2015-04-19 00:12:53,5\n2015-04-19 00:17:53,2\n2015-04-19 00:22:53,11\n2015-04-19 00:27:53,8\n2015-04-19 00:32:53,9\n2015-04-19 00:37:53,15\n2015-04-19 00:42:53,5\n2015-04-19 00:47:53,5\n2015-04-19 00:52:53,5\n2015-04-19 00:57:53,5\n2015-04-19 01:02:53,5\n2015-04-19 01:07:53,7\n2015-04-19 01:12:53,11\n2015-04-19 01:17:53,6\n2015-04-19 01:22:53,12\n2015-04-19 01:27:53,10\n2015-04-19 01:32:53,14\n2015-04-19 01:37:53,8\n2015-04-19 01:42:53,7\n2015-04-19 01:47:53,7\n2015-04-19 01:52:53,7\n2015-04-19 01:57:53,6\n2015-04-19 02:02:53,6\n2015-04-19 02:07:53,15\n2015-04-19 02:12:53,7\n2015-04-19 02:17:53,6\n2015-04-19 02:22:53,10\n2015-04-19 02:27:53,3\n2015-04-19 02:32:53,6\n2015-04-19 02:37:53,8\n2015-04-19 02:42:53,5\n2015-04-19 02:47:53,9\n2015-04-19 02:52:53,8\n2015-04-19 02:57:53,11\n2015-04-19 03:02:53,4\n2015-04-19 03:07:53,15\n2015-04-19 03:12:53,8\n2015-04-19 03:17:53,11\n2015-04-19 03:22:53,5\n2015-04-19 03:27:53,2\n2015-04-19 03:32:53,11\n2015-04-19 03:37:53,8\n2015-04-19 03:42:53,4\n2015-04-19 03:47:53,10\n2015-04-19 03:52:53,2\n2015-04-19 03:57:53,3\n2015-04-19 04:02:53,10\n2015-04-19 04:07:53,5\n2015-04-19 04:12:53,4\n2015-04-19 04:17:53,4\n2015-04-19 04:22:53,4\n2015-04-19 04:27:53,4\n2015-04-19 04:32:53,6\n2015-04-19 04:37:53,11\n2015-04-19 04:42:53,8\n2015-04-19 04:47:53,6\n2015-04-19 04:52:53,5\n2015-04-19 04:57:53,18\n2015-04-19 05:02:53,19\n2015-04-19 05:07:53,13\n2015-04-19 05:12:53,11\n2015-04-19 05:17:53,8\n2015-04-19 05:22:53,10\n2015-04-19 05:27:53,8\n2015-04-19 05:32:53,11\n2015-04-19 05:37:53,6\n2015-04-19 05:42:53,14\n2015-04-19 05:47:53,14\n2015-04-19 05:52:53,6\n2015-04-19 05:57:53,3\n2015-04-19 06:02:53,7\n2015-04-19 06:07:53,8\n2015-04-19 06:12:53,5\n2015-04-19 06:17:53,5\n2015-04-19 06:22:53,7\n2015-04-19 06:27:53,3\n2015-04-19 06:32:53,3\n2015-04-19 06:37:53,5\n2015-04-19 06:42:53,8\n2015-04-19 06:47:53,9\n2015-04-19 06:52:53,6\n2015-04-19 06:57:53,5\n2015-04-19 07:02:53,10\n2015-04-19 07:07:53,4\n2015-04-19 07:12:53,8\n2015-04-19 07:17:53,3\n2015-04-19 07:22:53,12\n2015-04-19 07:27:53,6\n2015-04-19 07:32:53,6\n2015-04-19 07:37:53,6\n2015-04-19 07:42:53,9\n2015-04-19 07:47:53,4\n2015-04-19 07:52:53,5\n2015-04-19 07:57:53,5\n2015-04-19 08:02:53,5\n2015-04-19 08:07:53,10\n2015-04-19 08:12:53,8\n2015-04-19 08:17:53,7\n2015-04-19 08:22:53,5\n2015-04-19 08:27:53,6\n2015-04-19 08:32:53,6\n2015-04-19 08:37:53,12\n2015-04-19 08:42:53,6\n2015-04-19 08:47:53,3\n2015-04-19 08:52:53,4\n2015-04-19 08:57:53,6\n2015-04-19 09:02:53,11\n2015-04-19 09:07:53,3\n2015-04-19 09:12:53,11\n2015-04-19 09:17:53,4\n2015-04-19 09:22:53,8\n2015-04-19 09:27:53,10\n2015-04-19 09:32:53,13\n2015-04-19 09:37:53,4\n2015-04-19 09:42:53,11\n2015-04-19 09:47:53,10\n2015-04-19 09:52:53,6\n2015-04-19 09:57:53,5\n2015-04-19 10:02:53,8\n2015-04-19 10:07:53,4\n2015-04-19 10:12:53,6\n2015-04-19 10:17:53,6\n2015-04-19 10:22:53,4\n2015-04-19 10:27:53,8\n2015-04-19 10:32:53,2\n2015-04-19 10:37:53,8\n2015-04-19 10:42:53,11\n2015-04-19 10:47:53,15\n2015-04-19 10:52:53,8\n2015-04-19 10:57:53,13\n2015-04-19 11:02:53,6\n2015-04-19 11:07:53,7\n2015-04-19 11:12:53,12\n2015-04-19 11:17:53,3\n2015-04-19 11:22:53,5\n2015-04-19 11:27:53,5\n2015-04-19 11:32:53,12\n2015-04-19 11:37:53,5\n2015-04-19 11:42:53,1\n2015-04-19 11:47:53,5\n2015-04-19 11:52:53,10\n2015-04-19 11:57:53,14\n2015-04-19 12:02:53,8\n2015-04-19 12:07:53,4\n2015-04-19 12:12:53,2\n2015-04-19 12:17:53,13\n2015-04-19 12:22:53,6\n2015-04-19 12:27:53,5\n2015-04-19 12:32:53,10\n2015-04-19 12:37:53,12\n2015-04-19 12:42:53,11\n2015-04-19 12:47:53,12\n2015-04-19 12:52:53,11\n2015-04-19 12:57:53,7\n2015-04-19 13:02:53,15\n2015-04-19 13:07:53,8\n2015-04-19 13:12:53,14\n2015-04-19 13:17:53,15\n2015-04-19 13:22:53,5\n2015-04-19 13:27:53,5\n2015-04-19 13:32:53,11\n2015-04-19 13:37:53,4\n2015-04-19 13:42:53,10\n2015-04-19 13:47:53,6\n2015-04-19 13:52:53,7\n2015-04-19 13:57:53,4\n2015-04-19 14:02:53,11\n2015-04-19 14:07:53,7\n2015-04-19 14:12:53,7\n2015-04-19 14:17:53,4\n2015-04-19 14:22:53,13\n2015-04-19 14:27:53,8\n2015-04-19 14:32:53,8\n2015-04-19 14:37:53,10\n2015-04-19 14:42:53,7\n2015-04-19 14:47:53,14\n2015-04-19 14:52:53,20\n2015-04-19 14:57:53,9\n2015-04-19 15:02:53,12\n2015-04-19 15:07:53,12\n2015-04-19 15:12:53,3\n2015-04-19 15:17:53,6\n2015-04-19 15:22:53,7\n2015-04-19 15:27:53,5\n2015-04-19 15:32:53,16\n2015-04-19 15:37:53,14\n2015-04-19 15:42:53,10\n2015-04-19 15:47:53,12\n2015-04-19 15:52:53,9\n2015-04-19 15:57:53,16\n2015-04-19 16:02:53,23\n2015-04-19 16:07:53,9\n2015-04-19 16:12:53,8\n2015-04-19 16:17:53,6\n2015-04-19 16:22:53,4\n2015-04-19 16:27:53,11\n2015-04-19 16:32:53,12\n2015-04-19 16:37:53,6\n2015-04-19 16:42:53,6\n2015-04-19 16:47:53,12\n2015-04-19 16:52:53,12\n2015-04-19 16:57:53,7\n2015-04-19 17:02:53,20\n2015-04-19 17:07:53,14\n2015-04-19 17:12:53,11\n2015-04-19 17:17:53,10\n2015-04-19 17:22:53,9\n2015-04-19 17:27:53,15\n2015-04-19 17:32:53,14\n2015-04-19 17:37:53,11\n2015-04-19 17:42:53,13\n2015-04-19 17:47:53,21\n2015-04-19 17:52:53,7\n2015-04-19 17:57:53,15\n2015-04-19 18:02:53,9\n2015-04-19 18:07:53,12\n2015-04-19 18:12:53,11\n2015-04-19 18:17:53,14\n2015-04-19 18:22:53,8\n2015-04-19 18:27:53,19\n2015-04-19 18:32:53,18\n2015-04-19 18:37:53,12\n2015-04-19 18:42:53,26\n2015-04-19 18:47:53,18\n2015-04-19 18:52:53,17\n2015-04-19 18:57:53,12\n2015-04-19 19:02:53,7\n2015-04-19 19:07:53,10\n2015-04-19 19:12:53,10\n2015-04-19 19:17:53,10\n2015-04-19 19:22:53,8\n2015-04-19 19:27:53,10\n2015-04-19 19:32:53,14\n2015-04-19 19:37:53,5\n2015-04-19 19:42:53,9\n2015-04-19 19:47:53,11\n2015-04-19 19:52:53,7\n2015-04-19 19:57:53,12\n2015-04-19 20:02:53,9\n2015-04-19 20:07:53,14\n2015-04-19 20:12:53,8\n2015-04-19 20:17:53,19\n2015-04-19 20:22:53,6\n2015-04-19 20:27:53,11\n2015-04-19 20:32:53,12\n2015-04-19 20:37:53,14\n2015-04-19 20:42:53,18\n2015-04-19 20:47:53,5\n2015-04-19 20:52:53,8\n2015-04-19 20:57:53,19\n2015-04-19 21:02:53,19\n2015-04-19 21:07:53,10\n2015-04-19 21:12:53,14\n2015-04-19 21:17:53,8\n2015-04-19 21:22:53,8\n2015-04-19 21:27:53,16\n2015-04-19 21:32:53,16\n2015-04-19 21:37:53,15\n2015-04-19 21:42:53,16\n2015-04-19 21:47:53,16\n2015-04-19 21:52:53,10\n2015-04-19 21:57:53,6\n2015-04-19 22:02:53,15\n2015-04-19 22:07:53,6\n2015-04-19 22:12:53,9\n2015-04-19 22:17:53,6\n2015-04-19 22:22:53,10\n2015-04-19 22:27:53,19\n2015-04-19 22:32:53,10\n2015-04-19 22:37:53,2\n2015-04-19 22:42:53,9\n2015-04-19 22:47:53,11\n2015-04-19 22:52:53,18\n2015-04-19 22:57:53,19\n2015-04-19 23:02:53,13\n2015-04-19 23:07:53,9\n2015-04-19 23:12:53,13\n2015-04-19 23:17:53,17\n2015-04-19 23:22:53,5\n2015-04-19 23:27:53,12\n2015-04-19 23:32:53,12\n2015-04-19 23:37:53,8\n2015-04-19 23:42:53,4\n2015-04-19 23:47:53,7\n2015-04-19 23:52:53,7\n2015-04-19 23:57:53,6\n2015-04-20 00:02:53,4\n2015-04-20 00:07:53,13\n2015-04-20 00:12:53,14\n2015-04-20 00:17:53,4\n2015-04-20 00:22:53,4\n2015-04-20 00:27:53,10\n2015-04-20 00:32:53,5\n2015-04-20 00:37:53,3\n2015-04-20 00:42:53,7\n2015-04-20 00:47:53,23\n2015-04-20 00:52:53,7\n2015-04-20 00:57:53,12\n2015-04-20 01:02:53,8\n2015-04-20 01:07:53,15\n2015-04-20 01:12:53,10\n2015-04-20 01:17:53,7\n2015-04-20 01:22:53,18\n2015-04-20 01:27:53,13\n2015-04-20 01:32:53,10\n2015-04-20 01:37:53,16\n2015-04-20 01:42:53,8\n2015-04-20 01:47:53,9\n2015-04-20 01:52:53,6\n2015-04-20 01:57:53,19\n2015-04-20 02:02:53,5\n2015-04-20 02:07:53,10\n2015-04-20 02:12:53,10\n2015-04-20 02:17:53,14\n2015-04-20 02:22:53,7\n2015-04-20 02:27:53,14\n2015-04-20 02:32:53,7\n2015-04-20 02:37:53,7\n2015-04-20 02:42:53,5\n2015-04-20 02:47:53,8\n2015-04-20 02:52:53,5\n2015-04-20 02:57:53,10\n2015-04-20 03:02:53,0\n2015-04-20 03:07:53,16\n2015-04-20 03:12:53,7\n2015-04-20 03:17:53,11\n2015-04-20 03:22:53,13\n2015-04-20 03:27:53,14\n2015-04-20 03:32:53,15\n2015-04-20 03:37:53,6\n2015-04-20 03:42:53,9\n2015-04-20 03:47:53,8\n2015-04-20 03:52:53,16\n2015-04-20 03:57:53,15\n2015-04-20 04:02:53,14\n2015-04-20 04:07:53,9\n2015-04-20 04:12:53,13\n2015-04-20 04:17:53,11\n2015-04-20 04:22:53,9\n2015-04-20 04:27:53,8\n2015-04-20 04:32:53,3\n2015-04-20 04:37:53,6\n2015-04-20 04:42:53,8\n2015-04-20 04:47:53,14\n2015-04-20 04:52:53,9\n2015-04-20 04:57:53,10\n2015-04-20 05:02:53,6\n2015-04-20 05:07:53,4\n2015-04-20 05:12:53,9\n2015-04-20 05:17:53,16\n2015-04-20 05:22:53,11\n2015-04-20 05:27:53,8\n2015-04-20 05:32:53,8\n2015-04-20 05:37:53,1\n2015-04-20 05:42:53,5\n2015-04-20 05:47:53,12\n2015-04-20 05:52:53,3\n2015-04-20 05:57:53,15\n2015-04-20 06:02:53,16\n2015-04-20 06:07:53,7\n2015-04-20 06:12:53,4\n2015-04-20 06:17:53,10\n2015-04-20 06:22:53,7\n2015-04-20 06:27:53,13\n2015-04-20 06:32:53,5\n2015-04-20 06:37:53,15\n2015-04-20 06:42:53,5\n2015-04-20 06:47:53,7\n2015-04-20 06:52:53,15\n2015-04-20 06:57:53,14\n2015-04-20 07:02:53,4\n2015-04-20 07:07:53,11\n2015-04-20 07:12:53,10\n2015-04-20 07:17:53,9\n2015-04-20 07:22:53,7\n2015-04-20 07:27:53,8\n2015-04-20 07:32:53,9\n2015-04-20 07:37:53,12\n2015-04-20 07:42:53,8\n2015-04-20 07:47:53,13\n2015-04-20 07:52:53,11\n2015-04-20 07:57:53,20\n2015-04-20 08:02:53,14\n2015-04-20 08:07:53,15\n2015-04-20 08:12:53,11\n2015-04-20 08:17:53,11\n2015-04-20 08:22:53,12\n2015-04-20 08:27:53,10\n2015-04-20 08:32:53,14\n2015-04-20 08:37:53,8\n2015-04-20 08:42:53,9\n2015-04-20 08:47:53,8\n2015-04-20 08:52:53,8\n2015-04-20 08:57:53,13\n2015-04-20 09:02:53,12\n2015-04-20 09:07:53,18\n2015-04-20 09:12:53,10\n2015-04-20 09:17:53,7\n2015-04-20 09:22:53,13\n2015-04-20 09:27:53,11\n2015-04-20 09:32:53,12\n2015-04-20 09:37:53,9\n2015-04-20 09:42:53,14\n2015-04-20 09:47:53,8\n2015-04-20 09:52:53,10\n2015-04-20 09:57:53,16\n2015-04-20 10:02:53,11\n2015-04-20 10:07:53,7\n2015-04-20 10:12:53,11\n2015-04-20 10:17:53,10\n2015-04-20 10:22:53,16\n2015-04-20 10:27:53,10\n2015-04-20 10:32:53,11\n2015-04-20 10:37:53,7\n2015-04-20 10:42:53,7\n2015-04-20 10:47:53,7\n2015-04-20 10:52:53,8\n2015-04-20 10:57:53,13\n2015-04-20 11:02:53,7\n2015-04-20 11:07:53,15\n2015-04-20 11:12:53,11\n2015-04-20 11:17:53,13\n2015-04-20 11:22:53,13\n2015-04-20 11:27:53,14\n2015-04-20 11:32:53,16\n2015-04-20 11:37:53,27\n2015-04-20 11:42:53,16\n2015-04-20 11:47:53,27\n2015-04-20 11:52:53,12\n2015-04-20 11:57:53,32\n2015-04-20 12:02:53,26\n2015-04-20 12:07:53,19\n2015-04-20 12:12:53,21\n2015-04-20 12:17:53,27\n2015-04-20 12:22:53,16\n2015-04-20 12:27:53,29\n2015-04-20 12:32:53,15\n2015-04-20 12:37:53,18\n2015-04-20 12:42:53,16\n2015-04-20 12:47:53,16\n2015-04-20 12:52:53,27\n2015-04-20 12:57:53,41\n2015-04-20 13:02:53,27\n2015-04-20 13:07:53,24\n2015-04-20 13:12:53,32\n2015-04-20 13:17:53,38\n2015-04-20 13:22:53,33\n2015-04-20 13:27:53,24\n2015-04-20 13:32:53,33\n2015-04-20 13:37:53,25\n2015-04-20 13:42:53,35\n2015-04-20 13:47:53,32\n2015-04-20 13:52:53,23\n2015-04-20 13:57:53,33\n2015-04-20 14:02:53,35\n2015-04-20 14:07:53,35\n2015-04-20 14:12:53,36\n2015-04-20 14:17:53,44\n2015-04-20 14:22:53,26\n2015-04-20 14:27:53,37\n2015-04-20 14:32:53,30\n2015-04-20 14:37:53,21\n2015-04-20 14:42:53,32\n2015-04-20 14:47:53,23\n2015-04-20 14:52:53,32\n2015-04-20 14:57:53,30\n2015-04-20 15:02:53,25\n2015-04-20 15:07:53,28\n2015-04-20 15:12:53,26\n2015-04-20 15:17:53,24\n2015-04-20 15:22:53,32\n2015-04-20 15:27:53,29\n2015-04-20 15:32:53,29\n2015-04-20 15:37:53,26\n2015-04-20 15:42:53,29\n2015-04-20 15:47:53,30\n2015-04-20 15:52:53,25\n2015-04-20 15:57:53,38\n2015-04-20 16:02:53,19\n2015-04-20 16:07:53,28\n2015-04-20 16:12:53,23\n2015-04-20 16:17:53,32\n2015-04-20 16:22:53,25\n2015-04-20 16:27:53,22\n2015-04-20 16:32:53,24\n2015-04-20 16:37:53,22\n2015-04-20 16:42:53,59\n2015-04-20 16:47:53,39\n2015-04-20 16:52:53,36\n2015-04-20 16:57:53,27\n2015-04-20 17:02:53,49\n2015-04-20 17:07:53,31\n2015-04-20 17:12:53,29\n2015-04-20 17:17:53,32\n2015-04-20 17:22:53,30\n2015-04-20 17:27:53,27\n2015-04-20 17:32:53,23\n2015-04-20 17:37:53,24\n2015-04-20 17:42:53,34\n2015-04-20 17:47:53,27\n2015-04-20 17:52:53,28\n2015-04-20 17:57:53,42\n2015-04-20 18:02:53,75\n2015-04-20 18:07:53,39\n2015-04-20 18:12:53,34\n2015-04-20 18:17:53,42\n2015-04-20 18:22:53,43\n2015-04-20 18:27:53,25\n2015-04-20 18:32:53,46\n2015-04-20 18:37:53,35\n2015-04-20 18:42:53,43\n2015-04-20 18:47:53,30\n2015-04-20 18:52:53,29\n2015-04-20 18:57:53,31\n2015-04-20 19:02:53,46\n2015-04-20 19:07:53,23\n2015-04-20 19:12:53,25\n2015-04-20 19:17:53,28\n2015-04-20 19:22:53,27\n2015-04-20 19:27:53,32\n2015-04-20 19:32:53,20\n2015-04-20 19:37:53,17\n2015-04-20 19:42:53,22\n2015-04-20 19:47:53,16\n2015-04-20 19:52:53,19\n2015-04-20 19:57:53,30\n2015-04-20 20:02:53,32\n2015-04-20 20:07:53,33\n2015-04-20 20:12:53,16\n2015-04-20 20:17:53,20\n2015-04-20 20:22:53,17\n2015-04-20 20:27:53,17\n2015-04-20 20:32:53,17\n2015-04-20 20:37:53,26\n2015-04-20 20:42:53,31\n2015-04-20 20:47:53,23\n2015-04-20 20:52:53,17\n2015-04-20 20:57:53,29\n2015-04-20 21:02:53,14\n2015-04-20 21:07:53,29\n2015-04-20 21:12:53,16\n2015-04-20 21:17:53,14\n2015-04-20 21:22:53,15\n2015-04-20 21:27:53,26\n2015-04-20 21:32:53,22\n2015-04-20 21:37:53,27\n2015-04-20 21:42:53,18\n2015-04-20 21:47:53,18\n2015-04-20 21:52:53,22\n2015-04-20 21:57:53,29\n2015-04-20 22:02:53,34\n2015-04-20 22:07:53,42\n2015-04-20 22:12:53,25\n2015-04-20 22:17:53,15\n2015-04-20 22:22:53,14\n2015-04-20 22:27:53,28\n2015-04-20 22:32:53,16\n2015-04-20 22:37:53,29\n2015-04-20 22:42:53,31\n2015-04-20 22:47:53,28\n2015-04-20 22:52:53,16\n2015-04-20 22:57:53,28\n2015-04-20 23:02:53,24\n2015-04-20 23:07:53,16\n2015-04-20 23:12:53,15\n2015-04-20 23:17:53,10\n2015-04-20 23:22:53,10\n2015-04-20 23:27:53,15\n2015-04-20 23:32:53,12\n2015-04-20 23:37:53,20\n2015-04-20 23:42:53,13\n2015-04-20 23:47:53,29\n2015-04-20 23:52:53,22\n2015-04-20 23:57:53,18\n2015-04-21 00:02:53,14\n2015-04-21 00:07:53,21\n2015-04-21 00:12:53,16\n2015-04-21 00:17:53,17\n2015-04-21 00:22:53,20\n2015-04-21 00:27:53,14\n2015-04-21 00:32:53,16\n2015-04-21 00:37:53,20\n2015-04-21 00:42:53,21\n2015-04-21 00:47:53,23\n2015-04-21 00:52:53,26\n2015-04-21 00:57:53,35\n2015-04-21 01:02:53,16\n2015-04-21 01:07:53,18\n2015-04-21 01:12:53,25\n2015-04-21 01:17:53,15\n2015-04-21 01:22:53,14\n2015-04-21 01:27:53,17\n2015-04-21 01:32:53,11\n2015-04-21 01:37:53,16\n2015-04-21 01:42:53,35\n2015-04-21 01:47:53,10\n2015-04-21 01:52:53,14\n2015-04-21 01:57:53,9\n2015-04-21 02:02:53,13\n2015-04-21 02:07:53,20\n2015-04-21 02:12:53,19\n2015-04-21 02:17:53,10\n2015-04-21 02:22:53,20\n2015-04-21 02:27:53,16\n2015-04-21 02:32:53,12\n2015-04-21 02:37:53,11\n2015-04-21 02:42:53,11\n2015-04-21 02:47:53,12\n2015-04-21 02:52:53,13\n2015-04-21 02:57:53,11\n2015-04-21 03:02:53,8\n2015-04-21 03:07:53,8\n2015-04-21 03:12:53,13\n2015-04-21 03:17:53,13\n2015-04-21 03:22:53,7\n2015-04-21 03:27:53,20\n2015-04-21 03:32:53,20\n2015-04-21 03:37:53,14\n2015-04-21 03:42:53,11\n2015-04-21 03:47:53,17\n2015-04-21 03:52:53,13\n2015-04-21 03:57:53,12\n2015-04-21 04:02:53,12\n2015-04-21 04:07:53,12\n2015-04-21 04:12:53,14\n2015-04-21 04:17:53,16\n2015-04-21 04:22:53,13\n2015-04-21 04:27:53,15\n2015-04-21 04:32:53,10\n2015-04-21 04:37:53,14\n2015-04-21 04:42:53,9\n2015-04-21 04:47:53,13\n2015-04-21 04:52:53,12\n2015-04-21 04:57:53,14\n2015-04-21 05:02:53,9\n2015-04-21 05:07:53,14\n2015-04-21 05:12:53,21\n2015-04-21 05:17:53,16\n2015-04-21 05:22:53,12\n2015-04-21 05:27:53,16\n2015-04-21 05:32:53,8\n2015-04-21 05:37:53,18\n2015-04-21 05:42:53,14\n2015-04-21 05:47:53,11\n2015-04-21 05:52:53,26\n2015-04-21 05:57:53,8\n2015-04-21 06:02:53,18\n2015-04-21 06:07:53,19\n2015-04-21 06:12:53,14\n2015-04-21 06:17:53,8\n2015-04-21 06:22:53,8\n2015-04-21 06:27:53,27\n2015-04-21 06:32:53,17\n2015-04-21 06:37:53,26\n2015-04-21 06:42:53,16\n2015-04-21 06:47:53,24\n2015-04-21 06:52:53,24\n2015-04-21 06:57:53,17\n2015-04-21 07:02:53,17\n2015-04-21 07:07:53,14\n2015-04-21 07:12:53,24\n2015-04-21 07:17:53,19\n2015-04-21 07:22:53,11\n2015-04-21 07:27:53,25\n2015-04-21 07:32:53,13\n2015-04-21 07:37:53,20\n2015-04-21 07:42:53,27\n2015-04-21 07:47:53,32\n2015-04-21 07:52:53,38\n2015-04-21 07:57:53,18\n2015-04-21 08:02:53,23\n2015-04-21 08:07:53,8\n2015-04-21 08:12:53,23\n2015-04-21 08:17:53,19\n2015-04-21 08:22:53,14\n2015-04-21 08:27:53,27\n2015-04-21 08:32:53,24\n2015-04-21 08:37:53,17\n2015-04-21 08:42:53,21\n2015-04-21 08:47:53,18\n2015-04-21 08:52:53,23\n2015-04-21 08:57:53,23\n2015-04-21 09:02:53,23\n2015-04-21 09:07:53,20\n2015-04-21 09:12:53,29\n2015-04-21 09:17:53,24\n2015-04-21 09:22:53,18\n2015-04-21 09:27:53,17\n2015-04-21 09:32:53,16\n2015-04-21 09:37:53,15\n2015-04-21 09:42:53,17\n2015-04-21 09:47:53,13\n2015-04-21 09:52:53,35\n2015-04-21 09:57:53,29\n2015-04-21 10:02:53,34\n2015-04-21 10:07:53,13\n2015-04-21 10:12:53,19\n2015-04-21 10:17:53,29\n2015-04-21 10:22:53,32\n2015-04-21 10:27:53,18\n2015-04-21 10:32:53,19\n2015-04-21 10:37:53,22\n2015-04-21 10:42:53,25\n2015-04-21 10:47:53,33\n2015-04-21 10:52:53,24\n2015-04-21 10:57:53,33\n2015-04-21 11:02:53,22\n2015-04-21 11:07:53,24\n2015-04-21 11:12:53,30\n2015-04-21 11:17:53,29\n2015-04-21 11:22:53,24\n2015-04-21 11:27:53,25\n2015-04-21 11:32:53,20\n2015-04-21 11:37:53,22\n2015-04-21 11:42:53,27\n2015-04-21 11:47:53,26\n2015-04-21 11:52:53,34\n2015-04-21 11:57:53,24\n2015-04-21 12:02:53,49\n2015-04-21 12:07:53,27\n2015-04-21 12:12:53,24\n2015-04-21 12:17:53,32\n2015-04-21 12:22:53,24\n2015-04-21 12:27:53,31\n2015-04-21 12:32:53,32\n2015-04-21 12:37:53,39\n2015-04-21 12:42:53,28\n2015-04-21 12:47:53,21\n2015-04-21 12:52:53,21\n2015-04-21 12:57:53,29\n2015-04-21 13:02:53,43\n2015-04-21 13:07:53,17\n2015-04-21 13:12:53,30\n2015-04-21 13:17:53,27\n2015-04-21 13:22:53,22\n2015-04-21 13:27:53,22\n2015-04-21 13:32:53,44\n2015-04-21 13:37:53,41\n2015-04-21 13:42:53,23\n2015-04-21 13:47:53,34\n2015-04-21 13:52:53,36\n2015-04-21 13:57:53,24\n2015-04-21 14:02:53,40\n2015-04-21 14:07:53,32\n2015-04-21 14:12:53,27\n2015-04-21 14:17:53,36\n2015-04-21 14:22:53,54\n2015-04-21 14:27:53,79\n2015-04-21 14:32:53,52\n2015-04-21 14:37:53,55\n2015-04-21 14:42:53,60\n2015-04-21 14:47:53,44\n2015-04-21 14:52:53,51\n2015-04-21 14:57:53,56\n2015-04-21 15:02:53,67\n2015-04-21 15:07:53,38\n2015-04-21 15:12:53,82\n2015-04-21 15:17:53,59\n2015-04-21 15:22:53,46\n2015-04-21 15:27:53,74\n2015-04-21 15:32:53,41\n2015-04-21 15:37:53,34\n2015-04-21 15:42:53,57\n2015-04-21 15:47:53,47\n2015-04-21 15:52:53,42\n2015-04-21 15:57:53,31\n2015-04-21 16:02:53,42\n2015-04-21 16:07:53,44\n2015-04-21 16:12:53,52\n2015-04-21 16:17:53,43\n2015-04-21 16:22:53,47\n2015-04-21 16:27:53,59\n2015-04-21 16:32:53,39\n2015-04-21 16:37:53,36\n2015-04-21 16:42:53,43\n2015-04-21 16:47:53,30\n2015-04-21 16:52:53,32\n2015-04-21 16:57:53,52\n2015-04-21 17:02:53,40\n2015-04-21 17:07:53,36\n2015-04-21 17:12:53,34\n2015-04-21 17:17:53,39\n2015-04-21 17:22:53,54\n2015-04-21 17:27:53,30\n2015-04-21 17:32:53,36\n2015-04-21 17:37:53,44\n2015-04-21 17:42:53,25\n2015-04-21 17:47:53,29\n2015-04-21 17:52:53,45\n2015-04-21 17:57:53,41\n2015-04-21 18:02:53,37\n2015-04-21 18:07:53,38\n2015-04-21 18:12:53,35\n2015-04-21 18:17:53,32\n2015-04-21 18:22:53,40\n2015-04-21 18:27:53,29\n2015-04-21 18:32:53,37\n2015-04-21 18:37:53,41\n2015-04-21 18:42:53,32\n2015-04-21 18:47:53,28\n2015-04-21 18:52:53,36\n2015-04-21 18:57:53,119\n2015-04-21 19:02:53,69\n2015-04-21 19:07:53,43\n2015-04-21 19:12:53,61\n2015-04-21 19:17:53,30\n2015-04-21 19:22:53,25\n2015-04-21 19:27:53,59\n2015-04-21 19:32:53,31\n2015-04-21 19:37:53,34\n2015-04-21 19:42:53,27\n2015-04-21 19:47:53,81\n2015-04-21 19:52:53,93\n2015-04-21 19:57:53,68\n2015-04-21 20:02:53,44\n2015-04-21 20:07:53,46\n2015-04-21 20:12:53,46\n2015-04-21 20:17:53,52\n2015-04-21 20:22:53,34\n2015-04-21 20:27:53,47\n2015-04-21 20:32:53,60\n2015-04-21 20:37:53,37\n2015-04-21 20:42:53,44\n2015-04-21 20:47:53,53\n2015-04-21 20:52:53,29\n2015-04-21 20:57:53,39\n2015-04-21 21:02:53,38\n2015-04-21 21:07:53,29\n2015-04-21 21:12:53,30\n2015-04-21 21:17:53,43\n2015-04-21 21:22:53,26\n2015-04-21 21:27:53,21\n2015-04-21 21:32:53,25\n2015-04-21 21:37:53,32\n2015-04-21 21:42:53,21\n2015-04-21 21:47:53,16\n2015-04-21 21:52:53,19\n2015-04-21 21:57:53,32\n2015-04-21 22:02:53,22\n2015-04-21 22:07:53,19\n2015-04-21 22:12:53,16\n2015-04-21 22:17:53,30\n2015-04-21 22:22:53,23\n2015-04-21 22:27:53,35\n2015-04-21 22:32:53,31\n2015-04-21 22:37:53,27\n2015-04-21 22:42:53,32\n2015-04-21 22:47:53,24\n2015-04-21 22:52:53,21\n2015-04-21 22:57:53,23\n2015-04-21 23:02:53,22\n2015-04-21 23:07:53,28\n2015-04-21 23:12:53,19\n2015-04-21 23:17:53,30\n2015-04-21 23:22:53,23\n2015-04-21 23:27:53,30\n2015-04-21 23:32:53,13\n2015-04-21 23:37:53,14\n2015-04-21 23:42:53,13\n2015-04-21 23:47:53,30\n2015-04-21 23:52:53,60\n2015-04-21 23:57:53,53\n2015-04-22 00:02:53,30\n2015-04-22 00:07:53,35\n2015-04-22 00:12:53,32\n2015-04-22 00:17:53,32\n2015-04-22 00:22:53,21\n2015-04-22 00:27:53,32\n2015-04-22 00:32:53,24\n2015-04-22 00:37:53,30\n2015-04-22 00:42:53,16\n2015-04-22 00:47:53,27\n2015-04-22 00:52:53,25\n2015-04-22 00:57:53,16\n2015-04-22 01:02:53,37\n2015-04-22 01:07:53,31\n2015-04-22 01:12:53,18\n2015-04-22 01:17:53,56\n2015-04-22 01:22:53,38\n2015-04-22 01:27:53,19\n2015-04-22 01:32:53,13\n2015-04-22 01:37:53,28\n2015-04-22 01:42:53,16\n2015-04-22 01:47:53,21\n2015-04-22 01:52:53,19\n2015-04-22 01:57:53,31\n2015-04-22 02:02:53,59\n2015-04-22 02:07:53,39\n2015-04-22 02:12:53,29\n2015-04-22 02:17:53,35\n2015-04-22 02:22:53,29\n2015-04-22 02:27:53,36\n2015-04-22 02:32:53,21\n2015-04-22 02:37:53,14\n2015-04-22 02:42:53,23\n2015-04-22 02:47:53,17\n2015-04-22 02:52:53,29\n2015-04-22 02:57:53,33\n2015-04-22 03:02:53,17\n2015-04-22 03:07:53,23\n2015-04-22 03:12:53,14\n2015-04-22 03:17:53,14\n2015-04-22 03:22:53,22\n2015-04-22 03:27:53,22\n2015-04-22 03:32:53,22\n2015-04-22 03:37:53,26\n2015-04-22 03:42:53,12\n2015-04-22 03:47:53,16\n2015-04-22 03:52:53,23\n2015-04-22 03:57:53,29\n2015-04-22 04:02:53,18\n2015-04-22 04:07:53,13\n2015-04-22 04:12:53,11\n2015-04-22 04:17:53,17\n2015-04-22 04:22:53,18\n2015-04-22 04:27:53,19\n2015-04-22 04:32:53,29\n2015-04-22 04:37:53,17\n2015-04-22 04:42:53,22\n2015-04-22 04:47:53,18\n2015-04-22 04:52:53,26\n2015-04-22 04:57:53,24\n2015-04-22 05:02:53,31\n2015-04-22 05:07:53,21\n2015-04-22 05:12:53,32\n2015-04-22 05:17:53,39\n2015-04-22 05:22:53,22\n2015-04-22 05:27:53,41\n2015-04-22 05:32:53,22\n2015-04-22 05:37:53,23\n2015-04-22 05:42:53,37\n2015-04-22 05:47:53,23\n2015-04-22 05:52:53,34\n2015-04-22 05:57:53,29\n2015-04-22 06:02:53,23\n2015-04-22 06:07:53,28\n2015-04-22 06:12:53,30\n2015-04-22 06:17:53,21\n2015-04-22 06:22:53,28\n2015-04-22 06:27:53,18\n2015-04-22 06:32:53,10\n2015-04-22 06:37:53,24\n2015-04-22 06:42:53,21\n2015-04-22 06:47:53,26\n2015-04-22 06:52:53,21\n2015-04-22 06:57:53,22\n2015-04-22 07:02:53,37\n2015-04-22 07:07:53,29\n2015-04-22 07:12:53,26\n2015-04-22 07:17:53,28\n2015-04-22 07:22:53,25\n2015-04-22 07:27:53,19\n2015-04-22 07:32:53,26\n2015-04-22 07:37:53,26\n2015-04-22 07:42:53,18\n2015-04-22 07:47:53,16\n2015-04-22 07:52:53,26\n2015-04-22 07:57:53,24\n2015-04-22 08:02:53,29\n2015-04-22 08:07:53,40\n2015-04-22 08:12:53,28\n2015-04-22 08:17:53,39\n2015-04-22 08:22:53,26\n2015-04-22 08:27:53,35\n2015-04-22 08:32:53,24\n2015-04-22 08:37:53,31\n2015-04-22 08:42:53,26\n2015-04-22 08:47:53,28\n2015-04-22 08:52:53,28\n2015-04-22 08:57:53,30\n2015-04-22 09:02:53,41\n2015-04-22 09:07:53,31\n2015-04-22 09:12:53,28\n2015-04-22 09:17:53,23\n2015-04-22 09:22:53,32\n2015-04-22 09:27:53,23\n2015-04-22 09:32:53,30\n2015-04-22 09:37:53,18\n2015-04-22 09:42:53,40\n2015-04-22 09:47:53,21\n2015-04-22 09:52:53,26\n2015-04-22 09:57:53,30\n2015-04-22 10:02:53,27\n2015-04-22 10:07:53,29\n2015-04-22 10:12:53,34\n2015-04-22 10:17:53,31\n2015-04-22 10:22:53,39\n2015-04-22 10:27:53,39\n2015-04-22 10:32:53,31\n2015-04-22 10:37:53,37\n2015-04-22 10:42:53,30\n2015-04-22 10:47:53,29\n2015-04-22 10:52:53,24\n2015-04-22 10:57:53,36\n2015-04-22 11:02:53,38\n2015-04-22 11:07:53,41\n2015-04-22 11:12:53,27\n2015-04-22 11:17:53,21\n2015-04-22 11:22:53,33\n2015-04-22 11:27:53,36\n2015-04-22 11:32:53,33\n2015-04-22 11:37:53,44\n2015-04-22 11:42:53,37\n2015-04-22 11:47:53,26\n2015-04-22 11:52:53,31\n2015-04-22 11:57:53,50\n2015-04-22 12:02:53,45\n2015-04-22 12:07:53,131\n2015-04-22 12:12:53,127\n2015-04-22 12:17:53,39\n2015-04-22 12:22:53,30\n2015-04-22 12:27:53,42\n2015-04-22 12:32:53,38\n2015-04-22 12:37:53,40\n2015-04-22 12:42:53,36\n2015-04-22 12:47:53,58\n2015-04-22 12:52:53,31\n2015-04-22 12:57:53,47\n2015-04-22 13:02:53,46\n2015-04-22 13:07:53,35\n2015-04-22 13:12:53,47\n2015-04-22 13:17:53,53\n2015-04-22 13:22:53,57\n2015-04-22 13:27:53,51\n2015-04-22 13:32:53,42\n2015-04-22 13:37:53,42\n2015-04-22 13:42:53,48\n2015-04-22 13:47:53,39\n2015-04-22 13:52:53,38\n2015-04-22 13:57:53,62\n2015-04-22 14:02:53,134\n2015-04-22 14:07:53,30\n2015-04-22 14:12:53,31\n2015-04-22 14:17:53,54\n2015-04-22 14:22:53,29\n2015-04-22 14:27:53,116\n2015-04-22 14:32:53,59\n2015-04-22 14:37:53,65\n2015-04-22 14:42:53,69\n2015-04-22 14:47:53,68\n2015-04-22 14:52:53,42\n2015-04-22 14:57:53,65\n2015-04-22 15:02:53,72\n2015-04-22 15:07:53,73\n2015-04-22 15:12:53,72\n2015-04-22 15:17:53,62\n2015-04-22 15:22:53,56\n2015-04-22 15:27:53,71\n2015-04-22 15:32:53,67\n2015-04-22 15:37:53,55\n2015-04-22 15:42:53,148\n2015-04-22 15:47:53,127\n2015-04-22 15:52:53,88\n2015-04-22 15:57:53,107\n2015-04-22 16:02:53,73\n2015-04-22 16:07:53,73\n2015-04-22 16:12:53,73\n2015-04-22 16:17:53,83\n2015-04-22 16:22:53,62\n2015-04-22 16:27:53,59\n2015-04-22 16:32:53,43\n2015-04-22 16:37:53,55\n2015-04-22 16:42:53,66\n2015-04-22 16:47:53,45\n2015-04-22 16:52:53,48\n2015-04-22 16:57:53,65\n2015-04-22 17:02:53,36\n2015-04-22 17:07:53,53\n2015-04-22 17:12:53,53\n2015-04-22 17:17:53,65\n2015-04-22 17:22:53,64\n2015-04-22 17:27:53,77\n2015-04-22 17:32:53,74\n2015-04-22 17:37:53,67\n2015-04-22 17:42:53,85\n2015-04-22 17:47:53,89\n2015-04-22 17:52:53,89\n2015-04-22 17:57:53,87\n2015-04-22 18:02:53,139\n2015-04-22 18:07:53,111\n2015-04-22 18:12:53,106\n2015-04-22 18:17:53,77\n2015-04-22 18:22:53,98\n2015-04-22 18:27:53,107\n2015-04-22 18:32:53,94\n2015-04-22 18:37:53,87\n2015-04-22 18:42:53,64\n2015-04-22 18:47:53,71\n2015-04-22 18:52:53,98\n2015-04-22 18:57:53,102\n2015-04-22 19:02:53,68\n2015-04-22 19:07:53,59\n2015-04-22 19:12:53,58\n2015-04-22 19:17:53,50\n2015-04-22 19:22:53,61\n2015-04-22 19:27:53,70\n2015-04-22 19:32:53,60\n2015-04-22 19:37:53,60\n2015-04-22 19:42:53,61\n2015-04-22 19:47:53,52\n2015-04-22 19:52:53,51\n2015-04-22 19:57:53,67\n2015-04-22 20:02:53,106\n2015-04-22 20:07:53,86\n2015-04-22 20:12:53,61\n2015-04-22 20:17:53,62\n2015-04-22 20:22:53,54\n2015-04-22 20:27:53,54\n2015-04-22 20:32:53,57\n2015-04-22 20:37:53,58\n2015-04-22 20:42:53,65\n2015-04-22 20:47:53,59\n2015-04-22 20:52:53,52\n2015-04-22 20:57:53,50\n2015-04-22 21:02:53,61\n2015-04-22 21:07:53,56\n2015-04-22 21:12:53,59\n2015-04-22 21:17:53,57\n2015-04-22 21:22:53,62\n2015-04-22 21:27:53,58\n2015-04-22 21:32:53,50\n2015-04-22 21:37:53,32\n2015-04-22 21:42:53,72\n2015-04-22 21:47:53,72\n"
  },
  {
    "path": "workspace/anomaly_detector/datasets/selected/seasonal/art_daily_jumpsdown.csv",
    "content": "timestamp,value\n2014-04-01 00:00:00,18.090486228499998\n2014-04-01 00:05:00,20.359842585899997\n2014-04-01 00:10:00,21.105469847200002\n2014-04-01 00:15:00,21.1515852522\n2014-04-01 00:20:00,18.1371405424\n2014-04-01 00:25:00,21.6256605306\n2014-04-01 00:30:00,21.6738066877\n2014-04-01 00:35:00,20.2455614926\n2014-04-01 00:40:00,19.9283327955\n2014-04-01 00:45:00,18.1794698523\n2014-04-01 00:50:00,20.24781657\n2014-04-01 00:55:00,19.637516327100002\n2014-04-01 01:00:00,21.0912256296\n2014-04-01 01:05:00,19.6155342675\n2014-04-01 01:10:00,20.7343233333\n2014-04-01 01:15:00,18.405632585\n2014-04-01 01:20:00,18.5318090831\n2014-04-01 01:25:00,18.5588407626\n2014-04-01 01:30:00,18.1821019992\n2014-04-01 01:35:00,20.165315437100002\n2014-04-01 01:40:00,21.1758709042\n2014-04-01 01:45:00,20.4416448148\n2014-04-01 01:50:00,20.2998195422\n2014-04-01 01:55:00,20.722495713599997\n2014-04-01 02:00:00,19.3585812923\n2014-04-01 02:05:00,19.447816286600002\n2014-04-01 02:10:00,19.2570803929\n2014-04-01 02:15:00,20.848435731400002\n2014-04-01 02:20:00,18.6465613427\n2014-04-01 02:25:00,18.0521011213\n2014-04-01 02:30:00,20.3847857869\n2014-04-01 02:35:00,21.7695254589\n2014-04-01 02:40:00,20.437631667999998\n2014-04-01 02:45:00,21.1316866118\n2014-04-01 02:50:00,20.6911628379\n2014-04-01 02:55:00,19.9897466141\n2014-04-01 03:00:00,20.873569607100002\n2014-04-01 03:05:00,21.2964164954\n2014-04-01 03:10:00,18.8989265767\n2014-04-01 03:15:00,19.3445219219\n2014-04-01 03:20:00,18.89490293\n2014-04-01 03:25:00,19.8086918224\n2014-04-01 03:30:00,21.5402582037\n2014-04-01 03:35:00,19.3808284033\n2014-04-01 03:40:00,19.4978675565\n2014-04-01 03:45:00,21.441468938699998\n2014-04-01 03:50:00,20.061497323\n2014-04-01 03:55:00,20.1417959986\n2014-04-01 04:00:00,21.4432048133\n2014-04-01 04:05:00,19.9621069481\n2014-04-01 04:10:00,20.7262301385\n2014-04-01 04:15:00,18.3425786635\n2014-04-01 04:20:00,18.7145268525\n2014-04-01 04:25:00,19.6175048029\n2014-04-01 04:30:00,19.979356271300002\n2014-04-01 04:35:00,21.862934804899997\n2014-04-01 04:40:00,21.882606532199997\n2014-04-01 04:45:00,21.4047883499\n2014-04-01 04:50:00,19.2623953411\n2014-04-01 04:55:00,21.856113163299998\n2014-04-01 05:00:00,20.7573634587\n2014-04-01 05:05:00,19.571760511300003\n2014-04-01 05:10:00,20.8066996679\n2014-04-01 05:15:00,18.066090919100002\n2014-04-01 05:20:00,18.5846187291\n2014-04-01 05:25:00,21.3187428462\n2014-04-01 05:30:00,20.5822945475\n2014-04-01 05:35:00,19.4567788052\n2014-04-01 05:40:00,20.0026665609\n2014-04-01 05:45:00,21.620568598600002\n2014-04-01 05:50:00,20.5263124379\n2014-04-01 05:55:00,19.5925971357\n2014-04-01 06:00:00,18.4813066296\n2014-04-01 06:05:00,19.174987206500003\n2014-04-01 06:10:00,21.9133609312\n2014-04-01 06:15:00,19.7494522514\n2014-04-01 06:20:00,19.8873578554\n2014-04-01 06:25:00,19.9943921296\n2014-04-01 06:30:00,21.5364160918\n2014-04-01 06:35:00,20.4157131375\n2014-04-01 06:40:00,20.7747081458\n2014-04-01 06:45:00,19.5576541702\n2014-04-01 06:50:00,18.1163504744\n2014-04-01 06:55:00,21.723891657\n2014-04-01 07:00:00,21.7965107237\n2014-04-01 07:05:00,21.796612213400003\n2014-04-01 07:10:00,21.7747483466\n2014-04-01 07:15:00,21.260967764300002\n2014-04-01 07:20:00,20.7383842005\n2014-04-01 07:25:00,21.378039673099998\n2014-04-01 07:30:00,20.402184956\n2014-04-01 07:35:00,18.5374784556\n2014-04-01 07:40:00,19.5648726602\n2014-04-01 07:45:00,21.8851796479\n2014-04-01 07:50:00,19.4045512544\n2014-04-01 07:55:00,21.4713116549\n2014-04-01 08:00:00,18.3728458831\n2014-04-01 08:05:00,19.3367353695\n2014-04-01 08:10:00,19.4038132989\n2014-04-01 08:15:00,18.206410172400002\n2014-04-01 08:20:00,18.4763773207\n2014-04-01 08:25:00,18.7726608445\n2014-04-01 08:30:00,21.3512623632\n2014-04-01 08:35:00,18.2536079598\n2014-04-01 08:40:00,19.1948036054\n2014-04-01 08:45:00,18.0407000104\n2014-04-01 08:50:00,20.7825109816\n2014-04-01 08:55:00,20.4812123602\n2014-04-01 09:00:00,69.9717587639\n2014-04-01 09:05:00,66.2916058721\n2014-04-01 09:10:00,64.0324423692\n2014-04-01 09:15:00,70.9963549007\n2014-04-01 09:20:00,72.23120306930001\n2014-04-01 09:25:00,63.0849803741\n2014-04-01 09:30:00,67.8208802199\n2014-04-01 09:35:00,64.5825332749\n2014-04-01 09:40:00,63.486253312399995\n2014-04-01 09:45:00,71.1868242635\n2014-04-01 09:50:00,68.5181183224\n2014-04-01 09:55:00,64.1401205203\n2014-04-01 10:00:00,74.651200174\n2014-04-01 10:05:00,84.842464979\n2014-04-01 10:10:00,83.0115068443\n2014-04-01 10:15:00,83.4967734494\n2014-04-01 10:20:00,76.9793877467\n2014-04-01 10:25:00,79.5214887361\n2014-04-01 10:30:00,75.687435328\n2014-04-01 10:35:00,71.0460898627\n2014-04-01 10:40:00,76.06459570140001\n2014-04-01 10:45:00,79.05858128979999\n2014-04-01 10:50:00,74.2964790823\n2014-04-01 10:55:00,83.0001929198\n2014-04-01 11:00:00,73.9710969315\n2014-04-01 11:05:00,77.4068210384\n2014-04-01 11:10:00,73.55447171029999\n2014-04-01 11:15:00,78.0064502589\n2014-04-01 11:20:00,72.1987733943\n2014-04-01 11:25:00,75.9026255791\n2014-04-01 11:30:00,77.9412934973\n2014-04-01 11:35:00,79.17274193760001\n2014-04-01 11:40:00,80.2149468852\n2014-04-01 11:45:00,75.94145892819999\n2014-04-01 11:50:00,79.88644938569999\n2014-04-01 11:55:00,79.6632095013\n2014-04-01 12:00:00,76.9663781954\n2014-04-01 12:05:00,85.1808654442\n2014-04-01 12:10:00,80.6333817159\n2014-04-01 12:15:00,77.2235359213\n2014-04-01 12:20:00,87.0528272939\n2014-04-01 12:25:00,85.4191724508\n2014-04-01 12:30:00,87.6161392988\n2014-04-01 12:35:00,82.9760511039\n2014-04-01 12:40:00,77.9579046083\n2014-04-01 12:45:00,76.4019781421\n2014-04-01 12:50:00,82.5139497962\n2014-04-01 12:55:00,87.5878336415\n2014-04-01 13:00:00,82.0077546958\n2014-04-01 13:05:00,86.08517365450001\n2014-04-01 13:10:00,77.2471111396\n2014-04-01 13:15:00,78.4924178171\n2014-04-01 13:20:00,86.4796437365\n2014-04-01 13:25:00,84.0896808632\n2014-04-01 13:30:00,87.6815165103\n2014-04-01 13:35:00,84.3759722612\n2014-04-01 13:40:00,79.15724901520001\n2014-04-01 13:45:00,80.47776901600001\n2014-04-01 13:50:00,86.3875098999\n2014-04-01 13:55:00,80.80694945409999\n2014-04-01 14:00:00,76.0827058414\n2014-04-01 14:05:00,78.9661264483\n2014-04-01 14:10:00,80.25720329090001\n2014-04-01 14:15:00,73.543987056\n2014-04-01 14:20:00,83.8961755783\n2014-04-01 14:25:00,73.7461229499\n2014-04-01 14:30:00,78.4749164371\n2014-04-01 14:35:00,84.8698851146\n2014-04-01 14:40:00,79.4773106918\n2014-04-01 14:45:00,85.4681456476\n2014-04-01 14:50:00,77.466382588\n2014-04-01 14:55:00,87.3179892393\n2014-04-01 15:00:00,75.3507715345\n2014-04-01 15:05:00,72.6115292425\n2014-04-01 15:10:00,85.9579994831\n2014-04-01 15:15:00,84.03443671689999\n2014-04-01 15:20:00,75.7110145604\n2014-04-01 15:25:00,87.7550232579\n2014-04-01 15:30:00,80.0357137181\n2014-04-01 15:35:00,87.2162097587\n2014-04-01 15:40:00,80.07969156979999\n2014-04-01 15:45:00,79.5492297084\n2014-04-01 15:50:00,79.1854564066\n2014-04-01 15:55:00,77.3572617813\n2014-04-01 16:00:00,80.5390693195\n2014-04-01 16:05:00,79.2407224487\n2014-04-01 16:10:00,72.58781065710002\n2014-04-01 16:15:00,76.1668174942\n2014-04-01 16:20:00,75.4098200146\n2014-04-01 16:25:00,85.87880474949999\n2014-04-01 16:30:00,81.5817629983\n2014-04-01 16:35:00,84.2187679069\n2014-04-01 16:40:00,87.30904897030001\n2014-04-01 16:45:00,82.3044703355\n2014-04-01 16:50:00,87.7215914367\n2014-04-01 16:55:00,76.988077009\n2014-04-01 17:00:00,74.9802461246\n2014-04-01 17:05:00,78.452928082\n2014-04-01 17:10:00,79.5327600984\n2014-04-01 17:15:00,86.3257515365\n2014-04-01 17:20:00,80.9590159363\n2014-04-01 17:25:00,76.6748665475\n2014-04-01 17:30:00,83.8821163151\n2014-04-01 17:35:00,80.0932802384\n2014-04-01 17:40:00,74.5940824803\n2014-04-01 17:45:00,81.2290854095\n2014-04-01 17:50:00,86.5822793413\n2014-04-01 17:55:00,85.4819290545\n2014-04-01 18:00:00,32.5555775742\n2014-04-01 18:05:00,31.2133263199\n2014-04-01 18:10:00,29.356658370300003\n2014-04-01 18:15:00,31.805747002600004\n2014-04-01 18:20:00,33.6133019464\n2014-04-01 18:25:00,31.105745834\n2014-04-01 18:30:00,30.3068538646\n2014-04-01 18:35:00,34.7608235293\n2014-04-01 18:40:00,34.057949943800004\n2014-04-01 18:45:00,32.8849576504\n2014-04-01 18:50:00,29.6754077034\n2014-04-01 18:55:00,29.727410870900002\n2014-04-01 19:00:00,20.6224226384\n2014-04-01 19:05:00,22.9210078103\n2014-04-01 19:10:00,20.6777201939\n2014-04-01 19:15:00,23.934968537899998\n2014-04-01 19:20:00,24.6084818582\n2014-04-01 19:25:00,21.801238671500002\n2014-04-01 19:30:00,22.192439696999998\n2014-04-01 19:35:00,23.3482676721\n2014-04-01 19:40:00,24.3584441321\n2014-04-01 19:45:00,24.165538779899997\n2014-04-01 19:50:00,20.4180102727\n2014-04-01 19:55:00,20.917440528\n2014-04-01 20:00:00,21.522829867\n2014-04-01 20:05:00,21.2537059155\n2014-04-01 20:10:00,18.9776631335\n2014-04-01 20:15:00,20.488456282\n2014-04-01 20:20:00,21.6302164694\n2014-04-01 20:25:00,19.3281254426\n2014-04-01 20:30:00,22.000793891999997\n2014-04-01 20:35:00,18.6489721659\n2014-04-01 20:40:00,21.6358708088\n2014-04-01 20:45:00,20.9543939621\n2014-04-01 20:50:00,19.7230562872\n2014-04-01 20:55:00,21.384939461400002\n2014-04-01 21:00:00,21.2308845519\n2014-04-01 21:05:00,21.839926692\n2014-04-01 21:10:00,19.564559914500002\n2014-04-01 21:15:00,20.8436384143\n2014-04-01 21:20:00,20.5084352901\n2014-04-01 21:25:00,20.197308185\n2014-04-01 21:30:00,21.665161839899998\n2014-04-01 21:35:00,18.0991300247\n2014-04-01 21:40:00,19.2202629202\n2014-04-01 21:45:00,20.2498438317\n2014-04-01 21:50:00,18.802996231199998\n2014-04-01 21:55:00,21.735297119200002\n2014-04-01 22:00:00,20.6101472256\n2014-04-01 22:05:00,19.9306470394\n2014-04-01 22:10:00,21.279215480599998\n2014-04-01 22:15:00,19.8225561591\n2014-04-01 22:20:00,20.2540372653\n2014-04-01 22:25:00,18.0282945372\n2014-04-01 22:30:00,19.481486401199998\n2014-04-01 22:35:00,18.5729748357\n2014-04-01 22:40:00,20.778683117\n2014-04-01 22:45:00,19.9352272896\n2014-04-01 22:50:00,19.225468968599998\n2014-04-01 22:55:00,19.8904058239\n2014-04-01 23:00:00,18.8421365457\n2014-04-01 23:05:00,21.7045129943\n2014-04-01 23:10:00,18.2193879794\n2014-04-01 23:15:00,21.4657887794\n2014-04-01 23:20:00,20.049283876500002\n2014-04-01 23:25:00,20.4797173335\n2014-04-01 23:30:00,19.2141108829\n2014-04-01 23:35:00,21.8709888888\n2014-04-01 23:40:00,19.131076293699998\n2014-04-01 23:45:00,20.3594202449\n2014-04-01 23:50:00,21.9778857623\n2014-04-01 23:55:00,21.5285102639\n2014-04-02 00:00:00,20.1453193011\n2014-04-02 00:05:00,21.9614980919\n2014-04-02 00:10:00,20.8054794469\n2014-04-02 00:15:00,18.8348016646\n2014-04-02 00:20:00,19.6223848417\n2014-04-02 00:25:00,19.337973335999997\n2014-04-02 00:30:00,19.3760548331\n2014-04-02 00:35:00,21.0418257574\n2014-04-02 00:40:00,20.337051709100002\n2014-04-02 00:45:00,18.1523708464\n2014-04-02 00:50:00,21.5097939346\n2014-04-02 00:55:00,19.1871845619\n2014-04-02 01:00:00,21.9882995077\n2014-04-02 01:05:00,21.8167629213\n2014-04-02 01:10:00,21.7621228667\n2014-04-02 01:15:00,21.244510416300002\n2014-04-02 01:20:00,18.882453326700002\n2014-04-02 01:25:00,20.130530976099998\n2014-04-02 01:30:00,18.8972105073\n2014-04-02 01:35:00,19.0387018224\n2014-04-02 01:40:00,20.4438070777\n2014-04-02 01:45:00,18.1633341814\n2014-04-02 01:50:00,21.8778342673\n2014-04-02 01:55:00,21.674692690300002\n2014-04-02 02:00:00,19.5230702886\n2014-04-02 02:05:00,20.061689792\n2014-04-02 02:10:00,19.864477677100002\n2014-04-02 02:15:00,21.528799114499996\n2014-04-02 02:20:00,20.7544075053\n2014-04-02 02:25:00,19.112444989700002\n2014-04-02 02:30:00,19.7873650179\n2014-04-02 02:35:00,19.7158639027\n2014-04-02 02:40:00,21.837340673099998\n2014-04-02 02:45:00,18.7012436421\n2014-04-02 02:50:00,18.358305349200002\n2014-04-02 02:55:00,21.522475328600002\n2014-04-02 03:00:00,21.586743958000003\n2014-04-02 03:05:00,21.4869563516\n2014-04-02 03:10:00,20.0439076625\n2014-04-02 03:15:00,20.6389777131\n2014-04-02 03:20:00,20.2534521902\n2014-04-02 03:25:00,18.2777913042\n2014-04-02 03:30:00,20.3833395876\n2014-04-02 03:35:00,18.054456589\n2014-04-02 03:40:00,19.2999496382\n2014-04-02 03:45:00,21.7291703035\n2014-04-02 03:50:00,19.2161810785\n2014-04-02 03:55:00,21.7593065706\n2014-04-02 04:00:00,19.0005358286\n2014-04-02 04:05:00,19.2582489618\n2014-04-02 04:10:00,20.513629985799998\n2014-04-02 04:15:00,21.046507891199997\n2014-04-02 04:20:00,20.005551072\n2014-04-02 04:25:00,21.528462748800006\n2014-04-02 04:30:00,18.1609616864\n2014-04-02 04:35:00,21.6887793545\n2014-04-02 04:40:00,18.785231199600002\n2014-04-02 04:45:00,21.536954980300003\n2014-04-02 04:50:00,19.603452717899998\n2014-04-02 04:55:00,21.3310282235\n2014-04-02 05:00:00,20.6866621992\n2014-04-02 05:05:00,18.7037665299\n2014-04-02 05:10:00,21.672190279499997\n2014-04-02 05:15:00,18.982069562\n2014-04-02 05:20:00,18.9765604748\n2014-04-02 05:25:00,21.2567155865\n2014-04-02 05:30:00,18.4234930223\n2014-04-02 05:35:00,18.8881436255\n2014-04-02 05:40:00,20.0147102937\n2014-04-02 05:45:00,21.3219081147\n2014-04-02 05:50:00,18.589935898900002\n2014-04-02 05:55:00,20.190672938\n2014-04-02 06:00:00,20.8449623672\n2014-04-02 06:05:00,21.4423808989\n2014-04-02 06:10:00,21.7422622408\n2014-04-02 06:15:00,21.1385596579\n2014-04-02 06:20:00,20.6113135929\n2014-04-02 06:25:00,19.7344803413\n2014-04-02 06:30:00,18.4484406168\n2014-04-02 06:35:00,20.8389487701\n2014-04-02 06:40:00,21.9709492179\n2014-04-02 06:45:00,20.9470423789\n2014-04-02 06:50:00,18.066844375\n2014-04-02 06:55:00,19.9850399122\n2014-04-02 07:00:00,20.4585865299\n2014-04-02 07:05:00,20.7586968044\n2014-04-02 07:10:00,20.8789033424\n2014-04-02 07:15:00,20.2324337649\n2014-04-02 07:20:00,18.8934413309\n2014-04-02 07:25:00,21.768802645900003\n2014-04-02 07:30:00,20.7866658707\n2014-04-02 07:35:00,18.9473601475\n2014-04-02 07:40:00,19.289287329100002\n2014-04-02 07:45:00,21.6877106825\n2014-04-02 07:50:00,21.549940746799997\n2014-04-02 07:55:00,19.6205857534\n2014-04-02 08:00:00,18.153228888\n2014-04-02 08:05:00,18.1939894756\n2014-04-02 08:10:00,19.135673163699998\n2014-04-02 08:15:00,20.5164888774\n2014-04-02 08:20:00,20.336778541300003\n2014-04-02 08:25:00,20.535311147799998\n2014-04-02 08:30:00,20.8691318877\n2014-04-02 08:35:00,18.0761290144\n2014-04-02 08:40:00,18.4203423807\n2014-04-02 08:45:00,19.4379338073\n2014-04-02 08:50:00,18.6194399901\n2014-04-02 08:55:00,18.3012801702\n2014-04-02 09:00:00,69.9171157856\n2014-04-02 09:05:00,72.2885760939\n2014-04-02 09:10:00,71.43572254109999\n2014-04-02 09:15:00,72.3117409891\n2014-04-02 09:20:00,70.2556489992\n2014-04-02 09:25:00,71.2006963767\n2014-04-02 09:30:00,64.89619132920001\n2014-04-02 09:35:00,74.70490929350001\n2014-04-02 09:40:00,63.691052901099994\n2014-04-02 09:45:00,64.1171166917\n2014-04-02 09:50:00,65.1293369127\n2014-04-02 09:55:00,74.46452104939999\n2014-04-02 10:00:00,85.1782389068\n2014-04-02 10:05:00,82.1767509954\n2014-04-02 10:10:00,79.6029739296\n2014-04-02 10:15:00,77.9113711669\n2014-04-02 10:20:00,84.9040355251\n2014-04-02 10:25:00,80.6360659004\n2014-04-02 10:30:00,84.5022115916\n2014-04-02 10:35:00,74.7528684079\n2014-04-02 10:40:00,75.02018477600001\n2014-04-02 10:45:00,83.10532570069999\n2014-04-02 10:50:00,72.1657483675\n2014-04-02 10:55:00,84.5208004073\n2014-04-02 11:00:00,79.6388721366\n2014-04-02 11:05:00,86.301686325\n2014-04-02 11:10:00,76.9243525119\n2014-04-02 11:15:00,82.9546104114\n2014-04-02 11:20:00,79.2476459399\n2014-04-02 11:25:00,81.5366849354\n2014-04-02 11:30:00,79.5895401309\n2014-04-02 11:35:00,86.94900677870001\n2014-04-02 11:40:00,82.5752442468\n2014-04-02 11:45:00,75.56497687699999\n2014-04-02 11:50:00,86.03550176600002\n2014-04-02 11:55:00,76.2442489556\n2014-04-02 12:00:00,77.8521467709\n2014-04-02 12:05:00,73.5456183933\n2014-04-02 12:10:00,86.29578495959998\n2014-04-02 12:15:00,76.4858990208\n2014-04-02 12:20:00,76.0513106686\n2014-04-02 12:25:00,86.620132526\n2014-04-02 12:30:00,84.7865636827\n2014-04-02 12:35:00,74.168154029\n2014-04-02 12:40:00,84.208021032\n2014-04-02 12:45:00,86.5045993334\n2014-04-02 12:50:00,73.16827207600001\n2014-04-02 12:55:00,85.1011957906\n2014-04-02 13:00:00,80.739338737\n2014-04-02 13:05:00,82.6873094719\n2014-04-02 13:10:00,79.8664968618\n2014-04-02 13:15:00,83.1448897946\n2014-04-02 13:20:00,72.5281548509\n2014-04-02 13:25:00,84.1830987778\n2014-04-02 13:30:00,72.5160911259\n2014-04-02 13:35:00,79.2657692125\n2014-04-02 13:40:00,74.3975801845\n2014-04-02 13:45:00,85.1567459124\n2014-04-02 13:50:00,77.00009008890001\n2014-04-02 13:55:00,79.2464729945\n2014-04-02 14:00:00,78.8562265802\n2014-04-02 14:05:00,84.3559821694\n2014-04-02 14:10:00,79.6944842379\n2014-04-02 14:15:00,84.61927144020001\n2014-04-02 14:20:00,73.1726199745\n2014-04-02 14:25:00,75.06190034229999\n2014-04-02 14:30:00,80.820668416\n2014-04-02 14:35:00,87.14922983219999\n2014-04-02 14:40:00,73.1926121335\n2014-04-02 14:45:00,72.6858583698\n2014-04-02 14:50:00,74.5012345679\n2014-04-02 14:55:00,82.2545016562\n2014-04-02 15:00:00,78.38313418140001\n2014-04-02 15:05:00,85.2080200658\n2014-04-02 15:10:00,73.15022817479999\n2014-04-02 15:15:00,75.1419040198\n2014-04-02 15:20:00,76.7996852034\n2014-04-02 15:25:00,82.0268939213\n2014-04-02 15:30:00,82.9619666023\n2014-04-02 15:35:00,73.9865424258\n2014-04-02 15:40:00,87.10003917549999\n2014-04-02 15:45:00,77.4559625787\n2014-04-02 15:50:00,83.4098994653\n2014-04-02 15:55:00,80.38655178489999\n2014-04-02 16:00:00,75.5639847336\n2014-04-02 16:05:00,85.5394889337\n2014-04-02 16:10:00,85.0916450748\n2014-04-02 16:15:00,78.3369992553\n2014-04-02 16:20:00,81.41756504909999\n2014-04-02 16:25:00,76.1250649746\n2014-04-02 16:30:00,83.0374666277\n2014-04-02 16:35:00,76.9442812686\n2014-04-02 16:40:00,85.50509558\n2014-04-02 16:45:00,75.4780167504\n2014-04-02 16:50:00,72.23671607029999\n2014-04-02 16:55:00,76.2959821829\n2014-04-02 17:00:00,75.05681096149999\n2014-04-02 17:05:00,80.1325522647\n2014-04-02 17:10:00,75.259223767\n2014-04-02 17:15:00,84.2110055945\n2014-04-02 17:20:00,75.8619010771\n2014-04-02 17:25:00,83.311458887\n2014-04-02 17:30:00,81.2555035661\n2014-04-02 17:35:00,87.779963996\n2014-04-02 17:40:00,87.9983818408\n2014-04-02 17:45:00,85.91238434270002\n2014-04-02 17:50:00,84.15970159140001\n2014-04-02 17:55:00,78.1832726016\n2014-04-02 18:00:00,33.6209645984\n2014-04-02 18:05:00,34.9227167321\n2014-04-02 18:10:00,28.9496109242\n2014-04-02 18:15:00,32.2426478907\n2014-04-02 18:20:00,30.1951833506\n2014-04-02 18:25:00,32.3704022064\n2014-04-02 18:30:00,31.785255271700002\n2014-04-02 18:35:00,32.4849126848\n2014-04-02 18:40:00,32.3261520105\n2014-04-02 18:45:00,34.9446783413\n2014-04-02 18:50:00,32.3339848891\n2014-04-02 18:55:00,34.2158787945\n2014-04-02 19:00:00,21.592793700300003\n2014-04-02 19:05:00,22.1226898722\n2014-04-02 19:10:00,22.2674511512\n2014-04-02 19:15:00,21.4087004597\n2014-04-02 19:20:00,21.861459172199996\n2014-04-02 19:25:00,22.841337343000003\n2014-04-02 19:30:00,22.7592399311\n2014-04-02 19:35:00,23.0112290814\n2014-04-02 19:40:00,21.7361430687\n2014-04-02 19:45:00,21.574923914699998\n2014-04-02 19:50:00,22.900046858499998\n2014-04-02 19:55:00,20.755219494400002\n2014-04-02 20:00:00,19.468416968699998\n2014-04-02 20:05:00,18.6045549873\n2014-04-02 20:10:00,18.7294138275\n2014-04-02 20:15:00,19.4288976787\n2014-04-02 20:20:00,18.51199171\n2014-04-02 20:25:00,19.4372015519\n2014-04-02 20:30:00,21.1147827659\n2014-04-02 20:35:00,18.6822943692\n2014-04-02 20:40:00,20.2208731896\n2014-04-02 20:45:00,22.1720933252\n2014-04-02 20:50:00,21.6731023992\n2014-04-02 20:55:00,19.6830717732\n2014-04-02 21:00:00,21.803378128600002\n2014-04-02 21:05:00,19.4113151523\n2014-04-02 21:10:00,18.3778542379\n2014-04-02 21:15:00,22.081709647399997\n2014-04-02 21:20:00,21.5831944885\n2014-04-02 21:25:00,19.9590769938\n2014-04-02 21:30:00,20.7647004752\n2014-04-02 21:35:00,20.7841998397\n2014-04-02 21:40:00,18.8680629356\n2014-04-02 21:45:00,18.8904354202\n2014-04-02 21:50:00,19.9737387141\n2014-04-02 21:55:00,21.7501947116\n2014-04-02 22:00:00,18.0572934667\n2014-04-02 22:05:00,21.1503073551\n2014-04-02 22:10:00,18.2476080287\n2014-04-02 22:15:00,19.9320048227\n2014-04-02 22:20:00,20.5712207539\n2014-04-02 22:25:00,20.7669542137\n2014-04-02 22:30:00,18.2514216059\n2014-04-02 22:35:00,19.6933018978\n2014-04-02 22:40:00,20.354870967100002\n2014-04-02 22:45:00,18.2817157551\n2014-04-02 22:50:00,18.5581769804\n2014-04-02 22:55:00,20.67442436\n2014-04-02 23:00:00,20.0904094025\n2014-04-02 23:05:00,18.6508949277\n2014-04-02 23:10:00,20.1448244095\n2014-04-02 23:15:00,21.6549264394\n2014-04-02 23:20:00,18.065818308599997\n2014-04-02 23:25:00,20.5744846347\n2014-04-02 23:30:00,18.298114300199998\n2014-04-02 23:35:00,18.0292587233\n2014-04-02 23:40:00,18.6061896555\n2014-04-02 23:45:00,19.6954073178\n2014-04-02 23:50:00,21.213448194\n2014-04-02 23:55:00,19.130814395799998\n2014-04-03 00:00:00,20.5026928496\n2014-04-03 00:05:00,19.644626551800002\n2014-04-03 00:10:00,18.9373271679\n2014-04-03 00:15:00,20.0569884571\n2014-04-03 00:20:00,21.1898579615\n2014-04-03 00:25:00,21.3299694802\n2014-04-03 00:30:00,21.3860781275\n2014-04-03 00:35:00,19.3542312502\n2014-04-03 00:40:00,21.1738242589\n2014-04-03 00:45:00,18.8487138204\n2014-04-03 00:50:00,20.953700405\n2014-04-03 00:55:00,21.793537705100004\n2014-04-03 01:00:00,18.054975338800002\n2014-04-03 01:05:00,19.7614557247\n2014-04-03 01:10:00,20.5910839537\n2014-04-03 01:15:00,20.807103082\n2014-04-03 01:20:00,18.7043510331\n2014-04-03 01:25:00,21.888733101\n2014-04-03 01:30:00,20.4610614719\n2014-04-03 01:35:00,18.6573624049\n2014-04-03 01:40:00,18.0820900469\n2014-04-03 01:45:00,21.133056795199998\n2014-04-03 01:50:00,18.3188189578\n2014-04-03 01:55:00,18.5642036843\n2014-04-03 02:00:00,20.2993201074\n2014-04-03 02:05:00,20.4140220138\n2014-04-03 02:10:00,20.747548474400002\n2014-04-03 02:15:00,19.574056050699998\n2014-04-03 02:20:00,21.0955946759\n2014-04-03 02:25:00,21.8974343985\n2014-04-03 02:30:00,19.0843797723\n2014-04-03 02:35:00,20.8121144662\n2014-04-03 02:40:00,21.7138746096\n2014-04-03 02:45:00,20.745147050499998\n2014-04-03 02:50:00,20.7244379946\n2014-04-03 02:55:00,18.8950902763\n2014-04-03 03:00:00,20.140520801300003\n2014-04-03 03:05:00,20.2500913744\n2014-04-03 03:10:00,20.8005182498\n2014-04-03 03:15:00,21.9872857996\n2014-04-03 03:20:00,18.1345752902\n2014-04-03 03:25:00,18.2609306451\n2014-04-03 03:30:00,18.3118002777\n2014-04-03 03:35:00,20.971916538\n2014-04-03 03:40:00,18.5454151804\n2014-04-03 03:45:00,20.489807498\n2014-04-03 03:50:00,19.298675511600003\n2014-04-03 03:55:00,19.8292798248\n2014-04-03 04:00:00,18.862652639300002\n2014-04-03 04:05:00,21.4644262452\n2014-04-03 04:10:00,20.344601296700002\n2014-04-03 04:15:00,21.7782530543\n2014-04-03 04:20:00,20.2983849988\n2014-04-03 04:25:00,18.4956321224\n2014-04-03 04:30:00,18.6834817354\n2014-04-03 04:35:00,21.956295905500003\n2014-04-03 04:40:00,20.9022607893\n2014-04-03 04:45:00,18.1971150001\n2014-04-03 04:50:00,20.8151240201\n2014-04-03 04:55:00,19.6486921872\n2014-04-03 05:00:00,19.2288335473\n2014-04-03 05:05:00,18.6162431749\n2014-04-03 05:10:00,21.359615818199998\n2014-04-03 05:15:00,18.255365515999998\n2014-04-03 05:20:00,19.1593418495\n2014-04-03 05:25:00,19.2255315753\n2014-04-03 05:30:00,18.6436211359\n2014-04-03 05:35:00,20.0327395331\n2014-04-03 05:40:00,18.0468105072\n2014-04-03 05:45:00,19.2039020616\n2014-04-03 05:50:00,21.734517776100002\n2014-04-03 05:55:00,19.2421182774\n2014-04-03 06:00:00,19.4418375484\n2014-04-03 06:05:00,19.8926601929\n2014-04-03 06:10:00,20.2467734994\n2014-04-03 06:15:00,21.2348345793\n2014-04-03 06:20:00,18.7612848926\n2014-04-03 06:25:00,21.4869855088\n2014-04-03 06:30:00,21.030197428599998\n2014-04-03 06:35:00,20.8906013386\n2014-04-03 06:40:00,18.3472182949\n2014-04-03 06:45:00,18.0865627599\n2014-04-03 06:50:00,20.3760508036\n2014-04-03 06:55:00,21.4525358501\n2014-04-03 07:00:00,20.3377658566\n2014-04-03 07:05:00,18.852939461800002\n2014-04-03 07:10:00,18.3620795918\n2014-04-03 07:15:00,20.7983858113\n2014-04-03 07:20:00,20.887081109300002\n2014-04-03 07:25:00,18.6901268027\n2014-04-03 07:30:00,18.112761262\n2014-04-03 07:35:00,19.6331340529\n2014-04-03 07:40:00,20.3308748085\n2014-04-03 07:45:00,20.824009638299998\n2014-04-03 07:50:00,21.2397800366\n2014-04-03 07:55:00,20.442149709200002\n2014-04-03 08:00:00,18.443522434400002\n2014-04-03 08:05:00,20.730326688599998\n2014-04-03 08:10:00,21.9367065716\n2014-04-03 08:15:00,21.622338338400002\n2014-04-03 08:20:00,21.4866756371\n2014-04-03 08:25:00,19.2086806134\n2014-04-03 08:30:00,21.003152705799998\n2014-04-03 08:35:00,21.4044137839\n2014-04-03 08:40:00,20.7133048185\n2014-04-03 08:45:00,19.0022470263\n2014-04-03 08:50:00,21.8153358875\n2014-04-03 08:55:00,19.803277645799998\n2014-04-03 09:00:00,62.9653555979\n2014-04-03 09:05:00,62.692979372799996\n2014-04-03 09:10:00,70.0062582273\n2014-04-03 09:15:00,67.1528511913\n2014-04-03 09:20:00,62.484980702399994\n2014-04-03 09:25:00,71.26895818130002\n2014-04-03 09:30:00,72.0708222747\n2014-04-03 09:35:00,71.0656525787\n2014-04-03 09:40:00,63.950747936499994\n2014-04-03 09:45:00,70.5809462015\n2014-04-03 09:50:00,61.3458301194\n2014-04-03 09:55:00,65.3495250996\n2014-04-03 10:00:00,76.0297101674\n2014-04-03 10:05:00,82.8030326467\n2014-04-03 10:10:00,75.89892067\n2014-04-03 10:15:00,70.01490180489999\n2014-04-03 10:20:00,75.3084163116\n2014-04-03 10:25:00,77.58330200649999\n2014-04-03 10:30:00,84.5685542892\n2014-04-03 10:35:00,84.4448523948\n2014-04-03 10:40:00,72.6471650732\n2014-04-03 10:45:00,72.7134743278\n2014-04-03 10:50:00,72.3756802043\n2014-04-03 10:55:00,82.08406839109999\n2014-04-03 11:00:00,71.66377453\n2014-04-03 11:05:00,73.59062616\n2014-04-03 11:10:00,80.1237099817\n2014-04-03 11:15:00,75.5052271118\n2014-04-03 11:20:00,73.0368371118\n2014-04-03 11:25:00,77.2914999082\n2014-04-03 11:30:00,75.9289977509\n2014-04-03 11:35:00,79.6966028908\n2014-04-03 11:40:00,87.14173107629999\n2014-04-03 11:45:00,73.5449409439\n2014-04-03 11:50:00,77.4958455137\n2014-04-03 11:55:00,86.3902897242\n2014-04-03 12:00:00,85.9267327335\n2014-04-03 12:05:00,78.2143665527\n2014-04-03 12:10:00,83.0834323296\n2014-04-03 12:15:00,73.3176253626\n2014-04-03 12:20:00,83.3005761004\n2014-04-03 12:25:00,87.4606448033\n2014-04-03 12:30:00,80.5030906728\n2014-04-03 12:35:00,79.8798726202\n2014-04-03 12:40:00,74.9071013977\n2014-04-03 12:45:00,82.0420424491\n2014-04-03 12:50:00,81.34926009670002\n2014-04-03 12:55:00,82.3320118369\n2014-04-03 13:00:00,72.3999524271\n2014-04-03 13:05:00,80.7601887154\n2014-04-03 13:10:00,81.4993929462\n2014-04-03 13:15:00,75.30240525090001\n2014-04-03 13:20:00,75.3152457216\n2014-04-03 13:25:00,76.4011500184\n2014-04-03 13:30:00,83.3675324567\n2014-04-03 13:35:00,81.68064895479999\n2014-04-03 13:40:00,85.5116746093\n2014-04-03 13:45:00,76.7121218206\n2014-04-03 13:50:00,86.57230661690002\n2014-04-03 13:55:00,83.8791627601\n2014-04-03 14:00:00,78.3164273513\n2014-04-03 14:05:00,73.5206638887\n2014-04-03 14:10:00,76.1080852363\n2014-04-03 14:15:00,87.3041006774\n2014-04-03 14:20:00,76.9621196551\n2014-04-03 14:25:00,77.2747059984\n2014-04-03 14:30:00,75.0298212933\n2014-04-03 14:35:00,84.905533957\n2014-04-03 14:40:00,76.4066399891\n2014-04-03 14:45:00,77.28042233560001\n2014-04-03 14:50:00,78.6257955156\n2014-04-03 14:55:00,78.9358633731\n2014-04-03 15:00:00,78.5806982647\n2014-04-03 15:05:00,80.05913055100001\n2014-04-03 15:10:00,85.03138976470001\n2014-04-03 15:15:00,85.10774360970001\n2014-04-03 15:20:00,84.77219631930001\n2014-04-03 15:25:00,73.6172906931\n2014-04-03 15:30:00,84.79404682170002\n2014-04-03 15:35:00,73.9233187051\n2014-04-03 15:40:00,73.9948699633\n2014-04-03 15:45:00,87.16496755440002\n2014-04-03 15:50:00,85.1095484558\n2014-04-03 15:55:00,80.8377914196\n2014-04-03 16:00:00,85.9993581526\n2014-04-03 16:05:00,87.8296656475\n2014-04-03 16:10:00,81.77011606720001\n2014-04-03 16:15:00,81.8062179235\n2014-04-03 16:20:00,84.0706710506\n2014-04-03 16:25:00,75.71407786649999\n2014-04-03 16:30:00,74.67385441020001\n2014-04-03 16:35:00,84.1531304259\n2014-04-03 16:40:00,77.5183278844\n2014-04-03 16:45:00,74.16098331149999\n2014-04-03 16:50:00,77.0378957016\n2014-04-03 16:55:00,77.7380406287\n2014-04-03 17:00:00,87.44360897370001\n2014-04-03 17:05:00,83.1673234411\n2014-04-03 17:10:00,80.4936701688\n2014-04-03 17:15:00,87.50193661819998\n2014-04-03 17:20:00,86.45020265069998\n2014-04-03 17:25:00,80.1919829121\n2014-04-03 17:30:00,86.4908409535\n2014-04-03 17:35:00,78.468844397\n2014-04-03 17:40:00,75.686701582\n2014-04-03 17:45:00,75.7228217516\n2014-04-03 17:50:00,82.5970166738\n2014-04-03 17:55:00,80.0170944047\n2014-04-03 18:00:00,33.0172790815\n2014-04-03 18:05:00,33.1908797986\n2014-04-03 18:10:00,28.9428608295\n2014-04-03 18:15:00,29.145847795\n2014-04-03 18:20:00,32.209131266\n2014-04-03 18:25:00,30.0226212933\n2014-04-03 18:30:00,32.8482098135\n2014-04-03 18:35:00,32.3339825226\n2014-04-03 18:40:00,32.5488600442\n2014-04-03 18:45:00,30.7357085297\n2014-04-03 18:50:00,32.894992124299996\n2014-04-03 18:55:00,34.1087463246\n2014-04-03 19:00:00,24.631357864899996\n2014-04-03 19:05:00,23.916229538099998\n2014-04-03 19:10:00,22.6575932004\n2014-04-03 19:15:00,21.0265634173\n2014-04-03 19:20:00,23.212876251599997\n2014-04-03 19:25:00,24.3606876229\n2014-04-03 19:30:00,21.10916094\n2014-04-03 19:35:00,21.306859211099997\n2014-04-03 19:40:00,20.8275571319\n2014-04-03 19:45:00,23.4605116765\n2014-04-03 19:50:00,21.9813943295\n2014-04-03 19:55:00,20.4408753409\n2014-04-03 20:00:00,22.015794901\n2014-04-03 20:05:00,20.7162238731\n2014-04-03 20:10:00,19.7881619826\n2014-04-03 20:15:00,19.8409540319\n2014-04-03 20:20:00,19.6208687625\n2014-04-03 20:25:00,20.2976465425\n2014-04-03 20:30:00,19.8125225183\n2014-04-03 20:35:00,20.676387813399998\n2014-04-03 20:40:00,21.600326406100002\n2014-04-03 20:45:00,21.1945931627\n2014-04-03 20:50:00,19.6380951971\n2014-04-03 20:55:00,20.5977229361\n2014-04-03 21:00:00,21.463035009400002\n2014-04-03 21:05:00,18.3605344538\n2014-04-03 21:10:00,18.4010923305\n2014-04-03 21:15:00,20.3217586878\n2014-04-03 21:20:00,20.6551314735\n2014-04-03 21:25:00,18.9361111467\n2014-04-03 21:30:00,21.0815886816\n2014-04-03 21:35:00,20.6838617144\n2014-04-03 21:40:00,21.7972841736\n2014-04-03 21:45:00,18.7654606822\n2014-04-03 21:50:00,21.1063233957\n2014-04-03 21:55:00,18.422578264600002\n2014-04-03 22:00:00,20.280620351\n2014-04-03 22:05:00,20.2269798254\n2014-04-03 22:10:00,19.5723115675\n2014-04-03 22:15:00,21.398807733399998\n2014-04-03 22:20:00,18.034779353599998\n2014-04-03 22:25:00,20.0999950866\n2014-04-03 22:30:00,18.8867280597\n2014-04-03 22:35:00,20.994129500899998\n2014-04-03 22:40:00,18.1897150752\n2014-04-03 22:45:00,21.3466919122\n2014-04-03 22:50:00,21.3728671705\n2014-04-03 22:55:00,21.3519422446\n2014-04-03 23:00:00,18.6138472777\n2014-04-03 23:05:00,20.525566224400002\n2014-04-03 23:10:00,18.0609364691\n2014-04-03 23:15:00,21.3959575983\n2014-04-03 23:20:00,20.895912016900002\n2014-04-03 23:25:00,20.1284788477\n2014-04-03 23:30:00,20.9263828246\n2014-04-03 23:35:00,18.3808248257\n2014-04-03 23:40:00,20.1184853344\n2014-04-03 23:45:00,19.1687856657\n2014-04-03 23:50:00,21.8946808225\n2014-04-03 23:55:00,21.432586067\n2014-04-04 00:00:00,20.9331027833\n2014-04-04 00:05:00,21.734990541\n2014-04-04 00:10:00,19.3873732183\n2014-04-04 00:15:00,21.603519595999998\n2014-04-04 00:20:00,19.300952928399997\n2014-04-04 00:25:00,20.931186878800002\n2014-04-04 00:30:00,20.9456676471\n2014-04-04 00:35:00,18.073399505799998\n2014-04-04 00:40:00,19.4442387931\n2014-04-04 00:45:00,18.0777306896\n2014-04-04 00:50:00,21.9883680704\n2014-04-04 00:55:00,18.4887870473\n2014-04-04 01:00:00,20.1712435826\n2014-04-04 01:05:00,21.1622249551\n2014-04-04 01:10:00,18.805054409\n2014-04-04 01:15:00,19.9402106724\n2014-04-04 01:20:00,20.4297150437\n2014-04-04 01:25:00,18.6408190176\n2014-04-04 01:30:00,21.1142218396\n2014-04-04 01:35:00,19.1973458288\n2014-04-04 01:40:00,18.8440923054\n2014-04-04 01:45:00,20.2331549857\n2014-04-04 01:50:00,19.6412545106\n2014-04-04 01:55:00,21.681143778499997\n2014-04-04 02:00:00,21.520250792800002\n2014-04-04 02:05:00,19.933402653599998\n2014-04-04 02:10:00,19.4370550989\n2014-04-04 02:15:00,19.302071926500002\n2014-04-04 02:20:00,19.070254492300002\n2014-04-04 02:25:00,20.1781914149\n2014-04-04 02:30:00,21.2199144189\n2014-04-04 02:35:00,19.2430264328\n2014-04-04 02:40:00,18.760376358800002\n2014-04-04 02:45:00,19.9019352247\n2014-04-04 02:50:00,18.2761376672\n2014-04-04 02:55:00,20.805116024500002\n2014-04-04 03:00:00,20.0734330652\n2014-04-04 03:05:00,19.9854992319\n2014-04-04 03:10:00,19.2017815182\n2014-04-04 03:15:00,21.618693750100004\n2014-04-04 03:20:00,18.361945167400002\n2014-04-04 03:25:00,21.479296035500003\n2014-04-04 03:30:00,19.5068208097\n2014-04-04 03:35:00,21.522494063899998\n2014-04-04 03:40:00,20.9150458333\n2014-04-04 03:45:00,18.416682906600002\n2014-04-04 03:50:00,21.326145145999998\n2014-04-04 03:55:00,20.7287073348\n2014-04-04 04:00:00,18.1292076517\n2014-04-04 04:05:00,18.5348107284\n2014-04-04 04:10:00,20.542512223299997\n2014-04-04 04:15:00,20.650402011500002\n2014-04-04 04:20:00,20.9866057314\n2014-04-04 04:25:00,20.8809816031\n2014-04-04 04:30:00,20.6380798187\n2014-04-04 04:35:00,21.064955607\n2014-04-04 04:40:00,20.300342823599998\n2014-04-04 04:45:00,19.0431655421\n2014-04-04 04:50:00,21.6495064549\n2014-04-04 04:55:00,18.0728561237\n2014-04-04 05:00:00,19.4662468795\n2014-04-04 05:05:00,20.9154811724\n2014-04-04 05:10:00,19.7086241646\n2014-04-04 05:15:00,18.0993376299\n2014-04-04 05:20:00,18.2639236125\n2014-04-04 05:25:00,20.5945494766\n2014-04-04 05:30:00,21.8594583976\n2014-04-04 05:35:00,20.2074545433\n2014-04-04 05:40:00,20.0270312721\n2014-04-04 05:45:00,19.273300852200002\n2014-04-04 05:50:00,19.0267626955\n2014-04-04 05:55:00,18.083939927\n2014-04-04 06:00:00,19.0918194706\n2014-04-04 06:05:00,19.7964417635\n2014-04-04 06:10:00,18.7917991322\n2014-04-04 06:15:00,18.3493919539\n2014-04-04 06:20:00,20.870911469\n2014-04-04 06:25:00,21.5784810763\n2014-04-04 06:30:00,21.747088278699998\n2014-04-04 06:35:00,20.471994914\n2014-04-04 06:40:00,18.2110983304\n2014-04-04 06:45:00,20.9634505198\n2014-04-04 06:50:00,18.440381221\n2014-04-04 06:55:00,20.6789924708\n2014-04-04 07:00:00,21.117463343\n2014-04-04 07:05:00,20.903458843299997\n2014-04-04 07:10:00,21.807535223000002\n2014-04-04 07:15:00,20.952585137899998\n2014-04-04 07:20:00,20.7728391119\n2014-04-04 07:25:00,19.0469726887\n2014-04-04 07:30:00,21.699074745700003\n2014-04-04 07:35:00,18.7181754832\n2014-04-04 07:40:00,21.6195864459\n2014-04-04 07:45:00,19.2506501734\n2014-04-04 07:50:00,18.5206543755\n2014-04-04 07:55:00,21.3067321091\n2014-04-04 08:00:00,18.0099818144\n2014-04-04 08:05:00,21.3283532707\n2014-04-04 08:10:00,19.0492473682\n2014-04-04 08:15:00,21.538885090999997\n2014-04-04 08:20:00,20.765916729\n2014-04-04 08:25:00,20.6647333314\n2014-04-04 08:30:00,19.4612782527\n2014-04-04 08:35:00,18.2376118956\n2014-04-04 08:40:00,21.3202923928\n2014-04-04 08:45:00,18.6836151807\n2014-04-04 08:50:00,19.4890345676\n2014-04-04 08:55:00,20.401418742\n2014-04-04 09:00:00,67.7586508444\n2014-04-04 09:05:00,63.9017846383\n2014-04-04 09:10:00,63.1123824536\n2014-04-04 09:15:00,62.87614930260001\n2014-04-04 09:20:00,72.9369071884\n2014-04-04 09:25:00,61.629209867200004\n2014-04-04 09:30:00,74.4873939306\n2014-04-04 09:35:00,63.899990189200004\n2014-04-04 09:40:00,62.7003832376\n2014-04-04 09:45:00,69.046814505\n2014-04-04 09:50:00,62.28780902800001\n2014-04-04 09:55:00,69.39336437899999\n2014-04-04 10:00:00,83.0417255275\n2014-04-04 10:05:00,70.5833772932\n2014-04-04 10:10:00,82.2539607423\n2014-04-04 10:15:00,75.962289884\n2014-04-04 10:20:00,72.3152946371\n2014-04-04 10:25:00,72.5730173738\n2014-04-04 10:30:00,84.0992257181\n2014-04-04 10:35:00,71.5566012701\n2014-04-04 10:40:00,83.292468856\n2014-04-04 10:45:00,78.2866765177\n2014-04-04 10:50:00,70.4461518952\n2014-04-04 10:55:00,77.0486697815\n2014-04-04 11:00:00,84.5687170782\n2014-04-04 11:05:00,83.1175291346\n2014-04-04 11:10:00,79.3415955709\n2014-04-04 11:15:00,85.2462332867\n2014-04-04 11:20:00,73.4822811714\n2014-04-04 11:25:00,86.0397025132\n2014-04-04 11:30:00,85.0298009797\n2014-04-04 11:35:00,82.8324346353\n2014-04-04 11:40:00,84.5756866508\n2014-04-04 11:45:00,80.2168418208\n2014-04-04 11:50:00,82.30578327239999\n2014-04-04 11:55:00,80.4837517165\n2014-04-04 12:00:00,77.5936322603\n2014-04-04 12:05:00,81.0044506305\n2014-04-04 12:10:00,76.0281019861\n2014-04-04 12:15:00,78.9496133734\n2014-04-04 12:20:00,76.4006156283\n2014-04-04 12:25:00,73.8774451858\n2014-04-04 12:30:00,77.0572099546\n2014-04-04 12:35:00,85.52903733640001\n2014-04-04 12:40:00,78.0035755795\n2014-04-04 12:45:00,83.8672967134\n2014-04-04 12:50:00,74.713401869\n2014-04-04 12:55:00,78.69615769880002\n2014-04-04 13:00:00,73.8199760621\n2014-04-04 13:05:00,74.200124709\n2014-04-04 13:10:00,81.8593311225\n2014-04-04 13:15:00,81.70009634899999\n2014-04-04 13:20:00,75.39585116960002\n2014-04-04 13:25:00,79.57166932359999\n2014-04-04 13:30:00,85.79230357600001\n2014-04-04 13:35:00,74.769275205\n2014-04-04 13:40:00,72.2900147607\n2014-04-04 13:45:00,82.4121385893\n2014-04-04 13:50:00,72.8384858963\n2014-04-04 13:55:00,87.6580008466\n2014-04-04 14:00:00,81.7500003524\n2014-04-04 14:05:00,79.5225243811\n2014-04-04 14:10:00,78.8760944061\n2014-04-04 14:15:00,81.165234418\n2014-04-04 14:20:00,73.44646538800001\n2014-04-04 14:25:00,86.8761346865\n2014-04-04 14:30:00,82.00633660369998\n2014-04-04 14:35:00,74.9400586663\n2014-04-04 14:40:00,80.997408798\n2014-04-04 14:45:00,74.1285457523\n2014-04-04 14:50:00,72.2773740004\n2014-04-04 14:55:00,82.0843315264\n2014-04-04 15:00:00,82.3749426629\n2014-04-04 15:05:00,81.3383644691\n2014-04-04 15:10:00,74.9350118867\n2014-04-04 15:15:00,81.6540938491\n2014-04-04 15:20:00,72.9034751747\n2014-04-04 15:25:00,81.7470289101\n2014-04-04 15:30:00,80.8634960087\n2014-04-04 15:35:00,82.4832854463\n2014-04-04 15:40:00,86.326780947\n2014-04-04 15:45:00,85.6049078688\n2014-04-04 15:50:00,87.68962523649998\n2014-04-04 15:55:00,87.6190153764\n2014-04-04 16:00:00,84.3569531283\n2014-04-04 16:05:00,87.3025463336\n2014-04-04 16:10:00,85.8763772913\n2014-04-04 16:15:00,83.641158607\n2014-04-04 16:20:00,73.2060075185\n2014-04-04 16:25:00,72.7846584655\n2014-04-04 16:30:00,85.40142910899999\n2014-04-04 16:35:00,79.8343404437\n2014-04-04 16:40:00,85.0335436853\n2014-04-04 16:45:00,77.0065444776\n2014-04-04 16:50:00,78.3622472774\n2014-04-04 16:55:00,83.2028277865\n2014-04-04 17:00:00,86.6451945191\n2014-04-04 17:05:00,73.4041554045\n2014-04-04 17:10:00,85.7836173732\n2014-04-04 17:15:00,84.68817107779999\n2014-04-04 17:20:00,77.048598745\n2014-04-04 17:25:00,77.6834359957\n2014-04-04 17:30:00,72.7433557021\n2014-04-04 17:35:00,72.2518220332\n2014-04-04 17:40:00,79.632067443\n2014-04-04 17:45:00,73.52860609300001\n2014-04-04 17:50:00,75.10400019069999\n2014-04-04 17:55:00,85.54824234189999\n2014-04-04 18:00:00,32.4545754727\n2014-04-04 18:05:00,32.8552412903\n2014-04-04 18:10:00,29.9998619573\n2014-04-04 18:15:00,34.1034290006\n2014-04-04 18:20:00,34.3550639474\n2014-04-04 18:25:00,32.1492904271\n2014-04-04 18:30:00,34.6403630891\n2014-04-04 18:35:00,34.206896631999996\n2014-04-04 18:40:00,33.4804683025\n2014-04-04 18:45:00,33.498079428800004\n2014-04-04 18:50:00,29.474512574200002\n2014-04-04 18:55:00,30.5333447788\n2014-04-04 19:00:00,20.4594744224\n2014-04-04 19:05:00,20.198890709300002\n2014-04-04 19:10:00,20.8692255558\n2014-04-04 19:15:00,24.1045812559\n2014-04-04 19:20:00,21.2346346196\n2014-04-04 19:25:00,24.506288408099998\n2014-04-04 19:30:00,22.835862425300004\n2014-04-04 19:35:00,21.222916860399998\n2014-04-04 19:40:00,22.3871447715\n2014-04-04 19:45:00,21.1415436459\n2014-04-04 19:50:00,24.5682001929\n2014-04-04 19:55:00,23.9557458138\n2014-04-04 20:00:00,18.5394738564\n2014-04-04 20:05:00,22.3140903571\n2014-04-04 20:10:00,21.3854824229\n2014-04-04 20:15:00,18.769433383\n2014-04-04 20:20:00,21.1789319548\n2014-04-04 20:25:00,21.0818115019\n2014-04-04 20:30:00,19.3281584709\n2014-04-04 20:35:00,21.5385974248\n2014-04-04 20:40:00,18.7886167993\n2014-04-04 20:45:00,20.4367672171\n2014-04-04 20:50:00,18.4726452349\n2014-04-04 20:55:00,22.3999484857\n2014-04-04 21:00:00,21.1070844972\n2014-04-04 21:05:00,18.7248582187\n2014-04-04 21:10:00,19.459656253800002\n2014-04-04 21:15:00,18.7317322631\n2014-04-04 21:20:00,21.1675888601\n2014-04-04 21:25:00,18.323116066300003\n2014-04-04 21:30:00,21.4641623775\n2014-04-04 21:35:00,21.8732754715\n2014-04-04 21:40:00,20.805902976800002\n2014-04-04 21:45:00,18.9423506903\n2014-04-04 21:50:00,19.5336740653\n2014-04-04 21:55:00,20.0045224559\n2014-04-04 22:00:00,20.4381008379\n2014-04-04 22:05:00,20.6945000153\n2014-04-04 22:10:00,20.2362670358\n2014-04-04 22:15:00,19.4238847192\n2014-04-04 22:20:00,21.584370234\n2014-04-04 22:25:00,18.3431607686\n2014-04-04 22:30:00,19.884094630499998\n2014-04-04 22:35:00,21.1225175125\n2014-04-04 22:40:00,18.261004403199998\n2014-04-04 22:45:00,20.841329344200002\n2014-04-04 22:50:00,21.2992741732\n2014-04-04 22:55:00,20.6631427761\n2014-04-04 23:00:00,18.0552135029\n2014-04-04 23:05:00,18.7241424519\n2014-04-04 23:10:00,19.3721710565\n2014-04-04 23:15:00,18.9383956146\n2014-04-04 23:20:00,21.8548038756\n2014-04-04 23:25:00,20.6103320786\n2014-04-04 23:30:00,19.1915679012\n2014-04-04 23:35:00,21.7229600002\n2014-04-04 23:40:00,20.9664015722\n2014-04-04 23:45:00,19.142103423800002\n2014-04-04 23:50:00,19.5192732567\n2014-04-04 23:55:00,18.8013245927\n2014-04-05 00:00:00,21.8842959931\n2014-04-05 00:05:00,20.0691859836\n2014-04-05 00:10:00,21.58422675\n2014-04-05 00:15:00,19.3859990841\n2014-04-05 00:20:00,21.4433664124\n2014-04-05 00:25:00,18.2155473937\n2014-04-05 00:30:00,21.9283612701\n2014-04-05 00:35:00,21.6481374681\n2014-04-05 00:40:00,19.4528117791\n2014-04-05 00:45:00,21.098888661300002\n2014-04-05 00:50:00,21.0090317059\n2014-04-05 00:55:00,21.6050191884\n2014-04-05 01:00:00,19.2290199245\n2014-04-05 01:05:00,19.862080021300002\n2014-04-05 01:10:00,21.4599984504\n2014-04-05 01:15:00,21.1143178165\n2014-04-05 01:20:00,19.573866875\n2014-04-05 01:25:00,21.382900931600002\n2014-04-05 01:30:00,18.187816156900002\n2014-04-05 01:35:00,21.1281852119\n2014-04-05 01:40:00,18.8270634377\n2014-04-05 01:45:00,19.1444836313\n2014-04-05 01:50:00,19.972859374400002\n2014-04-05 01:55:00,19.798938004300002\n2014-04-05 02:00:00,20.0822804275\n2014-04-05 02:05:00,20.1791023827\n2014-04-05 02:10:00,19.3261107641\n2014-04-05 02:15:00,18.7009100521\n2014-04-05 02:20:00,21.0739249171\n2014-04-05 02:25:00,19.5999045963\n2014-04-05 02:30:00,20.0233634498\n2014-04-05 02:35:00,20.5787868734\n2014-04-05 02:40:00,21.6385516892\n2014-04-05 02:45:00,20.8302113246\n2014-04-05 02:50:00,18.1818369024\n2014-04-05 02:55:00,21.3542414536\n2014-04-05 03:00:00,21.957420060500002\n2014-04-05 03:05:00,19.889940101500002\n2014-04-05 03:10:00,21.8783613458\n2014-04-05 03:15:00,20.1893149694\n2014-04-05 03:20:00,19.8384639835\n2014-04-05 03:25:00,19.325619058900003\n2014-04-05 03:30:00,20.630219503299998\n2014-04-05 03:35:00,18.9192816821\n2014-04-05 03:40:00,18.4197368741\n2014-04-05 03:45:00,18.1089484103\n2014-04-05 03:50:00,19.1695204509\n2014-04-05 03:55:00,19.5830833287\n2014-04-05 04:00:00,20.2083067851\n2014-04-05 04:05:00,19.1709993007\n2014-04-05 04:10:00,21.936238289499997\n2014-04-05 04:15:00,19.166980673\n2014-04-05 04:20:00,19.7639015538\n2014-04-05 04:25:00,18.4131046621\n2014-04-05 04:30:00,19.0425060533\n2014-04-05 04:35:00,18.1933285592\n2014-04-05 04:40:00,20.2380345337\n2014-04-05 04:45:00,21.0042587325\n2014-04-05 04:50:00,18.7828392573\n2014-04-05 04:55:00,19.4716437513\n2014-04-05 05:00:00,18.066464906900002\n2014-04-05 05:05:00,21.3580882229\n2014-04-05 05:10:00,21.1198540997\n2014-04-05 05:15:00,18.2530161235\n2014-04-05 05:20:00,19.4594704373\n2014-04-05 05:25:00,21.8211464554\n2014-04-05 05:30:00,19.5681082243\n2014-04-05 05:35:00,20.1048347069\n2014-04-05 05:40:00,19.420971444\n2014-04-05 05:45:00,20.3845255525\n2014-04-05 05:50:00,21.9126275025\n2014-04-05 05:55:00,21.990010013899997\n2014-04-05 06:00:00,21.098859912\n2014-04-05 06:05:00,19.6172443921\n2014-04-05 06:10:00,19.9777288033\n2014-04-05 06:15:00,19.4269253124\n2014-04-05 06:20:00,21.9422985196\n2014-04-05 06:25:00,20.831041223299998\n2014-04-05 06:30:00,19.7957257817\n2014-04-05 06:35:00,18.0484610804\n2014-04-05 06:40:00,20.0819336576\n2014-04-05 06:45:00,21.935712806799998\n2014-04-05 06:50:00,20.092243635899997\n2014-04-05 06:55:00,18.729706742\n2014-04-05 07:00:00,18.0883749884\n2014-04-05 07:05:00,19.4188150325\n2014-04-05 07:10:00,21.6729122228\n2014-04-05 07:15:00,21.9862164327\n2014-04-05 07:20:00,21.7814718992\n2014-04-05 07:25:00,20.917679973\n2014-04-05 07:30:00,20.2325709138\n2014-04-05 07:35:00,20.3627445855\n2014-04-05 07:40:00,20.1559680364\n2014-04-05 07:45:00,20.8281972197\n2014-04-05 07:50:00,19.675492906800002\n2014-04-05 07:55:00,20.6768160198\n2014-04-05 08:00:00,18.486448459800002\n2014-04-05 08:05:00,19.0627812262\n2014-04-05 08:10:00,21.3440121552\n2014-04-05 08:15:00,21.614995723000003\n2014-04-05 08:20:00,20.1560329502\n2014-04-05 08:25:00,18.126542468900002\n2014-04-05 08:30:00,21.7078942832\n2014-04-05 08:35:00,20.808257032100002\n2014-04-05 08:40:00,19.656111695\n2014-04-05 08:45:00,20.3935157728\n2014-04-05 08:50:00,19.7190993378\n2014-04-05 08:55:00,19.8613569069\n2014-04-05 09:00:00,73.26061417300001\n2014-04-05 09:05:00,63.3907457581\n2014-04-05 09:10:00,62.60990024260001\n2014-04-05 09:15:00,61.237110925399996\n2014-04-05 09:20:00,65.4704051083\n2014-04-05 09:25:00,63.2048272242\n2014-04-05 09:30:00,64.1918027339\n2014-04-05 09:35:00,61.3528501642\n2014-04-05 09:40:00,64.28985763979999\n2014-04-05 09:45:00,65.7248775143\n2014-04-05 09:50:00,61.6293179512\n2014-04-05 09:55:00,69.4674960904\n2014-04-05 10:00:00,78.6677814147\n2014-04-05 10:05:00,71.3459952825\n2014-04-05 10:10:00,79.0745517471\n2014-04-05 10:15:00,85.3391088168\n2014-04-05 10:20:00,84.49815814760001\n2014-04-05 10:25:00,69.8814538171\n2014-04-05 10:30:00,82.18427139180001\n2014-04-05 10:35:00,75.3279538872\n2014-04-05 10:40:00,70.82786926760001\n2014-04-05 10:45:00,74.43365947689999\n2014-04-05 10:50:00,74.83335073319999\n2014-04-05 10:55:00,77.96075059409999\n2014-04-05 11:00:00,82.0818762346\n2014-04-05 11:05:00,83.4809804566\n2014-04-05 11:10:00,75.4788419889\n2014-04-05 11:15:00,76.68543914920002\n2014-04-05 11:20:00,76.4725026659\n2014-04-05 11:25:00,77.3369671506\n2014-04-05 11:30:00,87.4665339376\n2014-04-05 11:35:00,83.9404102882\n2014-04-05 11:40:00,87.07424835959999\n2014-04-05 11:45:00,82.59123829100001\n2014-04-05 11:50:00,78.02932923899999\n2014-04-05 11:55:00,77.76649149640001\n2014-04-05 12:00:00,79.7215175616\n2014-04-05 12:05:00,78.57551263399999\n2014-04-05 12:10:00,85.1509160736\n2014-04-05 12:15:00,79.3447041698\n2014-04-05 12:20:00,76.63775396770001\n2014-04-05 12:25:00,84.296486982\n2014-04-05 12:30:00,85.5679216782\n2014-04-05 12:35:00,78.6323910623\n2014-04-05 12:40:00,82.5857152259\n2014-04-05 12:45:00,72.85334349520001\n2014-04-05 12:50:00,80.3748719064\n2014-04-05 12:55:00,72.6324345661\n2014-04-05 13:00:00,72.4496613551\n2014-04-05 13:05:00,81.78716397689999\n2014-04-05 13:10:00,76.83492131050001\n2014-04-05 13:15:00,83.8604632566\n2014-04-05 13:20:00,86.3166000131\n2014-04-05 13:25:00,74.21244351760001\n2014-04-05 13:30:00,83.5723032496\n2014-04-05 13:35:00,80.2130642158\n2014-04-05 13:40:00,73.7761974647\n2014-04-05 13:45:00,82.4056995881\n2014-04-05 13:50:00,81.7318484972\n2014-04-05 13:55:00,80.2310098136\n2014-04-05 14:00:00,86.81937174309998\n2014-04-05 14:05:00,80.3334189485\n2014-04-05 14:10:00,87.84402513159998\n2014-04-05 14:15:00,80.1438139338\n2014-04-05 14:20:00,73.8500876385\n2014-04-05 14:25:00,79.5237226953\n2014-04-05 14:30:00,74.9136641724\n2014-04-05 14:35:00,81.550221165\n2014-04-05 14:40:00,83.0861264776\n2014-04-05 14:45:00,79.491148701\n2014-04-05 14:50:00,73.5597164471\n2014-04-05 14:55:00,79.49444646069999\n2014-04-05 15:00:00,73.3025637244\n2014-04-05 15:05:00,82.9132193136\n2014-04-05 15:10:00,84.64507899729999\n2014-04-05 15:15:00,87.39724621399998\n2014-04-05 15:20:00,74.3801196581\n2014-04-05 15:25:00,80.5179523888\n2014-04-05 15:30:00,81.0798195068\n2014-04-05 15:35:00,86.7587916481\n2014-04-05 15:40:00,82.03563869989999\n2014-04-05 15:45:00,74.32744078\n2014-04-05 15:50:00,78.98086295979999\n2014-04-05 15:55:00,82.4754086846\n2014-04-05 16:00:00,83.2043911604\n2014-04-05 16:05:00,85.80901922380002\n2014-04-05 16:10:00,74.8879701323\n2014-04-05 16:15:00,87.2245068767\n2014-04-05 16:20:00,72.9460905355\n2014-04-05 16:25:00,87.7400256919\n2014-04-05 16:30:00,85.72410889529999\n2014-04-05 16:35:00,82.56420600060001\n2014-04-05 16:40:00,83.7597671852\n2014-04-05 16:45:00,73.1629316216\n2014-04-05 16:50:00,72.663538292\n2014-04-05 16:55:00,73.6281113786\n2014-04-05 17:00:00,73.39772884989999\n2014-04-05 17:05:00,80.75806872439999\n2014-04-05 17:10:00,75.4470748221\n2014-04-05 17:15:00,85.7632572622\n2014-04-05 17:20:00,79.1319475824\n2014-04-05 17:25:00,83.1281357021\n2014-04-05 17:30:00,82.4459378283\n2014-04-05 17:35:00,77.11761900970001\n2014-04-05 17:40:00,75.89065203439999\n2014-04-05 17:45:00,77.47927081270001\n2014-04-05 17:50:00,84.7465014389\n2014-04-05 17:55:00,81.3803983246\n2014-04-05 18:00:00,30.422641599000002\n2014-04-05 18:05:00,34.034210701\n2014-04-05 18:10:00,29.1504544742\n2014-04-05 18:15:00,33.2747672112\n2014-04-05 18:20:00,31.610239087600004\n2014-04-05 18:25:00,33.4802520426\n2014-04-05 18:30:00,34.7357455243\n2014-04-05 18:35:00,33.6002117756\n2014-04-05 18:40:00,31.62857220130001\n2014-04-05 18:45:00,29.766238646599998\n2014-04-05 18:50:00,33.960639724699995\n2014-04-05 18:55:00,31.7485092766\n2014-04-05 19:00:00,20.4973980847\n2014-04-05 19:05:00,23.3813668994\n2014-04-05 19:10:00,21.4674956297\n2014-04-05 19:15:00,20.3790181502\n2014-04-05 19:20:00,24.204323219299997\n2014-04-05 19:25:00,22.3242916679\n2014-04-05 19:30:00,21.418704343199998\n2014-04-05 19:35:00,23.3694104973\n2014-04-05 19:40:00,24.1288413284\n2014-04-05 19:45:00,20.1613745902\n2014-04-05 19:50:00,23.241576514000002\n2014-04-05 19:55:00,23.5962110948\n2014-04-05 20:00:00,19.291862510599998\n2014-04-05 20:05:00,20.4374989682\n2014-04-05 20:10:00,18.797714816400003\n2014-04-05 20:15:00,21.490687260900003\n2014-04-05 20:20:00,21.9031795892\n2014-04-05 20:25:00,18.8751323219\n2014-04-05 20:30:00,21.7762209367\n2014-04-05 20:35:00,21.5923511592\n2014-04-05 20:40:00,19.852956722000002\n2014-04-05 20:45:00,21.2594256595\n2014-04-05 20:50:00,18.432196894300002\n2014-04-05 20:55:00,22.2486429257\n2014-04-05 21:00:00,20.2985002497\n2014-04-05 21:05:00,20.5796659121\n2014-04-05 21:10:00,20.757799064100002\n2014-04-05 21:15:00,20.3426543042\n2014-04-05 21:20:00,21.5299053641\n2014-04-05 21:25:00,20.536913553599998\n2014-04-05 21:30:00,21.734868903600002\n2014-04-05 21:35:00,20.426907206099997\n2014-04-05 21:40:00,18.7741751925\n2014-04-05 21:45:00,21.7581905712\n2014-04-05 21:50:00,20.8259971905\n2014-04-05 21:55:00,20.8967813153\n2014-04-05 22:00:00,21.962991241399997\n2014-04-05 22:05:00,18.3183549626\n2014-04-05 22:10:00,19.7332962143\n2014-04-05 22:15:00,18.9745796889\n2014-04-05 22:20:00,20.541406686400002\n2014-04-05 22:25:00,21.2476248814\n2014-04-05 22:30:00,21.8862334579\n2014-04-05 22:35:00,19.8374100671\n2014-04-05 22:40:00,21.1651719902\n2014-04-05 22:45:00,21.6890078356\n2014-04-05 22:50:00,20.7532056896\n2014-04-05 22:55:00,18.9891422935\n2014-04-05 23:00:00,20.4353394344\n2014-04-05 23:05:00,21.8840091123\n2014-04-05 23:10:00,21.9544297546\n2014-04-05 23:15:00,20.5733886252\n2014-04-05 23:20:00,21.552088236\n2014-04-05 23:25:00,18.8050073219\n2014-04-05 23:30:00,18.9879594063\n2014-04-05 23:35:00,21.8157382671\n2014-04-05 23:40:00,18.5445013609\n2014-04-05 23:45:00,18.7680285203\n2014-04-05 23:50:00,19.685973375899998\n2014-04-05 23:55:00,20.3622459497\n2014-04-06 00:00:00,20.4152688759\n2014-04-06 00:05:00,19.1679040347\n2014-04-06 00:10:00,21.682455591799997\n2014-04-06 00:15:00,21.6603996304\n2014-04-06 00:20:00,19.5682722122\n2014-04-06 00:25:00,19.7371670777\n2014-04-06 00:30:00,20.809988467300002\n2014-04-06 00:35:00,20.6519835856\n2014-04-06 00:40:00,19.5291880598\n2014-04-06 00:45:00,19.6569770061\n2014-04-06 00:50:00,19.392155773699997\n2014-04-06 00:55:00,18.9415400278\n2014-04-06 01:00:00,19.8325534517\n2014-04-06 01:05:00,20.7457365276\n2014-04-06 01:10:00,20.9678668213\n2014-04-06 01:15:00,21.115494593\n2014-04-06 01:20:00,19.4989280538\n2014-04-06 01:25:00,21.0585439771\n2014-04-06 01:30:00,18.0260652628\n2014-04-06 01:35:00,19.9081997509\n2014-04-06 01:40:00,21.1756176005\n2014-04-06 01:45:00,20.5201788826\n2014-04-06 01:50:00,19.896252496600003\n2014-04-06 01:55:00,20.578568026400003\n2014-04-06 02:00:00,21.627784012600003\n2014-04-06 02:05:00,20.2655272024\n2014-04-06 02:10:00,21.1991447658\n2014-04-06 02:15:00,21.9229709009\n2014-04-06 02:20:00,20.8222728083\n2014-04-06 02:25:00,20.2933030556\n2014-04-06 02:30:00,18.1499437885\n2014-04-06 02:35:00,19.497911592999998\n2014-04-06 02:40:00,20.2617709341\n2014-04-06 02:45:00,21.1888262868\n2014-04-06 02:50:00,19.7524191586\n2014-04-06 02:55:00,21.8402331031\n2014-04-06 03:00:00,19.0871750105\n2014-04-06 03:05:00,20.9782687808\n2014-04-06 03:10:00,19.6761256683\n2014-04-06 03:15:00,19.943953978299998\n2014-04-06 03:20:00,21.2100081355\n2014-04-06 03:25:00,19.184861046600002\n2014-04-06 03:30:00,18.3872482264\n2014-04-06 03:35:00,20.0810223385\n2014-04-06 03:40:00,20.1151784472\n2014-04-06 03:45:00,21.1886710889\n2014-04-06 03:50:00,21.873276824899996\n2014-04-06 03:55:00,18.2212027453\n2014-04-06 04:00:00,20.366757895\n2014-04-06 04:05:00,20.725114121300003\n2014-04-06 04:10:00,21.943205403\n2014-04-06 04:15:00,21.770360857100002\n2014-04-06 04:20:00,20.849803058800003\n2014-04-06 04:25:00,20.087157645\n2014-04-06 04:30:00,18.6460956892\n2014-04-06 04:35:00,19.5367062208\n2014-04-06 04:40:00,20.3404893002\n2014-04-06 04:45:00,20.9008015864\n2014-04-06 04:50:00,20.5415982299\n2014-04-06 04:55:00,20.8564912073\n2014-04-06 05:00:00,19.7166100182\n2014-04-06 05:05:00,20.9105091623\n2014-04-06 05:10:00,18.574965024100003\n2014-04-06 05:15:00,18.6503452471\n2014-04-06 05:20:00,18.6513285833\n2014-04-06 05:25:00,21.5634598281\n2014-04-06 05:30:00,18.3041362532\n2014-04-06 05:35:00,21.206033490899998\n2014-04-06 05:40:00,18.9342835922\n2014-04-06 05:45:00,19.873719762\n2014-04-06 05:50:00,21.6638263819\n2014-04-06 05:55:00,20.343748918800003\n2014-04-06 06:00:00,18.8404707449\n2014-04-06 06:05:00,19.1363602413\n2014-04-06 06:10:00,21.6817864956\n2014-04-06 06:15:00,19.7085757004\n2014-04-06 06:20:00,20.347941932\n2014-04-06 06:25:00,19.8397287865\n2014-04-06 06:30:00,19.5137523522\n2014-04-06 06:35:00,18.8931165077\n2014-04-06 06:40:00,20.7447660019\n2014-04-06 06:45:00,20.8729681051\n2014-04-06 06:50:00,19.0995403664\n2014-04-06 06:55:00,21.1560433722\n2014-04-06 07:00:00,21.4181408012\n2014-04-06 07:05:00,21.682700385\n2014-04-06 07:10:00,18.6448496557\n2014-04-06 07:15:00,19.2156947345\n2014-04-06 07:20:00,21.44141339\n2014-04-06 07:25:00,18.7941608113\n2014-04-06 07:30:00,18.013873837000002\n2014-04-06 07:35:00,21.483309241\n2014-04-06 07:40:00,19.305797767\n2014-04-06 07:45:00,19.6579901006\n2014-04-06 07:50:00,19.7853361029\n2014-04-06 07:55:00,21.3930984027\n2014-04-06 08:00:00,19.3515685784\n2014-04-06 08:05:00,21.569119543400003\n2014-04-06 08:10:00,20.4677565522\n2014-04-06 08:15:00,20.1091468961\n2014-04-06 08:20:00,19.3024580285\n2014-04-06 08:25:00,18.9748467851\n2014-04-06 08:30:00,20.496233771099998\n2014-04-06 08:35:00,19.7875766402\n2014-04-06 08:40:00,21.6420640397\n2014-04-06 08:45:00,19.9665548645\n2014-04-06 08:50:00,20.0471796668\n2014-04-06 08:55:00,19.6668931245\n2014-04-06 09:00:00,71.9339767591\n2014-04-06 09:05:00,66.9778130943\n2014-04-06 09:10:00,64.8630511966\n2014-04-06 09:15:00,72.9236198904\n2014-04-06 09:20:00,69.3168638106\n2014-04-06 09:25:00,69.2445389889\n2014-04-06 09:30:00,69.5071820174\n2014-04-06 09:35:00,70.97622057560001\n2014-04-06 09:40:00,65.4577246547\n2014-04-06 09:45:00,61.6602834433\n2014-04-06 09:50:00,72.2240669879\n2014-04-06 09:55:00,62.9531087328\n2014-04-06 10:00:00,81.0426423215\n2014-04-06 10:05:00,71.1175334294\n2014-04-06 10:10:00,75.6647777083\n2014-04-06 10:15:00,70.8181646038\n2014-04-06 10:20:00,77.94475630779999\n2014-04-06 10:25:00,79.9766671936\n2014-04-06 10:30:00,72.5006423511\n2014-04-06 10:35:00,75.6076606382\n2014-04-06 10:40:00,84.277316901\n2014-04-06 10:45:00,76.7058790975\n2014-04-06 10:50:00,82.2954761905\n2014-04-06 10:55:00,84.2299072433\n2014-04-06 11:00:00,87.06399600040001\n2014-04-06 11:05:00,85.8549134012\n2014-04-06 11:10:00,76.6160143549\n2014-04-06 11:15:00,86.87675918149998\n2014-04-06 11:20:00,84.4883339247\n2014-04-06 11:25:00,84.8824404822\n2014-04-06 11:30:00,71.8093111403\n2014-04-06 11:35:00,86.7442148822\n2014-04-06 11:40:00,83.9427469201\n2014-04-06 11:45:00,83.7817550645\n2014-04-06 11:50:00,72.8645693207\n2014-04-06 11:55:00,75.26677007720001\n2014-04-06 12:00:00,87.2913112182\n2014-04-06 12:05:00,79.9148201971\n2014-04-06 12:10:00,78.27168941779999\n2014-04-06 12:15:00,85.3365262107\n2014-04-06 12:20:00,73.3093696899\n2014-04-06 12:25:00,78.5766669736\n2014-04-06 12:30:00,77.9175989359\n2014-04-06 12:35:00,77.5045050459\n2014-04-06 12:40:00,76.8307682074\n2014-04-06 12:45:00,75.2707658695\n2014-04-06 12:50:00,74.6768529604\n2014-04-06 12:55:00,82.1478020733\n2014-04-06 13:00:00,86.68950698309997\n2014-04-06 13:05:00,80.1223923337\n2014-04-06 13:10:00,76.7491686153\n2014-04-06 13:15:00,74.5286719884\n2014-04-06 13:20:00,85.26182609029999\n2014-04-06 13:25:00,87.5228623741\n2014-04-06 13:30:00,77.5678656667\n2014-04-06 13:35:00,76.6368095592\n2014-04-06 13:40:00,81.60429751470001\n2014-04-06 13:45:00,84.385006432\n2014-04-06 13:50:00,79.26741611\n2014-04-06 13:55:00,82.06147091689999\n2014-04-06 14:00:00,83.4607787787\n2014-04-06 14:05:00,87.3652828708\n2014-04-06 14:10:00,74.6370145397\n2014-04-06 14:15:00,87.9538979115\n2014-04-06 14:20:00,78.2707493075\n2014-04-06 14:25:00,83.5671908659\n2014-04-06 14:30:00,81.15473443329998\n2014-04-06 14:35:00,79.7828681106\n2014-04-06 14:40:00,83.16521377779999\n2014-04-06 14:45:00,78.3283016646\n2014-04-06 14:50:00,74.0142068489\n2014-04-06 14:55:00,79.81846265979999\n2014-04-06 15:00:00,80.3498825646\n2014-04-06 15:05:00,75.22971224220001\n2014-04-06 15:10:00,86.9690747901\n2014-04-06 15:15:00,75.6388842061\n2014-04-06 15:20:00,78.546887448\n2014-04-06 15:25:00,74.4781599923\n2014-04-06 15:30:00,80.5719728406\n2014-04-06 15:35:00,76.92146327649999\n2014-04-06 15:40:00,79.82759396739999\n2014-04-06 15:45:00,75.5931449622\n2014-04-06 15:50:00,72.85970258729999\n2014-04-06 15:55:00,84.4668155281\n2014-04-06 16:00:00,82.2572226092\n2014-04-06 16:05:00,77.4516809839\n2014-04-06 16:10:00,72.7597678959\n2014-04-06 16:15:00,85.84903617270001\n2014-04-06 16:20:00,74.71657662289998\n2014-04-06 16:25:00,86.89170866010002\n2014-04-06 16:30:00,79.6573731151\n2014-04-06 16:35:00,77.44603866189999\n2014-04-06 16:40:00,83.8679906034\n2014-04-06 16:45:00,86.02926532069998\n2014-04-06 16:50:00,77.93126739\n2014-04-06 16:55:00,78.5173492811\n2014-04-06 17:00:00,78.9305012002\n2014-04-06 17:05:00,86.75713566889999\n2014-04-06 17:10:00,83.0809919611\n2014-04-06 17:15:00,75.9623087032\n2014-04-06 17:20:00,74.9599663754\n2014-04-06 17:25:00,75.6858535514\n2014-04-06 17:30:00,76.2169929596\n2014-04-06 17:35:00,75.6829067991\n2014-04-06 17:40:00,82.5360714612\n2014-04-06 17:45:00,73.8549078102\n2014-04-06 17:50:00,78.1977058074\n2014-04-06 17:55:00,82.0008256792\n2014-04-06 18:00:00,30.661497946199997\n2014-04-06 18:05:00,29.2177504523\n2014-04-06 18:10:00,29.323667476100002\n2014-04-06 18:15:00,29.60618168400001\n2014-04-06 18:20:00,34.1493888025\n2014-04-06 18:25:00,33.0103200979\n2014-04-06 18:30:00,29.2129378221\n2014-04-06 18:35:00,31.302834816399997\n2014-04-06 18:40:00,30.5829392343\n2014-04-06 18:45:00,32.4994504745\n2014-04-06 18:50:00,32.1459519059\n2014-04-06 18:55:00,31.8791876288\n2014-04-06 19:00:00,21.569014236100006\n2014-04-06 19:05:00,20.777341839\n2014-04-06 19:10:00,23.4858449069\n2014-04-06 19:15:00,24.1017570023\n2014-04-06 19:20:00,24.3897947354\n2014-04-06 19:25:00,20.422611868\n2014-04-06 19:30:00,23.4747897402\n2014-04-06 19:35:00,23.414734213699997\n2014-04-06 19:40:00,24.4030497327\n2014-04-06 19:45:00,21.2930562153\n2014-04-06 19:50:00,23.484960803200003\n2014-04-06 19:55:00,20.4047246543\n2014-04-06 20:00:00,21.01758222\n2014-04-06 20:05:00,19.869072448900003\n2014-04-06 20:10:00,21.581452805399998\n2014-04-06 20:15:00,21.9680940936\n2014-04-06 20:20:00,19.926306749800002\n2014-04-06 20:25:00,20.5848003887\n2014-04-06 20:30:00,18.9128868125\n2014-04-06 20:35:00,20.139650687899998\n2014-04-06 20:40:00,19.9098381719\n2014-04-06 20:45:00,19.1820734611\n2014-04-06 20:50:00,22.0957841819\n2014-04-06 20:55:00,19.0385675561\n2014-04-06 21:00:00,20.6415635753\n2014-04-06 21:05:00,21.6640612597\n2014-04-06 21:10:00,21.751784063000002\n2014-04-06 21:15:00,21.274588949600002\n2014-04-06 21:20:00,18.7943463993\n2014-04-06 21:25:00,21.3718202676\n2014-04-06 21:30:00,19.1979692471\n2014-04-06 21:35:00,21.7937020986\n2014-04-06 21:40:00,20.936361138800002\n2014-04-06 21:45:00,21.2425473293\n2014-04-06 21:50:00,18.428162392\n2014-04-06 21:55:00,20.428649494000002\n2014-04-06 22:00:00,21.3050016829\n2014-04-06 22:05:00,21.4669499075\n2014-04-06 22:10:00,18.1319167558\n2014-04-06 22:15:00,21.777523290999998\n2014-04-06 22:20:00,18.190801345\n2014-04-06 22:25:00,20.477714460399998\n2014-04-06 22:30:00,20.7934927084\n2014-04-06 22:35:00,18.4470733615\n2014-04-06 22:40:00,18.2095118191\n2014-04-06 22:45:00,21.1599426701\n2014-04-06 22:50:00,19.5574396248\n2014-04-06 22:55:00,18.4461413643\n2014-04-06 23:00:00,21.0547129924\n2014-04-06 23:05:00,21.4007604357\n2014-04-06 23:10:00,20.353451873599997\n2014-04-06 23:15:00,18.6485270618\n2014-04-06 23:20:00,18.064357575\n2014-04-06 23:25:00,20.8072041395\n2014-04-06 23:30:00,20.2044372046\n2014-04-06 23:35:00,20.6071443771\n2014-04-06 23:40:00,21.2568192045\n2014-04-06 23:45:00,19.740700593\n2014-04-06 23:50:00,18.5016135014\n2014-04-06 23:55:00,21.7641110466\n2014-04-07 00:00:00,20.181048509\n2014-04-07 00:05:00,20.461176476400002\n2014-04-07 00:10:00,21.733645718200002\n2014-04-07 00:15:00,21.7263346252\n2014-04-07 00:20:00,20.2883784269\n2014-04-07 00:25:00,19.1904456989\n2014-04-07 00:30:00,21.9884545361\n2014-04-07 00:35:00,20.7232683598\n2014-04-07 00:40:00,19.6337467076\n2014-04-07 00:45:00,20.239347211400002\n2014-04-07 00:50:00,19.663336201099998\n2014-04-07 00:55:00,21.5532206092\n2014-04-07 01:00:00,19.9299974995\n2014-04-07 01:05:00,21.2941135039\n2014-04-07 01:10:00,21.360705191300003\n2014-04-07 01:15:00,21.2973293509\n2014-04-07 01:20:00,20.8887544499\n2014-04-07 01:25:00,21.4195108672\n2014-04-07 01:30:00,19.5489183185\n2014-04-07 01:35:00,18.4586528246\n2014-04-07 01:40:00,21.3698168175\n2014-04-07 01:45:00,19.9926736627\n2014-04-07 01:50:00,18.5095041301\n2014-04-07 01:55:00,18.461250088699998\n2014-04-07 02:00:00,18.636969576\n2014-04-07 02:05:00,21.0038930387\n2014-04-07 02:10:00,20.8434266939\n2014-04-07 02:15:00,18.8152747207\n2014-04-07 02:20:00,21.3876936724\n2014-04-07 02:25:00,19.125179182100002\n2014-04-07 02:30:00,21.1719423333\n2014-04-07 02:35:00,19.9552236309\n2014-04-07 02:40:00,20.9261947302\n2014-04-07 02:45:00,19.5255506523\n2014-04-07 02:50:00,19.3885623884\n2014-04-07 02:55:00,21.3654383958\n2014-04-07 03:00:00,18.1412090181\n2014-04-07 03:05:00,21.898947789\n2014-04-07 03:10:00,20.5927182331\n2014-04-07 03:15:00,19.7299335528\n2014-04-07 03:20:00,20.5122181246\n2014-04-07 03:25:00,18.490963785799998\n2014-04-07 03:30:00,20.0562098212\n2014-04-07 03:35:00,21.9403820934\n2014-04-07 03:40:00,18.9410777514\n2014-04-07 03:45:00,20.8891123961\n2014-04-07 03:50:00,19.7398855033\n2014-04-07 03:55:00,20.609832594\n2014-04-07 04:00:00,18.8195489148\n2014-04-07 04:05:00,19.8818599305\n2014-04-07 04:10:00,21.920370855399998\n2014-04-07 04:15:00,18.7811486041\n2014-04-07 04:20:00,20.545780111400003\n2014-04-07 04:25:00,20.3023909951\n2014-04-07 04:30:00,20.2602063452\n2014-04-07 04:35:00,20.4604931586\n2014-04-07 04:40:00,20.0089518948\n2014-04-07 04:45:00,18.067723000999997\n2014-04-07 04:50:00,21.600387245900002\n2014-04-07 04:55:00,21.3079153099\n2014-04-07 05:00:00,18.6966707237\n2014-04-07 05:05:00,19.6530927095\n2014-04-07 05:10:00,21.0821959228\n2014-04-07 05:15:00,21.9202492615\n2014-04-07 05:20:00,21.804548185799998\n2014-04-07 05:25:00,21.5974367987\n2014-04-07 05:30:00,18.633495589200002\n2014-04-07 05:35:00,21.657900424\n2014-04-07 05:40:00,21.513779651799997\n2014-04-07 05:45:00,19.5077996447\n2014-04-07 05:50:00,19.5780903781\n2014-04-07 05:55:00,19.8396356878\n2014-04-07 06:00:00,20.6247025239\n2014-04-07 06:05:00,19.0433424639\n2014-04-07 06:10:00,18.091793717799998\n2014-04-07 06:15:00,18.5649180984\n2014-04-07 06:20:00,19.7604636303\n2014-04-07 06:25:00,19.1280102777\n2014-04-07 06:30:00,21.0580662441\n2014-04-07 06:35:00,18.4267602822\n2014-04-07 06:40:00,21.669860902199996\n2014-04-07 06:45:00,21.5813087198\n2014-04-07 06:50:00,21.6350272677\n2014-04-07 06:55:00,20.9584399944\n2014-04-07 07:00:00,18.4279998859\n2014-04-07 07:05:00,19.7525502855\n2014-04-07 07:10:00,18.5256214872\n2014-04-07 07:15:00,21.950796771\n2014-04-07 07:20:00,19.3321536936\n2014-04-07 07:25:00,20.3413221676\n2014-04-07 07:30:00,21.117572217\n2014-04-07 07:35:00,21.6824643369\n2014-04-07 07:40:00,21.0221909034\n2014-04-07 07:45:00,20.6980151151\n2014-04-07 07:50:00,19.8639271282\n2014-04-07 07:55:00,20.421600535\n2014-04-07 08:00:00,18.3766552354\n2014-04-07 08:05:00,21.535690167800002\n2014-04-07 08:10:00,20.1751092354\n2014-04-07 08:15:00,18.1605402017\n2014-04-07 08:20:00,21.6796085026\n2014-04-07 08:25:00,19.957207895299998\n2014-04-07 08:30:00,21.474356566199997\n2014-04-07 08:35:00,21.4275518168\n2014-04-07 08:40:00,21.2630063498\n2014-04-07 08:45:00,18.2456120772\n2014-04-07 08:50:00,18.9882665817\n2014-04-07 08:55:00,21.502191489899996\n2014-04-07 09:00:00,73.4262783623\n2014-04-07 09:05:00,67.4297365282\n2014-04-07 09:10:00,67.18456396010001\n2014-04-07 09:15:00,63.5819126209\n2014-04-07 09:20:00,74.3703867262\n2014-04-07 09:25:00,64.0986832649\n2014-04-07 09:30:00,63.7967402672\n2014-04-07 09:35:00,70.18591399399999\n2014-04-07 09:40:00,64.5026825208\n2014-04-07 09:45:00,73.96729390979999\n2014-04-07 09:50:00,61.3483351363\n2014-04-07 09:55:00,61.2782443676\n2014-04-07 10:00:00,77.6756879583\n2014-04-07 10:05:00,77.4147293779\n2014-04-07 10:10:00,72.3754096199\n2014-04-07 10:15:00,77.51494361729999\n2014-04-07 10:20:00,76.2289803522\n2014-04-07 10:25:00,83.6579142333\n2014-04-07 10:30:00,69.9836208418\n2014-04-07 10:35:00,84.9917073741\n2014-04-07 10:40:00,79.53057570189999\n2014-04-07 10:45:00,72.19661027640001\n2014-04-07 10:50:00,70.5657154143\n2014-04-07 10:55:00,78.1913998208\n2014-04-07 11:00:00,75.3036931996\n2014-04-07 11:05:00,76.3577367005\n2014-04-07 11:10:00,75.4665819495\n2014-04-07 11:15:00,81.9083404751\n2014-04-07 11:20:00,80.37132461350001\n2014-04-07 11:25:00,72.8081052317\n2014-04-07 11:30:00,79.9418779836\n2014-04-07 11:35:00,84.1510820315\n2014-04-07 11:40:00,72.8593187724\n2014-04-07 11:45:00,85.718408678\n2014-04-07 11:50:00,80.7653889528\n2014-04-07 11:55:00,86.6867315593\n2014-04-07 12:00:00,74.2810151722\n2014-04-07 12:05:00,87.7915635417\n2014-04-07 12:10:00,82.2095958165\n2014-04-07 12:15:00,80.9826113031\n2014-04-07 12:20:00,80.148180617\n2014-04-07 12:25:00,72.2916158056\n2014-04-07 12:30:00,86.9297859923\n2014-04-07 12:35:00,82.2051468718\n2014-04-07 12:40:00,73.37786452350001\n2014-04-07 12:45:00,72.248432443\n2014-04-07 12:50:00,72.7251631819\n2014-04-07 12:55:00,81.6522318163\n2014-04-07 13:00:00,81.8046088191\n2014-04-07 13:05:00,79.9754779461\n2014-04-07 13:10:00,76.8897951497\n2014-04-07 13:15:00,80.4885618137\n2014-04-07 13:20:00,80.241566535\n2014-04-07 13:25:00,72.29329440229999\n2014-04-07 13:30:00,76.5011430034\n2014-04-07 13:35:00,72.83348123180001\n2014-04-07 13:40:00,86.38173942889999\n2014-04-07 13:45:00,83.5835057476\n2014-04-07 13:50:00,87.9167376408\n2014-04-07 13:55:00,76.8162998752\n2014-04-07 14:00:00,86.05164288700001\n2014-04-07 14:05:00,81.6449491412\n2014-04-07 14:10:00,79.2462025101\n2014-04-07 14:15:00,75.55754284449999\n2014-04-07 14:20:00,83.8102515594\n2014-04-07 14:25:00,86.4621016024\n2014-04-07 14:30:00,75.7612976524\n2014-04-07 14:35:00,74.8026546598\n2014-04-07 14:40:00,83.1355599416\n2014-04-07 14:45:00,87.6273642882\n2014-04-07 14:50:00,83.9952496521\n2014-04-07 14:55:00,76.5496172668\n2014-04-07 15:00:00,78.7185310812\n2014-04-07 15:05:00,78.14833193609999\n2014-04-07 15:10:00,85.632698207\n2014-04-07 15:15:00,84.3411227794\n2014-04-07 15:20:00,81.4228252896\n2014-04-07 15:25:00,76.3986123326\n2014-04-07 15:30:00,87.0069811685\n2014-04-07 15:35:00,82.4522520471\n2014-04-07 15:40:00,87.52678607790001\n2014-04-07 15:45:00,81.28109222270001\n2014-04-07 15:50:00,85.1382667986\n2014-04-07 15:55:00,85.0088699773\n2014-04-07 16:00:00,77.3971118266\n2014-04-07 16:05:00,87.4241637126\n2014-04-07 16:10:00,72.3509245675\n2014-04-07 16:15:00,84.2992126855\n2014-04-07 16:20:00,87.44874547030001\n2014-04-07 16:25:00,77.4223826013\n2014-04-07 16:30:00,82.3696112547\n2014-04-07 16:35:00,80.99541648600001\n2014-04-07 16:40:00,84.1839553213\n2014-04-07 16:45:00,85.8586818973\n2014-04-07 16:50:00,81.6485563433\n2014-04-07 16:55:00,85.0543100775\n2014-04-07 17:00:00,76.9965396475\n2014-04-07 17:05:00,75.6573638868\n2014-04-07 17:10:00,78.89065273850001\n2014-04-07 17:15:00,82.8437537813\n2014-04-07 17:20:00,74.99592238460002\n2014-04-07 17:25:00,82.88560324630002\n2014-04-07 17:30:00,78.3054683078\n2014-04-07 17:35:00,84.7291718463\n2014-04-07 17:40:00,72.5893451993\n2014-04-07 17:45:00,82.68769045319999\n2014-04-07 17:50:00,82.3971257459\n2014-04-07 17:55:00,87.05493418889999\n2014-04-07 18:00:00,33.3655459366\n2014-04-07 18:05:00,33.896325629\n2014-04-07 18:10:00,34.5893758603\n2014-04-07 18:15:00,33.120325918\n2014-04-07 18:20:00,30.6569773776\n2014-04-07 18:25:00,34.366545719\n2014-04-07 18:30:00,33.5844935164\n2014-04-07 18:35:00,31.516394614499998\n2014-04-07 18:40:00,33.3473803023\n2014-04-07 18:45:00,34.3532022181\n2014-04-07 18:50:00,35.044166912399994\n2014-04-07 18:55:00,34.8950429255\n2014-04-07 19:00:00,21.617467478000002\n2014-04-07 19:05:00,22.0491866279\n2014-04-07 19:10:00,20.6507228575\n2014-04-07 19:15:00,21.268997239100003\n2014-04-07 19:20:00,24.1132456912\n2014-04-07 19:25:00,21.776606475100003\n2014-04-07 19:30:00,22.9400746521\n2014-04-07 19:35:00,23.1435247004\n2014-04-07 19:40:00,23.6625938546\n2014-04-07 19:45:00,20.9789429847\n2014-04-07 19:50:00,21.525561662199998\n2014-04-07 19:55:00,22.1685455936\n2014-04-07 20:00:00,19.9263887477\n2014-04-07 20:05:00,22.457979564299997\n2014-04-07 20:10:00,21.8519172677\n2014-04-07 20:15:00,20.3967967022\n2014-04-07 20:20:00,22.033484028\n2014-04-07 20:25:00,19.855986235\n2014-04-07 20:30:00,21.6507525548\n2014-04-07 20:35:00,19.3481750177\n2014-04-07 20:40:00,21.5954308381\n2014-04-07 20:45:00,20.3016328959\n2014-04-07 20:50:00,18.8723169923\n2014-04-07 20:55:00,19.5512827792\n2014-04-07 21:00:00,19.703222120699998\n2014-04-07 21:05:00,21.097958019\n2014-04-07 21:10:00,18.379732082100002\n2014-04-07 21:15:00,20.737251232000002\n2014-04-07 21:20:00,20.9642019744\n2014-04-07 21:25:00,20.7146407193\n2014-04-07 21:30:00,21.143683358\n2014-04-07 21:35:00,18.8024952555\n2014-04-07 21:40:00,20.4460857547\n2014-04-07 21:45:00,21.869049718299998\n2014-04-07 21:50:00,20.541264087000002\n2014-04-07 21:55:00,20.543482995399998\n2014-04-07 22:00:00,20.9658664864\n2014-04-07 22:05:00,19.3513764233\n2014-04-07 22:10:00,20.8218734225\n2014-04-07 22:15:00,21.685733660500002\n2014-04-07 22:20:00,18.0609037218\n2014-04-07 22:25:00,21.501073388000002\n2014-04-07 22:30:00,18.8925928102\n2014-04-07 22:35:00,19.8427238304\n2014-04-07 22:40:00,21.429944208800002\n2014-04-07 22:45:00,21.3160923219\n2014-04-07 22:50:00,21.5884149034\n2014-04-07 22:55:00,21.7825583603\n2014-04-07 23:00:00,19.7924272417\n2014-04-07 23:05:00,20.6294153286\n2014-04-07 23:10:00,19.5656696476\n2014-04-07 23:15:00,19.4065922185\n2014-04-07 23:20:00,19.7301691057\n2014-04-07 23:25:00,20.9763312195\n2014-04-07 23:30:00,20.0096040931\n2014-04-07 23:35:00,21.2603198935\n2014-04-07 23:40:00,20.9849022345\n2014-04-07 23:45:00,18.0853855702\n2014-04-07 23:50:00,20.5248926493\n2014-04-07 23:55:00,19.7500757779\n2014-04-08 00:00:00,19.8265159566\n2014-04-08 00:05:00,21.2734922155\n2014-04-08 00:10:00,20.190431944300002\n2014-04-08 00:15:00,21.5424872938\n2014-04-08 00:20:00,20.851222369600002\n2014-04-08 00:25:00,20.2113600351\n2014-04-08 00:30:00,21.0181519046\n2014-04-08 00:35:00,18.153396203699998\n2014-04-08 00:40:00,18.1083346193\n2014-04-08 00:45:00,18.3333973077\n2014-04-08 00:50:00,19.7502613006\n2014-04-08 00:55:00,18.9418005825\n2014-04-08 01:00:00,21.9370451777\n2014-04-08 01:05:00,20.169160555999998\n2014-04-08 01:10:00,20.6496629843\n2014-04-08 01:15:00,19.115280545\n2014-04-08 01:20:00,19.287187634400002\n2014-04-08 01:25:00,19.341847656600002\n2014-04-08 01:30:00,20.7949428206\n2014-04-08 01:35:00,19.894824830799998\n2014-04-08 01:40:00,20.0707346101\n2014-04-08 01:45:00,20.368011928599998\n2014-04-08 01:50:00,21.075246625\n2014-04-08 01:55:00,18.3614789941\n2014-04-08 02:00:00,21.107495648900002\n2014-04-08 02:05:00,20.2529402755\n2014-04-08 02:10:00,20.6763817794\n2014-04-08 02:15:00,19.3102070594\n2014-04-08 02:20:00,19.6375473473\n2014-04-08 02:25:00,18.9246632786\n2014-04-08 02:30:00,21.9171999897\n2014-04-08 02:35:00,19.98801189\n2014-04-08 02:40:00,21.984307663200003\n2014-04-08 02:45:00,19.959143912200002\n2014-04-08 02:50:00,18.8790050575\n2014-04-08 02:55:00,20.0298095869\n2014-04-08 03:00:00,18.158382287200002\n2014-04-08 03:05:00,21.6190792057\n2014-04-08 03:10:00,21.274201004800002\n2014-04-08 03:15:00,20.9032820828\n2014-04-08 03:20:00,20.439306861800002\n2014-04-08 03:25:00,20.3193369347\n2014-04-08 03:30:00,21.986912856300002\n2014-04-08 03:35:00,19.1119897361\n2014-04-08 03:40:00,21.1187374615\n2014-04-08 03:45:00,20.325619080899997\n2014-04-08 03:50:00,21.903522175\n2014-04-08 03:55:00,21.311212733199998\n2014-04-08 04:00:00,21.994100451999998\n2014-04-08 04:05:00,20.3532999778\n2014-04-08 04:10:00,18.8181758302\n2014-04-08 04:15:00,20.0147481428\n2014-04-08 04:20:00,20.844444536199997\n2014-04-08 04:25:00,21.0974415447\n2014-04-08 04:30:00,18.0020399561\n2014-04-08 04:35:00,20.020108354\n2014-04-08 04:40:00,18.9409383199\n2014-04-08 04:45:00,21.499647333000002\n2014-04-08 04:50:00,18.6116217762\n2014-04-08 04:55:00,20.6658249983\n2014-04-08 05:00:00,19.0642487613\n2014-04-08 05:05:00,19.4261685729\n2014-04-08 05:10:00,21.762237043000003\n2014-04-08 05:15:00,18.9617925016\n2014-04-08 05:20:00,18.380011047300002\n2014-04-08 05:25:00,18.2771396058\n2014-04-08 05:30:00,20.0184604404\n2014-04-08 05:35:00,20.5668459291\n2014-04-08 05:40:00,19.309174574300002\n2014-04-08 05:45:00,20.7610389672\n2014-04-08 05:50:00,18.244134874300002\n2014-04-08 05:55:00,21.4293385797\n2014-04-08 06:00:00,21.266268839000002\n2014-04-08 06:05:00,21.9419850856\n2014-04-08 06:10:00,21.746019923600002\n2014-04-08 06:15:00,19.4247886557\n2014-04-08 06:20:00,19.5971015361\n2014-04-08 06:25:00,20.9838593899\n2014-04-08 06:30:00,18.5363310878\n2014-04-08 06:35:00,19.256058840999998\n2014-04-08 06:40:00,18.4741637479\n2014-04-08 06:45:00,19.8195457963\n2014-04-08 06:50:00,20.2080171195\n2014-04-08 06:55:00,18.8446418799\n2014-04-08 07:00:00,18.1065267477\n2014-04-08 07:05:00,20.877423327\n2014-04-08 07:10:00,18.0800206577\n2014-04-08 07:15:00,21.8936104357\n2014-04-08 07:20:00,18.886429027000002\n2014-04-08 07:25:00,20.6556003685\n2014-04-08 07:30:00,19.739006905\n2014-04-08 07:35:00,18.238695441300003\n2014-04-08 07:40:00,19.8887344265\n2014-04-08 07:45:00,20.0670425372\n2014-04-08 07:50:00,21.4187328324\n2014-04-08 07:55:00,20.9293962786\n2014-04-08 08:00:00,18.317209899\n2014-04-08 08:05:00,18.836650733699997\n2014-04-08 08:10:00,19.2475507369\n2014-04-08 08:15:00,18.4656307459\n2014-04-08 08:20:00,19.8275962837\n2014-04-08 08:25:00,21.9372367635\n2014-04-08 08:30:00,20.058451165\n2014-04-08 08:35:00,20.9675286733\n2014-04-08 08:40:00,20.7317511908\n2014-04-08 08:45:00,21.3996457404\n2014-04-08 08:50:00,18.8628939619\n2014-04-08 08:55:00,21.0153050468\n2014-04-08 09:00:00,73.1864312682\n2014-04-08 09:05:00,63.5325335925\n2014-04-08 09:10:00,65.9165101891\n2014-04-08 09:15:00,74.39338399489999\n2014-04-08 09:20:00,71.8187147053\n2014-04-08 09:25:00,65.0432353225\n2014-04-08 09:30:00,68.8696080672\n2014-04-08 09:35:00,66.6988352708\n2014-04-08 09:40:00,67.863526398\n2014-04-08 09:45:00,66.0302602029\n2014-04-08 09:50:00,64.998901852\n2014-04-08 09:55:00,70.3767773629\n2014-04-08 10:00:00,81.9229689701\n2014-04-08 10:05:00,83.403814545\n2014-04-08 10:10:00,72.25072109279999\n2014-04-08 10:15:00,82.610717727\n2014-04-08 10:20:00,73.7945087959\n2014-04-08 10:25:00,76.4722607714\n2014-04-08 10:30:00,83.83040600439999\n2014-04-08 10:35:00,76.89389588729999\n2014-04-08 10:40:00,72.8984260484\n2014-04-08 10:45:00,72.3211615293\n2014-04-08 10:50:00,77.1807080584\n2014-04-08 10:55:00,81.6766760201\n2014-04-08 11:00:00,87.4275506098\n2014-04-08 11:05:00,84.0909468266\n2014-04-08 11:10:00,85.515998195\n2014-04-08 11:15:00,83.4615258683\n2014-04-08 11:20:00,85.8089998424\n2014-04-08 11:25:00,72.7813725129\n2014-04-08 11:30:00,86.3576321502\n2014-04-08 11:35:00,77.8724434689\n2014-04-08 11:40:00,86.22535260709999\n2014-04-08 11:45:00,72.772455047\n2014-04-08 11:50:00,82.94322399010001\n2014-04-08 11:55:00,83.2683938589\n2014-04-08 12:00:00,87.8450335397\n2014-04-08 12:05:00,84.2005223098\n2014-04-08 12:10:00,78.0274338779\n2014-04-08 12:15:00,80.8188776537\n2014-04-08 12:20:00,77.7713772327\n2014-04-08 12:25:00,75.0461347669\n2014-04-08 12:30:00,75.8848659953\n2014-04-08 12:35:00,75.46150594609999\n2014-04-08 12:40:00,80.6841080283\n2014-04-08 12:45:00,86.3947718683\n2014-04-08 12:50:00,86.49970166620001\n2014-04-08 12:55:00,72.7887689759\n2014-04-08 13:00:00,73.2608036015\n2014-04-08 13:05:00,75.9036836576\n2014-04-08 13:10:00,76.0626918112\n2014-04-08 13:15:00,73.5005824294\n2014-04-08 13:20:00,78.1966417595\n2014-04-08 13:25:00,81.3840694176\n2014-04-08 13:30:00,81.23109506670002\n2014-04-08 13:35:00,80.6755081302\n2014-04-08 13:40:00,77.400170298\n2014-04-08 13:45:00,83.2832981752\n2014-04-08 13:50:00,85.2032893574\n2014-04-08 13:55:00,77.5217785705\n2014-04-08 14:00:00,73.3650440576\n2014-04-08 14:05:00,76.7376004358\n2014-04-08 14:10:00,74.1943369741\n2014-04-08 14:15:00,79.4739247041\n2014-04-08 14:20:00,74.4913866629\n2014-04-08 14:25:00,79.4017046578\n2014-04-08 14:30:00,75.532420547\n2014-04-08 14:35:00,83.81567434189999\n2014-04-08 14:40:00,72.437614681\n2014-04-08 14:45:00,80.8720588161\n2014-04-08 14:50:00,74.7082262317\n2014-04-08 14:55:00,72.01241306979999\n2014-04-08 15:00:00,85.9063766999\n2014-04-08 15:05:00,82.7436502584\n2014-04-08 15:10:00,73.58237875520001\n2014-04-08 15:15:00,82.62436468140001\n2014-04-08 15:20:00,81.7855721748\n2014-04-08 15:25:00,79.57294308510001\n2014-04-08 15:30:00,78.7073739768\n2014-04-08 15:35:00,86.19228875270002\n2014-04-08 15:40:00,75.9216394636\n2014-04-08 15:45:00,78.3722085318\n2014-04-08 15:50:00,77.2651048542\n2014-04-08 15:55:00,84.3384068081\n2014-04-08 16:00:00,86.6632785059\n2014-04-08 16:05:00,85.59634283449999\n2014-04-08 16:10:00,84.76310013930001\n2014-04-08 16:15:00,87.7884705749\n2014-04-08 16:20:00,83.1541531503\n2014-04-08 16:25:00,84.016699347\n2014-04-08 16:30:00,87.72467220360001\n2014-04-08 16:35:00,72.1117141116\n2014-04-08 16:40:00,82.144616305\n2014-04-08 16:45:00,83.82338357\n2014-04-08 16:50:00,86.68506642450001\n2014-04-08 16:55:00,86.1413434753\n2014-04-08 17:00:00,85.4713380787\n2014-04-08 17:05:00,87.13262689209999\n2014-04-08 17:10:00,80.598036057\n2014-04-08 17:15:00,72.1106938388\n2014-04-08 17:20:00,72.17684266319999\n2014-04-08 17:25:00,80.7141938956\n2014-04-08 17:30:00,78.96432549949999\n2014-04-08 17:35:00,79.2198904334\n2014-04-08 17:40:00,78.40644568729999\n2014-04-08 17:45:00,86.683579659\n2014-04-08 17:50:00,77.746695764\n2014-04-08 17:55:00,85.6995981596\n2014-04-08 18:00:00,34.578328041199995\n2014-04-08 18:05:00,31.9968051846\n2014-04-08 18:10:00,31.660397360300003\n2014-04-08 18:15:00,33.6705254022\n2014-04-08 18:20:00,33.3310112493\n2014-04-08 18:25:00,30.9026188129\n2014-04-08 18:30:00,29.456302350300003\n2014-04-08 18:35:00,30.49504950610001\n2014-04-08 18:40:00,29.6385767466\n2014-04-08 18:45:00,30.686280673200002\n2014-04-08 18:50:00,30.4756521684\n2014-04-08 18:55:00,32.8813467997\n2014-04-08 19:00:00,24.436140867\n2014-04-08 19:05:00,23.232130646399998\n2014-04-08 19:10:00,24.311388014499997\n2014-04-08 19:15:00,23.672911219899998\n2014-04-08 19:20:00,23.4208904621\n2014-04-08 19:25:00,22.014996284499997\n2014-04-08 19:30:00,21.6150781871\n2014-04-08 19:35:00,23.9513213148\n2014-04-08 19:40:00,24.2161603551\n2014-04-08 19:45:00,22.184432354600002\n2014-04-08 19:50:00,20.200601571700002\n2014-04-08 19:55:00,23.7105378432\n2014-04-08 20:00:00,19.5996417354\n2014-04-08 20:05:00,18.4725004734\n2014-04-08 20:10:00,21.729232876799998\n2014-04-08 20:15:00,20.5513282708\n2014-04-08 20:20:00,21.2386229621\n2014-04-08 20:25:00,22.1785692413\n2014-04-08 20:30:00,20.6486477605\n2014-04-08 20:35:00,20.4930826754\n2014-04-08 20:40:00,19.622551813599998\n2014-04-08 20:45:00,19.6820737097\n2014-04-08 20:50:00,21.6946360421\n2014-04-08 20:55:00,20.2712235467\n2014-04-08 21:00:00,18.7436444918\n2014-04-08 21:05:00,18.466329963099998\n2014-04-08 21:10:00,19.9871604848\n2014-04-08 21:15:00,19.9551471821\n2014-04-08 21:20:00,20.7127794611\n2014-04-08 21:25:00,19.9797143577\n2014-04-08 21:30:00,18.6630575044\n2014-04-08 21:35:00,20.1273613054\n2014-04-08 21:40:00,21.7309679189\n2014-04-08 21:45:00,18.7272268758\n2014-04-08 21:50:00,20.858661802\n2014-04-08 21:55:00,20.4732391077\n2014-04-08 22:00:00,21.0144974657\n2014-04-08 22:05:00,18.6202593896\n2014-04-08 22:10:00,21.7873171014\n2014-04-08 22:15:00,20.5035302121\n2014-04-08 22:20:00,21.4088172934\n2014-04-08 22:25:00,19.0046540154\n2014-04-08 22:30:00,20.9777708928\n2014-04-08 22:35:00,21.1444019649\n2014-04-08 22:40:00,19.6085472314\n2014-04-08 22:45:00,19.5545681832\n2014-04-08 22:50:00,20.6509909876\n2014-04-08 22:55:00,18.391269403499997\n2014-04-08 23:00:00,20.9465175582\n2014-04-08 23:05:00,18.1750359746\n2014-04-08 23:10:00,18.765963576\n2014-04-08 23:15:00,20.6605410893\n2014-04-08 23:20:00,18.3968261791\n2014-04-08 23:25:00,21.8915707385\n2014-04-08 23:30:00,21.477707764\n2014-04-08 23:35:00,20.5091463278\n2014-04-08 23:40:00,21.280314856700002\n2014-04-08 23:45:00,21.554457853699997\n2014-04-08 23:50:00,19.0415578737\n2014-04-08 23:55:00,21.4017546978\n2014-04-09 00:00:00,18.7791751346\n2014-04-09 00:05:00,19.653369056600003\n2014-04-09 00:10:00,20.233038525\n2014-04-09 00:15:00,20.8555638523\n2014-04-09 00:20:00,18.1205652709\n2014-04-09 00:25:00,19.1620376511\n2014-04-09 00:30:00,20.434076392799998\n2014-04-09 00:35:00,19.4294747166\n2014-04-09 00:40:00,21.1001002225\n2014-04-09 00:45:00,20.6066086446\n2014-04-09 00:50:00,18.9376058149\n2014-04-09 00:55:00,18.5837159184\n2014-04-09 01:00:00,20.5161879743\n2014-04-09 01:05:00,19.8018693108\n2014-04-09 01:10:00,18.675828164400002\n2014-04-09 01:15:00,19.3054968213\n2014-04-09 01:20:00,19.212186993299998\n2014-04-09 01:25:00,18.4325278894\n2014-04-09 01:30:00,20.1876360771\n2014-04-09 01:35:00,21.054594535699998\n2014-04-09 01:40:00,20.3018675554\n2014-04-09 01:45:00,21.3051654597\n2014-04-09 01:50:00,18.510274188900002\n2014-04-09 01:55:00,19.7424474313\n2014-04-09 02:00:00,20.4376604146\n2014-04-09 02:05:00,20.704006243800002\n2014-04-09 02:10:00,20.7831452257\n2014-04-09 02:15:00,20.915861708399998\n2014-04-09 02:20:00,20.6057192488\n2014-04-09 02:25:00,18.3769123558\n2014-04-09 02:30:00,20.781222710399998\n2014-04-09 02:35:00,20.8991306271\n2014-04-09 02:40:00,21.9739197373\n2014-04-09 02:45:00,20.7734497468\n2014-04-09 02:50:00,20.747321582999998\n2014-04-09 02:55:00,20.0592531607\n2014-04-09 03:00:00,21.4716916343\n2014-04-09 03:05:00,21.987339047800003\n2014-04-09 03:10:00,21.1161794808\n2014-04-09 03:15:00,20.4500015114\n2014-04-09 03:20:00,18.3158193077\n2014-04-09 03:25:00,20.9069565269\n2014-04-09 03:30:00,20.8342462743\n2014-04-09 03:35:00,21.1022725912\n2014-04-09 03:40:00,18.4982215536\n2014-04-09 03:45:00,20.6149300005\n2014-04-09 03:50:00,19.1828956198\n2014-04-09 03:55:00,21.0410849736\n2014-04-09 04:00:00,18.961495816099998\n2014-04-09 04:05:00,20.7359147073\n2014-04-09 04:10:00,19.1799717879\n2014-04-09 04:15:00,18.0359771713\n2014-04-09 04:20:00,20.5334316479\n2014-04-09 04:25:00,18.4530763326\n2014-04-09 04:30:00,20.6371658912\n2014-04-09 04:35:00,21.7024377934\n2014-04-09 04:40:00,21.8769837368\n2014-04-09 04:45:00,18.9436923493\n2014-04-09 04:50:00,21.2370129106\n2014-04-09 04:55:00,19.4142131075\n2014-04-09 05:00:00,21.601828291\n2014-04-09 05:05:00,21.1499582745\n2014-04-09 05:10:00,18.2956868666\n2014-04-09 05:15:00,19.6285479755\n2014-04-09 05:20:00,19.349271304000002\n2014-04-09 05:25:00,21.1407240829\n2014-04-09 05:30:00,19.6411428426\n2014-04-09 05:35:00,20.7383535906\n2014-04-09 05:40:00,20.4097410224\n2014-04-09 05:45:00,21.9025548764\n2014-04-09 05:50:00,21.7511398272\n2014-04-09 05:55:00,19.710798059000002\n2014-04-09 06:00:00,20.894312846600002\n2014-04-09 06:05:00,21.317840375899998\n2014-04-09 06:10:00,21.5955430154\n2014-04-09 06:15:00,18.2725370551\n2014-04-09 06:20:00,19.2083151971\n2014-04-09 06:25:00,19.2809201639\n2014-04-09 06:30:00,19.7377838049\n2014-04-09 06:35:00,18.6770590029\n2014-04-09 06:40:00,19.9848235198\n2014-04-09 06:45:00,20.6528573092\n2014-04-09 06:50:00,19.9894556809\n2014-04-09 06:55:00,20.6631723808\n2014-04-09 07:00:00,18.2657665273\n2014-04-09 07:05:00,21.503949326799997\n2014-04-09 07:10:00,21.756276768400003\n2014-04-09 07:15:00,20.471629696500003\n2014-04-09 07:20:00,21.525563994499997\n2014-04-09 07:25:00,18.5257840666\n2014-04-09 07:30:00,21.1897956803\n2014-04-09 07:35:00,18.476592773900002\n2014-04-09 07:40:00,19.632040926\n2014-04-09 07:45:00,19.2952741382\n2014-04-09 07:50:00,20.342367300899998\n2014-04-09 07:55:00,19.206058141\n2014-04-09 08:00:00,20.5492545187\n2014-04-09 08:05:00,19.4695491566\n2014-04-09 08:10:00,21.443161524100002\n2014-04-09 08:15:00,20.5355353609\n2014-04-09 08:20:00,18.8611931893\n2014-04-09 08:25:00,19.344517688099998\n2014-04-09 08:30:00,21.3896835505\n2014-04-09 08:35:00,19.5459189999\n2014-04-09 08:40:00,20.143196262300002\n2014-04-09 08:45:00,20.5957677438\n2014-04-09 08:50:00,19.3912385983\n2014-04-09 08:55:00,19.175914523\n2014-04-09 09:00:00,67.6634666755\n2014-04-09 09:05:00,64.1223812205\n2014-04-09 09:10:00,65.0652639821\n2014-04-09 09:15:00,62.044267382799994\n2014-04-09 09:20:00,65.3339957532\n2014-04-09 09:25:00,65.5615756697\n2014-04-09 09:30:00,74.2809310616\n2014-04-09 09:35:00,69.22031202630001\n2014-04-09 09:40:00,71.9084009857\n2014-04-09 09:45:00,61.8171306378\n2014-04-09 09:50:00,62.6488990331\n2014-04-09 09:55:00,72.2777026677\n2014-04-09 10:00:00,79.517489007\n2014-04-09 10:05:00,72.804041114\n2014-04-09 10:10:00,76.12242469899999\n2014-04-09 10:15:00,78.2001971997\n2014-04-09 10:20:00,82.9328245482\n2014-04-09 10:25:00,70.7775941111\n2014-04-09 10:30:00,79.101129931\n2014-04-09 10:35:00,80.968397503\n2014-04-09 10:40:00,85.0168816348\n2014-04-09 10:45:00,82.36712441510001\n2014-04-09 10:50:00,74.1270479065\n2014-04-09 10:55:00,80.852669089\n2014-04-09 11:00:00,83.70717148189999\n2014-04-09 11:05:00,83.1737133907\n2014-04-09 11:10:00,84.6115712567\n2014-04-09 11:15:00,85.9409215417\n2014-04-09 11:20:00,73.1334286364\n2014-04-09 11:25:00,73.23416439260001\n2014-04-09 11:30:00,84.23394542140001\n2014-04-09 11:35:00,75.5817318666\n2014-04-09 11:40:00,72.4990427747\n2014-04-09 11:45:00,77.94914889430001\n2014-04-09 11:50:00,84.6073224057\n2014-04-09 11:55:00,73.5808901387\n2014-04-09 12:00:00,82.650172183\n2014-04-09 12:05:00,71.9713843638\n2014-04-09 12:10:00,73.6672921964\n2014-04-09 12:15:00,77.5204692057\n2014-04-09 12:20:00,73.2496313326\n2014-04-09 12:25:00,85.431785367\n2014-04-09 12:30:00,85.7221378967\n2014-04-09 12:35:00,83.9882242921\n2014-04-09 12:40:00,75.78861849340001\n2014-04-09 12:45:00,80.27550686\n2014-04-09 12:50:00,74.8570799887\n2014-04-09 12:55:00,76.4086546549\n2014-04-09 13:00:00,80.23682321449999\n2014-04-09 13:05:00,83.74011848229999\n2014-04-09 13:10:00,73.4968266135\n2014-04-09 13:15:00,76.7287278467\n2014-04-09 13:20:00,86.8051033512\n2014-04-09 13:25:00,78.847045251\n2014-04-09 13:30:00,87.00102952299999\n2014-04-09 13:35:00,87.8413216868\n2014-04-09 13:40:00,80.4072548441\n2014-04-09 13:45:00,76.59031806760001\n2014-04-09 13:50:00,84.6321123542\n2014-04-09 13:55:00,74.5310800152\n2014-04-09 14:00:00,76.0291001828\n2014-04-09 14:05:00,84.5540197642\n2014-04-09 14:10:00,78.9345457556\n2014-04-09 14:15:00,75.2209962107\n2014-04-09 14:20:00,82.41405585470001\n2014-04-09 14:25:00,83.720171021\n2014-04-09 14:30:00,73.9975877765\n2014-04-09 14:35:00,76.4280154388\n2014-04-09 14:40:00,75.5368021454\n2014-04-09 14:45:00,78.07392633180001\n2014-04-09 14:50:00,84.2110760035\n2014-04-09 14:55:00,83.41532550859999\n2014-04-09 15:00:00,82.5995896025\n2014-04-09 15:05:00,72.0998765684\n2014-04-09 15:10:00,74.2735799809\n2014-04-09 15:15:00,75.57203528710002\n2014-04-09 15:20:00,76.3505605642\n2014-04-09 15:25:00,74.3421109753\n2014-04-09 15:30:00,78.5642945991\n2014-04-09 15:35:00,73.2021866125\n2014-04-09 15:40:00,83.9995486428\n2014-04-09 15:45:00,84.6027204028\n2014-04-09 15:50:00,81.1874876263\n2014-04-09 15:55:00,73.434573054\n2014-04-09 16:00:00,86.2411651294\n2014-04-09 16:05:00,87.450005355\n2014-04-09 16:10:00,75.2376725085\n2014-04-09 16:15:00,83.2740772245\n2014-04-09 16:20:00,85.4708539859\n2014-04-09 16:25:00,80.6373415367\n2014-04-09 16:30:00,77.1730214199\n2014-04-09 16:35:00,79.6567865\n2014-04-09 16:40:00,80.1961460357\n2014-04-09 16:45:00,78.41004215939999\n2014-04-09 16:50:00,86.8773130934\n2014-04-09 16:55:00,83.901968683\n2014-04-09 17:00:00,75.8607971455\n2014-04-09 17:05:00,81.3688837515\n2014-04-09 17:10:00,83.0189945356\n2014-04-09 17:15:00,74.2424742381\n2014-04-09 17:20:00,77.7347820279\n2014-04-09 17:25:00,86.488739294\n2014-04-09 17:30:00,81.07473847029999\n2014-04-09 17:35:00,75.4719349557\n2014-04-09 17:40:00,73.9645283675\n2014-04-09 17:45:00,80.2915994636\n2014-04-09 17:50:00,80.7629405555\n2014-04-09 17:55:00,77.350601519\n2014-04-09 18:00:00,32.834656277600004\n2014-04-09 18:05:00,29.239576377800002\n2014-04-09 18:10:00,29.728888329\n2014-04-09 18:15:00,32.2961462536\n2014-04-09 18:20:00,29.195614835\n2014-04-09 18:25:00,34.4378094839\n2014-04-09 18:30:00,29.7097310667\n2014-04-09 18:35:00,33.1130808364\n2014-04-09 18:40:00,31.303696016700002\n2014-04-09 18:45:00,31.3586355634\n2014-04-09 18:50:00,33.6952865136\n2014-04-09 18:55:00,31.9965515154\n2014-04-09 19:00:00,23.4109351929\n2014-04-09 19:05:00,22.4232554747\n2014-04-09 19:10:00,22.8162146779\n2014-04-09 19:15:00,23.56800024\n2014-04-09 19:20:00,22.8807419131\n2014-04-09 19:25:00,22.917954432800002\n2014-04-09 19:30:00,23.6957024697\n2014-04-09 19:35:00,24.4119075957\n2014-04-09 19:40:00,21.847687171100002\n2014-04-09 19:45:00,22.745483616599998\n2014-04-09 19:50:00,20.5465026195\n2014-04-09 19:55:00,21.7674401908\n2014-04-09 20:00:00,20.1197533878\n2014-04-09 20:05:00,21.8531317875\n2014-04-09 20:10:00,20.5348550327\n2014-04-09 20:15:00,21.4264476079\n2014-04-09 20:20:00,18.5098540884\n2014-04-09 20:25:00,20.3345617308\n2014-04-09 20:30:00,22.123796890999998\n2014-04-09 20:35:00,19.3507895403\n2014-04-09 20:40:00,18.5611146483\n2014-04-09 20:45:00,20.2072419308\n2014-04-09 20:50:00,21.3173524816\n2014-04-09 20:55:00,20.2934822805\n2014-04-09 21:00:00,19.9351447889\n2014-04-09 21:05:00,20.7784803709\n2014-04-09 21:10:00,19.1088394515\n2014-04-09 21:15:00,21.1083953989\n2014-04-09 21:20:00,18.7017938577\n2014-04-09 21:25:00,19.6770007846\n2014-04-09 21:30:00,20.7230277389\n2014-04-09 21:35:00,21.4157806615\n2014-04-09 21:40:00,21.2677216292\n2014-04-09 21:45:00,20.9869987094\n2014-04-09 21:50:00,19.5296801369\n2014-04-09 21:55:00,18.577965462599998\n2014-04-09 22:00:00,18.8854495049\n2014-04-09 22:05:00,21.4799362096\n2014-04-09 22:10:00,21.4498976225\n2014-04-09 22:15:00,21.827177393099998\n2014-04-09 22:20:00,18.321526395\n2014-04-09 22:25:00,20.166577678099998\n2014-04-09 22:30:00,20.6145031124\n2014-04-09 22:35:00,20.8626384224\n2014-04-09 22:40:00,20.5952053648\n2014-04-09 22:45:00,21.100282393\n2014-04-09 22:50:00,19.4565466665\n2014-04-09 22:55:00,18.7357001012\n2014-04-09 23:00:00,18.8219466068\n2014-04-09 23:05:00,18.0513799557\n2014-04-09 23:10:00,19.4050125337\n2014-04-09 23:15:00,18.370502661099998\n2014-04-09 23:20:00,19.2896576726\n2014-04-09 23:25:00,20.516778772000002\n2014-04-09 23:30:00,21.5820551794\n2014-04-09 23:35:00,21.3625226188\n2014-04-09 23:40:00,19.0143468998\n2014-04-09 23:45:00,18.5398915428\n2014-04-09 23:50:00,18.7758933728\n2014-04-09 23:55:00,21.888148323200003\n2014-04-10 00:00:00,20.197897918699997\n2014-04-10 00:05:00,18.730008892\n2014-04-10 00:10:00,21.3629846187\n2014-04-10 00:15:00,19.5807649773\n2014-04-10 00:20:00,21.5968886079\n2014-04-10 00:25:00,19.0427085073\n2014-04-10 00:30:00,19.5728870352\n2014-04-10 00:35:00,20.0197910512\n2014-04-10 00:40:00,21.570461336399998\n2014-04-10 00:45:00,21.4750297264\n2014-04-10 00:50:00,20.297420281199997\n2014-04-10 00:55:00,18.8871020391\n2014-04-10 01:00:00,19.613427887\n2014-04-10 01:05:00,21.9025322615\n2014-04-10 01:10:00,20.4310928955\n2014-04-10 01:15:00,21.1243910205\n2014-04-10 01:20:00,19.799458781400002\n2014-04-10 01:25:00,20.1280291019\n2014-04-10 01:30:00,19.7158164489\n2014-04-10 01:35:00,20.8116839922\n2014-04-10 01:40:00,21.4058840555\n2014-04-10 01:45:00,20.0294541729\n2014-04-10 01:50:00,19.9234698345\n2014-04-10 01:55:00,19.361145868399998\n2014-04-10 02:00:00,18.7083867772\n2014-04-10 02:05:00,21.7569908915\n2014-04-10 02:10:00,19.2643188747\n2014-04-10 02:15:00,21.2027658543\n2014-04-10 02:20:00,20.8613880851\n2014-04-10 02:25:00,21.1636704011\n2014-04-10 02:30:00,21.7470725335\n2014-04-10 02:35:00,20.4934830409\n2014-04-10 02:40:00,21.591801373499997\n2014-04-10 02:45:00,18.670789291600002\n2014-04-10 02:50:00,20.5068503038\n2014-04-10 02:55:00,21.0891024517\n2014-04-10 03:00:00,19.086564523\n2014-04-10 03:05:00,20.9630152052\n2014-04-10 03:10:00,21.1139073165\n2014-04-10 03:15:00,21.3247518241\n2014-04-10 03:20:00,19.2515316504\n2014-04-10 03:25:00,20.7264263607\n2014-04-10 03:30:00,19.2170131336\n2014-04-10 03:35:00,20.95616155\n2014-04-10 03:40:00,19.8518946606\n2014-04-10 03:45:00,20.390177498099998\n2014-04-10 03:50:00,19.6633599257\n2014-04-10 03:55:00,18.6479317077\n2014-04-10 04:00:00,18.7121181184\n2014-04-10 04:05:00,18.310275629\n2014-04-10 04:10:00,20.472290718900002\n2014-04-10 04:15:00,21.3945535918\n2014-04-10 04:20:00,18.083347305\n2014-04-10 04:25:00,18.2649580084\n2014-04-10 04:30:00,19.829867969200002\n2014-04-10 04:35:00,20.950882944700002\n2014-04-10 04:40:00,18.6308305788\n2014-04-10 04:45:00,19.0866052782\n2014-04-10 04:50:00,18.9280248051\n2014-04-10 04:55:00,19.5962048747\n2014-04-10 05:00:00,18.8999947081\n2014-04-10 05:05:00,19.410394714200002\n2014-04-10 05:10:00,20.9141703946\n2014-04-10 05:15:00,20.4440369938\n2014-04-10 05:20:00,18.324726821600002\n2014-04-10 05:25:00,20.550982665\n2014-04-10 05:30:00,19.908308686199998\n2014-04-10 05:35:00,21.738262298800002\n2014-04-10 05:40:00,19.1572172684\n2014-04-10 05:45:00,20.9046656788\n2014-04-10 05:50:00,20.9234432922\n2014-04-10 05:55:00,18.886003124000002\n2014-04-10 06:00:00,21.612894499899998\n2014-04-10 06:05:00,19.964732801700002\n2014-04-10 06:10:00,20.7155334676\n2014-04-10 06:15:00,18.5834222355\n2014-04-10 06:20:00,19.031215667999998\n2014-04-10 06:25:00,20.344428471700002\n2014-04-10 06:30:00,19.2761090735\n2014-04-10 06:35:00,19.998771674300002\n2014-04-10 06:40:00,19.4960207975\n2014-04-10 06:45:00,20.5622151866\n2014-04-10 06:50:00,19.948581451099997\n2014-04-10 06:55:00,18.0184397439\n2014-04-10 07:00:00,20.5987233518\n2014-04-10 07:05:00,19.6884862282\n2014-04-10 07:10:00,19.366793362\n2014-04-10 07:15:00,18.3765870091\n2014-04-10 07:20:00,18.8814787623\n2014-04-10 07:25:00,18.8950891663\n2014-04-10 07:30:00,21.7414779976\n2014-04-10 07:35:00,19.730051899\n2014-04-10 07:40:00,18.1682633889\n2014-04-10 07:45:00,18.555266729\n2014-04-10 07:50:00,18.3161307029\n2014-04-10 07:55:00,20.3554775608\n2014-04-10 08:00:00,18.7464859663\n2014-04-10 08:05:00,19.9942305611\n2014-04-10 08:10:00,19.4802482515\n2014-04-10 08:15:00,21.2155055086\n2014-04-10 08:20:00,19.2819585491\n2014-04-10 08:25:00,19.8330619296\n2014-04-10 08:30:00,20.8851421944\n2014-04-10 08:35:00,19.7334048277\n2014-04-10 08:40:00,21.1728621441\n2014-04-10 08:45:00,20.6467374249\n2014-04-10 08:50:00,19.6421164558\n2014-04-10 08:55:00,20.0159277027\n2014-04-10 09:00:00,74.3539669995\n2014-04-10 09:05:00,70.1979163525\n2014-04-10 09:10:00,73.5079350732\n2014-04-10 09:15:00,63.63111564720001\n2014-04-10 09:20:00,67.7720117249\n2014-04-10 09:25:00,73.5577987099\n2014-04-10 09:30:00,65.5875240356\n2014-04-10 09:35:00,74.3602330948\n2014-04-10 09:40:00,62.5202538704\n2014-04-10 09:45:00,73.4763279157\n2014-04-10 09:50:00,67.2548848601\n2014-04-10 09:55:00,62.2029206459\n2014-04-10 10:00:00,83.49017511689999\n2014-04-10 10:05:00,73.75011209659999\n2014-04-10 10:10:00,70.1853219477\n2014-04-10 10:15:00,71.9477262784\n2014-04-10 10:20:00,80.0694607943\n2014-04-10 10:25:00,85.0156343114\n2014-04-10 10:30:00,71.5698924063\n2014-04-10 10:35:00,77.0094337069\n2014-04-10 10:40:00,72.6434792707\n2014-04-10 10:45:00,81.4029670093\n2014-04-10 10:50:00,71.6722741243\n2014-04-10 10:55:00,73.5623439364\n2014-04-10 11:00:00,74.6916405095\n2014-04-10 11:05:00,80.355274587\n2014-04-10 11:10:00,85.4551197992\n2014-04-10 11:15:00,79.6963785592\n2014-04-10 11:20:00,72.4943038729\n2014-04-10 11:25:00,80.52813755220001\n2014-04-10 11:30:00,84.2517739732\n2014-04-10 11:35:00,73.6698121619\n2014-04-10 11:40:00,72.7243991529\n2014-04-10 11:45:00,74.5548948943\n2014-04-10 11:50:00,83.4337568782\n2014-04-10 11:55:00,80.9780853922\n2014-04-10 12:00:00,80.55273504600001\n2014-04-10 12:05:00,75.90048830010001\n2014-04-10 12:10:00,77.2230065813\n2014-04-10 12:15:00,87.3492152148\n2014-04-10 12:20:00,75.7589836233\n2014-04-10 12:25:00,86.32261518\n2014-04-10 12:30:00,81.1909578664\n2014-04-10 12:35:00,73.8839761698\n2014-04-10 12:40:00,79.3816256528\n2014-04-10 12:45:00,87.0721673424\n2014-04-10 12:50:00,78.60261311069999\n2014-04-10 12:55:00,85.7112080146\n2014-04-10 13:00:00,76.08459442819999\n2014-04-10 13:05:00,81.11528208770001\n2014-04-10 13:10:00,85.4811125393\n2014-04-10 13:15:00,86.7101996151\n2014-04-10 13:20:00,79.7540283127\n2014-04-10 13:25:00,82.215273232\n2014-04-10 13:30:00,72.03039064880002\n2014-04-10 13:35:00,76.03332054270001\n2014-04-10 13:40:00,76.4410434055\n2014-04-10 13:45:00,73.4782491733\n2014-04-10 13:50:00,76.4567661849\n2014-04-10 13:55:00,77.1194394203\n2014-04-10 14:00:00,87.4960566208\n2014-04-10 14:05:00,82.6936686023\n2014-04-10 14:10:00,78.8122980988\n2014-04-10 14:15:00,87.8046565453\n2014-04-10 14:20:00,74.4481434413\n2014-04-10 14:25:00,79.6129974956\n2014-04-10 14:30:00,82.349042369\n2014-04-10 14:35:00,72.8857914658\n2014-04-10 14:40:00,83.4679750742\n2014-04-10 14:45:00,73.5943449486\n2014-04-10 14:50:00,74.24095320079998\n2014-04-10 14:55:00,74.5514535578\n2014-04-10 15:00:00,86.861403349\n2014-04-10 15:05:00,82.93097257720001\n2014-04-10 15:10:00,82.486048144\n2014-04-10 15:15:00,80.8871194196\n2014-04-10 15:20:00,76.6841598041\n2014-04-10 15:25:00,81.9334487049\n2014-04-10 15:30:00,78.5616413192\n2014-04-10 15:35:00,74.32594486560001\n2014-04-10 15:40:00,83.0327595231\n2014-04-10 15:45:00,74.0726035831\n2014-04-10 15:50:00,75.0499768096\n2014-04-10 15:55:00,85.0823721909\n2014-04-10 16:00:00,82.5617150192\n2014-04-10 16:05:00,82.0957008434\n2014-04-10 16:10:00,78.69109346229999\n2014-04-10 16:15:00,78.3403378781\n2014-04-10 16:20:00,83.0440423021\n2014-04-10 16:25:00,83.8399276448\n2014-04-10 16:30:00,80.1632573241\n2014-04-10 16:35:00,87.5081398936\n2014-04-10 16:40:00,87.29102534360001\n2014-04-10 16:45:00,78.5987209304\n2014-04-10 16:50:00,85.129792619\n2014-04-10 16:55:00,80.6921305364\n2014-04-10 17:00:00,80.1880634087\n2014-04-10 17:05:00,72.8793969964\n2014-04-10 17:10:00,81.183564193\n2014-04-10 17:15:00,86.40921370790001\n2014-04-10 17:20:00,84.482109146\n2014-04-10 17:25:00,84.5810418361\n2014-04-10 17:30:00,74.5588359866\n2014-04-10 17:35:00,77.7351613038\n2014-04-10 17:40:00,75.73124958560001\n2014-04-10 17:45:00,77.05461493029999\n2014-04-10 17:50:00,81.2725982872\n2014-04-10 17:55:00,77.8365111247\n2014-04-10 18:00:00,32.3884598132\n2014-04-10 18:05:00,31.6064019205\n2014-04-10 18:10:00,30.6343336923\n2014-04-10 18:15:00,29.4105763321\n2014-04-10 18:20:00,34.507759501500004\n2014-04-10 18:25:00,28.872783998899997\n2014-04-10 18:30:00,28.8105703925\n2014-04-10 18:35:00,34.0914989889\n2014-04-10 18:40:00,35.1795832636\n2014-04-10 18:45:00,33.4534516743\n2014-04-10 18:50:00,28.8977470152\n2014-04-10 18:55:00,30.2508116425\n2014-04-10 19:00:00,24.5137643524\n2014-04-10 19:05:00,23.782545745100002\n2014-04-10 19:10:00,22.699262055\n2014-04-10 19:15:00,21.2211348142\n2014-04-10 19:20:00,20.2243774131\n2014-04-10 19:25:00,20.2534582864\n2014-04-10 19:30:00,22.9016730123\n2014-04-10 19:35:00,20.257805694800002\n2014-04-10 19:40:00,24.6114616857\n2014-04-10 19:45:00,20.9815584231\n2014-04-10 19:50:00,23.3439677006\n2014-04-10 19:55:00,20.854666407899998\n2014-04-10 20:00:00,20.6442224051\n2014-04-10 20:05:00,18.7621836124\n2014-04-10 20:10:00,21.572724168\n2014-04-10 20:15:00,20.8278365541\n2014-04-10 20:20:00,18.7849385508\n2014-04-10 20:25:00,21.9078087681\n2014-04-10 20:30:00,20.6725879981\n2014-04-10 20:35:00,22.2068418353\n2014-04-10 20:40:00,22.1864890723\n2014-04-10 20:45:00,22.202399639299998\n2014-04-10 20:50:00,18.750607955\n2014-04-10 20:55:00,18.927442765\n2014-04-10 21:00:00,22.0561871365\n2014-04-10 21:05:00,20.0461651723\n2014-04-10 21:10:00,19.0438298746\n2014-04-10 21:15:00,21.1798354604\n2014-04-10 21:20:00,19.1486151143\n2014-04-10 21:25:00,21.0092252419\n2014-04-10 21:30:00,21.451618945899998\n2014-04-10 21:35:00,21.238511314100002\n2014-04-10 21:40:00,19.1878529038\n2014-04-10 21:45:00,19.7005853248\n2014-04-10 21:50:00,19.7473383839\n2014-04-10 21:55:00,20.060924063399998\n2014-04-10 22:00:00,18.6874141087\n2014-04-10 22:05:00,19.828897676900002\n2014-04-10 22:10:00,20.0623733589\n2014-04-10 22:15:00,20.146157739\n2014-04-10 22:20:00,21.3000301271\n2014-04-10 22:25:00,20.088604548499998\n2014-04-10 22:30:00,18.941301891\n2014-04-10 22:35:00,20.6723413572\n2014-04-10 22:40:00,21.2095982522\n2014-04-10 22:45:00,19.295993043499998\n2014-04-10 22:50:00,20.6009816807\n2014-04-10 22:55:00,18.605596216600002\n2014-04-10 23:00:00,19.3714238158\n2014-04-10 23:05:00,21.64105\n2014-04-10 23:10:00,21.6493885352\n2014-04-10 23:15:00,20.3051961623\n2014-04-10 23:20:00,20.8134012473\n2014-04-10 23:25:00,21.4201735426\n2014-04-10 23:30:00,21.838404908\n2014-04-10 23:35:00,19.963377992\n2014-04-10 23:40:00,20.2501902347\n2014-04-10 23:45:00,19.6663414774\n2014-04-10 23:50:00,18.2914390286\n2014-04-10 23:55:00,19.6949946009\n2014-04-11 00:00:00,21.1625093575\n2014-04-11 00:05:00,21.219541992\n2014-04-11 00:10:00,21.5695084584\n2014-04-11 00:15:00,18.2058668207\n2014-04-11 00:20:00,20.1086183583\n2014-04-11 00:25:00,18.4296979517\n2014-04-11 00:30:00,18.8029687327\n2014-04-11 00:35:00,21.6008660095\n2014-04-11 00:40:00,19.9871650337\n2014-04-11 00:45:00,21.034179683599998\n2014-04-11 00:50:00,18.2575364237\n2014-04-11 00:55:00,19.6673060157\n2014-04-11 01:00:00,20.6969611227\n2014-04-11 01:05:00,18.5336259251\n2014-04-11 01:10:00,19.303271516400002\n2014-04-11 01:15:00,18.2581912201\n2014-04-11 01:20:00,20.605359763499997\n2014-04-11 01:25:00,21.8835650362\n2014-04-11 01:30:00,21.3081819646\n2014-04-11 01:35:00,21.898492467199997\n2014-04-11 01:40:00,21.3824191804\n2014-04-11 01:45:00,21.4207832248\n2014-04-11 01:50:00,20.308708781500002\n2014-04-11 01:55:00,20.0730092457\n2014-04-11 02:00:00,19.6250170657\n2014-04-11 02:05:00,21.2723795802\n2014-04-11 02:10:00,18.728270449100002\n2014-04-11 02:15:00,18.2248996633\n2014-04-11 02:20:00,21.791575290700003\n2014-04-11 02:25:00,18.0151127408\n2014-04-11 02:30:00,21.9073172875\n2014-04-11 02:35:00,20.9154134795\n2014-04-11 02:40:00,19.3139956788\n2014-04-11 02:45:00,20.7912793723\n2014-04-11 02:50:00,21.2715006287\n2014-04-11 02:55:00,18.9814482239\n2014-04-11 03:00:00,21.0835827331\n2014-04-11 03:05:00,21.2174785\n2014-04-11 03:10:00,18.9974185205\n2014-04-11 03:15:00,18.1677054175\n2014-04-11 03:20:00,18.816489138199998\n2014-04-11 03:25:00,18.8025856356\n2014-04-11 03:30:00,18.2609618167\n2014-04-11 03:35:00,20.9040295386\n2014-04-11 03:40:00,19.5198996978\n2014-04-11 03:45:00,21.5375446698\n2014-04-11 03:50:00,19.0086844227\n2014-04-11 03:55:00,19.8129286604\n2014-04-11 04:00:00,20.556069715699998\n2014-04-11 04:05:00,21.5098597987\n2014-04-11 04:10:00,20.098484406500003\n2014-04-11 04:15:00,19.494098511199997\n2014-04-11 04:20:00,21.4680603139\n2014-04-11 04:25:00,19.2409856988\n2014-04-11 04:30:00,18.3176947985\n2014-04-11 04:35:00,19.78016843\n2014-04-11 04:40:00,21.140373225999998\n2014-04-11 04:45:00,18.123123327000002\n2014-04-11 04:50:00,20.34352898\n2014-04-11 04:55:00,20.3778561941\n2014-04-11 05:00:00,21.7141670537\n2014-04-11 05:05:00,19.1458592686\n2014-04-11 05:10:00,19.1153464528\n2014-04-11 05:15:00,19.7619346054\n2014-04-11 05:20:00,19.4276596059\n2014-04-11 05:25:00,20.945383450799998\n2014-04-11 05:30:00,20.5670083085\n2014-04-11 05:35:00,21.0356841516\n2014-04-11 05:40:00,21.2801671648\n2014-04-11 05:45:00,21.691924530900003\n2014-04-11 05:50:00,19.7237469271\n2014-04-11 05:55:00,21.938789557899998\n2014-04-11 06:00:00,18.862643253599998\n2014-04-11 06:05:00,20.8574606478\n2014-04-11 06:10:00,20.1360372692\n2014-04-11 06:15:00,21.267602378699998\n2014-04-11 06:20:00,19.9070820824\n2014-04-11 06:25:00,21.1357545414\n2014-04-11 06:30:00,21.720674858600002\n2014-04-11 06:35:00,20.9291770646\n2014-04-11 06:40:00,21.1043771449\n2014-04-11 06:45:00,18.2687017251\n2014-04-11 06:50:00,18.819830648900002\n2014-04-11 06:55:00,21.897214962\n2014-04-11 07:00:00,20.7727480151\n2014-04-11 07:05:00,20.2457960692\n2014-04-11 07:10:00,19.4679054936\n2014-04-11 07:15:00,18.1775560048\n2014-04-11 07:20:00,19.4765436319\n2014-04-11 07:25:00,19.9956514932\n2014-04-11 07:30:00,18.8458380375\n2014-04-11 07:35:00,18.6925471651\n2014-04-11 07:40:00,20.0336662054\n2014-04-11 07:45:00,20.3436169425\n2014-04-11 07:50:00,18.9596716754\n2014-04-11 07:55:00,20.3495578978\n2014-04-11 08:00:00,21.6013598555\n2014-04-11 08:05:00,19.8926930321\n2014-04-11 08:10:00,21.4295606783\n2014-04-11 08:15:00,21.7090857781\n2014-04-11 08:20:00,18.3695761157\n2014-04-11 08:25:00,18.383246318599998\n2014-04-11 08:30:00,19.9041767316\n2014-04-11 08:35:00,20.3524097773\n2014-04-11 08:40:00,19.7035338579\n2014-04-11 08:45:00,19.305803081700002\n2014-04-11 08:50:00,20.5639764645\n2014-04-11 08:55:00,18.0083260494\n2014-04-11 09:00:00,39.370127622199995\n2014-04-11 09:05:00,34.070969435\n2014-04-11 09:10:00,39.003111133800004\n2014-04-11 09:15:00,33.1849061606\n2014-04-11 09:20:00,34.1142277107\n2014-04-11 09:25:00,34.0910906478\n2014-04-11 09:30:00,39.5723009102\n2014-04-11 09:35:00,32.4331239292\n2014-04-11 09:40:00,37.005395107\n2014-04-11 09:45:00,38.661743383600005\n2014-04-11 09:50:00,37.240370309\n2014-04-11 09:55:00,35.011683491199996\n2014-04-11 10:00:00,42.7931454036\n2014-04-11 10:05:00,42.285202716\n2014-04-11 10:10:00,38.6822065748\n2014-04-11 10:15:00,39.7748953821\n2014-04-11 10:20:00,42.8653504324\n2014-04-11 10:25:00,42.9832732375\n2014-04-11 10:30:00,38.8066144816\n2014-04-11 10:35:00,41.9232242206\n2014-04-11 10:40:00,37.6475249793\n2014-04-11 10:45:00,38.1950129238\n2014-04-11 10:50:00,36.5722035626\n2014-04-11 10:55:00,36.9200072074\n2014-04-11 11:00:00,41.0899664724\n2014-04-11 11:05:00,39.9259079323\n2014-04-11 11:10:00,37.6976586655\n2014-04-11 11:15:00,39.0663838232\n2014-04-11 11:20:00,38.8295258082\n2014-04-11 11:25:00,43.72328610970001\n2014-04-11 11:30:00,42.6572125909\n2014-04-11 11:35:00,38.9473157444\n2014-04-11 11:40:00,43.138087300600006\n2014-04-11 11:45:00,38.5861188005\n2014-04-11 11:50:00,41.1778392535\n2014-04-11 11:55:00,43.558267173599994\n2014-04-11 12:00:00,39.090933127199996\n2014-04-11 12:05:00,41.4059284571\n2014-04-11 12:10:00,38.3366965761\n2014-04-11 12:15:00,38.099994126\n2014-04-11 12:20:00,40.5607787288\n2014-04-11 12:25:00,43.7990494908\n2014-04-11 12:30:00,39.5933707331\n2014-04-11 12:35:00,43.4662948859\n2014-04-11 12:40:00,43.2802562354\n2014-04-11 12:45:00,37.999676818000005\n2014-04-11 12:50:00,39.1831836125\n2014-04-11 12:55:00,41.1135026921\n2014-04-11 13:00:00,40.1379439766\n2014-04-11 13:05:00,36.761785411999995\n2014-04-11 13:10:00,43.9425523075\n2014-04-11 13:15:00,42.014508612600004\n2014-04-11 13:20:00,39.495232057399996\n2014-04-11 13:25:00,40.9387971416\n2014-04-11 13:30:00,36.6947104449\n2014-04-11 13:35:00,39.9560192434\n2014-04-11 13:40:00,43.439707861\n2014-04-11 13:45:00,43.1659000152\n2014-04-11 13:50:00,38.6928549164\n2014-04-11 13:55:00,40.2445027597\n2014-04-11 14:00:00,41.5777376625\n2014-04-11 14:05:00,38.7188350929\n2014-04-11 14:10:00,36.5178651357\n2014-04-11 14:15:00,40.0422518607\n2014-04-11 14:20:00,40.8117798678\n2014-04-11 14:25:00,36.0455793055\n2014-04-11 14:30:00,36.763426521\n2014-04-11 14:35:00,37.6571200823\n2014-04-11 14:40:00,38.7831771945\n2014-04-11 14:45:00,40.327119273499996\n2014-04-11 14:50:00,38.3495161263\n2014-04-11 14:55:00,38.2082478122\n2014-04-11 15:00:00,42.95451983979999\n2014-04-11 15:05:00,37.1601672998\n2014-04-11 15:10:00,39.9634252978\n2014-04-11 15:15:00,43.62231855090001\n2014-04-11 15:20:00,40.9998435923\n2014-04-11 15:25:00,41.737376718200004\n2014-04-11 15:30:00,39.4496434518\n2014-04-11 15:35:00,36.1592259164\n2014-04-11 15:40:00,41.1687794651\n2014-04-11 15:45:00,41.0551314969\n2014-04-11 15:50:00,36.883185037800004\n2014-04-11 15:55:00,39.6970236464\n2014-04-11 16:00:00,43.32257610439999\n2014-04-11 16:05:00,37.6406304757\n2014-04-11 16:10:00,39.6887392354\n2014-04-11 16:15:00,39.6887746799\n2014-04-11 16:20:00,42.486037363\n2014-04-11 16:25:00,42.596552439\n2014-04-11 16:30:00,42.0741015024\n2014-04-11 16:35:00,38.923583451300004\n2014-04-11 16:40:00,36.5762485825\n2014-04-11 16:45:00,38.7958141591\n2014-04-11 16:50:00,41.4382765691\n2014-04-11 16:55:00,41.6219193198\n2014-04-11 17:00:00,43.719990483500005\n2014-04-11 17:05:00,39.6291197065\n2014-04-11 17:10:00,41.0594741523\n2014-04-11 17:15:00,40.3135166455\n2014-04-11 17:20:00,37.2049389564\n2014-04-11 17:25:00,39.6896096165\n2014-04-11 17:30:00,40.3586709057\n2014-04-11 17:35:00,43.605985685200004\n2014-04-11 17:40:00,38.9323024686\n2014-04-11 17:45:00,43.8407816016\n2014-04-11 17:50:00,40.3383902656\n2014-04-11 17:55:00,37.9397442338\n2014-04-11 18:00:00,22.519987135999997\n2014-04-11 18:05:00,22.280133701599997\n2014-04-11 18:10:00,23.77407575\n2014-04-11 18:15:00,21.7052450108\n2014-04-11 18:20:00,23.7362153344\n2014-04-11 18:25:00,26.3443402743\n2014-04-11 18:30:00,24.8165105018\n2014-04-11 18:35:00,25.246971227399996\n2014-04-11 18:40:00,22.1712239835\n2014-04-11 18:45:00,23.870882098200003\n2014-04-11 18:50:00,22.9738689245\n2014-04-11 18:55:00,25.891665924899996\n2014-04-11 19:00:00,19.4741763001\n2014-04-11 19:05:00,20.6283302347\n2014-04-11 19:10:00,21.1662780915\n2014-04-11 19:15:00,20.8584105302\n2014-04-11 19:20:00,22.1738126397\n2014-04-11 19:25:00,19.6828448051\n2014-04-11 19:30:00,20.2899466198\n2014-04-11 19:35:00,22.0150702402\n2014-04-11 19:40:00,20.9167766609\n2014-04-11 19:45:00,20.3928079227\n2014-04-11 19:50:00,18.842480490299998\n2014-04-11 19:55:00,21.8540829335\n2014-04-11 20:00:00,22.0638380487\n2014-04-11 20:05:00,20.6449971384\n2014-04-11 20:10:00,21.5975741141\n2014-04-11 20:15:00,20.2280429144\n2014-04-11 20:20:00,19.0781375751\n2014-04-11 20:25:00,18.2022304903\n2014-04-11 20:30:00,20.7785017305\n2014-04-11 20:35:00,20.1322147943\n2014-04-11 20:40:00,21.2974196425\n2014-04-11 20:45:00,20.944959422\n2014-04-11 20:50:00,22.1274238587\n2014-04-11 20:55:00,20.2015802542\n2014-04-11 21:00:00,19.740233061199998\n2014-04-11 21:05:00,19.177593876099998\n2014-04-11 21:10:00,19.9392970631\n2014-04-11 21:15:00,21.5258722723\n2014-04-11 21:20:00,18.1988305025\n2014-04-11 21:25:00,21.9466587315\n2014-04-11 21:30:00,22.0083859253\n2014-04-11 21:35:00,20.423911554500002\n2014-04-11 21:40:00,19.357098681900002\n2014-04-11 21:45:00,18.922423371199997\n2014-04-11 21:50:00,19.1365311056\n2014-04-11 21:55:00,18.2295423658\n2014-04-11 22:00:00,19.906811972699998\n2014-04-11 22:05:00,18.2351304555\n2014-04-11 22:10:00,20.8805765027\n2014-04-11 22:15:00,19.4939538886\n2014-04-11 22:20:00,18.8034741108\n2014-04-11 22:25:00,20.1858716406\n2014-04-11 22:30:00,21.9020436373\n2014-04-11 22:35:00,20.7871739604\n2014-04-11 22:40:00,19.973376833099998\n2014-04-11 22:45:00,21.114411643900002\n2014-04-11 22:50:00,20.956609854\n2014-04-11 22:55:00,21.5738432621\n2014-04-11 23:00:00,18.819880185\n2014-04-11 23:05:00,21.436882177\n2014-04-11 23:10:00,19.2053334102\n2014-04-11 23:15:00,21.7653886063\n2014-04-11 23:20:00,19.1254845478\n2014-04-11 23:25:00,21.708783445199998\n2014-04-11 23:30:00,21.8565615876\n2014-04-11 23:35:00,18.583154675\n2014-04-11 23:40:00,21.8994010043\n2014-04-11 23:45:00,18.3440658182\n2014-04-11 23:50:00,18.8754790992\n2014-04-11 23:55:00,19.7779408301\n2014-04-12 00:00:00,21.9743894628\n2014-04-12 00:05:00,19.9542522047\n2014-04-12 00:10:00,20.2016377727\n2014-04-12 00:15:00,20.7776997981\n2014-04-12 00:20:00,21.8731742331\n2014-04-12 00:25:00,21.133405600499998\n2014-04-12 00:30:00,18.8966160177\n2014-04-12 00:35:00,19.2119637227\n2014-04-12 00:40:00,18.3905129584\n2014-04-12 00:45:00,20.577809456700002\n2014-04-12 00:50:00,18.7229612262\n2014-04-12 00:55:00,19.0296195539\n2014-04-12 01:00:00,21.5524546207\n2014-04-12 01:05:00,19.307022701300003\n2014-04-12 01:10:00,20.266586873399998\n2014-04-12 01:15:00,19.5902640352\n2014-04-12 01:20:00,18.2961251496\n2014-04-12 01:25:00,19.4514553196\n2014-04-12 01:30:00,19.632272812100002\n2014-04-12 01:35:00,21.5828044076\n2014-04-12 01:40:00,19.297802614600002\n2014-04-12 01:45:00,19.516964479000002\n2014-04-12 01:50:00,21.1315870747\n2014-04-12 01:55:00,21.0358266048\n2014-04-12 02:00:00,21.193141106600002\n2014-04-12 02:05:00,21.815082960300003\n2014-04-12 02:10:00,21.1822299936\n2014-04-12 02:15:00,19.6304328129\n2014-04-12 02:20:00,21.2860340676\n2014-04-12 02:25:00,20.0346985284\n2014-04-12 02:30:00,19.1108561301\n2014-04-12 02:35:00,19.2116682725\n2014-04-12 02:40:00,18.8953695543\n2014-04-12 02:45:00,18.5799718313\n2014-04-12 02:50:00,18.7379616474\n2014-04-12 02:55:00,18.2527121998\n2014-04-12 03:00:00,21.5538034597\n2014-04-12 03:05:00,21.724031238600002\n2014-04-12 03:10:00,20.34708157\n2014-04-12 03:15:00,21.361958226400002\n2014-04-12 03:20:00,18.7342844106\n2014-04-12 03:25:00,21.6066953009\n2014-04-12 03:30:00,20.0254462385\n2014-04-12 03:35:00,18.268659970399998\n2014-04-12 03:40:00,18.565250977999998\n2014-04-12 03:45:00,19.2359058431\n2014-04-12 03:50:00,18.1742303214\n2014-04-12 03:55:00,19.2371735121\n2014-04-12 04:00:00,18.2397217325\n2014-04-12 04:05:00,18.944110420799998\n2014-04-12 04:10:00,19.062679023399998\n2014-04-12 04:15:00,21.9774759055\n2014-04-12 04:20:00,18.9421866951\n2014-04-12 04:25:00,18.9567457958\n2014-04-12 04:30:00,20.7471558734\n2014-04-12 04:35:00,21.4374299141\n2014-04-12 04:40:00,19.5482216504\n2014-04-12 04:45:00,21.5024720798\n2014-04-12 04:50:00,19.360568083\n2014-04-12 04:55:00,18.7880635185\n2014-04-12 05:00:00,19.3185552973\n2014-04-12 05:05:00,20.437425495699998\n2014-04-12 05:10:00,19.4685726372\n2014-04-12 05:15:00,20.691575216\n2014-04-12 05:20:00,18.9477435177\n2014-04-12 05:25:00,20.803971576\n2014-04-12 05:30:00,19.389753453\n2014-04-12 05:35:00,19.8234734864\n2014-04-12 05:40:00,20.2309805618\n2014-04-12 05:45:00,20.7449000127\n2014-04-12 05:50:00,18.9548547674\n2014-04-12 05:55:00,21.3437821496\n2014-04-12 06:00:00,20.887370999\n2014-04-12 06:05:00,18.936391676099998\n2014-04-12 06:10:00,21.8998982504\n2014-04-12 06:15:00,20.6591879641\n2014-04-12 06:20:00,19.8097075459\n2014-04-12 06:25:00,18.6301093022\n2014-04-12 06:30:00,20.1328840092\n2014-04-12 06:35:00,18.6591035473\n2014-04-12 06:40:00,19.7179667148\n2014-04-12 06:45:00,19.634850091\n2014-04-12 06:50:00,20.8797585774\n2014-04-12 06:55:00,18.7695327249\n2014-04-12 07:00:00,21.2874854195\n2014-04-12 07:05:00,19.3045293081\n2014-04-12 07:10:00,19.7759545079\n2014-04-12 07:15:00,21.0893639022\n2014-04-12 07:20:00,20.5015695989\n2014-04-12 07:25:00,19.232101407200002\n2014-04-12 07:30:00,19.5448116982\n2014-04-12 07:35:00,19.223147256\n2014-04-12 07:40:00,20.379080669100002\n2014-04-12 07:45:00,19.3304981328\n2014-04-12 07:50:00,20.902790779100002\n2014-04-12 07:55:00,20.3191486343\n2014-04-12 08:00:00,18.582826447000002\n2014-04-12 08:05:00,19.2410744747\n2014-04-12 08:10:00,18.8857897676\n2014-04-12 08:15:00,19.5612528502\n2014-04-12 08:20:00,20.063936344800002\n2014-04-12 08:25:00,20.027051429100002\n2014-04-12 08:30:00,21.0180947063\n2014-04-12 08:35:00,18.7566874544\n2014-04-12 08:40:00,21.785891317199997\n2014-04-12 08:45:00,19.3713804275\n2014-04-12 08:50:00,19.2009953877\n2014-04-12 08:55:00,20.7407143127\n2014-04-12 09:00:00,72.1550261501\n2014-04-12 09:05:00,66.3472160015\n2014-04-12 09:10:00,71.3571188586\n2014-04-12 09:15:00,73.2188090035\n2014-04-12 09:20:00,71.6285298468\n2014-04-12 09:25:00,61.6650722038\n2014-04-12 09:30:00,72.4522171946\n2014-04-12 09:35:00,71.732941035\n2014-04-12 09:40:00,70.3023472389\n2014-04-12 09:45:00,71.5363048996\n2014-04-12 09:50:00,74.5201853833\n2014-04-12 09:55:00,67.06313527430001\n2014-04-12 10:00:00,70.88330460649999\n2014-04-12 10:05:00,76.9930123286\n2014-04-12 10:10:00,70.5606503317\n2014-04-12 10:15:00,74.4067663335\n2014-04-12 10:20:00,78.9483743687\n2014-04-12 10:25:00,74.6453472982\n2014-04-12 10:30:00,80.4773342165\n2014-04-12 10:35:00,82.5972278057\n2014-04-12 10:40:00,76.3652160624\n2014-04-12 10:45:00,83.8101410041\n2014-04-12 10:50:00,71.0791002146\n2014-04-12 10:55:00,82.87855630840001\n2014-04-12 11:00:00,84.7456273051\n2014-04-12 11:05:00,76.68899092720001\n2014-04-12 11:10:00,76.31876633600001\n2014-04-12 11:15:00,76.4202305803\n2014-04-12 11:20:00,84.4724056011\n2014-04-12 11:25:00,84.794617067\n2014-04-12 11:30:00,76.8119059852\n2014-04-12 11:35:00,80.9925568858\n2014-04-12 11:40:00,73.777594081\n2014-04-12 11:45:00,79.0234570536\n2014-04-12 11:50:00,87.4528015\n2014-04-12 11:55:00,74.0941778051\n2014-04-12 12:00:00,87.0564090367\n2014-04-12 12:05:00,85.0858498608\n2014-04-12 12:10:00,87.45036789379999\n2014-04-12 12:15:00,74.7834122576\n2014-04-12 12:20:00,75.3257962921\n2014-04-12 12:25:00,72.1831510579\n2014-04-12 12:30:00,83.49491473180001\n2014-04-12 12:35:00,82.20674847689999\n2014-04-12 12:40:00,74.7592281568\n2014-04-12 12:45:00,84.5567294653\n2014-04-12 12:50:00,76.69498354439999\n2014-04-12 12:55:00,74.0709371944\n2014-04-12 13:00:00,78.7420999997\n2014-04-12 13:05:00,73.43788825060001\n2014-04-12 13:10:00,76.19360764470001\n2014-04-12 13:15:00,77.92262781470001\n2014-04-12 13:20:00,85.6092756338\n2014-04-12 13:25:00,84.6604564735\n2014-04-12 13:30:00,79.0650883956\n2014-04-12 13:35:00,83.5731385558\n2014-04-12 13:40:00,81.07893056430001\n2014-04-12 13:45:00,77.4348808485\n2014-04-12 13:50:00,83.5939221384\n2014-04-12 13:55:00,82.91608183470001\n2014-04-12 14:00:00,81.90157961060001\n2014-04-12 14:05:00,81.88335774689999\n2014-04-12 14:10:00,82.9237313471\n2014-04-12 14:15:00,78.14897687130002\n2014-04-12 14:20:00,85.9010895909\n2014-04-12 14:25:00,74.59334487550001\n2014-04-12 14:30:00,86.13803258780001\n2014-04-12 14:35:00,77.4727906161\n2014-04-12 14:40:00,73.9969538255\n2014-04-12 14:45:00,81.59652162180001\n2014-04-12 14:50:00,78.0120419474\n2014-04-12 14:55:00,85.0439133299\n2014-04-12 15:00:00,78.8918101278\n2014-04-12 15:05:00,82.6962065178\n2014-04-12 15:10:00,76.9313892837\n2014-04-12 15:15:00,75.35051462850001\n2014-04-12 15:20:00,78.2080336909\n2014-04-12 15:25:00,81.70814094800001\n2014-04-12 15:30:00,82.5103557204\n2014-04-12 15:35:00,81.2505266322\n2014-04-12 15:40:00,87.8080485326\n2014-04-12 15:45:00,83.0566456325\n2014-04-12 15:50:00,86.9034797601\n2014-04-12 15:55:00,73.8862218038\n2014-04-12 16:00:00,72.9818267516\n2014-04-12 16:05:00,76.9757674384\n2014-04-12 16:10:00,74.185280578\n2014-04-12 16:15:00,80.413742057\n2014-04-12 16:20:00,80.3035458733\n2014-04-12 16:25:00,81.2005987577\n2014-04-12 16:30:00,83.9234849599\n2014-04-12 16:35:00,87.5411071241\n2014-04-12 16:40:00,86.05197384290001\n2014-04-12 16:45:00,73.893733957\n2014-04-12 16:50:00,77.4160703812\n2014-04-12 16:55:00,76.09302230189999\n2014-04-12 17:00:00,74.8290489901\n2014-04-12 17:05:00,80.7155670317\n2014-04-12 17:10:00,80.8521993853\n2014-04-12 17:15:00,75.635888202\n2014-04-12 17:20:00,83.390323983\n2014-04-12 17:25:00,83.72659663569999\n2014-04-12 17:30:00,72.3356521404\n2014-04-12 17:35:00,78.33209318\n2014-04-12 17:40:00,86.24221714219999\n2014-04-12 17:45:00,80.32506688710002\n2014-04-12 17:50:00,77.5620150392\n2014-04-12 17:55:00,76.0587892189\n2014-04-12 18:00:00,30.3574630988\n2014-04-12 18:05:00,29.438509764499997\n2014-04-12 18:10:00,34.030242548400004\n2014-04-12 18:15:00,29.3546017584\n2014-04-12 18:20:00,30.6706806127\n2014-04-12 18:25:00,29.09231914110001\n2014-04-12 18:30:00,33.8008675565\n2014-04-12 18:35:00,29.051409988400003\n2014-04-12 18:40:00,30.7731211563\n2014-04-12 18:45:00,32.4690969345\n2014-04-12 18:50:00,31.421186673\n2014-04-12 18:55:00,30.6065289539\n2014-04-12 19:00:00,21.3928458709\n2014-04-12 19:05:00,23.7340992689\n2014-04-12 19:10:00,24.5234205207\n2014-04-12 19:15:00,21.7192228042\n2014-04-12 19:20:00,20.3353707854\n2014-04-12 19:25:00,20.3238135701\n2014-04-12 19:30:00,23.561274807600004\n2014-04-12 19:35:00,22.6346155591\n2014-04-12 19:40:00,23.6704938067\n2014-04-12 19:45:00,23.2847853288\n2014-04-12 19:50:00,24.2256271158\n2014-04-12 19:55:00,24.1284915003\n2014-04-12 20:00:00,21.6609887525\n2014-04-12 20:05:00,20.378374555\n2014-04-12 20:10:00,19.694085529200002\n2014-04-12 20:15:00,20.5087814753\n2014-04-12 20:20:00,20.4884850577\n2014-04-12 20:25:00,20.9316883971\n2014-04-12 20:30:00,19.194255407300002\n2014-04-12 20:35:00,21.1174187769\n2014-04-12 20:40:00,20.3022371419\n2014-04-12 20:45:00,20.97235874\n2014-04-12 20:50:00,19.4134211217\n2014-04-12 20:55:00,20.2112812428\n2014-04-12 21:00:00,18.9312406748\n2014-04-12 21:05:00,21.6044264332\n2014-04-12 21:10:00,20.0476129832\n2014-04-12 21:15:00,18.990645259\n2014-04-12 21:20:00,18.252025945299998\n2014-04-12 21:25:00,20.8023287901\n2014-04-12 21:30:00,18.9490999881\n2014-04-12 21:35:00,22.0637286934\n2014-04-12 21:40:00,20.2314484913\n2014-04-12 21:45:00,19.2478562962\n2014-04-12 21:50:00,20.7297370912\n2014-04-12 21:55:00,19.1925638693\n2014-04-12 22:00:00,21.3015270185\n2014-04-12 22:05:00,19.2514078207\n2014-04-12 22:10:00,21.974065790100003\n2014-04-12 22:15:00,20.4401828877\n2014-04-12 22:20:00,21.398167124100002\n2014-04-12 22:25:00,18.3088214807\n2014-04-12 22:30:00,19.4118151298\n2014-04-12 22:35:00,20.9700602848\n2014-04-12 22:40:00,20.6400314859\n2014-04-12 22:45:00,18.7949983701\n2014-04-12 22:50:00,19.4434595317\n2014-04-12 22:55:00,19.0720652433\n2014-04-12 23:00:00,20.4574077453\n2014-04-12 23:05:00,19.381993544300002\n2014-04-12 23:10:00,19.2399103198\n2014-04-12 23:15:00,18.8331271862\n2014-04-12 23:20:00,19.6398786146\n2014-04-12 23:25:00,18.7856165049\n2014-04-12 23:30:00,21.8544736008\n2014-04-12 23:35:00,18.6215819015\n2014-04-12 23:40:00,21.657376275700003\n2014-04-12 23:45:00,19.717677458\n2014-04-12 23:50:00,19.5152101654\n2014-04-12 23:55:00,18.9289128554\n2014-04-13 00:00:00,20.5430253375\n2014-04-13 00:05:00,20.74211206\n2014-04-13 00:10:00,19.870283849\n2014-04-13 00:15:00,18.2228275828\n2014-04-13 00:20:00,21.6740406028\n2014-04-13 00:25:00,21.9213165315\n2014-04-13 00:30:00,19.7241736608\n2014-04-13 00:35:00,20.454643229600002\n2014-04-13 00:40:00,19.801194505\n2014-04-13 00:45:00,19.2875186035\n2014-04-13 00:50:00,18.3092751714\n2014-04-13 00:55:00,19.8242709216\n2014-04-13 01:00:00,21.2735382254\n2014-04-13 01:05:00,18.0681258444\n2014-04-13 01:10:00,20.3284307327\n2014-04-13 01:15:00,21.523088434899996\n2014-04-13 01:20:00,18.8701977201\n2014-04-13 01:25:00,18.7330234588\n2014-04-13 01:30:00,21.0891065028\n2014-04-13 01:35:00,19.0203457245\n2014-04-13 01:40:00,18.7679370702\n2014-04-13 01:45:00,19.5119570023\n2014-04-13 01:50:00,19.5700080491\n2014-04-13 01:55:00,21.4964042521\n2014-04-13 02:00:00,20.4737738877\n2014-04-13 02:05:00,19.6238458254\n2014-04-13 02:10:00,20.1375518571\n2014-04-13 02:15:00,21.815860933299998\n2014-04-13 02:20:00,18.4528587064\n2014-04-13 02:25:00,18.8308620869\n2014-04-13 02:30:00,21.8501148263\n2014-04-13 02:35:00,21.829299394099998\n2014-04-13 02:40:00,18.7086616851\n2014-04-13 02:45:00,18.5804352685\n2014-04-13 02:50:00,19.6843405374\n2014-04-13 02:55:00,18.19887317\n2014-04-13 03:00:00,20.6196141291\n2014-04-13 03:05:00,18.3099840866\n2014-04-13 03:10:00,18.2321185084\n2014-04-13 03:15:00,19.9407477448\n2014-04-13 03:20:00,21.8311465444\n2014-04-13 03:25:00,19.7071837443\n2014-04-13 03:30:00,19.4259246346\n2014-04-13 03:35:00,21.991826861999996\n2014-04-13 03:40:00,20.1278758431\n2014-04-13 03:45:00,19.5009656276\n2014-04-13 03:50:00,19.5434432534\n2014-04-13 03:55:00,18.779837984100002\n2014-04-13 04:00:00,20.0488922298\n2014-04-13 04:05:00,19.7554201127\n2014-04-13 04:10:00,19.0831811854\n2014-04-13 04:15:00,18.6421603464\n2014-04-13 04:20:00,19.2449554747\n2014-04-13 04:25:00,20.0347333108\n2014-04-13 04:30:00,18.2333330891\n2014-04-13 04:35:00,18.6149761143\n2014-04-13 04:40:00,21.7906290679\n2014-04-13 04:45:00,20.171421404100002\n2014-04-13 04:50:00,18.2537972146\n2014-04-13 04:55:00,20.7723510351\n2014-04-13 05:00:00,18.2472114803\n2014-04-13 05:05:00,20.9554969082\n2014-04-13 05:10:00,20.9998508869\n2014-04-13 05:15:00,20.604315903\n2014-04-13 05:20:00,20.9288181785\n2014-04-13 05:25:00,18.3518631241\n2014-04-13 05:30:00,20.9071222094\n2014-04-13 05:35:00,18.546753278900002\n2014-04-13 05:40:00,19.3580236291\n2014-04-13 05:45:00,21.770981014\n2014-04-13 05:50:00,20.0115019106\n2014-04-13 05:55:00,21.869705728299998\n2014-04-13 06:00:00,18.355689835499998\n2014-04-13 06:05:00,19.9102263983\n2014-04-13 06:10:00,18.2496092811\n2014-04-13 06:15:00,20.5208410496\n2014-04-13 06:20:00,18.3148280055\n2014-04-13 06:25:00,18.7014712102\n2014-04-13 06:30:00,19.0353212403\n2014-04-13 06:35:00,20.9949754067\n2014-04-13 06:40:00,18.6558484753\n2014-04-13 06:45:00,21.3865282132\n2014-04-13 06:50:00,18.5276157553\n2014-04-13 06:55:00,18.1409777963\n2014-04-13 07:00:00,19.5801816759\n2014-04-13 07:05:00,21.9177665679\n2014-04-13 07:10:00,18.441368911199998\n2014-04-13 07:15:00,18.406873776199998\n2014-04-13 07:20:00,21.0046660432\n2014-04-13 07:25:00,19.248646775999998\n2014-04-13 07:30:00,20.8691264689\n2014-04-13 07:35:00,18.8000423578\n2014-04-13 07:40:00,19.8402879768\n2014-04-13 07:45:00,19.061159511\n2014-04-13 07:50:00,19.8061128595\n2014-04-13 07:55:00,21.0763883703\n2014-04-13 08:00:00,21.0480397619\n2014-04-13 08:05:00,20.063089150699998\n2014-04-13 08:10:00,21.713487374899998\n2014-04-13 08:15:00,19.0551364098\n2014-04-13 08:20:00,18.9612454045\n2014-04-13 08:25:00,20.4552256047\n2014-04-13 08:30:00,20.4851881369\n2014-04-13 08:35:00,18.186160158299998\n2014-04-13 08:40:00,20.4311108495\n2014-04-13 08:45:00,19.4977446294\n2014-04-13 08:50:00,20.9897701013\n2014-04-13 08:55:00,21.2324226582\n2014-04-13 09:00:00,68.7092919458\n2014-04-13 09:05:00,61.2231884284\n2014-04-13 09:10:00,69.8545750183\n2014-04-13 09:15:00,71.3847854035\n2014-04-13 09:20:00,64.5861724207\n2014-04-13 09:25:00,67.5191856155\n2014-04-13 09:30:00,74.3338820784\n2014-04-13 09:35:00,65.2543715262\n2014-04-13 09:40:00,64.2348842142\n2014-04-13 09:45:00,64.0676251505\n2014-04-13 09:50:00,68.7996913472\n2014-04-13 09:55:00,74.11710457779999\n2014-04-13 10:00:00,79.28687080520001\n2014-04-13 10:05:00,74.5475748261\n2014-04-13 10:10:00,79.7506029556\n2014-04-13 10:15:00,79.5375524587\n2014-04-13 10:20:00,79.10427810649999\n2014-04-13 10:25:00,72.3142947309\n2014-04-13 10:30:00,79.6884767258\n2014-04-13 10:35:00,76.516152303\n2014-04-13 10:40:00,70.12854874979999\n2014-04-13 10:45:00,78.2171448405\n2014-04-13 10:50:00,85.1934198858\n2014-04-13 10:55:00,75.2679584499\n2014-04-13 11:00:00,86.92425380809998\n2014-04-13 11:05:00,73.0980561154\n2014-04-13 11:10:00,83.21688664279999\n2014-04-13 11:15:00,73.3863042351\n2014-04-13 11:20:00,75.9188823058\n2014-04-13 11:25:00,80.646652645\n2014-04-13 11:30:00,80.995568253\n2014-04-13 11:35:00,83.8969607893\n2014-04-13 11:40:00,81.3539126205\n2014-04-13 11:45:00,81.00884825850001\n2014-04-13 11:50:00,86.07806349549999\n2014-04-13 11:55:00,78.7591646031\n2014-04-13 12:00:00,75.5135273562\n2014-04-13 12:05:00,74.49911101949999\n2014-04-13 12:10:00,78.3058336527\n2014-04-13 12:15:00,83.30395923020001\n2014-04-13 12:20:00,72.593478924\n2014-04-13 12:25:00,73.9759763591\n2014-04-13 12:30:00,73.60937798319999\n2014-04-13 12:35:00,81.2663656459\n2014-04-13 12:40:00,75.7947714072\n2014-04-13 12:45:00,74.5705586718\n2014-04-13 12:50:00,81.3865503181\n2014-04-13 12:55:00,84.07994149689999\n2014-04-13 13:00:00,77.2959231884\n2014-04-13 13:05:00,81.2317733851\n2014-04-13 13:10:00,73.5523338134\n2014-04-13 13:15:00,86.94218535379999\n2014-04-13 13:20:00,77.3717652837\n2014-04-13 13:25:00,87.93898066889999\n2014-04-13 13:30:00,87.6363663166\n2014-04-13 13:35:00,84.44090450729999\n2014-04-13 13:40:00,72.3037164689\n2014-04-13 13:45:00,80.6762317825\n2014-04-13 13:50:00,73.37176927520001\n2014-04-13 13:55:00,86.3014910854\n2014-04-13 14:00:00,84.63011760170002\n2014-04-13 14:05:00,87.55324326809998\n2014-04-13 14:10:00,81.73020401229999\n2014-04-13 14:15:00,80.350907843\n2014-04-13 14:20:00,80.2997271232\n2014-04-13 14:25:00,78.1794211989\n2014-04-13 14:30:00,79.4952251217\n2014-04-13 14:35:00,82.1626573333\n2014-04-13 14:40:00,86.9229892171\n2014-04-13 14:45:00,81.5302357729\n2014-04-13 14:50:00,85.70974081199999\n2014-04-13 14:55:00,85.8003599659\n2014-04-13 15:00:00,80.3005519209\n2014-04-13 15:05:00,77.55876969260001\n2014-04-13 15:10:00,82.2323925348\n2014-04-13 15:15:00,79.1332777839\n2014-04-13 15:20:00,73.3023501678\n2014-04-13 15:25:00,78.0441963754\n2014-04-13 15:30:00,87.90431031930002\n2014-04-13 15:35:00,72.775491269\n2014-04-13 15:40:00,83.1458723824\n2014-04-13 15:45:00,85.4581988746\n2014-04-13 15:50:00,82.3788236113\n2014-04-13 15:55:00,81.1151929853\n2014-04-13 16:00:00,83.3207106956\n2014-04-13 16:05:00,78.86933236739999\n2014-04-13 16:10:00,73.46164675029999\n2014-04-13 16:15:00,87.39778026479998\n2014-04-13 16:20:00,78.9166607995\n2014-04-13 16:25:00,82.6460691139\n2014-04-13 16:30:00,80.5008124284\n2014-04-13 16:35:00,72.8746292321\n2014-04-13 16:40:00,87.2437781075\n2014-04-13 16:45:00,84.6804330311\n2014-04-13 16:50:00,74.3854234912\n2014-04-13 16:55:00,87.70621362440002\n2014-04-13 17:00:00,83.7903897792\n2014-04-13 17:05:00,79.5571158569\n2014-04-13 17:10:00,81.7818895007\n2014-04-13 17:15:00,73.7077586084\n2014-04-13 17:20:00,80.9665530691\n2014-04-13 17:25:00,73.1785490517\n2014-04-13 17:30:00,80.71765311829998\n2014-04-13 17:35:00,80.8430999764\n2014-04-13 17:40:00,85.99098754200001\n2014-04-13 17:45:00,83.6008879016\n2014-04-13 17:50:00,75.9928090942\n2014-04-13 17:55:00,86.2147851685\n2014-04-13 18:00:00,32.468746820999996\n2014-04-13 18:05:00,32.6808223882\n2014-04-13 18:10:00,29.8814750258\n2014-04-13 18:15:00,34.2897444306\n2014-04-13 18:20:00,34.7581700625\n2014-04-13 18:25:00,33.7599336749\n2014-04-13 18:30:00,34.8208090113\n2014-04-13 18:35:00,30.734713485300002\n2014-04-13 18:40:00,34.3111560898\n2014-04-13 18:45:00,31.928909984\n2014-04-13 18:50:00,29.8490643678\n2014-04-13 18:55:00,33.0803174824\n2014-04-13 19:00:00,23.2248575387\n2014-04-13 19:05:00,21.4454206452\n2014-04-13 19:10:00,20.283169013\n2014-04-13 19:15:00,21.055314565699998\n2014-04-13 19:20:00,21.951002209400002\n2014-04-13 19:25:00,20.9106806944\n2014-04-13 19:30:00,21.0292530145\n2014-04-13 19:35:00,21.913428974299997\n2014-04-13 19:40:00,24.4688026898\n2014-04-13 19:45:00,23.5838096553\n2014-04-13 19:50:00,21.592471653\n2014-04-13 19:55:00,24.423184889\n2014-04-13 20:00:00,21.0765690082\n2014-04-13 20:05:00,20.2975215009\n2014-04-13 20:10:00,20.3501573707\n2014-04-13 20:15:00,20.1144090989\n2014-04-13 20:20:00,19.3863352146\n2014-04-13 20:25:00,20.0156452191\n2014-04-13 20:30:00,20.5942633419\n2014-04-13 20:35:00,20.5947997815\n2014-04-13 20:40:00,21.5520740928\n2014-04-13 20:45:00,19.9016357841\n2014-04-13 20:50:00,21.368004471600003\n2014-04-13 20:55:00,20.799863922\n2014-04-13 21:00:00,21.952248996199998\n2014-04-13 21:05:00,19.634937126700002\n2014-04-13 21:10:00,21.7085691601\n2014-04-13 21:15:00,21.3847264738\n2014-04-13 21:20:00,20.6493002421\n2014-04-13 21:25:00,20.717024494100002\n2014-04-13 21:30:00,18.4266249721\n2014-04-13 21:35:00,21.9055426812\n2014-04-13 21:40:00,18.5161973811\n2014-04-13 21:45:00,20.3501472647\n2014-04-13 21:50:00,19.413020513699998\n2014-04-13 21:55:00,19.8140610227\n2014-04-13 22:00:00,20.4603551361\n2014-04-13 22:05:00,21.6561754902\n2014-04-13 22:10:00,19.8493055423\n2014-04-13 22:15:00,21.9719910919\n2014-04-13 22:20:00,20.3908046497\n2014-04-13 22:25:00,18.6601122885\n2014-04-13 22:30:00,18.7780468058\n2014-04-13 22:35:00,20.8844739985\n2014-04-13 22:40:00,18.2190646956\n2014-04-13 22:45:00,19.9404908067\n2014-04-13 22:50:00,18.6107255915\n2014-04-13 22:55:00,19.7518180906\n2014-04-13 23:00:00,21.0037016228\n2014-04-13 23:05:00,19.8390600793\n2014-04-13 23:10:00,18.6573859645\n2014-04-13 23:15:00,19.011350958199998\n2014-04-13 23:20:00,19.4738966231\n2014-04-13 23:25:00,18.2817541551\n2014-04-13 23:30:00,20.341255313599998\n2014-04-13 23:35:00,20.434057749100003\n2014-04-13 23:40:00,18.2521114394\n2014-04-13 23:45:00,19.6130102579\n2014-04-13 23:50:00,19.6597766821\n2014-04-13 23:55:00,19.3389906457\n2014-04-14 00:00:00,20.2309589613\n2014-04-14 00:05:00,19.3838299602\n2014-04-14 00:10:00,19.6656371179\n2014-04-14 00:15:00,21.1900941898\n2014-04-14 00:20:00,18.648437421700002\n2014-04-14 00:25:00,20.476458781199998\n2014-04-14 00:30:00,20.0223776068\n2014-04-14 00:35:00,19.2202865499\n2014-04-14 00:40:00,20.910138626\n2014-04-14 00:45:00,20.2047534382\n2014-04-14 00:50:00,19.9094461078\n2014-04-14 00:55:00,20.6706772591\n2014-04-14 01:00:00,21.2091612319\n2014-04-14 01:05:00,21.890675160100002\n2014-04-14 01:10:00,20.517401473499998\n2014-04-14 01:15:00,21.4977599416\n2014-04-14 01:20:00,18.004366164100002\n2014-04-14 01:25:00,20.120942770899997\n2014-04-14 01:30:00,18.8585901951\n2014-04-14 01:35:00,18.3767698283\n2014-04-14 01:40:00,20.1278840683\n2014-04-14 01:45:00,20.9873060246\n2014-04-14 01:50:00,19.6490900899\n2014-04-14 01:55:00,20.6804297974\n2014-04-14 02:00:00,19.9588770154\n2014-04-14 02:05:00,19.7483434638\n2014-04-14 02:10:00,19.1610265617\n2014-04-14 02:15:00,19.530374058\n2014-04-14 02:20:00,19.3991825232\n2014-04-14 02:25:00,20.5847487361\n2014-04-14 02:30:00,18.4640740451\n2014-04-14 02:35:00,18.3705454748\n2014-04-14 02:40:00,20.640051976800002\n2014-04-14 02:45:00,20.1851922795\n2014-04-14 02:50:00,19.720800387\n2014-04-14 02:55:00,18.6097715376\n2014-04-14 03:00:00,19.6441084475\n2014-04-14 03:05:00,21.158927053299998\n2014-04-14 03:10:00,21.558484943200003\n2014-04-14 03:15:00,20.8103062799\n2014-04-14 03:20:00,18.2396487035\n2014-04-14 03:25:00,20.681639106400002\n2014-04-14 03:30:00,18.9639423582\n2014-04-14 03:35:00,19.2610049721\n2014-04-14 03:40:00,18.7834928318\n2014-04-14 03:45:00,21.1030231625\n2014-04-14 03:50:00,20.5944084905\n2014-04-14 03:55:00,20.4473402184\n2014-04-14 04:00:00,20.6718904387\n2014-04-14 04:05:00,18.9470890456\n2014-04-14 04:10:00,19.7785776573\n2014-04-14 04:15:00,20.5330148862\n2014-04-14 04:20:00,20.5463761105\n2014-04-14 04:25:00,21.167407451\n2014-04-14 04:30:00,19.1484158668\n2014-04-14 04:35:00,21.0813444868\n2014-04-14 04:40:00,19.7607379225\n2014-04-14 04:45:00,20.680690768199998\n2014-04-14 04:50:00,19.8228775203\n2014-04-14 04:55:00,21.7944406792\n2014-04-14 05:00:00,18.717209059\n2014-04-14 05:05:00,20.7000203543\n2014-04-14 05:10:00,20.306140003099998\n2014-04-14 05:15:00,18.690924163800002\n2014-04-14 05:20:00,18.2640253432\n2014-04-14 05:25:00,21.1965775559\n2014-04-14 05:30:00,18.6298053346\n2014-04-14 05:35:00,18.7460267311\n2014-04-14 05:40:00,21.913736896\n2014-04-14 05:45:00,20.869043405899998\n2014-04-14 05:50:00,19.0019473664\n2014-04-14 05:55:00,20.363795840599998\n2014-04-14 06:00:00,20.136447353599998\n2014-04-14 06:05:00,21.3778930701\n2014-04-14 06:10:00,20.917282991300002\n2014-04-14 06:15:00,21.326884502000002\n2014-04-14 06:20:00,18.8460263519\n2014-04-14 06:25:00,20.5608768175\n2014-04-14 06:30:00,18.160963433699997\n2014-04-14 06:35:00,18.2757624491\n2014-04-14 06:40:00,20.8541081308\n2014-04-14 06:45:00,18.0976804106\n2014-04-14 06:50:00,20.3190600356\n2014-04-14 06:55:00,21.361620393800003\n2014-04-14 07:00:00,19.519767233699998\n2014-04-14 07:05:00,18.1793617474\n2014-04-14 07:10:00,20.8553897985\n2014-04-14 07:15:00,21.718745809899996\n2014-04-14 07:20:00,20.8686855682\n2014-04-14 07:25:00,20.313788972\n2014-04-14 07:30:00,18.9201153195\n2014-04-14 07:35:00,18.0615024962\n2014-04-14 07:40:00,20.7786884339\n2014-04-14 07:45:00,18.924104703399998\n2014-04-14 07:50:00,21.4326507087\n2014-04-14 07:55:00,19.8654564753\n2014-04-14 08:00:00,20.1225423295\n2014-04-14 08:05:00,21.0157461771\n2014-04-14 08:10:00,21.117722431199997\n2014-04-14 08:15:00,20.5706033323\n2014-04-14 08:20:00,21.7537272617\n2014-04-14 08:25:00,21.9291937453\n2014-04-14 08:30:00,21.7875417775\n2014-04-14 08:35:00,21.2967167414\n2014-04-14 08:40:00,20.822500881\n2014-04-14 08:45:00,20.6533034315\n2014-04-14 08:50:00,18.4150007077\n2014-04-14 08:55:00,19.0859373873\n2014-04-14 09:00:00,61.27735984\n2014-04-14 09:05:00,63.0687742352\n2014-04-14 09:10:00,67.1735208895\n2014-04-14 09:15:00,63.192897090699994\n2014-04-14 09:20:00,73.4626224396\n2014-04-14 09:25:00,72.15750892060001\n2014-04-14 09:30:00,62.1739220044\n2014-04-14 09:35:00,64.58522653039999\n2014-04-14 09:40:00,72.3393776307\n2014-04-14 09:45:00,72.1214273212\n2014-04-14 09:50:00,74.0581274816\n2014-04-14 09:55:00,74.766649558\n2014-04-14 10:00:00,84.9917113815\n2014-04-14 10:05:00,76.2053415384\n2014-04-14 10:10:00,73.7250974478\n2014-04-14 10:15:00,81.6105261554\n2014-04-14 10:20:00,74.4847152954\n2014-04-14 10:25:00,82.3553335892\n2014-04-14 10:30:00,78.1269774158\n2014-04-14 10:35:00,82.1617513116\n2014-04-14 10:40:00,74.1216557332\n2014-04-14 10:45:00,77.7245839374\n2014-04-14 10:50:00,78.5936492767\n2014-04-14 10:55:00,84.47703721100001\n2014-04-14 11:00:00,75.8079678619\n2014-04-14 11:05:00,86.4650897576\n2014-04-14 11:10:00,84.3684761916\n2014-04-14 11:15:00,83.1921390362\n2014-04-14 11:20:00,84.0823847611\n2014-04-14 11:25:00,81.1966799297\n2014-04-14 11:30:00,75.4498484864\n2014-04-14 11:35:00,74.58172798439999\n2014-04-14 11:40:00,85.3462941958\n2014-04-14 11:45:00,83.1006170589\n2014-04-14 11:50:00,74.958800913\n2014-04-14 11:55:00,81.35044489090001\n2014-04-14 12:00:00,79.0657508102\n2014-04-14 12:05:00,74.4490365401\n2014-04-14 12:10:00,80.4131020932\n2014-04-14 12:15:00,76.4125003129\n2014-04-14 12:20:00,73.4516580993\n2014-04-14 12:25:00,79.3759671774\n2014-04-14 12:30:00,81.34400674930001\n2014-04-14 12:35:00,72.663201963\n2014-04-14 12:40:00,78.33936380979999\n2014-04-14 12:45:00,76.0312436085\n2014-04-14 12:50:00,72.40342096\n2014-04-14 12:55:00,73.9217880728\n2014-04-14 13:00:00,74.2067326499\n2014-04-14 13:05:00,74.90800573279999\n2014-04-14 13:10:00,84.8336761731\n2014-04-14 13:15:00,79.0129022149\n2014-04-14 13:20:00,74.3355310661\n2014-04-14 13:25:00,73.5870863305\n2014-04-14 13:30:00,76.74862324829998\n2014-04-14 13:35:00,84.74790391970001\n2014-04-14 13:40:00,77.8126780412\n2014-04-14 13:45:00,74.5404637588\n2014-04-14 13:50:00,78.4470270986\n2014-04-14 13:55:00,80.8655725202\n2014-04-14 14:00:00,72.46986821760001\n2014-04-14 14:05:00,82.0383307941\n2014-04-14 14:10:00,78.3178526109\n2014-04-14 14:15:00,72.1521505326\n2014-04-14 14:20:00,82.7782568361\n2014-04-14 14:25:00,83.39419905529999\n2014-04-14 14:30:00,82.057497668\n2014-04-14 14:35:00,77.4671648792\n2014-04-14 14:40:00,80.4698149285\n2014-04-14 14:45:00,78.190769961\n2014-04-14 14:50:00,83.2059536051\n2014-04-14 14:55:00,81.3333787902\n2014-04-14 15:00:00,73.30808205689999\n2014-04-14 15:05:00,82.28870695229999\n2014-04-14 15:10:00,82.9950178696\n2014-04-14 15:15:00,77.93048675\n2014-04-14 15:20:00,86.01174677469999\n2014-04-14 15:25:00,85.4874089905\n2014-04-14 15:30:00,74.80194627680001\n2014-04-14 15:35:00,86.46743084049999\n2014-04-14 15:40:00,79.0531990259\n2014-04-14 15:45:00,83.5791920742\n2014-04-14 15:50:00,85.0247358662\n2014-04-14 15:55:00,80.0810299518\n2014-04-14 16:00:00,78.3854805295\n2014-04-14 16:05:00,86.64705553520002\n2014-04-14 16:10:00,75.6935115151\n2014-04-14 16:15:00,76.1113751094\n2014-04-14 16:20:00,77.7857756752\n2014-04-14 16:25:00,85.7512878047\n2014-04-14 16:30:00,87.0204451478\n2014-04-14 16:35:00,75.5209384356\n2014-04-14 16:40:00,85.821757584\n2014-04-14 16:45:00,76.13110117949999\n2014-04-14 16:50:00,87.53009188989998\n2014-04-14 16:55:00,81.5583696793\n2014-04-14 17:00:00,72.1133557876\n2014-04-14 17:05:00,72.54605060739999\n2014-04-14 17:10:00,74.3597239387\n2014-04-14 17:15:00,75.0011417247\n2014-04-14 17:20:00,84.281873601\n2014-04-14 17:25:00,75.564225006\n2014-04-14 17:30:00,87.5062323184\n2014-04-14 17:35:00,82.177761359\n2014-04-14 17:40:00,83.08024824520001\n2014-04-14 17:45:00,75.48503532229999\n2014-04-14 17:50:00,86.28326789270002\n2014-04-14 17:55:00,82.6850014141\n2014-04-14 18:00:00,34.332189404\n2014-04-14 18:05:00,34.921472317399996\n2014-04-14 18:10:00,29.604096569499998\n2014-04-14 18:15:00,29.4181526254\n2014-04-14 18:20:00,33.9418035733\n2014-04-14 18:25:00,34.343200184299995\n2014-04-14 18:30:00,32.5360668467\n2014-04-14 18:35:00,31.1423975263\n2014-04-14 18:40:00,32.9768233393\n2014-04-14 18:45:00,30.7562441594\n2014-04-14 18:50:00,30.3256626073\n2014-04-14 18:55:00,31.9241232115\n2014-04-14 19:00:00,21.128367988599997\n2014-04-14 19:05:00,22.326990940500004\n2014-04-14 19:10:00,24.445595803499998\n2014-04-14 19:15:00,23.9222311673\n2014-04-14 19:20:00,24.378505181999998\n2014-04-14 19:25:00,23.7723525032\n2014-04-14 19:30:00,21.749282999899997\n2014-04-14 19:35:00,23.797961363200002\n2014-04-14 19:40:00,24.2946611984\n2014-04-14 19:45:00,24.4027189908\n2014-04-14 19:50:00,23.2207250972\n2014-04-14 19:55:00,21.1069214064\n2014-04-14 20:00:00,18.594730389000002\n2014-04-14 20:05:00,19.0349319061\n2014-04-14 20:10:00,22.3868799071\n2014-04-14 20:15:00,20.324748348\n2014-04-14 20:20:00,21.9340224535\n2014-04-14 20:25:00,20.336820608900002\n2014-04-14 20:30:00,21.1387085682\n2014-04-14 20:35:00,18.5308804007\n2014-04-14 20:40:00,19.4554465719\n2014-04-14 20:45:00,20.2189587284\n2014-04-14 20:50:00,21.015064517\n2014-04-14 20:55:00,19.134550556700002\n2014-04-14 21:00:00,21.1592851934\n2014-04-14 21:05:00,19.5510153471\n2014-04-14 21:10:00,21.3718357818\n2014-04-14 21:15:00,18.4801573229\n2014-04-14 21:20:00,20.8184776263\n2014-04-14 21:25:00,19.2653451897\n2014-04-14 21:30:00,21.2832040014\n2014-04-14 21:35:00,19.702803332200002\n2014-04-14 21:40:00,20.7605731912\n2014-04-14 21:45:00,21.8415596823\n2014-04-14 21:50:00,18.169302515\n2014-04-14 21:55:00,18.1310805272\n2014-04-14 22:00:00,21.1013548707\n2014-04-14 22:05:00,20.6053343452\n2014-04-14 22:10:00,19.1903239147\n2014-04-14 22:15:00,19.996765284600002\n2014-04-14 22:20:00,18.185183686400002\n2014-04-14 22:25:00,18.787801403299998\n2014-04-14 22:30:00,19.7168955545\n2014-04-14 22:35:00,21.356660385\n2014-04-14 22:40:00,19.9377906436\n2014-04-14 22:45:00,20.3649816401\n2014-04-14 22:50:00,21.515650372\n2014-04-14 22:55:00,19.2537415095\n2014-04-14 23:00:00,20.8067914194\n2014-04-14 23:05:00,21.4507867931\n2014-04-14 23:10:00,18.8140744098\n2014-04-14 23:15:00,19.4296424339\n2014-04-14 23:20:00,21.923449187600003\n2014-04-14 23:25:00,21.9370853689\n2014-04-14 23:30:00,18.8965471599\n2014-04-14 23:35:00,18.2692903842\n2014-04-14 23:40:00,19.0873505112\n2014-04-14 23:45:00,19.5946892854\n2014-04-14 23:50:00,19.7678170941\n2014-04-14 23:55:00,20.4791564706\n"
  },
  {
    "path": "workspace/anomaly_detector/datasets/selected/seasonal/art_daily_jumpsup.csv",
    "content": "timestamp,value\n2014-04-01 00:00:00,19.761251902999998\n2014-04-01 00:05:00,20.500833287\n2014-04-01 00:10:00,19.9616414445\n2014-04-01 00:15:00,21.4902660734\n2014-04-01 00:20:00,20.1877394098\n2014-04-01 00:25:00,19.9231256718\n2014-04-01 00:30:00,21.698403961700002\n2014-04-01 00:35:00,20.8787583842\n2014-04-01 00:40:00,18.4461996294\n2014-04-01 00:45:00,18.7108178448\n2014-04-01 00:50:00,21.148491451800002\n2014-04-01 00:55:00,21.3434052847\n2014-04-01 01:00:00,20.1807633164\n2014-04-01 01:05:00,20.217820911500002\n2014-04-01 01:10:00,20.527731851400002\n2014-04-01 01:15:00,19.7564630971\n2014-04-01 01:20:00,20.7207964939\n2014-04-01 01:25:00,18.4339250303\n2014-04-01 01:30:00,21.845116969499998\n2014-04-01 01:35:00,21.0006192952\n2014-04-01 01:40:00,20.524696816\n2014-04-01 01:45:00,19.265288228\n2014-04-01 01:50:00,18.6438219498\n2014-04-01 01:55:00,19.6373718553\n2014-04-01 02:00:00,20.6463069623\n2014-04-01 02:05:00,20.534838973699998\n2014-04-01 02:10:00,19.530564620299998\n2014-04-01 02:15:00,20.4531455753\n2014-04-01 02:20:00,21.2549931823\n2014-04-01 02:25:00,18.1051390894\n2014-04-01 02:30:00,19.8024841917\n2014-04-01 02:35:00,21.0342209139\n2014-04-01 02:40:00,20.1845778819\n2014-04-01 02:45:00,20.6059043517\n2014-04-01 02:50:00,20.0667055704\n2014-04-01 02:55:00,21.967498178699998\n2014-04-01 03:00:00,18.218486146\n2014-04-01 03:05:00,19.964179287100002\n2014-04-01 03:10:00,18.3656661965\n2014-04-01 03:15:00,18.6391422485\n2014-04-01 03:20:00,19.5321534017\n2014-04-01 03:25:00,18.622160366\n2014-04-01 03:30:00,21.854748663800002\n2014-04-01 03:35:00,21.7871591069\n2014-04-01 03:40:00,19.3444385849\n2014-04-01 03:45:00,20.5589908482\n2014-04-01 03:50:00,20.1350132824\n2014-04-01 03:55:00,21.262347922100002\n2014-04-01 04:00:00,20.5097824393\n2014-04-01 04:05:00,18.001009818\n2014-04-01 04:10:00,21.0526975424\n2014-04-01 04:15:00,20.9873924852\n2014-04-01 04:20:00,20.0388908223\n2014-04-01 04:25:00,21.6116758929\n2014-04-01 04:30:00,21.633784822800003\n2014-04-01 04:35:00,20.0956467068\n2014-04-01 04:40:00,20.4319529248\n2014-04-01 04:45:00,21.9860882877\n2014-04-01 04:50:00,19.1952809392\n2014-04-01 04:55:00,19.2984689692\n2014-04-01 05:00:00,18.7310956107\n2014-04-01 05:05:00,21.583467756599998\n2014-04-01 05:10:00,20.9779535598\n2014-04-01 05:15:00,18.4225713955\n2014-04-01 05:20:00,21.9270694048\n2014-04-01 05:25:00,20.9238468326\n2014-04-01 05:30:00,21.4020884384\n2014-04-01 05:35:00,18.192603156700002\n2014-04-01 05:40:00,20.0198436758\n2014-04-01 05:45:00,20.7943931469\n2014-04-01 05:50:00,20.1717863383\n2014-04-01 05:55:00,20.6665898628\n2014-04-01 06:00:00,21.2714962544\n2014-04-01 06:05:00,19.497348251800002\n2014-04-01 06:10:00,21.3946747025\n2014-04-01 06:15:00,18.6516644191\n2014-04-01 06:20:00,19.0835442201\n2014-04-01 06:25:00,18.1733824797\n2014-04-01 06:30:00,19.4577072453\n2014-04-01 06:35:00,19.5196381793\n2014-04-01 06:40:00,21.221082388800003\n2014-04-01 06:45:00,20.612522681199998\n2014-04-01 06:50:00,19.7468902326\n2014-04-01 06:55:00,20.608455914500002\n2014-04-01 07:00:00,18.2111334021\n2014-04-01 07:05:00,18.7210861441\n2014-04-01 07:10:00,20.507791421\n2014-04-01 07:15:00,20.5654672769\n2014-04-01 07:20:00,21.0965386348\n2014-04-01 07:25:00,19.6119990362\n2014-04-01 07:30:00,20.8902163865\n2014-04-01 07:35:00,20.7359213302\n2014-04-01 07:40:00,21.8535735135\n2014-04-01 07:45:00,18.8605209057\n2014-04-01 07:50:00,20.206718255\n2014-04-01 07:55:00,20.407057768399998\n2014-04-01 08:00:00,21.994591539699996\n2014-04-01 08:05:00,18.804736568699997\n2014-04-01 08:10:00,20.0928720799\n2014-04-01 08:15:00,19.384741230899998\n2014-04-01 08:20:00,20.103571874300002\n2014-04-01 08:25:00,18.928514408399998\n2014-04-01 08:30:00,18.1904495137\n2014-04-01 08:35:00,20.2902618156\n2014-04-01 08:40:00,19.3434172634\n2014-04-01 08:45:00,18.727765607000002\n2014-04-01 08:50:00,19.2957422643\n2014-04-01 08:55:00,18.1971208058\n2014-04-01 09:00:00,74.1260143836\n2014-04-01 09:05:00,69.10361164359999\n2014-04-01 09:10:00,72.2808540663\n2014-04-01 09:15:00,66.9544074866\n2014-04-01 09:20:00,73.4850794789\n2014-04-01 09:25:00,67.7731278131\n2014-04-01 09:30:00,69.0056563819\n2014-04-01 09:35:00,67.88839812890001\n2014-04-01 09:40:00,71.1725848238\n2014-04-01 09:45:00,68.9065226554\n2014-04-01 09:50:00,64.8937453607\n2014-04-01 09:55:00,63.179337626000006\n2014-04-01 10:00:00,79.2470505155\n2014-04-01 10:05:00,77.4320730032\n2014-04-01 10:10:00,71.3295428127\n2014-04-01 10:15:00,75.9799830691\n2014-04-01 10:20:00,77.8293300694\n2014-04-01 10:25:00,82.67338298899999\n2014-04-01 10:30:00,71.0210883865\n2014-04-01 10:35:00,75.2486478048\n2014-04-01 10:40:00,82.6076230245\n2014-04-01 10:45:00,79.90353942109999\n2014-04-01 10:50:00,74.3401531544\n2014-04-01 10:55:00,82.9596010938\n2014-04-01 11:00:00,79.41334110529999\n2014-04-01 11:05:00,79.4937884794\n2014-04-01 11:10:00,87.0996450426\n2014-04-01 11:15:00,86.6309408675\n2014-04-01 11:20:00,77.2701037963\n2014-04-01 11:25:00,73.8037704623\n2014-04-01 11:30:00,76.7474037102\n2014-04-01 11:35:00,72.052805772\n2014-04-01 11:40:00,71.8982924702\n2014-04-01 11:45:00,77.8583840549\n2014-04-01 11:50:00,86.5339792602\n2014-04-01 11:55:00,85.426067155\n2014-04-01 12:00:00,80.08686564029999\n2014-04-01 12:05:00,80.9463697522\n2014-04-01 12:10:00,72.0084220248\n2014-04-01 12:15:00,75.3574808711\n2014-04-01 12:20:00,72.3095103677\n2014-04-01 12:25:00,83.9717453641\n2014-04-01 12:30:00,74.2411363371\n2014-04-01 12:35:00,85.8016679353\n2014-04-01 12:40:00,82.194437192\n2014-04-01 12:45:00,75.5798939857\n2014-04-01 12:50:00,74.4340968432\n2014-04-01 12:55:00,81.94354482050001\n2014-04-01 13:00:00,86.3926524705\n2014-04-01 13:05:00,83.47372499939999\n2014-04-01 13:10:00,77.5581280065\n2014-04-01 13:15:00,81.3786019713\n2014-04-01 13:20:00,76.953713801\n2014-04-01 13:25:00,87.9652763341\n2014-04-01 13:30:00,83.9612714729\n2014-04-01 13:35:00,81.81046701060001\n2014-04-01 13:40:00,78.7532409691\n2014-04-01 13:45:00,81.8707829394\n2014-04-01 13:50:00,77.4472651938\n2014-04-01 13:55:00,72.4444465903\n2014-04-01 14:00:00,78.31765692970001\n2014-04-01 14:05:00,86.883522504\n2014-04-01 14:10:00,82.0168805171\n2014-04-01 14:15:00,73.3397707712\n2014-04-01 14:20:00,86.15576213920002\n2014-04-01 14:25:00,76.2983350936\n2014-04-01 14:30:00,75.89666867439999\n2014-04-01 14:35:00,76.7497713346\n2014-04-01 14:40:00,81.2313364867\n2014-04-01 14:45:00,80.7111351745\n2014-04-01 14:50:00,79.8587866682\n2014-04-01 14:55:00,83.4765827479\n2014-04-01 15:00:00,77.06386388119998\n2014-04-01 15:05:00,84.51222102\n2014-04-01 15:10:00,74.8044287246\n2014-04-01 15:15:00,84.5211212147\n2014-04-01 15:20:00,82.6201685228\n2014-04-01 15:25:00,82.930536812\n2014-04-01 15:30:00,79.7040891874\n2014-04-01 15:35:00,82.6712308715\n2014-04-01 15:40:00,73.2760492881\n2014-04-01 15:45:00,85.6239958745\n2014-04-01 15:50:00,72.8880560037\n2014-04-01 15:55:00,74.3791501112\n2014-04-01 16:00:00,81.228479377\n2014-04-01 16:05:00,83.83042233260001\n2014-04-01 16:10:00,73.2198844471\n2014-04-01 16:15:00,86.73207050010002\n2014-04-01 16:20:00,87.5775542316\n2014-04-01 16:25:00,81.69504591329998\n2014-04-01 16:30:00,79.6997422622\n2014-04-01 16:35:00,83.8621585408\n2014-04-01 16:40:00,77.2535693101\n2014-04-01 16:45:00,79.8920775526\n2014-04-01 16:50:00,86.6582500449\n2014-04-01 16:55:00,87.29031920610001\n2014-04-01 17:00:00,86.8330725129\n2014-04-01 17:05:00,76.19913981090001\n2014-04-01 17:10:00,75.7194755672\n2014-04-01 17:15:00,76.762602618\n2014-04-01 17:20:00,79.0609474388\n2014-04-01 17:25:00,77.02664902640001\n2014-04-01 17:30:00,77.98737478470001\n2014-04-01 17:35:00,81.93015977270001\n2014-04-01 17:40:00,84.20037850050001\n2014-04-01 17:45:00,83.768899005\n2014-04-01 17:50:00,85.0307444214\n2014-04-01 17:55:00,72.5149226057\n2014-04-01 18:00:00,29.105490665700003\n2014-04-01 18:05:00,33.8520444488\n2014-04-01 18:10:00,32.211698278200004\n2014-04-01 18:15:00,32.5000940721\n2014-04-01 18:20:00,29.1365503112\n2014-04-01 18:25:00,30.4340024842\n2014-04-01 18:30:00,32.8854612373\n2014-04-01 18:35:00,34.2987575113\n2014-04-01 18:40:00,34.6686870856\n2014-04-01 18:45:00,32.0026786288\n2014-04-01 18:50:00,32.2910288896\n2014-04-01 18:55:00,34.131511085599996\n2014-04-01 19:00:00,22.568556973299998\n2014-04-01 19:05:00,22.4755249615\n2014-04-01 19:10:00,24.2147751608\n2014-04-01 19:15:00,23.698897290300003\n2014-04-01 19:20:00,24.232643588800002\n2014-04-01 19:25:00,21.1377456459\n2014-04-01 19:30:00,22.5092009454\n2014-04-01 19:35:00,23.9342738231\n2014-04-01 19:40:00,20.6579411338\n2014-04-01 19:45:00,23.72008515\n2014-04-01 19:50:00,20.9797196068\n2014-04-01 19:55:00,23.7803707178\n2014-04-01 20:00:00,20.938755589\n2014-04-01 20:05:00,19.2234943904\n2014-04-01 20:10:00,20.3708584741\n2014-04-01 20:15:00,21.2250833071\n2014-04-01 20:20:00,21.0282612297\n2014-04-01 20:25:00,20.1820042736\n2014-04-01 20:30:00,22.1158050371\n2014-04-01 20:35:00,20.558902699\n2014-04-01 20:40:00,20.5040322087\n2014-04-01 20:45:00,18.6869781922\n2014-04-01 20:50:00,22.2090048501\n2014-04-01 20:55:00,19.1574692354\n2014-04-01 21:00:00,20.2099229424\n2014-04-01 21:05:00,21.3160988514\n2014-04-01 21:10:00,18.9523497644\n2014-04-01 21:15:00,20.2060186776\n2014-04-01 21:20:00,19.0537607405\n2014-04-01 21:25:00,21.1397660835\n2014-04-01 21:30:00,20.3545999721\n2014-04-01 21:35:00,21.526738125399998\n2014-04-01 21:40:00,21.6818074721\n2014-04-01 21:45:00,20.693789562\n2014-04-01 21:50:00,21.0018924452\n2014-04-01 21:55:00,20.2938253758\n2014-04-01 22:00:00,19.556471129000002\n2014-04-01 22:05:00,20.6122404548\n2014-04-01 22:10:00,21.6539223116\n2014-04-01 22:15:00,19.6856015647\n2014-04-01 22:20:00,19.2761274305\n2014-04-01 22:25:00,19.5725193424\n2014-04-01 22:30:00,19.760542437999998\n2014-04-01 22:35:00,18.3118065813\n2014-04-01 22:40:00,20.0129613686\n2014-04-01 22:45:00,19.9964351491\n2014-04-01 22:50:00,20.3733149249\n2014-04-01 22:55:00,19.4699533412\n2014-04-01 23:00:00,20.4563572484\n2014-04-01 23:05:00,21.516995709099998\n2014-04-01 23:10:00,21.8260737616\n2014-04-01 23:15:00,20.338353076700002\n2014-04-01 23:20:00,18.173852523900003\n2014-04-01 23:25:00,21.8811443602\n2014-04-01 23:30:00,20.8274463436\n2014-04-01 23:35:00,19.3475686124\n2014-04-01 23:40:00,18.5921998191\n2014-04-01 23:45:00,18.5772405926\n2014-04-01 23:50:00,18.6745624504\n2014-04-01 23:55:00,18.185781084400002\n2014-04-02 00:00:00,21.6086167546\n2014-04-02 00:05:00,20.1630729313\n2014-04-02 00:10:00,20.7998376509\n2014-04-02 00:15:00,21.3124340371\n2014-04-02 00:20:00,21.1661640253\n2014-04-02 00:25:00,21.530422494899998\n2014-04-02 00:30:00,21.869018490100004\n2014-04-02 00:35:00,19.756282459\n2014-04-02 00:40:00,21.8013418667\n2014-04-02 00:45:00,20.8931597934\n2014-04-02 00:50:00,18.2826727612\n2014-04-02 00:55:00,20.7271324848\n2014-04-02 01:00:00,20.7468666384\n2014-04-02 01:05:00,21.6234422552\n2014-04-02 01:10:00,19.4917285299\n2014-04-02 01:15:00,20.3396460011\n2014-04-02 01:20:00,18.048750204\n2014-04-02 01:25:00,19.3283009687\n2014-04-02 01:30:00,18.2489749046\n2014-04-02 01:35:00,20.087491891099997\n2014-04-02 01:40:00,21.269790602\n2014-04-02 01:45:00,18.8257707685\n2014-04-02 01:50:00,20.1097641822\n2014-04-02 01:55:00,18.816034545999997\n2014-04-02 02:00:00,18.4827538714\n2014-04-02 02:05:00,20.0439871677\n2014-04-02 02:10:00,18.3165944838\n2014-04-02 02:15:00,20.3494185246\n2014-04-02 02:20:00,18.1253498427\n2014-04-02 02:25:00,18.4268598875\n2014-04-02 02:30:00,20.1999899419\n2014-04-02 02:35:00,20.365629651600003\n2014-04-02 02:40:00,18.1159477204\n2014-04-02 02:45:00,20.293507152\n2014-04-02 02:50:00,21.354010101300002\n2014-04-02 02:55:00,20.8892647092\n2014-04-02 03:00:00,18.5247404157\n2014-04-02 03:05:00,20.3698985903\n2014-04-02 03:10:00,20.6890100003\n2014-04-02 03:15:00,18.148924807\n2014-04-02 03:20:00,21.4213906747\n2014-04-02 03:25:00,21.625069589200002\n2014-04-02 03:30:00,21.4018090934\n2014-04-02 03:35:00,21.298525872\n2014-04-02 03:40:00,20.9798607938\n2014-04-02 03:45:00,20.5337281251\n2014-04-02 03:50:00,20.71450802\n2014-04-02 03:55:00,21.2255811733\n2014-04-02 04:00:00,20.6499938334\n2014-04-02 04:05:00,19.3109078267\n2014-04-02 04:10:00,19.5038444086\n2014-04-02 04:15:00,21.588229873499998\n2014-04-02 04:20:00,18.0684883432\n2014-04-02 04:25:00,20.795282325\n2014-04-02 04:30:00,21.819110209699996\n2014-04-02 04:35:00,20.8249126798\n2014-04-02 04:40:00,21.9756479529\n2014-04-02 04:45:00,20.7501796221\n2014-04-02 04:50:00,18.1374521169\n2014-04-02 04:55:00,21.308039526600002\n2014-04-02 05:00:00,19.1385196478\n2014-04-02 05:05:00,19.7842289027\n2014-04-02 05:10:00,19.2483676636\n2014-04-02 05:15:00,19.0742164248\n2014-04-02 05:20:00,19.7256228147\n2014-04-02 05:25:00,19.5150057938\n2014-04-02 05:30:00,20.5333543274\n2014-04-02 05:35:00,21.252604804\n2014-04-02 05:40:00,19.1883546127\n2014-04-02 05:45:00,18.8548846113\n2014-04-02 05:50:00,20.6675810835\n2014-04-02 05:55:00,20.6812802633\n2014-04-02 06:00:00,21.6045249571\n2014-04-02 06:05:00,18.063782745799998\n2014-04-02 06:10:00,21.4121626485\n2014-04-02 06:15:00,20.0840086918\n2014-04-02 06:20:00,20.4852083567\n2014-04-02 06:25:00,18.3654857622\n2014-04-02 06:30:00,19.7304597315\n2014-04-02 06:35:00,18.909209629\n2014-04-02 06:40:00,19.0169001203\n2014-04-02 06:45:00,20.0163804587\n2014-04-02 06:50:00,21.2498238016\n2014-04-02 06:55:00,20.9751237206\n2014-04-02 07:00:00,20.3639998363\n2014-04-02 07:05:00,20.157672770999998\n2014-04-02 07:10:00,19.7092241729\n2014-04-02 07:15:00,21.8908398942\n2014-04-02 07:20:00,20.2407702169\n2014-04-02 07:25:00,19.0158655932\n2014-04-02 07:30:00,18.920363168199998\n2014-04-02 07:35:00,20.4454121231\n2014-04-02 07:40:00,20.091310109200002\n2014-04-02 07:45:00,18.0307912118\n2014-04-02 07:50:00,21.3202614888\n2014-04-02 07:55:00,20.8164894169\n2014-04-02 08:00:00,20.647317158699998\n2014-04-02 08:05:00,18.2751226308\n2014-04-02 08:10:00,19.448223400699998\n2014-04-02 08:15:00,21.741529042899998\n2014-04-02 08:20:00,21.4503569654\n2014-04-02 08:25:00,19.1421717515\n2014-04-02 08:30:00,18.628235536400002\n2014-04-02 08:35:00,19.796351828699997\n2014-04-02 08:40:00,19.4233215147\n2014-04-02 08:45:00,20.7289055068\n2014-04-02 08:50:00,21.8657392403\n2014-04-02 08:55:00,19.4520057999\n2014-04-02 09:00:00,62.046248748100005\n2014-04-02 09:05:00,73.4075505135\n2014-04-02 09:10:00,61.7161163313\n2014-04-02 09:15:00,74.1576162013\n2014-04-02 09:20:00,70.2382802209\n2014-04-02 09:25:00,74.0069732348\n2014-04-02 09:30:00,63.91537173840001\n2014-04-02 09:35:00,61.753517215500004\n2014-04-02 09:40:00,67.8396557046\n2014-04-02 09:45:00,67.3284784382\n2014-04-02 09:50:00,65.7082949163\n2014-04-02 09:55:00,74.2241280517\n2014-04-02 10:00:00,82.6064995231\n2014-04-02 10:05:00,80.1077529717\n2014-04-02 10:10:00,72.3675606862\n2014-04-02 10:15:00,81.2366992956\n2014-04-02 10:20:00,81.1232332969\n2014-04-02 10:25:00,76.4370580545\n2014-04-02 10:30:00,84.1926773188\n2014-04-02 10:35:00,72.4314967322\n2014-04-02 10:40:00,73.9890789686\n2014-04-02 10:45:00,70.8212417452\n2014-04-02 10:50:00,82.1853988709\n2014-04-02 10:55:00,79.4897056722\n2014-04-02 11:00:00,76.5768106216\n2014-04-02 11:05:00,74.1732925058\n2014-04-02 11:10:00,72.2065101345\n2014-04-02 11:15:00,74.2199215234\n2014-04-02 11:20:00,78.77703901539998\n2014-04-02 11:25:00,75.4991025151\n2014-04-02 11:30:00,75.6868525499\n2014-04-02 11:35:00,85.4931665355\n2014-04-02 11:40:00,79.7607495587\n2014-04-02 11:45:00,83.16602338060001\n2014-04-02 11:50:00,72.1359469333\n2014-04-02 11:55:00,77.3755580087\n2014-04-02 12:00:00,79.5711095069\n2014-04-02 12:05:00,74.89269047970001\n2014-04-02 12:10:00,73.83435698550001\n2014-04-02 12:15:00,85.82175062350001\n2014-04-02 12:20:00,86.92646894639999\n2014-04-02 12:25:00,73.1729940801\n2014-04-02 12:30:00,77.4911982414\n2014-04-02 12:35:00,87.22777096629999\n2014-04-02 12:40:00,73.24259102479999\n2014-04-02 12:45:00,82.1995040517\n2014-04-02 12:50:00,87.4504752851\n2014-04-02 12:55:00,87.5463968029\n2014-04-02 13:00:00,79.5204837969\n2014-04-02 13:05:00,74.5860807679\n2014-04-02 13:10:00,75.2152930359\n2014-04-02 13:15:00,86.2129262526\n2014-04-02 13:20:00,86.56614720649998\n2014-04-02 13:25:00,81.7064600441\n2014-04-02 13:30:00,84.2386002741\n2014-04-02 13:35:00,83.8187786875\n2014-04-02 13:40:00,82.5693241729\n2014-04-02 13:45:00,85.21597453439999\n2014-04-02 13:50:00,82.9465940072\n2014-04-02 13:55:00,80.5247063231\n2014-04-02 14:00:00,75.7876638189\n2014-04-02 14:05:00,83.8981829998\n2014-04-02 14:10:00,79.5711862851\n2014-04-02 14:15:00,76.7129845441\n2014-04-02 14:20:00,84.8270685171\n2014-04-02 14:25:00,83.1434265296\n2014-04-02 14:30:00,86.9932571332\n2014-04-02 14:35:00,74.6434831811\n2014-04-02 14:40:00,82.3830739768\n2014-04-02 14:45:00,75.90418791350001\n2014-04-02 14:50:00,86.4531778131\n2014-04-02 14:55:00,73.5884582126\n2014-04-02 15:00:00,82.4977969167\n2014-04-02 15:05:00,84.6565588337\n2014-04-02 15:10:00,77.6779397305\n2014-04-02 15:15:00,87.2653715145\n2014-04-02 15:20:00,85.61086908109999\n2014-04-02 15:25:00,76.7131563416\n2014-04-02 15:30:00,72.11996512510001\n2014-04-02 15:35:00,76.74577805130002\n2014-04-02 15:40:00,76.5002331182\n2014-04-02 15:45:00,86.2386058215\n2014-04-02 15:50:00,87.4730991023\n2014-04-02 15:55:00,73.1263377559\n2014-04-02 16:00:00,79.5405645384\n2014-04-02 16:05:00,80.7731568917\n2014-04-02 16:10:00,73.486445487\n2014-04-02 16:15:00,78.0398135095\n2014-04-02 16:20:00,77.0731706975\n2014-04-02 16:25:00,80.5767469616\n2014-04-02 16:30:00,82.5788958439\n2014-04-02 16:35:00,83.25560191689999\n2014-04-02 16:40:00,74.1879379367\n2014-04-02 16:45:00,85.0070000174\n2014-04-02 16:50:00,82.85651339180001\n2014-04-02 16:55:00,86.2250331156\n2014-04-02 17:00:00,79.1893465422\n2014-04-02 17:05:00,86.3022030635\n2014-04-02 17:10:00,85.8523529904\n2014-04-02 17:15:00,79.0145189762\n2014-04-02 17:20:00,78.0982630549\n2014-04-02 17:25:00,86.92495886030001\n2014-04-02 17:30:00,83.44260371060001\n2014-04-02 17:35:00,86.8518921919\n2014-04-02 17:40:00,84.75156391770001\n2014-04-02 17:45:00,81.7487276371\n2014-04-02 17:50:00,73.8536160723\n2014-04-02 17:55:00,76.6636613224\n2014-04-02 18:00:00,35.000584685300005\n2014-04-02 18:05:00,30.844295509699997\n2014-04-02 18:10:00,29.396825522399997\n2014-04-02 18:15:00,33.3283350788\n2014-04-02 18:20:00,33.4976207975\n2014-04-02 18:25:00,30.626923529499997\n2014-04-02 18:30:00,30.7050947724\n2014-04-02 18:35:00,31.80090900150001\n2014-04-02 18:40:00,28.939443722100002\n2014-04-02 18:45:00,33.851660766799995\n2014-04-02 18:50:00,30.8293623193\n2014-04-02 18:55:00,34.264077274099996\n2014-04-02 19:00:00,23.7557829856\n2014-04-02 19:05:00,23.123079839899997\n2014-04-02 19:10:00,21.6154382188\n2014-04-02 19:15:00,22.473096963400003\n2014-04-02 19:20:00,22.1528338588\n2014-04-02 19:25:00,21.678189661199998\n2014-04-02 19:30:00,23.9596492617\n2014-04-02 19:35:00,22.3261104694\n2014-04-02 19:40:00,23.890598167600004\n2014-04-02 19:45:00,20.6313776324\n2014-04-02 19:50:00,20.7917899124\n2014-04-02 19:55:00,24.5383936208\n2014-04-02 20:00:00,20.8394993728\n2014-04-02 20:05:00,20.5200163364\n2014-04-02 20:10:00,20.5748469877\n2014-04-02 20:15:00,19.3137406667\n2014-04-02 20:20:00,21.3758111207\n2014-04-02 20:25:00,18.7792612094\n2014-04-02 20:30:00,20.7803336795\n2014-04-02 20:35:00,20.7698687416\n2014-04-02 20:40:00,22.176515519099997\n2014-04-02 20:45:00,20.5872445431\n2014-04-02 20:50:00,18.9934085748\n2014-04-02 20:55:00,20.7779971005\n2014-04-02 21:00:00,18.4534640231\n2014-04-02 21:05:00,18.905488136600002\n2014-04-02 21:10:00,18.211431577\n2014-04-02 21:15:00,20.1494295173\n2014-04-02 21:20:00,18.4261534423\n2014-04-02 21:25:00,19.972989837300002\n2014-04-02 21:30:00,21.836092632600003\n2014-04-02 21:35:00,20.9792650199\n2014-04-02 21:40:00,18.397532956\n2014-04-02 21:45:00,18.9875440308\n2014-04-02 21:50:00,20.7939839472\n2014-04-02 21:55:00,21.6823856668\n2014-04-02 22:00:00,18.1490807455\n2014-04-02 22:05:00,21.270204328800002\n2014-04-02 22:10:00,20.266692876700002\n2014-04-02 22:15:00,20.203742282\n2014-04-02 22:20:00,21.8522107229\n2014-04-02 22:25:00,21.0107293954\n2014-04-02 22:30:00,21.4210199182\n2014-04-02 22:35:00,19.4346216116\n2014-04-02 22:40:00,20.2368649113\n2014-04-02 22:45:00,20.4812658575\n2014-04-02 22:50:00,19.3048506343\n2014-04-02 22:55:00,20.3004622426\n2014-04-02 23:00:00,18.9502592674\n2014-04-02 23:05:00,18.577068795\n2014-04-02 23:10:00,19.4996242444\n2014-04-02 23:15:00,20.9611822874\n2014-04-02 23:20:00,21.6689082219\n2014-04-02 23:25:00,19.8346637284\n2014-04-02 23:30:00,20.5752444397\n2014-04-02 23:35:00,18.4156836546\n2014-04-02 23:40:00,21.6220056603\n2014-04-02 23:45:00,20.2783095403\n2014-04-02 23:50:00,21.1254082882\n2014-04-02 23:55:00,21.1818309324\n2014-04-03 00:00:00,19.0259221055\n2014-04-03 00:05:00,20.1166978127\n2014-04-03 00:10:00,21.841919006199998\n2014-04-03 00:15:00,18.3585381793\n2014-04-03 00:20:00,20.7321995921\n2014-04-03 00:25:00,21.8490563121\n2014-04-03 00:30:00,19.2023084322\n2014-04-03 00:35:00,21.4457916856\n2014-04-03 00:40:00,21.7346301816\n2014-04-03 00:45:00,20.9883448376\n2014-04-03 00:50:00,18.925313249200002\n2014-04-03 00:55:00,19.3360028753\n2014-04-03 01:00:00,18.1432371777\n2014-04-03 01:05:00,21.325812937000002\n2014-04-03 01:10:00,21.398444746\n2014-04-03 01:15:00,20.5308412399\n2014-04-03 01:20:00,19.4101114051\n2014-04-03 01:25:00,18.3072441106\n2014-04-03 01:30:00,21.0122304397\n2014-04-03 01:35:00,20.9061047744\n2014-04-03 01:40:00,21.650410086999997\n2014-04-03 01:45:00,20.922128084\n2014-04-03 01:50:00,21.314779769\n2014-04-03 01:55:00,20.9838184716\n2014-04-03 02:00:00,20.5227487532\n2014-04-03 02:05:00,19.7078655768\n2014-04-03 02:10:00,21.6084692346\n2014-04-03 02:15:00,20.6038742876\n2014-04-03 02:20:00,19.5934212879\n2014-04-03 02:25:00,18.3338771807\n2014-04-03 02:30:00,19.1628194236\n2014-04-03 02:35:00,20.1749069393\n2014-04-03 02:40:00,19.1025414801\n2014-04-03 02:45:00,18.8849413917\n2014-04-03 02:50:00,20.1095740564\n2014-04-03 02:55:00,18.6792813836\n2014-04-03 03:00:00,21.2016402533\n2014-04-03 03:05:00,19.9374726054\n2014-04-03 03:10:00,20.2954510959\n2014-04-03 03:15:00,18.589533070399998\n2014-04-03 03:20:00,19.2983053425\n2014-04-03 03:25:00,19.640358733\n2014-04-03 03:30:00,21.2328513221\n2014-04-03 03:35:00,21.0806380923\n2014-04-03 03:40:00,18.8919098992\n2014-04-03 03:45:00,20.4647163264\n2014-04-03 03:50:00,18.9738254311\n2014-04-03 03:55:00,21.952988622800003\n2014-04-03 04:00:00,21.8084955125\n2014-04-03 04:05:00,20.2530588821\n2014-04-03 04:10:00,20.7956102876\n2014-04-03 04:15:00,21.2057215288\n2014-04-03 04:20:00,20.8839936802\n2014-04-03 04:25:00,20.7993147643\n2014-04-03 04:30:00,21.834216031799997\n2014-04-03 04:35:00,20.3858244252\n2014-04-03 04:40:00,20.5452106873\n2014-04-03 04:45:00,21.3970750018\n2014-04-03 04:50:00,20.6795634714\n2014-04-03 04:55:00,20.931730488099998\n2014-04-03 05:00:00,18.9366747448\n2014-04-03 05:05:00,19.4850676965\n2014-04-03 05:10:00,18.5892053828\n2014-04-03 05:15:00,20.0230617693\n2014-04-03 05:20:00,19.8229096027\n2014-04-03 05:25:00,21.9886512571\n2014-04-03 05:30:00,20.444834611300003\n2014-04-03 05:35:00,21.1457792928\n2014-04-03 05:40:00,19.336058683\n2014-04-03 05:45:00,21.3261813254\n2014-04-03 05:50:00,20.460339865999998\n2014-04-03 05:55:00,20.787969326400003\n2014-04-03 06:00:00,19.177723111800002\n2014-04-03 06:05:00,20.1945535668\n2014-04-03 06:10:00,20.536147893699997\n2014-04-03 06:15:00,20.3563787033\n2014-04-03 06:20:00,21.6607748457\n2014-04-03 06:25:00,21.593090658\n2014-04-03 06:30:00,21.8839362315\n2014-04-03 06:35:00,20.669712024000003\n2014-04-03 06:40:00,21.887656520500002\n2014-04-03 06:45:00,21.3299120001\n2014-04-03 06:50:00,19.083328561400002\n2014-04-03 06:55:00,19.709742678199998\n2014-04-03 07:00:00,18.9535697688\n2014-04-03 07:05:00,18.0167886433\n2014-04-03 07:10:00,18.7521950126\n2014-04-03 07:15:00,18.0162423451\n2014-04-03 07:20:00,20.8793538454\n2014-04-03 07:25:00,19.7021371909\n2014-04-03 07:30:00,19.2502989083\n2014-04-03 07:35:00,21.0468835644\n2014-04-03 07:40:00,21.3299470985\n2014-04-03 07:45:00,21.9011981546\n2014-04-03 07:50:00,20.568054338699998\n2014-04-03 07:55:00,19.8461158342\n2014-04-03 08:00:00,19.2210572064\n2014-04-03 08:05:00,18.889272836900002\n2014-04-03 08:10:00,18.8517038019\n2014-04-03 08:15:00,19.6367574989\n2014-04-03 08:20:00,21.967145421199998\n2014-04-03 08:25:00,18.0034147897\n2014-04-03 08:30:00,18.7888235889\n2014-04-03 08:35:00,18.7535719296\n2014-04-03 08:40:00,20.8684779421\n2014-04-03 08:45:00,19.4099389104\n2014-04-03 08:50:00,19.8290432184\n2014-04-03 08:55:00,18.594496521900002\n2014-04-03 09:00:00,66.7079597287\n2014-04-03 09:05:00,62.603517441899996\n2014-04-03 09:10:00,68.4493887153\n2014-04-03 09:15:00,62.5319617692\n2014-04-03 09:20:00,71.950913984\n2014-04-03 09:25:00,68.90578335859999\n2014-04-03 09:30:00,71.0459630833\n2014-04-03 09:35:00,66.8918228585\n2014-04-03 09:40:00,66.3882815881\n2014-04-03 09:45:00,62.535640891099995\n2014-04-03 09:50:00,68.3244362558\n2014-04-03 09:55:00,68.1972294421\n2014-04-03 10:00:00,77.1049437299\n2014-04-03 10:05:00,81.33284501989999\n2014-04-03 10:10:00,82.76046828850001\n2014-04-03 10:15:00,81.4922557552\n2014-04-03 10:20:00,72.0727963284\n2014-04-03 10:25:00,79.4943635841\n2014-04-03 10:30:00,71.0866146003\n2014-04-03 10:35:00,80.6205379011\n2014-04-03 10:40:00,75.7661427786\n2014-04-03 10:45:00,71.8963838013\n2014-04-03 10:50:00,83.2190293003\n2014-04-03 10:55:00,79.3694094219\n2014-04-03 11:00:00,77.2095458902\n2014-04-03 11:05:00,72.0566850652\n2014-04-03 11:10:00,80.1133823592\n2014-04-03 11:15:00,86.2509843714\n2014-04-03 11:20:00,81.0528248593\n2014-04-03 11:25:00,87.0211312159\n2014-04-03 11:30:00,73.738118585\n2014-04-03 11:35:00,80.60632438350001\n2014-04-03 11:40:00,84.2613807635\n2014-04-03 11:45:00,79.9261997878\n2014-04-03 11:50:00,73.01631932560001\n2014-04-03 11:55:00,80.8382189686\n2014-04-03 12:00:00,81.6896611257\n2014-04-03 12:05:00,83.55895675800001\n2014-04-03 12:10:00,84.0783689816\n2014-04-03 12:15:00,84.2311641758\n2014-04-03 12:20:00,82.5159721659\n2014-04-03 12:25:00,75.3624354079\n2014-04-03 12:30:00,78.3736107669\n2014-04-03 12:35:00,84.3167778664\n2014-04-03 12:40:00,87.15012593629999\n2014-04-03 12:45:00,73.17523565569999\n2014-04-03 12:50:00,80.4719045405\n2014-04-03 12:55:00,76.90795591359999\n2014-04-03 13:00:00,75.5881567965\n2014-04-03 13:05:00,80.0737486233\n2014-04-03 13:10:00,81.6778220658\n2014-04-03 13:15:00,72.1390381773\n2014-04-03 13:20:00,84.463029162\n2014-04-03 13:25:00,85.0976857528\n2014-04-03 13:30:00,87.4271856315\n2014-04-03 13:35:00,74.8723260597\n2014-04-03 13:40:00,81.4932779159\n2014-04-03 13:45:00,78.8070877342\n2014-04-03 13:50:00,77.3386798859\n2014-04-03 13:55:00,81.0306831905\n2014-04-03 14:00:00,84.5140726214\n2014-04-03 14:05:00,72.3653708306\n2014-04-03 14:10:00,87.5062013018\n2014-04-03 14:15:00,84.9540273822\n2014-04-03 14:20:00,84.0144263723\n2014-04-03 14:25:00,84.1621581374\n2014-04-03 14:30:00,78.2212165553\n2014-04-03 14:35:00,84.0218955689\n2014-04-03 14:40:00,78.1845702981\n2014-04-03 14:45:00,86.37516306639999\n2014-04-03 14:50:00,74.83196602609999\n2014-04-03 14:55:00,76.6738782646\n2014-04-03 15:00:00,80.8206247977\n2014-04-03 15:05:00,77.1066363434\n2014-04-03 15:10:00,78.7870395619\n2014-04-03 15:15:00,79.8779961943\n2014-04-03 15:20:00,85.7008308451\n2014-04-03 15:25:00,80.3703044954\n2014-04-03 15:30:00,77.798610704\n2014-04-03 15:35:00,75.96304937229999\n2014-04-03 15:40:00,78.538061688\n2014-04-03 15:45:00,80.2510072536\n2014-04-03 15:50:00,83.937031912\n2014-04-03 15:55:00,73.9360706257\n2014-04-03 16:00:00,75.545601964\n2014-04-03 16:05:00,78.0743143509\n2014-04-03 16:10:00,77.76622517050001\n2014-04-03 16:15:00,78.2678191272\n2014-04-03 16:20:00,84.6961776173\n2014-04-03 16:25:00,77.18632224939999\n2014-04-03 16:30:00,80.0302172281\n2014-04-03 16:35:00,81.98235511930001\n2014-04-03 16:40:00,75.7147114304\n2014-04-03 16:45:00,83.498965876\n2014-04-03 16:50:00,80.7536260686\n2014-04-03 16:55:00,79.1483466434\n2014-04-03 17:00:00,84.9565118045\n2014-04-03 17:05:00,75.8958950029\n2014-04-03 17:10:00,86.1307824556\n2014-04-03 17:15:00,80.97674867079998\n2014-04-03 17:20:00,81.74676667930001\n2014-04-03 17:25:00,86.0009104023\n2014-04-03 17:30:00,85.0812903344\n2014-04-03 17:35:00,81.6249617572\n2014-04-03 17:40:00,84.05097098600001\n2014-04-03 17:45:00,78.9330815334\n2014-04-03 17:50:00,80.7580130449\n2014-04-03 17:55:00,72.993094158\n2014-04-03 18:00:00,29.3750850352\n2014-04-03 18:05:00,34.108316038000005\n2014-04-03 18:10:00,29.1818929934\n2014-04-03 18:15:00,29.8841486663\n2014-04-03 18:20:00,33.8933225098\n2014-04-03 18:25:00,28.807328553\n2014-04-03 18:30:00,30.607381828\n2014-04-03 18:35:00,32.5378411628\n2014-04-03 18:40:00,32.6108733001\n2014-04-03 18:45:00,33.7737721281\n2014-04-03 18:50:00,32.0379218775\n2014-04-03 18:55:00,32.0601658094\n2014-04-03 19:00:00,23.409390094299997\n2014-04-03 19:05:00,22.393836367\n2014-04-03 19:10:00,22.8860388123\n2014-04-03 19:15:00,24.1820264992\n2014-04-03 19:20:00,21.9584993095\n2014-04-03 19:25:00,21.885359117100002\n2014-04-03 19:30:00,20.1758983768\n2014-04-03 19:35:00,22.908148394899996\n2014-04-03 19:40:00,20.2933770319\n2014-04-03 19:45:00,22.4185840042\n2014-04-03 19:50:00,23.76296607130001\n2014-04-03 19:55:00,22.623645154899997\n2014-04-03 20:00:00,19.5364294983\n2014-04-03 20:05:00,21.6521455944\n2014-04-03 20:10:00,19.5367606143\n2014-04-03 20:15:00,21.4344979175\n2014-04-03 20:20:00,20.9316183813\n2014-04-03 20:25:00,19.128304601900002\n2014-04-03 20:30:00,22.1394280857\n2014-04-03 20:35:00,19.2538362943\n2014-04-03 20:40:00,22.4853483859\n2014-04-03 20:45:00,18.46194354\n2014-04-03 20:50:00,19.511227678599997\n2014-04-03 20:55:00,19.2506275466\n2014-04-03 21:00:00,18.1426422698\n2014-04-03 21:05:00,21.0299330128\n2014-04-03 21:10:00,20.8734169327\n2014-04-03 21:15:00,21.2710169439\n2014-04-03 21:20:00,19.118122751199998\n2014-04-03 21:25:00,19.8722718549\n2014-04-03 21:30:00,20.735509015399998\n2014-04-03 21:35:00,19.8539175223\n2014-04-03 21:40:00,20.889091685\n2014-04-03 21:45:00,20.634465872699998\n2014-04-03 21:50:00,18.5471924045\n2014-04-03 21:55:00,21.2255684603\n2014-04-03 22:00:00,20.9027528233\n2014-04-03 22:05:00,20.6431359444\n2014-04-03 22:10:00,18.6382499754\n2014-04-03 22:15:00,19.0902948922\n2014-04-03 22:20:00,19.5914979165\n2014-04-03 22:25:00,19.138073407\n2014-04-03 22:30:00,18.9293959449\n2014-04-03 22:35:00,21.241803243699998\n2014-04-03 22:40:00,20.5726597872\n2014-04-03 22:45:00,20.2813399292\n2014-04-03 22:50:00,18.9219584925\n2014-04-03 22:55:00,21.6931116524\n2014-04-03 23:00:00,18.7683349831\n2014-04-03 23:05:00,21.1838702515\n2014-04-03 23:10:00,21.8708890693\n2014-04-03 23:15:00,20.9123853221\n2014-04-03 23:20:00,21.975653614099997\n2014-04-03 23:25:00,20.6081604731\n2014-04-03 23:30:00,18.8734643821\n2014-04-03 23:35:00,18.818890506400002\n2014-04-03 23:40:00,19.3019624005\n2014-04-03 23:45:00,18.031981555\n2014-04-03 23:50:00,20.7307734227\n2014-04-03 23:55:00,19.0783334735\n2014-04-04 00:00:00,21.2607329292\n2014-04-04 00:05:00,19.4366906022\n2014-04-04 00:10:00,19.9198259739\n2014-04-04 00:15:00,21.862755666199998\n2014-04-04 00:20:00,18.968688492200002\n2014-04-04 00:25:00,20.8850163897\n2014-04-04 00:30:00,21.0204711572\n2014-04-04 00:35:00,18.8839926301\n2014-04-04 00:40:00,20.003987346400002\n2014-04-04 00:45:00,19.4008077013\n2014-04-04 00:50:00,21.0876249736\n2014-04-04 00:55:00,20.4899332761\n2014-04-04 01:00:00,19.9039322194\n2014-04-04 01:05:00,21.1174530602\n2014-04-04 01:10:00,18.94062228\n2014-04-04 01:15:00,21.0144875223\n2014-04-04 01:20:00,21.4614972484\n2014-04-04 01:25:00,21.514486387199998\n2014-04-04 01:30:00,21.1346943721\n2014-04-04 01:35:00,19.632056668\n2014-04-04 01:40:00,21.927232090900002\n2014-04-04 01:45:00,19.5183745753\n2014-04-04 01:50:00,20.5545015964\n2014-04-04 01:55:00,18.6442967123\n2014-04-04 02:00:00,21.921795594499997\n2014-04-04 02:05:00,20.8159436875\n2014-04-04 02:10:00,21.013510180999997\n2014-04-04 02:15:00,18.2631068136\n2014-04-04 02:20:00,21.0536712569\n2014-04-04 02:25:00,21.0988937169\n2014-04-04 02:30:00,20.687090905399998\n2014-04-04 02:35:00,19.1676384552\n2014-04-04 02:40:00,19.958760168599998\n2014-04-04 02:45:00,18.4417374852\n2014-04-04 02:50:00,19.8863482658\n2014-04-04 02:55:00,18.9752954104\n2014-04-04 03:00:00,19.396387945999997\n2014-04-04 03:05:00,18.650401633599998\n2014-04-04 03:10:00,18.920217470999997\n2014-04-04 03:15:00,18.3062745673\n2014-04-04 03:20:00,21.679605465700003\n2014-04-04 03:25:00,20.1216427519\n2014-04-04 03:30:00,19.586967885099998\n2014-04-04 03:35:00,20.1401168511\n2014-04-04 03:40:00,20.5131729139\n2014-04-04 03:45:00,21.6875151735\n2014-04-04 03:50:00,18.7147718091\n2014-04-04 03:55:00,19.1822099945\n2014-04-04 04:00:00,21.9031573454\n2014-04-04 04:05:00,19.484771946600002\n2014-04-04 04:10:00,18.090246603\n2014-04-04 04:15:00,18.5905739705\n2014-04-04 04:20:00,18.105354807\n2014-04-04 04:25:00,21.9596925697\n2014-04-04 04:30:00,19.115483396\n2014-04-04 04:35:00,21.6941710277\n2014-04-04 04:40:00,21.983545103\n2014-04-04 04:45:00,20.3993648846\n2014-04-04 04:50:00,18.1327852603\n2014-04-04 04:55:00,18.326366521500002\n2014-04-04 05:00:00,19.9263562204\n2014-04-04 05:05:00,19.6246880516\n2014-04-04 05:10:00,20.4247092231\n2014-04-04 05:15:00,19.7553912388\n2014-04-04 05:20:00,21.7363073971\n2014-04-04 05:25:00,20.1389588617\n2014-04-04 05:30:00,20.7749042458\n2014-04-04 05:35:00,21.5859410906\n2014-04-04 05:40:00,18.5874875033\n2014-04-04 05:45:00,18.9189386165\n2014-04-04 05:50:00,18.4292746419\n2014-04-04 05:55:00,18.5585535969\n2014-04-04 06:00:00,20.0503358677\n2014-04-04 06:05:00,19.284717035899998\n2014-04-04 06:10:00,19.6926913581\n2014-04-04 06:15:00,21.9299593272\n2014-04-04 06:20:00,18.6268173912\n2014-04-04 06:25:00,20.163248283199998\n2014-04-04 06:30:00,18.3954846202\n2014-04-04 06:35:00,19.2739852531\n2014-04-04 06:40:00,20.1101036947\n2014-04-04 06:45:00,21.7865269839\n2014-04-04 06:50:00,19.5649128851\n2014-04-04 06:55:00,18.2596267849\n2014-04-04 07:00:00,19.5526457918\n2014-04-04 07:05:00,18.5829647035\n2014-04-04 07:10:00,18.9199584532\n2014-04-04 07:15:00,20.4723624927\n2014-04-04 07:20:00,18.2696954648\n2014-04-04 07:25:00,19.858895025\n2014-04-04 07:30:00,20.437846344\n2014-04-04 07:35:00,19.6874335695\n2014-04-04 07:40:00,18.0765054025\n2014-04-04 07:45:00,21.9420774276\n2014-04-04 07:50:00,19.468463069400002\n2014-04-04 07:55:00,21.1143087477\n2014-04-04 08:00:00,19.302585968699997\n2014-04-04 08:05:00,19.900067028\n2014-04-04 08:10:00,19.5538545704\n2014-04-04 08:15:00,19.370156918\n2014-04-04 08:20:00,18.0874055088\n2014-04-04 08:25:00,19.4400837514\n2014-04-04 08:30:00,21.557959961599998\n2014-04-04 08:35:00,20.7615733544\n2014-04-04 08:40:00,18.5816914364\n2014-04-04 08:45:00,20.3646200185\n2014-04-04 08:50:00,21.5689234398\n2014-04-04 08:55:00,20.8001361639\n2014-04-04 09:00:00,63.2221077361\n2014-04-04 09:05:00,73.0025219556\n2014-04-04 09:10:00,65.3009985807\n2014-04-04 09:15:00,67.3754355626\n2014-04-04 09:20:00,68.3555415318\n2014-04-04 09:25:00,72.7668898195\n2014-04-04 09:30:00,73.869861934\n2014-04-04 09:35:00,73.843279138\n2014-04-04 09:40:00,61.3081768654\n2014-04-04 09:45:00,73.737683404\n2014-04-04 09:50:00,61.9396627376\n2014-04-04 09:55:00,64.8145217327\n2014-04-04 10:00:00,77.8326115054\n2014-04-04 10:05:00,77.2884466933\n2014-04-04 10:10:00,79.2250960011\n2014-04-04 10:15:00,77.28100547\n2014-04-04 10:20:00,84.341510548\n2014-04-04 10:25:00,73.5733181243\n2014-04-04 10:30:00,74.09286325149999\n2014-04-04 10:35:00,84.129852762\n2014-04-04 10:40:00,71.0309972533\n2014-04-04 10:45:00,79.300383956\n2014-04-04 10:50:00,80.4205419761\n2014-04-04 10:55:00,77.6860075476\n2014-04-04 11:00:00,82.6090638008\n2014-04-04 11:05:00,74.3154898902\n2014-04-04 11:10:00,85.12826303\n2014-04-04 11:15:00,73.7949685653\n2014-04-04 11:20:00,77.9425211144\n2014-04-04 11:25:00,72.7648968912\n2014-04-04 11:30:00,80.2390369975\n2014-04-04 11:35:00,82.2196373213\n2014-04-04 11:40:00,86.53718888459998\n2014-04-04 11:45:00,83.32640285949999\n2014-04-04 11:50:00,80.17370078329998\n2014-04-04 11:55:00,86.4003410411\n2014-04-04 12:00:00,79.5594034214\n2014-04-04 12:05:00,80.882115301\n2014-04-04 12:10:00,81.439731351\n2014-04-04 12:15:00,78.4654040034\n2014-04-04 12:20:00,85.3132241814\n2014-04-04 12:25:00,74.87285964350001\n2014-04-04 12:30:00,80.7804220759\n2014-04-04 12:35:00,83.4554652205\n2014-04-04 12:40:00,86.3598624075\n2014-04-04 12:45:00,86.03932310969999\n2014-04-04 12:50:00,80.0436768173\n2014-04-04 12:55:00,82.19183451880002\n2014-04-04 13:00:00,78.2890099052\n2014-04-04 13:05:00,79.4717664035\n2014-04-04 13:10:00,86.4794926205\n2014-04-04 13:15:00,86.8704099877\n2014-04-04 13:20:00,86.3059065391\n2014-04-04 13:25:00,74.1961224449\n2014-04-04 13:30:00,85.5808000186\n2014-04-04 13:35:00,87.15289797959998\n2014-04-04 13:40:00,77.7613279144\n2014-04-04 13:45:00,80.279069029\n2014-04-04 13:50:00,84.4452523672\n2014-04-04 13:55:00,80.973811821\n2014-04-04 14:00:00,87.89151735200001\n2014-04-04 14:05:00,79.2876078546\n2014-04-04 14:10:00,83.4190790713\n2014-04-04 14:15:00,84.6773935331\n2014-04-04 14:20:00,79.90177118300001\n2014-04-04 14:25:00,85.70762672779999\n2014-04-04 14:30:00,80.7345980126\n2014-04-04 14:35:00,78.58264060100001\n2014-04-04 14:40:00,73.721639973\n2014-04-04 14:45:00,78.29085908\n2014-04-04 14:50:00,83.7389636125\n2014-04-04 14:55:00,86.7364190389\n2014-04-04 15:00:00,76.0261406038\n2014-04-04 15:05:00,77.6830225131\n2014-04-04 15:10:00,74.4626610573\n2014-04-04 15:15:00,83.0507690126\n2014-04-04 15:20:00,87.3621761952\n2014-04-04 15:25:00,82.25444586729999\n2014-04-04 15:30:00,81.8724384971\n2014-04-04 15:35:00,80.855062672\n2014-04-04 15:40:00,73.4145870642\n2014-04-04 15:45:00,83.67125797109999\n2014-04-04 15:50:00,81.63200902199999\n2014-04-04 15:55:00,82.58283549890001\n2014-04-04 16:00:00,86.38081163700001\n2014-04-04 16:05:00,84.5432102697\n2014-04-04 16:10:00,84.49448180479999\n2014-04-04 16:15:00,86.834773579\n2014-04-04 16:20:00,87.8387905726\n2014-04-04 16:25:00,81.3003676144\n2014-04-04 16:30:00,73.7419642717\n2014-04-04 16:35:00,79.3459261799\n2014-04-04 16:40:00,84.6014559083\n2014-04-04 16:45:00,72.4434661045\n2014-04-04 16:50:00,72.9100590261\n2014-04-04 16:55:00,73.074384215\n2014-04-04 17:00:00,83.6965399938\n2014-04-04 17:05:00,80.01863532979999\n2014-04-04 17:10:00,77.90233718180001\n2014-04-04 17:15:00,73.6898444273\n2014-04-04 17:20:00,83.71581185640001\n2014-04-04 17:25:00,77.1362873485\n2014-04-04 17:30:00,76.2451558429\n2014-04-04 17:35:00,82.437075569\n2014-04-04 17:40:00,80.944143199\n2014-04-04 17:45:00,77.79854039439999\n2014-04-04 17:50:00,82.2637679436\n2014-04-04 17:55:00,76.3395150118\n2014-04-04 18:00:00,33.886907168\n2014-04-04 18:05:00,30.2676354706\n2014-04-04 18:10:00,29.8165555257\n2014-04-04 18:15:00,33.8076057297\n2014-04-04 18:20:00,33.330502597\n2014-04-04 18:25:00,29.9688836905\n2014-04-04 18:30:00,29.5439671448\n2014-04-04 18:35:00,34.1657476065\n2014-04-04 18:40:00,33.7702238022\n2014-04-04 18:45:00,30.8944412599\n2014-04-04 18:50:00,33.0124570742\n2014-04-04 18:55:00,29.5946195117\n2014-04-04 19:00:00,22.431572281999998\n2014-04-04 19:05:00,20.2439105979\n2014-04-04 19:10:00,21.9143752244\n2014-04-04 19:15:00,20.4952947159\n2014-04-04 19:20:00,22.2886581444\n2014-04-04 19:25:00,22.0491325683\n2014-04-04 19:30:00,22.1508437042\n2014-04-04 19:35:00,20.3630831161\n2014-04-04 19:40:00,21.7800400142\n2014-04-04 19:45:00,23.5490463521\n2014-04-04 19:50:00,21.812735196\n2014-04-04 19:55:00,23.363969066\n2014-04-04 20:00:00,19.9453846127\n2014-04-04 20:05:00,20.1655885104\n2014-04-04 20:10:00,20.7417018452\n2014-04-04 20:15:00,22.3259929452\n2014-04-04 20:20:00,18.8778921629\n2014-04-04 20:25:00,18.5668145736\n2014-04-04 20:30:00,20.9221923738\n2014-04-04 20:35:00,22.3195014084\n2014-04-04 20:40:00,22.4859056811\n2014-04-04 20:45:00,20.415136512300002\n2014-04-04 20:50:00,20.3492620758\n2014-04-04 20:55:00,21.0737713521\n2014-04-04 21:00:00,20.319607166500003\n2014-04-04 21:05:00,20.6349266707\n2014-04-04 21:10:00,21.5991784383\n2014-04-04 21:15:00,21.0859537048\n2014-04-04 21:20:00,20.0834495635\n2014-04-04 21:25:00,19.9427255848\n2014-04-04 21:30:00,20.657087297100002\n2014-04-04 21:35:00,19.9179746496\n2014-04-04 21:40:00,19.9263067199\n2014-04-04 21:45:00,18.1519366361\n2014-04-04 21:50:00,18.7859985351\n2014-04-04 21:55:00,20.0498339728\n2014-04-04 22:00:00,21.311052815\n2014-04-04 22:05:00,19.1332583292\n2014-04-04 22:10:00,20.1098606734\n2014-04-04 22:15:00,19.3984529839\n2014-04-04 22:20:00,18.4368983964\n2014-04-04 22:25:00,21.8541537877\n2014-04-04 22:30:00,21.4392574181\n2014-04-04 22:35:00,18.3315510998\n2014-04-04 22:40:00,20.8991930227\n2014-04-04 22:45:00,19.4089343147\n2014-04-04 22:50:00,22.0004994407\n2014-04-04 22:55:00,19.2280352802\n2014-04-04 23:00:00,18.9585931307\n2014-04-04 23:05:00,20.2754543312\n2014-04-04 23:10:00,21.3446020282\n2014-04-04 23:15:00,18.7736793399\n2014-04-04 23:20:00,20.8416118982\n2014-04-04 23:25:00,18.249129490999998\n2014-04-04 23:30:00,21.6799007122\n2014-04-04 23:35:00,18.3278179283\n2014-04-04 23:40:00,21.6610836329\n2014-04-04 23:45:00,19.9670619358\n2014-04-04 23:50:00,19.7961645832\n2014-04-04 23:55:00,21.897431815700003\n2014-04-05 00:00:00,21.9615367108\n2014-04-05 00:05:00,20.6007125038\n2014-04-05 00:10:00,18.5084771674\n2014-04-05 00:15:00,20.0246803426\n2014-04-05 00:20:00,20.1166524038\n2014-04-05 00:25:00,20.0577857125\n2014-04-05 00:30:00,20.2779673541\n2014-04-05 00:35:00,18.0748988552\n2014-04-05 00:40:00,20.8449091259\n2014-04-05 00:45:00,20.8495772078\n2014-04-05 00:50:00,18.4618791007\n2014-04-05 00:55:00,20.2809577698\n2014-04-05 01:00:00,20.2734447297\n2014-04-05 01:05:00,20.729801680799998\n2014-04-05 01:10:00,18.341590768499998\n2014-04-05 01:15:00,20.506013229100002\n2014-04-05 01:20:00,19.123007803\n2014-04-05 01:25:00,20.028011962\n2014-04-05 01:30:00,21.0932942108\n2014-04-05 01:35:00,20.8225837455\n2014-04-05 01:40:00,18.4756120707\n2014-04-05 01:45:00,20.3647391485\n2014-04-05 01:50:00,21.8764661238\n2014-04-05 01:55:00,18.6270777493\n2014-04-05 02:00:00,21.4116283509\n2014-04-05 02:05:00,20.8101923222\n2014-04-05 02:10:00,21.096013251600002\n2014-04-05 02:15:00,19.1278333086\n2014-04-05 02:20:00,19.1515557175\n2014-04-05 02:25:00,21.6240778231\n2014-04-05 02:30:00,19.4393281284\n2014-04-05 02:35:00,18.252061562799998\n2014-04-05 02:40:00,20.4023868143\n2014-04-05 02:45:00,18.4992706762\n2014-04-05 02:50:00,21.1863849656\n2014-04-05 02:55:00,20.56698577\n2014-04-05 03:00:00,21.4989060209\n2014-04-05 03:05:00,21.1393489991\n2014-04-05 03:10:00,18.448454593399997\n2014-04-05 03:15:00,19.5242827057\n2014-04-05 03:20:00,21.0982409997\n2014-04-05 03:25:00,19.6693658931\n2014-04-05 03:30:00,21.8894619391\n2014-04-05 03:35:00,20.9429617996\n2014-04-05 03:40:00,18.061999666800002\n2014-04-05 03:45:00,21.5199427662\n2014-04-05 03:50:00,18.4032191395\n2014-04-05 03:55:00,18.5620948967\n2014-04-05 04:00:00,20.9379696024\n2014-04-05 04:05:00,21.4598742377\n2014-04-05 04:10:00,20.1453985116\n2014-04-05 04:15:00,19.156198931800002\n2014-04-05 04:20:00,19.405262180999998\n2014-04-05 04:25:00,19.3715573184\n2014-04-05 04:30:00,19.3067124152\n2014-04-05 04:35:00,18.9716386873\n2014-04-05 04:40:00,20.435468378499998\n2014-04-05 04:45:00,21.601621274299998\n2014-04-05 04:50:00,19.2283296523\n2014-04-05 04:55:00,18.7467771898\n2014-04-05 05:00:00,21.354310665499998\n2014-04-05 05:05:00,20.9671333236\n2014-04-05 05:10:00,21.723348126199998\n2014-04-05 05:15:00,18.6620789424\n2014-04-05 05:20:00,18.5770052565\n2014-04-05 05:25:00,20.1657175772\n2014-04-05 05:30:00,20.457734619300002\n2014-04-05 05:35:00,19.9206937674\n2014-04-05 05:40:00,20.3958665453\n2014-04-05 05:45:00,18.721519075499998\n2014-04-05 05:50:00,19.9184550167\n2014-04-05 05:55:00,20.6323702438\n2014-04-05 06:00:00,19.730825797\n2014-04-05 06:05:00,20.717789343299998\n2014-04-05 06:10:00,19.8047651222\n2014-04-05 06:15:00,19.3343983234\n2014-04-05 06:20:00,19.2144201883\n2014-04-05 06:25:00,19.643608236\n2014-04-05 06:30:00,18.0923584907\n2014-04-05 06:35:00,20.674100553800002\n2014-04-05 06:40:00,21.3804225639\n2014-04-05 06:45:00,19.4185083778\n2014-04-05 06:50:00,18.1841325446\n2014-04-05 06:55:00,21.9471023895\n2014-04-05 07:00:00,19.054793021800002\n2014-04-05 07:05:00,18.5064844868\n2014-04-05 07:10:00,19.4790100319\n2014-04-05 07:15:00,20.9542281625\n2014-04-05 07:20:00,19.1756663876\n2014-04-05 07:25:00,20.2988128157\n2014-04-05 07:30:00,19.6622399777\n2014-04-05 07:35:00,18.4710559691\n2014-04-05 07:40:00,19.32114805\n2014-04-05 07:45:00,20.8994820229\n2014-04-05 07:50:00,20.448015589300002\n2014-04-05 07:55:00,18.4791135195\n2014-04-05 08:00:00,18.653289638900002\n2014-04-05 08:05:00,20.5629334372\n2014-04-05 08:10:00,21.2536616573\n2014-04-05 08:15:00,19.3978979838\n2014-04-05 08:20:00,20.3812430074\n2014-04-05 08:25:00,18.682574355\n2014-04-05 08:30:00,19.245505347599998\n2014-04-05 08:35:00,18.0810808227\n2014-04-05 08:40:00,21.073103791199998\n2014-04-05 08:45:00,19.6040392791\n2014-04-05 08:50:00,21.2645022946\n2014-04-05 08:55:00,20.8334919841\n2014-04-05 09:00:00,72.47092201390001\n2014-04-05 09:05:00,65.0849579063\n2014-04-05 09:10:00,63.7174787338\n2014-04-05 09:15:00,74.4179172841\n2014-04-05 09:20:00,70.9556579038\n2014-04-05 09:25:00,72.5429748438\n2014-04-05 09:30:00,61.3786138825\n2014-04-05 09:35:00,66.020678036\n2014-04-05 09:40:00,71.3023069919\n2014-04-05 09:45:00,62.2605665287\n2014-04-05 09:50:00,68.9158230421\n2014-04-05 09:55:00,67.0353896374\n2014-04-05 10:00:00,70.1134081908\n2014-04-05 10:05:00,73.5023409569\n2014-04-05 10:10:00,74.2599716703\n2014-04-05 10:15:00,71.5760663673\n2014-04-05 10:20:00,79.6414528392\n2014-04-05 10:25:00,73.6020150394\n2014-04-05 10:30:00,74.1486546341\n2014-04-05 10:35:00,83.7806630441\n2014-04-05 10:40:00,77.0897503986\n2014-04-05 10:45:00,75.925828841\n2014-04-05 10:50:00,81.0744785146\n2014-04-05 10:55:00,83.9572061276\n2014-04-05 11:00:00,71.9661778915\n2014-04-05 11:05:00,78.69679061560001\n2014-04-05 11:10:00,81.2818666871\n2014-04-05 11:15:00,76.6344275126\n2014-04-05 11:20:00,83.8523724126\n2014-04-05 11:25:00,87.0183713256\n2014-04-05 11:30:00,86.5722688328\n2014-04-05 11:35:00,75.7981863063\n2014-04-05 11:40:00,75.1676839803\n2014-04-05 11:45:00,86.7959294054\n2014-04-05 11:50:00,78.8620274641\n2014-04-05 11:55:00,74.8807669879\n2014-04-05 12:00:00,83.2119770764\n2014-04-05 12:05:00,76.4588643122\n2014-04-05 12:10:00,76.1844204592\n2014-04-05 12:15:00,85.9647031076\n2014-04-05 12:20:00,74.5101468543\n2014-04-05 12:25:00,72.9426507989\n2014-04-05 12:30:00,76.2154146631\n2014-04-05 12:35:00,81.6130732535\n2014-04-05 12:40:00,73.8806423677\n2014-04-05 12:45:00,79.4500601387\n2014-04-05 12:50:00,81.9389488943\n2014-04-05 12:55:00,85.4770961312\n2014-04-05 13:00:00,75.65975076\n2014-04-05 13:05:00,85.0571225642\n2014-04-05 13:10:00,75.74031813810001\n2014-04-05 13:15:00,82.80838587630002\n2014-04-05 13:20:00,78.8718433572\n2014-04-05 13:25:00,73.8171795021\n2014-04-05 13:30:00,83.40819263350001\n2014-04-05 13:35:00,75.4660856883\n2014-04-05 13:40:00,74.8080165824\n2014-04-05 13:45:00,77.7145108974\n2014-04-05 13:50:00,82.4328552816\n2014-04-05 13:55:00,75.7257651142\n2014-04-05 14:00:00,74.9349875684\n2014-04-05 14:05:00,72.155794367\n2014-04-05 14:10:00,79.5424713317\n2014-04-05 14:15:00,78.8545439092\n2014-04-05 14:20:00,75.73824828779999\n2014-04-05 14:25:00,72.8549374193\n2014-04-05 14:30:00,78.864308325\n2014-04-05 14:35:00,84.6072204356\n2014-04-05 14:40:00,83.4405087646\n2014-04-05 14:45:00,85.76860114729999\n2014-04-05 14:50:00,72.1498596439\n2014-04-05 14:55:00,87.4585108588\n2014-04-05 15:00:00,77.4618524011\n2014-04-05 15:05:00,87.8455214124\n2014-04-05 15:10:00,76.0411813673\n2014-04-05 15:15:00,79.5438185733\n2014-04-05 15:20:00,77.6620972619\n2014-04-05 15:25:00,77.6914255951\n2014-04-05 15:30:00,85.4756930054\n2014-04-05 15:35:00,83.9418971858\n2014-04-05 15:40:00,87.8735793692\n2014-04-05 15:45:00,81.8154494876\n2014-04-05 15:50:00,79.4113433141\n2014-04-05 15:55:00,73.44047677180001\n2014-04-05 16:00:00,87.94481385790002\n2014-04-05 16:05:00,80.8243352639\n2014-04-05 16:10:00,83.2074797564\n2014-04-05 16:15:00,78.5077274599\n2014-04-05 16:20:00,80.763296265\n2014-04-05 16:25:00,87.08107651430002\n2014-04-05 16:30:00,74.6625676545\n2014-04-05 16:35:00,76.6778141276\n2014-04-05 16:40:00,74.4328127332\n2014-04-05 16:45:00,84.67529188399999\n2014-04-05 16:50:00,72.9925840207\n2014-04-05 16:55:00,73.3059656499\n2014-04-05 17:00:00,76.7758763227\n2014-04-05 17:05:00,80.2269800876\n2014-04-05 17:10:00,78.5003666648\n2014-04-05 17:15:00,72.7170330474\n2014-04-05 17:20:00,87.3198313951\n2014-04-05 17:25:00,87.2458788233\n2014-04-05 17:30:00,76.4696718075\n2014-04-05 17:35:00,83.7043777018\n2014-04-05 17:40:00,81.2571753794\n2014-04-05 17:45:00,75.79959801300001\n2014-04-05 17:50:00,76.1947155691\n2014-04-05 17:55:00,79.8584201233\n2014-04-05 18:00:00,31.4831103808\n2014-04-05 18:05:00,30.6638618132\n2014-04-05 18:10:00,33.9680676945\n2014-04-05 18:15:00,31.8813565517\n2014-04-05 18:20:00,32.991021265\n2014-04-05 18:25:00,30.0113446389\n2014-04-05 18:30:00,32.2144428549\n2014-04-05 18:35:00,30.83504079610001\n2014-04-05 18:40:00,32.1690409301\n2014-04-05 18:45:00,33.7972788448\n2014-04-05 18:50:00,33.7210380701\n2014-04-05 18:55:00,31.067006374600002\n2014-04-05 19:00:00,23.270360208000003\n2014-04-05 19:05:00,24.3769776405\n2014-04-05 19:10:00,22.9629973384\n2014-04-05 19:15:00,20.8248762104\n2014-04-05 19:20:00,23.205093386199998\n2014-04-05 19:25:00,20.629970519100002\n2014-04-05 19:30:00,24.0670533111\n2014-04-05 19:35:00,22.4746377883\n2014-04-05 19:40:00,21.8854292981\n2014-04-05 19:45:00,20.4153884241\n2014-04-05 19:50:00,21.865909931500006\n2014-04-05 19:55:00,24.2063645444\n2014-04-05 20:00:00,18.5179461306\n2014-04-05 20:05:00,20.3761586098\n2014-04-05 20:10:00,22.246023274200002\n2014-04-05 20:15:00,20.0492684944\n2014-04-05 20:20:00,20.1858073736\n2014-04-05 20:25:00,20.8017817365\n2014-04-05 20:30:00,20.3281910744\n2014-04-05 20:35:00,19.1225922978\n2014-04-05 20:40:00,18.508003265899998\n2014-04-05 20:45:00,20.9297882999\n2014-04-05 20:50:00,22.2036235139\n2014-04-05 20:55:00,18.8676672625\n2014-04-05 21:00:00,18.9342611229\n2014-04-05 21:05:00,19.574426301600003\n2014-04-05 21:10:00,21.3368967147\n2014-04-05 21:15:00,19.1686110171\n2014-04-05 21:20:00,21.6315530088\n2014-04-05 21:25:00,18.307286645\n2014-04-05 21:30:00,21.868292798699997\n2014-04-05 21:35:00,20.3401546056\n2014-04-05 21:40:00,20.734159194700002\n2014-04-05 21:45:00,19.5642176811\n2014-04-05 21:50:00,21.2293913804\n2014-04-05 21:55:00,18.755863026500002\n2014-04-05 22:00:00,18.2131151136\n2014-04-05 22:05:00,19.6008665479\n2014-04-05 22:10:00,21.4353410369\n2014-04-05 22:15:00,21.0398862553\n2014-04-05 22:20:00,20.087889751\n2014-04-05 22:25:00,20.3080279876\n2014-04-05 22:30:00,18.5373500845\n2014-04-05 22:35:00,21.383234241\n2014-04-05 22:40:00,21.1681406466\n2014-04-05 22:45:00,20.6456824117\n2014-04-05 22:50:00,19.8838343091\n2014-04-05 22:55:00,21.878820586\n2014-04-05 23:00:00,21.5202589819\n2014-04-05 23:05:00,20.5816728947\n2014-04-05 23:10:00,19.4909455321\n2014-04-05 23:15:00,20.476019753800003\n2014-04-05 23:20:00,20.3056616428\n2014-04-05 23:25:00,19.5807267273\n2014-04-05 23:30:00,19.2303874105\n2014-04-05 23:35:00,19.631811751300003\n2014-04-05 23:40:00,20.2995423861\n2014-04-05 23:45:00,19.7163241845\n2014-04-05 23:50:00,19.057956376099998\n2014-04-05 23:55:00,21.047893688800002\n2014-04-06 00:00:00,20.1258699838\n2014-04-06 00:05:00,18.2707006529\n2014-04-06 00:10:00,19.4732660225\n2014-04-06 00:15:00,21.539653828800002\n2014-04-06 00:20:00,21.020946124800002\n2014-04-06 00:25:00,19.2929871358\n2014-04-06 00:30:00,21.752732608200002\n2014-04-06 00:35:00,18.3064116334\n2014-04-06 00:40:00,21.8449388156\n2014-04-06 00:45:00,18.9828203699\n2014-04-06 00:50:00,18.0363767212\n2014-04-06 00:55:00,19.7352321461\n2014-04-06 01:00:00,19.4358817187\n2014-04-06 01:05:00,20.1563560208\n2014-04-06 01:10:00,21.1870914423\n2014-04-06 01:15:00,21.3697232086\n2014-04-06 01:20:00,19.6049199984\n2014-04-06 01:25:00,19.7193829748\n2014-04-06 01:30:00,18.5927109213\n2014-04-06 01:35:00,18.1901904355\n2014-04-06 01:40:00,20.564859960899998\n2014-04-06 01:45:00,18.2577505022\n2014-04-06 01:50:00,20.9353204777\n2014-04-06 01:55:00,20.1563605801\n2014-04-06 02:00:00,18.7943319129\n2014-04-06 02:05:00,20.1580917741\n2014-04-06 02:10:00,18.7319908664\n2014-04-06 02:15:00,19.75494883\n2014-04-06 02:20:00,21.198241265\n2014-04-06 02:25:00,19.847677173599998\n2014-04-06 02:30:00,18.5947972732\n2014-04-06 02:35:00,20.8953147273\n2014-04-06 02:40:00,18.7470736651\n2014-04-06 02:45:00,20.9541994975\n2014-04-06 02:50:00,19.9174091569\n2014-04-06 02:55:00,19.814967036400002\n2014-04-06 03:00:00,21.4057401514\n2014-04-06 03:05:00,20.8344140974\n2014-04-06 03:10:00,18.131643187799998\n2014-04-06 03:15:00,19.1846972584\n2014-04-06 03:20:00,21.4836826434\n2014-04-06 03:25:00,18.0733046742\n2014-04-06 03:30:00,20.181013785\n2014-04-06 03:35:00,20.9113026767\n2014-04-06 03:40:00,20.4874243419\n2014-04-06 03:45:00,21.042128808399998\n2014-04-06 03:50:00,20.9027673957\n2014-04-06 03:55:00,20.7681227806\n2014-04-06 04:00:00,21.286159443699997\n2014-04-06 04:05:00,20.5827626738\n2014-04-06 04:10:00,19.609673977\n2014-04-06 04:15:00,19.8876364397\n2014-04-06 04:20:00,20.8668991307\n2014-04-06 04:25:00,21.5052241187\n2014-04-06 04:30:00,19.0888752034\n2014-04-06 04:35:00,19.3683071839\n2014-04-06 04:40:00,21.7229575854\n2014-04-06 04:45:00,20.314047169600002\n2014-04-06 04:50:00,18.7158472685\n2014-04-06 04:55:00,20.6547805556\n2014-04-06 05:00:00,21.9630486222\n2014-04-06 05:05:00,21.2938142579\n2014-04-06 05:10:00,20.982964546199998\n2014-04-06 05:15:00,18.8321866171\n2014-04-06 05:20:00,21.5045591387\n2014-04-06 05:25:00,20.1031553741\n2014-04-06 05:30:00,21.557160088299998\n2014-04-06 05:35:00,19.3193113177\n2014-04-06 05:40:00,18.2482042105\n2014-04-06 05:45:00,19.9039038746\n2014-04-06 05:50:00,19.0793504193\n2014-04-06 05:55:00,20.8609171591\n2014-04-06 06:00:00,21.8284262114\n2014-04-06 06:05:00,20.7638966046\n2014-04-06 06:10:00,21.547735718800002\n2014-04-06 06:15:00,19.8120960544\n2014-04-06 06:20:00,21.0865629488\n2014-04-06 06:25:00,21.3721737467\n2014-04-06 06:30:00,20.8435025103\n2014-04-06 06:35:00,20.0311091443\n2014-04-06 06:40:00,20.5034644385\n2014-04-06 06:45:00,20.8020279827\n2014-04-06 06:50:00,19.012337612899998\n2014-04-06 06:55:00,21.2383170437\n2014-04-06 07:00:00,21.801298155900003\n2014-04-06 07:05:00,19.860957260699998\n2014-04-06 07:10:00,20.8042687324\n2014-04-06 07:15:00,20.948103623199998\n2014-04-06 07:20:00,20.6489901901\n2014-04-06 07:25:00,20.188460433299998\n2014-04-06 07:30:00,21.5265918183\n2014-04-06 07:35:00,19.7957068371\n2014-04-06 07:40:00,18.2444118259\n2014-04-06 07:45:00,21.3782255028\n2014-04-06 07:50:00,20.6959250893\n2014-04-06 07:55:00,21.397034506\n2014-04-06 08:00:00,18.5541897698\n2014-04-06 08:05:00,18.123011762\n2014-04-06 08:10:00,21.7374981615\n2014-04-06 08:15:00,18.590913223399998\n2014-04-06 08:20:00,21.2386093283\n2014-04-06 08:25:00,21.2928397687\n2014-04-06 08:30:00,20.8348208022\n2014-04-06 08:35:00,18.5250488444\n2014-04-06 08:40:00,20.6695944982\n2014-04-06 08:45:00,21.5563463333\n2014-04-06 08:50:00,19.7021265792\n2014-04-06 08:55:00,19.6540674175\n2014-04-06 09:00:00,67.22287301029999\n2014-04-06 09:05:00,62.318897713199995\n2014-04-06 09:10:00,73.3315477388\n2014-04-06 09:15:00,73.0208869501\n2014-04-06 09:20:00,74.7715667763\n2014-04-06 09:25:00,69.1584907244\n2014-04-06 09:30:00,71.41620625569999\n2014-04-06 09:35:00,63.9563379258\n2014-04-06 09:40:00,70.2783919278\n2014-04-06 09:45:00,70.0363667431\n2014-04-06 09:50:00,73.45643880739999\n2014-04-06 09:55:00,72.4987810306\n2014-04-06 10:00:00,84.4049994998\n2014-04-06 10:05:00,83.3242954963\n2014-04-06 10:10:00,83.3221292488\n2014-04-06 10:15:00,70.8289860302\n2014-04-06 10:20:00,82.9693295058\n2014-04-06 10:25:00,79.2680646827\n2014-04-06 10:30:00,75.7444978914\n2014-04-06 10:35:00,70.7171069705\n2014-04-06 10:40:00,80.3574969844\n2014-04-06 10:45:00,74.9336911683\n2014-04-06 10:50:00,77.0998876326\n2014-04-06 10:55:00,80.4204253431\n2014-04-06 11:00:00,86.0688623959\n2014-04-06 11:05:00,84.6957487058\n2014-04-06 11:10:00,78.7342967413\n2014-04-06 11:15:00,77.735303336\n2014-04-06 11:20:00,75.3814569666\n2014-04-06 11:25:00,77.49107505069999\n2014-04-06 11:30:00,73.33408174350001\n2014-04-06 11:35:00,87.012462005\n2014-04-06 11:40:00,80.6955830287\n2014-04-06 11:45:00,73.6006241238\n2014-04-06 11:50:00,77.1790267714\n2014-04-06 11:55:00,80.2681105401\n2014-04-06 12:00:00,80.429538782\n2014-04-06 12:05:00,72.48097223479999\n2014-04-06 12:10:00,87.10880039979997\n2014-04-06 12:15:00,76.3143236905\n2014-04-06 12:20:00,72.1722439573\n2014-04-06 12:25:00,73.1352364182\n2014-04-06 12:30:00,81.1855787098\n2014-04-06 12:35:00,74.1155228488\n2014-04-06 12:40:00,72.5803955696\n2014-04-06 12:45:00,77.9803346344\n2014-04-06 12:50:00,81.8658220626\n2014-04-06 12:55:00,73.7008895532\n2014-04-06 13:00:00,76.9947621355\n2014-04-06 13:05:00,78.665286545\n2014-04-06 13:10:00,74.53346923779999\n2014-04-06 13:15:00,80.0779590517\n2014-04-06 13:20:00,73.3458181683\n2014-04-06 13:25:00,72.7268373105\n2014-04-06 13:30:00,80.2980897067\n2014-04-06 13:35:00,75.9481196396\n2014-04-06 13:40:00,73.5083346909\n2014-04-06 13:45:00,78.7636935755\n2014-04-06 13:50:00,86.6214576918\n2014-04-06 13:55:00,83.5670182475\n2014-04-06 14:00:00,85.0457722525\n2014-04-06 14:05:00,85.9464981902\n2014-04-06 14:10:00,87.5578408842\n2014-04-06 14:15:00,84.2079030029\n2014-04-06 14:20:00,81.7306034937\n2014-04-06 14:25:00,77.84307743779999\n2014-04-06 14:30:00,74.9026962829\n2014-04-06 14:35:00,82.9825746289\n2014-04-06 14:40:00,87.91497965639999\n2014-04-06 14:45:00,79.4739240224\n2014-04-06 14:50:00,83.5748581037\n2014-04-06 14:55:00,79.9176429689\n2014-04-06 15:00:00,78.9101772288\n2014-04-06 15:05:00,78.56413559399999\n2014-04-06 15:10:00,80.0732262166\n2014-04-06 15:15:00,77.8695830347\n2014-04-06 15:20:00,83.9795669376\n2014-04-06 15:25:00,85.98752693729998\n2014-04-06 15:30:00,86.1253380951\n2014-04-06 15:35:00,75.6424532403\n2014-04-06 15:40:00,86.3337174081\n2014-04-06 15:45:00,77.4640760474\n2014-04-06 15:50:00,76.9481839381\n2014-04-06 15:55:00,83.6272940886\n2014-04-06 16:00:00,76.8749938411\n2014-04-06 16:05:00,72.8473226226\n2014-04-06 16:10:00,77.9777346394\n2014-04-06 16:15:00,83.5432892023\n2014-04-06 16:20:00,77.2311864402\n2014-04-06 16:25:00,82.0727873159\n2014-04-06 16:30:00,82.5617525893\n2014-04-06 16:35:00,83.7396154073\n2014-04-06 16:40:00,86.3539216611\n2014-04-06 16:45:00,78.9208804599\n2014-04-06 16:50:00,74.6627698738\n2014-04-06 16:55:00,77.1026634095\n2014-04-06 17:00:00,78.91464577949999\n2014-04-06 17:05:00,83.4222314751\n2014-04-06 17:10:00,72.2099262804\n2014-04-06 17:15:00,77.0525365469\n2014-04-06 17:20:00,84.477448857\n2014-04-06 17:25:00,82.73369148350001\n2014-04-06 17:30:00,83.7078074336\n2014-04-06 17:35:00,84.9889396753\n2014-04-06 17:40:00,84.53173904180001\n2014-04-06 17:45:00,82.9148988191\n2014-04-06 17:50:00,79.0345541686\n2014-04-06 17:55:00,87.7375395708\n2014-04-06 18:00:00,32.4420622229\n2014-04-06 18:05:00,30.0977171612\n2014-04-06 18:10:00,30.6739963833\n2014-04-06 18:15:00,33.2387933364\n2014-04-06 18:20:00,34.7183265514\n2014-04-06 18:25:00,29.9438030777\n2014-04-06 18:30:00,29.327011942\n2014-04-06 18:35:00,34.441792094600004\n2014-04-06 18:40:00,34.657772410700005\n2014-04-06 18:45:00,30.5688219408\n2014-04-06 18:50:00,31.214622642800002\n2014-04-06 18:55:00,33.0251968431\n2014-04-06 19:00:00,21.638085306399997\n2014-04-06 19:05:00,24.089669691599997\n2014-04-06 19:10:00,20.641951455799997\n2014-04-06 19:15:00,20.3301592346\n2014-04-06 19:20:00,21.0940170491\n2014-04-06 19:25:00,21.4416720701\n2014-04-06 19:30:00,20.665909995299998\n2014-04-06 19:35:00,20.454292001400002\n2014-04-06 19:40:00,23.545121264899997\n2014-04-06 19:45:00,20.895957868900002\n2014-04-06 19:50:00,24.25437012130001\n2014-04-06 19:55:00,21.8086372869\n2014-04-06 20:00:00,21.1788011425\n2014-04-06 20:05:00,19.3552468298\n2014-04-06 20:10:00,19.4163618267\n2014-04-06 20:15:00,20.7860086455\n2014-04-06 20:20:00,20.7283931727\n2014-04-06 20:25:00,21.580714659\n2014-04-06 20:30:00,21.5360030417\n2014-04-06 20:35:00,21.1791368299\n2014-04-06 20:40:00,20.2716385546\n2014-04-06 20:45:00,22.080062757199997\n2014-04-06 20:50:00,20.9820812442\n2014-04-06 20:55:00,22.4878527471\n2014-04-06 21:00:00,21.37961112\n2014-04-06 21:05:00,18.2644899487\n2014-04-06 21:10:00,19.3749309839\n2014-04-06 21:15:00,20.3848828298\n2014-04-06 21:20:00,20.9861303153\n2014-04-06 21:25:00,20.2983124022\n2014-04-06 21:30:00,21.246015342\n2014-04-06 21:35:00,19.2224495525\n2014-04-06 21:40:00,18.8255792703\n2014-04-06 21:45:00,18.3031018907\n2014-04-06 21:50:00,20.3906625523\n2014-04-06 21:55:00,20.8540191425\n2014-04-06 22:00:00,19.3231312739\n2014-04-06 22:05:00,20.4739728926\n2014-04-06 22:10:00,18.2261091982\n2014-04-06 22:15:00,18.4148346626\n2014-04-06 22:20:00,20.8269938171\n2014-04-06 22:25:00,19.490972199\n2014-04-06 22:30:00,20.7051940369\n2014-04-06 22:35:00,21.3473582797\n2014-04-06 22:40:00,21.4310438095\n2014-04-06 22:45:00,18.7066116964\n2014-04-06 22:50:00,19.9642896162\n2014-04-06 22:55:00,20.9558051629\n2014-04-06 23:00:00,21.0999728001\n2014-04-06 23:05:00,21.142762552\n2014-04-06 23:10:00,18.9163005682\n2014-04-06 23:15:00,18.7737431358\n2014-04-06 23:20:00,20.3639590007\n2014-04-06 23:25:00,20.968368342799998\n2014-04-06 23:30:00,19.2802591594\n2014-04-06 23:35:00,18.4223570392\n2014-04-06 23:40:00,20.8709919908\n2014-04-06 23:45:00,19.2024774916\n2014-04-06 23:50:00,18.669034662\n2014-04-06 23:55:00,18.594463563399998\n2014-04-07 00:00:00,19.2596381901\n2014-04-07 00:05:00,20.3707122637\n2014-04-07 00:10:00,19.4336089548\n2014-04-07 00:15:00,18.0826474064\n2014-04-07 00:20:00,18.3876337387\n2014-04-07 00:25:00,19.1620129888\n2014-04-07 00:30:00,20.638817928599998\n2014-04-07 00:35:00,18.3940602939\n2014-04-07 00:40:00,20.242627414\n2014-04-07 00:45:00,18.4795434833\n2014-04-07 00:50:00,18.846461309400002\n2014-04-07 00:55:00,18.6887541102\n2014-04-07 01:00:00,18.2689145423\n2014-04-07 01:05:00,20.6853192695\n2014-04-07 01:10:00,19.8536141895\n2014-04-07 01:15:00,21.3242137636\n2014-04-07 01:20:00,18.3955633599\n2014-04-07 01:25:00,18.578931733399997\n2014-04-07 01:30:00,19.2258309254\n2014-04-07 01:35:00,21.0634639478\n2014-04-07 01:40:00,19.2230352926\n2014-04-07 01:45:00,19.63367483\n2014-04-07 01:50:00,19.2064142652\n2014-04-07 01:55:00,18.320897167200002\n2014-04-07 02:00:00,21.757734491599997\n2014-04-07 02:05:00,20.1941559683\n2014-04-07 02:10:00,21.1513327527\n2014-04-07 02:15:00,20.6334283687\n2014-04-07 02:20:00,20.057017116199997\n2014-04-07 02:25:00,18.3587130266\n2014-04-07 02:30:00,20.5709341811\n2014-04-07 02:35:00,18.6214814237\n2014-04-07 02:40:00,19.6575326774\n2014-04-07 02:45:00,20.5164525739\n2014-04-07 02:50:00,21.128916001900002\n2014-04-07 02:55:00,20.7401807028\n2014-04-07 03:00:00,20.686134116199998\n2014-04-07 03:05:00,18.596168836700002\n2014-04-07 03:10:00,19.3845141603\n2014-04-07 03:15:00,18.1716490906\n2014-04-07 03:20:00,20.8779075727\n2014-04-07 03:25:00,21.810343925300003\n2014-04-07 03:30:00,19.056441560699998\n2014-04-07 03:35:00,18.3507868366\n2014-04-07 03:40:00,19.902280307\n2014-04-07 03:45:00,21.4267928925\n2014-04-07 03:50:00,20.2078967811\n2014-04-07 03:55:00,18.1871086008\n2014-04-07 04:00:00,21.8970889621\n2014-04-07 04:05:00,21.3145996399\n2014-04-07 04:10:00,18.5263763082\n2014-04-07 04:15:00,21.687191026\n2014-04-07 04:20:00,19.8027531544\n2014-04-07 04:25:00,19.4875919623\n2014-04-07 04:30:00,19.8442133221\n2014-04-07 04:35:00,21.3382878275\n2014-04-07 04:40:00,20.6379187131\n2014-04-07 04:45:00,18.2369938096\n2014-04-07 04:50:00,21.8304174845\n2014-04-07 04:55:00,18.591136533900002\n2014-04-07 05:00:00,20.982271806900002\n2014-04-07 05:05:00,20.5445461217\n2014-04-07 05:10:00,18.7501121918\n2014-04-07 05:15:00,18.6829283045\n2014-04-07 05:20:00,21.4813103748\n2014-04-07 05:25:00,19.678779694\n2014-04-07 05:30:00,20.6183060567\n2014-04-07 05:35:00,20.0162840154\n2014-04-07 05:40:00,20.9094140683\n2014-04-07 05:45:00,19.9169695002\n2014-04-07 05:50:00,19.149519661\n2014-04-07 05:55:00,19.453533484\n2014-04-07 06:00:00,21.4363107778\n2014-04-07 06:05:00,19.8721387717\n2014-04-07 06:10:00,18.853797329000002\n2014-04-07 06:15:00,21.7384215523\n2014-04-07 06:20:00,21.186401825999997\n2014-04-07 06:25:00,18.2226645842\n2014-04-07 06:30:00,21.9957718479\n2014-04-07 06:35:00,20.7797067858\n2014-04-07 06:40:00,18.6410663962\n2014-04-07 06:45:00,18.9486707252\n2014-04-07 06:50:00,20.769781925\n2014-04-07 06:55:00,21.119044221099998\n2014-04-07 07:00:00,18.9561437726\n2014-04-07 07:05:00,19.0278754156\n2014-04-07 07:10:00,19.228482779500002\n2014-04-07 07:15:00,20.3920734593\n2014-04-07 07:20:00,18.687264713199998\n2014-04-07 07:25:00,18.416972795499998\n2014-04-07 07:30:00,20.715456356300002\n2014-04-07 07:35:00,21.1163917592\n2014-04-07 07:40:00,20.0037176177\n2014-04-07 07:45:00,19.4553308411\n2014-04-07 07:50:00,19.7281708541\n2014-04-07 07:55:00,19.5536313355\n2014-04-07 08:00:00,21.839939633\n2014-04-07 08:05:00,21.0723596209\n2014-04-07 08:10:00,18.8323488594\n2014-04-07 08:15:00,19.5367566082\n2014-04-07 08:20:00,20.1760491655\n2014-04-07 08:25:00,20.4519434483\n2014-04-07 08:30:00,19.872735584100003\n2014-04-07 08:35:00,21.24050654\n2014-04-07 08:40:00,21.0704240778\n2014-04-07 08:45:00,20.0206316745\n2014-04-07 08:50:00,21.4177175471\n2014-04-07 08:55:00,21.0043581218\n2014-04-07 09:00:00,71.7887131426\n2014-04-07 09:05:00,74.2070506003\n2014-04-07 09:10:00,64.8239504004\n2014-04-07 09:15:00,64.8400150082\n2014-04-07 09:20:00,73.2897506774\n2014-04-07 09:25:00,71.702278678\n2014-04-07 09:30:00,73.8010193635\n2014-04-07 09:35:00,62.0585701804\n2014-04-07 09:40:00,69.73749625079999\n2014-04-07 09:45:00,63.166945398500005\n2014-04-07 09:50:00,68.0530018968\n2014-04-07 09:55:00,63.3181582732\n2014-04-07 10:00:00,71.8277784594\n2014-04-07 10:05:00,70.0288527203\n2014-04-07 10:10:00,79.6213063682\n2014-04-07 10:15:00,75.41203101100001\n2014-04-07 10:20:00,71.47252218130002\n2014-04-07 10:25:00,74.8504423104\n2014-04-07 10:30:00,72.4620122993\n2014-04-07 10:35:00,84.4551037849\n2014-04-07 10:40:00,74.806475827\n2014-04-07 10:45:00,75.0229586815\n2014-04-07 10:50:00,82.8745962128\n2014-04-07 10:55:00,79.8931694152\n2014-04-07 11:00:00,82.8625692441\n2014-04-07 11:05:00,81.68297269060001\n2014-04-07 11:10:00,86.6163056999\n2014-04-07 11:15:00,74.86014122510001\n2014-04-07 11:20:00,87.2976801009\n2014-04-07 11:25:00,84.7835270479\n2014-04-07 11:30:00,80.9350200535\n2014-04-07 11:35:00,82.10235831439999\n2014-04-07 11:40:00,81.88692673989999\n2014-04-07 11:45:00,72.4967335474\n2014-04-07 11:50:00,75.03533439270001\n2014-04-07 11:55:00,86.8592329475\n2014-04-07 12:00:00,80.4531710647\n2014-04-07 12:05:00,77.959993263\n2014-04-07 12:10:00,84.0915842757\n2014-04-07 12:15:00,80.2958323188\n2014-04-07 12:20:00,72.1239516177\n2014-04-07 12:25:00,83.67926578560001\n2014-04-07 12:30:00,83.6150223837\n2014-04-07 12:35:00,74.5528085385\n2014-04-07 12:40:00,87.2017935411\n2014-04-07 12:45:00,75.4918310685\n2014-04-07 12:50:00,79.2288010903\n2014-04-07 12:55:00,73.7471724497\n2014-04-07 13:00:00,81.6329205071\n2014-04-07 13:05:00,77.9884961886\n2014-04-07 13:10:00,77.63213920930001\n2014-04-07 13:15:00,85.2111744443\n2014-04-07 13:20:00,72.1356706886\n2014-04-07 13:25:00,84.74680421869998\n2014-04-07 13:30:00,81.12370268949999\n2014-04-07 13:35:00,87.7565095974\n2014-04-07 13:40:00,81.41154806770001\n2014-04-07 13:45:00,72.8685734905\n2014-04-07 13:50:00,72.792850745\n2014-04-07 13:55:00,86.10977647450001\n2014-04-07 14:00:00,85.4553242757\n2014-04-07 14:05:00,77.53051956569999\n2014-04-07 14:10:00,81.884589098\n2014-04-07 14:15:00,79.8296297067\n2014-04-07 14:20:00,87.4704261002\n2014-04-07 14:25:00,87.1951888441\n2014-04-07 14:30:00,87.7372125483\n2014-04-07 14:35:00,85.8590590575\n2014-04-07 14:40:00,86.5486709168\n2014-04-07 14:45:00,75.4728375902\n2014-04-07 14:50:00,85.2920144106\n2014-04-07 14:55:00,83.337713409\n2014-04-07 15:00:00,87.4037450572\n2014-04-07 15:05:00,81.1394103093\n2014-04-07 15:10:00,73.36197038569999\n2014-04-07 15:15:00,81.55759929850001\n2014-04-07 15:20:00,82.9844981895\n2014-04-07 15:25:00,75.5244114181\n2014-04-07 15:30:00,78.3050624004\n2014-04-07 15:35:00,81.5752714947\n2014-04-07 15:40:00,77.9849431344\n2014-04-07 15:45:00,77.99841468380002\n2014-04-07 15:50:00,74.12867458470001\n2014-04-07 15:55:00,87.0511118705\n2014-04-07 16:00:00,84.0077488567\n2014-04-07 16:05:00,72.0197567437\n2014-04-07 16:10:00,84.24965078470001\n2014-04-07 16:15:00,83.836558916\n2014-04-07 16:20:00,72.1555568236\n2014-04-07 16:25:00,77.9135191676\n2014-04-07 16:30:00,81.7078061659\n2014-04-07 16:35:00,79.2438582812\n2014-04-07 16:40:00,84.4476157598\n2014-04-07 16:45:00,78.8071820121\n2014-04-07 16:50:00,74.4616645446\n2014-04-07 16:55:00,87.62248175290001\n2014-04-07 17:00:00,75.87261074930001\n2014-04-07 17:05:00,83.4830449112\n2014-04-07 17:10:00,74.2904724591\n2014-04-07 17:15:00,77.2641721511\n2014-04-07 17:20:00,79.0724113711\n2014-04-07 17:25:00,75.07568324340001\n2014-04-07 17:30:00,79.1993228093\n2014-04-07 17:35:00,74.5145765543\n2014-04-07 17:40:00,80.9440735412\n2014-04-07 17:45:00,82.61938031449999\n2014-04-07 17:50:00,72.9989205129\n2014-04-07 17:55:00,85.9380809371\n2014-04-07 18:00:00,29.9848959072\n2014-04-07 18:05:00,30.242313715500003\n2014-04-07 18:10:00,33.0326326343\n2014-04-07 18:15:00,31.8000006812\n2014-04-07 18:20:00,31.9961256914\n2014-04-07 18:25:00,29.6201862141\n2014-04-07 18:30:00,33.9567027403\n2014-04-07 18:35:00,32.7491408872\n2014-04-07 18:40:00,29.6664393812\n2014-04-07 18:45:00,31.1935899598\n2014-04-07 18:50:00,33.9866170441\n2014-04-07 18:55:00,32.437466066300004\n2014-04-07 19:00:00,20.6467453979\n2014-04-07 19:05:00,21.8300399676\n2014-04-07 19:10:00,21.247269739500002\n2014-04-07 19:15:00,22.4782444473\n2014-04-07 19:20:00,23.9382565442\n2014-04-07 19:25:00,22.114475550799998\n2014-04-07 19:30:00,22.1013710836\n2014-04-07 19:35:00,24.215970714\n2014-04-07 19:40:00,22.7413094005\n2014-04-07 19:45:00,22.696534826500002\n2014-04-07 19:50:00,21.3333551453\n2014-04-07 19:55:00,22.882596655\n2014-04-07 20:00:00,20.7909290251\n2014-04-07 20:05:00,20.0575033818\n2014-04-07 20:10:00,22.489888768\n2014-04-07 20:15:00,22.0442251279\n2014-04-07 20:20:00,21.502305186100006\n2014-04-07 20:25:00,20.6329672825\n2014-04-07 20:30:00,20.3245967047\n2014-04-07 20:35:00,19.1893395006\n2014-04-07 20:40:00,19.6843004574\n2014-04-07 20:45:00,21.6021431769\n2014-04-07 20:50:00,20.2905554718\n2014-04-07 20:55:00,22.045775675300003\n2014-04-07 21:00:00,18.680884393499998\n2014-04-07 21:05:00,20.1295485991\n2014-04-07 21:10:00,20.6866844266\n2014-04-07 21:15:00,20.1637172663\n2014-04-07 21:20:00,21.660380669699997\n2014-04-07 21:25:00,22.0636526884\n2014-04-07 21:30:00,18.5519626134\n2014-04-07 21:35:00,18.608714705\n2014-04-07 21:40:00,18.6101986317\n2014-04-07 21:45:00,20.8241869336\n2014-04-07 21:50:00,19.5842597151\n2014-04-07 21:55:00,21.0337382351\n2014-04-07 22:00:00,19.6407228924\n2014-04-07 22:05:00,20.5301168851\n2014-04-07 22:10:00,21.0996682671\n2014-04-07 22:15:00,20.2122487818\n2014-04-07 22:20:00,20.177366045699998\n2014-04-07 22:25:00,18.3705561119\n2014-04-07 22:30:00,19.6619843639\n2014-04-07 22:35:00,20.202484387200002\n2014-04-07 22:40:00,19.8669772993\n2014-04-07 22:45:00,21.623866993000004\n2014-04-07 22:50:00,21.6468835955\n2014-04-07 22:55:00,21.3081056746\n2014-04-07 23:00:00,19.5049365285\n2014-04-07 23:05:00,20.873203490399998\n2014-04-07 23:10:00,19.5849134239\n2014-04-07 23:15:00,18.9340090259\n2014-04-07 23:20:00,19.3753299215\n2014-04-07 23:25:00,18.2873690322\n2014-04-07 23:30:00,19.3308208392\n2014-04-07 23:35:00,19.8467787171\n2014-04-07 23:40:00,21.8261133863\n2014-04-07 23:45:00,19.2573390423\n2014-04-07 23:50:00,21.613963239\n2014-04-07 23:55:00,18.9190648646\n2014-04-08 00:00:00,18.763875590999998\n2014-04-08 00:05:00,20.075981825699998\n2014-04-08 00:10:00,20.6900454772\n2014-04-08 00:15:00,18.1773290032\n2014-04-08 00:20:00,18.8842634602\n2014-04-08 00:25:00,19.822734666\n2014-04-08 00:30:00,19.3240173439\n2014-04-08 00:35:00,20.8504843174\n2014-04-08 00:40:00,20.0446423842\n2014-04-08 00:45:00,18.6414364224\n2014-04-08 00:50:00,21.5778615173\n2014-04-08 00:55:00,19.171622701900002\n2014-04-08 01:00:00,20.9245244359\n2014-04-08 01:05:00,21.1196631164\n2014-04-08 01:10:00,21.852630801\n2014-04-08 01:15:00,19.9940298661\n2014-04-08 01:20:00,20.4633420619\n2014-04-08 01:25:00,19.3395051739\n2014-04-08 01:30:00,20.712717173599998\n2014-04-08 01:35:00,19.8535339435\n2014-04-08 01:40:00,19.7506094589\n2014-04-08 01:45:00,21.421870116500003\n2014-04-08 01:50:00,18.200675374\n2014-04-08 01:55:00,21.5278497113\n2014-04-08 02:00:00,21.408279351300003\n2014-04-08 02:05:00,20.0254650142\n2014-04-08 02:10:00,19.960811416800002\n2014-04-08 02:15:00,19.447229472100002\n2014-04-08 02:20:00,21.9766951667\n2014-04-08 02:25:00,18.444677330999998\n2014-04-08 02:30:00,20.3608609425\n2014-04-08 02:35:00,20.7267263604\n2014-04-08 02:40:00,21.7373200329\n2014-04-08 02:45:00,21.120813987400002\n2014-04-08 02:50:00,20.5753888112\n2014-04-08 02:55:00,18.4672492672\n2014-04-08 03:00:00,19.4949340673\n2014-04-08 03:05:00,18.5553665702\n2014-04-08 03:10:00,21.524850929899998\n2014-04-08 03:15:00,20.9984846223\n2014-04-08 03:20:00,21.0301471472\n2014-04-08 03:25:00,20.6090260711\n2014-04-08 03:30:00,20.0281741477\n2014-04-08 03:35:00,18.5998842379\n2014-04-08 03:40:00,19.318779546800002\n2014-04-08 03:45:00,18.5476631699\n2014-04-08 03:50:00,20.8996525714\n2014-04-08 03:55:00,18.6409151041\n2014-04-08 04:00:00,20.808454200699998\n2014-04-08 04:05:00,20.7690215584\n2014-04-08 04:10:00,19.837217916\n2014-04-08 04:15:00,18.5409146165\n2014-04-08 04:20:00,19.2592033045\n2014-04-08 04:25:00,19.280372436300002\n2014-04-08 04:30:00,20.8015405326\n2014-04-08 04:35:00,18.4549720777\n2014-04-08 04:40:00,21.3162745849\n2014-04-08 04:45:00,21.0440291607\n2014-04-08 04:50:00,18.7452276727\n2014-04-08 04:55:00,20.8766575271\n2014-04-08 05:00:00,20.674052725899998\n2014-04-08 05:05:00,20.9924832004\n2014-04-08 05:10:00,18.7557142218\n2014-04-08 05:15:00,18.6303612886\n2014-04-08 05:20:00,18.9459359437\n2014-04-08 05:25:00,19.4634868126\n2014-04-08 05:30:00,21.174659924100002\n2014-04-08 05:35:00,20.9516957499\n2014-04-08 05:40:00,21.701806369099998\n2014-04-08 05:45:00,18.2345182364\n2014-04-08 05:50:00,18.0462251241\n2014-04-08 05:55:00,20.7965553188\n2014-04-08 06:00:00,19.1171499832\n2014-04-08 06:05:00,19.3363155821\n2014-04-08 06:10:00,20.187208103699998\n2014-04-08 06:15:00,18.4096524925\n2014-04-08 06:20:00,20.570777666199998\n2014-04-08 06:25:00,19.3005897849\n2014-04-08 06:30:00,20.5308604972\n2014-04-08 06:35:00,21.3360276523\n2014-04-08 06:40:00,18.684445333299998\n2014-04-08 06:45:00,21.7234923717\n2014-04-08 06:50:00,20.122752564200002\n2014-04-08 06:55:00,21.6917110607\n2014-04-08 07:00:00,18.8309203288\n2014-04-08 07:05:00,20.418250658399998\n2014-04-08 07:10:00,19.615548469300002\n2014-04-08 07:15:00,21.0968887646\n2014-04-08 07:20:00,20.4236357729\n2014-04-08 07:25:00,19.9780618278\n2014-04-08 07:30:00,21.6519416257\n2014-04-08 07:35:00,19.508468256700002\n2014-04-08 07:40:00,18.8799208196\n2014-04-08 07:45:00,20.4324047474\n2014-04-08 07:50:00,20.496113748699997\n2014-04-08 07:55:00,19.7563784863\n2014-04-08 08:00:00,19.9464401748\n2014-04-08 08:05:00,21.838213657199997\n2014-04-08 08:10:00,20.930742765599998\n2014-04-08 08:15:00,18.442407005899998\n2014-04-08 08:20:00,18.848520283499997\n2014-04-08 08:25:00,21.9023065377\n2014-04-08 08:30:00,20.9058622152\n2014-04-08 08:35:00,21.6601805046\n2014-04-08 08:40:00,19.215445856\n2014-04-08 08:45:00,20.9674674403\n2014-04-08 08:50:00,20.8560108341\n2014-04-08 08:55:00,19.1787599418\n2014-04-08 09:00:00,68.6911020261\n2014-04-08 09:05:00,69.7328455133\n2014-04-08 09:10:00,67.7433926273\n2014-04-08 09:15:00,72.4496304105\n2014-04-08 09:20:00,72.5270189685\n2014-04-08 09:25:00,72.7681674569\n2014-04-08 09:30:00,72.12656053970001\n2014-04-08 09:35:00,67.8379352899\n2014-04-08 09:40:00,66.3875608548\n2014-04-08 09:45:00,72.5067174585\n2014-04-08 09:50:00,67.8667398364\n2014-04-08 09:55:00,64.5506510213\n2014-04-08 10:00:00,77.7139716216\n2014-04-08 10:05:00,72.0415092362\n2014-04-08 10:10:00,80.5740896941\n2014-04-08 10:15:00,75.0534982908\n2014-04-08 10:20:00,73.8854245519\n2014-04-08 10:25:00,84.6850157416\n2014-04-08 10:30:00,81.8971930542\n2014-04-08 10:35:00,82.0553186823\n2014-04-08 10:40:00,79.5201649632\n2014-04-08 10:45:00,82.8639620191\n2014-04-08 10:50:00,81.6222017077\n2014-04-08 10:55:00,79.1329678882\n2014-04-08 11:00:00,86.85372248700001\n2014-04-08 11:05:00,74.61512607979999\n2014-04-08 11:10:00,86.5715110509\n2014-04-08 11:15:00,77.95247252840001\n2014-04-08 11:20:00,79.971657432\n2014-04-08 11:25:00,73.520046138\n2014-04-08 11:30:00,80.15786870859999\n2014-04-08 11:35:00,81.2886321816\n2014-04-08 11:40:00,87.4354453209\n2014-04-08 11:45:00,87.0774601057\n2014-04-08 11:50:00,86.93758253\n2014-04-08 11:55:00,77.1087637079\n2014-04-08 12:00:00,87.75483166309998\n2014-04-08 12:05:00,79.192505245\n2014-04-08 12:10:00,85.526624884\n2014-04-08 12:15:00,75.3705661609\n2014-04-08 12:20:00,79.9972188775\n2014-04-08 12:25:00,87.3512461058\n2014-04-08 12:30:00,87.047919348\n2014-04-08 12:35:00,82.8402303355\n2014-04-08 12:40:00,84.6633111259\n2014-04-08 12:45:00,74.7330397531\n2014-04-08 12:50:00,83.4462809476\n2014-04-08 12:55:00,81.7905463578\n2014-04-08 13:00:00,73.4471962134\n2014-04-08 13:05:00,73.7928295748\n2014-04-08 13:10:00,73.7174014605\n2014-04-08 13:15:00,83.5696494266\n2014-04-08 13:20:00,74.24961914560001\n2014-04-08 13:25:00,79.4646402459\n2014-04-08 13:30:00,77.6930580839\n2014-04-08 13:35:00,80.78867231640001\n2014-04-08 13:40:00,83.2836309258\n2014-04-08 13:45:00,82.935651261\n2014-04-08 13:50:00,80.2290590582\n2014-04-08 13:55:00,79.4102949319\n2014-04-08 14:00:00,78.3612879996\n2014-04-08 14:05:00,85.78644122600001\n2014-04-08 14:10:00,77.2899187838\n2014-04-08 14:15:00,76.1461979457\n2014-04-08 14:20:00,83.8890210322\n2014-04-08 14:25:00,77.7524830888\n2014-04-08 14:30:00,85.5478711012\n2014-04-08 14:35:00,77.2425116797\n2014-04-08 14:40:00,83.2271220996\n2014-04-08 14:45:00,72.7182534568\n2014-04-08 14:50:00,78.1652539695\n2014-04-08 14:55:00,77.4879631987\n2014-04-08 15:00:00,85.0660431866\n2014-04-08 15:05:00,87.4720467119\n2014-04-08 15:10:00,79.37333843569999\n2014-04-08 15:15:00,85.1965625396\n2014-04-08 15:20:00,83.1943165422\n2014-04-08 15:25:00,87.4773360121\n2014-04-08 15:30:00,84.9769204432\n2014-04-08 15:35:00,73.2389459548\n2014-04-08 15:40:00,83.411706798\n2014-04-08 15:45:00,80.567221994\n2014-04-08 15:50:00,72.2622832023\n2014-04-08 15:55:00,76.0202775379\n2014-04-08 16:00:00,86.7479173641\n2014-04-08 16:05:00,86.816815276\n2014-04-08 16:10:00,84.7814445825\n2014-04-08 16:15:00,87.70830525219999\n2014-04-08 16:20:00,84.9045605769\n2014-04-08 16:25:00,72.1631284431\n2014-04-08 16:30:00,76.6052023626\n2014-04-08 16:35:00,72.489847735\n2014-04-08 16:40:00,73.5055863688\n2014-04-08 16:45:00,75.5013081084\n2014-04-08 16:50:00,80.0567830319\n2014-04-08 16:55:00,85.5603477792\n2014-04-08 17:00:00,85.7914351546\n2014-04-08 17:05:00,81.859198303\n2014-04-08 17:10:00,86.85078167430002\n2014-04-08 17:15:00,80.0009665051\n2014-04-08 17:20:00,86.2245435959\n2014-04-08 17:25:00,79.2650136635\n2014-04-08 17:30:00,76.4355707675\n2014-04-08 17:35:00,86.66257341120001\n2014-04-08 17:40:00,78.2069311794\n2014-04-08 17:45:00,80.05443500060001\n2014-04-08 17:50:00,77.261740452\n2014-04-08 17:55:00,82.6053698842\n2014-04-08 18:00:00,35.1681930877\n2014-04-08 18:05:00,28.963281151799997\n2014-04-08 18:10:00,34.5590206031\n2014-04-08 18:15:00,28.825121230300002\n2014-04-08 18:20:00,31.1310524622\n2014-04-08 18:25:00,29.879077823499998\n2014-04-08 18:30:00,33.6469809361\n2014-04-08 18:35:00,29.123903789099998\n2014-04-08 18:40:00,32.3422974932\n2014-04-08 18:45:00,30.687521364600002\n2014-04-08 18:50:00,29.6554838989\n2014-04-08 18:55:00,33.7396300794\n2014-04-08 19:00:00,21.1340262581\n2014-04-08 19:05:00,21.1620637891\n2014-04-08 19:10:00,21.3923428239\n2014-04-08 19:15:00,22.788713851799997\n2014-04-08 19:20:00,23.115302105900003\n2014-04-08 19:25:00,20.2388581959\n2014-04-08 19:30:00,21.2435748044\n2014-04-08 19:35:00,22.0907481626\n2014-04-08 19:40:00,21.6472555582\n2014-04-08 19:45:00,24.1210832269\n2014-04-08 19:50:00,23.688933814899997\n2014-04-08 19:55:00,22.9639869059\n2014-04-08 20:00:00,19.816621498099998\n2014-04-08 20:05:00,21.3019536689\n2014-04-08 20:10:00,21.887541038000002\n2014-04-08 20:15:00,20.8684249752\n2014-04-08 20:20:00,21.6451539087\n2014-04-08 20:25:00,21.500333663899998\n2014-04-08 20:30:00,20.7738357772\n2014-04-08 20:35:00,19.7107022196\n2014-04-08 20:40:00,21.486723461300002\n2014-04-08 20:45:00,19.2790376853\n2014-04-08 20:50:00,21.6247840077\n2014-04-08 20:55:00,21.727422990300003\n2014-04-08 21:00:00,21.3907646477\n2014-04-08 21:05:00,19.987143821700002\n2014-04-08 21:10:00,18.8600186557\n2014-04-08 21:15:00,18.4872090482\n2014-04-08 21:20:00,21.074117486400002\n2014-04-08 21:25:00,21.648461703800002\n2014-04-08 21:30:00,20.7022494812\n2014-04-08 21:35:00,18.665808069100002\n2014-04-08 21:40:00,21.8439357525\n2014-04-08 21:45:00,22.0617987629\n2014-04-08 21:50:00,19.8282352606\n2014-04-08 21:55:00,20.4771217526\n2014-04-08 22:00:00,21.1291786271\n2014-04-08 22:05:00,20.9656668867\n2014-04-08 22:10:00,21.8921450598\n2014-04-08 22:15:00,18.477253506300002\n2014-04-08 22:20:00,20.3424094381\n2014-04-08 22:25:00,20.7876626851\n2014-04-08 22:30:00,21.581091664099997\n2014-04-08 22:35:00,21.5170750813\n2014-04-08 22:40:00,21.9330346827\n2014-04-08 22:45:00,20.0675601872\n2014-04-08 22:50:00,21.343513578499998\n2014-04-08 22:55:00,19.7280475846\n2014-04-08 23:00:00,19.693035846500003\n2014-04-08 23:05:00,19.0170440276\n2014-04-08 23:10:00,21.2770335522\n2014-04-08 23:15:00,21.9474735271\n2014-04-08 23:20:00,19.029019782\n2014-04-08 23:25:00,18.2280254594\n2014-04-08 23:30:00,21.2662520842\n2014-04-08 23:35:00,20.4848525448\n2014-04-08 23:40:00,21.8429882487\n2014-04-08 23:45:00,19.0126065942\n2014-04-08 23:50:00,18.287621179400002\n2014-04-08 23:55:00,19.9736032372\n2014-04-09 00:00:00,18.3418640919\n2014-04-09 00:05:00,19.047160004400002\n2014-04-09 00:10:00,18.503911443299998\n2014-04-09 00:15:00,18.8965287186\n2014-04-09 00:20:00,18.4245786113\n2014-04-09 00:25:00,21.8156239977\n2014-04-09 00:30:00,19.1142508538\n2014-04-09 00:35:00,19.775590344\n2014-04-09 00:40:00,21.594447230500002\n2014-04-09 00:45:00,20.7092863518\n2014-04-09 00:50:00,20.4721499222\n2014-04-09 00:55:00,20.8222527614\n2014-04-09 01:00:00,21.3152890284\n2014-04-09 01:05:00,21.5106770714\n2014-04-09 01:10:00,20.5705586827\n2014-04-09 01:15:00,21.5600290988\n2014-04-09 01:20:00,20.1415901097\n2014-04-09 01:25:00,19.1091634251\n2014-04-09 01:30:00,21.5203068355\n2014-04-09 01:35:00,20.1658913097\n2014-04-09 01:40:00,21.6245503503\n2014-04-09 01:45:00,18.1606712558\n2014-04-09 01:50:00,19.590063006199998\n2014-04-09 01:55:00,21.7912200734\n2014-04-09 02:00:00,18.998600371\n2014-04-09 02:05:00,21.7661449842\n2014-04-09 02:10:00,21.8156098445\n2014-04-09 02:15:00,21.5285692569\n2014-04-09 02:20:00,20.2546721804\n2014-04-09 02:25:00,20.5877577963\n2014-04-09 02:30:00,21.478467993800002\n2014-04-09 02:35:00,21.1035883296\n2014-04-09 02:40:00,20.5203753978\n2014-04-09 02:45:00,21.9290376315\n2014-04-09 02:50:00,20.7427065453\n2014-04-09 02:55:00,21.9019279698\n2014-04-09 03:00:00,18.2295538984\n2014-04-09 03:05:00,18.555841483\n2014-04-09 03:10:00,19.805835384\n2014-04-09 03:15:00,19.5395178435\n2014-04-09 03:20:00,21.1309393654\n2014-04-09 03:25:00,18.6424561059\n2014-04-09 03:30:00,21.9043807164\n2014-04-09 03:35:00,19.260263501\n2014-04-09 03:40:00,19.715694831\n2014-04-09 03:45:00,19.0989801298\n2014-04-09 03:50:00,20.3174544693\n2014-04-09 03:55:00,18.2345148017\n2014-04-09 04:00:00,18.5987100223\n2014-04-09 04:05:00,20.9831908137\n2014-04-09 04:10:00,18.7460023336\n2014-04-09 04:15:00,18.942057806199998\n2014-04-09 04:20:00,21.1719289429\n2014-04-09 04:25:00,18.3732047134\n2014-04-09 04:30:00,19.7498952911\n2014-04-09 04:35:00,18.092253548\n2014-04-09 04:40:00,19.3872295973\n2014-04-09 04:45:00,20.7959256104\n2014-04-09 04:50:00,18.360413118900002\n2014-04-09 04:55:00,21.5533385071\n2014-04-09 05:00:00,21.637996171799998\n2014-04-09 05:05:00,18.4199615005\n2014-04-09 05:10:00,21.962929745500002\n2014-04-09 05:15:00,19.190118213599998\n2014-04-09 05:20:00,18.3364066845\n2014-04-09 05:25:00,18.020268458\n2014-04-09 05:30:00,19.6340915831\n2014-04-09 05:35:00,20.5192399428\n2014-04-09 05:40:00,19.3287169996\n2014-04-09 05:45:00,21.3468694619\n2014-04-09 05:50:00,20.8664251023\n2014-04-09 05:55:00,19.4006461279\n2014-04-09 06:00:00,20.937238666400003\n2014-04-09 06:05:00,21.7619509479\n2014-04-09 06:10:00,18.3723839942\n2014-04-09 06:15:00,19.2244158406\n2014-04-09 06:20:00,19.8533037565\n2014-04-09 06:25:00,19.991960511\n2014-04-09 06:30:00,20.1687825795\n2014-04-09 06:35:00,19.2025076262\n2014-04-09 06:40:00,20.6690385839\n2014-04-09 06:45:00,20.5803380141\n2014-04-09 06:50:00,20.3112860251\n2014-04-09 06:55:00,18.4550468868\n2014-04-09 07:00:00,19.9078715644\n2014-04-09 07:05:00,19.42490755\n2014-04-09 07:10:00,19.9641538794\n2014-04-09 07:15:00,21.6874657421\n2014-04-09 07:20:00,19.9221253726\n2014-04-09 07:25:00,18.0559231674\n2014-04-09 07:30:00,19.755346952300002\n2014-04-09 07:35:00,21.2825927202\n2014-04-09 07:40:00,21.1202436929\n2014-04-09 07:45:00,20.053560294100002\n2014-04-09 07:50:00,18.9990760514\n2014-04-09 07:55:00,19.8603546517\n2014-04-09 08:00:00,20.2548088777\n2014-04-09 08:05:00,21.9994857531\n2014-04-09 08:10:00,20.5767123607\n2014-04-09 08:15:00,20.7770597203\n2014-04-09 08:20:00,19.9658165743\n2014-04-09 08:25:00,19.4179582031\n2014-04-09 08:30:00,21.2518119346\n2014-04-09 08:35:00,19.9797292974\n2014-04-09 08:40:00,21.978760519899996\n2014-04-09 08:45:00,19.8284822971\n2014-04-09 08:50:00,18.2720011346\n2014-04-09 08:55:00,20.7303125484\n2014-04-09 09:00:00,61.83432373260001\n2014-04-09 09:05:00,64.6068217176\n2014-04-09 09:10:00,66.0108402378\n2014-04-09 09:15:00,71.2569767645\n2014-04-09 09:20:00,67.9216085991\n2014-04-09 09:25:00,61.5895846658\n2014-04-09 09:30:00,69.58915797739999\n2014-04-09 09:35:00,66.795532829\n2014-04-09 09:40:00,73.7369493356\n2014-04-09 09:45:00,67.9940474315\n2014-04-09 09:50:00,70.8420619848\n2014-04-09 09:55:00,64.1766114957\n2014-04-09 10:00:00,81.6503097215\n2014-04-09 10:05:00,81.0292264187\n2014-04-09 10:10:00,83.8713481166\n2014-04-09 10:15:00,70.3649118795\n2014-04-09 10:20:00,76.785210827\n2014-04-09 10:25:00,80.38049185050001\n2014-04-09 10:30:00,71.3169437292\n2014-04-09 10:35:00,76.21257512220001\n2014-04-09 10:40:00,84.4621152796\n2014-04-09 10:45:00,76.60570329859999\n2014-04-09 10:50:00,85.1334822396\n2014-04-09 10:55:00,70.722142228\n2014-04-09 11:00:00,82.9843647597\n2014-04-09 11:05:00,80.8084822213\n2014-04-09 11:10:00,79.5285830251\n2014-04-09 11:15:00,87.0083570732\n2014-04-09 11:20:00,73.62995996939999\n2014-04-09 11:25:00,85.8179673275\n2014-04-09 11:30:00,82.5614874987\n2014-04-09 11:35:00,75.68707354979999\n2014-04-09 11:40:00,85.9081460921\n2014-04-09 11:45:00,78.3955063737\n2014-04-09 11:50:00,84.5174714257\n2014-04-09 11:55:00,77.7520559671\n2014-04-09 12:00:00,85.51215536699999\n2014-04-09 12:05:00,82.087442616\n2014-04-09 12:10:00,74.167638042\n2014-04-09 12:15:00,82.2957370828\n2014-04-09 12:20:00,74.9714423838\n2014-04-09 12:25:00,78.4964531319\n2014-04-09 12:30:00,74.6350596728\n2014-04-09 12:35:00,72.2654351413\n2014-04-09 12:40:00,75.2997164096\n2014-04-09 12:45:00,80.4852540367\n2014-04-09 12:50:00,79.60932951390001\n2014-04-09 12:55:00,79.9279247843\n2014-04-09 13:00:00,75.9447589375\n2014-04-09 13:05:00,82.9426681908\n2014-04-09 13:10:00,83.24822821810001\n2014-04-09 13:15:00,77.7088306125\n2014-04-09 13:20:00,86.0780577224\n2014-04-09 13:25:00,82.284618417\n2014-04-09 13:30:00,83.3886103333\n2014-04-09 13:35:00,76.4190937017\n2014-04-09 13:40:00,71.9925038138\n2014-04-09 13:45:00,85.82540675130002\n2014-04-09 13:50:00,85.1383520436\n2014-04-09 13:55:00,73.95331715180001\n2014-04-09 14:00:00,77.9819388466\n2014-04-09 14:05:00,82.5774650256\n2014-04-09 14:10:00,82.42981689439999\n2014-04-09 14:15:00,85.7614886079\n2014-04-09 14:20:00,74.2407268602\n2014-04-09 14:25:00,78.8752497708\n2014-04-09 14:30:00,73.5520600185\n2014-04-09 14:35:00,78.2297687659\n2014-04-09 14:40:00,72.2382515269\n2014-04-09 14:45:00,86.36822316799999\n2014-04-09 14:50:00,80.42884317949999\n2014-04-09 14:55:00,85.59272752470001\n2014-04-09 15:00:00,72.9577748147\n2014-04-09 15:05:00,75.63860363\n2014-04-09 15:10:00,76.1493488828\n2014-04-09 15:15:00,78.1863133184\n2014-04-09 15:20:00,84.84504743810001\n2014-04-09 15:25:00,78.1841754044\n2014-04-09 15:30:00,75.2737338396\n2014-04-09 15:35:00,73.0391429829\n2014-04-09 15:40:00,73.2711645637\n2014-04-09 15:45:00,84.1599473521\n2014-04-09 15:50:00,79.1160883348\n2014-04-09 15:55:00,83.6180952106\n2014-04-09 16:00:00,82.91643474840001\n2014-04-09 16:05:00,74.1656569898\n2014-04-09 16:10:00,74.28606431760001\n2014-04-09 16:15:00,84.0853108028\n2014-04-09 16:20:00,83.5401322984\n2014-04-09 16:25:00,78.0483424169\n2014-04-09 16:30:00,73.2386155949\n2014-04-09 16:35:00,72.1934297355\n2014-04-09 16:40:00,76.6103640992\n2014-04-09 16:45:00,72.1474178541\n2014-04-09 16:50:00,75.6810166298\n2014-04-09 16:55:00,78.7118607163\n2014-04-09 17:00:00,73.94262385100001\n2014-04-09 17:05:00,73.6684158366\n2014-04-09 17:10:00,86.3429658158\n2014-04-09 17:15:00,81.3674892192\n2014-04-09 17:20:00,86.9512575989\n2014-04-09 17:25:00,77.53318884779999\n2014-04-09 17:30:00,82.8342871889\n2014-04-09 17:35:00,75.2750378883\n2014-04-09 17:40:00,81.8934136294\n2014-04-09 17:45:00,74.073343236\n2014-04-09 17:50:00,72.033262566\n2014-04-09 17:55:00,86.90447545120001\n2014-04-09 18:00:00,32.3513177961\n2014-04-09 18:05:00,34.7324135732\n2014-04-09 18:10:00,30.9365158119\n2014-04-09 18:15:00,30.897824910300002\n2014-04-09 18:20:00,31.3641859894\n2014-04-09 18:25:00,33.318655900100005\n2014-04-09 18:30:00,32.4211690339\n2014-04-09 18:35:00,34.7222647388\n2014-04-09 18:40:00,28.9628162064\n2014-04-09 18:45:00,33.3324476032\n2014-04-09 18:50:00,30.914091276399997\n2014-04-09 18:55:00,29.9534896206\n2014-04-09 19:00:00,22.4465711575\n2014-04-09 19:05:00,22.4226845231\n2014-04-09 19:10:00,20.7738082689\n2014-04-09 19:15:00,21.064493175899997\n2014-04-09 19:20:00,21.9885764925\n2014-04-09 19:25:00,21.991473921100006\n2014-04-09 19:30:00,21.5826592815\n2014-04-09 19:35:00,20.825481136300002\n2014-04-09 19:40:00,20.1795929754\n2014-04-09 19:45:00,24.506651735300004\n2014-04-09 19:50:00,24.3868752113\n2014-04-09 19:55:00,22.326752473899997\n2014-04-09 20:00:00,22.5077317113\n2014-04-09 20:05:00,21.1912878846\n2014-04-09 20:10:00,18.714040249500002\n2014-04-09 20:15:00,18.9141735165\n2014-04-09 20:20:00,22.184389750300003\n2014-04-09 20:25:00,21.0126935679\n2014-04-09 20:30:00,21.885679872199997\n2014-04-09 20:35:00,22.111312219600002\n2014-04-09 20:40:00,20.266770235\n2014-04-09 20:45:00,18.6307620741\n2014-04-09 20:50:00,19.203196078599998\n2014-04-09 20:55:00,18.7046784717\n2014-04-09 21:00:00,18.844983141700002\n2014-04-09 21:05:00,19.7364138897\n2014-04-09 21:10:00,18.5614565754\n2014-04-09 21:15:00,18.756534223699997\n2014-04-09 21:20:00,19.8782468579\n2014-04-09 21:25:00,19.4536150362\n2014-04-09 21:30:00,19.9660114839\n2014-04-09 21:35:00,19.8113281655\n2014-04-09 21:40:00,20.676686031400003\n2014-04-09 21:45:00,21.8531521814\n2014-04-09 21:50:00,18.5199283038\n2014-04-09 21:55:00,18.485346346900002\n2014-04-09 22:00:00,21.4317792093\n2014-04-09 22:05:00,20.0448113721\n2014-04-09 22:10:00,21.0858430792\n2014-04-09 22:15:00,18.8797948253\n2014-04-09 22:20:00,21.335913114500002\n2014-04-09 22:25:00,21.7162140571\n2014-04-09 22:30:00,20.5616523069\n2014-04-09 22:35:00,18.4412026523\n2014-04-09 22:40:00,21.6018971781\n2014-04-09 22:45:00,21.1902740519\n2014-04-09 22:50:00,21.023674466400003\n2014-04-09 22:55:00,18.1643337829\n2014-04-09 23:00:00,21.1999197022\n2014-04-09 23:05:00,18.555365986400002\n2014-04-09 23:10:00,18.8931714955\n2014-04-09 23:15:00,20.312438577\n2014-04-09 23:20:00,19.063582595\n2014-04-09 23:25:00,20.649356738599998\n2014-04-09 23:30:00,20.4362047869\n2014-04-09 23:35:00,18.436137449100002\n2014-04-09 23:40:00,20.6280181355\n2014-04-09 23:45:00,21.699985234499998\n2014-04-09 23:50:00,18.6480193513\n2014-04-09 23:55:00,20.3921626254\n2014-04-10 00:00:00,19.367461487699998\n2014-04-10 00:05:00,19.8384466871\n2014-04-10 00:10:00,19.1480007163\n2014-04-10 00:15:00,19.4165225454\n2014-04-10 00:20:00,18.1156472931\n2014-04-10 00:25:00,21.9262069517\n2014-04-10 00:30:00,20.4991996883\n2014-04-10 00:35:00,20.002822362\n2014-04-10 00:40:00,19.534861398\n2014-04-10 00:45:00,20.1574982353\n2014-04-10 00:50:00,19.5204239949\n2014-04-10 00:55:00,19.43963171\n2014-04-10 01:00:00,19.8557861669\n2014-04-10 01:05:00,19.1039321347\n2014-04-10 01:10:00,18.7201995999\n2014-04-10 01:15:00,20.2264235927\n2014-04-10 01:20:00,21.3710617446\n2014-04-10 01:25:00,18.6113127109\n2014-04-10 01:30:00,18.1309373624\n2014-04-10 01:35:00,18.9872469806\n2014-04-10 01:40:00,21.9188825738\n2014-04-10 01:45:00,21.315032295\n2014-04-10 01:50:00,20.3834642141\n2014-04-10 01:55:00,21.716995661\n2014-04-10 02:00:00,19.7811164673\n2014-04-10 02:05:00,21.9331224103\n2014-04-10 02:10:00,19.1852081805\n2014-04-10 02:15:00,18.9612229981\n2014-04-10 02:20:00,20.5521928046\n2014-04-10 02:25:00,19.5126158718\n2014-04-10 02:30:00,20.5054621679\n2014-04-10 02:35:00,19.2199820732\n2014-04-10 02:40:00,20.4716730274\n2014-04-10 02:45:00,19.1029850423\n2014-04-10 02:50:00,18.2038882753\n2014-04-10 02:55:00,21.6485436077\n2014-04-10 03:00:00,21.5328208075\n2014-04-10 03:05:00,21.8831925971\n2014-04-10 03:10:00,20.8661087049\n2014-04-10 03:15:00,20.7308847109\n2014-04-10 03:20:00,20.2360122803\n2014-04-10 03:25:00,18.5037696654\n2014-04-10 03:30:00,18.7569412438\n2014-04-10 03:35:00,19.1578787547\n2014-04-10 03:40:00,21.5606254503\n2014-04-10 03:45:00,18.6918780984\n2014-04-10 03:50:00,21.691492698\n2014-04-10 03:55:00,20.0911429322\n2014-04-10 04:00:00,20.8622785419\n2014-04-10 04:05:00,18.440977946700002\n2014-04-10 04:10:00,19.0761341951\n2014-04-10 04:15:00,21.8340744327\n2014-04-10 04:20:00,19.0645997877\n2014-04-10 04:25:00,19.1860868816\n2014-04-10 04:30:00,18.7903895394\n2014-04-10 04:35:00,18.5162946612\n2014-04-10 04:40:00,18.9330305658\n2014-04-10 04:45:00,20.5693075678\n2014-04-10 04:50:00,19.821470934\n2014-04-10 04:55:00,20.2150233454\n2014-04-10 05:00:00,18.4894593151\n2014-04-10 05:05:00,21.2084657887\n2014-04-10 05:10:00,21.1363788023\n2014-04-10 05:15:00,18.0863596446\n2014-04-10 05:20:00,19.534060378\n2014-04-10 05:25:00,18.2750824079\n2014-04-10 05:30:00,21.1684231177\n2014-04-10 05:35:00,20.9490787325\n2014-04-10 05:40:00,21.607952377199997\n2014-04-10 05:45:00,18.945615835799998\n2014-04-10 05:50:00,19.8251835325\n2014-04-10 05:55:00,18.7379515087\n2014-04-10 06:00:00,19.4849397379\n2014-04-10 06:05:00,20.0889730063\n2014-04-10 06:10:00,18.2133231594\n2014-04-10 06:15:00,20.8594816427\n2014-04-10 06:20:00,20.1731734415\n2014-04-10 06:25:00,21.3158360688\n2014-04-10 06:30:00,19.0871220048\n2014-04-10 06:35:00,21.6132844211\n2014-04-10 06:40:00,21.994777012100002\n2014-04-10 06:45:00,21.6771937535\n2014-04-10 06:50:00,21.111569903299998\n2014-04-10 06:55:00,21.249475211500002\n2014-04-10 07:00:00,20.2949769702\n2014-04-10 07:05:00,18.7606154517\n2014-04-10 07:10:00,20.7081627406\n2014-04-10 07:15:00,20.851012008199998\n2014-04-10 07:20:00,21.941540561100002\n2014-04-10 07:25:00,20.165205265\n2014-04-10 07:30:00,19.0854760601\n2014-04-10 07:35:00,20.734690087\n2014-04-10 07:40:00,21.9175032787\n2014-04-10 07:45:00,18.7088556331\n2014-04-10 07:50:00,19.3039916741\n2014-04-10 07:55:00,20.1675238151\n2014-04-10 08:00:00,18.6808585395\n2014-04-10 08:05:00,18.0888825581\n2014-04-10 08:10:00,19.3479324898\n2014-04-10 08:15:00,21.461483206\n2014-04-10 08:20:00,18.173873597300002\n2014-04-10 08:25:00,19.7157162361\n2014-04-10 08:30:00,21.0488030917\n2014-04-10 08:35:00,21.812730387600002\n2014-04-10 08:40:00,21.941901595999997\n2014-04-10 08:45:00,19.6878775224\n2014-04-10 08:50:00,21.8015371775\n2014-04-10 08:55:00,18.1416758931\n2014-04-10 09:00:00,71.3444703568\n2014-04-10 09:05:00,69.941346071\n2014-04-10 09:10:00,64.59349726319999\n2014-04-10 09:15:00,68.0995316092\n2014-04-10 09:20:00,62.961930833500006\n2014-04-10 09:25:00,73.0537212529\n2014-04-10 09:30:00,66.0674139634\n2014-04-10 09:35:00,69.7142047983\n2014-04-10 09:40:00,63.359357493500006\n2014-04-10 09:45:00,64.003841887\n2014-04-10 09:50:00,74.6906066429\n2014-04-10 09:55:00,71.44197496439999\n2014-04-10 10:00:00,84.7698034189\n2014-04-10 10:05:00,74.4316100841\n2014-04-10 10:10:00,72.3940158451\n2014-04-10 10:15:00,77.6476225532\n2014-04-10 10:20:00,77.51725174020001\n2014-04-10 10:25:00,72.55516989350001\n2014-04-10 10:30:00,81.2195677199\n2014-04-10 10:35:00,75.4547873345\n2014-04-10 10:40:00,72.73238838399999\n2014-04-10 10:45:00,74.9923822833\n2014-04-10 10:50:00,78.5879830183\n2014-04-10 10:55:00,81.11482886739999\n2014-04-10 11:00:00,79.2319926519\n2014-04-10 11:05:00,79.92706271819999\n2014-04-10 11:10:00,73.7777961652\n2014-04-10 11:15:00,86.1152444666\n2014-04-10 11:20:00,86.3384296449\n2014-04-10 11:25:00,82.437216494\n2014-04-10 11:30:00,71.8484099277\n2014-04-10 11:35:00,80.1096283297\n2014-04-10 11:40:00,81.5750985321\n2014-04-10 11:45:00,87.3869807619\n2014-04-10 11:50:00,87.40944885540002\n2014-04-10 11:55:00,85.2074490866\n2014-04-10 12:00:00,72.9336703174\n2014-04-10 12:05:00,87.1477193458\n2014-04-10 12:10:00,81.70441685850001\n2014-04-10 12:15:00,84.7124113017\n2014-04-10 12:20:00,78.42086749229999\n2014-04-10 12:25:00,77.0221738859\n2014-04-10 12:30:00,79.3166120401\n2014-04-10 12:35:00,74.2607722169\n2014-04-10 12:40:00,77.6198025502\n2014-04-10 12:45:00,85.61901374029999\n2014-04-10 12:50:00,72.5200791308\n2014-04-10 12:55:00,74.3247518907\n2014-04-10 13:00:00,73.9840981083\n2014-04-10 13:05:00,78.4303808731\n2014-04-10 13:10:00,87.93068198459999\n2014-04-10 13:15:00,74.7557811889\n2014-04-10 13:20:00,74.30988374020001\n2014-04-10 13:25:00,86.6200978624\n2014-04-10 13:30:00,86.0921411975\n2014-04-10 13:35:00,72.4984421169\n2014-04-10 13:40:00,84.007128812\n2014-04-10 13:45:00,82.4676542353\n2014-04-10 13:50:00,84.26362483289998\n2014-04-10 13:55:00,79.89286038729999\n2014-04-10 14:00:00,87.8578501159\n2014-04-10 14:05:00,72.6980626249\n2014-04-10 14:10:00,75.7463093851\n2014-04-10 14:15:00,78.3409752443\n2014-04-10 14:20:00,79.1926456356\n2014-04-10 14:25:00,86.737714833\n2014-04-10 14:30:00,80.95618374189999\n2014-04-10 14:35:00,72.7182852831\n2014-04-10 14:40:00,78.5220381761\n2014-04-10 14:45:00,78.6600707333\n2014-04-10 14:50:00,87.443657518\n2014-04-10 14:55:00,81.58323727300001\n2014-04-10 15:00:00,82.1696283025\n2014-04-10 15:05:00,83.4112477444\n2014-04-10 15:10:00,84.3198195729\n2014-04-10 15:15:00,82.16002837939999\n2014-04-10 15:20:00,75.7943819851\n2014-04-10 15:25:00,85.983909176\n2014-04-10 15:30:00,83.71311315300001\n2014-04-10 15:35:00,83.86912261020001\n2014-04-10 15:40:00,87.9440635566\n2014-04-10 15:45:00,84.8396100897\n2014-04-10 15:50:00,85.2656038928\n2014-04-10 15:55:00,87.22165091549999\n2014-04-10 16:00:00,74.4180011147\n2014-04-10 16:05:00,79.9634844935\n2014-04-10 16:10:00,81.2889163024\n2014-04-10 16:15:00,77.2682633122\n2014-04-10 16:20:00,85.4302894758\n2014-04-10 16:25:00,84.1985522848\n2014-04-10 16:30:00,83.5339688066\n2014-04-10 16:35:00,87.95422216370001\n2014-04-10 16:40:00,76.1499557663\n2014-04-10 16:45:00,83.76715519359999\n2014-04-10 16:50:00,80.82231641930001\n2014-04-10 16:55:00,77.0076790649\n2014-04-10 17:00:00,74.5693612969\n2014-04-10 17:05:00,86.3341082408\n2014-04-10 17:10:00,81.5272564168\n2014-04-10 17:15:00,85.19890868590001\n2014-04-10 17:20:00,80.7254887454\n2014-04-10 17:25:00,75.5196042909\n2014-04-10 17:30:00,77.4007512877\n2014-04-10 17:35:00,78.1045914874\n2014-04-10 17:40:00,87.5669233743\n2014-04-10 17:45:00,72.0901047715\n2014-04-10 17:50:00,87.77062266450001\n2014-04-10 17:55:00,87.68735248979998\n2014-04-10 18:00:00,35.1753583057\n2014-04-10 18:05:00,31.850158229899996\n2014-04-10 18:10:00,34.9683706916\n2014-04-10 18:15:00,31.331828748099998\n2014-04-10 18:20:00,28.9682788584\n2014-04-10 18:25:00,30.2358161875\n2014-04-10 18:30:00,34.8498892764\n2014-04-10 18:35:00,28.888088490799998\n2014-04-10 18:40:00,32.2943562662\n2014-04-10 18:45:00,29.283844546399997\n2014-04-10 18:50:00,30.6329322204\n2014-04-10 18:55:00,29.363788606700002\n2014-04-10 19:00:00,24.0106869054\n2014-04-10 19:05:00,22.807995528000003\n2014-04-10 19:10:00,24.2014356388\n2014-04-10 19:15:00,23.2438210589\n2014-04-10 19:20:00,24.510209163400003\n2014-04-10 19:25:00,22.4442506621\n2014-04-10 19:30:00,23.021422143400002\n2014-04-10 19:35:00,22.741862265500004\n2014-04-10 19:40:00,22.329485499\n2014-04-10 19:45:00,23.9498966433\n2014-04-10 19:50:00,23.0474713435\n2014-04-10 19:55:00,23.7498776437\n2014-04-10 20:00:00,21.652946424499998\n2014-04-10 20:05:00,19.2145207475\n2014-04-10 20:10:00,21.0950695761\n2014-04-10 20:15:00,19.2497580556\n2014-04-10 20:20:00,20.821280429\n2014-04-10 20:25:00,21.206772213\n2014-04-10 20:30:00,22.516674583\n2014-04-10 20:35:00,18.5570997198\n2014-04-10 20:40:00,18.8057286206\n2014-04-10 20:45:00,18.7475011234\n2014-04-10 20:50:00,20.0636875878\n2014-04-10 20:55:00,21.7972256671\n2014-04-10 21:00:00,21.4788311602\n2014-04-10 21:05:00,21.0484683396\n2014-04-10 21:10:00,21.6911329765\n2014-04-10 21:15:00,19.3840386402\n2014-04-10 21:20:00,18.4407111011\n2014-04-10 21:25:00,18.3201286053\n2014-04-10 21:30:00,21.5112917741\n2014-04-10 21:35:00,21.0221695028\n2014-04-10 21:40:00,20.8942745868\n2014-04-10 21:45:00,19.4516270923\n2014-04-10 21:50:00,19.6133148861\n2014-04-10 21:55:00,21.9372498417\n2014-04-10 22:00:00,18.2727439776\n2014-04-10 22:05:00,21.1151780673\n2014-04-10 22:10:00,19.2570022773\n2014-04-10 22:15:00,18.173648434500002\n2014-04-10 22:20:00,20.9904119019\n2014-04-10 22:25:00,19.3421982349\n2014-04-10 22:30:00,20.9086431112\n2014-04-10 22:35:00,20.8506149151\n2014-04-10 22:40:00,20.1584810734\n2014-04-10 22:45:00,21.1297576193\n2014-04-10 22:50:00,20.343664473900002\n2014-04-10 22:55:00,19.1649280875\n2014-04-10 23:00:00,20.9404810028\n2014-04-10 23:05:00,20.3604677209\n2014-04-10 23:10:00,18.0543748995\n2014-04-10 23:15:00,21.6107251717\n2014-04-10 23:20:00,20.1864495256\n2014-04-10 23:25:00,21.478632165500002\n2014-04-10 23:30:00,21.535081295700003\n2014-04-10 23:35:00,19.7836643594\n2014-04-10 23:40:00,20.034485866700003\n2014-04-10 23:45:00,19.6667928481\n2014-04-10 23:50:00,19.8015482667\n2014-04-10 23:55:00,21.584732106799997\n2014-04-11 00:00:00,21.1525760559\n2014-04-11 00:05:00,18.5061027053\n2014-04-11 00:10:00,20.441231126199998\n2014-04-11 00:15:00,21.9836265615\n2014-04-11 00:20:00,20.3822028049\n2014-04-11 00:25:00,21.143486502400002\n2014-04-11 00:30:00,21.076245893499998\n2014-04-11 00:35:00,19.4012701035\n2014-04-11 00:40:00,19.487397210799998\n2014-04-11 00:45:00,20.8963056872\n2014-04-11 00:50:00,19.9999341264\n2014-04-11 00:55:00,20.282282836500002\n2014-04-11 01:00:00,20.8516231615\n2014-04-11 01:05:00,21.1103001082\n2014-04-11 01:10:00,19.086066310899998\n2014-04-11 01:15:00,18.5871750377\n2014-04-11 01:20:00,19.1671785869\n2014-04-11 01:25:00,20.0301533004\n2014-04-11 01:30:00,19.3685652692\n2014-04-11 01:35:00,20.2734510354\n2014-04-11 01:40:00,18.2138628965\n2014-04-11 01:45:00,20.0390016465\n2014-04-11 01:50:00,19.4719396278\n2014-04-11 01:55:00,20.1386670196\n2014-04-11 02:00:00,19.6901334195\n2014-04-11 02:05:00,19.1369034026\n2014-04-11 02:10:00,21.616431621799997\n2014-04-11 02:15:00,18.7390599537\n2014-04-11 02:20:00,20.7254623023\n2014-04-11 02:25:00,21.698578850300002\n2014-04-11 02:30:00,20.154679838699998\n2014-04-11 02:35:00,21.5056339543\n2014-04-11 02:40:00,18.4994059137\n2014-04-11 02:45:00,19.975155081\n2014-04-11 02:50:00,19.8281011219\n2014-04-11 02:55:00,18.0324752281\n2014-04-11 03:00:00,19.7730293654\n2014-04-11 03:05:00,19.4761190255\n2014-04-11 03:10:00,20.679194911099998\n2014-04-11 03:15:00,21.753319114299998\n2014-04-11 03:20:00,18.343164353\n2014-04-11 03:25:00,19.3099055469\n2014-04-11 03:30:00,19.7762589496\n2014-04-11 03:35:00,19.8207415121\n2014-04-11 03:40:00,21.099238883399998\n2014-04-11 03:45:00,19.7735826633\n2014-04-11 03:50:00,18.1086452058\n2014-04-11 03:55:00,20.8404163784\n2014-04-11 04:00:00,21.5393187806\n2014-04-11 04:05:00,20.0556188502\n2014-04-11 04:10:00,20.3244340868\n2014-04-11 04:15:00,18.6517457559\n2014-04-11 04:20:00,18.8825837787\n2014-04-11 04:25:00,18.9406809565\n2014-04-11 04:30:00,19.722967899500002\n2014-04-11 04:35:00,21.7125808836\n2014-04-11 04:40:00,20.0871390669\n2014-04-11 04:45:00,18.7683905808\n2014-04-11 04:50:00,19.0643509435\n2014-04-11 04:55:00,19.5360601189\n2014-04-11 05:00:00,20.4930359028\n2014-04-11 05:05:00,19.760132612\n2014-04-11 05:10:00,19.5697793767\n2014-04-11 05:15:00,20.258914401600002\n2014-04-11 05:20:00,18.9673399798\n2014-04-11 05:25:00,18.3156130903\n2014-04-11 05:30:00,18.0976572593\n2014-04-11 05:35:00,19.0050366539\n2014-04-11 05:40:00,18.366368136600002\n2014-04-11 05:45:00,19.3453625541\n2014-04-11 05:50:00,21.0917341614\n2014-04-11 05:55:00,20.8651773219\n2014-04-11 06:00:00,20.443710491199997\n2014-04-11 06:05:00,21.4100009755\n2014-04-11 06:10:00,19.1282704982\n2014-04-11 06:15:00,21.5402150121\n2014-04-11 06:20:00,19.5969566787\n2014-04-11 06:25:00,19.6035732731\n2014-04-11 06:30:00,19.6214064545\n2014-04-11 06:35:00,18.392377465\n2014-04-11 06:40:00,21.9019619933\n2014-04-11 06:45:00,18.5540271113\n2014-04-11 06:50:00,19.3635428979\n2014-04-11 06:55:00,19.2772012813\n2014-04-11 07:00:00,18.298717731300002\n2014-04-11 07:05:00,18.6090405204\n2014-04-11 07:10:00,18.1794333447\n2014-04-11 07:15:00,19.1696179742\n2014-04-11 07:20:00,21.466627696099998\n2014-04-11 07:25:00,19.3577688229\n2014-04-11 07:30:00,18.4947673283\n2014-04-11 07:35:00,20.5827754735\n2014-04-11 07:40:00,21.986403648200003\n2014-04-11 07:45:00,18.9292951581\n2014-04-11 07:50:00,19.118284021500003\n2014-04-11 07:55:00,21.8873882171\n2014-04-11 08:00:00,18.7151051502\n2014-04-11 08:05:00,20.0448562698\n2014-04-11 08:10:00,18.9586085321\n2014-04-11 08:15:00,21.729407591599998\n2014-04-11 08:20:00,21.9260840583\n2014-04-11 08:25:00,21.2587913845\n2014-04-11 08:30:00,19.2591352633\n2014-04-11 08:35:00,19.6139499011\n2014-04-11 08:40:00,18.9692227347\n2014-04-11 08:45:00,21.563031868000003\n2014-04-11 08:50:00,21.658233110799998\n2014-04-11 08:55:00,19.675482649\n2014-04-11 09:00:00,127.882020134\n2014-04-11 09:05:00,115.705718858\n2014-04-11 09:10:00,122.386410329\n2014-04-11 09:15:00,127.26117784600001\n2014-04-11 09:20:00,121.15799733899999\n2014-04-11 09:25:00,120.46846823700001\n2014-04-11 09:30:00,111.62477500799999\n2014-04-11 09:35:00,131.54647790200002\n2014-04-11 09:40:00,133.655572778\n2014-04-11 09:45:00,135.642695533\n2014-04-11 09:50:00,129.43793035\n2014-04-11 09:55:00,125.21004934700001\n2014-04-11 10:00:00,138.118479694\n2014-04-11 10:05:00,159.259712824\n2014-04-11 10:10:00,147.399242667\n2014-04-11 10:15:00,150.046221935\n2014-04-11 10:20:00,150.08248245\n2014-04-11 10:25:00,154.798492005\n2014-04-11 10:30:00,130.600116725\n2014-04-11 10:35:00,136.698351395\n2014-04-11 10:40:00,149.593864645\n2014-04-11 10:45:00,156.24342053799998\n2014-04-11 10:50:00,150.16741112399998\n2014-04-11 10:55:00,142.294707802\n2014-04-11 11:00:00,144.83546133299998\n2014-04-11 11:05:00,156.04894706299999\n2014-04-11 11:10:00,156.146953473\n2014-04-11 11:15:00,152.149471713\n2014-04-11 11:20:00,142.74738558200002\n2014-04-11 11:25:00,161.62621235\n2014-04-11 11:30:00,150.505607236\n2014-04-11 11:35:00,157.614348277\n2014-04-11 11:40:00,140.448671746\n2014-04-11 11:45:00,144.313663174\n2014-04-11 11:50:00,160.119472952\n2014-04-11 11:55:00,135.556788636\n2014-04-11 12:00:00,150.160947021\n2014-04-11 12:05:00,149.243925447\n2014-04-11 12:10:00,157.318454491\n2014-04-11 12:15:00,143.257886337\n2014-04-11 12:20:00,141.37569147600001\n2014-04-11 12:25:00,162.558258037\n2014-04-11 12:30:00,151.940306437\n2014-04-11 12:35:00,137.949131962\n2014-04-11 12:40:00,140.595854562\n2014-04-11 12:45:00,164.736030621\n2014-04-11 12:50:00,140.67293255299998\n2014-04-11 12:55:00,153.101669559\n2014-04-11 13:00:00,147.562906904\n2014-04-11 13:05:00,161.523164661\n2014-04-11 13:10:00,157.611334766\n2014-04-11 13:15:00,152.86613525200002\n2014-04-11 13:20:00,135.284640106\n2014-04-11 13:25:00,161.349096329\n2014-04-11 13:30:00,148.298884492\n2014-04-11 13:35:00,162.902138864\n2014-04-11 13:40:00,149.824607501\n2014-04-11 13:45:00,155.783518728\n2014-04-11 13:50:00,137.04076296899999\n2014-04-11 13:55:00,157.310909944\n2014-04-11 14:00:00,145.131830514\n2014-04-11 14:05:00,145.532697769\n2014-04-11 14:10:00,138.551989898\n2014-04-11 14:15:00,139.397982089\n2014-04-11 14:20:00,140.56497458299998\n2014-04-11 14:25:00,144.838150922\n2014-04-11 14:30:00,161.750125145\n2014-04-11 14:35:00,146.039706362\n2014-04-11 14:40:00,156.722187857\n2014-04-11 14:45:00,137.474799425\n2014-04-11 14:50:00,152.72449239\n2014-04-11 14:55:00,149.448447071\n2014-04-11 15:00:00,164.336915344\n2014-04-11 15:05:00,160.384453878\n2014-04-11 15:10:00,148.643244206\n2014-04-11 15:15:00,158.252527354\n2014-04-11 15:20:00,140.789600396\n2014-04-11 15:25:00,151.86840507600002\n2014-04-11 15:30:00,137.23704923399998\n2014-04-11 15:35:00,145.441057524\n2014-04-11 15:40:00,141.774292682\n2014-04-11 15:45:00,156.56555760700002\n2014-04-11 15:50:00,149.701060034\n2014-04-11 15:55:00,157.530366809\n2014-04-11 16:00:00,150.458529311\n2014-04-11 16:05:00,137.594227988\n2014-04-11 16:10:00,157.060681026\n2014-04-11 16:15:00,159.99652294\n2014-04-11 16:20:00,162.10557711799999\n2014-04-11 16:25:00,152.159420767\n2014-04-11 16:30:00,157.607211091\n2014-04-11 16:35:00,157.56098053\n2014-04-11 16:40:00,139.672182907\n2014-04-11 16:45:00,139.926310173\n2014-04-11 16:50:00,137.126260936\n2014-04-11 16:55:00,144.597088241\n2014-04-11 17:00:00,149.205191425\n2014-04-11 17:05:00,164.936862395\n2014-04-11 17:10:00,147.929734621\n2014-04-11 17:15:00,156.787208083\n2014-04-11 17:20:00,155.801841654\n2014-04-11 17:25:00,141.134395882\n2014-04-11 17:30:00,136.755153861\n2014-04-11 17:35:00,151.380135374\n2014-04-11 17:40:00,156.009098543\n2014-04-11 17:45:00,164.947480513\n2014-04-11 17:50:00,145.758266891\n2014-04-11 17:55:00,161.890865026\n2014-04-11 18:00:00,44.9137655963\n2014-04-11 18:05:00,47.7425739013\n2014-04-11 18:10:00,46.9039133872\n2014-04-11 18:15:00,41.8873927765\n2014-04-11 18:20:00,42.121161338600004\n2014-04-11 18:25:00,41.5910175894\n2014-04-11 18:30:00,44.81166061020001\n2014-04-11 18:35:00,48.26135568220001\n2014-04-11 18:40:00,42.98933718399999\n2014-04-11 18:45:00,46.973833715299996\n2014-04-11 18:50:00,44.057202826499996\n2014-04-11 18:55:00,48.7323180379\n2014-04-11 19:00:00,26.703913769699998\n2014-04-11 19:05:00,26.588086346399997\n2014-04-11 19:10:00,25.325158233899998\n2014-04-11 19:15:00,24.1142136711\n2014-04-11 19:20:00,26.759595154\n2014-04-11 19:25:00,23.6179443369\n2014-04-11 19:30:00,24.1403858438\n2014-04-11 19:35:00,23.607093944899997\n2014-04-11 19:40:00,26.0780164532\n2014-04-11 19:45:00,26.1386268201\n2014-04-11 19:50:00,25.96864762\n2014-04-11 19:55:00,24.774628775500002\n2014-04-11 20:00:00,19.3575191084\n2014-04-11 20:05:00,22.7702010354\n2014-04-11 20:10:00,21.072531363299998\n2014-04-11 20:15:00,20.6485384736\n2014-04-11 20:20:00,21.4137746088\n2014-04-11 20:25:00,19.7472616542\n2014-04-11 20:30:00,19.4937647691\n2014-04-11 20:35:00,20.6424496095\n2014-04-11 20:40:00,19.8921441773\n2014-04-11 20:45:00,19.9639730542\n2014-04-11 20:50:00,22.6916877663\n2014-04-11 20:55:00,21.169434081800002\n2014-04-11 21:00:00,20.141188464200003\n2014-04-11 21:05:00,20.9738006155\n2014-04-11 21:10:00,22.032976740100004\n2014-04-11 21:15:00,18.6406616199\n2014-04-11 21:20:00,21.556013192800002\n2014-04-11 21:25:00,20.547571809100003\n2014-04-11 21:30:00,18.777941795\n2014-04-11 21:35:00,19.3881585842\n2014-04-11 21:40:00,20.136711794700002\n2014-04-11 21:45:00,20.980661437000002\n2014-04-11 21:50:00,19.1677204187\n2014-04-11 21:55:00,20.3489661134\n2014-04-11 22:00:00,20.7818229555\n2014-04-11 22:05:00,19.8361365054\n2014-04-11 22:10:00,21.496724197600003\n2014-04-11 22:15:00,21.522510288200003\n2014-04-11 22:20:00,19.9241210003\n2014-04-11 22:25:00,21.9372375602\n2014-04-11 22:30:00,18.3404092181\n2014-04-11 22:35:00,18.0509174691\n2014-04-11 22:40:00,19.5632801944\n2014-04-11 22:45:00,20.4468293513\n2014-04-11 22:50:00,20.5594755533\n2014-04-11 22:55:00,19.9471869525\n2014-04-11 23:00:00,18.5072290549\n2014-04-11 23:05:00,18.689761791\n2014-04-11 23:10:00,21.4174979051\n2014-04-11 23:15:00,21.4805767265\n2014-04-11 23:20:00,20.7042035142\n2014-04-11 23:25:00,20.6654651434\n2014-04-11 23:30:00,20.399211050799998\n2014-04-11 23:35:00,18.8195292075\n2014-04-11 23:40:00,19.721203406\n2014-04-11 23:45:00,20.7922245701\n2014-04-11 23:50:00,20.1573910715\n2014-04-11 23:55:00,18.08184025\n2014-04-12 00:00:00,21.8142272269\n2014-04-12 00:05:00,21.3792642103\n2014-04-12 00:10:00,19.0421800564\n2014-04-12 00:15:00,20.465835740699998\n2014-04-12 00:20:00,21.692957534899996\n2014-04-12 00:25:00,18.384044048499998\n2014-04-12 00:30:00,20.012117923199998\n2014-04-12 00:35:00,19.8249721034\n2014-04-12 00:40:00,19.640820021099998\n2014-04-12 00:45:00,21.3423544356\n2014-04-12 00:50:00,19.5225845868\n2014-04-12 00:55:00,18.254653333\n2014-04-12 01:00:00,18.2633509687\n2014-04-12 01:05:00,18.1709784261\n2014-04-12 01:10:00,19.6365816875\n2014-04-12 01:15:00,20.8736251108\n2014-04-12 01:20:00,18.814889847699998\n2014-04-12 01:25:00,20.585874081700002\n2014-04-12 01:30:00,20.7483538884\n2014-04-12 01:35:00,19.0208084961\n2014-04-12 01:40:00,20.4022306242\n2014-04-12 01:45:00,20.7394733601\n2014-04-12 01:50:00,19.8664544912\n2014-04-12 01:55:00,19.3468663891\n2014-04-12 02:00:00,20.4766062063\n2014-04-12 02:05:00,21.911388349299997\n2014-04-12 02:10:00,19.7073656375\n2014-04-12 02:15:00,19.5669403851\n2014-04-12 02:20:00,19.8570676097\n2014-04-12 02:25:00,18.304873573800002\n2014-04-12 02:30:00,20.2126531187\n2014-04-12 02:35:00,19.314789548900002\n2014-04-12 02:40:00,18.4856884893\n2014-04-12 02:45:00,19.8650269645\n2014-04-12 02:50:00,18.013535946300003\n2014-04-12 02:55:00,19.6071409807\n2014-04-12 03:00:00,18.422941071700002\n2014-04-12 03:05:00,18.0971708136\n2014-04-12 03:10:00,21.297900185\n2014-04-12 03:15:00,21.6649952131\n2014-04-12 03:20:00,18.830698593399998\n2014-04-12 03:25:00,20.1571930553\n2014-04-12 03:30:00,19.1118326285\n2014-04-12 03:35:00,19.974309754700002\n2014-04-12 03:40:00,19.7465252836\n2014-04-12 03:45:00,19.0762042203\n2014-04-12 03:50:00,20.8015743185\n2014-04-12 03:55:00,18.5059638373\n2014-04-12 04:00:00,18.2122911287\n2014-04-12 04:05:00,21.0707017321\n2014-04-12 04:10:00,20.6637201249\n2014-04-12 04:15:00,19.994104496600002\n2014-04-12 04:20:00,19.8711590819\n2014-04-12 04:25:00,19.989645518\n2014-04-12 04:30:00,19.7480963044\n2014-04-12 04:35:00,19.5715691833\n2014-04-12 04:40:00,19.9987624115\n2014-04-12 04:45:00,20.114060684600002\n2014-04-12 04:50:00,20.767609256300002\n2014-04-12 04:55:00,20.8448286429\n2014-04-12 05:00:00,19.5105163206\n2014-04-12 05:05:00,19.654162091\n2014-04-12 05:10:00,19.4947886789\n2014-04-12 05:15:00,20.1461430945\n2014-04-12 05:20:00,19.8134141517\n2014-04-12 05:25:00,21.5583858525\n2014-04-12 05:30:00,20.7854450677\n2014-04-12 05:35:00,21.594625535\n2014-04-12 05:40:00,20.836547966199998\n2014-04-12 05:45:00,21.883968594099997\n2014-04-12 05:50:00,20.542947113\n2014-04-12 05:55:00,21.8542005527\n2014-04-12 06:00:00,18.6326795616\n2014-04-12 06:05:00,18.2099107233\n2014-04-12 06:10:00,20.3165007408\n2014-04-12 06:15:00,21.9339728232\n2014-04-12 06:20:00,19.6704209892\n2014-04-12 06:25:00,18.8481734488\n2014-04-12 06:30:00,20.0861657968\n2014-04-12 06:35:00,20.5951944983\n2014-04-12 06:40:00,19.2607147821\n2014-04-12 06:45:00,20.859077434\n2014-04-12 06:50:00,21.900458028200003\n2014-04-12 06:55:00,21.5878524868\n2014-04-12 07:00:00,19.166341494\n2014-04-12 07:05:00,19.3068947326\n2014-04-12 07:10:00,19.4861648978\n2014-04-12 07:15:00,19.5782111136\n2014-04-12 07:20:00,18.4012779968\n2014-04-12 07:25:00,21.0478513556\n2014-04-12 07:30:00,19.4613570544\n2014-04-12 07:35:00,21.519279906799998\n2014-04-12 07:40:00,21.7077624925\n2014-04-12 07:45:00,18.0977252372\n2014-04-12 07:50:00,21.9540122797\n2014-04-12 07:55:00,20.840090926\n2014-04-12 08:00:00,20.081568904\n2014-04-12 08:05:00,19.558110433499998\n2014-04-12 08:10:00,20.0740725304\n2014-04-12 08:15:00,19.2984988959\n2014-04-12 08:20:00,20.4907512548\n2014-04-12 08:25:00,18.3719211058\n2014-04-12 08:30:00,20.4844904116\n2014-04-12 08:35:00,19.1013794006\n2014-04-12 08:40:00,18.070539316199998\n2014-04-12 08:45:00,20.2108230647\n2014-04-12 08:50:00,20.3137910234\n2014-04-12 08:55:00,19.7062760188\n2014-04-12 09:00:00,62.18309276270001\n2014-04-12 09:05:00,73.3494641581\n2014-04-12 09:10:00,69.5154589783\n2014-04-12 09:15:00,62.7737008741\n2014-04-12 09:20:00,68.1486558417\n2014-04-12 09:25:00,67.9626586969\n2014-04-12 09:30:00,62.021465415600005\n2014-04-12 09:35:00,69.45329196899999\n2014-04-12 09:40:00,72.1932390253\n2014-04-12 09:45:00,71.3865095378\n2014-04-12 09:50:00,63.960384032600004\n2014-04-12 09:55:00,72.9271784019\n2014-04-12 10:00:00,75.156254411\n2014-04-12 10:05:00,84.5298100311\n2014-04-12 10:10:00,70.9535284048\n2014-04-12 10:15:00,77.3859588458\n2014-04-12 10:20:00,79.1073703338\n2014-04-12 10:25:00,73.6835295283\n2014-04-12 10:30:00,81.8118205289\n2014-04-12 10:35:00,79.56942095069999\n2014-04-12 10:40:00,70.1210584667\n2014-04-12 10:45:00,79.28188052760001\n2014-04-12 10:50:00,77.4677421982\n2014-04-12 10:55:00,72.8823732104\n2014-04-12 11:00:00,87.4043798032\n2014-04-12 11:05:00,85.83646754649999\n2014-04-12 11:10:00,76.2200423817\n2014-04-12 11:15:00,80.1731919244\n2014-04-12 11:20:00,76.6016500331\n2014-04-12 11:25:00,83.901484434\n2014-04-12 11:30:00,86.36399111360001\n2014-04-12 11:35:00,77.2748101644\n2014-04-12 11:40:00,84.3800118984\n2014-04-12 11:45:00,79.4946735593\n2014-04-12 11:50:00,77.8751854391\n2014-04-12 11:55:00,86.4926611358\n2014-04-12 12:00:00,80.0702752495\n2014-04-12 12:05:00,79.3831937225\n2014-04-12 12:10:00,82.65963969090001\n2014-04-12 12:15:00,76.0883315196\n2014-04-12 12:20:00,77.10404990949999\n2014-04-12 12:25:00,86.8084380998\n2014-04-12 12:30:00,82.757049754\n2014-04-12 12:35:00,85.1239229311\n2014-04-12 12:40:00,76.24618284510001\n2014-04-12 12:45:00,80.60380226720001\n2014-04-12 12:50:00,87.43728946350002\n2014-04-12 12:55:00,77.0067432696\n2014-04-12 13:00:00,74.5497273914\n2014-04-12 13:05:00,80.1549343293\n2014-04-12 13:10:00,78.18636818659999\n2014-04-12 13:15:00,74.53534294800001\n2014-04-12 13:20:00,86.1961300859\n2014-04-12 13:25:00,87.830498189\n2014-04-12 13:30:00,81.0778515355\n2014-04-12 13:35:00,84.3745735352\n2014-04-12 13:40:00,85.7240352054\n2014-04-12 13:45:00,83.1957403254\n2014-04-12 13:50:00,72.6890472266\n2014-04-12 13:55:00,74.504262392\n2014-04-12 14:00:00,73.1323165387\n2014-04-12 14:05:00,72.15461011869998\n2014-04-12 14:10:00,76.8922515349\n2014-04-12 14:15:00,78.2739380383\n2014-04-12 14:20:00,75.8528346065\n2014-04-12 14:25:00,73.030168753\n2014-04-12 14:30:00,80.4739465185\n2014-04-12 14:35:00,76.3694432101\n2014-04-12 14:40:00,84.7325271213\n2014-04-12 14:45:00,72.1253797616\n2014-04-12 14:50:00,85.4763297598\n2014-04-12 14:55:00,87.2718696123\n2014-04-12 15:00:00,83.4573598121\n2014-04-12 15:05:00,83.7375011565\n2014-04-12 15:10:00,86.93616239049999\n2014-04-12 15:15:00,75.34441725149999\n2014-04-12 15:20:00,87.9122051261\n2014-04-12 15:25:00,84.37488924729999\n2014-04-12 15:30:00,83.62432853199999\n2014-04-12 15:35:00,77.7767026004\n2014-04-12 15:40:00,80.7316647351\n2014-04-12 15:45:00,82.4618929706\n2014-04-12 15:50:00,81.92469929640001\n2014-04-12 15:55:00,83.27895473\n2014-04-12 16:00:00,73.3179670545\n2014-04-12 16:05:00,77.6902257598\n2014-04-12 16:10:00,78.943848693\n2014-04-12 16:15:00,76.16992251949999\n2014-04-12 16:20:00,74.7618927812\n2014-04-12 16:25:00,74.2226971708\n2014-04-12 16:30:00,77.8619847808\n2014-04-12 16:35:00,79.8949138105\n2014-04-12 16:40:00,73.0074828677\n2014-04-12 16:45:00,87.1431621983\n2014-04-12 16:50:00,84.2437314175\n2014-04-12 16:55:00,83.6934676792\n2014-04-12 17:00:00,74.7657396898\n2014-04-12 17:05:00,81.6607809304\n2014-04-12 17:10:00,80.4755682463\n2014-04-12 17:15:00,87.7194678483\n2014-04-12 17:20:00,83.9627160796\n2014-04-12 17:25:00,81.212158954\n2014-04-12 17:30:00,85.6129697881\n2014-04-12 17:35:00,74.4814797329\n2014-04-12 17:40:00,72.24343673359999\n2014-04-12 17:45:00,83.0437014458\n2014-04-12 17:50:00,73.5729551118\n2014-04-12 17:55:00,73.8469098825\n2014-04-12 18:00:00,33.5659502045\n2014-04-12 18:05:00,30.5314171404\n2014-04-12 18:10:00,32.8232334776\n2014-04-12 18:15:00,34.6713976701\n2014-04-12 18:20:00,30.825431084\n2014-04-12 18:25:00,30.1897168137\n2014-04-12 18:30:00,29.4819967954\n2014-04-12 18:35:00,29.634953423200002\n2014-04-12 18:40:00,29.1982196444\n2014-04-12 18:45:00,29.360905587199998\n2014-04-12 18:50:00,31.5648233079\n2014-04-12 18:55:00,30.8535303643\n2014-04-12 19:00:00,23.32539116860001\n2014-04-12 19:05:00,24.0586813092\n2014-04-12 19:10:00,23.6757826513\n2014-04-12 19:15:00,22.5372536735\n2014-04-12 19:20:00,20.6189395496\n2014-04-12 19:25:00,23.3397561517\n2014-04-12 19:30:00,21.7854714917\n2014-04-12 19:35:00,20.5437126378\n2014-04-12 19:40:00,23.9342481913\n2014-04-12 19:45:00,21.6752088079\n2014-04-12 19:50:00,21.1377536101\n2014-04-12 19:55:00,24.0641039294\n2014-04-12 20:00:00,22.127140059600002\n2014-04-12 20:05:00,19.820424311300002\n2014-04-12 20:10:00,19.8852663748\n2014-04-12 20:15:00,20.8061581993\n2014-04-12 20:20:00,21.4361761014\n2014-04-12 20:25:00,18.6906589067\n2014-04-12 20:30:00,20.862335369500002\n2014-04-12 20:35:00,22.334750705\n2014-04-12 20:40:00,19.5055363688\n2014-04-12 20:45:00,22.154556003099998\n2014-04-12 20:50:00,22.323889255900003\n2014-04-12 20:55:00,19.534453079000002\n2014-04-12 21:00:00,21.1176880877\n2014-04-12 21:05:00,19.046084466900002\n2014-04-12 21:10:00,21.0510067297\n2014-04-12 21:15:00,21.2913902965\n2014-04-12 21:20:00,19.0799691177\n2014-04-12 21:25:00,20.9636228183\n2014-04-12 21:30:00,21.3504105104\n2014-04-12 21:35:00,19.527600155\n2014-04-12 21:40:00,18.7604309514\n2014-04-12 21:45:00,18.4560239438\n2014-04-12 21:50:00,20.398974093299998\n2014-04-12 21:55:00,22.0175719073\n2014-04-12 22:00:00,21.3122413989\n2014-04-12 22:05:00,19.7623121702\n2014-04-12 22:10:00,20.165824225799998\n2014-04-12 22:15:00,19.1364649193\n2014-04-12 22:20:00,18.6701696332\n2014-04-12 22:25:00,19.9474558148\n2014-04-12 22:30:00,19.873066100899997\n2014-04-12 22:35:00,20.1070040124\n2014-04-12 22:40:00,21.8321571011\n2014-04-12 22:45:00,20.4351801485\n2014-04-12 22:50:00,20.4426935003\n2014-04-12 22:55:00,18.5298706574\n2014-04-12 23:00:00,21.990176765999998\n2014-04-12 23:05:00,21.0954293198\n2014-04-12 23:10:00,21.5129430664\n2014-04-12 23:15:00,19.6609758281\n2014-04-12 23:20:00,20.0123540156\n2014-04-12 23:25:00,20.092192195\n2014-04-12 23:30:00,18.7799832199\n2014-04-12 23:35:00,20.761942150899998\n2014-04-12 23:40:00,21.616056378499998\n2014-04-12 23:45:00,18.6584049968\n2014-04-12 23:50:00,18.3487953846\n2014-04-12 23:55:00,20.9568985722\n2014-04-13 00:00:00,19.0928073267\n2014-04-13 00:05:00,20.4954501665\n2014-04-13 00:10:00,20.783033352\n2014-04-13 00:15:00,19.287643054300002\n2014-04-13 00:20:00,21.2605783897\n2014-04-13 00:25:00,20.1999559285\n2014-04-13 00:30:00,21.4759976318\n2014-04-13 00:35:00,21.053174210199998\n2014-04-13 00:40:00,21.4743025281\n2014-04-13 00:45:00,18.0806455285\n2014-04-13 00:50:00,18.974025043\n2014-04-13 00:55:00,18.360031761800002\n2014-04-13 01:00:00,19.7683320688\n2014-04-13 01:05:00,21.5598404865\n2014-04-13 01:10:00,19.870161049100002\n2014-04-13 01:15:00,21.3988521783\n2014-04-13 01:20:00,19.3087129521\n2014-04-13 01:25:00,19.3582802912\n2014-04-13 01:30:00,21.5822469213\n2014-04-13 01:35:00,19.703268586\n2014-04-13 01:40:00,21.159061951199998\n2014-04-13 01:45:00,18.9465741915\n2014-04-13 01:50:00,21.7952033187\n2014-04-13 01:55:00,20.298312986099997\n2014-04-13 02:00:00,21.037294274300002\n2014-04-13 02:05:00,18.358062799200003\n2014-04-13 02:10:00,19.9706569033\n2014-04-13 02:15:00,21.604153990900002\n2014-04-13 02:20:00,21.508154516199998\n2014-04-13 02:25:00,18.1872558289\n2014-04-13 02:30:00,19.2147938765\n2014-04-13 02:35:00,19.7732800259\n2014-04-13 02:40:00,18.6890592574\n2014-04-13 02:45:00,20.919993244\n2014-04-13 02:50:00,18.7380479824\n2014-04-13 02:55:00,19.3865587775\n2014-04-13 03:00:00,20.6531225474\n2014-04-13 03:05:00,19.9283573781\n2014-04-13 03:10:00,20.9542841545\n2014-04-13 03:15:00,21.844831604899998\n2014-04-13 03:20:00,18.4661867509\n2014-04-13 03:25:00,20.8382708656\n2014-04-13 03:30:00,18.9213766225\n2014-04-13 03:35:00,19.6579069096\n2014-04-13 03:40:00,18.1314509032\n2014-04-13 03:45:00,18.5436295292\n2014-04-13 03:50:00,19.2791091562\n2014-04-13 03:55:00,19.367943221199997\n2014-04-13 04:00:00,21.5983408658\n2014-04-13 04:05:00,20.9672516371\n2014-04-13 04:10:00,21.8887318727\n2014-04-13 04:15:00,20.3962860413\n2014-04-13 04:20:00,18.9668549284\n2014-04-13 04:25:00,19.3106201197\n2014-04-13 04:30:00,19.279343693199998\n2014-04-13 04:35:00,19.305977310699998\n2014-04-13 04:40:00,20.691856692400002\n2014-04-13 04:45:00,20.1232317124\n2014-04-13 04:50:00,19.5416967123\n2014-04-13 04:55:00,18.5963590749\n2014-04-13 05:00:00,18.0885566518\n2014-04-13 05:05:00,18.8753387104\n2014-04-13 05:10:00,18.429885615899998\n2014-04-13 05:15:00,21.1417801234\n2014-04-13 05:20:00,18.4499918313\n2014-04-13 05:25:00,20.8969129492\n2014-04-13 05:30:00,19.5426347591\n2014-04-13 05:35:00,18.293513559\n2014-04-13 05:40:00,21.2509201977\n2014-04-13 05:45:00,20.318522280899998\n2014-04-13 05:50:00,18.9430460515\n2014-04-13 05:55:00,21.5787246973\n2014-04-13 06:00:00,18.1810332555\n2014-04-13 06:05:00,18.8072784328\n2014-04-13 06:10:00,21.008187711199998\n2014-04-13 06:15:00,20.8375117212\n2014-04-13 06:20:00,19.1570867749\n2014-04-13 06:25:00,18.248099501400002\n2014-04-13 06:30:00,21.4323122889\n2014-04-13 06:35:00,19.2547905523\n2014-04-13 06:40:00,18.7828536597\n2014-04-13 06:45:00,20.0642472894\n2014-04-13 06:50:00,21.6409087971\n2014-04-13 06:55:00,18.1741863114\n2014-04-13 07:00:00,21.0632163521\n2014-04-13 07:05:00,20.2898929118\n2014-04-13 07:10:00,19.701796466199998\n2014-04-13 07:15:00,20.976321776400003\n2014-04-13 07:20:00,21.863297697800004\n2014-04-13 07:25:00,18.9168248447\n2014-04-13 07:30:00,18.5745894603\n2014-04-13 07:35:00,21.6515269809\n2014-04-13 07:40:00,20.6758123098\n2014-04-13 07:45:00,19.751944086199998\n2014-04-13 07:50:00,20.2930382811\n2014-04-13 07:55:00,20.982455620699998\n2014-04-13 08:00:00,21.0921275948\n2014-04-13 08:05:00,21.6795767233\n2014-04-13 08:10:00,19.7073711556\n2014-04-13 08:15:00,19.1736436401\n2014-04-13 08:20:00,20.5586570672\n2014-04-13 08:25:00,19.6629115971\n2014-04-13 08:30:00,20.3783938158\n2014-04-13 08:35:00,19.6799431938\n2014-04-13 08:40:00,18.611983146700002\n2014-04-13 08:45:00,19.8777070066\n2014-04-13 08:50:00,20.7636712878\n2014-04-13 08:55:00,21.1971352307\n2014-04-13 09:00:00,67.9092373644\n2014-04-13 09:05:00,63.4472353069\n2014-04-13 09:10:00,66.8397528512\n2014-04-13 09:15:00,71.8935974322\n2014-04-13 09:20:00,66.8148860804\n2014-04-13 09:25:00,70.672818793\n2014-04-13 09:30:00,68.0981060708\n2014-04-13 09:35:00,64.48063450149999\n2014-04-13 09:40:00,72.0276469091\n2014-04-13 09:45:00,62.3453029754\n2014-04-13 09:50:00,68.3385078455\n2014-04-13 09:55:00,64.0409180657\n2014-04-13 10:00:00,70.880858555\n2014-04-13 10:05:00,77.6455347035\n2014-04-13 10:10:00,77.5932046601\n2014-04-13 10:15:00,80.811101994\n2014-04-13 10:20:00,81.3985307562\n2014-04-13 10:25:00,81.1353239045\n2014-04-13 10:30:00,76.1963515349\n2014-04-13 10:35:00,79.6438254978\n2014-04-13 10:40:00,78.7941901658\n2014-04-13 10:45:00,76.3826384549\n2014-04-13 10:50:00,79.1087410138\n2014-04-13 10:55:00,84.5412870465\n2014-04-13 11:00:00,74.63578209949999\n2014-04-13 11:05:00,85.9733994114\n2014-04-13 11:10:00,72.4181564944\n2014-04-13 11:15:00,76.472622042\n2014-04-13 11:20:00,76.1506620339\n2014-04-13 11:25:00,81.5297106757\n2014-04-13 11:30:00,73.6550016331\n2014-04-13 11:35:00,85.6008564187\n2014-04-13 11:40:00,84.7452816002\n2014-04-13 11:45:00,81.93845479630002\n2014-04-13 11:50:00,78.8586135808\n2014-04-13 11:55:00,86.4057328942\n2014-04-13 12:00:00,85.1895945417\n2014-04-13 12:05:00,79.8930555185\n2014-04-13 12:10:00,83.1300977029\n2014-04-13 12:15:00,80.97359417979999\n2014-04-13 12:20:00,81.3093873232\n2014-04-13 12:25:00,77.2028623705\n2014-04-13 12:30:00,79.29808164960002\n2014-04-13 12:35:00,73.1620429612\n2014-04-13 12:40:00,77.6243179718\n2014-04-13 12:45:00,83.0334963383\n2014-04-13 12:50:00,87.14675474030001\n2014-04-13 12:55:00,87.3041349732\n2014-04-13 13:00:00,80.8721519302\n2014-04-13 13:05:00,81.6863465995\n2014-04-13 13:10:00,74.9535457987\n2014-04-13 13:15:00,83.1049797464\n2014-04-13 13:20:00,73.112989353\n2014-04-13 13:25:00,76.53659777979999\n2014-04-13 13:30:00,82.6739670413\n2014-04-13 13:35:00,76.9464905138\n2014-04-13 13:40:00,72.7800785738\n2014-04-13 13:45:00,85.2894521672\n2014-04-13 13:50:00,76.9468084469\n2014-04-13 13:55:00,72.99216127369998\n2014-04-13 14:00:00,73.1930971947\n2014-04-13 14:05:00,76.0244914299\n2014-04-13 14:10:00,74.84466243930001\n2014-04-13 14:15:00,84.38475122199999\n2014-04-13 14:20:00,77.1432416933\n2014-04-13 14:25:00,84.8710585543\n2014-04-13 14:30:00,74.7779464514\n2014-04-13 14:35:00,79.8822323415\n2014-04-13 14:40:00,83.0046097243\n2014-04-13 14:45:00,82.4278969329\n2014-04-13 14:50:00,81.6141528915\n2014-04-13 14:55:00,86.7929793679\n2014-04-13 15:00:00,75.65567606180001\n2014-04-13 15:05:00,79.8987402361\n2014-04-13 15:10:00,86.1430538199\n2014-04-13 15:15:00,73.245597085\n2014-04-13 15:20:00,72.89351250760001\n2014-04-13 15:25:00,75.7321095657\n2014-04-13 15:30:00,82.1275510805\n2014-04-13 15:35:00,76.15734290569999\n2014-04-13 15:40:00,75.0431177201\n2014-04-13 15:45:00,79.3400753737\n2014-04-13 15:50:00,81.8167836516\n2014-04-13 15:55:00,75.9761939338\n2014-04-13 16:00:00,76.8109115103\n2014-04-13 16:05:00,81.8167917884\n2014-04-13 16:10:00,87.1316474587\n2014-04-13 16:15:00,82.7957086709\n2014-04-13 16:20:00,84.5263040065\n2014-04-13 16:25:00,77.8688120077\n2014-04-13 16:30:00,76.35592314649999\n2014-04-13 16:35:00,79.2681316961\n2014-04-13 16:40:00,84.91396222430001\n2014-04-13 16:45:00,79.3006420111\n2014-04-13 16:50:00,85.5474422892\n2014-04-13 16:55:00,87.820183076\n2014-04-13 17:00:00,73.1523985612\n2014-04-13 17:05:00,72.7265345703\n2014-04-13 17:10:00,74.3934066795\n2014-04-13 17:15:00,78.1498848022\n2014-04-13 17:20:00,74.0966468932\n2014-04-13 17:25:00,85.93059864450001\n2014-04-13 17:30:00,72.3703122262\n2014-04-13 17:35:00,77.0526538731\n2014-04-13 17:40:00,74.9550852891\n2014-04-13 17:45:00,86.9045959111\n2014-04-13 17:50:00,82.7116643169\n2014-04-13 17:55:00,86.59245085170002\n2014-04-13 18:00:00,35.022897021599995\n2014-04-13 18:05:00,31.981422619099998\n2014-04-13 18:10:00,30.299636474\n2014-04-13 18:15:00,30.039858464\n2014-04-13 18:20:00,30.2266749113\n2014-04-13 18:25:00,33.3349907685\n2014-04-13 18:30:00,29.0588470807\n2014-04-13 18:35:00,29.128705274699996\n2014-04-13 18:40:00,32.6921085544\n2014-04-13 18:45:00,32.9091594206\n2014-04-13 18:50:00,33.0576763686\n2014-04-13 18:55:00,31.180029242800003\n2014-04-13 19:00:00,23.7706317975\n2014-04-13 19:05:00,22.550636916\n2014-04-13 19:10:00,20.6324848906\n2014-04-13 19:15:00,23.7310035938\n2014-04-13 19:20:00,24.4297423423\n2014-04-13 19:25:00,20.4289615616\n2014-04-13 19:30:00,21.913252795300004\n2014-04-13 19:35:00,22.3440706551\n2014-04-13 19:40:00,20.8161878632\n2014-04-13 19:45:00,24.0473347669\n2014-04-13 19:50:00,21.4329892334\n2014-04-13 19:55:00,23.6678769606\n2014-04-13 20:00:00,21.1803931442\n2014-04-13 20:05:00,20.881595438199998\n2014-04-13 20:10:00,19.2190168776\n2014-04-13 20:15:00,19.336001388099998\n2014-04-13 20:20:00,18.625938842300002\n2014-04-13 20:25:00,19.4179578794\n2014-04-13 20:30:00,19.8469367862\n2014-04-13 20:35:00,21.8445629025\n2014-04-13 20:40:00,19.932744123699997\n2014-04-13 20:45:00,21.522930563899997\n2014-04-13 20:50:00,20.231955341400003\n2014-04-13 20:55:00,21.6468203462\n2014-04-13 21:00:00,22.010230762600003\n2014-04-13 21:05:00,19.0503711436\n2014-04-13 21:10:00,21.552323354099997\n2014-04-13 21:15:00,20.5856353173\n2014-04-13 21:20:00,21.3712690439\n2014-04-13 21:25:00,20.7052540078\n2014-04-13 21:30:00,19.7903378112\n2014-04-13 21:35:00,19.0030787501\n2014-04-13 21:40:00,18.3678855327\n2014-04-13 21:45:00,20.2387553609\n2014-04-13 21:50:00,22.0667185852\n2014-04-13 21:55:00,21.052737571199998\n2014-04-13 22:00:00,19.327919163\n2014-04-13 22:05:00,21.329275656300002\n2014-04-13 22:10:00,21.0961688889\n2014-04-13 22:15:00,19.1449046455\n2014-04-13 22:20:00,18.0745648911\n2014-04-13 22:25:00,18.4903842896\n2014-04-13 22:30:00,21.5298736064\n2014-04-13 22:35:00,21.3667445328\n2014-04-13 22:40:00,19.1992495966\n2014-04-13 22:45:00,19.1591568462\n2014-04-13 22:50:00,21.1917845396\n2014-04-13 22:55:00,21.7718307808\n2014-04-13 23:00:00,21.1206034025\n2014-04-13 23:05:00,20.426235790499998\n2014-04-13 23:10:00,18.9743277711\n2014-04-13 23:15:00,20.106851428800002\n2014-04-13 23:20:00,18.937682769600002\n2014-04-13 23:25:00,21.236122231099998\n2014-04-13 23:30:00,19.5515975023\n2014-04-13 23:35:00,21.3388851453\n2014-04-13 23:40:00,19.530185945899998\n2014-04-13 23:45:00,21.3006865654\n2014-04-13 23:50:00,19.3369832468\n2014-04-13 23:55:00,19.7643248384\n2014-04-14 00:00:00,20.4619536774\n2014-04-14 00:05:00,18.2811504561\n2014-04-14 00:10:00,21.7928282473\n2014-04-14 00:15:00,20.2944231445\n2014-04-14 00:20:00,20.0312800588\n2014-04-14 00:25:00,21.3575758845\n2014-04-14 00:30:00,21.4630509196\n2014-04-14 00:35:00,20.089041618099998\n2014-04-14 00:40:00,21.7090493032\n2014-04-14 00:45:00,18.2589510643\n2014-04-14 00:50:00,18.452903169000002\n2014-04-14 00:55:00,20.3871529201\n2014-04-14 01:00:00,19.4162634472\n2014-04-14 01:05:00,19.8569006648\n2014-04-14 01:10:00,19.3123168716\n2014-04-14 01:15:00,19.6189012458\n2014-04-14 01:20:00,21.2905853886\n2014-04-14 01:25:00,20.3739047994\n2014-04-14 01:30:00,21.9893781971\n2014-04-14 01:35:00,21.147516791300003\n2014-04-14 01:40:00,19.0946650164\n2014-04-14 01:45:00,19.0573804709\n2014-04-14 01:50:00,19.3435930805\n2014-04-14 01:55:00,21.3730379226\n2014-04-14 02:00:00,18.1091506026\n2014-04-14 02:05:00,18.920725115499998\n2014-04-14 02:10:00,21.6196736814\n2014-04-14 02:15:00,20.5595857443\n2014-04-14 02:20:00,18.907388382\n2014-04-14 02:25:00,18.8765798729\n2014-04-14 02:30:00,21.450472407\n2014-04-14 02:35:00,21.5750300331\n2014-04-14 02:40:00,19.0245243638\n2014-04-14 02:45:00,19.6820414323\n2014-04-14 02:50:00,21.338382954500002\n2014-04-14 02:55:00,21.0840297544\n2014-04-14 03:00:00,21.2556644263\n2014-04-14 03:05:00,20.0735927632\n2014-04-14 03:10:00,21.6461961932\n2014-04-14 03:15:00,19.3038061758\n2014-04-14 03:20:00,18.6266885374\n2014-04-14 03:25:00,20.8349293303\n2014-04-14 03:30:00,20.157417664\n2014-04-14 03:35:00,21.4183430752\n2014-04-14 03:40:00,18.3246369965\n2014-04-14 03:45:00,21.3747696138\n2014-04-14 03:50:00,19.1731786128\n2014-04-14 03:55:00,20.6194226687\n2014-04-14 04:00:00,18.1605151563\n2014-04-14 04:05:00,20.4383251852\n2014-04-14 04:10:00,20.8690867567\n2014-04-14 04:15:00,19.475000857999998\n2014-04-14 04:20:00,18.861642821\n2014-04-14 04:25:00,20.1505227064\n2014-04-14 04:30:00,21.3327632177\n2014-04-14 04:35:00,19.2941894332\n2014-04-14 04:40:00,19.0098771901\n2014-04-14 04:45:00,19.1157412346\n2014-04-14 04:50:00,21.7965286117\n2014-04-14 04:55:00,19.4371076631\n2014-04-14 05:00:00,18.014416959600002\n2014-04-14 05:05:00,21.1267248318\n2014-04-14 05:10:00,20.797099181300002\n2014-04-14 05:15:00,18.5142730584\n2014-04-14 05:20:00,21.9396169965\n2014-04-14 05:25:00,20.4322491412\n2014-04-14 05:30:00,20.0031179638\n2014-04-14 05:35:00,19.5288770705\n2014-04-14 05:40:00,21.5946910223\n2014-04-14 05:45:00,18.9758539257\n2014-04-14 05:50:00,19.143075600899998\n2014-04-14 05:55:00,18.4896432267\n2014-04-14 06:00:00,21.036476382300002\n2014-04-14 06:05:00,20.3821971216\n2014-04-14 06:10:00,20.436264677\n2014-04-14 06:15:00,18.873881724100002\n2014-04-14 06:20:00,20.6046735565\n2014-04-14 06:25:00,21.061833789\n2014-04-14 06:30:00,19.4315541229\n2014-04-14 06:35:00,21.2053885758\n2014-04-14 06:40:00,19.395162354100002\n2014-04-14 06:45:00,21.032553846\n2014-04-14 06:50:00,18.1349204298\n2014-04-14 06:55:00,20.2046584059\n2014-04-14 07:00:00,21.8781062426\n2014-04-14 07:05:00,21.9249784027\n2014-04-14 07:10:00,19.1270103134\n2014-04-14 07:15:00,19.765596364300002\n2014-04-14 07:20:00,18.2519116319\n2014-04-14 07:25:00,21.4933652304\n2014-04-14 07:30:00,20.2742886126\n2014-04-14 07:35:00,19.5404027158\n2014-04-14 07:40:00,18.451082234\n2014-04-14 07:45:00,21.787069141999996\n2014-04-14 07:50:00,20.120876191300002\n2014-04-14 07:55:00,19.1317117163\n2014-04-14 08:00:00,19.4008605205\n2014-04-14 08:05:00,19.0827887237\n2014-04-14 08:10:00,20.4072392354\n2014-04-14 08:15:00,21.7198543031\n2014-04-14 08:20:00,21.4267752133\n2014-04-14 08:25:00,19.8415235017\n2014-04-14 08:30:00,21.3059974492\n2014-04-14 08:35:00,19.6924219251\n2014-04-14 08:40:00,19.009228563\n2014-04-14 08:45:00,21.9336604611\n2014-04-14 08:50:00,19.2155502719\n2014-04-14 08:55:00,19.2948969239\n2014-04-14 09:00:00,74.6598230019\n2014-04-14 09:05:00,63.0214139071\n2014-04-14 09:10:00,71.54326223689999\n2014-04-14 09:15:00,73.9270535154\n2014-04-14 09:20:00,68.1604119221\n2014-04-14 09:25:00,61.234295959200004\n2014-04-14 09:30:00,66.3008016399\n2014-04-14 09:35:00,62.7173382964\n2014-04-14 09:40:00,66.8601521887\n2014-04-14 09:45:00,71.9443639583\n2014-04-14 09:50:00,67.16647706479999\n2014-04-14 09:55:00,67.07418165029999\n2014-04-14 10:00:00,78.4813726818\n2014-04-14 10:05:00,78.8678378753\n2014-04-14 10:10:00,83.1297187126\n2014-04-14 10:15:00,74.6256764168\n2014-04-14 10:20:00,82.592338023\n2014-04-14 10:25:00,78.6232917797\n2014-04-14 10:30:00,74.5042186116\n2014-04-14 10:35:00,74.420356203\n2014-04-14 10:40:00,75.4448542655\n2014-04-14 10:45:00,79.50419912550001\n2014-04-14 10:50:00,73.42219807069999\n2014-04-14 10:55:00,84.12357687720001\n2014-04-14 11:00:00,80.7114097388\n2014-04-14 11:05:00,86.1999309173\n2014-04-14 11:10:00,72.3060149188\n2014-04-14 11:15:00,77.0168912358\n2014-04-14 11:20:00,71.9307330356\n2014-04-14 11:25:00,75.8978928673\n2014-04-14 11:30:00,85.277350935\n2014-04-14 11:35:00,72.1502409208\n2014-04-14 11:40:00,78.5044834771\n2014-04-14 11:45:00,73.4377866888\n2014-04-14 11:50:00,78.1974338449\n2014-04-14 11:55:00,84.9090955961\n2014-04-14 12:00:00,81.87077357060001\n2014-04-14 12:05:00,83.6875558035\n2014-04-14 12:10:00,77.4925630482\n2014-04-14 12:15:00,87.00583068440002\n2014-04-14 12:20:00,83.2481756683\n2014-04-14 12:25:00,78.6542825712\n2014-04-14 12:30:00,78.7288486795\n2014-04-14 12:35:00,86.59490811090002\n2014-04-14 12:40:00,81.12500812489999\n2014-04-14 12:45:00,83.20210487760001\n2014-04-14 12:50:00,78.5781565159\n2014-04-14 12:55:00,75.48838933520001\n2014-04-14 13:00:00,83.5568902042\n2014-04-14 13:05:00,81.705566311\n2014-04-14 13:10:00,80.0022809301\n2014-04-14 13:15:00,81.9646587995\n2014-04-14 13:20:00,75.3144895604\n2014-04-14 13:25:00,84.6826905799\n2014-04-14 13:30:00,87.1496839352\n2014-04-14 13:35:00,86.2369484706\n2014-04-14 13:40:00,77.1244576117\n2014-04-14 13:45:00,78.4772533103\n2014-04-14 13:50:00,84.9140525319\n2014-04-14 13:55:00,81.5023088434\n2014-04-14 14:00:00,80.7627543005\n2014-04-14 14:05:00,86.8221038195\n2014-04-14 14:10:00,80.57253170850001\n2014-04-14 14:15:00,80.2351674005\n2014-04-14 14:20:00,72.66880919\n2014-04-14 14:25:00,73.10716202520001\n2014-04-14 14:30:00,72.11526322729999\n2014-04-14 14:35:00,86.607750241\n2014-04-14 14:40:00,78.53041691930001\n2014-04-14 14:45:00,79.493166163\n2014-04-14 14:50:00,85.5220859043\n2014-04-14 14:55:00,81.74401706479999\n2014-04-14 15:00:00,81.75124072279999\n2014-04-14 15:05:00,76.743814122\n2014-04-14 15:10:00,85.3417146945\n2014-04-14 15:15:00,74.6525629451\n2014-04-14 15:20:00,72.849694111\n2014-04-14 15:25:00,75.06493309\n2014-04-14 15:30:00,76.283063176\n2014-04-14 15:35:00,76.5162423627\n2014-04-14 15:40:00,82.727423387\n2014-04-14 15:45:00,75.4844687394\n2014-04-14 15:50:00,82.8257377372\n2014-04-14 15:55:00,73.4574095738\n2014-04-14 16:00:00,74.3550966155\n2014-04-14 16:05:00,80.1409893049\n2014-04-14 16:10:00,86.7501662806\n2014-04-14 16:15:00,85.7529167751\n2014-04-14 16:20:00,87.49988707899998\n2014-04-14 16:25:00,82.4075068217\n2014-04-14 16:30:00,82.8128788616\n2014-04-14 16:35:00,82.00021054220001\n2014-04-14 16:40:00,81.9649453927\n2014-04-14 16:45:00,74.3537827615\n2014-04-14 16:50:00,80.699668355\n2014-04-14 16:55:00,78.17693683520001\n2014-04-14 17:00:00,79.0805650855\n2014-04-14 17:05:00,80.37757830390001\n2014-04-14 17:10:00,74.054310312\n2014-04-14 17:15:00,77.7517738849\n2014-04-14 17:20:00,73.0151649362\n2014-04-14 17:25:00,87.6746564197\n2014-04-14 17:30:00,73.8964200849\n2014-04-14 17:35:00,76.13636658029999\n2014-04-14 17:40:00,86.26065370319998\n2014-04-14 17:45:00,79.7233301261\n2014-04-14 17:50:00,74.170166743\n2014-04-14 17:55:00,78.1476585999\n2014-04-14 18:00:00,29.541549490799998\n2014-04-14 18:05:00,30.0813766057\n2014-04-14 18:10:00,29.1329854269\n2014-04-14 18:15:00,31.604649896999998\n2014-04-14 18:20:00,33.9624646582\n2014-04-14 18:25:00,32.550196494\n2014-04-14 18:30:00,32.6806036804\n2014-04-14 18:35:00,30.0837320165\n2014-04-14 18:40:00,31.0009146446\n2014-04-14 18:45:00,34.2095428963\n2014-04-14 18:50:00,29.3622739421\n2014-04-14 18:55:00,34.2907495997\n2014-04-14 19:00:00,22.3269300929\n2014-04-14 19:05:00,23.9104191807\n2014-04-14 19:10:00,21.5846675748\n2014-04-14 19:15:00,21.6780152339\n2014-04-14 19:20:00,23.527188519499997\n2014-04-14 19:25:00,23.676781558000002\n2014-04-14 19:30:00,21.188806995\n2014-04-14 19:35:00,24.5184621902\n2014-04-14 19:40:00,20.5385145403\n2014-04-14 19:45:00,20.4668921519\n2014-04-14 19:50:00,22.827857632199997\n2014-04-14 19:55:00,23.3978773561\n2014-04-14 20:00:00,22.3677893169\n2014-04-14 20:05:00,20.0906576771\n2014-04-14 20:10:00,18.535593388800002\n2014-04-14 20:15:00,20.9014631556\n2014-04-14 20:20:00,19.6185946649\n2014-04-14 20:25:00,20.205351166\n2014-04-14 20:30:00,20.4327707541\n2014-04-14 20:35:00,18.6962434292\n2014-04-14 20:40:00,20.4225811445\n2014-04-14 20:45:00,20.1782051131\n2014-04-14 20:50:00,21.3505810544\n2014-04-14 20:55:00,21.0766473194\n2014-04-14 21:00:00,18.8308189683\n2014-04-14 21:05:00,18.9149134938\n2014-04-14 21:10:00,19.095243987\n2014-04-14 21:15:00,18.805637563599998\n2014-04-14 21:20:00,20.727871241400003\n2014-04-14 21:25:00,22.083213722199996\n2014-04-14 21:30:00,20.7073537916\n2014-04-14 21:35:00,20.524774420299998\n2014-04-14 21:40:00,19.7339823015\n2014-04-14 21:45:00,19.3427225291\n2014-04-14 21:50:00,21.7481875906\n2014-04-14 21:55:00,21.9810122788\n2014-04-14 22:00:00,20.006292313\n2014-04-14 22:05:00,19.1791963425\n2014-04-14 22:10:00,21.100726089600002\n2014-04-14 22:15:00,18.547615788399998\n2014-04-14 22:20:00,21.0825727991\n2014-04-14 22:25:00,21.2962182485\n2014-04-14 22:30:00,18.5173754006\n2014-04-14 22:35:00,21.9284770125\n2014-04-14 22:40:00,21.963113518000004\n2014-04-14 22:45:00,21.7677549094\n2014-04-14 22:50:00,20.0033240015\n2014-04-14 22:55:00,19.0025214845\n2014-04-14 23:00:00,20.3319401047\n2014-04-14 23:05:00,19.6835138611\n2014-04-14 23:10:00,18.8274087456\n2014-04-14 23:15:00,19.69848702\n2014-04-14 23:20:00,20.6595252081\n2014-04-14 23:25:00,18.2871637028\n2014-04-14 23:30:00,19.3373840689\n2014-04-14 23:35:00,18.0746492248\n2014-04-14 23:40:00,21.0020136323\n2014-04-14 23:45:00,20.5667131193\n2014-04-14 23:50:00,18.254192669200002\n2014-04-14 23:55:00,21.8631471547\n"
  },
  {
    "path": "workspace/anomaly_detector/datasets/selected/seasonal/art_daily_jumpsup_noised.csv",
    "content": "timestamp,value\n2014-04-01 00:00:00,19.761251902999998\n2014-04-01 00:05:00,20.500833287\n2014-04-01 00:10:00,19.9616414445\n2014-04-01 00:15:00,21.4902660734\n2014-04-01 00:20:00,20.1877394098\n2014-04-01 00:25:00,19.9231256718\n2014-04-01 00:30:00,21.698403961700002\n2014-04-01 00:35:00,20.8787583842\n2014-04-01 00:40:00,18.4461996294\n2014-04-01 00:45:00,18.7108178448\n2014-04-01 00:50:00,21.148491451800002\n2014-04-01 00:55:00,21.3434052847\n2014-04-01 01:00:00,20.1807633164\n2014-04-01 01:05:00,20.217820911500002\n2014-04-01 01:10:00,20.527731851400002\n2014-04-01 01:15:00,19.7564630971\n2014-04-01 01:20:00,20.7207964939\n2014-04-01 01:25:00,18.4339250303\n2014-04-01 01:30:00,21.845116969499998\n2014-04-01 01:35:00,21.0006192952\n2014-04-01 01:40:00,20.524696816\n2014-04-01 01:45:00,19.265288228\n2014-04-01 01:50:00,18.6438219498\n2014-04-01 01:55:00,19.6373718553\n2014-04-01 02:00:00,20.6463069623\n2014-04-01 02:05:00,20.534838973699998\n2014-04-01 02:10:00,19.530564620299998\n2014-04-01 02:15:00,20.4531455753\n2014-04-01 02:20:00,21.2549931823\n2014-04-01 02:25:00,18.1051390894\n2014-04-01 02:30:00,19.8024841917\n2014-04-01 02:35:00,21.0342209139\n2014-04-01 02:40:00,20.1845778819\n2014-04-01 02:45:00,20.6059043517\n2014-04-01 02:50:00,20.0667055704\n2014-04-01 02:55:00,21.967498178699998\n2014-04-01 03:00:00,18.218486146\n2014-04-01 03:05:00,19.964179287100002\n2014-04-01 03:10:00,18.3656661965\n2014-04-01 03:15:00,18.6391422485\n2014-04-01 03:20:00,19.5321534017\n2014-04-01 03:25:00,18.622160366\n2014-04-01 03:30:00,21.854748663800002\n2014-04-01 03:35:00,21.7871591069\n2014-04-01 03:40:00,19.3444385849\n2014-04-01 03:45:00,20.5589908482\n2014-04-01 03:50:00,20.1350132824\n2014-04-01 03:55:00,21.262347922100002\n2014-04-01 04:00:00,20.5097824393\n2014-04-01 04:05:00,18.001009818\n2014-04-01 04:10:00,21.0526975424\n2014-04-01 04:15:00,20.9873924852\n2014-04-01 04:20:00,20.0388908223\n2014-04-01 04:25:00,21.6116758929\n2014-04-01 04:30:00,21.633784822800003\n2014-04-01 04:35:00,20.0956467068\n2014-04-01 04:40:00,20.4319529248\n2014-04-01 04:45:00,21.9860882877\n2014-04-01 04:50:00,19.1952809392\n2014-04-01 04:55:00,19.2984689692\n2014-04-01 05:00:00,18.7310956107\n2014-04-01 05:05:00,21.583467756599998\n2014-04-01 05:10:00,20.9779535598\n2014-04-01 05:15:00,18.4225713955\n2014-04-01 05:20:00,21.9270694048\n2014-04-01 05:25:00,20.9238468326\n2014-04-01 05:30:00,21.4020884384\n2014-04-01 05:35:00,18.192603156700002\n2014-04-01 05:40:00,20.0198436758\n2014-04-01 05:45:00,20.7943931469\n2014-04-01 05:50:00,20.1717863383\n2014-04-01 05:55:00,20.6665898628\n2014-04-01 06:00:00,21.2714962544\n2014-04-01 06:05:00,19.497348251800002\n2014-04-01 06:10:00,21.3946747025\n2014-04-01 06:15:00,18.6516644191\n2014-04-01 06:20:00,19.0835442201\n2014-04-01 06:25:00,18.1733824797\n2014-04-01 06:30:00,19.4577072453\n2014-04-01 06:35:00,19.5196381793\n2014-04-01 06:40:00,21.221082388800003\n2014-04-01 06:45:00,20.612522681199998\n2014-04-01 06:50:00,19.7468902326\n2014-04-01 06:55:00,20.608455914500002\n2014-04-01 07:00:00,18.2111334021\n2014-04-01 07:05:00,18.7210861441\n2014-04-01 07:10:00,20.507791421\n2014-04-01 07:15:00,20.5654672769\n2014-04-01 07:20:00,21.0965386348\n2014-04-01 07:25:00,19.6119990362\n2014-04-01 07:30:00,20.8902163865\n2014-04-01 07:35:00,20.7359213302\n2014-04-01 07:40:00,21.8535735135\n2014-04-01 07:45:00,18.8605209057\n2014-04-01 07:50:00,20.206718255\n2014-04-01 07:55:00,20.407057768399998\n2014-04-01 08:00:00,21.994591539699996\n2014-04-01 08:05:00,18.804736568699997\n2014-04-01 08:10:00,20.0928720799\n2014-04-01 08:15:00,19.384741230899998\n2014-04-01 08:20:00,20.103571874300002\n2014-04-01 08:25:00,18.928514408399998\n2014-04-01 08:30:00,18.1904495137\n2014-04-01 08:35:00,20.2902618156\n2014-04-01 08:40:00,19.3434172634\n2014-04-01 08:45:00,18.727765607000002\n2014-04-01 08:50:00,19.2957422643\n2014-04-01 08:55:00,18.1971208058\n2014-04-01 09:00:00,74.1260143836\n2014-04-01 09:05:00,69.10361164359999\n2014-04-01 09:10:00,72.2808540663\n2014-04-01 09:15:00,66.9544074866\n2014-04-01 09:20:00,73.4850794789\n2014-04-01 09:25:00,67.7731278131\n2014-04-01 09:30:00,69.0056563819\n2014-04-01 09:35:00,67.88839812890001\n2014-04-01 09:40:00,71.1725848238\n2014-04-01 09:45:00,68.9065226554\n2014-04-01 09:50:00,64.8937453607\n2014-04-01 09:55:00,63.179337626000006\n2014-04-01 10:00:00,79.2470505155\n2014-04-01 10:05:00,77.4320730032\n2014-04-01 10:10:00,71.3295428127\n2014-04-01 10:15:00,75.9799830691\n2014-04-01 10:20:00,77.8293300694\n2014-04-01 10:25:00,82.67338298899999\n2014-04-01 10:30:00,71.0210883865\n2014-04-01 10:35:00,75.2486478048\n2014-04-01 10:40:00,82.6076230245\n2014-04-01 10:45:00,79.90353942109999\n2014-04-01 10:50:00,74.3401531544\n2014-04-01 10:55:00,82.9596010938\n2014-04-01 11:00:00,79.41334110529999\n2014-04-01 11:05:00,79.4937884794\n2014-04-01 11:10:00,87.0996450426\n2014-04-01 11:15:00,86.6309408675\n2014-04-01 11:20:00,77.2701037963\n2014-04-01 11:25:00,73.8037704623\n2014-04-01 11:30:00,76.7474037102\n2014-04-01 11:35:00,72.052805772\n2014-04-01 11:40:00,71.8982924702\n2014-04-01 11:45:00,77.8583840549\n2014-04-01 11:50:00,86.5339792602\n2014-04-01 11:55:00,85.426067155\n2014-04-01 12:00:00,80.08686564029999\n2014-04-01 12:05:00,80.9463697522\n2014-04-01 12:10:00,72.0084220248\n2014-04-01 12:15:00,75.3574808711\n2014-04-01 12:20:00,72.3095103677\n2014-04-01 12:25:00,83.9717453641\n2014-04-01 12:30:00,74.2411363371\n2014-04-01 12:35:00,85.8016679353\n2014-04-01 12:40:00,82.194437192\n2014-04-01 12:45:00,75.5798939857\n2014-04-01 12:50:00,74.4340968432\n2014-04-01 12:55:00,81.94354482050001\n2014-04-01 13:00:00,86.3926524705\n2014-04-01 13:05:00,83.47372499939999\n2014-04-01 13:10:00,77.5581280065\n2014-04-01 13:15:00,81.3786019713\n2014-04-01 13:20:00,76.953713801\n2014-04-01 13:25:00,87.9652763341\n2014-04-01 13:30:00,83.9612714729\n2014-04-01 13:35:00,81.81046701060001\n2014-04-01 13:40:00,78.7532409691\n2014-04-01 13:45:00,81.8707829394\n2014-04-01 13:50:00,77.4472651938\n2014-04-01 13:55:00,72.4444465903\n2014-04-01 14:00:00,78.31765692970001\n2014-04-01 14:05:00,86.883522504\n2014-04-01 14:10:00,82.0168805171\n2014-04-01 14:15:00,73.3397707712\n2014-04-01 14:20:00,86.15576213920002\n2014-04-01 14:25:00,76.2983350936\n2014-04-01 14:30:00,75.89666867439999\n2014-04-01 14:35:00,76.7497713346\n2014-04-01 14:40:00,81.2313364867\n2014-04-01 14:45:00,80.7111351745\n2014-04-01 14:50:00,79.8587866682\n2014-04-01 14:55:00,83.4765827479\n2014-04-01 15:00:00,77.06386388119998\n2014-04-01 15:05:00,84.51222102\n2014-04-01 15:10:00,74.8044287246\n2014-04-01 15:15:00,84.5211212147\n2014-04-01 15:20:00,82.6201685228\n2014-04-01 15:25:00,82.930536812\n2014-04-01 15:30:00,79.7040891874\n2014-04-01 15:35:00,82.6712308715\n2014-04-01 15:40:00,73.2760492881\n2014-04-01 15:45:00,85.6239958745\n2014-04-01 15:50:00,72.8880560037\n2014-04-01 15:55:00,74.3791501112\n2014-04-01 16:00:00,81.228479377\n2014-04-01 16:05:00,83.83042233260001\n2014-04-01 16:10:00,73.2198844471\n2014-04-01 16:15:00,86.73207050010002\n2014-04-01 16:20:00,87.5775542316\n2014-04-01 16:25:00,81.69504591329998\n2014-04-01 16:30:00,79.6997422622\n2014-04-01 16:35:00,83.8621585408\n2014-04-01 16:40:00,77.2535693101\n2014-04-01 16:45:00,79.8920775526\n2014-04-01 16:50:00,86.6582500449\n2014-04-01 16:55:00,87.29031920610001\n2014-04-01 17:00:00,86.8330725129\n2014-04-01 17:05:00,76.19913981090001\n2014-04-01 17:10:00,75.7194755672\n2014-04-01 17:15:00,76.762602618\n2014-04-01 17:20:00,79.0609474388\n2014-04-01 17:25:00,77.02664902640001\n2014-04-01 17:30:00,77.98737478470001\n2014-04-01 17:35:00,81.93015977270001\n2014-04-01 17:40:00,84.20037850050001\n2014-04-01 17:45:00,83.768899005\n2014-04-01 17:50:00,85.0307444214\n2014-04-01 17:55:00,72.5149226057\n2014-04-01 18:00:00,29.105490665700003\n2014-04-01 18:05:00,33.8520444488\n2014-04-01 18:10:00,32.211698278200004\n2014-04-01 18:15:00,32.5000940721\n2014-04-01 18:20:00,29.1365503112\n2014-04-01 18:25:00,30.4340024842\n2014-04-01 18:30:00,32.8854612373\n2014-04-01 18:35:00,34.2987575113\n2014-04-01 18:40:00,34.6686870856\n2014-04-01 18:45:00,32.0026786288\n2014-04-01 18:50:00,32.2910288896\n2014-04-01 18:55:00,34.131511085599996\n2014-04-01 19:00:00,22.568556973299998\n2014-04-01 19:05:00,22.4755249615\n2014-04-01 19:10:00,24.2147751608\n2014-04-01 19:15:00,23.698897290300003\n2014-04-01 19:20:00,24.232643588800002\n2014-04-01 19:25:00,21.1377456459\n2014-04-01 19:30:00,22.5092009454\n2014-04-01 19:35:00,23.9342738231\n2014-04-01 19:40:00,20.6579411338\n2014-04-01 19:45:00,23.72008515\n2014-04-01 19:50:00,20.9797196068\n2014-04-01 19:55:00,23.7803707178\n2014-04-01 20:00:00,20.938755589\n2014-04-01 20:05:00,19.2234943904\n2014-04-01 20:10:00,20.3708584741\n2014-04-01 20:15:00,21.2250833071\n2014-04-01 20:20:00,21.0282612297\n2014-04-01 20:25:00,20.1820042736\n2014-04-01 20:30:00,22.1158050371\n2014-04-01 20:35:00,20.558902699\n2014-04-01 20:40:00,20.5040322087\n2014-04-01 20:45:00,18.6869781922\n2014-04-01 20:50:00,22.2090048501\n2014-04-01 20:55:00,19.1574692354\n2014-04-01 21:00:00,20.2099229424\n2014-04-01 21:05:00,21.3160988514\n2014-04-01 21:10:00,18.9523497644\n2014-04-01 21:15:00,20.2060186776\n2014-04-01 21:20:00,19.0537607405\n2014-04-01 21:25:00,21.1397660835\n2014-04-01 21:30:00,20.3545999721\n2014-04-01 21:35:00,21.526738125399998\n2014-04-01 21:40:00,21.6818074721\n2014-04-01 21:45:00,20.693789562\n2014-04-01 21:50:00,21.0018924452\n2014-04-01 21:55:00,20.2938253758\n2014-04-01 22:00:00,19.556471129000002\n2014-04-01 22:05:00,20.6122404548\n2014-04-01 22:10:00,21.6539223116\n2014-04-01 22:15:00,19.6856015647\n2014-04-01 22:20:00,19.2761274305\n2014-04-01 22:25:00,19.5725193424\n2014-04-01 22:30:00,19.760542437999998\n2014-04-01 22:35:00,18.3118065813\n2014-04-01 22:40:00,20.0129613686\n2014-04-01 22:45:00,19.9964351491\n2014-04-01 22:50:00,20.3733149249\n2014-04-01 22:55:00,19.4699533412\n2014-04-01 23:00:00,20.4563572484\n2014-04-01 23:05:00,21.516995709099998\n2014-04-01 23:10:00,21.8260737616\n2014-04-01 23:15:00,20.338353076700002\n2014-04-01 23:20:00,18.173852523900003\n2014-04-01 23:25:00,21.8811443602\n2014-04-01 23:30:00,20.8274463436\n2014-04-01 23:35:00,19.3475686124\n2014-04-01 23:40:00,18.5921998191\n2014-04-01 23:45:00,18.5772405926\n2014-04-01 23:50:00,18.6745624504\n2014-04-01 23:55:00,18.185781084400002\n2014-04-02 00:00:00,21.6086167546\n2014-04-02 00:05:00,20.1630729313\n2014-04-02 00:10:00,20.7998376509\n2014-04-02 00:15:00,21.3124340371\n2014-04-02 00:20:00,21.1661640253\n2014-04-02 00:25:00,21.530422494899998\n2014-04-02 00:30:00,21.869018490100004\n2014-04-02 00:35:00,19.756282459\n2014-04-02 00:40:00,21.8013418667\n2014-04-02 00:45:00,20.8931597934\n2014-04-02 00:50:00,18.2826727612\n2014-04-02 00:55:00,20.7271324848\n2014-04-02 01:00:00,20.7468666384\n2014-04-02 01:05:00,21.6234422552\n2014-04-02 01:10:00,19.4917285299\n2014-04-02 01:15:00,20.3396460011\n2014-04-02 01:20:00,18.048750204\n2014-04-02 01:25:00,19.3283009687\n2014-04-02 01:30:00,18.2489749046\n2014-04-02 01:35:00,20.087491891099997\n2014-04-02 01:40:00,21.269790602\n2014-04-02 01:45:00,18.8257707685\n2014-04-02 01:50:00,20.1097641822\n2014-04-02 01:55:00,18.816034545999997\n2014-04-02 02:00:00,18.4827538714\n2014-04-02 02:05:00,20.0439871677\n2014-04-02 02:10:00,18.3165944838\n2014-04-02 02:15:00,20.3494185246\n2014-04-02 02:20:00,18.1253498427\n2014-04-02 02:25:00,18.4268598875\n2014-04-02 02:30:00,20.1999899419\n2014-04-02 02:35:00,20.365629651600003\n2014-04-02 02:40:00,18.1159477204\n2014-04-02 02:45:00,20.293507152\n2014-04-02 02:50:00,21.354010101300002\n2014-04-02 02:55:00,20.8892647092\n2014-04-02 03:00:00,18.5247404157\n2014-04-02 03:05:00,20.3698985903\n2014-04-02 03:10:00,20.6890100003\n2014-04-02 03:15:00,18.148924807\n2014-04-02 03:20:00,21.4213906747\n2014-04-02 03:25:00,21.625069589200002\n2014-04-02 03:30:00,21.4018090934\n2014-04-02 03:35:00,21.298525872\n2014-04-02 03:40:00,20.9798607938\n2014-04-02 03:45:00,20.5337281251\n2014-04-02 03:50:00,20.71450802\n2014-04-02 03:55:00,21.2255811733\n2014-04-02 04:00:00,20.6499938334\n2014-04-02 04:05:00,19.3109078267\n2014-04-02 04:10:00,19.5038444086\n2014-04-02 04:15:00,21.588229873499998\n2014-04-02 04:20:00,18.0684883432\n2014-04-02 04:25:00,20.795282325\n2014-04-02 04:30:00,21.819110209699996\n2014-04-02 04:35:00,20.8249126798\n2014-04-02 04:40:00,21.9756479529\n2014-04-02 04:45:00,20.7501796221\n2014-04-02 04:50:00,18.1374521169\n2014-04-02 04:55:00,21.308039526600002\n2014-04-02 05:00:00,19.1385196478\n2014-04-02 05:05:00,19.7842289027\n2014-04-02 05:10:00,19.2483676636\n2014-04-02 05:15:00,19.0742164248\n2014-04-02 05:20:00,19.7256228147\n2014-04-02 05:25:00,19.5150057938\n2014-04-02 05:30:00,20.5333543274\n2014-04-02 05:35:00,21.252604804\n2014-04-02 05:40:00,19.1883546127\n2014-04-02 05:45:00,18.8548846113\n2014-04-02 05:50:00,20.6675810835\n2014-04-02 05:55:00,20.6812802633\n2014-04-02 06:00:00,21.6045249571\n2014-04-02 06:05:00,18.063782745799998\n2014-04-02 06:10:00,21.4121626485\n2014-04-02 06:15:00,20.0840086918\n2014-04-02 06:20:00,20.4852083567\n2014-04-02 06:25:00,18.3654857622\n2014-04-02 06:30:00,19.7304597315\n2014-04-02 06:35:00,18.909209629\n2014-04-02 06:40:00,19.0169001203\n2014-04-02 06:45:00,20.0163804587\n2014-04-02 06:50:00,21.2498238016\n2014-04-02 06:55:00,20.9751237206\n2014-04-02 07:00:00,20.3639998363\n2014-04-02 07:05:00,20.157672770999998\n2014-04-02 07:10:00,19.7092241729\n2014-04-02 07:15:00,21.8908398942\n2014-04-02 07:20:00,20.2407702169\n2014-04-02 07:25:00,19.0158655932\n2014-04-02 07:30:00,18.920363168199998\n2014-04-02 07:35:00,20.4454121231\n2014-04-02 07:40:00,20.091310109200002\n2014-04-02 07:45:00,18.0307912118\n2014-04-02 07:50:00,21.3202614888\n2014-04-02 07:55:00,20.8164894169\n2014-04-02 08:00:00,20.647317158699998\n2014-04-02 08:05:00,18.2751226308\n2014-04-02 08:10:00,19.448223400699998\n2014-04-02 08:15:00,21.741529042899998\n2014-04-02 08:20:00,21.4503569654\n2014-04-02 08:25:00,19.1421717515\n2014-04-02 08:30:00,18.628235536400002\n2014-04-02 08:35:00,19.796351828699997\n2014-04-02 08:40:00,19.4233215147\n2014-04-02 08:45:00,20.7289055068\n2014-04-02 08:50:00,21.8657392403\n2014-04-02 08:55:00,19.4520057999\n2014-04-02 09:00:00,62.046248748100005\n2014-04-02 09:05:00,73.4075505135\n2014-04-02 09:10:00,61.7161163313\n2014-04-02 09:15:00,74.1576162013\n2014-04-02 09:20:00,70.2382802209\n2014-04-02 09:25:00,74.0069732348\n2014-04-02 09:30:00,63.91537173840001\n2014-04-02 09:35:00,61.753517215500004\n2014-04-02 09:40:00,67.8396557046\n2014-04-02 09:45:00,67.3284784382\n2014-04-02 09:50:00,65.7082949163\n2014-04-02 09:55:00,74.2241280517\n2014-04-02 10:00:00,82.6064995231\n2014-04-02 10:05:00,80.1077529717\n2014-04-02 10:10:00,72.3675606862\n2014-04-02 10:15:00,81.2366992956\n2014-04-02 10:20:00,81.1232332969\n2014-04-02 10:25:00,76.4370580545\n2014-04-02 10:30:00,84.1926773188\n2014-04-02 10:35:00,72.4314967322\n2014-04-02 10:40:00,73.9890789686\n2014-04-02 10:45:00,70.8212417452\n2014-04-02 10:50:00,82.1853988709\n2014-04-02 10:55:00,79.4897056722\n2014-04-02 11:00:00,76.5768106216\n2014-04-02 11:05:00,74.1732925058\n2014-04-02 11:10:00,72.2065101345\n2014-04-02 11:15:00,74.2199215234\n2014-04-02 11:20:00,78.77703901539998\n2014-04-02 11:25:00,75.4991025151\n2014-04-02 11:30:00,75.6868525499\n2014-04-02 11:35:00,85.4931665355\n2014-04-02 11:40:00,79.7607495587\n2014-04-02 11:45:00,83.16602338060001\n2014-04-02 11:50:00,72.1359469333\n2014-04-02 11:55:00,77.3755580087\n2014-04-02 12:00:00,79.5711095069\n2014-04-02 12:05:00,74.89269047970001\n2014-04-02 12:10:00,73.83435698550001\n2014-04-02 12:15:00,85.82175062350001\n2014-04-02 12:20:00,86.92646894639999\n2014-04-02 12:25:00,73.1729940801\n2014-04-02 12:30:00,77.4911982414\n2014-04-02 12:35:00,87.22777096629999\n2014-04-02 12:40:00,73.24259102479999\n2014-04-02 12:45:00,82.1995040517\n2014-04-02 12:50:00,87.4504752851\n2014-04-02 12:55:00,87.5463968029\n2014-04-02 13:00:00,79.5204837969\n2014-04-02 13:05:00,74.5860807679\n2014-04-02 13:10:00,75.2152930359\n2014-04-02 13:15:00,86.2129262526\n2014-04-02 13:20:00,86.56614720649998\n2014-04-02 13:25:00,81.7064600441\n2014-04-02 13:30:00,84.2386002741\n2014-04-02 13:35:00,83.8187786875\n2014-04-02 13:40:00,82.5693241729\n2014-04-02 13:45:00,85.21597453439999\n2014-04-02 13:50:00,82.9465940072\n2014-04-02 13:55:00,80.5247063231\n2014-04-02 14:00:00,75.7876638189\n2014-04-02 14:05:00,83.8981829998\n2014-04-02 14:10:00,79.5711862851\n2014-04-02 14:15:00,76.7129845441\n2014-04-02 14:20:00,84.8270685171\n2014-04-02 14:25:00,83.1434265296\n2014-04-02 14:30:00,86.9932571332\n2014-04-02 14:35:00,74.6434831811\n2014-04-02 14:40:00,82.3830739768\n2014-04-02 14:45:00,75.90418791350001\n2014-04-02 14:50:00,86.4531778131\n2014-04-02 14:55:00,73.5884582126\n2014-04-02 15:00:00,82.4977969167\n2014-04-02 15:05:00,84.6565588337\n2014-04-02 15:10:00,77.6779397305\n2014-04-02 15:15:00,87.2653715145\n2014-04-02 15:20:00,85.61086908109999\n2014-04-02 15:25:00,76.7131563416\n2014-04-02 15:30:00,72.11996512510001\n2014-04-02 15:35:00,76.74577805130002\n2014-04-02 15:40:00,76.5002331182\n2014-04-02 15:45:00,86.2386058215\n2014-04-02 15:50:00,87.4730991023\n2014-04-02 15:55:00,73.1263377559\n2014-04-02 16:00:00,79.5405645384\n2014-04-02 16:05:00,80.7731568917\n2014-04-02 16:10:00,73.486445487\n2014-04-02 16:15:00,78.0398135095\n2014-04-02 16:20:00,77.0731706975\n2014-04-02 16:25:00,80.5767469616\n2014-04-02 16:30:00,82.5788958439\n2014-04-02 16:35:00,83.25560191689999\n2014-04-02 16:40:00,74.1879379367\n2014-04-02 16:45:00,85.0070000174\n2014-04-02 16:50:00,82.85651339180001\n2014-04-02 16:55:00,86.2250331156\n2014-04-02 17:00:00,79.1893465422\n2014-04-02 17:05:00,86.3022030635\n2014-04-02 17:10:00,85.8523529904\n2014-04-02 17:15:00,79.0145189762\n2014-04-02 17:20:00,178.0982630549\n2014-04-02 17:25:00,86.92495886030001\n2014-04-02 17:30:00,83.44260371060001\n2014-04-02 17:35:00,86.8518921919\n2014-04-02 17:40:00,84.75156391770001\n2014-04-02 17:45:00,81.7487276371\n2014-04-02 17:50:00,73.8536160723\n2014-04-02 17:55:00,76.6636613224\n2014-04-02 18:00:00,35.000584685300005\n2014-04-02 18:05:00,30.844295509699997\n2014-04-02 18:10:00,29.396825522399997\n2014-04-02 18:15:00,33.3283350788\n2014-04-02 18:20:00,33.4976207975\n2014-04-02 18:25:00,30.626923529499997\n2014-04-02 18:30:00,30.7050947724\n2014-04-02 18:35:00,31.80090900150001\n2014-04-02 18:40:00,28.939443722100002\n2014-04-02 18:45:00,33.851660766799995\n2014-04-02 18:50:00,30.8293623193\n2014-04-02 18:55:00,34.264077274099996\n2014-04-02 19:00:00,23.7557829856\n2014-04-02 19:05:00,23.123079839899997\n2014-04-02 19:10:00,21.6154382188\n2014-04-02 19:15:00,22.473096963400003\n2014-04-02 19:20:00,22.1528338588\n2014-04-02 19:25:00,21.678189661199998\n2014-04-02 19:30:00,23.9596492617\n2014-04-02 19:35:00,22.3261104694\n2014-04-02 19:40:00,23.890598167600004\n2014-04-02 19:45:00,20.6313776324\n2014-04-02 19:50:00,20.7917899124\n2014-04-02 19:55:00,24.5383936208\n2014-04-02 20:00:00,20.8394993728\n2014-04-02 20:05:00,20.5200163364\n2014-04-02 20:10:00,20.5748469877\n2014-04-02 20:15:00,19.3137406667\n2014-04-02 20:20:00,21.3758111207\n2014-04-02 20:25:00,18.7792612094\n2014-04-02 20:30:00,20.7803336795\n2014-04-02 20:35:00,20.7698687416\n2014-04-02 20:40:00,22.176515519099997\n2014-04-02 20:45:00,20.5872445431\n2014-04-02 20:50:00,18.9934085748\n2014-04-02 20:55:00,20.7779971005\n2014-04-02 21:00:00,18.4534640231\n2014-04-02 21:05:00,18.905488136600002\n2014-04-02 21:10:00,18.211431577\n2014-04-02 21:15:00,20.1494295173\n2014-04-02 21:20:00,18.4261534423\n2014-04-02 21:25:00,19.972989837300002\n2014-04-02 21:30:00,21.836092632600003\n2014-04-02 21:35:00,20.9792650199\n2014-04-02 21:40:00,18.397532956\n2014-04-02 21:45:00,18.9875440308\n2014-04-02 21:50:00,20.7939839472\n2014-04-02 21:55:00,21.6823856668\n2014-04-02 22:00:00,18.1490807455\n2014-04-02 22:05:00,21.270204328800002\n2014-04-02 22:10:00,20.266692876700002\n2014-04-02 22:15:00,20.203742282\n2014-04-02 22:20:00,21.8522107229\n2014-04-02 22:25:00,21.0107293954\n2014-04-02 22:30:00,21.4210199182\n2014-04-02 22:35:00,19.4346216116\n2014-04-02 22:40:00,20.2368649113\n2014-04-02 22:45:00,20.4812658575\n2014-04-02 22:50:00,19.3048506343\n2014-04-02 22:55:00,20.3004622426\n2014-04-02 23:00:00,18.9502592674\n2014-04-02 23:05:00,18.577068795\n2014-04-02 23:10:00,19.4996242444\n2014-04-02 23:15:00,20.9611822874\n2014-04-02 23:20:00,21.6689082219\n2014-04-02 23:25:00,19.8346637284\n2014-04-02 23:30:00,20.5752444397\n2014-04-02 23:35:00,18.4156836546\n2014-04-02 23:40:00,21.6220056603\n2014-04-02 23:45:00,20.2783095403\n2014-04-02 23:50:00,21.1254082882\n2014-04-02 23:55:00,21.1818309324\n2014-04-03 00:00:00,19.0259221055\n2014-04-03 00:05:00,20.1166978127\n2014-04-03 00:10:00,21.841919006199998\n2014-04-03 00:15:00,18.3585381793\n2014-04-03 00:20:00,20.7321995921\n2014-04-03 00:25:00,21.8490563121\n2014-04-03 00:30:00,19.2023084322\n2014-04-03 00:35:00,21.4457916856\n2014-04-03 00:40:00,21.7346301816\n2014-04-03 00:45:00,20.9883448376\n2014-04-03 00:50:00,18.925313249200002\n2014-04-03 00:55:00,19.3360028753\n2014-04-03 01:00:00,18.1432371777\n2014-04-03 01:05:00,21.325812937000002\n2014-04-03 01:10:00,21.398444746\n2014-04-03 01:15:00,20.5308412399\n2014-04-03 01:20:00,19.4101114051\n2014-04-03 01:25:00,18.3072441106\n2014-04-03 01:30:00,21.0122304397\n2014-04-03 01:35:00,20.9061047744\n2014-04-03 01:40:00,21.650410086999997\n2014-04-03 01:45:00,20.922128084\n2014-04-03 01:50:00,21.314779769\n2014-04-03 01:55:00,20.9838184716\n2014-04-03 02:00:00,20.5227487532\n2014-04-03 02:05:00,19.7078655768\n2014-04-03 02:10:00,21.6084692346\n2014-04-03 02:15:00,20.6038742876\n2014-04-03 02:20:00,19.5934212879\n2014-04-03 02:25:00,18.3338771807\n2014-04-03 02:30:00,19.1628194236\n2014-04-03 02:35:00,20.1749069393\n2014-04-03 02:40:00,19.1025414801\n2014-04-03 02:45:00,18.8849413917\n2014-04-03 02:50:00,20.1095740564\n2014-04-03 02:55:00,18.6792813836\n2014-04-03 03:00:00,21.2016402533\n2014-04-03 03:05:00,19.9374726054\n2014-04-03 03:10:00,20.2954510959\n2014-04-03 03:15:00,18.589533070399998\n2014-04-03 03:20:00,19.2983053425\n2014-04-03 03:25:00,19.640358733\n2014-04-03 03:30:00,21.2328513221\n2014-04-03 03:35:00,21.0806380923\n2014-04-03 03:40:00,18.8919098992\n2014-04-03 03:45:00,20.4647163264\n2014-04-03 03:50:00,18.9738254311\n2014-04-03 03:55:00,21.952988622800003\n2014-04-03 04:00:00,21.8084955125\n2014-04-03 04:05:00,20.2530588821\n2014-04-03 04:10:00,20.7956102876\n2014-04-03 04:15:00,21.2057215288\n2014-04-03 04:20:00,20.8839936802\n2014-04-03 04:25:00,20.7993147643\n2014-04-03 04:30:00,21.834216031799997\n2014-04-03 04:35:00,20.3858244252\n2014-04-03 04:40:00,20.5452106873\n2014-04-03 04:45:00,21.3970750018\n2014-04-03 04:50:00,20.6795634714\n2014-04-03 04:55:00,20.931730488099998\n2014-04-03 05:00:00,18.9366747448\n2014-04-03 05:05:00,19.4850676965\n2014-04-03 05:10:00,18.5892053828\n2014-04-03 05:15:00,20.0230617693\n2014-04-03 05:20:00,19.8229096027\n2014-04-03 05:25:00,21.9886512571\n2014-04-03 05:30:00,20.444834611300003\n2014-04-03 05:35:00,21.1457792928\n2014-04-03 05:40:00,19.336058683\n2014-04-03 05:45:00,21.3261813254\n2014-04-03 05:50:00,20.460339865999998\n2014-04-03 05:55:00,20.787969326400003\n2014-04-03 06:00:00,19.177723111800002\n2014-04-03 06:05:00,20.1945535668\n2014-04-03 06:10:00,20.536147893699997\n2014-04-03 06:15:00,20.3563787033\n2014-04-03 06:20:00,21.6607748457\n2014-04-03 06:25:00,21.593090658\n2014-04-03 06:30:00,21.8839362315\n2014-04-03 06:35:00,20.669712024000003\n2014-04-03 06:40:00,21.887656520500002\n2014-04-03 06:45:00,21.3299120001\n2014-04-03 06:50:00,19.083328561400002\n2014-04-03 06:55:00,19.709742678199998\n2014-04-03 07:00:00,18.9535697688\n2014-04-03 07:05:00,18.0167886433\n2014-04-03 07:10:00,18.7521950126\n2014-04-03 07:15:00,18.0162423451\n2014-04-03 07:20:00,20.8793538454\n2014-04-03 07:25:00,19.7021371909\n2014-04-03 07:30:00,19.2502989083\n2014-04-03 07:35:00,21.0468835644\n2014-04-03 07:40:00,21.3299470985\n2014-04-03 07:45:00,21.9011981546\n2014-04-03 07:50:00,20.568054338699998\n2014-04-03 07:55:00,19.8461158342\n2014-04-03 08:00:00,19.2210572064\n2014-04-03 08:05:00,18.889272836900002\n2014-04-03 08:10:00,18.8517038019\n2014-04-03 08:15:00,19.6367574989\n2014-04-03 08:20:00,21.967145421199998\n2014-04-03 08:25:00,18.0034147897\n2014-04-03 08:30:00,18.7888235889\n2014-04-03 08:35:00,18.7535719296\n2014-04-03 08:40:00,20.8684779421\n2014-04-03 08:45:00,19.4099389104\n2014-04-03 08:50:00,19.8290432184\n2014-04-03 08:55:00,18.594496521900002\n2014-04-03 09:00:00,66.7079597287\n2014-04-03 09:05:00,62.603517441899996\n2014-04-03 09:10:00,68.4493887153\n2014-04-03 09:15:00,62.5319617692\n2014-04-03 09:20:00,71.950913984\n2014-04-03 09:25:00,68.90578335859999\n2014-04-03 09:30:00,71.0459630833\n2014-04-03 09:35:00,66.8918228585\n2014-04-03 09:40:00,66.3882815881\n2014-04-03 09:45:00,62.535640891099995\n2014-04-03 09:50:00,68.3244362558\n2014-04-03 09:55:00,68.1972294421\n2014-04-03 10:00:00,77.1049437299\n2014-04-03 10:05:00,81.33284501989999\n2014-04-03 10:10:00,82.76046828850001\n2014-04-03 10:15:00,81.4922557552\n2014-04-03 10:20:00,72.0727963284\n2014-04-03 10:25:00,79.4943635841\n2014-04-03 10:30:00,71.0866146003\n2014-04-03 10:35:00,80.6205379011\n2014-04-03 10:40:00,75.7661427786\n2014-04-03 10:45:00,71.8963838013\n2014-04-03 10:50:00,83.2190293003\n2014-04-03 10:55:00,79.3694094219\n2014-04-03 11:00:00,77.2095458902\n2014-04-03 11:05:00,72.0566850652\n2014-04-03 11:10:00,80.1133823592\n2014-04-03 11:15:00,86.2509843714\n2014-04-03 11:20:00,81.0528248593\n2014-04-03 11:25:00,87.0211312159\n2014-04-03 11:30:00,73.738118585\n2014-04-03 11:35:00,80.60632438350001\n2014-04-03 11:40:00,84.2613807635\n2014-04-03 11:45:00,79.9261997878\n2014-04-03 11:50:00,73.01631932560001\n2014-04-03 11:55:00,80.8382189686\n2014-04-03 12:00:00,81.6896611257\n2014-04-03 12:05:00,83.55895675800001\n2014-04-03 12:10:00,84.0783689816\n2014-04-03 12:15:00,84.2311641758\n2014-04-03 12:20:00,82.5159721659\n2014-04-03 12:25:00,75.3624354079\n2014-04-03 12:30:00,78.3736107669\n2014-04-03 12:35:00,84.3167778664\n2014-04-03 12:40:00,87.15012593629999\n2014-04-03 12:45:00,73.17523565569999\n2014-04-03 12:50:00,80.4719045405\n2014-04-03 12:55:00,76.90795591359999\n2014-04-03 13:00:00,75.5881567965\n2014-04-03 13:05:00,80.0737486233\n2014-04-03 13:10:00,81.6778220658\n2014-04-03 13:15:00,72.1390381773\n2014-04-03 13:20:00,84.463029162\n2014-04-03 13:25:00,85.0976857528\n2014-04-03 13:30:00,87.4271856315\n2014-04-03 13:35:00,74.8723260597\n2014-04-03 13:40:00,81.4932779159\n2014-04-03 13:45:00,78.8070877342\n2014-04-03 13:50:00,77.3386798859\n2014-04-03 13:55:00,81.0306831905\n2014-04-03 14:00:00,84.5140726214\n2014-04-03 14:05:00,72.3653708306\n2014-04-03 14:10:00,87.5062013018\n2014-04-03 14:15:00,84.9540273822\n2014-04-03 14:20:00,84.0144263723\n2014-04-03 14:25:00,84.1621581374\n2014-04-03 14:30:00,78.2212165553\n2014-04-03 14:35:00,84.0218955689\n2014-04-03 14:40:00,78.1845702981\n2014-04-03 14:45:00,86.37516306639999\n2014-04-03 14:50:00,74.83196602609999\n2014-04-03 14:55:00,76.6738782646\n2014-04-03 15:00:00,80.8206247977\n2014-04-03 15:05:00,77.1066363434\n2014-04-03 15:10:00,78.7870395619\n2014-04-03 15:15:00,79.8779961943\n2014-04-03 15:20:00,85.7008308451\n2014-04-03 15:25:00,80.3703044954\n2014-04-03 15:30:00,77.798610704\n2014-04-03 15:35:00,75.96304937229999\n2014-04-03 15:40:00,78.538061688\n2014-04-03 15:45:00,80.2510072536\n2014-04-03 15:50:00,83.937031912\n2014-04-03 15:55:00,73.9360706257\n2014-04-03 16:00:00,75.545601964\n2014-04-03 16:05:00,78.0743143509\n2014-04-03 16:10:00,77.76622517050001\n2014-04-03 16:15:00,78.2678191272\n2014-04-03 16:20:00,84.6961776173\n2014-04-03 16:25:00,77.18632224939999\n2014-04-03 16:30:00,80.0302172281\n2014-04-03 16:35:00,81.98235511930001\n2014-04-03 16:40:00,75.7147114304\n2014-04-03 16:45:00,83.498965876\n2014-04-03 16:50:00,80.7536260686\n2014-04-03 16:55:00,79.1483466434\n2014-04-03 17:00:00,84.9565118045\n2014-04-03 17:05:00,75.8958950029\n2014-04-03 17:10:00,86.1307824556\n2014-04-03 17:15:00,80.97674867079998\n2014-04-03 17:20:00,81.74676667930001\n2014-04-03 17:25:00,86.0009104023\n2014-04-03 17:30:00,85.0812903344\n2014-04-03 17:35:00,81.6249617572\n2014-04-03 17:40:00,84.05097098600001\n2014-04-03 17:45:00,78.9330815334\n2014-04-03 17:50:00,80.7580130449\n2014-04-03 17:55:00,72.993094158\n2014-04-03 18:00:00,29.3750850352\n2014-04-03 18:05:00,34.108316038000005\n2014-04-03 18:10:00,29.1818929934\n2014-04-03 18:15:00,29.8841486663\n2014-04-03 18:20:00,33.8933225098\n2014-04-03 18:25:00,28.807328553\n2014-04-03 18:30:00,30.607381828\n2014-04-03 18:35:00,32.5378411628\n2014-04-03 18:40:00,32.6108733001\n2014-04-03 18:45:00,33.7737721281\n2014-04-03 18:50:00,32.0379218775\n2014-04-03 18:55:00,32.0601658094\n2014-04-03 19:00:00,23.409390094299997\n2014-04-03 19:05:00,22.393836367\n2014-04-03 19:10:00,22.8860388123\n2014-04-03 19:15:00,24.1820264992\n2014-04-03 19:20:00,21.9584993095\n2014-04-03 19:25:00,21.885359117100002\n2014-04-03 19:30:00,20.1758983768\n2014-04-03 19:35:00,22.908148394899996\n2014-04-03 19:40:00,20.2933770319\n2014-04-03 19:45:00,22.4185840042\n2014-04-03 19:50:00,23.76296607130001\n2014-04-03 19:55:00,22.623645154899997\n2014-04-03 20:00:00,19.5364294983\n2014-04-03 20:05:00,21.6521455944\n2014-04-03 20:10:00,19.5367606143\n2014-04-03 20:15:00,80.0000000000\n2014-04-03 20:20:00,20.9316183813\n2014-04-03 20:25:00,19.128304601900002\n2014-04-03 20:30:00,22.1394280857\n2014-04-03 20:35:00,19.2538362943\n2014-04-03 20:40:00,22.4853483859\n2014-04-03 20:45:00,18.46194354\n2014-04-03 20:50:00,19.511227678599997\n2014-04-03 20:55:00,19.2506275466\n2014-04-03 21:00:00,18.1426422698\n2014-04-03 21:05:00,21.0299330128\n2014-04-03 21:10:00,20.8734169327\n2014-04-03 21:15:00,21.2710169439\n2014-04-03 21:20:00,19.118122751199998\n2014-04-03 21:25:00,19.8722718549\n2014-04-03 21:30:00,20.735509015399998\n2014-04-03 21:35:00,19.8539175223\n2014-04-03 21:40:00,20.889091685\n2014-04-03 21:45:00,20.634465872699998\n2014-04-03 21:50:00,18.5471924045\n2014-04-03 21:55:00,21.2255684603\n2014-04-03 22:00:00,20.9027528233\n2014-04-03 22:05:00,20.6431359444\n2014-04-03 22:10:00,18.6382499754\n2014-04-03 22:15:00,19.0902948922\n2014-04-03 22:20:00,19.5914979165\n2014-04-03 22:25:00,19.138073407\n2014-04-03 22:30:00,18.9293959449\n2014-04-03 22:35:00,21.241803243699998\n2014-04-03 22:40:00,20.5726597872\n2014-04-03 22:45:00,20.2813399292\n2014-04-03 22:50:00,18.9219584925\n2014-04-03 22:55:00,21.6931116524\n2014-04-03 23:00:00,18.7683349831\n2014-04-03 23:05:00,21.1838702515\n2014-04-03 23:10:00,21.8708890693\n2014-04-03 23:15:00,20.9123853221\n2014-04-03 23:20:00,21.975653614099997\n2014-04-03 23:25:00,20.6081604731\n2014-04-03 23:30:00,18.8734643821\n2014-04-03 23:35:00,18.818890506400002\n2014-04-03 23:40:00,19.3019624005\n2014-04-03 23:45:00,18.031981555\n2014-04-03 23:50:00,20.7307734227\n2014-04-03 23:55:00,19.0783334735\n2014-04-04 00:00:00,21.2607329292\n2014-04-04 00:05:00,19.4366906022\n2014-04-04 00:10:00,19.9198259739\n2014-04-04 00:15:00,21.862755666199998\n2014-04-04 00:20:00,18.968688492200002\n2014-04-04 00:25:00,20.8850163897\n2014-04-04 00:30:00,21.0204711572\n2014-04-04 00:35:00,18.8839926301\n2014-04-04 00:40:00,20.003987346400002\n2014-04-04 00:45:00,19.4008077013\n2014-04-04 00:50:00,21.0876249736\n2014-04-04 00:55:00,20.4899332761\n2014-04-04 01:00:00,19.9039322194\n2014-04-04 01:05:00,21.1174530602\n2014-04-04 01:10:00,18.94062228\n2014-04-04 01:15:00,21.0144875223\n2014-04-04 01:20:00,21.4614972484\n2014-04-04 01:25:00,21.514486387199998\n2014-04-04 01:30:00,21.1346943721\n2014-04-04 01:35:00,19.632056668\n2014-04-04 01:40:00,21.927232090900002\n2014-04-04 01:45:00,19.5183745753\n2014-04-04 01:50:00,20.5545015964\n2014-04-04 01:55:00,18.6442967123\n2014-04-04 02:00:00,21.921795594499997\n2014-04-04 02:05:00,20.8159436875\n2014-04-04 02:10:00,21.013510180999997\n2014-04-04 02:15:00,18.2631068136\n2014-04-04 02:20:00,21.0536712569\n2014-04-04 02:25:00,21.0988937169\n2014-04-04 02:30:00,20.687090905399998\n2014-04-04 02:35:00,19.1676384552\n2014-04-04 02:40:00,19.958760168599998\n2014-04-04 02:45:00,18.4417374852\n2014-04-04 02:50:00,19.8863482658\n2014-04-04 02:55:00,18.9752954104\n2014-04-04 03:00:00,19.396387945999997\n2014-04-04 03:05:00,18.650401633599998\n2014-04-04 03:10:00,18.920217470999997\n2014-04-04 03:15:00,18.3062745673\n2014-04-04 03:20:00,21.679605465700003\n2014-04-04 03:25:00,20.1216427519\n2014-04-04 03:30:00,19.586967885099998\n2014-04-04 03:35:00,20.1401168511\n2014-04-04 03:40:00,20.5131729139\n2014-04-04 03:45:00,21.6875151735\n2014-04-04 03:50:00,18.7147718091\n2014-04-04 03:55:00,19.1822099945\n2014-04-04 04:00:00,21.9031573454\n2014-04-04 04:05:00,19.484771946600002\n2014-04-04 04:10:00,18.090246603\n2014-04-04 04:15:00,18.5905739705\n2014-04-04 04:20:00,18.105354807\n2014-04-04 04:25:00,21.9596925697\n2014-04-04 04:30:00,19.115483396\n2014-04-04 04:35:00,21.6941710277\n2014-04-04 04:40:00,21.983545103\n2014-04-04 04:45:00,20.3993648846\n2014-04-04 04:50:00,18.1327852603\n2014-04-04 04:55:00,18.326366521500002\n2014-04-04 05:00:00,19.9263562204\n2014-04-04 05:05:00,19.6246880516\n2014-04-04 05:10:00,20.4247092231\n2014-04-04 05:15:00,19.7553912388\n2014-04-04 05:20:00,21.7363073971\n2014-04-04 05:25:00,20.1389588617\n2014-04-04 05:30:00,20.7749042458\n2014-04-04 05:35:00,21.5859410906\n2014-04-04 05:40:00,18.5874875033\n2014-04-04 05:45:00,18.9189386165\n2014-04-04 05:50:00,18.4292746419\n2014-04-04 05:55:00,18.5585535969\n2014-04-04 06:00:00,20.0503358677\n2014-04-04 06:05:00,19.284717035899998\n2014-04-04 06:10:00,19.6926913581\n2014-04-04 06:15:00,21.9299593272\n2014-04-04 06:20:00,18.6268173912\n2014-04-04 06:25:00,20.163248283199998\n2014-04-04 06:30:00,18.3954846202\n2014-04-04 06:35:00,19.2739852531\n2014-04-04 06:40:00,20.1101036947\n2014-04-04 06:45:00,21.7865269839\n2014-04-04 06:50:00,19.5649128851\n2014-04-04 06:55:00,18.2596267849\n2014-04-04 07:00:00,19.5526457918\n2014-04-04 07:05:00,18.5829647035\n2014-04-04 07:10:00,18.9199584532\n2014-04-04 07:15:00,20.4723624927\n2014-04-04 07:20:00,18.2696954648\n2014-04-04 07:25:00,19.858895025\n2014-04-04 07:30:00,20.437846344\n2014-04-04 07:35:00,19.6874335695\n2014-04-04 07:40:00,18.0765054025\n2014-04-04 07:45:00,21.9420774276\n2014-04-04 07:50:00,19.468463069400002\n2014-04-04 07:55:00,21.1143087477\n2014-04-04 08:00:00,19.302585968699997\n2014-04-04 08:05:00,19.900067028\n2014-04-04 08:10:00,19.5538545704\n2014-04-04 08:15:00,19.370156918\n2014-04-04 08:20:00,18.0874055088\n2014-04-04 08:25:00,19.4400837514\n2014-04-04 08:30:00,21.557959961599998\n2014-04-04 08:35:00,20.7615733544\n2014-04-04 08:40:00,18.5816914364\n2014-04-04 08:45:00,20.3646200185\n2014-04-04 08:50:00,21.5689234398\n2014-04-04 08:55:00,20.8001361639\n2014-04-04 09:00:00,63.2221077361\n2014-04-04 09:05:00,73.0025219556\n2014-04-04 09:10:00,65.3009985807\n2014-04-04 09:15:00,67.3754355626\n2014-04-04 09:20:00,68.3555415318\n2014-04-04 09:25:00,72.7668898195\n2014-04-04 09:30:00,73.869861934\n2014-04-04 09:35:00,73.843279138\n2014-04-04 09:40:00,61.3081768654\n2014-04-04 09:45:00,73.737683404\n2014-04-04 09:50:00,61.9396627376\n2014-04-04 09:55:00,64.8145217327\n2014-04-04 10:00:00,77.8326115054\n2014-04-04 10:05:00,77.2884466933\n2014-04-04 10:10:00,79.2250960011\n2014-04-04 10:15:00,77.28100547\n2014-04-04 10:20:00,84.341510548\n2014-04-04 10:25:00,73.5733181243\n2014-04-04 10:30:00,74.09286325149999\n2014-04-04 10:35:00,84.129852762\n2014-04-04 10:40:00,71.0309972533\n2014-04-04 10:45:00,79.300383956\n2014-04-04 10:50:00,80.4205419761\n2014-04-04 10:55:00,77.6860075476\n2014-04-04 11:00:00,82.6090638008\n2014-04-04 11:05:00,74.3154898902\n2014-04-04 11:10:00,85.12826303\n2014-04-04 11:15:00,73.7949685653\n2014-04-04 11:20:00,77.9425211144\n2014-04-04 11:25:00,72.7648968912\n2014-04-04 11:30:00,80.2390369975\n2014-04-04 11:35:00,82.2196373213\n2014-04-04 11:40:00,86.53718888459998\n2014-04-04 11:45:00,83.32640285949999\n2014-04-04 11:50:00,80.17370078329998\n2014-04-04 11:55:00,86.4003410411\n2014-04-04 12:00:00,79.5594034214\n2014-04-04 12:05:00,80.882115301\n2014-04-04 12:10:00,81.439731351\n2014-04-04 12:15:00,78.4654040034\n2014-04-04 12:20:00,85.3132241814\n2014-04-04 12:25:00,74.87285964350001\n2014-04-04 12:30:00,80.7804220759\n2014-04-04 12:35:00,83.4554652205\n2014-04-04 12:40:00,86.3598624075\n2014-04-04 12:45:00,86.03932310969999\n2014-04-04 12:50:00,80.0436768173\n2014-04-04 12:55:00,82.19183451880002\n2014-04-04 13:00:00,78.2890099052\n2014-04-04 13:05:00,79.4717664035\n2014-04-04 13:10:00,86.4794926205\n2014-04-04 13:15:00,86.8704099877\n2014-04-04 13:20:00,86.3059065391\n2014-04-04 13:25:00,74.1961224449\n2014-04-04 13:30:00,85.5808000186\n2014-04-04 13:35:00,87.15289797959998\n2014-04-04 13:40:00,77.7613279144\n2014-04-04 13:45:00,80.279069029\n2014-04-04 13:50:00,84.4452523672\n2014-04-04 13:55:00,80.973811821\n2014-04-04 14:00:00,87.89151735200001\n2014-04-04 14:05:00,79.2876078546\n2014-04-04 14:10:00,83.4190790713\n2014-04-04 14:15:00,84.6773935331\n2014-04-04 14:20:00,79.90177118300001\n2014-04-04 14:25:00,85.70762672779999\n2014-04-04 14:30:00,80.7345980126\n2014-04-04 14:35:00,78.58264060100001\n2014-04-04 14:40:00,73.721639973\n2014-04-04 14:45:00,78.29085908\n2014-04-04 14:50:00,83.7389636125\n2014-04-04 14:55:00,86.7364190389\n2014-04-04 15:00:00,76.0261406038\n2014-04-04 15:05:00,77.6830225131\n2014-04-04 15:10:00,74.4626610573\n2014-04-04 15:15:00,83.0507690126\n2014-04-04 15:20:00,87.3621761952\n2014-04-04 15:25:00,82.25444586729999\n2014-04-04 15:30:00,81.8724384971\n2014-04-04 15:35:00,80.855062672\n2014-04-04 15:40:00,73.4145870642\n2014-04-04 15:45:00,83.67125797109999\n2014-04-04 15:50:00,81.63200902199999\n2014-04-04 15:55:00,82.58283549890001\n2014-04-04 16:00:00,86.38081163700001\n2014-04-04 16:05:00,84.5432102697\n2014-04-04 16:10:00,84.49448180479999\n2014-04-04 16:15:00,86.834773579\n2014-04-04 16:20:00,87.8387905726\n2014-04-04 16:25:00,81.3003676144\n2014-04-04 16:30:00,73.7419642717\n2014-04-04 16:35:00,79.3459261799\n2014-04-04 16:40:00,84.6014559083\n2014-04-04 16:45:00,72.4434661045\n2014-04-04 16:50:00,72.9100590261\n2014-04-04 16:55:00,73.074384215\n2014-04-04 17:00:00,83.6965399938\n2014-04-04 17:05:00,80.01863532979999\n2014-04-04 17:10:00,77.90233718180001\n2014-04-04 17:15:00,73.6898444273\n2014-04-04 17:20:00,83.71581185640001\n2014-04-04 17:25:00,77.1362873485\n2014-04-04 17:30:00,76.2451558429\n2014-04-04 17:35:00,82.437075569\n2014-04-04 17:40:00,80.944143199\n2014-04-04 17:45:00,77.79854039439999\n2014-04-04 17:50:00,82.2637679436\n2014-04-04 17:55:00,76.3395150118\n2014-04-04 18:00:00,33.886907168\n2014-04-04 18:05:00,30.2676354706\n2014-04-04 18:10:00,29.8165555257\n2014-04-04 18:15:00,33.8076057297\n2014-04-04 18:20:00,33.330502597\n2014-04-04 18:25:00,29.9688836905\n2014-04-04 18:30:00,29.5439671448\n2014-04-04 18:35:00,34.1657476065\n2014-04-04 18:40:00,33.7702238022\n2014-04-04 18:45:00,30.8944412599\n2014-04-04 18:50:00,33.0124570742\n2014-04-04 18:55:00,29.5946195117\n2014-04-04 19:00:00,22.431572281999998\n2014-04-04 19:05:00,20.2439105979\n2014-04-04 19:10:00,21.9143752244\n2014-04-04 19:15:00,20.4952947159\n2014-04-04 19:20:00,22.2886581444\n2014-04-04 19:25:00,22.0491325683\n2014-04-04 19:30:00,22.1508437042\n2014-04-04 19:35:00,20.3630831161\n2014-04-04 19:40:00,21.7800400142\n2014-04-04 19:45:00,23.5490463521\n2014-04-04 19:50:00,21.812735196\n2014-04-04 19:55:00,23.363969066\n2014-04-04 20:00:00,19.9453846127\n2014-04-04 20:05:00,20.1655885104\n2014-04-04 20:10:00,20.7417018452\n2014-04-04 20:15:00,22.3259929452\n2014-04-04 20:20:00,18.8778921629\n2014-04-04 20:25:00,18.5668145736\n2014-04-04 20:30:00,20.9221923738\n2014-04-04 20:35:00,22.3195014084\n2014-04-04 20:40:00,22.4859056811\n2014-04-04 20:45:00,20.415136512300002\n2014-04-04 20:50:00,20.3492620758\n2014-04-04 20:55:00,21.0737713521\n2014-04-04 21:00:00,20.319607166500003\n2014-04-04 21:05:00,20.6349266707\n2014-04-04 21:10:00,21.5991784383\n2014-04-04 21:15:00,21.0859537048\n2014-04-04 21:20:00,20.0834495635\n2014-04-04 21:25:00,19.9427255848\n2014-04-04 21:30:00,20.657087297100002\n2014-04-04 21:35:00,19.9179746496\n2014-04-04 21:40:00,19.9263067199\n2014-04-04 21:45:00,18.1519366361\n2014-04-04 21:50:00,18.7859985351\n2014-04-04 21:55:00,20.0498339728\n2014-04-04 22:00:00,21.311052815\n2014-04-04 22:05:00,19.1332583292\n2014-04-04 22:10:00,20.1098606734\n2014-04-04 22:15:00,19.3984529839\n2014-04-04 22:20:00,18.4368983964\n2014-04-04 22:25:00,21.8541537877\n2014-04-04 22:30:00,21.4392574181\n2014-04-04 22:35:00,18.3315510998\n2014-04-04 22:40:00,20.8991930227\n2014-04-04 22:45:00,19.4089343147\n2014-04-04 22:50:00,22.0004994407\n2014-04-04 22:55:00,19.2280352802\n2014-04-04 23:00:00,18.9585931307\n2014-04-04 23:05:00,20.2754543312\n2014-04-04 23:10:00,21.3446020282\n2014-04-04 23:15:00,18.7736793399\n2014-04-04 23:20:00,20.8416118982\n2014-04-04 23:25:00,18.249129490999998\n2014-04-04 23:30:00,21.6799007122\n2014-04-04 23:35:00,18.3278179283\n2014-04-04 23:40:00,21.6610836329\n2014-04-04 23:45:00,19.9670619358\n2014-04-04 23:50:00,19.7961645832\n2014-04-04 23:55:00,21.897431815700003\n2014-04-05 00:00:00,21.9615367108\n2014-04-05 00:05:00,20.6007125038\n2014-04-05 00:10:00,18.5084771674\n2014-04-05 00:15:00,20.0246803426\n2014-04-05 00:20:00,20.1166524038\n2014-04-05 00:25:00,20.0577857125\n2014-04-05 00:30:00,20.2779673541\n2014-04-05 00:35:00,18.0748988552\n2014-04-05 00:40:00,20.8449091259\n2014-04-05 00:45:00,20.8495772078\n2014-04-05 00:50:00,18.4618791007\n2014-04-05 00:55:00,20.2809577698\n2014-04-05 01:00:00,20.2734447297\n2014-04-05 01:05:00,20.729801680799998\n2014-04-05 01:10:00,18.341590768499998\n2014-04-05 01:15:00,20.506013229100002\n2014-04-05 01:20:00,19.123007803\n2014-04-05 01:25:00,20.028011962\n2014-04-05 01:30:00,21.0932942108\n2014-04-05 01:35:00,20.8225837455\n2014-04-05 01:40:00,18.4756120707\n2014-04-05 01:45:00,20.3647391485\n2014-04-05 01:50:00,21.8764661238\n2014-04-05 01:55:00,18.6270777493\n2014-04-05 02:00:00,21.4116283509\n2014-04-05 02:05:00,20.8101923222\n2014-04-05 02:10:00,21.096013251600002\n2014-04-05 02:15:00,19.1278333086\n2014-04-05 02:20:00,19.1515557175\n2014-04-05 02:25:00,21.6240778231\n2014-04-05 02:30:00,19.4393281284\n2014-04-05 02:35:00,18.252061562799998\n2014-04-05 02:40:00,20.4023868143\n2014-04-05 02:45:00,18.4992706762\n2014-04-05 02:50:00,21.1863849656\n2014-04-05 02:55:00,20.56698577\n2014-04-05 03:00:00,21.4989060209\n2014-04-05 03:05:00,21.1393489991\n2014-04-05 03:10:00,18.448454593399997\n2014-04-05 03:15:00,19.5242827057\n2014-04-05 03:20:00,21.0982409997\n2014-04-05 03:25:00,19.6693658931\n2014-04-05 03:30:00,21.8894619391\n2014-04-05 03:35:00,20.9429617996\n2014-04-05 03:40:00,18.061999666800002\n2014-04-05 03:45:00,21.5199427662\n2014-04-05 03:50:00,18.4032191395\n2014-04-05 03:55:00,18.5620948967\n2014-04-05 04:00:00,20.9379696024\n2014-04-05 04:05:00,21.4598742377\n2014-04-05 04:10:00,20.1453985116\n2014-04-05 04:15:00,19.156198931800002\n2014-04-05 04:20:00,19.405262180999998\n2014-04-05 04:25:00,19.3715573184\n2014-04-05 04:30:00,19.3067124152\n2014-04-05 04:35:00,18.9716386873\n2014-04-05 04:40:00,20.435468378499998\n2014-04-05 04:45:00,21.601621274299998\n2014-04-05 04:50:00,19.2283296523\n2014-04-05 04:55:00,18.7467771898\n2014-04-05 05:00:00,21.354310665499998\n2014-04-05 05:05:00,20.9671333236\n2014-04-05 05:10:00,21.723348126199998\n2014-04-05 05:15:00,18.6620789424\n2014-04-05 05:20:00,18.5770052565\n2014-04-05 05:25:00,20.1657175772\n2014-04-05 05:30:00,20.457734619300002\n2014-04-05 05:35:00,19.9206937674\n2014-04-05 05:40:00,20.3958665453\n2014-04-05 05:45:00,18.721519075499998\n2014-04-05 05:50:00,19.9184550167\n2014-04-05 05:55:00,20.6323702438\n2014-04-05 06:00:00,19.730825797\n2014-04-05 06:05:00,20.717789343299998\n2014-04-05 06:10:00,19.8047651222\n2014-04-05 06:15:00,19.3343983234\n2014-04-05 06:20:00,19.2144201883\n2014-04-05 06:25:00,19.643608236\n2014-04-05 06:30:00,18.0923584907\n2014-04-05 06:35:00,20.674100553800002\n2014-04-05 06:40:00,21.3804225639\n2014-04-05 06:45:00,19.4185083778\n2014-04-05 06:50:00,18.1841325446\n2014-04-05 06:55:00,21.9471023895\n2014-04-05 07:00:00,19.054793021800002\n2014-04-05 07:05:00,18.5064844868\n2014-04-05 07:10:00,19.4790100319\n2014-04-05 07:15:00,20.9542281625\n2014-04-05 07:20:00,19.1756663876\n2014-04-05 07:25:00,20.2988128157\n2014-04-05 07:30:00,19.6622399777\n2014-04-05 07:35:00,18.4710559691\n2014-04-05 07:40:00,19.32114805\n2014-04-05 07:45:00,20.8994820229\n2014-04-05 07:50:00,20.448015589300002\n2014-04-05 07:55:00,18.4791135195\n2014-04-05 08:00:00,18.653289638900002\n2014-04-05 08:05:00,20.5629334372\n2014-04-05 08:10:00,21.2536616573\n2014-04-05 08:15:00,19.3978979838\n2014-04-05 08:20:00,20.3812430074\n2014-04-05 08:25:00,18.682574355\n2014-04-05 08:30:00,19.245505347599998\n2014-04-05 08:35:00,18.0810808227\n2014-04-05 08:40:00,21.073103791199998\n2014-04-05 08:45:00,19.6040392791\n2014-04-05 08:50:00,21.2645022946\n2014-04-05 08:55:00,20.8334919841\n2014-04-05 09:00:00,72.47092201390001\n2014-04-05 09:05:00,65.0849579063\n2014-04-05 09:10:00,63.7174787338\n2014-04-05 09:15:00,74.4179172841\n2014-04-05 09:20:00,70.9556579038\n2014-04-05 09:25:00,72.5429748438\n2014-04-05 09:30:00,61.3786138825\n2014-04-05 09:35:00,66.020678036\n2014-04-05 09:40:00,71.3023069919\n2014-04-05 09:45:00,62.2605665287\n2014-04-05 09:50:00,68.9158230421\n2014-04-05 09:55:00,67.0353896374\n2014-04-05 10:00:00,70.1134081908\n2014-04-05 10:05:00,73.5023409569\n2014-04-05 10:10:00,74.2599716703\n2014-04-05 10:15:00,71.5760663673\n2014-04-05 10:20:00,79.6414528392\n2014-04-05 10:25:00,73.6020150394\n2014-04-05 10:30:00,74.1486546341\n2014-04-05 10:35:00,83.7806630441\n2014-04-05 10:40:00,77.0897503986\n2014-04-05 10:45:00,75.925828841\n2014-04-05 10:50:00,81.0744785146\n2014-04-05 10:55:00,83.9572061276\n2014-04-05 11:00:00,71.9661778915\n2014-04-05 11:05:00,78.69679061560001\n2014-04-05 11:10:00,81.2818666871\n2014-04-05 11:15:00,76.6344275126\n2014-04-05 11:20:00,83.8523724126\n2014-04-05 11:25:00,87.0183713256\n2014-04-05 11:30:00,86.5722688328\n2014-04-05 11:35:00,75.7981863063\n2014-04-05 11:40:00,75.1676839803\n2014-04-05 11:45:00,86.7959294054\n2014-04-05 11:50:00,78.8620274641\n2014-04-05 11:55:00,74.8807669879\n2014-04-05 12:00:00,83.2119770764\n2014-04-05 12:05:00,76.4588643122\n2014-04-05 12:10:00,76.1844204592\n2014-04-05 12:15:00,85.9647031076\n2014-04-05 12:20:00,74.5101468543\n2014-04-05 12:25:00,72.9426507989\n2014-04-05 12:30:00,76.2154146631\n2014-04-05 12:35:00,81.6130732535\n2014-04-05 12:40:00,73.8806423677\n2014-04-05 12:45:00,79.4500601387\n2014-04-05 12:50:00,81.9389488943\n2014-04-05 12:55:00,85.4770961312\n2014-04-05 13:00:00,75.65975076\n2014-04-05 13:05:00,85.0571225642\n2014-04-05 13:10:00,75.74031813810001\n2014-04-05 13:15:00,82.80838587630002\n2014-04-05 13:20:00,78.8718433572\n2014-04-05 13:25:00,73.8171795021\n2014-04-05 13:30:00,83.40819263350001\n2014-04-05 13:35:00,75.4660856883\n2014-04-05 13:40:00,74.8080165824\n2014-04-05 13:45:00,77.7145108974\n2014-04-05 13:50:00,82.4328552816\n2014-04-05 13:55:00,75.7257651142\n2014-04-05 14:00:00,74.9349875684\n2014-04-05 14:05:00,72.155794367\n2014-04-05 14:10:00,79.5424713317\n2014-04-05 14:15:00,78.8545439092\n2014-04-05 14:20:00,75.73824828779999\n2014-04-05 14:25:00,72.8549374193\n2014-04-05 14:30:00,78.864308325\n2014-04-05 14:35:00,84.6072204356\n2014-04-05 14:40:00,83.4405087646\n2014-04-05 14:45:00,85.76860114729999\n2014-04-05 14:50:00,72.1498596439\n2014-04-05 14:55:00,87.4585108588\n2014-04-05 15:00:00,77.4618524011\n2014-04-05 15:05:00,87.8455214124\n2014-04-05 15:10:00,76.0411813673\n2014-04-05 15:15:00,79.5438185733\n2014-04-05 15:20:00,77.6620972619\n2014-04-05 15:25:00,77.6914255951\n2014-04-05 15:30:00,85.4756930054\n2014-04-05 15:35:00,83.9418971858\n2014-04-05 15:40:00,87.8735793692\n2014-04-05 15:45:00,81.8154494876\n2014-04-05 15:50:00,79.4113433141\n2014-04-05 15:55:00,73.44047677180001\n2014-04-05 16:00:00,87.94481385790002\n2014-04-05 16:05:00,80.8243352639\n2014-04-05 16:10:00,83.2074797564\n2014-04-05 16:15:00,78.5077274599\n2014-04-05 16:20:00,80.763296265\n2014-04-05 16:25:00,87.08107651430002\n2014-04-05 16:30:00,74.6625676545\n2014-04-05 16:35:00,76.6778141276\n2014-04-05 16:40:00,74.4328127332\n2014-04-05 16:45:00,84.67529188399999\n2014-04-05 16:50:00,72.9925840207\n2014-04-05 16:55:00,73.3059656499\n2014-04-05 17:00:00,76.7758763227\n2014-04-05 17:05:00,80.2269800876\n2014-04-05 17:10:00,78.5003666648\n2014-04-05 17:15:00,72.7170330474\n2014-04-05 17:20:00,87.3198313951\n2014-04-05 17:25:00,87.2458788233\n2014-04-05 17:30:00,76.4696718075\n2014-04-05 17:35:00,83.7043777018\n2014-04-05 17:40:00,81.2571753794\n2014-04-05 17:45:00,75.79959801300001\n2014-04-05 17:50:00,76.1947155691\n2014-04-05 17:55:00,79.8584201233\n2014-04-05 18:00:00,31.4831103808\n2014-04-05 18:05:00,30.6638618132\n2014-04-05 18:10:00,33.9680676945\n2014-04-05 18:15:00,31.8813565517\n2014-04-05 18:20:00,32.991021265\n2014-04-05 18:25:00,30.0113446389\n2014-04-05 18:30:00,32.2144428549\n2014-04-05 18:35:00,30.83504079610001\n2014-04-05 18:40:00,32.1690409301\n2014-04-05 18:45:00,33.7972788448\n2014-04-05 18:50:00,33.7210380701\n2014-04-05 18:55:00,31.067006374600002\n2014-04-05 19:00:00,23.270360208000003\n2014-04-05 19:05:00,24.3769776405\n2014-04-05 19:10:00,22.9629973384\n2014-04-05 19:15:00,20.8248762104\n2014-04-05 19:20:00,23.205093386199998\n2014-04-05 19:25:00,20.629970519100002\n2014-04-05 19:30:00,24.0670533111\n2014-04-05 19:35:00,22.4746377883\n2014-04-05 19:40:00,21.8854292981\n2014-04-05 19:45:00,20.4153884241\n2014-04-05 19:50:00,21.865909931500006\n2014-04-05 19:55:00,24.2063645444\n2014-04-05 20:00:00,18.5179461306\n2014-04-05 20:05:00,20.3761586098\n2014-04-05 20:10:00,22.246023274200002\n2014-04-05 20:15:00,20.0492684944\n2014-04-05 20:20:00,20.1858073736\n2014-04-05 20:25:00,20.8017817365\n2014-04-05 20:30:00,20.3281910744\n2014-04-05 20:35:00,19.1225922978\n2014-04-05 20:40:00,18.508003265899998\n2014-04-05 20:45:00,20.9297882999\n2014-04-05 20:50:00,22.2036235139\n2014-04-05 20:55:00,18.8676672625\n2014-04-05 21:00:00,18.9342611229\n2014-04-05 21:05:00,19.574426301600003\n2014-04-05 21:10:00,21.3368967147\n2014-04-05 21:15:00,19.1686110171\n2014-04-05 21:20:00,21.6315530088\n2014-04-05 21:25:00,18.307286645\n2014-04-05 21:30:00,21.868292798699997\n2014-04-05 21:35:00,20.3401546056\n2014-04-05 21:40:00,20.734159194700002\n2014-04-05 21:45:00,19.5642176811\n2014-04-05 21:50:00,21.2293913804\n2014-04-05 21:55:00,18.755863026500002\n2014-04-05 22:00:00,18.2131151136\n2014-04-05 22:05:00,19.6008665479\n2014-04-05 22:10:00,21.4353410369\n2014-04-05 22:15:00,21.0398862553\n2014-04-05 22:20:00,20.087889751\n2014-04-05 22:25:00,20.3080279876\n2014-04-05 22:30:00,18.5373500845\n2014-04-05 22:35:00,21.383234241\n2014-04-05 22:40:00,21.1681406466\n2014-04-05 22:45:00,20.6456824117\n2014-04-05 22:50:00,19.8838343091\n2014-04-05 22:55:00,21.878820586\n2014-04-05 23:00:00,21.5202589819\n2014-04-05 23:05:00,20.5816728947\n2014-04-05 23:10:00,19.4909455321\n2014-04-05 23:15:00,20.476019753800003\n2014-04-05 23:20:00,20.3056616428\n2014-04-05 23:25:00,19.5807267273\n2014-04-05 23:30:00,19.2303874105\n2014-04-05 23:35:00,19.631811751300003\n2014-04-05 23:40:00,20.2995423861\n2014-04-05 23:45:00,19.7163241845\n2014-04-05 23:50:00,19.057956376099998\n2014-04-05 23:55:00,21.047893688800002\n2014-04-06 00:00:00,20.1258699838\n2014-04-06 00:05:00,18.2707006529\n2014-04-06 00:10:00,19.4732660225\n2014-04-06 00:15:00,21.539653828800002\n2014-04-06 00:20:00,21.020946124800002\n2014-04-06 00:25:00,19.2929871358\n2014-04-06 00:30:00,21.752732608200002\n2014-04-06 00:35:00,18.3064116334\n2014-04-06 00:40:00,21.8449388156\n2014-04-06 00:45:00,18.9828203699\n2014-04-06 00:50:00,18.0363767212\n2014-04-06 00:55:00,19.7352321461\n2014-04-06 01:00:00,19.4358817187\n2014-04-06 01:05:00,20.1563560208\n2014-04-06 01:10:00,21.1870914423\n2014-04-06 01:15:00,21.3697232086\n2014-04-06 01:20:00,19.6049199984\n2014-04-06 01:25:00,19.7193829748\n2014-04-06 01:30:00,18.5927109213\n2014-04-06 01:35:00,18.1901904355\n2014-04-06 01:40:00,20.564859960899998\n2014-04-06 01:45:00,18.2577505022\n2014-04-06 01:50:00,20.9353204777\n2014-04-06 01:55:00,20.1563605801\n2014-04-06 02:00:00,18.7943319129\n2014-04-06 02:05:00,20.1580917741\n2014-04-06 02:10:00,18.7319908664\n2014-04-06 02:15:00,19.75494883\n2014-04-06 02:20:00,21.198241265\n2014-04-06 02:25:00,19.847677173599998\n2014-04-06 02:30:00,18.5947972732\n2014-04-06 02:35:00,20.8953147273\n2014-04-06 02:40:00,18.7470736651\n2014-04-06 02:45:00,20.9541994975\n2014-04-06 02:50:00,19.9174091569\n2014-04-06 02:55:00,19.814967036400002\n2014-04-06 03:00:00,21.4057401514\n2014-04-06 03:05:00,20.8344140974\n2014-04-06 03:10:00,18.131643187799998\n2014-04-06 03:15:00,19.1846972584\n2014-04-06 03:20:00,21.4836826434\n2014-04-06 03:25:00,18.0733046742\n2014-04-06 03:30:00,20.181013785\n2014-04-06 03:35:00,20.9113026767\n2014-04-06 03:40:00,20.4874243419\n2014-04-06 03:45:00,21.042128808399998\n2014-04-06 03:50:00,20.9027673957\n2014-04-06 03:55:00,20.7681227806\n2014-04-06 04:00:00,21.286159443699997\n2014-04-06 04:05:00,20.5827626738\n2014-04-06 04:10:00,19.609673977\n2014-04-06 04:15:00,19.8876364397\n2014-04-06 04:20:00,20.8668991307\n2014-04-06 04:25:00,21.5052241187\n2014-04-06 04:30:00,19.0888752034\n2014-04-06 04:35:00,19.3683071839\n2014-04-06 04:40:00,21.7229575854\n2014-04-06 04:45:00,20.314047169600002\n2014-04-06 04:50:00,18.7158472685\n2014-04-06 04:55:00,20.6547805556\n2014-04-06 05:00:00,21.9630486222\n2014-04-06 05:05:00,21.2938142579\n2014-04-06 05:10:00,20.982964546199998\n2014-04-06 05:15:00,18.8321866171\n2014-04-06 05:20:00,21.5045591387\n2014-04-06 05:25:00,20.1031553741\n2014-04-06 05:30:00,21.557160088299998\n2014-04-06 05:35:00,19.3193113177\n2014-04-06 05:40:00,18.2482042105\n2014-04-06 05:45:00,19.9039038746\n2014-04-06 05:50:00,19.0793504193\n2014-04-06 05:55:00,20.8609171591\n2014-04-06 06:00:00,21.8284262114\n2014-04-06 06:05:00,20.7638966046\n2014-04-06 06:10:00,21.547735718800002\n2014-04-06 06:15:00,19.8120960544\n2014-04-06 06:20:00,21.0865629488\n2014-04-06 06:25:00,21.3721737467\n2014-04-06 06:30:00,20.8435025103\n2014-04-06 06:35:00,20.0311091443\n2014-04-06 06:40:00,20.5034644385\n2014-04-06 06:45:00,20.8020279827\n2014-04-06 06:50:00,19.012337612899998\n2014-04-06 06:55:00,21.2383170437\n2014-04-06 07:00:00,21.801298155900003\n2014-04-06 07:05:00,19.860957260699998\n2014-04-06 07:10:00,20.8042687324\n2014-04-06 07:15:00,20.948103623199998\n2014-04-06 07:20:00,20.6489901901\n2014-04-06 07:25:00,20.188460433299998\n2014-04-06 07:30:00,21.5265918183\n2014-04-06 07:35:00,19.7957068371\n2014-04-06 07:40:00,18.2444118259\n2014-04-06 07:45:00,21.3782255028\n2014-04-06 07:50:00,20.6959250893\n2014-04-06 07:55:00,21.397034506\n2014-04-06 08:00:00,18.5541897698\n2014-04-06 08:05:00,18.123011762\n2014-04-06 08:10:00,21.7374981615\n2014-04-06 08:15:00,18.590913223399998\n2014-04-06 08:20:00,21.2386093283\n2014-04-06 08:25:00,21.2928397687\n2014-04-06 08:30:00,20.8348208022\n2014-04-06 08:35:00,18.5250488444\n2014-04-06 08:40:00,20.6695944982\n2014-04-06 08:45:00,21.5563463333\n2014-04-06 08:50:00,19.7021265792\n2014-04-06 08:55:00,19.6540674175\n2014-04-06 09:00:00,67.22287301029999\n2014-04-06 09:05:00,62.318897713199995\n2014-04-06 09:10:00,73.3315477388\n2014-04-06 09:15:00,73.0208869501\n2014-04-06 09:20:00,74.7715667763\n2014-04-06 09:25:00,69.1584907244\n2014-04-06 09:30:00,71.41620625569999\n2014-04-06 09:35:00,63.9563379258\n2014-04-06 09:40:00,70.2783919278\n2014-04-06 09:45:00,70.0363667431\n2014-04-06 09:50:00,73.45643880739999\n2014-04-06 09:55:00,72.4987810306\n2014-04-06 10:00:00,84.4049994998\n2014-04-06 10:05:00,83.3242954963\n2014-04-06 10:10:00,83.3221292488\n2014-04-06 10:15:00,70.8289860302\n2014-04-06 10:20:00,82.9693295058\n2014-04-06 10:25:00,79.2680646827\n2014-04-06 10:30:00,75.7444978914\n2014-04-06 10:35:00,70.7171069705\n2014-04-06 10:40:00,80.3574969844\n2014-04-06 10:45:00,74.9336911683\n2014-04-06 10:50:00,77.0998876326\n2014-04-06 10:55:00,80.4204253431\n2014-04-06 11:00:00,86.0688623959\n2014-04-06 11:05:00,84.6957487058\n2014-04-06 11:10:00,78.7342967413\n2014-04-06 11:15:00,77.735303336\n2014-04-06 11:20:00,75.3814569666\n2014-04-06 11:25:00,77.49107505069999\n2014-04-06 11:30:00,73.33408174350001\n2014-04-06 11:35:00,87.012462005\n2014-04-06 11:40:00,80.6955830287\n2014-04-06 11:45:00,73.6006241238\n2014-04-06 11:50:00,77.1790267714\n2014-04-06 11:55:00,80.2681105401\n2014-04-06 12:00:00,80.429538782\n2014-04-06 12:05:00,72.48097223479999\n2014-04-06 12:10:00,87.10880039979997\n2014-04-06 12:15:00,76.3143236905\n2014-04-06 12:20:00,72.1722439573\n2014-04-06 12:25:00,73.1352364182\n2014-04-06 12:30:00,81.1855787098\n2014-04-06 12:35:00,74.1155228488\n2014-04-06 12:40:00,72.5803955696\n2014-04-06 12:45:00,77.9803346344\n2014-04-06 12:50:00,81.8658220626\n2014-04-06 12:55:00,73.7008895532\n2014-04-06 13:00:00,76.9947621355\n2014-04-06 13:05:00,78.665286545\n2014-04-06 13:10:00,74.53346923779999\n2014-04-06 13:15:00,80.0779590517\n2014-04-06 13:20:00,73.3458181683\n2014-04-06 13:25:00,72.7268373105\n2014-04-06 13:30:00,80.2980897067\n2014-04-06 13:35:00,75.9481196396\n2014-04-06 13:40:00,73.5083346909\n2014-04-06 13:45:00,78.7636935755\n2014-04-06 13:50:00,86.6214576918\n2014-04-06 13:55:00,83.5670182475\n2014-04-06 14:00:00,85.0457722525\n2014-04-06 14:05:00,85.9464981902\n2014-04-06 14:10:00,87.5578408842\n2014-04-06 14:15:00,84.2079030029\n2014-04-06 14:20:00,81.7306034937\n2014-04-06 14:25:00,77.84307743779999\n2014-04-06 14:30:00,74.9026962829\n2014-04-06 14:35:00,82.9825746289\n2014-04-06 14:40:00,87.91497965639999\n2014-04-06 14:45:00,79.4739240224\n2014-04-06 14:50:00,83.5748581037\n2014-04-06 14:55:00,79.9176429689\n2014-04-06 15:00:00,78.9101772288\n2014-04-06 15:05:00,78.56413559399999\n2014-04-06 15:10:00,80.0732262166\n2014-04-06 15:15:00,77.8695830347\n2014-04-06 15:20:00,83.9795669376\n2014-04-06 15:25:00,85.98752693729998\n2014-04-06 15:30:00,86.1253380951\n2014-04-06 15:35:00,75.6424532403\n2014-04-06 15:40:00,86.3337174081\n2014-04-06 15:45:00,77.4640760474\n2014-04-06 15:50:00,76.9481839381\n2014-04-06 15:55:00,83.6272940886\n2014-04-06 16:00:00,76.8749938411\n2014-04-06 16:05:00,72.8473226226\n2014-04-06 16:10:00,77.9777346394\n2014-04-06 16:15:00,83.5432892023\n2014-04-06 16:20:00,77.2311864402\n2014-04-06 16:25:00,82.0727873159\n2014-04-06 16:30:00,82.5617525893\n2014-04-06 16:35:00,83.7396154073\n2014-04-06 16:40:00,86.3539216611\n2014-04-06 16:45:00,78.9208804599\n2014-04-06 16:50:00,74.6627698738\n2014-04-06 16:55:00,77.1026634095\n2014-04-06 17:00:00,78.91464577949999\n2014-04-06 17:05:00,83.4222314751\n2014-04-06 17:10:00,72.2099262804\n2014-04-06 17:15:00,77.0525365469\n2014-04-06 17:20:00,84.477448857\n2014-04-06 17:25:00,82.73369148350001\n2014-04-06 17:30:00,83.7078074336\n2014-04-06 17:35:00,84.9889396753\n2014-04-06 17:40:00,84.53173904180001\n2014-04-06 17:45:00,82.9148988191\n2014-04-06 17:50:00,79.0345541686\n2014-04-06 17:55:00,87.7375395708\n2014-04-06 18:00:00,32.4420622229\n2014-04-06 18:05:00,30.0977171612\n2014-04-06 18:10:00,30.6739963833\n2014-04-06 18:15:00,33.2387933364\n2014-04-06 18:20:00,34.7183265514\n2014-04-06 18:25:00,29.9438030777\n2014-04-06 18:30:00,29.327011942\n2014-04-06 18:35:00,34.441792094600004\n2014-04-06 18:40:00,34.657772410700005\n2014-04-06 18:45:00,30.5688219408\n2014-04-06 18:50:00,31.214622642800002\n2014-04-06 18:55:00,33.0251968431\n2014-04-06 19:00:00,21.638085306399997\n2014-04-06 19:05:00,24.089669691599997\n2014-04-06 19:10:00,20.641951455799997\n2014-04-06 19:15:00,20.3301592346\n2014-04-06 19:20:00,21.0940170491\n2014-04-06 19:25:00,21.4416720701\n2014-04-06 19:30:00,20.665909995299998\n2014-04-06 19:35:00,20.454292001400002\n2014-04-06 19:40:00,23.545121264899997\n2014-04-06 19:45:00,20.895957868900002\n2014-04-06 19:50:00,24.25437012130001\n2014-04-06 19:55:00,21.8086372869\n2014-04-06 20:00:00,21.1788011425\n2014-04-06 20:05:00,19.3552468298\n2014-04-06 20:10:00,19.4163618267\n2014-04-06 20:15:00,20.7860086455\n2014-04-06 20:20:00,20.7283931727\n2014-04-06 20:25:00,21.580714659\n2014-04-06 20:30:00,21.5360030417\n2014-04-06 20:35:00,21.1791368299\n2014-04-06 20:40:00,20.2716385546\n2014-04-06 20:45:00,22.080062757199997\n2014-04-06 20:50:00,20.9820812442\n2014-04-06 20:55:00,22.4878527471\n2014-04-06 21:00:00,21.37961112\n2014-04-06 21:05:00,18.2644899487\n2014-04-06 21:10:00,19.3749309839\n2014-04-06 21:15:00,20.3848828298\n2014-04-06 21:20:00,20.9861303153\n2014-04-06 21:25:00,20.2983124022\n2014-04-06 21:30:00,21.246015342\n2014-04-06 21:35:00,19.2224495525\n2014-04-06 21:40:00,18.8255792703\n2014-04-06 21:45:00,18.3031018907\n2014-04-06 21:50:00,20.3906625523\n2014-04-06 21:55:00,20.8540191425\n2014-04-06 22:00:00,19.3231312739\n2014-04-06 22:05:00,20.4739728926\n2014-04-06 22:10:00,18.2261091982\n2014-04-06 22:15:00,18.4148346626\n2014-04-06 22:20:00,20.8269938171\n2014-04-06 22:25:00,19.490972199\n2014-04-06 22:30:00,20.7051940369\n2014-04-06 22:35:00,21.3473582797\n2014-04-06 22:40:00,21.4310438095\n2014-04-06 22:45:00,18.7066116964\n2014-04-06 22:50:00,19.9642896162\n2014-04-06 22:55:00,20.9558051629\n2014-04-06 23:00:00,21.0999728001\n2014-04-06 23:05:00,21.142762552\n2014-04-06 23:10:00,18.9163005682\n2014-04-06 23:15:00,18.7737431358\n2014-04-06 23:20:00,20.3639590007\n2014-04-06 23:25:00,20.968368342799998\n2014-04-06 23:30:00,19.2802591594\n2014-04-06 23:35:00,18.4223570392\n2014-04-06 23:40:00,20.8709919908\n2014-04-06 23:45:00,19.2024774916\n2014-04-06 23:50:00,18.669034662\n2014-04-06 23:55:00,18.594463563399998\n2014-04-07 00:00:00,19.2596381901\n2014-04-07 00:05:00,20.3707122637\n2014-04-07 00:10:00,19.4336089548\n2014-04-07 00:15:00,18.0826474064\n2014-04-07 00:20:00,18.3876337387\n2014-04-07 00:25:00,19.1620129888\n2014-04-07 00:30:00,20.638817928599998\n2014-04-07 00:35:00,18.3940602939\n2014-04-07 00:40:00,20.242627414\n2014-04-07 00:45:00,18.4795434833\n2014-04-07 00:50:00,18.846461309400002\n2014-04-07 00:55:00,18.6887541102\n2014-04-07 01:00:00,18.2689145423\n2014-04-07 01:05:00,20.6853192695\n2014-04-07 01:10:00,19.8536141895\n2014-04-07 01:15:00,21.3242137636\n2014-04-07 01:20:00,18.3955633599\n2014-04-07 01:25:00,18.578931733399997\n2014-04-07 01:30:00,19.2258309254\n2014-04-07 01:35:00,21.0634639478\n2014-04-07 01:40:00,19.2230352926\n2014-04-07 01:45:00,19.63367483\n2014-04-07 01:50:00,19.2064142652\n2014-04-07 01:55:00,18.320897167200002\n2014-04-07 02:00:00,21.757734491599997\n2014-04-07 02:05:00,20.1941559683\n2014-04-07 02:10:00,21.1513327527\n2014-04-07 02:15:00,20.6334283687\n2014-04-07 02:20:00,20.057017116199997\n2014-04-07 02:25:00,18.3587130266\n2014-04-07 02:30:00,20.5709341811\n2014-04-07 02:35:00,18.6214814237\n2014-04-07 02:40:00,19.6575326774\n2014-04-07 02:45:00,20.5164525739\n2014-04-07 02:50:00,21.128916001900002\n2014-04-07 02:55:00,20.7401807028\n2014-04-07 03:00:00,20.686134116199998\n2014-04-07 03:05:00,18.596168836700002\n2014-04-07 03:10:00,19.3845141603\n2014-04-07 03:15:00,18.1716490906\n2014-04-07 03:20:00,20.8779075727\n2014-04-07 03:25:00,21.810343925300003\n2014-04-07 03:30:00,19.056441560699998\n2014-04-07 03:35:00,18.3507868366\n2014-04-07 03:40:00,19.902280307\n2014-04-07 03:45:00,21.4267928925\n2014-04-07 03:50:00,20.2078967811\n2014-04-07 03:55:00,18.1871086008\n2014-04-07 04:00:00,21.8970889621\n2014-04-07 04:05:00,21.3145996399\n2014-04-07 04:10:00,18.5263763082\n2014-04-07 04:15:00,21.687191026\n2014-04-07 04:20:00,19.8027531544\n2014-04-07 04:25:00,19.4875919623\n2014-04-07 04:30:00,19.8442133221\n2014-04-07 04:35:00,21.3382878275\n2014-04-07 04:40:00,20.6379187131\n2014-04-07 04:45:00,18.2369938096\n2014-04-07 04:50:00,21.8304174845\n2014-04-07 04:55:00,18.591136533900002\n2014-04-07 05:00:00,20.982271806900002\n2014-04-07 05:05:00,20.5445461217\n2014-04-07 05:10:00,18.7501121918\n2014-04-07 05:15:00,18.6829283045\n2014-04-07 05:20:00,21.4813103748\n2014-04-07 05:25:00,19.678779694\n2014-04-07 05:30:00,20.6183060567\n2014-04-07 05:35:00,20.0162840154\n2014-04-07 05:40:00,20.9094140683\n2014-04-07 05:45:00,19.9169695002\n2014-04-07 05:50:00,19.149519661\n2014-04-07 05:55:00,19.453533484\n2014-04-07 06:00:00,21.4363107778\n2014-04-07 06:05:00,19.8721387717\n2014-04-07 06:10:00,18.853797329000002\n2014-04-07 06:15:00,21.7384215523\n2014-04-07 06:20:00,21.186401825999997\n2014-04-07 06:25:00,18.2226645842\n2014-04-07 06:30:00,21.9957718479\n2014-04-07 06:35:00,20.7797067858\n2014-04-07 06:40:00,18.6410663962\n2014-04-07 06:45:00,18.9486707252\n2014-04-07 06:50:00,20.769781925\n2014-04-07 06:55:00,21.119044221099998\n2014-04-07 07:00:00,18.9561437726\n2014-04-07 07:05:00,19.0278754156\n2014-04-07 07:10:00,19.228482779500002\n2014-04-07 07:15:00,20.3920734593\n2014-04-07 07:20:00,18.687264713199998\n2014-04-07 07:25:00,18.416972795499998\n2014-04-07 07:30:00,20.715456356300002\n2014-04-07 07:35:00,21.1163917592\n2014-04-07 07:40:00,20.0037176177\n2014-04-07 07:45:00,19.4553308411\n2014-04-07 07:50:00,19.7281708541\n2014-04-07 07:55:00,19.5536313355\n2014-04-07 08:00:00,21.839939633\n2014-04-07 08:05:00,21.0723596209\n2014-04-07 08:10:00,18.8323488594\n2014-04-07 08:15:00,19.5367566082\n2014-04-07 08:20:00,20.1760491655\n2014-04-07 08:25:00,20.4519434483\n2014-04-07 08:30:00,19.872735584100003\n2014-04-07 08:35:00,21.24050654\n2014-04-07 08:40:00,21.0704240778\n2014-04-07 08:45:00,20.0206316745\n2014-04-07 08:50:00,21.4177175471\n2014-04-07 08:55:00,21.0043581218\n2014-04-07 09:00:00,71.7887131426\n2014-04-07 09:05:00,74.2070506003\n2014-04-07 09:10:00,64.8239504004\n2014-04-07 09:15:00,64.8400150082\n2014-04-07 09:20:00,73.2897506774\n2014-04-07 09:25:00,71.702278678\n2014-04-07 09:30:00,73.8010193635\n2014-04-07 09:35:00,62.0585701804\n2014-04-07 09:40:00,69.73749625079999\n2014-04-07 09:45:00,63.166945398500005\n2014-04-07 09:50:00,68.0530018968\n2014-04-07 09:55:00,63.3181582732\n2014-04-07 10:00:00,71.8277784594\n2014-04-07 10:05:00,70.0288527203\n2014-04-07 10:10:00,79.6213063682\n2014-04-07 10:15:00,75.41203101100001\n2014-04-07 10:20:00,71.47252218130002\n2014-04-07 10:25:00,74.8504423104\n2014-04-07 10:30:00,72.4620122993\n2014-04-07 10:35:00,84.4551037849\n2014-04-07 10:40:00,74.806475827\n2014-04-07 10:45:00,75.0229586815\n2014-04-07 10:50:00,82.8745962128\n2014-04-07 10:55:00,79.8931694152\n2014-04-07 11:00:00,82.8625692441\n2014-04-07 11:05:00,81.68297269060001\n2014-04-07 11:10:00,86.6163056999\n2014-04-07 11:15:00,74.86014122510001\n2014-04-07 11:20:00,87.2976801009\n2014-04-07 11:25:00,84.7835270479\n2014-04-07 11:30:00,80.9350200535\n2014-04-07 11:35:00,82.10235831439999\n2014-04-07 11:40:00,81.88692673989999\n2014-04-07 11:45:00,72.4967335474\n2014-04-07 11:50:00,75.03533439270001\n2014-04-07 11:55:00,86.8592329475\n2014-04-07 12:00:00,80.4531710647\n2014-04-07 12:05:00,77.959993263\n2014-04-07 12:10:00,84.0915842757\n2014-04-07 12:15:00,80.2958323188\n2014-04-07 12:20:00,72.1239516177\n2014-04-07 12:25:00,83.67926578560001\n2014-04-07 12:30:00,83.6150223837\n2014-04-07 12:35:00,74.5528085385\n2014-04-07 12:40:00,87.2017935411\n2014-04-07 12:45:00,75.4918310685\n2014-04-07 12:50:00,79.2288010903\n2014-04-07 12:55:00,73.7471724497\n2014-04-07 13:00:00,81.6329205071\n2014-04-07 13:05:00,77.9884961886\n2014-04-07 13:10:00,77.63213920930001\n2014-04-07 13:15:00,85.2111744443\n2014-04-07 13:20:00,72.1356706886\n2014-04-07 13:25:00,84.74680421869998\n2014-04-07 13:30:00,81.12370268949999\n2014-04-07 13:35:00,87.7565095974\n2014-04-07 13:40:00,81.41154806770001\n2014-04-07 13:45:00,72.8685734905\n2014-04-07 13:50:00,72.792850745\n2014-04-07 13:55:00,86.10977647450001\n2014-04-07 14:00:00,85.4553242757\n2014-04-07 14:05:00,77.53051956569999\n2014-04-07 14:10:00,81.884589098\n2014-04-07 14:15:00,79.8296297067\n2014-04-07 14:20:00,87.4704261002\n2014-04-07 14:25:00,87.1951888441\n2014-04-07 14:30:00,87.7372125483\n2014-04-07 14:35:00,85.8590590575\n2014-04-07 14:40:00,86.5486709168\n2014-04-07 14:45:00,75.4728375902\n2014-04-07 14:50:00,85.2920144106\n2014-04-07 14:55:00,83.337713409\n2014-04-07 15:00:00,87.4037450572\n2014-04-07 15:05:00,81.1394103093\n2014-04-07 15:10:00,73.36197038569999\n2014-04-07 15:15:00,81.55759929850001\n2014-04-07 15:20:00,82.9844981895\n2014-04-07 15:25:00,75.5244114181\n2014-04-07 15:30:00,78.3050624004\n2014-04-07 15:35:00,81.5752714947\n2014-04-07 15:40:00,77.9849431344\n2014-04-07 15:45:00,77.99841468380002\n2014-04-07 15:50:00,74.12867458470001\n2014-04-07 15:55:00,87.0511118705\n2014-04-07 16:00:00,84.0077488567\n2014-04-07 16:05:00,72.0197567437\n2014-04-07 16:10:00,84.24965078470001\n2014-04-07 16:15:00,83.836558916\n2014-04-07 16:20:00,72.1555568236\n2014-04-07 16:25:00,77.9135191676\n2014-04-07 16:30:00,81.7078061659\n2014-04-07 16:35:00,79.2438582812\n2014-04-07 16:40:00,84.4476157598\n2014-04-07 16:45:00,78.8071820121\n2014-04-07 16:50:00,74.4616645446\n2014-04-07 16:55:00,87.62248175290001\n2014-04-07 17:00:00,75.87261074930001\n2014-04-07 17:05:00,83.4830449112\n2014-04-07 17:10:00,74.2904724591\n2014-04-07 17:15:00,77.2641721511\n2014-04-07 17:20:00,79.0724113711\n2014-04-07 17:25:00,75.07568324340001\n2014-04-07 17:30:00,79.1993228093\n2014-04-07 17:35:00,74.5145765543\n2014-04-07 17:40:00,80.9440735412\n2014-04-07 17:45:00,82.61938031449999\n2014-04-07 17:50:00,72.9989205129\n2014-04-07 17:55:00,85.9380809371\n2014-04-07 18:00:00,29.9848959072\n2014-04-07 18:05:00,30.242313715500003\n2014-04-07 18:10:00,33.0326326343\n2014-04-07 18:15:00,31.8000006812\n2014-04-07 18:20:00,31.9961256914\n2014-04-07 18:25:00,29.6201862141\n2014-04-07 18:30:00,33.9567027403\n2014-04-07 18:35:00,32.7491408872\n2014-04-07 18:40:00,29.6664393812\n2014-04-07 18:45:00,31.1935899598\n2014-04-07 18:50:00,33.9866170441\n2014-04-07 18:55:00,32.437466066300004\n2014-04-07 19:00:00,20.6467453979\n2014-04-07 19:05:00,21.8300399676\n2014-04-07 19:10:00,21.247269739500002\n2014-04-07 19:15:00,22.4782444473\n2014-04-07 19:20:00,23.9382565442\n2014-04-07 19:25:00,22.114475550799998\n2014-04-07 19:30:00,22.1013710836\n2014-04-07 19:35:00,24.215970714\n2014-04-07 19:40:00,22.7413094005\n2014-04-07 19:45:00,22.696534826500002\n2014-04-07 19:50:00,21.3333551453\n2014-04-07 19:55:00,22.882596655\n2014-04-07 20:00:00,20.7909290251\n2014-04-07 20:05:00,20.0575033818\n2014-04-07 20:10:00,22.489888768\n2014-04-07 20:15:00,22.0442251279\n2014-04-07 20:20:00,21.502305186100006\n2014-04-07 20:25:00,20.6329672825\n2014-04-07 20:30:00,20.3245967047\n2014-04-07 20:35:00,19.1893395006\n2014-04-07 20:40:00,19.6843004574\n2014-04-07 20:45:00,21.6021431769\n2014-04-07 20:50:00,20.2905554718\n2014-04-07 20:55:00,22.045775675300003\n2014-04-07 21:00:00,18.680884393499998\n2014-04-07 21:05:00,20.1295485991\n2014-04-07 21:10:00,20.6866844266\n2014-04-07 21:15:00,20.1637172663\n2014-04-07 21:20:00,21.660380669699997\n2014-04-07 21:25:00,22.0636526884\n2014-04-07 21:30:00,18.5519626134\n2014-04-07 21:35:00,18.608714705\n2014-04-07 21:40:00,18.6101986317\n2014-04-07 21:45:00,20.8241869336\n2014-04-07 21:50:00,19.5842597151\n2014-04-07 21:55:00,21.0337382351\n2014-04-07 22:00:00,19.6407228924\n2014-04-07 22:05:00,20.5301168851\n2014-04-07 22:10:00,21.0996682671\n2014-04-07 22:15:00,20.2122487818\n2014-04-07 22:20:00,20.177366045699998\n2014-04-07 22:25:00,18.3705561119\n2014-04-07 22:30:00,19.6619843639\n2014-04-07 22:35:00,20.202484387200002\n2014-04-07 22:40:00,19.8669772993\n2014-04-07 22:45:00,21.623866993000004\n2014-04-07 22:50:00,21.6468835955\n2014-04-07 22:55:00,21.3081056746\n2014-04-07 23:00:00,19.5049365285\n2014-04-07 23:05:00,20.873203490399998\n2014-04-07 23:10:00,19.5849134239\n2014-04-07 23:15:00,18.9340090259\n2014-04-07 23:20:00,19.3753299215\n2014-04-07 23:25:00,18.2873690322\n2014-04-07 23:30:00,19.3308208392\n2014-04-07 23:35:00,19.8467787171\n2014-04-07 23:40:00,21.8261133863\n2014-04-07 23:45:00,19.2573390423\n2014-04-07 23:50:00,21.613963239\n2014-04-07 23:55:00,18.9190648646\n2014-04-08 00:00:00,18.763875590999998\n2014-04-08 00:05:00,20.075981825699998\n2014-04-08 00:10:00,20.6900454772\n2014-04-08 00:15:00,18.1773290032\n2014-04-08 00:20:00,18.8842634602\n2014-04-08 00:25:00,19.822734666\n2014-04-08 00:30:00,19.3240173439\n2014-04-08 00:35:00,20.8504843174\n2014-04-08 00:40:00,20.0446423842\n2014-04-08 00:45:00,18.6414364224\n2014-04-08 00:50:00,21.5778615173\n2014-04-08 00:55:00,19.171622701900002\n2014-04-08 01:00:00,20.9245244359\n2014-04-08 01:05:00,21.1196631164\n2014-04-08 01:10:00,21.852630801\n2014-04-08 01:15:00,19.9940298661\n2014-04-08 01:20:00,20.4633420619\n2014-04-08 01:25:00,19.3395051739\n2014-04-08 01:30:00,20.712717173599998\n2014-04-08 01:35:00,19.8535339435\n2014-04-08 01:40:00,19.7506094589\n2014-04-08 01:45:00,21.421870116500003\n2014-04-08 01:50:00,18.200675374\n2014-04-08 01:55:00,21.5278497113\n2014-04-08 02:00:00,21.408279351300003\n2014-04-08 02:05:00,20.0254650142\n2014-04-08 02:10:00,19.960811416800002\n2014-04-08 02:15:00,19.447229472100002\n2014-04-08 02:20:00,21.9766951667\n2014-04-08 02:25:00,18.444677330999998\n2014-04-08 02:30:00,20.3608609425\n2014-04-08 02:35:00,20.7267263604\n2014-04-08 02:40:00,21.7373200329\n2014-04-08 02:45:00,21.120813987400002\n2014-04-08 02:50:00,20.5753888112\n2014-04-08 02:55:00,18.4672492672\n2014-04-08 03:00:00,19.4949340673\n2014-04-08 03:05:00,18.5553665702\n2014-04-08 03:10:00,21.524850929899998\n2014-04-08 03:15:00,20.9984846223\n2014-04-08 03:20:00,21.0301471472\n2014-04-08 03:25:00,20.6090260711\n2014-04-08 03:30:00,20.0281741477\n2014-04-08 03:35:00,18.5998842379\n2014-04-08 03:40:00,19.318779546800002\n2014-04-08 03:45:00,18.5476631699\n2014-04-08 03:50:00,20.8996525714\n2014-04-08 03:55:00,18.6409151041\n2014-04-08 04:00:00,20.808454200699998\n2014-04-08 04:05:00,20.7690215584\n2014-04-08 04:10:00,19.837217916\n2014-04-08 04:15:00,18.5409146165\n2014-04-08 04:20:00,19.2592033045\n2014-04-08 04:25:00,19.280372436300002\n2014-04-08 04:30:00,20.8015405326\n2014-04-08 04:35:00,18.4549720777\n2014-04-08 04:40:00,21.3162745849\n2014-04-08 04:45:00,21.0440291607\n2014-04-08 04:50:00,18.7452276727\n2014-04-08 04:55:00,20.8766575271\n2014-04-08 05:00:00,20.674052725899998\n2014-04-08 05:05:00,20.9924832004\n2014-04-08 05:10:00,18.7557142218\n2014-04-08 05:15:00,18.6303612886\n2014-04-08 05:20:00,18.9459359437\n2014-04-08 05:25:00,19.4634868126\n2014-04-08 05:30:00,21.174659924100002\n2014-04-08 05:35:00,20.9516957499\n2014-04-08 05:40:00,21.701806369099998\n2014-04-08 05:45:00,18.2345182364\n2014-04-08 05:50:00,18.0462251241\n2014-04-08 05:55:00,20.7965553188\n2014-04-08 06:00:00,19.1171499832\n2014-04-08 06:05:00,19.3363155821\n2014-04-08 06:10:00,20.187208103699998\n2014-04-08 06:15:00,18.4096524925\n2014-04-08 06:20:00,20.570777666199998\n2014-04-08 06:25:00,19.3005897849\n2014-04-08 06:30:00,20.5308604972\n2014-04-08 06:35:00,21.3360276523\n2014-04-08 06:40:00,18.684445333299998\n2014-04-08 06:45:00,21.7234923717\n2014-04-08 06:50:00,20.122752564200002\n2014-04-08 06:55:00,21.6917110607\n2014-04-08 07:00:00,18.8309203288\n2014-04-08 07:05:00,20.418250658399998\n2014-04-08 07:10:00,19.615548469300002\n2014-04-08 07:15:00,21.0968887646\n2014-04-08 07:20:00,20.4236357729\n2014-04-08 07:25:00,19.9780618278\n2014-04-08 07:30:00,21.6519416257\n2014-04-08 07:35:00,19.508468256700002\n2014-04-08 07:40:00,18.8799208196\n2014-04-08 07:45:00,20.4324047474\n2014-04-08 07:50:00,20.496113748699997\n2014-04-08 07:55:00,19.7563784863\n2014-04-08 08:00:00,19.9464401748\n2014-04-08 08:05:00,21.838213657199997\n2014-04-08 08:10:00,20.930742765599998\n2014-04-08 08:15:00,18.442407005899998\n2014-04-08 08:20:00,18.848520283499997\n2014-04-08 08:25:00,21.9023065377\n2014-04-08 08:30:00,20.9058622152\n2014-04-08 08:35:00,21.6601805046\n2014-04-08 08:40:00,19.215445856\n2014-04-08 08:45:00,20.9674674403\n2014-04-08 08:50:00,20.8560108341\n2014-04-08 08:55:00,19.1787599418\n2014-04-08 09:00:00,68.6911020261\n2014-04-08 09:05:00,69.7328455133\n2014-04-08 09:10:00,67.7433926273\n2014-04-08 09:15:00,72.4496304105\n2014-04-08 09:20:00,72.5270189685\n2014-04-08 09:25:00,72.7681674569\n2014-04-08 09:30:00,72.12656053970001\n2014-04-08 09:35:00,67.8379352899\n2014-04-08 09:40:00,66.3875608548\n2014-04-08 09:45:00,72.5067174585\n2014-04-08 09:50:00,67.8667398364\n2014-04-08 09:55:00,64.5506510213\n2014-04-08 10:00:00,77.7139716216\n2014-04-08 10:05:00,72.0415092362\n2014-04-08 10:10:00,80.5740896941\n2014-04-08 10:15:00,75.0534982908\n2014-04-08 10:20:00,73.8854245519\n2014-04-08 10:25:00,84.6850157416\n2014-04-08 10:30:00,81.8971930542\n2014-04-08 10:35:00,82.0553186823\n2014-04-08 10:40:00,79.5201649632\n2014-04-08 10:45:00,82.8639620191\n2014-04-08 10:50:00,81.6222017077\n2014-04-08 10:55:00,79.1329678882\n2014-04-08 11:00:00,86.85372248700001\n2014-04-08 11:05:00,74.61512607979999\n2014-04-08 11:10:00,86.5715110509\n2014-04-08 11:15:00,77.95247252840001\n2014-04-08 11:20:00,79.971657432\n2014-04-08 11:25:00,73.520046138\n2014-04-08 11:30:00,80.15786870859999\n2014-04-08 11:35:00,81.2886321816\n2014-04-08 11:40:00,87.4354453209\n2014-04-08 11:45:00,87.0774601057\n2014-04-08 11:50:00,86.93758253\n2014-04-08 11:55:00,77.1087637079\n2014-04-08 12:00:00,87.75483166309998\n2014-04-08 12:05:00,79.192505245\n2014-04-08 12:10:00,85.526624884\n2014-04-08 12:15:00,75.3705661609\n2014-04-08 12:20:00,79.9972188775\n2014-04-08 12:25:00,87.3512461058\n2014-04-08 12:30:00,87.047919348\n2014-04-08 12:35:00,82.8402303355\n2014-04-08 12:40:00,84.6633111259\n2014-04-08 12:45:00,74.7330397531\n2014-04-08 12:50:00,83.4462809476\n2014-04-08 12:55:00,81.7905463578\n2014-04-08 13:00:00,73.4471962134\n2014-04-08 13:05:00,73.7928295748\n2014-04-08 13:10:00,73.7174014605\n2014-04-08 13:15:00,83.5696494266\n2014-04-08 13:20:00,74.24961914560001\n2014-04-08 13:25:00,79.4646402459\n2014-04-08 13:30:00,77.6930580839\n2014-04-08 13:35:00,80.78867231640001\n2014-04-08 13:40:00,83.2836309258\n2014-04-08 13:45:00,82.935651261\n2014-04-08 13:50:00,80.2290590582\n2014-04-08 13:55:00,79.4102949319\n2014-04-08 14:00:00,78.3612879996\n2014-04-08 14:05:00,85.78644122600001\n2014-04-08 14:10:00,77.2899187838\n2014-04-08 14:15:00,76.1461979457\n2014-04-08 14:20:00,83.8890210322\n2014-04-08 14:25:00,77.7524830888\n2014-04-08 14:30:00,85.5478711012\n2014-04-08 14:35:00,77.2425116797\n2014-04-08 14:40:00,83.2271220996\n2014-04-08 14:45:00,72.7182534568\n2014-04-08 14:50:00,78.1652539695\n2014-04-08 14:55:00,77.4879631987\n2014-04-08 15:00:00,85.0660431866\n2014-04-08 15:05:00,87.4720467119\n2014-04-08 15:10:00,79.37333843569999\n2014-04-08 15:15:00,85.1965625396\n2014-04-08 15:20:00,83.1943165422\n2014-04-08 15:25:00,87.4773360121\n2014-04-08 15:30:00,84.9769204432\n2014-04-08 15:35:00,73.2389459548\n2014-04-08 15:40:00,83.411706798\n2014-04-08 15:45:00,80.567221994\n2014-04-08 15:50:00,72.2622832023\n2014-04-08 15:55:00,76.0202775379\n2014-04-08 16:00:00,86.7479173641\n2014-04-08 16:05:00,86.816815276\n2014-04-08 16:10:00,84.7814445825\n2014-04-08 16:15:00,87.70830525219999\n2014-04-08 16:20:00,84.9045605769\n2014-04-08 16:25:00,72.1631284431\n2014-04-08 16:30:00,76.6052023626\n2014-04-08 16:35:00,72.489847735\n2014-04-08 16:40:00,73.5055863688\n2014-04-08 16:45:00,75.5013081084\n2014-04-08 16:50:00,80.0567830319\n2014-04-08 16:55:00,85.5603477792\n2014-04-08 17:00:00,85.7914351546\n2014-04-08 17:05:00,81.859198303\n2014-04-08 17:10:00,86.85078167430002\n2014-04-08 17:15:00,80.0009665051\n2014-04-08 17:20:00,86.2245435959\n2014-04-08 17:25:00,79.2650136635\n2014-04-08 17:30:00,76.4355707675\n2014-04-08 17:35:00,86.66257341120001\n2014-04-08 17:40:00,78.2069311794\n2014-04-08 17:45:00,80.05443500060001\n2014-04-08 17:50:00,77.261740452\n2014-04-08 17:55:00,82.6053698842\n2014-04-08 18:00:00,35.1681930877\n2014-04-08 18:05:00,28.963281151799997\n2014-04-08 18:10:00,34.5590206031\n2014-04-08 18:15:00,28.825121230300002\n2014-04-08 18:20:00,31.1310524622\n2014-04-08 18:25:00,29.879077823499998\n2014-04-08 18:30:00,33.6469809361\n2014-04-08 18:35:00,29.123903789099998\n2014-04-08 18:40:00,32.3422974932\n2014-04-08 18:45:00,30.687521364600002\n2014-04-08 18:50:00,29.6554838989\n2014-04-08 18:55:00,33.7396300794\n2014-04-08 19:00:00,21.1340262581\n2014-04-08 19:05:00,21.1620637891\n2014-04-08 19:10:00,21.3923428239\n2014-04-08 19:15:00,22.788713851799997\n2014-04-08 19:20:00,23.115302105900003\n2014-04-08 19:25:00,20.2388581959\n2014-04-08 19:30:00,21.2435748044\n2014-04-08 19:35:00,22.0907481626\n2014-04-08 19:40:00,21.6472555582\n2014-04-08 19:45:00,24.1210832269\n2014-04-08 19:50:00,23.688933814899997\n2014-04-08 19:55:00,22.9639869059\n2014-04-08 20:00:00,19.816621498099998\n2014-04-08 20:05:00,21.3019536689\n2014-04-08 20:10:00,21.887541038000002\n2014-04-08 20:15:00,20.8684249752\n2014-04-08 20:20:00,21.6451539087\n2014-04-08 20:25:00,21.500333663899998\n2014-04-08 20:30:00,20.7738357772\n2014-04-08 20:35:00,19.7107022196\n2014-04-08 20:40:00,21.486723461300002\n2014-04-08 20:45:00,19.2790376853\n2014-04-08 20:50:00,21.6247840077\n2014-04-08 20:55:00,21.727422990300003\n2014-04-08 21:00:00,21.3907646477\n2014-04-08 21:05:00,19.987143821700002\n2014-04-08 21:10:00,18.8600186557\n2014-04-08 21:15:00,18.4872090482\n2014-04-08 21:20:00,21.074117486400002\n2014-04-08 21:25:00,21.648461703800002\n2014-04-08 21:30:00,20.7022494812\n2014-04-08 21:35:00,18.665808069100002\n2014-04-08 21:40:00,21.8439357525\n2014-04-08 21:45:00,22.0617987629\n2014-04-08 21:50:00,19.8282352606\n2014-04-08 21:55:00,20.4771217526\n2014-04-08 22:00:00,21.1291786271\n2014-04-08 22:05:00,20.9656668867\n2014-04-08 22:10:00,21.8921450598\n2014-04-08 22:15:00,18.477253506300002\n2014-04-08 22:20:00,20.3424094381\n2014-04-08 22:25:00,20.7876626851\n2014-04-08 22:30:00,21.581091664099997\n2014-04-08 22:35:00,21.5170750813\n2014-04-08 22:40:00,21.9330346827\n2014-04-08 22:45:00,20.0675601872\n2014-04-08 22:50:00,21.343513578499998\n2014-04-08 22:55:00,19.7280475846\n2014-04-08 23:00:00,19.693035846500003\n2014-04-08 23:05:00,19.0170440276\n2014-04-08 23:10:00,21.2770335522\n2014-04-08 23:15:00,21.9474735271\n2014-04-08 23:20:00,19.029019782\n2014-04-08 23:25:00,18.2280254594\n2014-04-08 23:30:00,21.2662520842\n2014-04-08 23:35:00,20.4848525448\n2014-04-08 23:40:00,21.8429882487\n2014-04-08 23:45:00,19.0126065942\n2014-04-08 23:50:00,18.287621179400002\n2014-04-08 23:55:00,19.9736032372\n2014-04-09 00:00:00,18.3418640919\n2014-04-09 00:05:00,19.047160004400002\n2014-04-09 00:10:00,18.503911443299998\n2014-04-09 00:15:00,18.8965287186\n2014-04-09 00:20:00,18.4245786113\n2014-04-09 00:25:00,21.8156239977\n2014-04-09 00:30:00,19.1142508538\n2014-04-09 00:35:00,19.775590344\n2014-04-09 00:40:00,21.594447230500002\n2014-04-09 00:45:00,20.7092863518\n2014-04-09 00:50:00,20.4721499222\n2014-04-09 00:55:00,20.8222527614\n2014-04-09 01:00:00,21.3152890284\n2014-04-09 01:05:00,21.5106770714\n2014-04-09 01:10:00,20.5705586827\n2014-04-09 01:15:00,21.5600290988\n2014-04-09 01:20:00,20.1415901097\n2014-04-09 01:25:00,19.1091634251\n2014-04-09 01:30:00,21.5203068355\n2014-04-09 01:35:00,20.1658913097\n2014-04-09 01:40:00,21.6245503503\n2014-04-09 01:45:00,18.1606712558\n2014-04-09 01:50:00,19.590063006199998\n2014-04-09 01:55:00,21.7912200734\n2014-04-09 02:00:00,18.998600371\n2014-04-09 02:05:00,21.7661449842\n2014-04-09 02:10:00,21.8156098445\n2014-04-09 02:15:00,21.5285692569\n2014-04-09 02:20:00,20.2546721804\n2014-04-09 02:25:00,20.5877577963\n2014-04-09 02:30:00,21.478467993800002\n2014-04-09 02:35:00,21.1035883296\n2014-04-09 02:40:00,20.5203753978\n2014-04-09 02:45:00,21.9290376315\n2014-04-09 02:50:00,20.7427065453\n2014-04-09 02:55:00,21.9019279698\n2014-04-09 03:00:00,18.2295538984\n2014-04-09 03:05:00,18.555841483\n2014-04-09 03:10:00,19.805835384\n2014-04-09 03:15:00,19.5395178435\n2014-04-09 03:20:00,21.1309393654\n2014-04-09 03:25:00,18.6424561059\n2014-04-09 03:30:00,21.9043807164\n2014-04-09 03:35:00,19.260263501\n2014-04-09 03:40:00,19.715694831\n2014-04-09 03:45:00,19.0989801298\n2014-04-09 03:50:00,20.3174544693\n2014-04-09 03:55:00,18.2345148017\n2014-04-09 04:00:00,18.5987100223\n2014-04-09 04:05:00,20.9831908137\n2014-04-09 04:10:00,18.7460023336\n2014-04-09 04:15:00,18.942057806199998\n2014-04-09 04:20:00,21.1719289429\n2014-04-09 04:25:00,18.3732047134\n2014-04-09 04:30:00,19.7498952911\n2014-04-09 04:35:00,18.092253548\n2014-04-09 04:40:00,19.3872295973\n2014-04-09 04:45:00,20.7959256104\n2014-04-09 04:50:00,18.360413118900002\n2014-04-09 04:55:00,21.5533385071\n2014-04-09 05:00:00,21.637996171799998\n2014-04-09 05:05:00,18.4199615005\n2014-04-09 05:10:00,21.962929745500002\n2014-04-09 05:15:00,19.190118213599998\n2014-04-09 05:20:00,18.3364066845\n2014-04-09 05:25:00,18.020268458\n2014-04-09 05:30:00,19.6340915831\n2014-04-09 05:35:00,20.5192399428\n2014-04-09 05:40:00,19.3287169996\n2014-04-09 05:45:00,21.3468694619\n2014-04-09 05:50:00,20.8664251023\n2014-04-09 05:55:00,19.4006461279\n2014-04-09 06:00:00,20.937238666400003\n2014-04-09 06:05:00,21.7619509479\n2014-04-09 06:10:00,18.3723839942\n2014-04-09 06:15:00,19.2244158406\n2014-04-09 06:20:00,19.8533037565\n2014-04-09 06:25:00,19.991960511\n2014-04-09 06:30:00,20.1687825795\n2014-04-09 06:35:00,19.2025076262\n2014-04-09 06:40:00,20.6690385839\n2014-04-09 06:45:00,20.5803380141\n2014-04-09 06:50:00,20.3112860251\n2014-04-09 06:55:00,18.4550468868\n2014-04-09 07:00:00,19.9078715644\n2014-04-09 07:05:00,19.42490755\n2014-04-09 07:10:00,19.9641538794\n2014-04-09 07:15:00,21.6874657421\n2014-04-09 07:20:00,19.9221253726\n2014-04-09 07:25:00,18.0559231674\n2014-04-09 07:30:00,19.755346952300002\n2014-04-09 07:35:00,21.2825927202\n2014-04-09 07:40:00,21.1202436929\n2014-04-09 07:45:00,20.053560294100002\n2014-04-09 07:50:00,18.9990760514\n2014-04-09 07:55:00,19.8603546517\n2014-04-09 08:00:00,20.2548088777\n2014-04-09 08:05:00,21.9994857531\n2014-04-09 08:10:00,20.5767123607\n2014-04-09 08:15:00,20.7770597203\n2014-04-09 08:20:00,19.9658165743\n2014-04-09 08:25:00,19.4179582031\n2014-04-09 08:30:00,21.2518119346\n2014-04-09 08:35:00,19.9797292974\n2014-04-09 08:40:00,21.978760519899996\n2014-04-09 08:45:00,19.8284822971\n2014-04-09 08:50:00,18.2720011346\n2014-04-09 08:55:00,20.7303125484\n2014-04-09 09:00:00,61.83432373260001\n2014-04-09 09:05:00,64.6068217176\n2014-04-09 09:10:00,66.0108402378\n2014-04-09 09:15:00,71.2569767645\n2014-04-09 09:20:00,67.9216085991\n2014-04-09 09:25:00,61.5895846658\n2014-04-09 09:30:00,69.58915797739999\n2014-04-09 09:35:00,66.795532829\n2014-04-09 09:40:00,73.7369493356\n2014-04-09 09:45:00,67.9940474315\n2014-04-09 09:50:00,70.8420619848\n2014-04-09 09:55:00,64.1766114957\n2014-04-09 10:00:00,81.6503097215\n2014-04-09 10:05:00,81.0292264187\n2014-04-09 10:10:00,83.8713481166\n2014-04-09 10:15:00,70.3649118795\n2014-04-09 10:20:00,76.785210827\n2014-04-09 10:25:00,80.38049185050001\n2014-04-09 10:30:00,71.3169437292\n2014-04-09 10:35:00,76.21257512220001\n2014-04-09 10:40:00,84.4621152796\n2014-04-09 10:45:00,76.60570329859999\n2014-04-09 10:50:00,85.1334822396\n2014-04-09 10:55:00,70.722142228\n2014-04-09 11:00:00,82.9843647597\n2014-04-09 11:05:00,80.8084822213\n2014-04-09 11:10:00,79.5285830251\n2014-04-09 11:15:00,87.0083570732\n2014-04-09 11:20:00,73.62995996939999\n2014-04-09 11:25:00,85.8179673275\n2014-04-09 11:30:00,82.5614874987\n2014-04-09 11:35:00,75.68707354979999\n2014-04-09 11:40:00,85.9081460921\n2014-04-09 11:45:00,78.3955063737\n2014-04-09 11:50:00,84.5174714257\n2014-04-09 11:55:00,77.7520559671\n2014-04-09 12:00:00,85.51215536699999\n2014-04-09 12:05:00,82.087442616\n2014-04-09 12:10:00,74.167638042\n2014-04-09 12:15:00,82.2957370828\n2014-04-09 12:20:00,74.9714423838\n2014-04-09 12:25:00,78.4964531319\n2014-04-09 12:30:00,74.6350596728\n2014-04-09 12:35:00,72.2654351413\n2014-04-09 12:40:00,75.2997164096\n2014-04-09 12:45:00,80.4852540367\n2014-04-09 12:50:00,79.60932951390001\n2014-04-09 12:55:00,79.9279247843\n2014-04-09 13:00:00,75.9447589375\n2014-04-09 13:05:00,82.9426681908\n2014-04-09 13:10:00,83.24822821810001\n2014-04-09 13:15:00,77.7088306125\n2014-04-09 13:20:00,86.0780577224\n2014-04-09 13:25:00,82.284618417\n2014-04-09 13:30:00,83.3886103333\n2014-04-09 13:35:00,76.4190937017\n2014-04-09 13:40:00,71.9925038138\n2014-04-09 13:45:00,85.82540675130002\n2014-04-09 13:50:00,85.1383520436\n2014-04-09 13:55:00,73.95331715180001\n2014-04-09 14:00:00,77.9819388466\n2014-04-09 14:05:00,82.5774650256\n2014-04-09 14:10:00,82.42981689439999\n2014-04-09 14:15:00,85.7614886079\n2014-04-09 14:20:00,74.2407268602\n2014-04-09 14:25:00,78.8752497708\n2014-04-09 14:30:00,73.5520600185\n2014-04-09 14:35:00,78.2297687659\n2014-04-09 14:40:00,72.2382515269\n2014-04-09 14:45:00,86.36822316799999\n2014-04-09 14:50:00,80.42884317949999\n2014-04-09 14:55:00,85.59272752470001\n2014-04-09 15:00:00,72.9577748147\n2014-04-09 15:05:00,75.63860363\n2014-04-09 15:10:00,76.1493488828\n2014-04-09 15:15:00,78.1863133184\n2014-04-09 15:20:00,84.84504743810001\n2014-04-09 15:25:00,78.1841754044\n2014-04-09 15:30:00,75.2737338396\n2014-04-09 15:35:00,73.0391429829\n2014-04-09 15:40:00,73.2711645637\n2014-04-09 15:45:00,84.1599473521\n2014-04-09 15:50:00,79.1160883348\n2014-04-09 15:55:00,83.6180952106\n2014-04-09 16:00:00,82.91643474840001\n2014-04-09 16:05:00,74.1656569898\n2014-04-09 16:10:00,74.28606431760001\n2014-04-09 16:15:00,84.0853108028\n2014-04-09 16:20:00,83.5401322984\n2014-04-09 16:25:00,78.0483424169\n2014-04-09 16:30:00,73.2386155949\n2014-04-09 16:35:00,72.1934297355\n2014-04-09 16:40:00,76.6103640992\n2014-04-09 16:45:00,72.1474178541\n2014-04-09 16:50:00,75.6810166298\n2014-04-09 16:55:00,78.7118607163\n2014-04-09 17:00:00,73.94262385100001\n2014-04-09 17:05:00,73.6684158366\n2014-04-09 17:10:00,86.3429658158\n2014-04-09 17:15:00,81.3674892192\n2014-04-09 17:20:00,86.9512575989\n2014-04-09 17:25:00,77.53318884779999\n2014-04-09 17:30:00,82.8342871889\n2014-04-09 17:35:00,75.2750378883\n2014-04-09 17:40:00,81.8934136294\n2014-04-09 17:45:00,74.073343236\n2014-04-09 17:50:00,72.033262566\n2014-04-09 17:55:00,86.90447545120001\n2014-04-09 18:00:00,32.3513177961\n2014-04-09 18:05:00,34.7324135732\n2014-04-09 18:10:00,30.9365158119\n2014-04-09 18:15:00,30.897824910300002\n2014-04-09 18:20:00,31.3641859894\n2014-04-09 18:25:00,33.318655900100005\n2014-04-09 18:30:00,32.4211690339\n2014-04-09 18:35:00,34.7222647388\n2014-04-09 18:40:00,28.9628162064\n2014-04-09 18:45:00,33.3324476032\n2014-04-09 18:50:00,30.914091276399997\n2014-04-09 18:55:00,29.9534896206\n2014-04-09 19:00:00,22.4465711575\n2014-04-09 19:05:00,22.4226845231\n2014-04-09 19:10:00,20.7738082689\n2014-04-09 19:15:00,21.064493175899997\n2014-04-09 19:20:00,21.9885764925\n2014-04-09 19:25:00,21.991473921100006\n2014-04-09 19:30:00,21.5826592815\n2014-04-09 19:35:00,20.825481136300002\n2014-04-09 19:40:00,20.1795929754\n2014-04-09 19:45:00,24.506651735300004\n2014-04-09 19:50:00,24.3868752113\n2014-04-09 19:55:00,22.326752473899997\n2014-04-09 20:00:00,22.5077317113\n2014-04-09 20:05:00,21.1912878846\n2014-04-09 20:10:00,18.714040249500002\n2014-04-09 20:15:00,18.9141735165\n2014-04-09 20:20:00,22.184389750300003\n2014-04-09 20:25:00,21.0126935679\n2014-04-09 20:30:00,21.885679872199997\n2014-04-09 20:35:00,22.111312219600002\n2014-04-09 20:40:00,20.266770235\n2014-04-09 20:45:00,18.6307620741\n2014-04-09 20:50:00,19.203196078599998\n2014-04-09 20:55:00,18.7046784717\n2014-04-09 21:00:00,18.844983141700002\n2014-04-09 21:05:00,19.7364138897\n2014-04-09 21:10:00,18.5614565754\n2014-04-09 21:15:00,18.756534223699997\n2014-04-09 21:20:00,19.8782468579\n2014-04-09 21:25:00,19.4536150362\n2014-04-09 21:30:00,19.9660114839\n2014-04-09 21:35:00,19.8113281655\n2014-04-09 21:40:00,20.676686031400003\n2014-04-09 21:45:00,21.8531521814\n2014-04-09 21:50:00,18.5199283038\n2014-04-09 21:55:00,18.485346346900002\n2014-04-09 22:00:00,21.4317792093\n2014-04-09 22:05:00,20.0448113721\n2014-04-09 22:10:00,21.0858430792\n2014-04-09 22:15:00,18.8797948253\n2014-04-09 22:20:00,21.335913114500002\n2014-04-09 22:25:00,21.7162140571\n2014-04-09 22:30:00,20.5616523069\n2014-04-09 22:35:00,18.4412026523\n2014-04-09 22:40:00,21.6018971781\n2014-04-09 22:45:00,21.1902740519\n2014-04-09 22:50:00,21.023674466400003\n2014-04-09 22:55:00,18.1643337829\n2014-04-09 23:00:00,21.1999197022\n2014-04-09 23:05:00,18.555365986400002\n2014-04-09 23:10:00,18.8931714955\n2014-04-09 23:15:00,20.312438577\n2014-04-09 23:20:00,19.063582595\n2014-04-09 23:25:00,20.649356738599998\n2014-04-09 23:30:00,20.4362047869\n2014-04-09 23:35:00,18.436137449100002\n2014-04-09 23:40:00,20.6280181355\n2014-04-09 23:45:00,21.699985234499998\n2014-04-09 23:50:00,18.6480193513\n2014-04-09 23:55:00,20.3921626254\n2014-04-10 00:00:00,19.367461487699998\n2014-04-10 00:05:00,19.8384466871\n2014-04-10 00:10:00,19.1480007163\n2014-04-10 00:15:00,19.4165225454\n2014-04-10 00:20:00,18.1156472931\n2014-04-10 00:25:00,21.9262069517\n2014-04-10 00:30:00,20.4991996883\n2014-04-10 00:35:00,20.002822362\n2014-04-10 00:40:00,19.534861398\n2014-04-10 00:45:00,20.1574982353\n2014-04-10 00:50:00,19.5204239949\n2014-04-10 00:55:00,19.43963171\n2014-04-10 01:00:00,19.8557861669\n2014-04-10 01:05:00,19.1039321347\n2014-04-10 01:10:00,18.7201995999\n2014-04-10 01:15:00,20.2264235927\n2014-04-10 01:20:00,21.3710617446\n2014-04-10 01:25:00,18.6113127109\n2014-04-10 01:30:00,18.1309373624\n2014-04-10 01:35:00,18.9872469806\n2014-04-10 01:40:00,21.9188825738\n2014-04-10 01:45:00,21.315032295\n2014-04-10 01:50:00,20.3834642141\n2014-04-10 01:55:00,21.716995661\n2014-04-10 02:00:00,19.7811164673\n2014-04-10 02:05:00,21.9331224103\n2014-04-10 02:10:00,19.1852081805\n2014-04-10 02:15:00,18.9612229981\n2014-04-10 02:20:00,20.5521928046\n2014-04-10 02:25:00,19.5126158718\n2014-04-10 02:30:00,20.5054621679\n2014-04-10 02:35:00,19.2199820732\n2014-04-10 02:40:00,20.4716730274\n2014-04-10 02:45:00,19.1029850423\n2014-04-10 02:50:00,18.2038882753\n2014-04-10 02:55:00,21.6485436077\n2014-04-10 03:00:00,21.5328208075\n2014-04-10 03:05:00,21.8831925971\n2014-04-10 03:10:00,20.8661087049\n2014-04-10 03:15:00,20.7308847109\n2014-04-10 03:20:00,20.2360122803\n2014-04-10 03:25:00,18.5037696654\n2014-04-10 03:30:00,18.7569412438\n2014-04-10 03:35:00,19.1578787547\n2014-04-10 03:40:00,21.5606254503\n2014-04-10 03:45:00,18.6918780984\n2014-04-10 03:50:00,21.691492698\n2014-04-10 03:55:00,20.0911429322\n2014-04-10 04:00:00,20.8622785419\n2014-04-10 04:05:00,18.440977946700002\n2014-04-10 04:10:00,19.0761341951\n2014-04-10 04:15:00,21.8340744327\n2014-04-10 04:20:00,19.0645997877\n2014-04-10 04:25:00,19.1860868816\n2014-04-10 04:30:00,18.7903895394\n2014-04-10 04:35:00,18.5162946612\n2014-04-10 04:40:00,18.9330305658\n2014-04-10 04:45:00,20.5693075678\n2014-04-10 04:50:00,19.821470934\n2014-04-10 04:55:00,20.2150233454\n2014-04-10 05:00:00,18.4894593151\n2014-04-10 05:05:00,21.2084657887\n2014-04-10 05:10:00,21.1363788023\n2014-04-10 05:15:00,18.0863596446\n2014-04-10 05:20:00,19.534060378\n2014-04-10 05:25:00,18.2750824079\n2014-04-10 05:30:00,21.1684231177\n2014-04-10 05:35:00,20.9490787325\n2014-04-10 05:40:00,21.607952377199997\n2014-04-10 05:45:00,18.945615835799998\n2014-04-10 05:50:00,19.8251835325\n2014-04-10 05:55:00,18.7379515087\n2014-04-10 06:00:00,19.4849397379\n2014-04-10 06:05:00,20.0889730063\n2014-04-10 06:10:00,18.2133231594\n2014-04-10 06:15:00,20.8594816427\n2014-04-10 06:20:00,20.1731734415\n2014-04-10 06:25:00,21.3158360688\n2014-04-10 06:30:00,19.0871220048\n2014-04-10 06:35:00,21.6132844211\n2014-04-10 06:40:00,21.994777012100002\n2014-04-10 06:45:00,21.6771937535\n2014-04-10 06:50:00,21.111569903299998\n2014-04-10 06:55:00,21.249475211500002\n2014-04-10 07:00:00,20.2949769702\n2014-04-10 07:05:00,18.7606154517\n2014-04-10 07:10:00,20.7081627406\n2014-04-10 07:15:00,20.851012008199998\n2014-04-10 07:20:00,21.941540561100002\n2014-04-10 07:25:00,20.165205265\n2014-04-10 07:30:00,19.0854760601\n2014-04-10 07:35:00,20.734690087\n2014-04-10 07:40:00,21.9175032787\n2014-04-10 07:45:00,18.7088556331\n2014-04-10 07:50:00,19.3039916741\n2014-04-10 07:55:00,20.1675238151\n2014-04-10 08:00:00,18.6808585395\n2014-04-10 08:05:00,18.0888825581\n2014-04-10 08:10:00,19.3479324898\n2014-04-10 08:15:00,21.461483206\n2014-04-10 08:20:00,18.173873597300002\n2014-04-10 08:25:00,19.7157162361\n2014-04-10 08:30:00,21.0488030917\n2014-04-10 08:35:00,21.812730387600002\n2014-04-10 08:40:00,21.941901595999997\n2014-04-10 08:45:00,19.6878775224\n2014-04-10 08:50:00,21.8015371775\n2014-04-10 08:55:00,18.1416758931\n2014-04-10 09:00:00,71.3444703568\n2014-04-10 09:05:00,69.941346071\n2014-04-10 09:10:00,64.59349726319999\n2014-04-10 09:15:00,68.0995316092\n2014-04-10 09:20:00,62.961930833500006\n2014-04-10 09:25:00,73.0537212529\n2014-04-10 09:30:00,66.0674139634\n2014-04-10 09:35:00,69.7142047983\n2014-04-10 09:40:00,63.359357493500006\n2014-04-10 09:45:00,64.003841887\n2014-04-10 09:50:00,74.6906066429\n2014-04-10 09:55:00,71.44197496439999\n2014-04-10 10:00:00,84.7698034189\n2014-04-10 10:05:00,74.4316100841\n2014-04-10 10:10:00,72.3940158451\n2014-04-10 10:15:00,77.6476225532\n2014-04-10 10:20:00,77.51725174020001\n2014-04-10 10:25:00,72.55516989350001\n2014-04-10 10:30:00,81.2195677199\n2014-04-10 10:35:00,75.4547873345\n2014-04-10 10:40:00,72.73238838399999\n2014-04-10 10:45:00,74.9923822833\n2014-04-10 10:50:00,78.5879830183\n2014-04-10 10:55:00,81.11482886739999\n2014-04-10 11:00:00,79.2319926519\n2014-04-10 11:05:00,79.92706271819999\n2014-04-10 11:10:00,73.7777961652\n2014-04-10 11:15:00,86.1152444666\n2014-04-10 11:20:00,86.3384296449\n2014-04-10 11:25:00,82.437216494\n2014-04-10 11:30:00,71.8484099277\n2014-04-10 11:35:00,80.1096283297\n2014-04-10 11:40:00,81.5750985321\n2014-04-10 11:45:00,87.3869807619\n2014-04-10 11:50:00,87.40944885540002\n2014-04-10 11:55:00,85.2074490866\n2014-04-10 12:00:00,72.9336703174\n2014-04-10 12:05:00,87.1477193458\n2014-04-10 12:10:00,81.70441685850001\n2014-04-10 12:15:00,84.7124113017\n2014-04-10 12:20:00,78.42086749229999\n2014-04-10 12:25:00,77.0221738859\n2014-04-10 12:30:00,79.3166120401\n2014-04-10 12:35:00,74.2607722169\n2014-04-10 12:40:00,77.6198025502\n2014-04-10 12:45:00,85.61901374029999\n2014-04-10 12:50:00,72.5200791308\n2014-04-10 12:55:00,74.3247518907\n2014-04-10 13:00:00,73.9840981083\n2014-04-10 13:05:00,78.4303808731\n2014-04-10 13:10:00,87.93068198459999\n2014-04-10 13:15:00,74.7557811889\n2014-04-10 13:20:00,74.30988374020001\n2014-04-10 13:25:00,86.6200978624\n2014-04-10 13:30:00,86.0921411975\n2014-04-10 13:35:00,72.4984421169\n2014-04-10 13:40:00,84.007128812\n2014-04-10 13:45:00,82.4676542353\n2014-04-10 13:50:00,84.26362483289998\n2014-04-10 13:55:00,79.89286038729999\n2014-04-10 14:00:00,87.8578501159\n2014-04-10 14:05:00,72.6980626249\n2014-04-10 14:10:00,75.7463093851\n2014-04-10 14:15:00,78.3409752443\n2014-04-10 14:20:00,79.1926456356\n2014-04-10 14:25:00,86.737714833\n2014-04-10 14:30:00,80.95618374189999\n2014-04-10 14:35:00,72.7182852831\n2014-04-10 14:40:00,78.5220381761\n2014-04-10 14:45:00,78.6600707333\n2014-04-10 14:50:00,87.443657518\n2014-04-10 14:55:00,81.58323727300001\n2014-04-10 15:00:00,82.1696283025\n2014-04-10 15:05:00,83.4112477444\n2014-04-10 15:10:00,84.3198195729\n2014-04-10 15:15:00,82.16002837939999\n2014-04-10 15:20:00,75.7943819851\n2014-04-10 15:25:00,85.983909176\n2014-04-10 15:30:00,83.71311315300001\n2014-04-10 15:35:00,83.86912261020001\n2014-04-10 15:40:00,87.9440635566\n2014-04-10 15:45:00,84.8396100897\n2014-04-10 15:50:00,85.2656038928\n2014-04-10 15:55:00,87.22165091549999\n2014-04-10 16:00:00,74.4180011147\n2014-04-10 16:05:00,79.9634844935\n2014-04-10 16:10:00,81.2889163024\n2014-04-10 16:15:00,77.2682633122\n2014-04-10 16:20:00,85.4302894758\n2014-04-10 16:25:00,84.1985522848\n2014-04-10 16:30:00,83.5339688066\n2014-04-10 16:35:00,87.95422216370001\n2014-04-10 16:40:00,76.1499557663\n2014-04-10 16:45:00,83.76715519359999\n2014-04-10 16:50:00,80.82231641930001\n2014-04-10 16:55:00,77.0076790649\n2014-04-10 17:00:00,74.5693612969\n2014-04-10 17:05:00,86.3341082408\n2014-04-10 17:10:00,81.5272564168\n2014-04-10 17:15:00,85.19890868590001\n2014-04-10 17:20:00,80.7254887454\n2014-04-10 17:25:00,75.5196042909\n2014-04-10 17:30:00,77.4007512877\n2014-04-10 17:35:00,78.1045914874\n2014-04-10 17:40:00,87.5669233743\n2014-04-10 17:45:00,72.0901047715\n2014-04-10 17:50:00,87.77062266450001\n2014-04-10 17:55:00,87.68735248979998\n2014-04-10 18:00:00,35.1753583057\n2014-04-10 18:05:00,31.850158229899996\n2014-04-10 18:10:00,34.9683706916\n2014-04-10 18:15:00,31.331828748099998\n2014-04-10 18:20:00,28.9682788584\n2014-04-10 18:25:00,30.2358161875\n2014-04-10 18:30:00,34.8498892764\n2014-04-10 18:35:00,28.888088490799998\n2014-04-10 18:40:00,32.2943562662\n2014-04-10 18:45:00,29.283844546399997\n2014-04-10 18:50:00,30.6329322204\n2014-04-10 18:55:00,29.363788606700002\n2014-04-10 19:00:00,24.0106869054\n2014-04-10 19:05:00,22.807995528000003\n2014-04-10 19:10:00,24.2014356388\n2014-04-10 19:15:00,23.2438210589\n2014-04-10 19:20:00,24.510209163400003\n2014-04-10 19:25:00,22.4442506621\n2014-04-10 19:30:00,23.021422143400002\n2014-04-10 19:35:00,22.741862265500004\n2014-04-10 19:40:00,22.329485499\n2014-04-10 19:45:00,23.9498966433\n2014-04-10 19:50:00,23.0474713435\n2014-04-10 19:55:00,23.7498776437\n2014-04-10 20:00:00,21.652946424499998\n2014-04-10 20:05:00,19.2145207475\n2014-04-10 20:10:00,21.0950695761\n2014-04-10 20:15:00,19.2497580556\n2014-04-10 20:20:00,20.821280429\n2014-04-10 20:25:00,21.206772213\n2014-04-10 20:30:00,22.516674583\n2014-04-10 20:35:00,18.5570997198\n2014-04-10 20:40:00,18.8057286206\n2014-04-10 20:45:00,18.7475011234\n2014-04-10 20:50:00,20.0636875878\n2014-04-10 20:55:00,21.7972256671\n2014-04-10 21:00:00,21.4788311602\n2014-04-10 21:05:00,21.0484683396\n2014-04-10 21:10:00,21.6911329765\n2014-04-10 21:15:00,19.3840386402\n2014-04-10 21:20:00,18.4407111011\n2014-04-10 21:25:00,18.3201286053\n2014-04-10 21:30:00,21.5112917741\n2014-04-10 21:35:00,21.0221695028\n2014-04-10 21:40:00,20.8942745868\n2014-04-10 21:45:00,19.4516270923\n2014-04-10 21:50:00,19.6133148861\n2014-04-10 21:55:00,21.9372498417\n2014-04-10 22:00:00,18.2727439776\n2014-04-10 22:05:00,21.1151780673\n2014-04-10 22:10:00,19.2570022773\n2014-04-10 22:15:00,18.173648434500002\n2014-04-10 22:20:00,20.9904119019\n2014-04-10 22:25:00,19.3421982349\n2014-04-10 22:30:00,20.9086431112\n2014-04-10 22:35:00,20.8506149151\n2014-04-10 22:40:00,20.1584810734\n2014-04-10 22:45:00,21.1297576193\n2014-04-10 22:50:00,20.343664473900002\n2014-04-10 22:55:00,19.1649280875\n2014-04-10 23:00:00,20.9404810028\n2014-04-10 23:05:00,20.3604677209\n2014-04-10 23:10:00,18.0543748995\n2014-04-10 23:15:00,21.6107251717\n2014-04-10 23:20:00,20.1864495256\n2014-04-10 23:25:00,21.478632165500002\n2014-04-10 23:30:00,21.535081295700003\n2014-04-10 23:35:00,19.7836643594\n2014-04-10 23:40:00,20.034485866700003\n2014-04-10 23:45:00,19.6667928481\n2014-04-10 23:50:00,19.8015482667\n2014-04-10 23:55:00,21.584732106799997\n2014-04-11 00:00:00,21.1525760559\n2014-04-11 00:05:00,18.5061027053\n2014-04-11 00:10:00,20.441231126199998\n2014-04-11 00:15:00,21.9836265615\n2014-04-11 00:20:00,20.3822028049\n2014-04-11 00:25:00,21.143486502400002\n2014-04-11 00:30:00,21.076245893499998\n2014-04-11 00:35:00,19.4012701035\n2014-04-11 00:40:00,19.487397210799998\n2014-04-11 00:45:00,20.8963056872\n2014-04-11 00:50:00,19.9999341264\n2014-04-11 00:55:00,20.282282836500002\n2014-04-11 01:00:00,20.8516231615\n2014-04-11 01:05:00,21.1103001082\n2014-04-11 01:10:00,19.086066310899998\n2014-04-11 01:15:00,18.5871750377\n2014-04-11 01:20:00,19.1671785869\n2014-04-11 01:25:00,20.0301533004\n2014-04-11 01:30:00,19.3685652692\n2014-04-11 01:35:00,20.2734510354\n2014-04-11 01:40:00,18.2138628965\n2014-04-11 01:45:00,20.0390016465\n2014-04-11 01:50:00,19.4719396278\n2014-04-11 01:55:00,20.1386670196\n2014-04-11 02:00:00,19.6901334195\n2014-04-11 02:05:00,19.1369034026\n2014-04-11 02:10:00,21.616431621799997\n2014-04-11 02:15:00,18.7390599537\n2014-04-11 02:20:00,20.7254623023\n2014-04-11 02:25:00,21.698578850300002\n2014-04-11 02:30:00,20.154679838699998\n2014-04-11 02:35:00,21.5056339543\n2014-04-11 02:40:00,18.4994059137\n2014-04-11 02:45:00,19.975155081\n2014-04-11 02:50:00,19.8281011219\n2014-04-11 02:55:00,18.0324752281\n2014-04-11 03:00:00,19.7730293654\n2014-04-11 03:05:00,19.4761190255\n2014-04-11 03:10:00,20.679194911099998\n2014-04-11 03:15:00,21.753319114299998\n2014-04-11 03:20:00,18.343164353\n2014-04-11 03:25:00,19.3099055469\n2014-04-11 03:30:00,19.7762589496\n2014-04-11 03:35:00,19.8207415121\n2014-04-11 03:40:00,21.099238883399998\n2014-04-11 03:45:00,19.7735826633\n2014-04-11 03:50:00,18.1086452058\n2014-04-11 03:55:00,20.8404163784\n2014-04-11 04:00:00,21.5393187806\n2014-04-11 04:05:00,20.0556188502\n2014-04-11 04:10:00,20.3244340868\n2014-04-11 04:15:00,18.6517457559\n2014-04-11 04:20:00,18.8825837787\n2014-04-11 04:25:00,18.9406809565\n2014-04-11 04:30:00,19.722967899500002\n2014-04-11 04:35:00,21.7125808836\n2014-04-11 04:40:00,20.0871390669\n2014-04-11 04:45:00,18.7683905808\n2014-04-11 04:50:00,19.0643509435\n2014-04-11 04:55:00,19.5360601189\n2014-04-11 05:00:00,20.4930359028\n2014-04-11 05:05:00,19.760132612\n2014-04-11 05:10:00,19.5697793767\n2014-04-11 05:15:00,20.258914401600002\n2014-04-11 05:20:00,18.9673399798\n2014-04-11 05:25:00,18.3156130903\n2014-04-11 05:30:00,18.0976572593\n2014-04-11 05:35:00,19.0050366539\n2014-04-11 05:40:00,18.366368136600002\n2014-04-11 05:45:00,19.3453625541\n2014-04-11 05:50:00,21.0917341614\n2014-04-11 05:55:00,20.8651773219\n2014-04-11 06:00:00,20.443710491199997\n2014-04-11 06:05:00,21.4100009755\n2014-04-11 06:10:00,19.1282704982\n2014-04-11 06:15:00,21.5402150121\n2014-04-11 06:20:00,19.5969566787\n2014-04-11 06:25:00,19.6035732731\n2014-04-11 06:30:00,19.6214064545\n2014-04-11 06:35:00,18.392377465\n2014-04-11 06:40:00,21.9019619933\n2014-04-11 06:45:00,18.5540271113\n2014-04-11 06:50:00,19.3635428979\n2014-04-11 06:55:00,19.2772012813\n2014-04-11 07:00:00,18.298717731300002\n2014-04-11 07:05:00,18.6090405204\n2014-04-11 07:10:00,18.1794333447\n2014-04-11 07:15:00,19.1696179742\n2014-04-11 07:20:00,21.466627696099998\n2014-04-11 07:25:00,19.3577688229\n2014-04-11 07:30:00,18.4947673283\n2014-04-11 07:35:00,20.5827754735\n2014-04-11 07:40:00,21.986403648200003\n2014-04-11 07:45:00,18.9292951581\n2014-04-11 07:50:00,19.118284021500003\n2014-04-11 07:55:00,21.8873882171\n2014-04-11 08:00:00,18.7151051502\n2014-04-11 08:05:00,20.0448562698\n2014-04-11 08:10:00,18.9586085321\n2014-04-11 08:15:00,21.729407591599998\n2014-04-11 08:20:00,21.9260840583\n2014-04-11 08:25:00,21.2587913845\n2014-04-11 08:30:00,19.2591352633\n2014-04-11 08:35:00,19.6139499011\n2014-04-11 08:40:00,18.9692227347\n2014-04-11 08:45:00,21.563031868000003\n2014-04-11 08:50:00,21.658233110799998\n2014-04-11 08:55:00,19.675482649\n2014-04-11 09:00:00,127.882020134\n2014-04-11 09:05:00,115.705718858\n2014-04-11 09:10:00,122.386410329\n2014-04-11 09:15:00,127.26117784600001\n2014-04-11 09:20:00,121.15799733899999\n2014-04-11 09:25:00,120.46846823700001\n2014-04-11 09:30:00,111.62477500799999\n2014-04-11 09:35:00,131.54647790200002\n2014-04-11 09:40:00,133.655572778\n2014-04-11 09:45:00,135.642695533\n2014-04-11 09:50:00,129.43793035\n2014-04-11 09:55:00,125.21004934700001\n2014-04-11 10:00:00,138.118479694\n2014-04-11 10:05:00,159.259712824\n2014-04-11 10:10:00,147.399242667\n2014-04-11 10:15:00,150.046221935\n2014-04-11 10:20:00,150.08248245\n2014-04-11 10:25:00,154.798492005\n2014-04-11 10:30:00,130.600116725\n2014-04-11 10:35:00,136.698351395\n2014-04-11 10:40:00,149.593864645\n2014-04-11 10:45:00,156.24342053799998\n2014-04-11 10:50:00,150.16741112399998\n2014-04-11 10:55:00,142.294707802\n2014-04-11 11:00:00,144.83546133299998\n2014-04-11 11:05:00,156.04894706299999\n2014-04-11 11:10:00,156.146953473\n2014-04-11 11:15:00,152.149471713\n2014-04-11 11:20:00,142.74738558200002\n2014-04-11 11:25:00,161.62621235\n2014-04-11 11:30:00,150.505607236\n2014-04-11 11:35:00,157.614348277\n2014-04-11 11:40:00,140.448671746\n2014-04-11 11:45:00,144.313663174\n2014-04-11 11:50:00,160.119472952\n2014-04-11 11:55:00,135.556788636\n2014-04-11 12:00:00,150.160947021\n2014-04-11 12:05:00,149.243925447\n2014-04-11 12:10:00,157.318454491\n2014-04-11 12:15:00,143.257886337\n2014-04-11 12:20:00,141.37569147600001\n2014-04-11 12:25:00,162.558258037\n2014-04-11 12:30:00,151.940306437\n2014-04-11 12:35:00,137.949131962\n2014-04-11 12:40:00,140.595854562\n2014-04-11 12:45:00,164.736030621\n2014-04-11 12:50:00,140.67293255299998\n2014-04-11 12:55:00,153.101669559\n2014-04-11 13:00:00,147.562906904\n2014-04-11 13:05:00,161.523164661\n2014-04-11 13:10:00,157.611334766\n2014-04-11 13:15:00,152.86613525200002\n2014-04-11 13:20:00,135.284640106\n2014-04-11 13:25:00,161.349096329\n2014-04-11 13:30:00,148.298884492\n2014-04-11 13:35:00,162.902138864\n2014-04-11 13:40:00,149.824607501\n2014-04-11 13:45:00,155.783518728\n2014-04-11 13:50:00,137.04076296899999\n2014-04-11 13:55:00,157.310909944\n2014-04-11 14:00:00,145.131830514\n2014-04-11 14:05:00,145.532697769\n2014-04-11 14:10:00,138.551989898\n2014-04-11 14:15:00,139.397982089\n2014-04-11 14:20:00,140.56497458299998\n2014-04-11 14:25:00,144.838150922\n2014-04-11 14:30:00,161.750125145\n2014-04-11 14:35:00,146.039706362\n2014-04-11 14:40:00,156.722187857\n2014-04-11 14:45:00,137.474799425\n2014-04-11 14:50:00,152.72449239\n2014-04-11 14:55:00,149.448447071\n2014-04-11 15:00:00,164.336915344\n2014-04-11 15:05:00,160.384453878\n2014-04-11 15:10:00,148.643244206\n2014-04-11 15:15:00,158.252527354\n2014-04-11 15:20:00,140.789600396\n2014-04-11 15:25:00,151.86840507600002\n2014-04-11 15:30:00,137.23704923399998\n2014-04-11 15:35:00,145.441057524\n2014-04-11 15:40:00,141.774292682\n2014-04-11 15:45:00,156.56555760700002\n2014-04-11 15:50:00,149.701060034\n2014-04-11 15:55:00,157.530366809\n2014-04-11 16:00:00,150.458529311\n2014-04-11 16:05:00,137.594227988\n2014-04-11 16:10:00,157.060681026\n2014-04-11 16:15:00,159.99652294\n2014-04-11 16:20:00,162.10557711799999\n2014-04-11 16:25:00,152.159420767\n2014-04-11 16:30:00,157.607211091\n2014-04-11 16:35:00,157.56098053\n2014-04-11 16:40:00,139.672182907\n2014-04-11 16:45:00,139.926310173\n2014-04-11 16:50:00,137.126260936\n2014-04-11 16:55:00,144.597088241\n2014-04-11 17:00:00,149.205191425\n2014-04-11 17:05:00,164.936862395\n2014-04-11 17:10:00,147.929734621\n2014-04-11 17:15:00,156.787208083\n2014-04-11 17:20:00,155.801841654\n2014-04-11 17:25:00,141.134395882\n2014-04-11 17:30:00,136.755153861\n2014-04-11 17:35:00,151.380135374\n2014-04-11 17:40:00,156.009098543\n2014-04-11 17:45:00,164.947480513\n2014-04-11 17:50:00,145.758266891\n2014-04-11 17:55:00,161.890865026\n2014-04-11 18:00:00,44.9137655963\n2014-04-11 18:05:00,47.7425739013\n2014-04-11 18:10:00,46.9039133872\n2014-04-11 18:15:00,41.8873927765\n2014-04-11 18:20:00,42.121161338600004\n2014-04-11 18:25:00,41.5910175894\n2014-04-11 18:30:00,44.81166061020001\n2014-04-11 18:35:00,48.26135568220001\n2014-04-11 18:40:00,42.98933718399999\n2014-04-11 18:45:00,46.973833715299996\n2014-04-11 18:50:00,44.057202826499996\n2014-04-11 18:55:00,48.7323180379\n2014-04-11 19:00:00,26.703913769699998\n2014-04-11 19:05:00,26.588086346399997\n2014-04-11 19:10:00,25.325158233899998\n2014-04-11 19:15:00,24.1142136711\n2014-04-11 19:20:00,26.759595154\n2014-04-11 19:25:00,23.6179443369\n2014-04-11 19:30:00,24.1403858438\n2014-04-11 19:35:00,23.607093944899997\n2014-04-11 19:40:00,26.0780164532\n2014-04-11 19:45:00,26.1386268201\n2014-04-11 19:50:00,25.96864762\n2014-04-11 19:55:00,24.774628775500002\n2014-04-11 20:00:00,19.3575191084\n2014-04-11 20:05:00,22.7702010354\n2014-04-11 20:10:00,21.072531363299998\n2014-04-11 20:15:00,20.6485384736\n2014-04-11 20:20:00,21.4137746088\n2014-04-11 20:25:00,19.7472616542\n2014-04-11 20:30:00,19.4937647691\n2014-04-11 20:35:00,20.6424496095\n2014-04-11 20:40:00,19.8921441773\n2014-04-11 20:45:00,19.9639730542\n2014-04-11 20:50:00,22.6916877663\n2014-04-11 20:55:00,21.169434081800002\n2014-04-11 21:00:00,20.141188464200003\n2014-04-11 21:05:00,20.9738006155\n2014-04-11 21:10:00,22.032976740100004\n2014-04-11 21:15:00,18.6406616199\n2014-04-11 21:20:00,21.556013192800002\n2014-04-11 21:25:00,20.547571809100003\n2014-04-11 21:30:00,18.777941795\n2014-04-11 21:35:00,19.3881585842\n2014-04-11 21:40:00,20.136711794700002\n2014-04-11 21:45:00,20.980661437000002\n2014-04-11 21:50:00,19.1677204187\n2014-04-11 21:55:00,20.3489661134\n2014-04-11 22:00:00,20.7818229555\n2014-04-11 22:05:00,19.8361365054\n2014-04-11 22:10:00,21.496724197600003\n2014-04-11 22:15:00,21.522510288200003\n2014-04-11 22:20:00,19.9241210003\n2014-04-11 22:25:00,21.9372375602\n2014-04-11 22:30:00,18.3404092181\n2014-04-11 22:35:00,18.0509174691\n2014-04-11 22:40:00,19.5632801944\n2014-04-11 22:45:00,20.4468293513\n2014-04-11 22:50:00,20.5594755533\n2014-04-11 22:55:00,19.9471869525\n2014-04-11 23:00:00,18.5072290549\n2014-04-11 23:05:00,18.689761791\n2014-04-11 23:10:00,21.4174979051\n2014-04-11 23:15:00,21.4805767265\n2014-04-11 23:20:00,20.7042035142\n2014-04-11 23:25:00,20.6654651434\n2014-04-11 23:30:00,20.399211050799998\n2014-04-11 23:35:00,18.8195292075\n2014-04-11 23:40:00,19.721203406\n2014-04-11 23:45:00,20.7922245701\n2014-04-11 23:50:00,20.1573910715\n2014-04-11 23:55:00,18.08184025\n2014-04-12 00:00:00,21.8142272269\n2014-04-12 00:05:00,21.3792642103\n2014-04-12 00:10:00,19.0421800564\n2014-04-12 00:15:00,20.465835740699998\n2014-04-12 00:20:00,21.692957534899996\n2014-04-12 00:25:00,18.384044048499998\n2014-04-12 00:30:00,20.012117923199998\n2014-04-12 00:35:00,19.8249721034\n2014-04-12 00:40:00,19.640820021099998\n2014-04-12 00:45:00,21.3423544356\n2014-04-12 00:50:00,19.5225845868\n2014-04-12 00:55:00,18.254653333\n2014-04-12 01:00:00,18.2633509687\n2014-04-12 01:05:00,18.1709784261\n2014-04-12 01:10:00,19.6365816875\n2014-04-12 01:15:00,20.8736251108\n2014-04-12 01:20:00,18.814889847699998\n2014-04-12 01:25:00,20.585874081700002\n2014-04-12 01:30:00,20.7483538884\n2014-04-12 01:35:00,19.0208084961\n2014-04-12 01:40:00,20.4022306242\n2014-04-12 01:45:00,20.7394733601\n2014-04-12 01:50:00,19.8664544912\n2014-04-12 01:55:00,19.3468663891\n2014-04-12 02:00:00,20.4766062063\n2014-04-12 02:05:00,21.911388349299997\n2014-04-12 02:10:00,19.7073656375\n2014-04-12 02:15:00,19.5669403851\n2014-04-12 02:20:00,19.8570676097\n2014-04-12 02:25:00,18.304873573800002\n2014-04-12 02:30:00,20.2126531187\n2014-04-12 02:35:00,19.314789548900002\n2014-04-12 02:40:00,18.4856884893\n2014-04-12 02:45:00,19.8650269645\n2014-04-12 02:50:00,18.013535946300003\n2014-04-12 02:55:00,19.6071409807\n2014-04-12 03:00:00,18.422941071700002\n2014-04-12 03:05:00,18.0971708136\n2014-04-12 03:10:00,21.297900185\n2014-04-12 03:15:00,21.6649952131\n2014-04-12 03:20:00,18.830698593399998\n2014-04-12 03:25:00,20.1571930553\n2014-04-12 03:30:00,19.1118326285\n2014-04-12 03:35:00,19.974309754700002\n2014-04-12 03:40:00,19.7465252836\n2014-04-12 03:45:00,19.0762042203\n2014-04-12 03:50:00,20.8015743185\n2014-04-12 03:55:00,18.5059638373\n2014-04-12 04:00:00,18.2122911287\n2014-04-12 04:05:00,21.0707017321\n2014-04-12 04:10:00,20.6637201249\n2014-04-12 04:15:00,19.994104496600002\n2014-04-12 04:20:00,19.8711590819\n2014-04-12 04:25:00,19.989645518\n2014-04-12 04:30:00,19.7480963044\n2014-04-12 04:35:00,19.5715691833\n2014-04-12 04:40:00,19.9987624115\n2014-04-12 04:45:00,20.114060684600002\n2014-04-12 04:50:00,20.767609256300002\n2014-04-12 04:55:00,20.8448286429\n2014-04-12 05:00:00,19.5105163206\n2014-04-12 05:05:00,19.654162091\n2014-04-12 05:10:00,19.4947886789\n2014-04-12 05:15:00,20.1461430945\n2014-04-12 05:20:00,19.8134141517\n2014-04-12 05:25:00,21.5583858525\n2014-04-12 05:30:00,20.7854450677\n2014-04-12 05:35:00,21.594625535\n2014-04-12 05:40:00,20.836547966199998\n2014-04-12 05:45:00,21.883968594099997\n2014-04-12 05:50:00,20.542947113\n2014-04-12 05:55:00,21.8542005527\n2014-04-12 06:00:00,18.6326795616\n2014-04-12 06:05:00,18.2099107233\n2014-04-12 06:10:00,20.3165007408\n2014-04-12 06:15:00,21.9339728232\n2014-04-12 06:20:00,19.6704209892\n2014-04-12 06:25:00,18.8481734488\n2014-04-12 06:30:00,20.0861657968\n2014-04-12 06:35:00,20.5951944983\n2014-04-12 06:40:00,19.2607147821\n2014-04-12 06:45:00,20.859077434\n2014-04-12 06:50:00,21.900458028200003\n2014-04-12 06:55:00,21.5878524868\n2014-04-12 07:00:00,19.166341494\n2014-04-12 07:05:00,19.3068947326\n2014-04-12 07:10:00,19.4861648978\n2014-04-12 07:15:00,19.5782111136\n2014-04-12 07:20:00,18.4012779968\n2014-04-12 07:25:00,21.0478513556\n2014-04-12 07:30:00,19.4613570544\n2014-04-12 07:35:00,21.519279906799998\n2014-04-12 07:40:00,21.7077624925\n2014-04-12 07:45:00,18.0977252372\n2014-04-12 07:50:00,21.9540122797\n2014-04-12 07:55:00,20.840090926\n2014-04-12 08:00:00,20.081568904\n2014-04-12 08:05:00,19.558110433499998\n2014-04-12 08:10:00,20.0740725304\n2014-04-12 08:15:00,19.2984988959\n2014-04-12 08:20:00,20.4907512548\n2014-04-12 08:25:00,18.3719211058\n2014-04-12 08:30:00,20.4844904116\n2014-04-12 08:35:00,19.1013794006\n2014-04-12 08:40:00,18.070539316199998\n2014-04-12 08:45:00,20.2108230647\n2014-04-12 08:50:00,20.3137910234\n2014-04-12 08:55:00,19.7062760188\n2014-04-12 09:00:00,62.18309276270001\n2014-04-12 09:05:00,73.3494641581\n2014-04-12 09:10:00,69.5154589783\n2014-04-12 09:15:00,62.7737008741\n2014-04-12 09:20:00,68.1486558417\n2014-04-12 09:25:00,67.9626586969\n2014-04-12 09:30:00,62.021465415600005\n2014-04-12 09:35:00,69.45329196899999\n2014-04-12 09:40:00,72.1932390253\n2014-04-12 09:45:00,71.3865095378\n2014-04-12 09:50:00,63.960384032600004\n2014-04-12 09:55:00,72.9271784019\n2014-04-12 10:00:00,75.156254411\n2014-04-12 10:05:00,84.5298100311\n2014-04-12 10:10:00,70.9535284048\n2014-04-12 10:15:00,77.3859588458\n2014-04-12 10:20:00,79.1073703338\n2014-04-12 10:25:00,73.6835295283\n2014-04-12 10:30:00,81.8118205289\n2014-04-12 10:35:00,79.56942095069999\n2014-04-12 10:40:00,70.1210584667\n2014-04-12 10:45:00,79.28188052760001\n2014-04-12 10:50:00,77.4677421982\n2014-04-12 10:55:00,72.8823732104\n2014-04-12 11:00:00,87.4043798032\n2014-04-12 11:05:00,85.83646754649999\n2014-04-12 11:10:00,76.2200423817\n2014-04-12 11:15:00,80.1731919244\n2014-04-12 11:20:00,76.6016500331\n2014-04-12 11:25:00,83.901484434\n2014-04-12 11:30:00,86.36399111360001\n2014-04-12 11:35:00,77.2748101644\n2014-04-12 11:40:00,84.3800118984\n2014-04-12 11:45:00,79.4946735593\n2014-04-12 11:50:00,77.8751854391\n2014-04-12 11:55:00,86.4926611358\n2014-04-12 12:00:00,80.0702752495\n2014-04-12 12:05:00,79.3831937225\n2014-04-12 12:10:00,82.65963969090001\n2014-04-12 12:15:00,76.0883315196\n2014-04-12 12:20:00,77.10404990949999\n2014-04-12 12:25:00,86.8084380998\n2014-04-12 12:30:00,82.757049754\n2014-04-12 12:35:00,85.1239229311\n2014-04-12 12:40:00,76.24618284510001\n2014-04-12 12:45:00,80.60380226720001\n2014-04-12 12:50:00,87.43728946350002\n2014-04-12 12:55:00,77.0067432696\n2014-04-12 13:00:00,74.5497273914\n2014-04-12 13:05:00,80.1549343293\n2014-04-12 13:10:00,78.18636818659999\n2014-04-12 13:15:00,74.53534294800001\n2014-04-12 13:20:00,86.1961300859\n2014-04-12 13:25:00,87.830498189\n2014-04-12 13:30:00,81.0778515355\n2014-04-12 13:35:00,84.3745735352\n2014-04-12 13:40:00,85.7240352054\n2014-04-12 13:45:00,83.1957403254\n2014-04-12 13:50:00,72.6890472266\n2014-04-12 13:55:00,74.504262392\n2014-04-12 14:00:00,73.1323165387\n2014-04-12 14:05:00,72.15461011869998\n2014-04-12 14:10:00,76.8922515349\n2014-04-12 14:15:00,78.2739380383\n2014-04-12 14:20:00,75.8528346065\n2014-04-12 14:25:00,73.030168753\n2014-04-12 14:30:00,80.4739465185\n2014-04-12 14:35:00,76.3694432101\n2014-04-12 14:40:00,84.7325271213\n2014-04-12 14:45:00,72.1253797616\n2014-04-12 14:50:00,85.4763297598\n2014-04-12 14:55:00,87.2718696123\n2014-04-12 15:00:00,83.4573598121\n2014-04-12 15:05:00,83.7375011565\n2014-04-12 15:10:00,86.93616239049999\n2014-04-12 15:15:00,75.34441725149999\n2014-04-12 15:20:00,87.9122051261\n2014-04-12 15:25:00,84.37488924729999\n2014-04-12 15:30:00,83.62432853199999\n2014-04-12 15:35:00,77.7767026004\n2014-04-12 15:40:00,80.7316647351\n2014-04-12 15:45:00,82.4618929706\n2014-04-12 15:50:00,81.92469929640001\n2014-04-12 15:55:00,83.27895473\n2014-04-12 16:00:00,73.3179670545\n2014-04-12 16:05:00,77.6902257598\n2014-04-12 16:10:00,78.943848693\n2014-04-12 16:15:00,76.16992251949999\n2014-04-12 16:20:00,74.7618927812\n2014-04-12 16:25:00,74.2226971708\n2014-04-12 16:30:00,77.8619847808\n2014-04-12 16:35:00,79.8949138105\n2014-04-12 16:40:00,73.0074828677\n2014-04-12 16:45:00,87.1431621983\n2014-04-12 16:50:00,84.2437314175\n2014-04-12 16:55:00,83.6934676792\n2014-04-12 17:00:00,74.7657396898\n2014-04-12 17:05:00,81.6607809304\n2014-04-12 17:10:00,80.4755682463\n2014-04-12 17:15:00,87.7194678483\n2014-04-12 17:20:00,83.9627160796\n2014-04-12 17:25:00,81.212158954\n2014-04-12 17:30:00,85.6129697881\n2014-04-12 17:35:00,74.4814797329\n2014-04-12 17:40:00,72.24343673359999\n2014-04-12 17:45:00,83.0437014458\n2014-04-12 17:50:00,73.5729551118\n2014-04-12 17:55:00,73.8469098825\n2014-04-12 18:00:00,33.5659502045\n2014-04-12 18:05:00,30.5314171404\n2014-04-12 18:10:00,32.8232334776\n2014-04-12 18:15:00,34.6713976701\n2014-04-12 18:20:00,30.825431084\n2014-04-12 18:25:00,30.1897168137\n2014-04-12 18:30:00,29.4819967954\n2014-04-12 18:35:00,29.634953423200002\n2014-04-12 18:40:00,29.1982196444\n2014-04-12 18:45:00,29.360905587199998\n2014-04-12 18:50:00,31.5648233079\n2014-04-12 18:55:00,30.8535303643\n2014-04-12 19:00:00,23.32539116860001\n2014-04-12 19:05:00,24.0586813092\n2014-04-12 19:10:00,23.6757826513\n2014-04-12 19:15:00,22.5372536735\n2014-04-12 19:20:00,20.6189395496\n2014-04-12 19:25:00,23.3397561517\n2014-04-12 19:30:00,21.7854714917\n2014-04-12 19:35:00,20.5437126378\n2014-04-12 19:40:00,23.9342481913\n2014-04-12 19:45:00,21.6752088079\n2014-04-12 19:50:00,21.1377536101\n2014-04-12 19:55:00,24.0641039294\n2014-04-12 20:00:00,22.127140059600002\n2014-04-12 20:05:00,19.820424311300002\n2014-04-12 20:10:00,19.8852663748\n2014-04-12 20:15:00,20.8061581993\n2014-04-12 20:20:00,21.4361761014\n2014-04-12 20:25:00,18.6906589067\n2014-04-12 20:30:00,20.862335369500002\n2014-04-12 20:35:00,22.334750705\n2014-04-12 20:40:00,19.5055363688\n2014-04-12 20:45:00,22.154556003099998\n2014-04-12 20:50:00,22.323889255900003\n2014-04-12 20:55:00,19.534453079000002\n2014-04-12 21:00:00,21.1176880877\n2014-04-12 21:05:00,19.046084466900002\n2014-04-12 21:10:00,21.0510067297\n2014-04-12 21:15:00,21.2913902965\n2014-04-12 21:20:00,19.0799691177\n2014-04-12 21:25:00,20.9636228183\n2014-04-12 21:30:00,21.3504105104\n2014-04-12 21:35:00,19.527600155\n2014-04-12 21:40:00,18.7604309514\n2014-04-12 21:45:00,18.4560239438\n2014-04-12 21:50:00,20.398974093299998\n2014-04-12 21:55:00,22.0175719073\n2014-04-12 22:00:00,21.3122413989\n2014-04-12 22:05:00,19.7623121702\n2014-04-12 22:10:00,20.165824225799998\n2014-04-12 22:15:00,19.1364649193\n2014-04-12 22:20:00,18.6701696332\n2014-04-12 22:25:00,19.9474558148\n2014-04-12 22:30:00,19.873066100899997\n2014-04-12 22:35:00,20.1070040124\n2014-04-12 22:40:00,21.8321571011\n2014-04-12 22:45:00,20.4351801485\n2014-04-12 22:50:00,20.4426935003\n2014-04-12 22:55:00,18.5298706574\n2014-04-12 23:00:00,21.990176765999998\n2014-04-12 23:05:00,21.0954293198\n2014-04-12 23:10:00,21.5129430664\n2014-04-12 23:15:00,19.6609758281\n2014-04-12 23:20:00,20.0123540156\n2014-04-12 23:25:00,20.092192195\n2014-04-12 23:30:00,18.7799832199\n2014-04-12 23:35:00,20.761942150899998\n2014-04-12 23:40:00,21.616056378499998\n2014-04-12 23:45:00,18.6584049968\n2014-04-12 23:50:00,18.3487953846\n2014-04-12 23:55:00,20.9568985722\n2014-04-13 00:00:00,19.0928073267\n2014-04-13 00:05:00,20.4954501665\n2014-04-13 00:10:00,20.783033352\n2014-04-13 00:15:00,19.287643054300002\n2014-04-13 00:20:00,100.000000000\n2014-04-13 00:25:00,20.1999559285\n2014-04-13 00:30:00,21.4759976318\n2014-04-13 00:35:00,21.053174210199998\n2014-04-13 00:40:00,21.4743025281\n2014-04-13 00:45:00,18.0806455285\n2014-04-13 00:50:00,18.974025043\n2014-04-13 00:55:00,18.360031761800002\n2014-04-13 01:00:00,19.7683320688\n2014-04-13 01:05:00,21.5598404865\n2014-04-13 01:10:00,19.870161049100002\n2014-04-13 01:15:00,21.3988521783\n2014-04-13 01:20:00,19.3087129521\n2014-04-13 01:25:00,19.3582802912\n2014-04-13 01:30:00,21.5822469213\n2014-04-13 01:35:00,19.703268586\n2014-04-13 01:40:00,21.159061951199998\n2014-04-13 01:45:00,18.9465741915\n2014-04-13 01:50:00,21.7952033187\n2014-04-13 01:55:00,20.298312986099997\n2014-04-13 02:00:00,21.037294274300002\n2014-04-13 02:05:00,18.358062799200003\n2014-04-13 02:10:00,19.9706569033\n2014-04-13 02:15:00,21.604153990900002\n2014-04-13 02:20:00,21.508154516199998\n2014-04-13 02:25:00,18.1872558289\n2014-04-13 02:30:00,19.2147938765\n2014-04-13 02:35:00,19.7732800259\n2014-04-13 02:40:00,18.6890592574\n2014-04-13 02:45:00,20.919993244\n2014-04-13 02:50:00,18.7380479824\n2014-04-13 02:55:00,19.3865587775\n2014-04-13 03:00:00,20.6531225474\n2014-04-13 03:05:00,19.9283573781\n2014-04-13 03:10:00,20.9542841545\n2014-04-13 03:15:00,21.844831604899998\n2014-04-13 03:20:00,18.4661867509\n2014-04-13 03:25:00,20.8382708656\n2014-04-13 03:30:00,18.9213766225\n2014-04-13 03:35:00,19.6579069096\n2014-04-13 03:40:00,18.1314509032\n2014-04-13 03:45:00,18.5436295292\n2014-04-13 03:50:00,19.2791091562\n2014-04-13 03:55:00,19.367943221199997\n2014-04-13 04:00:00,21.5983408658\n2014-04-13 04:05:00,20.9672516371\n2014-04-13 04:10:00,21.8887318727\n2014-04-13 04:15:00,20.3962860413\n2014-04-13 04:20:00,18.9668549284\n2014-04-13 04:25:00,19.3106201197\n2014-04-13 04:30:00,19.279343693199998\n2014-04-13 04:35:00,19.305977310699998\n2014-04-13 04:40:00,20.691856692400002\n2014-04-13 04:45:00,20.1232317124\n2014-04-13 04:50:00,19.5416967123\n2014-04-13 04:55:00,18.5963590749\n2014-04-13 05:00:00,18.0885566518\n2014-04-13 05:05:00,18.8753387104\n2014-04-13 05:10:00,18.429885615899998\n2014-04-13 05:15:00,21.1417801234\n2014-04-13 05:20:00,18.4499918313\n2014-04-13 05:25:00,20.8969129492\n2014-04-13 05:30:00,19.5426347591\n2014-04-13 05:35:00,18.293513559\n2014-04-13 05:40:00,21.2509201977\n2014-04-13 05:45:00,20.318522280899998\n2014-04-13 05:50:00,18.9430460515\n2014-04-13 05:55:00,21.5787246973\n2014-04-13 06:00:00,18.1810332555\n2014-04-13 06:05:00,18.8072784328\n2014-04-13 06:10:00,21.008187711199998\n2014-04-13 06:15:00,20.8375117212\n2014-04-13 06:20:00,19.1570867749\n2014-04-13 06:25:00,18.248099501400002\n2014-04-13 06:30:00,21.4323122889\n2014-04-13 06:35:00,19.2547905523\n2014-04-13 06:40:00,18.7828536597\n2014-04-13 06:45:00,20.0642472894\n2014-04-13 06:50:00,21.6409087971\n2014-04-13 06:55:00,18.1741863114\n2014-04-13 07:00:00,21.0632163521\n2014-04-13 07:05:00,20.2898929118\n2014-04-13 07:10:00,19.701796466199998\n2014-04-13 07:15:00,20.976321776400003\n2014-04-13 07:20:00,21.863297697800004\n2014-04-13 07:25:00,18.9168248447\n2014-04-13 07:30:00,18.5745894603\n2014-04-13 07:35:00,21.6515269809\n2014-04-13 07:40:00,20.6758123098\n2014-04-13 07:45:00,19.751944086199998\n2014-04-13 07:50:00,20.2930382811\n2014-04-13 07:55:00,20.982455620699998\n2014-04-13 08:00:00,21.0921275948\n2014-04-13 08:05:00,21.6795767233\n2014-04-13 08:10:00,19.7073711556\n2014-04-13 08:15:00,19.1736436401\n2014-04-13 08:20:00,20.5586570672\n2014-04-13 08:25:00,19.6629115971\n2014-04-13 08:30:00,20.3783938158\n2014-04-13 08:35:00,19.6799431938\n2014-04-13 08:40:00,18.611983146700002\n2014-04-13 08:45:00,19.8777070066\n2014-04-13 08:50:00,20.7636712878\n2014-04-13 08:55:00,21.1971352307\n2014-04-13 09:00:00,67.9092373644\n2014-04-13 09:05:00,63.4472353069\n2014-04-13 09:10:00,66.8397528512\n2014-04-13 09:15:00,71.8935974322\n2014-04-13 09:20:00,66.8148860804\n2014-04-13 09:25:00,70.672818793\n2014-04-13 09:30:00,68.0981060708\n2014-04-13 09:35:00,64.48063450149999\n2014-04-13 09:40:00,72.0276469091\n2014-04-13 09:45:00,62.3453029754\n2014-04-13 09:50:00,68.3385078455\n2014-04-13 09:55:00,64.0409180657\n2014-04-13 10:00:00,70.880858555\n2014-04-13 10:05:00,77.6455347035\n2014-04-13 10:10:00,77.5932046601\n2014-04-13 10:15:00,80.811101994\n2014-04-13 10:20:00,81.3985307562\n2014-04-13 10:25:00,81.1353239045\n2014-04-13 10:30:00,76.1963515349\n2014-04-13 10:35:00,79.6438254978\n2014-04-13 10:40:00,78.7941901658\n2014-04-13 10:45:00,76.3826384549\n2014-04-13 10:50:00,79.1087410138\n2014-04-13 10:55:00,84.5412870465\n2014-04-13 11:00:00,74.63578209949999\n2014-04-13 11:05:00,85.9733994114\n2014-04-13 11:10:00,72.4181564944\n2014-04-13 11:15:00,76.472622042\n2014-04-13 11:20:00,76.1506620339\n2014-04-13 11:25:00,81.5297106757\n2014-04-13 11:30:00,73.6550016331\n2014-04-13 11:35:00,85.6008564187\n2014-04-13 11:40:00,84.7452816002\n2014-04-13 11:45:00,81.93845479630002\n2014-04-13 11:50:00,78.8586135808\n2014-04-13 11:55:00,86.4057328942\n2014-04-13 12:00:00,85.1895945417\n2014-04-13 12:05:00,79.8930555185\n2014-04-13 12:10:00,83.1300977029\n2014-04-13 12:15:00,80.97359417979999\n2014-04-13 12:20:00,81.3093873232\n2014-04-13 12:25:00,77.2028623705\n2014-04-13 12:30:00,79.29808164960002\n2014-04-13 12:35:00,73.1620429612\n2014-04-13 12:40:00,77.6243179718\n2014-04-13 12:45:00,83.0334963383\n2014-04-13 12:50:00,87.14675474030001\n2014-04-13 12:55:00,87.3041349732\n2014-04-13 13:00:00,80.8721519302\n2014-04-13 13:05:00,81.6863465995\n2014-04-13 13:10:00,74.9535457987\n2014-04-13 13:15:00,83.1049797464\n2014-04-13 13:20:00,73.112989353\n2014-04-13 13:25:00,76.53659777979999\n2014-04-13 13:30:00,82.6739670413\n2014-04-13 13:35:00,76.9464905138\n2014-04-13 13:40:00,72.7800785738\n2014-04-13 13:45:00,85.2894521672\n2014-04-13 13:50:00,76.9468084469\n2014-04-13 13:55:00,72.99216127369998\n2014-04-13 14:00:00,73.1930971947\n2014-04-13 14:05:00,76.0244914299\n2014-04-13 14:10:00,74.84466243930001\n2014-04-13 14:15:00,84.38475122199999\n2014-04-13 14:20:00,77.1432416933\n2014-04-13 14:25:00,84.8710585543\n2014-04-13 14:30:00,74.7779464514\n2014-04-13 14:35:00,79.8822323415\n2014-04-13 14:40:00,83.0046097243\n2014-04-13 14:45:00,82.4278969329\n2014-04-13 14:50:00,81.6141528915\n2014-04-13 14:55:00,86.7929793679\n2014-04-13 15:00:00,75.65567606180001\n2014-04-13 15:05:00,79.8987402361\n2014-04-13 15:10:00,86.1430538199\n2014-04-13 15:15:00,73.245597085\n2014-04-13 15:20:00,72.89351250760001\n2014-04-13 15:25:00,75.7321095657\n2014-04-13 15:30:00,82.1275510805\n2014-04-13 15:35:00,76.15734290569999\n2014-04-13 15:40:00,75.0431177201\n2014-04-13 15:45:00,79.3400753737\n2014-04-13 15:50:00,81.8167836516\n2014-04-13 15:55:00,75.9761939338\n2014-04-13 16:00:00,76.8109115103\n2014-04-13 16:05:00,81.8167917884\n2014-04-13 16:10:00,87.1316474587\n2014-04-13 16:15:00,82.7957086709\n2014-04-13 16:20:00,84.5263040065\n2014-04-13 16:25:00,77.8688120077\n2014-04-13 16:30:00,76.35592314649999\n2014-04-13 16:35:00,79.2681316961\n2014-04-13 16:40:00,84.91396222430001\n2014-04-13 16:45:00,79.3006420111\n2014-04-13 16:50:00,85.5474422892\n2014-04-13 16:55:00,87.820183076\n2014-04-13 17:00:00,73.1523985612\n2014-04-13 17:05:00,72.7265345703\n2014-04-13 17:10:00,74.3934066795\n2014-04-13 17:15:00,78.1498848022\n2014-04-13 17:20:00,74.0966468932\n2014-04-13 17:25:00,85.93059864450001\n2014-04-13 17:30:00,72.3703122262\n2014-04-13 17:35:00,77.0526538731\n2014-04-13 17:40:00,74.9550852891\n2014-04-13 17:45:00,86.9045959111\n2014-04-13 17:50:00,82.7116643169\n2014-04-13 17:55:00,86.59245085170002\n2014-04-13 18:00:00,35.022897021599995\n2014-04-13 18:05:00,31.981422619099998\n2014-04-13 18:10:00,30.299636474\n2014-04-13 18:15:00,30.039858464\n2014-04-13 18:20:00,30.2266749113\n2014-04-13 18:25:00,33.3349907685\n2014-04-13 18:30:00,29.0588470807\n2014-04-13 18:35:00,29.128705274699996\n2014-04-13 18:40:00,32.6921085544\n2014-04-13 18:45:00,32.9091594206\n2014-04-13 18:50:00,33.0576763686\n2014-04-13 18:55:00,31.180029242800003\n2014-04-13 19:00:00,23.7706317975\n2014-04-13 19:05:00,22.550636916\n2014-04-13 19:10:00,20.6324848906\n2014-04-13 19:15:00,23.7310035938\n2014-04-13 19:20:00,24.4297423423\n2014-04-13 19:25:00,20.4289615616\n2014-04-13 19:30:00,21.913252795300004\n2014-04-13 19:35:00,22.3440706551\n2014-04-13 19:40:00,20.8161878632\n2014-04-13 19:45:00,24.0473347669\n2014-04-13 19:50:00,21.4329892334\n2014-04-13 19:55:00,23.6678769606\n2014-04-13 20:00:00,21.1803931442\n2014-04-13 20:05:00,20.881595438199998\n2014-04-13 20:10:00,19.2190168776\n2014-04-13 20:15:00,19.336001388099998\n2014-04-13 20:20:00,18.625938842300002\n2014-04-13 20:25:00,19.4179578794\n2014-04-13 20:30:00,19.8469367862\n2014-04-13 20:35:00,21.8445629025\n2014-04-13 20:40:00,19.932744123699997\n2014-04-13 20:45:00,21.522930563899997\n2014-04-13 20:50:00,20.231955341400003\n2014-04-13 20:55:00,21.6468203462\n2014-04-13 21:00:00,22.010230762600003\n2014-04-13 21:05:00,19.0503711436\n2014-04-13 21:10:00,21.552323354099997\n2014-04-13 21:15:00,20.5856353173\n2014-04-13 21:20:00,21.3712690439\n2014-04-13 21:25:00,20.7052540078\n2014-04-13 21:30:00,19.7903378112\n2014-04-13 21:35:00,19.0030787501\n2014-04-13 21:40:00,18.3678855327\n2014-04-13 21:45:00,20.2387553609\n2014-04-13 21:50:00,22.0667185852\n2014-04-13 21:55:00,21.052737571199998\n2014-04-13 22:00:00,19.327919163\n2014-04-13 22:05:00,21.329275656300002\n2014-04-13 22:10:00,21.0961688889\n2014-04-13 22:15:00,19.1449046455\n2014-04-13 22:20:00,18.0745648911\n2014-04-13 22:25:00,18.4903842896\n2014-04-13 22:30:00,21.5298736064\n2014-04-13 22:35:00,21.3667445328\n2014-04-13 22:40:00,19.1992495966\n2014-04-13 22:45:00,19.1591568462\n2014-04-13 22:50:00,21.1917845396\n2014-04-13 22:55:00,21.7718307808\n2014-04-13 23:00:00,21.1206034025\n2014-04-13 23:05:00,20.426235790499998\n2014-04-13 23:10:00,18.9743277711\n2014-04-13 23:15:00,20.106851428800002\n2014-04-13 23:20:00,18.937682769600002\n2014-04-13 23:25:00,21.236122231099998\n2014-04-13 23:30:00,19.5515975023\n2014-04-13 23:35:00,21.3388851453\n2014-04-13 23:40:00,19.530185945899998\n2014-04-13 23:45:00,21.3006865654\n2014-04-13 23:50:00,19.3369832468\n2014-04-13 23:55:00,19.7643248384\n2014-04-14 00:00:00,20.4619536774\n2014-04-14 00:05:00,18.2811504561\n2014-04-14 00:10:00,21.7928282473\n2014-04-14 00:15:00,20.2944231445\n2014-04-14 00:20:00,20.0312800588\n2014-04-14 00:25:00,21.3575758845\n2014-04-14 00:30:00,21.4630509196\n2014-04-14 00:35:00,20.089041618099998\n2014-04-14 00:40:00,21.7090493032\n2014-04-14 00:45:00,18.2589510643\n2014-04-14 00:50:00,18.452903169000002\n2014-04-14 00:55:00,20.3871529201\n2014-04-14 01:00:00,19.4162634472\n2014-04-14 01:05:00,19.8569006648\n2014-04-14 01:10:00,19.3123168716\n2014-04-14 01:15:00,19.6189012458\n2014-04-14 01:20:00,21.2905853886\n2014-04-14 01:25:00,20.3739047994\n2014-04-14 01:30:00,21.9893781971\n2014-04-14 01:35:00,21.147516791300003\n2014-04-14 01:40:00,19.0946650164\n2014-04-14 01:45:00,19.0573804709\n2014-04-14 01:50:00,19.3435930805\n2014-04-14 01:55:00,21.3730379226\n2014-04-14 02:00:00,18.1091506026\n2014-04-14 02:05:00,18.920725115499998\n2014-04-14 02:10:00,21.6196736814\n2014-04-14 02:15:00,20.5595857443\n2014-04-14 02:20:00,18.907388382\n2014-04-14 02:25:00,18.8765798729\n2014-04-14 02:30:00,21.450472407\n2014-04-14 02:35:00,21.5750300331\n2014-04-14 02:40:00,19.0245243638\n2014-04-14 02:45:00,19.6820414323\n2014-04-14 02:50:00,21.338382954500002\n2014-04-14 02:55:00,21.0840297544\n2014-04-14 03:00:00,21.2556644263\n2014-04-14 03:05:00,20.0735927632\n2014-04-14 03:10:00,21.6461961932\n2014-04-14 03:15:00,19.3038061758\n2014-04-14 03:20:00,18.6266885374\n2014-04-14 03:25:00,20.8349293303\n2014-04-14 03:30:00,20.157417664\n2014-04-14 03:35:00,21.4183430752\n2014-04-14 03:40:00,18.3246369965\n2014-04-14 03:45:00,21.3747696138\n2014-04-14 03:50:00,19.1731786128\n2014-04-14 03:55:00,20.6194226687\n2014-04-14 04:00:00,18.1605151563\n2014-04-14 04:05:00,20.4383251852\n2014-04-14 04:10:00,20.8690867567\n2014-04-14 04:15:00,19.475000857999998\n2014-04-14 04:20:00,18.861642821\n2014-04-14 04:25:00,20.1505227064\n2014-04-14 04:30:00,21.3327632177\n2014-04-14 04:35:00,19.2941894332\n2014-04-14 04:40:00,19.0098771901\n2014-04-14 04:45:00,19.1157412346\n2014-04-14 04:50:00,21.7965286117\n2014-04-14 04:55:00,19.4371076631\n2014-04-14 05:00:00,18.014416959600002\n2014-04-14 05:05:00,21.1267248318\n2014-04-14 05:10:00,20.797099181300002\n2014-04-14 05:15:00,18.5142730584\n2014-04-14 05:20:00,21.9396169965\n2014-04-14 05:25:00,20.4322491412\n2014-04-14 05:30:00,20.0031179638\n2014-04-14 05:35:00,19.5288770705\n2014-04-14 05:40:00,21.5946910223\n2014-04-14 05:45:00,18.9758539257\n2014-04-14 05:50:00,19.143075600899998\n2014-04-14 05:55:00,18.4896432267\n2014-04-14 06:00:00,21.036476382300002\n2014-04-14 06:05:00,20.3821971216\n2014-04-14 06:10:00,20.436264677\n2014-04-14 06:15:00,18.873881724100002\n2014-04-14 06:20:00,20.6046735565\n2014-04-14 06:25:00,21.061833789\n2014-04-14 06:30:00,19.4315541229\n2014-04-14 06:35:00,21.2053885758\n2014-04-14 06:40:00,19.395162354100002\n2014-04-14 06:45:00,21.032553846\n2014-04-14 06:50:00,18.1349204298\n2014-04-14 06:55:00,20.2046584059\n2014-04-14 07:00:00,21.8781062426\n2014-04-14 07:05:00,21.9249784027\n2014-04-14 07:10:00,19.1270103134\n2014-04-14 07:15:00,19.765596364300002\n2014-04-14 07:20:00,18.2519116319\n2014-04-14 07:25:00,21.4933652304\n2014-04-14 07:30:00,20.2742886126\n2014-04-14 07:35:00,19.5404027158\n2014-04-14 07:40:00,18.451082234\n2014-04-14 07:45:00,21.787069141999996\n2014-04-14 07:50:00,20.120876191300002\n2014-04-14 07:55:00,19.1317117163\n2014-04-14 08:00:00,19.4008605205\n2014-04-14 08:05:00,19.0827887237\n2014-04-14 08:10:00,20.4072392354\n2014-04-14 08:15:00,21.7198543031\n2014-04-14 08:20:00,21.4267752133\n2014-04-14 08:25:00,19.8415235017\n2014-04-14 08:30:00,21.3059974492\n2014-04-14 08:35:00,19.6924219251\n2014-04-14 08:40:00,19.009228563\n2014-04-14 08:45:00,21.9336604611\n2014-04-14 08:50:00,19.2155502719\n2014-04-14 08:55:00,19.2948969239\n2014-04-14 09:00:00,74.6598230019\n2014-04-14 09:05:00,63.0214139071\n2014-04-14 09:10:00,71.54326223689999\n2014-04-14 09:15:00,73.9270535154\n2014-04-14 09:20:00,68.1604119221\n2014-04-14 09:25:00,61.234295959200004\n2014-04-14 09:30:00,66.3008016399\n2014-04-14 09:35:00,62.7173382964\n2014-04-14 09:40:00,66.8601521887\n2014-04-14 09:45:00,71.9443639583\n2014-04-14 09:50:00,67.16647706479999\n2014-04-14 09:55:00,67.07418165029999\n2014-04-14 10:00:00,78.4813726818\n2014-04-14 10:05:00,78.8678378753\n2014-04-14 10:10:00,83.1297187126\n2014-04-14 10:15:00,74.6256764168\n2014-04-14 10:20:00,82.592338023\n2014-04-14 10:25:00,78.6232917797\n2014-04-14 10:30:00,74.5042186116\n2014-04-14 10:35:00,74.420356203\n2014-04-14 10:40:00,75.4448542655\n2014-04-14 10:45:00,79.50419912550001\n2014-04-14 10:50:00,73.42219807069999\n2014-04-14 10:55:00,84.12357687720001\n2014-04-14 11:00:00,80.7114097388\n2014-04-14 11:05:00,86.1999309173\n2014-04-14 11:10:00,72.3060149188\n2014-04-14 11:15:00,77.0168912358\n2014-04-14 11:20:00,71.9307330356\n2014-04-14 11:25:00,75.8978928673\n2014-04-14 11:30:00,85.277350935\n2014-04-14 11:35:00,72.1502409208\n2014-04-14 11:40:00,78.5044834771\n2014-04-14 11:45:00,73.4377866888\n2014-04-14 11:50:00,78.1974338449\n2014-04-14 11:55:00,84.9090955961\n2014-04-14 12:00:00,81.87077357060001\n2014-04-14 12:05:00,83.6875558035\n2014-04-14 12:10:00,77.4925630482\n2014-04-14 12:15:00,87.00583068440002\n2014-04-14 12:20:00,83.2481756683\n2014-04-14 12:25:00,78.6542825712\n2014-04-14 12:30:00,78.7288486795\n2014-04-14 12:35:00,86.59490811090002\n2014-04-14 12:40:00,81.12500812489999\n2014-04-14 12:45:00,83.20210487760001\n2014-04-14 12:50:00,78.5781565159\n2014-04-14 12:55:00,75.48838933520001\n2014-04-14 13:00:00,83.5568902042\n2014-04-14 13:05:00,181.705566311\n2014-04-14 13:10:00,80.0022809301\n2014-04-14 13:15:00,81.9646587995\n2014-04-14 13:20:00,75.3144895604\n2014-04-14 13:25:00,84.6826905799\n2014-04-14 13:30:00,87.1496839352\n2014-04-14 13:35:00,86.2369484706\n2014-04-14 13:40:00,77.1244576117\n2014-04-14 13:45:00,78.4772533103\n2014-04-14 13:50:00,84.9140525319\n2014-04-14 13:55:00,81.5023088434\n2014-04-14 14:00:00,80.7627543005\n2014-04-14 14:05:00,86.8221038195\n2014-04-14 14:10:00,80.57253170850001\n2014-04-14 14:15:00,80.2351674005\n2014-04-14 14:20:00,72.66880919\n2014-04-14 14:25:00,73.10716202520001\n2014-04-14 14:30:00,72.11526322729999\n2014-04-14 14:35:00,86.607750241\n2014-04-14 14:40:00,78.53041691930001\n2014-04-14 14:45:00,79.493166163\n2014-04-14 14:50:00,85.5220859043\n2014-04-14 14:55:00,81.74401706479999\n2014-04-14 15:00:00,81.75124072279999\n2014-04-14 15:05:00,76.743814122\n2014-04-14 15:10:00,85.3417146945\n2014-04-14 15:15:00,74.6525629451\n2014-04-14 15:20:00,72.849694111\n2014-04-14 15:25:00,75.06493309\n2014-04-14 15:30:00,76.283063176\n2014-04-14 15:35:00,76.5162423627\n2014-04-14 15:40:00,82.727423387\n2014-04-14 15:45:00,75.4844687394\n2014-04-14 15:50:00,82.8257377372\n2014-04-14 15:55:00,73.4574095738\n2014-04-14 16:00:00,74.3550966155\n2014-04-14 16:05:00,80.1409893049\n2014-04-14 16:10:00,86.7501662806\n2014-04-14 16:15:00,85.7529167751\n2014-04-14 16:20:00,87.49988707899998\n2014-04-14 16:25:00,82.4075068217\n2014-04-14 16:30:00,82.8128788616\n2014-04-14 16:35:00,82.00021054220001\n2014-04-14 16:40:00,81.9649453927\n2014-04-14 16:45:00,74.3537827615\n2014-04-14 16:50:00,80.699668355\n2014-04-14 16:55:00,78.17693683520001\n2014-04-14 17:00:00,79.0805650855\n2014-04-14 17:05:00,80.37757830390001\n2014-04-14 17:10:00,74.054310312\n2014-04-14 17:15:00,77.7517738849\n2014-04-14 17:20:00,73.0151649362\n2014-04-14 17:25:00,87.6746564197\n2014-04-14 17:30:00,73.8964200849\n2014-04-14 17:35:00,76.13636658029999\n2014-04-14 17:40:00,86.26065370319998\n2014-04-14 17:45:00,79.7233301261\n2014-04-14 17:50:00,74.170166743\n2014-04-14 17:55:00,78.1476585999\n2014-04-14 18:00:00,29.541549490799998\n2014-04-14 18:05:00,30.0813766057\n2014-04-14 18:10:00,29.1329854269\n2014-04-14 18:15:00,31.604649896999998\n2014-04-14 18:20:00,33.9624646582\n2014-04-14 18:25:00,32.550196494\n2014-04-14 18:30:00,32.6806036804\n2014-04-14 18:35:00,30.0837320165\n2014-04-14 18:40:00,31.0009146446\n2014-04-14 18:45:00,34.2095428963\n2014-04-14 18:50:00,29.3622739421\n2014-04-14 18:55:00,34.2907495997\n2014-04-14 19:00:00,22.3269300929\n2014-04-14 19:05:00,23.9104191807\n2014-04-14 19:10:00,21.5846675748\n2014-04-14 19:15:00,21.6780152339\n2014-04-14 19:20:00,23.527188519499997\n2014-04-14 19:25:00,23.676781558000002\n2014-04-14 19:30:00,21.188806995\n2014-04-14 19:35:00,24.5184621902\n2014-04-14 19:40:00,20.5385145403\n2014-04-14 19:45:00,20.4668921519\n2014-04-14 19:50:00,22.827857632199997\n2014-04-14 19:55:00,23.3978773561\n2014-04-14 20:00:00,22.3677893169\n2014-04-14 20:05:00,20.0906576771\n2014-04-14 20:10:00,18.535593388800002\n2014-04-14 20:15:00,20.9014631556\n2014-04-14 20:20:00,19.6185946649\n2014-04-14 20:25:00,20.205351166\n2014-04-14 20:30:00,20.4327707541\n2014-04-14 20:35:00,18.6962434292\n2014-04-14 20:40:00,20.4225811445\n2014-04-14 20:45:00,20.1782051131\n2014-04-14 20:50:00,21.3505810544\n2014-04-14 20:55:00,21.0766473194\n2014-04-14 21:00:00,18.8308189683\n2014-04-14 21:05:00,18.9149134938\n2014-04-14 21:10:00,19.095243987\n2014-04-14 21:15:00,18.805637563599998\n2014-04-14 21:20:00,20.727871241400003\n2014-04-14 21:25:00,22.083213722199996\n2014-04-14 21:30:00,20.7073537916\n2014-04-14 21:35:00,20.524774420299998\n2014-04-14 21:40:00,19.7339823015\n2014-04-14 21:45:00,19.3427225291\n2014-04-14 21:50:00,21.7481875906\n2014-04-14 21:55:00,21.9810122788\n2014-04-14 22:00:00,20.006292313\n2014-04-14 22:05:00,19.1791963425\n2014-04-14 22:10:00,21.100726089600002\n2014-04-14 22:15:00,18.547615788399998\n2014-04-14 22:20:00,21.0825727991\n2014-04-14 22:25:00,21.2962182485\n2014-04-14 22:30:00,18.5173754006\n2014-04-14 22:35:00,21.9284770125\n2014-04-14 22:40:00,21.963113518000004\n2014-04-14 22:45:00,21.7677549094\n2014-04-14 22:50:00,20.0033240015\n2014-04-14 22:55:00,19.0025214845\n2014-04-14 23:00:00,20.3319401047\n2014-04-14 23:05:00,19.6835138611\n2014-04-14 23:10:00,18.8274087456\n2014-04-14 23:15:00,19.69848702\n2014-04-14 23:20:00,20.6595252081\n2014-04-14 23:25:00,18.2871637028\n2014-04-14 23:30:00,19.3373840689\n2014-04-14 23:35:00,18.0746492248\n2014-04-14 23:40:00,21.0020136323\n2014-04-14 23:45:00,20.5667131193\n2014-04-14 23:50:00,18.254192669200002\n2014-04-14 23:55:00,21.8631471547\n"
  },
  {
    "path": "workspace/anomaly_detector/datasets/selected/seasonal/art_daily_jumpsup_noised_trended.csv",
    "content": "timestamp,value\n2014-04-01 00:00:00,19.761251902999998\n2014-04-01 00:05:00,20.500833287\n2014-04-01 00:10:00,19.9616414445\n2014-04-01 00:15:00,21.4902660734\n2014-04-01 00:20:00,20.1877394098\n2014-04-01 00:25:00,19.9231256718\n2014-04-01 00:30:00,21.698403961700002\n2014-04-01 00:35:00,20.8787583842\n2014-04-01 00:40:00,18.4461996294\n2014-04-01 00:45:00,18.7108178448\n2014-04-01 00:50:00,21.148491451800002\n2014-04-01 00:55:00,21.3434052847\n2014-04-01 01:00:00,20.1807633164\n2014-04-01 01:05:00,20.217820911500002\n2014-04-01 01:10:00,20.527731851400002\n2014-04-01 01:15:00,19.7564630971\n2014-04-01 01:20:00,20.7207964939\n2014-04-01 01:25:00,18.4339250303\n2014-04-01 01:30:00,21.845116969499998\n2014-04-01 01:35:00,21.0006192952\n2014-04-01 01:40:00,20.524696816\n2014-04-01 01:45:00,19.265288228\n2014-04-01 01:50:00,18.6438219498\n2014-04-01 01:55:00,19.6373718553\n2014-04-01 02:00:00,20.6463069623\n2014-04-01 02:05:00,20.534838973699998\n2014-04-01 02:10:00,19.530564620299998\n2014-04-01 02:15:00,20.4531455753\n2014-04-01 02:20:00,21.2549931823\n2014-04-01 02:25:00,18.1051390894\n2014-04-01 02:30:00,19.8024841917\n2014-04-01 02:35:00,21.0342209139\n2014-04-01 02:40:00,20.1845778819\n2014-04-01 02:45:00,20.6059043517\n2014-04-01 02:50:00,20.0667055704\n2014-04-01 02:55:00,21.967498178699998\n2014-04-01 03:00:00,18.218486146\n2014-04-01 03:05:00,19.964179287100002\n2014-04-01 03:10:00,18.3656661965\n2014-04-01 03:15:00,18.6391422485\n2014-04-01 03:20:00,19.5321534017\n2014-04-01 03:25:00,18.622160366\n2014-04-01 03:30:00,21.854748663800002\n2014-04-01 03:35:00,21.7871591069\n2014-04-01 03:40:00,19.3444385849\n2014-04-01 03:45:00,20.5589908482\n2014-04-01 03:50:00,20.1350132824\n2014-04-01 03:55:00,21.262347922100002\n2014-04-01 04:00:00,20.5097824393\n2014-04-01 04:05:00,18.001009818\n2014-04-01 04:10:00,21.0526975424\n2014-04-01 04:15:00,20.9873924852\n2014-04-01 04:20:00,20.0388908223\n2014-04-01 04:25:00,21.6116758929\n2014-04-01 04:30:00,21.633784822800003\n2014-04-01 04:35:00,20.0956467068\n2014-04-01 04:40:00,20.4319529248\n2014-04-01 04:45:00,21.9860882877\n2014-04-01 04:50:00,19.1952809392\n2014-04-01 04:55:00,19.2984689692\n2014-04-01 05:00:00,18.7310956107\n2014-04-01 05:05:00,21.583467756599998\n2014-04-01 05:10:00,20.9779535598\n2014-04-01 05:15:00,18.4225713955\n2014-04-01 05:20:00,21.9270694048\n2014-04-01 05:25:00,20.9238468326\n2014-04-01 05:30:00,21.4020884384\n2014-04-01 05:35:00,18.192603156700002\n2014-04-01 05:40:00,20.0198436758\n2014-04-01 05:45:00,20.7943931469\n2014-04-01 05:50:00,20.1717863383\n2014-04-01 05:55:00,20.6665898628\n2014-04-01 06:00:00,21.2714962544\n2014-04-01 06:05:00,19.497348251800002\n2014-04-01 06:10:00,21.3946747025\n2014-04-01 06:15:00,18.6516644191\n2014-04-01 06:20:00,19.0835442201\n2014-04-01 06:25:00,18.1733824797\n2014-04-01 06:30:00,19.4577072453\n2014-04-01 06:35:00,19.5196381793\n2014-04-01 06:40:00,21.221082388800003\n2014-04-01 06:45:00,20.612522681199998\n2014-04-01 06:50:00,19.7468902326\n2014-04-01 06:55:00,20.608455914500002\n2014-04-01 07:00:00,18.2111334021\n2014-04-01 07:05:00,18.7210861441\n2014-04-01 07:10:00,20.507791421\n2014-04-01 07:15:00,20.5654672769\n2014-04-01 07:20:00,21.0965386348\n2014-04-01 07:25:00,19.6119990362\n2014-04-01 07:30:00,20.8902163865\n2014-04-01 07:35:00,20.7359213302\n2014-04-01 07:40:00,21.8535735135\n2014-04-01 07:45:00,18.8605209057\n2014-04-01 07:50:00,20.206718255\n2014-04-01 07:55:00,20.407057768399998\n2014-04-01 08:00:00,21.994591539699996\n2014-04-01 08:05:00,18.804736568699997\n2014-04-01 08:10:00,20.0928720799\n2014-04-01 08:15:00,19.384741230899998\n2014-04-01 08:20:00,20.103571874300002\n2014-04-01 08:25:00,18.928514408399998\n2014-04-01 08:30:00,18.1904495137\n2014-04-01 08:35:00,20.2902618156\n2014-04-01 08:40:00,19.3434172634\n2014-04-01 08:45:00,18.727765607000002\n2014-04-01 08:50:00,19.2957422643\n2014-04-01 08:55:00,18.1971208058\n2014-04-01 09:00:00,74.1260143836\n2014-04-01 09:05:00,69.10361164359999\n2014-04-01 09:10:00,72.2808540663\n2014-04-01 09:15:00,66.9544074866\n2014-04-01 09:20:00,73.4850794789\n2014-04-01 09:25:00,67.7731278131\n2014-04-01 09:30:00,69.0056563819\n2014-04-01 09:35:00,67.88839812890001\n2014-04-01 09:40:00,71.1725848238\n2014-04-01 09:45:00,68.9065226554\n2014-04-01 09:50:00,64.8937453607\n2014-04-01 09:55:00,63.179337626000006\n2014-04-01 10:00:00,79.2470505155\n2014-04-01 10:05:00,77.4320730032\n2014-04-01 10:10:00,71.3295428127\n2014-04-01 10:15:00,75.9799830691\n2014-04-01 10:20:00,77.8293300694\n2014-04-01 10:25:00,82.67338298899999\n2014-04-01 10:30:00,71.0210883865\n2014-04-01 10:35:00,75.2486478048\n2014-04-01 10:40:00,82.6076230245\n2014-04-01 10:45:00,79.90353942109999\n2014-04-01 10:50:00,74.3401531544\n2014-04-01 10:55:00,82.9596010938\n2014-04-01 11:00:00,79.41334110529999\n2014-04-01 11:05:00,79.4937884794\n2014-04-01 11:10:00,87.0996450426\n2014-04-01 11:15:00,86.6309408675\n2014-04-01 11:20:00,77.2701037963\n2014-04-01 11:25:00,73.8037704623\n2014-04-01 11:30:00,76.7474037102\n2014-04-01 11:35:00,72.052805772\n2014-04-01 11:40:00,71.8982924702\n2014-04-01 11:45:00,77.8583840549\n2014-04-01 11:50:00,86.5339792602\n2014-04-01 11:55:00,85.426067155\n2014-04-01 12:00:00,80.08686564029999\n2014-04-01 12:05:00,80.9463697522\n2014-04-01 12:10:00,72.0084220248\n2014-04-01 12:15:00,75.3574808711\n2014-04-01 12:20:00,72.3095103677\n2014-04-01 12:25:00,83.9717453641\n2014-04-01 12:30:00,74.2411363371\n2014-04-01 12:35:00,85.8016679353\n2014-04-01 12:40:00,82.194437192\n2014-04-01 12:45:00,75.5798939857\n2014-04-01 12:50:00,74.4340968432\n2014-04-01 12:55:00,81.94354482050001\n2014-04-01 13:00:00,86.3926524705\n2014-04-01 13:05:00,83.47372499939999\n2014-04-01 13:10:00,77.5581280065\n2014-04-01 13:15:00,81.3786019713\n2014-04-01 13:20:00,76.953713801\n2014-04-01 13:25:00,87.9652763341\n2014-04-01 13:30:00,83.9612714729\n2014-04-01 13:35:00,81.81046701060001\n2014-04-01 13:40:00,78.7532409691\n2014-04-01 13:45:00,81.8707829394\n2014-04-01 13:50:00,77.4472651938\n2014-04-01 13:55:00,72.4444465903\n2014-04-01 14:00:00,78.31765692970001\n2014-04-01 14:05:00,86.883522504\n2014-04-01 14:10:00,82.0168805171\n2014-04-01 14:15:00,73.3397707712\n2014-04-01 14:20:00,86.15576213920002\n2014-04-01 14:25:00,76.2983350936\n2014-04-01 14:30:00,75.89666867439999\n2014-04-01 14:35:00,76.7497713346\n2014-04-01 14:40:00,81.2313364867\n2014-04-01 14:45:00,80.7111351745\n2014-04-01 14:50:00,79.8587866682\n2014-04-01 14:55:00,83.4765827479\n2014-04-01 15:00:00,77.06386388119998\n2014-04-01 15:05:00,84.51222102\n2014-04-01 15:10:00,74.8044287246\n2014-04-01 15:15:00,84.5211212147\n2014-04-01 15:20:00,82.6201685228\n2014-04-01 15:25:00,82.930536812\n2014-04-01 15:30:00,79.7040891874\n2014-04-01 15:35:00,82.6712308715\n2014-04-01 15:40:00,73.2760492881\n2014-04-01 15:45:00,85.6239958745\n2014-04-01 15:50:00,72.8880560037\n2014-04-01 15:55:00,74.3791501112\n2014-04-01 16:00:00,81.228479377\n2014-04-01 16:05:00,83.83042233260001\n2014-04-01 16:10:00,73.2198844471\n2014-04-01 16:15:00,86.73207050010002\n2014-04-01 16:20:00,87.5775542316\n2014-04-01 16:25:00,81.69504591329998\n2014-04-01 16:30:00,79.6997422622\n2014-04-01 16:35:00,83.8621585408\n2014-04-01 16:40:00,77.2535693101\n2014-04-01 16:45:00,79.8920775526\n2014-04-01 16:50:00,86.6582500449\n2014-04-01 16:55:00,87.29031920610001\n2014-04-01 17:00:00,86.8330725129\n2014-04-01 17:05:00,76.19913981090001\n2014-04-01 17:10:00,75.7194755672\n2014-04-01 17:15:00,76.762602618\n2014-04-01 17:20:00,79.0609474388\n2014-04-01 17:25:00,77.02664902640001\n2014-04-01 17:30:00,77.98737478470001\n2014-04-01 17:35:00,81.93015977270001\n2014-04-01 17:40:00,84.20037850050001\n2014-04-01 17:45:00,83.768899005\n2014-04-01 17:50:00,85.0307444214\n2014-04-01 17:55:00,72.5149226057\n2014-04-01 18:00:00,29.105490665700003\n2014-04-01 18:05:00,33.8520444488\n2014-04-01 18:10:00,32.211698278200004\n2014-04-01 18:15:00,32.5000940721\n2014-04-01 18:20:00,29.1365503112\n2014-04-01 18:25:00,30.4340024842\n2014-04-01 18:30:00,32.8854612373\n2014-04-01 18:35:00,34.2987575113\n2014-04-01 18:40:00,34.6686870856\n2014-04-01 18:45:00,32.0026786288\n2014-04-01 18:50:00,32.2910288896\n2014-04-01 18:55:00,34.131511085599996\n2014-04-01 19:00:00,22.568556973299998\n2014-04-01 19:05:00,22.4755249615\n2014-04-01 19:10:00,24.2147751608\n2014-04-01 19:15:00,23.698897290300003\n2014-04-01 19:20:00,24.232643588800002\n2014-04-01 19:25:00,21.1377456459\n2014-04-01 19:30:00,22.5092009454\n2014-04-01 19:35:00,23.9342738231\n2014-04-01 19:40:00,20.6579411338\n2014-04-01 19:45:00,23.72008515\n2014-04-01 19:50:00,20.9797196068\n2014-04-01 19:55:00,23.7803707178\n2014-04-01 20:00:00,20.938755589\n2014-04-01 20:05:00,19.2234943904\n2014-04-01 20:10:00,20.3708584741\n2014-04-01 20:15:00,21.2250833071\n2014-04-01 20:20:00,21.0282612297\n2014-04-01 20:25:00,20.1820042736\n2014-04-01 20:30:00,22.1158050371\n2014-04-01 20:35:00,20.558902699\n2014-04-01 20:40:00,20.5040322087\n2014-04-01 20:45:00,18.6869781922\n2014-04-01 20:50:00,22.2090048501\n2014-04-01 20:55:00,19.1574692354\n2014-04-01 21:00:00,20.2099229424\n2014-04-01 21:05:00,21.3160988514\n2014-04-01 21:10:00,18.9523497644\n2014-04-01 21:15:00,20.2060186776\n2014-04-01 21:20:00,19.0537607405\n2014-04-01 21:25:00,21.1397660835\n2014-04-01 21:30:00,20.3545999721\n2014-04-01 21:35:00,21.526738125399998\n2014-04-01 21:40:00,21.6818074721\n2014-04-01 21:45:00,20.693789562\n2014-04-01 21:50:00,21.0018924452\n2014-04-01 21:55:00,20.2938253758\n2014-04-01 22:00:00,19.556471129000002\n2014-04-01 22:05:00,20.6122404548\n2014-04-01 22:10:00,21.6539223116\n2014-04-01 22:15:00,19.6856015647\n2014-04-01 22:20:00,19.2761274305\n2014-04-01 22:25:00,19.5725193424\n2014-04-01 22:30:00,19.760542437999998\n2014-04-01 22:35:00,18.3118065813\n2014-04-01 22:40:00,20.0129613686\n2014-04-01 22:45:00,19.9964351491\n2014-04-01 22:50:00,20.3733149249\n2014-04-01 22:55:00,19.4699533412\n2014-04-01 23:00:00,20.4563572484\n2014-04-01 23:05:00,21.516995709099998\n2014-04-01 23:10:00,21.8260737616\n2014-04-01 23:15:00,20.338353076700002\n2014-04-01 23:20:00,18.173852523900003\n2014-04-01 23:25:00,21.8811443602\n2014-04-01 23:30:00,20.8274463436\n2014-04-01 23:35:00,19.3475686124\n2014-04-01 23:40:00,18.5921998191\n2014-04-01 23:45:00,18.5772405926\n2014-04-01 23:50:00,18.6745624504\n2014-04-01 23:55:00,18.185781084400002\n2014-04-02 00:00:00,21.6086167546\n2014-04-02 00:05:00,20.1630729313\n2014-04-02 00:10:00,20.7998376509\n2014-04-02 00:15:00,21.3124340371\n2014-04-02 00:20:00,21.1661640253\n2014-04-02 00:25:00,21.530422494899998\n2014-04-02 00:30:00,21.869018490100004\n2014-04-02 00:35:00,19.756282459\n2014-04-02 00:40:00,21.8013418667\n2014-04-02 00:45:00,20.8931597934\n2014-04-02 00:50:00,18.2826727612\n2014-04-02 00:55:00,20.7271324848\n2014-04-02 01:00:00,20.7468666384\n2014-04-02 01:05:00,21.6234422552\n2014-04-02 01:10:00,19.4917285299\n2014-04-02 01:15:00,20.3396460011\n2014-04-02 01:20:00,18.048750204\n2014-04-02 01:25:00,19.3283009687\n2014-04-02 01:30:00,18.2489749046\n2014-04-02 01:35:00,20.087491891099997\n2014-04-02 01:40:00,21.269790602\n2014-04-02 01:45:00,18.8257707685\n2014-04-02 01:50:00,20.1097641822\n2014-04-02 01:55:00,18.816034545999997\n2014-04-02 02:00:00,18.4827538714\n2014-04-02 02:05:00,20.0439871677\n2014-04-02 02:10:00,18.3165944838\n2014-04-02 02:15:00,20.3494185246\n2014-04-02 02:20:00,18.1253498427\n2014-04-02 02:25:00,18.4268598875\n2014-04-02 02:30:00,20.1999899419\n2014-04-02 02:35:00,20.365629651600003\n2014-04-02 02:40:00,18.1159477204\n2014-04-02 02:45:00,20.293507152\n2014-04-02 02:50:00,21.354010101300002\n2014-04-02 02:55:00,20.8892647092\n2014-04-02 03:00:00,18.5247404157\n2014-04-02 03:05:00,20.3698985903\n2014-04-02 03:10:00,20.6890100003\n2014-04-02 03:15:00,18.148924807\n2014-04-02 03:20:00,21.4213906747\n2014-04-02 03:25:00,21.625069589200002\n2014-04-02 03:30:00,21.4018090934\n2014-04-02 03:35:00,21.298525872\n2014-04-02 03:40:00,20.9798607938\n2014-04-02 03:45:00,20.5337281251\n2014-04-02 03:50:00,20.71450802\n2014-04-02 03:55:00,21.2255811733\n2014-04-02 04:00:00,20.6499938334\n2014-04-02 04:05:00,19.3109078267\n2014-04-02 04:10:00,19.5038444086\n2014-04-02 04:15:00,21.588229873499998\n2014-04-02 04:20:00,18.0684883432\n2014-04-02 04:25:00,20.795282325\n2014-04-02 04:30:00,21.819110209699996\n2014-04-02 04:35:00,20.8249126798\n2014-04-02 04:40:00,21.9756479529\n2014-04-02 04:45:00,20.7501796221\n2014-04-02 04:50:00,18.1374521169\n2014-04-02 04:55:00,21.308039526600002\n2014-04-02 05:00:00,19.1385196478\n2014-04-02 05:05:00,19.7842289027\n2014-04-02 05:10:00,19.2483676636\n2014-04-02 05:15:00,19.0742164248\n2014-04-02 05:20:00,19.7256228147\n2014-04-02 05:25:00,19.5150057938\n2014-04-02 05:30:00,20.5333543274\n2014-04-02 05:35:00,21.252604804\n2014-04-02 05:40:00,19.1883546127\n2014-04-02 05:45:00,18.8548846113\n2014-04-02 05:50:00,20.6675810835\n2014-04-02 05:55:00,20.6812802633\n2014-04-02 06:00:00,21.6045249571\n2014-04-02 06:05:00,18.063782745799998\n2014-04-02 06:10:00,21.4121626485\n2014-04-02 06:15:00,20.0840086918\n2014-04-02 06:20:00,20.4852083567\n2014-04-02 06:25:00,18.3654857622\n2014-04-02 06:30:00,19.7304597315\n2014-04-02 06:35:00,18.909209629\n2014-04-02 06:40:00,19.0169001203\n2014-04-02 06:45:00,20.0163804587\n2014-04-02 06:50:00,21.2498238016\n2014-04-02 06:55:00,20.9751237206\n2014-04-02 07:00:00,20.3639998363\n2014-04-02 07:05:00,20.157672770999998\n2014-04-02 07:10:00,19.7092241729\n2014-04-02 07:15:00,21.8908398942\n2014-04-02 07:20:00,20.2407702169\n2014-04-02 07:25:00,19.0158655932\n2014-04-02 07:30:00,18.920363168199998\n2014-04-02 07:35:00,20.4454121231\n2014-04-02 07:40:00,20.091310109200002\n2014-04-02 07:45:00,18.0307912118\n2014-04-02 07:50:00,21.3202614888\n2014-04-02 07:55:00,20.8164894169\n2014-04-02 08:00:00,20.647317158699998\n2014-04-02 08:05:00,18.2751226308\n2014-04-02 08:10:00,19.448223400699998\n2014-04-02 08:15:00,21.741529042899998\n2014-04-02 08:20:00,21.4503569654\n2014-04-02 08:25:00,19.1421717515\n2014-04-02 08:30:00,18.628235536400002\n2014-04-02 08:35:00,19.796351828699997\n2014-04-02 08:40:00,19.4233215147\n2014-04-02 08:45:00,20.7289055068\n2014-04-02 08:50:00,21.8657392403\n2014-04-02 08:55:00,19.4520057999\n2014-04-02 09:00:00,62.046248748100005\n2014-04-02 09:05:00,73.4075505135\n2014-04-02 09:10:00,61.7161163313\n2014-04-02 09:15:00,74.1576162013\n2014-04-02 09:20:00,70.2382802209\n2014-04-02 09:25:00,74.0069732348\n2014-04-02 09:30:00,63.91537173840001\n2014-04-02 09:35:00,61.753517215500004\n2014-04-02 09:40:00,67.8396557046\n2014-04-02 09:45:00,67.3284784382\n2014-04-02 09:50:00,65.7082949163\n2014-04-02 09:55:00,74.2241280517\n2014-04-02 10:00:00,82.6064995231\n2014-04-02 10:05:00,80.1077529717\n2014-04-02 10:10:00,72.3675606862\n2014-04-02 10:15:00,81.2366992956\n2014-04-02 10:20:00,81.1232332969\n2014-04-02 10:25:00,76.4370580545\n2014-04-02 10:30:00,84.1926773188\n2014-04-02 10:35:00,72.4314967322\n2014-04-02 10:40:00,73.9890789686\n2014-04-02 10:45:00,70.8212417452\n2014-04-02 10:50:00,82.1853988709\n2014-04-02 10:55:00,79.4897056722\n2014-04-02 11:00:00,76.5768106216\n2014-04-02 11:05:00,74.1732925058\n2014-04-02 11:10:00,72.2065101345\n2014-04-02 11:15:00,74.2199215234\n2014-04-02 11:20:00,78.77703901539998\n2014-04-02 11:25:00,75.4991025151\n2014-04-02 11:30:00,75.6868525499\n2014-04-02 11:35:00,85.4931665355\n2014-04-02 11:40:00,79.7607495587\n2014-04-02 11:45:00,83.16602338060001\n2014-04-02 11:50:00,72.1359469333\n2014-04-02 11:55:00,77.3755580087\n2014-04-02 12:00:00,79.5711095069\n2014-04-02 12:05:00,74.89269047970001\n2014-04-02 12:10:00,73.83435698550001\n2014-04-02 12:15:00,85.82175062350001\n2014-04-02 12:20:00,86.92646894639999\n2014-04-02 12:25:00,73.1729940801\n2014-04-02 12:30:00,77.4911982414\n2014-04-02 12:35:00,87.22777096629999\n2014-04-02 12:40:00,73.24259102479999\n2014-04-02 12:45:00,82.1995040517\n2014-04-02 12:50:00,87.4504752851\n2014-04-02 12:55:00,87.5463968029\n2014-04-02 13:00:00,79.5204837969\n2014-04-02 13:05:00,74.5860807679\n2014-04-02 13:10:00,75.2152930359\n2014-04-02 13:15:00,86.2129262526\n2014-04-02 13:20:00,86.56614720649998\n2014-04-02 13:25:00,81.7064600441\n2014-04-02 13:30:00,84.2386002741\n2014-04-02 13:35:00,83.8187786875\n2014-04-02 13:40:00,82.5693241729\n2014-04-02 13:45:00,85.21597453439999\n2014-04-02 13:50:00,82.9465940072\n2014-04-02 13:55:00,80.5247063231\n2014-04-02 14:00:00,75.7876638189\n2014-04-02 14:05:00,83.8981829998\n2014-04-02 14:10:00,79.5711862851\n2014-04-02 14:15:00,76.7129845441\n2014-04-02 14:20:00,84.8270685171\n2014-04-02 14:25:00,83.1434265296\n2014-04-02 14:30:00,86.9932571332\n2014-04-02 14:35:00,74.6434831811\n2014-04-02 14:40:00,82.3830739768\n2014-04-02 14:45:00,75.90418791350001\n2014-04-02 14:50:00,86.4531778131\n2014-04-02 14:55:00,73.5884582126\n2014-04-02 15:00:00,82.4977969167\n2014-04-02 15:05:00,84.6565588337\n2014-04-02 15:10:00,77.6779397305\n2014-04-02 15:15:00,87.2653715145\n2014-04-02 15:20:00,85.61086908109999\n2014-04-02 15:25:00,76.7131563416\n2014-04-02 15:30:00,72.11996512510001\n2014-04-02 15:35:00,76.74577805130002\n2014-04-02 15:40:00,76.5002331182\n2014-04-02 15:45:00,86.2386058215\n2014-04-02 15:50:00,87.4730991023\n2014-04-02 15:55:00,73.1263377559\n2014-04-02 16:00:00,79.5405645384\n2014-04-02 16:05:00,80.7731568917\n2014-04-02 16:10:00,73.486445487\n2014-04-02 16:15:00,78.0398135095\n2014-04-02 16:20:00,77.0731706975\n2014-04-02 16:25:00,80.5767469616\n2014-04-02 16:30:00,82.5788958439\n2014-04-02 16:35:00,83.25560191689999\n2014-04-02 16:40:00,74.1879379367\n2014-04-02 16:45:00,85.0070000174\n2014-04-02 16:50:00,82.85651339180001\n2014-04-02 16:55:00,86.2250331156\n2014-04-02 17:00:00,79.1893465422\n2014-04-02 17:05:00,86.3022030635\n2014-04-02 17:10:00,85.8523529904\n2014-04-02 17:15:00,79.0145189762\n2014-04-02 17:20:00,178.0982630549\n2014-04-02 17:25:00,86.92495886030001\n2014-04-02 17:30:00,83.44260371060001\n2014-04-02 17:35:00,86.8518921919\n2014-04-02 17:40:00,84.75156391770001\n2014-04-02 17:45:00,81.7487276371\n2014-04-02 17:50:00,73.8536160723\n2014-04-02 17:55:00,76.6636613224\n2014-04-02 18:00:00,35.000584685300005\n2014-04-02 18:05:00,30.844295509699997\n2014-04-02 18:10:00,29.396825522399997\n2014-04-02 18:15:00,33.3283350788\n2014-04-02 18:20:00,33.4976207975\n2014-04-02 18:25:00,30.626923529499997\n2014-04-02 18:30:00,30.7050947724\n2014-04-02 18:35:00,31.80090900150001\n2014-04-02 18:40:00,28.939443722100002\n2014-04-02 18:45:00,33.851660766799995\n2014-04-02 18:50:00,30.8293623193\n2014-04-02 18:55:00,34.264077274099996\n2014-04-02 19:00:00,23.7557829856\n2014-04-02 19:05:00,23.123079839899997\n2014-04-02 19:10:00,21.6154382188\n2014-04-02 19:15:00,22.473096963400003\n2014-04-02 19:20:00,22.1528338588\n2014-04-02 19:25:00,21.678189661199998\n2014-04-02 19:30:00,23.9596492617\n2014-04-02 19:35:00,22.3261104694\n2014-04-02 19:40:00,23.890598167600004\n2014-04-02 19:45:00,20.6313776324\n2014-04-02 19:50:00,20.7917899124\n2014-04-02 19:55:00,24.5383936208\n2014-04-02 20:00:00,20.8394993728\n2014-04-02 20:05:00,20.5200163364\n2014-04-02 20:10:00,20.5748469877\n2014-04-02 20:15:00,19.3137406667\n2014-04-02 20:20:00,21.3758111207\n2014-04-02 20:25:00,18.7792612094\n2014-04-02 20:30:00,20.7803336795\n2014-04-02 20:35:00,20.7698687416\n2014-04-02 20:40:00,22.176515519099997\n2014-04-02 20:45:00,20.5872445431\n2014-04-02 20:50:00,18.9934085748\n2014-04-02 20:55:00,20.7779971005\n2014-04-02 21:00:00,18.4534640231\n2014-04-02 21:05:00,18.905488136600002\n2014-04-02 21:10:00,18.211431577\n2014-04-02 21:15:00,20.1494295173\n2014-04-02 21:20:00,18.4261534423\n2014-04-02 21:25:00,19.972989837300002\n2014-04-02 21:30:00,21.836092632600003\n2014-04-02 21:35:00,20.9792650199\n2014-04-02 21:40:00,18.397532956\n2014-04-02 21:45:00,18.9875440308\n2014-04-02 21:50:00,20.7939839472\n2014-04-02 21:55:00,21.6823856668\n2014-04-02 22:00:00,18.1490807455\n2014-04-02 22:05:00,21.270204328800002\n2014-04-02 22:10:00,20.266692876700002\n2014-04-02 22:15:00,20.203742282\n2014-04-02 22:20:00,21.8522107229\n2014-04-02 22:25:00,21.0107293954\n2014-04-02 22:30:00,21.4210199182\n2014-04-02 22:35:00,19.4346216116\n2014-04-02 22:40:00,20.2368649113\n2014-04-02 22:45:00,20.4812658575\n2014-04-02 22:50:00,19.3048506343\n2014-04-02 22:55:00,20.3004622426\n2014-04-02 23:00:00,18.9502592674\n2014-04-02 23:05:00,18.577068795\n2014-04-02 23:10:00,19.4996242444\n2014-04-02 23:15:00,20.9611822874\n2014-04-02 23:20:00,21.6689082219\n2014-04-02 23:25:00,19.8346637284\n2014-04-02 23:30:00,20.5752444397\n2014-04-02 23:35:00,18.4156836546\n2014-04-02 23:40:00,21.6220056603\n2014-04-02 23:45:00,20.2783095403\n2014-04-02 23:50:00,21.1254082882\n2014-04-02 23:55:00,21.1818309324\n2014-04-03 00:00:00,19.0259221055\n2014-04-03 00:05:00,20.1166978127\n2014-04-03 00:10:00,21.841919006199998\n2014-04-03 00:15:00,18.3585381793\n2014-04-03 00:20:00,20.7321995921\n2014-04-03 00:25:00,21.8490563121\n2014-04-03 00:30:00,19.2023084322\n2014-04-03 00:35:00,21.4457916856\n2014-04-03 00:40:00,21.7346301816\n2014-04-03 00:45:00,20.9883448376\n2014-04-03 00:50:00,18.925313249200002\n2014-04-03 00:55:00,19.3360028753\n2014-04-03 01:00:00,18.1432371777\n2014-04-03 01:05:00,21.325812937000002\n2014-04-03 01:10:00,21.398444746\n2014-04-03 01:15:00,20.5308412399\n2014-04-03 01:20:00,19.4101114051\n2014-04-03 01:25:00,18.3072441106\n2014-04-03 01:30:00,21.0122304397\n2014-04-03 01:35:00,20.9061047744\n2014-04-03 01:40:00,21.650410086999997\n2014-04-03 01:45:00,20.922128084\n2014-04-03 01:50:00,21.314779769\n2014-04-03 01:55:00,20.9838184716\n2014-04-03 02:00:00,20.5227487532\n2014-04-03 02:05:00,19.7078655768\n2014-04-03 02:10:00,21.6084692346\n2014-04-03 02:15:00,20.6038742876\n2014-04-03 02:20:00,19.5934212879\n2014-04-03 02:25:00,18.3338771807\n2014-04-03 02:30:00,19.1628194236\n2014-04-03 02:35:00,20.1749069393\n2014-04-03 02:40:00,19.1025414801\n2014-04-03 02:45:00,18.8849413917\n2014-04-03 02:50:00,20.1095740564\n2014-04-03 02:55:00,18.6792813836\n2014-04-03 03:00:00,21.2016402533\n2014-04-03 03:05:00,19.9374726054\n2014-04-03 03:10:00,20.2954510959\n2014-04-03 03:15:00,18.589533070399998\n2014-04-03 03:20:00,19.2983053425\n2014-04-03 03:25:00,19.640358733\n2014-04-03 03:30:00,21.2328513221\n2014-04-03 03:35:00,21.0806380923\n2014-04-03 03:40:00,18.8919098992\n2014-04-03 03:45:00,20.4647163264\n2014-04-03 03:50:00,18.9738254311\n2014-04-03 03:55:00,21.952988622800003\n2014-04-03 04:00:00,21.8084955125\n2014-04-03 04:05:00,20.2530588821\n2014-04-03 04:10:00,20.7956102876\n2014-04-03 04:15:00,21.2057215288\n2014-04-03 04:20:00,20.8839936802\n2014-04-03 04:25:00,20.7993147643\n2014-04-03 04:30:00,21.834216031799997\n2014-04-03 04:35:00,20.3858244252\n2014-04-03 04:40:00,20.5452106873\n2014-04-03 04:45:00,21.3970750018\n2014-04-03 04:50:00,20.6795634714\n2014-04-03 04:55:00,20.931730488099998\n2014-04-03 05:00:00,18.9366747448\n2014-04-03 05:05:00,19.4850676965\n2014-04-03 05:10:00,18.5892053828\n2014-04-03 05:15:00,20.0230617693\n2014-04-03 05:20:00,19.8229096027\n2014-04-03 05:25:00,21.9886512571\n2014-04-03 05:30:00,20.444834611300003\n2014-04-03 05:35:00,21.1457792928\n2014-04-03 05:40:00,19.336058683\n2014-04-03 05:45:00,21.3261813254\n2014-04-03 05:50:00,20.460339865999998\n2014-04-03 05:55:00,20.787969326400003\n2014-04-03 06:00:00,19.177723111800002\n2014-04-03 06:05:00,20.1945535668\n2014-04-03 06:10:00,20.536147893699997\n2014-04-03 06:15:00,20.3563787033\n2014-04-03 06:20:00,21.6607748457\n2014-04-03 06:25:00,21.593090658\n2014-04-03 06:30:00,21.8839362315\n2014-04-03 06:35:00,20.669712024000003\n2014-04-03 06:40:00,21.887656520500002\n2014-04-03 06:45:00,21.3299120001\n2014-04-03 06:50:00,19.083328561400002\n2014-04-03 06:55:00,19.709742678199998\n2014-04-03 07:00:00,18.9535697688\n2014-04-03 07:05:00,18.0167886433\n2014-04-03 07:10:00,18.7521950126\n2014-04-03 07:15:00,18.0162423451\n2014-04-03 07:20:00,20.8793538454\n2014-04-03 07:25:00,19.7021371909\n2014-04-03 07:30:00,19.2502989083\n2014-04-03 07:35:00,21.0468835644\n2014-04-03 07:40:00,21.3299470985\n2014-04-03 07:45:00,21.9011981546\n2014-04-03 07:50:00,20.568054338699998\n2014-04-03 07:55:00,19.8461158342\n2014-04-03 08:00:00,19.2210572064\n2014-04-03 08:05:00,18.889272836900002\n2014-04-03 08:10:00,18.8517038019\n2014-04-03 08:15:00,19.6367574989\n2014-04-03 08:20:00,21.967145421199998\n2014-04-03 08:25:00,18.0034147897\n2014-04-03 08:30:00,18.7888235889\n2014-04-03 08:35:00,18.7535719296\n2014-04-03 08:40:00,20.8684779421\n2014-04-03 08:45:00,19.4099389104\n2014-04-03 08:50:00,19.8290432184\n2014-04-03 08:55:00,18.594496521900002\n2014-04-03 09:00:00,66.7079597287\n2014-04-03 09:05:00,62.603517441899996\n2014-04-03 09:10:00,68.4493887153\n2014-04-03 09:15:00,62.5319617692\n2014-04-03 09:20:00,71.950913984\n2014-04-03 09:25:00,68.90578335859999\n2014-04-03 09:30:00,71.0459630833\n2014-04-03 09:35:00,66.8918228585\n2014-04-03 09:40:00,66.3882815881\n2014-04-03 09:45:00,62.535640891099995\n2014-04-03 09:50:00,68.3244362558\n2014-04-03 09:55:00,68.1972294421\n2014-04-03 10:00:00,77.1049437299\n2014-04-03 10:05:00,81.33284501989999\n2014-04-03 10:10:00,82.76046828850001\n2014-04-03 10:15:00,81.4922557552\n2014-04-03 10:20:00,72.0727963284\n2014-04-03 10:25:00,79.4943635841\n2014-04-03 10:30:00,71.0866146003\n2014-04-03 10:35:00,80.6205379011\n2014-04-03 10:40:00,75.7661427786\n2014-04-03 10:45:00,71.8963838013\n2014-04-03 10:50:00,83.2190293003\n2014-04-03 10:55:00,79.3694094219\n2014-04-03 11:00:00,77.2095458902\n2014-04-03 11:05:00,72.0566850652\n2014-04-03 11:10:00,80.1133823592\n2014-04-03 11:15:00,86.2509843714\n2014-04-03 11:20:00,81.0528248593\n2014-04-03 11:25:00,87.0211312159\n2014-04-03 11:30:00,73.738118585\n2014-04-03 11:35:00,80.60632438350001\n2014-04-03 11:40:00,84.2613807635\n2014-04-03 11:45:00,79.9261997878\n2014-04-03 11:50:00,73.01631932560001\n2014-04-03 11:55:00,80.8382189686\n2014-04-03 12:00:00,81.6896611257\n2014-04-03 12:05:00,83.55895675800001\n2014-04-03 12:10:00,84.0783689816\n2014-04-03 12:15:00,84.2311641758\n2014-04-03 12:20:00,82.5159721659\n2014-04-03 12:25:00,75.3624354079\n2014-04-03 12:30:00,78.3736107669\n2014-04-03 12:35:00,84.3167778664\n2014-04-03 12:40:00,87.15012593629999\n2014-04-03 12:45:00,73.17523565569999\n2014-04-03 12:50:00,80.4719045405\n2014-04-03 12:55:00,76.90795591359999\n2014-04-03 13:00:00,75.5881567965\n2014-04-03 13:05:00,80.0737486233\n2014-04-03 13:10:00,81.6778220658\n2014-04-03 13:15:00,72.1390381773\n2014-04-03 13:20:00,84.463029162\n2014-04-03 13:25:00,85.0976857528\n2014-04-03 13:30:00,87.4271856315\n2014-04-03 13:35:00,74.8723260597\n2014-04-03 13:40:00,81.4932779159\n2014-04-03 13:45:00,78.8070877342\n2014-04-03 13:50:00,77.3386798859\n2014-04-03 13:55:00,81.0306831905\n2014-04-03 14:00:00,84.5140726214\n2014-04-03 14:05:00,72.3653708306\n2014-04-03 14:10:00,87.5062013018\n2014-04-03 14:15:00,84.9540273822\n2014-04-03 14:20:00,84.0144263723\n2014-04-03 14:25:00,84.1621581374\n2014-04-03 14:30:00,78.2212165553\n2014-04-03 14:35:00,84.0218955689\n2014-04-03 14:40:00,78.1845702981\n2014-04-03 14:45:00,86.37516306639999\n2014-04-03 14:50:00,74.83196602609999\n2014-04-03 14:55:00,76.6738782646\n2014-04-03 15:00:00,80.8206247977\n2014-04-03 15:05:00,77.1066363434\n2014-04-03 15:10:00,78.7870395619\n2014-04-03 15:15:00,79.8779961943\n2014-04-03 15:20:00,85.7008308451\n2014-04-03 15:25:00,80.3703044954\n2014-04-03 15:30:00,77.798610704\n2014-04-03 15:35:00,75.96304937229999\n2014-04-03 15:40:00,78.538061688\n2014-04-03 15:45:00,80.2510072536\n2014-04-03 15:50:00,83.937031912\n2014-04-03 15:55:00,73.9360706257\n2014-04-03 16:00:00,75.545601964\n2014-04-03 16:05:00,78.0743143509\n2014-04-03 16:10:00,77.76622517050001\n2014-04-03 16:15:00,78.2678191272\n2014-04-03 16:20:00,84.6961776173\n2014-04-03 16:25:00,77.18632224939999\n2014-04-03 16:30:00,80.0302172281\n2014-04-03 16:35:00,81.98235511930001\n2014-04-03 16:40:00,75.7147114304\n2014-04-03 16:45:00,83.498965876\n2014-04-03 16:50:00,80.7536260686\n2014-04-03 16:55:00,79.1483466434\n2014-04-03 17:00:00,84.9565118045\n2014-04-03 17:05:00,75.8958950029\n2014-04-03 17:10:00,86.1307824556\n2014-04-03 17:15:00,80.97674867079998\n2014-04-03 17:20:00,81.74676667930001\n2014-04-03 17:25:00,86.0009104023\n2014-04-03 17:30:00,85.0812903344\n2014-04-03 17:35:00,81.6249617572\n2014-04-03 17:40:00,84.05097098600001\n2014-04-03 17:45:00,78.9330815334\n2014-04-03 17:50:00,80.7580130449\n2014-04-03 17:55:00,72.993094158\n2014-04-03 18:00:00,29.3750850352\n2014-04-03 18:05:00,34.108316038000005\n2014-04-03 18:10:00,29.1818929934\n2014-04-03 18:15:00,29.8841486663\n2014-04-03 18:20:00,33.8933225098\n2014-04-03 18:25:00,28.807328553\n2014-04-03 18:30:00,30.607381828\n2014-04-03 18:35:00,32.5378411628\n2014-04-03 18:40:00,32.6108733001\n2014-04-03 18:45:00,33.7737721281\n2014-04-03 18:50:00,32.0379218775\n2014-04-03 18:55:00,32.0601658094\n2014-04-03 19:00:00,23.409390094299997\n2014-04-03 19:05:00,22.393836367\n2014-04-03 19:10:00,22.8860388123\n2014-04-03 19:15:00,24.1820264992\n2014-04-03 19:20:00,21.9584993095\n2014-04-03 19:25:00,21.885359117100002\n2014-04-03 19:30:00,20.1758983768\n2014-04-03 19:35:00,22.908148394899996\n2014-04-03 19:40:00,20.2933770319\n2014-04-03 19:45:00,22.4185840042\n2014-04-03 19:50:00,23.76296607130001\n2014-04-03 19:55:00,22.623645154899997\n2014-04-03 20:00:00,19.5364294983\n2014-04-03 20:05:00,21.6521455944\n2014-04-03 20:10:00,19.5367606143\n2014-04-03 20:15:00,80.0000000000\n2014-04-03 20:20:00,20.9316183813\n2014-04-03 20:25:00,19.128304601900002\n2014-04-03 20:30:00,22.1394280857\n2014-04-03 20:35:00,19.2538362943\n2014-04-03 20:40:00,22.4853483859\n2014-04-03 20:45:00,18.46194354\n2014-04-03 20:50:00,19.511227678599997\n2014-04-03 20:55:00,19.2506275466\n2014-04-03 21:00:00,18.1426422698\n2014-04-03 21:05:00,21.0299330128\n2014-04-03 21:10:00,20.8734169327\n2014-04-03 21:15:00,21.2710169439\n2014-04-03 21:20:00,19.118122751199998\n2014-04-03 21:25:00,19.8722718549\n2014-04-03 21:30:00,20.735509015399998\n2014-04-03 21:35:00,19.8539175223\n2014-04-03 21:40:00,20.889091685\n2014-04-03 21:45:00,20.634465872699998\n2014-04-03 21:50:00,18.5471924045\n2014-04-03 21:55:00,21.2255684603\n2014-04-03 22:00:00,20.9027528233\n2014-04-03 22:05:00,20.6431359444\n2014-04-03 22:10:00,18.6382499754\n2014-04-03 22:15:00,19.0902948922\n2014-04-03 22:20:00,19.5914979165\n2014-04-03 22:25:00,19.138073407\n2014-04-03 22:30:00,18.9293959449\n2014-04-03 22:35:00,21.241803243699998\n2014-04-03 22:40:00,20.5726597872\n2014-04-03 22:45:00,20.2813399292\n2014-04-03 22:50:00,18.9219584925\n2014-04-03 22:55:00,21.6931116524\n2014-04-03 23:00:00,18.7683349831\n2014-04-03 23:05:00,21.1838702515\n2014-04-03 23:10:00,21.8708890693\n2014-04-03 23:15:00,20.9123853221\n2014-04-03 23:20:00,21.975653614099997\n2014-04-03 23:25:00,20.6081604731\n2014-04-03 23:30:00,18.8734643821\n2014-04-03 23:35:00,18.818890506400002\n2014-04-03 23:40:00,19.3019624005\n2014-04-03 23:45:00,18.031981555\n2014-04-03 23:50:00,20.7307734227\n2014-04-03 23:55:00,19.0783334735\n2014-04-04 00:00:00,21.2607329292\n2014-04-04 00:05:00,19.4366906022\n2014-04-04 00:10:00,19.9198259739\n2014-04-04 00:15:00,21.862755666199998\n2014-04-04 00:20:00,18.968688492200002\n2014-04-04 00:25:00,20.8850163897\n2014-04-04 00:30:00,21.0204711572\n2014-04-04 00:35:00,18.8839926301\n2014-04-04 00:40:00,20.003987346400002\n2014-04-04 00:45:00,19.4008077013\n2014-04-04 00:50:00,21.0876249736\n2014-04-04 00:55:00,20.4899332761\n2014-04-04 01:00:00,19.9039322194\n2014-04-04 01:05:00,21.1174530602\n2014-04-04 01:10:00,18.94062228\n2014-04-04 01:15:00,21.0144875223\n2014-04-04 01:20:00,21.4614972484\n2014-04-04 01:25:00,21.514486387199998\n2014-04-04 01:30:00,21.1346943721\n2014-04-04 01:35:00,19.632056668\n2014-04-04 01:40:00,21.927232090900002\n2014-04-04 01:45:00,19.5183745753\n2014-04-04 01:50:00,20.5545015964\n2014-04-04 01:55:00,18.6442967123\n2014-04-04 02:00:00,21.921795594499997\n2014-04-04 02:05:00,20.8159436875\n2014-04-04 02:10:00,21.013510180999997\n2014-04-04 02:15:00,18.2631068136\n2014-04-04 02:20:00,21.0536712569\n2014-04-04 02:25:00,21.0988937169\n2014-04-04 02:30:00,20.687090905399998\n2014-04-04 02:35:00,19.1676384552\n2014-04-04 02:40:00,19.958760168599998\n2014-04-04 02:45:00,18.4417374852\n2014-04-04 02:50:00,19.8863482658\n2014-04-04 02:55:00,18.9752954104\n2014-04-04 03:00:00,19.396387945999997\n2014-04-04 03:05:00,18.650401633599998\n2014-04-04 03:10:00,18.920217470999997\n2014-04-04 03:15:00,18.3062745673\n2014-04-04 03:20:00,21.679605465700003\n2014-04-04 03:25:00,20.1216427519\n2014-04-04 03:30:00,19.586967885099998\n2014-04-04 03:35:00,20.1401168511\n2014-04-04 03:40:00,20.5131729139\n2014-04-04 03:45:00,21.6875151735\n2014-04-04 03:50:00,18.7147718091\n2014-04-04 03:55:00,19.1822099945\n2014-04-04 04:00:00,21.9031573454\n2014-04-04 04:05:00,19.484771946600002\n2014-04-04 04:10:00,18.090246603\n2014-04-04 04:15:00,18.5905739705\n2014-04-04 04:20:00,18.105354807\n2014-04-04 04:25:00,21.9596925697\n2014-04-04 04:30:00,19.115483396\n2014-04-04 04:35:00,21.6941710277\n2014-04-04 04:40:00,21.983545103\n2014-04-04 04:45:00,20.3993648846\n2014-04-04 04:50:00,18.1327852603\n2014-04-04 04:55:00,18.326366521500002\n2014-04-04 05:00:00,19.9263562204\n2014-04-04 05:05:00,19.6246880516\n2014-04-04 05:10:00,20.4247092231\n2014-04-04 05:15:00,19.7553912388\n2014-04-04 05:20:00,21.7363073971\n2014-04-04 05:25:00,20.1389588617\n2014-04-04 05:30:00,20.7749042458\n2014-04-04 05:35:00,21.5859410906\n2014-04-04 05:40:00,18.5874875033\n2014-04-04 05:45:00,18.9189386165\n2014-04-04 05:50:00,18.4292746419\n2014-04-04 05:55:00,18.5585535969\n2014-04-04 06:00:00,20.0503358677\n2014-04-04 06:05:00,19.284717035899998\n2014-04-04 06:10:00,19.6926913581\n2014-04-04 06:15:00,21.9299593272\n2014-04-04 06:20:00,18.6268173912\n2014-04-04 06:25:00,20.163248283199998\n2014-04-04 06:30:00,18.3954846202\n2014-04-04 06:35:00,19.2739852531\n2014-04-04 06:40:00,20.1101036947\n2014-04-04 06:45:00,21.7865269839\n2014-04-04 06:50:00,19.5649128851\n2014-04-04 06:55:00,18.2596267849\n2014-04-04 07:00:00,19.5526457918\n2014-04-04 07:05:00,18.5829647035\n2014-04-04 07:10:00,18.9199584532\n2014-04-04 07:15:00,20.4723624927\n2014-04-04 07:20:00,18.2696954648\n2014-04-04 07:25:00,19.858895025\n2014-04-04 07:30:00,20.437846344\n2014-04-04 07:35:00,19.6874335695\n2014-04-04 07:40:00,18.0765054025\n2014-04-04 07:45:00,21.9420774276\n2014-04-04 07:50:00,19.468463069400002\n2014-04-04 07:55:00,21.1143087477\n2014-04-04 08:00:00,19.302585968699997\n2014-04-04 08:05:00,19.900067028\n2014-04-04 08:10:00,19.5538545704\n2014-04-04 08:15:00,19.370156918\n2014-04-04 08:20:00,18.0874055088\n2014-04-04 08:25:00,19.4400837514\n2014-04-04 08:30:00,21.557959961599998\n2014-04-04 08:35:00,20.7615733544\n2014-04-04 08:40:00,18.5816914364\n2014-04-04 08:45:00,20.3646200185\n2014-04-04 08:50:00,21.5689234398\n2014-04-04 08:55:00,20.8001361639\n2014-04-04 09:00:00,63.2221077361\n2014-04-04 09:05:00,73.0025219556\n2014-04-04 09:10:00,65.3009985807\n2014-04-04 09:15:00,67.3754355626\n2014-04-04 09:20:00,68.3555415318\n2014-04-04 09:25:00,72.7668898195\n2014-04-04 09:30:00,73.869861934\n2014-04-04 09:35:00,73.843279138\n2014-04-04 09:40:00,61.3081768654\n2014-04-04 09:45:00,73.737683404\n2014-04-04 09:50:00,61.9396627376\n2014-04-04 09:55:00,64.8145217327\n2014-04-04 10:00:00,77.8326115054\n2014-04-04 10:05:00,77.2884466933\n2014-04-04 10:10:00,79.2250960011\n2014-04-04 10:15:00,77.28100547\n2014-04-04 10:20:00,84.341510548\n2014-04-04 10:25:00,73.5733181243\n2014-04-04 10:30:00,74.09286325149999\n2014-04-04 10:35:00,84.129852762\n2014-04-04 10:40:00,71.0309972533\n2014-04-04 10:45:00,79.300383956\n2014-04-04 10:50:00,80.4205419761\n2014-04-04 10:55:00,77.6860075476\n2014-04-04 11:00:00,82.6090638008\n2014-04-04 11:05:00,74.3154898902\n2014-04-04 11:10:00,85.12826303\n2014-04-04 11:15:00,73.7949685653\n2014-04-04 11:20:00,77.9425211144\n2014-04-04 11:25:00,72.7648968912\n2014-04-04 11:30:00,80.2390369975\n2014-04-04 11:35:00,82.2196373213\n2014-04-04 11:40:00,86.53718888459998\n2014-04-04 11:45:00,83.32640285949999\n2014-04-04 11:50:00,80.17370078329998\n2014-04-04 11:55:00,86.4003410411\n2014-04-04 12:00:00,79.5594034214\n2014-04-04 12:05:00,80.882115301\n2014-04-04 12:10:00,81.439731351\n2014-04-04 12:15:00,78.4654040034\n2014-04-04 12:20:00,85.3132241814\n2014-04-04 12:25:00,74.87285964350001\n2014-04-04 12:30:00,80.7804220759\n2014-04-04 12:35:00,83.4554652205\n2014-04-04 12:40:00,86.3598624075\n2014-04-04 12:45:00,86.03932310969999\n2014-04-04 12:50:00,80.0436768173\n2014-04-04 12:55:00,82.19183451880002\n2014-04-04 13:00:00,78.2890099052\n2014-04-04 13:05:00,79.4717664035\n2014-04-04 13:10:00,86.4794926205\n2014-04-04 13:15:00,86.8704099877\n2014-04-04 13:20:00,86.3059065391\n2014-04-04 13:25:00,74.1961224449\n2014-04-04 13:30:00,85.5808000186\n2014-04-04 13:35:00,87.15289797959998\n2014-04-04 13:40:00,77.7613279144\n2014-04-04 13:45:00,80.279069029\n2014-04-04 13:50:00,84.4452523672\n2014-04-04 13:55:00,80.973811821\n2014-04-04 14:00:00,87.89151735200001\n2014-04-04 14:05:00,79.2876078546\n2014-04-04 14:10:00,83.4190790713\n2014-04-04 14:15:00,84.6773935331\n2014-04-04 14:20:00,79.90177118300001\n2014-04-04 14:25:00,85.70762672779999\n2014-04-04 14:30:00,80.7345980126\n2014-04-04 14:35:00,78.58264060100001\n2014-04-04 14:40:00,73.721639973\n2014-04-04 14:45:00,78.29085908\n2014-04-04 14:50:00,83.7389636125\n2014-04-04 14:55:00,86.7364190389\n2014-04-04 15:00:00,76.0261406038\n2014-04-04 15:05:00,77.6830225131\n2014-04-04 15:10:00,74.4626610573\n2014-04-04 15:15:00,83.0507690126\n2014-04-04 15:20:00,87.3621761952\n2014-04-04 15:25:00,82.25444586729999\n2014-04-04 15:30:00,81.8724384971\n2014-04-04 15:35:00,80.855062672\n2014-04-04 15:40:00,73.4145870642\n2014-04-04 15:45:00,83.67125797109999\n2014-04-04 15:50:00,81.63200902199999\n2014-04-04 15:55:00,82.58283549890001\n2014-04-04 16:00:00,86.38081163700001\n2014-04-04 16:05:00,84.5432102697\n2014-04-04 16:10:00,84.49448180479999\n2014-04-04 16:15:00,86.834773579\n2014-04-04 16:20:00,87.8387905726\n2014-04-04 16:25:00,81.3003676144\n2014-04-04 16:30:00,73.7419642717\n2014-04-04 16:35:00,79.3459261799\n2014-04-04 16:40:00,84.6014559083\n2014-04-04 16:45:00,72.4434661045\n2014-04-04 16:50:00,72.9100590261\n2014-04-04 16:55:00,73.074384215\n2014-04-04 17:00:00,83.6965399938\n2014-04-04 17:05:00,80.01863532979999\n2014-04-04 17:10:00,77.90233718180001\n2014-04-04 17:15:00,73.6898444273\n2014-04-04 17:20:00,83.71581185640001\n2014-04-04 17:25:00,77.1362873485\n2014-04-04 17:30:00,76.2451558429\n2014-04-04 17:35:00,82.437075569\n2014-04-04 17:40:00,80.944143199\n2014-04-04 17:45:00,77.79854039439999\n2014-04-04 17:50:00,82.2637679436\n2014-04-04 17:55:00,76.3395150118\n2014-04-04 18:00:00,33.886907168\n2014-04-04 18:05:00,30.2676354706\n2014-04-04 18:10:00,29.8165555257\n2014-04-04 18:15:00,33.8076057297\n2014-04-04 18:20:00,33.330502597\n2014-04-04 18:25:00,29.9688836905\n2014-04-04 18:30:00,29.5439671448\n2014-04-04 18:35:00,34.1657476065\n2014-04-04 18:40:00,33.7702238022\n2014-04-04 18:45:00,30.8944412599\n2014-04-04 18:50:00,33.0124570742\n2014-04-04 18:55:00,29.5946195117\n2014-04-04 19:00:00,22.431572281999998\n2014-04-04 19:05:00,20.2439105979\n2014-04-04 19:10:00,21.9143752244\n2014-04-04 19:15:00,20.4952947159\n2014-04-04 19:20:00,22.2886581444\n2014-04-04 19:25:00,22.0491325683\n2014-04-04 19:30:00,22.1508437042\n2014-04-04 19:35:00,20.3630831161\n2014-04-04 19:40:00,21.7800400142\n2014-04-04 19:45:00,23.5490463521\n2014-04-04 19:50:00,21.812735196\n2014-04-04 19:55:00,23.363969066\n2014-04-04 20:00:00,19.9453846127\n2014-04-04 20:05:00,20.1655885104\n2014-04-04 20:10:00,20.7417018452\n2014-04-04 20:15:00,22.3259929452\n2014-04-04 20:20:00,18.8778921629\n2014-04-04 20:25:00,18.5668145736\n2014-04-04 20:30:00,20.9221923738\n2014-04-04 20:35:00,22.3195014084\n2014-04-04 20:40:00,22.4859056811\n2014-04-04 20:45:00,20.415136512300002\n2014-04-04 20:50:00,20.3492620758\n2014-04-04 20:55:00,21.0737713521\n2014-04-04 21:00:00,20.319607166500003\n2014-04-04 21:05:00,20.6349266707\n2014-04-04 21:10:00,21.5991784383\n2014-04-04 21:15:00,21.0859537048\n2014-04-04 21:20:00,20.0834495635\n2014-04-04 21:25:00,19.9427255848\n2014-04-04 21:30:00,20.657087297100002\n2014-04-04 21:35:00,19.9179746496\n2014-04-04 21:40:00,19.9263067199\n2014-04-04 21:45:00,18.1519366361\n2014-04-04 21:50:00,18.7859985351\n2014-04-04 21:55:00,20.0498339728\n2014-04-04 22:00:00,21.311052815\n2014-04-04 22:05:00,19.1332583292\n2014-04-04 22:10:00,20.1098606734\n2014-04-04 22:15:00,19.3984529839\n2014-04-04 22:20:00,18.4368983964\n2014-04-04 22:25:00,21.8541537877\n2014-04-04 22:30:00,21.4392574181\n2014-04-04 22:35:00,18.3315510998\n2014-04-04 22:40:00,20.8991930227\n2014-04-04 22:45:00,19.4089343147\n2014-04-04 22:50:00,22.0004994407\n2014-04-04 22:55:00,19.2280352802\n2014-04-04 23:00:00,18.9585931307\n2014-04-04 23:05:00,20.2754543312\n2014-04-04 23:10:00,21.3446020282\n2014-04-04 23:15:00,18.7736793399\n2014-04-04 23:20:00,20.8416118982\n2014-04-04 23:25:00,18.249129490999998\n2014-04-04 23:30:00,21.6799007122\n2014-04-04 23:35:00,18.3278179283\n2014-04-04 23:40:00,21.6610836329\n2014-04-04 23:45:00,19.9670619358\n2014-04-04 23:50:00,19.7961645832\n2014-04-04 23:55:00,21.897431815700003\n2014-04-05 00:00:00,21.9615367108\n2014-04-05 00:05:00,20.6007125038\n2014-04-05 00:10:00,18.5084771674\n2014-04-05 00:15:00,20.0246803426\n2014-04-05 00:20:00,20.1166524038\n2014-04-05 00:25:00,20.0577857125\n2014-04-05 00:30:00,20.2779673541\n2014-04-05 00:35:00,18.0748988552\n2014-04-05 00:40:00,20.8449091259\n2014-04-05 00:45:00,20.8495772078\n2014-04-05 00:50:00,18.4618791007\n2014-04-05 00:55:00,20.2809577698\n2014-04-05 01:00:00,20.2734447297\n2014-04-05 01:05:00,20.729801680799998\n2014-04-05 01:10:00,18.341590768499998\n2014-04-05 01:15:00,20.506013229100002\n2014-04-05 01:20:00,19.123007803\n2014-04-05 01:25:00,20.028011962\n2014-04-05 01:30:00,21.0932942108\n2014-04-05 01:35:00,20.8225837455\n2014-04-05 01:40:00,18.4756120707\n2014-04-05 01:45:00,20.3647391485\n2014-04-05 01:50:00,21.8764661238\n2014-04-05 01:55:00,18.6270777493\n2014-04-05 02:00:00,21.4116283509\n2014-04-05 02:05:00,20.8101923222\n2014-04-05 02:10:00,21.096013251600002\n2014-04-05 02:15:00,19.1278333086\n2014-04-05 02:20:00,19.1515557175\n2014-04-05 02:25:00,21.6240778231\n2014-04-05 02:30:00,19.4393281284\n2014-04-05 02:35:00,18.252061562799998\n2014-04-05 02:40:00,20.4023868143\n2014-04-05 02:45:00,18.4992706762\n2014-04-05 02:50:00,21.1863849656\n2014-04-05 02:55:00,20.56698577\n2014-04-05 03:00:00,21.4989060209\n2014-04-05 03:05:00,21.1393489991\n2014-04-05 03:10:00,18.448454593399997\n2014-04-05 03:15:00,19.5242827057\n2014-04-05 03:20:00,21.0982409997\n2014-04-05 03:25:00,19.6693658931\n2014-04-05 03:30:00,21.8894619391\n2014-04-05 03:35:00,20.9429617996\n2014-04-05 03:40:00,18.061999666800002\n2014-04-05 03:45:00,21.5199427662\n2014-04-05 03:50:00,18.4032191395\n2014-04-05 03:55:00,18.5620948967\n2014-04-05 04:00:00,20.9379696024\n2014-04-05 04:05:00,21.4598742377\n2014-04-05 04:10:00,20.1453985116\n2014-04-05 04:15:00,19.156198931800002\n2014-04-05 04:20:00,19.405262180999998\n2014-04-05 04:25:00,19.3715573184\n2014-04-05 04:30:00,19.3067124152\n2014-04-05 04:35:00,18.9716386873\n2014-04-05 04:40:00,20.435468378499998\n2014-04-05 04:45:00,21.601621274299998\n2014-04-05 04:50:00,19.2283296523\n2014-04-05 04:55:00,18.7467771898\n2014-04-05 05:00:00,21.354310665499998\n2014-04-05 05:05:00,20.9671333236\n2014-04-05 05:10:00,21.723348126199998\n2014-04-05 05:15:00,18.6620789424\n2014-04-05 05:20:00,18.5770052565\n2014-04-05 05:25:00,20.1657175772\n2014-04-05 05:30:00,20.457734619300002\n2014-04-05 05:35:00,19.9206937674\n2014-04-05 05:40:00,20.3958665453\n2014-04-05 05:45:00,18.721519075499998\n2014-04-05 05:50:00,19.9184550167\n2014-04-05 05:55:00,20.6323702438\n2014-04-05 06:00:00,19.730825797\n2014-04-05 06:05:00,20.717789343299998\n2014-04-05 06:10:00,19.8047651222\n2014-04-05 06:15:00,19.3343983234\n2014-04-05 06:20:00,19.2144201883\n2014-04-05 06:25:00,19.643608236\n2014-04-05 06:30:00,18.0923584907\n2014-04-05 06:35:00,20.674100553800002\n2014-04-05 06:40:00,21.3804225639\n2014-04-05 06:45:00,19.4185083778\n2014-04-05 06:50:00,18.1841325446\n2014-04-05 06:55:00,21.9471023895\n2014-04-05 07:00:00,19.054793021800002\n2014-04-05 07:05:00,18.5064844868\n2014-04-05 07:10:00,19.4790100319\n2014-04-05 07:15:00,20.9542281625\n2014-04-05 07:20:00,19.1756663876\n2014-04-05 07:25:00,20.2988128157\n2014-04-05 07:30:00,19.6622399777\n2014-04-05 07:35:00,18.4710559691\n2014-04-05 07:40:00,19.32114805\n2014-04-05 07:45:00,20.8994820229\n2014-04-05 07:50:00,20.448015589300002\n2014-04-05 07:55:00,18.4791135195\n2014-04-05 08:00:00,18.653289638900002\n2014-04-05 08:05:00,20.5629334372\n2014-04-05 08:10:00,21.2536616573\n2014-04-05 08:15:00,19.3978979838\n2014-04-05 08:20:00,20.3812430074\n2014-04-05 08:25:00,18.682574355\n2014-04-05 08:30:00,19.245505347599998\n2014-04-05 08:35:00,18.0810808227\n2014-04-05 08:40:00,21.073103791199998\n2014-04-05 08:45:00,19.6040392791\n2014-04-05 08:50:00,21.2645022946\n2014-04-05 08:55:00,20.8334919841\n2014-04-05 09:00:00,72.47092201390001\n2014-04-05 09:05:00,65.0849579063\n2014-04-05 09:10:00,63.7174787338\n2014-04-05 09:15:00,74.4179172841\n2014-04-05 09:20:00,70.9556579038\n2014-04-05 09:25:00,72.5429748438\n2014-04-05 09:30:00,61.3786138825\n2014-04-05 09:35:00,66.020678036\n2014-04-05 09:40:00,71.3023069919\n2014-04-05 09:45:00,62.2605665287\n2014-04-05 09:50:00,68.9158230421\n2014-04-05 09:55:00,67.0353896374\n2014-04-05 10:00:00,70.1134081908\n2014-04-05 10:05:00,73.5023409569\n2014-04-05 10:10:00,74.2599716703\n2014-04-05 10:15:00,71.5760663673\n2014-04-05 10:20:00,79.6414528392\n2014-04-05 10:25:00,73.6020150394\n2014-04-05 10:30:00,74.1486546341\n2014-04-05 10:35:00,83.7806630441\n2014-04-05 10:40:00,77.0897503986\n2014-04-05 10:45:00,75.925828841\n2014-04-05 10:50:00,81.0744785146\n2014-04-05 10:55:00,83.9572061276\n2014-04-05 11:00:00,71.9661778915\n2014-04-05 11:05:00,78.69679061560001\n2014-04-05 11:10:00,81.2818666871\n2014-04-05 11:15:00,76.6344275126\n2014-04-05 11:20:00,83.8523724126\n2014-04-05 11:25:00,87.0183713256\n2014-04-05 11:30:00,86.5722688328\n2014-04-05 11:35:00,75.7981863063\n2014-04-05 11:40:00,75.1676839803\n2014-04-05 11:45:00,86.7959294054\n2014-04-05 11:50:00,78.8620274641\n2014-04-05 11:55:00,74.8807669879\n2014-04-05 12:00:00,83.2119770764\n2014-04-05 12:05:00,76.4588643122\n2014-04-05 12:10:00,76.1844204592\n2014-04-05 12:15:00,85.9647031076\n2014-04-05 12:20:00,74.5101468543\n2014-04-05 12:25:00,72.9426507989\n2014-04-05 12:30:00,76.2154146631\n2014-04-05 12:35:00,81.6130732535\n2014-04-05 12:40:00,73.8806423677\n2014-04-05 12:45:00,79.4500601387\n2014-04-05 12:50:00,81.9389488943\n2014-04-05 12:55:00,85.4770961312\n2014-04-05 13:00:00,75.65975076\n2014-04-05 13:05:00,85.0571225642\n2014-04-05 13:10:00,75.74031813810001\n2014-04-05 13:15:00,82.80838587630002\n2014-04-05 13:20:00,78.8718433572\n2014-04-05 13:25:00,73.8171795021\n2014-04-05 13:30:00,83.40819263350001\n2014-04-05 13:35:00,75.4660856883\n2014-04-05 13:40:00,74.8080165824\n2014-04-05 13:45:00,77.7145108974\n2014-04-05 13:50:00,82.4328552816\n2014-04-05 13:55:00,75.7257651142\n2014-04-05 14:00:00,74.9349875684\n2014-04-05 14:05:00,72.155794367\n2014-04-05 14:10:00,79.5424713317\n2014-04-05 14:15:00,78.8545439092\n2014-04-05 14:20:00,75.73824828779999\n2014-04-05 14:25:00,72.8549374193\n2014-04-05 14:30:00,78.864308325\n2014-04-05 14:35:00,84.6072204356\n2014-04-05 14:40:00,83.4405087646\n2014-04-05 14:45:00,85.76860114729999\n2014-04-05 14:50:00,72.1498596439\n2014-04-05 14:55:00,87.4585108588\n2014-04-05 15:00:00,77.4618524011\n2014-04-05 15:05:00,87.8455214124\n2014-04-05 15:10:00,76.0411813673\n2014-04-05 15:15:00,79.5438185733\n2014-04-05 15:20:00,77.6620972619\n2014-04-05 15:25:00,77.6914255951\n2014-04-05 15:30:00,85.4756930054\n2014-04-05 15:35:00,83.9418971858\n2014-04-05 15:40:00,87.8735793692\n2014-04-05 15:45:00,81.8154494876\n2014-04-05 15:50:00,79.4113433141\n2014-04-05 15:55:00,73.44047677180001\n2014-04-05 16:00:00,87.94481385790002\n2014-04-05 16:05:00,80.8243352639\n2014-04-05 16:10:00,83.2074797564\n2014-04-05 16:15:00,78.5077274599\n2014-04-05 16:20:00,80.763296265\n2014-04-05 16:25:00,87.08107651430002\n2014-04-05 16:30:00,74.6625676545\n2014-04-05 16:35:00,76.6778141276\n2014-04-05 16:40:00,74.4328127332\n2014-04-05 16:45:00,84.67529188399999\n2014-04-05 16:50:00,72.9925840207\n2014-04-05 16:55:00,73.3059656499\n2014-04-05 17:00:00,76.7758763227\n2014-04-05 17:05:00,80.2269800876\n2014-04-05 17:10:00,78.5003666648\n2014-04-05 17:15:00,72.7170330474\n2014-04-05 17:20:00,87.3198313951\n2014-04-05 17:25:00,87.2458788233\n2014-04-05 17:30:00,76.4696718075\n2014-04-05 17:35:00,83.7043777018\n2014-04-05 17:40:00,81.2571753794\n2014-04-05 17:45:00,75.79959801300001\n2014-04-05 17:50:00,76.1947155691\n2014-04-05 17:55:00,79.8584201233\n2014-04-05 18:00:00,31.4831103808\n2014-04-05 18:05:00,30.6638618132\n2014-04-05 18:10:00,33.9680676945\n2014-04-05 18:15:00,31.8813565517\n2014-04-05 18:20:00,32.991021265\n2014-04-05 18:25:00,30.0113446389\n2014-04-05 18:30:00,32.2144428549\n2014-04-05 18:35:00,30.83504079610001\n2014-04-05 18:40:00,32.1690409301\n2014-04-05 18:45:00,33.7972788448\n2014-04-05 18:50:00,33.7210380701\n2014-04-05 18:55:00,31.067006374600002\n2014-04-05 19:00:00,23.270360208000003\n2014-04-05 19:05:00,24.3769776405\n2014-04-05 19:10:00,22.9629973384\n2014-04-05 19:15:00,20.8248762104\n2014-04-05 19:20:00,23.205093386199998\n2014-04-05 19:25:00,20.629970519100002\n2014-04-05 19:30:00,24.0670533111\n2014-04-05 19:35:00,22.4746377883\n2014-04-05 19:40:00,21.8854292981\n2014-04-05 19:45:00,20.4153884241\n2014-04-05 19:50:00,21.865909931500006\n2014-04-05 19:55:00,24.2063645444\n2014-04-05 20:00:00,18.5179461306\n2014-04-05 20:05:00,20.3761586098\n2014-04-05 20:10:00,22.246023274200002\n2014-04-05 20:15:00,20.0492684944\n2014-04-05 20:20:00,20.1858073736\n2014-04-05 20:25:00,20.8017817365\n2014-04-05 20:30:00,20.3281910744\n2014-04-05 20:35:00,19.1225922978\n2014-04-05 20:40:00,18.508003265899998\n2014-04-05 20:45:00,20.9297882999\n2014-04-05 20:50:00,22.2036235139\n2014-04-05 20:55:00,18.8676672625\n2014-04-05 21:00:00,18.9342611229\n2014-04-05 21:05:00,19.574426301600003\n2014-04-05 21:10:00,21.3368967147\n2014-04-05 21:15:00,19.1686110171\n2014-04-05 21:20:00,21.6315530088\n2014-04-05 21:25:00,18.307286645\n2014-04-05 21:30:00,21.868292798699997\n2014-04-05 21:35:00,20.3401546056\n2014-04-05 21:40:00,20.734159194700002\n2014-04-05 21:45:00,19.5642176811\n2014-04-05 21:50:00,21.2293913804\n2014-04-05 21:55:00,18.755863026500002\n2014-04-05 22:00:00,18.2131151136\n2014-04-05 22:05:00,19.6008665479\n2014-04-05 22:10:00,21.4353410369\n2014-04-05 22:15:00,21.0398862553\n2014-04-05 22:20:00,20.087889751\n2014-04-05 22:25:00,20.3080279876\n2014-04-05 22:30:00,18.5373500845\n2014-04-05 22:35:00,21.383234241\n2014-04-05 22:40:00,21.1681406466\n2014-04-05 22:45:00,20.6456824117\n2014-04-05 22:50:00,19.8838343091\n2014-04-05 22:55:00,21.878820586\n2014-04-05 23:00:00,21.5202589819\n2014-04-05 23:05:00,20.5816728947\n2014-04-05 23:10:00,19.4909455321\n2014-04-05 23:15:00,20.476019753800003\n2014-04-05 23:20:00,20.3056616428\n2014-04-05 23:25:00,19.5807267273\n2014-04-05 23:30:00,19.2303874105\n2014-04-05 23:35:00,19.631811751300003\n2014-04-05 23:40:00,20.2995423861\n2014-04-05 23:45:00,19.7163241845\n2014-04-05 23:50:00,19.057956376099998\n2014-04-05 23:55:00,21.047893688800002\n2014-04-06 00:00:00,20.1258699838\n2014-04-06 00:05:00,18.2707006529\n2014-04-06 00:10:00,19.4732660225\n2014-04-06 00:15:00,21.539653828800002\n2014-04-06 00:20:00,21.020946124800002\n2014-04-06 00:25:00,19.2929871358\n2014-04-06 00:30:00,21.752732608200002\n2014-04-06 00:35:00,18.3064116334\n2014-04-06 00:40:00,21.8449388156\n2014-04-06 00:45:00,18.9828203699\n2014-04-06 00:50:00,18.0363767212\n2014-04-06 00:55:00,19.7352321461\n2014-04-06 01:00:00,19.4358817187\n2014-04-06 01:05:00,20.1563560208\n2014-04-06 01:10:00,21.1870914423\n2014-04-06 01:15:00,21.3697232086\n2014-04-06 01:20:00,19.6049199984\n2014-04-06 01:25:00,19.7193829748\n2014-04-06 01:30:00,18.5927109213\n2014-04-06 01:35:00,18.1901904355\n2014-04-06 01:40:00,20.564859960899998\n2014-04-06 01:45:00,18.2577505022\n2014-04-06 01:50:00,20.9353204777\n2014-04-06 01:55:00,20.1563605801\n2014-04-06 02:00:00,18.7943319129\n2014-04-06 02:05:00,20.1580917741\n2014-04-06 02:10:00,18.7319908664\n2014-04-06 02:15:00,19.75494883\n2014-04-06 02:20:00,21.198241265\n2014-04-06 02:25:00,19.847677173599998\n2014-04-06 02:30:00,18.5947972732\n2014-04-06 02:35:00,20.8953147273\n2014-04-06 02:40:00,18.7470736651\n2014-04-06 02:45:00,20.9541994975\n2014-04-06 02:50:00,19.9174091569\n2014-04-06 02:55:00,19.814967036400002\n2014-04-06 03:00:00,21.4057401514\n2014-04-06 03:05:00,20.8344140974\n2014-04-06 03:10:00,18.131643187799998\n2014-04-06 03:15:00,19.1846972584\n2014-04-06 03:20:00,21.4836826434\n2014-04-06 03:25:00,18.0733046742\n2014-04-06 03:30:00,20.181013785\n2014-04-06 03:35:00,20.9113026767\n2014-04-06 03:40:00,20.4874243419\n2014-04-06 03:45:00,21.042128808399998\n2014-04-06 03:50:00,20.9027673957\n2014-04-06 03:55:00,20.7681227806\n2014-04-06 04:00:00,21.286159443699997\n2014-04-06 04:05:00,20.5827626738\n2014-04-06 04:10:00,19.609673977\n2014-04-06 04:15:00,19.8876364397\n2014-04-06 04:20:00,20.8668991307\n2014-04-06 04:25:00,21.5052241187\n2014-04-06 04:30:00,19.0888752034\n2014-04-06 04:35:00,19.3683071839\n2014-04-06 04:40:00,21.7229575854\n2014-04-06 04:45:00,20.314047169600002\n2014-04-06 04:50:00,18.7158472685\n2014-04-06 04:55:00,20.6547805556\n2014-04-06 05:00:00,21.9630486222\n2014-04-06 05:05:00,21.2938142579\n2014-04-06 05:10:00,20.982964546199998\n2014-04-06 05:15:00,18.8321866171\n2014-04-06 05:20:00,21.5045591387\n2014-04-06 05:25:00,20.1031553741\n2014-04-06 05:30:00,21.557160088299998\n2014-04-06 05:35:00,19.3193113177\n2014-04-06 05:40:00,18.2482042105\n2014-04-06 05:45:00,19.9039038746\n2014-04-06 05:50:00,19.0793504193\n2014-04-06 05:55:00,20.8609171591\n2014-04-06 06:00:00,21.8284262114\n2014-04-06 06:05:00,20.7638966046\n2014-04-06 06:10:00,21.547735718800002\n2014-04-06 06:15:00,19.8120960544\n2014-04-06 06:20:00,21.0865629488\n2014-04-06 06:25:00,21.3721737467\n2014-04-06 06:30:00,20.8435025103\n2014-04-06 06:35:00,20.0311091443\n2014-04-06 06:40:00,20.5034644385\n2014-04-06 06:45:00,20.8020279827\n2014-04-06 06:50:00,19.012337612899998\n2014-04-06 06:55:00,21.2383170437\n2014-04-06 07:00:00,21.801298155900003\n2014-04-06 07:05:00,19.860957260699998\n2014-04-06 07:10:00,20.8042687324\n2014-04-06 07:15:00,20.948103623199998\n2014-04-06 07:20:00,20.6489901901\n2014-04-06 07:25:00,20.188460433299998\n2014-04-06 07:30:00,21.5265918183\n2014-04-06 07:35:00,19.7957068371\n2014-04-06 07:40:00,18.2444118259\n2014-04-06 07:45:00,21.3782255028\n2014-04-06 07:50:00,20.6959250893\n2014-04-06 07:55:00,21.397034506\n2014-04-06 08:00:00,18.5541897698\n2014-04-06 08:05:00,18.123011762\n2014-04-06 08:10:00,21.7374981615\n2014-04-06 08:15:00,18.590913223399998\n2014-04-06 08:20:00,21.2386093283\n2014-04-06 08:25:00,21.2928397687\n2014-04-06 08:30:00,20.8348208022\n2014-04-06 08:35:00,18.5250488444\n2014-04-06 08:40:00,20.6695944982\n2014-04-06 08:45:00,21.5563463333\n2014-04-06 08:50:00,19.7021265792\n2014-04-06 08:55:00,19.6540674175\n2014-04-06 09:00:00,67.22287301029999\n2014-04-06 09:05:00,62.318897713199995\n2014-04-06 09:10:00,73.3315477388\n2014-04-06 09:15:00,73.0208869501\n2014-04-06 09:20:00,74.7715667763\n2014-04-06 09:25:00,69.1584907244\n2014-04-06 09:30:00,71.41620625569999\n2014-04-06 09:35:00,63.9563379258\n2014-04-06 09:40:00,70.2783919278\n2014-04-06 09:45:00,70.0363667431\n2014-04-06 09:50:00,73.45643880739999\n2014-04-06 09:55:00,72.4987810306\n2014-04-06 10:00:00,84.4049994998\n2014-04-06 10:05:00,83.3242954963\n2014-04-06 10:10:00,83.3221292488\n2014-04-06 10:15:00,70.8289860302\n2014-04-06 10:20:00,82.9693295058\n2014-04-06 10:25:00,79.2680646827\n2014-04-06 10:30:00,75.7444978914\n2014-04-06 10:35:00,70.7171069705\n2014-04-06 10:40:00,80.3574969844\n2014-04-06 10:45:00,74.9336911683\n2014-04-06 10:50:00,77.0998876326\n2014-04-06 10:55:00,80.4204253431\n2014-04-06 11:00:00,86.0688623959\n2014-04-06 11:05:00,84.6957487058\n2014-04-06 11:10:00,78.7342967413\n2014-04-06 11:15:00,77.735303336\n2014-04-06 11:20:00,75.3814569666\n2014-04-06 11:25:00,77.49107505069999\n2014-04-06 11:30:00,73.33408174350001\n2014-04-06 11:35:00,87.012462005\n2014-04-06 11:40:00,80.6955830287\n2014-04-06 11:45:00,73.6006241238\n2014-04-06 11:50:00,77.1790267714\n2014-04-06 11:55:00,80.2681105401\n2014-04-06 12:00:00,80.429538782\n2014-04-06 12:05:00,72.48097223479999\n2014-04-06 12:10:00,87.10880039979997\n2014-04-06 12:15:00,76.3143236905\n2014-04-06 12:20:00,72.1722439573\n2014-04-06 12:25:00,73.1352364182\n2014-04-06 12:30:00,81.1855787098\n2014-04-06 12:35:00,74.1155228488\n2014-04-06 12:40:00,72.5803955696\n2014-04-06 12:45:00,77.9803346344\n2014-04-06 12:50:00,81.8658220626\n2014-04-06 12:55:00,73.7008895532\n2014-04-06 13:00:00,76.9947621355\n2014-04-06 13:05:00,78.665286545\n2014-04-06 13:10:00,74.53346923779999\n2014-04-06 13:15:00,80.0779590517\n2014-04-06 13:20:00,73.3458181683\n2014-04-06 13:25:00,72.7268373105\n2014-04-06 13:30:00,80.2980897067\n2014-04-06 13:35:00,75.9481196396\n2014-04-06 13:40:00,73.5083346909\n2014-04-06 13:45:00,78.7636935755\n2014-04-06 13:50:00,86.6214576918\n2014-04-06 13:55:00,83.5670182475\n2014-04-06 14:00:00,85.0457722525\n2014-04-06 14:05:00,85.9464981902\n2014-04-06 14:10:00,87.5578408842\n2014-04-06 14:15:00,84.2079030029\n2014-04-06 14:20:00,81.7306034937\n2014-04-06 14:25:00,77.84307743779999\n2014-04-06 14:30:00,74.9026962829\n2014-04-06 14:35:00,82.9825746289\n2014-04-06 14:40:00,87.91497965639999\n2014-04-06 14:45:00,79.4739240224\n2014-04-06 14:50:00,83.5748581037\n2014-04-06 14:55:00,79.9176429689\n2014-04-06 15:00:00,78.9101772288\n2014-04-06 15:05:00,78.56413559399999\n2014-04-06 15:10:00,80.0732262166\n2014-04-06 15:15:00,77.8695830347\n2014-04-06 15:20:00,83.9795669376\n2014-04-06 15:25:00,85.98752693729998\n2014-04-06 15:30:00,86.1253380951\n2014-04-06 15:35:00,75.6424532403\n2014-04-06 15:40:00,86.3337174081\n2014-04-06 15:45:00,77.4640760474\n2014-04-06 15:50:00,76.9481839381\n2014-04-06 15:55:00,83.6272940886\n2014-04-06 16:00:00,76.8749938411\n2014-04-06 16:05:00,72.8473226226\n2014-04-06 16:10:00,77.9777346394\n2014-04-06 16:15:00,83.5432892023\n2014-04-06 16:20:00,77.2311864402\n2014-04-06 16:25:00,82.0727873159\n2014-04-06 16:30:00,82.5617525893\n2014-04-06 16:35:00,83.7396154073\n2014-04-06 16:40:00,86.3539216611\n2014-04-06 16:45:00,78.9208804599\n2014-04-06 16:50:00,74.6627698738\n2014-04-06 16:55:00,77.1026634095\n2014-04-06 17:00:00,78.91464577949999\n2014-04-06 17:05:00,83.4222314751\n2014-04-06 17:10:00,72.2099262804\n2014-04-06 17:15:00,77.0525365469\n2014-04-06 17:20:00,84.477448857\n2014-04-06 17:25:00,82.73369148350001\n2014-04-06 17:30:00,83.7078074336\n2014-04-06 17:35:00,84.9889396753\n2014-04-06 17:40:00,84.53173904180001\n2014-04-06 17:45:00,82.9148988191\n2014-04-06 17:50:00,79.0345541686\n2014-04-06 17:55:00,87.7375395708\n2014-04-06 18:00:00,32.4420622229\n2014-04-06 18:05:00,30.0977171612\n2014-04-06 18:10:00,30.6739963833\n2014-04-06 18:15:00,33.2387933364\n2014-04-06 18:20:00,34.7183265514\n2014-04-06 18:25:00,29.9438030777\n2014-04-06 18:30:00,29.327011942\n2014-04-06 18:35:00,34.441792094600004\n2014-04-06 18:40:00,34.657772410700005\n2014-04-06 18:45:00,30.5688219408\n2014-04-06 18:50:00,31.214622642800002\n2014-04-06 18:55:00,33.0251968431\n2014-04-06 19:00:00,21.638085306399997\n2014-04-06 19:05:00,24.089669691599997\n2014-04-06 19:10:00,20.641951455799997\n2014-04-06 19:15:00,20.3301592346\n2014-04-06 19:20:00,21.0940170491\n2014-04-06 19:25:00,21.4416720701\n2014-04-06 19:30:00,20.665909995299998\n2014-04-06 19:35:00,20.454292001400002\n2014-04-06 19:40:00,23.545121264899997\n2014-04-06 19:45:00,20.895957868900002\n2014-04-06 19:50:00,24.25437012130001\n2014-04-06 19:55:00,21.8086372869\n2014-04-06 20:00:00,21.1788011425\n2014-04-06 20:05:00,19.3552468298\n2014-04-06 20:10:00,19.4163618267\n2014-04-06 20:15:00,20.7860086455\n2014-04-06 20:20:00,20.7283931727\n2014-04-06 20:25:00,21.580714659\n2014-04-06 20:30:00,21.5360030417\n2014-04-06 20:35:00,21.1791368299\n2014-04-06 20:40:00,20.2716385546\n2014-04-06 20:45:00,22.080062757199997\n2014-04-06 20:50:00,20.9820812442\n2014-04-06 20:55:00,22.4878527471\n2014-04-06 21:00:00,21.37961112\n2014-04-06 21:05:00,18.2644899487\n2014-04-06 21:10:00,19.3749309839\n2014-04-06 21:15:00,20.3848828298\n2014-04-06 21:20:00,20.9861303153\n2014-04-06 21:25:00,20.2983124022\n2014-04-06 21:30:00,21.246015342\n2014-04-06 21:35:00,19.2224495525\n2014-04-06 21:40:00,18.8255792703\n2014-04-06 21:45:00,18.3031018907\n2014-04-06 21:50:00,20.3906625523\n2014-04-06 21:55:00,20.8540191425\n2014-04-06 22:00:00,19.3231312739\n2014-04-06 22:05:00,20.4739728926\n2014-04-06 22:10:00,18.2261091982\n2014-04-06 22:15:00,18.4148346626\n2014-04-06 22:20:00,20.8269938171\n2014-04-06 22:25:00,19.490972199\n2014-04-06 22:30:00,20.7051940369\n2014-04-06 22:35:00,21.3473582797\n2014-04-06 22:40:00,21.4310438095\n2014-04-06 22:45:00,18.7066116964\n2014-04-06 22:50:00,19.9642896162\n2014-04-06 22:55:00,20.9558051629\n2014-04-06 23:00:00,21.0999728001\n2014-04-06 23:05:00,21.142762552\n2014-04-06 23:10:00,18.9163005682\n2014-04-06 23:15:00,18.7737431358\n2014-04-06 23:20:00,20.3639590007\n2014-04-06 23:25:00,20.968368342799998\n2014-04-06 23:30:00,19.2802591594\n2014-04-06 23:35:00,18.4223570392\n2014-04-06 23:40:00,20.8709919908\n2014-04-06 23:45:00,19.2024774916\n2014-04-06 23:50:00,18.669034662\n2014-04-06 23:55:00,18.594463563399998\n2014-04-07 00:00:00,19.2596381901\n2014-04-07 00:05:00,20.3707122637\n2014-04-07 00:10:00,19.4336089548\n2014-04-07 00:15:00,18.0826474064\n2014-04-07 00:20:00,18.3876337387\n2014-04-07 00:25:00,19.1620129888\n2014-04-07 00:30:00,20.638817928599998\n2014-04-07 00:35:00,18.3940602939\n2014-04-07 00:40:00,20.242627414\n2014-04-07 00:45:00,18.4795434833\n2014-04-07 00:50:00,18.846461309400002\n2014-04-07 00:55:00,18.6887541102\n2014-04-07 01:00:00,18.2689145423\n2014-04-07 01:05:00,20.6853192695\n2014-04-07 01:10:00,19.8536141895\n2014-04-07 01:15:00,21.3242137636\n2014-04-07 01:20:00,18.3955633599\n2014-04-07 01:25:00,18.578931733399997\n2014-04-07 01:30:00,19.2258309254\n2014-04-07 01:35:00,21.0634639478\n2014-04-07 01:40:00,19.2230352926\n2014-04-07 01:45:00,19.63367483\n2014-04-07 01:50:00,19.2064142652\n2014-04-07 01:55:00,18.320897167200002\n2014-04-07 02:00:00,21.757734491599997\n2014-04-07 02:05:00,20.1941559683\n2014-04-07 02:10:00,21.1513327527\n2014-04-07 02:15:00,20.6334283687\n2014-04-07 02:20:00,20.057017116199997\n2014-04-07 02:25:00,18.3587130266\n2014-04-07 02:30:00,20.5709341811\n2014-04-07 02:35:00,18.6214814237\n2014-04-07 02:40:00,19.6575326774\n2014-04-07 02:45:00,20.5164525739\n2014-04-07 02:50:00,21.128916001900002\n2014-04-07 02:55:00,20.7401807028\n2014-04-07 03:00:00,20.686134116199998\n2014-04-07 03:05:00,18.596168836700002\n2014-04-07 03:10:00,19.3845141603\n2014-04-07 03:15:00,18.1716490906\n2014-04-07 03:20:00,20.8779075727\n2014-04-07 03:25:00,21.810343925300003\n2014-04-07 03:30:00,19.056441560699998\n2014-04-07 03:35:00,18.3507868366\n2014-04-07 03:40:00,19.902280307\n2014-04-07 03:45:00,21.4267928925\n2014-04-07 03:50:00,20.2078967811\n2014-04-07 03:55:00,18.1871086008\n2014-04-07 04:00:00,21.8970889621\n2014-04-07 04:05:00,21.3145996399\n2014-04-07 04:10:00,18.5263763082\n2014-04-07 04:15:00,21.687191026\n2014-04-07 04:20:00,19.8027531544\n2014-04-07 04:25:00,19.4875919623\n2014-04-07 04:30:00,19.8442133221\n2014-04-07 04:35:00,21.3382878275\n2014-04-07 04:40:00,20.6379187131\n2014-04-07 04:45:00,18.2369938096\n2014-04-07 04:50:00,21.8304174845\n2014-04-07 04:55:00,18.591136533900002\n2014-04-07 05:00:00,20.982271806900002\n2014-04-07 05:05:00,20.5445461217\n2014-04-07 05:10:00,18.7501121918\n2014-04-07 05:15:00,18.6829283045\n2014-04-07 05:20:00,21.4813103748\n2014-04-07 05:25:00,19.678779694\n2014-04-07 05:30:00,20.6183060567\n2014-04-07 05:35:00,20.0162840154\n2014-04-07 05:40:00,20.9094140683\n2014-04-07 05:45:00,19.9169695002\n2014-04-07 05:50:00,19.149519661\n2014-04-07 05:55:00,19.453533484\n2014-04-07 06:00:00,21.4363107778\n2014-04-07 06:05:00,19.8721387717\n2014-04-07 06:10:00,18.853797329000002\n2014-04-07 06:15:00,21.7384215523\n2014-04-07 06:20:00,21.186401825999997\n2014-04-07 06:25:00,18.2226645842\n2014-04-07 06:30:00,21.9957718479\n2014-04-07 06:35:00,20.7797067858\n2014-04-07 06:40:00,18.6410663962\n2014-04-07 06:45:00,18.9486707252\n2014-04-07 06:50:00,20.769781925\n2014-04-07 06:55:00,21.119044221099998\n2014-04-07 07:00:00,18.9561437726\n2014-04-07 07:05:00,19.0278754156\n2014-04-07 07:10:00,19.228482779500002\n2014-04-07 07:15:00,20.3920734593\n2014-04-07 07:20:00,18.687264713199998\n2014-04-07 07:25:00,18.416972795499998\n2014-04-07 07:30:00,20.715456356300002\n2014-04-07 07:35:00,21.1163917592\n2014-04-07 07:40:00,20.0037176177\n2014-04-07 07:45:00,19.4553308411\n2014-04-07 07:50:00,19.7281708541\n2014-04-07 07:55:00,19.5536313355\n2014-04-07 08:00:00,21.839939633\n2014-04-07 08:05:00,21.0723596209\n2014-04-07 08:10:00,18.8323488594\n2014-04-07 08:15:00,19.5367566082\n2014-04-07 08:20:00,20.1760491655\n2014-04-07 08:25:00,20.4519434483\n2014-04-07 08:30:00,19.872735584100003\n2014-04-07 08:35:00,21.24050654\n2014-04-07 08:40:00,21.0704240778\n2014-04-07 08:45:00,20.0206316745\n2014-04-07 08:50:00,21.4177175471\n2014-04-07 08:55:00,21.0043581218\n2014-04-07 09:00:00,71.7887131426\n2014-04-07 09:05:00,74.2070506003\n2014-04-07 09:10:00,64.8239504004\n2014-04-07 09:15:00,64.8400150082\n2014-04-07 09:20:00,73.2897506774\n2014-04-07 09:25:00,71.702278678\n2014-04-07 09:30:00,73.8010193635\n2014-04-07 09:35:00,62.0585701804\n2014-04-07 09:40:00,69.73749625079999\n2014-04-07 09:45:00,63.166945398500005\n2014-04-07 09:50:00,68.0530018968\n2014-04-07 09:55:00,63.3181582732\n2014-04-07 10:00:00,71.8277784594\n2014-04-07 10:05:00,70.0288527203\n2014-04-07 10:10:00,79.6213063682\n2014-04-07 10:15:00,75.41203101100001\n2014-04-07 10:20:00,71.47252218130002\n2014-04-07 10:25:00,74.8504423104\n2014-04-07 10:30:00,72.4620122993\n2014-04-07 10:35:00,84.4551037849\n2014-04-07 10:40:00,74.806475827\n2014-04-07 10:45:00,75.0229586815\n2014-04-07 10:50:00,82.8745962128\n2014-04-07 10:55:00,79.8931694152\n2014-04-07 11:00:00,82.8625692441\n2014-04-07 11:05:00,81.68297269060001\n2014-04-07 11:10:00,86.6163056999\n2014-04-07 11:15:00,74.86014122510001\n2014-04-07 11:20:00,87.2976801009\n2014-04-07 11:25:00,84.7835270479\n2014-04-07 11:30:00,80.9350200535\n2014-04-07 11:35:00,82.10235831439999\n2014-04-07 11:40:00,81.88692673989999\n2014-04-07 11:45:00,72.4967335474\n2014-04-07 11:50:00,75.03533439270001\n2014-04-07 11:55:00,86.8592329475\n2014-04-07 12:00:00,80.4531710647\n2014-04-07 12:05:00,77.959993263\n2014-04-07 12:10:00,84.0915842757\n2014-04-07 12:15:00,80.2958323188\n2014-04-07 12:20:00,72.1239516177\n2014-04-07 12:25:00,83.67926578560001\n2014-04-07 12:30:00,83.6150223837\n2014-04-07 12:35:00,74.5528085385\n2014-04-07 12:40:00,87.2017935411\n2014-04-07 12:45:00,75.4918310685\n2014-04-07 12:50:00,79.2288010903\n2014-04-07 12:55:00,73.7471724497\n2014-04-07 13:00:00,81.6329205071\n2014-04-07 13:05:00,77.9884961886\n2014-04-07 13:10:00,77.63213920930001\n2014-04-07 13:15:00,85.2111744443\n2014-04-07 13:20:00,72.1356706886\n2014-04-07 13:25:00,84.74680421869998\n2014-04-07 13:30:00,81.12370268949999\n2014-04-07 13:35:00,87.7565095974\n2014-04-07 13:40:00,81.41154806770001\n2014-04-07 13:45:00,72.8685734905\n2014-04-07 13:50:00,72.792850745\n2014-04-07 13:55:00,86.10977647450001\n2014-04-07 14:00:00,85.4553242757\n2014-04-07 14:05:00,77.53051956569999\n2014-04-07 14:10:00,81.884589098\n2014-04-07 14:15:00,79.8296297067\n2014-04-07 14:20:00,87.4704261002\n2014-04-07 14:25:00,87.1951888441\n2014-04-07 14:30:00,87.7372125483\n2014-04-07 14:35:00,85.8590590575\n2014-04-07 14:40:00,86.5486709168\n2014-04-07 14:45:00,75.4728375902\n2014-04-07 14:50:00,85.2920144106\n2014-04-07 14:55:00,83.337713409\n2014-04-07 15:00:00,87.4037450572\n2014-04-07 15:05:00,81.1394103093\n2014-04-07 15:10:00,73.36197038569999\n2014-04-07 15:15:00,81.55759929850001\n2014-04-07 15:20:00,82.9844981895\n2014-04-07 15:25:00,75.5244114181\n2014-04-07 15:30:00,78.3050624004\n2014-04-07 15:35:00,81.5752714947\n2014-04-07 15:40:00,77.9849431344\n2014-04-07 15:45:00,77.99841468380002\n2014-04-07 15:50:00,74.12867458470001\n2014-04-07 15:55:00,87.0511118705\n2014-04-07 16:00:00,84.0077488567\n2014-04-07 16:05:00,72.0197567437\n2014-04-07 16:10:00,84.24965078470001\n2014-04-07 16:15:00,83.836558916\n2014-04-07 16:20:00,72.1555568236\n2014-04-07 16:25:00,77.9135191676\n2014-04-07 16:30:00,81.7078061659\n2014-04-07 16:35:00,79.2438582812\n2014-04-07 16:40:00,84.4476157598\n2014-04-07 16:45:00,78.8071820121\n2014-04-07 16:50:00,74.4616645446\n2014-04-07 16:55:00,87.62248175290001\n2014-04-07 17:00:00,75.87261074930001\n2014-04-07 17:05:00,83.4830449112\n2014-04-07 17:10:00,74.2904724591\n2014-04-07 17:15:00,77.2641721511\n2014-04-07 17:20:00,79.0724113711\n2014-04-07 17:25:00,75.07568324340001\n2014-04-07 17:30:00,79.1993228093\n2014-04-07 17:35:00,74.5145765543\n2014-04-07 17:40:00,80.9440735412\n2014-04-07 17:45:00,82.61938031449999\n2014-04-07 17:50:00,72.9989205129\n2014-04-07 17:55:00,85.9380809371\n2014-04-07 18:00:00,29.9848959072\n2014-04-07 18:05:00,30.242313715500003\n2014-04-07 18:10:00,33.0326326343\n2014-04-07 18:15:00,31.8000006812\n2014-04-07 18:20:00,31.9961256914\n2014-04-07 18:25:00,29.6201862141\n2014-04-07 18:30:00,33.9567027403\n2014-04-07 18:35:00,32.7491408872\n2014-04-07 18:40:00,29.6664393812\n2014-04-07 18:45:00,31.1935899598\n2014-04-07 18:50:00,33.9866170441\n2014-04-07 18:55:00,32.437466066300004\n2014-04-07 19:00:00,20.6467453979\n2014-04-07 19:05:00,21.8300399676\n2014-04-07 19:10:00,21.247269739500002\n2014-04-07 19:15:00,22.4782444473\n2014-04-07 19:20:00,23.9382565442\n2014-04-07 19:25:00,22.114475550799998\n2014-04-07 19:30:00,22.1013710836\n2014-04-07 19:35:00,24.215970714\n2014-04-07 19:40:00,22.7413094005\n2014-04-07 19:45:00,22.696534826500002\n2014-04-07 19:50:00,21.3333551453\n2014-04-07 19:55:00,22.882596655\n2014-04-07 20:00:00,20.7909290251\n2014-04-07 20:05:00,20.0575033818\n2014-04-07 20:10:00,22.489888768\n2014-04-07 20:15:00,22.0442251279\n2014-04-07 20:20:00,21.502305186100006\n2014-04-07 20:25:00,20.6329672825\n2014-04-07 20:30:00,20.3245967047\n2014-04-07 20:35:00,19.1893395006\n2014-04-07 20:40:00,19.6843004574\n2014-04-07 20:45:00,21.6021431769\n2014-04-07 20:50:00,20.2905554718\n2014-04-07 20:55:00,22.045775675300003\n2014-04-07 21:00:00,18.680884393499998\n2014-04-07 21:05:00,20.1295485991\n2014-04-07 21:10:00,20.6866844266\n2014-04-07 21:15:00,20.1637172663\n2014-04-07 21:20:00,21.660380669699997\n2014-04-07 21:25:00,22.0636526884\n2014-04-07 21:30:00,18.5519626134\n2014-04-07 21:35:00,18.608714705\n2014-04-07 21:40:00,18.6101986317\n2014-04-07 21:45:00,20.8241869336\n2014-04-07 21:50:00,19.5842597151\n2014-04-07 21:55:00,21.0337382351\n2014-04-07 22:00:00,19.6407228924\n2014-04-07 22:05:00,20.5301168851\n2014-04-07 22:10:00,21.0996682671\n2014-04-07 22:15:00,20.2122487818\n2014-04-07 22:20:00,20.177366045699998\n2014-04-07 22:25:00,18.3705561119\n2014-04-07 22:30:00,19.6619843639\n2014-04-07 22:35:00,20.202484387200002\n2014-04-07 22:40:00,19.8669772993\n2014-04-07 22:45:00,21.623866993000004\n2014-04-07 22:50:00,21.6468835955\n2014-04-07 22:55:00,21.3081056746\n2014-04-07 23:00:00,19.5049365285\n2014-04-07 23:05:00,20.873203490399998\n2014-04-07 23:10:00,19.5849134239\n2014-04-07 23:15:00,18.9340090259\n2014-04-07 23:20:00,19.3753299215\n2014-04-07 23:25:00,18.2873690322\n2014-04-07 23:30:00,19.3308208392\n2014-04-07 23:35:00,19.8467787171\n2014-04-07 23:40:00,21.8261133863\n2014-04-07 23:45:00,19.2573390423\n2014-04-07 23:50:00,21.613963239\n2014-04-07 23:55:00,18.9190648646\n2014-04-08 00:00:00,18.763875590999998\n2014-04-08 00:05:00,20.075981825699998\n2014-04-08 00:10:00,20.6900454772\n2014-04-08 00:15:00,18.1773290032\n2014-04-08 00:20:00,18.8842634602\n2014-04-08 00:25:00,19.822734666\n2014-04-08 00:30:00,19.3240173439\n2014-04-08 00:35:00,20.8504843174\n2014-04-08 00:40:00,20.0446423842\n2014-04-08 00:45:00,18.6414364224\n2014-04-08 00:50:00,21.5778615173\n2014-04-08 00:55:00,19.171622701900002\n2014-04-08 01:00:00,20.9245244359\n2014-04-08 01:05:00,21.1196631164\n2014-04-08 01:10:00,21.852630801\n2014-04-08 01:15:00,19.9940298661\n2014-04-08 01:20:00,20.4633420619\n2014-04-08 01:25:00,19.3395051739\n2014-04-08 01:30:00,20.712717173599998\n2014-04-08 01:35:00,19.8535339435\n2014-04-08 01:40:00,19.7506094589\n2014-04-08 01:45:00,21.421870116500003\n2014-04-08 01:50:00,18.200675374\n2014-04-08 01:55:00,21.5278497113\n2014-04-08 02:00:00,21.408279351300003\n2014-04-08 02:05:00,20.0254650142\n2014-04-08 02:10:00,19.960811416800002\n2014-04-08 02:15:00,19.447229472100002\n2014-04-08 02:20:00,21.9766951667\n2014-04-08 02:25:00,18.444677330999998\n2014-04-08 02:30:00,20.3608609425\n2014-04-08 02:35:00,20.7267263604\n2014-04-08 02:40:00,21.7373200329\n2014-04-08 02:45:00,21.120813987400002\n2014-04-08 02:50:00,20.5753888112\n2014-04-08 02:55:00,18.4672492672\n2014-04-08 03:00:00,19.4949340673\n2014-04-08 03:05:00,18.5553665702\n2014-04-08 03:10:00,21.524850929899998\n2014-04-08 03:15:00,20.9984846223\n2014-04-08 03:20:00,21.0301471472\n2014-04-08 03:25:00,20.6090260711\n2014-04-08 03:30:00,20.0281741477\n2014-04-08 03:35:00,18.5998842379\n2014-04-08 03:40:00,19.318779546800002\n2014-04-08 03:45:00,18.5476631699\n2014-04-08 03:50:00,20.8996525714\n2014-04-08 03:55:00,18.6409151041\n2014-04-08 04:00:00,20.808454200699998\n2014-04-08 04:05:00,20.7690215584\n2014-04-08 04:10:00,19.837217916\n2014-04-08 04:15:00,18.5409146165\n2014-04-08 04:20:00,19.2592033045\n2014-04-08 04:25:00,19.280372436300002\n2014-04-08 04:30:00,20.8015405326\n2014-04-08 04:35:00,18.4549720777\n2014-04-08 04:40:00,21.3162745849\n2014-04-08 04:45:00,21.0440291607\n2014-04-08 04:50:00,18.7452276727\n2014-04-08 04:55:00,20.8766575271\n2014-04-08 05:00:00,20.674052725899998\n2014-04-08 05:05:00,20.9924832004\n2014-04-08 05:10:00,18.7557142218\n2014-04-08 05:15:00,18.6303612886\n2014-04-08 05:20:00,18.9459359437\n2014-04-08 05:25:00,19.4634868126\n2014-04-08 05:30:00,21.174659924100002\n2014-04-08 05:35:00,20.9516957499\n2014-04-08 05:40:00,21.701806369099998\n2014-04-08 05:45:00,18.2345182364\n2014-04-08 05:50:00,18.0462251241\n2014-04-08 05:55:00,20.7965553188\n2014-04-08 06:00:00,19.1171499832\n2014-04-08 06:05:00,19.3363155821\n2014-04-08 06:10:00,20.187208103699998\n2014-04-08 06:15:00,18.4096524925\n2014-04-08 06:20:00,20.570777666199998\n2014-04-08 06:25:00,19.3005897849\n2014-04-08 06:30:00,20.5308604972\n2014-04-08 06:35:00,21.3360276523\n2014-04-08 06:40:00,18.684445333299998\n2014-04-08 06:45:00,21.7234923717\n2014-04-08 06:50:00,20.122752564200002\n2014-04-08 06:55:00,21.6917110607\n2014-04-08 07:00:00,18.8309203288\n2014-04-08 07:05:00,20.418250658399998\n2014-04-08 07:10:00,19.615548469300002\n2014-04-08 07:15:00,21.0968887646\n2014-04-08 07:20:00,20.4236357729\n2014-04-08 07:25:00,19.9780618278\n2014-04-08 07:30:00,21.6519416257\n2014-04-08 07:35:00,19.508468256700002\n2014-04-08 07:40:00,18.8799208196\n2014-04-08 07:45:00,20.4324047474\n2014-04-08 07:50:00,20.496113748699997\n2014-04-08 07:55:00,19.7563784863\n2014-04-08 08:00:00,19.9464401748\n2014-04-08 08:05:00,21.838213657199997\n2014-04-08 08:10:00,20.930742765599998\n2014-04-08 08:15:00,18.442407005899998\n2014-04-08 08:20:00,18.848520283499997\n2014-04-08 08:25:00,21.9023065377\n2014-04-08 08:30:00,20.9058622152\n2014-04-08 08:35:00,21.6601805046\n2014-04-08 08:40:00,19.215445856\n2014-04-08 08:45:00,20.9674674403\n2014-04-08 08:50:00,20.8560108341\n2014-04-08 08:55:00,19.1787599418\n2014-04-08 09:00:00,68.6911020261\n2014-04-08 09:05:00,69.7328455133\n2014-04-08 09:10:00,67.7433926273\n2014-04-08 09:15:00,72.4496304105\n2014-04-08 09:20:00,72.5270189685\n2014-04-08 09:25:00,72.7681674569\n2014-04-08 09:30:00,72.12656053970001\n2014-04-08 09:35:00,67.8379352899\n2014-04-08 09:40:00,66.3875608548\n2014-04-08 09:45:00,72.5067174585\n2014-04-08 09:50:00,67.8667398364\n2014-04-08 09:55:00,64.5506510213\n2014-04-08 10:00:00,77.7139716216\n2014-04-08 10:05:00,72.0415092362\n2014-04-08 10:10:00,80.5740896941\n2014-04-08 10:15:00,75.0534982908\n2014-04-08 10:20:00,73.8854245519\n2014-04-08 10:25:00,84.6850157416\n2014-04-08 10:30:00,81.8971930542\n2014-04-08 10:35:00,82.0553186823\n2014-04-08 10:40:00,79.5201649632\n2014-04-08 10:45:00,82.8639620191\n2014-04-08 10:50:00,81.6222017077\n2014-04-08 10:55:00,79.1329678882\n2014-04-08 11:00:00,86.85372248700001\n2014-04-08 11:05:00,74.61512607979999\n2014-04-08 11:10:00,86.5715110509\n2014-04-08 11:15:00,77.95247252840001\n2014-04-08 11:20:00,79.971657432\n2014-04-08 11:25:00,73.520046138\n2014-04-08 11:30:00,80.15786870859999\n2014-04-08 11:35:00,81.2886321816\n2014-04-08 11:40:00,87.4354453209\n2014-04-08 11:45:00,87.0774601057\n2014-04-08 11:50:00,86.93758253\n2014-04-08 11:55:00,77.1087637079\n2014-04-08 12:00:00,87.75483166309998\n2014-04-08 12:05:00,79.192505245\n2014-04-08 12:10:00,85.526624884\n2014-04-08 12:15:00,75.3705661609\n2014-04-08 12:20:00,79.9972188775\n2014-04-08 12:25:00,87.3512461058\n2014-04-08 12:30:00,87.047919348\n2014-04-08 12:35:00,82.8402303355\n2014-04-08 12:40:00,84.6633111259\n2014-04-08 12:45:00,74.7330397531\n2014-04-08 12:50:00,83.4462809476\n2014-04-08 12:55:00,81.7905463578\n2014-04-08 13:00:00,73.4471962134\n2014-04-08 13:05:00,73.7928295748\n2014-04-08 13:10:00,73.7174014605\n2014-04-08 13:15:00,83.5696494266\n2014-04-08 13:20:00,74.24961914560001\n2014-04-08 13:25:00,79.4646402459\n2014-04-08 13:30:00,77.6930580839\n2014-04-08 13:35:00,80.78867231640001\n2014-04-08 13:40:00,83.2836309258\n2014-04-08 13:45:00,82.935651261\n2014-04-08 13:50:00,80.2290590582\n2014-04-08 13:55:00,79.4102949319\n2014-04-08 14:00:00,78.3612879996\n2014-04-08 14:05:00,85.78644122600001\n2014-04-08 14:10:00,77.2899187838\n2014-04-08 14:15:00,76.1461979457\n2014-04-08 14:20:00,83.8890210322\n2014-04-08 14:25:00,77.7524830888\n2014-04-08 14:30:00,85.5478711012\n2014-04-08 14:35:00,77.2425116797\n2014-04-08 14:40:00,83.2271220996\n2014-04-08 14:45:00,72.7182534568\n2014-04-08 14:50:00,78.1652539695\n2014-04-08 14:55:00,77.4879631987\n2014-04-08 15:00:00,85.0660431866\n2014-04-08 15:05:00,87.4720467119\n2014-04-08 15:10:00,79.37333843569999\n2014-04-08 15:15:00,85.1965625396\n2014-04-08 15:20:00,83.1943165422\n2014-04-08 15:25:00,87.4773360121\n2014-04-08 15:30:00,84.9769204432\n2014-04-08 15:35:00,73.2389459548\n2014-04-08 15:40:00,83.411706798\n2014-04-08 15:45:00,80.567221994\n2014-04-08 15:50:00,72.2622832023\n2014-04-08 15:55:00,76.0202775379\n2014-04-08 16:00:00,86.7479173641\n2014-04-08 16:05:00,86.816815276\n2014-04-08 16:10:00,84.7814445825\n2014-04-08 16:15:00,87.70830525219999\n2014-04-08 16:20:00,84.9045605769\n2014-04-08 16:25:00,72.1631284431\n2014-04-08 16:30:00,76.6052023626\n2014-04-08 16:35:00,72.489847735\n2014-04-08 16:40:00,73.5055863688\n2014-04-08 16:45:00,75.5013081084\n2014-04-08 16:50:00,80.0567830319\n2014-04-08 16:55:00,85.5603477792\n2014-04-08 17:00:00,85.7914351546\n2014-04-08 17:05:00,81.859198303\n2014-04-08 17:10:00,86.85078167430002\n2014-04-08 17:15:00,80.0009665051\n2014-04-08 17:20:00,86.2245435959\n2014-04-08 17:25:00,79.2650136635\n2014-04-08 17:30:00,76.4355707675\n2014-04-08 17:35:00,86.66257341120001\n2014-04-08 17:40:00,78.2069311794\n2014-04-08 17:45:00,80.05443500060001\n2014-04-08 17:50:00,77.261740452\n2014-04-08 17:55:00,82.6053698842\n2014-04-08 18:00:00,35.1681930877\n2014-04-08 18:05:00,28.963281151799997\n2014-04-08 18:10:00,34.5590206031\n2014-04-08 18:15:00,28.825121230300002\n2014-04-08 18:20:00,31.1310524622\n2014-04-08 18:25:00,29.879077823499998\n2014-04-08 18:30:00,33.6469809361\n2014-04-08 18:35:00,29.123903789099998\n2014-04-08 18:40:00,32.3422974932\n2014-04-08 18:45:00,30.687521364600002\n2014-04-08 18:50:00,29.6554838989\n2014-04-08 18:55:00,33.7396300794\n2014-04-08 19:00:00,21.1340262581\n2014-04-08 19:05:00,21.1620637891\n2014-04-08 19:10:00,21.3923428239\n2014-04-08 19:15:00,22.788713851799997\n2014-04-08 19:20:00,23.115302105900003\n2014-04-08 19:25:00,20.2388581959\n2014-04-08 19:30:00,21.2435748044\n2014-04-08 19:35:00,22.0907481626\n2014-04-08 19:40:00,21.6472555582\n2014-04-08 19:45:00,24.1210832269\n2014-04-08 19:50:00,23.688933814899997\n2014-04-08 19:55:00,22.9639869059\n2014-04-08 20:00:00,19.816621498099998\n2014-04-08 20:05:00,21.3019536689\n2014-04-08 20:10:00,21.887541038000002\n2014-04-08 20:15:00,20.8684249752\n2014-04-08 20:20:00,21.6451539087\n2014-04-08 20:25:00,21.500333663899998\n2014-04-08 20:30:00,20.7738357772\n2014-04-08 20:35:00,19.7107022196\n2014-04-08 20:40:00,21.486723461300002\n2014-04-08 20:45:00,19.2790376853\n2014-04-08 20:50:00,21.6247840077\n2014-04-08 20:55:00,21.727422990300003\n2014-04-08 21:00:00,21.3907646477\n2014-04-08 21:05:00,19.987143821700002\n2014-04-08 21:10:00,18.8600186557\n2014-04-08 21:15:00,18.4872090482\n2014-04-08 21:20:00,21.074117486400002\n2014-04-08 21:25:00,21.648461703800002\n2014-04-08 21:30:00,20.7022494812\n2014-04-08 21:35:00,18.665808069100002\n2014-04-08 21:40:00,21.8439357525\n2014-04-08 21:45:00,22.0617987629\n2014-04-08 21:50:00,19.8282352606\n2014-04-08 21:55:00,20.4771217526\n2014-04-08 22:00:00,21.1291786271\n2014-04-08 22:05:00,20.9656668867\n2014-04-08 22:10:00,21.8921450598\n2014-04-08 22:15:00,18.477253506300002\n2014-04-08 22:20:00,20.3424094381\n2014-04-08 22:25:00,20.7876626851\n2014-04-08 22:30:00,21.581091664099997\n2014-04-08 22:35:00,21.5170750813\n2014-04-08 22:40:00,21.9330346827\n2014-04-08 22:45:00,20.0675601872\n2014-04-08 22:50:00,21.343513578499998\n2014-04-08 22:55:00,19.7280475846\n2014-04-08 23:00:00,19.693035846500003\n2014-04-08 23:05:00,19.0170440276\n2014-04-08 23:10:00,21.2770335522\n2014-04-08 23:15:00,21.9474735271\n2014-04-08 23:20:00,19.029019782\n2014-04-08 23:25:00,18.2280254594\n2014-04-08 23:30:00,21.2662520842\n2014-04-08 23:35:00,20.4848525448\n2014-04-08 23:40:00,21.8429882487\n2014-04-08 23:45:00,19.0126065942\n2014-04-08 23:50:00,18.287621179400002\n2014-04-08 23:55:00,19.9736032372\n2014-04-09 00:00:00,18.3418640919\n2014-04-09 00:05:00,19.047160004400002\n2014-04-09 00:10:00,18.503911443299998\n2014-04-09 00:15:00,18.8965287186\n2014-04-09 00:20:00,18.4245786113\n2014-04-09 00:25:00,21.8156239977\n2014-04-09 00:30:00,19.1142508538\n2014-04-09 00:35:00,19.775590344\n2014-04-09 00:40:00,21.594447230500002\n2014-04-09 00:45:00,20.7092863518\n2014-04-09 00:50:00,20.4721499222\n2014-04-09 00:55:00,20.8222527614\n2014-04-09 01:00:00,21.3152890284\n2014-04-09 01:05:00,21.5106770714\n2014-04-09 01:10:00,20.5705586827\n2014-04-09 01:15:00,21.5600290988\n2014-04-09 01:20:00,20.1415901097\n2014-04-09 01:25:00,19.1091634251\n2014-04-09 01:30:00,21.5203068355\n2014-04-09 01:35:00,20.1658913097\n2014-04-09 01:40:00,21.6245503503\n2014-04-09 01:45:00,18.1606712558\n2014-04-09 01:50:00,19.590063006199998\n2014-04-09 01:55:00,21.7912200734\n2014-04-09 02:00:00,18.998600371\n2014-04-09 02:05:00,21.7661449842\n2014-04-09 02:10:00,21.8156098445\n2014-04-09 02:15:00,21.5285692569\n2014-04-09 02:20:00,20.2546721804\n2014-04-09 02:25:00,20.5877577963\n2014-04-09 02:30:00,21.478467993800002\n2014-04-09 02:35:00,21.1035883296\n2014-04-09 02:40:00,20.5203753978\n2014-04-09 02:45:00,21.9290376315\n2014-04-09 02:50:00,20.7427065453\n2014-04-09 02:55:00,21.9019279698\n2014-04-09 03:00:00,18.2295538984\n2014-04-09 03:05:00,18.555841483\n2014-04-09 03:10:00,19.805835384\n2014-04-09 03:15:00,19.5395178435\n2014-04-09 03:20:00,21.1309393654\n2014-04-09 03:25:00,18.6424561059\n2014-04-09 03:30:00,21.9043807164\n2014-04-09 03:35:00,19.260263501\n2014-04-09 03:40:00,19.715694831\n2014-04-09 03:45:00,19.0989801298\n2014-04-09 03:50:00,20.3174544693\n2014-04-09 03:55:00,18.2345148017\n2014-04-09 04:00:00,18.5987100223\n2014-04-09 04:05:00,20.9831908137\n2014-04-09 04:10:00,18.7460023336\n2014-04-09 04:15:00,18.942057806199998\n2014-04-09 04:20:00,21.1719289429\n2014-04-09 04:25:00,18.3732047134\n2014-04-09 04:30:00,19.7498952911\n2014-04-09 04:35:00,18.092253548\n2014-04-09 04:40:00,19.3872295973\n2014-04-09 04:45:00,20.7959256104\n2014-04-09 04:50:00,18.360413118900002\n2014-04-09 04:55:00,21.5533385071\n2014-04-09 05:00:00,21.637996171799998\n2014-04-09 05:05:00,18.4199615005\n2014-04-09 05:10:00,21.962929745500002\n2014-04-09 05:15:00,19.190118213599998\n2014-04-09 05:20:00,18.3364066845\n2014-04-09 05:25:00,18.020268458\n2014-04-09 05:30:00,19.6340915831\n2014-04-09 05:35:00,20.5192399428\n2014-04-09 05:40:00,19.3287169996\n2014-04-09 05:45:00,21.3468694619\n2014-04-09 05:50:00,20.8664251023\n2014-04-09 05:55:00,19.4006461279\n2014-04-09 06:00:00,20.937238666400003\n2014-04-09 06:05:00,21.7619509479\n2014-04-09 06:10:00,18.3723839942\n2014-04-09 06:15:00,19.2244158406\n2014-04-09 06:20:00,19.8533037565\n2014-04-09 06:25:00,19.991960511\n2014-04-09 06:30:00,20.1687825795\n2014-04-09 06:35:00,19.2025076262\n2014-04-09 06:40:00,20.6690385839\n2014-04-09 06:45:00,20.5803380141\n2014-04-09 06:50:00,20.3112860251\n2014-04-09 06:55:00,18.4550468868\n2014-04-09 07:00:00,19.9078715644\n2014-04-09 07:05:00,19.42490755\n2014-04-09 07:10:00,19.9641538794\n2014-04-09 07:15:00,21.6874657421\n2014-04-09 07:20:00,19.9221253726\n2014-04-09 07:25:00,18.0559231674\n2014-04-09 07:30:00,19.755346952300002\n2014-04-09 07:35:00,21.2825927202\n2014-04-09 07:40:00,21.1202436929\n2014-04-09 07:45:00,20.053560294100002\n2014-04-09 07:50:00,18.9990760514\n2014-04-09 07:55:00,19.8603546517\n2014-04-09 08:00:00,20.2548088777\n2014-04-09 08:05:00,21.9994857531\n2014-04-09 08:10:00,20.5767123607\n2014-04-09 08:15:00,20.7770597203\n2014-04-09 08:20:00,19.9658165743\n2014-04-09 08:25:00,19.4179582031\n2014-04-09 08:30:00,21.2518119346\n2014-04-09 08:35:00,19.9797292974\n2014-04-09 08:40:00,21.978760519899996\n2014-04-09 08:45:00,19.8284822971\n2014-04-09 08:50:00,18.2720011346\n2014-04-09 08:55:00,20.7303125484\n2014-04-09 09:00:00,61.83432373260001\n2014-04-09 09:05:00,64.6068217176\n2014-04-09 09:10:00,66.0108402378\n2014-04-09 09:15:00,71.2569767645\n2014-04-09 09:20:00,67.9216085991\n2014-04-09 09:25:00,61.5895846658\n2014-04-09 09:30:00,69.58915797739999\n2014-04-09 09:35:00,66.795532829\n2014-04-09 09:40:00,73.7369493356\n2014-04-09 09:45:00,67.9940474315\n2014-04-09 09:50:00,70.8420619848\n2014-04-09 09:55:00,64.1766114957\n2014-04-09 10:00:00,81.6503097215\n2014-04-09 10:05:00,81.0292264187\n2014-04-09 10:10:00,83.8713481166\n2014-04-09 10:15:00,70.3649118795\n2014-04-09 10:20:00,76.785210827\n2014-04-09 10:25:00,80.38049185050001\n2014-04-09 10:30:00,71.3169437292\n2014-04-09 10:35:00,76.21257512220001\n2014-04-09 10:40:00,84.4621152796\n2014-04-09 10:45:00,76.60570329859999\n2014-04-09 10:50:00,85.1334822396\n2014-04-09 10:55:00,70.722142228\n2014-04-09 11:00:00,82.9843647597\n2014-04-09 11:05:00,80.8084822213\n2014-04-09 11:10:00,79.5285830251\n2014-04-09 11:15:00,87.0083570732\n2014-04-09 11:20:00,73.62995996939999\n2014-04-09 11:25:00,85.8179673275\n2014-04-09 11:30:00,82.5614874987\n2014-04-09 11:35:00,75.68707354979999\n2014-04-09 11:40:00,85.9081460921\n2014-04-09 11:45:00,78.3955063737\n2014-04-09 11:50:00,84.5174714257\n2014-04-09 11:55:00,77.7520559671\n2014-04-09 12:00:00,85.51215536699999\n2014-04-09 12:05:00,82.087442616\n2014-04-09 12:10:00,74.167638042\n2014-04-09 12:15:00,82.2957370828\n2014-04-09 12:20:00,74.9714423838\n2014-04-09 12:25:00,78.4964531319\n2014-04-09 12:30:00,74.6350596728\n2014-04-09 12:35:00,72.2654351413\n2014-04-09 12:40:00,75.2997164096\n2014-04-09 12:45:00,80.4852540367\n2014-04-09 12:50:00,79.60932951390001\n2014-04-09 12:55:00,79.9279247843\n2014-04-09 13:00:00,75.9447589375\n2014-04-09 13:05:00,82.9426681908\n2014-04-09 13:10:00,83.24822821810001\n2014-04-09 13:15:00,77.7088306125\n2014-04-09 13:20:00,86.0780577224\n2014-04-09 13:25:00,82.284618417\n2014-04-09 13:30:00,83.3886103333\n2014-04-09 13:35:00,76.4190937017\n2014-04-09 13:40:00,71.9925038138\n2014-04-09 13:45:00,85.82540675130002\n2014-04-09 13:50:00,85.1383520436\n2014-04-09 13:55:00,73.95331715180001\n2014-04-09 14:00:00,77.9819388466\n2014-04-09 14:05:00,82.5774650256\n2014-04-09 14:10:00,82.42981689439999\n2014-04-09 14:15:00,85.7614886079\n2014-04-09 14:20:00,74.2407268602\n2014-04-09 14:25:00,78.8752497708\n2014-04-09 14:30:00,73.5520600185\n2014-04-09 14:35:00,78.2297687659\n2014-04-09 14:40:00,72.2382515269\n2014-04-09 14:45:00,86.36822316799999\n2014-04-09 14:50:00,80.42884317949999\n2014-04-09 14:55:00,85.59272752470001\n2014-04-09 15:00:00,72.9577748147\n2014-04-09 15:05:00,75.63860363\n2014-04-09 15:10:00,76.1493488828\n2014-04-09 15:15:00,78.1863133184\n2014-04-09 15:20:00,84.84504743810001\n2014-04-09 15:25:00,78.1841754044\n2014-04-09 15:30:00,75.2737338396\n2014-04-09 15:35:00,73.0391429829\n2014-04-09 15:40:00,73.2711645637\n2014-04-09 15:45:00,84.1599473521\n2014-04-09 15:50:00,79.1160883348\n2014-04-09 15:55:00,83.6180952106\n2014-04-09 16:00:00,82.91643474840001\n2014-04-09 16:05:00,74.1656569898\n2014-04-09 16:10:00,74.28606431760001\n2014-04-09 16:15:00,84.0853108028\n2014-04-09 16:20:00,83.5401322984\n2014-04-09 16:25:00,78.0483424169\n2014-04-09 16:30:00,73.2386155949\n2014-04-09 16:35:00,72.1934297355\n2014-04-09 16:40:00,76.6103640992\n2014-04-09 16:45:00,72.1474178541\n2014-04-09 16:50:00,75.6810166298\n2014-04-09 16:55:00,78.7118607163\n2014-04-09 17:00:00,73.94262385100001\n2014-04-09 17:05:00,73.6684158366\n2014-04-09 17:10:00,86.3429658158\n2014-04-09 17:15:00,81.3674892192\n2014-04-09 17:20:00,86.9512575989\n2014-04-09 17:25:00,77.53318884779999\n2014-04-09 17:30:00,82.8342871889\n2014-04-09 17:35:00,75.2750378883\n2014-04-09 17:40:00,81.8934136294\n2014-04-09 17:45:00,74.073343236\n2014-04-09 17:50:00,72.033262566\n2014-04-09 17:55:00,86.90447545120001\n2014-04-09 18:00:00,32.3513177961\n2014-04-09 18:05:00,34.7324135732\n2014-04-09 18:10:00,30.9365158119\n2014-04-09 18:15:00,30.897824910300002\n2014-04-09 18:20:00,31.3641859894\n2014-04-09 18:25:00,33.318655900100005\n2014-04-09 18:30:00,32.4211690339\n2014-04-09 18:35:00,34.7222647388\n2014-04-09 18:40:00,28.9628162064\n2014-04-09 18:45:00,33.3324476032\n2014-04-09 18:50:00,30.914091276399997\n2014-04-09 18:55:00,29.9534896206\n2014-04-09 19:00:00,22.4465711575\n2014-04-09 19:05:00,22.4226845231\n2014-04-09 19:10:00,20.7738082689\n2014-04-09 19:15:00,21.064493175899997\n2014-04-09 19:20:00,21.9885764925\n2014-04-09 19:25:00,21.991473921100006\n2014-04-09 19:30:00,21.5826592815\n2014-04-09 19:35:00,20.825481136300002\n2014-04-09 19:40:00,20.1795929754\n2014-04-09 19:45:00,24.506651735300004\n2014-04-09 19:50:00,24.3868752113\n2014-04-09 19:55:00,22.326752473899997\n2014-04-09 20:00:00,22.5077317113\n2014-04-09 20:05:00,21.1912878846\n2014-04-09 20:10:00,18.714040249500002\n2014-04-09 20:15:00,18.9141735165\n2014-04-09 20:20:00,22.184389750300003\n2014-04-09 20:25:00,21.0126935679\n2014-04-09 20:30:00,21.885679872199997\n2014-04-09 20:35:00,22.111312219600002\n2014-04-09 20:40:00,20.266770235\n2014-04-09 20:45:00,18.6307620741\n2014-04-09 20:50:00,19.203196078599998\n2014-04-09 20:55:00,18.7046784717\n2014-04-09 21:00:00,18.844983141700002\n2014-04-09 21:05:00,19.7364138897\n2014-04-09 21:10:00,18.5614565754\n2014-04-09 21:15:00,18.756534223699997\n2014-04-09 21:20:00,19.8782468579\n2014-04-09 21:25:00,19.4536150362\n2014-04-09 21:30:00,19.9660114839\n2014-04-09 21:35:00,19.8113281655\n2014-04-09 21:40:00,20.676686031400003\n2014-04-09 21:45:00,21.8531521814\n2014-04-09 21:50:00,18.5199283038\n2014-04-09 21:55:00,18.485346346900002\n2014-04-09 22:00:00,21.4317792093\n2014-04-09 22:05:00,20.0448113721\n2014-04-09 22:10:00,21.0858430792\n2014-04-09 22:15:00,18.8797948253\n2014-04-09 22:20:00,21.335913114500002\n2014-04-09 22:25:00,21.7162140571\n2014-04-09 22:30:00,20.5616523069\n2014-04-09 22:35:00,18.4412026523\n2014-04-09 22:40:00,21.6018971781\n2014-04-09 22:45:00,21.1902740519\n2014-04-09 22:50:00,21.023674466400003\n2014-04-09 22:55:00,18.1643337829\n2014-04-09 23:00:00,21.1999197022\n2014-04-09 23:05:00,18.555365986400002\n2014-04-09 23:10:00,18.8931714955\n2014-04-09 23:15:00,20.312438577\n2014-04-09 23:20:00,19.063582595\n2014-04-09 23:25:00,20.649356738599998\n2014-04-09 23:30:00,20.4362047869\n2014-04-09 23:35:00,18.436137449100002\n2014-04-09 23:40:00,20.6280181355\n2014-04-09 23:45:00,21.699985234499998\n2014-04-09 23:50:00,18.6480193513\n2014-04-09 23:55:00,20.3921626254\n2014-04-10 00:00:00,19.367461487699998\n2014-04-10 00:05:00,19.8384466871\n2014-04-10 00:10:00,19.1480007163\n2014-04-10 00:15:00,19.4165225454\n2014-04-10 00:20:00,18.1156472931\n2014-04-10 00:25:00,21.9262069517\n2014-04-10 00:30:00,20.4991996883\n2014-04-10 00:35:00,20.002822362\n2014-04-10 00:40:00,19.534861398\n2014-04-10 00:45:00,20.1574982353\n2014-04-10 00:50:00,19.5204239949\n2014-04-10 00:55:00,19.43963171\n2014-04-10 01:00:00,19.8557861669\n2014-04-10 01:05:00,19.1039321347\n2014-04-10 01:10:00,18.7201995999\n2014-04-10 01:15:00,20.2264235927\n2014-04-10 01:20:00,21.3710617446\n2014-04-10 01:25:00,18.6113127109\n2014-04-10 01:30:00,18.1309373624\n2014-04-10 01:35:00,18.9872469806\n2014-04-10 01:40:00,21.9188825738\n2014-04-10 01:45:00,21.315032295\n2014-04-10 01:50:00,20.3834642141\n2014-04-10 01:55:00,21.716995661\n2014-04-10 02:00:00,19.7811164673\n2014-04-10 02:05:00,21.9331224103\n2014-04-10 02:10:00,19.1852081805\n2014-04-10 02:15:00,18.9612229981\n2014-04-10 02:20:00,20.5521928046\n2014-04-10 02:25:00,19.5126158718\n2014-04-10 02:30:00,20.5054621679\n2014-04-10 02:35:00,19.2199820732\n2014-04-10 02:40:00,20.4716730274\n2014-04-10 02:45:00,19.1029850423\n2014-04-10 02:50:00,18.2038882753\n2014-04-10 02:55:00,21.6485436077\n2014-04-10 03:00:00,21.5328208075\n2014-04-10 03:05:00,21.8831925971\n2014-04-10 03:10:00,20.8661087049\n2014-04-10 03:15:00,20.7308847109\n2014-04-10 03:20:00,20.2360122803\n2014-04-10 03:25:00,18.5037696654\n2014-04-10 03:30:00,18.7569412438\n2014-04-10 03:35:00,19.1578787547\n2014-04-10 03:40:00,21.5606254503\n2014-04-10 03:45:00,18.6918780984\n2014-04-10 03:50:00,21.691492698\n2014-04-10 03:55:00,20.0911429322\n2014-04-10 04:00:00,20.8622785419\n2014-04-10 04:05:00,18.440977946700002\n2014-04-10 04:10:00,19.0761341951\n2014-04-10 04:15:00,21.8340744327\n2014-04-10 04:20:00,19.0645997877\n2014-04-10 04:25:00,19.1860868816\n2014-04-10 04:30:00,18.7903895394\n2014-04-10 04:35:00,18.5162946612\n2014-04-10 04:40:00,18.9330305658\n2014-04-10 04:45:00,20.5693075678\n2014-04-10 04:50:00,19.821470934\n2014-04-10 04:55:00,20.2150233454\n2014-04-10 05:00:00,18.4894593151\n2014-04-10 05:05:00,21.2084657887\n2014-04-10 05:10:00,21.1363788023\n2014-04-10 05:15:00,18.0863596446\n2014-04-10 05:20:00,19.534060378\n2014-04-10 05:25:00,18.2750824079\n2014-04-10 05:30:00,21.1684231177\n2014-04-10 05:35:00,20.9490787325\n2014-04-10 05:40:00,21.607952377199997\n2014-04-10 05:45:00,18.945615835799998\n2014-04-10 05:50:00,19.8251835325\n2014-04-10 05:55:00,18.7379515087\n2014-04-10 06:00:00,19.4849397379\n2014-04-10 06:05:00,20.0889730063\n2014-04-10 06:10:00,18.2133231594\n2014-04-10 06:15:00,20.8594816427\n2014-04-10 06:20:00,20.1731734415\n2014-04-10 06:25:00,21.3158360688\n2014-04-10 06:30:00,19.0871220048\n2014-04-10 06:35:00,21.6132844211\n2014-04-10 06:40:00,21.994777012100002\n2014-04-10 06:45:00,21.6771937535\n2014-04-10 06:50:00,21.111569903299998\n2014-04-10 06:55:00,21.249475211500002\n2014-04-10 07:00:00,20.2949769702\n2014-04-10 07:05:00,18.7606154517\n2014-04-10 07:10:00,20.7081627406\n2014-04-10 07:15:00,20.851012008199998\n2014-04-10 07:20:00,21.941540561100002\n2014-04-10 07:25:00,20.165205265\n2014-04-10 07:30:00,19.0854760601\n2014-04-10 07:35:00,20.734690087\n2014-04-10 07:40:00,21.9175032787\n2014-04-10 07:45:00,18.7088556331\n2014-04-10 07:50:00,19.3039916741\n2014-04-10 07:55:00,20.1675238151\n2014-04-10 08:00:00,18.6808585395\n2014-04-10 08:05:00,18.0888825581\n2014-04-10 08:10:00,19.3479324898\n2014-04-10 08:15:00,21.461483206\n2014-04-10 08:20:00,18.173873597300002\n2014-04-10 08:25:00,19.7157162361\n2014-04-10 08:30:00,21.0488030917\n2014-04-10 08:35:00,21.812730387600002\n2014-04-10 08:40:00,21.941901595999997\n2014-04-10 08:45:00,19.6878775224\n2014-04-10 08:50:00,21.8015371775\n2014-04-10 08:55:00,18.1416758931\n2014-04-10 09:00:00,71.3444703568\n2014-04-10 09:05:00,69.941346071\n2014-04-10 09:10:00,64.59349726319999\n2014-04-10 09:15:00,68.0995316092\n2014-04-10 09:20:00,62.961930833500006\n2014-04-10 09:25:00,73.0537212529\n2014-04-10 09:30:00,66.0674139634\n2014-04-10 09:35:00,69.7142047983\n2014-04-10 09:40:00,63.359357493500006\n2014-04-10 09:45:00,64.003841887\n2014-04-10 09:50:00,74.6906066429\n2014-04-10 09:55:00,71.44197496439999\n2014-04-10 10:00:00,84.7698034189\n2014-04-10 10:05:00,74.4316100841\n2014-04-10 10:10:00,72.3940158451\n2014-04-10 10:15:00,77.6476225532\n2014-04-10 10:20:00,77.51725174020001\n2014-04-10 10:25:00,72.55516989350001\n2014-04-10 10:30:00,81.2195677199\n2014-04-10 10:35:00,75.4547873345\n2014-04-10 10:40:00,72.73238838399999\n2014-04-10 10:45:00,74.9923822833\n2014-04-10 10:50:00,78.5879830183\n2014-04-10 10:55:00,81.11482886739999\n2014-04-10 11:00:00,79.2319926519\n2014-04-10 11:05:00,79.92706271819999\n2014-04-10 11:10:00,73.7777961652\n2014-04-10 11:15:00,86.1152444666\n2014-04-10 11:20:00,86.3384296449\n2014-04-10 11:25:00,82.437216494\n2014-04-10 11:30:00,71.8484099277\n2014-04-10 11:35:00,80.1096283297\n2014-04-10 11:40:00,81.5750985321\n2014-04-10 11:45:00,87.3869807619\n2014-04-10 11:50:00,87.40944885540002\n2014-04-10 11:55:00,85.2074490866\n2014-04-10 12:00:00,72.9336703174\n2014-04-10 12:05:00,87.1477193458\n2014-04-10 12:10:00,81.70441685850001\n2014-04-10 12:15:00,84.7124113017\n2014-04-10 12:20:00,78.42086749229999\n2014-04-10 12:25:00,77.0221738859\n2014-04-10 12:30:00,79.3166120401\n2014-04-10 12:35:00,74.2607722169\n2014-04-10 12:40:00,77.6198025502\n2014-04-10 12:45:00,85.61901374029999\n2014-04-10 12:50:00,72.5200791308\n2014-04-10 12:55:00,74.3247518907\n2014-04-10 13:00:00,73.9840981083\n2014-04-10 13:05:00,78.4303808731\n2014-04-10 13:10:00,87.93068198459999\n2014-04-10 13:15:00,74.7557811889\n2014-04-10 13:20:00,74.30988374020001\n2014-04-10 13:25:00,86.6200978624\n2014-04-10 13:30:00,86.0921411975\n2014-04-10 13:35:00,72.4984421169\n2014-04-10 13:40:00,84.007128812\n2014-04-10 13:45:00,82.4676542353\n2014-04-10 13:50:00,84.26362483289998\n2014-04-10 13:55:00,79.89286038729999\n2014-04-10 14:00:00,87.8578501159\n2014-04-10 14:05:00,72.6980626249\n2014-04-10 14:10:00,75.7463093851\n2014-04-10 14:15:00,78.3409752443\n2014-04-10 14:20:00,79.1926456356\n2014-04-10 14:25:00,86.737714833\n2014-04-10 14:30:00,80.95618374189999\n2014-04-10 14:35:00,72.7182852831\n2014-04-10 14:40:00,78.5220381761\n2014-04-10 14:45:00,78.6600707333\n2014-04-10 14:50:00,87.443657518\n2014-04-10 14:55:00,81.58323727300001\n2014-04-10 15:00:00,82.1696283025\n2014-04-10 15:05:00,83.4112477444\n2014-04-10 15:10:00,84.3198195729\n2014-04-10 15:15:00,82.16002837939999\n2014-04-10 15:20:00,75.7943819851\n2014-04-10 15:25:00,85.983909176\n2014-04-10 15:30:00,83.71311315300001\n2014-04-10 15:35:00,83.86912261020001\n2014-04-10 15:40:00,87.9440635566\n2014-04-10 15:45:00,84.8396100897\n2014-04-10 15:50:00,85.2656038928\n2014-04-10 15:55:00,87.22165091549999\n2014-04-10 16:00:00,74.4180011147\n2014-04-10 16:05:00,79.9634844935\n2014-04-10 16:10:00,81.2889163024\n2014-04-10 16:15:00,77.2682633122\n2014-04-10 16:20:00,85.4302894758\n2014-04-10 16:25:00,84.1985522848\n2014-04-10 16:30:00,83.5339688066\n2014-04-10 16:35:00,87.95422216370001\n2014-04-10 16:40:00,76.1499557663\n2014-04-10 16:45:00,83.76715519359999\n2014-04-10 16:50:00,80.82231641930001\n2014-04-10 16:55:00,77.0076790649\n2014-04-10 17:00:00,74.5693612969\n2014-04-10 17:05:00,86.3341082408\n2014-04-10 17:10:00,81.5272564168\n2014-04-10 17:15:00,85.19890868590001\n2014-04-10 17:20:00,80.7254887454\n2014-04-10 17:25:00,75.5196042909\n2014-04-10 17:30:00,77.4007512877\n2014-04-10 17:35:00,78.1045914874\n2014-04-10 17:40:00,87.5669233743\n2014-04-10 17:45:00,72.0901047715\n2014-04-10 17:50:00,87.77062266450001\n2014-04-10 17:55:00,87.68735248979998\n2014-04-10 18:00:00,35.1753583057\n2014-04-10 18:05:00,31.850158229899996\n2014-04-10 18:10:00,34.9683706916\n2014-04-10 18:15:00,31.331828748099998\n2014-04-10 18:20:00,28.9682788584\n2014-04-10 18:25:00,30.2358161875\n2014-04-10 18:30:00,34.8498892764\n2014-04-10 18:35:00,28.888088490799998\n2014-04-10 18:40:00,32.2943562662\n2014-04-10 18:45:00,29.283844546399997\n2014-04-10 18:50:00,30.6329322204\n2014-04-10 18:55:00,29.363788606700002\n2014-04-10 19:00:00,24.0106869054\n2014-04-10 19:05:00,22.807995528000003\n2014-04-10 19:10:00,24.2014356388\n2014-04-10 19:15:00,23.2438210589\n2014-04-10 19:20:00,24.510209163400003\n2014-04-10 19:25:00,22.4442506621\n2014-04-10 19:30:00,23.021422143400002\n2014-04-10 19:35:00,22.741862265500004\n2014-04-10 19:40:00,22.329485499\n2014-04-10 19:45:00,23.9498966433\n2014-04-10 19:50:00,23.0474713435\n2014-04-10 19:55:00,23.7498776437\n2014-04-10 20:00:00,21.652946424499998\n2014-04-10 20:05:00,19.2145207475\n2014-04-10 20:10:00,21.0950695761\n2014-04-10 20:15:00,19.2497580556\n2014-04-10 20:20:00,20.821280429\n2014-04-10 20:25:00,21.206772213\n2014-04-10 20:30:00,22.516674583\n2014-04-10 20:35:00,18.5570997198\n2014-04-10 20:40:00,18.8057286206\n2014-04-10 20:45:00,18.7475011234\n2014-04-10 20:50:00,20.0636875878\n2014-04-10 20:55:00,21.7972256671\n2014-04-10 21:00:00,21.4788311602\n2014-04-10 21:05:00,21.0484683396\n2014-04-10 21:10:00,21.6911329765\n2014-04-10 21:15:00,19.3840386402\n2014-04-10 21:20:00,18.4407111011\n2014-04-10 21:25:00,18.3201286053\n2014-04-10 21:30:00,21.5112917741\n2014-04-10 21:35:00,21.0221695028\n2014-04-10 21:40:00,20.8942745868\n2014-04-10 21:45:00,19.4516270923\n2014-04-10 21:50:00,19.6133148861\n2014-04-10 21:55:00,21.9372498417\n2014-04-10 22:00:00,18.2727439776\n2014-04-10 22:05:00,21.1151780673\n2014-04-10 22:10:00,19.2570022773\n2014-04-10 22:15:00,18.173648434500002\n2014-04-10 22:20:00,20.9904119019\n2014-04-10 22:25:00,19.3421982349\n2014-04-10 22:30:00,20.9086431112\n2014-04-10 22:35:00,20.8506149151\n2014-04-10 22:40:00,20.1584810734\n2014-04-10 22:45:00,21.1297576193\n2014-04-10 22:50:00,20.343664473900002\n2014-04-10 22:55:00,19.1649280875\n2014-04-10 23:00:00,20.9404810028\n2014-04-10 23:05:00,20.3604677209\n2014-04-10 23:10:00,18.0543748995\n2014-04-10 23:15:00,21.6107251717\n2014-04-10 23:20:00,20.1864495256\n2014-04-10 23:25:00,21.478632165500002\n2014-04-10 23:30:00,21.535081295700003\n2014-04-10 23:35:00,19.7836643594\n2014-04-10 23:40:00,20.034485866700003\n2014-04-10 23:45:00,19.6667928481\n2014-04-10 23:50:00,19.8015482667\n2014-04-10 23:55:00,21.584732106799997\n2014-04-11 00:00:00,21.1525760559\n2014-04-11 00:05:00,18.5061027053\n2014-04-11 00:10:00,20.441231126199998\n2014-04-11 00:15:00,21.9836265615\n2014-04-11 00:20:00,20.3822028049\n2014-04-11 00:25:00,21.143486502400002\n2014-04-11 00:30:00,21.076245893499998\n2014-04-11 00:35:00,19.4012701035\n2014-04-11 00:40:00,19.487397210799998\n2014-04-11 00:45:00,20.8963056872\n2014-04-11 00:50:00,19.9999341264\n2014-04-11 00:55:00,20.282282836500002\n2014-04-11 01:00:00,20.8516231615\n2014-04-11 01:05:00,21.1103001082\n2014-04-11 01:10:00,19.086066310899998\n2014-04-11 01:15:00,18.5871750377\n2014-04-11 01:20:00,19.1671785869\n2014-04-11 01:25:00,20.0301533004\n2014-04-11 01:30:00,19.3685652692\n2014-04-11 01:35:00,20.2734510354\n2014-04-11 01:40:00,18.2138628965\n2014-04-11 01:45:00,20.0390016465\n2014-04-11 01:50:00,19.4719396278\n2014-04-11 01:55:00,20.1386670196\n2014-04-11 02:00:00,19.6901334195\n2014-04-11 02:05:00,19.1369034026\n2014-04-11 02:10:00,21.616431621799997\n2014-04-11 02:15:00,18.7390599537\n2014-04-11 02:20:00,20.7254623023\n2014-04-11 02:25:00,21.698578850300002\n2014-04-11 02:30:00,20.154679838699998\n2014-04-11 02:35:00,21.5056339543\n2014-04-11 02:40:00,18.4994059137\n2014-04-11 02:45:00,19.975155081\n2014-04-11 02:50:00,19.8281011219\n2014-04-11 02:55:00,18.0324752281\n2014-04-11 03:00:00,19.7730293654\n2014-04-11 03:05:00,19.4761190255\n2014-04-11 03:10:00,20.679194911099998\n2014-04-11 03:15:00,21.753319114299998\n2014-04-11 03:20:00,18.343164353\n2014-04-11 03:25:00,19.3099055469\n2014-04-11 03:30:00,19.7762589496\n2014-04-11 03:35:00,19.8207415121\n2014-04-11 03:40:00,21.099238883399998\n2014-04-11 03:45:00,19.7735826633\n2014-04-11 03:50:00,18.1086452058\n2014-04-11 03:55:00,20.8404163784\n2014-04-11 04:00:00,21.5393187806\n2014-04-11 04:05:00,20.0556188502\n2014-04-11 04:10:00,20.3244340868\n2014-04-11 04:15:00,18.6517457559\n2014-04-11 04:20:00,18.8825837787\n2014-04-11 04:25:00,18.9406809565\n2014-04-11 04:30:00,19.722967899500002\n2014-04-11 04:35:00,21.7125808836\n2014-04-11 04:40:00,20.0871390669\n2014-04-11 04:45:00,18.7683905808\n2014-04-11 04:50:00,19.0643509435\n2014-04-11 04:55:00,19.5360601189\n2014-04-11 05:00:00,20.4930359028\n2014-04-11 05:05:00,19.760132612\n2014-04-11 05:10:00,19.5697793767\n2014-04-11 05:15:00,20.258914401600002\n2014-04-11 05:20:00,18.9673399798\n2014-04-11 05:25:00,18.3156130903\n2014-04-11 05:30:00,18.0976572593\n2014-04-11 05:35:00,19.0050366539\n2014-04-11 05:40:00,18.366368136600002\n2014-04-11 05:45:00,19.3453625541\n2014-04-11 05:50:00,21.0917341614\n2014-04-11 05:55:00,20.8651773219\n2014-04-11 06:00:00,20.443710491199997\n2014-04-11 06:05:00,21.4100009755\n2014-04-11 06:10:00,19.1282704982\n2014-04-11 06:15:00,21.5402150121\n2014-04-11 06:20:00,19.5969566787\n2014-04-11 06:25:00,19.6035732731\n2014-04-11 06:30:00,19.6214064545\n2014-04-11 06:35:00,18.392377465\n2014-04-11 06:40:00,21.9019619933\n2014-04-11 06:45:00,18.5540271113\n2014-04-11 06:50:00,19.3635428979\n2014-04-11 06:55:00,19.2772012813\n2014-04-11 07:00:00,18.298717731300002\n2014-04-11 07:05:00,18.6090405204\n2014-04-11 07:10:00,18.1794333447\n2014-04-11 07:15:00,19.1696179742\n2014-04-11 07:20:00,21.466627696099998\n2014-04-11 07:25:00,19.3577688229\n2014-04-11 07:30:00,18.4947673283\n2014-04-11 07:35:00,20.5827754735\n2014-04-11 07:40:00,21.986403648200003\n2014-04-11 07:45:00,18.9292951581\n2014-04-11 07:50:00,19.118284021500003\n2014-04-11 07:55:00,21.8873882171\n2014-04-11 08:00:00,18.7151051502\n2014-04-11 08:05:00,20.0448562698\n2014-04-11 08:10:00,18.9586085321\n2014-04-11 08:15:00,21.729407591599998\n2014-04-11 08:20:00,21.9260840583\n2014-04-11 08:25:00,21.2587913845\n2014-04-11 08:30:00,19.2591352633\n2014-04-11 08:35:00,19.6139499011\n2014-04-11 08:40:00,18.9692227347\n2014-04-11 08:45:00,21.563031868000003\n2014-04-11 08:50:00,21.658233110799998\n2014-04-11 08:55:00,19.675482649\n2014-04-11 09:00:00,127.882020134\n2014-04-11 09:05:00,115.705718858\n2014-04-11 09:10:00,122.386410329\n2014-04-11 09:15:00,127.26117784600001\n2014-04-11 09:20:00,121.15799733899999\n2014-04-11 09:25:00,120.46846823700001\n2014-04-11 09:30:00,111.62477500799999\n2014-04-11 09:35:00,131.54647790200002\n2014-04-11 09:40:00,133.655572778\n2014-04-11 09:45:00,135.642695533\n2014-04-11 09:50:00,129.43793035\n2014-04-11 09:55:00,125.21004934700001\n2014-04-11 10:00:00,138.118479694\n2014-04-11 10:05:00,159.259712824\n2014-04-11 10:10:00,147.399242667\n2014-04-11 10:15:00,150.046221935\n2014-04-11 10:20:00,150.08248245\n2014-04-11 10:25:00,154.798492005\n2014-04-11 10:30:00,130.600116725\n2014-04-11 10:35:00,136.698351395\n2014-04-11 10:40:00,149.593864645\n2014-04-11 10:45:00,156.24342053799998\n2014-04-11 10:50:00,150.16741112399998\n2014-04-11 10:55:00,142.294707802\n2014-04-11 11:00:00,144.83546133299998\n2014-04-11 11:05:00,156.04894706299999\n2014-04-11 11:10:00,156.146953473\n2014-04-11 11:15:00,152.149471713\n2014-04-11 11:20:00,142.74738558200002\n2014-04-11 11:25:00,161.62621235\n2014-04-11 11:30:00,150.505607236\n2014-04-11 11:35:00,157.614348277\n2014-04-11 11:40:00,140.448671746\n2014-04-11 11:45:00,144.313663174\n2014-04-11 11:50:00,160.119472952\n2014-04-11 11:55:00,135.556788636\n2014-04-11 12:00:00,150.160947021\n2014-04-11 12:05:00,149.243925447\n2014-04-11 12:10:00,157.318454491\n2014-04-11 12:15:00,143.257886337\n2014-04-11 12:20:00,141.37569147600001\n2014-04-11 12:25:00,162.558258037\n2014-04-11 12:30:00,151.940306437\n2014-04-11 12:35:00,137.949131962\n2014-04-11 12:40:00,140.595854562\n2014-04-11 12:45:00,164.736030621\n2014-04-11 12:50:00,140.67293255299998\n2014-04-11 12:55:00,153.101669559\n2014-04-11 13:00:00,147.562906904\n2014-04-11 13:05:00,161.523164661\n2014-04-11 13:10:00,157.611334766\n2014-04-11 13:15:00,152.86613525200002\n2014-04-11 13:20:00,135.284640106\n2014-04-11 13:25:00,161.349096329\n2014-04-11 13:30:00,148.298884492\n2014-04-11 13:35:00,162.902138864\n2014-04-11 13:40:00,149.824607501\n2014-04-11 13:45:00,155.783518728\n2014-04-11 13:50:00,137.04076296899999\n2014-04-11 13:55:00,157.310909944\n2014-04-11 14:00:00,145.131830514\n2014-04-11 14:05:00,145.532697769\n2014-04-11 14:10:00,138.551989898\n2014-04-11 14:15:00,139.397982089\n2014-04-11 14:20:00,140.56497458299998\n2014-04-11 14:25:00,144.838150922\n2014-04-11 14:30:00,161.750125145\n2014-04-11 14:35:00,146.039706362\n2014-04-11 14:40:00,156.722187857\n2014-04-11 14:45:00,137.474799425\n2014-04-11 14:50:00,152.72449239\n2014-04-11 14:55:00,149.448447071\n2014-04-11 15:00:00,164.336915344\n2014-04-11 15:05:00,160.384453878\n2014-04-11 15:10:00,148.643244206\n2014-04-11 15:15:00,158.252527354\n2014-04-11 15:20:00,140.789600396\n2014-04-11 15:25:00,151.86840507600002\n2014-04-11 15:30:00,137.23704923399998\n2014-04-11 15:35:00,145.441057524\n2014-04-11 15:40:00,141.774292682\n2014-04-11 15:45:00,156.56555760700002\n2014-04-11 15:50:00,149.701060034\n2014-04-11 15:55:00,157.530366809\n2014-04-11 16:00:00,150.458529311\n2014-04-11 16:05:00,137.594227988\n2014-04-11 16:10:00,157.060681026\n2014-04-11 16:15:00,159.99652294\n2014-04-11 16:20:00,162.10557711799999\n2014-04-11 16:25:00,152.159420767\n2014-04-11 16:30:00,157.607211091\n2014-04-11 16:35:00,157.56098053\n2014-04-11 16:40:00,139.672182907\n2014-04-11 16:45:00,139.926310173\n2014-04-11 16:50:00,137.126260936\n2014-04-11 16:55:00,144.597088241\n2014-04-11 17:00:00,149.205191425\n2014-04-11 17:05:00,164.936862395\n2014-04-11 17:10:00,147.929734621\n2014-04-11 17:15:00,156.787208083\n2014-04-11 17:20:00,155.801841654\n2014-04-11 17:25:00,141.134395882\n2014-04-11 17:30:00,136.755153861\n2014-04-11 17:35:00,151.380135374\n2014-04-11 17:40:00,156.009098543\n2014-04-11 17:45:00,164.947480513\n2014-04-11 17:50:00,145.758266891\n2014-04-11 17:55:00,161.890865026\n2014-04-11 18:00:00,44.9137655963\n2014-04-11 18:05:00,47.7425739013\n2014-04-11 18:10:00,46.9039133872\n2014-04-11 18:15:00,41.8873927765\n2014-04-11 18:20:00,42.121161338600004\n2014-04-11 18:25:00,41.5910175894\n2014-04-11 18:30:00,44.81166061020001\n2014-04-11 18:35:00,48.26135568220001\n2014-04-11 18:40:00,42.98933718399999\n2014-04-11 18:45:00,46.973833715299996\n2014-04-11 18:50:00,44.057202826499996\n2014-04-11 18:55:00,48.7323180379\n2014-04-11 19:00:00,26.703913769699998\n2014-04-11 19:05:00,26.588086346399997\n2014-04-11 19:10:00,25.325158233899998\n2014-04-11 19:15:00,24.1142136711\n2014-04-11 19:20:00,26.759595154\n2014-04-11 19:25:00,23.6179443369\n2014-04-11 19:30:00,24.1403858438\n2014-04-11 19:35:00,23.607093944899997\n2014-04-11 19:40:00,26.0780164532\n2014-04-11 19:45:00,26.1386268201\n2014-04-11 19:50:00,25.96864762\n2014-04-11 19:55:00,24.774628775500002\n2014-04-11 20:00:00,19.3575191084\n2014-04-11 20:05:00,22.7702010354\n2014-04-11 20:10:00,21.072531363299998\n2014-04-11 20:15:00,20.6485384736\n2014-04-11 20:20:00,21.4137746088\n2014-04-11 20:25:00,19.7472616542\n2014-04-11 20:30:00,19.4937647691\n2014-04-11 20:35:00,20.6424496095\n2014-04-11 20:40:00,19.8921441773\n2014-04-11 20:45:00,19.9639730542\n2014-04-11 20:50:00,22.6916877663\n2014-04-11 20:55:00,21.169434081800002\n2014-04-11 21:00:00,20.141188464200003\n2014-04-11 21:05:00,20.9738006155\n2014-04-11 21:10:00,22.032976740100004\n2014-04-11 21:15:00,18.6406616199\n2014-04-11 21:20:00,21.556013192800002\n2014-04-11 21:25:00,20.547571809100003\n2014-04-11 21:30:00,18.777941795\n2014-04-11 21:35:00,19.3881585842\n2014-04-11 21:40:00,20.136711794700002\n2014-04-11 21:45:00,20.980661437000002\n2014-04-11 21:50:00,19.1677204187\n2014-04-11 21:55:00,20.3489661134\n2014-04-11 22:00:00,20.7818229555\n2014-04-11 22:05:00,19.8361365054\n2014-04-11 22:10:00,21.496724197600003\n2014-04-11 22:15:00,21.522510288200003\n2014-04-11 22:20:00,19.9241210003\n2014-04-11 22:25:00,21.9372375602\n2014-04-11 22:30:00,18.3404092181\n2014-04-11 22:35:00,18.0509174691\n2014-04-11 22:40:00,19.5632801944\n2014-04-11 22:45:00,20.4468293513\n2014-04-11 22:50:00,20.5594755533\n2014-04-11 22:55:00,19.9471869525\n2014-04-11 23:00:00,18.5072290549\n2014-04-11 23:05:00,18.689761791\n2014-04-11 23:10:00,21.4174979051\n2014-04-11 23:15:00,21.4805767265\n2014-04-11 23:20:00,20.7042035142\n2014-04-11 23:25:00,20.6654651434\n2014-04-11 23:30:00,20.399211050799998\n2014-04-11 23:35:00,18.8195292075\n2014-04-11 23:40:00,19.721203406\n2014-04-11 23:45:00,20.7922245701\n2014-04-11 23:50:00,20.1573910715\n2014-04-11 23:55:00,18.08184025\n2014-04-12 00:00:00,21.8142272269\n2014-04-12 00:05:00,21.3792642103\n2014-04-12 00:10:00,19.0421800564\n2014-04-12 00:15:00,20.465835740699998\n2014-04-12 00:20:00,21.692957534899996\n2014-04-12 00:25:00,18.384044048499998\n2014-04-12 00:30:00,20.012117923199998\n2014-04-12 00:35:00,19.8249721034\n2014-04-12 00:40:00,19.640820021099998\n2014-04-12 00:45:00,21.3423544356\n2014-04-12 00:50:00,19.5225845868\n2014-04-12 00:55:00,18.254653333\n2014-04-12 01:00:00,18.2633509687\n2014-04-12 01:05:00,18.1709784261\n2014-04-12 01:10:00,19.6365816875\n2014-04-12 01:15:00,20.8736251108\n2014-04-12 01:20:00,18.814889847699998\n2014-04-12 01:25:00,20.585874081700002\n2014-04-12 01:30:00,20.7483538884\n2014-04-12 01:35:00,19.0208084961\n2014-04-12 01:40:00,20.4022306242\n2014-04-12 01:45:00,20.7394733601\n2014-04-12 01:50:00,19.8664544912\n2014-04-12 01:55:00,19.3468663891\n2014-04-12 02:00:00,20.4766062063\n2014-04-12 02:05:00,21.911388349299997\n2014-04-12 02:10:00,19.7073656375\n2014-04-12 02:15:00,19.5669403851\n2014-04-12 02:20:00,19.8570676097\n2014-04-12 02:25:00,18.304873573800002\n2014-04-12 02:30:00,20.2126531187\n2014-04-12 02:35:00,19.314789548900002\n2014-04-12 02:40:00,18.4856884893\n2014-04-12 02:45:00,19.8650269645\n2014-04-12 02:50:00,18.013535946300003\n2014-04-12 02:55:00,19.6071409807\n2014-04-12 03:00:00,18.422941071700002\n2014-04-12 03:05:00,18.0971708136\n2014-04-12 03:10:00,21.297900185\n2014-04-12 03:15:00,21.6649952131\n2014-04-12 03:20:00,18.830698593399998\n2014-04-12 03:25:00,20.1571930553\n2014-04-12 03:30:00,19.1118326285\n2014-04-12 03:35:00,19.974309754700002\n2014-04-12 03:40:00,19.7465252836\n2014-04-12 03:45:00,19.0762042203\n2014-04-12 03:50:00,20.8015743185\n2014-04-12 03:55:00,18.5059638373\n2014-04-12 04:00:00,18.2122911287\n2014-04-12 04:05:00,21.0707017321\n2014-04-12 04:10:00,20.6637201249\n2014-04-12 04:15:00,19.994104496600002\n2014-04-12 04:20:00,19.8711590819\n2014-04-12 04:25:00,19.989645518\n2014-04-12 04:30:00,19.7480963044\n2014-04-12 04:35:00,19.5715691833\n2014-04-12 04:40:00,19.9987624115\n2014-04-12 04:45:00,20.114060684600002\n2014-04-12 04:50:00,20.767609256300002\n2014-04-12 04:55:00,20.8448286429\n2014-04-12 05:00:00,19.5105163206\n2014-04-12 05:05:00,19.654162091\n2014-04-12 05:10:00,19.4947886789\n2014-04-12 05:15:00,20.1461430945\n2014-04-12 05:20:00,19.8134141517\n2014-04-12 05:25:00,21.5583858525\n2014-04-12 05:30:00,20.7854450677\n2014-04-12 05:35:00,21.594625535\n2014-04-12 05:40:00,20.836547966199998\n2014-04-12 05:45:00,21.883968594099997\n2014-04-12 05:50:00,20.542947113\n2014-04-12 05:55:00,21.8542005527\n2014-04-12 06:00:00,18.6326795616\n2014-04-12 06:05:00,18.2099107233\n2014-04-12 06:10:00,20.3165007408\n2014-04-12 06:15:00,21.9339728232\n2014-04-12 06:20:00,19.6704209892\n2014-04-12 06:25:00,18.8481734488\n2014-04-12 06:30:00,20.0861657968\n2014-04-12 06:35:00,20.5951944983\n2014-04-12 06:40:00,19.2607147821\n2014-04-12 06:45:00,20.859077434\n2014-04-12 06:50:00,21.900458028200003\n2014-04-12 06:55:00,21.5878524868\n2014-04-12 07:00:00,19.166341494\n2014-04-12 07:05:00,19.3068947326\n2014-04-12 07:10:00,19.4861648978\n2014-04-12 07:15:00,19.5782111136\n2014-04-12 07:20:00,18.4012779968\n2014-04-12 07:25:00,21.0478513556\n2014-04-12 07:30:00,19.4613570544\n2014-04-12 07:35:00,21.519279906799998\n2014-04-12 07:40:00,21.7077624925\n2014-04-12 07:45:00,18.0977252372\n2014-04-12 07:50:00,21.9540122797\n2014-04-12 07:55:00,20.840090926\n2014-04-12 08:00:00,20.081568904\n2014-04-12 08:05:00,19.558110433499998\n2014-04-12 08:10:00,20.0740725304\n2014-04-12 08:15:00,19.2984988959\n2014-04-12 08:20:00,20.4907512548\n2014-04-12 08:25:00,18.3719211058\n2014-04-12 08:30:00,20.4844904116\n2014-04-12 08:35:00,19.1013794006\n2014-04-12 08:40:00,18.070539316199998\n2014-04-12 08:45:00,20.2108230647\n2014-04-12 08:50:00,20.3137910234\n2014-04-12 08:55:00,19.7062760188\n2014-04-12 09:00:00,62.18309276270001\n2014-04-12 09:05:00,73.3494641581\n2014-04-12 09:10:00,69.5154589783\n2014-04-12 09:15:00,62.7737008741\n2014-04-12 09:20:00,68.1486558417\n2014-04-12 09:25:00,67.9626586969\n2014-04-12 09:30:00,62.021465415600005\n2014-04-12 09:35:00,69.45329196899999\n2014-04-12 09:40:00,72.1932390253\n2014-04-12 09:45:00,71.3865095378\n2014-04-12 09:50:00,63.960384032600004\n2014-04-12 09:55:00,72.9271784019\n2014-04-12 10:00:00,75.156254411\n2014-04-12 10:05:00,84.5298100311\n2014-04-12 10:10:00,70.9535284048\n2014-04-12 10:15:00,77.3859588458\n2014-04-12 10:20:00,79.1073703338\n2014-04-12 10:25:00,73.6835295283\n2014-04-12 10:30:00,81.8118205289\n2014-04-12 10:35:00,79.56942095069999\n2014-04-12 10:40:00,70.1210584667\n2014-04-12 10:45:00,79.28188052760001\n2014-04-12 10:50:00,77.4677421982\n2014-04-12 10:55:00,72.8823732104\n2014-04-12 11:00:00,87.4043798032\n2014-04-12 11:05:00,85.83646754649999\n2014-04-12 11:10:00,76.2200423817\n2014-04-12 11:15:00,80.1731919244\n2014-04-12 11:20:00,76.6016500331\n2014-04-12 11:25:00,83.901484434\n2014-04-12 11:30:00,86.36399111360001\n2014-04-12 11:35:00,77.2748101644\n2014-04-12 11:40:00,84.3800118984\n2014-04-12 11:45:00,79.4946735593\n2014-04-12 11:50:00,77.8751854391\n2014-04-12 11:55:00,86.4926611358\n2014-04-12 12:00:00,80.0702752495\n2014-04-12 12:05:00,79.3831937225\n2014-04-12 12:10:00,82.65963969090001\n2014-04-12 12:15:00,76.0883315196\n2014-04-12 12:20:00,77.10404990949999\n2014-04-12 12:25:00,86.8084380998\n2014-04-12 12:30:00,82.757049754\n2014-04-12 12:35:00,85.1239229311\n2014-04-12 12:40:00,76.24618284510001\n2014-04-12 12:45:00,80.60380226720001\n2014-04-12 12:50:00,87.43728946350002\n2014-04-12 12:55:00,77.0067432696\n2014-04-12 13:00:00,74.5497273914\n2014-04-12 13:05:00,80.1549343293\n2014-04-12 13:10:00,78.18636818659999\n2014-04-12 13:15:00,74.53534294800001\n2014-04-12 13:20:00,86.1961300859\n2014-04-12 13:25:00,87.830498189\n2014-04-12 13:30:00,81.0778515355\n2014-04-12 13:35:00,84.3745735352\n2014-04-12 13:40:00,85.7240352054\n2014-04-12 13:45:00,83.1957403254\n2014-04-12 13:50:00,72.6890472266\n2014-04-12 13:55:00,74.504262392\n2014-04-12 14:00:00,73.1323165387\n2014-04-12 14:05:00,72.15461011869998\n2014-04-12 14:10:00,76.8922515349\n2014-04-12 14:15:00,78.2739380383\n2014-04-12 14:20:00,75.8528346065\n2014-04-12 14:25:00,73.030168753\n2014-04-12 14:30:00,80.4739465185\n2014-04-12 14:35:00,76.3694432101\n2014-04-12 14:40:00,84.7325271213\n2014-04-12 14:45:00,72.1253797616\n2014-04-12 14:50:00,85.4763297598\n2014-04-12 14:55:00,87.2718696123\n2014-04-12 15:00:00,83.4573598121\n2014-04-12 15:05:00,83.7375011565\n2014-04-12 15:10:00,86.93616239049999\n2014-04-12 15:15:00,75.34441725149999\n2014-04-12 15:20:00,87.9122051261\n2014-04-12 15:25:00,84.37488924729999\n2014-04-12 15:30:00,83.62432853199999\n2014-04-12 15:35:00,77.7767026004\n2014-04-12 15:40:00,80.7316647351\n2014-04-12 15:45:00,82.4618929706\n2014-04-12 15:50:00,81.92469929640001\n2014-04-12 15:55:00,83.27895473\n2014-04-12 16:00:00,73.3179670545\n2014-04-12 16:05:00,77.6902257598\n2014-04-12 16:10:00,78.943848693\n2014-04-12 16:15:00,76.16992251949999\n2014-04-12 16:20:00,74.7618927812\n2014-04-12 16:25:00,74.2226971708\n2014-04-12 16:30:00,77.8619847808\n2014-04-12 16:35:00,79.8949138105\n2014-04-12 16:40:00,73.0074828677\n2014-04-12 16:45:00,87.1431621983\n2014-04-12 16:50:00,84.2437314175\n2014-04-12 16:55:00,83.6934676792\n2014-04-12 17:00:00,74.7657396898\n2014-04-12 17:05:00,81.6607809304\n2014-04-12 17:10:00,80.4755682463\n2014-04-12 17:15:00,87.7194678483\n2014-04-12 17:20:00,83.9627160796\n2014-04-12 17:25:00,81.212158954\n2014-04-12 17:30:00,85.6129697881\n2014-04-12 17:35:00,74.4814797329\n2014-04-12 17:40:00,72.24343673359999\n2014-04-12 17:45:00,83.0437014458\n2014-04-12 17:50:00,73.5729551118\n2014-04-12 17:55:00,73.8469098825\n2014-04-12 18:00:00,33.5659502045\n2014-04-12 18:05:00,30.5314171404\n2014-04-12 18:10:00,32.8232334776\n2014-04-12 18:15:00,34.6713976701\n2014-04-12 18:20:00,30.825431084\n2014-04-12 18:25:00,30.1897168137\n2014-04-12 18:30:00,29.4819967954\n2014-04-12 18:35:00,29.634953423200002\n2014-04-12 18:40:00,29.1982196444\n2014-04-12 18:45:00,29.360905587199998\n2014-04-12 18:50:00,31.5648233079\n2014-04-12 18:55:00,30.8535303643\n2014-04-12 19:00:00,23.32539116860001\n2014-04-12 19:05:00,24.0586813092\n2014-04-12 19:10:00,23.6757826513\n2014-04-12 19:15:00,22.5372536735\n2014-04-12 19:20:00,20.6189395496\n2014-04-12 19:25:00,23.3397561517\n2014-04-12 19:30:00,21.7854714917\n2014-04-12 19:35:00,20.5437126378\n2014-04-12 19:40:00,23.9342481913\n2014-04-12 19:45:00,21.6752088079\n2014-04-12 19:50:00,21.1377536101\n2014-04-12 19:55:00,24.0641039294\n2014-04-12 20:00:00,22.127140059600002\n2014-04-12 20:05:00,19.820424311300002\n2014-04-12 20:10:00,19.8852663748\n2014-04-12 20:15:00,20.8061581993\n2014-04-12 20:20:00,21.4361761014\n2014-04-12 20:25:00,18.6906589067\n2014-04-12 20:30:00,20.862335369500002\n2014-04-12 20:35:00,22.334750705\n2014-04-12 20:40:00,19.5055363688\n2014-04-12 20:45:00,22.154556003099998\n2014-04-12 20:50:00,22.323889255900003\n2014-04-12 20:55:00,19.534453079000002\n2014-04-12 21:00:00,21.1176880877\n2014-04-12 21:05:00,19.046084466900002\n2014-04-12 21:10:00,21.0510067297\n2014-04-12 21:15:00,21.2913902965\n2014-04-12 21:20:00,19.0799691177\n2014-04-12 21:25:00,20.9636228183\n2014-04-12 21:30:00,21.3504105104\n2014-04-12 21:35:00,19.527600155\n2014-04-12 21:40:00,18.7604309514\n2014-04-12 21:45:00,18.4560239438\n2014-04-12 21:50:00,20.398974093299998\n2014-04-12 21:55:00,22.0175719073\n2014-04-12 22:00:00,21.3122413989\n2014-04-12 22:05:00,19.7623121702\n2014-04-12 22:10:00,20.165824225799998\n2014-04-12 22:15:00,19.1364649193\n2014-04-12 22:20:00,18.6701696332\n2014-04-12 22:25:00,19.9474558148\n2014-04-12 22:30:00,19.873066100899997\n2014-04-12 22:35:00,20.1070040124\n2014-04-12 22:40:00,21.8321571011\n2014-04-12 22:45:00,20.4351801485\n2014-04-12 22:50:00,20.4426935003\n2014-04-12 22:55:00,18.5298706574\n2014-04-12 23:00:00,21.990176765999998\n2014-04-12 23:05:00,21.0954293198\n2014-04-12 23:10:00,21.5129430664\n2014-04-12 23:15:00,19.6609758281\n2014-04-12 23:20:00,20.0123540156\n2014-04-12 23:25:00,20.092192195\n2014-04-12 23:30:00,18.7799832199\n2014-04-12 23:35:00,20.761942150899998\n2014-04-12 23:40:00,21.616056378499998\n2014-04-12 23:45:00,18.6584049968\n2014-04-12 23:50:00,18.3487953846\n2014-04-12 23:55:00,20.9568985722\n2014-04-13 00:00:00,19.0928073267\n2014-04-13 00:05:00,20.4954501665\n2014-04-13 00:10:00,20.783033352\n2014-04-13 00:15:00,19.287643054300002\n2014-04-13 00:20:00,100.000000000\n2014-04-13 00:25:00,20.1999559285\n2014-04-13 00:30:00,21.4759976318\n2014-04-13 00:35:00,21.053174210199998\n2014-04-13 00:40:00,21.4743025281\n2014-04-13 00:45:00,18.0806455285\n2014-04-13 00:50:00,18.974025043\n2014-04-13 00:55:00,18.360031761800002\n2014-04-13 01:00:00,19.7683320688\n2014-04-13 01:05:00,21.5598404865\n2014-04-13 01:10:00,19.870161049100002\n2014-04-13 01:15:00,21.3988521783\n2014-04-13 01:20:00,19.3087129521\n2014-04-13 01:25:00,19.3582802912\n2014-04-13 01:30:00,21.5822469213\n2014-04-13 01:35:00,19.703268586\n2014-04-13 01:40:00,21.159061951199998\n2014-04-13 01:45:00,18.9465741915\n2014-04-13 01:50:00,21.7952033187\n2014-04-13 01:55:00,20.298312986099997\n2014-04-13 02:00:00,21.037294274300002\n2014-04-13 02:05:00,18.358062799200003\n2014-04-13 02:10:00,19.9706569033\n2014-04-13 02:15:00,21.604153990900002\n2014-04-13 02:20:00,21.508154516199998\n2014-04-13 02:25:00,18.1872558289\n2014-04-13 02:30:00,19.2147938765\n2014-04-13 02:35:00,19.7732800259\n2014-04-13 02:40:00,18.6890592574\n2014-04-13 02:45:00,20.919993244\n2014-04-13 02:50:00,18.7380479824\n2014-04-13 02:55:00,19.3865587775\n2014-04-13 03:00:00,20.6531225474\n2014-04-13 03:05:00,19.9283573781\n2014-04-13 03:10:00,20.9542841545\n2014-04-13 03:15:00,21.844831604899998\n2014-04-13 03:20:00,18.4661867509\n2014-04-13 03:25:00,20.8382708656\n2014-04-13 03:30:00,18.9213766225\n2014-04-13 03:35:00,19.6579069096\n2014-04-13 03:40:00,18.1314509032\n2014-04-13 03:45:00,18.5436295292\n2014-04-13 03:50:00,19.2791091562\n2014-04-13 03:55:00,19.367943221199997\n2014-04-13 04:00:00,21.5983408658\n2014-04-13 04:05:00,20.9672516371\n2014-04-13 04:10:00,21.8887318727\n2014-04-13 04:15:00,20.3962860413\n2014-04-13 04:20:00,18.9668549284\n2014-04-13 04:25:00,19.3106201197\n2014-04-13 04:30:00,19.279343693199998\n2014-04-13 04:35:00,19.305977310699998\n2014-04-13 04:40:00,20.691856692400002\n2014-04-13 04:45:00,20.1232317124\n2014-04-13 04:50:00,19.5416967123\n2014-04-13 04:55:00,18.5963590749\n2014-04-13 05:00:00,18.0885566518\n2014-04-13 05:05:00,18.8753387104\n2014-04-13 05:10:00,18.429885615899998\n2014-04-13 05:15:00,21.1417801234\n2014-04-13 05:20:00,18.4499918313\n2014-04-13 05:25:00,20.8969129492\n2014-04-13 05:30:00,19.5426347591\n2014-04-13 05:35:00,18.293513559\n2014-04-13 05:40:00,21.2509201977\n2014-04-13 05:45:00,20.318522280899998\n2014-04-13 05:50:00,18.9430460515\n2014-04-13 05:55:00,21.5787246973\n2014-04-13 06:00:00,18.1810332555\n2014-04-13 06:05:00,18.8072784328\n2014-04-13 06:10:00,21.008187711199998\n2014-04-13 06:15:00,20.8375117212\n2014-04-13 06:20:00,19.1570867749\n2014-04-13 06:25:00,18.248099501400002\n2014-04-13 06:30:00,21.4323122889\n2014-04-13 06:35:00,19.2547905523\n2014-04-13 06:40:00,18.7828536597\n2014-04-13 06:45:00,20.0642472894\n2014-04-13 06:50:00,21.6409087971\n2014-04-13 06:55:00,18.1741863114\n2014-04-13 07:00:00,21.0632163521\n2014-04-13 07:05:00,20.2898929118\n2014-04-13 07:10:00,19.701796466199998\n2014-04-13 07:15:00,20.976321776400003\n2014-04-13 07:20:00,21.863297697800004\n2014-04-13 07:25:00,18.9168248447\n2014-04-13 07:30:00,18.5745894603\n2014-04-13 07:35:00,21.6515269809\n2014-04-13 07:40:00,20.6758123098\n2014-04-13 07:45:00,19.751944086199998\n2014-04-13 07:50:00,20.2930382811\n2014-04-13 07:55:00,20.982455620699998\n2014-04-13 08:00:00,21.0921275948\n2014-04-13 08:05:00,21.6795767233\n2014-04-13 08:10:00,19.7073711556\n2014-04-13 08:15:00,19.1736436401\n2014-04-13 08:20:00,20.5586570672\n2014-04-13 08:25:00,19.6629115971\n2014-04-13 08:30:00,20.3783938158\n2014-04-13 08:35:00,19.6799431938\n2014-04-13 08:40:00,18.611983146700002\n2014-04-13 08:45:00,19.8777070066\n2014-04-13 08:50:00,20.7636712878\n2014-04-13 08:55:00,21.1971352307\n2014-04-13 09:00:00,67.9092373644\n2014-04-13 09:05:00,63.4472353069\n2014-04-13 09:10:00,66.8397528512\n2014-04-13 09:15:00,71.8935974322\n2014-04-13 09:20:00,66.8148860804\n2014-04-13 09:25:00,70.672818793\n2014-04-13 09:30:00,68.0981060708\n2014-04-13 09:35:00,64.48063450149999\n2014-04-13 09:40:00,72.0276469091\n2014-04-13 09:45:00,62.3453029754\n2014-04-13 09:50:00,68.3385078455\n2014-04-13 09:55:00,64.0409180657\n2014-04-13 10:00:00,70.880858555\n2014-04-13 10:05:00,77.6455347035\n2014-04-13 10:10:00,77.5932046601\n2014-04-13 10:15:00,80.811101994\n2014-04-13 10:20:00,81.3985307562\n2014-04-13 10:25:00,81.1353239045\n2014-04-13 10:30:00,76.1963515349\n2014-04-13 10:35:00,79.6438254978\n2014-04-13 10:40:00,78.7941901658\n2014-04-13 10:45:00,76.3826384549\n2014-04-13 10:50:00,79.1087410138\n2014-04-13 10:55:00,84.5412870465\n2014-04-13 11:00:00,74.63578209949999\n2014-04-13 11:05:00,85.9733994114\n2014-04-13 11:10:00,72.4181564944\n2014-04-13 11:15:00,76.472622042\n2014-04-13 11:20:00,76.1506620339\n2014-04-13 11:25:00,81.5297106757\n2014-04-13 11:30:00,73.6550016331\n2014-04-13 11:35:00,85.6008564187\n2014-04-13 11:40:00,84.7452816002\n2014-04-13 11:45:00,81.93845479630002\n2014-04-13 11:50:00,78.8586135808\n2014-04-13 11:55:00,86.4057328942\n2014-04-13 12:00:00,85.1895945417\n2014-04-13 12:05:00,79.8930555185\n2014-04-13 12:10:00,83.1300977029\n2014-04-13 12:15:00,80.97359417979999\n2014-04-13 12:20:00,81.3093873232\n2014-04-13 12:25:00,77.2028623705\n2014-04-13 12:30:00,79.29808164960002\n2014-04-13 12:35:00,73.1620429612\n2014-04-13 12:40:00,77.6243179718\n2014-04-13 12:45:00,83.0334963383\n2014-04-13 12:50:00,87.14675474030001\n2014-04-13 12:55:00,87.3041349732\n2014-04-13 13:00:00,80.8721519302\n2014-04-13 13:05:00,81.6863465995\n2014-04-13 13:10:00,74.9535457987\n2014-04-13 13:15:00,83.1049797464\n2014-04-13 13:20:00,73.112989353\n2014-04-13 13:25:00,76.53659777979999\n2014-04-13 13:30:00,82.6739670413\n2014-04-13 13:35:00,76.9464905138\n2014-04-13 13:40:00,72.7800785738\n2014-04-13 13:45:00,85.2894521672\n2014-04-13 13:50:00,76.9468084469\n2014-04-13 13:55:00,72.99216127369998\n2014-04-13 14:00:00,73.1930971947\n2014-04-13 14:05:00,76.0244914299\n2014-04-13 14:10:00,74.84466243930001\n2014-04-13 14:15:00,84.38475122199999\n2014-04-13 14:20:00,77.1432416933\n2014-04-13 14:25:00,84.8710585543\n2014-04-13 14:30:00,74.7779464514\n2014-04-13 14:35:00,79.8822323415\n2014-04-13 14:40:00,83.0046097243\n2014-04-13 14:45:00,82.4278969329\n2014-04-13 14:50:00,81.6141528915\n2014-04-13 14:55:00,86.7929793679\n2014-04-13 15:00:00,75.65567606180001\n2014-04-13 15:05:00,79.8987402361\n2014-04-13 15:10:00,86.1430538199\n2014-04-13 15:15:00,73.245597085\n2014-04-13 15:20:00,72.89351250760001\n2014-04-13 15:25:00,75.7321095657\n2014-04-13 15:30:00,82.1275510805\n2014-04-13 15:35:00,76.15734290569999\n2014-04-13 15:40:00,75.0431177201\n2014-04-13 15:45:00,79.3400753737\n2014-04-13 15:50:00,81.8167836516\n2014-04-13 15:55:00,75.9761939338\n2014-04-13 16:00:00,76.8109115103\n2014-04-13 16:05:00,81.8167917884\n2014-04-13 16:10:00,87.1316474587\n2014-04-13 16:15:00,82.7957086709\n2014-04-13 16:20:00,84.5263040065\n2014-04-13 16:25:00,77.8688120077\n2014-04-13 16:30:00,76.35592314649999\n2014-04-13 16:35:00,79.2681316961\n2014-04-13 16:40:00,84.91396222430001\n2014-04-13 16:45:00,79.3006420111\n2014-04-13 16:50:00,85.5474422892\n2014-04-13 16:55:00,87.820183076\n2014-04-13 17:00:00,73.1523985612\n2014-04-13 17:05:00,72.7265345703\n2014-04-13 17:10:00,74.3934066795\n2014-04-13 17:15:00,78.1498848022\n2014-04-13 17:20:00,74.0966468932\n2014-04-13 17:25:00,85.93059864450001\n2014-04-13 17:30:00,72.3703122262\n2014-04-13 17:35:00,77.0526538731\n2014-04-13 17:40:00,74.9550852891\n2014-04-13 17:45:00,86.9045959111\n2014-04-13 17:50:00,82.7116643169\n2014-04-13 17:55:00,86.59245085170002\n2014-04-13 18:00:00,35.022897021599995\n2014-04-13 18:05:00,31.981422619099998\n2014-04-13 18:10:00,30.299636474\n2014-04-13 18:15:00,30.039858464\n2014-04-13 18:20:00,30.2266749113\n2014-04-13 18:25:00,33.3349907685\n2014-04-13 18:30:00,29.0588470807\n2014-04-13 18:35:00,29.128705274699996\n2014-04-13 18:40:00,32.6921085544\n2014-04-13 18:45:00,32.9091594206\n2014-04-13 18:50:00,33.0576763686\n2014-04-13 18:55:00,31.180029242800003\n2014-04-13 19:00:00,23.7706317975\n2014-04-13 19:05:00,22.550636916\n2014-04-13 19:10:00,20.6324848906\n2014-04-13 19:15:00,23.7310035938\n2014-04-13 19:20:00,24.4297423423\n2014-04-13 19:25:00,20.4289615616\n2014-04-13 19:30:00,21.913252795300004\n2014-04-13 19:35:00,22.3440706551\n2014-04-13 19:40:00,20.8161878632\n2014-04-13 19:45:00,24.0473347669\n2014-04-13 19:50:00,21.4329892334\n2014-04-13 19:55:00,23.6678769606\n2014-04-13 20:00:00,21.1803931442\n2014-04-13 20:05:00,20.881595438199998\n2014-04-13 20:10:00,19.2190168776\n2014-04-13 20:15:00,19.336001388099998\n2014-04-13 20:20:00,18.625938842300002\n2014-04-13 20:25:00,19.4179578794\n2014-04-13 20:30:00,19.8469367862\n2014-04-13 20:35:00,21.8445629025\n2014-04-13 20:40:00,19.932744123699997\n2014-04-13 20:45:00,21.522930563899997\n2014-04-13 20:50:00,20.231955341400003\n2014-04-13 20:55:00,21.6468203462\n2014-04-13 21:00:00,22.010230762600003\n2014-04-13 21:05:00,19.0503711436\n2014-04-13 21:10:00,21.552323354099997\n2014-04-13 21:15:00,20.5856353173\n2014-04-13 21:20:00,21.3712690439\n2014-04-13 21:25:00,20.7052540078\n2014-04-13 21:30:00,19.7903378112\n2014-04-13 21:35:00,19.0030787501\n2014-04-13 21:40:00,18.3678855327\n2014-04-13 21:45:00,20.2387553609\n2014-04-13 21:50:00,22.0667185852\n2014-04-13 21:55:00,21.052737571199998\n2014-04-13 22:00:00,19.327919163\n2014-04-13 22:05:00,21.329275656300002\n2014-04-13 22:10:00,21.0961688889\n2014-04-13 22:15:00,19.1449046455\n2014-04-13 22:20:00,18.0745648911\n2014-04-13 22:25:00,18.4903842896\n2014-04-13 22:30:00,21.5298736064\n2014-04-13 22:35:00,21.3667445328\n2014-04-13 22:40:00,19.1992495966\n2014-04-13 22:45:00,19.1591568462\n2014-04-13 22:50:00,21.1917845396\n2014-04-13 22:55:00,21.7718307808\n2014-04-13 23:00:00,21.1206034025\n2014-04-13 23:05:00,20.426235790499998\n2014-04-13 23:10:00,18.9743277711\n2014-04-13 23:15:00,20.106851428800002\n2014-04-13 23:20:00,18.937682769600002\n2014-04-13 23:25:00,21.236122231099998\n2014-04-13 23:30:00,19.5515975023\n2014-04-13 23:35:00,21.3388851453\n2014-04-13 23:40:00,19.530185945899998\n2014-04-13 23:45:00,21.3006865654\n2014-04-13 23:50:00,19.3369832468\n2014-04-13 23:55:00,19.7643248384\n2014-04-14 00:00:00,20.4619536774\n2014-04-14 00:05:00,18.2811504561\n2014-04-14 00:10:00,21.7928282473\n2014-04-14 00:15:00,20.2944231445\n2014-04-14 00:20:00,20.0312800588\n2014-04-14 00:25:00,21.3575758845\n2014-04-14 00:30:00,21.4630509196\n2014-04-14 00:35:00,20.089041618099998\n2014-04-14 00:40:00,21.7090493032\n2014-04-14 00:45:00,18.2589510643\n2014-04-14 00:50:00,18.452903169000002\n2014-04-14 00:55:00,20.3871529201\n2014-04-14 01:00:00,19.4162634472\n2014-04-14 01:05:00,19.8569006648\n2014-04-14 01:10:00,19.3123168716\n2014-04-14 01:15:00,19.6189012458\n2014-04-14 01:20:00,21.2905853886\n2014-04-14 01:25:00,20.3739047994\n2014-04-14 01:30:00,21.9893781971\n2014-04-14 01:35:00,21.147516791300003\n2014-04-14 01:40:00,19.0946650164\n2014-04-14 01:45:00,19.0573804709\n2014-04-14 01:50:00,19.3435930805\n2014-04-14 01:55:00,21.3730379226\n2014-04-14 02:00:00,18.1091506026\n2014-04-14 02:05:00,18.920725115499998\n2014-04-14 02:10:00,21.6196736814\n2014-04-14 02:15:00,20.5595857443\n2014-04-14 02:20:00,18.907388382\n2014-04-14 02:25:00,18.8765798729\n2014-04-14 02:30:00,21.450472407\n2014-04-14 02:35:00,21.5750300331\n2014-04-14 02:40:00,19.0245243638\n2014-04-14 02:45:00,19.6820414323\n2014-04-14 02:50:00,21.338382954500002\n2014-04-14 02:55:00,21.0840297544\n2014-04-14 03:00:00,21.2556644263\n2014-04-14 03:05:00,20.0735927632\n2014-04-14 03:10:00,21.6461961932\n2014-04-14 03:15:00,19.3038061758\n2014-04-14 03:20:00,18.6266885374\n2014-04-14 03:25:00,20.8349293303\n2014-04-14 03:30:00,20.157417664\n2014-04-14 03:35:00,21.4183430752\n2014-04-14 03:40:00,18.3246369965\n2014-04-14 03:45:00,21.3747696138\n2014-04-14 03:50:00,19.1731786128\n2014-04-14 03:55:00,20.6194226687\n2014-04-14 04:00:00,18.1605151563\n2014-04-14 04:05:00,20.4383251852\n2014-04-14 04:10:00,20.8690867567\n2014-04-14 04:15:00,19.475000857999998\n2014-04-14 04:20:00,18.861642821\n2014-04-14 04:25:00,20.1505227064\n2014-04-14 04:30:00,21.3327632177\n2014-04-14 04:35:00,19.2941894332\n2014-04-14 04:40:00,19.0098771901\n2014-04-14 04:45:00,19.1157412346\n2014-04-14 04:50:00,21.7965286117\n2014-04-14 04:55:00,19.4371076631\n2014-04-14 05:00:00,18.014416959600002\n2014-04-14 05:05:00,21.1267248318\n2014-04-14 05:10:00,20.797099181300002\n2014-04-14 05:15:00,18.5142730584\n2014-04-14 05:20:00,21.9396169965\n2014-04-14 05:25:00,20.4322491412\n2014-04-14 05:30:00,20.0031179638\n2014-04-14 05:35:00,19.5288770705\n2014-04-14 05:40:00,21.5946910223\n2014-04-14 05:45:00,18.9758539257\n2014-04-14 05:50:00,19.143075600899998\n2014-04-14 05:55:00,18.4896432267\n2014-04-14 06:00:00,21.036476382300002\n2014-04-14 06:05:00,20.3821971216\n2014-04-14 06:10:00,20.436264677\n2014-04-14 06:15:00,18.873881724100002\n2014-04-14 06:20:00,20.6046735565\n2014-04-14 06:25:00,21.061833789\n2014-04-14 06:30:00,19.4315541229\n2014-04-14 06:35:00,21.2053885758\n2014-04-14 06:40:00,19.395162354100002\n2014-04-14 06:45:00,21.032553846\n2014-04-14 06:50:00,18.1349204298\n2014-04-14 06:55:00,20.2046584059\n2014-04-14 07:00:00,21.8781062426\n2014-04-14 07:05:00,21.9249784027\n2014-04-14 07:10:00,19.1270103134\n2014-04-14 07:15:00,19.765596364300002\n2014-04-14 07:20:00,18.2519116319\n2014-04-14 07:25:00,21.4933652304\n2014-04-14 07:30:00,20.2742886126\n2014-04-14 07:35:00,19.5404027158\n2014-04-14 07:40:00,18.451082234\n2014-04-14 07:45:00,21.787069141999996\n2014-04-14 07:50:00,20.120876191300002\n2014-04-14 07:55:00,19.1317117163\n2014-04-14 08:00:00,19.4008605205\n2014-04-14 08:05:00,19.0827887237\n2014-04-14 08:10:00,20.4072392354\n2014-04-14 08:15:00,21.7198543031\n2014-04-14 08:20:00,21.4267752133\n2014-04-14 08:25:00,19.8415235017\n2014-04-14 08:30:00,21.3059974492\n2014-04-14 08:35:00,19.6924219251\n2014-04-14 08:40:00,19.009228563\n2014-04-14 08:45:00,21.9336604611\n2014-04-14 08:50:00,19.2155502719\n2014-04-14 08:55:00,19.2948969239\n2014-04-14 09:00:00,74.6598230019\n2014-04-14 09:05:00,63.0214139071\n2014-04-14 09:10:00,71.54326223689999\n2014-04-14 09:15:00,73.9270535154\n2014-04-14 09:20:00,68.1604119221\n2014-04-14 09:25:00,61.234295959200004\n2014-04-14 09:30:00,66.3008016399\n2014-04-14 09:35:00,62.7173382964\n2014-04-14 09:40:00,66.8601521887\n2014-04-14 09:45:00,71.9443639583\n2014-04-14 09:50:00,67.16647706479999\n2014-04-14 09:55:00,67.07418165029999\n2014-04-14 10:00:00,78.4813726818\n2014-04-14 10:05:00,78.8678378753\n2014-04-14 10:10:00,83.1297187126\n2014-04-14 10:15:00,74.6256764168\n2014-04-14 10:20:00,82.592338023\n2014-04-14 10:25:00,78.6232917797\n2014-04-14 10:30:00,74.5042186116\n2014-04-14 10:35:00,74.420356203\n2014-04-14 10:40:00,75.4448542655\n2014-04-14 10:45:00,79.50419912550001\n2014-04-14 10:50:00,73.42219807069999\n2014-04-14 10:55:00,84.12357687720001\n2014-04-14 11:00:00,80.7114097388\n2014-04-14 11:05:00,86.1999309173\n2014-04-14 11:10:00,72.3060149188\n2014-04-14 11:15:00,77.0168912358\n2014-04-14 11:20:00,71.9307330356\n2014-04-14 11:25:00,75.8978928673\n2014-04-14 11:30:00,85.277350935\n2014-04-14 11:35:00,72.1502409208\n2014-04-14 11:40:00,78.5044834771\n2014-04-14 11:45:00,73.4377866888\n2014-04-14 11:50:00,78.1974338449\n2014-04-14 11:55:00,84.9090955961\n2014-04-14 12:00:00,81.87077357060001\n2014-04-14 12:05:00,83.6875558035\n2014-04-14 12:10:00,77.4925630482\n2014-04-14 12:15:00,87.00583068440002\n2014-04-14 12:20:00,83.2481756683\n2014-04-14 12:25:00,78.6542825712\n2014-04-14 12:30:00,78.7288486795\n2014-04-14 12:35:00,86.59490811090002\n2014-04-14 12:40:00,81.12500812489999\n2014-04-14 12:45:00,83.20210487760001\n2014-04-14 12:50:00,78.5781565159\n2014-04-14 12:55:00,75.48838933520001\n2014-04-14 13:00:00,83.5568902042\n2014-04-14 13:05:00,181.705566311\n2014-04-14 13:10:00,80.0022809301\n2014-04-14 13:15:00,81.9646587995\n2014-04-14 13:20:00,75.3144895604\n2014-04-14 13:25:00,84.6826905799\n2014-04-14 13:30:00,87.1496839352\n2014-04-14 13:35:00,86.2369484706\n2014-04-14 13:40:00,77.1244576117\n2014-04-14 13:45:00,78.4772533103\n2014-04-14 13:50:00,84.9140525319\n2014-04-14 13:55:00,81.5023088434\n2014-04-14 14:00:00,80.7627543005\n2014-04-14 14:05:00,86.8221038195\n2014-04-14 14:10:00,80.57253170850001\n2014-04-14 14:15:00,80.2351674005\n2014-04-14 14:20:00,72.66880919\n2014-04-14 14:25:00,73.10716202520001\n2014-04-14 14:30:00,72.11526322729999\n2014-04-14 14:35:00,86.607750241\n2014-04-14 14:40:00,78.53041691930001\n2014-04-14 14:45:00,79.493166163\n2014-04-14 14:50:00,85.5220859043\n2014-04-14 14:55:00,81.74401706479999\n2014-04-14 15:00:00,81.75124072279999\n2014-04-14 15:05:00,76.743814122\n2014-04-14 15:10:00,85.3417146945\n2014-04-14 15:15:00,74.6525629451\n2014-04-14 15:20:00,72.849694111\n2014-04-14 15:25:00,75.06493309\n2014-04-14 15:30:00,76.283063176\n2014-04-14 15:35:00,76.5162423627\n2014-04-14 15:40:00,82.727423387\n2014-04-14 15:45:00,75.4844687394\n2014-04-14 15:50:00,82.8257377372\n2014-04-14 15:55:00,73.4574095738\n2014-04-14 16:00:00,74.3550966155\n2014-04-14 16:05:00,80.1409893049\n2014-04-14 16:10:00,86.7501662806\n2014-04-14 16:15:00,85.7529167751\n2014-04-14 16:20:00,87.49988707899998\n2014-04-14 16:25:00,82.4075068217\n2014-04-14 16:30:00,82.8128788616\n2014-04-14 16:35:00,82.00021054220001\n2014-04-14 16:40:00,81.9649453927\n2014-04-14 16:45:00,74.3537827615\n2014-04-14 16:50:00,80.699668355\n2014-04-14 16:55:00,78.17693683520001\n2014-04-14 17:00:00,79.0805650855\n2014-04-14 17:05:00,80.37757830390001\n2014-04-14 17:10:00,74.054310312\n2014-04-14 17:15:00,77.7517738849\n2014-04-14 17:20:00,73.0151649362\n2014-04-14 17:25:00,87.6746564197\n2014-04-14 17:30:00,73.8964200849\n2014-04-14 17:35:00,76.13636658029999\n2014-04-14 17:40:00,86.26065370319998\n2014-04-14 17:45:00,79.7233301261\n2014-04-14 17:50:00,74.170166743\n2014-04-14 17:55:00,78.1476585999\n2014-04-14 18:00:00,29.541549490799998\n2014-04-14 18:05:00,30.0813766057\n2014-04-14 18:10:00,29.1329854269\n2014-04-14 18:15:00,31.604649896999998\n2014-04-14 18:20:00,33.9624646582\n2014-04-14 18:25:00,32.550196494\n2014-04-14 18:30:00,32.6806036804\n2014-04-14 18:35:00,30.0837320165\n2014-04-14 18:40:00,31.0009146446\n2014-04-14 18:45:00,34.2095428963\n2014-04-14 18:50:00,29.3622739421\n2014-04-14 18:55:00,34.2907495997\n2014-04-14 19:00:00,22.3269300929\n2014-04-14 19:05:00,23.9104191807\n2014-04-14 19:10:00,21.5846675748\n2014-04-14 19:15:00,21.6780152339\n2014-04-14 19:20:00,23.527188519499997\n2014-04-14 19:25:00,23.676781558000002\n2014-04-14 19:30:00,21.188806995\n2014-04-14 19:35:00,24.5184621902\n2014-04-14 19:40:00,20.5385145403\n2014-04-14 19:45:00,20.4668921519\n2014-04-14 19:50:00,22.827857632199997\n2014-04-14 19:55:00,23.3978773561\n2014-04-14 20:00:00,22.3677893169\n2014-04-14 20:05:00,20.0906576771\n2014-04-14 20:10:00,18.535593388800002\n2014-04-14 20:15:00,20.9014631556\n2014-04-14 20:20:00,19.6185946649\n2014-04-14 20:25:00,20.205351166\n2014-04-14 20:30:00,20.4327707541\n2014-04-14 20:35:00,18.6962434292\n2014-04-14 20:40:00,20.4225811445\n2014-04-14 20:45:00,20.1782051131\n2014-04-14 20:50:00,21.3505810544\n2014-04-14 20:55:00,21.0766473194\n2014-04-14 21:00:00,18.8308189683\n2014-04-14 21:05:00,18.9149134938\n2014-04-14 21:10:00,19.095243987\n2014-04-14 21:15:00,18.805637563599998\n2014-04-14 21:20:00,20.727871241400003\n2014-04-14 21:25:00,22.083213722199996\n2014-04-14 21:30:00,20.7073537916\n2014-04-14 21:35:00,20.524774420299998\n2014-04-14 21:40:00,19.7339823015\n2014-04-14 21:45:00,19.3427225291\n2014-04-14 21:50:00,21.7481875906\n2014-04-14 21:55:00,21.9810122788\n2014-04-14 22:00:00,20.006292313\n2014-04-14 22:05:00,19.1791963425\n2014-04-14 22:10:00,21.100726089600002\n2014-04-14 22:15:00,18.547615788399998\n2014-04-14 22:20:00,21.0825727991\n2014-04-14 22:25:00,21.2962182485\n2014-04-14 22:30:00,18.5173754006\n2014-04-14 22:35:00,21.9284770125\n2014-04-14 22:40:00,21.963113518000004\n2014-04-14 22:45:00,21.7677549094\n2014-04-14 22:50:00,20.0033240015\n2014-04-14 22:55:00,19.0025214845\n2014-04-14 23:00:00,20.3319401047\n2014-04-14 23:05:00,19.6835138611\n2014-04-14 23:10:00,18.8274087456\n2014-04-14 23:15:00,19.69848702\n2014-04-14 23:20:00,20.6595252081\n2014-04-14 23:25:00,18.2871637028\n2014-04-14 23:30:00,19.3373840689\n2014-04-14 23:35:00,18.0746492248\n2014-04-14 23:40:00,21.0020136323\n2014-04-14 23:45:00,20.5667131193\n2014-04-14 23:50:00,18.254192669200002\n2014-04-14 23:55:00,21.8631471547\n"
  },
  {
    "path": "workspace/anomaly_detector/datasets/selected/seasonal/art_daily_jumpsup_noised_trended_det.csv",
    "content": ",timestamp,value\n0,2014-04-01 00:00:00,19.761251902999998\n1,2014-04-01 00:05:00,20.508273763190473\n2,2014-04-01 00:10:00,19.976522396880952\n3,2014-04-01 00:15:00,21.512587501971428\n4,2014-04-01 00:20:00,20.217501314561904\n5,2014-04-01 00:25:00,19.96032805275238\n6,2014-04-01 00:30:00,21.74304681884286\n7,2014-04-01 00:35:00,20.930841717533333\n8,2014-04-01 00:40:00,18.50572343892381\n9,2014-04-01 00:45:00,18.777782130514286\n10,2014-04-01 00:50:00,21.222896213704765\n11,2014-04-01 00:55:00,21.42525052279524\n12,2014-04-01 01:00:00,20.270049030685716\n13,2014-04-01 01:05:00,20.314547101976192\n14,2014-04-01 01:10:00,20.63189851806667\n15,2014-04-01 01:15:00,19.86807023995714\n16,2014-04-01 01:20:00,20.83984411294762\n17,2014-04-01 01:25:00,18.560413125538094\n18,2014-04-01 01:30:00,21.97904554092857\n19,2014-04-01 01:35:00,21.141988342819047\n20,2014-04-01 01:40:00,20.673506339809524\n21,2014-04-01 01:45:00,19.421538228\n22,2014-04-01 01:50:00,18.807512425990474\n23,2014-04-01 01:55:00,19.808502807680952\n24,2014-04-01 02:00:00,20.824878390871426\n25,2014-04-01 02:05:00,20.720850878461903\n26,2014-04-01 02:10:00,19.724017001252378\n27,2014-04-01 02:15:00,20.654038432442857\n28,2014-04-01 02:20:00,21.463326515633334\n29,2014-04-01 02:25:00,18.32091289892381\n30,2014-04-01 02:30:00,20.025698477414284\n31,2014-04-01 02:35:00,21.264875675804763\n32,2014-04-01 02:40:00,20.42267311999524\n33,2014-04-01 02:45:00,20.851440065985717\n34,2014-04-01 02:50:00,20.31968176087619\n35,2014-04-01 02:55:00,22.227914845366666\n36,2014-04-01 03:00:00,18.486343288857142\n37,2014-04-01 03:05:00,20.239476906147623\n38,2014-04-01 03:10:00,18.648404291738096\n39,2014-04-01 03:15:00,18.929320819928574\n40,2014-04-01 03:20:00,19.829772449319048\n41,2014-04-01 03:25:00,18.927219889809525\n42,2014-04-01 03:30:00,22.167248663800002\n43,2014-04-01 03:35:00,22.107099583090474\n44,2014-04-01 03:40:00,19.671819537280953\n45,2014-04-01 03:45:00,20.893812276771428\n46,2014-04-01 03:50:00,20.477275187161904\n47,2014-04-01 03:55:00,21.61205030305238\n48,2014-04-01 04:00:00,20.866925296442858\n49,2014-04-01 04:05:00,18.365593151333332\n50,2014-04-01 04:10:00,21.42472135192381\n51,2014-04-01 04:15:00,21.366856770914286\n52,2014-04-01 04:20:00,20.425795584204764\n53,2014-04-01 04:25:00,22.006021130995236\n54,2014-04-01 04:30:00,22.035570537085718\n55,2014-04-01 04:35:00,20.50487289727619\n56,2014-04-01 04:40:00,20.84861959146667\n57,2014-04-01 04:45:00,22.410195430557142\n58,2014-04-01 04:50:00,19.62682855824762\n59,2014-04-01 04:55:00,19.737457064438097\n60,2014-04-01 05:00:00,19.177524182128572\n61,2014-04-01 05:05:00,22.037336804219045\n62,2014-04-01 05:10:00,21.439263083609525\n63,2014-04-01 05:15:00,18.8913213955\n64,2014-04-01 05:20:00,22.403259880990475\n65,2014-04-01 05:25:00,21.40747778498095\n66,2014-04-01 05:30:00,21.893159866971427\n67,2014-04-01 05:35:00,18.691115061461907\n68,2014-04-01 05:40:00,20.52579605675238\n69,2014-04-01 05:45:00,21.307786004042857\n70,2014-04-01 05:50:00,20.69261967163333\n71,2014-04-01 05:55:00,21.19486367232381\n72,2014-04-01 06:00:00,21.807210540114284\n73,2014-04-01 06:05:00,20.040503013704765\n74,2014-04-01 06:10:00,21.94526994059524\n75,2014-04-01 06:15:00,19.209700133385716\n76,2014-04-01 06:20:00,19.64902041057619\n77,2014-04-01 06:25:00,18.746299146366667\n78,2014-04-01 06:30:00,20.038064388157142\n79,2014-04-01 06:35:00,20.10743579834762\n80,2014-04-01 06:40:00,21.816320484038098\n81,2014-04-01 06:45:00,21.21520125262857\n82,2014-04-01 06:50:00,20.357009280219046\n83,2014-04-01 06:55:00,21.226015438309524\n84,2014-04-01 07:00:00,18.8361334021\n85,2014-04-01 07:05:00,19.353526620290474\n86,2014-04-01 07:10:00,21.147672373380953\n87,2014-04-01 07:15:00,21.21278870547143\n88,2014-04-01 07:20:00,21.751300539561907\n89,2014-04-01 07:25:00,20.27420141715238\n90,2014-04-01 07:30:00,21.559859243642858\n91,2014-04-01 07:35:00,21.413004663533332\n92,2014-04-01 07:40:00,22.53809732302381\n93,2014-04-01 07:45:00,19.552485191414284\n94,2014-04-01 07:50:00,20.90612301690476\n95,2014-04-01 07:55:00,21.113903006495235\n96,2014-04-01 08:00:00,22.70887725398571\n97,2014-04-01 08:05:00,19.526462759176187\n98,2014-04-01 08:10:00,20.82203874656667\n99,2014-04-01 08:15:00,20.12134837375714\n100,2014-04-01 08:20:00,20.847619493347622\n101,2014-04-01 08:25:00,19.680002503638093\n102,2014-04-01 08:30:00,18.949378085128572\n103,2014-04-01 08:35:00,21.05663086321905\n104,2014-04-01 08:40:00,20.117226787209525\n105,2014-04-01 08:45:00,19.509015607000002\n106,2014-04-01 08:50:00,20.084432740490474\n107,2014-04-01 08:55:00,18.993251758180953\n108,2014-04-01 09:00:00,74.92958581217142\n109,2014-04-01 09:05:00,69.91462354836189\n110,2014-04-01 09:10:00,73.09930644725237\n111,2014-04-01 09:15:00,67.78030034374287\n112,2014-04-01 09:20:00,74.31841281223333\n113,2014-04-01 09:25:00,68.61390162262381\n114,2014-04-01 09:30:00,69.85387066761429\n115,2014-04-01 09:35:00,68.74405289080477\n116,2014-04-01 09:40:00,72.03568006189523\n117,2014-04-01 09:45:00,69.7770583696857\n118,2014-04-01 09:50:00,65.77172155117619\n119,2014-04-01 09:55:00,64.06475429266668\n120,2014-04-01 10:00:00,80.13990765835715\n121,2014-04-01 10:05:00,78.33237062224762\n122,2014-04-01 10:10:00,72.2372809079381\n123,2014-04-01 10:15:00,76.89516164052857\n124,2014-04-01 10:20:00,78.75194911701905\n125,2014-04-01 10:25:00,83.60344251280951\n126,2014-04-01 10:30:00,71.9585883865\n127,2014-04-01 10:35:00,76.19358828099048\n128,2014-04-01 10:40:00,83.56000397688095\n129,2014-04-01 10:45:00,80.86336084967142\n130,2014-04-01 10:50:00,75.3074150591619\n131,2014-04-01 10:55:00,83.93430347475238\n132,2014-04-01 11:00:00,80.39548396244285\n133,2014-04-01 11:05:00,80.48337181273332\n134,2014-04-01 11:10:00,88.09666885212381\n135,2014-04-01 11:15:00,87.6354051532143\n136,2014-04-01 11:20:00,78.28200855820477\n137,2014-04-01 11:25:00,74.82311570039523\n138,2014-04-01 11:30:00,77.77418942448571\n139,2014-04-01 11:35:00,73.08703196247619\n140,2014-04-01 11:40:00,72.93995913686668\n141,2014-04-01 11:45:00,78.90749119775714\n142,2014-04-01 11:50:00,87.59052687924762\n143,2014-04-01 11:55:00,86.4900552502381\n144,2014-04-01 12:00:00,81.15829421172856\n145,2014-04-01 12:05:00,82.02523879981905\n146,2014-04-01 12:10:00,73.09473154860952\n147,2014-04-01 12:15:00,76.4512308711\n148,2014-04-01 12:20:00,73.41070084389048\n149,2014-04-01 12:25:00,85.08037631648095\n150,2014-04-01 12:30:00,75.35720776567143\n151,2014-04-01 12:35:00,86.9251798400619\n152,2014-04-01 12:40:00,83.32538957295237\n153,2014-04-01 12:45:00,76.71828684284286\n154,2014-04-01 12:50:00,75.57993017653332\n155,2014-04-01 12:55:00,83.09681863002382\n156,2014-04-01 13:00:00,87.55336675621429\n157,2014-04-01 13:05:00,84.64187976130475\n158,2014-04-01 13:10:00,78.73372324459524\n159,2014-04-01 13:15:00,82.56163768558571\n160,2014-04-01 13:20:00,78.1441899914762\n161,2014-04-01 13:25:00,89.16319300076667\n162,2014-04-01 13:30:00,85.16662861575713\n163,2014-04-01 13:35:00,83.02326462964763\n164,2014-04-01 13:40:00,79.97347906433811\n165,2014-04-01 13:45:00,83.09846151082857\n166,2014-04-01 13:50:00,78.68238424141906\n167,2014-04-01 13:55:00,73.68700611410952\n168,2014-04-01 14:00:00,79.56765692970001\n169,2014-04-01 14:05:00,88.14096298019048\n170,2014-04-01 14:10:00,83.28176146948095\n171,2014-04-01 14:15:00,74.61209219977142\n172,2014-04-01 14:20:00,87.43552404396192\n173,2014-04-01 14:25:00,77.58553747455238\n174,2014-04-01 14:30:00,77.19131153154285\n175,2014-04-01 14:35:00,78.05185466793333\n176,2014-04-01 14:40:00,82.54086029622381\n177,2014-04-01 14:45:00,82.02809946021429\n178,2014-04-01 14:50:00,81.18319143010476\n179,2014-04-01 14:55:00,84.80842798599524\n180,2014-04-01 15:00:00,78.40314959548569\n181,2014-04-01 15:05:00,85.85894721047619\n182,2014-04-01 15:10:00,76.15859539126667\n183,2014-04-01 15:15:00,85.88272835755714\n184,2014-04-01 15:20:00,83.98921614184762\n185,2014-04-01 15:25:00,84.3070249072381\n186,2014-04-01 15:30:00,81.08801775882857\n187,2014-04-01 15:35:00,84.06259991911905\n188,2014-04-01 15:40:00,74.67485881190952\n189,2014-04-01 15:45:00,87.0302458745\n190,2014-04-01 15:50:00,74.30174647989048\n191,2014-04-01 15:55:00,75.80028106358095\n192,2014-04-01 16:00:00,82.65705080557143\n193,2014-04-01 16:05:00,85.2664342373619\n194,2014-04-01 16:10:00,74.66333682805238\n195,2014-04-01 16:15:00,88.18296335724288\n196,2014-04-01 16:20:00,89.03588756493333\n197,2014-04-01 16:25:00,83.16081972282379\n198,2014-04-01 16:30:00,81.1729565479143\n199,2014-04-01 16:35:00,85.34281330270476\n200,2014-04-01 16:40:00,78.74166454819525\n201,2014-04-01 16:45:00,81.38761326688571\n202,2014-04-01 16:50:00,88.16122623537619\n203,2014-04-01 16:55:00,88.80073587276668\n204,2014-04-01 17:00:00,88.35092965575714\n205,2014-04-01 17:05:00,77.72443742994763\n206,2014-04-01 17:10:00,77.25221366243811\n207,2014-04-01 17:15:00,78.30278118942857\n208,2014-04-01 17:20:00,80.60856648641905\n209,2014-04-01 17:25:00,78.58170855020953\n210,2014-04-01 17:30:00,79.54987478470001\n211,2014-04-01 17:35:00,83.50010024889049\n212,2014-04-01 17:40:00,85.77775945288096\n213,2014-04-01 17:45:00,85.35372043357143\n214,2014-04-01 17:50:00,86.6230063261619\n215,2014-04-01 17:55:00,74.11462498665237\n216,2014-04-01 18:00:00,30.71263352284286\n217,2014-04-01 18:05:00,35.46662778213334\n218,2014-04-01 18:10:00,33.833722087723814\n219,2014-04-01 18:15:00,34.12955835781428\n220,2014-04-01 18:20:00,30.773455073104763\n221,2014-04-01 18:25:00,32.07834772229524\n222,2014-04-01 18:30:00,34.537246951585715\n223,2014-04-01 18:35:00,35.95798370177619\n224,2014-04-01 18:40:00,36.33535375226666\n225,2014-04-01 18:45:00,33.676785771657144\n226,2014-04-01 18:50:00,33.97257650864762\n227,2014-04-01 18:55:00,35.82049918083809\n228,2014-04-01 19:00:00,24.26498554472857\n229,2014-04-01 19:05:00,24.179394009119047\n230,2014-04-01 19:10:00,25.92608468460952\n231,2014-04-01 19:15:00,25.417647290300003\n232,2014-04-01 19:20:00,25.958834064990477\n233,2014-04-01 19:25:00,22.871376598280953\n234,2014-04-01 19:30:00,24.250272373971427\n235,2014-04-01 19:35:00,25.682785727861905\n236,2014-04-01 19:40:00,22.41389351475238\n237,2014-04-01 19:45:00,25.483478007142857\n238,2014-04-01 19:50:00,22.750552940133332\n239,2014-04-01 19:55:00,25.55864452732381\n240,2014-04-01 20:00:00,22.724469874714284\n241,2014-04-01 20:05:00,21.016649152304762\n242,2014-04-01 20:10:00,22.171453712195238\n243,2014-04-01 20:15:00,23.033119021385716\n244,2014-04-01 20:20:00,22.84373742017619\n245,2014-04-01 20:25:00,22.00492094026667\n246,2014-04-01 20:30:00,23.946162179957142\n247,2014-04-01 20:35:00,22.39670031804762\n248,2014-04-01 20:40:00,22.349270303938095\n249,2014-04-01 20:45:00,20.539656763628575\n250,2014-04-01 20:50:00,24.06912389771905\n251,2014-04-01 20:55:00,21.025028759209526\n252,2014-04-01 21:00:00,22.0849229424\n253,2014-04-01 21:05:00,23.198539327590474\n254,2014-04-01 21:10:00,20.842230716780954\n255,2014-04-01 21:15:00,22.103340106171427\n256,2014-04-01 21:20:00,20.958522645261905\n257,2014-04-01 21:25:00,23.05196846445238\n258,2014-04-01 21:30:00,22.27424282924286\n259,2014-04-01 21:35:00,23.45382145873333\n260,2014-04-01 21:40:00,23.61633128162381\n261,2014-04-01 21:45:00,22.635753847714284\n262,2014-04-01 21:50:00,22.951297207104762\n263,2014-04-01 21:55:00,22.250670613895238\n264,2014-04-01 22:00:00,21.520756843285717\n265,2014-04-01 22:05:00,22.58396664527619\n266,2014-04-01 22:10:00,23.633088978266667\n267,2014-04-01 22:15:00,21.672208707557143\n268,2014-04-01 22:20:00,21.27017504954762\n269,2014-04-01 22:25:00,21.574007437638095\n270,2014-04-01 22:30:00,21.76947100942857\n271,2014-04-01 22:35:00,20.32817562891905\n272,2014-04-01 22:40:00,22.03677089240952\n273,2014-04-01 22:45:00,22.0276851491\n274,2014-04-01 22:50:00,22.412005401090475\n275,2014-04-01 22:55:00,21.516084293580953\n276,2014-04-01 23:00:00,22.509928676971427\n277,2014-04-01 23:05:00,23.578007613861903\n278,2014-04-01 23:10:00,23.89452614255238\n279,2014-04-01 23:15:00,22.41424593384286\n280,2014-04-01 23:20:00,20.257185857233335\n281,2014-04-01 23:25:00,23.97191816972381\n282,2014-04-01 23:30:00,22.925660629314283\n283,2014-04-01 23:35:00,21.453223374304763\n284,2014-04-01 23:40:00,20.705295057195237\n285,2014-04-01 23:45:00,20.697776306885714\n286,2014-04-01 23:50:00,20.80253864087619\n287,2014-04-01 23:55:00,20.32119775106667\n288,2014-04-02 00:00:00,23.751473897457142\n289,2014-04-02 00:05:00,22.31337055034762\n290,2014-04-02 00:10:00,22.957575746138094\n291,2014-04-02 00:15:00,23.477612608528574\n292,2014-04-02 00:20:00,23.338783072919046\n293,2014-04-02 00:25:00,23.71048201870952\n294,2014-04-02 00:30:00,24.056518490100004\n295,2014-04-02 00:35:00,21.95122293519048\n296,2014-04-02 00:40:00,24.003722819080952\n297,2014-04-02 00:45:00,23.102981221971426\n298,2014-04-02 00:50:00,20.499934665961906\n299,2014-04-02 00:55:00,22.951834865752378\n300,2014-04-02 01:00:00,22.979009495542858\n301,2014-04-02 01:05:00,23.863025588533333\n302,2014-04-02 01:10:00,21.73875233942381\n303,2014-04-02 01:15:00,22.594110286814285\n304,2014-04-02 01:20:00,20.310654965904764\n305,2014-04-02 01:25:00,21.597646206795236\n306,2014-04-02 01:30:00,20.525760618885716\n307,2014-04-02 01:35:00,22.371718081576187\n308,2014-04-02 01:40:00,23.56145726866667\n309,2014-04-02 01:45:00,21.124877911357142\n310,2014-04-02 01:50:00,22.41631180124762\n311,2014-04-02 01:55:00,21.130022641238092\n312,2014-04-02 02:00:00,20.80418244282857\n313,2014-04-02 02:05:00,22.372856215319047\n314,2014-04-02 02:10:00,20.65290400760952\n315,2014-04-02 02:15:00,22.6931685246\n316,2014-04-02 02:20:00,20.47654031889048\n317,2014-04-02 02:25:00,20.785490839880953\n318,2014-04-02 02:30:00,22.566061370471427\n319,2014-04-02 02:35:00,22.739141556361908\n320,2014-04-02 02:40:00,20.49690010135238\n321,2014-04-02 02:45:00,22.681900009142858\n322,2014-04-02 02:50:00,23.749843434633334\n323,2014-04-02 02:55:00,23.29253851872381\n324,2014-04-02 03:00:00,20.935454701414283\n325,2014-04-02 03:05:00,22.788053352204763\n326,2014-04-02 03:10:00,23.11460523839524\n327,2014-04-02 03:15:00,20.581960521285716\n328,2014-04-02 03:20:00,23.86186686517619\n329,2014-04-02 03:25:00,24.07298625586667\n330,2014-04-02 03:30:00,23.857166236257143\n331,2014-04-02 03:35:00,23.76132349104762\n332,2014-04-02 03:40:00,23.450098889038095\n333,2014-04-02 03:45:00,23.011406696528574\n334,2014-04-02 03:50:00,23.199627067619048\n335,2014-04-02 03:55:00,23.718140697109526\n336,2014-04-02 04:00:00,23.1499938334\n337,2014-04-02 04:05:00,21.818348302890474\n338,2014-04-02 04:10:00,22.01872536098095\n339,2014-04-02 04:15:00,24.110551302071425\n340,2014-04-02 04:20:00,20.598250247961904\n341,2014-04-02 04:25:00,23.33248470595238\n342,2014-04-02 04:30:00,24.363753066842854\n343,2014-04-02 04:35:00,23.376996013133333\n344,2014-04-02 04:40:00,24.53517176242381\n345,2014-04-02 04:45:00,23.317143907814284\n346,2014-04-02 04:50:00,20.711856878804763\n347,2014-04-02 04:55:00,23.88988476469524\n348,2014-04-02 05:00:00,21.727805362085714\n349,2014-04-02 05:05:00,22.38095509317619\n350,2014-04-02 05:10:00,21.852534330266668\n351,2014-04-02 05:15:00,21.685823567657142\n352,2014-04-02 05:20:00,22.34467043374762\n353,2014-04-02 05:25:00,22.141493889038095\n354,2014-04-02 05:30:00,23.167282898828574\n355,2014-04-02 05:35:00,23.893973851619048\n356,2014-04-02 05:40:00,21.83716413650952\n357,2014-04-02 05:45:00,21.5111346113\n358,2014-04-02 05:50:00,23.331271559690475\n359,2014-04-02 05:55:00,23.352411215680952\n360,2014-04-02 06:00:00,24.283096385671428\n361,2014-04-02 06:05:00,20.749794650561903\n362,2014-04-02 06:10:00,24.10561502945238\n363,2014-04-02 06:15:00,22.78490154894286\n364,2014-04-02 06:20:00,23.19354169003333\n365,2014-04-02 06:25:00,21.08125957172381\n366,2014-04-02 06:30:00,22.453674017214286\n367,2014-04-02 06:35:00,21.639864390904762\n368,2014-04-02 06:40:00,21.754995358395238\n369,2014-04-02 06:45:00,22.761916172985714\n370,2014-04-02 06:50:00,24.00279999207619\n371,2014-04-02 06:55:00,23.735540387266667\n372,2014-04-02 07:00:00,23.131856979157142\n373,2014-04-02 07:05:00,22.93297039004762\n374,2014-04-02 07:10:00,22.491962268138096\n375,2014-04-02 07:15:00,24.68101846562857\n376,2014-04-02 07:20:00,23.038389264519047\n377,2014-04-02 07:25:00,21.820925117009523\n378,2014-04-02 07:30:00,21.732863168199998\n379,2014-04-02 07:35:00,23.265352599290473\n380,2014-04-02 07:40:00,22.918691061580954\n381,2014-04-02 07:45:00,20.865612640371427\n382,2014-04-02 07:50:00,24.162523393561905\n383,2014-04-02 07:55:00,23.66619179785238\n384,2014-04-02 08:00:00,23.504460015842856\n385,2014-04-02 08:05:00,21.13970596413333\n386,2014-04-02 08:10:00,22.32024721022381\n387,2014-04-02 08:15:00,24.620993328614283\n388,2014-04-02 08:20:00,24.337261727304764\n389,2014-04-02 08:25:00,22.03651698959524\n390,2014-04-02 08:30:00,21.530021250685717\n391,2014-04-02 08:35:00,22.705578019176187\n392,2014-04-02 08:40:00,22.339988181366667\n393,2014-04-02 08:45:00,23.653012649657143\n394,2014-04-02 08:50:00,24.797286859347622\n395,2014-04-02 08:55:00,22.390993895138095\n396,2014-04-02 09:00:00,64.99267731952858\n397,2014-04-02 09:05:00,76.36141956111905\n398,2014-04-02 09:10:00,64.67742585510952\n399,2014-04-02 09:15:00,77.1263662013\n400,2014-04-02 09:20:00,73.21447069709048\n401,2014-04-02 09:25:00,76.99060418718095\n402,2014-04-02 09:30:00,66.90644316697144\n403,2014-04-02 09:35:00,64.75202912026191\n404,2014-04-02 09:40:00,70.84560808555239\n405,2014-04-02 09:45:00,70.34187129534286\n406,2014-04-02 09:50:00,68.72912824963333\n407,2014-04-02 09:55:00,77.25240186122382\n408,2014-04-02 10:00:00,85.64221380881429\n409,2014-04-02 10:05:00,83.15090773360475\n410,2014-04-02 10:10:00,75.41815592429523\n411,2014-04-02 10:15:00,84.29473500988571\n412,2014-04-02 10:20:00,84.18870948737619\n413,2014-04-02 10:25:00,79.50997472116667\n414,2014-04-02 10:30:00,87.27303446165713\n415,2014-04-02 10:35:00,75.51929435124762\n416,2014-04-02 10:40:00,77.08431706383809\n417,2014-04-02 10:45:00,73.92392031662857\n418,2014-04-02 10:50:00,85.29551791851905\n419,2014-04-02 10:55:00,82.60726519600952\n420,2014-04-02 11:00:00,79.7018106216\n421,2014-04-02 11:05:00,77.30573298199049\n422,2014-04-02 11:10:00,75.34639108688094\n423,2014-04-02 11:15:00,77.36724295197143\n424,2014-04-02 11:20:00,81.93180092016188\n425,2014-04-02 11:25:00,78.66130489605239\n426,2014-04-02 11:30:00,78.85649540704286\n427,2014-04-02 11:35:00,88.67024986883332\n428,2014-04-02 11:40:00,82.94527336822381\n429,2014-04-02 11:45:00,86.3579876663143\n430,2014-04-02 11:50:00,75.33535169520476\n431,2014-04-02 11:55:00,80.58240324679524\n432,2014-04-02 12:00:00,82.78539522118571\n433,2014-04-02 12:05:00,78.1144166701762\n434,2014-04-02 12:10:00,77.06352365216668\n435,2014-04-02 12:15:00,89.05835776635715\n436,2014-04-02 12:20:00,90.17051656544761\n437,2014-04-02 12:25:00,76.42448217533808\n438,2014-04-02 12:30:00,80.75012681282857\n439,2014-04-02 12:35:00,90.49414001391904\n440,2014-04-02 12:40:00,76.51640054860951\n441,2014-04-02 12:45:00,85.4807540517\n442,2014-04-02 12:50:00,90.73916576129048\n443,2014-04-02 12:55:00,90.84252775528095\n444,2014-04-02 13:00:00,82.82405522547143\n445,2014-04-02 13:05:00,77.8970926726619\n446,2014-04-02 13:10:00,78.53374541685238\n447,2014-04-02 13:15:00,89.53881910974286\n448,2014-04-02 13:20:00,89.8994805398333\n449,2014-04-02 13:25:00,85.04723385362381\n450,2014-04-02 13:30:00,87.58681455981429\n451,2014-04-02 13:35:00,87.17443344940476\n452,2014-04-02 13:40:00,85.93241941099524\n453,2014-04-02 13:45:00,88.5865102486857\n454,2014-04-02 13:50:00,86.3245701976762\n455,2014-04-02 13:55:00,83.91012298976668\n456,2014-04-02 14:00:00,79.18052096175714\n457,2014-04-02 14:05:00,87.29848061884762\n458,2014-04-02 14:10:00,82.9789243803381\n459,2014-04-02 14:15:00,80.12816311552857\n460,2014-04-02 14:20:00,88.24968756471905\n461,2014-04-02 14:25:00,86.57348605340952\n462,2014-04-02 14:30:00,90.4307571332\n463,2014-04-02 14:35:00,78.08842365729048\n464,2014-04-02 14:40:00,85.83545492918095\n465,2014-04-02 14:45:00,79.36400934207144\n466,2014-04-02 14:50:00,89.9204397178619\n467,2014-04-02 14:55:00,77.06316059355238\n468,2014-04-02 15:00:00,85.97993977384286\n469,2014-04-02 15:05:00,88.14614216703333\n470,2014-04-02 15:10:00,81.17496354002381\n471,2014-04-02 15:15:00,90.7698358002143\n472,2014-04-02 15:20:00,89.12277384300475\n473,2014-04-02 15:25:00,80.23250157969524\n474,2014-04-02 15:30:00,75.64675083938572\n475,2014-04-02 15:35:00,80.28000424177621\n476,2014-04-02 15:40:00,80.04189978486667\n477,2014-04-02 15:45:00,89.78771296435714\n478,2014-04-02 15:50:00,91.02964672134762\n479,2014-04-02 15:55:00,76.69032585113808\n480,2014-04-02 16:00:00,83.11199310982857\n481,2014-04-02 16:05:00,84.35202593931905\n482,2014-04-02 16:10:00,77.07275501080952\n483,2014-04-02 16:15:00,81.6335635095\n484,2014-04-02 16:20:00,80.67436117369049\n485,2014-04-02 16:25:00,84.18537791398094\n486,2014-04-02 16:30:00,86.19496727247143\n487,2014-04-02 16:35:00,86.87911382166189\n488,2014-04-02 16:40:00,77.81889031765238\n489,2014-04-02 16:45:00,88.64539287454286\n490,2014-04-02 16:50:00,86.50234672513334\n491,2014-04-02 16:55:00,89.87830692512381\n492,2014-04-02 17:00:00,82.85006082791429\n493,2014-04-02 17:05:00,89.97035782540476\n494,2014-04-02 17:10:00,89.52794822849523\n495,2014-04-02 17:15:00,82.6975546904857\n496,2014-04-02 17:20:00,181.78873924537623\n497,2014-04-02 17:25:00,90.62287552696668\n498,2014-04-02 17:30:00,87.14796085345715\n499,2014-04-02 17:35:00,90.56468981094763\n500,2014-04-02 17:40:00,88.4718020129381\n501,2014-04-02 17:45:00,85.47640620852857\n502,2014-04-02 17:50:00,77.58873511991905\n503,2014-04-02 17:55:00,80.40622084620952\n504,2014-04-02 18:00:00,38.750584685300005\n505,2014-04-02 18:05:00,34.60173598589047\n506,2014-04-02 18:10:00,33.16170647478095\n507,2014-04-02 18:15:00,37.10065650737143\n508,2014-04-02 18:20:00,37.2773827022619\n509,2014-04-02 18:25:00,34.41412591045238\n510,2014-04-02 18:30:00,34.49973762954286\n511,2014-04-02 18:35:00,35.602992334833345\n512,2014-04-02 18:40:00,32.74896753162381\n513,2014-04-02 18:45:00,37.66862505251428\n514,2014-04-02 18:50:00,34.65376708120476\n515,2014-04-02 18:55:00,38.09592251219524\n516,2014-04-02 19:00:00,27.595068699885715\n517,2014-04-02 19:05:00,26.969806030376187\n518,2014-04-02 19:10:00,25.46960488546667\n519,2014-04-02 19:15:00,26.334704106257146\n520,2014-04-02 19:20:00,26.02188147784762\n521,2014-04-02 19:25:00,25.554677756438092\n522,2014-04-02 19:30:00,27.84357783312857\n523,2014-04-02 19:35:00,26.217479517019047\n524,2014-04-02 19:40:00,27.78940769140953\n525,2014-04-02 19:45:00,24.5376276324\n526,2014-04-02 19:50:00,24.705480388590473\n527,2014-04-02 19:55:00,28.459524573180953\n528,2014-04-02 20:00:00,24.768070801371426\n529,2014-04-02 20:05:00,24.456028241161906\n530,2014-04-02 20:10:00,24.51829936865238\n531,2014-04-02 20:15:00,23.264633523842857\n532,2014-04-02 20:20:00,25.334144454033332\n533,2014-04-02 20:25:00,22.74503501892381\n534,2014-04-02 20:30:00,24.753547965214285\n535,2014-04-02 20:35:00,24.750523503504763\n536,2014-04-02 20:40:00,26.164610757195234\n537,2014-04-02 20:45:00,24.582780257385714\n538,2014-04-02 20:50:00,22.99638476527619\n539,2014-04-02 20:55:00,24.788413767166666\n540,2014-04-02 21:00:00,22.471321165957143\n541,2014-04-02 21:05:00,22.93078575564762\n542,2014-04-02 21:10:00,22.244169672238094\n543,2014-04-02 21:15:00,24.18960808872857\n544,2014-04-02 21:20:00,22.473772489919046\n545,2014-04-02 21:25:00,24.028049361109524\n546,2014-04-02 21:30:00,25.898592632600003\n547,2014-04-02 21:35:00,25.04920549609048\n548,2014-04-02 21:40:00,22.47491390838095\n549,2014-04-02 21:45:00,23.072365459371426\n550,2014-04-02 21:50:00,24.886245851961906\n551,2014-04-02 21:55:00,25.782088047752378\n552,2014-04-02 22:00:00,22.25622360264286\n553,2014-04-02 22:05:00,25.384787662133334\n554,2014-04-02 22:10:00,24.388716686223813\n555,2014-04-02 22:15:00,24.333206567714285\n556,2014-04-02 22:20:00,25.989115484804763\n557,2014-04-02 22:25:00,25.155074633495236\n558,2014-04-02 22:30:00,25.572805632485714\n559,2014-04-02 22:35:00,23.59384780207619\n560,2014-04-02 22:40:00,24.403531577966667\n561,2014-04-02 22:45:00,24.65537300035714\n562,2014-04-02 22:50:00,23.486398253347616\n563,2014-04-02 22:55:00,24.489450337838093\n564,2014-04-02 23:00:00,23.14668783882857\n565,2014-04-02 23:05:00,22.780937842619046\n566,2014-04-02 23:10:00,23.71093376820952\n567,2014-04-02 23:15:00,25.1799322874\n568,2014-04-02 23:20:00,25.89509869809048\n569,2014-04-02 23:25:00,24.06829468078095\n570,2014-04-02 23:30:00,24.816315868271428\n571,2014-04-02 23:35:00,22.664195559361904\n572,2014-04-02 23:40:00,25.87795804125238\n573,2014-04-02 23:45:00,24.541702397442858\n574,2014-04-02 23:50:00,25.39624162153333\n575,2014-04-02 23:55:00,25.46010474192381\n576,2014-04-03 00:00:00,23.311636391214286\n577,2014-04-03 00:05:00,24.409852574604763\n578,2014-04-03 00:10:00,26.142514244295235\n579,2014-04-03 00:15:00,22.666573893585717\n580,2014-04-03 00:20:00,25.04767578257619\n581,2014-04-03 00:25:00,26.171972978766668\n582,2014-04-03 00:30:00,23.53266557505714\n583,2014-04-03 00:35:00,25.78358930464762\n584,2014-04-03 00:40:00,26.079868276838095\n585,2014-04-03 00:45:00,25.341023409028573\n586,2014-04-03 00:50:00,23.28543229681905\n587,2014-04-03 00:55:00,23.703562399109522\n588,2014-04-03 01:00:00,22.5182371777\n589,2014-04-03 01:05:00,25.708253413190477\n590,2014-04-03 01:10:00,25.78832569838095\n591,2014-04-03 01:15:00,24.928162668471426\n592,2014-04-03 01:20:00,23.814873309861905\n593,2014-04-03 01:25:00,22.71944649155238\n594,2014-04-03 01:30:00,25.43187329684286\n595,2014-04-03 01:35:00,25.33318810773333\n596,2014-04-03 01:40:00,26.084933896523808\n597,2014-04-03 01:45:00,25.364092369714285\n598,2014-04-03 01:50:00,25.764184530904764\n599,2014-04-03 01:55:00,25.440663709695237\n600,2014-04-03 02:00:00,24.987034467485714\n601,2014-04-03 02:05:00,24.17959176727619\n602,2014-04-03 02:10:00,26.087635901266665\n603,2014-04-03 02:15:00,25.090481430457142\n604,2014-04-03 02:20:00,24.08746890694762\n605,2014-04-03 02:25:00,22.835365275938095\n606,2014-04-03 02:30:00,23.671747995028568\n607,2014-04-03 02:35:00,24.69127598691905\n608,2014-04-03 02:40:00,23.626351003909527\n609,2014-04-03 02:45:00,23.4161913917\n610,2014-04-03 02:50:00,24.648264532590474\n611,2014-04-03 02:55:00,23.225412335980952\n612,2014-04-03 03:00:00,25.755211681871426\n613,2014-04-03 03:05:00,24.498484510161905\n614,2014-04-03 03:10:00,24.86390347685238\n615,2014-04-03 03:15:00,23.165425927542856\n616,2014-04-03 03:20:00,23.881638675833333\n617,2014-04-03 03:25:00,24.23113254252381\n618,2014-04-03 03:30:00,25.831065607814285\n619,2014-04-03 03:35:00,25.686292854204762\n620,2014-04-03 03:40:00,23.50500513729524\n621,2014-04-03 03:45:00,25.085252040685717\n622,2014-04-03 03:50:00,23.60180162157619\n623,2014-04-03 03:55:00,26.58840528946667\n624,2014-04-03 04:00:00,26.45135265535714\n625,2014-04-03 04:05:00,24.90335650114762\n626,2014-04-03 04:10:00,25.453348382838094\n627,2014-04-03 04:15:00,25.870900100228575\n628,2014-04-03 04:20:00,25.556612727819047\n629,2014-04-03 04:25:00,25.479374288109526\n630,2014-04-03 04:30:00,26.521716031799997\n631,2014-04-03 04:35:00,25.080764901390474\n632,2014-04-03 04:40:00,25.24759163968095\n633,2014-04-03 04:45:00,26.106896430371428\n634,2014-04-03 04:50:00,25.396825376161907\n635,2014-04-03 04:55:00,25.656432869052377\n636,2014-04-03 05:00:00,23.66881760194286\n637,2014-04-03 05:05:00,24.224651029833332\n638,2014-04-03 05:10:00,23.33622919232381\n639,2014-04-03 05:15:00,24.777526055014285\n640,2014-04-03 05:20:00,24.584814364604764\n641,2014-04-03 05:25:00,26.757996495195236\n642,2014-04-03 05:30:00,25.221620325585718\n643,2014-04-03 05:35:00,25.93000548327619\n644,2014-04-03 05:40:00,24.12772534966667\n645,2014-04-03 05:45:00,26.125288468257143\n646,2014-04-03 05:50:00,25.26688748504762\n647,2014-04-03 05:55:00,25.601957421638097\n648,2014-04-03 06:00:00,23.999151683228575\n649,2014-04-03 06:05:00,25.023422614419047\n650,2014-04-03 06:10:00,25.372457417509523\n651,2014-04-03 06:15:00,25.2001287033\n652,2014-04-03 06:20:00,26.51196532189048\n653,2014-04-03 06:25:00,26.451721610380954\n654,2014-04-03 06:30:00,26.75000766007143\n655,2014-04-03 06:35:00,25.543223928761908\n656,2014-04-03 06:40:00,26.76860890145238\n657,2014-04-03 06:45:00,26.218304857242856\n658,2014-04-03 06:50:00,23.979161894733334\n659,2014-04-03 06:55:00,24.613016487723808\n660,2014-04-03 07:00:00,23.864284054514286\n661,2014-04-03 07:05:00,22.934943405204763\n662,2014-04-03 07:10:00,23.67779025069524\n663,2014-04-03 07:15:00,22.949278059385716\n664,2014-04-03 07:20:00,25.81983003587619\n665,2014-04-03 07:25:00,24.650053857566668\n666,2014-04-03 07:30:00,24.205656051157142\n667,2014-04-03 07:35:00,26.00968118344762\n668,2014-04-03 07:40:00,26.300185193738095\n669,2014-04-03 07:45:00,26.878876726028572\n670,2014-04-03 07:50:00,25.553173386319045\n671,2014-04-03 07:55:00,24.838675358009525\n672,2014-04-03 08:00:00,24.2210572064\n673,2014-04-03 08:05:00,23.89671331309048\n674,2014-04-03 08:10:00,23.866584754280954\n675,2014-04-03 08:15:00,24.659078927471427\n676,2014-04-03 08:20:00,26.996907325961903\n677,2014-04-03 08:25:00,23.04061717065238\n678,2014-04-03 08:30:00,23.83346644604286\n679,2014-04-03 08:35:00,23.805655262933332\n680,2014-04-03 08:40:00,25.92800175162381\n681,2014-04-03 08:45:00,24.476903196114286\n682,2014-04-03 08:50:00,24.90344798030476\n683,2014-04-03 08:55:00,23.67634175999524\n684,2014-04-03 09:00:00,71.79724544298571\n685,2014-04-03 09:05:00,67.70024363237619\n686,2014-04-03 09:10:00,73.55355538196667\n687,2014-04-03 09:15:00,67.64356891205715\n688,2014-04-03 09:20:00,77.06996160304762\n689,2014-04-03 09:25:00,74.03227145383809\n690,2014-04-03 09:30:00,76.17989165472856\n691,2014-04-03 09:35:00,72.03319190611906\n692,2014-04-03 09:40:00,71.53709111190952\n693,2014-04-03 09:45:00,67.6918908911\n694,2014-04-03 09:50:00,73.48812673199048\n695,2014-04-03 09:55:00,73.36836039448094\n696,2014-04-03 10:00:00,82.28351515847143\n697,2014-04-03 10:05:00,86.51885692466189\n698,2014-04-03 10:10:00,87.95392066945239\n699,2014-04-03 10:15:00,86.69314861234287\n700,2014-04-03 10:20:00,77.28112966173333\n701,2014-04-03 10:25:00,84.71013739362381\n702,2014-04-03 10:30:00,76.30982888601429\n703,2014-04-03 10:35:00,85.85119266300475\n704,2014-04-03 10:40:00,81.00423801669524\n705,2014-04-03 10:45:00,77.14191951558571\n706,2014-04-03 10:50:00,88.47200549077618\n707,2014-04-03 10:55:00,84.62982608856667\n708,2014-04-03 11:00:00,82.47740303305714\n709,2014-04-03 11:05:00,77.33198268424762\n710,2014-04-03 11:10:00,85.39612045443809\n711,2014-04-03 11:15:00,91.54116294282856\n712,2014-04-03 11:20:00,86.35044390691905\n713,2014-04-03 11:25:00,92.32619073970952\n714,2014-04-03 11:30:00,79.050618585\n715,2014-04-03 11:35:00,85.92626485969049\n716,2014-04-03 11:40:00,89.58876171588095\n717,2014-04-03 11:45:00,85.26102121637143\n718,2014-04-03 11:50:00,78.3585812303619\n719,2014-04-03 11:55:00,86.18792134955238\n720,2014-04-03 12:00:00,87.04680398284286\n721,2014-04-03 12:05:00,88.92354009133334\n722,2014-04-03 12:10:00,89.4503927911238\n723,2014-04-03 12:15:00,89.6106284615143\n724,2014-04-03 12:20:00,87.90287692780475\n725,2014-04-03 12:25:00,80.75678064599524\n726,2014-04-03 12:30:00,83.77539648118571\n727,2014-04-03 12:35:00,89.72600405687619\n728,2014-04-03 12:40:00,92.56679260296666\n729,2014-04-03 12:45:00,78.59934279855713\n730,2014-04-03 12:50:00,85.90345215954763\n731,2014-04-03 12:55:00,82.34694400883808\n732,2014-04-03 13:00:00,81.03458536792857\n733,2014-04-03 13:05:00,85.52761767091906\n734,2014-04-03 13:10:00,87.13913158960952\n735,2014-04-03 13:15:00,77.6077881773\n736,2014-04-03 13:20:00,89.93921963819048\n737,2014-04-03 13:25:00,90.58131670518095\n738,2014-04-03 13:30:00,92.91825706007143\n739,2014-04-03 13:35:00,80.3708379644619\n740,2014-04-03 13:40:00,86.99923029685237\n741,2014-04-03 13:45:00,84.32048059134286\n742,2014-04-03 13:50:00,82.85951321923334\n743,2014-04-03 13:55:00,86.55895700002381\n744,2014-04-03 14:00:00,90.0497869071143\n745,2014-04-03 14:05:00,77.90852559250476\n746,2014-04-03 14:10:00,93.05679653989525\n747,2014-04-03 14:15:00,90.5120630964857\n748,2014-04-03 14:20:00,89.57990256277618\n749,2014-04-03 14:25:00,89.73507480406667\n750,2014-04-03 14:30:00,83.80157369815714\n751,2014-04-03 14:35:00,89.60969318794763\n752,2014-04-03 14:40:00,83.7798083933381\n753,2014-04-03 14:45:00,91.97784163782856\n754,2014-04-03 14:50:00,80.44208507371904\n755,2014-04-03 14:55:00,82.29143778840952\n756,2014-04-03 15:00:00,86.4456247977\n757,2014-04-03 15:05:00,82.73907681959048\n758,2014-04-03 15:10:00,84.42692051428095\n759,2014-04-03 15:15:00,85.52531762287143\n760,2014-04-03 15:20:00,91.3555927498619\n761,2014-04-03 15:25:00,86.03250687635239\n762,2014-04-03 15:30:00,83.46825356114286\n763,2014-04-03 15:35:00,81.64013270563332\n764,2014-04-03 15:40:00,84.22258549752381\n765,2014-04-03 15:45:00,85.94297153931429\n766,2014-04-03 15:50:00,89.63643667390475\n767,2014-04-03 15:55:00,79.64291586379524\n768,2014-04-03 16:00:00,81.25988767828571\n769,2014-04-03 16:05:00,83.79604054137619\n770,2014-04-03 16:10:00,83.49539183716668\n771,2014-04-03 16:15:00,84.00442627005714\n772,2014-04-03 16:20:00,90.44022523634762\n773,2014-04-03 16:25:00,82.93781034463808\n774,2014-04-03 16:30:00,85.78914579952857\n775,2014-04-03 16:35:00,87.74872416691906\n776,2014-04-03 16:40:00,81.48852095420952\n777,2014-04-03 16:45:00,89.280215876\n778,2014-04-03 16:50:00,86.54231654479048\n779,2014-04-03 16:55:00,84.94447759578095\n780,2014-04-03 17:00:00,90.76008323307143\n781,2014-04-03 17:05:00,81.7069069076619\n782,2014-04-03 17:10:00,91.94923483655238\n783,2014-04-03 17:15:00,86.80264152794284\n784,2014-04-03 17:20:00,87.58010001263334\n785,2014-04-03 17:25:00,91.8416842118238\n786,2014-04-03 17:30:00,90.92950462011429\n787,2014-04-03 17:35:00,87.48061651910476\n788,2014-04-03 17:40:00,89.91406622409525\n789,2014-04-03 17:45:00,84.80361724768571\n790,2014-04-03 17:50:00,86.63598923537619\n791,2014-04-03 17:55:00,78.87851082466668\n792,2014-04-03 18:00:00,35.26794217805714\n793,2014-04-03 18:05:00,40.008613657047626\n794,2014-04-03 18:10:00,35.0896310886381\n795,2014-04-03 18:15:00,35.79932723772857\n796,2014-04-03 18:20:00,39.81594155741905\n797,2014-04-03 18:25:00,34.73738807680952\n798,2014-04-03 18:30:00,36.544881828\n799,2014-04-03 18:35:00,38.482781638990474\n800,2014-04-03 18:40:00,38.56325425248095\n801,2014-04-03 18:45:00,39.73359355667143\n802,2014-04-03 18:50:00,38.0051837822619\n803,2014-04-03 18:55:00,38.03486819035238\n804,2014-04-03 19:00:00,29.391532951442855\n805,2014-04-03 19:05:00,28.38341970033333\n806,2014-04-03 19:10:00,28.88306262182381\n807,2014-04-03 19:15:00,30.186490784914284\n808,2014-04-03 19:20:00,27.97040407140476\n809,2014-04-03 19:25:00,27.90470435519524\n810,2014-04-03 19:30:00,26.202684091085715\n811,2014-04-03 19:35:00,28.942374585376186\n812,2014-04-03 19:40:00,26.335043698566665\n813,2014-04-03 19:45:00,28.467691147057142\n814,2014-04-03 19:50:00,29.819513690347627\n815,2014-04-03 19:55:00,28.68763325013809\n816,2014-04-03 20:00:00,25.60785806972857\n817,2014-04-03 20:05:00,27.731014642019048\n818,2014-04-03 20:10:00,25.623070138109526\n819,2014-04-03 20:15:00,86.09375\n820,2014-04-03 20:20:00,27.03280885749048\n821,2014-04-03 20:25:00,25.236935554280954\n822,2014-04-03 20:30:00,28.255499514271428\n823,2014-04-03 20:35:00,25.377348199061906\n824,2014-04-03 20:40:00,28.61630076685238\n825,2014-04-03 20:45:00,24.600336397142858\n826,2014-04-03 20:50:00,25.65706101193333\n827,2014-04-03 20:55:00,25.40390135612381\n828,2014-04-03 21:00:00,24.303356555514284\n829,2014-04-03 21:05:00,27.198087774704764\n830,2014-04-03 21:10:00,27.049012170795237\n831,2014-04-03 21:15:00,27.454052658185716\n832,2014-04-03 21:20:00,25.308598941676188\n833,2014-04-03 21:25:00,26.070188521566664\n834,2014-04-03 21:30:00,26.94086615825714\n835,2014-04-03 21:35:00,26.066715141347622\n836,2014-04-03 21:40:00,27.109329780238095\n837,2014-04-03 21:45:00,26.862144444128567\n838,2014-04-03 21:50:00,24.782311452119046\n839,2014-04-03 21:55:00,27.468127984109522\n840,2014-04-03 22:00:00,27.1527528233\n841,2014-04-03 22:05:00,26.900576420590475\n842,2014-04-03 22:10:00,24.903130927780953\n843,2014-04-03 22:15:00,25.362616320771426\n844,2014-04-03 22:20:00,25.871259821261905\n845,2014-04-03 22:25:00,25.42527578795238\n846,2014-04-03 22:30:00,25.22403880204286\n847,2014-04-03 22:35:00,27.54388657703333\n848,2014-04-03 22:40:00,26.88218359672381\n849,2014-04-03 22:45:00,26.598304214914286\n850,2014-04-03 22:50:00,25.246363254404763\n851,2014-04-03 22:55:00,28.024956890495236\n852,2014-04-03 23:00:00,25.107620697385713\n853,2014-04-03 23:05:00,27.53059644197619\n854,2014-04-03 23:10:00,28.225055735966663\n855,2014-04-03 23:15:00,27.273992464957143\n856,2014-04-03 23:20:00,28.344701233147617\n857,2014-04-03 23:25:00,26.984648568338095\n858,2014-04-03 23:30:00,25.257392953528573\n859,2014-04-03 23:35:00,25.21025955401905\n860,2014-04-03 23:40:00,25.70077192430952\n861,2014-04-03 23:45:00,24.438231555\n862,2014-04-03 23:50:00,27.14446389889048\n863,2014-04-03 23:55:00,25.49946442588095\n864,2014-04-04 00:00:00,27.689304357771427\n865,2014-04-04 00:05:00,25.872702506961904\n866,2014-04-04 00:10:00,26.36327835485238\n867,2014-04-04 00:15:00,28.313648523342856\n868,2014-04-04 00:20:00,25.427021825533334\n869,2014-04-04 00:25:00,27.35079019922381\n870,2014-04-04 00:30:00,27.493685442914284\n871,2014-04-04 00:35:00,25.364647392004763\n872,2014-04-04 00:40:00,26.49208258449524\n873,2014-04-04 00:45:00,25.89634341558571\n874,2014-04-04 00:50:00,27.59060116407619\n875,2014-04-04 00:55:00,27.000349942766668\n876,2014-04-04 01:00:00,26.421789362257144\n877,2014-04-04 01:05:00,27.64275067924762\n878,2014-04-04 01:10:00,25.473360375238094\n879,2014-04-04 01:15:00,27.55466609372857\n880,2014-04-04 01:20:00,28.009116296019048\n881,2014-04-04 01:25:00,28.06954591100952\n882,2014-04-04 01:30:00,27.6971943721\n883,2014-04-04 01:35:00,26.201997144190475\n884,2014-04-04 01:40:00,28.504613043280955\n885,2014-04-04 01:45:00,26.103196003871428\n886,2014-04-04 01:50:00,27.146763501161907\n887,2014-04-04 01:55:00,25.24399909325238\n888,2014-04-04 02:00:00,28.528938451642855\n889,2014-04-04 02:05:00,27.43052702083333\n890,2014-04-04 02:10:00,27.635533990523808\n891,2014-04-04 02:15:00,24.892571099314285\n892,2014-04-04 02:20:00,27.690576018804762\n893,2014-04-04 02:25:00,27.74323895499524\n894,2014-04-04 02:30:00,27.338876619685713\n895,2014-04-04 02:35:00,25.82686464567619\n896,2014-04-04 02:40:00,26.625426835266666\n897,2014-04-04 02:45:00,25.115844628057143\n898,2014-04-04 02:50:00,26.567895884847616\n899,2014-04-04 02:55:00,25.664283505638096\n900,2014-04-04 03:00:00,26.092816517428567\n901,2014-04-04 03:05:00,25.354270681219045\n902,2014-04-04 03:10:00,25.63152699480952\n903,2014-04-04 03:15:00,25.0250245673\n904,2014-04-04 03:20:00,28.405795941890478\n905,2014-04-04 03:25:00,26.855273704280954\n906,2014-04-04 03:30:00,26.328039313671425\n907,2014-04-04 03:35:00,26.888628755861905\n908,2014-04-04 03:40:00,27.26912529485238\n909,2014-04-04 03:45:00,28.450908030642857\n910,2014-04-04 03:50:00,25.485605142433332\n911,2014-04-04 03:55:00,25.96048380402381\n912,2014-04-04 04:00:00,28.688871631114285\n913,2014-04-04 04:05:00,26.277926708504765\n914,2014-04-04 04:10:00,24.890841841095238\n915,2014-04-04 04:15:00,25.39860968478571\n916,2014-04-04 04:20:00,24.92083099747619\n917,2014-04-04 04:25:00,28.782609236366667\n918,2014-04-04 04:30:00,25.94584053885714\n919,2014-04-04 04:35:00,28.53196864674762\n920,2014-04-04 04:40:00,28.828783198238096\n921,2014-04-04 04:45:00,27.252043456028574\n922,2014-04-04 04:50:00,24.992904307919048\n923,2014-04-04 04:55:00,25.193926045309524\n924,2014-04-04 05:00:00,26.8013562204\n925,2014-04-04 05:05:00,26.507128527790474\n926,2014-04-04 05:10:00,27.31459017548095\n927,2014-04-04 05:15:00,26.65271266737143\n928,2014-04-04 05:20:00,28.641069301861904\n929,2014-04-04 05:25:00,27.05116124265238\n930,2014-04-04 05:30:00,27.694547102942856\n931,2014-04-04 05:35:00,28.51302442393333\n932,2014-04-04 05:40:00,25.52201131282381\n933,2014-04-04 05:45:00,25.860902902214285\n934,2014-04-04 05:50:00,25.378679403804764\n935,2014-04-04 05:55:00,25.51539883499524\n936,2014-04-04 06:00:00,27.014621581985715\n937,2014-04-04 06:05:00,26.256443226376188\n938,2014-04-04 06:10:00,26.671858024766664\n939,2014-04-04 06:15:00,28.91656647005714\n940,2014-04-04 06:20:00,25.62086501024762\n941,2014-04-04 06:25:00,27.164736378438093\n942,2014-04-04 06:30:00,25.40441319162857\n943,2014-04-04 06:35:00,26.29035430071905\n944,2014-04-04 06:40:00,27.133913218509527\n945,2014-04-04 06:45:00,28.8177769839\n946,2014-04-04 06:50:00,26.603603361290475\n947,2014-04-04 06:55:00,25.305757737280953\n948,2014-04-04 07:00:00,26.606217220371427\n949,2014-04-04 07:05:00,25.643976608261905\n950,2014-04-04 07:10:00,25.98841083415238\n951,2014-04-04 07:15:00,27.548255349842858\n952,2014-04-04 07:20:00,25.353028798133334\n953,2014-04-04 07:25:00,26.94966883452381\n954,2014-04-04 07:30:00,27.536060629714285\n955,2014-04-04 07:35:00,26.793088331404764\n956,2014-04-04 07:40:00,25.189600640595238\n957,2014-04-04 07:45:00,29.062613141885713\n958,2014-04-04 07:50:00,26.596439259876192\n959,2014-04-04 07:55:00,28.249725414366665\n960,2014-04-04 08:00:00,26.44544311155714\n961,2014-04-04 08:05:00,27.050364647047616\n962,2014-04-04 08:10:00,26.711592665638094\n963,2014-04-04 08:15:00,26.53533548942857\n964,2014-04-04 08:20:00,25.260024556419047\n965,2014-04-04 08:25:00,26.62014327520952\n966,2014-04-04 08:30:00,28.745459961599998\n967,2014-04-04 08:35:00,27.956513830590474\n968,2014-04-04 08:40:00,25.784072388780952\n969,2014-04-04 08:45:00,27.574441447071425\n970,2014-04-04 08:50:00,28.786185344561904\n971,2014-04-04 08:55:00,28.02483854485238\n972,2014-04-04 09:00:00,70.45425059324286\n973,2014-04-04 09:05:00,80.24210528893333\n974,2014-04-04 09:10:00,72.5480223902238\n975,2014-04-04 09:15:00,74.6298998483143\n976,2014-04-04 09:20:00,75.61744629370476\n977,2014-04-04 09:25:00,80.03623505759523\n978,2014-04-04 09:30:00,81.14664764828571\n979,2014-04-04 09:35:00,81.12750532847619\n980,2014-04-04 09:40:00,68.59984353206667\n981,2014-04-04 09:45:00,81.03679054685713\n982,2014-04-04 09:50:00,69.24621035664762\n983,2014-04-04 09:55:00,72.1285098279381\n984,2014-04-04 10:00:00,85.15404007682857\n985,2014-04-04 10:05:00,84.61731574091905\n986,2014-04-04 10:10:00,86.56140552490952\n987,2014-04-04 10:15:00,84.62475547\n988,2014-04-04 10:20:00,91.69270102419048\n989,2014-04-04 10:25:00,80.93194907668095\n990,2014-04-04 10:30:00,81.45893468007142\n991,2014-04-04 10:35:00,91.5033646667619\n992,2014-04-04 10:40:00,78.41194963425238\n993,2014-04-04 10:45:00,86.68877681314287\n994,2014-04-04 10:50:00,87.81637530943333\n995,2014-04-04 10:55:00,85.08928135712381\n996,2014-04-04 11:00:00,90.0197780865143\n997,2014-04-04 11:05:00,81.73364465210476\n998,2014-04-04 11:10:00,92.55385826809524\n999,2014-04-04 11:15:00,81.2280042795857\n1000,2014-04-04 11:20:00,85.38299730487618\n1001,2014-04-04 11:25:00,80.21281355786667\n1002,2014-04-04 11:30:00,87.69439414035713\n1003,2014-04-04 11:35:00,89.68243494034762\n1004,2014-04-04 11:40:00,94.00742697983807\n1005,2014-04-04 11:45:00,90.80408143092856\n1006,2014-04-04 11:50:00,87.65881983091903\n1007,2014-04-04 11:55:00,93.89290056490952\n1008,2014-04-04 12:00:00,87.0594034214\n1009,2014-04-04 12:05:00,88.38955577719048\n1010,2014-04-04 12:10:00,88.95461230338096\n1011,2014-04-04 12:15:00,85.98772543197143\n1012,2014-04-04 12:20:00,92.8429860861619\n1013,2014-04-04 12:25:00,82.41006202445239\n1014,2014-04-04 12:30:00,88.32506493304287\n1015,2014-04-04 12:35:00,91.00754855383333\n1016,2014-04-04 12:40:00,93.91938621702381\n1017,2014-04-04 12:45:00,93.60628739541428\n1018,2014-04-04 12:50:00,87.61808157920476\n1019,2014-04-04 12:55:00,89.77367975689526\n1020,2014-04-04 13:00:00,85.87829561948571\n1021,2014-04-04 13:05:00,87.06849259397619\n1022,2014-04-04 13:10:00,94.08365928716667\n1023,2014-04-04 13:15:00,94.48201713055714\n1024,2014-04-04 13:20:00,93.92495415814761\n1025,2014-04-04 13:25:00,81.8226105401381\n1026,2014-04-04 13:30:00,93.21472859002857\n1027,2014-04-04 13:35:00,94.79426702721904\n1028,2014-04-04 13:40:00,85.41013743820952\n1029,2014-04-04 13:45:00,87.935319029\n1030,2014-04-04 13:50:00,92.10894284339048\n1031,2014-04-04 13:55:00,88.64494277338095\n1032,2014-04-04 14:00:00,95.57008878057144\n1033,2014-04-04 14:05:00,86.9736197593619\n1034,2014-04-04 14:10:00,91.11253145225238\n1035,2014-04-04 14:15:00,92.37828639024286\n1036,2014-04-04 14:20:00,87.61010451633334\n1037,2014-04-04 14:25:00,93.4234005373238\n1038,2014-04-04 14:30:00,88.4578122983143\n1039,2014-04-04 14:35:00,86.31329536290477\n1040,2014-04-04 14:40:00,81.45973521109524\n1041,2014-04-04 14:45:00,86.03639479428571\n1042,2014-04-04 14:50:00,91.49193980297619\n1043,2014-04-04 14:55:00,94.49683570556667\n1044,2014-04-04 15:00:00,83.79399774665714\n1045,2014-04-04 15:05:00,85.45832013214762\n1046,2014-04-04 15:10:00,82.24539915253808\n1047,2014-04-04 15:15:00,90.84094758402857\n1048,2014-04-04 15:20:00,95.15979524281906\n1049,2014-04-04 15:25:00,90.05950539110951\n1050,2014-04-04 15:30:00,89.6849384971\n1051,2014-04-04 15:35:00,88.67500314819048\n1052,2014-04-04 15:40:00,81.24196801658096\n1053,2014-04-04 15:45:00,91.50607939967142\n1054,2014-04-04 15:50:00,89.47427092676189\n1055,2014-04-04 15:55:00,90.43253787985239\n1056,2014-04-04 16:00:00,94.23795449414287\n1057,2014-04-04 16:05:00,92.40779360303333\n1058,2014-04-04 16:10:00,92.3665056143238\n1059,2014-04-04 16:15:00,94.71423786471429\n1060,2014-04-04 16:20:00,95.72569533450476\n1061,2014-04-04 16:25:00,89.19471285249524\n1062,2014-04-04 16:30:00,81.6437499859857\n1063,2014-04-04 16:35:00,87.2551523703762\n1064,2014-04-04 16:40:00,92.51812257496667\n1065,2014-04-04 16:45:00,80.36757324735714\n1066,2014-04-04 16:50:00,80.84160664514762\n1067,2014-04-04 16:55:00,81.01337231023808\n1068,2014-04-04 17:00:00,91.64296856522857\n1069,2014-04-04 17:05:00,87.97250437741904\n1070,2014-04-04 17:10:00,85.86364670560953\n1071,2014-04-04 17:15:00,81.6585944273\n1072,2014-04-04 17:20:00,91.69200233259049\n1073,2014-04-04 17:25:00,85.11991830088095\n1074,2014-04-04 17:30:00,84.23622727147144\n1075,2014-04-04 17:35:00,90.4355874737619\n1076,2014-04-04 17:40:00,88.95009557995238\n1077,2014-04-04 17:45:00,85.81193325154285\n1078,2014-04-04 17:50:00,90.28460127693333\n1079,2014-04-04 17:55:00,84.36778882132381\n1080,2014-04-04 18:00:00,41.922621453714285\n1081,2014-04-04 18:05:00,38.31079023250476\n1082,2014-04-04 18:10:00,37.86715076379524\n1083,2014-04-04 18:15:00,41.865641443985716\n1084,2014-04-04 18:20:00,41.39597878747619\n1085,2014-04-04 18:25:00,38.041800357166665\n1086,2014-04-04 18:30:00,37.624324287657146\n1087,2014-04-04 18:35:00,42.25354522554762\n1088,2014-04-04 18:40:00,41.865461897438095\n1089,2014-04-04 18:45:00,38.99711983132857\n1090,2014-04-04 18:50:00,41.12257612181905\n1091,2014-04-04 18:55:00,37.71217903550952\n1092,2014-04-04 19:00:00,30.556572281999998\n1093,2014-04-04 19:05:00,28.37635107409048\n1094,2014-04-04 19:10:00,30.054256176780953\n1095,2014-04-04 19:15:00,28.642616144471425\n1096,2014-04-04 19:20:00,30.443420049161904\n1097,2014-04-04 19:25:00,30.211334949252382\n1098,2014-04-04 19:30:00,30.320486561342854\n1099,2014-04-04 19:35:00,28.540166449433332\n1100,2014-04-04 19:40:00,29.964563823723807\n1101,2014-04-04 19:45:00,31.741010637814284\n1102,2014-04-04 19:50:00,30.012139957904758\n1103,2014-04-04 19:55:00,31.570814304095236\n1104,2014-04-04 20:00:00,28.15967032698571\n1105,2014-04-04 20:05:00,28.38731470087619\n1106,2014-04-04 20:10:00,28.97086851186667\n1107,2014-04-04 20:15:00,30.562600088057142\n1108,2014-04-04 20:20:00,27.121939781947617\n1109,2014-04-04 20:25:00,26.818302668838093\n1110,2014-04-04 20:30:00,29.18112094522857\n1111,2014-04-04 20:35:00,30.585870456019048\n1112,2014-04-04 20:40:00,30.759715204909526\n1113,2014-04-04 20:45:00,28.696386512300002\n1114,2014-04-04 20:50:00,28.637952551990473\n1115,2014-04-04 20:55:00,29.369902304480952\n1116,2014-04-04 21:00:00,28.62317859507143\n1117,2014-04-04 21:05:00,28.945938575461906\n1118,2014-04-04 21:10:00,29.91763081925238\n1119,2014-04-04 21:15:00,29.41184656194286\n1120,2014-04-04 21:20:00,28.416782896833332\n1121,2014-04-04 21:25:00,28.28349939432381\n1122,2014-04-04 21:30:00,29.005301582814287\n1123,2014-04-04 21:35:00,28.273629411504764\n1124,2014-04-04 21:40:00,28.28940195799524\n1125,2014-04-04 21:45:00,26.522472350385712\n1126,2014-04-04 21:50:00,27.16397472557619\n1127,2014-04-04 21:55:00,28.435250639466666\n1128,2014-04-04 22:00:00,29.703909957857142\n1129,2014-04-04 22:05:00,27.533555948247617\n1130,2014-04-04 22:10:00,28.517598768638095\n1131,2014-04-04 22:15:00,27.81363155532857\n1132,2014-04-04 22:20:00,26.859517444019048\n1133,2014-04-04 22:25:00,30.284213311509525\n1134,2014-04-04 22:30:00,29.8767574181\n1135,2014-04-04 22:35:00,26.776491575990477\n1136,2014-04-04 22:40:00,29.351573975080953\n1137,2014-04-04 22:45:00,27.86875574327143\n1138,2014-04-04 22:50:00,30.467761345461906\n1139,2014-04-04 22:55:00,27.70273766115238\n1140,2014-04-04 23:00:00,27.440735987842857\n1141,2014-04-04 23:05:00,28.76503766453333\n1142,2014-04-04 23:10:00,29.84162583772381\n1143,2014-04-04 23:15:00,27.278143625614284\n1144,2014-04-04 23:20:00,29.35351666010476\n1145,2014-04-04 23:25:00,26.768474729095235\n1146,2014-04-04 23:30:00,30.20668642648571\n1147,2014-04-04 23:35:00,26.86204411877619\n1148,2014-04-04 23:40:00,30.202750299566667\n1149,2014-04-04 23:45:00,28.516169078657143\n1150,2014-04-04 23:50:00,28.352712202247616\n1151,2014-04-04 23:55:00,30.461419910938098\n1152,2014-04-05 00:00:00,30.532965282228574\n1153,2014-04-05 00:05:00,29.179581551419048\n1154,2014-04-05 00:10:00,27.09478669120952\n1155,2014-04-05 00:15:00,28.6184303426\n1156,2014-04-05 00:20:00,28.717842879990478\n1157,2014-04-05 00:25:00,28.666416664880952\n1158,2014-04-05 00:30:00,28.89403878267143\n1159,2014-04-05 00:35:00,26.698410759961906\n1160,2014-04-05 00:40:00,29.47586150685238\n1161,2014-04-05 00:45:00,29.487970064942857\n1162,2014-04-05 00:50:00,27.10771243403333\n1163,2014-04-05 00:55:00,28.934231579323807\n1164,2014-04-05 01:00:00,28.934159015414284\n1165,2014-04-05 01:05:00,29.39795644270476\n1166,2014-04-05 01:10:00,27.017186006595235\n1167,2014-04-05 01:15:00,29.189048943385714\n1168,2014-04-05 01:20:00,27.81348399347619\n1169,2014-04-05 01:25:00,28.725928628666665\n1170,2014-04-05 01:30:00,29.798651353657142\n1171,2014-04-05 01:35:00,29.535381364547618\n1172,2014-04-05 01:40:00,27.195850165938094\n1173,2014-04-05 01:45:00,29.09241771992857\n1174,2014-04-05 01:50:00,30.611585171419048\n1175,2014-04-05 01:55:00,27.369637273109525\n1176,2014-04-05 02:00:00,30.1616283509\n1177,2014-04-05 02:05:00,29.567632798390477\n1178,2014-04-05 02:10:00,29.860894203980955\n1179,2014-04-05 02:15:00,27.900154737171427\n1180,2014-04-05 02:20:00,27.931317622261904\n1181,2014-04-05 02:25:00,30.411280204052378\n1182,2014-04-05 02:30:00,28.233970985542854\n1183,2014-04-05 02:35:00,27.05414489613333\n1184,2014-04-05 02:40:00,29.21191062382381\n1185,2014-04-05 02:45:00,27.316234961914283\n1186,2014-04-05 02:50:00,30.010789727504758\n1187,2014-04-05 02:55:00,29.398831008095236\n1188,2014-04-05 03:00:00,30.338191735185717\n1189,2014-04-05 03:05:00,29.98607518957619\n1190,2014-04-05 03:10:00,27.302621260066665\n1191,2014-04-05 03:15:00,28.38588984855714\n1192,2014-04-05 03:20:00,29.967288618747617\n1193,2014-04-05 03:25:00,28.545853988338095\n1194,2014-04-05 03:30:00,30.77339051052857\n1195,2014-04-05 03:35:00,29.834330847219046\n1196,2014-04-05 03:40:00,26.960809190609524\n1197,2014-04-05 03:45:00,30.4261927662\n1198,2014-04-05 03:50:00,27.316909615690477\n1199,2014-04-05 03:55:00,27.483225849080952\n1200,2014-04-05 04:00:00,29.866541030971426\n1201,2014-04-05 04:05:00,30.395886142461904\n1202,2014-04-05 04:10:00,29.08885089255238\n1203,2014-04-05 04:15:00,28.10709178894286\n1204,2014-04-05 04:20:00,28.36359551433333\n1205,2014-04-05 04:25:00,28.33733112792381\n1206,2014-04-05 04:30:00,28.279926700914285\n1207,2014-04-05 04:35:00,27.95229344920476\n1208,2014-04-05 04:40:00,29.423563616595235\n1209,2014-04-05 04:45:00,30.59715698858571\n1210,2014-04-05 04:50:00,28.23130584277619\n1211,2014-04-05 04:55:00,27.757193856466664\n1212,2014-04-05 05:00:00,30.37216780835714\n1213,2014-04-05 05:05:00,29.992430942647616\n1214,2014-04-05 05:10:00,30.756086221438093\n1215,2014-04-05 05:15:00,27.70225751382857\n1216,2014-04-05 05:20:00,27.62462430411905\n1217,2014-04-05 05:25:00,29.220777101009524\n1218,2014-04-05 05:30:00,29.520234619300002\n1219,2014-04-05 05:35:00,28.990634243590478\n1220,2014-04-05 05:40:00,29.47324749768095\n1221,2014-04-05 05:45:00,27.80634050407143\n1222,2014-04-05 05:50:00,29.010716921461906\n1223,2014-04-05 05:55:00,29.73207262475238\n1224,2014-04-05 06:00:00,28.837968654142855\n1225,2014-04-05 06:05:00,29.83237267663333\n1226,2014-04-05 06:10:00,28.926788931723806\n1227,2014-04-05 06:15:00,28.463862609114283\n1228,2014-04-05 06:20:00,28.351324950204763\n1229,2014-04-05 06:25:00,28.787953474095236\n1230,2014-04-05 06:30:00,27.244144204985716\n1231,2014-04-05 06:35:00,29.833326744276192\n1232,2014-04-05 06:40:00,30.54708923056667\n1233,2014-04-05 06:45:00,28.59261552065714\n1234,2014-04-05 06:50:00,27.365680163647617\n1235,2014-04-05 06:55:00,31.136090484738094\n1236,2014-04-05 07:00:00,28.25122159322857\n1237,2014-04-05 07:05:00,27.71035353441905\n1238,2014-04-05 07:10:00,28.69031955570952\n1239,2014-04-05 07:15:00,30.1729781625\n1240,2014-04-05 07:20:00,28.401856863790478\n1241,2014-04-05 07:25:00,29.532443768080952\n1242,2014-04-05 07:30:00,28.903311406271428\n1243,2014-04-05 07:35:00,27.719567873861905\n1244,2014-04-05 07:40:00,28.57710043095238\n1245,2014-04-05 07:45:00,30.162874880042857\n1246,2014-04-05 07:50:00,29.718848922633335\n1247,2014-04-05 07:55:00,27.757387329023807\n1248,2014-04-05 08:00:00,27.939003924614287\n1249,2014-04-05 08:05:00,29.85608819910476\n1250,2014-04-05 08:10:00,30.554256895395238\n1251,2014-04-05 08:15:00,28.705933698085715\n1252,2014-04-05 08:20:00,29.696719197876188\n1253,2014-04-05 08:25:00,28.005491021666664\n1254,2014-04-05 08:30:00,28.57586249045714\n1255,2014-04-05 08:35:00,27.418878441747616\n1256,2014-04-05 08:40:00,30.418341886438093\n1257,2014-04-05 08:45:00,28.95671785052857\n1258,2014-04-05 08:50:00,30.624621342219047\n1259,2014-04-05 08:55:00,30.201051507909526\n1260,2014-04-05 09:00:00,81.84592201390001\n1261,2014-04-05 09:05:00,74.46739838249049\n1262,2014-04-05 09:10:00,73.10735968618096\n1263,2014-04-05 09:15:00,83.81523871267143\n1264,2014-04-05 09:20:00,80.36041980856191\n1265,2014-04-05 09:25:00,81.95517722475238\n1266,2014-04-05 09:30:00,70.79825673964285\n1267,2014-04-05 09:35:00,75.44776136933334\n1268,2014-04-05 09:40:00,80.7368308014238\n1269,2014-04-05 09:45:00,71.70253081441427\n1270,2014-04-05 09:50:00,78.36522780400476\n1271,2014-04-05 09:55:00,76.49223487549524\n1272,2014-04-05 10:00:00,79.57769390508571\n1273,2014-04-05 10:05:00,82.97406714737619\n1274,2014-04-05 10:10:00,83.73913833696668\n1275,2014-04-05 10:15:00,81.06267351015714\n1276,2014-04-05 10:20:00,89.13550045824762\n1277,2014-04-05 10:25:00,83.10350313463809\n1278,2014-04-05 10:30:00,83.65758320552857\n1279,2014-04-05 10:35:00,93.29703209171905\n1280,2014-04-05 10:40:00,86.61355992240952\n1281,2014-04-05 10:45:00,85.457078841\n1282,2014-04-05 10:50:00,90.61316899079048\n1283,2014-04-05 10:55:00,93.50333707998095\n1284,2014-04-05 11:00:00,81.51974932007143\n1285,2014-04-05 11:05:00,88.2578025203619\n1286,2014-04-05 11:10:00,90.85031906805239\n1287,2014-04-05 11:15:00,86.21032036974286\n1288,2014-04-05 11:20:00,93.43570574593333\n1289,2014-04-05 11:25:00,96.60914513512381\n1290,2014-04-05 11:30:00,96.17048311851428\n1291,2014-04-05 11:35:00,85.40384106820476\n1292,2014-04-05 11:40:00,84.78077921839524\n1293,2014-04-05 11:45:00,96.41646511968571\n1294,2014-04-05 11:50:00,88.49000365457618\n1295,2014-04-05 11:55:00,84.51618365456667\n1296,2014-04-05 12:00:00,92.85483421925714\n1297,2014-04-05 12:05:00,86.10916193124763\n1298,2014-04-05 12:10:00,85.8421585544381\n1299,2014-04-05 12:15:00,95.62988167902857\n1300,2014-04-05 12:20:00,84.18276590191905\n1301,2014-04-05 12:25:00,82.62271032270952\n1302,2014-04-05 12:30:00,85.9029146631\n1303,2014-04-05 12:35:00,91.30801372969049\n1304,2014-04-05 12:40:00,83.58302332008095\n1305,2014-04-05 12:45:00,89.15988156727143\n1306,2014-04-05 12:50:00,91.65621079906191\n1307,2014-04-05 12:55:00,95.20179851215238\n1308,2014-04-05 13:00:00,85.39189361714286\n1309,2014-04-05 13:05:00,94.79670589753333\n1310,2014-04-05 13:10:00,85.48734194762382\n1311,2014-04-05 13:15:00,92.56285016201431\n1312,2014-04-05 13:20:00,88.63374811910477\n1313,2014-04-05 13:25:00,83.58652474019524\n1314,2014-04-05 13:30:00,93.18497834778572\n1315,2014-04-05 13:35:00,85.25031187877619\n1316,2014-04-05 13:40:00,84.59968324906667\n1317,2014-04-05 13:45:00,87.51361804025714\n1318,2014-04-05 13:50:00,92.23940290064762\n1319,2014-04-05 13:55:00,85.53975320943809\n1320,2014-04-05 14:00:00,84.75641613982857\n1321,2014-04-05 14:05:00,81.98466341461905\n1322,2014-04-05 14:10:00,89.37878085550952\n1323,2014-04-05 14:15:00,88.6982939092\n1324,2014-04-05 14:20:00,85.58943876399047\n1325,2014-04-05 14:25:00,82.71356837168095\n1326,2014-04-05 14:30:00,88.73037975357143\n1327,2014-04-05 14:35:00,94.4807323403619\n1328,2014-04-05 14:40:00,93.32146114555238\n1329,2014-04-05 14:45:00,95.65699400444285\n1330,2014-04-05 14:50:00,82.04569297723333\n1331,2014-04-05 14:55:00,97.3617846683238\n1332,2014-04-05 15:00:00,87.37256668681428\n1333,2014-04-05 15:05:00,97.76367617430476\n1334,2014-04-05 15:10:00,85.96677660539524\n1335,2014-04-05 15:15:00,89.47685428758571\n1336,2014-04-05 15:20:00,87.60257345237619\n1337,2014-04-05 15:25:00,87.63934226176667\n1338,2014-04-05 15:30:00,95.43105014825714\n1339,2014-04-05 15:35:00,93.90469480484762\n1340,2014-04-05 15:40:00,97.8438174644381\n1341,2014-04-05 15:45:00,91.79312805902858\n1342,2014-04-05 15:50:00,89.39646236171905\n1343,2014-04-05 15:55:00,83.43303629560953\n1344,2014-04-05 16:00:00,97.94481385790002\n1345,2014-04-05 16:05:00,90.83177574009048\n1346,2014-04-05 16:10:00,93.22236070878095\n1347,2014-04-05 16:15:00,88.53004888847143\n1348,2014-04-05 16:20:00,90.79305816976189\n1349,2014-04-05 16:25:00,97.1182788952524\n1350,2014-04-05 16:30:00,84.70721051164286\n1351,2014-04-05 16:35:00,86.72989746093333\n1352,2014-04-05 16:40:00,84.4923365427238\n1353,2014-04-05 16:45:00,94.74225616971427\n1354,2014-04-05 16:50:00,83.06698878260475\n1355,2014-04-05 16:55:00,83.38781088799524\n1356,2014-04-05 17:00:00,86.86516203698571\n1357,2014-04-05 17:05:00,90.32370627807619\n1358,2014-04-05 17:10:00,88.60453333146667\n1359,2014-04-05 17:15:00,82.82864019025713\n1360,2014-04-05 17:20:00,97.43887901414762\n1361,2014-04-05 17:25:00,97.37236691853809\n1362,2014-04-05 17:30:00,86.60360037892858\n1363,2014-04-05 17:35:00,93.84574674941905\n1364,2014-04-05 17:40:00,91.40598490320951\n1365,2014-04-05 17:45:00,85.95584801300001\n1366,2014-04-05 17:50:00,86.35840604529048\n1367,2014-04-05 17:55:00,90.02955107568094\n1368,2014-04-05 18:00:00,41.66168180937143\n1369,2014-04-05 18:05:00,40.849873717961906\n1370,2014-04-05 18:10:00,44.16152007545238\n1371,2014-04-05 18:15:00,42.082249408842856\n1372,2014-04-05 18:20:00,43.19935459833333\n1373,2014-04-05 18:25:00,40.22711844842381\n1374,2014-04-05 18:30:00,42.437657140614284\n1375,2014-04-05 18:35:00,41.06569555800477\n1376,2014-04-05 18:40:00,42.40713616819524\n1377,2014-04-05 18:45:00,44.04281455908571\n1378,2014-04-05 18:50:00,43.97401426057619\n1379,2014-04-05 18:55:00,41.32742304126667\n1380,2014-04-05 19:00:00,33.538217350857146\n1381,2014-04-05 19:05:00,34.65227525954762\n1382,2014-04-05 19:10:00,33.245735433638096\n1383,2014-04-05 19:15:00,31.11505478182857\n1384,2014-04-05 19:20:00,33.50271243381904\n1385,2014-04-05 19:25:00,30.935030042909524\n1386,2014-04-05 19:30:00,34.3795533111\n1387,2014-04-05 19:35:00,32.794578264490475\n1388,2014-04-05 19:40:00,32.212810250480956\n1389,2014-04-05 19:45:00,30.750209852671432\n1390,2014-04-05 19:50:00,32.20817183626191\n1391,2014-04-05 19:55:00,34.55606692535238\n1392,2014-04-05 20:00:00,28.875088987742856\n1393,2014-04-05 20:05:00,30.740741943133333\n1394,2014-04-05 20:10:00,32.61804708372381\n1395,2014-04-05 20:15:00,30.428732780114284\n1396,2014-04-05 20:20:00,30.57271213550476\n1397,2014-04-05 20:25:00,31.196126974595238\n1398,2014-04-05 20:30:00,30.72997678868571\n1399,2014-04-05 20:35:00,29.53181848827619\n1400,2014-04-05 20:40:00,28.924669932566665\n1401,2014-04-05 20:45:00,31.353895442757143\n1402,2014-04-05 20:50:00,32.63517113294762\n1403,2014-04-05 20:55:00,29.306655357738094\n1404,2014-04-05 21:00:00,29.380689694328574\n1405,2014-04-05 21:05:00,30.02829534921905\n1406,2014-04-05 21:10:00,31.798206238509522\n1407,2014-04-05 21:15:00,29.6373610171\n1408,2014-04-05 21:20:00,32.10774348499048\n1409,2014-04-05 21:25:00,28.790917597380954\n1410,2014-04-05 21:30:00,32.35936422727143\n1411,2014-04-05 21:35:00,30.838666510361904\n1412,2014-04-05 21:40:00,31.24011157565238\n1413,2014-04-05 21:45:00,30.07761053824286\n1414,2014-04-05 21:50:00,31.75022471373333\n1415,2014-04-05 21:55:00,29.284136836023812\n1416,2014-04-05 22:00:00,28.748829399314285\n1417,2014-04-05 22:05:00,30.144021309804764\n1418,2014-04-05 22:10:00,31.985936274995236\n1419,2014-04-05 22:15:00,31.597921969585713\n1420,2014-04-05 22:20:00,30.65336594147619\n1421,2014-04-05 22:25:00,30.880944654266663\n1422,2014-04-05 22:30:00,29.117707227357144\n1423,2014-04-05 22:35:00,31.971031860047617\n1424,2014-04-05 22:40:00,31.763378741838096\n1425,2014-04-05 22:45:00,31.24836098312857\n1426,2014-04-05 22:50:00,30.493953356719047\n1427,2014-04-05 22:55:00,32.49638010980952\n1428,2014-04-05 23:00:00,32.1452589819\n1429,2014-04-05 23:05:00,31.214113370890473\n1430,2014-04-05 23:10:00,30.130826484480952\n1431,2014-04-05 23:15:00,31.123341182371433\n1432,2014-04-05 23:20:00,30.960423547561902\n1433,2014-04-05 23:25:00,30.24292910825238\n1434,2014-04-05 23:30:00,29.900030267642855\n1435,2014-04-05 23:35:00,30.308895084633335\n1436,2014-04-05 23:40:00,30.98406619562381\n1437,2014-04-05 23:45:00,30.408288470214284\n1438,2014-04-05 23:50:00,29.75736113800476\n1439,2014-04-05 23:55:00,31.75473892689524\n1440,2014-04-06 00:00:00,30.840155698085717\n1441,2014-04-06 00:05:00,28.99242684337619\n1442,2014-04-06 00:10:00,30.202432689166663\n1443,2014-04-06 00:15:00,32.276260971657145\n1444,2014-04-06 00:20:00,31.76499374384762\n1445,2014-04-06 00:25:00,30.044475231038096\n1446,2014-04-06 00:30:00,32.511661179628575\n1447,2014-04-06 00:35:00,29.072780681019047\n1448,2014-04-06 00:40:00,32.61874833940952\n1449,2014-04-06 00:45:00,29.7640703699\n1450,2014-04-06 00:50:00,28.825067197390474\n1451,2014-04-06 00:55:00,30.531363098480952\n1452,2014-04-06 01:00:00,30.239453147271426\n1453,2014-04-06 01:05:00,30.967367925561902\n1454,2014-04-06 01:10:00,32.00554382325238\n1455,2014-04-06 01:15:00,32.195616065742854\n1456,2014-04-06 01:20:00,30.438253331733332\n1457,2014-04-06 01:25:00,30.56015678432381\n1458,2014-04-06 01:30:00,29.440925207014285\n1459,2014-04-06 01:35:00,29.04584519740476\n1460,2014-04-06 01:40:00,31.427955198995235\n1461,2014-04-06 01:45:00,29.128286216485712\n1462,2014-04-06 01:50:00,31.81329666817619\n1463,2014-04-06 01:55:00,31.041777246766664\n1464,2014-04-06 02:00:00,29.68718905575714\n1465,2014-04-06 02:05:00,31.05838939314762\n1466,2014-04-06 02:10:00,29.639728961638095\n1467,2014-04-06 02:15:00,30.670127401428573\n1468,2014-04-06 02:20:00,32.120860312619044\n1469,2014-04-06 02:25:00,30.777736697409523\n1470,2014-04-06 02:30:00,29.5322972732\n1471,2014-04-06 02:35:00,31.84025520349048\n1472,2014-04-06 02:40:00,29.699454617480953\n1473,2014-04-06 02:45:00,31.91402092607143\n1474,2014-04-06 02:50:00,30.884671061661905\n1475,2014-04-06 02:55:00,30.789669417352382\n1476,2014-04-06 03:00:00,32.38788300854286\n1477,2014-04-06 03:05:00,31.823997430733332\n1478,2014-04-06 03:10:00,29.128666997323805\n1479,2014-04-06 03:15:00,30.189161544114285\n1480,2014-04-06 03:20:00,32.49558740530476\n1481,2014-04-06 03:25:00,29.092649912295236\n1482,2014-04-06 03:30:00,31.207799499285713\n1483,2014-04-06 03:35:00,31.94552886717619\n1484,2014-04-06 03:40:00,31.529091008566667\n1485,2014-04-06 03:45:00,32.09123595125714\n1486,2014-04-06 03:50:00,31.959315014747617\n1487,2014-04-06 03:55:00,31.832110875838094\n1488,2014-04-06 04:00:00,32.35758801512857\n1489,2014-04-06 04:05:00,31.66163172141905\n1490,2014-04-06 04:10:00,30.695983500809525\n1491,2014-04-06 04:15:00,30.9813864397\n1492,2014-04-06 04:20:00,31.968089606890473\n1493,2014-04-06 04:25:00,32.61385507108095\n1494,2014-04-06 04:30:00,30.20494663197143\n1495,2014-04-06 04:35:00,30.491819088661906\n1496,2014-04-06 04:40:00,32.853909966352376\n1497,2014-04-06 04:45:00,31.452440026742856\n1498,2014-04-06 04:50:00,29.86168060183333\n1499,2014-04-06 04:55:00,31.80805436512381\n1500,2014-04-06 05:00:00,33.12376290791428\n1501,2014-04-06 05:05:00,32.46196901980476\n1502,2014-04-06 05:10:00,32.158559784295235\n1503,2014-04-06 05:15:00,30.015222331385715\n1504,2014-04-06 05:20:00,32.69503532917619\n1505,2014-04-06 05:25:00,31.30107204076667\n1506,2014-04-06 05:30:00,32.76251723115714\n1507,2014-04-06 05:35:00,30.53210893674762\n1508,2014-04-06 05:40:00,29.468442305738094\n1509,2014-04-06 05:45:00,31.131582446028574\n1510,2014-04-06 05:50:00,30.314469466919046\n1511,2014-04-06 05:55:00,32.10347668290952\n1512,2014-04-06 06:00:00,33.0784262114\n1513,2014-04-06 06:05:00,32.021337080790474\n1514,2014-04-06 06:10:00,32.812616671180955\n1515,2014-04-06 06:15:00,31.084417482971432\n1516,2014-04-06 06:20:00,32.366324853561906\n1517,2014-04-06 06:25:00,32.65937612765238\n1518,2014-04-06 06:30:00,32.13814536744285\n1519,2014-04-06 06:35:00,31.333192477633332\n1520,2014-04-06 06:40:00,31.812988248023807\n1521,2014-04-06 06:45:00,32.11899226841429\n1522,2014-04-06 06:50:00,30.336742374804757\n1523,2014-04-06 06:55:00,32.570162281795234\n1524,2014-04-06 07:00:00,33.140583870185715\n1525,2014-04-06 07:05:00,31.207683451176187\n1526,2014-04-06 07:10:00,32.15843539906667\n1527,2014-04-06 07:15:00,32.30971076605714\n1528,2014-04-06 07:20:00,32.01803780914762\n1529,2014-04-06 07:25:00,31.564948528538093\n1530,2014-04-06 07:30:00,32.91052038972857\n1531,2014-04-06 07:35:00,31.187075884719047\n1532,2014-04-06 07:40:00,29.64322134970952\n1533,2014-04-06 07:45:00,32.7844755028\n1534,2014-04-06 07:50:00,32.10961556549048\n1535,2014-04-06 07:55:00,32.81816545838095\n1536,2014-04-06 08:00:00,29.982761198371428\n1537,2014-04-06 08:05:00,29.559023666761902\n1538,2014-04-06 08:10:00,33.18095054245238\n1539,2014-04-06 08:15:00,30.041806080542855\n1540,2014-04-06 08:20:00,32.69694266163333\n1541,2014-04-06 08:25:00,32.75861357822381\n1542,2014-04-06 08:30:00,32.308035087914284\n1543,2014-04-06 08:35:00,30.005703606304763\n1544,2014-04-06 08:40:00,32.15768973629524\n1545,2014-04-06 08:45:00,33.051882047585714\n1546,2014-04-06 08:50:00,31.20510276967619\n1547,2014-04-06 08:55:00,31.164484084166666\n1548,2014-04-06 09:00:00,78.74073015315713\n1549,2014-04-06 09:05:00,73.84419533224761\n1550,2014-04-06 09:10:00,84.8642858340381\n1551,2014-04-06 09:15:00,84.56106552152858\n1552,2014-04-06 09:20:00,86.31918582391906\n1553,2014-04-06 09:25:00,80.71355024820951\n1554,2014-04-06 09:30:00,82.97870625569999\n1555,2014-04-06 09:35:00,75.52627840199048\n1556,2014-04-06 09:40:00,81.85577288018095\n1557,2014-04-06 09:45:00,81.62118817167143\n1558,2014-04-06 09:50:00,85.04870071216189\n1559,2014-04-06 09:55:00,84.09848341155238\n1560,2014-04-06 10:00:00,96.01214235694286\n1561,2014-04-06 10:05:00,94.93887882963332\n1562,2014-04-06 10:10:00,94.9441530583238\n1563,2014-04-06 10:15:00,82.45845031591429\n1564,2014-04-06 10:20:00,94.60623426770476\n1565,2014-04-06 10:25:00,90.91240992079524\n1566,2014-04-06 10:30:00,87.39628360568571\n1567,2014-04-06 10:35:00,82.37633316097619\n1568,2014-04-06 10:40:00,92.02416365106667\n1569,2014-04-06 10:45:00,86.60779831115714\n1570,2014-04-06 10:50:00,88.78143525164762\n1571,2014-04-06 10:55:00,92.1094134383381\n1572,2014-04-06 11:00:00,97.76529096732857\n1573,2014-04-06 11:05:00,96.39961775341905\n1574,2014-04-06 11:10:00,90.44560626510952\n1575,2014-04-06 11:15:00,89.454053336\n1576,2014-04-06 11:20:00,87.10764744279048\n1577,2014-04-06 11:25:00,89.22470600308094\n1578,2014-04-06 11:30:00,85.07515317207144\n1579,2014-04-06 11:35:00,98.7609739097619\n1580,2014-04-06 11:40:00,92.45153540965238\n1581,2014-04-06 11:45:00,85.36401698094286\n1582,2014-04-06 11:50:00,88.94986010473333\n1583,2014-04-06 11:55:00,92.0463843496238\n1584,2014-04-06 12:00:00,92.21525306771429\n1585,2014-04-06 12:05:00,84.27412699670475\n1586,2014-04-06 12:10:00,98.90939563789522\n1587,2014-04-06 12:15:00,88.12235940478571\n1588,2014-04-06 12:20:00,83.98772014777619\n1589,2014-04-06 12:25:00,84.95815308486667\n1590,2014-04-06 12:30:00,93.01593585265714\n1591,2014-04-06 12:35:00,85.95332046784762\n1592,2014-04-06 12:40:00,84.4256336648381\n1593,2014-04-06 12:45:00,89.83301320582856\n1594,2014-04-06 12:50:00,93.72594111021905\n1595,2014-04-06 12:55:00,85.56844907700952\n1596,2014-04-06 13:00:00,88.8697621355\n1597,2014-04-06 13:05:00,90.54772702119048\n1598,2014-04-06 13:10:00,86.42335019018094\n1599,2014-04-06 13:15:00,91.97528048027144\n1600,2014-04-06 13:20:00,85.2505800730619\n1601,2014-04-06 13:25:00,84.63903969145238\n1602,2014-04-06 13:30:00,92.21773256384286\n1603,2014-04-06 13:35:00,87.87520297293332\n1604,2014-04-06 13:40:00,85.44285850042381\n1605,2014-04-06 13:45:00,90.70565786121429\n1606,2014-04-06 13:50:00,98.57086245370476\n1607,2014-04-06 13:55:00,95.52386348559524\n1608,2014-04-06 14:00:00,97.01005796678571\n1609,2014-04-06 14:05:00,97.9182243806762\n1610,2014-04-06 14:10:00,99.53700755086668\n1611,2014-04-06 14:15:00,96.19451014575714\n1612,2014-04-06 14:20:00,93.72465111274762\n1613,2014-04-06 14:25:00,89.8445655330381\n1614,2014-04-06 14:30:00,86.91162485432856\n1615,2014-04-06 14:35:00,94.99894367651905\n1616,2014-04-06 14:40:00,99.93878918020951\n1617,2014-04-06 14:45:00,91.5051740224\n1618,2014-04-06 14:50:00,95.61354857989048\n1619,2014-04-06 14:55:00,91.96377392128095\n1620,2014-04-06 15:00:00,90.96374865737143\n1621,2014-04-06 15:05:00,90.62514749876189\n1622,2014-04-06 15:10:00,92.14167859755239\n1623,2014-04-06 15:15:00,89.94547589184286\n1624,2014-04-06 15:20:00,96.06290027093333\n1625,2014-04-06 15:25:00,98.07830074682379\n1626,2014-04-06 15:30:00,98.22355238081428\n1627,2014-04-06 15:35:00,87.74810800220476\n1628,2014-04-06 15:40:00,98.44681264619524\n1629,2014-04-06 15:45:00,89.58461176168571\n1630,2014-04-06 15:50:00,89.07616012857619\n1631,2014-04-06 15:55:00,95.76271075526667\n1632,2014-04-06 16:00:00,89.01785098395713\n1633,2014-04-06 16:05:00,84.99762024164762\n1634,2014-04-06 16:10:00,90.13547273463809\n1635,2014-04-06 16:15:00,95.70846777372857\n1636,2014-04-06 16:20:00,89.40380548781906\n1637,2014-04-06 16:25:00,94.25284683970952\n1638,2014-04-06 16:30:00,94.7492525893\n1639,2014-04-06 16:35:00,95.93455588349048\n1640,2014-04-06 16:40:00,98.55630261348095\n1641,2014-04-06 16:45:00,91.13070188847144\n1642,2014-04-06 16:50:00,86.8800317785619\n1643,2014-04-06 16:55:00,89.32736579045238\n1644,2014-04-06 17:00:00,91.14678863664285\n1645,2014-04-06 17:05:00,95.66181480843333\n1646,2014-04-06 17:10:00,84.45695008992381\n1647,2014-04-06 17:15:00,89.30700083261428\n1648,2014-04-06 17:20:00,96.73935361890476\n1649,2014-04-06 17:25:00,95.00303672159525\n1650,2014-04-06 17:30:00,95.9845931478857\n1651,2014-04-06 17:35:00,97.27316586577619\n1652,2014-04-06 17:40:00,96.82340570846668\n1653,2014-04-06 17:45:00,95.21400596195714\n1654,2014-04-06 17:50:00,91.34110178764762\n1655,2014-04-06 17:55:00,100.05152766603808\n1656,2014-04-06 18:00:00,44.76349079432857\n1657,2014-04-06 18:05:00,42.426586208819046\n1658,2014-04-06 18:10:00,43.010305907109526\n1659,2014-04-06 18:15:00,45.5825433364\n1660,2014-04-06 18:20:00,47.06951702759047\n1661,2014-04-06 18:25:00,42.30243403008095\n1662,2014-04-06 18:30:00,41.69308337057143\n1663,2014-04-06 18:35:00,46.81530399936191\n1664,2014-04-06 18:40:00,47.038724791652385\n1665,2014-04-06 18:45:00,42.957214797942854\n1666,2014-04-06 18:50:00,43.61045597613334\n1667,2014-04-06 18:55:00,45.42847065262381\n1668,2014-04-06 19:00:00,34.04879959211428\n1669,2014-04-06 19:05:00,36.50782445350476\n1670,2014-04-06 19:10:00,33.06754669389524\n1671,2014-04-06 19:15:00,32.76319494888571\n1672,2014-04-06 19:20:00,33.53449323957619\n1673,2014-04-06 19:25:00,33.88958873676667\n1674,2014-04-06 19:30:00,33.12126713815714\n1675,2014-04-06 19:35:00,32.91708962044762\n1676,2014-04-06 19:40:00,36.01535936013809\n1677,2014-04-06 19:45:00,33.373636440328575\n1678,2014-04-06 19:50:00,36.73948916891906\n1679,2014-04-06 19:55:00,34.30119681070953\n1680,2014-04-06 20:00:00,33.6788011425\n1681,2014-04-06 20:05:00,31.862687305990477\n1682,2014-04-06 20:10:00,31.931242779080954\n1683,2014-04-06 20:15:00,33.30833007407143\n1684,2014-04-06 20:20:00,33.2581550774619\n1685,2014-04-06 20:25:00,34.11791703995238\n1686,2014-04-06 20:30:00,34.08064589884285\n1687,2014-04-06 20:35:00,33.73122016323333\n1688,2014-04-06 20:40:00,32.831162364123806\n1689,2014-04-06 20:45:00,34.64702704291428\n1690,2014-04-06 20:50:00,33.55648600610476\n1691,2014-04-06 20:55:00,35.06969798519523\n1692,2014-04-06 21:00:00,33.968896834285715\n1693,2014-04-06 21:05:00,30.86121613917619\n1694,2014-04-06 21:10:00,31.979097650566665\n1695,2014-04-06 21:15:00,32.996489972657145\n1696,2014-04-06 21:20:00,33.605177934347616\n1697,2014-04-06 21:25:00,32.9248004974381\n1698,2014-04-06 21:30:00,33.87994391342857\n1699,2014-04-06 21:35:00,31.863818600119046\n1700,2014-04-06 21:40:00,31.474388794109522\n1701,2014-04-06 21:45:00,30.9593518907\n1702,2014-04-06 21:50:00,33.054353028490475\n1703,2014-04-06 21:55:00,33.525150094880956\n1704,2014-04-06 22:00:00,32.00170270247143\n1705,2014-04-06 22:05:00,33.1599847973619\n1706,2014-04-06 22:10:00,30.91956157915238\n1707,2014-04-06 22:15:00,31.115727519742855\n1708,2014-04-06 22:20:00,33.53532715043333\n1709,2014-04-06 22:25:00,32.20674600852381\n1710,2014-04-06 22:30:00,33.42840832261429\n1711,2014-04-06 22:35:00,34.07801304160476\n1712,2014-04-06 22:40:00,34.16913904759524\n1713,2014-04-06 22:45:00,31.45214741068571\n1714,2014-04-06 22:50:00,32.71726580667619\n1715,2014-04-06 22:55:00,33.71622182956666\n1716,2014-04-06 23:00:00,33.867829942957144\n1717,2014-04-06 23:05:00,33.91806017104762\n1718,2014-04-06 23:10:00,31.699038663438095\n1719,2014-04-06 23:15:00,31.563921707228573\n1720,2014-04-06 23:20:00,33.16157804831904\n1721,2014-04-06 23:25:00,33.773427866609524\n1722,2014-04-06 23:30:00,32.0927591594\n1723,2014-04-06 23:35:00,31.242297515390476\n1724,2014-04-06 23:40:00,33.698372943180956\n1725,2014-04-06 23:45:00,32.03729892017142\n1726,2014-04-06 23:50:00,31.511296566761906\n1727,2014-04-06 23:55:00,31.444165944352378\n1728,2014-04-07 00:00:00,32.11678104724285\n1729,2014-04-07 00:05:00,33.23529559703333\n1730,2014-04-07 00:10:00,32.30563276432381\n1731,2014-04-07 00:15:00,30.962111692114284\n1732,2014-04-07 00:20:00,31.274538500604763\n1733,2014-04-07 00:25:00,32.05635822689524\n1734,2014-04-07 00:30:00,33.54060364288571\n1735,2014-04-07 00:35:00,31.30328648437619\n1736,2014-04-07 00:40:00,33.15929408066667\n1737,2014-04-07 00:45:00,31.40365062615714\n1738,2014-04-07 00:50:00,31.77800892844762\n1739,2014-04-07 00:55:00,31.627742205438096\n1740,2014-04-07 01:00:00,31.215343113728572\n1741,2014-04-07 01:05:00,33.63918831711905\n1742,2014-04-07 01:10:00,32.814923713309526\n1743,2014-04-07 01:15:00,34.2929637636\n1744,2014-04-07 01:20:00,31.371753836090477\n1745,2014-04-07 01:25:00,31.562562685780946\n1746,2014-04-07 01:30:00,32.21690235397143\n1747,2014-04-07 01:35:00,34.0619758525619\n1748,2014-04-07 01:40:00,32.22898767355238\n1749,2014-04-07 01:45:00,32.64706768714286\n1750,2014-04-07 01:50:00,32.22724759853333\n1751,2014-04-07 01:55:00,31.349170976723812\n1752,2014-04-07 02:00:00,34.79344877731428\n1753,2014-04-07 02:05:00,33.23731073020476\n1754,2014-04-07 02:10:00,34.20192799079524\n1755,2014-04-07 02:15:00,33.69146408298571\n1756,2014-04-07 02:20:00,33.12249330667619\n1757,2014-04-07 02:25:00,31.431629693266665\n1758,2014-04-07 02:30:00,33.65129132395714\n1759,2014-04-07 02:35:00,31.709279042747617\n1760,2014-04-07 02:40:00,32.752770772638094\n1761,2014-04-07 02:45:00,33.61913114532857\n1762,2014-04-07 02:50:00,34.239035049519046\n1763,2014-04-07 02:55:00,33.85774022660952\n1764,2014-04-07 03:00:00,33.811134116199995\n1765,2014-04-07 03:05:00,31.728609312890477\n1766,2014-04-07 03:10:00,32.52439511268095\n1767,2014-04-07 03:15:00,31.318970519171426\n1768,2014-04-07 03:20:00,34.0326694774619\n1769,2014-04-07 03:25:00,34.97254630625238\n1770,2014-04-07 03:30:00,32.226084417842856\n1771,2014-04-07 03:35:00,31.527870169933333\n1772,2014-04-07 03:40:00,33.08680411652381\n1773,2014-04-07 03:45:00,34.61875717821428\n1774,2014-04-07 03:50:00,33.40730154300476\n1775,2014-04-07 03:55:00,31.393953838895236\n1776,2014-04-07 04:00:00,35.111374676385715\n1777,2014-04-07 04:05:00,34.536325830376185\n1778,2014-04-07 04:10:00,31.755542974866664\n1779,2014-04-07 04:15:00,34.92379816885715\n1780,2014-04-07 04:20:00,33.04680077344762\n1781,2014-04-07 04:25:00,32.7390800575381\n1782,2014-04-07 04:30:00,33.10314189352857\n1783,2014-04-07 04:35:00,34.60465687511905\n1784,2014-04-07 04:40:00,33.911728236909525\n1785,2014-04-07 04:45:00,31.5182438096\n1786,2014-04-07 04:50:00,35.11910796069048\n1787,2014-04-07 04:55:00,31.887267486280955\n1788,2014-04-07 05:00:00,34.28584323547143\n1789,2014-04-07 05:05:00,33.85555802646191\n1790,2014-04-07 05:10:00,32.06856457275238\n1791,2014-04-07 05:15:00,32.00882116164286\n1792,2014-04-07 05:20:00,34.81464370813333\n1793,2014-04-07 05:25:00,33.01955350352381\n1794,2014-04-07 05:30:00,33.966520342414285\n1795,2014-04-07 05:35:00,33.37193877730476\n1796,2014-04-07 05:40:00,34.272509306395236\n1797,2014-04-07 05:45:00,33.28750521448571\n1798,2014-04-07 05:50:00,32.52749585147619\n1799,2014-04-07 05:55:00,32.83895015066667\n1800,2014-04-07 06:00:00,34.82916792065714\n1801,2014-04-07 06:05:00,33.27243639074762\n1802,2014-04-07 06:10:00,32.2615354242381\n1803,2014-04-07 06:15:00,35.15360012372857\n1804,2014-04-07 06:20:00,34.609020873619045\n1805,2014-04-07 06:25:00,31.652724108009522\n1806,2014-04-07 06:30:00,35.4332718479\n1807,2014-04-07 06:35:00,34.22464726199048\n1808,2014-04-07 06:40:00,32.09344734858095\n1809,2014-04-07 06:45:00,32.40849215377143\n1810,2014-04-07 06:50:00,34.2370438297619\n1811,2014-04-07 06:55:00,34.59374660205238\n1812,2014-04-07 07:00:00,32.438286629742855\n1813,2014-04-07 07:05:00,32.517458748933336\n1814,2014-04-07 07:10:00,32.72550658902381\n1815,2014-04-07 07:15:00,33.896537745014285\n1816,2014-04-07 07:20:00,32.19916947510476\n1817,2014-04-07 07:25:00,31.936318033595235\n1818,2014-04-07 07:30:00,34.24224207058572\n1819,2014-04-07 07:35:00,34.65061794967619\n1820,2014-04-07 07:40:00,33.54538428436667\n1821,2014-04-07 07:45:00,33.004437983957146\n1822,2014-04-07 07:50:00,33.28471847314762\n1823,2014-04-07 07:55:00,33.117619430738095\n1824,2014-04-07 08:00:00,35.41136820442857\n1825,2014-04-07 08:05:00,34.651228668519046\n1826,2014-04-07 08:10:00,32.418658383209525\n1827,2014-04-07 08:15:00,33.1305066082\n1828,2014-04-07 08:20:00,33.77723964169048\n1829,2014-04-07 08:25:00,34.06057440068095\n1830,2014-04-07 08:30:00,33.48880701267143\n1831,2014-04-07 08:35:00,34.8640184447619\n1832,2014-04-07 08:40:00,34.70137645875238\n1833,2014-04-07 08:45:00,33.65902453164286\n1834,2014-04-07 08:50:00,35.06355088043333\n1835,2014-04-07 08:55:00,34.657631931323806\n1836,2014-04-07 09:00:00,85.4494274283143\n1837,2014-04-07 09:05:00,87.87520536220475\n1838,2014-04-07 09:10:00,78.49954563849523\n1839,2014-04-07 09:15:00,78.5230507224857\n1840,2014-04-07 09:20:00,86.98022686787618\n1841,2014-04-07 09:25:00,85.40019534466667\n1842,2014-04-07 09:30:00,87.50637650635714\n1843,2014-04-07 09:35:00,75.77136779944762\n1844,2014-04-07 09:40:00,83.45773434603808\n1845,2014-04-07 09:45:00,76.89462396992857\n1846,2014-04-07 09:50:00,81.78812094441905\n1847,2014-04-07 09:55:00,77.06071779700952\n1848,2014-04-07 10:00:00,85.5777784594\n1849,2014-04-07 10:05:00,83.78629319649048\n1850,2014-04-07 10:10:00,93.38618732058094\n1851,2014-04-07 10:15:00,89.18435243957144\n1852,2014-04-07 10:20:00,85.25228408606192\n1853,2014-04-07 10:25:00,88.63764469135238\n1854,2014-04-07 10:30:00,86.25665515644286\n1855,2014-04-07 10:35:00,98.25718711823333\n1856,2014-04-07 10:40:00,88.61599963652381\n1857,2014-04-07 10:45:00,88.83992296721428\n1858,2014-04-07 10:50:00,96.69900097470476\n1859,2014-04-07 10:55:00,93.72501465329525\n1860,2014-04-07 11:00:00,96.70185495838571\n1861,2014-04-07 11:05:00,95.5296988810762\n1862,2014-04-07 11:10:00,100.47047236656667\n1863,2014-04-07 11:15:00,88.72174836795715\n1864,2014-04-07 11:20:00,101.16672771994762\n1865,2014-04-07 11:25:00,98.66001514313808\n1866,2014-04-07 11:30:00,94.81894862492857\n1867,2014-04-07 11:35:00,95.99372736201904\n1868,2014-04-07 11:40:00,95.78573626370951\n1869,2014-04-07 11:45:00,86.4029835474\n1870,2014-04-07 11:50:00,88.94902486889049\n1871,2014-04-07 11:55:00,100.78036389988095\n1872,2014-04-07 12:00:00,94.38174249327143\n1873,2014-04-07 12:05:00,91.8960051677619\n1874,2014-04-07 12:10:00,98.03503665665238\n1875,2014-04-07 12:15:00,94.24672517594286\n1876,2014-04-07 12:20:00,86.08228495103333\n1877,2014-04-07 12:25:00,97.64503959512382\n1878,2014-04-07 12:30:00,97.58823666941427\n1879,2014-04-07 12:35:00,88.53346330040476\n1880,2014-04-07 12:40:00,101.18988877919524\n1881,2014-04-07 12:45:00,89.48736678278571\n1882,2014-04-07 12:50:00,93.23177728077619\n1883,2014-04-07 12:55:00,87.75758911636667\n1884,2014-04-07 13:00:00,95.65077764995713\n1885,2014-04-07 13:05:00,92.01379380764762\n1886,2014-04-07 13:10:00,91.6648773045381\n1887,2014-04-07 13:15:00,99.25135301572857\n1888,2014-04-07 13:20:00,86.18328973621905\n1889,2014-04-07 13:25:00,98.8018637425095\n1890,2014-04-07 13:30:00,95.18620268949999\n1891,2014-04-07 13:35:00,101.82645007359048\n1892,2014-04-07 13:40:00,95.48892902008096\n1893,2014-04-07 13:45:00,86.95339491907143\n1894,2014-04-07 13:50:00,86.8851126497619\n1895,2014-04-07 13:55:00,100.20947885545239\n1896,2014-04-07 14:00:00,99.56246713284285\n1897,2014-04-07 14:05:00,91.64510289903332\n1898,2014-04-07 14:10:00,96.00661290752382\n1899,2014-04-07 14:15:00,93.9590939924143\n1900,2014-04-07 14:20:00,101.60733086210476\n1901,2014-04-07 14:25:00,101.33953408219524\n1902,2014-04-07 14:30:00,101.8889982625857\n1903,2014-04-07 14:35:00,100.0182852479762\n1904,2014-04-07 14:40:00,100.71533758346668\n1905,2014-04-07 14:45:00,89.64694473305714\n1906,2014-04-07 14:50:00,99.47356202964762\n1907,2014-04-07 14:55:00,97.5267015042381\n1908,2014-04-07 15:00:00,101.60017362862857\n1909,2014-04-07 15:05:00,95.34327935691906\n1910,2014-04-07 15:10:00,87.57327990950951\n1911,2014-04-07 15:15:00,95.77634929850001\n1912,2014-04-07 15:20:00,97.21068866569048\n1913,2014-04-07 15:25:00,89.75804237048095\n1914,2014-04-07 15:30:00,92.54613382897143\n1915,2014-04-07 15:35:00,95.8237833994619\n1916,2014-04-07 15:40:00,92.24089551535238\n1917,2014-04-07 15:45:00,92.26180754094288\n1918,2014-04-07 15:50:00,88.39950791803334\n1919,2014-04-07 15:55:00,101.3293856800238\n1920,2014-04-07 16:00:00,98.29346314241428\n1921,2014-04-07 16:05:00,86.31291150560476\n1922,2014-04-07 16:10:00,98.55024602279525\n1923,2014-04-07 16:15:00,98.14459463028571\n1924,2014-04-07 16:20:00,86.47103301407618\n1925,2014-04-07 16:25:00,92.23643583426667\n1926,2014-04-07 16:30:00,96.03816330875713\n1927,2014-04-07 16:35:00,93.58165590024763\n1928,2014-04-07 16:40:00,98.79285385503809\n1929,2014-04-07 16:45:00,93.15986058352857\n1930,2014-04-07 16:50:00,88.82178359221905\n1931,2014-04-07 16:55:00,101.99004127670953\n1932,2014-04-07 17:00:00,90.24761074930001\n1933,2014-04-07 17:05:00,97.86548538739048\n1934,2014-04-07 17:10:00,88.68035341148095\n1935,2014-04-07 17:15:00,91.66149357967143\n1936,2014-04-07 17:20:00,93.4771732758619\n1937,2014-04-07 17:25:00,89.48788562435239\n1938,2014-04-07 17:30:00,93.61896566644286\n1939,2014-04-07 17:35:00,88.94165988763334\n1940,2014-04-07 17:40:00,95.37859735072381\n1941,2014-04-07 17:45:00,97.06134460021428\n1942,2014-04-07 17:50:00,87.44832527480476\n1943,2014-04-07 17:55:00,100.39492617519524\n1944,2014-04-07 18:00:00,44.449181621485714\n1945,2014-04-07 18:05:00,44.71403990597619\n1946,2014-04-07 18:10:00,47.511799300966665\n1947,2014-04-07 18:15:00,46.28660782405714\n1948,2014-04-07 18:20:00,46.49017331044762\n1949,2014-04-07 18:25:00,44.12167430933809\n1950,2014-04-07 18:30:00,48.46563131172857\n1951,2014-04-07 18:35:00,47.26550993481905\n1952,2014-04-07 18:40:00,44.190248905009526\n1953,2014-04-07 18:45:00,45.7248399598\n1954,2014-04-07 18:50:00,48.525307520290475\n1955,2014-04-07 18:55:00,46.98359701868095\n1956,2014-04-07 19:00:00,35.20031682647142\n1957,2014-04-07 19:05:00,36.391051872361906\n1958,2014-04-07 19:10:00,35.81572212045238\n1959,2014-04-07 19:15:00,37.054137304442854\n1960,2014-04-07 19:20:00,38.52158987753333\n1961,2014-04-07 19:25:00,36.705249360323805\n1962,2014-04-07 19:30:00,36.699585369314285\n1963,2014-04-07 19:35:00,38.82162547590476\n1964,2014-04-07 19:40:00,37.35440463859524\n1965,2014-04-07 19:45:00,37.317070540785714\n1966,2014-04-07 19:50:00,35.961331335776194\n1967,2014-04-07 19:55:00,37.518013321666665\n1968,2014-04-07 20:00:00,35.43378616795714\n1969,2014-04-07 20:05:00,34.70780100084762\n1970,2014-04-07 20:10:00,37.147626863238095\n1971,2014-04-07 20:15:00,36.70940369932857\n1972,2014-04-07 20:20:00,36.174924233719054\n1973,2014-04-07 20:25:00,35.31302680630952\n1974,2014-04-07 20:30:00,35.0120967047\n1975,2014-04-07 20:35:00,33.884279976790474\n1976,2014-04-07 20:40:00,34.38668140978095\n1977,2014-04-07 20:45:00,36.31196460547143\n1978,2014-04-07 20:50:00,35.0078173765619\n1979,2014-04-07 20:55:00,36.77047805625239\n1980,2014-04-07 21:00:00,33.413027250642855\n1981,2014-04-07 21:05:00,34.86913193243333\n1982,2014-04-07 21:10:00,35.433708236123806\n1983,2014-04-07 21:15:00,34.91818155201429\n1984,2014-04-07 21:20:00,36.422285431604756\n1985,2014-04-07 21:25:00,36.83299792649524\n1986,2014-04-07 21:30:00,33.328748327685716\n1987,2014-04-07 21:35:00,33.39294089547619\n1988,2014-04-07 21:40:00,33.401865298366666\n1989,2014-04-07 21:45:00,35.62329407645714\n1990,2014-04-07 21:50:00,34.39080733414762\n1991,2014-04-07 21:55:00,35.84772633033809\n1992,2014-04-07 22:00:00,34.46215146382857\n1993,2014-04-07 22:05:00,35.35898593271905\n1994,2014-04-07 22:10:00,35.935977790909526\n1995,2014-04-07 22:15:00,35.0559987818\n1996,2014-04-07 22:20:00,35.02855652189047\n1997,2014-04-07 22:25:00,33.22918706428095\n1998,2014-04-07 22:30:00,34.52805579247143\n1999,2014-04-07 22:35:00,35.07599629196191\n2000,2014-04-07 22:40:00,34.74792968025238\n2001,2014-04-07 22:45:00,36.51225985014286\n2002,2014-04-07 22:50:00,36.54271692883333\n2003,2014-04-07 22:55:00,36.21137948412381\n2004,2014-04-07 23:00:00,34.41565081421429\n2005,2014-04-07 23:05:00,35.79135825230476\n2006,2014-04-07 23:10:00,34.51050866199524\n2007,2014-04-07 23:15:00,33.86704474018571\n2008,2014-04-07 23:20:00,34.31580611197619\n2009,2014-04-07 23:25:00,33.23528569886667\n2010,2014-04-07 23:30:00,34.28617798205714\n2011,2014-04-07 23:35:00,34.80957633614762\n2012,2014-04-07 23:40:00,36.796351481538096\n2013,2014-04-07 23:45:00,34.23501761372857\n2014,2014-04-07 23:50:00,36.59908228661905\n2015,2014-04-07 23:55:00,33.91162438840952\n2016,2014-04-08 00:00:00,33.763875591\n2017,2014-04-08 00:05:00,35.08342230189047\n2018,2014-04-08 00:10:00,35.70492642958095\n2019,2014-04-08 00:15:00,33.19965043177143\n2020,2014-04-08 00:20:00,33.9140253649619\n2021,2014-04-08 00:25:00,34.85993704695238\n2022,2014-04-08 00:30:00,34.36866020104286\n2023,2014-04-08 00:35:00,35.90256765073333\n2024,2014-04-08 00:40:00,35.104166193723806\n2025,2014-04-08 00:45:00,33.70840070811428\n2026,2014-04-08 00:50:00,36.65226627920476\n2027,2014-04-08 00:55:00,34.25346793999524\n2028,2014-04-08 01:00:00,36.01381015018571\n2029,2014-04-08 01:05:00,36.216389306876195\n2030,2014-04-08 01:10:00,36.95679746766667\n2031,2014-04-08 01:15:00,35.105637008957146\n2032,2014-04-08 01:20:00,35.58238968094762\n2033,2014-04-08 01:25:00,34.465993269138096\n2034,2014-04-08 01:30:00,35.84664574502857\n2035,2014-04-08 01:35:00,34.99490299111905\n2036,2014-04-08 01:40:00,34.89941898270953\n2037,2014-04-08 01:45:00,36.5781201165\n2038,2014-04-08 01:50:00,33.364365850190474\n2039,2014-04-08 01:55:00,36.69898066368095\n2040,2014-04-08 02:00:00,36.586850779871426\n2041,2014-04-08 02:05:00,35.21147691896191\n2042,2014-04-08 02:10:00,35.15426379775238\n2043,2014-04-08 02:15:00,34.64812232924286\n2044,2014-04-08 02:20:00,37.18502850003333\n2045,2014-04-08 02:25:00,33.660451140523804\n2046,2014-04-08 02:30:00,35.58407522821429\n2047,2014-04-08 02:35:00,35.95738112230476\n2048,2014-04-08 02:40:00,36.97541527099524\n2049,2014-04-08 02:45:00,36.366349701685714\n2050,2014-04-08 02:50:00,35.82836500167619\n2051,2014-04-08 02:55:00,33.72766593386667\n2052,2014-04-08 03:00:00,34.76279121015715\n2053,2014-04-08 03:05:00,33.83066418924762\n2054,2014-04-08 03:10:00,36.80758902513809\n2055,2014-04-08 03:15:00,36.288663193728574\n2056,2014-04-08 03:20:00,36.32776619481905\n2057,2014-04-08 03:25:00,35.91408559490952\n2058,2014-04-08 03:30:00,35.3406741477\n2059,2014-04-08 03:35:00,33.919824714090474\n2060,2014-04-08 03:40:00,34.64616049918095\n2061,2014-04-08 03:45:00,33.88248459847143\n2062,2014-04-08 03:50:00,36.2419144761619\n2063,2014-04-08 03:55:00,33.99061748505238\n2064,2014-04-08 04:00:00,36.16559705784285\n2065,2014-04-08 04:05:00,36.13360489173333\n2066,2014-04-08 04:10:00,35.20924172552381\n2067,2014-04-08 04:15:00,33.92037890221428\n2068,2014-04-08 04:20:00,34.646108066404764\n2069,2014-04-08 04:25:00,34.67471767439524\n2070,2014-04-08 04:30:00,36.203326246885716\n2071,2014-04-08 04:35:00,33.86419826817619\n2072,2014-04-08 04:40:00,36.732941251566665\n2073,2014-04-08 04:45:00,36.468136303557145\n2074,2014-04-08 04:50:00,34.17677529174762\n2075,2014-04-08 04:55:00,36.315645622338096\n2076,2014-04-08 05:00:00,36.12048129732857\n2077,2014-04-08 05:05:00,36.446352248019046\n2078,2014-04-08 05:10:00,34.217023745609524\n2079,2014-04-08 05:15:00,34.0991112886\n2080,2014-04-08 05:20:00,34.422126419890475\n2081,2014-04-08 05:25:00,34.94711776498095\n2082,2014-04-08 05:30:00,36.66573135267143\n2083,2014-04-08 05:35:00,36.4502076546619\n2084,2014-04-08 05:40:00,37.20775875005238\n2085,2014-04-08 05:45:00,33.747911093542854\n2086,2014-04-08 05:50:00,33.56705845743333\n2087,2014-04-08 05:55:00,36.324829128323806\n2088,2014-04-08 06:00:00,34.652864268914286\n2089,2014-04-08 06:05:00,34.87947034400476\n2090,2014-04-08 06:10:00,35.737803341795235\n2091,2014-04-08 06:15:00,33.967688206785716\n2092,2014-04-08 06:20:00,36.13625385667619\n2093,2014-04-08 06:25:00,34.87350645156667\n2094,2014-04-08 06:30:00,36.11121764005714\n2095,2014-04-08 06:35:00,36.92382527134762\n2096,2014-04-08 06:40:00,34.27968342853809\n2097,2014-04-08 06:45:00,37.326170943128574\n2098,2014-04-08 06:50:00,35.73287161181905\n2099,2014-04-08 06:55:00,37.30927058450953\n2100,2014-04-08 07:00:00,34.455920328800005\n2101,2014-04-08 07:05:00,36.05069113459047\n2102,2014-04-08 07:10:00,35.25542942168095\n2103,2014-04-08 07:15:00,36.744210193171426\n2104,2014-04-08 07:20:00,36.078397677661904\n2105,2014-04-08 07:25:00,35.640264208752384\n2106,2014-04-08 07:30:00,37.32158448284286\n2107,2014-04-08 07:35:00,35.185551590033334\n2108,2014-04-08 07:40:00,34.564444629123805\n2109,2014-04-08 07:45:00,36.124369033114284\n2110,2014-04-08 07:50:00,36.19551851060476\n2111,2014-04-08 07:55:00,35.463223724395235\n2112,2014-04-08 08:00:00,35.66072588908571\n2113,2014-04-08 08:05:00,37.55993984767619\n2114,2014-04-08 08:10:00,36.659909432266666\n2115,2014-04-08 08:15:00,34.17901414875714\n2116,2014-04-08 08:20:00,34.592567902547614\n2117,2014-04-08 08:25:00,37.653794632938094\n2118,2014-04-08 08:30:00,36.66479078662857\n2119,2014-04-08 08:35:00,37.42654955221904\n2120,2014-04-08 08:40:00,34.98925537980952\n2121,2014-04-08 08:45:00,36.7487174403\n2122,2014-04-08 08:50:00,36.64470131029047\n2123,2014-04-08 08:55:00,34.97489089418095\n2124,2014-04-08 09:00:00,84.49467345467143\n2125,2014-04-08 09:05:00,85.5438574180619\n2126,2014-04-08 09:10:00,83.56184500825238\n2127,2014-04-08 09:15:00,88.27552326764287\n2128,2014-04-08 09:20:00,88.36035230183333\n2129,2014-04-08 09:25:00,88.60894126642381\n2130,2014-04-08 09:30:00,87.9747748254143\n2131,2014-04-08 09:35:00,83.69359005180476\n2132,2014-04-08 09:40:00,82.25065609289524\n2133,2014-04-08 09:45:00,88.37725317278571\n2134,2014-04-08 09:50:00,83.74471602687619\n2135,2014-04-08 09:55:00,80.43606768796667\n2136,2014-04-08 10:00:00,93.60682876445713\n2137,2014-04-08 10:05:00,87.94180685524762\n2138,2014-04-08 10:10:00,96.4818277893381\n2139,2014-04-08 10:15:00,90.96867686222856\n2140,2014-04-08 10:20:00,89.80804359951905\n2141,2014-04-08 10:25:00,100.61507526540952\n2142,2014-04-08 10:30:00,97.8346930542\n2143,2014-04-08 10:35:00,98.00025915849048\n2144,2014-04-08 10:40:00,95.47254591558095\n2145,2014-04-08 10:45:00,98.82378344767143\n2146,2014-04-08 10:50:00,97.5894636124619\n2147,2014-04-08 10:55:00,95.10767026915238\n2148,2014-04-08 11:00:00,102.83586534414287\n2149,2014-04-08 11:05:00,90.60470941313332\n2150,2014-04-08 11:10:00,102.56853486042381\n2151,2014-04-08 11:15:00,93.9569368141143\n2152,2014-04-08 11:20:00,95.98356219390476\n2153,2014-04-08 11:25:00,89.53939137609524\n2154,2014-04-08 11:30:00,96.1846544228857\n2155,2014-04-08 11:35:00,97.32285837207618\n2156,2014-04-08 11:40:00,103.47711198756667\n2157,2014-04-08 11:45:00,103.12656724855714\n2158,2014-04-08 11:50:00,102.99413014904762\n2159,2014-04-08 11:55:00,93.17275180313808\n2160,2014-04-08 12:00:00,103.82626023452855\n2161,2014-04-08 12:05:00,95.27137429261906\n2162,2014-04-08 12:10:00,101.61293440780952\n2163,2014-04-08 12:15:00,91.4643161609\n2164,2014-04-08 12:20:00,96.09840935369047\n2165,2014-04-08 12:25:00,103.45987705818095\n2166,2014-04-08 12:30:00,103.16399077657142\n2167,2014-04-08 12:35:00,98.9637422402619\n2168,2014-04-08 12:40:00,100.79426350685237\n2169,2014-04-08 12:45:00,90.87143261024286\n2170,2014-04-08 12:50:00,99.59211428093333\n2171,2014-04-08 12:55:00,97.9438201673238\n2172,2014-04-08 13:00:00,89.6079104991143\n2173,2014-04-08 13:05:00,89.96098433670475\n2174,2014-04-08 13:10:00,89.89299669859524\n2175,2014-04-08 13:15:00,99.7526851408857\n2176,2014-04-08 13:20:00,90.4400953360762\n2177,2014-04-08 13:25:00,95.66255691256666\n2178,2014-04-08 13:30:00,93.89841522675714\n2179,2014-04-08 13:35:00,97.00146993544763\n2180,2014-04-08 13:40:00,99.5038690210381\n2181,2014-04-08 13:45:00,99.16332983242857\n2182,2014-04-08 13:50:00,96.46417810581904\n2183,2014-04-08 13:55:00,95.65285445570952\n2184,2014-04-08 14:00:00,94.6112879996\n2185,2014-04-08 14:05:00,102.04388170219048\n2186,2014-04-08 14:10:00,93.55479973618095\n2187,2014-04-08 14:15:00,92.41851937427143\n2188,2014-04-08 14:20:00,100.16878293696192\n2189,2014-04-08 14:25:00,94.03968546975238\n2190,2014-04-08 14:30:00,101.84251395834286\n2191,2014-04-08 14:35:00,93.54459501303333\n2192,2014-04-08 14:40:00,99.5366459091238\n2193,2014-04-08 14:45:00,89.03521774251428\n2194,2014-04-08 14:50:00,94.48965873140476\n2195,2014-04-08 14:55:00,93.81980843679524\n2196,2014-04-08 15:00:00,101.4053289008857\n2197,2014-04-08 15:05:00,103.8187729023762\n2198,2014-04-08 15:10:00,95.72750510236665\n2199,2014-04-08 15:15:00,101.55816968245713\n2200,2014-04-08 15:20:00,99.56336416124762\n2201,2014-04-08 15:25:00,103.85382410733808\n2202,2014-04-08 15:30:00,101.36084901462857\n2203,2014-04-08 15:35:00,89.63031500241905\n2204,2014-04-08 15:40:00,99.81051632180952\n2205,2014-04-08 15:45:00,96.973471994\n2206,2014-04-08 15:50:00,88.67597367849046\n2207,2014-04-08 15:55:00,92.44140849028095\n2208,2014-04-08 16:00:00,103.17648879267144\n2209,2014-04-08 16:05:00,103.2528271807619\n2210,2014-04-08 16:10:00,101.22489696345238\n2211,2014-04-08 16:15:00,104.15919810934285\n2212,2014-04-08 16:20:00,101.36289391023332\n2213,2014-04-08 16:25:00,88.62890225262382\n2214,2014-04-08 16:30:00,93.07841664831429\n2215,2014-04-08 16:35:00,88.97050249690476\n2216,2014-04-08 16:40:00,89.99368160689524\n2217,2014-04-08 16:45:00,91.9968438226857\n2218,2014-04-08 16:50:00,96.55975922237619\n2219,2014-04-08 16:55:00,102.07076444586667\n2220,2014-04-08 17:00:00,102.30929229745713\n2221,2014-04-08 17:05:00,98.38449592204762\n2222,2014-04-08 17:10:00,103.38351976953811\n2223,2014-04-08 17:15:00,96.54114507652857\n2224,2014-04-08 17:20:00,102.77216264351905\n2225,2014-04-08 17:25:00,95.82007318730952\n2226,2014-04-08 17:30:00,92.9980707675\n2227,2014-04-08 17:35:00,103.2325138873905\n2228,2014-04-08 17:40:00,94.78431213178095\n2229,2014-04-08 17:45:00,96.63925642917144\n2230,2014-04-08 17:50:00,93.8540023567619\n2231,2014-04-08 17:55:00,99.20507226515238\n2232,2014-04-08 18:00:00,51.77533594484285\n2233,2014-04-08 18:05:00,45.57786448513333\n2234,2014-04-08 18:10:00,51.18104441262381\n2235,2014-04-08 18:15:00,45.45458551601429\n2236,2014-04-08 18:20:00,47.76795722410476\n2237,2014-04-08 18:25:00,46.52342306159524\n2238,2014-04-08 18:30:00,50.298766650385716\n2239,2014-04-08 18:35:00,45.78312997957619\n2240,2014-04-08 18:40:00,49.008964159866665\n2241,2014-04-08 18:45:00,47.36162850745714\n2242,2014-04-08 18:50:00,46.337031517947615\n2243,2014-04-08 18:55:00,50.428618174638096\n2244,2014-04-08 19:00:00,37.83045482952857\n2245,2014-04-08 19:05:00,37.86593283671905\n2246,2014-04-08 19:10:00,38.10365234770953\n2247,2014-04-08 19:15:00,39.5074638518\n2248,2014-04-08 19:20:00,39.84149258209048\n2249,2014-04-08 19:25:00,36.97248914828096\n2250,2014-04-08 19:30:00,37.98464623297143\n2251,2014-04-08 19:35:00,38.839260067361906\n2252,2014-04-08 19:40:00,38.40320793915238\n2253,2014-04-08 19:45:00,40.88447608404286\n2254,2014-04-08 19:50:00,40.459767148233325\n2255,2014-04-08 19:55:00,39.74226071542381\n2256,2014-04-08 20:00:00,36.60233578381428\n2257,2014-04-08 20:05:00,38.09510843080476\n2258,2014-04-08 20:10:00,38.688136276095236\n2259,2014-04-08 20:15:00,37.67646068948571\n2260,2014-04-08 20:20:00,38.460630099176186\n2261,2014-04-08 20:25:00,38.323250330566665\n2262,2014-04-08 20:30:00,37.604192920057145\n2263,2014-04-08 20:35:00,36.548499838647615\n2264,2014-04-08 20:40:00,38.3319615565381\n2265,2014-04-08 20:45:00,36.131716256728566\n2266,2014-04-08 20:50:00,38.48490305531905\n2267,2014-04-08 20:55:00,38.594982514109525\n2268,2014-04-08 21:00:00,38.265764647699996\n2269,2014-04-08 21:05:00,36.869584297890476\n2270,2014-04-08 21:10:00,35.74989960808095\n2271,2014-04-08 21:15:00,35.38453047677143\n2272,2014-04-08 21:20:00,37.97887939116191\n2273,2014-04-08 21:25:00,38.56066408475238\n2274,2014-04-08 21:30:00,37.62189233834286\n2275,2014-04-08 21:35:00,35.59289140243334\n2276,2014-04-08 21:40:00,38.77845956202381\n2277,2014-04-08 21:45:00,39.00376304861429\n2278,2014-04-08 21:50:00,36.777640022504755\n2279,2014-04-08 21:55:00,37.43396699069524\n2280,2014-04-08 22:00:00,38.09346434138571\n2281,2014-04-08 22:05:00,37.93739307717619\n2282,2014-04-08 22:10:00,38.871311726466665\n2283,2014-04-08 22:15:00,35.46386064915714\n2284,2014-04-08 22:20:00,37.33645705714761\n2285,2014-04-08 22:25:00,37.78915078033809\n2286,2014-04-08 22:30:00,38.59002023552857\n2287,2014-04-08 22:35:00,38.533444128919044\n2288,2014-04-08 22:40:00,38.95684420650952\n2289,2014-04-08 22:45:00,37.0988101872\n2290,2014-04-08 22:50:00,38.382204054690476\n2291,2014-04-08 22:55:00,36.774178536980955\n2292,2014-04-08 23:00:00,36.746607275071426\n2293,2014-04-08 23:05:00,36.078055932361906\n2294,2014-04-08 23:10:00,38.345485933152375\n2295,2014-04-08 23:15:00,39.02336638424286\n2296,2014-04-08 23:20:00,36.112353115333335\n2297,2014-04-08 23:25:00,35.31879926892381\n2298,2014-04-08 23:30:00,38.36446636991428\n2299,2014-04-08 23:35:00,37.59050730670476\n2300,2014-04-08 23:40:00,38.95608348679524\n2301,2014-04-08 23:45:00,36.133142308485716\n2302,2014-04-08 23:50:00,35.415597369876195\n2303,2014-04-08 23:55:00,37.10901990386667\n2304,2014-04-09 00:00:00,35.484721234757146\n2305,2014-04-09 00:05:00,36.19745762344762\n2306,2014-04-09 00:10:00,35.66164953853809\n2307,2014-04-09 00:15:00,36.061707290028565\n2308,2014-04-09 00:20:00,35.59719765891904\n2309,2014-04-09 00:25:00,38.99568352150952\n2310,2014-04-09 00:30:00,36.3017508538\n2311,2014-04-09 00:35:00,36.970530820190476\n2312,2014-04-09 00:40:00,38.79682818288096\n2313,2014-04-09 00:45:00,37.91910778037143\n2314,2014-04-09 00:50:00,37.6894118269619\n2315,2014-04-09 00:55:00,38.04695514235238\n2316,2014-04-09 01:00:00,38.547431885542856\n2317,2014-04-09 01:05:00,38.75026040473333\n2318,2014-04-09 01:10:00,37.817582492223806\n2319,2014-04-09 01:15:00,38.814493384514286\n2320,2014-04-09 01:20:00,37.403494871604764\n2321,2014-04-09 01:25:00,36.378508663195234\n2322,2014-04-09 01:30:00,38.79709254978572\n2323,2014-04-09 01:35:00,37.45011750017619\n2324,2014-04-09 01:40:00,38.91621701696667\n2325,2014-04-09 01:45:00,35.45977839865714\n2326,2014-04-09 01:50:00,36.89661062524762\n2327,2014-04-09 01:55:00,39.1052081686381\n2328,2014-04-09 02:00:00,36.320028942428564\n2329,2014-04-09 02:05:00,39.09501403181905\n2330,2014-04-09 02:10:00,39.15191936830952\n2331,2014-04-09 02:15:00,38.8723192569\n2332,2014-04-09 02:20:00,37.605862656590475\n2333,2014-04-09 02:25:00,37.94638874868095\n2334,2014-04-09 02:30:00,38.844539422371426\n2335,2014-04-09 02:35:00,38.477100234361906\n2336,2014-04-09 02:40:00,37.901327778752375\n2337,2014-04-09 02:45:00,39.317430488642856\n2338,2014-04-09 02:50:00,38.13853987863333\n2339,2014-04-09 02:55:00,39.30520177932381\n2340,2014-04-09 03:00:00,35.640268184114284\n2341,2014-04-09 03:05:00,35.973996244904754\n2342,2014-04-09 03:10:00,37.23143062209524\n2343,2014-04-09 03:15:00,36.972553557785716\n2344,2014-04-09 03:20:00,38.571415555876186\n2345,2014-04-09 03:25:00,36.09037277256667\n2346,2014-04-09 03:30:00,39.35973785925714\n2347,2014-04-09 03:35:00,36.72306112004762\n2348,2014-04-09 03:40:00,37.185932926238095\n2349,2014-04-09 03:45:00,36.57665870122857\n2350,2014-04-09 03:50:00,37.80257351691905\n2351,2014-04-09 03:55:00,35.72707432550952\n2352,2014-04-09 04:00:00,36.0987100223\n2353,2014-04-09 04:05:00,38.49063128989047\n2354,2014-04-09 04:10:00,36.26088328598095\n2355,2014-04-09 04:15:00,36.46437923477143\n2356,2014-04-09 04:20:00,38.70169084766191\n2357,2014-04-09 04:25:00,35.91040709435238\n2358,2014-04-09 04:30:00,37.29453814824286\n2359,2014-04-09 04:35:00,35.64433688133333\n2360,2014-04-09 04:40:00,36.94675340682381\n2361,2014-04-09 04:45:00,38.36288989611428\n2362,2014-04-09 04:50:00,35.93481788080476\n2363,2014-04-09 04:55:00,39.135183745195235\n2364,2014-04-09 05:00:00,39.227281886085706\n2365,2014-04-09 05:05:00,36.01668769097619\n2366,2014-04-09 05:10:00,39.56709641216666\n2367,2014-04-09 05:15:00,36.80172535645714\n2368,2014-04-09 05:20:00,35.95545430354762\n2369,2014-04-09 05:25:00,35.64675655323809\n2370,2014-04-09 05:30:00,37.26802015452857\n2371,2014-04-09 05:35:00,38.16060899041905\n2372,2014-04-09 05:40:00,36.97752652340952\n2373,2014-04-09 05:45:00,39.0031194619\n2374,2014-04-09 05:50:00,38.530115578490474\n2375,2014-04-09 05:55:00,37.07177708028095\n2376,2014-04-09 06:00:00,38.61581009497143\n2377,2014-04-09 06:05:00,39.4479628526619\n2378,2014-04-09 06:10:00,36.06583637515238\n2379,2014-04-09 06:15:00,36.92530869774286\n2380,2014-04-09 06:20:00,37.56163708983333\n2381,2014-04-09 06:25:00,37.70773432052381\n2382,2014-04-09 06:30:00,37.89199686521428\n2383,2014-04-09 06:35:00,36.93316238810476\n2384,2014-04-09 06:40:00,38.40713382199524\n2385,2014-04-09 06:45:00,38.325873728385716\n2386,2014-04-09 06:50:00,38.06426221557619\n2387,2014-04-09 06:55:00,36.21546355346666\n2388,2014-04-09 07:00:00,37.67572870725714\n2389,2014-04-09 07:05:00,37.20020516904762\n2390,2014-04-09 07:10:00,37.746891974638096\n2391,2014-04-09 07:15:00,39.47764431352857\n2392,2014-04-09 07:20:00,37.719744420219044\n2393,2014-04-09 07:25:00,35.86098269120952\n2394,2014-04-09 07:30:00,37.5678469523\n2395,2014-04-09 07:35:00,39.102533196390475\n2396,2014-04-09 07:40:00,38.94762464528095\n2397,2014-04-09 07:45:00,37.888381722671426\n2398,2014-04-09 07:50:00,36.84133795616191\n2399,2014-04-09 07:55:00,37.71005703265238\n2400,2014-04-09 08:00:00,38.11195173484286\n2401,2014-04-09 08:05:00,39.86406908643333\n2402,2014-04-09 08:10:00,38.44873617022381\n2403,2014-04-09 08:15:00,38.65652400601428\n2404,2014-04-09 08:20:00,37.85272133620476\n2405,2014-04-09 08:25:00,37.31230344119524\n2406,2014-04-09 08:30:00,39.15359764888571\n2407,2014-04-09 08:35:00,37.88895548787619\n2408,2014-04-09 08:40:00,39.895427186566664\n2409,2014-04-09 08:45:00,37.75258943995714\n2410,2014-04-09 08:50:00,36.20354875364762\n2411,2014-04-09 08:55:00,38.669300643638095\n2412,2014-04-09 09:00:00,79.78075230402858\n2413,2014-04-09 09:05:00,82.56069076521905\n2414,2014-04-09 09:10:00,83.97214976160951\n2415,2014-04-09 09:15:00,89.2257267645\n2416,2014-04-09 09:20:00,85.89779907529046\n2417,2014-04-09 09:25:00,79.57321561818095\n2418,2014-04-09 09:30:00,87.58022940597142\n2419,2014-04-09 09:35:00,84.7940447337619\n2420,2014-04-09 09:40:00,91.74290171655238\n2421,2014-04-09 09:45:00,86.00744028864285\n2422,2014-04-09 09:50:00,88.86289531813333\n2423,2014-04-09 09:55:00,82.20488530522381\n2424,2014-04-09 10:00:00,99.68602400721429\n2425,2014-04-09 10:05:00,99.07238118060476\n2426,2014-04-09 10:10:00,101.92194335469524\n2427,2014-04-09 10:15:00,88.42294759378571\n2428,2014-04-09 10:20:00,94.85068701747619\n2429,2014-04-09 10:25:00,98.45340851716668\n2430,2014-04-09 10:30:00,89.39730087205714\n2431,2014-04-09 10:35:00,94.30037274124763\n2432,2014-04-09 10:40:00,102.5573533748381\n2433,2014-04-09 10:45:00,94.70838187002856\n2434,2014-04-09 10:50:00,103.24360128721905\n2435,2014-04-09 10:55:00,88.83970175180951\n2436,2014-04-09 11:00:00,101.1093647597\n2437,2014-04-09 11:05:00,98.94092269749046\n2438,2014-04-09 11:10:00,97.66846397748095\n2439,2014-04-09 11:15:00,105.15567850177143\n2440,2014-04-09 11:20:00,91.7847218741619\n2441,2014-04-09 11:25:00,103.98016970845238\n2442,2014-04-09 11:30:00,100.73113035584286\n2443,2014-04-09 11:35:00,93.86415688313332\n2444,2014-04-09 11:40:00,104.09266990162381\n2445,2014-04-09 11:45:00,96.5874706594143\n2446,2014-04-09 11:50:00,102.71687618760475\n2447,2014-04-09 11:55:00,95.95890120519525\n2448,2014-04-09 12:00:00,103.7264410812857\n2449,2014-04-09 12:05:00,100.3091688064762\n2450,2014-04-09 12:10:00,92.39680470866665\n2451,2014-04-09 12:15:00,100.53234422565714\n2452,2014-04-09 12:20:00,93.21549000284762\n2453,2014-04-09 12:25:00,96.74794122713809\n2454,2014-04-09 12:30:00,92.89398824422857\n2455,2014-04-09 12:35:00,90.53180418891905\n2456,2014-04-09 12:40:00,93.57352593340951\n2457,2014-04-09 12:45:00,98.7665040367\n2458,2014-04-09 12:50:00,97.89801999009049\n2459,2014-04-09 12:55:00,98.22405573668095\n2460,2014-04-09 13:00:00,94.24833036607143\n2461,2014-04-09 13:05:00,101.25368009556192\n2462,2014-04-09 13:10:00,101.56668059905239\n2463,2014-04-09 13:15:00,96.03472346964286\n2464,2014-04-09 13:20:00,104.41139105573333\n2465,2014-04-09 13:25:00,100.62539222652381\n2466,2014-04-09 13:30:00,101.73682461901427\n2467,2014-04-09 13:35:00,94.77474846360477\n2468,2014-04-09 13:40:00,90.35559905189524\n2469,2014-04-09 13:45:00,104.19594246558573\n2470,2014-04-09 13:50:00,103.51632823407618\n2471,2014-04-09 13:55:00,92.33873381846666\n2472,2014-04-09 14:00:00,96.37479598945714\n2473,2014-04-09 14:05:00,100.97776264464763\n2474,2014-04-09 14:10:00,100.83755498963808\n2475,2014-04-09 14:15:00,104.17666717932858\n2476,2014-04-09 14:20:00,92.66334590781905\n2477,2014-04-09 14:25:00,97.30530929460951\n2478,2014-04-09 14:30:00,91.9895600185\n2479,2014-04-09 14:35:00,96.67470924209047\n2480,2014-04-09 14:40:00,90.69063247928095\n2481,2014-04-09 14:45:00,104.82804459657142\n2482,2014-04-09 14:50:00,98.8961050842619\n2483,2014-04-09 14:55:00,104.06742990565239\n2484,2014-04-09 15:00:00,91.43991767184286\n2485,2014-04-09 15:05:00,94.12818696333333\n2486,2014-04-09 15:10:00,94.64637269232381\n2487,2014-04-09 15:15:00,96.69077760411429\n2488,2014-04-09 15:20:00,103.35695220000477\n2489,2014-04-09 15:25:00,96.70352064249523\n2490,2014-04-09 15:30:00,93.8005195538857\n2491,2014-04-09 15:35:00,91.5733691733762\n2492,2014-04-09 15:40:00,91.81283123036667\n2493,2014-04-09 15:45:00,102.70905449495714\n2494,2014-04-09 15:50:00,97.67263595384762\n2495,2014-04-09 15:55:00,102.18208330583809\n2496,2014-04-09 16:00:00,101.48786331982858\n2497,2014-04-09 16:05:00,92.74452603741905\n2498,2014-04-09 16:10:00,92.87237384140953\n2499,2014-04-09 16:15:00,102.6790608028\n2500,2014-04-09 16:20:00,102.14132277459046\n2501,2014-04-09 16:25:00,96.65697336928095\n2502,2014-04-09 16:30:00,91.85468702347143\n2503,2014-04-09 16:35:00,90.81694164026192\n2504,2014-04-09 16:40:00,95.24131648015238\n2505,2014-04-09 16:45:00,90.78581071124286\n2506,2014-04-09 16:50:00,94.32684996313333\n2507,2014-04-09 16:55:00,97.3651345258238\n2508,2014-04-09 17:00:00,92.60333813671429\n2509,2014-04-09 17:05:00,92.33657059850476\n2510,2014-04-09 17:10:00,105.01856105389524\n2511,2014-04-09 17:15:00,100.0505249334857\n2512,2014-04-09 17:20:00,105.64173378937619\n2513,2014-04-09 17:25:00,96.23110551446666\n2514,2014-04-09 17:30:00,101.53964433175715\n2515,2014-04-09 17:35:00,93.98783550734763\n2516,2014-04-09 17:40:00,100.61365172463809\n2517,2014-04-09 17:45:00,92.80102180742857\n2518,2014-04-09 17:50:00,90.76838161361906\n2519,2014-04-09 17:55:00,105.64703497500953\n2520,2014-04-09 18:00:00,51.1013177961\n2521,2014-04-09 18:05:00,53.48985404939047\n2522,2014-04-09 18:10:00,49.70139676428096\n2523,2014-04-09 18:15:00,49.67014633887143\n2524,2014-04-09 18:20:00,50.143947894161904\n2525,2014-04-09 18:25:00,52.105858281052384\n2526,2014-04-09 18:30:00,51.21581189104286\n2527,2014-04-09 18:35:00,53.524348072133336\n2528,2014-04-09 18:40:00,47.77234001592381\n2529,2014-04-09 18:45:00,52.14941188891429\n2530,2014-04-09 18:50:00,49.73849603830476\n2531,2014-04-09 18:55:00,48.78533485869524\n2532,2014-04-09 19:00:00,41.28585687178571\n2533,2014-04-09 19:05:00,41.26941071357619\n2534,2014-04-09 19:10:00,39.62797493556667\n2535,2014-04-09 19:15:00,39.926100318757136\n2536,2014-04-09 19:20:00,40.857624111547615\n2537,2014-04-09 19:25:00,40.8679620163381\n2538,2014-04-09 19:30:00,40.46658785292857\n2539,2014-04-09 19:35:00,39.71685018391905\n2540,2014-04-09 19:40:00,39.07840249920952\n2541,2014-04-09 19:45:00,43.412901735300004\n2542,2014-04-09 19:50:00,43.300565687490476\n2543,2014-04-09 19:55:00,41.24788342628095\n2544,2014-04-09 20:00:00,41.43630313987143\n2545,2014-04-09 20:05:00,40.127299789361906\n2546,2014-04-09 20:10:00,37.65749263045238\n2547,2014-04-09 20:15:00,37.86506637364286\n2548,2014-04-09 20:20:00,41.142723083633335\n2549,2014-04-09 20:25:00,39.97846737742381\n2550,2014-04-09 20:30:00,40.85889415791428\n2551,2014-04-09 20:35:00,41.09196698150476\n2552,2014-04-09 20:40:00,39.254865473095236\n2553,2014-04-09 20:45:00,37.62629778838571\n2554,2014-04-09 20:50:00,38.20617226907619\n2555,2014-04-09 20:55:00,37.715095138366664\n2556,2014-04-09 21:00:00,37.862840284557144\n2557,2014-04-09 21:05:00,38.76171150874762\n2558,2014-04-09 21:10:00,37.594194670638096\n2559,2014-04-09 21:15:00,37.79671279512857\n2560,2014-04-09 21:20:00,38.925865905519046\n2561,2014-04-09 21:25:00,38.508674560009524\n2562,2014-04-09 21:30:00,39.028511483900004\n2563,2014-04-09 21:35:00,38.881268641690475\n2564,2014-04-09 21:40:00,39.75406698378096\n2565,2014-04-09 21:45:00,40.93797360997142\n2566,2014-04-09 21:50:00,37.612190208561906\n2567,2014-04-09 21:55:00,37.58504872785238\n2568,2014-04-09 22:00:00,40.53892206644286\n2569,2014-04-09 22:05:00,39.15939470543333\n2570,2014-04-09 22:10:00,40.207866888723814\n2571,2014-04-09 22:15:00,38.00925911101429\n2572,2014-04-09 22:20:00,40.47281787640476\n2573,2014-04-09 22:25:00,40.86055929519524\n2574,2014-04-09 22:30:00,39.71343802118571\n2575,2014-04-09 22:35:00,37.60042884277619\n2576,2014-04-09 22:40:00,40.76856384476666\n2577,2014-04-09 22:45:00,40.364381194757144\n2578,2014-04-09 22:50:00,40.205222085447616\n2579,2014-04-09 22:55:00,37.35332187813809\n2580,2014-04-09 23:00:00,40.39634827362857\n2581,2014-04-09 23:05:00,37.75923503401905\n2582,2014-04-09 23:10:00,38.10448101930952\n2583,2014-04-09 23:15:00,39.531188577\n2584,2014-04-09 23:20:00,38.289773071190474\n2585,2014-04-09 23:25:00,39.882987690980954\n2586,2014-04-09 23:30:00,39.67727621547142\n2587,2014-04-09 23:35:00,37.68464935386191\n2588,2014-04-09 23:40:00,39.88397051645238\n2589,2014-04-09 23:45:00,40.96337809164285\n2590,2014-04-09 23:50:00,37.918852684633336\n2591,2014-04-09 23:55:00,39.670436434923815\n2592,2014-04-10 00:00:00,38.65317577341428\n2593,2014-04-10 00:05:00,39.13160144900476\n2594,2014-04-10 00:10:00,38.44859595439524\n2595,2014-04-10 00:15:00,38.72455825968571\n2596,2014-04-10 00:20:00,37.43112348357619\n2597,2014-04-10 00:25:00,41.24912361836667\n2598,2014-04-10 00:30:00,39.82955683115714\n2599,2014-04-10 00:35:00,39.34061998104762\n2600,2014-04-10 00:40:00,38.88009949323809\n2601,2014-04-10 00:45:00,39.510176806728566\n2602,2014-04-10 00:50:00,38.88054304251905\n2603,2014-04-10 00:55:00,38.80719123380952\n2604,2014-04-10 01:00:00,39.2307861669\n2605,2014-04-10 01:05:00,38.48637261089047\n2606,2014-04-10 01:10:00,38.11008055228095\n2607,2014-04-10 01:15:00,39.62374502127143\n2608,2014-04-10 01:20:00,40.775823649361904\n2609,2014-04-10 01:25:00,38.023515091852374\n2610,2014-04-10 01:30:00,37.55058021954286\n2611,2014-04-10 01:35:00,38.414330313933334\n2612,2014-04-10 01:40:00,41.353406383323815\n2613,2014-04-10 01:45:00,40.756996580714286\n2614,2014-04-10 01:50:00,39.83286897600476\n2615,2014-04-10 01:55:00,41.17384089909524\n2616,2014-04-10 02:00:00,39.24540218158571\n2617,2014-04-10 02:05:00,41.40484860077619\n2618,2014-04-10 02:10:00,38.66437484716666\n2619,2014-04-10 02:15:00,38.44783014095714\n2620,2014-04-10 02:20:00,40.04624042364762\n2621,2014-04-10 02:25:00,39.014103967038096\n2622,2014-04-10 02:30:00,40.01439073932857\n2623,2014-04-10 02:35:00,38.73635112081905\n2624,2014-04-10 02:40:00,39.99548255120952\n2625,2014-04-10 02:45:00,38.6342350423\n2626,2014-04-10 02:50:00,37.74257875149047\n2627,2014-04-10 02:55:00,41.194674560080955\n2628,2014-04-10 03:00:00,41.086392236071426\n2629,2014-04-10 03:05:00,41.444204501861904\n2630,2014-04-10 03:10:00,40.43456108585238\n2631,2014-04-10 03:15:00,40.30677756804286\n2632,2014-04-10 03:20:00,39.81934561363333\n2633,2014-04-10 03:25:00,38.09454347492381\n2634,2014-04-10 03:30:00,38.355155529514285\n2635,2014-04-10 03:35:00,38.76353351660476\n2636,2014-04-10 03:40:00,41.173720688395235\n2637,2014-04-10 03:45:00,38.31241381268571\n2638,2014-04-10 03:50:00,41.319468888476194\n2639,2014-04-10 03:55:00,39.726559598866665\n2640,2014-04-10 04:00:00,40.50513568475714\n2641,2014-04-10 04:05:00,38.09127556574762\n2642,2014-04-10 04:10:00,38.7338722903381\n2643,2014-04-10 04:15:00,41.49925300412857\n2644,2014-04-10 04:20:00,38.73721883531905\n2645,2014-04-10 04:25:00,38.86614640540952\n2646,2014-04-10 04:30:00,38.477889539399996\n2647,2014-04-10 04:35:00,38.211235137390474\n2648,2014-04-10 04:40:00,38.63541151818095\n2649,2014-04-10 04:45:00,40.279128996371426\n2650,2014-04-10 04:50:00,39.5387328387619\n2651,2014-04-10 04:55:00,39.93972572635238\n2652,2014-04-10 05:00:00,38.221602172242854\n2653,2014-04-10 05:05:00,40.94804912203333\n2654,2014-04-10 05:10:00,40.88340261182381\n2655,2014-04-10 05:15:00,37.840823930314286\n2656,2014-04-10 05:20:00,39.29596513990476\n2657,2014-04-10 05:25:00,38.04442764599524\n2658,2014-04-10 05:30:00,40.94520883198571\n2659,2014-04-10 05:35:00,40.73330492297619\n2660,2014-04-10 05:40:00,41.399619043866664\n2661,2014-04-10 05:45:00,38.74472297865714\n2662,2014-04-10 05:50:00,39.63173115154761\n2663,2014-04-10 05:55:00,38.551939603938095\n2664,2014-04-10 06:00:00,39.30636830932857\n2665,2014-04-10 06:05:00,39.917842053919045\n2666,2014-04-10 06:10:00,38.04963268320952\n2667,2014-04-10 06:15:00,40.703231642700004\n2668,2014-04-10 06:20:00,40.02436391769048\n2669,2014-04-10 06:25:00,41.17446702118095\n2670,2014-04-10 06:30:00,38.953193433371425\n2671,2014-04-10 06:35:00,41.4867963258619\n2672,2014-04-10 06:40:00,41.87572939305238\n2673,2014-04-10 06:45:00,41.56558661064285\n2674,2014-04-10 06:50:00,41.00740323663333\n2675,2014-04-10 06:55:00,41.15274902102381\n2676,2014-04-10 07:00:00,40.20569125591429\n2677,2014-04-10 07:05:00,38.678770213604764\n2678,2014-04-10 07:10:00,40.633757978695236\n2679,2014-04-10 07:15:00,40.78404772248571\n2680,2014-04-10 07:20:00,41.88201675157619\n2681,2014-04-10 07:25:00,40.11312193166667\n2682,2014-04-10 07:30:00,39.040833202957145\n2683,2014-04-10 07:35:00,40.69748770604762\n2684,2014-04-10 07:40:00,41.8877413739381\n2685,2014-04-10 07:45:00,38.68653420452857\n2686,2014-04-10 07:50:00,39.28911072171905\n2687,2014-04-10 07:55:00,40.16008333890952\n2688,2014-04-10 08:00:00,38.6808585395\n2689,2014-04-10 08:05:00,38.09632303429048\n2690,2014-04-10 08:10:00,39.36281344218095\n2691,2014-04-10 08:15:00,41.48380463457143\n2692,2014-04-10 08:20:00,38.20363550206191\n2693,2014-04-10 08:25:00,39.75291861705238\n2694,2014-04-10 08:30:00,41.093445948842856\n2695,2014-04-10 08:35:00,41.864813720933334\n2696,2014-04-10 08:40:00,42.001425405523804\n2697,2014-04-10 08:45:00,39.754841808114286\n2698,2014-04-10 08:50:00,41.875941939404754\n2699,2014-04-10 08:55:00,38.22352113119524\n2700,2014-04-10 09:00:00,91.43375607108571\n2701,2014-04-10 09:05:00,90.03807226147619\n2702,2014-04-10 09:10:00,84.69766392986665\n2703,2014-04-10 09:15:00,88.21113875205714\n2704,2014-04-10 09:20:00,83.08097845254763\n2705,2014-04-10 09:25:00,93.1802093481381\n2706,2014-04-10 09:30:00,86.20134253482857\n2707,2014-04-10 09:35:00,89.85557384591905\n2708,2014-04-10 09:40:00,83.50816701730953\n2709,2014-04-10 09:45:00,84.160091887\n2710,2014-04-10 09:50:00,94.85429711909046\n2711,2014-04-10 09:55:00,91.61310591678094\n2712,2014-04-10 10:00:00,104.94837484747143\n2713,2014-04-10 10:05:00,94.61762198886191\n2714,2014-04-10 10:10:00,92.58746822605238\n2715,2014-04-10 10:15:00,97.84851541034286\n2716,2014-04-10 10:20:00,97.72558507353334\n2717,2014-04-10 10:25:00,92.77094370302382\n2718,2014-04-10 10:30:00,101.44278200561428\n2719,2014-04-10 10:35:00,95.68544209640476\n2720,2014-04-10 10:40:00,92.97048362209523\n2721,2014-04-10 10:45:00,95.23791799758571\n2722,2014-04-10 10:50:00,98.84095920877618\n2723,2014-04-10 10:55:00,101.37524553406666\n2724,2014-04-10 11:00:00,99.49984979475714\n2725,2014-04-10 11:05:00,100.20236033724761\n2726,2014-04-10 11:10:00,94.06053426043809\n2727,2014-04-10 11:15:00,106.40542303802857\n2728,2014-04-10 11:20:00,106.63604869251905\n2729,2014-04-10 11:25:00,102.74227601780952\n2730,2014-04-10 11:30:00,92.1609099277\n2731,2014-04-10 11:35:00,100.42956880589048\n2732,2014-04-10 11:40:00,101.90247948448095\n2733,2014-04-10 11:45:00,107.72180219047144\n2734,2014-04-10 11:50:00,107.75171076016193\n2735,2014-04-10 11:55:00,105.55715146755237\n2736,2014-04-10 12:00:00,93.29081317454286\n2737,2014-04-10 12:05:00,107.51230267913333\n2738,2014-04-10 12:10:00,102.07644066802382\n2739,2014-04-10 12:15:00,105.09187558741428\n2740,2014-04-10 12:20:00,98.80777225420475\n2741,2014-04-10 12:25:00,97.41651912399524\n2742,2014-04-10 12:30:00,99.7183977543857\n2743,2014-04-10 12:35:00,94.66999840737618\n2744,2014-04-10 12:40:00,98.03646921686666\n2745,2014-04-10 12:45:00,106.04312088315713\n2746,2014-04-10 12:50:00,92.95162674984762\n2747,2014-04-10 12:55:00,94.76373998593809\n2748,2014-04-10 13:00:00,94.43052667972857\n2749,2014-04-10 13:05:00,98.88424992071906\n2750,2014-04-10 13:10:00,108.3919915084095\n2751,2014-04-10 13:15:00,95.2245311889\n2752,2014-04-10 13:20:00,94.78607421639049\n2753,2014-04-10 13:25:00,107.10372881478095\n2754,2014-04-10 13:30:00,106.58321262607143\n2755,2014-04-10 13:35:00,92.9969540216619\n2756,2014-04-10 13:40:00,104.51308119295238\n2757,2014-04-10 13:45:00,102.98104709244286\n2758,2014-04-10 13:50:00,104.7844581662333\n2759,2014-04-10 13:55:00,100.4211341968238\n2760,2014-04-10 14:00:00,108.3935644016143\n2761,2014-04-10 14:05:00,93.24121738680476\n2762,2014-04-10 14:10:00,96.29690462319525\n2763,2014-04-10 14:15:00,98.8990109585857\n2764,2014-04-10 14:20:00,99.75812182607619\n2765,2014-04-10 14:25:00,107.31063149966667\n2766,2014-04-10 14:30:00,101.53654088475713\n2767,2014-04-10 14:35:00,93.30608290214762\n2768,2014-04-10 14:40:00,99.11727627133808\n2769,2014-04-10 14:45:00,99.26274930472857\n2770,2014-04-10 14:50:00,108.05377656561905\n2771,2014-04-10 14:55:00,102.20079679680953\n2772,2014-04-10 15:00:00,102.7946283025\n2773,2014-04-10 15:05:00,104.04368822059047\n2774,2014-04-10 15:10:00,104.95970052528095\n2775,2014-04-10 15:15:00,102.80734980797142\n2776,2014-04-10 15:20:00,96.44914388986192\n2777,2014-04-10 15:25:00,106.64611155695238\n2778,2014-04-10 15:30:00,104.38275601014287\n2779,2014-04-10 15:35:00,104.54620594353334\n2780,2014-04-10 15:40:00,108.62858736612381\n2781,2014-04-10 15:45:00,105.5315743754143\n2782,2014-04-10 15:50:00,105.96500865470476\n2783,2014-04-10 15:55:00,107.92849615359523\n2784,2014-04-10 16:00:00,95.13228682898571\n2785,2014-04-10 16:05:00,100.6852106839762\n2786,2014-04-10 16:10:00,102.01808296906665\n2787,2014-04-10 16:15:00,98.00487045505714\n2788,2014-04-10 16:20:00,106.17433709484762\n2789,2014-04-10 16:25:00,104.9500403800381\n2790,2014-04-10 16:30:00,104.29289737802857\n2791,2014-04-10 16:35:00,108.72059121131906\n2792,2014-04-10 16:40:00,96.92376529010951\n2793,2014-04-10 16:45:00,104.54840519359999\n2794,2014-04-10 16:50:00,101.61100689549048\n2795,2014-04-10 16:55:00,97.80381001728095\n2796,2014-04-10 17:00:00,95.37293272547143\n2797,2014-04-10 17:05:00,107.14512014556192\n2798,2014-04-10 17:10:00,102.34570879775238\n2799,2014-04-10 17:15:00,106.02480154304287\n2800,2014-04-10 17:20:00,101.55882207873333\n2801,2014-04-10 17:25:00,96.36037810042382\n2802,2014-04-10 17:30:00,98.2489655734143\n2803,2014-04-10 17:35:00,98.96024624930476\n2804,2014-04-10 17:40:00,108.43001861239524\n2805,2014-04-10 17:45:00,92.9606404857857\n2806,2014-04-10 17:50:00,108.6485988549762\n2807,2014-04-10 17:55:00,108.57276915646665\n2808,2014-04-10 18:00:00,56.06821544855714\n2809,2014-04-10 18:05:00,52.75045584894761\n2810,2014-04-10 18:10:00,55.876108786838095\n2811,2014-04-10 18:15:00,52.247007319528564\n2812,2014-04-10 18:20:00,49.89089790601905\n2813,2014-04-10 18:25:00,51.165875711309525\n2814,2014-04-10 18:30:00,55.7873892764\n2815,2014-04-10 18:35:00,49.83302896699047\n2816,2014-04-10 18:40:00,53.24673721858095\n2817,2014-04-10 18:45:00,50.24366597497142\n2818,2014-04-10 18:50:00,51.600194125161906\n2819,2014-04-10 18:55:00,50.33849098765238\n2820,2014-04-10 19:00:00,44.992829762542854\n2821,2014-04-10 19:05:00,43.797578861333335\n2822,2014-04-10 19:10:00,45.1984594483238\n2823,2014-04-10 19:15:00,44.24828534461429\n2824,2014-04-10 19:20:00,45.522113925304765\n2825,2014-04-10 19:25:00,43.46359590019524\n2826,2014-04-10 19:30:00,44.04820785768571\n2827,2014-04-10 19:35:00,43.77608845597619\n2828,2014-04-10 19:40:00,43.371152165666665\n2829,2014-04-10 19:45:00,44.99900378615715\n2830,2014-04-10 19:50:00,44.10401896254761\n2831,2014-04-10 19:55:00,44.81386573893809\n2832,2014-04-10 20:00:00,42.72437499592857\n2833,2014-04-10 20:05:00,40.29338979511905\n2834,2014-04-10 20:10:00,42.18137909990952\n2835,2014-04-10 20:15:00,40.3435080556\n2836,2014-04-10 20:20:00,41.92247090519048\n2837,2014-04-10 20:25:00,42.31540316538096\n2838,2014-04-10 20:30:00,43.63274601157143\n2839,2014-04-10 20:35:00,39.680611624561905\n2840,2014-04-10 20:40:00,39.93668100155238\n2841,2014-04-10 20:45:00,39.88589398054286\n2842,2014-04-10 20:50:00,41.20952092113333\n2843,2014-04-10 20:55:00,42.950499476623804\n2844,2014-04-10 21:00:00,42.63954544591428\n2845,2014-04-10 21:05:00,42.21662310150476\n2846,2014-04-10 21:10:00,42.86672821459524\n2847,2014-04-10 21:15:00,40.56707435448571\n2848,2014-04-10 21:20:00,39.63118729157619\n2849,2014-04-10 21:25:00,39.51804527196666\n2850,2014-04-10 21:30:00,42.71664891695714\n2851,2014-04-10 21:35:00,42.23496712184762\n2852,2014-04-10 21:40:00,42.1145126820381\n2853,2014-04-10 21:45:00,40.67930566372857\n2854,2014-04-10 21:50:00,40.84843393371905\n2855,2014-04-10 21:55:00,43.17980936550953\n2856,2014-04-10 22:00:00,39.5227439776\n2857,2014-04-10 22:05:00,42.372618543490475\n2858,2014-04-10 22:10:00,40.52188322968095\n2859,2014-04-10 22:15:00,39.445969863071426\n2860,2014-04-10 22:20:00,42.2701738066619\n2861,2014-04-10 22:25:00,40.629400615852376\n2862,2014-04-10 22:30:00,42.203285968342854\n2863,2014-04-10 22:35:00,42.15269824843333\n2864,2014-04-10 22:40:00,41.46800488292381\n2865,2014-04-10 22:45:00,42.446721905014286\n2866,2014-04-10 22:50:00,41.668069235804765\n2867,2014-04-10 22:55:00,40.49677332559524\n2868,2014-04-10 23:00:00,42.27976671708571\n2869,2014-04-10 23:05:00,41.707193911376194\n2870,2014-04-10 23:10:00,39.40854156616666\n2871,2014-04-10 23:15:00,42.97233231455714\n2872,2014-04-10 23:20:00,41.55549714464762\n2873,2014-04-10 23:25:00,42.8551202607381\n2874,2014-04-10 23:30:00,42.91900986712857\n2875,2014-04-10 23:35:00,41.17503340701904\n2876,2014-04-10 23:40:00,41.43329539050953\n2877,2014-04-10 23:45:00,41.0730428481\n2878,2014-04-10 23:50:00,41.21523874289048\n2879,2014-04-10 23:55:00,43.00586305918095\n2880,2014-04-11 00:00:00,42.58114748447143\n2881,2014-04-11 00:05:00,39.94211461006191\n2882,2014-04-11 00:10:00,41.884683507152374\n2883,2014-04-11 00:15:00,43.43451941864286\n2884,2014-04-11 00:20:00,41.84053613823333\n2885,2014-04-11 00:25:00,42.609260311923805\n2886,2014-04-11 00:30:00,42.54946017921428\n2887,2014-04-11 00:35:00,40.881924865404756\n2888,2014-04-11 00:40:00,40.97549244889524\n2889,2014-04-11 00:45:00,42.39184140148571\n2890,2014-04-11 00:50:00,41.50291031687619\n2891,2014-04-11 00:55:00,41.792699503166666\n2892,2014-04-11 01:00:00,42.36948030435714\n2893,2014-04-11 01:05:00,42.635597727247614\n2894,2014-04-11 01:10:00,40.618804406138096\n2895,2014-04-11 01:15:00,40.12735360912857\n2896,2014-04-11 01:20:00,40.714797634519044\n2897,2014-04-11 01:25:00,41.58521282420952\n2898,2014-04-11 01:30:00,40.931065269200005\n2899,2014-04-11 01:35:00,41.843391511590475\n2900,2014-04-11 01:40:00,39.79124384888095\n2901,2014-04-11 01:45:00,41.62382307507143\n2902,2014-04-11 01:50:00,41.06420153256191\n2903,2014-04-11 01:55:00,41.73836940055238\n2904,2014-04-11 02:00:00,41.29727627664286\n2905,2014-04-11 02:05:00,40.751486735933334\n2906,2014-04-11 02:10:00,43.2384554313238\n2907,2014-04-11 02:15:00,40.368524239414285\n2908,2014-04-11 02:20:00,42.36236706420476\n2909,2014-04-11 02:25:00,43.342924088395236\n2910,2014-04-11 02:30:00,41.80646555298571\n2911,2014-04-11 02:35:00,43.164860144776185\n2912,2014-04-11 02:40:00,40.16607258036666\n2913,2014-04-11 02:45:00,41.64926222385714\n2914,2014-04-11 02:50:00,41.50964874094762\n2915,2014-04-11 02:55:00,39.7214633233381\n2916,2014-04-11 03:00:00,41.46945793682857\n2917,2014-04-11 03:05:00,41.17998807311905\n2918,2014-04-11 03:10:00,42.390504434909516\n2919,2014-04-11 03:15:00,43.4720691143\n2920,2014-04-11 03:20:00,40.06935482919047\n2921,2014-04-11 03:25:00,41.043536499280954\n2922,2014-04-11 03:30:00,41.51733037817142\n2923,2014-04-11 03:35:00,41.569253416861905\n2924,2014-04-11 03:40:00,42.85519126435238\n2925,2014-04-11 03:45:00,41.53697552044286\n2926,2014-04-11 03:50:00,39.87947853913333\n2927,2014-04-11 03:55:00,42.618690187923804\n2928,2014-04-11 04:00:00,43.32503306631428\n2929,2014-04-11 04:05:00,41.84877361210476\n2930,2014-04-11 04:10:00,42.12502932489524\n2931,2014-04-11 04:15:00,40.45978147018571\n2932,2014-04-11 04:20:00,40.698059969176185\n2933,2014-04-11 04:25:00,40.76359762316666\n2934,2014-04-11 04:30:00,41.553325042357145\n2935,2014-04-11 04:35:00,43.55037850264762\n2936,2014-04-11 04:40:00,41.932377162138096\n2937,2014-04-11 04:45:00,40.62106915222857\n2938,2014-04-11 04:50:00,40.92446999111905\n2939,2014-04-11 04:55:00,41.40361964270952\n2940,2014-04-11 05:00:00,42.3680359028\n2941,2014-04-11 05:05:00,41.642573088190474\n2942,2014-04-11 05:10:00,41.459660329080954\n2943,2014-04-11 05:15:00,42.156235830171426\n2944,2014-04-11 05:20:00,40.8721018845619\n2945,2014-04-11 05:25:00,40.227815471252384\n2946,2014-04-11 05:30:00,40.017300116442854\n2947,2014-04-11 05:35:00,40.932119987233335\n2948,2014-04-11 05:40:00,40.30089194612381\n2949,2014-04-11 05:45:00,41.287326839814284\n2950,2014-04-11 05:50:00,43.04113892330476\n2951,2014-04-11 05:55:00,42.82202255999523\n2952,2014-04-11 06:00:00,42.40799620548571\n2953,2014-04-11 06:05:00,43.38172716597619\n2954,2014-04-11 06:10:00,41.10743716486667\n2955,2014-04-11 06:15:00,43.526822154957145\n2956,2014-04-11 06:20:00,41.59100429774762\n2957,2014-04-11 06:25:00,41.6050613683381\n2958,2014-04-11 06:30:00,41.630335025928574\n2959,2014-04-11 06:35:00,40.40874651261905\n2960,2014-04-11 06:40:00,43.925771517109524\n2961,2014-04-11 06:45:00,40.5852771113\n2962,2014-04-11 06:50:00,41.40223337409047\n2963,2014-04-11 06:55:00,41.32333223368096\n2964,2014-04-11 07:00:00,40.35228915987143\n2965,2014-04-11 07:05:00,40.670052425161906\n2966,2014-04-11 07:10:00,40.24788572565238\n2967,2014-04-11 07:15:00,41.245510831342855\n2968,2014-04-11 07:20:00,43.549961029433334\n2969,2014-04-11 07:25:00,41.44854263242381\n2970,2014-04-11 07:30:00,40.592981614014285\n2971,2014-04-11 07:35:00,42.68843023540476\n2972,2014-04-11 07:40:00,44.09949888629524\n2973,2014-04-11 07:45:00,41.04983087238571\n2974,2014-04-11 07:50:00,41.24626021197619\n2975,2014-04-11 07:55:00,44.02280488376667\n2976,2014-04-11 08:00:00,40.85796229305714\n2977,2014-04-11 08:05:00,42.195153888847614\n2978,2014-04-11 08:10:00,41.116346627338096\n2979,2014-04-11 08:15:00,43.89458616302856\n2980,2014-04-11 08:20:00,44.09870310591904\n2981,2014-04-11 08:25:00,43.43885090830952\n2982,2014-04-11 08:30:00,41.446635263299996\n2983,2014-04-11 08:35:00,41.808890377290474\n2984,2014-04-11 08:40:00,41.17160368708095\n2985,2014-04-11 08:45:00,43.77285329657143\n2986,2014-04-11 08:50:00,43.8754950155619\n2987,2014-04-11 08:55:00,41.90018502995238\n2988,2014-04-11 09:00:00,150.11416299114285\n2989,2014-04-11 09:05:00,137.94530219133333\n2990,2014-04-11 09:10:00,144.6334341385238\n2991,2014-04-11 09:15:00,149.5156421317143\n2992,2014-04-11 09:20:00,143.41990210090475\n2993,2014-04-11 09:25:00,142.73781347509524\n2994,2014-04-11 09:30:00,133.9015607222857\n2995,2014-04-11 09:35:00,153.8307040924762\n2996,2014-04-11 09:40:00,155.94723944466665\n2997,2014-04-11 09:45:00,157.94180267585713\n2998,2014-04-11 09:50:00,151.7444779690476\n2999,2014-04-11 09:55:00,147.5240374422381\n3000,2014-04-11 10:00:00,160.43990826542858\n3001,2014-04-11 10:05:00,181.58858187161903\n3002,2014-04-11 10:10:00,169.73555219080953\n3003,2014-04-11 10:15:00,172.389971935\n3004,2014-04-11 10:20:00,172.43367292619047\n3005,2014-04-11 10:25:00,177.15712295738098\n3006,2014-04-11 10:30:00,152.9661881535714\n3007,2014-04-11 10:35:00,159.0718632997619\n3008,2014-04-11 10:40:00,171.97481702595238\n3009,2014-04-11 10:45:00,178.63181339514284\n3010,2014-04-11 10:50:00,172.56324445733333\n3011,2014-04-11 10:55:00,164.6979816115238\n3012,2014-04-11 11:00:00,167.24617561871426\n3013,2014-04-11 11:05:00,178.46710182490474\n3014,2014-04-11 11:10:00,178.57254871109524\n3015,2014-04-11 11:15:00,174.58250742728572\n3016,2014-04-11 11:20:00,165.1878617724762\n3017,2014-04-11 11:25:00,184.07412901666666\n3018,2014-04-11 11:30:00,172.96096437885714\n3019,2014-04-11 11:35:00,180.07714589604763\n3020,2014-04-11 11:40:00,162.9189098412381\n3021,2014-04-11 11:45:00,166.79134174542855\n3022,2014-04-11 11:50:00,182.60459199961903\n3023,2014-04-11 11:55:00,158.0493481598095\n3024,2014-04-11 12:00:00,172.660947021\n3025,2014-04-11 12:05:00,171.7513659231905\n3026,2014-04-11 12:10:00,179.83333544338097\n3027,2014-04-11 12:15:00,165.78020776557142\n3028,2014-04-11 12:20:00,163.9054533807619\n3029,2014-04-11 12:25:00,185.09546041795238\n3030,2014-04-11 12:30:00,174.48494929414287\n3031,2014-04-11 12:35:00,160.50121529533334\n3032,2014-04-11 12:40:00,163.1553783715238\n3033,2014-04-11 12:45:00,187.30299490671428\n3034,2014-04-11 12:50:00,163.24733731490474\n3035,2014-04-11 12:55:00,175.68351479709523\n3036,2014-04-11 13:00:00,170.1521926182857\n3037,2014-04-11 13:05:00,184.1198908514762\n3038,2014-04-11 13:10:00,180.21550143266666\n3039,2014-04-11 13:15:00,175.47774239485716\n3040,2014-04-11 13:20:00,157.90368772504763\n3041,2014-04-11 13:25:00,183.9755844242381\n3042,2014-04-11 13:30:00,170.93281306342857\n3043,2014-04-11 13:35:00,185.54350791161903\n3044,2014-04-11 13:40:00,172.47341702480952\n3045,2014-04-11 13:45:00,178.439768728\n3046,2014-04-11 13:50:00,159.70445344519047\n3047,2014-04-11 13:55:00,179.98204089638097\n3048,2014-04-11 14:00:00,167.81040194257142\n3049,2014-04-11 14:05:00,168.2187096737619\n3050,2014-04-11 14:10:00,161.24544227895237\n3051,2014-04-11 14:15:00,162.09887494614287\n3052,2014-04-11 14:20:00,163.27330791633332\n3053,2014-04-11 14:25:00,167.5539247315238\n3054,2014-04-11 14:30:00,184.47333943071428\n3055,2014-04-11 14:35:00,168.77036112390476\n3056,2014-04-11 14:40:00,179.46028309509524\n3057,2014-04-11 14:45:00,160.2203351392857\n3058,2014-04-11 14:50:00,175.47746858047617\n3059,2014-04-11 14:55:00,172.20886373766666\n3060,2014-04-11 15:00:00,187.10477248685714\n3061,2014-04-11 15:05:00,183.1597514970476\n3062,2014-04-11 15:10:00,171.4259823012381\n3063,2014-04-11 15:15:00,181.04270592542855\n3064,2014-04-11 15:20:00,163.58721944361903\n3065,2014-04-11 15:25:00,174.67346459980953\n3066,2014-04-11 15:30:00,160.04954923399998\n3067,2014-04-11 15:35:00,168.26099800019048\n3068,2014-04-11 15:40:00,164.60167363438097\n3069,2014-04-11 15:45:00,179.40037903557143\n3070,2014-04-11 15:50:00,172.5433219387619\n3071,2014-04-11 15:55:00,180.38006918995237\n3072,2014-04-11 16:00:00,173.31567216814287\n3073,2014-04-11 16:05:00,160.45881132133334\n3074,2014-04-11 16:10:00,179.9327048355238\n3075,2014-04-11 16:15:00,182.87598722571428\n3076,2014-04-11 16:20:00,184.99248187990474\n3077,2014-04-11 16:25:00,175.05376600509524\n3078,2014-04-11 16:30:00,180.50899680528573\n3079,2014-04-11 16:35:00,180.4702067204762\n3080,2014-04-11 16:40:00,162.58884957366666\n3081,2014-04-11 16:45:00,162.85041731585713\n3082,2014-04-11 16:50:00,160.05780855504761\n3083,2014-04-11 16:55:00,167.5360763362381\n3084,2014-04-11 17:00:00,172.15161999642856\n3085,2014-04-11 17:05:00,187.89073144261903\n3086,2014-04-11 17:10:00,170.8910441448095\n3087,2014-04-11 17:15:00,179.755958083\n3088,2014-04-11 17:20:00,178.77803213019047\n3089,2014-04-11 17:25:00,164.11802683438097\n3090,2014-04-11 17:30:00,159.7462252895714\n3091,2014-04-11 17:35:00,174.3786472787619\n3092,2014-04-11 17:40:00,179.01505092395237\n3093,2014-04-11 17:45:00,187.96087337014285\n3094,2014-04-11 17:50:00,168.77910022433335\n3095,2014-04-11 17:55:00,184.9191388355238\n3096,2014-04-11 18:00:00,67.94947988201429\n3097,2014-04-11 18:05:00,70.78572866320476\n3098,2014-04-11 18:10:00,69.95450862529523\n3099,2014-04-11 18:15:00,64.94542849078572\n3100,2014-04-11 18:20:00,65.1866375290762\n3101,2014-04-11 18:25:00,64.66393425606667\n3102,2014-04-11 18:30:00,67.89201775305715\n3103,2014-04-11 18:35:00,71.34915330124763\n3104,2014-04-11 18:40:00,66.0845752792381\n3105,2014-04-11 18:45:00,70.07651228672856\n3106,2014-04-11 18:50:00,67.16732187411904\n3107,2014-04-11 18:55:00,71.84987756170952\n3108,2014-04-11 19:00:00,49.828913769699994\n3109,2014-04-11 19:05:00,49.72052682259047\n3110,2014-04-11 19:10:00,48.46503918628095\n3111,2014-04-11 19:15:00,47.26153509967143\n3112,2014-04-11 19:20:00,49.91435705876191\n3113,2014-04-11 19:25:00,46.780146717852375\n3114,2014-04-11 19:30:00,47.31002870094285\n3115,2014-04-11 19:35:00,46.78417727823333\n3116,2014-04-11 19:40:00,49.2625402627238\n3117,2014-04-11 19:45:00,49.330591105814285\n3118,2014-04-11 19:50:00,49.16805238190476\n3119,2014-04-11 19:55:00,47.98147401359524\n3120,2014-04-11 20:00:00,42.571804822685706\n3121,2014-04-11 20:05:00,45.99192722587619\n3122,2014-04-11 20:10:00,44.30169802996666\n3123,2014-04-11 20:15:00,43.88514561645714\n3124,2014-04-11 20:20:00,44.65782222784762\n3125,2014-04-11 20:25:00,42.99874974943809\n3126,2014-04-11 20:30:00,42.752693340528566\n3127,2014-04-11 20:35:00,43.90881865711905\n3128,2014-04-11 20:40:00,43.16595370110952\n3129,2014-04-11 20:45:00,43.2452230542\n3130,2014-04-11 20:50:00,45.980378242490474\n3131,2014-04-11 20:55:00,44.465565034180955\n3132,2014-04-11 21:00:00,43.44475989277143\n3133,2014-04-11 21:05:00,44.28481252026191\n3134,2014-04-11 21:10:00,45.351429121052384\n3135,2014-04-11 21:15:00,41.966554477042855\n3136,2014-04-11 21:20:00,44.88934652613334\n3137,2014-04-11 21:25:00,43.88834561862381\n3138,2014-04-11 21:30:00,42.12615608071428\n3139,2014-04-11 21:35:00,42.74381334610476\n3140,2014-04-11 21:40:00,43.49980703279524\n3141,2014-04-11 21:45:00,44.35119715128572\n3142,2014-04-11 21:50:00,42.54569660917619\n3143,2014-04-11 21:55:00,43.73438278006667\n3144,2014-04-11 22:00:00,44.17468009835714\n3145,2014-04-11 22:05:00,43.23643412444761\n3146,2014-04-11 22:10:00,44.9044622928381\n3147,2014-04-11 22:15:00,44.93768885962857\n3148,2014-04-11 22:20:00,43.34674004791905\n3149,2014-04-11 22:25:00,45.36729708400952\n3150,2014-04-11 22:30:00,41.7779092181\n3151,2014-04-11 22:35:00,41.495857945290474\n3152,2014-04-11 22:40:00,43.01566114678096\n3153,2014-04-11 22:45:00,43.90665077987143\n3154,2014-04-11 22:50:00,44.0267374580619\n3155,2014-04-11 22:55:00,43.421889333452384\n3156,2014-04-11 23:00:00,41.989371912042856\n3157,2014-04-11 23:05:00,42.17934512433333\n3158,2014-04-11 23:10:00,44.9145217146238\n3159,2014-04-11 23:15:00,44.98504101221428\n3160,2014-04-11 23:20:00,44.21610827610476\n3161,2014-04-11 23:25:00,44.18481038149524\n3162,2014-04-11 23:30:00,43.92599676508571\n3163,2014-04-11 23:35:00,42.35375539797619\n3164,2014-04-11 23:40:00,43.262870072666665\n3165,2014-04-11 23:45:00,44.34133171295714\n3166,2014-04-11 23:50:00,43.71393869054762\n3167,2014-04-11 23:55:00,41.645828345238094\n3168,2014-04-12 00:00:00,45.38565579832857\n3169,2014-04-12 00:05:00,44.958133257919044\n3170,2014-04-12 00:10:00,42.62848958020952\n3171,2014-04-12 00:15:00,44.0595857407\n3172,2014-04-12 00:20:00,45.29414801109047\n3173,2014-04-12 00:25:00,41.99267500088095\n3174,2014-04-12 00:30:00,43.628189351771425\n3175,2014-04-12 00:35:00,43.448484008161905\n3176,2014-04-12 00:40:00,43.27177240205238\n3177,2014-04-12 00:45:00,44.980747292742855\n3178,2014-04-12 00:50:00,43.16841792013334\n3179,2014-04-12 00:55:00,41.9079271425238\n3180,2014-04-12 01:00:00,41.92406525441429\n3181,2014-04-12 01:05:00,41.83913318800476\n3182,2014-04-12 01:10:00,43.31217692559524\n3183,2014-04-12 01:15:00,44.556660825085714\n3184,2014-04-12 01:20:00,42.50536603817619\n3185,2014-04-12 01:25:00,44.28379074836667\n3186,2014-04-12 01:30:00,44.45371103125714\n3187,2014-04-12 01:35:00,42.733606115147616\n3188,2014-04-12 01:40:00,44.122468719438096\n3189,2014-04-12 01:45:00,44.46715193152857\n3190,2014-04-12 01:50:00,43.601573538819046\n3191,2014-04-12 01:55:00,43.08942591290952\n3192,2014-04-12 02:00:00,44.226606206300005\n3193,2014-04-12 02:05:00,45.66882882549047\n3194,2014-04-12 02:10:00,43.47224658988095\n3195,2014-04-12 02:15:00,43.33926181367143\n3196,2014-04-12 02:20:00,43.63682951446191\n3197,2014-04-12 02:25:00,42.09207595475238\n3198,2014-04-12 02:30:00,44.00729597584285\n3199,2014-04-12 02:35:00,43.11687288223334\n3200,2014-04-12 02:40:00,42.295212298823806\n3201,2014-04-12 02:45:00,43.68199125021428\n3202,2014-04-12 02:50:00,41.83794070820476\n3203,2014-04-12 02:55:00,43.438986218795236\n3204,2014-04-12 03:00:00,42.26222678598572\n3205,2014-04-12 03:05:00,41.94389700407619\n3206,2014-04-12 03:10:00,45.15206685166666\n3207,2014-04-12 03:15:00,45.52660235595714\n3208,2014-04-12 03:20:00,42.699746212447614\n3209,2014-04-12 03:25:00,44.033681150538094\n3210,2014-04-12 03:30:00,42.995761199928566\n3211,2014-04-12 03:35:00,43.86567880231905\n3212,2014-04-12 03:40:00,43.645334807409526\n3213,2014-04-12 03:45:00,42.9824542203\n3214,2014-04-12 03:50:00,44.71526479469047\n3215,2014-04-12 03:55:00,42.42709478968095\n3216,2014-04-12 04:00:00,42.140862557271426\n3217,2014-04-12 04:05:00,45.0067136368619\n3218,2014-04-12 04:10:00,44.607172505852375\n3219,2014-04-12 04:15:00,43.944997353742856\n3220,2014-04-12 04:20:00,43.82949241523333\n3221,2014-04-12 04:25:00,43.955419327523806\n3222,2014-04-12 04:30:00,43.721310590114285\n3223,2014-04-12 04:35:00,43.55222394520476\n3224,2014-04-12 04:40:00,43.98685764959524\n3225,2014-04-12 04:45:00,44.109596398885714\n3226,2014-04-12 04:50:00,44.770585446776195\n3227,2014-04-12 04:55:00,44.85524530956667\n3228,2014-04-12 05:00:00,43.52837346345714\n3229,2014-04-12 05:05:00,43.67945971004762\n3230,2014-04-12 05:10:00,43.527526774138096\n3231,2014-04-12 05:15:00,44.186321665928574\n3232,2014-04-12 05:20:00,43.86103319931905\n3233,2014-04-12 05:25:00,45.61344537630952\n3234,2014-04-12 05:30:00,44.847945067699996\n3235,2014-04-12 05:35:00,45.66456601119047\n3236,2014-04-12 05:40:00,44.91392891858095\n3237,2014-04-12 05:45:00,45.96879002267143\n3238,2014-04-12 05:50:00,44.63520901776191\n3239,2014-04-12 05:55:00,45.95390293365238\n3240,2014-04-12 06:00:00,42.739822418742854\n3241,2014-04-12 06:05:00,42.32449405663333\n3242,2014-04-12 06:10:00,44.438524550323805\n3243,2014-04-12 06:15:00,46.063437108914286\n3244,2014-04-12 06:20:00,43.807325751104756\n3245,2014-04-12 06:25:00,42.99251868689524\n3246,2014-04-12 06:30:00,44.23795151108571\n3247,2014-04-12 06:35:00,44.75442068877619\n3248,2014-04-12 06:40:00,43.42738144876667\n3249,2014-04-12 06:45:00,45.03318457685714\n3250,2014-04-12 06:50:00,46.08200564724762\n3251,2014-04-12 06:55:00,45.77684058203809\n3252,2014-04-12 07:00:00,43.36277006542857\n3253,2014-04-12 07:05:00,43.51076378021905\n3254,2014-04-12 07:10:00,43.69747442160952\n3255,2014-04-12 07:15:00,43.7969611136\n3256,2014-04-12 07:20:00,42.62746847299047\n3257,2014-04-12 07:25:00,45.28148230798095\n3258,2014-04-12 07:30:00,43.70242848297143\n3259,2014-04-12 07:35:00,45.76779181156191\n3260,2014-04-12 07:40:00,45.963714873452375\n3261,2014-04-12 07:45:00,42.36111809434286\n3262,2014-04-12 07:50:00,46.22484561303333\n3263,2014-04-12 07:55:00,45.118364735523805\n3264,2014-04-12 08:00:00,44.367283189714286\n3265,2014-04-12 08:05:00,43.85126519540476\n3266,2014-04-12 08:10:00,44.374667768495236\n3267,2014-04-12 08:15:00,43.60653461018571\n3268,2014-04-12 08:20:00,44.80622744527619\n3269,2014-04-12 08:25:00,42.69483777246666\n3270,2014-04-12 08:30:00,44.814847554457145\n3271,2014-04-12 08:35:00,43.439177019647616\n3272,2014-04-12 08:40:00,42.41577741143809\n3273,2014-04-12 08:45:00,44.56350163612857\n3274,2014-04-12 08:50:00,44.67391007101905\n3275,2014-04-12 08:55:00,44.07383554260952\n3276,2014-04-12 09:00:00,86.5580927627\n3277,2014-04-12 09:05:00,97.73190463429049\n3278,2014-04-12 09:10:00,93.90533993068095\n3279,2014-04-12 09:15:00,87.17102230267143\n3280,2014-04-12 09:20:00,92.55341774646192\n3281,2014-04-12 09:25:00,92.37486107785237\n3282,2014-04-12 09:30:00,86.44110827274287\n3283,2014-04-12 09:35:00,93.88037530233332\n3284,2014-04-12 09:40:00,96.62776283482381\n3285,2014-04-12 09:45:00,95.82847382351429\n3286,2014-04-12 09:50:00,88.40978879450476\n3287,2014-04-12 09:55:00,97.38402363999523\n3288,2014-04-12 10:00:00,99.62054012528571\n3289,2014-04-12 10:05:00,109.00153622157619\n3290,2014-04-12 10:10:00,95.43269507146667\n3291,2014-04-12 10:15:00,101.87256598865714\n3292,2014-04-12 10:20:00,103.60141795284763\n3293,2014-04-12 10:25:00,98.1850176235381\n3294,2014-04-12 10:30:00,106.32074910032857\n3295,2014-04-12 10:35:00,104.08578999831904\n3296,2014-04-12 10:40:00,94.64486799050952\n3297,2014-04-12 10:45:00,103.81313052760001\n3298,2014-04-12 10:50:00,102.00643267439048\n3299,2014-04-12 10:55:00,97.42850416278095\n3300,2014-04-12 11:00:00,111.95795123177143\n3301,2014-04-12 11:05:00,110.39747945126189\n3302,2014-04-12 11:10:00,100.78849476265238\n3303,2014-04-12 11:15:00,104.74908478154285\n3304,2014-04-12 11:20:00,101.18498336643333\n3305,2014-04-12 11:25:00,108.4922582435238\n3306,2014-04-12 11:30:00,110.96220539931429\n3307,2014-04-12 11:35:00,101.88046492630475\n3308,2014-04-12 11:40:00,108.99310713649524\n3309,2014-04-12 11:45:00,104.1152092735857\n3310,2014-04-12 11:50:00,102.50316162957618\n3311,2014-04-12 11:55:00,111.12807780246666\n3312,2014-04-12 12:00:00,104.71313239235714\n3313,2014-04-12 12:05:00,104.03349134154762\n3314,2014-04-12 12:10:00,107.31737778613811\n3315,2014-04-12 12:15:00,100.75351009102857\n3316,2014-04-12 12:20:00,101.77666895711904\n3317,2014-04-12 12:25:00,111.48849762360952\n3318,2014-04-12 12:30:00,107.444549754\n3319,2014-04-12 12:35:00,109.81886340729048\n3320,2014-04-12 12:40:00,100.94856379748096\n3321,2014-04-12 12:45:00,105.31362369577144\n3322,2014-04-12 12:50:00,112.15455136826193\n3323,2014-04-12 12:55:00,101.73144565055237\n3324,2014-04-12 13:00:00,99.28187024854284\n3325,2014-04-12 13:05:00,104.89451766263333\n3326,2014-04-12 13:10:00,102.9333919961238\n3327,2014-04-12 13:15:00,99.2898072337143\n3328,2014-04-12 13:20:00,110.95803484780475\n3329,2014-04-12 13:25:00,112.59984342709524\n3330,2014-04-12 13:30:00,105.85463724978571\n3331,2014-04-12 13:35:00,109.15879972567619\n3332,2014-04-12 13:40:00,110.51570187206667\n3333,2014-04-12 13:45:00,107.99484746825713\n3334,2014-04-12 13:50:00,97.49559484564762\n3335,2014-04-12 13:55:00,99.31825048723809\n3336,2014-04-12 14:00:00,97.95374511012857\n3337,2014-04-12 14:05:00,96.98347916631903\n3338,2014-04-12 14:10:00,101.72856105870952\n3339,2014-04-12 14:15:00,103.1176880383\n3340,2014-04-12 14:20:00,100.70402508269046\n3341,2014-04-12 14:25:00,97.88879970538095\n3342,2014-04-12 14:30:00,105.34001794707143\n3343,2014-04-12 14:35:00,101.2429551148619\n3344,2014-04-12 14:40:00,109.61347950225237\n3345,2014-04-12 14:45:00,97.01377261874285\n3346,2014-04-12 14:50:00,110.37216309313332\n3347,2014-04-12 14:55:00,112.1751434218238\n3348,2014-04-12 15:00:00,108.36807409781429\n3349,2014-04-12 15:05:00,108.65565591840476\n3350,2014-04-12 15:10:00,111.86175762859523\n3351,2014-04-12 15:15:00,100.2774529657857\n3352,2014-04-12 15:20:00,112.8526813165762\n3353,2014-04-12 15:25:00,109.32280591396665\n3354,2014-04-12 15:30:00,108.57968567485713\n3355,2014-04-12 15:35:00,102.73950021944762\n3356,2014-04-12 15:40:00,105.7019028303381\n3357,2014-04-12 15:45:00,107.43957154202857\n3358,2014-04-12 15:50:00,106.90981834401906\n3359,2014-04-12 15:55:00,108.27151425380951\n3360,2014-04-12 16:00:00,98.3179670545\n3361,2014-04-12 16:05:00,102.69766623599048\n3362,2014-04-12 16:10:00,103.95872964538096\n3363,2014-04-12 16:15:00,101.19224394807142\n3364,2014-04-12 16:20:00,99.7916546859619\n3365,2014-04-12 16:25:00,99.25989955175238\n3366,2014-04-12 16:30:00,102.90662763794285\n3367,2014-04-12 16:35:00,104.94699714383333\n3368,2014-04-12 16:40:00,98.06700667722382\n3369,2014-04-12 16:45:00,112.2101264840143\n3370,2014-04-12 16:50:00,109.31813617940476\n3371,2014-04-12 16:55:00,108.77531291729524\n3372,2014-04-12 17:00:00,99.85502540408571\n3373,2014-04-12 17:05:00,106.75750712087618\n3374,2014-04-12 17:10:00,105.57973491296667\n3375,2014-04-12 17:15:00,112.83107499115714\n3376,2014-04-12 17:20:00,109.08176369864762\n3377,2014-04-12 17:25:00,106.33864704923809\n3378,2014-04-12 17:30:00,110.74689835952857\n3379,2014-04-12 17:35:00,99.62284878051905\n3380,2014-04-12 17:40:00,97.39224625740951\n3381,2014-04-12 17:45:00,108.1999514458\n3382,2014-04-12 17:50:00,98.73664558799047\n3383,2014-04-12 17:55:00,99.01804083488095\n3384,2014-04-12 18:00:00,58.74452163307143\n3385,2014-04-12 18:05:00,55.71742904516191\n3386,2014-04-12 18:10:00,58.01668585855238\n3387,2014-04-12 18:15:00,59.87229052724285\n3388,2014-04-12 18:20:00,56.03376441733333\n3389,2014-04-12 18:25:00,55.405490623223805\n3390,2014-04-12 18:30:00,54.705211081114285\n3391,2014-04-12 18:35:00,54.86560818510476\n3392,2014-04-12 18:40:00,54.43631488249524\n3393,2014-04-12 18:45:00,54.60644130148571\n3394,2014-04-12 18:50:00,56.81779949837619\n3395,2014-04-12 18:55:00,56.11394703096666\n3396,2014-04-12 19:00:00,48.59324831145715\n3397,2014-04-12 19:05:00,49.33397892824762\n3398,2014-04-12 19:10:00,48.9585207465381\n3399,2014-04-12 19:15:00,47.82743224492857\n3400,2014-04-12 19:20:00,45.91655859721905\n3401,2014-04-12 19:25:00,48.64481567550952\n3402,2014-04-12 19:30:00,47.0979714917\n3403,2014-04-12 19:35:00,45.86365311399047\n3404,2014-04-12 19:40:00,49.26162914368095\n3405,2014-04-12 19:45:00,47.01003023647142\n3406,2014-04-12 19:50:00,46.480015514861904\n3407,2014-04-12 19:55:00,49.413806310352385\n3408,2014-04-12 20:00:00,47.484282916742856\n3409,2014-04-12 20:05:00,45.18500764463333\n3410,2014-04-12 20:10:00,45.25729018432381\n3411,2014-04-12 20:15:00,46.185622485014285\n3412,2014-04-12 20:20:00,46.82308086330476\n3413,2014-04-12 20:25:00,44.085004144795235\n3414,2014-04-12 20:30:00,46.26412108378571\n3415,2014-04-12 20:35:00,47.743976895476194\n3416,2014-04-12 20:40:00,44.922203035466666\n3417,2014-04-12 20:45:00,47.57866314595714\n3418,2014-04-12 20:50:00,47.75543687494762\n3419,2014-04-12 20:55:00,44.9734411742381\n3420,2014-04-12 21:00:00,46.56411665912857\n3421,2014-04-12 21:05:00,44.49995351451905\n3422,2014-04-12 21:10:00,46.512316253509525\n3423,2014-04-12 21:15:00,46.7601402965\n3424,2014-04-12 21:20:00,44.55615959389047\n3425,2014-04-12 21:25:00,46.44725377068095\n3426,2014-04-12 21:30:00,46.84148193897143\n3427,2014-04-12 21:35:00,45.0261120597619\n3428,2014-04-12 21:40:00,44.266383332352376\n3429,2014-04-12 21:45:00,43.96941680094285\n3430,2014-04-12 21:50:00,45.91980742663333\n3431,2014-04-12 21:55:00,47.545845716823806\n3432,2014-04-12 22:00:00,46.847955684614284\n3433,2014-04-12 22:05:00,45.305466932104764\n3434,2014-04-12 22:10:00,45.716419463895235\n3435,2014-04-12 22:15:00,44.69450063358571\n3436,2014-04-12 22:20:00,44.235645823676194\n3437,2014-04-12 22:25:00,45.520372481466666\n3438,2014-04-12 22:30:00,45.45342324375714\n3439,2014-04-12 22:35:00,45.69480163144762\n3440,2014-04-12 22:40:00,47.4273951963381\n3441,2014-04-12 22:45:00,46.037858719928565\n3442,2014-04-12 22:50:00,46.052812547919046\n3443,2014-04-12 22:55:00,44.14743018120952\n3444,2014-04-12 23:00:00,47.615176766\n3445,2014-04-12 23:05:00,46.72786979599047\n3446,2014-04-12 23:10:00,47.15282401878095\n3447,2014-04-12 23:15:00,45.30829725667142\n3448,2014-04-12 23:20:00,45.66711592036191\n3449,2014-04-12 23:25:00,45.754394575952375\n3450,2014-04-12 23:30:00,44.44962607704285\n3451,2014-04-12 23:35:00,46.439025484233326\n3452,2014-04-12 23:40:00,47.3005801880238\n3453,2014-04-12 23:45:00,44.350369282514286\n3454,2014-04-12 23:50:00,44.048200146504755\n3455,2014-04-12 23:55:00,46.66374381029524\n3456,2014-04-13 00:00:00,44.80709304098571\n3457,2014-04-13 00:05:00,46.21717635697619\n3458,2014-04-13 00:10:00,46.51220001866666\n3459,2014-04-13 00:15:00,45.024250197157144\n3460,2014-04-13 00:20:00,125.74404761904762\n3461,2014-04-13 00:25:00,45.95144402373809\n3462,2014-04-13 00:30:00,47.23492620322857\n3463,2014-04-13 00:35:00,46.81954325781905\n3464,2014-04-13 00:40:00,47.24811205190952\n3465,2014-04-13 00:45:00,43.8618955285\n3466,2014-04-13 00:50:00,44.76271551919048\n3467,2014-04-13 00:55:00,44.15616271418095\n3468,2014-04-13 01:00:00,45.57190349737142\n3469,2014-04-13 01:05:00,47.370852391261906\n3470,2014-04-13 01:10:00,45.688613430052385\n3471,2014-04-13 01:15:00,47.22474503544285\n3472,2014-04-13 01:20:00,45.14204628543333\n3473,2014-04-13 01:25:00,45.19905410072381\n3474,2014-04-13 01:30:00,47.43046120701429\n3475,2014-04-13 01:35:00,45.55892334790476\n3476,2014-04-13 01:40:00,47.022157189295235\n3477,2014-04-13 01:45:00,44.81710990578571\n3478,2014-04-13 01:50:00,47.673179509176194\n3479,2014-04-13 01:55:00,46.18372965276666\n3480,2014-04-13 02:00:00,46.93015141715715\n3481,2014-04-13 02:05:00,44.25836041824762\n3482,2014-04-13 02:10:00,45.8783949985381\n3483,2014-04-13 02:15:00,47.51933256232857\n3484,2014-04-13 02:20:00,47.430773563819045\n3485,2014-04-13 02:25:00,44.117315352709525\n3486,2014-04-13 02:30:00,45.152293876499996\n3487,2014-04-13 02:35:00,45.718220502090475\n3488,2014-04-13 02:40:00,44.64144020978095\n3489,2014-04-13 02:45:00,46.87981467257143\n3490,2014-04-13 02:50:00,44.7053098871619\n3491,2014-04-13 02:55:00,45.36126115845238\n3492,2014-04-13 03:00:00,46.63526540454285\n3493,2014-04-13 03:05:00,45.91794071143333\n3494,2014-04-13 03:10:00,46.95130796402381\n3495,2014-04-13 03:15:00,47.849295890614286\n3496,2014-04-13 03:20:00,44.47809151280476\n3497,2014-04-13 03:25:00,46.857616103695236\n3498,2014-04-13 03:30:00,44.948162336785714\n3499,2014-04-13 03:35:00,45.69213310007619\n3500,2014-04-13 03:40:00,44.17311756986666\n3501,2014-04-13 03:45:00,44.59273667205714\n3502,2014-04-13 03:50:00,45.335656775247614\n3503,2014-04-13 03:55:00,45.431931316438096\n3504,2014-04-13 04:00:00,47.66976943722857\n3505,2014-04-13 04:05:00,47.04612068471904\n3506,2014-04-13 04:10:00,47.975041396509525\n3507,2014-04-13 04:15:00,46.4900360413\n3508,2014-04-13 04:20:00,45.06804540459048\n3509,2014-04-13 04:25:00,45.419251072080954\n3510,2014-04-13 04:30:00,45.39541512177142\n3511,2014-04-13 04:35:00,45.4294892154619\n3512,2014-04-13 04:40:00,46.82280907335238\n3513,2014-04-13 04:45:00,46.26162456954285\n3514,2014-04-13 04:50:00,45.68753004563333\n3515,2014-04-13 04:55:00,44.749632884423804\n3516,2014-04-13 05:00:00,44.24927093751428\n3517,2014-04-13 05:05:00,45.04349347230476\n3518,2014-04-13 05:10:00,44.60548085399523\n3519,2014-04-13 05:15:00,47.32481583768571\n3520,2014-04-13 05:20:00,44.640468021776186\n3521,2014-04-13 05:25:00,47.094829615866665\n3522,2014-04-13 05:30:00,45.74799190195714\n3523,2014-04-13 05:35:00,44.50631117804762\n3524,2014-04-13 05:40:00,47.4711582929381\n3525,2014-04-13 05:45:00,46.54620085232857\n3526,2014-04-13 05:50:00,45.17816509911905\n3527,2014-04-13 05:55:00,47.82128422110952\n3528,2014-04-13 06:00:00,44.4310332555\n3529,2014-04-13 06:05:00,45.06471890899047\n3530,2014-04-13 06:10:00,47.27306866358095\n3531,2014-04-13 06:15:00,47.109833149771426\n3532,2014-04-13 06:20:00,45.43684867966191\n3533,2014-04-13 06:25:00,44.535301882352385\n3534,2014-04-13 06:30:00,47.726955146042854\n3535,2014-04-13 06:35:00,45.55687388563334\n3536,2014-04-13 06:40:00,45.092377469223806\n3537,2014-04-13 06:45:00,46.381211575114285\n3538,2014-04-13 06:50:00,47.965313559004755\n3539,2014-04-13 06:55:00,44.50603154949523\n3540,2014-04-13 07:00:00,47.40250206638571\n3541,2014-04-13 07:05:00,46.636619102276185\n3542,2014-04-13 07:10:00,46.055963132866665\n3543,2014-04-13 07:15:00,47.337928919257145\n3544,2014-04-13 07:20:00,48.23234531684762\n3545,2014-04-13 07:25:00,45.29331293993809\n3546,2014-04-13 07:30:00,44.95851803172857\n3547,2014-04-13 07:35:00,48.04289602851905\n3548,2014-04-13 07:40:00,47.07462183360953\n3549,2014-04-13 07:45:00,46.1581940862\n3550,2014-04-13 07:50:00,46.70672875729048\n3551,2014-04-13 07:55:00,47.40358657308095\n3552,2014-04-13 08:00:00,47.52069902337143\n3553,2014-04-13 08:05:00,48.1155886280619\n3554,2014-04-13 08:10:00,46.15082353655238\n3555,2014-04-13 08:15:00,45.62453649724286\n3556,2014-04-13 08:20:00,47.01699040053333\n3557,2014-04-13 08:25:00,46.1286854066238\n3558,2014-04-13 08:30:00,46.85160810151429\n3559,2014-04-13 08:35:00,46.16059795570476\n3560,2014-04-13 08:40:00,45.10007838479524\n3561,2014-04-13 08:45:00,46.37324272088571\n3562,2014-04-13 08:50:00,47.26664747827619\n3563,2014-04-13 08:55:00,47.70755189736666\n3564,2014-04-13 09:00:00,94.42709450725714\n3565,2014-04-13 09:05:00,89.97253292594762\n3566,2014-04-13 09:10:00,93.37249094643809\n3567,2014-04-13 09:15:00,98.43377600362857\n3568,2014-04-13 09:20:00,93.36250512801905\n3569,2014-04-13 09:25:00,97.22787831680952\n3570,2014-04-13 09:30:00,94.6606060708\n3571,2014-04-13 09:35:00,91.05057497769047\n3572,2014-04-13 09:40:00,98.60502786148095\n3573,2014-04-13 09:45:00,88.93012440397143\n3574,2014-04-13 09:50:00,94.9307697502619\n3575,2014-04-13 09:55:00,90.64062044665238\n3576,2014-04-13 10:00:00,97.48800141214286\n3577,2014-04-13 10:05:00,104.26011803683333\n3578,2014-04-13 10:10:00,104.21522846962381\n3579,2014-04-13 10:15:00,107.44056627971429\n3580,2014-04-13 10:20:00,108.03543551810476\n3581,2014-04-13 10:25:00,107.77966914259524\n3582,2014-04-13 10:30:00,102.84813724918571\n3583,2014-04-13 10:35:00,106.30305168827618\n3584,2014-04-13 10:40:00,105.46085683246667\n3585,2014-04-13 10:45:00,103.05674559775714\n3586,2014-04-13 10:50:00,105.79028863284762\n3587,2014-04-13 10:55:00,111.2302751417381\n3588,2014-04-13 11:00:00,101.33221067092856\n3589,2014-04-13 11:05:00,112.67726845901905\n3590,2014-04-13 11:10:00,99.12946601820951\n3591,2014-04-13 11:15:00,103.191372042\n3592,2014-04-13 11:20:00,102.87685251009049\n3593,2014-04-13 11:25:00,108.26334162808095\n3594,2014-04-13 11:30:00,100.39607306167143\n3595,2014-04-13 11:35:00,112.3493683234619\n3596,2014-04-13 11:40:00,111.50123398115238\n3597,2014-04-13 11:45:00,108.70184765344288\n3598,2014-04-13 11:50:00,105.62944691413333\n3599,2014-04-13 11:55:00,113.18400670372381\n3600,2014-04-13 12:00:00,111.9753088274143\n3601,2014-04-13 12:05:00,106.68621028040477\n3602,2014-04-13 12:10:00,109.93069294099524\n3603,2014-04-13 12:15:00,107.7816298940857\n3604,2014-04-13 12:20:00,108.12486351367619\n3605,2014-04-13 12:25:00,104.02577903716667\n3606,2014-04-13 12:30:00,106.12843879245716\n3607,2014-04-13 12:35:00,99.99984058024762\n3608,2014-04-13 12:40:00,104.4695560670381\n3609,2014-04-13 12:45:00,109.88617490972857\n3610,2014-04-13 12:50:00,114.00687378791906\n3611,2014-04-13 12:55:00,114.17169449700951\n3612,2014-04-13 13:00:00,107.7471519302\n3613,2014-04-13 13:05:00,108.56878707569047\n3614,2014-04-13 13:10:00,101.84342675108095\n3615,2014-04-13 13:15:00,110.00230117497144\n3616,2014-04-13 13:20:00,100.0177512577619\n3617,2014-04-13 13:25:00,103.44880016075237\n3618,2014-04-13 13:30:00,109.59360989844285\n3619,2014-04-13 13:35:00,103.87357384713333\n3620,2014-04-13 13:40:00,99.71460238332381\n3621,2014-04-13 13:45:00,112.23141645291429\n3622,2014-04-13 13:50:00,103.89621320880475\n3623,2014-04-13 13:55:00,99.94900651179522\n3624,2014-04-13 14:00:00,100.15738290898571\n3625,2014-04-13 14:05:00,102.99621762037619\n3626,2014-04-13 14:10:00,101.82382910596667\n3627,2014-04-13 14:15:00,111.37135836485713\n3628,2014-04-13 14:20:00,104.13728931234762\n3629,2014-04-13 14:25:00,111.8725466495381\n3630,2014-04-13 14:30:00,101.78687502282857\n3631,2014-04-13 14:35:00,106.89860138911905\n3632,2014-04-13 14:40:00,110.02841924810951\n3633,2014-04-13 14:45:00,109.4591469329\n3634,2014-04-13 14:50:00,108.65284336769048\n3635,2014-04-13 14:55:00,113.83911032028095\n3636,2014-04-13 15:00:00,102.70924749037144\n3637,2014-04-13 15:05:00,106.9597521408619\n3638,2014-04-13 15:10:00,113.21150620085238\n3639,2014-04-13 15:15:00,100.32148994214285\n3640,2014-04-13 15:20:00,99.97684584093334\n3641,2014-04-13 15:25:00,102.82288337522381\n3642,2014-04-13 15:30:00,109.22576536621429\n3643,2014-04-13 15:35:00,103.26299766760475\n3644,2014-04-13 15:40:00,102.15621295819524\n3645,2014-04-13 15:45:00,106.46061108798571\n3646,2014-04-13 15:50:00,108.9447598420762\n3647,2014-04-13 15:55:00,103.11161060046666\n3648,2014-04-13 16:00:00,103.95376865315714\n3649,2014-04-13 16:05:00,108.96708940744762\n3650,2014-04-13 16:10:00,114.2893855539381\n3651,2014-04-13 16:15:00,109.96088724232857\n3652,2014-04-13 16:20:00,111.69892305411905\n3653,2014-04-13 16:25:00,105.04887153150952\n3654,2014-04-13 16:30:00,103.54342314649999\n3655,2014-04-13 16:35:00,106.46307217229048\n3656,2014-04-13 16:40:00,112.11634317668096\n3657,2014-04-13 16:45:00,106.51046343967143\n3658,2014-04-13 16:50:00,112.7647041939619\n3659,2014-04-13 16:55:00,115.04488545695239\n3660,2014-04-13 17:00:00,100.38454141834285\n3661,2014-04-13 17:05:00,99.96611790363333\n3662,2014-04-13 17:10:00,101.64043048902381\n3663,2014-04-13 17:15:00,105.40434908791428\n3664,2014-04-13 17:20:00,101.35855165510476\n3665,2014-04-13 17:25:00,113.19994388259525\n3666,2014-04-13 17:30:00,99.64709794048571\n3667,2014-04-13 17:35:00,104.33688006357619\n3668,2014-04-13 17:40:00,102.24675195576665\n3669,2014-04-13 17:45:00,114.20370305395714\n3670,2014-04-13 17:50:00,110.01821193594762\n3671,2014-04-13 17:55:00,113.90643894693812\n3672,2014-04-13 18:00:00,62.344325593028564\n3673,2014-04-13 18:05:00,59.310291666719046\n3674,2014-04-13 18:10:00,57.63594599780952\n3675,2014-04-13 18:15:00,57.383608464000005\n3676,2014-04-13 18:20:00,57.577865387490476\n3677,2014-04-13 18:25:00,60.693621720880955\n3678,2014-04-13 18:30:00,56.42491850927143\n3679,2014-04-13 18:35:00,56.502217179461894\n3680,2014-04-13 18:40:00,60.07306093535238\n3681,2014-04-13 18:45:00,60.29755227774285\n3682,2014-04-13 18:50:00,60.45350970193333\n3683,2014-04-13 18:55:00,58.583303052323814\n3684,2014-04-13 19:00:00,51.18134608321428\n3685,2014-04-13 19:05:00,49.96879167790476\n3686,2014-04-13 19:10:00,48.05808012869524\n3687,2014-04-13 19:15:00,51.16403930808571\n3688,2014-04-13 19:20:00,51.87021853277619\n3689,2014-04-13 19:25:00,47.87687822826666\n3690,2014-04-13 19:30:00,49.36860993815715\n3691,2014-04-13 19:35:00,49.80686827414762\n3692,2014-04-13 19:40:00,48.286425958438095\n3693,2014-04-13 19:45:00,51.52501333832857\n3694,2014-04-13 19:50:00,48.918108281019045\n3695,2014-04-13 19:55:00,51.16043648440952\n3696,2014-04-13 20:00:00,48.680393144199996\n3697,2014-04-13 20:05:00,48.389035914390476\n3698,2014-04-13 20:10:00,46.733897829980954\n3699,2014-04-13 20:15:00,46.858322816671425\n3700,2014-04-13 20:20:00,46.1557007470619\n3701,2014-04-13 20:25:00,46.95516026035238\n3702,2014-04-13 20:30:00,47.39157964334285\n3703,2014-04-13 20:35:00,49.39664623583333\n3704,2014-04-13 20:40:00,47.4922679332238\n3705,2014-04-13 20:45:00,49.08989484961428\n3706,2014-04-13 20:50:00,47.80636010330476\n3707,2014-04-13 20:55:00,49.228665584295236\n3708,2014-04-13 21:00:00,49.59951647688571\n3709,2014-04-13 21:05:00,46.64709733407619\n3710,2014-04-13 21:10:00,49.15649002076666\n3711,2014-04-13 21:15:00,48.19724246015714\n3712,2014-04-13 21:20:00,48.99031666294762\n3713,2014-04-13 21:25:00,48.331742103038096\n3714,2014-04-13 21:30:00,47.42426638262857\n3715,2014-04-13 21:35:00,46.644447797719046\n3716,2014-04-13 21:40:00,46.01669505650952\n3717,2014-04-13 21:45:00,47.8950053609\n3718,2014-04-13 21:50:00,49.730409061390475\n3719,2014-04-13 21:55:00,48.72386852358095\n3720,2014-04-13 22:00:00,47.00649059157143\n3721,2014-04-13 22:05:00,49.0152875610619\n3722,2014-04-13 22:10:00,48.789621269852375\n3723,2014-04-13 22:15:00,46.84579750264285\n3724,2014-04-13 22:20:00,45.78289822443333\n3725,2014-04-13 22:25:00,46.20615809912381\n3726,2014-04-13 22:30:00,49.25308789211428\n3727,2014-04-13 22:35:00,49.09739929470476\n3728,2014-04-13 22:40:00,46.93734483469524\n3729,2014-04-13 22:45:00,46.904692560485714\n3730,2014-04-13 22:50:00,48.94476073007619\n3731,2014-04-13 22:55:00,49.53224744746666\n3732,2014-04-13 23:00:00,48.88846054535714\n3733,2014-04-13 23:05:00,48.201533409547615\n3734,2014-04-13 23:10:00,46.757065866338095\n3735,2014-04-13 23:15:00,47.89703000022857\n3736,2014-04-13 23:20:00,46.73530181721905\n3737,2014-04-13 23:25:00,49.041181754909516\n3738,2014-04-13 23:30:00,47.3640975023\n3739,2014-04-13 23:35:00,49.15882562149048\n3740,2014-04-13 23:40:00,47.35756689828095\n3741,2014-04-13 23:45:00,49.13550799397143\n3742,2014-04-13 23:50:00,47.1792451515619\n3743,2014-04-13 23:55:00,47.61402721935238\n3744,2014-04-14 00:00:00,48.31909653454285\n3745,2014-04-14 00:05:00,46.145733789433336\n3746,2014-04-14 00:10:00,49.664852056823804\n3747,2014-04-14 00:15:00,48.173887430214286\n3748,2014-04-14 00:20:00,47.91818482070476\n3749,2014-04-14 00:25:00,49.251921122595235\n3750,2014-04-14 00:30:00,49.364836633885716\n3751,2014-04-14 00:35:00,47.99826780857619\n3752,2014-04-14 00:40:00,49.62571596986666\n3753,2014-04-14 00:45:00,46.183058207157146\n3754,2014-04-14 00:50:00,46.384450788047616\n3755,2014-04-14 00:55:00,48.326141015338095\n3756,2014-04-14 01:00:00,47.362692018628564\n3757,2014-04-14 01:05:00,47.810769712419045\n3758,2014-04-14 01:10:00,47.27362639540952\n3759,2014-04-14 01:15:00,47.587651245800004\n3760,2014-04-14 01:20:00,49.266775864790475\n3761,2014-04-14 01:25:00,48.35753575178096\n3762,2014-04-14 01:30:00,49.980449625671426\n3763,2014-04-14 01:35:00,49.146028696061904\n3764,2014-04-14 01:40:00,47.10061739735238\n3765,2014-04-14 01:45:00,47.070773328042854\n3766,2014-04-14 01:50:00,47.36442641383333\n3767,2014-04-14 01:55:00,49.4013117321238\n3768,2014-04-14 02:00:00,46.14486488831429\n3769,2014-04-14 02:05:00,46.96387987740476\n3770,2014-04-14 02:10:00,49.670268919495236\n3771,2014-04-14 02:15:00,48.61762145858572\n3772,2014-04-14 02:20:00,46.97286457247619\n3773,2014-04-14 02:25:00,46.94949653956667\n3774,2014-04-14 02:30:00,49.530829549857145\n3775,2014-04-14 02:35:00,49.66282765214761\n3776,2014-04-14 02:40:00,47.1197624590381\n3777,2014-04-14 02:45:00,47.784720003728566\n3778,2014-04-14 02:50:00,49.44850200211905\n3779,2014-04-14 02:55:00,49.201589278209525\n3780,2014-04-14 03:00:00,49.3806644263\n3781,2014-04-14 03:05:00,48.20603323939048\n3782,2014-04-14 03:10:00,49.786077145580954\n3783,2014-04-14 03:15:00,47.45112760437142\n3784,2014-04-14 03:20:00,46.7814504421619\n3785,2014-04-14 03:25:00,48.99713171125238\n3786,2014-04-14 03:30:00,48.327060521142855\n3787,2014-04-14 03:35:00,49.59542640853333\n3788,2014-04-14 03:40:00,46.50916080602381\n3789,2014-04-14 03:45:00,49.56673389951429\n3790,2014-04-14 03:50:00,47.37258337470476\n3791,2014-04-14 03:55:00,48.82626790679524\n3792,2014-04-14 04:00:00,46.374800870585716\n3793,2014-04-14 04:05:00,48.66005137567619\n3794,2014-04-14 04:10:00,49.098253423366664\n3795,2014-04-14 04:15:00,47.71160800085714\n3796,2014-04-14 04:20:00,47.10569044004762\n3797,2014-04-14 04:25:00,48.4020108016381\n3798,2014-04-14 04:30:00,49.59169178912857\n3799,2014-04-14 04:35:00,47.56055848081905\n3800,2014-04-14 04:40:00,47.28368671390952\n3801,2014-04-14 04:45:00,47.3969912346\n3802,2014-04-14 04:50:00,50.08521908789048\n3803,2014-04-14 04:55:00,47.73323861548096\n3804,2014-04-14 05:00:00,46.31798838817143\n3805,2014-04-14 05:05:00,49.4377367365619\n3806,2014-04-14 05:10:00,49.11555156225238\n3807,2014-04-14 05:15:00,46.840165915542855\n3808,2014-04-14 05:20:00,50.272950329833336\n3809,2014-04-14 05:25:00,48.773022950723806\n3810,2014-04-14 05:30:00,48.351332249514286\n3811,2014-04-14 05:35:00,47.88453183240476\n3812,2014-04-14 05:40:00,49.95778626039524\n3813,2014-04-14 05:45:00,47.346389639985716\n3814,2014-04-14 05:50:00,47.52105179137619\n3815,2014-04-14 05:55:00,46.87505989336667\n3816,2014-04-14 06:00:00,49.42933352515715\n3817,2014-04-14 06:05:00,48.78249474064762\n3818,2014-04-14 06:10:00,48.8440027722381\n3819,2014-04-14 06:15:00,47.28906029552857\n3820,2014-04-14 06:20:00,49.02729260411905\n3821,2014-04-14 06:25:00,49.49189331280952\n3822,2014-04-14 06:30:00,47.869054122899996\n3823,2014-04-14 06:35:00,49.650329051990475\n3824,2014-04-14 06:40:00,47.84754330648096\n3825,2014-04-14 06:45:00,49.49237527457143\n3826,2014-04-14 06:50:00,46.6021823345619\n3827,2014-04-14 06:55:00,48.67936078685238\n3828,2014-04-14 07:00:00,50.36024909974286\n3829,2014-04-14 07:05:00,50.414561736033335\n3830,2014-04-14 07:10:00,47.6240341229238\n3831,2014-04-14 07:15:00,48.27006065001429\n3832,2014-04-14 07:20:00,46.76381639380476\n3833,2014-04-14 07:25:00,50.012710468495236\n3834,2014-04-14 07:30:00,48.80107432688571\n3835,2014-04-14 07:35:00,48.07462890627619\n3836,2014-04-14 07:40:00,46.99274890066667\n3837,2014-04-14 07:45:00,50.33617628485714\n3838,2014-04-14 07:50:00,48.67742381034762\n3839,2014-04-14 07:55:00,47.69569981153809\n3840,2014-04-14 08:00:00,47.97228909192857\n3841,2014-04-14 08:05:00,47.66165777131904\n3842,2014-04-14 08:10:00,48.99354875920952\n3843,2014-04-14 08:15:00,50.3136043031\n3844,2014-04-14 08:20:00,50.02796568949047\n3845,2014-04-14 08:25:00,48.45015445408095\n3846,2014-04-14 08:30:00,49.92206887777142\n3847,2014-04-14 08:35:00,48.315933829861905\n3848,2014-04-14 08:40:00,47.64018094395238\n3849,2014-04-14 08:45:00,50.57205331824285\n3850,2014-04-14 08:50:00,47.86138360523333\n3851,2014-04-14 08:55:00,47.94817073342381\n3852,2014-04-14 09:00:00,103.32053728761429\n3853,2014-04-14 09:05:00,91.68956866900476\n3854,2014-04-14 09:10:00,100.21885747499523\n3855,2014-04-14 09:15:00,102.61008922968571\n3856,2014-04-14 09:20:00,96.85088811257619\n3857,2014-04-14 09:25:00,89.93221262586667\n3858,2014-04-14 09:30:00,95.00615878275714\n3859,2014-04-14 09:35:00,91.43013591544762\n3860,2014-04-14 09:40:00,95.5803902839381\n3861,2014-04-14 09:45:00,100.67204252972857\n3862,2014-04-14 09:50:00,95.90159611241904\n3863,2014-04-14 09:55:00,95.81674117410951\n3864,2014-04-14 10:00:00,107.2313726818\n3865,2014-04-14 10:05:00,107.62527835149046\n3866,2014-04-14 10:10:00,111.89459966498094\n3867,2014-04-14 10:15:00,103.39799784537144\n3868,2014-04-14 10:20:00,111.3720999277619\n3869,2014-04-14 10:25:00,107.41049416065238\n3870,2014-04-14 10:30:00,103.29886146874284\n3871,2014-04-14 10:35:00,103.22243953633333\n3872,2014-04-14 10:40:00,104.25437807502381\n3873,2014-04-14 10:45:00,108.32116341121429\n3874,2014-04-14 10:50:00,102.24660283260475\n3875,2014-04-14 10:55:00,112.95542211529525\n3876,2014-04-14 11:00:00,109.55069545308571\n3877,2014-04-14 11:05:00,115.04665710777618\n3878,2014-04-14 11:10:00,101.16018158546666\n3879,2014-04-14 11:15:00,105.87849837865714\n3880,2014-04-14 11:20:00,100.79978065464762\n3881,2014-04-14 11:25:00,104.77438096253809\n3882,2014-04-14 11:30:00,114.16127950642857\n3883,2014-04-14 11:35:00,101.04160996841905\n3884,2014-04-14 11:40:00,107.40329300090951\n3885,2014-04-14 11:45:00,102.3440366888\n3886,2014-04-14 11:50:00,107.11112432109047\n3887,2014-04-14 11:55:00,113.83022654848095\n3888,2014-04-14 12:00:00,110.79934499917144\n3889,2014-04-14 12:05:00,112.6235677082619\n3890,2014-04-14 12:10:00,106.43601542915238\n3891,2014-04-14 12:15:00,115.95672354154289\n3892,2014-04-14 12:20:00,112.20650900163332\n3893,2014-04-14 12:25:00,107.62005638072381\n3894,2014-04-14 12:30:00,107.70206296521428\n3895,2014-04-14 12:35:00,115.57556287280478\n3896,2014-04-14 12:40:00,110.11310336299523\n3897,2014-04-14 12:45:00,112.19764059188572\n3898,2014-04-14 12:50:00,107.5811327063762\n3899,2014-04-14 12:55:00,104.49880600186668\n3900,2014-04-14 13:00:00,112.57474734705714\n3901,2014-04-14 13:05:00,210.7308639300476\n3902,2014-04-14 13:10:00,109.0350190253381\n3903,2014-04-14 13:15:00,111.00483737092857\n3904,2014-04-14 13:20:00,104.36210860801906\n3905,2014-04-14 13:25:00,113.73775010370952\n3906,2014-04-14 13:30:00,116.2121839352\n3907,2014-04-14 13:35:00,115.30688894679048\n3908,2014-04-14 13:40:00,106.20183856408094\n3909,2014-04-14 13:45:00,107.56207473887143\n3910,2014-04-14 13:50:00,114.0063144366619\n3911,2014-04-14 13:55:00,110.60201122435238\n3912,2014-04-14 14:00:00,109.86989715764287\n3913,2014-04-14 14:05:00,115.93668715283333\n3914,2014-04-14 14:10:00,109.69455551802382\n3915,2014-04-14 14:15:00,109.3646316862143\n3916,2014-04-14 14:20:00,101.80571395190476\n3917,2014-04-14 14:25:00,102.25150726329525\n3918,2014-04-14 14:30:00,101.2670489415857\n3919,2014-04-14 14:35:00,115.7669764314762\n3920,2014-04-14 14:40:00,107.69708358596668\n3921,2014-04-14 14:45:00,108.66727330585714\n3922,2014-04-14 14:50:00,114.70363352334762\n3923,2014-04-14 14:55:00,110.93300516003808\n3924,2014-04-14 15:00:00,110.94766929422856\n3925,2014-04-14 15:05:00,105.94768316961905\n3926,2014-04-14 15:10:00,114.55302421830952\n3927,2014-04-14 15:15:00,103.8713129451\n3928,2014-04-14 15:20:00,102.07588458719047\n3929,2014-04-14 15:25:00,104.29856404238095\n3930,2014-04-14 15:30:00,105.52413460457143\n3931,2014-04-14 15:35:00,105.7647542674619\n3932,2014-04-14 15:40:00,111.98337576795238\n3933,2014-04-14 15:45:00,104.74786159654286\n3934,2014-04-14 15:50:00,112.09657107053333\n3935,2014-04-14 15:55:00,102.73568338332382\n3936,2014-04-14 16:00:00,103.64081090121428\n3937,2014-04-14 16:05:00,109.43414406680476\n3938,2014-04-14 16:10:00,116.05076151869524\n3939,2014-04-14 16:15:00,115.06095248938571\n3940,2014-04-14 16:20:00,116.81536326947617\n3941,2014-04-14 16:25:00,111.73042348836665\n3942,2014-04-14 16:30:00,112.14323600445714\n3943,2014-04-14 16:35:00,111.33800816124763\n3944,2014-04-14 16:40:00,111.3101834879381\n3945,2014-04-14 16:45:00,103.70646133292857\n3946,2014-04-14 16:50:00,110.05978740261905\n3947,2014-04-14 16:55:00,107.54449635900953\n3948,2014-04-14 17:00:00,108.4555650855\n3949,2014-04-14 17:05:00,109.76001878009049\n3950,2014-04-14 17:10:00,103.44419126438095\n3951,2014-04-14 17:15:00,107.14909531347143\n3952,2014-04-14 17:20:00,102.41992684096189\n3953,2014-04-14 17:25:00,117.08685880065238\n3954,2014-04-14 17:30:00,103.31606294204286\n3955,2014-04-14 17:35:00,105.56344991363332\n3956,2014-04-14 17:40:00,115.69517751272379\n3957,2014-04-14 17:45:00,109.16529441181427\n3958,2014-04-14 17:50:00,103.61957150490475\n3959,2014-04-14 17:55:00,107.60450383799524\n3960,2014-04-14 18:00:00,59.00583520508571\n3961,2014-04-14 18:05:00,59.55310279617619\n3962,2014-04-14 18:10:00,58.612152093566664\n3963,2014-04-14 18:15:00,61.09125703985714\n3964,2014-04-14 18:20:00,63.45651227724761\n3965,2014-04-14 18:25:00,62.05168458923809\n3966,2014-04-14 18:30:00,62.18953225182857\n3967,2014-04-14 18:35:00,59.600101064119045\n3968,2014-04-14 18:40:00,60.52472416840952\n3969,2014-04-14 18:45:00,63.7407928963\n3970,2014-04-14 18:50:00,58.90096441829047\n3971,2014-04-14 18:55:00,63.83688055208095\n3972,2014-04-14 19:00:00,51.88050152147143\n3973,2014-04-14 19:05:00,53.4714310854619\n3974,2014-04-14 19:10:00,51.15311995575238\n3975,2014-04-14 19:15:00,51.25390809104285\n3976,2014-04-14 19:20:00,53.11052185283333\n3977,2014-04-14 19:25:00,53.26755536752381\n3978,2014-04-14 19:30:00,50.787021280714285\n3979,2014-04-14 19:35:00,54.12411695210476\n3980,2014-04-14 19:40:00,50.15160977839524\n3981,2014-04-14 19:45:00,50.08742786618571\n3982,2014-04-14 19:50:00,52.45583382267618\n3983,2014-04-14 19:55:00,53.03329402276667\n3984,2014-04-14 20:00:00,52.01064645975714\n3985,2014-04-14 20:05:00,49.74095529614762\n3986,2014-04-14 20:10:00,48.1933314840381\n3987,2014-04-14 20:15:00,50.56664172702857\n3988,2014-04-14 20:20:00,49.29121371251905\n3989,2014-04-14 20:25:00,49.88541068980952\n3990,2014-04-14 20:30:00,50.120270754100005\n3991,2014-04-14 20:35:00,48.39118390539048\n3992,2014-04-14 20:40:00,50.12496209688095\n3993,2014-04-14 20:45:00,49.88802654167142\n3994,2014-04-14 20:50:00,51.0678429591619\n3995,2014-04-14 20:55:00,50.801349700352375\n3996,2014-04-14 21:00:00,48.562961825442855\n3997,2014-04-14 21:05:00,48.65449682713333\n3998,2014-04-14 21:10:00,48.84226779652381\n3999,2014-04-14 21:15:00,48.56010184931428\n4000,2014-04-14 21:20:00,50.48977600330476\n4001,2014-04-14 21:25:00,51.852558960295234\n4002,2014-04-14 21:30:00,50.48413950588571\n4003,2014-04-14 21:35:00,50.30900061077619\n4004,2014-04-14 21:40:00,49.525648968166664\n4005,2014-04-14 21:45:00,49.14182967195714\n4006,2014-04-14 21:50:00,51.55473520964762\n4007,2014-04-14 21:55:00,51.795000374038096\n4008,2014-04-14 22:00:00,49.82772088442857\n4009,2014-04-14 22:05:00,49.00806539011904\n4010,2014-04-14 22:10:00,50.93703561340952\n4011,2014-04-14 22:15:00,48.391365788399995\n4012,2014-04-14 22:20:00,50.933763275290474\n4013,2014-04-14 22:25:00,51.154849200880946\n4014,2014-04-14 22:30:00,48.383446829171426\n4015,2014-04-14 22:35:00,51.8019889172619\n4016,2014-04-14 22:40:00,51.84406589895238\n4017,2014-04-14 22:45:00,51.65614776654286\n4018,2014-04-14 22:50:00,49.89915733483333\n4019,2014-04-14 22:55:00,48.905795294023804\n4020,2014-04-14 23:00:00,50.24265439041429\n4021,2014-04-14 23:05:00,49.601668623004755\n4022,2014-04-14 23:10:00,48.75300398369524\n4023,2014-04-14 23:15:00,49.63152273428571\n4024,2014-04-14 23:20:00,50.60000139857619\n4025,2014-04-14 23:25:00,48.235080369466665\n4026,2014-04-14 23:30:00,49.292741211757146\n4027,2014-04-14 23:35:00,48.03744684384762\n4028,2014-04-14 23:40:00,50.972251727538094\n4029,2014-04-14 23:45:00,50.544391690728574\n4030,2014-04-14 23:50:00,48.239311716819046\n4031,2014-04-14 23:55:00,51.85570667850952\n"
  },
  {
    "path": "workspace/anomaly_detector/datasets/selected/seasonal/art_daily_jumpsup_noised_trended_det2.csv",
    "content": "timestamp,value\n2014-04-01 00:00:00,19.761251902999998\n2014-04-01 00:05:00,20.508273763190473\n2014-04-01 00:10:00,19.976522396880952\n2014-04-01 00:15:00,21.512587501971428\n2014-04-01 00:20:00,20.217501314561904\n2014-04-01 00:25:00,19.96032805275238\n2014-04-01 00:30:00,21.74304681884286\n2014-04-01 00:35:00,20.930841717533333\n2014-04-01 00:40:00,18.50572343892381\n2014-04-01 00:45:00,18.777782130514286\n2014-04-01 00:50:00,21.222896213704765\n2014-04-01 00:55:00,21.42525052279524\n2014-04-01 01:00:00,20.270049030685716\n2014-04-01 01:05:00,20.314547101976192\n2014-04-01 01:10:00,20.63189851806667\n2014-04-01 01:15:00,19.86807023995714\n2014-04-01 01:20:00,20.83984411294762\n2014-04-01 01:25:00,18.560413125538094\n2014-04-01 01:30:00,21.97904554092857\n2014-04-01 01:35:00,21.141988342819047\n2014-04-01 01:40:00,20.673506339809524\n2014-04-01 01:45:00,19.421538228\n2014-04-01 01:50:00,18.807512425990474\n2014-04-01 01:55:00,19.808502807680952\n2014-04-01 02:00:00,20.824878390871426\n2014-04-01 02:05:00,20.720850878461903\n2014-04-01 02:10:00,19.724017001252378\n2014-04-01 02:15:00,20.654038432442857\n2014-04-01 02:20:00,21.463326515633334\n2014-04-01 02:25:00,18.32091289892381\n2014-04-01 02:30:00,20.025698477414284\n2014-04-01 02:35:00,21.264875675804763\n2014-04-01 02:40:00,20.42267311999524\n2014-04-01 02:45:00,20.851440065985717\n2014-04-01 02:50:00,20.31968176087619\n2014-04-01 02:55:00,22.227914845366666\n2014-04-01 03:00:00,18.486343288857142\n2014-04-01 03:05:00,20.239476906147623\n2014-04-01 03:10:00,18.648404291738096\n2014-04-01 03:15:00,18.929320819928574\n2014-04-01 03:20:00,19.829772449319048\n2014-04-01 03:25:00,18.927219889809525\n2014-04-01 03:30:00,22.167248663800002\n2014-04-01 03:35:00,22.107099583090474\n2014-04-01 03:40:00,19.671819537280953\n2014-04-01 03:45:00,20.893812276771428\n2014-04-01 03:50:00,20.477275187161904\n2014-04-01 03:55:00,21.61205030305238\n2014-04-01 04:00:00,20.866925296442858\n2014-04-01 04:05:00,18.365593151333332\n2014-04-01 04:10:00,21.42472135192381\n2014-04-01 04:15:00,21.366856770914286\n2014-04-01 04:20:00,20.425795584204764\n2014-04-01 04:25:00,22.006021130995236\n2014-04-01 04:30:00,22.035570537085718\n2014-04-01 04:35:00,20.50487289727619\n2014-04-01 04:40:00,20.84861959146667\n2014-04-01 04:45:00,22.410195430557142\n2014-04-01 04:50:00,19.62682855824762\n2014-04-01 04:55:00,19.737457064438097\n2014-04-01 05:00:00,19.177524182128572\n2014-04-01 05:05:00,22.037336804219045\n2014-04-01 05:10:00,21.439263083609525\n2014-04-01 05:15:00,18.8913213955\n2014-04-01 05:20:00,22.403259880990475\n2014-04-01 05:25:00,21.40747778498095\n2014-04-01 05:30:00,21.893159866971427\n2014-04-01 05:35:00,18.691115061461907\n2014-04-01 05:40:00,20.52579605675238\n2014-04-01 05:45:00,21.307786004042857\n2014-04-01 05:50:00,20.69261967163333\n2014-04-01 05:55:00,21.19486367232381\n2014-04-01 06:00:00,21.807210540114284\n2014-04-01 06:05:00,20.040503013704765\n2014-04-01 06:10:00,21.94526994059524\n2014-04-01 06:15:00,19.209700133385716\n2014-04-01 06:20:00,19.64902041057619\n2014-04-01 06:25:00,18.746299146366667\n2014-04-01 06:30:00,20.038064388157142\n2014-04-01 06:35:00,20.10743579834762\n2014-04-01 06:40:00,21.816320484038098\n2014-04-01 06:45:00,21.21520125262857\n2014-04-01 06:50:00,20.357009280219046\n2014-04-01 06:55:00,21.226015438309524\n2014-04-01 07:00:00,18.8361334021\n2014-04-01 07:05:00,19.353526620290474\n2014-04-01 07:10:00,21.147672373380953\n2014-04-01 07:15:00,21.21278870547143\n2014-04-01 07:20:00,21.751300539561907\n2014-04-01 07:25:00,20.27420141715238\n2014-04-01 07:30:00,21.559859243642858\n2014-04-01 07:35:00,21.413004663533332\n2014-04-01 07:40:00,22.53809732302381\n2014-04-01 07:45:00,19.552485191414284\n2014-04-01 07:50:00,20.90612301690476\n2014-04-01 07:55:00,21.113903006495235\n2014-04-01 08:00:00,22.70887725398571\n2014-04-01 08:05:00,19.526462759176187\n2014-04-01 08:10:00,20.82203874656667\n2014-04-01 08:15:00,20.12134837375714\n2014-04-01 08:20:00,20.847619493347622\n2014-04-01 08:25:00,19.680002503638093\n2014-04-01 08:30:00,18.949378085128572\n2014-04-01 08:35:00,21.05663086321905\n2014-04-01 08:40:00,20.117226787209525\n2014-04-01 08:45:00,19.509015607000002\n2014-04-01 08:50:00,20.084432740490474\n2014-04-01 08:55:00,18.993251758180953\n2014-04-01 09:00:00,74.92958581217142\n2014-04-01 09:05:00,69.91462354836189\n2014-04-01 09:10:00,73.09930644725237\n2014-04-01 09:15:00,67.78030034374287\n2014-04-01 09:20:00,74.31841281223333\n2014-04-01 09:25:00,68.61390162262381\n2014-04-01 09:30:00,69.85387066761429\n2014-04-01 09:35:00,68.74405289080477\n2014-04-01 09:40:00,72.03568006189523\n2014-04-01 09:45:00,69.7770583696857\n2014-04-01 09:50:00,65.77172155117619\n2014-04-01 09:55:00,64.06475429266668\n2014-04-01 10:00:00,80.13990765835715\n2014-04-01 10:05:00,78.33237062224762\n2014-04-01 10:10:00,72.2372809079381\n2014-04-01 10:15:00,76.89516164052857\n2014-04-01 10:20:00,78.75194911701905\n2014-04-01 10:25:00,83.60344251280951\n2014-04-01 10:30:00,71.9585883865\n2014-04-01 10:35:00,76.19358828099048\n2014-04-01 10:40:00,83.56000397688095\n2014-04-01 10:45:00,80.86336084967142\n2014-04-01 10:50:00,75.3074150591619\n2014-04-01 10:55:00,83.93430347475238\n2014-04-01 11:00:00,80.39548396244285\n2014-04-01 11:05:00,80.48337181273332\n2014-04-01 11:10:00,88.09666885212381\n2014-04-01 11:15:00,87.6354051532143\n2014-04-01 11:20:00,78.28200855820477\n2014-04-01 11:25:00,74.82311570039523\n2014-04-01 11:30:00,77.77418942448571\n2014-04-01 11:35:00,73.08703196247619\n2014-04-01 11:40:00,72.93995913686668\n2014-04-01 11:45:00,78.90749119775714\n2014-04-01 11:50:00,87.59052687924762\n2014-04-01 11:55:00,86.4900552502381\n2014-04-01 12:00:00,81.15829421172856\n2014-04-01 12:05:00,82.02523879981905\n2014-04-01 12:10:00,73.09473154860952\n2014-04-01 12:15:00,76.4512308711\n2014-04-01 12:20:00,73.41070084389048\n2014-04-01 12:25:00,85.08037631648095\n2014-04-01 12:30:00,75.35720776567143\n2014-04-01 12:35:00,86.9251798400619\n2014-04-01 12:40:00,83.32538957295237\n2014-04-01 12:45:00,76.71828684284286\n2014-04-01 12:50:00,75.57993017653332\n2014-04-01 12:55:00,83.09681863002382\n2014-04-01 13:00:00,87.55336675621429\n2014-04-01 13:05:00,84.64187976130475\n2014-04-01 13:10:00,78.73372324459524\n2014-04-01 13:15:00,82.56163768558571\n2014-04-01 13:20:00,78.1441899914762\n2014-04-01 13:25:00,89.16319300076667\n2014-04-01 13:30:00,85.16662861575713\n2014-04-01 13:35:00,83.02326462964763\n2014-04-01 13:40:00,79.97347906433811\n2014-04-01 13:45:00,83.09846151082857\n2014-04-01 13:50:00,78.68238424141906\n2014-04-01 13:55:00,73.68700611410952\n2014-04-01 14:00:00,79.56765692970001\n2014-04-01 14:05:00,88.14096298019048\n2014-04-01 14:10:00,83.28176146948095\n2014-04-01 14:15:00,74.61209219977142\n2014-04-01 14:20:00,87.43552404396192\n2014-04-01 14:25:00,77.58553747455238\n2014-04-01 14:30:00,77.19131153154285\n2014-04-01 14:35:00,78.05185466793333\n2014-04-01 14:40:00,82.54086029622381\n2014-04-01 14:45:00,82.02809946021429\n2014-04-01 14:50:00,81.18319143010476\n2014-04-01 14:55:00,84.80842798599524\n2014-04-01 15:00:00,78.40314959548569\n2014-04-01 15:05:00,85.85894721047619\n2014-04-01 15:10:00,76.15859539126667\n2014-04-01 15:15:00,85.88272835755714\n2014-04-01 15:20:00,83.98921614184762\n2014-04-01 15:25:00,84.3070249072381\n2014-04-01 15:30:00,81.08801775882857\n2014-04-01 15:35:00,84.06259991911905\n2014-04-01 15:40:00,74.67485881190952\n2014-04-01 15:45:00,87.0302458745\n2014-04-01 15:50:00,74.30174647989048\n2014-04-01 15:55:00,75.80028106358095\n2014-04-01 16:00:00,82.65705080557143\n2014-04-01 16:05:00,85.2664342373619\n2014-04-01 16:10:00,74.66333682805238\n2014-04-01 16:15:00,88.18296335724288\n2014-04-01 16:20:00,89.03588756493333\n2014-04-01 16:25:00,83.16081972282379\n2014-04-01 16:30:00,81.1729565479143\n2014-04-01 16:35:00,85.34281330270476\n2014-04-01 16:40:00,78.74166454819525\n2014-04-01 16:45:00,81.38761326688571\n2014-04-01 16:50:00,88.16122623537619\n2014-04-01 16:55:00,88.80073587276668\n2014-04-01 17:00:00,88.35092965575714\n2014-04-01 17:05:00,77.72443742994763\n2014-04-01 17:10:00,77.25221366243811\n2014-04-01 17:15:00,78.30278118942857\n2014-04-01 17:20:00,80.60856648641905\n2014-04-01 17:25:00,78.58170855020953\n2014-04-01 17:30:00,79.54987478470001\n2014-04-01 17:35:00,83.50010024889049\n2014-04-01 17:40:00,85.77775945288096\n2014-04-01 17:45:00,85.35372043357143\n2014-04-01 17:50:00,86.6230063261619\n2014-04-01 17:55:00,74.11462498665237\n2014-04-01 18:00:00,30.71263352284286\n2014-04-01 18:05:00,35.46662778213334\n2014-04-01 18:10:00,33.833722087723814\n2014-04-01 18:15:00,34.12955835781428\n2014-04-01 18:20:00,30.773455073104763\n2014-04-01 18:25:00,32.07834772229524\n2014-04-01 18:30:00,34.537246951585715\n2014-04-01 18:35:00,35.95798370177619\n2014-04-01 18:40:00,36.33535375226666\n2014-04-01 18:45:00,33.676785771657144\n2014-04-01 18:50:00,33.97257650864762\n2014-04-01 18:55:00,35.82049918083809\n2014-04-01 19:00:00,24.26498554472857\n2014-04-01 19:05:00,24.179394009119047\n2014-04-01 19:10:00,25.92608468460952\n2014-04-01 19:15:00,25.417647290300003\n2014-04-01 19:20:00,25.958834064990477\n2014-04-01 19:25:00,22.871376598280953\n2014-04-01 19:30:00,24.250272373971427\n2014-04-01 19:35:00,25.682785727861905\n2014-04-01 19:40:00,22.41389351475238\n2014-04-01 19:45:00,25.483478007142857\n2014-04-01 19:50:00,22.750552940133332\n2014-04-01 19:55:00,25.55864452732381\n2014-04-01 20:00:00,22.724469874714284\n2014-04-01 20:05:00,21.016649152304762\n2014-04-01 20:10:00,22.171453712195238\n2014-04-01 20:15:00,23.033119021385716\n2014-04-01 20:20:00,22.84373742017619\n2014-04-01 20:25:00,22.00492094026667\n2014-04-01 20:30:00,23.946162179957142\n2014-04-01 20:35:00,22.39670031804762\n2014-04-01 20:40:00,22.349270303938095\n2014-04-01 20:45:00,20.539656763628575\n2014-04-01 20:50:00,24.06912389771905\n2014-04-01 20:55:00,21.025028759209526\n2014-04-01 21:00:00,22.0849229424\n2014-04-01 21:05:00,23.198539327590474\n2014-04-01 21:10:00,20.842230716780954\n2014-04-01 21:15:00,22.103340106171427\n2014-04-01 21:20:00,20.958522645261905\n2014-04-01 21:25:00,23.05196846445238\n2014-04-01 21:30:00,22.27424282924286\n2014-04-01 21:35:00,23.45382145873333\n2014-04-01 21:40:00,23.61633128162381\n2014-04-01 21:45:00,22.635753847714284\n2014-04-01 21:50:00,22.951297207104762\n2014-04-01 21:55:00,22.250670613895238\n2014-04-01 22:00:00,21.520756843285717\n2014-04-01 22:05:00,22.58396664527619\n2014-04-01 22:10:00,23.633088978266667\n2014-04-01 22:15:00,21.672208707557143\n2014-04-01 22:20:00,21.27017504954762\n2014-04-01 22:25:00,21.574007437638095\n2014-04-01 22:30:00,21.76947100942857\n2014-04-01 22:35:00,20.32817562891905\n2014-04-01 22:40:00,22.03677089240952\n2014-04-01 22:45:00,22.0276851491\n2014-04-01 22:50:00,22.412005401090475\n2014-04-01 22:55:00,21.516084293580953\n2014-04-01 23:00:00,22.509928676971427\n2014-04-01 23:05:00,23.578007613861903\n2014-04-01 23:10:00,23.89452614255238\n2014-04-01 23:15:00,22.41424593384286\n2014-04-01 23:20:00,20.257185857233335\n2014-04-01 23:25:00,23.97191816972381\n2014-04-01 23:30:00,22.925660629314283\n2014-04-01 23:35:00,21.453223374304763\n2014-04-01 23:40:00,20.705295057195237\n2014-04-01 23:45:00,20.697776306885714\n2014-04-01 23:50:00,20.80253864087619\n2014-04-01 23:55:00,20.32119775106667\n2014-04-02 00:00:00,23.751473897457142\n2014-04-02 00:05:00,22.31337055034762\n2014-04-02 00:10:00,22.957575746138094\n2014-04-02 00:15:00,23.477612608528574\n2014-04-02 00:20:00,23.338783072919046\n2014-04-02 00:25:00,23.71048201870952\n2014-04-02 00:30:00,24.056518490100004\n2014-04-02 00:35:00,21.95122293519048\n2014-04-02 00:40:00,24.003722819080952\n2014-04-02 00:45:00,23.102981221971426\n2014-04-02 00:50:00,20.499934665961906\n2014-04-02 00:55:00,22.951834865752378\n2014-04-02 01:00:00,22.979009495542858\n2014-04-02 01:05:00,23.863025588533333\n2014-04-02 01:10:00,21.73875233942381\n2014-04-02 01:15:00,22.594110286814285\n2014-04-02 01:20:00,20.310654965904764\n2014-04-02 01:25:00,21.597646206795236\n2014-04-02 01:30:00,20.525760618885716\n2014-04-02 01:35:00,22.371718081576187\n2014-04-02 01:40:00,23.56145726866667\n2014-04-02 01:45:00,21.124877911357142\n2014-04-02 01:50:00,22.41631180124762\n2014-04-02 01:55:00,21.130022641238092\n2014-04-02 02:00:00,20.80418244282857\n2014-04-02 02:05:00,22.372856215319047\n2014-04-02 02:10:00,20.65290400760952\n2014-04-02 02:15:00,22.6931685246\n2014-04-02 02:20:00,20.47654031889048\n2014-04-02 02:25:00,20.785490839880953\n2014-04-02 02:30:00,22.566061370471427\n2014-04-02 02:35:00,22.739141556361908\n2014-04-02 02:40:00,20.49690010135238\n2014-04-02 02:45:00,22.681900009142858\n2014-04-02 02:50:00,23.749843434633334\n2014-04-02 02:55:00,23.29253851872381\n2014-04-02 03:00:00,20.935454701414283\n2014-04-02 03:05:00,22.788053352204763\n2014-04-02 03:10:00,23.11460523839524\n2014-04-02 03:15:00,20.581960521285716\n2014-04-02 03:20:00,23.86186686517619\n2014-04-02 03:25:00,24.07298625586667\n2014-04-02 03:30:00,23.857166236257143\n2014-04-02 03:35:00,23.76132349104762\n2014-04-02 03:40:00,23.450098889038095\n2014-04-02 03:45:00,23.011406696528574\n2014-04-02 03:50:00,23.199627067619048\n2014-04-02 03:55:00,23.718140697109526\n2014-04-02 04:00:00,23.1499938334\n2014-04-02 04:05:00,21.818348302890474\n2014-04-02 04:10:00,22.01872536098095\n2014-04-02 04:15:00,24.110551302071425\n2014-04-02 04:20:00,20.598250247961904\n2014-04-02 04:25:00,23.33248470595238\n2014-04-02 04:30:00,24.363753066842854\n2014-04-02 04:35:00,23.376996013133333\n2014-04-02 04:40:00,24.53517176242381\n2014-04-02 04:45:00,23.317143907814284\n2014-04-02 04:50:00,20.711856878804763\n2014-04-02 04:55:00,23.88988476469524\n2014-04-02 05:00:00,21.727805362085714\n2014-04-02 05:05:00,22.38095509317619\n2014-04-02 05:10:00,21.852534330266668\n2014-04-02 05:15:00,21.685823567657142\n2014-04-02 05:20:00,22.34467043374762\n2014-04-02 05:25:00,22.141493889038095\n2014-04-02 05:30:00,23.167282898828574\n2014-04-02 05:35:00,23.893973851619048\n2014-04-02 05:40:00,21.83716413650952\n2014-04-02 05:45:00,21.5111346113\n2014-04-02 05:50:00,23.331271559690475\n2014-04-02 05:55:00,23.352411215680952\n2014-04-02 06:00:00,24.283096385671428\n2014-04-02 06:05:00,20.749794650561903\n2014-04-02 06:10:00,24.10561502945238\n2014-04-02 06:15:00,22.78490154894286\n2014-04-02 06:20:00,23.19354169003333\n2014-04-02 06:25:00,21.08125957172381\n2014-04-02 06:30:00,22.453674017214286\n2014-04-02 06:35:00,21.639864390904762\n2014-04-02 06:40:00,21.754995358395238\n2014-04-02 06:45:00,22.761916172985714\n2014-04-02 06:50:00,24.00279999207619\n2014-04-02 06:55:00,23.735540387266667\n2014-04-02 07:00:00,23.131856979157142\n2014-04-02 07:05:00,22.93297039004762\n2014-04-02 07:10:00,22.491962268138096\n2014-04-02 07:15:00,24.68101846562857\n2014-04-02 07:20:00,23.038389264519047\n2014-04-02 07:25:00,21.820925117009523\n2014-04-02 07:30:00,21.732863168199998\n2014-04-02 07:35:00,23.265352599290473\n2014-04-02 07:40:00,22.918691061580954\n2014-04-02 07:45:00,20.865612640371427\n2014-04-02 07:50:00,24.162523393561905\n2014-04-02 07:55:00,23.66619179785238\n2014-04-02 08:00:00,23.504460015842856\n2014-04-02 08:05:00,21.13970596413333\n2014-04-02 08:10:00,22.32024721022381\n2014-04-02 08:15:00,24.620993328614283\n2014-04-02 08:20:00,24.337261727304764\n2014-04-02 08:25:00,22.03651698959524\n2014-04-02 08:30:00,21.530021250685717\n2014-04-02 08:35:00,22.705578019176187\n2014-04-02 08:40:00,22.339988181366667\n2014-04-02 08:45:00,23.653012649657143\n2014-04-02 08:50:00,24.797286859347622\n2014-04-02 08:55:00,22.390993895138095\n2014-04-02 09:00:00,64.99267731952858\n2014-04-02 09:05:00,76.36141956111905\n2014-04-02 09:10:00,64.67742585510952\n2014-04-02 09:15:00,77.1263662013\n2014-04-02 09:20:00,73.21447069709048\n2014-04-02 09:25:00,76.99060418718095\n2014-04-02 09:30:00,66.90644316697144\n2014-04-02 09:35:00,64.75202912026191\n2014-04-02 09:40:00,70.84560808555239\n2014-04-02 09:45:00,70.34187129534286\n2014-04-02 09:50:00,68.72912824963333\n2014-04-02 09:55:00,77.25240186122382\n2014-04-02 10:00:00,85.64221380881429\n2014-04-02 10:05:00,83.15090773360475\n2014-04-02 10:10:00,75.41815592429523\n2014-04-02 10:15:00,84.29473500988571\n2014-04-02 10:20:00,84.18870948737619\n2014-04-02 10:25:00,79.50997472116667\n2014-04-02 10:30:00,87.27303446165713\n2014-04-02 10:35:00,75.51929435124762\n2014-04-02 10:40:00,77.08431706383809\n2014-04-02 10:45:00,73.92392031662857\n2014-04-02 10:50:00,85.29551791851905\n2014-04-02 10:55:00,82.60726519600952\n2014-04-02 11:00:00,79.7018106216\n2014-04-02 11:05:00,77.30573298199049\n2014-04-02 11:10:00,75.34639108688094\n2014-04-02 11:15:00,77.36724295197143\n2014-04-02 11:20:00,81.93180092016188\n2014-04-02 11:25:00,78.66130489605239\n2014-04-02 11:30:00,78.85649540704286\n2014-04-02 11:35:00,88.67024986883332\n2014-04-02 11:40:00,82.94527336822381\n2014-04-02 11:45:00,86.3579876663143\n2014-04-02 11:50:00,75.33535169520476\n2014-04-02 11:55:00,80.58240324679524\n2014-04-02 12:00:00,82.78539522118571\n2014-04-02 12:05:00,78.1144166701762\n2014-04-02 12:10:00,77.06352365216668\n2014-04-02 12:15:00,89.05835776635715\n2014-04-02 12:20:00,90.17051656544761\n2014-04-02 12:25:00,76.42448217533808\n2014-04-02 12:30:00,80.75012681282857\n2014-04-02 12:35:00,90.49414001391904\n2014-04-02 12:40:00,76.51640054860951\n2014-04-02 12:45:00,85.4807540517\n2014-04-02 12:50:00,90.73916576129048\n2014-04-02 12:55:00,90.84252775528095\n2014-04-02 13:00:00,82.82405522547143\n2014-04-02 13:05:00,77.8970926726619\n2014-04-02 13:10:00,78.53374541685238\n2014-04-02 13:15:00,89.53881910974286\n2014-04-02 13:20:00,89.8994805398333\n2014-04-02 13:25:00,85.04723385362381\n2014-04-02 13:30:00,87.58681455981429\n2014-04-02 13:35:00,87.17443344940476\n2014-04-02 13:40:00,85.93241941099524\n2014-04-02 13:45:00,88.5865102486857\n2014-04-02 13:50:00,86.3245701976762\n2014-04-02 13:55:00,83.91012298976668\n2014-04-02 14:00:00,79.18052096175714\n2014-04-02 14:05:00,87.29848061884762\n2014-04-02 14:10:00,82.9789243803381\n2014-04-02 14:15:00,80.12816311552857\n2014-04-02 14:20:00,88.24968756471905\n2014-04-02 14:25:00,86.57348605340952\n2014-04-02 14:30:00,90.4307571332\n2014-04-02 14:35:00,78.08842365729048\n2014-04-02 14:40:00,85.83545492918095\n2014-04-02 14:45:00,79.36400934207144\n2014-04-02 14:50:00,89.9204397178619\n2014-04-02 14:55:00,77.06316059355238\n2014-04-02 15:00:00,85.97993977384286\n2014-04-02 15:05:00,88.14614216703333\n2014-04-02 15:10:00,81.17496354002381\n2014-04-02 15:15:00,90.7698358002143\n2014-04-02 15:20:00,89.12277384300475\n2014-04-02 15:25:00,80.23250157969524\n2014-04-02 15:30:00,75.64675083938572\n2014-04-02 15:35:00,80.28000424177621\n2014-04-02 15:40:00,80.04189978486667\n2014-04-02 15:45:00,89.78771296435714\n2014-04-02 15:50:00,91.02964672134762\n2014-04-02 15:55:00,76.69032585113808\n2014-04-02 16:00:00,83.11199310982857\n2014-04-02 16:05:00,84.35202593931905\n2014-04-02 16:10:00,77.07275501080952\n2014-04-02 16:15:00,81.6335635095\n2014-04-02 16:20:00,80.67436117369049\n2014-04-02 16:25:00,84.18537791398094\n2014-04-02 16:30:00,86.19496727247143\n2014-04-02 16:35:00,86.87911382166189\n2014-04-02 16:40:00,77.81889031765238\n2014-04-02 16:45:00,88.64539287454286\n2014-04-02 16:50:00,86.50234672513334\n2014-04-02 16:55:00,89.87830692512381\n2014-04-02 17:00:00,82.85006082791429\n2014-04-02 17:05:00,89.97035782540476\n2014-04-02 17:10:00,89.52794822849523\n2014-04-02 17:15:00,82.6975546904857\n2014-04-02 17:20:00,181.78873924537623\n2014-04-02 17:25:00,90.62287552696668\n2014-04-02 17:30:00,87.14796085345715\n2014-04-02 17:35:00,90.56468981094763\n2014-04-02 17:40:00,88.4718020129381\n2014-04-02 17:45:00,85.47640620852857\n2014-04-02 17:50:00,77.58873511991905\n2014-04-02 17:55:00,80.40622084620952\n2014-04-02 18:00:00,38.750584685300005\n2014-04-02 18:05:00,34.60173598589047\n2014-04-02 18:10:00,33.16170647478095\n2014-04-02 18:15:00,37.10065650737143\n2014-04-02 18:20:00,37.2773827022619\n2014-04-02 18:25:00,34.41412591045238\n2014-04-02 18:30:00,34.49973762954286\n2014-04-02 18:35:00,35.602992334833345\n2014-04-02 18:40:00,32.74896753162381\n2014-04-02 18:45:00,37.66862505251428\n2014-04-02 18:50:00,34.65376708120476\n2014-04-02 18:55:00,38.09592251219524\n2014-04-02 19:00:00,27.595068699885715\n2014-04-02 19:05:00,26.969806030376187\n2014-04-02 19:10:00,25.46960488546667\n2014-04-02 19:15:00,26.334704106257146\n2014-04-02 19:20:00,26.02188147784762\n2014-04-02 19:25:00,25.554677756438092\n2014-04-02 19:30:00,27.84357783312857\n2014-04-02 19:35:00,26.217479517019047\n2014-04-02 19:40:00,27.78940769140953\n2014-04-02 19:45:00,24.5376276324\n2014-04-02 19:50:00,24.705480388590473\n2014-04-02 19:55:00,28.459524573180953\n2014-04-02 20:00:00,24.768070801371426\n2014-04-02 20:05:00,24.456028241161906\n2014-04-02 20:10:00,24.51829936865238\n2014-04-02 20:15:00,23.264633523842857\n2014-04-02 20:20:00,25.334144454033332\n2014-04-02 20:25:00,22.74503501892381\n2014-04-02 20:30:00,24.753547965214285\n2014-04-02 20:35:00,24.750523503504763\n2014-04-02 20:40:00,26.164610757195234\n2014-04-02 20:45:00,24.582780257385714\n2014-04-02 20:50:00,22.99638476527619\n2014-04-02 20:55:00,24.788413767166666\n2014-04-02 21:00:00,22.471321165957143\n2014-04-02 21:05:00,22.93078575564762\n2014-04-02 21:10:00,22.244169672238094\n2014-04-02 21:15:00,24.18960808872857\n2014-04-02 21:20:00,22.473772489919046\n2014-04-02 21:25:00,24.028049361109524\n2014-04-02 21:30:00,25.898592632600003\n2014-04-02 21:35:00,25.04920549609048\n2014-04-02 21:40:00,22.47491390838095\n2014-04-02 21:45:00,23.072365459371426\n2014-04-02 21:50:00,24.886245851961906\n2014-04-02 21:55:00,25.782088047752378\n2014-04-02 22:00:00,22.25622360264286\n2014-04-02 22:05:00,25.384787662133334\n2014-04-02 22:10:00,24.388716686223813\n2014-04-02 22:15:00,24.333206567714285\n2014-04-02 22:20:00,25.989115484804763\n2014-04-02 22:25:00,25.155074633495236\n2014-04-02 22:30:00,25.572805632485714\n2014-04-02 22:35:00,23.59384780207619\n2014-04-02 22:40:00,24.403531577966667\n2014-04-02 22:45:00,24.65537300035714\n2014-04-02 22:50:00,23.486398253347616\n2014-04-02 22:55:00,24.489450337838093\n2014-04-02 23:00:00,23.14668783882857\n2014-04-02 23:05:00,22.780937842619046\n2014-04-02 23:10:00,23.71093376820952\n2014-04-02 23:15:00,25.1799322874\n2014-04-02 23:20:00,25.89509869809048\n2014-04-02 23:25:00,24.06829468078095\n2014-04-02 23:30:00,24.816315868271428\n2014-04-02 23:35:00,22.664195559361904\n2014-04-02 23:40:00,25.87795804125238\n2014-04-02 23:45:00,24.541702397442858\n2014-04-02 23:50:00,25.39624162153333\n2014-04-02 23:55:00,25.46010474192381\n2014-04-03 00:00:00,23.311636391214286\n2014-04-03 00:05:00,24.409852574604763\n2014-04-03 00:10:00,26.142514244295235\n2014-04-03 00:15:00,22.666573893585717\n2014-04-03 00:20:00,25.04767578257619\n2014-04-03 00:25:00,26.171972978766668\n2014-04-03 00:30:00,23.53266557505714\n2014-04-03 00:35:00,25.78358930464762\n2014-04-03 00:40:00,26.079868276838095\n2014-04-03 00:45:00,25.341023409028573\n2014-04-03 00:50:00,23.28543229681905\n2014-04-03 00:55:00,23.703562399109522\n2014-04-03 01:00:00,22.5182371777\n2014-04-03 01:05:00,25.708253413190477\n2014-04-03 01:10:00,25.78832569838095\n2014-04-03 01:15:00,24.928162668471426\n2014-04-03 01:20:00,23.814873309861905\n2014-04-03 01:25:00,22.71944649155238\n2014-04-03 01:30:00,25.43187329684286\n2014-04-03 01:35:00,25.33318810773333\n2014-04-03 01:40:00,26.084933896523808\n2014-04-03 01:45:00,25.364092369714285\n2014-04-03 01:50:00,25.764184530904764\n2014-04-03 01:55:00,25.440663709695237\n2014-04-03 02:00:00,24.987034467485714\n2014-04-03 02:05:00,24.17959176727619\n2014-04-03 02:10:00,26.087635901266665\n2014-04-03 02:15:00,25.090481430457142\n2014-04-03 02:20:00,24.08746890694762\n2014-04-03 02:25:00,22.835365275938095\n2014-04-03 02:30:00,23.671747995028568\n2014-04-03 02:35:00,24.69127598691905\n2014-04-03 02:40:00,23.626351003909527\n2014-04-03 02:45:00,23.4161913917\n2014-04-03 02:50:00,24.648264532590474\n2014-04-03 02:55:00,23.225412335980952\n2014-04-03 03:00:00,25.755211681871426\n2014-04-03 03:05:00,24.498484510161905\n2014-04-03 03:10:00,24.86390347685238\n2014-04-03 03:15:00,23.165425927542856\n2014-04-03 03:20:00,23.881638675833333\n2014-04-03 03:25:00,24.23113254252381\n2014-04-03 03:30:00,25.831065607814285\n2014-04-03 03:35:00,25.686292854204762\n2014-04-03 03:40:00,23.50500513729524\n2014-04-03 03:45:00,25.085252040685717\n2014-04-03 03:50:00,23.60180162157619\n2014-04-03 03:55:00,26.58840528946667\n2014-04-03 04:00:00,26.45135265535714\n2014-04-03 04:05:00,24.90335650114762\n2014-04-03 04:10:00,25.453348382838094\n2014-04-03 04:15:00,25.870900100228575\n2014-04-03 04:20:00,25.556612727819047\n2014-04-03 04:25:00,25.479374288109526\n2014-04-03 04:30:00,26.521716031799997\n2014-04-03 04:35:00,25.080764901390474\n2014-04-03 04:40:00,25.24759163968095\n2014-04-03 04:45:00,26.106896430371428\n2014-04-03 04:50:00,25.396825376161907\n2014-04-03 04:55:00,25.656432869052377\n2014-04-03 05:00:00,23.66881760194286\n2014-04-03 05:05:00,24.224651029833332\n2014-04-03 05:10:00,23.33622919232381\n2014-04-03 05:15:00,24.777526055014285\n2014-04-03 05:20:00,24.584814364604764\n2014-04-03 05:25:00,26.757996495195236\n2014-04-03 05:30:00,25.221620325585718\n2014-04-03 05:35:00,25.93000548327619\n2014-04-03 05:40:00,24.12772534966667\n2014-04-03 05:45:00,26.125288468257143\n2014-04-03 05:50:00,25.26688748504762\n2014-04-03 05:55:00,25.601957421638097\n2014-04-03 06:00:00,23.999151683228575\n2014-04-03 06:05:00,25.023422614419047\n2014-04-03 06:10:00,25.372457417509523\n2014-04-03 06:15:00,25.2001287033\n2014-04-03 06:20:00,26.51196532189048\n2014-04-03 06:25:00,26.451721610380954\n2014-04-03 06:30:00,26.75000766007143\n2014-04-03 06:35:00,25.543223928761908\n2014-04-03 06:40:00,26.76860890145238\n2014-04-03 06:45:00,26.218304857242856\n2014-04-03 06:50:00,23.979161894733334\n2014-04-03 06:55:00,24.613016487723808\n2014-04-03 07:00:00,23.864284054514286\n2014-04-03 07:05:00,22.934943405204763\n2014-04-03 07:10:00,23.67779025069524\n2014-04-03 07:15:00,22.949278059385716\n2014-04-03 07:20:00,25.81983003587619\n2014-04-03 07:25:00,24.650053857566668\n2014-04-03 07:30:00,24.205656051157142\n2014-04-03 07:35:00,26.00968118344762\n2014-04-03 07:40:00,26.300185193738095\n2014-04-03 07:45:00,26.878876726028572\n2014-04-03 07:50:00,25.553173386319045\n2014-04-03 07:55:00,24.838675358009525\n2014-04-03 08:00:00,24.2210572064\n2014-04-03 08:05:00,23.89671331309048\n2014-04-03 08:10:00,23.866584754280954\n2014-04-03 08:15:00,24.659078927471427\n2014-04-03 08:20:00,26.996907325961903\n2014-04-03 08:25:00,23.04061717065238\n2014-04-03 08:30:00,23.83346644604286\n2014-04-03 08:35:00,23.805655262933332\n2014-04-03 08:40:00,25.92800175162381\n2014-04-03 08:45:00,24.476903196114286\n2014-04-03 08:50:00,24.90344798030476\n2014-04-03 08:55:00,23.67634175999524\n2014-04-03 09:00:00,71.79724544298571\n2014-04-03 09:05:00,67.70024363237619\n2014-04-03 09:10:00,73.55355538196667\n2014-04-03 09:15:00,67.64356891205715\n2014-04-03 09:20:00,77.06996160304762\n2014-04-03 09:25:00,74.03227145383809\n2014-04-03 09:30:00,76.17989165472856\n2014-04-03 09:35:00,72.03319190611906\n2014-04-03 09:40:00,71.53709111190952\n2014-04-03 09:45:00,67.6918908911\n2014-04-03 09:50:00,73.48812673199048\n2014-04-03 09:55:00,73.36836039448094\n2014-04-03 10:00:00,82.28351515847143\n2014-04-03 10:05:00,86.51885692466189\n2014-04-03 10:10:00,87.95392066945239\n2014-04-03 10:15:00,86.69314861234287\n2014-04-03 10:20:00,77.28112966173333\n2014-04-03 10:25:00,84.71013739362381\n2014-04-03 10:30:00,76.30982888601429\n2014-04-03 10:35:00,85.85119266300475\n2014-04-03 10:40:00,81.00423801669524\n2014-04-03 10:45:00,77.14191951558571\n2014-04-03 10:50:00,88.47200549077618\n2014-04-03 10:55:00,84.62982608856667\n2014-04-03 11:00:00,82.47740303305714\n2014-04-03 11:05:00,77.33198268424762\n2014-04-03 11:10:00,85.39612045443809\n2014-04-03 11:15:00,91.54116294282856\n2014-04-03 11:20:00,86.35044390691905\n2014-04-03 11:25:00,92.32619073970952\n2014-04-03 11:30:00,79.050618585\n2014-04-03 11:35:00,85.92626485969049\n2014-04-03 11:40:00,89.58876171588095\n2014-04-03 11:45:00,85.26102121637143\n2014-04-03 11:50:00,78.3585812303619\n2014-04-03 11:55:00,86.18792134955238\n2014-04-03 12:00:00,87.04680398284286\n2014-04-03 12:05:00,88.92354009133334\n2014-04-03 12:10:00,89.4503927911238\n2014-04-03 12:15:00,89.6106284615143\n2014-04-03 12:20:00,87.90287692780475\n2014-04-03 12:25:00,80.75678064599524\n2014-04-03 12:30:00,83.77539648118571\n2014-04-03 12:35:00,89.72600405687619\n2014-04-03 12:40:00,92.56679260296666\n2014-04-03 12:45:00,78.59934279855713\n2014-04-03 12:50:00,85.90345215954763\n2014-04-03 12:55:00,82.34694400883808\n2014-04-03 13:00:00,81.03458536792857\n2014-04-03 13:05:00,85.52761767091906\n2014-04-03 13:10:00,87.13913158960952\n2014-04-03 13:15:00,77.6077881773\n2014-04-03 13:20:00,89.93921963819048\n2014-04-03 13:25:00,90.58131670518095\n2014-04-03 13:30:00,92.91825706007143\n2014-04-03 13:35:00,80.3708379644619\n2014-04-03 13:40:00,86.99923029685237\n2014-04-03 13:45:00,84.32048059134286\n2014-04-03 13:50:00,82.85951321923334\n2014-04-03 13:55:00,86.55895700002381\n2014-04-03 14:00:00,90.0497869071143\n2014-04-03 14:05:00,77.90852559250476\n2014-04-03 14:10:00,93.05679653989525\n2014-04-03 14:15:00,90.5120630964857\n2014-04-03 14:20:00,89.57990256277618\n2014-04-03 14:25:00,89.73507480406667\n2014-04-03 14:30:00,83.80157369815714\n2014-04-03 14:35:00,89.60969318794763\n2014-04-03 14:40:00,83.7798083933381\n2014-04-03 14:45:00,91.97784163782856\n2014-04-03 14:50:00,80.44208507371904\n2014-04-03 14:55:00,82.29143778840952\n2014-04-03 15:00:00,86.4456247977\n2014-04-03 15:05:00,82.73907681959048\n2014-04-03 15:10:00,84.42692051428095\n2014-04-03 15:15:00,85.52531762287143\n2014-04-03 15:20:00,91.3555927498619\n2014-04-03 15:25:00,86.03250687635239\n2014-04-03 15:30:00,83.46825356114286\n2014-04-03 15:35:00,81.64013270563332\n2014-04-03 15:40:00,84.22258549752381\n2014-04-03 15:45:00,85.94297153931429\n2014-04-03 15:50:00,89.63643667390475\n2014-04-03 15:55:00,79.64291586379524\n2014-04-03 16:00:00,81.25988767828571\n2014-04-03 16:05:00,83.79604054137619\n2014-04-03 16:10:00,83.49539183716668\n2014-04-03 16:15:00,84.00442627005714\n2014-04-03 16:20:00,90.44022523634762\n2014-04-03 16:25:00,82.93781034463808\n2014-04-03 16:30:00,85.78914579952857\n2014-04-03 16:35:00,87.74872416691906\n2014-04-03 16:40:00,81.48852095420952\n2014-04-03 16:45:00,89.280215876\n2014-04-03 16:50:00,86.54231654479048\n2014-04-03 16:55:00,84.94447759578095\n2014-04-03 17:00:00,90.76008323307143\n2014-04-03 17:05:00,81.7069069076619\n2014-04-03 17:10:00,91.94923483655238\n2014-04-03 17:15:00,86.80264152794284\n2014-04-03 17:20:00,87.58010001263334\n2014-04-03 17:25:00,91.8416842118238\n2014-04-03 17:30:00,90.92950462011429\n2014-04-03 17:35:00,87.48061651910476\n2014-04-03 17:40:00,89.91406622409525\n2014-04-03 17:45:00,84.80361724768571\n2014-04-03 17:50:00,86.63598923537619\n2014-04-03 17:55:00,78.87851082466668\n2014-04-03 18:00:00,35.26794217805714\n2014-04-03 18:05:00,40.008613657047626\n2014-04-03 18:10:00,35.0896310886381\n2014-04-03 18:15:00,35.79932723772857\n2014-04-03 18:20:00,39.81594155741905\n2014-04-03 18:25:00,34.73738807680952\n2014-04-03 18:30:00,36.544881828\n2014-04-03 18:35:00,38.482781638990474\n2014-04-03 18:40:00,38.56325425248095\n2014-04-03 18:45:00,39.73359355667143\n2014-04-03 18:50:00,38.0051837822619\n2014-04-03 18:55:00,38.03486819035238\n2014-04-03 19:00:00,29.391532951442855\n2014-04-03 19:05:00,28.38341970033333\n2014-04-03 19:10:00,28.88306262182381\n2014-04-03 19:15:00,30.186490784914284\n2014-04-03 19:20:00,27.97040407140476\n2014-04-03 19:25:00,27.90470435519524\n2014-04-03 19:30:00,26.202684091085715\n2014-04-03 19:35:00,28.942374585376186\n2014-04-03 19:40:00,26.335043698566665\n2014-04-03 19:45:00,28.467691147057142\n2014-04-03 19:50:00,29.819513690347627\n2014-04-03 19:55:00,28.68763325013809\n2014-04-03 20:00:00,25.60785806972857\n2014-04-03 20:05:00,27.731014642019048\n2014-04-03 20:10:00,25.623070138109526\n2014-04-03 20:15:00,86.09375\n2014-04-03 20:20:00,27.03280885749048\n2014-04-03 20:25:00,25.236935554280954\n2014-04-03 20:30:00,28.255499514271428\n2014-04-03 20:35:00,25.377348199061906\n2014-04-03 20:40:00,28.61630076685238\n2014-04-03 20:45:00,24.600336397142858\n2014-04-03 20:50:00,25.65706101193333\n2014-04-03 20:55:00,25.40390135612381\n2014-04-03 21:00:00,24.303356555514284\n2014-04-03 21:05:00,27.198087774704764\n2014-04-03 21:10:00,27.049012170795237\n2014-04-03 21:15:00,27.454052658185716\n2014-04-03 21:20:00,25.308598941676188\n2014-04-03 21:25:00,26.070188521566664\n2014-04-03 21:30:00,26.94086615825714\n2014-04-03 21:35:00,26.066715141347622\n2014-04-03 21:40:00,27.109329780238095\n2014-04-03 21:45:00,26.862144444128567\n2014-04-03 21:50:00,24.782311452119046\n2014-04-03 21:55:00,27.468127984109522\n2014-04-03 22:00:00,27.1527528233\n2014-04-03 22:05:00,26.900576420590475\n2014-04-03 22:10:00,24.903130927780953\n2014-04-03 22:15:00,25.362616320771426\n2014-04-03 22:20:00,25.871259821261905\n2014-04-03 22:25:00,25.42527578795238\n2014-04-03 22:30:00,25.22403880204286\n2014-04-03 22:35:00,27.54388657703333\n2014-04-03 22:40:00,26.88218359672381\n2014-04-03 22:45:00,26.598304214914286\n2014-04-03 22:50:00,25.246363254404763\n2014-04-03 22:55:00,28.024956890495236\n2014-04-03 23:00:00,25.107620697385713\n2014-04-03 23:05:00,27.53059644197619\n2014-04-03 23:10:00,28.225055735966663\n2014-04-03 23:15:00,27.273992464957143\n2014-04-03 23:20:00,28.344701233147617\n2014-04-03 23:25:00,26.984648568338095\n2014-04-03 23:30:00,25.257392953528573\n2014-04-03 23:35:00,25.21025955401905\n2014-04-03 23:40:00,25.70077192430952\n2014-04-03 23:45:00,24.438231555\n2014-04-03 23:50:00,27.14446389889048\n2014-04-03 23:55:00,25.49946442588095\n2014-04-04 00:00:00,27.689304357771427\n2014-04-04 00:05:00,25.872702506961904\n2014-04-04 00:10:00,26.36327835485238\n2014-04-04 00:15:00,28.313648523342856\n2014-04-04 00:20:00,25.427021825533334\n2014-04-04 00:25:00,27.35079019922381\n2014-04-04 00:30:00,27.493685442914284\n2014-04-04 00:35:00,25.364647392004763\n2014-04-04 00:40:00,26.49208258449524\n2014-04-04 00:45:00,25.89634341558571\n2014-04-04 00:50:00,27.59060116407619\n2014-04-04 00:55:00,27.000349942766668\n2014-04-04 01:00:00,26.421789362257144\n2014-04-04 01:05:00,27.64275067924762\n2014-04-04 01:10:00,25.473360375238094\n2014-04-04 01:15:00,27.55466609372857\n2014-04-04 01:20:00,28.009116296019048\n2014-04-04 01:25:00,28.06954591100952\n2014-04-04 01:30:00,27.6971943721\n2014-04-04 01:35:00,26.201997144190475\n2014-04-04 01:40:00,28.504613043280955\n2014-04-04 01:45:00,26.103196003871428\n2014-04-04 01:50:00,27.146763501161907\n2014-04-04 01:55:00,25.24399909325238\n2014-04-04 02:00:00,28.528938451642855\n2014-04-04 02:05:00,27.43052702083333\n2014-04-04 02:10:00,27.635533990523808\n2014-04-04 02:15:00,24.892571099314285\n2014-04-04 02:20:00,27.690576018804762\n2014-04-04 02:25:00,27.74323895499524\n2014-04-04 02:30:00,27.338876619685713\n2014-04-04 02:35:00,25.82686464567619\n2014-04-04 02:40:00,26.625426835266666\n2014-04-04 02:45:00,25.115844628057143\n2014-04-04 02:50:00,26.567895884847616\n2014-04-04 02:55:00,25.664283505638096\n2014-04-04 03:00:00,26.092816517428567\n2014-04-04 03:05:00,25.354270681219045\n2014-04-04 03:10:00,25.63152699480952\n2014-04-04 03:15:00,25.0250245673\n2014-04-04 03:20:00,28.405795941890478\n2014-04-04 03:25:00,26.855273704280954\n2014-04-04 03:30:00,26.328039313671425\n2014-04-04 03:35:00,26.888628755861905\n2014-04-04 03:40:00,27.26912529485238\n2014-04-04 03:45:00,28.450908030642857\n2014-04-04 03:50:00,25.485605142433332\n2014-04-04 03:55:00,25.96048380402381\n2014-04-04 04:00:00,28.688871631114285\n2014-04-04 04:05:00,26.277926708504765\n2014-04-04 04:10:00,24.890841841095238\n2014-04-04 04:15:00,25.39860968478571\n2014-04-04 04:20:00,24.92083099747619\n2014-04-04 04:25:00,28.782609236366667\n2014-04-04 04:30:00,25.94584053885714\n2014-04-04 04:35:00,28.53196864674762\n2014-04-04 04:40:00,28.828783198238096\n2014-04-04 04:45:00,27.252043456028574\n2014-04-04 04:50:00,24.992904307919048\n2014-04-04 04:55:00,25.193926045309524\n2014-04-04 05:00:00,26.8013562204\n2014-04-04 05:05:00,26.507128527790474\n2014-04-04 05:10:00,27.31459017548095\n2014-04-04 05:15:00,26.65271266737143\n2014-04-04 05:20:00,28.641069301861904\n2014-04-04 05:25:00,27.05116124265238\n2014-04-04 05:30:00,27.694547102942856\n2014-04-04 05:35:00,28.51302442393333\n2014-04-04 05:40:00,25.52201131282381\n2014-04-04 05:45:00,25.860902902214285\n2014-04-04 05:50:00,25.378679403804764\n2014-04-04 05:55:00,25.51539883499524\n2014-04-04 06:00:00,27.014621581985715\n2014-04-04 06:05:00,26.256443226376188\n2014-04-04 06:10:00,26.671858024766664\n2014-04-04 06:15:00,28.91656647005714\n2014-04-04 06:20:00,25.62086501024762\n2014-04-04 06:25:00,27.164736378438093\n2014-04-04 06:30:00,25.40441319162857\n2014-04-04 06:35:00,26.29035430071905\n2014-04-04 06:40:00,27.133913218509527\n2014-04-04 06:45:00,28.8177769839\n2014-04-04 06:50:00,26.603603361290475\n2014-04-04 06:55:00,25.305757737280953\n2014-04-04 07:00:00,26.606217220371427\n2014-04-04 07:05:00,25.643976608261905\n2014-04-04 07:10:00,25.98841083415238\n2014-04-04 07:15:00,27.548255349842858\n2014-04-04 07:20:00,25.353028798133334\n2014-04-04 07:25:00,26.94966883452381\n2014-04-04 07:30:00,27.536060629714285\n2014-04-04 07:35:00,26.793088331404764\n2014-04-04 07:40:00,25.189600640595238\n2014-04-04 07:45:00,29.062613141885713\n2014-04-04 07:50:00,26.596439259876192\n2014-04-04 07:55:00,28.249725414366665\n2014-04-04 08:00:00,26.44544311155714\n2014-04-04 08:05:00,27.050364647047616\n2014-04-04 08:10:00,26.711592665638094\n2014-04-04 08:15:00,26.53533548942857\n2014-04-04 08:20:00,25.260024556419047\n2014-04-04 08:25:00,26.62014327520952\n2014-04-04 08:30:00,28.745459961599998\n2014-04-04 08:35:00,27.956513830590474\n2014-04-04 08:40:00,25.784072388780952\n2014-04-04 08:45:00,27.574441447071425\n2014-04-04 08:50:00,28.786185344561904\n2014-04-04 08:55:00,28.02483854485238\n2014-04-04 09:00:00,70.45425059324286\n2014-04-04 09:05:00,80.24210528893333\n2014-04-04 09:10:00,72.5480223902238\n2014-04-04 09:15:00,74.6298998483143\n2014-04-04 09:20:00,75.61744629370476\n2014-04-04 09:25:00,80.03623505759523\n2014-04-04 09:30:00,81.14664764828571\n2014-04-04 09:35:00,81.12750532847619\n2014-04-04 09:40:00,68.59984353206667\n2014-04-04 09:45:00,81.03679054685713\n2014-04-04 09:50:00,69.24621035664762\n2014-04-04 09:55:00,72.1285098279381\n2014-04-04 10:00:00,85.15404007682857\n2014-04-04 10:05:00,84.61731574091905\n2014-04-04 10:10:00,86.56140552490952\n2014-04-04 10:15:00,84.62475547\n2014-04-04 10:20:00,91.69270102419048\n2014-04-04 10:25:00,80.93194907668095\n2014-04-04 10:30:00,81.45893468007142\n2014-04-04 10:35:00,91.5033646667619\n2014-04-04 10:40:00,78.41194963425238\n2014-04-04 10:45:00,86.68877681314287\n2014-04-04 10:50:00,87.81637530943333\n2014-04-04 10:55:00,85.08928135712381\n2014-04-04 11:00:00,90.0197780865143\n2014-04-04 11:05:00,81.73364465210476\n2014-04-04 11:10:00,92.55385826809524\n2014-04-04 11:15:00,81.2280042795857\n2014-04-04 11:20:00,85.38299730487618\n2014-04-04 11:25:00,80.21281355786667\n2014-04-04 11:30:00,87.69439414035713\n2014-04-04 11:35:00,89.68243494034762\n2014-04-04 11:40:00,94.00742697983807\n2014-04-04 11:45:00,90.80408143092856\n2014-04-04 11:50:00,87.65881983091903\n2014-04-04 11:55:00,93.89290056490952\n2014-04-04 12:00:00,87.0594034214\n2014-04-04 12:05:00,88.38955577719048\n2014-04-04 12:10:00,88.95461230338096\n2014-04-04 12:15:00,85.98772543197143\n2014-04-04 12:20:00,92.8429860861619\n2014-04-04 12:25:00,82.41006202445239\n2014-04-04 12:30:00,88.32506493304287\n2014-04-04 12:35:00,91.00754855383333\n2014-04-04 12:40:00,93.91938621702381\n2014-04-04 12:45:00,93.60628739541428\n2014-04-04 12:50:00,87.61808157920476\n2014-04-04 12:55:00,89.77367975689526\n2014-04-04 13:00:00,85.87829561948571\n2014-04-04 13:05:00,87.06849259397619\n2014-04-04 13:10:00,94.08365928716667\n2014-04-04 13:15:00,94.48201713055714\n2014-04-04 13:20:00,93.92495415814761\n2014-04-04 13:25:00,81.8226105401381\n2014-04-04 13:30:00,93.21472859002857\n2014-04-04 13:35:00,94.79426702721904\n2014-04-04 13:40:00,85.41013743820952\n2014-04-04 13:45:00,87.935319029\n2014-04-04 13:50:00,92.10894284339048\n2014-04-04 13:55:00,88.64494277338095\n2014-04-04 14:00:00,95.57008878057144\n2014-04-04 14:05:00,86.9736197593619\n2014-04-04 14:10:00,91.11253145225238\n2014-04-04 14:15:00,92.37828639024286\n2014-04-04 14:20:00,87.61010451633334\n2014-04-04 14:25:00,93.4234005373238\n2014-04-04 14:30:00,88.4578122983143\n2014-04-04 14:35:00,86.31329536290477\n2014-04-04 14:40:00,81.45973521109524\n2014-04-04 14:45:00,86.03639479428571\n2014-04-04 14:50:00,91.49193980297619\n2014-04-04 14:55:00,94.49683570556667\n2014-04-04 15:00:00,83.79399774665714\n2014-04-04 15:05:00,85.45832013214762\n2014-04-04 15:10:00,82.24539915253808\n2014-04-04 15:15:00,90.84094758402857\n2014-04-04 15:20:00,95.15979524281906\n2014-04-04 15:25:00,90.05950539110951\n2014-04-04 15:30:00,89.6849384971\n2014-04-04 15:35:00,88.67500314819048\n2014-04-04 15:40:00,81.24196801658096\n2014-04-04 15:45:00,91.50607939967142\n2014-04-04 15:50:00,89.47427092676189\n2014-04-04 15:55:00,90.43253787985239\n2014-04-04 16:00:00,94.23795449414287\n2014-04-04 16:05:00,92.40779360303333\n2014-04-04 16:10:00,92.3665056143238\n2014-04-04 16:15:00,94.71423786471429\n2014-04-04 16:20:00,95.72569533450476\n2014-04-04 16:25:00,89.19471285249524\n2014-04-04 16:30:00,81.6437499859857\n2014-04-04 16:35:00,87.2551523703762\n2014-04-04 16:40:00,92.51812257496667\n2014-04-04 16:45:00,80.36757324735714\n2014-04-04 16:50:00,80.84160664514762\n2014-04-04 16:55:00,81.01337231023808\n2014-04-04 17:00:00,91.64296856522857\n2014-04-04 17:05:00,87.97250437741904\n2014-04-04 17:10:00,85.86364670560953\n2014-04-04 17:15:00,81.6585944273\n2014-04-04 17:20:00,91.69200233259049\n2014-04-04 17:25:00,85.11991830088095\n2014-04-04 17:30:00,84.23622727147144\n2014-04-04 17:35:00,90.4355874737619\n2014-04-04 17:40:00,88.95009557995238\n2014-04-04 17:45:00,85.81193325154285\n2014-04-04 17:50:00,90.28460127693333\n2014-04-04 17:55:00,84.36778882132381\n2014-04-04 18:00:00,41.922621453714285\n2014-04-04 18:05:00,38.31079023250476\n2014-04-04 18:10:00,37.86715076379524\n2014-04-04 18:15:00,41.865641443985716\n2014-04-04 18:20:00,41.39597878747619\n2014-04-04 18:25:00,38.041800357166665\n2014-04-04 18:30:00,37.624324287657146\n2014-04-04 18:35:00,42.25354522554762\n2014-04-04 18:40:00,41.865461897438095\n2014-04-04 18:45:00,38.99711983132857\n2014-04-04 18:50:00,41.12257612181905\n2014-04-04 18:55:00,37.71217903550952\n2014-04-04 19:00:00,30.556572281999998\n2014-04-04 19:05:00,28.37635107409048\n2014-04-04 19:10:00,30.054256176780953\n2014-04-04 19:15:00,28.642616144471425\n2014-04-04 19:20:00,30.443420049161904\n2014-04-04 19:25:00,30.211334949252382\n2014-04-04 19:30:00,30.320486561342854\n2014-04-04 19:35:00,28.540166449433332\n2014-04-04 19:40:00,29.964563823723807\n2014-04-04 19:45:00,31.741010637814284\n2014-04-04 19:50:00,30.012139957904758\n2014-04-04 19:55:00,31.570814304095236\n2014-04-04 20:00:00,28.15967032698571\n2014-04-04 20:05:00,28.38731470087619\n2014-04-04 20:10:00,28.97086851186667\n2014-04-04 20:15:00,30.562600088057142\n2014-04-04 20:20:00,27.121939781947617\n2014-04-04 20:25:00,26.818302668838093\n2014-04-04 20:30:00,29.18112094522857\n2014-04-04 20:35:00,30.585870456019048\n2014-04-04 20:40:00,30.759715204909526\n2014-04-04 20:45:00,28.696386512300002\n2014-04-04 20:50:00,28.637952551990473\n2014-04-04 20:55:00,29.369902304480952\n2014-04-04 21:00:00,28.62317859507143\n2014-04-04 21:05:00,28.945938575461906\n2014-04-04 21:10:00,29.91763081925238\n2014-04-04 21:15:00,29.41184656194286\n2014-04-04 21:20:00,28.416782896833332\n2014-04-04 21:25:00,28.28349939432381\n2014-04-04 21:30:00,29.005301582814287\n2014-04-04 21:35:00,28.273629411504764\n2014-04-04 21:40:00,28.28940195799524\n2014-04-04 21:45:00,26.522472350385712\n2014-04-04 21:50:00,27.16397472557619\n2014-04-04 21:55:00,28.435250639466666\n2014-04-04 22:00:00,29.703909957857142\n2014-04-04 22:05:00,27.533555948247617\n2014-04-04 22:10:00,28.517598768638095\n2014-04-04 22:15:00,27.81363155532857\n2014-04-04 22:20:00,26.859517444019048\n2014-04-04 22:25:00,30.284213311509525\n2014-04-04 22:30:00,29.8767574181\n2014-04-04 22:35:00,26.776491575990477\n2014-04-04 22:40:00,29.351573975080953\n2014-04-04 22:45:00,27.86875574327143\n2014-04-04 22:50:00,30.467761345461906\n2014-04-04 22:55:00,27.70273766115238\n2014-04-04 23:00:00,27.440735987842857\n2014-04-04 23:05:00,28.76503766453333\n2014-04-04 23:10:00,29.84162583772381\n2014-04-04 23:15:00,27.278143625614284\n2014-04-04 23:20:00,29.35351666010476\n2014-04-04 23:25:00,26.768474729095235\n2014-04-04 23:30:00,30.20668642648571\n2014-04-04 23:35:00,26.86204411877619\n2014-04-04 23:40:00,30.202750299566667\n2014-04-04 23:45:00,28.516169078657143\n2014-04-04 23:50:00,28.352712202247616\n2014-04-04 23:55:00,30.461419910938098\n2014-04-05 00:00:00,30.532965282228574\n2014-04-05 00:05:00,29.179581551419048\n2014-04-05 00:10:00,27.09478669120952\n2014-04-05 00:15:00,28.6184303426\n2014-04-05 00:20:00,28.717842879990478\n2014-04-05 00:25:00,28.666416664880952\n2014-04-05 00:30:00,28.89403878267143\n2014-04-05 00:35:00,26.698410759961906\n2014-04-05 00:40:00,29.47586150685238\n2014-04-05 00:45:00,29.487970064942857\n2014-04-05 00:50:00,27.10771243403333\n2014-04-05 00:55:00,28.934231579323807\n2014-04-05 01:00:00,28.934159015414284\n2014-04-05 01:05:00,29.39795644270476\n2014-04-05 01:10:00,27.017186006595235\n2014-04-05 01:15:00,29.189048943385714\n2014-04-05 01:20:00,27.81348399347619\n2014-04-05 01:25:00,28.725928628666665\n2014-04-05 01:30:00,29.798651353657142\n2014-04-05 01:35:00,29.535381364547618\n2014-04-05 01:40:00,27.195850165938094\n2014-04-05 01:45:00,29.09241771992857\n2014-04-05 01:50:00,30.611585171419048\n2014-04-05 01:55:00,27.369637273109525\n2014-04-05 02:00:00,30.1616283509\n2014-04-05 02:05:00,29.567632798390477\n2014-04-05 02:10:00,29.860894203980955\n2014-04-05 02:15:00,27.900154737171427\n2014-04-05 02:20:00,27.931317622261904\n2014-04-05 02:25:00,30.411280204052378\n2014-04-05 02:30:00,28.233970985542854\n2014-04-05 02:35:00,27.05414489613333\n2014-04-05 02:40:00,29.21191062382381\n2014-04-05 02:45:00,27.316234961914283\n2014-04-05 02:50:00,30.010789727504758\n2014-04-05 02:55:00,29.398831008095236\n2014-04-05 03:00:00,30.338191735185717\n2014-04-05 03:05:00,29.98607518957619\n2014-04-05 03:10:00,27.302621260066665\n2014-04-05 03:15:00,28.38588984855714\n2014-04-05 03:20:00,29.967288618747617\n2014-04-05 03:25:00,28.545853988338095\n2014-04-05 03:30:00,30.77339051052857\n2014-04-05 03:35:00,29.834330847219046\n2014-04-05 03:40:00,26.960809190609524\n2014-04-05 03:45:00,30.4261927662\n2014-04-05 03:50:00,27.316909615690477\n2014-04-05 03:55:00,27.483225849080952\n2014-04-05 04:00:00,29.866541030971426\n2014-04-05 04:05:00,30.395886142461904\n2014-04-05 04:10:00,29.08885089255238\n2014-04-05 04:15:00,28.10709178894286\n2014-04-05 04:20:00,28.36359551433333\n2014-04-05 04:25:00,28.33733112792381\n2014-04-05 04:30:00,28.279926700914285\n2014-04-05 04:35:00,27.95229344920476\n2014-04-05 04:40:00,29.423563616595235\n2014-04-05 04:45:00,30.59715698858571\n2014-04-05 04:50:00,28.23130584277619\n2014-04-05 04:55:00,27.757193856466664\n2014-04-05 05:00:00,30.37216780835714\n2014-04-05 05:05:00,29.992430942647616\n2014-04-05 05:10:00,30.756086221438093\n2014-04-05 05:15:00,27.70225751382857\n2014-04-05 05:20:00,27.62462430411905\n2014-04-05 05:25:00,29.220777101009524\n2014-04-05 05:30:00,29.520234619300002\n2014-04-05 05:35:00,28.990634243590478\n2014-04-05 05:40:00,29.47324749768095\n2014-04-05 05:45:00,27.80634050407143\n2014-04-05 05:50:00,29.010716921461906\n2014-04-05 05:55:00,29.73207262475238\n2014-04-05 06:00:00,28.837968654142855\n2014-04-05 06:05:00,29.83237267663333\n2014-04-05 06:10:00,28.926788931723806\n2014-04-05 06:15:00,28.463862609114283\n2014-04-05 06:20:00,28.351324950204763\n2014-04-05 06:25:00,28.787953474095236\n2014-04-05 06:30:00,27.244144204985716\n2014-04-05 06:35:00,29.833326744276192\n2014-04-05 06:40:00,30.54708923056667\n2014-04-05 06:45:00,28.59261552065714\n2014-04-05 06:50:00,27.365680163647617\n2014-04-05 06:55:00,31.136090484738094\n2014-04-05 07:00:00,28.25122159322857\n2014-04-05 07:05:00,27.71035353441905\n2014-04-05 07:10:00,28.69031955570952\n2014-04-05 07:15:00,30.1729781625\n2014-04-05 07:20:00,28.401856863790478\n2014-04-05 07:25:00,29.532443768080952\n2014-04-05 07:30:00,28.903311406271428\n2014-04-05 07:35:00,27.719567873861905\n2014-04-05 07:40:00,28.57710043095238\n2014-04-05 07:45:00,30.162874880042857\n2014-04-05 07:50:00,29.718848922633335\n2014-04-05 07:55:00,27.757387329023807\n2014-04-05 08:00:00,27.939003924614287\n2014-04-05 08:05:00,29.85608819910476\n2014-04-05 08:10:00,30.554256895395238\n2014-04-05 08:15:00,28.705933698085715\n2014-04-05 08:20:00,29.696719197876188\n2014-04-05 08:25:00,28.005491021666664\n2014-04-05 08:30:00,28.57586249045714\n2014-04-05 08:35:00,27.418878441747616\n2014-04-05 08:40:00,30.418341886438093\n2014-04-05 08:45:00,28.95671785052857\n2014-04-05 08:50:00,30.624621342219047\n2014-04-05 08:55:00,30.201051507909526\n2014-04-05 09:00:00,81.84592201390001\n2014-04-05 09:05:00,74.46739838249049\n2014-04-05 09:10:00,73.10735968618096\n2014-04-05 09:15:00,83.81523871267143\n2014-04-05 09:20:00,80.36041980856191\n2014-04-05 09:25:00,81.95517722475238\n2014-04-05 09:30:00,70.79825673964285\n2014-04-05 09:35:00,75.44776136933334\n2014-04-05 09:40:00,80.7368308014238\n2014-04-05 09:45:00,71.70253081441427\n2014-04-05 09:50:00,78.36522780400476\n2014-04-05 09:55:00,76.49223487549524\n2014-04-05 10:00:00,79.57769390508571\n2014-04-05 10:05:00,82.97406714737619\n2014-04-05 10:10:00,83.73913833696668\n2014-04-05 10:15:00,81.06267351015714\n2014-04-05 10:20:00,89.13550045824762\n2014-04-05 10:25:00,83.10350313463809\n2014-04-05 10:30:00,83.65758320552857\n2014-04-05 10:35:00,93.29703209171905\n2014-04-05 10:40:00,86.61355992240952\n2014-04-05 10:45:00,85.457078841\n2014-04-05 10:50:00,90.61316899079048\n2014-04-05 10:55:00,93.50333707998095\n2014-04-05 11:00:00,81.51974932007143\n2014-04-05 11:05:00,88.2578025203619\n2014-04-05 11:10:00,90.85031906805239\n2014-04-05 11:15:00,86.21032036974286\n2014-04-05 11:20:00,93.43570574593333\n2014-04-05 11:25:00,96.60914513512381\n2014-04-05 11:30:00,96.17048311851428\n2014-04-05 11:35:00,85.40384106820476\n2014-04-05 11:40:00,84.78077921839524\n2014-04-05 11:45:00,96.41646511968571\n2014-04-05 11:50:00,88.49000365457618\n2014-04-05 11:55:00,84.51618365456667\n2014-04-05 12:00:00,92.85483421925714\n2014-04-05 12:05:00,86.10916193124763\n2014-04-05 12:10:00,85.8421585544381\n2014-04-05 12:15:00,95.62988167902857\n2014-04-05 12:20:00,84.18276590191905\n2014-04-05 12:25:00,82.62271032270952\n2014-04-05 12:30:00,85.9029146631\n2014-04-05 12:35:00,91.30801372969049\n2014-04-05 12:40:00,83.58302332008095\n2014-04-05 12:45:00,89.15988156727143\n2014-04-05 12:50:00,91.65621079906191\n2014-04-05 12:55:00,95.20179851215238\n2014-04-05 13:00:00,85.39189361714286\n2014-04-05 13:05:00,94.79670589753333\n2014-04-05 13:10:00,85.48734194762382\n2014-04-05 13:15:00,92.56285016201431\n2014-04-05 13:20:00,88.63374811910477\n2014-04-05 13:25:00,83.58652474019524\n2014-04-05 13:30:00,93.18497834778572\n2014-04-05 13:35:00,85.25031187877619\n2014-04-05 13:40:00,84.59968324906667\n2014-04-05 13:45:00,87.51361804025714\n2014-04-05 13:50:00,92.23940290064762\n2014-04-05 13:55:00,85.53975320943809\n2014-04-05 14:00:00,84.75641613982857\n2014-04-05 14:05:00,81.98466341461905\n2014-04-05 14:10:00,89.37878085550952\n2014-04-05 14:15:00,88.6982939092\n2014-04-05 14:20:00,85.58943876399047\n2014-04-05 14:25:00,82.71356837168095\n2014-04-05 14:30:00,88.73037975357143\n2014-04-05 14:35:00,94.4807323403619\n2014-04-05 14:40:00,93.32146114555238\n2014-04-05 14:45:00,95.65699400444285\n2014-04-05 14:50:00,82.04569297723333\n2014-04-05 14:55:00,97.3617846683238\n2014-04-05 15:00:00,87.37256668681428\n2014-04-05 15:05:00,97.76367617430476\n2014-04-05 15:10:00,85.96677660539524\n2014-04-05 15:15:00,89.47685428758571\n2014-04-05 15:20:00,87.60257345237619\n2014-04-05 15:25:00,87.63934226176667\n2014-04-05 15:30:00,95.43105014825714\n2014-04-05 15:35:00,93.90469480484762\n2014-04-05 15:40:00,97.8438174644381\n2014-04-05 15:45:00,91.79312805902858\n2014-04-05 15:50:00,89.39646236171905\n2014-04-05 15:55:00,83.43303629560953\n2014-04-05 16:00:00,97.94481385790002\n2014-04-05 16:05:00,90.83177574009048\n2014-04-05 16:10:00,93.22236070878095\n2014-04-05 16:15:00,88.53004888847143\n2014-04-05 16:20:00,90.79305816976189\n2014-04-05 16:25:00,97.1182788952524\n2014-04-05 16:30:00,84.70721051164286\n2014-04-05 16:35:00,86.72989746093333\n2014-04-05 16:40:00,84.4923365427238\n2014-04-05 16:45:00,94.74225616971427\n2014-04-05 16:50:00,83.06698878260475\n2014-04-05 16:55:00,83.38781088799524\n2014-04-05 17:00:00,86.86516203698571\n2014-04-05 17:05:00,90.32370627807619\n2014-04-05 17:10:00,88.60453333146667\n2014-04-05 17:15:00,82.82864019025713\n2014-04-05 17:20:00,97.43887901414762\n2014-04-05 17:25:00,97.37236691853809\n2014-04-05 17:30:00,86.60360037892858\n2014-04-05 17:35:00,93.84574674941905\n2014-04-05 17:40:00,91.40598490320951\n2014-04-05 17:45:00,85.95584801300001\n2014-04-05 17:50:00,86.35840604529048\n2014-04-05 17:55:00,90.02955107568094\n2014-04-05 18:00:00,41.66168180937143\n2014-04-05 18:05:00,40.849873717961906\n2014-04-05 18:10:00,44.16152007545238\n2014-04-05 18:15:00,42.082249408842856\n2014-04-05 18:20:00,43.19935459833333\n2014-04-05 18:25:00,40.22711844842381\n2014-04-05 18:30:00,42.437657140614284\n2014-04-05 18:35:00,41.06569555800477\n2014-04-05 18:40:00,42.40713616819524\n2014-04-05 18:45:00,44.04281455908571\n2014-04-05 18:50:00,43.97401426057619\n2014-04-05 18:55:00,41.32742304126667\n2014-04-05 19:00:00,33.538217350857146\n2014-04-05 19:05:00,34.65227525954762\n2014-04-05 19:10:00,33.245735433638096\n2014-04-05 19:15:00,31.11505478182857\n2014-04-05 19:20:00,33.50271243381904\n2014-04-05 19:25:00,30.935030042909524\n2014-04-05 19:30:00,34.3795533111\n2014-04-05 19:35:00,32.794578264490475\n2014-04-05 19:40:00,32.212810250480956\n2014-04-05 19:45:00,30.750209852671432\n2014-04-05 19:50:00,32.20817183626191\n2014-04-05 19:55:00,34.55606692535238\n2014-04-05 20:00:00,28.875088987742856\n2014-04-05 20:05:00,30.740741943133333\n2014-04-05 20:10:00,32.61804708372381\n2014-04-05 20:15:00,30.428732780114284\n2014-04-05 20:20:00,30.57271213550476\n2014-04-05 20:25:00,31.196126974595238\n2014-04-05 20:30:00,30.72997678868571\n2014-04-05 20:35:00,29.53181848827619\n2014-04-05 20:40:00,28.924669932566665\n2014-04-05 20:45:00,31.353895442757143\n2014-04-05 20:50:00,32.63517113294762\n2014-04-05 20:55:00,29.306655357738094\n2014-04-05 21:00:00,29.380689694328574\n2014-04-05 21:05:00,30.02829534921905\n2014-04-05 21:10:00,31.798206238509522\n2014-04-05 21:15:00,29.6373610171\n2014-04-05 21:20:00,32.10774348499048\n2014-04-05 21:25:00,28.790917597380954\n2014-04-05 21:30:00,32.35936422727143\n2014-04-05 21:35:00,30.838666510361904\n2014-04-05 21:40:00,31.24011157565238\n2014-04-05 21:45:00,30.07761053824286\n2014-04-05 21:50:00,31.75022471373333\n2014-04-05 21:55:00,29.284136836023812\n2014-04-05 22:00:00,28.748829399314285\n2014-04-05 22:05:00,30.144021309804764\n2014-04-05 22:10:00,31.985936274995236\n2014-04-05 22:15:00,31.597921969585713\n2014-04-05 22:20:00,30.65336594147619\n2014-04-05 22:25:00,30.880944654266663\n2014-04-05 22:30:00,29.117707227357144\n2014-04-05 22:35:00,31.971031860047617\n2014-04-05 22:40:00,31.763378741838096\n2014-04-05 22:45:00,31.24836098312857\n2014-04-05 22:50:00,30.493953356719047\n2014-04-05 22:55:00,32.49638010980952\n2014-04-05 23:00:00,32.1452589819\n2014-04-05 23:05:00,31.214113370890473\n2014-04-05 23:10:00,30.130826484480952\n2014-04-05 23:15:00,31.123341182371433\n2014-04-05 23:20:00,30.960423547561902\n2014-04-05 23:25:00,30.24292910825238\n2014-04-05 23:30:00,29.900030267642855\n2014-04-05 23:35:00,30.308895084633335\n2014-04-05 23:40:00,30.98406619562381\n2014-04-05 23:45:00,30.408288470214284\n2014-04-05 23:50:00,29.75736113800476\n2014-04-05 23:55:00,31.75473892689524\n2014-04-06 00:00:00,30.840155698085717\n2014-04-06 00:05:00,28.99242684337619\n2014-04-06 00:10:00,30.202432689166663\n2014-04-06 00:15:00,32.276260971657145\n2014-04-06 00:20:00,31.76499374384762\n2014-04-06 00:25:00,30.044475231038096\n2014-04-06 00:30:00,32.511661179628575\n2014-04-06 00:35:00,29.072780681019047\n2014-04-06 00:40:00,32.61874833940952\n2014-04-06 00:45:00,29.7640703699\n2014-04-06 00:50:00,28.825067197390474\n2014-04-06 00:55:00,30.531363098480952\n2014-04-06 01:00:00,30.239453147271426\n2014-04-06 01:05:00,30.967367925561902\n2014-04-06 01:10:00,32.00554382325238\n2014-04-06 01:15:00,32.195616065742854\n2014-04-06 01:20:00,30.438253331733332\n2014-04-06 01:25:00,30.56015678432381\n2014-04-06 01:30:00,29.440925207014285\n2014-04-06 01:35:00,29.04584519740476\n2014-04-06 01:40:00,31.427955198995235\n2014-04-06 01:45:00,29.128286216485712\n2014-04-06 01:50:00,31.81329666817619\n2014-04-06 01:55:00,31.041777246766664\n2014-04-06 02:00:00,29.68718905575714\n2014-04-06 02:05:00,31.05838939314762\n2014-04-06 02:10:00,29.639728961638095\n2014-04-06 02:15:00,30.670127401428573\n2014-04-06 02:20:00,32.120860312619044\n2014-04-06 02:25:00,30.777736697409523\n2014-04-06 02:30:00,29.5322972732\n2014-04-06 02:35:00,31.84025520349048\n2014-04-06 02:40:00,29.699454617480953\n2014-04-06 02:45:00,31.91402092607143\n2014-04-06 02:50:00,30.884671061661905\n2014-04-06 02:55:00,30.789669417352382\n2014-04-06 03:00:00,32.38788300854286\n2014-04-06 03:05:00,31.823997430733332\n2014-04-06 03:10:00,29.128666997323805\n2014-04-06 03:15:00,30.189161544114285\n2014-04-06 03:20:00,32.49558740530476\n2014-04-06 03:25:00,29.092649912295236\n2014-04-06 03:30:00,31.207799499285713\n2014-04-06 03:35:00,31.94552886717619\n2014-04-06 03:40:00,31.529091008566667\n2014-04-06 03:45:00,32.09123595125714\n2014-04-06 03:50:00,31.959315014747617\n2014-04-06 03:55:00,31.832110875838094\n2014-04-06 04:00:00,32.35758801512857\n2014-04-06 04:05:00,31.66163172141905\n2014-04-06 04:10:00,30.695983500809525\n2014-04-06 04:15:00,30.9813864397\n2014-04-06 04:20:00,31.968089606890473\n2014-04-06 04:25:00,32.61385507108095\n2014-04-06 04:30:00,30.20494663197143\n2014-04-06 04:35:00,30.491819088661906\n2014-04-06 04:40:00,32.853909966352376\n2014-04-06 04:45:00,31.452440026742856\n2014-04-06 04:50:00,29.86168060183333\n2014-04-06 04:55:00,31.80805436512381\n2014-04-06 05:00:00,33.12376290791428\n2014-04-06 05:05:00,32.46196901980476\n2014-04-06 05:10:00,32.158559784295235\n2014-04-06 05:15:00,30.015222331385715\n2014-04-06 05:20:00,32.69503532917619\n2014-04-06 05:25:00,31.30107204076667\n2014-04-06 05:30:00,32.76251723115714\n2014-04-06 05:35:00,30.53210893674762\n2014-04-06 05:40:00,29.468442305738094\n2014-04-06 05:45:00,31.131582446028574\n2014-04-06 05:50:00,30.314469466919046\n2014-04-06 05:55:00,32.10347668290952\n2014-04-06 06:00:00,33.0784262114\n2014-04-06 06:05:00,32.021337080790474\n2014-04-06 06:10:00,32.812616671180955\n2014-04-06 06:15:00,31.084417482971432\n2014-04-06 06:20:00,32.366324853561906\n2014-04-06 06:25:00,32.65937612765238\n2014-04-06 06:30:00,32.13814536744285\n2014-04-06 06:35:00,31.333192477633332\n2014-04-06 06:40:00,31.812988248023807\n2014-04-06 06:45:00,32.11899226841429\n2014-04-06 06:50:00,30.336742374804757\n2014-04-06 06:55:00,32.570162281795234\n2014-04-06 07:00:00,33.140583870185715\n2014-04-06 07:05:00,31.207683451176187\n2014-04-06 07:10:00,32.15843539906667\n2014-04-06 07:15:00,32.30971076605714\n2014-04-06 07:20:00,32.01803780914762\n2014-04-06 07:25:00,31.564948528538093\n2014-04-06 07:30:00,32.91052038972857\n2014-04-06 07:35:00,31.187075884719047\n2014-04-06 07:40:00,29.64322134970952\n2014-04-06 07:45:00,32.7844755028\n2014-04-06 07:50:00,32.10961556549048\n2014-04-06 07:55:00,32.81816545838095\n2014-04-06 08:00:00,29.982761198371428\n2014-04-06 08:05:00,29.559023666761902\n2014-04-06 08:10:00,33.18095054245238\n2014-04-06 08:15:00,30.041806080542855\n2014-04-06 08:20:00,32.69694266163333\n2014-04-06 08:25:00,32.75861357822381\n2014-04-06 08:30:00,32.308035087914284\n2014-04-06 08:35:00,30.005703606304763\n2014-04-06 08:40:00,32.15768973629524\n2014-04-06 08:45:00,33.051882047585714\n2014-04-06 08:50:00,31.20510276967619\n2014-04-06 08:55:00,31.164484084166666\n2014-04-06 09:00:00,78.74073015315713\n2014-04-06 09:05:00,73.84419533224761\n2014-04-06 09:10:00,84.8642858340381\n2014-04-06 09:15:00,84.56106552152858\n2014-04-06 09:20:00,86.31918582391906\n2014-04-06 09:25:00,80.71355024820951\n2014-04-06 09:30:00,82.97870625569999\n2014-04-06 09:35:00,75.52627840199048\n2014-04-06 09:40:00,81.85577288018095\n2014-04-06 09:45:00,81.62118817167143\n2014-04-06 09:50:00,85.04870071216189\n2014-04-06 09:55:00,84.09848341155238\n2014-04-06 10:00:00,96.01214235694286\n2014-04-06 10:05:00,94.93887882963332\n2014-04-06 10:10:00,94.9441530583238\n2014-04-06 10:15:00,82.45845031591429\n2014-04-06 10:20:00,94.60623426770476\n2014-04-06 10:25:00,90.91240992079524\n2014-04-06 10:30:00,87.39628360568571\n2014-04-06 10:35:00,82.37633316097619\n2014-04-06 10:40:00,92.02416365106667\n2014-04-06 10:45:00,86.60779831115714\n2014-04-06 10:50:00,88.78143525164762\n2014-04-06 10:55:00,92.1094134383381\n2014-04-06 11:00:00,97.76529096732857\n2014-04-06 11:05:00,96.39961775341905\n2014-04-06 11:10:00,90.44560626510952\n2014-04-06 11:15:00,89.454053336\n2014-04-06 11:20:00,87.10764744279048\n2014-04-06 11:25:00,89.22470600308094\n2014-04-06 11:30:00,85.07515317207144\n2014-04-06 11:35:00,98.7609739097619\n2014-04-06 11:40:00,92.45153540965238\n2014-04-06 11:45:00,85.36401698094286\n2014-04-06 11:50:00,88.94986010473333\n2014-04-06 11:55:00,92.0463843496238\n2014-04-06 12:00:00,92.21525306771429\n2014-04-06 12:05:00,84.27412699670475\n2014-04-06 12:10:00,98.90939563789522\n2014-04-06 12:15:00,88.12235940478571\n2014-04-06 12:20:00,83.98772014777619\n2014-04-06 12:25:00,84.95815308486667\n2014-04-06 12:30:00,93.01593585265714\n2014-04-06 12:35:00,85.95332046784762\n2014-04-06 12:40:00,84.4256336648381\n2014-04-06 12:45:00,89.83301320582856\n2014-04-06 12:50:00,93.72594111021905\n2014-04-06 12:55:00,85.56844907700952\n2014-04-06 13:00:00,88.8697621355\n2014-04-06 13:05:00,90.54772702119048\n2014-04-06 13:10:00,86.42335019018094\n2014-04-06 13:15:00,91.97528048027144\n2014-04-06 13:20:00,85.2505800730619\n2014-04-06 13:25:00,84.63903969145238\n2014-04-06 13:30:00,92.21773256384286\n2014-04-06 13:35:00,87.87520297293332\n2014-04-06 13:40:00,85.44285850042381\n2014-04-06 13:45:00,90.70565786121429\n2014-04-06 13:50:00,98.57086245370476\n2014-04-06 13:55:00,95.52386348559524\n2014-04-06 14:00:00,97.01005796678571\n2014-04-06 14:05:00,97.9182243806762\n2014-04-06 14:10:00,99.53700755086668\n2014-04-06 14:15:00,96.19451014575714\n2014-04-06 14:20:00,93.72465111274762\n2014-04-06 14:25:00,89.8445655330381\n2014-04-06 14:30:00,86.91162485432856\n2014-04-06 14:35:00,94.99894367651905\n2014-04-06 14:40:00,99.93878918020951\n2014-04-06 14:45:00,91.5051740224\n2014-04-06 14:50:00,95.61354857989048\n2014-04-06 14:55:00,91.96377392128095\n2014-04-06 15:00:00,90.96374865737143\n2014-04-06 15:05:00,90.62514749876189\n2014-04-06 15:10:00,92.14167859755239\n2014-04-06 15:15:00,89.94547589184286\n2014-04-06 15:20:00,96.06290027093333\n2014-04-06 15:25:00,98.07830074682379\n2014-04-06 15:30:00,98.22355238081428\n2014-04-06 15:35:00,87.74810800220476\n2014-04-06 15:40:00,98.44681264619524\n2014-04-06 15:45:00,89.58461176168571\n2014-04-06 15:50:00,89.07616012857619\n2014-04-06 15:55:00,95.76271075526667\n2014-04-06 16:00:00,89.01785098395713\n2014-04-06 16:05:00,84.99762024164762\n2014-04-06 16:10:00,90.13547273463809\n2014-04-06 16:15:00,95.70846777372857\n2014-04-06 16:20:00,89.40380548781906\n2014-04-06 16:25:00,94.25284683970952\n2014-04-06 16:30:00,94.7492525893\n2014-04-06 16:35:00,95.93455588349048\n2014-04-06 16:40:00,98.55630261348095\n2014-04-06 16:45:00,91.13070188847144\n2014-04-06 16:50:00,86.8800317785619\n2014-04-06 16:55:00,89.32736579045238\n2014-04-06 17:00:00,91.14678863664285\n2014-04-06 17:05:00,95.66181480843333\n2014-04-06 17:10:00,84.45695008992381\n2014-04-06 17:15:00,89.30700083261428\n2014-04-06 17:20:00,96.73935361890476\n2014-04-06 17:25:00,95.00303672159525\n2014-04-06 17:30:00,95.9845931478857\n2014-04-06 17:35:00,97.27316586577619\n2014-04-06 17:40:00,96.82340570846668\n2014-04-06 17:45:00,95.21400596195714\n2014-04-06 17:50:00,91.34110178764762\n2014-04-06 17:55:00,100.05152766603808\n2014-04-06 18:00:00,44.76349079432857\n2014-04-06 18:05:00,42.426586208819046\n2014-04-06 18:10:00,43.010305907109526\n2014-04-06 18:15:00,45.5825433364\n2014-04-06 18:20:00,47.06951702759047\n2014-04-06 18:25:00,42.30243403008095\n2014-04-06 18:30:00,41.69308337057143\n2014-04-06 18:35:00,46.81530399936191\n2014-04-06 18:40:00,47.038724791652385\n2014-04-06 18:45:00,42.957214797942854\n2014-04-06 18:50:00,43.61045597613334\n2014-04-06 18:55:00,45.42847065262381\n2014-04-06 19:00:00,34.04879959211428\n2014-04-06 19:05:00,36.50782445350476\n2014-04-06 19:10:00,33.06754669389524\n2014-04-06 19:15:00,32.76319494888571\n2014-04-06 19:20:00,33.53449323957619\n2014-04-06 19:25:00,33.88958873676667\n2014-04-06 19:30:00,33.12126713815714\n2014-04-06 19:35:00,32.91708962044762\n2014-04-06 19:40:00,36.01535936013809\n2014-04-06 19:45:00,33.373636440328575\n2014-04-06 19:50:00,36.73948916891906\n2014-04-06 19:55:00,34.30119681070953\n2014-04-06 20:00:00,33.6788011425\n2014-04-06 20:05:00,31.862687305990477\n2014-04-06 20:10:00,31.931242779080954\n2014-04-06 20:15:00,33.30833007407143\n2014-04-06 20:20:00,33.2581550774619\n2014-04-06 20:25:00,34.11791703995238\n2014-04-06 20:30:00,34.08064589884285\n2014-04-06 20:35:00,33.73122016323333\n2014-04-06 20:40:00,32.831162364123806\n2014-04-06 20:45:00,34.64702704291428\n2014-04-06 20:50:00,33.55648600610476\n2014-04-06 20:55:00,35.06969798519523\n2014-04-06 21:00:00,33.968896834285715\n2014-04-06 21:05:00,30.86121613917619\n2014-04-06 21:10:00,31.979097650566665\n2014-04-06 21:15:00,32.996489972657145\n2014-04-06 21:20:00,33.605177934347616\n2014-04-06 21:25:00,32.9248004974381\n2014-04-06 21:30:00,33.87994391342857\n2014-04-06 21:35:00,31.863818600119046\n2014-04-06 21:40:00,31.474388794109522\n2014-04-06 21:45:00,30.9593518907\n2014-04-06 21:50:00,33.054353028490475\n2014-04-06 21:55:00,33.525150094880956\n2014-04-06 22:00:00,32.00170270247143\n2014-04-06 22:05:00,33.1599847973619\n2014-04-06 22:10:00,30.91956157915238\n2014-04-06 22:15:00,31.115727519742855\n2014-04-06 22:20:00,33.53532715043333\n2014-04-06 22:25:00,32.20674600852381\n2014-04-06 22:30:00,33.42840832261429\n2014-04-06 22:35:00,34.07801304160476\n2014-04-06 22:40:00,34.16913904759524\n2014-04-06 22:45:00,31.45214741068571\n2014-04-06 22:50:00,32.71726580667619\n2014-04-06 22:55:00,33.71622182956666\n2014-04-06 23:00:00,33.867829942957144\n2014-04-06 23:05:00,33.91806017104762\n2014-04-06 23:10:00,31.699038663438095\n2014-04-06 23:15:00,31.563921707228573\n2014-04-06 23:20:00,33.16157804831904\n2014-04-06 23:25:00,33.773427866609524\n2014-04-06 23:30:00,32.0927591594\n2014-04-06 23:35:00,31.242297515390476\n2014-04-06 23:40:00,33.698372943180956\n2014-04-06 23:45:00,32.03729892017142\n2014-04-06 23:50:00,31.511296566761906\n2014-04-06 23:55:00,31.444165944352378\n2014-04-07 00:00:00,32.11678104724285\n2014-04-07 00:05:00,33.23529559703333\n2014-04-07 00:10:00,32.30563276432381\n2014-04-07 00:15:00,30.962111692114284\n2014-04-07 00:20:00,31.274538500604763\n2014-04-07 00:25:00,32.05635822689524\n2014-04-07 00:30:00,33.54060364288571\n2014-04-07 00:35:00,31.30328648437619\n2014-04-07 00:40:00,33.15929408066667\n2014-04-07 00:45:00,31.40365062615714\n2014-04-07 00:50:00,31.77800892844762\n2014-04-07 00:55:00,31.627742205438096\n2014-04-07 01:00:00,31.215343113728572\n2014-04-07 01:05:00,33.63918831711905\n2014-04-07 01:10:00,32.814923713309526\n2014-04-07 01:15:00,34.2929637636\n2014-04-07 01:20:00,31.371753836090477\n2014-04-07 01:25:00,31.562562685780946\n2014-04-07 01:30:00,32.21690235397143\n2014-04-07 01:35:00,34.0619758525619\n2014-04-07 01:40:00,32.22898767355238\n2014-04-07 01:45:00,32.64706768714286\n2014-04-07 01:50:00,32.22724759853333\n2014-04-07 01:55:00,31.349170976723812\n2014-04-07 02:00:00,34.79344877731428\n2014-04-07 02:05:00,33.23731073020476\n2014-04-07 02:10:00,34.20192799079524\n2014-04-07 02:15:00,33.69146408298571\n2014-04-07 02:20:00,33.12249330667619\n2014-04-07 02:25:00,31.431629693266665\n2014-04-07 02:30:00,33.65129132395714\n2014-04-07 02:35:00,31.709279042747617\n2014-04-07 02:40:00,32.752770772638094\n2014-04-07 02:45:00,33.61913114532857\n2014-04-07 02:50:00,34.239035049519046\n2014-04-07 02:55:00,33.85774022660952\n2014-04-07 03:00:00,33.811134116199995\n2014-04-07 03:05:00,31.728609312890477\n2014-04-07 03:10:00,32.52439511268095\n2014-04-07 03:15:00,31.318970519171426\n2014-04-07 03:20:00,34.0326694774619\n2014-04-07 03:25:00,34.97254630625238\n2014-04-07 03:30:00,32.226084417842856\n2014-04-07 03:35:00,31.527870169933333\n2014-04-07 03:40:00,33.08680411652381\n2014-04-07 03:45:00,34.61875717821428\n2014-04-07 03:50:00,33.40730154300476\n2014-04-07 03:55:00,31.393953838895236\n2014-04-07 04:00:00,35.111374676385715\n2014-04-07 04:05:00,34.536325830376185\n2014-04-07 04:10:00,31.755542974866664\n2014-04-07 04:15:00,34.92379816885715\n2014-04-07 04:20:00,33.04680077344762\n2014-04-07 04:25:00,32.7390800575381\n2014-04-07 04:30:00,33.10314189352857\n2014-04-07 04:35:00,34.60465687511905\n2014-04-07 04:40:00,33.911728236909525\n2014-04-07 04:45:00,31.5182438096\n2014-04-07 04:50:00,35.11910796069048\n2014-04-07 04:55:00,31.887267486280955\n2014-04-07 05:00:00,34.28584323547143\n2014-04-07 05:05:00,33.85555802646191\n2014-04-07 05:10:00,32.06856457275238\n2014-04-07 05:15:00,32.00882116164286\n2014-04-07 05:20:00,34.81464370813333\n2014-04-07 05:25:00,33.01955350352381\n2014-04-07 05:30:00,33.966520342414285\n2014-04-07 05:35:00,33.37193877730476\n2014-04-07 05:40:00,34.272509306395236\n2014-04-07 05:45:00,33.28750521448571\n2014-04-07 05:50:00,32.52749585147619\n2014-04-07 05:55:00,32.83895015066667\n2014-04-07 06:00:00,34.82916792065714\n2014-04-07 06:05:00,33.27243639074762\n2014-04-07 06:10:00,32.2615354242381\n2014-04-07 06:15:00,35.15360012372857\n2014-04-07 06:20:00,34.609020873619045\n2014-04-07 06:25:00,31.652724108009522\n2014-04-07 06:30:00,35.4332718479\n2014-04-07 06:35:00,34.22464726199048\n2014-04-07 06:40:00,32.09344734858095\n2014-04-07 06:45:00,32.40849215377143\n2014-04-07 06:50:00,34.2370438297619\n2014-04-07 06:55:00,34.59374660205238\n2014-04-07 07:00:00,32.438286629742855\n2014-04-07 07:05:00,32.517458748933336\n2014-04-07 07:10:00,32.72550658902381\n2014-04-07 07:15:00,33.896537745014285\n2014-04-07 07:20:00,32.19916947510476\n2014-04-07 07:25:00,31.936318033595235\n2014-04-07 07:30:00,34.24224207058572\n2014-04-07 07:35:00,34.65061794967619\n2014-04-07 07:40:00,33.54538428436667\n2014-04-07 07:45:00,33.004437983957146\n2014-04-07 07:50:00,33.28471847314762\n2014-04-07 07:55:00,33.117619430738095\n2014-04-07 08:00:00,35.41136820442857\n2014-04-07 08:05:00,34.651228668519046\n2014-04-07 08:10:00,32.418658383209525\n2014-04-07 08:15:00,33.1305066082\n2014-04-07 08:20:00,33.77723964169048\n2014-04-07 08:25:00,34.06057440068095\n2014-04-07 08:30:00,33.48880701267143\n2014-04-07 08:35:00,34.8640184447619\n2014-04-07 08:40:00,34.70137645875238\n2014-04-07 08:45:00,33.65902453164286\n2014-04-07 08:50:00,35.06355088043333\n2014-04-07 08:55:00,34.657631931323806\n2014-04-07 09:00:00,85.4494274283143\n2014-04-07 09:05:00,87.87520536220475\n2014-04-07 09:10:00,78.49954563849523\n2014-04-07 09:15:00,78.5230507224857\n2014-04-07 09:20:00,86.98022686787618\n2014-04-07 09:25:00,85.40019534466667\n2014-04-07 09:30:00,87.50637650635714\n2014-04-07 09:35:00,75.77136779944762\n2014-04-07 09:40:00,83.45773434603808\n2014-04-07 09:45:00,76.89462396992857\n2014-04-07 09:50:00,81.78812094441905\n2014-04-07 09:55:00,77.06071779700952\n2014-04-07 10:00:00,85.5777784594\n2014-04-07 10:05:00,83.78629319649048\n2014-04-07 10:10:00,93.38618732058094\n2014-04-07 10:15:00,89.18435243957144\n2014-04-07 10:20:00,85.25228408606192\n2014-04-07 10:25:00,88.63764469135238\n2014-04-07 10:30:00,86.25665515644286\n2014-04-07 10:35:00,98.25718711823333\n2014-04-07 10:40:00,88.61599963652381\n2014-04-07 10:45:00,88.83992296721428\n2014-04-07 10:50:00,96.69900097470476\n2014-04-07 10:55:00,93.72501465329525\n2014-04-07 11:00:00,96.70185495838571\n2014-04-07 11:05:00,95.5296988810762\n2014-04-07 11:10:00,100.47047236656667\n2014-04-07 11:15:00,88.72174836795715\n2014-04-07 11:20:00,101.16672771994762\n2014-04-07 11:25:00,98.66001514313808\n2014-04-07 11:30:00,94.81894862492857\n2014-04-07 11:35:00,95.99372736201904\n2014-04-07 11:40:00,95.78573626370951\n2014-04-07 11:45:00,86.4029835474\n2014-04-07 11:50:00,88.94902486889049\n2014-04-07 11:55:00,100.78036389988095\n2014-04-07 12:00:00,94.38174249327143\n2014-04-07 12:05:00,91.8960051677619\n2014-04-07 12:10:00,98.03503665665238\n2014-04-07 12:15:00,94.24672517594286\n2014-04-07 12:20:00,86.08228495103333\n2014-04-07 12:25:00,97.64503959512382\n2014-04-07 12:30:00,97.58823666941427\n2014-04-07 12:35:00,88.53346330040476\n2014-04-07 12:40:00,101.18988877919524\n2014-04-07 12:45:00,89.48736678278571\n2014-04-07 12:50:00,93.23177728077619\n2014-04-07 12:55:00,87.75758911636667\n2014-04-07 13:00:00,95.65077764995713\n2014-04-07 13:05:00,92.01379380764762\n2014-04-07 13:10:00,91.6648773045381\n2014-04-07 13:15:00,99.25135301572857\n2014-04-07 13:20:00,86.18328973621905\n2014-04-07 13:25:00,98.8018637425095\n2014-04-07 13:30:00,95.18620268949999\n2014-04-07 13:35:00,101.82645007359048\n2014-04-07 13:40:00,95.48892902008096\n2014-04-07 13:45:00,86.95339491907143\n2014-04-07 13:50:00,86.8851126497619\n2014-04-07 13:55:00,100.20947885545239\n2014-04-07 14:00:00,99.56246713284285\n2014-04-07 14:05:00,91.64510289903332\n2014-04-07 14:10:00,96.00661290752382\n2014-04-07 14:15:00,93.9590939924143\n2014-04-07 14:20:00,101.60733086210476\n2014-04-07 14:25:00,101.33953408219524\n2014-04-07 14:30:00,101.8889982625857\n2014-04-07 14:35:00,100.0182852479762\n2014-04-07 14:40:00,100.71533758346668\n2014-04-07 14:45:00,89.64694473305714\n2014-04-07 14:50:00,99.47356202964762\n2014-04-07 14:55:00,97.5267015042381\n2014-04-07 15:00:00,101.60017362862857\n2014-04-07 15:05:00,95.34327935691906\n2014-04-07 15:10:00,87.57327990950951\n2014-04-07 15:15:00,95.77634929850001\n2014-04-07 15:20:00,97.21068866569048\n2014-04-07 15:25:00,89.75804237048095\n2014-04-07 15:30:00,92.54613382897143\n2014-04-07 15:35:00,95.8237833994619\n2014-04-07 15:40:00,92.24089551535238\n2014-04-07 15:45:00,92.26180754094288\n2014-04-07 15:50:00,88.39950791803334\n2014-04-07 15:55:00,101.3293856800238\n2014-04-07 16:00:00,98.29346314241428\n2014-04-07 16:05:00,86.31291150560476\n2014-04-07 16:10:00,98.55024602279525\n2014-04-07 16:15:00,98.14459463028571\n2014-04-07 16:20:00,86.47103301407618\n2014-04-07 16:25:00,92.23643583426667\n2014-04-07 16:30:00,96.03816330875713\n2014-04-07 16:35:00,93.58165590024763\n2014-04-07 16:40:00,98.79285385503809\n2014-04-07 16:45:00,93.15986058352857\n2014-04-07 16:50:00,88.82178359221905\n2014-04-07 16:55:00,101.99004127670953\n2014-04-07 17:00:00,90.24761074930001\n2014-04-07 17:05:00,97.86548538739048\n2014-04-07 17:10:00,88.68035341148095\n2014-04-07 17:15:00,91.66149357967143\n2014-04-07 17:20:00,93.4771732758619\n2014-04-07 17:25:00,89.48788562435239\n2014-04-07 17:30:00,93.61896566644286\n2014-04-07 17:35:00,88.94165988763334\n2014-04-07 17:40:00,95.37859735072381\n2014-04-07 17:45:00,97.06134460021428\n2014-04-07 17:50:00,87.44832527480476\n2014-04-07 17:55:00,100.39492617519524\n2014-04-07 18:00:00,44.449181621485714\n2014-04-07 18:05:00,44.71403990597619\n2014-04-07 18:10:00,47.511799300966665\n2014-04-07 18:15:00,46.28660782405714\n2014-04-07 18:20:00,46.49017331044762\n2014-04-07 18:25:00,44.12167430933809\n2014-04-07 18:30:00,48.46563131172857\n2014-04-07 18:35:00,47.26550993481905\n2014-04-07 18:40:00,44.190248905009526\n2014-04-07 18:45:00,45.7248399598\n2014-04-07 18:50:00,48.525307520290475\n2014-04-07 18:55:00,46.98359701868095\n2014-04-07 19:00:00,35.20031682647142\n2014-04-07 19:05:00,36.391051872361906\n2014-04-07 19:10:00,35.81572212045238\n2014-04-07 19:15:00,37.054137304442854\n2014-04-07 19:20:00,38.52158987753333\n2014-04-07 19:25:00,36.705249360323805\n2014-04-07 19:30:00,36.699585369314285\n2014-04-07 19:35:00,38.82162547590476\n2014-04-07 19:40:00,37.35440463859524\n2014-04-07 19:45:00,37.317070540785714\n2014-04-07 19:50:00,35.961331335776194\n2014-04-07 19:55:00,37.518013321666665\n2014-04-07 20:00:00,35.43378616795714\n2014-04-07 20:05:00,34.70780100084762\n2014-04-07 20:10:00,37.147626863238095\n2014-04-07 20:15:00,36.70940369932857\n2014-04-07 20:20:00,36.174924233719054\n2014-04-07 20:25:00,35.31302680630952\n2014-04-07 20:30:00,35.0120967047\n2014-04-07 20:35:00,33.884279976790474\n2014-04-07 20:40:00,34.38668140978095\n2014-04-07 20:45:00,36.31196460547143\n2014-04-07 20:50:00,35.0078173765619\n2014-04-07 20:55:00,36.77047805625239\n2014-04-07 21:00:00,33.413027250642855\n2014-04-07 21:05:00,34.86913193243333\n2014-04-07 21:10:00,35.433708236123806\n2014-04-07 21:15:00,34.91818155201429\n2014-04-07 21:20:00,36.422285431604756\n2014-04-07 21:25:00,36.83299792649524\n2014-04-07 21:30:00,33.328748327685716\n2014-04-07 21:35:00,33.39294089547619\n2014-04-07 21:40:00,33.401865298366666\n2014-04-07 21:45:00,35.62329407645714\n2014-04-07 21:50:00,34.39080733414762\n2014-04-07 21:55:00,35.84772633033809\n2014-04-07 22:00:00,34.46215146382857\n2014-04-07 22:05:00,35.35898593271905\n2014-04-07 22:10:00,35.935977790909526\n2014-04-07 22:15:00,35.0559987818\n2014-04-07 22:20:00,35.02855652189047\n2014-04-07 22:25:00,33.22918706428095\n2014-04-07 22:30:00,34.52805579247143\n2014-04-07 22:35:00,35.07599629196191\n2014-04-07 22:40:00,34.74792968025238\n2014-04-07 22:45:00,36.51225985014286\n2014-04-07 22:50:00,36.54271692883333\n2014-04-07 22:55:00,36.21137948412381\n2014-04-07 23:00:00,34.41565081421429\n2014-04-07 23:05:00,35.79135825230476\n2014-04-07 23:10:00,34.51050866199524\n2014-04-07 23:15:00,33.86704474018571\n2014-04-07 23:20:00,34.31580611197619\n2014-04-07 23:25:00,33.23528569886667\n2014-04-07 23:30:00,34.28617798205714\n2014-04-07 23:35:00,34.80957633614762\n2014-04-07 23:40:00,36.796351481538096\n2014-04-07 23:45:00,34.23501761372857\n2014-04-07 23:50:00,36.59908228661905\n2014-04-07 23:55:00,33.91162438840952\n2014-04-08 00:00:00,33.763875591\n2014-04-08 00:05:00,35.08342230189047\n2014-04-08 00:10:00,35.70492642958095\n2014-04-08 00:15:00,33.19965043177143\n2014-04-08 00:20:00,33.9140253649619\n2014-04-08 00:25:00,34.85993704695238\n2014-04-08 00:30:00,34.36866020104286\n2014-04-08 00:35:00,35.90256765073333\n2014-04-08 00:40:00,35.104166193723806\n2014-04-08 00:45:00,33.70840070811428\n2014-04-08 00:50:00,36.65226627920476\n2014-04-08 00:55:00,34.25346793999524\n2014-04-08 01:00:00,36.01381015018571\n2014-04-08 01:05:00,36.216389306876195\n2014-04-08 01:10:00,36.95679746766667\n2014-04-08 01:15:00,35.105637008957146\n2014-04-08 01:20:00,35.58238968094762\n2014-04-08 01:25:00,34.465993269138096\n2014-04-08 01:30:00,35.84664574502857\n2014-04-08 01:35:00,34.99490299111905\n2014-04-08 01:40:00,34.89941898270953\n2014-04-08 01:45:00,36.5781201165\n2014-04-08 01:50:00,33.364365850190474\n2014-04-08 01:55:00,36.69898066368095\n2014-04-08 02:00:00,36.586850779871426\n2014-04-08 02:05:00,35.21147691896191\n2014-04-08 02:10:00,35.15426379775238\n2014-04-08 02:15:00,34.64812232924286\n2014-04-08 02:20:00,37.18502850003333\n2014-04-08 02:25:00,33.660451140523804\n2014-04-08 02:30:00,35.58407522821429\n2014-04-08 02:35:00,35.95738112230476\n2014-04-08 02:40:00,36.97541527099524\n2014-04-08 02:45:00,36.366349701685714\n2014-04-08 02:50:00,35.82836500167619\n2014-04-08 02:55:00,33.72766593386667\n2014-04-08 03:00:00,34.76279121015715\n2014-04-08 03:05:00,33.83066418924762\n2014-04-08 03:10:00,36.80758902513809\n2014-04-08 03:15:00,36.288663193728574\n2014-04-08 03:20:00,36.32776619481905\n2014-04-08 03:25:00,35.91408559490952\n2014-04-08 03:30:00,35.3406741477\n2014-04-08 03:35:00,33.919824714090474\n2014-04-08 03:40:00,34.64616049918095\n2014-04-08 03:45:00,33.88248459847143\n2014-04-08 03:50:00,36.2419144761619\n2014-04-08 03:55:00,33.99061748505238\n2014-04-08 04:00:00,36.16559705784285\n2014-04-08 04:05:00,36.13360489173333\n2014-04-08 04:10:00,35.20924172552381\n2014-04-08 04:15:00,33.92037890221428\n2014-04-08 04:20:00,34.646108066404764\n2014-04-08 04:25:00,34.67471767439524\n2014-04-08 04:30:00,36.203326246885716\n2014-04-08 04:35:00,33.86419826817619\n2014-04-08 04:40:00,36.732941251566665\n2014-04-08 04:45:00,36.468136303557145\n2014-04-08 04:50:00,34.17677529174762\n2014-04-08 04:55:00,36.315645622338096\n2014-04-08 05:00:00,36.12048129732857\n2014-04-08 05:05:00,36.446352248019046\n2014-04-08 05:10:00,34.217023745609524\n2014-04-08 05:15:00,34.0991112886\n2014-04-08 05:20:00,34.422126419890475\n2014-04-08 05:25:00,34.94711776498095\n2014-04-08 05:30:00,36.66573135267143\n2014-04-08 05:35:00,36.4502076546619\n2014-04-08 05:40:00,37.20775875005238\n2014-04-08 05:45:00,33.747911093542854\n2014-04-08 05:50:00,33.56705845743333\n2014-04-08 05:55:00,36.324829128323806\n2014-04-08 06:00:00,34.652864268914286\n2014-04-08 06:05:00,34.87947034400476\n2014-04-08 06:10:00,35.737803341795235\n2014-04-08 06:15:00,33.967688206785716\n2014-04-08 06:20:00,36.13625385667619\n2014-04-08 06:25:00,34.87350645156667\n2014-04-08 06:30:00,36.11121764005714\n2014-04-08 06:35:00,36.92382527134762\n2014-04-08 06:40:00,34.27968342853809\n2014-04-08 06:45:00,37.326170943128574\n2014-04-08 06:50:00,35.73287161181905\n2014-04-08 06:55:00,37.30927058450953\n2014-04-08 07:00:00,34.455920328800005\n2014-04-08 07:05:00,36.05069113459047\n2014-04-08 07:10:00,35.25542942168095\n2014-04-08 07:15:00,36.744210193171426\n2014-04-08 07:20:00,36.078397677661904\n2014-04-08 07:25:00,35.640264208752384\n2014-04-08 07:30:00,37.32158448284286\n2014-04-08 07:35:00,35.185551590033334\n2014-04-08 07:40:00,34.564444629123805\n2014-04-08 07:45:00,36.124369033114284\n2014-04-08 07:50:00,36.19551851060476\n2014-04-08 07:55:00,35.463223724395235\n2014-04-08 08:00:00,35.66072588908571\n2014-04-08 08:05:00,37.55993984767619\n2014-04-08 08:10:00,36.659909432266666\n2014-04-08 08:15:00,34.17901414875714\n2014-04-08 08:20:00,34.592567902547614\n2014-04-08 08:25:00,37.653794632938094\n2014-04-08 08:30:00,36.66479078662857\n2014-04-08 08:35:00,37.42654955221904\n2014-04-08 08:40:00,34.98925537980952\n2014-04-08 08:45:00,36.7487174403\n2014-04-08 08:50:00,36.64470131029047\n2014-04-08 08:55:00,34.97489089418095\n2014-04-08 09:00:00,84.49467345467143\n2014-04-08 09:05:00,85.5438574180619\n2014-04-08 09:10:00,83.56184500825238\n2014-04-08 09:15:00,88.27552326764287\n2014-04-08 09:20:00,88.36035230183333\n2014-04-08 09:25:00,88.60894126642381\n2014-04-08 09:30:00,87.9747748254143\n2014-04-08 09:35:00,83.69359005180476\n2014-04-08 09:40:00,82.25065609289524\n2014-04-08 09:45:00,88.37725317278571\n2014-04-08 09:50:00,83.74471602687619\n2014-04-08 09:55:00,80.43606768796667\n2014-04-08 10:00:00,93.60682876445713\n2014-04-08 10:05:00,87.94180685524762\n2014-04-08 10:10:00,96.4818277893381\n2014-04-08 10:15:00,90.96867686222856\n2014-04-08 10:20:00,89.80804359951905\n2014-04-08 10:25:00,100.61507526540952\n2014-04-08 10:30:00,97.8346930542\n2014-04-08 10:35:00,98.00025915849048\n2014-04-08 10:40:00,95.47254591558095\n2014-04-08 10:45:00,98.82378344767143\n2014-04-08 10:50:00,97.5894636124619\n2014-04-08 10:55:00,95.10767026915238\n2014-04-08 11:00:00,102.83586534414287\n2014-04-08 11:05:00,90.60470941313332\n2014-04-08 11:10:00,102.56853486042381\n2014-04-08 11:15:00,93.9569368141143\n2014-04-08 11:20:00,95.98356219390476\n2014-04-08 11:25:00,89.53939137609524\n2014-04-08 11:30:00,96.1846544228857\n2014-04-08 11:35:00,97.32285837207618\n2014-04-08 11:40:00,103.47711198756667\n2014-04-08 11:45:00,103.12656724855714\n2014-04-08 11:50:00,102.99413014904762\n2014-04-08 11:55:00,93.17275180313808\n2014-04-08 12:00:00,103.82626023452855\n2014-04-08 12:05:00,95.27137429261906\n2014-04-08 12:10:00,101.61293440780952\n2014-04-08 12:15:00,91.4643161609\n2014-04-08 12:20:00,96.09840935369047\n2014-04-08 12:25:00,103.45987705818095\n2014-04-08 12:30:00,103.16399077657142\n2014-04-08 12:35:00,98.9637422402619\n2014-04-08 12:40:00,100.79426350685237\n2014-04-08 12:45:00,90.87143261024286\n2014-04-08 12:50:00,99.59211428093333\n2014-04-08 12:55:00,97.9438201673238\n2014-04-08 13:00:00,89.6079104991143\n2014-04-08 13:05:00,89.96098433670475\n2014-04-08 13:10:00,89.89299669859524\n2014-04-08 13:15:00,99.7526851408857\n2014-04-08 13:20:00,90.4400953360762\n2014-04-08 13:25:00,95.66255691256666\n2014-04-08 13:30:00,93.89841522675714\n2014-04-08 13:35:00,97.00146993544763\n2014-04-08 13:40:00,99.5038690210381\n2014-04-08 13:45:00,99.16332983242857\n2014-04-08 13:50:00,96.46417810581904\n2014-04-08 13:55:00,95.65285445570952\n2014-04-08 14:00:00,94.6112879996\n2014-04-08 14:05:00,102.04388170219048\n2014-04-08 14:10:00,93.55479973618095\n2014-04-08 14:15:00,92.41851937427143\n2014-04-08 14:20:00,100.16878293696192\n2014-04-08 14:25:00,94.03968546975238\n2014-04-08 14:30:00,101.84251395834286\n2014-04-08 14:35:00,93.54459501303333\n2014-04-08 14:40:00,99.5366459091238\n2014-04-08 14:45:00,89.03521774251428\n2014-04-08 14:50:00,94.48965873140476\n2014-04-08 14:55:00,93.81980843679524\n2014-04-08 15:00:00,101.4053289008857\n2014-04-08 15:05:00,103.8187729023762\n2014-04-08 15:10:00,95.72750510236665\n2014-04-08 15:15:00,101.55816968245713\n2014-04-08 15:20:00,99.56336416124762\n2014-04-08 15:25:00,103.85382410733808\n2014-04-08 15:30:00,101.36084901462857\n2014-04-08 15:35:00,89.63031500241905\n2014-04-08 15:40:00,99.81051632180952\n2014-04-08 15:45:00,96.973471994\n2014-04-08 15:50:00,88.67597367849046\n2014-04-08 15:55:00,92.44140849028095\n2014-04-08 16:00:00,103.17648879267144\n2014-04-08 16:05:00,103.2528271807619\n2014-04-08 16:10:00,101.22489696345238\n2014-04-08 16:15:00,104.15919810934285\n2014-04-08 16:20:00,101.36289391023332\n2014-04-08 16:25:00,88.62890225262382\n2014-04-08 16:30:00,93.07841664831429\n2014-04-08 16:35:00,88.97050249690476\n2014-04-08 16:40:00,89.99368160689524\n2014-04-08 16:45:00,91.9968438226857\n2014-04-08 16:50:00,96.55975922237619\n2014-04-08 16:55:00,102.07076444586667\n2014-04-08 17:00:00,102.30929229745713\n2014-04-08 17:05:00,98.38449592204762\n2014-04-08 17:10:00,103.38351976953811\n2014-04-08 17:15:00,96.54114507652857\n2014-04-08 17:20:00,102.77216264351905\n2014-04-08 17:25:00,95.82007318730952\n2014-04-08 17:30:00,92.9980707675\n2014-04-08 17:35:00,103.2325138873905\n2014-04-08 17:40:00,94.78431213178095\n2014-04-08 17:45:00,96.63925642917144\n2014-04-08 17:50:00,93.8540023567619\n2014-04-08 17:55:00,99.20507226515238\n2014-04-08 18:00:00,51.77533594484285\n2014-04-08 18:05:00,45.57786448513333\n2014-04-08 18:10:00,51.18104441262381\n2014-04-08 18:15:00,45.45458551601429\n2014-04-08 18:20:00,47.76795722410476\n2014-04-08 18:25:00,46.52342306159524\n2014-04-08 18:30:00,50.298766650385716\n2014-04-08 18:35:00,45.78312997957619\n2014-04-08 18:40:00,49.008964159866665\n2014-04-08 18:45:00,47.36162850745714\n2014-04-08 18:50:00,46.337031517947615\n2014-04-08 18:55:00,50.428618174638096\n2014-04-08 19:00:00,37.83045482952857\n2014-04-08 19:05:00,37.86593283671905\n2014-04-08 19:10:00,38.10365234770953\n2014-04-08 19:15:00,39.5074638518\n2014-04-08 19:20:00,39.84149258209048\n2014-04-08 19:25:00,36.97248914828096\n2014-04-08 19:30:00,37.98464623297143\n2014-04-08 19:35:00,38.839260067361906\n2014-04-08 19:40:00,38.40320793915238\n2014-04-08 19:45:00,40.88447608404286\n2014-04-08 19:50:00,40.459767148233325\n2014-04-08 19:55:00,39.74226071542381\n2014-04-08 20:00:00,36.60233578381428\n2014-04-08 20:05:00,38.09510843080476\n2014-04-08 20:10:00,38.688136276095236\n2014-04-08 20:15:00,37.67646068948571\n2014-04-08 20:20:00,38.460630099176186\n2014-04-08 20:25:00,38.323250330566665\n2014-04-08 20:30:00,37.604192920057145\n2014-04-08 20:35:00,36.548499838647615\n2014-04-08 20:40:00,38.3319615565381\n2014-04-08 20:45:00,36.131716256728566\n2014-04-08 20:50:00,38.48490305531905\n2014-04-08 20:55:00,38.594982514109525\n2014-04-08 21:00:00,38.265764647699996\n2014-04-08 21:05:00,36.869584297890476\n2014-04-08 21:10:00,35.74989960808095\n2014-04-08 21:15:00,35.38453047677143\n2014-04-08 21:20:00,37.97887939116191\n2014-04-08 21:25:00,38.56066408475238\n2014-04-08 21:30:00,37.62189233834286\n2014-04-08 21:35:00,35.59289140243334\n2014-04-08 21:40:00,38.77845956202381\n2014-04-08 21:45:00,39.00376304861429\n2014-04-08 21:50:00,36.777640022504755\n2014-04-08 21:55:00,37.43396699069524\n2014-04-08 22:00:00,38.09346434138571\n2014-04-08 22:05:00,37.93739307717619\n2014-04-08 22:10:00,38.871311726466665\n2014-04-08 22:15:00,35.46386064915714\n2014-04-08 22:20:00,37.33645705714761\n2014-04-08 22:25:00,37.78915078033809\n2014-04-08 22:30:00,38.59002023552857\n2014-04-08 22:35:00,38.533444128919044\n2014-04-08 22:40:00,38.95684420650952\n2014-04-08 22:45:00,37.0988101872\n2014-04-08 22:50:00,38.382204054690476\n2014-04-08 22:55:00,36.774178536980955\n2014-04-08 23:00:00,36.746607275071426\n2014-04-08 23:05:00,36.078055932361906\n2014-04-08 23:10:00,38.345485933152375\n2014-04-08 23:15:00,39.02336638424286\n2014-04-08 23:20:00,36.112353115333335\n2014-04-08 23:25:00,35.31879926892381\n2014-04-08 23:30:00,38.36446636991428\n2014-04-08 23:35:00,37.59050730670476\n2014-04-08 23:40:00,38.95608348679524\n2014-04-08 23:45:00,36.133142308485716\n2014-04-08 23:50:00,35.415597369876195\n2014-04-08 23:55:00,37.10901990386667\n2014-04-09 00:00:00,35.484721234757146\n2014-04-09 00:05:00,36.19745762344762\n2014-04-09 00:10:00,35.66164953853809\n2014-04-09 00:15:00,36.061707290028565\n2014-04-09 00:20:00,35.59719765891904\n2014-04-09 00:25:00,38.99568352150952\n2014-04-09 00:30:00,36.3017508538\n2014-04-09 00:35:00,36.970530820190476\n2014-04-09 00:40:00,38.79682818288096\n2014-04-09 00:45:00,37.91910778037143\n2014-04-09 00:50:00,37.6894118269619\n2014-04-09 00:55:00,38.04695514235238\n2014-04-09 01:00:00,38.547431885542856\n2014-04-09 01:05:00,38.75026040473333\n2014-04-09 01:10:00,37.817582492223806\n2014-04-09 01:15:00,38.814493384514286\n2014-04-09 01:20:00,37.403494871604764\n2014-04-09 01:25:00,36.378508663195234\n2014-04-09 01:30:00,38.79709254978572\n2014-04-09 01:35:00,37.45011750017619\n2014-04-09 01:40:00,38.91621701696667\n2014-04-09 01:45:00,35.45977839865714\n2014-04-09 01:50:00,36.89661062524762\n2014-04-09 01:55:00,39.1052081686381\n2014-04-09 02:00:00,36.320028942428564\n2014-04-09 02:05:00,39.09501403181905\n2014-04-09 02:10:00,39.15191936830952\n2014-04-09 02:15:00,38.8723192569\n2014-04-09 02:20:00,37.605862656590475\n2014-04-09 02:25:00,37.94638874868095\n2014-04-09 02:30:00,38.844539422371426\n2014-04-09 02:35:00,38.477100234361906\n2014-04-09 02:40:00,37.901327778752375\n2014-04-09 02:45:00,39.317430488642856\n2014-04-09 02:50:00,38.13853987863333\n2014-04-09 02:55:00,39.30520177932381\n2014-04-09 03:00:00,35.640268184114284\n2014-04-09 03:05:00,35.973996244904754\n2014-04-09 03:10:00,37.23143062209524\n2014-04-09 03:15:00,36.972553557785716\n2014-04-09 03:20:00,38.571415555876186\n2014-04-09 03:25:00,36.09037277256667\n2014-04-09 03:30:00,39.35973785925714\n2014-04-09 03:35:00,36.72306112004762\n2014-04-09 03:40:00,37.185932926238095\n2014-04-09 03:45:00,36.57665870122857\n2014-04-09 03:50:00,37.80257351691905\n2014-04-09 03:55:00,35.72707432550952\n2014-04-09 04:00:00,36.0987100223\n2014-04-09 04:05:00,38.49063128989047\n2014-04-09 04:10:00,36.26088328598095\n2014-04-09 04:15:00,36.46437923477143\n2014-04-09 04:20:00,38.70169084766191\n2014-04-09 04:25:00,35.91040709435238\n2014-04-09 04:30:00,37.29453814824286\n2014-04-09 04:35:00,35.64433688133333\n2014-04-09 04:40:00,36.94675340682381\n2014-04-09 04:45:00,38.36288989611428\n2014-04-09 04:50:00,35.93481788080476\n2014-04-09 04:55:00,39.135183745195235\n2014-04-09 05:00:00,39.227281886085706\n2014-04-09 05:05:00,36.01668769097619\n2014-04-09 05:10:00,39.56709641216666\n2014-04-09 05:15:00,36.80172535645714\n2014-04-09 05:20:00,35.95545430354762\n2014-04-09 05:25:00,35.64675655323809\n2014-04-09 05:30:00,37.26802015452857\n2014-04-09 05:35:00,38.16060899041905\n2014-04-09 05:40:00,36.97752652340952\n2014-04-09 05:45:00,39.0031194619\n2014-04-09 05:50:00,38.530115578490474\n2014-04-09 05:55:00,37.07177708028095\n2014-04-09 06:00:00,38.61581009497143\n2014-04-09 06:05:00,39.4479628526619\n2014-04-09 06:10:00,36.06583637515238\n2014-04-09 06:15:00,36.92530869774286\n2014-04-09 06:20:00,37.56163708983333\n2014-04-09 06:25:00,37.70773432052381\n2014-04-09 06:30:00,37.89199686521428\n2014-04-09 06:35:00,36.93316238810476\n2014-04-09 06:40:00,38.40713382199524\n2014-04-09 06:45:00,38.325873728385716\n2014-04-09 06:50:00,38.06426221557619\n2014-04-09 06:55:00,36.21546355346666\n2014-04-09 07:00:00,37.67572870725714\n2014-04-09 07:05:00,37.20020516904762\n2014-04-09 07:10:00,37.746891974638096\n2014-04-09 07:15:00,39.47764431352857\n2014-04-09 07:20:00,37.719744420219044\n2014-04-09 07:25:00,35.86098269120952\n2014-04-09 07:30:00,37.5678469523\n2014-04-09 07:35:00,39.102533196390475\n2014-04-09 07:40:00,38.94762464528095\n2014-04-09 07:45:00,37.888381722671426\n2014-04-09 07:50:00,36.84133795616191\n2014-04-09 07:55:00,37.71005703265238\n2014-04-09 08:00:00,38.11195173484286\n2014-04-09 08:05:00,39.86406908643333\n2014-04-09 08:10:00,38.44873617022381\n2014-04-09 08:15:00,38.65652400601428\n2014-04-09 08:20:00,37.85272133620476\n2014-04-09 08:25:00,37.31230344119524\n2014-04-09 08:30:00,39.15359764888571\n2014-04-09 08:35:00,37.88895548787619\n2014-04-09 08:40:00,39.895427186566664\n2014-04-09 08:45:00,37.75258943995714\n2014-04-09 08:50:00,36.20354875364762\n2014-04-09 08:55:00,38.669300643638095\n2014-04-09 09:00:00,79.78075230402858\n2014-04-09 09:05:00,82.56069076521905\n2014-04-09 09:10:00,83.97214976160951\n2014-04-09 09:15:00,89.2257267645\n2014-04-09 09:20:00,85.89779907529046\n2014-04-09 09:25:00,79.57321561818095\n2014-04-09 09:30:00,87.58022940597142\n2014-04-09 09:35:00,84.7940447337619\n2014-04-09 09:40:00,91.74290171655238\n2014-04-09 09:45:00,86.00744028864285\n2014-04-09 09:50:00,88.86289531813333\n2014-04-09 09:55:00,82.20488530522381\n2014-04-09 10:00:00,99.68602400721429\n2014-04-09 10:05:00,99.07238118060476\n2014-04-09 10:10:00,101.92194335469524\n2014-04-09 10:15:00,88.42294759378571\n2014-04-09 10:20:00,94.85068701747619\n2014-04-09 10:25:00,98.45340851716668\n2014-04-09 10:30:00,89.39730087205714\n2014-04-09 10:35:00,94.30037274124763\n2014-04-09 10:40:00,102.5573533748381\n2014-04-09 10:45:00,94.70838187002856\n2014-04-09 10:50:00,103.24360128721905\n2014-04-09 10:55:00,88.83970175180951\n2014-04-09 11:00:00,101.1093647597\n2014-04-09 11:05:00,98.94092269749046\n2014-04-09 11:10:00,97.66846397748095\n2014-04-09 11:15:00,105.15567850177143\n2014-04-09 11:20:00,91.7847218741619\n2014-04-09 11:25:00,103.98016970845238\n2014-04-09 11:30:00,100.73113035584286\n2014-04-09 11:35:00,93.86415688313332\n2014-04-09 11:40:00,104.09266990162381\n2014-04-09 11:45:00,96.5874706594143\n2014-04-09 11:50:00,102.71687618760475\n2014-04-09 11:55:00,95.95890120519525\n2014-04-09 12:00:00,103.7264410812857\n2014-04-09 12:05:00,100.3091688064762\n2014-04-09 12:10:00,92.39680470866665\n2014-04-09 12:15:00,100.53234422565714\n2014-04-09 12:20:00,93.21549000284762\n2014-04-09 12:25:00,96.74794122713809\n2014-04-09 12:30:00,92.89398824422857\n2014-04-09 12:35:00,90.53180418891905\n2014-04-09 12:40:00,93.57352593340951\n2014-04-09 12:45:00,98.7665040367\n2014-04-09 12:50:00,97.89801999009049\n2014-04-09 12:55:00,98.22405573668095\n2014-04-09 13:00:00,94.24833036607143\n2014-04-09 13:05:00,101.25368009556192\n2014-04-09 13:10:00,101.56668059905239\n2014-04-09 13:15:00,96.03472346964286\n2014-04-09 13:20:00,104.41139105573333\n2014-04-09 13:25:00,100.62539222652381\n2014-04-09 13:30:00,101.73682461901427\n2014-04-09 13:35:00,94.77474846360477\n2014-04-09 13:40:00,90.35559905189524\n2014-04-09 13:45:00,104.19594246558573\n2014-04-09 13:50:00,103.51632823407618\n2014-04-09 13:55:00,92.33873381846666\n2014-04-09 14:00:00,96.37479598945714\n2014-04-09 14:05:00,100.97776264464763\n2014-04-09 14:10:00,100.83755498963808\n2014-04-09 14:15:00,104.17666717932858\n2014-04-09 14:20:00,92.66334590781905\n2014-04-09 14:25:00,97.30530929460951\n2014-04-09 14:30:00,91.9895600185\n2014-04-09 14:35:00,96.67470924209047\n2014-04-09 14:40:00,90.69063247928095\n2014-04-09 14:45:00,104.82804459657142\n2014-04-09 14:50:00,98.8961050842619\n2014-04-09 14:55:00,104.06742990565239\n2014-04-09 15:00:00,91.43991767184286\n2014-04-09 15:05:00,94.12818696333333\n2014-04-09 15:10:00,94.64637269232381\n2014-04-09 15:15:00,96.69077760411429\n2014-04-09 15:20:00,103.35695220000477\n2014-04-09 15:25:00,96.70352064249523\n2014-04-09 15:30:00,93.8005195538857\n2014-04-09 15:35:00,91.5733691733762\n2014-04-09 15:40:00,91.81283123036667\n2014-04-09 15:45:00,102.70905449495714\n2014-04-09 15:50:00,97.67263595384762\n2014-04-09 15:55:00,102.18208330583809\n2014-04-09 16:00:00,101.48786331982858\n2014-04-09 16:05:00,92.74452603741905\n2014-04-09 16:10:00,92.87237384140953\n2014-04-09 16:15:00,102.6790608028\n2014-04-09 16:20:00,102.14132277459046\n2014-04-09 16:25:00,96.65697336928095\n2014-04-09 16:30:00,91.85468702347143\n2014-04-09 16:35:00,90.81694164026192\n2014-04-09 16:40:00,95.24131648015238\n2014-04-09 16:45:00,90.78581071124286\n2014-04-09 16:50:00,94.32684996313333\n2014-04-09 16:55:00,97.3651345258238\n2014-04-09 17:00:00,92.60333813671429\n2014-04-09 17:05:00,92.33657059850476\n2014-04-09 17:10:00,105.01856105389524\n2014-04-09 17:15:00,100.0505249334857\n2014-04-09 17:20:00,105.64173378937619\n2014-04-09 17:25:00,96.23110551446666\n2014-04-09 17:30:00,101.53964433175715\n2014-04-09 17:35:00,93.98783550734763\n2014-04-09 17:40:00,100.61365172463809\n2014-04-09 17:45:00,92.80102180742857\n2014-04-09 17:50:00,90.76838161361906\n2014-04-09 17:55:00,105.64703497500953\n2014-04-09 18:00:00,51.1013177961\n2014-04-09 18:05:00,53.48985404939047\n2014-04-09 18:10:00,49.70139676428096\n2014-04-09 18:15:00,49.67014633887143\n2014-04-09 18:20:00,50.143947894161904\n2014-04-09 18:25:00,52.105858281052384\n2014-04-09 18:30:00,51.21581189104286\n2014-04-09 18:35:00,53.524348072133336\n2014-04-09 18:40:00,47.77234001592381\n2014-04-09 18:45:00,52.14941188891429\n2014-04-09 18:50:00,49.73849603830476\n2014-04-09 18:55:00,48.78533485869524\n2014-04-09 19:00:00,41.28585687178571\n2014-04-09 19:05:00,41.26941071357619\n2014-04-09 19:10:00,39.62797493556667\n2014-04-09 19:15:00,39.926100318757136\n2014-04-09 19:20:00,40.857624111547615\n2014-04-09 19:25:00,40.8679620163381\n2014-04-09 19:30:00,40.46658785292857\n2014-04-09 19:35:00,39.71685018391905\n2014-04-09 19:40:00,39.07840249920952\n2014-04-09 19:45:00,43.412901735300004\n2014-04-09 19:50:00,43.300565687490476\n2014-04-09 19:55:00,41.24788342628095\n2014-04-09 20:00:00,41.43630313987143\n2014-04-09 20:05:00,40.127299789361906\n2014-04-09 20:10:00,37.65749263045238\n2014-04-09 20:15:00,37.86506637364286\n2014-04-09 20:20:00,41.142723083633335\n2014-04-09 20:25:00,39.97846737742381\n2014-04-09 20:30:00,40.85889415791428\n2014-04-09 20:35:00,41.09196698150476\n2014-04-09 20:40:00,39.254865473095236\n2014-04-09 20:45:00,37.62629778838571\n2014-04-09 20:50:00,38.20617226907619\n2014-04-09 20:55:00,37.715095138366664\n2014-04-09 21:00:00,37.862840284557144\n2014-04-09 21:05:00,38.76171150874762\n2014-04-09 21:10:00,37.594194670638096\n2014-04-09 21:15:00,37.79671279512857\n2014-04-09 21:20:00,38.925865905519046\n2014-04-09 21:25:00,38.508674560009524\n2014-04-09 21:30:00,39.028511483900004\n2014-04-09 21:35:00,38.881268641690475\n2014-04-09 21:40:00,39.75406698378096\n2014-04-09 21:45:00,40.93797360997142\n2014-04-09 21:50:00,37.612190208561906\n2014-04-09 21:55:00,37.58504872785238\n2014-04-09 22:00:00,40.53892206644286\n2014-04-09 22:05:00,39.15939470543333\n2014-04-09 22:10:00,40.207866888723814\n2014-04-09 22:15:00,38.00925911101429\n2014-04-09 22:20:00,40.47281787640476\n2014-04-09 22:25:00,40.86055929519524\n2014-04-09 22:30:00,39.71343802118571\n2014-04-09 22:35:00,37.60042884277619\n2014-04-09 22:40:00,40.76856384476666\n2014-04-09 22:45:00,40.364381194757144\n2014-04-09 22:50:00,40.205222085447616\n2014-04-09 22:55:00,37.35332187813809\n2014-04-09 23:00:00,40.39634827362857\n2014-04-09 23:05:00,37.75923503401905\n2014-04-09 23:10:00,38.10448101930952\n2014-04-09 23:15:00,39.531188577\n2014-04-09 23:20:00,38.289773071190474\n2014-04-09 23:25:00,39.882987690980954\n2014-04-09 23:30:00,39.67727621547142\n2014-04-09 23:35:00,37.68464935386191\n2014-04-09 23:40:00,39.88397051645238\n2014-04-09 23:45:00,40.96337809164285\n2014-04-09 23:50:00,37.918852684633336\n2014-04-09 23:55:00,39.670436434923815\n2014-04-10 00:00:00,38.65317577341428\n2014-04-10 00:05:00,39.13160144900476\n2014-04-10 00:10:00,38.44859595439524\n2014-04-10 00:15:00,38.72455825968571\n2014-04-10 00:20:00,37.43112348357619\n2014-04-10 00:25:00,41.24912361836667\n2014-04-10 00:30:00,39.82955683115714\n2014-04-10 00:35:00,39.34061998104762\n2014-04-10 00:40:00,38.88009949323809\n2014-04-10 00:45:00,39.510176806728566\n2014-04-10 00:50:00,38.88054304251905\n2014-04-10 00:55:00,38.80719123380952\n2014-04-10 01:00:00,39.2307861669\n2014-04-10 01:05:00,38.48637261089047\n2014-04-10 01:10:00,38.11008055228095\n2014-04-10 01:15:00,39.62374502127143\n2014-04-10 01:20:00,40.775823649361904\n2014-04-10 01:25:00,38.023515091852374\n2014-04-10 01:30:00,37.55058021954286\n2014-04-10 01:35:00,38.414330313933334\n2014-04-10 01:40:00,41.353406383323815\n2014-04-10 01:45:00,40.756996580714286\n2014-04-10 01:50:00,39.83286897600476\n2014-04-10 01:55:00,41.17384089909524\n2014-04-10 02:00:00,39.24540218158571\n2014-04-10 02:05:00,41.40484860077619\n2014-04-10 02:10:00,38.66437484716666\n2014-04-10 02:15:00,38.44783014095714\n2014-04-10 02:20:00,40.04624042364762\n2014-04-10 02:25:00,39.014103967038096\n2014-04-10 02:30:00,40.01439073932857\n2014-04-10 02:35:00,38.73635112081905\n2014-04-10 02:40:00,39.99548255120952\n2014-04-10 02:45:00,38.6342350423\n2014-04-10 02:50:00,37.74257875149047\n2014-04-10 02:55:00,41.194674560080955\n2014-04-10 03:00:00,41.086392236071426\n2014-04-10 03:05:00,41.444204501861904\n2014-04-10 03:10:00,40.43456108585238\n2014-04-10 03:15:00,40.30677756804286\n2014-04-10 03:20:00,39.81934561363333\n2014-04-10 03:25:00,38.09454347492381\n2014-04-10 03:30:00,38.355155529514285\n2014-04-10 03:35:00,38.76353351660476\n2014-04-10 03:40:00,41.173720688395235\n2014-04-10 03:45:00,38.31241381268571\n2014-04-10 03:50:00,41.319468888476194\n2014-04-10 03:55:00,39.726559598866665\n2014-04-10 04:00:00,40.50513568475714\n2014-04-10 04:05:00,38.09127556574762\n2014-04-10 04:10:00,38.7338722903381\n2014-04-10 04:15:00,41.49925300412857\n2014-04-10 04:20:00,38.73721883531905\n2014-04-10 04:25:00,38.86614640540952\n2014-04-10 04:30:00,38.477889539399996\n2014-04-10 04:35:00,38.211235137390474\n2014-04-10 04:40:00,38.63541151818095\n2014-04-10 04:45:00,40.279128996371426\n2014-04-10 04:50:00,39.5387328387619\n2014-04-10 04:55:00,39.93972572635238\n2014-04-10 05:00:00,38.221602172242854\n2014-04-10 05:05:00,40.94804912203333\n2014-04-10 05:10:00,40.88340261182381\n2014-04-10 05:15:00,37.840823930314286\n2014-04-10 05:20:00,39.29596513990476\n2014-04-10 05:25:00,38.04442764599524\n2014-04-10 05:30:00,40.94520883198571\n2014-04-10 05:35:00,40.73330492297619\n2014-04-10 05:40:00,41.399619043866664\n2014-04-10 05:45:00,38.74472297865714\n2014-04-10 05:50:00,39.63173115154761\n2014-04-10 05:55:00,38.551939603938095\n2014-04-10 06:00:00,39.30636830932857\n2014-04-10 06:05:00,39.917842053919045\n2014-04-10 06:10:00,38.04963268320952\n2014-04-10 06:15:00,40.703231642700004\n2014-04-10 06:20:00,40.02436391769048\n2014-04-10 06:25:00,41.17446702118095\n2014-04-10 06:30:00,38.953193433371425\n2014-04-10 06:35:00,41.4867963258619\n2014-04-10 06:40:00,41.87572939305238\n2014-04-10 06:45:00,41.56558661064285\n2014-04-10 06:50:00,41.00740323663333\n2014-04-10 06:55:00,41.15274902102381\n2014-04-10 07:00:00,40.20569125591429\n2014-04-10 07:05:00,38.678770213604764\n2014-04-10 07:10:00,40.633757978695236\n2014-04-10 07:15:00,40.78404772248571\n2014-04-10 07:20:00,41.88201675157619\n2014-04-10 07:25:00,40.11312193166667\n2014-04-10 07:30:00,39.040833202957145\n2014-04-10 07:35:00,40.69748770604762\n2014-04-10 07:40:00,41.8877413739381\n2014-04-10 07:45:00,38.68653420452857\n2014-04-10 07:50:00,39.28911072171905\n2014-04-10 07:55:00,40.16008333890952\n2014-04-10 08:00:00,38.6808585395\n2014-04-10 08:05:00,38.09632303429048\n2014-04-10 08:10:00,39.36281344218095\n2014-04-10 08:15:00,41.48380463457143\n2014-04-10 08:20:00,38.20363550206191\n2014-04-10 08:25:00,39.75291861705238\n2014-04-10 08:30:00,41.093445948842856\n2014-04-10 08:35:00,41.864813720933334\n2014-04-10 08:40:00,42.001425405523804\n2014-04-10 08:45:00,39.754841808114286\n2014-04-10 08:50:00,41.875941939404754\n2014-04-10 08:55:00,38.22352113119524\n2014-04-10 09:00:00,91.43375607108571\n2014-04-10 09:05:00,90.03807226147619\n2014-04-10 09:10:00,84.69766392986665\n2014-04-10 09:15:00,88.21113875205714\n2014-04-10 09:20:00,83.08097845254763\n2014-04-10 09:25:00,93.1802093481381\n2014-04-10 09:30:00,86.20134253482857\n2014-04-10 09:35:00,89.85557384591905\n2014-04-10 09:40:00,83.50816701730953\n2014-04-10 09:45:00,84.160091887\n2014-04-10 09:50:00,94.85429711909046\n2014-04-10 09:55:00,91.61310591678094\n2014-04-10 10:00:00,104.94837484747143\n2014-04-10 10:05:00,94.61762198886191\n2014-04-10 10:10:00,92.58746822605238\n2014-04-10 10:15:00,97.84851541034286\n2014-04-10 10:20:00,97.72558507353334\n2014-04-10 10:25:00,92.77094370302382\n2014-04-10 10:30:00,101.44278200561428\n2014-04-10 10:35:00,95.68544209640476\n2014-04-10 10:40:00,92.97048362209523\n2014-04-10 10:45:00,95.23791799758571\n2014-04-10 10:50:00,98.84095920877618\n2014-04-10 10:55:00,101.37524553406666\n2014-04-10 11:00:00,99.49984979475714\n2014-04-10 11:05:00,100.20236033724761\n2014-04-10 11:10:00,94.06053426043809\n2014-04-10 11:15:00,106.40542303802857\n2014-04-10 11:20:00,106.63604869251905\n2014-04-10 11:25:00,102.74227601780952\n2014-04-10 11:30:00,92.1609099277\n2014-04-10 11:35:00,100.42956880589048\n2014-04-10 11:40:00,101.90247948448095\n2014-04-10 11:45:00,107.72180219047144\n2014-04-10 11:50:00,107.75171076016193\n2014-04-10 11:55:00,105.55715146755237\n2014-04-10 12:00:00,93.29081317454286\n2014-04-10 12:05:00,107.51230267913333\n2014-04-10 12:10:00,102.07644066802382\n2014-04-10 12:15:00,105.09187558741428\n2014-04-10 12:20:00,98.80777225420475\n2014-04-10 12:25:00,97.41651912399524\n2014-04-10 12:30:00,99.7183977543857\n2014-04-10 12:35:00,94.66999840737618\n2014-04-10 12:40:00,98.03646921686666\n2014-04-10 12:45:00,106.04312088315713\n2014-04-10 12:50:00,92.95162674984762\n2014-04-10 12:55:00,94.76373998593809\n2014-04-10 13:00:00,94.43052667972857\n2014-04-10 13:05:00,98.88424992071906\n2014-04-10 13:10:00,108.3919915084095\n2014-04-10 13:15:00,95.2245311889\n2014-04-10 13:20:00,94.78607421639049\n2014-04-10 13:25:00,107.10372881478095\n2014-04-10 13:30:00,106.58321262607143\n2014-04-10 13:35:00,92.9969540216619\n2014-04-10 13:40:00,104.51308119295238\n2014-04-10 13:45:00,102.98104709244286\n2014-04-10 13:50:00,104.7844581662333\n2014-04-10 13:55:00,100.4211341968238\n2014-04-10 14:00:00,108.3935644016143\n2014-04-10 14:05:00,93.24121738680476\n2014-04-10 14:10:00,96.29690462319525\n2014-04-10 14:15:00,98.8990109585857\n2014-04-10 14:20:00,99.75812182607619\n2014-04-10 14:25:00,107.31063149966667\n2014-04-10 14:30:00,101.53654088475713\n2014-04-10 14:35:00,93.30608290214762\n2014-04-10 14:40:00,99.11727627133808\n2014-04-10 14:45:00,99.26274930472857\n2014-04-10 14:50:00,108.05377656561905\n2014-04-10 14:55:00,102.20079679680953\n2014-04-10 15:00:00,102.7946283025\n2014-04-10 15:05:00,104.04368822059047\n2014-04-10 15:10:00,104.95970052528095\n2014-04-10 15:15:00,102.80734980797142\n2014-04-10 15:20:00,96.44914388986192\n2014-04-10 15:25:00,106.64611155695238\n2014-04-10 15:30:00,104.38275601014287\n2014-04-10 15:35:00,104.54620594353334\n2014-04-10 15:40:00,108.62858736612381\n2014-04-10 15:45:00,105.5315743754143\n2014-04-10 15:50:00,105.96500865470476\n2014-04-10 15:55:00,107.92849615359523\n2014-04-10 16:00:00,95.13228682898571\n2014-04-10 16:05:00,100.6852106839762\n2014-04-10 16:10:00,102.01808296906665\n2014-04-10 16:15:00,98.00487045505714\n2014-04-10 16:20:00,106.17433709484762\n2014-04-10 16:25:00,104.9500403800381\n2014-04-10 16:30:00,104.29289737802857\n2014-04-10 16:35:00,108.72059121131906\n2014-04-10 16:40:00,96.92376529010951\n2014-04-10 16:45:00,104.54840519359999\n2014-04-10 16:50:00,101.61100689549048\n2014-04-10 16:55:00,97.80381001728095\n2014-04-10 17:00:00,95.37293272547143\n2014-04-10 17:05:00,107.14512014556192\n2014-04-10 17:10:00,102.34570879775238\n2014-04-10 17:15:00,106.02480154304287\n2014-04-10 17:20:00,101.55882207873333\n2014-04-10 17:25:00,96.36037810042382\n2014-04-10 17:30:00,98.2489655734143\n2014-04-10 17:35:00,98.96024624930476\n2014-04-10 17:40:00,108.43001861239524\n2014-04-10 17:45:00,92.9606404857857\n2014-04-10 17:50:00,108.6485988549762\n2014-04-10 17:55:00,108.57276915646665\n2014-04-10 18:00:00,56.06821544855714\n2014-04-10 18:05:00,52.75045584894761\n2014-04-10 18:10:00,55.876108786838095\n2014-04-10 18:15:00,52.247007319528564\n2014-04-10 18:20:00,49.89089790601905\n2014-04-10 18:25:00,51.165875711309525\n2014-04-10 18:30:00,55.7873892764\n2014-04-10 18:35:00,49.83302896699047\n2014-04-10 18:40:00,53.24673721858095\n2014-04-10 18:45:00,50.24366597497142\n2014-04-10 18:50:00,51.600194125161906\n2014-04-10 18:55:00,50.33849098765238\n2014-04-10 19:00:00,44.992829762542854\n2014-04-10 19:05:00,43.797578861333335\n2014-04-10 19:10:00,45.1984594483238\n2014-04-10 19:15:00,44.24828534461429\n2014-04-10 19:20:00,45.522113925304765\n2014-04-10 19:25:00,43.46359590019524\n2014-04-10 19:30:00,44.04820785768571\n2014-04-10 19:35:00,43.77608845597619\n2014-04-10 19:40:00,43.371152165666665\n2014-04-10 19:45:00,44.99900378615715\n2014-04-10 19:50:00,44.10401896254761\n2014-04-10 19:55:00,44.81386573893809\n2014-04-10 20:00:00,42.72437499592857\n2014-04-10 20:05:00,40.29338979511905\n2014-04-10 20:10:00,42.18137909990952\n2014-04-10 20:15:00,40.3435080556\n2014-04-10 20:20:00,41.92247090519048\n2014-04-10 20:25:00,42.31540316538096\n2014-04-10 20:30:00,43.63274601157143\n2014-04-10 20:35:00,39.680611624561905\n2014-04-10 20:40:00,39.93668100155238\n2014-04-10 20:45:00,39.88589398054286\n2014-04-10 20:50:00,41.20952092113333\n2014-04-10 20:55:00,42.950499476623804\n2014-04-10 21:00:00,42.63954544591428\n2014-04-10 21:05:00,42.21662310150476\n2014-04-10 21:10:00,42.86672821459524\n2014-04-10 21:15:00,40.56707435448571\n2014-04-10 21:20:00,39.63118729157619\n2014-04-10 21:25:00,39.51804527196666\n2014-04-10 21:30:00,42.71664891695714\n2014-04-10 21:35:00,42.23496712184762\n2014-04-10 21:40:00,42.1145126820381\n2014-04-10 21:45:00,40.67930566372857\n2014-04-10 21:50:00,40.84843393371905\n2014-04-10 21:55:00,43.17980936550953\n2014-04-10 22:00:00,39.5227439776\n2014-04-10 22:05:00,42.372618543490475\n2014-04-10 22:10:00,40.52188322968095\n2014-04-10 22:15:00,39.445969863071426\n2014-04-10 22:20:00,42.2701738066619\n2014-04-10 22:25:00,40.629400615852376\n2014-04-10 22:30:00,42.203285968342854\n2014-04-10 22:35:00,42.15269824843333\n2014-04-10 22:40:00,41.46800488292381\n2014-04-10 22:45:00,42.446721905014286\n2014-04-10 22:50:00,41.668069235804765\n2014-04-10 22:55:00,40.49677332559524\n2014-04-10 23:00:00,42.27976671708571\n2014-04-10 23:05:00,41.707193911376194\n2014-04-10 23:10:00,39.40854156616666\n2014-04-10 23:15:00,42.97233231455714\n2014-04-10 23:20:00,41.55549714464762\n2014-04-10 23:25:00,42.8551202607381\n2014-04-10 23:30:00,42.91900986712857\n2014-04-10 23:35:00,41.17503340701904\n2014-04-10 23:40:00,41.43329539050953\n2014-04-10 23:45:00,41.0730428481\n2014-04-10 23:50:00,41.21523874289048\n2014-04-10 23:55:00,43.00586305918095\n2014-04-11 00:00:00,42.58114748447143\n2014-04-11 00:05:00,39.94211461006191\n2014-04-11 00:10:00,41.884683507152374\n2014-04-11 00:15:00,43.43451941864286\n2014-04-11 00:20:00,41.84053613823333\n2014-04-11 00:25:00,42.609260311923805\n2014-04-11 00:30:00,42.54946017921428\n2014-04-11 00:35:00,40.881924865404756\n2014-04-11 00:40:00,40.97549244889524\n2014-04-11 00:45:00,42.39184140148571\n2014-04-11 00:50:00,41.50291031687619\n2014-04-11 00:55:00,41.792699503166666\n2014-04-11 01:00:00,42.36948030435714\n2014-04-11 01:05:00,42.635597727247614\n2014-04-11 01:10:00,40.618804406138096\n2014-04-11 01:15:00,40.12735360912857\n2014-04-11 01:20:00,40.714797634519044\n2014-04-11 01:25:00,41.58521282420952\n2014-04-11 01:30:00,40.931065269200005\n2014-04-11 01:35:00,41.843391511590475\n2014-04-11 01:40:00,39.79124384888095\n2014-04-11 01:45:00,41.62382307507143\n2014-04-11 01:50:00,41.06420153256191\n2014-04-11 01:55:00,41.73836940055238\n2014-04-11 02:00:00,41.29727627664286\n2014-04-11 02:05:00,40.751486735933334\n2014-04-11 02:10:00,43.2384554313238\n2014-04-11 02:15:00,40.368524239414285\n2014-04-11 02:20:00,42.36236706420476\n2014-04-11 02:25:00,43.342924088395236\n2014-04-11 02:30:00,41.80646555298571\n2014-04-11 02:35:00,43.164860144776185\n2014-04-11 02:40:00,40.16607258036666\n2014-04-11 02:45:00,41.64926222385714\n2014-04-11 02:50:00,41.50964874094762\n2014-04-11 02:55:00,39.7214633233381\n2014-04-11 03:00:00,41.46945793682857\n2014-04-11 03:05:00,41.17998807311905\n2014-04-11 03:10:00,42.390504434909516\n2014-04-11 03:15:00,43.4720691143\n2014-04-11 03:20:00,40.06935482919047\n2014-04-11 03:25:00,41.043536499280954\n2014-04-11 03:30:00,41.51733037817142\n2014-04-11 03:35:00,41.569253416861905\n2014-04-11 03:40:00,42.85519126435238\n2014-04-11 03:45:00,41.53697552044286\n2014-04-11 03:50:00,39.87947853913333\n2014-04-11 03:55:00,42.618690187923804\n2014-04-11 04:00:00,43.32503306631428\n2014-04-11 04:05:00,41.84877361210476\n2014-04-11 04:10:00,42.12502932489524\n2014-04-11 04:15:00,40.45978147018571\n2014-04-11 04:20:00,40.698059969176185\n2014-04-11 04:25:00,40.76359762316666\n2014-04-11 04:30:00,41.553325042357145\n2014-04-11 04:35:00,43.55037850264762\n2014-04-11 04:40:00,41.932377162138096\n2014-04-11 04:45:00,40.62106915222857\n2014-04-11 04:50:00,40.92446999111905\n2014-04-11 04:55:00,41.40361964270952\n2014-04-11 05:00:00,42.3680359028\n2014-04-11 05:05:00,41.642573088190474\n2014-04-11 05:10:00,41.459660329080954\n2014-04-11 05:15:00,42.156235830171426\n2014-04-11 05:20:00,40.8721018845619\n2014-04-11 05:25:00,40.227815471252384\n2014-04-11 05:30:00,40.017300116442854\n2014-04-11 05:35:00,40.932119987233335\n2014-04-11 05:40:00,40.30089194612381\n2014-04-11 05:45:00,41.287326839814284\n2014-04-11 05:50:00,43.04113892330476\n2014-04-11 05:55:00,42.82202255999523\n2014-04-11 06:00:00,42.40799620548571\n2014-04-11 06:05:00,43.38172716597619\n2014-04-11 06:10:00,41.10743716486667\n2014-04-11 06:15:00,43.526822154957145\n2014-04-11 06:20:00,41.59100429774762\n2014-04-11 06:25:00,41.6050613683381\n2014-04-11 06:30:00,41.630335025928574\n2014-04-11 06:35:00,40.40874651261905\n2014-04-11 06:40:00,43.925771517109524\n2014-04-11 06:45:00,40.5852771113\n2014-04-11 06:50:00,41.40223337409047\n2014-04-11 06:55:00,41.32333223368096\n2014-04-11 07:00:00,40.35228915987143\n2014-04-11 07:05:00,40.670052425161906\n2014-04-11 07:10:00,40.24788572565238\n2014-04-11 07:15:00,41.245510831342855\n2014-04-11 07:20:00,43.549961029433334\n2014-04-11 07:25:00,41.44854263242381\n2014-04-11 07:30:00,40.592981614014285\n2014-04-11 07:35:00,42.68843023540476\n2014-04-11 07:40:00,44.09949888629524\n2014-04-11 07:45:00,41.04983087238571\n2014-04-11 07:50:00,41.24626021197619\n2014-04-11 07:55:00,44.02280488376667\n2014-04-11 08:00:00,40.85796229305714\n2014-04-11 08:05:00,42.195153888847614\n2014-04-11 08:10:00,41.116346627338096\n2014-04-11 08:15:00,43.89458616302856\n2014-04-11 08:20:00,44.09870310591904\n2014-04-11 08:25:00,43.43885090830952\n2014-04-11 08:30:00,41.446635263299996\n2014-04-11 08:35:00,41.808890377290474\n2014-04-11 08:40:00,41.17160368708095\n2014-04-11 08:45:00,43.77285329657143\n2014-04-11 08:50:00,43.8754950155619\n2014-04-11 08:55:00,41.90018502995238\n2014-04-11 09:00:00,150.11416299114285\n2014-04-11 09:05:00,137.94530219133333\n2014-04-11 09:10:00,144.6334341385238\n2014-04-11 09:15:00,149.5156421317143\n2014-04-11 09:20:00,143.41990210090475\n2014-04-11 09:25:00,142.73781347509524\n2014-04-11 09:30:00,133.9015607222857\n2014-04-11 09:35:00,153.8307040924762\n2014-04-11 09:40:00,155.94723944466665\n2014-04-11 09:45:00,157.94180267585713\n2014-04-11 09:50:00,151.7444779690476\n2014-04-11 09:55:00,147.5240374422381\n2014-04-11 10:00:00,160.43990826542858\n2014-04-11 10:05:00,181.58858187161903\n2014-04-11 10:10:00,169.73555219080953\n2014-04-11 10:15:00,172.389971935\n2014-04-11 10:20:00,172.43367292619047\n2014-04-11 10:25:00,177.15712295738098\n2014-04-11 10:30:00,152.9661881535714\n2014-04-11 10:35:00,159.0718632997619\n2014-04-11 10:40:00,171.97481702595238\n2014-04-11 10:45:00,178.63181339514284\n2014-04-11 10:50:00,172.56324445733333\n2014-04-11 10:55:00,164.6979816115238\n2014-04-11 11:00:00,167.24617561871426\n2014-04-11 11:05:00,178.46710182490474\n2014-04-11 11:10:00,178.57254871109524\n2014-04-11 11:15:00,174.58250742728572\n2014-04-11 11:20:00,165.1878617724762\n2014-04-11 11:25:00,184.07412901666666\n2014-04-11 11:30:00,172.96096437885714\n2014-04-11 11:35:00,180.07714589604763\n2014-04-11 11:40:00,162.9189098412381\n2014-04-11 11:45:00,166.79134174542855\n2014-04-11 11:50:00,182.60459199961903\n2014-04-11 11:55:00,158.0493481598095\n2014-04-11 12:00:00,172.660947021\n2014-04-11 12:05:00,171.7513659231905\n2014-04-11 12:10:00,179.83333544338097\n2014-04-11 12:15:00,165.78020776557142\n2014-04-11 12:20:00,163.9054533807619\n2014-04-11 12:25:00,185.09546041795238\n2014-04-11 12:30:00,174.48494929414287\n2014-04-11 12:35:00,160.50121529533334\n2014-04-11 12:40:00,163.1553783715238\n2014-04-11 12:45:00,187.30299490671428\n2014-04-11 12:50:00,163.24733731490474\n2014-04-11 12:55:00,175.68351479709523\n2014-04-11 13:00:00,170.1521926182857\n2014-04-11 13:05:00,184.1198908514762\n2014-04-11 13:10:00,180.21550143266666\n2014-04-11 13:15:00,175.47774239485716\n2014-04-11 13:20:00,157.90368772504763\n2014-04-11 13:25:00,183.9755844242381\n2014-04-11 13:30:00,170.93281306342857\n2014-04-11 13:35:00,185.54350791161903\n2014-04-11 13:40:00,172.47341702480952\n2014-04-11 13:45:00,178.439768728\n2014-04-11 13:50:00,159.70445344519047\n2014-04-11 13:55:00,179.98204089638097\n2014-04-11 14:00:00,167.81040194257142\n2014-04-11 14:05:00,168.2187096737619\n2014-04-11 14:10:00,161.24544227895237\n2014-04-11 14:15:00,162.09887494614287\n2014-04-11 14:20:00,163.27330791633332\n2014-04-11 14:25:00,167.5539247315238\n2014-04-11 14:30:00,184.47333943071428\n2014-04-11 14:35:00,168.77036112390476\n2014-04-11 14:40:00,179.46028309509524\n2014-04-11 14:45:00,160.2203351392857\n2014-04-11 14:50:00,175.47746858047617\n2014-04-11 14:55:00,172.20886373766666\n2014-04-11 15:00:00,187.10477248685714\n2014-04-11 15:05:00,183.1597514970476\n2014-04-11 15:10:00,171.4259823012381\n2014-04-11 15:15:00,181.04270592542855\n2014-04-11 15:20:00,163.58721944361903\n2014-04-11 15:25:00,174.67346459980953\n2014-04-11 15:30:00,160.04954923399998\n2014-04-11 15:35:00,168.26099800019048\n2014-04-11 15:40:00,164.60167363438097\n2014-04-11 15:45:00,179.40037903557143\n2014-04-11 15:50:00,172.5433219387619\n2014-04-11 15:55:00,180.38006918995237\n2014-04-11 16:00:00,173.31567216814287\n2014-04-11 16:05:00,160.45881132133334\n2014-04-11 16:10:00,179.9327048355238\n2014-04-11 16:15:00,182.87598722571428\n2014-04-11 16:20:00,184.99248187990474\n2014-04-11 16:25:00,175.05376600509524\n2014-04-11 16:30:00,180.50899680528573\n2014-04-11 16:35:00,180.4702067204762\n2014-04-11 16:40:00,162.58884957366666\n2014-04-11 16:45:00,162.85041731585713\n2014-04-11 16:50:00,160.05780855504761\n2014-04-11 16:55:00,167.5360763362381\n2014-04-11 17:00:00,172.15161999642856\n2014-04-11 17:05:00,187.89073144261903\n2014-04-11 17:10:00,170.8910441448095\n2014-04-11 17:15:00,179.755958083\n2014-04-11 17:20:00,178.77803213019047\n2014-04-11 17:25:00,164.11802683438097\n2014-04-11 17:30:00,159.7462252895714\n2014-04-11 17:35:00,174.3786472787619\n2014-04-11 17:40:00,179.01505092395237\n2014-04-11 17:45:00,187.96087337014285\n2014-04-11 17:50:00,168.77910022433335\n2014-04-11 17:55:00,184.9191388355238\n2014-04-11 18:00:00,67.94947988201429\n2014-04-11 18:05:00,70.78572866320476\n2014-04-11 18:10:00,69.95450862529523\n2014-04-11 18:15:00,64.94542849078572\n2014-04-11 18:20:00,65.1866375290762\n2014-04-11 18:25:00,64.66393425606667\n2014-04-11 18:30:00,67.89201775305715\n2014-04-11 18:35:00,71.34915330124763\n2014-04-11 18:40:00,66.0845752792381\n2014-04-11 18:45:00,70.07651228672856\n2014-04-11 18:50:00,67.16732187411904\n2014-04-11 18:55:00,71.84987756170952\n2014-04-11 19:00:00,49.828913769699994\n2014-04-11 19:05:00,49.72052682259047\n2014-04-11 19:10:00,48.46503918628095\n2014-04-11 19:15:00,47.26153509967143\n2014-04-11 19:20:00,49.91435705876191\n2014-04-11 19:25:00,46.780146717852375\n2014-04-11 19:30:00,47.31002870094285\n2014-04-11 19:35:00,46.78417727823333\n2014-04-11 19:40:00,49.2625402627238\n2014-04-11 19:45:00,49.330591105814285\n2014-04-11 19:50:00,49.16805238190476\n2014-04-11 19:55:00,47.98147401359524\n2014-04-11 20:00:00,42.571804822685706\n2014-04-11 20:05:00,45.99192722587619\n2014-04-11 20:10:00,44.30169802996666\n2014-04-11 20:15:00,43.88514561645714\n2014-04-11 20:20:00,44.65782222784762\n2014-04-11 20:25:00,42.99874974943809\n2014-04-11 20:30:00,42.752693340528566\n2014-04-11 20:35:00,43.90881865711905\n2014-04-11 20:40:00,43.16595370110952\n2014-04-11 20:45:00,43.2452230542\n2014-04-11 20:50:00,45.980378242490474\n2014-04-11 20:55:00,44.465565034180955\n2014-04-11 21:00:00,43.44475989277143\n2014-04-11 21:05:00,44.28481252026191\n2014-04-11 21:10:00,45.351429121052384\n2014-04-11 21:15:00,41.966554477042855\n2014-04-11 21:20:00,44.88934652613334\n2014-04-11 21:25:00,43.88834561862381\n2014-04-11 21:30:00,42.12615608071428\n2014-04-11 21:35:00,42.74381334610476\n2014-04-11 21:40:00,43.49980703279524\n2014-04-11 21:45:00,44.35119715128572\n2014-04-11 21:50:00,42.54569660917619\n2014-04-11 21:55:00,43.73438278006667\n2014-04-11 22:00:00,44.17468009835714\n2014-04-11 22:05:00,43.23643412444761\n2014-04-11 22:10:00,44.9044622928381\n2014-04-11 22:15:00,44.93768885962857\n2014-04-11 22:20:00,43.34674004791905\n2014-04-11 22:25:00,45.36729708400952\n2014-04-11 22:30:00,41.7779092181\n2014-04-11 22:35:00,41.495857945290474\n2014-04-11 22:40:00,43.01566114678096\n2014-04-11 22:45:00,43.90665077987143\n2014-04-11 22:50:00,44.0267374580619\n2014-04-11 22:55:00,43.421889333452384\n2014-04-11 23:00:00,41.989371912042856\n2014-04-11 23:05:00,42.17934512433333\n2014-04-11 23:10:00,44.9145217146238\n2014-04-11 23:15:00,44.98504101221428\n2014-04-11 23:20:00,44.21610827610476\n2014-04-11 23:25:00,44.18481038149524\n2014-04-11 23:30:00,43.92599676508571\n2014-04-11 23:35:00,42.35375539797619\n2014-04-11 23:40:00,43.262870072666665\n2014-04-11 23:45:00,44.34133171295714\n2014-04-11 23:50:00,43.71393869054762\n2014-04-11 23:55:00,41.645828345238094\n2014-04-12 00:00:00,45.38565579832857\n2014-04-12 00:05:00,44.958133257919044\n2014-04-12 00:10:00,42.62848958020952\n2014-04-12 00:15:00,44.0595857407\n2014-04-12 00:20:00,45.29414801109047\n2014-04-12 00:25:00,41.99267500088095\n2014-04-12 00:30:00,43.628189351771425\n2014-04-12 00:35:00,43.448484008161905\n2014-04-12 00:40:00,43.27177240205238\n2014-04-12 00:45:00,44.980747292742855\n2014-04-12 00:50:00,43.16841792013334\n2014-04-12 00:55:00,41.9079271425238\n2014-04-12 01:00:00,41.92406525441429\n2014-04-12 01:05:00,41.83913318800476\n2014-04-12 01:10:00,43.31217692559524\n2014-04-12 01:15:00,44.556660825085714\n2014-04-12 01:20:00,42.50536603817619\n2014-04-12 01:25:00,44.28379074836667\n2014-04-12 01:30:00,44.45371103125714\n2014-04-12 01:35:00,42.733606115147616\n2014-04-12 01:40:00,44.122468719438096\n2014-04-12 01:45:00,44.46715193152857\n2014-04-12 01:50:00,43.601573538819046\n2014-04-12 01:55:00,43.08942591290952\n2014-04-12 02:00:00,44.226606206300005\n2014-04-12 02:05:00,45.66882882549047\n2014-04-12 02:10:00,43.47224658988095\n2014-04-12 02:15:00,43.33926181367143\n2014-04-12 02:20:00,43.63682951446191\n2014-04-12 02:25:00,42.09207595475238\n2014-04-12 02:30:00,44.00729597584285\n2014-04-12 02:35:00,43.11687288223334\n2014-04-12 02:40:00,42.295212298823806\n2014-04-12 02:45:00,43.68199125021428\n2014-04-12 02:50:00,41.83794070820476\n2014-04-12 02:55:00,43.438986218795236\n2014-04-12 03:00:00,42.26222678598572\n2014-04-12 03:05:00,41.94389700407619\n2014-04-12 03:10:00,45.15206685166666\n2014-04-12 03:15:00,45.52660235595714\n2014-04-12 03:20:00,42.699746212447614\n2014-04-12 03:25:00,44.033681150538094\n2014-04-12 03:30:00,42.995761199928566\n2014-04-12 03:35:00,43.86567880231905\n2014-04-12 03:40:00,43.645334807409526\n2014-04-12 03:45:00,42.9824542203\n2014-04-12 03:50:00,44.71526479469047\n2014-04-12 03:55:00,42.42709478968095\n2014-04-12 04:00:00,42.140862557271426\n2014-04-12 04:05:00,45.0067136368619\n2014-04-12 04:10:00,44.607172505852375\n2014-04-12 04:15:00,43.944997353742856\n2014-04-12 04:20:00,43.82949241523333\n2014-04-12 04:25:00,43.955419327523806\n2014-04-12 04:30:00,43.721310590114285\n2014-04-12 04:35:00,43.55222394520476\n2014-04-12 04:40:00,43.98685764959524\n2014-04-12 04:45:00,44.109596398885714\n2014-04-12 04:50:00,44.770585446776195\n2014-04-12 04:55:00,44.85524530956667\n2014-04-12 05:00:00,43.52837346345714\n2014-04-12 05:05:00,43.67945971004762\n2014-04-12 05:10:00,43.527526774138096\n2014-04-12 05:15:00,44.186321665928574\n2014-04-12 05:20:00,43.86103319931905\n2014-04-12 05:25:00,45.61344537630952\n2014-04-12 05:30:00,44.847945067699996\n2014-04-12 05:35:00,45.66456601119047\n2014-04-12 05:40:00,44.91392891858095\n2014-04-12 05:45:00,45.96879002267143\n2014-04-12 05:50:00,44.63520901776191\n2014-04-12 05:55:00,45.95390293365238\n2014-04-12 06:00:00,42.739822418742854\n2014-04-12 06:05:00,42.32449405663333\n2014-04-12 06:10:00,44.438524550323805\n2014-04-12 06:15:00,46.063437108914286\n2014-04-12 06:20:00,43.807325751104756\n2014-04-12 06:25:00,42.99251868689524\n2014-04-12 06:30:00,44.23795151108571\n2014-04-12 06:35:00,44.75442068877619\n2014-04-12 06:40:00,43.42738144876667\n2014-04-12 06:45:00,45.03318457685714\n2014-04-12 06:50:00,46.08200564724762\n2014-04-12 06:55:00,45.77684058203809\n2014-04-12 07:00:00,43.36277006542857\n2014-04-12 07:05:00,43.51076378021905\n2014-04-12 07:10:00,43.69747442160952\n2014-04-12 07:15:00,43.7969611136\n2014-04-12 07:20:00,42.62746847299047\n2014-04-12 07:25:00,45.28148230798095\n2014-04-12 07:30:00,43.70242848297143\n2014-04-12 07:35:00,45.76779181156191\n2014-04-12 07:40:00,45.963714873452375\n2014-04-12 07:45:00,42.36111809434286\n2014-04-12 07:50:00,46.22484561303333\n2014-04-12 07:55:00,45.118364735523805\n2014-04-12 08:00:00,44.367283189714286\n2014-04-12 08:05:00,43.85126519540476\n2014-04-12 08:10:00,44.374667768495236\n2014-04-12 08:15:00,43.60653461018571\n2014-04-12 08:20:00,44.80622744527619\n2014-04-12 08:25:00,42.69483777246666\n2014-04-12 08:30:00,44.814847554457145\n2014-04-12 08:35:00,43.439177019647616\n2014-04-12 08:40:00,42.41577741143809\n2014-04-12 08:45:00,44.56350163612857\n2014-04-12 08:50:00,44.67391007101905\n2014-04-12 08:55:00,44.07383554260952\n2014-04-12 09:00:00,86.5580927627\n2014-04-12 09:05:00,97.73190463429049\n2014-04-12 09:10:00,93.90533993068095\n2014-04-12 09:15:00,87.17102230267143\n2014-04-12 09:20:00,92.55341774646192\n2014-04-12 09:25:00,92.37486107785237\n2014-04-12 09:30:00,86.44110827274287\n2014-04-12 09:35:00,93.88037530233332\n2014-04-12 09:40:00,96.62776283482381\n2014-04-12 09:45:00,95.82847382351429\n2014-04-12 09:50:00,88.40978879450476\n2014-04-12 09:55:00,97.38402363999523\n2014-04-12 10:00:00,99.62054012528571\n2014-04-12 10:05:00,109.00153622157619\n2014-04-12 10:10:00,95.43269507146667\n2014-04-12 10:15:00,101.87256598865714\n2014-04-12 10:20:00,103.60141795284763\n2014-04-12 10:25:00,98.1850176235381\n2014-04-12 10:30:00,106.32074910032857\n2014-04-12 10:35:00,104.08578999831904\n2014-04-12 10:40:00,94.64486799050952\n2014-04-12 10:45:00,103.81313052760001\n2014-04-12 10:50:00,102.00643267439048\n2014-04-12 10:55:00,97.42850416278095\n2014-04-12 11:00:00,111.95795123177143\n2014-04-12 11:05:00,110.39747945126189\n2014-04-12 11:10:00,100.78849476265238\n2014-04-12 11:15:00,104.74908478154285\n2014-04-12 11:20:00,101.18498336643333\n2014-04-12 11:25:00,108.4922582435238\n2014-04-12 11:30:00,110.96220539931429\n2014-04-12 11:35:00,101.88046492630475\n2014-04-12 11:40:00,108.99310713649524\n2014-04-12 11:45:00,104.1152092735857\n2014-04-12 11:50:00,102.50316162957618\n2014-04-12 11:55:00,111.12807780246666\n2014-04-12 12:00:00,104.71313239235714\n2014-04-12 12:05:00,104.03349134154762\n2014-04-12 12:10:00,107.31737778613811\n2014-04-12 12:15:00,100.75351009102857\n2014-04-12 12:20:00,101.77666895711904\n2014-04-12 12:25:00,111.48849762360952\n2014-04-12 12:30:00,107.444549754\n2014-04-12 12:35:00,109.81886340729048\n2014-04-12 12:40:00,100.94856379748096\n2014-04-12 12:45:00,105.31362369577144\n2014-04-12 12:50:00,112.15455136826193\n2014-04-12 12:55:00,101.73144565055237\n2014-04-12 13:00:00,99.28187024854284\n2014-04-12 13:05:00,104.89451766263333\n2014-04-12 13:10:00,102.9333919961238\n2014-04-12 13:15:00,99.2898072337143\n2014-04-12 13:20:00,110.95803484780475\n2014-04-12 13:25:00,112.59984342709524\n2014-04-12 13:30:00,105.85463724978571\n2014-04-12 13:35:00,109.15879972567619\n2014-04-12 13:40:00,110.51570187206667\n2014-04-12 13:45:00,107.99484746825713\n2014-04-12 13:50:00,97.49559484564762\n2014-04-12 13:55:00,99.31825048723809\n2014-04-12 14:00:00,97.95374511012857\n2014-04-12 14:05:00,96.98347916631903\n2014-04-12 14:10:00,101.72856105870952\n2014-04-12 14:15:00,103.1176880383\n2014-04-12 14:20:00,100.70402508269046\n2014-04-12 14:25:00,97.88879970538095\n2014-04-12 14:30:00,105.34001794707143\n2014-04-12 14:35:00,101.2429551148619\n2014-04-12 14:40:00,109.61347950225237\n2014-04-12 14:45:00,97.01377261874285\n2014-04-12 14:50:00,110.37216309313332\n2014-04-12 14:55:00,112.1751434218238\n2014-04-12 15:00:00,108.36807409781429\n2014-04-12 15:05:00,108.65565591840476\n2014-04-12 15:10:00,111.86175762859523\n2014-04-12 15:15:00,100.2774529657857\n2014-04-12 15:20:00,112.8526813165762\n2014-04-12 15:25:00,109.32280591396665\n2014-04-12 15:30:00,108.57968567485713\n2014-04-12 15:35:00,102.73950021944762\n2014-04-12 15:40:00,105.7019028303381\n2014-04-12 15:45:00,107.43957154202857\n2014-04-12 15:50:00,106.90981834401906\n2014-04-12 15:55:00,108.27151425380951\n2014-04-12 16:00:00,98.3179670545\n2014-04-12 16:05:00,102.69766623599048\n2014-04-12 16:10:00,103.95872964538096\n2014-04-12 16:15:00,101.19224394807142\n2014-04-12 16:20:00,99.7916546859619\n2014-04-12 16:25:00,99.25989955175238\n2014-04-12 16:30:00,102.90662763794285\n2014-04-12 16:35:00,104.94699714383333\n2014-04-12 16:40:00,98.06700667722382\n2014-04-12 16:45:00,112.2101264840143\n2014-04-12 16:50:00,109.31813617940476\n2014-04-12 16:55:00,108.77531291729524\n2014-04-12 17:00:00,99.85502540408571\n2014-04-12 17:05:00,106.75750712087618\n2014-04-12 17:10:00,105.57973491296667\n2014-04-12 17:15:00,112.83107499115714\n2014-04-12 17:20:00,109.08176369864762\n2014-04-12 17:25:00,106.33864704923809\n2014-04-12 17:30:00,110.74689835952857\n2014-04-12 17:35:00,99.62284878051905\n2014-04-12 17:40:00,97.39224625740951\n2014-04-12 17:45:00,108.1999514458\n2014-04-12 17:50:00,98.73664558799047\n2014-04-12 17:55:00,99.01804083488095\n2014-04-12 18:00:00,58.74452163307143\n2014-04-12 18:05:00,55.71742904516191\n2014-04-12 18:10:00,58.01668585855238\n2014-04-12 18:15:00,59.87229052724285\n2014-04-12 18:20:00,56.03376441733333\n2014-04-12 18:25:00,55.405490623223805\n2014-04-12 18:30:00,54.705211081114285\n2014-04-12 18:35:00,54.86560818510476\n2014-04-12 18:40:00,54.43631488249524\n2014-04-12 18:45:00,54.60644130148571\n2014-04-12 18:50:00,56.81779949837619\n2014-04-12 18:55:00,56.11394703096666\n2014-04-12 19:00:00,48.59324831145715\n2014-04-12 19:05:00,49.33397892824762\n2014-04-12 19:10:00,48.9585207465381\n2014-04-12 19:15:00,47.82743224492857\n2014-04-12 19:20:00,45.91655859721905\n2014-04-12 19:25:00,48.64481567550952\n2014-04-12 19:30:00,47.0979714917\n2014-04-12 19:35:00,45.86365311399047\n2014-04-12 19:40:00,49.26162914368095\n2014-04-12 19:45:00,47.01003023647142\n2014-04-12 19:50:00,46.480015514861904\n2014-04-12 19:55:00,49.413806310352385\n2014-04-12 20:00:00,47.484282916742856\n2014-04-12 20:05:00,45.18500764463333\n2014-04-12 20:10:00,45.25729018432381\n2014-04-12 20:15:00,46.185622485014285\n2014-04-12 20:20:00,46.82308086330476\n2014-04-12 20:25:00,44.085004144795235\n2014-04-12 20:30:00,46.26412108378571\n2014-04-12 20:35:00,47.743976895476194\n2014-04-12 20:40:00,44.922203035466666\n2014-04-12 20:45:00,47.57866314595714\n2014-04-12 20:50:00,47.75543687494762\n2014-04-12 20:55:00,44.9734411742381\n2014-04-12 21:00:00,46.56411665912857\n2014-04-12 21:05:00,44.49995351451905\n2014-04-12 21:10:00,46.512316253509525\n2014-04-12 21:15:00,46.7601402965\n2014-04-12 21:20:00,44.55615959389047\n2014-04-12 21:25:00,46.44725377068095\n2014-04-12 21:30:00,46.84148193897143\n2014-04-12 21:35:00,45.0261120597619\n2014-04-12 21:40:00,44.266383332352376\n2014-04-12 21:45:00,43.96941680094285\n2014-04-12 21:50:00,45.91980742663333\n2014-04-12 21:55:00,47.545845716823806\n2014-04-12 22:00:00,46.847955684614284\n2014-04-12 22:05:00,45.305466932104764\n2014-04-12 22:10:00,45.716419463895235\n2014-04-12 22:15:00,44.69450063358571\n2014-04-12 22:20:00,44.235645823676194\n2014-04-12 22:25:00,45.520372481466666\n2014-04-12 22:30:00,45.45342324375714\n2014-04-12 22:35:00,45.69480163144762\n2014-04-12 22:40:00,47.4273951963381\n2014-04-12 22:45:00,46.037858719928565\n2014-04-12 22:50:00,46.052812547919046\n2014-04-12 22:55:00,44.14743018120952\n2014-04-12 23:00:00,47.615176766\n2014-04-12 23:05:00,46.72786979599047\n2014-04-12 23:10:00,47.15282401878095\n2014-04-12 23:15:00,45.30829725667142\n2014-04-12 23:20:00,45.66711592036191\n2014-04-12 23:25:00,45.754394575952375\n2014-04-12 23:30:00,44.44962607704285\n2014-04-12 23:35:00,46.439025484233326\n2014-04-12 23:40:00,47.3005801880238\n2014-04-12 23:45:00,44.350369282514286\n2014-04-12 23:50:00,44.048200146504755\n2014-04-12 23:55:00,46.66374381029524\n2014-04-13 00:00:00,44.80709304098571\n2014-04-13 00:05:00,46.21717635697619\n2014-04-13 00:10:00,46.51220001866666\n2014-04-13 00:15:00,45.024250197157144\n2014-04-13 00:20:00,125.74404761904762\n2014-04-13 00:25:00,45.95144402373809\n2014-04-13 00:30:00,47.23492620322857\n2014-04-13 00:35:00,46.81954325781905\n2014-04-13 00:40:00,47.24811205190952\n2014-04-13 00:45:00,43.8618955285\n2014-04-13 00:50:00,44.76271551919048\n2014-04-13 00:55:00,44.15616271418095\n2014-04-13 01:00:00,45.57190349737142\n2014-04-13 01:05:00,47.370852391261906\n2014-04-13 01:10:00,45.688613430052385\n2014-04-13 01:15:00,47.22474503544285\n2014-04-13 01:20:00,45.14204628543333\n2014-04-13 01:25:00,45.19905410072381\n2014-04-13 01:30:00,47.43046120701429\n2014-04-13 01:35:00,45.55892334790476\n2014-04-13 01:40:00,47.022157189295235\n2014-04-13 01:45:00,44.81710990578571\n2014-04-13 01:50:00,47.673179509176194\n2014-04-13 01:55:00,46.18372965276666\n2014-04-13 02:00:00,46.93015141715715\n2014-04-13 02:05:00,44.25836041824762\n2014-04-13 02:10:00,45.8783949985381\n2014-04-13 02:15:00,47.51933256232857\n2014-04-13 02:20:00,47.430773563819045\n2014-04-13 02:25:00,44.117315352709525\n2014-04-13 02:30:00,45.152293876499996\n2014-04-13 02:35:00,45.718220502090475\n2014-04-13 02:40:00,44.64144020978095\n2014-04-13 02:45:00,46.87981467257143\n2014-04-13 02:50:00,44.7053098871619\n2014-04-13 02:55:00,45.36126115845238\n2014-04-13 03:00:00,46.63526540454285\n2014-04-13 03:05:00,45.91794071143333\n2014-04-13 03:10:00,46.95130796402381\n2014-04-13 03:15:00,47.849295890614286\n2014-04-13 03:20:00,44.47809151280476\n2014-04-13 03:25:00,46.857616103695236\n2014-04-13 03:30:00,44.948162336785714\n2014-04-13 03:35:00,45.69213310007619\n2014-04-13 03:40:00,44.17311756986666\n2014-04-13 03:45:00,44.59273667205714\n2014-04-13 03:50:00,45.335656775247614\n2014-04-13 03:55:00,45.431931316438096\n2014-04-13 04:00:00,47.66976943722857\n2014-04-13 04:05:00,47.04612068471904\n2014-04-13 04:10:00,47.975041396509525\n2014-04-13 04:15:00,46.4900360413\n2014-04-13 04:20:00,45.06804540459048\n2014-04-13 04:25:00,45.419251072080954\n2014-04-13 04:30:00,45.39541512177142\n2014-04-13 04:35:00,45.4294892154619\n2014-04-13 04:40:00,46.82280907335238\n2014-04-13 04:45:00,46.26162456954285\n2014-04-13 04:50:00,45.68753004563333\n2014-04-13 04:55:00,44.749632884423804\n2014-04-13 05:00:00,44.24927093751428\n2014-04-13 05:05:00,45.04349347230476\n2014-04-13 05:10:00,44.60548085399523\n2014-04-13 05:15:00,47.32481583768571\n2014-04-13 05:20:00,44.640468021776186\n2014-04-13 05:25:00,47.094829615866665\n2014-04-13 05:30:00,45.74799190195714\n2014-04-13 05:35:00,44.50631117804762\n2014-04-13 05:40:00,47.4711582929381\n2014-04-13 05:45:00,46.54620085232857\n2014-04-13 05:50:00,45.17816509911905\n2014-04-13 05:55:00,47.82128422110952\n2014-04-13 06:00:00,44.4310332555\n2014-04-13 06:05:00,45.06471890899047\n2014-04-13 06:10:00,47.27306866358095\n2014-04-13 06:15:00,47.109833149771426\n2014-04-13 06:20:00,45.43684867966191\n2014-04-13 06:25:00,44.535301882352385\n2014-04-13 06:30:00,47.726955146042854\n2014-04-13 06:35:00,45.55687388563334\n2014-04-13 06:40:00,45.092377469223806\n2014-04-13 06:45:00,46.381211575114285\n2014-04-13 06:50:00,47.965313559004755\n2014-04-13 06:55:00,44.50603154949523\n2014-04-13 07:00:00,47.40250206638571\n2014-04-13 07:05:00,46.636619102276185\n2014-04-13 07:10:00,46.055963132866665\n2014-04-13 07:15:00,47.337928919257145\n2014-04-13 07:20:00,48.23234531684762\n2014-04-13 07:25:00,45.29331293993809\n2014-04-13 07:30:00,44.95851803172857\n2014-04-13 07:35:00,48.04289602851905\n2014-04-13 07:40:00,47.07462183360953\n2014-04-13 07:45:00,46.1581940862\n2014-04-13 07:50:00,46.70672875729048\n2014-04-13 07:55:00,47.40358657308095\n2014-04-13 08:00:00,47.52069902337143\n2014-04-13 08:05:00,48.1155886280619\n2014-04-13 08:10:00,46.15082353655238\n2014-04-13 08:15:00,45.62453649724286\n2014-04-13 08:20:00,47.01699040053333\n2014-04-13 08:25:00,46.1286854066238\n2014-04-13 08:30:00,46.85160810151429\n2014-04-13 08:35:00,46.16059795570476\n2014-04-13 08:40:00,45.10007838479524\n2014-04-13 08:45:00,46.37324272088571\n2014-04-13 08:50:00,47.26664747827619\n2014-04-13 08:55:00,47.70755189736666\n2014-04-13 09:00:00,94.42709450725714\n2014-04-13 09:05:00,89.97253292594762\n2014-04-13 09:10:00,93.37249094643809\n2014-04-13 09:15:00,98.43377600362857\n2014-04-13 09:20:00,93.36250512801905\n2014-04-13 09:25:00,97.22787831680952\n2014-04-13 09:30:00,94.6606060708\n2014-04-13 09:35:00,91.05057497769047\n2014-04-13 09:40:00,98.60502786148095\n2014-04-13 09:45:00,88.93012440397143\n2014-04-13 09:50:00,94.9307697502619\n2014-04-13 09:55:00,90.64062044665238\n2014-04-13 10:00:00,97.48800141214286\n2014-04-13 10:05:00,104.26011803683333\n2014-04-13 10:10:00,104.21522846962381\n2014-04-13 10:15:00,107.44056627971429\n2014-04-13 10:20:00,108.03543551810476\n2014-04-13 10:25:00,107.77966914259524\n2014-04-13 10:30:00,102.84813724918571\n2014-04-13 10:35:00,106.30305168827618\n2014-04-13 10:40:00,105.46085683246667\n2014-04-13 10:45:00,103.05674559775714\n2014-04-13 10:50:00,105.79028863284762\n2014-04-13 10:55:00,111.2302751417381\n2014-04-13 11:00:00,101.33221067092856\n2014-04-13 11:05:00,112.67726845901905\n2014-04-13 11:10:00,99.12946601820951\n2014-04-13 11:15:00,103.191372042\n2014-04-13 11:20:00,102.87685251009049\n2014-04-13 11:25:00,108.26334162808095\n2014-04-13 11:30:00,100.39607306167143\n2014-04-13 11:35:00,112.3493683234619\n2014-04-13 11:40:00,111.50123398115238\n2014-04-13 11:45:00,108.70184765344288\n2014-04-13 11:50:00,105.62944691413333\n2014-04-13 11:55:00,113.18400670372381\n2014-04-13 12:00:00,111.9753088274143\n2014-04-13 12:05:00,106.68621028040477\n2014-04-13 12:10:00,109.93069294099524\n2014-04-13 12:15:00,107.7816298940857\n2014-04-13 12:20:00,108.12486351367619\n2014-04-13 12:25:00,104.02577903716667\n2014-04-13 12:30:00,106.12843879245716\n2014-04-13 12:35:00,99.99984058024762\n2014-04-13 12:40:00,104.4695560670381\n2014-04-13 12:45:00,109.88617490972857\n2014-04-13 12:50:00,114.00687378791906\n2014-04-13 12:55:00,114.17169449700951\n2014-04-13 13:00:00,107.7471519302\n2014-04-13 13:05:00,108.56878707569047\n2014-04-13 13:10:00,101.84342675108095\n2014-04-13 13:15:00,110.00230117497144\n2014-04-13 13:20:00,100.0177512577619\n2014-04-13 13:25:00,103.44880016075237\n2014-04-13 13:30:00,109.59360989844285\n2014-04-13 13:35:00,103.87357384713333\n2014-04-13 13:40:00,99.71460238332381\n2014-04-13 13:45:00,112.23141645291429\n2014-04-13 13:50:00,103.89621320880475\n2014-04-13 13:55:00,99.94900651179522\n2014-04-13 14:00:00,100.15738290898571\n2014-04-13 14:05:00,102.99621762037619\n2014-04-13 14:10:00,101.82382910596667\n2014-04-13 14:15:00,111.37135836485713\n2014-04-13 14:20:00,104.13728931234762\n2014-04-13 14:25:00,111.8725466495381\n2014-04-13 14:30:00,101.78687502282857\n2014-04-13 14:35:00,106.89860138911905\n2014-04-13 14:40:00,110.02841924810951\n2014-04-13 14:45:00,109.4591469329\n2014-04-13 14:50:00,108.65284336769048\n2014-04-13 14:55:00,113.83911032028095\n2014-04-13 15:00:00,102.70924749037144\n2014-04-13 15:05:00,106.9597521408619\n2014-04-13 15:10:00,113.21150620085238\n2014-04-13 15:15:00,100.32148994214285\n2014-04-13 15:20:00,99.97684584093334\n2014-04-13 15:25:00,102.82288337522381\n2014-04-13 15:30:00,109.22576536621429\n2014-04-13 15:35:00,103.26299766760475\n2014-04-13 15:40:00,102.15621295819524\n2014-04-13 15:45:00,106.46061108798571\n2014-04-13 15:50:00,108.9447598420762\n2014-04-13 15:55:00,103.11161060046666\n2014-04-13 16:00:00,103.95376865315714\n2014-04-13 16:05:00,108.96708940744762\n2014-04-13 16:10:00,114.2893855539381\n2014-04-13 16:15:00,109.96088724232857\n2014-04-13 16:20:00,111.69892305411905\n2014-04-13 16:25:00,105.04887153150952\n2014-04-13 16:30:00,103.54342314649999\n2014-04-13 16:35:00,106.46307217229048\n2014-04-13 16:40:00,112.11634317668096\n2014-04-13 16:45:00,106.51046343967143\n2014-04-13 16:50:00,112.7647041939619\n2014-04-13 16:55:00,115.04488545695239\n2014-04-13 17:00:00,100.38454141834285\n2014-04-13 17:05:00,99.96611790363333\n2014-04-13 17:10:00,101.64043048902381\n2014-04-13 17:15:00,105.40434908791428\n2014-04-13 17:20:00,101.35855165510476\n2014-04-13 17:25:00,113.19994388259525\n2014-04-13 17:30:00,99.64709794048571\n2014-04-13 17:35:00,104.33688006357619\n2014-04-13 17:40:00,102.24675195576665\n2014-04-13 17:45:00,114.20370305395714\n2014-04-13 17:50:00,110.01821193594762\n2014-04-13 17:55:00,113.90643894693812\n2014-04-13 18:00:00,62.344325593028564\n2014-04-13 18:05:00,59.310291666719046\n2014-04-13 18:10:00,57.63594599780952\n2014-04-13 18:15:00,57.383608464000005\n2014-04-13 18:20:00,57.577865387490476\n2014-04-13 18:25:00,60.693621720880955\n2014-04-13 18:30:00,56.42491850927143\n2014-04-13 18:35:00,56.502217179461894\n2014-04-13 18:40:00,60.07306093535238\n2014-04-13 18:45:00,60.29755227774285\n2014-04-13 18:50:00,60.45350970193333\n2014-04-13 18:55:00,58.583303052323814\n2014-04-13 19:00:00,51.18134608321428\n2014-04-13 19:05:00,49.96879167790476\n2014-04-13 19:10:00,48.05808012869524\n2014-04-13 19:15:00,51.16403930808571\n2014-04-13 19:20:00,51.87021853277619\n2014-04-13 19:25:00,47.87687822826666\n2014-04-13 19:30:00,49.36860993815715\n2014-04-13 19:35:00,49.80686827414762\n2014-04-13 19:40:00,48.286425958438095\n2014-04-13 19:45:00,51.52501333832857\n2014-04-13 19:50:00,48.918108281019045\n2014-04-13 19:55:00,51.16043648440952\n2014-04-13 20:00:00,48.680393144199996\n2014-04-13 20:05:00,48.389035914390476\n2014-04-13 20:10:00,46.733897829980954\n2014-04-13 20:15:00,46.858322816671425\n2014-04-13 20:20:00,46.1557007470619\n2014-04-13 20:25:00,46.95516026035238\n2014-04-13 20:30:00,47.39157964334285\n2014-04-13 20:35:00,49.39664623583333\n2014-04-13 20:40:00,47.4922679332238\n2014-04-13 20:45:00,49.08989484961428\n2014-04-13 20:50:00,47.80636010330476\n2014-04-13 20:55:00,49.228665584295236\n2014-04-13 21:00:00,49.59951647688571\n2014-04-13 21:05:00,46.64709733407619\n2014-04-13 21:10:00,49.15649002076666\n2014-04-13 21:15:00,48.19724246015714\n2014-04-13 21:20:00,48.99031666294762\n2014-04-13 21:25:00,48.331742103038096\n2014-04-13 21:30:00,47.42426638262857\n2014-04-13 21:35:00,46.644447797719046\n2014-04-13 21:40:00,46.01669505650952\n2014-04-13 21:45:00,47.8950053609\n2014-04-13 21:50:00,49.730409061390475\n2014-04-13 21:55:00,48.72386852358095\n2014-04-13 22:00:00,47.00649059157143\n2014-04-13 22:05:00,49.0152875610619\n2014-04-13 22:10:00,48.789621269852375\n2014-04-13 22:15:00,46.84579750264285\n2014-04-13 22:20:00,45.78289822443333\n2014-04-13 22:25:00,46.20615809912381\n2014-04-13 22:30:00,49.25308789211428\n2014-04-13 22:35:00,49.09739929470476\n2014-04-13 22:40:00,46.93734483469524\n2014-04-13 22:45:00,46.904692560485714\n2014-04-13 22:50:00,48.94476073007619\n2014-04-13 22:55:00,49.53224744746666\n2014-04-13 23:00:00,48.88846054535714\n2014-04-13 23:05:00,48.201533409547615\n2014-04-13 23:10:00,46.757065866338095\n2014-04-13 23:15:00,47.89703000022857\n2014-04-13 23:20:00,46.73530181721905\n2014-04-13 23:25:00,49.041181754909516\n2014-04-13 23:30:00,47.3640975023\n2014-04-13 23:35:00,49.15882562149048\n2014-04-13 23:40:00,47.35756689828095\n2014-04-13 23:45:00,49.13550799397143\n2014-04-13 23:50:00,47.1792451515619\n2014-04-13 23:55:00,47.61402721935238\n2014-04-14 00:00:00,48.31909653454285\n2014-04-14 00:05:00,46.145733789433336\n2014-04-14 00:10:00,49.664852056823804\n2014-04-14 00:15:00,48.173887430214286\n2014-04-14 00:20:00,47.91818482070476\n2014-04-14 00:25:00,49.251921122595235\n2014-04-14 00:30:00,49.364836633885716\n2014-04-14 00:35:00,47.99826780857619\n2014-04-14 00:40:00,49.62571596986666\n2014-04-14 00:45:00,46.183058207157146\n2014-04-14 00:50:00,46.384450788047616\n2014-04-14 00:55:00,48.326141015338095\n2014-04-14 01:00:00,47.362692018628564\n2014-04-14 01:05:00,47.810769712419045\n2014-04-14 01:10:00,47.27362639540952\n2014-04-14 01:15:00,47.587651245800004\n2014-04-14 01:20:00,49.266775864790475\n2014-04-14 01:25:00,48.35753575178096\n2014-04-14 01:30:00,49.980449625671426\n2014-04-14 01:35:00,49.146028696061904\n2014-04-14 01:40:00,47.10061739735238\n2014-04-14 01:45:00,47.070773328042854\n2014-04-14 01:50:00,47.36442641383333\n2014-04-14 01:55:00,49.4013117321238\n2014-04-14 02:00:00,46.14486488831429\n2014-04-14 02:05:00,46.96387987740476\n2014-04-14 02:10:00,49.670268919495236\n2014-04-14 02:15:00,48.61762145858572\n2014-04-14 02:20:00,46.97286457247619\n2014-04-14 02:25:00,46.94949653956667\n2014-04-14 02:30:00,49.530829549857145\n2014-04-14 02:35:00,49.66282765214761\n2014-04-14 02:40:00,47.1197624590381\n2014-04-14 02:45:00,47.784720003728566\n2014-04-14 02:50:00,49.44850200211905\n2014-04-14 02:55:00,49.201589278209525\n2014-04-14 03:00:00,49.3806644263\n2014-04-14 03:05:00,48.20603323939048\n2014-04-14 03:10:00,49.786077145580954\n2014-04-14 03:15:00,47.45112760437142\n2014-04-14 03:20:00,46.7814504421619\n2014-04-14 03:25:00,48.99713171125238\n2014-04-14 03:30:00,48.327060521142855\n2014-04-14 03:35:00,49.59542640853333\n2014-04-14 03:40:00,46.50916080602381\n2014-04-14 03:45:00,49.56673389951429\n2014-04-14 03:50:00,47.37258337470476\n2014-04-14 03:55:00,48.82626790679524\n2014-04-14 04:00:00,46.374800870585716\n2014-04-14 04:05:00,48.66005137567619\n2014-04-14 04:10:00,49.098253423366664\n2014-04-14 04:15:00,47.71160800085714\n2014-04-14 04:20:00,47.10569044004762\n2014-04-14 04:25:00,48.4020108016381\n2014-04-14 04:30:00,49.59169178912857\n2014-04-14 04:35:00,47.56055848081905\n2014-04-14 04:40:00,47.28368671390952\n2014-04-14 04:45:00,47.3969912346\n2014-04-14 04:50:00,50.08521908789048\n2014-04-14 04:55:00,47.73323861548096\n2014-04-14 05:00:00,46.31798838817143\n2014-04-14 05:05:00,49.4377367365619\n2014-04-14 05:10:00,49.11555156225238\n2014-04-14 05:15:00,46.840165915542855\n2014-04-14 05:20:00,50.272950329833336\n2014-04-14 05:25:00,48.773022950723806\n2014-04-14 05:30:00,48.351332249514286\n2014-04-14 05:35:00,47.88453183240476\n2014-04-14 05:40:00,49.95778626039524\n2014-04-14 05:45:00,47.346389639985716\n2014-04-14 05:50:00,47.52105179137619\n2014-04-14 05:55:00,46.87505989336667\n2014-04-14 06:00:00,49.42933352515715\n2014-04-14 06:05:00,48.78249474064762\n2014-04-14 06:10:00,48.8440027722381\n2014-04-14 06:15:00,47.28906029552857\n2014-04-14 06:20:00,49.02729260411905\n2014-04-14 06:25:00,49.49189331280952\n2014-04-14 06:30:00,47.869054122899996\n2014-04-14 06:35:00,49.650329051990475\n2014-04-14 06:40:00,47.84754330648096\n2014-04-14 06:45:00,49.49237527457143\n2014-04-14 06:50:00,46.6021823345619\n2014-04-14 06:55:00,48.67936078685238\n2014-04-14 07:00:00,50.36024909974286\n2014-04-14 07:05:00,50.414561736033335\n2014-04-14 07:10:00,47.6240341229238\n2014-04-14 07:15:00,48.27006065001429\n2014-04-14 07:20:00,46.76381639380476\n2014-04-14 07:25:00,50.012710468495236\n2014-04-14 07:30:00,48.80107432688571\n2014-04-14 07:35:00,48.07462890627619\n2014-04-14 07:40:00,46.99274890066667\n2014-04-14 07:45:00,50.33617628485714\n2014-04-14 07:50:00,48.67742381034762\n2014-04-14 07:55:00,47.69569981153809\n2014-04-14 08:00:00,47.97228909192857\n2014-04-14 08:05:00,47.66165777131904\n2014-04-14 08:10:00,48.99354875920952\n2014-04-14 08:15:00,50.3136043031\n2014-04-14 08:20:00,50.02796568949047\n2014-04-14 08:25:00,48.45015445408095\n2014-04-14 08:30:00,49.92206887777142\n2014-04-14 08:35:00,48.315933829861905\n2014-04-14 08:40:00,47.64018094395238\n2014-04-14 08:45:00,50.57205331824285\n2014-04-14 08:50:00,47.86138360523333\n2014-04-14 08:55:00,47.94817073342381\n2014-04-14 09:00:00,103.32053728761429\n2014-04-14 09:05:00,91.68956866900476\n2014-04-14 09:10:00,100.21885747499523\n2014-04-14 09:15:00,102.61008922968571\n2014-04-14 09:20:00,96.85088811257619\n2014-04-14 09:25:00,89.93221262586667\n2014-04-14 09:30:00,95.00615878275714\n2014-04-14 09:35:00,91.43013591544762\n2014-04-14 09:40:00,95.5803902839381\n2014-04-14 09:45:00,100.67204252972857\n2014-04-14 09:50:00,95.90159611241904\n2014-04-14 09:55:00,95.81674117410951\n2014-04-14 10:00:00,107.2313726818\n2014-04-14 10:05:00,107.62527835149046\n2014-04-14 10:10:00,111.89459966498094\n2014-04-14 10:15:00,103.39799784537144\n2014-04-14 10:20:00,111.3720999277619\n2014-04-14 10:25:00,107.41049416065238\n2014-04-14 10:30:00,103.29886146874284\n2014-04-14 10:35:00,103.22243953633333\n2014-04-14 10:40:00,104.25437807502381\n2014-04-14 10:45:00,108.32116341121429\n2014-04-14 10:50:00,102.24660283260475\n2014-04-14 10:55:00,112.95542211529525\n2014-04-14 11:00:00,109.55069545308571\n2014-04-14 11:05:00,115.04665710777618\n2014-04-14 11:10:00,101.16018158546666\n2014-04-14 11:15:00,105.87849837865714\n2014-04-14 11:20:00,100.79978065464762\n2014-04-14 11:25:00,104.77438096253809\n2014-04-14 11:30:00,114.16127950642857\n2014-04-14 11:35:00,101.04160996841905\n2014-04-14 11:40:00,107.40329300090951\n2014-04-14 11:45:00,102.3440366888\n2014-04-14 11:50:00,107.11112432109047\n2014-04-14 11:55:00,113.83022654848095\n2014-04-14 12:00:00,110.79934499917144\n2014-04-14 12:05:00,112.6235677082619\n2014-04-14 12:10:00,106.43601542915238\n2014-04-14 12:15:00,115.95672354154289\n2014-04-14 12:20:00,112.20650900163332\n2014-04-14 12:25:00,107.62005638072381\n2014-04-14 12:30:00,107.70206296521428\n2014-04-14 12:35:00,115.57556287280478\n2014-04-14 12:40:00,110.11310336299523\n2014-04-14 12:45:00,112.19764059188572\n2014-04-14 12:50:00,107.5811327063762\n2014-04-14 12:55:00,104.49880600186668\n2014-04-14 13:00:00,112.57474734705714\n2014-04-14 13:05:00,210.7308639300476\n2014-04-14 13:10:00,109.0350190253381\n2014-04-14 13:15:00,111.00483737092857\n2014-04-14 13:20:00,104.36210860801906\n2014-04-14 13:25:00,113.73775010370952\n2014-04-14 13:30:00,116.2121839352\n2014-04-14 13:35:00,115.30688894679048\n2014-04-14 13:40:00,106.20183856408094\n2014-04-14 13:45:00,107.56207473887143\n2014-04-14 13:50:00,114.0063144366619\n2014-04-14 13:55:00,110.60201122435238\n2014-04-14 14:00:00,109.86989715764287\n2014-04-14 14:05:00,115.93668715283333\n2014-04-14 14:10:00,109.69455551802382\n2014-04-14 14:15:00,109.3646316862143\n2014-04-14 14:20:00,101.80571395190476\n2014-04-14 14:25:00,102.25150726329525\n2014-04-14 14:30:00,101.2670489415857\n2014-04-14 14:35:00,115.7669764314762\n2014-04-14 14:40:00,107.69708358596668\n2014-04-14 14:45:00,108.66727330585714\n2014-04-14 14:50:00,114.70363352334762\n2014-04-14 14:55:00,110.93300516003808\n2014-04-14 15:00:00,110.94766929422856\n2014-04-14 15:05:00,105.94768316961905\n2014-04-14 15:10:00,114.55302421830952\n2014-04-14 15:15:00,103.8713129451\n2014-04-14 15:20:00,102.07588458719047\n2014-04-14 15:25:00,104.29856404238095\n2014-04-14 15:30:00,105.52413460457143\n2014-04-14 15:35:00,105.7647542674619\n2014-04-14 15:40:00,111.98337576795238\n2014-04-14 15:45:00,104.74786159654286\n2014-04-14 15:50:00,112.09657107053333\n2014-04-14 15:55:00,102.73568338332382\n2014-04-14 16:00:00,103.64081090121428\n2014-04-14 16:05:00,109.43414406680476\n2014-04-14 16:10:00,116.05076151869524\n2014-04-14 16:15:00,115.06095248938571\n2014-04-14 16:20:00,116.81536326947617\n2014-04-14 16:25:00,111.73042348836665\n2014-04-14 16:30:00,112.14323600445714\n2014-04-14 16:35:00,111.33800816124763\n2014-04-14 16:40:00,111.3101834879381\n2014-04-14 16:45:00,103.70646133292857\n2014-04-14 16:50:00,110.05978740261905\n2014-04-14 16:55:00,107.54449635900953\n2014-04-14 17:00:00,108.4555650855\n2014-04-14 17:05:00,109.76001878009049\n2014-04-14 17:10:00,103.44419126438095\n2014-04-14 17:15:00,107.14909531347143\n2014-04-14 17:20:00,102.41992684096189\n2014-04-14 17:25:00,117.08685880065238\n2014-04-14 17:30:00,103.31606294204286\n2014-04-14 17:35:00,105.56344991363332\n2014-04-14 17:40:00,115.69517751272379\n2014-04-14 17:45:00,109.16529441181427\n2014-04-14 17:50:00,103.61957150490475\n2014-04-14 17:55:00,107.60450383799524\n2014-04-14 18:00:00,59.00583520508571\n2014-04-14 18:05:00,59.55310279617619\n2014-04-14 18:10:00,58.612152093566664\n2014-04-14 18:15:00,61.09125703985714\n2014-04-14 18:20:00,63.45651227724761\n2014-04-14 18:25:00,62.05168458923809\n2014-04-14 18:30:00,62.18953225182857\n2014-04-14 18:35:00,59.600101064119045\n2014-04-14 18:40:00,60.52472416840952\n2014-04-14 18:45:00,63.7407928963\n2014-04-14 18:50:00,58.90096441829047\n2014-04-14 18:55:00,63.83688055208095\n2014-04-14 19:00:00,51.88050152147143\n2014-04-14 19:05:00,53.4714310854619\n2014-04-14 19:10:00,51.15311995575238\n2014-04-14 19:15:00,51.25390809104285\n2014-04-14 19:20:00,53.11052185283333\n2014-04-14 19:25:00,53.26755536752381\n2014-04-14 19:30:00,50.787021280714285\n2014-04-14 19:35:00,54.12411695210476\n2014-04-14 19:40:00,50.15160977839524\n2014-04-14 19:45:00,50.08742786618571\n2014-04-14 19:50:00,52.45583382267618\n2014-04-14 19:55:00,53.03329402276667\n2014-04-14 20:00:00,52.01064645975714\n2014-04-14 20:05:00,49.74095529614762\n2014-04-14 20:10:00,48.1933314840381\n2014-04-14 20:15:00,50.56664172702857\n2014-04-14 20:20:00,49.29121371251905\n2014-04-14 20:25:00,49.88541068980952\n2014-04-14 20:30:00,50.120270754100005\n2014-04-14 20:35:00,48.39118390539048\n2014-04-14 20:40:00,50.12496209688095\n2014-04-14 20:45:00,49.88802654167142\n2014-04-14 20:50:00,51.0678429591619\n2014-04-14 20:55:00,50.801349700352375\n2014-04-14 21:00:00,48.562961825442855\n2014-04-14 21:05:00,48.65449682713333\n2014-04-14 21:10:00,48.84226779652381\n2014-04-14 21:15:00,48.56010184931428\n2014-04-14 21:20:00,50.48977600330476\n2014-04-14 21:25:00,51.852558960295234\n2014-04-14 21:30:00,50.48413950588571\n2014-04-14 21:35:00,50.30900061077619\n2014-04-14 21:40:00,49.525648968166664\n2014-04-14 21:45:00,49.14182967195714\n2014-04-14 21:50:00,51.55473520964762\n2014-04-14 21:55:00,51.795000374038096\n2014-04-14 22:00:00,49.82772088442857\n2014-04-14 22:05:00,49.00806539011904\n2014-04-14 22:10:00,50.93703561340952\n2014-04-14 22:15:00,48.391365788399995\n2014-04-14 22:20:00,50.933763275290474\n2014-04-14 22:25:00,51.154849200880946\n2014-04-14 22:30:00,48.383446829171426\n2014-04-14 22:35:00,51.8019889172619\n2014-04-14 22:40:00,51.84406589895238\n2014-04-14 22:45:00,51.65614776654286\n2014-04-14 22:50:00,49.89915733483333\n2014-04-14 22:55:00,48.905795294023804\n2014-04-14 23:00:00,50.24265439041429\n2014-04-14 23:05:00,49.601668623004755\n2014-04-14 23:10:00,48.75300398369524\n2014-04-14 23:15:00,49.63152273428571\n2014-04-14 23:20:00,50.60000139857619\n2014-04-14 23:25:00,48.235080369466665\n2014-04-14 23:30:00,49.292741211757146\n2014-04-14 23:35:00,48.03744684384762\n2014-04-14 23:40:00,50.972251727538094\n2014-04-14 23:45:00,50.544391690728574\n2014-04-14 23:50:00,48.239311716819046\n2014-04-14 23:55:00,51.85570667850952\n"
  },
  {
    "path": "workspace/anomaly_detector/datasets/selected/seasonal/art_daily_jumpsup_noised_trended_det2_ts.csv",
    "content": "timestamp,value\n1396310400,19.761251902999998\n1396310700,20.508273763190477\n1396311000,19.976522396880952\n1396311300,21.512587501971424\n1396311600,20.217501314561908\n1396311900,19.960328052752377\n1396312200,21.74304681884286\n1396312500,20.93084171753333\n1396312800,18.50572343892381\n1396313100,18.77778213051429\n1396313400,21.222896213704765\n1396313700,21.42525052279524\n1396314000,20.27004903068572\n1396314300,20.314547101976192\n1396314600,20.63189851806667\n1396314900,19.868070239957138\n1396315200,20.83984411294762\n1396315500,18.560413125538094\n1396315800,21.97904554092857\n1396316100,21.141988342819047\n1396316400,20.673506339809524\n1396316700,19.421538228\n1396317000,18.807512425990478\n1396317300,19.808502807680952\n1396317600,20.824878390871426\n1396317900,20.720850878461906\n1396318200,19.724017001252374\n1396318500,20.654038432442857\n1396318800,21.463326515633334\n1396319100,18.320912898923808\n1396319400,20.025698477414288\n1396319700,21.264875675804767\n1396320000,20.42267311999524\n1396320300,20.851440065985717\n1396320600,20.31968176087619\n1396320900,22.227914845366662\n1396321200,18.486343288857146\n1396321500,20.239476906147626\n1396321800,18.648404291738093\n1396322100,18.929320819928574\n1396322400,19.829772449319048\n1396322700,18.92721988980952\n1396323000,22.167248663800002\n1396323300,22.107099583090477\n1396323600,19.671819537280953\n1396323900,20.893812276771428\n1396324200,20.477275187161904\n1396324500,21.612050303052378\n1396324800,20.866925296442854\n1396325100,18.36559315133333\n1396325400,21.424721351923807\n1396325700,21.36685677091429\n1396326000,20.425795584204767\n1396326300,22.00602113099524\n1396326600,22.035570537085718\n1396326900,20.50487289727619\n1396327200,20.848619591466672\n1396327500,22.410195430557145\n1396327800,19.62682855824762\n1396328100,19.737457064438093\n1396328400,19.177524182128565\n1396328700,22.037336804219045\n1396329000,21.439263083609525\n1396329300,18.8913213955\n1396329600,22.403259880990475\n1396329900,21.40747778498095\n1396330200,21.893159866971427\n1396330500,18.691115061461907\n1396330800,20.52579605675238\n1396331100,21.307786004042853\n1396331400,20.692619671633327\n1396331700,21.19486367232381\n1396332000,21.807210540114284\n1396332300,20.040503013704765\n1396332600,21.945269940595242\n1396332900,19.209700133385716\n1396333200,19.649020410576192\n1396333500,18.746299146366667\n1396333800,20.038064388157142\n1396334100,20.10743579834762\n1396334400,21.816320484038094\n1396334700,21.21520125262857\n1396335000,20.357009280219046\n1396335300,21.226015438309524\n1396335600,18.8361334021\n1396335900,19.353526620290477\n1396336200,21.147672373380953\n1396336500,21.21278870547143\n1396336800,21.751300539561907\n1396337100,20.27420141715238\n1396337400,21.559859243642855\n1396337700,21.41300466353333\n1396338000,22.53809732302381\n1396338300,19.552485191414284\n1396338600,20.90612301690476\n1396338900,21.113903006495235\n1396339200,22.70887725398571\n1396339500,19.526462759176187\n1396339800,20.822038746566673\n1396340100,20.12134837375714\n1396340400,20.847619493347626\n1396340700,19.680002503638093\n1396341000,18.94937808512857\n1396341300,21.056630863219052\n1396341600,20.11722678720952\n1396341900,19.509015607000002\n1396342200,20.084432740490477\n1396342500,18.993251758180953\n1396342800,74.92958581217142\n1396343100,69.91462354836189\n1396343400,73.09930644725237\n1396343700,67.78030034374287\n1396344000,74.31841281223332\n1396344300,68.61390162262381\n1396344600,69.85387066761429\n1396344900,68.74405289080478\n1396345200,72.03568006189523\n1396345500,69.7770583696857\n1396345800,65.77172155117619\n1396346100,64.06475429266668\n1396346400,80.13990765835716\n1396346700,78.33237062224762\n1396347000,72.23728090793809\n1396347300,76.89516164052857\n1396347600,78.75194911701904\n1396347900,83.60344251280951\n1396348200,71.9585883865\n1396348500,76.19358828099048\n1396348800,83.56000397688095\n1396349100,80.86336084967142\n1396349400,75.30741505916191\n1396349700,83.93430347475238\n1396350000,80.39548396244285\n1396350300,80.48337181273331\n1396350600,88.09666885212381\n1396350900,87.63540515321431\n1396351200,78.28200855820477\n1396351500,74.82311570039523\n1396351800,77.7741894244857\n1396352100,73.08703196247619\n1396352400,72.93995913686669\n1396352700,78.90749119775714\n1396353000,87.59052687924763\n1396353300,86.4900552502381\n1396353600,81.15829421172856\n1396353900,82.02523879981905\n1396354200,73.09473154860952\n1396354500,76.4512308711\n1396354800,73.41070084389048\n1396355100,85.08037631648095\n1396355400,75.35720776567143\n1396355700,86.92517984006192\n1396356000,83.32538957295237\n1396356300,76.71828684284286\n1396356600,75.57993017653331\n1396356900,83.09681863002382\n1396357200,87.55336675621429\n1396357500,84.64187976130475\n1396357800,78.73372324459523\n1396358100,82.5616376855857\n1396358400,78.1441899914762\n1396358700,89.16319300076668\n1396359000,85.16662861575712\n1396359300,83.02326462964763\n1396359600,79.97347906433811\n1396359900,83.09846151082856\n1396360200,78.68238424141906\n1396360500,73.68700611410952\n1396360800,79.56765692970001\n1396361100,88.14096298019048\n1396361400,83.28176146948095\n1396361700,74.61209219977142\n1396362000,87.43552404396192\n1396362300,77.58553747455237\n1396362600,77.19131153154285\n1396362900,78.05185466793333\n1396363200,82.54086029622381\n1396363500,82.0280994602143\n1396363800,81.18319143010476\n1396364100,84.80842798599524\n1396364400,78.40314959548569\n1396364700,85.85894721047619\n1396365000,76.15859539126667\n1396365300,85.88272835755714\n1396365600,83.98921614184763\n1396365900,84.30702490723809\n1396366200,81.08801775882857\n1396366500,84.06259991911904\n1396366800,74.67485881190952\n1396367100,87.03024587450001\n1396367400,74.30174647989048\n1396367700,75.80028106358095\n1396368000,82.65705080557144\n1396368300,85.2664342373619\n1396368600,74.66333682805238\n1396368900,88.18296335724287\n1396369200,89.03588756493332\n1396369500,83.1608197228238\n1396369800,81.1729565479143\n1396370100,85.34281330270477\n1396370400,78.74166454819525\n1396370700,81.3876132668857\n1396371000,88.16122623537619\n1396371300,88.80073587276668\n1396371600,88.35092965575714\n1396371900,77.72443742994763\n1396372200,77.25221366243811\n1396372500,78.30278118942856\n1396372800,80.60856648641905\n1396373100,78.58170855020953\n1396373400,79.54987478470001\n1396373700,83.50010024889049\n1396374000,85.77775945288096\n1396374300,85.35372043357144\n1396374600,86.6230063261619\n1396374900,74.11462498665237\n1396375200,30.71263352284286\n1396375500,35.466627782133344\n1396375800,33.83372208772381\n1396376100,34.12955835781428\n1396376400,30.773455073104767\n1396376700,32.078347722295234\n1396377000,34.537246951585715\n1396377300,35.95798370177619\n1396377600,36.335353752266656\n1396377900,33.676785771657144\n1396378200,33.97257650864762\n1396378500,35.82049918083809\n1396378800,24.26498554472857\n1396379100,24.179394009119054\n1396379400,25.926084684609517\n1396379700,25.417647290300003\n1396380000,25.958834064990484\n1396380300,22.871376598280953\n1396380600,24.25027237397143\n1396380900,25.682785727861905\n1396381200,22.413893514752377\n1396381500,25.483478007142853\n1396381800,22.75055294013333\n1396382100,25.558644527323807\n1396382400,22.724469874714284\n1396382700,21.016649152304762\n1396383000,22.171453712195238\n1396383300,23.03311902138572\n1396383600,22.84373742017619\n1396383900,22.004920940266672\n1396384200,23.946162179957145\n1396384500,22.396700318047618\n1396384800,22.349270303938095\n1396385100,20.539656763628575\n1396385400,24.06912389771905\n1396385700,21.02502875920953\n1396386000,22.0849229424\n1396386300,23.198539327590474\n1396386600,20.842230716780954\n1396386900,22.103340106171427\n1396387200,20.958522645261905\n1396387500,23.051968464452383\n1396387800,22.27424282924286\n1396388100,23.45382145873333\n1396388400,23.616331281623808\n1396388700,22.635753847714287\n1396389000,22.951297207104766\n1396389300,22.250670613895238\n1396389600,21.520756843285717\n1396389900,22.583966645276195\n1396390200,23.633088978266674\n1396390500,21.672208707557143\n1396390800,21.27017504954762\n1396391100,21.57400743763809\n1396391400,21.76947100942857\n1396391700,20.328175628919052\n1396392000,22.03677089240952\n1396392300,22.027685149099998\n1396392600,22.41200540109048\n1396392900,21.516084293580953\n1396393200,22.509928676971427\n1396393500,23.578007613861903\n1396393800,23.89452614255238\n1396394100,22.41424593384286\n1396394400,20.25718585723333\n1396394700,23.971918169723807\n1396395000,22.925660629314283\n1396395300,21.453223374304766\n1396395600,20.70529505719524\n1396395900,20.697776306885714\n1396396200,20.80253864087619\n1396396500,20.321197751066673\n1396396800,23.751473897457146\n1396397100,22.31337055034762\n1396397400,22.95757574613809\n1396397700,23.47761260852857\n1396398000,23.33878307291905\n1396398300,23.71048201870952\n1396398600,24.056518490100004\n1396398900,21.951222935190483\n1396399200,24.00372281908095\n1396399500,23.102981221971426\n1396399800,20.499934665961906\n1396400100,22.95183486575237\n1396400400,22.979009495542854\n1396400700,23.86302558853333\n1396401000,21.738752339423808\n1396401300,22.594110286814285\n1396401600,20.310654965904764\n1396401900,21.59764620679524\n1396402200,20.52576061888572\n1396402500,22.371718081576184\n1396402800,23.561457268666672\n1396403100,21.124877911357146\n1396403400,22.41631180124762\n1396403700,21.130022641238085\n1396404000,20.80418244282857\n1396404300,22.372856215319047\n1396404600,20.65290400760952\n1396404900,22.6931685246\n1396405200,20.476540318890482\n1396405500,20.785490839880953\n1396405800,22.56606137047143\n1396406100,22.739141556361908\n1396406400,20.49690010135238\n1396406700,22.681900009142858\n1396407000,23.749843434633327\n1396407300,23.292538518723806\n1396407600,20.935454701414283\n1396407900,22.788053352204766\n1396408200,23.11460523839524\n1396408500,20.58196052128572\n1396408800,23.861866865176193\n1396409100,24.07298625586667\n1396409400,23.857166236257143\n1396409700,23.76132349104762\n1396410000,23.45009888903809\n1396410300,23.011406696528567\n1396410600,23.19962706761905\n1396410900,23.718140697109533\n1396411200,23.1499938334\n1396411500,21.818348302890477\n1396411800,22.018725360980948\n1396412100,24.110551302071425\n1396412400,20.598250247961907\n1396412700,23.33248470595238\n1396413000,24.36375306684285\n1396413300,23.37699601313333\n1396413600,24.53517176242381\n1396413900,23.317143907814284\n1396414200,20.711856878804763\n1396414500,23.88988476469524\n1396414800,21.727805362085714\n1396415100,22.380955093176194\n1396415400,21.852534330266668\n1396415700,21.685823567657145\n1396416000,22.34467043374762\n1396416300,22.141493889038095\n1396416600,23.167282898828567\n1396416900,23.89397385161905\n1396417200,21.837164136509518\n1396417500,21.5111346113\n1396417800,23.331271559690475\n1396418100,23.35241121568095\n1396418400,24.28309638567143\n1396418700,20.749794650561906\n1396419000,24.10561502945238\n1396419300,22.784901548942862\n1396419600,23.193541690033324\n1396419900,21.08125957172381\n1396420200,22.45367401721429\n1396420500,21.639864390904762\n1396420800,21.754995358395238\n1396421100,22.761916172985718\n1396421400,24.00279999207619\n1396421700,23.735540387266674\n1396422000,23.131856979157142\n1396422300,22.932970390047622\n1396422600,22.491962268138092\n1396422900,24.681018465628572\n1396423200,23.038389264519054\n1396423500,21.820925117009526\n1396423800,21.7328631682\n1396424100,23.265352599290477\n1396424400,22.918691061580954\n1396424700,20.865612640371424\n1396425000,24.162523393561905\n1396425300,23.666191797852377\n1396425600,23.504460015842856\n1396425900,21.139705964133327\n1396426200,22.32024721022381\n1396426500,24.620993328614286\n1396426800,24.337261727304764\n1396427100,22.03651698959524\n1396427400,21.53002125068572\n1396427700,22.705578019176194\n1396428000,22.339988181366667\n1396428300,23.653012649657146\n1396428600,24.797286859347626\n1396428900,22.39099389513809\n1396429200,64.99267731952858\n1396429500,76.36141956111905\n1396429800,64.67742585510952\n1396430100,77.1263662013\n1396430400,73.21447069709048\n1396430700,76.99060418718096\n1396431000,66.90644316697144\n1396431300,64.75202912026191\n1396431600,70.84560808555239\n1396431900,70.34187129534286\n1396432200,68.72912824963333\n1396432500,77.25240186122382\n1396432800,85.64221380881429\n1396433100,83.15090773360474\n1396433400,75.41815592429523\n1396433700,84.2947350098857\n1396434000,84.18870948737619\n1396434300,79.50997472116667\n1396434600,87.27303446165712\n1396434900,75.51929435124762\n1396435200,77.08431706383809\n1396435500,73.92392031662857\n1396435800,85.29551791851905\n1396436100,82.60726519600951\n1396436400,79.7018106216\n1396436700,77.30573298199047\n1396437000,75.34639108688094\n1396437300,77.36724295197143\n1396437600,81.93180092016188\n1396437900,78.66130489605239\n1396438200,78.85649540704286\n1396438500,88.67024986883331\n1396438800,82.94527336822381\n1396439100,86.3579876663143\n1396439400,75.33535169520476\n1396439700,80.58240324679524\n1396440000,82.78539522118571\n1396440300,78.1144166701762\n1396440600,77.0635236521667\n1396440900,89.05835776635716\n1396441200,90.1705165654476\n1396441500,76.42448217533807\n1396441800,80.75012681282855\n1396442100,90.49414001391905\n1396442400,76.51640054860951\n1396442700,85.4807540517\n1396443000,90.7391657612905\n1396443300,90.84252775528095\n1396443600,82.82405522547144\n1396443900,77.8970926726619\n1396444200,78.53374541685238\n1396444500,89.53881910974285\n1396444800,89.89948053983329\n1396445100,85.04723385362381\n1396445400,87.5868145598143\n1396445700,87.17443344940477\n1396446000,85.93241941099524\n1396446300,88.5865102486857\n1396446600,86.3245701976762\n1396446900,83.91012298976668\n1396447200,79.18052096175714\n1396447500,87.29848061884762\n1396447800,82.9789243803381\n1396448100,80.12816311552857\n1396448400,88.24968756471905\n1396448700,86.57348605340952\n1396449000,90.4307571332\n1396449300,78.08842365729049\n1396449600,85.83545492918095\n1396449900,79.36400934207144\n1396450200,89.9204397178619\n1396450500,77.06316059355238\n1396450800,85.97993977384287\n1396451100,88.14614216703333\n1396451400,81.17496354002381\n1396451700,90.7698358002143\n1396452000,89.12277384300474\n1396452300,80.23250157969524\n1396452600,75.64675083938572\n1396452900,80.2800042417762\n1396453200,80.04189978486667\n1396453500,89.78771296435714\n1396453800,91.02964672134762\n1396454100,76.69032585113807\n1396454400,83.11199310982856\n1396454700,84.35202593931905\n1396455000,77.07275501080952\n1396455300,81.6335635095\n1396455600,80.67436117369049\n1396455900,84.18537791398094\n1396456200,86.19496727247144\n1396456500,86.87911382166189\n1396456800,77.81889031765238\n1396457100,88.64539287454286\n1396457400,86.50234672513334\n1396457700,89.87830692512381\n1396458000,82.85006082791429\n1396458300,89.97035782540476\n1396458600,89.52794822849523\n1396458900,82.6975546904857\n1396459200,181.78873924537623\n1396459500,90.62287552696668\n1396459800,87.14796085345716\n1396460100,90.56468981094764\n1396460400,88.4718020129381\n1396460700,85.47640620852857\n1396461000,77.58873511991904\n1396461300,80.40622084620952\n1396461600,38.750584685300005\n1396461900,34.60173598589047\n1396462200,33.16170647478095\n1396462500,37.10065650737143\n1396462800,37.277382702261896\n1396463100,34.41412591045238\n1396463400,34.499737629542864\n1396463700,35.602992334833345\n1396464000,32.748967531623805\n1396464300,37.66862505251428\n1396464600,34.65376708120476\n1396464900,38.095922512195244\n1396465200,27.595068699885715\n1396465500,26.96980603037619\n1396465800,25.46960488546667\n1396466100,26.334704106257142\n1396466400,26.021881477847618\n1396466700,25.55467775643809\n1396467000,27.84357783312857\n1396467300,26.217479517019054\n1396467600,27.78940769140953\n1396467900,24.537627632399996\n1396468200,24.70548038859048\n1396468500,28.459524573180953\n1396468800,24.768070801371426\n1396469100,24.456028241161903\n1396469400,24.51829936865238\n1396469700,23.264633523842853\n1396470000,25.33414445403333\n1396470300,22.745035018923808\n1396470600,24.753547965214285\n1396470900,24.750523503504766\n1396471200,26.164610757195234\n1396471500,24.582780257385718\n1396471800,22.996384765276193\n1396472100,24.788413767166663\n1396472400,22.471321165957146\n1396472700,22.930785755647623\n1396473000,22.244169672238094\n1396473300,24.189608088728573\n1396473600,22.473772489919046\n1396473900,24.028049361109524\n1396474200,25.898592632600003\n1396474500,25.04920549609048\n1396474800,22.474913908380948\n1396475100,23.072365459371422\n1396475400,24.88624585196191\n1396475700,25.782088047752374\n1396476000,22.256223602642862\n1396476300,25.384787662133327\n1396476600,24.38871668622381\n1396476900,24.333206567714285\n1396477200,25.989115484804763\n1396477500,25.15507463349524\n1396477800,25.572805632485714\n1396478100,23.59384780207619\n1396478400,24.40353157796667\n1396478700,24.65537300035714\n1396479000,23.486398253347613\n1396479300,24.489450337838093\n1396479600,23.14668783882857\n1396479900,22.780937842619053\n1396480200,23.710933768209518\n1396480500,25.179932287399996\n1396480800,25.895098698090482\n1396481100,24.068294680780948\n1396481400,24.81631586827143\n1396481700,22.664195559361907\n1396482000,25.87795804125238\n1396482300,24.541702397442855\n1396482600,25.396241621533328\n1396482900,25.46010474192381\n1396483200,23.31163639121429\n1396483500,24.409852574604763\n1396483800,26.142514244295235\n1396484100,22.66657389358572\n1396484400,25.04767578257619\n1396484700,26.17197297876667\n1396485000,23.532665575057138\n1396485300,25.783589304647624\n1396485600,26.079868276838088\n1396485900,25.34102340902857\n1396486200,23.285432296819053\n1396486500,23.703562399109522\n1396486800,22.5182371777\n1396487100,25.70825341319048\n1396487400,25.788325698380948\n1396487700,24.928162668471426\n1396488000,23.81487330986191\n1396488300,22.719446491552375\n1396488600,25.431873296842863\n1396488900,25.333188107733324\n1396489200,26.08493389652381\n1396489500,25.364092369714285\n1396489800,25.764184530904764\n1396490100,25.44066370969524\n1396490400,24.987034467485714\n1396490700,24.179591767276193\n1396491000,26.087635901266665\n1396491300,25.090481430457142\n1396491600,24.087468906947624\n1396491900,22.83536527593809\n1396492200,23.67174799502857\n1396492500,24.69127598691905\n1396492800,23.62635100390953\n1396493100,23.4161913917\n1396493400,24.648264532590474\n1396493700,23.22541233598095\n1396494000,25.755211681871423\n1396494300,24.498484510161905\n1396494600,24.86390347685238\n1396494900,23.165425927542852\n1396495200,23.88163867583333\n1396495500,24.23113254252381\n1396495800,25.831065607814285\n1396496100,25.68629285420476\n1396496400,23.505005137295235\n1396496700,25.08525204068572\n1396497000,23.60180162157619\n1396497300,26.58840528946667\n1396497600,26.45135265535714\n1396497900,24.903356501147623\n1396498200,25.45334838283809\n1396498500,25.87090010022857\n1396498800,25.55661272781905\n1396499100,25.479374288109533\n1396499400,26.521716031799997\n1396499700,25.080764901390477\n1396500000,25.247591639680948\n1396500300,26.106896430371428\n1396500600,25.39682537616191\n1396500900,25.656432869052377\n1396501200,23.66881760194286\n1396501500,24.224651029833325\n1396501800,23.33622919232381\n1396502100,24.777526055014285\n1396502400,24.584814364604764\n1396502700,26.757996495195236\n1396503000,25.221620325585718\n1396503300,25.93000548327619\n1396503600,24.127725349666672\n1396503900,26.125288468257146\n1396504200,25.266887485047622\n1396504500,25.601957421638094\n1396504800,23.99915168322857\n1396505100,25.02342261441905\n1396505400,25.372457417509523\n1396505700,25.2001287033\n1396506000,26.51196532189048\n1396506300,26.451721610380954\n1396506600,26.75000766007143\n1396506900,25.54322392876191\n1396507200,26.768608901452378\n1396507500,26.218304857242856\n1396507800,23.97916189473333\n1396508100,24.613016487723808\n1396508400,23.86428405451429\n1396508700,22.934943405204763\n1396509000,23.67779025069524\n1396509300,22.94927805938572\n1396509600,25.819830035876194\n1396509900,24.65005385756667\n1396510200,24.205656051157145\n1396510500,26.009681183447622\n1396510800,26.300185193738088\n1396511100,26.878876726028572\n1396511400,25.553173386319045\n1396511700,24.838675358009525\n1396512000,24.221057206399998\n1396512300,23.896713313090483\n1396512600,23.866584754280954\n1396512900,24.659078927471427\n1396513200,26.996907325961903\n1396513500,23.04061717065238\n1396513800,23.833466446042856\n1396514100,23.805655262933325\n1396514400,25.928001751623807\n1396514700,24.476903196114286\n1396515000,24.90344798030476\n1396515300,23.676341759995235\n1396515600,71.79724544298571\n1396515900,67.70024363237619\n1396516200,73.55355538196666\n1396516500,67.64356891205715\n1396516800,77.06996160304763\n1396517100,74.03227145383809\n1396517400,76.17989165472856\n1396517700,72.03319190611906\n1396518000,71.53709111190952\n1396518300,67.6918908911\n1396518600,73.48812673199048\n1396518900,73.36836039448093\n1396519200,82.28351515847145\n1396519500,86.51885692466189\n1396519800,87.95392066945239\n1396520100,86.69314861234287\n1396520400,77.28112966173333\n1396520700,84.71013739362381\n1396521000,76.3098288860143\n1396521300,85.85119266300475\n1396521600,81.00423801669523\n1396521900,77.1419195155857\n1396522200,88.4720054907762\n1396522500,84.62982608856667\n1396522800,82.47740303305714\n1396523100,77.33198268424762\n1396523400,85.39612045443809\n1396523700,91.54116294282856\n1396524000,86.35044390691904\n1396524300,92.32619073970952\n1396524600,79.050618585\n1396524900,85.92626485969048\n1396525200,89.58876171588095\n1396525500,85.26102121637145\n1396525800,78.3585812303619\n1396526100,86.18792134955238\n1396526400,87.04680398284286\n1396526700,88.92354009133335\n1396527000,89.45039279112379\n1396527300,89.6106284615143\n1396527600,87.90287692780475\n1396527900,80.75678064599524\n1396528200,83.77539648118571\n1396528500,89.72600405687618\n1396528800,92.56679260296666\n1396529100,78.59934279855713\n1396529400,85.90345215954764\n1396529700,82.34694400883808\n1396530000,81.03458536792856\n1396530300,85.52761767091907\n1396530600,87.1391315896095\n1396530900,77.6077881773\n1396531200,89.93921963819048\n1396531500,90.58131670518095\n1396531800,92.91825706007143\n1396532100,80.37083796446191\n1396532400,86.99923029685237\n1396532700,84.32048059134286\n1396533000,82.85951321923334\n1396533300,86.55895700002381\n1396533600,90.0497869071143\n1396533900,77.90852559250477\n1396534200,93.05679653989523\n1396534500,90.5120630964857\n1396534800,89.57990256277618\n1396535100,89.73507480406667\n1396535400,83.80157369815714\n1396535700,89.60969318794761\n1396536000,83.77980839333809\n1396536300,91.97784163782856\n1396536600,80.44208507371904\n1396536900,82.29143778840952\n1396537200,86.4456247977\n1396537500,82.73907681959048\n1396537800,84.42692051428095\n1396538100,85.52531762287144\n1396538400,91.35559274986191\n1396538700,86.03250687635239\n1396539000,83.46825356114286\n1396539300,81.64013270563332\n1396539600,84.22258549752381\n1396539900,85.94297153931429\n1396540200,89.63643667390474\n1396540500,79.64291586379524\n1396540800,81.25988767828571\n1396541100,83.79604054137619\n1396541400,83.4953918371667\n1396541700,84.00442627005714\n1396542000,90.44022523634762\n1396542300,82.93781034463808\n1396542600,85.78914579952855\n1396542900,87.74872416691906\n1396543200,81.48852095420952\n1396543500,89.280215876\n1396543800,86.54231654479048\n1396544100,84.94447759578095\n1396544400,90.76008323307144\n1396544700,81.7069069076619\n1396545000,91.94923483655238\n1396545300,86.80264152794285\n1396545600,87.58010001263334\n1396545900,91.84168421182379\n1396546200,90.92950462011429\n1396546500,87.48061651910477\n1396546800,89.91406622409525\n1396547100,84.8036172476857\n1396547400,86.63598923537619\n1396547700,78.87851082466669\n1396548000,35.26794217805714\n1396548300,40.008613657047626\n1396548600,35.0896310886381\n1396548900,35.79932723772857\n1396549200,39.815941557419045\n1396549500,34.73738807680952\n1396549800,36.544881828\n1396550100,38.48278163899048\n1396550400,38.56325425248095\n1396550700,39.73359355667143\n1396551000,38.005183782261895\n1396551300,38.034868190352384\n1396551600,29.39153295144285\n1396551900,28.383419700333327\n1396552200,28.883062621823807\n1396552500,30.186490784914284\n1396552800,27.97040407140476\n1396553100,27.904704355195236\n1396553400,26.202684091085715\n1396553700,28.942374585376182\n1396554000,26.335043698566665\n1396554300,28.467691147057142\n1396554600,29.81951369034763\n1396554900,28.68763325013809\n1396555200,25.60785806972857\n1396555500,27.73101464201905\n1396555800,25.623070138109533\n1396556100,86.09375\n1396556400,27.032808857490483\n1396556700,25.236935554280954\n1396557000,28.25549951427143\n1396557300,25.377348199061903\n1396557600,28.61630076685238\n1396557900,24.600336397142854\n1396558200,25.657061011933326\n1396558500,25.40390135612381\n1396558800,24.303356555514284\n1396559100,27.198087774704767\n1396559400,27.04901217079524\n1396559700,27.45405265818572\n1396560000,25.30859894167619\n1396560300,26.070188521566664\n1396560600,26.94086615825714\n1396560900,26.066715141347622\n1396561200,27.109329780238088\n1396561500,26.86214444412857\n1396561800,24.78231145211905\n1396562100,27.468127984109522\n1396562400,27.1527528233\n1396562700,26.900576420590475\n1396563000,24.903130927780953\n1396563300,25.362616320771426\n1396563600,25.871259821261905\n1396563900,25.42527578795238\n1396564200,25.224038802042863\n1396564500,27.54388657703333\n1396564800,26.88218359672381\n1396565100,26.59830421491429\n1396565400,25.246363254404763\n1396565700,28.02495689049524\n1396566000,25.107620697385716\n1396566300,27.53059644197619\n1396566600,28.225055735966663\n1396566900,27.273992464957146\n1396567200,28.34470123314761\n1396567500,26.984648568338088\n1396567800,25.257392953528573\n1396568100,25.21025955401905\n1396568400,25.70077192430952\n1396568700,24.438231555\n1396569000,27.144463898890482\n1396569300,25.499464425880948\n1396569600,27.68930435777143\n1396569900,25.872702506961907\n1396570200,26.36327835485238\n1396570500,28.313648523342856\n1396570800,25.427021825533327\n1396571100,27.35079019922381\n1396571400,27.493685442914284\n1396571700,25.364647392004766\n1396572000,26.49208258449524\n1396572300,25.896343415585708\n1396572600,27.59060116407619\n1396572900,27.00034994276667\n1396573200,26.421789362257147\n1396573500,27.642750679247623\n1396573800,25.47336037523809\n1396574100,27.55466609372857\n1396574400,28.009116296019048\n1396574700,28.06954591100952\n1396575000,27.6971943721\n1396575300,26.20199714419048\n1396575600,28.504613043280955\n1396575900,26.10319600387143\n1396576200,27.14676350116191\n1396576500,25.243999093252377\n1396576800,28.52893845164285\n1396577100,27.43052702083333\n1396577400,27.63553399052381\n1396577700,24.892571099314285\n1396578000,27.69057601880476\n1396578300,27.743238954995235\n1396578600,27.338876619685717\n1396578900,25.826864645676192\n1396579200,26.625426835266666\n1396579500,25.115844628057147\n1396579800,26.567895884847612\n1396580100,25.664283505638092\n1396580400,26.09281651742857\n1396580700,25.35427068121905\n1396581000,25.63152699480952\n1396581300,25.0250245673\n1396581600,28.405795941890478\n1396581900,26.855273704280954\n1396582200,26.328039313671425\n1396582500,26.888628755861905\n1396582800,27.26912529485238\n1396583100,28.450908030642857\n1396583400,25.48560514243333\n1396583700,25.96048380402381\n1396584000,28.68887163111429\n1396584300,26.27792670850477\n1396584600,24.890841841095238\n1396584900,25.398609684785708\n1396585200,24.92083099747619\n1396585500,28.78260923636667\n1396585800,25.94584053885714\n1396586100,28.53196864674762\n1396586400,28.828783198238092\n1396586700,27.25204345602857\n1396587000,24.992904307919048\n1396587300,25.193926045309524\n1396587600,26.8013562204\n1396587900,26.507128527790474\n1396588200,27.314590175480948\n1396588500,26.652712667371432\n1396588800,28.641069301861908\n1396589100,27.051161242652377\n1396589400,27.694547102942856\n1396589700,28.51302442393333\n1396590000,25.52201131282381\n1396590300,25.860902902214285\n1396590600,25.378679403804764\n1396590900,25.515398834995235\n1396591200,27.01462158198572\n1396591500,26.25644322637619\n1396591800,26.671858024766664\n1396592100,28.916566470057138\n1396592400,25.62086501024762\n1396592700,27.164736378438093\n1396593000,25.40441319162857\n1396593300,26.290354300719052\n1396593600,27.13391321850953\n1396593900,28.8177769839\n1396594200,26.603603361290478\n1396594500,25.305757737280956\n1396594800,26.606217220371427\n1396595100,25.643976608261905\n1396595400,25.98841083415238\n1396595700,27.548255349842854\n1396596000,25.35302879813333\n1396596300,26.949668834523806\n1396596600,27.536060629714285\n1396596900,26.793088331404768\n1396597200,25.18960064059524\n1396597500,29.062613141885713\n1396597800,26.59643925987619\n1396598100,28.249725414366665\n1396598400,26.44544311155714\n1396598700,27.050364647047616\n1396599000,26.71159266563809\n1396599300,26.535335489428572\n1396599600,25.260024556419054\n1396599900,26.620143275209518\n1396600200,28.745459961599998\n1396600500,27.956513830590477\n1396600800,25.784072388780952\n1396601100,27.574441447071422\n1396601400,28.786185344561908\n1396601700,28.02483854485238\n1396602000,70.45425059324286\n1396602300,80.24210528893333\n1396602600,72.54802239022379\n1396602900,74.6298998483143\n1396603200,75.61744629370477\n1396603500,80.03623505759523\n1396603800,81.14664764828571\n1396604100,81.12750532847619\n1396604400,68.59984353206667\n1396604700,81.03679054685713\n1396605000,69.24621035664761\n1396605300,72.12850982793809\n1396605600,85.15404007682857\n1396605900,84.61731574091904\n1396606200,86.56140552490952\n1396606500,84.62475547\n1396606800,91.69270102419048\n1396607100,80.93194907668095\n1396607400,81.45893468007142\n1396607700,91.50336466676191\n1396608000,78.41194963425238\n1396608300,86.68877681314287\n1396608600,87.81637530943333\n1396608900,85.08928135712381\n1396609200,90.01977808651431\n1396609500,81.73364465210477\n1396609800,92.55385826809523\n1396610100,81.2280042795857\n1396610400,85.38299730487618\n1396610700,80.21281355786667\n1396611000,87.69439414035713\n1396611300,89.68243494034763\n1396611600,94.00742697983809\n1396611900,90.80408143092855\n1396612200,87.65881983091904\n1396612500,93.89290056490951\n1396612800,87.05940342139999\n1396613100,88.38955577719048\n1396613400,88.95461230338094\n1396613700,85.98772543197144\n1396614000,92.8429860861619\n1396614300,82.41006202445239\n1396614600,88.32506493304287\n1396614900,91.00754855383332\n1396615200,93.9193862170238\n1396615500,93.60628739541427\n1396615800,87.61808157920477\n1396616100,89.77367975689528\n1396616400,85.8782956194857\n1396616700,87.06849259397619\n1396617000,94.0836592871667\n1396617300,94.48201713055714\n1396617600,93.9249541581476\n1396617900,81.82261054013809\n1396618200,93.21472859002856\n1396618500,94.79426702721905\n1396618800,85.41013743820952\n1396619100,87.935319029\n1396619400,92.10894284339048\n1396619700,88.64494277338095\n1396620000,95.57008878057144\n1396620300,86.97361975936191\n1396620600,91.11253145225237\n1396620900,92.37828639024286\n1396621200,87.61010451633335\n1396621500,93.4234005373238\n1396621800,88.45781229831431\n1396622100,86.31329536290475\n1396622400,81.45973521109524\n1396622700,86.0363947942857\n1396623000,91.4919398029762\n1396623300,94.4968357055667\n1396623600,83.79399774665714\n1396623900,85.45832013214763\n1396624200,82.24539915253808\n1396624500,90.84094758402857\n1396624800,95.15979524281906\n1396625100,90.05950539110952\n1396625400,89.68493849709999\n1396625700,88.67500314819048\n1396626000,81.24196801658096\n1396626300,91.50607939967142\n1396626600,89.47427092676189\n1396626900,90.4325378798524\n1396627200,94.23795449414287\n1396627500,92.40779360303331\n1396627800,92.36650561432378\n1396628100,94.71423786471428\n1396628400,95.72569533450476\n1396628700,89.19471285249523\n1396629000,81.64374998598569\n1396629300,87.25515237037621\n1396629600,92.51812257496668\n1396629900,80.36757324735714\n1396630200,80.84160664514764\n1396630500,81.01337231023807\n1396630800,91.64296856522856\n1396631100,87.97250437741906\n1396631400,85.86364670560953\n1396631700,81.6585944273\n1396632000,91.69200233259049\n1396632300,85.11991830088095\n1396632600,84.23622727147144\n1396632900,90.4355874737619\n1396633200,88.95009557995238\n1396633500,85.81193325154284\n1396633800,90.2846012769333\n1396634100,84.36778882132381\n1396634400,41.92262145371429\n1396634700,38.31079023250476\n1396635000,37.867150763795244\n1396635300,41.86564144398572\n1396635600,41.39597878747619\n1396635900,38.041800357166665\n1396636200,37.624324287657146\n1396636500,42.25354522554762\n1396636800,41.865461897438095\n1396637100,38.99711983132857\n1396637400,41.12257612181905\n1396637700,37.71217903550952\n1396638000,30.556572281999998\n1396638300,28.37635107409048\n1396638600,30.054256176780953\n1396638900,28.642616144471425\n1396639200,30.443420049161904\n1396639500,30.211334949252386\n1396639800,30.32048656134285\n1396640100,28.540166449433325\n1396640400,29.964563823723807\n1396640700,31.741010637814284\n1396641000,30.012139957904765\n1396641300,31.57081430409524\n1396641600,28.15967032698571\n1396641900,28.387314700876193\n1396642200,28.97086851186667\n1396642500,30.562600088057145\n1396642800,27.121939781947614\n1396643100,26.81830266883809\n1396643400,29.18112094522857\n1396643700,30.585870456019048\n1396644000,30.75971520490953\n1396644300,28.696386512300002\n1396644600,28.637952551990477\n1396644900,29.36990230448095\n1396645200,28.62317859507143\n1396645500,28.945938575461906\n1396645800,29.917630819252377\n1396646100,29.41184656194286\n1396646400,28.41678289683333\n1396646700,28.283499394323808\n1396647000,29.005301582814287\n1396647300,28.273629411504764\n1396647600,28.28940195799524\n1396647900,26.52247235038571\n1396648200,27.163974725576193\n1396648500,28.435250639466663\n1396648800,29.703909957857146\n1396649100,27.533555948247614\n1396649400,28.51759876863809\n1396649700,27.81363155532857\n1396650000,26.85951744401905\n1396650300,30.284213311509525\n1396650600,29.8767574181\n1396650900,26.77649157599048\n1396651200,29.351573975080953\n1396651500,27.868755743271432\n1396651800,30.467761345461906\n1396652100,27.702737661152376\n1396652400,27.440735987842857\n1396652700,28.765037664533327\n1396653000,29.841625837723807\n1396653300,27.278143625614284\n1396653600,29.353516660104763\n1396653900,26.768474729095235\n1396654200,30.20668642648571\n1396654500,26.862044118776193\n1396654800,30.202750299566674\n1396655100,28.516169078657146\n1396655400,28.352712202247616\n1396655700,30.461419910938098\n1396656000,30.53296528222857\n1396656300,29.17958155141905\n1396656600,27.09478669120952\n1396656900,28.618430342600004\n1396657200,28.71784287999048\n1396657500,28.66641666488095\n1396657800,28.894038782671426\n1396658100,26.698410759961906\n1396658400,29.47586150685238\n1396658700,29.487970064942857\n1396659000,27.107712434033328\n1396659300,28.934231579323807\n1396659600,28.934159015414284\n1396659900,29.397956442704764\n1396660200,27.017186006595235\n1396660500,29.189048943385714\n1396660800,27.81348399347619\n1396661100,28.72592862866666\n1396661400,29.798651353657146\n1396661700,29.535381364547614\n1396662000,27.19585016593809\n1396662300,29.09241771992857\n1396662600,30.611585171419055\n1396662900,27.36963727310952\n1396663200,30.161628350900003\n1396663500,29.56763279839048\n1396663800,29.86089420398095\n1396664100,27.90015473717143\n1396664400,27.931317622261904\n1396664700,30.411280204052378\n1396665000,28.23397098554285\n1396665300,27.054144896133327\n1396665600,29.211910623823808\n1396665900,27.316234961914287\n1396666200,30.010789727504765\n1396666500,29.39883100809524\n1396666800,30.338191735185717\n1396667100,29.98607518957619\n1396667400,27.302621260066662\n1396667700,28.385889848557138\n1396668000,29.96728861874761\n1396668300,28.545853988338088\n1396668600,30.773390510528568\n1396668900,29.834330847219054\n1396669200,26.96080919060952\n1396669500,30.4261927662\n1396669800,27.31690961569048\n1396670100,27.48322584908095\n1396670400,29.866541030971426\n1396670700,30.395886142461904\n1396671000,29.08885089255238\n1396671300,28.10709178894286\n1396671600,28.36359551433333\n1396671900,28.337331127923807\n1396672200,28.279926700914285\n1396672500,27.95229344920476\n1396672800,29.423563616595235\n1396673100,30.59715698858571\n1396673400,28.231305842776194\n1396673700,27.757193856466664\n1396674000,30.372167808357137\n1396674300,29.992430942647616\n1396674600,30.75608622143809\n1396674900,27.702257513828567\n1396675200,27.624624304119052\n1396675500,29.22077710100952\n1396675800,29.5202346193\n1396676100,28.990634243590478\n1396676400,29.47324749768095\n1396676700,27.806340504071432\n1396677000,29.010716921461906\n1396677300,29.73207262475238\n1396677600,28.837968654142852\n1396677900,29.83237267663333\n1396678200,28.92678893172381\n1396678500,28.463862609114283\n1396678800,28.351324950204763\n1396679100,28.78795347409524\n1396679400,27.24414420498572\n1396679700,29.83332674427619\n1396680000,30.547089230566673\n1396680300,28.592615520657137\n1396680600,27.365680163647614\n1396680900,31.136090484738087\n1396681200,28.251221593228568\n1396681500,27.71035353441905\n1396681800,28.690319555709518\n1396682100,30.1729781625\n1396682400,28.401856863790478\n1396682700,29.53244376808095\n1396683000,28.903311406271428\n1396683300,27.719567873861905\n1396683600,28.577100430952378\n1396683900,30.162874880042853\n1396684200,29.718848922633327\n1396684500,27.75738732902381\n1396684800,27.93900392461429\n1396685100,29.85608819910476\n1396685400,30.554256895395238\n1396685700,28.705933698085712\n1396686000,29.69671919787619\n1396686300,28.005491021666664\n1396686600,28.57586249045714\n1396686900,27.418878441747612\n1396687200,30.41834188643809\n1396687500,28.95671785052857\n1396687800,30.62462134221905\n1396688100,30.201051507909533\n1396688400,81.84592201390001\n1396688700,74.46739838249049\n1396689000,73.10735968618096\n1396689300,83.81523871267144\n1396689600,80.3604198085619\n1396689900,81.95517722475238\n1396690200,70.79825673964284\n1396690500,75.44776136933335\n1396690800,80.73683080142379\n1396691100,71.70253081441426\n1396691400,78.36522780400476\n1396691700,76.49223487549523\n1396692000,79.57769390508571\n1396692300,82.97406714737619\n1396692600,83.73913833696669\n1396692900,81.06267351015714\n1396693200,89.13550045824762\n1396693500,83.10350313463809\n1396693800,83.65758320552857\n1396694100,93.29703209171906\n1396694400,86.61355992240952\n1396694700,85.457078841\n1396695000,90.61316899079048\n1396695300,93.50333707998095\n1396695600,81.51974932007144\n1396695900,88.2578025203619\n1396696200,90.8503190680524\n1396696500,86.21032036974285\n1396696800,93.4357057459333\n1396697100,96.60914513512381\n1396697400,96.17048311851428\n1396697700,85.40384106820477\n1396698000,84.78077921839524\n1396698300,96.41646511968572\n1396698600,88.49000365457618\n1396698900,84.51618365456667\n1396699200,92.85483421925714\n1396699500,86.10916193124761\n1396699800,85.8421585544381\n1396700100,95.62988167902857\n1396700400,84.18276590191905\n1396700700,82.62271032270951\n1396701000,85.90291466309999\n1396701300,91.30801372969047\n1396701600,83.58302332008095\n1396701900,89.15988156727144\n1396702200,91.65621079906192\n1396702500,95.20179851215237\n1396702800,85.39189361714286\n1396703100,94.79670589753331\n1396703400,85.48734194762382\n1396703700,92.56285016201431\n1396704000,88.63374811910477\n1396704300,83.58652474019523\n1396704600,93.18497834778572\n1396704900,85.25031187877619\n1396705200,84.59968324906667\n1396705500,87.51361804025714\n1396705800,92.23940290064762\n1396706100,85.53975320943809\n1396706400,84.75641613982856\n1396706700,81.98466341461905\n1396707000,89.3787808555095\n1396707300,88.6982939092\n1396707600,85.58943876399047\n1396707900,82.71356837168095\n1396708200,88.73037975357144\n1396708500,94.4807323403619\n1396708800,93.32146114555236\n1396709100,95.65699400444285\n1396709400,82.04569297723333\n1396709700,97.3617846683238\n1396710000,87.3725666868143\n1396710300,97.76367617430478\n1396710600,85.96677660539524\n1396710900,89.4768542875857\n1396711200,87.60257345237619\n1396711500,87.63934226176666\n1396711800,95.43105014825714\n1396712100,93.90469480484762\n1396712400,97.84381746443809\n1396712700,91.79312805902859\n1396713000,89.39646236171906\n1396713300,83.43303629560953\n1396713600,97.94481385790002\n1396713900,90.83177574009048\n1396714200,93.22236070878095\n1396714500,88.53004888847143\n1396714800,90.79305816976186\n1396715100,97.1182788952524\n1396715400,84.70721051164286\n1396715700,86.72989746093333\n1396716000,84.4923365427238\n1396716300,94.74225616971428\n1396716600,83.06698878260475\n1396716900,83.38781088799523\n1396717200,86.86516203698571\n1396717500,90.32370627807622\n1396717800,88.60453333146667\n1396718100,82.82864019025713\n1396718400,97.43887901414763\n1396718700,97.37236691853808\n1396719000,86.60360037892859\n1396719300,93.84574674941904\n1396719600,91.40598490320951\n1396719900,85.95584801300001\n1396720200,86.3584060452905\n1396720500,90.02955107568094\n1396720800,41.66168180937143\n1396721100,40.849873717961906\n1396721400,44.16152007545239\n1396721700,42.08224940884285\n1396722000,43.19935459833333\n1396722300,40.227118448423816\n1396722600,42.43765714061429\n1396722900,41.065695558004776\n1396723200,42.407136168195244\n1396723500,44.04281455908571\n1396723800,43.97401426057619\n1396724100,41.32742304126667\n1396724400,33.538217350857146\n1396724700,34.65227525954762\n1396725000,33.245735433638096\n1396725300,31.11505478182857\n1396725600,33.50271243381904\n1396725900,30.93503004290952\n1396726200,34.379553311100004\n1396726500,32.794578264490475\n1396726800,32.21281025048096\n1396727100,30.75020985267143\n1396727400,32.20817183626191\n1396727700,34.556066925352376\n1396728000,28.875088987742853\n1396728300,30.74074194313333\n1396728600,32.61804708372381\n1396728900,30.428732780114284\n1396729200,30.572712135504762\n1396729500,31.196126974595238\n1396729800,30.72997678868571\n1396730100,29.53181848827619\n1396730400,28.924669932566662\n1396730700,31.353895442757143\n1396731000,32.63517113294762\n1396731300,29.30665535773809\n1396731600,29.38068969432857\n1396731900,30.02829534921905\n1396732200,31.798206238509522\n1396732500,29.6373610171\n1396732800,32.10774348499048\n1396733100,28.790917597380954\n1396733400,32.35936422727143\n1396733700,30.838666510361904\n1396734000,31.24011157565238\n1396734300,30.07761053824286\n1396734600,31.75022471373333\n1396734900,29.28413683602381\n1396735200,28.748829399314285\n1396735500,30.144021309804764\n1396735800,31.985936274995236\n1396736100,31.597921969585716\n1396736400,30.653365941476192\n1396736700,30.880944654266663\n1396737000,29.117707227357144\n1396737300,31.971031860047614\n1396737600,31.763378741838093\n1396737900,31.24836098312857\n1396738200,30.49395335671905\n1396738500,32.496380109809515\n1396738800,32.1452589819\n1396739100,31.214113370890473\n1396739400,30.13082648448095\n1396739700,31.123341182371433\n1396740000,30.96042354756191\n1396740300,30.242929108252376\n1396740600,29.90003026764285\n1396740900,30.308895084633328\n1396741200,30.984066195623807\n1396741500,30.408288470214284\n1396741800,29.75736113800476\n1396742100,31.754738926895236\n1396742400,30.840155698085717\n1396742700,28.992426843376194\n1396743000,30.202432689166667\n1396743300,32.276260971657145\n1396743600,31.764993743847622\n1396743900,30.044475231038092\n1396744200,32.511661179628575\n1396744500,29.072780681019047\n1396744800,32.61874833940952\n1396745100,29.764070369899997\n1396745400,28.825067197390474\n1396745700,30.53136309848095\n1396746000,30.23945314727143\n1396746300,30.967367925561906\n1396746600,32.005543823252374\n1396746900,32.19561606574285\n1396747200,30.43825333173333\n1396747500,30.560156784323805\n1396747800,29.440925207014285\n1396748100,29.045845197404763\n1396748400,31.42795519899523\n1396748700,29.12828621648571\n1396749000,31.813296668176193\n1396749300,31.041777246766664\n1396749600,29.68718905575714\n1396749900,31.05838939314762\n1396750200,29.639728961638088\n1396750500,30.67012740142857\n1396750800,32.120860312619044\n1396751100,30.777736697409527\n1396751400,29.5322972732\n1396751700,31.840255203490482\n1396752000,29.699454617480956\n1396752300,31.91402092607143\n1396752600,30.884671061661905\n1396752900,30.789669417352385\n1396753200,32.38788300854286\n1396753500,31.82399743073333\n1396753800,29.128666997323805\n1396754100,30.189161544114285\n1396754400,32.49558740530476\n1396754700,29.092649912295236\n1396755000,31.207799499285716\n1396755300,31.94552886717619\n1396755600,31.52909100856667\n1396755900,32.09123595125714\n1396756200,31.959315014747617\n1396756500,31.83211087583809\n1396756800,32.35758801512857\n1396757100,31.661631721419052\n1396757400,30.695983500809522\n1396757700,30.9813864397\n1396758000,31.968089606890477\n1396758300,32.61385507108095\n1396758600,30.20494663197143\n1396758900,30.491819088661906\n1396759200,32.853909966352376\n1396759500,31.452440026742853\n1396759800,29.861680601833328\n1396760100,31.808054365123812\n1396760400,33.12376290791428\n1396760700,32.46196901980476\n1396761000,32.158559784295235\n1396761300,30.01522233138571\n1396761600,32.69503532917619\n1396761900,31.301072040766673\n1396762200,32.76251723115714\n1396762500,30.532108936747623\n1396762800,29.46844230573809\n1396763100,31.13158244602857\n1396763400,30.31446946691905\n1396763700,32.103476682909516\n1396764000,33.0784262114\n1396764300,32.021337080790474\n1396764600,32.812616671180955\n1396764900,31.08441748297143\n1396765200,32.366324853561906\n1396765500,32.65937612765238\n1396765800,32.13814536744285\n1396766100,31.33319247763333\n1396766400,31.81298824802381\n1396766700,32.11899226841429\n1396767000,30.336742374804764\n1396767300,32.570162281795234\n1396767600,33.140583870185715\n1396767900,31.20768345117619\n1396768200,32.158435399066676\n1396768500,32.30971076605714\n1396768800,32.01803780914762\n1396769100,31.56494852853809\n1396769400,32.91052038972857\n1396769700,31.187075884719054\n1396770000,29.64322134970952\n1396770300,32.7844755028\n1396770600,32.10961556549048\n1396770900,32.818165458380946\n1396771200,29.982761198371428\n1396771500,29.55902366676191\n1396771800,33.18095054245238\n1396772100,30.04180608054285\n1396772400,32.69694266163333\n1396772700,32.75861357822381\n1396773000,32.308035087914284\n1396773300,30.005703606304763\n1396773600,32.15768973629524\n1396773900,33.051882047585714\n1396774200,31.205102769676188\n1396774500,31.164484084166666\n1396774800,78.74073015315713\n1396775100,73.84419533224761\n1396775400,84.8642858340381\n1396775700,84.56106552152858\n1396776000,86.31918582391907\n1396776300,80.71355024820951\n1396776600,82.97870625569999\n1396776900,75.52627840199048\n1396777200,81.85577288018095\n1396777500,81.62118817167143\n1396777800,85.04870071216189\n1396778100,84.09848341155237\n1396778400,96.01214235694286\n1396778700,94.93887882963331\n1396779000,94.9441530583238\n1396779300,82.45845031591429\n1396779600,94.60623426770478\n1396779900,90.91240992079523\n1396780200,87.39628360568571\n1396780500,82.37633316097619\n1396780800,92.02416365106669\n1396781100,86.60779831115713\n1396781400,88.78143525164762\n1396781700,92.1094134383381\n1396782000,97.76529096732857\n1396782300,96.39961775341905\n1396782600,90.44560626510952\n1396782900,89.454053336\n1396783200,87.1076474427905\n1396783500,89.22470600308094\n1396783800,85.07515317207144\n1396784100,98.7609739097619\n1396784400,92.45153540965237\n1396784700,85.36401698094286\n1396785000,88.94986010473333\n1396785300,92.04638434962379\n1396785600,92.21525306771429\n1396785900,84.27412699670475\n1396786200,98.90939563789522\n1396786500,88.12235940478571\n1396786800,83.98772014777619\n1396787100,84.95815308486668\n1396787400,93.01593585265715\n1396787700,85.95332046784763\n1396788000,84.42563366483809\n1396788300,89.83301320582858\n1396788600,93.72594111021904\n1396788900,85.56844907700952\n1396789200,88.8697621355\n1396789500,90.5477270211905\n1396789800,86.42335019018093\n1396790100,91.97528048027144\n1396790400,85.25058007306191\n1396790700,84.63903969145238\n1396791000,92.21773256384287\n1396791300,87.87520297293331\n1396791600,85.44285850042381\n1396791900,90.70565786121428\n1396792200,98.57086245370476\n1396792500,95.52386348559523\n1396792800,97.01005796678572\n1396793100,97.91822438067621\n1396793400,99.53700755086668\n1396793700,96.19451014575714\n1396794000,93.72465111274764\n1396794300,89.84456553303811\n1396794600,86.91162485432855\n1396794900,94.99894367651905\n1396795200,99.93878918020953\n1396795500,91.5051740224\n1396795800,95.61354857989048\n1396796100,91.96377392128096\n1396796400,90.96374865737144\n1396796700,90.62514749876188\n1396797000,92.14167859755241\n1396797300,89.94547589184286\n1396797600,96.0629002709333\n1396797900,98.07830074682379\n1396798200,98.22355238081428\n1396798500,87.74810800220476\n1396798800,98.44681264619524\n1396799100,89.5846117616857\n1396799400,89.07616012857618\n1396799700,95.76271075526668\n1396800000,89.01785098395712\n1396800300,84.99762024164762\n1396800600,90.13547273463809\n1396800900,95.70846777372856\n1396801200,89.40380548781906\n1396801500,94.2528468397095\n1396801800,94.7492525893\n1396802100,95.93455588349049\n1396802400,98.55630261348095\n1396802700,91.13070188847144\n1396803000,86.8800317785619\n1396803300,89.32736579045236\n1396803600,91.14678863664284\n1396803900,95.6618148084333\n1396804200,84.45695008992381\n1396804500,89.30700083261429\n1396804800,96.73935361890476\n1396805100,95.00303672159524\n1396805400,95.9845931478857\n1396805700,97.27316586577619\n1396806000,96.82340570846668\n1396806300,95.21400596195716\n1396806600,91.34110178764763\n1396806900,100.05152766603807\n1396807200,44.76349079432857\n1396807500,42.426586208819046\n1396807800,43.010305907109526\n1396808100,45.5825433364\n1396808400,47.069517027590464\n1396808700,42.30243403008095\n1396809000,41.69308337057143\n1396809300,46.81530399936191\n1396809600,47.03872479165239\n1396809900,42.95721479794285\n1396810200,43.610455976133345\n1396810500,45.428470652623815\n1396810800,34.04879959211428\n1396811100,36.50782445350476\n1396811400,33.06754669389524\n1396811700,32.76319494888571\n1396812000,33.53449323957619\n1396812300,33.88958873676667\n1396812600,33.12126713815714\n1396812900,32.91708962044762\n1396813200,36.01535936013809\n1396813500,33.37363644032857\n1396813800,36.739489168919064\n1396814100,34.30119681070953\n1396814400,33.6788011425\n1396814700,31.86268730599048\n1396815000,31.931242779080954\n1396815300,33.30833007407143\n1396815600,33.2581550774619\n1396815900,34.11791703995238\n1396816200,34.08064589884285\n1396816500,33.73122016323333\n1396816800,32.831162364123806\n1396817100,34.64702704291428\n1396817400,33.55648600610476\n1396817700,35.06969798519523\n1396818000,33.968896834285715\n1396818300,30.861216139176193\n1396818600,31.979097650566665\n1396818900,32.996489972657145\n1396819200,33.605177934347616\n1396819500,32.9248004974381\n1396819800,33.87994391342857\n1396820100,31.863818600119053\n1396820400,31.474388794109522\n1396820700,30.959351890700002\n1396821000,33.054353028490475\n1396821300,33.52515009488096\n1396821600,32.00170270247143\n1396821900,33.1599847973619\n1396822200,30.91956157915238\n1396822500,31.11572751974285\n1396822800,33.535327150433325\n1396823100,32.20674600852381\n1396823400,33.42840832261429\n1396823700,34.07801304160476\n1396824000,34.16913904759524\n1396824300,31.45214741068571\n1396824600,32.717265806676195\n1396824900,33.71622182956666\n1396825200,33.867829942957144\n1396825500,33.91806017104762\n1396825800,31.699038663438092\n1396826100,31.56392170722857\n1396826400,33.161578048319036\n1396826700,33.773427866609524\n1396827000,32.0927591594\n1396827300,31.242297515390483\n1396827600,33.69837294318096\n1396827900,32.03729892017142\n1396828200,31.51129656676191\n1396828500,31.444165944352374\n1396828800,32.11678104724285\n1396829100,33.23529559703333\n1396829400,32.3056327643238\n1396829700,30.962111692114288\n1396830000,31.274538500604766\n1396830300,32.056358226895235\n1396830600,33.540603642885706\n1396830900,31.30328648437619\n1396831200,33.15929408066667\n1396831500,31.40365062615714\n1396831800,31.778008928447623\n1396832100,31.627742205438093\n1396832400,31.215343113728572\n1396832700,33.63918831711905\n1396833000,32.81492371330953\n1396833300,34.2929637636\n1396833600,31.37175383609048\n1396833900,31.562562685780946\n1396834200,32.21690235397143\n1396834500,34.0619758525619\n1396834800,32.22898767355238\n1396835100,32.64706768714286\n1396835400,32.22724759853333\n1396835700,31.34917097672381\n1396836000,34.79344877731428\n1396836300,33.23731073020476\n1396836600,34.20192799079524\n1396836900,33.69146408298571\n1396837200,33.12249330667619\n1396837500,31.431629693266665\n1396837800,33.651291323957146\n1396838100,31.70927904274761\n1396838400,32.752770772638094\n1396838700,33.619131145328566\n1396839000,34.23903504951905\n1396839300,33.85774022660952\n1396839600,33.811134116199995\n1396839900,31.72860931289048\n1396840200,32.52439511268095\n1396840500,31.318970519171422\n1396840800,34.0326694774619\n1396841100,34.97254630625238\n1396841400,32.226084417842856\n1396841700,31.52787016993333\n1396842000,33.08680411652381\n1396842300,34.61875717821428\n1396842600,33.40730154300476\n1396842900,31.39395383889524\n1396843200,35.111374676385715\n1396843500,34.53632583037618\n1396843800,31.75554297486666\n1396844100,34.92379816885715\n1396844400,33.04680077344762\n1396844700,32.7390800575381\n1396845000,33.10314189352857\n1396845300,34.604656875119055\n1396845600,33.911728236909525\n1396845900,31.5182438096\n1396846200,35.11910796069048\n1396846500,31.88726748628095\n1396846800,34.28584323547143\n1396847100,33.855558026461914\n1396847400,32.06856457275238\n1396847700,32.008821161642864\n1396848000,34.81464370813333\n1396848300,33.01955350352381\n1396848600,33.966520342414285\n1396848900,33.37193877730476\n1396849200,34.27250930639524\n1396849500,33.28750521448571\n1396849800,32.52749585147619\n1396850100,32.83895015066667\n1396850400,34.82916792065714\n1396850700,33.27243639074762\n1396851000,32.2615354242381\n1396851300,35.15360012372857\n1396851600,34.609020873619045\n1396851900,31.65272410800952\n1396852200,35.4332718479\n1396852500,34.224647261990484\n1396852800,32.093447348580945\n1396853100,32.40849215377143\n1396853400,34.237043829761895\n1396853700,34.59374660205238\n1396854000,32.43828662974285\n1396854300,32.517458748933336\n1396854600,32.72550658902381\n1396854900,33.896537745014285\n1396855200,32.19916947510476\n1396855500,31.93631803359523\n1396855800,34.24224207058572\n1396856100,34.65061794967619\n1396856400,33.54538428436667\n1396856700,33.004437983957146\n1396857000,33.28471847314762\n1396857300,33.11761943073809\n1396857600,35.41136820442857\n1396857900,34.651228668519046\n1396858200,32.418658383209525\n1396858500,33.1305066082\n1396858800,33.77723964169048\n1396859100,34.06057440068095\n1396859400,33.48880701267143\n1396859700,34.864018444761896\n1396860000,34.70137645875238\n1396860300,33.659024531642864\n1396860600,35.063550880433326\n1396860900,34.65763193132381\n1396861200,85.4494274283143\n1396861500,87.87520536220474\n1396861800,78.49954563849523\n1396862100,78.5230507224857\n1396862400,86.98022686787618\n1396862700,85.40019534466667\n1396863000,87.50637650635714\n1396863300,75.77136779944762\n1396863600,83.45773434603808\n1396863900,76.89462396992856\n1396864200,81.78812094441905\n1396864500,77.06071779700952\n1396864800,85.5777784594\n1396865100,83.78629319649049\n1396865400,93.38618732058094\n1396865700,89.18435243957144\n1396866000,85.25228408606192\n1396866300,88.63764469135236\n1396866600,86.25665515644285\n1396866900,98.25718711823332\n1396867200,88.61599963652382\n1396867500,88.83992296721428\n1396867800,96.69900097470476\n1396868100,93.72501465329523\n1396868400,96.70185495838571\n1396868700,95.5296988810762\n1396869000,100.4704723665667\n1396869300,88.72174836795715\n1396869600,101.16672771994763\n1396869900,98.66001514313808\n1396870200,94.81894862492857\n1396870500,95.99372736201904\n1396870800,95.78573626370951\n1396871100,86.4029835474\n1396871400,88.94902486889048\n1396871700,100.78036389988097\n1396872000,94.38174249327145\n1396872300,91.8960051677619\n1396872600,98.03503665665238\n1396872900,94.24672517594286\n1396873200,86.08228495103333\n1396873500,97.6450395951238\n1396873800,97.58823666941427\n1396874100,88.53346330040476\n1396874400,101.18988877919523\n1396874700,89.4873667827857\n1396875000,93.2317772807762\n1396875300,87.75758911636667\n1396875600,95.65077764995712\n1396875900,92.01379380764763\n1396876200,91.6648773045381\n1396876500,99.25135301572857\n1396876800,86.18328973621904\n1396877100,98.8018637425095\n1396877400,95.1862026895\n1396877700,101.8264500735905\n1396878000,95.48892902008095\n1396878300,86.95339491907144\n1396878600,86.88511264976191\n1396878900,100.2094788554524\n1396879200,99.56246713284284\n1396879500,91.64510289903332\n1396879800,96.0066129075238\n1396880100,93.9590939924143\n1396880400,101.60733086210476\n1396880700,101.33953408219524\n1396881000,101.8889982625857\n1396881300,100.01828524797621\n1396881600,100.71533758346668\n1396881900,89.64694473305714\n1396882200,99.47356202964762\n1396882500,97.52670150423809\n1396882800,101.60017362862855\n1396883100,95.34327935691906\n1396883400,87.57327990950951\n1396883700,95.77634929850001\n1396884000,97.21068866569048\n1396884300,89.75804237048095\n1396884600,92.54613382897145\n1396884900,95.8237833994619\n1396885200,92.24089551535238\n1396885500,92.26180754094288\n1396885800,88.39950791803335\n1396886100,101.3293856800238\n1396886400,98.29346314241428\n1396886700,86.31291150560476\n1396887000,98.55024602279524\n1396887300,98.14459463028572\n1396887600,86.4710330140762\n1396887900,92.23643583426669\n1396888200,96.03816330875713\n1396888500,93.58165590024765\n1396888800,98.79285385503808\n1396889100,93.15986058352856\n1396889400,88.82178359221905\n1396889700,101.99004127670952\n1396890000,90.24761074930001\n1396890300,97.86548538739048\n1396890600,88.68035341148097\n1396890900,91.66149357967144\n1396891200,93.47717327586192\n1396891500,89.4878856243524\n1396891800,93.61896566644285\n1396892100,88.94165988763335\n1396892400,95.3785973507238\n1396892700,97.06134460021428\n1396893000,87.44832527480476\n1396893300,100.39492617519524\n1396893600,44.44918162148571\n1396893900,44.71403990597619\n1396894200,47.51179930096665\n1396894500,46.28660782405714\n1396894800,46.49017331044762\n1396895100,44.12167430933809\n1396895400,48.46563131172857\n1396895700,47.26550993481905\n1396896000,44.190248905009526\n1396896300,45.72483995979999\n1396896600,48.52530752029048\n1396896900,46.98359701868095\n1396897200,35.20031682647142\n1396897500,36.391051872361906\n1396897800,35.815722120452385\n1396898100,37.054137304442854\n1396898400,38.52158987753332\n1396898700,36.70524936032381\n1396899000,36.69958536931429\n1396899300,38.82162547590475\n1396899600,37.35440463859524\n1396899900,37.317070540785714\n1396900200,35.961331335776194\n1396900500,37.518013321666665\n1396900800,35.43378616795714\n1396901100,34.707801000847624\n1396901400,37.14762686323809\n1396901700,36.70940369932857\n1396902000,36.174924233719054\n1396902300,35.31302680630952\n1396902600,35.0120967047\n1396902900,33.884279976790474\n1396903200,34.38668140978095\n1396903500,36.31196460547143\n1396903800,35.0078173765619\n1396904100,36.77047805625239\n1396904400,33.413027250642855\n1396904700,34.869131932433326\n1396905000,35.43370823612381\n1396905300,34.91818155201429\n1396905600,36.422285431604756\n1396905900,36.832997926495246\n1396906200,33.328748327685716\n1396906500,33.392940895476194\n1396906800,33.401865298366666\n1396907100,35.62329407645714\n1396907400,34.39080733414762\n1396907700,35.84772633033809\n1396908000,34.46215146382857\n1396908300,35.358985932719044\n1396908600,35.93597779090953\n1396908900,35.0559987818\n1396909200,35.028556521890465\n1396909500,33.22918706428095\n1396909800,34.52805579247143\n1396910100,35.07599629196191\n1396910400,34.74792968025238\n1396910700,36.51225985014286\n1396911000,36.54271692883333\n1396911300,36.21137948412381\n1396911600,34.41565081421429\n1396911900,35.79135825230476\n1396912200,34.51050866199524\n1396912500,33.86704474018571\n1396912800,34.31580611197619\n1396913100,33.235285698866676\n1396913400,34.28617798205714\n1396913700,34.80957633614762\n1396914000,36.796351481538096\n1396914300,34.23501761372857\n1396914600,36.59908228661905\n1396914900,33.91162438840952\n1396915200,33.763875591\n1396915500,35.083422301890465\n1396915800,35.70492642958096\n1396916100,33.19965043177143\n1396916400,33.9140253649619\n1396916700,34.85993704695238\n1396917000,34.36866020104286\n1396917300,35.902567650733324\n1396917600,35.104166193723806\n1396917900,33.70840070811428\n1396918200,36.65226627920476\n1396918500,34.25346793999524\n1396918800,36.01381015018571\n1396919100,36.2163893068762\n1396919400,36.956797467666675\n1396919700,35.105637008957146\n1396920000,35.58238968094762\n1396920300,34.465993269138096\n1396920600,35.846645745028574\n1396920900,34.99490299111905\n1396921200,34.899418982709534\n1396921500,36.5781201165\n1396921800,33.364365850190474\n1396922100,36.698980663680956\n1396922400,36.58685077987143\n1396922700,35.21147691896191\n1396923000,35.15426379775238\n1396923300,34.64812232924286\n1396923600,37.185028500033326\n1396923900,33.660451140523804\n1396924200,35.58407522821429\n1396924500,35.95738112230476\n1396924800,36.97541527099524\n1396925100,36.36634970168571\n1396925400,35.82836500167619\n1396925700,33.727665933866675\n1396926000,34.76279121015715\n1396926300,33.83066418924762\n1396926600,36.80758902513809\n1396926900,36.28866319372858\n1396927200,36.32776619481905\n1396927500,35.91408559490952\n1396927800,35.3406741477\n1396928100,33.919824714090474\n1396928400,34.64616049918095\n1396928700,33.88248459847143\n1396929000,36.2419144761619\n1396929300,33.99061748505238\n1396929600,36.16559705784285\n1396929900,36.13360489173333\n1396930200,35.20924172552381\n1396930500,33.92037890221428\n1396930800,34.646108066404764\n1396931100,34.67471767439524\n1396931400,36.203326246885716\n1396931700,33.864198268176196\n1396932000,36.732941251566665\n1396932300,36.468136303557145\n1396932600,34.176775291747624\n1396932900,36.315645622338096\n1396933200,36.120481297328574\n1396933500,36.446352248019046\n1396933800,34.217023745609524\n1396934100,34.0991112886\n1396934400,34.422126419890475\n1396934700,34.94711776498095\n1396935000,36.66573135267143\n1396935300,36.450207654661895\n1396935600,37.20775875005238\n1396935900,33.747911093542854\n1396936200,33.567058457433326\n1396936500,36.32482912832381\n1396936800,34.65286426891429\n1396937100,34.87947034400476\n1396937400,35.737803341795235\n1396937700,33.967688206785716\n1396938000,36.136253856676184\n1396938300,34.87350645156667\n1396938600,36.11121764005714\n1396938900,36.92382527134762\n1396939200,34.279683428538085\n1396939500,37.326170943128574\n1396939800,35.73287161181905\n1396940100,37.30927058450953\n1396940400,34.455920328800005\n1396940700,36.050691134590465\n1396941000,35.25542942168095\n1396941300,36.744210193171426\n1396941600,36.078397677661904\n1396941900,35.640264208752384\n1396942200,37.32158448284286\n1396942500,35.18555159003333\n1396942800,34.564444629123805\n1396943100,36.12436903311429\n1396943400,36.19551851060476\n1396943700,35.463223724395235\n1396944000,35.66072588908571\n1396944300,37.55993984767618\n1396944600,36.659909432266666\n1396944900,34.17901414875714\n1396945200,34.59256790254761\n1396945500,37.653794632938094\n1396945800,36.66479078662857\n1396946100,37.426549552219036\n1396946400,34.98925537980952\n1396946700,36.748717440300005\n1396947000,36.64470131029047\n1396947300,34.97489089418095\n1396947600,84.49467345467144\n1396947900,85.5438574180619\n1396948200,83.56184500825238\n1396948500,88.27552326764288\n1396948800,88.36035230183333\n1396949100,88.60894126642381\n1396949400,87.9747748254143\n1396949700,83.69359005180476\n1396950000,82.25065609289523\n1396950300,88.3772531727857\n1396950600,83.74471602687619\n1396950900,80.43606768796667\n1396951200,93.60682876445713\n1396951500,87.94180685524763\n1396951800,96.4818277893381\n1396952100,90.96867686222856\n1396952400,89.80804359951904\n1396952700,100.6150752654095\n1396953000,97.8346930542\n1396953300,98.00025915849048\n1396953600,95.47254591558097\n1396953900,98.82378344767143\n1396954200,97.58946361246191\n1396954500,95.10767026915238\n1396954800,102.83586534414287\n1396955100,90.60470941313332\n1396955400,102.5685348604238\n1396955700,93.9569368141143\n1396956000,95.98356219390476\n1396956300,89.53939137609524\n1396956600,96.1846544228857\n1396956900,97.32285837207618\n1396957200,103.47711198756669\n1396957500,103.12656724855715\n1396957800,102.99413014904762\n1396958100,93.17275180313808\n1396958400,103.82626023452856\n1396958700,95.27137429261906\n1396959000,101.61293440780952\n1396959300,91.4643161609\n1396959600,96.09840935369049\n1396959900,103.45987705818096\n1396960200,103.16399077657142\n1396960500,98.9637422402619\n1396960800,100.79426350685236\n1396961100,90.87143261024286\n1396961400,99.5921142809333\n1396961700,97.94382016732379\n1396962000,89.6079104991143\n1396962300,89.96098433670475\n1396962600,89.89299669859524\n1396962900,99.7526851408857\n1396963200,90.4400953360762\n1396963500,95.66255691256666\n1396963800,93.89841522675715\n1396964100,97.00146993544763\n1396964400,99.5038690210381\n1396964700,99.16332983242857\n1396965000,96.46417810581906\n1396965300,95.65285445570952\n1396965600,94.6112879996\n1396965900,102.04388170219048\n1396966200,93.55479973618095\n1396966500,92.41851937427143\n1396966800,100.16878293696192\n1396967100,94.03968546975237\n1396967400,101.84251395834286\n1396967700,93.54459501303332\n1396968000,99.5366459091238\n1396968300,89.03521774251429\n1396968600,94.48965873140476\n1396968900,93.81980843679523\n1396969200,101.40532890088569\n1396969500,103.8187729023762\n1396969800,95.72750510236664\n1396970100,101.55816968245712\n1396970400,99.56336416124762\n1396970700,103.85382410733808\n1396971000,101.36084901462856\n1396971300,89.63031500241905\n1396971600,99.81051632180952\n1396971900,96.973471994\n1396972200,88.67597367849045\n1396972500,92.44140849028095\n1396972800,103.17648879267144\n1396973100,103.25282718076191\n1396973400,101.22489696345238\n1396973700,104.15919810934284\n1396974000,101.36289391023331\n1396974300,88.6289022526238\n1396974600,93.07841664831429\n1396974900,88.97050249690477\n1396975200,89.99368160689524\n1396975500,91.9968438226857\n1396975800,96.5597592223762\n1396976100,102.07076444586669\n1396976400,102.30929229745712\n1396976700,98.38449592204763\n1396977000,103.38351976953811\n1396977300,96.54114507652857\n1396977600,102.77216264351904\n1396977900,95.82007318730952\n1396978200,92.9980707675\n1396978500,103.2325138873905\n1396978800,94.78431213178095\n1396979100,96.63925642917143\n1396979400,93.85400235676191\n1396979700,99.20507226515238\n1396980000,51.77533594484285\n1396980300,45.577864485133325\n1396980600,51.18104441262381\n1396980900,45.45458551601429\n1396981200,47.767957224104755\n1396981500,46.52342306159524\n1396981800,50.29876665038572\n1396982100,45.78312997957619\n1396982400,49.00896415986666\n1396982700,47.36162850745714\n1396983000,46.337031517947615\n1396983300,50.428618174638096\n1396983600,37.83045482952857\n1396983900,37.86593283671905\n1396984200,38.103652347709534\n1396984500,39.5074638518\n1396984800,39.84149258209048\n1396985100,36.97248914828096\n1396985400,37.98464623297143\n1396985700,38.839260067361906\n1396986000,38.40320793915238\n1396986300,40.88447608404286\n1396986600,40.459767148233325\n1396986900,39.74226071542381\n1396987200,36.60233578381428\n1396987500,38.09510843080476\n1396987800,38.68813627609524\n1396988100,37.676460689485715\n1396988400,38.460630099176186\n1396988700,38.323250330566665\n1396989000,37.60419292005715\n1396989300,36.548499838647615\n1396989600,38.3319615565381\n1396989900,36.131716256728566\n1396990200,38.484903055319045\n1396990500,38.59498251410953\n1396990800,38.2657646477\n1396991100,36.869584297890476\n1396991400,35.74989960808095\n1396991700,35.38453047677143\n1396992000,37.978879391161904\n1396992300,38.56066408475238\n1396992600,37.62189233834286\n1396992900,35.592891402433345\n1396993200,38.77845956202381\n1396993500,39.00376304861429\n1396993800,36.77764002250476\n1396994100,37.43396699069524\n1396994400,38.09346434138571\n1396994700,37.93739307717619\n1396995000,38.871311726466665\n1396995300,35.46386064915714\n1396995600,37.336457057147605\n1396995900,37.78915078033809\n1396996200,38.59002023552857\n1396996500,38.53344412891904\n1396996800,38.95684420650952\n1396997100,37.098810187199994\n1396997400,38.382204054690476\n1396997700,36.77417853698096\n1396998000,36.74660727507143\n1396998300,36.078055932361906\n1396998600,38.345485933152375\n1396998900,39.023366384242856\n1396999200,36.112353115333335\n1396999500,35.31879926892381\n1396999800,38.36446636991428\n1397000100,37.59050730670476\n1397000400,38.956083486795244\n1397000700,36.133142308485716\n1397001000,35.415597369876195\n1397001300,37.109019903866674\n1397001600,35.484721234757146\n1397001900,36.19745762344762\n1397002200,35.66164953853809\n1397002500,36.06170729002857\n1397002800,35.597197658919036\n1397003100,38.99568352150953\n1397003400,36.3017508538\n1397003700,36.970530820190476\n1397004000,38.79682818288096\n1397004300,37.91910778037143\n1397004600,37.6894118269619\n1397004900,38.04695514235238\n1397005200,38.54743188554285\n1397005500,38.75026040473333\n1397005800,37.81758249222381\n1397006100,38.814493384514286\n1397006400,37.40349487160477\n1397006700,36.37850866319523\n1397007000,38.79709254978572\n1397007300,37.450117500176184\n1397007600,38.91621701696667\n1397007900,35.45977839865714\n1397008200,36.89661062524762\n1397008500,39.1052081686381\n1397008800,36.32002894242856\n1397009100,39.09501403181905\n1397009400,39.15191936830952\n1397009700,38.8723192569\n1397010000,37.605862656590475\n1397010300,37.94638874868095\n1397010600,38.84453942237143\n1397010900,38.477100234361906\n1397011200,37.901327778752375\n1397011500,39.31743048864285\n1397011800,38.138539878633324\n1397012100,39.30520177932381\n1397012400,35.64026818411428\n1397012700,35.973996244904754\n1397013000,37.23143062209524\n1397013300,36.97255355778572\n1397013600,38.571415555876186\n1397013900,36.090372772566674\n1397014200,39.35973785925714\n1397014500,36.72306112004762\n1397014800,37.185932926238095\n1397015100,36.576658701228574\n1397015400,37.80257351691905\n1397015700,35.72707432550953\n1397016000,36.0987100223\n1397016300,38.49063128989047\n1397016600,36.26088328598095\n1397016900,36.46437923477143\n1397017200,38.70169084766191\n1397017500,35.91040709435239\n1397017800,37.29453814824286\n1397018100,35.64433688133333\n1397018400,36.94675340682381\n1397018700,38.36288989611428\n1397019000,35.93481788080476\n1397019300,39.13518374519524\n1397019600,39.2272818860857\n1397019900,36.016687690976184\n1397020200,39.567096412166656\n1397020500,36.80172535645714\n1397020800,35.95545430354762\n1397021100,35.64675655323809\n1397021400,37.26802015452857\n1397021700,38.16060899041904\n1397022000,36.97752652340952\n1397022300,39.0031194619\n1397022600,38.530115578490474\n1397022900,37.07177708028095\n1397023200,38.61581009497143\n1397023500,39.4479628526619\n1397023800,36.06583637515238\n1397024100,36.92530869774286\n1397024400,37.561637089833326\n1397024700,37.70773432052381\n1397025000,37.89199686521428\n1397025300,36.933162388104755\n1397025600,38.407133821995245\n1397025900,38.32587372838572\n1397026200,38.064262215576186\n1397026500,36.215463553466655\n1397026800,37.67572870725714\n1397027100,37.20020516904762\n1397027400,37.746891974638096\n1397027700,39.47764431352857\n1397028000,37.71974442021904\n1397028300,35.86098269120952\n1397028600,37.5678469523\n1397028900,39.102533196390475\n1397029200,38.94762464528095\n1397029500,37.888381722671426\n1397029800,36.8413379561619\n1397030100,37.71005703265238\n1397030400,38.11195173484286\n1397030700,39.86406908643333\n1397031000,38.44873617022381\n1397031300,38.65652400601428\n1397031600,37.85272133620476\n1397031900,37.31230344119524\n1397032200,39.153597648885714\n1397032500,37.88895548787619\n1397032800,39.89542718656666\n1397033100,37.75258943995714\n1397033400,36.20354875364762\n1397033700,38.669300643638095\n1397034000,79.78075230402858\n1397034300,82.56069076521905\n1397034600,83.97214976160951\n1397034900,89.22572676450001\n1397035200,85.89779907529045\n1397035500,79.57321561818095\n1397035800,87.58022940597141\n1397036100,84.79404473376191\n1397036400,91.74290171655237\n1397036700,86.00744028864284\n1397037000,88.86289531813334\n1397037300,82.20488530522381\n1397037600,99.68602400721429\n1397037900,99.07238118060476\n1397038200,101.92194335469524\n1397038500,88.42294759378571\n1397038800,94.85068701747619\n1397039100,98.4534085171667\n1397039400,89.39730087205713\n1397039700,94.30037274124763\n1397040000,102.55735337483809\n1397040300,94.70838187002855\n1397040600,103.24360128721905\n1397040900,88.83970175180951\n1397041200,101.1093647597\n1397041500,98.94092269749045\n1397041800,97.66846397748094\n1397042100,105.15567850177143\n1397042400,91.78472187416192\n1397042700,103.98016970845238\n1397043000,100.73113035584285\n1397043300,93.86415688313332\n1397043600,104.09266990162381\n1397043900,96.5874706594143\n1397044200,102.71687618760477\n1397044500,95.95890120519523\n1397044800,103.7264410812857\n1397045100,100.30916880647621\n1397045400,92.39680470866665\n1397045700,100.53234422565714\n1397046000,93.21549000284763\n1397046300,96.74794122713809\n1397046600,92.89398824422855\n1397046900,90.53180418891905\n1397047200,93.57352593340951\n1397047500,98.7665040367\n1397047800,97.89801999009049\n1397048100,98.22405573668095\n1397048400,94.24833036607143\n1397048700,101.25368009556192\n1397049000,101.5666805990524\n1397049300,96.03472346964287\n1397049600,104.41139105573332\n1397049900,100.6253922265238\n1397050200,101.73682461901429\n1397050500,94.77474846360478\n1397050800,90.35559905189524\n1397051100,104.19594246558573\n1397051400,103.5163282340762\n1397051700,92.33873381846666\n1397052000,96.37479598945716\n1397052300,100.97776264464764\n1397052600,100.83755498963808\n1397052900,104.17666717932858\n1397053200,92.66334590781904\n1397053500,97.30530929460951\n1397053800,91.9895600185\n1397054100,96.67470924209049\n1397054400,90.69063247928095\n1397054700,104.82804459657143\n1397055000,98.89610508426192\n1397055300,104.0674299056524\n1397055600,91.43991767184286\n1397055900,94.12818696333332\n1397056200,94.6463726923238\n1397056500,96.69077760411429\n1397056800,103.35695220000477\n1397057100,96.70352064249523\n1397057400,93.8005195538857\n1397057700,91.5733691733762\n1397058000,91.81283123036668\n1397058300,102.70905449495714\n1397058600,97.67263595384762\n1397058900,102.18208330583806\n1397059200,101.48786331982859\n1397059500,92.74452603741905\n1397059800,92.87237384140951\n1397060100,102.67906080280001\n1397060400,102.14132277459045\n1397060700,96.65697336928095\n1397061000,91.85468702347143\n1397061300,90.81694164026192\n1397061600,95.24131648015238\n1397061900,90.78581071124286\n1397062200,94.32684996313331\n1397062500,97.3651345258238\n1397062800,92.60333813671429\n1397063100,92.33657059850478\n1397063400,105.01856105389523\n1397063700,100.0505249334857\n1397064000,105.6417337893762\n1397064300,96.23110551446665\n1397064600,101.53964433175716\n1397064900,93.98783550734764\n1397065200,100.61365172463807\n1397065500,92.80102180742857\n1397065800,90.76838161361906\n1397066100,105.64703497500952\n1397066400,51.1013177961\n1397066700,53.489854049390466\n1397067000,49.70139676428096\n1397067300,49.67014633887143\n1397067600,50.143947894161904\n1397067900,52.10585828105238\n1397068200,51.21581189104286\n1397068500,53.52434807213334\n1397068800,47.77234001592382\n1397069100,52.14941188891429\n1397069400,49.73849603830476\n1397069700,48.785334858695244\n1397070000,41.28585687178571\n1397070300,41.269410713576185\n1397070600,39.62797493556668\n1397070900,39.926100318757136\n1397071200,40.857624111547615\n1397071500,40.8679620163381\n1397071800,40.46658785292857\n1397072100,39.71685018391905\n1397072400,39.078402499209524\n1397072700,43.4129017353\n1397073000,43.300565687490476\n1397073300,41.24788342628095\n1397073600,41.43630313987143\n1397073900,40.127299789361906\n1397074200,37.65749263045239\n1397074500,37.86506637364286\n1397074800,41.142723083633335\n1397075100,39.97846737742381\n1397075400,40.85889415791428\n1397075700,41.09196698150476\n1397076000,39.25486547309524\n1397076300,37.62629778838571\n1397076600,38.206172269076184\n1397076900,37.71509513836666\n1397077200,37.86284028455713\n1397077500,38.76171150874762\n1397077800,37.594194670638096\n1397078100,37.79671279512857\n1397078400,38.925865905519046\n1397078700,38.508674560009524\n1397079000,39.0285114839\n1397079300,38.881268641690475\n1397079600,39.75406698378096\n1397079900,40.93797360997142\n1397080200,37.612190208561906\n1397080500,37.58504872785238\n1397080800,40.538922066442865\n1397081100,39.15939470543333\n1397081400,40.207866888723814\n1397081700,38.00925911101429\n1397082000,40.472817876404754\n1397082300,40.86055929519524\n1397082600,39.713438021185716\n1397082900,37.60042884277619\n1397083200,40.76856384476665\n1397083500,40.36438119475713\n1397083800,40.205222085447616\n1397084100,37.3533218781381\n1397084400,40.39634827362857\n1397084700,37.75923503401905\n1397085000,38.104481019309524\n1397085300,39.531188576999995\n1397085600,38.289773071190474\n1397085900,39.88298769098096\n1397086200,39.67727621547142\n1397086500,37.68464935386191\n1397086800,39.883970516452386\n1397087100,40.96337809164285\n1397087400,37.918852684633336\n1397087700,39.67043643492381\n1397088000,38.65317577341428\n1397088300,39.13160144900476\n1397088600,38.448595954395245\n1397088900,38.724558259685715\n1397089200,37.43112348357619\n1397089500,41.24912361836667\n1397089800,39.82955683115714\n1397090100,39.34061998104762\n1397090400,38.88009949323809\n1397090700,39.510176806728566\n1397091000,38.880543042519044\n1397091300,38.807191233809526\n1397091600,39.2307861669\n1397091900,38.48637261089047\n1397092200,38.110080552280955\n1397092500,39.62374502127143\n1397092800,40.775823649361904\n1397093100,38.02351509185237\n1397093400,37.55058021954286\n1397093700,38.41433031393333\n1397094000,41.353406383323815\n1397094300,40.756996580714286\n1397094600,39.83286897600476\n1397094900,41.17384089909525\n1397095200,39.24540218158571\n1397095500,41.404848600776184\n1397095800,38.664374847166656\n1397096100,38.447830140957144\n1397096400,40.04624042364762\n1397096700,39.01410396703809\n1397097000,40.01439073932857\n1397097300,38.73635112081905\n1397097600,39.99548255120952\n1397097900,38.6342350423\n1397098200,37.74257875149047\n1397098500,41.19467456008096\n1397098800,41.08639223607143\n1397099100,41.444204501861904\n1397099400,40.43456108585239\n1397099700,40.30677756804286\n1397100000,39.81934561363333\n1397100300,38.09454347492381\n1397100600,38.35515552951429\n1397100900,38.76353351660476\n1397101200,41.17372068839524\n1397101500,38.31241381268571\n1397101800,41.31946888847619\n1397102100,39.726559598866665\n1397102400,40.50513568475714\n1397102700,38.091275565747615\n1397103000,38.7338722903381\n1397103300,41.49925300412857\n1397103600,38.73721883531905\n1397103900,38.86614640540952\n1397104200,38.4778895394\n1397104500,38.211235137390474\n1397104800,38.63541151818095\n1397105100,40.27912899637143\n1397105400,39.538732838761895\n1397105700,39.93972572635238\n1397106000,38.221602172242854\n1397106300,40.94804912203333\n1397106600,40.88340261182381\n1397106900,37.840823930314286\n1397107200,39.29596513990476\n1397107500,38.04442764599524\n1397107800,40.94520883198571\n1397108100,40.73330492297619\n1397108400,41.39961904386666\n1397108700,38.744722978657144\n1397109000,39.631731151547605\n1397109300,38.551939603938095\n1397109600,39.30636830932857\n1397109900,39.917842053919045\n1397110200,38.04963268320952\n1397110500,40.7032316427\n1397110800,40.02436391769048\n1397111100,41.17446702118095\n1397111400,38.95319343337143\n1397111700,41.486796325861896\n1397112000,41.87572939305238\n1397112300,41.56558661064285\n1397112600,41.00740323663333\n1397112900,41.152749021023816\n1397113200,40.20569125591429\n1397113500,38.67877021360477\n1397113800,40.63375797869524\n1397114100,40.78404772248571\n1397114400,41.88201675157619\n1397114700,40.11312193166667\n1397115000,39.040833202957145\n1397115300,40.69748770604762\n1397115600,41.887741373938105\n1397115900,38.68653420452857\n1397116200,39.28911072171905\n1397116500,40.16008333890952\n1397116800,38.6808585395\n1397117100,38.09632303429048\n1397117400,39.36281344218095\n1397117700,41.48380463457143\n1397118000,38.20363550206191\n1397118300,39.75291861705238\n1397118600,41.09344594884285\n1397118900,41.86481372093333\n1397119200,42.00142540552381\n1397119500,39.75484180811429\n1397119800,41.87594193940475\n1397120100,38.22352113119524\n1397120400,91.43375607108572\n1397120700,90.03807226147619\n1397121000,84.69766392986666\n1397121300,88.21113875205714\n1397121600,83.08097845254763\n1397121900,93.18020934813808\n1397122200,86.20134253482857\n1397122500,89.85557384591905\n1397122800,83.50816701730953\n1397123100,84.160091887\n1397123400,94.85429711909046\n1397123700,91.61310591678092\n1397124000,104.94837484747144\n1397124300,94.61762198886193\n1397124600,92.58746822605238\n1397124900,97.84851541034287\n1397125200,97.72558507353334\n1397125500,92.77094370302382\n1397125800,101.44278200561428\n1397126100,95.68544209640476\n1397126400,92.97048362209524\n1397126700,95.23791799758571\n1397127000,98.84095920877618\n1397127300,101.37524553406666\n1397127600,99.49984979475714\n1397127900,100.2023603372476\n1397128200,94.06053426043808\n1397128500,106.40542303802856\n1397128800,106.63604869251905\n1397129100,102.74227601780953\n1397129400,92.1609099277\n1397129700,100.42956880589048\n1397130000,101.90247948448095\n1397130300,107.72180219047144\n1397130600,107.75171076016191\n1397130900,105.55715146755236\n1397131200,93.29081317454286\n1397131500,107.51230267913331\n1397131800,102.07644066802382\n1397132100,105.09187558741428\n1397132400,98.80777225420476\n1397132700,97.41651912399523\n1397133000,99.7183977543857\n1397133300,94.6699984073762\n1397133600,98.03646921686666\n1397133900,106.04312088315712\n1397134200,92.95162674984762\n1397134500,94.76373998593807\n1397134800,94.43052667972856\n1397135100,98.88424992071907\n1397135400,108.3919915084095\n1397135700,95.22453118889999\n1397136000,94.78607421639047\n1397136300,107.10372881478096\n1397136600,106.58321262607143\n1397136900,92.9969540216619\n1397137200,104.51308119295237\n1397137500,102.98104709244285\n1397137800,104.78445816623329\n1397138100,100.42113419682379\n1397138400,108.3935644016143\n1397138700,93.24121738680478\n1397139000,96.29690462319523\n1397139300,98.8990109585857\n1397139600,99.7581218260762\n1397139900,107.31063149966668\n1397140200,101.53654088475712\n1397140500,93.30608290214762\n1397140800,99.11727627133808\n1397141100,99.26274930472856\n1397141400,108.05377656561905\n1397141700,102.20079679680953\n1397142000,102.7946283025\n1397142300,104.04368822059048\n1397142600,104.95970052528095\n1397142900,102.80734980797142\n1397143200,96.44914388986193\n1397143500,106.64611155695238\n1397143800,104.38275601014288\n1397144100,104.54620594353334\n1397144400,108.6285873661238\n1397144700,105.5315743754143\n1397145000,105.96500865470476\n1397145300,107.92849615359523\n1397145600,95.13228682898571\n1397145900,100.68521068397621\n1397146200,102.01808296906664\n1397146500,98.00487045505714\n1397146800,106.17433709484762\n1397147100,104.95004038003809\n1397147400,104.29289737802857\n1397147700,108.72059121131906\n1397148000,96.92376529010951\n1397148300,104.5484051936\n1397148600,101.61100689549049\n1397148900,97.80381001728097\n1397149200,95.37293272547144\n1397149500,107.14512014556192\n1397149800,102.34570879775238\n1397150100,106.02480154304287\n1397150400,101.55882207873331\n1397150700,96.36037810042382\n1397151000,98.24896557341428\n1397151300,98.96024624930477\n1397151600,108.43001861239523\n1397151900,92.96064048578569\n1397152200,108.6485988549762\n1397152500,108.57276915646663\n1397152800,56.06821544855714\n1397153100,52.75045584894761\n1397153400,55.8761087868381\n1397153700,52.247007319528564\n1397154000,49.89089790601905\n1397154300,51.165875711309525\n1397154600,55.787389276400006\n1397154900,49.83302896699047\n1397155200,53.246737218580954\n1397155500,50.24366597497142\n1397155800,51.600194125161906\n1397156100,50.33849098765238\n1397156400,44.99282976254285\n1397156700,43.797578861333335\n1397157000,45.198459448323796\n1397157300,44.24828534461429\n1397157600,45.52211392530477\n1397157900,43.463595900195244\n1397158200,44.04820785768571\n1397158500,43.77608845597619\n1397158800,43.371152165666665\n1397159100,44.999003786157154\n1397159400,44.104018962547606\n1397159700,44.81386573893809\n1397160000,42.72437499592857\n1397160300,40.29338979511905\n1397160600,42.18137909990953\n1397160900,40.3435080556\n1397161200,41.92247090519048\n1397161500,42.31540316538096\n1397161800,43.63274601157143\n1397162100,39.680611624561905\n1397162400,39.93668100155238\n1397162700,39.88589398054286\n1397163000,41.209520921133326\n1397163300,42.95049947662381\n1397163600,42.63954544591428\n1397163900,42.21662310150476\n1397164200,42.86672821459524\n1397164500,40.56707435448571\n1397164800,39.63118729157618\n1397165100,39.518045271966656\n1397165400,42.71664891695714\n1397165700,42.23496712184762\n1397166000,42.114512682038104\n1397166300,40.67930566372857\n1397166600,40.84843393371905\n1397166900,43.17980936550953\n1397167200,39.5227439776\n1397167500,42.372618543490475\n1397167800,40.52188322968095\n1397168100,39.445969863071426\n1397168400,42.270173806661894\n1397168700,40.629400615852376\n1397169000,42.203285968342854\n1397169300,42.152698248433325\n1397169600,41.468004882923815\n1397169900,42.44672190501429\n1397170200,41.66806923580477\n1397170500,40.49677332559524\n1397170800,42.27976671708571\n1397171100,41.70719391137619\n1397171400,39.40854156616666\n1397171700,42.97233231455714\n1397172000,41.55549714464762\n1397172300,42.855120260738104\n1397172600,42.91900986712857\n1397172900,41.175033407019036\n1397173200,41.43329539050953\n1397173500,41.0730428481\n1397173800,41.21523874289048\n1397174100,43.00586305918095\n1397174400,42.58114748447143\n1397174700,39.94211461006191\n1397175000,41.88468350715237\n1397175300,43.43451941864286\n1397175600,41.840536138233325\n1397175900,42.60926031192381\n1397176200,42.54946017921428\n1397176500,40.881924865404756\n1397176800,40.97549244889524\n1397177100,42.39184140148571\n1397177400,41.50291031687619\n1397177700,41.792699503166666\n1397178000,42.36948030435714\n1397178300,42.635597727247614\n1397178600,40.618804406138096\n1397178900,40.12735360912857\n1397179200,40.71479763451904\n1397179500,41.58521282420952\n1397179800,40.931065269200005\n1397180100,41.843391511590475\n1397180400,39.79124384888095\n1397180700,41.62382307507143\n1397181000,41.06420153256191\n1397181300,41.73836940055238\n1397181600,41.29727627664286\n1397181900,40.75148673593333\n1397182200,43.23845543132379\n1397182500,40.36852423941429\n1397182800,42.36236706420476\n1397183100,43.34292408839524\n1397183400,41.80646555298571\n1397183700,43.16486014477619\n1397184000,40.16607258036665\n1397184300,41.64926222385714\n1397184600,41.50964874094762\n1397184900,39.72146332333811\n1397185200,41.46945793682857\n1397185500,41.17998807311905\n1397185800,42.39050443490952\n1397186100,43.472069114300005\n1397186400,40.069354829190466\n1397186700,41.04353649928096\n1397187000,41.51733037817142\n1397187300,41.569253416861905\n1397187600,42.855191264352385\n1397187900,41.53697552044286\n1397188200,39.87947853913333\n1397188500,42.61869018792381\n1397188800,43.325033066314276\n1397189100,41.84877361210476\n1397189400,42.125029324895245\n1397189700,40.45978147018571\n1397190000,40.698059969176185\n1397190300,40.76359762316665\n1397190600,41.55332504235715\n1397190900,43.55037850264762\n1397191200,41.932377162138096\n1397191500,40.62106915222857\n1397191800,40.92446999111905\n1397192100,41.40361964270952\n1397192400,42.3680359028\n1397192700,41.642573088190474\n1397193000,41.45966032908096\n1397193300,42.156235830171426\n1397193600,40.87210188456189\n1397193900,40.227815471252384\n1397194200,40.017300116442854\n1397194500,40.932119987233335\n1397194800,40.30089194612381\n1397195100,41.28732683981429\n1397195400,43.04113892330476\n1397195700,42.822022559995226\n1397196000,42.40799620548571\n1397196300,43.38172716597619\n1397196600,41.107437164866674\n1397196900,43.52682215495715\n1397197200,41.59100429774762\n1397197500,41.605061368338106\n1397197800,41.63033502592858\n1397198100,40.40874651261905\n1397198400,43.925771517109524\n1397198700,40.5852771113\n1397199000,41.402233374090464\n1397199300,41.32333223368096\n1397199600,40.35228915987143\n1397199900,40.670052425161906\n1397200200,40.24788572565239\n1397200500,41.24551083134285\n1397200800,43.54996102943333\n1397201100,41.44854263242381\n1397201400,40.592981614014285\n1397201700,42.68843023540476\n1397202000,44.099498886295244\n1397202300,41.04983087238571\n1397202600,41.24626021197619\n1397202900,44.02280488376667\n1397203200,40.85796229305714\n1397203500,42.19515388884762\n1397203800,41.116346627338096\n1397204100,43.89458616302856\n1397204400,44.098703105919036\n1397204700,43.438850908309526\n1397205000,41.446635263299996\n1397205300,41.808890377290474\n1397205600,41.17160368708095\n1397205900,43.77285329657143\n1397206200,43.875495015561896\n1397206500,41.90018502995238\n1397206800,150.11416299114285\n1397207100,137.94530219133333\n1397207400,144.6334341385238\n1397207700,149.51564213171432\n1397208000,143.41990210090475\n1397208300,142.73781347509527\n1397208600,133.90156072228572\n1397208900,153.8307040924762\n1397209200,155.94723944466662\n1397209500,157.94180267585713\n1397209800,151.74447796904758\n1397210100,147.5240374422381\n1397210400,160.4399082654286\n1397210700,181.58858187161903\n1397211000,169.73555219080953\n1397211300,172.389971935\n1397211600,172.43367292619044\n1397211900,177.15712295738098\n1397212200,152.9661881535714\n1397212500,159.0718632997619\n1397212800,171.97481702595238\n1397213100,178.63181339514287\n1397213400,172.5632444573333\n1397213700,164.69798161152383\n1397214000,167.24617561871426\n1397214300,178.46710182490474\n1397214600,178.57254871109524\n1397214900,174.58250742728572\n1397215200,165.1878617724762\n1397215500,184.07412901666663\n1397215800,172.9609643788571\n1397216100,180.07714589604763\n1397216400,162.9189098412381\n1397216700,166.79134174542855\n1397217000,182.60459199961903\n1397217300,158.04934815980948\n1397217600,172.660947021\n1397217900,171.7513659231905\n1397218200,179.83333544338097\n1397218500,165.7802077655714\n1397218800,163.9054533807619\n1397219100,185.0954604179524\n1397219400,174.48494929414287\n1397219700,160.50121529533334\n1397220000,163.15537837152382\n1397220300,187.30299490671428\n1397220600,163.24733731490474\n1397220900,175.68351479709526\n1397221200,170.15219261828568\n1397221500,184.11989085147619\n1397221800,180.21550143266663\n1397222100,175.47774239485713\n1397222400,157.90368772504763\n1397222700,183.9755844242381\n1397223000,170.93281306342857\n1397223300,185.54350791161903\n1397223600,172.47341702480952\n1397223900,178.439768728\n1397224200,159.70445344519047\n1397224500,179.98204089638097\n1397224800,167.81040194257142\n1397225100,168.2187096737619\n1397225400,161.24544227895237\n1397225700,162.09887494614287\n1397226000,163.27330791633332\n1397226300,167.5539247315238\n1397226600,184.47333943071428\n1397226900,168.77036112390473\n1397227200,179.46028309509526\n1397227500,160.22033513928568\n1397227800,175.47746858047614\n1397228100,172.20886373766666\n1397228400,187.10477248685714\n1397228700,183.15975149704758\n1397229000,171.4259823012381\n1397229300,181.04270592542855\n1397229600,163.58721944361903\n1397229900,174.67346459980953\n1397230200,160.04954923399998\n1397230500,168.26099800019045\n1397230800,164.60167363438097\n1397231100,179.40037903557143\n1397231400,172.5433219387619\n1397231700,180.3800691899524\n1397232000,173.3156721681429\n1397232300,160.45881132133334\n1397232600,179.9327048355238\n1397232900,182.87598722571425\n1397233200,184.99248187990474\n1397233500,175.05376600509524\n1397233800,180.50899680528573\n1397234100,180.4702067204762\n1397234400,162.58884957366664\n1397234700,162.85041731585713\n1397235000,160.0578085550476\n1397235300,167.5360763362381\n1397235600,172.15161999642856\n1397235900,187.89073144261903\n1397236200,170.89104414480948\n1397236500,179.755958083\n1397236800,178.77803213019047\n1397237100,164.11802683438097\n1397237400,159.7462252895714\n1397237700,174.3786472787619\n1397238000,179.01505092395237\n1397238300,187.96087337014285\n1397238600,168.77910022433338\n1397238900,184.9191388355238\n1397239200,67.94947988201429\n1397239500,70.78572866320476\n1397239800,69.95450862529523\n1397240100,64.94542849078572\n1397240400,65.18663752907621\n1397240700,64.66393425606668\n1397241000,67.89201775305715\n1397241300,71.34915330124763\n1397241600,66.0845752792381\n1397241900,70.07651228672856\n1397242200,67.16732187411904\n1397242500,71.84987756170952\n1397242800,49.8289137697\n1397243100,49.720526822590465\n1397243400,48.465039186280954\n1397243700,47.261535099671434\n1397244000,49.9143570587619\n1397244300,46.78014671785238\n1397244600,47.31002870094285\n1397244900,46.78417727823333\n1397245200,49.262540262723796\n1397245500,49.330591105814285\n1397245800,49.16805238190476\n1397246100,47.98147401359524\n1397246400,42.571804822685706\n1397246700,45.99192722587619\n1397247000,44.30169802996666\n1397247300,43.88514561645714\n1397247600,44.65782222784762\n1397247900,42.9987497494381\n1397248200,42.752693340528566\n1397248500,43.90881865711904\n1397248800,43.16595370110952\n1397249100,43.245223054200004\n1397249400,45.980378242490474\n1397249700,44.46556503418097\n1397250000,43.44475989277142\n1397250300,44.28481252026191\n1397250600,45.35142912105238\n1397250900,41.96655447704285\n1397251200,44.889346526133345\n1397251500,43.88834561862381\n1397251800,42.12615608071428\n1397252100,42.74381334610476\n1397252400,43.49980703279524\n1397252700,44.35119715128572\n1397253000,42.54569660917619\n1397253300,43.734382780066674\n1397253600,44.17468009835714\n1397253900,43.23643412444761\n1397254200,44.904462292838105\n1397254500,44.93768885962857\n1397254800,43.34674004791904\n1397255100,45.36729708400952\n1397255400,41.7779092181\n1397255700,41.495857945290474\n1397256000,43.01566114678096\n1397256300,43.90665077987143\n1397256600,44.026737458061895\n1397256900,43.421889333452384\n1397257200,41.98937191204285\n1397257500,42.17934512433333\n1397257800,44.914521714623795\n1397258100,44.98504101221428\n1397258400,44.216108276104755\n1397258700,44.18481038149525\n1397259000,43.925996765085706\n1397259300,42.35375539797619\n1397259600,43.262870072666665\n1397259900,44.34133171295714\n1397260200,43.71393869054762\n1397260500,41.645828345238094\n1397260800,45.38565579832857\n1397261100,44.95813325791904\n1397261400,42.628489580209525\n1397261700,44.059585740699994\n1397262000,45.29414801109047\n1397262300,41.99267500088095\n1397262600,43.62818935177143\n1397262900,43.448484008161905\n1397263200,43.271772402052385\n1397263500,44.980747292742855\n1397263800,43.168417920133344\n1397264100,41.907927142523796\n1397264400,41.924065254414295\n1397264700,41.83913318800476\n1397265000,43.312176925595246\n1397265300,44.55666082508571\n1397265600,42.50536603817619\n1397265900,44.28379074836667\n1397266200,44.45371103125714\n1397266500,42.733606115147616\n1397266800,44.122468719438096\n1397267100,44.46715193152857\n1397267400,43.601573538819046\n1397267700,43.089425912909526\n1397268000,44.22660620630001\n1397268300,45.668828825490465\n1397268600,43.47224658988095\n1397268900,43.33926181367143\n1397269200,43.63682951446191\n1397269500,42.09207595475238\n1397269800,44.00729597584285\n1397270100,43.116872882233345\n1397270400,42.29521229882381\n1397270700,43.68199125021428\n1397271000,41.837940708204755\n1397271300,43.43898621879524\n1397271600,42.26222678598572\n1397271900,41.943897004076184\n1397272200,45.15206685166666\n1397272500,45.52660235595714\n1397272800,42.69974621244762\n1397273100,44.033681150538094\n1397273400,42.99576119992857\n1397273700,43.86567880231905\n1397274000,43.64533480740953\n1397274300,42.9824542203\n1397274600,44.71526479469047\n1397274900,42.42709478968095\n1397275200,42.140862557271426\n1397275500,45.006713636861896\n1397275800,44.607172505852375\n1397276100,43.94499735374285\n1397276400,43.829492415233325\n1397276700,43.95541932752381\n1397277000,43.721310590114285\n1397277300,43.55222394520475\n1397277600,43.986857649595244\n1397277900,44.10959639888571\n1397278200,44.7705854467762\n1397278500,44.85524530956667\n1397278800,43.528373463457136\n1397279100,43.67945971004762\n1397279400,43.527526774138096\n1397279700,44.186321665928574\n1397280000,43.861033199319046\n1397280300,45.61344537630952\n1397280600,44.8479450677\n1397280900,45.66456601119047\n1397281200,44.91392891858095\n1397281500,45.968790022671435\n1397281800,44.63520901776191\n1397282100,45.95390293365238\n1397282400,42.739822418742854\n1397282700,42.32449405663333\n1397283000,44.43852455032381\n1397283300,46.063437108914286\n1397283600,43.807325751104756\n1397283900,42.992518686895245\n1397284200,44.23795151108571\n1397284500,44.754420688776186\n1397284800,43.42738144876667\n1397285100,45.03318457685714\n1397285400,46.08200564724762\n1397285700,45.7768405820381\n1397286000,43.36277006542857\n1397286300,43.51076378021905\n1397286600,43.69747442160953\n1397286900,43.7969611136\n1397287200,42.62746847299047\n1397287500,45.28148230798096\n1397287800,43.70242848297143\n1397288100,45.76779181156191\n1397288400,45.96371487345239\n1397288700,42.361118094342864\n1397289000,46.22484561303333\n1397289300,45.11836473552381\n1397289600,44.367283189714286\n1397289900,43.85126519540476\n1397290200,44.37466776849524\n1397290500,43.60653461018571\n1397290800,44.806227445276186\n1397291100,42.694837772466656\n1397291400,44.81484755445715\n1397291700,43.439177019647616\n1397292000,42.41577741143809\n1397292300,44.56350163612857\n1397292600,44.67391007101905\n1397292900,44.07383554260952\n1397293200,86.5580927627\n1397293500,97.73190463429049\n1397293800,93.90533993068097\n1397294100,87.17102230267143\n1397294400,92.55341774646193\n1397294700,92.37486107785236\n1397295000,86.44110827274288\n1397295300,93.88037530233332\n1397295600,96.6277628348238\n1397295900,95.82847382351429\n1397296200,88.40978879450476\n1397296500,97.38402363999523\n1397296800,99.62054012528571\n1397297100,109.00153622157619\n1397297400,95.4326950714667\n1397297700,101.87256598865713\n1397298000,103.60141795284764\n1397298300,98.18501762353809\n1397298600,106.32074910032856\n1397298900,104.08578999831906\n1397299200,94.64486799050951\n1397299500,103.81313052760001\n1397299800,102.00643267439048\n1397300100,97.42850416278095\n1397300400,111.95795123177143\n1397300700,110.39747945126189\n1397301000,100.78849476265238\n1397301300,104.74908478154283\n1397301600,101.18498336643331\n1397301900,108.49225824352379\n1397302200,110.96220539931429\n1397302500,101.88046492630475\n1397302800,108.99310713649523\n1397303100,104.1152092735857\n1397303400,102.50316162957618\n1397303700,111.12807780246666\n1397304000,104.71313239235714\n1397304300,104.03349134154762\n1397304600,107.31737778613814\n1397304900,100.75351009102856\n1397305200,101.77666895711904\n1397305500,111.48849762360952\n1397305800,107.444549754\n1397306100,109.81886340729048\n1397306400,100.94856379748094\n1397306700,105.31362369577144\n1397307000,112.15455136826193\n1397307300,101.73144565055237\n1397307600,99.28187024854284\n1397307900,104.8945176626333\n1397308200,102.93339199612379\n1397308500,99.2898072337143\n1397308800,110.95803484780475\n1397309100,112.59984342709524\n1397309400,105.85463724978571\n1397309700,109.15879972567622\n1397310000,110.51570187206669\n1397310300,107.99484746825712\n1397310600,97.49559484564762\n1397310900,99.31825048723809\n1397311200,97.95374511012855\n1397311500,96.98347916631904\n1397311800,101.7285610587095\n1397312100,103.1176880383\n1397312400,100.70402508269045\n1397312700,97.88879970538096\n1397313000,105.34001794707144\n1397313300,101.24295511486191\n1397313600,109.61347950225235\n1397313900,97.01377261874285\n1397314200,110.37216309313331\n1397314500,112.17514342182379\n1397314800,108.36807409781427\n1397315100,108.65565591840478\n1397315400,111.86175762859524\n1397315700,100.2774529657857\n1397316000,112.8526813165762\n1397316300,109.32280591396663\n1397316600,108.57968567485712\n1397316900,102.73950021944763\n1397317200,105.7019028303381\n1397317500,107.43957154202856\n1397317800,106.90981834401907\n1397318100,108.27151425380951\n1397318400,98.3179670545\n1397318700,102.69766623599048\n1397319000,103.95872964538096\n1397319300,101.19224394807142\n1397319600,99.79165468596192\n1397319900,99.25989955175238\n1397320200,102.90662763794285\n1397320500,104.94699714383331\n1397320800,98.06700667722382\n1397321100,112.2101264840143\n1397321400,109.31813617940477\n1397321700,108.77531291729522\n1397322000,99.85502540408571\n1397322300,106.75750712087618\n1397322600,105.57973491296669\n1397322900,112.83107499115714\n1397323200,109.08176369864763\n1397323500,106.33864704923808\n1397323800,110.74689835952856\n1397324100,99.62284878051905\n1397324400,97.39224625740951\n1397324700,108.1999514458\n1397325000,98.7366455879905\n1397325300,99.01804083488096\n1397325600,58.74452163307143\n1397325900,55.71742904516191\n1397326200,58.01668585855238\n1397326500,59.87229052724285\n1397326800,56.03376441733332\n1397327100,55.40549062322381\n1397327400,54.70521108111429\n1397327700,54.86560818510476\n1397328000,54.43631488249524\n1397328300,54.60644130148571\n1397328600,56.81779949837619\n1397328900,56.113947030966656\n1397329200,48.593248311457145\n1397329500,49.33397892824761\n1397329800,48.958520746538106\n1397330100,47.827432244928566\n1397330400,45.916558597219044\n1397330700,48.64481567550952\n1397331000,47.0979714917\n1397331300,45.863653113990466\n1397331600,49.261629143680956\n1397331900,47.01003023647142\n1397332200,46.4800155148619\n1397332500,49.41380631035239\n1397332800,47.484282916742856\n1397333100,45.18500764463333\n1397333400,45.257290184323814\n1397333700,46.185622485014285\n1397334000,46.82308086330476\n1397334300,44.08500414479525\n1397334600,46.26412108378572\n1397334900,47.74397689547619\n1397335200,44.92220303546666\n1397335500,47.57866314595714\n1397335800,47.75543687494761\n1397336100,44.9734411742381\n1397336400,46.56411665912857\n1397336700,44.49995351451904\n1397337000,46.51231625350953\n1397337300,46.7601402965\n1397337600,44.55615959389047\n1397337900,46.44725377068095\n1397338200,46.841481938971434\n1397338500,45.02611205976189\n1397338800,44.26638333235237\n1397339100,43.96941680094285\n1397339400,45.91980742663333\n1397339700,47.54584571682382\n1397340000,46.847955684614284\n1397340300,45.30546693210477\n1397340600,45.71641946389524\n1397340900,44.69450063358571\n1397341200,44.23564582367619\n1397341500,45.52037248146666\n1397341800,45.45342324375714\n1397342100,45.69480163144762\n1397342400,47.427395196338104\n1397342700,46.03785871992857\n1397343000,46.052812547919046\n1397343300,44.14743018120953\n1397343600,47.615176766000005\n1397343900,46.727869795990465\n1397344200,47.152824018780954\n1397344500,45.308297256671416\n1397344800,45.66711592036191\n1397345100,45.75439457595239\n1397345400,44.44962607704286\n1397345700,46.43902548423333\n1397346000,47.300580188023794\n1397346300,44.350369282514286\n1397346600,44.048200146504755\n1397346900,46.66374381029524\n1397347200,44.807093040985706\n1397347500,46.21717635697618\n1397347800,46.51220001866666\n1397348100,45.02425019715714\n1397348400,125.74404761904762\n1397348700,45.9514440237381\n1397349000,47.23492620322857\n1397349300,46.81954325781904\n1397349600,47.24811205190952\n1397349900,43.86189552850001\n1397350200,44.76271551919047\n1397350500,44.15616271418096\n1397350800,45.57190349737142\n1397351100,47.3708523912619\n1397351400,45.68861343005239\n1397351700,47.22474503544285\n1397352000,45.14204628543333\n1397352300,45.199054100723814\n1397352600,47.4304612070143\n1397352900,45.55892334790476\n1397353200,47.02215718929524\n1397353500,44.81710990578571\n1397353800,47.67317950917619\n1397354100,46.18372965276666\n1397354400,46.93015141715714\n1397354700,44.25836041824761\n1397355000,45.878394998538106\n1397355300,47.519332562328565\n1397355600,47.430773563819045\n1397355900,44.11731535270953\n1397356200,45.152293876499996\n1397356500,45.718220502090475\n1397356800,44.64144020978095\n1397357100,46.87981467257143\n1397357400,44.705309887161896\n1397357700,45.361261158452386\n1397358000,46.63526540454286\n1397358300,45.917940711433324\n1397358600,46.95130796402381\n1397358900,47.84929589061429\n1397359200,44.47809151280476\n1397359500,46.85761610369524\n1397359800,44.94816233678571\n1397360100,45.69213310007619\n1397360400,44.173117569866655\n1397360700,44.59273667205714\n1397361000,45.33565677524762\n1397361300,45.4319313164381\n1397361600,47.669769437228574\n1397361900,47.046120684719035\n1397362200,47.97504139650953\n1397362500,46.4900360413\n1397362800,45.06804540459047\n1397363100,45.41925107208097\n1397363400,45.39541512177142\n1397363700,45.4294892154619\n1397364000,46.82280907335238\n1397364300,46.26162456954285\n1397364600,45.68753004563332\n1397364900,44.74963288442381\n1397365200,44.249270937514275\n1397365500,45.04349347230475\n1397365800,44.605480853995225\n1397366100,47.32481583768571\n1397366400,44.640468021776186\n1397366700,47.09482961586665\n1397367000,45.74799190195714\n1397367300,44.50631117804762\n1397367600,47.4711582929381\n1397367900,46.54620085232857\n1397368200,45.17816509911904\n1397368500,47.82128422110952\n1397368800,44.431033255500004\n1397369100,45.06471890899047\n1397369400,47.27306866358095\n1397369700,47.10983314977143\n1397370000,45.43684867966191\n1397370300,44.53530188235239\n1397370600,47.726955146042854\n1397370900,45.556873885633344\n1397371200,45.09237746922381\n1397371500,46.381211575114285\n1397371800,47.965313559004755\n1397372100,44.506031549495226\n1397372400,47.40250206638571\n1397372700,46.636619102276185\n1397373000,46.05596313286666\n1397373300,47.337928919257145\n1397373600,48.23234531684762\n1397373900,45.2933129399381\n1397374200,44.95851803172857\n1397374500,48.042896028519046\n1397374800,47.074621833609534\n1397375100,46.1581940862\n1397375400,46.70672875729048\n1397375700,47.40358657308095\n1397376000,47.52069902337143\n1397376300,48.11558862806189\n1397376600,46.15082353655238\n1397376900,45.62453649724286\n1397377200,47.01699040053333\n1397377500,46.128685406623795\n1397377800,46.851608101514294\n1397378100,46.16059795570476\n1397378400,45.100078384795246\n1397378700,46.37324272088571\n1397379000,47.266647478276184\n1397379300,47.707551897366656\n1397379600,94.42709450725714\n1397379900,89.97253292594763\n1397380200,93.37249094643808\n1397380500,98.43377600362857\n1397380800,93.36250512801905\n1397381100,97.22787831680952\n1397381400,94.6606060708\n1397381700,91.05057497769049\n1397382000,98.60502786148096\n1397382300,88.93012440397145\n1397382600,94.9307697502619\n1397382900,90.64062044665238\n1397383200,97.48800141214286\n1397383500,104.2601180368333\n1397383800,104.2152284696238\n1397384100,107.44056627971428\n1397384400,108.03543551810476\n1397384700,107.77966914259524\n1397385000,102.84813724918571\n1397385300,106.3030516882762\n1397385600,105.46085683246667\n1397385900,103.05674559775714\n1397386200,105.79028863284763\n1397386500,111.23027514173809\n1397386800,101.33221067092856\n1397387100,112.67726845901905\n1397387400,99.12946601820951\n1397387700,103.19137204200001\n1397388000,102.87685251009049\n1397388300,108.26334162808097\n1397388600,100.39607306167143\n1397388900,112.34936832346192\n1397389200,111.50123398115238\n1397389500,108.70184765344288\n1397389800,105.62944691413333\n1397390100,113.1840067037238\n1397390400,111.97530882741431\n1397390700,106.68621028040477\n1397391000,109.93069294099523\n1397391300,107.78162989408571\n1397391600,108.1248635136762\n1397391900,104.02577903716669\n1397392200,106.12843879245716\n1397392500,99.99984058024764\n1397392800,104.4695560670381\n1397393100,109.88617490972857\n1397393400,114.00687378791906\n1397393700,114.17169449700951\n1397394000,107.7471519302\n1397394300,108.56878707569048\n1397394600,101.84342675108095\n1397394900,110.00230117497145\n1397395200,100.0177512577619\n1397395500,103.44880016075236\n1397395800,109.59360989844284\n1397396100,103.87357384713331\n1397396400,99.71460238332381\n1397396700,112.23141645291427\n1397397000,103.89621320880477\n1397397300,99.94900651179522\n1397397600,100.15738290898571\n1397397900,102.9962176203762\n1397398200,101.82382910596668\n1397398500,111.37135836485712\n1397398800,104.13728931234762\n1397399100,111.8725466495381\n1397399400,101.78687502282855\n1397399700,106.89860138911905\n1397400000,110.02841924810951\n1397400300,109.45914693290001\n1397400600,108.6528433676905\n1397400900,113.83911032028095\n1397401200,102.70924749037144\n1397401500,106.95975214086191\n1397401800,113.21150620085237\n1397402100,100.32148994214285\n1397402400,99.97684584093334\n1397402700,102.8228833752238\n1397403000,109.22576536621428\n1397403300,103.26299766760476\n1397403600,102.15621295819523\n1397403900,106.46061108798573\n1397404200,108.94475984207621\n1397404500,103.11161060046665\n1397404800,103.95376865315714\n1397405100,108.96708940744763\n1397405400,114.2893855539381\n1397405700,109.96088724232857\n1397406000,111.69892305411905\n1397406300,105.04887153150952\n1397406600,103.54342314649999\n1397406900,106.46307217229048\n1397407200,112.11634317668094\n1397407500,106.51046343967144\n1397407800,112.7647041939619\n1397408100,115.0448854569524\n1397408400,100.38454141834283\n1397408700,99.9661179036333\n1397409000,101.6404304890238\n1397409300,105.40434908791427\n1397409600,101.35855165510478\n1397409900,113.19994388259524\n1397410200,99.64709794048572\n1397410500,104.3368800635762\n1397410800,102.24675195576664\n1397411100,114.20370305395714\n1397411400,110.01821193594763\n1397411700,113.90643894693814\n1397412000,62.344325593028564\n1397412300,59.310291666719046\n1397412600,57.63594599780952\n1397412900,57.383608464000005\n1397413200,57.577865387490476\n1397413500,60.693621720880955\n1397413800,56.42491850927143\n1397414100,56.50221717946189\n1397414400,60.07306093535238\n1397414700,60.29755227774285\n1397415000,60.45350970193333\n1397415300,58.58330305232381\n1397415600,51.18134608321428\n1397415900,49.96879167790476\n1397416200,48.05808012869524\n1397416500,51.164039308085705\n1397416800,51.870218532776185\n1397417100,47.87687822826666\n1397417400,49.36860993815715\n1397417700,49.80686827414762\n1397418000,48.2864259584381\n1397418300,51.52501333832857\n1397418600,48.91810828101905\n1397418900,51.16043648440952\n1397419200,48.6803931442\n1397419500,48.389035914390476\n1397419800,46.73389782998097\n1397420100,46.85832281667143\n1397420400,46.1557007470619\n1397420700,46.955160260352386\n1397421000,47.39157964334285\n1397421300,49.39664623583333\n1397421600,47.4922679332238\n1397421900,49.089894849614275\n1397422200,47.806360103304755\n1397422500,49.22866558429524\n1397422800,49.59951647688571\n1397423100,46.647097334076186\n1397423400,49.15649002076666\n1397423700,48.197242460157135\n1397424000,48.99031666294761\n1397424300,48.3317421030381\n1397424600,47.42426638262857\n1397424900,46.644447797719046\n1397425200,46.016695056509526\n1397425500,47.8950053609\n1397425800,49.730409061390475\n1397426100,48.723868523580954\n1397426400,47.00649059157143\n1397426700,49.015287561061896\n1397427000,48.78962126985238\n1397427300,46.84579750264285\n1397427600,45.782898224433325\n1397427900,46.20615809912381\n1397428200,49.25308789211428\n1397428500,49.097399294704765\n1397428800,46.937344834695246\n1397429100,46.90469256048571\n1397429400,48.94476073007619\n1397429700,49.53224744746666\n1397430000,48.88846054535714\n1397430300,48.201533409547615\n1397430600,46.7570658663381\n1397430900,47.89703000022857\n1397431200,46.735301817219046\n1397431500,49.04118175490952\n1397431800,47.3640975023\n1397432100,49.15882562149048\n1397432400,47.35756689828096\n1397432700,49.13550799397143\n1397433000,47.1792451515619\n1397433300,47.61402721935238\n1397433600,48.31909653454286\n1397433900,46.14573378943334\n1397434200,49.66485205682382\n1397434500,48.17388743021429\n1397434800,47.91818482070475\n1397435100,49.25192112259524\n1397435400,49.364836633885716\n1397435700,47.99826780857618\n1397436000,49.625715969866654\n1397436300,46.183058207157146\n1397436600,46.384450788047616\n1397436900,48.32614101533811\n1397437200,47.36269201862856\n1397437500,47.810769712419045\n1397437800,47.27362639540953\n1397438100,47.5876512458\n1397438400,49.266775864790475\n1397438700,48.35753575178096\n1397439000,49.98044962567143\n1397439300,49.1460286960619\n1397439600,47.10061739735238\n1397439900,47.07077332804285\n1397440200,47.364426413833336\n1397440500,49.401311732123794\n1397440800,46.14486488831429\n1397441100,46.96387987740476\n1397441400,49.67026891949524\n1397441700,48.61762145858572\n1397442000,46.97286457247618\n1397442300,46.94949653956667\n1397442600,49.53082954985714\n1397442900,49.662827652147605\n1397443200,47.11976245903811\n1397443500,47.78472000372857\n1397443800,49.44850200211904\n1397444100,49.20158927820953\n1397444400,49.3806644263\n1397444700,48.20603323939048\n1397445000,49.78607714558096\n1397445300,47.45112760437142\n1397445600,46.78145044216189\n1397445900,48.997131711252386\n1397446200,48.327060521142855\n1397446500,49.59542640853333\n1397446800,46.509160806023814\n1397447100,49.5667338995143\n1397447400,47.37258337470476\n1397447700,48.826267906795245\n1397448000,46.374800870585716\n1397448300,48.66005137567618\n1397448600,49.09825342336665\n1397448900,47.71160800085714\n1397449200,47.10569044004762\n1397449500,48.4020108016381\n1397449800,49.59169178912857\n1397450100,47.56055848081905\n1397450400,47.28368671390952\n1397450700,47.3969912346\n1397451000,50.08521908789047\n1397451300,47.73323861548096\n1397451600,46.317988388171436\n1397451900,49.4377367365619\n1397452200,49.11555156225238\n1397452500,46.84016591554286\n1397452800,50.27295032983334\n1397453100,48.77302295072381\n1397453400,48.35133224951429\n1397453700,47.884531832404754\n1397454000,49.95778626039524\n1397454300,47.34638963998572\n1397454600,47.52105179137619\n1397454900,46.87505989336667\n1397455200,49.42933352515715\n1397455500,48.78249474064762\n1397455800,48.8440027722381\n1397456100,47.28906029552857\n1397456400,49.02729260411904\n1397456700,49.49189331280952\n1397457000,47.869054122899996\n1397457300,49.65032905199048\n1397457600,47.84754330648096\n1397457900,49.49237527457143\n1397458200,46.6021823345619\n1397458500,48.67936078685238\n1397458800,50.36024909974286\n1397459100,50.41456173603334\n1397459400,47.624034122923796\n1397459700,48.27006065001429\n1397460000,46.76381639380476\n1397460300,50.01271046849524\n1397460600,48.80107432688571\n1397460900,48.07462890627619\n1397461200,46.992748900666676\n1397461500,50.33617628485714\n1397461800,48.67742381034761\n1397462100,47.6956998115381\n1397462400,47.972289091928566\n1397462700,47.661657771319035\n1397463000,48.99354875920953\n1397463300,50.31360430310001\n1397463600,50.02796568949047\n1397463900,48.45015445408095\n1397464200,49.92206887777142\n1397464500,48.315933829861905\n1397464800,47.64018094395238\n1397465100,50.57205331824286\n1397465400,47.86138360523333\n1397465700,47.948170733423815\n1397466000,103.32053728761429\n1397466300,91.68956866900477\n1397466600,100.21885747499523\n1397466900,102.61008922968573\n1397467200,96.8508881125762\n1397467500,89.93221262586668\n1397467800,95.00615878275715\n1397468100,91.43013591544762\n1397468400,95.5803902839381\n1397468700,100.67204252972857\n1397469000,95.90159611241906\n1397469300,95.81674117410951\n1397469600,107.2313726818\n1397469900,107.62527835149046\n1397470200,111.89459966498094\n1397470500,103.39799784537144\n1397470800,111.3720999277619\n1397471100,107.41049416065238\n1397471400,103.29886146874284\n1397471700,103.22243953633331\n1397472000,104.25437807502381\n1397472300,108.32116341121427\n1397472600,102.24660283260476\n1397472900,112.95542211529524\n1397473200,109.55069545308572\n1397473500,115.04665710777618\n1397473800,101.16018158546665\n1397474100,105.87849837865713\n1397474400,100.79978065464762\n1397474700,104.77438096253807\n1397475000,114.16127950642857\n1397475300,101.04160996841905\n1397475600,107.40329300090951\n1397475900,102.34403668879999\n1397476200,107.11112432109049\n1397476500,113.83022654848095\n1397476800,110.79934499917142\n1397477100,112.62356770826192\n1397477400,106.43601542915238\n1397477700,115.95672354154287\n1397478000,112.20650900163332\n1397478300,107.6200563807238\n1397478600,107.7020629652143\n1397478900,115.57556287280478\n1397479200,110.11310336299525\n1397479500,112.19764059188572\n1397479800,107.58113270637621\n1397480100,104.49880600186668\n1397480400,112.57474734705713\n1397480700,210.7308639300476\n1397481000,109.0350190253381\n1397481300,111.00483737092856\n1397481600,104.36210860801907\n1397481900,113.7377501037095\n1397482200,116.2121839352\n1397482500,115.30688894679048\n1397482800,106.20183856408094\n1397483100,107.56207473887144\n1397483400,114.00631443666191\n1397483700,110.60201122435238\n1397484000,109.86989715764288\n1397484300,115.93668715283331\n1397484600,109.69455551802382\n1397484900,109.3646316862143\n1397485200,101.80571395190478\n1397485500,102.25150726329522\n1397485800,101.26704894158571\n1397486100,115.76697643147621\n1397486400,107.69708358596668\n1397486700,108.66727330585714\n1397487000,114.70363352334762\n1397487300,110.93300516003806\n1397487600,110.94766929422855\n1397487900,105.94768316961904\n1397488200,114.55302421830952\n1397488500,103.8713129451\n1397488800,102.07588458719047\n1397489100,104.29856404238096\n1397489400,105.52413460457144\n1397489700,105.76475426746191\n1397490000,111.98337576795237\n1397490300,104.74786159654285\n1397490600,112.09657107053332\n1397490900,102.73568338332382\n1397491200,103.64081090121428\n1397491500,109.43414406680478\n1397491800,116.05076151869524\n1397492100,115.06095248938571\n1397492400,116.81536326947617\n1397492700,111.73042348836664\n1397493000,112.14323600445715\n1397493300,111.33800816124763\n1397493600,111.3101834879381\n1397493900,103.70646133292857\n1397494200,110.05978740261904\n1397494500,107.54449635900951\n1397494800,108.4555650855\n1397495100,109.76001878009049\n1397495400,103.44419126438095\n1397495700,107.14909531347143\n1397496000,102.41992684096188\n1397496300,117.08685880065237\n1397496600,103.31606294204286\n1397496900,105.5634499136333\n1397497200,115.69517751272379\n1397497500,109.16529441181429\n1397497800,103.61957150490477\n1397498100,107.60450383799524\n1397498400,59.00583520508571\n1397498700,59.553102796176184\n1397499000,58.61215209356666\n1397499300,61.09125703985714\n1397499600,63.45651227724761\n1397499900,62.05168458923809\n1397500200,62.18953225182857\n1397500500,59.600101064119045\n1397500800,60.52472416840952\n1397501100,63.7407928963\n1397501400,58.90096441829047\n1397501700,63.836880552080956\n1397502000,51.88050152147143\n1397502300,53.4714310854619\n1397502600,51.15311995575238\n1397502900,51.25390809104285\n1397503200,53.11052185283333\n1397503500,53.26755536752381\n1397503800,50.78702128071429\n1397504100,54.12411695210476\n1397504400,50.15160977839524\n1397504700,50.08742786618571\n1397505000,52.45583382267618\n1397505300,53.033294022766675\n1397505600,52.01064645975714\n1397505900,49.74095529614761\n1397506200,48.193331484038104\n1397506500,50.56664172702857\n1397506800,49.291213712519045\n1397507100,49.885410689809525\n1397507400,50.120270754100005\n1397507700,48.39118390539047\n1397508000,50.12496209688095\n1397508300,49.88802654167142\n1397508600,51.0678429591619\n1397508900,50.80134970035238\n1397509200,48.562961825442855\n1397509500,48.65449682713333\n1397509800,48.84226779652381\n1397510100,48.56010184931428\n1397510400,50.489776003304755\n1397510700,51.85255896029523\n1397511000,50.484139505885715\n1397511300,50.30900061077619\n1397511600,49.52564896816666\n1397511900,49.14182967195714\n1397512200,51.55473520964762\n1397512500,51.7950003740381\n1397512800,49.827720884428565\n1397513100,49.008065390119036\n1397513400,50.93703561340952\n1397513700,48.3913657884\n1397514000,50.93376327529048\n1397514300,51.15484920088095\n1397514600,48.383446829171426\n1397514900,51.801988917261895\n1397515200,51.84406589895238\n1397515500,51.656147766542865\n1397515800,49.899157334833326\n1397516100,48.90579529402381\n1397516400,50.24265439041429\n1397516700,49.60166862300476\n1397517000,48.75300398369524\n1397517300,49.63152273428571\n1397517600,50.60000139857618\n1397517900,48.23508036946666\n1397518200,49.292741211757146\n1397518500,48.03744684384762\n1397518800,50.9722517275381\n1397519100,50.54439169072858\n1397519400,48.239311716819046\n1397519700,51.85570667850952\n"
  },
  {
    "path": "workspace/anomaly_detector/datasets/selected/seasonal/art_daily_nojump.csv",
    "content": "timestamp,value\n2014-04-07 01:50:00,19.6866160273\n2014-04-07 01:55:00,19.3563053672\n2014-04-07 02:00:00,20.4140421657\n2014-04-07 02:05:00,18.8776063185\n2014-04-07 02:10:00,18.9195739623\n2014-04-07 02:15:00,20.081154923499998\n2014-04-07 02:20:00,19.6370909146\n2014-04-07 02:25:00,19.179929535699998\n2014-04-07 02:30:00,18.2158045291\n2014-04-07 02:35:00,20.083096954600002\n2014-04-07 02:40:00,21.2664368224\n2014-04-07 02:45:00,21.4055088211\n2014-04-07 02:50:00,18.9417599189\n2014-04-07 02:55:00,20.3985648158\n2014-04-07 03:00:00,21.423525237899998\n2014-04-07 03:05:00,19.634903713099998\n2014-04-07 03:10:00,21.7285472692\n2014-04-07 03:15:00,21.6119141165\n2014-04-07 03:20:00,18.8325355897\n2014-04-07 03:25:00,19.0358593316\n2014-04-07 03:30:00,18.7217679946\n2014-04-07 03:35:00,18.7842174058\n2014-04-07 03:40:00,21.631448348699998\n2014-04-07 03:45:00,21.724551636799998\n2014-04-07 03:50:00,18.2075889647\n2014-04-07 03:55:00,20.374413422699998\n2014-04-07 04:00:00,20.2569262514\n2014-04-07 04:05:00,19.5621905869\n2014-04-07 04:10:00,20.526790371300002\n2014-04-07 04:15:00,21.789471302\n2014-04-07 04:20:00,18.6810195309\n2014-04-07 04:25:00,18.4816436389\n2014-04-07 04:30:00,18.133562283299998\n2014-04-07 04:35:00,19.4553332314\n2014-04-07 04:40:00,19.350513908299998\n2014-04-07 04:45:00,19.7232787526\n2014-04-07 04:50:00,20.013240123499997\n2014-04-07 04:55:00,21.031295976099997\n2014-04-07 05:00:00,19.568453561800002\n2014-04-07 05:05:00,19.3224524374\n2014-04-07 05:10:00,21.307515281\n2014-04-07 05:15:00,21.3991866826\n2014-04-07 05:20:00,18.9310638572\n2014-04-07 05:25:00,19.258687290799998\n2014-04-07 05:30:00,21.3004654836\n2014-04-07 05:35:00,18.3176329772\n2014-04-07 05:40:00,19.3033871216\n2014-04-07 05:45:00,19.7934004282\n2014-04-07 05:50:00,18.7482864608\n2014-04-07 05:55:00,18.7196567864\n2014-04-07 06:00:00,19.6994482321\n2014-04-07 06:05:00,21.018086898900002\n2014-04-07 06:10:00,21.3609319182\n2014-04-07 06:15:00,21.9169403701\n2014-04-07 06:20:00,18.2959362004\n2014-04-07 06:25:00,18.8667288046\n2014-04-07 06:30:00,21.0265193695\n2014-04-07 06:35:00,20.1623948242\n2014-04-07 06:40:00,19.3107190958\n2014-04-07 06:45:00,18.822358645\n2014-04-07 06:50:00,19.121910206600003\n2014-04-07 06:55:00,19.7171558012\n2014-04-07 07:00:00,18.708604878\n2014-04-07 07:05:00,21.856903823499998\n2014-04-07 07:10:00,18.4303537784\n2014-04-07 07:15:00,21.942309738000002\n2014-04-07 07:20:00,21.367573144\n2014-04-07 07:25:00,19.6926064701\n2014-04-07 07:30:00,20.9592653376\n2014-04-07 07:35:00,20.6860609748\n2014-04-07 07:40:00,18.853147671800002\n2014-04-07 07:45:00,19.3562803445\n2014-04-07 07:50:00,20.0524902512\n2014-04-07 07:55:00,20.5513767196\n2014-04-07 08:00:00,20.1715799254\n2014-04-07 08:05:00,19.891949844000003\n2014-04-07 08:10:00,19.7726090938\n2014-04-07 08:15:00,19.9930579972\n2014-04-07 08:20:00,19.7374060794\n2014-04-07 08:25:00,20.1653203102\n2014-04-07 08:30:00,21.551941196199998\n2014-04-07 08:35:00,20.5313172522\n2014-04-07 08:40:00,20.8904835\n2014-04-07 08:45:00,20.3899325349\n2014-04-07 08:50:00,20.572070729700002\n2014-04-07 08:55:00,20.3133993138\n2014-04-07 09:00:00,61.565384701899994\n2014-04-07 09:05:00,74.7945379979\n2014-04-07 09:10:00,61.657085666899995\n2014-04-07 09:15:00,66.574012912\n2014-04-07 09:20:00,62.6295732249\n2014-04-07 09:25:00,62.518226926000004\n2014-04-07 09:30:00,71.9919665428\n2014-04-07 09:35:00,66.9925905993\n2014-04-07 09:40:00,72.0954864329\n2014-04-07 09:45:00,64.9098960013\n2014-04-07 09:50:00,64.6878939686\n2014-04-07 09:55:00,64.6167467927\n2014-04-07 10:00:00,79.4025801219\n2014-04-07 10:05:00,82.4887905304\n2014-04-07 10:10:00,76.8590908764\n2014-04-07 10:15:00,75.7259427827\n2014-04-07 10:20:00,84.9499546812\n2014-04-07 10:25:00,71.65202263890001\n2014-04-07 10:30:00,77.3925392253\n2014-04-07 10:35:00,76.1797299294\n2014-04-07 10:40:00,71.362924779\n2014-04-07 10:45:00,74.0024696196\n2014-04-07 10:50:00,70.2814076192\n2014-04-07 10:55:00,83.450330565\n2014-04-07 11:00:00,81.2352389091\n2014-04-07 11:05:00,84.5300541901\n2014-04-07 11:10:00,79.862802011\n2014-04-07 11:15:00,81.1026043271\n2014-04-07 11:20:00,82.7143896151\n2014-04-07 11:25:00,86.0090169232\n2014-04-07 11:30:00,73.027222024\n2014-04-07 11:35:00,76.8314032699\n2014-04-07 11:40:00,82.84435253689999\n2014-04-07 11:45:00,86.809607354\n2014-04-07 11:50:00,87.1667613427\n2014-04-07 11:55:00,81.71639025729999\n2014-04-07 12:00:00,75.0074585533\n2014-04-07 12:05:00,73.8186537715\n2014-04-07 12:10:00,87.0321342705\n2014-04-07 12:15:00,78.8481116198\n2014-04-07 12:20:00,75.0269160644\n2014-04-07 12:25:00,86.83794951610001\n2014-04-07 12:30:00,73.583981479\n2014-04-07 12:35:00,83.5727297847\n2014-04-07 12:40:00,81.9058033906\n2014-04-07 12:45:00,73.3156701245\n2014-04-07 12:50:00,77.32707675340001\n2014-04-07 12:55:00,74.3096123634\n2014-04-07 13:00:00,81.6523762059\n2014-04-07 13:05:00,79.6146963928\n2014-04-07 13:10:00,72.0511055781\n2014-04-07 13:15:00,87.590342332\n2014-04-07 13:20:00,77.5747319932\n2014-04-07 13:25:00,76.1129987805\n2014-04-07 13:30:00,75.54095311180001\n2014-04-07 13:35:00,74.5231644857\n2014-04-07 13:40:00,87.96507653309997\n2014-04-07 13:45:00,76.7033382657\n2014-04-07 13:50:00,78.4693787838\n2014-04-07 13:55:00,85.92106865209999\n2014-04-07 14:00:00,82.2662510871\n2014-04-07 14:05:00,77.89537143060001\n2014-04-07 14:10:00,86.3691090585\n2014-04-07 14:15:00,83.9915554472\n2014-04-07 14:20:00,75.64277709310001\n2014-04-07 14:25:00,82.2958735221\n2014-04-07 14:30:00,86.75421157059998\n2014-04-07 14:35:00,79.9395367733\n2014-04-07 14:40:00,83.733779031\n2014-04-07 14:45:00,87.53345809620001\n2014-04-07 14:50:00,83.0426400163\n2014-04-07 14:55:00,73.6354843633\n2014-04-07 15:00:00,75.9122240506\n2014-04-07 15:05:00,81.52076039069999\n2014-04-07 15:10:00,76.40815952060001\n2014-04-07 15:15:00,87.31982900780001\n2014-04-07 15:20:00,78.4848790823\n2014-04-07 15:25:00,79.3149250611\n2014-04-07 15:30:00,83.2248345294\n2014-04-07 15:35:00,80.3872239767\n2014-04-07 15:40:00,78.1135855726\n2014-04-07 15:45:00,73.2255030309\n2014-04-07 15:50:00,81.5423466181\n2014-04-07 15:55:00,85.88045603239999\n2014-04-07 16:00:00,82.9720397615\n2014-04-07 16:05:00,78.10377020119998\n2014-04-07 16:10:00,74.0434748702\n2014-04-07 16:15:00,85.0612476726\n2014-04-07 16:20:00,87.0678066252\n2014-04-07 16:25:00,78.212217685\n2014-04-07 16:30:00,83.6581144031\n2014-04-07 16:35:00,78.5720641796\n2014-04-07 16:40:00,80.036117352\n2014-04-07 16:45:00,85.3834581533\n2014-04-07 16:50:00,73.3346486726\n2014-04-07 16:55:00,80.4852110487\n2014-04-07 17:00:00,75.4338954281\n2014-04-07 17:05:00,77.4368653922\n2014-04-07 17:10:00,82.3108295869\n2014-04-07 17:15:00,72.4356267821\n2014-04-07 17:20:00,81.5011702871\n2014-04-07 17:25:00,76.5350464418\n2014-04-07 17:30:00,82.7117180116\n2014-04-07 17:35:00,74.2652731127\n2014-04-07 17:40:00,83.7729534922\n2014-04-07 17:45:00,82.3302039014\n2014-04-07 17:50:00,87.5398357108\n2014-04-07 17:55:00,86.5797325655\n2014-04-07 18:00:00,30.613132446799998\n2014-04-07 18:05:00,28.974820502300002\n2014-04-07 18:10:00,32.9943524562\n2014-04-07 18:15:00,32.6584730192\n2014-04-07 18:20:00,28.975538556799997\n2014-04-07 18:25:00,29.5851305066\n2014-04-07 18:30:00,32.5420846609\n2014-04-07 18:35:00,34.6356878398\n2014-04-07 18:40:00,34.601595126199996\n2014-04-07 18:45:00,29.7694986338\n2014-04-07 18:50:00,31.2612672548\n2014-04-07 18:55:00,29.0764927492\n2014-04-07 19:00:00,22.262336650500004\n2014-04-07 19:05:00,23.5338126083\n2014-04-07 19:10:00,23.6990764469\n2014-04-07 19:15:00,22.3954715818\n2014-04-07 19:20:00,20.5894950132\n2014-04-07 19:25:00,21.8685094092\n2014-04-07 19:30:00,24.335815445700003\n2014-04-07 19:35:00,21.1886630909\n2014-04-07 19:40:00,21.592498751100006\n2014-04-07 19:45:00,23.505784456599997\n2014-04-07 19:50:00,23.446440648000003\n2014-04-07 19:55:00,24.2466649202\n2014-04-07 20:00:00,20.0217339169\n2014-04-07 20:05:00,20.5397961265\n2014-04-07 20:10:00,20.346439277\n2014-04-07 20:15:00,22.232072625700003\n2014-04-07 20:20:00,21.5831778328\n2014-04-07 20:25:00,21.8375852681\n2014-04-07 20:30:00,18.9771702814\n2014-04-07 20:35:00,21.6754037939\n2014-04-07 20:40:00,20.2054807833\n2014-04-07 20:45:00,18.5275950225\n2014-04-07 20:50:00,18.678121668699998\n2014-04-07 20:55:00,21.208710666600002\n2014-04-07 21:00:00,19.581592355599998\n2014-04-07 21:05:00,21.5755300591\n2014-04-07 21:10:00,21.0375905282\n2014-04-07 21:15:00,18.1735362584\n2014-04-07 21:20:00,20.8471414519\n2014-04-07 21:25:00,18.8595030123\n2014-04-07 21:30:00,19.7848438117\n2014-04-07 21:35:00,20.597335674\n2014-04-07 21:40:00,21.594027494899997\n2014-04-07 21:45:00,19.9195485843\n2014-04-07 21:50:00,21.335884781300003\n2014-04-07 21:55:00,21.23329554\n2014-04-07 22:00:00,19.6770258696\n2014-04-07 22:05:00,20.0231244077\n2014-04-07 22:10:00,20.8219098924\n2014-04-07 22:15:00,18.1419933397\n2014-04-07 22:20:00,21.5839463604\n2014-04-07 22:25:00,21.099500721400002\n2014-04-07 22:30:00,19.0159012733\n2014-04-07 22:35:00,21.945767533\n2014-04-07 22:40:00,18.7355302601\n2014-04-07 22:45:00,21.677136776999998\n2014-04-07 22:50:00,19.3164198019\n2014-04-07 22:55:00,21.072797313699997\n2014-04-07 23:00:00,19.8293128683\n2014-04-07 23:05:00,20.9498911547\n2014-04-07 23:10:00,18.626707831300003\n2014-04-07 23:15:00,19.0816888126\n2014-04-07 23:20:00,18.4029639869\n2014-04-07 23:25:00,21.4646963542\n2014-04-07 23:30:00,19.1888555022\n2014-04-07 23:35:00,20.7818942734\n2014-04-07 23:40:00,21.2849707188\n2014-04-07 23:45:00,21.6098212326\n2014-04-07 23:50:00,18.4287260956\n2014-04-07 23:55:00,21.5762015674\n2014-04-08 00:00:00,18.7890111109\n2014-04-08 00:05:00,20.947608046400003\n2014-04-08 00:10:00,20.9153960775\n2014-04-08 00:15:00,18.034012567\n2014-04-08 00:20:00,18.882495633199998\n2014-04-08 00:25:00,19.9676340587\n2014-04-08 00:30:00,19.680138826700002\n2014-04-08 00:35:00,21.6742939195\n2014-04-08 00:40:00,19.438963477999998\n2014-04-08 00:45:00,21.7479348593\n2014-04-08 00:50:00,19.8377172736\n2014-04-08 00:55:00,21.857411586599998\n2014-04-08 01:00:00,20.9494192401\n2014-04-08 01:05:00,21.3173383665\n2014-04-08 01:10:00,18.4195075534\n2014-04-08 01:15:00,20.344565733\n2014-04-08 01:20:00,18.570801439300002\n2014-04-08 01:25:00,19.1904840082\n2014-04-08 01:30:00,20.494261624700002\n2014-04-08 01:35:00,20.9049028188\n2014-04-08 01:40:00,18.156735128\n2014-04-08 01:45:00,20.1237749243\n2014-04-08 01:50:00,20.2612559452\n2014-04-08 01:55:00,18.315311988399998\n2014-04-08 02:00:00,20.0027521368\n2014-04-08 02:05:00,20.8553691202\n2014-04-08 02:10:00,18.2129091395\n2014-04-08 02:15:00,21.0410711053\n2014-04-08 02:20:00,20.3057060196\n2014-04-08 02:25:00,21.3329088331\n2014-04-08 02:30:00,18.8722502914\n2014-04-08 02:35:00,21.3330947369\n2014-04-08 02:40:00,18.3782439011\n2014-04-08 02:45:00,19.6153187858\n2014-04-08 02:50:00,18.797939166099997\n2014-04-08 02:55:00,21.5040833292\n2014-04-08 03:00:00,20.8196792652\n2014-04-08 03:05:00,18.1014471086\n2014-04-08 03:10:00,18.0380934225\n2014-04-08 03:15:00,19.1649970179\n2014-04-08 03:20:00,18.5731324571\n2014-04-08 03:25:00,20.5212179102\n2014-04-08 03:30:00,20.6551877355\n2014-04-08 03:35:00,21.767803614600002\n2014-04-08 03:40:00,21.8081596982\n2014-04-08 03:45:00,20.6355868216\n2014-04-08 03:50:00,18.022700451400002\n2014-04-08 03:55:00,19.4359916663\n2014-04-08 04:00:00,20.052566053\n2014-04-08 04:05:00,19.996719025999997\n2014-04-08 04:10:00,20.413362518\n2014-04-08 04:15:00,21.8422059312\n2014-04-08 04:20:00,21.5407707678\n2014-04-08 04:25:00,18.435632133800002\n2014-04-08 04:30:00,19.0639215656\n2014-04-08 04:35:00,21.3324376697\n2014-04-08 04:40:00,21.2972276353\n2014-04-08 04:45:00,19.101482896500002\n2014-04-08 04:50:00,20.9223521227\n2014-04-08 04:55:00,20.6881495149\n2014-04-08 05:00:00,19.8940958599\n2014-04-08 05:05:00,18.8058198107\n2014-04-08 05:10:00,21.5545727236\n2014-04-08 05:15:00,20.7114047372\n2014-04-08 05:20:00,18.6759716995\n2014-04-08 05:25:00,20.8192093794\n2014-04-08 05:30:00,20.965734878299997\n2014-04-08 05:35:00,21.547521140500002\n2014-04-08 05:40:00,18.891357020999997\n2014-04-08 05:45:00,21.9550164217\n2014-04-08 05:50:00,18.6135736901\n2014-04-08 05:55:00,20.4027555674\n2014-04-08 06:00:00,20.628706021099998\n2014-04-08 06:05:00,19.6758115811\n2014-04-08 06:10:00,19.9001508351\n2014-04-08 06:15:00,21.5636403869\n2014-04-08 06:20:00,20.5810969187\n2014-04-08 06:25:00,19.9880038329\n2014-04-08 06:30:00,18.5133982497\n2014-04-08 06:35:00,18.029350500899998\n2014-04-08 06:40:00,18.4998744726\n2014-04-08 06:45:00,21.8247382699\n2014-04-08 06:50:00,21.056347132\n2014-04-08 06:55:00,21.86846531\n2014-04-08 07:00:00,18.142834838800002\n2014-04-08 07:05:00,20.7208816154\n2014-04-08 07:10:00,18.1771741056\n2014-04-08 07:15:00,21.1282258755\n2014-04-08 07:20:00,19.5238006909\n2014-04-08 07:25:00,18.3830614404\n2014-04-08 07:30:00,20.2721865672\n2014-04-08 07:35:00,19.1204807864\n2014-04-08 07:40:00,20.6382957675\n2014-04-08 07:45:00,20.6326990381\n2014-04-08 07:50:00,20.8200298965\n2014-04-08 07:55:00,21.969860315100004\n2014-04-08 08:00:00,19.5467908398\n2014-04-08 08:05:00,19.8612618979\n2014-04-08 08:10:00,21.2184468041\n2014-04-08 08:15:00,20.3134800921\n2014-04-08 08:20:00,18.1490288428\n2014-04-08 08:25:00,21.372314081\n2014-04-08 08:30:00,18.2059947278\n2014-04-08 08:35:00,18.683280546\n2014-04-08 08:40:00,18.4083198679\n2014-04-08 08:45:00,18.311708531500003\n2014-04-08 08:50:00,18.1027395012\n2014-04-08 08:55:00,18.2201108559\n2014-04-08 09:00:00,67.2171729728\n2014-04-08 09:05:00,64.6387908718\n2014-04-08 09:10:00,62.920901614499996\n2014-04-08 09:15:00,70.1583953811\n2014-04-08 09:20:00,64.2751219846\n2014-04-08 09:25:00,61.4577085127\n2014-04-08 09:30:00,66.8905090592\n2014-04-08 09:35:00,65.4218886909\n2014-04-08 09:40:00,65.5330202663\n2014-04-08 09:45:00,67.2556723833\n2014-04-08 09:50:00,70.29722941039999\n2014-04-08 09:55:00,69.5841160325\n2014-04-08 10:00:00,84.3863001839\n2014-04-08 10:05:00,77.874962661\n2014-04-08 10:10:00,77.1742849989\n2014-04-08 10:15:00,73.1521920346\n2014-04-08 10:20:00,81.5635176029\n2014-04-08 10:25:00,72.02484004680001\n2014-04-08 10:30:00,77.46238245\n2014-04-08 10:35:00,76.37892051899999\n2014-04-08 10:40:00,80.0568296328\n2014-04-08 10:45:00,84.0814852137\n2014-04-08 10:50:00,84.5311635801\n2014-04-08 10:55:00,72.4442446264\n2014-04-08 11:00:00,75.7319410393\n2014-04-08 11:05:00,84.47624812869998\n2014-04-08 11:10:00,79.810721342\n2014-04-08 11:15:00,78.7730617751\n2014-04-08 11:20:00,82.86978719470001\n2014-04-08 11:25:00,81.1410144463\n2014-04-08 11:30:00,87.0062363215\n2014-04-08 11:35:00,80.85553287\n2014-04-08 11:40:00,78.9788477342\n2014-04-08 11:45:00,80.20096732649999\n2014-04-08 11:50:00,84.4270172447\n2014-04-08 11:55:00,81.3119841031\n2014-04-08 12:00:00,82.2539461388\n2014-04-08 12:05:00,87.4379704541\n2014-04-08 12:10:00,81.7960545575\n2014-04-08 12:15:00,77.9908624966\n2014-04-08 12:20:00,82.9615429725\n2014-04-08 12:25:00,82.4522887312\n2014-04-08 12:30:00,72.1348962935\n2014-04-08 12:35:00,79.3818960261\n2014-04-08 12:40:00,83.78579389689999\n2014-04-08 12:45:00,79.8886817275\n2014-04-08 12:50:00,84.3725694492\n2014-04-08 12:55:00,79.1190821759\n2014-04-08 13:00:00,87.7120896073\n2014-04-08 13:05:00,76.6678607236\n2014-04-08 13:10:00,73.4563279795\n2014-04-08 13:15:00,78.8612575731\n2014-04-08 13:20:00,80.6479842353\n2014-04-08 13:25:00,77.566879187\n2014-04-08 13:30:00,75.8582882022\n2014-04-08 13:35:00,82.73307835680001\n2014-04-08 13:40:00,78.0152734373\n2014-04-08 13:45:00,82.08219201050001\n2014-04-08 13:50:00,84.4448715432\n2014-04-08 13:55:00,84.1558397941\n2014-04-08 14:00:00,78.0012047326\n2014-04-08 14:05:00,81.0824795174\n2014-04-08 14:10:00,79.1907302536\n2014-04-08 14:15:00,85.9287592649\n2014-04-08 14:20:00,86.05600479030001\n2014-04-08 14:25:00,77.49614533270001\n2014-04-08 14:30:00,73.4642727117\n2014-04-08 14:35:00,74.67773502979999\n2014-04-08 14:40:00,77.8682900168\n2014-04-08 14:45:00,81.0241099322\n2014-04-08 14:50:00,82.504631763\n2014-04-08 14:55:00,77.2982262476\n2014-04-08 15:00:00,82.6791921861\n2014-04-08 15:05:00,87.00300450190002\n2014-04-08 15:10:00,82.43143468529999\n2014-04-08 15:15:00,74.5363281155\n2014-04-08 15:20:00,81.2739223705\n2014-04-08 15:25:00,80.66955383310001\n2014-04-08 15:30:00,85.9303768348\n2014-04-08 15:35:00,77.6041038769\n2014-04-08 15:40:00,78.7663735965\n2014-04-08 15:45:00,81.5777617338\n2014-04-08 15:50:00,80.3900332361\n2014-04-08 15:55:00,83.5034638375\n2014-04-08 16:00:00,72.64608437390001\n2014-04-08 16:05:00,81.0161007561\n2014-04-08 16:10:00,73.9466083103\n2014-04-08 16:15:00,77.0431959571\n2014-04-08 16:20:00,82.5858712193\n2014-04-08 16:25:00,74.5184841337\n2014-04-08 16:30:00,76.94132164050001\n2014-04-08 16:35:00,83.247943889\n2014-04-08 16:40:00,82.4127256477\n2014-04-08 16:45:00,73.45649367060001\n2014-04-08 16:50:00,81.2361399222\n2014-04-08 16:55:00,74.355928627\n2014-04-08 17:00:00,76.0363128615\n2014-04-08 17:05:00,79.3473499888\n2014-04-08 17:10:00,73.7495208529\n2014-04-08 17:15:00,87.89831773370001\n2014-04-08 17:20:00,74.64588431279999\n2014-04-08 17:25:00,84.50096960649999\n2014-04-08 17:30:00,85.2773887738\n2014-04-08 17:35:00,87.91138976030001\n2014-04-08 17:40:00,78.858421204\n2014-04-08 17:45:00,85.98547930379999\n2014-04-08 17:50:00,87.3205974931\n2014-04-08 17:55:00,74.7662776081\n2014-04-08 18:00:00,31.8683848513\n2014-04-08 18:05:00,29.1840636373\n2014-04-08 18:10:00,32.7726273846\n2014-04-08 18:15:00,32.520993159899994\n2014-04-08 18:20:00,30.1064024414\n2014-04-08 18:25:00,33.9065711469\n2014-04-08 18:30:00,29.0385142503\n2014-04-08 18:35:00,33.9598483541\n2014-04-08 18:40:00,28.97052430110001\n2014-04-08 18:45:00,33.003698061\n2014-04-08 18:50:00,29.3041192627\n2014-04-08 18:55:00,30.407837485300004\n2014-04-08 19:00:00,23.3941705216\n2014-04-08 19:05:00,21.4162123275\n2014-04-08 19:10:00,22.4500576107\n2014-04-08 19:15:00,24.260310916599998\n2014-04-08 19:20:00,20.382360788\n2014-04-08 19:25:00,23.7936361707\n2014-04-08 19:30:00,20.4524174316\n2014-04-08 19:35:00,20.7280397655\n2014-04-08 19:40:00,20.6945484502\n2014-04-08 19:45:00,24.6135768786\n2014-04-08 19:50:00,20.9672335604\n2014-04-08 19:55:00,24.1774917449\n2014-04-08 20:00:00,22.490857869499997\n2014-04-08 20:05:00,20.0039821796\n2014-04-08 20:10:00,21.016774582100002\n2014-04-08 20:15:00,21.6231575159\n2014-04-08 20:20:00,20.0402740147\n2014-04-08 20:25:00,19.0947904903\n2014-04-08 20:30:00,20.208691956099997\n2014-04-08 20:35:00,21.5936515348\n2014-04-08 20:40:00,21.6300040167\n2014-04-08 20:45:00,19.376286660199998\n2014-04-08 20:50:00,19.148659031199998\n2014-04-08 20:55:00,22.2026163694\n2014-04-08 21:00:00,18.263240859\n2014-04-08 21:05:00,21.0394608303\n2014-04-08 21:10:00,18.2729767877\n2014-04-08 21:15:00,21.4540878319\n2014-04-08 21:20:00,21.7254431646\n2014-04-08 21:25:00,19.2817868969\n2014-04-08 21:30:00,18.3835620935\n2014-04-08 21:35:00,20.0183672395\n2014-04-08 21:40:00,19.2859825901\n2014-04-08 21:45:00,19.7629535368\n2014-04-08 21:50:00,20.7591094839\n2014-04-08 21:55:00,18.9297327574\n2014-04-08 22:00:00,19.4464569625\n2014-04-08 22:05:00,21.1505349907\n2014-04-08 22:10:00,20.5947998356\n2014-04-08 22:15:00,19.323634852999998\n2014-04-08 22:20:00,20.677037309\n2014-04-08 22:25:00,21.0814704828\n2014-04-08 22:30:00,20.389497458399997\n2014-04-08 22:35:00,18.9761869885\n2014-04-08 22:40:00,18.0182620951\n2014-04-08 22:45:00,21.2317593581\n2014-04-08 22:50:00,21.3109731237\n2014-04-08 22:55:00,20.8103767966\n2014-04-08 23:00:00,18.3098385378\n2014-04-08 23:05:00,20.3447945987\n2014-04-08 23:10:00,21.2881692269\n2014-04-08 23:15:00,19.5624285438\n2014-04-08 23:20:00,18.7956109996\n2014-04-08 23:25:00,20.3544164847\n2014-04-08 23:30:00,21.3093171106\n2014-04-08 23:35:00,18.1989733652\n2014-04-08 23:40:00,20.3917193252\n2014-04-08 23:45:00,20.5766451368\n2014-04-08 23:50:00,20.4133867733\n2014-04-08 23:55:00,20.6040899608\n2014-04-09 00:00:00,20.5255012304\n2014-04-09 00:05:00,18.5216155399\n2014-04-09 00:10:00,18.9397471078\n2014-04-09 00:15:00,20.475976021199997\n2014-04-09 00:20:00,18.0707726445\n2014-04-09 00:25:00,20.5389780749\n2014-04-09 00:30:00,20.6615464951\n2014-04-09 00:35:00,18.9566990394\n2014-04-09 00:40:00,20.392531319\n2014-04-09 00:45:00,20.1363602429\n2014-04-09 00:50:00,19.0427661926\n2014-04-09 00:55:00,19.8518960475\n2014-04-09 01:00:00,21.6384981176\n2014-04-09 01:05:00,19.706411121800002\n2014-04-09 01:10:00,20.5193767075\n2014-04-09 01:15:00,18.1414032842\n2014-04-09 01:20:00,18.3112004533\n2014-04-09 01:25:00,18.3252322932\n2014-04-09 01:30:00,21.1129630545\n2014-04-09 01:35:00,19.4010275792\n2014-04-09 01:40:00,18.9104467535\n2014-04-09 01:45:00,20.989298273800003\n2014-04-09 01:50:00,18.679840250199998\n2014-04-09 01:55:00,18.9859701003\n2014-04-09 02:00:00,19.7237257731\n2014-04-09 02:05:00,19.325752276099998\n2014-04-09 02:10:00,20.3415688441\n2014-04-09 02:15:00,19.3513624763\n2014-04-09 02:20:00,19.571806543399997\n2014-04-09 02:25:00,21.451546433\n2014-04-09 02:30:00,21.538125758499998\n2014-04-09 02:35:00,21.3108447633\n2014-04-09 02:40:00,21.459323730799998\n2014-04-09 02:45:00,20.2789146774\n2014-04-09 02:50:00,20.584932859000002\n2014-04-09 02:55:00,20.2286926662\n2014-04-09 03:00:00,21.1423523362\n2014-04-09 03:05:00,20.204001942999998\n2014-04-09 03:10:00,18.4443078582\n2014-04-09 03:15:00,21.238320481800002\n2014-04-09 03:20:00,21.0423406827\n2014-04-09 03:25:00,21.281202381099998\n2014-04-09 03:30:00,18.7617178536\n2014-04-09 03:35:00,19.086468210899998\n2014-04-09 03:40:00,19.183006789100002\n2014-04-09 03:45:00,20.0323221447\n2014-04-09 03:50:00,18.5355083367\n2014-04-09 03:55:00,19.541527013099998\n2014-04-09 04:00:00,18.7286326443\n2014-04-09 04:05:00,19.0590508521\n2014-04-09 04:10:00,20.825550538199998\n2014-04-09 04:15:00,21.4192446253\n2014-04-09 04:20:00,18.0916234664\n2014-04-09 04:25:00,20.2635878534\n2014-04-09 04:30:00,18.1442390482\n2014-04-09 04:35:00,18.34099698\n2014-04-09 04:40:00,20.8203361385\n2014-04-09 04:45:00,20.942432426\n2014-04-09 04:50:00,21.2559226927\n2014-04-09 04:55:00,19.8969660471\n2014-04-09 05:00:00,21.439229928099998\n2014-04-09 05:05:00,18.6673531666\n2014-04-09 05:10:00,18.9988656545\n2014-04-09 05:15:00,18.5380085904\n2014-04-09 05:20:00,21.1901490423\n2014-04-09 05:25:00,18.914700473499998\n2014-04-09 05:30:00,18.622044970999998\n2014-04-09 05:35:00,20.4924427504\n2014-04-09 05:40:00,18.3083281054\n2014-04-09 05:45:00,18.179601108900002\n2014-04-09 05:50:00,18.4268705942\n2014-04-09 05:55:00,18.0009635359\n2014-04-09 06:00:00,20.7879606169\n2014-04-09 06:05:00,20.2489412869\n2014-04-09 06:10:00,18.839500436199998\n2014-04-09 06:15:00,18.9320197919\n2014-04-09 06:20:00,21.2438743939\n2014-04-09 06:25:00,20.0072804634\n2014-04-09 06:30:00,20.794113428299998\n2014-04-09 06:35:00,19.8110218051\n2014-04-09 06:40:00,18.9508721041\n2014-04-09 06:45:00,21.8816112027\n2014-04-09 06:50:00,20.262590253499997\n2014-04-09 06:55:00,18.5239276151\n2014-04-09 07:00:00,19.624360168699997\n2014-04-09 07:05:00,19.3173496478\n2014-04-09 07:10:00,18.8563498744\n2014-04-09 07:15:00,21.733759956999997\n2014-04-09 07:20:00,21.523679981799997\n2014-04-09 07:25:00,18.796588466099998\n2014-04-09 07:30:00,19.408591556199998\n2014-04-09 07:35:00,21.0492615667\n2014-04-09 07:40:00,18.8340241926\n2014-04-09 07:45:00,20.3662594504\n2014-04-09 07:50:00,20.7991757685\n2014-04-09 07:55:00,20.6158893028\n2014-04-09 08:00:00,20.8256345611\n2014-04-09 08:05:00,20.8267983561\n2014-04-09 08:10:00,21.8592236794\n2014-04-09 08:15:00,19.3859955581\n2014-04-09 08:20:00,21.5143616975\n2014-04-09 08:25:00,18.0872282501\n2014-04-09 08:30:00,19.152811853299998\n2014-04-09 08:35:00,18.194623128\n2014-04-09 08:40:00,20.6048158398\n2014-04-09 08:45:00,18.4031614829\n2014-04-09 08:50:00,21.3828274546\n2014-04-09 08:55:00,20.5863667352\n2014-04-09 09:00:00,61.5918894543\n2014-04-09 09:05:00,70.9209721699\n2014-04-09 09:10:00,72.9236752827\n2014-04-09 09:15:00,70.1912457042\n2014-04-09 09:20:00,61.6151293367\n2014-04-09 09:25:00,72.8677058591\n2014-04-09 09:30:00,71.1615092159\n2014-04-09 09:35:00,66.3469378498\n2014-04-09 09:40:00,65.6693715131\n2014-04-09 09:45:00,67.7255544671\n2014-04-09 09:50:00,72.99258381279999\n2014-04-09 09:55:00,64.6280071854\n2014-04-09 10:00:00,71.4069583505\n2014-04-09 10:05:00,83.2591565084\n2014-04-09 10:10:00,70.2480184546\n2014-04-09 10:15:00,83.9786737852\n2014-04-09 10:20:00,74.5851654156\n2014-04-09 10:25:00,77.72761633020001\n2014-04-09 10:30:00,71.8932265442\n2014-04-09 10:35:00,83.8429971247\n2014-04-09 10:40:00,81.4774581869\n2014-04-09 10:45:00,84.1828947042\n2014-04-09 10:50:00,80.4437148734\n2014-04-09 10:55:00,72.706447415\n2014-04-09 11:00:00,76.4706784155\n2014-04-09 11:05:00,79.3108397384\n2014-04-09 11:10:00,81.225834498\n2014-04-09 11:15:00,86.3024108914\n2014-04-09 11:20:00,77.67436411189999\n2014-04-09 11:25:00,82.7496574364\n2014-04-09 11:30:00,86.8518847331\n2014-04-09 11:35:00,73.9913571046\n2014-04-09 11:40:00,85.2885333\n2014-04-09 11:45:00,78.25890934350001\n2014-04-09 11:50:00,83.2164359244\n2014-04-09 11:55:00,76.2364337393\n2014-04-09 12:00:00,77.2509349953\n2014-04-09 12:05:00,72.34721064\n2014-04-09 12:10:00,87.43741549090002\n2014-04-09 12:15:00,84.9132229142\n2014-04-09 12:20:00,73.414484102\n2014-04-09 12:25:00,87.8865501617\n2014-04-09 12:30:00,81.582377083\n2014-04-09 12:35:00,85.55686661760001\n2014-04-09 12:40:00,72.9788923258\n2014-04-09 12:45:00,78.1373413932\n2014-04-09 12:50:00,82.6151606553\n2014-04-09 12:55:00,73.6144959718\n2014-04-09 13:00:00,79.8032880316\n2014-04-09 13:05:00,79.0638661097\n2014-04-09 13:10:00,75.4385339971\n2014-04-09 13:15:00,76.7858843375\n2014-04-09 13:20:00,87.45289993739998\n2014-04-09 13:25:00,76.59998736600001\n2014-04-09 13:30:00,75.3967185871\n2014-04-09 13:35:00,80.5600076939\n2014-04-09 13:40:00,82.7154720663\n2014-04-09 13:45:00,83.5814254196\n2014-04-09 13:50:00,84.0477786428\n2014-04-09 13:55:00,72.5718984275\n2014-04-09 14:00:00,78.29640799810001\n2014-04-09 14:05:00,84.3792788767\n2014-04-09 14:10:00,86.47348270239998\n2014-04-09 14:15:00,81.6312834836\n2014-04-09 14:20:00,72.8334134845\n2014-04-09 14:25:00,78.3425722697\n2014-04-09 14:30:00,73.1841208475\n2014-04-09 14:35:00,83.9725749259\n2014-04-09 14:40:00,73.0125827363\n2014-04-09 14:45:00,74.9680984263\n2014-04-09 14:50:00,78.66755855939999\n2014-04-09 14:55:00,79.3985625599\n2014-04-09 15:00:00,78.5029535695\n2014-04-09 15:05:00,79.413583968\n2014-04-09 15:10:00,83.4110256788\n2014-04-09 15:15:00,77.9075532476\n2014-04-09 15:20:00,80.7632320119\n2014-04-09 15:25:00,76.8531703229\n2014-04-09 15:30:00,77.6572944043\n2014-04-09 15:35:00,81.81999786520001\n2014-04-09 15:40:00,79.8471478862\n2014-04-09 15:45:00,83.56777845939999\n2014-04-09 15:50:00,80.9678401101\n2014-04-09 15:55:00,84.85637073720001\n2014-04-09 16:00:00,79.0943795464\n2014-04-09 16:05:00,79.85638459329998\n2014-04-09 16:10:00,82.7193827609\n2014-04-09 16:15:00,75.53975807399999\n2014-04-09 16:20:00,78.1747224951\n2014-04-09 16:25:00,81.99730246909999\n2014-04-09 16:30:00,72.4618811812\n2014-04-09 16:35:00,78.9913912744\n2014-04-09 16:40:00,81.5814423442\n2014-04-09 16:45:00,87.4778405539\n2014-04-09 16:50:00,86.0320998039\n2014-04-09 16:55:00,76.4917243827\n2014-04-09 17:00:00,80.11533090020001\n2014-04-09 17:05:00,72.902601968\n2014-04-09 17:10:00,75.8520415099\n2014-04-09 17:15:00,84.3976614804\n2014-04-09 17:20:00,73.9729957908\n2014-04-09 17:25:00,76.1230191661\n2014-04-09 17:30:00,87.10464657959999\n2014-04-09 17:35:00,85.18166009810001\n2014-04-09 17:40:00,84.5092109508\n2014-04-09 17:45:00,85.832886885\n2014-04-09 17:50:00,83.9936587317\n2014-04-09 17:55:00,73.92935106899999\n2014-04-09 18:00:00,32.1059863252\n2014-04-09 18:05:00,31.6431550176\n2014-04-09 18:10:00,30.791364189\n2014-04-09 18:15:00,34.1378520677\n2014-04-09 18:20:00,31.770484795300003\n2014-04-09 18:25:00,29.185899045\n2014-04-09 18:30:00,30.5597738683\n2014-04-09 18:35:00,30.2631689609\n2014-04-09 18:40:00,34.4798582427\n2014-04-09 18:45:00,32.9435975189\n2014-04-09 18:50:00,32.3864018835\n2014-04-09 18:55:00,32.0425489946\n2014-04-09 19:00:00,23.0725050977\n2014-04-09 19:05:00,23.5418411581\n2014-04-09 19:10:00,22.64364224\n2014-04-09 19:15:00,24.3635173234\n2014-04-09 19:20:00,24.536215738499997\n2014-04-09 19:25:00,24.6191322279\n2014-04-09 19:30:00,23.1588709028\n2014-04-09 19:35:00,24.3381383559\n2014-04-09 19:40:00,21.9720678297\n2014-04-09 19:45:00,24.0109725956\n2014-04-09 19:50:00,24.233099529\n2014-04-09 19:55:00,24.2105479879\n2014-04-09 20:00:00,21.8351461128\n2014-04-09 20:05:00,20.0974299249\n2014-04-09 20:10:00,19.0828848172\n2014-04-09 20:15:00,19.799884998\n2014-04-09 20:20:00,21.5748137209\n2014-04-09 20:25:00,19.3858988218\n2014-04-09 20:30:00,20.3910021328\n2014-04-09 20:35:00,20.7478761767\n2014-04-09 20:40:00,20.9054044209\n2014-04-09 20:45:00,22.264731579\n2014-04-09 20:50:00,21.1414751579\n2014-04-09 20:55:00,21.6526796908\n2014-04-09 21:00:00,20.4250854059\n2014-04-09 21:05:00,21.4367259651\n2014-04-09 21:10:00,19.1461167468\n2014-04-09 21:15:00,18.9299402917\n2014-04-09 21:20:00,21.809465486599997\n2014-04-09 21:25:00,20.8736382872\n2014-04-09 21:30:00,20.7853955485\n2014-04-09 21:35:00,19.964552974300002\n2014-04-09 21:40:00,19.600421576600002\n2014-04-09 21:45:00,20.319833999100002\n2014-04-09 21:50:00,18.5709802262\n2014-04-09 21:55:00,19.9139806768\n2014-04-09 22:00:00,19.8404994201\n2014-04-09 22:05:00,20.1726932541\n2014-04-09 22:10:00,20.5584596401\n2014-04-09 22:15:00,21.8502295557\n2014-04-09 22:20:00,20.6284608277\n2014-04-09 22:25:00,21.555574101799998\n2014-04-09 22:30:00,20.244631642799998\n2014-04-09 22:35:00,20.527398923499998\n2014-04-09 22:40:00,18.2968959774\n2014-04-09 22:45:00,18.5508466151\n2014-04-09 22:50:00,20.3381876653\n2014-04-09 22:55:00,19.6016510076\n2014-04-09 23:00:00,21.1993115639\n2014-04-09 23:05:00,20.176584658099998\n2014-04-09 23:10:00,21.533297753200003\n2014-04-09 23:15:00,21.893529462399997\n2014-04-09 23:20:00,18.5941101225\n2014-04-09 23:25:00,19.5830702324\n2014-04-09 23:30:00,20.6638908043\n2014-04-09 23:35:00,19.2256456351\n2014-04-09 23:40:00,19.0717904298\n2014-04-09 23:45:00,21.259035191600002\n2014-04-09 23:50:00,21.925722804699998\n2014-04-09 23:55:00,21.099263603900003\n2014-04-10 00:00:00,20.0947064912\n2014-04-10 00:05:00,19.7700449278\n2014-04-10 00:10:00,20.1585908821\n2014-04-10 00:15:00,19.8513588088\n2014-04-10 00:20:00,20.0115522271\n2014-04-10 00:25:00,18.8138122021\n2014-04-10 00:30:00,21.6149677972\n2014-04-10 00:35:00,21.018140006099998\n2014-04-10 00:40:00,20.7239096908\n2014-04-10 00:45:00,21.799699883899997\n2014-04-10 00:50:00,19.1375773277\n2014-04-10 00:55:00,18.3246376436\n2014-04-10 01:00:00,21.3045546414\n2014-04-10 01:05:00,21.9936678546\n2014-04-10 01:10:00,20.3137297521\n2014-04-10 01:15:00,18.2352375517\n2014-04-10 01:20:00,21.1218721606\n2014-04-10 01:25:00,18.2949961954\n2014-04-10 01:30:00,20.160055945\n2014-04-10 01:35:00,19.1101298968\n2014-04-10 01:40:00,21.6601071224\n2014-04-10 01:45:00,19.805324853\n2014-04-10 01:50:00,21.593853393899998\n2014-04-10 01:55:00,19.196324341\n2014-04-10 02:00:00,19.5494503353\n2014-04-10 02:05:00,21.788476753\n2014-04-10 02:10:00,18.805257803699998\n2014-04-10 02:15:00,20.3140046066\n2014-04-10 02:20:00,19.5540413142\n2014-04-10 02:25:00,21.0966675403\n2014-04-10 02:30:00,18.5171854847\n2014-04-10 02:35:00,19.748859875999997\n2014-04-10 02:40:00,20.795730507400002\n2014-04-10 02:45:00,19.62806494\n2014-04-10 02:50:00,18.2341269571\n2014-04-10 02:55:00,20.8204490453\n2014-04-10 03:00:00,20.012793310699998\n2014-04-10 03:05:00,18.0452347467\n2014-04-10 03:10:00,20.4506235809\n2014-04-10 03:15:00,21.679524090100003\n2014-04-10 03:20:00,18.4441037928\n2014-04-10 03:25:00,20.36268494\n2014-04-10 03:30:00,20.9146755271\n2014-04-10 03:35:00,18.283094680599998\n2014-04-10 03:40:00,18.0904618327\n2014-04-10 03:45:00,19.8567834666\n2014-04-10 03:50:00,21.1647467489\n2014-04-10 03:55:00,18.6428776404\n2014-04-10 04:00:00,21.3465490889\n2014-04-10 04:05:00,20.6263090217\n2014-04-10 04:10:00,19.3286931512\n2014-04-10 04:15:00,20.063303194\n2014-04-10 04:20:00,21.8622999189\n2014-04-10 04:25:00,18.8657478825\n2014-04-10 04:30:00,19.998141591\n2014-04-10 04:35:00,20.4979462244\n2014-04-10 04:40:00,18.5520584219\n2014-04-10 04:45:00,18.1740883545\n2014-04-10 04:50:00,18.0538398117\n2014-04-10 04:55:00,19.298771426400002\n2014-04-10 05:00:00,18.295789177899998\n2014-04-10 05:05:00,21.2150798102\n2014-04-10 05:10:00,21.9892781086\n2014-04-10 05:15:00,18.2452152869\n2014-04-10 05:20:00,19.7309051037\n2014-04-10 05:25:00,18.102928491900002\n2014-04-10 05:30:00,18.535963563\n2014-04-10 05:35:00,19.291690243599998\n2014-04-10 05:40:00,19.5747928522\n2014-04-10 05:45:00,21.759131785700003\n2014-04-10 05:50:00,19.583347235\n2014-04-10 05:55:00,19.985110636199998\n2014-04-10 06:00:00,18.9823334731\n2014-04-10 06:05:00,18.000500555\n2014-04-10 06:10:00,21.597337826900002\n2014-04-10 06:15:00,18.3268590281\n2014-04-10 06:20:00,21.856995364099998\n2014-04-10 06:25:00,18.5233764164\n2014-04-10 06:30:00,20.419513923\n2014-04-10 06:35:00,21.9976423514\n2014-04-10 06:40:00,18.5538583843\n2014-04-10 06:45:00,19.6957723398\n2014-04-10 06:50:00,21.1216946759\n2014-04-10 06:55:00,18.1287605994\n2014-04-10 07:00:00,20.7591310046\n2014-04-10 07:05:00,18.3214933516\n2014-04-10 07:10:00,18.9460805691\n2014-04-10 07:15:00,18.64030465\n2014-04-10 07:20:00,21.629345726599997\n2014-04-10 07:25:00,18.7218268671\n2014-04-10 07:30:00,18.1617363821\n2014-04-10 07:35:00,20.3505027138\n2014-04-10 07:40:00,19.384723701600002\n2014-04-10 07:45:00,19.6228248826\n2014-04-10 07:50:00,18.4762509795\n2014-04-10 07:55:00,20.992937965699998\n2014-04-10 08:00:00,20.4062145986\n2014-04-10 08:05:00,19.456868179\n2014-04-10 08:10:00,18.6862997751\n2014-04-10 08:15:00,20.3738069567\n2014-04-10 08:20:00,21.114389118\n2014-04-10 08:25:00,19.2495891355\n2014-04-10 08:30:00,18.1034415342\n2014-04-10 08:35:00,18.857375939\n2014-04-10 08:40:00,20.7295912756\n2014-04-10 08:45:00,21.9563855098\n2014-04-10 08:50:00,18.0535049576\n2014-04-10 08:55:00,19.2246142485\n2014-04-10 09:00:00,62.0434838381\n2014-04-10 09:05:00,65.50235031359999\n2014-04-10 09:10:00,66.7204350665\n2014-04-10 09:15:00,73.7237244505\n2014-04-10 09:20:00,62.2956268719\n2014-04-10 09:25:00,71.7690231217\n2014-04-10 09:30:00,66.5792677865\n2014-04-10 09:35:00,72.2331747555\n2014-04-10 09:40:00,68.1822697204\n2014-04-10 09:45:00,61.7342357283\n2014-04-10 09:50:00,74.0684000321\n2014-04-10 09:55:00,62.3251832627\n2014-04-10 10:00:00,79.1160479593\n2014-04-10 10:05:00,83.4614036807\n2014-04-10 10:10:00,71.07802726109999\n2014-04-10 10:15:00,78.43642538819999\n2014-04-10 10:20:00,82.63297886810001\n2014-04-10 10:25:00,85.1477594782\n2014-04-10 10:30:00,81.0815612606\n2014-04-10 10:35:00,74.1597495072\n2014-04-10 10:40:00,80.6973315192\n2014-04-10 10:45:00,80.7935002597\n2014-04-10 10:50:00,80.7034725079\n2014-04-10 10:55:00,83.0981219837\n2014-04-10 11:00:00,72.9576925143\n2014-04-10 11:05:00,73.29230922149999\n2014-04-10 11:10:00,81.7563747437\n2014-04-10 11:15:00,86.7385249523\n2014-04-10 11:20:00,78.9766977134\n2014-04-10 11:25:00,86.8447892067\n2014-04-10 11:30:00,86.4873079673\n2014-04-10 11:35:00,85.92787647690002\n2014-04-10 11:40:00,86.0382699042\n2014-04-10 11:45:00,85.8548620891\n2014-04-10 11:50:00,84.6075207558\n2014-04-10 11:55:00,82.62094535770001\n2014-04-10 12:00:00,72.3036622205\n2014-04-10 12:05:00,74.0271182055\n2014-04-10 12:10:00,74.0587356171\n2014-04-10 12:15:00,72.289792575\n2014-04-10 12:20:00,73.7785876208\n2014-04-10 12:25:00,86.61188380549999\n2014-04-10 12:30:00,82.5217235483\n2014-04-10 12:35:00,76.9007764908\n2014-04-10 12:40:00,84.5921276836\n2014-04-10 12:45:00,79.7181350971\n2014-04-10 12:50:00,74.1849037515\n2014-04-10 12:55:00,86.04865085969999\n2014-04-10 13:00:00,77.4000106779\n2014-04-10 13:05:00,83.16178406899999\n2014-04-10 13:10:00,76.6311106864\n2014-04-10 13:15:00,79.98193973720001\n2014-04-10 13:20:00,85.0396289741\n2014-04-10 13:25:00,74.4905555178\n2014-04-10 13:30:00,87.61498967850002\n2014-04-10 13:35:00,73.1059051366\n2014-04-10 13:40:00,80.5248119616\n2014-04-10 13:45:00,86.6356107716\n2014-04-10 13:50:00,87.1101906936\n2014-04-10 13:55:00,75.6955721077\n2014-04-10 14:00:00,74.300193119\n2014-04-10 14:05:00,83.5864356636\n2014-04-10 14:10:00,72.6680888567\n2014-04-10 14:15:00,79.75999484100001\n2014-04-10 14:20:00,84.7376160279\n2014-04-10 14:25:00,80.9601893166\n2014-04-10 14:30:00,75.0046118582\n2014-04-10 14:35:00,79.7888787415\n2014-04-10 14:40:00,86.7362319242\n2014-04-10 14:45:00,81.8714776291\n2014-04-10 14:50:00,83.5398399363\n2014-04-10 14:55:00,77.3765078239\n2014-04-10 15:00:00,75.01502025159999\n2014-04-10 15:05:00,76.0895452117\n2014-04-10 15:10:00,80.53006840409999\n2014-04-10 15:15:00,76.482788216\n2014-04-10 15:20:00,80.670662153\n2014-04-10 15:25:00,83.3238709212\n2014-04-10 15:30:00,83.7495300155\n2014-04-10 15:35:00,74.634242539\n2014-04-10 15:40:00,84.0060871152\n2014-04-10 15:45:00,82.7622157086\n2014-04-10 15:50:00,72.1913890899\n2014-04-10 15:55:00,72.9412545587\n2014-04-10 16:00:00,82.339833937\n2014-04-10 16:05:00,78.1391123656\n2014-04-10 16:10:00,74.3375212649\n2014-04-10 16:15:00,72.7102053429\n2014-04-10 16:20:00,74.55023031399999\n2014-04-10 16:25:00,87.3200557743\n2014-04-10 16:30:00,83.6408896743\n2014-04-10 16:35:00,80.4431322838\n2014-04-10 16:40:00,87.0644808367\n2014-04-10 16:45:00,81.9056097438\n2014-04-10 16:50:00,83.6101624807\n2014-04-10 16:55:00,76.52228217300001\n2014-04-10 17:00:00,81.42367823069999\n2014-04-10 17:05:00,74.2956073792\n2014-04-10 17:10:00,78.47170019\n2014-04-10 17:15:00,72.5318173476\n2014-04-10 17:20:00,75.46602042239999\n2014-04-10 17:25:00,73.1978699628\n2014-04-10 17:30:00,78.20443108159999\n2014-04-10 17:35:00,85.4885298066\n2014-04-10 17:40:00,78.0469157315\n2014-04-10 17:45:00,85.30620125829998\n2014-04-10 17:50:00,82.5039413197\n2014-04-10 17:55:00,80.1524403675\n2014-04-10 18:00:00,30.316101016199998\n2014-04-10 18:05:00,34.7017923315\n2014-04-10 18:10:00,29.1468795804\n2014-04-10 18:15:00,33.2090369371\n2014-04-10 18:20:00,32.775929020999996\n2014-04-10 18:25:00,31.622659670900003\n2014-04-10 18:30:00,30.338048289\n2014-04-10 18:35:00,31.556447936999998\n2014-04-10 18:40:00,34.3857388415\n2014-04-10 18:45:00,34.1552965478\n2014-04-10 18:50:00,34.8248333135\n2014-04-10 18:55:00,30.769870614600002\n2014-04-10 19:00:00,21.894225428400002\n2014-04-10 19:05:00,20.2438920534\n2014-04-10 19:10:00,24.384414638699997\n2014-04-10 19:15:00,21.6356664245\n2014-04-10 19:20:00,21.9706527152\n2014-04-10 19:25:00,24.226963330300002\n2014-04-10 19:30:00,22.5191597318\n2014-04-10 19:35:00,22.696460702\n2014-04-10 19:40:00,20.9495219657\n2014-04-10 19:45:00,22.3939956648\n2014-04-10 19:50:00,24.273573200500003\n2014-04-10 19:55:00,22.6630557915\n2014-04-10 20:00:00,19.4769563958\n2014-04-10 20:05:00,18.5597165968\n2014-04-10 20:10:00,19.809491826400002\n2014-04-10 20:15:00,20.7773321347\n2014-04-10 20:20:00,18.6065438059\n2014-04-10 20:25:00,20.929710145399998\n2014-04-10 20:30:00,20.575902789\n2014-04-10 20:35:00,21.640951421999997\n2014-04-10 20:40:00,18.550325730999997\n2014-04-10 20:45:00,21.6303504648\n2014-04-10 20:50:00,20.5655121326\n2014-04-10 20:55:00,19.9496879077\n2014-04-10 21:00:00,21.9664672049\n2014-04-10 21:05:00,18.729952438399998\n2014-04-10 21:10:00,20.2620938691\n2014-04-10 21:15:00,19.3764886913\n2014-04-10 21:20:00,20.2064732042\n2014-04-10 21:25:00,20.306105449300002\n2014-04-10 21:30:00,18.445910355\n2014-04-10 21:35:00,20.7436343318\n2014-04-10 21:40:00,20.6365079779\n2014-04-10 21:45:00,21.1790428184\n2014-04-10 21:50:00,18.4507745726\n2014-04-10 21:55:00,19.2811415046\n2014-04-10 22:00:00,20.6202188135\n2014-04-10 22:05:00,18.5647283409\n2014-04-10 22:10:00,20.7302748101\n2014-04-10 22:15:00,18.2536134969\n2014-04-10 22:20:00,19.3582923395\n2014-04-10 22:25:00,21.4073758495\n2014-04-10 22:30:00,21.1174184297\n2014-04-10 22:35:00,20.5987987319\n2014-04-10 22:40:00,21.5024562163\n2014-04-10 22:45:00,20.8570817615\n2014-04-10 22:50:00,20.0967748114\n2014-04-10 22:55:00,21.939912105999998\n2014-04-10 23:00:00,20.7834139666\n2014-04-10 23:05:00,20.4093865552\n2014-04-10 23:10:00,19.6392522545\n2014-04-10 23:15:00,21.613799045\n2014-04-10 23:20:00,19.1865194851\n2014-04-10 23:25:00,18.0403414557\n2014-04-10 23:30:00,18.7905691846\n2014-04-10 23:35:00,18.4416100754\n2014-04-10 23:40:00,19.279676082\n2014-04-10 23:45:00,21.3076049826\n2014-04-10 23:50:00,20.6100751142\n2014-04-10 23:55:00,18.6795081322\n2014-04-11 00:00:00,21.1552868844\n2014-04-11 00:05:00,20.016879464400002\n2014-04-11 00:10:00,20.050858496500002\n2014-04-11 00:15:00,19.4484487239\n2014-04-11 00:20:00,21.4584654593\n2014-04-11 00:25:00,19.2733092154\n2014-04-11 00:30:00,18.3765590427\n2014-04-11 00:35:00,19.2109159759\n2014-04-11 00:40:00,20.8614141851\n2014-04-11 00:45:00,20.6303275472\n2014-04-11 00:50:00,18.752068614200002\n2014-04-11 00:55:00,18.4471371964\n2014-04-11 01:00:00,20.6434630336\n2014-04-11 01:05:00,20.7055073426\n2014-04-11 01:10:00,19.4645985488\n2014-04-11 01:15:00,21.3712055341\n2014-04-11 01:20:00,21.9128208152\n2014-04-11 01:25:00,18.8225808938\n2014-04-11 01:30:00,20.3082748628\n2014-04-11 01:35:00,18.021385316\n2014-04-11 01:40:00,20.8522175841\n2014-04-11 01:45:00,19.6571284543\n2014-04-11 01:50:00,18.7730769076\n2014-04-11 01:55:00,21.0088876871\n2014-04-11 02:00:00,21.2425951902\n2014-04-11 02:05:00,18.4446660047\n2014-04-11 02:10:00,18.1639830474\n2014-04-11 02:15:00,19.336313766700002\n2014-04-11 02:20:00,20.503961863\n2014-04-11 02:25:00,21.1736781088\n2014-04-11 02:30:00,20.1842499865\n2014-04-11 02:35:00,20.3229951052\n2014-04-11 02:40:00,21.199432887\n2014-04-11 02:45:00,20.115373496900002\n2014-04-11 02:50:00,20.4446179609\n2014-04-11 02:55:00,20.0648693599\n2014-04-11 03:00:00,21.5218329335\n2014-04-11 03:05:00,18.9420664743\n2014-04-11 03:10:00,19.0559743382\n2014-04-11 03:15:00,18.5118458464\n2014-04-11 03:20:00,21.277867005999997\n2014-04-11 03:25:00,19.6471091622\n2014-04-11 03:30:00,19.3915757635\n2014-04-11 03:35:00,21.9253948683\n2014-04-11 03:40:00,21.7072134658\n2014-04-11 03:45:00,21.887950728499998\n2014-04-11 03:50:00,18.569195987\n2014-04-11 03:55:00,21.5650072526\n2014-04-11 04:00:00,19.3148383975\n2014-04-11 04:05:00,18.0506270808\n2014-04-11 04:10:00,19.565193343900003\n2014-04-11 04:15:00,20.0367854126\n2014-04-11 04:20:00,18.4328816943\n2014-04-11 04:25:00,20.1507104675\n2014-04-11 04:30:00,21.2778543367\n2014-04-11 04:35:00,19.5106038034\n2014-04-11 04:40:00,19.410579226099998\n2014-04-11 04:45:00,19.3552416809\n2014-04-11 04:50:00,21.6923777835\n2014-04-11 04:55:00,18.1950323952\n2014-04-11 05:00:00,19.780304568\n2014-04-11 05:05:00,19.0583978166\n2014-04-11 05:10:00,21.575228101599997\n2014-04-11 05:15:00,18.3842090543\n2014-04-11 05:20:00,19.6457710667\n2014-04-11 05:25:00,19.6272646081\n2014-04-11 05:30:00,21.5535776702\n2014-04-11 05:35:00,18.8619737802\n2014-04-11 05:40:00,20.579581641199997\n2014-04-11 05:45:00,18.5376245076\n2014-04-11 05:50:00,21.815902856300006\n2014-04-11 05:55:00,20.3720598371\n2014-04-11 06:00:00,20.5050269213\n2014-04-11 06:05:00,19.7350936066\n2014-04-11 06:10:00,19.3691308507\n2014-04-11 06:15:00,18.850705718\n2014-04-11 06:20:00,20.4159510153\n2014-04-11 06:25:00,21.818246981399998\n2014-04-11 06:30:00,19.4391638164\n2014-04-11 06:35:00,21.5326275546\n2014-04-11 06:40:00,18.5951052514\n2014-04-11 06:45:00,21.7445040835\n2014-04-11 06:50:00,19.4019451356\n2014-04-11 06:55:00,19.518908846400002\n2014-04-11 07:00:00,19.8513690281\n2014-04-11 07:05:00,20.872977079800002\n2014-04-11 07:10:00,20.878613734800002\n2014-04-11 07:15:00,19.918354338900002\n2014-04-11 07:20:00,20.0926115973\n2014-04-11 07:25:00,18.1200419511\n2014-04-11 07:30:00,19.217186806199997\n2014-04-11 07:35:00,19.3840682969\n2014-04-11 07:40:00,20.2349090749\n2014-04-11 07:45:00,20.2331990695\n2014-04-11 07:50:00,20.8395991909\n2014-04-11 07:55:00,20.8681091849\n2014-04-11 08:00:00,18.9408428968\n2014-04-11 08:05:00,21.0807486044\n2014-04-11 08:10:00,18.0784142722\n2014-04-11 08:15:00,20.8646475384\n2014-04-11 08:20:00,18.4082444141\n2014-04-11 08:25:00,20.9185928337\n2014-04-11 08:30:00,20.1084723623\n2014-04-11 08:35:00,19.7490180027\n2014-04-11 08:40:00,20.762665559000002\n2014-04-11 08:45:00,18.145483335\n2014-04-11 08:50:00,18.8938813027\n2014-04-11 08:55:00,20.4657605699\n2014-04-11 09:00:00,21.388861626500002\n2014-04-11 09:05:00,19.524430547799998\n2014-04-11 09:10:00,19.0350458905\n2014-04-11 09:15:00,20.0749457432\n2014-04-11 09:20:00,20.4892610095\n2014-04-11 09:25:00,19.6804121256\n2014-04-11 09:30:00,21.5068427306\n2014-04-11 09:35:00,20.0937548354\n2014-04-11 09:40:00,18.1432943503\n2014-04-11 09:45:00,18.8922158188\n2014-04-11 09:50:00,19.802588123699998\n2014-04-11 09:55:00,20.7909020761\n2014-04-11 10:00:00,18.8790089752\n2014-04-11 10:05:00,21.9050297589\n2014-04-11 10:10:00,19.274233032799998\n2014-04-11 10:15:00,20.1299208274\n2014-04-11 10:20:00,18.0758655389\n2014-04-11 10:25:00,21.5395628857\n2014-04-11 10:30:00,21.1553386141\n2014-04-11 10:35:00,18.7818320172\n2014-04-11 10:40:00,21.732946765\n2014-04-11 10:45:00,19.2633590552\n2014-04-11 10:50:00,20.7687451535\n2014-04-11 10:55:00,21.2759052721\n2014-04-11 11:00:00,20.9636578449\n2014-04-11 11:05:00,21.6703311361\n2014-04-11 11:10:00,21.4570990414\n2014-04-11 11:15:00,21.9784460564\n2014-04-11 11:20:00,18.7304456503\n2014-04-11 11:25:00,19.2190472049\n2014-04-11 11:30:00,20.5449034697\n2014-04-11 11:35:00,20.932188743599998\n2014-04-11 11:40:00,20.1384202182\n2014-04-11 11:45:00,18.2957134595\n2014-04-11 11:50:00,21.3663809072\n2014-04-11 11:55:00,21.843497424099997\n2014-04-11 12:00:00,19.6220673753\n2014-04-11 12:05:00,18.8992499268\n2014-04-11 12:10:00,18.0772550198\n2014-04-11 12:15:00,18.949196144400002\n2014-04-11 12:20:00,20.7996750994\n2014-04-11 12:25:00,21.646357550700003\n2014-04-11 12:30:00,18.374052265699998\n2014-04-11 12:35:00,20.2130367486\n2014-04-11 12:40:00,20.782124994\n2014-04-11 12:45:00,19.1055232844\n2014-04-11 12:50:00,20.2795881567\n2014-04-11 12:55:00,20.860993704000002\n2014-04-11 13:00:00,21.3508769725\n2014-04-11 13:05:00,19.8099994033\n2014-04-11 13:10:00,20.9914288757\n2014-04-11 13:15:00,19.207131887\n2014-04-11 13:20:00,18.8521869871\n2014-04-11 13:25:00,18.7492549844\n2014-04-11 13:30:00,19.435490927300002\n2014-04-11 13:35:00,18.1435187272\n2014-04-11 13:40:00,19.1319673507\n2014-04-11 13:45:00,20.6088912978\n2014-04-11 13:50:00,20.591676188599997\n2014-04-11 13:55:00,18.294215226\n2014-04-11 14:00:00,19.1496624683\n2014-04-11 14:05:00,20.2782306587\n2014-04-11 14:10:00,19.27420855\n2014-04-11 14:15:00,19.671952096800002\n2014-04-11 14:20:00,20.8512430285\n2014-04-11 14:25:00,18.0370673178\n2014-04-11 14:30:00,19.1055741764\n2014-04-11 14:35:00,18.5694889751\n2014-04-11 14:40:00,18.5104367311\n2014-04-11 14:45:00,21.8361608658\n2014-04-11 14:50:00,19.506241326199998\n2014-04-11 14:55:00,20.1083543396\n2014-04-11 15:00:00,20.9352875483\n2014-04-11 15:05:00,18.1897898994\n2014-04-11 15:10:00,18.964090554200002\n2014-04-11 15:15:00,21.3285911494\n2014-04-11 15:20:00,21.4479624527\n2014-04-11 15:25:00,19.4918036826\n2014-04-11 15:30:00,19.4994463986\n2014-04-11 15:35:00,21.0275875084\n2014-04-11 15:40:00,19.180280907\n2014-04-11 15:45:00,18.4683763246\n2014-04-11 15:50:00,19.030141801\n2014-04-11 15:55:00,19.5493789265\n2014-04-11 16:00:00,18.2088188384\n2014-04-11 16:05:00,19.9147210168\n2014-04-11 16:10:00,20.9600300511\n2014-04-11 16:15:00,20.0549805779\n2014-04-11 16:20:00,18.2875813621\n2014-04-11 16:25:00,19.7605985254\n2014-04-11 16:30:00,20.8356184322\n2014-04-11 16:35:00,18.232386616\n2014-04-11 16:40:00,18.239388758900002\n2014-04-11 16:45:00,19.4824056127\n2014-04-11 16:50:00,18.7798558565\n2014-04-11 16:55:00,21.7391231652\n2014-04-11 17:00:00,20.325374415\n2014-04-11 17:05:00,19.1493015976\n2014-04-11 17:10:00,20.8191069165\n2014-04-11 17:15:00,19.4997162054\n2014-04-11 17:20:00,18.5284625775\n2014-04-11 17:25:00,18.9489289194\n2014-04-11 17:30:00,20.570989137799998\n2014-04-11 17:35:00,18.207504424\n2014-04-11 17:40:00,19.0907561602\n2014-04-11 17:45:00,18.8332459106\n2014-04-11 17:50:00,18.8045404427\n2014-04-11 17:55:00,20.7310496479\n2014-04-11 18:00:00,21.303267667\n2014-04-11 18:05:00,20.8634664323\n2014-04-11 18:10:00,20.5829112632\n2014-04-11 18:15:00,21.6658070873\n2014-04-11 18:20:00,18.2335695217\n2014-04-11 18:25:00,18.6699323439\n2014-04-11 18:30:00,19.6576274227\n2014-04-11 18:35:00,19.489806574\n2014-04-11 18:40:00,19.6722064119\n2014-04-11 18:45:00,18.8258196202\n2014-04-11 18:50:00,18.5980132623\n2014-04-11 18:55:00,20.0367729898\n2014-04-11 19:00:00,21.7122100963\n2014-04-11 19:05:00,19.567877849400002\n2014-04-11 19:10:00,18.1734128565\n2014-04-11 19:15:00,20.824669371600002\n2014-04-11 19:20:00,19.1644196221\n2014-04-11 19:25:00,18.9803800292\n2014-04-11 19:30:00,19.297032002799998\n2014-04-11 19:35:00,20.8952620956\n2014-04-11 19:40:00,21.2752775475\n2014-04-11 19:45:00,20.3522242694\n2014-04-11 19:50:00,19.2899150149\n2014-04-11 19:55:00,19.2419129325\n2014-04-11 20:00:00,18.4972333996\n2014-04-11 20:05:00,21.7332041929\n2014-04-11 20:10:00,20.552557595899998\n2014-04-11 20:15:00,18.1078984794\n2014-04-11 20:20:00,20.6494683807\n2014-04-11 20:25:00,19.788613696800002\n2014-04-11 20:30:00,21.8902318522\n2014-04-11 20:35:00,21.2762752992\n2014-04-11 20:40:00,18.6852630153\n2014-04-11 20:45:00,20.8804444755\n2014-04-11 20:50:00,19.9422640153\n2014-04-11 20:55:00,18.7481806547\n2014-04-11 21:00:00,20.7949596293\n2014-04-11 21:05:00,20.1895503148\n2014-04-11 21:10:00,18.1214955151\n2014-04-11 21:15:00,20.5863518021\n2014-04-11 21:20:00,20.5399483594\n2014-04-11 21:25:00,18.576340644200002\n2014-04-11 21:30:00,19.395950908\n2014-04-11 21:35:00,20.343595883\n2014-04-11 21:40:00,18.5551320564\n2014-04-11 21:45:00,21.4108935113\n2014-04-11 21:50:00,18.1099441852\n2014-04-11 21:55:00,18.4113496599\n2014-04-11 22:00:00,18.4644276794\n2014-04-11 22:05:00,20.112428503900002\n2014-04-11 22:10:00,20.4804560487\n2014-04-11 22:15:00,19.614963186\n2014-04-11 22:20:00,19.1546673107\n2014-04-11 22:25:00,21.2372695025\n2014-04-11 22:30:00,18.2731439349\n2014-04-11 22:35:00,19.1211674445\n2014-04-11 22:40:00,18.1564623152\n2014-04-11 22:45:00,18.0555605399\n2014-04-11 22:50:00,19.413519547699998\n2014-04-11 22:55:00,18.7792946498\n2014-04-11 23:00:00,19.0734634194\n2014-04-11 23:05:00,21.2837886298\n2014-04-11 23:10:00,18.651920385\n2014-04-11 23:15:00,21.1209334686\n2014-04-11 23:20:00,20.7002024926\n2014-04-11 23:25:00,19.3057821006\n2014-04-11 23:30:00,20.1862245807\n2014-04-11 23:35:00,19.777742439100003\n2014-04-11 23:40:00,18.513581262\n2014-04-11 23:45:00,21.628741286900002\n2014-04-11 23:50:00,20.2784718703\n2014-04-11 23:55:00,21.520960183200003\n2014-04-12 00:00:00,21.2953060473\n2014-04-12 00:05:00,18.3191037012\n2014-04-12 00:10:00,18.8290826641\n2014-04-12 00:15:00,18.5810444575\n2014-04-12 00:20:00,21.3231181311\n2014-04-12 00:25:00,21.4497865058\n2014-04-12 00:30:00,20.1118860392\n2014-04-12 00:35:00,18.41671229\n2014-04-12 00:40:00,18.5424664742\n2014-04-12 00:45:00,21.2541952498\n2014-04-12 00:50:00,21.7167605461\n2014-04-12 00:55:00,18.797902740399998\n2014-04-12 01:00:00,18.0445503059\n2014-04-12 01:05:00,19.3238116206\n2014-04-12 01:10:00,18.1219975586\n2014-04-12 01:15:00,21.3118996643\n2014-04-12 01:20:00,19.966049028900002\n2014-04-12 01:25:00,20.5674431151\n2014-04-12 01:30:00,19.6459395045\n2014-04-12 01:35:00,19.3820301881\n2014-04-12 01:40:00,18.8888016523\n2014-04-12 01:45:00,21.0821301882\n2014-04-12 01:50:00,20.7821903377\n2014-04-12 01:55:00,19.442915938\n2014-04-12 02:00:00,19.2844645372\n2014-04-12 02:05:00,18.0049715146\n2014-04-12 02:10:00,18.2542085202\n2014-04-12 02:15:00,20.4930220996\n2014-04-12 02:20:00,20.0584292409\n2014-04-12 02:25:00,19.7392128179\n2014-04-12 02:30:00,21.310008963199998\n2014-04-12 02:35:00,20.015592817599998\n2014-04-12 02:40:00,19.5379743256\n2014-04-12 02:45:00,18.6450253901\n2014-04-12 02:50:00,21.2827520329\n2014-04-12 02:55:00,20.304993000499998\n2014-04-12 03:00:00,18.369839863699998\n2014-04-12 03:05:00,20.595593592\n2014-04-12 03:10:00,19.700282982\n2014-04-12 03:15:00,21.245544894400002\n2014-04-12 03:20:00,21.675658388000002\n2014-04-12 03:25:00,20.4018632527\n2014-04-12 03:30:00,20.9264512773\n2014-04-12 03:35:00,18.2263633904\n2014-04-12 03:40:00,20.24102182\n2014-04-12 03:45:00,21.021359913399998\n2014-04-12 03:50:00,19.9870485979\n2014-04-12 03:55:00,20.374200358\n2014-04-12 04:00:00,21.5957927423\n2014-04-12 04:05:00,18.7923982881\n2014-04-12 04:10:00,18.3929860302\n2014-04-12 04:15:00,20.7625744526\n2014-04-12 04:20:00,21.2913956221\n2014-04-12 04:25:00,21.4019607543\n2014-04-12 04:30:00,20.5665779884\n2014-04-12 04:35:00,21.3328536727\n2014-04-12 04:40:00,20.8026568229\n2014-04-12 04:45:00,18.349507663599997\n2014-04-12 04:50:00,21.0481740315\n2014-04-12 04:55:00,18.7174387582\n2014-04-12 05:00:00,18.946437370399998\n2014-04-12 05:05:00,19.578602508\n2014-04-12 05:10:00,19.2582682653\n2014-04-12 05:15:00,19.2866069532\n2014-04-12 05:20:00,18.6770380968\n2014-04-12 05:25:00,19.1754841884\n2014-04-12 05:30:00,18.0786503599\n2014-04-12 05:35:00,19.8916437868\n2014-04-12 05:40:00,21.0743638351\n2014-04-12 05:45:00,21.4489894769\n2014-04-12 05:50:00,21.2817142358\n2014-04-12 05:55:00,19.665830875999998\n2014-04-12 06:00:00,20.9217059247\n2014-04-12 06:05:00,19.1515630964\n2014-04-12 06:10:00,18.2222498909\n2014-04-12 06:15:00,20.703886101600002\n2014-04-12 06:20:00,20.595184658900003\n2014-04-12 06:25:00,21.206517581900002\n2014-04-12 06:30:00,20.464424826800002\n2014-04-12 06:35:00,18.6275664999\n2014-04-12 06:40:00,21.4126495682\n2014-04-12 06:45:00,20.5090111521\n2014-04-12 06:50:00,21.2304387961\n2014-04-12 06:55:00,21.096428481500002\n2014-04-12 07:00:00,19.191457948900002\n2014-04-12 07:05:00,18.298211899400002\n2014-04-12 07:10:00,18.706017636400002\n2014-04-12 07:15:00,18.3714493373\n2014-04-12 07:20:00,18.9736497283\n2014-04-12 07:25:00,19.8381290921\n2014-04-12 07:30:00,21.627242419899996\n2014-04-12 07:35:00,21.4880750237\n2014-04-12 07:40:00,20.8743992604\n2014-04-12 07:45:00,18.0964494382\n2014-04-12 07:50:00,19.3655568053\n2014-04-12 07:55:00,20.729393705899998\n2014-04-12 08:00:00,18.5161155874\n2014-04-12 08:05:00,21.2043514001\n2014-04-12 08:10:00,21.65829472\n2014-04-12 08:15:00,19.4164177866\n2014-04-12 08:20:00,20.8233722475\n2014-04-12 08:25:00,18.5928165307\n2014-04-12 08:30:00,20.7632657965\n2014-04-12 08:35:00,18.0858216491\n2014-04-12 08:40:00,18.6030860272\n2014-04-12 08:45:00,20.8395257864\n2014-04-12 08:50:00,20.8474008915\n2014-04-12 08:55:00,20.564650823399997\n2014-04-12 09:00:00,67.6921507316\n2014-04-12 09:05:00,70.3787500399\n2014-04-12 09:10:00,71.7236908567\n2014-04-12 09:15:00,74.3441505629\n2014-04-12 09:20:00,73.2855180291\n2014-04-12 09:25:00,72.0056651549\n2014-04-12 09:30:00,70.64870222729999\n2014-04-12 09:35:00,69.0085154179\n2014-04-12 09:40:00,62.8402799976\n2014-04-12 09:45:00,63.4515730525\n2014-04-12 09:50:00,72.3558020251\n2014-04-12 09:55:00,72.125055606\n2014-04-12 10:00:00,79.3764025311\n2014-04-12 10:05:00,76.65079885979999\n2014-04-12 10:10:00,70.2440267253\n2014-04-12 10:15:00,74.917786148\n2014-04-12 10:20:00,76.3683274854\n2014-04-12 10:25:00,77.3798687614\n2014-04-12 10:30:00,84.2631177697\n2014-04-12 10:35:00,71.5271698849\n2014-04-12 10:40:00,77.892814595\n2014-04-12 10:45:00,75.5501540488\n2014-04-12 10:50:00,85.2063228102\n2014-04-12 10:55:00,83.21612953270001\n2014-04-12 11:00:00,78.5464502258\n2014-04-12 11:05:00,87.4671589712\n2014-04-12 11:10:00,79.7436618719\n2014-04-12 11:15:00,74.225841437\n2014-04-12 11:20:00,80.4086310988\n2014-04-12 11:25:00,75.1655764993\n2014-04-12 11:30:00,81.6879194086\n2014-04-12 11:35:00,86.4770485414\n2014-04-12 11:40:00,84.07170216600001\n2014-04-12 11:45:00,75.9123953324\n2014-04-12 11:50:00,76.28923957149999\n2014-04-12 11:55:00,72.6699595819\n2014-04-12 12:00:00,76.4819967079\n2014-04-12 12:05:00,73.3938183987\n2014-04-12 12:10:00,79.8951900938\n2014-04-12 12:15:00,83.233553008\n2014-04-12 12:20:00,83.9180759057\n2014-04-12 12:25:00,72.8649247547\n2014-04-12 12:30:00,77.3463672186\n2014-04-12 12:35:00,76.5188153668\n2014-04-12 12:40:00,73.5804026016\n2014-04-12 12:45:00,77.7061815257\n2014-04-12 12:50:00,76.69697480010001\n2014-04-12 12:55:00,82.0534052842\n2014-04-12 13:00:00,86.1121707375\n2014-04-12 13:05:00,79.2584409418\n2014-04-12 13:10:00,83.92649557\n2014-04-12 13:15:00,74.318325194\n2014-04-12 13:20:00,86.2987453874\n2014-04-12 13:25:00,74.4236498476\n2014-04-12 13:30:00,75.05560122109999\n2014-04-12 13:35:00,73.6857320364\n2014-04-12 13:40:00,76.936402855\n2014-04-12 13:45:00,80.8191658913\n2014-04-12 13:50:00,87.7868318851\n2014-04-12 13:55:00,84.6735620213\n2014-04-12 14:00:00,78.0832246716\n2014-04-12 14:05:00,81.2096386767\n2014-04-12 14:10:00,81.9689937945\n2014-04-12 14:15:00,85.1595476855\n2014-04-12 14:20:00,83.7792069717\n2014-04-12 14:25:00,81.104764816\n2014-04-12 14:30:00,82.7029585001\n2014-04-12 14:35:00,83.93065291069999\n2014-04-12 14:40:00,74.1267466915\n2014-04-12 14:45:00,75.20367743109999\n2014-04-12 14:50:00,83.0133637898\n2014-04-12 14:55:00,85.602699865\n2014-04-12 15:00:00,78.54744246050001\n2014-04-12 15:05:00,87.6774034484\n2014-04-12 15:10:00,75.4564233342\n2014-04-12 15:15:00,78.6664333077\n2014-04-12 15:20:00,78.0556193543\n2014-04-12 15:25:00,86.8839009582\n2014-04-12 15:30:00,76.565321247\n2014-04-12 15:35:00,79.5318889352\n2014-04-12 15:40:00,74.9950214747\n2014-04-12 15:45:00,80.33948855050001\n2014-04-12 15:50:00,85.7176438141\n2014-04-12 15:55:00,76.86389348979999\n2014-04-12 16:00:00,84.9725100071\n2014-04-12 16:05:00,86.5808190793\n2014-04-12 16:10:00,73.1671857542\n2014-04-12 16:15:00,84.1026311037\n2014-04-12 16:20:00,76.0853488943\n2014-04-12 16:25:00,74.8050989745\n2014-04-12 16:30:00,81.6178015659\n2014-04-12 16:35:00,83.28948194350001\n2014-04-12 16:40:00,78.3160254047\n2014-04-12 16:45:00,72.6266398699\n2014-04-12 16:50:00,86.5391062317\n2014-04-12 16:55:00,83.691789981\n2014-04-12 17:00:00,76.34663958979999\n2014-04-12 17:05:00,79.9497909912\n2014-04-12 17:10:00,72.44465682069999\n2014-04-12 17:15:00,77.4284947763\n2014-04-12 17:20:00,80.3605329109\n2014-04-12 17:25:00,80.275547016\n2014-04-12 17:30:00,75.330929121\n2014-04-12 17:35:00,84.4279254386\n2014-04-12 17:40:00,76.7817650522\n2014-04-12 17:45:00,81.2865291568\n2014-04-12 17:50:00,76.3443262924\n2014-04-12 17:55:00,78.8026557076\n2014-04-12 18:00:00,30.128087816999997\n2014-04-12 18:05:00,32.8512435648\n2014-04-12 18:10:00,31.5237338523\n2014-04-12 18:15:00,28.9031451993\n2014-04-12 18:20:00,28.9802503975\n2014-04-12 18:25:00,31.815253529699998\n2014-04-12 18:30:00,29.972639793400003\n2014-04-12 18:35:00,32.5442628596\n2014-04-12 18:40:00,31.412421372199997\n2014-04-12 18:45:00,32.9882806137\n2014-04-12 18:50:00,34.8953224141\n2014-04-12 18:55:00,32.1839050834\n2014-04-12 19:00:00,23.6874548447\n2014-04-12 19:05:00,23.5336223725\n2014-04-12 19:10:00,24.289622814899996\n2014-04-12 19:15:00,21.118798886700002\n2014-04-12 19:20:00,23.866423519899996\n2014-04-12 19:25:00,24.2167299672\n2014-04-12 19:30:00,21.919576952199996\n2014-04-12 19:35:00,21.5658953688\n2014-04-12 19:40:00,24.425119535500002\n2014-04-12 19:45:00,22.971793783000003\n2014-04-12 19:50:00,21.8654294544\n2014-04-12 19:55:00,23.707386889299997\n2014-04-12 20:00:00,19.6791248649\n2014-04-12 20:05:00,19.1545652427\n2014-04-12 20:10:00,20.6600993803\n2014-04-12 20:15:00,20.751204286900002\n2014-04-12 20:20:00,21.8142573296\n2014-04-12 20:25:00,20.3039838025\n2014-04-12 20:30:00,21.7685462046\n2014-04-12 20:35:00,19.7071774581\n2014-04-12 20:40:00,20.7887079067\n2014-04-12 20:45:00,19.285904270899998\n2014-04-12 20:50:00,20.0107863748\n2014-04-12 20:55:00,21.944482339\n2014-04-12 21:00:00,18.954499700699998\n2014-04-12 21:05:00,21.3429143971\n2014-04-12 21:10:00,19.2233177202\n2014-04-12 21:15:00,18.2250210368\n2014-04-12 21:20:00,18.5282489787\n2014-04-12 21:25:00,21.084239017\n2014-04-12 21:30:00,19.139715421\n2014-04-12 21:35:00,20.715541913699997\n2014-04-12 21:40:00,20.8966201789\n2014-04-12 21:45:00,19.4735000846\n2014-04-12 21:50:00,19.9951943445\n2014-04-12 21:55:00,19.7092206418\n2014-04-12 22:00:00,21.810313794899997\n2014-04-12 22:05:00,19.298304043599998\n2014-04-12 22:10:00,18.7512761202\n2014-04-12 22:15:00,19.481055238499998\n2014-04-12 22:20:00,20.6979137606\n2014-04-12 22:25:00,20.809408624\n2014-04-12 22:30:00,21.7170576309\n2014-04-12 22:35:00,21.5476838661\n2014-04-12 22:40:00,19.1716692231\n2014-04-12 22:45:00,19.839680813\n2014-04-12 22:50:00,21.0092254553\n2014-04-12 22:55:00,21.686948614899997\n2014-04-12 23:00:00,19.3523749923\n2014-04-12 23:05:00,19.7815630658\n2014-04-12 23:10:00,21.602059879000002\n2014-04-12 23:15:00,19.4376668063\n2014-04-12 23:20:00,19.9258769768\n2014-04-12 23:25:00,21.6221672219\n2014-04-12 23:30:00,21.2130449927\n2014-04-12 23:35:00,18.9773666531\n2014-04-12 23:40:00,19.3028857024\n2014-04-12 23:45:00,19.4155619802\n2014-04-12 23:50:00,21.655110874699997\n2014-04-12 23:55:00,21.9999581274\n2014-04-13 00:00:00,21.0960172086\n2014-04-13 00:05:00,19.93730521\n2014-04-13 00:10:00,18.0406952723\n2014-04-13 00:15:00,20.7899522264\n2014-04-13 00:20:00,19.557444657999998\n2014-04-13 00:25:00,20.5319458809\n2014-04-13 00:30:00,20.426775853800002\n2014-04-13 00:35:00,19.9233282263\n2014-04-13 00:40:00,21.7775495909\n2014-04-13 00:45:00,18.0925853814\n2014-04-13 00:50:00,20.8485299379\n2014-04-13 00:55:00,19.6393594732\n"
  },
  {
    "path": "workspace/anomaly_detector/datasets/selected/seasonal/exchange-2_cpc_results.csv",
    "content": "timestamp,value\r\n2011-07-01 00:00:01,0.0819647355164\r\n2011-07-01 01:00:01,0.0989722357526\r\n2011-07-01 02:00:01,0.0653139485883\r\n2011-07-01 03:00:01,0.0706628339533\r\n2011-07-01 04:00:01,0.102490196078\r\n2011-07-01 05:00:01,0.123394648829\r\n2011-07-01 06:00:01,0.153045112782\r\n2011-07-01 07:00:01,0.148321513002\r\n2011-07-01 08:00:01,0.218257756563\r\n2011-07-01 09:00:01,0.226597938144\r\n2011-07-01 10:00:01,0.174045801527\r\n2011-07-01 11:00:01,0.159901960784\r\n2011-07-01 12:00:01,0.145626477541\r\n2011-07-01 13:00:01,0.143828571429\r\n2011-07-01 14:00:01,0.136604651163\r\n2011-07-01 15:00:01,0.134952494062\r\n2011-07-01 16:00:01,0.112707774799\r\n2011-07-01 17:00:01,0.103763277693\r\n2011-07-01 18:00:01,0.0987147766323\r\n2011-07-01 19:00:01,0.0916247582205\r\n2011-07-01 20:00:01,0.0804951690821\r\n2011-07-01 21:00:01,0.0845783926219\r\n2011-07-01 22:00:01,0.0866643159379\r\n2011-07-01 23:00:01,0.0988316679477\r\n2011-07-02 00:00:01,0.11795614722\r\n2011-07-02 01:00:01,0.0909769230769\r\n2011-07-02 02:00:01,0.0843243243243\r\n2011-07-02 03:00:01,0.0694744820616\r\n2011-07-02 04:00:01,0.0712875751503\r\n2011-07-02 05:00:01,0.0738199181446\r\n2011-07-02 06:00:01,0.113498134328\r\n2011-07-02 07:00:01,0.141458064516\r\n2011-07-02 08:00:01,0.189128787879\r\n2011-07-02 09:00:01,0.151339712919\r\n2011-07-02 10:00:01,0.155231143552\r\n2011-07-02 11:00:01,0.14298245614\r\n2011-07-02 12:00:01,0.144218181818\r\n2011-07-02 13:00:01,0.143366500829\r\n2011-07-02 14:00:01,0.152361516035\r\n2011-07-02 15:00:01,0.143050228311\r\n2011-07-02 16:00:01,0.102183828611\r\n2011-07-02 17:00:01,0.0924731182796\r\n2011-07-02 18:00:01,0.0764556962025\r\n2011-07-02 19:00:01,0.0743530192435\r\n2011-07-02 20:00:01,0.0709893842887\r\n2011-07-02 21:00:01,0.0571908831909\r\n2011-07-02 22:00:01,0.0629096362955\r\n2011-07-02 23:00:01,0.065544768069\r\n2011-07-03 00:00:01,0.0567160161507\r\n2011-07-03 01:00:01,0.0587607170694\r\n2011-07-03 02:00:01,0.0598788546256\r\n2011-07-03 03:00:01,0.0512832369942\r\n2011-07-03 04:00:01,0.0591086065574\r\n2011-07-03 05:00:01,0.0691399082569\r\n2011-07-03 06:00:01,0.091963099631\r\n2011-07-03 07:00:01,0.124621212121\r\n2011-07-03 08:00:01,0.218095238095\r\n2011-07-03 09:00:01,0.172130325815\r\n2011-07-03 10:00:01,0.142936288089\r\n2011-07-03 11:00:01,0.147341389728\r\n2011-07-03 12:00:01,0.123138297872\r\n2011-07-03 13:00:01,0.123795986622\r\n2011-07-03 14:00:01,0.121458797327\r\n2011-07-03 15:00:01,0.114387596899\r\n2011-07-03 16:00:01,0.0894912891986\r\n2011-07-03 17:00:01,0.0797851697852\r\n2011-07-03 18:00:01,0.0724256756757\r\n2011-07-03 19:00:01,0.0671052631579\r\n2011-07-03 20:00:01,0.0625718496684\r\n2011-07-03 21:00:01,0.0512057335582\r\n2011-07-03 22:00:01,0.050217721519\r\n2011-07-03 23:00:01,0.0530833333333\r\n2011-07-04 00:00:01,0.0454658136745\r\n2011-07-04 01:00:01,0.0482011892963\r\n2011-07-04 02:00:01,0.0424707080998\r\n2011-07-04 03:00:01,0.0361947700631\r\n2011-07-04 04:00:01,0.0423479561316\r\n2011-07-04 05:00:01,0.0616081330869\r\n2011-07-04 06:00:01,0.0973949579832\r\n2011-07-04 07:00:01,0.122106918239\r\n2011-07-04 08:00:01,0.182614213198\r\n2011-07-04 09:00:01,0.176124567474\r\n2011-07-04 10:00:01,0.146950672646\r\n2011-07-04 11:00:01,0.121809045226\r\n2011-07-04 12:00:01,0.127351694915\r\n2011-07-04 13:00:01,0.111390532544\r\n2011-07-04 14:00:01,0.123798816568\r\n2011-07-04 15:00:01,0.110897571278\r\n2011-07-04 16:00:01,0.0864069952305\r\n2011-07-04 17:00:01,0.0857901085645\r\n2011-07-04 18:00:01,0.0712333965844\r\n2011-07-04 19:00:01,0.0664840182648\r\n2011-07-04 20:00:01,0.0633661075766\r\n2011-07-04 21:00:01,0.0602728613569\r\n2011-07-04 22:00:01,0.0604935424354\r\n2011-07-04 23:00:01,0.059634551495\r\n2011-07-05 00:00:01,0.0555023094688\r\n2011-07-05 01:00:01,0.0426701570681\r\n2011-07-05 02:00:01,0.0454550792719\r\n2011-07-05 03:00:01,0.0372700871249\r\n2011-07-05 04:00:01,0.0448206751055\r\n2011-07-05 05:00:01,0.0649965493444\r\n2011-07-05 06:00:01,0.0948186528497\r\n2011-07-05 07:00:01,0.11772173913\r\n2011-07-05 08:00:01,0.176833333333\r\n2011-07-05 09:00:01,0.146557377049\r\n2011-07-05 10:00:01,0.133574297189\r\n2011-07-05 11:00:01,0.139591836735\r\n2011-07-05 12:00:01,0.113243243243\r\n2011-07-05 13:00:01,0.121060070671\r\n2011-07-05 14:00:01,0.119309210526\r\n2011-07-05 15:00:01,0.105715846995\r\n2011-07-05 16:00:01,0.0908553546592\r\n2011-07-05 17:00:01,0.0824758220503\r\n2011-07-05 18:00:01,0.0744980370163\r\n2011-07-05 19:00:01,0.0757240204429\r\n2011-07-05 20:00:01,0.0704836829837\r\n2011-07-05 21:00:01,0.0659228486647\r\n2011-07-05 22:00:01,0.0508973252804\r\n2011-07-05 23:00:01,0.0550694444444\r\n2011-07-06 00:00:01,0.0592647765497\r\n2011-07-06 01:00:01,0.0506581469649\r\n2011-07-06 02:00:01,0.0409549982824\r\n2011-07-06 03:00:01,0.0354873115116\r\n2011-07-06 04:00:01,0.0584235976789\r\n2011-07-06 05:00:01,0.0979736408567\r\n2011-07-06 06:00:01,0.109025423729\r\n2011-07-06 07:00:01,0.11874025974\r\n2011-07-06 08:00:01,0.171501416431\r\n2011-07-06 09:00:01,0.177857142857\r\n2011-07-06 10:00:01,0.138678414097\r\n2011-07-06 11:00:01,0.140806451613\r\n2011-07-06 12:00:01,0.153417721519\r\n2011-07-06 13:00:01,0.11140070922\r\n2011-07-06 14:00:01,0.114154929577\r\n2011-07-06 15:00:01,0.117304261645\r\n2011-07-06 16:00:01,0.0871753246753\r\n2011-07-06 17:00:01,0.0905656934307\r\n2011-07-06 18:00:01,0.0828233970754\r\n2011-07-06 19:00:01,0.0885174625802\r\n2011-07-06 20:00:01,0.0849336128581\r\n2011-07-06 21:00:01,0.0927850877193\r\n2011-07-06 22:00:01,0.080655983976\r\n2011-07-06 23:00:01,0.0737714285714\r\n2011-07-07 00:00:01,0.0589785227868\r\n2011-07-07 01:00:01,0.0518829376035\r\n2011-07-07 02:00:01,0.0399152920196\r\n2011-07-07 03:00:01,0.0365565345081\r\n2011-07-07 04:00:01,0.0422852912142\r\n2011-07-07 05:00:01,0.0599111111111\r\n2011-07-07 06:00:01,0.06836\r\n2011-07-07 07:00:01,0.0785412474849\r\n2011-07-07 08:00:01,0.1369\r\n2011-07-07 09:00:01,0.134372469636\r\n2011-07-07 10:00:01,0.130298102981\r\n2011-07-07 11:00:01,0.0940255591054\r\n2011-07-07 12:00:01,0.0949642004773\r\n2011-07-07 13:00:01,0.0797727272727\r\n2011-07-07 14:00:01,0.0865840938722\r\n2011-07-07 15:00:01,0.0828489795918\r\n2011-07-07 16:00:01,0.0643440860215\r\n2011-07-07 17:00:01,0.0631866776316\r\n2011-07-07 18:00:01,0.0588312368973\r\n2011-07-07 19:00:01,0.0553018372703\r\n2011-07-07 20:00:01,0.0636177474403\r\n2011-07-07 21:00:01,0.0696616541353\r\n2011-07-07 22:00:01,0.0672093023256\r\n2011-07-07 23:00:01,0.0647668393782\r\n2011-07-08 00:00:01,0.0529286858974\r\n2011-07-08 01:00:01,0.043\r\n2011-07-08 02:00:01,0.0370847315436\r\n2011-07-08 03:00:01,0.029056261343\r\n2011-07-08 04:00:01,0.0390342793955\r\n2011-07-08 05:00:01,0.0547750865052\r\n2011-07-08 06:00:01,0.077652733119\r\n2011-07-08 07:00:01,0.105649202733\r\n2011-07-08 08:00:01,0.106728624535\r\n2011-07-08 09:00:01,0.13031358885\r\n2011-07-08 10:00:01,0.114\r\n2011-07-08 11:00:01,0.0982986111111\r\n2011-07-08 12:00:01,0.0896160558464\r\n2011-07-08 13:00:01,0.082061482821\r\n2011-07-08 14:00:01,0.0775255102041\r\n2011-07-08 15:00:01,0.080700525394\r\n2011-07-08 16:00:01,0.0630213706706\r\n2011-07-08 17:00:01,0.0710957642726\r\n2011-07-08 18:00:01,0.0692333019755\r\n2011-07-08 19:00:01,0.0578288770053\r\n2011-07-08 20:00:01,0.0509116607774\r\n2011-07-08 21:00:01,0.0566599025974\r\n2011-07-08 22:00:01,0.051887966805\r\n2011-07-08 23:00:01,0.0498945703743\r\n2011-07-09 00:00:01,0.05091367713\r\n2011-07-09 01:00:01,0.0543451568895\r\n2011-07-09 02:00:01,0.0465873959572\r\n2011-07-09 03:00:01,0.0408384458078\r\n2011-07-09 04:00:01,0.0569039323046\r\n2011-07-09 05:00:01,0.065549898167\r\n2011-07-09 06:00:01,0.0830152671756\r\n2011-07-09 07:00:01,0.103198924731\r\n2011-07-09 08:00:01,0.137385398981\r\n2011-07-09 09:00:01,0.124793187348\r\n2011-07-09 10:00:01,0.108936170213\r\n2011-07-09 11:00:01,0.110889423077\r\n2011-07-09 12:00:01,0.102679180887\r\n2011-07-09 13:00:01,0.0846708860759\r\n2011-07-09 14:00:01,0.074122983871\r\n2011-07-09 15:00:01,0.0688360175695\r\n2011-07-09 16:00:01,0.0609321533923\r\n2011-07-09 17:00:01,0.0511821086262\r\n2011-07-09 18:00:01,0.0732703213611\r\n2011-07-09 19:00:01,0.0747021445592\r\n2011-07-09 20:00:01,0.0693601190476\r\n2011-07-09 21:00:01,0.069770879527\r\n2011-07-09 22:00:01,0.0528718226068\r\n2011-07-09 23:00:01,0.0605546403075\r\n2011-07-10 00:00:01,0.0679034582133\r\n2011-07-10 01:00:01,0.0553818443804\r\n2011-07-10 02:00:01,0.0410645339217\r\n2011-07-10 03:00:01,0.03905\r\n2011-07-10 04:00:01,0.0452134831461\r\n2011-07-10 05:00:01,0.0568603465851\r\n2011-07-10 06:00:01,0.0712981199642\r\n2011-07-10 07:00:01,0.088981042654\r\n2011-07-10 08:00:01,0.14926335175\r\n2011-07-10 09:00:01,0.12248\r\n2011-07-10 10:00:01,0.116993318486\r\n2011-07-10 11:00:01,0.111520342612\r\n2011-07-10 12:00:01,0.100423728814\r\n2011-07-10 13:00:01,0.0807338129496\r\n2011-07-10 14:00:01,0.0885483870968\r\n2011-07-10 15:00:01,0.0845520833333\r\n2011-07-10 16:00:01,0.0803118503119\r\n2011-07-10 17:00:01,0.0752053063803\r\n2011-07-10 18:00:01,0.0604114134041\r\n2011-07-10 19:00:01,0.0611792138574\r\n2011-07-10 20:00:01,0.0581619758759\r\n2011-07-10 21:00:01,0.0557387444515\r\n2011-07-10 22:00:01,0.0557292271935\r\n2011-07-10 23:00:01,0.0554871794872\r\n2011-07-11 00:00:01,0.0435956467141\r\n2011-07-11 01:00:01,0.0410140708394\r\n2011-07-11 02:00:01,0.0390708661417\r\n2011-07-11 03:00:01,0.0484085051546\r\n2011-07-11 04:00:01,0.0548306233062\r\n2011-07-11 05:00:01,0.0798846787479\r\n2011-07-11 06:00:01,0.0904545454545\r\n2011-07-11 07:00:01,0.109911504425\r\n2011-07-11 08:00:01,0.14953125\r\n2011-07-11 09:00:01,0.128966789668\r\n2011-07-11 10:00:01,0.120981132075\r\n2011-07-11 11:00:01,0.10642599278\r\n2011-07-11 12:00:01,0.0980687830688\r\n2011-07-11 13:00:01,0.0895955882353\r\n2011-07-11 14:00:01,0.0831072555205\r\n2011-07-11 15:00:01,0.0761529933481\r\n2011-07-11 16:00:01,0.0695591836735\r\n2011-07-11 17:00:01,0.0800690184049\r\n2011-07-11 18:00:01,0.0713066871637\r\n2011-07-11 19:00:01,0.0689016172507\r\n2011-07-11 20:00:01,0.0657076101469\r\n2011-07-11 21:00:01,0.0488832772166\r\n2011-07-11 22:00:01,0.0446334716459\r\n2011-07-11 23:00:01,0.0437057808456\r\n2011-07-12 00:00:01,0.0405548387097\r\n2011-07-12 01:00:01,0.0395984286338\r\n2011-07-12 02:00:01,0.0376497277677\r\n2011-07-12 03:00:01,0.0273855730502\r\n2011-07-12 04:00:01,0.0399748638458\r\n2011-07-12 05:00:01,0.0512578222778\r\n2011-07-12 06:00:01,0.0768638392857\r\n2011-07-12 07:00:01,0.0844540229885\r\n2011-07-12 08:00:01,0.134916317992\r\n2011-07-12 09:00:01,0.130771812081\r\n2011-07-12 10:00:01,0.122636363636\r\n2011-07-12 11:00:01,0.116319218241\r\n2011-07-12 12:00:01,0.113074935401\r\n2011-07-12 13:00:01,0.0957581227437\r\n2011-07-12 14:00:01,0.0948387096774\r\n2011-07-12 15:00:01,0.0883890954151\r\n2011-07-12 16:00:01,0.0805347091932\r\n2011-07-12 17:00:01,0.0838054474708\r\n2011-07-12 18:00:01,0.0699471598415\r\n2011-07-12 19:00:01,0.0719724437999\r\n2011-07-12 20:00:01,0.0716866359447\r\n2011-07-12 21:00:01,0.0751682134571\r\n2011-07-12 22:00:01,0.0701829697396\r\n2011-07-12 23:00:01,0.0624853458382\r\n2011-07-13 00:00:01,0.0591021967526\r\n2011-07-13 01:00:01,0.0564490339773\r\n2011-07-13 02:00:01,0.0495853829937\r\n2011-07-13 03:00:01,0.0428013833992\r\n2011-07-13 04:00:01,0.06172\r\n2011-07-13 05:00:01,0.0787394957983\r\n2011-07-13 06:00:01,0.104476190476\r\n2011-07-13 07:00:01,0.137398843931\r\n2011-07-13 08:00:01,0.173003095975\r\n2011-07-13 09:00:01,0.160666666667\r\n2011-07-13 10:00:01,0.140447761194\r\n2011-07-13 11:00:01,0.14541322314\r\n2011-07-13 12:00:01,0.105280665281\r\n2011-07-13 13:00:01,0.109710144928\r\n2011-07-13 14:00:01,0.119234234234\r\n2011-07-13 15:00:01,0.109706521739\r\n2011-07-13 16:00:01,0.1125\r\n2011-07-13 17:00:01,0.0806234203875\r\n2011-07-13 18:00:01,0.0751756954612\r\n2011-07-13 19:00:01,0.0643361473523\r\n2011-07-13 20:00:01,0.0632748143147\r\n2011-07-13 21:00:01,0.0527571669477\r\n2011-07-13 22:00:01,0.0587525562372\r\n2011-07-13 23:00:01,0.0675053153792\r\n2011-07-14 00:00:01,0.0630647709321\r\n2011-07-14 01:00:01,0.0542712671029\r\n2011-07-14 02:00:01,0.0454437869822\r\n2011-07-14 03:00:01,0.0427843915344\r\n2011-07-14 04:00:01,0.0754888039323\r\n2011-07-14 05:00:01,0.12162962963\r\n2011-07-14 06:00:01,0.104147465438\r\n2011-07-14 07:00:01,0.11685300207\r\n2011-07-14 08:00:01,0.163841463415\r\n2011-07-14 09:00:01,0.134169491525\r\n2011-07-14 10:00:01,0.119638554217\r\n2011-07-14 11:00:01,0.105258215962\r\n2011-07-14 12:00:01,0.139400428266\r\n2011-07-14 13:00:01,0.172899728997\r\n2011-07-14 14:00:01,0.143414285714\r\n2011-07-14 15:00:01,0.113112980769\r\n2011-07-14 16:00:01,0.102432082794\r\n2011-07-14 17:00:01,0.0945905420992\r\n2011-07-14 18:00:01,0.0876892109501\r\n2011-07-14 19:00:01,0.0769917743831\r\n2011-07-14 20:00:01,0.0660641579272\r\n2011-07-14 21:00:01,0.0686515748031\r\n2011-07-14 22:00:01,0.0630867518494\r\n2011-07-14 23:00:01,0.0668716289105\r\n2011-07-15 00:00:01,0.066568\r\n2011-07-15 01:00:01,0.064297188755\r\n2011-07-15 02:00:01,0.0545993031359\r\n2011-07-15 03:00:01,0.0488020833333\r\n2011-07-15 04:00:01,0.0657415254237\r\n2011-07-15 05:00:01,0.0831349628055\r\n2011-07-15 06:00:01,0.0972619047619\r\n2011-07-15 07:00:01,0.128293650794\r\n2011-07-15 08:00:01,0.142421052632\r\n2011-07-15 09:00:01,0.143630573248\r\n2011-07-15 10:00:01,0.107873754153\r\n2011-07-15 11:00:01,0.128459119497\r\n2011-07-15 12:00:01,0.153944954128\r\n2011-07-15 13:00:01,0.121011904762\r\n2011-07-15 14:00:01,0.122206349206\r\n2011-07-15 15:00:01,0.119244114002\r\n2011-07-15 16:00:01,0.125719257541\r\n2011-07-15 17:00:01,0.105527472527\r\n2011-07-15 18:00:01,0.107925531915\r\n2011-07-15 19:00:01,0.101285140562\r\n2011-07-15 20:00:01,0.0782247557003\r\n2011-07-15 21:00:01,0.0794422535211\r\n2011-07-15 22:00:01,0.0666718386346\r\n2011-07-15 23:00:01,0.0679684763573\r\n2011-07-16 00:00:01,0.0628316953317\r\n2011-07-16 01:00:01,0.0576279974076\r\n2011-07-16 02:00:01,0.0515857226448\r\n2011-07-16 03:00:01,0.0459335873707\r\n2011-07-16 04:00:01,0.0593970893971\r\n2011-07-16 05:00:01,0.0690847322142\r\n2011-07-16 06:00:01,0.0845133819951\r\n2011-07-16 07:00:01,0.128930987821\r\n2011-07-16 08:00:01,0.133377777778\r\n2011-07-16 09:00:01,0.133666666667\r\n2011-07-16 10:00:01,0.110243902439\r\n2011-07-16 11:00:01,0.124468085106\r\n2011-07-16 12:00:01,0.129587426326\r\n2011-07-16 13:00:01,0.116791277259\r\n2011-07-16 14:00:01,0.131853658537\r\n2011-07-16 15:00:01,0.12354799514\r\n2011-07-16 16:00:01,0.106280991736\r\n2011-07-16 17:00:01,0.0875408163265\r\n2011-07-16 18:00:01,0.0848959032908\r\n2011-07-16 19:00:01,0.0850235849057\r\n2011-07-16 20:00:01,0.088818263205\r\n2011-07-16 21:00:01,0.0806446140797\r\n2011-07-16 22:00:01,0.0916818181818\r\n2011-07-16 23:00:01,0.0951011433597\r\n2011-07-17 00:00:01,0.0823130608175\r\n2011-07-17 01:00:01,0.0839484126984\r\n2011-07-17 02:00:01,0.0714049586777\r\n2011-07-17 03:00:01,0.0668453865337\r\n2011-07-17 04:00:01,0.089832149774\r\n2011-07-17 05:00:01,0.0864338235294\r\n2011-07-17 06:00:01,0.0963191763192\r\n2011-07-17 07:00:01,0.133951219512\r\n2011-07-17 08:00:01,0.129698113208\r\n2011-07-17 09:00:01,0.113882352941\r\n2011-07-17 10:00:01,0.103264033264\r\n2011-07-17 11:00:01,0.123671232877\r\n2011-07-17 12:00:01,0.118403361345\r\n2011-07-17 13:00:01,0.120855263158\r\n2011-07-17 14:00:01,0.128103932584\r\n2011-07-17 15:00:01,0.123614864865\r\n2011-07-17 16:00:01,0.103994169096\r\n2011-07-17 17:00:01,0.0921825023518\r\n2011-07-17 18:00:01,0.0784539007092\r\n2011-07-17 19:00:01,0.0691608391608\r\n2011-07-17 20:00:01,0.0860685033507\r\n2011-07-17 21:00:01,0.0812937347437\r\n2011-07-17 22:00:01,0.0766594360087\r\n2011-07-17 23:00:01,0.0688845553822\r\n2011-07-18 00:00:01,0.0831017369727\r\n2011-07-18 01:00:01,0.0562208915502\r\n2011-07-18 02:00:01,0.0542358688067\r\n2011-07-18 03:00:01,0.0529631794272\r\n2011-07-18 04:00:01,0.057367657723\r\n2011-07-18 05:00:01,0.080813810111\r\n2011-07-18 06:00:01,0.0828771384137\r\n2011-07-18 07:00:01,0.098482428115\r\n2011-07-18 08:00:01,0.133706720978\r\n2011-07-18 09:00:01,0.125448504983\r\n2011-07-18 10:00:01,0.112797202797\r\n2011-07-18 11:00:01,0.133260869565\r\n2011-07-18 12:00:01,0.114242424242\r\n2011-07-18 13:00:01,0.109731958763\r\n2011-07-18 14:00:01,0.110627118644\r\n2011-07-18 15:00:01,0.13235915493\r\n2011-07-18 16:00:01,0.108308004053\r\n2011-07-18 17:00:01,0.112766934558\r\n2011-07-18 18:00:01,0.0867071057192\r\n2011-07-18 19:00:01,0.0666476624857\r\n2011-07-18 20:00:01,0.0610063291139\r\n2011-07-18 21:00:01,0.0633564814815\r\n2011-07-18 22:00:01,0.0577608297743\r\n2011-07-18 23:00:01,0.0592826221398\r\n2011-07-19 00:00:01,0.058606557377\r\n2011-07-19 01:00:01,0.060243902439\r\n2011-07-19 02:00:01,0.0581115202525\r\n2011-07-19 03:00:01,0.0536248012719\r\n2011-07-19 04:00:01,0.0759214285714\r\n2011-07-19 05:00:01,0.0956813819578\r\n2011-07-19 06:00:01,0.145669456067\r\n2011-07-19 07:00:01,0.0781401273885\r\n2011-07-19 08:00:01,0.126855670103\r\n2011-07-19 09:00:01,0.13587628866\r\n2011-07-19 10:00:01,0.123628691983\r\n2011-07-19 11:00:01,0.11277992278\r\n2011-07-19 12:00:01,0.108265306122\r\n2011-07-19 13:00:01,0.101017964072\r\n2011-07-19 14:00:01,0.119724310777\r\n2011-07-19 15:00:01,0.105197740113\r\n2011-07-19 16:00:01,0.104038997214\r\n2011-07-19 17:00:01,0.0876279650437\r\n2011-07-19 18:00:01,0.0786526122823\r\n2011-07-19 19:00:01,0.0785493682733\r\n2011-07-19 20:00:01,0.0720879940343\r\n2011-07-19 21:00:01,0.069072079536\r\n2011-07-19 22:00:01,0.0646453546454\r\n2011-07-19 23:00:01,0.0581058328322\r\n2011-07-20 00:00:01,0.0471131270011\r\n2011-07-20 01:00:01,0.0470863683663\r\n2011-07-20 02:00:01,0.0441111667501\r\n2011-07-20 03:00:01,0.0398035363458\r\n2011-07-20 04:00:01,0.0531552962298\r\n2011-07-20 05:00:01,0.0831355181577\r\n2011-07-20 06:00:01,0.0858263971463\r\n2011-07-20 07:00:01,0.11486013986\r\n2011-07-20 08:00:01,0.140924092409\r\n2011-07-20 09:00:01,0.145905797101\r\n2011-07-20 10:00:01,0.1198046875\r\n2011-07-20 11:00:01,0.105261324042\r\n2011-07-20 12:00:01,0.114985163205\r\n2011-07-20 13:00:01,0.12178807947\r\n2011-07-20 14:00:01,0.123\r\n2011-07-20 15:00:01,0.101586666667\r\n2011-07-20 16:00:01,0.105029069767\r\n2011-07-20 17:00:01,0.0886812627291\r\n2011-07-20 18:00:01,0.076380952381\r\n2011-07-20 19:00:01,0.0720992028344\r\n2011-07-20 20:00:01,0.0846785486951\r\n2011-07-20 21:00:01,0.086369168357\r\n2011-07-20 22:00:01,0.0858272208639\r\n2011-07-20 23:00:01,0.0881660899654\r\n2011-07-21 00:00:01,0.0725509670674\r\n2011-07-21 01:00:01,0.0504150702427\r\n2011-07-21 02:00:01,0.0539956092206\r\n2011-07-21 03:00:01,0.0498293891029\r\n2011-07-21 04:00:01,0.0638204456094\r\n2011-07-21 06:00:01,0.0896588235294\r\n2011-07-21 07:00:01,0.0983348017621\r\n2011-07-21 08:00:01,0.156194690265\r\n2011-07-21 09:00:01,0.113283018868\r\n2011-07-21 10:00:01,0.121479289941\r\n2011-07-21 11:00:01,0.117583333333\r\n2011-07-21 12:00:01,0.1255754858\r\n2011-07-21 13:00:01,0.125865237366\r\n2011-07-21 14:00:01,0.129348230912\r\n2011-07-21 15:00:01,0.122638190955\r\n2011-07-21 16:00:01,0.102814070352\r\n2011-07-21 17:00:01,0.08875\r\n2011-07-21 18:00:01,0.0884564740307\r\n2011-07-21 19:00:01,0.0861376146789\r\n2011-07-21 20:00:01,0.0786027190332\r\n2011-07-21 21:00:01,0.0796965317919\r\n2011-07-21 22:00:01,0.0731962761831\r\n2011-07-21 23:00:01,0.0628108465608\r\n2011-07-22 00:00:01,0.057536\r\n2011-07-22 01:00:01,0.0501960784314\r\n2011-07-22 02:00:01,0.0441025641026\r\n2011-07-22 03:00:01,0.0395596330275\r\n2011-07-22 04:00:01,0.0612002152853\r\n2011-07-22 05:00:01,0.0658501208703\r\n2011-07-22 06:00:01,0.0704761904762\r\n2011-07-22 07:00:01,0.0902773497689\r\n2011-07-22 08:00:01,0.123726708075\r\n2011-07-22 09:00:01,0.125622119816\r\n2011-07-22 10:00:01,0.122831460674\r\n2011-07-22 11:00:01,0.10141955836\r\n2011-07-22 12:00:01,0.114628820961\r\n2011-07-22 13:00:01,0.125454545455\r\n2011-07-22 14:00:01,0.125721311475\r\n2011-07-22 15:00:01,0.117919191919\r\n2011-07-22 16:00:01,0.108773784355\r\n2011-07-22 17:00:01,0.0938828202582\r\n2011-07-22 18:00:01,0.0868648648649\r\n2011-07-22 19:00:01,0.0619215686275\r\n2011-07-22 20:00:01,0.0658013245033\r\n2011-07-22 21:00:01,0.0715577275504\r\n2011-07-22 22:00:01,0.071060197664\r\n2011-07-22 23:00:01,0.0672566371681\r\n2011-07-23 00:00:01,0.0576546530393\r\n2011-07-23 01:00:01,0.0647784200385\r\n2011-07-23 02:00:01,0.0429639309984\r\n2011-07-23 03:00:01,0.0369493177388\r\n2011-07-23 04:00:01,0.0667547633682\r\n2011-07-23 05:00:01,0.0781133671743\r\n2011-07-23 06:00:01,0.0569483101392\r\n2011-07-23 07:00:01,0.087599469496\r\n2011-07-23 08:00:01,0.128206521739\r\n2011-07-23 09:00:01,0.123089770355\r\n2011-07-23 10:00:01,0.110472222222\r\n2011-07-23 11:00:01,0.118646616541\r\n2011-07-23 12:00:01,0.124588477366\r\n2011-07-23 13:00:01,0.117697478992\r\n2011-07-23 14:00:01,0.125595984944\r\n2011-07-23 15:00:01,0.112482690406\r\n2011-07-23 16:00:01,0.0839690301548\r\n2011-07-23 17:00:01,0.0694921583271\r\n2011-07-23 18:00:01,0.0620277953253\r\n2011-07-23 19:00:01,0.0605489260143\r\n2011-07-23 20:00:01,0.0551867219917\r\n2011-07-23 21:00:01,0.050596432553\r\n2011-07-23 22:00:01,0.0578482513337\r\n2011-07-23 23:00:01,0.0493202416918\r\n2011-07-24 00:00:01,0.0517379958246\r\n2011-07-24 01:00:01,0.0433963202387\r\n2011-07-24 02:00:01,0.0352476572959\r\n2011-07-24 03:00:01,0.029256302521\r\n2011-07-24 04:00:01,0.0570788614092\r\n2011-07-24 05:00:01,0.0647458628842\r\n2011-07-24 06:00:01,0.0498529411765\r\n2011-07-24 07:00:01,0.0787314017228\r\n2011-07-24 08:00:01,0.106375464684\r\n2011-07-24 09:00:01,0.10786\r\n2011-07-24 10:00:01,0.111375358166\r\n2011-07-24 11:00:01,0.108213166144\r\n2011-07-24 12:00:01,0.104781144781\r\n2011-07-24 13:00:01,0.102242424242\r\n2011-07-24 14:00:01,0.136987087518\r\n2011-07-24 15:00:01,0.107728571429\r\n2011-07-24 16:00:01,0.081749837978\r\n2011-07-24 17:00:01,0.0739983713355\r\n2011-07-24 18:00:01,0.0703389830508\r\n2011-07-24 19:00:01,0.0576832018038\r\n2011-07-24 20:00:01,0.0548765432099\r\n2011-07-24 21:00:01,0.0514774417452\r\n2011-07-24 22:00:01,0.0539698492462\r\n2011-07-24 23:00:01,0.0497205284553\r\n2011-07-25 00:00:01,0.0473873873874\r\n2011-07-25 01:00:01,0.0363285910968\r\n2011-07-25 02:00:01,0.0298359310911\r\n2011-07-25 03:00:01,0.0268430335097\r\n2011-07-25 04:00:01,0.0470331753555\r\n2011-07-25 05:00:01,0.0762164750958\r\n2011-07-25 06:00:01,0.06735\r\n2011-07-25 07:00:01,0.0817728055077\r\n2011-07-25 08:00:01,0.135342465753\r\n2011-07-25 09:00:01,0.10347107438\r\n2011-07-25 10:00:01,0.104528301887\r\n2011-07-25 11:00:01,0.110830188679\r\n2011-07-25 12:00:01,0.114666666667\r\n2011-07-25 13:00:01,0.115458715596\r\n2011-07-25 14:00:01,0.119266409266\r\n2011-07-25 15:00:01,0.122647058824\r\n2011-07-25 16:00:01,0.106795366795\r\n2011-07-25 17:00:01,0.0827593360996\r\n2011-07-25 18:00:01,0.0724266144814\r\n2011-07-25 19:00:01,0.0713251879699\r\n2011-07-25 20:00:01,0.063962529274\r\n2011-07-25 21:00:01,0.0686650185414\r\n2011-07-25 22:00:01,0.0754482323232\r\n2011-07-25 23:00:01,0.0718975705844\r\n2011-07-26 00:00:01,0.0666692015209\r\n2011-07-26 01:00:01,0.0498381877023\r\n2011-07-26 02:00:01,0.0471448352257\r\n2011-07-26 03:00:01,0.041893349311\r\n2011-07-26 04:00:01,0.0506090863704\r\n2011-07-26 05:00:01,0.0692014971928\r\n2011-07-26 06:00:01,0.0692014971928\r\n2011-07-26 07:00:01,0.0724771838331\r\n2011-07-26 08:00:01,0.137659090909\r\n2011-07-26 09:00:01,0.110408805031\r\n2011-07-26 10:00:01,0.115993589744\r\n2011-07-26 11:00:01,0.105376712329\r\n2011-07-26 12:00:01,0.109313432836\r\n2011-07-26 13:00:01,0.0955578512397\r\n2011-07-26 14:00:01,0.115785498489\r\n2011-07-26 15:00:01,0.109773869347\r\n2011-07-26 16:00:01,0.0816580756014\r\n2011-07-26 17:00:01,0.0825984911987\r\n2011-07-26 18:00:01,0.0901673640167\r\n2011-07-26 19:00:01,0.0776923076923\r\n2011-07-26 20:00:01,0.0674664224664\r\n2011-07-26 21:00:01,0.0651013941698\r\n2011-07-26 22:00:01,0.0701068376068\r\n2011-07-26 23:00:01,0.0780705543557\r\n2011-07-27 00:00:01,0.0710584752036\r\n2011-07-27 01:00:01,0.070609939759\r\n2011-07-27 02:00:01,0.0600668449198\r\n2011-07-27 03:00:01,0.0437102272727\r\n2011-07-27 04:00:01,0.0566702470462\r\n2011-07-27 05:00:01,0.10780075188\r\n2011-07-27 06:00:01,0.07596\r\n2011-07-27 07:00:01,0.0859259259259\r\n2011-07-27 08:00:01,0.124216589862\r\n2011-07-27 09:00:01,0.0986075949367\r\n2011-07-27 10:00:01,0.11397260274\r\n2011-07-27 11:00:01,0.118854625551\r\n2011-07-27 12:00:01,0.110099800399\r\n2011-07-27 13:00:01,0.114842657343\r\n2011-07-27 14:00:01,0.120839260313\r\n2011-07-27 15:00:01,0.11123880597\r\n2011-07-27 16:00:01,0.10975257732\r\n2011-07-27 17:00:01,0.104363207547\r\n2011-07-27 18:00:01,0.0920824881677\r\n2011-07-27 19:00:01,0.087886563133\r\n2011-07-27 20:00:01,0.0919845360825\r\n2011-07-27 21:00:01,0.0936326737697\r\n2011-07-27 22:00:01,0.104090189873\r\n2011-07-27 23:00:01,0.0873058082575\r\n2011-07-28 00:00:01,0.078776328987\r\n2011-07-28 01:00:01,0.0860120391272\r\n2011-07-28 02:00:01,0.074702467344\r\n2011-07-28 03:00:01,0.070370096225\r\n2011-07-28 04:00:01,0.0783658787256\r\n2011-07-28 05:00:01,0.110487421384\r\n2011-07-28 06:00:01,0.0803856041131\r\n2011-07-28 07:00:01,0.0619230769231\r\n2011-07-28 08:00:01,0.1198\r\n2011-07-28 09:00:01,0.113601398601\r\n2011-07-28 10:00:01,0.124456824513\r\n2011-07-28 11:00:01,0.107990074442\r\n2011-07-28 12:00:01,0.10199488491\r\n2011-07-28 13:00:01,0.104290780142\r\n2011-07-28 14:00:01,0.119104234528\r\n2011-07-28 15:00:01,0.118211206897\r\n2011-07-28 16:00:01,0.118211206897\r\n2011-07-28 17:00:01,0.118211206897\r\n2011-07-28 18:00:01,0.0885949110561\r\n2011-07-28 19:00:01,0.0801347449471\r\n2011-07-28 20:00:01,0.0899249374479\r\n2011-07-28 21:00:01,0.0973896499239\r\n2011-07-28 22:00:01,0.0805698005698\r\n2011-07-28 23:00:01,0.073049074819\r\n2011-07-29 00:00:01,0.0734753857458\r\n2011-07-29 01:00:01,0.0722496749025\r\n2011-07-29 02:00:01,0.0732498394348\r\n2011-07-29 03:00:01,0.0676326129666\r\n2011-07-29 04:00:01,0.0724244415243\r\n2011-07-29 05:00:01,0.0896695821186\r\n2011-07-29 06:00:01,0.0784363636364\r\n2011-07-29 07:00:01,0.096213740458\r\n2011-07-29 08:00:01,0.156112311015\r\n2011-07-29 09:00:01,0.11890052356\r\n2011-07-29 10:00:01,0.132742857143\r\n2011-07-29 11:00:01,0.114931880109\r\n2011-07-29 12:00:01,0.128949880668\r\n2011-07-29 13:00:01,0.122662807525\r\n2011-07-29 14:00:01,0.117895953757\r\n2011-07-29 15:00:01,0.113000987167\r\n2011-07-29 16:00:01,0.0856885245902\r\n2011-07-29 17:00:01,0.0841629711752\r\n2011-07-29 18:00:01,0.0767937701396\r\n2011-07-29 19:00:01,0.0789443005181\r\n2011-07-29 20:00:01,0.0845344129555\r\n2011-07-29 21:00:01,0.0913032031593\r\n2011-07-29 22:00:01,0.0925146689019\r\n2011-07-29 23:00:01,0.101165644172\r\n2011-07-30 00:00:01,0.0886551155116\r\n2011-07-30 01:00:01,0.0797572435395\r\n2011-07-30 02:00:01,0.0728994544037\r\n2011-07-30 03:00:01,0.0740775780511\r\n2011-07-30 04:00:01,0.0722648238966\r\n2011-07-30 05:00:01,0.0683806818182\r\n2011-07-30 06:00:01,0.0948214285714\r\n2011-07-30 07:00:01,0.0938634046891\r\n2011-07-30 08:00:01,0.130261437908\r\n2011-07-30 09:00:01,0.111311827957\r\n2011-07-30 10:00:01,0.0984196891192\r\n2011-07-30 11:00:01,0.116709265176\r\n2011-07-30 12:00:01,0.113532818533\r\n2011-07-30 13:00:01,0.125555555556\r\n2011-07-30 14:00:01,0.115386533666\r\n2011-07-30 15:00:01,0.1102342918\r\n2011-07-30 16:00:01,0.0929906542056\r\n2011-07-30 17:00:01,0.0869395348837\r\n2011-07-30 18:00:01,0.0907490864799\r\n2011-07-30 19:00:01,0.0838778311599\r\n2011-07-30 20:00:01,0.0804285714286\r\n2011-07-30 21:00:01,0.0788680555556\r\n2011-07-30 22:00:01,0.0821278089888\r\n2011-07-30 23:00:01,0.0842050520059\r\n2011-07-31 00:00:01,0.080601387818\r\n2011-07-31 01:00:01,0.0680497925311\r\n2011-07-31 02:00:01,0.0631529726119\r\n2011-07-31 03:00:01,0.0551472556894\r\n2011-07-31 04:00:01,0.0601333333333\r\n2011-07-31 05:00:01,0.0610477941176\r\n2011-07-31 06:00:01,0.0709155429383\r\n2011-07-31 07:00:01,0.083761682243\r\n2011-07-31 08:00:01,0.12181663837\r\n2011-07-31 09:00:01,0.118093841642\r\n2011-07-31 10:00:01,0.0936153846154\r\n2011-07-31 11:00:01,0.0994202898551\r\n2011-07-31 12:00:01,0.0964052287582\r\n2011-07-31 13:00:01,0.100709459459\r\n2011-07-31 14:00:01,0.115931034483\r\n2011-07-31 15:00:01,0.105705329154\r\n2011-07-31 16:00:01,0.103412969283\r\n2011-07-31 17:00:01,0.0962058823529\r\n2011-07-31 18:00:01,0.0869072948328\r\n2011-07-31 19:00:01,0.0886683209264\r\n2011-07-31 20:00:01,0.0852365930599\r\n2011-07-31 21:00:01,0.0830542986425\r\n2011-07-31 22:00:01,0.0863148788927\r\n2011-07-31 23:00:01,0.0808888888889\r\n2011-08-01 00:00:01,0.0844655929722\r\n2011-08-01 01:00:01,0.0788088235294\r\n2011-08-01 02:00:01,0.0846559633028\r\n2011-08-01 03:00:01,0.0568824940048\r\n2011-08-01 04:00:01,0.0727328714396\r\n2011-08-01 05:00:01,0.0826939471441\r\n2011-08-01 06:00:01,0.084090382387\r\n2011-08-01 07:00:01,0.0908172362556\r\n2011-08-01 08:00:01,0.135628865979\r\n2011-08-01 09:00:01,0.125981308411\r\n2011-08-01 10:00:01,0.121021505376\r\n2011-08-01 11:00:01,0.127050147493\r\n2011-08-01 12:00:01,0.105648854962\r\n2011-08-01 13:00:01,0.111731748727\r\n2011-08-01 14:00:01,0.11498392283\r\n2011-08-01 15:00:01,0.112511415525\r\n2011-08-01 16:00:01,0.0994946808511\r\n2011-08-01 17:00:01,0.106244665718\r\n2011-08-01 18:00:01,0.0854833424358\r\n2011-08-01 19:00:01,0.0872797427653\r\n2011-08-01 20:00:01,0.0819312169312\r\n2011-08-01 21:00:01,0.0881\r\n2011-08-01 22:00:01,0.0955753337572\r\n2011-08-01 23:00:01,0.0987902592302\r\n2011-08-02 00:00:01,0.0889931350114\r\n2011-08-02 01:00:01,0.084732061762\r\n2011-08-02 02:00:01,0.0879424920128\r\n2011-08-02 03:00:01,0.0664155251142\r\n2011-08-02 04:00:01,0.0831809145129\r\n2011-08-02 05:00:01,0.0926953125\r\n2011-08-02 06:00:01,0.0890781796966\r\n2011-08-02 07:00:01,0.116447166922\r\n2011-08-02 08:00:01,0.150505050505\r\n2011-08-02 09:00:01,0.120997442455\r\n2011-08-02 10:00:01,0.12171641791\r\n2011-08-02 11:00:01,0.13024691358\r\n2011-08-02 12:00:01,0.12217032967\r\n2011-08-02 13:00:01,0.120845070423\r\n2011-08-02 14:00:01,0.137652671756\r\n2011-08-02 15:00:01,0.124419354839\r\n2011-08-02 16:00:01,0.119978448276\r\n2011-08-02 17:00:01,0.102033898305\r\n2011-08-02 18:00:01,0.0973706896552\r\n2011-08-02 19:00:01,0.0990192791282\r\n2011-08-02 20:00:01,0.104033546326\r\n2011-08-02 21:00:01,0.103341483293\r\n2011-08-02 22:00:01,0.104043126685\r\n2011-08-02 23:00:01,0.0923657817109\r\n2011-08-03 00:00:01,0.0908755364807\r\n2011-08-03 01:00:01,0.0832804614275\r\n2011-08-03 02:00:01,0.0718162983425\r\n2011-08-03 03:00:01,0.0641237113402\r\n2011-08-03 04:00:01,0.0730695970696\r\n2011-08-03 05:00:01,0.0877640203933\r\n2011-08-03 06:00:01,0.0793930348259\r\n2011-08-03 07:00:01,0.113240310078\r\n2011-08-03 08:00:01,0.135289079229\r\n2011-08-03 09:00:01,0.140438596491\r\n2011-08-03 10:00:01,0.132291262136\r\n2011-08-03 11:00:01,0.0986138613861\r\n2011-08-03 12:00:01,0.107055702918\r\n2011-08-03 13:00:01,0.122393320965\r\n2011-08-03 14:00:01,0.118733974359\r\n2011-08-03 15:00:01,0.131208333333\r\n2011-08-03 16:00:01,0.120161137441\r\n2011-08-03 17:00:01,0.102637465051\r\n2011-08-03 18:00:01,0.0927382875606\r\n2011-08-03 19:00:01,0.110486641221\r\n2011-08-03 20:00:01,0.0917786561265\r\n2011-08-03 21:00:01,0.0896810631229\r\n2011-08-03 22:00:01,0.0854006586169\r\n2011-08-03 23:00:01,0.0681545998911\r\n2011-08-04 00:00:01,0.0555156537753\r\n2011-08-04 01:00:01,0.0530039700044\r\n2011-08-04 02:00:01,0.0474216027875\r\n2011-08-04 03:00:01,0.0435638051044\r\n2011-08-04 04:00:01,0.0628515815085\r\n2011-08-04 05:00:01,0.0907293354943\r\n2011-08-04 06:00:01,0.079404641776\r\n2011-08-04 07:00:01,0.124388254486\r\n2011-08-04 08:00:01,0.192708333333\r\n2011-08-04 09:00:01,0.155310880829\r\n2011-08-04 10:00:01,0.11597826087\r\n2011-08-04 11:00:01,0.122092307692\r\n2011-08-04 12:00:01,0.118666666667\r\n2011-08-04 13:00:01,0.114611398964\r\n2011-08-04 14:00:01,0.11694980695\r\n2011-08-04 15:00:01,0.111554663992\r\n2011-08-04 16:00:01,0.117184466019\r\n2011-08-04 17:00:01,0.107725080386\r\n2011-08-04 18:00:01,0.0907093292213\r\n2011-08-04 19:00:01,0.0940831074977\r\n2011-08-04 20:00:01,0.0903178991016\r\n2011-08-04 21:00:01,0.0942023346304\r\n2011-08-04 22:00:01,0.0980128548473\r\n2011-08-04 23:00:01,0.0961186903138\r\n2011-08-05 00:00:01,0.083626707132\r\n2011-08-05 01:00:01,0.0662049335863\r\n2011-08-05 02:00:01,0.0627621483376\r\n2011-08-05 03:00:01,0.0654652071931\r\n2011-08-05 04:00:01,0.0682556591212\r\n2011-08-05 05:00:01,0.108736462094\r\n2011-08-05 06:00:01,0.0956589147287\r\n2011-08-05 07:00:01,0.121594684385\r\n2011-08-05 08:00:01,0.169946808511\r\n2011-08-05 09:00:01,0.138291925466\r\n2011-08-05 10:00:01,0.122438162544\r\n2011-08-05 11:00:01,0.124915730337\r\n2011-08-05 12:00:01,0.103655172414\r\n2011-08-05 13:00:01,0.120434782609\r\n2011-08-05 14:00:01,0.127615384615\r\n2011-08-05 15:00:01,0.116647398844\r\n2011-08-05 16:00:01,0.119007470651\r\n2011-08-05 17:00:01,0.123242753623\r\n2011-08-05 18:00:01,0.10378812199\r\n2011-08-05 19:00:01,0.103911671924\r\n2011-08-05 20:00:01,0.1031834404\r\n2011-08-05 21:00:01,0.0813955342903\r\n2011-08-05 22:00:01,0.0997409326425\r\n2011-08-05 23:00:01,0.0937476808905\r\n2011-08-06 00:00:01,0.0944382022472\r\n2011-08-06 01:00:01,0.0806839452844\r\n2011-08-06 02:00:01,0.0811759868421\r\n2011-08-06 03:00:01,0.079875\r\n2011-08-06 04:00:01,0.101463607595\r\n2011-08-06 05:00:01,0.0946192528736\r\n2011-08-06 06:00:01,0.103779385172\r\n2011-08-06 07:00:01,0.131770833333\r\n2011-08-06 08:00:01,0.164243902439\r\n2011-08-06 09:00:01,0.114065420561\r\n2011-08-06 10:00:01,0.097802690583\r\n2011-08-06 11:00:01,0.118575418994\r\n2011-08-06 12:00:01,0.144545454545\r\n2011-08-06 13:00:01,0.115585106383\r\n2011-08-06 14:00:01,0.138979865772\r\n2011-08-06 15:00:01,0.117599277978\r\n2011-08-06 16:00:01,0.127989556136\r\n2011-08-06 17:00:01,0.11869047619\r\n2011-08-06 18:00:01,0.112857142857\r\n2011-08-06 19:00:01,0.104221105528\r\n2011-08-06 20:00:01,0.110081300813\r\n2011-08-06 21:00:01,0.109489795918\r\n2011-08-06 22:00:01,0.132456320658\r\n2011-08-06 23:00:01,0.112317198764\r\n2011-08-07 00:00:01,0.0978862793572\r\n2011-08-07 01:00:01,0.0939727126806\r\n2011-08-07 02:00:01,0.0917095777549\r\n2011-08-07 03:00:01,0.08609375\r\n2011-08-07 04:00:01,0.0917391304348\r\n2011-08-07 05:00:01,0.0846818181818\r\n2011-08-07 06:00:01,0.0921988950276\r\n2011-08-07 07:00:01,0.137547169811\r\n2011-08-07 08:00:01,0.194764957265\r\n2011-08-07 09:00:01,0.137314578005\r\n2011-08-07 10:00:01,0.123309178744\r\n2011-08-07 11:00:01,0.101875\r\n2011-08-07 12:00:01,0.113897810219\r\n2011-08-07 13:00:01,0.123737541528\r\n2011-08-07 14:00:01,0.125498533724\r\n2011-08-07 15:00:01,0.124308390023\r\n2011-08-07 16:00:01,0.107933014354\r\n2011-08-07 17:00:01,0.114069050555\r\n2011-08-07 18:00:01,0.114200260078\r\n2011-08-07 19:00:01,0.115863921218\r\n2011-08-07 20:00:01,0.132262016965\r\n2011-08-07 21:00:01,0.0852321428571\r\n2011-08-07 22:00:01,0.085404040404\r\n2011-08-07 23:00:01,0.0957723577236\r\n2011-08-08 00:00:01,0.0809021406728\r\n2011-08-08 01:00:01,0.0813665086888\r\n2011-08-08 02:00:01,0.0686845549738\r\n2011-08-08 03:00:01,0.06375\r\n2011-08-08 04:00:01,0.0718086419753\r\n2011-08-08 05:00:01,0.0990780141844\r\n2011-08-08 06:00:01,0.101891891892\r\n2011-08-08 07:00:01,0.131940594059\r\n2011-08-08 08:00:01,0.198534031414\r\n2011-08-08 09:00:01,0.131197411003\r\n2011-08-08 10:00:01,0.135933333333\r\n2011-08-08 11:00:01,0.137407407407\r\n2011-08-08 12:00:01,0.135081081081\r\n2011-08-08 13:00:01,0.127449799197\r\n2011-08-08 14:00:01,0.134806547619\r\n2011-08-08 15:00:01,0.146736292428\r\n2011-08-08 16:00:01,0.140640732265\r\n2011-08-08 17:00:01,0.124901639344\r\n2011-08-08 19:00:01,0.107754940711\r\n2011-08-08 20:00:01,0.0973099801718\r\n2011-08-08 21:00:01,0.105857445307\r\n2011-08-08 22:00:01,0.104513274336\r\n2011-08-08 23:00:01,0.0998374558304\r\n2011-08-09 00:00:01,0.0816804822909\r\n2011-08-09 01:00:01,0.0678761061947\r\n2011-08-09 02:00:01,0.0752766639936\r\n2011-08-09 03:00:01,0.0670263591433\r\n2011-08-09 04:00:01,0.079624920534\r\n2011-08-09 05:00:01,0.088817264574\r\n2011-08-09 06:00:01,0.0894524119948\r\n2011-08-09 07:00:01,0.110949913644\r\n2011-08-09 08:00:01,0.184171428571\r\n2011-08-09 09:00:01,0.126060606061\r\n2011-08-09 10:00:01,0.122429022082\r\n2011-08-09 11:00:01,0.113667711599\r\n2011-08-09 12:00:01,0.12118902439\r\n2011-08-09 13:00:01,0.120177304965\r\n2011-08-09 14:00:01,0.126299212598\r\n2011-08-09 15:00:01,0.160228136882\r\n2011-08-09 16:00:01,0.130101180438\r\n2011-08-09 17:00:01,0.132857142857\r\n2011-08-09 18:00:01,0.106023657871\r\n2011-08-09 19:00:01,0.109564902103\r\n2011-08-09 20:00:01,0.112048293089\r\n2011-08-09 21:00:01,0.109079847909\r\n2011-08-09 22:00:01,0.108366935484\r\n2011-08-09 23:00:01,0.0944126738794\r\n2011-08-10 00:00:01,0.0868382352941\r\n2011-08-10 01:00:01,0.0871462264151\r\n2011-08-10 02:00:01,0.0835324107793\r\n2011-08-10 03:00:01,0.0797773654917\r\n2011-08-10 04:00:01,0.0870853573907\r\n2011-08-10 05:00:01,0.107430962343\r\n2011-08-10 06:00:01,0.103407572383\r\n2011-08-10 07:00:01,0.131053763441\r\n2011-08-10 08:00:01,0.149262820513\r\n2011-08-10 09:00:01,0.149195804196\r\n2011-08-10 10:00:01,0.116387096774\r\n2011-08-10 11:00:01,0.133109243697\r\n2011-08-10 12:00:01,0.113486973948\r\n2011-08-10 13:00:01,0.134677419355\r\n2011-08-10 14:00:01,0.13365159129\r\n2011-08-10 15:00:01,0.162853025937\r\n2011-08-10 17:00:01,0.129087837838\r\n2011-08-10 18:00:01,0.129151061174\r\n2011-08-10 19:00:01,0.0959275452842\r\n2011-08-10 20:00:01,0.120016652789\r\n2011-08-10 21:00:01,0.139963099631\r\n2011-08-10 22:00:01,0.1335\r\n2011-08-10 23:00:01,0.11544\r\n2011-08-11 00:00:01,0.0934608208955\r\n2011-08-11 01:00:01,0.100648648649\r\n2011-08-11 02:00:01,0.0751342281879\r\n2011-08-11 03:00:01,0.0717509481669\r\n2011-08-11 04:00:01,0.0848198198198\r\n2011-08-11 05:00:01,0.0985912823752\r\n2011-08-11 06:00:01,0.111722365039\r\n2011-08-11 07:00:01,0.144885931559\r\n2011-08-11 08:00:01,0.158951310861\r\n2011-08-11 09:00:01,0.168668341709\r\n2011-08-11 10:00:01,0.153682170543\r\n2011-08-11 11:00:01,0.12256281407\r\n2011-08-11 12:00:01,0.151400437637\r\n2011-08-11 13:00:01,0.136942675159\r\n2011-08-11 14:00:01,0.129286498353\r\n2011-08-11 15:00:01,0.116570477248\r\n2011-08-11 16:00:01,0.100236486486\r\n2011-08-11 17:00:01,0.132017857143\r\n2011-08-11 18:00:01,0.121481481481\r\n2011-08-11 19:00:01,0.117148626817\r\n2011-08-11 20:00:01,0.0993429158111\r\n2011-08-11 21:00:01,0.0867046718576\r\n2011-08-11 22:00:01,0.101101137044\r\n2011-08-11 23:00:01,0.0985993485342\r\n2011-08-12 00:00:01,0.0790524534687\r\n2011-08-12 01:00:01,0.0890992767916\r\n2011-08-12 02:00:01,0.0801247537754\r\n2011-08-12 03:00:01,0.0816735112936\r\n2011-08-12 04:00:01,0.108480420807\r\n2011-08-12 05:00:01,0.123552123552\r\n2011-08-12 06:00:01,0.123780864198\r\n2011-08-12 07:00:01,0.154623955432\r\n2011-08-12 08:00:01,0.218536121673\r\n2011-08-12 09:00:01,0.174148148148\r\n2011-08-12 10:00:01,0.139515151515\r\n2011-08-12 11:00:01,0.144714714715\r\n2011-08-12 12:00:01,0.130277777778\r\n2011-08-12 13:00:01,0.164316831683\r\n2011-08-12 14:00:01,0.146094364351\r\n2011-08-12 15:00:01,0.15875491481\r\n2011-08-12 16:00:01,0.137076271186\r\n2011-08-12 17:00:01,0.117378723404\r\n2011-08-12 18:00:01,0.112778702163\r\n2011-08-12 19:00:01,0.140034423408\r\n2011-08-12 20:00:01,0.127083333333\r\n2011-08-12 21:00:01,0.103282647585\r\n2011-08-12 22:00:01,0.0950205930807\r\n2011-08-12 23:00:01,0.114839491217\r\n2011-08-13 00:00:01,0.111620400258\r\n2011-08-13 01:00:01,0.115210150674\r\n2011-08-13 02:00:01,0.0884778292522\r\n2011-08-13 03:00:01,0.0781188118812\r\n2011-08-13 04:00:01,0.0926106770833\r\n2011-08-13 05:00:01,0.105254452926\r\n2011-08-13 06:00:01,0.147014084507\r\n2011-08-13 07:00:01,0.184960526316\r\n2011-08-13 08:00:01,0.200205338809\r\n2011-08-13 09:00:01,0.16768707483\r\n2011-08-13 10:00:01,0.143217158177\r\n2011-08-13 11:00:01,0.128606965174\r\n2011-08-13 12:00:01,0.176341463415\r\n2011-08-13 13:00:01,0.190699844479\r\n2011-08-13 14:00:01,0.207095490716\r\n2011-08-13 15:00:01,0.170642303433\r\n2011-08-13 16:00:01,0.166080956762\r\n2011-08-13 17:00:01,0.140209339775\r\n2011-08-13 18:00:01,0.121964285714\r\n2011-08-13 19:00:01,0.121059288538\r\n2011-08-13 20:00:01,0.111311258278\r\n2011-08-13 21:00:01,0.105853485064\r\n2011-08-13 22:00:01,0.0939015904573\r\n2011-08-13 23:00:01,0.0974674220963\r\n2011-08-14 00:00:01,0.103974603175\r\n2011-08-14 01:00:01,0.100102880658\r\n2011-08-14 02:00:01,0.0934496124031\r\n2011-08-14 03:00:01,0.0931725768322\r\n2011-08-14 04:00:01,0.101034282394\r\n2011-08-14 05:00:01,0.123640988372\r\n2011-08-14 06:00:01,0.168444444444\r\n2011-08-14 07:00:01,0.191602465331\r\n2011-08-14 08:00:01,0.177750556793\r\n2011-08-14 09:00:01,0.13620596206\r\n2011-08-14 10:00:01,0.131743486974\r\n2011-08-14 11:00:01,0.1367003367\r\n2011-08-14 12:00:01,0.135974499089\r\n2011-08-14 13:00:01,0.153161875946\r\n2011-08-14 14:00:01,0.176701183432\r\n2011-08-14 15:00:01,0.149260739261\r\n2011-08-14 16:00:01,0.140222793488\r\n2011-08-14 17:00:01,0.123384879725\r\n2011-08-14 18:00:01,0.113982056591\r\n2011-08-14 19:00:01,0.102060857538\r\n2011-08-14 20:00:01,0.0899290780142\r\n2011-08-14 21:00:01,0.1030813618\r\n2011-08-14 22:00:01,0.115312\r\n2011-08-14 23:00:01,0.0971056439942\r\n2011-08-15 00:00:01,0.0887619047619\r\n2011-08-15 01:00:01,0.0767574059247\r\n2011-08-15 02:00:01,0.0635458409229\r\n2011-08-15 03:00:01,0.0615452688904\r\n2011-08-15 04:00:01,0.0844965034965\r\n2011-08-15 05:00:01,0.125080416272\r\n2011-08-15 06:00:01,0.152823529412\r\n2011-08-15 07:00:01,0.160897435897\r\n2011-08-15 08:00:01,0.208504464286\r\n2011-08-15 09:00:01,0.159442622951\r\n2011-08-15 10:00:01,0.126083333333\r\n2011-08-15 11:00:01,0.147287066246\r\n2011-08-15 12:00:01,0.13907275321\r\n2011-08-15 13:00:01,0.152277580071\r\n2011-08-15 14:00:01,0.175957820738\r\n2011-08-15 15:00:01,0.172835595777\r\n2011-08-15 16:00:01,0.15900990099\r\n2011-08-15 17:00:01,0.145223880597\r\n2011-08-15 18:00:01,0.149354518371\r\n2011-08-15 19:00:01,0.131401693321\r\n2011-08-15 20:00:01,0.124854288093\r\n2011-08-15 21:00:01,0.120876451954\r\n2011-08-16 00:00:01,0.112879852126\r\n2011-08-16 01:00:01,0.0948547717842\r\n2011-08-16 02:00:01,0.07600505689\r\n2011-08-16 03:00:01,0.0601774785802\r\n2011-08-16 04:00:01,0.0721493506494\r\n2011-08-16 05:00:01,0.109337016575\r\n2011-08-16 06:00:01,0.12738045738\r\n2011-08-16 07:00:01,0.180516795866\r\n2011-08-16 08:00:01,0.175753424658\r\n2011-08-16 09:00:01,0.144705882353\r\n2011-08-16 10:00:01,0.139488054608\r\n2011-08-16 11:00:01,0.156717325228\r\n2011-08-16 12:00:01,0.156968911917\r\n2011-08-16 13:00:01,0.173802281369\r\n2011-08-16 14:00:01,0.195833333333\r\n2011-08-16 15:00:01,0.159928315412\r\n2011-08-16 16:00:01,0.156680555556\r\n2011-08-16 17:00:01,0.130603732162\r\n2011-08-16 18:00:01,0.120630541872\r\n2011-08-16 19:00:01,0.117578194817\r\n2011-08-16 20:00:01,0.100228855721\r\n2011-08-16 21:00:01,0.110859774821\r\n2011-08-16 22:00:01,0.100555972953\r\n2011-08-16 23:00:01,0.0928300609343\r\n2011-08-17 00:00:01,0.0887169312169\r\n2011-08-17 01:00:01,0.0751711026616\r\n2011-08-17 02:00:01,0.0671932299013\r\n2011-08-17 03:00:01,0.0569876453488\r\n2011-08-17 04:00:01,0.0739644970414\r\n2011-08-17 05:00:01,0.0940488656195\r\n2011-08-17 06:00:01,0.0884420289855\r\n2011-08-17 07:00:01,0.119948275862\r\n2011-08-17 08:00:01,0.135165394402\r\n2011-08-17 09:00:01,0.128560411311\r\n2011-08-17 10:00:01,0.12003236246\r\n2011-08-17 11:00:01,0.116625\r\n2011-08-17 12:00:01,0.115021276596\r\n2011-08-17 13:00:01,0.124337152209\r\n2011-08-17 14:00:01,0.110400972053\r\n2011-08-17 15:00:01,0.148208409506\r\n2011-08-17 16:00:01,0.146277890467\r\n2011-08-17 17:00:01,0.110632911392\r\n2011-08-17 18:00:01,0.129878721058\r\n2011-08-17 19:00:01,0.107172489083\r\n2011-08-17 20:00:01,0.109739130435\r\n2011-08-17 21:00:01,0.102514619883\r\n2011-08-17 22:00:01,0.0949129852744\r\n2011-08-17 23:00:01,0.0821228615863\r\n2011-08-18 00:00:01,0.0739106901218\r\n2011-08-18 01:00:01,0.0707963246554\r\n2011-08-18 02:00:01,0.0606611570248\r\n2011-08-18 03:00:01,0.0442401392111\r\n2011-08-18 04:00:01,0.0616063675832\r\n2011-08-18 05:00:01,0.0953426248548\r\n2011-08-18 06:00:01,0.0802471169687\r\n2011-08-18 07:00:01,0.139586563307\r\n2011-08-18 08:00:01,0.172919463087\r\n2011-08-18 09:00:01,0.145015772871\r\n2011-08-18 10:00:01,0.152935153584\r\n2011-08-18 11:00:01,0.126653846154\r\n2011-08-18 12:00:01,0.134631578947\r\n2011-08-18 13:00:01,0.139772296015\r\n2011-08-18 14:00:01,0.156115384615\r\n2011-08-18 15:00:01,0.161610429448\r\n2011-08-18 16:00:01,0.142340136054\r\n2011-08-18 17:00:01,0.124217758985\r\n2011-08-18 18:00:01,0.112732502397\r\n2011-08-18 19:00:01,0.109907407407\r\n2011-08-18 20:00:01,0.103028301887\r\n2011-08-18 21:00:01,0.108101265823\r\n2011-08-18 22:00:01,0.109340101523\r\n2011-08-18 23:00:01,0.0928143133462\r\n2011-08-19 00:00:01,0.0860546875\r\n2011-08-19 01:00:01,0.0710621468927\r\n2011-08-19 02:00:01,0.0732460447354\r\n2011-08-19 03:00:01,0.0536189747513\r\n2011-08-19 04:00:01,0.0822508038585\r\n2011-08-19 05:00:01,0.094796030871\r\n2011-08-19 06:00:01,0.0969190140845\r\n2011-08-19 07:00:01,0.144830699774\r\n2011-08-19 08:00:01,0.174155844156\r\n2011-08-19 09:00:01,0.151114369501\r\n2011-08-19 10:00:01,0.152806324111\r\n2011-08-19 11:00:01,0.146851311953\r\n2011-08-19 12:00:01,0.16219858156\r\n2011-08-19 13:00:01,0.18921875\r\n2011-08-19 14:00:01,0.157520242915\r\n2011-08-19 15:00:01,0.158472584856\r\n2011-08-19 16:00:01,0.13572815534\r\n2011-08-19 17:00:01,0.101354420114\r\n2011-08-19 18:00:01,0.10043381535\r\n2011-08-19 19:00:01,0.113808016878\r\n2011-08-19 20:00:01,0.104941176471\r\n2011-08-19 21:00:01,0.0976577840112\r\n2011-08-19 22:00:01,0.101288951841\r\n2011-08-19 23:00:01,0.0807769145394\r\n2011-08-20 00:00:01,0.0770080321285\r\n2011-08-20 01:00:01,0.0724773834377\r\n2011-08-20 02:00:01,0.0632070707071\r\n2011-08-20 03:00:01,0.0492577224527\r\n2011-08-20 04:00:01,0.0694444444444\r\n2011-08-20 05:00:01,0.111746183206\r\n2011-08-20 06:00:01,0.0953485064011\r\n2011-08-20 07:00:01,0.13880866426\r\n2011-08-20 08:00:01,0.158722891566\r\n2011-08-20 09:00:01,0.142033333333\r\n2011-08-20 10:00:01,0.118189415042\r\n2011-08-20 11:00:01,0.123484848485\r\n2011-08-20 12:00:01,0.155338983051\r\n2011-08-20 13:00:01,0.171588132635\r\n2011-08-20 14:00:01,0.154665757162\r\n2011-08-20 15:00:01,0.144744897959\r\n2011-08-20 16:00:01,0.142985409652\r\n2011-08-20 17:00:01,0.101298157454\r\n2011-08-20 18:00:01,0.0898817567568\r\n2011-08-20 19:00:01,0.0887995198079\r\n2011-08-20 20:00:01,0.0915183946488\r\n2011-08-20 21:00:01,0.088203125\r\n2011-08-20 22:00:01,0.0940313111546\r\n2011-08-20 23:00:01,0.0947100802855\r\n2011-08-21 00:00:01,0.0783\r\n2011-08-21 01:00:01,0.0807470049331\r\n2011-08-21 02:00:01,0.0641913439636\r\n2011-08-21 03:00:01,0.0538818565401\r\n2011-08-21 04:00:01,0.0753577106518\r\n2011-08-21 05:00:01,0.115963203463\r\n2011-08-21 06:00:01,0.0939847715736\r\n2011-08-21 07:00:01,0.137370242215\r\n2011-08-21 08:00:01,0.171899109792\r\n2011-08-21 09:00:01,0.134024640657\r\n2011-08-21 10:00:01,0.116201780415\r\n2011-08-21 11:00:01,0.111481481481\r\n2011-08-21 12:00:01,0.121878172589\r\n2011-08-21 13:00:01,0.121111111111\r\n2011-08-21 14:00:01,0.127411067194\r\n2011-08-21 15:00:01,0.129568014706\r\n2011-08-21 16:00:01,0.113125\r\n2011-08-21 17:00:01,0.091846419327\r\n2011-08-21 18:00:01,0.083811023622\r\n2011-08-21 19:00:01,0.0901892744479\r\n2011-08-21 20:00:01,0.0848633440514\r\n2011-08-21 21:00:01,0.0827652733119\r\n2011-08-21 22:00:01,0.0729182295574\r\n2011-08-21 23:00:01,0.0687188019967\r\n2011-08-22 00:00:01,0.0652910512598\r\n2011-08-22 01:00:01,0.0597656744775\r\n2011-08-22 02:00:01,0.0489229720518\r\n2011-08-22 03:00:01,0.0477128782548\r\n2011-08-22 04:00:01,0.0638228438228\r\n2011-08-22 05:00:01,0.103051702396\r\n2011-08-22 06:00:01,0.0895652173913\r\n2011-08-22 07:00:01,0.124128440367\r\n2011-08-22 08:00:01,0.215017421603\r\n2011-08-22 09:00:01,0.154131274131\r\n2011-08-22 10:00:01,0.151511111111\r\n2011-08-22 11:00:01,0.129569230769\r\n2011-08-22 12:00:01,0.137255369928\r\n2011-08-22 13:00:01,0.141398305085\r\n2011-08-22 14:00:01,0.127036395147\r\n2011-08-22 15:00:01,0.144790528233\r\n2011-08-22 16:00:01,0.117414880202\r\n2011-08-22 17:00:01,0.118756157635\r\n2011-08-22 18:00:01,0.119006309148\r\n2011-08-22 19:00:01,0.113553859203\r\n2011-08-22 20:00:01,0.0979017857143\r\n2011-08-22 21:00:01,0.10843902439\r\n2011-08-22 22:00:01,0.0995095948827\r\n2011-08-22 23:00:01,0.0754669887279\r\n2011-08-23 00:00:01,0.0701578947368\r\n2011-08-23 01:00:01,0.0633381088825\r\n2011-08-23 02:00:01,0.0578227245687\r\n2011-08-23 03:00:01,0.054068914956\r\n2011-08-23 04:00:01,0.0800538116592\r\n2011-08-23 05:00:01,0.0942072409488\r\n2011-08-23 06:00:01,0.110804347826\r\n2011-08-23 07:00:01,0.141096605744\r\n2011-08-23 08:00:01,0.211731601732\r\n2011-08-23 09:00:01,0.181084337349\r\n2011-08-23 10:00:01,0.158333333333\r\n2011-08-23 11:00:01,0.128907563025\r\n2011-08-23 12:00:01,0.116029411765\r\n2011-08-23 13:00:01,0.120865800866\r\n2011-08-23 14:00:01,0.133739130435\r\n2011-08-23 15:00:01,0.143019480519\r\n2011-08-23 16:00:01,0.12492286115\r\n2011-08-23 17:00:01,0.105073529412\r\n2011-08-23 18:00:01,0.0983081155433\r\n2011-08-23 19:00:01,0.0931699687174\r\n2011-08-23 20:00:01,0.0918820224719\r\n2011-08-23 21:00:01,0.0894471387003\r\n2011-08-23 22:00:01,0.102030360531\r\n2011-08-23 23:00:01,0.0903076923077\r\n2011-08-24 00:00:01,0.1046875\r\n2011-08-24 01:00:01,0.0749254226052\r\n2011-08-24 02:00:01,0.0649182561308\r\n2011-08-24 03:00:01,0.0571681415929\r\n2011-08-24 04:00:01,0.0727165775401\r\n2011-08-24 05:00:01,0.0925959780622\r\n2011-08-24 06:00:01,0.107063492063\r\n2011-08-24 07:00:01,0.140641891892\r\n2011-08-24 08:00:01,0.197115384615\r\n2011-08-24 09:00:01,0.191169590643\r\n2011-08-24 10:00:01,0.103025477707\r\n2011-08-24 11:00:01,0.134267515924\r\n2011-08-24 12:00:01,0.13125\r\n2011-08-24 12:00:01,0.119452887538\r\n2011-08-24 13:00:01,0.142298578199\r\n2011-08-24 14:00:01,0.121895424837\r\n2011-08-24 15:00:01,0.128388791594\r\n2011-08-24 16:00:01,0.107593880389\r\n2011-08-24 17:00:01,0.134992967651\r\n2011-08-24 18:00:01,0.137509247842\r\n2011-08-24 19:00:01,0.118355995056\r\n2011-08-24 20:00:01,0.0995682613769\r\n2011-08-24 21:00:01,0.100749711649\r\n2011-08-24 22:00:01,0.0836117936118\r\n2011-08-24 23:00:01,0.089214527027\r\n2011-08-25 00:00:01,0.0810109090909\r\n2011-08-25 01:00:01,0.0740128410915\r\n2011-08-25 02:00:01,0.0661502347418\r\n2011-08-25 03:00:01,0.0658904109589\r\n2011-08-25 04:00:01,0.0658904109589\r\n2011-08-25 05:00:01,0.0795053147997\r\n2011-08-25 06:00:01,0.100915331808\r\n2011-08-25 07:00:01,0.150614334471\r\n2011-08-25 08:00:01,0.161641791045\r\n2011-08-25 09:00:01,0.186170212766\r\n2011-08-25 10:00:01,0.120856269113\r\n2011-08-25 11:00:01,0.139667774086\r\n2011-08-25 12:00:01,0.148098159509\r\n2011-08-25 13:00:01,0.150740740741\r\n2011-08-25 14:00:01,0.128050089445\r\n2011-08-25 15:00:01,0.123235685752\r\n2011-08-25 16:00:01,0.113632019116\r\n2011-08-25 17:00:01,0.103065217391\r\n2011-08-25 18:00:01,0.102137203166\r\n2011-08-25 19:00:01,0.116292517007\r\n2011-08-25 20:00:01,0.0962192216044\r\n2011-08-25 21:00:01,0.0926034958602\r\n2011-08-25 22:00:01,0.0993384223919\r\n2011-08-25 23:00:01,0.0854255319149\r\n2011-08-26 00:00:01,0.0726258992806\r\n2011-08-26 01:00:01,0.0689721485411\r\n2011-08-26 02:00:01,0.0659612903226\r\n2011-08-26 03:00:01,0.0546968403074\r\n2011-08-26 04:00:01,0.0795277777778\r\n2011-08-26 05:00:01,0.0923461538462\r\n2011-08-26 06:00:01,0.105986842105\r\n2011-08-26 07:00:01,0.165223097113\r\n2011-08-26 08:00:01,0.175538461538\r\n2011-08-26 09:00:01,0.151849315068\r\n2011-08-26 10:00:01,0.177138263666\r\n2011-08-26 11:00:01,0.121359773371\r\n2011-08-26 12:00:01,0.131615541922\r\n2011-08-26 13:00:01,0.145436241611\r\n2011-08-26 14:00:01,0.131875\r\n2011-08-26 15:00:01,0.145088566828\r\n2011-08-26 16:00:01,0.138504672897\r\n2011-08-26 17:00:01,0.123757881463\r\n2011-08-26 18:00:01,0.117987804878\r\n2011-08-26 19:00:01,0.110223577236\r\n2011-08-26 20:00:01,0.107444608567\r\n2011-08-26 21:00:01,0.103782095767\r\n2011-08-26 22:00:01,0.095650713686\r\n2011-08-26 23:00:01,0.101652360515\r\n2011-08-27 00:00:01,0.0850060606061\r\n2011-08-27 01:00:01,0.0855480769231\r\n2011-08-27 02:00:01,0.0793292682927\r\n2011-08-27 03:00:01,0.0749841269841\r\n2011-08-27 04:00:01,0.0956683168317\r\n2011-08-27 05:00:01,0.0981013824885\r\n2011-08-27 06:00:01,0.110380622837\r\n2011-08-27 07:00:01,0.135073529412\r\n2011-08-27 08:00:01,0.163687635575\r\n2011-08-27 09:00:01,0.147275132275\r\n2011-08-27 10:00:01,0.118717339667\r\n2011-08-27 11:00:01,0.154738292011\r\n2011-08-27 12:00:01,0.134536082474\r\n2011-08-27 13:00:01,0.131927536232\r\n2011-08-27 14:00:01,0.126748057714\r\n2011-08-27 15:00:01,0.120754005655\r\n2011-08-27 16:00:01,0.118395833333\r\n2011-08-27 17:00:01,0.103737646002\r\n2011-08-27 18:00:01,0.100345140781\r\n2011-08-27 19:00:01,0.098473547268\r\n2011-08-27 20:00:01,0.0985117967332\r\n2011-08-27 21:00:01,0.0954140127389\r\n2011-08-27 22:00:01,0.0860727272727\r\n2011-08-27 23:00:01,0.0821031746032\r\n2011-08-28 00:00:01,0.0727639751553\r\n2011-08-28 01:00:01,0.062752851711\r\n2011-08-28 02:00:01,0.0587381473377\r\n2011-08-28 03:00:01,0.0479363057325\r\n2011-08-28 04:00:01,0.0682142857143\r\n2011-08-28 05:00:01,0.0759542586751\r\n2011-08-28 06:00:01,0.106373626374\r\n2011-08-28 07:00:01,0.0969246861925\r\n2011-08-28 08:00:01,0.170033388982\r\n2011-08-28 09:00:01,0.124548104956\r\n2011-08-28 10:00:01,0.114635514019\r\n2011-08-28 11:00:01,0.103448275862\r\n2011-08-28 12:00:01,0.116266173752\r\n2011-08-28 13:00:01,0.126609907121\r\n2011-08-28 14:00:01,0.130183006536\r\n2011-08-28 15:00:01,0.120176531672\r\n2011-08-28 16:00:01,0.111587301587\r\n2011-08-28 17:00:01,0.0976240846216\r\n2011-08-28 18:00:01,0.0948384353741\r\n2011-08-28 19:00:01,0.0840584166026\r\n2011-08-28 20:00:01,0.0743294117647\r\n2011-08-28 21:00:01,0.0712329863891\r\n2011-08-28 22:00:01,0.0668421052632\r\n2011-08-28 23:00:01,0.0719213114754\r\n2011-08-29 00:00:01,0.0600398406375\r\n2011-08-29 01:00:01,0.0555158069884\r\n2011-08-29 02:00:01,0.0490916597853\r\n2011-08-29 03:00:01,0.0423600973236\r\n2011-08-29 04:00:01,0.0606539735099\r\n2011-08-29 05:00:01,0.0777566539924\r\n2011-08-29 06:00:01,0.0873804971319\r\n2011-08-29 07:00:01,0.129604863222\r\n2011-08-29 08:00:01,0.158345070423\r\n2011-08-29 09:00:01,0.138106508876\r\n2011-08-29 10:00:01,0.150680272109\r\n2011-08-29 11:00:01,0.116778042959\r\n2011-08-29 12:00:01,0.0966950959488\r\n2011-08-29 13:00:01,0.123992932862\r\n2011-08-29 14:00:01,0.11081570997\r\n2011-08-29 15:00:01,0.129307432432\r\n2011-08-29 16:00:01,0.125940740741\r\n2011-08-29 17:00:01,0.102137592138\r\n2011-08-29 18:00:01,0.0941742081448\r\n2011-08-29 19:00:01,0.109444995045\r\n2011-08-29 20:00:01,0.0872681451613\r\n2011-08-29 21:00:01,0.0890061349693\r\n2011-08-29 22:00:01,0.0870618228171\r\n2011-08-29 23:00:01,0.0841054613936\r\n2011-08-30 00:00:01,0.0761148325359\r\n2011-08-30 01:00:01,0.0600057937428\r\n2011-08-30 02:00:01,0.054295958279\r\n2011-08-30 03:00:01,0.051952887538\r\n2011-08-30 04:00:01,0.0924405218726\r\n2011-08-30 05:00:01,0.109405010438\r\n2011-08-30 06:00:01,0.122962138085\r\n2011-08-30 07:00:01,0.147909407666\r\n2011-08-30 08:00:01,0.152699228792\r\n2011-08-30 09:00:01,0.1541875\r\n2011-08-30 10:00:01,0.115840707965\r\n2011-08-30 11:00:01,0.110201149425\r\n2011-08-30 12:00:01,0.110076142132\r\n2011-08-30 13:00:01,0.108673267327\r\n2011-08-30 14:00:01,0.106678832117\r\n2011-08-30 15:00:01,0.107907949791\r\n2011-08-30 16:00:01,0.119509692132\r\n2011-08-30 17:00:01,0.101547749726\r\n2011-08-30 18:00:01,0.111957340025\r\n2011-08-30 19:00:01,0.101444007859\r\n2011-08-30 20:00:01,0.0753491055972\r\n2011-08-30 21:00:01,0.0653881278539\r\n2011-08-30 22:00:01,0.089246805649\r\n2011-08-30 23:00:01,0.0813057961359\r\n2011-08-31 00:00:01,0.0938608119304\r\n2011-08-31 01:00:01,0.0797480451781\r\n2011-08-31 02:00:01,0.066393442623\r\n2011-08-31 03:00:01,0.0646177606178\r\n2011-08-31 04:00:01,0.0873961499493\r\n2011-08-31 05:00:01,0.10959047619\r\n2011-08-31 06:00:01,0.126039119804\r\n2011-08-31 07:00:01,0.12546835443\r\n2011-08-31 08:00:01,0.156303030303\r\n2011-08-31 09:00:01,0.147432432432\r\n2011-08-31 10:00:01,0.133876651982\r\n2011-08-31 11:00:01,0.129890410959\r\n2011-08-31 12:00:01,0.141053811659\r\n2011-08-31 13:00:01,0.117336065574\r\n2011-08-31 14:00:01,0.137372708758\r\n2011-08-31 15:00:01,0.113037593985\r\n2011-08-31 16:00:01,0.110820995962\r\n2011-08-31 17:00:01,0.0996882793017\r\n2011-08-31 18:00:01,0.111057934509\r\n2011-08-31 19:00:01,0.145935563817\r\n2011-08-31 20:00:01,0.165860349127\r\n2011-08-31 21:00:01,0.17193687231\r\n2011-08-31 22:00:01,0.183753623188\r\n2011-08-31 23:00:01,0.173424036281\r\n2011-09-01 00:00:01,0.12689453125\r\n2011-09-01 01:00:01,0.107446988974\r\n2011-09-01 02:00:01,0.0718667642753\r\n2011-09-01 03:00:01,0.0693063583815\r\n2011-09-01 04:00:01,0.136761168385\r\n2011-09-01 05:00:01,0.161497461929\r\n2011-09-01 06:00:01,0.183985890653\r\n2011-09-01 07:00:01,0.190461538462\r\n2011-09-01 08:00:01,0.19428030303\r\n2011-09-01 09:00:01,0.170563380282\r\n2011-09-01 10:00:01,0.181725490196\r\n2011-09-01 11:00:01,0.155087719298\r\n2011-09-01 12:00:01,0.127297297297\r\n2011-09-01 13:00:01,0.127475728155\r\n2011-09-01 14:00:01,0.138672839506\r\n2011-09-01 15:00:01,0.124584980237\r\n2011-09-01 16:00:01,0.119408450704\r\n2011-09-01 17:00:01,0.105145228216\r\n2011-09-01 18:00:01,0.104637681159\r\n2011-09-02 15:00:01,0.125439066059\r\n2011-09-02 16:00:01,0.120748373102\r\n2011-09-02 17:00:01,0.0994585448393\r\n2011-09-02 18:00:01,0.10984\r\n2011-09-02 19:00:01,0.0994903339192\r\n2011-09-02 20:00:01,0.108297511312\r\n2011-09-02 21:00:01,0.109546979866\r\n2011-09-02 22:00:01,0.129507908612\r\n2011-09-02 23:00:01,0.143330266789\r\n2011-09-03 00:00:01,0.121093613298\r\n2011-09-03 01:00:01,0.11054478301\r\n2011-09-03 02:00:01,0.101602160216\r\n2011-09-03 03:00:01,0.0762834917891\r\n2011-09-03 04:00:01,0.0875485799701\r\n2011-09-03 05:00:01,0.127487091222\r\n2011-09-03 06:00:01,0.125506241331\r\n2011-09-03 07:00:01,0.114149797571\r\n2011-09-03 08:00:01,0.148712871287\r\n2011-09-03 09:00:01,0.159177057357\r\n2011-09-03 10:00:01,0.125173267327\r\n2011-09-03 11:00:01,0.12546835443\r\n2011-09-03 12:00:01,0.136340508806\r\n2011-09-03 13:00:01,0.14014084507\r\n2011-09-03 14:00:01,0.135180586907\r\n2011-09-03 15:00:01,0.126968888889\r\n2011-09-03 16:00:01,0.12272195122\r\n2011-09-03 17:00:01,0.112063609467\r\n2011-09-03 18:00:01,0.10224852071\r\n2011-09-03 19:00:01,0.0998234774934\r\n2011-09-03 20:00:01,0.0981008902077\r\n2011-09-03 21:00:01,0.095011148272\r\n2011-09-03 22:00:01,0.0947378277154\r\n2011-09-03 23:00:01,0.0939592123769\r\n2011-09-04 00:00:01,0.0895993589744\r\n2011-09-04 01:00:01,0.0939749328559\r\n2011-09-04 02:00:01,0.0869841269841\r\n2011-09-04 03:00:01,0.0758333333333\r\n2011-09-04 04:00:01,0.103483976993\r\n2011-09-04 05:00:01,0.124340101523\r\n2011-09-04 06:00:01,0.123559748428\r\n2011-09-04 07:00:01,0.143132780083\r\n2011-09-04 08:00:01,0.153292978208\r\n2011-09-04 09:00:01,0.144975961538\r\n2011-09-04 10:00:01,0.148344988345\r\n2011-09-04 11:00:01,0.121404958678\r\n2011-09-04 12:00:01,0.125106761566\r\n2011-09-04 13:00:01,0.137014446228\r\n2011-09-04 14:00:01,0.145497572816\r\n2011-09-04 15:00:01,0.129219653179\r\n2011-09-04 16:00:01,0.125491891892\r\n2011-09-04 17:00:01,0.112601296596\r\n2011-09-04 18:00:01,0.108785123967\r\n2011-09-04 19:00:01,0.104248704663\r\n2011-09-04 20:00:01,0.0923049001815\r\n2011-09-04 21:00:01,0.0836208178439\r\n2011-09-04 22:00:01,0.0923566878981\r\n2011-09-04 23:00:01,0.0781174984207\r\n2011-09-05 00:00:01,0.0772262190248\r\n2011-09-05 01:00:01,0.0748298755187\r\n2011-09-05 02:00:01,0.0652133044107\r\n2011-09-05 03:00:01,0.0451913709116\r\n2011-09-05 04:00:01,0.0791123188406\r\n2011-09-05 05:00:01,0.117971830986\r\n2011-09-05 06:00:01,0.114479338843\r\n2011-09-05 07:00:01,0.113695150115\r\n2011-09-05 08:00:01,0.175580645161\r\n2011-09-05 09:00:01,0.154212328767\r\n2011-09-05 10:00:01,0.139960784314\r\n2011-09-05 11:00:01,0.131630094044\r\n2011-09-05 12:00:01,0.124085714286\r\n2011-09-05 13:00:01,0.127188552189\r\n2011-09-05 14:00:01,0.133503448276\r\n2011-09-05 15:00:01,0.12168972332\r\n2011-09-05 16:00:01,0.115792592593\r\n2011-09-05 17:00:01,0.098496835443\r\n2011-09-05 18:00:01,0.0950494396836\r\n2011-09-05 19:00:01,0.0910444874275\r\n2011-09-05 20:00:01,0.0811893687708\r\n2011-09-05 21:00:01,0.0825793907971\r\n2011-09-05 22:00:01,0.0765527950311\r\n2011-09-05 23:00:01,0.0788387978142\r\n2011-09-06 00:00:01,0.0739627659574\r\n2011-09-06 01:00:01,0.0691387900356\r\n2011-09-06 02:00:01,0.0510319076714\r\n2011-09-06 03:00:01,0.0468152031455\r\n2011-09-06 04:00:01,0.0999201596806\r\n2011-09-06 05:00:01,0.10201884253\r\n2011-09-06 06:00:01,0.106287262873\r\n2011-09-06 07:00:01,0.150187265918\r\n2011-09-06 08:00:01,0.140684210526\r\n2011-09-06 09:00:01,0.154042553191\r\n2011-09-06 10:00:01,0.138396946565\r\n2011-09-06 11:00:01,0.116378737542\r\n2011-09-06 12:00:01,0.111181318681\r\n2011-09-06 13:00:01,0.116266375546\r\n2011-09-06 14:00:01,0.116395112016\r\n2011-09-06 15:00:01,0.114629948365\r\n2011-09-06 16:00:01,0.111974522293\r\n2011-09-06 17:00:01,0.0947324613555\r\n2011-09-06 18:00:01,0.112244224422\r\n2011-09-06 19:00:01,0.102278911565\r\n2011-09-06 20:00:01,0.0928500496524\r\n2011-09-06 21:00:01,0.0991582733813\r\n2011-09-06 22:00:01,0.0976913580247\r\n2011-09-06 23:00:01,0.0857002111189\r\n2011-09-07 00:00:01,0.0823789294817\r\n2011-09-07 01:00:01,0.0659537882859\r\n2011-09-07 02:00:01,0.0494587280108\r\n2011-09-07 03:00:01,0.0497890818859\r\n2011-09-07 04:00:01,0.0654583772392\r\n2011-09-07 05:00:01,0.0896212121212\r\n2011-09-07 06:00:01,0.111073619632\r\n2011-09-07 07:00:01,0.101031746032\r\n2011-09-07 08:00:01,0.151616766467\r\n2011-09-07 09:00:01,0.124743589744\r\n2011-09-07 10:00:01,0.135588235294\r\n2011-09-07 11:00:01,0.0946623794212\r\n2011-09-07 12:00:01,0.097656612529\r\n2011-09-07 13:00:01,0.0962009803922\r\n2011-09-07 14:00:01,0.0853863636364\r\n2011-09-07 15:00:01,0.109326923077\r\n"
  },
  {
    "path": "workspace/anomaly_detector/datasets/selected/seasonal/exchange-2_cpm_results.csv",
    "content": "timestamp,value\r\n2011-07-01 00:00:01,0.401048098657\r\n2011-07-01 01:00:01,0.392718881005\r\n2011-07-01 02:00:01,0.309996119798\r\n2011-07-01 03:00:01,0.212938552018\r\n2011-07-01 04:00:01,0.205800905571\r\n2011-07-01 05:00:01,0.255867457952\r\n2011-07-01 06:00:01,0.306630479265\r\n2011-07-01 07:00:01,0.29600203814\r\n2011-07-01 08:00:01,0.530440128999\r\n2011-07-01 09:00:01,0.790249514633\r\n2011-07-01 10:00:01,0.743906815883\r\n2011-07-01 11:00:01,0.736919786741\r\n2011-07-01 12:00:01,0.697582243361\r\n2011-07-01 13:00:01,0.687341841286\r\n2011-07-01 14:00:01,0.517447938078\r\n2011-07-01 15:00:01,0.519026716424\r\n2011-07-01 16:00:01,0.51413336812\r\n2011-07-01 17:00:01,0.417275625868\r\n2011-07-01 18:00:01,0.24845741212\r\n2011-07-01 19:00:01,0.309360489543\r\n2011-07-01 20:00:01,0.273067885947\r\n2011-07-01 21:00:01,0.264461005442\r\n2011-07-01 22:00:01,0.23187973727\r\n2011-07-01 23:00:01,0.261552512902\r\n2011-07-02 00:00:01,0.324815629448\r\n2011-07-02 01:00:01,0.251320671322\r\n2011-07-02 02:00:01,0.21464613516\r\n2011-07-02 03:00:01,0.166280263697\r\n2011-07-02 04:00:01,0.211815143689\r\n2011-07-02 05:00:01,0.303217093576\r\n2011-07-02 06:00:01,0.2878979686\r\n2011-07-02 07:00:01,0.396715687694\r\n2011-07-02 08:00:01,0.588415532379\r\n2011-07-02 09:00:01,0.59337773192\r\n2011-07-02 10:00:01,0.71387011592\r\n2011-07-02 11:00:01,0.787525214093\r\n2011-07-02 12:00:01,0.736921318877\r\n2011-07-02 13:00:01,0.682062044372\r\n2011-07-02 14:00:01,0.72266165164\r\n2011-07-02 15:00:01,0.529339407129\r\n2011-07-02 16:00:01,0.403918440491\r\n2011-07-02 17:00:01,0.346285484196\r\n2011-07-02 18:00:01,0.276515628398\r\n2011-07-02 19:00:01,0.273633723983\r\n2011-07-02 20:00:01,0.348633036515\r\n2011-07-02 21:00:01,0.289148226997\r\n2011-07-02 22:00:01,0.321686929479\r\n2011-07-02 23:00:01,0.260040957735\r\n2011-07-03 00:00:01,0.204862942608\r\n2011-07-03 01:00:01,0.207419676118\r\n2011-07-03 02:00:01,0.173298017129\r\n2011-07-03 03:00:01,0.132202637198\r\n2011-07-03 04:00:01,0.17089560971\r\n2011-07-03 05:00:01,0.279315632688\r\n2011-07-03 06:00:01,0.247734583438\r\n2011-07-03 07:00:01,0.347788950248\r\n2011-07-03 08:00:01,0.677039989488\r\n2011-07-03 09:00:01,0.628506062686\r\n2011-07-03 10:00:01,0.600754435803\r\n2011-07-03 11:00:01,0.595576831487\r\n2011-07-03 12:00:01,0.718312044267\r\n2011-07-03 13:00:01,0.636428503882\r\n2011-07-03 14:00:01,0.561490030939\r\n2011-07-03 15:00:01,0.439826406276\r\n2011-07-03 16:00:01,0.364600634261\r\n2011-07-03 17:00:01,0.304671828772\r\n2011-07-03 18:00:01,0.263320157909\r\n2011-07-03 19:00:01,0.24291524883\r\n2011-07-03 20:00:01,0.241346377957\r\n2011-07-03 21:00:01,0.208214406325\r\n2011-07-03 22:00:01,0.20241559894\r\n2011-07-03 23:00:01,0.231243016929\r\n2011-07-04 00:00:01,0.179941670478\r\n2011-07-04 01:00:01,0.192673380292\r\n2011-07-04 02:00:01,0.166335472132\r\n2011-07-04 03:00:01,0.14227206431\r\n2011-07-04 04:00:01,0.13035498909\r\n2011-07-04 05:00:01,0.167021065133\r\n2011-07-04 06:00:01,0.212676159718\r\n2011-07-04 07:00:01,0.280531152468\r\n2011-07-04 08:00:01,0.475011553443\r\n2011-07-04 09:00:01,0.544187140505\r\n2011-07-04 10:00:01,0.504340064024\r\n2011-07-04 11:00:01,0.534922211188\r\n2011-07-04 12:00:01,0.60978950038\r\n2011-07-04 13:00:01,0.519403479245\r\n2011-07-04 14:00:01,0.523303802344\r\n2011-07-04 15:00:01,0.426077466417\r\n2011-07-04 16:00:01,0.328359110681\r\n2011-07-04 17:00:01,0.350118888796\r\n2011-07-04 18:00:01,0.244078992995\r\n2011-07-04 19:00:01,0.240777566013\r\n2011-07-04 20:00:01,0.219701770288\r\n2011-07-04 21:00:01,0.216081451577\r\n2011-07-04 22:00:01,0.22231036663\r\n2011-07-04 23:00:01,0.251700203323\r\n2011-07-05 00:00:01,0.228566944935\r\n2011-07-05 01:00:01,0.162717684817\r\n2011-07-05 02:00:01,0.180383183189\r\n2011-07-05 03:00:01,0.12846822497\r\n2011-07-05 04:00:01,0.13198890411\r\n2011-07-05 05:00:01,0.175684372523\r\n2011-07-05 06:00:01,0.221543602021\r\n2011-07-05 07:00:01,0.277728770304\r\n2011-07-05 08:00:01,0.441068874921\r\n2011-07-05 09:00:01,0.478228308548\r\n2011-07-05 10:00:01,0.545594724496\r\n2011-07-05 11:00:01,0.667490729295\r\n2011-07-05 12:00:01,0.543584663105\r\n2011-07-05 13:00:01,0.588245394138\r\n2011-07-05 14:00:01,0.428748744016\r\n2011-07-05 15:00:01,0.395360148449\r\n2011-07-05 16:00:01,0.362225419824\r\n2011-07-05 17:00:01,0.32167455849\r\n2011-07-05 18:00:01,0.271341345083\r\n2011-07-05 19:00:01,0.238122873903\r\n2011-07-05 20:00:01,0.215218118536\r\n2011-07-05 21:00:01,0.212734989045\r\n2011-07-05 22:00:01,0.191313851687\r\n2011-07-05 23:00:01,0.242111992062\r\n2011-07-06 00:00:01,0.225081442142\r\n2011-07-06 01:00:01,0.197461002199\r\n2011-07-06 02:00:01,0.136700901134\r\n2011-07-06 03:00:01,0.113719800728\r\n2011-07-06 04:00:01,0.15875414394\r\n2011-07-06 05:00:01,0.202746124147\r\n2011-07-06 06:00:01,0.225718914303\r\n2011-07-06 07:00:01,0.282354321784\r\n2011-07-06 08:00:01,0.479532349027\r\n2011-07-06 09:00:01,0.645141390712\r\n2011-07-06 10:00:01,0.526166240452\r\n2011-07-06 11:00:01,0.575165121144\r\n2011-07-06 12:00:01,0.576957406548\r\n2011-07-06 13:00:01,0.515025329115\r\n2011-07-06 14:00:01,0.406212215185\r\n2011-07-06 15:00:01,0.446764580432\r\n2011-07-06 16:00:01,0.360918143496\r\n2011-07-06 17:00:01,0.354822719712\r\n2011-07-06 18:00:01,0.28959628398\r\n2011-07-06 19:00:01,0.243605335426\r\n2011-07-06 20:00:01,0.207677612716\r\n2011-07-06 21:00:01,0.295679762953\r\n2011-07-06 22:00:01,0.215115083297\r\n2011-07-06 23:00:01,0.225798427437\r\n2011-07-07 00:00:01,0.211171317162\r\n2011-07-07 01:00:01,0.163630094284\r\n2011-07-07 02:00:01,0.123460876016\r\n2011-07-07 03:00:01,0.112138881944\r\n2011-07-07 04:00:01,0.123695651232\r\n2011-07-07 05:00:01,0.174191714264\r\n2011-07-07 06:00:01,0.194801123896\r\n2011-07-07 07:00:01,0.248622655329\r\n2011-07-07 08:00:01,0.408404765219\r\n2011-07-07 09:00:01,0.533661344524\r\n2011-07-07 10:00:01,0.541734270777\r\n2011-07-07 11:00:01,0.440232756428\r\n2011-07-07 12:00:01,0.465434553749\r\n2011-07-07 13:00:01,0.434325310895\r\n2011-07-07 14:00:01,0.350176907623\r\n2011-07-07 15:00:01,0.381217461856\r\n2011-07-07 16:00:01,0.322961923523\r\n2011-07-07 17:00:01,0.250851707414\r\n2011-07-07 18:00:01,0.228276143974\r\n2011-07-07 19:00:01,0.151708247831\r\n2011-07-07 20:00:01,0.180537641872\r\n2011-07-07 21:00:01,0.172451902159\r\n2011-07-07 22:00:01,0.170809031956\r\n2011-07-07 23:00:01,0.15733239773\r\n2011-07-08 00:00:01,0.160795812079\r\n2011-07-08 01:00:01,0.146745639797\r\n2011-07-08 02:00:01,0.140944765148\r\n2011-07-08 03:00:01,0.102638951514\r\n2011-07-08 04:00:01,0.11056241713\r\n2011-07-08 05:00:01,0.144226388965\r\n2011-07-08 06:00:01,0.158332277056\r\n2011-07-08 07:00:01,0.312025914701\r\n2011-07-08 08:00:01,0.527204950695\r\n2011-07-08 09:00:01,0.434005616543\r\n2011-07-08 10:00:01,0.494257013647\r\n2011-07-08 11:00:01,0.456944556533\r\n2011-07-08 12:00:01,0.444284861437\r\n2011-07-08 13:00:01,0.361783886347\r\n2011-07-08 14:00:01,0.309215412949\r\n2011-07-08 15:00:01,0.323232323232\r\n2011-07-08 16:00:01,0.228027186216\r\n2011-07-08 17:00:01,0.248385861855\r\n2011-07-08 18:00:01,0.230339962317\r\n2011-07-08 19:00:01,0.199236511832\r\n2011-07-08 20:00:01,0.182615991827\r\n2011-07-08 21:00:01,0.201566213223\r\n2011-07-08 22:00:01,0.197890930527\r\n2011-07-08 23:00:01,0.180271292582\r\n2011-07-09 00:00:01,0.192514343728\r\n2011-07-09 01:00:01,0.15683009122\r\n2011-07-09 02:00:01,0.129613425807\r\n2011-07-09 03:00:01,0.110494486342\r\n2011-07-09 04:00:01,0.170957809371\r\n2011-07-09 05:00:01,0.237131289763\r\n2011-07-09 06:00:01,0.229209149397\r\n2011-07-09 07:00:01,0.298367102676\r\n2011-07-09 08:00:01,0.499133363352\r\n2011-07-09 09:00:01,0.464385632928\r\n2011-07-09 10:00:01,0.472395538999\r\n2011-07-09 11:00:01,0.544146269537\r\n2011-07-09 12:00:01,0.577541441502\r\n2011-07-09 13:00:01,0.515494108308\r\n2011-07-09 14:00:01,0.407933425798\r\n2011-07-09 15:00:01,0.399840114981\r\n2011-07-09 16:00:01,0.353425088801\r\n2011-07-09 17:00:01,0.288194806737\r\n2011-07-09 18:00:01,0.215691621082\r\n2011-07-09 19:00:01,0.235888689633\r\n2011-07-09 20:00:01,0.191367325907\r\n2011-07-09 21:00:01,0.188934143242\r\n2011-07-09 22:00:01,0.201572828906\r\n2011-07-09 23:00:01,0.22097753552\r\n2011-07-10 00:00:01,0.20411036036\r\n2011-07-10 01:00:01,0.162965130084\r\n2011-07-10 02:00:01,0.119492242233\r\n2011-07-10 03:00:01,0.11211438251\r\n2011-07-10 04:00:01,0.132642082613\r\n2011-07-10 05:00:01,0.222133726255\r\n2011-07-10 06:00:01,0.191750214286\r\n2011-07-10 07:00:01,0.260790149008\r\n2011-07-10 08:00:01,0.471314096973\r\n2011-07-10 09:00:01,0.477296463143\r\n2011-07-10 10:00:01,0.446584938704\r\n2011-07-10 11:00:01,0.496146481342\r\n2011-07-10 12:00:01,0.495432405878\r\n2011-07-10 13:00:01,0.429185534206\r\n2011-07-10 14:00:01,0.416406816228\r\n2011-07-10 15:00:01,0.376365524788\r\n2011-07-10 16:00:01,0.346310385427\r\n2011-07-10 17:00:01,0.324941180324\r\n2011-07-10 18:00:01,0.224988446606\r\n2011-07-10 19:00:01,0.193877335585\r\n2011-07-10 20:00:01,0.195783481953\r\n2011-07-10 21:00:01,0.179647327158\r\n2011-07-10 22:00:01,0.179125049492\r\n2011-07-10 23:00:01,0.15644170512\r\n2011-07-11 00:00:01,0.139389470106\r\n2011-07-11 01:00:01,0.140954515364\r\n2011-07-11 02:00:01,0.0922539182816\r\n2011-07-11 03:00:01,0.082216125654\r\n2011-07-11 04:00:01,0.0908497986666\r\n2011-07-11 05:00:01,0.157180412254\r\n2011-07-11 06:00:01,0.1727280618\r\n2011-07-11 07:00:01,0.256565982078\r\n2011-07-11 08:00:01,0.428283732379\r\n2011-07-11 09:00:01,0.444226956124\r\n2011-07-11 10:00:01,0.483698194053\r\n2011-07-11 11:00:01,0.458668492213\r\n2011-07-11 12:00:01,0.418402013567\r\n2011-07-11 13:00:01,0.393451621757\r\n2011-07-11 14:00:01,0.313871961208\r\n2011-07-11 15:00:01,0.2891833066\r\n2011-07-11 16:00:01,0.249155689411\r\n2011-07-11 17:00:01,0.25617308183\r\n2011-07-11 18:00:01,0.212968170705\r\n2011-07-11 19:00:01,0.216770052025\r\n2011-07-11 20:00:01,0.197776496284\r\n2011-07-11 21:00:01,0.187934318994\r\n2011-07-11 22:00:01,0.187420141712\r\n2011-07-11 23:00:01,0.187506940589\r\n2011-07-12 00:00:01,0.168980614452\r\n2011-07-12 01:00:01,0.152074937809\r\n2011-07-12 02:00:01,0.137461484942\r\n2011-07-12 03:00:01,0.104112579122\r\n2011-07-12 04:00:01,0.142918552002\r\n2011-07-12 05:00:01,0.143275447091\r\n2011-07-12 06:00:01,0.185618913885\r\n2011-07-12 07:00:01,0.172907780556\r\n2011-07-12 08:00:01,0.489569415766\r\n2011-07-12 09:00:01,0.475371441118\r\n2011-07-12 10:00:01,0.510875190931\r\n2011-07-12 11:00:01,0.539295638516\r\n2011-07-12 12:00:01,0.562670369799\r\n2011-07-12 13:00:01,0.493639908065\r\n2011-07-12 14:00:01,0.375071761179\r\n2011-07-12 15:00:01,0.367231783852\r\n2011-07-12 16:00:01,0.309527758348\r\n2011-07-12 17:00:01,0.289907743167\r\n2011-07-12 18:00:01,0.247273915988\r\n2011-07-12 19:00:01,0.225066896458\r\n2011-07-12 20:00:01,0.235480042627\r\n2011-07-12 21:00:01,0.243742335442\r\n2011-07-12 22:00:01,0.226198468573\r\n2011-07-12 23:00:01,0.220480258123\r\n2011-07-13 00:00:01,0.177474657233\r\n2011-07-13 01:00:01,0.165109689891\r\n2011-07-13 02:00:01,0.130659891709\r\n2011-07-13 03:00:01,0.114740658034\r\n2011-07-13 04:00:01,0.141167988992\r\n2011-07-13 05:00:01,0.186317495352\r\n2011-07-13 06:00:01,0.229541927497\r\n2011-07-13 07:00:01,0.373358604369\r\n2011-07-13 08:00:01,0.487958224908\r\n2011-07-13 09:00:01,0.539149888143\r\n2011-07-13 10:00:01,0.464484920282\r\n2011-07-13 11:00:01,0.622171145686\r\n2011-07-13 12:00:01,0.557672400502\r\n2011-07-13 13:00:01,0.454296051165\r\n2011-07-13 14:00:01,0.455315598903\r\n2011-07-13 15:00:01,0.40590212985\r\n2011-07-13 16:00:01,0.412460472538\r\n2011-07-13 17:00:01,0.321670941047\r\n2011-07-13 18:00:01,0.313384053393\r\n2011-07-13 19:00:01,0.261011165287\r\n2011-07-13 20:00:01,0.267151307818\r\n2011-07-13 21:00:01,0.202422469962\r\n2011-07-13 22:00:01,0.250151828141\r\n2011-07-13 23:00:01,0.258616476517\r\n2011-07-14 00:00:01,0.203289190586\r\n2011-07-14 01:00:01,0.167275100891\r\n2011-07-14 02:00:01,0.129840366979\r\n2011-07-14 03:00:01,0.117719206301\r\n2011-07-14 04:00:01,0.185196847018\r\n2011-07-14 05:00:01,0.252898111735\r\n2011-07-14 06:00:01,0.231405043299\r\n2011-07-14 07:00:01,0.368990180311\r\n2011-07-14 08:00:01,0.493794641216\r\n2011-07-14 09:00:01,0.495958899818\r\n2011-07-14 10:00:01,0.449545022409\r\n2011-07-14 11:00:01,0.418541266078\r\n2011-07-14 12:00:01,0.594471687259\r\n2011-07-14 13:00:01,0.660831736496\r\n2011-07-14 14:00:01,0.564546967788\r\n2011-07-14 15:00:01,0.426793043242\r\n2011-07-14 16:00:01,0.401047443943\r\n2011-07-14 17:00:01,0.249061577522\r\n2011-07-14 18:00:01,0.310849033716\r\n2011-07-14 19:00:01,0.233542090686\r\n2011-07-14 20:00:01,0.216787081441\r\n2011-07-14 21:00:01,0.234240406218\r\n2011-07-14 22:00:01,0.224834627552\r\n2011-07-14 23:00:01,0.224770026795\r\n2011-07-15 00:00:01,0.186996327941\r\n2011-07-15 01:00:01,0.192104631629\r\n2011-07-15 02:00:01,0.134936613375\r\n2011-07-15 03:00:01,0.129935763999\r\n2011-07-15 04:00:01,0.167604705679\r\n2011-07-15 05:00:01,0.181410049787\r\n2011-07-15 06:00:01,0.231296513212\r\n2011-07-15 07:00:01,0.288950955201\r\n2011-07-15 08:00:01,0.459122644791\r\n2011-07-15 09:00:01,0.577886549723\r\n2011-07-15 10:00:01,0.459511477173\r\n2011-07-15 11:00:01,0.573333333333\r\n2011-07-15 12:00:01,0.735811618194\r\n2011-07-15 13:00:01,0.531054359278\r\n2011-07-15 14:00:01,0.481355974591\r\n2011-07-15 15:00:01,0.449878916513\r\n2011-07-15 16:00:01,0.420883789935\r\n2011-07-15 17:00:01,0.322864798895\r\n2011-07-15 18:00:01,0.143973206366\r\n2011-07-15 19:00:01,0.0449098864075\r\n2011-07-15 20:00:01,0.231909669663\r\n2011-07-15 21:00:01,0.307814215642\r\n2011-07-15 22:00:01,0.215337200416\r\n2011-07-15 23:00:01,0.200955847706\r\n2011-07-16 00:00:01,0.457925390707\r\n2011-07-16 01:00:01,0.207633787425\r\n2011-07-16 02:00:01,0.183786893926\r\n2011-07-16 03:00:01,0.166145206736\r\n2011-07-16 04:00:01,0.0546898928025\r\n2011-07-16 05:00:01,0.41349399435\r\n2011-07-16 06:00:01,0.21266565237\r\n2011-07-16 07:00:01,0.405484768787\r\n2011-07-16 08:00:01,0.393868203116\r\n2011-07-16 09:00:01,0.529876582362\r\n2011-07-16 10:00:01,0.474258533856\r\n2011-07-16 11:00:01,0.48150129635\r\n2011-07-16 12:00:01,0.714378546983\r\n2011-07-16 13:00:01,0.594970759306\r\n2011-07-16 14:00:01,0.497414475258\r\n2011-07-16 15:00:01,0.472394120161\r\n2011-07-16 16:00:01,0.391052321493\r\n2011-07-16 17:00:01,0.347261857056\r\n2011-07-16 18:00:01,0.295052657131\r\n2011-07-16 19:00:01,0.279554883486\r\n2011-07-16 20:00:01,0.247339868564\r\n2011-07-16 21:00:01,0.234330907379\r\n2011-07-16 22:00:01,0.244476551099\r\n2011-07-16 23:00:01,0.260264476655\r\n2011-07-17 00:00:01,0.19759374095\r\n2011-07-17 01:00:01,0.196832352893\r\n2011-07-17 02:00:01,0.165662875197\r\n2011-07-17 03:00:01,0.143359111767\r\n2011-07-17 04:00:01,0.21387587975\r\n2011-07-17 05:00:01,0.217570859757\r\n2011-07-17 06:00:01,0.234414152551\r\n2011-07-17 07:00:01,0.346885066425\r\n2011-07-17 08:00:01,0.417195190785\r\n2011-07-17 09:00:01,0.42452044101\r\n2011-07-17 10:00:01,0.548663964034\r\n2011-07-17 11:00:01,0.584730174357\r\n2011-07-17 12:00:01,0.6129684815\r\n2011-07-17 13:00:01,0.570864765338\r\n2011-07-17 14:00:01,0.58035288204\r\n2011-07-17 15:00:01,0.525839273396\r\n2011-07-17 16:00:01,0.396771251233\r\n2011-07-17 17:00:01,0.346949542015\r\n2011-07-17 18:00:01,0.288522229931\r\n2011-07-17 19:00:01,0.256968065004\r\n2011-07-17 20:00:01,0.270501758648\r\n2011-07-17 21:00:01,0.239742956006\r\n2011-07-17 22:00:01,0.234361529517\r\n2011-07-17 23:00:01,0.187886021629\r\n2011-07-18 00:00:01,0.225183226125\r\n2011-07-18 01:00:01,0.161582089438\r\n2011-07-18 02:00:01,0.150193152414\r\n2011-07-18 03:00:01,0.138530070901\r\n2011-07-18 04:00:01,0.139423483631\r\n2011-07-18 05:00:01,0.145971095318\r\n2011-07-18 06:00:01,0.186878853127\r\n2011-07-18 07:00:01,0.319640385124\r\n2011-07-18 08:00:01,0.520614428117\r\n2011-07-18 09:00:01,0.453551781296\r\n2011-07-18 10:00:01,0.502821160261\r\n2011-07-18 11:00:01,0.59417456907\r\n2011-07-18 12:00:01,0.416779265447\r\n2011-07-18 13:00:01,0.457051579327\r\n2011-07-18 14:00:01,0.425053888784\r\n2011-07-18 15:00:01,0.391342369917\r\n2011-07-18 16:00:01,0.565611458262\r\n2011-07-18 17:00:01,0.321790125479\r\n2011-07-18 18:00:01,0.224332674191\r\n2011-07-18 19:00:01,0.246549051451\r\n2011-07-18 20:00:01,0.208119218911\r\n2011-07-18 21:00:01,0.228249765454\r\n2011-07-18 22:00:01,0.207939342422\r\n2011-07-18 23:00:01,0.202166765437\r\n2011-07-19 00:00:01,0.209550828532\r\n2011-07-19 01:00:01,0.184091194376\r\n2011-07-19 02:00:01,0.175728556885\r\n2011-07-19 03:00:01,0.156583178334\r\n2011-07-19 04:00:01,0.169780127627\r\n2011-07-19 05:00:01,0.213679793221\r\n2011-07-19 06:00:01,0.307929755045\r\n2011-07-19 07:00:01,0.206288191397\r\n2011-07-19 08:00:01,0.384913156022\r\n2011-07-19 09:00:01,0.485701650943\r\n2011-07-19 10:00:01,0.543841413616\r\n2011-07-19 11:00:01,0.512707996911\r\n2011-07-19 12:00:01,0.514567697661\r\n2011-07-19 13:00:01,0.387080490715\r\n2011-07-19 14:00:01,0.299222659994\r\n2011-07-19 15:00:01,0.467463346053\r\n2011-07-19 16:00:01,0.305939401882\r\n2011-07-19 17:00:01,0.266237288393\r\n2011-07-19 18:00:01,0.228824225875\r\n2011-07-19 19:00:01,0.377479839707\r\n2011-07-19 20:00:01,0.222640362231\r\n2011-07-19 21:00:01,0.239374301933\r\n2011-07-19 22:00:01,0.210807509061\r\n2011-07-19 23:00:01,0.20721999674\r\n2011-07-20 00:00:01,0.183171233672\r\n2011-07-20 01:00:01,0.17535293411\r\n2011-07-20 02:00:01,0.149082471767\r\n2011-07-20 03:00:01,0.13322111022\r\n2011-07-20 04:00:01,0.152328400635\r\n2011-07-20 05:00:01,0.194135398375\r\n2011-07-20 06:00:01,0.228316568609\r\n2011-07-20 07:00:01,0.317831969929\r\n2011-07-20 08:00:01,0.368739205527\r\n2011-07-20 09:00:01,0.506948990382\r\n2011-07-20 10:00:01,0.47500309751\r\n2011-07-20 11:00:01,0.493425888118\r\n2011-07-20 12:00:01,0.484030128533\r\n2011-07-20 13:00:01,0.525203484221\r\n2011-07-20 14:00:01,0.37446179272\r\n2011-07-20 15:00:01,0.298930848455\r\n2011-07-20 16:00:01,0.209247912154\r\n2011-07-20 17:00:01,0.395342238767\r\n2011-07-20 18:00:01,0.247451712976\r\n2011-07-20 19:00:01,0.201449246669\r\n2011-07-20 20:00:01,0.226587929504\r\n2011-07-20 21:00:01,0.216551601378\r\n2011-07-20 22:00:01,0.217818915146\r\n2011-07-20 23:00:01,0.279013742631\r\n2011-07-21 00:00:01,0.176800070317\r\n2011-07-21 01:00:01,0.155743881702\r\n2011-07-21 02:00:01,0.16790458896\r\n2011-07-21 03:00:01,0.145339317705\r\n2011-07-21 04:00:01,0.162310985782\r\n2011-07-21 06:00:01,0.225127023514\r\n2011-07-21 07:00:01,0.305405131769\r\n2011-07-21 08:00:01,0.272592485817\r\n2011-07-21 09:00:01,0.333844887792\r\n2011-07-21 10:00:01,0.500682860209\r\n2011-07-21 11:00:01,0.394310306282\r\n2011-07-21 12:00:01,0.688708170058\r\n2011-07-21 13:00:01,0.546541474379\r\n2011-07-21 14:00:01,0.468349650727\r\n2011-07-21 15:00:01,0.438412517347\r\n2011-07-21 16:00:01,0.405492179511\r\n2011-07-21 17:00:01,0.34746436655\r\n2011-07-21 18:00:01,0.355934947384\r\n2011-07-21 19:00:01,0.321369405386\r\n2011-07-21 20:00:01,0.297296988465\r\n2011-07-21 21:00:01,0.310397325461\r\n2011-07-21 22:00:01,0.279340360019\r\n2011-07-21 23:00:01,0.273138547997\r\n2011-07-22 00:00:01,0.216208416255\r\n2011-07-22 01:00:01,0.218956491608\r\n2011-07-22 02:00:01,0.185362212692\r\n2011-07-22 03:00:01,0.160410400635\r\n2011-07-22 04:00:01,0.2296313499\r\n2011-07-22 05:00:01,0.211899236364\r\n2011-07-22 06:00:01,0.236990707817\r\n2011-07-22 07:00:01,0.285074808417\r\n2011-07-22 08:00:01,0.496803531495\r\n2011-07-22 09:00:01,0.414682750962\r\n2011-07-22 10:00:01,0.658459017973\r\n2011-07-22 11:00:01,0.477002967359\r\n2011-07-22 12:00:01,0.596746877025\r\n2011-07-22 13:00:01,0.512225170584\r\n2011-07-22 14:00:01,0.491375775283\r\n2011-07-22 15:00:01,0.376930826058\r\n2011-07-22 16:00:01,0.335408585677\r\n2011-07-22 17:00:01,0.331426247669\r\n2011-07-22 18:00:01,0.330962613101\r\n2011-07-22 19:00:01,0.165794585514\r\n2011-07-22 20:00:01,0.394205934513\r\n2011-07-22 21:00:01,0.285497024143\r\n2011-07-22 22:00:01,0.285426606134\r\n2011-07-22 23:00:01,0.28290912475\r\n2011-07-23 00:00:01,0.26473414201\r\n2011-07-23 01:00:01,0.294095349176\r\n2011-07-23 02:00:01,0.214179244496\r\n2011-07-23 03:00:01,0.180678676961\r\n2011-07-23 04:00:01,0.270198998415\r\n2011-07-23 05:00:01,0.271868273594\r\n2011-07-23 06:00:01,0.224572434312\r\n2011-07-23 07:00:01,0.362203601746\r\n2011-07-23 08:00:01,0.493507761398\r\n2011-07-23 09:00:01,0.486753791412\r\n2011-07-23 10:00:01,0.509806435072\r\n2011-07-23 11:00:01,0.606573130886\r\n2011-07-23 12:00:01,0.620478347304\r\n2011-07-23 13:00:01,0.536817575544\r\n2011-07-23 14:00:01,0.588276778053\r\n2011-07-23 15:00:01,0.520050669728\r\n2011-07-23 16:00:01,0.407757000099\r\n2011-07-23 17:00:01,0.320313118552\r\n2011-07-23 18:00:01,0.30309578123\r\n2011-07-23 19:00:01,0.256693040856\r\n2011-07-23 20:00:01,0.229650861622\r\n2011-07-23 21:00:01,0.199366122475\r\n2011-07-23 22:00:01,0.204156773323\r\n2011-07-23 23:00:01,0.201065369338\r\n2011-07-24 00:00:01,0.211396157209\r\n2011-07-24 01:00:01,0.174167629608\r\n2011-07-24 02:00:01,0.128643599089\r\n2011-07-24 03:00:01,0.113269608672\r\n2011-07-24 04:00:01,0.193969379098\r\n2011-07-24 05:00:01,0.211982066182\r\n2011-07-24 06:00:01,0.182067187626\r\n2011-07-24 07:00:01,0.28538258695\r\n2011-07-24 08:00:01,0.289536124982\r\n2011-07-24 09:00:01,0.43311355076\r\n2011-07-24 10:00:01,0.434267710905\r\n2011-07-24 11:00:01,0.6073508454\r\n2011-07-24 12:00:01,0.551777941294\r\n2011-07-24 13:00:01,0.513737999711\r\n2011-07-24 14:00:01,0.575968342251\r\n2011-07-24 15:00:01,0.464939917259\r\n2011-07-24 16:00:01,0.363468714432\r\n2011-07-24 17:00:01,0.292985374913\r\n2011-07-24 18:00:01,0.274288096558\r\n2011-07-24 19:00:01,0.212545877133\r\n2011-07-24 20:00:01,0.213512020559\r\n2011-07-24 21:00:01,0.198521271775\r\n2011-07-24 22:00:01,0.191002754581\r\n2011-07-24 23:00:01,0.176639853272\r\n2011-07-25 00:00:01,0.17807286211\r\n2011-07-25 01:00:01,0.135347010517\r\n2011-07-25 02:00:01,0.114142604504\r\n2011-07-25 03:00:01,0.104569738809\r\n2011-07-25 04:00:01,0.144246911642\r\n2011-07-25 05:00:01,0.170474143934\r\n2011-07-25 06:00:01,0.153459241305\r\n2011-07-25 07:00:01,0.190020237895\r\n2011-07-25 08:00:01,0.375302939367\r\n2011-07-25 09:00:01,0.347942083762\r\n2011-07-25 10:00:01,0.390454308388\r\n2011-07-25 11:00:01,0.409452112087\r\n2011-07-25 12:00:01,0.430285297861\r\n2011-07-25 13:00:01,0.424308833446\r\n2011-07-25 14:00:01,0.452680324746\r\n2011-07-25 15:00:01,0.445520436247\r\n2011-07-25 16:00:01,0.157649955543\r\n2011-07-25 17:00:01,0.400905529913\r\n2011-07-25 18:00:01,0.24124369894\r\n2011-07-25 19:00:01,0.169687077264\r\n2011-07-25 20:00:01,0.235160002135\r\n2011-07-25 21:00:01,0.200913242009\r\n2011-07-25 22:00:01,0.203985491786\r\n2011-07-25 23:00:01,0.205137620179\r\n2011-07-26 00:00:01,0.142881356485\r\n2011-07-26 01:00:01,0.448868356238\r\n2011-07-26 02:00:01,0.139351944698\r\n2011-07-26 03:00:01,0.128736004655\r\n2011-07-26 04:00:01,0.128572624444\r\n2011-07-26 05:00:01,0.162722674678\r\n2011-07-26 06:00:01,0.000983971620187\r\n2011-07-26 07:00:01,0.242902773348\r\n2011-07-26 08:00:01,0.38248295024\r\n2011-07-26 09:00:01,0.329844801022\r\n2011-07-26 10:00:01,0.5233777315\r\n2011-07-26 11:00:01,0.458856512273\r\n2011-07-26 12:00:01,0.399162869787\r\n2011-07-26 13:00:01,0.379555694156\r\n2011-07-26 14:00:01,0.419891863465\r\n2011-07-26 15:00:01,0.300920186241\r\n2011-07-26 16:00:01,0.28030162283\r\n2011-07-26 17:00:01,0.253520184622\r\n2011-07-26 18:00:01,0.259408524489\r\n2011-07-26 19:00:01,0.193844435914\r\n2011-07-26 20:00:01,0.218603988717\r\n2011-07-26 21:00:01,0.195998000527\r\n2011-07-26 22:00:01,0.1877134733\r\n2011-07-26 23:00:01,0.196431126834\r\n2011-07-27 00:00:01,0.176174912325\r\n2011-07-27 01:00:01,0.161064534026\r\n2011-07-27 02:00:01,0.14548881067\r\n2011-07-27 03:00:01,0.10755273831\r\n2011-07-27 04:00:01,0.155952563936\r\n2011-07-27 05:00:01,0.209577337144\r\n2011-07-27 06:00:01,0.148669490265\r\n2011-07-27 07:00:01,0.209511837419\r\n2011-07-27 08:00:01,0.295059356682\r\n2011-07-27 09:00:01,0.361572165905\r\n2011-07-27 10:00:01,0.439566245328\r\n2011-07-27 11:00:01,0.491474788691\r\n2011-07-27 12:00:01,0.442614926619\r\n2011-07-27 13:00:01,0.448160352579\r\n2011-07-27 14:00:01,0.438678027369\r\n2011-07-27 15:00:01,0.37405645226\r\n2011-07-27 16:00:01,0.379522109676\r\n2011-07-27 17:00:01,0.321533673235\r\n2011-07-27 18:00:01,0.331314163382\r\n2011-07-27 19:00:01,0.259387243472\r\n2011-07-27 20:00:01,0.256637040872\r\n2011-07-27 21:00:01,0.225029690994\r\n2011-07-27 22:00:01,0.243701401417\r\n2011-07-27 23:00:01,0.213428038176\r\n2011-07-28 00:00:01,0.147534516765\r\n2011-07-28 01:00:01,0.221122616563\r\n2011-07-28 02:00:01,0.157066545009\r\n2011-07-28 03:00:01,0.135839707145\r\n2011-07-28 04:00:01,0.142731993306\r\n2011-07-28 05:00:01,0.203193201254\r\n2011-07-28 06:00:01,0.162148007374\r\n2011-07-28 07:00:01,0.0356090305386\r\n2011-07-28 08:00:01,0.517897285146\r\n2011-07-28 09:00:01,0.370649235087\r\n2011-07-28 10:00:01,0.612499485928\r\n2011-07-28 11:00:01,0.478236502896\r\n2011-07-28 12:00:01,0.446529542833\r\n2011-07-28 13:00:01,0.419630308694\r\n2011-07-28 14:00:01,0.404135857732\r\n2011-07-28 15:00:01,0.378717263569\r\n2011-07-28 16:00:01,0.00326508400789\r\n2011-07-28 17:00:01,0.00307836835862\r\n2011-07-28 18:00:01,0.455160685778\r\n2011-07-28 19:00:01,0.297786274149\r\n2011-07-28 20:00:01,0.202158077792\r\n2011-07-28 21:00:01,0.241454196911\r\n2011-07-28 22:00:01,0.220964257391\r\n2011-07-28 23:00:01,0.225213493959\r\n2011-07-29 00:00:01,0.211517106446\r\n2011-07-29 01:00:01,0.196341739229\r\n2011-07-29 02:00:01,0.147722062332\r\n2011-07-29 03:00:01,0.134019815857\r\n2011-07-29 04:00:01,0.141013537197\r\n2011-07-29 05:00:01,0.168965441467\r\n2011-07-29 06:00:01,0.158813135032\r\n2011-07-29 07:00:01,0.223773542028\r\n2011-07-29 08:00:01,0.457448087743\r\n2011-07-29 09:00:01,0.497110585763\r\n2011-07-29 10:00:01,0.469454155973\r\n2011-07-29 11:00:01,0.495279695646\r\n2011-07-29 12:00:01,0.465535068068\r\n2011-07-29 13:00:01,0.531950947043\r\n2011-07-29 14:00:01,0.45310146576\r\n2011-07-29 15:00:01,0.427706184123\r\n2011-07-29 16:00:01,0.172425168071\r\n2011-07-29 17:00:01,0.423704927457\r\n2011-07-29 18:00:01,0.266947696995\r\n2011-07-29 19:00:01,0.260453726674\r\n2011-07-29 20:00:01,0.062668451477\r\n2011-07-29 21:00:01,0.335431661925\r\n2011-07-29 22:00:01,0.220403664009\r\n2011-07-29 23:00:01,0.273034152036\r\n2011-07-30 00:00:01,0.229069311321\r\n2011-07-30 01:00:01,0.209343911864\r\n2011-07-30 02:00:01,0.154835868682\r\n2011-07-30 03:00:01,0.171468364853\r\n2011-07-30 04:00:01,0.203818083967\r\n2011-07-30 05:00:01,0.298213445003\r\n2011-07-30 06:00:01,0.232935602737\r\n2011-07-30 07:00:01,0.271720206092\r\n2011-07-30 08:00:01,0.375881709479\r\n2011-07-30 09:00:01,0.377435538444\r\n2011-07-30 10:00:01,0.439536282858\r\n2011-07-30 11:00:01,0.577576802062\r\n2011-07-30 12:00:01,0.475051899481\r\n2011-07-30 13:00:01,0.561543737839\r\n2011-07-30 14:00:01,0.454925326176\r\n2011-07-30 15:00:01,0.41081754716\r\n2011-07-30 16:00:01,0.310035490495\r\n2011-07-30 17:00:01,0.318734610636\r\n2011-07-30 18:00:01,0.322629535726\r\n2011-07-30 19:00:01,0.263100107643\r\n2011-07-30 20:00:01,0.239908136512\r\n2011-07-30 21:00:01,0.24635895478\r\n2011-07-30 22:00:01,0.234870484843\r\n2011-07-30 23:00:01,0.235311703923\r\n2011-07-31 00:00:01,0.25892067675\r\n2011-07-31 01:00:01,0.215918456552\r\n2011-07-31 02:00:01,0.168897432416\r\n2011-07-31 03:00:01,0.13620050354\r\n2011-07-31 04:00:01,0.195074396444\r\n2011-07-31 05:00:01,0.257899682382\r\n2011-07-31 06:00:01,0.21212590836\r\n2011-07-31 07:00:01,0.253616780446\r\n2011-07-31 08:00:01,0.280396110798\r\n2011-07-31 09:00:01,0.335011022836\r\n2011-07-31 10:00:01,0.325472865004\r\n2011-07-31 11:00:01,0.478309878796\r\n2011-07-31 12:00:01,0.42241017221\r\n2011-07-31 13:00:01,0.428092396729\r\n2011-07-31 14:00:01,0.454567579407\r\n2011-07-31 15:00:01,0.434495021948\r\n2011-07-31 16:00:01,0.376663051281\r\n2011-07-31 17:00:01,0.276657889247\r\n2011-07-31 18:00:01,0.231251390096\r\n2011-07-31 19:00:01,0.230442483964\r\n2011-07-31 20:00:01,0.221718482353\r\n2011-07-31 21:00:01,0.147292482506\r\n2011-07-31 22:00:01,0.2719695304\r\n2011-07-31 23:00:01,0.18424957212\r\n2011-08-01 00:00:01,0.183854930206\r\n2011-08-01 01:00:01,0.146498617435\r\n2011-08-01 02:00:01,0.136459424487\r\n2011-08-01 03:00:01,0.087785768676\r\n2011-08-01 04:00:01,0.113553461349\r\n2011-08-01 05:00:01,0.123708237311\r\n2011-08-01 06:00:01,0.149411987548\r\n2011-08-01 07:00:01,0.218854736601\r\n2011-08-01 08:00:01,0.361513984073\r\n2011-08-01 09:00:01,0.20819818985\r\n2011-08-01 10:00:01,0.488597227448\r\n2011-08-01 11:00:01,0.508212583188\r\n2011-08-01 12:00:01,0.41313021761\r\n2011-08-01 13:00:01,0.448025379708\r\n2011-08-01 14:00:01,0.359762170646\r\n2011-08-01 15:00:01,0.376602931511\r\n2011-08-01 16:00:01,0.289073768803\r\n2011-08-01 17:00:01,0.316292739115\r\n2011-08-01 18:00:01,0.323627807345\r\n2011-08-01 19:00:01,0.25922530369\r\n2011-08-01 20:00:01,0.229332661947\r\n2011-08-01 21:00:01,0.217184733646\r\n2011-08-01 22:00:01,0.202887167798\r\n2011-08-01 23:00:01,0.192562989504\r\n2011-08-02 00:00:01,0.175209644865\r\n2011-08-02 01:00:01,0.130037217212\r\n2011-08-02 02:00:01,0.172503691226\r\n2011-08-02 03:00:01,0.102679648204\r\n2011-08-02 04:00:01,0.122842945119\r\n2011-08-02 05:00:01,0.162794978716\r\n2011-08-02 06:00:01,0.171762466504\r\n2011-08-02 07:00:01,0.291704229404\r\n2011-08-02 08:00:01,0.401144203264\r\n2011-08-02 09:00:01,0.471953153836\r\n2011-08-02 10:00:01,0.447094298246\r\n2011-08-02 11:00:01,0.581099131105\r\n2011-08-02 12:00:01,0.464249548487\r\n2011-08-02 13:00:01,0.496229838855\r\n2011-08-02 14:00:01,0.452098154126\r\n2011-08-02 15:00:01,0.433815975945\r\n2011-08-02 16:00:01,0.387994271038\r\n2011-08-02 17:00:01,0.338336251156\r\n2011-08-02 18:00:01,0.309087077998\r\n2011-08-02 19:00:01,0.290744323188\r\n2011-08-02 20:00:01,0.305809320552\r\n2011-08-02 21:00:01,0.317276030146\r\n2011-08-02 22:00:01,0.29720504068\r\n2011-08-02 23:00:01,0.235773190287\r\n2011-08-03 00:00:01,0.188286974461\r\n2011-08-03 01:00:01,0.171487446869\r\n2011-08-03 02:00:01,0.133994781432\r\n2011-08-03 03:00:01,0.10274998997\r\n2011-08-03 04:00:01,0.128252606457\r\n2011-08-03 05:00:01,0.174345589129\r\n2011-08-03 06:00:01,0.153733810649\r\n2011-08-03 07:00:01,0.224686610782\r\n2011-08-03 08:00:01,0.362468087548\r\n2011-08-03 09:00:01,0.1944754871\r\n2011-08-03 10:00:01,0.691956124314\r\n2011-08-03 11:00:01,0.468199125652\r\n2011-08-03 12:00:01,0.444023939447\r\n2011-08-03 13:00:01,0.488482128973\r\n2011-08-03 14:00:01,0.453174792496\r\n2011-08-03 15:00:01,0.413451733329\r\n2011-08-03 16:00:01,0.378406614728\r\n2011-08-03 17:00:01,0.290162457252\r\n2011-08-03 18:00:01,0.267312071302\r\n2011-08-03 19:00:01,0.316459501711\r\n2011-08-03 20:00:01,0.260711886419\r\n2011-08-03 21:00:01,0.236257686646\r\n2011-08-03 22:00:01,0.233285806598\r\n2011-08-03 23:00:01,0.197457031016\r\n2011-08-04 00:00:01,0.158111370303\r\n2011-08-04 01:00:01,0.154896261014\r\n2011-08-04 02:00:01,0.128176016257\r\n2011-08-04 03:00:01,0.0970092266232\r\n2011-08-04 04:00:01,0.124495046127\r\n2011-08-04 05:00:01,0.134242511807\r\n2011-08-04 06:00:01,0.125320507716\r\n2011-08-04 07:00:01,0.229197163666\r\n2011-08-04 08:00:01,0.505902851026\r\n2011-08-04 09:00:01,0.4434204395\r\n2011-08-04 10:00:01,0.417950592782\r\n2011-08-04 11:00:01,0.534482758621\r\n2011-08-04 12:00:01,0.549754911728\r\n2011-08-04 13:00:01,0.47062494681\r\n2011-08-04 14:00:01,0.442797415431\r\n2011-08-04 15:00:01,0.412228226625\r\n2011-08-04 16:00:01,0.377236338633\r\n2011-08-04 17:00:01,0.277504550528\r\n2011-08-04 18:00:01,0.307153691718\r\n2011-08-04 19:00:01,0.251961989181\r\n2011-08-04 20:00:01,0.257590838762\r\n2011-08-04 21:00:01,0.248772705904\r\n2011-08-04 22:00:01,0.239097911372\r\n2011-08-04 23:00:01,0.221741388264\r\n2011-08-05 00:00:01,0.171688928697\r\n2011-08-05 01:00:01,0.157732699811\r\n2011-08-05 02:00:01,0.126886132106\r\n2011-08-05 03:00:01,0.100102337993\r\n2011-08-05 04:00:01,0.12949774781\r\n2011-08-05 05:00:01,0.190892065494\r\n2011-08-05 06:00:01,0.184490653727\r\n2011-08-05 07:00:01,0.337005713444\r\n2011-08-05 08:00:01,0.50548598641\r\n2011-08-05 09:00:01,0.556096708127\r\n2011-08-05 10:00:01,0.467201510146\r\n2011-08-05 11:00:01,0.567045802305\r\n2011-08-05 12:00:01,0.452915473859\r\n2011-08-05 13:00:01,0.496396431493\r\n2011-08-05 14:00:01,0.470616936536\r\n2011-08-05 15:00:01,0.427549619485\r\n2011-08-05 16:00:01,0.378977633828\r\n2011-08-05 17:00:01,0.332794411519\r\n2011-08-05 18:00:01,0.268990764623\r\n2011-08-05 19:00:01,0.274022173834\r\n2011-08-05 20:00:01,0.251701544928\r\n2011-08-05 21:00:01,0.241048360814\r\n2011-08-05 22:00:01,0.246216858429\r\n2011-08-05 23:00:01,0.215926329509\r\n2011-08-06 00:00:01,0.249949816738\r\n2011-08-06 01:00:01,0.158907963264\r\n2011-08-06 02:00:01,0.137552866091\r\n2011-08-06 03:00:01,0.197561654283\r\n2011-08-06 04:00:01,0.288752499144\r\n2011-08-06 05:00:01,0.381611047047\r\n2011-08-06 06:00:01,0.273987644537\r\n2011-08-06 07:00:01,0.500351036795\r\n2011-08-06 08:00:01,0.580597323769\r\n2011-08-06 09:00:01,0.430048801113\r\n2011-08-06 10:00:01,0.420263604131\r\n2011-08-06 11:00:01,0.534715574142\r\n2011-08-06 12:00:01,0.751038636193\r\n2011-08-06 13:00:01,0.526120396749\r\n2011-08-06 14:00:01,0.560445151722\r\n2011-08-06 15:00:01,0.405883598938\r\n2011-08-06 16:00:01,0.447607191665\r\n2011-08-06 17:00:01,0.369951829013\r\n2011-08-06 18:00:01,0.349190198989\r\n2011-08-06 19:00:01,0.300690835019\r\n2011-08-06 20:00:01,0.34599954003\r\n2011-08-06 21:00:01,0.310183250683\r\n2011-08-06 22:00:01,0.394767069663\r\n2011-08-06 23:00:01,0.308900212146\r\n2011-08-07 00:00:01,0.30013037612\r\n2011-08-07 01:00:01,0.257981928706\r\n2011-08-07 02:00:01,0.220632140194\r\n2011-08-07 03:00:01,0.213772281907\r\n2011-08-07 04:00:01,0.255685414881\r\n2011-08-07 05:00:01,0.329683456102\r\n2011-08-07 06:00:01,0.265684254769\r\n2011-08-07 07:00:01,0.442110689396\r\n2011-08-07 08:00:01,0.705293375736\r\n2011-08-07 09:00:01,0.48961762587\r\n2011-08-07 10:00:01,0.570971602411\r\n2011-08-07 11:00:01,0.22696418004\r\n2011-08-07 12:00:01,0.625506089104\r\n2011-08-07 13:00:01,0.58756714546\r\n2011-08-07 14:00:01,0.494468355527\r\n2011-08-07 15:00:01,0.485719475295\r\n2011-08-07 16:00:01,0.343257645616\r\n2011-08-07 17:00:01,0.326607707109\r\n2011-08-07 18:00:01,0.295759445392\r\n2011-08-07 19:00:01,0.255623742077\r\n2011-08-07 20:00:01,0.2688082445\r\n2011-08-07 21:00:01,0.1781069836\r\n2011-08-07 22:00:01,0.203492220123\r\n2011-08-07 23:00:01,0.181770487756\r\n2011-08-08 00:00:01,0.158421474179\r\n2011-08-08 01:00:01,0.147071211249\r\n2011-08-08 02:00:01,0.121540243196\r\n2011-08-08 03:00:01,0.0939121008678\r\n2011-08-08 04:00:01,0.125770320237\r\n2011-08-08 05:00:01,0.173913163759\r\n2011-08-08 06:00:01,0.164388738427\r\n2011-08-08 07:00:01,0.311083305709\r\n2011-08-08 08:00:01,0.538720538721\r\n2011-08-08 09:00:01,0.427245038836\r\n2011-08-08 10:00:01,0.504777937317\r\n2011-08-08 11:00:01,0.642475589125\r\n2011-08-08 12:00:01,0.552252988884\r\n2011-08-08 13:00:01,0.475174437756\r\n2011-08-08 14:00:01,0.488050599086\r\n2011-08-08 15:00:01,0.437199279633\r\n2011-08-08 16:00:01,0.371820079252\r\n2011-08-08 17:00:01,0.310788044919\r\n2011-08-08 19:00:01,0.303475913506\r\n2011-08-08 20:00:01,0.1854877826\r\n2011-08-08 21:00:01,0.228444369989\r\n2011-08-08 22:00:01,0.228988961458\r\n2011-08-08 23:00:01,0.224449362654\r\n2011-08-09 00:00:01,0.166602366156\r\n2011-08-09 01:00:01,0.136542467022\r\n2011-08-09 02:00:01,0.131424755232\r\n2011-08-09 03:00:01,0.120690831531\r\n2011-08-09 04:00:01,0.118270279458\r\n2011-08-09 05:00:01,0.162574348651\r\n2011-08-09 06:00:01,0.178186039626\r\n2011-08-09 07:00:01,0.303853030489\r\n2011-08-09 08:00:01,0.550789527651\r\n2011-08-09 09:00:01,0.441010177158\r\n2011-08-09 10:00:01,0.530068153571\r\n2011-08-09 11:00:01,0.464782413638\r\n2011-08-09 12:00:01,0.480716903095\r\n2011-08-09 13:00:01,0.438503988458\r\n2011-08-09 14:00:01,0.344222628775\r\n2011-08-09 15:00:01,0.164215514352\r\n2011-08-09 16:00:01,0.451334552102\r\n2011-08-09 17:00:01,0.488523409429\r\n2011-08-09 18:00:01,0.301641007852\r\n2011-08-09 19:00:01,0.262345464648\r\n2011-08-09 20:00:01,0.271071656625\r\n2011-08-09 21:00:01,0.257790414093\r\n2011-08-09 22:00:01,0.293765610568\r\n2011-08-09 23:00:01,0.20190184698\r\n2011-08-10 00:00:01,0.180893592905\r\n2011-08-10 01:00:01,0.183241464642\r\n2011-08-10 02:00:01,0.152546971805\r\n2011-08-10 03:00:01,0.121649223991\r\n2011-08-10 04:00:01,0.132782550453\r\n2011-08-10 05:00:01,0.191172813493\r\n2011-08-10 06:00:01,0.247488073346\r\n2011-08-10 07:00:01,0.307326101538\r\n2011-08-10 08:00:01,0.354036794891\r\n2011-08-10 09:00:01,0.517268550509\r\n2011-08-10 10:00:01,0.457137065099\r\n2011-08-10 11:00:01,0.546461283701\r\n2011-08-10 12:00:01,0.450287840718\r\n2011-08-10 13:00:01,0.482360222818\r\n2011-08-10 14:00:01,0.485721764645\r\n2011-08-10 15:00:01,0.587476998888\r\n2011-08-10 17:00:01,0.948150721473\r\n2011-08-10 18:00:01,0.65729071692\r\n2011-08-10 19:00:01,0.182410748433\r\n2011-08-10 20:00:01,0.210126419891\r\n2011-08-10 21:00:01,0.335356850457\r\n2011-08-10 22:00:01,0.298046930123\r\n2011-08-10 23:00:01,0.238643552035\r\n2011-08-11 00:00:01,0.212103377903\r\n2011-08-11 01:00:01,0.185923903004\r\n2011-08-11 02:00:01,0.154776075863\r\n2011-08-11 03:00:01,0.13665744862\r\n2011-08-11 04:00:01,0.160230773158\r\n2011-08-11 05:00:01,0.210830475115\r\n2011-08-11 06:00:01,0.286224224343\r\n2011-08-11 07:00:01,0.436791095675\r\n2011-08-11 08:00:01,0.461444787544\r\n2011-08-11 09:00:01,0.576718213058\r\n2011-08-11 10:00:01,0.678798876943\r\n2011-08-11 11:00:01,0.543104312101\r\n2011-08-11 12:00:01,0.651850316551\r\n2011-08-11 13:00:01,0.515319777893\r\n2011-08-11 14:00:01,0.567822431348\r\n2011-08-11 15:00:01,0.476313569699\r\n2011-08-11 16:00:01,0.410222140289\r\n2011-08-11 17:00:01,0.37021457723\r\n2011-08-11 18:00:01,0.0360733895514\r\n2011-08-11 19:00:01,0.323799955347\r\n2011-08-11 20:00:01,0.343160724482\r\n2011-08-11 21:00:01,0.397203435066\r\n2011-08-11 22:00:01,0.315529764651\r\n2011-08-11 23:00:01,0.30144478392\r\n2011-08-12 00:00:01,0.26762085518\r\n2011-08-12 01:00:01,0.233376729833\r\n2011-08-12 02:00:01,0.194452765968\r\n2011-08-12 03:00:01,0.138647787561\r\n2011-08-12 04:00:01,0.213030424064\r\n2011-08-12 05:00:01,0.258790799987\r\n2011-08-12 06:00:01,0.24952092977\r\n2011-08-12 07:00:01,0.276817816874\r\n2011-08-12 08:00:01,1.0514424748\r\n2011-08-12 09:00:01,0.550761758252\r\n2011-08-12 10:00:01,0.555629306912\r\n2011-08-12 11:00:01,0.609984557353\r\n2011-08-12 12:00:01,0.577830188679\r\n2011-08-12 13:00:01,0.590268886044\r\n2011-08-12 14:00:01,0.552825126341\r\n2011-08-12 15:00:01,0.491198332529\r\n2011-08-12 16:00:01,0.410258361313\r\n2011-08-12 17:00:01,0.33909556486\r\n2011-08-12 18:00:01,0.286050702466\r\n2011-08-12 19:00:01,0.323586496548\r\n2011-08-12 20:00:01,0.304786649345\r\n2011-08-12 21:00:01,0.255882392047\r\n2011-08-12 22:00:01,0.247207914596\r\n2011-08-12 23:00:01,0.250140836151\r\n2011-08-13 00:00:01,0.25194385834\r\n2011-08-13 01:00:01,0.258218632693\r\n2011-08-13 02:00:01,0.226015539942\r\n2011-08-13 03:00:01,0.159070977107\r\n2011-08-13 04:00:01,0.211005513585\r\n2011-08-13 05:00:01,0.247687565773\r\n2011-08-13 06:00:01,0.282709693961\r\n2011-08-13 07:00:01,0.424723840371\r\n2011-08-13 08:00:01,0.543314721321\r\n2011-08-13 09:00:01,0.61625\r\n2011-08-13 10:00:01,0.654440319992\r\n2011-08-13 11:00:01,0.635822510823\r\n2011-08-13 12:00:01,0.821226108237\r\n2011-08-13 13:00:01,0.842164545573\r\n2011-08-13 14:00:01,0.731631892872\r\n2011-08-13 15:00:01,0.540964671767\r\n2011-08-13 16:00:01,0.455897653464\r\n2011-08-13 17:00:01,0.374288563715\r\n2011-08-13 18:00:01,0.319265175906\r\n2011-08-13 19:00:01,0.307065473481\r\n2011-08-13 20:00:01,0.273386162835\r\n2011-08-13 21:00:01,0.260776318994\r\n2011-08-13 22:00:01,0.286839076795\r\n2011-08-13 23:00:01,0.278639375568\r\n2011-08-14 00:00:01,0.305872772168\r\n2011-08-14 01:00:01,0.287767656453\r\n2011-08-14 02:00:01,0.266756655086\r\n2011-08-14 03:00:01,0.261519269562\r\n2011-08-14 04:00:01,0.279994138609\r\n2011-08-14 05:00:01,0.357949130112\r\n2011-08-14 06:00:01,0.395057867769\r\n2011-08-14 07:00:01,0.514521207708\r\n2011-08-14 08:00:01,0.532560172426\r\n2011-08-14 09:00:01,0.476172430128\r\n2011-08-14 10:00:01,0.60236216865\r\n2011-08-14 11:00:01,0.644956314535\r\n2011-08-14 12:00:01,0.697846165352\r\n2011-08-14 13:00:01,0.698616430321\r\n2011-08-14 14:00:01,0.705035886297\r\n2011-08-14 15:00:01,0.617404347988\r\n2011-08-14 16:00:01,0.51239017303\r\n2011-08-14 17:00:01,0.403875086121\r\n2011-08-14 18:00:01,0.374578723674\r\n2011-08-14 19:00:01,0.285211260801\r\n2011-08-14 20:00:01,0.258318839399\r\n2011-08-14 21:00:01,0.247235485434\r\n2011-08-14 22:00:01,0.252419295524\r\n2011-08-14 23:00:01,0.215061345367\r\n2011-08-15 00:00:01,0.219272374672\r\n2011-08-15 01:00:01,0.259993491349\r\n2011-08-15 02:00:01,0.112465680559\r\n2011-08-15 03:00:01,0.129889907492\r\n2011-08-15 04:00:01,0.184368853672\r\n2011-08-15 05:00:01,0.291590392801\r\n2011-08-15 06:00:01,0.354687066255\r\n2011-08-15 07:00:01,0.369693934663\r\n2011-08-15 08:00:01,0.616148756951\r\n2011-08-15 09:00:01,0.571445358402\r\n2011-08-15 10:00:01,0.571309896915\r\n2011-08-15 11:00:01,0.763170368917\r\n2011-08-15 12:00:01,0.542183415828\r\n2011-08-15 13:00:01,0.624161269619\r\n2011-08-15 14:00:01,0.577879875789\r\n2011-08-15 15:00:01,0.674388083594\r\n2011-08-15 16:00:01,0.465648351938\r\n2011-08-15 17:00:01,0.379129244052\r\n2011-08-15 18:00:01,0.377605768531\r\n2011-08-15 19:00:01,0.295029612795\r\n2011-08-15 20:00:01,0.294380946024\r\n2011-08-15 21:00:01,0.286841907435\r\n2011-08-16 00:00:01,0.643067449002\r\n2011-08-16 01:00:01,0.111433485031\r\n2011-08-16 02:00:01,0.167272282104\r\n2011-08-16 03:00:01,0.136371705472\r\n2011-08-16 04:00:01,0.178216551315\r\n2011-08-16 05:00:01,0.213757839048\r\n2011-08-16 06:00:01,0.24371422548\r\n2011-08-16 07:00:01,0.397670672215\r\n2011-08-16 08:00:01,0.569862575619\r\n2011-08-16 09:00:01,0.615672379046\r\n2011-08-16 10:00:01,0.565135026756\r\n2011-08-16 11:00:01,0.649623908579\r\n2011-08-16 12:00:01,0.684601825906\r\n2011-08-16 13:00:01,0.649529655839\r\n2011-08-16 14:00:01,0.761553756413\r\n2011-08-16 15:00:01,0.547737809294\r\n2011-08-16 16:00:01,0.414905863704\r\n2011-08-16 17:00:01,0.345750477303\r\n2011-08-16 18:00:01,0.290037711535\r\n2011-08-16 19:00:01,0.291690037489\r\n2011-08-16 20:00:01,0.251921989966\r\n2011-08-16 21:00:01,0.253541172643\r\n2011-08-16 22:00:01,0.232801250976\r\n2011-08-16 23:00:01,0.217425777744\r\n2011-08-17 00:00:01,0.23586630843\r\n2011-08-17 01:00:01,0.195312307046\r\n2011-08-17 02:00:01,0.195701468993\r\n2011-08-17 03:00:01,0.204026143655\r\n2011-08-17 04:00:01,0.147768401599\r\n2011-08-17 05:00:01,0.268017002427\r\n2011-08-17 06:00:01,0.265700570732\r\n2011-08-17 07:00:01,0.398809933274\r\n2011-08-17 08:00:01,0.457430227251\r\n2011-08-17 09:00:01,0.652012359682\r\n2011-08-17 10:00:01,0.581056523374\r\n2011-08-17 11:00:01,0.484555758969\r\n2011-08-17 12:00:01,0.510756497832\r\n2011-08-17 13:00:01,0.552549276311\r\n2011-08-17 14:00:01,0.528956989498\r\n2011-08-17 15:00:01,0.49939939015\r\n2011-08-17 16:00:01,0.444223371391\r\n2011-08-17 17:00:01,0.345758932585\r\n2011-08-17 18:00:01,0.356207628528\r\n2011-08-17 19:00:01,0.365411529986\r\n2011-08-17 20:00:01,0.303964545498\r\n2011-08-17 21:00:01,0.312720759806\r\n2011-08-17 22:00:01,0.265141882694\r\n2011-08-17 23:00:01,0.203903533414\r\n2011-08-18 00:00:01,0.201826116196\r\n2011-08-18 01:00:01,0.176334283725\r\n2011-08-18 02:00:01,0.168131389871\r\n2011-08-18 03:00:01,0.126134290765\r\n2011-08-18 04:00:01,0.148568237737\r\n2011-08-18 05:00:01,0.185830771529\r\n2011-08-18 06:00:01,0.191789020266\r\n2011-08-18 07:00:01,0.357648865878\r\n2011-08-18 08:00:01,0.563748550423\r\n2011-08-18 09:00:01,0.621535383035\r\n2011-08-18 10:00:01,0.651507000683\r\n2011-08-18 11:00:01,0.552312904633\r\n2011-08-18 12:00:01,0.561417986445\r\n2011-08-18 13:00:01,0.472352077362\r\n2011-08-18 14:00:01,0.457558336152\r\n2011-08-18 15:00:01,0.514818687278\r\n2011-08-18 16:00:01,0.440904397665\r\n2011-08-18 17:00:01,0.438773033624\r\n2011-08-18 18:00:01,0.384591481943\r\n2011-08-18 19:00:01,0.3398700712\r\n2011-08-18 20:00:01,0.278668738629\r\n2011-08-18 21:00:01,0.288797207236\r\n2011-08-18 22:00:01,0.267286115268\r\n2011-08-18 23:00:01,0.223896266296\r\n2011-08-19 00:00:01,0.203410801178\r\n2011-08-19 01:00:01,0.175413151105\r\n2011-08-19 02:00:01,0.166775150428\r\n2011-08-19 03:00:01,0.12467887362\r\n2011-08-19 04:00:01,0.193797788902\r\n2011-08-19 05:00:01,0.193257346049\r\n2011-08-19 06:00:01,0.241784594303\r\n2011-08-19 07:00:01,0.468629026368\r\n2011-08-19 08:00:01,0.578231585846\r\n2011-08-19 09:00:01,0.654648474223\r\n2011-08-19 10:00:01,0.59239963224\r\n2011-08-19 11:00:01,0.632796894433\r\n2011-08-19 12:00:01,0.654688066566\r\n2011-08-19 13:00:01,0.860451897115\r\n2011-08-19 14:00:01,0.568877159379\r\n2011-08-19 15:00:01,0.548794271092\r\n2011-08-19 16:00:01,0.43334728228\r\n2011-08-19 17:00:01,0.32739514291\r\n2011-08-19 18:00:01,0.287733789679\r\n2011-08-19 19:00:01,0.333736493864\r\n2011-08-19 20:00:01,0.267481161941\r\n2011-08-19 21:00:01,0.253034377498\r\n2011-08-19 22:00:01,0.279273210119\r\n2011-08-19 23:00:01,0.230464507263\r\n2011-08-20 00:00:01,0.217553267932\r\n2011-08-20 01:00:01,0.222056393582\r\n2011-08-20 02:00:01,0.181206110186\r\n2011-08-20 03:00:01,0.146636380481\r\n2011-08-20 04:00:01,0.175709562939\r\n2011-08-20 05:00:01,0.253476618725\r\n2011-08-20 06:00:01,0.221588241906\r\n2011-08-20 07:00:01,0.40262623301\r\n2011-08-20 08:00:01,0.538118423632\r\n2011-08-20 09:00:01,0.537468938811\r\n2011-08-20 10:00:01,0.556407936321\r\n2011-08-20 11:00:01,0.56064608442\r\n2011-08-20 12:00:01,0.73048260471\r\n2011-08-20 13:00:01,0.6854003862\r\n2011-08-20 14:00:01,0.637795142698\r\n2011-08-20 15:00:01,0.490752336998\r\n2011-08-20 16:00:01,0.449458814896\r\n2011-08-20 17:00:01,0.31548826994\r\n2011-08-20 18:00:01,0.27838088113\r\n2011-08-20 19:00:01,0.236309268997\r\n2011-08-20 20:00:01,0.235254469267\r\n2011-08-20 21:00:01,0.220512119377\r\n2011-08-20 22:00:01,0.232456508137\r\n2011-08-20 23:00:01,0.240371118336\r\n2011-08-21 00:00:01,0.195062405022\r\n2011-08-21 01:00:01,0.219409444296\r\n2011-08-21 02:00:01,0.154082530934\r\n2011-08-21 03:00:01,0.124101873028\r\n2011-08-21 04:00:01,0.161069173093\r\n2011-08-21 05:00:01,0.224335890393\r\n2011-08-21 06:00:01,0.201105728499\r\n2011-08-21 07:00:01,0.327890515953\r\n2011-08-21 08:00:01,0.587823439878\r\n2011-08-21 09:00:01,0.490445812012\r\n2011-08-21 10:00:01,0.523634418667\r\n2011-08-21 11:00:01,0.601553131959\r\n2011-08-21 12:00:01,0.512415566677\r\n2011-08-21 13:00:01,0.530476204522\r\n2011-08-21 14:00:01,0.493195327382\r\n2011-08-21 15:00:01,0.476013601353\r\n2011-08-21 16:00:01,0.32574985779\r\n2011-08-21 17:00:01,0.261994654275\r\n2011-08-21 18:00:01,0.221285300868\r\n2011-08-21 19:00:01,0.210531741765\r\n2011-08-21 20:00:01,0.201633388977\r\n2011-08-21 21:00:01,0.186981062174\r\n2011-08-21 22:00:01,0.177261959255\r\n2011-08-21 23:00:01,0.176000818212\r\n2011-08-22 00:00:01,0.151385433559\r\n2011-08-22 01:00:01,0.136277320086\r\n2011-08-22 02:00:01,0.110605455837\r\n2011-08-22 03:00:01,0.106407187978\r\n2011-08-22 04:00:01,0.123628854559\r\n2011-08-22 05:00:01,0.17403044894\r\n2011-08-22 06:00:01,0.157171522962\r\n2011-08-22 07:00:01,0.294450489663\r\n2011-08-22 08:00:01,0.667178411573\r\n2011-08-22 09:00:01,0.534268392243\r\n2011-08-22 10:00:01,0.531195462478\r\n2011-08-22 11:00:01,0.527912545288\r\n2011-08-22 12:00:01,0.515761625039\r\n2011-08-22 13:00:01,0.55597207644\r\n2011-08-22 14:00:01,0.519979853441\r\n2011-08-22 15:00:01,0.394642121307\r\n2011-08-22 16:00:01,0.373577168902\r\n2011-08-22 17:00:01,0.2985790942\r\n2011-08-22 18:00:01,0.307674114188\r\n2011-08-22 19:00:01,0.340823750741\r\n2011-08-22 20:00:01,0.335536583127\r\n2011-08-22 21:00:01,0.345641197072\r\n2011-08-22 22:00:01,0.273107112762\r\n2011-08-22 23:00:01,0.155089425029\r\n2011-08-23 00:00:01,0.123046532451\r\n2011-08-23 01:00:01,0.160052421603\r\n2011-08-23 02:00:01,0.0853665712587\r\n2011-08-23 03:00:01,0.0899181896878\r\n2011-08-23 04:00:01,0.121679410333\r\n2011-08-23 05:00:01,0.171454019149\r\n2011-08-23 06:00:01,0.238440523194\r\n2011-08-23 07:00:01,0.381339486702\r\n2011-08-23 08:00:01,0.82047238811\r\n2011-08-23 09:00:01,0.772525570956\r\n2011-08-23 10:00:01,0.692144654921\r\n2011-08-23 11:00:01,0.613436416955\r\n2011-08-23 12:00:01,0.572794590446\r\n2011-08-23 13:00:01,0.555439507425\r\n2011-08-23 14:00:01,0.665397594531\r\n2011-08-23 15:00:01,0.458677384758\r\n2011-08-23 16:00:01,0.272270417989\r\n2011-08-23 17:00:01,0.327019749338\r\n2011-08-23 18:00:01,0.290489487183\r\n2011-08-23 19:00:01,0.279222240278\r\n2011-08-23 20:00:01,0.233345064394\r\n2011-08-23 21:00:01,0.226307303822\r\n2011-08-23 22:00:01,0.258378562796\r\n2011-08-23 23:00:01,0.176908471716\r\n2011-08-24 00:00:01,0.245062179956\r\n2011-08-24 01:00:01,0.172705171911\r\n2011-08-24 02:00:01,0.136768867789\r\n2011-08-24 03:00:01,0.0966510269546\r\n2011-08-24 04:00:01,0.118956597201\r\n2011-08-24 05:00:01,0.160615189472\r\n2011-08-24 06:00:01,0.199960472355\r\n2011-08-24 07:00:01,0.361688633264\r\n2011-08-24 08:00:01,0.533729073915\r\n2011-08-24 09:00:01,0.732902126515\r\n2011-08-24 10:00:01,0.412975208722\r\n2011-08-24 11:00:01,0.54914424154\r\n2011-08-24 12:00:01,0.408489668886\r\n2011-08-24 12:00:01,0.461744524861\r\n2011-08-24 13:00:01,0.486782694693\r\n2011-08-24 14:00:01,0.443630395224\r\n2011-08-24 15:00:01,0.395182983036\r\n2011-08-24 16:00:01,0.31286904473\r\n2011-08-24 17:00:01,0.359353179254\r\n2011-08-24 18:00:01,0.393515741335\r\n2011-08-24 19:00:01,0.344992829914\r\n2011-08-24 20:00:01,0.269384611013\r\n2011-08-24 21:00:01,0.407613767872\r\n2011-08-24 22:00:01,0.173129266121\r\n2011-08-24 23:00:01,0.216109054976\r\n2011-08-25 00:00:01,0.175930985902\r\n2011-08-25 01:00:01,0.169038558828\r\n2011-08-25 02:00:01,0.147807538989\r\n2011-08-25 03:00:01,0.105627064622\r\n2011-08-25 04:00:01,0.000385004945833\r\n2011-08-25 05:00:01,0.461301616821\r\n2011-08-25 06:00:01,0.233271621264\r\n2011-08-25 07:00:01,0.468516100264\r\n2011-08-25 08:00:01,0.581226855579\r\n2011-08-25 09:00:01,0.63461901101\r\n2011-08-25 10:00:01,0.566099898297\r\n2011-08-25 11:00:01,0.493856166154\r\n2011-08-25 12:00:01,0.510208394978\r\n2011-08-25 13:00:01,0.598881695115\r\n2011-08-25 14:00:01,0.470719757998\r\n2011-08-25 15:00:01,0.487960478101\r\n2011-08-25 16:00:01,0.40945390361\r\n2011-08-25 17:00:01,0.398078876882\r\n2011-08-25 18:00:01,0.28019152332\r\n2011-08-25 19:00:01,0.241039451792\r\n2011-08-25 20:00:01,0.381863230297\r\n2011-08-25 21:00:01,0.245432579188\r\n2011-08-25 22:00:01,0.234515320987\r\n2011-08-25 23:00:01,0.206420721247\r\n2011-08-26 00:00:01,0.172429499479\r\n2011-08-26 01:00:01,0.159241958671\r\n2011-08-26 02:00:01,0.155278229609\r\n2011-08-26 03:00:01,0.118453611679\r\n2011-08-26 04:00:01,0.240569535561\r\n2011-08-26 05:00:01,0.22545800559\r\n2011-08-26 06:00:01,0.279070573154\r\n2011-08-26 07:00:01,0.56754661185\r\n2011-08-26 08:00:01,0.561253351042\r\n2011-08-26 09:00:01,0.641437375228\r\n2011-08-26 10:00:01,0.820133388912\r\n2011-08-26 11:00:01,0.493383546972\r\n2011-08-26 12:00:01,0.547982528587\r\n2011-08-26 13:00:01,0.622099310054\r\n2011-08-26 14:00:01,0.512080118077\r\n2011-08-26 15:00:01,0.507217005562\r\n2011-08-26 16:00:01,0.489108910891\r\n2011-08-26 17:00:01,0.424249760079\r\n2011-08-26 18:00:01,0.412710194262\r\n2011-08-26 19:00:01,0.34001279045\r\n2011-08-26 20:00:01,0.326853774051\r\n2011-08-26 21:00:01,0.28062583972\r\n2011-08-26 22:00:01,0.252289920805\r\n2011-08-26 23:00:01,0.291602799682\r\n2011-08-27 00:00:01,0.215436933318\r\n2011-08-27 01:00:01,0.220260936301\r\n2011-08-27 02:00:01,0.186717041518\r\n2011-08-27 03:00:01,0.176219012927\r\n2011-08-27 04:00:01,0.231765575966\r\n2011-08-27 05:00:01,0.275286303963\r\n2011-08-27 06:00:01,0.264370483326\r\n2011-08-27 07:00:01,0.400318162503\r\n2011-08-27 08:00:01,0.622545622546\r\n2011-08-27 09:00:01,0.633239680138\r\n2011-08-27 10:00:01,0.650044871045\r\n2011-08-27 11:00:01,0.734008493956\r\n2011-08-27 12:00:01,0.598190302441\r\n2011-08-27 13:00:01,0.633516598232\r\n2011-08-27 14:00:01,0.475215553114\r\n2011-08-27 15:00:01,0.463420456765\r\n2011-08-27 16:00:01,0.386224238408\r\n2011-08-27 17:00:01,0.328932749121\r\n2011-08-27 18:00:01,0.322341586383\r\n2011-08-27 19:00:01,0.314598024411\r\n2011-08-27 20:00:01,0.298952180319\r\n2011-08-27 21:00:01,0.294076404898\r\n2011-08-27 22:00:01,0.246401440725\r\n2011-08-27 23:00:01,0.235950187027\r\n2011-08-28 00:00:01,0.207632234838\r\n2011-08-28 01:00:01,0.168988587332\r\n2011-08-28 02:00:01,0.141435536447\r\n2011-08-28 03:00:01,0.126585685019\r\n2011-08-28 04:00:01,0.183147548843\r\n2011-08-28 05:00:01,0.2020204139\r\n2011-08-28 06:00:01,0.255996614921\r\n2011-08-28 07:00:01,0.29123345193\r\n2011-08-28 08:00:01,0.540378503706\r\n2011-08-28 09:00:01,0.527062539326\r\n2011-08-28 10:00:01,0.549995516097\r\n2011-08-28 11:00:01,0.55179662353\r\n2011-08-28 12:00:01,0.599372992958\r\n2011-08-28 13:00:01,0.559588399094\r\n2011-08-28 14:00:01,0.511762469039\r\n2011-08-28 15:00:01,0.423079453978\r\n2011-08-28 16:00:01,0.36398231864\r\n2011-08-28 17:00:01,0.316098691924\r\n2011-08-28 18:00:01,0.266430646333\r\n2011-08-28 19:00:01,0.239828768926\r\n2011-08-28 20:00:01,0.193407373847\r\n2011-08-28 21:00:01,0.208397747608\r\n2011-08-28 22:00:01,0.21315769397\r\n2011-08-28 23:00:01,0.182707732595\r\n2011-08-29 00:00:01,0.148677099386\r\n2011-08-29 01:00:01,0.122675363449\r\n2011-08-29 02:00:01,0.109181934384\r\n2011-08-29 03:00:01,0.0892852563938\r\n2011-08-29 04:00:01,0.124574945593\r\n2011-08-29 05:00:01,0.176364561503\r\n2011-08-29 06:00:01,0.202152459227\r\n2011-08-29 07:00:01,0.33298712252\r\n2011-08-29 08:00:01,0.534548955745\r\n2011-08-29 09:00:01,0.64617045722\r\n2011-08-29 10:00:01,0.676532123822\r\n2011-08-29 11:00:01,0.489383195143\r\n2011-08-29 12:00:01,0.40194279738\r\n2011-08-29 13:00:01,0.54963816923\r\n2011-08-29 14:00:01,0.434075134761\r\n2011-08-29 15:00:01,0.435051944804\r\n2011-08-29 16:00:01,0.431632394009\r\n2011-08-29 17:00:01,0.330456971831\r\n2011-08-29 18:00:01,0.301809771023\r\n2011-08-29 19:00:01,0.350951347332\r\n2011-08-29 20:00:01,0.25222889109\r\n2011-08-29 21:00:01,0.241087185555\r\n2011-08-29 22:00:01,0.241589040418\r\n2011-08-29 23:00:01,0.281068471368\r\n2011-08-30 00:00:01,0.206532492386\r\n2011-08-30 01:00:01,0.152663766787\r\n2011-08-30 02:00:01,0.131335780603\r\n2011-08-30 03:00:01,0.109843853676\r\n2011-08-30 04:00:01,0.25651510021\r\n2011-08-30 05:00:01,0.311446035534\r\n2011-08-30 06:00:01,0.283640212075\r\n2011-08-30 07:00:01,0.44263013013\r\n2011-08-30 08:00:01,0.648082483225\r\n2011-08-30 09:00:01,0.791351906205\r\n2011-08-30 10:00:01,0.418384632595\r\n2011-08-30 11:00:01,0.448443602516\r\n2011-08-30 12:00:01,0.435691108365\r\n2011-08-30 13:00:01,0.439349301909\r\n2011-08-30 14:00:01,0.326906301027\r\n2011-08-30 15:00:01,0.447574697018\r\n2011-08-30 16:00:01,0.4682634356\r\n2011-08-30 17:00:01,0.362289894575\r\n2011-08-30 18:00:01,0.3538050999\r\n2011-08-30 19:00:01,0.356699998273\r\n2011-08-30 20:00:01,0.354342033138\r\n2011-08-30 21:00:01,0.300823483278\r\n2011-08-30 22:00:01,0.255876324836\r\n2011-08-30 23:00:01,0.263742533346\r\n2011-08-31 00:00:01,0.241733293219\r\n2011-08-31 01:00:01,0.187582254993\r\n2011-08-31 02:00:01,0.162264258936\r\n2011-08-31 03:00:01,0.144376676817\r\n2011-08-31 04:00:01,0.231260053619\r\n2011-08-31 05:00:01,0.456911647336\r\n2011-08-31 06:00:01,0.329230985394\r\n2011-08-31 07:00:01,0.39677837734\r\n2011-08-31 08:00:01,0.621348463494\r\n2011-08-31 09:00:01,0.533931484502\r\n2011-08-31 10:00:01,0.537277018546\r\n2011-08-31 11:00:01,0.450036545891\r\n2011-08-31 12:00:01,0.57521395655\r\n2011-08-31 13:00:01,0.43598099531\r\n2011-08-31 14:00:01,0.482761582341\r\n2011-08-31 15:00:01,0.394738224019\r\n2011-08-31 16:00:01,0.421161390641\r\n2011-08-31 17:00:01,0.361342866699\r\n2011-08-31 18:00:01,0.408855917468\r\n2011-08-31 19:00:01,0.493310546466\r\n2011-08-31 20:00:01,0.491194901203\r\n2011-08-31 21:00:01,0.494053140395\r\n2011-08-31 22:00:01,0.342674749528\r\n2011-08-31 23:00:01,0.344078797404\r\n2011-09-01 00:00:01,0.216449062676\r\n2011-09-01 01:00:01,0.197612674167\r\n2011-09-01 02:00:01,0.157555506338\r\n2011-09-01 03:00:01,0.129452284039\r\n2011-09-01 04:00:01,0.265415755215\r\n2011-09-01 05:00:01,0.414916925324\r\n2011-09-01 06:00:01,0.436399536493\r\n2011-09-01 07:00:01,0.510638297872\r\n2011-09-01 08:00:01,0.667334565042\r\n2011-09-01 09:00:01,0.683456790123\r\n2011-09-01 10:00:01,0.736830389086\r\n2011-09-01 11:00:01,0.572532679915\r\n2011-09-01 12:00:01,0.420446983591\r\n2011-09-01 13:00:01,0.528570163362\r\n2011-09-01 14:00:01,0.412298289967\r\n2011-09-01 15:00:01,0.490840855649\r\n2011-09-01 16:00:01,0.428572872891\r\n2011-09-01 17:00:01,0.344159041135\r\n2011-09-01 18:00:01,0.362985835006\r\n2011-09-02 15:00:01,0.29474600602\r\n2011-09-02 16:00:01,0.485279887016\r\n2011-09-02 17:00:01,0.41176305761\r\n2011-09-02 18:00:01,0.410321629465\r\n2011-09-02 19:00:01,0.361436552275\r\n2011-09-02 20:00:01,0.330957212541\r\n2011-09-02 21:00:01,0.276432333565\r\n2011-09-02 22:00:01,0.291694292981\r\n2011-09-02 23:00:01,0.301794690505\r\n2011-09-03 00:00:01,0.291617242099\r\n2011-09-03 01:00:01,0.277953194651\r\n2011-09-03 02:00:01,0.248127176169\r\n2011-09-03 03:00:01,0.169511707947\r\n2011-09-03 04:00:01,0.249690391588\r\n2011-09-03 05:00:01,0.385299625468\r\n2011-09-03 06:00:01,0.384656257837\r\n2011-09-03 07:00:01,0.376194161285\r\n2011-09-03 08:00:01,0.578187102424\r\n2011-09-03 09:00:01,0.729936189191\r\n2011-09-03 10:00:01,0.673216449006\r\n2011-09-03 11:00:01,0.61254001409\r\n2011-09-03 12:00:01,0.641445854126\r\n2011-09-03 13:00:01,0.588598734069\r\n2011-09-03 14:00:01,0.570395805255\r\n2011-09-03 15:00:01,0.472354497354\r\n2011-09-03 16:00:01,0.37974110345\r\n2011-09-03 17:00:01,0.350129181052\r\n2011-09-03 18:00:01,0.275710950256\r\n2011-09-03 19:00:01,0.28777674021\r\n2011-09-03 20:00:01,0.265807976651\r\n2011-09-03 21:00:01,0.278050562952\r\n2011-09-03 22:00:01,0.28659804327\r\n2011-09-03 23:00:01,0.262018924352\r\n2011-09-04 00:00:01,0.259513603461\r\n2011-09-04 01:00:01,0.246324607821\r\n2011-09-04 02:00:01,0.209808549698\r\n2011-09-04 03:00:01,0.17836460505\r\n2011-09-04 04:00:01,0.245289560099\r\n2011-09-04 05:00:01,0.344276292442\r\n2011-09-04 06:00:01,0.306586474989\r\n2011-09-04 07:00:01,0.430391276139\r\n2011-09-04 08:00:01,0.547901341411\r\n2011-09-04 09:00:01,0.641821064842\r\n2011-09-04 10:00:01,0.81641030904\r\n2011-09-04 11:00:01,0.670888581041\r\n2011-09-04 12:00:01,0.614528069363\r\n2011-09-04 13:00:01,0.612822169574\r\n2011-09-04 14:00:01,0.579268292683\r\n2011-09-04 15:00:01,0.485615808491\r\n2011-09-04 16:00:01,0.402082460157\r\n2011-09-04 17:00:01,0.375212989741\r\n2011-09-04 18:00:01,0.307740145091\r\n2011-09-04 19:00:01,0.27382792936\r\n2011-09-04 20:00:01,0.246910383732\r\n2011-09-04 21:00:01,0.228353890665\r\n2011-09-04 22:00:01,0.233535193639\r\n2011-09-04 23:00:01,0.215548571638\r\n2011-09-05 00:00:01,0.225015080971\r\n2011-09-05 01:00:01,0.209993129869\r\n2011-09-05 02:00:01,0.15313251846\r\n2011-09-05 03:00:01,0.119231002264\r\n2011-09-05 04:00:01,0.165732017867\r\n2011-09-05 05:00:01,0.230474174382\r\n2011-09-05 06:00:01,0.233619482907\r\n2011-09-05 07:00:01,0.284188650927\r\n2011-09-05 08:00:01,0.550548728064\r\n2011-09-05 09:00:01,0.728971054847\r\n2011-09-05 10:00:01,0.530146611013\r\n2011-09-05 11:00:01,0.67969179967\r\n2011-09-05 12:00:01,0.56956630077\r\n2011-09-05 13:00:01,0.558141252955\r\n2011-09-05 14:00:01,0.503757754924\r\n2011-09-05 15:00:01,0.387006146845\r\n2011-09-05 16:00:01,0.360744566447\r\n2011-09-05 17:00:01,0.262992239088\r\n2011-09-05 18:00:01,0.266060699999\r\n2011-09-05 19:00:01,0.240317359828\r\n2011-09-05 20:00:01,0.226144185194\r\n2011-09-05 21:00:01,0.20473812416\r\n2011-09-05 22:00:01,0.174043818091\r\n2011-09-05 23:00:01,0.172111187824\r\n2011-09-06 00:00:01,0.181676539327\r\n2011-09-06 01:00:01,0.166772823961\r\n2011-09-06 02:00:01,0.105305627274\r\n2011-09-06 03:00:01,0.0892502429895\r\n2011-09-06 04:00:01,0.163954560416\r\n2011-09-06 05:00:01,0.188989727735\r\n2011-09-06 06:00:01,0.215441237057\r\n2011-09-06 07:00:01,0.445466462263\r\n2011-09-06 08:00:01,0.514810677555\r\n2011-09-06 09:00:01,0.497141778106\r\n2011-09-06 10:00:01,0.601606052562\r\n2011-09-06 11:00:01,0.400448117791\r\n2011-09-06 12:00:01,0.385146130933\r\n2011-09-06 13:00:01,0.451650113231\r\n2011-09-06 14:00:01,0.414082425226\r\n2011-09-06 15:00:01,0.425809421513\r\n2011-09-06 16:00:01,0.342556508184\r\n2011-09-06 17:00:01,0.325499873346\r\n2011-09-06 18:00:01,0.180503882346\r\n2011-09-06 19:00:01,0.557667699041\r\n2011-09-06 20:00:01,0.367222540787\r\n2011-09-06 21:00:01,0.464463472743\r\n2011-09-06 22:00:01,0.327087544384\r\n2011-09-06 23:00:01,0.277730265483\r\n2011-09-07 00:00:01,0.288533644404\r\n2011-09-07 01:00:01,0.2231056289\r\n2011-09-07 02:00:01,0.151394339798\r\n2011-09-07 03:00:01,0.133753737139\r\n2011-09-07 04:00:01,0.153141093435\r\n2011-09-07 05:00:01,0.240614655527\r\n2011-09-07 06:00:01,0.307711918419\r\n2011-09-07 07:00:01,0.391228851975\r\n2011-09-07 08:00:01,0.562866797083\r\n2011-09-07 09:00:01,0.572038880615\r\n2011-09-07 10:00:01,0.587186345688\r\n2011-09-07 11:00:01,0.343989530753\r\n2011-09-07 12:00:01,0.404890624699\r\n2011-09-07 13:00:01,0.441900001126\r\n2011-09-07 14:00:01,0.285779485034\r\n2011-09-07 15:00:01,0.378583558086\r\n"
  },
  {
    "path": "workspace/anomaly_detector/datasets/selected/seasonal/exchange-3_cpm_results.csv",
    "content": "timestamp,value\r\n2011-07-01 00:15:01,0.405422534525\r\n2011-07-01 01:15:01,0.433961278227\r\n2011-07-01 02:15:01,0.389267501625\r\n2011-07-01 03:15:01,0.368098502243\r\n2011-07-01 04:15:01,0.365234426765\r\n2011-07-01 05:15:01,0.3428794869\r\n2011-07-01 06:15:01,0.320650020989\r\n2011-07-01 07:15:01,0.328999171839\r\n2011-07-01 08:15:01,0.330918820695\r\n2011-07-01 09:15:01,0.396968683829\r\n2011-07-01 10:15:01,0.44347161212\r\n2011-07-01 11:15:01,0.662412074347\r\n2011-07-01 12:15:01,0.707460331375\r\n2011-07-01 13:15:01,0.597161557559\r\n2011-07-01 14:15:01,0.600127175161\r\n2011-07-01 15:15:01,0.534812246524\r\n2011-07-01 16:15:01,0.46917505741\r\n2011-07-01 17:15:01,0.505456517193\r\n2011-07-01 18:15:01,0.4535763584\r\n2011-07-01 19:15:01,0.579827163973\r\n2011-07-01 20:15:01,0.929018598624\r\n2011-07-01 21:15:01,0.481969218049\r\n2011-07-01 22:15:01,1.59456911756\r\n2011-07-01 23:15:01,3.02086765513\r\n2011-07-02 00:15:01,2.82484901469\r\n2011-07-02 01:15:01,1.01660459594\r\n2011-07-02 02:15:01,0.550420623732\r\n2011-07-02 03:15:01,0.689861668363\r\n2011-07-02 04:15:01,0.643394562177\r\n2011-07-02 05:15:01,0.603330401792\r\n2011-07-02 06:15:01,0.60099737106\r\n2011-07-02 07:15:01,0.644907856905\r\n2011-07-02 08:15:01,0.619896282481\r\n2011-07-02 09:15:01,0.711410835499\r\n2011-07-02 10:15:01,0.823032683736\r\n2011-07-02 11:15:01,0.982650117997\r\n2011-07-02 12:15:01,1.82198845938\r\n2011-07-02 13:15:01,1.4539117855\r\n2011-07-02 14:15:01,1.33707622155\r\n2011-07-02 15:15:01,1.08711717782\r\n2011-07-02 16:15:01,0.91170299956\r\n2011-07-02 17:15:01,0.803212193223\r\n2011-07-02 18:15:01,1.11925182413\r\n2011-07-02 19:15:01,0.747777030865\r\n2011-07-02 20:15:01,0.79998925588\r\n2011-07-02 21:15:01,0.765987648091\r\n2011-07-02 22:15:01,0.705948517041\r\n2011-07-02 23:15:01,1.45388610672\r\n2011-07-03 00:15:01,1.38902113011\r\n2011-07-03 01:15:01,0.925834177713\r\n2011-07-03 02:15:01,0.831415320602\r\n2011-07-03 03:15:01,0.483019261215\r\n2011-07-03 04:15:01,0.693500280828\r\n2011-07-03 05:15:01,0.680136615604\r\n2011-07-03 06:15:01,0.696506878058\r\n2011-07-03 07:15:01,0.742017606353\r\n2011-07-03 08:15:01,0.713239099849\r\n2011-07-03 09:15:01,0.757453614431\r\n2011-07-03 10:15:01,0.963004377293\r\n2011-07-03 11:15:01,1.6822211246\r\n2011-07-03 12:15:01,2.07516028693\r\n2011-07-03 13:15:01,1.94973024968\r\n2011-07-03 14:15:01,1.38908773657\r\n2011-07-03 15:15:01,1.11706077222\r\n2011-07-03 16:15:01,1.00365466979\r\n2011-07-03 17:15:01,0.959327269607\r\n2011-07-03 18:15:01,0.835083924374\r\n2011-07-03 19:15:01,0.814624009308\r\n2011-07-03 20:15:01,0.827716419656\r\n2011-07-03 21:15:01,0.882878070554\r\n2011-07-03 22:15:01,0.997623517817\r\n2011-07-03 23:15:01,1.74638339578\r\n2011-07-04 00:15:01,1.43257308234\r\n2011-07-04 01:15:01,0.943704898459\r\n2011-07-04 02:15:01,0.558643628895\r\n2011-07-04 03:15:01,0.715673181984\r\n2011-07-04 04:15:01,0.732596504133\r\n2011-07-04 05:15:01,0.640847995481\r\n2011-07-04 06:15:01,0.623399850096\r\n2011-07-04 07:15:01,0.674131851371\r\n2011-07-04 08:15:01,0.781035713426\r\n2011-07-04 09:15:01,0.684518122173\r\n2011-07-04 10:15:01,0.899108227688\r\n2011-07-04 11:15:01,1.63733247215\r\n2011-07-04 12:15:01,1.74557145559\r\n2011-07-04 13:15:01,1.97659441357\r\n2011-07-04 14:15:01,1.58846906697\r\n2011-07-04 15:15:01,1.04741587993\r\n2011-07-04 16:15:01,0.678772584881\r\n2011-07-04 17:15:01,0.602611129637\r\n2011-07-04 18:15:01,0.570830160915\r\n2011-07-04 19:15:01,0.550038076316\r\n2011-07-04 20:15:01,0.59489693004\r\n2011-07-04 21:15:01,0.582188580506\r\n2011-07-04 22:15:01,0.675870716328\r\n2011-07-04 23:15:01,1.05814892078\r\n2011-07-05 00:15:01,1.09302018155\r\n2011-07-05 01:15:01,0.619185328719\r\n2011-07-05 02:15:01,0.546216679365\r\n2011-07-05 03:15:01,0.43930623552\r\n2011-07-05 04:15:01,0.464924821965\r\n2011-07-05 05:15:01,0.457552001746\r\n2011-07-05 06:15:01,0.426136705088\r\n2011-07-05 07:15:01,0.463126895367\r\n2011-07-05 08:15:01,0.470788232029\r\n2011-07-05 09:15:01,0.438059738418\r\n2011-07-05 10:15:01,0.750424972956\r\n2011-07-05 11:15:01,0.787270610412\r\n2011-07-05 12:15:01,1.07755946225\r\n2011-07-05 13:15:01,0.998522373197\r\n2011-07-05 14:15:01,0.952744270496\r\n2011-07-05 15:15:01,0.707829298362\r\n2011-07-05 16:15:01,0.612651923352\r\n2011-07-05 17:15:01,0.582697780816\r\n2011-07-05 18:15:01,0.650834949828\r\n2011-07-05 19:15:01,0.616827982495\r\n2011-07-05 20:15:01,0.588550728092\r\n2011-07-05 21:15:01,0.525827739324\r\n2011-07-05 22:15:01,0.580492705313\r\n2011-07-05 23:15:01,0.850236788743\r\n2011-07-06 00:15:01,0.989699069715\r\n2011-07-06 01:15:01,0.542059746448\r\n2011-07-06 02:15:01,0.417662676746\r\n2011-07-06 03:15:01,0.42774941839\r\n2011-07-06 04:15:01,0.42921970945\r\n2011-07-06 05:15:01,0.407084105315\r\n2011-07-06 06:15:01,0.419973474988\r\n2011-07-06 07:15:01,0.419987213504\r\n2011-07-06 08:15:01,0.419571904869\r\n2011-07-06 09:15:01,0.542099108317\r\n2011-07-06 10:15:01,0.523028762708\r\n2011-07-06 11:15:01,0.860811277047\r\n2011-07-06 12:15:01,1.03834696676\r\n2011-07-06 13:15:01,1.02756469696\r\n2011-07-06 14:15:01,0.726965750121\r\n2011-07-06 15:15:01,0.697692029382\r\n2011-07-06 16:15:01,0.61312845603\r\n2011-07-06 17:15:01,0.589332440756\r\n2011-07-06 18:15:01,0.70509726472\r\n2011-07-06 19:15:01,0.684018898444\r\n2011-07-06 20:15:01,0.453724582931\r\n2011-07-06 21:15:01,0.689319329302\r\n2011-07-06 22:15:01,0.56934558103\r\n2011-07-06 23:15:01,0.593638974059\r\n2011-07-07 00:15:01,0.495223004774\r\n2011-07-07 01:15:01,0.533024251743\r\n2011-07-07 02:15:01,0.513768520467\r\n2011-07-07 05:15:01,0.484609943601\r\n2011-07-07 06:15:01,0.372865059711\r\n2011-07-07 07:15:01,0.580024914694\r\n2011-07-07 08:15:01,0.448067683962\r\n2011-07-07 09:15:01,0.613364729387\r\n2011-07-07 10:15:01,0.618467559655\r\n2011-07-07 11:15:01,0.838079048024\r\n2011-07-07 12:15:01,1.2565580859\r\n2011-07-07 13:15:01,1.14752664089\r\n2011-07-07 14:15:01,1.01583644619\r\n2011-07-07 15:15:01,0.913571537965\r\n2011-07-07 16:15:01,0.618304360192\r\n2011-07-07 17:15:01,0.763646369801\r\n2011-07-07 18:15:01,0.764605470099\r\n2011-07-07 19:15:01,1.21798800094\r\n2011-07-07 20:15:01,1.01495047186\r\n2011-07-07 21:15:01,1.03107344633\r\n2011-07-07 22:15:01,0.876598530712\r\n2011-07-07 23:15:01,0.552934085566\r\n2011-07-08 00:15:01,0.49550387185\r\n2011-07-08 01:15:01,0.847840103159\r\n2011-07-08 02:15:01,0.643240884261\r\n2011-07-08 06:15:01,0.706602697276\r\n2011-07-08 09:15:01,0.681349823745\r\n2011-07-08 10:15:01,0.590646181328\r\n2011-07-08 14:15:01,1.24385033027\r\n2011-07-08 16:15:01,2.59258016906\r\n2011-07-08 17:15:01,1.3542439637\r\n2011-07-08 18:15:01,0.700856342781\r\n2011-07-08 19:15:01,0.970253925004\r\n2011-07-08 20:15:01,1.18064743289\r\n2011-07-08 21:15:01,1.04666954508\r\n2011-07-08 22:15:01,1.09588027648\r\n2011-07-08 23:15:01,0.989867032787\r\n2011-07-09 09:15:01,0.722730241672\r\n2011-07-09 15:15:01,0.672810392706\r\n2011-07-09 17:15:01,0.730694412571\r\n2011-07-09 18:15:01,1.1065965848\r\n2011-07-09 19:15:01,0.951126681146\r\n2011-07-09 20:15:01,0.86612700358\r\n2011-07-09 21:15:01,0.822021986321\r\n2011-07-09 22:15:01,1.03145922094\r\n2011-07-09 23:15:01,1.16544612166\r\n2011-07-10 00:15:01,1.05581045236\r\n2011-07-10 01:15:01,0.933769979761\r\n2011-07-10 02:15:01,0.852321869447\r\n2011-07-10 03:15:01,0.562376237624\r\n2011-07-10 04:15:01,0.690265027243\r\n2011-07-10 05:15:01,0.661577265667\r\n2011-07-10 06:15:01,0.683708791707\r\n2011-07-10 07:15:01,0.585272294012\r\n2011-07-10 08:15:01,0.725823769416\r\n2011-07-10 09:15:01,1.06548190842\r\n2011-07-10 10:15:01,0.812296171035\r\n2011-07-10 11:15:01,1.15012216089\r\n2011-07-10 12:15:01,1.91079022846\r\n2011-07-10 13:15:01,1.89823760173\r\n2011-07-10 14:15:01,1.60666972834\r\n2011-07-10 15:15:01,1.36903179016\r\n2011-07-10 16:15:01,1.23539136879\r\n2011-07-10 17:15:01,1.30004968561\r\n2011-07-10 18:15:01,1.02969040624\r\n2011-07-10 19:15:01,0.932536450273\r\n2011-07-10 20:15:01,0.931886464036\r\n2011-07-10 21:15:01,0.863524014067\r\n2011-07-10 22:15:01,0.991745182096\r\n2011-07-10 23:15:01,0.862854251012\r\n2011-07-11 00:15:01,0.747998448544\r\n2011-07-11 01:15:01,0.850183503168\r\n2011-07-11 02:15:01,0.654526695899\r\n2011-07-11 03:15:01,0.728679424723\r\n2011-07-11 04:15:01,0.690021862785\r\n2011-07-11 05:15:01,0.698213122487\r\n2011-07-11 06:15:01,0.638280829834\r\n2011-07-11 07:15:01,0.671747063098\r\n2011-07-11 08:15:01,0.641360186156\r\n2011-07-11 09:15:01,0.588559867574\r\n2011-07-11 10:15:01,0.97926990996\r\n2011-07-11 11:15:01,2.03972428805\r\n2011-07-11 12:15:01,1.43419613562\r\n2011-07-11 13:15:01,1.50993833205\r\n2011-07-11 14:15:01,1.39176641082\r\n2011-07-11 15:15:01,1.10735535393\r\n2011-07-11 16:15:01,0.997729716812\r\n2011-07-11 17:15:01,0.838516364175\r\n2011-07-11 18:15:01,0.591521865594\r\n2011-07-11 19:15:01,0.523210749244\r\n2011-07-11 20:15:01,0.50741379187\r\n2011-07-11 21:15:01,0.538820681939\r\n2011-07-11 22:15:01,0.537126366514\r\n2011-07-11 23:15:01,0.575014047574\r\n2011-07-12 00:15:01,0.434892834119\r\n2011-07-12 01:15:01,0.568473258729\r\n2011-07-12 02:15:01,0.576361277601\r\n2011-07-12 03:15:01,0.561665799733\r\n2011-07-12 04:15:01,0.506676771373\r\n2011-07-12 05:15:01,0.532992059663\r\n2011-07-12 06:15:01,0.533646651609\r\n2011-07-12 07:15:01,0.543344592151\r\n2011-07-12 08:15:01,0.63393689344\r\n2011-07-12 09:15:01,0.673402868318\r\n2011-07-12 10:15:01,0.670085200379\r\n2011-07-12 11:15:01,0.702719812998\r\n2011-07-12 12:15:01,0.995558682556\r\n2011-07-12 13:15:01,1.16926536732\r\n2011-07-12 14:15:01,1.01409928115\r\n2011-07-12 15:15:01,0.996637659048\r\n2011-07-12 16:15:01,0.679225381434\r\n2011-07-12 17:15:01,0.75814025419\r\n2011-07-12 18:15:01,0.763981210671\r\n2011-07-12 19:15:01,0.708667855921\r\n2011-07-12 20:15:01,0.714510023353\r\n2011-07-12 21:15:01,0.762345540039\r\n2011-07-12 22:15:01,0.703105906489\r\n2011-07-12 23:15:01,0.707826549505\r\n2011-07-13 00:15:01,0.57670519965\r\n2011-07-13 01:15:01,0.679474448094\r\n2011-07-13 02:15:01,0.557389600963\r\n2011-07-13 03:15:01,0.531382043611\r\n2011-07-13 04:15:01,0.529654200621\r\n2011-07-13 05:15:01,0.519767135236\r\n2011-07-13 06:15:01,0.512662431177\r\n2011-07-13 07:15:01,0.555591534137\r\n2011-07-13 08:15:01,0.656115012713\r\n2011-07-13 09:15:01,0.78798286152\r\n2011-07-13 10:15:01,0.692587249625\r\n2011-07-13 11:15:01,0.935283109196\r\n2011-07-13 12:15:01,1.07905121568\r\n2011-07-13 13:15:01,1.26547389169\r\n2011-07-13 14:15:01,0.758122743682\r\n2011-07-13 15:15:01,0.861263139606\r\n2011-07-13 16:15:01,0.818969842122\r\n2011-07-13 17:15:01,0.781863718801\r\n2011-07-13 18:15:01,0.754097953198\r\n2011-07-13 19:15:01,0.734934125478\r\n2011-07-13 20:15:01,0.690540979909\r\n2011-07-13 21:15:01,0.729830698994\r\n2011-07-13 22:15:01,0.75001446262\r\n2011-07-13 23:15:01,0.788613597882\r\n2011-07-14 00:15:01,0.599371499577\r\n2011-07-14 01:15:01,0.618132010667\r\n2011-07-14 02:15:01,0.492632136346\r\n2011-07-14 03:15:01,0.433984949291\r\n2011-07-14 04:15:01,0.401924624437\r\n2011-07-14 05:15:01,0.391060382405\r\n2011-07-14 06:15:01,0.394108266834\r\n2011-07-14 07:15:01,0.414870889838\r\n2011-07-14 08:15:01,0.459231967846\r\n2011-07-14 09:15:01,0.554594329429\r\n2011-07-14 10:15:01,0.586447433981\r\n2011-07-14 11:15:01,0.774360121165\r\n2011-07-14 12:15:01,1.09174200349\r\n2011-07-14 13:15:01,1.02217110037\r\n2011-07-14 14:15:01,0.927402784199\r\n2011-07-14 15:15:01,0.758385916177\r\n2011-07-14 16:15:01,0.628370275811\r\n2011-07-14 17:15:01,0.620875293673\r\n2011-07-14 18:15:01,0.599521386669\r\n2011-07-14 19:15:01,0.571684647103\r\n2011-07-14 20:15:01,0.553937947494\r\n2011-07-14 21:15:01,0.583300039952\r\n2011-07-14 22:15:01,0.54794987059\r\n2011-07-14 23:15:01,0.584078029022\r\n2011-07-15 00:15:01,0.470730436595\r\n2011-07-15 01:15:01,0.613684756703\r\n2011-07-15 02:15:01,0.500075260381\r\n2011-07-15 03:15:01,0.465845307932\r\n2011-07-15 04:15:01,0.41024236317\r\n2011-07-15 05:15:01,0.387587791441\r\n2011-07-15 06:15:01,0.424290111819\r\n2011-07-15 07:15:01,0.419710942605\r\n2011-07-15 08:15:01,0.490660629494\r\n2011-07-15 09:15:01,0.579498460973\r\n2011-07-15 10:15:01,0.629326672567\r\n2011-07-15 11:15:01,0.678068562505\r\n2011-07-15 12:15:01,0.92753386871\r\n2011-07-15 13:15:01,0.999694137996\r\n2011-07-15 14:15:01,0.666268214936\r\n2011-07-15 15:15:01,0.697556091181\r\n2011-07-15 16:15:01,0.641203792909\r\n2011-07-15 17:15:01,0.63342731861\r\n2011-07-15 18:15:01,0.582036667388\r\n2011-07-15 19:15:01,0.563113818597\r\n2011-07-15 20:15:01,0.526980162514\r\n2011-07-15 21:15:01,0.52827791804\r\n2011-07-15 22:15:01,0.475220574063\r\n2011-07-15 23:15:01,0.447709441696\r\n2011-07-16 00:15:01,0.573151033543\r\n2011-07-16 01:15:01,0.660520510001\r\n2011-07-16 02:15:01,0.653658941313\r\n2011-07-16 03:15:01,0.54005469609\r\n2011-07-16 04:15:01,0.515772970517\r\n2011-07-16 05:15:01,0.429273997931\r\n2011-07-16 06:15:01,0.407590018152\r\n2011-07-16 07:15:01,0.421466054048\r\n2011-07-16 08:15:01,0.530038045387\r\n2011-07-16 09:15:01,0.57930338213\r\n2011-07-16 10:15:01,0.770295651048\r\n2011-07-16 11:15:01,0.808551183638\r\n2011-07-16 12:15:01,0.841766168283\r\n2011-07-16 13:15:01,1.14397851684\r\n2011-07-16 14:15:01,0.693110948221\r\n2011-07-16 15:15:01,0.765183723366\r\n2011-07-16 16:15:01,0.679417321464\r\n2011-07-16 17:15:01,0.599942000367\r\n2011-07-16 18:15:01,0.577088263652\r\n2011-07-16 19:15:01,0.61229276245\r\n2011-07-16 22:15:01,0.554915456933\r\n2011-07-16 23:15:01,0.558064606445\r\n2011-07-17 00:15:01,0.551861184907\r\n2011-07-17 01:15:01,0.61407608019\r\n2011-07-17 02:15:01,0.614105010588\r\n2011-07-17 03:15:01,0.547997259079\r\n2011-07-17 04:15:01,0.52247125088\r\n2011-07-17 05:15:01,0.44803768545\r\n2011-07-17 06:15:01,0.422634977534\r\n2011-07-17 07:15:01,0.449383287256\r\n2011-07-17 08:15:01,0.48685191239\r\n2011-07-17 09:15:01,0.55355034739\r\n2011-07-17 10:15:01,0.751857084264\r\n2011-07-17 11:15:01,0.752667091441\r\n2011-07-17 12:15:01,0.929141547083\r\n2011-07-17 13:15:01,1.20847661477\r\n2011-07-17 14:15:01,0.779651764165\r\n2011-07-17 15:15:01,0.842350417376\r\n2011-07-17 16:15:01,0.660812279132\r\n2011-07-17 17:15:01,0.604369143437\r\n2011-07-17 18:15:01,0.545339087944\r\n2011-07-17 19:15:01,0.553533960498\r\n2011-07-17 20:15:01,0.548774325402\r\n2011-07-17 21:15:01,0.538358082874\r\n2011-07-17 22:15:01,0.53644178623\r\n2011-07-17 23:15:01,0.534592977484\r\n2011-07-18 00:15:01,0.512258339014\r\n2011-07-18 01:15:01,0.566221756929\r\n2011-07-18 02:15:01,0.522523408729\r\n2011-07-18 03:15:01,0.471140262255\r\n2011-07-18 04:15:01,0.427749227361\r\n2011-07-18 05:15:01,0.389042222628\r\n2011-07-18 06:15:01,0.383151727687\r\n2011-07-18 07:15:01,0.431656005927\r\n2011-07-18 08:15:01,0.450789800048\r\n2011-07-18 09:15:01,0.579229368551\r\n2011-07-18 10:15:01,0.619556840077\r\n2011-07-18 11:15:01,0.723378174503\r\n2011-07-18 12:15:01,1.01502410409\r\n2011-07-18 13:15:01,0.846268382728\r\n2011-07-18 14:15:01,0.839328087923\r\n2011-07-18 15:15:01,0.725356643836\r\n2011-07-18 16:15:01,0.724121952079\r\n2011-07-18 17:15:01,0.651006083675\r\n2011-07-18 18:15:01,0.602683655851\r\n2011-07-18 19:15:01,0.586257084968\r\n2011-07-18 20:15:01,0.562953513723\r\n2011-07-18 21:15:01,0.515027143549\r\n2011-07-18 22:15:01,0.51568420058\r\n2011-07-18 23:15:01,0.520976591741\r\n2011-07-19 00:15:01,0.443980609863\r\n2011-07-19 01:15:01,0.616688653055\r\n2011-07-19 02:15:01,0.543115927044\r\n2011-07-19 03:15:01,0.453472535098\r\n2011-07-19 04:15:01,0.42156878009\r\n2011-07-19 05:15:01,0.354035310108\r\n2011-07-19 06:15:01,0.338454738679\r\n2011-07-19 07:15:01,0.410903748263\r\n2011-07-19 08:15:01,0.447593728971\r\n2011-07-19 09:15:01,0.55913499836\r\n2011-07-19 10:15:01,0.719621810927\r\n2011-07-19 11:15:01,0.767196681645\r\n2011-07-19 12:15:01,0.942294520548\r\n2011-07-19 13:15:01,1.0032383212\r\n2011-07-19 14:15:01,0.862942524284\r\n2011-07-19 15:15:01,0.733837310024\r\n2011-07-19 16:15:01,0.625142679429\r\n2011-07-19 17:15:01,0.509370235269\r\n2011-07-19 18:15:01,0.53930596467\r\n2011-07-19 19:15:01,0.50644543215\r\n2011-07-19 20:15:01,0.488141028621\r\n2011-07-19 21:15:01,0.436814157173\r\n2011-07-19 22:15:01,0.47635140278\r\n2011-07-19 23:15:01,0.457919393325\r\n2011-07-20 00:15:01,0.4295801077\r\n2011-07-20 01:15:01,0.564498167608\r\n2011-07-20 02:15:01,0.509544562716\r\n2011-07-20 03:15:01,0.463203968782\r\n2011-07-20 04:15:01,0.407072030767\r\n2011-07-20 05:15:01,0.358862801122\r\n2011-07-20 06:15:01,0.373697236561\r\n2011-07-20 07:15:01,0.439205007516\r\n2011-07-20 08:15:01,0.415318662475\r\n2011-07-20 09:15:01,0.542676839911\r\n2011-07-20 10:15:01,0.575836639641\r\n2011-07-20 11:15:01,0.693750209668\r\n2011-07-20 12:15:01,0.958649679038\r\n2011-07-20 13:15:01,0.978838236235\r\n2011-07-20 14:15:01,0.847355615316\r\n2011-07-20 15:15:01,0.662280939932\r\n2011-07-20 16:15:01,0.583318113117\r\n2011-07-20 17:15:01,0.533766852362\r\n2011-07-20 18:15:01,0.534896914979\r\n2011-07-20 19:15:01,0.49444521527\r\n2011-07-20 20:15:01,0.472729580661\r\n2011-07-20 21:15:01,0.480673062305\r\n2011-07-20 22:15:01,0.423097534834\r\n2011-07-20 23:15:01,0.486307654948\r\n2011-07-21 00:15:01,0.422066413938\r\n2011-07-21 01:15:01,0.519997336916\r\n2011-07-21 02:15:01,0.503462395529\r\n2011-07-21 03:15:01,0.443251378533\r\n2011-07-21 04:15:01,0.384122851996\r\n2011-07-21 05:15:01,0.362461723631\r\n2011-07-21 06:15:01,0.362696176533\r\n2011-07-21 07:15:01,0.382357225458\r\n2011-07-21 08:15:01,0.409054677065\r\n2011-07-21 09:15:01,0.529625586473\r\n2011-07-21 10:15:01,0.575244382969\r\n2011-07-21 11:15:01,0.5888\r\n2011-07-21 12:15:01,0.847774407738\r\n2011-07-21 13:15:01,0.791340636411\r\n2011-07-21 14:15:01,0.896465706439\r\n2011-07-21 15:15:01,0.665230969614\r\n2011-07-21 16:15:01,0.593758564712\r\n2011-07-21 17:15:01,0.569387656299\r\n2011-07-21 18:15:01,0.634304010683\r\n2011-07-21 22:15:01,0.486431017698\r\n2011-07-22 00:15:01,0.422591891003\r\n2011-07-22 01:15:01,0.486913311221\r\n2011-07-22 02:15:01,0.46735676419\r\n2011-07-22 03:15:01,0.434363028666\r\n2011-07-22 04:15:01,0.386714049044\r\n2011-07-22 05:15:01,0.369504587288\r\n2011-07-22 06:15:01,0.397595454874\r\n2011-07-22 07:15:01,0.410352632737\r\n2011-07-22 08:15:01,0.423393177227\r\n2011-07-22 09:15:01,0.491140774627\r\n2011-07-22 10:15:01,0.468621217473\r\n2011-07-22 11:15:01,0.580554113678\r\n2011-07-22 12:15:01,0.833853226071\r\n2011-07-22 13:15:01,0.896172284725\r\n2011-07-22 14:15:01,0.767720788852\r\n2011-07-22 15:15:01,0.56208989333\r\n2011-07-22 16:15:01,0.605598263972\r\n2011-07-22 17:15:01,0.474154728687\r\n2011-07-22 18:15:01,0.527754990429\r\n2011-07-22 19:15:01,0.570643559125\r\n2011-07-22 20:15:01,0.487113274889\r\n2011-07-22 21:15:01,0.446442694765\r\n2011-07-22 22:15:01,0.493629595145\r\n2011-07-22 23:15:01,0.416509432515\r\n2011-07-23 03:15:01,0.471425611142\r\n2011-07-23 05:15:01,0.429440714477\r\n2011-07-23 06:15:01,0.432265331459\r\n2011-07-23 07:15:01,0.454228292268\r\n2011-07-23 08:15:01,0.394017939728\r\n2011-07-23 11:15:01,0.524489350397\r\n2011-07-23 12:15:01,0.634432981899\r\n2011-07-23 13:15:01,1.04193118459\r\n2011-07-23 14:15:01,0.90026207413\r\n2011-07-23 15:15:01,0.801925327328\r\n2011-07-23 16:15:01,0.664488563101\r\n2011-07-23 17:15:01,0.746938916439\r\n2011-07-23 18:15:01,0.58430610608\r\n2011-07-23 19:15:01,0.551052096356\r\n2011-07-23 20:15:01,0.539589028335\r\n2011-07-23 21:15:01,0.458878228066\r\n2011-07-23 22:15:01,0.508391976452\r\n2011-07-23 23:15:01,0.455166495807\r\n2011-07-24 00:15:01,0.354592054203\r\n2011-07-24 01:15:01,0.847647604173\r\n2011-07-24 02:15:01,0.623232870952\r\n2011-07-24 03:15:01,0.454925500145\r\n2011-07-24 04:15:01,0.388240283175\r\n2011-07-24 05:15:01,0.362204837798\r\n2011-07-24 06:15:01,0.38663181282\r\n2011-07-24 07:15:01,0.432720462465\r\n2011-07-24 08:15:01,0.463825888665\r\n2011-07-24 09:15:01,0.5587072312\r\n2011-07-24 10:15:01,0.537009158919\r\n2011-07-24 11:15:01,0.668545698278\r\n2011-07-24 12:15:01,1.00081699346\r\n2011-07-24 13:15:01,0.875236467932\r\n2011-07-24 14:15:01,0.940858277968\r\n2011-07-24 15:15:01,0.528411701639\r\n2011-07-24 16:15:01,0.65468678144\r\n2011-07-24 17:15:01,0.581666157293\r\n2011-07-24 18:15:01,0.514303731701\r\n2011-07-24 19:15:01,0.461928980193\r\n2011-07-24 20:15:01,0.422771996885\r\n2011-07-24 21:15:01,0.411778295097\r\n2011-07-24 22:15:01,0.422908418695\r\n2011-07-24 23:15:01,0.373979374279\r\n2011-07-25 00:15:01,0.392288088245\r\n2011-07-25 01:15:01,0.624979173708\r\n2011-07-25 02:15:01,0.467264498355\r\n2011-07-25 03:15:01,0.491341991342\r\n2011-07-25 04:15:01,0.380918382013\r\n2011-07-25 05:15:01,0.335816771323\r\n2011-07-25 06:15:01,0.39575696898\r\n2011-07-25 07:15:01,0.389068499632\r\n2011-07-25 08:15:01,0.401918936275\r\n2011-07-25 09:15:01,0.560098031871\r\n2011-07-25 10:15:01,0.632278380734\r\n2011-07-25 11:15:01,0.754956701996\r\n2011-07-25 12:15:01,0.956091142046\r\n2011-07-25 13:15:01,0.993110160026\r\n2011-07-25 14:15:01,0.89732544683\r\n2011-07-25 15:15:01,0.677849823197\r\n2011-07-25 16:15:01,0.61280505222\r\n2011-07-25 17:15:01,0.554349758464\r\n2011-07-25 18:15:01,0.455914446791\r\n2011-07-25 19:15:01,0.464386331397\r\n2011-07-25 20:15:01,0.401464711746\r\n2011-07-25 21:15:01,0.359988588258\r\n2011-07-25 22:15:01,0.403315849798\r\n2011-07-25 23:15:01,0.396394253289\r\n2011-07-26 00:15:01,0.345829294262\r\n2011-07-26 01:15:01,0.458796101136\r\n2011-07-26 02:15:01,0.478773805802\r\n2011-07-26 03:15:01,0.398860697414\r\n2011-07-26 04:15:01,0.44840088318\r\n2011-07-26 05:15:01,0.323450423714\r\n2011-07-26 06:15:01,0.365505482974\r\n2011-07-26 07:15:01,0.394108235626\r\n2011-07-26 08:15:01,0.441997940672\r\n2011-07-26 09:15:01,0.524900355719\r\n2011-07-26 10:15:01,0.691827625706\r\n2011-07-26 11:15:01,0.796475686699\r\n2011-07-26 12:15:01,0.843537414966\r\n2011-07-26 13:15:01,0.861174539371\r\n2011-07-26 14:15:01,0.86726415966\r\n2011-07-26 15:15:01,0.541147669817\r\n2011-07-26 16:15:01,0.620446859419\r\n2011-07-26 17:15:01,0.525748138561\r\n2011-07-26 19:15:01,0.484852616211\r\n2011-07-26 20:15:01,0.484225645719\r\n2011-07-26 21:15:01,0.396638624414\r\n2011-07-26 22:15:01,0.422340743999\r\n2011-07-26 23:15:01,0.347862423243\r\n2011-07-27 00:15:01,0.355651253272\r\n2011-07-27 01:15:01,0.472819637318\r\n2011-07-27 02:15:01,0.42465090411\r\n2011-07-27 05:15:01,0.369590666017\r\n2011-07-27 06:15:01,0.341975423207\r\n2011-07-27 07:15:01,0.385071903859\r\n2011-07-27 08:15:01,0.449638417028\r\n2011-07-27 09:15:01,0.485024107731\r\n2011-07-27 10:15:01,0.503880485702\r\n2011-07-27 11:15:01,0.649875468026\r\n2011-07-27 12:15:01,0.900444803882\r\n2011-07-27 13:15:01,0.921812066603\r\n2011-07-27 14:15:01,0.799267434936\r\n2011-07-27 15:15:01,0.5669058795\r\n2011-07-27 16:15:01,0.592411494104\r\n2011-07-27 17:15:01,0.476107270232\r\n2011-07-27 18:15:01,0.491887576287\r\n2011-07-27 19:15:01,0.475071540278\r\n2011-07-27 20:15:01,0.447284149613\r\n2011-07-27 21:15:01,0.478995312103\r\n2011-07-27 22:15:01,0.44316906746\r\n2011-07-27 23:15:01,0.362373551562\r\n2011-07-28 00:15:01,0.353371351895\r\n2011-07-28 01:15:01,0.500298235797\r\n2011-07-28 02:15:01,0.453735304062\r\n2011-07-28 03:15:01,0.444910788743\r\n2011-07-28 04:15:01,0.388427934987\r\n2011-07-28 05:15:01,0.336372101252\r\n2011-07-28 06:15:01,0.356857600543\r\n2011-07-28 07:15:01,0.50117066916\r\n2011-07-28 08:15:01,0.419210640281\r\n2011-07-28 09:15:01,0.606202190542\r\n2011-07-28 10:15:01,0.612685287889\r\n2011-07-28 11:15:01,0.849234393404\r\n2011-07-28 12:15:01,1.19378143801\r\n2011-07-28 13:15:01,0.693728857663\r\n2011-07-28 14:15:01,0.830594474462\r\n2011-07-28 15:15:01,0.642496762959\r\n2011-07-28 16:15:01,0.549461019164\r\n2011-07-28 17:15:01,0.471706205502\r\n2011-07-28 18:15:01,0.523558103174\r\n2011-07-28 19:15:01,0.460153344327\r\n2011-07-28 20:15:01,0.484955907773\r\n2011-07-28 21:15:01,0.515769796423\r\n2011-07-28 22:15:01,0.448284108066\r\n2011-07-28 23:15:01,0.430648577052\r\n2011-07-29 00:15:01,0.428464730929\r\n2011-07-29 01:15:01,0.50383463487\r\n2011-07-29 02:15:01,0.48908390281\r\n2011-07-29 03:15:01,0.430424920234\r\n2011-07-29 04:15:01,0.421459720562\r\n2011-07-29 05:15:01,0.38182361723\r\n2011-07-29 06:15:01,0.414216287201\r\n2011-07-29 07:15:01,0.429408844655\r\n2011-07-29 08:15:01,0.536157500477\r\n2011-07-29 09:15:01,0.72305326685\r\n2011-07-29 10:15:01,0.796266588887\r\n2011-07-29 11:15:01,1.03498390948\r\n2011-07-29 12:15:01,1.10071677602\r\n2011-07-29 13:15:01,0.980824921978\r\n2011-07-29 14:15:01,1.00210466131\r\n2011-07-29 15:15:01,0.734911682259\r\n2011-07-29 16:15:01,0.756412897909\r\n2011-07-29 17:15:01,0.59817101608\r\n2011-07-29 18:15:01,0.673976028606\r\n2011-07-29 19:15:01,0.649754020916\r\n2011-07-29 20:15:01,0.592631426905\r\n2011-07-29 21:15:01,0.65991491423\r\n2011-07-29 22:15:01,0.626581379568\r\n2011-07-29 23:15:01,0.578915126635\r\n2011-07-30 00:15:01,0.608687044547\r\n2011-07-30 01:15:01,0.670799943403\r\n2011-07-30 02:15:01,0.640060585538\r\n2011-07-30 03:15:01,0.659653508315\r\n2011-07-30 04:15:01,0.475267844485\r\n2011-07-30 05:15:01,0.512949516523\r\n2011-07-30 06:15:01,0.524415858356\r\n2011-07-30 07:15:01,0.574065799941\r\n2011-07-30 08:15:01,0.568731977426\r\n2011-07-30 09:15:01,0.644472679623\r\n2011-07-30 10:15:01,0.559871884315\r\n2011-07-30 11:15:01,0.969953850686\r\n2011-07-30 12:15:01,1.07140826653\r\n2011-07-30 13:15:01,1.03096993273\r\n2011-07-30 14:15:01,0.937015144758\r\n2011-07-30 15:15:01,0.819120085845\r\n2011-07-30 16:15:01,0.683689190651\r\n2011-07-30 17:15:01,0.535112398674\r\n2011-07-30 20:15:01,0.576377992756\r\n2011-07-30 21:15:01,0.553529713893\r\n2011-07-30 22:15:01,0.523731134272\r\n2011-07-30 23:15:01,0.51688836525\r\n2011-07-31 00:15:01,0.439294307061\r\n2011-07-31 01:15:01,0.648390249655\r\n2011-07-31 02:15:01,0.581880306629\r\n2011-07-31 04:15:01,0.529118257924\r\n2011-07-31 05:15:01,0.485536149182\r\n2011-07-31 06:15:01,0.500015487422\r\n2011-07-31 07:15:01,0.51460008046\r\n2011-07-31 08:15:01,0.533621281078\r\n2011-07-31 09:15:01,0.682004403246\r\n2011-07-31 10:15:01,0.630815315617\r\n2011-07-31 11:15:01,0.851473399697\r\n2011-07-31 12:15:01,1.02661392802\r\n2011-07-31 13:15:01,1.29937784256\r\n2011-07-31 14:15:01,0.901679325483\r\n2011-07-31 15:15:01,0.832724097616\r\n2011-07-31 16:15:01,0.677929487521\r\n2011-07-31 17:15:01,0.635344512686\r\n2011-07-31 18:15:01,0.541728069495\r\n2011-07-31 19:15:01,0.557364618123\r\n2011-07-31 20:15:01,0.611843812083\r\n2011-07-31 21:15:01,0.523288282779\r\n2011-07-31 23:15:01,0.518364312775\r\n2011-08-01 00:15:01,0.498728225752\r\n2011-08-01 03:15:01,0.576555937381\r\n2011-08-01 05:15:01,0.554290565277\r\n2011-08-01 06:15:01,0.476010861023\r\n2011-08-01 07:15:01,0.449696671034\r\n2011-08-01 08:15:01,0.551743210305\r\n2011-08-01 09:15:01,0.756095103768\r\n2011-08-01 10:15:01,0.734396138798\r\n2011-08-01 11:15:01,0.846458555842\r\n2011-08-01 12:15:01,1.1775573547\r\n2011-08-01 13:15:01,0.780463324214\r\n2011-08-01 14:15:01,1.00941909107\r\n2011-08-01 15:15:01,0.819694770134\r\n2011-08-01 16:15:01,0.764223282266\r\n2011-08-01 17:15:01,0.663092200538\r\n2011-08-01 18:15:01,0.653564393467\r\n2011-08-01 20:15:01,0.577674184768\r\n2011-08-01 21:15:01,0.54488363266\r\n2011-08-01 23:15:01,0.531751330342\r\n2011-08-02 00:15:01,0.574685145904\r\n2011-08-02 01:15:01,0.635687697157\r\n2011-08-02 02:15:01,0.58853026189\r\n2011-08-02 03:15:01,0.466300750966\r\n2011-08-02 05:15:01,0.426776142971\r\n2011-08-02 06:15:01,0.431905267695\r\n2011-08-02 07:15:01,0.486788508189\r\n2011-08-02 08:15:01,0.520916021747\r\n2011-08-02 09:15:01,0.631112923168\r\n2011-08-02 10:15:01,0.787905664181\r\n2011-08-02 11:15:01,1.15101155113\r\n2011-08-02 12:15:01,1.40471250275\r\n2011-08-02 13:15:01,0.919172005914\r\n2011-08-02 14:15:01,0.930289680113\r\n2011-08-02 15:15:01,0.911233169005\r\n2011-08-02 16:15:01,0.562151951525\r\n2011-08-02 18:15:01,0.645033038997\r\n2011-08-02 19:15:01,0.648685752389\r\n2011-08-02 20:15:01,0.541655156634\r\n2011-08-02 21:15:01,0.629047798928\r\n2011-08-02 22:15:01,0.70048738269\r\n2011-08-02 23:15:01,0.53379122543\r\n2011-08-03 00:15:01,0.440444722304\r\n2011-08-03 01:15:01,0.719683930527\r\n2011-08-03 02:15:01,0.710997940534\r\n2011-08-03 03:15:01,0.594979361314\r\n2011-08-03 04:15:01,0.449055478674\r\n2011-08-03 05:15:01,0.477755007181\r\n2011-08-03 06:15:01,0.503697983752\r\n2011-08-03 07:15:01,0.600102091293\r\n2011-08-03 08:15:01,0.561552932585\r\n2011-08-03 09:15:01,0.79419877957\r\n2011-08-03 10:15:01,0.785667933624\r\n2011-08-03 11:15:01,1.13982041415\r\n2011-08-03 12:15:01,1.19103416667\r\n2011-08-03 13:15:01,1.17852075751\r\n2011-08-03 14:15:01,0.75004468933\r\n2011-08-03 15:15:01,0.817874388891\r\n2011-08-03 17:15:01,0.722743200455\r\n2011-08-03 18:15:01,0.584243911365\r\n2011-08-03 19:15:01,0.62690718902\r\n2011-08-03 20:15:01,0.583636953993\r\n2011-08-03 21:15:01,0.638105501939\r\n2011-08-03 22:15:01,0.553943354236\r\n2011-08-03 23:15:01,0.698302566298\r\n2011-08-04 00:15:01,0.585952461824\r\n2011-08-04 01:15:01,0.680807542384\r\n2011-08-04 02:15:01,0.633855601382\r\n2011-08-04 03:15:01,0.820624317284\r\n2011-08-04 04:15:01,0.557292109026\r\n2011-08-04 05:15:01,0.41470422161\r\n2011-08-04 06:15:01,0.525180710389\r\n2011-08-04 07:15:01,0.548682741313\r\n2011-08-04 08:15:01,0.556389097274\r\n2011-08-04 09:15:01,0.671852412749\r\n2011-08-04 10:15:01,0.815993714002\r\n2011-08-04 11:15:01,0.893970122675\r\n2011-08-04 12:15:01,1.08664281817\r\n2011-08-04 13:15:01,1.12298696319\r\n2011-08-04 14:15:01,0.95005399809\r\n2011-08-04 16:15:01,0.715950660979\r\n2011-08-04 17:15:01,0.795825740766\r\n2011-08-04 18:15:01,0.647634508959\r\n2011-08-04 19:15:01,0.555697769319\r\n2011-08-04 20:15:01,1.42072295982\r\n2011-08-04 21:15:01,0.592265160479\r\n2011-08-04 22:15:01,0.568243786567\r\n2011-08-04 23:15:01,0.604767739087\r\n2011-08-05 00:15:01,0.555048814747\r\n2011-08-05 01:15:01,0.686409550046\r\n2011-08-05 02:15:01,0.664502043993\r\n2011-08-05 03:15:01,0.751783059049\r\n2011-08-05 04:15:01,0.536707916534\r\n2011-08-05 05:15:01,0.584625706011\r\n2011-08-05 06:15:01,0.543533656374\r\n2011-08-05 07:15:01,0.541778547457\r\n2011-08-05 08:15:01,0.611421644746\r\n2011-08-05 09:15:01,0.726964468474\r\n2011-08-05 10:15:01,0.802952723852\r\n2011-08-05 11:15:01,1.0420973625\r\n2011-08-05 12:15:01,1.05794478293\r\n2011-08-05 13:15:01,1.14759081927\r\n2011-08-05 14:15:01,0.995947810883\r\n2011-08-05 15:15:01,0.837924146178\r\n2011-08-05 17:15:01,0.639849442198\r\n2011-08-05 19:15:01,0.676064732772\r\n2011-08-05 20:15:01,0.543911542172\r\n2011-08-05 21:15:01,0.577292345427\r\n2011-08-05 22:15:01,0.543720793978\r\n2011-08-05 23:15:01,0.574428235604\r\n2011-08-06 00:15:01,0.536694938229\r\n2011-08-06 01:15:01,0.721242372337\r\n2011-08-06 02:15:01,0.719180486143\r\n2011-08-06 03:15:01,0.664986357941\r\n2011-08-06 04:15:01,0.675107829796\r\n2011-08-06 05:15:01,0.568417908432\r\n2011-08-06 06:15:01,0.560745261334\r\n2011-08-06 07:15:01,0.589784142503\r\n2011-08-06 08:15:01,0.675166106392\r\n2011-08-06 09:15:01,0.713929339861\r\n2011-08-06 10:15:01,0.720525247971\r\n2011-08-06 11:15:01,0.973101693998\r\n2011-08-06 12:15:01,1.04109900091\r\n2011-08-06 13:15:01,1.10076528064\r\n2011-08-06 15:15:01,0.858281143262\r\n2011-08-06 16:15:01,0.718258734174\r\n2011-08-06 17:15:01,0.652482726953\r\n2011-08-06 18:15:01,0.603126873225\r\n2011-08-06 19:15:01,0.615980506115\r\n2011-08-06 20:15:01,0.518617271676\r\n2011-08-06 21:15:01,0.612084186098\r\n2011-08-06 22:15:01,0.6041011793\r\n2011-08-06 23:15:01,0.519409820872\r\n2011-08-07 00:15:01,0.635188073777\r\n2011-08-07 01:15:01,0.68608152933\r\n2011-08-07 02:15:01,0.609118718996\r\n2011-08-07 03:15:01,0.582622271093\r\n2011-08-07 04:15:01,0.598422475252\r\n2011-08-07 05:15:01,0.561157963103\r\n2011-08-07 06:15:01,0.593355289604\r\n2011-08-07 07:15:01,0.623050235785\r\n2011-08-07 08:15:01,0.687373850639\r\n2011-08-07 09:15:01,0.665167658556\r\n2011-08-07 10:15:01,0.849833024706\r\n2011-08-07 11:15:01,0.946772757303\r\n2011-08-07 12:15:01,1.05214350573\r\n2011-08-07 13:15:01,1.49678514312\r\n2011-08-07 14:15:01,0.867744078979\r\n2011-08-07 15:15:01,0.819632696943\r\n2011-08-07 16:15:01,0.74004421129\r\n2011-08-07 17:15:01,0.705276178788\r\n2011-08-07 18:15:01,0.648443555101\r\n2011-08-07 19:15:01,0.55609604234\r\n2011-08-07 20:15:01,0.624781661692\r\n2011-08-07 21:15:01,0.605392560095\r\n2011-08-07 22:15:01,0.568348885355\r\n2011-08-07 23:15:01,0.548749163255\r\n2011-08-08 00:15:01,0.606434621799\r\n2011-08-08 01:15:01,0.646378233592\r\n2011-08-08 02:15:01,0.580301698869\r\n2011-08-08 03:15:01,0.565836250493\r\n2011-08-08 04:15:01,0.569189356342\r\n2011-08-08 05:15:01,0.538710969129\r\n2011-08-08 06:15:01,0.513768455929\r\n2011-08-08 07:15:01,0.559171613811\r\n2011-08-08 08:15:01,0.575195729644\r\n2011-08-08 09:15:01,0.652947245764\r\n2011-08-08 10:15:01,0.74503888758\r\n2011-08-08 11:15:01,0.857579554687\r\n2011-08-08 12:15:01,0.875553118504\r\n2011-08-08 13:15:01,0.854941413658\r\n2011-08-08 14:15:01,0.790767678673\r\n2011-08-08 16:15:01,0.712741698358\r\n2011-08-08 17:15:01,0.615699781863\r\n2011-08-08 18:15:01,0.595200849764\r\n2011-08-08 19:15:01,0.634719459996\r\n2011-08-08 20:15:01,0.547550792253\r\n2011-08-08 21:15:01,0.590809094235\r\n2011-08-08 22:15:01,0.570679942692\r\n2011-08-08 23:15:01,0.54153421526\r\n2011-08-09 00:15:01,0.536134186043\r\n2011-08-09 01:15:01,0.58694728119\r\n2011-08-09 02:15:01,0.599060021738\r\n2011-08-09 03:15:01,0.578157413533\r\n2011-08-09 04:15:01,0.50181775834\r\n2011-08-09 05:15:01,0.518201067593\r\n2011-08-09 06:15:01,0.511505673511\r\n2011-08-09 07:15:01,0.597075586726\r\n2011-08-09 08:15:01,0.598728666922\r\n2011-08-09 09:15:01,0.783646778861\r\n2011-08-09 10:15:01,0.788622722111\r\n2011-08-09 11:15:01,0.86311824481\r\n2011-08-09 12:15:01,1.27301519137\r\n2011-08-09 14:15:01,0.88404025791\r\n2011-08-09 15:15:01,0.802570074162\r\n2011-08-09 16:15:01,0.723815454876\r\n2011-08-09 17:15:01,0.661586612293\r\n2011-08-09 18:15:01,0.617642290617\r\n2011-08-09 19:15:01,0.629898957434\r\n2011-08-09 20:15:01,0.601685026205\r\n2011-08-09 21:15:01,0.645256582208\r\n2011-08-09 22:15:01,0.590185964475\r\n2011-08-09 23:15:01,0.620264322455\r\n2011-08-10 00:15:01,0.559184359065\r\n2011-08-10 01:15:01,0.590161480456\r\n2011-08-10 02:15:01,0.591462623116\r\n2011-08-10 03:15:01,0.642369010583\r\n2011-08-10 04:15:01,0.520049263822\r\n2011-08-10 05:15:01,0.502427012098\r\n2011-08-10 06:15:01,0.504466919255\r\n2011-08-10 07:15:01,0.50623672691\r\n2011-08-10 08:15:01,0.547044702758\r\n2011-08-10 09:15:01,0.624164877273\r\n2011-08-10 10:15:01,0.821473591903\r\n2011-08-10 11:15:01,0.962219823481\r\n2011-08-10 12:15:01,1.13254543144\r\n2011-08-10 13:15:01,0.946045959158\r\n2011-08-10 15:15:01,0.983489745003\r\n2011-08-10 17:15:01,0.82094562393\r\n2011-08-10 18:15:01,0.730903856743\r\n2011-08-10 19:15:01,0.625206071634\r\n2011-08-10 20:15:01,0.731170579564\r\n2011-08-10 21:15:01,0.676400974391\r\n2011-08-10 23:15:01,0.660492954703\r\n2011-08-11 00:15:01,0.554590237895\r\n2011-08-11 01:15:01,0.715748968801\r\n2011-08-11 02:15:01,0.552449342809\r\n2011-08-11 03:15:01,0.608818563823\r\n2011-08-11 04:15:01,0.56535245238\r\n2011-08-11 05:15:01,0.545612490685\r\n2011-08-11 06:15:01,0.521651179882\r\n2011-08-11 07:15:01,0.577066436906\r\n2011-08-11 08:15:01,0.649319201432\r\n2011-08-11 09:15:01,0.761580436424\r\n2011-08-11 10:15:01,0.958909403592\r\n2011-08-11 11:15:01,0.879025593085\r\n2011-08-11 12:15:01,1.02881514616\r\n2011-08-11 14:15:01,1.12794638303\r\n2011-08-11 15:15:01,0.806395267298\r\n2011-08-11 16:15:01,0.998546127412\r\n2011-08-11 17:15:01,0.797586425481\r\n2011-08-11 18:15:01,0.653892646469\r\n2011-08-11 19:15:01,0.668489407469\r\n2011-08-11 20:15:01,0.704774059598\r\n2011-08-11 21:15:01,0.618160741346\r\n2011-08-11 22:15:01,0.703522679277\r\n2011-08-11 23:15:01,0.645565581113\r\n2011-08-12 00:15:01,0.641368766824\r\n2011-08-12 01:15:01,0.705282913257\r\n2011-08-12 02:15:01,0.612891663325\r\n2011-08-12 03:15:01,0.59561723886\r\n2011-08-12 04:15:01,0.397505242902\r\n2011-08-12 05:15:01,0.4334602526\r\n2011-08-12 06:15:01,0.452638011815\r\n2011-08-12 07:15:01,0.554466657955\r\n2011-08-12 08:15:01,0.762423745569\r\n2011-08-12 09:15:01,0.743389683572\r\n2011-08-12 10:15:01,1.2398054085\r\n2011-08-12 11:15:01,1.24785288471\r\n2011-08-12 13:15:01,1.56976504958\r\n2011-08-12 14:15:01,1.30445869153\r\n2011-08-12 15:15:01,0.913389056971\r\n2011-08-12 16:15:01,0.797229088648\r\n2011-08-12 17:15:01,0.588670630441\r\n2011-08-12 18:15:01,0.621693121693\r\n2011-08-12 19:15:01,0.561822051743\r\n2011-08-12 21:15:01,0.586936754634\r\n2011-08-12 22:15:01,0.510457600443\r\n2011-08-12 23:15:01,0.411906443438\r\n2011-08-13 00:15:01,0.481140662888\r\n2011-08-13 01:15:01,0.727249846188\r\n2011-08-13 02:15:01,0.692740174194\r\n2011-08-13 03:15:01,0.606669069316\r\n2011-08-13 04:15:01,0.481597592012\r\n2011-08-13 05:15:01,0.452214871573\r\n2011-08-13 06:15:01,0.503423930085\r\n2011-08-13 07:15:01,0.592080023871\r\n2011-08-13 08:15:01,0.670440067671\r\n2011-08-13 09:15:01,0.781322734271\r\n2011-08-13 10:15:01,1.12155162029\r\n2011-08-13 11:15:01,1.14461358314\r\n2011-08-13 12:15:01,2.3458511804\r\n2011-08-13 13:15:01,1.78017877028\r\n2011-08-13 15:15:01,1.16344626108\r\n2011-08-13 17:15:01,0.80366590851\r\n2011-08-13 18:15:01,0.835319293809\r\n2011-08-13 19:15:01,0.61608130586\r\n2011-08-13 20:15:01,0.551187458629\r\n2011-08-13 21:15:01,0.496627535469\r\n2011-08-13 22:15:01,0.471666183154\r\n2011-08-13 23:15:01,0.646252600178\r\n2011-08-14 00:15:01,0.610524145889\r\n2011-08-14 01:15:01,0.740457772665\r\n2011-08-14 02:15:01,0.67648312914\r\n2011-08-14 03:15:01,0.6999543225\r\n2011-08-14 04:15:01,0.581878572182\r\n2011-08-14 05:15:01,0.574517129817\r\n2011-08-14 06:15:01,0.588103546132\r\n2011-08-14 07:15:01,0.682825589466\r\n2011-08-14 08:15:01,0.702503350973\r\n2011-08-14 09:15:01,0.811665071193\r\n2011-08-14 10:15:01,0.959159638626\r\n2011-08-14 11:15:01,1.13891248326\r\n2011-08-14 12:15:01,1.31995254103\r\n2011-08-14 13:15:01,1.14913574749\r\n2011-08-14 14:15:01,1.17398097723\r\n2011-08-14 15:15:01,0.910558605102\r\n2011-08-14 16:15:01,0.786068674769\r\n2011-08-14 17:15:01,0.809601949747\r\n2011-08-14 18:15:01,0.755417840119\r\n2011-08-14 19:15:01,0.749192553692\r\n2011-08-14 20:15:01,0.665563624108\r\n2011-08-14 21:15:01,0.721558658688\r\n2011-08-14 22:15:01,0.685192621577\r\n2011-08-14 23:15:01,0.557077450057\r\n2011-08-15 01:15:01,0.636081308305\r\n2011-08-15 02:15:01,0.667131109384\r\n2011-08-15 03:15:01,0.735076057078\r\n2011-08-15 04:15:01,0.580668384959\r\n2011-08-15 05:15:01,0.579281629473\r\n2011-08-15 06:15:01,0.602451454238\r\n2011-08-15 07:15:01,0.644382914486\r\n2011-08-15 08:15:01,0.714276606054\r\n2011-08-15 09:15:01,0.848933518167\r\n2011-08-15 10:15:01,0.966559247715\r\n2011-08-15 11:15:01,1.05050887436\r\n2011-08-15 12:15:01,1.04251488078\r\n2011-08-15 14:15:01,0.932878270762\r\n2011-08-15 15:15:01,0.826720919972\r\n2011-08-15 16:15:01,0.776904573404\r\n2011-08-15 17:15:01,0.716201992703\r\n2011-08-15 18:15:01,0.711605913562\r\n2011-08-15 19:15:01,0.708530490055\r\n2011-08-15 20:15:01,0.663736975075\r\n2011-08-15 21:15:01,0.622400018566\r\n2011-08-15 22:15:01,0.607611681058\r\n2011-08-15 23:15:01,0.611072281173\r\n2011-08-16 00:15:01,0.563604798437\r\n2011-08-16 01:15:01,0.686922142397\r\n2011-08-16 02:15:01,0.675897036319\r\n2011-08-16 03:15:01,0.667313844917\r\n2011-08-16 04:15:01,0.628226199954\r\n2011-08-16 05:15:01,0.595912441675\r\n2011-08-16 06:15:01,0.634416844861\r\n2011-08-16 07:15:01,0.685898336104\r\n2011-08-16 08:15:01,0.826101318279\r\n2011-08-16 09:15:01,0.892529350396\r\n2011-08-16 10:15:01,1.12081818742\r\n2011-08-16 11:15:01,1.12547861639\r\n2011-08-16 12:15:01,1.12175474239\r\n2011-08-16 13:15:01,1.05128934078\r\n2011-08-16 14:15:01,0.966681309319\r\n2011-08-16 15:15:01,0.990511125266\r\n2011-08-16 16:15:01,0.879749252927\r\n2011-08-16 17:15:01,0.714478939876\r\n2011-08-16 18:15:01,0.877238546553\r\n2011-08-16 19:15:01,0.725744019401\r\n2011-08-16 20:15:01,0.761700055415\r\n2011-08-16 21:15:01,0.714732926186\r\n2011-08-16 22:15:01,0.676804863428\r\n2011-08-16 23:15:01,0.711416021227\r\n2011-08-17 00:15:01,0.607743520633\r\n2011-08-17 01:15:01,0.736028088655\r\n2011-08-17 02:15:01,0.66488033209\r\n2011-08-17 03:15:01,0.619237027662\r\n2011-08-17 04:15:01,0.550742015432\r\n2011-08-17 05:15:01,0.555550082264\r\n2011-08-17 06:15:01,0.616679440644\r\n2011-08-17 07:15:01,0.693236714976\r\n2011-08-17 08:15:01,0.810488810541\r\n2011-08-17 09:15:01,0.932629669333\r\n2011-08-17 10:15:01,1.10551712253\r\n2011-08-17 11:15:01,1.24432225675\r\n2011-08-17 12:15:01,1.07751682008\r\n2011-08-17 13:15:01,0.993365801281\r\n2011-08-17 14:15:01,1.03636422863\r\n2011-08-17 15:15:01,0.927039239851\r\n2011-08-17 16:15:01,0.821436448207\r\n2011-08-17 18:15:01,0.762617399275\r\n2011-08-17 19:15:01,0.714061062878\r\n2011-08-17 20:15:01,0.735661201354\r\n2011-08-17 21:15:01,0.666658952973\r\n2011-08-17 22:15:01,0.621769977351\r\n2011-08-17 23:15:01,0.548446739751\r\n2011-08-18 00:15:01,0.544978141492\r\n2011-08-18 01:15:01,0.758639317537\r\n2011-08-18 02:15:01,0.732381898533\r\n2011-08-18 03:15:01,0.570647047727\r\n2011-08-18 04:15:01,0.534028307408\r\n2011-08-18 05:15:01,0.542765533075\r\n2011-08-18 06:15:01,0.567515064457\r\n2011-08-18 07:15:01,0.683516370065\r\n2011-08-18 08:15:01,0.718008272579\r\n2011-08-18 09:15:01,0.936216066342\r\n2011-08-18 10:15:01,0.977670956737\r\n2011-08-18 11:15:01,0.953869233654\r\n2011-08-18 12:15:01,0.958412841486\r\n2011-08-18 13:15:01,0.982262310647\r\n2011-08-18 14:15:01,0.944170398835\r\n2011-08-18 15:15:01,0.712214878216\r\n2011-08-18 16:15:01,0.779245317679\r\n2011-08-18 18:15:01,0.770476887313\r\n2011-08-18 20:15:01,0.772785581145\r\n2011-08-18 21:15:01,0.792569185776\r\n2011-08-18 22:15:01,0.892232194744\r\n2011-08-18 23:15:01,0.928590112477\r\n2011-08-19 00:15:01,0.809001110711\r\n2011-08-19 01:15:01,0.773142351037\r\n2011-08-19 02:15:01,0.68364500895\r\n2011-08-19 03:15:01,0.666356498685\r\n2011-08-19 04:15:01,0.602663491936\r\n2011-08-19 05:15:01,0.615586216743\r\n2011-08-19 06:15:01,0.680106983428\r\n2011-08-19 07:15:01,0.715438473764\r\n2011-08-19 08:15:01,0.778365849468\r\n2011-08-19 09:15:01,0.940738025415\r\n2011-08-19 10:15:01,1.06431149513\r\n2011-08-19 11:15:01,1.03322345475\r\n2011-08-19 12:15:01,1.06920531499\r\n2011-08-19 13:15:01,0.90248188841\r\n2011-08-19 14:15:01,0.948048756512\r\n2011-08-19 15:15:01,0.940754216038\r\n2011-08-19 16:15:01,0.934222809879\r\n2011-08-19 18:15:01,5.49754000266\r\n2011-08-19 19:15:01,0.863326087315\r\n2011-08-19 20:15:01,0.703298738091\r\n2011-08-19 21:15:01,0.713623326394\r\n2011-08-19 22:15:01,0.654695043258\r\n2011-08-19 23:15:01,0.674132038136\r\n2011-08-20 00:15:01,0.662703093534\r\n2011-08-20 01:15:01,0.794094232044\r\n2011-08-20 02:15:01,0.682984438197\r\n2011-08-20 03:15:01,0.668096114705\r\n2011-08-20 04:15:01,0.644444815845\r\n2011-08-20 05:15:01,0.631821336803\r\n2011-08-20 06:15:01,0.664079704752\r\n2011-08-20 07:15:01,0.691809112522\r\n2011-08-20 08:15:01,0.731047520971\r\n2011-08-20 09:15:01,0.916183652659\r\n2011-08-20 10:15:01,1.12615701063\r\n2011-08-20 11:15:01,1.37892666256\r\n2011-08-20 12:15:01,1.48058619127\r\n2011-08-20 13:15:01,1.11576620573\r\n2011-08-20 14:15:01,1.10130283386\r\n2011-08-20 15:15:01,0.917978202373\r\n2011-08-20 16:15:01,0.868671626148\r\n2011-08-20 17:15:01,0.804527172255\r\n2011-08-20 18:15:01,0.745593099694\r\n2011-08-20 19:15:01,0.693628880174\r\n2011-08-20 20:15:01,0.713280266363\r\n2011-08-20 21:15:01,0.69452314481\r\n2011-08-20 22:15:01,0.676418731136\r\n2011-08-20 23:15:01,0.705210678675\r\n2011-08-21 00:15:01,0.693664559433\r\n2011-08-21 01:15:01,0.741737529738\r\n2011-08-21 02:15:01,0.740867235598\r\n2011-08-21 03:15:01,0.755155629406\r\n2011-08-21 04:15:01,0.663611083149\r\n2011-08-21 05:15:01,0.645370135798\r\n2011-08-21 06:15:01,0.649619761544\r\n2011-08-21 07:15:01,0.70872257412\r\n2011-08-21 08:15:01,0.692568813021\r\n2011-08-21 09:15:01,0.739975603038\r\n2011-08-21 10:15:01,1.07428499644\r\n2011-08-21 11:15:01,1.29783044803\r\n2011-08-21 12:15:01,1.18176109093\r\n2011-08-21 13:15:01,1.29187384737\r\n2011-08-21 15:15:01,0.937208385358\r\n2011-08-21 16:15:01,0.91911195455\r\n2011-08-21 17:15:01,0.755583102096\r\n2011-08-21 18:15:01,0.745270462145\r\n2011-08-21 19:15:01,0.710554099813\r\n2011-08-21 20:15:01,0.658328261736\r\n2011-08-21 21:15:01,0.724803116745\r\n2011-08-21 22:15:01,0.705354280218\r\n2011-08-21 23:15:01,0.689806462107\r\n2011-08-22 00:15:01,0.60689583826\r\n2011-08-22 01:15:01,0.651337689557\r\n2011-08-22 02:15:01,0.62934487776\r\n2011-08-22 03:15:01,0.62372916466\r\n2011-08-22 04:15:01,0.577398944823\r\n2011-08-22 05:15:01,0.572886854195\r\n2011-08-22 06:15:01,0.594058752156\r\n2011-08-22 07:15:01,0.582907570831\r\n2011-08-22 08:15:01,0.734216695443\r\n2011-08-22 09:15:01,0.806454982244\r\n2011-08-22 10:15:01,0.969068717606\r\n2011-08-22 11:15:01,0.849613756806\r\n2011-08-22 12:15:01,0.890577507599\r\n2011-08-22 13:15:01,0.972369871643\r\n2011-08-22 15:15:01,0.830408286317\r\n2011-08-22 16:15:01,0.790874543276\r\n2011-08-22 17:15:01,0.868033239748\r\n2011-08-22 18:15:01,0.753268013611\r\n2011-08-22 19:15:01,0.75341096872\r\n2011-08-22 20:15:01,0.723666685969\r\n2011-08-22 21:15:01,0.641627543036\r\n2011-08-22 22:15:01,0.793713273077\r\n2011-08-22 23:15:01,0.778934874729\r\n2011-08-23 00:15:01,0.710999652634\r\n2011-08-23 01:15:01,0.703201657157\r\n2011-08-23 02:15:01,0.669306023229\r\n2011-08-23 03:15:01,0.623246944026\r\n2011-08-23 04:15:01,0.59842770237\r\n2011-08-23 05:15:01,0.618625761565\r\n2011-08-23 06:15:01,0.673907341691\r\n2011-08-23 07:15:01,0.776481358143\r\n2011-08-23 08:15:01,0.904231856983\r\n2011-08-23 09:15:01,1.29383792352\r\n2011-08-23 10:15:01,1.13551430877\r\n2011-08-23 11:15:01,1.0251356609\r\n2011-08-23 12:15:01,1.18905411994\r\n2011-08-23 13:15:01,1.27127243107\r\n2011-08-23 14:15:01,1.15911742747\r\n2011-08-23 16:15:01,1.05845536275\r\n2011-08-23 17:15:01,0.926634493627\r\n2011-08-23 18:15:01,0.776918970136\r\n2011-08-23 19:15:01,0.928010146312\r\n2011-08-23 20:15:01,0.838158380029\r\n2011-08-23 21:15:01,0.819862464009\r\n2011-08-23 22:15:01,0.69970306261\r\n2011-08-23 23:15:01,0.842383353699\r\n2011-08-24 00:15:01,0.792468794781\r\n2011-08-24 01:15:01,0.713359095889\r\n2011-08-24 02:15:01,0.704135949192\r\n2011-08-24 03:15:01,0.641155335986\r\n2011-08-24 04:15:01,0.634568795601\r\n2011-08-24 05:15:01,0.645873833534\r\n2011-08-24 06:15:01,0.6590434368\r\n2011-08-24 07:15:01,0.812906195196\r\n2011-08-24 08:15:01,0.881111571307\r\n2011-08-24 09:15:01,1.24918386562\r\n2011-08-24 10:15:01,1.36501420903\r\n2011-08-24 11:15:01,1.95241011285\r\n2011-08-24 12:15:01,1.54697912263\r\n2011-08-24 13:15:01,1.5651661815\r\n2011-08-24 15:15:01,1.22446525543\r\n2011-08-24 16:15:01,1.1562087199\r\n2011-08-24 17:15:01,1.33774834437\r\n2011-08-24 18:15:01,1.03148188994\r\n2011-08-24 19:15:01,0.935049971832\r\n2011-08-24 20:15:01,0.711196895617\r\n2011-08-24 21:15:01,0.767570958313\r\n2011-08-24 22:15:01,0.735954907513\r\n2011-08-24 23:15:01,0.77345193875\r\n2011-08-25 00:15:01,0.692628331902\r\n2011-08-25 01:15:01,0.824416895061\r\n2011-08-25 02:15:01,0.730707604827\r\n2011-08-25 03:15:01,0.715088082545\r\n2011-08-25 04:15:01,0.744875421318\r\n2011-08-25 05:15:01,0.737488743085\r\n2011-08-25 06:15:01,0.717183548371\r\n2011-08-25 07:15:01,0.833624102622\r\n2011-08-25 08:15:01,0.953373503323\r\n2011-08-25 09:15:01,1.31115307189\r\n2011-08-25 10:15:01,1.16843727867\r\n2011-08-25 11:15:01,1.0374018924\r\n2011-08-25 12:15:01,1.07353824758\r\n2011-08-25 13:15:01,1.18426544594\r\n2011-08-25 15:15:01,0.81995711885\r\n2011-08-25 16:15:01,1.08679580518\r\n2011-08-25 17:15:01,1.2173424085\r\n2011-08-25 18:15:01,1.00456228294\r\n2011-08-25 19:15:01,1.03477665107\r\n2011-08-25 20:15:01,0.948686262348\r\n2011-08-25 21:15:01,0.993665532552\r\n2011-08-25 22:15:01,0.903960473484\r\n2011-08-25 23:15:01,0.788313159199\r\n2011-08-26 00:15:01,0.798556558757\r\n2011-08-26 01:15:01,0.734166131373\r\n2011-08-26 02:15:01,0.742638615815\r\n2011-08-26 03:15:01,0.675874389581\r\n2011-08-26 04:15:01,0.705817989883\r\n2011-08-26 05:15:01,0.727232396299\r\n2011-08-26 06:15:01,0.753356912152\r\n2011-08-26 07:15:01,0.875354972671\r\n2011-08-26 08:15:01,0.925335068588\r\n2011-08-26 10:15:01,1.19420541076\r\n2011-08-26 11:15:01,0.851330505206\r\n2011-08-26 12:15:01,1.31130509932\r\n2011-08-26 13:15:01,1.18812702098\r\n2011-08-26 14:15:01,1.10183903133\r\n2011-08-26 15:15:01,1.05379013513\r\n2011-08-26 16:15:01,1.07217664514\r\n2011-08-26 17:15:01,0.789734929311\r\n2011-08-26 18:15:01,0.890166131849\r\n2011-08-26 19:15:01,0.920508307487\r\n2011-08-26 20:15:01,0.950929806345\r\n2011-08-26 21:15:01,0.822102406411\r\n2011-08-26 22:15:01,0.826540433576\r\n2011-08-26 23:15:01,0.791927711761\r\n2011-08-27 00:15:01,0.702807204893\r\n2011-08-27 01:15:01,0.864523887721\r\n2011-08-27 02:15:01,0.809851903585\r\n2011-08-27 03:15:01,0.758690430787\r\n2011-08-27 04:15:01,0.80677831628\r\n2011-08-27 05:15:01,0.688049770453\r\n2011-08-27 06:15:01,0.81968980524\r\n2011-08-27 07:15:01,0.821442694794\r\n2011-08-27 08:15:01,1.06152614064\r\n2011-08-27 09:15:01,1.44317491332\r\n2011-08-27 10:15:01,1.22704597643\r\n2011-08-27 11:15:01,1.58093752585\r\n2011-08-27 12:15:01,1.51858142365\r\n2011-08-27 13:15:01,1.06284454245\r\n2011-08-27 14:15:01,1.29828215868\r\n2011-08-27 15:15:01,1.17357031987\r\n2011-08-27 16:15:01,0.938417521965\r\n2011-08-27 17:15:01,0.719759087413\r\n2011-08-27 18:15:01,0.793253640139\r\n2011-08-27 19:15:01,0.821043529075\r\n2011-08-27 20:15:01,0.77728705129\r\n2011-08-27 21:15:01,0.761011905195\r\n2011-08-27 22:15:01,0.794456554147\r\n2011-08-27 23:15:01,0.71510777014\r\n2011-08-28 00:15:01,0.670100640381\r\n2011-08-28 01:15:01,0.54761579658\r\n2011-08-28 17:15:01,0.849284090378\r\n2011-08-28 18:15:01,0.852476609926\r\n2011-08-28 19:15:01,0.805305280552\r\n2011-08-28 20:15:01,0.889728282553\r\n2011-08-28 21:15:01,0.778613508361\r\n2011-08-28 22:15:01,0.685767835952\r\n2011-08-28 23:15:01,0.726981575893\r\n2011-08-29 00:15:01,0.645975352581\r\n2011-08-29 01:15:01,0.777534142894\r\n2011-08-29 02:15:01,0.723113114405\r\n2011-08-29 03:15:01,0.831905214884\r\n2011-08-29 04:15:01,0.674230251552\r\n2011-08-29 05:15:01,0.71415081987\r\n2011-08-29 06:15:01,0.795823883546\r\n2011-08-29 07:15:01,0.853323981424\r\n2011-08-29 08:15:01,1.03638510945\r\n2011-08-29 09:15:01,1.16972027756\r\n2011-08-29 10:15:01,1.37015829137\r\n2011-08-29 11:15:01,1.19479416172\r\n2011-08-29 12:15:01,1.50872750294\r\n2011-08-29 13:15:01,1.25480461243\r\n2011-08-29 14:15:01,1.18351258787\r\n2011-08-29 15:15:01,0.838183770344\r\n2011-08-29 16:15:01,1.05843861494\r\n2011-08-29 17:15:01,1.1154608336\r\n2011-08-29 18:15:01,0.87860810131\r\n2011-08-29 19:15:01,1.09936880724\r\n2011-08-29 20:15:01,0.87085318709\r\n2011-08-29 21:15:01,0.843596628444\r\n2011-08-29 22:15:01,0.777040471902\r\n2011-08-29 23:15:01,0.688557936796\r\n2011-08-30 00:15:01,0.697836804319\r\n2011-08-30 01:15:01,0.771217121712\r\n2011-08-30 02:15:01,0.694660626848\r\n2011-08-30 03:15:01,0.786323057256\r\n2011-08-30 04:15:01,0.654660190687\r\n2011-08-30 05:15:01,0.72306000212\r\n2011-08-30 06:15:01,0.774674210709\r\n2011-08-30 07:15:01,0.884858627959\r\n2011-08-30 08:15:01,1.08493710832\r\n2011-08-30 09:15:01,1.14704937346\r\n2011-08-30 10:15:01,1.40645395214\r\n2011-08-30 11:15:01,0.967981387104\r\n2011-08-30 12:15:01,1.75374564605\r\n2011-08-30 13:15:01,1.22262717456\r\n2011-08-30 15:15:01,1.2477794358\r\n2011-08-30 16:15:01,1.04428573933\r\n2011-08-30 17:15:01,0.924926251082\r\n2011-08-30 18:15:01,1.20389636883\r\n2011-08-30 19:15:01,0.936448977169\r\n2011-08-30 21:15:01,0.869768173712\r\n2011-08-30 22:15:01,0.820539262738\r\n2011-08-30 23:15:01,0.855369516046\r\n2011-08-31 00:15:01,0.961147001986\r\n2011-08-31 01:15:01,0.958316270557\r\n2011-08-31 02:15:01,0.814787274063\r\n2011-08-31 03:15:01,0.771593377122\r\n2011-08-31 04:15:01,0.766299657727\r\n2011-08-31 05:15:01,0.724229465703\r\n2011-08-31 06:15:01,0.792862195384\r\n2011-08-31 07:15:01,0.942622099425\r\n2011-08-31 08:15:01,1.14142180366\r\n2011-08-31 09:15:01,1.50385784428\r\n2011-08-31 10:15:01,1.32986869524\r\n2011-08-31 11:15:01,1.35511366926\r\n2011-08-31 12:15:01,1.30690884147\r\n2011-08-31 13:15:01,1.36129882778\r\n2011-08-31 14:15:01,1.26118176226\r\n2011-08-31 15:15:01,1.29325090898\r\n2011-08-31 16:15:01,1.13162826786\r\n2011-08-31 17:15:01,0.878180273521\r\n2011-08-31 19:15:01,1.00724076188\r\n2011-08-31 20:15:01,0.82977849928\r\n2011-08-31 21:15:01,0.791770492231\r\n2011-08-31 22:15:01,0.776412218566\r\n2011-08-31 23:15:01,1.01967346467\r\n2011-09-01 00:15:01,0.672524767707\r\n2011-09-01 01:15:01,0.805459791968\r\n2011-09-01 02:15:01,0.697760708058\r\n2011-09-01 03:15:01,0.671198221878\r\n2011-09-01 04:15:01,0.686612619056\r\n2011-09-01 05:15:01,0.730138629699\r\n2011-09-01 06:15:01,0.773151750973\r\n2011-09-01 07:15:01,0.920818621438\r\n2011-09-01 08:15:01,1.05974998234\r\n2011-09-01 09:15:01,1.25720738674\r\n2011-09-01 10:15:01,1.69107806691\r\n2011-09-01 13:15:01,1.38872596255\r\n2011-09-01 18:15:01,1.18474325929\r\n2011-09-01 19:15:01,1.00755614801\r\n2011-09-01 20:15:01,0.889925459781\r\n2011-09-01 21:15:01,0.879357863581\r\n2011-09-01 22:15:01,0.813560856853\r\n2011-09-01 23:15:01,0.668334950547\r\n2011-09-02 00:15:01,0.634700519233\r\n2011-09-02 01:15:01,0.710229977153\r\n2011-09-02 02:15:01,0.697412833033\r\n2011-09-02 03:15:01,0.725219217625\r\n2011-09-02 04:15:01,0.60871199833\r\n2011-09-02 05:15:01,0.636974122101\r\n2011-09-02 06:15:01,0.841129477074\r\n2011-09-02 07:15:01,0.771209479568\r\n2011-09-02 08:15:01,1.02627235945\r\n2011-09-02 09:15:01,1.38391615999\r\n2011-09-02 10:15:01,1.70182048664\r\n2011-09-02 11:15:01,1.30911498665\r\n2011-09-02 12:15:01,1.44916720916\r\n2011-09-02 13:15:01,1.10994932226\r\n2011-09-02 14:15:01,1.20104749435\r\n2011-09-02 15:15:01,1.00461581227\r\n2011-09-02 16:15:01,1.24974971635\r\n2011-09-02 17:15:01,0.930537334322\r\n2011-09-02 18:15:01,0.696674235341\r\n2011-09-02 19:15:01,1.90695503664\r\n2011-09-02 20:15:01,1.14246709184\r\n2011-09-02 21:15:01,1.11277858928\r\n2011-09-02 22:15:01,0.694990722636\r\n2011-09-02 23:15:01,1.1243682849\r\n2011-09-03 00:15:01,1.63223166525\r\n2011-09-03 01:15:01,1.12621421132\r\n2011-09-03 02:15:01,1.22375614029\r\n2011-09-03 03:15:01,0.836308743265\r\n2011-09-03 04:15:01,0.764508533837\r\n2011-09-03 05:15:01,0.824846108339\r\n2011-09-03 06:15:01,0.858898956181\r\n2011-09-03 07:15:01,1.06302492473\r\n2011-09-03 08:15:01,1.40538621285\r\n2011-09-03 09:15:01,1.74459064633\r\n2011-09-03 10:15:01,2.03489870008\r\n2011-09-03 11:15:01,1.93540664402\r\n2011-09-03 12:15:01,2.27425030493\r\n2011-09-03 13:15:01,2.14033402306\r\n2011-09-03 14:15:01,1.77426028471\r\n2011-09-03 15:15:01,1.25941144301\r\n2011-09-03 16:15:01,1.02897679946\r\n2011-09-03 17:15:01,0.924615076404\r\n2011-09-03 18:15:01,0.909732905845\r\n2011-09-03 19:15:01,0.869216123697\r\n2011-09-03 20:15:01,0.541295740253\r\n2011-09-03 21:15:01,1.1777566405\r\n2011-09-03 22:15:01,1.13735222856\r\n2011-09-03 23:15:01,0.890667031052\r\n2011-09-04 00:15:01,0.610490083267\r\n2011-09-04 01:15:01,0.909803400811\r\n2011-09-04 02:15:01,0.997966281743\r\n2011-09-04 03:15:01,0.760097226529\r\n2011-09-04 04:15:01,0.695617328423\r\n2011-09-04 05:15:01,0.756014604219\r\n2011-09-04 06:15:01,0.79008464589\r\n2011-09-04 07:15:01,0.917348874571\r\n2011-09-04 08:15:01,1.13719366386\r\n2011-09-04 09:15:01,1.42018674399\r\n2011-09-04 10:15:01,1.62974773646\r\n2011-09-04 11:15:01,2.39951967225\r\n2011-09-04 12:15:01,1.90579824839\r\n2011-09-04 13:15:01,1.41094529283\r\n2011-09-04 14:15:01,1.51420659222\r\n2011-09-04 15:15:01,0.907680196378\r\n2011-09-04 16:15:01,0.949640701076\r\n2011-09-04 17:15:01,0.853479545072\r\n2011-09-04 19:15:01,0.734071967028\r\n2011-09-04 21:15:01,0.664832645575\r\n2011-09-04 22:15:01,0.751175591232\r\n2011-09-04 23:15:01,0.699932102092\r\n2011-09-05 00:15:01,0.512007082519\r\n2011-09-05 01:15:01,0.768525925193\r\n2011-09-05 02:15:01,0.720969190212\r\n2011-09-05 03:15:01,0.834640838517\r\n2011-09-05 04:15:01,0.627736806898\r\n2011-09-05 05:15:01,0.651203112053\r\n2011-09-05 06:15:01,0.830826437039\r\n2011-09-05 07:15:01,0.708797528226\r\n2011-09-05 08:15:01,0.914809516084\r\n2011-09-05 09:15:01,1.19163674636\r\n2011-09-05 10:15:01,1.64855351909\r\n2011-09-05 11:15:01,1.75118246316\r\n2011-09-05 12:15:01,2.23766160764\r\n2011-09-05 13:15:01,1.66328470303\r\n2011-09-05 15:15:01,0.832920669506\r\n2011-09-05 17:15:01,0.933893576278\r\n2011-09-05 18:15:01,0.689506085719\r\n2011-09-05 19:15:01,0.768903526829\r\n2011-09-05 20:15:01,0.698904886719\r\n2011-09-05 21:15:01,0.681318152131\r\n2011-09-05 22:15:01,0.570423466165\r\n2011-09-05 23:15:01,0.63045223235\r\n2011-09-06 01:15:01,0.614224788781\r\n2011-09-06 02:15:01,0.655868229912\r\n2011-09-06 03:15:01,0.693436352057\r\n2011-09-06 04:15:01,0.611312925873\r\n2011-09-06 05:15:01,0.807827692044\r\n2011-09-06 06:15:01,0.653708482915\r\n2011-09-06 07:15:01,0.937306761036\r\n2011-09-06 08:15:01,1.34108358121\r\n2011-09-06 09:15:01,1.47226847333\r\n2011-09-06 10:15:01,1.72638563622\r\n2011-09-06 11:15:01,1.3196855493\r\n2011-09-06 12:15:01,1.262905036\r\n2011-09-06 14:15:01,1.2017614271\r\n2011-09-06 15:15:01,1.10625236699\r\n2011-09-06 16:15:01,1.45940072715\r\n2011-09-06 17:15:01,1.09848556824\r\n2011-09-06 18:15:01,0.953394382083\r\n2011-09-06 19:15:01,0.878863784275\r\n2011-09-06 20:15:01,1.12067995176\r\n2011-09-06 21:15:01,0.991837847317\r\n2011-09-06 22:15:01,0.831665933419\r\n2011-09-06 23:15:01,0.60047251793\r\n2011-09-07 00:15:01,0.555876363857\r\n2011-09-07 01:15:01,0.823805154231\r\n2011-09-07 02:15:01,0.678606401328\r\n2011-09-07 03:15:01,0.687514096173\r\n2011-09-07 04:15:01,0.657496548202\r\n2011-09-07 05:15:01,0.75337310206\r\n2011-09-07 06:15:01,0.8787691939\r\n2011-09-07 07:15:01,1.14312883039\r\n2011-09-07 08:15:01,1.15805690626\r\n2011-09-07 09:15:01,1.63436764871\r\n2011-09-07 10:15:01,1.74975517548\r\n2011-09-07 11:15:01,2.01440045625\r\n2011-09-07 12:15:01,1.49396356503\r\n2011-09-07 13:15:01,0.908472003661\r\n2011-09-07 14:15:01,1.34644468314\r\n"
  },
  {
    "path": "workspace/anomaly_detector/datasets/selected/seasonal/nyc_taxi.csv",
    "content": "timestamp,value\n2014-07-01 00:00:00,10844\n2014-07-01 00:30:00,8127\n2014-07-01 01:00:00,6210\n2014-07-01 01:30:00,4656\n2014-07-01 02:00:00,3820\n2014-07-01 02:30:00,2873\n2014-07-01 03:00:00,2369\n2014-07-01 03:30:00,2064\n2014-07-01 04:00:00,2221\n2014-07-01 04:30:00,2158\n2014-07-01 05:00:00,2515\n2014-07-01 05:30:00,4364\n2014-07-01 06:00:00,6526\n2014-07-01 06:30:00,11039\n2014-07-01 07:00:00,13857\n2014-07-01 07:30:00,15865\n2014-07-01 08:00:00,17920\n2014-07-01 08:30:00,20346\n2014-07-01 09:00:00,19539\n2014-07-01 09:30:00,20107\n2014-07-01 10:00:00,18984\n2014-07-01 10:30:00,17720\n2014-07-01 11:00:00,17249\n2014-07-01 11:30:00,18463\n2014-07-01 12:00:00,18908\n2014-07-01 12:30:00,18886\n2014-07-01 13:00:00,18178\n2014-07-01 13:30:00,19459\n2014-07-01 14:00:00,19546\n2014-07-01 14:30:00,20591\n2014-07-01 15:00:00,19380\n2014-07-01 15:30:00,18544\n2014-07-01 16:00:00,16228\n2014-07-01 16:30:00,15013\n2014-07-01 17:00:00,17203\n2014-07-01 17:30:00,19525\n2014-07-01 18:00:00,22966\n2014-07-01 18:30:00,27598\n2014-07-01 19:00:00,26827\n2014-07-01 19:30:00,24904\n2014-07-01 20:00:00,22875\n2014-07-01 20:30:00,20394\n2014-07-01 21:00:00,23401\n2014-07-01 21:30:00,24439\n2014-07-01 22:00:00,23318\n2014-07-01 22:30:00,21733\n2014-07-01 23:00:00,20104\n2014-07-01 23:30:00,16111\n2014-07-02 00:00:00,13370\n2014-07-02 00:30:00,9945\n2014-07-02 01:00:00,7571\n2014-07-02 01:30:00,5917\n2014-07-02 02:00:00,4820\n2014-07-02 02:30:00,3634\n2014-07-02 03:00:00,2993\n2014-07-02 03:30:00,2535\n2014-07-02 04:00:00,2570\n2014-07-02 04:30:00,2485\n2014-07-02 05:00:00,2868\n2014-07-02 05:30:00,4482\n2014-07-02 06:00:00,6788\n2014-07-02 06:30:00,11078\n2014-07-02 07:00:00,13729\n2014-07-02 07:30:00,16700\n2014-07-02 08:00:00,19156\n2014-07-02 08:30:00,19953\n2014-07-02 09:00:00,19502\n2014-07-02 09:30:00,18994\n2014-07-02 10:00:00,17311\n2014-07-02 10:30:00,17904\n2014-07-02 11:00:00,17133\n2014-07-02 11:30:00,18589\n2014-07-02 12:00:00,19134\n2014-07-02 12:30:00,19259\n2014-07-02 13:00:00,18667\n2014-07-02 13:30:00,19078\n2014-07-02 14:00:00,18546\n2014-07-02 14:30:00,18593\n2014-07-02 15:00:00,17967\n2014-07-02 15:30:00,16624\n2014-07-02 16:00:00,14634\n2014-07-02 16:30:00,13888\n2014-07-02 17:00:00,17430\n2014-07-02 17:30:00,21919\n2014-07-02 18:00:00,23633\n2014-07-02 18:30:00,24512\n2014-07-02 19:00:00,24887\n2014-07-02 19:30:00,26872\n2014-07-02 20:00:00,22009\n2014-07-02 20:30:00,18259\n2014-07-02 21:00:00,20844\n2014-07-02 21:30:00,22576\n2014-07-02 22:00:00,22401\n2014-07-02 22:30:00,19056\n2014-07-02 23:00:00,17518\n2014-07-02 23:30:00,15307\n2014-07-03 00:00:00,12646\n2014-07-03 00:30:00,10562\n2014-07-03 01:00:00,8416\n2014-07-03 01:30:00,7098\n2014-07-03 02:00:00,5826\n2014-07-03 02:30:00,4383\n2014-07-03 03:00:00,3270\n2014-07-03 03:30:00,2948\n2014-07-03 04:00:00,3146\n2014-07-03 04:30:00,3077\n2014-07-03 05:00:00,3000\n2014-07-03 05:30:00,4592\n2014-07-03 06:00:00,6486\n2014-07-03 06:30:00,10113\n2014-07-03 07:00:00,12240\n2014-07-03 07:30:00,14574\n2014-07-03 08:00:00,16778\n2014-07-03 08:30:00,18910\n2014-07-03 09:00:00,18350\n2014-07-03 09:30:00,17218\n2014-07-03 10:00:00,16097\n2014-07-03 10:30:00,16409\n2014-07-03 11:00:00,15893\n2014-07-03 11:30:00,16778\n2014-07-03 12:00:00,17604\n2014-07-03 12:30:00,18665\n2014-07-03 13:00:00,19045\n2014-07-03 13:30:00,19261\n2014-07-03 14:00:00,19363\n2014-07-03 14:30:00,19078\n2014-07-03 15:00:00,18193\n2014-07-03 15:30:00,16635\n2014-07-03 16:00:00,14615\n2014-07-03 16:30:00,13759\n2014-07-03 17:00:00,17008\n2014-07-03 17:30:00,19595\n2014-07-03 18:00:00,21328\n2014-07-03 18:30:00,22661\n2014-07-03 19:00:00,29985\n2014-07-03 19:30:00,21501\n2014-07-03 20:00:00,22684\n2014-07-03 20:30:00,22188\n2014-07-03 21:00:00,22663\n2014-07-03 21:30:00,19573\n2014-07-03 22:00:00,17136\n2014-07-03 22:30:00,16606\n2014-07-03 23:00:00,16166\n2014-07-03 23:30:00,16020\n2014-07-04 00:00:00,15591\n2014-07-04 00:30:00,14395\n2014-07-04 01:00:00,12535\n2014-07-04 01:30:00,11341\n2014-07-04 02:00:00,9980\n2014-07-04 02:30:00,8404\n2014-07-04 03:00:00,7200\n2014-07-04 03:30:00,6578\n2014-07-04 04:00:00,5657\n2014-07-04 04:30:00,4474\n2014-07-04 05:00:00,3459\n2014-07-04 05:30:00,3276\n2014-07-04 06:00:00,3595\n2014-07-04 06:30:00,4240\n2014-07-04 07:00:00,4828\n2014-07-04 07:30:00,4926\n2014-07-04 08:00:00,5165\n2014-07-04 08:30:00,5776\n2014-07-04 09:00:00,7338\n2014-07-04 09:30:00,7839\n2014-07-04 10:00:00,8623\n2014-07-04 10:30:00,9731\n2014-07-04 11:00:00,11024\n2014-07-04 11:30:00,13231\n2014-07-04 12:00:00,13613\n2014-07-04 12:30:00,13737\n2014-07-04 13:00:00,15574\n2014-07-04 13:30:00,14226\n2014-07-04 14:00:00,18480\n2014-07-04 14:30:00,18265\n2014-07-04 15:00:00,16575\n2014-07-04 15:30:00,16417\n2014-07-04 16:00:00,14703\n2014-07-04 16:30:00,13469\n2014-07-04 17:00:00,12105\n2014-07-04 17:30:00,11676\n2014-07-04 18:00:00,15487\n2014-07-04 18:30:00,15077\n2014-07-04 19:00:00,14999\n2014-07-04 19:30:00,14487\n2014-07-04 20:00:00,14415\n2014-07-04 20:30:00,13796\n2014-07-04 21:00:00,14036\n2014-07-04 21:30:00,14021\n2014-07-04 22:00:00,15593\n2014-07-04 22:30:00,16589\n2014-07-04 23:00:00,17984\n2014-07-04 23:30:00,18035\n2014-07-05 00:00:00,17576\n2014-07-05 00:30:00,16189\n2014-07-05 01:00:00,14441\n2014-07-05 01:30:00,12535\n2014-07-05 02:00:00,11006\n2014-07-05 02:30:00,9151\n2014-07-05 03:00:00,8010\n2014-07-05 03:30:00,7096\n2014-07-05 04:00:00,6407\n2014-07-05 04:30:00,4421\n2014-07-05 05:00:00,3126\n2014-07-05 05:30:00,2514\n2014-07-05 06:00:00,2550\n2014-07-05 06:30:00,3148\n2014-07-05 07:00:00,3658\n2014-07-05 07:30:00,4345\n2014-07-05 08:00:00,4682\n2014-07-05 08:30:00,6248\n2014-07-05 09:00:00,7454\n2014-07-05 09:30:00,9010\n2014-07-05 10:00:00,10280\n2014-07-05 10:30:00,11488\n2014-07-05 11:00:00,11595\n2014-07-05 11:30:00,13098\n2014-07-05 12:00:00,12623\n2014-07-05 12:30:00,13031\n2014-07-05 13:00:00,13263\n2014-07-05 13:30:00,13349\n2014-07-05 14:00:00,13822\n2014-07-05 14:30:00,13716\n2014-07-05 15:00:00,13919\n2014-07-05 15:30:00,14203\n2014-07-05 16:00:00,13179\n2014-07-05 16:30:00,13708\n2014-07-05 17:00:00,13897\n2014-07-05 17:30:00,14740\n2014-07-05 18:00:00,14575\n2014-07-05 18:30:00,16085\n2014-07-05 19:00:00,18182\n2014-07-05 19:30:00,16861\n2014-07-05 20:00:00,14140\n2014-07-05 20:30:00,14477\n2014-07-05 21:00:00,15293\n2014-07-05 21:30:00,15457\n2014-07-05 22:00:00,16048\n2014-07-05 22:30:00,17477\n2014-07-05 23:00:00,16391\n2014-07-05 23:30:00,17006\n2014-07-06 00:00:00,15427\n2014-07-06 00:30:00,14615\n2014-07-06 01:00:00,13124\n2014-07-06 01:30:00,12222\n2014-07-06 02:00:00,11134\n2014-07-06 02:30:00,9145\n2014-07-06 03:00:00,8624\n2014-07-06 03:30:00,7885\n2014-07-06 04:00:00,7167\n2014-07-06 04:30:00,4805\n2014-07-06 05:00:00,3103\n2014-07-06 05:30:00,2671\n2014-07-06 06:00:00,2510\n2014-07-06 06:30:00,2917\n2014-07-06 07:00:00,3189\n2014-07-06 07:30:00,4107\n2014-07-06 08:00:00,4122\n2014-07-06 08:30:00,5654\n2014-07-06 09:00:00,6360\n2014-07-06 09:30:00,8406\n2014-07-06 10:00:00,9372\n2014-07-06 10:30:00,11067\n2014-07-06 11:00:00,11595\n2014-07-06 11:30:00,12909\n2014-07-06 12:00:00,13715\n2014-07-06 12:30:00,13648\n2014-07-06 13:00:00,14296\n2014-07-06 13:30:00,14798\n2014-07-06 14:00:00,15473\n2014-07-06 14:30:00,16032\n2014-07-06 15:00:00,14661\n2014-07-06 15:30:00,14836\n2014-07-06 16:00:00,13700\n2014-07-06 16:30:00,14565\n2014-07-06 17:00:00,15392\n2014-07-06 17:30:00,16866\n2014-07-06 18:00:00,16893\n2014-07-06 18:30:00,16877\n2014-07-06 19:00:00,17025\n2014-07-06 19:30:00,15884\n2014-07-06 20:00:00,14487\n2014-07-06 20:30:00,14159\n2014-07-06 21:00:00,16135\n2014-07-06 21:30:00,16165\n2014-07-06 22:00:00,14025\n2014-07-06 22:30:00,13970\n2014-07-06 23:00:00,13198\n2014-07-06 23:30:00,11355\n2014-07-07 00:00:00,8675\n2014-07-07 00:30:00,7180\n2014-07-07 01:00:00,5178\n2014-07-07 01:30:00,3658\n2014-07-07 02:00:00,3181\n2014-07-07 02:30:00,2402\n2014-07-07 03:00:00,1944\n2014-07-07 03:30:00,1877\n2014-07-07 04:00:00,2257\n2014-07-07 04:30:00,2280\n2014-07-07 05:00:00,2575\n2014-07-07 05:30:00,4174\n2014-07-07 06:00:00,6346\n2014-07-07 06:30:00,10594\n2014-07-07 07:00:00,12632\n2014-07-07 07:30:00,14893\n2014-07-07 08:00:00,16470\n2014-07-07 08:30:00,18998\n2014-07-07 09:00:00,17792\n2014-07-07 09:30:00,16396\n2014-07-07 10:00:00,14128\n2014-07-07 10:30:00,14161\n2014-07-07 11:00:00,14154\n2014-07-07 11:30:00,15074\n2014-07-07 12:00:00,15188\n2014-07-07 12:30:00,15483\n2014-07-07 13:00:00,15338\n2014-07-07 13:30:00,16242\n2014-07-07 14:00:00,16579\n2014-07-07 14:30:00,16885\n2014-07-07 15:00:00,16824\n2014-07-07 15:30:00,16238\n2014-07-07 16:00:00,15702\n2014-07-07 16:30:00,15132\n2014-07-07 17:00:00,17500\n2014-07-07 17:30:00,19167\n2014-07-07 18:00:00,21398\n2014-07-07 18:30:00,22382\n2014-07-07 19:00:00,22270\n2014-07-07 19:30:00,20575\n2014-07-07 20:00:00,18824\n2014-07-07 20:30:00,17909\n2014-07-07 21:00:00,19707\n2014-07-07 21:30:00,19066\n2014-07-07 22:00:00,17755\n2014-07-07 22:30:00,16583\n2014-07-07 23:00:00,14955\n2014-07-07 23:30:00,11849\n2014-07-08 00:00:00,9292\n2014-07-08 00:30:00,8110\n2014-07-08 01:00:00,7352\n2014-07-08 01:30:00,5049\n2014-07-08 02:00:00,3451\n2014-07-08 02:30:00,2465\n2014-07-08 03:00:00,2125\n2014-07-08 03:30:00,1877\n2014-07-08 04:00:00,2069\n2014-07-08 04:30:00,2080\n2014-07-08 05:00:00,2375\n2014-07-08 05:30:00,4303\n2014-07-08 06:00:00,6537\n2014-07-08 06:30:00,11331\n2014-07-08 07:00:00,13565\n2014-07-08 07:30:00,16455\n2014-07-08 08:00:00,18310\n2014-07-08 08:30:00,20288\n2014-07-08 09:00:00,19564\n2014-07-08 09:30:00,19380\n2014-07-08 10:00:00,16507\n2014-07-08 10:30:00,16939\n2014-07-08 11:00:00,16113\n2014-07-08 11:30:00,17537\n2014-07-08 12:00:00,18120\n2014-07-08 12:30:00,18038\n2014-07-08 13:00:00,17870\n2014-07-08 13:30:00,18427\n2014-07-08 14:00:00,18971\n2014-07-08 14:30:00,19071\n2014-07-08 15:00:00,18646\n2014-07-08 15:30:00,18229\n2014-07-08 16:00:00,15977\n2014-07-08 16:30:00,15026\n2014-07-08 17:00:00,17398\n2014-07-08 17:30:00,20865\n2014-07-08 18:00:00,23875\n2014-07-08 18:30:00,25290\n2014-07-08 19:00:00,25510\n2014-07-08 19:30:00,24535\n2014-07-08 20:00:00,21922\n2014-07-08 20:30:00,20113\n2014-07-08 21:00:00,22079\n2014-07-08 21:30:00,23111\n2014-07-08 22:00:00,25209\n2014-07-08 22:30:00,21978\n2014-07-08 23:00:00,18320\n2014-07-08 23:30:00,14881\n2014-07-09 00:00:00,12053\n2014-07-09 00:30:00,9409\n2014-07-09 01:00:00,7740\n2014-07-09 01:30:00,5528\n2014-07-09 02:00:00,4667\n2014-07-09 02:30:00,3242\n2014-07-09 03:00:00,2678\n2014-07-09 03:30:00,2370\n2014-07-09 04:00:00,2475\n2014-07-09 04:30:00,2304\n2014-07-09 05:00:00,2491\n2014-07-09 05:30:00,4117\n2014-07-09 06:00:00,6435\n2014-07-09 06:30:00,11067\n2014-07-09 07:00:00,13384\n2014-07-09 07:30:00,17194\n2014-07-09 08:00:00,18510\n2014-07-09 08:30:00,20464\n2014-07-09 09:00:00,19777\n2014-07-09 09:30:00,18928\n2014-07-09 10:00:00,17243\n2014-07-09 10:30:00,17490\n2014-07-09 11:00:00,16558\n2014-07-09 11:30:00,17830\n2014-07-09 12:00:00,18203\n2014-07-09 12:30:00,18126\n2014-07-09 13:00:00,18122\n2014-07-09 13:30:00,18488\n2014-07-09 14:00:00,18487\n2014-07-09 14:30:00,18542\n2014-07-09 15:00:00,18240\n2014-07-09 15:30:00,17393\n2014-07-09 16:00:00,15175\n2014-07-09 16:30:00,15360\n2014-07-09 17:00:00,17103\n2014-07-09 17:30:00,19561\n2014-07-09 18:00:00,22262\n2014-07-09 18:30:00,24725\n2014-07-09 19:00:00,25995\n2014-07-09 19:30:00,26319\n2014-07-09 20:00:00,24995\n2014-07-09 20:30:00,20534\n2014-07-09 21:00:00,23458\n2014-07-09 21:30:00,24681\n2014-07-09 22:00:00,23955\n2014-07-09 22:30:00,23655\n2014-07-09 23:00:00,21896\n2014-07-09 23:30:00,19338\n2014-07-10 00:00:00,15185\n2014-07-10 00:30:00,11459\n2014-07-10 01:00:00,8847\n2014-07-10 01:30:00,6580\n2014-07-10 02:00:00,5247\n2014-07-10 02:30:00,4127\n2014-07-10 03:00:00,3440\n2014-07-10 03:30:00,2957\n2014-07-10 04:00:00,2779\n2014-07-10 04:30:00,2532\n2014-07-10 05:00:00,2718\n2014-07-10 05:30:00,4449\n2014-07-10 06:00:00,6601\n2014-07-10 06:30:00,11202\n2014-07-10 07:00:00,13934\n2014-07-10 07:30:00,17176\n2014-07-10 08:00:00,19057\n2014-07-10 08:30:00,21112\n2014-07-10 09:00:00,19882\n2014-07-10 09:30:00,19024\n2014-07-10 10:00:00,16989\n2014-07-10 10:30:00,16979\n2014-07-10 11:00:00,16381\n2014-07-10 11:30:00,17815\n2014-07-10 12:00:00,18029\n2014-07-10 12:30:00,17495\n2014-07-10 13:00:00,17075\n2014-07-10 13:30:00,18234\n2014-07-10 14:00:00,18091\n2014-07-10 14:30:00,18495\n2014-07-10 15:00:00,17523\n2014-07-10 15:30:00,16714\n2014-07-10 16:00:00,14735\n2014-07-10 16:30:00,13610\n2014-07-10 17:00:00,16290\n2014-07-10 17:30:00,19152\n2014-07-10 18:00:00,21865\n2014-07-10 18:30:00,24347\n2014-07-10 19:00:00,26186\n2014-07-10 19:30:00,25852\n2014-07-10 20:00:00,23995\n2014-07-10 20:30:00,21664\n2014-07-10 21:00:00,25027\n2014-07-10 21:30:00,25431\n2014-07-10 22:00:00,25643\n2014-07-10 22:30:00,24654\n2014-07-10 23:00:00,23154\n2014-07-10 23:30:00,21863\n2014-07-11 00:00:00,20051\n2014-07-11 00:30:00,16122\n2014-07-11 01:00:00,13107\n2014-07-11 01:30:00,10506\n2014-07-11 02:00:00,8444\n2014-07-11 02:30:00,6876\n2014-07-11 03:00:00,5375\n2014-07-11 03:30:00,4366\n2014-07-11 04:00:00,4183\n2014-07-11 04:30:00,3249\n2014-07-11 05:00:00,3134\n2014-07-11 05:30:00,4620\n2014-07-11 06:00:00,6725\n2014-07-11 06:30:00,10651\n2014-07-11 07:00:00,12952\n2014-07-11 07:30:00,15808\n2014-07-11 08:00:00,17565\n2014-07-11 08:30:00,19784\n2014-07-11 09:00:00,19699\n2014-07-11 09:30:00,18663\n2014-07-11 10:00:00,16509\n2014-07-11 10:30:00,16600\n2014-07-11 11:00:00,15636\n2014-07-11 11:30:00,17434\n2014-07-11 12:00:00,17668\n2014-07-11 12:30:00,17124\n2014-07-11 13:00:00,17124\n2014-07-11 13:30:00,17489\n2014-07-11 14:00:00,18371\n2014-07-11 14:30:00,18381\n2014-07-11 15:00:00,17898\n2014-07-11 15:30:00,16350\n2014-07-11 16:00:00,14688\n2014-07-11 16:30:00,14227\n2014-07-11 17:00:00,16924\n2014-07-11 17:30:00,19952\n2014-07-11 18:00:00,22665\n2014-07-11 18:30:00,23465\n2014-07-11 19:00:00,25111\n2014-07-11 19:30:00,23984\n2014-07-11 20:00:00,21701\n2014-07-11 20:30:00,20592\n2014-07-11 21:00:00,22630\n2014-07-11 21:30:00,22854\n2014-07-11 22:00:00,23892\n2014-07-11 22:30:00,24959\n2014-07-11 23:00:00,26039\n2014-07-11 23:30:00,26873\n2014-07-12 00:00:00,25871\n2014-07-12 00:30:00,24874\n2014-07-12 01:00:00,23243\n2014-07-12 01:30:00,21674\n2014-07-12 02:00:00,19221\n2014-07-12 02:30:00,16140\n2014-07-12 03:00:00,13371\n2014-07-12 03:30:00,12041\n2014-07-12 04:00:00,10301\n2014-07-12 04:30:00,6472\n2014-07-12 05:00:00,4507\n2014-07-12 05:30:00,3682\n2014-07-12 06:00:00,3422\n2014-07-12 06:30:00,4554\n2014-07-12 07:00:00,5347\n2014-07-12 07:30:00,6853\n2014-07-12 08:00:00,7107\n2014-07-12 08:30:00,9463\n2014-07-12 09:00:00,11022\n2014-07-12 09:30:00,13393\n2014-07-12 10:00:00,13567\n2014-07-12 10:30:00,15452\n2014-07-12 11:00:00,15525\n2014-07-12 11:30:00,17165\n2014-07-12 12:00:00,17263\n2014-07-12 12:30:00,18418\n2014-07-12 13:00:00,18578\n2014-07-12 13:30:00,18762\n2014-07-12 14:00:00,18076\n2014-07-12 14:30:00,18604\n2014-07-12 15:00:00,18580\n2014-07-12 15:30:00,19306\n2014-07-12 16:00:00,18140\n2014-07-12 16:30:00,17455\n2014-07-12 17:00:00,18980\n2014-07-12 17:30:00,21152\n2014-07-12 18:00:00,22483\n2014-07-12 18:30:00,22534\n2014-07-12 19:00:00,22801\n2014-07-12 19:30:00,22117\n2014-07-12 20:00:00,19864\n2014-07-12 20:30:00,19494\n2014-07-12 21:00:00,20607\n2014-07-12 21:30:00,20627\n2014-07-12 22:00:00,21706\n2014-07-12 22:30:00,24243\n2014-07-12 23:00:00,25204\n2014-07-12 23:30:00,25752\n2014-07-13 00:00:00,25792\n2014-07-13 00:30:00,25033\n2014-07-13 01:00:00,23935\n2014-07-13 01:30:00,21440\n2014-07-13 02:00:00,19468\n2014-07-13 02:30:00,16622\n2014-07-13 03:00:00,14485\n2014-07-13 03:30:00,12974\n2014-07-13 04:00:00,11191\n2014-07-13 04:30:00,6911\n2014-07-13 05:00:00,4410\n2014-07-13 05:30:00,3467\n2014-07-13 06:00:00,3429\n2014-07-13 06:30:00,3599\n2014-07-13 07:00:00,3575\n2014-07-13 07:30:00,4557\n2014-07-13 08:00:00,5243\n2014-07-13 08:30:00,6588\n2014-07-13 09:00:00,8009\n2014-07-13 09:30:00,10743\n2014-07-13 10:00:00,13524\n2014-07-13 10:30:00,16179\n2014-07-13 11:00:00,14905\n2014-07-13 11:30:00,16916\n2014-07-13 12:00:00,17082\n2014-07-13 12:30:00,18606\n2014-07-13 13:00:00,18935\n2014-07-13 13:30:00,20175\n2014-07-13 14:00:00,22219\n2014-07-13 14:30:00,22868\n2014-07-13 15:00:00,20375\n2014-07-13 15:30:00,18489\n2014-07-13 16:00:00,16187\n2014-07-13 16:30:00,14015\n2014-07-13 17:00:00,14261\n2014-07-13 17:30:00,20081\n2014-07-13 18:00:00,21503\n2014-07-13 18:30:00,19850\n2014-07-13 19:00:00,18383\n2014-07-13 19:30:00,17640\n2014-07-13 20:00:00,16225\n2014-07-13 20:30:00,15566\n2014-07-13 21:00:00,17088\n2014-07-13 21:30:00,16968\n2014-07-13 22:00:00,15271\n2014-07-13 22:30:00,14141\n2014-07-13 23:00:00,12851\n2014-07-13 23:30:00,13877\n2014-07-14 00:00:00,12484\n2014-07-14 00:30:00,9037\n2014-07-14 01:00:00,7393\n2014-07-14 01:30:00,5176\n2014-07-14 02:00:00,3479\n2014-07-14 02:30:00,2755\n2014-07-14 03:00:00,2027\n2014-07-14 03:30:00,1769\n2014-07-14 04:00:00,2091\n2014-07-14 04:30:00,2553\n2014-07-14 05:00:00,2853\n2014-07-14 05:30:00,4835\n2014-07-14 06:00:00,6603\n2014-07-14 06:30:00,11230\n2014-07-14 07:00:00,13395\n2014-07-14 07:30:00,15650\n2014-07-14 08:00:00,17601\n2014-07-14 08:30:00,18818\n2014-07-14 09:00:00,18515\n2014-07-14 09:30:00,16972\n2014-07-14 10:00:00,15316\n2014-07-14 10:30:00,16003\n2014-07-14 11:00:00,14818\n2014-07-14 11:30:00,15610\n2014-07-14 12:00:00,16536\n2014-07-14 12:30:00,16153\n2014-07-14 13:00:00,15548\n2014-07-14 13:30:00,16500\n2014-07-14 14:00:00,16726\n2014-07-14 14:30:00,16838\n2014-07-14 15:00:00,16550\n2014-07-14 15:30:00,16621\n2014-07-14 16:00:00,15657\n2014-07-14 16:30:00,15334\n2014-07-14 17:00:00,17584\n2014-07-14 17:30:00,20903\n2014-07-14 18:00:00,21968\n2014-07-14 18:30:00,26945\n2014-07-14 19:00:00,24416\n2014-07-14 19:30:00,22401\n2014-07-14 20:00:00,23549\n2014-07-14 20:30:00,21498\n2014-07-14 21:00:00,23114\n2014-07-14 21:30:00,23341\n2014-07-14 22:00:00,22141\n2014-07-14 22:30:00,19110\n2014-07-14 23:00:00,16682\n2014-07-14 23:30:00,12631\n2014-07-15 00:00:00,10089\n2014-07-15 00:30:00,8553\n2014-07-15 01:00:00,6416\n2014-07-15 01:30:00,4694\n2014-07-15 02:00:00,3933\n2014-07-15 02:30:00,2833\n2014-07-15 03:00:00,2089\n2014-07-15 03:30:00,1896\n2014-07-15 04:00:00,2055\n2014-07-15 04:30:00,2031\n2014-07-15 05:00:00,2449\n2014-07-15 05:30:00,4360\n2014-07-15 06:00:00,7036\n2014-07-15 06:30:00,11730\n2014-07-15 07:00:00,14387\n2014-07-15 07:30:00,17505\n2014-07-15 08:00:00,19091\n2014-07-15 08:30:00,21057\n2014-07-15 09:00:00,20050\n2014-07-15 09:30:00,18637\n2014-07-15 10:00:00,17555\n2014-07-15 10:30:00,17595\n2014-07-15 11:00:00,16312\n2014-07-15 11:30:00,18232\n2014-07-15 12:00:00,18446\n2014-07-15 12:30:00,18204\n2014-07-15 13:00:00,17607\n2014-07-15 13:30:00,18945\n2014-07-15 14:00:00,22208\n2014-07-15 14:30:00,21574\n2014-07-15 15:00:00,17299\n2014-07-15 15:30:00,15515\n2014-07-15 16:00:00,13246\n2014-07-15 16:30:00,12328\n2014-07-15 17:00:00,15342\n2014-07-15 17:30:00,18730\n2014-07-15 18:00:00,23412\n2014-07-15 18:30:00,26340\n2014-07-15 19:00:00,27167\n2014-07-15 19:30:00,26279\n2014-07-15 20:00:00,23392\n2014-07-15 20:30:00,21571\n2014-07-15 21:00:00,23477\n2014-07-15 21:30:00,22612\n2014-07-15 22:00:00,21389\n2014-07-15 22:30:00,19575\n2014-07-15 23:00:00,18165\n2014-07-15 23:30:00,14923\n2014-07-16 00:00:00,11815\n2014-07-16 00:30:00,9024\n2014-07-16 01:00:00,7363\n2014-07-16 01:30:00,5812\n2014-07-16 02:00:00,4559\n2014-07-16 02:30:00,3673\n2014-07-16 03:00:00,2830\n2014-07-16 03:30:00,2374\n2014-07-16 04:00:00,2556\n2014-07-16 04:30:00,2456\n2014-07-16 05:00:00,2486\n2014-07-16 05:30:00,4451\n2014-07-16 06:00:00,6723\n2014-07-16 06:30:00,12501\n2014-07-16 07:00:00,14763\n2014-07-16 07:30:00,18127\n2014-07-16 08:00:00,20393\n2014-07-16 08:30:00,20753\n2014-07-16 09:00:00,20124\n2014-07-16 09:30:00,19253\n2014-07-16 10:00:00,17981\n2014-07-16 10:30:00,17720\n2014-07-16 11:00:00,16525\n2014-07-16 11:30:00,18153\n2014-07-16 12:00:00,18558\n2014-07-16 12:30:00,17652\n2014-07-16 13:00:00,17292\n2014-07-16 13:30:00,17551\n2014-07-16 14:00:00,17951\n2014-07-16 14:30:00,17909\n2014-07-16 15:00:00,17442\n2014-07-16 15:30:00,16533\n2014-07-16 16:00:00,14776\n2014-07-16 16:30:00,13462\n2014-07-16 17:00:00,16363\n2014-07-16 17:30:00,19310\n2014-07-16 18:00:00,22346\n2014-07-16 18:30:00,24408\n2014-07-16 19:00:00,26225\n2014-07-16 19:30:00,25423\n2014-07-16 20:00:00,23811\n2014-07-16 20:30:00,22028\n2014-07-16 21:00:00,24290\n2014-07-16 21:30:00,24835\n2014-07-16 22:00:00,24269\n2014-07-16 22:30:00,23526\n2014-07-16 23:00:00,21968\n2014-07-16 23:30:00,20137\n2014-07-17 00:00:00,16928\n2014-07-17 00:30:00,12753\n2014-07-17 01:00:00,10087\n2014-07-17 01:30:00,7881\n2014-07-17 02:00:00,6006\n2014-07-17 02:30:00,4382\n2014-07-17 03:00:00,3676\n2014-07-17 03:30:00,3214\n2014-07-17 04:00:00,3205\n2014-07-17 04:30:00,2849\n2014-07-17 05:00:00,2887\n2014-07-17 05:30:00,5039\n2014-07-17 06:00:00,7132\n2014-07-17 06:30:00,12095\n2014-07-17 07:00:00,14558\n2014-07-17 07:30:00,17298\n2014-07-17 08:00:00,19124\n2014-07-17 08:30:00,20407\n2014-07-17 09:00:00,19379\n2014-07-17 09:30:00,18867\n2014-07-17 10:00:00,17662\n2014-07-17 10:30:00,17447\n2014-07-17 11:00:00,16579\n2014-07-17 11:30:00,18340\n2014-07-17 12:00:00,18760\n2014-07-17 12:30:00,18457\n2014-07-17 13:00:00,17608\n2014-07-17 13:30:00,18913\n2014-07-17 14:00:00,19122\n2014-07-17 14:30:00,19547\n2014-07-17 15:00:00,17267\n2014-07-17 15:30:00,15916\n2014-07-17 16:00:00,13836\n2014-07-17 16:30:00,11985\n2014-07-17 17:00:00,14313\n2014-07-17 17:30:00,17988\n2014-07-17 18:00:00,21181\n2014-07-17 18:30:00,23539\n2014-07-17 19:00:00,24714\n2014-07-17 19:30:00,25079\n2014-07-17 20:00:00,23032\n2014-07-17 20:30:00,21168\n2014-07-17 21:00:00,25514\n2014-07-17 21:30:00,26286\n2014-07-17 22:00:00,25650\n2014-07-17 22:30:00,24850\n2014-07-17 23:00:00,23869\n2014-07-17 23:30:00,22913\n2014-07-18 00:00:00,20850\n2014-07-18 00:30:00,16734\n2014-07-18 01:00:00,14106\n2014-07-18 01:30:00,11587\n2014-07-18 02:00:00,8951\n2014-07-18 02:30:00,7199\n2014-07-18 03:00:00,6051\n2014-07-18 03:30:00,4693\n2014-07-18 04:00:00,4507\n2014-07-18 04:30:00,3791\n2014-07-18 05:00:00,3586\n2014-07-18 05:30:00,4918\n2014-07-18 06:00:00,7039\n2014-07-18 06:30:00,11262\n2014-07-18 07:00:00,13725\n2014-07-18 07:30:00,15899\n2014-07-18 08:00:00,17329\n2014-07-18 08:30:00,19757\n2014-07-18 09:00:00,19341\n2014-07-18 09:30:00,17660\n2014-07-18 10:00:00,16532\n2014-07-18 10:30:00,16354\n2014-07-18 11:00:00,16054\n2014-07-18 11:30:00,17326\n2014-07-18 12:00:00,17463\n2014-07-18 12:30:00,17091\n2014-07-18 13:00:00,16668\n2014-07-18 13:30:00,17096\n2014-07-18 14:00:00,17811\n2014-07-18 14:30:00,17980\n2014-07-18 15:00:00,17080\n2014-07-18 15:30:00,15185\n2014-07-18 16:00:00,13538\n2014-07-18 16:30:00,12704\n2014-07-18 17:00:00,15019\n2014-07-18 17:30:00,18778\n2014-07-18 18:00:00,21583\n2014-07-18 18:30:00,23834\n2014-07-18 19:00:00,25123\n2014-07-18 19:30:00,24762\n2014-07-18 20:00:00,22761\n2014-07-18 20:30:00,22227\n2014-07-18 21:00:00,23985\n2014-07-18 21:30:00,23788\n2014-07-18 22:00:00,23855\n2014-07-18 22:30:00,26040\n2014-07-18 23:00:00,25863\n2014-07-18 23:30:00,25851\n2014-07-19 00:00:00,26100\n2014-07-19 00:30:00,24625\n2014-07-19 01:00:00,22657\n2014-07-19 01:30:00,20289\n2014-07-19 02:00:00,18524\n2014-07-19 02:30:00,15943\n2014-07-19 03:00:00,13179\n2014-07-19 03:30:00,12423\n2014-07-19 04:00:00,10478\n2014-07-19 04:30:00,6556\n2014-07-19 05:00:00,4561\n2014-07-19 05:30:00,3513\n2014-07-19 06:00:00,3607\n2014-07-19 06:30:00,4781\n2014-07-19 07:00:00,5423\n2014-07-19 07:30:00,6669\n2014-07-19 08:00:00,7064\n2014-07-19 08:30:00,9363\n2014-07-19 09:00:00,10874\n2014-07-19 09:30:00,13255\n2014-07-19 10:00:00,13164\n2014-07-19 10:30:00,15159\n2014-07-19 11:00:00,16030\n2014-07-19 11:30:00,18256\n2014-07-19 12:00:00,17751\n2014-07-19 12:30:00,17675\n2014-07-19 13:00:00,18557\n2014-07-19 13:30:00,18389\n2014-07-19 14:00:00,17538\n2014-07-19 14:30:00,17506\n2014-07-19 15:00:00,17580\n2014-07-19 15:30:00,18027\n2014-07-19 16:00:00,16959\n2014-07-19 16:30:00,17066\n2014-07-19 17:00:00,18155\n2014-07-19 17:30:00,20610\n2014-07-19 18:00:00,20793\n2014-07-19 18:30:00,21584\n2014-07-19 19:00:00,23493\n2014-07-19 19:30:00,22555\n2014-07-19 20:00:00,20183\n2014-07-19 20:30:00,20441\n2014-07-19 21:00:00,21555\n2014-07-19 21:30:00,22406\n2014-07-19 22:00:00,22512\n2014-07-19 22:30:00,24667\n2014-07-19 23:00:00,25424\n2014-07-19 23:30:00,25852\n2014-07-20 00:00:00,25137\n2014-07-20 00:30:00,24099\n2014-07-20 01:00:00,23058\n2014-07-20 01:30:00,20786\n2014-07-20 02:00:00,19217\n2014-07-20 02:30:00,16329\n2014-07-20 03:00:00,14293\n2014-07-20 03:30:00,13193\n2014-07-20 04:00:00,11166\n2014-07-20 04:30:00,7518\n2014-07-20 05:00:00,4877\n2014-07-20 05:30:00,3639\n2014-07-20 06:00:00,3412\n2014-07-20 06:30:00,3827\n2014-07-20 07:00:00,3922\n2014-07-20 07:30:00,5241\n2014-07-20 08:00:00,5601\n2014-07-20 08:30:00,7147\n2014-07-20 09:00:00,8425\n2014-07-20 09:30:00,10951\n2014-07-20 10:00:00,11800\n2014-07-20 10:30:00,13936\n2014-07-20 11:00:00,14835\n2014-07-20 11:30:00,16412\n2014-07-20 12:00:00,16763\n2014-07-20 12:30:00,17613\n2014-07-20 13:00:00,17439\n2014-07-20 13:30:00,17921\n2014-07-20 14:00:00,18605\n2014-07-20 14:30:00,18113\n2014-07-20 15:00:00,17579\n2014-07-20 15:30:00,16927\n2014-07-20 16:00:00,16526\n2014-07-20 16:30:00,16956\n2014-07-20 17:00:00,17381\n2014-07-20 17:30:00,19232\n2014-07-20 18:00:00,19127\n2014-07-20 18:30:00,19404\n2014-07-20 19:00:00,18812\n2014-07-20 19:30:00,18253\n2014-07-20 20:00:00,16497\n2014-07-20 20:30:00,16681\n2014-07-20 21:00:00,17334\n2014-07-20 21:30:00,17674\n2014-07-20 22:00:00,16469\n2014-07-20 22:30:00,15128\n2014-07-20 23:00:00,13973\n2014-07-20 23:30:00,12040\n2014-07-21 00:00:00,9494\n2014-07-21 00:30:00,6963\n2014-07-21 01:00:00,5611\n2014-07-21 01:30:00,4140\n2014-07-21 02:00:00,3370\n2014-07-21 02:30:00,2625\n2014-07-21 03:00:00,2093\n2014-07-21 03:30:00,1854\n2014-07-21 04:00:00,2482\n2014-07-21 04:30:00,2529\n2014-07-21 05:00:00,2968\n2014-07-21 05:30:00,4540\n2014-07-21 06:00:00,6868\n2014-07-21 06:30:00,10765\n2014-07-21 07:00:00,13095\n2014-07-21 07:30:00,15651\n2014-07-21 08:00:00,17427\n2014-07-21 08:30:00,18637\n2014-07-21 09:00:00,18614\n2014-07-21 09:30:00,17187\n2014-07-21 10:00:00,15281\n2014-07-21 10:30:00,15505\n2014-07-21 11:00:00,15168\n2014-07-21 11:30:00,15813\n2014-07-21 12:00:00,15979\n2014-07-21 12:30:00,16314\n2014-07-21 13:00:00,16002\n2014-07-21 13:30:00,16845\n2014-07-21 14:00:00,17009\n2014-07-21 14:30:00,17302\n2014-07-21 15:00:00,16649\n2014-07-21 15:30:00,16857\n2014-07-21 16:00:00,15733\n2014-07-21 16:30:00,15537\n2014-07-21 17:00:00,17362\n2014-07-21 17:30:00,19639\n2014-07-21 18:00:00,22891\n2014-07-21 18:30:00,22920\n2014-07-21 19:00:00,22941\n2014-07-21 19:30:00,21849\n2014-07-21 20:00:00,20483\n2014-07-21 20:30:00,18868\n2014-07-21 21:00:00,20235\n2014-07-21 21:30:00,20658\n2014-07-21 22:00:00,20751\n2014-07-21 22:30:00,18642\n2014-07-21 23:00:00,16106\n2014-07-21 23:30:00,13303\n2014-07-22 00:00:00,10611\n2014-07-22 00:30:00,8009\n2014-07-22 01:00:00,6210\n2014-07-22 01:30:00,4830\n2014-07-22 02:00:00,3753\n2014-07-22 02:30:00,2962\n2014-07-22 03:00:00,2379\n2014-07-22 03:30:00,2114\n2014-07-22 04:00:00,2232\n2014-07-22 04:30:00,2090\n2014-07-22 05:00:00,2532\n2014-07-22 05:30:00,4492\n2014-07-22 06:00:00,6830\n2014-07-22 06:30:00,11269\n2014-07-22 07:00:00,13635\n2014-07-22 07:30:00,16356\n2014-07-22 08:00:00,18449\n2014-07-22 08:30:00,20054\n2014-07-22 09:00:00,19462\n2014-07-22 09:30:00,19016\n2014-07-22 10:00:00,17349\n2014-07-22 10:30:00,17684\n2014-07-22 11:00:00,17412\n2014-07-22 11:30:00,17854\n2014-07-22 12:00:00,18649\n2014-07-22 12:30:00,19970\n2014-07-22 13:00:00,19168\n2014-07-22 13:30:00,19270\n2014-07-22 14:00:00,19463\n2014-07-22 14:30:00,18999\n2014-07-22 15:00:00,17998\n2014-07-22 15:30:00,17209\n2014-07-22 16:00:00,15581\n2014-07-22 16:30:00,14846\n2014-07-22 17:00:00,17832\n2014-07-22 17:30:00,21545\n2014-07-22 18:00:00,24769\n2014-07-22 18:30:00,25573\n2014-07-22 19:00:00,26243\n2014-07-22 19:30:00,25057\n2014-07-22 20:00:00,23381\n2014-07-22 20:30:00,22148\n2014-07-22 21:00:00,24590\n2014-07-22 21:30:00,24168\n2014-07-22 22:00:00,23364\n2014-07-22 22:30:00,23272\n2014-07-22 23:00:00,19939\n2014-07-22 23:30:00,17316\n2014-07-23 00:00:00,13369\n2014-07-23 00:30:00,10390\n2014-07-23 01:00:00,7994\n2014-07-23 01:30:00,5889\n2014-07-23 02:00:00,4711\n2014-07-23 02:30:00,3757\n2014-07-23 03:00:00,3066\n2014-07-23 03:30:00,2647\n2014-07-23 04:00:00,2645\n2014-07-23 04:30:00,2411\n2014-07-23 05:00:00,2600\n2014-07-23 05:30:00,4483\n2014-07-23 06:00:00,6956\n2014-07-23 06:30:00,11788\n2014-07-23 07:00:00,14098\n2014-07-23 07:30:00,17141\n2014-07-23 08:00:00,19124\n2014-07-23 08:30:00,20604\n2014-07-23 09:00:00,20114\n2014-07-23 09:30:00,19641\n2014-07-23 10:00:00,18423\n2014-07-23 10:30:00,18480\n2014-07-23 11:00:00,18318\n2014-07-23 11:30:00,19378\n2014-07-23 12:00:00,19585\n2014-07-23 12:30:00,19614\n2014-07-23 13:00:00,19295\n2014-07-23 13:30:00,19850\n2014-07-23 14:00:00,20120\n2014-07-23 14:30:00,19621\n2014-07-23 15:00:00,18809\n2014-07-23 15:30:00,17731\n2014-07-23 16:00:00,15483\n2014-07-23 16:30:00,15112\n2014-07-23 17:00:00,18183\n2014-07-23 17:30:00,21187\n2014-07-23 18:00:00,24034\n2014-07-23 18:30:00,25411\n2014-07-23 19:00:00,26528\n2014-07-23 19:30:00,26022\n2014-07-23 20:00:00,23253\n2014-07-23 20:30:00,25665\n2014-07-23 21:00:00,26600\n2014-07-23 21:30:00,24757\n2014-07-23 22:00:00,24337\n2014-07-23 22:30:00,24294\n2014-07-23 23:00:00,22087\n2014-07-23 23:30:00,19064\n2014-07-24 00:00:00,15542\n2014-07-24 00:30:00,12026\n2014-07-24 01:00:00,8678\n2014-07-24 01:30:00,7042\n2014-07-24 02:00:00,5355\n2014-07-24 02:30:00,4129\n2014-07-24 03:00:00,3109\n2014-07-24 03:30:00,2534\n2014-07-24 04:00:00,2788\n2014-07-24 04:30:00,2507\n2014-07-24 05:00:00,2671\n2014-07-24 05:30:00,4445\n2014-07-24 06:00:00,7163\n2014-07-24 06:30:00,11942\n2014-07-24 07:00:00,14544\n2014-07-24 07:30:00,17435\n2014-07-24 08:00:00,19254\n2014-07-24 08:30:00,20518\n2014-07-24 09:00:00,20003\n2014-07-24 09:30:00,19642\n2014-07-24 10:00:00,17626\n2014-07-24 10:30:00,18194\n2014-07-24 11:00:00,16975\n2014-07-24 11:30:00,18125\n2014-07-24 12:00:00,18555\n2014-07-24 12:30:00,18356\n2014-07-24 13:00:00,17683\n2014-07-24 13:30:00,18298\n2014-07-24 14:00:00,18613\n2014-07-24 14:30:00,18548\n2014-07-24 15:00:00,17742\n2014-07-24 15:30:00,16312\n2014-07-24 16:00:00,14782\n2014-07-24 16:30:00,13614\n2014-07-24 17:00:00,16220\n2014-07-24 17:30:00,18901\n2014-07-24 18:00:00,21794\n2014-07-24 18:30:00,23933\n2014-07-24 19:00:00,25474\n2014-07-24 19:30:00,24985\n2014-07-24 20:00:00,22877\n2014-07-24 20:30:00,22518\n2014-07-24 21:00:00,25246\n2014-07-24 21:30:00,25871\n2014-07-24 22:00:00,25324\n2014-07-24 22:30:00,25738\n2014-07-24 23:00:00,24763\n2014-07-24 23:30:00,23158\n2014-07-25 00:00:00,20525\n2014-07-25 00:30:00,17608\n2014-07-25 01:00:00,14436\n2014-07-25 01:30:00,11145\n2014-07-25 02:00:00,8915\n2014-07-25 02:30:00,7244\n2014-07-25 03:00:00,5856\n2014-07-25 03:30:00,4953\n2014-07-25 04:00:00,4546\n2014-07-25 04:30:00,3589\n2014-07-25 05:00:00,3516\n2014-07-25 05:30:00,5087\n2014-07-25 06:00:00,7102\n2014-07-25 06:30:00,10887\n2014-07-25 07:00:00,12988\n2014-07-25 07:30:00,15831\n2014-07-25 08:00:00,17326\n2014-07-25 08:30:00,19179\n2014-07-25 09:00:00,18805\n2014-07-25 09:30:00,17730\n2014-07-25 10:00:00,16439\n2014-07-25 10:30:00,16401\n2014-07-25 11:00:00,16240\n2014-07-25 11:30:00,17487\n2014-07-25 12:00:00,17622\n2014-07-25 12:30:00,17313\n2014-07-25 13:00:00,16647\n2014-07-25 13:30:00,16627\n2014-07-25 14:00:00,17646\n2014-07-25 14:30:00,17694\n2014-07-25 15:00:00,17661\n2014-07-25 15:30:00,15842\n2014-07-25 16:00:00,14950\n2014-07-25 16:30:00,13473\n2014-07-25 17:00:00,16633\n2014-07-25 17:30:00,19501\n2014-07-25 18:00:00,22009\n2014-07-25 18:30:00,23891\n2014-07-25 19:00:00,25196\n2014-07-25 19:30:00,24427\n2014-07-25 20:00:00,22357\n2014-07-25 20:30:00,22460\n2014-07-25 21:00:00,24066\n2014-07-25 21:30:00,23690\n2014-07-25 22:00:00,24491\n2014-07-25 22:30:00,25737\n2014-07-25 23:00:00,26688\n2014-07-25 23:30:00,26230\n2014-07-26 00:00:00,26300\n2014-07-26 00:30:00,24337\n2014-07-26 01:00:00,23124\n2014-07-26 01:30:00,20675\n2014-07-26 02:00:00,18663\n2014-07-26 02:30:00,15997\n2014-07-26 03:00:00,13405\n2014-07-26 03:30:00,11921\n2014-07-26 04:00:00,10203\n2014-07-26 04:30:00,6543\n2014-07-26 05:00:00,4719\n2014-07-26 05:30:00,3853\n2014-07-26 06:00:00,4116\n2014-07-26 06:30:00,5274\n2014-07-26 07:00:00,5331\n2014-07-26 07:30:00,6830\n2014-07-26 08:00:00,7303\n2014-07-26 08:30:00,9704\n2014-07-26 09:00:00,11209\n2014-07-26 09:30:00,13874\n2014-07-26 10:00:00,14548\n2014-07-26 10:30:00,16204\n2014-07-26 11:00:00,16938\n2014-07-26 11:30:00,18696\n2014-07-26 12:00:00,17585\n2014-07-26 12:30:00,18538\n2014-07-26 13:00:00,18206\n2014-07-26 13:30:00,17532\n2014-07-26 14:00:00,17657\n2014-07-26 14:30:00,17943\n2014-07-26 15:00:00,17698\n2014-07-26 15:30:00,18074\n2014-07-26 16:00:00,16920\n2014-07-26 16:30:00,18262\n2014-07-26 17:00:00,19013\n2014-07-26 17:30:00,19902\n2014-07-26 18:00:00,20449\n2014-07-26 18:30:00,22190\n2014-07-26 19:00:00,23099\n2014-07-26 19:30:00,22128\n2014-07-26 20:00:00,20110\n2014-07-26 20:30:00,20261\n2014-07-26 21:00:00,22299\n2014-07-26 21:30:00,21886\n2014-07-26 22:00:00,22600\n2014-07-26 22:30:00,24667\n2014-07-26 23:00:00,25662\n2014-07-26 23:30:00,25832\n2014-07-27 00:00:00,25659\n2014-07-27 00:30:00,24748\n2014-07-27 01:00:00,22552\n2014-07-27 01:30:00,20712\n2014-07-27 02:00:00,19122\n2014-07-27 02:30:00,16777\n2014-07-27 03:00:00,14475\n2014-07-27 03:30:00,12720\n2014-07-27 04:00:00,11239\n2014-07-27 04:30:00,7087\n2014-07-27 05:00:00,4896\n2014-07-27 05:30:00,3818\n2014-07-27 06:00:00,3449\n2014-07-27 06:30:00,3883\n2014-07-27 07:00:00,3810\n2014-07-27 07:30:00,5059\n2014-07-27 08:00:00,5476\n2014-07-27 08:30:00,7083\n2014-07-27 09:00:00,8153\n2014-07-27 09:30:00,10647\n2014-07-27 10:00:00,11873\n2014-07-27 10:30:00,14193\n2014-07-27 11:00:00,14938\n2014-07-27 11:30:00,16488\n2014-07-27 12:00:00,16996\n2014-07-27 12:30:00,17381\n2014-07-27 13:00:00,18173\n2014-07-27 13:30:00,17651\n2014-07-27 14:00:00,18698\n2014-07-27 14:30:00,18260\n2014-07-27 15:00:00,18181\n2014-07-27 15:30:00,17413\n2014-07-27 16:00:00,17230\n2014-07-27 16:30:00,18275\n2014-07-27 17:00:00,18883\n2014-07-27 17:30:00,19851\n2014-07-27 18:00:00,19673\n2014-07-27 18:30:00,20508\n2014-07-27 19:00:00,19557\n2014-07-27 19:30:00,18268\n2014-07-27 20:00:00,16615\n2014-07-27 20:30:00,16969\n2014-07-27 21:00:00,18252\n2014-07-27 21:30:00,16920\n2014-07-27 22:00:00,16356\n2014-07-27 22:30:00,15567\n2014-07-27 23:00:00,14278\n2014-07-27 23:30:00,12786\n2014-07-28 00:00:00,10323\n2014-07-28 00:30:00,7645\n2014-07-28 01:00:00,6791\n2014-07-28 01:30:00,5394\n2014-07-28 02:00:00,3694\n2014-07-28 02:30:00,2713\n2014-07-28 03:00:00,2376\n2014-07-28 03:30:00,2146\n2014-07-28 04:00:00,2250\n2014-07-28 04:30:00,2370\n2014-07-28 05:00:00,2906\n2014-07-28 05:30:00,4477\n2014-07-28 06:00:00,6446\n2014-07-28 06:30:00,9332\n2014-07-28 07:00:00,10577\n2014-07-28 07:30:00,11765\n2014-07-28 08:00:00,13452\n2014-07-28 08:30:00,14290\n2014-07-28 09:00:00,15239\n2014-07-28 09:30:00,14926\n2014-07-28 10:00:00,14475\n2014-07-28 10:30:00,14435\n2014-07-28 11:00:00,14103\n2014-07-28 11:30:00,15124\n2014-07-28 12:00:00,15376\n2014-07-28 12:30:00,15758\n2014-07-28 13:00:00,14653\n2014-07-28 13:30:00,15786\n2014-07-28 14:00:00,15554\n2014-07-28 14:30:00,16332\n2014-07-28 15:00:00,15602\n2014-07-28 15:30:00,14931\n2014-07-28 16:00:00,13817\n2014-07-28 16:30:00,13611\n2014-07-28 17:00:00,14678\n2014-07-28 17:30:00,16669\n2014-07-28 18:00:00,18171\n2014-07-28 18:30:00,20033\n2014-07-28 19:00:00,20467\n2014-07-28 19:30:00,20263\n2014-07-28 20:00:00,18901\n2014-07-28 20:30:00,18249\n2014-07-28 21:00:00,18421\n2014-07-28 21:30:00,17932\n2014-07-28 22:00:00,17568\n2014-07-28 22:30:00,16656\n2014-07-28 23:00:00,15574\n2014-07-28 23:30:00,13310\n2014-07-29 00:00:00,10468\n2014-07-29 00:30:00,7932\n2014-07-29 01:00:00,6080\n2014-07-29 01:30:00,4735\n2014-07-29 02:00:00,3834\n2014-07-29 02:30:00,2746\n2014-07-29 03:00:00,2244\n2014-07-29 03:30:00,1940\n2014-07-29 04:00:00,2066\n2014-07-29 04:30:00,2046\n2014-07-29 05:00:00,2295\n2014-07-29 05:30:00,4533\n2014-07-29 06:00:00,6655\n2014-07-29 06:30:00,11415\n2014-07-29 07:00:00,13863\n2014-07-29 07:30:00,15517\n2014-07-29 08:00:00,17106\n2014-07-29 08:30:00,18521\n2014-07-29 09:00:00,18016\n2014-07-29 09:30:00,17448\n2014-07-29 10:00:00,16131\n2014-07-29 10:30:00,16534\n2014-07-29 11:00:00,15744\n2014-07-29 11:30:00,17039\n2014-07-29 12:00:00,17357\n2014-07-29 12:30:00,16841\n2014-07-29 13:00:00,16797\n2014-07-29 13:30:00,17226\n2014-07-29 14:00:00,17550\n2014-07-29 14:30:00,17336\n2014-07-29 15:00:00,17343\n2014-07-29 15:30:00,16601\n2014-07-29 16:00:00,15090\n2014-07-29 16:30:00,14130\n2014-07-29 17:00:00,16356\n2014-07-29 17:30:00,19357\n2014-07-29 18:00:00,22313\n2014-07-29 18:30:00,23636\n2014-07-29 19:00:00,24822\n2014-07-29 19:30:00,24550\n2014-07-29 20:00:00,22761\n2014-07-29 20:30:00,23119\n2014-07-29 21:00:00,23658\n2014-07-29 21:30:00,23853\n2014-07-29 22:00:00,22995\n2014-07-29 22:30:00,21708\n2014-07-29 23:00:00,20231\n2014-07-29 23:30:00,17264\n2014-07-30 00:00:00,13549\n2014-07-30 00:30:00,10142\n2014-07-30 01:00:00,7783\n2014-07-30 01:30:00,6011\n2014-07-30 02:00:00,4935\n2014-07-30 02:30:00,3668\n2014-07-30 03:00:00,3092\n2014-07-30 03:30:00,2577\n2014-07-30 04:00:00,2772\n2014-07-30 04:30:00,2637\n2014-07-30 05:00:00,2605\n2014-07-30 05:30:00,4449\n2014-07-30 06:00:00,6912\n2014-07-30 06:30:00,11909\n2014-07-30 07:00:00,14184\n2014-07-30 07:30:00,17246\n2014-07-30 08:00:00,18393\n2014-07-30 08:30:00,19797\n2014-07-30 09:00:00,19101\n2014-07-30 09:30:00,18889\n2014-07-30 10:00:00,16897\n2014-07-30 10:30:00,16922\n2014-07-30 11:00:00,16218\n2014-07-30 11:30:00,17511\n2014-07-30 12:00:00,17941\n2014-07-30 12:30:00,17203\n2014-07-30 13:00:00,16879\n2014-07-30 13:30:00,17733\n2014-07-30 14:00:00,17587\n2014-07-30 14:30:00,17564\n2014-07-30 15:00:00,17003\n2014-07-30 15:30:00,15725\n2014-07-30 16:00:00,13832\n2014-07-30 16:30:00,12826\n2014-07-30 17:00:00,15603\n2014-07-30 17:30:00,18935\n2014-07-30 18:00:00,21175\n2014-07-30 18:30:00,22980\n2014-07-30 19:00:00,24644\n2014-07-30 19:30:00,24938\n2014-07-30 20:00:00,24095\n2014-07-30 20:30:00,23952\n2014-07-30 21:00:00,24913\n2014-07-30 21:30:00,25138\n2014-07-30 22:00:00,24972\n2014-07-30 22:30:00,23605\n2014-07-30 23:00:00,22758\n2014-07-30 23:30:00,19560\n2014-07-31 00:00:00,15486\n2014-07-31 00:30:00,12362\n2014-07-31 01:00:00,9401\n2014-07-31 01:30:00,7131\n2014-07-31 02:00:00,5949\n2014-07-31 02:30:00,4722\n2014-07-31 03:00:00,3792\n2014-07-31 03:30:00,3266\n2014-07-31 04:00:00,3267\n2014-07-31 04:30:00,2605\n2014-07-31 05:00:00,2562\n2014-07-31 05:30:00,4595\n2014-07-31 06:00:00,7263\n2014-07-31 06:30:00,11825\n2014-07-31 07:00:00,13863\n2014-07-31 07:30:00,16898\n2014-07-31 08:00:00,18741\n2014-07-31 08:30:00,20117\n2014-07-31 09:00:00,19185\n2014-07-31 09:30:00,17821\n2014-07-31 10:00:00,16721\n2014-07-31 10:30:00,16869\n2014-07-31 11:00:00,16188\n2014-07-31 11:30:00,17325\n2014-07-31 12:00:00,17849\n2014-07-31 12:30:00,17746\n2014-07-31 13:00:00,17208\n2014-07-31 13:30:00,17848\n2014-07-31 14:00:00,18132\n2014-07-31 14:30:00,18019\n2014-07-31 15:00:00,17120\n2014-07-31 15:30:00,15410\n2014-07-31 16:00:00,13868\n2014-07-31 16:30:00,13146\n2014-07-31 17:00:00,15734\n2014-07-31 17:30:00,18139\n2014-07-31 18:00:00,20969\n2014-07-31 18:30:00,23287\n2014-07-31 19:00:00,24723\n2014-07-31 19:30:00,25186\n2014-07-31 20:00:00,24192\n2014-07-31 20:30:00,24605\n2014-07-31 21:00:00,25805\n2014-07-31 21:30:00,25969\n2014-07-31 22:00:00,25593\n2014-07-31 22:30:00,24695\n2014-07-31 23:00:00,24316\n2014-07-31 23:30:00,23050\n2014-08-01 00:00:00,20138\n2014-08-01 00:30:00,17252\n2014-08-01 01:00:00,14103\n2014-08-01 01:30:00,10859\n2014-08-01 02:00:00,9242\n2014-08-01 02:30:00,7122\n2014-08-01 03:00:00,5763\n2014-08-01 03:30:00,4912\n2014-08-01 04:00:00,4648\n2014-08-01 04:30:00,3673\n2014-08-01 05:00:00,3322\n2014-08-01 05:30:00,4968\n2014-08-01 06:00:00,7209\n2014-08-01 06:30:00,11113\n2014-08-01 07:00:00,13143\n2014-08-01 07:30:00,15932\n2014-08-01 08:00:00,17355\n2014-08-01 08:30:00,19462\n2014-08-01 09:00:00,18581\n2014-08-01 09:30:00,18123\n2014-08-01 10:00:00,16476\n2014-08-01 10:30:00,16964\n2014-08-01 11:00:00,16009\n2014-08-01 11:30:00,16890\n2014-08-01 12:00:00,17069\n2014-08-01 12:30:00,16779\n2014-08-01 13:00:00,16654\n2014-08-01 13:30:00,16580\n2014-08-01 14:00:00,17407\n2014-08-01 14:30:00,17037\n2014-08-01 15:00:00,16651\n2014-08-01 15:30:00,15324\n2014-08-01 16:00:00,12987\n2014-08-01 16:30:00,12845\n2014-08-01 17:00:00,15439\n2014-08-01 17:30:00,18280\n2014-08-01 18:00:00,20439\n2014-08-01 18:30:00,22588\n2014-08-01 19:00:00,24047\n2014-08-01 19:30:00,23745\n2014-08-01 20:00:00,22420\n2014-08-01 20:30:00,23260\n2014-08-01 21:00:00,23454\n2014-08-01 21:30:00,22822\n2014-08-01 22:00:00,23704\n2014-08-01 22:30:00,24940\n2014-08-01 23:00:00,25951\n2014-08-01 23:30:00,25479\n2014-08-02 00:00:00,25234\n2014-08-02 00:30:00,23378\n2014-08-02 01:00:00,22180\n2014-08-02 01:30:00,20497\n2014-08-02 02:00:00,18933\n2014-08-02 02:30:00,17041\n2014-08-02 03:00:00,14983\n2014-08-02 03:30:00,12488\n2014-08-02 04:00:00,10554\n2014-08-02 04:30:00,6425\n2014-08-02 05:00:00,4384\n2014-08-02 05:30:00,3611\n2014-08-02 06:00:00,3904\n2014-08-02 06:30:00,5204\n2014-08-02 07:00:00,5624\n2014-08-02 07:30:00,7264\n2014-08-02 08:00:00,7501\n2014-08-02 08:30:00,9344\n2014-08-02 09:00:00,10021\n2014-08-02 09:30:00,12227\n2014-08-02 10:00:00,12203\n2014-08-02 10:30:00,14669\n2014-08-02 11:00:00,14849\n2014-08-02 11:30:00,16363\n2014-08-02 12:00:00,16489\n2014-08-02 12:30:00,17237\n2014-08-02 13:00:00,17955\n2014-08-02 13:30:00,17713\n2014-08-02 14:00:00,17418\n2014-08-02 14:30:00,17679\n2014-08-02 15:00:00,18014\n2014-08-02 15:30:00,18031\n2014-08-02 16:00:00,17643\n2014-08-02 16:30:00,17167\n2014-08-02 17:00:00,18409\n2014-08-02 17:30:00,20034\n2014-08-02 18:00:00,21113\n2014-08-02 18:30:00,21487\n2014-08-02 19:00:00,22872\n2014-08-02 19:30:00,22995\n2014-08-02 20:00:00,20896\n2014-08-02 20:30:00,21411\n2014-08-02 21:00:00,21273\n2014-08-02 21:30:00,21628\n2014-08-02 22:00:00,21872\n2014-08-02 22:30:00,23457\n2014-08-02 23:00:00,24958\n2014-08-02 23:30:00,24984\n2014-08-03 00:00:00,24613\n2014-08-03 00:30:00,23468\n2014-08-03 01:00:00,22125\n2014-08-03 01:30:00,22220\n2014-08-03 02:00:00,20171\n2014-08-03 02:30:00,17690\n2014-08-03 03:00:00,14908\n2014-08-03 03:30:00,13465\n2014-08-03 04:00:00,11663\n2014-08-03 04:30:00,6997\n2014-08-03 05:00:00,4810\n2014-08-03 05:30:00,3650\n2014-08-03 06:00:00,3561\n2014-08-03 06:30:00,4060\n2014-08-03 07:00:00,4382\n2014-08-03 07:30:00,5741\n2014-08-03 08:00:00,6722\n2014-08-03 08:30:00,7857\n2014-08-03 09:00:00,8424\n2014-08-03 09:30:00,10636\n2014-08-03 10:00:00,11811\n2014-08-03 10:30:00,13776\n2014-08-03 11:00:00,14821\n2014-08-03 11:30:00,16169\n2014-08-03 12:00:00,16715\n2014-08-03 12:30:00,17652\n2014-08-03 13:00:00,17360\n2014-08-03 13:30:00,17167\n2014-08-03 14:00:00,18546\n2014-08-03 14:30:00,17882\n2014-08-03 15:00:00,17268\n2014-08-03 15:30:00,17322\n2014-08-03 16:00:00,16500\n2014-08-03 16:30:00,16446\n2014-08-03 17:00:00,17317\n2014-08-03 17:30:00,18472\n2014-08-03 18:00:00,19503\n2014-08-03 18:30:00,19622\n2014-08-03 19:00:00,18900\n2014-08-03 19:30:00,17188\n2014-08-03 20:00:00,16880\n2014-08-03 20:30:00,17035\n2014-08-03 21:00:00,16790\n2014-08-03 21:30:00,17007\n2014-08-03 22:00:00,15893\n2014-08-03 22:30:00,14672\n2014-08-03 23:00:00,12667\n2014-08-03 23:30:00,10905\n2014-08-04 00:00:00,8882\n2014-08-04 00:30:00,6896\n2014-08-04 01:00:00,5417\n2014-08-04 01:30:00,4245\n2014-08-04 02:00:00,3478\n2014-08-04 02:30:00,2525\n2014-08-04 03:00:00,2288\n2014-08-04 03:30:00,2114\n2014-08-04 04:00:00,2212\n2014-08-04 04:30:00,2303\n2014-08-04 05:00:00,2482\n2014-08-04 05:30:00,4420\n2014-08-04 06:00:00,6426\n2014-08-04 06:30:00,10775\n2014-08-04 07:00:00,12795\n2014-08-04 07:30:00,15762\n2014-08-04 08:00:00,17271\n2014-08-04 08:30:00,18418\n2014-08-04 09:00:00,18214\n2014-08-04 09:30:00,17223\n2014-08-04 10:00:00,15029\n2014-08-04 10:30:00,15614\n2014-08-04 11:00:00,15026\n2014-08-04 11:30:00,16170\n2014-08-04 12:00:00,16111\n2014-08-04 12:30:00,16049\n2014-08-04 13:00:00,16084\n2014-08-04 13:30:00,16640\n2014-08-04 14:00:00,16634\n2014-08-04 14:30:00,17210\n2014-08-04 15:00:00,16546\n2014-08-04 15:30:00,16798\n2014-08-04 16:00:00,15124\n2014-08-04 16:30:00,14870\n2014-08-04 17:00:00,16956\n2014-08-04 17:30:00,18613\n2014-08-04 18:00:00,21126\n2014-08-04 18:30:00,22510\n2014-08-04 19:00:00,22568\n2014-08-04 19:30:00,21668\n2014-08-04 20:00:00,21659\n2014-08-04 20:30:00,21278\n2014-08-04 21:00:00,21346\n2014-08-04 21:30:00,20247\n2014-08-04 22:00:00,19945\n2014-08-04 22:30:00,17601\n2014-08-04 23:00:00,15750\n2014-08-04 23:30:00,12897\n2014-08-05 00:00:00,10385\n2014-08-05 00:30:00,8125\n2014-08-05 01:00:00,6294\n2014-08-05 01:30:00,4485\n2014-08-05 02:00:00,3669\n2014-08-05 02:30:00,3097\n2014-08-05 03:00:00,2484\n2014-08-05 03:30:00,2011\n2014-08-05 04:00:00,2175\n2014-08-05 04:30:00,2108\n2014-08-05 05:00:00,2252\n2014-08-05 05:30:00,4131\n2014-08-05 06:00:00,6599\n2014-08-05 06:30:00,11040\n2014-08-05 07:00:00,13290\n2014-08-05 07:30:00,16754\n2014-08-05 08:00:00,18504\n2014-08-05 08:30:00,19897\n2014-08-05 09:00:00,19208\n2014-08-05 09:30:00,18253\n2014-08-05 10:00:00,16976\n2014-08-05 10:30:00,16888\n2014-08-05 11:00:00,16080\n2014-08-05 11:30:00,17328\n2014-08-05 12:00:00,17901\n2014-08-05 12:30:00,18121\n2014-08-05 13:00:00,17478\n2014-08-05 13:30:00,18616\n2014-08-05 14:00:00,18576\n2014-08-05 14:30:00,18465\n2014-08-05 15:00:00,17373\n2014-08-05 15:30:00,16457\n2014-08-05 16:00:00,14626\n2014-08-05 16:30:00,13466\n2014-08-05 17:00:00,16213\n2014-08-05 17:30:00,18715\n2014-08-05 18:00:00,21356\n2014-08-05 18:30:00,22899\n2014-08-05 19:00:00,23782\n2014-08-05 19:30:00,22778\n2014-08-05 20:00:00,22401\n2014-08-05 20:30:00,22986\n2014-08-05 21:00:00,23340\n2014-08-05 21:30:00,24046\n2014-08-05 22:00:00,22726\n2014-08-05 22:30:00,20819\n2014-08-05 23:00:00,19149\n2014-08-05 23:30:00,16406\n2014-08-06 00:00:00,13399\n2014-08-06 00:30:00,10273\n2014-08-06 01:00:00,7723\n2014-08-06 01:30:00,5860\n2014-08-06 02:00:00,4664\n2014-08-06 02:30:00,3875\n2014-08-06 03:00:00,3057\n2014-08-06 03:30:00,2675\n2014-08-06 04:00:00,2803\n2014-08-06 04:30:00,2364\n2014-08-06 05:00:00,2602\n2014-08-06 05:30:00,4488\n2014-08-06 06:00:00,6944\n2014-08-06 06:30:00,11761\n2014-08-06 07:00:00,14631\n2014-08-06 07:30:00,17455\n2014-08-06 08:00:00,19107\n2014-08-06 08:30:00,19737\n2014-08-06 09:00:00,18707\n2014-08-06 09:30:00,18466\n2014-08-06 10:00:00,16630\n2014-08-06 10:30:00,17291\n2014-08-06 11:00:00,15977\n2014-08-06 11:30:00,17643\n2014-08-06 12:00:00,17959\n2014-08-06 12:30:00,17652\n2014-08-06 13:00:00,17197\n2014-08-06 13:30:00,17949\n2014-08-06 14:00:00,17918\n2014-08-06 14:30:00,17534\n2014-08-06 15:00:00,17350\n2014-08-06 15:30:00,16327\n2014-08-06 16:00:00,14582\n2014-08-06 16:30:00,13374\n2014-08-06 17:00:00,16090\n2014-08-06 17:30:00,18989\n2014-08-06 18:00:00,21429\n2014-08-06 18:30:00,23892\n2014-08-06 19:00:00,24481\n2014-08-06 19:30:00,24197\n2014-08-06 20:00:00,23556\n2014-08-06 20:30:00,23555\n2014-08-06 21:00:00,24355\n2014-08-06 21:30:00,24699\n2014-08-06 22:00:00,23955\n2014-08-06 22:30:00,22754\n2014-08-06 23:00:00,21450\n2014-08-06 23:30:00,18427\n2014-08-07 00:00:00,15411\n2014-08-07 00:30:00,11851\n2014-08-07 01:00:00,9317\n2014-08-07 01:30:00,6973\n2014-08-07 02:00:00,5807\n2014-08-07 02:30:00,4812\n2014-08-07 03:00:00,3738\n2014-08-07 03:30:00,3108\n2014-08-07 04:00:00,3199\n2014-08-07 04:30:00,2642\n2014-08-07 05:00:00,2704\n2014-08-07 05:30:00,4812\n2014-08-07 06:00:00,6873\n2014-08-07 06:30:00,11765\n2014-08-07 07:00:00,13641\n2014-08-07 07:30:00,17052\n2014-08-07 08:00:00,18252\n2014-08-07 08:30:00,19400\n2014-08-07 09:00:00,18455\n2014-08-07 09:30:00,18277\n2014-08-07 10:00:00,16719\n2014-08-07 10:30:00,16764\n2014-08-07 11:00:00,16636\n2014-08-07 11:30:00,18205\n2014-08-07 12:00:00,18034\n2014-08-07 12:30:00,17700\n2014-08-07 13:00:00,16970\n2014-08-07 13:30:00,17983\n2014-08-07 14:00:00,18230\n2014-08-07 14:30:00,18073\n2014-08-07 15:00:00,17471\n2014-08-07 15:30:00,15872\n2014-08-07 16:00:00,13784\n2014-08-07 16:30:00,13341\n2014-08-07 17:00:00,15857\n2014-08-07 17:30:00,18396\n2014-08-07 18:00:00,21500\n2014-08-07 18:30:00,23368\n2014-08-07 19:00:00,24977\n2014-08-07 19:30:00,24747\n2014-08-07 20:00:00,23895\n2014-08-07 20:30:00,24153\n2014-08-07 21:00:00,24778\n2014-08-07 21:30:00,24533\n2014-08-07 22:00:00,24478\n2014-08-07 22:30:00,24253\n2014-08-07 23:00:00,23299\n2014-08-07 23:30:00,22155\n2014-08-08 00:00:00,19329\n2014-08-08 00:30:00,15933\n2014-08-08 01:00:00,13410\n2014-08-08 01:30:00,10614\n2014-08-08 02:00:00,8934\n2014-08-08 02:30:00,7079\n2014-08-08 03:00:00,5803\n2014-08-08 03:30:00,4992\n2014-08-08 04:00:00,4555\n2014-08-08 04:30:00,3601\n2014-08-08 05:00:00,3643\n2014-08-08 05:30:00,4924\n2014-08-08 06:00:00,6649\n2014-08-08 06:30:00,10748\n2014-08-08 07:00:00,12731\n2014-08-08 07:30:00,15178\n2014-08-08 08:00:00,16731\n2014-08-08 08:30:00,18521\n2014-08-08 09:00:00,17924\n2014-08-08 09:30:00,17129\n2014-08-08 10:00:00,15820\n2014-08-08 10:30:00,16405\n2014-08-08 11:00:00,15710\n2014-08-08 11:30:00,16406\n2014-08-08 12:00:00,17040\n2014-08-08 12:30:00,16998\n2014-08-08 13:00:00,16524\n2014-08-08 13:30:00,17157\n2014-08-08 14:00:00,17341\n2014-08-08 14:30:00,17716\n2014-08-08 15:00:00,17135\n2014-08-08 15:30:00,15591\n2014-08-08 16:00:00,13942\n2014-08-08 16:30:00,13215\n2014-08-08 17:00:00,16320\n2014-08-08 17:30:00,19539\n2014-08-08 18:00:00,21553\n2014-08-08 18:30:00,23100\n2014-08-08 19:00:00,24705\n2014-08-08 19:30:00,23913\n2014-08-08 20:00:00,22283\n2014-08-08 20:30:00,22808\n2014-08-08 21:00:00,22239\n2014-08-08 21:30:00,21989\n2014-08-08 22:00:00,22689\n2014-08-08 22:30:00,23756\n2014-08-08 23:00:00,24182\n2014-08-08 23:30:00,24184\n2014-08-09 00:00:00,23849\n2014-08-09 00:30:00,22495\n2014-08-09 01:00:00,20367\n2014-08-09 01:30:00,18368\n2014-08-09 02:00:00,17499\n2014-08-09 02:30:00,15607\n2014-08-09 03:00:00,13502\n2014-08-09 03:30:00,11670\n2014-08-09 04:00:00,9956\n2014-08-09 04:30:00,5950\n2014-08-09 05:00:00,4023\n2014-08-09 05:30:00,3499\n2014-08-09 06:00:00,3663\n2014-08-09 06:30:00,4608\n2014-08-09 07:00:00,5226\n2014-08-09 07:30:00,6154\n2014-08-09 08:00:00,7082\n2014-08-09 08:30:00,8917\n2014-08-09 09:00:00,9965\n2014-08-09 09:30:00,12488\n2014-08-09 10:00:00,12845\n2014-08-09 10:30:00,14960\n2014-08-09 11:00:00,15195\n2014-08-09 11:30:00,16331\n2014-08-09 12:00:00,16385\n2014-08-09 12:30:00,16704\n2014-08-09 13:00:00,17450\n2014-08-09 13:30:00,17458\n2014-08-09 14:00:00,16849\n2014-08-09 14:30:00,16880\n2014-08-09 15:00:00,16951\n2014-08-09 15:30:00,16926\n2014-08-09 16:00:00,16376\n2014-08-09 16:30:00,16454\n2014-08-09 17:00:00,17768\n2014-08-09 17:30:00,19335\n2014-08-09 18:00:00,20035\n2014-08-09 18:30:00,21023\n2014-08-09 19:00:00,21977\n2014-08-09 19:30:00,20987\n2014-08-09 20:00:00,19159\n2014-08-09 20:30:00,19801\n2014-08-09 21:00:00,20361\n2014-08-09 21:30:00,20651\n2014-08-09 22:00:00,20833\n2014-08-09 22:30:00,22467\n2014-08-09 23:00:00,23285\n2014-08-09 23:30:00,23652\n2014-08-10 00:00:00,23701\n2014-08-10 00:30:00,21532\n2014-08-10 01:00:00,20557\n2014-08-10 01:30:00,18415\n2014-08-10 02:00:00,17813\n2014-08-10 02:30:00,16223\n2014-08-10 03:00:00,13777\n2014-08-10 03:30:00,11818\n2014-08-10 04:00:00,10499\n2014-08-10 04:30:00,6180\n2014-08-10 05:00:00,4096\n2014-08-10 05:30:00,3476\n2014-08-10 06:00:00,3259\n2014-08-10 06:30:00,3468\n2014-08-10 07:00:00,3690\n2014-08-10 07:30:00,5047\n2014-08-10 08:00:00,5503\n2014-08-10 08:30:00,6667\n2014-08-10 09:00:00,8014\n2014-08-10 09:30:00,10532\n2014-08-10 10:00:00,11486\n2014-08-10 10:30:00,13733\n2014-08-10 11:00:00,14525\n2014-08-10 11:30:00,15314\n2014-08-10 12:00:00,16013\n2014-08-10 12:30:00,16268\n2014-08-10 13:00:00,16610\n2014-08-10 13:30:00,16496\n2014-08-10 14:00:00,16885\n2014-08-10 14:30:00,16396\n2014-08-10 15:00:00,15796\n2014-08-10 15:30:00,15545\n2014-08-10 16:00:00,15642\n2014-08-10 16:30:00,15531\n2014-08-10 17:00:00,16410\n2014-08-10 17:30:00,17684\n2014-08-10 18:00:00,17992\n2014-08-10 18:30:00,18285\n2014-08-10 19:00:00,17697\n2014-08-10 19:30:00,16452\n2014-08-10 20:00:00,16195\n2014-08-10 20:30:00,16545\n2014-08-10 21:00:00,15989\n2014-08-10 21:30:00,15763\n2014-08-10 22:00:00,14767\n2014-08-10 22:30:00,14157\n2014-08-10 23:00:00,12939\n2014-08-10 23:30:00,11801\n2014-08-11 00:00:00,9595\n2014-08-11 00:30:00,7267\n2014-08-11 01:00:00,5616\n2014-08-11 01:30:00,4253\n2014-08-11 02:00:00,3261\n2014-08-11 02:30:00,2770\n2014-08-11 03:00:00,2240\n2014-08-11 03:30:00,2084\n2014-08-11 04:00:00,2407\n2014-08-11 04:30:00,2262\n2014-08-11 05:00:00,2728\n2014-08-11 05:30:00,4273\n2014-08-11 06:00:00,6194\n2014-08-11 06:30:00,10158\n2014-08-11 07:00:00,12697\n2014-08-11 07:30:00,14281\n2014-08-11 08:00:00,16009\n2014-08-11 08:30:00,17659\n2014-08-11 09:00:00,17250\n2014-08-11 09:30:00,16687\n2014-08-11 10:00:00,14465\n2014-08-11 10:30:00,14373\n2014-08-11 11:00:00,14599\n2014-08-11 11:30:00,15212\n2014-08-11 12:00:00,16026\n2014-08-11 12:30:00,15526\n2014-08-11 13:00:00,15672\n2014-08-11 13:30:00,16419\n2014-08-11 14:00:00,16083\n2014-08-11 14:30:00,16352\n2014-08-11 15:00:00,16535\n2014-08-11 15:30:00,16248\n2014-08-11 16:00:00,14959\n2014-08-11 16:30:00,14201\n2014-08-11 17:00:00,16142\n2014-08-11 17:30:00,18163\n2014-08-11 18:00:00,20715\n2014-08-11 18:30:00,21256\n2014-08-11 19:00:00,21528\n2014-08-11 19:30:00,20720\n2014-08-11 20:00:00,20604\n2014-08-11 20:30:00,19786\n2014-08-11 21:00:00,19471\n2014-08-11 21:30:00,19116\n2014-08-11 22:00:00,18358\n2014-08-11 22:30:00,16440\n2014-08-11 23:00:00,14821\n2014-08-11 23:30:00,12022\n2014-08-12 00:00:00,9701\n2014-08-12 00:30:00,7757\n2014-08-12 01:00:00,6003\n2014-08-12 01:30:00,4648\n2014-08-12 02:00:00,3805\n2014-08-12 02:30:00,3093\n2014-08-12 03:00:00,2487\n2014-08-12 03:30:00,2164\n2014-08-12 04:00:00,2288\n2014-08-12 04:30:00,2083\n2014-08-12 05:00:00,2452\n2014-08-12 05:30:00,4282\n2014-08-12 06:00:00,6142\n2014-08-12 06:30:00,10744\n2014-08-12 07:00:00,13034\n2014-08-12 07:30:00,15724\n2014-08-12 08:00:00,18102\n2014-08-12 08:30:00,19748\n2014-08-12 09:00:00,18510\n2014-08-12 09:30:00,17502\n2014-08-12 10:00:00,15832\n2014-08-12 10:30:00,15940\n2014-08-12 11:00:00,15064\n2014-08-12 11:30:00,16927\n2014-08-12 12:00:00,16871\n2014-08-12 12:30:00,17325\n2014-08-12 13:00:00,16350\n2014-08-12 13:30:00,17244\n2014-08-12 14:00:00,18778\n2014-08-12 14:30:00,19036\n2014-08-12 15:00:00,18549\n2014-08-12 15:30:00,16263\n2014-08-12 16:00:00,13781\n2014-08-12 16:30:00,13197\n2014-08-12 17:00:00,14909\n2014-08-12 17:30:00,18695\n2014-08-12 18:00:00,21494\n2014-08-12 18:30:00,23426\n2014-08-12 19:00:00,25057\n2014-08-12 19:30:00,26062\n2014-08-12 20:00:00,20944\n2014-08-12 20:30:00,20583\n2014-08-12 21:00:00,22343\n2014-08-12 21:30:00,22704\n2014-08-12 22:00:00,20090\n2014-08-12 22:30:00,21338\n2014-08-12 23:00:00,18853\n2014-08-12 23:30:00,14548\n2014-08-13 00:00:00,12933\n2014-08-13 00:30:00,11301\n2014-08-13 01:00:00,8095\n2014-08-13 01:30:00,6266\n2014-08-13 02:00:00,4752\n2014-08-13 02:30:00,3446\n2014-08-13 03:00:00,2793\n2014-08-13 03:30:00,2333\n2014-08-13 04:00:00,2468\n2014-08-13 04:30:00,2059\n2014-08-13 05:00:00,2411\n2014-08-13 05:30:00,4204\n2014-08-13 06:00:00,6516\n2014-08-13 06:30:00,11706\n2014-08-13 07:00:00,14894\n2014-08-13 07:30:00,17894\n2014-08-13 08:00:00,18081\n2014-08-13 08:30:00,19597\n2014-08-13 09:00:00,19047\n2014-08-13 09:30:00,19060\n2014-08-13 10:00:00,17041\n2014-08-13 10:30:00,16354\n2014-08-13 11:00:00,15259\n2014-08-13 11:30:00,16470\n2014-08-13 12:00:00,17146\n2014-08-13 12:30:00,17220\n2014-08-13 13:00:00,16932\n2014-08-13 13:30:00,17515\n2014-08-13 14:00:00,17285\n2014-08-13 14:30:00,17467\n2014-08-13 15:00:00,16869\n2014-08-13 15:30:00,16383\n2014-08-13 16:00:00,14727\n2014-08-13 16:30:00,14059\n2014-08-13 17:00:00,16707\n2014-08-13 17:30:00,20486\n2014-08-13 18:00:00,22207\n2014-08-13 18:30:00,23183\n2014-08-13 19:00:00,24873\n2014-08-13 19:30:00,24028\n2014-08-13 20:00:00,22822\n2014-08-13 20:30:00,22831\n2014-08-13 21:00:00,23148\n2014-08-13 21:30:00,23005\n2014-08-13 22:00:00,23506\n2014-08-13 22:30:00,22493\n2014-08-13 23:00:00,20703\n2014-08-13 23:30:00,18013\n2014-08-14 00:00:00,14505\n2014-08-14 00:30:00,11389\n2014-08-14 01:00:00,8924\n2014-08-14 01:30:00,7135\n2014-08-14 02:00:00,5649\n2014-08-14 02:30:00,4544\n2014-08-14 03:00:00,3542\n2014-08-14 03:30:00,3086\n2014-08-14 04:00:00,3091\n2014-08-14 04:30:00,2590\n2014-08-14 05:00:00,2706\n2014-08-14 05:30:00,4336\n2014-08-14 06:00:00,6237\n2014-08-14 06:30:00,10724\n2014-08-14 07:00:00,13183\n2014-08-14 07:30:00,15723\n2014-08-14 08:00:00,17752\n2014-08-14 08:30:00,19645\n2014-08-14 09:00:00,18448\n2014-08-14 09:30:00,17796\n2014-08-14 10:00:00,16361\n2014-08-14 10:30:00,16636\n2014-08-14 11:00:00,15606\n2014-08-14 11:30:00,17003\n2014-08-14 12:00:00,17538\n2014-08-14 12:30:00,16979\n2014-08-14 13:00:00,16844\n2014-08-14 13:30:00,17372\n2014-08-14 14:00:00,17667\n2014-08-14 14:30:00,17859\n2014-08-14 15:00:00,17357\n2014-08-14 15:30:00,16100\n2014-08-14 16:00:00,14347\n2014-08-14 16:30:00,13630\n2014-08-14 17:00:00,16197\n2014-08-14 17:30:00,18210\n2014-08-14 18:00:00,21282\n2014-08-14 18:30:00,22623\n2014-08-14 19:00:00,24035\n2014-08-14 19:30:00,24056\n2014-08-14 20:00:00,23987\n2014-08-14 20:30:00,24289\n2014-08-14 21:00:00,24134\n2014-08-14 21:30:00,24141\n2014-08-14 22:00:00,24661\n2014-08-14 22:30:00,24114\n2014-08-14 23:00:00,23611\n2014-08-14 23:30:00,21287\n2014-08-15 00:00:00,19491\n2014-08-15 00:30:00,16128\n2014-08-15 01:00:00,13044\n2014-08-15 01:30:00,9984\n2014-08-15 02:00:00,8526\n2014-08-15 02:30:00,7009\n2014-08-15 03:00:00,5525\n2014-08-15 03:30:00,4688\n2014-08-15 04:00:00,4665\n2014-08-15 04:30:00,3542\n2014-08-15 05:00:00,3163\n2014-08-15 05:30:00,4547\n2014-08-15 06:00:00,6346\n2014-08-15 06:30:00,10699\n2014-08-15 07:00:00,12050\n2014-08-15 07:30:00,14555\n2014-08-15 08:00:00,16322\n2014-08-15 08:30:00,18762\n2014-08-15 09:00:00,18321\n2014-08-15 09:30:00,17235\n2014-08-15 10:00:00,15496\n2014-08-15 10:30:00,15859\n2014-08-15 11:00:00,15559\n2014-08-15 11:30:00,16873\n2014-08-15 12:00:00,17350\n2014-08-15 12:30:00,16611\n2014-08-15 13:00:00,16543\n2014-08-15 13:30:00,16753\n2014-08-15 14:00:00,17552\n2014-08-15 14:30:00,17361\n2014-08-15 15:00:00,16508\n2014-08-15 15:30:00,15776\n2014-08-15 16:00:00,14232\n2014-08-15 16:30:00,13784\n2014-08-15 17:00:00,16867\n2014-08-15 17:30:00,19906\n2014-08-15 18:00:00,21668\n2014-08-15 18:30:00,23098\n2014-08-15 19:00:00,24319\n2014-08-15 19:30:00,23800\n2014-08-15 20:00:00,22649\n2014-08-15 20:30:00,23190\n2014-08-15 21:00:00,22209\n2014-08-15 21:30:00,22105\n2014-08-15 22:00:00,23041\n2014-08-15 22:30:00,23974\n2014-08-15 23:00:00,24057\n2014-08-15 23:30:00,23997\n2014-08-16 00:00:00,23174\n2014-08-16 00:30:00,21534\n2014-08-16 01:00:00,20240\n2014-08-16 01:30:00,18434\n2014-08-16 02:00:00,17382\n2014-08-16 02:30:00,14870\n2014-08-16 03:00:00,12921\n2014-08-16 03:30:00,11258\n2014-08-16 04:00:00,9869\n2014-08-16 04:30:00,6061\n2014-08-16 05:00:00,4150\n2014-08-16 05:30:00,3688\n2014-08-16 06:00:00,3811\n2014-08-16 06:30:00,4938\n2014-08-16 07:00:00,5248\n2014-08-16 07:30:00,6972\n2014-08-16 08:00:00,7885\n2014-08-16 08:30:00,9526\n2014-08-16 09:00:00,10750\n2014-08-16 09:30:00,12899\n2014-08-16 10:00:00,12950\n2014-08-16 10:30:00,14145\n2014-08-16 11:00:00,14724\n2014-08-16 11:30:00,15667\n2014-08-16 12:00:00,16016\n2014-08-16 12:30:00,16245\n2014-08-16 13:00:00,17156\n2014-08-16 13:30:00,17194\n2014-08-16 14:00:00,16993\n2014-08-16 14:30:00,17286\n2014-08-16 15:00:00,17109\n2014-08-16 15:30:00,17115\n2014-08-16 16:00:00,16437\n2014-08-16 16:30:00,15986\n2014-08-16 17:00:00,17735\n2014-08-16 17:30:00,19247\n2014-08-16 18:00:00,20555\n2014-08-16 18:30:00,21424\n2014-08-16 19:00:00,22252\n2014-08-16 19:30:00,21379\n2014-08-16 20:00:00,20043\n2014-08-16 20:30:00,19941\n2014-08-16 21:00:00,19947\n2014-08-16 21:30:00,20601\n2014-08-16 22:00:00,21109\n2014-08-16 22:30:00,22185\n2014-08-16 23:00:00,22255\n2014-08-16 23:30:00,23286\n2014-08-17 00:00:00,23263\n2014-08-17 00:30:00,22356\n2014-08-17 01:00:00,20247\n2014-08-17 01:30:00,19261\n2014-08-17 02:00:00,18335\n2014-08-17 02:30:00,15881\n2014-08-17 03:00:00,14076\n2014-08-17 03:30:00,12215\n2014-08-17 04:00:00,10492\n2014-08-17 04:30:00,6297\n2014-08-17 05:00:00,4328\n2014-08-17 05:30:00,3426\n2014-08-17 06:00:00,3367\n2014-08-17 06:30:00,3930\n2014-08-17 07:00:00,3834\n2014-08-17 07:30:00,5166\n2014-08-17 08:00:00,6704\n2014-08-17 08:30:00,8252\n2014-08-17 09:00:00,8872\n2014-08-17 09:30:00,10157\n2014-08-17 10:00:00,11490\n2014-08-17 10:30:00,13701\n2014-08-17 11:00:00,14623\n2014-08-17 11:30:00,15373\n2014-08-17 12:00:00,15798\n2014-08-17 12:30:00,16478\n2014-08-17 13:00:00,16986\n2014-08-17 13:30:00,16375\n2014-08-17 14:00:00,17545\n2014-08-17 14:30:00,17532\n2014-08-17 15:00:00,16751\n2014-08-17 15:30:00,16425\n2014-08-17 16:00:00,16231\n2014-08-17 16:30:00,16257\n2014-08-17 17:00:00,16875\n2014-08-17 17:30:00,18041\n2014-08-17 18:00:00,18055\n2014-08-17 18:30:00,18276\n2014-08-17 19:00:00,18030\n2014-08-17 19:30:00,17081\n2014-08-17 20:00:00,16006\n2014-08-17 20:30:00,16544\n2014-08-17 21:00:00,16394\n2014-08-17 21:30:00,16467\n2014-08-17 22:00:00,15480\n2014-08-17 22:30:00,14150\n2014-08-17 23:00:00,12599\n2014-08-17 23:30:00,11942\n2014-08-18 00:00:00,9875\n2014-08-18 00:30:00,7581\n2014-08-18 01:00:00,5815\n2014-08-18 01:30:00,4164\n2014-08-18 02:00:00,3757\n2014-08-18 02:30:00,2863\n2014-08-18 03:00:00,2372\n2014-08-18 03:30:00,1951\n2014-08-18 04:00:00,2353\n2014-08-18 04:30:00,2332\n2014-08-18 05:00:00,2702\n2014-08-18 05:30:00,4271\n2014-08-18 06:00:00,6107\n2014-08-18 06:30:00,10069\n2014-08-18 07:00:00,11882\n2014-08-18 07:30:00,14095\n2014-08-18 08:00:00,15597\n2014-08-18 08:30:00,18046\n2014-08-18 09:00:00,17168\n2014-08-18 09:30:00,16333\n2014-08-18 10:00:00,14794\n2014-08-18 10:30:00,14653\n2014-08-18 11:00:00,14058\n2014-08-18 11:30:00,15162\n2014-08-18 12:00:00,15013\n2014-08-18 12:30:00,15376\n2014-08-18 13:00:00,14922\n2014-08-18 13:30:00,16122\n2014-08-18 14:00:00,16229\n2014-08-18 14:30:00,16481\n2014-08-18 15:00:00,16424\n2014-08-18 15:30:00,15719\n2014-08-18 16:00:00,15087\n2014-08-18 16:30:00,14465\n2014-08-18 17:00:00,16588\n2014-08-18 17:30:00,17923\n2014-08-18 18:00:00,20054\n2014-08-18 18:30:00,21402\n2014-08-18 19:00:00,21523\n2014-08-18 19:30:00,20447\n2014-08-18 20:00:00,20431\n2014-08-18 20:30:00,19708\n2014-08-18 21:00:00,19821\n2014-08-18 21:30:00,19291\n2014-08-18 22:00:00,18093\n2014-08-18 22:30:00,16177\n2014-08-18 23:00:00,14282\n2014-08-18 23:30:00,11852\n2014-08-19 00:00:00,9601\n2014-08-19 00:30:00,7532\n2014-08-19 01:00:00,5866\n2014-08-19 01:30:00,4515\n2014-08-19 02:00:00,3787\n2014-08-19 02:30:00,2947\n2014-08-19 03:00:00,2237\n2014-08-19 03:30:00,2022\n2014-08-19 04:00:00,2313\n2014-08-19 04:30:00,1932\n2014-08-19 05:00:00,2200\n2014-08-19 05:30:00,4019\n2014-08-19 06:00:00,5928\n2014-08-19 06:30:00,9987\n2014-08-19 07:00:00,12094\n2014-08-19 07:30:00,14716\n2014-08-19 08:00:00,16670\n2014-08-19 08:30:00,18950\n2014-08-19 09:00:00,17964\n2014-08-19 09:30:00,17783\n2014-08-19 10:00:00,15966\n2014-08-19 10:30:00,15946\n2014-08-19 11:00:00,15205\n2014-08-19 11:30:00,16175\n2014-08-19 12:00:00,16790\n2014-08-19 12:30:00,17284\n2014-08-19 13:00:00,16153\n2014-08-19 13:30:00,17673\n2014-08-19 14:00:00,18157\n2014-08-19 14:30:00,17858\n2014-08-19 15:00:00,17087\n2014-08-19 15:30:00,16385\n2014-08-19 16:00:00,15063\n2014-08-19 16:30:00,13909\n2014-08-19 17:00:00,16462\n2014-08-19 17:30:00,18855\n2014-08-19 18:00:00,21606\n2014-08-19 18:30:00,22910\n2014-08-19 19:00:00,23691\n2014-08-19 19:30:00,22752\n2014-08-19 20:00:00,22414\n2014-08-19 20:30:00,21896\n2014-08-19 21:00:00,21887\n2014-08-19 21:30:00,21845\n2014-08-19 22:00:00,21436\n2014-08-19 22:30:00,19787\n2014-08-19 23:00:00,18369\n2014-08-19 23:30:00,15132\n2014-08-20 00:00:00,12168\n2014-08-20 00:30:00,9288\n2014-08-20 01:00:00,7465\n2014-08-20 01:30:00,5656\n2014-08-20 02:00:00,4693\n2014-08-20 02:30:00,3694\n2014-08-20 03:00:00,3027\n2014-08-20 03:30:00,2587\n2014-08-20 04:00:00,2733\n2014-08-20 04:30:00,2216\n2014-08-20 05:00:00,2289\n2014-08-20 05:30:00,3937\n2014-08-20 06:00:00,5718\n2014-08-20 06:30:00,10053\n2014-08-20 07:00:00,12154\n2014-08-20 07:30:00,15289\n2014-08-20 08:00:00,17424\n2014-08-20 08:30:00,19403\n2014-08-20 09:00:00,18488\n2014-08-20 09:30:00,17881\n2014-08-20 10:00:00,16397\n2014-08-20 10:30:00,16319\n2014-08-20 11:00:00,15923\n2014-08-20 11:30:00,17200\n2014-08-20 12:00:00,17140\n2014-08-20 12:30:00,17422\n2014-08-20 13:00:00,17393\n2014-08-20 13:30:00,17612\n2014-08-20 14:00:00,17475\n2014-08-20 14:30:00,17685\n2014-08-20 15:00:00,16765\n2014-08-20 15:30:00,15701\n2014-08-20 16:00:00,14276\n2014-08-20 16:30:00,13715\n2014-08-20 17:00:00,15577\n2014-08-20 17:30:00,18831\n2014-08-20 18:00:00,21971\n2014-08-20 18:30:00,23814\n2014-08-20 19:00:00,24147\n2014-08-20 19:30:00,23300\n2014-08-20 20:00:00,23237\n2014-08-20 20:30:00,23018\n2014-08-20 21:00:00,22814\n2014-08-20 21:30:00,22716\n2014-08-20 22:00:00,22838\n2014-08-20 22:30:00,21546\n2014-08-20 23:00:00,19205\n2014-08-20 23:30:00,17041\n2014-08-21 00:00:00,14569\n2014-08-21 00:30:00,11396\n2014-08-21 01:00:00,8719\n2014-08-21 01:30:00,6717\n2014-08-21 02:00:00,5410\n2014-08-21 02:30:00,4458\n2014-08-21 03:00:00,3703\n2014-08-21 03:30:00,3166\n2014-08-21 04:00:00,3256\n2014-08-21 04:30:00,2805\n2014-08-21 05:00:00,3067\n2014-08-21 05:30:00,4424\n2014-08-21 06:00:00,6076\n2014-08-21 06:30:00,10251\n2014-08-21 07:00:00,12400\n2014-08-21 07:30:00,15229\n2014-08-21 08:00:00,17252\n2014-08-21 08:30:00,19332\n2014-08-21 09:00:00,18249\n2014-08-21 09:30:00,18059\n2014-08-21 10:00:00,15889\n2014-08-21 10:30:00,16234\n2014-08-21 11:00:00,15730\n2014-08-21 11:30:00,16578\n2014-08-21 12:00:00,17363\n2014-08-21 12:30:00,16708\n2014-08-21 13:00:00,16809\n2014-08-21 13:30:00,17193\n2014-08-21 14:00:00,18105\n2014-08-21 14:30:00,19035\n2014-08-21 15:00:00,17230\n2014-08-21 15:30:00,15928\n2014-08-21 16:00:00,14180\n2014-08-21 16:30:00,13252\n2014-08-21 17:00:00,15256\n2014-08-21 17:30:00,17773\n2014-08-21 18:00:00,21104\n2014-08-21 18:30:00,23557\n2014-08-21 19:00:00,24797\n2014-08-21 19:30:00,24794\n2014-08-21 20:00:00,24154\n2014-08-21 20:30:00,24501\n2014-08-21 21:00:00,24042\n2014-08-21 21:30:00,24125\n2014-08-21 22:00:00,23970\n2014-08-21 22:30:00,25949\n2014-08-21 23:00:00,25094\n2014-08-21 23:30:00,23295\n2014-08-22 00:00:00,20552\n2014-08-22 00:30:00,16266\n2014-08-22 01:00:00,13365\n2014-08-22 01:30:00,10287\n2014-08-22 02:00:00,7901\n2014-08-22 02:30:00,6235\n2014-08-22 03:00:00,4869\n2014-08-22 03:30:00,3995\n2014-08-22 04:00:00,3734\n2014-08-22 04:30:00,3190\n2014-08-22 05:00:00,2878\n2014-08-22 05:30:00,4020\n2014-08-22 06:00:00,6062\n2014-08-22 06:30:00,9502\n2014-08-22 07:00:00,11446\n2014-08-22 07:30:00,13665\n2014-08-22 08:00:00,15257\n2014-08-22 08:30:00,17391\n2014-08-22 09:00:00,16922\n2014-08-22 09:30:00,16227\n2014-08-22 10:00:00,15185\n2014-08-22 10:30:00,15390\n2014-08-22 11:00:00,14725\n2014-08-22 11:30:00,15415\n2014-08-22 12:00:00,15729\n2014-08-22 12:30:00,16131\n2014-08-22 13:00:00,16058\n2014-08-22 13:30:00,16015\n2014-08-22 14:00:00,16749\n2014-08-22 14:30:00,16857\n2014-08-22 15:00:00,16588\n2014-08-22 15:30:00,15430\n2014-08-22 16:00:00,14186\n2014-08-22 16:30:00,13756\n2014-08-22 17:00:00,15596\n2014-08-22 17:30:00,17743\n2014-08-22 18:00:00,19439\n2014-08-22 18:30:00,21047\n2014-08-22 19:00:00,22647\n2014-08-22 19:30:00,21734\n2014-08-22 20:00:00,21394\n2014-08-22 20:30:00,20208\n2014-08-22 21:00:00,20329\n2014-08-22 21:30:00,20221\n2014-08-22 22:00:00,20945\n2014-08-22 22:30:00,22327\n2014-08-22 23:00:00,22765\n2014-08-22 23:30:00,22852\n2014-08-23 00:00:00,22726\n2014-08-23 00:30:00,21079\n2014-08-23 01:00:00,19166\n2014-08-23 01:30:00,17719\n2014-08-23 02:00:00,16471\n2014-08-23 02:30:00,14158\n2014-08-23 03:00:00,12730\n2014-08-23 03:30:00,10984\n2014-08-23 04:00:00,9409\n2014-08-23 04:30:00,5667\n2014-08-23 05:00:00,3879\n2014-08-23 05:30:00,3398\n2014-08-23 06:00:00,3683\n2014-08-23 06:30:00,4437\n2014-08-23 07:00:00,4732\n2014-08-23 07:30:00,6130\n2014-08-23 08:00:00,6492\n2014-08-23 08:30:00,8397\n2014-08-23 09:00:00,9673\n2014-08-23 09:30:00,11493\n2014-08-23 10:00:00,11723\n2014-08-23 10:30:00,14060\n2014-08-23 11:00:00,14204\n2014-08-23 11:30:00,15542\n2014-08-23 12:00:00,15446\n2014-08-23 12:30:00,15993\n2014-08-23 13:00:00,16206\n2014-08-23 13:30:00,16531\n2014-08-23 14:00:00,15717\n2014-08-23 14:30:00,15964\n2014-08-23 15:00:00,15868\n2014-08-23 15:30:00,16012\n2014-08-23 16:00:00,16200\n2014-08-23 16:30:00,15778\n2014-08-23 17:00:00,16268\n2014-08-23 17:30:00,18160\n2014-08-23 18:00:00,19155\n2014-08-23 18:30:00,20365\n2014-08-23 19:00:00,21278\n2014-08-23 19:30:00,20466\n2014-08-23 20:00:00,20057\n2014-08-23 20:30:00,23457\n2014-08-23 21:00:00,18798\n2014-08-23 21:30:00,19387\n2014-08-23 22:00:00,19998\n2014-08-23 22:30:00,21426\n2014-08-23 23:00:00,22449\n2014-08-23 23:30:00,22640\n2014-08-24 00:00:00,22666\n2014-08-24 00:30:00,21430\n2014-08-24 01:00:00,20015\n2014-08-24 01:30:00,18791\n2014-08-24 02:00:00,17683\n2014-08-24 02:30:00,15830\n2014-08-24 03:00:00,13862\n2014-08-24 03:30:00,11961\n2014-08-24 04:00:00,10153\n2014-08-24 04:30:00,6051\n2014-08-24 05:00:00,3848\n2014-08-24 05:30:00,2948\n2014-08-24 06:00:00,3143\n2014-08-24 06:30:00,3505\n2014-08-24 07:00:00,3812\n2014-08-24 07:30:00,4939\n2014-08-24 08:00:00,5442\n2014-08-24 08:30:00,6630\n2014-08-24 09:00:00,7744\n2014-08-24 09:30:00,10198\n2014-08-24 10:00:00,11041\n2014-08-24 10:30:00,13200\n2014-08-24 11:00:00,14107\n2014-08-24 11:30:00,15069\n2014-08-24 12:00:00,15638\n2014-08-24 12:30:00,15464\n2014-08-24 13:00:00,15901\n2014-08-24 13:30:00,16001\n2014-08-24 14:00:00,16492\n2014-08-24 14:30:00,16166\n2014-08-24 15:00:00,15531\n2014-08-24 15:30:00,15655\n2014-08-24 16:00:00,15040\n2014-08-24 16:30:00,15083\n2014-08-24 17:00:00,16229\n2014-08-24 17:30:00,17409\n2014-08-24 18:00:00,17288\n2014-08-24 18:30:00,17242\n2014-08-24 19:00:00,17129\n2014-08-24 19:30:00,16103\n2014-08-24 20:00:00,16485\n2014-08-24 20:30:00,16190\n2014-08-24 21:00:00,15500\n2014-08-24 21:30:00,15128\n2014-08-24 22:00:00,14489\n2014-08-24 22:30:00,13947\n2014-08-24 23:00:00,12525\n2014-08-24 23:30:00,11899\n2014-08-25 00:00:00,9192\n2014-08-25 00:30:00,6886\n2014-08-25 01:00:00,4888\n2014-08-25 01:30:00,4138\n2014-08-25 02:00:00,3366\n2014-08-25 02:30:00,2698\n2014-08-25 03:00:00,2290\n2014-08-25 03:30:00,2009\n2014-08-25 04:00:00,2265\n2014-08-25 04:30:00,2213\n2014-08-25 05:00:00,2450\n2014-08-25 05:30:00,3829\n2014-08-25 06:00:00,5933\n2014-08-25 06:30:00,9356\n2014-08-25 07:00:00,11482\n2014-08-25 07:30:00,13178\n2014-08-25 08:00:00,14803\n2014-08-25 08:30:00,16826\n2014-08-25 09:00:00,16649\n2014-08-25 09:30:00,15422\n2014-08-25 10:00:00,13996\n2014-08-25 10:30:00,13682\n2014-08-25 11:00:00,13297\n2014-08-25 11:30:00,14284\n2014-08-25 12:00:00,14435\n2014-08-25 12:30:00,14612\n2014-08-25 13:00:00,14814\n2014-08-25 13:30:00,15398\n2014-08-25 14:00:00,15511\n2014-08-25 14:30:00,15828\n2014-08-25 15:00:00,15396\n2014-08-25 15:30:00,15109\n2014-08-25 16:00:00,14787\n2014-08-25 16:30:00,14532\n2014-08-25 17:00:00,16387\n2014-08-25 17:30:00,18242\n2014-08-25 18:00:00,19715\n2014-08-25 18:30:00,20288\n2014-08-25 19:00:00,20761\n2014-08-25 19:30:00,19466\n2014-08-25 20:00:00,19670\n2014-08-25 20:30:00,18802\n2014-08-25 21:00:00,18709\n2014-08-25 21:30:00,17186\n2014-08-25 22:00:00,16500\n2014-08-25 22:30:00,15616\n2014-08-25 23:00:00,13902\n2014-08-25 23:30:00,11077\n2014-08-26 00:00:00,9618\n2014-08-26 00:30:00,7193\n2014-08-26 01:00:00,5665\n2014-08-26 01:30:00,4149\n2014-08-26 02:00:00,3502\n2014-08-26 02:30:00,2634\n2014-08-26 03:00:00,2100\n2014-08-26 03:30:00,1985\n2014-08-26 04:00:00,2053\n2014-08-26 04:30:00,1841\n2014-08-26 05:00:00,1909\n2014-08-26 05:30:00,3547\n2014-08-26 06:00:00,5829\n2014-08-26 06:30:00,9599\n2014-08-26 07:00:00,11323\n2014-08-26 07:30:00,13923\n2014-08-26 08:00:00,16029\n2014-08-26 08:30:00,18308\n2014-08-26 09:00:00,17153\n2014-08-26 09:30:00,16723\n2014-08-26 10:00:00,15360\n2014-08-26 10:30:00,16066\n2014-08-26 11:00:00,14643\n2014-08-26 11:30:00,15960\n2014-08-26 12:00:00,16351\n2014-08-26 12:30:00,16173\n2014-08-26 13:00:00,15659\n2014-08-26 13:30:00,17346\n2014-08-26 14:00:00,17145\n2014-08-26 14:30:00,16896\n2014-08-26 15:00:00,16746\n2014-08-26 15:30:00,15797\n2014-08-26 16:00:00,14202\n2014-08-26 16:30:00,14083\n2014-08-26 17:00:00,16074\n2014-08-26 17:30:00,18329\n2014-08-26 18:00:00,20961\n2014-08-26 18:30:00,22545\n2014-08-26 19:00:00,22067\n2014-08-26 19:30:00,21416\n2014-08-26 20:00:00,21484\n2014-08-26 20:30:00,20731\n2014-08-26 21:00:00,20969\n2014-08-26 21:30:00,20820\n2014-08-26 22:00:00,19650\n2014-08-26 22:30:00,18240\n2014-08-26 23:00:00,17133\n2014-08-26 23:30:00,14907\n2014-08-27 00:00:00,11703\n2014-08-27 00:30:00,8521\n2014-08-27 01:00:00,6962\n2014-08-27 01:30:00,5451\n2014-08-27 02:00:00,4439\n2014-08-27 02:30:00,3436\n2014-08-27 03:00:00,2741\n2014-08-27 03:30:00,2311\n2014-08-27 04:00:00,2532\n2014-08-27 04:30:00,2066\n2014-08-27 05:00:00,2111\n2014-08-27 05:30:00,3623\n2014-08-27 06:00:00,5719\n2014-08-27 06:30:00,9376\n2014-08-27 07:00:00,11971\n2014-08-27 07:30:00,14673\n2014-08-27 08:00:00,16545\n2014-08-27 08:30:00,18678\n2014-08-27 09:00:00,17655\n2014-08-27 09:30:00,17485\n2014-08-27 10:00:00,15834\n2014-08-27 10:30:00,15703\n2014-08-27 11:00:00,15816\n2014-08-27 11:30:00,16870\n2014-08-27 12:00:00,17123\n2014-08-27 12:30:00,16841\n2014-08-27 13:00:00,16700\n2014-08-27 13:30:00,17722\n2014-08-27 14:00:00,17849\n2014-08-27 14:30:00,18221\n2014-08-27 15:00:00,17208\n2014-08-27 15:30:00,16318\n2014-08-27 16:00:00,14910\n2014-08-27 16:30:00,14145\n2014-08-27 17:00:00,16330\n2014-08-27 17:30:00,19328\n2014-08-27 18:00:00,21226\n2014-08-27 18:30:00,23109\n2014-08-27 19:00:00,24206\n2014-08-27 19:30:00,23297\n2014-08-27 20:00:00,23493\n2014-08-27 20:30:00,22794\n2014-08-27 21:00:00,22502\n2014-08-27 21:30:00,22337\n2014-08-27 22:00:00,24446\n2014-08-27 22:30:00,20929\n2014-08-27 23:00:00,17937\n2014-08-27 23:30:00,16036\n2014-08-28 00:00:00,13547\n2014-08-28 00:30:00,10363\n2014-08-28 01:00:00,8553\n2014-08-28 01:30:00,6457\n2014-08-28 02:00:00,5248\n2014-08-28 02:30:00,3879\n2014-08-28 03:00:00,3173\n2014-08-28 03:30:00,2653\n2014-08-28 04:00:00,2858\n2014-08-28 04:30:00,2244\n2014-08-28 05:00:00,2312\n2014-08-28 05:30:00,3859\n2014-08-28 06:00:00,5772\n2014-08-28 06:30:00,9391\n2014-08-28 07:00:00,11375\n2014-08-28 07:30:00,14319\n2014-08-28 08:00:00,16103\n2014-08-28 08:30:00,18835\n2014-08-28 09:00:00,17891\n2014-08-28 09:30:00,17000\n2014-08-28 10:00:00,15534\n2014-08-28 10:30:00,15916\n2014-08-28 11:00:00,15153\n2014-08-28 11:30:00,16440\n2014-08-28 12:00:00,16424\n2014-08-28 12:30:00,16093\n2014-08-28 13:00:00,16178\n2014-08-28 13:30:00,17050\n2014-08-28 14:00:00,16795\n2014-08-28 14:30:00,17547\n2014-08-28 15:00:00,16769\n2014-08-28 15:30:00,15701\n2014-08-28 16:00:00,14067\n2014-08-28 16:30:00,13534\n2014-08-28 17:00:00,15939\n2014-08-28 17:30:00,18560\n2014-08-28 18:00:00,21029\n2014-08-28 18:30:00,22181\n2014-08-28 19:00:00,22860\n2014-08-28 19:30:00,22742\n2014-08-28 20:00:00,22569\n2014-08-28 20:30:00,22184\n2014-08-28 21:00:00,21926\n2014-08-28 21:30:00,22510\n2014-08-28 22:00:00,22350\n2014-08-28 22:30:00,21756\n2014-08-28 23:00:00,20994\n2014-08-28 23:30:00,19084\n2014-08-29 00:00:00,16702\n2014-08-29 00:30:00,13985\n2014-08-29 01:00:00,11632\n2014-08-29 01:30:00,9900\n2014-08-29 02:00:00,8443\n2014-08-29 02:30:00,6546\n2014-08-29 03:00:00,5270\n2014-08-29 03:30:00,4521\n2014-08-29 04:00:00,4369\n2014-08-29 04:30:00,3409\n2014-08-29 05:00:00,2967\n2014-08-29 05:30:00,4444\n2014-08-29 06:00:00,5712\n2014-08-29 06:30:00,9008\n2014-08-29 07:00:00,10312\n2014-08-29 07:30:00,12809\n2014-08-29 08:00:00,13491\n2014-08-29 08:30:00,16417\n2014-08-29 09:00:00,15906\n2014-08-29 09:30:00,15249\n2014-08-29 10:00:00,14367\n2014-08-29 10:30:00,14667\n2014-08-29 11:00:00,14738\n2014-08-29 11:30:00,16134\n2014-08-29 12:00:00,16343\n2014-08-29 12:30:00,15908\n2014-08-29 13:00:00,16700\n2014-08-29 13:30:00,16712\n2014-08-29 14:00:00,17394\n2014-08-29 14:30:00,17680\n2014-08-29 15:00:00,17495\n2014-08-29 15:30:00,15984\n2014-08-29 16:00:00,14946\n2014-08-29 16:30:00,14572\n2014-08-29 17:00:00,16880\n2014-08-29 17:30:00,19398\n2014-08-29 18:00:00,20797\n2014-08-29 18:30:00,21449\n2014-08-29 19:00:00,22077\n2014-08-29 19:30:00,21483\n2014-08-29 20:00:00,20415\n2014-08-29 20:30:00,20436\n2014-08-29 21:00:00,19315\n2014-08-29 21:30:00,19328\n2014-08-29 22:00:00,19660\n2014-08-29 22:30:00,21469\n2014-08-29 23:00:00,20853\n2014-08-29 23:30:00,21452\n2014-08-30 00:00:00,20564\n2014-08-30 00:30:00,19267\n2014-08-30 01:00:00,17439\n2014-08-30 01:30:00,14848\n2014-08-30 02:00:00,13900\n2014-08-30 02:30:00,12731\n2014-08-30 03:00:00,10776\n2014-08-30 03:30:00,9550\n2014-08-30 04:00:00,8605\n2014-08-30 04:30:00,5547\n2014-08-30 05:00:00,3605\n2014-08-30 05:30:00,3238\n2014-08-30 06:00:00,3520\n2014-08-30 06:30:00,4315\n2014-08-30 07:00:00,5116\n2014-08-30 07:30:00,5918\n2014-08-30 08:00:00,6383\n2014-08-30 08:30:00,8259\n2014-08-30 09:00:00,9430\n2014-08-30 09:30:00,11656\n2014-08-30 10:00:00,11833\n2014-08-30 10:30:00,13393\n2014-08-30 11:00:00,13778\n2014-08-30 11:30:00,15204\n2014-08-30 12:00:00,15367\n2014-08-30 12:30:00,15775\n2014-08-30 13:00:00,16045\n2014-08-30 13:30:00,16499\n2014-08-30 14:00:00,16113\n2014-08-30 14:30:00,16651\n2014-08-30 15:00:00,16507\n2014-08-30 15:30:00,16868\n2014-08-30 16:00:00,15594\n2014-08-30 16:30:00,16037\n2014-08-30 17:00:00,16973\n2014-08-30 17:30:00,18390\n2014-08-30 18:00:00,18681\n2014-08-30 18:30:00,19196\n2014-08-30 19:00:00,19744\n2014-08-30 19:30:00,19564\n2014-08-30 20:00:00,17522\n2014-08-30 20:30:00,17731\n2014-08-30 21:00:00,17364\n2014-08-30 21:30:00,17483\n2014-08-30 22:00:00,18037\n2014-08-30 22:30:00,19559\n2014-08-30 23:00:00,19421\n2014-08-30 23:30:00,19857\n2014-08-31 00:00:00,19205\n2014-08-31 00:30:00,18139\n2014-08-31 01:00:00,16686\n2014-08-31 01:30:00,14841\n2014-08-31 02:00:00,14018\n2014-08-31 02:30:00,12187\n2014-08-31 03:00:00,10536\n2014-08-31 03:30:00,9591\n2014-08-31 04:00:00,8665\n2014-08-31 04:30:00,5317\n2014-08-31 05:00:00,3597\n2014-08-31 05:30:00,2783\n2014-08-31 06:00:00,2587\n2014-08-31 06:30:00,2914\n2014-08-31 07:00:00,3167\n2014-08-31 07:30:00,4212\n2014-08-31 08:00:00,4502\n2014-08-31 08:30:00,5730\n2014-08-31 09:00:00,7102\n2014-08-31 09:30:00,9054\n2014-08-31 10:00:00,10152\n2014-08-31 10:30:00,13059\n2014-08-31 11:00:00,13923\n2014-08-31 11:30:00,14755\n2014-08-31 12:00:00,15186\n2014-08-31 12:30:00,16404\n2014-08-31 13:00:00,16652\n2014-08-31 13:30:00,17446\n2014-08-31 14:00:00,17493\n2014-08-31 14:30:00,17264\n2014-08-31 15:00:00,16546\n2014-08-31 15:30:00,17090\n2014-08-31 16:00:00,17297\n2014-08-31 16:30:00,16546\n2014-08-31 17:00:00,16474\n2014-08-31 17:30:00,16959\n2014-08-31 18:00:00,16567\n2014-08-31 18:30:00,17590\n2014-08-31 19:00:00,17053\n2014-08-31 19:30:00,16561\n2014-08-31 20:00:00,16870\n2014-08-31 20:30:00,16514\n2014-08-31 21:00:00,15871\n2014-08-31 21:30:00,15529\n2014-08-31 22:00:00,15049\n2014-08-31 22:30:00,15675\n2014-08-31 23:00:00,15673\n2014-08-31 23:30:00,15524\n2014-09-01 00:00:00,14618\n2014-09-01 00:30:00,12908\n2014-09-01 01:00:00,10842\n2014-09-01 01:30:00,9248\n2014-09-01 02:00:00,8588\n2014-09-01 02:30:00,7631\n2014-09-01 03:00:00,6519\n2014-09-01 03:30:00,5657\n2014-09-01 04:00:00,5214\n2014-09-01 04:30:00,3827\n2014-09-01 05:00:00,2939\n2014-09-01 05:30:00,2872\n2014-09-01 06:00:00,2994\n2014-09-01 06:30:00,3708\n2014-09-01 07:00:00,3547\n2014-09-01 07:30:00,4761\n2014-09-01 08:00:00,5038\n2014-09-01 08:30:00,5875\n2014-09-01 09:00:00,6910\n2014-09-01 09:30:00,8800\n2014-09-01 10:00:00,9782\n2014-09-01 10:30:00,11506\n2014-09-01 11:00:00,12291\n2014-09-01 11:30:00,13600\n2014-09-01 12:00:00,14040\n2014-09-01 12:30:00,15063\n2014-09-01 13:00:00,15073\n2014-09-01 13:30:00,15834\n2014-09-01 14:00:00,16567\n2014-09-01 14:30:00,16955\n2014-09-01 15:00:00,17408\n2014-09-01 15:30:00,16857\n2014-09-01 16:00:00,16002\n2014-09-01 16:30:00,15826\n2014-09-01 17:00:00,16961\n2014-09-01 17:30:00,17779\n2014-09-01 18:00:00,17578\n2014-09-01 18:30:00,17777\n2014-09-01 19:00:00,17764\n2014-09-01 19:30:00,17130\n2014-09-01 20:00:00,16641\n2014-09-01 20:30:00,16884\n2014-09-01 21:00:00,15068\n2014-09-01 21:30:00,15557\n2014-09-01 22:00:00,13766\n2014-09-01 22:30:00,13377\n2014-09-01 23:00:00,11025\n2014-09-01 23:30:00,9707\n2014-09-02 00:00:00,8043\n2014-09-02 00:30:00,5630\n2014-09-02 01:00:00,4347\n2014-09-02 01:30:00,3606\n2014-09-02 02:00:00,2588\n2014-09-02 02:30:00,1969\n2014-09-02 03:00:00,1876\n2014-09-02 03:30:00,1431\n2014-09-02 04:00:00,1752\n2014-09-02 04:30:00,2044\n2014-09-02 05:00:00,2447\n2014-09-02 05:30:00,4617\n2014-09-02 06:00:00,6988\n2014-09-02 06:30:00,11616\n2014-09-02 07:00:00,14774\n2014-09-02 07:30:00,17823\n2014-09-02 08:00:00,18623\n2014-09-02 08:30:00,18814\n2014-09-02 09:00:00,19221\n2014-09-02 09:30:00,18627\n2014-09-02 10:00:00,16650\n2014-09-02 10:30:00,17378\n2014-09-02 11:00:00,16414\n2014-09-02 11:30:00,17230\n2014-09-02 12:00:00,17557\n2014-09-02 12:30:00,18262\n2014-09-02 13:00:00,17698\n2014-09-02 13:30:00,18863\n2014-09-02 14:00:00,18234\n2014-09-02 14:30:00,18514\n2014-09-02 15:00:00,18364\n2014-09-02 15:30:00,17952\n2014-09-02 16:00:00,15781\n2014-09-02 16:30:00,14487\n2014-09-02 17:00:00,16062\n2014-09-02 17:30:00,18952\n2014-09-02 18:00:00,21395\n2014-09-02 18:30:00,23040\n2014-09-02 19:00:00,22890\n2014-09-02 19:30:00,22306\n2014-09-02 20:00:00,21704\n2014-09-02 20:30:00,20543\n2014-09-02 21:00:00,19896\n2014-09-02 21:30:00,19857\n2014-09-02 22:00:00,17841\n2014-09-02 22:30:00,16192\n2014-09-02 23:00:00,14116\n2014-09-02 23:30:00,12865\n2014-09-03 00:00:00,10465\n2014-09-03 00:30:00,8215\n2014-09-03 01:00:00,6481\n2014-09-03 01:30:00,4265\n2014-09-03 02:00:00,3434\n2014-09-03 02:30:00,2726\n2014-09-03 03:00:00,2358\n2014-09-03 03:30:00,2019\n2014-09-03 04:00:00,2137\n2014-09-03 04:30:00,1903\n2014-09-03 05:00:00,2252\n2014-09-03 05:30:00,4206\n2014-09-03 06:00:00,6545\n2014-09-03 06:30:00,11780\n2014-09-03 07:00:00,14707\n2014-09-03 07:30:00,18624\n2014-09-03 08:00:00,19178\n2014-09-03 08:30:00,20265\n2014-09-03 09:00:00,19277\n2014-09-03 09:30:00,19042\n2014-09-03 10:00:00,18108\n2014-09-03 10:30:00,18275\n2014-09-03 11:00:00,17300\n2014-09-03 11:30:00,18631\n2014-09-03 12:00:00,18582\n2014-09-03 12:30:00,18037\n2014-09-03 13:00:00,17899\n2014-09-03 13:30:00,18984\n2014-09-03 14:00:00,18491\n2014-09-03 14:30:00,19072\n2014-09-03 15:00:00,18693\n2014-09-03 15:30:00,17268\n2014-09-03 16:00:00,15918\n2014-09-03 16:30:00,14478\n2014-09-03 17:00:00,16540\n2014-09-03 17:30:00,19765\n2014-09-03 18:00:00,22526\n2014-09-03 18:30:00,23454\n2014-09-03 19:00:00,24380\n2014-09-03 19:30:00,24477\n2014-09-03 20:00:00,24234\n2014-09-03 20:30:00,23319\n2014-09-03 21:00:00,23387\n2014-09-03 21:30:00,22963\n2014-09-03 22:00:00,22006\n2014-09-03 22:30:00,20301\n2014-09-03 23:00:00,18259\n2014-09-03 23:30:00,15608\n2014-09-04 00:00:00,12990\n2014-09-04 00:30:00,10273\n2014-09-04 01:00:00,8434\n2014-09-04 01:30:00,6378\n2014-09-04 02:00:00,5549\n2014-09-04 02:30:00,4131\n2014-09-04 03:00:00,3241\n2014-09-04 03:30:00,2410\n2014-09-04 04:00:00,2804\n2014-09-04 04:30:00,2320\n2014-09-04 05:00:00,2431\n2014-09-04 05:30:00,4222\n2014-09-04 06:00:00,6633\n2014-09-04 06:30:00,12006\n2014-09-04 07:00:00,15589\n2014-09-04 07:30:00,20359\n2014-09-04 08:00:00,20593\n2014-09-04 08:30:00,19590\n2014-09-04 09:00:00,19637\n2014-09-04 09:30:00,19026\n2014-09-04 10:00:00,18629\n2014-09-04 10:30:00,18568\n2014-09-04 11:00:00,18041\n2014-09-04 11:30:00,18695\n2014-09-04 12:00:00,19692\n2014-09-04 12:30:00,19173\n2014-09-04 13:00:00,17824\n2014-09-04 13:30:00,19684\n2014-09-04 14:00:00,20139\n2014-09-04 14:30:00,20320\n2014-09-04 15:00:00,19468\n2014-09-04 15:30:00,17391\n2014-09-04 16:00:00,15218\n2014-09-04 16:30:00,13649\n2014-09-04 17:00:00,16052\n2014-09-04 17:30:00,18987\n2014-09-04 18:00:00,21967\n2014-09-04 18:30:00,24107\n2014-09-04 19:00:00,25260\n2014-09-04 19:30:00,25638\n2014-09-04 20:00:00,26045\n2014-09-04 20:30:00,25045\n2014-09-04 21:00:00,24846\n2014-09-04 21:30:00,24703\n2014-09-04 22:00:00,24863\n2014-09-04 22:30:00,23610\n2014-09-04 23:00:00,21637\n2014-09-04 23:30:00,21643\n2014-09-05 00:00:00,18962\n2014-09-05 00:30:00,15475\n2014-09-05 01:00:00,11955\n2014-09-05 01:30:00,9339\n2014-09-05 02:00:00,7967\n2014-09-05 02:30:00,6372\n2014-09-05 03:00:00,5132\n2014-09-05 03:30:00,4357\n2014-09-05 04:00:00,4305\n2014-09-05 04:30:00,3195\n2014-09-05 05:00:00,2878\n2014-09-05 05:30:00,4762\n2014-09-05 06:00:00,7294\n2014-09-05 06:30:00,12886\n2014-09-05 07:00:00,15820\n2014-09-05 07:30:00,19874\n2014-09-05 08:00:00,20367\n2014-09-05 08:30:00,20091\n2014-09-05 09:00:00,19600\n2014-09-05 09:30:00,19283\n2014-09-05 10:00:00,18413\n2014-09-05 10:30:00,18745\n2014-09-05 11:00:00,17998\n2014-09-05 11:30:00,19325\n2014-09-05 12:00:00,19004\n2014-09-05 12:30:00,18450\n2014-09-05 13:00:00,18029\n2014-09-05 13:30:00,18057\n2014-09-05 14:00:00,19315\n2014-09-05 14:30:00,20057\n2014-09-05 15:00:00,19211\n2014-09-05 15:30:00,16903\n2014-09-05 16:00:00,15288\n2014-09-05 16:30:00,13729\n2014-09-05 17:00:00,17003\n2014-09-05 17:30:00,20142\n2014-09-05 18:00:00,23177\n2014-09-05 18:30:00,25036\n2014-09-05 19:00:00,27337\n2014-09-05 19:30:00,26812\n2014-09-05 20:00:00,26592\n2014-09-05 20:30:00,26243\n2014-09-05 21:00:00,25919\n2014-09-05 21:30:00,25898\n2014-09-05 22:00:00,26603\n2014-09-05 22:30:00,26899\n2014-09-05 23:00:00,26900\n2014-09-05 23:30:00,26763\n2014-09-06 00:00:00,25721\n2014-09-06 00:30:00,24590\n2014-09-06 01:00:00,22118\n2014-09-06 01:30:00,20378\n2014-09-06 02:00:00,19093\n2014-09-06 02:30:00,16717\n2014-09-06 03:00:00,14043\n2014-09-06 03:30:00,12077\n2014-09-06 04:00:00,10212\n2014-09-06 04:30:00,6328\n2014-09-06 05:00:00,4440\n2014-09-06 05:30:00,3603\n2014-09-06 06:00:00,3781\n2014-09-06 06:30:00,4846\n2014-09-06 07:00:00,5444\n2014-09-06 07:30:00,7701\n2014-09-06 08:00:00,8375\n2014-09-06 08:30:00,11334\n2014-09-06 09:00:00,12747\n2014-09-06 09:30:00,15930\n2014-09-06 10:00:00,16567\n2014-09-06 10:30:00,18716\n2014-09-06 11:00:00,18722\n2014-09-06 11:30:00,20103\n2014-09-06 12:00:00,20287\n2014-09-06 12:30:00,21127\n2014-09-06 13:00:00,21259\n2014-09-06 13:30:00,21946\n2014-09-06 14:00:00,21655\n2014-09-06 14:30:00,21830\n2014-09-06 15:00:00,22886\n2014-09-06 15:30:00,20736\n2014-09-06 16:00:00,18209\n2014-09-06 16:30:00,17090\n2014-09-06 17:00:00,19270\n2014-09-06 17:30:00,22270\n2014-09-06 18:00:00,24264\n2014-09-06 18:30:00,25210\n2014-09-06 19:00:00,25976\n2014-09-06 19:30:00,25765\n2014-09-06 20:00:00,24487\n2014-09-06 20:30:00,23499\n2014-09-06 21:00:00,23210\n2014-09-06 21:30:00,23487\n2014-09-06 22:00:00,24515\n2014-09-06 22:30:00,30313\n2014-09-06 23:00:00,30373\n2014-09-06 23:30:00,28464\n2014-09-07 00:00:00,25818\n2014-09-07 00:30:00,24635\n2014-09-07 01:00:00,23410\n2014-09-07 01:30:00,21481\n2014-09-07 02:00:00,19800\n2014-09-07 02:30:00,17674\n2014-09-07 03:00:00,15215\n2014-09-07 03:30:00,13501\n2014-09-07 04:00:00,10896\n2014-09-07 04:30:00,6766\n2014-09-07 05:00:00,4261\n2014-09-07 05:30:00,3415\n2014-09-07 06:00:00,3220\n2014-09-07 06:30:00,4160\n2014-09-07 07:00:00,4345\n2014-09-07 07:30:00,5963\n2014-09-07 08:00:00,6887\n2014-09-07 08:30:00,8834\n2014-09-07 09:00:00,10042\n2014-09-07 09:30:00,13188\n2014-09-07 10:00:00,14600\n2014-09-07 10:30:00,18209\n2014-09-07 11:00:00,18446\n2014-09-07 11:30:00,20350\n2014-09-07 12:00:00,20838\n2014-09-07 12:30:00,22183\n2014-09-07 13:00:00,20582\n2014-09-07 13:30:00,20506\n2014-09-07 14:00:00,20109\n2014-09-07 14:30:00,20198\n2014-09-07 15:00:00,18873\n2014-09-07 15:30:00,19041\n2014-09-07 16:00:00,19295\n2014-09-07 16:30:00,18868\n2014-09-07 17:00:00,18851\n2014-09-07 17:30:00,20518\n2014-09-07 18:00:00,21710\n2014-09-07 18:30:00,20895\n2014-09-07 19:00:00,20761\n2014-09-07 19:30:00,19916\n2014-09-07 20:00:00,19740\n2014-09-07 20:30:00,18975\n2014-09-07 21:00:00,17866\n2014-09-07 21:30:00,17750\n2014-09-07 22:00:00,16820\n2014-09-07 22:30:00,15292\n2014-09-07 23:00:00,13219\n2014-09-07 23:30:00,12246\n2014-09-08 00:00:00,9733\n2014-09-08 00:30:00,7542\n2014-09-08 01:00:00,5518\n2014-09-08 01:30:00,4348\n2014-09-08 02:00:00,3828\n2014-09-08 02:30:00,3083\n2014-09-08 03:00:00,2583\n2014-09-08 03:30:00,2328\n2014-09-08 04:00:00,2523\n2014-09-08 04:30:00,2579\n2014-09-08 05:00:00,2901\n2014-09-08 05:30:00,4963\n2014-09-08 06:00:00,7013\n2014-09-08 06:30:00,11830\n2014-09-08 07:00:00,14665\n2014-09-08 07:30:00,18099\n2014-09-08 08:00:00,18601\n2014-09-08 08:30:00,18329\n2014-09-08 09:00:00,18506\n2014-09-08 09:30:00,17983\n2014-09-08 10:00:00,16869\n2014-09-08 10:30:00,16771\n2014-09-08 11:00:00,16010\n2014-09-08 11:30:00,17370\n2014-09-08 12:00:00,17526\n2014-09-08 12:30:00,17910\n2014-09-08 13:00:00,16565\n2014-09-08 13:30:00,18380\n2014-09-08 14:00:00,18294\n2014-09-08 14:30:00,19585\n2014-09-08 15:00:00,19323\n2014-09-08 15:30:00,18113\n2014-09-08 16:00:00,16472\n2014-09-08 16:30:00,16007\n2014-09-08 17:00:00,18299\n2014-09-08 17:30:00,20385\n2014-09-08 18:00:00,22906\n2014-09-08 18:30:00,24153\n2014-09-08 19:00:00,24545\n2014-09-08 19:30:00,23635\n2014-09-08 20:00:00,23773\n2014-09-08 20:30:00,23212\n2014-09-08 21:00:00,21918\n2014-09-08 21:30:00,21096\n2014-09-08 22:00:00,21563\n2014-09-08 22:30:00,17989\n2014-09-08 23:00:00,15442\n2014-09-08 23:30:00,12815\n2014-09-09 00:00:00,10436\n2014-09-09 00:30:00,8092\n2014-09-09 01:00:00,6061\n2014-09-09 01:30:00,5058\n2014-09-09 02:00:00,4073\n2014-09-09 02:30:00,3310\n2014-09-09 03:00:00,2623\n2014-09-09 03:30:00,2364\n2014-09-09 04:00:00,2333\n2014-09-09 04:30:00,2287\n2014-09-09 05:00:00,2444\n2014-09-09 05:30:00,4427\n2014-09-09 06:00:00,6661\n2014-09-09 06:30:00,12136\n2014-09-09 07:00:00,15910\n2014-09-09 07:30:00,20003\n2014-09-09 08:00:00,19956\n2014-09-09 08:30:00,19897\n2014-09-09 09:00:00,18719\n2014-09-09 09:30:00,18485\n2014-09-09 10:00:00,17235\n2014-09-09 10:30:00,17705\n2014-09-09 11:00:00,17089\n2014-09-09 11:30:00,18334\n2014-09-09 12:00:00,18564\n2014-09-09 12:30:00,18599\n2014-09-09 13:00:00,17715\n2014-09-09 13:30:00,18692\n2014-09-09 14:00:00,19276\n2014-09-09 14:30:00,20557\n2014-09-09 15:00:00,19505\n2014-09-09 15:30:00,16820\n2014-09-09 16:00:00,14005\n2014-09-09 16:30:00,13683\n2014-09-09 17:00:00,16918\n2014-09-09 17:30:00,20051\n2014-09-09 18:00:00,22624\n2014-09-09 18:30:00,23987\n2014-09-09 19:00:00,24069\n2014-09-09 19:30:00,24933\n2014-09-09 20:00:00,24928\n2014-09-09 20:30:00,24390\n2014-09-09 21:00:00,24199\n2014-09-09 21:30:00,24277\n2014-09-09 22:00:00,23154\n2014-09-09 22:30:00,21090\n2014-09-09 23:00:00,18854\n2014-09-09 23:30:00,16194\n2014-09-10 00:00:00,13226\n2014-09-10 00:30:00,9866\n2014-09-10 01:00:00,8085\n2014-09-10 01:30:00,6177\n2014-09-10 02:00:00,5324\n2014-09-10 02:30:00,4177\n2014-09-10 03:00:00,3464\n2014-09-10 03:30:00,2855\n2014-09-10 04:00:00,2850\n2014-09-10 04:30:00,2361\n2014-09-10 05:00:00,2675\n2014-09-10 05:30:00,4589\n2014-09-10 06:00:00,6868\n2014-09-10 06:30:00,12256\n2014-09-10 07:00:00,16024\n2014-09-10 07:30:00,20193\n2014-09-10 08:00:00,20747\n2014-09-10 08:30:00,20007\n2014-09-10 09:00:00,18782\n2014-09-10 09:30:00,18657\n2014-09-10 10:00:00,17331\n2014-09-10 10:30:00,17989\n2014-09-10 11:00:00,17529\n2014-09-10 11:30:00,18953\n2014-09-10 12:00:00,18567\n2014-09-10 12:30:00,17872\n2014-09-10 13:00:00,17411\n2014-09-10 13:30:00,18792\n2014-09-10 14:00:00,18899\n2014-09-10 14:30:00,19548\n2014-09-10 15:00:00,19093\n2014-09-10 15:30:00,16956\n2014-09-10 16:00:00,14987\n2014-09-10 16:30:00,13895\n2014-09-10 17:00:00,17078\n2014-09-10 17:30:00,20224\n2014-09-10 18:00:00,22805\n2014-09-10 18:30:00,24418\n2014-09-10 19:00:00,25720\n2014-09-10 19:30:00,25891\n2014-09-10 20:00:00,26138\n2014-09-10 20:30:00,25149\n2014-09-10 21:00:00,24908\n2014-09-10 21:30:00,24260\n2014-09-10 22:00:00,24620\n2014-09-10 22:30:00,22813\n2014-09-10 23:00:00,20948\n2014-09-10 23:30:00,18271\n2014-09-11 00:00:00,14939\n2014-09-11 00:30:00,11332\n2014-09-11 01:00:00,8890\n2014-09-11 01:30:00,6980\n2014-09-11 02:00:00,5659\n2014-09-11 02:30:00,4679\n2014-09-11 03:00:00,3550\n2014-09-11 03:30:00,2761\n2014-09-11 04:00:00,3009\n2014-09-11 04:30:00,2596\n2014-09-11 05:00:00,2755\n2014-09-11 05:30:00,4554\n2014-09-11 06:00:00,6964\n2014-09-11 06:30:00,12814\n2014-09-11 07:00:00,16360\n2014-09-11 07:30:00,20658\n2014-09-11 08:00:00,21352\n2014-09-11 08:30:00,20521\n2014-09-11 09:00:00,19759\n2014-09-11 09:30:00,19670\n2014-09-11 10:00:00,18301\n2014-09-11 10:30:00,17768\n2014-09-11 11:00:00,16583\n2014-09-11 11:30:00,18179\n2014-09-11 12:00:00,18896\n2014-09-11 12:30:00,18611\n2014-09-11 13:00:00,17662\n2014-09-11 13:30:00,19057\n2014-09-11 14:00:00,18951\n2014-09-11 14:30:00,19997\n2014-09-11 15:00:00,19260\n2014-09-11 15:30:00,17088\n2014-09-11 16:00:00,15367\n2014-09-11 16:30:00,13915\n2014-09-11 17:00:00,17107\n2014-09-11 17:30:00,20299\n2014-09-11 18:00:00,23029\n2014-09-11 18:30:00,24408\n2014-09-11 19:00:00,25778\n2014-09-11 19:30:00,26274\n2014-09-11 20:00:00,26475\n2014-09-11 20:30:00,25326\n2014-09-11 21:00:00,24557\n2014-09-11 21:30:00,24984\n2014-09-11 22:00:00,25001\n2014-09-11 22:30:00,24112\n2014-09-11 23:00:00,23100\n2014-09-11 23:30:00,20158\n2014-09-12 00:00:00,17954\n2014-09-12 00:30:00,14466\n2014-09-12 01:00:00,11632\n2014-09-12 01:30:00,9400\n2014-09-12 02:00:00,7816\n2014-09-12 02:30:00,6678\n2014-09-12 03:00:00,5499\n2014-09-12 03:30:00,4088\n2014-09-12 04:00:00,4312\n2014-09-12 04:30:00,3433\n2014-09-12 05:00:00,3156\n2014-09-12 05:30:00,4545\n2014-09-12 06:00:00,6802\n2014-09-12 06:30:00,11555\n2014-09-12 07:00:00,15447\n2014-09-12 07:30:00,20385\n2014-09-12 08:00:00,20562\n2014-09-12 08:30:00,20191\n2014-09-12 09:00:00,19405\n2014-09-12 09:30:00,18903\n2014-09-12 10:00:00,17251\n2014-09-12 10:30:00,17874\n2014-09-12 11:00:00,17024\n2014-09-12 11:30:00,18267\n2014-09-12 12:00:00,18351\n2014-09-12 12:30:00,17253\n2014-09-12 13:00:00,17098\n2014-09-12 13:30:00,17885\n2014-09-12 14:00:00,18868\n2014-09-12 14:30:00,19352\n2014-09-12 15:00:00,18035\n2014-09-12 15:30:00,15737\n2014-09-12 16:00:00,14420\n2014-09-12 16:30:00,13148\n2014-09-12 17:00:00,16354\n2014-09-12 17:30:00,20087\n2014-09-12 18:00:00,22814\n2014-09-12 18:30:00,25027\n2014-09-12 19:00:00,25983\n2014-09-12 19:30:00,27090\n2014-09-12 20:00:00,26622\n2014-09-12 20:30:00,25560\n2014-09-12 21:00:00,25141\n2014-09-12 21:30:00,25495\n2014-09-12 22:00:00,26737\n2014-09-12 22:30:00,26657\n2014-09-12 23:00:00,27379\n2014-09-12 23:30:00,27284\n2014-09-13 00:00:00,26227\n2014-09-13 00:30:00,24744\n2014-09-13 01:00:00,23304\n2014-09-13 01:30:00,21293\n2014-09-13 02:00:00,19870\n2014-09-13 02:30:00,17657\n2014-09-13 03:00:00,15100\n2014-09-13 03:30:00,12932\n2014-09-13 04:00:00,10574\n2014-09-13 04:30:00,6546\n2014-09-13 05:00:00,4531\n2014-09-13 05:30:00,3807\n2014-09-13 06:00:00,3672\n2014-09-13 06:30:00,5070\n2014-09-13 07:00:00,5484\n2014-09-13 07:30:00,7528\n2014-09-13 08:00:00,8713\n2014-09-13 08:30:00,11686\n2014-09-13 09:00:00,12432\n2014-09-13 09:30:00,16216\n2014-09-13 10:00:00,16126\n2014-09-13 10:30:00,18527\n2014-09-13 11:00:00,18755\n2014-09-13 11:30:00,20352\n2014-09-13 12:00:00,21020\n2014-09-13 12:30:00,20732\n2014-09-13 13:00:00,21345\n2014-09-13 13:30:00,21500\n2014-09-13 14:00:00,20453\n2014-09-13 14:30:00,23821\n2014-09-13 15:00:00,26150\n2014-09-13 15:30:00,24051\n2014-09-13 16:00:00,19433\n2014-09-13 16:30:00,17521\n2014-09-13 17:00:00,19137\n2014-09-13 17:30:00,22602\n2014-09-13 18:00:00,25039\n2014-09-13 18:30:00,25988\n2014-09-13 19:00:00,26920\n2014-09-13 19:30:00,26845\n2014-09-13 20:00:00,26733\n2014-09-13 20:30:00,24954\n2014-09-13 21:00:00,22317\n2014-09-13 21:30:00,22581\n2014-09-13 22:00:00,23544\n2014-09-13 22:30:00,25662\n2014-09-13 23:00:00,26615\n2014-09-13 23:30:00,27542\n2014-09-14 00:00:00,27320\n2014-09-14 00:30:00,25627\n2014-09-14 01:00:00,23964\n2014-09-14 01:30:00,22332\n2014-09-14 02:00:00,20620\n2014-09-14 02:30:00,18567\n2014-09-14 03:00:00,15772\n2014-09-14 03:30:00,13346\n2014-09-14 04:00:00,11616\n2014-09-14 04:30:00,6999\n2014-09-14 05:00:00,4273\n2014-09-14 05:30:00,3568\n2014-09-14 06:00:00,4209\n2014-09-14 06:30:00,4684\n2014-09-14 07:00:00,4527\n2014-09-14 07:30:00,6231\n2014-09-14 08:00:00,7725\n2014-09-14 08:30:00,10159\n2014-09-14 09:00:00,11013\n2014-09-14 09:30:00,14091\n2014-09-14 10:00:00,15480\n2014-09-14 10:30:00,18669\n2014-09-14 11:00:00,18796\n2014-09-14 11:30:00,20213\n2014-09-14 12:00:00,20410\n2014-09-14 12:30:00,21782\n2014-09-14 13:00:00,20634\n2014-09-14 13:30:00,20061\n2014-09-14 14:00:00,19774\n2014-09-14 14:30:00,20069\n2014-09-14 15:00:00,19417\n2014-09-14 15:30:00,19363\n2014-09-14 16:00:00,19206\n2014-09-14 16:30:00,18284\n2014-09-14 17:00:00,19503\n2014-09-14 17:30:00,20621\n2014-09-14 18:00:00,21554\n2014-09-14 18:30:00,21538\n2014-09-14 19:00:00,20589\n2014-09-14 19:30:00,20391\n2014-09-14 20:00:00,19593\n2014-09-14 20:30:00,18439\n2014-09-14 21:00:00,17587\n2014-09-14 21:30:00,17638\n2014-09-14 22:00:00,15698\n2014-09-14 22:30:00,14343\n2014-09-14 23:00:00,12808\n2014-09-14 23:30:00,10827\n2014-09-15 00:00:00,8077\n2014-09-15 00:30:00,6261\n2014-09-15 01:00:00,4724\n2014-09-15 01:30:00,3852\n2014-09-15 02:00:00,3132\n2014-09-15 02:30:00,2606\n2014-09-15 03:00:00,1975\n2014-09-15 03:30:00,1896\n2014-09-15 04:00:00,2310\n2014-09-15 04:30:00,2388\n2014-09-15 05:00:00,2778\n2014-09-15 05:30:00,4775\n2014-09-15 06:00:00,7022\n2014-09-15 06:30:00,11923\n2014-09-15 07:00:00,14969\n2014-09-15 07:30:00,17943\n2014-09-15 08:00:00,18886\n2014-09-15 08:30:00,18711\n2014-09-15 09:00:00,18012\n2014-09-15 09:30:00,17214\n2014-09-15 10:00:00,16337\n2014-09-15 10:30:00,16157\n2014-09-15 11:00:00,15487\n2014-09-15 11:30:00,16741\n2014-09-15 12:00:00,16793\n2014-09-15 12:30:00,16685\n2014-09-15 13:00:00,15824\n2014-09-15 13:30:00,17040\n2014-09-15 14:00:00,17360\n2014-09-15 14:30:00,18501\n2014-09-15 15:00:00,18143\n2014-09-15 15:30:00,16972\n2014-09-15 16:00:00,16098\n2014-09-15 16:30:00,15878\n2014-09-15 17:00:00,18183\n2014-09-15 17:30:00,20482\n2014-09-15 18:00:00,23314\n2014-09-15 18:30:00,24477\n2014-09-15 19:00:00,24387\n2014-09-15 19:30:00,24193\n2014-09-15 20:00:00,24388\n2014-09-15 20:30:00,22725\n2014-09-15 21:00:00,21907\n2014-09-15 21:30:00,21789\n2014-09-15 22:00:00,20289\n2014-09-15 22:30:00,16585\n2014-09-15 23:00:00,14423\n2014-09-15 23:30:00,12432\n2014-09-16 00:00:00,9359\n2014-09-16 00:30:00,7247\n2014-09-16 01:00:00,5659\n2014-09-16 01:30:00,4155\n2014-09-16 02:00:00,3369\n2014-09-16 02:30:00,2617\n2014-09-16 03:00:00,2214\n2014-09-16 03:30:00,1871\n2014-09-16 04:00:00,2101\n2014-09-16 04:30:00,2016\n2014-09-16 05:00:00,2334\n2014-09-16 05:30:00,4141\n2014-09-16 06:00:00,6465\n2014-09-16 06:30:00,11772\n2014-09-16 07:00:00,16219\n2014-09-16 07:30:00,21253\n2014-09-16 08:00:00,22609\n2014-09-16 08:30:00,21527\n2014-09-16 09:00:00,20975\n2014-09-16 09:30:00,19673\n2014-09-16 10:00:00,18065\n2014-09-16 10:30:00,18948\n2014-09-16 11:00:00,18111\n2014-09-16 11:30:00,17622\n2014-09-16 12:00:00,17320\n2014-09-16 12:30:00,16939\n2014-09-16 13:00:00,16404\n2014-09-16 13:30:00,17247\n2014-09-16 14:00:00,17782\n2014-09-16 14:30:00,18554\n2014-09-16 15:00:00,18680\n2014-09-16 15:30:00,16755\n2014-09-16 16:00:00,14825\n2014-09-16 16:30:00,13975\n2014-09-16 17:00:00,17093\n2014-09-16 17:30:00,19977\n2014-09-16 18:00:00,22922\n2014-09-16 18:30:00,24364\n2014-09-16 19:00:00,24630\n2014-09-16 19:30:00,25234\n2014-09-16 20:00:00,24839\n2014-09-16 20:30:00,24161\n2014-09-16 21:00:00,24550\n2014-09-16 21:30:00,23734\n2014-09-16 22:00:00,22366\n2014-09-16 22:30:00,20411\n2014-09-16 23:00:00,17774\n2014-09-16 23:30:00,14027\n2014-09-17 00:00:00,11590\n2014-09-17 00:30:00,8440\n2014-09-17 01:00:00,6881\n2014-09-17 01:30:00,4920\n2014-09-17 02:00:00,4097\n2014-09-17 02:30:00,3159\n2014-09-17 03:00:00,2653\n2014-09-17 03:30:00,2347\n2014-09-17 04:00:00,2387\n2014-09-17 04:30:00,2194\n2014-09-17 05:00:00,2479\n2014-09-17 05:30:00,4554\n2014-09-17 06:00:00,6775\n2014-09-17 06:30:00,12311\n2014-09-17 07:00:00,15989\n2014-09-17 07:30:00,20058\n2014-09-17 08:00:00,20361\n2014-09-17 08:30:00,20172\n2014-09-17 09:00:00,18974\n2014-09-17 09:30:00,17732\n2014-09-17 10:00:00,17336\n2014-09-17 10:30:00,17321\n2014-09-17 11:00:00,16872\n2014-09-17 11:30:00,18295\n2014-09-17 12:00:00,18273\n2014-09-17 12:30:00,17275\n2014-09-17 13:00:00,17095\n2014-09-17 13:30:00,17715\n2014-09-17 14:00:00,18451\n2014-09-17 14:30:00,18612\n2014-09-17 15:00:00,18148\n2014-09-17 15:30:00,16473\n2014-09-17 16:00:00,14474\n2014-09-17 16:30:00,13434\n2014-09-17 17:00:00,16229\n2014-09-17 17:30:00,19852\n2014-09-17 18:00:00,22394\n2014-09-17 18:30:00,24618\n2014-09-17 19:00:00,25838\n2014-09-17 19:30:00,25496\n2014-09-17 20:00:00,24980\n2014-09-17 20:30:00,23545\n2014-09-17 21:00:00,23847\n2014-09-17 21:30:00,24236\n2014-09-17 22:00:00,23551\n2014-09-17 22:30:00,22454\n2014-09-17 23:00:00,20389\n2014-09-17 23:30:00,17673\n2014-09-18 00:00:00,13651\n2014-09-18 00:30:00,10769\n2014-09-18 01:00:00,8102\n2014-09-18 01:30:00,6196\n2014-09-18 02:00:00,5249\n2014-09-18 02:30:00,3850\n2014-09-18 03:00:00,3150\n2014-09-18 03:30:00,2584\n2014-09-18 04:00:00,2770\n2014-09-18 04:30:00,2477\n2014-09-18 05:00:00,2678\n2014-09-18 05:30:00,4506\n2014-09-18 06:00:00,7292\n2014-09-18 06:30:00,12449\n2014-09-18 07:00:00,16418\n2014-09-18 07:30:00,20080\n2014-09-18 08:00:00,20693\n2014-09-18 08:30:00,19988\n2014-09-18 09:00:00,19313\n2014-09-18 09:30:00,18918\n2014-09-18 10:00:00,17790\n2014-09-18 10:30:00,18028\n2014-09-18 11:00:00,17242\n2014-09-18 11:30:00,18279\n2014-09-18 12:00:00,18118\n2014-09-18 12:30:00,17858\n2014-09-18 13:00:00,17635\n2014-09-18 13:30:00,18265\n2014-09-18 14:00:00,18676\n2014-09-18 14:30:00,18686\n2014-09-18 15:00:00,18134\n2014-09-18 15:30:00,15579\n2014-09-18 16:00:00,13635\n2014-09-18 16:30:00,12689\n2014-09-18 17:00:00,15756\n2014-09-18 17:30:00,19691\n2014-09-18 18:00:00,21487\n2014-09-18 18:30:00,22751\n2014-09-18 19:00:00,24126\n2014-09-18 19:30:00,24956\n2014-09-18 20:00:00,26003\n2014-09-18 20:30:00,25167\n2014-09-18 21:00:00,25659\n2014-09-18 21:30:00,25536\n2014-09-18 22:00:00,25761\n2014-09-18 22:30:00,25212\n2014-09-18 23:00:00,23548\n2014-09-18 23:30:00,22005\n2014-09-19 00:00:00,19518\n2014-09-19 00:30:00,15755\n2014-09-19 01:00:00,12747\n2014-09-19 01:30:00,10116\n2014-09-19 02:00:00,8379\n2014-09-19 02:30:00,6566\n2014-09-19 03:00:00,5478\n2014-09-19 03:30:00,4552\n2014-09-19 04:00:00,4546\n2014-09-19 04:30:00,3489\n2014-09-19 05:00:00,3269\n2014-09-19 05:30:00,4799\n2014-09-19 06:00:00,7384\n2014-09-19 06:30:00,11928\n2014-09-19 07:00:00,15434\n2014-09-19 07:30:00,19509\n2014-09-19 08:00:00,19672\n2014-09-19 08:30:00,19287\n2014-09-19 09:00:00,18369\n2014-09-19 09:30:00,18050\n2014-09-19 10:00:00,17306\n2014-09-19 10:30:00,17661\n2014-09-19 11:00:00,17158\n2014-09-19 11:30:00,18215\n2014-09-19 12:00:00,18175\n2014-09-19 12:30:00,17568\n2014-09-19 13:00:00,17079\n2014-09-19 13:30:00,17287\n2014-09-19 14:00:00,17885\n2014-09-19 14:30:00,18287\n2014-09-19 15:00:00,17782\n2014-09-19 15:30:00,16021\n2014-09-19 16:00:00,14205\n2014-09-19 16:30:00,12834\n2014-09-19 17:00:00,16332\n2014-09-19 17:30:00,19704\n2014-09-19 18:00:00,22931\n2014-09-19 18:30:00,25328\n2014-09-19 19:00:00,26188\n2014-09-19 19:30:00,27541\n2014-09-19 20:00:00,26811\n2014-09-19 20:30:00,26093\n2014-09-19 21:00:00,26091\n2014-09-19 21:30:00,26247\n2014-09-19 22:00:00,27090\n2014-09-19 22:30:00,27681\n2014-09-19 23:00:00,27159\n2014-09-19 23:30:00,26816\n2014-09-20 00:00:00,25251\n2014-09-20 00:30:00,23375\n2014-09-20 01:00:00,21806\n2014-09-20 01:30:00,20635\n2014-09-20 02:00:00,19322\n2014-09-20 02:30:00,16841\n2014-09-20 03:00:00,14744\n2014-09-20 03:30:00,12309\n2014-09-20 04:00:00,10242\n2014-09-20 04:30:00,6470\n2014-09-20 05:00:00,4374\n2014-09-20 05:30:00,3435\n2014-09-20 06:00:00,3789\n2014-09-20 06:30:00,4454\n2014-09-20 07:00:00,5381\n2014-09-20 07:30:00,7585\n2014-09-20 08:00:00,8782\n2014-09-20 08:30:00,11824\n2014-09-20 09:00:00,12587\n2014-09-20 09:30:00,15795\n2014-09-20 10:00:00,16088\n2014-09-20 10:30:00,18430\n2014-09-20 11:00:00,18543\n2014-09-20 11:30:00,20332\n2014-09-20 12:00:00,19797\n2014-09-20 12:30:00,20601\n2014-09-20 13:00:00,20823\n2014-09-20 13:30:00,21182\n2014-09-20 14:00:00,20742\n2014-09-20 14:30:00,20477\n2014-09-20 15:00:00,20654\n2014-09-20 15:30:00,20386\n2014-09-20 16:00:00,18174\n2014-09-20 16:30:00,16690\n2014-09-20 17:00:00,18151\n2014-09-20 17:30:00,21330\n2014-09-20 18:00:00,23268\n2014-09-20 18:30:00,25025\n2014-09-20 19:00:00,25816\n2014-09-20 19:30:00,25694\n2014-09-20 20:00:00,24693\n2014-09-20 20:30:00,24187\n2014-09-20 21:00:00,23820\n2014-09-20 21:30:00,24549\n2014-09-20 22:00:00,25442\n2014-09-20 22:30:00,25914\n2014-09-20 23:00:00,26329\n2014-09-20 23:30:00,26618\n2014-09-21 00:00:00,26477\n2014-09-21 00:30:00,25461\n2014-09-21 01:00:00,25371\n2014-09-21 01:30:00,21726\n2014-09-21 02:00:00,20737\n2014-09-21 02:30:00,18852\n2014-09-21 03:00:00,16474\n2014-09-21 03:30:00,13647\n2014-09-21 04:00:00,11793\n2014-09-21 04:30:00,7142\n2014-09-21 05:00:00,4611\n2014-09-21 05:30:00,3474\n2014-09-21 06:00:00,4131\n2014-09-21 06:30:00,4395\n2014-09-21 07:00:00,4443\n2014-09-21 07:30:00,6155\n2014-09-21 08:00:00,6827\n2014-09-21 08:30:00,9510\n2014-09-21 09:00:00,10785\n2014-09-21 09:30:00,13570\n2014-09-21 10:00:00,14691\n2014-09-21 10:30:00,17071\n2014-09-21 11:00:00,17457\n2014-09-21 11:30:00,17961\n2014-09-21 12:00:00,17900\n2014-09-21 12:30:00,18347\n2014-09-21 13:00:00,17302\n2014-09-21 13:30:00,16009\n2014-09-21 14:00:00,15427\n2014-09-21 14:30:00,14986\n2014-09-21 15:00:00,14381\n2014-09-21 15:30:00,13763\n2014-09-21 16:00:00,13163\n2014-09-21 16:30:00,11940\n2014-09-21 17:00:00,13536\n2014-09-21 17:30:00,15175\n2014-09-21 18:00:00,16406\n2014-09-21 18:30:00,17318\n2014-09-21 19:00:00,17588\n2014-09-21 19:30:00,17895\n2014-09-21 20:00:00,18084\n2014-09-21 20:30:00,16972\n2014-09-21 21:00:00,16389\n2014-09-21 21:30:00,15846\n2014-09-21 22:00:00,15329\n2014-09-21 22:30:00,14446\n2014-09-21 23:00:00,12721\n2014-09-21 23:30:00,10826\n2014-09-22 00:00:00,9067\n2014-09-22 00:30:00,6546\n2014-09-22 01:00:00,4580\n2014-09-22 01:30:00,3654\n2014-09-22 02:00:00,3137\n2014-09-22 02:30:00,2610\n2014-09-22 03:00:00,2061\n2014-09-22 03:30:00,1959\n2014-09-22 04:00:00,2356\n2014-09-22 04:30:00,2400\n2014-09-22 05:00:00,2911\n2014-09-22 05:30:00,4833\n2014-09-22 06:00:00,7398\n2014-09-22 06:30:00,11809\n2014-09-22 07:00:00,14495\n2014-09-22 07:30:00,16812\n2014-09-22 08:00:00,17569\n2014-09-22 08:30:00,16738\n2014-09-22 09:00:00,16612\n2014-09-22 09:30:00,15702\n2014-09-22 10:00:00,14817\n2014-09-22 10:30:00,14668\n2014-09-22 11:00:00,14458\n2014-09-22 11:30:00,15475\n2014-09-22 12:00:00,15539\n2014-09-22 12:30:00,15345\n2014-09-22 13:00:00,15222\n2014-09-22 13:30:00,15213\n2014-09-22 14:00:00,16167\n2014-09-22 14:30:00,16210\n2014-09-22 15:00:00,16393\n2014-09-22 15:30:00,14797\n2014-09-22 16:00:00,13755\n2014-09-22 16:30:00,13960\n2014-09-22 17:00:00,16248\n2014-09-22 17:30:00,18272\n2014-09-22 18:00:00,20440\n2014-09-22 18:30:00,21524\n2014-09-22 19:00:00,21828\n2014-09-22 19:30:00,22825\n2014-09-22 20:00:00,22647\n2014-09-22 20:30:00,22210\n2014-09-22 21:00:00,22426\n2014-09-22 21:30:00,20839\n2014-09-22 22:00:00,20239\n2014-09-22 22:30:00,18144\n2014-09-22 23:00:00,15459\n2014-09-22 23:30:00,13766\n2014-09-23 00:00:00,11187\n2014-09-23 00:30:00,8959\n2014-09-23 01:00:00,7101\n2014-09-23 01:30:00,4710\n2014-09-23 02:00:00,3571\n2014-09-23 02:30:00,2765\n2014-09-23 03:00:00,2101\n2014-09-23 03:30:00,1867\n2014-09-23 04:00:00,2126\n2014-09-23 04:30:00,2082\n2014-09-23 05:00:00,2393\n2014-09-23 05:30:00,4443\n2014-09-23 06:00:00,7297\n2014-09-23 06:30:00,12466\n2014-09-23 07:00:00,15547\n2014-09-23 07:30:00,18160\n2014-09-23 08:00:00,18295\n2014-09-23 08:30:00,17794\n2014-09-23 09:00:00,16541\n2014-09-23 09:30:00,16239\n2014-09-23 10:00:00,15239\n2014-09-23 10:30:00,15153\n2014-09-23 11:00:00,14168\n2014-09-23 11:30:00,14872\n2014-09-23 12:00:00,15293\n2014-09-23 12:30:00,14971\n2014-09-23 13:00:00,14359\n2014-09-23 13:30:00,14486\n2014-09-23 14:00:00,14471\n2014-09-23 14:30:00,14920\n2014-09-23 15:00:00,14411\n2014-09-23 15:30:00,13573\n2014-09-23 16:00:00,11876\n2014-09-23 16:30:00,11040\n2014-09-23 17:00:00,13441\n2014-09-23 17:30:00,16163\n2014-09-23 18:00:00,19059\n2014-09-23 18:30:00,19621\n2014-09-23 19:00:00,21616\n2014-09-23 19:30:00,23427\n2014-09-23 20:00:00,23735\n2014-09-23 20:30:00,23354\n2014-09-23 21:00:00,23391\n2014-09-23 21:30:00,23228\n2014-09-23 22:00:00,21882\n2014-09-23 22:30:00,21221\n2014-09-23 23:00:00,18922\n2014-09-23 23:30:00,15473\n2014-09-24 00:00:00,12457\n2014-09-24 00:30:00,9497\n2014-09-24 01:00:00,7073\n2014-09-24 01:30:00,5496\n2014-09-24 02:00:00,4477\n2014-09-24 02:30:00,3527\n2014-09-24 03:00:00,2971\n2014-09-24 03:30:00,2660\n2014-09-24 04:00:00,2497\n2014-09-24 04:30:00,2250\n2014-09-24 05:00:00,2594\n2014-09-24 05:30:00,4316\n2014-09-24 06:00:00,7112\n2014-09-24 06:30:00,12119\n2014-09-24 07:00:00,15652\n2014-09-24 07:30:00,18565\n2014-09-24 08:00:00,18437\n2014-09-24 08:30:00,17831\n2014-09-24 09:00:00,17103\n2014-09-24 09:30:00,16446\n2014-09-24 10:00:00,15593\n2014-09-24 10:30:00,15353\n2014-09-24 11:00:00,15105\n2014-09-24 11:30:00,16058\n2014-09-24 12:00:00,16475\n2014-09-24 12:30:00,16226\n2014-09-24 13:00:00,15766\n2014-09-24 13:30:00,16242\n2014-09-24 14:00:00,16976\n2014-09-24 14:30:00,17117\n2014-09-24 15:00:00,16910\n2014-09-24 15:30:00,14845\n2014-09-24 16:00:00,12840\n2014-09-24 16:30:00,12913\n2014-09-24 17:00:00,15736\n2014-09-24 17:30:00,18396\n2014-09-24 18:00:00,21170\n2014-09-24 18:30:00,21255\n2014-09-24 19:00:00,22014\n2014-09-24 19:30:00,22334\n2014-09-24 20:00:00,21426\n2014-09-24 20:30:00,21152\n2014-09-24 21:00:00,22304\n2014-09-24 21:30:00,22947\n2014-09-24 22:00:00,22195\n2014-09-24 22:30:00,21592\n2014-09-24 23:00:00,18884\n2014-09-24 23:30:00,15885\n2014-09-25 00:00:00,12556\n2014-09-25 00:30:00,10023\n2014-09-25 01:00:00,7320\n2014-09-25 01:30:00,6007\n2014-09-25 02:00:00,4886\n2014-09-25 02:30:00,4068\n2014-09-25 03:00:00,3170\n2014-09-25 03:30:00,2671\n2014-09-25 04:00:00,2844\n2014-09-25 04:30:00,2430\n2014-09-25 05:00:00,2534\n2014-09-25 05:30:00,4193\n2014-09-25 06:00:00,6274\n2014-09-25 06:30:00,11614\n2014-09-25 07:00:00,14471\n2014-09-25 07:30:00,17184\n2014-09-25 08:00:00,18428\n2014-09-25 08:30:00,18257\n2014-09-25 09:00:00,17375\n2014-09-25 09:30:00,18079\n2014-09-25 10:00:00,17902\n2014-09-25 10:30:00,17934\n2014-09-25 11:00:00,16311\n2014-09-25 11:30:00,16460\n2014-09-25 12:00:00,17383\n2014-09-25 12:30:00,16931\n2014-09-25 13:00:00,17236\n2014-09-25 13:30:00,17120\n2014-09-25 14:00:00,16635\n2014-09-25 14:30:00,16048\n2014-09-25 15:00:00,15553\n2014-09-25 15:30:00,14421\n2014-09-25 16:00:00,13456\n2014-09-25 16:30:00,12820\n2014-09-25 17:00:00,16109\n2014-09-25 17:30:00,19198\n2014-09-25 18:00:00,21302\n2014-09-25 18:30:00,22657\n2014-09-25 19:00:00,23276\n2014-09-25 19:30:00,23723\n2014-09-25 20:00:00,23021\n2014-09-25 20:30:00,21823\n2014-09-25 21:00:00,21666\n2014-09-25 21:30:00,22491\n2014-09-25 22:00:00,22004\n2014-09-25 22:30:00,23595\n2014-09-25 23:00:00,22090\n2014-09-25 23:30:00,20296\n2014-09-26 00:00:00,16288\n2014-09-26 00:30:00,13049\n2014-09-26 01:00:00,10504\n2014-09-26 01:30:00,8423\n2014-09-26 02:00:00,7090\n2014-09-26 02:30:00,5920\n2014-09-26 03:00:00,4849\n2014-09-26 03:30:00,4102\n2014-09-26 04:00:00,4093\n2014-09-26 04:30:00,3162\n2014-09-26 05:00:00,2939\n2014-09-26 05:30:00,4012\n2014-09-26 06:00:00,6627\n2014-09-26 06:30:00,10911\n2014-09-26 07:00:00,13043\n2014-09-26 07:30:00,16141\n2014-09-26 08:00:00,16551\n2014-09-26 08:30:00,17566\n2014-09-26 09:00:00,16839\n2014-09-26 09:30:00,16706\n2014-09-26 10:00:00,15946\n2014-09-26 10:30:00,16319\n2014-09-26 11:00:00,15319\n2014-09-26 11:30:00,16456\n2014-09-26 12:00:00,16719\n2014-09-26 12:30:00,16157\n2014-09-26 13:00:00,15798\n2014-09-26 13:30:00,16747\n2014-09-26 14:00:00,16855\n2014-09-26 14:30:00,17441\n2014-09-26 15:00:00,16769\n2014-09-26 15:30:00,15274\n2014-09-26 16:00:00,14150\n2014-09-26 16:30:00,13382\n2014-09-26 17:00:00,16018\n2014-09-26 17:30:00,19412\n2014-09-26 18:00:00,22047\n2014-09-26 18:30:00,23843\n2014-09-26 19:00:00,24816\n2014-09-26 19:30:00,25433\n2014-09-26 20:00:00,25249\n2014-09-26 20:30:00,24492\n2014-09-26 21:00:00,24332\n2014-09-26 21:30:00,24473\n2014-09-26 22:00:00,25932\n2014-09-26 22:30:00,25931\n2014-09-26 23:00:00,26479\n2014-09-26 23:30:00,25878\n2014-09-27 00:00:00,25100\n2014-09-27 00:30:00,23886\n2014-09-27 01:00:00,22982\n2014-09-27 01:30:00,20541\n2014-09-27 02:00:00,18970\n2014-09-27 02:30:00,17433\n2014-09-27 03:00:00,14547\n2014-09-27 03:30:00,12694\n2014-09-27 04:00:00,10374\n2014-09-27 04:30:00,6339\n2014-09-27 05:00:00,4313\n2014-09-27 05:30:00,3538\n2014-09-27 06:00:00,3709\n2014-09-27 06:30:00,5311\n2014-09-27 07:00:00,5974\n2014-09-27 07:30:00,8183\n2014-09-27 08:00:00,8942\n2014-09-27 08:30:00,11805\n2014-09-27 09:00:00,12261\n2014-09-27 09:30:00,15226\n2014-09-27 10:00:00,15802\n2014-09-27 10:30:00,17334\n2014-09-27 11:00:00,18070\n2014-09-27 11:30:00,20105\n2014-09-27 12:00:00,20138\n2014-09-27 12:30:00,19968\n2014-09-27 13:00:00,20411\n2014-09-27 13:30:00,20317\n2014-09-27 14:00:00,19930\n2014-09-27 14:30:00,20502\n2014-09-27 15:00:00,19916\n2014-09-27 15:30:00,19259\n2014-09-27 16:00:00,17572\n2014-09-27 16:30:00,15629\n2014-09-27 17:00:00,17721\n2014-09-27 17:30:00,21308\n2014-09-27 18:00:00,23297\n2014-09-27 18:30:00,24024\n2014-09-27 19:00:00,24925\n2014-09-27 19:30:00,25418\n2014-09-27 20:00:00,23601\n2014-09-27 20:30:00,23219\n2014-09-27 21:00:00,22544\n2014-09-27 21:30:00,23273\n2014-09-27 22:00:00,25131\n2014-09-27 22:30:00,26895\n2014-09-27 23:00:00,27936\n2014-09-27 23:30:00,28113\n2014-09-28 00:00:00,27269\n2014-09-28 00:30:00,26320\n2014-09-28 01:00:00,24571\n2014-09-28 01:30:00,22698\n2014-09-28 02:00:00,20948\n2014-09-28 02:30:00,18561\n2014-09-28 03:00:00,16218\n2014-09-28 03:30:00,13873\n2014-09-28 04:00:00,11926\n2014-09-28 04:30:00,7361\n2014-09-28 05:00:00,4330\n2014-09-28 05:30:00,3681\n2014-09-28 06:00:00,3886\n2014-09-28 06:30:00,4600\n2014-09-28 07:00:00,4930\n2014-09-28 07:30:00,6204\n2014-09-28 08:00:00,7212\n2014-09-28 08:30:00,9136\n2014-09-28 09:00:00,10287\n2014-09-28 09:30:00,12808\n2014-09-28 10:00:00,13952\n2014-09-28 10:30:00,16763\n2014-09-28 11:00:00,17356\n2014-09-28 11:30:00,19238\n2014-09-28 12:00:00,19607\n2014-09-28 12:30:00,20310\n2014-09-28 13:00:00,20033\n2014-09-28 13:30:00,19595\n2014-09-28 14:00:00,19871\n2014-09-28 14:30:00,19819\n2014-09-28 15:00:00,18620\n2014-09-28 15:30:00,18657\n2014-09-28 16:00:00,17688\n2014-09-28 16:30:00,16927\n2014-09-28 17:00:00,17637\n2014-09-28 17:30:00,19283\n2014-09-28 18:00:00,20448\n2014-09-28 18:30:00,19638\n2014-09-28 19:00:00,19509\n2014-09-28 19:30:00,18936\n2014-09-28 20:00:00,18188\n2014-09-28 20:30:00,16594\n2014-09-28 21:00:00,16330\n2014-09-28 21:30:00,16075\n2014-09-28 22:00:00,14977\n2014-09-28 22:30:00,13503\n2014-09-28 23:00:00,12052\n2014-09-28 23:30:00,10779\n2014-09-29 00:00:00,8332\n2014-09-29 00:30:00,6357\n2014-09-29 01:00:00,4958\n2014-09-29 01:30:00,3461\n2014-09-29 02:00:00,3253\n2014-09-29 02:30:00,2493\n2014-09-29 03:00:00,1993\n2014-09-29 03:30:00,1839\n2014-09-29 04:00:00,2275\n2014-09-29 04:30:00,2280\n2014-09-29 05:00:00,2986\n2014-09-29 05:30:00,4608\n2014-09-29 06:00:00,7253\n2014-09-29 06:30:00,11360\n2014-09-29 07:00:00,14157\n2014-09-29 07:30:00,16864\n2014-09-29 08:00:00,17399\n2014-09-29 08:30:00,16671\n2014-09-29 09:00:00,15478\n2014-09-29 09:30:00,14677\n2014-09-29 10:00:00,14935\n2014-09-29 10:30:00,15392\n2014-09-29 11:00:00,15147\n2014-09-29 11:30:00,16345\n2014-09-29 12:00:00,16382\n2014-09-29 12:30:00,15798\n2014-09-29 13:00:00,15584\n2014-09-29 13:30:00,16544\n2014-09-29 14:00:00,17377\n2014-09-29 14:30:00,18345\n2014-09-29 15:00:00,18004\n2014-09-29 15:30:00,16863\n2014-09-29 16:00:00,15714\n2014-09-29 16:30:00,14743\n2014-09-29 17:00:00,17579\n2014-09-29 17:30:00,21604\n2014-09-29 18:00:00,23120\n2014-09-29 18:30:00,22717\n2014-09-29 19:00:00,22757\n2014-09-29 19:30:00,22311\n2014-09-29 20:00:00,21642\n2014-09-29 20:30:00,20568\n2014-09-29 21:00:00,19969\n2014-09-29 21:30:00,19484\n2014-09-29 22:00:00,17993\n2014-09-29 22:30:00,17446\n2014-09-29 23:00:00,13722\n2014-09-29 23:30:00,11549\n2014-09-30 00:00:00,9459\n2014-09-30 00:30:00,6800\n2014-09-30 01:00:00,5323\n2014-09-30 01:30:00,3976\n2014-09-30 02:00:00,3279\n2014-09-30 02:30:00,2617\n2014-09-30 03:00:00,2010\n2014-09-30 03:30:00,1853\n2014-09-30 04:00:00,2150\n2014-09-30 04:30:00,2019\n2014-09-30 05:00:00,2414\n2014-09-30 05:30:00,4193\n2014-09-30 06:00:00,6473\n2014-09-30 06:30:00,11500\n2014-09-30 07:00:00,14892\n2014-09-30 07:30:00,19148\n2014-09-30 08:00:00,19942\n2014-09-30 08:30:00,19874\n2014-09-30 09:00:00,18453\n2014-09-30 09:30:00,18316\n2014-09-30 10:00:00,16768\n2014-09-30 10:30:00,16430\n2014-09-30 11:00:00,16035\n2014-09-30 11:30:00,17493\n2014-09-30 12:00:00,17298\n2014-09-30 12:30:00,16790\n2014-09-30 13:00:00,15966\n2014-09-30 13:30:00,17428\n2014-09-30 14:00:00,18268\n2014-09-30 14:30:00,18462\n2014-09-30 15:00:00,18361\n2014-09-30 15:30:00,16495\n2014-09-30 16:00:00,14614\n2014-09-30 16:30:00,14124\n2014-09-30 17:00:00,17230\n2014-09-30 17:30:00,20123\n2014-09-30 18:00:00,22947\n2014-09-30 18:30:00,23715\n2014-09-30 19:00:00,24428\n2014-09-30 19:30:00,24482\n2014-09-30 20:00:00,24208\n2014-09-30 20:30:00,23513\n2014-09-30 21:00:00,24049\n2014-09-30 21:30:00,23634\n2014-09-30 22:00:00,22175\n2014-09-30 22:30:00,20697\n2014-09-30 23:00:00,17890\n2014-09-30 23:30:00,15516\n2014-10-01 00:00:00,12751\n2014-10-01 00:30:00,8767\n2014-10-01 01:00:00,7005\n2014-10-01 01:30:00,5257\n2014-10-01 02:00:00,4189\n2014-10-01 02:30:00,3236\n2014-10-01 03:00:00,2817\n2014-10-01 03:30:00,2527\n2014-10-01 04:00:00,2406\n2014-10-01 04:30:00,1961\n2014-10-01 05:00:00,2478\n2014-10-01 05:30:00,4483\n2014-10-01 06:00:00,7002\n2014-10-01 06:30:00,11917\n2014-10-01 07:00:00,15929\n2014-10-01 07:30:00,20327\n2014-10-01 08:00:00,20974\n2014-10-01 08:30:00,20999\n2014-10-01 09:00:00,19639\n2014-10-01 09:30:00,19221\n2014-10-01 10:00:00,17308\n2014-10-01 10:30:00,17140\n2014-10-01 11:00:00,16773\n2014-10-01 11:30:00,19397\n2014-10-01 12:00:00,18697\n2014-10-01 12:30:00,18042\n2014-10-01 13:00:00,17332\n2014-10-01 13:30:00,17585\n2014-10-01 14:00:00,18263\n2014-10-01 14:30:00,18842\n2014-10-01 15:00:00,18583\n2014-10-01 15:30:00,17301\n2014-10-01 16:00:00,15060\n2014-10-01 16:30:00,14201\n2014-10-01 17:00:00,16655\n2014-10-01 17:30:00,19964\n2014-10-01 18:00:00,22960\n2014-10-01 18:30:00,23759\n2014-10-01 19:00:00,25024\n2014-10-01 19:30:00,25414\n2014-10-01 20:00:00,24917\n2014-10-01 20:30:00,24348\n2014-10-01 21:00:00,24248\n2014-10-01 21:30:00,24669\n2014-10-01 22:00:00,23132\n2014-10-01 22:30:00,22753\n2014-10-01 23:00:00,20371\n2014-10-01 23:30:00,17313\n2014-10-02 00:00:00,13534\n2014-10-02 00:30:00,10485\n2014-10-02 01:00:00,7944\n2014-10-02 01:30:00,6030\n2014-10-02 02:00:00,4867\n2014-10-02 02:30:00,3812\n2014-10-02 03:00:00,3251\n2014-10-02 03:30:00,2738\n2014-10-02 04:00:00,2755\n2014-10-02 04:30:00,2221\n2014-10-02 05:00:00,2363\n2014-10-02 05:30:00,4351\n2014-10-02 06:00:00,6835\n2014-10-02 06:30:00,11982\n2014-10-02 07:00:00,15844\n2014-10-02 07:30:00,19853\n2014-10-02 08:00:00,20187\n2014-10-02 08:30:00,20480\n2014-10-02 09:00:00,19531\n2014-10-02 09:30:00,18873\n2014-10-02 10:00:00,17534\n2014-10-02 10:30:00,17803\n2014-10-02 11:00:00,16994\n2014-10-02 11:30:00,18149\n2014-10-02 12:00:00,18251\n2014-10-02 12:30:00,17723\n2014-10-02 13:00:00,17104\n2014-10-02 13:30:00,18124\n2014-10-02 14:00:00,18680\n2014-10-02 14:30:00,19364\n2014-10-02 15:00:00,19044\n2014-10-02 15:30:00,16883\n2014-10-02 16:00:00,14389\n2014-10-02 16:30:00,13866\n2014-10-02 17:00:00,17005\n2014-10-02 17:30:00,20674\n2014-10-02 18:00:00,22678\n2014-10-02 18:30:00,23225\n2014-10-02 19:00:00,25012\n2014-10-02 19:30:00,25574\n2014-10-02 20:00:00,25301\n2014-10-02 20:30:00,25391\n2014-10-02 21:00:00,25520\n2014-10-02 21:30:00,25582\n2014-10-02 22:00:00,24848\n2014-10-02 22:30:00,24100\n2014-10-02 23:00:00,23336\n2014-10-02 23:30:00,21549\n2014-10-03 00:00:00,18003\n2014-10-03 00:30:00,15266\n2014-10-03 01:00:00,12130\n2014-10-03 01:30:00,9847\n2014-10-03 02:00:00,8022\n2014-10-03 02:30:00,6508\n2014-10-03 03:00:00,5309\n2014-10-03 03:30:00,4339\n2014-10-03 04:00:00,4202\n2014-10-03 04:30:00,3358\n2014-10-03 05:00:00,3083\n2014-10-03 05:30:00,4391\n2014-10-03 06:00:00,6769\n2014-10-03 06:30:00,11309\n2014-10-03 07:00:00,14866\n2014-10-03 07:30:00,18942\n2014-10-03 08:00:00,19693\n2014-10-03 08:30:00,19776\n2014-10-03 09:00:00,19309\n2014-10-03 09:30:00,18801\n2014-10-03 10:00:00,17108\n2014-10-03 10:30:00,16952\n2014-10-03 11:00:00,17108\n2014-10-03 11:30:00,17927\n2014-10-03 12:00:00,18426\n2014-10-03 12:30:00,17340\n2014-10-03 13:00:00,17150\n2014-10-03 13:30:00,17581\n2014-10-03 14:00:00,18924\n2014-10-03 14:30:00,19602\n2014-10-03 15:00:00,18893\n2014-10-03 15:30:00,16691\n2014-10-03 16:00:00,15332\n2014-10-03 16:30:00,14661\n2014-10-03 17:00:00,18110\n2014-10-03 17:30:00,22624\n2014-10-03 18:00:00,25209\n2014-10-03 18:30:00,24975\n2014-10-03 19:00:00,26477\n2014-10-03 19:30:00,27165\n2014-10-03 20:00:00,25960\n2014-10-03 20:30:00,25435\n2014-10-03 21:00:00,24847\n2014-10-03 21:30:00,25174\n2014-10-03 22:00:00,25419\n2014-10-03 22:30:00,25904\n2014-10-03 23:00:00,24543\n2014-10-03 23:30:00,24513\n2014-10-04 00:00:00,23316\n2014-10-04 00:30:00,22311\n2014-10-04 01:00:00,20470\n2014-10-04 01:30:00,18629\n2014-10-04 02:00:00,17120\n2014-10-04 02:30:00,15544\n2014-10-04 03:00:00,14012\n2014-10-04 03:30:00,11425\n2014-10-04 04:00:00,9541\n2014-10-04 04:30:00,5912\n2014-10-04 05:00:00,3832\n2014-10-04 05:30:00,3230\n2014-10-04 06:00:00,3425\n2014-10-04 06:30:00,4159\n2014-10-04 07:00:00,4720\n2014-10-04 07:30:00,5848\n2014-10-04 08:00:00,6901\n2014-10-04 08:30:00,9611\n2014-10-04 09:00:00,11626\n2014-10-04 09:30:00,14814\n2014-10-04 10:00:00,16839\n2014-10-04 10:30:00,18245\n2014-10-04 11:00:00,18230\n2014-10-04 11:30:00,18322\n2014-10-04 12:00:00,18541\n2014-10-04 12:30:00,18062\n2014-10-04 13:00:00,18008\n2014-10-04 13:30:00,18784\n2014-10-04 14:00:00,17708\n2014-10-04 14:30:00,17998\n2014-10-04 15:00:00,18033\n2014-10-04 15:30:00,17851\n2014-10-04 16:00:00,17046\n2014-10-04 16:30:00,17241\n2014-10-04 17:00:00,19295\n2014-10-04 17:30:00,21740\n2014-10-04 18:00:00,22729\n2014-10-04 18:30:00,23854\n2014-10-04 19:00:00,25857\n2014-10-04 19:30:00,26490\n2014-10-04 20:00:00,24115\n2014-10-04 20:30:00,23384\n2014-10-04 21:00:00,23515\n2014-10-04 21:30:00,24476\n2014-10-04 22:00:00,24455\n2014-10-04 22:30:00,25474\n2014-10-04 23:00:00,25811\n2014-10-04 23:30:00,25847\n2014-10-05 00:00:00,25224\n2014-10-05 00:30:00,23248\n2014-10-05 01:00:00,22772\n2014-10-05 01:30:00,20671\n2014-10-05 02:00:00,19208\n2014-10-05 02:30:00,17300\n2014-10-05 03:00:00,15260\n2014-10-05 03:30:00,12970\n2014-10-05 04:00:00,11168\n2014-10-05 04:30:00,6678\n2014-10-05 05:00:00,4321\n2014-10-05 05:30:00,3259\n2014-10-05 06:00:00,3277\n2014-10-05 06:30:00,4072\n2014-10-05 07:00:00,4566\n2014-10-05 07:30:00,5973\n2014-10-05 08:00:00,7209\n2014-10-05 08:30:00,8999\n2014-10-05 09:00:00,10669\n2014-10-05 09:30:00,12678\n2014-10-05 10:00:00,14511\n2014-10-05 10:30:00,16953\n2014-10-05 11:00:00,17817\n2014-10-05 11:30:00,18894\n2014-10-05 12:00:00,18505\n2014-10-05 12:30:00,19227\n2014-10-05 13:00:00,18361\n2014-10-05 13:30:00,18014\n2014-10-05 14:00:00,17486\n2014-10-05 14:30:00,17816\n2014-10-05 15:00:00,17364\n2014-10-05 15:30:00,16871\n2014-10-05 16:00:00,15497\n2014-10-05 16:30:00,15185\n2014-10-05 17:00:00,16114\n2014-10-05 17:30:00,18312\n2014-10-05 18:00:00,19793\n2014-10-05 18:30:00,19706\n2014-10-05 19:00:00,20198\n2014-10-05 19:30:00,19790\n2014-10-05 20:00:00,18192\n2014-10-05 20:30:00,17701\n2014-10-05 21:00:00,16484\n2014-10-05 21:30:00,16626\n2014-10-05 22:00:00,14889\n2014-10-05 22:30:00,14114\n2014-10-05 23:00:00,11870\n2014-10-05 23:30:00,10041\n2014-10-06 00:00:00,7997\n2014-10-06 00:30:00,5689\n2014-10-06 01:00:00,4351\n2014-10-06 01:30:00,3348\n2014-10-06 02:00:00,2809\n2014-10-06 02:30:00,2193\n2014-10-06 03:00:00,1752\n2014-10-06 03:30:00,1731\n2014-10-06 04:00:00,1994\n2014-10-06 04:30:00,2178\n2014-10-06 05:00:00,2787\n2014-10-06 05:30:00,4578\n2014-10-06 06:00:00,6816\n2014-10-06 06:30:00,11243\n2014-10-06 07:00:00,14265\n2014-10-06 07:30:00,17395\n2014-10-06 08:00:00,18327\n2014-10-06 08:30:00,17729\n2014-10-06 09:00:00,17870\n2014-10-06 09:30:00,16982\n2014-10-06 10:00:00,15335\n2014-10-06 10:30:00,15998\n2014-10-06 11:00:00,15414\n2014-10-06 11:30:00,16233\n2014-10-06 12:00:00,16499\n2014-10-06 12:30:00,16380\n2014-10-06 13:00:00,15414\n2014-10-06 13:30:00,16720\n2014-10-06 14:00:00,17137\n2014-10-06 14:30:00,18046\n2014-10-06 15:00:00,18110\n2014-10-06 15:30:00,17087\n2014-10-06 16:00:00,15794\n2014-10-06 16:30:00,15965\n2014-10-06 17:00:00,18732\n2014-10-06 17:30:00,21107\n2014-10-06 18:00:00,23450\n2014-10-06 18:30:00,24200\n2014-10-06 19:00:00,24518\n2014-10-06 19:30:00,23704\n2014-10-06 20:00:00,22112\n2014-10-06 20:30:00,20986\n2014-10-06 21:00:00,21032\n2014-10-06 21:30:00,19963\n2014-10-06 22:00:00,18986\n2014-10-06 22:30:00,17125\n2014-10-06 23:00:00,15528\n2014-10-06 23:30:00,11610\n2014-10-07 00:00:00,9469\n2014-10-07 00:30:00,6605\n2014-10-07 01:00:00,5283\n2014-10-07 01:30:00,4152\n2014-10-07 02:00:00,3319\n2014-10-07 02:30:00,2432\n2014-10-07 03:00:00,1968\n2014-10-07 03:30:00,1769\n2014-10-07 04:00:00,2018\n2014-10-07 04:30:00,1933\n2014-10-07 05:00:00,2240\n2014-10-07 05:30:00,4305\n2014-10-07 06:00:00,6719\n2014-10-07 06:30:00,11392\n2014-10-07 07:00:00,14960\n2014-10-07 07:30:00,18975\n2014-10-07 08:00:00,19602\n2014-10-07 08:30:00,19572\n2014-10-07 09:00:00,18772\n2014-10-07 09:30:00,17757\n2014-10-07 10:00:00,16706\n2014-10-07 10:30:00,16601\n2014-10-07 11:00:00,15673\n2014-10-07 11:30:00,16929\n2014-10-07 12:00:00,17435\n2014-10-07 12:30:00,16953\n2014-10-07 13:00:00,16417\n2014-10-07 13:30:00,17022\n2014-10-07 14:00:00,17540\n2014-10-07 14:30:00,18417\n2014-10-07 15:00:00,18698\n2014-10-07 15:30:00,16193\n2014-10-07 16:00:00,14544\n2014-10-07 16:30:00,13864\n2014-10-07 17:00:00,17041\n2014-10-07 17:30:00,20434\n2014-10-07 18:00:00,23029\n2014-10-07 18:30:00,23711\n2014-10-07 19:00:00,24817\n2014-10-07 19:30:00,24933\n2014-10-07 20:00:00,24002\n2014-10-07 20:30:00,23651\n2014-10-07 21:00:00,23764\n2014-10-07 21:30:00,23224\n2014-10-07 22:00:00,22020\n2014-10-07 22:30:00,22214\n2014-10-07 23:00:00,21446\n2014-10-07 23:30:00,15974\n2014-10-08 00:00:00,12484\n2014-10-08 00:30:00,9130\n2014-10-08 01:00:00,6693\n2014-10-08 01:30:00,5333\n2014-10-08 02:00:00,3820\n2014-10-08 02:30:00,3065\n2014-10-08 03:00:00,2511\n2014-10-08 03:30:00,2299\n2014-10-08 04:00:00,2318\n2014-10-08 04:30:00,2125\n2014-10-08 05:00:00,2484\n2014-10-08 05:30:00,4358\n2014-10-08 06:00:00,6790\n2014-10-08 06:30:00,11660\n2014-10-08 07:00:00,15780\n2014-10-08 07:30:00,19516\n2014-10-08 08:00:00,20307\n2014-10-08 08:30:00,19954\n2014-10-08 09:00:00,18254\n2014-10-08 09:30:00,18010\n2014-10-08 10:00:00,17206\n2014-10-08 10:30:00,17213\n2014-10-08 11:00:00,16691\n2014-10-08 11:30:00,18259\n2014-10-08 12:00:00,18151\n2014-10-08 12:30:00,17555\n2014-10-08 13:00:00,16944\n2014-10-08 13:30:00,17728\n2014-10-08 14:00:00,18074\n2014-10-08 14:30:00,18993\n2014-10-08 15:00:00,18695\n2014-10-08 15:30:00,17191\n2014-10-08 16:00:00,15023\n2014-10-08 16:30:00,14164\n2014-10-08 17:00:00,17004\n2014-10-08 17:30:00,20361\n2014-10-08 18:00:00,23633\n2014-10-08 18:30:00,24661\n2014-10-08 19:00:00,25754\n2014-10-08 19:30:00,25671\n2014-10-08 20:00:00,25156\n2014-10-08 20:30:00,24961\n2014-10-08 21:00:00,24938\n2014-10-08 21:30:00,24851\n2014-10-08 22:00:00,24683\n2014-10-08 22:30:00,23411\n2014-10-08 23:00:00,20599\n2014-10-08 23:30:00,17147\n2014-10-09 00:00:00,13602\n2014-10-09 00:30:00,10452\n2014-10-09 01:00:00,7836\n2014-10-09 01:30:00,6040\n2014-10-09 02:00:00,4981\n2014-10-09 02:30:00,3613\n2014-10-09 03:00:00,2923\n2014-10-09 03:30:00,2632\n2014-10-09 04:00:00,2912\n2014-10-09 04:30:00,2577\n2014-10-09 05:00:00,2921\n2014-10-09 05:30:00,4679\n2014-10-09 06:00:00,6693\n2014-10-09 06:30:00,12140\n2014-10-09 07:00:00,15534\n2014-10-09 07:30:00,19974\n2014-10-09 08:00:00,20533\n2014-10-09 08:30:00,19988\n2014-10-09 09:00:00,19239\n2014-10-09 09:30:00,18788\n2014-10-09 10:00:00,17934\n2014-10-09 10:30:00,18048\n2014-10-09 11:00:00,17415\n2014-10-09 11:30:00,18292\n2014-10-09 12:00:00,18506\n2014-10-09 12:30:00,18180\n2014-10-09 13:00:00,17401\n2014-10-09 13:30:00,18973\n2014-10-09 14:00:00,19361\n2014-10-09 14:30:00,19722\n2014-10-09 15:00:00,19572\n2014-10-09 15:30:00,17500\n2014-10-09 16:00:00,15213\n2014-10-09 16:30:00,14457\n2014-10-09 17:00:00,17736\n2014-10-09 17:30:00,21319\n2014-10-09 18:00:00,23270\n2014-10-09 18:30:00,24892\n2014-10-09 19:00:00,26555\n2014-10-09 19:30:00,26743\n2014-10-09 20:00:00,26376\n2014-10-09 20:30:00,26311\n2014-10-09 21:00:00,26179\n2014-10-09 21:30:00,26774\n2014-10-09 22:00:00,26449\n2014-10-09 22:30:00,25459\n2014-10-09 23:00:00,23927\n2014-10-09 23:30:00,21851\n2014-10-10 00:00:00,18756\n2014-10-10 00:30:00,14990\n2014-10-10 01:00:00,13865\n2014-10-10 01:30:00,10263\n2014-10-10 02:00:00,7873\n2014-10-10 02:30:00,6480\n2014-10-10 03:00:00,5094\n2014-10-10 03:30:00,4217\n2014-10-10 04:00:00,4289\n2014-10-10 04:30:00,3640\n2014-10-10 05:00:00,3376\n2014-10-10 05:30:00,5145\n2014-10-10 06:00:00,7144\n2014-10-10 06:30:00,11739\n2014-10-10 07:00:00,15197\n2014-10-10 07:30:00,19716\n2014-10-10 08:00:00,20851\n2014-10-10 08:30:00,20463\n2014-10-10 09:00:00,19658\n2014-10-10 09:30:00,19287\n2014-10-10 10:00:00,17986\n2014-10-10 10:30:00,17776\n2014-10-10 11:00:00,17735\n2014-10-10 11:30:00,18716\n2014-10-10 12:00:00,19032\n2014-10-10 12:30:00,17702\n2014-10-10 13:00:00,17023\n2014-10-10 13:30:00,18352\n2014-10-10 14:00:00,19791\n2014-10-10 14:30:00,20131\n2014-10-10 15:00:00,18645\n2014-10-10 15:30:00,16572\n2014-10-10 16:00:00,14736\n2014-10-10 16:30:00,13731\n2014-10-10 17:00:00,17166\n2014-10-10 17:30:00,20392\n2014-10-10 18:00:00,22838\n2014-10-10 18:30:00,23791\n2014-10-10 19:00:00,25914\n2014-10-10 19:30:00,26355\n2014-10-10 20:00:00,25656\n2014-10-10 20:30:00,25449\n2014-10-10 21:00:00,25448\n2014-10-10 21:30:00,25823\n2014-10-10 22:00:00,25813\n2014-10-10 22:30:00,26407\n2014-10-10 23:00:00,26898\n2014-10-10 23:30:00,26587\n2014-10-11 00:00:00,25257\n2014-10-11 00:30:00,23717\n2014-10-11 01:00:00,22541\n2014-10-11 01:30:00,19773\n2014-10-11 02:00:00,19652\n2014-10-11 02:30:00,16294\n2014-10-11 03:00:00,13968\n2014-10-11 03:30:00,12000\n2014-10-11 04:00:00,10432\n2014-10-11 04:30:00,6402\n2014-10-11 05:00:00,4443\n2014-10-11 05:30:00,3481\n2014-10-11 06:00:00,3971\n2014-10-11 06:30:00,5191\n2014-10-11 07:00:00,6434\n2014-10-11 07:30:00,8435\n2014-10-11 08:00:00,10255\n2014-10-11 08:30:00,13847\n2014-10-11 09:00:00,14970\n2014-10-11 09:30:00,18403\n2014-10-11 10:00:00,19338\n2014-10-11 10:30:00,21107\n2014-10-11 11:00:00,20821\n2014-10-11 11:30:00,21854\n2014-10-11 12:00:00,21813\n2014-10-11 12:30:00,22250\n2014-10-11 13:00:00,21450\n2014-10-11 13:30:00,21271\n2014-10-11 14:00:00,20595\n2014-10-11 14:30:00,20863\n2014-10-11 15:00:00,20262\n2014-10-11 15:30:00,21024\n2014-10-11 16:00:00,19141\n2014-10-11 16:30:00,17903\n2014-10-11 17:00:00,19903\n2014-10-11 17:30:00,22820\n2014-10-11 18:00:00,24243\n2014-10-11 18:30:00,25880\n2014-10-11 19:00:00,26756\n2014-10-11 19:30:00,26593\n2014-10-11 20:00:00,25248\n2014-10-11 20:30:00,23934\n2014-10-11 21:00:00,23401\n2014-10-11 21:30:00,24145\n2014-10-11 22:00:00,25308\n2014-10-11 22:30:00,26284\n2014-10-11 23:00:00,27136\n2014-10-11 23:30:00,27099\n2014-10-12 00:00:00,26610\n2014-10-12 00:30:00,25400\n2014-10-12 01:00:00,23992\n2014-10-12 01:30:00,22359\n2014-10-12 02:00:00,21054\n2014-10-12 02:30:00,18812\n2014-10-12 03:00:00,16584\n2014-10-12 03:30:00,14204\n2014-10-12 04:00:00,11990\n2014-10-12 04:30:00,7092\n2014-10-12 05:00:00,4311\n2014-10-12 05:30:00,3844\n2014-10-12 06:00:00,3796\n2014-10-12 06:30:00,4755\n2014-10-12 07:00:00,4491\n2014-10-12 07:30:00,5559\n2014-10-12 08:00:00,6959\n2014-10-12 08:30:00,9127\n2014-10-12 09:00:00,11015\n2014-10-12 09:30:00,13961\n2014-10-12 10:00:00,15445\n2014-10-12 10:30:00,17923\n2014-10-12 11:00:00,18438\n2014-10-12 11:30:00,19592\n2014-10-12 12:00:00,19733\n2014-10-12 12:30:00,19766\n2014-10-12 13:00:00,19809\n2014-10-12 13:30:00,19242\n2014-10-12 14:00:00,18990\n2014-10-12 14:30:00,18676\n2014-10-12 15:00:00,18037\n2014-10-12 15:30:00,16660\n2014-10-12 16:00:00,15948\n2014-10-12 16:30:00,15261\n2014-10-12 17:00:00,17141\n2014-10-12 17:30:00,19085\n2014-10-12 18:00:00,20188\n2014-10-12 18:30:00,20512\n2014-10-12 19:00:00,20723\n2014-10-12 19:30:00,20415\n2014-10-12 20:00:00,19483\n2014-10-12 20:30:00,19008\n2014-10-12 21:00:00,17958\n2014-10-12 21:30:00,18341\n2014-10-12 22:00:00,18181\n2014-10-12 22:30:00,17069\n2014-10-12 23:00:00,15057\n2014-10-12 23:30:00,13867\n2014-10-13 00:00:00,11544\n2014-10-13 00:30:00,9016\n2014-10-13 01:00:00,6739\n2014-10-13 01:30:00,5420\n2014-10-13 02:00:00,4584\n2014-10-13 02:30:00,3787\n2014-10-13 03:00:00,3018\n2014-10-13 03:30:00,2667\n2014-10-13 04:00:00,2981\n2014-10-13 04:30:00,2756\n2014-10-13 05:00:00,2712\n2014-10-13 05:30:00,3798\n2014-10-13 06:00:00,5117\n2014-10-13 06:30:00,7727\n2014-10-13 07:00:00,9655\n2014-10-13 07:30:00,12109\n2014-10-13 08:00:00,13484\n2014-10-13 08:30:00,15506\n2014-10-13 09:00:00,15325\n2014-10-13 09:30:00,15924\n2014-10-13 10:00:00,14830\n2014-10-13 10:30:00,14907\n2014-10-13 11:00:00,14796\n2014-10-13 11:30:00,15699\n2014-10-13 12:00:00,15705\n2014-10-13 12:30:00,15880\n2014-10-13 13:00:00,15693\n2014-10-13 13:30:00,16643\n2014-10-13 14:00:00,16929\n2014-10-13 14:30:00,17698\n2014-10-13 15:00:00,17429\n2014-10-13 15:30:00,17248\n2014-10-13 16:00:00,16219\n2014-10-13 16:30:00,15918\n2014-10-13 17:00:00,17780\n2014-10-13 17:30:00,19414\n2014-10-13 18:00:00,21594\n2014-10-13 18:30:00,24915\n2014-10-13 19:00:00,24556\n2014-10-13 19:30:00,22341\n2014-10-13 20:00:00,22343\n2014-10-13 20:30:00,21619\n2014-10-13 21:00:00,21315\n2014-10-13 21:30:00,19821\n2014-10-13 22:00:00,17669\n2014-10-13 22:30:00,15504\n2014-10-13 23:00:00,14525\n2014-10-13 23:30:00,10738\n2014-10-14 00:00:00,8908\n2014-10-14 00:30:00,6593\n2014-10-14 01:00:00,5560\n2014-10-14 01:30:00,4014\n2014-10-14 02:00:00,3046\n2014-10-14 02:30:00,2349\n2014-10-14 03:00:00,1876\n2014-10-14 03:30:00,1691\n2014-10-14 04:00:00,1941\n2014-10-14 04:30:00,1850\n2014-10-14 05:00:00,2318\n2014-10-14 05:30:00,4337\n2014-10-14 06:00:00,6669\n2014-10-14 06:30:00,11585\n2014-10-14 07:00:00,15170\n2014-10-14 07:30:00,19136\n2014-10-14 08:00:00,20085\n2014-10-14 08:30:00,19758\n2014-10-14 09:00:00,18842\n2014-10-14 09:30:00,18530\n2014-10-14 10:00:00,16617\n2014-10-14 10:30:00,17458\n2014-10-14 11:00:00,16359\n2014-10-14 11:30:00,17483\n2014-10-14 12:00:00,17600\n2014-10-14 12:30:00,17552\n2014-10-14 13:00:00,17058\n2014-10-14 13:30:00,17658\n2014-10-14 14:00:00,18319\n2014-10-14 14:30:00,18818\n2014-10-14 15:00:00,18735\n2014-10-14 15:30:00,17254\n2014-10-14 16:00:00,15022\n2014-10-14 16:30:00,14365\n2014-10-14 17:00:00,16300\n2014-10-14 17:30:00,19687\n2014-10-14 18:00:00,22620\n2014-10-14 18:30:00,23309\n2014-10-14 19:00:00,23636\n2014-10-14 19:30:00,23752\n2014-10-14 20:00:00,23095\n2014-10-14 20:30:00,23108\n2014-10-14 21:00:00,23221\n2014-10-14 21:30:00,23581\n2014-10-14 22:00:00,22249\n2014-10-14 22:30:00,19533\n2014-10-14 23:00:00,17226\n2014-10-14 23:30:00,13935\n2014-10-15 00:00:00,11429\n2014-10-15 00:30:00,8486\n2014-10-15 01:00:00,6484\n2014-10-15 01:30:00,5093\n2014-10-15 02:00:00,4018\n2014-10-15 02:30:00,3218\n2014-10-15 03:00:00,2536\n2014-10-15 03:30:00,2219\n2014-10-15 04:00:00,2171\n2014-10-15 04:30:00,2268\n2014-10-15 05:00:00,2437\n2014-10-15 05:30:00,4569\n2014-10-15 06:00:00,6862\n2014-10-15 06:30:00,11924\n2014-10-15 07:00:00,15860\n2014-10-15 07:30:00,19821\n2014-10-15 08:00:00,20508\n2014-10-15 08:30:00,20540\n2014-10-15 09:00:00,19590\n2014-10-15 09:30:00,18480\n2014-10-15 10:00:00,17330\n2014-10-15 10:30:00,18508\n2014-10-15 11:00:00,17354\n2014-10-15 11:30:00,18552\n2014-10-15 12:00:00,18241\n2014-10-15 12:30:00,18475\n2014-10-15 13:00:00,17939\n2014-10-15 13:30:00,18398\n2014-10-15 14:00:00,18875\n2014-10-15 14:30:00,19559\n2014-10-15 15:00:00,19133\n2014-10-15 15:30:00,16816\n2014-10-15 16:00:00,14757\n2014-10-15 16:30:00,14470\n2014-10-15 17:00:00,17800\n2014-10-15 17:30:00,21127\n2014-10-15 18:00:00,22269\n2014-10-15 18:30:00,22819\n2014-10-15 19:00:00,23582\n2014-10-15 19:30:00,26273\n2014-10-15 20:00:00,25338\n2014-10-15 20:30:00,24021\n2014-10-15 21:00:00,26163\n2014-10-15 21:30:00,23839\n2014-10-15 22:00:00,22608\n2014-10-15 22:30:00,24886\n2014-10-15 23:00:00,20128\n2014-10-15 23:30:00,16180\n2014-10-16 00:00:00,13302\n2014-10-16 00:30:00,10509\n2014-10-16 01:00:00,8241\n2014-10-16 01:30:00,5536\n2014-10-16 02:00:00,4664\n2014-10-16 02:30:00,3460\n2014-10-16 03:00:00,2799\n2014-10-16 03:30:00,2730\n2014-10-16 04:00:00,2801\n2014-10-16 04:30:00,2511\n2014-10-16 05:00:00,2670\n2014-10-16 05:30:00,4767\n2014-10-16 06:00:00,7096\n2014-10-16 06:30:00,12556\n2014-10-16 07:00:00,16431\n2014-10-16 07:30:00,21581\n2014-10-16 08:00:00,21355\n2014-10-16 08:30:00,21573\n2014-10-16 09:00:00,20390\n2014-10-16 09:30:00,20452\n2014-10-16 10:00:00,19678\n2014-10-16 10:30:00,18801\n2014-10-16 11:00:00,17223\n2014-10-16 11:30:00,18249\n2014-10-16 12:00:00,17691\n2014-10-16 12:30:00,17052\n2014-10-16 13:00:00,16783\n2014-10-16 13:30:00,18392\n2014-10-16 14:00:00,18593\n2014-10-16 14:30:00,19364\n2014-10-16 15:00:00,19176\n2014-10-16 15:30:00,16795\n2014-10-16 16:00:00,15293\n2014-10-16 16:30:00,14922\n2014-10-16 17:00:00,17899\n2014-10-16 17:30:00,21758\n2014-10-16 18:00:00,24169\n2014-10-16 18:30:00,24615\n2014-10-16 19:00:00,26370\n2014-10-16 19:30:00,26990\n2014-10-16 20:00:00,26168\n2014-10-16 20:30:00,25449\n2014-10-16 21:00:00,25994\n2014-10-16 21:30:00,27115\n2014-10-16 22:00:00,26191\n2014-10-16 22:30:00,25146\n2014-10-16 23:00:00,24371\n2014-10-16 23:30:00,23771\n2014-10-17 00:00:00,19268\n2014-10-17 00:30:00,15623\n2014-10-17 01:00:00,12595\n2014-10-17 01:30:00,10224\n2014-10-17 02:00:00,7941\n2014-10-17 02:30:00,6678\n2014-10-17 03:00:00,5182\n2014-10-17 03:30:00,4502\n2014-10-17 04:00:00,4316\n2014-10-17 04:30:00,3512\n2014-10-17 05:00:00,3174\n2014-10-17 05:30:00,4771\n2014-10-17 06:00:00,6557\n2014-10-17 06:30:00,11929\n2014-10-17 07:00:00,14950\n2014-10-17 07:30:00,19835\n2014-10-17 08:00:00,20149\n2014-10-17 08:30:00,19998\n2014-10-17 09:00:00,19310\n2014-10-17 09:30:00,18601\n2014-10-17 10:00:00,17567\n2014-10-17 10:30:00,17890\n2014-10-17 11:00:00,17470\n2014-10-17 11:30:00,18557\n2014-10-17 12:00:00,18944\n2014-10-17 12:30:00,17922\n2014-10-17 13:00:00,17627\n2014-10-17 13:30:00,18361\n2014-10-17 14:00:00,19557\n2014-10-17 14:30:00,19811\n2014-10-17 15:00:00,19277\n2014-10-17 15:30:00,16741\n2014-10-17 16:00:00,14948\n2014-10-17 16:30:00,14244\n2014-10-17 17:00:00,17563\n2014-10-17 17:30:00,21246\n2014-10-17 18:00:00,23115\n2014-10-17 18:30:00,24785\n2014-10-17 19:00:00,26396\n2014-10-17 19:30:00,26837\n2014-10-17 20:00:00,26621\n2014-10-17 20:30:00,26144\n2014-10-17 21:00:00,26019\n2014-10-17 21:30:00,26816\n2014-10-17 22:00:00,26701\n2014-10-17 22:30:00,26519\n2014-10-17 23:00:00,26740\n2014-10-17 23:30:00,26173\n2014-10-18 00:00:00,25059\n2014-10-18 00:30:00,24437\n2014-10-18 01:00:00,22718\n2014-10-18 01:30:00,20700\n2014-10-18 02:00:00,19623\n2014-10-18 02:30:00,16675\n2014-10-18 03:00:00,14447\n2014-10-18 03:30:00,12377\n2014-10-18 04:00:00,10609\n2014-10-18 04:30:00,6436\n2014-10-18 05:00:00,4562\n2014-10-18 05:30:00,3783\n2014-10-18 06:00:00,3923\n2014-10-18 06:30:00,5060\n2014-10-18 07:00:00,5992\n2014-10-18 07:30:00,8639\n2014-10-18 08:00:00,10309\n2014-10-18 08:30:00,13563\n2014-10-18 09:00:00,14136\n2014-10-18 09:30:00,16945\n2014-10-18 10:00:00,17004\n2014-10-18 10:30:00,19045\n2014-10-18 11:00:00,19859\n2014-10-18 11:30:00,21198\n2014-10-18 12:00:00,21550\n2014-10-18 12:30:00,21583\n2014-10-18 13:00:00,21455\n2014-10-18 13:30:00,21869\n2014-10-18 14:00:00,21426\n2014-10-18 14:30:00,21650\n2014-10-18 15:00:00,21611\n2014-10-18 15:30:00,20904\n2014-10-18 16:00:00,18820\n2014-10-18 16:30:00,17255\n2014-10-18 17:00:00,19029\n2014-10-18 17:30:00,22812\n2014-10-18 18:00:00,24455\n2014-10-18 18:30:00,26373\n2014-10-18 19:00:00,27460\n2014-10-18 19:30:00,27222\n2014-10-18 20:00:00,25204\n2014-10-18 20:30:00,24329\n2014-10-18 21:00:00,24526\n2014-10-18 21:30:00,25203\n2014-10-18 22:00:00,25975\n2014-10-18 22:30:00,27073\n2014-10-18 23:00:00,27881\n2014-10-18 23:30:00,28626\n2014-10-19 00:00:00,28093\n2014-10-19 00:30:00,26200\n2014-10-19 01:00:00,25610\n2014-10-19 01:30:00,23483\n2014-10-19 02:00:00,21850\n2014-10-19 02:30:00,19297\n2014-10-19 03:00:00,16574\n2014-10-19 03:30:00,14355\n2014-10-19 04:00:00,12112\n2014-10-19 04:30:00,7284\n2014-10-19 05:00:00,4845\n2014-10-19 05:30:00,3667\n2014-10-19 06:00:00,3718\n2014-10-19 06:30:00,4573\n2014-10-19 07:00:00,5167\n2014-10-19 07:30:00,6844\n2014-10-19 08:00:00,7279\n2014-10-19 08:30:00,9761\n2014-10-19 09:00:00,11712\n2014-10-19 09:30:00,14210\n2014-10-19 10:00:00,15394\n2014-10-19 10:30:00,18387\n2014-10-19 11:00:00,19168\n2014-10-19 11:30:00,20891\n2014-10-19 12:00:00,21806\n2014-10-19 12:30:00,22188\n2014-10-19 13:00:00,22153\n2014-10-19 13:30:00,21713\n2014-10-19 14:00:00,21838\n2014-10-19 14:30:00,21082\n2014-10-19 15:00:00,20448\n2014-10-19 15:30:00,20113\n2014-10-19 16:00:00,18645\n2014-10-19 16:30:00,17210\n2014-10-19 17:00:00,18326\n2014-10-19 17:30:00,20498\n2014-10-19 18:00:00,20924\n2014-10-19 18:30:00,21579\n2014-10-19 19:00:00,22026\n2014-10-19 19:30:00,22197\n2014-10-19 20:00:00,19709\n2014-10-19 20:30:00,18780\n2014-10-19 21:00:00,18060\n2014-10-19 21:30:00,17973\n2014-10-19 22:00:00,16572\n2014-10-19 22:30:00,14957\n2014-10-19 23:00:00,12461\n2014-10-19 23:30:00,10448\n2014-10-20 00:00:00,8295\n2014-10-20 00:30:00,6837\n2014-10-20 01:00:00,4747\n2014-10-20 01:30:00,3283\n2014-10-20 02:00:00,2904\n2014-10-20 02:30:00,2345\n2014-10-20 03:00:00,1917\n2014-10-20 03:30:00,1783\n2014-10-20 04:00:00,2174\n2014-10-20 04:30:00,2157\n2014-10-20 05:00:00,2989\n2014-10-20 05:30:00,4841\n2014-10-20 06:00:00,7228\n2014-10-20 06:30:00,11726\n2014-10-20 07:00:00,14557\n2014-10-20 07:30:00,17848\n2014-10-20 08:00:00,18436\n2014-10-20 08:30:00,18059\n2014-10-20 09:00:00,18028\n2014-10-20 09:30:00,17353\n2014-10-20 10:00:00,16350\n2014-10-20 10:30:00,16376\n2014-10-20 11:00:00,16099\n2014-10-20 11:30:00,16817\n2014-10-20 12:00:00,16898\n2014-10-20 12:30:00,16809\n2014-10-20 13:00:00,16199\n2014-10-20 13:30:00,16758\n2014-10-20 14:00:00,17679\n2014-10-20 14:30:00,18148\n2014-10-20 15:00:00,18644\n2014-10-20 15:30:00,17183\n2014-10-20 16:00:00,16196\n2014-10-20 16:30:00,15534\n2014-10-20 17:00:00,18451\n2014-10-20 17:30:00,20950\n2014-10-20 18:00:00,23192\n2014-10-20 18:30:00,24655\n2014-10-20 19:00:00,24094\n2014-10-20 19:30:00,23285\n2014-10-20 20:00:00,22083\n2014-10-20 20:30:00,21485\n2014-10-20 21:00:00,21579\n2014-10-20 21:30:00,21118\n2014-10-20 22:00:00,20204\n2014-10-20 22:30:00,16909\n2014-10-20 23:00:00,13785\n2014-10-20 23:30:00,11695\n2014-10-21 00:00:00,9214\n2014-10-21 00:30:00,6931\n2014-10-21 01:00:00,5413\n2014-10-21 01:30:00,4130\n2014-10-21 02:00:00,3276\n2014-10-21 02:30:00,2475\n2014-10-21 03:00:00,2080\n2014-10-21 03:30:00,1917\n2014-10-21 04:00:00,2123\n2014-10-21 04:30:00,1984\n2014-10-21 05:00:00,2458\n2014-10-21 05:30:00,4338\n2014-10-21 06:00:00,6470\n2014-10-21 06:30:00,11775\n2014-10-21 07:00:00,15088\n2014-10-21 07:30:00,19429\n2014-10-21 08:00:00,20482\n2014-10-21 08:30:00,19886\n2014-10-21 09:00:00,19170\n2014-10-21 09:30:00,18277\n2014-10-21 10:00:00,17064\n2014-10-21 10:30:00,16386\n2014-10-21 11:00:00,16633\n2014-10-21 11:30:00,17681\n2014-10-21 12:00:00,18233\n2014-10-21 12:30:00,17996\n2014-10-21 13:00:00,16695\n2014-10-21 13:30:00,16912\n2014-10-21 14:00:00,18124\n2014-10-21 14:30:00,18411\n2014-10-21 15:00:00,19013\n2014-10-21 15:30:00,17590\n2014-10-21 16:00:00,15673\n2014-10-21 16:30:00,14923\n2014-10-21 17:00:00,17981\n2014-10-21 17:30:00,21208\n2014-10-21 18:00:00,23458\n2014-10-21 18:30:00,24028\n2014-10-21 19:00:00,24934\n2014-10-21 19:30:00,25135\n2014-10-21 20:00:00,24613\n2014-10-21 20:30:00,24617\n2014-10-21 21:00:00,25841\n2014-10-21 21:30:00,24141\n2014-10-21 22:00:00,23069\n2014-10-21 22:30:00,21243\n2014-10-21 23:00:00,18077\n2014-10-21 23:30:00,15745\n2014-10-22 00:00:00,12115\n2014-10-22 00:30:00,9035\n2014-10-22 01:00:00,7015\n2014-10-22 01:30:00,5113\n2014-10-22 02:00:00,4220\n2014-10-22 02:30:00,3331\n2014-10-22 03:00:00,2870\n2014-10-22 03:30:00,2516\n2014-10-22 04:00:00,2656\n2014-10-22 04:30:00,2336\n2014-10-22 05:00:00,2494\n2014-10-22 05:30:00,5081\n2014-10-22 06:00:00,8091\n2014-10-22 06:30:00,13037\n2014-10-22 07:00:00,16579\n2014-10-22 07:30:00,19657\n2014-10-22 08:00:00,20914\n2014-10-22 08:30:00,20612\n2014-10-22 09:00:00,20015\n2014-10-22 09:30:00,19001\n2014-10-22 10:00:00,17533\n2014-10-22 10:30:00,17877\n2014-10-22 11:00:00,16470\n2014-10-22 11:30:00,18266\n2014-10-22 12:00:00,17992\n2014-10-22 12:30:00,17419\n2014-10-22 13:00:00,16775\n2014-10-22 13:30:00,17378\n2014-10-22 14:00:00,18067\n2014-10-22 14:30:00,19841\n2014-10-22 15:00:00,18552\n2014-10-22 15:30:00,16825\n2014-10-22 16:00:00,14712\n2014-10-22 16:30:00,14439\n2014-10-22 17:00:00,17305\n2014-10-22 17:30:00,20949\n2014-10-22 18:00:00,22182\n2014-10-22 18:30:00,23886\n2014-10-22 19:00:00,25234\n2014-10-22 19:30:00,24731\n2014-10-22 20:00:00,25195\n2014-10-22 20:30:00,25551\n2014-10-22 21:00:00,26110\n2014-10-22 21:30:00,24842\n2014-10-22 22:00:00,23178\n2014-10-22 22:30:00,23408\n2014-10-22 23:00:00,21749\n2014-10-22 23:30:00,17918\n2014-10-23 00:00:00,13496\n2014-10-23 00:30:00,10416\n2014-10-23 01:00:00,8090\n2014-10-23 01:30:00,5946\n2014-10-23 02:00:00,4330\n2014-10-23 02:30:00,3282\n2014-10-23 03:00:00,2732\n2014-10-23 03:30:00,2524\n2014-10-23 04:00:00,2700\n2014-10-23 04:30:00,2290\n2014-10-23 05:00:00,2743\n2014-10-23 05:30:00,4732\n2014-10-23 06:00:00,7570\n2014-10-23 06:30:00,12751\n2014-10-23 07:00:00,16887\n2014-10-23 07:30:00,20268\n2014-10-23 08:00:00,21992\n2014-10-23 08:30:00,21301\n2014-10-23 09:00:00,20526\n2014-10-23 09:30:00,19251\n2014-10-23 10:00:00,18228\n2014-10-23 10:30:00,18603\n2014-10-23 11:00:00,18762\n2014-10-23 11:30:00,19645\n2014-10-23 12:00:00,20453\n2014-10-23 12:30:00,19400\n2014-10-23 13:00:00,18448\n2014-10-23 13:30:00,18199\n2014-10-23 14:00:00,18845\n2014-10-23 14:30:00,18973\n2014-10-23 15:00:00,17968\n2014-10-23 15:30:00,15112\n2014-10-23 16:00:00,13580\n2014-10-23 16:30:00,12751\n2014-10-23 17:00:00,15901\n2014-10-23 17:30:00,19774\n2014-10-23 18:00:00,21960\n2014-10-23 18:30:00,23790\n2014-10-23 19:00:00,24998\n2014-10-23 19:30:00,25414\n2014-10-23 20:00:00,26075\n2014-10-23 20:30:00,25616\n2014-10-23 21:00:00,25916\n2014-10-23 21:30:00,25589\n2014-10-23 22:00:00,25041\n2014-10-23 22:30:00,24891\n2014-10-23 23:00:00,23888\n2014-10-23 23:30:00,22464\n2014-10-24 00:00:00,19061\n2014-10-24 00:30:00,16689\n2014-10-24 01:00:00,13006\n2014-10-24 01:30:00,9512\n2014-10-24 02:00:00,7745\n2014-10-24 02:30:00,6037\n2014-10-24 03:00:00,5194\n2014-10-24 03:30:00,4419\n2014-10-24 04:00:00,4267\n2014-10-24 04:30:00,3366\n2014-10-24 05:00:00,3096\n2014-10-24 05:30:00,4532\n2014-10-24 06:00:00,6877\n2014-10-24 06:30:00,11826\n2014-10-24 07:00:00,15333\n2014-10-24 07:30:00,19013\n2014-10-24 08:00:00,20131\n2014-10-24 08:30:00,19779\n2014-10-24 09:00:00,19227\n2014-10-24 09:30:00,18824\n2014-10-24 10:00:00,17705\n2014-10-24 10:30:00,18111\n2014-10-24 11:00:00,17408\n2014-10-24 11:30:00,18509\n2014-10-24 12:00:00,18510\n2014-10-24 12:30:00,17910\n2014-10-24 13:00:00,17690\n2014-10-24 13:30:00,18149\n2014-10-24 14:00:00,19632\n2014-10-24 14:30:00,19426\n2014-10-24 15:00:00,18760\n2014-10-24 15:30:00,16379\n2014-10-24 16:00:00,15083\n2014-10-24 16:30:00,14553\n2014-10-24 17:00:00,17509\n2014-10-24 17:30:00,20911\n2014-10-24 18:00:00,22958\n2014-10-24 18:30:00,25257\n2014-10-24 19:00:00,26659\n2014-10-24 19:30:00,27104\n2014-10-24 20:00:00,26439\n2014-10-24 20:30:00,25840\n2014-10-24 21:00:00,25694\n2014-10-24 21:30:00,26093\n2014-10-24 22:00:00,26821\n2014-10-24 22:30:00,26870\n2014-10-24 23:00:00,26889\n2014-10-24 23:30:00,27283\n2014-10-25 00:00:00,25739\n2014-10-25 00:30:00,23889\n2014-10-25 01:00:00,22278\n2014-10-25 01:30:00,20337\n2014-10-25 02:00:00,19179\n2014-10-25 02:30:00,16566\n2014-10-25 03:00:00,14146\n2014-10-25 03:30:00,12015\n2014-10-25 04:00:00,10285\n2014-10-25 04:30:00,6316\n2014-10-25 05:00:00,4106\n2014-10-25 05:30:00,3465\n2014-10-25 06:00:00,3657\n2014-10-25 06:30:00,4756\n2014-10-25 07:00:00,6003\n2014-10-25 07:30:00,7853\n2014-10-25 08:00:00,9091\n2014-10-25 08:30:00,12209\n2014-10-25 09:00:00,13433\n2014-10-25 09:30:00,16768\n2014-10-25 10:00:00,16390\n2014-10-25 10:30:00,18666\n2014-10-25 11:00:00,19740\n2014-10-25 11:30:00,21266\n2014-10-25 12:00:00,21452\n2014-10-25 12:30:00,21613\n2014-10-25 13:00:00,21773\n2014-10-25 13:30:00,21440\n2014-10-25 14:00:00,20362\n2014-10-25 14:30:00,20601\n2014-10-25 15:00:00,20989\n2014-10-25 15:30:00,20210\n2014-10-25 16:00:00,18243\n2014-10-25 16:30:00,16875\n2014-10-25 17:00:00,19078\n2014-10-25 17:30:00,22244\n2014-10-25 18:00:00,23703\n2014-10-25 18:30:00,25544\n2014-10-25 19:00:00,27125\n2014-10-25 19:30:00,26539\n2014-10-25 20:00:00,24964\n2014-10-25 20:30:00,23665\n2014-10-25 21:00:00,23200\n2014-10-25 21:30:00,24238\n2014-10-25 22:00:00,25202\n2014-10-25 22:30:00,26140\n2014-10-25 23:00:00,27417\n2014-10-25 23:30:00,27692\n2014-10-26 00:00:00,26866\n2014-10-26 00:30:00,26254\n2014-10-26 01:00:00,24482\n2014-10-26 01:30:00,22425\n2014-10-26 02:00:00,20865\n2014-10-26 02:30:00,18801\n2014-10-26 03:00:00,16066\n2014-10-26 03:30:00,14093\n2014-10-26 04:00:00,11863\n2014-10-26 04:30:00,7194\n2014-10-26 05:00:00,4661\n2014-10-26 05:30:00,3656\n2014-10-26 06:00:00,3780\n2014-10-26 06:30:00,4116\n2014-10-26 07:00:00,4530\n2014-10-26 07:30:00,6287\n2014-10-26 08:00:00,7318\n2014-10-26 08:30:00,9260\n2014-10-26 09:00:00,10911\n2014-10-26 09:30:00,14136\n2014-10-26 10:00:00,15466\n2014-10-26 10:30:00,18611\n2014-10-26 11:00:00,18437\n2014-10-26 11:30:00,20375\n2014-10-26 12:00:00,20658\n2014-10-26 12:30:00,21283\n2014-10-26 13:00:00,20200\n2014-10-26 13:30:00,20135\n2014-10-26 14:00:00,20306\n2014-10-26 14:30:00,20404\n2014-10-26 15:00:00,19931\n2014-10-26 15:30:00,19772\n2014-10-26 16:00:00,18406\n2014-10-26 16:30:00,16957\n2014-10-26 17:00:00,17972\n2014-10-26 17:30:00,19563\n2014-10-26 18:00:00,20106\n2014-10-26 18:30:00,20449\n2014-10-26 19:00:00,19860\n2014-10-26 19:30:00,19343\n2014-10-26 20:00:00,18128\n2014-10-26 20:30:00,17298\n2014-10-26 21:00:00,16004\n2014-10-26 21:30:00,16422\n2014-10-26 22:00:00,14618\n2014-10-26 22:30:00,13017\n2014-10-26 23:00:00,11532\n2014-10-26 23:30:00,10089\n2014-10-27 00:00:00,8326\n2014-10-27 00:30:00,6579\n2014-10-27 01:00:00,4385\n2014-10-27 01:30:00,3470\n2014-10-27 02:00:00,2854\n2014-10-27 02:30:00,2128\n2014-10-27 03:00:00,1785\n2014-10-27 03:30:00,1707\n2014-10-27 04:00:00,2138\n2014-10-27 04:30:00,2406\n2014-10-27 05:00:00,2847\n2014-10-27 05:30:00,4951\n2014-10-27 06:00:00,7094\n2014-10-27 06:30:00,11090\n2014-10-27 07:00:00,14205\n2014-10-27 07:30:00,17506\n2014-10-27 08:00:00,18105\n2014-10-27 08:30:00,17656\n2014-10-27 09:00:00,17751\n2014-10-27 09:30:00,17096\n2014-10-27 10:00:00,15784\n2014-10-27 10:30:00,16086\n2014-10-27 11:00:00,14843\n2014-10-27 11:30:00,16446\n2014-10-27 12:00:00,16614\n2014-10-27 12:30:00,16155\n2014-10-27 13:00:00,15502\n2014-10-27 13:30:00,16293\n2014-10-27 14:00:00,16885\n2014-10-27 14:30:00,17759\n2014-10-27 15:00:00,18533\n2014-10-27 15:30:00,17617\n2014-10-27 16:00:00,16279\n2014-10-27 16:30:00,15551\n2014-10-27 17:00:00,18199\n2014-10-27 17:30:00,20618\n2014-10-27 18:00:00,22703\n2014-10-27 18:30:00,23897\n2014-10-27 19:00:00,24329\n2014-10-27 19:30:00,23182\n2014-10-27 20:00:00,21778\n2014-10-27 20:30:00,21251\n2014-10-27 21:00:00,21189\n2014-10-27 21:30:00,20884\n2014-10-27 22:00:00,19670\n2014-10-27 22:30:00,18163\n2014-10-27 23:00:00,15613\n2014-10-27 23:30:00,13371\n2014-10-28 00:00:00,10910\n2014-10-28 00:30:00,7638\n2014-10-28 01:00:00,5589\n2014-10-28 01:30:00,4215\n2014-10-28 02:00:00,3386\n2014-10-28 02:30:00,2753\n2014-10-28 03:00:00,2181\n2014-10-28 03:30:00,2034\n2014-10-28 04:00:00,2094\n2014-10-28 04:30:00,1896\n2014-10-28 05:00:00,2632\n2014-10-28 05:30:00,4581\n2014-10-28 06:00:00,6612\n2014-10-28 06:30:00,11609\n2014-10-28 07:00:00,15127\n2014-10-28 07:30:00,19097\n2014-10-28 08:00:00,19516\n2014-10-28 08:30:00,19422\n2014-10-28 09:00:00,18088\n2014-10-28 09:30:00,17669\n2014-10-28 10:00:00,16744\n2014-10-28 10:30:00,17075\n2014-10-28 11:00:00,16035\n2014-10-28 11:30:00,17421\n2014-10-28 12:00:00,17756\n2014-10-28 12:30:00,17057\n2014-10-28 13:00:00,16101\n2014-10-28 13:30:00,17443\n2014-10-28 14:00:00,17890\n2014-10-28 14:30:00,18651\n2014-10-28 15:00:00,18762\n2014-10-28 15:30:00,17135\n2014-10-28 16:00:00,15175\n2014-10-28 16:30:00,13958\n2014-10-28 17:00:00,16881\n2014-10-28 17:30:00,19615\n2014-10-28 18:00:00,22196\n2014-10-28 18:30:00,22906\n2014-10-28 19:00:00,23482\n2014-10-28 19:30:00,23088\n2014-10-28 20:00:00,23728\n2014-10-28 20:30:00,23210\n2014-10-28 21:00:00,23685\n2014-10-28 21:30:00,23843\n2014-10-28 22:00:00,22597\n2014-10-28 22:30:00,20923\n2014-10-28 23:00:00,19229\n2014-10-28 23:30:00,15963\n2014-10-29 00:00:00,12292\n2014-10-29 00:30:00,9190\n2014-10-29 01:00:00,6864\n2014-10-29 01:30:00,5693\n2014-10-29 02:00:00,4499\n2014-10-29 02:30:00,3304\n2014-10-29 03:00:00,2560\n2014-10-29 03:30:00,2485\n2014-10-29 04:00:00,2560\n2014-10-29 04:30:00,2248\n2014-10-29 05:00:00,2389\n2014-10-29 05:30:00,4313\n2014-10-29 06:00:00,6649\n2014-10-29 06:30:00,11289\n2014-10-29 07:00:00,15103\n2014-10-29 07:30:00,19437\n2014-10-29 08:00:00,19443\n2014-10-29 08:30:00,19707\n2014-10-29 09:00:00,18912\n2014-10-29 09:30:00,18203\n2014-10-29 10:00:00,16492\n2014-10-29 10:30:00,16837\n2014-10-29 11:00:00,16075\n2014-10-29 11:30:00,17160\n2014-10-29 12:00:00,17606\n2014-10-29 12:30:00,17267\n2014-10-29 13:00:00,16875\n2014-10-29 13:30:00,17940\n2014-10-29 14:00:00,18339\n2014-10-29 14:30:00,18971\n2014-10-29 15:00:00,19298\n2014-10-29 15:30:00,16665\n2014-10-29 16:00:00,15008\n2014-10-29 16:30:00,13873\n2014-10-29 17:00:00,17894\n2014-10-29 17:30:00,21574\n2014-10-29 18:00:00,22116\n2014-10-29 18:30:00,23582\n2014-10-29 19:00:00,25553\n2014-10-29 19:30:00,25299\n2014-10-29 20:00:00,24778\n2014-10-29 20:30:00,24729\n2014-10-29 21:00:00,24907\n2014-10-29 21:30:00,24810\n2014-10-29 22:00:00,24246\n2014-10-29 22:30:00,23250\n2014-10-29 23:00:00,20700\n2014-10-29 23:30:00,18631\n2014-10-30 00:00:00,14048\n2014-10-30 00:30:00,10691\n2014-10-30 01:00:00,8363\n2014-10-30 01:30:00,6405\n2014-10-30 02:00:00,5251\n2014-10-30 02:30:00,3714\n2014-10-30 03:00:00,3232\n2014-10-30 03:30:00,3057\n2014-10-30 04:00:00,3005\n2014-10-30 04:30:00,2506\n2014-10-30 05:00:00,2821\n2014-10-30 05:30:00,5287\n2014-10-30 06:00:00,7427\n2014-10-30 06:30:00,12248\n2014-10-30 07:00:00,15618\n2014-10-30 07:30:00,19528\n2014-10-30 08:00:00,19813\n2014-10-30 08:30:00,19680\n2014-10-30 09:00:00,19351\n2014-10-30 09:30:00,18967\n2014-10-30 10:00:00,17899\n2014-10-30 10:30:00,17994\n2014-10-30 11:00:00,17167\n2014-10-30 11:30:00,18094\n2014-10-30 12:00:00,18575\n2014-10-30 12:30:00,18022\n2014-10-30 13:00:00,17359\n2014-10-30 13:30:00,18035\n2014-10-30 14:00:00,18733\n2014-10-30 14:30:00,19410\n2014-10-30 15:00:00,18991\n2014-10-30 15:30:00,16749\n2014-10-30 16:00:00,14604\n2014-10-30 16:30:00,13367\n2014-10-30 17:00:00,16382\n2014-10-30 17:30:00,19879\n2014-10-30 18:00:00,21735\n2014-10-30 18:30:00,23802\n2014-10-30 19:00:00,24832\n2014-10-30 19:30:00,24964\n2014-10-30 20:00:00,25791\n2014-10-30 20:30:00,25810\n2014-10-30 21:00:00,25816\n2014-10-30 21:30:00,25849\n2014-10-30 22:00:00,24877\n2014-10-30 22:30:00,25072\n2014-10-30 23:00:00,24763\n2014-10-30 23:30:00,22241\n2014-10-31 00:00:00,19957\n2014-10-31 00:30:00,16881\n2014-10-31 01:00:00,13588\n2014-10-31 01:30:00,10958\n2014-10-31 02:00:00,9119\n2014-10-31 02:30:00,7589\n2014-10-31 03:00:00,6221\n2014-10-31 03:30:00,4936\n2014-10-31 04:00:00,4796\n2014-10-31 04:30:00,3555\n2014-10-31 05:00:00,3337\n2014-10-31 05:30:00,4665\n2014-10-31 06:00:00,7084\n2014-10-31 06:30:00,11681\n2014-10-31 07:00:00,14822\n2014-10-31 07:30:00,19004\n2014-10-31 08:00:00,20306\n2014-10-31 08:30:00,20687\n2014-10-31 09:00:00,19585\n2014-10-31 09:30:00,18702\n2014-10-31 10:00:00,18099\n2014-10-31 10:30:00,18335\n2014-10-31 11:00:00,17653\n2014-10-31 11:30:00,18889\n2014-10-31 12:00:00,19146\n2014-10-31 12:30:00,18833\n2014-10-31 13:00:00,18315\n2014-10-31 13:30:00,18917\n2014-10-31 14:00:00,20430\n2014-10-31 14:30:00,20608\n2014-10-31 15:00:00,19915\n2014-10-31 15:30:00,16981\n2014-10-31 16:00:00,15045\n2014-10-31 16:30:00,13978\n2014-10-31 17:00:00,16891\n2014-10-31 17:30:00,20025\n2014-10-31 18:00:00,21438\n2014-10-31 18:30:00,23813\n2014-10-31 19:00:00,25517\n2014-10-31 19:30:00,25493\n2014-10-31 20:00:00,25475\n2014-10-31 20:30:00,26996\n2014-10-31 21:00:00,27015\n2014-10-31 21:30:00,27264\n2014-10-31 22:00:00,26977\n2014-10-31 22:30:00,26343\n2014-10-31 23:00:00,26333\n2014-10-31 23:30:00,26524\n2014-11-01 00:00:00,25425\n2014-11-01 00:30:00,24937\n2014-11-01 01:00:00,24946\n2014-11-01 01:30:00,23736\n2014-11-01 02:00:00,23245\n2014-11-01 02:30:00,21459\n2014-11-01 03:00:00,19849\n2014-11-01 03:30:00,17679\n2014-11-01 04:00:00,15018\n2014-11-01 04:30:00,10600\n2014-11-01 05:00:00,7758\n2014-11-01 05:30:00,5907\n2014-11-01 06:00:00,5743\n2014-11-01 06:30:00,6223\n2014-11-01 07:00:00,6386\n2014-11-01 07:30:00,9098\n2014-11-01 08:00:00,9864\n2014-11-01 08:30:00,12903\n2014-11-01 09:00:00,14185\n2014-11-01 09:30:00,18584\n2014-11-01 10:00:00,19066\n2014-11-01 10:30:00,22683\n2014-11-01 11:00:00,23292\n2014-11-01 11:30:00,24154\n2014-11-01 12:00:00,25310\n2014-11-01 12:30:00,26625\n2014-11-01 13:00:00,25584\n2014-11-01 13:30:00,25115\n2014-11-01 14:00:00,23935\n2014-11-01 14:30:00,23341\n2014-11-01 15:00:00,23337\n2014-11-01 15:30:00,22199\n2014-11-01 16:00:00,20008\n2014-11-01 16:30:00,18443\n2014-11-01 17:00:00,20865\n2014-11-01 17:30:00,23719\n2014-11-01 18:00:00,25241\n2014-11-01 18:30:00,27383\n2014-11-01 19:00:00,28398\n2014-11-01 19:30:00,27426\n2014-11-01 20:00:00,26537\n2014-11-01 20:30:00,25980\n2014-11-01 21:00:00,24601\n2014-11-01 21:30:00,24838\n2014-11-01 22:00:00,26372\n2014-11-01 22:30:00,26567\n2014-11-01 23:00:00,25879\n2014-11-01 23:30:00,26125\n2014-11-02 00:00:00,25110\n2014-11-02 00:30:00,23109\n2014-11-02 01:00:00,39197\n2014-11-02 01:30:00,35212\n2014-11-02 02:00:00,13259\n2014-11-02 02:30:00,12250\n2014-11-02 03:00:00,10013\n2014-11-02 03:30:00,7898\n2014-11-02 04:00:00,6375\n2014-11-02 04:30:00,4532\n2014-11-02 05:00:00,5116\n2014-11-02 05:30:00,5232\n2014-11-02 06:00:00,4542\n2014-11-02 06:30:00,5298\n2014-11-02 07:00:00,5155\n2014-11-02 07:30:00,6029\n2014-11-02 08:00:00,6280\n2014-11-02 08:30:00,8771\n2014-11-02 09:00:00,10151\n2014-11-02 09:30:00,12501\n2014-11-02 10:00:00,13990\n2014-11-02 10:30:00,16534\n2014-11-02 11:00:00,17133\n2014-11-02 11:30:00,18775\n2014-11-02 12:00:00,18985\n2014-11-02 12:30:00,19911\n2014-11-02 13:00:00,19123\n2014-11-02 13:30:00,19524\n2014-11-02 14:00:00,19640\n2014-11-02 14:30:00,18364\n2014-11-02 15:00:00,17940\n2014-11-02 15:30:00,17949\n2014-11-02 16:00:00,17288\n2014-11-02 16:30:00,16326\n2014-11-02 17:00:00,17522\n2014-11-02 17:30:00,19243\n2014-11-02 18:00:00,20291\n2014-11-02 18:30:00,21649\n2014-11-02 19:00:00,22839\n2014-11-02 19:30:00,21772\n2014-11-02 20:00:00,20994\n2014-11-02 20:30:00,19774\n2014-11-02 21:00:00,18398\n2014-11-02 21:30:00,17764\n2014-11-02 22:00:00,17334\n2014-11-02 22:30:00,15431\n2014-11-02 23:00:00,12958\n2014-11-02 23:30:00,10224\n2014-11-03 00:00:00,8771\n2014-11-03 00:30:00,6045\n2014-11-03 01:00:00,4413\n2014-11-03 01:30:00,3235\n2014-11-03 02:00:00,2688\n2014-11-03 02:30:00,1983\n2014-11-03 03:00:00,1756\n2014-11-03 03:30:00,1683\n2014-11-03 04:00:00,2140\n2014-11-03 04:30:00,2288\n2014-11-03 05:00:00,2948\n2014-11-03 05:30:00,4813\n2014-11-03 06:00:00,8044\n2014-11-03 06:30:00,12885\n2014-11-03 07:00:00,14627\n2014-11-03 07:30:00,18111\n2014-11-03 08:00:00,18266\n2014-11-03 08:30:00,18384\n2014-11-03 09:00:00,18104\n2014-11-03 09:30:00,17357\n2014-11-03 10:00:00,16008\n2014-11-03 10:30:00,16379\n2014-11-03 11:00:00,15351\n2014-11-03 11:30:00,16770\n2014-11-03 12:00:00,16711\n2014-11-03 12:30:00,17011\n2014-11-03 13:00:00,16373\n2014-11-03 13:30:00,17097\n2014-11-03 14:00:00,17364\n2014-11-03 14:30:00,18333\n2014-11-03 15:00:00,18428\n2014-11-03 15:30:00,16974\n2014-11-03 16:00:00,16139\n2014-11-03 16:30:00,15205\n2014-11-03 17:00:00,17392\n2014-11-03 17:30:00,20141\n2014-11-03 18:00:00,22581\n2014-11-03 18:30:00,23098\n2014-11-03 19:00:00,23154\n2014-11-03 19:30:00,22688\n2014-11-03 20:00:00,22047\n2014-11-03 20:30:00,21283\n2014-11-03 21:00:00,21070\n2014-11-03 21:30:00,19910\n2014-11-03 22:00:00,20541\n2014-11-03 22:30:00,18105\n2014-11-03 23:00:00,14554\n2014-11-03 23:30:00,12695\n2014-11-04 00:00:00,10667\n2014-11-04 00:30:00,8479\n2014-11-04 01:00:00,6005\n2014-11-04 01:30:00,3899\n2014-11-04 02:00:00,3111\n2014-11-04 02:30:00,2526\n2014-11-04 03:00:00,2112\n2014-11-04 03:30:00,1885\n2014-11-04 04:00:00,1921\n2014-11-04 04:30:00,2267\n2014-11-04 05:00:00,2413\n2014-11-04 05:30:00,4413\n2014-11-04 06:00:00,7168\n2014-11-04 06:30:00,12160\n2014-11-04 07:00:00,14845\n2014-11-04 07:30:00,18403\n2014-11-04 08:00:00,18445\n2014-11-04 08:30:00,19018\n2014-11-04 09:00:00,18105\n2014-11-04 09:30:00,17459\n2014-11-04 10:00:00,16381\n2014-11-04 10:30:00,16623\n2014-11-04 11:00:00,16144\n2014-11-04 11:30:00,17318\n2014-11-04 12:00:00,17658\n2014-11-04 12:30:00,17108\n2014-11-04 13:00:00,16178\n2014-11-04 13:30:00,17973\n2014-11-04 14:00:00,18152\n2014-11-04 14:30:00,18445\n2014-11-04 15:00:00,18556\n2014-11-04 15:30:00,16865\n2014-11-04 16:00:00,14505\n2014-11-04 16:30:00,13471\n2014-11-04 17:00:00,15853\n2014-11-04 17:30:00,18369\n2014-11-04 18:00:00,20968\n2014-11-04 18:30:00,22239\n2014-11-04 19:00:00,22626\n2014-11-04 19:30:00,22924\n2014-11-04 20:00:00,22853\n2014-11-04 20:30:00,22393\n2014-11-04 21:00:00,23088\n2014-11-04 21:30:00,22431\n2014-11-04 22:00:00,22239\n2014-11-04 22:30:00,19918\n2014-11-04 23:00:00,17675\n2014-11-04 23:30:00,14953\n2014-11-05 00:00:00,12025\n2014-11-05 00:30:00,8767\n2014-11-05 01:00:00,6670\n2014-11-05 01:30:00,5197\n2014-11-05 02:00:00,4289\n2014-11-05 02:30:00,3186\n2014-11-05 03:00:00,2747\n2014-11-05 03:30:00,2257\n2014-11-05 04:00:00,2397\n2014-11-05 04:30:00,2205\n2014-11-05 05:00:00,2625\n2014-11-05 05:30:00,4404\n2014-11-05 06:00:00,7007\n2014-11-05 06:30:00,12065\n2014-11-05 07:00:00,15803\n2014-11-05 07:30:00,19844\n2014-11-05 08:00:00,19937\n2014-11-05 08:30:00,20299\n2014-11-05 09:00:00,19584\n2014-11-05 09:30:00,19313\n2014-11-05 10:00:00,16887\n2014-11-05 10:30:00,17118\n2014-11-05 11:00:00,16847\n2014-11-05 11:30:00,18356\n2014-11-05 12:00:00,18124\n2014-11-05 12:30:00,17783\n2014-11-05 13:00:00,17223\n2014-11-05 13:30:00,17852\n2014-11-05 14:00:00,18374\n2014-11-05 14:30:00,18641\n2014-11-05 15:00:00,18913\n2014-11-05 15:30:00,16314\n2014-11-05 16:00:00,13917\n2014-11-05 16:30:00,13151\n2014-11-05 17:00:00,16100\n2014-11-05 17:30:00,19136\n2014-11-05 18:00:00,21762\n2014-11-05 18:30:00,22829\n2014-11-05 19:00:00,23705\n2014-11-05 19:30:00,23740\n2014-11-05 20:00:00,23789\n2014-11-05 20:30:00,23389\n2014-11-05 21:00:00,24122\n2014-11-05 21:30:00,24156\n2014-11-05 22:00:00,23679\n2014-11-05 22:30:00,22803\n2014-11-05 23:00:00,20814\n2014-11-05 23:30:00,17376\n2014-11-06 00:00:00,13846\n2014-11-06 00:30:00,10387\n2014-11-06 01:00:00,8384\n2014-11-06 01:30:00,6455\n2014-11-06 02:00:00,5043\n2014-11-06 02:30:00,3738\n2014-11-06 03:00:00,3155\n2014-11-06 03:30:00,2758\n2014-11-06 04:00:00,3122\n2014-11-06 04:30:00,2625\n2014-11-06 05:00:00,2760\n2014-11-06 05:30:00,4995\n2014-11-06 06:00:00,8021\n2014-11-06 06:30:00,13803\n2014-11-06 07:00:00,17405\n2014-11-06 07:30:00,20841\n2014-11-06 08:00:00,21338\n2014-11-06 08:30:00,21281\n2014-11-06 09:00:00,20108\n2014-11-06 09:30:00,20198\n2014-11-06 10:00:00,19035\n2014-11-06 10:30:00,19155\n2014-11-06 11:00:00,17964\n2014-11-06 11:30:00,18680\n2014-11-06 12:00:00,18600\n2014-11-06 12:30:00,17556\n2014-11-06 13:00:00,17373\n2014-11-06 13:30:00,17832\n2014-11-06 14:00:00,18087\n2014-11-06 14:30:00,18057\n2014-11-06 15:00:00,17634\n2014-11-06 15:30:00,15492\n2014-11-06 16:00:00,13677\n2014-11-06 16:30:00,12574\n2014-11-06 17:00:00,15818\n2014-11-06 17:30:00,19350\n2014-11-06 18:00:00,21754\n2014-11-06 18:30:00,23740\n2014-11-06 19:00:00,24666\n2014-11-06 19:30:00,25142\n2014-11-06 20:00:00,25597\n2014-11-06 20:30:00,25126\n2014-11-06 21:00:00,25312\n2014-11-06 21:30:00,26067\n2014-11-06 22:00:00,25613\n2014-11-06 22:30:00,23971\n2014-11-06 23:00:00,22859\n2014-11-06 23:30:00,21287\n2014-11-07 00:00:00,18308\n2014-11-07 00:30:00,14352\n2014-11-07 01:00:00,11746\n2014-11-07 01:30:00,9042\n2014-11-07 02:00:00,7318\n2014-11-07 02:30:00,6009\n2014-11-07 03:00:00,5364\n2014-11-07 03:30:00,4336\n2014-11-07 04:00:00,4008\n2014-11-07 04:30:00,3263\n2014-11-07 05:00:00,3183\n2014-11-07 05:30:00,4813\n2014-11-07 06:00:00,7519\n2014-11-07 06:30:00,12074\n2014-11-07 07:00:00,15249\n2014-11-07 07:30:00,19300\n2014-11-07 08:00:00,19564\n2014-11-07 08:30:00,19132\n2014-11-07 09:00:00,18454\n2014-11-07 09:30:00,17950\n2014-11-07 10:00:00,17374\n2014-11-07 10:30:00,17674\n2014-11-07 11:00:00,17016\n2014-11-07 11:30:00,18484\n2014-11-07 12:00:00,18460\n2014-11-07 12:30:00,17693\n2014-11-07 13:00:00,18093\n2014-11-07 13:30:00,19918\n2014-11-07 14:00:00,19945\n2014-11-07 14:30:00,19077\n2014-11-07 15:00:00,18186\n2014-11-07 15:30:00,16030\n2014-11-07 16:00:00,14092\n2014-11-07 16:30:00,13270\n2014-11-07 17:00:00,15935\n2014-11-07 17:30:00,19419\n2014-11-07 18:00:00,21778\n2014-11-07 18:30:00,24460\n2014-11-07 19:00:00,26246\n2014-11-07 19:30:00,27224\n2014-11-07 20:00:00,26862\n2014-11-07 20:30:00,27340\n2014-11-07 21:00:00,27335\n2014-11-07 21:30:00,26727\n2014-11-07 22:00:00,27181\n2014-11-07 22:30:00,27761\n2014-11-07 23:00:00,27193\n2014-11-07 23:30:00,26857\n2014-11-08 00:00:00,25692\n2014-11-08 00:30:00,24162\n2014-11-08 01:00:00,22219\n2014-11-08 01:30:00,20748\n2014-11-08 02:00:00,19471\n2014-11-08 02:30:00,16940\n2014-11-08 03:00:00,14431\n2014-11-08 03:30:00,11898\n2014-11-08 04:00:00,10264\n2014-11-08 04:30:00,5942\n2014-11-08 05:00:00,4063\n2014-11-08 05:30:00,3498\n2014-11-08 06:00:00,3726\n2014-11-08 06:30:00,5242\n2014-11-08 07:00:00,5655\n2014-11-08 07:30:00,8191\n2014-11-08 08:00:00,9371\n2014-11-08 08:30:00,13050\n2014-11-08 09:00:00,13820\n2014-11-08 09:30:00,17437\n2014-11-08 10:00:00,17281\n2014-11-08 10:30:00,19718\n2014-11-08 11:00:00,19999\n2014-11-08 11:30:00,22047\n2014-11-08 12:00:00,22352\n2014-11-08 12:30:00,22898\n2014-11-08 13:00:00,22660\n2014-11-08 13:30:00,23047\n2014-11-08 14:00:00,21976\n2014-11-08 14:30:00,22746\n2014-11-08 15:00:00,22382\n2014-11-08 15:30:00,21956\n2014-11-08 16:00:00,18619\n2014-11-08 16:30:00,15861\n2014-11-08 17:00:00,18326\n2014-11-08 17:30:00,22332\n2014-11-08 18:00:00,25097\n2014-11-08 18:30:00,27236\n2014-11-08 19:00:00,27898\n2014-11-08 19:30:00,26790\n2014-11-08 20:00:00,25561\n2014-11-08 20:30:00,24344\n2014-11-08 21:00:00,23890\n2014-11-08 21:30:00,24609\n2014-11-08 22:00:00,26595\n2014-11-08 22:30:00,27260\n2014-11-08 23:00:00,27998\n2014-11-08 23:30:00,27854\n2014-11-09 00:00:00,26931\n2014-11-09 00:30:00,25208\n2014-11-09 01:00:00,23782\n2014-11-09 01:30:00,22472\n2014-11-09 02:00:00,21183\n2014-11-09 02:30:00,18443\n2014-11-09 03:00:00,16105\n2014-11-09 03:30:00,13801\n2014-11-09 04:00:00,11997\n2014-11-09 04:30:00,7112\n2014-11-09 05:00:00,4627\n2014-11-09 05:30:00,3683\n2014-11-09 06:00:00,3587\n2014-11-09 06:30:00,4158\n2014-11-09 07:00:00,4351\n2014-11-09 07:30:00,5823\n2014-11-09 08:00:00,6850\n2014-11-09 08:30:00,9839\n2014-11-09 09:00:00,11422\n2014-11-09 09:30:00,14897\n2014-11-09 10:00:00,15815\n2014-11-09 10:30:00,18787\n2014-11-09 11:00:00,18880\n2014-11-09 11:30:00,19871\n2014-11-09 12:00:00,20722\n2014-11-09 12:30:00,21774\n2014-11-09 13:00:00,21318\n2014-11-09 13:30:00,20699\n2014-11-09 14:00:00,20831\n2014-11-09 14:30:00,20467\n2014-11-09 15:00:00,20249\n2014-11-09 15:30:00,20100\n2014-11-09 16:00:00,18688\n2014-11-09 16:30:00,17249\n2014-11-09 17:00:00,18573\n2014-11-09 17:30:00,19937\n2014-11-09 18:00:00,20564\n2014-11-09 18:30:00,20132\n2014-11-09 19:00:00,19654\n2014-11-09 19:30:00,18449\n2014-11-09 20:00:00,17176\n2014-11-09 20:30:00,17596\n2014-11-09 21:00:00,16431\n2014-11-09 21:30:00,15860\n2014-11-09 22:00:00,15253\n2014-11-09 22:30:00,13845\n2014-11-09 23:00:00,11656\n2014-11-09 23:30:00,9818\n2014-11-10 00:00:00,7870\n2014-11-10 00:30:00,6079\n2014-11-10 01:00:00,4644\n2014-11-10 01:30:00,3501\n2014-11-10 02:00:00,2989\n2014-11-10 02:30:00,2247\n2014-11-10 03:00:00,1853\n2014-11-10 03:30:00,1791\n2014-11-10 04:00:00,2189\n2014-11-10 04:30:00,2328\n2014-11-10 05:00:00,2827\n2014-11-10 05:30:00,4738\n2014-11-10 06:00:00,6803\n2014-11-10 06:30:00,11738\n2014-11-10 07:00:00,14296\n2014-11-10 07:30:00,17240\n2014-11-10 08:00:00,17657\n2014-11-10 08:30:00,17904\n2014-11-10 09:00:00,17705\n2014-11-10 09:30:00,16814\n2014-11-10 10:00:00,15908\n2014-11-10 10:30:00,15545\n2014-11-10 11:00:00,15119\n2014-11-10 11:30:00,16241\n2014-11-10 12:00:00,16354\n2014-11-10 12:30:00,16002\n2014-11-10 13:00:00,15560\n2014-11-10 13:30:00,16855\n2014-11-10 14:00:00,17292\n2014-11-10 14:30:00,17780\n2014-11-10 15:00:00,18467\n2014-11-10 15:30:00,17048\n2014-11-10 16:00:00,15386\n2014-11-10 16:30:00,15329\n2014-11-10 17:00:00,17444\n2014-11-10 17:30:00,19765\n2014-11-10 18:00:00,22418\n2014-11-10 18:30:00,22794\n2014-11-10 19:00:00,23094\n2014-11-10 19:30:00,22197\n2014-11-10 20:00:00,21796\n2014-11-10 20:30:00,20849\n2014-11-10 21:00:00,21169\n2014-11-10 21:30:00,20613\n2014-11-10 22:00:00,20734\n2014-11-10 22:30:00,17540\n2014-11-10 23:00:00,15189\n2014-11-10 23:30:00,12879\n2014-11-11 00:00:00,10511\n2014-11-11 00:30:00,7509\n2014-11-11 01:00:00,6277\n2014-11-11 01:30:00,4622\n2014-11-11 02:00:00,3785\n2014-11-11 02:30:00,2970\n2014-11-11 03:00:00,2332\n2014-11-11 03:30:00,2166\n2014-11-11 04:00:00,2179\n2014-11-11 04:30:00,2040\n2014-11-11 05:00:00,2278\n2014-11-11 05:30:00,3860\n2014-11-11 06:00:00,5517\n2014-11-11 06:30:00,9569\n2014-11-11 07:00:00,12272\n2014-11-11 07:30:00,16460\n2014-11-11 08:00:00,16976\n2014-11-11 08:30:00,17823\n2014-11-11 09:00:00,17655\n2014-11-11 09:30:00,16946\n2014-11-11 10:00:00,15846\n2014-11-11 10:30:00,15835\n2014-11-11 11:00:00,15442\n2014-11-11 11:30:00,16069\n2014-11-11 12:00:00,15966\n2014-11-11 12:30:00,15584\n2014-11-11 13:00:00,15384\n2014-11-11 13:30:00,15909\n2014-11-11 14:00:00,16140\n2014-11-11 14:30:00,16337\n2014-11-11 15:00:00,16381\n2014-11-11 15:30:00,15196\n2014-11-11 16:00:00,13003\n2014-11-11 16:30:00,12213\n2014-11-11 17:00:00,15103\n2014-11-11 17:30:00,18301\n2014-11-11 18:00:00,20626\n2014-11-11 18:30:00,22533\n2014-11-11 19:00:00,22905\n2014-11-11 19:30:00,22181\n2014-11-11 20:00:00,21899\n2014-11-11 20:30:00,21789\n2014-11-11 21:00:00,22253\n2014-11-11 21:30:00,22515\n2014-11-11 22:00:00,21410\n2014-11-11 22:30:00,19812\n2014-11-11 23:00:00,17135\n2014-11-11 23:30:00,13567\n2014-11-12 00:00:00,10829\n2014-11-12 00:30:00,7850\n2014-11-12 01:00:00,6572\n2014-11-12 01:30:00,4748\n2014-11-12 02:00:00,3777\n2014-11-12 02:30:00,3255\n2014-11-12 03:00:00,2415\n2014-11-12 03:30:00,2279\n2014-11-12 04:00:00,2353\n2014-11-12 04:30:00,2142\n2014-11-12 05:00:00,2540\n2014-11-12 05:30:00,4177\n2014-11-12 06:00:00,6843\n2014-11-12 06:30:00,11818\n2014-11-12 07:00:00,15665\n2014-11-12 07:30:00,19785\n2014-11-12 08:00:00,19813\n2014-11-12 08:30:00,19623\n2014-11-12 09:00:00,18444\n2014-11-12 09:30:00,17937\n2014-11-12 10:00:00,16552\n2014-11-12 10:30:00,17394\n2014-11-12 11:00:00,16960\n2014-11-12 11:30:00,18105\n2014-11-12 12:00:00,17724\n2014-11-12 12:30:00,16327\n2014-11-12 13:00:00,16527\n2014-11-12 13:30:00,17290\n2014-11-12 14:00:00,18042\n2014-11-12 14:30:00,18250\n2014-11-12 15:00:00,17656\n2014-11-12 15:30:00,16288\n2014-11-12 16:00:00,13992\n2014-11-12 16:30:00,12912\n2014-11-12 17:00:00,16032\n2014-11-12 17:30:00,18814\n2014-11-12 18:00:00,21296\n2014-11-12 18:30:00,23115\n2014-11-12 19:00:00,23859\n2014-11-12 19:30:00,24749\n2014-11-12 20:00:00,23879\n2014-11-12 20:30:00,23815\n2014-11-12 21:00:00,24595\n2014-11-12 21:30:00,24494\n2014-11-12 22:00:00,24213\n2014-11-12 22:30:00,22931\n2014-11-12 23:00:00,20785\n2014-11-12 23:30:00,17464\n2014-11-13 00:00:00,13303\n2014-11-13 00:30:00,10350\n2014-11-13 01:00:00,7850\n2014-11-13 01:30:00,5961\n2014-11-13 02:00:00,5051\n2014-11-13 02:30:00,3833\n2014-11-13 03:00:00,3006\n2014-11-13 03:30:00,2515\n2014-11-13 04:00:00,2816\n2014-11-13 04:30:00,2248\n2014-11-13 05:00:00,2621\n2014-11-13 05:30:00,4392\n2014-11-13 06:00:00,7062\n2014-11-13 06:30:00,12333\n2014-11-13 07:00:00,15661\n2014-11-13 07:30:00,19597\n2014-11-13 08:00:00,20200\n2014-11-13 08:30:00,19843\n2014-11-13 09:00:00,19031\n2014-11-13 09:30:00,18253\n2014-11-13 10:00:00,17244\n2014-11-13 10:30:00,17402\n2014-11-13 11:00:00,17286\n2014-11-13 11:30:00,18936\n2014-11-13 12:00:00,18516\n2014-11-13 12:30:00,17635\n2014-11-13 13:00:00,17343\n2014-11-13 13:30:00,19090\n2014-11-13 14:00:00,19197\n2014-11-13 14:30:00,19207\n2014-11-13 15:00:00,18412\n2014-11-13 15:30:00,16391\n2014-11-13 16:00:00,13472\n2014-11-13 16:30:00,12807\n2014-11-13 17:00:00,16097\n2014-11-13 17:30:00,19322\n2014-11-13 18:00:00,21645\n2014-11-13 18:30:00,22745\n2014-11-13 19:00:00,24219\n2014-11-13 19:30:00,25443\n2014-11-13 20:00:00,25695\n2014-11-13 20:30:00,25994\n2014-11-13 21:00:00,26424\n2014-11-13 21:30:00,25450\n2014-11-13 22:00:00,24621\n2014-11-13 22:30:00,23727\n2014-11-13 23:00:00,22503\n2014-11-13 23:30:00,20709\n2014-11-14 00:00:00,17932\n2014-11-14 00:30:00,14668\n2014-11-14 01:00:00,11986\n2014-11-14 01:30:00,9213\n2014-11-14 02:00:00,7202\n2014-11-14 02:30:00,5552\n2014-11-14 03:00:00,5023\n2014-11-14 03:30:00,3900\n2014-11-14 04:00:00,4039\n2014-11-14 04:30:00,2987\n2014-11-14 05:00:00,3090\n2014-11-14 05:30:00,4737\n2014-11-14 06:00:00,7102\n2014-11-14 06:30:00,12268\n2014-11-14 07:00:00,15903\n2014-11-14 07:30:00,20015\n2014-11-14 08:00:00,20432\n2014-11-14 08:30:00,20735\n2014-11-14 09:00:00,19149\n2014-11-14 09:30:00,18665\n2014-11-14 10:00:00,17992\n2014-11-14 10:30:00,17773\n2014-11-14 11:00:00,17786\n2014-11-14 11:30:00,18128\n2014-11-14 12:00:00,18355\n2014-11-14 12:30:00,17629\n2014-11-14 13:00:00,17104\n2014-11-14 13:30:00,18151\n2014-11-14 14:00:00,18892\n2014-11-14 14:30:00,19540\n2014-11-14 15:00:00,18557\n2014-11-14 15:30:00,16263\n2014-11-14 16:00:00,14668\n2014-11-14 16:30:00,13473\n2014-11-14 17:00:00,16747\n2014-11-14 17:30:00,20594\n2014-11-14 18:00:00,23151\n2014-11-14 18:30:00,25446\n2014-11-14 19:00:00,27196\n2014-11-14 19:30:00,26881\n2014-11-14 20:00:00,25994\n2014-11-14 20:30:00,25879\n2014-11-14 21:00:00,26301\n2014-11-14 21:30:00,27136\n2014-11-14 22:00:00,26940\n2014-11-14 22:30:00,26834\n2014-11-14 23:00:00,26960\n2014-11-14 23:30:00,26107\n2014-11-15 00:00:00,25034\n2014-11-15 00:30:00,24103\n2014-11-15 01:00:00,22682\n2014-11-15 01:30:00,20630\n2014-11-15 02:00:00,19226\n2014-11-15 02:30:00,16555\n2014-11-15 03:00:00,14088\n2014-11-15 03:30:00,12491\n2014-11-15 04:00:00,10208\n2014-11-15 04:30:00,5853\n2014-11-15 05:00:00,4019\n2014-11-15 05:30:00,3477\n2014-11-15 06:00:00,3582\n2014-11-15 06:30:00,4936\n2014-11-15 07:00:00,5272\n2014-11-15 07:30:00,7427\n2014-11-15 08:00:00,8646\n2014-11-15 08:30:00,12313\n2014-11-15 09:00:00,13426\n2014-11-15 09:30:00,17040\n2014-11-15 10:00:00,16811\n2014-11-15 10:30:00,19069\n2014-11-15 11:00:00,19423\n2014-11-15 11:30:00,21552\n2014-11-15 12:00:00,21685\n2014-11-15 12:30:00,22380\n2014-11-15 13:00:00,21954\n2014-11-15 13:30:00,21926\n2014-11-15 14:00:00,21851\n2014-11-15 14:30:00,22014\n2014-11-15 15:00:00,22075\n2014-11-15 15:30:00,20936\n2014-11-15 16:00:00,18358\n2014-11-15 16:30:00,15289\n2014-11-15 17:00:00,17742\n2014-11-15 17:30:00,21769\n2014-11-15 18:00:00,24058\n2014-11-15 18:30:00,26029\n2014-11-15 19:00:00,27266\n2014-11-15 19:30:00,26817\n2014-11-15 20:00:00,25049\n2014-11-15 20:30:00,23713\n2014-11-15 21:00:00,23324\n2014-11-15 21:30:00,23970\n2014-11-15 22:00:00,26325\n2014-11-15 22:30:00,26139\n2014-11-15 23:00:00,27312\n2014-11-15 23:30:00,28114\n2014-11-16 00:00:00,26651\n2014-11-16 00:30:00,25212\n2014-11-16 01:00:00,24273\n2014-11-16 01:30:00,22665\n2014-11-16 02:00:00,21069\n2014-11-16 02:30:00,18803\n2014-11-16 03:00:00,16590\n2014-11-16 03:30:00,14414\n2014-11-16 04:00:00,12228\n2014-11-16 04:30:00,7230\n2014-11-16 05:00:00,4624\n2014-11-16 05:30:00,3594\n2014-11-16 06:00:00,3332\n2014-11-16 06:30:00,4083\n2014-11-16 07:00:00,4416\n2014-11-16 07:30:00,5214\n2014-11-16 08:00:00,6429\n2014-11-16 08:30:00,8898\n2014-11-16 09:00:00,10911\n2014-11-16 09:30:00,13475\n2014-11-16 10:00:00,15157\n2014-11-16 10:30:00,18595\n2014-11-16 11:00:00,19233\n2014-11-16 11:30:00,20372\n2014-11-16 12:00:00,21847\n2014-11-16 12:30:00,21695\n2014-11-16 13:00:00,21880\n2014-11-16 13:30:00,21047\n2014-11-16 14:00:00,21107\n2014-11-16 14:30:00,20602\n2014-11-16 15:00:00,19817\n2014-11-16 15:30:00,19310\n2014-11-16 16:00:00,18479\n2014-11-16 16:30:00,16296\n2014-11-16 17:00:00,17751\n2014-11-16 17:30:00,19230\n2014-11-16 18:00:00,19883\n2014-11-16 18:30:00,19768\n2014-11-16 19:00:00,18931\n2014-11-16 19:30:00,17936\n2014-11-16 20:00:00,16360\n2014-11-16 20:30:00,16885\n2014-11-16 21:00:00,16000\n2014-11-16 21:30:00,14902\n2014-11-16 22:00:00,13707\n2014-11-16 22:30:00,13406\n2014-11-16 23:00:00,12021\n2014-11-16 23:30:00,11115\n2014-11-17 00:00:00,8317\n2014-11-17 00:30:00,5887\n2014-11-17 01:00:00,4464\n2014-11-17 01:30:00,3425\n2014-11-17 02:00:00,2961\n2014-11-17 02:30:00,2328\n2014-11-17 03:00:00,2020\n2014-11-17 03:30:00,1764\n2014-11-17 04:00:00,2139\n2014-11-17 04:30:00,2296\n2014-11-17 05:00:00,2960\n2014-11-17 05:30:00,5121\n2014-11-17 06:00:00,7871\n2014-11-17 06:30:00,11902\n2014-11-17 07:00:00,14583\n2014-11-17 07:30:00,17190\n2014-11-17 08:00:00,18725\n2014-11-17 08:30:00,18822\n2014-11-17 09:00:00,17992\n2014-11-17 09:30:00,17210\n2014-11-17 10:00:00,15940\n2014-11-17 10:30:00,17094\n2014-11-17 11:00:00,15247\n2014-11-17 11:30:00,16676\n2014-11-17 12:00:00,16895\n2014-11-17 12:30:00,17205\n2014-11-17 13:00:00,17634\n2014-11-17 13:30:00,18189\n2014-11-17 14:00:00,19319\n2014-11-17 14:30:00,18757\n2014-11-17 15:00:00,17239\n2014-11-17 15:30:00,14885\n2014-11-17 16:00:00,13577\n2014-11-17 16:30:00,13513\n2014-11-17 17:00:00,15864\n2014-11-17 17:30:00,18502\n2014-11-17 18:00:00,20313\n2014-11-17 18:30:00,20674\n2014-11-17 19:00:00,21079\n2014-11-17 19:30:00,21433\n2014-11-17 20:00:00,20590\n2014-11-17 20:30:00,19515\n2014-11-17 21:00:00,20194\n2014-11-17 21:30:00,19251\n2014-11-17 22:00:00,18436\n2014-11-17 22:30:00,16099\n2014-11-17 23:00:00,14985\n2014-11-17 23:30:00,11612\n2014-11-18 00:00:00,9828\n2014-11-18 00:30:00,7529\n2014-11-18 01:00:00,6162\n2014-11-18 01:30:00,4296\n2014-11-18 02:00:00,3090\n2014-11-18 02:30:00,2366\n2014-11-18 03:00:00,2094\n2014-11-18 03:30:00,1831\n2014-11-18 04:00:00,1987\n2014-11-18 04:30:00,1936\n2014-11-18 05:00:00,2346\n2014-11-18 05:30:00,4328\n2014-11-18 06:00:00,6935\n2014-11-18 06:30:00,12642\n2014-11-18 07:00:00,16037\n2014-11-18 07:30:00,20032\n2014-11-18 08:00:00,20709\n2014-11-18 08:30:00,20897\n2014-11-18 09:00:00,20127\n2014-11-18 09:30:00,19075\n2014-11-18 10:00:00,17883\n2014-11-18 10:30:00,17581\n2014-11-18 11:00:00,16559\n2014-11-18 11:30:00,17870\n2014-11-18 12:00:00,18097\n2014-11-18 12:30:00,17714\n2014-11-18 13:00:00,17104\n2014-11-18 13:30:00,17999\n2014-11-18 14:00:00,19071\n2014-11-18 14:30:00,19197\n2014-11-18 15:00:00,19000\n2014-11-18 15:30:00,17013\n2014-11-18 16:00:00,14962\n2014-11-18 16:30:00,13727\n2014-11-18 17:00:00,16826\n2014-11-18 17:30:00,20320\n2014-11-18 18:00:00,23167\n2014-11-18 18:30:00,23782\n2014-11-18 19:00:00,24068\n2014-11-18 19:30:00,24831\n2014-11-18 20:00:00,25564\n2014-11-18 20:30:00,25300\n2014-11-18 21:00:00,25503\n2014-11-18 21:30:00,24598\n2014-11-18 22:00:00,24120\n2014-11-18 22:30:00,22641\n2014-11-18 23:00:00,19722\n2014-11-18 23:30:00,15507\n2014-11-19 00:00:00,12079\n2014-11-19 00:30:00,8561\n2014-11-19 01:00:00,6632\n2014-11-19 01:30:00,4846\n2014-11-19 02:00:00,3996\n2014-11-19 02:30:00,3339\n2014-11-19 03:00:00,2594\n2014-11-19 03:30:00,2315\n2014-11-19 04:00:00,2462\n2014-11-19 04:30:00,2077\n2014-11-19 05:00:00,2448\n2014-11-19 05:30:00,4656\n2014-11-19 06:00:00,7055\n2014-11-19 06:30:00,12903\n2014-11-19 07:00:00,16639\n2014-11-19 07:30:00,20585\n2014-11-19 08:00:00,21833\n2014-11-19 08:30:00,21453\n2014-11-19 09:00:00,20023\n2014-11-19 09:30:00,18790\n2014-11-19 10:00:00,18382\n2014-11-19 10:30:00,17956\n2014-11-19 11:00:00,17477\n2014-11-19 11:30:00,18590\n2014-11-19 12:00:00,18409\n2014-11-19 12:30:00,18020\n2014-11-19 13:00:00,16950\n2014-11-19 13:30:00,17826\n2014-11-19 14:00:00,18105\n2014-11-19 14:30:00,18187\n2014-11-19 15:00:00,18565\n2014-11-19 15:30:00,16454\n2014-11-19 16:00:00,14355\n2014-11-19 16:30:00,13109\n2014-11-19 17:00:00,15924\n2014-11-19 17:30:00,19175\n2014-11-19 18:00:00,21521\n2014-11-19 18:30:00,22762\n2014-11-19 19:00:00,23889\n2014-11-19 19:30:00,24408\n2014-11-19 20:00:00,24501\n2014-11-19 20:30:00,24316\n2014-11-19 21:00:00,24362\n2014-11-19 21:30:00,24032\n2014-11-19 22:00:00,23174\n2014-11-19 22:30:00,22453\n2014-11-19 23:00:00,20964\n2014-11-19 23:30:00,18142\n2014-11-20 00:00:00,14466\n2014-11-20 00:30:00,10771\n2014-11-20 01:00:00,8100\n2014-11-20 01:30:00,5976\n2014-11-20 02:00:00,5000\n2014-11-20 02:30:00,3727\n2014-11-20 03:00:00,2984\n2014-11-20 03:30:00,2584\n2014-11-20 04:00:00,2591\n2014-11-20 04:30:00,2253\n2014-11-20 05:00:00,2489\n2014-11-20 05:30:00,4419\n2014-11-20 06:00:00,7014\n2014-11-20 06:30:00,12470\n2014-11-20 07:00:00,16549\n2014-11-20 07:30:00,19879\n2014-11-20 08:00:00,20437\n2014-11-20 08:30:00,19549\n2014-11-20 09:00:00,18639\n2014-11-20 09:30:00,18683\n2014-11-20 10:00:00,18486\n2014-11-20 10:30:00,18014\n2014-11-20 11:00:00,16720\n2014-11-20 11:30:00,18570\n2014-11-20 12:00:00,18309\n2014-11-20 12:30:00,17294\n2014-11-20 13:00:00,16699\n2014-11-20 13:30:00,17819\n2014-11-20 14:00:00,18227\n2014-11-20 14:30:00,18586\n2014-11-20 15:00:00,18078\n2014-11-20 15:30:00,15656\n2014-11-20 16:00:00,12989\n2014-11-20 16:30:00,11740\n2014-11-20 17:00:00,14934\n2014-11-20 17:30:00,18494\n2014-11-20 18:00:00,21215\n2014-11-20 18:30:00,23643\n2014-11-20 19:00:00,24623\n2014-11-20 19:30:00,24564\n2014-11-20 20:00:00,25305\n2014-11-20 20:30:00,25039\n2014-11-20 21:00:00,25351\n2014-11-20 21:30:00,24526\n2014-11-20 22:00:00,24739\n2014-11-20 22:30:00,23638\n2014-11-20 23:00:00,21861\n2014-11-20 23:30:00,21500\n2014-11-21 00:00:00,19838\n2014-11-21 00:30:00,16307\n2014-11-21 01:00:00,12324\n2014-11-21 01:30:00,10006\n2014-11-21 02:00:00,8077\n2014-11-21 02:30:00,6355\n2014-11-21 03:00:00,5091\n2014-11-21 03:30:00,4247\n2014-11-21 04:00:00,4440\n2014-11-21 04:30:00,3089\n2014-11-21 05:00:00,2930\n2014-11-21 05:30:00,4782\n2014-11-21 06:00:00,7250\n2014-11-21 06:30:00,12167\n2014-11-21 07:00:00,15235\n2014-11-21 07:30:00,20053\n2014-11-21 08:00:00,20654\n2014-11-21 08:30:00,21158\n2014-11-21 09:00:00,19863\n2014-11-21 09:30:00,18775\n2014-11-21 10:00:00,18346\n2014-11-21 10:30:00,18645\n2014-11-21 11:00:00,17986\n2014-11-21 11:30:00,19070\n2014-11-21 12:00:00,18901\n2014-11-21 12:30:00,17585\n2014-11-21 13:00:00,17309\n2014-11-21 13:30:00,18226\n2014-11-21 14:00:00,18788\n2014-11-21 14:30:00,19103\n2014-11-21 15:00:00,18261\n2014-11-21 15:30:00,15945\n2014-11-21 16:00:00,14181\n2014-11-21 16:30:00,12992\n2014-11-21 17:00:00,15847\n2014-11-21 17:30:00,19426\n2014-11-21 18:00:00,22514\n2014-11-21 18:30:00,24457\n2014-11-21 19:00:00,26156\n2014-11-21 19:30:00,26677\n2014-11-21 20:00:00,26217\n2014-11-21 20:30:00,26289\n2014-11-21 21:00:00,26370\n2014-11-21 21:30:00,26344\n2014-11-21 22:00:00,26736\n2014-11-21 22:30:00,27093\n2014-11-21 23:00:00,27569\n2014-11-21 23:30:00,27064\n2014-11-22 00:00:00,26220\n2014-11-22 00:30:00,24289\n2014-11-22 01:00:00,22849\n2014-11-22 01:30:00,20731\n2014-11-22 02:00:00,19081\n2014-11-22 02:30:00,16573\n2014-11-22 03:00:00,14188\n2014-11-22 03:30:00,12213\n2014-11-22 04:00:00,10145\n2014-11-22 04:30:00,5902\n2014-11-22 05:00:00,3983\n2014-11-22 05:30:00,3556\n2014-11-22 06:00:00,3651\n2014-11-22 06:30:00,5153\n2014-11-22 07:00:00,5379\n2014-11-22 07:30:00,7174\n2014-11-22 08:00:00,9070\n2014-11-22 08:30:00,12114\n2014-11-22 09:00:00,13665\n2014-11-22 09:30:00,17463\n2014-11-22 10:00:00,17209\n2014-11-22 10:30:00,20299\n2014-11-22 11:00:00,20255\n2014-11-22 11:30:00,22981\n2014-11-22 12:00:00,23368\n2014-11-22 12:30:00,23444\n2014-11-22 13:00:00,22610\n2014-11-22 13:30:00,22258\n2014-11-22 14:00:00,21160\n2014-11-22 14:30:00,22960\n2014-11-22 15:00:00,23007\n2014-11-22 15:30:00,21145\n2014-11-22 16:00:00,18440\n2014-11-22 16:30:00,16028\n2014-11-22 17:00:00,19101\n2014-11-22 17:30:00,22361\n2014-11-22 18:00:00,24256\n2014-11-22 18:30:00,26410\n2014-11-22 19:00:00,27377\n2014-11-22 19:30:00,26255\n2014-11-22 20:00:00,23977\n2014-11-22 20:30:00,23565\n2014-11-22 21:00:00,22703\n2014-11-22 21:30:00,23078\n2014-11-22 22:00:00,25755\n2014-11-22 22:30:00,27028\n2014-11-22 23:00:00,28126\n2014-11-22 23:30:00,28472\n2014-11-23 00:00:00,27424\n2014-11-23 00:30:00,25493\n2014-11-23 01:00:00,24876\n2014-11-23 01:30:00,22639\n2014-11-23 02:00:00,21013\n2014-11-23 02:30:00,19100\n2014-11-23 03:00:00,16662\n2014-11-23 03:30:00,14489\n2014-11-23 04:00:00,12023\n2014-11-23 04:30:00,7069\n2014-11-23 05:00:00,4453\n2014-11-23 05:30:00,3483\n2014-11-23 06:00:00,3479\n2014-11-23 06:30:00,3968\n2014-11-23 07:00:00,4092\n2014-11-23 07:30:00,5877\n2014-11-23 08:00:00,6845\n2014-11-23 08:30:00,8283\n2014-11-23 09:00:00,10231\n2014-11-23 09:30:00,13189\n2014-11-23 10:00:00,14458\n2014-11-23 10:30:00,17284\n2014-11-23 11:00:00,17800\n2014-11-23 11:30:00,19509\n2014-11-23 12:00:00,20547\n2014-11-23 12:30:00,20211\n2014-11-23 13:00:00,20041\n2014-11-23 13:30:00,19619\n2014-11-23 14:00:00,19947\n2014-11-23 14:30:00,19844\n2014-11-23 15:00:00,19088\n2014-11-23 15:30:00,19237\n2014-11-23 16:00:00,18316\n2014-11-23 16:30:00,16996\n2014-11-23 17:00:00,18134\n2014-11-23 17:30:00,19633\n2014-11-23 18:00:00,20204\n2014-11-23 18:30:00,19810\n2014-11-23 19:00:00,17925\n2014-11-23 19:30:00,16938\n2014-11-23 20:00:00,15096\n2014-11-23 20:30:00,15539\n2014-11-23 21:00:00,14806\n2014-11-23 21:30:00,15035\n2014-11-23 22:00:00,13285\n2014-11-23 22:30:00,12090\n2014-11-23 23:00:00,10552\n2014-11-23 23:30:00,9136\n2014-11-24 00:00:00,8106\n2014-11-24 00:30:00,7020\n2014-11-24 01:00:00,5562\n2014-11-24 01:30:00,3917\n2014-11-24 02:00:00,3592\n2014-11-24 02:30:00,2637\n2014-11-24 03:00:00,2031\n2014-11-24 03:30:00,1900\n2014-11-24 04:00:00,2172\n2014-11-24 04:30:00,2008\n2014-11-24 05:00:00,2546\n2014-11-24 05:30:00,4409\n2014-11-24 06:00:00,7269\n2014-11-24 06:30:00,11863\n2014-11-24 07:00:00,14244\n2014-11-24 07:30:00,17238\n2014-11-24 08:00:00,18382\n2014-11-24 08:30:00,17940\n2014-11-24 09:00:00,17447\n2014-11-24 09:30:00,16773\n2014-11-24 10:00:00,15319\n2014-11-24 10:30:00,15867\n2014-11-24 11:00:00,15751\n2014-11-24 11:30:00,17462\n2014-11-24 12:00:00,16292\n2014-11-24 12:30:00,16317\n2014-11-24 13:00:00,16104\n2014-11-24 13:30:00,16967\n2014-11-24 14:00:00,17035\n2014-11-24 14:30:00,17976\n2014-11-24 15:00:00,18230\n2014-11-24 15:30:00,16521\n2014-11-24 16:00:00,14887\n2014-11-24 16:30:00,13707\n2014-11-24 17:00:00,16596\n2014-11-24 17:30:00,18683\n2014-11-24 18:00:00,20289\n2014-11-24 18:30:00,21377\n2014-11-24 19:00:00,21962\n2014-11-24 19:30:00,21126\n2014-11-24 20:00:00,20531\n2014-11-24 20:30:00,19217\n2014-11-24 21:00:00,19353\n2014-11-24 21:30:00,19109\n2014-11-24 22:00:00,18814\n2014-11-24 22:30:00,17036\n2014-11-24 23:00:00,14147\n2014-11-24 23:30:00,11595\n2014-11-25 00:00:00,10091\n2014-11-25 00:30:00,7575\n2014-11-25 01:00:00,5977\n2014-11-25 01:30:00,4705\n2014-11-25 02:00:00,3796\n2014-11-25 02:30:00,2894\n2014-11-25 03:00:00,2471\n2014-11-25 03:30:00,2115\n2014-11-25 04:00:00,2474\n2014-11-25 04:30:00,2285\n2014-11-25 05:00:00,2538\n2014-11-25 05:30:00,4380\n2014-11-25 06:00:00,6537\n2014-11-25 06:30:00,11238\n2014-11-25 07:00:00,14764\n2014-11-25 07:30:00,18187\n2014-11-25 08:00:00,18885\n2014-11-25 08:30:00,19188\n2014-11-25 09:00:00,18398\n2014-11-25 09:30:00,18057\n2014-11-25 10:00:00,16899\n2014-11-25 10:30:00,17137\n2014-11-25 11:00:00,16203\n2014-11-25 11:30:00,17742\n2014-11-25 12:00:00,17843\n2014-11-25 12:30:00,17866\n2014-11-25 13:00:00,17548\n2014-11-25 13:30:00,18306\n2014-11-25 14:00:00,18577\n2014-11-25 14:30:00,18506\n2014-11-25 15:00:00,18691\n2014-11-25 15:30:00,15729\n2014-11-25 16:00:00,13396\n2014-11-25 16:30:00,11923\n2014-11-25 17:00:00,14463\n2014-11-25 17:30:00,17026\n2014-11-25 18:00:00,19078\n2014-11-25 18:30:00,20439\n2014-11-25 19:00:00,20776\n2014-11-25 19:30:00,20941\n2014-11-25 20:00:00,20209\n2014-11-25 20:30:00,19987\n2014-11-25 21:00:00,19952\n2014-11-25 21:30:00,19234\n2014-11-25 22:00:00,18455\n2014-11-25 22:30:00,18097\n2014-11-25 23:00:00,17461\n2014-11-25 23:30:00,16002\n2014-11-26 00:00:00,13400\n2014-11-26 00:30:00,10978\n2014-11-26 01:00:00,8613\n2014-11-26 01:30:00,6446\n2014-11-26 02:00:00,5205\n2014-11-26 02:30:00,4118\n2014-11-26 03:00:00,3510\n2014-11-26 03:30:00,3249\n2014-11-26 04:00:00,3698\n2014-11-26 04:30:00,3584\n2014-11-26 05:00:00,3622\n2014-11-26 05:30:00,4987\n2014-11-26 06:00:00,7213\n2014-11-26 06:30:00,10827\n2014-11-26 07:00:00,14141\n2014-11-26 07:30:00,16965\n2014-11-26 08:00:00,19391\n2014-11-26 08:30:00,19557\n2014-11-26 09:00:00,19067\n2014-11-26 09:30:00,18807\n2014-11-26 10:00:00,18232\n2014-11-26 10:30:00,18999\n2014-11-26 11:00:00,18896\n2014-11-26 11:30:00,19764\n2014-11-26 12:00:00,20227\n2014-11-26 12:30:00,19602\n2014-11-26 13:00:00,20456\n2014-11-26 13:30:00,19580\n2014-11-26 14:00:00,19156\n2014-11-26 14:30:00,19572\n2014-11-26 15:00:00,18925\n2014-11-26 15:30:00,17545\n2014-11-26 16:00:00,15465\n2014-11-26 16:30:00,14104\n2014-11-26 17:00:00,16996\n2014-11-26 17:30:00,20113\n2014-11-26 18:00:00,21015\n2014-11-26 18:30:00,21580\n2014-11-26 19:00:00,22501\n2014-11-26 19:30:00,21159\n2014-11-26 20:00:00,18991\n2014-11-26 20:30:00,18046\n2014-11-26 21:00:00,18300\n2014-11-26 21:30:00,18538\n2014-11-26 22:00:00,17170\n2014-11-26 22:30:00,17081\n2014-11-26 23:00:00,15613\n2014-11-26 23:30:00,13718\n2014-11-27 00:00:00,13522\n2014-11-27 00:30:00,11323\n2014-11-27 01:00:00,10315\n2014-11-27 01:30:00,8870\n2014-11-27 02:00:00,8150\n2014-11-27 02:30:00,7209\n2014-11-27 03:00:00,6018\n2014-11-27 03:30:00,5819\n2014-11-27 04:00:00,5291\n2014-11-27 04:30:00,4127\n2014-11-27 05:00:00,3540\n2014-11-27 05:30:00,3715\n2014-11-27 06:00:00,4613\n2014-11-27 06:30:00,5500\n2014-11-27 07:00:00,5955\n2014-11-27 07:30:00,6512\n2014-11-27 08:00:00,7076\n2014-11-27 08:30:00,7813\n2014-11-27 09:00:00,8365\n2014-11-27 09:30:00,9013\n2014-11-27 10:00:00,9695\n2014-11-27 10:30:00,11389\n2014-11-27 11:00:00,12701\n2014-11-27 11:30:00,13400\n2014-11-27 12:00:00,13282\n2014-11-27 12:30:00,13542\n2014-11-27 13:00:00,13538\n2014-11-27 13:30:00,13663\n2014-11-27 14:00:00,13980\n2014-11-27 14:30:00,14673\n2014-11-27 15:00:00,14614\n2014-11-27 15:30:00,15255\n2014-11-27 16:00:00,13560\n2014-11-27 16:30:00,13120\n2014-11-27 17:00:00,13273\n2014-11-27 17:30:00,13334\n2014-11-27 18:00:00,12930\n2014-11-27 18:30:00,13683\n2014-11-27 19:00:00,13682\n2014-11-27 19:30:00,14106\n2014-11-27 20:00:00,14088\n2014-11-27 20:30:00,14417\n2014-11-27 21:00:00,15187\n2014-11-27 21:30:00,15280\n2014-11-27 22:00:00,15654\n2014-11-27 22:30:00,13989\n2014-11-27 23:00:00,12592\n2014-11-27 23:30:00,11811\n2014-11-28 00:00:00,9653\n2014-11-28 00:30:00,7791\n2014-11-28 01:00:00,6862\n2014-11-28 01:30:00,5644\n2014-11-28 02:00:00,4639\n2014-11-28 02:30:00,3673\n2014-11-28 03:00:00,2945\n2014-11-28 03:30:00,2875\n2014-11-28 04:00:00,2883\n2014-11-28 04:30:00,2165\n2014-11-28 05:00:00,1902\n2014-11-28 05:30:00,2226\n2014-11-28 06:00:00,2870\n2014-11-28 06:30:00,4313\n2014-11-28 07:00:00,4936\n2014-11-28 07:30:00,6240\n2014-11-28 08:00:00,7376\n2014-11-28 08:30:00,8850\n2014-11-28 09:00:00,9864\n2014-11-28 09:30:00,10863\n2014-11-28 10:00:00,11900\n2014-11-28 10:30:00,12969\n2014-11-28 11:00:00,14045\n2014-11-28 11:30:00,15281\n2014-11-28 12:00:00,16153\n2014-11-28 12:30:00,17025\n2014-11-28 13:00:00,17596\n2014-11-28 13:30:00,18437\n2014-11-28 14:00:00,17777\n2014-11-28 14:30:00,18774\n2014-11-28 15:00:00,18868\n2014-11-28 15:30:00,19046\n2014-11-28 16:00:00,17706\n2014-11-28 16:30:00,16591\n2014-11-28 17:00:00,18951\n2014-11-28 17:30:00,20519\n2014-11-28 18:00:00,20626\n2014-11-28 18:30:00,21227\n2014-11-28 19:00:00,22716\n2014-11-28 19:30:00,21044\n2014-11-28 20:00:00,18862\n2014-11-28 20:30:00,18821\n2014-11-28 21:00:00,18485\n2014-11-28 21:30:00,18416\n2014-11-28 22:00:00,19806\n2014-11-28 22:30:00,19671\n2014-11-28 23:00:00,19234\n2014-11-28 23:30:00,17725\n2014-11-29 00:00:00,16089\n2014-11-29 00:30:00,14561\n2014-11-29 01:00:00,13292\n2014-11-29 01:30:00,12000\n2014-11-29 02:00:00,10967\n2014-11-29 02:30:00,9747\n2014-11-29 03:00:00,8556\n2014-11-29 03:30:00,8342\n2014-11-29 04:00:00,7178\n2014-11-29 04:30:00,4441\n2014-11-29 05:00:00,2747\n2014-11-29 05:30:00,2489\n2014-11-29 06:00:00,2283\n2014-11-29 06:30:00,3109\n2014-11-29 07:00:00,3380\n2014-11-29 07:30:00,4628\n2014-11-29 08:00:00,5291\n2014-11-29 08:30:00,7405\n2014-11-29 09:00:00,9044\n2014-11-29 09:30:00,11193\n2014-11-29 10:00:00,12541\n2014-11-29 10:30:00,15281\n2014-11-29 11:00:00,15551\n2014-11-29 11:30:00,17665\n2014-11-29 12:00:00,18499\n2014-11-29 12:30:00,18680\n2014-11-29 13:00:00,19621\n2014-11-29 13:30:00,19830\n2014-11-29 14:00:00,19187\n2014-11-29 14:30:00,19999\n2014-11-29 15:00:00,19722\n2014-11-29 15:30:00,20600\n2014-11-29 16:00:00,19125\n2014-11-29 16:30:00,16658\n2014-11-29 17:00:00,18684\n2014-11-29 17:30:00,20891\n2014-11-29 18:00:00,21554\n2014-11-29 18:30:00,22678\n2014-11-29 19:00:00,24055\n2014-11-29 19:30:00,23418\n2014-11-29 20:00:00,20196\n2014-11-29 20:30:00,19676\n2014-11-29 21:00:00,19566\n2014-11-29 21:30:00,19272\n2014-11-29 22:00:00,20686\n2014-11-29 22:30:00,21659\n2014-11-29 23:00:00,21154\n2014-11-29 23:30:00,21170\n2014-11-30 00:00:00,20149\n2014-11-30 00:30:00,18555\n2014-11-30 01:00:00,17768\n2014-11-30 01:30:00,15608\n2014-11-30 02:00:00,14966\n2014-11-30 02:30:00,13074\n2014-11-30 03:00:00,11332\n2014-11-30 03:30:00,9965\n2014-11-30 04:00:00,9167\n2014-11-30 04:30:00,5520\n2014-11-30 05:00:00,3812\n2014-11-30 05:30:00,3123\n2014-11-30 06:00:00,3103\n2014-11-30 06:30:00,3777\n2014-11-30 07:00:00,3699\n2014-11-30 07:30:00,4968\n2014-11-30 08:00:00,5630\n2014-11-30 08:30:00,7422\n2014-11-30 09:00:00,9123\n2014-11-30 09:30:00,10981\n2014-11-30 10:00:00,12227\n2014-11-30 10:30:00,15247\n2014-11-30 11:00:00,14970\n2014-11-30 11:30:00,16912\n2014-11-30 12:00:00,17420\n2014-11-30 12:30:00,18336\n2014-11-30 13:00:00,18091\n2014-11-30 13:30:00,17841\n2014-11-30 14:00:00,18946\n2014-11-30 14:30:00,19156\n2014-11-30 15:00:00,18159\n2014-11-30 15:30:00,17805\n2014-11-30 16:00:00,16838\n2014-11-30 16:30:00,15906\n2014-11-30 17:00:00,16917\n2014-11-30 17:30:00,17670\n2014-11-30 18:00:00,17941\n2014-11-30 18:30:00,18093\n2014-11-30 19:00:00,17587\n2014-11-30 19:30:00,16867\n2014-11-30 20:00:00,15693\n2014-11-30 20:30:00,15342\n2014-11-30 21:00:00,13821\n2014-11-30 21:30:00,14083\n2014-11-30 22:00:00,13714\n2014-11-30 22:30:00,12119\n2014-11-30 23:00:00,9904\n2014-11-30 23:30:00,8970\n2014-12-01 00:00:00,7706\n2014-12-01 00:30:00,5494\n2014-12-01 01:00:00,4249\n2014-12-01 01:30:00,2891\n2014-12-01 02:00:00,2632\n2014-12-01 02:30:00,2192\n2014-12-01 03:00:00,1648\n2014-12-01 03:30:00,1639\n2014-12-01 04:00:00,1913\n2014-12-01 04:30:00,2142\n2014-12-01 05:00:00,2909\n2014-12-01 05:30:00,4587\n2014-12-01 06:00:00,7235\n2014-12-01 06:30:00,11448\n2014-12-01 07:00:00,14106\n2014-12-01 07:30:00,17184\n2014-12-01 08:00:00,18306\n2014-12-01 08:30:00,18746\n2014-12-01 09:00:00,17914\n2014-12-01 09:30:00,16699\n2014-12-01 10:00:00,15681\n2014-12-01 10:30:00,15210\n2014-12-01 11:00:00,14532\n2014-12-01 11:30:00,15985\n2014-12-01 12:00:00,16226\n2014-12-01 12:30:00,16000\n2014-12-01 13:00:00,15641\n2014-12-01 13:30:00,16373\n2014-12-01 14:00:00,16830\n2014-12-01 14:30:00,17470\n2014-12-01 15:00:00,18131\n2014-12-01 15:30:00,16870\n2014-12-01 16:00:00,15192\n2014-12-01 16:30:00,14453\n2014-12-01 17:00:00,17382\n2014-12-01 17:30:00,19815\n2014-12-01 18:00:00,21750\n2014-12-01 18:30:00,22217\n2014-12-01 19:00:00,21813\n2014-12-01 19:30:00,21536\n2014-12-01 20:00:00,22541\n2014-12-01 20:30:00,21329\n2014-12-01 21:00:00,20165\n2014-12-01 21:30:00,19498\n2014-12-01 22:00:00,19355\n2014-12-01 22:30:00,16691\n2014-12-01 23:00:00,14387\n2014-12-01 23:30:00,12101\n2014-12-02 00:00:00,9805\n2014-12-02 00:30:00,7121\n2014-12-02 01:00:00,5019\n2014-12-02 01:30:00,3822\n2014-12-02 02:00:00,3268\n2014-12-02 02:30:00,2261\n2014-12-02 03:00:00,1853\n2014-12-02 03:30:00,1722\n2014-12-02 04:00:00,2077\n2014-12-02 04:30:00,1988\n2014-12-02 05:00:00,2296\n2014-12-02 05:30:00,4537\n2014-12-02 06:00:00,6661\n2014-12-02 06:30:00,11901\n2014-12-02 07:00:00,15501\n2014-12-02 07:30:00,19573\n2014-12-02 08:00:00,20896\n2014-12-02 08:30:00,21051\n2014-12-02 09:00:00,19670\n2014-12-02 09:30:00,18654\n2014-12-02 10:00:00,17108\n2014-12-02 10:30:00,17553\n2014-12-02 11:00:00,16232\n2014-12-02 11:30:00,17534\n2014-12-02 12:00:00,17697\n2014-12-02 12:30:00,19165\n2014-12-02 13:00:00,18916\n2014-12-02 13:30:00,19543\n2014-12-02 14:00:00,18570\n2014-12-02 14:30:00,19043\n2014-12-02 15:00:00,18343\n2014-12-02 15:30:00,16666\n2014-12-02 16:00:00,14050\n2014-12-02 16:30:00,12845\n2014-12-02 17:00:00,16111\n2014-12-02 17:30:00,19112\n2014-12-02 18:00:00,21205\n2014-12-02 18:30:00,22337\n2014-12-02 19:00:00,23340\n2014-12-02 19:30:00,23082\n2014-12-02 20:00:00,23718\n2014-12-02 20:30:00,22936\n2014-12-02 21:00:00,23466\n2014-12-02 21:30:00,23387\n2014-12-02 22:00:00,22893\n2014-12-02 22:30:00,20923\n2014-12-02 23:00:00,18684\n2014-12-02 23:30:00,14962\n2014-12-03 00:00:00,12558\n2014-12-03 00:30:00,8876\n2014-12-03 01:00:00,6626\n2014-12-03 01:30:00,4926\n2014-12-03 02:00:00,4046\n2014-12-03 02:30:00,3168\n2014-12-03 03:00:00,2692\n2014-12-03 03:30:00,2237\n2014-12-03 04:00:00,2384\n2014-12-03 04:30:00,2109\n2014-12-03 05:00:00,2403\n2014-12-03 05:30:00,4250\n2014-12-03 06:00:00,6529\n2014-12-03 06:30:00,12185\n2014-12-03 07:00:00,16016\n2014-12-03 07:30:00,19504\n2014-12-03 08:00:00,20925\n2014-12-03 08:30:00,20891\n2014-12-03 09:00:00,20047\n2014-12-03 09:30:00,19138\n2014-12-03 10:00:00,18431\n2014-12-03 10:30:00,16960\n2014-12-03 11:00:00,16426\n2014-12-03 11:30:00,18092\n2014-12-03 12:00:00,19190\n2014-12-03 12:30:00,18957\n2014-12-03 13:00:00,18288\n2014-12-03 13:30:00,18843\n2014-12-03 14:00:00,19003\n2014-12-03 14:30:00,18193\n2014-12-03 15:00:00,17260\n2014-12-03 15:30:00,15103\n2014-12-03 16:00:00,12941\n2014-12-03 16:30:00,11797\n2014-12-03 17:00:00,15545\n2014-12-03 17:30:00,17938\n2014-12-03 18:00:00,20693\n2014-12-03 18:30:00,21585\n2014-12-03 19:00:00,21689\n2014-12-03 19:30:00,21995\n2014-12-03 20:00:00,22096\n2014-12-03 20:30:00,22115\n2014-12-03 21:00:00,21860\n2014-12-03 21:30:00,22041\n2014-12-03 22:00:00,21680\n2014-12-03 22:30:00,21378\n2014-12-03 23:00:00,20295\n2014-12-03 23:30:00,18176\n2014-12-04 00:00:00,14846\n2014-12-04 00:30:00,11480\n2014-12-04 01:00:00,8939\n2014-12-04 01:30:00,6679\n2014-12-04 02:00:00,5175\n2014-12-04 02:30:00,3800\n2014-12-04 03:00:00,3135\n2014-12-04 03:30:00,2671\n2014-12-04 04:00:00,2843\n2014-12-04 04:30:00,2476\n2014-12-04 05:00:00,2670\n2014-12-04 05:30:00,4521\n2014-12-04 06:00:00,6841\n2014-12-04 06:30:00,12178\n2014-12-04 07:00:00,15916\n2014-12-04 07:30:00,19872\n2014-12-04 08:00:00,20957\n2014-12-04 08:30:00,20358\n2014-12-04 09:00:00,19717\n2014-12-04 09:30:00,18943\n2014-12-04 10:00:00,18082\n2014-12-04 10:30:00,18560\n2014-12-04 11:00:00,17316\n2014-12-04 11:30:00,18817\n2014-12-04 12:00:00,18439\n2014-12-04 12:30:00,17771\n2014-12-04 13:00:00,17214\n2014-12-04 13:30:00,17836\n2014-12-04 14:00:00,18676\n2014-12-04 14:30:00,19241\n2014-12-04 15:00:00,19068\n2014-12-04 15:30:00,16567\n2014-12-04 16:00:00,14529\n2014-12-04 16:30:00,12862\n2014-12-04 17:00:00,16086\n2014-12-04 17:30:00,19221\n2014-12-04 18:00:00,21408\n2014-12-04 18:30:00,23385\n2014-12-04 19:00:00,23604\n2014-12-04 19:30:00,23384\n2014-12-04 20:00:00,23209\n2014-12-04 20:30:00,22592\n2014-12-04 21:00:00,23164\n2014-12-04 21:30:00,23638\n2014-12-04 22:00:00,23192\n2014-12-04 22:30:00,22417\n2014-12-04 23:00:00,22630\n2014-12-04 23:30:00,21278\n2014-12-05 00:00:00,19300\n2014-12-05 00:30:00,16241\n2014-12-05 01:00:00,12966\n2014-12-05 01:30:00,10322\n2014-12-05 02:00:00,8160\n2014-12-05 02:30:00,6611\n2014-12-05 03:00:00,5410\n2014-12-05 03:30:00,4453\n2014-12-05 04:00:00,4287\n2014-12-05 04:30:00,3250\n2014-12-05 05:00:00,3396\n2014-12-05 05:30:00,4846\n2014-12-05 06:00:00,7090\n2014-12-05 06:30:00,11832\n2014-12-05 07:00:00,15506\n2014-12-05 07:30:00,20211\n2014-12-05 08:00:00,21053\n2014-12-05 08:30:00,20635\n2014-12-05 09:00:00,20128\n2014-12-05 09:30:00,18838\n2014-12-05 10:00:00,17936\n2014-12-05 10:30:00,18210\n2014-12-05 11:00:00,17653\n2014-12-05 11:30:00,18847\n2014-12-05 12:00:00,18814\n2014-12-05 12:30:00,17478\n2014-12-05 13:00:00,18029\n2014-12-05 13:30:00,18953\n2014-12-05 14:00:00,19684\n2014-12-05 14:30:00,19747\n2014-12-05 15:00:00,18464\n2014-12-05 15:30:00,16396\n2014-12-05 16:00:00,14436\n2014-12-05 16:30:00,13461\n2014-12-05 17:00:00,17047\n2014-12-05 17:30:00,20614\n2014-12-05 18:00:00,23322\n2014-12-05 18:30:00,25791\n2014-12-05 19:00:00,26650\n2014-12-05 19:30:00,26971\n2014-12-05 20:00:00,26688\n2014-12-05 20:30:00,25508\n2014-12-05 21:00:00,26284\n2014-12-05 21:30:00,26978\n2014-12-05 22:00:00,26983\n2014-12-05 22:30:00,25438\n2014-12-05 23:00:00,24914\n2014-12-05 23:30:00,24165\n2014-12-06 00:00:00,22925\n2014-12-06 00:30:00,22187\n2014-12-06 01:00:00,21493\n2014-12-06 01:30:00,19021\n2014-12-06 02:00:00,18009\n2014-12-06 02:30:00,15786\n2014-12-06 03:00:00,13114\n2014-12-06 03:30:00,10541\n2014-12-06 04:00:00,9296\n2014-12-06 04:30:00,5388\n2014-12-06 05:00:00,3578\n2014-12-06 05:30:00,3205\n2014-12-06 06:00:00,3427\n2014-12-06 06:30:00,4666\n2014-12-06 07:00:00,5262\n2014-12-06 07:30:00,7841\n2014-12-06 08:00:00,8786\n2014-12-06 08:30:00,11893\n2014-12-06 09:00:00,12849\n2014-12-06 09:30:00,16411\n2014-12-06 10:00:00,16917\n2014-12-06 10:30:00,19706\n2014-12-06 11:00:00,22924\n2014-12-06 11:30:00,26224\n2014-12-06 12:00:00,25548\n2014-12-06 12:30:00,24376\n2014-12-06 13:00:00,24464\n2014-12-06 13:30:00,23825\n2014-12-06 14:00:00,24235\n2014-12-06 14:30:00,24001\n2014-12-06 15:00:00,23877\n2014-12-06 15:30:00,21761\n2014-12-06 16:00:00,18277\n2014-12-06 16:30:00,15670\n2014-12-06 17:00:00,18411\n2014-12-06 17:30:00,21332\n2014-12-06 18:00:00,23306\n2014-12-06 18:30:00,24856\n2014-12-06 19:00:00,25798\n2014-12-06 19:30:00,25274\n2014-12-06 20:00:00,25158\n2014-12-06 20:30:00,24164\n2014-12-06 21:00:00,23771\n2014-12-06 21:30:00,24363\n2014-12-06 22:00:00,25705\n2014-12-06 22:30:00,26429\n2014-12-06 23:00:00,27272\n2014-12-06 23:30:00,27636\n2014-12-07 00:00:00,26695\n2014-12-07 00:30:00,25626\n2014-12-07 01:00:00,24285\n2014-12-07 01:30:00,22249\n2014-12-07 02:00:00,20741\n2014-12-07 02:30:00,18554\n2014-12-07 03:00:00,15770\n2014-12-07 03:30:00,13976\n2014-12-07 04:00:00,11368\n2014-12-07 04:30:00,6531\n2014-12-07 05:00:00,3929\n2014-12-07 05:30:00,3236\n2014-12-07 06:00:00,3177\n2014-12-07 06:30:00,3757\n2014-12-07 07:00:00,4042\n2014-12-07 07:30:00,5401\n2014-12-07 08:00:00,6483\n2014-12-07 08:30:00,9264\n2014-12-07 09:00:00,11497\n2014-12-07 09:30:00,14585\n2014-12-07 10:00:00,16159\n2014-12-07 10:30:00,20205\n2014-12-07 11:00:00,21146\n2014-12-07 11:30:00,22387\n2014-12-07 12:00:00,23081\n2014-12-07 12:30:00,23163\n2014-12-07 13:00:00,22660\n2014-12-07 13:30:00,22127\n2014-12-07 14:00:00,22237\n2014-12-07 14:30:00,22193\n2014-12-07 15:00:00,21252\n2014-12-07 15:30:00,20818\n2014-12-07 16:00:00,19110\n2014-12-07 16:30:00,17255\n2014-12-07 17:00:00,18368\n2014-12-07 17:30:00,20327\n2014-12-07 18:00:00,21411\n2014-12-07 18:30:00,21379\n2014-12-07 19:00:00,21735\n2014-12-07 19:30:00,20031\n2014-12-07 20:00:00,18305\n2014-12-07 20:30:00,17961\n2014-12-07 21:00:00,17334\n2014-12-07 21:30:00,17401\n2014-12-07 22:00:00,17020\n2014-12-07 22:30:00,14661\n2014-12-07 23:00:00,12367\n2014-12-07 23:30:00,10891\n2014-12-08 00:00:00,8141\n2014-12-08 00:30:00,6411\n2014-12-08 01:00:00,4762\n2014-12-08 01:30:00,3616\n2014-12-08 02:00:00,3130\n2014-12-08 02:30:00,2273\n2014-12-08 03:00:00,2031\n2014-12-08 03:30:00,1788\n2014-12-08 04:00:00,2203\n2014-12-08 04:30:00,2270\n2014-12-08 05:00:00,2727\n2014-12-08 05:30:00,4686\n2014-12-08 06:00:00,6827\n2014-12-08 06:30:00,11984\n2014-12-08 07:00:00,14644\n2014-12-08 07:30:00,18338\n2014-12-08 08:00:00,19590\n2014-12-08 08:30:00,19762\n2014-12-08 09:00:00,19372\n2014-12-08 09:30:00,18754\n2014-12-08 10:00:00,17736\n2014-12-08 10:30:00,17624\n2014-12-08 11:00:00,16856\n2014-12-08 11:30:00,18005\n2014-12-08 12:00:00,18028\n2014-12-08 12:30:00,17733\n2014-12-08 13:00:00,17678\n2014-12-08 13:30:00,18275\n2014-12-08 14:00:00,18070\n2014-12-08 14:30:00,19038\n2014-12-08 15:00:00,18998\n2014-12-08 15:30:00,16932\n2014-12-08 16:00:00,15201\n2014-12-08 16:30:00,14426\n2014-12-08 17:00:00,16942\n2014-12-08 17:30:00,19768\n2014-12-08 18:00:00,21911\n2014-12-08 18:30:00,22917\n2014-12-08 19:00:00,23371\n2014-12-08 19:30:00,23343\n2014-12-08 20:00:00,22358\n2014-12-08 20:30:00,22302\n2014-12-08 21:00:00,22712\n2014-12-08 21:30:00,22329\n2014-12-08 22:00:00,21979\n2014-12-08 22:30:00,19387\n2014-12-08 23:00:00,17494\n2014-12-08 23:30:00,13745\n2014-12-09 00:00:00,11339\n2014-12-09 00:30:00,8699\n2014-12-09 01:00:00,6796\n2014-12-09 01:30:00,5236\n2014-12-09 02:00:00,3800\n2014-12-09 02:30:00,3042\n2014-12-09 03:00:00,2532\n2014-12-09 03:30:00,2258\n2014-12-09 04:00:00,2212\n2014-12-09 04:30:00,2135\n2014-12-09 05:00:00,2592\n2014-12-09 05:30:00,4617\n2014-12-09 06:00:00,8006\n2014-12-09 06:30:00,13619\n2014-12-09 07:00:00,16700\n2014-12-09 07:30:00,19651\n2014-12-09 08:00:00,20630\n2014-12-09 08:30:00,21217\n2014-12-09 09:00:00,19857\n2014-12-09 09:30:00,18753\n2014-12-09 10:00:00,17813\n2014-12-09 10:30:00,17833\n2014-12-09 11:00:00,17164\n2014-12-09 11:30:00,18181\n2014-12-09 12:00:00,17482\n2014-12-09 12:30:00,15676\n2014-12-09 13:00:00,16018\n2014-12-09 13:30:00,17066\n2014-12-09 14:00:00,17654\n2014-12-09 14:30:00,17696\n2014-12-09 15:00:00,16781\n2014-12-09 15:30:00,14189\n2014-12-09 16:00:00,12461\n2014-12-09 16:30:00,12252\n2014-12-09 17:00:00,15431\n2014-12-09 17:30:00,18137\n2014-12-09 18:00:00,20649\n2014-12-09 18:30:00,21989\n2014-12-09 19:00:00,22350\n2014-12-09 19:30:00,22177\n2014-12-09 20:00:00,22991\n2014-12-09 20:30:00,22128\n2014-12-09 21:00:00,23207\n2014-12-09 21:30:00,23091\n2014-12-09 22:00:00,22616\n2014-12-09 22:30:00,21118\n2014-12-09 23:00:00,19301\n2014-12-09 23:30:00,16789\n2014-12-10 00:00:00,14252\n2014-12-10 00:30:00,10138\n2014-12-10 01:00:00,7847\n2014-12-10 01:30:00,5782\n2014-12-10 02:00:00,4951\n2014-12-10 02:30:00,3696\n2014-12-10 03:00:00,2833\n2014-12-10 03:30:00,2375\n2014-12-10 04:00:00,2533\n2014-12-10 04:30:00,2423\n2014-12-10 05:00:00,2512\n2014-12-10 05:30:00,4337\n2014-12-10 06:00:00,6721\n2014-12-10 06:30:00,11812\n2014-12-10 07:00:00,16054\n2014-12-10 07:30:00,19337\n2014-12-10 08:00:00,21348\n2014-12-10 08:30:00,21167\n2014-12-10 09:00:00,20051\n2014-12-10 09:30:00,18809\n2014-12-10 10:00:00,17812\n2014-12-10 10:30:00,17889\n2014-12-10 11:00:00,17482\n2014-12-10 11:30:00,18775\n2014-12-10 12:00:00,18351\n2014-12-10 12:30:00,17604\n2014-12-10 13:00:00,17729\n2014-12-10 13:30:00,17499\n2014-12-10 14:00:00,17558\n2014-12-10 14:30:00,18070\n2014-12-10 15:00:00,17422\n2014-12-10 15:30:00,14666\n2014-12-10 16:00:00,12252\n2014-12-10 16:30:00,11174\n2014-12-10 17:00:00,13853\n2014-12-10 17:30:00,16962\n2014-12-10 18:00:00,19708\n2014-12-10 18:30:00,20764\n2014-12-10 19:00:00,21802\n2014-12-10 19:30:00,22239\n2014-12-10 20:00:00,22169\n2014-12-10 20:30:00,23923\n2014-12-10 21:00:00,24403\n2014-12-10 21:30:00,24211\n2014-12-10 22:00:00,23439\n2014-12-10 22:30:00,23394\n2014-12-10 23:00:00,21701\n2014-12-10 23:30:00,19727\n2014-12-11 00:00:00,17270\n2014-12-11 00:30:00,13379\n2014-12-11 01:00:00,10314\n2014-12-11 01:30:00,7470\n2014-12-11 02:00:00,6039\n2014-12-11 02:30:00,4322\n2014-12-11 03:00:00,3461\n2014-12-11 03:30:00,2872\n2014-12-11 04:00:00,2854\n2014-12-11 04:30:00,2422\n2014-12-11 05:00:00,2578\n2014-12-11 05:30:00,4513\n2014-12-11 06:00:00,6672\n2014-12-11 06:30:00,12358\n2014-12-11 07:00:00,15790\n2014-12-11 07:30:00,19441\n2014-12-11 08:00:00,20920\n2014-12-11 08:30:00,20665\n2014-12-11 09:00:00,19708\n2014-12-11 09:30:00,20066\n2014-12-11 10:00:00,18424\n2014-12-11 10:30:00,18403\n2014-12-11 11:00:00,17621\n2014-12-11 11:30:00,18994\n2014-12-11 12:00:00,18845\n2014-12-11 12:30:00,17937\n2014-12-11 13:00:00,17974\n2014-12-11 13:30:00,18671\n2014-12-11 14:00:00,19082\n2014-12-11 14:30:00,20224\n2014-12-11 15:00:00,18966\n2014-12-11 15:30:00,16165\n2014-12-11 16:00:00,14013\n2014-12-11 16:30:00,12246\n2014-12-11 17:00:00,15021\n2014-12-11 17:30:00,18834\n2014-12-11 18:00:00,21115\n2014-12-11 18:30:00,22746\n2014-12-11 19:00:00,23679\n2014-12-11 19:30:00,23992\n2014-12-11 20:00:00,23597\n2014-12-11 20:30:00,23581\n2014-12-11 21:00:00,24093\n2014-12-11 21:30:00,24130\n2014-12-11 22:00:00,24027\n2014-12-11 22:30:00,23575\n2014-12-11 23:00:00,22502\n2014-12-11 23:30:00,22049\n2014-12-12 00:00:00,20667\n2014-12-12 00:30:00,19265\n2014-12-12 01:00:00,16192\n2014-12-12 01:30:00,12814\n2014-12-12 02:00:00,10410\n2014-12-12 02:30:00,8218\n2014-12-12 03:00:00,6335\n2014-12-12 03:30:00,5377\n2014-12-12 04:00:00,4659\n2014-12-12 04:30:00,3597\n2014-12-12 05:00:00,3208\n2014-12-12 05:30:00,4698\n2014-12-12 06:00:00,6900\n2014-12-12 06:30:00,12308\n2014-12-12 07:00:00,15444\n2014-12-12 07:30:00,19511\n2014-12-12 08:00:00,20489\n2014-12-12 08:30:00,20834\n2014-12-12 09:00:00,19854\n2014-12-12 09:30:00,18687\n2014-12-12 10:00:00,18014\n2014-12-12 10:30:00,18564\n2014-12-12 11:00:00,18237\n2014-12-12 11:30:00,18916\n2014-12-12 12:00:00,18244\n2014-12-12 12:30:00,16850\n2014-12-12 13:00:00,17845\n2014-12-12 13:30:00,18162\n2014-12-12 14:00:00,19043\n2014-12-12 14:30:00,19128\n2014-12-12 15:00:00,18287\n2014-12-12 15:30:00,15667\n2014-12-12 16:00:00,13938\n2014-12-12 16:30:00,12626\n2014-12-12 17:00:00,15807\n2014-12-12 17:30:00,19375\n2014-12-12 18:00:00,21905\n2014-12-12 18:30:00,24008\n2014-12-12 19:00:00,25410\n2014-12-12 19:30:00,25568\n2014-12-12 20:00:00,24888\n2014-12-12 20:30:00,25190\n2014-12-12 21:00:00,25350\n2014-12-12 21:30:00,25927\n2014-12-12 22:00:00,26737\n2014-12-12 22:30:00,26771\n2014-12-12 23:00:00,26180\n2014-12-12 23:30:00,25739\n2014-12-13 00:00:00,24743\n2014-12-13 00:30:00,24285\n2014-12-13 01:00:00,22826\n2014-12-13 01:30:00,21266\n2014-12-13 02:00:00,19907\n2014-12-13 02:30:00,17053\n2014-12-13 03:00:00,14423\n2014-12-13 03:30:00,12363\n2014-12-13 04:00:00,10600\n2014-12-13 04:30:00,6501\n2014-12-13 05:00:00,4211\n2014-12-13 05:30:00,3425\n2014-12-13 06:00:00,3475\n2014-12-13 06:30:00,5132\n2014-12-13 07:00:00,4986\n2014-12-13 07:30:00,7716\n2014-12-13 08:00:00,8873\n2014-12-13 08:30:00,12361\n2014-12-13 09:00:00,13217\n2014-12-13 09:30:00,17706\n2014-12-13 10:00:00,19199\n2014-12-13 10:30:00,21605\n2014-12-13 11:00:00,22106\n2014-12-13 11:30:00,23452\n2014-12-13 12:00:00,24095\n2014-12-13 12:30:00,24114\n2014-12-13 13:00:00,24368\n2014-12-13 13:30:00,23648\n2014-12-13 14:00:00,22929\n2014-12-13 14:30:00,22531\n2014-12-13 15:00:00,21489\n2014-12-13 15:30:00,19081\n2014-12-13 16:00:00,15734\n2014-12-13 16:30:00,13140\n2014-12-13 17:00:00,15041\n2014-12-13 17:30:00,17961\n2014-12-13 18:00:00,20757\n2014-12-13 18:30:00,22233\n2014-12-13 19:00:00,23550\n2014-12-13 19:30:00,24311\n2014-12-13 20:00:00,24320\n2014-12-13 20:30:00,23465\n2014-12-13 21:00:00,24125\n2014-12-13 21:30:00,24696\n2014-12-13 22:00:00,24848\n2014-12-13 22:30:00,25952\n2014-12-13 23:00:00,26481\n2014-12-13 23:30:00,26376\n2014-12-14 00:00:00,26065\n2014-12-14 00:30:00,25745\n2014-12-14 01:00:00,24053\n2014-12-14 01:30:00,22288\n2014-12-14 02:00:00,21263\n2014-12-14 02:30:00,18637\n2014-12-14 03:00:00,16106\n2014-12-14 03:30:00,13609\n2014-12-14 04:00:00,11786\n2014-12-14 04:30:00,6978\n2014-12-14 05:00:00,4468\n2014-12-14 05:30:00,3728\n2014-12-14 06:00:00,3611\n2014-12-14 06:30:00,3909\n2014-12-14 07:00:00,4139\n2014-12-14 07:30:00,5583\n2014-12-14 08:00:00,6831\n2014-12-14 08:30:00,8929\n2014-12-14 09:00:00,10358\n2014-12-14 09:30:00,14261\n2014-12-14 10:00:00,16254\n2014-12-14 10:30:00,19993\n2014-12-14 11:00:00,20203\n2014-12-14 11:30:00,21630\n2014-12-14 12:00:00,22210\n2014-12-14 12:30:00,22458\n2014-12-14 13:00:00,21793\n2014-12-14 13:30:00,21177\n2014-12-14 14:00:00,20831\n2014-12-14 14:30:00,20577\n2014-12-14 15:00:00,20293\n2014-12-14 15:30:00,18839\n2014-12-14 16:00:00,17406\n2014-12-14 16:30:00,15292\n2014-12-14 17:00:00,16443\n2014-12-14 17:30:00,17727\n2014-12-14 18:00:00,18988\n2014-12-14 18:30:00,19533\n2014-12-14 19:00:00,19548\n2014-12-14 19:30:00,18055\n2014-12-14 20:00:00,17006\n2014-12-14 20:30:00,16671\n2014-12-14 21:00:00,16007\n2014-12-14 21:30:00,16344\n2014-12-14 22:00:00,15913\n2014-12-14 22:30:00,14327\n2014-12-14 23:00:00,12060\n2014-12-14 23:30:00,10952\n2014-12-15 00:00:00,9228\n2014-12-15 00:30:00,6754\n2014-12-15 01:00:00,5230\n2014-12-15 01:30:00,4058\n2014-12-15 02:00:00,3386\n2014-12-15 02:30:00,2854\n2014-12-15 03:00:00,2088\n2014-12-15 03:30:00,2063\n2014-12-15 04:00:00,2573\n2014-12-15 04:30:00,2606\n2014-12-15 05:00:00,3027\n2014-12-15 05:30:00,4795\n2014-12-15 06:00:00,7029\n2014-12-15 06:30:00,11534\n2014-12-15 07:00:00,14434\n2014-12-15 07:30:00,17808\n2014-12-15 08:00:00,18371\n2014-12-15 08:30:00,18743\n2014-12-15 09:00:00,17992\n2014-12-15 09:30:00,17405\n2014-12-15 10:00:00,16508\n2014-12-15 10:30:00,15778\n2014-12-15 11:00:00,15424\n2014-12-15 11:30:00,16627\n2014-12-15 12:00:00,16484\n2014-12-15 12:30:00,16637\n2014-12-15 13:00:00,16135\n2014-12-15 13:30:00,16513\n2014-12-15 14:00:00,17025\n2014-12-15 14:30:00,18231\n2014-12-15 15:00:00,17722\n2014-12-15 15:30:00,16477\n2014-12-15 16:00:00,14298\n2014-12-15 16:30:00,13229\n2014-12-15 17:00:00,15523\n2014-12-15 17:30:00,17795\n2014-12-15 18:00:00,20424\n2014-12-15 18:30:00,21017\n2014-12-15 19:00:00,21475\n2014-12-15 19:30:00,22549\n2014-12-15 20:00:00,21924\n2014-12-15 20:30:00,21131\n2014-12-15 21:00:00,21393\n2014-12-15 21:30:00,21577\n2014-12-15 22:00:00,21019\n2014-12-15 22:30:00,18908\n2014-12-15 23:00:00,17370\n2014-12-15 23:30:00,13782\n2014-12-16 00:00:00,11608\n2014-12-16 00:30:00,8753\n2014-12-16 01:00:00,6959\n2014-12-16 01:30:00,5332\n2014-12-16 02:00:00,4417\n2014-12-16 02:30:00,3812\n2014-12-16 03:00:00,2785\n2014-12-16 03:30:00,2230\n2014-12-16 04:00:00,2383\n2014-12-16 04:30:00,2206\n2014-12-16 05:00:00,2455\n2014-12-16 05:30:00,4355\n2014-12-16 06:00:00,6534\n2014-12-16 06:30:00,11684\n2014-12-16 07:00:00,14785\n2014-12-16 07:30:00,18872\n2014-12-16 08:00:00,19244\n2014-12-16 08:30:00,20521\n2014-12-16 09:00:00,19197\n2014-12-16 09:30:00,18299\n2014-12-16 10:00:00,17178\n2014-12-16 10:30:00,16812\n2014-12-16 11:00:00,16250\n2014-12-16 11:30:00,17275\n2014-12-16 12:00:00,17818\n2014-12-16 12:30:00,17228\n2014-12-16 13:00:00,16423\n2014-12-16 13:30:00,17067\n2014-12-16 14:00:00,17759\n2014-12-16 14:30:00,18175\n2014-12-16 15:00:00,17997\n2014-12-16 15:30:00,16045\n2014-12-16 16:00:00,14086\n2014-12-16 16:30:00,12498\n2014-12-16 17:00:00,15616\n2014-12-16 17:30:00,17897\n2014-12-16 18:00:00,20215\n2014-12-16 18:30:00,21911\n2014-12-16 19:00:00,22798\n2014-12-16 19:30:00,24359\n2014-12-16 20:00:00,23687\n2014-12-16 20:30:00,23843\n2014-12-16 21:00:00,23849\n2014-12-16 21:30:00,24686\n2014-12-16 22:00:00,23566\n2014-12-16 22:30:00,22591\n2014-12-16 23:00:00,20184\n2014-12-16 23:30:00,17824\n2014-12-17 00:00:00,14522\n2014-12-17 00:30:00,10981\n2014-12-17 01:00:00,8494\n2014-12-17 01:30:00,6739\n2014-12-17 02:00:00,5562\n2014-12-17 02:30:00,4095\n2014-12-17 03:00:00,3228\n2014-12-17 03:30:00,2801\n2014-12-17 04:00:00,2905\n2014-12-17 04:30:00,2604\n2014-12-17 05:00:00,2634\n2014-12-17 05:30:00,4453\n2014-12-17 06:00:00,6610\n2014-12-17 06:30:00,11882\n2014-12-17 07:00:00,15378\n2014-12-17 07:30:00,18958\n2014-12-17 08:00:00,20241\n2014-12-17 08:30:00,20321\n2014-12-17 09:00:00,19626\n2014-12-17 09:30:00,18615\n2014-12-17 10:00:00,17801\n2014-12-17 10:30:00,17622\n2014-12-17 11:00:00,17122\n2014-12-17 11:30:00,18747\n2014-12-17 12:00:00,18708\n2014-12-17 12:30:00,18308\n2014-12-17 13:00:00,17777\n2014-12-17 13:30:00,17824\n2014-12-17 14:00:00,18196\n2014-12-17 14:30:00,18499\n2014-12-17 15:00:00,18003\n2014-12-17 15:30:00,16052\n2014-12-17 16:00:00,13607\n2014-12-17 16:30:00,12212\n2014-12-17 17:00:00,14983\n2014-12-17 17:30:00,18285\n2014-12-17 18:00:00,20665\n2014-12-17 18:30:00,21841\n2014-12-17 19:00:00,23081\n2014-12-17 19:30:00,22785\n2014-12-17 20:00:00,24069\n2014-12-17 20:30:00,24039\n2014-12-17 21:00:00,25073\n2014-12-17 21:30:00,24980\n2014-12-17 22:00:00,24878\n2014-12-17 22:30:00,23338\n2014-12-17 23:00:00,22407\n2014-12-17 23:30:00,20950\n2014-12-18 00:00:00,18285\n2014-12-18 00:30:00,14827\n2014-12-18 01:00:00,10904\n2014-12-18 01:30:00,8901\n2014-12-18 02:00:00,6765\n2014-12-18 02:30:00,5188\n2014-12-18 03:00:00,3823\n2014-12-18 03:30:00,3524\n2014-12-18 04:00:00,3414\n2014-12-18 04:30:00,2681\n2014-12-18 05:00:00,3079\n2014-12-18 05:30:00,4828\n2014-12-18 06:00:00,7029\n2014-12-18 06:30:00,12063\n2014-12-18 07:00:00,15230\n2014-12-18 07:30:00,18835\n2014-12-18 08:00:00,20484\n2014-12-18 08:30:00,20222\n2014-12-18 09:00:00,19752\n2014-12-18 09:30:00,18914\n2014-12-18 10:00:00,18466\n2014-12-18 10:30:00,18364\n2014-12-18 11:00:00,17439\n2014-12-18 11:30:00,19228\n2014-12-18 12:00:00,19485\n2014-12-18 12:30:00,18539\n2014-12-18 13:00:00,18424\n2014-12-18 13:30:00,18594\n2014-12-18 14:00:00,19253\n2014-12-18 14:30:00,19536\n2014-12-18 15:00:00,19129\n2014-12-18 15:30:00,16419\n2014-12-18 16:00:00,14143\n2014-12-18 16:30:00,12440\n2014-12-18 17:00:00,15352\n2014-12-18 17:30:00,19402\n2014-12-18 18:00:00,21772\n2014-12-18 18:30:00,23309\n2014-12-18 19:00:00,24617\n2014-12-18 19:30:00,24906\n2014-12-18 20:00:00,25149\n2014-12-18 20:30:00,25441\n2014-12-18 21:00:00,26065\n2014-12-18 21:30:00,25822\n2014-12-18 22:00:00,25738\n2014-12-18 22:30:00,24879\n2014-12-18 23:00:00,24496\n2014-12-18 23:30:00,23501\n2014-12-19 00:00:00,20698\n2014-12-19 00:30:00,19243\n2014-12-19 01:00:00,16900\n2014-12-19 01:30:00,13421\n2014-12-19 02:00:00,10585\n2014-12-19 02:30:00,8512\n2014-12-19 03:00:00,6744\n2014-12-19 03:30:00,5653\n2014-12-19 04:00:00,5420\n2014-12-19 04:30:00,3982\n2014-12-19 05:00:00,3682\n2014-12-19 05:30:00,4979\n2014-12-19 06:00:00,6847\n2014-12-19 06:30:00,11330\n2014-12-19 07:00:00,14716\n2014-12-19 07:30:00,18996\n2014-12-19 08:00:00,20784\n2014-12-19 08:30:00,20763\n2014-12-19 09:00:00,21030\n2014-12-19 09:30:00,19778\n2014-12-19 10:00:00,18496\n2014-12-19 10:30:00,18800\n2014-12-19 11:00:00,18765\n2014-12-19 11:30:00,20209\n2014-12-19 12:00:00,19684\n2014-12-19 12:30:00,18093\n2014-12-19 13:00:00,17958\n2014-12-19 13:30:00,18794\n2014-12-19 14:00:00,19592\n2014-12-19 14:30:00,20240\n2014-12-19 15:00:00,19125\n2014-12-19 15:30:00,16262\n2014-12-19 16:00:00,14858\n2014-12-19 16:30:00,12685\n2014-12-19 17:00:00,15752\n2014-12-19 17:30:00,19931\n2014-12-19 18:00:00,22925\n2014-12-19 18:30:00,24921\n2014-12-19 19:00:00,26335\n2014-12-19 19:30:00,26896\n2014-12-19 20:00:00,26796\n2014-12-19 20:30:00,25989\n2014-12-19 21:00:00,26280\n2014-12-19 21:30:00,26403\n2014-12-19 22:00:00,26905\n2014-12-19 22:30:00,26723\n2014-12-19 23:00:00,25807\n2014-12-19 23:30:00,26432\n2014-12-20 00:00:00,25976\n2014-12-20 00:30:00,24322\n2014-12-20 01:00:00,22993\n2014-12-20 01:30:00,21186\n2014-12-20 02:00:00,19390\n2014-12-20 02:30:00,16298\n2014-12-20 03:00:00,14308\n2014-12-20 03:30:00,12289\n2014-12-20 04:00:00,10822\n2014-12-20 04:30:00,6612\n2014-12-20 05:00:00,4648\n2014-12-20 05:30:00,3998\n2014-12-20 06:00:00,4080\n2014-12-20 06:30:00,5139\n2014-12-20 07:00:00,4833\n2014-12-20 07:30:00,6360\n2014-12-20 08:00:00,7568\n2014-12-20 08:30:00,10329\n2014-12-20 09:00:00,11646\n2014-12-20 09:30:00,15228\n2014-12-20 10:00:00,16173\n2014-12-20 10:30:00,18920\n2014-12-20 11:00:00,19813\n2014-12-20 11:30:00,21529\n2014-12-20 12:00:00,22544\n2014-12-20 12:30:00,22751\n2014-12-20 13:00:00,22744\n2014-12-20 13:30:00,22263\n2014-12-20 14:00:00,22212\n2014-12-20 14:30:00,21906\n2014-12-20 15:00:00,21744\n2014-12-20 15:30:00,21173\n2014-12-20 16:00:00,18061\n2014-12-20 16:30:00,15360\n2014-12-20 17:00:00,17470\n2014-12-20 17:30:00,20909\n2014-12-20 18:00:00,22562\n2014-12-20 18:30:00,24471\n2014-12-20 19:00:00,25685\n2014-12-20 19:30:00,25252\n2014-12-20 20:00:00,23238\n2014-12-20 20:30:00,22683\n2014-12-20 21:00:00,22523\n2014-12-20 21:30:00,23214\n2014-12-20 22:00:00,23741\n2014-12-20 22:30:00,24614\n2014-12-20 23:00:00,25195\n2014-12-20 23:30:00,25864\n2014-12-21 00:00:00,25530\n2014-12-21 00:30:00,24429\n2014-12-21 01:00:00,22976\n2014-12-21 01:30:00,21027\n2014-12-21 02:00:00,19741\n2014-12-21 02:30:00,17359\n2014-12-21 03:00:00,15156\n2014-12-21 03:30:00,12970\n2014-12-21 04:00:00,11246\n2014-12-21 04:30:00,6712\n2014-12-21 05:00:00,4593\n2014-12-21 05:30:00,3675\n2014-12-21 06:00:00,3974\n2014-12-21 06:30:00,3929\n2014-12-21 07:00:00,3922\n2014-12-21 07:30:00,5061\n2014-12-21 08:00:00,5995\n2014-12-21 08:30:00,7813\n2014-12-21 09:00:00,9237\n2014-12-21 09:30:00,12647\n2014-12-21 10:00:00,13946\n2014-12-21 10:30:00,18143\n2014-12-21 11:00:00,18415\n2014-12-21 11:30:00,19646\n2014-12-21 12:00:00,20124\n2014-12-21 12:30:00,21235\n2014-12-21 13:00:00,20709\n2014-12-21 13:30:00,20382\n2014-12-21 14:00:00,20570\n2014-12-21 14:30:00,20093\n2014-12-21 15:00:00,19670\n2014-12-21 15:30:00,19194\n2014-12-21 16:00:00,17506\n2014-12-21 16:30:00,15650\n2014-12-21 17:00:00,17057\n2014-12-21 17:30:00,19010\n2014-12-21 18:00:00,19688\n2014-12-21 18:30:00,19461\n2014-12-21 19:00:00,19098\n2014-12-21 19:30:00,17989\n2014-12-21 20:00:00,16406\n2014-12-21 20:30:00,16716\n2014-12-21 21:00:00,15983\n2014-12-21 21:30:00,16304\n2014-12-21 22:00:00,15546\n2014-12-21 22:30:00,13653\n2014-12-21 23:00:00,12018\n2014-12-21 23:30:00,10392\n2014-12-22 00:00:00,8488\n2014-12-22 00:30:00,6812\n2014-12-22 01:00:00,5155\n2014-12-22 01:30:00,4081\n2014-12-22 02:00:00,3429\n2014-12-22 02:30:00,2686\n2014-12-22 03:00:00,2341\n2014-12-22 03:30:00,2080\n2014-12-22 04:00:00,2561\n2014-12-22 04:30:00,2438\n2014-12-22 05:00:00,2549\n2014-12-22 05:30:00,4003\n2014-12-22 06:00:00,5410\n2014-12-22 06:30:00,9139\n2014-12-22 07:00:00,10980\n2014-12-22 07:30:00,13351\n2014-12-22 08:00:00,14666\n2014-12-22 08:30:00,16540\n2014-12-22 09:00:00,16439\n2014-12-22 09:30:00,16681\n2014-12-22 10:00:00,15663\n2014-12-22 10:30:00,16128\n2014-12-22 11:00:00,16377\n2014-12-22 11:30:00,17607\n2014-12-22 12:00:00,17770\n2014-12-22 12:30:00,17843\n2014-12-22 13:00:00,17279\n2014-12-22 13:30:00,18264\n2014-12-22 14:00:00,18359\n2014-12-22 14:30:00,18664\n2014-12-22 15:00:00,18428\n2014-12-22 15:30:00,15976\n2014-12-22 16:00:00,13994\n2014-12-22 16:30:00,12958\n2014-12-22 17:00:00,15433\n2014-12-22 17:30:00,17793\n2014-12-22 18:00:00,19903\n2014-12-22 18:30:00,20358\n2014-12-22 19:00:00,20800\n2014-12-22 19:30:00,19898\n2014-12-22 20:00:00,18981\n2014-12-22 20:30:00,19600\n2014-12-22 21:00:00,19672\n2014-12-22 21:30:00,20359\n2014-12-22 22:00:00,19147\n2014-12-22 22:30:00,17490\n2014-12-22 23:00:00,14392\n2014-12-22 23:30:00,12366\n2014-12-23 00:00:00,10077\n2014-12-23 00:30:00,8426\n2014-12-23 01:00:00,7343\n2014-12-23 01:30:00,5818\n2014-12-23 02:00:00,4395\n2014-12-23 02:30:00,3238\n2014-12-23 03:00:00,2837\n2014-12-23 03:30:00,2628\n2014-12-23 04:00:00,2815\n2014-12-23 04:30:00,2524\n2014-12-23 05:00:00,2749\n2014-12-23 05:30:00,4221\n2014-12-23 06:00:00,5790\n2014-12-23 06:30:00,9106\n2014-12-23 07:00:00,10805\n2014-12-23 07:30:00,13627\n2014-12-23 08:00:00,14896\n2014-12-23 08:30:00,16914\n2014-12-23 09:00:00,16813\n2014-12-23 09:30:00,17257\n2014-12-23 10:00:00,16746\n2014-12-23 10:30:00,16668\n2014-12-23 11:00:00,16334\n2014-12-23 11:30:00,17869\n2014-12-23 12:00:00,18559\n2014-12-23 12:30:00,18627\n2014-12-23 13:00:00,18394\n2014-12-23 13:30:00,19529\n2014-12-23 14:00:00,18765\n2014-12-23 14:30:00,19273\n2014-12-23 15:00:00,18364\n2014-12-23 15:30:00,16426\n2014-12-23 16:00:00,13940\n2014-12-23 16:30:00,12171\n2014-12-23 17:00:00,14585\n2014-12-23 17:30:00,16878\n2014-12-23 18:00:00,19444\n2014-12-23 18:30:00,20377\n2014-12-23 19:00:00,20065\n2014-12-23 19:30:00,19194\n2014-12-23 20:00:00,18589\n2014-12-23 20:30:00,17560\n2014-12-23 21:00:00,17394\n2014-12-23 21:30:00,18424\n2014-12-23 22:00:00,16611\n2014-12-23 22:30:00,15547\n2014-12-23 23:00:00,14391\n2014-12-23 23:30:00,12687\n2014-12-24 00:00:00,11488\n2014-12-24 00:30:00,9158\n2014-12-24 01:00:00,7484\n2014-12-24 01:30:00,6303\n2014-12-24 02:00:00,5454\n2014-12-24 02:30:00,4400\n2014-12-24 03:00:00,3409\n2014-12-24 03:30:00,3301\n2014-12-24 04:00:00,3479\n2014-12-24 04:30:00,2809\n2014-12-24 05:00:00,2713\n2014-12-24 05:30:00,3654\n2014-12-24 06:00:00,4943\n2014-12-24 06:30:00,6952\n2014-12-24 07:00:00,7357\n2014-12-24 07:30:00,9019\n2014-12-24 08:00:00,9982\n2014-12-24 08:30:00,12036\n2014-12-24 09:00:00,13416\n2014-12-24 09:30:00,16386\n2014-12-24 10:00:00,18242\n2014-12-24 10:30:00,17436\n2014-12-24 11:00:00,19281\n2014-12-24 11:30:00,18939\n2014-12-24 12:00:00,18558\n2014-12-24 12:30:00,20400\n2014-12-24 13:00:00,21494\n2014-12-24 13:30:00,19961\n2014-12-24 14:00:00,19618\n2014-12-24 14:30:00,17870\n2014-12-24 15:00:00,17549\n2014-12-24 15:30:00,17387\n2014-12-24 16:00:00,15882\n2014-12-24 16:30:00,15280\n2014-12-24 17:00:00,16907\n2014-12-24 17:30:00,16821\n2014-12-24 18:00:00,17096\n2014-12-24 18:30:00,16830\n2014-12-24 19:00:00,15846\n2014-12-24 19:30:00,14421\n2014-12-24 20:00:00,13101\n2014-12-24 20:30:00,13010\n2014-12-24 21:00:00,12453\n2014-12-24 21:30:00,12904\n2014-12-24 22:00:00,12563\n2014-12-24 22:30:00,12915\n2014-12-24 23:00:00,12169\n2014-12-24 23:30:00,11420\n2014-12-25 00:00:00,10665\n2014-12-25 00:30:00,9890\n2014-12-25 01:00:00,8488\n2014-12-25 01:30:00,7209\n2014-12-25 02:00:00,6240\n2014-12-25 02:30:00,5143\n2014-12-25 03:00:00,4003\n2014-12-25 03:30:00,3414\n2014-12-25 04:00:00,3206\n2014-12-25 04:30:00,2193\n2014-12-25 05:00:00,1801\n2014-12-25 05:30:00,1756\n2014-12-25 06:00:00,2144\n2014-12-25 06:30:00,2710\n2014-12-25 07:00:00,2637\n2014-12-25 07:30:00,3029\n2014-12-25 08:00:00,2926\n2014-12-25 08:30:00,3485\n2014-12-25 09:00:00,4195\n2014-12-25 09:30:00,5410\n2014-12-25 10:00:00,6572\n2014-12-25 10:30:00,7857\n2014-12-25 11:00:00,8586\n2014-12-25 11:30:00,9599\n2014-12-25 12:00:00,10158\n2014-12-25 12:30:00,10843\n2014-12-25 13:00:00,10618\n2014-12-25 13:30:00,11206\n2014-12-25 14:00:00,11176\n2014-12-25 14:30:00,12218\n2014-12-25 15:00:00,12039\n2014-12-25 15:30:00,11754\n2014-12-25 16:00:00,11282\n2014-12-25 16:30:00,10380\n2014-12-25 17:00:00,10642\n2014-12-25 17:30:00,10788\n2014-12-25 18:00:00,10786\n2014-12-25 18:30:00,11433\n2014-12-25 19:00:00,11262\n2014-12-25 19:30:00,10510\n2014-12-25 20:00:00,9827\n2014-12-25 20:30:00,10446\n2014-12-25 21:00:00,10164\n2014-12-25 21:30:00,11279\n2014-12-25 22:00:00,10756\n2014-12-25 22:30:00,10622\n2014-12-25 23:00:00,8270\n2014-12-25 23:30:00,7685\n2014-12-26 00:00:00,6540\n2014-12-26 00:30:00,5312\n2014-12-26 01:00:00,4573\n2014-12-26 01:30:00,3322\n2014-12-26 02:00:00,2840\n2014-12-26 02:30:00,2294\n2014-12-26 03:00:00,1888\n2014-12-26 03:30:00,1628\n2014-12-26 04:00:00,1962\n2014-12-26 04:30:00,1541\n2014-12-26 05:00:00,1459\n2014-12-26 05:30:00,1993\n2014-12-26 06:00:00,2763\n2014-12-26 06:30:00,3830\n2014-12-26 07:00:00,4376\n2014-12-26 07:30:00,5533\n2014-12-26 08:00:00,6342\n2014-12-26 08:30:00,7425\n2014-12-26 09:00:00,8473\n2014-12-26 09:30:00,9288\n2014-12-26 10:00:00,10259\n2014-12-26 10:30:00,10994\n2014-12-26 11:00:00,11708\n2014-12-26 11:30:00,13105\n2014-12-26 12:00:00,13577\n2014-12-26 12:30:00,14110\n2014-12-26 13:00:00,14559\n2014-12-26 13:30:00,14063\n2014-12-26 14:00:00,14506\n2014-12-26 14:30:00,15863\n2014-12-26 15:00:00,16608\n2014-12-26 15:30:00,15959\n2014-12-26 16:00:00,15481\n2014-12-26 16:30:00,14491\n2014-12-26 17:00:00,15597\n2014-12-26 17:30:00,16349\n2014-12-26 18:00:00,16711\n2014-12-26 18:30:00,16708\n2014-12-26 19:00:00,18113\n2014-12-26 19:30:00,16700\n2014-12-26 20:00:00,15087\n2014-12-26 20:30:00,15282\n2014-12-26 21:00:00,14797\n2014-12-26 21:30:00,14744\n2014-12-26 22:00:00,15618\n2014-12-26 22:30:00,16172\n2014-12-26 23:00:00,14863\n2014-12-26 23:30:00,13696\n2014-12-27 00:00:00,13396\n2014-12-27 00:30:00,12040\n2014-12-27 01:00:00,11298\n2014-12-27 01:30:00,10005\n2014-12-27 02:00:00,9368\n2014-12-27 02:30:00,8002\n2014-12-27 03:00:00,7493\n2014-12-27 03:30:00,6509\n2014-12-27 04:00:00,5928\n2014-12-27 04:30:00,4158\n2014-12-27 05:00:00,2648\n2014-12-27 05:30:00,2313\n2014-12-27 06:00:00,2391\n2014-12-27 06:30:00,2821\n2014-12-27 07:00:00,2967\n2014-12-27 07:30:00,4013\n2014-12-27 08:00:00,4505\n2014-12-27 08:30:00,6117\n2014-12-27 09:00:00,7591\n2014-12-27 09:30:00,9467\n2014-12-27 10:00:00,10065\n2014-12-27 10:30:00,11788\n2014-12-27 11:00:00,12882\n2014-12-27 11:30:00,14317\n2014-12-27 12:00:00,15130\n2014-12-27 12:30:00,15345\n2014-12-27 13:00:00,17040\n2014-12-27 13:30:00,16684\n2014-12-27 14:00:00,16291\n2014-12-27 14:30:00,17065\n2014-12-27 15:00:00,17860\n2014-12-27 15:30:00,17447\n2014-12-27 16:00:00,16199\n2014-12-27 16:30:00,14999\n2014-12-27 17:00:00,15570\n2014-12-27 17:30:00,17132\n2014-12-27 18:00:00,17710\n2014-12-27 18:30:00,18132\n2014-12-27 19:00:00,18627\n2014-12-27 19:30:00,17430\n2014-12-27 20:00:00,16148\n2014-12-27 20:30:00,15807\n2014-12-27 21:00:00,16121\n2014-12-27 21:30:00,17054\n2014-12-27 22:00:00,18095\n2014-12-27 22:30:00,17628\n2014-12-27 23:00:00,17414\n2014-12-27 23:30:00,17594\n2014-12-28 00:00:00,16514\n2014-12-28 00:30:00,15556\n2014-12-28 01:00:00,14465\n2014-12-28 01:30:00,12810\n2014-12-28 02:00:00,12680\n2014-12-28 02:30:00,11121\n2014-12-28 03:00:00,9850\n2014-12-28 03:30:00,9033\n2014-12-28 04:00:00,8122\n2014-12-28 04:30:00,5228\n2014-12-28 05:00:00,3452\n2014-12-28 05:30:00,2937\n2014-12-28 06:00:00,2764\n2014-12-28 06:30:00,3090\n2014-12-28 07:00:00,3109\n2014-12-28 07:30:00,4300\n2014-12-28 08:00:00,5130\n2014-12-28 08:30:00,6652\n2014-12-28 09:00:00,7486\n2014-12-28 09:30:00,9812\n2014-12-28 10:00:00,10911\n2014-12-28 10:30:00,13280\n2014-12-28 11:00:00,13191\n2014-12-28 11:30:00,14218\n2014-12-28 12:00:00,14878\n2014-12-28 12:30:00,15665\n2014-12-28 13:00:00,15911\n2014-12-28 13:30:00,15002\n2014-12-28 14:00:00,15102\n2014-12-28 14:30:00,15658\n2014-12-28 15:00:00,15756\n2014-12-28 15:30:00,16645\n2014-12-28 16:00:00,16464\n2014-12-28 16:30:00,15288\n2014-12-28 17:00:00,15988\n2014-12-28 17:30:00,16608\n2014-12-28 18:00:00,16556\n2014-12-28 18:30:00,16635\n2014-12-28 19:00:00,16446\n2014-12-28 19:30:00,15796\n2014-12-28 20:00:00,14951\n2014-12-28 20:30:00,14373\n2014-12-28 21:00:00,13695\n2014-12-28 21:30:00,14411\n2014-12-28 22:00:00,14035\n2014-12-28 22:30:00,12954\n2014-12-28 23:00:00,11239\n2014-12-28 23:30:00,10461\n2014-12-29 00:00:00,8548\n2014-12-29 00:30:00,6766\n2014-12-29 01:00:00,5087\n2014-12-29 01:30:00,4353\n2014-12-29 02:00:00,3646\n2014-12-29 02:30:00,2857\n2014-12-29 03:00:00,2484\n2014-12-29 03:30:00,2105\n2014-12-29 04:00:00,2270\n2014-12-29 04:30:00,2033\n2014-12-29 05:00:00,2123\n2014-12-29 05:30:00,2886\n2014-12-29 06:00:00,4249\n2014-12-29 06:30:00,6400\n2014-12-29 07:00:00,6953\n2014-12-29 07:30:00,8715\n2014-12-29 08:00:00,9590\n2014-12-29 08:30:00,12167\n2014-12-29 09:00:00,12436\n2014-12-29 09:30:00,13052\n2014-12-29 10:00:00,13503\n2014-12-29 10:30:00,13798\n2014-12-29 11:00:00,14277\n2014-12-29 11:30:00,15344\n2014-12-29 12:00:00,15677\n2014-12-29 12:30:00,16534\n2014-12-29 13:00:00,16220\n2014-12-29 13:30:00,16650\n2014-12-29 14:00:00,17395\n2014-12-29 14:30:00,17895\n2014-12-29 15:00:00,17701\n2014-12-29 15:30:00,17989\n2014-12-29 16:00:00,16737\n2014-12-29 16:30:00,15371\n2014-12-29 17:00:00,17519\n2014-12-29 17:30:00,18500\n2014-12-29 18:00:00,20064\n2014-12-29 18:30:00,20153\n2014-12-29 19:00:00,20364\n2014-12-29 19:30:00,18808\n2014-12-29 20:00:00,17718\n2014-12-29 20:30:00,16678\n2014-12-29 21:00:00,17523\n2014-12-29 21:30:00,17397\n2014-12-29 22:00:00,16308\n2014-12-29 22:30:00,15954\n2014-12-29 23:00:00,14488\n2014-12-29 23:30:00,12738\n2014-12-30 00:00:00,11042\n2014-12-30 00:30:00,8774\n2014-12-30 01:00:00,7267\n2014-12-30 01:30:00,5704\n2014-12-30 02:00:00,4749\n2014-12-30 02:30:00,3932\n2014-12-30 03:00:00,3336\n2014-12-30 03:30:00,3023\n2014-12-30 04:00:00,3059\n2014-12-30 04:30:00,2399\n2014-12-30 05:00:00,2091\n2014-12-30 05:30:00,3019\n2014-12-30 06:00:00,4208\n2014-12-30 06:30:00,6505\n2014-12-30 07:00:00,7026\n2014-12-30 07:30:00,8953\n2014-12-30 08:00:00,10186\n2014-12-30 08:30:00,13046\n2014-12-30 09:00:00,13519\n2014-12-30 09:30:00,14319\n2014-12-30 10:00:00,14433\n2014-12-30 10:30:00,15570\n2014-12-30 11:00:00,15690\n2014-12-30 11:30:00,17265\n2014-12-30 12:00:00,17830\n2014-12-30 12:30:00,18552\n2014-12-30 13:00:00,19340\n2014-12-30 13:30:00,19070\n2014-12-30 14:00:00,18866\n2014-12-30 14:30:00,18709\n2014-12-30 15:00:00,18906\n2014-12-30 15:30:00,18178\n2014-12-30 16:00:00,16420\n2014-12-30 16:30:00,15066\n2014-12-30 17:00:00,17023\n2014-12-30 17:30:00,19201\n2014-12-30 18:00:00,20950\n2014-12-30 18:30:00,22321\n2014-12-30 19:00:00,22549\n2014-12-30 19:30:00,21405\n2014-12-30 20:00:00,20209\n2014-12-30 20:30:00,19574\n2014-12-30 21:00:00,20294\n2014-12-30 21:30:00,20054\n2014-12-30 22:00:00,19779\n2014-12-30 22:30:00,18396\n2014-12-30 23:00:00,17966\n2014-12-30 23:30:00,15892\n2014-12-31 00:00:00,14294\n2014-12-31 00:30:00,12150\n2014-12-31 01:00:00,10423\n2014-12-31 01:30:00,8229\n2014-12-31 02:00:00,7068\n2014-12-31 02:30:00,5572\n2014-12-31 03:00:00,4669\n2014-12-31 03:30:00,3922\n2014-12-31 04:00:00,4120\n2014-12-31 04:30:00,2786\n2014-12-31 05:00:00,2265\n2014-12-31 05:30:00,2825\n2014-12-31 06:00:00,3705\n2014-12-31 06:30:00,5745\n2014-12-31 07:00:00,6334\n2014-12-31 07:30:00,8324\n2014-12-31 08:00:00,9449\n2014-12-31 08:30:00,11877\n2014-12-31 09:00:00,11917\n2014-12-31 09:30:00,12621\n2014-12-31 10:00:00,13294\n2014-12-31 10:30:00,13850\n2014-12-31 11:00:00,15128\n2014-12-31 11:30:00,16996\n2014-12-31 12:00:00,16815\n2014-12-31 12:30:00,17275\n2014-12-31 13:00:00,18553\n2014-12-31 13:30:00,18607\n2014-12-31 14:00:00,18703\n2014-12-31 14:30:00,18970\n2014-12-31 15:00:00,19316\n2014-12-31 15:30:00,18542\n2014-12-31 16:00:00,17583\n2014-12-31 16:30:00,16607\n2014-12-31 17:00:00,17991\n2014-12-31 17:30:00,18983\n2014-12-31 18:00:00,20014\n2014-12-31 18:30:00,20943\n2014-12-31 19:00:00,22114\n2014-12-31 19:30:00,24368\n2014-12-31 20:00:00,25524\n2014-12-31 20:30:00,26779\n2014-12-31 21:00:00,27804\n2014-12-31 21:30:00,27315\n2014-12-31 22:00:00,25417\n2014-12-31 22:30:00,23177\n2014-12-31 23:00:00,21826\n2014-12-31 23:30:00,14152\n2015-01-01 00:00:00,22153\n2015-01-01 00:30:00,29547\n2015-01-01 01:00:00,30236\n2015-01-01 01:30:00,28348\n2015-01-01 02:00:00,26264\n2015-01-01 02:30:00,25243\n2015-01-01 03:00:00,23117\n2015-01-01 03:30:00,21017\n2015-01-01 04:00:00,18170\n2015-01-01 04:30:00,12629\n2015-01-01 05:00:00,8899\n2015-01-01 05:30:00,6999\n2015-01-01 06:00:00,5750\n2015-01-01 06:30:00,5381\n2015-01-01 07:00:00,5056\n2015-01-01 07:30:00,4930\n2015-01-01 08:00:00,4624\n2015-01-01 08:30:00,4726\n2015-01-01 09:00:00,5505\n2015-01-01 09:30:00,6510\n2015-01-01 10:00:00,7705\n2015-01-01 10:30:00,10007\n2015-01-01 11:00:00,11405\n2015-01-01 11:30:00,13562\n2015-01-01 12:00:00,14537\n2015-01-01 12:30:00,15296\n2015-01-01 13:00:00,15376\n2015-01-01 13:30:00,16302\n2015-01-01 14:00:00,16066\n2015-01-01 14:30:00,16485\n2015-01-01 15:00:00,16887\n2015-01-01 15:30:00,16430\n2015-01-01 16:00:00,16044\n2015-01-01 16:30:00,14655\n2015-01-01 17:00:00,15514\n2015-01-01 17:30:00,16184\n2015-01-01 18:00:00,16280\n2015-01-01 18:30:00,16550\n2015-01-01 19:00:00,15626\n2015-01-01 19:30:00,14304\n2015-01-01 20:00:00,13741\n2015-01-01 20:30:00,13578\n2015-01-01 21:00:00,13326\n2015-01-01 21:30:00,13560\n2015-01-01 22:00:00,12730\n2015-01-01 22:30:00,12533\n2015-01-01 23:00:00,10673\n2015-01-01 23:30:00,9947\n2015-01-02 00:00:00,8258\n2015-01-02 00:30:00,8343\n2015-01-02 01:00:00,6326\n2015-01-02 01:30:00,4485\n2015-01-02 02:00:00,3991\n2015-01-02 02:30:00,3126\n2015-01-02 03:00:00,2794\n2015-01-02 03:30:00,2296\n2015-01-02 04:00:00,2506\n2015-01-02 04:30:00,2012\n2015-01-02 05:00:00,1955\n2015-01-02 05:30:00,2486\n2015-01-02 06:00:00,3774\n2015-01-02 06:30:00,5344\n2015-01-02 07:00:00,5956\n2015-01-02 07:30:00,7314\n2015-01-02 08:00:00,8030\n2015-01-02 08:30:00,10085\n2015-01-02 09:00:00,10867\n2015-01-02 09:30:00,11830\n2015-01-02 10:00:00,12507\n2015-01-02 10:30:00,13943\n2015-01-02 11:00:00,14115\n2015-01-02 11:30:00,15399\n2015-01-02 12:00:00,16521\n2015-01-02 12:30:00,16913\n2015-01-02 13:00:00,16207\n2015-01-02 13:30:00,17068\n2015-01-02 14:00:00,17756\n2015-01-02 14:30:00,17887\n2015-01-02 15:00:00,17936\n2015-01-02 15:30:00,18259\n2015-01-02 16:00:00,16710\n2015-01-02 16:30:00,15525\n2015-01-02 17:00:00,17440\n2015-01-02 17:30:00,19523\n2015-01-02 18:00:00,20137\n2015-01-02 18:30:00,20936\n2015-01-02 19:00:00,21998\n2015-01-02 19:30:00,19934\n2015-01-02 20:00:00,18302\n2015-01-02 20:30:00,17815\n2015-01-02 21:00:00,17366\n2015-01-02 21:30:00,17518\n2015-01-02 22:00:00,19508\n2015-01-02 22:30:00,19720\n2015-01-02 23:00:00,18658\n2015-01-02 23:30:00,19337\n2015-01-03 00:00:00,18085\n2015-01-03 00:30:00,16661\n2015-01-03 01:00:00,15624\n2015-01-03 01:30:00,14177\n2015-01-03 02:00:00,12850\n2015-01-03 02:30:00,11509\n2015-01-03 03:00:00,10329\n2015-01-03 03:30:00,8830\n2015-01-03 04:00:00,7903\n2015-01-03 04:30:00,4497\n2015-01-03 05:00:00,3189\n2015-01-03 05:30:00,2793\n2015-01-03 06:00:00,2810\n2015-01-03 06:30:00,3696\n2015-01-03 07:00:00,3707\n2015-01-03 07:30:00,4758\n2015-01-03 08:00:00,5334\n2015-01-03 08:30:00,7736\n2015-01-03 09:00:00,9130\n2015-01-03 09:30:00,11189\n2015-01-03 10:00:00,11887\n2015-01-03 10:30:00,14095\n2015-01-03 11:00:00,14737\n2015-01-03 11:30:00,16826\n2015-01-03 12:00:00,18143\n2015-01-03 12:30:00,20074\n2015-01-03 13:00:00,21386\n2015-01-03 13:30:00,21466\n2015-01-03 14:00:00,21368\n2015-01-03 14:30:00,21695\n2015-01-03 15:00:00,21529\n2015-01-03 15:30:00,20273\n2015-01-03 16:00:00,19355\n2015-01-03 16:30:00,17061\n2015-01-03 17:00:00,18676\n2015-01-03 17:30:00,21073\n2015-01-03 18:00:00,22091\n2015-01-03 18:30:00,23100\n2015-01-03 19:00:00,23801\n2015-01-03 19:30:00,22393\n2015-01-03 20:00:00,18954\n2015-01-03 20:30:00,18005\n2015-01-03 21:00:00,19333\n2015-01-03 21:30:00,18891\n2015-01-03 22:00:00,20259\n2015-01-03 22:30:00,20055\n2015-01-03 23:00:00,19787\n2015-01-03 23:30:00,20995\n2015-01-04 00:00:00,19613\n2015-01-04 00:30:00,16975\n2015-01-04 01:00:00,16541\n2015-01-04 01:30:00,14379\n2015-01-04 02:00:00,13089\n2015-01-04 02:30:00,10506\n2015-01-04 03:00:00,9216\n2015-01-04 03:30:00,8103\n2015-01-04 04:00:00,6823\n2015-01-04 04:30:00,4263\n2015-01-04 05:00:00,3025\n2015-01-04 05:30:00,2549\n2015-01-04 06:00:00,2605\n2015-01-04 06:30:00,3064\n2015-01-04 07:00:00,3205\n2015-01-04 07:30:00,4254\n2015-01-04 08:00:00,4897\n2015-01-04 08:30:00,6628\n2015-01-04 09:00:00,7726\n2015-01-04 09:30:00,9284\n2015-01-04 10:00:00,10955\n2015-01-04 10:30:00,13348\n2015-01-04 11:00:00,13517\n2015-01-04 11:30:00,14443\n2015-01-04 12:00:00,15285\n2015-01-04 12:30:00,16028\n2015-01-04 13:00:00,16329\n2015-01-04 13:30:00,15891\n2015-01-04 14:00:00,15960\n2015-01-04 14:30:00,16376\n2015-01-04 15:00:00,15303\n2015-01-04 15:30:00,16271\n2015-01-04 16:00:00,15873\n2015-01-04 16:30:00,15588\n2015-01-04 17:00:00,15471\n2015-01-04 17:30:00,16139\n2015-01-04 18:00:00,15862\n2015-01-04 18:30:00,16218\n2015-01-04 19:00:00,14093\n2015-01-04 19:30:00,17786\n2015-01-04 20:00:00,16079\n2015-01-04 20:30:00,14137\n2015-01-04 21:00:00,11407\n2015-01-04 21:30:00,12479\n2015-01-04 22:00:00,11317\n2015-01-04 22:30:00,10005\n2015-01-04 23:00:00,8802\n2015-01-04 23:30:00,8002\n2015-01-05 00:00:00,6669\n2015-01-05 00:30:00,5961\n2015-01-05 01:00:00,4169\n2015-01-05 01:30:00,3365\n2015-01-05 02:00:00,2853\n2015-01-05 02:30:00,2227\n2015-01-05 03:00:00,1609\n2015-01-05 03:30:00,1697\n2015-01-05 04:00:00,1883\n2015-01-05 04:30:00,1837\n2015-01-05 05:00:00,2476\n2015-01-05 05:30:00,4040\n2015-01-05 06:00:00,6431\n2015-01-05 06:30:00,10496\n2015-01-05 07:00:00,13610\n2015-01-05 07:30:00,16277\n2015-01-05 08:00:00,17760\n2015-01-05 08:30:00,18026\n2015-01-05 09:00:00,16706\n2015-01-05 09:30:00,14662\n2015-01-05 10:00:00,13070\n2015-01-05 10:30:00,13459\n2015-01-05 11:00:00,13218\n2015-01-05 11:30:00,13909\n2015-01-05 12:00:00,14379\n2015-01-05 12:30:00,14113\n2015-01-05 13:00:00,13982\n2015-01-05 13:30:00,14514\n2015-01-05 14:00:00,15268\n2015-01-05 14:30:00,16675\n2015-01-05 15:00:00,17423\n2015-01-05 15:30:00,16521\n2015-01-05 16:00:00,15352\n2015-01-05 16:30:00,14644\n2015-01-05 17:00:00,17059\n2015-01-05 17:30:00,19269\n2015-01-05 18:00:00,21361\n2015-01-05 18:30:00,21906\n2015-01-05 19:00:00,21994\n2015-01-05 19:30:00,20678\n2015-01-05 20:00:00,19248\n2015-01-05 20:30:00,17546\n2015-01-05 21:00:00,17201\n2015-01-05 21:30:00,15830\n2015-01-05 22:00:00,14238\n2015-01-05 22:30:00,13120\n2015-01-05 23:00:00,11660\n2015-01-05 23:30:00,9741\n2015-01-06 00:00:00,7969\n2015-01-06 00:30:00,6005\n2015-01-06 01:00:00,4592\n2015-01-06 01:30:00,3487\n2015-01-06 02:00:00,2856\n2015-01-06 02:30:00,2238\n2015-01-06 03:00:00,1689\n2015-01-06 03:30:00,1602\n2015-01-06 04:00:00,1774\n2015-01-06 04:30:00,1721\n2015-01-06 05:00:00,2118\n2015-01-06 05:30:00,4101\n2015-01-06 06:00:00,6266\n2015-01-06 06:30:00,11168\n2015-01-06 07:00:00,13976\n2015-01-06 07:30:00,18081\n2015-01-06 08:00:00,19819\n2015-01-06 08:30:00,20102\n2015-01-06 09:00:00,18237\n2015-01-06 09:30:00,16472\n2015-01-06 10:00:00,14510\n2015-01-06 10:30:00,14365\n2015-01-06 11:00:00,13611\n2015-01-06 11:30:00,14729\n2015-01-06 12:00:00,15072\n2015-01-06 12:30:00,14628\n2015-01-06 13:00:00,14069\n2015-01-06 13:30:00,14987\n2015-01-06 14:00:00,15176\n2015-01-06 14:30:00,16884\n2015-01-06 15:00:00,17055\n2015-01-06 15:30:00,16238\n2015-01-06 16:00:00,14566\n2015-01-06 16:30:00,14604\n2015-01-06 17:00:00,16314\n2015-01-06 17:30:00,18758\n2015-01-06 18:00:00,21579\n2015-01-06 18:30:00,22500\n2015-01-06 19:00:00,21920\n2015-01-06 19:30:00,20788\n2015-01-06 20:00:00,20461\n2015-01-06 20:30:00,19640\n2015-01-06 21:00:00,19580\n2015-01-06 21:30:00,19424\n2015-01-06 22:00:00,17170\n2015-01-06 22:30:00,14955\n2015-01-06 23:00:00,12934\n2015-01-06 23:30:00,11087\n2015-01-07 00:00:00,8357\n2015-01-07 00:30:00,6788\n2015-01-07 01:00:00,5378\n2015-01-07 01:30:00,3889\n2015-01-07 02:00:00,3068\n2015-01-07 02:30:00,2406\n2015-01-07 03:00:00,2025\n2015-01-07 03:30:00,1739\n2015-01-07 04:00:00,1897\n2015-01-07 04:30:00,1820\n2015-01-07 05:00:00,2039\n2015-01-07 05:30:00,3857\n2015-01-07 06:00:00,6280\n2015-01-07 06:30:00,11280\n2015-01-07 07:00:00,14586\n2015-01-07 07:30:00,18374\n2015-01-07 08:00:00,20307\n2015-01-07 08:30:00,21113\n2015-01-07 09:00:00,19287\n2015-01-07 09:30:00,17966\n2015-01-07 10:00:00,15690\n2015-01-07 10:30:00,16091\n2015-01-07 11:00:00,14981\n2015-01-07 11:30:00,16906\n2015-01-07 12:00:00,16648\n2015-01-07 12:30:00,16826\n2015-01-07 13:00:00,16379\n2015-01-07 13:30:00,17457\n2015-01-07 14:00:00,17335\n2015-01-07 14:30:00,18690\n2015-01-07 15:00:00,19029\n2015-01-07 15:30:00,17234\n2015-01-07 16:00:00,16505\n2015-01-07 16:30:00,15509\n2015-01-07 17:00:00,17873\n2015-01-07 17:30:00,21871\n2015-01-07 18:00:00,24019\n2015-01-07 18:30:00,24965\n2015-01-07 19:00:00,25708\n2015-01-07 19:30:00,24871\n2015-01-07 20:00:00,23732\n2015-01-07 20:30:00,22463\n2015-01-07 21:00:00,23142\n2015-01-07 21:30:00,22369\n2015-01-07 22:00:00,21904\n2015-01-07 22:30:00,18610\n2015-01-07 23:00:00,15262\n2015-01-07 23:30:00,12490\n2015-01-08 00:00:00,9843\n2015-01-08 00:30:00,7477\n2015-01-08 01:00:00,5697\n2015-01-08 01:30:00,4327\n2015-01-08 02:00:00,3405\n2015-01-08 02:30:00,2739\n2015-01-08 03:00:00,2066\n2015-01-08 03:30:00,2013\n2015-01-08 04:00:00,1975\n2015-01-08 04:30:00,1760\n2015-01-08 05:00:00,2033\n2015-01-08 05:30:00,4164\n2015-01-08 06:00:00,6627\n2015-01-08 06:30:00,12142\n2015-01-08 07:00:00,15873\n2015-01-08 07:30:00,20194\n2015-01-08 08:00:00,21891\n2015-01-08 08:30:00,22117\n2015-01-08 09:00:00,20435\n2015-01-08 09:30:00,19472\n2015-01-08 10:00:00,17256\n2015-01-08 10:30:00,17401\n2015-01-08 11:00:00,15595\n2015-01-08 11:30:00,17559\n2015-01-08 12:00:00,17823\n2015-01-08 12:30:00,16634\n2015-01-08 13:00:00,16523\n2015-01-08 13:30:00,17209\n2015-01-08 14:00:00,17438\n2015-01-08 14:30:00,19801\n2015-01-08 15:00:00,20241\n2015-01-08 15:30:00,18535\n2015-01-08 16:00:00,16573\n2015-01-08 16:30:00,15095\n2015-01-08 17:00:00,17871\n2015-01-08 17:30:00,21606\n2015-01-08 18:00:00,24071\n2015-01-08 18:30:00,25176\n2015-01-08 19:00:00,25592\n2015-01-08 19:30:00,25125\n2015-01-08 20:00:00,24584\n2015-01-08 20:30:00,23692\n2015-01-08 21:00:00,23593\n2015-01-08 21:30:00,23676\n2015-01-08 22:00:00,23367\n2015-01-08 22:30:00,21952\n2015-01-08 23:00:00,19331\n2015-01-08 23:30:00,15847\n2015-01-09 00:00:00,13156\n2015-01-09 00:30:00,10295\n2015-01-09 01:00:00,8080\n2015-01-09 01:30:00,6041\n2015-01-09 02:00:00,5180\n2015-01-09 02:30:00,3992\n2015-01-09 03:00:00,3359\n2015-01-09 03:30:00,2808\n2015-01-09 04:00:00,2703\n2015-01-09 04:30:00,2176\n2015-01-09 05:00:00,2434\n2015-01-09 05:30:00,4092\n2015-01-09 06:00:00,6053\n2015-01-09 06:30:00,11326\n2015-01-09 07:00:00,13826\n2015-01-09 07:30:00,15011\n2015-01-09 08:00:00,15124\n2015-01-09 08:30:00,15755\n2015-01-09 09:00:00,16110\n2015-01-09 09:30:00,16271\n2015-01-09 10:00:00,15323\n2015-01-09 10:30:00,15421\n2015-01-09 11:00:00,14604\n2015-01-09 11:30:00,15840\n2015-01-09 12:00:00,15962\n2015-01-09 12:30:00,15948\n2015-01-09 13:00:00,16283\n2015-01-09 13:30:00,16502\n2015-01-09 14:00:00,17377\n2015-01-09 14:30:00,18858\n2015-01-09 15:00:00,18338\n2015-01-09 15:30:00,17567\n2015-01-09 16:00:00,15857\n2015-01-09 16:30:00,15069\n2015-01-09 17:00:00,18144\n2015-01-09 17:30:00,21770\n2015-01-09 18:00:00,24651\n2015-01-09 18:30:00,26480\n2015-01-09 19:00:00,27443\n2015-01-09 19:30:00,27676\n2015-01-09 20:00:00,25589\n2015-01-09 20:30:00,23761\n2015-01-09 21:00:00,23882\n2015-01-09 21:30:00,23922\n2015-01-09 22:00:00,24901\n2015-01-09 22:30:00,25440\n2015-01-09 23:00:00,25306\n2015-01-09 23:30:00,25133\n2015-01-10 00:00:00,24251\n2015-01-10 00:30:00,22330\n2015-01-10 01:00:00,19918\n2015-01-10 01:30:00,17922\n2015-01-10 02:00:00,16425\n2015-01-10 02:30:00,13977\n2015-01-10 03:00:00,11797\n2015-01-10 03:30:00,10171\n2015-01-10 04:00:00,8666\n2015-01-10 04:30:00,4721\n2015-01-10 05:00:00,3390\n2015-01-10 05:30:00,2905\n2015-01-10 06:00:00,3265\n2015-01-10 06:30:00,4249\n2015-01-10 07:00:00,5058\n2015-01-10 07:30:00,6976\n2015-01-10 08:00:00,7425\n2015-01-10 08:30:00,11024\n2015-01-10 09:00:00,13013\n2015-01-10 09:30:00,16327\n2015-01-10 10:00:00,16385\n2015-01-10 10:30:00,18820\n2015-01-10 11:00:00,19868\n2015-01-10 11:30:00,22503\n2015-01-10 12:00:00,22724\n2015-01-10 12:30:00,23856\n2015-01-10 13:00:00,23073\n2015-01-10 13:30:00,22492\n2015-01-10 14:00:00,21336\n2015-01-10 14:30:00,22371\n2015-01-10 15:00:00,23119\n2015-01-10 15:30:00,23941\n2015-01-10 16:00:00,22728\n2015-01-10 16:30:00,20126\n2015-01-10 17:00:00,21139\n2015-01-10 17:30:00,24417\n2015-01-10 18:00:00,26639\n2015-01-10 18:30:00,26907\n2015-01-10 19:00:00,28043\n2015-01-10 19:30:00,26853\n2015-01-10 20:00:00,27983\n2015-01-10 20:30:00,24555\n2015-01-10 21:00:00,23596\n2015-01-10 21:30:00,24947\n2015-01-10 22:00:00,26085\n2015-01-10 22:30:00,27646\n2015-01-10 23:00:00,28301\n2015-01-10 23:30:00,28401\n2015-01-11 00:00:00,26653\n2015-01-11 00:30:00,24790\n2015-01-11 01:00:00,23141\n2015-01-11 01:30:00,20654\n2015-01-11 02:00:00,19179\n2015-01-11 02:30:00,16879\n2015-01-11 03:00:00,14597\n2015-01-11 03:30:00,12394\n2015-01-11 04:00:00,9787\n2015-01-11 04:30:00,5859\n2015-01-11 05:00:00,3682\n2015-01-11 05:30:00,3108\n2015-01-11 06:00:00,2883\n2015-01-11 06:30:00,3710\n2015-01-11 07:00:00,3790\n2015-01-11 07:30:00,5294\n2015-01-11 08:00:00,6133\n2015-01-11 08:30:00,8808\n2015-01-11 09:00:00,9884\n2015-01-11 09:30:00,13052\n2015-01-11 10:00:00,13881\n2015-01-11 10:30:00,17481\n2015-01-11 11:00:00,17730\n2015-01-11 11:30:00,20015\n2015-01-11 12:00:00,19794\n2015-01-11 12:30:00,21709\n2015-01-11 13:00:00,21296\n2015-01-11 13:30:00,20381\n2015-01-11 14:00:00,19508\n2015-01-11 14:30:00,19210\n2015-01-11 15:00:00,18255\n2015-01-11 15:30:00,19171\n2015-01-11 16:00:00,18758\n2015-01-11 16:30:00,19444\n2015-01-11 17:00:00,19816\n2015-01-11 17:30:00,19830\n2015-01-11 18:00:00,19842\n2015-01-11 18:30:00,19586\n2015-01-11 19:00:00,18579\n2015-01-11 19:30:00,17586\n2015-01-11 20:00:00,15320\n2015-01-11 20:30:00,13987\n2015-01-11 21:00:00,13611\n2015-01-11 21:30:00,13943\n2015-01-11 22:00:00,12956\n2015-01-11 22:30:00,11585\n2015-01-11 23:00:00,12116\n2015-01-11 23:30:00,9058\n2015-01-12 00:00:00,7147\n2015-01-12 00:30:00,5365\n2015-01-12 01:00:00,3756\n2015-01-12 01:30:00,3077\n2015-01-12 02:00:00,2603\n2015-01-12 02:30:00,2264\n2015-01-12 03:00:00,1973\n2015-01-12 03:30:00,1679\n2015-01-12 04:00:00,1964\n2015-01-12 04:30:00,1891\n2015-01-12 05:00:00,2303\n2015-01-12 05:30:00,4462\n2015-01-12 06:00:00,6496\n2015-01-12 06:30:00,11269\n2015-01-12 07:00:00,14140\n2015-01-12 07:30:00,18040\n2015-01-12 08:00:00,19618\n2015-01-12 08:30:00,19631\n2015-01-12 09:00:00,18598\n2015-01-12 09:30:00,17797\n2015-01-12 10:00:00,16160\n2015-01-12 10:30:00,15872\n2015-01-12 11:00:00,15103\n2015-01-12 11:30:00,16858\n2015-01-12 12:00:00,17532\n2015-01-12 12:30:00,16478\n2015-01-12 13:00:00,16071\n2015-01-12 13:30:00,17036\n2015-01-12 14:00:00,17167\n2015-01-12 14:30:00,18607\n2015-01-12 15:00:00,19387\n2015-01-12 15:30:00,16274\n2015-01-12 16:00:00,15210\n2015-01-12 16:30:00,14695\n2015-01-12 17:00:00,16686\n2015-01-12 17:30:00,19234\n2015-01-12 18:00:00,21350\n2015-01-12 18:30:00,22150\n2015-01-12 19:00:00,21582\n2015-01-12 19:30:00,20321\n2015-01-12 20:00:00,20071\n2015-01-12 20:30:00,18532\n2015-01-12 21:00:00,18801\n2015-01-12 21:30:00,17972\n2015-01-12 22:00:00,17298\n2015-01-12 22:30:00,14655\n2015-01-12 23:00:00,12376\n2015-01-12 23:30:00,10191\n2015-01-13 00:00:00,11139\n2015-01-13 00:30:00,7323\n2015-01-13 01:00:00,5142\n2015-01-13 01:30:00,3987\n2015-01-13 02:00:00,3197\n2015-01-13 02:30:00,2336\n2015-01-13 03:00:00,1800\n2015-01-13 03:30:00,1742\n2015-01-13 04:00:00,1901\n2015-01-13 04:30:00,1681\n2015-01-13 05:00:00,2036\n2015-01-13 05:30:00,4284\n2015-01-13 06:00:00,6390\n2015-01-13 06:30:00,11432\n2015-01-13 07:00:00,14929\n2015-01-13 07:30:00,19814\n2015-01-13 08:00:00,21295\n2015-01-13 08:30:00,21258\n2015-01-13 09:00:00,20209\n2015-01-13 09:30:00,19420\n2015-01-13 10:00:00,18088\n2015-01-13 10:30:00,17942\n2015-01-13 11:00:00,17251\n2015-01-13 11:30:00,18843\n2015-01-13 12:00:00,18906\n2015-01-13 12:30:00,18117\n2015-01-13 13:00:00,17533\n2015-01-13 13:30:00,18593\n2015-01-13 14:00:00,18967\n2015-01-13 14:30:00,20374\n2015-01-13 15:00:00,20245\n2015-01-13 15:30:00,18663\n2015-01-13 16:00:00,16688\n2015-01-13 16:30:00,14860\n2015-01-13 17:00:00,16990\n2015-01-13 17:30:00,20233\n2015-01-13 18:00:00,23012\n2015-01-13 18:30:00,24353\n2015-01-13 19:00:00,24698\n2015-01-13 19:30:00,24188\n2015-01-13 20:00:00,24033\n2015-01-13 20:30:00,23737\n2015-01-13 21:00:00,23774\n2015-01-13 21:30:00,23522\n2015-01-13 22:00:00,21828\n2015-01-13 22:30:00,18996\n2015-01-13 23:00:00,15659\n2015-01-13 23:30:00,12989\n2015-01-14 00:00:00,10584\n2015-01-14 00:30:00,7941\n2015-01-14 01:00:00,6221\n2015-01-14 01:30:00,4792\n2015-01-14 02:00:00,3814\n2015-01-14 02:30:00,3053\n2015-01-14 03:00:00,2725\n2015-01-14 03:30:00,2356\n2015-01-14 04:00:00,2327\n2015-01-14 04:30:00,2058\n2015-01-14 05:00:00,2267\n2015-01-14 05:30:00,4547\n2015-01-14 06:00:00,6582\n2015-01-14 06:30:00,12004\n2015-01-14 07:00:00,15442\n2015-01-14 07:30:00,20021\n2015-01-14 08:00:00,20953\n2015-01-14 08:30:00,21276\n2015-01-14 09:00:00,20444\n2015-01-14 09:30:00,19071\n2015-01-14 10:00:00,17173\n2015-01-14 10:30:00,17446\n2015-01-14 11:00:00,16319\n2015-01-14 11:30:00,18120\n2015-01-14 12:00:00,18258\n2015-01-14 12:30:00,17222\n2015-01-14 13:00:00,16563\n2015-01-14 13:30:00,17953\n2015-01-14 14:00:00,18119\n2015-01-14 14:30:00,18740\n2015-01-14 15:00:00,18803\n2015-01-14 15:30:00,17318\n2015-01-14 16:00:00,15354\n2015-01-14 16:30:00,14243\n2015-01-14 17:00:00,16310\n2015-01-14 17:30:00,20078\n2015-01-14 18:00:00,22844\n2015-01-14 18:30:00,23895\n2015-01-14 19:00:00,24410\n2015-01-14 19:30:00,24216\n2015-01-14 20:00:00,22351\n2015-01-14 20:30:00,22154\n2015-01-14 21:00:00,22757\n2015-01-14 21:30:00,22301\n2015-01-14 22:00:00,22537\n2015-01-14 22:30:00,19647\n2015-01-14 23:00:00,16555\n2015-01-14 23:30:00,13935\n2015-01-15 00:00:00,10852\n2015-01-15 00:30:00,8131\n2015-01-15 01:00:00,6253\n2015-01-15 01:30:00,4881\n2015-01-15 02:00:00,3872\n2015-01-15 02:30:00,2952\n2015-01-15 03:00:00,2530\n2015-01-15 03:30:00,2242\n2015-01-15 04:00:00,2384\n2015-01-15 04:30:00,2102\n2015-01-15 05:00:00,2353\n2015-01-15 05:30:00,4388\n2015-01-15 06:00:00,6600\n2015-01-15 06:30:00,11844\n2015-01-15 07:00:00,15429\n2015-01-15 07:30:00,19536\n2015-01-15 08:00:00,20800\n2015-01-15 08:30:00,21237\n2015-01-15 09:00:00,20044\n2015-01-15 09:30:00,19195\n2015-01-15 10:00:00,16819\n2015-01-15 10:30:00,17002\n2015-01-15 11:00:00,15592\n2015-01-15 11:30:00,17319\n2015-01-15 12:00:00,18062\n2015-01-15 12:30:00,16821\n2015-01-15 13:00:00,16158\n2015-01-15 13:30:00,17614\n2015-01-15 14:00:00,17978\n2015-01-15 14:30:00,18693\n2015-01-15 15:00:00,18743\n2015-01-15 15:30:00,17213\n2015-01-15 16:00:00,15389\n2015-01-15 16:30:00,13926\n2015-01-15 17:00:00,16336\n2015-01-15 17:30:00,19647\n2015-01-15 18:00:00,22732\n2015-01-15 18:30:00,24064\n2015-01-15 19:00:00,24881\n2015-01-15 19:30:00,24507\n2015-01-15 20:00:00,24438\n2015-01-15 20:30:00,23792\n2015-01-15 21:00:00,24517\n2015-01-15 21:30:00,24126\n2015-01-15 22:00:00,23957\n2015-01-15 22:30:00,22825\n2015-01-15 23:00:00,21086\n2015-01-15 23:30:00,17957\n2015-01-16 00:00:00,14729\n2015-01-16 00:30:00,11814\n2015-01-16 01:00:00,9221\n2015-01-16 01:30:00,7049\n2015-01-16 02:00:00,6102\n2015-01-16 02:30:00,4971\n2015-01-16 03:00:00,4205\n2015-01-16 03:30:00,3238\n2015-01-16 04:00:00,3474\n2015-01-16 04:30:00,2952\n2015-01-16 05:00:00,2858\n2015-01-16 05:30:00,4621\n2015-01-16 06:00:00,6570\n2015-01-16 06:30:00,11368\n2015-01-16 07:00:00,14644\n2015-01-16 07:30:00,18846\n2015-01-16 08:00:00,19936\n2015-01-16 08:30:00,20315\n2015-01-16 09:00:00,19285\n2015-01-16 09:30:00,18492\n2015-01-16 10:00:00,16873\n2015-01-16 10:30:00,16492\n2015-01-16 11:00:00,15440\n2015-01-16 11:30:00,17341\n2015-01-16 12:00:00,17377\n2015-01-16 12:30:00,16922\n2015-01-16 13:00:00,16465\n2015-01-16 13:30:00,17797\n2015-01-16 14:00:00,18924\n2015-01-16 14:30:00,19579\n2015-01-16 15:00:00,19159\n2015-01-16 15:30:00,17343\n2015-01-16 16:00:00,15856\n2015-01-16 16:30:00,14769\n2015-01-16 17:00:00,16980\n2015-01-16 17:30:00,21604\n2015-01-16 18:00:00,24026\n2015-01-16 18:30:00,26085\n2015-01-16 19:00:00,27462\n2015-01-16 19:30:00,27681\n2015-01-16 20:00:00,26427\n2015-01-16 20:30:00,25444\n2015-01-16 21:00:00,25168\n2015-01-16 21:30:00,25376\n2015-01-16 22:00:00,26024\n2015-01-16 22:30:00,26428\n2015-01-16 23:00:00,25890\n2015-01-16 23:30:00,25472\n2015-01-17 00:00:00,24841\n2015-01-17 00:30:00,22159\n2015-01-17 01:00:00,20046\n2015-01-17 01:30:00,17945\n2015-01-17 02:00:00,15954\n2015-01-17 02:30:00,14210\n2015-01-17 03:00:00,12146\n2015-01-17 03:30:00,10342\n2015-01-17 04:00:00,8970\n2015-01-17 04:30:00,5302\n2015-01-17 05:00:00,3600\n2015-01-17 05:30:00,3192\n2015-01-17 06:00:00,3473\n2015-01-17 06:30:00,4304\n2015-01-17 07:00:00,4478\n2015-01-17 07:30:00,6310\n2015-01-17 08:00:00,7465\n2015-01-17 08:30:00,11664\n2015-01-17 09:00:00,12000\n2015-01-17 09:30:00,14970\n2015-01-17 10:00:00,15205\n2015-01-17 10:30:00,17118\n2015-01-17 11:00:00,17495\n2015-01-17 11:30:00,19508\n2015-01-17 12:00:00,20017\n2015-01-17 12:30:00,20707\n2015-01-17 13:00:00,20941\n2015-01-17 13:30:00,20725\n2015-01-17 14:00:00,19358\n2015-01-17 14:30:00,20008\n2015-01-17 15:00:00,20758\n2015-01-17 15:30:00,21068\n2015-01-17 16:00:00,20316\n2015-01-17 16:30:00,19248\n2015-01-17 17:00:00,20449\n2015-01-17 17:30:00,23133\n2015-01-17 18:00:00,23733\n2015-01-17 18:30:00,25602\n2015-01-17 19:00:00,27074\n2015-01-17 19:30:00,25487\n2015-01-17 20:00:00,22437\n2015-01-17 20:30:00,21569\n2015-01-17 21:00:00,21542\n2015-01-17 21:30:00,22661\n2015-01-17 22:00:00,23754\n2015-01-17 22:30:00,25114\n2015-01-17 23:00:00,25308\n2015-01-17 23:30:00,25251\n2015-01-18 00:00:00,25423\n2015-01-18 00:30:00,23964\n2015-01-18 01:00:00,22134\n2015-01-18 01:30:00,20253\n2015-01-18 02:00:00,19354\n2015-01-18 02:30:00,17470\n2015-01-18 03:00:00,14916\n2015-01-18 03:30:00,13069\n2015-01-18 04:00:00,10617\n2015-01-18 04:30:00,6053\n2015-01-18 05:00:00,4097\n2015-01-18 05:30:00,3219\n2015-01-18 06:00:00,3050\n2015-01-18 06:30:00,3114\n2015-01-18 07:00:00,3521\n2015-01-18 07:30:00,4745\n2015-01-18 08:00:00,6290\n2015-01-18 08:30:00,8298\n2015-01-18 09:00:00,9919\n2015-01-18 09:30:00,13441\n2015-01-18 10:00:00,15096\n2015-01-18 10:30:00,18880\n2015-01-18 11:00:00,20210\n2015-01-18 11:30:00,22395\n2015-01-18 12:00:00,22791\n2015-01-18 12:30:00,22619\n2015-01-18 13:00:00,22916\n2015-01-18 13:30:00,22472\n2015-01-18 14:00:00,22015\n2015-01-18 14:30:00,23848\n2015-01-18 15:00:00,22149\n2015-01-18 15:30:00,19787\n2015-01-18 16:00:00,18399\n2015-01-18 16:30:00,18309\n2015-01-18 17:00:00,17623\n2015-01-18 17:30:00,18567\n2015-01-18 18:00:00,18557\n2015-01-18 18:30:00,20670\n2015-01-18 19:00:00,16805\n2015-01-18 19:30:00,14576\n2015-01-18 20:00:00,14056\n2015-01-18 20:30:00,14591\n2015-01-18 21:00:00,13904\n2015-01-18 21:30:00,14487\n2015-01-18 22:00:00,15516\n2015-01-18 22:30:00,14292\n2015-01-18 23:00:00,12676\n2015-01-18 23:30:00,11970\n2015-01-19 00:00:00,10938\n2015-01-19 00:30:00,9181\n2015-01-19 01:00:00,7630\n2015-01-19 01:30:00,6241\n2015-01-19 02:00:00,5370\n2015-01-19 02:30:00,4199\n2015-01-19 03:00:00,3815\n2015-01-19 03:30:00,3367\n2015-01-19 04:00:00,3278\n2015-01-19 04:30:00,2542\n2015-01-19 05:00:00,2341\n2015-01-19 05:30:00,2774\n2015-01-19 06:00:00,3479\n2015-01-19 06:30:00,5228\n2015-01-19 07:00:00,5531\n2015-01-19 07:30:00,7133\n2015-01-19 08:00:00,8572\n2015-01-19 08:30:00,11251\n2015-01-19 09:00:00,11815\n2015-01-19 09:30:00,13223\n2015-01-19 10:00:00,12862\n2015-01-19 10:30:00,14360\n2015-01-19 11:00:00,14101\n2015-01-19 11:30:00,16056\n2015-01-19 12:00:00,16454\n2015-01-19 12:30:00,17460\n2015-01-19 13:00:00,17295\n2015-01-19 13:30:00,17872\n2015-01-19 14:00:00,17517\n2015-01-19 14:30:00,18228\n2015-01-19 15:00:00,17900\n2015-01-19 15:30:00,18245\n2015-01-19 16:00:00,17379\n2015-01-19 16:30:00,16921\n2015-01-19 17:00:00,17309\n2015-01-19 17:30:00,18431\n2015-01-19 18:00:00,19142\n2015-01-19 18:30:00,19449\n2015-01-19 19:00:00,18494\n2015-01-19 19:30:00,17217\n2015-01-19 20:00:00,16075\n2015-01-19 20:30:00,15157\n2015-01-19 21:00:00,14245\n2015-01-19 21:30:00,14069\n2015-01-19 22:00:00,13506\n2015-01-19 22:30:00,12936\n2015-01-19 23:00:00,10400\n2015-01-19 23:30:00,8189\n2015-01-20 00:00:00,6941\n2015-01-20 00:30:00,5164\n2015-01-20 01:00:00,3940\n2015-01-20 01:30:00,3073\n2015-01-20 02:00:00,2690\n2015-01-20 02:30:00,2006\n2015-01-20 03:00:00,1584\n2015-01-20 03:30:00,1495\n2015-01-20 04:00:00,1692\n2015-01-20 04:30:00,1663\n2015-01-20 05:00:00,2275\n2015-01-20 05:30:00,4423\n2015-01-20 06:00:00,6390\n2015-01-20 06:30:00,11694\n2015-01-20 07:00:00,14427\n2015-01-20 07:30:00,18672\n2015-01-20 08:00:00,19568\n2015-01-20 08:30:00,20068\n2015-01-20 09:00:00,18961\n2015-01-20 09:30:00,17965\n2015-01-20 10:00:00,15858\n2015-01-20 10:30:00,15942\n2015-01-20 11:00:00,14858\n2015-01-20 11:30:00,16031\n2015-01-20 12:00:00,15767\n2015-01-20 12:30:00,15718\n2015-01-20 13:00:00,14752\n2015-01-20 13:30:00,16556\n2015-01-20 14:00:00,16333\n2015-01-20 14:30:00,17782\n2015-01-20 15:00:00,17590\n2015-01-20 15:30:00,16525\n2015-01-20 16:00:00,15174\n2015-01-20 16:30:00,14241\n2015-01-20 17:00:00,16378\n2015-01-20 17:30:00,19480\n2015-01-20 18:00:00,22419\n2015-01-20 18:30:00,23262\n2015-01-20 19:00:00,22395\n2015-01-20 19:30:00,21663\n2015-01-20 20:00:00,21386\n2015-01-20 20:30:00,20673\n2015-01-20 21:00:00,21258\n2015-01-20 21:30:00,21186\n2015-01-20 22:00:00,20053\n2015-01-20 22:30:00,16936\n2015-01-20 23:00:00,14319\n2015-01-20 23:30:00,11226\n2015-01-21 00:00:00,8987\n2015-01-21 00:30:00,6616\n2015-01-21 01:00:00,5410\n2015-01-21 01:30:00,4152\n2015-01-21 02:00:00,3405\n2015-01-21 02:30:00,2682\n2015-01-21 03:00:00,2180\n2015-01-21 03:30:00,1905\n2015-01-21 04:00:00,2089\n2015-01-21 04:30:00,1981\n2015-01-21 05:00:00,2213\n2015-01-21 05:30:00,4205\n2015-01-21 06:00:00,6482\n2015-01-21 06:30:00,11513\n2015-01-21 07:00:00,15263\n2015-01-21 07:30:00,19134\n2015-01-21 08:00:00,20366\n2015-01-21 08:30:00,21165\n2015-01-21 09:00:00,19723\n2015-01-21 09:30:00,18557\n2015-01-21 10:00:00,17106\n2015-01-21 10:30:00,17373\n2015-01-21 11:00:00,15714\n2015-01-21 11:30:00,16754\n2015-01-21 12:00:00,17156\n2015-01-21 12:30:00,16405\n2015-01-21 13:00:00,15565\n2015-01-21 13:30:00,17267\n2015-01-21 14:00:00,17711\n2015-01-21 14:30:00,18372\n2015-01-21 15:00:00,18579\n2015-01-21 15:30:00,16601\n2015-01-21 16:00:00,15939\n2015-01-21 16:30:00,14513\n2015-01-21 17:00:00,17001\n2015-01-21 17:30:00,20962\n2015-01-21 18:00:00,23400\n2015-01-21 18:30:00,23891\n2015-01-21 19:00:00,24112\n2015-01-21 19:30:00,23195\n2015-01-21 20:00:00,22527\n2015-01-21 20:30:00,21978\n2015-01-21 21:00:00,22624\n2015-01-21 21:30:00,21970\n2015-01-21 22:00:00,21085\n2015-01-21 22:30:00,19624\n2015-01-21 23:00:00,15974\n2015-01-21 23:30:00,12520\n2015-01-22 00:00:00,10173\n2015-01-22 00:30:00,7771\n2015-01-22 01:00:00,6287\n2015-01-22 01:30:00,4720\n2015-01-22 02:00:00,3642\n2015-01-22 02:30:00,2769\n2015-01-22 03:00:00,2406\n2015-01-22 03:30:00,2194\n2015-01-22 04:00:00,2275\n2015-01-22 04:30:00,2021\n2015-01-22 05:00:00,2385\n2015-01-22 05:30:00,4276\n2015-01-22 06:00:00,6311\n2015-01-22 06:30:00,11643\n2015-01-22 07:00:00,14874\n2015-01-22 07:30:00,19720\n2015-01-22 08:00:00,20607\n2015-01-22 08:30:00,20838\n2015-01-22 09:00:00,19347\n2015-01-22 09:30:00,18316\n2015-01-22 10:00:00,16233\n2015-01-22 10:30:00,16420\n2015-01-22 11:00:00,14997\n2015-01-22 11:30:00,17341\n2015-01-22 12:00:00,17606\n2015-01-22 12:30:00,16850\n2015-01-22 13:00:00,15625\n2015-01-22 13:30:00,17210\n2015-01-22 14:00:00,17552\n2015-01-22 14:30:00,18531\n2015-01-22 15:00:00,18806\n2015-01-22 15:30:00,17322\n2015-01-22 16:00:00,15719\n2015-01-22 16:30:00,14717\n2015-01-22 17:00:00,16955\n2015-01-22 17:30:00,20647\n2015-01-22 18:00:00,23122\n2015-01-22 18:30:00,25031\n2015-01-22 19:00:00,25376\n2015-01-22 19:30:00,25849\n2015-01-22 20:00:00,24434\n2015-01-22 20:30:00,23690\n2015-01-22 21:00:00,24704\n2015-01-22 21:30:00,25221\n2015-01-22 22:00:00,24320\n2015-01-22 22:30:00,22823\n2015-01-22 23:00:00,21754\n2015-01-22 23:30:00,17946\n2015-01-23 00:00:00,14722\n2015-01-23 00:30:00,11815\n2015-01-23 01:00:00,9274\n2015-01-23 01:30:00,7241\n2015-01-23 02:00:00,6184\n2015-01-23 02:30:00,4956\n2015-01-23 03:00:00,4158\n2015-01-23 03:30:00,3499\n2015-01-23 04:00:00,3433\n2015-01-23 04:30:00,2736\n2015-01-23 05:00:00,2534\n2015-01-23 05:30:00,4436\n2015-01-23 06:00:00,6559\n2015-01-23 06:30:00,11173\n2015-01-23 07:00:00,14477\n2015-01-23 07:30:00,19424\n2015-01-23 08:00:00,20059\n2015-01-23 08:30:00,20211\n2015-01-23 09:00:00,19220\n2015-01-23 09:30:00,18519\n2015-01-23 10:00:00,16466\n2015-01-23 10:30:00,16651\n2015-01-23 11:00:00,15564\n2015-01-23 11:30:00,17483\n2015-01-23 12:00:00,18057\n2015-01-23 12:30:00,16855\n2015-01-23 13:00:00,16827\n2015-01-23 13:30:00,17900\n2015-01-23 14:00:00,18747\n2015-01-23 14:30:00,19493\n2015-01-23 15:00:00,19020\n2015-01-23 15:30:00,17169\n2015-01-23 16:00:00,15680\n2015-01-23 16:30:00,15126\n2015-01-23 17:00:00,17664\n2015-01-23 17:30:00,21065\n2015-01-23 18:00:00,23573\n2015-01-23 18:30:00,25063\n2015-01-23 19:00:00,26854\n2015-01-23 19:30:00,26037\n2015-01-23 20:00:00,24863\n2015-01-23 20:30:00,23793\n2015-01-23 21:00:00,23560\n2015-01-23 21:30:00,23904\n2015-01-23 22:00:00,25266\n2015-01-23 22:30:00,25284\n2015-01-23 23:00:00,25157\n2015-01-23 23:30:00,24597\n2015-01-24 00:00:00,24223\n2015-01-24 00:30:00,21761\n2015-01-24 01:00:00,20356\n2015-01-24 01:30:00,18221\n2015-01-24 02:00:00,14264\n2015-01-24 02:30:00,11852\n2015-01-24 03:00:00,10245\n2015-01-24 03:30:00,8895\n2015-01-24 04:00:00,7634\n2015-01-24 04:30:00,4822\n2015-01-24 05:00:00,3521\n2015-01-24 05:30:00,2971\n2015-01-24 06:00:00,3225\n2015-01-24 06:30:00,4324\n2015-01-24 07:00:00,4948\n2015-01-24 07:30:00,6401\n2015-01-24 08:00:00,7537\n2015-01-24 08:30:00,10085\n2015-01-24 09:00:00,11421\n2015-01-24 09:30:00,15063\n2015-01-24 10:00:00,14932\n2015-01-24 10:30:00,16512\n2015-01-24 11:00:00,16893\n2015-01-24 11:30:00,19945\n2015-01-24 12:00:00,19851\n2015-01-24 12:30:00,20385\n2015-01-24 13:00:00,20321\n2015-01-24 13:30:00,19563\n2015-01-24 14:00:00,18692\n2015-01-24 14:30:00,19016\n2015-01-24 15:00:00,19252\n2015-01-24 15:30:00,19325\n2015-01-24 16:00:00,19139\n2015-01-24 16:30:00,19092\n2015-01-24 17:00:00,19901\n2015-01-24 17:30:00,21433\n2015-01-24 18:00:00,22997\n2015-01-24 18:30:00,24210\n2015-01-24 19:00:00,26175\n2015-01-24 19:30:00,24935\n2015-01-24 20:00:00,21243\n2015-01-24 20:30:00,20206\n2015-01-24 21:00:00,20188\n2015-01-24 21:30:00,21588\n2015-01-24 22:00:00,24357\n2015-01-24 22:30:00,25009\n2015-01-24 23:00:00,25641\n2015-01-24 23:30:00,25928\n2015-01-25 00:00:00,25026\n2015-01-25 00:30:00,23773\n2015-01-25 01:00:00,22667\n2015-01-25 01:30:00,20864\n2015-01-25 02:00:00,19498\n2015-01-25 02:30:00,17494\n2015-01-25 03:00:00,15262\n2015-01-25 03:30:00,12727\n2015-01-25 04:00:00,10682\n2015-01-25 04:30:00,5804\n2015-01-25 05:00:00,3732\n2015-01-25 05:30:00,3050\n2015-01-25 06:00:00,2793\n2015-01-25 06:30:00,3690\n2015-01-25 07:00:00,4009\n2015-01-25 07:30:00,5014\n2015-01-25 08:00:00,5354\n2015-01-25 08:30:00,7694\n2015-01-25 09:00:00,9298\n2015-01-25 09:30:00,12036\n2015-01-25 10:00:00,13457\n2015-01-25 10:30:00,16776\n2015-01-25 11:00:00,16838\n2015-01-25 11:30:00,18681\n2015-01-25 12:00:00,19382\n2015-01-25 12:30:00,19841\n2015-01-25 13:00:00,19688\n2015-01-25 13:30:00,19900\n2015-01-25 14:00:00,19767\n2015-01-25 14:30:00,19114\n2015-01-25 15:00:00,18144\n2015-01-25 15:30:00,18343\n2015-01-25 16:00:00,17879\n2015-01-25 16:30:00,17910\n2015-01-25 17:00:00,17868\n2015-01-25 17:30:00,19079\n2015-01-25 18:00:00,19687\n2015-01-25 18:30:00,19227\n2015-01-25 19:00:00,17843\n2015-01-25 19:30:00,16231\n2015-01-25 20:00:00,14905\n2015-01-25 20:30:00,14598\n2015-01-25 21:00:00,13551\n2015-01-25 21:30:00,13933\n2015-01-25 22:00:00,12374\n2015-01-25 22:30:00,10625\n2015-01-25 23:00:00,9964\n2015-01-25 23:30:00,8190\n2015-01-26 00:00:00,6663\n2015-01-26 00:30:00,5151\n2015-01-26 01:00:00,4092\n2015-01-26 01:30:00,3207\n2015-01-26 02:00:00,2626\n2015-01-26 02:30:00,1994\n2015-01-26 03:00:00,1987\n2015-01-26 03:30:00,1912\n2015-01-26 04:00:00,2156\n2015-01-26 04:30:00,2175\n2015-01-26 05:00:00,2757\n2015-01-26 05:30:00,4689\n2015-01-26 06:00:00,6715\n2015-01-26 06:30:00,11577\n2015-01-26 07:00:00,13954\n2015-01-26 07:30:00,17717\n2015-01-26 08:00:00,18686\n2015-01-26 08:30:00,18923\n2015-01-26 09:00:00,17326\n2015-01-26 09:30:00,15926\n2015-01-26 10:00:00,13785\n2015-01-26 10:30:00,13905\n2015-01-26 11:00:00,13575\n2015-01-26 11:30:00,14094\n2015-01-26 12:00:00,14488\n2015-01-26 12:30:00,14428\n2015-01-26 13:00:00,14402\n2015-01-26 13:30:00,14747\n2015-01-26 14:00:00,13915\n2015-01-26 14:30:00,11432\n2015-01-26 15:00:00,9659\n2015-01-26 15:30:00,7681\n2015-01-26 16:00:00,6257\n2015-01-26 16:30:00,5520\n2015-01-26 17:00:00,5159\n2015-01-26 17:30:00,5283\n2015-01-26 18:00:00,5821\n2015-01-26 18:30:00,5586\n2015-01-26 19:00:00,4729\n2015-01-26 19:30:00,4402\n2015-01-26 20:00:00,3877\n2015-01-26 20:30:00,3384\n2015-01-26 21:00:00,3203\n2015-01-26 21:30:00,2611\n2015-01-26 22:00:00,1783\n2015-01-26 22:30:00,866\n2015-01-26 23:00:00,297\n2015-01-26 23:30:00,189\n2015-01-27 00:00:00,109\n2015-01-27 00:30:00,80\n2015-01-27 01:00:00,40\n2015-01-27 01:30:00,39\n2015-01-27 02:00:00,26\n2015-01-27 02:30:00,32\n2015-01-27 03:00:00,8\n2015-01-27 03:30:00,11\n2015-01-27 04:00:00,9\n2015-01-27 04:30:00,20\n2015-01-27 05:00:00,21\n2015-01-27 05:30:00,37\n2015-01-27 06:00:00,69\n2015-01-27 06:30:00,107\n2015-01-27 07:00:00,216\n2015-01-27 07:30:00,332\n2015-01-27 08:00:00,570\n2015-01-27 08:30:00,1049\n2015-01-27 09:00:00,1589\n2015-01-27 09:30:00,2285\n2015-01-27 10:00:00,2945\n2015-01-27 10:30:00,3544\n2015-01-27 11:00:00,3876\n2015-01-27 11:30:00,4535\n2015-01-27 12:00:00,4923\n2015-01-27 12:30:00,5157\n2015-01-27 13:00:00,5273\n2015-01-27 13:30:00,5584\n2015-01-27 14:00:00,5773\n2015-01-27 14:30:00,6569\n2015-01-27 15:00:00,7007\n2015-01-27 15:30:00,7400\n2015-01-27 16:00:00,7962\n2015-01-27 16:30:00,8760\n2015-01-27 17:00:00,9776\n2015-01-27 17:30:00,10863\n2015-01-27 18:00:00,12687\n2015-01-27 18:30:00,12541\n2015-01-27 19:00:00,11967\n2015-01-27 19:30:00,10813\n2015-01-27 20:00:00,10419\n2015-01-27 20:30:00,10132\n2015-01-27 21:00:00,10566\n2015-01-27 21:30:00,11073\n2015-01-27 22:00:00,10559\n2015-01-27 22:30:00,9121\n2015-01-27 23:00:00,8700\n2015-01-27 23:30:00,6884\n2015-01-28 00:00:00,5502\n2015-01-28 00:30:00,4001\n2015-01-28 01:00:00,3039\n2015-01-28 01:30:00,2431\n2015-01-28 02:00:00,2005\n2015-01-28 02:30:00,1661\n2015-01-28 03:00:00,1300\n2015-01-28 03:30:00,1279\n2015-01-28 04:00:00,1407\n2015-01-28 04:30:00,1353\n2015-01-28 05:00:00,1887\n2015-01-28 05:30:00,3714\n2015-01-28 06:00:00,6019\n2015-01-28 06:30:00,11208\n2015-01-28 07:00:00,14063\n2015-01-28 07:30:00,17572\n2015-01-28 08:00:00,18746\n2015-01-28 08:30:00,18397\n2015-01-28 09:00:00,17430\n2015-01-28 09:30:00,15997\n2015-01-28 10:00:00,13900\n2015-01-28 10:30:00,14138\n2015-01-28 11:00:00,13361\n2015-01-28 11:30:00,14156\n2015-01-28 12:00:00,14075\n2015-01-28 12:30:00,13887\n2015-01-28 13:00:00,13593\n2015-01-28 13:30:00,14093\n2015-01-28 14:00:00,14699\n2015-01-28 14:30:00,15372\n2015-01-28 15:00:00,16220\n2015-01-28 15:30:00,15107\n2015-01-28 16:00:00,14057\n2015-01-28 16:30:00,13802\n2015-01-28 17:00:00,15961\n2015-01-28 17:30:00,18422\n2015-01-28 18:00:00,21270\n2015-01-28 18:30:00,22262\n2015-01-28 19:00:00,22786\n2015-01-28 19:30:00,22169\n2015-01-28 20:00:00,21155\n2015-01-28 20:30:00,20120\n2015-01-28 21:00:00,20428\n2015-01-28 21:30:00,20309\n2015-01-28 22:00:00,20059\n2015-01-28 22:30:00,19055\n2015-01-28 23:00:00,15481\n2015-01-28 23:30:00,12535\n2015-01-29 00:00:00,10134\n2015-01-29 00:30:00,7568\n2015-01-29 01:00:00,5619\n2015-01-29 01:30:00,4342\n2015-01-29 02:00:00,3604\n2015-01-29 02:30:00,2822\n2015-01-29 03:00:00,2379\n2015-01-29 03:30:00,2121\n2015-01-29 04:00:00,2130\n2015-01-29 04:30:00,1968\n2015-01-29 05:00:00,2339\n2015-01-29 05:30:00,4306\n2015-01-29 06:00:00,6575\n2015-01-29 06:30:00,11896\n2015-01-29 07:00:00,15030\n2015-01-29 07:30:00,18687\n2015-01-29 08:00:00,19710\n2015-01-29 08:30:00,19585\n2015-01-29 09:00:00,18438\n2015-01-29 09:30:00,17398\n2015-01-29 10:00:00,16241\n2015-01-29 10:30:00,15905\n2015-01-29 11:00:00,14690\n2015-01-29 11:30:00,16203\n2015-01-29 12:00:00,16711\n2015-01-29 12:30:00,16013\n2015-01-29 13:00:00,15725\n2015-01-29 13:30:00,16432\n2015-01-29 14:00:00,17190\n2015-01-29 14:30:00,17571\n2015-01-29 15:00:00,18184\n2015-01-29 15:30:00,16484\n2015-01-29 16:00:00,14774\n2015-01-29 16:30:00,13800\n2015-01-29 17:00:00,15971\n2015-01-29 17:30:00,19384\n2015-01-29 18:00:00,21649\n2015-01-29 18:30:00,23102\n2015-01-29 19:00:00,23464\n2015-01-29 19:30:00,23343\n2015-01-29 20:00:00,23197\n2015-01-29 20:30:00,23120\n2015-01-29 21:00:00,23208\n2015-01-29 21:30:00,23188\n2015-01-29 22:00:00,22638\n2015-01-29 22:30:00,21501\n2015-01-29 23:00:00,20719\n2015-01-29 23:30:00,17877\n2015-01-30 00:00:00,14367\n2015-01-30 00:30:00,11118\n2015-01-30 01:00:00,8733\n2015-01-30 01:30:00,6954\n2015-01-30 02:00:00,5898\n2015-01-30 02:30:00,4541\n2015-01-30 03:00:00,3834\n2015-01-30 03:30:00,3143\n2015-01-30 04:00:00,3295\n2015-01-30 04:30:00,2652\n2015-01-30 05:00:00,2541\n2015-01-30 05:30:00,4585\n2015-01-30 06:00:00,6626\n2015-01-30 06:30:00,11854\n2015-01-30 07:00:00,15913\n2015-01-30 07:30:00,19574\n2015-01-30 08:00:00,20898\n2015-01-30 08:30:00,20859\n2015-01-30 09:00:00,19707\n2015-01-30 09:30:00,18495\n2015-01-30 10:00:00,17096\n2015-01-30 10:30:00,16561\n2015-01-30 11:00:00,16496\n2015-01-30 11:30:00,17310\n2015-01-30 12:00:00,17354\n2015-01-30 12:30:00,16305\n2015-01-30 13:00:00,16685\n2015-01-30 13:30:00,18077\n2015-01-30 14:00:00,18375\n2015-01-30 14:30:00,18633\n2015-01-30 15:00:00,18401\n2015-01-30 15:30:00,17079\n2015-01-30 16:00:00,15582\n2015-01-30 16:30:00,14719\n2015-01-30 17:00:00,17569\n2015-01-30 17:30:00,21013\n2015-01-30 18:00:00,23696\n2015-01-30 18:30:00,25758\n2015-01-30 19:00:00,27289\n2015-01-30 19:30:00,28107\n2015-01-30 20:00:00,27308\n2015-01-30 20:30:00,26570\n2015-01-30 21:00:00,25935\n2015-01-30 21:30:00,26432\n2015-01-30 22:00:00,26739\n2015-01-30 22:30:00,26874\n2015-01-30 23:00:00,26928\n2015-01-30 23:30:00,26000\n2015-01-31 00:00:00,25778\n2015-01-31 00:30:00,23304\n2015-01-31 01:00:00,21318\n2015-01-31 01:30:00,19024\n2015-01-31 02:00:00,17022\n2015-01-31 02:30:00,14733\n2015-01-31 03:00:00,12593\n2015-01-31 03:30:00,11048\n2015-01-31 04:00:00,9364\n2015-01-31 04:30:00,5209\n2015-01-31 05:00:00,3683\n2015-01-31 05:30:00,3329\n2015-01-31 06:00:00,3714\n2015-01-31 06:30:00,4531\n2015-01-31 07:00:00,4803\n2015-01-31 07:30:00,7049\n2015-01-31 08:00:00,8363\n2015-01-31 08:30:00,11899\n2015-01-31 09:00:00,13522\n2015-01-31 09:30:00,18164\n2015-01-31 10:00:00,17645\n2015-01-31 10:30:00,20056\n2015-01-31 11:00:00,20270\n2015-01-31 11:30:00,22865\n2015-01-31 12:00:00,22951\n2015-01-31 12:30:00,23387\n2015-01-31 13:00:00,23069\n2015-01-31 13:30:00,23298\n2015-01-31 14:00:00,21817\n2015-01-31 14:30:00,21565\n2015-01-31 15:00:00,21729\n2015-01-31 15:30:00,22838\n2015-01-31 16:00:00,21068\n2015-01-31 16:30:00,19920\n2015-01-31 17:00:00,20715\n2015-01-31 17:30:00,23595\n2015-01-31 18:00:00,26044\n2015-01-31 18:30:00,27286\n2015-01-31 19:00:00,28804\n2015-01-31 19:30:00,27773\n2015-01-31 20:00:00,24985\n2015-01-31 20:30:00,23291\n2015-01-31 21:00:00,23719\n2015-01-31 21:30:00,24670\n2015-01-31 22:00:00,25721\n2015-01-31 22:30:00,27309\n2015-01-31 23:00:00,26591\n2015-01-31 23:30:00,26288"
  },
  {
    "path": "workspace/anomaly_detector/datasets/selected/seasonal/occupancy_6005.csv",
    "content": "timestamp,value\n2015-09-01 13:45:00,3.06\n2015-09-01 13:50:00,6.44\n2015-09-01 13:55:00,5.17\n2015-09-01 14:00:00,3.83\n2015-09-01 14:05:00,4.5\n2015-09-01 14:20:00,2.94\n2015-09-01 14:25:00,2.28\n2015-09-01 14:35:00,1.67\n2015-09-01 14:40:00,18.83\n2015-09-01 14:45:00,12\n2015-09-01 14:50:00,13.11\n2015-09-01 14:55:00,12.72\n2015-09-01 15:20:00,1.67\n2015-09-01 17:15:00,12.78\n2015-09-01 17:25:00,7.5\n2015-09-01 17:30:00,1.94\n2015-09-01 17:35:00,3.72\n2015-09-01 17:45:00,2.72\n2015-09-01 17:55:00,3.83\n2015-09-01 18:10:00,3.83\n2015-09-01 18:45:00,1.83\n2015-09-01 18:50:00,2.56\n2015-09-01 19:00:00,2.28\n2015-09-01 19:05:00,2.28\n2015-09-01 19:10:00,7.89\n2015-09-01 19:20:00,2.28\n2015-09-01 19:25:00,2.06\n2015-09-01 19:30:00,1.17\n2015-09-01 19:40:00,1.17\n2015-09-01 19:55:00,1.56\n2015-09-01 20:00:00,3.61\n2015-09-01 20:05:00,2.72\n2015-09-01 20:10:00,1.17\n2015-09-01 20:20:00,3.44\n2015-09-01 20:25:00,3.5\n2015-09-01 20:30:00,4.5\n2015-09-01 20:45:00,1.44\n2015-09-01 20:55:00,5.44\n2015-09-01 21:05:00,1.67\n2015-09-01 21:25:00,5.17\n2015-09-01 21:40:00,2.06\n2015-09-01 22:30:00,2.56\n2015-09-01 22:35:00,2.94\n2015-09-01 22:40:00,1.44\n2015-09-01 22:45:00,2.94\n2015-09-01 23:01:00,1.83\n2015-09-01 23:05:00,1.94\n2015-09-01 23:10:00,2.17\n2015-09-01 23:20:00,1\n2015-09-01 23:40:00,0.89\n2015-09-02 00:00:00,1.39\n2015-09-02 00:05:00,0.28\n2015-09-02 00:15:00,0.39\n2015-09-02 00:20:00,1\n2015-09-02 00:35:00,1\n2015-09-02 01:00:00,0.5\n2015-09-02 01:35:00,0.22\n2015-09-02 02:10:00,5\n2015-09-02 02:25:00,0.5\n2015-09-02 02:40:00,0\n2015-09-02 03:05:00,0.5\n2015-09-02 03:10:00,0\n2015-09-02 03:35:00,1.67\n2015-09-02 04:15:00,2.17\n2015-09-02 04:20:00,0.5\n2015-09-02 04:25:00,1.44\n2015-09-02 04:30:00,1.39\n2015-09-02 04:35:00,3.5\n2015-09-02 04:45:00,2.56\n2015-09-02 04:50:00,2.56\n2015-09-02 05:00:00,6.06\n2015-09-02 05:05:00,2.06\n2015-09-02 05:15:00,4.39\n2015-09-02 05:20:00,5.44\n2015-09-02 05:25:00,12.39\n2015-09-02 05:30:00,5.83\n2015-09-02 05:35:00,4.5\n2015-09-02 05:45:00,9.28\n2015-09-02 05:50:00,5.39\n2015-09-02 05:55:00,9.17\n2015-09-02 06:00:00,7.5\n2015-09-02 06:05:00,10.33\n2015-09-02 06:10:00,10.44\n2015-09-02 06:15:00,10.94\n2015-09-02 06:20:00,8.89\n2015-09-02 06:25:00,15.61\n2015-09-02 06:30:00,11.89\n2015-09-02 06:35:00,17\n2015-09-02 06:40:00,7.83\n2015-09-02 06:45:00,11.11\n2015-09-02 06:50:00,14.33\n2015-09-02 06:55:00,10.83\n2015-09-02 07:00:00,8.11\n2015-09-02 07:05:00,14.83\n2015-09-02 07:10:00,13.67\n2015-09-02 07:15:00,16.5\n2015-09-02 07:20:00,12.28\n2015-09-02 07:25:00,11.06\n2015-09-02 07:30:00,7.61\n2015-09-02 07:35:00,11.44\n2015-09-02 07:40:00,6.33\n2015-09-02 07:45:00,13.89\n2015-09-02 07:50:00,9.44\n2015-09-02 07:55:00,2.72\n2015-09-02 08:00:00,6.17\n2015-09-02 08:05:00,11.83\n2015-09-02 08:10:00,8.5\n2015-09-02 08:15:00,6.06\n2015-09-02 08:20:00,7.5\n2015-09-02 08:30:00,9.78\n2015-09-02 08:35:00,11.89\n2015-09-02 08:45:00,9.28\n2015-09-02 08:50:00,6.44\n2015-09-02 08:55:00,4.28\n2015-09-02 09:00:00,6.83\n2015-09-02 09:05:00,8\n2015-09-02 09:10:00,9\n2015-09-02 09:20:00,1.06\n2015-09-02 09:30:00,4.11\n2015-09-02 09:35:00,8.11\n2015-09-02 09:40:00,5.06\n2015-09-02 09:50:00,4.61\n2015-09-02 09:55:00,1\n2015-09-02 10:00:00,1.39\n2015-09-02 10:10:00,4.22\n2015-09-02 10:15:00,3.33\n2015-09-02 10:20:00,4.67\n2015-09-02 10:25:00,3.33\n2015-09-02 10:30:00,2.94\n2015-09-02 10:35:00,3.83\n2015-09-02 10:40:00,1.78\n2015-09-02 10:45:00,3.89\n2015-09-02 10:50:00,3.5\n2015-09-02 11:00:00,6.67\n2015-09-02 11:15:00,2.28\n2015-09-02 11:20:00,5.39\n2015-09-02 11:25:00,4.11\n2015-09-02 11:30:00,2.17\n2015-09-02 11:35:00,3.33\n2015-09-02 12:00:00,1.28\n2015-09-02 12:05:00,2.28\n2015-09-02 12:10:00,4.28\n2015-09-02 12:15:00,7.06\n2015-09-02 12:25:00,4.67\n2015-09-02 12:35:00,4.5\n2015-09-02 12:40:00,4.89\n2015-09-02 12:45:00,7.11\n2015-09-02 12:50:00,2.33\n2015-09-02 12:55:00,3.06\n2015-09-02 13:05:00,1.56\n2015-09-02 13:10:00,3.33\n2015-09-02 13:15:00,4.22\n2015-09-02 13:20:00,7.89\n2015-09-02 13:25:00,4.28\n2015-09-02 13:30:00,3.22\n2015-09-02 13:35:00,5.06\n2015-09-02 13:40:00,1\n2015-09-02 13:45:00,4.89\n2015-09-02 13:50:00,2.17\n2015-09-02 13:55:00,6.28\n2015-09-02 14:05:00,1\n2015-09-02 14:15:00,6.28\n2015-09-02 14:20:00,6.72\n2015-09-02 14:25:00,5.94\n2015-09-02 14:30:00,4.39\n2015-09-02 14:35:00,5.06\n2015-09-02 14:50:00,5.83\n2015-09-02 14:55:00,3.72\n2015-09-02 15:05:00,3.33\n2015-09-02 15:10:00,4.67\n2015-09-02 15:15:00,4.61\n2015-09-02 15:20:00,4.28\n2015-09-02 15:25:00,2.44\n2015-09-02 15:30:00,3.11\n2015-09-02 15:35:00,3.11\n2015-09-02 15:40:00,2.83\n2015-09-02 15:45:00,6.17\n2015-09-02 15:50:00,5\n2015-09-02 16:05:00,1.44\n2015-09-02 16:15:00,2.17\n2015-09-02 16:20:00,3.44\n2015-09-02 16:25:00,6.83\n2015-09-02 16:30:00,7.89\n2015-09-02 16:50:00,9.39\n2015-09-02 16:55:00,7.33\n2015-09-02 17:00:00,5.44\n2015-09-02 17:10:00,8.5\n2015-09-02 17:20:00,7.83\n2015-09-02 17:35:00,4\n2015-09-02 17:45:00,4.78\n2015-09-02 18:05:00,2.72\n2015-09-02 18:10:00,5.39\n2015-09-02 18:15:00,2.56\n2015-09-02 18:20:00,3.83\n2015-09-02 18:30:00,4.67\n2015-09-02 18:35:00,4.61\n2015-09-02 18:45:00,0.78\n2015-09-02 18:50:00,1.56\n2015-09-02 19:00:00,4\n2015-09-02 19:05:00,4.11\n2015-09-02 19:10:00,4.39\n2015-09-02 19:15:00,2.67\n2015-09-02 19:21:00,4.67\n2015-09-02 19:26:00,4.22\n2015-09-02 19:46:00,4.89\n2015-09-02 19:56:00,1.17\n2015-09-02 20:11:00,2.33\n2015-09-02 20:46:00,4.89\n2015-09-02 20:56:00,3.89\n2015-09-02 21:00:00,4.61\n2015-09-02 21:16:00,3.72\n2015-09-02 21:21:00,3.5\n2015-09-02 21:31:00,1.17\n2015-09-02 21:36:00,2.67\n2015-09-02 21:46:00,4.67\n2015-09-02 21:51:00,2.28\n2015-09-02 22:11:00,1.28\n2015-09-02 22:21:00,3.44\n2015-09-02 22:31:00,2.67\n2015-09-02 22:36:00,2.56\n2015-09-02 22:41:00,0.78\n2015-09-02 22:51:00,1.56\n2015-09-02 23:51:00,2.94\n2015-09-03 00:01:00,1.83\n2015-09-03 00:11:00,0\n2015-09-03 00:21:00,2.33\n2015-09-03 00:36:00,1.06\n2015-09-03 00:41:00,0.22\n2015-09-03 00:51:00,0.28\n2015-09-03 01:21:00,1\n2015-09-03 01:26:00,1.28\n2015-09-03 01:51:00,1.44\n2015-09-03 01:56:00,0.5\n2015-09-03 02:01:00,0.61\n2015-09-03 02:11:00,0.28\n2015-09-03 02:16:00,1.78\n2015-09-03 02:21:00,0.28\n2015-09-03 03:11:00,1.94\n2015-09-03 03:21:00,1\n2015-09-03 03:26:00,1.17\n2015-09-03 03:46:00,1.94\n2015-09-03 03:51:00,2.44\n2015-09-03 04:06:00,0.22\n2015-09-03 04:11:00,1.67\n2015-09-03 04:16:00,1.83\n2015-09-03 04:36:00,0.39\n2015-09-03 04:56:00,1.56\n2015-09-03 05:01:00,4.78\n2015-09-03 05:06:00,1.17\n2015-09-03 05:11:00,10.94\n2015-09-03 05:21:00,1.56\n2015-09-03 05:26:00,3.89\n2015-09-03 05:31:00,5.39\n2015-09-03 05:36:00,4.11\n2015-09-03 05:41:00,3.61\n2015-09-03 05:46:00,2.56\n2015-09-03 05:51:00,7.44\n2015-09-03 05:56:00,9.94\n2015-09-03 06:01:00,4.61\n2015-09-03 06:06:00,12.28\n2015-09-03 06:11:00,10.56\n2015-09-03 06:16:00,21.17\n2015-09-03 06:21:00,15.33\n2015-09-03 06:26:00,12.11\n2015-09-03 06:36:00,11.33\n2015-09-03 06:41:00,13.94\n2015-09-03 06:46:00,14.78\n2015-09-03 06:51:00,11.44\n2015-09-03 06:56:00,13.89\n2015-09-03 07:01:00,9.39\n2015-09-03 07:06:00,12\n2015-09-03 07:11:00,17.89\n2015-09-03 07:16:00,11.89\n2015-09-03 07:21:00,10.17\n2015-09-03 07:26:00,11.11\n2015-09-03 07:31:00,21.11\n2015-09-03 07:36:00,9.28\n2015-09-03 07:41:00,5.28\n2015-09-03 07:46:00,10.06\n2015-09-03 07:51:00,10.72\n2015-09-03 07:56:00,5.83\n2015-09-03 08:01:00,6.44\n2015-09-03 08:11:00,4.11\n2015-09-03 08:16:00,10.28\n2015-09-03 08:21:00,10.44\n2015-09-03 08:26:00,9.28\n2015-09-03 08:31:00,11.22\n2015-09-03 08:36:00,7.44\n2015-09-03 08:41:00,5.06\n2015-09-03 08:46:00,15.33\n2015-09-03 08:56:00,8\n2015-09-03 09:01:00,3.83\n2015-09-03 09:06:00,14.28\n2015-09-03 09:16:00,6.83\n2015-09-03 09:21:00,5.39\n2015-09-03 09:26:00,8.39\n2015-09-03 09:31:00,6.72\n2015-09-03 09:36:00,7.5\n2015-09-03 09:41:00,7.11\n2015-09-03 09:56:00,5.78\n2015-09-03 10:01:00,5.28\n2015-09-03 10:06:00,6.94\n2015-09-03 10:11:00,5.06\n2015-09-03 10:16:00,3.06\n2015-09-03 10:26:00,2.94\n2015-09-03 10:31:00,4.5\n2015-09-03 10:36:00,4.89\n2015-09-03 10:41:00,3.5\n2015-09-03 10:46:00,4.61\n2015-09-03 10:51:00,1.67\n2015-09-03 11:01:00,5.17\n2015-09-03 11:06:00,3.72\n2015-09-03 11:16:00,5.56\n2015-09-03 11:21:00,6.28\n2015-09-03 11:26:00,4.61\n2015-09-03 11:36:00,7.06\n2015-09-03 11:46:00,3.5\n2015-09-03 12:01:00,3.83\n2015-09-03 12:06:00,1.67\n2015-09-03 12:11:00,3.72\n2015-09-03 12:16:00,2.83\n2015-09-03 12:21:00,2.83\n2015-09-03 12:31:00,3.89\n2015-09-03 12:41:00,7.33\n2015-09-03 12:46:00,3.61\n2015-09-03 12:51:00,2.67\n2015-09-03 12:56:00,4.11\n2015-09-03 13:01:00,4.61\n2015-09-03 13:06:00,0.78\n2015-09-03 13:11:00,5.44\n2015-09-03 13:21:00,1\n2015-09-03 13:26:00,1.78\n2015-09-03 13:31:00,8.5\n2015-09-03 13:41:00,5.56\n2015-09-03 13:46:00,9.83\n2015-09-03 14:01:00,6.17\n2015-09-03 14:06:00,2.28\n2015-09-03 14:11:00,8.28\n2015-09-03 14:16:00,7.72\n2015-09-03 14:21:00,4.89\n2015-09-03 14:26:00,6.94\n2015-09-03 14:31:00,5.39\n2015-09-03 14:41:00,8.78\n2015-09-03 14:46:00,7.5\n2015-09-03 14:56:00,7.61\n2015-09-03 15:01:00,6.72\n2015-09-03 15:06:00,2.17\n2015-09-03 15:11:00,5.67\n2015-09-03 15:16:00,7.22\n2015-09-03 15:21:00,5\n2015-09-03 15:26:00,5.17\n2015-09-03 15:31:00,9.94\n2015-09-03 15:36:00,10.72\n2015-09-03 15:41:00,7.44\n2015-09-03 15:46:00,9.83\n2015-09-03 15:51:00,3.89\n2015-09-03 15:56:00,4.11\n2015-09-03 16:06:00,4\n2015-09-03 16:21:00,7.22\n2015-09-03 16:31:00,3.44\n2015-09-03 16:36:00,7.33\n2015-09-03 16:41:00,9\n2015-09-03 16:46:00,11.44\n2015-09-03 16:56:00,10.17\n2015-09-03 17:01:00,8.67\n2015-09-03 17:06:00,9.83\n2015-09-03 17:11:00,4.5\n2015-09-03 17:16:00,9.83\n2015-09-03 17:21:00,3.83\n2015-09-03 17:26:00,7.22\n2015-09-03 17:36:00,5.78\n2015-09-03 17:41:00,10.28\n2015-09-03 17:46:00,3.89\n2015-09-03 17:51:00,5.28\n2015-09-03 17:56:00,3.5\n2015-09-03 18:01:00,7.5\n2015-09-03 18:11:00,7.72\n2015-09-03 18:16:00,2.94\n2015-09-03 18:21:00,3.33\n2015-09-03 18:31:00,3.61\n2015-09-03 18:36:00,2.83\n2015-09-03 18:41:00,7.06\n2015-09-03 18:51:00,3.06\n2015-09-03 19:06:00,3.33\n2015-09-03 19:11:00,6.67\n2015-09-03 19:21:00,3.5\n2015-09-03 19:26:00,3.44\n2015-09-03 20:02:00,1.67\n2015-09-03 20:12:00,3.11\n2015-09-03 20:17:00,7.22\n2015-09-03 20:22:00,3.06\n2015-09-03 20:27:00,5.56\n2015-09-03 20:57:00,1.67\n2015-09-03 21:02:00,4\n2015-09-03 21:32:00,0.67\n2015-09-03 21:42:00,4.89\n2015-09-03 22:02:00,0.39\n2015-09-03 22:22:00,1.56\n2015-09-03 22:27:00,2.67\n2015-09-03 23:22:00,3.22\n2015-09-03 23:27:00,4.11\n2015-09-03 23:32:00,3.11\n2015-09-03 23:42:00,0.89\n2015-09-03 23:57:00,5.06\n2015-09-04 00:02:00,2.56\n2015-09-04 00:07:00,0.22\n2015-09-04 00:22:00,0.61\n2015-09-04 00:27:00,1\n2015-09-04 00:42:00,0.28\n2015-09-04 01:07:00,1.28\n2015-09-04 01:27:00,1.78\n2015-09-04 02:27:00,1.44\n2015-09-04 02:52:00,1.17\n2015-09-04 02:57:00,1.44\n2015-09-04 03:12:00,1.39\n2015-09-04 03:27:00,2.56\n2015-09-04 04:02:00,1.78\n2015-09-04 04:22:00,1.39\n2015-09-04 04:37:00,4.39\n2015-09-04 04:52:00,0.67\n2015-09-04 05:12:00,5.06\n2015-09-04 05:17:00,3.44\n2015-09-04 05:22:00,3.61\n2015-09-04 05:32:00,4.67\n2015-09-04 05:37:00,3.61\n2015-09-04 05:42:00,8.78\n2015-09-04 05:47:00,6.17\n2015-09-04 05:52:00,2.56\n2015-09-04 05:57:00,5.67\n2015-09-04 06:07:00,5\n2015-09-04 06:12:00,6.56\n2015-09-04 06:17:00,8.39\n2015-09-04 06:22:00,6.83\n2015-09-04 06:27:00,10.67\n2015-09-04 06:32:00,8.28\n2015-09-04 06:37:00,9.06\n2015-09-04 06:42:00,8.78\n2015-09-04 06:47:00,5.83\n2015-09-04 06:52:00,14.28\n2015-09-04 06:57:00,15.56\n2015-09-04 07:02:00,5.67\n2015-09-04 07:07:00,4.61\n2015-09-04 07:12:00,9.06\n2015-09-04 07:22:00,9.39\n2015-09-04 07:27:00,12.22\n2015-09-04 07:32:00,8.5\n2015-09-04 07:37:00,8.67\n2015-09-04 07:47:00,6.56\n2015-09-04 07:52:00,6.17\n2015-09-04 07:57:00,8.89\n2015-09-04 08:02:00,7.72\n2015-09-04 08:07:00,12.11\n2015-09-04 08:12:00,7.22\n2015-09-04 08:17:00,9.28\n2015-09-04 08:22:00,10.94\n2015-09-04 08:27:00,5.17\n2015-09-04 08:32:00,6.83\n2015-09-04 08:37:00,5.78\n2015-09-04 08:52:00,7.89\n2015-09-04 08:57:00,2.33\n2015-09-04 09:12:00,7.06\n2015-09-04 09:17:00,8\n2015-09-04 09:32:00,2.94\n2015-09-04 09:42:00,2.17\n2015-09-04 09:47:00,6.17\n2015-09-04 09:52:00,8.22\n2015-09-04 09:57:00,4\n2015-09-04 10:12:00,3.89\n2015-09-04 10:17:00,8.22\n2015-09-04 10:22:00,4.78\n2015-09-04 10:27:00,3.83\n2015-09-04 10:32:00,6.17\n2015-09-04 10:37:00,4.11\n2015-09-04 10:42:00,2.83\n2015-09-04 10:47:00,5.56\n2015-09-04 10:57:00,3.33\n2015-09-04 11:02:00,8.61\n2015-09-04 11:07:00,4.5\n2015-09-04 11:17:00,5.94\n2015-09-04 11:22:00,9.39\n2015-09-04 11:27:00,3.11\n2015-09-04 11:32:00,6.72\n2015-09-04 11:37:00,4.61\n2015-09-04 11:42:00,5.67\n2015-09-04 11:47:00,4.89\n2015-09-04 11:52:00,5.78\n2015-09-04 11:57:00,7.5\n2015-09-04 12:12:00,3.72\n2015-09-04 12:27:00,2.33\n2015-09-04 12:32:00,5.06\n2015-09-04 12:37:00,6.44\n2015-09-04 12:42:00,2.44\n2015-09-04 12:52:00,6.33\n2015-09-04 12:57:00,9.78\n2015-09-04 13:02:00,2.17\n2015-09-04 13:12:00,6.67\n2015-09-04 13:17:00,6.83\n2015-09-04 13:27:00,2.06\n2015-09-04 13:37:00,8.22\n2015-09-04 13:47:00,7.61\n2015-09-04 13:52:00,5.56\n2015-09-04 13:57:00,4.61\n2015-09-04 14:02:00,3.11\n2015-09-04 14:07:00,6.44\n2015-09-04 14:12:00,4.11\n2015-09-04 14:17:00,11.44\n2015-09-04 14:22:00,7.22\n2015-09-04 14:27:00,8.28\n2015-09-04 14:32:00,3.11\n2015-09-04 14:37:00,3.22\n2015-09-04 14:42:00,4.39\n2015-09-04 14:47:00,8.67\n2015-09-04 14:52:00,2.33\n2015-09-04 15:02:00,3.61\n2015-09-04 15:17:00,3.5\n2015-09-04 15:22:00,6.17\n2015-09-04 15:32:00,6.44\n2015-09-04 15:42:00,3.89\n2015-09-04 15:47:00,5.83\n2015-09-04 15:52:00,6.67\n2015-09-04 16:02:00,6.83\n2015-09-04 16:12:00,3.61\n2015-09-04 16:17:00,4.39\n2015-09-04 16:27:00,3.72\n2015-09-04 16:32:00,5.28\n2015-09-04 16:42:00,5.28\n2015-09-04 16:47:00,4.28\n2015-09-04 16:52:00,5\n2015-09-04 16:57:00,7.06\n2015-09-04 17:02:00,4.61\n2015-09-04 17:07:00,5.39\n2015-09-04 17:12:00,14.44\n2015-09-04 17:17:00,7.61\n2015-09-04 17:22:00,11.5\n2015-09-04 17:27:00,6.33\n2015-09-04 17:32:00,6.44\n2015-09-04 17:37:00,6.06\n2015-09-04 17:42:00,6.33\n2015-09-04 17:47:00,3.61\n2015-09-04 18:02:00,5\n2015-09-04 18:07:00,5.56\n2015-09-04 18:12:00,2.72\n2015-09-04 18:17:00,6.33\n2015-09-04 18:22:00,4.22\n2015-09-04 18:27:00,4.11\n2015-09-04 18:32:00,4.78\n2015-09-04 18:37:00,7.5\n2015-09-04 18:42:00,13.28\n2015-09-04 18:47:00,7.22\n2015-09-04 18:52:00,10.06\n2015-09-04 18:57:00,2.44\n2015-09-04 19:02:00,3.83\n2015-09-04 19:07:00,2.33\n2015-09-04 19:12:00,4.28\n2015-09-04 19:22:00,2.06\n2015-09-04 19:27:00,1.39\n2015-09-04 19:32:00,4.22\n2015-09-04 19:42:00,2.33\n2015-09-04 19:47:00,1.56\n2015-09-04 19:57:00,5.67\n2015-09-04 20:02:00,4\n2015-09-04 20:12:00,3.33\n2015-09-04 20:17:00,4.28\n2015-09-04 20:23:00,2.17\n2015-09-04 20:28:00,4.61\n2015-09-04 20:33:00,3.33\n2015-09-04 20:38:00,6.28\n2015-09-04 20:48:00,1.78\n2015-09-04 20:53:00,3.5\n2015-09-04 21:03:00,3.22\n2015-09-04 21:13:00,3.44\n2015-09-04 21:18:00,5.17\n2015-09-04 21:33:00,2.72\n2015-09-04 21:38:00,4.22\n2015-09-04 21:53:00,2.83\n2015-09-04 22:08:00,0.89\n2015-09-04 22:13:00,1.83\n2015-09-04 22:23:00,3.72\n2015-09-04 22:34:00,3.61\n2015-09-04 22:41:00,0.78\n2015-09-08 10:44:00,3.61\n2015-09-08 10:49:00,1.44\n2015-09-08 10:59:00,4.28\n2015-09-08 11:04:00,6.28\n2015-09-08 11:09:00,4.61\n2015-09-08 11:14:00,5.28\n2015-09-08 11:19:00,2.06\n2015-09-08 11:29:00,7.5\n2015-09-08 11:34:00,8.39\n2015-09-08 11:39:00,0.67\n2015-09-08 11:49:00,2.94\n2015-09-08 11:59:00,1.67\n2015-09-08 12:14:00,5.44\n2015-09-08 12:19:00,3.72\n2015-09-08 12:24:00,3.5\n2015-09-08 12:27:00,3.11\n2015-09-08 12:32:00,5.78\n2015-09-08 12:36:00,4.67\n2015-09-08 12:46:00,9\n2015-09-08 12:51:00,6.72\n2015-09-08 12:56:00,1\n2015-09-08 13:01:00,5.17\n2015-09-08 13:06:00,8.89\n2015-09-08 13:16:00,6.06\n2015-09-08 13:26:00,1.39\n2015-09-08 13:36:00,2.44\n2015-09-08 13:41:00,3.44\n2015-09-08 13:46:00,6.06\n2015-09-08 13:51:00,1.78\n2015-09-08 13:56:00,3.89\n2015-09-08 14:00:00,5\n2015-09-08 14:06:00,5\n2015-09-08 14:11:00,10.28\n2015-09-08 14:21:00,1.17\n2015-09-08 14:31:00,4.67\n2015-09-08 14:36:00,5\n2015-09-08 14:41:00,5.39\n2015-09-08 14:51:00,1.67\n2015-09-08 14:56:00,4.39\n2015-09-08 15:01:00,4.22\n2015-09-08 15:06:00,4.5\n2015-09-08 15:11:00,7.89\n2015-09-08 15:16:00,4.28\n2015-09-08 15:26:00,5.06\n2015-09-08 15:29:00,2.72\n2015-09-08 15:41:00,5.56\n2015-09-08 16:15:00,6.83\n2015-09-08 16:31:00,2.83\n2015-09-08 16:36:00,3.44\n2015-09-08 16:41:00,2.06\n2015-09-08 16:46:00,7.06\n2015-09-08 16:56:00,1.83\n2015-09-08 17:06:00,7.72\n2015-09-08 17:11:00,6.94\n2015-09-08 17:21:00,5.28\n2015-09-08 17:26:00,3.5\n2015-09-08 17:31:00,5.83\n2015-09-08 17:36:00,8.22\n2015-09-08 17:46:00,6.33\n2015-09-08 17:51:00,4.11\n2015-09-08 17:56:00,5\n2015-09-08 18:26:00,1.78\n2015-09-08 18:31:00,7.89\n2015-09-08 18:36:00,4.78\n2015-09-08 18:41:00,2.72\n2015-09-08 18:46:00,1\n2015-09-08 18:56:00,1.17\n2015-09-08 19:01:00,5.56\n2015-09-08 19:06:00,1.28\n2015-09-08 19:16:00,7.44\n2015-09-08 19:26:00,2.44\n2015-09-08 19:36:00,2.67\n2015-09-08 19:41:00,4.39\n2015-09-08 19:46:00,1.44\n2015-09-08 19:51:00,1.56\n2015-09-08 20:06:00,2.72\n2015-09-08 20:11:00,2.67\n2015-09-08 20:26:00,1.56\n2015-09-08 20:36:00,2.94\n2015-09-08 20:41:00,0.67\n2015-09-08 20:46:00,1.44\n2015-09-08 20:56:00,0.89\n2015-09-08 21:06:00,1.78\n2015-09-08 21:11:00,1.56\n2015-09-08 21:16:00,0.89\n2015-09-08 21:21:00,2.33\n2015-09-08 21:46:00,0.22\n2015-09-08 21:51:00,1.39\n2015-09-08 21:56:00,0.5\n2015-09-08 22:06:00,1.06\n2015-09-08 22:12:00,0.67\n2015-09-08 22:26:00,2.56\n2015-09-08 22:36:00,1.17\n2015-09-08 22:51:00,0.28\n2015-09-08 22:56:00,3.33\n2015-09-08 23:56:00,2.94\n2015-09-09 00:26:00,1.67\n2015-09-09 01:11:00,1.67\n2015-09-09 01:51:00,0.61\n2015-09-09 03:11:00,0.78\n2015-09-09 06:04:00,12.28\n2015-09-09 07:34:00,8.89\n2015-09-09 09:20:00,5.06\n2015-09-09 09:48:00,2.06\n2015-09-09 09:53:00,6.44\n2015-09-09 09:58:00,2.44\n2015-09-09 10:03:00,4.67\n2015-09-09 10:08:00,4.61\n2015-09-09 10:18:00,5\n2015-09-09 10:23:00,9.67\n2015-09-09 10:33:00,4.67\n2015-09-09 10:43:00,4.5\n2015-09-09 10:53:00,3.83\n2015-09-09 10:58:00,4.67\n2015-09-09 11:08:00,5.39\n2015-09-09 11:18:00,2.94\n2015-09-09 11:23:00,3.06\n2015-09-09 11:38:00,3.22\n2015-09-09 11:43:00,2.94\n2015-09-09 11:48:00,5.56\n2015-09-09 11:58:00,4.89\n2015-09-09 12:13:00,6.06\n2015-09-09 12:23:00,2.56\n2015-09-09 12:28:00,2.17\n2015-09-09 12:43:00,3.06\n2015-09-09 12:53:00,1.06\n2015-09-09 12:58:00,5.17\n2015-09-09 13:03:00,6.56\n2015-09-09 13:13:00,1.44\n2015-09-09 13:18:00,0.22\n2015-09-09 13:23:00,1.67\n2015-09-09 13:38:00,6.28\n2015-09-09 13:48:00,2.67\n2015-09-09 13:53:00,4.89\n2015-09-09 14:08:00,2.06\n2015-09-09 14:13:00,7.11\n2015-09-09 14:18:00,2.06\n2015-09-09 14:23:00,7.83\n2015-09-09 14:33:00,3.5\n2015-09-09 14:43:00,4.5\n2015-09-09 15:03:00,3.06\n2015-09-09 15:08:00,3.11\n2015-09-09 15:13:00,11.06\n2015-09-09 15:18:00,5.78\n2015-09-09 15:23:00,6.56\n2015-09-09 15:28:00,2.28\n2015-09-09 15:33:00,7.22\n2015-09-09 15:43:00,4.78\n2015-09-09 15:48:00,5.56\n2015-09-09 15:53:00,6.44\n2015-09-09 15:58:00,3.44\n2015-09-09 16:03:00,1.56\n2015-09-09 16:08:00,5.39\n2015-09-09 16:13:00,10.56\n2015-09-09 16:23:00,8.5\n2015-09-09 16:28:00,3.5\n2015-09-09 16:38:00,6.17\n2015-09-09 16:43:00,3.44\n2015-09-09 16:48:00,5\n2015-09-09 16:53:00,7.61\n2015-09-09 16:58:00,3.83\n2015-09-09 17:08:00,7.11\n2015-09-09 17:13:00,5\n2015-09-09 17:18:00,3.44\n2015-09-09 17:23:00,7.22\n2015-09-09 17:33:00,4.5\n2015-09-09 17:48:00,3.61\n2015-09-09 17:58:00,1.94\n2015-09-09 18:03:00,2.56\n2015-09-09 18:08:00,2.17\n2015-09-09 18:18:00,3.22\n2015-09-09 18:23:00,4.39\n2015-09-09 18:28:00,1.17\n2015-09-09 18:43:00,4.5\n2015-09-09 18:48:00,1.56\n2015-09-09 18:53:00,1.28\n2015-09-09 19:03:00,2.56\n2015-09-09 19:18:00,4.89\n2015-09-09 19:33:00,4\n2015-09-09 19:38:00,3.22\n2015-09-09 19:43:00,2.06\n2015-09-09 19:48:00,0.39\n2015-09-09 19:58:00,1.67\n2015-09-09 20:03:00,2.94\n2015-09-09 20:08:00,4.11\n2015-09-09 20:13:00,7.22\n2015-09-09 20:18:00,0.61\n2015-09-09 20:33:00,2.44\n2015-09-09 20:38:00,1.44\n2015-09-09 20:48:00,0.61\n2015-09-09 20:58:00,1.56\n2015-09-09 21:03:00,4\n2015-09-09 21:08:00,1.06\n2015-09-09 21:13:00,0.78\n2015-09-09 21:18:00,1.67\n2015-09-09 21:23:00,7.06\n2015-09-09 21:33:00,1.94\n2015-09-09 21:38:00,3.11\n2015-09-09 21:43:00,2.94\n2015-09-09 21:48:00,0.78\n2015-09-09 22:03:00,0.61\n2015-09-09 22:08:00,1\n2015-09-09 22:13:00,0.78\n2015-09-09 22:23:00,3.83\n2015-09-09 22:28:00,1.28\n2015-09-09 22:33:00,0.67\n2015-09-09 22:38:00,1.06\n2015-09-09 22:41:00,8.28\n2015-09-09 22:46:00,2.83\n2015-09-10 00:08:00,0.39\n2015-09-10 00:23:00,3.61\n2015-09-10 00:38:00,1.39\n2015-09-10 00:53:00,0.5\n2015-09-10 00:58:00,1.67\n2015-09-10 01:03:00,1.06\n2015-09-10 01:08:00,0.61\n2015-09-10 01:13:00,2.17\n2015-09-10 01:38:00,1.06\n2015-09-10 01:58:00,2.17\n2015-09-10 02:08:00,2.72\n2015-09-10 02:18:00,0.39\n2015-09-10 02:23:00,0.67\n2015-09-10 02:28:00,0.89\n2015-09-10 05:28:00,11.33\n2015-09-10 05:33:00,6.72\n2015-09-10 05:38:00,5.67\n2015-09-10 05:45:00,6.44\n2015-09-10 08:00:00,8.67\n2015-09-10 08:13:00,9.06\n2015-09-10 08:18:00,5.28\n2015-09-10 08:23:00,12.28\n2015-09-10 08:28:00,9.06\n2015-09-10 08:33:00,8.89\n2015-09-10 08:43:00,3.89\n2015-09-10 08:48:00,2.94\n2015-09-10 08:53:00,6.33\n2015-09-10 08:58:00,6.56\n2015-09-10 09:03:00,4.78\n2015-09-10 09:08:00,3.61\n2015-09-10 09:13:00,7.22\n2015-09-10 09:18:00,10.72\n2015-09-10 09:28:00,4.11\n2015-09-10 09:33:00,6.06\n2015-09-10 09:38:00,7.5\n2015-09-10 09:43:00,1.94\n2015-09-10 09:48:00,3.72\n2015-09-10 09:52:00,6.06\n2015-09-10 09:57:00,2.28\n2015-09-10 10:02:00,1.67\n2015-09-10 10:07:00,4\n2015-09-10 10:17:00,10.56\n2015-09-10 10:22:00,4.78\n2015-09-10 10:27:00,4.28\n2015-09-10 10:37:00,1.67\n2015-09-10 10:42:00,4.39\n2015-09-10 10:47:00,7.44\n2015-09-10 10:52:00,1.39\n2015-09-10 10:57:00,2.33\n2015-09-10 11:02:00,7.06\n2015-09-10 11:07:00,4.22\n2015-09-10 11:12:00,1.56\n2015-09-10 11:22:00,4\n2015-09-10 11:32:00,1.44\n2015-09-10 11:42:00,1.78\n2015-09-10 11:47:00,6.56\n2015-09-10 11:57:00,2.28\n2015-09-10 12:02:00,5.78\n2015-09-10 12:12:00,1.17\n2015-09-10 12:17:00,3.22\n2015-09-10 12:22:00,1.28\n2015-09-10 12:57:00,2.44\n2015-09-10 13:02:00,1.94\n2015-09-10 13:07:00,6.44\n2015-09-10 13:12:00,3.89\n2015-09-10 13:17:00,2.06\n2015-09-10 13:22:00,2.28\n2015-09-10 13:27:00,6.44\n2015-09-10 13:42:00,0.61\n2015-09-10 13:47:00,2.17\n2015-09-10 13:57:00,4.67\n2015-09-10 14:02:00,7.61\n2015-09-10 14:12:00,7.06\n2015-09-10 14:37:00,1.94\n2015-09-10 14:42:00,4.39\n2015-09-10 14:47:00,5.06\n2015-09-10 14:57:00,4.61\n2015-09-10 15:02:00,1.78\n2015-09-10 15:07:00,6.33\n2015-09-10 15:12:00,4.39\n2015-09-10 15:17:00,3.72\n2015-09-10 15:22:00,5.83\n2015-09-10 15:27:00,4.39\n2015-09-10 15:32:00,3.5\n2015-09-10 15:37:00,5.56\n2015-09-10 15:42:00,2.28\n2015-09-10 15:47:00,6.17\n2015-09-10 15:52:00,3.72\n2015-09-10 15:57:00,1.67\n2015-09-10 16:02:00,5.06\n2015-09-10 16:12:00,8.61\n2015-09-10 16:17:00,8.11\n2015-09-10 16:27:00,6.17\n2015-09-10 16:32:00,5.17\n2015-09-10 16:37:00,5.67\n2015-09-10 16:42:00,8\n2015-09-10 16:47:00,4.28\n2015-09-10 16:57:00,4.5\n2015-09-10 17:02:00,6.94\n2015-09-10 17:17:00,5.44\n2015-09-10 17:22:00,6.33\n2015-09-10 17:27:00,7.33\n2015-09-10 17:37:00,4.28\n2015-09-10 17:42:00,5.83\n2015-09-10 17:47:00,5.28\n2015-09-10 17:52:00,9.28\n2015-09-10 18:02:00,4.39\n2015-09-10 18:07:00,6.06\n2015-09-10 18:12:00,9.56\n2015-09-10 18:17:00,5.67\n2015-09-10 18:22:00,3.83\n2015-09-10 18:27:00,2.83\n2015-09-10 18:32:00,5.44\n2015-09-10 18:42:00,8.61\n2015-09-10 18:47:00,1.06\n2015-09-10 18:52:00,5.28\n2015-09-10 19:02:00,2.33\n2015-09-10 19:07:00,2.33\n2015-09-10 19:17:00,2.17\n2015-09-10 19:27:00,5.06\n2015-09-10 19:37:00,0.39\n2015-09-10 19:47:00,1.83\n2015-09-10 19:52:00,3.06\n2015-09-10 20:02:00,5.06\n2015-09-10 20:12:00,2.56\n2015-09-10 20:28:00,3.11\n2015-09-10 20:32:00,1.83\n2015-09-10 20:43:00,1.83\n2015-09-10 20:47:00,1.83\n2015-09-10 20:57:00,3.11\n2015-09-10 21:07:00,1.78\n2015-09-10 21:12:00,2.33\n2015-09-10 21:17:00,1.44\n2015-09-10 21:32:00,3.44\n2015-09-10 21:37:00,1.94\n2015-09-10 21:42:00,0.22\n2015-09-10 21:47:00,2.06\n2015-09-10 22:12:00,3.5\n2015-09-10 22:27:00,0.61\n2015-09-10 22:32:00,1.44\n2015-09-10 22:37:00,1.56\n2015-09-10 22:47:00,0.28\n2015-09-10 22:57:00,0.78\n2015-09-10 23:02:00,0.89\n2015-09-10 23:07:00,4\n2015-09-10 23:37:00,2.33\n2015-09-10 23:42:00,2.28\n2015-09-10 23:57:00,1.44\n2015-09-11 00:02:00,1.83\n2015-09-11 00:22:00,1\n2015-09-11 01:07:00,0.28\n2015-09-11 01:17:00,0.78\n2015-09-11 01:32:00,1.06\n2015-09-11 01:42:00,0.39\n2015-09-11 01:57:00,1.78\n2015-09-11 02:12:00,0.67\n2015-09-11 02:22:00,0.89\n2015-09-11 02:32:00,1.67\n2015-09-11 02:57:00,1.17\n2015-09-11 03:12:00,0.5\n2015-09-11 03:27:00,1.56\n2015-09-11 03:32:00,0.78\n2015-09-11 03:47:00,3.33\n2015-09-11 04:07:00,0.61\n2015-09-11 04:12:00,0.22\n2015-09-11 04:17:00,3.5\n2015-09-11 04:27:00,0.67\n2015-09-11 04:47:00,2.72\n2015-09-11 04:52:00,2.94\n2015-09-11 05:17:00,3.61\n2015-09-11 05:22:00,4.11\n2015-09-11 05:32:00,2.67\n2015-09-11 05:37:00,4.5\n2015-09-11 05:42:00,6.44\n2015-09-11 05:47:00,8.39\n2015-09-11 05:52:00,7.06\n2015-09-11 05:57:00,4.5\n2015-09-11 06:02:00,8.39\n2015-09-11 06:07:00,6.44\n2015-09-11 06:12:00,11.5\n2015-09-11 06:17:00,9.06\n2015-09-11 06:22:00,5.44\n2015-09-11 06:27:00,9.94\n2015-09-11 06:32:00,12.5\n2015-09-11 06:37:00,14.17\n2015-09-11 06:42:00,12.11\n2015-09-11 06:47:00,6.94\n2015-09-11 06:52:00,14.33\n2015-09-11 06:57:00,8.11\n2015-09-11 07:02:00,13\n2015-09-11 07:07:00,10.94\n2015-09-11 07:12:00,11.83\n2015-09-11 07:17:00,6.33\n2015-09-11 07:22:00,10.44\n2015-09-11 07:27:00,13.11\n2015-09-11 07:32:00,12.78\n2015-09-11 07:37:00,8.39\n2015-09-11 07:42:00,11.33\n2015-09-11 07:47:00,9.44\n2015-09-11 07:57:00,7.44\n2015-09-11 08:02:00,4.39\n2015-09-11 08:07:00,9.06\n2015-09-11 08:12:00,5.56\n2015-09-11 08:17:00,4.39\n2015-09-11 08:22:00,6.67\n2015-09-11 08:27:00,9.56\n2015-09-11 08:32:00,9.17\n2015-09-11 08:37:00,5.28\n2015-09-11 08:47:00,5.28\n2015-09-11 08:52:00,3.5\n2015-09-11 08:57:00,4.22\n2015-09-11 09:02:00,5.17\n2015-09-11 09:12:00,4.78\n2015-09-11 09:17:00,5.28\n2015-09-11 09:22:00,8.22\n2015-09-11 09:27:00,0.89\n2015-09-11 09:32:00,5.39\n2015-09-11 09:37:00,0.28\n2015-09-11 09:42:00,2.67\n2015-09-11 10:02:00,2.33\n2015-09-11 10:07:00,4.28\n2015-09-11 10:17:00,7.11\n2015-09-11 10:34:00,3.22\n2015-09-11 10:44:00,3.72\n2015-09-11 10:49:00,8\n2015-09-11 10:54:00,1.39\n2015-09-11 10:59:00,5.83\n2015-09-11 11:04:00,3.61\n2015-09-11 11:09:00,8.5\n2015-09-11 11:14:00,6.28\n2015-09-11 11:24:00,5.28\n2015-09-11 11:29:00,1.67\n2015-09-11 11:34:00,6.67\n2015-09-11 11:39:00,2.06\n2015-09-11 11:44:00,4.39\n2015-09-11 11:49:00,3.89\n2015-09-11 11:54:00,3.5\n2015-09-11 11:59:00,5.28\n2015-09-11 12:04:00,6.67\n2015-09-11 12:09:00,3.83\n2015-09-11 12:14:00,6.33\n2015-09-11 12:19:00,5\n2015-09-11 12:24:00,2.67\n2015-09-11 12:29:00,1.78\n2015-09-11 12:34:00,5.94\n2015-09-11 12:44:00,3.89\n2015-09-11 12:49:00,7.5\n2015-09-11 12:54:00,1.94\n2015-09-11 12:59:00,4.39\n2015-09-11 13:04:00,4.28\n2015-09-11 13:09:00,8.11\n2015-09-11 13:19:00,7.44\n2015-09-11 13:24:00,5.56\n2015-09-11 13:29:00,3.89\n2015-09-11 13:34:00,4.89\n2015-09-11 13:39:00,5.83\n2015-09-11 13:44:00,9.94\n2015-09-11 13:49:00,9\n2015-09-11 13:54:00,4.61\n2015-09-11 13:59:00,5.78\n2015-09-11 14:04:00,3.33\n2015-09-11 14:09:00,2.56\n2015-09-11 14:14:00,6.06\n2015-09-11 14:19:00,4.39\n2015-09-11 14:24:00,5.56\n2015-09-11 14:29:00,1.94\n2015-09-11 14:34:00,10.33\n2015-09-11 14:39:00,4.11\n2015-09-11 14:44:00,5.56\n2015-09-11 14:49:00,10.17\n2015-09-11 14:54:00,10.83\n2015-09-11 14:59:00,6.72\n2015-09-11 15:04:00,3.22\n2015-09-11 15:19:00,10.06\n2015-09-11 15:24:00,8.28\n2015-09-11 15:29:00,7.22\n2015-09-11 15:34:00,6.28\n2015-09-11 15:39:00,4.61\n2015-09-11 15:44:00,7.61\n2015-09-11 15:49:00,3.5\n2015-09-11 15:54:00,8.89\n2015-09-11 15:59:00,2.67\n2015-09-11 16:04:00,1.56\n2015-09-11 16:09:00,5.94\n2015-09-11 16:14:00,4.89\n2015-09-11 16:19:00,7.11\n2015-09-11 16:24:00,6.33\n2015-09-11 16:29:00,8.28\n2015-09-11 16:34:00,9.28\n2015-09-11 16:39:00,6.83\n2015-09-11 16:44:00,1.67\n2015-09-11 16:49:00,4.67\n2015-09-11 16:54:00,4.78\n2015-09-11 16:59:00,10.33\n2015-09-11 17:04:00,4.67\n2015-09-11 17:09:00,3.72\n2015-09-11 17:14:00,9.78\n2015-09-11 17:19:00,7.61\n2015-09-11 17:24:00,6.56\n2015-09-11 17:29:00,5.56\n2015-09-11 17:34:00,4.78\n2015-09-11 17:39:00,7.11\n2015-09-11 17:44:00,6.83\n2015-09-11 17:49:00,3.06\n2015-09-11 17:54:00,5.44\n2015-09-11 17:59:00,7.5\n2015-09-11 18:04:00,5.83\n2015-09-11 18:11:00,5.06\n2015-09-11 18:16:00,3.5\n2015-09-11 18:21:00,6.33\n2015-09-11 18:26:00,3.44\n2015-09-11 18:31:00,2.83\n2015-09-11 18:36:00,4.5\n2015-09-11 18:41:00,1.78\n2015-09-11 18:46:00,2.83\n2015-09-11 18:51:00,3.72\n2015-09-11 18:56:00,3.44\n2015-09-11 19:01:00,1.28\n2015-09-11 19:06:00,1.67\n2015-09-11 19:11:00,3.22\n2015-09-11 19:21:00,4.39\n2015-09-11 19:31:00,1.94\n2015-09-11 19:41:00,3.11\n2015-09-11 19:46:00,6.06\n2015-09-11 19:51:00,8.39\n2015-09-11 20:11:00,1.39\n2015-09-11 20:26:00,5.17\n2015-09-11 20:31:00,2.44\n2015-09-11 20:36:00,7.83\n2015-09-11 20:41:00,2.33\n2015-09-11 20:46:00,1.39\n2015-09-11 20:51:00,2.28\n2015-09-11 20:56:00,2.44\n2015-09-11 21:01:00,1.39\n2015-09-11 21:06:00,0.78\n2015-09-11 21:21:00,3.06\n2015-09-11 21:26:00,0.78\n2015-09-11 21:36:00,1.39\n2015-09-11 21:46:00,2.28\n2015-09-11 21:51:00,5.06\n2015-09-11 22:06:00,2.72\n2015-09-11 22:11:00,4.67\n2015-09-11 22:21:00,2.06\n2015-09-11 22:41:00,3.06\n2015-09-11 22:46:00,5.06\n2015-09-11 22:56:00,0.78\n2015-09-11 23:01:00,2.28\n2015-09-11 23:11:00,1\n2015-09-11 23:16:00,0.78\n2015-09-11 23:36:00,1.06\n2015-09-11 23:41:00,0\n2015-09-12 00:11:00,0.78\n2015-09-12 00:26:00,3.61\n2015-09-12 00:31:00,0.67\n2015-09-12 00:41:00,1.67\n2015-09-12 00:46:00,0\n2015-09-12 00:51:00,0\n2015-09-12 01:01:00,0.89\n2015-09-12 01:26:00,0.89\n2015-09-12 01:31:00,0.61\n2015-09-12 02:21:00,1.67\n2015-09-12 02:56:00,2.44\n2015-09-12 03:46:00,3.33\n2015-09-12 03:56:00,0.5\n2015-09-12 04:06:00,0\n2015-09-12 04:36:00,0\n2015-09-12 04:41:00,0.22\n2015-09-12 04:51:00,1.67\n2015-09-12 05:06:00,0.39\n2015-09-12 05:21:00,1.39\n2015-09-12 05:41:00,1.39\n2015-09-12 05:46:00,1.94\n2015-09-12 05:56:00,4.11\n2015-09-12 06:06:00,1.56\n2015-09-12 06:16:00,2.06\n2015-09-12 06:26:00,3.61\n2015-09-12 06:51:00,0.28\n2015-09-12 06:56:00,2.83\n2015-09-12 07:01:00,3.61\n2015-09-12 07:16:00,5.06\n2015-09-12 07:21:00,2.28\n2015-09-12 07:31:00,3.06\n2015-09-12 07:36:00,2.44\n2015-09-12 07:46:00,2.17\n2015-09-12 07:51:00,1.67\n2015-09-12 07:56:00,5.44\n2015-09-12 08:06:00,3.44\n2015-09-12 08:11:00,2.72\n2015-09-12 08:16:00,3.11\n2015-09-12 08:21:00,2.06\n2015-09-12 08:26:00,2.06\n2015-09-12 08:31:00,2.17\n2015-09-12 08:36:00,0.89\n2015-09-12 08:46:00,8.61\n2015-09-12 08:56:00,2.44\n2015-09-12 09:01:00,2.72\n2015-09-12 09:06:00,7.11\n2015-09-12 09:11:00,2.72\n2015-09-12 09:16:00,1.39\n2015-09-12 09:21:00,2.67\n2015-09-12 09:26:00,1.28\n2015-09-12 09:36:00,5.94\n2015-09-12 09:41:00,1.94\n2015-09-12 09:51:00,2.33\n2015-09-12 10:01:00,2.56\n2015-09-12 10:06:00,3.22\n2015-09-12 10:11:00,3.89\n2015-09-12 10:16:00,1.94\n2015-09-12 10:21:00,5.28\n2015-09-12 10:31:00,3.83\n2015-09-12 10:36:00,3.61\n2015-09-12 10:41:00,8.61\n2015-09-12 10:46:00,12.5\n2015-09-12 10:51:00,5.17\n2015-09-12 10:56:00,3.33\n2015-09-12 11:01:00,4.78\n2015-09-12 11:06:00,2.33\n2015-09-12 11:11:00,5.39\n2015-09-12 11:16:00,6.72\n2015-09-12 11:21:00,4.22\n2015-09-12 11:26:00,3.11\n2015-09-12 11:31:00,8.89\n2015-09-12 11:36:00,7.22\n2015-09-12 11:46:00,8.78\n2015-09-12 11:51:00,11.89\n2015-09-12 11:56:00,6.06\n2015-09-12 12:01:00,5.78\n2015-09-12 12:16:00,3.83\n2015-09-12 12:21:00,7.72\n2015-09-12 12:26:00,4.78\n2015-09-12 12:31:00,6.17\n2015-09-12 12:36:00,6.17\n2015-09-12 12:41:00,11.11\n2015-09-12 12:46:00,5.78\n2015-09-12 12:51:00,3.72\n2015-09-12 12:56:00,4.67\n2015-09-12 13:01:00,5\n2015-09-12 13:11:00,2.33\n2015-09-12 13:16:00,6.28\n2015-09-12 13:21:00,6.56\n2015-09-12 13:31:00,8.28\n2015-09-12 13:41:00,6.83\n2015-09-12 13:46:00,4.5\n2015-09-12 13:56:00,5.94\n2015-09-12 14:01:00,7.22\n2015-09-12 14:06:00,4\n2015-09-12 14:11:00,5.67\n2015-09-12 14:16:00,3.89\n2015-09-12 14:21:00,5\n2015-09-12 14:26:00,5.17\n2015-09-12 14:31:00,4.22\n2015-09-12 14:36:00,8\n2015-09-12 14:41:00,7.06\n2015-09-12 14:46:00,4.67\n2015-09-12 14:51:00,6.06\n2015-09-12 14:56:00,7.5\n2015-09-12 15:01:00,2.17\n2015-09-12 15:06:00,6.28\n2015-09-12 15:11:00,0.67\n2015-09-12 15:21:00,5.39\n2015-09-12 15:26:00,5.44\n2015-09-12 15:36:00,4.89\n2015-09-12 15:41:00,6.83\n2015-09-12 15:46:00,8.28\n2015-09-12 15:51:00,1.83\n2015-09-12 15:56:00,2.33\n2015-09-12 16:01:00,6.17\n2015-09-12 16:06:00,2.94\n2015-09-12 16:11:00,2.72\n2015-09-12 16:16:00,3.22\n2015-09-12 16:21:00,4.28\n2015-09-12 16:26:00,4.22\n2015-09-12 16:36:00,3.11\n2015-09-12 16:41:00,2.28\n2015-09-12 16:46:00,2.06\n2015-09-12 16:56:00,2.56\n2015-09-12 17:01:00,2.94\n2015-09-12 17:06:00,7.89\n2015-09-12 17:11:00,1.83\n2015-09-12 17:16:00,2.72\n2015-09-12 17:21:00,1.78\n2015-09-12 17:26:00,2.44\n2015-09-12 17:31:00,3.61\n2015-09-12 17:36:00,5.67\n2015-09-12 17:41:00,3.22\n2015-09-12 17:46:00,1.94\n2015-09-12 17:51:00,3.72\n2015-09-12 17:56:00,3.11\n2015-09-12 18:01:00,2.83\n2015-09-12 18:06:00,0\n2015-09-12 18:11:00,3.61\n2015-09-12 18:16:00,1.39\n2015-09-12 18:21:00,3.33\n2015-09-12 18:26:00,2.72\n2015-09-12 18:36:00,3.83\n2015-09-12 18:41:00,2.17\n2015-09-12 18:46:00,1.39\n2015-09-12 18:51:00,6.94\n2015-09-12 19:01:00,2.67\n2015-09-12 19:06:00,1.56\n2015-09-12 19:21:00,7.22\n2015-09-12 19:31:00,5.39\n2015-09-12 19:36:00,5.39\n2015-09-12 19:41:00,5.44\n2015-09-12 19:51:00,3.44\n2015-09-12 19:56:00,3.5\n2015-09-12 20:01:00,5.83\n2015-09-12 20:11:00,3.72\n2015-09-12 20:21:00,0.67\n2015-09-12 20:31:00,4.89\n2015-09-12 20:36:00,2.17\n2015-09-12 20:46:00,1.94\n2015-09-12 21:01:00,7.22\n2015-09-12 21:06:00,3.5\n2015-09-12 21:11:00,2.94\n2015-09-12 21:16:00,6.17\n2015-09-12 21:21:00,3.5\n2015-09-12 21:26:00,0.28\n2015-09-12 21:31:00,1.39\n2015-09-12 21:46:00,0.61\n2015-09-12 21:56:00,4.22\n2015-09-12 22:11:00,0.61\n2015-09-12 22:16:00,5.28\n2015-09-12 22:21:00,2.33\n2015-09-12 22:26:00,1.94\n2015-09-12 22:36:00,0.61\n2015-09-12 22:41:00,2.33\n2015-09-12 22:46:00,2.72\n2015-09-12 22:56:00,2.28\n2015-09-12 23:01:00,3.11\n2015-09-12 23:11:00,0.89\n2015-09-12 23:26:00,1.94\n2015-09-12 23:31:00,0.67\n2015-09-12 23:41:00,2.44\n2015-09-12 23:51:00,1.56\n2015-09-13 00:16:00,0.67\n2015-09-13 00:21:00,1.06\n2015-09-13 00:26:00,2.06\n2015-09-13 02:21:00,1.83\n2015-09-13 02:26:00,1.17\n2015-09-13 02:36:00,0.78\n2015-09-13 02:56:00,1.06\n2015-09-13 04:41:00,0.89\n2015-09-13 04:46:00,0.61\n2015-09-13 04:51:00,0.89\n2015-09-13 05:21:00,0.39\n2015-09-13 06:11:00,1.17\n2015-09-13 06:21:00,1.17\n2015-09-13 06:41:00,1.28\n2015-09-13 06:46:00,1.78\n2015-09-13 06:51:00,0.89\n2015-09-13 07:11:00,1.83\n2015-09-13 07:16:00,1.28\n2015-09-13 07:21:00,4.28\n2015-09-13 07:36:00,0.39\n2015-09-13 07:46:00,3.33\n2015-09-13 07:56:00,0\n2015-09-13 08:01:00,2.28\n2015-09-13 08:16:00,0.22\n2015-09-13 08:31:00,2.33\n2015-09-13 08:41:00,1.56\n2015-09-13 08:56:00,3.61\n2015-09-13 09:06:00,3.22\n2015-09-13 09:11:00,1.28\n2015-09-13 09:16:00,2.67\n2015-09-13 09:31:00,2.94\n2015-09-13 09:36:00,4.22\n2015-09-13 09:46:00,4\n2015-09-13 09:51:00,1.78\n2015-09-13 10:01:00,0.5\n2015-09-13 10:06:00,3.5\n2015-09-13 10:11:00,3.33\n2015-09-13 10:16:00,8.22\n2015-09-13 10:21:00,4.39\n2015-09-13 10:26:00,2.44\n2015-09-13 10:31:00,4\n2015-09-13 10:36:00,7.11\n2015-09-13 10:41:00,5.39\n2015-09-13 10:46:00,2.06\n2015-09-13 10:51:00,7.72\n2015-09-13 10:56:00,1.78\n2015-09-13 11:06:00,6.94\n2015-09-13 11:11:00,4.67\n2015-09-13 11:16:00,6.56\n2015-09-13 11:26:00,7.89\n2015-09-13 11:31:00,9.28\n2015-09-13 11:36:00,5\n2015-09-13 11:41:00,3.89\n2015-09-13 11:46:00,1.78\n2015-09-13 11:51:00,4.67\n2015-09-13 11:56:00,4.39\n2015-09-13 12:01:00,6.83\n2015-09-13 12:06:00,5.94\n2015-09-13 12:11:00,4.61\n2015-09-13 12:16:00,8.11\n2015-09-13 12:21:00,4\n2015-09-13 12:26:00,10.72\n2015-09-13 12:31:00,2.44\n2015-09-13 12:41:00,3.72\n2015-09-13 12:46:00,8.22\n2015-09-13 12:53:00,2.67\n2015-09-13 12:58:00,7.06\n2015-09-13 13:03:00,13.28\n2015-09-13 13:08:00,5\n2015-09-13 13:13:00,8.39\n2015-09-13 13:18:00,8.89\n2015-09-13 13:23:00,7.33\n2015-09-13 13:33:00,12.28\n2015-09-13 13:38:00,11.33\n2015-09-13 13:43:00,6.28\n2015-09-13 13:48:00,6.17\n2015-09-13 13:53:00,9.06\n2015-09-13 13:58:00,4.22\n2015-09-13 14:03:00,6.83\n2015-09-13 14:13:00,7.72\n2015-09-13 14:18:00,7.11\n2015-09-13 14:28:00,3.5\n2015-09-13 14:38:00,4.28\n2015-09-13 14:43:00,7.44\n2015-09-13 14:48:00,5.94\n2015-09-13 14:53:00,5.17\n2015-09-13 15:03:00,10.83\n2015-09-13 15:13:00,2.56\n2015-09-13 15:18:00,8.11\n2015-09-13 15:23:00,10.67\n2015-09-13 15:28:00,6.56\n2015-09-13 15:33:00,8.22\n2015-09-13 15:43:00,9.83\n2015-09-13 15:48:00,5.67\n2015-09-13 15:53:00,6.83\n2015-09-13 15:58:00,7.33\n2015-09-13 16:03:00,7.06\n2015-09-13 16:08:00,7.11\n2015-09-13 16:13:00,3.83\n2015-09-13 16:18:00,5.83\n2015-09-13 16:23:00,11.06\n2015-09-13 16:28:00,11.83\n2015-09-13 16:33:00,6.06\n2015-09-13 16:38:00,6.56\n2015-09-13 16:43:00,8.61\n2015-09-13 16:48:00,8.67\n2015-09-13 16:58:00,8.78\n2015-09-13 17:03:00,9.28\n2015-09-13 17:08:00,9\n2015-09-13 17:13:00,9.44\n2015-09-13 17:18:00,5.17\n2015-09-13 17:23:00,4.28\n2015-09-13 17:28:00,2.94\n2015-09-13 17:33:00,10.17\n2015-09-13 17:38:00,10.67\n2015-09-13 17:43:00,6.72\n2015-09-13 17:48:00,10.06\n2015-09-13 17:53:00,5.28\n2015-09-13 17:58:00,5.56\n2015-09-13 18:03:00,5.17\n2015-09-13 18:08:00,10.67\n2015-09-13 18:13:00,5.06\n2015-09-13 18:18:00,3.11\n2015-09-13 18:23:00,10.72\n2015-09-13 18:28:00,7.22\n2015-09-13 18:33:00,5\n2015-09-13 18:38:00,10.67\n2015-09-13 18:43:00,1.67\n2015-09-13 18:48:00,5.56\n2015-09-13 18:53:00,10.28\n2015-09-13 18:58:00,11.06\n2015-09-13 19:03:00,5.44\n2015-09-13 19:13:00,4.89\n2015-09-13 19:18:00,10.28\n2015-09-13 19:23:00,6.67\n2015-09-13 19:33:00,0.67\n2015-09-13 19:38:00,5.17\n2015-09-13 19:43:00,4\n2015-09-13 19:48:00,2.56\n2015-09-13 19:53:00,2.67\n2015-09-13 19:58:00,4.11\n2015-09-13 20:03:00,4.11\n2015-09-13 20:08:00,7.61\n2015-09-13 20:13:00,3.11\n2015-09-13 20:18:00,9\n2015-09-13 20:28:00,2.44\n2015-09-13 20:33:00,2.67\n2015-09-13 20:38:00,2.94\n2015-09-13 20:48:00,1.39\n2015-09-13 20:53:00,2.67\n2015-09-13 20:58:00,1.17\n2015-09-13 21:03:00,3.22\n2015-09-13 21:08:00,1.44\n2015-09-13 21:13:00,2.06\n2015-09-13 21:18:00,1.44\n2015-09-13 21:43:00,3.06\n2015-09-13 22:03:00,1.44\n2015-09-13 22:13:00,3.44\n2015-09-13 22:28:00,1.67\n2015-09-13 22:33:00,1.44\n2015-09-13 22:38:00,1.67\n2015-09-13 22:43:00,0.22\n2015-09-13 22:48:00,0.28\n2015-09-13 22:58:00,2.44\n2015-09-13 23:03:00,0.67\n2015-09-13 23:13:00,0.78\n2015-09-13 23:18:00,1\n2015-09-13 23:28:00,0.39\n2015-09-13 23:33:00,0.67\n2015-09-13 23:38:00,0.78\n2015-09-13 23:48:00,1.06\n2015-09-13 23:59:00,0.67\n2015-09-14 00:03:00,2.94\n2015-09-14 00:18:00,0.78\n2015-09-14 00:33:00,0.39\n2015-09-14 01:08:00,2.28\n2015-09-14 01:33:00,3.5\n2015-09-14 01:53:00,0.89\n2015-09-14 01:58:00,0.28\n2015-09-14 02:08:00,0\n2015-09-14 02:23:00,0.67\n2015-09-14 02:28:00,1.28\n2015-09-14 02:33:00,1.06\n2015-09-14 02:48:00,0.5\n2015-09-14 02:53:00,0.78\n2015-09-14 03:18:00,0.78\n2015-09-14 03:33:00,0.78\n2015-09-14 03:38:00,0\n2015-09-14 03:43:00,1\n2015-09-14 03:48:00,0\n2015-09-14 04:03:00,0.61\n2015-09-14 04:08:00,0.22\n2015-09-14 04:23:00,0.39\n2015-09-14 04:28:00,1.06\n2015-09-14 04:43:00,1.44\n2015-09-14 04:48:00,0.78\n2015-09-14 04:53:00,4.5\n2015-09-14 04:58:00,2.33\n2015-09-14 05:03:00,1.67\n2015-09-14 05:08:00,3.33\n2015-09-14 05:13:00,5.44\n2015-09-14 05:18:00,2.94\n2015-09-14 05:23:00,10.33\n2015-09-14 05:28:00,6.56\n2015-09-14 05:33:00,5.28\n2015-09-14 05:38:00,6.17\n2015-09-14 05:43:00,8.39\n2015-09-14 05:48:00,3.72\n2015-09-14 05:53:00,5.83\n2015-09-14 05:58:00,8.22\n2015-09-14 06:03:00,9\n2015-09-14 06:08:00,16.72\n2015-09-14 06:13:00,10.33\n2015-09-14 06:18:00,8.5\n2015-09-14 06:23:00,13.56\n2015-09-14 06:28:00,18.33\n2015-09-14 06:33:00,9.83\n2015-09-14 06:38:00,9.06\n2015-09-14 06:43:00,17.11\n2015-09-14 08:23:00,9.83\n2015-09-14 08:28:00,8\n2015-09-14 08:33:00,8.78\n2015-09-14 08:38:00,9.28\n2015-09-14 08:43:00,4.28\n2015-09-14 08:48:00,6.44\n2015-09-14 08:53:00,3.83\n2015-09-14 08:58:00,7.5\n2015-09-14 09:03:00,1.06\n2015-09-14 09:08:00,1.17\n2015-09-14 09:13:00,6.72\n2015-09-14 09:23:00,3.33\n2015-09-14 09:28:00,2.44\n2015-09-14 09:33:00,5.83\n2015-09-14 09:38:00,5.28\n2015-09-14 09:43:00,4.61\n2015-09-14 09:48:00,3.06\n2015-09-14 09:53:00,1.17\n2015-09-14 09:58:00,2.28\n2015-09-14 10:03:00,4.11\n2015-09-14 10:08:00,2.72\n2015-09-14 10:13:00,3.5\n2015-09-14 10:18:00,2.17\n2015-09-14 10:23:00,6.83\n2015-09-14 10:28:00,8.61\n2015-09-14 10:33:00,1.83\n2015-09-14 10:38:00,4.5\n2015-09-14 10:43:00,5.06\n2015-09-14 10:48:00,4.89\n2015-09-14 10:53:00,1.78\n2015-09-14 10:58:00,2.44\n2015-09-14 11:03:00,2.44\n2015-09-14 11:23:00,4\n2015-09-14 11:33:00,4.22\n2015-09-14 11:38:00,3.33\n2015-09-14 11:48:00,4.11\n2015-09-14 11:53:00,5\n2015-09-14 11:58:00,1.67\n2015-09-14 12:03:00,1\n2015-09-14 12:08:00,3.72\n2015-09-14 12:13:00,4.61\n2015-09-14 12:18:00,2.06\n2015-09-14 12:23:00,5.39\n2015-09-14 12:28:00,5\n2015-09-14 12:33:00,4.5\n2015-09-14 12:38:00,2.17\n2015-09-14 12:43:00,1.06\n2015-09-14 12:48:00,7.44\n2015-09-14 13:03:00,1.83\n2015-09-14 13:08:00,3.72\n2015-09-14 13:13:00,2.94\n2015-09-14 13:15:00,3.61\n2015-09-14 13:20:00,2.17\n2015-09-14 13:25:00,7.11\n2015-09-14 13:35:00,3.06\n2015-09-14 13:40:00,3.22\n2015-09-14 13:45:00,6.17\n2015-09-14 13:55:00,4.5\n2015-09-14 14:00:00,4.28\n2015-09-14 14:05:00,4.39\n2015-09-14 14:10:00,7.33\n2015-09-14 14:15:00,5\n2015-09-14 14:20:00,2.28\n2015-09-14 14:25:00,4.22\n2015-09-14 14:30:00,1.28\n2015-09-14 14:35:00,6.56\n2015-09-14 14:40:00,5\n2015-09-14 14:45:00,5.17\n2015-09-14 14:50:00,5.06\n2015-09-14 14:55:00,4.78\n2015-09-14 15:00:00,1.83\n2015-09-14 15:05:00,4.39\n2015-09-14 15:10:00,5.94\n2015-09-14 15:15:00,6.44\n2015-09-14 15:20:00,1.28\n2015-09-14 15:25:00,2.06\n2015-09-14 15:30:00,1.94\n2015-09-14 15:35:00,5.56\n2015-09-14 15:40:00,4.78\n2015-09-14 15:45:00,3.33\n2015-09-14 15:50:00,3.22\n2015-09-14 15:55:00,3.11\n2015-09-14 16:00:00,3.72\n2015-09-14 16:05:00,3.11\n2015-09-14 16:10:00,3.22\n2015-09-14 16:15:00,3.11\n2015-09-14 16:20:00,2.17\n2015-09-14 16:25:00,6.06\n2015-09-14 16:30:00,1.83\n2015-09-14 16:35:00,2.72\n2015-09-14 16:40:00,3.72\n2015-09-14 16:45:00,2.33\n2015-09-14 16:50:00,6.72\n2015-09-14 16:55:00,5.06\n2015-09-14 17:00:00,4.28\n2015-09-14 17:10:00,4.11\n2015-09-14 17:15:00,6.44\n2015-09-14 17:20:00,5.67\n2015-09-14 17:25:00,7.5\n2015-09-14 17:30:00,5.17\n2015-09-14 17:35:00,3.22\n2015-09-14 17:40:00,2.94\n2015-09-14 17:45:00,3.11\n2015-09-14 17:50:00,4.67\n2015-09-14 17:55:00,1.56\n2015-09-14 18:00:00,3.11\n2015-09-14 18:05:00,1.17\n2015-09-14 18:10:00,3.83\n2015-09-14 18:15:00,5.78\n2015-09-14 18:20:00,3.5\n2015-09-14 18:25:00,2.06\n2015-09-14 18:30:00,1.56\n2015-09-14 18:35:00,2.94\n2015-09-14 18:45:00,2.94\n2015-09-14 18:50:00,5.44\n2015-09-14 18:55:00,3.61\n2015-09-14 19:01:00,1.78\n2015-09-14 19:05:00,1.39\n2015-09-14 19:10:00,2.33\n2015-09-14 19:15:00,1.83\n2015-09-14 19:20:00,2.72\n2015-09-14 19:30:00,0.89\n2015-09-14 19:35:00,1.39\n2015-09-14 19:40:00,2.44\n2015-09-14 19:45:00,1.78\n2015-09-14 19:50:00,4.67\n2015-09-14 19:55:00,3.11\n2015-09-14 20:05:00,1.94\n2015-09-14 20:10:00,2.44\n2015-09-14 20:15:00,1.78\n2015-09-14 20:20:00,1.28\n2015-09-14 20:25:00,1.39\n2015-09-14 20:30:00,1.78\n2015-09-14 20:50:00,1.78\n2015-09-14 20:55:00,1.56\n2015-09-14 20:59:00,2.56\n2015-09-14 21:05:00,2.33\n2015-09-14 21:10:00,2.33\n2015-09-14 21:25:00,4.61\n2015-09-14 21:35:00,0.5\n2015-09-14 21:45:00,2.17\n2015-09-14 21:50:00,0.89\n2015-09-14 21:55:00,1.94\n2015-09-14 22:01:00,1.17\n2015-09-14 22:06:00,1.06\n2015-09-14 22:11:00,1\n2015-09-14 22:16:00,2.33\n2015-09-14 22:21:00,0.67\n2015-09-14 22:25:00,2.06\n2015-09-14 22:30:00,1.17\n2015-09-14 22:40:00,0.61\n2015-09-14 23:01:00,1\n2015-09-14 23:06:00,0.78\n2015-09-14 23:11:00,0.67\n2015-09-14 23:15:00,0.39\n2015-09-14 23:26:00,0.28\n2015-09-14 23:31:00,0.89\n2015-09-14 23:36:00,0.61\n2015-09-14 23:41:00,0.39\n2015-09-14 23:51:00,0.39\n2015-09-14 23:56:00,1.67\n2015-09-15 00:06:00,1\n2015-09-15 00:11:00,0\n2015-09-15 00:16:00,0\n2015-09-15 00:20:00,1.67\n2015-09-15 00:40:00,0.5\n2015-09-15 00:56:00,2.17\n2015-09-15 01:10:00,0.89\n2015-09-15 01:15:00,0.61\n2015-09-15 01:25:00,0\n2015-09-15 01:35:00,0.39\n2015-09-15 01:40:00,0.78\n2015-09-15 01:45:00,1\n2015-09-15 01:50:00,0.89\n2015-09-15 01:55:00,0.28\n2015-09-15 02:06:00,0\n2015-09-15 02:11:00,0.78\n2015-09-15 02:31:00,0\n2015-09-15 02:41:00,1\n2015-09-15 02:56:00,2.44\n2015-09-15 03:01:00,0.89\n2015-09-15 03:10:00,0.67\n2015-09-15 03:20:00,0.28\n2015-09-15 03:25:00,0.28\n2015-09-15 03:30:00,0.61\n2015-09-15 03:40:00,0.78\n2015-09-15 03:45:00,1.06\n2015-09-15 03:50:00,1.17\n2015-09-15 04:01:00,1.39\n2015-09-15 04:06:00,1.28\n2015-09-15 04:10:00,1\n2015-09-15 04:16:00,1\n2015-09-15 04:21:00,1.67\n2015-09-15 04:26:00,2.28\n2015-09-15 04:31:00,0.78\n2015-09-15 04:35:00,0.61\n2015-09-15 04:46:00,2.06\n2015-09-15 04:51:00,2.28\n2015-09-15 04:55:00,3.44\n2015-09-15 05:01:00,3.11\n2015-09-15 05:05:00,2.67\n2015-09-15 05:10:00,3.33\n2015-09-15 05:15:00,3.61\n2015-09-15 05:20:00,3.72\n2015-09-15 05:26:00,8.22\n2015-09-15 05:31:00,8.28\n2015-09-15 05:36:00,5.06\n2015-09-15 05:46:00,3.89\n2015-09-15 05:51:00,2.56\n2015-09-15 05:55:00,7.33\n2015-09-15 06:00:00,9.83\n2015-09-15 06:05:00,8.78\n2015-09-15 06:10:00,11.72\n2015-09-15 06:16:00,14.28\n2015-09-15 06:20:00,9.94\n2015-09-15 06:25:00,13.94\n2015-09-15 06:30:00,14.17\n2015-09-15 06:35:00,11.11\n2015-09-15 06:41:00,17.94\n2015-09-15 06:45:00,7.61\n2015-09-15 06:50:00,6.67\n2015-09-15 06:55:00,22.28\n2015-09-15 07:00:00,13.78\n2015-09-15 07:06:00,14.17\n2015-09-15 07:11:00,15.94\n2015-09-15 07:16:00,8.61\n2015-09-15 07:21:00,17.39\n2015-09-15 07:26:00,13.39\n2015-09-15 07:31:00,9.83\n2015-09-15 07:36:00,12.28\n2015-09-15 07:41:00,14.44\n2015-09-15 07:46:00,9.83\n2015-09-15 07:51:00,10.17\n2015-09-15 07:56:00,9.56\n2015-09-15 08:01:00,8.89\n2015-09-15 08:06:00,8.67\n2015-09-15 08:11:00,4\n2015-09-15 08:16:00,8.39\n2015-09-15 08:21:00,12.78\n2015-09-15 08:26:00,6.33\n2015-09-15 08:31:00,3.44\n2015-09-15 08:36:00,4.5\n2015-09-15 08:41:00,3.89\n2015-09-15 08:46:00,5.83\n2015-09-15 08:51:00,4.78\n2015-09-15 08:56:00,5.78\n2015-09-15 09:01:00,5.39\n2015-09-15 09:06:00,4.11\n2015-09-15 09:11:00,1.94\n2015-09-15 09:16:00,5.67\n2015-09-15 09:21:00,3.72\n2015-09-15 09:26:00,7.89\n2015-09-15 09:31:00,5.56\n2015-09-15 09:36:00,4.22\n2015-09-15 09:41:00,4.11\n2015-09-15 09:46:00,13.28\n2015-09-15 09:51:00,4.61\n2015-09-15 10:01:00,0.22\n2015-09-15 10:06:00,7.89\n2015-09-15 10:11:00,5\n2015-09-15 10:21:00,0.89\n2015-09-15 10:31:00,2.17\n2015-09-15 10:36:00,3.11\n2015-09-15 10:41:00,2.72\n2015-09-15 10:46:00,6.44\n2015-09-15 10:51:00,3.89\n2015-09-15 11:01:00,5.28\n2015-09-15 11:06:00,2.17\n2015-09-15 11:11:00,7.83\n2015-09-15 11:16:00,4.39\n2015-09-15 11:21:00,3.72\n2015-09-15 11:26:00,1.67\n2015-09-15 11:31:00,4.22\n2015-09-15 11:36:00,6.28\n2015-09-15 11:41:00,1.39\n2015-09-15 11:46:00,3.5\n2015-09-15 11:51:00,3.89\n2015-09-15 11:56:00,4.39\n2015-09-15 12:01:00,1.78\n2015-09-15 12:06:00,2.83\n2015-09-15 12:11:00,1.39\n2015-09-15 12:16:00,2.67\n2015-09-15 12:21:00,2.44\n2015-09-15 12:26:00,6.83\n2015-09-15 12:31:00,4.61\n2015-09-15 12:36:00,3.72\n2015-09-15 12:46:00,1.06\n2015-09-15 12:51:00,3.72\n2015-09-15 12:56:00,2.28\n2015-09-15 13:01:00,1.67\n2015-09-15 13:06:00,2.28\n2015-09-15 13:11:00,4.67\n2015-09-15 13:16:00,3.06\n2015-09-15 13:21:00,2.72\n2015-09-15 13:26:00,3.72\n2015-09-15 13:31:00,6.44\n2015-09-15 13:36:00,1.56\n2015-09-15 13:46:00,2.28\n2015-09-15 13:51:00,1.94\n2015-09-15 13:54:00,0.61\n2015-09-15 13:59:00,4.61\n2015-09-15 14:04:00,8.11\n2015-09-15 14:09:00,2.83\n2015-09-15 14:14:00,4.89\n2015-09-15 14:19:00,5.06\n2015-09-15 14:24:00,4\n2015-09-15 14:29:00,5.28\n2015-09-15 14:34:00,5.06\n2015-09-15 14:39:00,2.67\n2015-09-15 14:44:00,2.83\n2015-09-15 14:49:00,4.5\n2015-09-15 14:54:00,2.33\n2015-09-15 15:04:00,5.17\n2015-09-15 15:09:00,5.78\n2015-09-15 15:14:00,4.39\n2015-09-15 15:19:00,3.06\n2015-09-15 15:24:00,4.67\n2015-09-15 15:29:00,5.39\n2015-09-15 15:34:00,5.94\n2015-09-15 15:39:00,1.78\n2015-09-15 15:44:00,7.11\n2015-09-15 15:49:00,3.33\n2015-09-15 15:54:00,5.44\n2015-09-15 15:59:00,4.5\n2015-09-15 16:04:00,6.28\n2015-09-15 16:09:00,5.17\n2015-09-15 16:14:00,8.78\n2015-09-15 16:19:00,5.44\n2015-09-15 16:24:00,6.44\n2015-09-15 16:29:00,9\n2015-09-15 16:34:00,4.22\n2015-09-15 16:39:00,6.06\n2015-09-15 16:44:00,7.06\n2015-09-15 16:49:00,4.89\n2015-09-15 16:54:00,1.39\n2015-09-15 16:59:00,5.39\n2015-09-15 17:04:00,1.94\n2015-09-15 17:09:00,3.83\n2015-09-15 17:14:00,5\n2015-09-15 17:19:00,5.78\n2015-09-15 17:24:00,10.72\n2015-09-15 17:29:00,10.44\n2015-09-15 17:34:00,4.28\n2015-09-15 17:39:00,5.39\n2015-09-15 17:44:00,3.22\n2015-09-15 17:49:00,0.61\n2015-09-15 17:54:00,5.67\n2015-09-15 18:04:00,5.06\n2015-09-15 18:09:00,6.28\n2015-09-15 18:14:00,5.39\n2015-09-15 18:19:00,2.44\n2015-09-15 18:24:00,4.67\n2015-09-15 18:29:00,3.33\n2015-09-15 18:39:00,2.28\n2015-09-15 18:44:00,2.06\n2015-09-15 18:49:00,3.89\n2015-09-15 18:54:00,1.94\n2015-09-15 18:59:00,3.33\n2015-09-15 19:04:00,4.61\n2015-09-15 19:14:00,5.06\n2015-09-15 19:24:00,6.94\n2015-09-15 19:29:00,3.72\n2015-09-15 19:34:00,1.83\n2015-09-15 19:44:00,1.67\n2015-09-15 19:49:00,3.72\n2015-09-15 19:54:00,3.22\n2015-09-15 19:59:00,5.83\n2015-09-15 20:04:00,1.67\n2015-09-15 20:09:00,2.17\n2015-09-15 20:14:00,5.28\n2015-09-15 20:19:00,4.22\n2015-09-15 20:29:00,1.06\n2015-09-15 20:34:00,1.17\n2015-09-15 20:39:00,0.78\n2015-09-15 20:44:00,1.67\n2015-09-15 20:49:00,2.28\n2015-09-15 20:54:00,0.67\n2015-09-15 20:59:00,4.5\n2015-09-15 21:04:00,1.28\n2015-09-15 21:09:00,0.39\n2015-09-15 21:14:00,0.67\n2015-09-15 21:19:00,2.33\n2015-09-15 21:24:00,0.78\n2015-09-15 21:29:00,2.17\n2015-09-15 21:34:00,1.94\n2015-09-15 21:39:00,1.67\n2015-09-15 21:44:00,1.83\n2015-09-15 21:59:00,1.67\n2015-09-15 22:09:00,2.72\n2015-09-15 22:19:00,0.89\n2015-09-15 22:24:00,1.56\n2015-09-15 22:34:00,0.28\n2015-09-15 22:44:00,0.89\n2015-09-15 22:59:00,0.67\n2015-09-15 23:04:00,1.44\n2015-09-15 23:09:00,0\n2015-09-15 23:19:00,1.44\n2015-09-15 23:24:00,0\n2015-09-15 23:29:00,1\n2015-09-15 23:34:00,1\n2015-09-15 23:39:00,2.44\n2015-09-15 23:44:00,0.61\n2015-09-15 23:49:00,0.89\n2015-09-15 23:54:00,1\n2015-09-16 00:09:00,0.89\n2015-09-16 00:14:00,1.06\n2015-09-16 00:19:00,1.83\n2015-09-16 00:29:00,3.44\n2015-09-16 00:34:00,0\n2015-09-16 00:44:00,0\n2015-09-16 00:49:00,0\n2015-09-16 00:54:00,1.17\n2015-09-16 01:04:00,0.28\n2015-09-16 01:09:00,0.22\n2015-09-16 01:14:00,0.61\n2015-09-16 01:19:00,0.78\n2015-09-16 01:24:00,0\n2015-09-16 01:29:00,0\n2015-09-16 01:34:00,0\n2015-09-16 01:39:00,1.78\n2015-09-16 02:04:00,1.67\n2015-09-16 02:09:00,1.67\n2015-09-16 02:24:00,0.89\n2015-09-16 02:44:00,0\n2015-09-16 02:49:00,0.61\n2015-09-16 02:54:00,1\n2015-09-16 02:59:00,0.78\n2015-09-16 03:04:00,1.28\n2015-09-16 03:14:00,1.17\n2015-09-16 03:19:00,0.78\n2015-09-16 03:29:00,0.89\n2015-09-16 03:34:00,0\n2015-09-16 03:39:00,1.94\n2015-09-16 03:44:00,1.17\n2015-09-16 03:49:00,0.28\n2015-09-16 03:54:00,1.06\n2015-09-16 03:59:00,3.44\n2015-09-16 04:09:00,0.22\n2015-09-16 04:14:00,1.78\n2015-09-16 04:29:00,1.94\n2015-09-16 04:34:00,3.33\n2015-09-16 04:44:00,0.78\n2015-09-16 04:49:00,0.67\n2015-09-16 05:09:00,3.89\n2015-09-16 05:14:00,6.44\n2015-09-16 05:19:00,6.33\n2015-09-16 05:24:00,6.56\n2015-09-16 05:29:00,13.5\n2015-09-16 05:39:00,4\n2015-09-16 05:44:00,5.83\n2015-09-16 05:49:00,8.78\n2015-09-16 05:54:00,9.06\n2015-09-16 05:59:00,8.5\n2015-09-16 06:04:00,9.17\n2015-09-16 06:09:00,11.5\n2015-09-16 06:14:00,10.83\n2015-09-16 06:19:00,12.22\n2015-09-16 06:24:00,17.56\n2015-09-16 06:29:00,13.28\n2015-09-16 06:34:00,16.11\n2015-09-16 06:39:00,11.06\n2015-09-16 06:44:00,14.78\n2015-09-16 06:49:00,10.44\n2015-09-16 06:54:00,11.83\n2015-09-16 06:59:00,14.67\n2015-09-16 07:04:00,17.17\n2015-09-16 07:09:00,14.67\n2015-09-16 07:14:00,10.44\n2015-09-16 07:19:00,17.56\n2015-09-16 07:24:00,11.22\n2015-09-16 07:29:00,10.17\n2015-09-16 07:34:00,12.22\n2015-09-16 07:39:00,8\n2015-09-16 07:44:00,18.67\n2015-09-16 07:49:00,8.89\n2015-09-16 07:54:00,10.28\n2015-09-16 07:59:00,15.83\n2015-09-16 08:04:00,12.61\n2015-09-16 08:09:00,5.28\n2015-09-16 08:14:00,13\n2015-09-16 08:19:00,8.11\n2015-09-16 08:24:00,7.72\n2015-09-16 08:29:00,7.61\n2015-09-16 08:34:00,5.94\n2015-09-16 08:39:00,8.11\n2015-09-16 08:44:00,8.22\n2015-09-16 08:49:00,4.39\n2015-09-16 08:54:00,6.72\n2015-09-16 08:59:00,5.56\n2015-09-16 09:04:00,6.17\n2015-09-16 09:09:00,4\n2015-09-16 09:14:00,6.17\n2015-09-16 09:19:00,2.72\n2015-09-16 09:24:00,8.67\n2015-09-16 09:29:00,3.61\n2015-09-16 09:34:00,9.28\n2015-09-16 09:39:00,5.67\n2015-09-16 09:49:00,3.33\n2015-09-16 09:54:00,6.44\n2015-09-16 09:59:00,3.72\n2015-09-16 10:04:00,1.67\n2015-09-16 10:09:00,3.33\n2015-09-16 10:14:00,2.17\n2015-09-16 10:19:00,6.56\n2015-09-16 10:24:00,4.39\n2015-09-16 10:29:00,3.33\n2015-09-16 10:34:00,2.67\n2015-09-16 10:39:00,1.67\n2015-09-16 10:44:00,8.67\n2015-09-16 10:49:00,3.5\n2015-09-16 10:54:00,3.61\n2015-09-16 10:59:00,4.78\n2015-09-16 11:04:00,2.06\n2015-09-16 11:09:00,3.5\n2015-09-16 11:14:00,6.06\n2015-09-16 11:24:00,3.06\n2015-09-16 11:29:00,1.44\n2015-09-16 11:34:00,1.39\n2015-09-16 11:39:00,2.17\n2015-09-16 11:44:00,5.39\n2015-09-16 11:49:00,1.94\n2015-09-16 11:54:00,2.17\n2015-09-16 11:59:00,2.17\n2015-09-16 12:04:00,4.11\n2015-09-16 12:09:00,4.28\n2015-09-16 12:14:00,1.67\n2015-09-16 12:19:00,6.44\n2015-09-16 12:24:00,3.5\n2015-09-16 12:29:00,4.67\n2015-09-16 12:34:00,2.94\n2015-09-16 12:39:00,2.72\n2015-09-16 12:44:00,2.17\n2015-09-16 12:49:00,1.67\n2015-09-16 12:54:00,4.22\n2015-09-16 12:59:00,2.33\n2015-09-16 13:04:00,2.33\n2015-09-16 13:09:00,1.67\n2015-09-16 13:14:00,4.89\n2015-09-16 13:19:00,2.56\n2015-09-16 13:24:00,4.22\n2015-09-16 13:29:00,2.56\n2015-09-16 13:34:00,1.67\n2015-09-16 13:39:00,6.17\n2015-09-16 13:44:00,1.83\n2015-09-16 13:54:00,4.28\n2015-09-16 13:59:00,3.5\n2015-09-16 14:04:00,2.94\n2015-09-16 14:09:00,8\n2015-09-16 14:14:00,3.44\n2015-09-16 14:19:00,3.83\n2015-09-16 14:24:00,6.83\n2015-09-16 14:29:00,5.94\n2015-09-16 14:30:00,2.94\n2015-09-16 14:35:00,1.44\n2015-09-16 14:40:00,4.5\n2015-09-16 14:50:00,1.39\n2015-09-16 14:55:00,4.11\n2015-09-16 15:00:00,1.17\n2015-09-16 15:05:00,5.28\n2015-09-16 15:10:00,4.11\n2015-09-16 15:15:00,2.83\n2015-09-16 15:20:00,1.83\n2015-09-16 15:25:00,4.89\n2015-09-16 15:30:00,3.61\n2015-09-16 15:35:00,2.17\n2015-09-16 15:40:00,5.78\n2015-09-16 15:45:00,7.5\n2015-09-16 15:50:00,6.06\n2015-09-16 15:55:00,1.06\n2015-09-16 16:00:00,8.67\n2015-09-16 16:05:00,4.11\n2015-09-16 16:10:00,4.28\n2015-09-16 16:15:00,3.06\n2015-09-16 16:20:00,6.06\n2015-09-16 16:25:00,5.83\n2015-09-16 16:30:00,2.44\n2015-09-16 16:35:00,2.28\n2015-09-16 16:40:00,4.61\n2015-09-16 16:45:00,5.56\n2015-09-16 16:55:00,5.83\n2015-09-16 17:00:00,3.11\n2015-09-16 17:05:00,3.89\n2015-09-16 17:10:00,2.83\n2015-09-16 17:15:00,3.44\n2015-09-16 17:20:00,2.44\n2015-09-16 17:25:00,1.44\n2015-09-16 17:30:00,5.56\n2015-09-16 17:35:00,4.78\n2015-09-16 17:45:00,3.61\n2015-09-16 17:50:00,1.39\n2015-09-16 17:55:00,0.67\n2015-09-16 18:00:00,5.94\n2015-09-16 18:05:00,3.83\n2015-09-16 18:10:00,4.61\n2015-09-16 18:15:00,5.83\n2015-09-16 18:20:00,4\n2015-09-16 18:30:00,5.94\n2015-09-16 18:35:00,1.83\n2015-09-16 18:40:00,1.94\n2015-09-16 18:45:00,1.83\n2015-09-16 18:50:00,2.72\n2015-09-16 18:55:00,3.11\n2015-09-16 19:00:00,4.89\n2015-09-16 19:05:00,0.89\n2015-09-16 19:10:00,2.33\n2015-09-16 19:15:00,1.56\n2015-09-16 19:20:00,2.72\n2015-09-16 19:25:00,2.83\n2015-09-16 19:30:00,2.33\n2015-09-16 19:35:00,2.83\n2015-09-16 19:40:00,3.06\n2015-09-16 19:45:00,6.44\n2015-09-16 19:50:00,1.56\n2015-09-16 19:55:00,4.39\n2015-09-16 20:00:00,1.39\n2015-09-16 20:05:00,4.11\n2015-09-16 20:10:00,1.44\n2015-09-16 20:15:00,1.56\n2015-09-16 20:20:00,4.67\n2015-09-16 20:25:00,0.67\n2015-09-16 20:30:00,5.67\n2015-09-16 20:35:00,2.67\n2015-09-16 20:40:00,1.28\n2015-09-16 20:45:00,2.06\n2015-09-16 20:50:00,2.72\n2015-09-16 20:55:00,3.89\n2015-09-16 21:00:00,1.06\n2015-09-16 21:15:00,2.44\n2015-09-16 21:20:00,1.44\n2015-09-16 21:30:00,2.44\n2015-09-16 21:35:00,4.39\n2015-09-16 21:40:00,1.56\n2015-09-16 21:45:00,1.94\n2015-09-16 21:50:00,3.61\n2015-09-16 21:55:00,1.28\n2015-09-16 21:59:00,1.44\n2015-09-16 22:05:00,0\n2015-09-16 22:10:00,1.83\n2015-09-16 22:14:00,0.67\n2015-09-16 22:20:00,0.39\n2015-09-16 22:25:00,1.67\n2015-09-16 22:30:00,1\n2015-09-16 22:35:00,2.06\n2015-09-16 22:40:00,0.39\n2015-09-16 22:45:00,0\n2015-09-16 23:00:00,0.61\n2015-09-16 23:05:00,0\n2015-09-16 23:10:00,0.28\n2015-09-16 23:15:00,0.5\n2015-09-16 23:20:00,0\n2015-09-16 23:40:00,0\n2015-09-16 23:45:00,0\n2015-09-16 23:50:00,0.39\n2015-09-17 00:00:00,1.94\n2015-09-17 00:10:00,1.56\n2015-09-17 00:15:00,2.28\n2015-09-17 00:25:00,0.39\n2015-09-17 00:50:00,0.39\n2015-09-17 00:59:00,2.28\n2015-09-17 01:05:00,1.94\n2015-09-17 01:15:00,1.06\n2015-09-17 01:25:00,0\n2015-09-17 01:40:00,0\n2015-09-17 01:45:00,1.06\n2015-09-17 01:50:00,0.67\n2015-09-17 01:55:00,0\n2015-09-17 02:00:00,0\n2015-09-17 02:05:00,1.28\n2015-09-17 02:15:00,0.67\n2015-09-17 02:20:00,1\n2015-09-17 02:25:00,0.67\n2015-09-17 02:35:00,0.89\n2015-09-17 02:40:00,0\n2015-09-17 02:45:00,2.06\n2015-09-17 02:50:00,0\n2015-09-17 02:55:00,0.5\n2015-09-17 03:00:00,0\n2015-09-17 03:05:00,1.83\n2015-09-17 03:10:00,2.56\n2015-09-17 03:15:00,0\n2015-09-17 03:20:00,0.39\n2015-09-17 03:30:00,0.89\n2015-09-17 03:35:00,2.28\n2015-09-17 03:40:00,0\n2015-09-17 03:45:00,0.89\n2015-09-17 03:50:00,0\n2015-09-17 03:55:00,0.28\n2015-09-17 04:00:00,0\n2015-09-17 04:05:00,0\n2015-09-17 04:10:00,0.28\n2015-09-17 04:15:00,3.33\n2015-09-17 04:20:00,0.78\n2015-09-17 04:25:00,1.39\n2015-09-17 04:30:00,0.89\n2015-09-17 04:35:00,5.28\n2015-09-17 04:40:00,1.83\n2015-09-17 04:45:00,2.83\n2015-09-17 04:50:00,2.28\n2015-09-17 04:55:00,2.28\n2015-09-17 05:00:00,1.83\n2015-09-17 05:05:00,3.33\n2015-09-17 05:10:00,4.67\n2015-09-17 05:15:00,1.28\n2015-09-17 05:20:00,3.89\n2015-09-17 05:25:00,6.56\n2015-09-17 05:30:00,7.44\n2015-09-17 05:35:00,7.06\n2015-09-17 05:40:00,7.61\n2015-09-17 05:45:00,5.56\n2015-09-17 05:50:00,7.5\n2015-09-17 05:55:00,7.72\n2015-09-17 06:00:00,14.06\n2015-09-17 06:05:00,11.06\n2015-09-17 06:10:00,8.61\n2015-09-17 06:15:00,16.33\n2015-09-17 06:20:00,13.28\n2015-09-17 06:25:00,16.61\n2015-09-17 06:30:00,14.44\n2015-09-17 06:35:00,16.78\n2015-09-17 06:40:00,18.17\n2015-09-17 06:45:00,14.67\n2015-09-17 06:50:00,16.78\n2015-09-17 06:55:00,8.89\n2015-09-17 07:00:00,10.83\n2015-09-17 07:05:00,8.5\n2015-09-17 07:10:00,1.28\n2015-09-17 07:15:00,2.83\n2015-09-17 07:20:00,16.78\n2015-09-17 07:25:00,8.11\n2015-09-17 07:30:00,1.28\n2015-09-17 07:35:00,5.39\n2015-09-17 07:40:00,19.17\n2015-09-17 07:45:00,6.67\n2015-09-17 07:50:00,8.11\n2015-09-17 07:55:00,9.39\n2015-09-17 08:00:00,12.89\n2015-09-17 08:05:00,8.67\n2015-09-17 08:10:00,6.94\n2015-09-17 08:15:00,12.72\n2015-09-17 08:20:00,8.67\n2015-09-17 08:25:00,6.06\n2015-09-17 08:30:00,4\n2015-09-17 08:35:00,8.78\n2015-09-17 08:40:00,6.83\n2015-09-17 08:45:00,5.78\n2015-09-17 08:50:00,6.06\n2015-09-17 08:55:00,4.61\n2015-09-17 09:00:00,3.22\n2015-09-17 09:05:00,4.22\n2015-09-17 09:10:00,13.39\n2015-09-17 09:15:00,6.28\n2015-09-17 09:20:00,9.56\n2015-09-17 09:25:00,12.39\n2015-09-17 09:30:00,2.33\n2015-09-17 09:35:00,5\n2015-09-17 09:40:00,6.56\n2015-09-17 09:45:00,4.67\n2015-09-17 09:50:00,2.94\n2015-09-17 09:55:00,6.17\n2015-09-17 10:00:00,1\n2015-09-17 10:05:00,7.11\n2015-09-17 10:10:00,3.61\n2015-09-17 10:15:00,3.22\n2015-09-17 10:20:00,7.61\n2015-09-17 10:25:00,3.06\n2015-09-17 10:30:00,2.06\n2015-09-17 10:35:00,5.83\n2015-09-17 10:40:00,4.22\n2015-09-17 10:45:00,4.5\n2015-09-17 10:50:00,4.5\n2015-09-17 10:55:00,1.44\n2015-09-17 11:05:00,0.67\n2015-09-17 11:10:00,5.56\n2015-09-17 11:15:00,2.56\n2015-09-17 11:20:00,3.33\n2015-09-17 11:25:00,3.61\n2015-09-17 11:30:00,5.78\n2015-09-17 11:35:00,5.17\n2015-09-17 11:40:00,6.56\n2015-09-17 11:45:00,3.72\n2015-09-17 11:50:00,2.28\n2015-09-17 11:55:00,5.39\n2015-09-17 12:00:00,2.06\n2015-09-17 12:05:00,4.78\n2015-09-17 12:10:00,5.94\n2015-09-17 12:15:00,3.83\n2015-09-17 12:20:00,3.22\n2015-09-17 12:25:00,6.94\n2015-09-17 12:30:00,1\n2015-09-17 12:35:00,1.83\n2015-09-17 12:40:00,3.5\n2015-09-17 12:45:00,2.56\n2015-09-17 12:50:00,3.83\n2015-09-17 12:55:00,5\n2015-09-17 13:00:00,3.06\n2015-09-17 13:05:00,1.28\n2015-09-17 13:10:00,2.33\n2015-09-17 13:15:00,2.44\n2015-09-17 13:20:00,5.06\n2015-09-17 13:25:00,2.83\n2015-09-17 13:30:00,4.89\n2015-09-17 13:35:00,1.56\n2015-09-17 13:40:00,2.67\n2015-09-17 13:45:00,2.17\n2015-09-17 13:50:00,5.67\n2015-09-17 13:55:00,2.06\n2015-09-17 14:00:00,3.83\n2015-09-17 14:05:00,5.94\n2015-09-17 14:10:00,3.89\n2015-09-17 14:15:00,5.06\n2015-09-17 14:20:00,6.94\n2015-09-17 14:25:00,0\n2015-09-17 14:30:00,5.39\n2015-09-17 14:34:00,4.67\n2015-09-17 14:39:00,5.67\n2015-09-17 14:44:00,6.06\n2015-09-17 14:49:00,7.22\n2015-09-17 14:54:00,2.94\n2015-09-17 14:58:00,3.06\n2015-09-17 15:04:00,3.44\n2015-09-17 15:08:00,3.89\n2015-09-17 15:13:00,2.56\n2015-09-17 15:18:00,2.72\n2015-09-17 15:23:00,6.28\n2015-09-17 15:28:00,2.83\n2015-09-17 15:34:00,4.11\n2015-09-17 15:38:00,5.78\n2015-09-17 15:43:00,7.89\n2015-09-17 15:48:00,4.22\n2015-09-17 15:49:00,2.83\n2015-09-17 15:54:00,4.5\n2015-09-17 15:59:00,11.11\n2015-09-17 16:04:00,9.28\n2015-09-17 16:09:00,5.06\n2015-09-17 16:14:00,3.44\n2015-09-17 16:19:00,8.5\n2015-09-17 16:24:00,5.56\n"
  },
  {
    "path": "workspace/anomaly_detector/datasets/selected/seasonal/occupancy_t4013.csv",
    "content": "timestamp,value\n2015-09-01 11:30:00,13.56\n2015-09-01 11:35:00,8.33\n2015-09-01 11:40:00,11.78\n2015-09-01 11:55:00,15.28\n2015-09-01 12:00:00,10.06\n2015-09-01 12:05:00,7.44\n2015-09-01 12:10:00,8.11\n2015-09-01 12:15:00,10.72\n2015-09-01 12:20:00,11.83\n2015-09-01 12:25:00,9.61\n2015-09-01 12:30:00,10.22\n2015-09-01 12:35:00,10.72\n2015-09-01 12:45:00,10.28\n2015-09-01 12:50:00,13.72\n2015-09-01 12:55:00,7.39\n2015-09-01 13:05:00,2.61\n2015-09-01 13:10:00,7.33\n2015-09-01 13:15:00,8.5\n2015-09-01 13:20:00,10.56\n2015-09-01 13:25:00,13.78\n2015-09-01 13:35:00,7.78\n2015-09-01 13:45:00,7.72\n2015-09-01 13:50:00,10.11\n2015-09-01 14:00:00,9.56\n2015-09-01 14:05:00,14.94\n2015-09-01 14:10:00,25.89\n2015-09-01 14:15:00,10.17\n2015-09-01 14:30:00,6.39\n2015-09-01 14:35:00,12.89\n2015-09-01 14:40:00,9.06\n2015-09-01 14:50:00,11.67\n2015-09-01 14:55:00,7.94\n2015-09-01 15:00:00,8.17\n2015-09-01 15:05:00,24.72\n2015-09-01 15:10:00,9.06\n2015-09-01 15:25:00,14.89\n2015-09-01 15:30:00,8.28\n2015-09-01 15:35:00,7.83\n2015-09-01 15:40:00,12.28\n2015-09-01 15:45:00,14.94\n2015-09-01 15:55:00,14.39\n2015-09-01 16:00:00,7.5\n2015-09-01 16:05:00,11.5\n2015-09-01 16:10:00,10\n2015-09-01 16:15:00,8.83\n2015-09-01 16:20:00,11.33\n2015-09-01 16:25:00,11.17\n2015-09-01 16:30:00,9.83\n2015-09-01 16:40:00,7.67\n2015-09-01 16:45:00,14.89\n2015-09-01 16:55:00,7.28\n2015-09-01 17:05:00,11.83\n2015-09-01 17:10:00,13.72\n2015-09-01 17:15:00,21.33\n2015-09-01 17:20:00,21.61\n2015-09-01 17:25:00,14.61\n2015-09-01 17:35:00,15.28\n2015-09-01 17:40:00,10.33\n2015-09-01 17:45:00,7.61\n2015-09-01 17:50:00,8.89\n2015-09-01 17:55:00,10.72\n2015-09-01 17:59:00,9.06\n2015-09-01 18:10:00,14\n2015-09-01 18:15:00,14.56\n2015-09-01 18:20:00,8.06\n2015-09-01 18:25:00,4.89\n2015-09-01 18:30:00,7.72\n2015-09-01 18:35:00,9.11\n2015-09-01 18:45:00,6.89\n2015-09-01 18:50:00,9.11\n2015-09-01 19:20:00,8.33\n2015-09-01 19:25:00,5.33\n2015-09-01 19:35:00,6.11\n2015-09-01 19:50:00,4.06\n2015-09-01 20:00:00,7.06\n2015-09-01 20:15:00,5.83\n2015-09-01 20:35:00,8.67\n2015-09-01 20:40:00,5.94\n2015-09-01 20:50:00,3.39\n2015-09-01 20:55:00,5.5\n2015-09-01 21:00:00,9.11\n2015-09-01 21:05:00,12.83\n2015-09-01 21:10:00,6.11\n2015-09-01 21:15:00,5.67\n2015-09-01 21:20:00,6.17\n2015-09-01 21:25:00,2.44\n2015-09-01 21:30:00,4\n2015-09-01 21:35:00,6.72\n2015-09-01 21:59:00,1.44\n2015-09-01 22:10:00,9\n2015-09-01 22:20:00,1.06\n2015-09-01 22:25:00,6.61\n2015-09-01 22:40:00,4.61\n2015-09-01 22:45:00,3.28\n2015-09-01 22:50:00,1.83\n2015-09-01 23:01:00,3.17\n2015-09-01 23:05:00,5.17\n2015-09-01 23:10:00,2.56\n2015-09-01 23:15:00,4.17\n2015-09-01 23:45:00,0.67\n2015-09-02 00:05:00,0.61\n2015-09-02 00:10:00,2.72\n2015-09-02 00:30:00,2.39\n2015-09-02 01:25:00,5.67\n2015-09-02 01:35:00,0.83\n2015-09-02 02:30:00,1.61\n2015-09-02 02:40:00,4.39\n2015-09-02 02:50:00,3.67\n2015-09-02 03:05:00,1.89\n2015-09-02 03:10:00,0.83\n2015-09-02 03:40:00,1.72\n2015-09-02 03:50:00,4.44\n2015-09-02 03:55:00,5.5\n2015-09-02 04:05:00,4.17\n2015-09-02 04:20:00,2.22\n2015-09-02 04:25:00,10.11\n2015-09-02 04:40:00,1.72\n2015-09-02 04:45:00,1.39\n2015-09-02 04:50:00,6.11\n2015-09-02 04:55:00,7.94\n2015-09-02 05:00:00,5.67\n2015-09-02 05:10:00,5.67\n2015-09-02 05:15:00,4.44\n2015-09-02 05:20:00,6.06\n2015-09-02 05:30:00,2.17\n2015-09-02 05:35:00,5.61\n2015-09-02 05:45:00,6.44\n2015-09-02 05:50:00,8\n2015-09-02 05:55:00,10.33\n2015-09-02 06:00:00,14.28\n2015-09-02 06:05:00,14.06\n2015-09-02 06:10:00,11.61\n2015-09-02 06:20:00,12.94\n2015-09-02 06:25:00,12.39\n2015-09-02 06:30:00,16.78\n2015-09-02 06:40:00,8.67\n2015-09-02 06:45:00,21.72\n2015-09-02 06:50:00,10.67\n2015-09-02 06:55:00,12.28\n2015-09-02 07:00:00,16.17\n2015-09-02 07:05:00,25.61\n2015-09-02 07:10:00,25.78\n2015-09-02 07:15:00,9.44\n2015-09-02 07:20:00,8.83\n2015-09-02 07:25:00,11.72\n2015-09-02 07:30:00,12.17\n2015-09-02 07:35:00,14.33\n2015-09-02 07:40:00,12.11\n2015-09-02 07:45:00,13.67\n2015-09-02 07:50:00,9.17\n2015-09-02 07:55:00,15.06\n2015-09-02 08:00:00,19.56\n2015-09-02 08:05:00,18\n2015-09-02 08:10:00,14.17\n2015-09-02 08:15:00,8.33\n2015-09-02 08:20:00,15.72\n2015-09-02 08:25:00,12.83\n2015-09-02 08:30:00,21.22\n2015-09-02 08:35:00,17.39\n2015-09-02 08:40:00,16.11\n2015-09-02 08:45:00,18.83\n2015-09-02 08:50:00,16.89\n2015-09-02 08:55:00,18.61\n2015-09-02 09:00:00,12.78\n2015-09-02 09:05:00,13.33\n2015-09-02 09:10:00,20.17\n2015-09-02 09:15:00,21.56\n2015-09-02 09:25:00,11.78\n2015-09-02 09:30:00,12.78\n2015-09-02 09:35:00,12.17\n2015-09-02 09:40:00,7.78\n2015-09-02 09:55:00,6.56\n2015-09-02 10:00:00,13.06\n2015-09-02 10:05:00,15.06\n2015-09-02 10:10:00,11.72\n2015-09-02 10:15:00,6.5\n2015-09-02 10:20:00,12.72\n2015-09-02 10:25:00,9.56\n2015-09-02 10:30:00,13.78\n2015-09-02 10:35:00,12.33\n2015-09-02 10:40:00,9.22\n2015-09-02 10:45:00,10.39\n2015-09-02 10:50:00,5.06\n2015-09-02 10:55:00,5.72\n2015-09-02 11:00:00,10.56\n2015-09-02 11:10:00,12.72\n2015-09-02 11:15:00,18.33\n2015-09-02 11:25:00,8.78\n2015-09-02 11:30:00,9.61\n2015-09-02 11:40:00,13.33\n2015-09-02 11:45:00,7\n2015-09-02 11:50:00,9.61\n2015-09-02 11:55:00,11.78\n2015-09-02 12:00:00,3.06\n2015-09-02 12:05:00,13.33\n2015-09-02 12:15:00,14.28\n2015-09-02 12:20:00,14.33\n2015-09-02 12:25:00,6.89\n2015-09-02 12:30:00,11.22\n2015-09-02 12:35:00,8.17\n2015-09-02 12:40:00,8.28\n2015-09-02 12:50:00,15.11\n2015-09-02 12:55:00,13.06\n2015-09-02 13:00:00,12.39\n2015-09-02 13:05:00,13.28\n2015-09-02 13:10:00,6.06\n2015-09-02 13:15:00,17.61\n2015-09-02 13:20:00,13.22\n2015-09-02 13:25:00,10.11\n2015-09-02 13:30:00,8.83\n2015-09-02 13:35:00,12.89\n2015-09-02 13:40:00,4.61\n2015-09-02 13:55:00,15.28\n2015-09-02 14:00:00,6.56\n2015-09-02 14:05:00,9.61\n2015-09-02 14:10:00,13.67\n2015-09-02 14:15:00,8.78\n2015-09-02 14:20:00,11.78\n2015-09-02 14:25:00,9.94\n2015-09-02 14:30:00,11.33\n2015-09-02 14:35:00,12.44\n2015-09-02 14:40:00,12.61\n2015-09-02 14:45:00,10.78\n2015-09-02 14:50:00,10.28\n2015-09-02 15:00:00,14.17\n2015-09-02 15:05:00,13.72\n2015-09-02 15:10:00,12.67\n2015-09-02 15:15:00,14.17\n2015-09-02 15:20:00,15.39\n2015-09-02 15:25:00,13.44\n2015-09-02 15:30:00,10.33\n2015-09-02 15:35:00,12.06\n2015-09-02 15:40:00,11.17\n2015-09-02 15:45:00,14\n2015-09-02 15:50:00,11.78\n2015-09-02 15:55:00,13.61\n2015-09-02 16:00:00,7.44\n2015-09-02 16:05:00,9.78\n2015-09-02 16:10:00,11.67\n2015-09-02 16:15:00,8.56\n2015-09-02 16:20:00,7.5\n2015-09-02 16:25:00,12.22\n2015-09-02 16:30:00,12.44\n2015-09-02 16:35:00,7.89\n2015-09-02 16:40:00,17.72\n2015-09-02 16:45:00,13.94\n2015-09-02 16:50:00,11.94\n2015-09-02 16:55:00,13.39\n2015-09-02 17:00:00,8.94\n2015-09-02 17:05:00,14.33\n2015-09-02 17:10:00,14.67\n2015-09-02 17:15:00,11.17\n2015-09-02 17:20:00,18.5\n2015-09-02 17:25:00,5.56\n2015-09-02 17:30:00,10.11\n2015-09-02 17:35:00,10.72\n2015-09-02 17:40:00,8.44\n2015-09-02 17:45:00,10.17\n2015-09-02 17:50:00,9.83\n2015-09-02 18:05:00,11.5\n2015-09-02 18:10:00,9.89\n2015-09-02 18:15:00,11.78\n2015-09-02 18:30:00,9.17\n2015-09-02 18:35:00,6.72\n2015-09-02 18:45:00,8.11\n2015-09-02 18:55:00,8.06\n2015-09-02 19:00:00,3.78\n2015-09-02 19:05:00,7.11\n2015-09-02 19:10:00,6.78\n2015-09-02 19:21:00,6.5\n2015-09-02 19:36:00,6.56\n2015-09-02 19:41:00,4.78\n2015-09-02 19:51:00,3.72\n2015-09-02 20:01:00,3.78\n2015-09-02 20:06:00,10.67\n2015-09-02 20:11:00,5.67\n2015-09-02 20:16:00,13.33\n2015-09-02 20:21:00,9.44\n2015-09-02 20:26:00,10.22\n2015-09-02 20:36:00,8\n2015-09-02 20:41:00,7.78\n2015-09-02 20:46:00,5.11\n2015-09-02 20:56:00,3.83\n2015-09-02 21:06:00,2.94\n2015-09-02 21:21:00,6.56\n2015-09-02 21:26:00,3.72\n2015-09-02 21:36:00,5.56\n2015-09-02 21:51:00,4.78\n2015-09-02 22:01:00,5.11\n2015-09-02 22:06:00,5.11\n2015-09-02 22:11:00,9.44\n2015-09-02 22:26:00,3.39\n2015-09-02 22:41:00,5.83\n2015-09-02 22:51:00,1.39\n2015-09-02 23:01:00,3.22\n2015-09-02 23:11:00,1.61\n2015-09-02 23:16:00,5.17\n2015-09-02 23:26:00,1.61\n2015-09-02 23:41:00,1.78\n2015-09-03 00:11:00,0.67\n2015-09-03 00:21:00,2.06\n2015-09-03 00:26:00,3.89\n2015-09-03 00:36:00,2.61\n2015-09-03 00:56:00,3.5\n2015-09-03 01:01:00,4.33\n2015-09-03 01:06:00,1.22\n2015-09-03 01:16:00,1.94\n2015-09-03 01:31:00,2.44\n2015-09-03 01:56:00,2.28\n2015-09-03 02:36:00,2.72\n2015-09-03 02:46:00,2.94\n2015-09-03 02:56:00,3.22\n2015-09-03 03:16:00,0.72\n2015-09-03 03:31:00,0.56\n2015-09-03 03:41:00,4.78\n2015-09-03 03:46:00,1.61\n2015-09-03 04:11:00,1.72\n2015-09-03 04:31:00,2.72\n2015-09-03 04:46:00,2.22\n2015-09-03 05:01:00,1.83\n2015-09-03 05:11:00,5.83\n2015-09-03 05:31:00,8.17\n2015-09-03 05:36:00,10.67\n2015-09-03 05:41:00,3.17\n2015-09-03 05:51:00,7.56\n2015-09-03 05:56:00,6.11\n2015-09-03 06:01:00,6.44\n2015-09-03 06:06:00,4.11\n2015-09-03 06:11:00,2.17\n2015-09-03 06:16:00,5.06\n2015-09-03 06:21:00,12\n2015-09-03 06:26:00,11.83\n2015-09-03 06:36:00,13.56\n2015-09-03 06:41:00,4.56\n2015-09-03 06:51:00,7\n2015-09-03 07:06:00,8\n2015-09-03 07:11:00,12.33\n2015-09-03 07:16:00,12.44\n2015-09-03 07:21:00,13.06\n2015-09-03 07:26:00,6.28\n2015-09-03 07:31:00,11.5\n2015-09-03 07:36:00,11.33\n2015-09-03 07:41:00,8.39\n2015-09-03 07:46:00,12.78\n2015-09-03 07:51:00,11.28\n2015-09-03 07:56:00,8.89\n2015-09-03 08:01:00,8.33\n2015-09-03 08:06:00,17.61\n2015-09-03 08:31:00,10.83\n2015-09-03 08:36:00,12.22\n2015-09-03 08:41:00,12.67\n2015-09-03 08:46:00,7.5\n2015-09-03 08:51:00,13\n2015-09-03 09:01:00,10.78\n2015-09-03 09:11:00,12.22\n2015-09-03 09:16:00,18.5\n2015-09-03 09:21:00,13.72\n2015-09-03 09:26:00,12.06\n2015-09-03 09:31:00,9.44\n2015-09-03 09:36:00,7.72\n2015-09-03 09:46:00,8.72\n2015-09-03 09:51:00,11.94\n2015-09-03 09:56:00,5.5\n2015-09-03 10:01:00,7.39\n2015-09-03 10:06:00,17.28\n2015-09-03 10:11:00,12.06\n2015-09-03 10:21:00,7.5\n2015-09-03 10:26:00,6.22\n2015-09-03 10:36:00,7.17\n2015-09-03 10:41:00,7.94\n2015-09-03 10:46:00,13.61\n2015-09-03 10:51:00,10.56\n2015-09-03 10:56:00,7.22\n2015-09-03 11:06:00,12.67\n2015-09-03 11:11:00,10.72\n2015-09-03 11:16:00,11.83\n2015-09-03 11:26:00,10.11\n2015-09-03 11:31:00,8.33\n2015-09-03 11:36:00,16.72\n2015-09-03 11:41:00,10.44\n2015-09-03 11:46:00,11.39\n2015-09-03 11:51:00,8.5\n2015-09-03 12:01:00,8.22\n2015-09-03 12:06:00,10.44\n2015-09-03 12:11:00,9.67\n2015-09-03 12:16:00,7.56\n2015-09-03 12:21:00,6.17\n2015-09-03 12:26:00,10.39\n2015-09-03 12:31:00,7.67\n2015-09-03 12:36:00,9.39\n2015-09-03 12:41:00,12.17\n2015-09-03 12:51:00,15.5\n2015-09-03 12:56:00,5.06\n2015-09-03 13:06:00,6.06\n2015-09-03 13:11:00,6.17\n2015-09-03 13:26:00,6.44\n2015-09-03 13:31:00,9.5\n2015-09-03 13:36:00,13.39\n2015-09-03 13:41:00,8.89\n2015-09-03 13:46:00,9.44\n2015-09-03 13:51:00,8\n2015-09-03 14:01:00,11.11\n2015-09-03 14:06:00,10.28\n2015-09-03 14:11:00,6.5\n2015-09-03 14:16:00,6.72\n2015-09-03 14:21:00,14.28\n2015-09-03 14:26:00,1.17\n2015-09-03 14:31:00,8.44\n2015-09-03 14:41:00,12.33\n2015-09-03 14:51:00,12.06\n2015-09-03 14:56:00,12.28\n2015-09-03 15:01:00,8.06\n2015-09-03 15:06:00,9.44\n2015-09-03 15:11:00,12.28\n2015-09-03 15:21:00,6.72\n2015-09-03 15:26:00,9.33\n2015-09-03 15:36:00,12.17\n2015-09-03 15:41:00,8.83\n2015-09-03 15:51:00,6.72\n2015-09-03 15:56:00,11.33\n2015-09-03 16:01:00,3.89\n2015-09-03 16:06:00,8.56\n2015-09-03 16:11:00,16.06\n2015-09-03 16:16:00,8.83\n2015-09-03 16:26:00,6.78\n2015-09-03 16:36:00,10.33\n2015-09-03 16:41:00,13.89\n2015-09-03 16:46:00,9.72\n2015-09-03 16:51:00,4.17\n2015-09-03 17:01:00,4\n2015-09-03 17:06:00,6.22\n2015-09-03 17:11:00,8.33\n2015-09-03 17:21:00,9.28\n2015-09-03 17:26:00,10.28\n2015-09-03 17:36:00,4.39\n2015-09-03 17:41:00,6.06\n2015-09-03 17:46:00,5.06\n2015-09-03 17:51:00,13.94\n2015-09-03 17:56:00,9.17\n2015-09-03 18:01:00,5.72\n2015-09-03 18:06:00,5.5\n2015-09-03 18:11:00,4.5\n2015-09-03 18:16:00,5.67\n2015-09-03 18:21:00,11.11\n2015-09-03 18:26:00,8.44\n2015-09-03 18:31:00,11.17\n2015-09-03 18:36:00,5.72\n2015-09-03 18:46:00,7.67\n2015-09-03 18:51:00,5\n2015-09-03 18:56:00,5.94\n2015-09-03 19:01:00,4.83\n2015-09-03 19:06:00,4.83\n2015-09-03 19:11:00,7.39\n2015-09-03 19:16:00,5.72\n2015-09-03 19:21:00,4.56\n2015-09-03 19:31:00,2.17\n2015-09-03 19:42:00,7.11\n2015-09-03 19:47:00,4.17\n2015-09-03 19:57:00,4.44\n2015-09-03 20:02:00,1.67\n2015-09-03 20:07:00,4.06\n2015-09-03 20:17:00,4.06\n2015-09-03 20:42:00,6.33\n2015-09-03 20:47:00,6.06\n2015-09-03 20:57:00,2.44\n2015-09-03 21:07:00,5.61\n2015-09-03 21:12:00,3.44\n2015-09-03 21:17:00,8.72\n2015-09-03 21:22:00,3.22\n2015-09-03 21:27:00,2\n2015-09-03 21:32:00,4.67\n2015-09-03 21:37:00,6.94\n2015-09-03 21:42:00,4.11\n2015-09-03 21:47:00,5.06\n2015-09-03 22:02:00,8.67\n2015-09-03 22:12:00,6.89\n2015-09-03 22:22:00,5.11\n2015-09-03 23:02:00,1.44\n2015-09-03 23:22:00,4.33\n2015-09-03 23:37:00,1.94\n2015-09-03 23:42:00,0.83\n2015-09-03 23:47:00,0.78\n2015-09-04 00:02:00,2.61\n2015-09-04 00:17:00,4.44\n2015-09-04 00:27:00,0.67\n2015-09-04 01:02:00,0.94\n2015-09-04 01:17:00,3.11\n2015-09-04 01:37:00,3.78\n2015-09-04 01:42:00,2.89\n2015-09-04 01:57:00,4.61\n2015-09-04 02:02:00,3.44\n2015-09-04 02:22:00,3.67\n2015-09-04 03:57:00,1.22\n2015-09-04 04:12:00,4.06\n2015-09-04 04:17:00,0.89\n2015-09-04 04:22:00,3.5\n2015-09-04 04:27:00,1.06\n2015-09-04 04:32:00,3.72\n2015-09-04 04:37:00,3\n2015-09-04 04:52:00,3.78\n2015-09-04 05:17:00,2.94\n2015-09-04 05:22:00,3.06\n2015-09-04 05:27:00,2.17\n2015-09-04 05:42:00,7.28\n2015-09-04 05:52:00,7.11\n2015-09-04 05:57:00,5.61\n2015-09-04 06:02:00,4.61\n2015-09-04 06:07:00,6.39\n2015-09-04 06:12:00,10.06\n2015-09-04 06:17:00,11.78\n2015-09-04 06:22:00,7.06\n2015-09-04 06:27:00,5.11\n2015-09-04 06:32:00,7.11\n2015-09-04 06:37:00,10.28\n2015-09-04 06:42:00,7.89\n2015-09-04 06:47:00,11.61\n2015-09-04 06:52:00,9.44\n2015-09-04 06:57:00,7.61\n2015-09-04 07:02:00,3.22\n2015-09-04 07:07:00,7.33\n2015-09-04 07:12:00,13.67\n2015-09-04 07:17:00,10.17\n2015-09-04 07:22:00,10.17\n2015-09-04 07:32:00,13.17\n2015-09-04 07:42:00,11.5\n2015-09-04 07:47:00,11.11\n2015-09-04 08:07:00,6.17\n2015-09-04 08:12:00,7.17\n2015-09-04 08:17:00,13.78\n2015-09-04 08:22:00,9.17\n2015-09-04 08:27:00,7.83\n2015-09-04 08:32:00,9.67\n2015-09-04 08:37:00,10.72\n2015-09-04 08:42:00,13.17\n2015-09-04 08:47:00,9.22\n2015-09-04 08:57:00,8\n2015-09-04 09:02:00,9.67\n2015-09-04 09:07:00,3.67\n2015-09-04 09:22:00,7\n2015-09-04 09:27:00,7.06\n2015-09-04 09:32:00,12.06\n2015-09-04 09:42:00,8.78\n2015-09-04 09:47:00,11.33\n2015-09-04 09:52:00,13.89\n2015-09-04 09:57:00,6\n2015-09-04 10:07:00,7.11\n2015-09-04 10:12:00,5.17\n2015-09-04 10:22:00,9\n2015-09-04 10:27:00,11.11\n2015-09-04 10:32:00,6.94\n2015-09-04 10:42:00,9.72\n2015-09-04 10:52:00,6\n2015-09-04 10:57:00,9.06\n2015-09-04 11:02:00,7.39\n2015-09-04 11:12:00,6\n2015-09-04 11:17:00,9.89\n2015-09-04 11:22:00,4.78\n2015-09-04 11:27:00,10.56\n2015-09-04 11:32:00,8.33\n2015-09-04 11:37:00,15.28\n2015-09-04 11:42:00,11.5\n2015-09-04 11:52:00,6.94\n2015-09-04 11:57:00,6.11\n2015-09-04 12:27:00,6.22\n2015-09-04 12:37:00,7.28\n2015-09-04 12:47:00,7.44\n2015-09-04 13:12:00,10.94\n2015-09-04 13:17:00,5.39\n2015-09-04 13:22:00,7.33\n2015-09-04 13:27:00,9.11\n2015-09-04 13:37:00,8.78\n2015-09-04 13:47:00,2.22\n2015-09-04 14:02:00,3.22\n2015-09-04 14:12:00,6.56\n2015-09-04 14:17:00,6.72\n2015-09-04 14:22:00,2.33\n2015-09-04 14:27:00,10.72\n2015-09-04 14:37:00,4.67\n2015-09-04 14:47:00,9.44\n2015-09-04 14:52:00,6.28\n2015-09-04 14:57:00,6.5\n2015-09-04 15:07:00,5\n2015-09-04 15:12:00,10.06\n2015-09-04 15:17:00,9.5\n2015-09-04 15:27:00,9\n2015-09-04 15:32:00,6.22\n2015-09-04 15:37:00,7\n2015-09-04 15:52:00,15\n2015-09-04 15:57:00,7.28\n2015-09-04 16:07:00,5.17\n2015-09-04 16:12:00,4.17\n2015-09-04 16:17:00,10.78\n2015-09-04 16:22:00,14.33\n2015-09-04 16:27:00,4.17\n2015-09-04 16:37:00,8.28\n2015-09-04 17:02:00,5.56\n2015-09-04 17:07:00,10.72\n2015-09-04 17:12:00,5.06\n2015-09-04 17:17:00,3.33\n2015-09-04 17:22:00,3.78\n2015-09-04 17:32:00,6.22\n2015-09-04 17:37:00,7.83\n2015-09-04 17:42:00,11.83\n2015-09-04 17:52:00,6\n2015-09-04 18:02:00,6.83\n2015-09-04 18:07:00,5.89\n2015-09-04 18:12:00,9.67\n2015-09-04 18:17:00,8.11\n2015-09-04 18:27:00,7.78\n2015-09-04 18:32:00,5.06\n2015-09-04 18:42:00,10.83\n2015-09-04 18:47:00,6.39\n2015-09-04 18:52:00,4.83\n2015-09-04 18:57:00,2.61\n2015-09-04 19:12:00,2.44\n2015-09-04 19:22:00,3.39\n2015-09-04 19:37:00,3.56\n2015-09-04 19:47:00,4.56\n2015-09-04 19:52:00,6.67\n2015-09-04 19:57:00,1.78\n2015-09-04 20:02:00,8.61\n2015-09-04 20:12:00,2\n2015-09-04 20:17:00,10.89\n2015-09-04 20:18:00,3.83\n2015-09-04 20:23:00,6.5\n2015-09-04 20:28:00,3.78\n2015-09-04 20:33:00,3.83\n2015-09-04 21:03:00,5.11\n2015-09-04 21:08:00,3.56\n2015-09-04 21:13:00,2.28\n2015-09-04 21:18:00,5.22\n2015-09-04 21:23:00,4.22\n2015-09-04 21:28:00,1.72\n2015-09-04 21:38:00,2.89\n2015-09-04 21:43:00,7\n2015-09-04 21:48:00,2.94\n2015-09-04 21:53:00,6.67\n2015-09-04 22:03:00,3\n2015-09-04 22:08:00,1.11\n2015-09-04 22:13:00,4.83\n2015-09-04 22:23:00,3.56\n2015-09-08 10:44:00,10.06\n2015-09-08 10:54:00,5.11\n2015-09-08 10:59:00,9.94\n2015-09-08 11:04:00,3.56\n2015-09-08 11:14:00,5.5\n2015-09-08 11:19:00,6.61\n2015-09-08 11:24:00,6.78\n2015-09-08 11:29:00,11.11\n2015-09-08 11:34:00,7.56\n2015-09-08 11:49:00,15\n2015-09-08 11:54:00,8.72\n2015-09-08 11:59:00,11.56\n2015-09-08 12:04:00,10.39\n2015-09-08 12:09:00,14.11\n2015-09-08 12:19:00,8.39\n2015-09-08 12:24:00,9.11\n2015-09-08 12:27:00,2.5\n2015-09-08 12:32:00,9.17\n2015-09-08 12:36:00,7.11\n2015-09-08 12:46:00,12.83\n2015-09-08 12:56:00,5.94\n2015-09-08 13:01:00,6.67\n2015-09-08 13:06:00,5\n2015-09-08 13:16:00,8.67\n2015-09-08 13:21:00,8.94\n2015-09-08 13:26:00,10.44\n2015-09-08 13:36:00,10.5\n2015-09-08 13:41:00,12.28\n2015-09-08 13:51:00,15.22\n2015-09-08 13:56:00,7.17\n2015-09-08 14:00:00,8.11\n2015-09-08 14:06:00,11.56\n2015-09-08 14:11:00,4.83\n2015-09-08 14:21:00,12.28\n2015-09-08 14:26:00,10.67\n2015-09-08 14:31:00,9.94\n2015-09-08 14:36:00,10.22\n2015-09-08 14:41:00,8.28\n2015-09-08 14:46:00,4.28\n2015-09-08 14:51:00,6.06\n2015-09-08 14:56:00,9.22\n2015-09-08 15:01:00,9.5\n2015-09-08 15:06:00,10.89\n2015-09-08 15:11:00,8.17\n2015-09-08 15:16:00,9.5\n2015-09-08 15:21:00,6.33\n2015-09-08 15:29:00,8.11\n2015-09-08 16:15:00,6.5\n2015-09-08 16:36:00,6.17\n2015-09-08 16:41:00,13.06\n2015-09-08 16:46:00,9.33\n2015-09-08 16:51:00,10.72\n2015-09-08 16:56:00,9.56\n2015-09-08 17:11:00,6.83\n2015-09-08 17:16:00,9.56\n2015-09-08 17:21:00,6.33\n2015-09-08 17:26:00,7.28\n2015-09-08 17:31:00,7.22\n2015-09-08 17:36:00,6.72\n2015-09-08 17:41:00,11.28\n2015-09-08 17:46:00,11.78\n2015-09-08 17:51:00,5.56\n2015-09-08 17:56:00,5.06\n2015-09-08 17:57:00,6.56\n2015-09-08 18:26:00,5.22\n2015-09-08 18:31:00,6.67\n2015-09-08 18:36:00,4\n2015-09-08 18:41:00,4.56\n2015-09-08 18:46:00,10.94\n2015-09-08 18:51:00,12.44\n2015-09-08 19:01:00,6.33\n2015-09-08 19:06:00,8.89\n2015-09-08 19:11:00,13.56\n2015-09-08 19:31:00,6.94\n2015-09-08 19:36:00,9.17\n2015-09-08 19:46:00,6.28\n2015-09-08 19:51:00,5.72\n2015-09-08 20:06:00,4.67\n2015-09-08 20:16:00,5.11\n2015-09-08 20:26:00,3.56\n2015-09-08 20:36:00,9.5\n2015-09-08 20:46:00,2.83\n2015-09-08 20:51:00,5.89\n2015-09-08 21:01:00,2.72\n2015-09-08 21:06:00,1.56\n2015-09-08 21:11:00,4.61\n2015-09-08 21:26:00,3.44\n2015-09-08 21:31:00,6.06\n2015-09-08 21:36:00,4.22\n2015-09-08 21:41:00,7.06\n2015-09-08 21:46:00,3\n2015-09-08 21:56:00,5.06\n2015-09-08 22:01:00,6.28\n2015-09-08 22:06:00,1.89\n2015-09-08 22:12:00,2.67\n2015-09-08 22:26:00,2.33\n2015-09-08 22:36:00,4.5\n2015-09-08 22:51:00,4.17\n2015-09-08 22:56:00,1.78\n2015-09-08 23:01:00,1.67\n2015-09-08 23:06:00,2.89\n2015-09-08 23:11:00,2.61\n2015-09-09 00:01:00,4.44\n2015-09-09 00:11:00,0.83\n2015-09-09 00:36:00,2.72\n2015-09-09 01:01:00,3.06\n2015-09-09 01:11:00,1.94\n2015-09-09 01:51:00,0.61\n2015-09-09 02:06:00,0.83\n2015-09-09 02:31:00,3.56\n2015-09-09 02:46:00,2.44\n2015-09-09 06:04:00,6.83\n2015-09-09 07:34:00,15.11\n2015-09-09 09:48:00,6.61\n2015-09-09 09:58:00,12.06\n2015-09-09 10:08:00,7.33\n2015-09-09 10:13:00,5.83\n2015-09-09 10:18:00,12.06\n2015-09-09 10:23:00,8.44\n2015-09-09 10:33:00,5.94\n2015-09-09 10:38:00,8.17\n2015-09-09 10:43:00,7.61\n2015-09-09 10:48:00,8.83\n2015-09-09 10:53:00,6.22\n2015-09-09 10:58:00,5.17\n2015-09-09 11:03:00,10.78\n2015-09-09 11:08:00,10.89\n2015-09-09 11:13:00,7.89\n2015-09-09 11:18:00,6.78\n2015-09-09 11:28:00,4.83\n2015-09-09 11:33:00,8.5\n2015-09-09 11:38:00,9.11\n2015-09-09 11:43:00,10.56\n2015-09-09 11:48:00,3.89\n2015-09-09 11:53:00,16.94\n2015-09-09 11:58:00,10.89\n2015-09-09 12:03:00,6.28\n2015-09-09 12:08:00,10.5\n2015-09-09 12:13:00,6.56\n2015-09-09 12:18:00,10.67\n2015-09-09 12:23:00,13.06\n2015-09-09 12:28:00,10.06\n2015-09-09 12:33:00,10.5\n2015-09-09 12:38:00,6.17\n2015-09-09 12:43:00,6.89\n2015-09-09 12:48:00,9.33\n2015-09-09 12:53:00,3.94\n2015-09-09 12:58:00,11\n2015-09-09 13:08:00,11.67\n2015-09-09 13:13:00,6.22\n2015-09-09 13:18:00,11\n2015-09-09 13:23:00,8.11\n2015-09-09 13:28:00,8.33\n2015-09-09 13:33:00,9.06\n2015-09-09 13:38:00,3.67\n2015-09-09 13:43:00,6.44\n2015-09-09 13:53:00,7.28\n2015-09-09 13:58:00,5.39\n2015-09-09 14:03:00,7.72\n2015-09-09 14:08:00,5\n2015-09-09 14:13:00,1.5\n2015-09-09 14:18:00,10.78\n2015-09-09 14:23:00,5.5\n2015-09-09 14:33:00,4.06\n2015-09-09 14:38:00,11.06\n2015-09-09 14:43:00,2.56\n2015-09-09 14:48:00,7.78\n2015-09-09 14:53:00,11.28\n2015-09-09 14:58:00,5.28\n2015-09-09 15:03:00,11.11\n2015-09-09 15:13:00,7.28\n2015-09-09 15:18:00,10.44\n2015-09-09 15:23:00,5.06\n2015-09-09 15:28:00,9.28\n2015-09-09 15:33:00,8.39\n2015-09-09 15:48:00,9.5\n2015-09-09 15:53:00,5.11\n2015-09-09 16:08:00,8.67\n2015-09-09 16:13:00,7.22\n2015-09-09 16:18:00,6.67\n2015-09-09 16:28:00,6.22\n2015-09-09 16:33:00,7\n2015-09-09 16:38:00,11.22\n2015-09-09 16:43:00,6.89\n2015-09-09 16:48:00,9.06\n2015-09-09 16:53:00,6.61\n2015-09-09 16:58:00,12.89\n2015-09-09 17:08:00,6.94\n2015-09-09 17:18:00,11.94\n2015-09-09 17:23:00,12.17\n2015-09-09 17:28:00,8.72\n2015-09-09 17:33:00,12.11\n2015-09-09 17:38:00,10.39\n2015-09-09 17:43:00,5.11\n2015-09-09 17:58:00,5.33\n2015-09-09 18:03:00,8.72\n2015-09-09 18:08:00,10.67\n2015-09-09 18:23:00,6.17\n2015-09-09 18:28:00,4.06\n2015-09-09 18:33:00,7.28\n2015-09-09 18:38:00,3.22\n2015-09-09 18:48:00,7.94\n2015-09-09 18:58:00,4.44\n2015-09-09 19:03:00,5.83\n2015-09-09 19:08:00,4.83\n2015-09-09 19:13:00,6.39\n2015-09-09 19:18:00,10.33\n2015-09-09 19:23:00,4.56\n2015-09-09 19:28:00,3.06\n2015-09-09 19:33:00,6.06\n2015-09-09 19:43:00,3.28\n2015-09-09 19:48:00,1.67\n2015-09-09 19:58:00,5.56\n2015-09-09 20:23:00,1.33\n2015-09-09 20:28:00,2.56\n2015-09-09 20:33:00,6.5\n2015-09-09 20:38:00,0.89\n2015-09-09 20:43:00,13.17\n2015-09-09 20:48:00,4.83\n2015-09-09 20:58:00,3.94\n2015-09-09 21:03:00,3.78\n2015-09-09 21:13:00,2.44\n2015-09-09 21:18:00,6\n2015-09-09 21:28:00,6.89\n2015-09-09 21:43:00,2.33\n2015-09-09 21:48:00,4.17\n2015-09-09 21:53:00,0.56\n2015-09-09 21:58:00,12.89\n2015-09-09 22:03:00,5.22\n2015-09-09 22:08:00,3.33\n2015-09-09 22:13:00,0.78\n2015-09-09 22:23:00,2.56\n2015-09-09 22:28:00,0.94\n2015-09-09 22:46:00,2.17\n2015-09-09 23:18:00,2.06\n2015-09-09 23:23:00,3.44\n2015-09-09 23:28:00,5.06\n2015-09-09 23:33:00,0.67\n2015-09-09 23:38:00,0.67\n2015-09-09 23:48:00,3.06\n2015-09-10 00:03:00,2.61\n2015-09-10 00:13:00,3.06\n2015-09-10 00:18:00,2.11\n2015-09-10 00:23:00,1.61\n2015-09-10 01:48:00,0.94\n2015-09-10 01:53:00,0.72\n2015-09-10 02:08:00,5.11\n2015-09-10 02:53:00,0.78\n2015-09-10 03:22:00,0.72\n2015-09-10 03:52:00,2.67\n2015-09-10 04:34:00,1.06\n2015-09-10 05:28:00,6.06\n2015-09-10 05:33:00,2.56\n2015-09-10 05:33:00,8.94\n2015-09-10 05:38:00,5.61\n2015-09-10 05:45:00,11.89\n2015-09-10 08:00:00,14.67\n2015-09-10 08:13:00,12.94\n2015-09-10 08:18:00,12.83\n2015-09-10 08:23:00,14.22\n2015-09-10 08:28:00,13\n2015-09-10 08:38:00,8.11\n2015-09-10 08:43:00,17.78\n2015-09-10 08:48:00,14.11\n2015-09-10 08:53:00,11.22\n2015-09-10 08:58:00,10.67\n2015-09-10 09:03:00,6.83\n2015-09-10 09:13:00,14.39\n2015-09-10 09:18:00,6.83\n2015-09-10 09:23:00,15.94\n2015-09-10 09:28:00,10.22\n2015-09-10 09:33:00,14.78\n2015-09-10 09:38:00,10.33\n2015-09-10 09:43:00,3.67\n2015-09-10 09:48:00,6.83\n2015-09-10 09:52:00,6.5\n2015-09-10 09:57:00,3.44\n2015-09-10 10:02:00,3.22\n2015-09-10 10:07:00,11.28\n2015-09-10 10:12:00,7.28\n2015-09-10 10:17:00,7.44\n2015-09-10 10:27:00,8.5\n2015-09-10 10:32:00,9.28\n2015-09-10 10:37:00,9.78\n2015-09-10 10:42:00,9.61\n2015-09-10 10:47:00,7.61\n2015-09-10 10:52:00,11.11\n2015-09-10 10:57:00,8.83\n2015-09-10 11:02:00,10.94\n2015-09-10 11:07:00,9.78\n2015-09-10 11:12:00,8.44\n2015-09-10 11:17:00,7\n2015-09-10 11:22:00,10.94\n2015-09-10 11:27:00,12.94\n2015-09-10 11:32:00,6.78\n2015-09-10 11:37:00,10.61\n2015-09-10 11:42:00,11.28\n2015-09-10 11:47:00,10.61\n2015-09-10 11:52:00,7.17\n2015-09-10 11:57:00,12.5\n2015-09-10 12:02:00,8.5\n2015-09-10 12:12:00,9.06\n2015-09-10 12:17:00,9.5\n2015-09-10 12:32:00,11.11\n2015-09-10 12:37:00,3.28\n2015-09-10 12:47:00,5.94\n2015-09-10 12:52:00,12.06\n2015-09-10 12:57:00,7.06\n2015-09-10 13:02:00,9.83\n2015-09-10 13:07:00,8.17\n2015-09-10 13:12:00,4.5\n2015-09-10 13:17:00,8.11\n2015-09-10 13:22:00,10.78\n2015-09-10 13:32:00,8.61\n2015-09-10 13:37:00,8.67\n2015-09-10 13:47:00,9\n2015-09-10 13:52:00,14.72\n2015-09-10 13:57:00,6.17\n2015-09-10 14:02:00,3.5\n2015-09-10 14:07:00,10.17\n2015-09-10 14:12:00,11.67\n2015-09-10 14:17:00,8.67\n2015-09-10 14:27:00,13.44\n2015-09-10 14:32:00,8.89\n2015-09-10 14:37:00,9.83\n2015-09-10 14:47:00,8.94\n2015-09-10 14:52:00,4.17\n2015-09-10 14:57:00,8.67\n2015-09-10 15:02:00,4\n2015-09-10 15:07:00,9.78\n2015-09-10 15:17:00,9.61\n2015-09-10 15:22:00,9.83\n2015-09-10 15:27:00,5.56\n2015-09-10 15:32:00,9.94\n2015-09-10 15:37:00,12.89\n2015-09-10 15:42:00,6.33\n2015-09-10 15:52:00,4.72\n2015-09-10 15:57:00,9.06\n2015-09-10 16:02:00,11.56\n2015-09-10 16:12:00,10\n2015-09-10 16:17:00,4.61\n2015-09-10 16:22:00,6.67\n2015-09-10 16:27:00,17.22\n2015-09-10 16:32:00,11.44\n2015-09-10 16:37:00,8.56\n2015-09-10 16:42:00,9.17\n2015-09-10 16:52:00,6.72\n2015-09-10 16:57:00,9.78\n2015-09-10 17:02:00,9.28\n2015-09-10 17:07:00,9.28\n2015-09-10 17:12:00,11.72\n2015-09-10 17:17:00,10.33\n2015-09-10 17:22:00,8.89\n2015-09-10 17:27:00,10.78\n2015-09-10 17:32:00,7.61\n2015-09-10 17:37:00,10.28\n2015-09-10 17:47:00,6.61\n2015-09-10 17:52:00,3.78\n2015-09-10 17:57:00,10.78\n2015-09-10 18:02:00,2.83\n2015-09-10 18:07:00,5.28\n2015-09-10 18:12:00,8.44\n2015-09-10 18:22:00,6.5\n2015-09-10 18:27:00,7.44\n2015-09-10 18:32:00,13.44\n2015-09-10 18:37:00,6.39\n2015-09-10 18:42:00,7.28\n2015-09-10 18:57:00,7.17\n2015-09-10 19:02:00,4.78\n2015-09-10 19:07:00,3\n2015-09-10 19:12:00,3.89\n2015-09-10 19:17:00,3.06\n2015-09-10 19:22:00,3.56\n2015-09-10 19:27:00,4.94\n2015-09-10 19:32:00,6.33\n2015-09-10 19:37:00,4.72\n2015-09-10 19:42:00,8.56\n2015-09-10 19:47:00,6.17\n2015-09-10 19:52:00,3.89\n2015-09-10 19:57:00,4.67\n2015-09-10 20:02:00,1.33\n2015-09-10 20:07:00,6.44\n2015-09-10 20:12:00,6.44\n2015-09-10 20:17:00,5.39\n2015-09-10 20:22:00,10.22\n2015-09-10 20:28:00,4.67\n2015-09-10 20:32:00,1.28\n2015-09-10 20:38:00,4.67\n2015-09-10 20:52:00,4.89\n2015-09-10 20:57:00,1.67\n2015-09-10 21:07:00,3.17\n2015-09-10 21:12:00,2\n2015-09-10 21:17:00,2.56\n2015-09-10 21:22:00,3.28\n2015-09-10 21:37:00,5.22\n2015-09-10 21:47:00,5.39\n2015-09-10 21:52:00,4.78\n2015-09-10 22:12:00,7.11\n2015-09-10 22:27:00,1.67\n2015-09-10 22:32:00,2.17\n2015-09-10 22:52:00,2.22\n2015-09-10 23:17:00,0.89\n2015-09-10 23:22:00,2.72\n2015-09-10 23:32:00,5.17\n2015-09-10 23:37:00,0.78\n2015-09-11 00:02:00,3\n2015-09-11 00:27:00,2.39\n2015-09-11 00:32:00,0.94\n2015-09-11 00:37:00,3.33\n2015-09-11 00:52:00,2.5\n2015-09-11 00:57:00,3.78\n2015-09-11 01:12:00,0.22\n2015-09-11 01:57:00,3.11\n2015-09-11 02:17:00,0.72\n2015-09-11 03:32:00,1\n2015-09-11 03:42:00,4.67\n2015-09-11 03:47:00,0.72\n2015-09-11 03:57:00,3.89\n2015-09-11 04:32:00,1.56\n2015-09-11 04:47:00,2.22\n2015-09-11 04:52:00,2.44\n2015-09-11 04:57:00,1.5\n2015-09-11 05:02:00,8.94\n2015-09-11 05:07:00,3.56\n2015-09-11 05:12:00,8.28\n2015-09-11 05:17:00,8.17\n2015-09-11 05:27:00,4.22\n2015-09-11 05:32:00,7.94\n2015-09-11 05:37:00,6.28\n2015-09-11 05:47:00,3\n2015-09-11 05:52:00,8.56\n2015-09-11 05:57:00,5.06\n2015-09-11 06:02:00,5.06\n2015-09-11 06:07:00,9.56\n2015-09-11 06:12:00,6.44\n2015-09-11 06:17:00,4.61\n2015-09-11 06:22:00,13.94\n2015-09-11 06:27:00,13.06\n2015-09-11 06:37:00,7.5\n2015-09-11 06:42:00,10.72\n2015-09-11 06:47:00,8.11\n2015-09-11 06:52:00,7.22\n2015-09-11 06:57:00,6.61\n2015-09-11 07:02:00,7.94\n2015-09-11 07:07:00,11.11\n2015-09-11 07:12:00,13.78\n2015-09-11 07:17:00,9.44\n2015-09-11 07:27:00,9.28\n2015-09-11 07:32:00,9.33\n2015-09-11 07:37:00,11.28\n2015-09-11 07:42:00,12.28\n2015-09-11 07:52:00,15.28\n2015-09-11 07:57:00,3.56\n2015-09-11 08:02:00,8.11\n2015-09-11 08:07:00,9.28\n2015-09-11 08:12:00,10.28\n2015-09-11 08:17:00,9.06\n2015-09-11 08:22:00,11.39\n2015-09-11 08:27:00,8.06\n2015-09-11 08:32:00,12.78\n2015-09-11 08:37:00,13.44\n2015-09-11 08:42:00,8\n2015-09-11 08:57:00,11.56\n2015-09-11 09:02:00,6.94\n2015-09-11 09:07:00,4.28\n2015-09-11 09:17:00,8.06\n2015-09-11 09:22:00,10.61\n2015-09-11 09:27:00,7.06\n2015-09-11 09:32:00,8.39\n2015-09-11 09:37:00,10.11\n2015-09-11 09:47:00,4.5\n2015-09-11 09:52:00,4.72\n2015-09-11 09:57:00,13.89\n2015-09-11 10:07:00,5.06\n2015-09-11 10:12:00,15.06\n2015-09-11 10:17:00,9.22\n2015-09-11 10:22:00,10.11\n2015-09-11 10:27:00,11.89\n2015-09-11 10:29:00,7.22\n2015-09-11 10:34:00,4.67\n2015-09-11 10:39:00,11.94\n2015-09-11 10:44:00,6.56\n2015-09-11 10:49:00,5.44\n2015-09-11 10:59:00,7.72\n2015-09-11 11:09:00,2.72\n2015-09-11 11:14:00,7.5\n2015-09-11 11:19:00,12.72\n2015-09-11 11:24:00,4.78\n2015-09-11 11:29:00,10.22\n2015-09-11 11:34:00,9.17\n2015-09-11 11:39:00,7.89\n2015-09-11 11:44:00,17.11\n2015-09-11 11:49:00,17.06\n2015-09-11 11:54:00,10.33\n2015-09-11 11:59:00,10.5\n2015-09-11 12:04:00,10.67\n2015-09-11 12:09:00,11\n2015-09-11 12:14:00,9.33\n2015-09-11 12:24:00,11.28\n2015-09-11 12:34:00,5.5\n2015-09-11 12:39:00,11.94\n2015-09-11 12:44:00,9.67\n2015-09-11 12:54:00,10.83\n2015-09-11 12:59:00,10.67\n2015-09-11 13:04:00,2.56\n2015-09-11 13:09:00,8.5\n2015-09-11 13:14:00,11\n2015-09-11 13:24:00,11.72\n2015-09-11 13:29:00,11.06\n2015-09-11 13:34:00,4.83\n2015-09-11 13:39:00,10.83\n2015-09-11 13:44:00,6.56\n2015-09-11 13:49:00,4.89\n2015-09-11 13:54:00,8.78\n2015-09-11 13:59:00,2.94\n2015-09-11 14:04:00,4.33\n2015-09-11 14:09:00,9.5\n2015-09-11 14:14:00,16.94\n2015-09-11 14:24:00,10.89\n2015-09-11 14:29:00,8.17\n2015-09-11 14:34:00,4.11\n2015-09-11 14:39:00,9.94\n2015-09-11 14:44:00,7.33\n2015-09-11 14:54:00,11\n2015-09-11 14:59:00,7.22\n2015-09-11 15:04:00,6\n2015-09-11 15:09:00,8.39\n2015-09-11 15:14:00,7.67\n2015-09-11 15:19:00,10.56\n2015-09-11 15:24:00,5.94\n2015-09-11 15:29:00,6.33\n2015-09-11 15:34:00,6.72\n2015-09-11 15:39:00,12.28\n2015-09-11 15:44:00,7\n2015-09-11 15:49:00,9.28\n2015-09-11 15:54:00,8\n2015-09-11 16:09:00,4.67\n2015-09-11 16:19:00,10\n2015-09-11 16:24:00,9.61\n2015-09-11 16:29:00,10.28\n2015-09-11 16:34:00,8.5\n2015-09-11 16:44:00,7.89\n2015-09-11 16:49:00,10.06\n2015-09-11 16:59:00,11.89\n2015-09-11 17:04:00,7.94\n2015-09-11 17:09:00,12.72\n2015-09-11 17:14:00,11.56\n2015-09-11 17:19:00,8.11\n2015-09-11 17:24:00,10.72\n2015-09-11 17:29:00,4.11\n2015-09-11 17:34:00,6.39\n2015-09-11 17:39:00,8.94\n2015-09-11 17:44:00,9.56\n2015-09-11 17:49:00,10.06\n2015-09-11 17:54:00,11.44\n2015-09-11 17:59:00,5.56\n2015-09-11 18:04:00,4.44\n2015-09-11 18:16:00,6.06\n2015-09-11 18:21:00,13.5\n2015-09-11 18:26:00,3.89\n2015-09-11 18:36:00,7.94\n2015-09-11 18:41:00,7.94\n2015-09-11 18:46:00,7.56\n2015-09-11 18:51:00,4.22\n2015-09-11 18:56:00,6.94\n2015-09-11 19:01:00,5.89\n2015-09-11 19:11:00,3.67\n2015-09-11 19:16:00,8.33\n2015-09-11 19:21:00,5.83\n2015-09-11 19:26:00,5.33\n2015-09-11 19:31:00,6.78\n2015-09-11 19:41:00,6.33\n2015-09-11 19:46:00,7.11\n2015-09-11 19:51:00,0.89\n2015-09-11 19:56:00,5.17\n2015-09-11 20:01:00,1.5\n2015-09-11 20:16:00,5.44\n2015-09-11 20:21:00,3.39\n2015-09-11 20:26:00,6.94\n2015-09-11 20:31:00,5.44\n2015-09-11 20:46:00,5.78\n2015-09-11 20:51:00,2.61\n2015-09-11 21:01:00,2.56\n2015-09-11 21:21:00,4.61\n2015-09-11 21:36:00,5.72\n2015-09-11 21:41:00,5.56\n2015-09-11 21:46:00,5.94\n2015-09-11 21:51:00,5.28\n2015-09-11 22:06:00,3.94\n2015-09-11 22:11:00,2.89\n2015-09-11 22:16:00,5.06\n2015-09-11 22:21:00,3.17\n2015-09-11 22:31:00,6.78\n2015-09-11 22:41:00,1.78\n2015-09-11 22:46:00,5.5\n2015-09-11 22:51:00,2.94\n2015-09-11 23:01:00,6.5\n2015-09-11 23:06:00,1\n2015-09-11 23:11:00,3.11\n2015-09-11 23:16:00,0.78\n2015-09-12 00:06:00,5.56\n2015-09-12 00:11:00,2.22\n2015-09-12 00:16:00,3.44\n2015-09-12 00:31:00,1.83\n2015-09-12 00:36:00,0.56\n2015-09-12 00:46:00,3.78\n2015-09-12 01:11:00,0.72\n2015-09-12 01:16:00,3.39\n2015-09-12 01:21:00,1.78\n2015-09-12 01:36:00,4.22\n2015-09-12 01:41:00,1.44\n2015-09-12 02:21:00,1.06\n2015-09-12 02:36:00,1\n2015-09-12 02:46:00,0.89\n2015-09-12 03:26:00,1.39\n2015-09-12 03:36:00,0.67\n2015-09-12 03:51:00,4.67\n2015-09-12 04:01:00,1.56\n2015-09-12 04:41:00,1.78\n2015-09-12 04:56:00,2.28\n2015-09-12 05:31:00,0.67\n2015-09-12 05:36:00,2.28\n2015-09-12 05:41:00,1.72\n2015-09-12 05:46:00,6.94\n2015-09-12 05:51:00,0.67\n2015-09-12 05:56:00,1.5\n2015-09-12 06:01:00,3.61\n2015-09-12 06:06:00,1.89\n2015-09-12 06:11:00,2.72\n2015-09-12 06:16:00,1.33\n2015-09-12 06:21:00,0.83\n2015-09-12 06:26:00,1.78\n2015-09-12 06:31:00,0.78\n2015-09-12 06:41:00,6.83\n2015-09-12 06:46:00,1.72\n2015-09-12 06:51:00,2.11\n2015-09-12 07:01:00,2.78\n2015-09-12 07:06:00,0.56\n2015-09-12 07:11:00,1.67\n2015-09-12 07:16:00,4.28\n2015-09-12 07:26:00,5.67\n2015-09-12 07:46:00,5.78\n2015-09-12 07:51:00,5.33\n2015-09-12 07:56:00,6.33\n2015-09-12 08:06:00,2.11\n2015-09-12 08:11:00,3.06\n2015-09-12 08:16:00,7.33\n2015-09-12 08:21:00,4.89\n2015-09-12 08:31:00,3.33\n2015-09-12 08:41:00,9.44\n2015-09-12 08:51:00,3.22\n2015-09-12 08:56:00,7\n2015-09-12 09:01:00,2.28\n2015-09-12 09:06:00,7.39\n2015-09-12 09:11:00,9\n2015-09-12 09:16:00,6.44\n2015-09-12 09:21:00,4.22\n2015-09-12 09:26:00,3\n2015-09-12 09:31:00,8.72\n2015-09-12 09:36:00,3.28\n2015-09-12 09:41:00,6\n2015-09-12 09:51:00,6.78\n2015-09-12 09:56:00,6.28\n2015-09-12 10:01:00,7.83\n2015-09-12 10:06:00,5.94\n2015-09-12 10:11:00,9.39\n2015-09-12 10:16:00,6.83\n2015-09-12 10:21:00,5.56\n2015-09-12 10:26:00,8.67\n2015-09-12 10:31:00,5.83\n2015-09-12 10:36:00,6.11\n2015-09-12 10:41:00,5.61\n2015-09-12 10:46:00,11.33\n2015-09-12 10:51:00,5\n2015-09-12 10:56:00,8.72\n2015-09-12 11:06:00,4.44\n2015-09-12 11:11:00,7.44\n2015-09-12 11:26:00,8.17\n2015-09-12 11:31:00,6.28\n2015-09-12 11:36:00,4.33\n2015-09-12 11:41:00,7.94\n2015-09-12 11:46:00,10.83\n2015-09-12 11:51:00,8.94\n2015-09-12 11:56:00,5.44\n2015-09-12 12:01:00,12.83\n2015-09-12 12:06:00,15.17\n2015-09-12 12:11:00,7.56\n2015-09-12 12:16:00,8.06\n2015-09-12 12:21:00,8.33\n2015-09-12 12:26:00,8.06\n2015-09-12 12:31:00,5.22\n2015-09-12 12:36:00,10.44\n2015-09-12 12:46:00,7.22\n2015-09-12 12:51:00,5.39\n2015-09-12 12:56:00,5.56\n2015-09-12 13:06:00,5.28\n2015-09-12 13:11:00,5.78\n2015-09-12 13:16:00,5.78\n2015-09-12 13:21:00,6.94\n2015-09-12 13:26:00,3.89\n2015-09-12 13:31:00,4.89\n2015-09-12 13:36:00,4.28\n2015-09-12 13:41:00,7.33\n2015-09-12 13:46:00,7\n2015-09-12 13:51:00,9.06\n2015-09-12 14:06:00,8.94\n2015-09-12 14:11:00,5.33\n2015-09-12 14:16:00,9.56\n2015-09-12 14:21:00,4.17\n2015-09-12 14:26:00,4.78\n2015-09-12 14:31:00,9.72\n2015-09-12 14:36:00,8.89\n2015-09-12 14:41:00,3.89\n2015-09-12 14:51:00,8.17\n2015-09-12 14:56:00,12.33\n2015-09-12 15:01:00,8\n2015-09-12 15:06:00,6.33\n2015-09-12 15:11:00,2.72\n2015-09-12 15:16:00,7.56\n2015-09-12 15:21:00,7.83\n2015-09-12 15:36:00,7.94\n2015-09-12 15:46:00,8.44\n2015-09-12 15:51:00,9.44\n2015-09-12 16:01:00,2.78\n2015-09-12 16:06:00,3.94\n2015-09-12 16:11:00,8.17\n2015-09-12 16:16:00,2.17\n2015-09-12 16:21:00,5.61\n2015-09-12 16:26:00,5.06\n2015-09-12 16:31:00,5.28\n2015-09-12 16:36:00,10.83\n2015-09-12 16:41:00,9.94\n2015-09-12 16:46:00,9.5\n2015-09-12 16:51:00,11.78\n2015-09-12 16:56:00,3.39\n2015-09-12 17:01:00,3.17\n2015-09-12 17:06:00,6.44\n2015-09-12 17:11:00,4\n2015-09-12 17:16:00,5.72\n2015-09-12 17:21:00,5.83\n2015-09-12 17:26:00,6.61\n2015-09-12 17:31:00,9.33\n2015-09-12 17:36:00,10.06\n2015-09-12 17:41:00,7.39\n2015-09-12 17:46:00,7.78\n2015-09-12 17:51:00,5.94\n2015-09-12 17:56:00,2.44\n2015-09-12 18:01:00,9.39\n2015-09-12 18:06:00,5\n2015-09-12 18:11:00,6\n2015-09-12 18:16:00,5.5\n2015-09-12 18:21:00,5.78\n2015-09-12 18:26:00,5.72\n2015-09-12 18:31:00,5.61\n2015-09-12 18:46:00,3.17\n2015-09-12 18:56:00,2.94\n2015-09-12 19:01:00,6.11\n2015-09-12 19:11:00,5.17\n2015-09-12 19:21:00,5.17\n2015-09-12 19:31:00,3.44\n2015-09-12 19:36:00,5.44\n2015-09-12 19:41:00,2.11\n2015-09-12 19:46:00,4.56\n2015-09-12 19:51:00,4.06\n2015-09-12 20:01:00,3.5\n2015-09-12 20:11:00,3.33\n2015-09-12 20:21:00,3.22\n2015-09-12 20:26:00,3.5\n2015-09-12 20:31:00,1.39\n2015-09-12 20:36:00,3.17\n2015-09-12 20:41:00,4.72\n2015-09-12 20:46:00,3.33\n2015-09-12 20:51:00,4.5\n2015-09-12 21:01:00,2.5\n2015-09-12 21:06:00,3.28\n2015-09-12 21:16:00,5.11\n2015-09-12 21:21:00,4.28\n2015-09-12 21:26:00,3.83\n2015-09-12 21:36:00,3.44\n2015-09-12 21:41:00,6.33\n2015-09-12 21:46:00,1.67\n2015-09-12 21:51:00,5.44\n2015-09-12 21:56:00,2.61\n2015-09-12 22:01:00,3.83\n2015-09-12 22:06:00,3.44\n2015-09-12 22:16:00,3.33\n2015-09-12 22:26:00,4.56\n2015-09-12 22:36:00,0.67\n2015-09-12 22:41:00,4.33\n2015-09-12 22:46:00,2.5\n2015-09-12 22:51:00,1.94\n2015-09-12 22:56:00,4.06\n2015-09-12 23:01:00,5.17\n2015-09-12 23:06:00,2\n2015-09-12 23:16:00,1.78\n2015-09-12 23:21:00,3.06\n2015-09-12 23:31:00,0.67\n2015-09-12 23:41:00,1.56\n2015-09-12 23:46:00,4.39\n2015-09-12 23:51:00,4.17\n2015-09-12 23:56:00,1.67\n2015-09-13 00:01:00,1.39\n2015-09-13 00:11:00,3.61\n2015-09-13 00:16:00,0.83\n2015-09-13 00:26:00,2.56\n2015-09-13 00:31:00,1.5\n2015-09-13 00:56:00,0.89\n2015-09-13 01:31:00,0.78\n2015-09-13 01:41:00,0.83\n2015-09-13 02:01:00,1\n2015-09-13 02:06:00,0.83\n2015-09-13 02:11:00,0.78\n2015-09-13 02:56:00,2\n2015-09-13 03:01:00,1.61\n2015-09-13 03:11:00,0.78\n2015-09-13 05:06:00,2.5\n2015-09-13 05:11:00,0.06\n2015-09-13 05:26:00,1.89\n2015-09-13 05:56:00,2.67\n2015-09-13 06:01:00,3.83\n2015-09-13 06:06:00,1.56\n2015-09-13 06:21:00,1.89\n2015-09-13 06:26:00,1.61\n2015-09-13 06:31:00,1.17\n2015-09-13 06:36:00,0.72\n2015-09-13 06:46:00,3.56\n2015-09-13 06:51:00,1.72\n2015-09-13 06:56:00,2.44\n2015-09-13 07:01:00,0.89\n2015-09-13 07:11:00,3.39\n2015-09-13 07:16:00,1.44\n2015-09-13 07:21:00,2.28\n2015-09-13 07:26:00,1.61\n2015-09-13 07:31:00,6.11\n2015-09-13 07:36:00,4.28\n2015-09-13 07:46:00,3.67\n2015-09-13 07:56:00,3.89\n2015-09-13 08:01:00,2.39\n2015-09-13 08:06:00,3.11\n2015-09-13 08:16:00,1.56\n2015-09-13 08:31:00,5.72\n2015-09-13 08:36:00,3.78\n2015-09-13 08:41:00,3.06\n2015-09-13 08:46:00,4.17\n2015-09-13 08:51:00,4.83\n2015-09-13 08:56:00,5\n2015-09-13 09:01:00,6.44\n2015-09-13 09:06:00,4.5\n2015-09-13 09:11:00,4.67\n2015-09-13 09:16:00,3.67\n2015-09-13 09:26:00,7.67\n2015-09-13 09:31:00,6.33\n2015-09-13 09:36:00,6.78\n2015-09-13 09:41:00,2.28\n2015-09-13 09:46:00,2.83\n2015-09-13 09:51:00,5.94\n2015-09-13 09:56:00,5\n2015-09-13 10:06:00,3.94\n2015-09-13 10:11:00,5.5\n2015-09-13 10:16:00,4\n2015-09-13 10:31:00,8.22\n2015-09-13 10:36:00,6.61\n2015-09-13 10:41:00,6.89\n2015-09-13 10:46:00,4.94\n2015-09-13 10:51:00,8.78\n2015-09-13 10:56:00,2.94\n2015-09-13 11:06:00,4.5\n2015-09-13 11:11:00,11.06\n2015-09-13 11:16:00,7.83\n2015-09-13 11:21:00,7.72\n2015-09-13 11:31:00,4.06\n2015-09-13 11:36:00,10.44\n2015-09-13 11:41:00,0.83\n2015-09-13 11:46:00,14.22\n2015-09-13 11:51:00,7.39\n2015-09-13 11:56:00,6.39\n2015-09-13 12:01:00,9.39\n2015-09-13 12:06:00,6.5\n2015-09-13 12:11:00,7.89\n2015-09-13 12:16:00,8.22\n2015-09-13 12:21:00,9.67\n2015-09-13 12:26:00,9.22\n2015-09-13 12:31:00,6.83\n2015-09-13 12:41:00,9.61\n2015-09-13 12:46:00,4.56\n2015-09-13 12:48:00,9.11\n2015-09-13 12:53:00,6.89\n2015-09-13 12:58:00,6.56\n2015-09-13 13:03:00,8.61\n2015-09-13 13:08:00,5.39\n2015-09-13 13:13:00,8.39\n2015-09-13 13:18:00,4.28\n2015-09-13 13:23:00,7.83\n2015-09-13 13:28:00,5.44\n2015-09-13 13:33:00,4.67\n2015-09-13 13:43:00,6.06\n2015-09-13 13:48:00,5.11\n2015-09-13 13:53:00,6.06\n2015-09-13 13:58:00,8.33\n2015-09-13 14:03:00,5.28\n2015-09-13 14:13:00,8.39\n2015-09-13 14:18:00,10.17\n2015-09-13 14:23:00,3\n2015-09-13 14:28:00,8.39\n2015-09-13 14:38:00,6.39\n2015-09-13 14:43:00,10.17\n2015-09-13 14:48:00,6.56\n2015-09-13 14:58:00,9.11\n2015-09-13 15:03:00,9.89\n2015-09-13 15:08:00,5.89\n2015-09-13 15:13:00,4.44\n2015-09-13 15:18:00,7\n2015-09-13 15:23:00,6.83\n2015-09-13 15:28:00,4.06\n2015-09-13 15:33:00,6.39\n2015-09-13 15:38:00,8.94\n2015-09-13 15:48:00,9.33\n2015-09-13 15:53:00,10.33\n2015-09-13 15:58:00,5.44\n2015-09-13 16:03:00,3.06\n2015-09-13 16:08:00,6.06\n2015-09-13 16:13:00,9.72\n2015-09-13 16:18:00,9.17\n2015-09-13 16:23:00,8.39\n2015-09-13 16:28:00,6.67\n2015-09-13 16:33:00,3.67\n2015-09-13 16:38:00,9.67\n2015-09-13 16:43:00,7.33\n2015-09-13 17:03:00,4.94\n2015-09-13 17:08:00,5.33\n2015-09-13 17:13:00,9.17\n2015-09-13 17:18:00,2.78\n2015-09-13 17:23:00,4.28\n2015-09-13 17:28:00,10.39\n2015-09-13 17:33:00,2.39\n2015-09-13 17:38:00,11.17\n2015-09-13 17:48:00,6.67\n2015-09-13 17:53:00,6.28\n2015-09-13 17:58:00,5.94\n2015-09-13 18:08:00,5.83\n2015-09-13 18:13:00,6\n2015-09-13 18:18:00,8.33\n2015-09-13 18:23:00,5.39\n2015-09-13 18:28:00,10.17\n2015-09-13 18:33:00,6.67\n2015-09-13 18:38:00,5.78\n2015-09-13 18:48:00,9.72\n2015-09-13 18:53:00,1.67\n2015-09-13 18:58:00,7.78\n2015-09-13 19:03:00,6.83\n2015-09-13 19:08:00,2\n2015-09-13 19:18:00,3.83\n2015-09-13 19:23:00,4.83\n2015-09-13 19:28:00,4.56\n2015-09-13 19:33:00,4.44\n2015-09-13 19:38:00,6.61\n2015-09-13 19:48:00,6.89\n2015-09-13 19:53:00,5.89\n2015-09-13 19:58:00,7\n2015-09-13 20:08:00,7.94\n2015-09-13 20:13:00,4.72\n2015-09-13 20:18:00,3.22\n2015-09-13 20:23:00,3\n2015-09-13 20:28:00,2.44\n2015-09-13 20:33:00,1.89\n2015-09-13 20:43:00,3.67\n2015-09-13 20:53:00,7.61\n2015-09-13 21:03:00,2.22\n2015-09-13 21:18:00,3.39\n2015-09-13 21:23:00,3.33\n2015-09-13 21:28:00,2.33\n2015-09-13 21:33:00,0.83\n2015-09-13 21:38:00,4.28\n2015-09-13 21:43:00,6.28\n2015-09-13 21:48:00,4.11\n2015-09-13 22:08:00,2.5\n2015-09-13 22:13:00,2.94\n2015-09-13 22:18:00,2.39\n2015-09-13 22:33:00,0.89\n2015-09-13 22:38:00,1.89\n2015-09-13 22:48:00,0.94\n2015-09-13 22:53:00,0.61\n2015-09-13 22:58:00,2.33\n2015-09-13 23:08:00,1.83\n2015-09-13 23:28:00,1.44\n2015-09-13 23:38:00,4.61\n2015-09-13 23:43:00,1.22\n2015-09-13 23:48:00,1.78\n2015-09-13 23:53:00,0.89\n2015-09-14 00:18:00,0.94\n2015-09-14 00:43:00,2.11\n2015-09-14 00:53:00,1.61\n2015-09-14 00:58:00,1.67\n2015-09-14 01:08:00,1.78\n2015-09-14 01:28:00,1.72\n2015-09-14 02:03:00,3.61\n2015-09-14 02:28:00,1.5\n2015-09-14 02:43:00,5.22\n2015-09-14 02:48:00,2.72\n2015-09-14 02:58:00,3.78\n2015-09-14 03:08:00,0.78\n2015-09-14 03:13:00,1.5\n2015-09-14 03:23:00,0.89\n2015-09-14 03:48:00,0.83\n2015-09-14 04:13:00,0.89\n2015-09-14 04:23:00,0.94\n2015-09-14 04:28:00,2.44\n2015-09-14 04:43:00,2.56\n2015-09-14 04:48:00,2.5\n2015-09-14 04:53:00,1.39\n2015-09-14 04:58:00,3.39\n2015-09-14 05:03:00,4\n2015-09-14 05:08:00,1.94\n2015-09-14 05:18:00,4.33\n2015-09-14 05:23:00,3.56\n2015-09-14 05:28:00,2.28\n2015-09-14 05:33:00,6.11\n2015-09-14 05:38:00,4.72\n2015-09-14 05:43:00,2.39\n2015-09-14 05:48:00,5.22\n2015-09-14 05:53:00,3.67\n2015-09-14 05:58:00,3.11\n2015-09-14 06:03:00,8\n2015-09-14 06:08:00,6.06\n2015-09-14 06:13:00,8.61\n2015-09-14 06:18:00,4.06\n2015-09-14 06:23:00,10.39\n2015-09-14 06:28:00,13.39\n2015-09-14 06:33:00,4.89\n2015-09-14 06:38:00,6.83\n2015-09-14 06:43:00,8.39\n2015-09-14 06:48:00,7.5\n2015-09-14 06:53:00,11.17\n2015-09-14 06:58:00,12.67\n2015-09-14 07:03:00,14\n2015-09-14 07:08:00,9.22\n2015-09-14 07:13:00,6.78\n2015-09-14 07:18:00,11.94\n2015-09-14 07:23:00,10.67\n2015-09-14 07:28:00,8.94\n2015-09-14 07:33:00,10.94\n2015-09-14 07:38:00,12.61\n2015-09-14 07:43:00,6\n2015-09-14 07:48:00,10.28\n2015-09-14 07:53:00,6.28\n2015-09-14 07:58:00,11.67\n2015-09-14 08:03:00,10.5\n2015-09-14 08:08:00,20.72\n2015-09-14 08:13:00,18.61\n2015-09-14 08:18:00,9.72\n2015-09-14 08:23:00,12.11\n2015-09-14 08:38:00,6.5\n2015-09-14 08:43:00,10.78\n2015-09-14 08:48:00,15.39\n2015-09-14 08:53:00,11.94\n2015-09-14 08:58:00,3.56\n2015-09-14 09:03:00,3.94\n2015-09-14 09:08:00,5.78\n2015-09-14 09:13:00,10.17\n2015-09-14 09:18:00,12.39\n2015-09-14 09:23:00,9.94\n2015-09-14 09:28:00,8.67\n2015-09-14 09:33:00,14.28\n2015-09-14 09:43:00,5.5\n2015-09-14 09:48:00,11.78\n2015-09-14 09:53:00,8.11\n2015-09-14 09:58:00,13.11\n2015-09-14 10:03:00,5.67\n2015-09-14 10:08:00,9.67\n2015-09-14 10:13:00,8.39\n2015-09-14 10:18:00,5.56\n2015-09-14 10:23:00,6.72\n2015-09-14 10:28:00,9.22\n2015-09-14 10:33:00,7.06\n2015-09-14 10:38:00,10.33\n2015-09-14 10:43:00,6.22\n2015-09-14 10:48:00,11.28\n2015-09-14 10:53:00,6.67\n2015-09-14 10:58:00,10.56\n2015-09-14 11:03:00,6.11\n2015-09-14 11:08:00,8.78\n2015-09-14 11:13:00,16.28\n2015-09-14 11:18:00,13.89\n2015-09-14 11:28:00,4.33\n2015-09-14 11:33:00,8.17\n2015-09-14 11:38:00,5.44\n2015-09-14 11:43:00,6\n2015-09-14 11:48:00,1.89\n2015-09-14 11:53:00,13.44\n2015-09-14 11:58:00,10.39\n2015-09-14 12:03:00,8.39\n2015-09-14 12:13:00,14.39\n2015-09-14 12:18:00,8.39\n2015-09-14 12:23:00,7.72\n2015-09-14 12:28:00,7.44\n2015-09-14 12:33:00,8.28\n2015-09-14 12:43:00,8.22\n2015-09-14 12:48:00,5.22\n2015-09-14 12:53:00,11\n2015-09-14 12:58:00,6.28\n2015-09-14 13:03:00,8.67\n2015-09-14 13:08:00,7.83\n2015-09-14 13:13:00,9.89\n2015-09-14 13:15:00,10.33\n2015-09-14 13:20:00,8.11\n2015-09-14 13:30:00,3.89\n2015-09-14 13:35:00,7\n2015-09-14 13:40:00,1.5\n2015-09-14 13:45:00,4.78\n2015-09-14 13:50:00,11.28\n2015-09-14 13:55:00,5.78\n2015-09-14 14:00:00,10.83\n2015-09-14 14:05:00,12\n2015-09-14 14:10:00,12.22\n2015-09-14 14:15:00,7.94\n2015-09-14 14:20:00,9.11\n2015-09-14 14:25:00,9.67\n2015-09-14 14:30:00,6.89\n2015-09-14 14:35:00,5.17\n2015-09-14 14:40:00,17.33\n2015-09-14 14:45:00,2.67\n2015-09-14 15:05:00,8.39\n2015-09-14 15:10:00,9.89\n2015-09-14 15:15:00,5.5\n2015-09-14 15:20:00,8.17\n2015-09-14 15:30:00,8.94\n2015-09-14 15:35:00,8.28\n2015-09-14 15:40:00,13.28\n2015-09-14 15:45:00,12.56\n2015-09-14 15:50:00,13.61\n2015-09-14 15:55:00,4.22\n2015-09-14 16:05:00,8.83\n2015-09-14 16:10:00,6.39\n2015-09-14 16:15:00,7.94\n2015-09-14 16:20:00,11.06\n2015-09-14 16:30:00,3.83\n2015-09-14 16:35:00,7.89\n2015-09-14 16:40:00,9\n2015-09-14 16:45:00,7.5\n2015-09-14 16:50:00,14.33\n2015-09-14 16:55:00,11.5\n2015-09-14 17:00:00,7.78\n2015-09-14 17:05:00,11.56\n2015-09-14 17:10:00,8.56\n2015-09-14 17:15:00,9.17\n2015-09-14 17:20:00,6.11\n2015-09-14 17:25:00,4.89\n2015-09-14 17:30:00,7.22\n2015-09-14 17:35:00,4.83\n2015-09-14 17:40:00,8.61\n2015-09-14 17:45:00,12.28\n2015-09-14 17:50:00,7.22\n2015-09-14 17:55:00,6.56\n2015-09-14 18:00:00,2.78\n2015-09-14 18:05:00,5.33\n2015-09-14 18:10:00,8.39\n2015-09-14 18:20:00,7.83\n2015-09-14 18:25:00,10.94\n2015-09-14 18:30:00,2.72\n2015-09-14 18:35:00,9.67\n2015-09-14 18:40:00,7.94\n2015-09-14 18:45:00,9.22\n2015-09-14 18:50:00,3.44\n2015-09-14 18:55:00,4.83\n2015-09-14 19:01:00,6.83\n2015-09-14 19:05:00,7.94\n2015-09-14 19:10:00,8.83\n2015-09-14 19:15:00,8.83\n2015-09-14 19:20:00,6.56\n2015-09-14 19:25:00,7.17\n2015-09-14 19:30:00,2.5\n2015-09-14 19:40:00,8.94\n2015-09-14 19:45:00,7.56\n2015-09-14 19:55:00,9.44\n2015-09-14 20:00:00,5.61\n2015-09-14 20:05:00,2.28\n2015-09-14 20:10:00,9.78\n2015-09-14 20:15:00,5.11\n2015-09-14 20:20:00,3.67\n2015-09-14 20:30:00,3.33\n2015-09-14 20:35:00,5.5\n2015-09-14 20:45:00,3.5\n2015-09-14 20:50:00,5.56\n2015-09-14 20:55:00,2.17\n2015-09-14 21:05:00,1.61\n2015-09-14 21:10:00,3.28\n2015-09-14 21:15:00,6.5\n2015-09-14 21:20:00,5.28\n2015-09-14 21:30:00,2.33\n2015-09-14 21:35:00,1.67\n2015-09-14 21:40:00,8.89\n2015-09-14 21:45:00,6.28\n2015-09-14 21:55:00,1.72\n2015-09-14 22:06:00,0.83\n2015-09-14 22:11:00,6.61\n2015-09-14 22:21:00,0.83\n2015-09-14 22:25:00,1\n2015-09-14 22:30:00,0.94\n2015-09-14 22:35:00,3\n2015-09-14 22:40:00,3.5\n2015-09-14 23:01:00,2.39\n2015-09-14 23:11:00,2.39\n2015-09-14 23:15:00,1.56\n2015-09-14 23:21:00,1.44\n2015-09-14 23:41:00,2.83\n2015-09-14 23:46:00,0.67\n2015-09-14 23:51:00,1\n2015-09-15 00:16:00,1.61\n2015-09-15 00:56:00,0.78\n2015-09-15 01:25:00,1\n2015-09-15 01:30:00,0.61\n2015-09-15 01:40:00,2.83\n2015-09-15 02:01:00,1.61\n2015-09-15 02:06:00,0.78\n2015-09-15 02:56:00,3.61\n2015-09-15 03:01:00,1.67\n2015-09-15 03:25:00,2.78\n2015-09-15 03:30:00,0.56\n2015-09-15 03:35:00,1\n2015-09-15 03:45:00,0.67\n2015-09-15 03:55:00,1.56\n2015-09-15 04:01:00,0.61\n2015-09-15 04:06:00,3.5\n2015-09-15 04:10:00,2.83\n2015-09-15 04:16:00,0.78\n2015-09-15 04:26:00,4.28\n2015-09-15 04:31:00,0.83\n2015-09-15 04:35:00,0.72\n2015-09-15 04:41:00,5.06\n2015-09-15 04:46:00,2.72\n2015-09-15 04:55:00,3.06\n2015-09-15 05:01:00,4.61\n2015-09-15 05:05:00,5.33\n2015-09-15 05:10:00,4.56\n2015-09-15 05:15:00,4.56\n2015-09-15 05:20:00,0.72\n2015-09-15 05:26:00,5.67\n2015-09-15 05:31:00,4.17\n2015-09-15 05:36:00,5.28\n2015-09-15 05:41:00,9.56\n2015-09-15 05:46:00,1.33\n2015-09-15 05:51:00,6.39\n2015-09-15 05:55:00,3.72\n2015-09-15 06:00:00,12.28\n2015-09-15 06:10:00,10.33\n2015-09-15 06:16:00,13.83\n2015-09-15 06:20:00,8.78\n2015-09-15 06:25:00,7.56\n2015-09-15 06:30:00,9.33\n2015-09-15 06:35:00,10.78\n2015-09-15 06:41:00,9.83\n2015-09-15 06:45:00,7.28\n2015-09-15 06:50:00,10.17\n2015-09-15 06:55:00,7.61\n2015-09-15 07:00:00,12.11\n2015-09-15 07:11:00,14.17\n2015-09-15 07:16:00,10.28\n2015-09-15 07:21:00,11.89\n2015-09-15 07:26:00,9.17\n2015-09-15 07:31:00,7.33\n2015-09-15 07:36:00,11.5\n2015-09-15 07:41:00,11.39\n2015-09-15 07:46:00,7.89\n2015-09-15 07:51:00,7.67\n2015-09-15 07:56:00,9.06\n2015-09-15 08:06:00,9.67\n2015-09-15 08:11:00,9.78\n2015-09-15 08:16:00,11.83\n2015-09-15 08:21:00,12.44\n2015-09-15 08:26:00,8.28\n2015-09-15 08:31:00,12.61\n2015-09-15 08:41:00,8.17\n2015-09-15 08:46:00,5.22\n2015-09-15 08:51:00,12.06\n2015-09-15 08:56:00,14.61\n2015-09-15 09:01:00,15\n2015-09-15 09:06:00,8.72\n2015-09-15 09:11:00,7.06\n2015-09-15 09:16:00,10.22\n2015-09-15 09:21:00,8.11\n2015-09-15 09:26:00,11.44\n2015-09-15 09:31:00,15.5\n2015-09-15 09:36:00,7.44\n2015-09-15 09:41:00,2.94\n2015-09-15 09:46:00,12.17\n2015-09-15 09:51:00,14.56\n2015-09-15 09:56:00,2.94\n2015-09-15 10:01:00,7.94\n2015-09-15 10:06:00,7.44\n2015-09-15 10:11:00,5\n2015-09-15 10:16:00,6.89\n2015-09-15 10:21:00,8.94\n2015-09-15 10:26:00,8.83\n2015-09-15 10:31:00,11.72\n2015-09-15 10:36:00,11.83\n2015-09-15 10:41:00,6.94\n2015-09-15 10:46:00,6.78\n2015-09-15 10:51:00,6.83\n2015-09-15 10:56:00,11.56\n2015-09-15 11:01:00,11.56\n2015-09-15 11:06:00,12.11\n2015-09-15 11:11:00,9\n2015-09-15 11:16:00,6.94\n2015-09-15 11:21:00,10\n2015-09-15 11:26:00,5.39\n2015-09-15 11:31:00,8.89\n2015-09-15 11:36:00,5.94\n2015-09-15 11:41:00,10.5\n2015-09-15 11:46:00,5.83\n2015-09-15 11:51:00,11.67\n2015-09-15 11:56:00,4.22\n2015-09-15 12:01:00,7.56\n2015-09-15 12:06:00,6.83\n2015-09-15 12:11:00,4.5\n2015-09-15 12:21:00,13.28\n2015-09-15 12:26:00,7.06\n2015-09-15 12:31:00,3.67\n2015-09-15 12:36:00,13.56\n2015-09-15 12:41:00,9.67\n2015-09-15 12:46:00,5.44\n2015-09-15 12:51:00,5.33\n2015-09-15 12:56:00,7.39\n2015-09-15 13:01:00,9.5\n2015-09-15 13:06:00,6.39\n2015-09-15 13:11:00,14.11\n2015-09-15 13:16:00,6.83\n2015-09-15 13:21:00,7.94\n2015-09-15 13:26:00,12.61\n2015-09-15 13:31:00,8.78\n2015-09-15 13:36:00,10.33\n2015-09-15 13:41:00,8.06\n2015-09-15 13:46:00,6.56\n2015-09-15 13:51:00,7.33\n2015-09-15 13:54:00,9.83\n2015-09-15 13:59:00,8.17\n2015-09-15 14:04:00,4.89\n2015-09-15 14:09:00,9.28\n2015-09-15 14:14:00,12.17\n2015-09-15 14:19:00,7.06\n2015-09-15 14:24:00,5.83\n2015-09-15 14:29:00,9.11\n2015-09-15 14:39:00,7\n2015-09-15 14:44:00,12.78\n2015-09-15 14:49:00,7.39\n2015-09-15 14:54:00,6.06\n2015-09-15 14:59:00,7.72\n2015-09-15 15:04:00,10.83\n2015-09-15 15:09:00,11.17\n2015-09-15 15:14:00,11.39\n2015-09-15 15:19:00,8.33\n2015-09-15 15:24:00,11.56\n2015-09-15 15:29:00,5.33\n2015-09-15 15:34:00,7.89\n2015-09-15 15:39:00,11.06\n2015-09-15 15:44:00,8\n2015-09-15 15:49:00,8.11\n2015-09-15 15:54:00,8.83\n2015-09-15 15:59:00,7.67\n2015-09-15 16:04:00,9.94\n2015-09-15 16:09:00,7.72\n2015-09-15 16:14:00,5.94\n2015-09-15 16:19:00,9.44\n2015-09-15 16:24:00,4.06\n2015-09-15 16:29:00,7.94\n2015-09-15 16:34:00,10.78\n2015-09-15 16:39:00,9.67\n2015-09-15 16:44:00,8.5\n2015-09-15 16:49:00,7.39\n2015-09-15 16:54:00,9.72\n2015-09-15 16:59:00,6.94\n2015-09-15 17:04:00,8.22\n2015-09-15 17:09:00,6.44\n2015-09-15 17:14:00,11.22\n2015-09-15 17:19:00,4.89\n2015-09-15 17:24:00,6.56\n2015-09-15 17:29:00,11.39\n2015-09-15 17:39:00,7.5\n2015-09-15 17:44:00,11.67\n2015-09-15 17:49:00,13\n2015-09-15 17:54:00,9.33\n2015-09-15 17:59:00,7.83\n2015-09-15 18:04:00,6.61\n2015-09-15 18:09:00,3.06\n2015-09-15 18:14:00,4.06\n2015-09-15 18:19:00,10.56\n2015-09-15 18:24:00,9.44\n2015-09-15 18:34:00,12.56\n2015-09-15 18:39:00,4.94\n2015-09-15 18:44:00,5.33\n2015-09-15 18:49:00,4.67\n2015-09-15 18:54:00,6.56\n2015-09-15 18:59:00,7.83\n2015-09-15 19:04:00,4.61\n2015-09-15 19:09:00,2.83\n2015-09-15 19:14:00,3.5\n2015-09-15 19:29:00,8.67\n2015-09-15 19:34:00,1.83\n2015-09-15 19:39:00,1.17\n2015-09-15 19:44:00,3.67\n2015-09-15 19:49:00,5.17\n2015-09-15 19:54:00,7.06\n2015-09-15 19:59:00,6.67\n2015-09-15 20:09:00,5.72\n2015-09-15 20:14:00,2.44\n2015-09-15 20:19:00,7\n2015-09-15 20:24:00,7.17\n2015-09-15 20:29:00,4.06\n2015-09-15 20:34:00,8.61\n2015-09-15 20:39:00,3.17\n2015-09-15 20:44:00,4.17\n2015-09-15 20:49:00,5.94\n2015-09-15 20:54:00,1.5\n2015-09-15 20:59:00,7.5\n2015-09-15 21:04:00,5.5\n2015-09-15 21:09:00,1.56\n2015-09-15 21:14:00,7.39\n2015-09-15 21:19:00,2.33\n2015-09-15 21:24:00,2.22\n2015-09-15 21:29:00,2.89\n2015-09-15 21:34:00,4.94\n2015-09-15 21:39:00,11.94\n2015-09-15 21:49:00,4.5\n2015-09-15 21:54:00,6.17\n2015-09-15 21:59:00,1.89\n2015-09-15 22:04:00,5.67\n2015-09-15 22:14:00,7.06\n2015-09-15 22:19:00,3.11\n2015-09-15 22:24:00,0.72\n2015-09-15 22:29:00,3.61\n2015-09-15 22:34:00,2.39\n2015-09-15 22:39:00,3.28\n2015-09-15 22:44:00,1.56\n2015-09-15 22:59:00,2.28\n2015-09-15 23:04:00,4.39\n2015-09-15 23:14:00,1\n2015-09-15 23:19:00,2.28\n2015-09-15 23:24:00,0.44\n2015-09-15 23:29:00,2.28\n2015-09-15 23:34:00,7.28\n2015-09-15 23:44:00,0.83\n2015-09-16 00:04:00,1.44\n2015-09-16 00:09:00,0.78\n2015-09-16 00:19:00,0.72\n2015-09-16 00:24:00,2.78\n2015-09-16 00:34:00,4.28\n2015-09-16 00:44:00,3.72\n2015-09-16 00:59:00,0.78\n2015-09-16 01:14:00,0.83\n2015-09-16 01:19:00,1.06\n2015-09-16 01:29:00,0.83\n2015-09-16 01:39:00,0.94\n2015-09-16 02:14:00,2.67\n2015-09-16 02:34:00,3.44\n2015-09-16 02:49:00,1.67\n2015-09-16 03:04:00,1.89\n2015-09-16 03:14:00,1.94\n2015-09-16 03:19:00,0.78\n2015-09-16 03:29:00,2.17\n2015-09-16 03:34:00,1.33\n2015-09-16 03:39:00,3.94\n2015-09-16 03:49:00,2.39\n2015-09-16 03:59:00,2.33\n2015-09-16 04:04:00,3.67\n2015-09-16 04:14:00,3.06\n2015-09-16 04:24:00,2.28\n2015-09-16 04:29:00,2.94\n2015-09-16 04:39:00,3.33\n2015-09-16 04:44:00,4.72\n2015-09-16 04:49:00,3.44\n2015-09-16 04:54:00,3.33\n2015-09-16 04:59:00,4.06\n2015-09-16 05:04:00,1.83\n2015-09-16 05:09:00,4.33\n2015-09-16 05:14:00,4.67\n2015-09-16 05:19:00,5.89\n2015-09-16 05:24:00,1.61\n2015-09-16 05:29:00,4.39\n2015-09-16 05:34:00,5.11\n2015-09-16 05:39:00,8.72\n2015-09-16 05:44:00,9.94\n2015-09-16 05:49:00,4.78\n2015-09-16 05:54:00,10.67\n2015-09-16 05:59:00,9.11\n2015-09-16 06:04:00,3.83\n2015-09-16 06:09:00,8.28\n2015-09-16 06:14:00,14.17\n2015-09-16 06:19:00,11.61\n2015-09-16 06:24:00,5.39\n2015-09-16 06:29:00,7.11\n2015-09-16 06:34:00,13.5\n2015-09-16 06:39:00,9.67\n2015-09-16 06:44:00,6.06\n2015-09-16 06:49:00,9.56\n2015-09-16 06:54:00,7.44\n2015-09-16 06:59:00,10.44\n2015-09-16 07:04:00,15.61\n2015-09-16 07:09:00,11.89\n2015-09-16 07:14:00,4.61\n2015-09-16 07:19:00,8.56\n2015-09-16 07:24:00,7.94\n2015-09-16 07:29:00,11.22\n2015-09-16 07:34:00,13.61\n2015-09-16 07:39:00,7.67\n2015-09-16 07:44:00,10.33\n2015-09-16 07:49:00,11.94\n2015-09-16 07:54:00,16.44\n2015-09-16 07:59:00,32.17\n2015-09-16 08:04:00,26\n2015-09-16 08:09:00,38.83\n2015-09-16 08:14:00,12.78\n2015-09-16 08:19:00,38.28\n2015-09-16 08:24:00,33.5\n2015-09-16 08:29:00,22.5\n2015-09-16 08:34:00,27.17\n2015-09-16 08:39:00,29.94\n2015-09-16 08:44:00,27.83\n2015-09-16 08:49:00,7.78\n2015-09-16 08:54:00,12.83\n2015-09-16 08:59:00,15.28\n2015-09-16 09:04:00,9.11\n2015-09-16 09:09:00,9.22\n2015-09-16 09:14:00,9.83\n2015-09-16 09:19:00,8.44\n2015-09-16 09:24:00,11.5\n2015-09-16 09:29:00,8\n2015-09-16 09:34:00,12.89\n2015-09-16 09:39:00,4.56\n2015-09-16 09:44:00,15.83\n2015-09-16 09:49:00,9.61\n2015-09-16 09:54:00,10.17\n2015-09-16 09:59:00,12.22\n2015-09-16 10:04:00,9.61\n2015-09-16 10:09:00,9\n2015-09-16 10:14:00,6.67\n2015-09-16 10:19:00,3.94\n2015-09-16 10:24:00,16.33\n2015-09-16 10:29:00,10\n2015-09-16 10:34:00,8.67\n2015-09-16 10:39:00,11.06\n2015-09-16 10:44:00,5.44\n2015-09-16 10:49:00,6.61\n2015-09-16 10:54:00,3.44\n2015-09-16 10:59:00,7.44\n2015-09-16 11:04:00,13.67\n2015-09-16 11:09:00,5.56\n2015-09-16 11:14:00,11.11\n2015-09-16 11:19:00,8.11\n2015-09-16 11:24:00,15.72\n2015-09-16 11:29:00,8.61\n2015-09-16 11:34:00,12.67\n2015-09-16 11:39:00,13.06\n2015-09-16 11:44:00,10.39\n2015-09-16 11:49:00,7.5\n2015-09-16 11:54:00,4.11\n2015-09-16 11:59:00,5.5\n2015-09-16 12:04:00,11.56\n2015-09-16 12:09:00,3.83\n2015-09-16 12:14:00,8.22\n2015-09-16 12:19:00,6.5\n2015-09-16 12:24:00,4.33\n2015-09-16 12:29:00,7.72\n2015-09-16 12:34:00,14\n2015-09-16 12:39:00,5.11\n2015-09-16 12:44:00,8.56\n2015-09-16 12:49:00,6.39\n2015-09-16 12:54:00,4\n2015-09-16 12:59:00,2.56\n2015-09-16 13:04:00,8.89\n2015-09-16 13:09:00,6.11\n2015-09-16 13:14:00,6.67\n2015-09-16 13:19:00,10\n2015-09-16 13:24:00,8.56\n2015-09-16 13:29:00,5.22\n2015-09-16 13:34:00,13.22\n2015-09-16 13:39:00,8.94\n2015-09-16 13:44:00,14.33\n2015-09-16 13:49:00,7.56\n2015-09-16 13:54:00,14.67\n2015-09-16 13:59:00,5.61\n2015-09-16 14:04:00,11.44\n2015-09-16 14:09:00,9.44\n2015-09-16 14:14:00,6.11\n2015-09-16 14:19:00,8.22\n2015-09-16 14:24:00,10.17\n2015-09-16 14:29:00,8.83\n2015-09-16 14:30:00,6.61\n2015-09-16 14:35:00,6\n2015-09-16 14:40:00,6.83\n2015-09-16 14:45:00,10.78\n2015-09-16 14:50:00,12.44\n2015-09-16 14:55:00,9.83\n2015-09-16 15:00:00,5.89\n2015-09-16 15:05:00,5.78\n2015-09-16 15:10:00,12.39\n2015-09-16 15:15:00,9.11\n2015-09-16 15:25:00,15.11\n2015-09-16 15:30:00,16\n2015-09-16 15:35:00,6.72\n2015-09-16 15:40:00,11.06\n2015-09-16 15:45:00,8.78\n2015-09-16 15:50:00,12.56\n2015-09-16 15:55:00,14.78\n2015-09-16 16:00:00,2.78\n2015-09-16 16:05:00,6.17\n2015-09-16 16:10:00,8.89\n2015-09-16 16:15:00,9.83\n2015-09-16 16:20:00,8.67\n2015-09-16 16:25:00,6.78\n2015-09-16 16:30:00,5.11\n2015-09-16 16:35:00,11.33\n2015-09-16 16:40:00,8.33\n2015-09-16 16:45:00,5.83\n2015-09-16 16:50:00,6.11\n2015-09-16 16:55:00,5.67\n2015-09-16 17:00:00,19\n2015-09-16 17:05:00,11.89\n2015-09-16 17:10:00,5.39\n2015-09-16 17:15:00,5.17\n2015-09-16 17:20:00,10.78\n2015-09-16 17:25:00,9.5\n2015-09-16 17:30:00,11.28\n2015-09-16 17:35:00,8.44\n2015-09-16 17:40:00,10.94\n2015-09-16 17:45:00,5.44\n2015-09-16 17:50:00,7.44\n2015-09-16 17:55:00,7\n2015-09-16 18:00:00,8.17\n2015-09-16 18:05:00,11.94\n2015-09-16 18:10:00,11.06\n2015-09-16 18:15:00,8.56\n2015-09-16 18:20:00,9\n2015-09-16 18:25:00,6.78\n2015-09-16 18:30:00,5.11\n2015-09-16 18:35:00,8.17\n2015-09-16 18:40:00,3.94\n2015-09-16 18:45:00,4.67\n2015-09-16 18:50:00,8.72\n2015-09-16 18:55:00,4.44\n2015-09-16 19:00:00,4.72\n2015-09-16 19:05:00,5.56\n2015-09-16 19:10:00,7.5\n2015-09-16 19:15:00,6.56\n2015-09-16 19:20:00,5.72\n2015-09-16 19:25:00,0.78\n2015-09-16 19:30:00,4.44\n2015-09-16 19:35:00,6.44\n2015-09-16 19:40:00,4.06\n2015-09-16 19:45:00,4.78\n2015-09-16 19:50:00,5.72\n2015-09-16 19:55:00,7.61\n2015-09-16 20:00:00,4.33\n2015-09-16 20:05:00,7.11\n2015-09-16 20:10:00,3.11\n2015-09-16 20:15:00,3.22\n2015-09-16 20:20:00,4.44\n2015-09-16 20:25:00,2.5\n2015-09-16 20:30:00,7\n2015-09-16 20:35:00,2.39\n2015-09-16 20:40:00,1.56\n2015-09-16 20:45:00,1.72\n2015-09-16 20:50:00,2.11\n2015-09-16 20:55:00,1.83\n2015-09-16 21:00:00,2.61\n2015-09-16 21:05:00,5.61\n2015-09-16 21:10:00,6.67\n2015-09-16 21:15:00,0.72\n2015-09-16 21:20:00,0.72\n2015-09-16 21:25:00,4.89\n2015-09-16 21:30:00,3.06\n2015-09-16 21:35:00,1.67\n2015-09-16 21:40:00,1.5\n2015-09-16 21:45:00,3.33\n2015-09-16 21:50:00,4.11\n2015-09-16 21:55:00,2.61\n2015-09-16 22:05:00,5.11\n2015-09-16 22:14:00,0.72\n2015-09-16 22:20:00,2.67\n2015-09-16 22:30:00,1.72\n2015-09-16 22:35:00,2.11\n2015-09-16 22:40:00,0.72\n2015-09-16 22:45:00,1.39\n2015-09-16 22:50:00,0.67\n2015-09-16 22:55:00,4.33\n2015-09-16 23:00:00,2.44\n2015-09-16 23:05:00,2.89\n2015-09-16 23:10:00,2.17\n2015-09-16 23:15:00,2.94\n2015-09-16 23:25:00,0.78\n2015-09-16 23:40:00,1.56\n2015-09-16 23:45:00,1.28\n2015-09-16 23:55:00,1.67\n2015-09-17 00:00:00,2.22\n2015-09-17 00:05:00,2.56\n2015-09-17 00:10:00,4.28\n2015-09-17 00:20:00,1.17\n2015-09-17 00:25:00,0.89\n2015-09-17 00:30:00,0.94\n2015-09-17 00:50:00,0.89\n2015-09-17 00:55:00,0.67\n2015-09-17 01:05:00,0.78\n2015-09-17 01:10:00,3.83\n2015-09-17 01:15:00,1.22\n2015-09-17 01:20:00,1\n2015-09-17 01:30:00,0.67\n2015-09-17 01:45:00,0.78\n2015-09-17 02:15:00,3.17\n2015-09-17 03:05:00,0.67\n2015-09-17 03:30:00,1.56\n2015-09-17 03:45:00,0.72\n2015-09-17 03:50:00,1.56\n2015-09-17 04:05:00,4.94\n2015-09-17 04:10:00,0.61\n2015-09-17 04:15:00,1.33\n2015-09-17 04:20:00,2.06\n2015-09-17 04:25:00,1.39\n2015-09-17 04:30:00,2.72\n2015-09-17 04:35:00,3.39\n2015-09-17 04:40:00,2.33\n2015-09-17 04:45:00,0\n2015-09-17 04:50:00,4.33\n2015-09-17 04:55:00,4.33\n2015-09-17 05:00:00,3.56\n2015-09-17 05:05:00,4.11\n2015-09-17 05:10:00,4.72\n2015-09-17 05:15:00,2.33\n2015-09-17 05:20:00,4.72\n2015-09-17 05:25:00,2.72\n2015-09-17 05:30:00,3.61\n2015-09-17 05:35:00,6.39\n2015-09-17 05:40:00,5.33\n2015-09-17 05:45:00,8.39\n2015-09-17 05:50:00,2.39\n2015-09-17 05:55:00,3.28\n2015-09-17 06:00:00,8.06\n2015-09-17 06:05:00,7.22\n2015-09-17 06:10:00,5.67\n2015-09-17 06:15:00,11.39\n2015-09-17 06:20:00,8.06\n2015-09-17 06:25:00,4.22\n2015-09-17 06:30:00,2.89\n2015-09-17 06:35:00,5.39\n2015-09-17 06:40:00,7\n2015-09-17 06:45:00,8.94\n2015-09-17 06:50:00,13.06\n2015-09-17 06:55:00,13\n2015-09-17 07:00:00,13.17\n2015-09-17 07:05:00,5.94\n2015-09-17 07:10:00,9\n2015-09-17 07:15:00,11.06\n2015-09-17 07:20:00,8.89\n2015-09-17 07:25:00,17.39\n2015-09-17 07:30:00,14.11\n2015-09-17 07:35:00,9.83\n2015-09-17 07:40:00,7.78\n2015-09-17 07:45:00,14.56\n2015-09-17 07:50:00,19\n2015-09-17 07:55:00,43.06\n2015-09-17 08:00:00,36.33\n2015-09-17 08:05:00,14.17\n2015-09-17 08:10:00,26.61\n2015-09-17 08:15:00,22.11\n2015-09-17 08:20:00,15.22\n2015-09-17 08:25:00,20.56\n2015-09-17 08:30:00,17.06\n2015-09-17 08:35:00,6.5\n2015-09-17 08:40:00,13.56\n2015-09-17 08:45:00,7.06\n2015-09-17 08:55:00,13.11\n2015-09-17 09:00:00,10.67\n2015-09-17 09:05:00,11.61\n2015-09-17 09:10:00,12.33\n2015-09-17 09:15:00,7.72\n2015-09-17 09:20:00,9.33\n2015-09-17 09:25:00,10.56\n2015-09-17 09:30:00,10.44\n2015-09-17 09:35:00,13.06\n2015-09-17 09:40:00,5.17\n2015-09-17 09:45:00,9.67\n2015-09-17 09:50:00,4\n2015-09-17 09:55:00,10.72\n2015-09-17 10:00:00,8.61\n2015-09-17 10:05:00,6.94\n2015-09-17 10:10:00,15.5\n2015-09-17 10:15:00,7.11\n2015-09-17 10:20:00,8.22\n2015-09-17 10:25:00,9.83\n2015-09-17 10:30:00,6.89\n2015-09-17 10:35:00,10.11\n2015-09-17 10:40:00,10.39\n2015-09-17 10:45:00,9.61\n2015-09-17 10:50:00,12.67\n2015-09-17 10:55:00,12.17\n2015-09-17 11:00:00,9.28\n2015-09-17 11:05:00,12.44\n2015-09-17 11:10:00,7.67\n2015-09-17 11:15:00,9.44\n2015-09-17 11:20:00,10.94\n2015-09-17 11:25:00,4.94\n2015-09-17 11:30:00,7.78\n2015-09-17 11:35:00,5.44\n2015-09-17 11:40:00,10\n2015-09-17 11:45:00,5.56\n2015-09-17 11:50:00,9.56\n2015-09-17 11:55:00,8.78\n2015-09-17 12:00:00,5.11\n2015-09-17 12:05:00,3.78\n2015-09-17 12:10:00,5.67\n2015-09-17 12:15:00,9.22\n2015-09-17 12:20:00,4.11\n2015-09-17 12:25:00,10.28\n2015-09-17 12:30:00,14.28\n2015-09-17 12:35:00,5.56\n2015-09-17 12:40:00,11.78\n2015-09-17 12:45:00,10.39\n2015-09-17 12:50:00,8.56\n2015-09-17 12:55:00,4.33\n2015-09-17 13:00:00,6.39\n2015-09-17 13:05:00,12.44\n2015-09-17 13:10:00,7.33\n2015-09-17 13:15:00,6.5\n2015-09-17 13:20:00,7.11\n2015-09-17 13:25:00,16.94\n2015-09-17 13:30:00,11.78\n2015-09-17 13:35:00,11.06\n2015-09-17 13:40:00,10.89\n2015-09-17 13:45:00,5.22\n2015-09-17 13:50:00,2.56\n2015-09-17 13:55:00,10.61\n2015-09-17 14:00:00,3.78\n2015-09-17 14:05:00,15.33\n2015-09-17 14:10:00,13.17\n2015-09-17 14:15:00,10.61\n2015-09-17 14:20:00,6.22\n2015-09-17 14:25:00,14.94\n2015-09-17 14:30:00,13.22\n2015-09-17 14:34:00,12.11\n2015-09-17 14:39:00,7.83\n2015-09-17 14:44:00,10.94\n2015-09-17 14:49:00,6.94\n2015-09-17 14:54:00,10\n2015-09-17 14:58:00,0.61\n2015-09-17 15:04:00,10.5\n2015-09-17 15:08:00,6.78\n2015-09-17 15:13:00,9.33\n2015-09-17 15:18:00,8.28\n2015-09-17 15:23:00,10.78\n2015-09-17 15:28:00,5.67\n2015-09-17 15:34:00,7.17\n2015-09-17 15:38:00,7.17\n2015-09-17 15:43:00,7.33\n2015-09-17 15:48:00,7.11\n2015-09-17 15:49:00,6.28\n2015-09-17 15:54:00,4.39\n2015-09-17 15:59:00,8.72\n2015-09-17 16:04:00,9.94\n2015-09-17 16:09:00,12.72\n2015-09-17 16:14:00,10\n2015-09-17 16:19:00,9.39\n2015-09-17 16:24:00,8.06"
  },
  {
    "path": "workspace/anomaly_detector/datasets/selected/trending/ambient_temperature_system_failure.csv",
    "content": "timestamp,value\n2013-07-04 00:00:00,69.88083514\n2013-07-04 01:00:00,71.22022706\n2013-07-04 02:00:00,70.87780496\n2013-07-04 03:00:00,68.95939994\n2013-07-04 04:00:00,69.28355102\n2013-07-04 05:00:00,70.06096581\n2013-07-04 06:00:00,69.27976479\n2013-07-04 07:00:00,69.36960846\n2013-07-04 08:00:00,69.16671394\n2013-07-04 09:00:00,68.98608257\n2013-07-04 10:00:00,69.96506224\n2013-07-04 11:00:00,70.55619466\n2013-07-04 12:00:00,70.30750511\n2013-07-04 13:00:00,70.24625215\n2013-07-04 14:00:00,69.85490839\n2013-07-04 15:00:00,71.64329118\n2013-07-04 16:00:00,71.24565942\n2013-07-04 17:00:00,70.74509976\n2013-07-04 18:00:00,71.37329829\n2013-07-04 19:00:00,71.7957509\n2013-07-04 20:00:00,72.09160609999998\n2013-07-04 21:00:00,71.55307612\n2013-07-04 22:00:00,72.18769545\n2013-07-04 23:00:00,70.64995744\n2013-07-05 00:00:00,71.34274211\n2013-07-05 01:00:00,71.5867281\n2013-07-05 02:00:00,70.97700116\n2013-07-05 03:00:00,70.24388209\n2013-07-05 04:00:00,70.43282627\n2013-07-05 05:00:00,69.74896285\n2013-07-05 06:00:00,68.74938222\n2013-07-05 07:00:00,69.35162661\n2013-07-05 08:00:00,68.85314844\n2013-07-05 09:00:00,70.31790951\n2013-07-05 10:00:00,70.30055692\n2013-07-05 11:00:00,72.53056283\n2013-07-05 12:00:00,71.64320692\n2013-07-05 13:00:00,72.92223804\n2013-07-05 14:00:00,72.63758833\n2013-07-05 15:00:00,72.95903086\n2013-07-05 16:00:00,72.15222081\n2013-07-05 17:00:00,72.16607562\n2013-07-05 18:00:00,72.30558574\n2013-07-05 19:00:00,72.3823022\n2013-07-05 20:00:00,72.61234869\n2013-07-05 21:00:00,72.77599570000002\n2013-07-05 22:00:00,71.91696888\n2013-07-05 23:00:00,71.55368851\n2013-07-06 00:00:00,71.63096403\n2013-07-06 01:00:00,70.59673521\n2013-07-06 02:00:00,70.85248247\n2013-07-06 03:00:00,71.08476824\n2013-07-06 04:00:00,70.84723252\n2013-07-06 05:00:00,70.23242259999999\n2013-07-06 06:00:00,70.12823808\n2013-07-06 07:00:00,69.92923136\n2013-07-06 08:00:00,69.28574982\n2013-07-06 09:00:00,69.72638712\n2013-07-06 10:00:00,68.19010253\n2013-07-06 11:00:00,68.91679541\n2013-07-06 12:00:00,67.26820458\n2013-07-06 13:00:00,66.9649601\n2013-07-06 14:00:00,67.76538379\n2013-07-06 15:00:00,66.91858576\n2013-07-06 16:00:00,67.60522282\n2013-07-06 17:00:00,67.17661097\n2013-07-06 18:00:00,67.99254044\n2013-07-06 19:00:00,67.25818019\n2013-07-06 20:00:00,66.59407898\n2013-07-06 21:00:00,67.86855757\n2013-07-06 22:00:00,67.2922007\n2013-07-06 23:00:00,67.16337656\n2013-07-07 00:00:00,66.27568448\n2013-07-07 01:00:00,65.96858705\n2013-07-07 02:00:00,65.31642297\n2013-07-07 03:00:00,65.42912751\n2013-07-07 04:00:00,66.75098393\n2013-07-07 05:00:00,64.68391715\n2013-07-07 06:00:00,64.56520692\n2013-07-07 07:00:00,66.12965686\n2013-07-07 08:00:00,66.09613054\n2013-07-07 09:00:00,64.9748123\n2013-07-07 10:00:00,64.33478963\n2013-07-07 11:00:00,65.54142516\n2013-07-07 12:00:00,63.9130944\n2013-07-07 13:00:00,65.00924432\n2013-07-07 14:00:00,64.04781966\n2013-07-07 15:00:00,64.25831852\n2013-07-07 16:00:00,63.89332373\n2013-07-07 17:00:00,64.14310465\n2013-07-07 18:00:00,64.17594209\n2013-07-07 19:00:00,63.1570819\n2013-07-07 20:00:00,63.38689893\n2013-07-07 21:00:00,63.99038726\n2013-07-07 22:00:00,62.67478854\n2013-07-07 23:00:00,64.24663357\n2013-07-08 00:00:00,62.48078508\n2013-07-08 01:00:00,62.03055446\n2013-07-08 02:00:00,63.41156044\n2013-07-08 03:00:00,61.70510991\n2013-07-08 04:00:00,62.77513946\n2013-07-08 05:00:00,61.36447611\n2013-07-08 06:00:00,61.68984072\n2013-07-08 07:00:00,62.20048874\n2013-07-08 08:00:00,62.98280722\n2013-07-08 09:00:00,64.44813096\n2013-07-08 10:00:00,65.33294727\n2013-07-08 11:00:00,66.51294379\n2013-07-08 12:00:00,67.88554227\n2013-07-08 13:00:00,67.22250712\n2013-07-08 14:00:00,68.08885127\n2013-07-08 15:00:00,68.55257476\n2013-07-08 16:00:00,70.32033392\n2013-07-08 17:00:00,70.48553783\n2013-07-08 18:00:00,72.33830154\n2013-07-08 19:00:00,71.1908248\n2013-07-08 20:00:00,70.75989770000002\n2013-07-08 21:00:00,70.57075487\n2013-07-08 22:00:00,68.88572309999999\n2013-07-08 23:00:00,68.36836764\n2013-07-09 00:00:00,68.42198714\n2013-07-09 01:00:00,67.55824354\n2013-07-09 02:00:00,66.4884322\n2013-07-09 03:00:00,66.00939653\n2013-07-09 04:00:00,64.88258671\n2013-07-09 05:00:00,65.79409771\n2013-07-09 06:00:00,65.69617694\n2013-07-09 07:00:00,66.14773729\n2013-07-09 08:00:00,67.47861967\n2013-07-09 09:00:00,67.43966413\n2013-07-09 10:00:00,68.50079012\n2013-07-09 11:00:00,69.93367814\n2013-07-09 12:00:00,70.66856782\n2013-07-09 13:00:00,69.43364009999999\n2013-07-09 14:00:00,70.20645921\n2013-07-09 15:00:00,70.23002897\n2013-07-09 16:00:00,71.58361231\n2013-07-09 17:00:00,71.56436778\n2013-07-09 18:00:00,71.02917453\n2013-07-09 19:00:00,72.831066\n2013-07-09 20:00:00,71.13716811\n2013-07-09 21:00:00,69.72083178\n2013-07-09 22:00:00,69.17560647\n2013-07-09 23:00:00,69.31959282\n2013-07-10 00:00:00,68.81260454\n2013-07-10 01:00:00,68.55716829\n2013-07-10 02:00:00,67.73062887\n2013-07-10 03:00:00,67.80815335\n2013-07-10 04:00:00,66.93277621\n2013-07-10 05:00:00,65.84066557\n2013-07-10 06:00:00,66.15467548\n2013-07-10 07:00:00,65.78125301\n2013-07-10 08:00:00,67.33388757\n2013-07-10 09:00:00,67.3485843\n2013-07-10 10:00:00,69.75301970000001\n2013-07-10 11:00:00,69.90438916\n2013-07-10 12:00:00,70.59424483\n2013-07-10 13:00:00,70.05946788\n2013-07-10 14:00:00,71.02625542\n2013-07-10 15:00:00,71.56116588\n2013-07-10 16:00:00,70.98303947\n2013-07-10 17:00:00,71.78059711\n2013-07-10 18:00:00,73.40419990000002\n2013-07-10 19:00:00,71.60391994\n2013-07-10 20:00:00,70.48045714\n2013-07-10 21:00:00,69.48780075\n2013-07-10 22:00:00,69.37470081\n2013-07-10 23:00:00,68.66754682\n2013-07-11 00:00:00,69.05640228\n2013-07-11 01:00:00,69.28118591\n2013-07-11 02:00:00,68.00921159\n2013-07-11 03:00:00,68.57902651\n2013-07-11 04:00:00,66.49549932\n2013-07-11 05:00:00,66.7500451\n2013-07-11 06:00:00,66.42304923\n2013-07-11 07:00:00,67.52779448\n2013-07-11 08:00:00,67.89346899\n2013-07-11 09:00:00,69.1011507\n2013-07-11 10:00:00,70.51575503\n2013-07-11 11:00:00,71.51359764\n2013-07-11 12:00:00,70.78913828\n2013-07-11 13:00:00,70.92408975\n2013-07-11 14:00:00,71.43667911\n2013-07-11 15:00:00,72.77048744\n2013-07-11 16:00:00,72.18360109\n2013-07-11 17:00:00,72.2317116\n2013-07-11 18:00:00,72.14511125\n2013-07-11 19:00:00,72.66568122\n2013-07-11 20:00:00,71.74663208\n2013-07-11 21:00:00,71.47523835\n2013-07-11 22:00:00,70.17998073\n2013-07-11 23:00:00,70.01828427\n2013-07-12 00:00:00,69.63409091\n2013-07-12 01:00:00,69.24166979\n2013-07-12 02:00:00,69.44746561\n2013-07-12 03:00:00,69.56135461\n2013-07-12 04:00:00,67.43148423\n2013-07-12 05:00:00,67.27588501\n2013-07-12 06:00:00,67.64302314\n2013-07-12 07:00:00,67.11633221\n2013-07-12 08:00:00,68.58615434\n2013-07-12 09:00:00,68.54878335\n2013-07-12 10:00:00,69.78361434\n2013-07-12 11:00:00,70.13666468\n2013-07-12 12:00:00,71.79856679999997\n2013-07-12 13:00:00,72.95326709\n2013-07-12 14:00:00,73.38358272\n2013-07-12 15:00:00,72.72556855\n2013-07-12 16:00:00,74.27730941\n2013-07-12 17:00:00,73.58946213\n2013-07-12 18:00:00,73.07774519\n2013-07-12 19:00:00,74.52428051\n2013-07-12 20:00:00,72.52552383\n2013-07-12 21:00:00,72.64264374\n2013-07-12 22:00:00,73.47727338\n2013-07-12 23:00:00,72.37521094\n2013-07-13 00:00:00,71.20816904\n2013-07-13 01:00:00,72.23586399\n2013-07-13 02:00:00,71.09992340000002\n2013-07-13 03:00:00,70.95986451\n2013-07-13 04:00:00,70.25370091\n2013-07-13 05:00:00,71.29442554\n2013-07-13 06:00:00,70.37620145\n2013-07-13 07:00:00,70.33534302\n2013-07-13 08:00:00,68.96127518\n2013-07-13 09:00:00,68.67478951\n2013-07-13 10:00:00,68.68142551\n2013-07-13 11:00:00,70.09922792\n2013-07-13 12:00:00,69.29115996\n2013-07-13 13:00:00,69.14944184\n2013-07-13 14:00:00,69.38045679999999\n2013-07-13 15:00:00,68.32729437\n2013-07-13 16:00:00,68.71167009999999\n2013-07-13 17:00:00,69.43031387\n2013-07-13 18:00:00,69.12568539\n2013-07-13 19:00:00,69.40509502\n2013-07-13 20:00:00,68.64876516\n2013-07-13 21:00:00,67.68106913\n2013-07-13 22:00:00,69.16363194\n2013-07-13 23:00:00,68.19982138\n2013-07-14 00:00:00,68.1347302\n2013-07-14 01:00:00,67.28588699\n2013-07-14 02:00:00,67.77737459\n2013-07-14 03:00:00,68.40400085\n2013-07-14 04:00:00,68.12434843\n2013-07-14 05:00:00,66.62975642\n2013-07-14 06:00:00,67.75402118\n2013-07-14 07:00:00,67.19706687\n2013-07-14 08:00:00,66.19511529\n2013-07-14 09:00:00,67.03467174\n2013-07-14 10:00:00,66.39229109\n2013-07-14 11:00:00,66.98910128\n2013-07-14 12:00:00,66.70652022\n2013-07-14 13:00:00,65.89533219\n2013-07-14 14:00:00,66.15310629999999\n2013-07-14 15:00:00,65.94826687\n2013-07-14 16:00:00,66.18545065\n2013-07-14 17:00:00,65.956704\n2013-07-14 18:00:00,66.58099932\n2013-07-14 19:00:00,67.19124175\n2013-07-14 20:00:00,66.74457508\n2013-07-14 21:00:00,65.89869767\n2013-07-14 22:00:00,65.51804828\n2013-07-14 23:00:00,65.98471013\n2013-07-15 00:00:00,66.62908319\n2013-07-15 01:00:00,64.90780861\n2013-07-15 02:00:00,64.9498236\n2013-07-15 03:00:00,65.64024470000001\n2013-07-15 04:00:00,64.33322178\n2013-07-15 05:00:00,65.81400458\n2013-07-15 06:00:00,64.19811908\n2013-07-15 07:00:00,65.79277627\n2013-07-15 08:00:00,66.47022878\n2013-07-15 09:00:00,66.21114689\n2013-07-15 10:00:00,68.4034625\n2013-07-15 11:00:00,69.51708004\n2013-07-15 12:00:00,69.39746721\n2013-07-15 13:00:00,70.91288645\n2013-07-15 14:00:00,70.88878119\n2013-07-15 15:00:00,71.10972093\n2013-07-15 16:00:00,72.96756108\n2013-07-15 17:00:00,72.02770961\n2013-07-15 18:00:00,73.95202783\n2013-07-15 19:00:00,73.37599022\n2013-07-15 20:00:00,73.50769737\n2013-07-15 21:00:00,72.71914771\n2013-07-15 22:00:00,72.47419791\n2013-07-15 23:00:00,72.0845572\n2013-07-16 00:00:00,70.36089703\n2013-07-16 01:00:00,71.0505306\n2013-07-16 02:00:00,71.07182369\n2013-07-16 03:00:00,70.51372607\n2013-07-16 04:00:00,70.18259029999999\n2013-07-16 05:00:00,69.85543379\n2013-07-16 06:00:00,67.99007603\n2013-07-16 07:00:00,68.45766038\n2013-07-16 08:00:00,68.27103298\n2013-07-16 09:00:00,68.96138225\n2013-07-16 10:00:00,69.74436809\n2013-07-16 11:00:00,70.61571518\n2013-07-16 12:00:00,71.17846267\n2013-07-16 13:00:00,72.386747\n2013-07-16 14:00:00,72.41193764\n2013-07-16 15:00:00,73.68813485\n2013-07-16 16:00:00,73.74326223\n2013-07-16 17:00:00,73.75611822\n2013-07-16 18:00:00,74.32401543\n2013-07-16 19:00:00,73.86398591\n2013-07-16 20:00:00,73.78849309\n2013-07-16 21:00:00,73.00264849\n2013-07-16 22:00:00,72.04541547\n2013-07-16 23:00:00,71.08743709\n2013-07-17 00:00:00,71.9849653\n2013-07-17 01:00:00,71.11160009999998\n2013-07-17 02:00:00,70.99668759999999\n2013-07-17 03:00:00,69.26084472\n2013-07-17 04:00:00,69.52490512\n2013-07-17 05:00:00,68.65398309\n2013-07-17 06:00:00,68.44222186\n2013-07-17 07:00:00,68.98691712\n2013-07-17 08:00:00,68.12116394\n2013-07-17 09:00:00,70.27706087\n2013-07-17 10:00:00,69.46657012\n2013-07-17 11:00:00,70.32267213\n2013-07-17 12:00:00,71.8078395\n2013-07-17 13:00:00,72.06436516\n2013-07-17 14:00:00,72.48594731\n2013-07-17 15:00:00,72.35822858\n2013-07-17 16:00:00,74.73026071\n2013-07-17 17:00:00,74.45593333\n2013-07-17 18:00:00,75.42083051\n2013-07-17 19:00:00,74.93021109\n2013-07-17 20:00:00,73.46169520000002\n2013-07-17 21:00:00,73.44264061\n2013-07-17 22:00:00,73.59425862\n2013-07-17 23:00:00,72.56355591\n2013-07-18 00:00:00,71.67826483\n2013-07-18 01:00:00,72.61615717\n2013-07-18 02:00:00,70.46155106\n2013-07-18 03:00:00,70.68690223\n2013-07-18 04:00:00,71.27823432\n2013-07-18 05:00:00,70.31179231\n2013-07-18 06:00:00,69.53791299\n2013-07-18 07:00:00,70.39827926\n2013-07-18 08:00:00,69.63338286\n2013-07-18 09:00:00,69.47214598\n2013-07-18 10:00:00,71.46398548\n2013-07-18 11:00:00,72.41314268\n2013-07-18 12:00:00,70.9737679\n2013-07-18 13:00:00,72.40852176\n2013-07-18 14:00:00,73.89859399\n2013-07-18 15:00:00,73.99496326\n2013-07-18 16:00:00,74.54050584\n2013-07-18 17:00:00,74.01063854\n2013-07-18 18:00:00,76.39001911\n2013-07-18 19:00:00,75.69719107\n2013-07-18 20:00:00,75.38408868\n2013-07-18 21:00:00,74.12498598\n2013-07-18 22:00:00,75.41434918\n2013-07-18 23:00:00,74.69411987\n2013-07-19 00:00:00,73.07657971\n2013-07-19 01:00:00,73.16384917\n2013-07-19 02:00:00,73.505794\n2013-07-19 03:00:00,74.12699807\n2013-07-19 04:00:00,73.71152259\n2013-07-19 05:00:00,71.98042488\n2013-07-19 06:00:00,71.25116014\n2013-07-19 07:00:00,72.16027157\n2013-07-19 08:00:00,71.37306717\n2013-07-19 09:00:00,71.51790632\n2013-07-19 10:00:00,72.2737793\n2013-07-19 11:00:00,71.8167371\n2013-07-19 12:00:00,73.80696593\n2013-07-19 13:00:00,72.94734057\n2013-07-19 14:00:00,75.32774091\n2013-07-19 15:00:00,75.75888894\n2013-07-19 16:00:00,75.61622646\n2013-07-19 17:00:00,74.80626301\n2013-07-19 18:00:00,75.95162112\n2013-07-19 19:00:00,75.00414728\n2013-07-19 20:00:00,75.7922298\n2013-07-19 21:00:00,75.93662081\n2013-07-19 22:00:00,74.08191979\n2013-07-19 23:00:00,74.0239745\n2013-07-20 00:00:00,73.62518064\n2013-07-20 01:00:00,73.55238749\n2013-07-20 02:00:00,74.17438898\n2013-07-20 03:00:00,72.87160933\n2013-07-20 04:00:00,72.28482269\n2013-07-20 05:00:00,73.51122601\n2013-07-20 06:00:00,72.89366827\n2013-07-20 07:00:00,72.14791650000002\n2013-07-20 08:00:00,72.9557522\n2013-07-20 09:00:00,72.42186823\n2013-07-20 10:00:00,70.665252\n2013-07-20 11:00:00,71.61263958\n2013-07-20 12:00:00,69.74580737\n2013-07-20 13:00:00,71.39185449\n2013-07-20 14:00:00,70.82733191\n2013-07-20 15:00:00,69.32886638\n2013-07-20 16:00:00,70.65200484\n2013-07-20 17:00:00,70.26620516\n2013-07-20 18:00:00,69.04063432\n2013-07-20 19:00:00,68.41965745\n2013-07-20 20:00:00,68.8585241\n2013-07-20 21:00:00,68.36710746\n2013-07-20 22:00:00,68.83774585\n2013-07-20 23:00:00,68.30402817\n2013-07-21 00:00:00,69.3689329\n2013-07-21 01:00:00,68.08187826\n2013-07-21 02:00:00,67.60392999\n2013-07-21 03:00:00,67.44621031\n2013-07-21 04:00:00,67.54039145\n2013-07-21 05:00:00,67.80852224\n2013-07-21 06:00:00,66.38552342\n2013-07-21 07:00:00,66.67172095\n2013-07-21 08:00:00,65.91622406\n2013-07-21 09:00:00,65.67154675\n2013-07-21 10:00:00,65.72519189\n2013-07-21 11:00:00,66.79848157\n2013-07-21 12:00:00,65.43107747\n2013-07-21 13:00:00,66.88734467\n2013-07-21 14:00:00,65.94946794\n2013-07-21 15:00:00,65.28216492\n2013-07-21 16:00:00,66.6497085\n2013-07-21 17:00:00,66.3990687\n2013-07-21 18:00:00,65.00919878\n2013-07-21 19:00:00,65.06137224\n2013-07-21 20:00:00,65.62911927\n2013-07-21 21:00:00,66.37157503\n2013-07-21 22:00:00,64.5293161\n2013-07-21 23:00:00,66.33871216\n2013-07-22 00:00:00,65.29158087\n2013-07-22 01:00:00,65.17119986\n2013-07-22 02:00:00,65.36758419\n2013-07-22 03:00:00,64.55987145\n2013-07-22 04:00:00,64.65845259\n2013-07-22 05:00:00,64.86762829999999\n2013-07-22 06:00:00,63.6094313\n2013-07-22 07:00:00,64.96073316\n2013-07-22 08:00:00,65.43995404\n2013-07-22 09:00:00,67.07099988\n2013-07-22 10:00:00,66.67125763\n2013-07-22 11:00:00,67.64060287\n2013-07-22 12:00:00,68.62797459999999\n2013-07-22 13:00:00,70.2454449\n2013-07-22 14:00:00,69.70567339\n2013-07-22 15:00:00,70.36650487\n2013-07-22 16:00:00,72.27945276\n2013-07-22 17:00:00,72.71664316\n2013-07-22 18:00:00,71.84306091\n2013-07-22 19:00:00,71.53844637\n2013-07-22 20:00:00,71.55812139\n2013-07-22 21:00:00,70.76534571\n2013-07-22 22:00:00,71.14242657\n2013-07-22 23:00:00,70.71393712\n2013-07-23 00:00:00,69.58966371\n2013-07-23 01:00:00,69.02299462\n2013-07-23 02:00:00,68.95729279\n2013-07-23 03:00:00,68.14795876\n2013-07-23 04:00:00,67.48635522\n2013-07-23 05:00:00,66.52278589\n2013-07-23 06:00:00,66.81771127\n2013-07-23 07:00:00,66.25215878\n2013-07-23 08:00:00,68.14487953\n2013-07-23 09:00:00,68.75540328\n2013-07-23 10:00:00,68.54546326\n2013-07-23 11:00:00,68.65504344\n2013-07-23 12:00:00,69.96525521\n2013-07-23 13:00:00,70.93097625\n2013-07-23 14:00:00,70.67200225\n2013-07-23 15:00:00,72.45541594\n2013-07-23 16:00:00,72.75267236\n2013-07-23 17:00:00,72.98703117\n2013-07-23 18:00:00,73.15160594\n2013-07-23 19:00:00,73.18754221\n2013-07-23 20:00:00,71.04274096\n2013-07-23 21:00:00,71.54354038\n2013-07-23 22:00:00,71.74520109\n2013-07-23 23:00:00,70.94274876\n2013-07-24 00:00:00,69.74530422\n2013-07-24 01:00:00,69.52726729\n2013-07-24 02:00:00,70.32903161\n2013-07-24 03:00:00,70.03017299\n2013-07-24 04:00:00,68.87043296\n2013-07-24 05:00:00,68.92349639\n2013-07-24 06:00:00,68.10636443\n2013-07-24 07:00:00,68.55988567\n2013-07-24 08:00:00,67.85392905\n2013-07-24 09:00:00,68.35577512\n2013-07-24 10:00:00,69.70795831\n2013-07-24 11:00:00,70.53390858\n2013-07-24 12:00:00,69.78024465\n2013-07-24 13:00:00,71.51678733\n2013-07-24 14:00:00,72.03103759999998\n2013-07-24 15:00:00,73.40007449\n2013-07-24 16:00:00,73.8675255\n2013-07-24 17:00:00,72.66779455\n2013-07-24 18:00:00,72.85222389\n2013-07-24 19:00:00,73.11323349999998\n2013-07-24 20:00:00,72.2813031\n2013-07-24 21:00:00,72.61561106\n2013-07-24 22:00:00,71.61517817\n2013-07-24 23:00:00,72.75668787\n2013-07-25 00:00:00,71.14354005\n2013-07-25 01:00:00,70.8585056\n2013-07-25 02:00:00,70.89259768\n2013-07-25 03:00:00,70.85000882\n2013-07-25 04:00:00,71.4091997\n2013-07-25 05:00:00,70.257825\n2013-07-25 06:00:00,69.82174319\n2013-07-25 07:00:00,69.39311984\n2013-07-25 08:00:00,69.94923869\n2013-07-25 09:00:00,70.35977277\n2013-07-25 10:00:00,71.59751048\n2013-07-25 11:00:00,71.15990415\n2013-07-25 12:00:00,72.51273013\n2013-07-25 13:00:00,73.02999473\n2013-07-25 14:00:00,72.09791824\n2013-07-25 15:00:00,72.92583014\n2013-07-25 16:00:00,73.86938351\n2013-07-25 17:00:00,73.91377788\n2013-07-25 18:00:00,74.46991144\n2013-07-25 19:00:00,73.21314175\n2013-07-25 20:00:00,74.51203141\n2013-07-25 21:00:00,72.84294254\n2013-07-25 22:00:00,73.43276491\n2013-07-25 23:00:00,73.30466379999999\n2013-07-26 00:00:00,72.81092703\n2013-07-26 01:00:00,72.86473466\n2013-07-26 02:00:00,71.38222869\n2013-07-26 03:00:00,71.19623896\n2013-07-26 04:00:00,71.03955791\n2013-07-26 05:00:00,72.27910059999998\n2013-07-26 06:00:00,70.21785723\n2013-07-26 07:00:00,70.31733297\n2013-07-26 08:00:00,69.78868463\n2013-07-26 09:00:00,70.88145123\n2013-07-26 10:00:00,71.61930479\n2013-07-26 11:00:00,72.28509323\n2013-07-26 12:00:00,72.77202114\n2013-07-26 13:00:00,73.24703993\n2013-07-26 14:00:00,72.80712104\n2013-07-26 15:00:00,72.58748947\n2013-07-26 16:00:00,74.68417583\n2013-07-26 17:00:00,73.09200323\n2013-07-26 18:00:00,74.09006089\n2013-07-26 19:00:00,74.61862587\n2013-07-26 20:00:00,73.81911639\n2013-07-26 21:00:00,74.57014385\n2013-07-26 22:00:00,72.69101123\n2013-07-26 23:00:00,73.56142292\n2013-07-27 00:00:00,73.77909916\n2013-07-27 01:00:00,72.91239911\n2013-07-27 02:00:00,73.48633826\n2013-07-27 03:00:00,72.73447053\n2013-07-27 04:00:00,71.62959719\n2013-07-27 05:00:00,72.41051865\n2013-07-27 06:00:00,71.64829313\n2013-07-27 07:00:00,71.34815297\n2013-07-27 08:00:00,70.69776199\n2013-07-27 09:00:00,70.47033288\n2013-07-27 10:00:00,71.02517791\n2013-07-27 11:00:00,69.83488902\n2013-07-27 12:00:00,71.50090936\n2013-07-27 13:00:00,70.40361959\n2013-07-27 14:00:00,70.54399168\n2013-07-27 15:00:00,71.85746328\n2013-07-27 16:00:00,71.15225757\n2013-07-27 17:00:00,72.78516393\n2013-07-27 18:00:00,73.36070500000002\n2013-07-27 19:00:00,72.86473047\n2013-07-27 20:00:00,72.70608578\n2013-07-27 21:00:00,73.85915886\n2013-07-27 22:00:00,73.50507967\n2013-07-27 23:00:00,72.19240313\n2013-07-28 00:00:00,72.13995763\n2013-07-28 01:00:00,72.76124036\n2013-07-28 03:00:00,72.78238947\n2013-07-28 04:00:00,71.89290086\n2013-07-29 12:00:00,73.24344321\n2013-07-29 13:00:00,73.25408094\n2013-07-29 14:00:00,72.61221201\n2013-07-29 15:00:00,73.02852459\n2013-07-29 16:00:00,73.29062043\n2013-07-29 17:00:00,74.12192813\n2013-07-29 18:00:00,75.04218319\n2013-07-29 19:00:00,75.01049779\n2013-07-29 20:00:00,74.14262591\n2013-07-29 21:00:00,73.92443272\n2013-07-29 22:00:00,74.65910397\n2013-07-29 23:00:00,74.79811406\n2013-07-30 00:00:00,74.46700925\n2013-07-30 01:00:00,73.29755441\n2013-07-30 02:00:00,73.68345172\n2013-07-30 03:00:00,72.34692708\n2013-07-30 04:00:00,73.24426001\n2013-07-30 05:00:00,72.14957625\n2013-07-30 06:00:00,72.41976913\n2013-07-30 07:00:00,71.31132501\n2013-07-30 08:00:00,71.70322328\n2013-07-30 09:00:00,72.25103685\n2013-07-30 10:00:00,71.97716389\n2013-07-30 11:00:00,71.39886276\n2013-07-30 12:00:00,71.59695286\n2013-07-30 13:00:00,72.63410157\n2013-07-30 14:00:00,73.23961797\n2013-07-30 15:00:00,72.52081721\n2013-07-30 16:00:00,74.01598050000003\n2013-07-30 17:00:00,73.67468353\n2013-07-30 18:00:00,75.75032693\n2013-07-30 19:00:00,74.3638755\n2013-07-30 20:00:00,74.41574553\n2013-07-30 21:00:00,74.22077381\n2013-07-30 22:00:00,75.24461638\n2013-07-30 23:00:00,75.76683279\n2013-07-31 00:00:00,75.2599283\n2013-07-31 01:00:00,75.00430133\n2013-07-31 02:00:00,72.99868724\n2013-07-31 03:00:00,74.22813959\n2013-07-31 04:00:00,73.86242657\n2013-07-31 05:00:00,73.64995716\n2013-07-31 06:00:00,72.4157443\n2013-07-31 07:00:00,72.33008672\n2013-07-31 08:00:00,72.6550647\n2013-07-31 09:00:00,72.28311126\n2013-07-31 10:00:00,73.03449417\n2013-07-31 11:00:00,72.28032012\n2013-07-31 12:00:00,71.87820491\n2013-07-31 13:00:00,73.40155661\n2013-07-31 14:00:00,74.44122979\n2013-07-31 15:00:00,73.87635966\n2013-07-31 16:00:00,73.90784081\n2013-07-31 17:00:00,75.16955484\n2013-07-31 18:00:00,75.15953611\n2013-07-31 19:00:00,74.80214938\n2013-07-31 20:00:00,76.28002237\n2013-07-31 21:00:00,74.85748264\n2013-07-31 22:00:00,75.92805235\n2013-07-31 23:00:00,75.91643042\n2013-08-01 00:00:00,74.39653829999997\n2013-08-01 01:00:00,75.10901277\n2013-08-01 02:00:00,74.09065784\n2013-08-01 03:00:00,74.99478559\n2013-08-01 04:00:00,74.49008385\n2013-08-01 05:00:00,74.15968431\n2013-08-01 06:00:00,73.77074883\n2013-08-01 07:00:00,73.761944\n2013-08-01 08:00:00,72.39267309\n2013-08-01 09:00:00,72.65461782\n2013-08-01 10:00:00,71.85842391\n2013-08-01 11:00:00,72.90726702\n2013-08-01 12:00:00,72.74347127\n2013-08-01 13:00:00,73.80882616\n2013-08-01 14:00:00,74.02068569\n2013-08-01 15:00:00,74.93830342\n2013-08-01 16:00:00,73.482711\n2013-08-01 17:00:00,74.16997946\n2013-08-01 18:00:00,74.01751843\n2013-08-01 19:00:00,74.49814040000003\n2013-08-01 20:00:00,76.3120219\n2013-08-01 21:00:00,75.08484325\n2013-08-01 22:00:00,74.65943066\n2013-08-01 23:00:00,75.82212698\n2013-08-02 00:00:00,74.8569766\n2013-08-02 01:00:00,73.98785798\n2013-08-02 02:00:00,74.22412386\n2013-08-02 03:00:00,74.51575386\n2013-08-02 04:00:00,74.45778211\n2013-08-02 05:00:00,74.12643606\n2013-08-02 06:00:00,73.99954302\n2013-08-02 07:00:00,72.26824527\n2013-08-02 08:00:00,73.7764128\n2013-08-02 09:00:00,72.90101937\n2013-08-02 10:00:00,72.11776996\n2013-08-02 11:00:00,72.92499217\n2013-08-02 12:00:00,72.05187563\n2013-08-02 13:00:00,72.38437545\n2013-08-02 14:00:00,74.07630529\n2013-08-02 15:00:00,74.61920753\n2013-08-02 16:00:00,75.08524938\n2013-08-02 17:00:00,75.82866138\n2013-08-02 18:00:00,75.42713311\n2013-08-02 19:00:00,76.56950166\n2013-08-02 20:00:00,76.17963379\n2013-08-02 21:00:00,74.94074803\n2013-08-02 22:00:00,74.76418837\n2013-08-02 23:00:00,74.12540695\n2013-08-03 00:00:00,74.84051371\n2013-08-03 01:00:00,73.79928772\n2013-08-03 02:00:00,74.780247\n2013-08-03 03:00:00,72.82864301\n2013-08-03 04:00:00,72.48177255\n2013-08-03 05:00:00,73.27429509999997\n2013-08-03 06:00:00,73.26715622\n2013-08-03 07:00:00,72.74611472\n2013-08-03 08:00:00,71.30564248\n2013-08-03 09:00:00,70.79796992\n2013-08-03 10:00:00,70.8324548\n2013-08-03 11:00:00,71.36899796\n2013-08-03 12:00:00,71.30600481\n2013-08-03 13:00:00,69.95127986\n2013-08-03 14:00:00,71.11183674\n2013-08-03 15:00:00,71.24355108\n2013-08-03 16:00:00,71.16602046\n2013-08-03 17:00:00,69.5362003\n2013-08-03 18:00:00,71.21599291\n2013-08-03 19:00:00,70.94704371\n2013-08-03 20:00:00,71.14172451\n2013-08-03 21:00:00,70.94719413\n2013-08-03 22:00:00,70.28093351\n2013-08-03 23:00:00,69.95038298\n2013-08-04 00:00:00,70.06016939\n2013-08-04 01:00:00,68.72937535\n2013-08-04 02:00:00,68.31124754\n2013-08-04 03:00:00,67.59938455\n2013-08-04 04:00:00,69.23919313\n2013-08-04 05:00:00,68.70527934\n2013-08-04 06:00:00,67.30881248\n2013-08-04 07:00:00,67.29093890000001\n2013-08-04 08:00:00,67.01058194\n2013-08-04 09:00:00,67.11700116\n2013-08-04 10:00:00,67.17114622\n2013-08-04 11:00:00,64.8612751\n2013-08-04 12:00:00,66.1031092\n2013-08-04 13:00:00,64.70015253\n2013-08-04 14:00:00,65.97732586\n2013-08-04 15:00:00,64.83488246\n2013-08-04 16:00:00,65.16140029\n2013-08-04 17:00:00,65.86503497\n2013-08-04 18:00:00,67.73521012\n2013-08-04 19:00:00,68.12101336\n2013-08-04 20:00:00,68.68838431\n2013-08-04 21:00:00,67.73402197\n2013-08-04 22:00:00,68.42818207\n2013-08-04 23:00:00,68.16946111\n2013-08-05 00:00:00,67.49229937\n2013-08-05 01:00:00,66.98395449\n2013-08-05 02:00:00,68.04064964\n2013-08-05 03:00:00,66.62055167\n2013-08-05 04:00:00,66.64744323\n2013-08-05 05:00:00,66.08743294\n2013-08-05 06:00:00,67.22510503\n2013-08-05 07:00:00,66.43247979\n2013-08-05 08:00:00,66.57052361\n2013-08-05 09:00:00,68.05327519\n2013-08-05 10:00:00,67.67038945\n2013-08-05 11:00:00,69.17031869\n2013-08-05 12:00:00,68.89948983\n2013-08-05 13:00:00,70.00978672\n2013-08-05 14:00:00,69.82913552\n2013-08-05 15:00:00,70.9242198\n2013-08-05 16:00:00,71.27814633\n2013-08-05 17:00:00,72.15965785\n2013-08-05 18:00:00,72.97618331\n2013-08-05 19:00:00,72.66683797\n2013-08-05 20:00:00,73.69117746\n2013-08-05 21:00:00,72.80151077\n2013-08-05 22:00:00,71.85931396\n2013-08-05 23:00:00,72.23815016\n2013-08-06 00:00:00,70.95862334\n2013-08-06 01:00:00,72.4688891\n2013-08-06 02:00:00,71.66219799\n2013-08-06 03:00:00,71.86755979\n2013-08-06 04:00:00,70.7802684\n2013-08-06 05:00:00,70.99083764\n2013-08-06 06:00:00,69.15653193\n2013-08-06 07:00:00,69.08522976\n2013-08-06 08:00:00,69.75214256\n2013-08-06 09:00:00,69.46942493\n2013-08-06 10:00:00,68.77679875\n2013-08-06 11:00:00,70.22714587\n2013-08-06 12:00:00,71.01598435\n2013-08-06 13:00:00,72.44743344\n2013-08-06 14:00:00,72.06658701\n2013-08-06 15:00:00,72.98693668\n2013-08-06 16:00:00,73.69835469\n2013-08-06 17:00:00,73.75209157\n2013-08-06 18:00:00,74.55800629\n2013-08-06 19:00:00,72.35247916\n2013-08-06 20:00:00,65.26017655\n2013-08-06 21:00:00,74.76223447\n2013-08-06 22:00:00,73.49525372\n2013-08-06 23:00:00,73.36538505\n2013-08-07 00:00:00,72.5976732\n2013-08-07 01:00:00,72.99425699999998\n2013-08-07 02:00:00,72.85282429\n2013-08-07 03:00:00,72.74890938\n2013-08-07 04:00:00,72.12765994\n2013-08-07 05:00:00,71.09856805\n2013-08-07 06:00:00,71.23849804\n2013-08-07 07:00:00,70.27255592\n2013-08-07 08:00:00,70.88395870000002\n2013-08-07 09:00:00,71.39022061\n2013-08-07 10:00:00,70.52089931\n2013-08-07 11:00:00,71.25419744\n2013-08-07 12:00:00,72.68993228\n2013-08-07 13:00:00,72.61074543\n2013-08-07 14:00:00,72.43902889\n2013-08-07 15:00:00,73.58512146\n2013-08-07 16:00:00,73.89459624\n2013-08-07 17:00:00,72.95170937\n2013-08-07 18:00:00,74.07563886\n2013-08-07 19:00:00,73.6806514\n2013-08-07 20:00:00,72.89217355\n2013-08-07 21:00:00,73.32218412\n2013-08-07 22:00:00,73.24266369\n2013-08-07 23:00:00,72.14171440000001\n2013-08-08 00:00:00,72.30380183\n2013-08-08 01:00:00,72.89276841\n2013-08-08 02:00:00,71.56299973\n2013-08-08 03:00:00,72.39705979\n2013-08-08 04:00:00,72.00657008\n2013-08-08 05:00:00,71.32736169\n2013-08-08 06:00:00,70.82135373\n2013-08-08 07:00:00,70.1336473\n2013-08-08 08:00:00,70.0467162\n2013-08-08 09:00:00,70.06918582\n2013-08-08 10:00:00,70.79634920000002\n2013-08-08 11:00:00,70.91540196\n2013-08-08 12:00:00,71.67451047\n2013-08-08 13:00:00,72.18760774\n2013-08-08 14:00:00,72.1207947\n2013-08-08 15:00:00,72.51156743\n2013-08-08 16:00:00,72.23695024\n2013-08-08 17:00:00,71.87503532\n2013-08-08 18:00:00,72.49582348\n2013-08-08 19:00:00,72.35768598\n2013-08-08 20:00:00,73.93378927\n2013-08-08 21:00:00,73.98233814\n2013-08-08 22:00:00,73.59560241\n2013-08-08 23:00:00,71.98821679\n2013-08-09 00:00:00,72.32396967\n2013-08-09 01:00:00,71.6259057\n2013-08-09 02:00:00,71.72859842\n2013-08-09 03:00:00,70.70127666\n2013-08-09 04:00:00,71.00161546\n2013-08-09 05:00:00,70.81636614\n2013-08-09 06:00:00,70.72324263\n2013-08-09 07:00:00,70.3860912\n2013-08-09 08:00:00,68.77908287\n2013-08-09 09:00:00,70.22778904\n2013-08-09 10:00:00,69.87258414\n2013-08-09 11:00:00,70.44715736\n2013-08-09 12:00:00,71.08361107\n2013-08-09 13:00:00,71.23292042\n2013-08-09 14:00:00,72.16067996\n2013-08-09 15:00:00,71.86722192\n2013-08-09 16:00:00,72.16014273\n2013-08-09 17:00:00,72.99568483\n2013-08-09 18:00:00,73.27572883\n2013-08-09 19:00:00,73.49417662\n2013-08-09 20:00:00,74.21107376\n2013-08-09 21:00:00,72.54083404\n2013-08-09 22:00:00,73.21324868\n2013-08-09 23:00:00,72.58771726\n2013-08-10 00:00:00,73.50120424\n2013-08-10 01:00:00,72.09154651\n2013-08-10 02:00:00,71.09042019\n2013-08-10 03:00:00,71.23416619\n2013-08-10 04:00:00,70.63012271\n2013-08-10 05:00:00,69.77541726\n2013-08-10 06:00:00,69.28687677\n2013-08-10 07:00:00,70.44057715\n2013-08-10 08:00:00,69.28731334\n2013-08-10 09:00:00,69.93728934\n2013-08-10 10:00:00,69.3391448\n2013-08-10 11:00:00,69.13334157\n2013-08-10 12:00:00,68.65929831\n2013-08-10 13:00:00,68.18197506\n2013-08-10 14:00:00,67.84812498\n2013-08-10 15:00:00,69.37597782\n2013-08-10 16:00:00,69.10036669\n2013-08-10 17:00:00,68.8546449\n2013-08-10 18:00:00,67.85837277\n2013-08-10 19:00:00,68.46916703\n2013-08-10 20:00:00,68.17855534\n2013-08-10 21:00:00,69.21501077\n2013-08-10 22:00:00,68.96464737\n2013-08-10 23:00:00,67.87377682\n2013-08-11 00:00:00,67.72178625\n2013-08-11 01:00:00,68.58499733\n2013-08-11 02:00:00,68.44962111\n2013-08-11 03:00:00,67.14273776\n2013-08-11 04:00:00,67.07599947\n2013-08-11 05:00:00,68.29349922\n2013-08-11 06:00:00,66.78969926\n2013-08-11 07:00:00,65.82622549\n2013-08-11 08:00:00,66.59954318\n2013-08-11 09:00:00,65.01332031\n2013-08-11 10:00:00,65.90620917\n2013-08-11 11:00:00,65.84496837\n2013-08-11 12:00:00,64.92189809\n2013-08-11 13:00:00,65.58278655\n2013-08-11 14:00:00,65.55748205\n2013-08-11 15:00:00,65.59894884\n2013-08-11 16:00:00,64.94337424\n2013-08-11 17:00:00,64.74950254\n2013-08-11 18:00:00,64.84844096\n2013-08-11 19:00:00,65.83625843\n2013-08-11 20:00:00,66.03749482\n2013-08-11 21:00:00,65.38311565\n2013-08-11 22:00:00,65.99967447\n2013-08-11 23:00:00,64.36458794\n2013-08-12 00:00:00,65.07952767\n2013-08-12 01:00:00,65.29604166\n2013-08-12 02:00:00,65.20610988\n2013-08-12 03:00:00,63.96596281\n2013-08-12 04:00:00,64.72425165\n2013-08-12 05:00:00,65.40331196\n2013-08-12 06:00:00,65.42865101\n2013-08-12 07:00:00,64.09801612\n2013-08-12 08:00:00,63.80900879\n2013-08-12 09:00:00,64.54585931\n2013-08-12 10:00:00,66.95784817\n2013-08-12 11:00:00,66.61279611\n2013-08-12 12:00:00,67.94979306\n2013-08-12 13:00:00,66.39778915\n2013-08-12 14:00:00,66.77796074\n2013-08-12 15:00:00,67.1940435\n2013-08-12 16:00:00,68.38187061\n2013-08-12 17:00:00,67.12861534\n2013-08-12 18:00:00,67.17067346\n2013-08-12 19:00:00,68.43923628\n2013-08-12 20:00:00,66.57086417\n2013-08-12 21:00:00,67.78803691\n2013-08-12 22:00:00,67.2787936\n2013-08-12 23:00:00,67.87219243\n2013-08-13 00:00:00,67.50915846\n2013-08-13 01:00:00,67.66070149\n2013-08-13 02:00:00,65.93597991\n2013-08-13 03:00:00,65.72336823\n2013-08-13 04:00:00,65.72245666\n2013-08-13 05:00:00,66.11658266\n2013-08-13 06:00:00,65.32184413\n2013-08-13 07:00:00,65.71791971\n2013-08-13 08:00:00,65.47364884\n2013-08-13 09:00:00,66.64929047\n2013-08-13 10:00:00,66.55123544\n2013-08-13 11:00:00,67.79521779999999\n2013-08-13 12:00:00,68.14077842\n2013-08-13 13:00:00,69.79685244\n2013-08-13 14:00:00,70.34622184\n2013-08-13 15:00:00,69.32175382\n2013-08-13 16:00:00,69.89015017\n2013-08-13 17:00:00,71.58845383\n2013-08-13 18:00:00,71.86175982\n2013-08-13 19:00:00,72.7410679\n2013-08-13 20:00:00,71.90458946\n2013-08-13 21:00:00,71.28351048\n2013-08-13 22:00:00,70.09728390000001\n2013-08-13 23:00:00,69.27726512\n2013-08-14 00:00:00,68.92546699\n2013-08-14 01:00:00,68.55186335\n2013-08-14 02:00:00,67.65673848\n2013-08-14 03:00:00,68.32131351\n2013-08-14 04:00:00,68.12150858\n2013-08-14 05:00:00,66.5554972\n2013-08-14 06:00:00,66.38718242\n2013-08-14 07:00:00,66.99569939\n2013-08-14 08:00:00,65.87173899\n2013-08-14 09:00:00,67.22433388\n2013-08-14 10:00:00,68.40446699\n2013-08-14 11:00:00,68.74846629999999\n2013-08-14 12:00:00,69.32469028\n2013-08-14 13:00:00,71.15467576\n2013-08-14 14:00:00,71.05227306\n2013-08-14 15:00:00,70.83181931\n2013-08-14 16:00:00,70.91625104\n2013-08-14 17:00:00,72.39488293\n2013-08-14 18:00:00,71.98328520000003\n2013-08-14 19:00:00,72.37378341\n2013-08-14 20:00:00,71.80748327\n2013-08-14 21:00:00,72.54903002\n2013-08-14 22:00:00,71.18557043\n2013-08-14 23:00:00,70.6560059\n2013-08-15 00:00:00,71.42334777\n2013-08-15 01:00:00,69.34699767\n2013-08-15 02:00:00,70.73289851\n2013-08-15 03:00:00,68.5593425\n2013-08-15 04:00:00,69.75429868\n2013-08-15 05:00:00,69.42528082\n2013-08-15 06:00:00,68.78050479\n2013-08-15 07:00:00,67.57592345\n2013-08-15 08:00:00,67.31292692\n2013-08-15 09:00:00,68.61465054\n2013-08-15 10:00:00,68.93048832\n2013-08-15 11:00:00,70.42238762\n2013-08-15 12:00:00,70.84558646\n2013-08-15 13:00:00,71.06424324\n2013-08-15 14:00:00,72.69610401\n2013-08-15 15:00:00,72.32617126\n2013-08-15 16:00:00,72.22167626\n2013-08-15 17:00:00,73.21437055\n2013-08-15 18:00:00,73.15708957\n2013-08-15 19:00:00,73.49412607\n2013-08-15 20:00:00,72.3006671\n2013-08-15 21:00:00,73.86668101\n2013-08-15 22:00:00,72.6701852\n2013-08-15 23:00:00,72.7624445\n2013-08-16 00:00:00,72.76328752\n2013-08-16 01:00:00,71.3147316\n2013-08-16 02:00:00,71.43288687\n2013-08-16 03:00:00,70.82264418\n2013-08-16 04:00:00,70.66687081\n2013-08-16 05:00:00,70.43909465\n2013-08-16 06:00:00,69.81296825\n2013-08-16 07:00:00,69.69858982\n2013-08-16 08:00:00,68.34291749\n2013-08-16 09:00:00,69.78913221\n2013-08-16 10:00:00,69.04301127\n2013-08-16 11:00:00,71.2618595\n2013-08-16 12:00:00,71.53303086\n2013-08-16 13:00:00,71.2414772\n2013-08-16 14:00:00,73.36763803\n2013-08-16 15:00:00,73.57415941\n2013-08-16 16:00:00,72.24425435\n2013-08-16 17:00:00,74.26516471\n2013-08-16 18:00:00,72.92651196\n2013-08-16 19:00:00,74.39635211\n2013-08-16 20:00:00,74.11889706\n2013-08-16 21:00:00,72.19232832\n2013-08-16 22:00:00,73.73903840000001\n2013-08-16 23:00:00,72.2079627\n2013-08-17 00:00:00,72.96446399\n2013-08-17 01:00:00,72.47851039\n2013-08-17 02:00:00,71.26534459\n2013-08-17 03:00:00,70.53066333\n2013-08-17 04:00:00,71.25037104\n2013-08-17 05:00:00,70.43519581\n2013-08-17 06:00:00,70.42341332\n2013-08-17 07:00:00,70.79164337\n2013-08-17 08:00:00,68.95439433\n2013-08-17 09:00:00,70.34051981\n2013-08-17 10:00:00,69.80542162\n2013-08-17 11:00:00,68.64316206\n2013-08-17 12:00:00,69.38668045\n2013-08-17 13:00:00,68.78927469999999\n2013-08-17 14:00:00,68.83952616\n2013-08-17 15:00:00,67.63291116\n2013-08-17 16:00:00,68.40694416\n2013-08-17 17:00:00,69.14007715\n2013-08-17 18:00:00,69.11590587\n2013-08-17 19:00:00,68.03579823\n2013-08-17 20:00:00,69.27272007\n2013-08-17 21:00:00,68.75322294\n2013-08-17 22:00:00,69.56566049\n2013-08-17 23:00:00,68.17712131\n2013-08-18 00:00:00,67.79477436\n2013-08-18 01:00:00,67.49347171\n2013-08-18 02:00:00,67.79427593\n2013-08-18 03:00:00,67.70107774\n2013-08-18 04:00:00,67.26294021\n2013-08-18 05:00:00,66.86984441\n2013-08-18 06:00:00,66.14932783\n2013-08-18 07:00:00,66.42313039\n2013-08-18 08:00:00,67.0524877\n2013-08-18 09:00:00,65.34818634\n2013-08-18 10:00:00,65.89940057\n2013-08-18 11:00:00,66.64739688\n2013-08-18 12:00:00,66.64122284\n2013-08-18 13:00:00,64.79138473\n2013-08-18 14:00:00,65.90167301\n2013-08-18 15:00:00,65.74127604\n2013-08-18 16:00:00,65.45031794\n2013-08-18 17:00:00,66.16094532\n2013-08-18 18:00:00,65.7044379\n2013-08-18 19:00:00,64.77549911\n2013-08-18 20:00:00,66.10922106\n2013-08-18 21:00:00,64.65138267\n2013-08-18 22:00:00,64.63763005\n2013-08-18 23:00:00,64.86524307\n2013-08-19 00:00:00,64.67189696\n2013-08-19 01:00:00,64.46795885\n2013-08-19 02:00:00,65.91187512\n2013-08-19 03:00:00,64.34806529\n2013-08-19 04:00:00,63.99581812\n2013-08-19 05:00:00,65.39461929\n2013-08-19 06:00:00,64.65292546\n2013-08-19 07:00:00,63.25807837\n2013-08-19 08:00:00,63.73827199\n2013-08-19 09:00:00,64.48038308\n2013-08-19 10:00:00,65.99746656\n2013-08-19 11:00:00,66.25822123\n2013-08-19 12:00:00,68.10328147\n2013-08-19 13:00:00,67.8042515\n2013-08-19 14:00:00,69.4870625\n2013-08-19 15:00:00,70.03024494\n2013-08-19 16:00:00,70.29600481\n2013-08-19 17:00:00,71.04468694\n2013-08-19 18:00:00,72.07494806\n2013-08-19 19:00:00,71.92135771\n2013-08-19 20:00:00,72.83067187\n2013-08-19 21:00:00,71.98101498\n2013-08-19 22:00:00,69.32089454\n2013-08-19 23:00:00,70.13159511\n2013-08-20 00:00:00,70.00507257\n2013-08-20 01:00:00,69.43663186\n2013-08-20 02:00:00,68.94680541\n2013-08-20 03:00:00,67.39526388\n2013-08-20 04:00:00,66.86451228\n2013-08-20 05:00:00,67.61515255\n2013-08-20 06:00:00,67.50015115\n2013-08-20 07:00:00,67.06492539999999\n2013-08-20 08:00:00,66.18109356\n2013-08-20 09:00:00,67.67862944\n2013-08-20 10:00:00,67.28780716\n2013-08-20 11:00:00,68.64887048\n2013-08-20 12:00:00,68.03818943\n2013-08-20 13:00:00,69.43733797\n2013-08-20 14:00:00,69.42521625\n2013-08-20 15:00:00,70.34561943\n2013-08-20 16:00:00,70.30816394\n2013-08-20 17:00:00,70.8360583\n2013-08-20 18:00:00,71.1470857\n2013-08-20 19:00:00,71.57781772\n2013-08-20 20:00:00,72.19406331\n2013-08-20 21:00:00,72.28995087\n2013-08-20 22:00:00,71.14766239\n2013-08-20 23:00:00,69.76492572\n2013-08-21 00:00:00,69.91788048\n2013-08-21 01:00:00,69.25384854\n2013-08-21 02:00:00,67.70300258\n2013-08-21 03:00:00,67.34860655\n2013-08-21 04:00:00,67.03007179\n2013-08-21 05:00:00,67.02774425\n2013-08-21 06:00:00,66.79530391\n2013-08-21 07:00:00,65.29474687\n2013-08-21 08:00:00,66.61324069\n2013-08-21 09:00:00,66.79489002\n2013-08-21 10:00:00,66.72432203\n2013-08-21 11:00:00,66.81536983\n2013-08-21 12:00:00,67.17358633\n2013-08-21 13:00:00,67.63012369\n2013-08-21 14:00:00,67.48754605\n2013-08-21 15:00:00,67.33171806\n2013-08-21 16:00:00,69.7284424\n2013-08-21 17:00:00,69.89615603\n2013-08-21 18:00:00,68.99214926\n2013-08-21 19:00:00,70.03999165\n2013-08-21 20:00:00,70.55714223\n2013-08-21 21:00:00,70.17848707\n2013-08-21 22:00:00,68.21913112\n2013-08-21 23:00:00,68.40833713\n2013-08-22 00:00:00,68.94808523\n2013-08-22 01:00:00,67.38899521\n2013-08-22 02:00:00,68.05245103\n2013-08-22 03:00:00,67.21188517\n2013-08-22 04:00:00,65.70328183\n2013-08-22 05:00:00,67.16985267\n2013-08-22 06:00:00,66.55460769\n2013-08-22 07:00:00,65.72798535\n2013-08-22 08:00:00,65.75716876\n2013-08-22 09:00:00,67.16913702\n2013-08-22 10:00:00,67.21744752\n2013-08-22 11:00:00,68.42865711\n2013-08-22 12:00:00,67.939555\n2013-08-22 13:00:00,68.21272047\n2013-08-22 14:00:00,68.59771355\n2013-08-22 15:00:00,69.8746694\n2013-08-22 16:00:00,69.78932095\n2013-08-22 17:00:00,71.20599841\n2013-08-22 18:00:00,71.58253869\n2013-08-22 19:00:00,71.88959565\n2013-08-22 20:00:00,71.86056438\n2013-08-22 21:00:00,72.04256027\n2013-08-22 22:00:00,71.39573223\n2013-08-22 23:00:00,69.55668318\n2013-08-23 00:00:00,68.93024269\n2013-08-23 01:00:00,69.66341833\n2013-08-23 02:00:00,69.04101322\n2013-08-23 03:00:00,67.96747227\n2013-08-23 04:00:00,69.31576272\n2013-08-23 05:00:00,68.15040455\n2013-08-23 06:00:00,68.35613984\n2013-08-23 07:00:00,67.76316051\n2013-08-23 08:00:00,67.03590822\n2013-08-23 09:00:00,67.39406286\n2013-08-23 10:00:00,68.68188132\n2013-08-23 11:00:00,70.23539114\n2013-08-23 12:00:00,70.72213492\n2013-08-23 13:00:00,70.58200639\n2013-08-23 14:00:00,71.80797978\n2013-08-23 15:00:00,70.57872691\n2013-08-23 16:00:00,72.0077339\n2013-08-23 17:00:00,71.71571281\n2013-08-23 18:00:00,72.11695816\n2013-08-23 19:00:00,72.64909676\n2013-08-23 20:00:00,71.43282886\n2013-08-23 21:00:00,71.71418699\n2013-08-23 22:00:00,72.28243141\n2013-08-23 23:00:00,72.25217338\n2013-08-24 00:00:00,71.74318478\n2013-08-24 01:00:00,69.68874182\n2013-08-24 02:00:00,70.11075437\n2013-08-24 03:00:00,68.69315914\n2013-08-24 04:00:00,68.49395196\n2013-08-24 05:00:00,69.05769349\n2013-08-24 06:00:00,67.38563023\n2013-08-24 07:00:00,68.51017483\n2013-08-24 08:00:00,68.046038\n2013-08-24 09:00:00,66.69591868\n2013-08-24 10:00:00,67.0893911\n2013-08-24 11:00:00,66.22561571\n2013-08-24 12:00:00,66.50296546\n2013-08-24 13:00:00,65.29980537\n2013-08-24 14:00:00,65.44279328\n2013-08-24 15:00:00,65.87726412\n2013-08-24 16:00:00,65.57372439\n2013-08-24 17:00:00,65.68296557\n2013-08-24 18:00:00,66.93568163\n2013-08-24 19:00:00,66.69982543\n2013-08-24 20:00:00,65.99025408\n2013-08-24 21:00:00,65.93769573\n2013-08-24 22:00:00,67.04970768\n2013-08-24 23:00:00,66.73555970000001\n2013-08-25 00:00:00,66.23665366\n2013-08-25 01:00:00,66.23546935\n2013-08-25 02:00:00,66.85525388\n2013-08-25 03:00:00,65.44418785\n2013-08-25 04:00:00,66.70939032\n2013-08-25 05:00:00,64.88554717\n2013-08-25 06:00:00,64.35080723\n2013-08-25 07:00:00,64.38802527\n2013-08-25 08:00:00,64.40835278\n2013-08-25 09:00:00,64.42226129\n2013-08-25 10:00:00,64.05518099\n2013-08-25 11:00:00,64.71716427\n2013-08-25 12:00:00,64.45389357\n2013-08-25 13:00:00,64.50166125\n2013-08-25 14:00:00,64.01651861\n2013-08-25 15:00:00,62.85522295\n2013-08-25 16:00:00,64.23986264\n2013-08-25 17:00:00,63.38848875\n2013-08-25 18:00:00,63.39183252\n2013-08-25 19:00:00,65.20905227\n2013-08-25 20:00:00,64.94516739\n2013-08-25 21:00:00,64.25107982\n2013-08-25 22:00:00,64.17982393\n2013-08-25 23:00:00,64.38921578\n2013-08-26 00:00:00,64.49909975\n2013-08-26 01:00:00,65.09660852\n2013-08-26 02:00:00,63.40543705\n2013-08-26 03:00:00,63.83826011\n2013-08-26 04:00:00,63.68217925\n2013-08-26 05:00:00,63.32128642\n2013-08-26 06:00:00,63.45009249\n2013-08-26 07:00:00,63.58602877\n2013-08-26 08:00:00,62.73132759\n2013-08-26 09:00:00,64.6219447\n2013-08-26 10:00:00,65.04527027\n2013-08-26 11:00:00,65.66669249\n2013-08-26 12:00:00,66.04597893\n2013-08-26 13:00:00,66.92945334\n2013-08-26 14:00:00,68.27335848\n2013-08-26 15:00:00,68.03643251\n2013-08-26 16:00:00,68.32526303\n2013-08-26 17:00:00,69.45241625\n2013-08-26 18:00:00,69.292876\n2013-08-26 19:00:00,69.61637759\n2013-08-26 20:00:00,69.09830136\n2013-08-26 21:00:00,68.9295352\n2013-08-26 22:00:00,68.38166541\n2013-08-26 23:00:00,66.69776707\n2013-08-27 00:00:00,66.55923923\n2013-08-27 01:00:00,65.50421593\n2013-08-27 02:00:00,65.36283826\n2013-08-27 03:00:00,65.03631072\n2013-08-27 04:00:00,64.28289583\n2013-08-27 05:00:00,64.70837708\n2013-08-27 06:00:00,65.19959422\n2013-08-27 07:00:00,64.37599177\n2013-08-27 08:00:00,65.80010808\n2013-08-27 09:00:00,66.90052411\n2013-08-27 10:00:00,65.97556180000001\n2013-08-27 11:00:00,67.21755426\n2013-08-29 11:00:00,67.61970814\n2013-08-29 12:00:00,68.68919867\n2013-08-29 13:00:00,68.99230755\n2013-08-29 14:00:00,69.01270334\n2013-08-29 15:00:00,69.60076165\n2013-08-29 16:00:00,70.62180453\n2013-08-29 17:00:00,70.80389723\n2013-08-29 18:00:00,71.95049453\n2013-08-29 19:00:00,71.45525932\n2013-08-29 20:00:00,70.69089941\n2013-08-29 21:00:00,70.84845568\n2013-08-29 22:00:00,71.14711094\n2013-08-29 23:00:00,70.19670613\n2013-08-30 00:00:00,70.26757380000001\n2013-08-30 01:00:00,70.3477134\n2013-08-30 02:00:00,68.94715476\n2013-08-30 03:00:00,68.19452413\n2013-08-30 04:00:00,67.41217981\n2013-08-30 05:00:00,67.6915133\n2013-08-30 06:00:00,68.1326941\n2013-08-30 07:00:00,67.72304464\n2013-08-30 08:00:00,67.00024303\n2013-08-30 09:00:00,68.33122058\n2013-08-30 10:00:00,68.77081792\n2013-08-30 11:00:00,67.89464946\n2013-08-30 12:00:00,70.32897545\n2013-08-30 13:00:00,69.94984745\n2013-08-30 14:00:00,69.04940045\n2013-08-30 15:00:00,70.48680148\n2013-08-30 16:00:00,70.73164318\n2013-08-30 17:00:00,70.27130965\n2013-08-30 18:00:00,70.56771532\n2013-08-30 19:00:00,70.52348927\n2013-08-30 20:00:00,70.94288585\n2013-08-30 21:00:00,70.09622236\n2013-08-30 22:00:00,70.92253659999999\n2013-08-30 23:00:00,69.73699276\n2013-08-31 00:00:00,69.50362657\n2013-08-31 01:00:00,68.74107885\n2013-08-31 02:00:00,67.98350404\n2013-08-31 03:00:00,68.65775842\n2013-08-31 04:00:00,69.01901831\n2013-08-31 05:00:00,68.7557281\n2013-08-31 06:00:00,67.6440132\n2013-08-31 07:00:00,67.09824802\n2013-08-31 08:00:00,68.86076740000001\n2013-08-31 09:00:00,68.54857064\n2013-08-31 10:00:00,68.10020545\n2013-08-31 11:00:00,67.3162411\n2013-08-31 12:00:00,67.37946307\n2013-08-31 13:00:00,68.16976322\n2013-08-31 14:00:00,68.33976301\n2013-08-31 15:00:00,68.55040093\n2013-08-31 16:00:00,67.16532869\n2013-08-31 17:00:00,67.30479343\n2013-08-31 18:00:00,66.79372649\n2013-08-31 19:00:00,66.97126902\n2013-08-31 20:00:00,66.36018507\n2013-08-31 21:00:00,67.20420628\n2013-08-31 22:00:00,68.07608732\n2013-08-31 23:00:00,67.23191893\n2013-09-01 00:00:00,67.78175194\n2013-09-01 01:00:00,66.07614673\n2013-09-01 02:00:00,66.11011254\n2013-09-01 03:00:00,67.10977933\n2013-09-01 04:00:00,67.52951352\n2013-09-01 05:00:00,67.37827727\n2013-09-01 06:00:00,67.10470918\n2013-09-01 07:00:00,66.9472606\n2013-09-01 08:00:00,67.13996477\n2013-09-01 09:00:00,66.67085420000001\n2013-09-01 10:00:00,65.9378113\n2013-09-01 11:00:00,66.5151767\n2013-09-01 12:00:00,66.072041\n2013-09-01 13:00:00,66.3918316\n2013-09-01 14:00:00,65.43023923\n2013-09-01 15:00:00,65.6508534\n2013-09-01 16:00:00,66.13170688\n2013-09-01 17:00:00,65.63831743\n2013-09-01 18:00:00,65.95578224\n2013-09-01 19:00:00,67.36956957\n2013-09-01 20:00:00,67.02516809\n2013-09-01 21:00:00,66.72385597\n2013-09-01 22:00:00,67.25433659\n2013-09-01 23:00:00,68.06762583\n2013-09-02 00:00:00,68.2229547\n2013-09-02 01:00:00,66.04236184\n2013-09-02 02:00:00,66.95310877\n2013-09-02 03:00:00,66.30459021\n2013-09-02 04:00:00,66.61170465\n2013-09-02 05:00:00,64.69937871\n2013-09-02 06:00:00,66.21768604\n2013-09-02 07:00:00,65.95636186\n2013-09-02 08:00:00,65.97202741\n2013-09-02 09:00:00,67.53287993\n2013-09-02 10:00:00,67.49599206\n2013-09-02 11:00:00,67.72868098\n2013-09-02 12:00:00,68.32218023\n2013-09-02 13:00:00,68.08308598\n2013-09-02 14:00:00,68.607251\n2013-09-02 15:00:00,68.77487445\n2013-09-02 16:00:00,68.7696785\n2013-09-02 17:00:00,68.64186817\n2013-09-02 18:00:00,70.62377265\n2013-09-02 19:00:00,69.50433389\n2013-09-02 20:00:00,68.92231254\n2013-09-02 21:00:00,70.48760069\n2013-09-02 22:00:00,68.22783476\n2013-09-02 23:00:00,69.04882691\n2013-09-03 00:00:00,67.74723934\n2013-09-03 01:00:00,68.09114575\n2013-09-03 02:00:00,68.65891435\n2013-09-03 03:00:00,69.63167183\n2013-09-03 04:00:00,69.57087107\n2013-09-03 05:00:00,68.92351224\n2013-09-03 06:00:00,67.53393503\n2013-09-03 07:00:00,68.2712078\n2013-09-03 08:00:00,68.65631055\n2013-09-03 09:00:00,67.39411119\n2013-09-03 10:00:00,68.37006622\n2013-09-03 11:00:00,68.23821811\n2013-09-03 12:00:00,68.24746423\n2013-09-03 13:00:00,67.42129150000001\n2013-09-03 14:00:00,67.17151006\n2013-09-03 15:00:00,68.84601436\n2013-09-03 16:00:00,68.98532397\n2013-09-03 17:00:00,68.6852691\n2013-09-03 18:00:00,70.38096941\n2013-09-03 19:00:00,70.63271507\n2013-09-03 20:00:00,70.71181053\n2013-09-03 21:00:00,71.77605259\n2013-09-03 22:00:00,71.9902121\n2013-09-03 23:00:00,70.50334409\n2013-09-04 00:00:00,70.02106963\n2013-09-04 01:00:00,71.10226832\n2013-09-04 02:00:00,71.07281481\n2013-09-04 03:00:00,71.00298194\n2013-09-04 04:00:00,69.64750524\n2013-09-04 05:00:00,69.29922688\n2013-09-04 06:00:00,70.19295937\n2013-09-04 07:00:00,69.59298326\n2013-09-04 08:00:00,69.94483099\n2013-09-04 09:00:00,68.38753638\n2013-09-04 10:00:00,70.12778664\n2013-09-04 11:00:00,69.75996879\n2013-09-04 12:00:00,70.57663801\n2013-09-04 13:00:00,70.11459489\n2013-09-04 14:00:00,71.54936878\n2013-09-04 15:00:00,71.04470664\n2013-09-04 16:00:00,71.67149466\n2013-09-04 17:00:00,73.23762503\n2013-09-04 18:00:00,72.25962147\n2013-09-04 19:00:00,72.93900293\n2013-09-04 20:00:00,71.27122808\n2013-09-04 21:00:00,72.55002116\n2013-09-04 22:00:00,71.25225098\n2013-09-04 23:00:00,71.97747232\n2013-09-05 00:00:00,70.23719215\n2013-09-05 01:00:00,69.94606111\n2013-09-05 02:00:00,69.450805\n2013-09-05 03:00:00,69.93479403\n2013-09-05 04:00:00,69.0965309\n2013-09-05 05:00:00,68.97376954\n2013-09-05 06:00:00,70.04102824\n2013-09-05 07:00:00,69.54259642\n2013-09-05 08:00:00,69.85107284\n2013-09-05 09:00:00,69.61953454\n2013-09-05 10:00:00,69.99920276\n2013-09-05 11:00:00,70.41283415\n2013-09-05 12:00:00,72.11046261\n2013-09-05 13:00:00,72.80678003\n2013-09-05 14:00:00,72.51801434\n2013-09-05 15:00:00,72.69228723\n2013-09-05 16:00:00,72.16597707\n2013-09-05 17:00:00,73.99614903\n2013-09-05 18:00:00,72.82582702\n2013-09-05 19:00:00,74.24818259\n2013-09-05 20:00:00,74.69982523\n2013-09-05 21:00:00,75.16462698\n2013-09-05 22:00:00,74.48402123\n2013-09-05 23:00:00,72.97264305\n2013-09-06 00:00:00,72.49176792\n2013-09-06 01:00:00,73.77290611\n2013-09-06 02:00:00,73.53132409999998\n2013-09-06 03:00:00,72.73837497\n2013-09-06 04:00:00,71.88548201\n2013-09-06 05:00:00,71.52278755\n2013-09-06 06:00:00,71.76144938\n2013-09-06 07:00:00,72.45670094\n2013-09-06 08:00:00,71.89475031\n2013-09-06 09:00:00,70.52341229\n2013-09-06 10:00:00,71.2629687\n2013-09-06 11:00:00,72.8074479\n2013-09-06 12:00:00,73.80156306\n2013-09-06 13:00:00,73.52862948\n2013-09-06 14:00:00,72.90089441\n2013-09-06 15:00:00,73.17178042\n2013-09-06 16:00:00,73.42038306\n2013-09-06 17:00:00,73.47819457\n2013-09-06 18:00:00,73.96854139\n2013-09-06 19:00:00,74.39984284\n2013-09-06 20:00:00,74.13263209\n2013-09-06 21:00:00,73.66106497\n2013-09-06 22:00:00,74.42455034\n2013-09-06 23:00:00,73.88125989\n2013-09-07 00:00:00,72.88416225\n2013-09-07 01:00:00,72.53366149\n2013-09-07 02:00:00,72.28026919\n2013-09-07 03:00:00,73.5383584\n2013-09-07 04:00:00,72.97417623\n2013-09-07 05:00:00,72.80378043\n2013-09-07 06:00:00,71.11640175\n2013-09-07 07:00:00,71.8028968\n2013-09-07 08:00:00,71.74339169\n2013-09-07 09:00:00,71.89946776\n2013-09-07 10:00:00,71.37667995\n2013-09-07 11:00:00,70.97398196\n2013-09-07 12:00:00,71.3123657\n2013-09-07 13:00:00,71.86460893\n2013-09-07 14:00:00,71.16599578\n2013-09-07 15:00:00,71.37723976\n2013-09-07 16:00:00,71.36848881\n2013-09-07 17:00:00,70.78637361\n2013-09-07 18:00:00,71.11015784\n2013-09-07 19:00:00,71.85983966\n2013-09-07 20:00:00,70.95035881\n2013-09-07 21:00:00,72.65891354\n2013-09-07 22:00:00,72.33779272\n2013-09-07 23:00:00,70.61711298\n2013-09-08 00:00:00,71.01930095\n2013-09-08 01:00:00,71.63639202\n2013-09-08 02:00:00,71.32415634\n2013-09-08 03:00:00,70.5466809\n2013-09-08 04:00:00,70.97726886\n2013-09-08 05:00:00,69.7019157\n2013-09-08 06:00:00,70.36501785\n2013-09-08 07:00:00,69.28265658\n2013-09-08 08:00:00,68.52513155\n2013-09-08 09:00:00,68.91671905\n2013-09-08 10:00:00,68.90391361\n2013-09-08 11:00:00,69.25304945\n2013-09-08 12:00:00,69.20694068\n2013-09-08 13:00:00,68.4344154\n2013-09-08 14:00:00,69.13783219\n2013-09-08 15:00:00,67.78567323\n2013-09-08 16:00:00,68.87397161\n2013-09-08 17:00:00,68.04502775\n2013-09-08 18:00:00,67.81055256\n2013-09-08 19:00:00,68.99773267\n2013-09-08 20:00:00,68.99448259\n2013-09-08 21:00:00,67.84551049\n2013-09-08 22:00:00,68.86458993\n2013-09-08 23:00:00,67.97043986\n2013-09-09 00:00:00,66.92321439\n2013-09-09 01:00:00,68.59393936\n2013-09-09 02:00:00,66.62695158\n2013-09-09 03:00:00,67.75427493\n2013-09-09 04:00:00,66.66782263\n2013-09-09 05:00:00,67.46664892\n2013-09-09 06:00:00,67.60322003\n2013-09-09 07:00:00,67.66040956\n2013-09-09 08:00:00,66.65714613\n2013-09-09 09:00:00,68.75283581\n2013-09-09 10:00:00,69.19079475\n2013-09-09 11:00:00,70.45646119\n2013-09-09 12:00:00,70.93982761\n2013-09-09 13:00:00,69.63003292\n2013-09-09 14:00:00,71.41526516\n2013-09-09 15:00:00,71.55056424\n2013-09-09 16:00:00,71.90106522\n2013-09-09 17:00:00,71.69673606\n2013-09-09 18:00:00,71.04065657\n2013-09-09 19:00:00,71.73045012\n2013-09-09 20:00:00,72.76664681\n2013-09-16 12:00:00,72.69643979\n2013-09-16 13:00:00,72.80547371\n2013-09-16 14:00:00,72.91975931\n2013-09-16 15:00:00,72.26792976\n2013-09-16 16:00:00,72.85550390000002\n2013-09-16 17:00:00,72.96351653\n2013-09-16 18:00:00,72.77608689\n2013-09-16 19:00:00,74.71764725\n2013-09-16 20:00:00,75.18175232\n2013-09-16 21:00:00,74.68157666\n2013-09-16 22:00:00,75.03251294\n2013-09-16 23:00:00,74.89547613\n2013-09-17 00:00:00,72.88724781\n2013-09-17 01:00:00,74.04983548\n2013-09-17 02:00:00,73.82712414\n2013-09-17 03:00:00,72.79875638\n2013-09-17 04:00:00,71.99918837\n2013-09-17 05:00:00,72.17190677\n2013-09-17 06:00:00,71.25158302\n2013-09-17 07:00:00,71.28680525\n2013-09-17 08:00:00,71.38988043\n2013-09-17 09:00:00,72.24634579\n2013-09-17 10:00:00,71.59644925\n2013-09-17 11:00:00,72.90837738\n2013-09-17 12:00:00,73.24145352\n2013-09-17 13:00:00,73.06605307\n2013-09-17 14:00:00,72.64709801\n2013-09-17 15:00:00,73.15343178\n2013-09-17 16:00:00,72.96232879\n2013-09-17 17:00:00,72.52813486\n2013-09-17 18:00:00,73.81719904\n2013-09-17 19:00:00,74.02874448\n2013-09-17 20:00:00,73.79102864\n2013-09-17 21:00:00,73.25605739\n2013-09-17 22:00:00,73.05358423\n2013-09-17 23:00:00,73.77224906\n2013-09-18 00:00:00,72.8998969\n2013-09-18 01:00:00,72.24385814\n2013-09-18 02:00:00,71.33933531\n2013-09-18 03:00:00,72.29793377\n2013-09-18 04:00:00,70.34516442\n2013-09-18 05:00:00,71.13949198\n2013-09-18 06:00:00,70.16453648\n2013-09-18 07:00:00,71.11202658\n2013-09-18 08:00:00,70.4874724\n2013-09-18 09:00:00,70.71749668\n2013-09-18 10:00:00,69.89570423\n2013-09-18 11:00:00,71.68790348\n2013-09-18 12:00:00,71.37615947\n2013-09-18 13:00:00,71.74150703\n2013-09-18 14:00:00,73.20729802\n2013-09-18 15:00:00,72.89029189\n2013-09-18 16:00:00,72.30341978\n2013-09-18 17:00:00,72.6912123\n2013-09-18 18:00:00,72.34201351\n2013-09-18 19:00:00,74.49429294\n2013-09-18 20:00:00,73.25501422\n2013-09-18 21:00:00,74.13004256\n2013-09-18 22:00:00,73.68325892\n2013-09-18 23:00:00,72.11340117\n2013-09-19 00:00:00,72.31138231\n2013-09-19 01:00:00,71.29385993\n2013-09-19 02:00:00,71.93404046\n2013-09-19 03:00:00,71.67908598\n2013-09-19 04:00:00,71.48141177\n2013-09-19 05:00:00,70.85357689\n2013-09-19 06:00:00,69.45647733\n2013-09-19 07:00:00,70.12965246\n2013-09-19 08:00:00,69.02484940000001\n2013-09-19 09:00:00,69.00810205\n2013-09-19 10:00:00,67.59898139\n2013-09-19 11:00:00,67.55493576\n2013-09-19 12:00:00,67.40273072\n2013-09-19 13:00:00,67.39032649\n2013-09-19 14:00:00,68.09580201\n2013-09-19 15:00:00,67.39266673\n2013-09-19 16:00:00,68.36226835\n2013-09-19 17:00:00,68.40469903\n2013-09-19 18:00:00,67.83621597\n2013-09-19 19:00:00,69.19489788\n2013-09-19 20:00:00,68.49088179\n2013-09-19 21:00:00,68.33740959999999\n2013-09-19 22:00:00,68.76983220000001\n2013-09-19 23:00:00,68.4357686\n2013-09-20 00:00:00,68.74846768\n2013-09-20 01:00:00,68.95527404\n2013-09-20 02:00:00,68.2181708\n2013-09-20 03:00:00,69.12993292\n2013-09-20 04:00:00,68.4385586\n2013-09-20 05:00:00,69.06796416\n2013-09-20 06:00:00,68.30227174\n2013-09-20 07:00:00,68.64631402\n2013-09-20 08:00:00,68.88148079\n2013-09-20 09:00:00,68.90088305\n2013-09-20 10:00:00,69.65328565\n2013-09-20 11:00:00,68.86754593\n2013-09-20 12:00:00,68.42564703\n2013-09-20 13:00:00,69.09581068\n2013-09-20 14:00:00,69.44780599\n2013-09-20 15:00:00,68.42082002\n2013-09-20 16:00:00,68.83199074\n2013-09-20 17:00:00,69.55729317\n2013-09-20 18:00:00,68.83137434\n2013-09-20 19:00:00,70.02835926\n2013-09-20 20:00:00,71.07058978\n2013-09-20 21:00:00,71.28937940000002\n2013-09-20 22:00:00,70.10090101\n2013-09-20 23:00:00,71.68557803\n2013-09-21 00:00:00,69.88814945\n2013-09-21 01:00:00,70.42523491\n2013-09-21 02:00:00,69.44404702\n2013-09-21 03:00:00,70.1451179\n2013-09-21 04:00:00,69.48543471\n2013-09-21 05:00:00,69.63115874\n2013-09-21 06:00:00,70.00727727\n2013-09-21 07:00:00,69.16183248\n2013-09-21 08:00:00,68.43812628\n2013-09-21 09:00:00,68.65276698\n2013-09-21 10:00:00,68.15293671\n2013-09-21 11:00:00,69.64474901\n2013-09-21 12:00:00,69.0369617\n2013-09-21 13:00:00,68.59565354\n2013-09-21 14:00:00,69.91779386\n2013-09-21 15:00:00,68.59944984\n2013-09-21 16:00:00,68.66763575\n2013-09-21 17:00:00,68.79732688\n2013-09-21 18:00:00,69.52728032\n2013-09-21 19:00:00,69.14499021\n2013-09-21 20:00:00,69.36640493\n2013-09-21 21:00:00,69.32436477\n2013-09-21 22:00:00,70.04079998\n2013-09-21 23:00:00,70.32088532\n2013-09-22 00:00:00,70.68643574\n2013-09-22 01:00:00,69.41778612\n2013-09-22 02:00:00,69.52225613\n2013-09-22 03:00:00,69.97825566\n2013-09-22 04:00:00,69.84686459999999\n2013-09-22 05:00:00,69.94587165\n2013-09-22 06:00:00,68.70555692\n2013-09-22 07:00:00,68.59229114\n2013-09-22 08:00:00,69.9367965\n2013-09-22 09:00:00,69.07467717\n2013-09-22 10:00:00,68.77459707\n2013-09-22 11:00:00,68.96774462\n2013-09-22 12:00:00,69.51423059\n2013-09-22 13:00:00,69.60984678\n2013-09-22 14:00:00,68.45901476\n2013-09-22 15:00:00,68.66205887\n2013-09-22 16:00:00,69.07470807\n2013-09-22 17:00:00,68.98798244\n2013-09-22 18:00:00,70.4512398\n2013-09-22 19:00:00,69.1587948\n2013-09-22 20:00:00,70.02852311\n2013-09-22 21:00:00,70.30112967\n2013-09-22 22:00:00,71.02701721\n2013-09-22 23:00:00,70.44438138\n2013-09-23 00:00:00,71.21079549\n2013-09-23 01:00:00,70.08097943\n2013-09-23 02:00:00,70.01900785\n2013-09-23 03:00:00,71.31684052\n2013-09-23 04:00:00,69.49194049\n2013-09-23 05:00:00,70.71476009\n2013-09-23 06:00:00,70.30901685\n2013-09-23 07:00:00,69.92749715\n2013-09-23 08:00:00,69.28252505\n2013-09-23 09:00:00,70.51499697\n2013-09-23 10:00:00,69.17037572\n2013-09-23 11:00:00,69.67300935\n2013-09-23 12:00:00,70.98686733\n2013-09-23 13:00:00,72.71037561\n2013-09-23 14:00:00,72.84618043\n2013-09-23 15:00:00,71.49931817\n2013-09-23 16:00:00,71.82884072\n2013-09-23 17:00:00,71.96846019\n2013-09-23 18:00:00,72.38205511\n2013-09-23 19:00:00,73.10852105\n2013-09-23 20:00:00,72.50710177\n2013-09-23 21:00:00,71.36822279\n2013-09-23 22:00:00,71.73373415\n2013-09-23 23:00:00,70.39800507\n2013-09-24 00:00:00,71.02329854\n2013-09-24 01:00:00,70.42861121\n2013-09-24 02:00:00,71.29850242\n2013-09-24 03:00:00,70.41391036\n2013-09-24 04:00:00,69.83300525\n2013-09-24 05:00:00,70.04073494\n2013-09-24 06:00:00,69.2952676\n2013-09-24 07:00:00,69.80497056\n2013-09-24 08:00:00,70.47845996\n2013-09-24 09:00:00,68.87983862\n2013-09-24 10:00:00,70.82988977\n2013-09-24 11:00:00,71.7612628\n2013-09-24 12:00:00,71.23686153\n2013-09-24 13:00:00,72.17708088\n2013-09-24 14:00:00,73.52407232\n2013-09-24 15:00:00,73.43257426\n2013-09-24 16:00:00,71.96142812\n2013-09-24 17:00:00,72.06857704\n2013-09-24 18:00:00,72.80742737\n2013-09-24 19:00:00,74.18072649\n2013-09-24 20:00:00,72.6407991\n2013-09-24 21:00:00,72.49329287\n2013-09-24 22:00:00,73.37279171\n2013-09-24 23:00:00,72.84631814\n2013-09-25 00:00:00,73.74634464\n2013-09-25 01:00:00,73.08950487\n2013-09-25 02:00:00,73.12797789\n2013-09-25 03:00:00,72.85145065\n2013-09-25 04:00:00,71.78459362\n2013-09-25 05:00:00,71.96428662\n2013-09-25 06:00:00,70.98315976\n2013-09-25 07:00:00,72.09370496\n2013-09-25 08:00:00,70.47875896\n2013-09-25 09:00:00,71.15613714\n2013-09-25 10:00:00,71.79613981\n2013-09-25 11:00:00,70.53267958\n2013-09-25 12:00:00,70.92408688\n2013-09-25 13:00:00,71.07714472\n2013-09-25 14:00:00,72.12801602\n2013-09-25 15:00:00,73.76239725\n2013-09-25 16:00:00,73.50455944\n2013-09-25 17:00:00,74.06381073\n2013-09-25 18:00:00,75.84971566\n2013-09-25 19:00:00,74.917338\n2013-09-25 20:00:00,74.48204982\n2013-09-25 21:00:00,75.4754704\n2013-09-25 22:00:00,75.86633429\n2013-09-25 23:00:00,75.82692618\n2013-09-26 00:00:00,74.83518922\n2013-09-26 01:00:00,75.84170562\n2013-09-26 02:00:00,74.56152098\n2013-09-26 03:00:00,74.74597341\n2013-09-26 04:00:00,73.95196621\n2013-09-26 05:00:00,74.73785827\n2013-09-26 06:00:00,73.40944252\n2013-09-26 07:00:00,74.09665445\n2013-09-26 08:00:00,74.24341181\n2013-09-26 09:00:00,72.4241878\n2013-09-26 10:00:00,73.53577955\n2013-09-26 11:00:00,72.89263790000003\n2013-09-26 12:00:00,74.20179708\n2013-09-26 13:00:00,73.82891751\n2013-09-26 14:00:00,75.00384972\n2013-09-26 15:00:00,75.06654759999998\n2013-09-26 16:00:00,76.10375919\n2013-09-26 17:00:00,75.0111683\n2013-09-26 18:00:00,76.19220719\n2013-09-26 19:00:00,75.75430219\n2013-09-26 20:00:00,76.55201347\n2013-09-26 21:00:00,76.3420965\n2013-09-26 22:00:00,77.36149124\n2013-09-26 23:00:00,76.62602951\n2013-09-27 00:00:00,77.08086395\n2013-09-27 01:00:00,77.09614267\n2013-09-27 02:00:00,76.94079244\n2013-09-27 03:00:00,76.9216273\n2013-09-27 04:00:00,76.41395592\n2013-09-27 05:00:00,76.76728419\n2013-09-27 06:00:00,75.56516500000002\n2013-09-27 07:00:00,75.00316640000001\n2013-09-27 08:00:00,74.96022554\n2013-09-27 09:00:00,76.25958507\n2013-09-27 10:00:00,75.03195475\n2013-09-27 11:00:00,75.97741221\n2013-09-27 12:00:00,74.70847211\n2013-10-01 12:00:00,75.66428844\n2013-10-01 13:00:00,76.15183593\n2013-10-01 14:00:00,74.94798282\n2013-10-01 15:00:00,76.11749514\n2013-10-01 16:00:00,76.35342739\n2013-10-01 17:00:00,78.18999866\n2013-10-01 18:00:00,78.34183958\n2013-10-01 19:00:00,77.44052693\n2013-10-01 20:00:00,76.20708541\n2013-10-01 21:00:00,78.08998122\n2013-10-01 22:00:00,78.05491504\n2013-10-01 23:00:00,78.98542499\n2013-10-02 00:00:00,78.23875807\n2013-10-02 01:00:00,78.65871078\n2013-10-02 02:00:00,78.53164898\n2013-10-02 03:00:00,78.14277259999999\n2013-10-02 04:00:00,76.73686252\n2013-10-02 05:00:00,76.53612798\n2013-10-02 06:00:00,77.21543335\n2013-10-02 07:00:00,76.92976821\n2013-10-02 08:00:00,77.61334761\n2013-10-02 09:00:00,75.94869317\n2013-10-02 10:00:00,76.80988678\n2013-10-02 11:00:00,76.35617474\n2013-10-02 12:00:00,75.51487417\n2013-10-02 13:00:00,76.75914485\n2013-10-02 14:00:00,77.18231352\n2013-10-02 15:00:00,76.72424559\n2013-10-02 16:00:00,77.02058259\n2013-10-02 17:00:00,77.59412726\n2013-10-02 18:00:00,76.57737238\n2013-10-02 19:00:00,78.14370344\n2013-10-02 20:00:00,76.44863817\n2013-10-02 21:00:00,77.11808435\n2013-10-02 22:00:00,76.66444143\n2013-10-02 23:00:00,77.60066939\n2013-10-03 00:00:00,76.44893235\n2013-10-03 01:00:00,77.72893525\n2013-10-03 02:00:00,76.61186772\n2013-10-03 03:00:00,77.04302364\n2013-10-03 04:00:00,75.7689679\n2013-10-03 05:00:00,76.38938955\n2013-10-03 06:00:00,76.10096966\n2013-10-03 07:00:00,76.62421773\n2013-10-03 08:00:00,75.41072897\n2013-10-03 09:00:00,76.32543548\n2013-10-03 10:00:00,75.26776154\n2013-10-03 11:00:00,75.11220118\n2013-10-03 12:00:00,76.37061231\n2013-10-03 13:00:00,75.17527773\n2013-10-03 14:00:00,76.48020188\n2013-10-03 15:00:00,75.40371872\n2013-10-03 16:00:00,76.08145149\n2013-10-03 17:00:00,74.83978917\n2013-10-03 18:00:00,74.700469\n2013-10-03 19:00:00,75.46720555\n2013-10-03 20:00:00,74.52571486\n2013-10-03 21:00:00,75.50447062\n2013-10-03 22:00:00,76.68142877\n2013-10-03 23:00:00,77.07422539\n2013-10-04 00:00:00,76.62848003\n2013-10-04 01:00:00,75.65887074\n2013-10-04 02:00:00,76.78498097\n2013-10-04 03:00:00,76.97398833\n2013-10-04 04:00:00,76.81809786\n2013-10-04 05:00:00,76.18810762\n2013-10-04 06:00:00,75.14738658\n2013-10-04 07:00:00,74.60880026\n2013-10-04 08:00:00,74.71020506\n2013-10-04 09:00:00,74.33666665\n2013-10-04 10:00:00,75.89063588\n2013-10-04 11:00:00,74.92352501\n2013-10-04 12:00:00,76.25032166\n2013-10-04 13:00:00,76.76285447\n2013-10-04 14:00:00,76.43795622\n2013-10-04 15:00:00,75.84095165\n2013-10-04 16:00:00,76.30759992\n2013-10-04 17:00:00,76.37889288\n2013-10-04 18:00:00,74.50037961\n2013-10-04 19:00:00,75.46855478\n2013-10-04 20:00:00,76.23977529\n2013-10-04 21:00:00,75.60803745\n2013-10-04 22:00:00,75.53609477\n2013-10-04 23:00:00,76.15092858\n2013-10-05 00:00:00,77.04357167\n2013-10-05 01:00:00,76.83958927\n2013-10-05 02:00:00,75.35704476\n2013-10-05 03:00:00,75.26244693\n2013-10-05 04:00:00,75.67256245\n2013-10-05 05:00:00,74.97423465\n2013-10-05 06:00:00,74.68662683\n2013-10-05 07:00:00,74.67127682\n2013-10-05 08:00:00,75.30039984\n2013-10-05 09:00:00,75.41442640000002\n2013-10-05 10:00:00,75.77834261\n2013-10-05 11:00:00,76.30250549\n2013-10-05 12:00:00,76.08729308\n2013-10-05 13:00:00,76.17387791\n2013-10-05 14:00:00,74.59539903\n2013-10-05 15:00:00,74.8586202\n2013-10-05 16:00:00,76.15473545\n2013-10-05 17:00:00,76.73544665\n2013-10-05 18:00:00,76.81207028\n2013-10-05 19:00:00,76.76942959\n2013-10-05 20:00:00,76.0742703\n2013-10-05 21:00:00,77.67624752\n2013-10-05 22:00:00,77.20513301\n2013-10-05 23:00:00,78.30547509\n2013-10-06 00:00:00,76.57887568\n2013-10-06 01:00:00,76.88289528\n2013-10-06 02:00:00,77.48251447\n2013-10-06 03:00:00,76.38323965\n2013-10-06 04:00:00,76.26112886\n2013-10-06 05:00:00,77.83782089\n2013-10-06 06:00:00,77.81793736\n2013-10-06 07:00:00,76.88455309\n2013-10-06 08:00:00,77.29695705\n2013-10-06 09:00:00,75.7818161\n2013-10-06 10:00:00,77.23681223\n2013-10-06 11:00:00,77.65970467\n2013-10-06 12:00:00,76.47686703\n2013-10-06 13:00:00,76.45250409\n2013-10-06 14:00:00,76.44446488\n2013-10-06 15:00:00,75.338712\n2013-10-06 16:00:00,75.43988813\n2013-10-06 17:00:00,76.11375195\n2013-10-06 18:00:00,75.44361839\n2013-10-06 19:00:00,74.85664993\n2013-10-06 20:00:00,75.89981187\n2013-10-06 21:00:00,75.52638288\n2013-10-06 22:00:00,76.70454118\n2013-10-06 23:00:00,76.91841747\n2013-10-07 00:00:00,76.77395886\n2013-10-07 01:00:00,76.24255849\n2013-10-07 02:00:00,75.93339717\n2013-10-07 03:00:00,75.02163716\n2013-10-07 04:00:00,75.85554729\n2013-10-07 05:00:00,75.36964545\n2013-10-07 06:00:00,74.66467269\n2013-10-07 07:00:00,73.75869737\n2013-10-07 08:00:00,74.69866385\n2013-10-07 09:00:00,74.63334088\n2013-10-07 10:00:00,74.24988343\n2013-10-07 11:00:00,75.38338771\n2013-10-07 12:00:00,74.12097863\n2013-10-07 13:00:00,75.46608714\n2013-10-07 14:00:00,74.99673301\n2013-10-07 15:00:00,75.84411143\n2013-10-07 16:00:00,76.15467811\n2013-10-07 17:00:00,75.38180222\n2013-10-07 18:00:00,74.98612428\n2013-10-07 19:00:00,74.83290714\n2013-10-07 20:00:00,75.33838706\n2013-10-07 21:00:00,75.99301951\n2013-10-07 22:00:00,75.44383011\n2013-10-07 23:00:00,74.71510278\n2013-10-08 00:00:00,75.16393256\n2013-10-08 01:00:00,73.98772604\n2013-10-08 02:00:00,72.99713921\n2013-10-08 03:00:00,72.73963377\n2013-10-08 04:00:00,72.56210332\n2013-10-08 05:00:00,71.95415339\n2013-10-08 06:00:00,71.53772099\n2013-10-08 07:00:00,73.3846364\n2013-10-08 08:00:00,73.02911198\n2013-10-08 09:00:00,73.32056873\n2013-10-08 10:00:00,72.65757445\n2013-10-08 11:00:00,72.91058794\n2013-10-08 12:00:00,72.00144343\n2013-10-08 13:00:00,72.17948397\n2013-10-08 14:00:00,73.13684959999998\n2013-10-08 15:00:00,72.74243972\n2013-10-08 16:00:00,74.04314141\n2013-10-08 17:00:00,74.9362334\n2013-10-08 18:00:00,73.60819261\n2013-10-08 19:00:00,74.85510654\n2013-10-08 20:00:00,75.18349971\n2013-10-08 21:00:00,74.64847435\n2013-10-08 22:00:00,74.30749947\n2013-10-08 23:00:00,74.22020409\n2013-10-09 00:00:00,73.93927621\n2013-10-09 01:00:00,73.62134422\n2013-10-09 02:00:00,73.81914203\n2013-10-09 03:00:00,72.9684546\n2013-10-09 04:00:00,73.01285776\n2013-10-09 05:00:00,72.80505299\n2013-10-09 06:00:00,72.66330867\n2013-10-09 07:00:00,72.77940061\n2013-10-09 08:00:00,72.45267623\n2013-10-09 09:00:00,72.41013365\n2013-10-09 10:00:00,72.97620201\n2013-10-09 11:00:00,72.70599693\n2013-10-09 12:00:00,72.67329612\n2013-10-09 13:00:00,73.25471351\n2013-10-09 14:00:00,74.21758249\n2013-10-09 15:00:00,73.41679227\n2013-10-09 16:00:00,73.26801845\n2013-10-09 17:00:00,74.21654701\n2013-10-09 18:00:00,74.49963991\n2013-10-09 19:00:00,74.93839694\n2013-10-09 20:00:00,74.48590659999998\n2013-10-09 21:00:00,74.5249187\n2013-10-09 22:00:00,74.94497354\n2013-10-09 23:00:00,75.11312816\n2013-10-10 00:00:00,73.45479839\n2013-10-10 01:00:00,73.62753539\n2013-10-10 02:00:00,74.65356252\n2013-10-10 03:00:00,73.65569667\n2013-10-10 04:00:00,74.30833238\n2013-10-10 05:00:00,72.36883324\n2013-10-10 06:00:00,72.63029089\n2013-10-10 07:00:00,72.92216679\n2013-10-10 08:00:00,73.50841047\n2013-10-10 09:00:00,73.8940062\n2013-10-10 10:00:00,72.75520825\n2013-10-10 11:00:00,72.77342691\n2013-10-10 12:00:00,74.0173653\n2013-10-10 13:00:00,74.07999403\n2013-10-10 14:00:00,74.98348749\n2013-10-10 15:00:00,74.93166228\n2013-10-10 16:00:00,75.00032977\n2013-10-10 17:00:00,74.79545142\n2013-10-10 18:00:00,74.22649476\n2013-10-10 19:00:00,74.89181277\n2013-10-10 20:00:00,76.03381278\n2013-10-10 21:00:00,75.75160616\n2013-10-10 22:00:00,75.35499490000002\n2013-10-10 23:00:00,75.3520882\n2013-10-11 00:00:00,75.59122877\n2013-10-11 01:00:00,74.60615095\n2013-10-11 02:00:00,73.66657269\n2013-10-11 03:00:00,75.29576071\n2013-10-11 04:00:00,73.07467638\n2013-10-11 05:00:00,73.54096289\n2013-10-11 06:00:00,73.56748044\n2013-10-11 07:00:00,72.23943668\n2013-10-11 08:00:00,72.98971633\n2013-10-11 09:00:00,71.8624757\n2013-10-11 10:00:00,72.15907086\n2013-10-11 11:00:00,73.28710779\n2013-10-11 12:00:00,73.23267068\n2013-10-11 13:00:00,72.91831075\n2013-10-11 14:00:00,74.13951981\n2013-10-11 15:00:00,73.91840559\n2013-10-11 16:00:00,74.05658495\n2013-10-11 17:00:00,74.4819446\n2013-10-11 18:00:00,75.13591435\n2013-10-11 19:00:00,75.68312614\n2013-10-11 20:00:00,74.4794284\n2013-10-14 19:00:00,72.98303434\n2013-10-14 20:00:00,73.97904439\n2013-10-14 21:00:00,72.80960896\n2013-10-14 22:00:00,74.45908003\n2013-10-14 23:00:00,73.22449615\n2013-10-15 00:00:00,74.08849517\n2013-10-15 01:00:00,72.09427723\n2013-10-15 02:00:00,73.30412261\n2013-10-15 03:00:00,72.49226170000001\n2013-10-15 04:00:00,71.55592659\n2013-10-15 05:00:00,71.92880201\n2013-10-15 06:00:00,72.20455302\n2013-10-15 07:00:00,71.5729309\n2013-10-15 08:00:00,71.38455809\n2013-10-15 09:00:00,71.57838797\n2013-10-15 10:00:00,72.33092601\n2013-10-15 11:00:00,72.5020361\n2013-10-15 12:00:00,72.16890223\n2013-10-15 13:00:00,71.80124576\n2013-10-15 14:00:00,71.98653741\n2013-10-15 15:00:00,73.57829998\n2013-10-15 16:00:00,73.76993449\n2013-10-15 17:00:00,73.90520817\n2013-10-15 18:00:00,73.88052554\n2013-10-15 19:00:00,72.72460722\n2013-10-15 20:00:00,73.87825084\n2013-10-15 21:00:00,73.1538236\n2013-10-15 22:00:00,74.25507299\n2013-10-15 23:00:00,72.78303586\n2013-10-16 00:00:00,72.70043711\n2013-10-16 01:00:00,72.55484862\n2013-10-16 02:00:00,72.52805707\n2013-10-16 03:00:00,73.14618943\n2013-10-16 04:00:00,71.23182363\n2013-10-16 05:00:00,72.41740232\n2013-10-16 06:00:00,71.66301343\n2013-10-16 07:00:00,71.06682037\n2013-10-16 08:00:00,72.17174017\n2013-10-16 09:00:00,71.98736373\n2013-10-16 10:00:00,71.53260775\n2013-10-16 11:00:00,72.36545699\n2013-10-16 12:00:00,72.78437383\n2013-10-16 13:00:00,71.97296390000002\n2013-10-16 14:00:00,72.4644608\n2013-10-16 15:00:00,72.62455626\n2013-10-16 16:00:00,73.55532127\n2013-10-16 17:00:00,72.89143683\n2013-10-16 18:00:00,74.21730356\n2013-10-16 19:00:00,75.25147517\n2013-10-16 20:00:00,75.28003046\n2013-10-16 21:00:00,73.45611639\n2013-10-16 22:00:00,67.59220788\n2013-10-16 23:00:00,74.3959065\n2013-10-17 00:00:00,72.76152535\n2013-10-17 01:00:00,72.84667905\n2013-10-17 02:00:00,74.06782481\n2013-10-17 03:00:00,73.40328569\n2013-10-17 04:00:00,72.4928657\n2013-10-17 05:00:00,72.36963864\n2013-10-17 06:00:00,70.63012656\n2013-10-17 07:00:00,70.32611117\n2013-10-17 08:00:00,71.46025104\n2013-10-17 09:00:00,71.14590855\n2013-10-17 10:00:00,71.46817075\n2013-10-17 11:00:00,71.41876211\n2013-10-17 12:00:00,72.99363734\n2013-10-17 13:00:00,72.24666709\n2013-10-17 14:00:00,73.45167119\n2013-10-17 15:00:00,74.39956072\n2013-10-17 16:00:00,72.81416628\n2013-10-17 17:00:00,73.03240204\n2013-10-17 18:00:00,75.04333658\n2013-10-17 19:00:00,73.92938757\n2013-10-17 20:00:00,73.81507515\n2013-10-17 21:00:00,74.08455767\n2013-10-17 22:00:00,73.38180602\n2013-10-17 23:00:00,73.23701247\n2013-10-18 00:00:00,72.99037413\n2013-10-18 01:00:00,72.99012950000002\n2013-10-18 02:00:00,72.66562134\n2013-10-18 03:00:00,72.51950292\n2013-10-18 04:00:00,72.45390193\n2013-10-18 05:00:00,72.03998157\n2013-10-18 06:00:00,72.47195408\n2013-10-18 07:00:00,72.34968064\n2013-10-18 08:00:00,71.45220535\n2013-10-18 09:00:00,71.55743829999999\n2013-10-18 10:00:00,72.63790855\n2013-10-18 11:00:00,71.85849263\n2013-10-18 12:00:00,72.93395917\n2013-10-18 13:00:00,72.38591831\n2013-10-18 14:00:00,73.80702055\n2013-10-18 15:00:00,73.52710171\n2013-10-18 16:00:00,74.83471181\n2013-10-18 17:00:00,74.21326248\n2013-10-18 18:00:00,73.25223693\n2013-10-18 19:00:00,73.93628199999998\n2013-10-18 20:00:00,73.04669143\n2013-10-18 21:00:00,73.08417829999998\n2013-10-18 22:00:00,74.19287354\n2013-10-18 23:00:00,73.41808921\n2013-10-19 00:00:00,74.12963911\n2013-10-19 01:00:00,73.46278565\n2013-10-19 02:00:00,73.62789649\n2013-10-19 03:00:00,71.92833946\n2013-10-19 04:00:00,72.26119661\n2013-10-19 05:00:00,71.47946165\n2013-10-19 06:00:00,72.63321496\n2013-10-19 07:00:00,72.24354039\n2013-10-19 08:00:00,71.57056509\n2013-10-19 09:00:00,72.2797028\n2013-10-19 10:00:00,73.01911793\n2013-10-19 11:00:00,71.61445258\n2013-10-19 12:00:00,71.26409105\n2013-10-19 13:00:00,71.75373049\n2013-10-19 14:00:00,72.57075359\n2013-10-19 15:00:00,71.7959401\n2013-10-19 16:00:00,71.53861613\n2013-10-19 17:00:00,70.90022339\n2013-10-19 18:00:00,71.73254786\n2013-10-19 19:00:00,71.71309029999998\n2013-10-19 20:00:00,72.76010528\n2013-10-19 21:00:00,72.84417558\n2013-10-19 22:00:00,71.99223058\n2013-10-19 23:00:00,71.70725001\n2013-10-20 00:00:00,71.71438532\n2013-10-20 01:00:00,72.55191183\n2013-10-20 02:00:00,71.03928043\n2013-10-20 03:00:00,71.46046414\n2013-10-20 04:00:00,71.99130446\n2013-10-20 05:00:00,71.45046564\n2013-10-20 06:00:00,71.51504432\n2013-10-20 07:00:00,70.99280008\n2013-10-20 08:00:00,71.34776909\n2013-10-20 09:00:00,70.72845843\n2013-10-20 10:00:00,70.27507626\n2013-10-20 11:00:00,70.27111929\n2013-10-20 12:00:00,70.85408914\n2013-10-20 13:00:00,69.94855497\n2013-10-20 14:00:00,69.53492069\n2013-10-20 15:00:00,70.92058525\n2013-10-20 16:00:00,70.99850582\n2013-10-20 17:00:00,71.05686947\n2013-10-20 18:00:00,72.14843798\n2013-10-20 19:00:00,71.45617637\n2013-10-20 20:00:00,73.27200083\n2013-10-20 21:00:00,71.80063059\n2013-10-20 22:00:00,73.01762667\n2013-10-20 23:00:00,72.12768954\n2013-10-21 00:00:00,73.33199587\n2013-10-21 01:00:00,73.21702132\n2013-10-21 02:00:00,72.41071376\n2013-10-21 03:00:00,72.12548765\n2013-10-21 04:00:00,73.03066312\n2013-10-21 05:00:00,71.54792939\n2013-10-21 06:00:00,72.74034991\n2013-10-21 07:00:00,71.35108732\n2013-10-21 08:00:00,71.40181091\n2013-10-21 09:00:00,72.12977881\n2013-10-21 10:00:00,72.31327617\n2013-10-21 11:00:00,71.50759292\n2013-10-21 12:00:00,73.42790189\n2013-10-21 13:00:00,74.33787739\n2013-10-21 14:00:00,73.42943331\n2013-10-21 15:00:00,72.64800749999998\n2013-10-21 16:00:00,74.48313565\n2013-10-21 17:00:00,73.37484563\n2013-10-21 18:00:00,74.54468294\n2013-10-21 19:00:00,74.91468608\n2013-10-21 20:00:00,74.48188759\n2013-10-21 21:00:00,73.21984661\n2013-10-21 22:00:00,73.46717767\n2013-10-21 23:00:00,73.43538257\n2013-10-22 00:00:00,74.11014418\n2013-10-22 01:00:00,74.0856674\n2013-10-22 02:00:00,74.43241463\n2013-10-22 03:00:00,74.304057\n2013-10-22 04:00:00,73.43146696\n2013-10-22 05:00:00,72.49383421\n2013-10-22 06:00:00,73.03216682\n2013-10-22 07:00:00,71.83335039\n2013-10-22 08:00:00,71.01856015\n2013-10-22 09:00:00,72.21563105\n2013-10-22 10:00:00,72.48771792\n2013-10-22 11:00:00,72.7382649\n2013-10-22 12:00:00,73.60978997\n2013-10-22 13:00:00,73.74620023\n2013-10-22 14:00:00,73.23713965\n2013-10-22 15:00:00,73.4530571\n2013-10-22 16:00:00,73.92328043\n2013-10-22 17:00:00,75.18250744\n2013-10-22 18:00:00,74.02490252\n2013-10-22 19:00:00,75.3285915\n2013-10-22 20:00:00,74.66865644\n2013-10-22 21:00:00,74.14984749\n2013-10-22 22:00:00,74.89985381\n2013-10-22 23:00:00,75.30346611\n2013-10-23 00:00:00,73.91031296\n2013-10-23 01:00:00,73.93275037\n2013-10-23 02:00:00,73.16148058\n2013-10-23 03:00:00,73.52562326\n2013-10-23 04:00:00,72.47484370000002\n2013-10-23 05:00:00,72.49504420000002\n2013-10-23 06:00:00,71.61991048\n2013-10-23 07:00:00,73.22943968\n2013-10-23 08:00:00,71.58909683\n2013-10-23 09:00:00,71.81584418\n2013-10-23 10:00:00,71.34809224\n2013-10-23 11:00:00,72.96869218\n2013-10-23 12:00:00,72.55053234\n2013-10-23 13:00:00,72.57797464\n2013-10-23 14:00:00,74.69536550000002\n2013-10-23 15:00:00,74.1296061\n2013-10-23 16:00:00,73.94533205\n2013-10-23 17:00:00,74.07901132\n2013-10-23 18:00:00,75.05479911\n2013-10-23 19:00:00,74.85789892\n2013-10-23 20:00:00,76.0974356\n2013-10-23 21:00:00,75.60625767\n2013-10-23 22:00:00,76.460003\n2013-10-23 23:00:00,75.95853846\n2013-10-24 00:00:00,75.66920488\n2013-10-24 01:00:00,76.19819465\n2013-10-24 02:00:00,74.83838032\n2013-10-24 03:00:00,75.34256101\n2013-10-24 04:00:00,75.63691814\n2013-10-24 05:00:00,76.00126612\n2013-10-24 06:00:00,74.28973725\n2013-10-24 07:00:00,74.80605955\n2013-10-24 08:00:00,75.30172567\n2013-10-24 09:00:00,74.34735395\n2013-10-24 10:00:00,75.12651355\n2013-10-24 11:00:00,73.75813908\n2013-10-24 12:00:00,75.04085467\n2013-10-24 13:00:00,74.7295084\n2013-10-24 14:00:00,75.23496324\n2013-10-24 15:00:00,74.09558127\n2013-10-24 16:00:00,75.40924951\n2013-10-24 17:00:00,75.05840643\n2013-10-24 18:00:00,75.20790637\n2013-10-24 19:00:00,73.69135931\n2013-10-24 20:00:00,73.54196014\n2013-10-24 21:00:00,75.19082042\n2013-10-24 22:00:00,74.60746814\n2013-10-24 23:00:00,74.53993625\n2013-10-25 00:00:00,73.4168865\n2013-10-25 01:00:00,73.95852383\n2013-10-25 02:00:00,73.75006416\n2013-10-25 03:00:00,74.14389026\n2013-10-25 04:00:00,72.51791753\n2013-10-25 05:00:00,73.6608867\n2013-10-25 06:00:00,71.99874820000002\n2013-10-25 07:00:00,72.38400327\n2013-10-25 08:00:00,72.51858237\n2013-10-25 09:00:00,71.55343537\n2013-10-25 10:00:00,72.55778642\n2013-10-25 11:00:00,71.96670972\n2013-10-25 12:00:00,72.36781957\n2013-10-25 13:00:00,72.69666807\n2013-10-25 14:00:00,72.75559541\n2013-10-25 15:00:00,73.59062056\n2013-10-25 16:00:00,73.17199341\n2013-10-25 17:00:00,74.06972966\n2013-10-25 18:00:00,74.49830916\n2013-10-25 19:00:00,73.95696452\n2013-10-25 20:00:00,73.63058672\n2013-10-25 21:00:00,73.49661513\n2013-10-25 22:00:00,75.0238628\n2013-10-25 23:00:00,73.41067783\n2013-10-26 00:00:00,74.43789627\n2013-10-26 01:00:00,73.69728217\n2013-10-26 02:00:00,72.79073013\n2013-10-26 03:00:00,74.02303394\n2013-10-26 04:00:00,73.99547327\n2013-10-26 05:00:00,72.63698998\n2013-10-26 06:00:00,72.65022647\n2013-10-26 07:00:00,71.45778273\n2013-10-26 08:00:00,73.30880143\n2013-10-26 09:00:00,71.88486246\n2013-10-26 10:00:00,72.3666265\n2013-10-26 11:00:00,71.51972021\n2013-10-26 12:00:00,71.73511359\n2013-10-26 13:00:00,72.78641155\n2013-10-26 14:00:00,71.38856419\n2013-10-26 15:00:00,72.18526942\n2013-10-26 16:00:00,73.51448987\n2013-10-26 17:00:00,73.57199426\n2013-10-26 18:00:00,72.91075318\n2013-10-26 19:00:00,73.81514959\n2013-10-26 20:00:00,72.68504592\n2013-10-26 21:00:00,74.08911438\n2013-10-26 22:00:00,72.9589277\n2013-10-26 23:00:00,73.14610095\n2013-10-27 00:00:00,73.78917147\n2013-10-27 01:00:00,72.79764335\n2013-10-27 02:00:00,73.85796513\n2013-10-27 03:00:00,73.14750042\n2013-10-27 04:00:00,73.68655845\n2013-10-27 05:00:00,71.99772202\n2013-10-27 06:00:00,71.98066434\n2013-10-27 07:00:00,72.34138543\n2013-10-27 08:00:00,72.73493389\n2013-10-27 09:00:00,71.65669486\n2013-10-27 10:00:00,71.49563964\n2013-10-27 11:00:00,72.5480017\n2013-10-27 12:00:00,71.57221259\n2013-10-27 13:00:00,72.7741422\n2013-10-27 14:00:00,72.50897204\n2013-10-27 15:00:00,72.37165679\n2013-10-27 16:00:00,71.76151786\n2013-10-27 17:00:00,71.14297184\n2013-10-27 18:00:00,71.17422664\n2013-10-27 19:00:00,72.7253094\n2013-10-27 20:00:00,71.85317981\n2013-10-27 21:00:00,72.85663059\n2013-10-27 22:00:00,71.76247182\n2013-10-27 23:00:00,71.69635699999998\n2013-10-28 00:00:00,70.92483713\n2013-10-28 01:00:00,71.43725419\n2013-10-28 02:00:00,72.13600699999998\n2013-10-28 03:00:00,70.64687742\n2013-10-28 04:00:00,70.22032111\n2013-10-28 05:00:00,69.75235982\n2013-10-28 06:00:00,71.33829611\n2013-10-28 07:00:00,69.61769321\n2013-10-28 08:00:00,70.75591875\n2013-10-28 09:00:00,71.47646234\n2013-10-28 10:00:00,71.59381864\n2013-10-28 11:00:00,70.66816135\n2013-10-28 12:00:00,73.12430398\n2013-10-28 13:00:00,72.97024298\n2013-10-28 14:00:00,73.74160859999998\n2013-10-28 15:00:00,73.95406465\n2013-10-28 16:00:00,73.45808119\n2013-10-28 17:00:00,73.14484568\n2013-10-28 18:00:00,74.48764885\n2013-10-28 19:00:00,73.40434954\n2013-10-28 20:00:00,73.32924842\n2013-10-28 21:00:00,74.46460516\n2013-10-28 22:00:00,74.68612326\n2013-10-28 23:00:00,73.64400862\n2013-10-29 00:00:00,73.05155138\n2013-10-29 01:00:00,73.20917824\n2013-10-29 02:00:00,72.9686264\n2013-10-29 03:00:00,73.44971023\n2013-10-29 04:00:00,73.55495921\n2013-10-29 05:00:00,71.69592455\n2013-10-29 06:00:00,73.53646843\n2013-10-29 07:00:00,72.02971426\n2013-10-29 08:00:00,73.42081575\n2013-10-29 09:00:00,72.58490985\n2013-10-29 10:00:00,73.0300541\n2013-10-29 11:00:00,73.33546169\n2013-10-29 12:00:00,73.69525708\n2013-10-29 13:00:00,74.44248772\n2013-10-29 14:00:00,73.36288859\n2013-10-29 15:00:00,74.23441848\n2013-10-29 16:00:00,73.53614618\n2013-10-29 17:00:00,73.55358243\n2013-10-29 18:00:00,73.31606619\n2013-10-29 19:00:00,74.07121348\n2013-10-29 20:00:00,73.84322808\n2013-10-29 21:00:00,74.31880636\n2013-10-29 22:00:00,75.37365059999998\n2013-10-29 23:00:00,74.6158649\n2013-10-30 00:00:00,74.22361987\n2013-10-30 01:00:00,74.90183652\n2013-10-30 02:00:00,74.60288205\n2013-10-30 03:00:00,73.60468314\n2013-10-30 04:00:00,74.41600686\n2013-10-30 05:00:00,74.16088548\n2013-10-30 06:00:00,72.84884222\n2013-10-30 07:00:00,72.92107082\n2013-10-30 08:00:00,73.01604281\n2013-10-30 09:00:00,74.13143498\n2013-10-30 10:00:00,72.57848043\n2013-10-30 11:00:00,72.87188536\n2013-10-30 12:00:00,73.61682058\n2013-10-30 13:00:00,73.37016715\n2013-10-30 14:00:00,74.04450691\n2013-10-30 15:00:00,74.12361236\n2013-10-30 16:00:00,74.66328477\n2013-10-30 17:00:00,75.70737338\n2013-10-30 18:00:00,75.3545802\n2013-10-30 19:00:00,75.25614118\n2013-10-30 20:00:00,74.87355721\n2013-10-30 21:00:00,76.29745203\n2013-10-30 22:00:00,75.32289320000002\n2013-10-30 23:00:00,75.85634859999998\n2013-10-31 00:00:00,75.14595644\n2013-10-31 01:00:00,75.88962012\n2013-10-31 02:00:00,76.4180307\n2013-10-31 03:00:00,76.56197890000001\n2013-10-31 04:00:00,76.10597378\n2013-10-31 05:00:00,75.25141922\n2013-10-31 06:00:00,75.72435817\n2013-10-31 07:00:00,74.49878947\n2013-10-31 08:00:00,75.84183322\n2013-10-31 09:00:00,75.2866983\n2013-10-31 10:00:00,74.87398102\n2013-10-31 11:00:00,74.94194615\n2013-10-31 12:00:00,75.98035652\n2013-10-31 13:00:00,74.95842691\n2013-10-31 14:00:00,75.24512346\n2013-10-31 15:00:00,75.35692048\n2013-10-31 16:00:00,76.88500697\n2013-10-31 17:00:00,76.12766594\n2013-10-31 18:00:00,75.86319296\n2013-10-31 19:00:00,76.41346624\n2013-10-31 20:00:00,75.5347714\n2013-10-31 21:00:00,75.84580103\n2013-10-31 22:00:00,76.34558396\n2013-10-31 23:00:00,77.39292354\n2013-11-01 00:00:00,76.30796353\n2013-11-01 01:00:00,77.25259793\n2013-11-01 02:00:00,76.43178992\n2013-11-01 03:00:00,77.69772574\n2013-11-01 04:00:00,76.53784364\n2013-11-01 05:00:00,76.38649065\n2013-11-01 06:00:00,77.20675318\n2013-11-01 07:00:00,77.18738382\n2013-11-01 08:00:00,75.67736243\n2013-11-01 09:00:00,74.81300493\n2013-11-01 10:00:00,75.83696911\n2013-11-01 11:00:00,75.02326067\n2013-11-01 12:00:00,75.05073943\n2013-11-01 13:00:00,75.28745236\n2013-11-01 14:00:00,75.20319345\n2013-11-01 15:00:00,75.12528566\n2013-11-01 16:00:00,75.19924971\n2013-11-01 17:00:00,75.73098218\n2013-11-01 18:00:00,75.93704108\n2013-11-01 19:00:00,74.89355303\n2013-11-01 20:00:00,75.07774926\n2013-11-01 21:00:00,75.25618705\n2013-11-01 22:00:00,75.71797654\n2013-11-01 23:00:00,75.63395379\n2013-11-02 00:00:00,75.48381386\n2013-11-02 01:00:00,75.66762937\n2013-11-02 02:00:00,76.51474357\n2013-11-02 03:00:00,75.08953119\n2013-11-02 04:00:00,75.81216694\n2013-11-02 05:00:00,75.60610346\n2013-11-02 06:00:00,74.96367140000002\n2013-11-02 07:00:00,74.98121493\n2013-11-02 08:00:00,74.45643905\n2013-11-02 09:00:00,75.51516542\n2013-11-02 10:00:00,74.73560812\n2013-11-02 11:00:00,74.69915087\n2013-11-02 12:00:00,74.54298971\n2013-11-02 13:00:00,73.35219351\n2013-11-02 14:00:00,74.12383795\n2013-11-02 15:00:00,74.22554631\n2013-11-02 16:00:00,73.99079534\n2013-11-02 17:00:00,74.79507379\n2013-11-02 18:00:00,76.11205116\n2013-11-02 19:00:00,75.22593768\n2013-11-02 20:00:00,75.27953666\n2013-11-02 21:00:00,77.15937503\n2013-11-02 22:00:00,76.19111223\n2013-11-02 23:00:00,76.31079818\n2013-11-03 00:00:00,76.38206634\n2013-11-03 01:00:00,75.57825005\n2013-11-03 02:00:00,76.13455079999999\n2013-11-03 03:00:00,75.23603382\n2013-11-03 04:00:00,76.23782807\n2013-11-03 05:00:00,75.336605\n2013-11-03 06:00:00,74.36531352\n2013-11-03 07:00:00,73.71769524\n2013-11-03 08:00:00,74.074138\n2013-11-03 09:00:00,74.84189513\n2013-11-03 10:00:00,73.95914727\n2013-11-03 11:00:00,74.04130502\n2013-11-03 12:00:00,74.56437617\n2013-11-03 13:00:00,73.29808803\n2013-11-03 14:00:00,73.53188681\n2013-11-03 15:00:00,73.87759563\n2013-11-03 16:00:00,74.87971926\n2013-11-03 17:00:00,74.1892936\n2013-11-03 18:00:00,75.41399344\n2013-11-03 19:00:00,75.86744504\n2013-11-03 20:00:00,75.6150603\n2013-11-03 21:00:00,76.97153329\n2013-11-03 22:00:00,77.0894334\n2013-11-03 23:00:00,76.17299187\n2013-11-04 00:00:00,75.60827582\n2013-11-04 01:00:00,76.66746590000002\n2013-11-04 02:00:00,76.59056219\n2013-11-04 03:00:00,75.05998404\n2013-11-04 04:00:00,75.88379996\n2013-11-04 05:00:00,75.47865146\n2013-11-04 06:00:00,74.4588194\n2013-11-04 07:00:00,73.60738959\n2013-11-04 08:00:00,74.41420743\n2013-11-04 09:00:00,74.765766\n2013-11-04 10:00:00,74.16291232\n2013-11-04 11:00:00,74.19468656\n2013-11-04 12:00:00,74.43225537\n2013-11-04 13:00:00,74.24359177\n2013-11-04 14:00:00,74.55720475\n2013-11-04 15:00:00,75.76889616\n2013-11-04 16:00:00,75.5197806\n2013-11-04 17:00:00,74.72805694\n2013-11-04 18:00:00,75.06364679\n2013-11-04 19:00:00,75.92542961\n2013-11-04 20:00:00,75.03438753\n2013-11-04 21:00:00,75.53025670000002\n2013-11-04 22:00:00,76.20838186\n2013-11-04 23:00:00,75.88011467\n2013-11-05 00:00:00,75.25305005\n2013-11-05 01:00:00,76.16092035\n2013-11-05 02:00:00,74.87732367\n2013-11-05 03:00:00,75.70725229\n2013-11-05 04:00:00,74.62446294\n2013-11-05 05:00:00,73.93894725\n2013-11-05 06:00:00,75.39833336\n2013-11-05 07:00:00,73.67042395\n2013-11-05 08:00:00,74.78394113\n2013-11-05 09:00:00,75.36637593\n2013-11-05 10:00:00,75.62678541\n2013-11-05 11:00:00,75.54245470000002\n2013-11-05 12:00:00,75.56486359\n2013-11-05 13:00:00,75.40045594\n2013-11-05 14:00:00,75.72241656\n2013-11-05 15:00:00,75.38360735\n2013-11-05 16:00:00,74.96366192\n2013-11-05 17:00:00,75.15506847\n2013-11-05 18:00:00,76.44462418\n2013-11-05 19:00:00,76.14152676\n2013-11-05 20:00:00,77.7365963\n2013-11-05 21:00:00,75.94504175\n2013-11-05 22:00:00,77.66560315\n2013-11-05 23:00:00,77.14421695\n2013-11-06 00:00:00,77.14840943\n2013-11-06 01:00:00,76.57972961\n2013-11-06 02:00:00,75.67263157\n2013-11-06 03:00:00,75.55554775\n2013-11-06 04:00:00,76.02875358\n2013-11-06 05:00:00,75.83856917\n2013-11-06 06:00:00,76.72809013\n2013-11-06 07:00:00,76.8067863\n2013-11-06 08:00:00,76.14957763\n2013-11-06 09:00:00,74.72851186\n2013-11-06 10:00:00,76.79427945\n2013-11-06 11:00:00,75.54402995\n2013-11-06 12:00:00,75.62375922\n2013-11-06 13:00:00,75.66503039\n2013-11-06 14:00:00,76.1298699\n2013-11-06 15:00:00,75.2965713\n2013-11-06 16:00:00,75.65848549\n2013-11-06 17:00:00,75.77541647\n2013-11-06 18:00:00,75.7226112\n2013-11-06 19:00:00,75.17457270000001\n2013-11-06 20:00:00,76.75484571\n2013-11-06 21:00:00,76.17423765\n2013-11-06 22:00:00,76.11021976\n2013-11-06 23:00:00,77.62413958\n2013-11-07 00:00:00,76.47954412\n2013-11-07 01:00:00,77.95666612\n2013-11-07 02:00:00,77.26824525\n2013-11-07 03:00:00,76.93680905\n2013-11-07 04:00:00,77.33274264\n2013-11-07 05:00:00,75.89490524\n2013-11-07 06:00:00,76.97245983\n2013-11-07 07:00:00,76.44928327\n2013-11-07 08:00:00,76.38799696\n2013-11-07 09:00:00,76.09948105\n2013-11-07 10:00:00,76.81359962\n2013-11-07 11:00:00,75.10202225\n2013-11-07 12:00:00,75.6896651\n2013-11-07 13:00:00,76.31908661\n2013-11-07 14:00:00,76.23526528\n2013-11-07 15:00:00,75.71330856\n2013-11-07 16:00:00,75.27910715\n2013-11-07 17:00:00,75.6502543\n2013-11-07 18:00:00,76.21250234\n2013-11-07 19:00:00,77.10759799\n2013-11-07 20:00:00,76.93375995\n2013-11-07 21:00:00,75.77571222\n2013-11-07 22:00:00,75.93642846\n2013-11-07 23:00:00,75.42451794\n2013-11-08 00:00:00,75.74984119\n2013-11-08 01:00:00,75.72379288\n2013-11-08 02:00:00,76.19812769\n2013-11-08 03:00:00,76.40959723\n2013-11-08 04:00:00,76.17249971\n2013-11-08 05:00:00,74.18157735\n2013-11-08 06:00:00,75.54911204\n2013-11-08 07:00:00,74.92685622\n2013-11-08 08:00:00,74.06821774\n2013-11-08 09:00:00,74.6063132\n2013-11-08 10:00:00,74.59934737\n2013-11-08 11:00:00,74.57257027\n2013-11-08 12:00:00,75.80192985\n2013-11-08 13:00:00,75.58576634\n2013-11-08 14:00:00,75.80339835\n2013-11-08 15:00:00,74.95083817\n2013-11-08 16:00:00,74.30202352\n2013-11-08 17:00:00,74.30126215\n2013-11-08 18:00:00,74.56143904\n2013-11-08 19:00:00,74.80702056\n2013-11-08 20:00:00,73.81540339\n2013-11-08 21:00:00,74.46177933\n2013-11-08 22:00:00,73.33340389\n2013-11-08 23:00:00,73.13844142\n2013-11-09 00:00:00,74.43327812\n2013-11-09 01:00:00,73.55423309999998\n2013-11-09 02:00:00,74.72110603\n2013-11-09 03:00:00,73.50877487\n2013-11-09 04:00:00,74.83946496\n2013-11-09 05:00:00,73.55614636\n2013-11-09 06:00:00,73.07126074\n2013-11-09 07:00:00,72.82584529\n2013-11-09 08:00:00,72.95550534\n2013-11-09 09:00:00,73.64826422\n2013-11-09 10:00:00,73.4784976\n2013-11-09 11:00:00,73.16790935\n2013-11-09 12:00:00,72.25990891\n2013-11-09 13:00:00,73.22695232\n2013-11-09 14:00:00,73.36574509999998\n2013-11-09 15:00:00,72.78698119\n2013-11-09 16:00:00,73.23132790000003\n2013-11-09 17:00:00,73.06305918\n2013-11-09 18:00:00,73.23528333\n2013-11-09 19:00:00,73.95548531\n2013-11-09 20:00:00,73.98859537\n2013-11-09 21:00:00,73.18927798\n2013-11-09 22:00:00,73.48796428\n2013-11-09 23:00:00,73.23741435\n2013-11-10 00:00:00,74.54367695\n2013-11-10 01:00:00,73.43081550000002\n2013-11-10 02:00:00,74.74891586\n2013-11-10 03:00:00,74.75362909\n2013-11-10 04:00:00,72.86175442\n2013-11-10 05:00:00,72.73720269\n2013-11-10 06:00:00,73.3559507\n2013-11-10 07:00:00,73.39759537\n2013-11-10 08:00:00,73.14595598\n2013-11-10 09:00:00,73.76092178\n2013-11-10 10:00:00,72.25168702\n2013-11-10 11:00:00,73.13205651\n2013-11-10 12:00:00,72.08360267\n2013-11-10 13:00:00,72.07368375\n2013-11-10 14:00:00,72.61268471\n2013-11-10 15:00:00,73.72321874\n2013-11-10 16:00:00,73.72849169\n2013-11-10 17:00:00,73.13296089\n2013-11-10 18:00:00,72.65494358\n2013-11-10 19:00:00,72.32299088\n2013-11-10 20:00:00,73.55015881\n2013-11-10 21:00:00,73.72223486\n2013-11-10 22:00:00,72.25297108\n2013-11-10 23:00:00,72.31541006\n2013-11-11 00:00:00,72.76195068\n2013-11-11 01:00:00,73.76142519\n2013-11-11 02:00:00,73.10583663\n2013-11-11 03:00:00,73.50193935\n2013-11-11 04:00:00,73.49132918\n2013-11-11 05:00:00,72.41669997\n2013-11-11 06:00:00,73.04263579\n2013-11-11 07:00:00,72.31388627\n2013-11-11 08:00:00,71.53125555\n2013-11-11 09:00:00,72.51297974\n2013-11-11 10:00:00,73.05072318\n2013-11-11 11:00:00,72.93039079\n2013-11-11 12:00:00,72.68112696\n2013-11-11 13:00:00,74.10651227\n2013-11-11 14:00:00,73.20678582\n2013-11-11 15:00:00,73.97883407\n2013-11-11 16:00:00,74.29101178\n2013-11-11 17:00:00,75.92300396\n2013-11-11 18:00:00,75.09551863\n2013-11-11 19:00:00,74.50642676\n2013-11-11 20:00:00,75.29868809\n2013-11-11 21:00:00,74.81087057\n2013-11-11 22:00:00,75.04623283\n2013-11-11 23:00:00,75.27267490000001\n2013-11-12 00:00:00,74.35723061\n2013-11-12 01:00:00,75.59912555\n2013-11-12 02:00:00,75.38508019\n2013-11-12 03:00:00,74.01849770000003\n2013-11-12 04:00:00,74.67643353\n2013-11-12 05:00:00,74.23187951\n2013-11-12 06:00:00,73.23464912\n2013-11-12 07:00:00,72.9246375\n2013-11-12 08:00:00,73.50042577\n2013-11-12 09:00:00,73.9103724\n2013-11-12 10:00:00,73.36473041\n2013-11-12 11:00:00,74.56847369\n2013-11-12 12:00:00,73.01626683\n2013-11-12 13:00:00,74.58986064\n2013-11-12 14:00:00,74.79361415\n2013-11-12 15:00:00,74.62816075\n2013-11-12 16:00:00,73.48499084\n2013-11-12 17:00:00,74.83572629999998\n2013-11-12 18:00:00,75.71863379\n2013-11-12 19:00:00,74.10748463\n2013-11-12 20:00:00,76.18679389\n2013-11-12 21:00:00,75.68515368\n2013-11-12 22:00:00,75.95116314\n2013-11-12 23:00:00,75.27091748\n2013-11-13 00:00:00,75.10698746\n2013-11-13 01:00:00,75.50230648\n2013-11-13 02:00:00,74.96947424\n2013-11-13 03:00:00,74.66135819\n2013-11-13 04:00:00,74.16500932\n2013-11-13 05:00:00,73.61945248\n2013-11-13 06:00:00,73.04705436\n2013-11-13 07:00:00,73.10898413\n2013-11-13 08:00:00,73.14571961\n2013-11-13 09:00:00,73.13454489\n2013-11-13 10:00:00,73.63776206\n2013-11-13 11:00:00,72.51683568\n2013-11-13 12:00:00,74.15631949\n2013-11-13 13:00:00,73.16933890000001\n2013-11-13 14:00:00,74.42966035\n2013-11-13 15:00:00,73.93593742\n2013-11-13 16:00:00,74.0165059\n2013-11-13 17:00:00,75.64136409999998\n2013-11-13 18:00:00,75.49191161\n2013-11-13 19:00:00,74.71810201\n2013-11-13 20:00:00,75.30978555\n2013-11-13 21:00:00,75.66631972\n2013-11-13 22:00:00,76.3113897\n2013-11-13 23:00:00,75.93818590000002\n2013-11-14 00:00:00,75.28806128\n2013-11-14 01:00:00,74.04154576\n2013-11-14 02:00:00,75.03847755\n2013-11-14 03:00:00,74.23765297\n2013-11-14 04:00:00,74.41627738\n2013-11-14 05:00:00,72.52116762\n2013-11-14 06:00:00,72.25396537\n2013-11-14 07:00:00,73.35919816\n2013-11-14 08:00:00,73.3005709\n2013-11-14 09:00:00,71.94989116\n2013-11-14 10:00:00,72.70754191\n2013-11-14 11:00:00,73.57919806\n2013-11-14 12:00:00,73.71447163\n2013-11-14 13:00:00,73.20962568\n2013-11-14 14:00:00,73.60901764\n2013-11-14 15:00:00,73.39056823\n2013-11-14 16:00:00,74.84991329\n2013-11-14 17:00:00,75.29117938\n2013-11-14 18:00:00,75.05266772\n2013-11-14 19:00:00,73.87313966\n2013-11-14 20:00:00,73.88685052\n2013-11-14 21:00:00,75.32457686\n2013-11-14 22:00:00,74.52795985\n2013-11-14 23:00:00,74.50517038\n2013-11-15 00:00:00,75.28019509999999\n2013-11-15 01:00:00,73.39054569\n2013-11-15 02:00:00,73.61502322\n2013-11-15 03:00:00,73.40129594\n2013-11-15 04:00:00,72.71904624\n2013-11-15 05:00:00,73.04163914\n2013-11-15 06:00:00,71.66850691\n2013-11-15 07:00:00,72.44293549\n2013-11-15 08:00:00,72.77424531\n2013-11-15 09:00:00,71.02651442\n2013-11-15 10:00:00,72.46122501\n2013-11-15 11:00:00,72.053069\n2013-11-15 12:00:00,71.43164940000003\n2013-11-15 13:00:00,73.5399011\n2013-11-15 14:00:00,73.32159625\n2013-11-15 15:00:00,74.17128378\n2013-11-15 16:00:00,73.44249817\n2013-11-15 17:00:00,73.84389329999998\n2013-11-15 18:00:00,74.32478195\n2013-11-15 19:00:00,74.33059913\n2013-11-15 20:00:00,74.50938842\n2013-11-15 21:00:00,74.18876225\n2013-11-15 22:00:00,73.26010958\n2013-11-15 23:00:00,72.71542581\n2013-11-16 00:00:00,72.91699629\n2013-11-16 01:00:00,72.72921375\n2013-11-16 02:00:00,72.00496338\n2013-11-16 03:00:00,72.91473652\n2013-11-16 04:00:00,72.22070042\n2013-11-16 05:00:00,72.19057869\n2013-11-16 06:00:00,72.75354149\n2013-11-16 07:00:00,70.85140062\n2013-11-16 08:00:00,72.60434778\n2013-11-16 09:00:00,72.2513124\n2013-11-16 10:00:00,72.44304869\n2013-11-16 11:00:00,71.82902242\n2013-11-16 12:00:00,72.13432831\n2013-11-16 13:00:00,72.28302117\n2013-11-16 14:00:00,70.87841589\n2013-11-16 15:00:00,70.5596423\n2013-11-16 16:00:00,71.49929374\n2013-11-16 17:00:00,70.91004612\n2013-11-16 18:00:00,71.52840484\n2013-11-16 19:00:00,71.62859496\n2013-11-16 20:00:00,72.74468133\n2013-11-16 21:00:00,71.59071961\n2013-11-16 22:00:00,72.53877392\n2013-11-16 23:00:00,72.67710054\n2013-11-17 00:00:00,72.51924339\n2013-11-17 01:00:00,72.53149628\n2013-11-17 02:00:00,71.57898299\n2013-11-17 03:00:00,72.42367877\n2013-11-17 04:00:00,71.48775583\n2013-11-17 05:00:00,71.06116079\n2013-11-17 06:00:00,70.32136308\n2013-11-17 07:00:00,71.8799218\n2013-11-17 08:00:00,72.01945706\n2013-11-17 09:00:00,71.02801335\n2013-11-17 10:00:00,70.32011267\n2013-11-17 11:00:00,70.43736052\n2013-11-17 12:00:00,70.71326074\n2013-11-17 13:00:00,71.29496969\n2013-11-17 14:00:00,71.19238211\n2013-11-17 15:00:00,70.76197992\n2013-11-17 16:00:00,71.97783594\n2013-11-17 17:00:00,71.93428932\n2013-11-17 18:00:00,70.92727189\n2013-11-17 19:00:00,70.69309796\n2013-11-17 20:00:00,72.26337995\n2013-11-17 21:00:00,71.59257385\n2013-11-17 22:00:00,72.78595446\n2013-11-17 23:00:00,72.51893435\n2013-11-18 00:00:00,71.86984301\n2013-11-18 01:00:00,72.26094927\n2013-11-18 02:00:00,71.49387364\n2013-11-18 03:00:00,71.34440084\n2013-11-18 04:00:00,71.45222531\n2013-11-18 05:00:00,71.07687116\n2013-11-18 06:00:00,70.85817442\n2013-11-18 07:00:00,70.94781553\n2013-11-18 08:00:00,70.27853073\n2013-11-18 09:00:00,69.32489169\n2013-11-18 10:00:00,70.20579203\n2013-11-18 11:00:00,70.38921093\n2013-11-18 12:00:00,71.97995521\n2013-11-18 13:00:00,71.09700465\n2013-11-18 14:00:00,73.01321007\n2013-11-18 15:00:00,72.74733169\n2013-11-18 16:00:00,72.53910037\n2013-11-18 17:00:00,73.35960207\n2013-11-18 18:00:00,72.84142418\n2013-11-18 19:00:00,74.43420638\n2013-11-18 20:00:00,74.6164561\n2013-11-18 21:00:00,74.22528903\n2013-11-18 22:00:00,74.42442215\n2013-11-18 23:00:00,73.14775012\n2013-11-19 00:00:00,73.69107041\n2013-11-19 01:00:00,74.03109935\n2013-11-19 02:00:00,73.46135999\n2013-11-19 03:00:00,72.49412233\n2013-11-19 04:00:00,73.09658152\n2013-11-19 05:00:00,73.46536527\n2013-11-19 06:00:00,72.80605916\n2013-11-19 07:00:00,71.59932742\n2013-11-19 08:00:00,72.73375635\n2013-11-19 09:00:00,73.27079545\n2013-11-19 10:00:00,72.32538482\n2013-11-19 11:00:00,71.96557762\n2013-11-19 12:00:00,72.50861543\n2013-11-19 13:00:00,72.20848244\n2013-11-19 14:00:00,73.98532747\n2013-11-19 15:00:00,73.77910642\n2013-11-19 16:00:00,73.74309124\n2013-11-19 17:00:00,75.62033656\n2013-11-19 18:00:00,75.92989871\n2013-11-19 19:00:00,76.14345589\n2013-11-19 20:00:00,75.62712477\n2013-11-19 21:00:00,76.09385992\n2013-11-19 22:00:00,76.71081637\n2013-11-19 23:00:00,76.04933698\n2013-11-20 00:00:00,75.72755913\n2013-11-20 01:00:00,75.51638547\n2013-11-20 02:00:00,74.52746945\n2013-11-20 03:00:00,74.48053719\n2013-11-20 04:00:00,75.44810401\n2013-11-20 05:00:00,73.87105555\n2013-11-20 06:00:00,75.52376743\n2013-11-20 07:00:00,73.59258353\n2013-11-20 08:00:00,73.54086694\n2013-11-20 09:00:00,74.60328237\n2013-11-20 10:00:00,73.53405054\n2013-11-20 11:00:00,73.18585771\n2013-11-20 12:00:00,74.73396876\n2013-11-20 13:00:00,74.00301199\n2013-11-20 14:00:00,74.25992091\n2013-11-20 15:00:00,75.3819048\n2013-11-20 16:00:00,74.89925956\n2013-11-20 17:00:00,74.95695549\n2013-11-20 18:00:00,74.99328121\n2013-11-20 19:00:00,76.8861063\n2013-11-20 20:00:00,75.74120031\n2013-11-20 21:00:00,77.29515004\n2013-11-20 22:00:00,77.42615583\n2013-11-20 23:00:00,77.57042544\n2013-11-21 00:00:00,76.97148499\n2013-11-21 01:00:00,76.55304852\n2013-11-21 02:00:00,76.83218408\n2013-11-21 03:00:00,76.76691174\n2013-11-21 04:00:00,75.03003109\n2013-11-21 05:00:00,76.13262453\n2013-11-21 06:00:00,74.88298612\n2013-11-21 07:00:00,74.75528879999997\n2013-11-21 08:00:00,74.96824419\n2013-11-21 09:00:00,74.38032373\n2013-11-21 10:00:00,74.51502775\n2013-11-21 11:00:00,75.03807231\n2013-11-21 12:00:00,75.47315484\n2013-11-21 13:00:00,74.28147702\n2013-11-21 14:00:00,74.9158214\n2013-11-21 15:00:00,74.73332116\n2013-11-21 16:00:00,74.57659907\n2013-11-21 17:00:00,75.13741621\n2013-11-21 18:00:00,76.09123393\n2013-11-21 19:00:00,75.48996689\n2013-11-21 20:00:00,75.37277558\n2013-11-21 21:00:00,74.86375645\n2013-11-21 22:00:00,74.72416427\n2013-11-21 23:00:00,75.88303251\n2013-11-22 00:00:00,76.26881945\n2013-11-22 01:00:00,74.40797403\n2013-11-22 02:00:00,75.07100534\n2013-11-22 03:00:00,75.22936273\n2013-11-22 04:00:00,75.3850351\n2013-11-22 05:00:00,74.12951939\n2013-11-22 06:00:00,74.33830078\n2013-11-22 07:00:00,73.13110340000001\n2013-11-22 08:00:00,73.72892540000002\n2013-11-22 09:00:00,73.47971521\n2013-11-22 10:00:00,73.55503441\n2013-11-22 11:00:00,73.21770574\n2013-11-22 12:00:00,74.8002409\n2013-11-22 13:00:00,75.10424352\n2013-11-22 14:00:00,74.02504086\n2013-11-22 15:00:00,75.99705923\n2013-11-22 16:00:00,76.14728499\n2013-11-22 17:00:00,75.97342391\n2013-11-22 18:00:00,74.55135899\n2013-11-22 19:00:00,75.52513628\n2013-11-22 20:00:00,74.83841776\n2013-11-22 21:00:00,75.86804316\n2013-11-22 22:00:00,74.78322701\n2013-11-22 23:00:00,74.93730171\n2013-11-23 00:00:00,75.99533878\n2013-11-23 01:00:00,74.9811996\n2013-11-23 02:00:00,74.90004537\n2013-11-23 03:00:00,74.45881512\n2013-11-23 04:00:00,74.98859321\n2013-11-23 05:00:00,74.80551896\n2013-11-23 06:00:00,74.37725744\n2013-11-23 07:00:00,73.23877045\n2013-11-23 08:00:00,74.57228705\n2013-11-23 09:00:00,73.61937989\n2013-11-23 10:00:00,73.62510552\n2013-11-23 11:00:00,73.89538449\n2013-11-23 12:00:00,73.97705688\n2013-11-23 13:00:00,73.49598319\n2013-11-23 14:00:00,74.480482\n2013-11-23 15:00:00,74.05324671\n2013-11-23 16:00:00,72.99508362\n2013-11-23 17:00:00,74.06252472\n2013-11-23 18:00:00,74.31310832\n2013-11-23 19:00:00,73.86600895\n2013-11-23 20:00:00,74.72618679\n2013-11-23 21:00:00,74.87409105\n2013-11-23 22:00:00,75.16150552\n2013-11-23 23:00:00,75.24524494\n2013-11-24 00:00:00,76.06110472\n2013-11-24 01:00:00,76.04876445\n2013-11-24 02:00:00,75.92643826\n2013-11-24 03:00:00,75.30896496\n2013-11-24 04:00:00,73.85862031\n2013-11-24 05:00:00,74.35243191\n2013-11-24 06:00:00,73.22576335\n2013-11-24 07:00:00,73.89709736\n2013-11-24 08:00:00,73.45107827\n2013-11-24 09:00:00,74.28662864\n2013-11-24 10:00:00,73.11935916\n2013-11-24 11:00:00,73.61847392\n2013-11-24 12:00:00,73.95085216\n2013-11-24 13:00:00,73.81302278\n2013-11-24 14:00:00,74.47090026\n2013-11-24 15:00:00,73.99949512\n2013-11-24 16:00:00,74.01073568\n2013-11-24 17:00:00,74.48269327\n2013-11-24 18:00:00,74.99975789\n2013-11-24 19:00:00,75.51838405\n2013-11-24 20:00:00,74.91884001\n2013-11-24 21:00:00,76.19947972\n2013-11-24 22:00:00,76.37182291\n2013-11-24 23:00:00,75.88886956\n2013-11-25 00:00:00,75.8200126\n2013-11-25 01:00:00,75.09124497\n2013-11-25 02:00:00,76.15627384\n2013-11-25 03:00:00,74.91899343\n2013-11-25 04:00:00,74.96455081\n2013-11-25 05:00:00,73.92706103\n2013-11-25 06:00:00,74.79903613\n2013-11-25 07:00:00,73.3751018\n2013-11-25 08:00:00,73.59611961\n2013-11-25 09:00:00,73.62927662\n2013-11-25 10:00:00,74.00708949\n2013-11-25 11:00:00,73.65766251\n2013-11-25 12:00:00,75.03306974\n2013-11-25 13:00:00,75.04645886\n2013-11-25 14:00:00,75.24681613\n2013-11-25 15:00:00,75.70692895\n2013-11-25 16:00:00,74.67360854\n2013-11-25 17:00:00,74.61358909\n2013-11-25 18:00:00,74.491203\n2013-11-25 19:00:00,76.12426881\n2013-11-25 20:00:00,76.37678862\n2013-11-25 21:00:00,76.92387133\n2013-11-25 22:00:00,75.33838879\n2013-11-25 23:00:00,75.99550579\n2013-11-26 00:00:00,76.69138228\n2013-11-26 01:00:00,75.88567453\n2013-11-26 02:00:00,75.76685516\n2013-11-26 03:00:00,75.37412724\n2013-11-26 04:00:00,76.68765753\n2013-11-26 05:00:00,74.51443263\n2013-11-26 06:00:00,74.81803517\n2013-11-26 07:00:00,75.98462212\n2013-11-26 08:00:00,75.47773677\n2013-11-26 09:00:00,73.83422894\n2013-11-26 10:00:00,74.80800635\n2013-11-26 11:00:00,74.2813275\n2013-11-26 12:00:00,75.90857214\n2013-11-26 13:00:00,75.58094376\n2013-11-26 14:00:00,75.38129562\n2013-11-26 15:00:00,75.16651189\n2013-11-26 16:00:00,75.93238329\n2013-11-26 17:00:00,74.27644123\n2013-11-26 18:00:00,74.14545793\n2013-11-26 19:00:00,74.83272443\n2013-11-26 20:00:00,75.96087554\n2013-11-26 21:00:00,76.77265319\n2013-11-26 22:00:00,77.00068715\n2013-11-26 23:00:00,77.15745947\n2013-11-27 00:00:00,77.15974376\n2013-11-27 01:00:00,76.69033706\n2013-11-27 02:00:00,76.17756923\n2013-11-27 03:00:00,77.24837065\n2013-11-27 04:00:00,77.35430618\n2013-11-27 05:00:00,77.55637201\n2013-11-27 06:00:00,77.11772453\n2013-11-27 07:00:00,76.16169102\n2013-11-27 08:00:00,76.13252582\n2013-11-27 09:00:00,76.22151059999999\n2013-11-27 10:00:00,74.98788383\n2013-11-27 11:00:00,75.70819313\n2013-11-27 12:00:00,75.28208686\n2013-11-27 13:00:00,75.58863441\n2013-11-27 14:00:00,76.04015957\n2013-11-27 15:00:00,76.30194796\n2013-11-27 16:00:00,76.25516001\n2013-11-27 17:00:00,74.8667481\n2013-11-27 18:00:00,75.62370485\n2013-11-27 19:00:00,74.98800103\n2013-11-27 20:00:00,76.56855175\n2013-11-27 21:00:00,76.20402117\n2013-11-27 22:00:00,76.04503464\n2013-11-27 23:00:00,78.00863821\n2013-11-28 00:00:00,77.16791565\n2013-11-28 01:00:00,77.47286351\n2013-11-28 02:00:00,78.34299712\n2013-11-28 03:00:00,77.23397943\n2013-11-28 04:00:00,78.33064076\n2013-11-28 05:00:00,77.74235688\n2013-11-28 06:00:00,76.90841346\n2013-11-28 07:00:00,78.19122395\n2013-11-28 08:00:00,77.11531177\n2013-11-28 09:00:00,76.19078959\n2013-11-28 10:00:00,75.89108336\n2013-11-28 11:00:00,74.91135143\n2013-11-28 12:00:00,76.05428041\n2013-11-28 13:00:00,74.98413324\n2013-11-28 14:00:00,76.71790748\n2013-11-28 15:00:00,76.87780803\n2013-11-28 16:00:00,75.59376618\n2013-11-28 17:00:00,75.42355277\n2013-11-28 18:00:00,76.12701487\n2013-11-28 19:00:00,76.85731503\n2013-11-28 20:00:00,76.36303141\n2013-11-28 21:00:00,75.84007067\n2013-11-28 22:00:00,76.46922703\n2013-11-28 23:00:00,76.80884417\n2013-11-29 00:00:00,79.02591263\n2013-11-29 01:00:00,78.20757005\n2013-11-29 02:00:00,78.47792298\n2013-11-29 03:00:00,79.23633448\n2013-11-29 04:00:00,78.88770756\n2013-11-29 05:00:00,78.8953397\n2013-11-29 06:00:00,78.876609\n2013-11-29 07:00:00,77.56230513\n2013-11-29 08:00:00,76.59404839\n2013-11-29 09:00:00,76.94499489\n2013-11-29 10:00:00,78.49555784\n2013-11-29 11:00:00,76.94027286\n2013-11-29 12:00:00,77.88769599\n2013-11-29 13:00:00,77.17967275\n2013-11-29 14:00:00,77.53951629\n2013-11-29 15:00:00,76.83583058\n2013-11-29 16:00:00,77.38018752\n2013-11-29 17:00:00,78.10468211\n2013-11-29 18:00:00,77.14646568\n2013-11-29 19:00:00,76.97117206\n2013-11-29 20:00:00,77.84318487\n2013-11-29 21:00:00,76.66135240000001\n2013-11-29 22:00:00,78.15703794\n2013-11-29 23:00:00,77.46965922\n2013-11-30 00:00:00,77.88460537\n2013-11-30 01:00:00,77.65864458\n2013-11-30 02:00:00,78.70593097\n2013-11-30 03:00:00,78.50094859\n2013-11-30 04:00:00,77.02001536\n2013-11-30 05:00:00,78.09143757\n2013-11-30 06:00:00,76.72362831\n2013-11-30 07:00:00,76.45580209\n2013-11-30 08:00:00,77.02544955\n2013-11-30 09:00:00,78.11045131\n2013-11-30 10:00:00,76.35997079\n2013-11-30 11:00:00,76.89472925\n2013-11-30 12:00:00,77.04274751\n2013-11-30 13:00:00,77.94149348\n2013-11-30 14:00:00,77.75067472\n2013-11-30 15:00:00,77.55710197\n2013-11-30 16:00:00,76.86340194\n2013-11-30 17:00:00,78.53850778\n2013-11-30 18:00:00,78.37908378\n2013-11-30 19:00:00,78.81008775\n2013-11-30 20:00:00,77.73485863\n2013-11-30 21:00:00,77.83555944\n2013-11-30 22:00:00,78.56664962\n2013-11-30 23:00:00,78.4432628\n2013-12-01 00:00:00,78.58726082\n2013-12-01 01:00:00,77.53521019\n2013-12-01 02:00:00,77.63065448\n2013-12-01 03:00:00,78.12865125\n2013-12-01 04:00:00,77.86603288\n2013-12-01 05:00:00,77.44856207\n2013-12-01 06:00:00,76.98370721\n2013-12-01 07:00:00,75.4790699\n2013-12-01 08:00:00,75.33305301\n2013-12-01 09:00:00,75.89776898\n2013-12-01 10:00:00,76.60147615\n2013-12-01 11:00:00,74.71098020000002\n2013-12-01 12:00:00,75.3552543\n2013-12-01 13:00:00,74.87224431\n2013-12-01 14:00:00,75.9791723\n2013-12-01 15:00:00,75.47730656\n2013-12-01 16:00:00,75.2003445\n2013-12-01 17:00:00,76.27953207\n2013-12-01 18:00:00,76.45168292\n2013-12-01 19:00:00,76.07015052\n2013-12-01 20:00:00,75.73563349999998\n2013-12-01 21:00:00,77.0986277\n2013-12-01 22:00:00,76.35243379\n2013-12-01 23:00:00,76.91635076\n2013-12-02 00:00:00,75.41786731\n2013-12-02 01:00:00,76.54536726\n2013-12-02 02:00:00,75.59756303\n2013-12-02 03:00:00,74.89586951\n2013-12-02 04:00:00,75.43229909\n2013-12-02 05:00:00,74.50186087\n2013-12-02 06:00:00,74.80732462\n2013-12-02 07:00:00,73.08595318\n2013-12-02 08:00:00,73.80861958\n2013-12-02 09:00:00,73.38120847\n2013-12-02 10:00:00,74.42042248\n2013-12-02 11:00:00,75.53513849\n2013-12-02 12:00:00,75.09092686\n2013-12-02 13:00:00,75.56936508\n2013-12-02 14:00:00,74.90652388\n2013-12-02 15:00:00,74.082068\n2013-12-02 16:00:00,75.77601988\n2013-12-02 17:00:00,74.20052806\n2013-12-02 18:00:00,75.23398924\n2013-12-02 19:00:00,74.67382574\n2013-12-02 20:00:00,74.65542741\n2013-12-02 21:00:00,74.67489567\n2013-12-02 22:00:00,74.8350368\n2013-12-02 23:00:00,76.08893067\n2013-12-03 00:00:00,75.15278013\n2013-12-03 01:00:00,75.02923911\n2013-12-03 02:00:00,75.85895688\n2013-12-03 03:00:00,74.36103377\n2013-12-03 04:00:00,75.5156958\n2013-12-03 05:00:00,74.70868339\n2013-12-03 06:00:00,73.83262026\n2013-12-03 07:00:00,73.70124329\n2013-12-03 08:00:00,73.63678504\n2013-12-03 09:00:00,73.41637369\n2013-12-03 10:00:00,73.80197277\n2013-12-03 11:00:00,73.97767514\n2013-12-03 12:00:00,74.83469243\n2013-12-03 13:00:00,74.97139121\n2013-12-03 14:00:00,73.77486044\n2013-12-03 15:00:00,75.13503163\n2013-12-03 16:00:00,73.87999867\n2013-12-03 17:00:00,75.77548486\n2013-12-03 18:00:00,75.01213492\n2013-12-03 19:00:00,75.50478063\n2013-12-03 20:00:00,76.25258396\n2013-12-03 21:00:00,75.71050611\n2013-12-03 22:00:00,77.20657998\n2013-12-03 23:00:00,77.30399661\n2013-12-04 00:00:00,75.91202374\n2013-12-04 01:00:00,76.66853953\n2013-12-04 02:00:00,75.74567822\n2013-12-04 03:00:00,75.19938463\n2013-12-04 04:00:00,76.19384417\n2013-12-04 05:00:00,76.09302338\n2013-12-04 06:00:00,76.04003915\n2013-12-04 07:00:00,75.29326815\n2013-12-04 08:00:00,74.21052551\n2013-12-04 09:00:00,75.1991017\n2013-12-04 10:00:00,74.06782191\n2013-12-04 11:00:00,75.64687089\n2013-12-04 12:00:00,74.70819726\n2013-12-04 13:00:00,75.45305517\n2013-12-04 14:00:00,74.00072839\n2013-12-04 15:00:00,74.0555797\n2013-12-04 16:00:00,74.61075053\n2013-12-04 17:00:00,75.33297088\n2013-12-04 18:00:00,75.94712761\n2013-12-04 19:00:00,75.58518275\n2013-12-04 20:00:00,76.02023976\n2013-12-04 21:00:00,76.59701799\n2013-12-04 22:00:00,76.96921944\n2013-12-04 23:00:00,77.22393149\n2013-12-05 00:00:00,75.97207085\n2013-12-05 01:00:00,77.39107002\n2013-12-05 02:00:00,76.84450656\n2013-12-05 03:00:00,77.41677019\n2013-12-05 04:00:00,75.98938319\n2013-12-05 05:00:00,76.6635247\n2013-12-05 06:00:00,75.44756559999998\n2013-12-05 07:00:00,76.21819272\n2013-12-05 08:00:00,76.32008979\n2013-12-05 09:00:00,74.9409507\n2013-12-05 10:00:00,75.4784256\n2013-12-05 11:00:00,75.17090954\n2013-12-05 12:00:00,74.29941509\n2013-12-05 13:00:00,74.3062439\n2013-12-05 14:00:00,75.90126283\n2013-12-05 15:00:00,75.04716769\n2013-12-05 16:00:00,75.58599677\n2013-12-05 17:00:00,74.87807236\n2013-12-05 18:00:00,75.27313151\n2013-12-05 19:00:00,76.48370315\n2013-12-05 20:00:00,75.50998007\n2013-12-05 21:00:00,76.75086745\n2013-12-05 22:00:00,76.68483447\n2013-12-05 23:00:00,77.38495142\n2013-12-06 00:00:00,75.87360168\n2013-12-06 01:00:00,77.6556306\n2013-12-06 02:00:00,76.42670507\n2013-12-06 03:00:00,75.71056203\n2013-12-06 04:00:00,75.06068153\n2013-12-06 05:00:00,76.10503754\n2013-12-06 06:00:00,75.62420413\n2013-12-06 07:00:00,76.08456044\n2013-12-06 08:00:00,75.29375586\n2013-12-06 09:00:00,74.80440567\n2013-12-06 10:00:00,75.19512835\n2013-12-06 11:00:00,76.00205619\n2013-12-06 12:00:00,74.52998721\n2013-12-06 13:00:00,74.90420227\n2013-12-06 14:00:00,74.16669948\n2013-12-06 15:00:00,73.80445232\n2013-12-06 16:00:00,74.47552074\n2013-12-06 17:00:00,75.30827578\n2013-12-06 18:00:00,75.03218705\n2013-12-06 19:00:00,76.23218309999999\n2013-12-06 20:00:00,75.6839157\n2013-12-06 21:00:00,74.92143663\n2013-12-06 22:00:00,76.87342138\n2013-12-06 23:00:00,76.59855258\n2013-12-07 00:00:00,75.33861432\n2013-12-07 01:00:00,75.45218311\n2013-12-07 02:00:00,76.06290495\n2013-12-07 03:00:00,74.9575668\n2013-12-07 04:00:00,76.00917564\n2013-12-07 05:00:00,75.8543825\n2013-12-07 06:00:00,75.27205469\n2013-12-07 07:00:00,75.31174871\n2013-12-07 08:00:00,74.68013979999998\n2013-12-07 09:00:00,74.82785613\n2013-12-07 10:00:00,74.52306854\n2013-12-07 11:00:00,74.15590675\n2013-12-07 12:00:00,75.10514663\n2013-12-07 13:00:00,74.7545796\n2013-12-07 14:00:00,74.52277912\n2013-12-07 15:00:00,75.82423762\n2013-12-07 16:00:00,74.22414092\n2013-12-07 17:00:00,75.46409745\n2013-12-07 18:00:00,76.33578873\n2013-12-07 19:00:00,76.79710999\n2013-12-07 20:00:00,75.93536531\n2013-12-07 21:00:00,75.56283028\n2013-12-07 22:00:00,77.20560211\n2013-12-07 23:00:00,76.87039405\n2013-12-08 00:00:00,75.44604893\n2013-12-08 01:00:00,76.57429989\n2013-12-08 02:00:00,76.06483199\n2013-12-08 03:00:00,76.00964555\n2013-12-08 04:00:00,74.80675596\n2013-12-08 05:00:00,75.1980522\n2013-12-08 06:00:00,76.07994366\n2013-12-08 07:00:00,74.76370837\n2013-12-08 08:00:00,74.52201927\n2013-12-08 09:00:00,74.64224735\n2013-12-08 10:00:00,75.14042076\n2013-12-08 11:00:00,74.36953798\n2013-12-08 12:00:00,75.37965099\n2013-12-08 13:00:00,74.93759126\n2013-12-08 14:00:00,74.37191177\n2013-12-08 15:00:00,74.73159262\n2013-12-08 16:00:00,75.61318422\n2013-12-08 17:00:00,74.40147509\n2013-12-08 18:00:00,76.13732359999999\n2013-12-08 19:00:00,74.9962055\n2013-12-08 20:00:00,75.54659614\n2013-12-08 21:00:00,75.26882561\n2013-12-08 22:00:00,74.39856404\n2013-12-08 23:00:00,74.28786598\n2013-12-09 00:00:00,75.1690554\n2013-12-09 01:00:00,75.28609538\n2013-12-09 02:00:00,75.1906637\n2013-12-09 03:00:00,73.93566312\n2013-12-09 04:00:00,74.13405397\n2013-12-09 05:00:00,74.18672976\n2013-12-09 06:00:00,74.17864554\n2013-12-09 07:00:00,72.37641122\n2013-12-09 08:00:00,73.10689581\n2013-12-09 09:00:00,73.18092841\n2013-12-09 10:00:00,72.4431114\n2013-12-09 11:00:00,73.61399348\n2013-12-09 12:00:00,73.50101128\n2013-12-09 13:00:00,72.3008609\n2013-12-09 14:00:00,72.34904296\n2013-12-09 15:00:00,72.21993949\n2013-12-09 16:00:00,73.2791445\n2013-12-09 17:00:00,73.29098671\n2013-12-09 18:00:00,73.02860249\n2013-12-09 19:00:00,73.73807814\n2013-12-09 20:00:00,73.96940648\n2013-12-09 21:00:00,73.87529271\n2013-12-09 22:00:00,74.12690095\n2013-12-09 23:00:00,74.54068596\n2013-12-10 00:00:00,74.58730262\n2013-12-10 01:00:00,73.27195908\n2013-12-10 02:00:00,73.90958789\n2013-12-10 03:00:00,74.12705890000002\n2013-12-10 04:00:00,73.64989009\n2013-12-10 05:00:00,73.12019765\n2013-12-10 06:00:00,72.94981371\n2013-12-10 07:00:00,72.63017091\n2013-12-10 08:00:00,72.71613838\n2013-12-10 09:00:00,72.71722481\n2013-12-10 10:00:00,73.73304064\n2013-12-10 11:00:00,72.67712283\n2013-12-10 12:00:00,73.64547544\n2013-12-10 13:00:00,72.30699831\n2013-12-10 14:00:00,72.64327782\n2013-12-10 15:00:00,72.70649962\n2013-12-10 16:00:00,74.00551\n2013-12-10 17:00:00,73.59150747\n2013-12-10 18:00:00,74.36327747\n2013-12-10 19:00:00,73.43398151\n2013-12-10 20:00:00,73.34037954\n2013-12-10 21:00:00,72.49370372\n2013-12-10 22:00:00,73.36328308\n2013-12-10 23:00:00,73.75270216\n2013-12-11 00:00:00,74.07760056\n2013-12-11 01:00:00,74.13267133\n2013-12-11 02:00:00,73.55944399\n2013-12-11 03:00:00,72.82256754\n2013-12-11 04:00:00,72.55823579\n2013-12-11 05:00:00,72.94645319\n2013-12-11 06:00:00,73.85665686\n2013-12-11 07:00:00,72.43060965\n2013-12-11 08:00:00,73.64939159\n2013-12-11 09:00:00,72.18117166\n2013-12-11 10:00:00,72.68621701\n2013-12-11 11:00:00,73.38138872\n2013-12-11 12:00:00,72.59355339\n2013-12-11 13:00:00,73.08965494\n2013-12-11 14:00:00,72.15235240000001\n2013-12-11 15:00:00,74.58666641\n2013-12-11 16:00:00,75.02738785\n2013-12-11 17:00:00,74.62411392\n2013-12-11 18:00:00,75.34149751\n2013-12-11 19:00:00,75.31820223\n2013-12-11 20:00:00,74.99496694\n2013-12-11 21:00:00,75.14356488\n2013-12-11 22:00:00,75.35414616\n2013-12-11 23:00:00,75.60743795\n2013-12-12 00:00:00,75.11999997\n2013-12-12 01:00:00,74.84177433\n2013-12-12 02:00:00,75.34780841\n2013-12-12 03:00:00,74.96166134\n2013-12-12 04:00:00,76.02028875\n2013-12-12 05:00:00,74.99070572\n2013-12-12 06:00:00,74.54696679\n2013-12-12 07:00:00,75.24551555\n2013-12-12 08:00:00,74.58234736\n2013-12-12 09:00:00,73.27790479\n2013-12-12 10:00:00,73.75848662\n2013-12-12 11:00:00,73.72426779\n2013-12-12 12:00:00,73.40027014\n2013-12-12 13:00:00,74.42141665\n2013-12-12 14:00:00,74.09206973\n2013-12-12 15:00:00,76.13283725\n2013-12-12 16:00:00,76.27032048\n2013-12-12 17:00:00,76.22574288\n2013-12-12 18:00:00,76.19386187\n2013-12-12 19:00:00,75.38155998\n2013-12-12 20:00:00,75.54108786\n2013-12-12 21:00:00,75.44093455\n2013-12-12 22:00:00,75.98674438\n2013-12-12 23:00:00,76.37852170000002\n2013-12-13 00:00:00,76.24170509\n2013-12-13 01:00:00,76.07005174\n2013-12-13 02:00:00,76.18773069\n2013-12-13 03:00:00,74.54095745\n2013-12-13 04:00:00,75.9857027\n2013-12-13 05:00:00,75.70301054\n2013-12-13 06:00:00,75.97637738\n2013-12-13 07:00:00,73.99051999\n2013-12-13 08:00:00,74.25959878\n2013-12-13 09:00:00,74.06537538\n2013-12-13 10:00:00,73.497738\n2013-12-13 11:00:00,74.40930673\n2013-12-13 12:00:00,73.53465219\n2013-12-13 13:00:00,74.01325297\n2013-12-13 14:00:00,74.65517361\n2013-12-13 15:00:00,73.80252519999998\n2013-12-13 16:00:00,73.47288405\n2013-12-13 17:00:00,74.39571525\n2013-12-13 18:00:00,75.54122752\n2013-12-13 19:00:00,75.61996717\n2013-12-13 20:00:00,74.29673142\n2013-12-13 21:00:00,75.83949955\n2013-12-13 22:00:00,76.92758894\n2013-12-13 23:00:00,75.89869489\n2013-12-14 00:00:00,75.17568757\n2013-12-14 01:00:00,75.81093193\n2013-12-14 02:00:00,75.69196428\n2013-12-14 03:00:00,74.5128894\n2013-12-14 04:00:00,74.98113099\n2013-12-14 05:00:00,76.17734177\n2013-12-14 06:00:00,74.42758116\n2013-12-14 07:00:00,74.07682949\n2013-12-14 08:00:00,75.69932551\n2013-12-14 09:00:00,74.84695927\n2013-12-14 10:00:00,74.35760136\n2013-12-14 11:00:00,74.39803827\n2013-12-14 12:00:00,75.02743496\n2013-12-14 13:00:00,74.02252097\n2013-12-14 14:00:00,74.56358368\n2013-12-14 15:00:00,74.69963645\n2013-12-14 16:00:00,75.09767236\n2013-12-14 17:00:00,76.44727912\n2013-12-14 18:00:00,76.95586845\n2013-12-14 19:00:00,76.87810004\n2013-12-14 20:00:00,78.17639551\n2013-12-14 21:00:00,78.63037082\n2013-12-14 22:00:00,77.38397999\n2013-12-14 23:00:00,78.19047845\n2013-12-15 00:00:00,78.61378004\n2013-12-15 01:00:00,77.03252890000002\n2013-12-15 02:00:00,78.6107109\n2013-12-15 03:00:00,76.68094652\n2013-12-15 04:00:00,77.05003701\n2013-12-15 05:00:00,76.33040884\n2013-12-15 06:00:00,77.55881425\n2013-12-15 07:00:00,77.29425879\n2013-12-15 08:00:00,75.96598011\n2013-12-15 09:00:00,76.44504229\n2013-12-15 10:00:00,77.37936193\n2013-12-15 11:00:00,76.39378285\n2013-12-15 12:00:00,76.18731941\n2013-12-15 13:00:00,75.55839334\n2013-12-15 14:00:00,77.31227539\n2013-12-15 15:00:00,77.63696989\n2013-12-15 16:00:00,76.61057145\n2013-12-15 17:00:00,78.01573292\n2013-12-15 18:00:00,78.11484883\n2013-12-15 19:00:00,77.7134697\n2013-12-15 20:00:00,78.35903267\n2013-12-15 21:00:00,77.54037213\n2013-12-15 22:00:00,77.50429946\n2013-12-15 23:00:00,78.54151818\n2013-12-16 00:00:00,78.51850373\n2013-12-16 01:00:00,79.21046638\n2013-12-16 02:00:00,79.13826897\n2013-12-16 03:00:00,78.40306640000001\n2013-12-16 04:00:00,78.62008697\n2013-12-16 05:00:00,77.13148416\n2013-12-16 06:00:00,78.02477786\n2013-12-16 07:00:00,77.86136184\n2013-12-16 08:00:00,77.78773632\n2013-12-16 09:00:00,76.85925072\n2013-12-16 10:00:00,76.69516519\n2013-12-16 11:00:00,77.00482738\n2013-12-16 12:00:00,76.44663657\n2013-12-16 13:00:00,76.83346215\n2013-12-16 14:00:00,76.46349867\n2013-12-16 15:00:00,75.94666293\n2013-12-16 16:00:00,75.43675043\n2013-12-16 17:00:00,76.31010809\n2013-12-16 18:00:00,75.95438461\n2013-12-16 19:00:00,76.15312638\n2013-12-16 20:00:00,76.12036689\n2013-12-16 21:00:00,75.94597297\n2013-12-16 22:00:00,76.55225442\n2013-12-16 23:00:00,76.79808015\n2013-12-17 00:00:00,76.48918773\n2013-12-17 01:00:00,76.33896896\n2013-12-17 02:00:00,77.05310437\n2013-12-17 03:00:00,76.54734976\n2013-12-17 04:00:00,75.9568436\n2013-12-17 05:00:00,76.51240415\n2013-12-17 06:00:00,76.18995103\n2013-12-17 07:00:00,76.90449174\n2013-12-17 08:00:00,76.17663538\n2013-12-17 09:00:00,75.63774692\n2013-12-17 10:00:00,74.76111351\n2013-12-17 11:00:00,75.90421071\n2013-12-17 12:00:00,76.50791927\n2013-12-17 13:00:00,75.03569534\n2013-12-17 14:00:00,76.44788554\n2013-12-17 15:00:00,75.69349585\n2013-12-17 16:00:00,74.67369137\n2013-12-17 17:00:00,75.53230267\n2013-12-17 18:00:00,75.69028376\n2013-12-17 19:00:00,75.61612508\n2013-12-17 20:00:00,75.38417556\n2013-12-17 21:00:00,76.53118614\n2013-12-17 22:00:00,76.0893708\n2013-12-17 23:00:00,76.67098365\n2013-12-18 00:00:00,77.51409604\n2013-12-18 01:00:00,77.71518301\n2013-12-18 02:00:00,77.49253948\n2013-12-18 03:00:00,76.1495223\n2013-12-18 04:00:00,77.69271299\n2013-12-18 05:00:00,77.3078518\n2013-12-18 06:00:00,76.58823094\n2013-12-18 07:00:00,77.01356606\n2013-12-18 08:00:00,76.29867262\n2013-12-18 09:00:00,76.6226516\n2013-12-18 10:00:00,76.44608657\n2013-12-18 11:00:00,75.00817082\n2013-12-18 12:00:00,74.40000215\n2013-12-18 13:00:00,75.95158419\n2013-12-18 14:00:00,74.806774\n2013-12-18 15:00:00,76.18399877\n2013-12-18 16:00:00,75.65218318\n2013-12-18 17:00:00,75.92126892\n2013-12-18 18:00:00,74.56981993\n2013-12-18 19:00:00,74.55990289\n2013-12-18 20:00:00,74.70972542\n2013-12-18 21:00:00,75.87615507\n2013-12-18 22:00:00,75.79608847\n2013-12-18 23:00:00,74.99922907\n2013-12-19 00:00:00,75.24370674\n2013-12-19 01:00:00,76.28685920000002\n2013-12-19 02:00:00,76.86505572\n2013-12-19 03:00:00,75.77297344\n2013-12-19 04:00:00,75.97494123\n2013-12-19 05:00:00,74.90139316\n2013-12-19 06:00:00,74.02325849\n2013-12-19 07:00:00,75.06232298\n2013-12-19 08:00:00,74.98321538\n2013-12-19 09:00:00,75.28863521\n2013-12-19 10:00:00,74.94672097\n2013-12-19 11:00:00,73.86675878\n2013-12-19 12:00:00,73.71014444\n2013-12-19 13:00:00,74.90952525\n2013-12-19 14:00:00,74.84580286\n2013-12-19 15:00:00,75.602222\n2013-12-19 16:00:00,74.74889536\n2013-12-19 17:00:00,75.01816634\n2013-12-19 18:00:00,75.72022589\n2013-12-19 19:00:00,76.30473901\n2013-12-19 20:00:00,76.01042931\n2013-12-19 21:00:00,77.21635808\n2013-12-19 22:00:00,76.50729669\n2013-12-19 23:00:00,76.88382451\n2013-12-20 00:00:00,76.77573772\n2013-12-20 01:00:00,76.28321772\n2013-12-20 02:00:00,76.24950337\n2013-12-20 03:00:00,76.06611132\n2013-12-20 04:00:00,75.81287763\n2013-12-20 05:00:00,75.70166172\n2013-12-20 06:00:00,77.39653919999998\n2013-12-20 07:00:00,76.21575455\n2013-12-20 08:00:00,76.42174243\n2013-12-20 09:00:00,76.12429859999997\n2013-12-20 10:00:00,75.95841843\n2013-12-20 11:00:00,74.24349947\n2013-12-20 12:00:00,76.0751302\n2013-12-20 13:00:00,75.84588787\n2013-12-20 14:00:00,74.92850291\n2013-12-20 15:00:00,76.3109073\n2013-12-20 16:00:00,75.13722516\n2013-12-20 17:00:00,75.66403255\n2013-12-20 18:00:00,77.34278041\n2013-12-20 19:00:00,76.93423637\n2013-12-20 20:00:00,76.61857052\n2013-12-20 21:00:00,77.03286984\n2013-12-20 22:00:00,77.55962287\n2013-12-20 23:00:00,79.09188313\n2013-12-21 00:00:00,78.52068112\n2013-12-21 01:00:00,78.98608769\n2013-12-21 02:00:00,79.4198418\n2013-12-21 03:00:00,79.04463822\n2013-12-21 04:00:00,78.08950603\n2013-12-21 05:00:00,77.60666850000001\n2013-12-21 06:00:00,77.94600233\n2013-12-21 07:00:00,77.89349375\n2013-12-21 08:00:00,78.60456446\n2013-12-21 09:00:00,77.06658421\n2013-12-21 10:00:00,78.3217143\n2013-12-21 11:00:00,77.70983715\n2013-12-21 12:00:00,78.84426107\n2013-12-21 13:00:00,77.1455334\n2013-12-21 14:00:00,78.76918765\n2013-12-21 15:00:00,77.91774797\n2013-12-21 16:00:00,78.34500813\n2013-12-21 17:00:00,79.86106375\n2013-12-21 18:00:00,80.52026302\n2013-12-21 19:00:00,79.89687488\n2013-12-21 20:00:00,82.28923988\n2013-12-21 21:00:00,82.98986906\n2013-12-21 22:00:00,83.24788623\n2013-12-21 23:00:00,82.51965884\n2013-12-22 00:00:00,82.73680192\n2013-12-22 01:00:00,83.78099481\n2013-12-22 02:00:00,83.00863385\n2013-12-22 03:00:00,82.8156272\n2013-12-22 04:00:00,81.77474405\n2013-12-22 05:00:00,82.45427776\n2013-12-22 06:00:00,82.09190101\n2013-12-22 07:00:00,80.96998612\n2013-12-22 08:00:00,81.84802474\n2013-12-22 09:00:00,82.11075802\n2013-12-22 10:00:00,80.90724311\n2013-12-22 11:00:00,81.79664979\n2013-12-22 12:00:00,80.13996622\n2013-12-22 13:00:00,80.56010402\n2013-12-22 14:00:00,81.53097122\n2013-12-22 15:00:00,81.83006626\n2013-12-22 16:00:00,83.51163000000003\n2013-12-22 17:00:00,84.39093203\n2013-12-22 18:00:00,85.22768546\n2013-12-22 19:00:00,86.09488844\n2013-12-22 20:00:00,86.20418922\n2013-12-22 21:00:00,86.22321261\n2013-12-22 22:00:00,85.64943737\n2013-12-22 23:00:00,86.07470988\n2013-12-23 00:00:00,85.32616543\n2013-12-23 01:00:00,85.70599036\n2013-12-23 02:00:00,84.08697057\n2013-12-23 03:00:00,85.22227695\n2013-12-23 04:00:00,83.65396808\n2013-12-23 05:00:00,84.32899995\n2013-12-23 06:00:00,83.11824067\n2013-12-23 07:00:00,82.62728762\n2013-12-23 08:00:00,82.6222981\n2013-12-23 09:00:00,82.37343675\n2013-12-23 10:00:00,81.32311924\n2013-12-23 11:00:00,80.15369446\n2013-12-23 12:00:00,80.29698997\n2013-12-23 13:00:00,81.14245049\n2013-12-23 14:00:00,79.87450895\n2013-12-23 15:00:00,78.72789303\n2013-12-23 16:00:00,80.46954892\n2013-12-23 17:00:00,79.03221423\n2013-12-23 18:00:00,79.87953093\n2013-12-23 19:00:00,78.55827641\n2013-12-23 20:00:00,79.53990963\n2013-12-23 21:00:00,78.25863964\n2013-12-23 22:00:00,79.65429515\n2013-12-23 23:00:00,80.24362459999998\n2013-12-24 00:00:00,80.69153985\n2013-12-24 01:00:00,80.39914328\n2013-12-24 02:00:00,81.39129706\n2013-12-24 03:00:00,81.17088406\n2013-12-24 04:00:00,79.61617311\n2013-12-24 05:00:00,81.12807513\n2013-12-24 06:00:00,80.430862\n2013-12-24 07:00:00,80.02182976\n2013-12-24 08:00:00,79.86815899999998\n2013-12-24 09:00:00,80.57302099\n2013-12-24 10:00:00,78.64657966\n2013-12-24 11:00:00,77.52978652\n2013-12-24 12:00:00,77.83306033\n2013-12-24 13:00:00,77.05832672\n2013-12-24 14:00:00,77.19065966\n2013-12-24 15:00:00,78.12445799999998\n2013-12-24 16:00:00,78.72794247\n2013-12-24 17:00:00,78.00471004\n2013-12-24 18:00:00,77.76657966\n2013-12-24 19:00:00,77.67753604\n2013-12-24 20:00:00,78.95358338\n2013-12-24 21:00:00,78.36725003\n2013-12-24 22:00:00,78.6347335\n2013-12-24 23:00:00,79.85459920000002\n2013-12-25 00:00:00,78.54898156\n2013-12-25 01:00:00,79.24333333\n2013-12-25 02:00:00,80.04303671\n2013-12-25 03:00:00,78.27609712\n2013-12-25 04:00:00,79.68598902\n2013-12-25 05:00:00,77.91620784\n2013-12-25 06:00:00,79.18453247\n2013-12-25 07:00:00,77.94191184\n2013-12-25 08:00:00,77.08242193\n2013-12-25 09:00:00,77.14715291\n2013-12-25 10:00:00,77.62220228\n2013-12-25 11:00:00,78.39516049\n2013-12-25 12:00:00,76.84592783\n2013-12-25 13:00:00,78.29719758\n2013-12-25 14:00:00,77.61888521\n2013-12-25 15:00:00,77.00744034\n2013-12-25 16:00:00,77.76062769\n2013-12-25 17:00:00,77.05181008\n2013-12-25 18:00:00,77.0723302\n2013-12-25 19:00:00,78.46417804\n2013-12-25 20:00:00,77.42081363\n2013-12-25 21:00:00,77.808112\n2013-12-25 22:00:00,77.61400932\n2013-12-25 23:00:00,78.09598691\n2013-12-26 00:00:00,77.77116624\n2013-12-26 01:00:00,77.12786457\n2013-12-26 02:00:00,77.0909157\n2013-12-26 03:00:00,78.23972837\n2013-12-26 04:00:00,77.93250468\n2013-12-26 05:00:00,77.65365613\n2013-12-26 06:00:00,76.34552706\n2013-12-26 07:00:00,77.17220436\n2013-12-26 08:00:00,76.85489779\n2013-12-26 09:00:00,77.10917493\n2013-12-26 10:00:00,76.08132018\n2013-12-26 11:00:00,75.97126016\n2013-12-26 12:00:00,75.31930024\n2013-12-26 13:00:00,76.16500538\n2013-12-26 14:00:00,76.33505989\n2013-12-26 15:00:00,74.71455759\n2013-12-26 16:00:00,75.16889103\n2013-12-26 17:00:00,76.88840520000002\n2013-12-26 18:00:00,75.877899\n2013-12-26 19:00:00,76.41369568\n2013-12-26 20:00:00,76.51985988\n2013-12-26 21:00:00,76.32626701\n2013-12-26 22:00:00,76.75690732\n2013-12-26 23:00:00,77.20223204\n2013-12-27 00:00:00,76.54350997\n2013-12-27 01:00:00,77.01021977\n2013-12-27 02:00:00,77.28761998\n2013-12-27 03:00:00,77.13929934\n2013-12-27 04:00:00,75.83918057\n2013-12-27 05:00:00,77.4130038\n2013-12-27 06:00:00,75.63631529\n2013-12-27 07:00:00,76.80939855\n2013-12-27 08:00:00,77.20317007\n2013-12-27 09:00:00,75.9880975\n2013-12-27 10:00:00,75.60517409\n2013-12-27 11:00:00,76.4823878\n2013-12-27 12:00:00,76.08486147\n2013-12-27 13:00:00,75.05631746\n2013-12-27 14:00:00,75.71939344\n2013-12-27 15:00:00,75.49636047\n2013-12-27 16:00:00,75.55847428\n2013-12-27 17:00:00,75.78702171\n2013-12-27 18:00:00,75.42590876\n2013-12-27 19:00:00,76.5985245\n2013-12-27 20:00:00,75.35253788\n2013-12-27 21:00:00,75.52461588\n2013-12-27 22:00:00,75.27324876\n2013-12-27 23:00:00,76.24473974\n2013-12-28 00:00:00,76.39365772\n2013-12-28 01:00:00,76.14188495\n2013-12-28 02:00:00,76.01404616\n2013-12-28 03:00:00,76.24766604\n2013-12-28 04:00:00,74.60550738\n2013-12-28 05:00:00,75.27305911\n2013-12-28 06:00:00,75.76095709\n2013-12-28 07:00:00,75.18391571\n2013-12-28 08:00:00,74.39944531\n2013-12-28 09:00:00,74.93700505\n2013-12-28 10:00:00,74.62630625\n2013-12-28 11:00:00,74.52466577\n2013-12-28 12:00:00,75.20171861\n2013-12-28 13:00:00,75.59031954\n2013-12-28 14:00:00,74.99300208\n2013-12-28 15:00:00,75.12205049\n2013-12-28 16:00:00,74.8451182\n2013-12-28 17:00:00,75.5004353\n2013-12-28 18:00:00,75.78745907\n2013-12-28 19:00:00,76.80171084\n2013-12-28 20:00:00,76.89224059\n2013-12-28 21:00:00,76.57189936\n2013-12-28 22:00:00,76.05772001\n2013-12-28 23:00:00,76.30518585\n2013-12-29 00:00:00,75.67921558\n2013-12-29 01:00:00,75.65697105\n2013-12-29 02:00:00,76.36312409\n2013-12-29 03:00:00,76.36912771\n2013-12-29 04:00:00,75.98000468\n2013-12-29 05:00:00,74.95772326\n2013-12-29 06:00:00,75.4259806\n2013-12-29 07:00:00,75.84298448\n2013-12-29 08:00:00,74.33460196\n2013-12-29 09:00:00,75.25125208\n2013-12-29 10:00:00,75.28419137\n2013-12-29 11:00:00,73.97549299\n2013-12-29 12:00:00,73.77993441\n2013-12-29 13:00:00,74.11605842\n2013-12-29 14:00:00,75.41199782\n2013-12-29 15:00:00,75.88781183\n2013-12-29 16:00:00,75.34116597\n2013-12-29 17:00:00,74.87521094\n2013-12-29 18:00:00,76.97509822\n2013-12-29 19:00:00,76.83889695\n2013-12-29 20:00:00,76.92440774\n2013-12-29 21:00:00,77.32019076\n2013-12-29 22:00:00,77.67837913\n2013-12-29 23:00:00,76.02861347\n2013-12-30 00:00:00,75.57417604\n2013-12-30 01:00:00,75.79405442\n2013-12-30 02:00:00,76.64253253\n2013-12-30 03:00:00,76.35495023\n2013-12-30 04:00:00,76.05391238\n2013-12-30 05:00:00,75.76492651\n2013-12-30 06:00:00,75.53227413\n2013-12-30 07:00:00,75.96286731\n2013-12-30 08:00:00,76.43916795\n2013-12-30 09:00:00,75.79904062\n2013-12-30 10:00:00,75.53723344\n2013-12-30 11:00:00,74.76067835\n2013-12-30 12:00:00,74.8480328\n2013-12-30 13:00:00,76.23999342\n2013-12-30 14:00:00,75.11179225\n2013-12-30 15:00:00,74.94556814\n2013-12-30 16:00:00,75.55307362\n2013-12-30 17:00:00,76.83833799\n2013-12-30 18:00:00,75.59523206\n2013-12-30 19:00:00,76.31503423\n2013-12-30 20:00:00,77.53459374\n2013-12-30 21:00:00,76.0050383\n2013-12-30 22:00:00,77.68454433\n2013-12-30 23:00:00,77.72108111\n2013-12-31 00:00:00,77.51558001\n2013-12-31 01:00:00,78.44437589\n2013-12-31 02:00:00,77.97499028\n2013-12-31 03:00:00,76.46430922\n2013-12-31 04:00:00,77.99078395\n2013-12-31 05:00:00,76.65166801\n2013-12-31 06:00:00,76.38382148\n2013-12-31 07:00:00,77.98764166\n2013-12-31 08:00:00,76.02353562\n2013-12-31 09:00:00,76.85941302\n2013-12-31 10:00:00,77.02694156\n2013-12-31 11:00:00,77.4351667\n2013-12-31 12:00:00,75.742419\n2013-12-31 13:00:00,76.75512501\n2013-12-31 14:00:00,76.1618611\n2013-12-31 15:00:00,76.68101761\n2013-12-31 16:00:00,76.57323145\n2013-12-31 17:00:00,77.42705796\n2013-12-31 18:00:00,78.04219444\n2013-12-31 19:00:00,77.03500259\n2013-12-31 20:00:00,77.59435294\n2013-12-31 21:00:00,76.86767814\n2013-12-31 22:00:00,77.59032761\n2013-12-31 23:00:00,77.68816859\n2014-01-01 00:00:00,77.17536982\n2014-01-01 01:00:00,76.88160145\n2014-01-01 02:00:00,77.64735761\n2014-01-01 03:00:00,76.6094964\n2014-01-01 04:00:00,76.88619653\n2014-01-01 05:00:00,76.25204932\n2014-01-01 06:00:00,75.93757409\n2014-01-01 07:00:00,77.0866129\n2014-01-01 08:00:00,76.89226412\n2014-01-01 09:00:00,77.15228638\n2014-01-01 10:00:00,76.16837159999999\n2014-01-01 11:00:00,76.0309472\n2014-01-01 12:00:00,76.36542467\n2014-01-01 13:00:00,76.21666009999998\n2014-01-01 14:00:00,77.344746\n2014-01-01 15:00:00,77.17413937\n2014-01-01 16:00:00,77.7444573\n2014-01-01 17:00:00,77.80851622\n2014-01-01 18:00:00,76.95110006\n2014-01-01 19:00:00,77.37914862\n2014-01-01 20:00:00,77.64861189\n2014-01-01 21:00:00,77.57337175\n2014-01-01 22:00:00,77.64969323\n2014-01-01 23:00:00,77.28681311\n2014-01-02 00:00:00,77.62789588\n2014-01-02 01:00:00,76.37452465\n2014-01-02 02:00:00,76.89324349\n2014-01-02 03:00:00,75.84159632\n2014-01-02 04:00:00,76.54495496\n2014-01-02 05:00:00,75.54568718\n2014-01-02 06:00:00,75.61285500000002\n2014-01-02 07:00:00,75.77509947\n2014-01-02 08:00:00,76.86025712\n2014-01-02 09:00:00,76.75063266\n2014-01-02 10:00:00,76.65430247\n2014-01-02 11:00:00,76.07822982\n2014-01-02 12:00:00,75.64525857\n2014-01-02 13:00:00,75.6153839\n2014-01-02 14:00:00,75.63346999\n2014-01-02 15:00:00,75.45555433\n2014-01-02 16:00:00,75.36337466\n2014-01-02 17:00:00,76.62929369\n2014-01-02 18:00:00,76.02807317\n2014-01-02 19:00:00,76.95841456\n2014-01-02 20:00:00,77.16409297\n2014-01-02 21:00:00,77.50435808\n2014-01-02 22:00:00,76.45265121\n2014-01-02 23:00:00,76.48343837\n2014-01-03 00:00:00,75.53864608\n2014-01-03 01:00:00,75.63032548\n2014-01-03 02:00:00,75.41759869\n2014-01-03 03:00:00,75.98132744\n2014-01-03 04:00:00,73.93952186\n2014-01-03 05:00:00,74.72379503\n2014-01-03 06:00:00,74.41912965\n2014-01-03 07:00:00,73.57769606\n2014-01-03 08:00:00,73.39289962\n2014-01-03 09:00:00,73.40029958\n2014-01-03 10:00:00,73.15702733\n2014-01-03 11:00:00,73.14839463\n2014-01-03 12:00:00,73.56870109\n2014-01-03 13:00:00,74.24132001\n2014-01-03 14:00:00,73.74719451\n2014-01-03 15:00:00,75.18506859\n2014-01-03 16:00:00,75.62687166\n2014-01-03 17:00:00,75.05191762\n2014-01-03 18:00:00,75.03447509\n2014-01-03 19:00:00,76.67924387\n2014-01-03 20:00:00,75.85058042\n2014-01-03 21:00:00,76.26521877\n2014-01-03 22:00:00,76.40487485\n2014-01-03 23:00:00,76.20869095\n2014-01-04 00:00:00,75.78848542\n2014-01-04 01:00:00,75.78491462\n2014-01-04 02:00:00,74.35316083\n2014-01-04 03:00:00,73.2440553\n2014-01-04 04:00:00,74.52607513\n2014-01-04 05:00:00,72.70071992\n2014-01-04 06:00:00,72.55197957\n2014-01-04 07:00:00,72.76263888\n2014-01-04 08:00:00,74.03023695\n2014-01-04 09:00:00,72.1040175\n2014-01-04 10:00:00,72.46775852\n2014-01-04 11:00:00,72.42871912\n2014-01-04 12:00:00,72.52468151\n2014-01-04 13:00:00,73.11919307\n2014-01-04 14:00:00,72.88771617\n2014-01-04 15:00:00,73.79287601\n2014-01-04 16:00:00,72.8959554\n2014-01-04 17:00:00,73.45337227\n2014-01-04 18:00:00,74.06806234\n2014-01-04 19:00:00,75.77846693\n2014-01-04 20:00:00,75.23072963\n2014-01-04 21:00:00,75.61607375\n2014-01-04 22:00:00,74.98886104\n2014-01-04 23:00:00,75.7975775\n2014-01-05 00:00:00,74.59213146\n2014-01-05 01:00:00,74.133984\n2014-01-05 02:00:00,75.68401665\n2014-01-05 03:00:00,74.63891988\n2014-01-05 04:00:00,74.84522321\n2014-01-05 05:00:00,74.99541401\n2014-01-05 06:00:00,73.95833504\n2014-01-05 07:00:00,73.91074857\n2014-01-05 08:00:00,73.56416169\n2014-01-05 09:00:00,73.94257293\n2014-01-05 10:00:00,73.32290889\n2014-01-05 11:00:00,73.93627585\n2014-01-05 12:00:00,74.19905101\n2014-01-05 13:00:00,72.79990441\n2014-01-05 14:00:00,74.06666139\n2014-01-05 15:00:00,74.44944008\n2014-01-05 16:00:00,74.62982839\n2014-01-05 17:00:00,73.89403209\n2014-01-05 18:00:00,75.44283941\n2014-01-05 19:00:00,74.9532114\n2014-01-05 20:00:00,75.48287312\n2014-01-05 21:00:00,74.85663000000002\n2014-01-05 22:00:00,75.91564308\n2014-01-05 23:00:00,74.31605939\n2014-01-06 00:00:00,75.58963791\n2014-01-06 01:00:00,73.80836459\n2014-01-06 02:00:00,74.64795190000002\n2014-01-06 03:00:00,75.13418494\n2014-01-06 04:00:00,73.66916292\n2014-01-06 05:00:00,73.35199946\n2014-01-06 06:00:00,73.97781018\n2014-01-06 07:00:00,74.35526471\n2014-01-06 08:00:00,73.95431726\n2014-01-06 09:00:00,73.80845391\n2014-01-06 10:00:00,73.97871909\n2014-01-06 11:00:00,72.86942158\n2014-01-06 12:00:00,74.94885797\n2014-01-06 13:00:00,75.39944679999998\n2014-01-06 14:00:00,74.74238142\n2014-01-06 15:00:00,74.66350681\n2014-01-06 16:00:00,74.41156835\n2014-01-06 17:00:00,75.13358423\n2014-01-06 18:00:00,75.11834143\n2014-01-06 19:00:00,75.43622284\n2014-01-06 20:00:00,76.21395639\n2014-01-06 21:00:00,74.73751944\n2014-01-06 22:00:00,74.54551289\n2014-01-06 23:00:00,75.71630602\n2014-01-07 00:00:00,73.71800848\n2014-01-07 01:00:00,73.64882122\n2014-01-07 02:00:00,74.84681716\n2014-01-07 03:00:00,73.4509252\n2014-01-07 04:00:00,74.87858197\n2014-01-07 05:00:00,74.74808979\n2014-01-07 06:00:00,74.36531581\n2014-01-07 07:00:00,74.17844994\n2014-01-07 08:00:00,74.32707278\n2014-01-07 09:00:00,73.04205499\n2014-01-07 10:00:00,73.88036889\n2014-01-07 11:00:00,74.06747359999999\n2014-01-07 12:00:00,73.85181753\n2014-01-07 13:00:00,73.52105745\n2014-01-07 14:00:00,75.89900009\n2014-01-07 15:00:00,75.83602568\n2014-01-07 16:00:00,75.7488075\n2014-01-07 17:00:00,77.03472136\n2014-01-07 18:00:00,75.75358374\n2014-01-07 19:00:00,76.37330245\n2014-01-07 20:00:00,76.41021209\n2014-01-07 21:00:00,76.86214074\n2014-01-07 22:00:00,76.37969889\n2014-01-07 23:00:00,75.8606675\n2014-01-08 00:00:00,75.98763517\n2014-01-08 01:00:00,75.23598479\n2014-01-08 02:00:00,75.71067527\n2014-01-08 03:00:00,75.16753331\n2014-01-08 04:00:00,74.70772724\n2014-01-08 05:00:00,76.07797055\n2014-01-08 06:00:00,74.98527003\n2014-01-08 07:00:00,74.9606503\n2014-01-08 08:00:00,75.33628459999998\n2014-01-08 09:00:00,73.55344265\n2014-01-08 10:00:00,73.99107759\n2014-01-08 11:00:00,74.84672677\n2014-01-08 12:00:00,75.07497205\n2014-01-08 13:00:00,74.36771562\n2014-01-08 14:00:00,75.74259037\n2014-01-08 15:00:00,74.87882442\n2014-01-08 16:00:00,76.24095087\n2014-01-08 17:00:00,75.95860682\n2014-01-08 18:00:00,76.37186909\n2014-01-08 19:00:00,75.9443031\n2014-01-08 20:00:00,75.11146533\n2014-01-08 21:00:00,75.15274793\n2014-01-08 22:00:00,75.06549983\n2014-01-08 23:00:00,74.69714713\n2014-01-09 00:00:00,76.19664042\n2014-01-09 01:00:00,74.10948331\n2014-01-09 02:00:00,74.63482711\n2014-01-09 03:00:00,73.51138733\n2014-01-09 04:00:00,73.12606794\n2014-01-09 05:00:00,74.01271456\n2014-01-09 06:00:00,73.86542453\n2014-01-09 07:00:00,73.89712719\n2014-01-09 08:00:00,74.03537465\n2014-01-09 09:00:00,73.72201999\n2014-01-09 10:00:00,72.66948077\n2014-01-09 11:00:00,72.50391252\n2014-01-09 12:00:00,73.95811461\n2014-01-09 13:00:00,74.01521745\n2014-01-09 14:00:00,74.01596603\n2014-01-09 15:00:00,75.4479466\n2014-01-09 16:00:00,76.13073887\n2014-01-09 17:00:00,75.25463596\n2014-01-09 18:00:00,75.93286118\n2014-01-09 19:00:00,75.59193841\n2014-01-09 20:00:00,76.30709504\n2014-01-09 21:00:00,77.18425747\n2014-01-09 22:00:00,75.64246944\n2014-01-09 23:00:00,76.37537373\n2014-01-10 00:00:00,74.68720578\n2014-01-10 01:00:00,75.18990319\n2014-01-10 02:00:00,75.849666\n2014-01-10 03:00:00,75.14636897\n2014-01-10 04:00:00,73.90081676\n2014-01-10 05:00:00,74.73933733\n2014-01-10 06:00:00,73.74171083\n2014-01-10 07:00:00,74.46143239\n2014-01-10 08:00:00,73.4840964\n2014-01-10 09:00:00,73.03863545\n2014-01-10 10:00:00,74.07519737\n2014-01-10 11:00:00,72.93006063\n2014-01-10 12:00:00,73.18888994\n2014-01-10 13:00:00,73.95558633\n2014-01-10 14:00:00,75.22775409\n2014-01-10 15:00:00,75.05332699\n2014-01-10 16:00:00,75.36510048\n2014-01-10 17:00:00,76.11231412\n2014-01-10 18:00:00,75.58706498\n2014-01-10 19:00:00,76.06972961\n2014-01-10 20:00:00,75.32744105\n2014-01-10 21:00:00,76.06533695\n2014-01-10 22:00:00,75.66969997\n2014-01-10 23:00:00,76.2727697\n2014-01-11 00:00:00,75.50606319\n2014-01-11 01:00:00,75.37971925\n2014-01-11 02:00:00,74.86435121\n2014-01-11 03:00:00,75.92346681\n2014-01-11 04:00:00,75.81348126\n2014-01-11 05:00:00,75.53701836\n2014-01-11 06:00:00,74.23671001\n2014-01-11 07:00:00,75.16424971\n2014-01-11 08:00:00,74.30239478\n2014-01-11 09:00:00,74.59790374\n2014-01-11 10:00:00,73.58871356\n2014-01-11 11:00:00,73.01315859\n2014-01-11 12:00:00,72.58458265\n2014-01-11 13:00:00,73.95143473\n2014-01-11 14:00:00,73.97461465\n2014-01-11 15:00:00,74.56884896\n2014-01-11 16:00:00,75.03613111\n2014-01-11 17:00:00,75.56055848\n2014-01-11 18:00:00,75.62240148\n2014-01-11 19:00:00,77.67158003\n2014-01-11 20:00:00,77.56623639\n2014-01-11 21:00:00,77.61657097\n2014-01-11 22:00:00,77.69091215\n2014-01-11 23:00:00,77.65642064\n2014-01-12 00:00:00,76.58082694\n2014-01-12 01:00:00,76.82821008\n2014-01-12 02:00:00,77.44683206\n2014-01-12 03:00:00,77.63174648\n2014-01-12 04:00:00,76.76049719\n2014-01-12 05:00:00,76.10329035\n2014-01-12 06:00:00,75.93474711\n2014-01-12 07:00:00,76.39983542\n2014-01-12 08:00:00,75.07645543\n2014-01-12 09:00:00,76.25156678\n2014-01-12 10:00:00,75.59060727\n2014-01-12 11:00:00,75.83963106\n2014-01-12 12:00:00,75.22056579999997\n2014-01-12 13:00:00,74.85866283\n2014-01-12 14:00:00,75.53354519\n2014-01-12 15:00:00,75.71749619\n2014-01-12 16:00:00,77.69659197\n2014-01-12 17:00:00,78.08214012\n2014-01-12 18:00:00,78.95522712\n2014-01-12 19:00:00,79.64623758\n2014-01-12 20:00:00,81.37618811\n2014-01-12 21:00:00,80.96947535\n2014-01-12 22:00:00,80.30864114\n2014-01-12 23:00:00,80.18657579\n2014-01-13 00:00:00,78.47491514\n2014-01-13 01:00:00,78.96162765\n2014-01-13 02:00:00,79.1300713\n2014-01-13 03:00:00,78.39635208\n2014-01-13 04:00:00,79.85480600000002\n2014-01-13 05:00:00,77.98583629\n2014-01-13 06:00:00,78.35432954\n2014-01-13 07:00:00,78.66812563\n2014-01-13 08:00:00,79.03360146\n2014-01-13 09:00:00,77.31328955\n2014-01-13 10:00:00,77.73451371\n2014-01-13 11:00:00,77.69436304\n2014-01-13 12:00:00,77.79754628\n2014-01-13 13:00:00,77.22909454\n2014-01-13 14:00:00,78.35433755\n2014-01-13 15:00:00,78.03170789\n2014-01-13 16:00:00,76.63660126\n2014-01-13 17:00:00,76.57220626\n2014-01-13 18:00:00,77.76546817\n2014-01-13 19:00:00,77.38246298\n2014-01-13 20:00:00,76.69839827\n2014-01-13 21:00:00,76.3966038\n2014-01-13 22:00:00,78.2430965\n2014-01-13 23:00:00,77.18014447\n2014-01-14 00:00:00,76.98731733\n2014-01-14 01:00:00,76.802564\n2014-01-14 02:00:00,78.04845667\n2014-01-14 03:00:00,78.30808931\n2014-01-14 04:00:00,78.56024461\n2014-01-14 05:00:00,78.00986597\n2014-01-14 06:00:00,77.74735738\n2014-01-14 07:00:00,76.56851354\n2014-01-14 08:00:00,76.57631974\n2014-01-14 09:00:00,76.29506325\n2014-01-14 10:00:00,76.91856774\n2014-01-14 11:00:00,77.35300179999999\n2014-01-14 12:00:00,76.69395845\n2014-01-14 13:00:00,76.79314078\n2014-01-14 14:00:00,76.78184988\n2014-01-14 15:00:00,76.58378687\n2014-01-14 16:00:00,75.29365403\n2014-01-14 17:00:00,77.08526779\n2014-01-14 18:00:00,77.16331386\n2014-01-14 19:00:00,76.08578513\n2014-01-14 20:00:00,76.26928873\n2014-01-14 21:00:00,76.76325951\n2014-01-14 22:00:00,75.47553688\n2014-01-14 23:00:00,75.0534243\n2014-01-15 00:00:00,75.69341909\n2014-01-15 01:00:00,74.84655904\n2014-01-15 02:00:00,74.60828148\n2014-01-15 03:00:00,75.23334924\n2014-01-15 04:00:00,74.76757914\n2014-01-15 05:00:00,74.32699919\n2014-01-15 06:00:00,72.97529237\n2014-01-15 07:00:00,73.30416843\n2014-01-15 08:00:00,73.38232286\n2014-01-15 09:00:00,74.58791578\n2014-01-15 10:00:00,72.9067279\n2014-01-15 11:00:00,74.15335692\n2014-01-15 12:00:00,74.15977548\n2014-01-15 13:00:00,75.48000267\n2014-01-15 14:00:00,74.94602944\n2014-01-15 15:00:00,74.36597865\n2014-01-15 16:00:00,75.40107507\n2014-01-15 17:00:00,76.43324294\n2014-01-15 18:00:00,76.76879953\n2014-01-15 19:00:00,75.42099851\n2014-01-15 20:00:00,75.04376408\n2014-01-15 21:00:00,75.14537633\n2014-01-15 22:00:00,75.26255156\n2014-01-15 23:00:00,75.35976422\n2014-01-16 00:00:00,75.45234139\n2014-01-16 01:00:00,73.94180609\n2014-01-16 02:00:00,75.00647379\n2014-01-16 03:00:00,74.33106778\n2014-01-16 04:00:00,74.87396446\n2014-01-16 05:00:00,73.3379579\n2014-01-16 06:00:00,72.80256039\n2014-01-16 07:00:00,73.66597073\n2014-01-16 08:00:00,73.87172516\n2014-01-16 09:00:00,73.27324959\n2014-01-16 10:00:00,72.72014324\n2014-01-16 11:00:00,74.17992104\n2014-01-16 12:00:00,74.15880306\n2014-01-16 13:00:00,75.59329179999997\n2014-01-16 14:00:00,75.41968933\n2014-01-16 15:00:00,74.53134496\n2014-01-16 16:00:00,74.44982256\n2014-01-16 17:00:00,75.434016\n2014-01-16 18:00:00,75.62950104\n2014-01-16 19:00:00,75.34933235\n2014-01-16 20:00:00,75.201389\n2014-01-16 21:00:00,75.40868152\n2014-01-16 22:00:00,75.11984946\n2014-01-16 23:00:00,74.38931293\n2014-01-17 00:00:00,74.69809723\n2014-01-17 01:00:00,75.18846342\n2014-01-17 02:00:00,74.45343886\n2014-01-17 03:00:00,74.67691315\n2014-01-17 04:00:00,73.41217429\n2014-01-17 05:00:00,72.83454005\n2014-01-17 06:00:00,73.5939262\n2014-01-17 07:00:00,72.76406621\n2014-01-17 08:00:00,72.68778157\n2014-01-17 09:00:00,73.37875182\n2014-01-17 10:00:00,72.06183623\n2014-01-17 11:00:00,72.86400869\n2014-01-17 12:00:00,74.31198445\n2014-01-17 13:00:00,73.92421104\n2014-01-17 14:00:00,73.6834725\n2014-01-17 15:00:00,73.71034271\n2014-01-17 16:00:00,73.515123\n2014-01-17 17:00:00,74.65384045\n2014-01-17 18:00:00,74.59773769\n2014-01-17 19:00:00,74.96277198\n2014-01-17 20:00:00,74.62437982\n2014-01-17 21:00:00,73.58807814\n2014-01-17 22:00:00,74.27463197\n2014-01-17 23:00:00,73.46593712\n2014-01-18 00:00:00,73.37697331\n2014-01-18 01:00:00,74.28679774\n2014-01-18 02:00:00,74.60507656\n2014-01-18 03:00:00,73.56215036\n2014-01-18 04:00:00,74.11232577\n2014-01-18 05:00:00,73.97053959\n2014-01-18 06:00:00,72.77785049\n2014-01-18 07:00:00,72.57867332\n2014-01-18 08:00:00,73.50341351\n2014-01-18 09:00:00,73.17997554\n2014-01-18 10:00:00,73.07969608\n2014-01-18 11:00:00,72.86778282\n2014-01-18 12:00:00,72.97978227\n2014-01-18 13:00:00,72.06864306\n2014-01-18 14:00:00,73.46915696\n2014-01-18 15:00:00,72.73501198\n2014-01-18 16:00:00,73.06122541\n2014-01-18 17:00:00,73.9831845\n2014-01-18 18:00:00,74.44162889\n2014-01-18 19:00:00,74.04541228\n2014-01-18 20:00:00,74.99423532\n2014-01-18 21:00:00,76.25032982\n2014-01-18 22:00:00,75.29434003\n2014-01-18 23:00:00,74.45046834\n2014-01-19 00:00:00,75.03906858\n2014-01-19 01:00:00,75.11973678\n2014-01-19 02:00:00,73.60403299\n2014-01-19 03:00:00,73.44321638\n2014-01-19 04:00:00,73.43418914\n2014-01-19 05:00:00,73.23859587\n2014-01-19 06:00:00,73.7150373\n2014-01-19 07:00:00,73.89335646\n2014-01-19 08:00:00,73.87424506\n2014-01-19 09:00:00,72.96073809\n2014-01-19 10:00:00,72.61113449999998\n2014-01-19 11:00:00,71.38831163\n2014-01-19 12:00:00,72.09667227\n2014-01-19 13:00:00,72.43175322\n2014-01-19 14:00:00,73.43453663\n2014-01-19 15:00:00,71.85172628\n2014-01-19 16:00:00,73.33181218\n2014-01-19 17:00:00,73.98179005\n2014-01-19 18:00:00,75.60339242\n2014-01-19 19:00:00,74.84669634\n2014-01-19 20:00:00,75.66432669\n2014-01-19 21:00:00,75.41398766\n2014-01-19 22:00:00,75.62691835\n2014-01-19 23:00:00,76.12839652\n2014-01-20 00:00:00,75.24374402\n2014-01-20 01:00:00,74.25000295\n2014-01-20 02:00:00,74.76520353\n2014-01-20 03:00:00,74.88412726\n2014-01-20 04:00:00,74.70121296\n2014-01-20 05:00:00,73.93681762\n2014-01-20 06:00:00,74.25651103\n2014-01-20 07:00:00,73.57337828\n2014-01-20 08:00:00,72.94924405\n2014-01-20 09:00:00,73.73581362\n2014-01-20 10:00:00,73.57616849\n2014-01-20 11:00:00,73.09497078\n2014-01-20 12:00:00,74.97348441\n2014-01-20 13:00:00,74.48410538\n2014-01-20 14:00:00,74.37005879\n2014-01-20 15:00:00,74.89437525\n2014-01-20 16:00:00,75.36858942\n2014-01-20 17:00:00,75.51543606\n2014-01-20 18:00:00,75.93149966\n2014-01-20 19:00:00,76.80408083\n2014-01-20 20:00:00,76.08022555\n2014-01-20 21:00:00,74.81338988\n2014-01-20 22:00:00,75.92940133\n2014-01-20 23:00:00,75.50636120000001\n2014-01-21 00:00:00,74.14574816\n2014-01-21 01:00:00,74.86999088\n2014-01-21 02:00:00,75.32625215\n2014-01-21 03:00:00,73.74854939\n2014-01-21 04:00:00,74.07036021\n2014-01-21 05:00:00,74.04524108\n2014-01-21 06:00:00,74.05595233\n2014-01-21 07:00:00,74.2393244\n2014-01-21 08:00:00,73.90532239\n2014-01-21 09:00:00,73.53187021\n2014-01-21 10:00:00,73.96226531\n2014-01-21 11:00:00,73.20525326\n2014-01-21 12:00:00,74.60467618\n2014-01-21 13:00:00,74.24149076\n2014-01-21 14:00:00,75.28123022\n2014-01-21 15:00:00,74.40222479\n2014-01-21 16:00:00,74.19210633\n2014-01-21 17:00:00,75.87886303\n2014-01-21 18:00:00,75.23863029\n2014-01-21 19:00:00,74.96873237\n2014-01-21 20:00:00,76.10793148\n2014-01-21 21:00:00,75.36131634\n2014-01-21 22:00:00,75.90263465\n2014-01-21 23:00:00,75.50472037\n2014-01-22 00:00:00,74.28022956\n2014-01-22 01:00:00,72.97203667\n2014-01-22 02:00:00,72.67511800000003\n2014-01-22 03:00:00,73.47639463\n2014-01-22 04:00:00,73.39614473\n2014-01-22 05:00:00,72.10091024\n2014-01-22 06:00:00,71.8777649\n2014-01-22 07:00:00,72.55737568\n2014-01-22 08:00:00,72.98505223\n2014-01-22 09:00:00,73.73262672\n2014-01-22 10:00:00,72.69930722\n2014-01-22 11:00:00,73.01882828\n2014-01-22 12:00:00,72.80921712\n2014-01-22 13:00:00,73.65716599\n2014-01-22 14:00:00,74.68008894\n2014-01-22 15:00:00,74.65383035\n2014-01-22 16:00:00,73.90375633\n2014-01-22 17:00:00,74.95962081\n2014-01-22 18:00:00,74.72151271\n2014-01-22 19:00:00,76.1127814\n2014-01-22 20:00:00,76.27976034\n2014-01-22 21:00:00,75.43044158\n2014-01-22 22:00:00,74.81221712\n2014-01-22 23:00:00,75.29112173\n2014-01-23 00:00:00,74.11805047\n2014-01-23 01:00:00,73.08506057\n2014-01-23 02:00:00,73.71635914\n2014-01-23 03:00:00,72.75477351\n2014-01-23 04:00:00,73.06979399999999\n2014-01-23 05:00:00,73.43277483\n2014-01-23 06:00:00,72.12848145\n2014-01-23 07:00:00,72.30633866\n2014-01-23 08:00:00,72.55350882\n2014-01-23 09:00:00,72.43365278\n2014-01-23 10:00:00,72.16028829999998\n2014-01-23 11:00:00,71.87997676\n2014-01-23 12:00:00,72.30469043\n2014-01-23 13:00:00,72.90140272\n2014-01-23 14:00:00,73.52178365\n2014-01-23 15:00:00,74.33549357\n2014-01-23 16:00:00,75.39468245\n2014-01-23 17:00:00,74.07597525\n2014-01-23 18:00:00,75.35896953\n2014-01-23 19:00:00,76.20885954\n2014-01-23 20:00:00,75.47638239\n2014-01-23 21:00:00,74.560063\n2014-01-23 22:00:00,74.52753611\n2014-01-23 23:00:00,73.71689559999999\n2014-01-24 00:00:00,73.90866358\n2014-01-24 01:00:00,74.09748437\n2014-01-24 02:00:00,73.87374575\n2014-01-24 03:00:00,73.74883976\n2014-01-24 04:00:00,72.9320447\n2014-01-24 05:00:00,73.49330934\n2014-01-24 06:00:00,73.66155176\n2014-01-24 07:00:00,73.62855627\n2014-01-24 08:00:00,73.16522286\n2014-01-24 09:00:00,72.7479508\n2014-01-24 10:00:00,73.56592026\n2014-01-24 11:00:00,71.75263157\n2014-01-24 12:00:00,73.18039611\n2014-01-24 13:00:00,73.92384\n2014-01-24 14:00:00,73.80439905\n2014-01-24 15:00:00,73.73073979\n2014-01-24 16:00:00,73.80911621\n2014-01-24 17:00:00,73.53212237\n2014-01-24 18:00:00,75.18577049\n2014-01-24 19:00:00,75.01261659\n2014-01-24 20:00:00,75.04608932\n2014-01-24 21:00:00,73.33607329\n2014-01-24 22:00:00,73.1043253\n2014-01-24 23:00:00,74.10360046\n2014-01-25 00:00:00,73.78519774\n2014-01-25 01:00:00,71.71663594\n2014-01-25 02:00:00,72.13397159\n2014-01-25 03:00:00,71.51253422\n2014-01-25 04:00:00,72.46607477\n2014-01-25 05:00:00,70.94402108\n2014-01-25 06:00:00,72.61890668\n2014-01-25 07:00:00,70.73076574\n2014-01-25 08:00:00,72.48740311\n2014-01-25 09:00:00,70.83079397\n2014-01-25 10:00:00,71.04843529\n2014-01-25 11:00:00,70.71591042\n2014-01-25 12:00:00,70.79152507\n2014-01-25 13:00:00,70.65705161\n2014-01-25 14:00:00,71.61997893\n2014-01-25 15:00:00,71.01293809\n2014-01-25 16:00:00,71.73672317\n2014-01-25 17:00:00,72.73172553\n2014-01-25 18:00:00,71.46886416\n2014-01-25 19:00:00,71.86085423\n2014-01-25 20:00:00,73.11208905\n2014-01-25 21:00:00,72.20025328\n2014-01-25 22:00:00,72.23507842\n2014-01-25 23:00:00,72.0287567\n2014-01-26 00:00:00,71.82552414\n2014-01-26 01:00:00,72.33922968\n2014-01-26 02:00:00,71.85635252\n2014-01-26 03:00:00,70.5453744\n2014-01-26 04:00:00,70.37989579\n2014-01-26 05:00:00,70.37604173\n2014-01-26 06:00:00,70.77914323\n2014-01-26 07:00:00,70.19317971\n2014-01-26 08:00:00,70.24674398\n2014-01-26 09:00:00,71.35010374\n2014-01-26 10:00:00,69.99332028\n2014-01-26 11:00:00,71.14020035\n2014-01-26 12:00:00,69.67929351\n2014-01-26 13:00:00,69.35287097\n2014-01-26 14:00:00,70.07391138\n2014-01-26 15:00:00,70.16723295\n2014-01-26 16:00:00,70.29923518\n2014-01-26 17:00:00,70.53565511\n2014-01-26 18:00:00,71.79430755\n2014-01-26 19:00:00,71.82889986\n2014-01-26 20:00:00,72.54095975\n2014-01-26 21:00:00,71.58480523\n2014-01-26 22:00:00,73.13032124\n2014-01-26 23:00:00,72.19137711\n2014-01-27 00:00:00,72.69299224\n2014-01-27 01:00:00,72.52594748\n2014-01-27 02:00:00,72.1202739\n2014-01-27 03:00:00,71.63100933\n2014-01-27 04:00:00,72.32810907\n2014-01-27 05:00:00,71.35093709\n2014-01-27 06:00:00,72.35543488\n2014-01-27 07:00:00,72.9372165\n2014-01-27 08:00:00,71.70966262\n2014-01-27 09:00:00,72.032484\n2014-01-27 10:00:00,72.49053701\n2014-01-27 11:00:00,71.89054985\n2014-01-27 12:00:00,71.26701803\n2014-01-27 13:00:00,74.46663598\n2014-01-27 14:00:00,72.22220945\n2014-01-27 15:00:00,73.72378953\n2014-01-27 16:00:00,73.22172217\n2014-01-27 17:00:00,73.98717586\n2014-01-27 18:00:00,73.03814208\n2014-01-27 19:00:00,73.32673418\n2014-01-27 20:00:00,74.66952758\n2014-01-27 21:00:00,74.79814747\n2014-01-27 22:00:00,73.00862053\n2014-01-27 23:00:00,72.03939489\n2014-01-28 00:00:00,72.84926503\n2014-01-28 01:00:00,72.21653075\n2014-01-28 02:00:00,72.82207234\n2014-01-28 03:00:00,72.13937972\n2014-01-28 04:00:00,71.41855654\n2014-01-28 05:00:00,72.13106037\n2014-01-28 06:00:00,70.30742259\n2014-01-28 07:00:00,71.29753092\n2014-01-28 08:00:00,70.73465105\n2014-01-28 09:00:00,70.97773483\n2014-01-28 10:00:00,71.29569485\n2014-01-28 11:00:00,70.86865163\n2014-01-28 12:00:00,71.13147563\n2014-01-28 13:00:00,71.26149539\n2014-01-28 14:00:00,71.94856019\n2014-01-28 15:00:00,73.39954311\n2014-01-28 16:00:00,72.71250801\n2014-01-28 17:00:00,72.77672232\n2014-01-28 18:00:00,72.35599271\n2014-01-28 19:00:00,73.15618385\n2014-01-28 20:00:00,73.63572063\n2014-01-28 21:00:00,72.21822025\n2014-01-28 22:00:00,73.09245779\n2014-01-28 23:00:00,72.11831496\n2014-01-29 00:00:00,71.42071144\n2014-01-29 01:00:00,70.56138073\n2014-01-29 02:00:00,71.67378573\n2014-01-29 03:00:00,70.69482748\n2014-01-29 04:00:00,71.05763613\n2014-01-29 05:00:00,69.64124933\n2014-01-29 06:00:00,69.98065226\n2014-01-29 07:00:00,69.64774646\n2014-01-29 08:00:00,68.90916513\n2014-01-29 09:00:00,68.87238795\n2014-01-29 10:00:00,69.78818855\n2014-01-29 11:00:00,71.12277947\n2014-01-29 12:00:00,69.26547487\n2014-01-29 13:00:00,69.4026087\n2014-01-29 14:00:00,70.83920046\n2014-01-29 15:00:00,69.3426551\n2014-01-29 16:00:00,70.48650218\n2014-01-29 17:00:00,71.05859214\n2014-01-29 18:00:00,72.61395853\n2014-01-29 19:00:00,72.86434604\n2014-01-29 20:00:00,72.37767629\n2014-01-29 21:00:00,71.96930019\n2014-01-29 22:00:00,70.34552908\n2014-01-29 23:00:00,70.14337141\n2014-01-30 00:00:00,69.65669593\n2014-01-30 01:00:00,70.78838358\n2014-01-30 02:00:00,69.51059999\n2014-01-30 03:00:00,70.31048879\n2014-01-30 04:00:00,68.33312277\n2014-01-30 05:00:00,69.11285507\n2014-01-30 06:00:00,68.36206502\n2014-01-30 07:00:00,70.00255638\n2014-01-30 08:00:00,69.84002555\n2014-01-30 09:00:00,70.8745921\n2014-01-30 10:00:00,69.71342166\n2014-01-30 11:00:00,70.57222326\n2014-01-30 12:00:00,71.52531104\n2014-01-30 13:00:00,72.153684\n2014-01-30 14:00:00,71.81595951\n2014-01-30 15:00:00,72.36544447\n2014-01-30 16:00:00,72.4569589\n2014-01-30 17:00:00,74.33983452\n2014-01-30 18:00:00,72.53925557\n2014-01-30 19:00:00,73.62854553\n2014-01-30 20:00:00,74.16754767\n2014-01-30 21:00:00,72.13192721\n2014-01-30 22:00:00,72.59170057\n2014-01-30 23:00:00,73.23535767\n2014-01-31 00:00:00,71.19719727\n2014-01-31 01:00:00,72.61891747\n2014-01-31 02:00:00,70.88976393\n2014-01-31 03:00:00,71.45727319\n2014-01-31 04:00:00,70.03927892\n2014-01-31 05:00:00,71.28071130000002\n2014-01-31 06:00:00,70.26626228\n2014-01-31 07:00:00,70.99283914\n2014-01-31 08:00:00,72.32981714\n2014-01-31 09:00:00,73.11036920000002\n2014-01-31 10:00:00,71.65932377\n2014-01-31 11:00:00,71.69114293\n2014-01-31 12:00:00,73.06636241\n2014-01-31 13:00:00,72.80727072\n2014-01-31 14:00:00,73.03538763\n2014-01-31 15:00:00,74.79646198\n2014-01-31 16:00:00,74.73596869\n2014-01-31 17:00:00,74.52413086\n2014-01-31 18:00:00,75.13725636\n2014-01-31 19:00:00,75.51339861\n2014-01-31 20:00:00,74.97912619\n2014-01-31 21:00:00,75.16085571\n2014-01-31 22:00:00,73.94071425\n2014-01-31 23:00:00,74.6188033\n2014-02-01 00:00:00,74.59156686\n2014-02-01 01:00:00,73.28286835\n2014-02-01 02:00:00,74.00350054\n2014-02-01 03:00:00,72.69543879\n2014-02-01 04:00:00,71.81722439\n2014-02-01 05:00:00,71.22178031\n2014-02-01 06:00:00,70.71015231\n2014-02-01 07:00:00,71.85774564\n2014-02-01 08:00:00,72.71240816\n2014-02-01 09:00:00,70.8336897\n2014-02-01 10:00:00,70.79616568\n2014-02-01 11:00:00,71.21849014\n2014-02-01 12:00:00,70.71605474\n2014-02-01 13:00:00,70.86097936\n2014-02-01 14:00:00,70.84299733\n2014-02-01 15:00:00,71.92974532\n2014-02-01 16:00:00,71.79294961\n2014-02-01 17:00:00,71.10245254\n2014-02-01 18:00:00,71.47578673\n2014-02-01 19:00:00,73.06019458\n2014-02-01 20:00:00,71.57960823\n2014-02-01 21:00:00,72.00120605\n2014-02-01 22:00:00,71.53750218\n2014-02-01 23:00:00,71.07065184\n2014-02-02 00:00:00,70.44906285\n2014-02-02 01:00:00,71.26135473\n2014-02-02 02:00:00,71.33996454\n2014-02-02 03:00:00,71.30097322\n2014-02-02 04:00:00,69.9892031\n2014-02-02 05:00:00,70.48431814\n2014-02-02 06:00:00,70.00301726\n2014-02-02 07:00:00,70.80399895\n2014-02-02 08:00:00,69.16903154\n2014-02-02 09:00:00,70.23674187\n2014-02-02 10:00:00,70.13354079\n2014-02-02 11:00:00,70.15141027\n2014-02-02 12:00:00,69.00452108\n2014-02-02 13:00:00,69.71760276\n2014-02-02 14:00:00,70.12305221\n2014-02-02 15:00:00,69.76208503\n2014-02-02 16:00:00,69.90676189\n2014-02-02 17:00:00,70.43625119\n2014-02-02 18:00:00,71.23295217\n2014-02-02 19:00:00,71.99986698\n2014-02-02 20:00:00,72.88904636\n2014-02-02 21:00:00,72.65424564\n2014-02-02 22:00:00,71.64446397\n2014-02-02 23:00:00,72.49652262\n2014-02-03 00:00:00,72.19594917\n2014-02-03 01:00:00,71.27499667\n2014-02-03 02:00:00,71.54927665\n2014-02-03 03:00:00,71.37741336\n2014-02-03 04:00:00,70.96126394\n2014-02-03 05:00:00,70.86526769\n2014-02-03 06:00:00,69.51742692\n2014-02-03 07:00:00,70.23699729\n2014-02-03 08:00:00,70.25478592\n2014-02-03 09:00:00,69.54660274\n2014-02-03 10:00:00,71.28535022\n2014-02-03 11:00:00,71.76620383\n2014-02-03 12:00:00,73.1581291\n2014-02-03 13:00:00,72.81950243\n2014-02-03 14:00:00,73.94357122\n2014-02-03 15:00:00,73.31051239\n2014-02-03 16:00:00,75.01779737\n2014-02-03 17:00:00,73.79603192\n2014-02-03 18:00:00,74.03478298\n2014-02-03 19:00:00,74.89001392\n2014-02-03 20:00:00,74.20342727\n2014-02-03 21:00:00,75.47335894\n2014-02-03 22:00:00,74.35480145\n2014-02-03 23:00:00,73.90516246\n2014-02-04 00:00:00,74.27115536\n2014-02-04 01:00:00,72.83977840000001\n2014-02-04 02:00:00,72.75240643\n2014-02-04 03:00:00,72.32492459999997\n2014-02-04 04:00:00,73.52854801\n2014-02-04 05:00:00,72.4911934\n2014-02-04 06:00:00,72.27198579\n2014-02-04 07:00:00,71.4871934\n2014-02-04 08:00:00,72.12293771\n2014-02-04 09:00:00,72.29360612\n2014-02-04 10:00:00,72.86539996\n2014-02-04 11:00:00,71.36774996\n2014-02-04 12:00:00,73.26391824\n2014-02-04 13:00:00,73.68072512\n2014-02-04 14:00:00,72.61150204\n2014-02-04 15:00:00,73.07639687\n2014-02-04 16:00:00,74.24530254\n2014-02-04 17:00:00,74.49700643\n2014-02-04 18:00:00,75.69456912\n2014-02-04 19:00:00,74.47440675\n2014-02-04 20:00:00,74.34991774\n2014-02-04 21:00:00,73.98990175\n2014-02-04 22:00:00,73.49337021\n2014-02-04 23:00:00,74.69248458\n2014-02-05 00:00:00,72.92171344\n2014-02-05 01:00:00,73.9381704\n2014-02-05 02:00:00,73.26932063\n2014-02-05 03:00:00,72.89486303\n2014-02-05 04:00:00,71.82789886\n2014-02-05 05:00:00,71.50326635\n2014-02-05 06:00:00,72.43797863\n2014-02-05 07:00:00,71.49212101\n2014-02-05 08:00:00,71.97523749\n2014-02-05 09:00:00,72.25395073\n2014-02-05 10:00:00,72.56517449\n2014-02-05 11:00:00,71.83775883\n2014-02-05 12:00:00,73.44242506\n2014-02-05 13:00:00,74.27947284\n2014-02-05 14:00:00,72.99596329\n2014-02-05 15:00:00,74.10552743\n2014-02-05 16:00:00,73.61788608\n2014-02-05 17:00:00,73.31701516\n2014-02-05 18:00:00,73.01174645\n2014-02-05 19:00:00,74.31390131\n2014-02-05 20:00:00,73.22819982\n2014-02-05 21:00:00,73.72890646\n2014-02-05 22:00:00,72.94723977\n2014-02-05 23:00:00,73.8378393\n2014-02-06 00:00:00,72.12373833\n2014-02-06 01:00:00,72.04284098\n2014-02-06 02:00:00,72.25186859\n2014-02-06 03:00:00,73.09282493\n2014-02-06 04:00:00,71.36865067\n2014-02-06 05:00:00,71.49960342\n2014-02-06 06:00:00,70.32354612\n2014-02-06 07:00:00,70.39520632\n2014-02-06 08:00:00,71.16626768\n2014-02-06 09:00:00,70.02861579\n2014-02-06 10:00:00,71.96241743\n2014-02-06 11:00:00,72.38074162\n2014-02-06 12:00:00,71.76366871\n2014-02-06 13:00:00,71.43442294\n2014-02-06 14:00:00,72.96389766\n2014-02-06 15:00:00,72.40563890000001\n2014-02-06 16:00:00,73.24319119\n2014-02-06 17:00:00,74.49209885\n2014-02-06 18:00:00,75.67593984\n2014-02-06 19:00:00,76.29491541\n2014-02-06 20:00:00,74.47855616\n2014-02-06 21:00:00,73.97881601\n2014-02-06 22:00:00,74.2503925\n2014-02-06 23:00:00,73.65281821\n2014-02-07 00:00:00,73.5566298\n2014-02-07 01:00:00,74.55125277\n2014-02-07 02:00:00,73.17815807\n2014-02-07 03:00:00,73.99622426\n2014-02-07 04:00:00,72.16705646\n2014-02-07 05:00:00,72.45023357\n2014-02-07 06:00:00,73.06302806\n2014-02-07 07:00:00,72.0095\n2014-02-07 08:00:00,71.80741665\n2014-02-07 09:00:00,71.04467432\n2014-02-07 10:00:00,71.97005629\n2014-02-07 11:00:00,72.90941163\n2014-02-07 12:00:00,72.17063774\n2014-02-07 13:00:00,73.06947938\n2014-02-07 14:00:00,73.0341092\n2014-02-07 15:00:00,73.80953945\n2014-02-07 16:00:00,74.31038278\n2014-02-07 17:00:00,73.68024234\n2014-02-07 18:00:00,74.41363078\n2014-02-07 19:00:00,74.41119626\n2014-02-07 20:00:00,75.30582101\n2014-02-07 21:00:00,73.72231831\n2014-02-07 22:00:00,73.956886\n2014-02-07 23:00:00,74.57015739\n2014-02-08 00:00:00,74.38656607\n2014-02-08 01:00:00,73.40422925\n2014-02-08 02:00:00,74.70798308\n2014-02-08 03:00:00,74.45851269\n2014-02-08 04:00:00,73.61811087\n2014-02-08 05:00:00,72.61189448\n2014-02-08 06:00:00,72.51799386\n2014-02-08 07:00:00,72.23863682\n2014-02-08 08:00:00,72.24960786\n2014-02-08 09:00:00,72.36965218\n2014-02-08 10:00:00,73.01194094\n2014-02-08 11:00:00,71.62813647\n2014-02-08 12:00:00,73.08187593\n2014-02-08 13:00:00,72.56747177\n2014-02-08 14:00:00,72.40514197\n2014-02-08 15:00:00,71.49508201\n2014-02-08 16:00:00,72.94715866\n2014-02-08 17:00:00,72.921265\n2014-02-08 18:00:00,73.01400553\n2014-02-08 19:00:00,72.79306485\n2014-02-08 20:00:00,72.85442183\n2014-02-08 21:00:00,71.65525912\n2014-02-08 22:00:00,72.67823919\n2014-02-08 23:00:00,71.24393979999998\n2014-02-09 00:00:00,72.55938056\n2014-02-09 01:00:00,72.05872252\n2014-02-09 02:00:00,70.76837988\n2014-02-09 03:00:00,72.2572247\n2014-02-09 04:00:00,70.78523809\n2014-02-09 05:00:00,70.62316491\n2014-02-09 06:00:00,69.95124246\n2014-02-09 07:00:00,69.93090011\n2014-02-09 08:00:00,70.59418428\n2014-02-09 09:00:00,70.22278152\n2014-02-09 10:00:00,70.96283441\n2014-02-09 11:00:00,69.80899995\n2014-02-09 12:00:00,70.54885559\n2014-02-09 13:00:00,69.93109781\n2014-02-09 14:00:00,69.51149457\n2014-02-09 15:00:00,69.65236836\n2014-02-09 16:00:00,70.29518506\n2014-02-09 17:00:00,71.62899935\n2014-02-09 18:00:00,70.19075454\n2014-02-09 19:00:00,70.75169665\n2014-02-09 20:00:00,70.81184472\n2014-02-09 21:00:00,72.25826358\n2014-02-09 22:00:00,71.2385615\n2014-02-09 23:00:00,71.58482682\n2014-02-10 00:00:00,72.05545689\n2014-02-10 01:00:00,70.68437859\n2014-02-10 02:00:00,71.74562272\n2014-02-10 03:00:00,70.63016123\n2014-02-10 04:00:00,70.10605477\n2014-02-10 05:00:00,69.15085681\n2014-02-10 06:00:00,70.53897933\n2014-02-10 07:00:00,69.75848063\n2014-02-10 08:00:00,69.0311664\n2014-02-10 09:00:00,69.97462923\n2014-02-10 10:00:00,70.99730927\n2014-02-10 11:00:00,71.81090729\n2014-02-10 12:00:00,71.22813976\n2014-02-10 13:00:00,73.54807891\n2014-02-10 14:00:00,73.1994691\n2014-02-10 15:00:00,72.48376476\n2014-02-10 16:00:00,73.27048296\n2014-02-10 17:00:00,72.63291885\n2014-02-10 18:00:00,73.04230204\n2014-02-10 19:00:00,73.59851179\n2014-02-10 20:00:00,73.94426246\n2014-02-10 21:00:00,72.24379429999998\n2014-02-10 22:00:00,72.89933674\n2014-02-10 23:00:00,73.3069622\n2014-02-11 00:00:00,73.94052267\n2014-02-11 01:00:00,72.92628635\n2014-02-11 02:00:00,72.67838417\n2014-02-11 03:00:00,73.30959938\n2014-02-11 04:00:00,73.02655382\n2014-02-11 05:00:00,72.29872004\n2014-02-11 06:00:00,71.88552448\n2014-02-11 07:00:00,72.40495323\n2014-02-11 08:00:00,72.02464429\n2014-02-11 09:00:00,72.19614083\n2014-02-11 10:00:00,72.60597358\n2014-02-11 11:00:00,72.39294669\n2014-02-11 12:00:00,71.43716569\n2014-02-11 13:00:00,73.99604465\n2014-02-11 14:00:00,73.50943035\n2014-02-11 15:00:00,73.45291204\n2014-02-11 16:00:00,72.83513404\n2014-02-11 17:00:00,73.94819798\n2014-02-11 18:00:00,72.4788448\n2014-02-11 19:00:00,72.83570362\n2014-02-11 20:00:00,73.99025826\n2014-02-11 21:00:00,72.88226906\n2014-02-11 22:00:00,73.27645109\n2014-02-11 23:00:00,74.02768967\n2014-02-12 00:00:00,73.89558413\n2014-02-12 01:00:00,72.59262336\n2014-02-12 02:00:00,71.72471476\n2014-02-12 03:00:00,72.13704935\n2014-02-12 04:00:00,71.67420314\n2014-02-12 05:00:00,70.80216066\n2014-02-12 06:00:00,71.79116991\n2014-02-12 07:00:00,70.14151030000001\n2014-02-12 08:00:00,71.38580367\n2014-02-12 09:00:00,70.1927803\n2014-02-12 10:00:00,71.53122540000003\n2014-02-12 11:00:00,70.74462709\n2014-02-12 12:00:00,71.60956249\n2014-02-12 13:00:00,72.63429747\n2014-02-12 14:00:00,72.72337319\n2014-02-12 15:00:00,73.61530291\n2014-02-12 16:00:00,73.79199341\n2014-02-12 17:00:00,74.02452744\n2014-02-12 18:00:00,73.33443313\n2014-02-12 19:00:00,73.77239947\n2014-02-12 20:00:00,74.18795723\n2014-02-12 21:00:00,72.73057539\n2014-02-12 22:00:00,73.0460628\n2014-02-12 23:00:00,72.61851266\n2014-02-13 00:00:00,73.63047725\n2014-02-13 01:00:00,71.86090259999997\n2014-02-13 02:00:00,73.39534945\n2014-02-13 03:00:00,72.5265888\n2014-02-13 04:00:00,72.50012423\n2014-02-13 05:00:00,70.9921352\n2014-02-13 06:00:00,70.68379403\n2014-02-13 07:00:00,70.92225816\n2014-02-13 08:00:00,71.06859469\n2014-02-13 09:00:00,70.50557416\n2014-02-13 10:00:00,72.40911188\n2014-02-13 11:00:00,71.18403064\n2014-02-13 12:00:00,72.27270943\n2014-02-13 13:00:00,72.11898377\n2014-02-13 14:00:00,74.22012096\n2014-02-13 15:00:00,74.14513886\n2014-02-13 16:00:00,72.57257271\n2014-02-13 17:00:00,73.9980464\n2014-02-13 18:00:00,73.63505079999999\n2014-02-13 19:00:00,74.18442393\n2014-02-13 20:00:00,74.01379528\n2014-02-13 21:00:00,73.31100848\n2014-02-13 22:00:00,73.2449359\n2014-02-13 23:00:00,73.63799953\n2014-02-14 00:00:00,74.22768593\n2014-02-14 01:00:00,73.25438431\n2014-02-14 02:00:00,73.33046811\n2014-02-14 03:00:00,73.61255907\n2014-02-14 04:00:00,72.97745167\n2014-02-14 05:00:00,71.89748993\n2014-02-14 06:00:00,72.9483533\n2014-02-14 07:00:00,70.81534967\n2014-02-14 08:00:00,72.54651585\n2014-02-14 09:00:00,71.6016416\n2014-02-14 10:00:00,71.38492873\n2014-02-14 11:00:00,72.63654073\n2014-02-14 12:00:00,72.26304553\n2014-02-14 13:00:00,73.08441684\n2014-02-14 14:00:00,72.98119162\n2014-02-14 15:00:00,73.44090643\n2014-02-14 16:00:00,73.67536027\n2014-02-14 17:00:00,73.57106999\n2014-02-14 18:00:00,75.09120703\n2014-02-14 19:00:00,74.01718788\n2014-02-14 20:00:00,74.75368514\n2014-02-14 21:00:00,74.06098855\n2014-02-14 22:00:00,73.64913399\n2014-02-14 23:00:00,72.97725908\n2014-02-15 00:00:00,74.31242165\n2014-02-15 01:00:00,73.36846791\n2014-02-15 02:00:00,73.40601581\n2014-02-15 03:00:00,71.88177019\n2014-02-15 04:00:00,72.16843891\n2014-02-15 05:00:00,72.02037785\n2014-02-15 06:00:00,71.46429845\n2014-02-15 07:00:00,70.13150262\n2014-02-15 08:00:00,71.3592175\n2014-02-15 09:00:00,71.52512352\n2014-02-15 10:00:00,71.20384956\n2014-02-15 11:00:00,70.74443864\n2014-02-15 12:00:00,70.44676548\n2014-02-15 13:00:00,69.73276669\n2014-02-15 14:00:00,69.16754481\n2014-02-15 15:00:00,68.61762076\n2014-02-15 16:00:00,68.2700207\n2014-02-15 17:00:00,68.32512358\n2014-02-15 18:00:00,68.00591358\n2014-02-15 19:00:00,67.69518570000001\n2014-02-15 20:00:00,67.66314846\n2014-02-15 21:00:00,68.83888277\n2014-02-15 22:00:00,67.71317938\n2014-02-15 23:00:00,68.16526105\n2014-02-16 00:00:00,67.74392032\n2014-02-16 01:00:00,66.91077531\n2014-02-16 02:00:00,67.67449688\n2014-02-16 03:00:00,67.30731382\n2014-02-16 04:00:00,67.90404578\n2014-02-16 05:00:00,66.9816318\n2014-02-16 06:00:00,67.36349977\n2014-02-16 07:00:00,66.85608572\n2014-02-16 08:00:00,66.82867178\n2014-02-16 09:00:00,65.9175334\n2014-02-16 10:00:00,65.85412004\n2014-02-16 11:00:00,66.57327898\n2014-02-16 12:00:00,66.93439295\n2014-02-16 13:00:00,65.95981552\n2014-02-16 14:00:00,65.52567020000001\n2014-02-16 15:00:00,65.00654684\n2014-02-16 16:00:00,65.86116824\n2014-02-16 17:00:00,66.24895835\n2014-02-16 18:00:00,64.84240685\n2014-02-16 19:00:00,65.69994977\n2014-02-16 20:00:00,65.11922166\n2014-02-16 21:00:00,65.06927583\n2014-02-16 22:00:00,65.16381523\n2014-02-16 23:00:00,64.32817118\n2014-02-17 00:00:00,66.17891449\n2014-02-17 01:00:00,65.64161252\n2014-02-17 02:00:00,64.79075623\n2014-02-17 03:00:00,64.67428457\n2014-02-17 04:00:00,64.36980786\n2014-02-17 05:00:00,63.50098479\n2014-02-17 06:00:00,63.81534068\n2014-02-17 07:00:00,64.24808886\n2014-02-17 08:00:00,63.39175042\n2014-02-17 09:00:00,65.78667951\n2014-02-17 10:00:00,65.26018668\n2014-02-17 11:00:00,66.52420616\n2014-02-17 12:00:00,68.3216973\n2014-02-17 13:00:00,69.51920746\n2014-02-17 14:00:00,70.41798643\n2014-02-17 15:00:00,69.85636686\n2014-02-17 16:00:00,70.50368788\n2014-02-17 17:00:00,71.55722128\n2014-02-17 18:00:00,72.21400820000002\n2014-02-17 19:00:00,72.23486752\n2014-02-17 20:00:00,72.30190595\n2014-02-17 21:00:00,71.38697638\n2014-02-17 22:00:00,71.71658422\n2014-02-17 23:00:00,70.60328489\n2014-02-18 00:00:00,70.70527374\n2014-02-18 01:00:00,69.37279327\n2014-02-18 02:00:00,69.26929995\n2014-02-18 03:00:00,68.33325827\n2014-02-18 04:00:00,68.26287644\n2014-02-18 05:00:00,68.58490764\n2014-02-18 06:00:00,67.91159536\n2014-02-18 07:00:00,67.02506652\n2014-02-18 08:00:00,66.65870493\n2014-02-18 09:00:00,68.35154455\n2014-02-18 10:00:00,67.47621403\n2014-02-18 11:00:00,69.77932913\n2014-02-18 12:00:00,69.15476006\n2014-02-18 13:00:00,71.2527348\n2014-02-18 14:00:00,70.75971585\n2014-02-18 15:00:00,72.72805852\n2014-02-18 16:00:00,71.57641906\n2014-02-18 17:00:00,71.53146856\n2014-02-18 18:00:00,72.43892738\n2014-02-18 19:00:00,72.51358476\n2014-02-18 20:00:00,73.04307154\n2014-02-18 21:00:00,72.01489481\n2014-02-18 22:00:00,72.03402933\n2014-02-18 23:00:00,71.36277817\n2014-02-19 00:00:00,70.22442557\n2014-02-19 01:00:00,71.04606096\n2014-02-19 02:00:00,70.29642466\n2014-02-19 03:00:00,69.67691329\n2014-02-19 04:00:00,68.59571214\n2014-02-19 05:00:00,69.32304528\n2014-02-19 06:00:00,69.67748164\n2014-02-19 07:00:00,68.7353527\n2014-02-19 08:00:00,68.35921937\n2014-02-19 09:00:00,68.72795161\n2014-02-19 10:00:00,68.99210194\n2014-02-19 11:00:00,70.19905465\n2014-02-19 12:00:00,69.97929042\n2014-02-19 13:00:00,71.22263248\n2014-02-19 14:00:00,71.68970302\n2014-02-19 15:00:00,71.30018987\n2014-02-19 16:00:00,71.27840683\n2014-02-19 17:00:00,71.89062285\n2014-02-19 18:00:00,70.7418569\n2014-02-19 19:00:00,72.45036867\n2014-02-19 20:00:00,71.32687587\n2014-02-19 21:00:00,71.41737459999997\n2014-02-19 22:00:00,72.27479477\n2014-02-19 23:00:00,70.60398854\n2014-02-20 00:00:00,71.26949942\n2014-02-20 01:00:00,70.11901901\n2014-02-20 02:00:00,70.71862637\n2014-02-20 03:00:00,70.01345997\n2014-02-20 04:00:00,70.36792895\n2014-02-20 05:00:00,70.25181505\n2014-02-20 06:00:00,70.06343925\n2014-02-20 07:00:00,69.51877722\n2014-02-20 08:00:00,69.51143689\n2014-02-20 09:00:00,69.28431029\n2014-02-20 10:00:00,70.02917117\n2014-02-20 11:00:00,69.77788948\n2014-02-20 12:00:00,70.64429563\n2014-02-20 13:00:00,72.09907213\n2014-02-20 14:00:00,72.55900491\n2014-02-20 15:00:00,72.48953325\n2014-02-20 16:00:00,72.02762569\n2014-02-20 17:00:00,72.56107268\n2014-02-20 18:00:00,72.29252772\n2014-02-20 19:00:00,72.14536417\n2014-02-20 20:00:00,73.17633192\n2014-02-20 21:00:00,72.09881309\n2014-02-20 22:00:00,73.03183616\n2014-02-20 23:00:00,73.4095494\n2014-02-21 00:00:00,73.61055026\n2014-02-21 01:00:00,73.22469023\n2014-02-21 02:00:00,72.77238923\n2014-02-21 03:00:00,71.77678685\n2014-02-21 04:00:00,71.39870017\n2014-02-21 05:00:00,72.01672718\n2014-02-21 06:00:00,71.71709105\n2014-02-21 07:00:00,71.89082404\n2014-02-21 08:00:00,71.79162775\n2014-02-21 09:00:00,71.73870688\n2014-02-21 10:00:00,70.86190335\n2014-02-21 11:00:00,71.69377098\n2014-02-21 12:00:00,72.24965305\n2014-02-21 13:00:00,71.86440398\n2014-02-21 14:00:00,71.71570293\n2014-02-21 15:00:00,73.11333987\n2014-02-21 16:00:00,73.11595078\n2014-02-21 17:00:00,71.98594655\n2014-02-21 18:00:00,71.77056727\n2014-02-21 19:00:00,72.69503008\n2014-02-21 20:00:00,72.97101070000002\n2014-02-21 21:00:00,72.4740122\n2014-02-21 22:00:00,73.52059659\n2014-02-21 23:00:00,72.43691661\n2014-02-22 00:00:00,72.18066282\n2014-02-22 01:00:00,71.32459195\n2014-02-22 02:00:00,71.85583639\n2014-02-22 03:00:00,71.88074888\n2014-02-22 04:00:00,72.15361442\n2014-02-22 05:00:00,71.17776846\n2014-02-22 06:00:00,71.41359324\n2014-02-22 07:00:00,71.75202769\n2014-02-22 08:00:00,72.29547661\n2014-02-22 09:00:00,72.06697006\n2014-02-22 10:00:00,70.50858274\n2014-02-22 11:00:00,70.18441596\n2014-02-22 12:00:00,71.29025253\n2014-02-22 13:00:00,70.23647890000001\n2014-02-22 14:00:00,70.42527414\n2014-02-22 15:00:00,70.62841849\n2014-02-22 16:00:00,71.29022977\n2014-02-22 17:00:00,70.83192557\n2014-02-22 18:00:00,71.13549561\n2014-02-22 19:00:00,70.83738869\n2014-02-22 20:00:00,70.83849743\n2014-02-22 21:00:00,70.93245308\n2014-02-22 22:00:00,70.27290872\n2014-02-22 23:00:00,70.58817206\n2014-02-23 00:00:00,70.24057965\n2014-02-23 01:00:00,70.80419\n2014-02-23 02:00:00,69.80143685\n2014-02-23 03:00:00,69.31283198\n2014-02-23 04:00:00,69.35668517\n2014-02-23 05:00:00,69.13396209999999\n2014-02-23 06:00:00,70.44526682\n2014-02-23 07:00:00,70.20928733\n2014-02-23 08:00:00,69.93524085\n2014-02-23 09:00:00,69.29629038\n2014-02-23 10:00:00,68.45718549\n2014-02-23 11:00:00,69.36682524\n2014-02-23 12:00:00,69.78440146\n2014-02-23 13:00:00,70.05047118\n2014-02-23 14:00:00,69.94616047\n2014-02-23 15:00:00,69.58663804\n2014-02-23 16:00:00,69.26826291\n2014-02-23 17:00:00,70.67206672\n2014-02-23 18:00:00,69.77136750000001\n2014-02-23 19:00:00,70.36000475\n2014-02-23 20:00:00,71.22900600000001\n2014-02-23 21:00:00,71.01855228\n2014-02-23 22:00:00,71.67436488\n2014-02-23 23:00:00,71.98920306\n2014-02-24 00:00:00,71.41241783\n2014-02-24 01:00:00,70.21304108\n2014-02-24 02:00:00,70.46941197\n2014-02-24 03:00:00,71.81875355\n2014-02-24 04:00:00,70.75726396\n2014-02-24 05:00:00,70.35054453\n2014-02-24 06:00:00,71.46188706\n2014-02-24 07:00:00,70.98973616\n2014-02-24 08:00:00,69.85618346\n2014-02-24 09:00:00,70.33833311\n2014-02-24 10:00:00,70.64534116\n2014-02-24 11:00:00,71.59340431\n2014-02-24 12:00:00,72.81269719\n2014-02-24 13:00:00,71.4608208\n2014-02-24 14:00:00,72.85545543\n2014-02-24 15:00:00,73.05311023\n2014-02-24 16:00:00,73.92592685\n2014-02-24 17:00:00,74.95996905\n2014-02-24 18:00:00,75.94820959999998\n2014-02-24 19:00:00,75.75487779999997\n2014-02-24 20:00:00,74.81028192\n2014-02-24 21:00:00,73.54824379\n2014-02-24 22:00:00,75.07458015\n2014-02-24 23:00:00,73.30253287\n2014-02-25 00:00:00,74.89976587\n2014-02-25 01:00:00,74.93152766\n2014-02-25 02:00:00,73.08132323\n2014-02-25 03:00:00,74.38609616\n2014-02-25 04:00:00,73.555717\n2014-02-25 05:00:00,72.43144467\n2014-02-25 06:00:00,73.01942581\n2014-02-25 07:00:00,72.1483262\n2014-02-25 08:00:00,72.8103996\n2014-02-25 09:00:00,72.69220185\n2014-02-25 10:00:00,72.93948367\n2014-02-25 11:00:00,72.10962389\n2014-02-25 12:00:00,73.58615695\n2014-02-25 13:00:00,72.55872059\n2014-02-25 14:00:00,73.58393306\n2014-02-25 15:00:00,72.67472192\n2014-02-25 16:00:00,73.6832062\n2014-02-25 17:00:00,74.65712512\n2014-02-25 18:00:00,74.81826612\n2014-02-25 19:00:00,75.30493537\n2014-02-25 20:00:00,74.75955931\n2014-02-25 21:00:00,74.82300241\n2014-02-25 22:00:00,75.2020531\n2014-02-25 23:00:00,73.73854426\n2014-02-26 00:00:00,74.52699276\n2014-02-26 01:00:00,74.22793271\n2014-02-26 02:00:00,73.43795586\n2014-02-26 03:00:00,73.07056291\n2014-02-26 04:00:00,72.27324959999999\n2014-02-26 05:00:00,71.51947436\n2014-02-26 06:00:00,71.63920884\n2014-02-26 07:00:00,72.10054496\n2014-02-26 08:00:00,72.35798657\n2014-02-26 09:00:00,71.52260473\n2014-02-26 10:00:00,70.96393378\n2014-02-26 11:00:00,72.58154764\n2014-02-26 12:00:00,72.58419551\n2014-02-26 13:00:00,72.36171361\n2014-02-26 14:00:00,72.42998458\n2014-02-26 15:00:00,71.75716944\n2014-02-26 16:00:00,73.07326185\n2014-02-26 17:00:00,72.75507065\n2014-02-26 18:00:00,72.5752305\n2014-02-26 19:00:00,73.48040164\n2014-02-26 20:00:00,72.81148014\n2014-02-26 21:00:00,72.55668889\n2014-02-26 22:00:00,72.85158523\n2014-02-26 23:00:00,73.26970533\n2014-02-27 00:00:00,71.19146991\n2014-02-27 01:00:00,72.08289113\n2014-02-27 02:00:00,71.96350659\n2014-02-27 03:00:00,71.82605361\n2014-02-27 04:00:00,70.82030946\n2014-02-27 05:00:00,69.42550165\n2014-02-27 06:00:00,69.92242421\n2014-02-27 07:00:00,69.31438143\n2014-02-27 08:00:00,70.76033757\n2014-02-27 09:00:00,70.97100633\n2014-02-27 10:00:00,70.17113554\n2014-02-27 11:00:00,70.71432592\n2014-02-27 12:00:00,71.921708\n2014-02-27 13:00:00,72.00375809999998\n2014-02-27 14:00:00,71.78458459\n2014-02-27 15:00:00,72.65555112\n2014-02-27 16:00:00,72.58009757\n2014-02-27 17:00:00,73.05064890000001\n2014-02-27 18:00:00,74.54039587\n2014-02-27 19:00:00,75.18858469\n2014-02-27 20:00:00,74.27894519\n2014-02-27 21:00:00,74.26208079\n2014-02-27 22:00:00,73.23807909\n2014-02-27 23:00:00,73.87025742\n2014-02-28 00:00:00,73.43235603\n2014-02-28 01:00:00,72.37198523\n2014-02-28 02:00:00,73.92808884\n2014-02-28 03:00:00,73.25719839\n2014-02-28 04:00:00,72.53001535\n2014-02-28 05:00:00,71.63872957\n2014-02-28 06:00:00,72.28002048\n2014-02-28 07:00:00,71.72196102\n2014-02-28 08:00:00,70.39334093\n2014-02-28 09:00:00,70.10964532\n2014-02-28 10:00:00,70.65823648\n2014-02-28 11:00:00,71.51087208\n2014-02-28 12:00:00,72.44637778\n2014-02-28 13:00:00,71.51568524\n2014-02-28 14:00:00,72.7279092\n2014-02-28 15:00:00,72.29771123\n2014-02-28 16:00:00,71.52876516\n2014-02-28 17:00:00,72.59605592\n2014-02-28 18:00:00,72.01554663\n2014-02-28 19:00:00,72.97598217\n2014-02-28 20:00:00,71.20551\n2014-02-28 21:00:00,72.52524715\n2014-02-28 22:00:00,72.49802968\n2014-02-28 23:00:00,72.6226827\n2014-03-01 00:00:00,71.39694912\n2014-03-01 01:00:00,70.29320788\n2014-03-01 02:00:00,70.10398202\n2014-03-01 03:00:00,70.02121361\n2014-03-01 04:00:00,70.27777940000001\n2014-03-01 05:00:00,68.76433592\n2014-03-01 06:00:00,69.37923216\n2014-03-01 07:00:00,67.78520256\n2014-03-01 08:00:00,68.49976639\n2014-03-01 09:00:00,66.66557183\n2014-03-01 10:00:00,66.92889456\n2014-03-01 11:00:00,65.80440933\n2014-03-01 12:00:00,66.89565828\n2014-03-01 13:00:00,66.20627379\n2014-03-01 14:00:00,65.62264979\n2014-03-01 15:00:00,66.38603358\n2014-03-01 16:00:00,66.57722161\n2014-03-01 17:00:00,67.22633566\n2014-03-01 18:00:00,66.59760208\n2014-03-01 19:00:00,67.12154486\n2014-03-01 20:00:00,65.97349626\n2014-03-01 21:00:00,66.84503091\n2014-03-01 22:00:00,66.34569414\n2014-03-01 23:00:00,65.04830890000001\n2014-03-02 00:00:00,65.36668131\n2014-03-02 01:00:00,64.60285133\n2014-03-02 02:00:00,65.00628144\n2014-03-02 03:00:00,65.10276279\n2014-03-03 09:00:00,64.73752596\n2014-03-03 10:00:00,66.44422198\n2014-03-03 11:00:00,66.67119237\n2014-03-03 12:00:00,68.20387067\n2014-03-03 13:00:00,67.99377700000001\n2014-03-03 14:00:00,68.82246666\n2014-03-03 15:00:00,69.83201105\n2014-03-03 16:00:00,70.41675915\n2014-03-03 17:00:00,69.67662317\n2014-03-03 18:00:00,69.75960523\n2014-03-03 19:00:00,70.63902199\n2014-03-03 20:00:00,71.26261117\n2014-03-03 21:00:00,70.37991099999998\n2014-03-03 22:00:00,68.99746538\n2014-03-03 23:00:00,67.80571471\n2014-03-04 00:00:00,68.65145086\n2014-03-04 01:00:00,67.3954395\n2014-03-04 02:00:00,67.04867326\n2014-03-04 03:00:00,66.58482439\n2014-03-04 04:00:00,65.50344586\n2014-03-04 05:00:00,65.72809278\n2014-03-04 06:00:00,65.71347736\n2014-03-04 07:00:00,66.21746488\n2014-03-04 08:00:00,67.3270938\n2014-03-04 09:00:00,67.62303328\n2014-03-04 10:00:00,68.08086803\n2014-03-04 11:00:00,68.72680885\n2014-03-04 12:00:00,70.45355378\n2014-03-04 13:00:00,70.06613398\n2014-03-04 14:00:00,69.97752106\n2014-03-04 15:00:00,70.4927163\n2014-03-04 16:00:00,71.61681198\n2014-03-04 17:00:00,70.29198332\n2014-03-04 18:00:00,71.67066391\n2014-03-04 19:00:00,70.70533885\n2014-03-04 20:00:00,70.4300817\n2014-03-04 21:00:00,69.29157767\n2014-03-04 22:00:00,69.34063822\n2014-03-04 23:00:00,70.38420092\n2014-03-05 00:00:00,69.63034413\n2014-03-05 01:00:00,69.0398113\n2014-03-05 02:00:00,67.76196134\n2014-03-05 03:00:00,67.67675741\n2014-03-05 04:00:00,68.86005963\n2014-03-05 05:00:00,67.57048842\n2014-03-05 06:00:00,68.46335363\n2014-03-05 07:00:00,69.29349205\n2014-03-05 08:00:00,68.01547296\n2014-03-05 09:00:00,68.10090635\n2014-03-05 10:00:00,68.12754514\n2014-03-05 11:00:00,70.01662351\n2014-03-05 12:00:00,70.25863434\n2014-03-05 13:00:00,71.09608996\n2014-03-05 14:00:00,71.50280303\n2014-03-05 15:00:00,71.42488612\n2014-03-05 16:00:00,72.71167276\n2014-03-05 17:00:00,71.59459113\n2014-03-05 18:00:00,72.43328872\n2014-03-05 19:00:00,71.48709146\n2014-03-05 20:00:00,71.99469951\n2014-03-05 21:00:00,71.35471229\n2014-03-05 22:00:00,70.39110149\n2014-03-05 23:00:00,69.43812495\n2014-03-06 00:00:00,70.2584932\n2014-03-06 01:00:00,69.67190229\n2014-03-06 02:00:00,68.22337002\n2014-03-06 03:00:00,68.80799396\n2014-03-06 04:00:00,68.03247815\n2014-03-06 05:00:00,67.80972606\n2014-03-06 06:00:00,66.40552502\n2014-03-06 07:00:00,67.83509944\n2014-03-06 08:00:00,65.97248106\n2014-03-06 09:00:00,66.31911328\n2014-03-06 10:00:00,66.29172592\n2014-03-06 11:00:00,66.46979301\n2014-03-06 12:00:00,67.19727082\n2014-03-06 13:00:00,67.26610171\n2014-03-06 14:00:00,66.58963271\n2014-03-06 15:00:00,66.13565431\n2014-03-06 16:00:00,67.45824979\n2014-03-06 17:00:00,67.08281943\n2014-03-06 18:00:00,66.60154522\n2014-03-06 19:00:00,66.14435074\n2014-03-06 20:00:00,65.70970149\n2014-03-06 21:00:00,65.72663154\n2014-03-06 22:00:00,65.58931781\n2014-03-06 23:00:00,65.82957452\n2014-03-07 00:00:00,65.66945407\n2014-03-07 01:00:00,64.47296805\n2014-03-07 02:00:00,64.33275758\n2014-03-07 03:00:00,64.30729548\n2014-03-07 04:00:00,63.27916803\n2014-03-07 05:00:00,63.28661915\n2014-03-07 06:00:00,62.71784797\n2014-03-07 07:00:00,62.10356599\n2014-03-07 08:00:00,62.35873434\n2014-03-07 09:00:00,62.26844161\n2014-03-07 10:00:00,64.14762913\n2014-03-07 11:00:00,66.74519744\n2014-03-07 12:00:00,66.88478620000001\n2014-03-07 13:00:00,67.39191825\n2014-03-07 14:00:00,66.3784179\n2014-03-07 15:00:00,67.24728902\n2014-03-07 16:00:00,68.80478948\n2014-03-07 17:00:00,67.78706753\n2014-03-07 18:00:00,67.6234333\n2014-03-07 19:00:00,68.13243751\n2014-03-07 20:00:00,68.35249809\n2014-03-07 21:00:00,68.76098726\n2014-03-07 22:00:00,68.27847874\n2014-03-07 23:00:00,67.18038204\n2014-03-08 00:00:00,66.54164375\n2014-03-08 01:00:00,67.01120528\n2014-03-08 02:00:00,66.64272086\n2014-03-08 03:00:00,65.06151932\n2014-03-08 04:00:00,65.17996189\n2014-03-08 05:00:00,64.67925087\n2014-03-08 06:00:00,65.55120828\n2014-03-08 07:00:00,64.59678509\n2014-03-08 08:00:00,65.27563058\n2014-03-08 09:00:00,64.88539882\n2014-03-08 10:00:00,65.15421592\n2014-03-08 11:00:00,64.26521212\n2014-03-08 12:00:00,64.07879166\n2014-03-08 13:00:00,63.99581719\n2014-03-08 14:00:00,63.37198838\n2014-03-08 15:00:00,63.85857426\n2014-03-08 16:00:00,65.7786958\n2014-03-08 17:00:00,66.00473119\n2014-03-08 18:00:00,65.12337382\n2014-03-08 19:00:00,66.57607623\n2014-03-08 20:00:00,65.02660446\n2014-03-08 21:00:00,64.95266133\n2014-03-08 22:00:00,64.97658136\n2014-03-08 23:00:00,65.67719536\n2014-03-09 00:00:00,65.24741305\n2014-03-09 01:00:00,65.41542891\n2014-03-09 02:00:00,64.98877478\n2014-03-09 03:00:00,64.96988162\n2014-03-09 04:00:00,63.30792665\n2014-03-09 05:00:00,64.40463119\n2014-03-09 06:00:00,63.87984768\n2014-03-09 07:00:00,62.65054877\n2014-03-09 08:00:00,63.64803912\n2014-03-09 09:00:00,63.06377998\n2014-03-09 10:00:00,63.08252395\n2014-03-09 11:00:00,62.42757669\n2014-03-09 12:00:00,62.08987607\n2014-03-09 13:00:00,61.82403302\n2014-03-09 14:00:00,61.80836032\n2014-03-09 15:00:00,63.57034584\n2014-03-09 16:00:00,63.14298573\n2014-03-09 17:00:00,65.21301797\n2014-03-09 18:00:00,63.94421349\n2014-03-09 19:00:00,64.45766756\n2014-03-09 20:00:00,63.5914373\n2014-03-09 21:00:00,62.89815719\n2014-03-09 22:00:00,64.45257404\n2014-03-09 23:00:00,64.12681763\n2014-03-10 00:00:00,63.49055243\n2014-03-10 01:00:00,63.42430336\n2014-03-10 02:00:00,62.15728246\n2014-03-10 03:00:00,62.18439593\n2014-03-10 04:00:00,62.23825287\n2014-03-10 05:00:00,61.28489989\n2014-03-10 06:00:00,62.43160143\n2014-03-10 07:00:00,62.64010591\n2014-03-10 08:00:00,62.75477551\n2014-03-10 09:00:00,63.07107014\n2014-03-10 10:00:00,65.36263572\n2014-03-10 11:00:00,67.68834829\n2014-03-10 12:00:00,66.78938507\n2014-03-10 13:00:00,67.4030453\n2014-03-10 14:00:00,69.22223465\n2014-03-10 15:00:00,68.72906724\n2014-03-10 16:00:00,69.43623743\n2014-03-10 17:00:00,70.25809179999999\n2014-03-10 18:00:00,70.25948981\n2014-03-10 19:00:00,70.60726748\n2014-03-10 20:00:00,70.2063059\n2014-03-10 21:00:00,69.81033474\n2014-03-10 22:00:00,68.24486669\n2014-03-10 23:00:00,68.10978258\n2014-03-11 00:00:00,67.63116079\n2014-03-11 01:00:00,68.12898944\n2014-03-11 02:00:00,66.93579537\n2014-03-11 03:00:00,67.28183681\n2014-03-11 04:00:00,67.12842156\n2014-03-11 05:00:00,65.79175844\n2014-03-11 06:00:00,65.13144669\n2014-03-11 07:00:00,66.1775294\n2014-03-11 08:00:00,66.51384686\n2014-03-11 09:00:00,66.52764863\n2014-03-11 10:00:00,67.78500622\n2014-03-11 11:00:00,69.36668186\n2014-03-11 12:00:00,71.10686192\n2014-03-11 13:00:00,71.34507296\n2014-03-11 14:00:00,71.63930695\n2014-03-11 15:00:00,70.36000942\n2014-03-11 16:00:00,71.98604698\n2014-03-11 17:00:00,71.66471114\n2014-03-11 18:00:00,72.72998288\n2014-03-11 19:00:00,72.17540433\n2014-03-11 20:00:00,71.92709502\n2014-03-11 21:00:00,70.85195269\n2014-03-11 22:00:00,69.01463509\n2014-03-11 23:00:00,68.49462169\n2014-03-12 00:00:00,67.48580392\n2014-03-12 01:00:00,68.07698894\n2014-03-12 02:00:00,68.23106386\n2014-03-12 03:00:00,67.01328165\n2014-03-12 04:00:00,67.18611750000001\n2014-03-12 05:00:00,65.92239173\n2014-03-12 06:00:00,66.38206209\n2014-03-12 07:00:00,66.46286064\n2014-03-12 08:00:00,68.24047875\n2014-03-12 09:00:00,68.02786863\n2014-03-12 10:00:00,70.1038357\n2014-03-12 11:00:00,70.22659164\n2014-03-12 12:00:00,71.37680632\n2014-03-12 13:00:00,70.67512681\n2014-03-12 14:00:00,70.46297529\n2014-03-12 15:00:00,71.28157524\n2014-03-12 16:00:00,71.05593879999998\n2014-03-12 17:00:00,71.70627229\n2014-03-12 18:00:00,72.17357465\n2014-03-12 19:00:00,71.84544009\n2014-03-12 20:00:00,71.17415427\n2014-03-12 21:00:00,71.43730024\n2014-03-12 22:00:00,71.00435876\n2014-03-12 23:00:00,71.1510194\n2014-03-13 00:00:00,69.55935905\n2014-03-13 01:00:00,69.6460687\n2014-03-13 02:00:00,69.7364644\n2014-03-13 03:00:00,68.79399824\n2014-03-13 04:00:00,69.72507825\n2014-03-13 05:00:00,69.23149065\n2014-03-13 06:00:00,67.21438079\n2014-03-13 07:00:00,68.75934959\n2014-03-13 08:00:00,69.27054515\n2014-03-13 09:00:00,69.90997802\n2014-03-13 10:00:00,69.07299661\n2014-03-13 11:00:00,70.97799327\n2014-03-13 12:00:00,70.81341304\n2014-03-13 13:00:00,69.80737543\n2014-03-13 14:00:00,70.50417147\n2014-03-13 15:00:00,71.00976364\n2014-03-13 16:00:00,71.64484062\n2014-03-13 17:00:00,71.60940441\n2014-03-13 18:00:00,71.17635266\n2014-03-13 19:00:00,70.46962717\n2014-03-13 20:00:00,70.50548628\n2014-03-13 21:00:00,70.62289581\n2014-03-13 22:00:00,71.69910104\n2014-03-13 23:00:00,70.73907743\n2014-03-14 00:00:00,69.02175496\n2014-03-14 01:00:00,68.78503059\n2014-03-14 02:00:00,69.22496356\n2014-03-14 03:00:00,67.87748709\n2014-03-14 04:00:00,67.29471566\n2014-03-14 05:00:00,67.28621294\n2014-03-14 06:00:00,66.7890731\n2014-03-14 07:00:00,67.50432318\n2014-03-14 08:00:00,67.79009858\n2014-03-14 09:00:00,69.87567\n2014-03-14 10:00:00,70.21520038\n2014-03-14 11:00:00,71.18656942\n2014-03-14 12:00:00,71.67624154\n2014-03-14 13:00:00,71.22363341\n2014-03-14 14:00:00,70.43924193\n2014-03-14 15:00:00,70.36288978\n2014-03-14 16:00:00,70.79729744\n2014-03-14 17:00:00,70.23646361\n2014-03-14 18:00:00,71.73164608\n2014-03-14 19:00:00,70.94221602\n2014-03-14 20:00:00,70.53918108\n2014-03-14 21:00:00,70.54767727\n2014-03-14 22:00:00,70.90770815\n2014-03-14 23:00:00,69.78682182\n2014-03-15 00:00:00,70.91189536\n2014-03-15 01:00:00,70.07406754\n2014-03-15 02:00:00,69.59586543\n2014-03-15 03:00:00,69.60260984\n2014-03-15 04:00:00,68.27877452\n2014-03-15 05:00:00,69.45619825\n2014-03-15 06:00:00,68.44995951\n2014-03-15 07:00:00,69.73862286\n2014-03-15 08:00:00,68.94209701\n2014-03-15 09:00:00,68.18149599\n2014-03-15 10:00:00,68.76664235\n2014-03-15 11:00:00,67.45815017\n2014-03-15 12:00:00,67.66257636\n2014-03-15 13:00:00,67.77115437\n2014-03-15 14:00:00,67.69510921\n2014-03-15 15:00:00,68.11376092\n2014-03-15 16:00:00,68.40917826\n2014-03-15 17:00:00,68.68576669\n2014-03-15 18:00:00,68.70780771\n2014-03-15 19:00:00,68.52816028\n2014-03-15 20:00:00,67.29328776\n2014-03-15 21:00:00,67.71998071\n2014-03-15 22:00:00,66.43501296\n2014-03-15 23:00:00,67.6421382\n2014-03-16 00:00:00,67.50558169\n2014-03-16 01:00:00,66.63507662\n2014-03-16 02:00:00,66.03094617\n2014-03-16 03:00:00,66.85659507\n2014-03-16 04:00:00,65.17315838\n2014-03-16 05:00:00,65.21746396\n2014-03-16 06:00:00,66.28285507\n2014-03-16 07:00:00,65.42152866\n2014-03-16 08:00:00,64.94362409\n2014-03-16 09:00:00,64.89450895\n2014-03-16 10:00:00,64.55896017\n2014-03-16 11:00:00,63.75135279\n2014-03-16 12:00:00,64.59758157\n2014-03-16 13:00:00,64.12270321\n2014-03-16 14:00:00,63.49946799\n2014-03-16 15:00:00,64.70090581\n2014-03-16 16:00:00,63.79618368\n2014-03-16 17:00:00,64.00797024\n2014-03-16 18:00:00,64.72220608\n2014-03-16 19:00:00,62.87773689\n2014-03-16 20:00:00,63.82235957\n2014-03-16 21:00:00,63.75804636\n2014-03-16 22:00:00,63.15739889\n2014-03-16 23:00:00,63.44294756\n2014-03-17 00:00:00,62.12890913\n2014-03-17 01:00:00,61.82512301\n2014-03-17 02:00:00,61.83080286\n2014-03-17 03:00:00,63.16291422\n2014-03-17 04:00:00,61.25053172\n2014-03-17 05:00:00,61.01365104\n2014-03-17 06:00:00,61.21543911\n2014-03-17 07:00:00,62.37751935\n2014-03-17 08:00:00,62.92591945\n2014-03-17 09:00:00,64.87107009\n2014-03-17 10:00:00,64.86490926\n2014-03-17 11:00:00,66.04123541\n2014-03-17 12:00:00,67.6714638\n2014-03-17 13:00:00,68.92351552\n2014-03-17 14:00:00,67.95417072\n2014-03-17 15:00:00,69.769521\n2014-03-17 16:00:00,70.24593681\n2014-03-17 17:00:00,69.82130302\n2014-03-17 18:00:00,70.83974955\n2014-03-17 19:00:00,70.51174374\n2014-03-17 20:00:00,71.02364643\n2014-03-17 21:00:00,68.7052537\n2014-03-17 22:00:00,68.11165389\n2014-03-17 23:00:00,68.1166531\n2014-03-18 00:00:00,67.21496653\n2014-03-18 01:00:00,67.06224246\n2014-03-18 02:00:00,67.30972126\n2014-03-18 05:00:00,66.69399198\n2014-03-18 06:00:00,65.70506463\n2014-03-18 07:00:00,64.62101714\n2014-03-18 08:00:00,65.77618074\n2014-03-18 09:00:00,67.40523118\n2014-03-18 10:00:00,68.71941661\n2014-03-18 11:00:00,69.61966828\n2014-03-18 12:00:00,70.27366665\n2014-03-18 13:00:00,70.56337429\n2014-03-18 14:00:00,70.67077922\n2014-03-18 15:00:00,72.26734255\n2014-03-18 16:00:00,70.62328355\n2014-03-18 17:00:00,71.06334712\n2014-03-18 18:00:00,71.65028164\n2014-03-18 19:00:00,71.77769312\n2014-03-18 20:00:00,70.059985\n2014-03-18 21:00:00,70.75799228\n2014-03-18 22:00:00,69.98433493\n2014-03-18 23:00:00,68.84969949\n2014-03-19 00:00:00,69.74606796\n2014-03-19 01:00:00,69.53952356\n2014-03-19 02:00:00,67.523201\n2014-03-19 03:00:00,67.37990329\n2014-03-19 04:00:00,67.41747840000001\n2014-03-19 05:00:00,65.93843117\n2014-03-19 06:00:00,66.82475179\n2014-03-19 07:00:00,67.27135893\n2014-03-19 08:00:00,67.13357776\n2014-03-19 09:00:00,68.52772342\n2014-03-19 10:00:00,68.55982584\n2014-03-19 11:00:00,68.81377025\n2014-03-19 12:00:00,70.36173769\n2014-03-19 13:00:00,71.70237934\n2014-03-19 14:00:00,72.13491131\n2014-03-19 15:00:00,72.18835193\n2014-03-19 16:00:00,71.92595429\n2014-03-19 17:00:00,71.92725603\n2014-03-19 18:00:00,71.54807344\n2014-03-19 19:00:00,70.49187639\n2014-03-19 20:00:00,71.48653484\n2014-03-19 21:00:00,70.20635388\n2014-03-19 22:00:00,69.49279694\n2014-03-19 23:00:00,68.9205068\n2014-03-20 00:00:00,68.33056564\n2014-03-20 01:00:00,68.82533073\n2014-03-20 02:00:00,68.84005375\n2014-03-20 03:00:00,68.31437625\n2014-03-20 04:00:00,66.64807821\n2014-03-20 05:00:00,66.34454369\n2014-03-20 06:00:00,66.17310237\n2014-03-20 07:00:00,66.74208658\n2014-03-20 08:00:00,68.01627433\n2014-03-20 09:00:00,68.92086970000001\n2014-03-20 10:00:00,70.1290524\n2014-03-20 11:00:00,70.85226597\n2014-03-20 12:00:00,70.66374179\n2014-03-20 13:00:00,70.4602105\n2014-03-20 14:00:00,70.72339624\n2014-03-20 15:00:00,71.44960721\n2014-03-20 16:00:00,72.70811888\n2014-03-20 17:00:00,72.77820708\n2014-03-20 18:00:00,71.29761709\n2014-03-20 19:00:00,71.33906347\n2014-03-20 20:00:00,72.43172383\n2014-03-20 21:00:00,70.68626447\n2014-03-20 22:00:00,70.90794649\n2014-03-20 23:00:00,69.22547767\n2014-03-21 00:00:00,69.59225848\n2014-03-21 01:00:00,69.23210541\n2014-03-21 02:00:00,68.15528042\n2014-03-21 03:00:00,66.91203197\n2014-03-21 04:00:00,67.71558241\n2014-03-21 05:00:00,66.33452731\n2014-03-21 06:00:00,66.34030271\n2014-03-21 07:00:00,66.1824594\n2014-03-21 08:00:00,66.26386\n2014-03-21 09:00:00,68.22384891\n2014-03-21 10:00:00,69.16427797\n2014-03-21 11:00:00,69.10930036\n2014-03-21 12:00:00,70.81803261\n2014-03-21 13:00:00,70.01676069\n2014-03-21 14:00:00,70.90161589\n2014-03-21 15:00:00,71.64555322\n2014-03-21 16:00:00,71.70339358\n2014-03-21 17:00:00,71.27680445\n2014-03-21 18:00:00,70.63130618\n2014-03-21 19:00:00,70.97130269\n2014-03-21 20:00:00,71.71353903\n2014-03-21 21:00:00,69.9054085\n2014-03-21 22:00:00,69.66400387\n2014-03-21 23:00:00,69.16838511\n2014-03-22 00:00:00,69.69722981\n2014-03-22 01:00:00,69.15682991\n2014-03-22 02:00:00,68.72517924\n2014-03-22 03:00:00,68.35990386\n2014-03-22 04:00:00,67.18127785\n2014-03-22 05:00:00,67.94571484\n2014-03-22 06:00:00,66.71803036\n2014-03-22 07:00:00,65.66712074\n2014-03-22 08:00:00,66.84586991\n2014-03-22 09:00:00,66.29208118\n2014-03-22 10:00:00,66.88373267\n2014-03-22 11:00:00,65.19948254\n2014-03-22 12:00:00,65.58210550000001\n2014-03-22 13:00:00,64.70394655\n2014-03-22 14:00:00,66.22315748\n2014-03-22 15:00:00,64.88013387\n2014-03-22 16:00:00,65.55529857\n2014-03-22 17:00:00,64.64947474\n2014-03-22 18:00:00,64.68176215\n2014-03-22 19:00:00,64.80958215\n2014-03-22 20:00:00,65.33285671\n2014-03-22 21:00:00,64.36267745\n2014-03-22 22:00:00,64.11222793\n2014-03-22 23:00:00,65.11150875\n2014-03-23 00:00:00,65.33899224\n2014-03-23 01:00:00,65.61427437\n2014-03-23 02:00:00,63.77836909\n2014-03-23 03:00:00,63.70443845\n2014-03-23 04:00:00,63.46343576\n2014-03-23 05:00:00,63.6445251\n2014-03-23 06:00:00,65.44047774\n2014-03-23 07:00:00,63.66470663\n2014-03-23 08:00:00,64.32136806\n2014-03-23 09:00:00,64.17341\n2014-03-23 10:00:00,64.86387244\n2014-03-23 11:00:00,62.98320455\n2014-03-23 12:00:00,63.83170364\n2014-03-23 13:00:00,62.81085999\n2014-03-23 14:00:00,62.84699795\n2014-03-23 15:00:00,63.166335499999995\n2014-03-23 16:00:00,63.23431085\n2014-03-23 17:00:00,63.01982143\n2014-03-23 18:00:00,63.70769083\n2014-03-23 19:00:00,62.51382762\n2014-03-23 20:00:00,63.21955192\n2014-03-23 21:00:00,62.20602098\n2014-03-23 22:00:00,62.15285065\n2014-03-23 23:00:00,63.05547087\n2014-03-24 00:00:00,62.10293066\n2014-03-24 01:00:00,62.540844799999995\n2014-03-24 02:00:00,62.5503174\n2014-03-24 03:00:00,63.20486663\n2014-03-24 04:00:00,62.9317748\n2014-03-24 19:00:00,71.94336325\n2014-03-24 20:00:00,70.71564295\n2014-03-24 21:00:00,69.28811871\n2014-03-24 22:00:00,68.43786337\n2014-03-24 23:00:00,68.24934959\n2014-03-25 00:00:00,68.47135744\n2014-03-25 01:00:00,67.01776467\n2014-03-25 02:00:00,68.08328348\n2014-03-25 03:00:00,67.68747842\n2014-03-25 04:00:00,67.39799093\n2014-03-25 05:00:00,66.2691171\n2014-03-25 06:00:00,65.34304105\n2014-03-25 07:00:00,64.77433465\n2014-03-25 08:00:00,66.44792487\n2014-03-25 09:00:00,67.26279954\n2014-03-25 10:00:00,67.60152815\n2014-03-25 11:00:00,69.90530838\n2014-03-25 12:00:00,70.73996852\n2014-03-25 13:00:00,70.49826866\n2014-03-25 14:00:00,70.2611678\n2014-03-25 15:00:00,71.53832084\n2014-03-25 16:00:00,71.27033912\n2014-03-25 17:00:00,70.90025791\n2014-03-25 18:00:00,71.52148116\n2014-03-25 19:00:00,70.28414588\n2014-03-25 20:00:00,71.60015916\n2014-03-25 21:00:00,70.28728127\n2014-03-25 22:00:00,68.83984168\n2014-03-25 23:00:00,68.49777461\n2014-03-26 00:00:00,69.31375581\n2014-03-26 01:00:00,67.72785184\n2014-03-26 02:00:00,68.09933961\n2014-03-26 03:00:00,67.25783658\n2014-03-26 04:00:00,66.86402700000001\n2014-03-26 05:00:00,66.59775853\n2014-03-26 06:00:00,65.53304117\n2014-03-26 07:00:00,66.86270078\n2014-03-26 08:00:00,67.50801513\n2014-03-26 09:00:00,67.77407736\n2014-03-26 10:00:00,68.52400365\n2014-03-26 11:00:00,69.56611683\n2014-03-26 12:00:00,71.28961034\n2014-03-26 13:00:00,70.14062086\n2014-03-26 14:00:00,71.034825\n2014-03-26 15:00:00,71.44418165\n2014-03-26 16:00:00,70.78327368\n2014-03-26 17:00:00,70.66347191\n2014-03-26 18:00:00,69.90711596\n2014-03-26 19:00:00,70.24754496\n2014-03-26 20:00:00,71.0175816\n2014-03-26 21:00:00,71.11791992\n2014-03-26 22:00:00,69.28691532\n2014-03-26 23:00:00,69.27422586\n2014-03-27 00:00:00,70.19449054\n2014-03-27 01:00:00,68.77820054\n2014-03-27 02:00:00,68.18678053\n2014-03-27 03:00:00,68.85984403\n2014-03-27 04:00:00,67.73755512\n2014-03-27 05:00:00,67.49811369\n2014-03-27 06:00:00,66.73351538\n2014-03-27 07:00:00,65.96544261\n2014-03-27 08:00:00,66.93124294\n2014-03-27 09:00:00,69.07779412\n2014-03-27 10:00:00,69.22374151\n2014-03-27 11:00:00,69.4535237\n2014-03-27 12:00:00,72.22574727\n2014-03-27 13:00:00,72.32609476\n2014-03-27 14:00:00,72.0268521\n2014-03-27 15:00:00,71.58630641\n2014-03-27 16:00:00,70.57044597\n2014-03-27 17:00:00,71.2768215\n2014-03-27 18:00:00,71.55483881\n2014-03-27 19:00:00,72.03927682\n2014-03-27 20:00:00,71.48654663\n2014-03-27 21:00:00,70.86464227\n2014-03-27 22:00:00,69.35637651\n2014-03-27 23:00:00,69.61239792\n2014-03-28 00:00:00,68.43977756\n2014-03-28 01:00:00,68.1853957\n2014-03-28 02:00:00,67.29170594\n2014-03-28 03:00:00,68.42970414\n2014-03-28 04:00:00,67.05828335\n2014-03-28 05:00:00,66.50295007\n2014-03-28 06:00:00,67.00732027\n2014-03-28 07:00:00,65.42638245\n2014-03-28 08:00:00,67.67939638\n2014-03-28 09:00:00,67.02204681\n2014-03-28 10:00:00,68.54764706\n2014-03-28 11:00:00,69.4655308\n2014-03-28 12:00:00,70.43402561\n2014-03-28 13:00:00,71.9389561\n2014-03-28 14:00:00,70.81297494\n2014-03-28 15:00:00,70.81249572\n2014-03-28 16:00:00,70.15898776\n2014-03-28 17:00:00,71.64451052\n2014-03-28 18:00:00,70.19782359\n2014-03-28 19:00:00,70.58227035\n2014-03-28 20:00:00,71.2087204\n2014-03-28 21:00:00,70.20658031\n2014-03-28 22:00:00,71.01175909999998\n2014-03-28 23:00:00,68.85446017\n2014-03-29 00:00:00,69.98331416\n2014-03-29 01:00:00,68.46446529\n2014-03-29 02:00:00,68.73818002\n2014-03-29 03:00:00,69.062706\n2014-03-29 04:00:00,68.38697286\n2014-03-29 05:00:00,67.58387429\n2014-03-29 06:00:00,67.83077241\n2014-03-29 07:00:00,68.81423687\n2014-03-29 08:00:00,66.69042351\n2014-03-29 09:00:00,66.36840797\n2014-03-29 10:00:00,66.61346754\n2014-03-29 11:00:00,67.33922911\n2014-03-29 12:00:00,66.9322944\n2014-03-29 13:00:00,66.76955124\n2014-03-29 14:00:00,66.00830414\n2014-03-29 15:00:00,66.7799832\n2014-03-29 16:00:00,66.58172048\n2014-03-29 17:00:00,67.11698683\n2014-03-29 18:00:00,66.15598172\n2014-03-29 19:00:00,66.69489329\n2014-03-29 20:00:00,64.82380273\n2014-03-29 21:00:00,65.2430426\n2014-03-29 22:00:00,65.21164883\n2014-03-29 23:00:00,64.54188892\n2014-03-30 00:00:00,64.8747141\n2014-03-30 01:00:00,65.4966696\n2014-03-30 02:00:00,65.38109608\n2014-03-30 03:00:00,65.02897391\n2014-03-30 04:00:00,64.67595377\n2014-03-30 05:00:00,64.44424833\n2014-03-30 06:00:00,64.25219739\n2014-03-30 07:00:00,65.40018788\n2014-03-30 08:00:00,63.73067948\n2014-03-30 09:00:00,64.20889648\n2014-03-30 10:00:00,63.45681538\n2014-03-30 11:00:00,64.48807692\n2014-03-30 12:00:00,63.79730874\n2014-03-30 13:00:00,64.36082107\n2014-03-30 14:00:00,63.84830762\n2014-03-30 15:00:00,65.51296869\n2014-03-30 16:00:00,65.48389278\n2014-03-30 17:00:00,65.75005021\n2014-03-30 18:00:00,64.65810145\n2014-03-30 19:00:00,64.36282383\n2014-03-30 20:00:00,64.99007209\n2014-03-30 21:00:00,65.34666001\n2014-03-30 22:00:00,65.39531562\n2014-03-30 23:00:00,64.45329069\n2014-03-31 00:00:00,64.61712504\n2014-03-31 01:00:00,63.75428142\n2014-03-31 02:00:00,63.49502357\n2014-03-31 03:00:00,64.12967698\n2014-03-31 04:00:00,63.69871435\n2014-03-31 05:00:00,62.31748849\n2014-03-31 06:00:00,62.56249792\n2014-03-31 07:00:00,62.083133\n2014-03-31 08:00:00,64.28414943\n2014-03-31 09:00:00,63.94397227\n2014-03-31 10:00:00,65.76317725\n2014-03-31 11:00:00,67.38934556\n2014-03-31 12:00:00,66.79761934\n2014-03-31 13:00:00,67.51730856\n2014-03-31 14:00:00,69.42271076\n2014-03-31 15:00:00,69.86566479\n2014-03-31 16:00:00,69.47338876\n2014-03-31 17:00:00,70.95110588\n2014-03-31 18:00:00,71.56889705\n2014-03-31 19:00:00,70.99062865\n2014-03-31 20:00:00,70.60246289\n2014-03-31 21:00:00,68.00017618\n2014-03-31 22:00:00,68.25783759999999\n2014-03-31 23:00:00,68.63980318\n2014-04-01 00:00:00,68.32316289\n2014-04-01 01:00:00,66.43383631\n2014-04-01 02:00:00,67.18821052\n2014-04-01 03:00:00,67.27079193\n2014-04-01 04:00:00,65.27791142\n2014-04-01 05:00:00,64.67375005\n2014-04-01 06:00:00,63.96850495\n2014-04-01 07:00:00,64.60849643\n2014-04-01 08:00:00,65.56452156\n2014-04-01 09:00:00,66.5334125\n2014-04-01 10:00:00,68.23406291\n2014-04-01 11:00:00,68.56959033\n2014-04-01 12:00:00,69.70420104\n2014-04-01 13:00:00,69.63981849\n2014-04-01 14:00:00,70.22222824\n2014-04-01 15:00:00,70.31535411\n2014-04-01 16:00:00,71.95951248\n2014-04-01 17:00:00,71.24637137\n2014-04-01 18:00:00,71.58768312\n2014-04-01 19:00:00,70.42108950000002\n2014-04-01 20:00:00,71.20646965\n2014-04-01 21:00:00,70.61530009\n2014-04-01 22:00:00,70.06998582\n2014-04-01 23:00:00,69.29171113\n2014-04-02 00:00:00,67.85447566\n2014-04-02 01:00:00,68.24887826\n2014-04-02 02:00:00,68.76715290000001\n2014-04-02 03:00:00,68.21590455\n2014-04-02 04:00:00,66.42226253\n2014-04-02 05:00:00,67.39517591\n2014-04-02 06:00:00,65.36892099\n2014-04-02 07:00:00,66.25362724\n2014-04-02 08:00:00,66.59754547\n2014-04-02 09:00:00,67.72967658\n2014-04-02 10:00:00,68.48225745\n2014-04-02 11:00:00,69.92320652\n2014-04-02 12:00:00,70.58513885\n2014-04-02 13:00:00,71.41308851\n2014-04-02 14:00:00,70.3227835\n2014-04-02 15:00:00,71.11789389\n2014-04-02 16:00:00,69.47243025\n2014-04-02 17:00:00,70.89176392\n2014-04-02 18:00:00,71.46215140000002\n2014-04-02 19:00:00,71.40483009\n2014-04-02 20:00:00,72.2868221\n2014-04-02 21:00:00,69.7696442\n2014-04-02 22:00:00,69.85857394\n2014-04-02 23:00:00,70.29044092\n2014-04-03 00:00:00,69.18897735\n2014-04-03 01:00:00,68.25903615\n2014-04-03 02:00:00,69.48405619\n2014-04-03 03:00:00,69.03729828\n2014-04-03 04:00:00,68.99054634\n2014-04-03 05:00:00,66.96693467\n2014-04-03 06:00:00,67.79585605\n2014-04-03 07:00:00,67.30111228\n2014-04-03 08:00:00,68.06321777\n2014-04-03 09:00:00,68.92309559\n2014-04-10 15:00:00,69.95467957\n2014-04-10 16:00:00,69.99969109999999\n2014-04-10 17:00:00,70.46057561\n2014-04-10 18:00:00,69.69177635\n2014-04-10 19:00:00,71.01239837\n2014-04-10 20:00:00,69.3636139\n2014-04-10 21:00:00,69.23956202\n2014-04-10 22:00:00,69.02602271\n2014-04-10 23:00:00,67.66881974\n2014-04-11 00:00:00,66.9784945\n2014-04-11 01:00:00,66.1376634\n2014-04-11 02:00:00,65.64125076\n2014-04-11 03:00:00,64.99436157\n2014-04-11 04:00:00,64.15511608\n2014-04-11 05:00:00,62.70299143\n2014-04-11 06:00:00,63.83944116\n2014-04-11 07:00:00,62.44194873\n2014-04-11 08:00:00,62.37114409\n2014-04-11 09:00:00,65.37565585\n2014-04-11 10:00:00,65.96957647\n2014-04-11 11:00:00,66.59359265\n2014-04-11 12:00:00,68.33141592\n2014-04-11 13:00:00,68.92824643\n2014-04-11 14:00:00,69.4470812\n2014-04-11 15:00:00,70.69379188\n2014-04-11 16:00:00,68.80751333\n2014-04-11 17:00:00,69.77099451\n2014-04-11 18:00:00,69.4302069\n2014-04-11 19:00:00,69.69943799\n2014-04-11 20:00:00,68.39255358\n2014-04-11 21:00:00,69.67023519\n2014-04-11 22:00:00,68.57844056\n2014-04-11 23:00:00,67.05017892\n2014-04-12 00:00:00,68.53844670000001\n2014-04-12 01:00:00,66.58977222\n2014-04-12 02:00:00,66.4437355\n2014-04-12 03:00:00,66.63975574\n2014-04-12 04:00:00,65.35200151\n2014-04-12 05:00:00,66.56495507\n2014-04-12 06:00:00,64.62244069\n2014-04-12 07:00:00,64.9923665\n2014-04-12 08:00:00,63.97746263\n2014-04-12 09:00:00,64.18268808\n2014-04-12 10:00:00,64.55629521\n2014-04-12 11:00:00,63.96192594\n2014-04-12 12:00:00,63.56770877\n2014-04-12 13:00:00,63.45102885\n2014-04-12 14:00:00,62.75664373\n2014-04-12 15:00:00,61.88488434\n2014-04-12 16:00:00,61.97105163\n2014-04-12 17:00:00,62.03644725\n2014-04-12 18:00:00,62.85879831\n2014-04-12 19:00:00,61.75532146\n2014-04-12 20:00:00,60.33080311\n2014-04-12 21:00:00,61.31862007\n2014-04-12 22:00:00,61.26515428\n2014-04-12 23:00:00,59.564727100000006\n2014-04-13 00:00:00,59.92144785\n2014-04-13 01:00:00,60.09354127\n2014-04-13 02:00:00,59.92218636\n2014-04-13 03:00:00,58.86227492\n2014-04-13 04:00:00,58.77714115\n2014-04-13 05:00:00,59.41074654\n2014-04-13 06:00:00,57.84457312\n2014-04-13 07:00:00,58.38952164\n2014-04-13 08:00:00,59.12502309\n2014-04-13 09:00:00,57.45840559\n2014-04-13 10:00:00,58.23364994\n2014-04-13 11:00:00,58.73348655\n2014-04-13 12:00:00,58.97261213\n2014-04-13 13:00:00,60.25792529\n2014-04-13 14:00:00,59.15943501\n2014-04-13 15:00:00,60.26702164\n2014-04-13 16:00:00,59.20056905\n2014-04-13 17:00:00,59.42050888\n2014-04-13 18:00:00,59.61076035\n2014-04-13 19:00:00,59.375844799999996\n2014-04-13 20:00:00,60.45036956\n2014-04-13 21:00:00,60.38321276\n2014-04-13 22:00:00,59.91094693\n2014-04-13 23:00:00,60.28396361\n2014-04-14 00:00:00,58.83249363\n2014-04-14 01:00:00,60.184197\n2014-04-14 02:00:00,60.57384958\n2014-04-14 03:00:00,60.58416247\n2014-04-14 04:00:00,59.54132737\n2014-04-14 05:00:00,60.578911899999994\n2014-04-14 06:00:00,59.20245134\n2014-04-14 07:00:00,59.53629772\n2014-04-14 08:00:00,61.42760267\n2014-04-14 09:00:00,62.35052077\n2014-04-14 10:00:00,63.87302969\n2014-04-14 11:00:00,63.95474106\n2014-04-14 12:00:00,64.33255339\n2014-04-14 13:00:00,66.89048639\n2014-04-14 14:00:00,66.76290578\n2014-04-14 15:00:00,68.22765033\n2014-04-14 16:00:00,68.66217484\n2014-04-14 17:00:00,68.77584664\n2014-04-14 18:00:00,69.85149804\n2014-04-14 19:00:00,69.64134024\n2014-04-14 20:00:00,68.67883235\n2014-04-14 21:00:00,66.53906385\n2014-04-14 22:00:00,66.75587974\n2014-04-14 23:00:00,66.67419463\n2014-04-15 00:00:00,65.2054392\n2014-04-15 01:00:00,65.2363275\n2014-04-15 02:00:00,63.50605093\n2014-04-15 03:00:00,64.46464095\n2014-04-15 04:00:00,63.51738461\n2014-04-15 05:00:00,63.61950823\n2014-04-15 06:00:00,62.96296552\n2014-04-15 07:00:00,61.77349005\n2014-04-15 08:00:00,63.95443765\n2014-04-15 09:00:00,63.98985647\n2014-04-15 10:00:00,66.04334863\n2014-04-15 11:00:00,68.14218819999999\n2014-04-15 12:00:00,68.61566659\n2014-04-15 13:00:00,68.80427879999999\n2014-04-15 14:00:00,70.24867959\n2014-04-15 15:00:00,68.84215496\n2014-04-15 16:00:00,71.07422118\n2014-04-15 17:00:00,70.7975171\n2014-04-15 18:00:00,70.00379538\n2014-04-15 19:00:00,69.63818207\n2014-04-15 20:00:00,71.11138859\n2014-04-15 21:00:00,68.9745537\n2014-04-15 22:00:00,68.41451411\n2014-04-15 23:00:00,67.63084599\n2014-04-16 00:00:00,65.73481705\n2014-04-16 01:00:00,65.50434383\n2014-04-16 02:00:00,64.79166617\n2014-04-16 03:00:00,63.918387100000004\n2014-04-16 04:00:00,64.49704161\n2014-04-16 05:00:00,63.67515316\n2014-04-16 06:00:00,62.46829544\n2014-04-16 07:00:00,63.58707467\n2014-04-16 08:00:00,64.98478124\n2014-04-16 09:00:00,64.79823783\n2014-04-16 10:00:00,67.37766731\n2014-04-16 11:00:00,67.53637026\n2014-04-16 12:00:00,68.93675906\n2014-04-16 13:00:00,69.01582856\n2014-04-16 14:00:00,70.01135347\n2014-04-16 15:00:00,70.54341131\n2014-04-16 16:00:00,70.35620490000001\n2014-04-16 17:00:00,72.05054652\n2014-04-16 18:00:00,70.83587447\n2014-04-16 19:00:00,71.22103625\n2014-04-16 20:00:00,70.22217235\n2014-04-16 21:00:00,69.83271805\n2014-04-16 22:00:00,67.95233259\n2014-04-16 23:00:00,67.65108997\n2014-04-17 00:00:00,67.466994\n2014-04-17 01:00:00,65.22016644\n2014-04-17 02:00:00,65.24342103\n2014-04-17 03:00:00,64.62596906\n2014-04-17 04:00:00,63.67041499\n2014-04-17 05:00:00,64.21771116\n2014-04-17 06:00:00,62.40771234\n2014-04-17 07:00:00,64.25745568\n2014-04-17 08:00:00,63.78224775\n2014-04-17 09:00:00,65.71063960000001\n2014-04-17 10:00:00,66.77957199\n2014-04-17 11:00:00,68.38229729\n2014-04-17 12:00:00,68.29797018\n2014-04-17 13:00:00,70.41445853\n2014-04-17 14:00:00,68.73075749\n2014-04-17 15:00:00,70.53796369999998\n2014-04-17 16:00:00,69.84495909999998\n2014-04-17 17:00:00,69.92419335\n2014-04-17 18:00:00,70.06645502\n2014-04-17 19:00:00,70.01194478\n2014-04-17 20:00:00,70.75213902\n2014-04-17 21:00:00,70.23146023\n2014-04-17 22:00:00,68.89087654\n2014-04-17 23:00:00,68.74794199\n2014-04-18 00:00:00,68.6134614\n2014-04-18 01:00:00,67.80409959999999\n2014-04-18 02:00:00,66.81999556\n2014-04-18 03:00:00,66.76963018\n2014-04-18 04:00:00,65.69553058\n2014-04-18 05:00:00,65.73002042\n2014-04-18 06:00:00,65.04376513\n2014-04-18 07:00:00,64.66042336\n2014-04-18 08:00:00,66.66369506\n2014-04-18 09:00:00,66.91478029\n2014-04-18 10:00:00,68.35124962\n2014-04-18 11:00:00,68.53892428\n2014-04-18 12:00:00,69.18079834\n2014-04-18 13:00:00,70.04821235\n2014-04-18 14:00:00,69.09186246\n2014-04-18 15:00:00,70.13679966\n2014-04-18 16:00:00,68.64486802\n2014-04-18 17:00:00,69.10913357\n2014-04-18 18:00:00,69.34877115\n2014-04-18 19:00:00,70.06810868\n2014-04-18 20:00:00,69.68681363\n2014-04-18 21:00:00,69.28946496\n2014-04-18 22:00:00,68.10328878\n2014-04-18 23:00:00,68.52704977\n2014-04-19 00:00:00,67.80210719\n2014-04-19 01:00:00,66.29263566\n2014-04-19 02:00:00,66.15580573\n2014-04-19 03:00:00,65.50262029\n2014-04-19 04:00:00,65.67858252\n2014-04-19 05:00:00,66.76499604\n2014-04-19 06:00:00,65.38745208\n2014-04-19 07:00:00,64.95897072\n2014-04-19 08:00:00,64.77271857\n2014-04-19 09:00:00,64.36173315\n2014-04-19 10:00:00,65.1175339\n2014-04-19 11:00:00,64.06584001\n2014-04-19 12:00:00,63.84447255\n2014-04-19 13:00:00,63.69995847\n2014-04-19 14:00:00,64.95980589\n2014-04-19 15:00:00,64.54564962\n2014-04-19 16:00:00,64.92641544\n2014-04-19 17:00:00,64.05690668\n2014-04-19 18:00:00,65.14093075\n2014-04-19 19:00:00,65.37596399\n2014-04-19 20:00:00,64.49955643\n2014-04-19 21:00:00,64.61511022\n2014-04-19 22:00:00,64.38633566\n2014-04-19 23:00:00,64.6986036\n2014-04-20 00:00:00,63.69621365\n2014-04-20 01:00:00,63.46227468\n2014-04-20 02:00:00,61.73732749\n2014-04-20 03:00:00,62.88858987\n2014-04-20 04:00:00,62.02517391\n2014-04-20 05:00:00,61.32938908\n2014-04-20 06:00:00,61.58004254\n2014-04-20 07:00:00,60.95237553\n2014-04-20 08:00:00,60.85101193\n2014-04-20 09:00:00,59.91009200000001\n2014-04-20 10:00:00,60.32414667\n2014-04-20 11:00:00,61.24486641\n2014-04-20 12:00:00,59.66938197\n2014-04-20 13:00:00,61.12053222\n2014-04-20 14:00:00,61.88004071\n2014-04-20 15:00:00,60.49012871\n2014-04-20 16:00:00,61.00233827\n2014-04-20 17:00:00,61.765906799999996\n2014-04-20 18:00:00,60.26541206\n2014-04-20 19:00:00,60.71115886\n2014-04-20 20:00:00,60.52159375\n2014-04-20 21:00:00,61.72193037\n2014-04-20 22:00:00,60.84591691\n2014-04-20 23:00:00,60.77650542\n2014-04-21 00:00:00,60.2969507\n2014-04-21 01:00:00,60.50295653\n2014-04-21 02:00:00,60.86537483\n2014-04-21 03:00:00,60.31204125\n2014-04-21 04:00:00,59.84361371\n2014-04-21 05:00:00,60.93695396\n2014-04-21 06:00:00,61.29175138\n2014-04-21 07:00:00,61.35624139\n2014-04-21 08:00:00,62.51476508\n2014-04-21 09:00:00,62.43283694\n2014-04-21 10:00:00,64.91681271\n2014-04-21 11:00:00,65.39698618\n2014-04-21 12:00:00,65.915587\n2014-04-21 13:00:00,67.29050932\n2014-04-21 14:00:00,68.45738752\n2014-04-21 15:00:00,70.07377229\n2014-04-21 16:00:00,69.70332453\n2014-04-21 17:00:00,69.7202728\n2014-04-21 18:00:00,69.40144364\n2014-04-21 19:00:00,68.60855551\n2014-04-21 20:00:00,68.59433384\n2014-04-21 21:00:00,67.36680577\n2014-04-21 22:00:00,67.03274551\n2014-04-21 23:00:00,67.24095409\n2014-04-22 00:00:00,65.7964252\n2014-04-22 01:00:00,64.99226274\n2014-04-22 02:00:00,64.49559793\n2014-04-22 03:00:00,65.11700189\n2014-04-22 04:00:00,64.3213603\n2014-04-22 05:00:00,63.60761024\n2014-04-22 06:00:00,64.31240029\n2014-04-22 07:00:00,63.6046907\n2014-04-22 08:00:00,64.44609818\n2014-04-22 09:00:00,65.51557705\n2014-04-22 10:00:00,66.98431814\n2014-04-22 11:00:00,67.61193771\n2014-04-22 12:00:00,69.98132266\n2014-04-22 13:00:00,70.67558021\n2014-04-22 14:00:00,69.62883752\n2014-04-22 15:00:00,69.69713146\n2014-04-22 16:00:00,69.91198782\n2014-04-22 17:00:00,70.55887454\n2014-04-22 18:00:00,70.51507392\n2014-04-22 19:00:00,69.61686927\n2014-04-22 20:00:00,69.95093901\n2014-04-22 21:00:00,68.91740485\n2014-04-22 22:00:00,67.98366316\n2014-04-22 23:00:00,69.21152689\n2014-04-23 00:00:00,68.4994454\n2014-04-23 01:00:00,68.2065762\n2014-04-23 02:00:00,67.17531475\n2014-04-23 03:00:00,66.98745597\n2014-04-23 04:00:00,66.01118571\n2014-04-23 05:00:00,66.26108706\n2014-04-23 06:00:00,66.03229855\n2014-04-23 07:00:00,66.26457169\n2014-04-23 08:00:00,66.5901253\n2014-04-23 09:00:00,67.33860469\n2014-04-23 10:00:00,67.71813475\n2014-04-23 11:00:00,68.74407883\n2014-04-23 12:00:00,70.07146655\n2014-04-23 13:00:00,69.09664385\n2014-04-23 14:00:00,68.54085218\n2014-04-23 15:00:00,68.74793879\n2014-04-23 16:00:00,70.2110304\n2014-04-23 17:00:00,69.08812898\n2014-04-23 18:00:00,71.14090948\n2014-04-23 19:00:00,71.35406032\n2014-04-23 20:00:00,70.40898557\n2014-04-23 21:00:00,70.11680124\n2014-04-23 22:00:00,68.45657214\n2014-04-23 23:00:00,68.04369977\n2014-04-24 00:00:00,67.86825922\n2014-04-24 01:00:00,68.25265298\n2014-04-24 02:00:00,67.93389846\n2014-04-24 03:00:00,67.41557857\n2014-04-24 04:00:00,66.82858317\n2014-04-24 05:00:00,66.46827942\n2014-04-24 06:00:00,66.70529771\n2014-04-24 07:00:00,65.99333339\n2014-04-24 08:00:00,66.39954920000001\n2014-04-24 09:00:00,68.68937881\n2014-04-24 10:00:00,68.86981543\n2014-04-24 11:00:00,69.28930829\n2014-04-24 12:00:00,70.13701442\n2014-04-24 13:00:00,70.87920902\n2014-04-24 14:00:00,69.73387857\n2014-04-24 15:00:00,71.07672883\n2014-04-24 16:00:00,70.8997397\n2014-04-24 17:00:00,70.81721973\n2014-04-24 18:00:00,70.08894813\n2014-04-24 19:00:00,71.49812440000002\n2014-04-24 20:00:00,70.33872212\n2014-04-24 21:00:00,69.97998584\n2014-04-24 22:00:00,69.11046806\n2014-04-24 23:00:00,68.18636306\n2014-04-25 00:00:00,67.39351909\n2014-04-25 01:00:00,66.57525861\n2014-04-25 02:00:00,67.73318644\n2014-04-25 03:00:00,66.68982673\n2014-04-25 04:00:00,65.83218116\n2014-04-25 05:00:00,65.95237266\n2014-04-25 06:00:00,67.28099527\n2014-04-25 07:00:00,66.90419491\n2014-04-25 08:00:00,67.80676658\n2014-04-25 09:00:00,68.71115712\n2014-04-25 10:00:00,70.02939458\n2014-04-25 11:00:00,69.32625844\n2014-04-25 12:00:00,70.95509984\n2014-04-25 13:00:00,70.33649459\n2014-04-25 14:00:00,70.46790053\n2014-04-25 15:00:00,71.4753647\n2014-04-25 16:00:00,71.6850702\n2014-04-25 17:00:00,70.43496647\n2014-04-25 18:00:00,70.80912379\n2014-04-25 19:00:00,70.67649218\n2014-04-25 20:00:00,70.53630655\n2014-04-25 21:00:00,70.9107218\n2014-04-25 22:00:00,69.72934336\n2014-04-25 23:00:00,69.6017667\n2014-04-26 00:00:00,69.48880205\n2014-04-26 01:00:00,67.24793666\n2014-04-26 02:00:00,67.33153476\n2014-04-26 03:00:00,66.89338891\n2014-04-26 04:00:00,66.56130689\n2014-04-26 05:00:00,66.53741504\n2014-04-26 06:00:00,67.13725522\n2014-04-26 07:00:00,66.5594858\n2014-04-26 08:00:00,65.90565072\n2014-04-26 09:00:00,65.53921771\n2014-04-26 10:00:00,65.83948867\n2014-04-26 11:00:00,64.57393058\n2014-04-26 12:00:00,65.47092598\n2014-04-26 13:00:00,64.06228730000001\n2014-04-26 14:00:00,65.61321875\n2014-04-26 15:00:00,65.0033148\n2014-04-26 16:00:00,65.06987305\n2014-04-26 17:00:00,65.49571691\n2014-04-26 18:00:00,64.89058829999999\n2014-04-26 19:00:00,63.93327257\n2014-04-26 20:00:00,65.74230017\n2014-04-26 21:00:00,64.87334743\n2014-04-26 22:00:00,64.59101491\n2014-04-26 23:00:00,64.52446439\n2014-04-27 00:00:00,65.86073905\n2014-04-27 01:00:00,65.70163338\n2014-04-27 02:00:00,65.48002454\n2014-04-27 03:00:00,65.01981817\n2014-04-27 04:00:00,64.07651163\n2014-04-27 05:00:00,64.19020524\n2014-04-27 06:00:00,64.54513799\n2014-04-27 07:00:00,64.16276662\n2014-04-27 08:00:00,64.68808942\n2014-04-27 09:00:00,65.0067767\n2014-04-27 10:00:00,64.86726485\n2014-04-27 11:00:00,65.27562701\n2014-04-27 12:00:00,64.76188253\n2014-04-27 13:00:00,64.21479337\n2014-04-27 14:00:00,64.22497124\n2014-04-27 15:00:00,63.48983416\n2014-04-27 16:00:00,64.02881119\n2014-04-27 17:00:00,65.14115001\n2014-04-27 18:00:00,64.16580322\n2014-04-27 19:00:00,63.82552427\n2014-04-27 20:00:00,64.51645768\n2014-04-27 21:00:00,64.81548712\n2014-04-27 22:00:00,63.65811355\n2014-04-27 23:00:00,63.04274263\n2014-04-28 00:00:00,63.66900707\n2014-04-28 01:00:00,62.84663436\n2014-04-28 02:00:00,64.00274294\n2014-04-28 03:00:00,64.17028398\n2014-04-28 04:00:00,64.29074432\n2014-04-28 05:00:00,62.8534311\n2014-04-28 06:00:00,64.27748755\n2014-04-28 07:00:00,63.93818963\n2014-04-28 08:00:00,64.19242071\n2014-04-28 09:00:00,66.39555183\n2014-04-28 10:00:00,66.35592434\n2014-04-28 11:00:00,66.93708398\n2014-04-28 12:00:00,67.94603672\n2014-04-28 13:00:00,67.83616225\n2014-04-28 14:00:00,68.02972643\n2014-04-28 15:00:00,67.63528784\n2014-04-28 16:00:00,67.95345262\n2014-04-28 17:00:00,67.94164899\n2014-04-28 18:00:00,66.31355879\n2014-04-28 19:00:00,66.90239851\n2014-04-28 20:00:00,67.92545865\n2014-04-28 21:00:00,66.24886617\n2014-04-28 22:00:00,66.61769712\n2014-04-28 23:00:00,66.45853965\n2014-04-29 00:00:00,65.70015178\n2014-04-29 01:00:00,66.15509081\n2014-04-29 02:00:00,64.37093221\n2014-04-29 03:00:00,64.73766535\n2014-04-29 04:00:00,63.71676928\n2014-04-29 05:00:00,65.12909065\n2014-04-29 06:00:00,64.59083625\n2014-04-29 07:00:00,65.39479955\n2014-04-29 08:00:00,64.99259943\n2014-04-29 09:00:00,63.55132406\n2014-04-29 10:00:00,63.86318351\n2014-04-29 11:00:00,63.4598629\n2014-04-29 12:00:00,63.08150923\n2014-04-29 13:00:00,63.48047822\n2014-04-29 14:00:00,64.82342973\n2014-04-29 15:00:00,64.45813978\n2014-04-29 16:00:00,63.80209508\n2014-04-29 17:00:00,65.04887616\n2014-04-29 18:00:00,65.88072103\n2014-04-29 19:00:00,65.4814587\n2014-04-29 20:00:00,64.19984122\n2014-04-29 21:00:00,65.87838087\n2014-04-29 22:00:00,64.72572253\n2014-04-29 23:00:00,65.00936847\n2014-04-30 00:00:00,64.37972197\n2014-04-30 01:00:00,64.81705324\n2014-04-30 02:00:00,64.01853731\n2014-04-30 03:00:00,62.59835239\n2014-04-30 04:00:00,62.15358748\n2014-04-30 05:00:00,63.65464859\n2014-04-30 06:00:00,62.66869499\n2014-04-30 07:00:00,63.19330523\n2014-04-30 08:00:00,64.24502053\n2014-04-30 09:00:00,65.1453243\n2014-04-30 10:00:00,64.9329398\n2014-04-30 11:00:00,66.64151484\n2014-04-30 12:00:00,66.82120203\n2014-04-30 13:00:00,67.1960497\n2014-04-30 14:00:00,66.13772358\n2014-04-30 15:00:00,66.37318638\n2014-04-30 16:00:00,67.38361772\n2014-04-30 17:00:00,67.98871109999999\n2014-04-30 18:00:00,66.25593843\n2014-04-30 19:00:00,65.92849928\n2014-04-30 20:00:00,67.21492219\n2014-04-30 21:00:00,66.24671438\n2014-04-30 22:00:00,66.61478769\n2014-04-30 23:00:00,64.84814958\n2014-05-01 00:00:00,64.94889814\n2014-05-01 01:00:00,64.45625398\n2014-05-01 02:00:00,63.9798679\n2014-05-01 03:00:00,64.26732464\n2014-05-01 04:00:00,64.59177699\n2014-05-01 05:00:00,65.37702424\n2014-05-01 06:00:00,65.19211401\n2014-05-01 07:00:00,65.37953893\n2014-05-01 08:00:00,65.05709023\n2014-05-01 09:00:00,65.87109317\n2014-05-01 10:00:00,66.54947805\n2014-05-01 11:00:00,66.4332683\n2014-05-01 12:00:00,67.94196795\n2014-05-01 13:00:00,67.73779434\n2014-05-01 14:00:00,67.94409258\n2014-05-01 15:00:00,68.59569962\n2014-05-01 16:00:00,67.76281833\n2014-05-01 17:00:00,66.3713461\n2014-05-01 18:00:00,66.45491031\n2014-05-01 19:00:00,67.7664687\n2014-05-01 20:00:00,66.30486725\n2014-05-01 21:00:00,66.77500592\n2014-05-01 22:00:00,66.08791142\n2014-05-01 23:00:00,66.23633214\n2014-05-02 00:00:00,66.08952394\n2014-05-02 01:00:00,65.49363114\n2014-05-02 02:00:00,65.20911118\n2014-05-02 03:00:00,64.65270388\n2014-05-02 04:00:00,65.68346791\n2014-05-02 05:00:00,64.53848669\n2014-05-02 06:00:00,64.87436222\n2014-05-02 07:00:00,65.83693065\n2014-05-02 08:00:00,66.45562134\n2014-05-02 09:00:00,66.22132242\n2014-05-02 10:00:00,67.40617703\n2014-05-02 11:00:00,66.82972449\n2014-05-02 12:00:00,66.3484439\n2014-05-02 13:00:00,66.56058031\n2014-05-02 14:00:00,67.87466603\n2014-05-02 15:00:00,68.36875479999999\n2014-05-02 16:00:00,68.32191349\n2014-05-02 17:00:00,68.61482576\n2014-05-02 18:00:00,67.74306346\n2014-05-02 19:00:00,67.08645996\n2014-05-02 20:00:00,68.34330065\n2014-05-02 21:00:00,68.30007946\n2014-05-02 22:00:00,68.22785404\n2014-05-02 23:00:00,66.69875824\n2014-05-03 00:00:00,66.4911086\n2014-05-03 01:00:00,66.35595511\n2014-05-03 02:00:00,66.81821492\n2014-05-03 03:00:00,65.56948969\n2014-05-03 04:00:00,66.61559763\n2014-05-03 05:00:00,65.6976645\n2014-05-03 06:00:00,64.59377619\n2014-05-03 07:00:00,64.74378706\n2014-05-03 08:00:00,65.25902071\n2014-05-03 09:00:00,64.47503572\n2014-05-03 10:00:00,64.61145531\n2014-05-03 11:00:00,63.68596001\n2014-05-03 12:00:00,65.43821188\n2014-05-03 13:00:00,64.12205423\n2014-05-03 14:00:00,65.42301205\n2014-05-03 15:00:00,65.95634267\n2014-05-03 16:00:00,65.81969209\n2014-05-03 17:00:00,64.85601416\n2014-05-03 18:00:00,65.00620928\n2014-05-03 19:00:00,63.94392708\n2014-05-03 20:00:00,65.20208745\n2014-05-03 21:00:00,63.84740672\n2014-05-03 22:00:00,63.75022634\n2014-05-03 23:00:00,64.87600042\n2014-05-04 00:00:00,64.18060217\n2014-05-04 01:00:00,64.07250966\n2014-05-04 02:00:00,62.43332813\n2014-05-04 03:00:00,62.52641171\n2014-05-04 04:00:00,62.30957888\n2014-05-04 05:00:00,62.35436891\n2014-05-04 06:00:00,63.42459056\n2014-05-04 07:00:00,63.09408094\n2014-05-04 08:00:00,62.58243369\n2014-05-04 09:00:00,63.37961637\n2014-05-04 10:00:00,62.86781634\n2014-05-04 11:00:00,62.88417215\n2014-05-04 12:00:00,62.11991599\n2014-05-04 13:00:00,62.70773678\n2014-05-04 14:00:00,63.59298753\n2014-05-04 15:00:00,62.71663598\n2014-05-04 16:00:00,63.60890306\n2014-05-04 17:00:00,62.82802932\n2014-05-04 18:00:00,63.79858076\n2014-05-04 19:00:00,63.11692463\n2014-05-04 20:00:00,62.12890815\n2014-05-04 21:00:00,61.59769629\n2014-05-04 22:00:00,62.8583145\n2014-05-04 23:00:00,61.41615236\n2014-05-05 00:00:00,61.49160445\n2014-05-05 01:00:00,61.82814205\n2014-05-05 02:00:00,61.69737845\n2014-05-05 03:00:00,61.65254063\n2014-05-05 04:00:00,60.606883700000004\n2014-05-05 05:00:00,60.47320097\n2014-05-05 06:00:00,61.5530172\n2014-05-05 07:00:00,62.01910222\n2014-05-05 08:00:00,61.23608102\n2014-05-05 09:00:00,63.67999575\n2014-05-05 10:00:00,63.36326181\n2014-05-05 11:00:00,64.13721032\n2014-05-05 12:00:00,64.5332446\n2014-05-05 13:00:00,64.19481423\n2014-05-05 14:00:00,65.1361502\n2014-05-05 15:00:00,65.97596267\n2014-05-05 16:00:00,65.85552001\n2014-05-05 17:00:00,66.32755106\n2014-05-05 18:00:00,66.92969566\n2014-05-05 19:00:00,67.2613918\n2014-05-05 20:00:00,65.80789035\n2014-05-05 21:00:00,66.20385124\n2014-05-05 22:00:00,66.51044071\n2014-05-05 23:00:00,64.8207324\n2014-05-06 00:00:00,63.59220664\n2014-05-06 01:00:00,63.23531713\n2014-05-06 02:00:00,62.49046863\n2014-05-06 03:00:00,62.28369414\n2014-05-06 04:00:00,63.30749881\n2014-05-06 05:00:00,62.80276256\n2014-05-06 06:00:00,62.34187092\n2014-05-06 07:00:00,64.17473372\n2014-05-06 08:00:00,63.97093501\n2014-05-06 09:00:00,65.0523434\n2014-05-06 10:00:00,64.75464232\n2014-05-06 11:00:00,65.04876411\n2014-05-06 12:00:00,65.74920338\n2014-05-06 13:00:00,66.40186825\n2014-05-06 14:00:00,66.18664212\n2014-05-06 15:00:00,67.31747692\n2014-05-06 16:00:00,66.95425995\n2014-05-06 17:00:00,66.93790428\n2014-05-06 18:00:00,67.73969822\n2014-05-06 19:00:00,66.72610529\n2014-05-06 20:00:00,66.08638956\n2014-05-06 21:00:00,66.71634147\n2014-05-06 22:00:00,65.14686479999999\n2014-05-06 23:00:00,64.64265197\n2014-05-07 00:00:00,65.62693199\n2014-05-07 01:00:00,64.08219838\n2014-05-07 02:00:00,64.54200752\n2014-05-07 03:00:00,65.09258433\n2014-05-07 04:00:00,64.43853993\n2014-05-07 05:00:00,64.62081306\n2014-05-07 06:00:00,63.29588419\n2014-05-07 07:00:00,64.71917156\n2014-05-07 08:00:00,63.73179147\n2014-05-07 09:00:00,66.29709464\n2014-05-07 10:00:00,67.19427577\n2014-05-07 11:00:00,67.06897531\n2014-05-07 12:00:00,68.72099133\n2014-05-07 13:00:00,69.96068224\n2014-05-07 14:00:00,70.56685636\n2014-05-07 15:00:00,69.75004488\n2014-05-07 16:00:00,69.17335133\n2014-05-07 17:00:00,70.50844769\n2014-05-07 18:00:00,70.24540175\n2014-05-07 19:00:00,70.81293524\n2014-05-07 20:00:00,69.94704581\n2014-05-07 21:00:00,68.86682809\n2014-05-07 22:00:00,68.39329009\n2014-05-07 23:00:00,66.6067577\n2014-05-08 00:00:00,66.76001378\n2014-05-08 01:00:00,66.27637613\n2014-05-08 02:00:00,65.75512541\n2014-05-08 03:00:00,65.81007339\n2014-05-08 04:00:00,65.37270606\n2014-05-08 05:00:00,66.28889617\n2014-05-08 06:00:00,66.23410255\n2014-05-08 07:00:00,64.91234651\n2014-05-08 08:00:00,67.05133706\n2014-05-08 09:00:00,67.83863065\n2014-05-08 10:00:00,68.10943196\n2014-05-08 11:00:00,69.65642273\n2014-05-08 12:00:00,70.60573585\n2014-05-08 13:00:00,70.62927012\n2014-05-08 14:00:00,70.21115072\n2014-05-08 15:00:00,70.29113189\n2014-05-08 16:00:00,70.64550484\n2014-05-08 17:00:00,71.27645212\n2014-05-08 18:00:00,71.83727293\n2014-05-08 19:00:00,71.46726041\n2014-05-08 20:00:00,69.75939304\n2014-05-08 21:00:00,70.11417736\n2014-05-08 22:00:00,70.05504972\n2014-05-08 23:00:00,69.37027812\n2014-05-09 00:00:00,67.98228281\n2014-05-09 01:00:00,67.7865791\n2014-05-09 02:00:00,68.43446290000001\n2014-05-09 03:00:00,68.07785549\n2014-05-09 04:00:00,67.81285784\n2014-05-09 05:00:00,67.56774369\n2014-05-09 06:00:00,66.24760777\n2014-05-09 07:00:00,67.65004294\n2014-05-09 08:00:00,67.05143804\n2014-05-09 09:00:00,69.05576366\n2014-05-09 10:00:00,70.10149255\n2014-05-09 11:00:00,70.63274013\n2014-05-09 12:00:00,71.06084806\n2014-05-09 13:00:00,71.07378866\n2014-05-09 14:00:00,69.87334432\n2014-05-09 15:00:00,70.92486991\n2014-05-09 16:00:00,71.2245648\n2014-05-09 17:00:00,70.78867373\n2014-05-09 18:00:00,71.99197043\n2014-05-09 19:00:00,70.89590208\n2014-05-09 20:00:00,72.38733933\n2014-05-09 21:00:00,70.14675317\n2014-05-09 22:00:00,69.74583888\n2014-05-09 23:00:00,69.43160284\n2014-05-10 00:00:00,68.23254059\n2014-05-10 01:00:00,69.47792142\n2014-05-10 02:00:00,68.91530719\n2014-05-10 03:00:00,68.35492212\n2014-05-10 04:00:00,68.39336374\n2014-05-10 05:00:00,68.42272702\n2014-05-10 06:00:00,67.0775277\n2014-05-10 07:00:00,66.90356792\n2014-05-10 08:00:00,66.37013021\n2014-05-10 09:00:00,68.21760218\n2014-05-10 10:00:00,67.53453251\n2014-05-10 11:00:00,67.42839785\n2014-05-10 12:00:00,66.96098515\n2014-05-10 13:00:00,67.33616722\n2014-05-10 14:00:00,66.84359334\n2014-05-10 15:00:00,65.89084398\n2014-05-10 16:00:00,66.81261725\n2014-05-10 17:00:00,65.32919958\n2014-05-10 18:00:00,65.92892671\n2014-05-10 19:00:00,66.58894429\n2014-05-10 20:00:00,65.10538195\n2014-05-10 21:00:00,65.63011787\n2014-05-10 22:00:00,65.81492917\n2014-05-10 23:00:00,65.57018764\n2014-05-11 00:00:00,63.91974669\n2014-05-11 01:00:00,64.51176296\n2014-05-11 02:00:00,64.43387227\n2014-05-11 03:00:00,64.33383818\n2014-05-11 04:00:00,64.57554395\n2014-05-11 05:00:00,65.03499427\n2014-05-11 06:00:00,63.11467108\n2014-05-11 07:00:00,63.87061555\n2014-05-11 08:00:00,64.64784774\n2014-05-11 09:00:00,63.64523071\n2014-05-11 10:00:00,64.05141919\n2014-05-11 11:00:00,62.7828001\n2014-05-11 12:00:00,63.82347474\n2014-05-11 13:00:00,63.58691465\n2014-05-11 14:00:00,62.08829654\n2014-05-11 15:00:00,63.01928506\n2014-05-11 16:00:00,63.90711168\n2014-05-11 17:00:00,63.07839314\n2014-05-11 18:00:00,62.69840054\n2014-05-11 19:00:00,61.72789308\n2014-05-11 20:00:00,62.289274\n2014-05-11 21:00:00,63.08826676\n2014-05-11 22:00:00,61.55557216\n2014-05-11 23:00:00,63.00932675\n2014-05-12 00:00:00,62.18412627\n2014-05-12 01:00:00,62.39660826\n2014-05-12 02:00:00,61.14767562\n2014-05-12 03:00:00,61.13299926\n2014-05-12 04:00:00,62.20171526\n2014-05-12 05:00:00,61.03856972\n2014-05-12 06:00:00,62.82075925\n2014-05-12 07:00:00,62.287278799999996\n2014-05-12 08:00:00,61.74042901\n2014-05-12 09:00:00,64.34959977\n2014-05-12 10:00:00,66.00850439\n2014-05-12 11:00:00,65.98530817\n2014-05-12 12:00:00,67.03067426\n2014-05-12 13:00:00,68.11149661\n2014-05-12 14:00:00,68.18592974\n2014-05-12 15:00:00,69.09194409999999\n2014-05-12 16:00:00,70.46158593\n2014-05-12 17:00:00,68.55542525\n2014-05-12 18:00:00,68.18348692\n2014-05-12 19:00:00,68.79946301\n2014-05-12 20:00:00,68.94392853\n2014-05-12 21:00:00,68.37912217\n2014-05-12 22:00:00,68.03272736\n2014-05-12 23:00:00,66.7522962\n2014-05-13 00:00:00,65.70093962\n2014-05-13 01:00:00,65.23145055\n2014-05-13 02:00:00,65.58334605\n2014-05-13 03:00:00,64.43826513\n2014-05-13 04:00:00,64.76745107\n2014-05-13 05:00:00,63.63936741\n2014-05-13 06:00:00,64.99365642\n2014-05-13 07:00:00,65.42791053\n2014-05-13 08:00:00,64.54368408\n2014-05-13 09:00:00,65.7424681\n2014-05-13 10:00:00,68.2490268\n2014-05-13 11:00:00,68.81523729\n2014-05-13 12:00:00,69.61897566\n2014-05-13 13:00:00,69.27540087\n2014-05-13 14:00:00,69.46898521\n2014-05-13 15:00:00,70.39851654\n2014-05-13 16:00:00,70.72748205\n2014-05-13 17:00:00,70.07376172\n2014-05-13 18:00:00,70.43111508\n2014-05-13 19:00:00,69.18648323\n2014-05-13 20:00:00,69.33720712\n2014-05-13 21:00:00,68.52452572\n2014-05-13 22:00:00,68.66320083\n2014-05-13 23:00:00,67.39728285\n2014-05-14 00:00:00,68.3111207\n2014-05-14 01:00:00,67.1601394\n2014-05-14 02:00:00,66.97372975\n2014-05-14 03:00:00,66.48481188\n2014-05-14 04:00:00,64.8808456\n2014-05-14 05:00:00,64.70801495\n2014-05-14 06:00:00,64.5459563\n2014-05-14 07:00:00,65.67840491\n2014-05-14 08:00:00,65.05875661\n2014-05-14 09:00:00,67.03858825\n2014-05-14 10:00:00,69.05639384\n2014-05-14 11:00:00,68.99189609999999\n2014-05-14 12:00:00,69.97788528\n2014-05-14 13:00:00,70.175432\n2014-05-14 14:00:00,68.16664370000001\n2014-05-14 15:00:00,68.57300267\n2014-05-14 16:00:00,69.83526008\n2014-05-14 17:00:00,70.27480031\n2014-05-14 18:00:00,70.20609040000001\n2014-05-14 19:00:00,69.40921677\n2014-05-14 20:00:00,70.27798951\n2014-05-14 21:00:00,68.30333556\n2014-05-14 22:00:00,68.09324242\n2014-05-14 23:00:00,68.36429597\n2014-05-15 00:00:00,67.72416061\n2014-05-15 01:00:00,67.8085136\n2014-05-15 02:00:00,68.26962214\n2014-05-15 03:00:00,66.64600393\n2014-05-15 04:00:00,67.56801604\n2014-05-15 05:00:00,67.36462946\n2014-05-15 06:00:00,64.81152604\n2014-05-15 07:00:00,66.53328753\n2014-05-15 08:00:00,67.08670333\n2014-05-15 09:00:00,66.85800575\n2014-05-15 10:00:00,69.47031702\n2014-05-15 11:00:00,70.77703377\n2014-05-15 12:00:00,71.07003789\n2014-05-15 13:00:00,70.78202725\n2014-05-15 14:00:00,70.7083186\n2014-05-15 15:00:00,70.96353620000002\n2014-05-15 16:00:00,70.2180453\n2014-05-15 17:00:00,71.14732103\n2014-05-15 18:00:00,71.78243404\n2014-05-15 19:00:00,70.94431125\n2014-05-15 20:00:00,70.25408586\n2014-05-15 21:00:00,69.97385592\n2014-05-15 22:00:00,71.20814017\n2014-05-15 23:00:00,70.28109027\n2014-05-16 00:00:00,68.42534022\n2014-05-16 01:00:00,68.14026632\n2014-05-16 02:00:00,68.31516842\n2014-05-16 03:00:00,68.80554576\n2014-05-16 04:00:00,68.70805438\n2014-05-16 05:00:00,68.21126844\n2014-05-16 06:00:00,67.02311979\n2014-05-16 07:00:00,68.13634615\n2014-05-16 08:00:00,68.50810021\n2014-05-16 09:00:00,68.78472332\n2014-05-16 10:00:00,70.26313322\n2014-05-16 11:00:00,69.48894493\n2014-05-16 12:00:00,69.78809126\n2014-05-16 13:00:00,69.96723012\n2014-05-16 14:00:00,69.74249505\n2014-05-16 15:00:00,70.69057352\n2014-05-16 16:00:00,70.63243838\n2014-05-16 17:00:00,70.67548445\n2014-05-16 18:00:00,71.48839758\n2014-05-16 19:00:00,70.21791457\n2014-05-16 20:00:00,69.93428517\n2014-05-16 21:00:00,70.22321349\n2014-05-16 22:00:00,70.68873242\n2014-05-16 23:00:00,68.72204475\n2014-05-17 00:00:00,69.45225691\n2014-05-17 01:00:00,68.41224787\n2014-05-17 02:00:00,68.36748732\n2014-05-17 03:00:00,67.63648402\n2014-05-17 04:00:00,67.66201157\n2014-05-17 05:00:00,65.90307781\n2014-05-17 06:00:00,66.21437481\n2014-05-17 07:00:00,65.82644339\n2014-05-17 08:00:00,65.50506941\n2014-05-17 09:00:00,65.74501564\n2014-05-17 10:00:00,65.36640537\n2014-05-17 11:00:00,65.90704699\n2014-05-17 12:00:00,63.77248723\n2014-05-17 13:00:00,64.55949992\n2014-05-17 14:00:00,64.5256338\n2014-05-17 15:00:00,64.67400160000001\n2014-05-17 16:00:00,62.79405286\n2014-05-17 17:00:00,64.31443601\n2014-05-17 18:00:00,62.55982025\n2014-05-17 19:00:00,62.74968304\n2014-05-17 20:00:00,62.73063243\n2014-05-17 21:00:00,63.65406403\n2014-05-17 22:00:00,63.42070867\n2014-05-17 23:00:00,61.94114934\n2014-05-18 00:00:00,62.89319989\n2014-05-18 01:00:00,61.96136235\n2014-05-18 02:00:00,61.33631343\n2014-05-18 03:00:00,61.95426535\n2014-05-18 04:00:00,61.38195858\n2014-05-18 05:00:00,62.38443786\n2014-05-18 06:00:00,61.0947659\n2014-05-18 07:00:00,61.36331427\n2014-05-18 08:00:00,60.59300743\n2014-05-18 09:00:00,60.43062383\n2014-05-18 10:00:00,60.58242408\n2014-05-18 11:00:00,60.31117133\n2014-05-18 12:00:00,59.76775547\n2014-05-18 13:00:00,59.86404445\n2014-05-18 14:00:00,60.24787212\n2014-05-18 15:00:00,60.87471092\n2014-05-18 16:00:00,60.28561460000001\n2014-05-18 17:00:00,59.52889185\n2014-05-18 18:00:00,59.31666076\n2014-05-18 19:00:00,59.14006513\n2014-05-18 20:00:00,59.33578729\n2014-05-18 21:00:00,58.5039748\n2014-05-18 22:00:00,59.10760819\n2014-05-18 23:00:00,58.16034228\n2014-05-19 00:00:00,58.42363855\n2014-05-19 01:00:00,57.8619057\n2014-05-19 02:00:00,58.63929497\n2014-05-19 03:00:00,59.07469099\n2014-05-19 04:00:00,60.49092523\n2014-05-19 05:00:00,59.71185823\n2014-05-19 06:00:00,60.37589367\n2014-05-19 07:00:00,60.17109245\n2014-05-19 08:00:00,60.29668226\n2014-05-19 09:00:00,62.032778\n2014-05-19 10:00:00,63.30565358\n2014-05-19 11:00:00,66.46108503\n2014-05-19 12:00:00,68.26175947\n2014-05-19 13:00:00,70.71157984\n2014-05-19 14:00:00,71.27550282\n2014-05-19 15:00:00,72.16832368\n2014-05-19 16:00:00,71.18424703\n2014-05-19 17:00:00,72.14062818\n2014-05-19 18:00:00,71.21197512\n2014-05-19 19:00:00,69.21714746\n2014-05-19 20:00:00,68.35285951\n2014-05-19 21:00:00,65.94373646\n2014-05-19 22:00:00,63.16581259\n2014-05-19 23:00:00,63.4757356\n2014-05-20 00:00:00,63.46895245\n2014-05-20 01:00:00,61.42920712\n2014-05-20 02:00:00,61.67708270000001\n2014-05-20 03:00:00,61.78693595\n2014-05-20 04:00:00,60.88555024\n2014-05-20 05:00:00,61.49993807\n2014-05-20 06:00:00,61.05565421\n2014-05-20 07:00:00,61.47083928\n2014-05-20 08:00:00,62.30626718\n2014-05-20 09:00:00,62.87057976\n2014-05-20 10:00:00,63.400864500000004\n2014-05-20 11:00:00,67.54217170000001\n2014-05-20 12:00:00,69.71421777\n2014-05-20 13:00:00,69.51084605\n2014-05-20 14:00:00,71.30924261\n2014-05-20 15:00:00,71.54100964\n2014-05-20 16:00:00,72.16153754\n2014-05-20 17:00:00,70.88654096\n2014-05-20 18:00:00,70.91172121\n2014-05-20 19:00:00,72.16415303\n2014-05-20 20:00:00,70.52750726\n2014-05-20 21:00:00,67.87157133\n2014-05-20 22:00:00,68.33303676\n2014-05-20 23:00:00,66.90035458\n2014-05-21 00:00:00,66.99561858\n2014-05-21 01:00:00,65.40626786\n2014-05-21 02:00:00,64.32359927\n2014-05-21 03:00:00,63.56365044\n2014-05-21 04:00:00,64.11854793\n2014-05-21 05:00:00,62.70245453\n2014-05-21 06:00:00,62.74071071\n2014-05-21 07:00:00,64.71093807\n2014-05-21 08:00:00,65.83512160000001\n2014-05-21 09:00:00,66.70320421\n2014-05-21 10:00:00,68.58472225\n2014-05-21 11:00:00,71.45729537\n2014-05-21 12:00:00,71.66573622\n2014-05-21 13:00:00,72.395749\n2014-05-21 14:00:00,73.90430952\n2014-05-21 15:00:00,74.74593843\n2014-05-21 16:00:00,74.30063758\n2014-05-21 17:00:00,72.59432304\n2014-05-21 18:00:00,72.22398046\n2014-05-21 19:00:00,72.32603021\n2014-05-21 20:00:00,73.63394052\n2014-05-21 21:00:00,71.85085806\n2014-05-21 22:00:00,70.92319988\n2014-05-21 23:00:00,69.67101298\n2014-05-22 00:00:00,69.59055937\n2014-05-22 01:00:00,68.10096848\n2014-05-22 02:00:00,67.59063877\n2014-05-22 03:00:00,67.28802796\n2014-05-22 04:00:00,65.50415242\n2014-05-22 05:00:00,64.98749725\n2014-05-22 06:00:00,63.84289079999999\n2014-05-22 07:00:00,65.27590436\n2014-05-22 08:00:00,65.24654655\n2014-05-22 09:00:00,69.10167387\n2014-05-22 10:00:00,70.78848187\n2014-05-22 11:00:00,71.86870384\n2014-05-22 12:00:00,71.94794239\n2014-05-22 13:00:00,73.677598\n2014-05-22 14:00:00,72.98770276\n2014-05-22 15:00:00,74.42875737\n2014-05-22 16:00:00,72.64701052\n2014-05-22 17:00:00,73.13696747\n2014-05-22 18:00:00,72.89262523\n2014-05-22 19:00:00,71.9456771\n2014-05-22 20:00:00,72.75306445\n2014-05-22 21:00:00,72.16946467\n2014-05-22 22:00:00,70.85768581\n2014-05-22 23:00:00,68.89846747\n2014-05-23 00:00:00,69.76426088\n2014-05-23 01:00:00,67.22274865\n2014-05-23 02:00:00,66.84469742\n2014-05-23 03:00:00,65.7499409\n2014-05-23 04:00:00,65.72828867\n2014-05-23 05:00:00,64.56403526\n2014-05-23 06:00:00,64.82619471\n2014-05-23 07:00:00,65.55274567\n2014-05-23 08:00:00,66.27026002\n2014-05-23 09:00:00,68.11559824\n2014-05-23 10:00:00,69.89230339\n2014-05-23 11:00:00,70.85563315\n2014-05-23 12:00:00,72.70590985\n2014-05-23 13:00:00,73.19388671\n2014-05-23 14:00:00,71.69026293\n2014-05-23 15:00:00,71.85985178\n2014-05-23 16:00:00,73.21648743\n2014-05-23 17:00:00,72.87018134\n2014-05-23 18:00:00,72.78601953\n2014-05-23 19:00:00,72.3176002\n2014-05-23 20:00:00,72.96734992\n2014-05-23 21:00:00,72.9728198\n2014-05-23 22:00:00,71.42381462\n2014-05-23 23:00:00,71.5294155\n2014-05-24 00:00:00,70.53019592\n2014-05-24 01:00:00,67.44737298\n2014-05-24 02:00:00,68.10673337\n2014-05-24 03:00:00,66.54488604\n2014-05-24 04:00:00,65.99044378\n2014-05-24 05:00:00,65.57383653\n2014-05-24 06:00:00,63.7342402\n2014-05-24 07:00:00,64.60030306\n2014-05-24 08:00:00,63.81887969\n2014-05-24 09:00:00,62.53317986\n2014-05-24 10:00:00,62.63998719\n2014-05-24 11:00:00,63.36766655\n2014-05-24 12:00:00,62.24567585\n2014-05-24 13:00:00,62.11892222\n2014-05-24 14:00:00,60.93392081\n2014-05-24 15:00:00,60.93279727\n2014-05-24 16:00:00,61.2825587\n2014-05-24 17:00:00,61.86767484\n2014-05-24 18:00:00,61.09664628\n2014-05-24 19:00:00,62.27844332\n2014-05-24 20:00:00,61.90070789\n2014-05-24 21:00:00,62.39310154\n2014-05-24 22:00:00,62.30137458\n2014-05-24 23:00:00,62.56461867\n2014-05-25 00:00:00,62.72498472\n2014-05-25 01:00:00,61.83288929\n2014-05-25 02:00:00,61.81999904\n2014-05-25 03:00:00,61.63311346\n2014-05-25 04:00:00,62.64551718\n2014-05-25 05:00:00,62.36561658\n2014-05-25 06:00:00,60.95432355\n2014-05-25 07:00:00,62.2887861\n2014-05-25 08:00:00,61.79099234\n2014-05-25 09:00:00,61.2350892\n2014-05-25 10:00:00,61.70115537\n2014-05-25 11:00:00,62.50943034\n2014-05-25 12:00:00,61.01775642\n2014-05-25 13:00:00,62.17679039\n2014-05-25 14:00:00,62.78656524\n2014-05-25 15:00:00,61.01764809\n2014-05-25 16:00:00,62.19066364\n2014-05-25 17:00:00,62.3200289\n2014-05-25 18:00:00,61.24446489\n2014-05-25 19:00:00,61.04660004\n2014-05-25 20:00:00,62.45615333\n2014-05-25 21:00:00,60.84765432\n2014-05-25 22:00:00,62.16201772\n2014-05-25 23:00:00,61.47244327\n2014-05-26 00:00:00,62.07873026\n2014-05-26 01:00:00,61.76786\n2014-05-26 02:00:00,61.14309718\n2014-05-26 03:00:00,61.00938428\n2014-05-26 04:00:00,61.95202076\n2014-05-26 05:00:00,62.03764829\n2014-05-26 06:00:00,61.473338899999995\n2014-05-26 07:00:00,61.51732548\n2014-05-26 08:00:00,63.77163674\n2014-05-26 09:00:00,66.16135606\n2014-05-26 10:00:00,68.07227638\n2014-05-26 11:00:00,69.81799259\n2014-05-26 12:00:00,72.0269253\n2014-05-26 13:00:00,71.77669121\n2014-05-26 14:00:00,72.19859519\n2014-05-26 15:00:00,72.23311654\n2014-05-26 16:00:00,72.51360720000002\n2014-05-26 17:00:00,73.97990891\n2014-05-26 18:00:00,72.13547844\n2014-05-26 19:00:00,73.53223604\n2014-05-26 20:00:00,71.63600005\n2014-05-26 21:00:00,70.98695943\n2014-05-26 22:00:00,69.02377801\n2014-05-26 23:00:00,68.51109537\n2014-05-27 00:00:00,67.10193816\n2014-05-27 01:00:00,66.822098\n2014-05-27 02:00:00,65.9294706\n2014-05-27 03:00:00,67.12169762\n2014-05-27 04:00:00,65.4066128\n2014-05-27 05:00:00,64.94669438\n2014-05-27 06:00:00,64.01596424\n2014-05-27 07:00:00,63.637964399999994\n2014-05-27 08:00:00,64.58194931\n2014-05-27 09:00:00,66.86987932\n2014-05-27 10:00:00,70.10010407\n2014-05-27 11:00:00,71.53161261\n2014-05-27 12:00:00,72.17782106\n2014-05-27 13:00:00,72.68078037\n2014-05-27 14:00:00,71.96861391\n2014-05-27 15:00:00,72.11443201\n2014-05-27 16:00:00,73.00783047\n2014-05-27 17:00:00,73.08768457\n2014-05-27 18:00:00,71.32243816\n2014-05-27 19:00:00,71.49022791\n2014-05-27 20:00:00,71.8134752\n2014-05-27 21:00:00,69.75022022\n2014-05-27 22:00:00,69.68719735\n2014-05-27 23:00:00,68.98695874\n2014-05-28 00:00:00,68.63483818\n2014-05-28 01:00:00,67.0000815\n2014-05-28 02:00:00,66.52891628\n2014-05-28 03:00:00,67.65632279\n2014-05-28 04:00:00,65.74329837\n2014-05-28 05:00:00,66.24037883\n2014-05-28 06:00:00,64.78402266\n2014-05-28 07:00:00,65.6458741\n2014-05-28 08:00:00,67.47256826\n2014-05-28 09:00:00,68.03307954\n2014-05-28 10:00:00,70.45571697\n2014-05-28 11:00:00,72.37020644\n2014-05-28 12:00:00,72.17295622\n2014-05-28 13:00:00,72.04656545\n2014-05-28 14:00:00,71.82522648\n2014-05-28 15:00:00,72.58408858\n"
  },
  {
    "path": "workspace/anomaly_detector/datasets/selected/variance_change/exchange-3_cpm_results.csv",
    "content": "timestamp,value\r\n2011-07-01 00:15:01,0.405422534525\r\n2011-07-01 01:15:01,0.433961278227\r\n2011-07-01 02:15:01,0.389267501625\r\n2011-07-01 03:15:01,0.368098502243\r\n2011-07-01 04:15:01,0.365234426765\r\n2011-07-01 05:15:01,0.3428794869\r\n2011-07-01 06:15:01,0.320650020989\r\n2011-07-01 07:15:01,0.328999171839\r\n2011-07-01 08:15:01,0.330918820695\r\n2011-07-01 09:15:01,0.396968683829\r\n2011-07-01 10:15:01,0.44347161212\r\n2011-07-01 11:15:01,0.662412074347\r\n2011-07-01 12:15:01,0.707460331375\r\n2011-07-01 13:15:01,0.597161557559\r\n2011-07-01 14:15:01,0.600127175161\r\n2011-07-01 15:15:01,0.534812246524\r\n2011-07-01 16:15:01,0.46917505741\r\n2011-07-01 17:15:01,0.505456517193\r\n2011-07-01 18:15:01,0.4535763584\r\n2011-07-01 19:15:01,0.579827163973\r\n2011-07-01 20:15:01,0.929018598624\r\n2011-07-01 21:15:01,0.481969218049\r\n2011-07-01 22:15:01,1.59456911756\r\n2011-07-01 23:15:01,3.02086765513\r\n2011-07-02 00:15:01,2.82484901469\r\n2011-07-02 01:15:01,1.01660459594\r\n2011-07-02 02:15:01,0.550420623732\r\n2011-07-02 03:15:01,0.689861668363\r\n2011-07-02 04:15:01,0.643394562177\r\n2011-07-02 05:15:01,0.603330401792\r\n2011-07-02 06:15:01,0.60099737106\r\n2011-07-02 07:15:01,0.644907856905\r\n2011-07-02 08:15:01,0.619896282481\r\n2011-07-02 09:15:01,0.711410835499\r\n2011-07-02 10:15:01,0.823032683736\r\n2011-07-02 11:15:01,0.982650117997\r\n2011-07-02 12:15:01,1.82198845938\r\n2011-07-02 13:15:01,1.4539117855\r\n2011-07-02 14:15:01,1.33707622155\r\n2011-07-02 15:15:01,1.08711717782\r\n2011-07-02 16:15:01,0.91170299956\r\n2011-07-02 17:15:01,0.803212193223\r\n2011-07-02 18:15:01,1.11925182413\r\n2011-07-02 19:15:01,0.747777030865\r\n2011-07-02 20:15:01,0.79998925588\r\n2011-07-02 21:15:01,0.765987648091\r\n2011-07-02 22:15:01,0.705948517041\r\n2011-07-02 23:15:01,1.45388610672\r\n2011-07-03 00:15:01,1.38902113011\r\n2011-07-03 01:15:01,0.925834177713\r\n2011-07-03 02:15:01,0.831415320602\r\n2011-07-03 03:15:01,0.483019261215\r\n2011-07-03 04:15:01,0.693500280828\r\n2011-07-03 05:15:01,0.680136615604\r\n2011-07-03 06:15:01,0.696506878058\r\n2011-07-03 07:15:01,0.742017606353\r\n2011-07-03 08:15:01,0.713239099849\r\n2011-07-03 09:15:01,0.757453614431\r\n2011-07-03 10:15:01,0.963004377293\r\n2011-07-03 11:15:01,1.6822211246\r\n2011-07-03 12:15:01,2.07516028693\r\n2011-07-03 13:15:01,1.94973024968\r\n2011-07-03 14:15:01,1.38908773657\r\n2011-07-03 15:15:01,1.11706077222\r\n2011-07-03 16:15:01,1.00365466979\r\n2011-07-03 17:15:01,0.959327269607\r\n2011-07-03 18:15:01,0.835083924374\r\n2011-07-03 19:15:01,0.814624009308\r\n2011-07-03 20:15:01,0.827716419656\r\n2011-07-03 21:15:01,0.882878070554\r\n2011-07-03 22:15:01,0.997623517817\r\n2011-07-03 23:15:01,1.74638339578\r\n2011-07-04 00:15:01,1.43257308234\r\n2011-07-04 01:15:01,0.943704898459\r\n2011-07-04 02:15:01,0.558643628895\r\n2011-07-04 03:15:01,0.715673181984\r\n2011-07-04 04:15:01,0.732596504133\r\n2011-07-04 05:15:01,0.640847995481\r\n2011-07-04 06:15:01,0.623399850096\r\n2011-07-04 07:15:01,0.674131851371\r\n2011-07-04 08:15:01,0.781035713426\r\n2011-07-04 09:15:01,0.684518122173\r\n2011-07-04 10:15:01,0.899108227688\r\n2011-07-04 11:15:01,1.63733247215\r\n2011-07-04 12:15:01,1.74557145559\r\n2011-07-04 13:15:01,1.97659441357\r\n2011-07-04 14:15:01,1.58846906697\r\n2011-07-04 15:15:01,1.04741587993\r\n2011-07-04 16:15:01,0.678772584881\r\n2011-07-04 17:15:01,0.602611129637\r\n2011-07-04 18:15:01,0.570830160915\r\n2011-07-04 19:15:01,0.550038076316\r\n2011-07-04 20:15:01,0.59489693004\r\n2011-07-04 21:15:01,0.582188580506\r\n2011-07-04 22:15:01,0.675870716328\r\n2011-07-04 23:15:01,1.05814892078\r\n2011-07-05 00:15:01,1.09302018155\r\n2011-07-05 01:15:01,0.619185328719\r\n2011-07-05 02:15:01,0.546216679365\r\n2011-07-05 03:15:01,0.43930623552\r\n2011-07-05 04:15:01,0.464924821965\r\n2011-07-05 05:15:01,0.457552001746\r\n2011-07-05 06:15:01,0.426136705088\r\n2011-07-05 07:15:01,0.463126895367\r\n2011-07-05 08:15:01,0.470788232029\r\n2011-07-05 09:15:01,0.438059738418\r\n2011-07-05 10:15:01,0.750424972956\r\n2011-07-05 11:15:01,0.787270610412\r\n2011-07-05 12:15:01,1.07755946225\r\n2011-07-05 13:15:01,0.998522373197\r\n2011-07-05 14:15:01,0.952744270496\r\n2011-07-05 15:15:01,0.707829298362\r\n2011-07-05 16:15:01,0.612651923352\r\n2011-07-05 17:15:01,0.582697780816\r\n2011-07-05 18:15:01,0.650834949828\r\n2011-07-05 19:15:01,0.616827982495\r\n2011-07-05 20:15:01,0.588550728092\r\n2011-07-05 21:15:01,0.525827739324\r\n2011-07-05 22:15:01,0.580492705313\r\n2011-07-05 23:15:01,0.850236788743\r\n2011-07-06 00:15:01,0.989699069715\r\n2011-07-06 01:15:01,0.542059746448\r\n2011-07-06 02:15:01,0.417662676746\r\n2011-07-06 03:15:01,0.42774941839\r\n2011-07-06 04:15:01,0.42921970945\r\n2011-07-06 05:15:01,0.407084105315\r\n2011-07-06 06:15:01,0.419973474988\r\n2011-07-06 07:15:01,0.419987213504\r\n2011-07-06 08:15:01,0.419571904869\r\n2011-07-06 09:15:01,0.542099108317\r\n2011-07-06 10:15:01,0.523028762708\r\n2011-07-06 11:15:01,0.860811277047\r\n2011-07-06 12:15:01,1.03834696676\r\n2011-07-06 13:15:01,1.02756469696\r\n2011-07-06 14:15:01,0.726965750121\r\n2011-07-06 15:15:01,0.697692029382\r\n2011-07-06 16:15:01,0.61312845603\r\n2011-07-06 17:15:01,0.589332440756\r\n2011-07-06 18:15:01,0.70509726472\r\n2011-07-06 19:15:01,0.684018898444\r\n2011-07-06 20:15:01,0.453724582931\r\n2011-07-06 21:15:01,0.689319329302\r\n2011-07-06 22:15:01,0.56934558103\r\n2011-07-06 23:15:01,0.593638974059\r\n2011-07-07 00:15:01,0.495223004774\r\n2011-07-07 01:15:01,0.533024251743\r\n2011-07-07 02:15:01,0.513768520467\r\n2011-07-07 05:15:01,0.484609943601\r\n2011-07-07 06:15:01,0.372865059711\r\n2011-07-07 07:15:01,0.580024914694\r\n2011-07-07 08:15:01,0.448067683962\r\n2011-07-07 09:15:01,0.613364729387\r\n2011-07-07 10:15:01,0.618467559655\r\n2011-07-07 11:15:01,0.838079048024\r\n2011-07-07 12:15:01,1.2565580859\r\n2011-07-07 13:15:01,1.14752664089\r\n2011-07-07 14:15:01,1.01583644619\r\n2011-07-07 15:15:01,0.913571537965\r\n2011-07-07 16:15:01,0.618304360192\r\n2011-07-07 17:15:01,0.763646369801\r\n2011-07-07 18:15:01,0.764605470099\r\n2011-07-07 19:15:01,1.21798800094\r\n2011-07-07 20:15:01,1.01495047186\r\n2011-07-07 21:15:01,1.03107344633\r\n2011-07-07 22:15:01,0.876598530712\r\n2011-07-07 23:15:01,0.552934085566\r\n2011-07-08 00:15:01,0.49550387185\r\n2011-07-08 01:15:01,0.847840103159\r\n2011-07-08 02:15:01,0.643240884261\r\n2011-07-08 06:15:01,0.706602697276\r\n2011-07-08 09:15:01,0.681349823745\r\n2011-07-08 10:15:01,0.590646181328\r\n2011-07-08 14:15:01,1.24385033027\r\n2011-07-08 16:15:01,2.59258016906\r\n2011-07-08 17:15:01,1.3542439637\r\n2011-07-08 18:15:01,0.700856342781\r\n2011-07-08 19:15:01,0.970253925004\r\n2011-07-08 20:15:01,1.18064743289\r\n2011-07-08 21:15:01,1.04666954508\r\n2011-07-08 22:15:01,1.09588027648\r\n2011-07-08 23:15:01,0.989867032787\r\n2011-07-09 09:15:01,0.722730241672\r\n2011-07-09 15:15:01,0.672810392706\r\n2011-07-09 17:15:01,0.730694412571\r\n2011-07-09 18:15:01,1.1065965848\r\n2011-07-09 19:15:01,0.951126681146\r\n2011-07-09 20:15:01,0.86612700358\r\n2011-07-09 21:15:01,0.822021986321\r\n2011-07-09 22:15:01,1.03145922094\r\n2011-07-09 23:15:01,1.16544612166\r\n2011-07-10 00:15:01,1.05581045236\r\n2011-07-10 01:15:01,0.933769979761\r\n2011-07-10 02:15:01,0.852321869447\r\n2011-07-10 03:15:01,0.562376237624\r\n2011-07-10 04:15:01,0.690265027243\r\n2011-07-10 05:15:01,0.661577265667\r\n2011-07-10 06:15:01,0.683708791707\r\n2011-07-10 07:15:01,0.585272294012\r\n2011-07-10 08:15:01,0.725823769416\r\n2011-07-10 09:15:01,1.06548190842\r\n2011-07-10 10:15:01,0.812296171035\r\n2011-07-10 11:15:01,1.15012216089\r\n2011-07-10 12:15:01,1.91079022846\r\n2011-07-10 13:15:01,1.89823760173\r\n2011-07-10 14:15:01,1.60666972834\r\n2011-07-10 15:15:01,1.36903179016\r\n2011-07-10 16:15:01,1.23539136879\r\n2011-07-10 17:15:01,1.30004968561\r\n2011-07-10 18:15:01,1.02969040624\r\n2011-07-10 19:15:01,0.932536450273\r\n2011-07-10 20:15:01,0.931886464036\r\n2011-07-10 21:15:01,0.863524014067\r\n2011-07-10 22:15:01,0.991745182096\r\n2011-07-10 23:15:01,0.862854251012\r\n2011-07-11 00:15:01,0.747998448544\r\n2011-07-11 01:15:01,0.850183503168\r\n2011-07-11 02:15:01,0.654526695899\r\n2011-07-11 03:15:01,0.728679424723\r\n2011-07-11 04:15:01,0.690021862785\r\n2011-07-11 05:15:01,0.698213122487\r\n2011-07-11 06:15:01,0.638280829834\r\n2011-07-11 07:15:01,0.671747063098\r\n2011-07-11 08:15:01,0.641360186156\r\n2011-07-11 09:15:01,0.588559867574\r\n2011-07-11 10:15:01,0.97926990996\r\n2011-07-11 11:15:01,2.03972428805\r\n2011-07-11 12:15:01,1.43419613562\r\n2011-07-11 13:15:01,1.50993833205\r\n2011-07-11 14:15:01,1.39176641082\r\n2011-07-11 15:15:01,1.10735535393\r\n2011-07-11 16:15:01,0.997729716812\r\n2011-07-11 17:15:01,0.838516364175\r\n2011-07-11 18:15:01,0.591521865594\r\n2011-07-11 19:15:01,0.523210749244\r\n2011-07-11 20:15:01,0.50741379187\r\n2011-07-11 21:15:01,0.538820681939\r\n2011-07-11 22:15:01,0.537126366514\r\n2011-07-11 23:15:01,0.575014047574\r\n2011-07-12 00:15:01,0.434892834119\r\n2011-07-12 01:15:01,0.568473258729\r\n2011-07-12 02:15:01,0.576361277601\r\n2011-07-12 03:15:01,0.561665799733\r\n2011-07-12 04:15:01,0.506676771373\r\n2011-07-12 05:15:01,0.532992059663\r\n2011-07-12 06:15:01,0.533646651609\r\n2011-07-12 07:15:01,0.543344592151\r\n2011-07-12 08:15:01,0.63393689344\r\n2011-07-12 09:15:01,0.673402868318\r\n2011-07-12 10:15:01,0.670085200379\r\n2011-07-12 11:15:01,0.702719812998\r\n2011-07-12 12:15:01,0.995558682556\r\n2011-07-12 13:15:01,1.16926536732\r\n2011-07-12 14:15:01,1.01409928115\r\n2011-07-12 15:15:01,0.996637659048\r\n2011-07-12 16:15:01,0.679225381434\r\n2011-07-12 17:15:01,0.75814025419\r\n2011-07-12 18:15:01,0.763981210671\r\n2011-07-12 19:15:01,0.708667855921\r\n2011-07-12 20:15:01,0.714510023353\r\n2011-07-12 21:15:01,0.762345540039\r\n2011-07-12 22:15:01,0.703105906489\r\n2011-07-12 23:15:01,0.707826549505\r\n2011-07-13 00:15:01,0.57670519965\r\n2011-07-13 01:15:01,0.679474448094\r\n2011-07-13 02:15:01,0.557389600963\r\n2011-07-13 03:15:01,0.531382043611\r\n2011-07-13 04:15:01,0.529654200621\r\n2011-07-13 05:15:01,0.519767135236\r\n2011-07-13 06:15:01,0.512662431177\r\n2011-07-13 07:15:01,0.555591534137\r\n2011-07-13 08:15:01,0.656115012713\r\n2011-07-13 09:15:01,0.78798286152\r\n2011-07-13 10:15:01,0.692587249625\r\n2011-07-13 11:15:01,0.935283109196\r\n2011-07-13 12:15:01,1.07905121568\r\n2011-07-13 13:15:01,1.26547389169\r\n2011-07-13 14:15:01,0.758122743682\r\n2011-07-13 15:15:01,0.861263139606\r\n2011-07-13 16:15:01,0.818969842122\r\n2011-07-13 17:15:01,0.781863718801\r\n2011-07-13 18:15:01,0.754097953198\r\n2011-07-13 19:15:01,0.734934125478\r\n2011-07-13 20:15:01,0.690540979909\r\n2011-07-13 21:15:01,0.729830698994\r\n2011-07-13 22:15:01,0.75001446262\r\n2011-07-13 23:15:01,0.788613597882\r\n2011-07-14 00:15:01,0.599371499577\r\n2011-07-14 01:15:01,0.618132010667\r\n2011-07-14 02:15:01,0.492632136346\r\n2011-07-14 03:15:01,0.433984949291\r\n2011-07-14 04:15:01,0.401924624437\r\n2011-07-14 05:15:01,0.391060382405\r\n2011-07-14 06:15:01,0.394108266834\r\n2011-07-14 07:15:01,0.414870889838\r\n2011-07-14 08:15:01,0.459231967846\r\n2011-07-14 09:15:01,0.554594329429\r\n2011-07-14 10:15:01,0.586447433981\r\n2011-07-14 11:15:01,0.774360121165\r\n2011-07-14 12:15:01,1.09174200349\r\n2011-07-14 13:15:01,1.02217110037\r\n2011-07-14 14:15:01,0.927402784199\r\n2011-07-14 15:15:01,0.758385916177\r\n2011-07-14 16:15:01,0.628370275811\r\n2011-07-14 17:15:01,0.620875293673\r\n2011-07-14 18:15:01,0.599521386669\r\n2011-07-14 19:15:01,0.571684647103\r\n2011-07-14 20:15:01,0.553937947494\r\n2011-07-14 21:15:01,0.583300039952\r\n2011-07-14 22:15:01,0.54794987059\r\n2011-07-14 23:15:01,0.584078029022\r\n2011-07-15 00:15:01,0.470730436595\r\n2011-07-15 01:15:01,0.613684756703\r\n2011-07-15 02:15:01,0.500075260381\r\n2011-07-15 03:15:01,0.465845307932\r\n2011-07-15 04:15:01,0.41024236317\r\n2011-07-15 05:15:01,0.387587791441\r\n2011-07-15 06:15:01,0.424290111819\r\n2011-07-15 07:15:01,0.419710942605\r\n2011-07-15 08:15:01,0.490660629494\r\n2011-07-15 09:15:01,0.579498460973\r\n2011-07-15 10:15:01,0.629326672567\r\n2011-07-15 11:15:01,0.678068562505\r\n2011-07-15 12:15:01,0.92753386871\r\n2011-07-15 13:15:01,0.999694137996\r\n2011-07-15 14:15:01,0.666268214936\r\n2011-07-15 15:15:01,0.697556091181\r\n2011-07-15 16:15:01,0.641203792909\r\n2011-07-15 17:15:01,0.63342731861\r\n2011-07-15 18:15:01,0.582036667388\r\n2011-07-15 19:15:01,0.563113818597\r\n2011-07-15 20:15:01,0.526980162514\r\n2011-07-15 21:15:01,0.52827791804\r\n2011-07-15 22:15:01,0.475220574063\r\n2011-07-15 23:15:01,0.447709441696\r\n2011-07-16 00:15:01,0.573151033543\r\n2011-07-16 01:15:01,0.660520510001\r\n2011-07-16 02:15:01,0.653658941313\r\n2011-07-16 03:15:01,0.54005469609\r\n2011-07-16 04:15:01,0.515772970517\r\n2011-07-16 05:15:01,0.429273997931\r\n2011-07-16 06:15:01,0.407590018152\r\n2011-07-16 07:15:01,0.421466054048\r\n2011-07-16 08:15:01,0.530038045387\r\n2011-07-16 09:15:01,0.57930338213\r\n2011-07-16 10:15:01,0.770295651048\r\n2011-07-16 11:15:01,0.808551183638\r\n2011-07-16 12:15:01,0.841766168283\r\n2011-07-16 13:15:01,1.14397851684\r\n2011-07-16 14:15:01,0.693110948221\r\n2011-07-16 15:15:01,0.765183723366\r\n2011-07-16 16:15:01,0.679417321464\r\n2011-07-16 17:15:01,0.599942000367\r\n2011-07-16 18:15:01,0.577088263652\r\n2011-07-16 19:15:01,0.61229276245\r\n2011-07-16 22:15:01,0.554915456933\r\n2011-07-16 23:15:01,0.558064606445\r\n2011-07-17 00:15:01,0.551861184907\r\n2011-07-17 01:15:01,0.61407608019\r\n2011-07-17 02:15:01,0.614105010588\r\n2011-07-17 03:15:01,0.547997259079\r\n2011-07-17 04:15:01,0.52247125088\r\n2011-07-17 05:15:01,0.44803768545\r\n2011-07-17 06:15:01,0.422634977534\r\n2011-07-17 07:15:01,0.449383287256\r\n2011-07-17 08:15:01,0.48685191239\r\n2011-07-17 09:15:01,0.55355034739\r\n2011-07-17 10:15:01,0.751857084264\r\n2011-07-17 11:15:01,0.752667091441\r\n2011-07-17 12:15:01,0.929141547083\r\n2011-07-17 13:15:01,1.20847661477\r\n2011-07-17 14:15:01,0.779651764165\r\n2011-07-17 15:15:01,0.842350417376\r\n2011-07-17 16:15:01,0.660812279132\r\n2011-07-17 17:15:01,0.604369143437\r\n2011-07-17 18:15:01,0.545339087944\r\n2011-07-17 19:15:01,0.553533960498\r\n2011-07-17 20:15:01,0.548774325402\r\n2011-07-17 21:15:01,0.538358082874\r\n2011-07-17 22:15:01,0.53644178623\r\n2011-07-17 23:15:01,0.534592977484\r\n2011-07-18 00:15:01,0.512258339014\r\n2011-07-18 01:15:01,0.566221756929\r\n2011-07-18 02:15:01,0.522523408729\r\n2011-07-18 03:15:01,0.471140262255\r\n2011-07-18 04:15:01,0.427749227361\r\n2011-07-18 05:15:01,0.389042222628\r\n2011-07-18 06:15:01,0.383151727687\r\n2011-07-18 07:15:01,0.431656005927\r\n2011-07-18 08:15:01,0.450789800048\r\n2011-07-18 09:15:01,0.579229368551\r\n2011-07-18 10:15:01,0.619556840077\r\n2011-07-18 11:15:01,0.723378174503\r\n2011-07-18 12:15:01,1.01502410409\r\n2011-07-18 13:15:01,0.846268382728\r\n2011-07-18 14:15:01,0.839328087923\r\n2011-07-18 15:15:01,0.725356643836\r\n2011-07-18 16:15:01,0.724121952079\r\n2011-07-18 17:15:01,0.651006083675\r\n2011-07-18 18:15:01,0.602683655851\r\n2011-07-18 19:15:01,0.586257084968\r\n2011-07-18 20:15:01,0.562953513723\r\n2011-07-18 21:15:01,0.515027143549\r\n2011-07-18 22:15:01,0.51568420058\r\n2011-07-18 23:15:01,0.520976591741\r\n2011-07-19 00:15:01,0.443980609863\r\n2011-07-19 01:15:01,0.616688653055\r\n2011-07-19 02:15:01,0.543115927044\r\n2011-07-19 03:15:01,0.453472535098\r\n2011-07-19 04:15:01,0.42156878009\r\n2011-07-19 05:15:01,0.354035310108\r\n2011-07-19 06:15:01,0.338454738679\r\n2011-07-19 07:15:01,0.410903748263\r\n2011-07-19 08:15:01,0.447593728971\r\n2011-07-19 09:15:01,0.55913499836\r\n2011-07-19 10:15:01,0.719621810927\r\n2011-07-19 11:15:01,0.767196681645\r\n2011-07-19 12:15:01,0.942294520548\r\n2011-07-19 13:15:01,1.0032383212\r\n2011-07-19 14:15:01,0.862942524284\r\n2011-07-19 15:15:01,0.733837310024\r\n2011-07-19 16:15:01,0.625142679429\r\n2011-07-19 17:15:01,0.509370235269\r\n2011-07-19 18:15:01,0.53930596467\r\n2011-07-19 19:15:01,0.50644543215\r\n2011-07-19 20:15:01,0.488141028621\r\n2011-07-19 21:15:01,0.436814157173\r\n2011-07-19 22:15:01,0.47635140278\r\n2011-07-19 23:15:01,0.457919393325\r\n2011-07-20 00:15:01,0.4295801077\r\n2011-07-20 01:15:01,0.564498167608\r\n2011-07-20 02:15:01,0.509544562716\r\n2011-07-20 03:15:01,0.463203968782\r\n2011-07-20 04:15:01,0.407072030767\r\n2011-07-20 05:15:01,0.358862801122\r\n2011-07-20 06:15:01,0.373697236561\r\n2011-07-20 07:15:01,0.439205007516\r\n2011-07-20 08:15:01,0.415318662475\r\n2011-07-20 09:15:01,0.542676839911\r\n2011-07-20 10:15:01,0.575836639641\r\n2011-07-20 11:15:01,0.693750209668\r\n2011-07-20 12:15:01,0.958649679038\r\n2011-07-20 13:15:01,0.978838236235\r\n2011-07-20 14:15:01,0.847355615316\r\n2011-07-20 15:15:01,0.662280939932\r\n2011-07-20 16:15:01,0.583318113117\r\n2011-07-20 17:15:01,0.533766852362\r\n2011-07-20 18:15:01,0.534896914979\r\n2011-07-20 19:15:01,0.49444521527\r\n2011-07-20 20:15:01,0.472729580661\r\n2011-07-20 21:15:01,0.480673062305\r\n2011-07-20 22:15:01,0.423097534834\r\n2011-07-20 23:15:01,0.486307654948\r\n2011-07-21 00:15:01,0.422066413938\r\n2011-07-21 01:15:01,0.519997336916\r\n2011-07-21 02:15:01,0.503462395529\r\n2011-07-21 03:15:01,0.443251378533\r\n2011-07-21 04:15:01,0.384122851996\r\n2011-07-21 05:15:01,0.362461723631\r\n2011-07-21 06:15:01,0.362696176533\r\n2011-07-21 07:15:01,0.382357225458\r\n2011-07-21 08:15:01,0.409054677065\r\n2011-07-21 09:15:01,0.529625586473\r\n2011-07-21 10:15:01,0.575244382969\r\n2011-07-21 11:15:01,0.5888\r\n2011-07-21 12:15:01,0.847774407738\r\n2011-07-21 13:15:01,0.791340636411\r\n2011-07-21 14:15:01,0.896465706439\r\n2011-07-21 15:15:01,0.665230969614\r\n2011-07-21 16:15:01,0.593758564712\r\n2011-07-21 17:15:01,0.569387656299\r\n2011-07-21 18:15:01,0.634304010683\r\n2011-07-21 22:15:01,0.486431017698\r\n2011-07-22 00:15:01,0.422591891003\r\n2011-07-22 01:15:01,0.486913311221\r\n2011-07-22 02:15:01,0.46735676419\r\n2011-07-22 03:15:01,0.434363028666\r\n2011-07-22 04:15:01,0.386714049044\r\n2011-07-22 05:15:01,0.369504587288\r\n2011-07-22 06:15:01,0.397595454874\r\n2011-07-22 07:15:01,0.410352632737\r\n2011-07-22 08:15:01,0.423393177227\r\n2011-07-22 09:15:01,0.491140774627\r\n2011-07-22 10:15:01,0.468621217473\r\n2011-07-22 11:15:01,0.580554113678\r\n2011-07-22 12:15:01,0.833853226071\r\n2011-07-22 13:15:01,0.896172284725\r\n2011-07-22 14:15:01,0.767720788852\r\n2011-07-22 15:15:01,0.56208989333\r\n2011-07-22 16:15:01,0.605598263972\r\n2011-07-22 17:15:01,0.474154728687\r\n2011-07-22 18:15:01,0.527754990429\r\n2011-07-22 19:15:01,0.570643559125\r\n2011-07-22 20:15:01,0.487113274889\r\n2011-07-22 21:15:01,0.446442694765\r\n2011-07-22 22:15:01,0.493629595145\r\n2011-07-22 23:15:01,0.416509432515\r\n2011-07-23 03:15:01,0.471425611142\r\n2011-07-23 05:15:01,0.429440714477\r\n2011-07-23 06:15:01,0.432265331459\r\n2011-07-23 07:15:01,0.454228292268\r\n2011-07-23 08:15:01,0.394017939728\r\n2011-07-23 11:15:01,0.524489350397\r\n2011-07-23 12:15:01,0.634432981899\r\n2011-07-23 13:15:01,1.04193118459\r\n2011-07-23 14:15:01,0.90026207413\r\n2011-07-23 15:15:01,0.801925327328\r\n2011-07-23 16:15:01,0.664488563101\r\n2011-07-23 17:15:01,0.746938916439\r\n2011-07-23 18:15:01,0.58430610608\r\n2011-07-23 19:15:01,0.551052096356\r\n2011-07-23 20:15:01,0.539589028335\r\n2011-07-23 21:15:01,0.458878228066\r\n2011-07-23 22:15:01,0.508391976452\r\n2011-07-23 23:15:01,0.455166495807\r\n2011-07-24 00:15:01,0.354592054203\r\n2011-07-24 01:15:01,0.847647604173\r\n2011-07-24 02:15:01,0.623232870952\r\n2011-07-24 03:15:01,0.454925500145\r\n2011-07-24 04:15:01,0.388240283175\r\n2011-07-24 05:15:01,0.362204837798\r\n2011-07-24 06:15:01,0.38663181282\r\n2011-07-24 07:15:01,0.432720462465\r\n2011-07-24 08:15:01,0.463825888665\r\n2011-07-24 09:15:01,0.5587072312\r\n2011-07-24 10:15:01,0.537009158919\r\n2011-07-24 11:15:01,0.668545698278\r\n2011-07-24 12:15:01,1.00081699346\r\n2011-07-24 13:15:01,0.875236467932\r\n2011-07-24 14:15:01,0.940858277968\r\n2011-07-24 15:15:01,0.528411701639\r\n2011-07-24 16:15:01,0.65468678144\r\n2011-07-24 17:15:01,0.581666157293\r\n2011-07-24 18:15:01,0.514303731701\r\n2011-07-24 19:15:01,0.461928980193\r\n2011-07-24 20:15:01,0.422771996885\r\n2011-07-24 21:15:01,0.411778295097\r\n2011-07-24 22:15:01,0.422908418695\r\n2011-07-24 23:15:01,0.373979374279\r\n2011-07-25 00:15:01,0.392288088245\r\n2011-07-25 01:15:01,0.624979173708\r\n2011-07-25 02:15:01,0.467264498355\r\n2011-07-25 03:15:01,0.491341991342\r\n2011-07-25 04:15:01,0.380918382013\r\n2011-07-25 05:15:01,0.335816771323\r\n2011-07-25 06:15:01,0.39575696898\r\n2011-07-25 07:15:01,0.389068499632\r\n2011-07-25 08:15:01,0.401918936275\r\n2011-07-25 09:15:01,0.560098031871\r\n2011-07-25 10:15:01,0.632278380734\r\n2011-07-25 11:15:01,0.754956701996\r\n2011-07-25 12:15:01,0.956091142046\r\n2011-07-25 13:15:01,0.993110160026\r\n2011-07-25 14:15:01,0.89732544683\r\n2011-07-25 15:15:01,0.677849823197\r\n2011-07-25 16:15:01,0.61280505222\r\n2011-07-25 17:15:01,0.554349758464\r\n2011-07-25 18:15:01,0.455914446791\r\n2011-07-25 19:15:01,0.464386331397\r\n2011-07-25 20:15:01,0.401464711746\r\n2011-07-25 21:15:01,0.359988588258\r\n2011-07-25 22:15:01,0.403315849798\r\n2011-07-25 23:15:01,0.396394253289\r\n2011-07-26 00:15:01,0.345829294262\r\n2011-07-26 01:15:01,0.458796101136\r\n2011-07-26 02:15:01,0.478773805802\r\n2011-07-26 03:15:01,0.398860697414\r\n2011-07-26 04:15:01,0.44840088318\r\n2011-07-26 05:15:01,0.323450423714\r\n2011-07-26 06:15:01,0.365505482974\r\n2011-07-26 07:15:01,0.394108235626\r\n2011-07-26 08:15:01,0.441997940672\r\n2011-07-26 09:15:01,0.524900355719\r\n2011-07-26 10:15:01,0.691827625706\r\n2011-07-26 11:15:01,0.796475686699\r\n2011-07-26 12:15:01,0.843537414966\r\n2011-07-26 13:15:01,0.861174539371\r\n2011-07-26 14:15:01,0.86726415966\r\n2011-07-26 15:15:01,0.541147669817\r\n2011-07-26 16:15:01,0.620446859419\r\n2011-07-26 17:15:01,0.525748138561\r\n2011-07-26 19:15:01,0.484852616211\r\n2011-07-26 20:15:01,0.484225645719\r\n2011-07-26 21:15:01,0.396638624414\r\n2011-07-26 22:15:01,0.422340743999\r\n2011-07-26 23:15:01,0.347862423243\r\n2011-07-27 00:15:01,0.355651253272\r\n2011-07-27 01:15:01,0.472819637318\r\n2011-07-27 02:15:01,0.42465090411\r\n2011-07-27 05:15:01,0.369590666017\r\n2011-07-27 06:15:01,0.341975423207\r\n2011-07-27 07:15:01,0.385071903859\r\n2011-07-27 08:15:01,0.449638417028\r\n2011-07-27 09:15:01,0.485024107731\r\n2011-07-27 10:15:01,0.503880485702\r\n2011-07-27 11:15:01,0.649875468026\r\n2011-07-27 12:15:01,0.900444803882\r\n2011-07-27 13:15:01,0.921812066603\r\n2011-07-27 14:15:01,0.799267434936\r\n2011-07-27 15:15:01,0.5669058795\r\n2011-07-27 16:15:01,0.592411494104\r\n2011-07-27 17:15:01,0.476107270232\r\n2011-07-27 18:15:01,0.491887576287\r\n2011-07-27 19:15:01,0.475071540278\r\n2011-07-27 20:15:01,0.447284149613\r\n2011-07-27 21:15:01,0.478995312103\r\n2011-07-27 22:15:01,0.44316906746\r\n2011-07-27 23:15:01,0.362373551562\r\n2011-07-28 00:15:01,0.353371351895\r\n2011-07-28 01:15:01,0.500298235797\r\n2011-07-28 02:15:01,0.453735304062\r\n2011-07-28 03:15:01,0.444910788743\r\n2011-07-28 04:15:01,0.388427934987\r\n2011-07-28 05:15:01,0.336372101252\r\n2011-07-28 06:15:01,0.356857600543\r\n2011-07-28 07:15:01,0.50117066916\r\n2011-07-28 08:15:01,0.419210640281\r\n2011-07-28 09:15:01,0.606202190542\r\n2011-07-28 10:15:01,0.612685287889\r\n2011-07-28 11:15:01,0.849234393404\r\n2011-07-28 12:15:01,1.19378143801\r\n2011-07-28 13:15:01,0.693728857663\r\n2011-07-28 14:15:01,0.830594474462\r\n2011-07-28 15:15:01,0.642496762959\r\n2011-07-28 16:15:01,0.549461019164\r\n2011-07-28 17:15:01,0.471706205502\r\n2011-07-28 18:15:01,0.523558103174\r\n2011-07-28 19:15:01,0.460153344327\r\n2011-07-28 20:15:01,0.484955907773\r\n2011-07-28 21:15:01,0.515769796423\r\n2011-07-28 22:15:01,0.448284108066\r\n2011-07-28 23:15:01,0.430648577052\r\n2011-07-29 00:15:01,0.428464730929\r\n2011-07-29 01:15:01,0.50383463487\r\n2011-07-29 02:15:01,0.48908390281\r\n2011-07-29 03:15:01,0.430424920234\r\n2011-07-29 04:15:01,0.421459720562\r\n2011-07-29 05:15:01,0.38182361723\r\n2011-07-29 06:15:01,0.414216287201\r\n2011-07-29 07:15:01,0.429408844655\r\n2011-07-29 08:15:01,0.536157500477\r\n2011-07-29 09:15:01,0.72305326685\r\n2011-07-29 10:15:01,0.796266588887\r\n2011-07-29 11:15:01,1.03498390948\r\n2011-07-29 12:15:01,1.10071677602\r\n2011-07-29 13:15:01,0.980824921978\r\n2011-07-29 14:15:01,1.00210466131\r\n2011-07-29 15:15:01,0.734911682259\r\n2011-07-29 16:15:01,0.756412897909\r\n2011-07-29 17:15:01,0.59817101608\r\n2011-07-29 18:15:01,0.673976028606\r\n2011-07-29 19:15:01,0.649754020916\r\n2011-07-29 20:15:01,0.592631426905\r\n2011-07-29 21:15:01,0.65991491423\r\n2011-07-29 22:15:01,0.626581379568\r\n2011-07-29 23:15:01,0.578915126635\r\n2011-07-30 00:15:01,0.608687044547\r\n2011-07-30 01:15:01,0.670799943403\r\n2011-07-30 02:15:01,0.640060585538\r\n2011-07-30 03:15:01,0.659653508315\r\n2011-07-30 04:15:01,0.475267844485\r\n2011-07-30 05:15:01,0.512949516523\r\n2011-07-30 06:15:01,0.524415858356\r\n2011-07-30 07:15:01,0.574065799941\r\n2011-07-30 08:15:01,0.568731977426\r\n2011-07-30 09:15:01,0.644472679623\r\n2011-07-30 10:15:01,0.559871884315\r\n2011-07-30 11:15:01,0.969953850686\r\n2011-07-30 12:15:01,1.07140826653\r\n2011-07-30 13:15:01,1.03096993273\r\n2011-07-30 14:15:01,0.937015144758\r\n2011-07-30 15:15:01,0.819120085845\r\n2011-07-30 16:15:01,0.683689190651\r\n2011-07-30 17:15:01,0.535112398674\r\n2011-07-30 20:15:01,0.576377992756\r\n2011-07-30 21:15:01,0.553529713893\r\n2011-07-30 22:15:01,0.523731134272\r\n2011-07-30 23:15:01,0.51688836525\r\n2011-07-31 00:15:01,0.439294307061\r\n2011-07-31 01:15:01,0.648390249655\r\n2011-07-31 02:15:01,0.581880306629\r\n2011-07-31 04:15:01,0.529118257924\r\n2011-07-31 05:15:01,0.485536149182\r\n2011-07-31 06:15:01,0.500015487422\r\n2011-07-31 07:15:01,0.51460008046\r\n2011-07-31 08:15:01,0.533621281078\r\n2011-07-31 09:15:01,0.682004403246\r\n2011-07-31 10:15:01,0.630815315617\r\n2011-07-31 11:15:01,0.851473399697\r\n2011-07-31 12:15:01,1.02661392802\r\n2011-07-31 13:15:01,1.29937784256\r\n2011-07-31 14:15:01,0.901679325483\r\n2011-07-31 15:15:01,0.832724097616\r\n2011-07-31 16:15:01,0.677929487521\r\n2011-07-31 17:15:01,0.635344512686\r\n2011-07-31 18:15:01,0.541728069495\r\n2011-07-31 19:15:01,0.557364618123\r\n2011-07-31 20:15:01,0.611843812083\r\n2011-07-31 21:15:01,0.523288282779\r\n2011-07-31 23:15:01,0.518364312775\r\n2011-08-01 00:15:01,0.498728225752\r\n2011-08-01 03:15:01,0.576555937381\r\n2011-08-01 05:15:01,0.554290565277\r\n2011-08-01 06:15:01,0.476010861023\r\n2011-08-01 07:15:01,0.449696671034\r\n2011-08-01 08:15:01,0.551743210305\r\n2011-08-01 09:15:01,0.756095103768\r\n2011-08-01 10:15:01,0.734396138798\r\n2011-08-01 11:15:01,0.846458555842\r\n2011-08-01 12:15:01,1.1775573547\r\n2011-08-01 13:15:01,0.780463324214\r\n2011-08-01 14:15:01,1.00941909107\r\n2011-08-01 15:15:01,0.819694770134\r\n2011-08-01 16:15:01,0.764223282266\r\n2011-08-01 17:15:01,0.663092200538\r\n2011-08-01 18:15:01,0.653564393467\r\n2011-08-01 20:15:01,0.577674184768\r\n2011-08-01 21:15:01,0.54488363266\r\n2011-08-01 23:15:01,0.531751330342\r\n2011-08-02 00:15:01,0.574685145904\r\n2011-08-02 01:15:01,0.635687697157\r\n2011-08-02 02:15:01,0.58853026189\r\n2011-08-02 03:15:01,0.466300750966\r\n2011-08-02 05:15:01,0.426776142971\r\n2011-08-02 06:15:01,0.431905267695\r\n2011-08-02 07:15:01,0.486788508189\r\n2011-08-02 08:15:01,0.520916021747\r\n2011-08-02 09:15:01,0.631112923168\r\n2011-08-02 10:15:01,0.787905664181\r\n2011-08-02 11:15:01,1.15101155113\r\n2011-08-02 12:15:01,1.40471250275\r\n2011-08-02 13:15:01,0.919172005914\r\n2011-08-02 14:15:01,0.930289680113\r\n2011-08-02 15:15:01,0.911233169005\r\n2011-08-02 16:15:01,0.562151951525\r\n2011-08-02 18:15:01,0.645033038997\r\n2011-08-02 19:15:01,0.648685752389\r\n2011-08-02 20:15:01,0.541655156634\r\n2011-08-02 21:15:01,0.629047798928\r\n2011-08-02 22:15:01,0.70048738269\r\n2011-08-02 23:15:01,0.53379122543\r\n2011-08-03 00:15:01,0.440444722304\r\n2011-08-03 01:15:01,0.719683930527\r\n2011-08-03 02:15:01,0.710997940534\r\n2011-08-03 03:15:01,0.594979361314\r\n2011-08-03 04:15:01,0.449055478674\r\n2011-08-03 05:15:01,0.477755007181\r\n2011-08-03 06:15:01,0.503697983752\r\n2011-08-03 07:15:01,0.600102091293\r\n2011-08-03 08:15:01,0.561552932585\r\n2011-08-03 09:15:01,0.79419877957\r\n2011-08-03 10:15:01,0.785667933624\r\n2011-08-03 11:15:01,1.13982041415\r\n2011-08-03 12:15:01,1.19103416667\r\n2011-08-03 13:15:01,1.17852075751\r\n2011-08-03 14:15:01,0.75004468933\r\n2011-08-03 15:15:01,0.817874388891\r\n2011-08-03 17:15:01,0.722743200455\r\n2011-08-03 18:15:01,0.584243911365\r\n2011-08-03 19:15:01,0.62690718902\r\n2011-08-03 20:15:01,0.583636953993\r\n2011-08-03 21:15:01,0.638105501939\r\n2011-08-03 22:15:01,0.553943354236\r\n2011-08-03 23:15:01,0.698302566298\r\n2011-08-04 00:15:01,0.585952461824\r\n2011-08-04 01:15:01,0.680807542384\r\n2011-08-04 02:15:01,0.633855601382\r\n2011-08-04 03:15:01,0.820624317284\r\n2011-08-04 04:15:01,0.557292109026\r\n2011-08-04 05:15:01,0.41470422161\r\n2011-08-04 06:15:01,0.525180710389\r\n2011-08-04 07:15:01,0.548682741313\r\n2011-08-04 08:15:01,0.556389097274\r\n2011-08-04 09:15:01,0.671852412749\r\n2011-08-04 10:15:01,0.815993714002\r\n2011-08-04 11:15:01,0.893970122675\r\n2011-08-04 12:15:01,1.08664281817\r\n2011-08-04 13:15:01,1.12298696319\r\n2011-08-04 14:15:01,0.95005399809\r\n2011-08-04 16:15:01,0.715950660979\r\n2011-08-04 17:15:01,0.795825740766\r\n2011-08-04 18:15:01,0.647634508959\r\n2011-08-04 19:15:01,0.555697769319\r\n2011-08-04 20:15:01,1.42072295982\r\n2011-08-04 21:15:01,0.592265160479\r\n2011-08-04 22:15:01,0.568243786567\r\n2011-08-04 23:15:01,0.604767739087\r\n2011-08-05 00:15:01,0.555048814747\r\n2011-08-05 01:15:01,0.686409550046\r\n2011-08-05 02:15:01,0.664502043993\r\n2011-08-05 03:15:01,0.751783059049\r\n2011-08-05 04:15:01,0.536707916534\r\n2011-08-05 05:15:01,0.584625706011\r\n2011-08-05 06:15:01,0.543533656374\r\n2011-08-05 07:15:01,0.541778547457\r\n2011-08-05 08:15:01,0.611421644746\r\n2011-08-05 09:15:01,0.726964468474\r\n2011-08-05 10:15:01,0.802952723852\r\n2011-08-05 11:15:01,1.0420973625\r\n2011-08-05 12:15:01,1.05794478293\r\n2011-08-05 13:15:01,1.14759081927\r\n2011-08-05 14:15:01,0.995947810883\r\n2011-08-05 15:15:01,0.837924146178\r\n2011-08-05 17:15:01,0.639849442198\r\n2011-08-05 19:15:01,0.676064732772\r\n2011-08-05 20:15:01,0.543911542172\r\n2011-08-05 21:15:01,0.577292345427\r\n2011-08-05 22:15:01,0.543720793978\r\n2011-08-05 23:15:01,0.574428235604\r\n2011-08-06 00:15:01,0.536694938229\r\n2011-08-06 01:15:01,0.721242372337\r\n2011-08-06 02:15:01,0.719180486143\r\n2011-08-06 03:15:01,0.664986357941\r\n2011-08-06 04:15:01,0.675107829796\r\n2011-08-06 05:15:01,0.568417908432\r\n2011-08-06 06:15:01,0.560745261334\r\n2011-08-06 07:15:01,0.589784142503\r\n2011-08-06 08:15:01,0.675166106392\r\n2011-08-06 09:15:01,0.713929339861\r\n2011-08-06 10:15:01,0.720525247971\r\n2011-08-06 11:15:01,0.973101693998\r\n2011-08-06 12:15:01,1.04109900091\r\n2011-08-06 13:15:01,1.10076528064\r\n2011-08-06 15:15:01,0.858281143262\r\n2011-08-06 16:15:01,0.718258734174\r\n2011-08-06 17:15:01,0.652482726953\r\n2011-08-06 18:15:01,0.603126873225\r\n2011-08-06 19:15:01,0.615980506115\r\n2011-08-06 20:15:01,0.518617271676\r\n2011-08-06 21:15:01,0.612084186098\r\n2011-08-06 22:15:01,0.6041011793\r\n2011-08-06 23:15:01,0.519409820872\r\n2011-08-07 00:15:01,0.635188073777\r\n2011-08-07 01:15:01,0.68608152933\r\n2011-08-07 02:15:01,0.609118718996\r\n2011-08-07 03:15:01,0.582622271093\r\n2011-08-07 04:15:01,0.598422475252\r\n2011-08-07 05:15:01,0.561157963103\r\n2011-08-07 06:15:01,0.593355289604\r\n2011-08-07 07:15:01,0.623050235785\r\n2011-08-07 08:15:01,0.687373850639\r\n2011-08-07 09:15:01,0.665167658556\r\n2011-08-07 10:15:01,0.849833024706\r\n2011-08-07 11:15:01,0.946772757303\r\n2011-08-07 12:15:01,1.05214350573\r\n2011-08-07 13:15:01,1.49678514312\r\n2011-08-07 14:15:01,0.867744078979\r\n2011-08-07 15:15:01,0.819632696943\r\n2011-08-07 16:15:01,0.74004421129\r\n2011-08-07 17:15:01,0.705276178788\r\n2011-08-07 18:15:01,0.648443555101\r\n2011-08-07 19:15:01,0.55609604234\r\n2011-08-07 20:15:01,0.624781661692\r\n2011-08-07 21:15:01,0.605392560095\r\n2011-08-07 22:15:01,0.568348885355\r\n2011-08-07 23:15:01,0.548749163255\r\n2011-08-08 00:15:01,0.606434621799\r\n2011-08-08 01:15:01,0.646378233592\r\n2011-08-08 02:15:01,0.580301698869\r\n2011-08-08 03:15:01,0.565836250493\r\n2011-08-08 04:15:01,0.569189356342\r\n2011-08-08 05:15:01,0.538710969129\r\n2011-08-08 06:15:01,0.513768455929\r\n2011-08-08 07:15:01,0.559171613811\r\n2011-08-08 08:15:01,0.575195729644\r\n2011-08-08 09:15:01,0.652947245764\r\n2011-08-08 10:15:01,0.74503888758\r\n2011-08-08 11:15:01,0.857579554687\r\n2011-08-08 12:15:01,0.875553118504\r\n2011-08-08 13:15:01,0.854941413658\r\n2011-08-08 14:15:01,0.790767678673\r\n2011-08-08 16:15:01,0.712741698358\r\n2011-08-08 17:15:01,0.615699781863\r\n2011-08-08 18:15:01,0.595200849764\r\n2011-08-08 19:15:01,0.634719459996\r\n2011-08-08 20:15:01,0.547550792253\r\n2011-08-08 21:15:01,0.590809094235\r\n2011-08-08 22:15:01,0.570679942692\r\n2011-08-08 23:15:01,0.54153421526\r\n2011-08-09 00:15:01,0.536134186043\r\n2011-08-09 01:15:01,0.58694728119\r\n2011-08-09 02:15:01,0.599060021738\r\n2011-08-09 03:15:01,0.578157413533\r\n2011-08-09 04:15:01,0.50181775834\r\n2011-08-09 05:15:01,0.518201067593\r\n2011-08-09 06:15:01,0.511505673511\r\n2011-08-09 07:15:01,0.597075586726\r\n2011-08-09 08:15:01,0.598728666922\r\n2011-08-09 09:15:01,0.783646778861\r\n2011-08-09 10:15:01,0.788622722111\r\n2011-08-09 11:15:01,0.86311824481\r\n2011-08-09 12:15:01,1.27301519137\r\n2011-08-09 14:15:01,0.88404025791\r\n2011-08-09 15:15:01,0.802570074162\r\n2011-08-09 16:15:01,0.723815454876\r\n2011-08-09 17:15:01,0.661586612293\r\n2011-08-09 18:15:01,0.617642290617\r\n2011-08-09 19:15:01,0.629898957434\r\n2011-08-09 20:15:01,0.601685026205\r\n2011-08-09 21:15:01,0.645256582208\r\n2011-08-09 22:15:01,0.590185964475\r\n2011-08-09 23:15:01,0.620264322455\r\n2011-08-10 00:15:01,0.559184359065\r\n2011-08-10 01:15:01,0.590161480456\r\n2011-08-10 02:15:01,0.591462623116\r\n2011-08-10 03:15:01,0.642369010583\r\n2011-08-10 04:15:01,0.520049263822\r\n2011-08-10 05:15:01,0.502427012098\r\n2011-08-10 06:15:01,0.504466919255\r\n2011-08-10 07:15:01,0.50623672691\r\n2011-08-10 08:15:01,0.547044702758\r\n2011-08-10 09:15:01,0.624164877273\r\n2011-08-10 10:15:01,0.821473591903\r\n2011-08-10 11:15:01,0.962219823481\r\n2011-08-10 12:15:01,1.13254543144\r\n2011-08-10 13:15:01,0.946045959158\r\n2011-08-10 15:15:01,0.983489745003\r\n2011-08-10 17:15:01,0.82094562393\r\n2011-08-10 18:15:01,0.730903856743\r\n2011-08-10 19:15:01,0.625206071634\r\n2011-08-10 20:15:01,0.731170579564\r\n2011-08-10 21:15:01,0.676400974391\r\n2011-08-10 23:15:01,0.660492954703\r\n2011-08-11 00:15:01,0.554590237895\r\n2011-08-11 01:15:01,0.715748968801\r\n2011-08-11 02:15:01,0.552449342809\r\n2011-08-11 03:15:01,0.608818563823\r\n2011-08-11 04:15:01,0.56535245238\r\n2011-08-11 05:15:01,0.545612490685\r\n2011-08-11 06:15:01,0.521651179882\r\n2011-08-11 07:15:01,0.577066436906\r\n2011-08-11 08:15:01,0.649319201432\r\n2011-08-11 09:15:01,0.761580436424\r\n2011-08-11 10:15:01,0.958909403592\r\n2011-08-11 11:15:01,0.879025593085\r\n2011-08-11 12:15:01,1.02881514616\r\n2011-08-11 14:15:01,1.12794638303\r\n2011-08-11 15:15:01,0.806395267298\r\n2011-08-11 16:15:01,0.998546127412\r\n2011-08-11 17:15:01,0.797586425481\r\n2011-08-11 18:15:01,0.653892646469\r\n2011-08-11 19:15:01,0.668489407469\r\n2011-08-11 20:15:01,0.704774059598\r\n2011-08-11 21:15:01,0.618160741346\r\n2011-08-11 22:15:01,0.703522679277\r\n2011-08-11 23:15:01,0.645565581113\r\n2011-08-12 00:15:01,0.641368766824\r\n2011-08-12 01:15:01,0.705282913257\r\n2011-08-12 02:15:01,0.612891663325\r\n2011-08-12 03:15:01,0.59561723886\r\n2011-08-12 04:15:01,0.397505242902\r\n2011-08-12 05:15:01,0.4334602526\r\n2011-08-12 06:15:01,0.452638011815\r\n2011-08-12 07:15:01,0.554466657955\r\n2011-08-12 08:15:01,0.762423745569\r\n2011-08-12 09:15:01,0.743389683572\r\n2011-08-12 10:15:01,1.2398054085\r\n2011-08-12 11:15:01,1.24785288471\r\n2011-08-12 13:15:01,1.56976504958\r\n2011-08-12 14:15:01,1.30445869153\r\n2011-08-12 15:15:01,0.913389056971\r\n2011-08-12 16:15:01,0.797229088648\r\n2011-08-12 17:15:01,0.588670630441\r\n2011-08-12 18:15:01,0.621693121693\r\n2011-08-12 19:15:01,0.561822051743\r\n2011-08-12 21:15:01,0.586936754634\r\n2011-08-12 22:15:01,0.510457600443\r\n2011-08-12 23:15:01,0.411906443438\r\n2011-08-13 00:15:01,0.481140662888\r\n2011-08-13 01:15:01,0.727249846188\r\n2011-08-13 02:15:01,0.692740174194\r\n2011-08-13 03:15:01,0.606669069316\r\n2011-08-13 04:15:01,0.481597592012\r\n2011-08-13 05:15:01,0.452214871573\r\n2011-08-13 06:15:01,0.503423930085\r\n2011-08-13 07:15:01,0.592080023871\r\n2011-08-13 08:15:01,0.670440067671\r\n2011-08-13 09:15:01,0.781322734271\r\n2011-08-13 10:15:01,1.12155162029\r\n2011-08-13 11:15:01,1.14461358314\r\n2011-08-13 12:15:01,2.3458511804\r\n2011-08-13 13:15:01,1.78017877028\r\n2011-08-13 15:15:01,1.16344626108\r\n2011-08-13 17:15:01,0.80366590851\r\n2011-08-13 18:15:01,0.835319293809\r\n2011-08-13 19:15:01,0.61608130586\r\n2011-08-13 20:15:01,0.551187458629\r\n2011-08-13 21:15:01,0.496627535469\r\n2011-08-13 22:15:01,0.471666183154\r\n2011-08-13 23:15:01,0.646252600178\r\n2011-08-14 00:15:01,0.610524145889\r\n2011-08-14 01:15:01,0.740457772665\r\n2011-08-14 02:15:01,0.67648312914\r\n2011-08-14 03:15:01,0.6999543225\r\n2011-08-14 04:15:01,0.581878572182\r\n2011-08-14 05:15:01,0.574517129817\r\n2011-08-14 06:15:01,0.588103546132\r\n2011-08-14 07:15:01,0.682825589466\r\n2011-08-14 08:15:01,0.702503350973\r\n2011-08-14 09:15:01,0.811665071193\r\n2011-08-14 10:15:01,0.959159638626\r\n2011-08-14 11:15:01,1.13891248326\r\n2011-08-14 12:15:01,1.31995254103\r\n2011-08-14 13:15:01,1.14913574749\r\n2011-08-14 14:15:01,1.17398097723\r\n2011-08-14 15:15:01,0.910558605102\r\n2011-08-14 16:15:01,0.786068674769\r\n2011-08-14 17:15:01,0.809601949747\r\n2011-08-14 18:15:01,0.755417840119\r\n2011-08-14 19:15:01,0.749192553692\r\n2011-08-14 20:15:01,0.665563624108\r\n2011-08-14 21:15:01,0.721558658688\r\n2011-08-14 22:15:01,0.685192621577\r\n2011-08-14 23:15:01,0.557077450057\r\n2011-08-15 01:15:01,0.636081308305\r\n2011-08-15 02:15:01,0.667131109384\r\n2011-08-15 03:15:01,0.735076057078\r\n2011-08-15 04:15:01,0.580668384959\r\n2011-08-15 05:15:01,0.579281629473\r\n2011-08-15 06:15:01,0.602451454238\r\n2011-08-15 07:15:01,0.644382914486\r\n2011-08-15 08:15:01,0.714276606054\r\n2011-08-15 09:15:01,0.848933518167\r\n2011-08-15 10:15:01,0.966559247715\r\n2011-08-15 11:15:01,1.05050887436\r\n2011-08-15 12:15:01,1.04251488078\r\n2011-08-15 14:15:01,0.932878270762\r\n2011-08-15 15:15:01,0.826720919972\r\n2011-08-15 16:15:01,0.776904573404\r\n2011-08-15 17:15:01,0.716201992703\r\n2011-08-15 18:15:01,0.711605913562\r\n2011-08-15 19:15:01,0.708530490055\r\n2011-08-15 20:15:01,0.663736975075\r\n2011-08-15 21:15:01,0.622400018566\r\n2011-08-15 22:15:01,0.607611681058\r\n2011-08-15 23:15:01,0.611072281173\r\n2011-08-16 00:15:01,0.563604798437\r\n2011-08-16 01:15:01,0.686922142397\r\n2011-08-16 02:15:01,0.675897036319\r\n2011-08-16 03:15:01,0.667313844917\r\n2011-08-16 04:15:01,0.628226199954\r\n2011-08-16 05:15:01,0.595912441675\r\n2011-08-16 06:15:01,0.634416844861\r\n2011-08-16 07:15:01,0.685898336104\r\n2011-08-16 08:15:01,0.826101318279\r\n2011-08-16 09:15:01,0.892529350396\r\n2011-08-16 10:15:01,1.12081818742\r\n2011-08-16 11:15:01,1.12547861639\r\n2011-08-16 12:15:01,1.12175474239\r\n2011-08-16 13:15:01,1.05128934078\r\n2011-08-16 14:15:01,0.966681309319\r\n2011-08-16 15:15:01,0.990511125266\r\n2011-08-16 16:15:01,0.879749252927\r\n2011-08-16 17:15:01,0.714478939876\r\n2011-08-16 18:15:01,0.877238546553\r\n2011-08-16 19:15:01,0.725744019401\r\n2011-08-16 20:15:01,0.761700055415\r\n2011-08-16 21:15:01,0.714732926186\r\n2011-08-16 22:15:01,0.676804863428\r\n2011-08-16 23:15:01,0.711416021227\r\n2011-08-17 00:15:01,0.607743520633\r\n2011-08-17 01:15:01,0.736028088655\r\n2011-08-17 02:15:01,0.66488033209\r\n2011-08-17 03:15:01,0.619237027662\r\n2011-08-17 04:15:01,0.550742015432\r\n2011-08-17 05:15:01,0.555550082264\r\n2011-08-17 06:15:01,0.616679440644\r\n2011-08-17 07:15:01,0.693236714976\r\n2011-08-17 08:15:01,0.810488810541\r\n2011-08-17 09:15:01,0.932629669333\r\n2011-08-17 10:15:01,1.10551712253\r\n2011-08-17 11:15:01,1.24432225675\r\n2011-08-17 12:15:01,1.07751682008\r\n2011-08-17 13:15:01,0.993365801281\r\n2011-08-17 14:15:01,1.03636422863\r\n2011-08-17 15:15:01,0.927039239851\r\n2011-08-17 16:15:01,0.821436448207\r\n2011-08-17 18:15:01,0.762617399275\r\n2011-08-17 19:15:01,0.714061062878\r\n2011-08-17 20:15:01,0.735661201354\r\n2011-08-17 21:15:01,0.666658952973\r\n2011-08-17 22:15:01,0.621769977351\r\n2011-08-17 23:15:01,0.548446739751\r\n2011-08-18 00:15:01,0.544978141492\r\n2011-08-18 01:15:01,0.758639317537\r\n2011-08-18 02:15:01,0.732381898533\r\n2011-08-18 03:15:01,0.570647047727\r\n2011-08-18 04:15:01,0.534028307408\r\n2011-08-18 05:15:01,0.542765533075\r\n2011-08-18 06:15:01,0.567515064457\r\n2011-08-18 07:15:01,0.683516370065\r\n2011-08-18 08:15:01,0.718008272579\r\n2011-08-18 09:15:01,0.936216066342\r\n2011-08-18 10:15:01,0.977670956737\r\n2011-08-18 11:15:01,0.953869233654\r\n2011-08-18 12:15:01,0.958412841486\r\n2011-08-18 13:15:01,0.982262310647\r\n2011-08-18 14:15:01,0.944170398835\r\n2011-08-18 15:15:01,0.712214878216\r\n2011-08-18 16:15:01,0.779245317679\r\n2011-08-18 18:15:01,0.770476887313\r\n2011-08-18 20:15:01,0.772785581145\r\n2011-08-18 21:15:01,0.792569185776\r\n2011-08-18 22:15:01,0.892232194744\r\n2011-08-18 23:15:01,0.928590112477\r\n2011-08-19 00:15:01,0.809001110711\r\n2011-08-19 01:15:01,0.773142351037\r\n2011-08-19 02:15:01,0.68364500895\r\n2011-08-19 03:15:01,0.666356498685\r\n2011-08-19 04:15:01,0.602663491936\r\n2011-08-19 05:15:01,0.615586216743\r\n2011-08-19 06:15:01,0.680106983428\r\n2011-08-19 07:15:01,0.715438473764\r\n2011-08-19 08:15:01,0.778365849468\r\n2011-08-19 09:15:01,0.940738025415\r\n2011-08-19 10:15:01,1.06431149513\r\n2011-08-19 11:15:01,1.03322345475\r\n2011-08-19 12:15:01,1.06920531499\r\n2011-08-19 13:15:01,0.90248188841\r\n2011-08-19 14:15:01,0.948048756512\r\n2011-08-19 15:15:01,0.940754216038\r\n2011-08-19 16:15:01,0.934222809879\r\n2011-08-19 18:15:01,5.49754000266\r\n2011-08-19 19:15:01,0.863326087315\r\n2011-08-19 20:15:01,0.703298738091\r\n2011-08-19 21:15:01,0.713623326394\r\n2011-08-19 22:15:01,0.654695043258\r\n2011-08-19 23:15:01,0.674132038136\r\n2011-08-20 00:15:01,0.662703093534\r\n2011-08-20 01:15:01,0.794094232044\r\n2011-08-20 02:15:01,0.682984438197\r\n2011-08-20 03:15:01,0.668096114705\r\n2011-08-20 04:15:01,0.644444815845\r\n2011-08-20 05:15:01,0.631821336803\r\n2011-08-20 06:15:01,0.664079704752\r\n2011-08-20 07:15:01,0.691809112522\r\n2011-08-20 08:15:01,0.731047520971\r\n2011-08-20 09:15:01,0.916183652659\r\n2011-08-20 10:15:01,1.12615701063\r\n2011-08-20 11:15:01,1.37892666256\r\n2011-08-20 12:15:01,1.48058619127\r\n2011-08-20 13:15:01,1.11576620573\r\n2011-08-20 14:15:01,1.10130283386\r\n2011-08-20 15:15:01,0.917978202373\r\n2011-08-20 16:15:01,0.868671626148\r\n2011-08-20 17:15:01,0.804527172255\r\n2011-08-20 18:15:01,0.745593099694\r\n2011-08-20 19:15:01,0.693628880174\r\n2011-08-20 20:15:01,0.713280266363\r\n2011-08-20 21:15:01,0.69452314481\r\n2011-08-20 22:15:01,0.676418731136\r\n2011-08-20 23:15:01,0.705210678675\r\n2011-08-21 00:15:01,0.693664559433\r\n2011-08-21 01:15:01,0.741737529738\r\n2011-08-21 02:15:01,0.740867235598\r\n2011-08-21 03:15:01,0.755155629406\r\n2011-08-21 04:15:01,0.663611083149\r\n2011-08-21 05:15:01,0.645370135798\r\n2011-08-21 06:15:01,0.649619761544\r\n2011-08-21 07:15:01,0.70872257412\r\n2011-08-21 08:15:01,0.692568813021\r\n2011-08-21 09:15:01,0.739975603038\r\n2011-08-21 10:15:01,1.07428499644\r\n2011-08-21 11:15:01,1.29783044803\r\n2011-08-21 12:15:01,1.18176109093\r\n2011-08-21 13:15:01,1.29187384737\r\n2011-08-21 15:15:01,0.937208385358\r\n2011-08-21 16:15:01,0.91911195455\r\n2011-08-21 17:15:01,0.755583102096\r\n2011-08-21 18:15:01,0.745270462145\r\n2011-08-21 19:15:01,0.710554099813\r\n2011-08-21 20:15:01,0.658328261736\r\n2011-08-21 21:15:01,0.724803116745\r\n2011-08-21 22:15:01,0.705354280218\r\n2011-08-21 23:15:01,0.689806462107\r\n2011-08-22 00:15:01,0.60689583826\r\n2011-08-22 01:15:01,0.651337689557\r\n2011-08-22 02:15:01,0.62934487776\r\n2011-08-22 03:15:01,0.62372916466\r\n2011-08-22 04:15:01,0.577398944823\r\n2011-08-22 05:15:01,0.572886854195\r\n2011-08-22 06:15:01,0.594058752156\r\n2011-08-22 07:15:01,0.582907570831\r\n2011-08-22 08:15:01,0.734216695443\r\n2011-08-22 09:15:01,0.806454982244\r\n2011-08-22 10:15:01,0.969068717606\r\n2011-08-22 11:15:01,0.849613756806\r\n2011-08-22 12:15:01,0.890577507599\r\n2011-08-22 13:15:01,0.972369871643\r\n2011-08-22 15:15:01,0.830408286317\r\n2011-08-22 16:15:01,0.790874543276\r\n2011-08-22 17:15:01,0.868033239748\r\n2011-08-22 18:15:01,0.753268013611\r\n2011-08-22 19:15:01,0.75341096872\r\n2011-08-22 20:15:01,0.723666685969\r\n2011-08-22 21:15:01,0.641627543036\r\n2011-08-22 22:15:01,0.793713273077\r\n2011-08-22 23:15:01,0.778934874729\r\n2011-08-23 00:15:01,0.710999652634\r\n2011-08-23 01:15:01,0.703201657157\r\n2011-08-23 02:15:01,0.669306023229\r\n2011-08-23 03:15:01,0.623246944026\r\n2011-08-23 04:15:01,0.59842770237\r\n2011-08-23 05:15:01,0.618625761565\r\n2011-08-23 06:15:01,0.673907341691\r\n2011-08-23 07:15:01,0.776481358143\r\n2011-08-23 08:15:01,0.904231856983\r\n2011-08-23 09:15:01,1.29383792352\r\n2011-08-23 10:15:01,1.13551430877\r\n2011-08-23 11:15:01,1.0251356609\r\n2011-08-23 12:15:01,1.18905411994\r\n2011-08-23 13:15:01,1.27127243107\r\n2011-08-23 14:15:01,1.15911742747\r\n2011-08-23 16:15:01,1.05845536275\r\n2011-08-23 17:15:01,0.926634493627\r\n2011-08-23 18:15:01,0.776918970136\r\n2011-08-23 19:15:01,0.928010146312\r\n2011-08-23 20:15:01,0.838158380029\r\n2011-08-23 21:15:01,0.819862464009\r\n2011-08-23 22:15:01,0.69970306261\r\n2011-08-23 23:15:01,0.842383353699\r\n2011-08-24 00:15:01,0.792468794781\r\n2011-08-24 01:15:01,0.713359095889\r\n2011-08-24 02:15:01,0.704135949192\r\n2011-08-24 03:15:01,0.641155335986\r\n2011-08-24 04:15:01,0.634568795601\r\n2011-08-24 05:15:01,0.645873833534\r\n2011-08-24 06:15:01,0.6590434368\r\n2011-08-24 07:15:01,0.812906195196\r\n2011-08-24 08:15:01,0.881111571307\r\n2011-08-24 09:15:01,1.24918386562\r\n2011-08-24 10:15:01,1.36501420903\r\n2011-08-24 11:15:01,1.95241011285\r\n2011-08-24 12:15:01,1.54697912263\r\n2011-08-24 13:15:01,1.5651661815\r\n2011-08-24 15:15:01,1.22446525543\r\n2011-08-24 16:15:01,1.1562087199\r\n2011-08-24 17:15:01,1.33774834437\r\n2011-08-24 18:15:01,1.03148188994\r\n2011-08-24 19:15:01,0.935049971832\r\n2011-08-24 20:15:01,0.711196895617\r\n2011-08-24 21:15:01,0.767570958313\r\n2011-08-24 22:15:01,0.735954907513\r\n2011-08-24 23:15:01,0.77345193875\r\n2011-08-25 00:15:01,0.692628331902\r\n2011-08-25 01:15:01,0.824416895061\r\n2011-08-25 02:15:01,0.730707604827\r\n2011-08-25 03:15:01,0.715088082545\r\n2011-08-25 04:15:01,0.744875421318\r\n2011-08-25 05:15:01,0.737488743085\r\n2011-08-25 06:15:01,0.717183548371\r\n2011-08-25 07:15:01,0.833624102622\r\n2011-08-25 08:15:01,0.953373503323\r\n2011-08-25 09:15:01,1.31115307189\r\n2011-08-25 10:15:01,1.16843727867\r\n2011-08-25 11:15:01,1.0374018924\r\n2011-08-25 12:15:01,1.07353824758\r\n2011-08-25 13:15:01,1.18426544594\r\n2011-08-25 15:15:01,0.81995711885\r\n2011-08-25 16:15:01,1.08679580518\r\n2011-08-25 17:15:01,1.2173424085\r\n2011-08-25 18:15:01,1.00456228294\r\n2011-08-25 19:15:01,1.03477665107\r\n2011-08-25 20:15:01,0.948686262348\r\n2011-08-25 21:15:01,0.993665532552\r\n2011-08-25 22:15:01,0.903960473484\r\n2011-08-25 23:15:01,0.788313159199\r\n2011-08-26 00:15:01,0.798556558757\r\n2011-08-26 01:15:01,0.734166131373\r\n2011-08-26 02:15:01,0.742638615815\r\n2011-08-26 03:15:01,0.675874389581\r\n2011-08-26 04:15:01,0.705817989883\r\n2011-08-26 05:15:01,0.727232396299\r\n2011-08-26 06:15:01,0.753356912152\r\n2011-08-26 07:15:01,0.875354972671\r\n2011-08-26 08:15:01,0.925335068588\r\n2011-08-26 10:15:01,1.19420541076\r\n2011-08-26 11:15:01,0.851330505206\r\n2011-08-26 12:15:01,1.31130509932\r\n2011-08-26 13:15:01,1.18812702098\r\n2011-08-26 14:15:01,1.10183903133\r\n2011-08-26 15:15:01,1.05379013513\r\n2011-08-26 16:15:01,1.07217664514\r\n2011-08-26 17:15:01,0.789734929311\r\n2011-08-26 18:15:01,0.890166131849\r\n2011-08-26 19:15:01,0.920508307487\r\n2011-08-26 20:15:01,0.950929806345\r\n2011-08-26 21:15:01,0.822102406411\r\n2011-08-26 22:15:01,0.826540433576\r\n2011-08-26 23:15:01,0.791927711761\r\n2011-08-27 00:15:01,0.702807204893\r\n2011-08-27 01:15:01,0.864523887721\r\n2011-08-27 02:15:01,0.809851903585\r\n2011-08-27 03:15:01,0.758690430787\r\n2011-08-27 04:15:01,0.80677831628\r\n2011-08-27 05:15:01,0.688049770453\r\n2011-08-27 06:15:01,0.81968980524\r\n2011-08-27 07:15:01,0.821442694794\r\n2011-08-27 08:15:01,1.06152614064\r\n2011-08-27 09:15:01,1.44317491332\r\n2011-08-27 10:15:01,1.22704597643\r\n2011-08-27 11:15:01,1.58093752585\r\n2011-08-27 12:15:01,1.51858142365\r\n2011-08-27 13:15:01,1.06284454245\r\n2011-08-27 14:15:01,1.29828215868\r\n2011-08-27 15:15:01,1.17357031987\r\n2011-08-27 16:15:01,0.938417521965\r\n2011-08-27 17:15:01,0.719759087413\r\n2011-08-27 18:15:01,0.793253640139\r\n2011-08-27 19:15:01,0.821043529075\r\n2011-08-27 20:15:01,0.77728705129\r\n2011-08-27 21:15:01,0.761011905195\r\n2011-08-27 22:15:01,0.794456554147\r\n2011-08-27 23:15:01,0.71510777014\r\n2011-08-28 00:15:01,0.670100640381\r\n2011-08-28 01:15:01,0.54761579658\r\n2011-08-28 17:15:01,0.849284090378\r\n2011-08-28 18:15:01,0.852476609926\r\n2011-08-28 19:15:01,0.805305280552\r\n2011-08-28 20:15:01,0.889728282553\r\n2011-08-28 21:15:01,0.778613508361\r\n2011-08-28 22:15:01,0.685767835952\r\n2011-08-28 23:15:01,0.726981575893\r\n2011-08-29 00:15:01,0.645975352581\r\n2011-08-29 01:15:01,0.777534142894\r\n2011-08-29 02:15:01,0.723113114405\r\n2011-08-29 03:15:01,0.831905214884\r\n2011-08-29 04:15:01,0.674230251552\r\n2011-08-29 05:15:01,0.71415081987\r\n2011-08-29 06:15:01,0.795823883546\r\n2011-08-29 07:15:01,0.853323981424\r\n2011-08-29 08:15:01,1.03638510945\r\n2011-08-29 09:15:01,1.16972027756\r\n2011-08-29 10:15:01,1.37015829137\r\n2011-08-29 11:15:01,1.19479416172\r\n2011-08-29 12:15:01,1.50872750294\r\n2011-08-29 13:15:01,1.25480461243\r\n2011-08-29 14:15:01,1.18351258787\r\n2011-08-29 15:15:01,0.838183770344\r\n2011-08-29 16:15:01,1.05843861494\r\n2011-08-29 17:15:01,1.1154608336\r\n2011-08-29 18:15:01,0.87860810131\r\n2011-08-29 19:15:01,1.09936880724\r\n2011-08-29 20:15:01,0.87085318709\r\n2011-08-29 21:15:01,0.843596628444\r\n2011-08-29 22:15:01,0.777040471902\r\n2011-08-29 23:15:01,0.688557936796\r\n2011-08-30 00:15:01,0.697836804319\r\n2011-08-30 01:15:01,0.771217121712\r\n2011-08-30 02:15:01,0.694660626848\r\n2011-08-30 03:15:01,0.786323057256\r\n2011-08-30 04:15:01,0.654660190687\r\n2011-08-30 05:15:01,0.72306000212\r\n2011-08-30 06:15:01,0.774674210709\r\n2011-08-30 07:15:01,0.884858627959\r\n2011-08-30 08:15:01,1.08493710832\r\n2011-08-30 09:15:01,1.14704937346\r\n2011-08-30 10:15:01,1.40645395214\r\n2011-08-30 11:15:01,0.967981387104\r\n2011-08-30 12:15:01,1.75374564605\r\n2011-08-30 13:15:01,1.22262717456\r\n2011-08-30 15:15:01,1.2477794358\r\n2011-08-30 16:15:01,1.04428573933\r\n2011-08-30 17:15:01,0.924926251082\r\n2011-08-30 18:15:01,1.20389636883\r\n2011-08-30 19:15:01,0.936448977169\r\n2011-08-30 21:15:01,0.869768173712\r\n2011-08-30 22:15:01,0.820539262738\r\n2011-08-30 23:15:01,0.855369516046\r\n2011-08-31 00:15:01,0.961147001986\r\n2011-08-31 01:15:01,0.958316270557\r\n2011-08-31 02:15:01,0.814787274063\r\n2011-08-31 03:15:01,0.771593377122\r\n2011-08-31 04:15:01,0.766299657727\r\n2011-08-31 05:15:01,0.724229465703\r\n2011-08-31 06:15:01,0.792862195384\r\n2011-08-31 07:15:01,0.942622099425\r\n2011-08-31 08:15:01,1.14142180366\r\n2011-08-31 09:15:01,1.50385784428\r\n2011-08-31 10:15:01,1.32986869524\r\n2011-08-31 11:15:01,1.35511366926\r\n2011-08-31 12:15:01,1.30690884147\r\n2011-08-31 13:15:01,1.36129882778\r\n2011-08-31 14:15:01,1.26118176226\r\n2011-08-31 15:15:01,1.29325090898\r\n2011-08-31 16:15:01,1.13162826786\r\n2011-08-31 17:15:01,0.878180273521\r\n2011-08-31 19:15:01,1.00724076188\r\n2011-08-31 20:15:01,0.82977849928\r\n2011-08-31 21:15:01,0.791770492231\r\n2011-08-31 22:15:01,0.776412218566\r\n2011-08-31 23:15:01,1.01967346467\r\n2011-09-01 00:15:01,0.672524767707\r\n2011-09-01 01:15:01,0.805459791968\r\n2011-09-01 02:15:01,0.697760708058\r\n2011-09-01 03:15:01,0.671198221878\r\n2011-09-01 04:15:01,0.686612619056\r\n2011-09-01 05:15:01,0.730138629699\r\n2011-09-01 06:15:01,0.773151750973\r\n2011-09-01 07:15:01,0.920818621438\r\n2011-09-01 08:15:01,1.05974998234\r\n2011-09-01 09:15:01,1.25720738674\r\n2011-09-01 10:15:01,1.69107806691\r\n2011-09-01 13:15:01,1.38872596255\r\n2011-09-01 18:15:01,1.18474325929\r\n2011-09-01 19:15:01,1.00755614801\r\n2011-09-01 20:15:01,0.889925459781\r\n2011-09-01 21:15:01,0.879357863581\r\n2011-09-01 22:15:01,0.813560856853\r\n2011-09-01 23:15:01,0.668334950547\r\n2011-09-02 00:15:01,0.634700519233\r\n2011-09-02 01:15:01,0.710229977153\r\n2011-09-02 02:15:01,0.697412833033\r\n2011-09-02 03:15:01,0.725219217625\r\n2011-09-02 04:15:01,0.60871199833\r\n2011-09-02 05:15:01,0.636974122101\r\n2011-09-02 06:15:01,0.841129477074\r\n2011-09-02 07:15:01,0.771209479568\r\n2011-09-02 08:15:01,1.02627235945\r\n2011-09-02 09:15:01,1.38391615999\r\n2011-09-02 10:15:01,1.70182048664\r\n2011-09-02 11:15:01,1.30911498665\r\n2011-09-02 12:15:01,1.44916720916\r\n2011-09-02 13:15:01,1.10994932226\r\n2011-09-02 14:15:01,1.20104749435\r\n2011-09-02 15:15:01,1.00461581227\r\n2011-09-02 16:15:01,1.24974971635\r\n2011-09-02 17:15:01,0.930537334322\r\n2011-09-02 18:15:01,0.696674235341\r\n2011-09-02 19:15:01,1.90695503664\r\n2011-09-02 20:15:01,1.14246709184\r\n2011-09-02 21:15:01,1.11277858928\r\n2011-09-02 22:15:01,0.694990722636\r\n2011-09-02 23:15:01,1.1243682849\r\n2011-09-03 00:15:01,1.63223166525\r\n2011-09-03 01:15:01,1.12621421132\r\n2011-09-03 02:15:01,1.22375614029\r\n2011-09-03 03:15:01,0.836308743265\r\n2011-09-03 04:15:01,0.764508533837\r\n2011-09-03 05:15:01,0.824846108339\r\n2011-09-03 06:15:01,0.858898956181\r\n2011-09-03 07:15:01,1.06302492473\r\n2011-09-03 08:15:01,1.40538621285\r\n2011-09-03 09:15:01,1.74459064633\r\n2011-09-03 10:15:01,2.03489870008\r\n2011-09-03 11:15:01,1.93540664402\r\n2011-09-03 12:15:01,2.27425030493\r\n2011-09-03 13:15:01,2.14033402306\r\n2011-09-03 14:15:01,1.77426028471\r\n2011-09-03 15:15:01,1.25941144301\r\n2011-09-03 16:15:01,1.02897679946\r\n2011-09-03 17:15:01,0.924615076404\r\n2011-09-03 18:15:01,0.909732905845\r\n2011-09-03 19:15:01,0.869216123697\r\n2011-09-03 20:15:01,0.541295740253\r\n2011-09-03 21:15:01,1.1777566405\r\n2011-09-03 22:15:01,1.13735222856\r\n2011-09-03 23:15:01,0.890667031052\r\n2011-09-04 00:15:01,0.610490083267\r\n2011-09-04 01:15:01,0.909803400811\r\n2011-09-04 02:15:01,0.997966281743\r\n2011-09-04 03:15:01,0.760097226529\r\n2011-09-04 04:15:01,0.695617328423\r\n2011-09-04 05:15:01,0.756014604219\r\n2011-09-04 06:15:01,0.79008464589\r\n2011-09-04 07:15:01,0.917348874571\r\n2011-09-04 08:15:01,1.13719366386\r\n2011-09-04 09:15:01,1.42018674399\r\n2011-09-04 10:15:01,1.62974773646\r\n2011-09-04 11:15:01,2.39951967225\r\n2011-09-04 12:15:01,1.90579824839\r\n2011-09-04 13:15:01,1.41094529283\r\n2011-09-04 14:15:01,1.51420659222\r\n2011-09-04 15:15:01,0.907680196378\r\n2011-09-04 16:15:01,0.949640701076\r\n2011-09-04 17:15:01,0.853479545072\r\n2011-09-04 19:15:01,0.734071967028\r\n2011-09-04 21:15:01,0.664832645575\r\n2011-09-04 22:15:01,0.751175591232\r\n2011-09-04 23:15:01,0.699932102092\r\n2011-09-05 00:15:01,0.512007082519\r\n2011-09-05 01:15:01,0.768525925193\r\n2011-09-05 02:15:01,0.720969190212\r\n2011-09-05 03:15:01,0.834640838517\r\n2011-09-05 04:15:01,0.627736806898\r\n2011-09-05 05:15:01,0.651203112053\r\n2011-09-05 06:15:01,0.830826437039\r\n2011-09-05 07:15:01,0.708797528226\r\n2011-09-05 08:15:01,0.914809516084\r\n2011-09-05 09:15:01,1.19163674636\r\n2011-09-05 10:15:01,1.64855351909\r\n2011-09-05 11:15:01,1.75118246316\r\n2011-09-05 12:15:01,2.23766160764\r\n2011-09-05 13:15:01,1.66328470303\r\n2011-09-05 15:15:01,0.832920669506\r\n2011-09-05 17:15:01,0.933893576278\r\n2011-09-05 18:15:01,0.689506085719\r\n2011-09-05 19:15:01,0.768903526829\r\n2011-09-05 20:15:01,0.698904886719\r\n2011-09-05 21:15:01,0.681318152131\r\n2011-09-05 22:15:01,0.570423466165\r\n2011-09-05 23:15:01,0.63045223235\r\n2011-09-06 01:15:01,0.614224788781\r\n2011-09-06 02:15:01,0.655868229912\r\n2011-09-06 03:15:01,0.693436352057\r\n2011-09-06 04:15:01,0.611312925873\r\n2011-09-06 05:15:01,0.807827692044\r\n2011-09-06 06:15:01,0.653708482915\r\n2011-09-06 07:15:01,0.937306761036\r\n2011-09-06 08:15:01,1.34108358121\r\n2011-09-06 09:15:01,1.47226847333\r\n2011-09-06 10:15:01,1.72638563622\r\n2011-09-06 11:15:01,1.3196855493\r\n2011-09-06 12:15:01,1.262905036\r\n2011-09-06 14:15:01,1.2017614271\r\n2011-09-06 15:15:01,1.10625236699\r\n2011-09-06 16:15:01,1.45940072715\r\n2011-09-06 17:15:01,1.09848556824\r\n2011-09-06 18:15:01,0.953394382083\r\n2011-09-06 19:15:01,0.878863784275\r\n2011-09-06 20:15:01,1.12067995176\r\n2011-09-06 21:15:01,0.991837847317\r\n2011-09-06 22:15:01,0.831665933419\r\n2011-09-06 23:15:01,0.60047251793\r\n2011-09-07 00:15:01,0.555876363857\r\n2011-09-07 01:15:01,0.823805154231\r\n2011-09-07 02:15:01,0.678606401328\r\n2011-09-07 03:15:01,0.687514096173\r\n2011-09-07 04:15:01,0.657496548202\r\n2011-09-07 05:15:01,0.75337310206\r\n2011-09-07 06:15:01,0.8787691939\r\n2011-09-07 07:15:01,1.14312883039\r\n2011-09-07 08:15:01,1.15805690626\r\n2011-09-07 09:15:01,1.63436764871\r\n2011-09-07 10:15:01,1.74975517548\r\n2011-09-07 11:15:01,2.01440045625\r\n2011-09-07 12:15:01,1.49396356503\r\n2011-09-07 13:15:01,0.908472003661\r\n2011-09-07 14:15:01,1.34644468314\r\n"
  },
  {
    "path": "workspace/concurrent_taskpool/Makefile",
    "content": "\nSUBDIRS := src tests_and_benchmarks \n\nall: $(SUBDIRS)\n\n$(SUBDIRS):\n\t$(MAKE) -C $@\n\n.PHONY: all $(SUBDIRS)\n\nclean:\n\t$(MAKE) -C src clean\n\t$(MAKE) -C tests_and_benchmarks clean\n"
  },
  {
    "path": "workspace/concurrent_taskpool/src/Makefile",
    "content": "# jemalloc is faster so let's use it by default\nJEM_LIBS:=\nJEM_FLAGS:=\n\n# there's no pkg-config ??\nJEM_LIB?=$(wildcard /usr/lib/x86_64-linux-gnu/libjemalloc.a)\n\nifeq ($(JEM_LIB),)\n$(info ** Not using jemalloc)\nelse\n$(info Using jemalloc: $(JEM_LIB))\nJEM_FLAGS:=-DUSE_JEMALLOC\nJEM_LIBS:=$(JEM_LIB)\nendif\n\nCFLAGS:=$(JEM_FLAGS)\nLIBS:=$(JEM_LIBS)\n\nLIBDIR=../lib\n\nall: libtaskpool\n\nlibtaskpool: concurrent_task_pool_list.o concurrent_task_pool_tree.o $(LIBDIR)\n\tar rcs $(LIBDIR)/libtaskpool.a concurrent_task_pool_list.o concurrent_task_pool_tree.o\n\tranlib $(LIBDIR)/libtaskpool.a\n\nconcurrent_task_pool_list.o:\n\tcc concurrent_task_pool_list.c -c -I src -latomic -lm -Wno-int-to-pointer-cast -Wno-pointer-to-int-cast\n\nconcurrent_task_pool_tree.o:\n\tcc concurrent_task_pool_tree.c -c -I src -latomic -lm -Wno-int-to-pointer-cast -Wno-pointer-to-int-cast\n\n$(LIBDIR):\n\tmkdir -p $(LIBDIR)\n\nclean:\n\trm -rf *.o *.a $(LIBDIR)\n\n"
  },
  {
    "path": "workspace/concurrent_taskpool/src/concurrent_task_pool.h",
    "content": "/*\n * A concurrent, scalable, wait-free task pool implementation that performs well under high CAS contention\n *\n *  Created on: 22 Jan 2019\n *      Author: aagapi\n */\n\n#ifndef KERNEL_CONCURRENT_TASK_POOL_H_\n#define KERNEL_CONCURRENT_TASK_POOL_H_\n\n#include <stdatomic.h>\n#include \"fastrand.h\"\n\n#define DEFAULT_TREE_HEIGHT 3\n#define DEFAULT_K_NO_TRIALS 4\n#define MAX_DEGREE 64\n#define DEFAULT_DEGREE MAX_DEGREE\n\n#define DEFAULT_PREALLOCATED_ELEMENTS 1000000\n#define SLACK_PREALLOCATED_ELEMENTS 1\n\n#define PRECALCULATE_TREE_LEVEL_SIZES\n\n#define CALCULATE_TREE_SIZE(h,d) ((((int) pow(d, h)) - 1) / (d - 1))\n#define TREE_FILL_FACTOR(h,d,k) ((int)(pow((double)d,(((double)k+2)*h/(k+3))) / (d - 1))) // == (degree^^((k+2)/(k+3)*height))/(degree-1)\n#define _NO_PREALLOCATED_TREES(no_elems, h,d,k) (((int) (SLACK_PREALLOCATED_ELEMENTS*(no_elems))) / (TREE_FILL_FACTOR(h,d,k)))\n#define MAX(a, b) ((a>b)?(a):(b))\n#define NO_PREALLOCATED_TREES(no_elems, h,d,k) (MAX(_NO_PREALLOCATED_TREES(no_elems, h,d,k),1))\n\n// Macros for version handling (ABA etc):\n\n#define EMPTY_0_VERSION 0\n#define FULL_0_VERSION (1 << 31)\n#define IS_EMPTY(n) (!((n) & (1 << 31)))\n#define VERSION(n) ((n) & ~(1 << 31))\n#define NEW_VERSION(n, v) ((v) | ((n) & (1 << 31)))\n\n#define EMPTY_0_VERSION_BYTE 0\n#define FULL_0_VERSION_BYTE ((unsigned char) (1 << 7))\n#define IS_EMPTY_BYTE(n) (!((n) & (1 << 7)))\n#define VERSION_BYTE(n) ((n) & ~(1 << 7))\n#define NEW_VERSION_BYTE(n, v) ((v) | ((n) & (1 << 7)))\n\n#define BITMASK(len) ((1 << len) - 1)\n// A 'slice' of a 32 bit integer, encompassing bits [start,start+len-1]:\n#define SLICE(n,start,len) ((n >> (32 - start - len)) & ((1 << len) - 1))\n\n// Macros for binary trees:\n\n#define LEFT_CHILD(i) (2*(i)+1)\n#define RIGHT_CHILD(i) (2*(i)+2)\n#define PARENT(i) (((i)-1)/2)\n#define HAS_PARENT(i) ((i)>0)\n\n#define HAS_TASKS(node) (!IS_EMPTY(node.tasks_left) || !IS_EMPTY(node.tasks_right) || (node.data != NULL))\n\n// Macros for k-ary trees:\n\n#define CHILD_K(p,k,d) ((d)*(p) + (k) + 1)\n#define PARENT_K(i,d) (((i)-1)/d)\n\n// Macro points to the array of TREE_SIZE elements, holding the actual tree data (struct concurrent_tree_pool_node *),\n// allocated contiguously in the same mem chunk, right after the corresponding tree pool metadata (struct concurrent_pool_node):\n\n#define TREE_PTR(ptr) ((struct concurrent_tree_pool_node *) (&ptr[1]))\n\n// CAS and atomic load utility macros:\n\n// #define USE_ATOMIC_LOAD\n// #define USE_MEMORY_ORDER_RELAXED\n\n#ifdef USE_ATOMIC_LOAD\n#ifdef USE_MEMORY_ORDER_RELAXED\n#define LOAD(a) (atomic_load_explicit(&(a), memory_order_relaxed))\n#else\n#define LOAD(a) (atomic_load_(&(a)))\n#endif\n#else\n#define LOAD(a) (a)\n#endif\n\n#define USE_WEAK_CAS_IN_LOOPS\n// #define USE_WEAK_CAS_OUT_OF_LOOPS\n\n#ifdef USE_WEAK_CAS_IN_LOOPS\n#define LOOP_CAS atomic_compare_exchange_weak\n#else\n#define LOOP_CAS atomic_compare_exchange_strong\n#endif\n\n#ifdef USE_WEAK_CAS_OUT_OF_LOOPS\n#define CAS atomic_compare_exchange_weak\n#else\n#define CAS atomic_compare_exchange_strong\n#endif\n\n// #define FAST_PUT\n// #define FAST_GET\n// #define FAST_GET_PER_LEVEL\n\n// #define TASKPOOL_DEBUG\n// #define TASKPOOL_TRACE\n\ntypedef void *WORD;\n\ntypedef struct concurrent_pool_node * concurrent_pool_node_ptr;\ntypedef _Atomic concurrent_pool_node_ptr atomic_concurrent_pool_node_ptr;\n\ntypedef struct concurrent_pool_node_ptr_pair\n{\n\tconcurrent_pool_node_ptr prev;\n\tconcurrent_pool_node_ptr crt;\n} concurrent_pool_node_ptr_pair;\n\ntypedef _Atomic concurrent_pool_node_ptr_pair atomic_concurrent_pool_node_ptr_pair;\n\ntypedef struct concurrent_pool\n{\n\tint tree_height;\t\t\t\t\t\t\t\t\t\t// tree height for component complete tree pools\n\tint degree;\t\t\t\t\t\t\t\t\t\t\t// tree degree for component complete tree pools\n\tint k_no_trials;\t\t\t\t\t\t\t\t\t\t// number of retries upon a failed put (influences fill factor of component trees)\n\n\tconcurrent_pool_node_ptr head; \t\t\t\t\t\t// head of concurrent tree list\n\tatomic_concurrent_pool_node_ptr producer_tree;\t\t// pointer to current producer tree\n\tatomic_concurrent_pool_node_ptr_pair consumer_trees;\t// pair of pointers to (previous ,current) consumer trees\n\tatomic_uint old_producers;\t\t\t\t\t\t\t// producers that currently attempt to move producer_tree backwards\n\n#ifdef PRECALCULATE_TREE_LEVEL_SIZES\n\tint * level_sizes;\t\t\t\t\t\t\t\t\t// precomputed array of level sizes (used to speed up pool inserts)\n#endif\n\n\tconcurrent_pool_node_ptr _last_prealloc_block;\n} concurrent_pool;\n\ntypedef struct concurrent_tree_pool_node\n{\n\tatomic_uchar child_has_tasks[MAX_DEGREE];\n\tatomic_uchar dirty;\t\t// any task was placed in this node?\n\tatomic_uchar grabbed;\t// was this task grabbed?\n\tatomic_uint pending;\t\t// pending concurrent updates to parent\n\n\tWORD data;\t\t\t\t\t// actual task\n} concurrent_tree_pool_node;\n\n// Actual array of \"struct concurrent_tree_pool_node\" tree nodes (array representation of the complete tree)\n// is allocated right after the \"struct concurrent_pool_node\" metadata, in the same mem chunk,\n// and accessible via the TREE_PTR) macro:\n\ntypedef struct concurrent_pool_node\n{\n\tint node_id;\n\tatomic_concurrent_pool_node_ptr next;\n} concurrent_pool_node;\n\n// \"Public\" API:\n\n// Functions to allocate a taskpool:\n\n// Set 'no_prealloc' if you have an idea of the typical number of items a pool will hold, to optimize mem allocations.\n// Otherwise, set 'no_prealloc' to something < 0 and a default value will be used.\n// Set 'degree' and 'tree_height' to choose custom values for the tree degree and height, respectively.\n// Degree must be smaller than MAX_DEGREE.\n\nconcurrent_pool * allocate_pool(int no_prealloc);\nconcurrent_pool * allocate_pool_with_tree_height(int tree_height, int no_prealloc);\nconcurrent_pool * allocate_pool_with_tree_height_and_degree(int tree_height, int degree, int no_prealloc);\nvoid free_pool(concurrent_pool * p);\n\n// Functions to manipulate a taskpool:\n\n// Args:\n//\t- task: void* allocated and managed by the app\n//\t- pool: ptr to taskpool\n//\t- fastrandstate: *Always* pass a valid pointer to the fast random generator state to each call.\n//\t\t\t\t\tBefore starting library use in each thread, seed this state via GET_RANDSEED(&fastrandstate, apprand),\n//\t\t\t\t\twhere apprand is an (optional) per-thread unique state. If not available, just call GET_RANDSEED(&fastrandstate, 0) to seed\n//\t\t\t\t\tUse the same pointer on each subsequent call to all taskpool library functions\n\nint put(WORD task, concurrent_pool* pool, unsigned int * fastrandstate);\nint get(WORD* task, concurrent_pool* pool, unsigned int * fastrandstate);\nint get_last_block_id(concurrent_pool * p);\nvoid set_no_trials(concurrent_pool * pool, int no_trials);\n\n// Lower level API to access tree pools directly:\n\nconcurrent_tree_pool_node * allocate_tree_pool(int tree_height, int degree, int * precomputed_level_sizes);\nvoid free_tree_pool(concurrent_tree_pool_node * p);\nint put_in_tree(WORD task, concurrent_tree_pool_node* pool, int degree, int tree_height, int k_no_trials, int * precomputed_level_sizes, unsigned int * fastrandstate);\nint get_from_tree(WORD* task, concurrent_tree_pool_node* pool, int degree, int tree_height, int * precomputed_level_sizes, unsigned int * fastrandstate);\nint preallocate_trees(concurrent_pool* pool, int no_trees, int per_tree_data_size, char * prealloc_mem);\n\n#endif /* KERNEL_CONCURRENT_TASK_POOL_H_ */\n"
  },
  {
    "path": "workspace/concurrent_taskpool/src/concurrent_task_pool_list.c",
    "content": "/*\n * Copyright (C) 2019-2021 Deutsche Telekom AG\n *\n * Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:\n *\n * 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.\n *\n * 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.\n *\n * 3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission.\n *\n * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS \"AS IS\" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n */\n\n/*\n * A concurrent, scalable, wait-free task pool implementation that performs well under high CAS contention\n *\n * This file contains functions related to managing lists of tree pools\n *\n *  Created on: 22 Jan 2019\n *      Author: aagapi\n */\n\n#include <stdio.h>\n#include <stdlib.h>\n#include <math.h>\n#include <stdatomic.h>\n#include <time.h>\n#include <string.h>\n\n#include \"concurrent_task_pool.h\"\n\nconcurrent_pool_node * allocate_pool_node(int node_id, int tree_height, int degree, int * precomputed_level_sizes, concurrent_pool_node * prealloc_mem)\n{\n\tconcurrent_pool_node * pn = NULL;\n\tint total_nodes, total_size;\n\n\tif(prealloc_mem != NULL)\n\t{\n\t\tpn=prealloc_mem;\n\t}\n\telse\n\t{\n\t\tif(precomputed_level_sizes!=NULL)\n\t\t\ttotal_nodes = precomputed_level_sizes[tree_height-1];\n\t\telse\n\t\t\ttotal_nodes = CALCULATE_TREE_SIZE(tree_height, degree);\n\n\t\ttotal_size = total_nodes * sizeof(struct concurrent_tree_pool_node);\n\n\t\t// Actual array of \"total_nodes\" tree nodes is allocated right after the \"struct concurrent_pool_node\" metadata:\n\n\t\tpn = (concurrent_pool_node *) malloc(sizeof(struct concurrent_pool_node) + total_size);\n\n\t\tif(pn == NULL)\n\t\t{\n\t\t\tprintf(\"Failed to allocate tree of size %d/%d\\n\", total_nodes, total_size);\n\t\t\treturn NULL;\n\t\t}\n\n\t\tmemset(pn, 0, sizeof(struct concurrent_pool_node) + total_size);\n\n\t#ifdef TASKPOOL_DEBUG\n\t\tprintf(\"Allocated tree of size %d/%d\\n\", total_nodes, total_size);\n\t#endif\n\t}\n\n\tpn->node_id = node_id;\n\tatomic_init(&pn->next, NULL);\n\n\treturn pn;\n}\n\nvoid free_pool_node(concurrent_pool_node * p)\n{\n\tfree(p);\n}\n\nconcurrent_pool * _allocate_pool(int tree_height, int k_no_trials, int degree, int no_prealloc)\n{\n\tint nodes_per_tree = CALCULATE_TREE_SIZE(tree_height, degree);\n\tint per_tree_data_size = nodes_per_tree * sizeof(struct concurrent_tree_pool_node);\n\tint no_prealloced_trees = NO_PREALLOCATED_TREES(no_prealloc, tree_height, degree, k_no_trials);\n\n\t// The list of all pre-allocated tree blocks is allocated in the memchunk right after the pool's metadata.\n\t// In turn, for each pre-allocated tree node block, the actual array of \"nodes_per_tree\" tree nodes is also\n\t// allocated in the chunk right after the \"struct concurrent_pool_node\" metadata. So we use a single malloc for all these:\n\n\tconcurrent_pool * p = (concurrent_pool *) malloc(sizeof(struct concurrent_pool) + no_prealloced_trees * (sizeof(struct concurrent_pool_node) + per_tree_data_size));\n\n\tif(p == NULL)\n\t{\n\t\tprintf(\"Failed to allocate pool of %d blocks, each of size %d/%d\\n\", no_prealloced_trees, nodes_per_tree, per_tree_data_size);\n\t\treturn NULL;\n\t}\n\n\tmemset(p, 0, sizeof(struct concurrent_pool) + no_prealloced_trees * (sizeof(struct concurrent_pool_node) + per_tree_data_size));\n\n#ifdef TASKPOOL_DEBUG\n\tprintf(\"Pre-allocated tree of %d blocks, each of size %d/%d\\n\", no_prealloced_trees, nodes_per_tree, per_tree_data_size);\n#endif\n\n#ifdef PRECALCULATE_TREE_LEVEL_SIZES\n\tp->level_sizes = (int *) malloc(tree_height * sizeof(int));\n\n\tif(p->level_sizes == NULL)\n\t{\n\t\tfree(p);\n\t\treturn NULL;\n\t}\n\n\tfor(int i=0;i<tree_height;i++)\n\t\tp->level_sizes[i]=CALCULATE_TREE_SIZE(i+1, degree);\n#endif\n\n\tp->tree_height = tree_height;\n\tp->degree = degree;\n\tp->k_no_trials = k_no_trials;\n\n\tpreallocate_trees(p, no_prealloced_trees, per_tree_data_size, (char *)(&p[1]));\n\n\tatomic_init(&p->producer_tree, p->head);\n\tconcurrent_pool_node_ptr_pair cts = { .prev = NULL, .crt = p->head };\n\tatomic_init(&p->consumer_trees, cts); // Set consumer pointer pair to (prev=NULL, current=producer=head)\n\n\treturn p;\n}\n\nconcurrent_pool * allocate_pool_with_tree_height_and_degree(int tree_height, int degree, int no_prealloc)\n{\n\treturn _allocate_pool(tree_height, DEFAULT_K_NO_TRIALS, degree, MAX(no_prealloc, DEFAULT_PREALLOCATED_ELEMENTS));\n}\n\nconcurrent_pool * allocate_pool_with_tree_height(int tree_height, int no_prealloc)\n{\n\treturn _allocate_pool(tree_height, DEFAULT_K_NO_TRIALS, DEFAULT_DEGREE, MAX(no_prealloc, DEFAULT_PREALLOCATED_ELEMENTS));\n}\n\nconcurrent_pool * allocate_pool(int no_prealloc)\n{\n\treturn _allocate_pool(DEFAULT_TREE_HEIGHT, DEFAULT_K_NO_TRIALS, DEFAULT_DEGREE, MAX(no_prealloc, DEFAULT_PREALLOCATED_ELEMENTS));\n}\n\nvoid set_no_trials(concurrent_pool * pool, int no_trials)\n{\n\tpool->k_no_trials = no_trials;\n}\n\nvoid free_pool(concurrent_pool * p)\n{\n\tconcurrent_pool_node_ptr pn = p->_last_prealloc_block->next, next_pn = NULL;\n\n\twhile(pn != NULL)\n\t{\n\t\tnext_pn = pn->next;\n\t\tfree_pool_node(pn);\n\t\tpn = next_pn;\n\t}\n\n#ifdef PRECALCULATE_TREE_LEVEL_SIZES\n\tfree(p->level_sizes);\n#endif\n\tfree(p);\n}\n\nint get_last_block_id(concurrent_pool * p)\n{\n\tconcurrent_pool_node_ptr pn = p->head, next_pn = NULL;\n\n\twhile(pn->next != NULL)\n\t{\n\t\tnext_pn = pn->next;\n\t\tpn = next_pn;\n\t}\n\n\treturn pn->node_id;\n}\n\nstatic inline int move_consumer_ptr_back(concurrent_pool* pool, concurrent_pool_node_ptr producer_tree, concurrent_pool_node_ptr_pair c_ptrs_in)\n{\n\tatomic_fetch_add(&(pool->old_producers), 1);\n\n\tconcurrent_pool_node_ptr_pair c_ptrs = c_ptrs_in;\n\n\twhile(1)\n\t{\n\t\tconcurrent_pool_node_ptr_pair new_cts = { .prev = NULL, .crt = producer_tree };\n\n\t\tif(LOOP_CAS(&(pool->consumer_trees), &c_ptrs, new_cts))\n\t\t{\n#ifdef TASKPOOL_DEBUG\n\t\t\tprintf(\"Succeeded moving back consumer ptrs to (%p/%d,%p/%d)\\n\",\n\t\t\t\t\t\tnew_cts.prev, (new_cts.prev!=NULL)?(new_cts.prev->node_id):-1,\n\t\t\t\t\t\tnew_cts.crt, (new_cts.crt!=NULL)?(new_cts.crt->node_id):-1);\n#endif\n\n\t\t\tbreak;\n\t\t}\n\t\telse\n\t\t{\n#ifdef TASKPOOL_DEBUG\n\t\t\tprintf(\"Failed moving back consumer ptrs to (%p/%d,%p/%d)\\n\",\n\t\t\t\t\t\tnew_cts.prev, (new_cts.prev!=NULL)?(new_cts.prev->node_id):-1,\n\t\t\t\t\t\tnew_cts.crt, (new_cts.crt!=NULL)?(new_cts.crt->node_id):-1);\n#endif\n\t\t}\n\n\t\tif(c_ptrs.crt->node_id <= producer_tree->node_id)\n\t\t\tbreak;\n\t}\n\n\tatomic_fetch_add(&(pool->old_producers), -1);\n\n\treturn 0;\n}\n\n\n// Note: This function is NOT supposed to be thread safe. Only call in pool constructor.\n\nint preallocate_trees(concurrent_pool* pool, int no_trees, int per_tree_data_size, char * prealloc_mem)\n{\n\tconcurrent_pool_node_ptr crt_tree = NULL;\n\n\tfor(int i=0;i<no_trees;i++)\n\t{\n#ifdef PRECALCULATE_TREE_LEVEL_SIZES\n\t\tconcurrent_pool_node_ptr pool_node = allocate_pool_node(i+1, pool->tree_height, pool->degree, pool->level_sizes, (concurrent_pool_node *)(prealloc_mem + i*(sizeof(struct concurrent_pool_node) + per_tree_data_size)));\n#else\n\t\tconcurrent_pool_node_ptr pool_node = allocate_pool_node(i+1, pool->tree_height, pool->degree, NULL, (concurrent_pool_node *)(prealloc_mem + i*(sizeof(struct concurrent_pool_node) + per_tree_data_size)));\n#endif\n\n\t\tif(crt_tree != NULL)\n\t\t{\n\t\t\tatomic_init(&crt_tree->next, pool_node);\n\t\t}\n\t\telse\n\t\t{\n\t\t\tpool->head = pool_node;\n\t\t}\n\n\t\tcrt_tree = pool_node;\n\t}\n\n\tpool->_last_prealloc_block=crt_tree;\n\n\treturn 0;\n}\n\n\nstatic inline int insert_new_tree(concurrent_pool* pool, concurrent_pool_node_ptr producer_tree_in)\n{\n\tconcurrent_pool_node_ptr producer_tree = producer_tree_in, next_ptr = LOAD(producer_tree_in->next);\n#ifdef PRECALCULATE_TREE_LEVEL_SIZES\n\tconcurrent_pool_node_ptr pool_node = allocate_pool_node(0, pool->tree_height, pool->degree, pool->level_sizes, NULL);\n#else\n\tconcurrent_pool_node_ptr pool_node = allocate_pool_node(0, pool->tree_height, pool->degree, NULL, NULL);\n#endif\n\n\tif(pool_node == NULL)\n\t\treturn -1;\n\n\t// Find end of tree list:\n\n\twhile(next_ptr != NULL)\n\t{\n\t\tproducer_tree = next_ptr;\n\t\tnext_ptr = LOAD(producer_tree->next);\n\t}\n\n\tpool_node->node_id = producer_tree->node_id + 1;\n\n\tconcurrent_pool_node_ptr old = NULL;\n\n\t// Attempt to chain our newly allocated tree pool to the end of the list.\n\t// If the CAS fails, it means a concurrent producer managed to extend the list before us,\n\t// in which case we free our newly allocated pool and return.\n\n\tif(!CAS(&(producer_tree->next), &old, pool_node))\n\t{\n#ifdef TASKPOOL_DEBUG\n\t\t\tprintf(\"Failed setting next ptr of %p/%d to %p/%d\\n\",\n\t\t\t\t\t\tproducer_tree, (producer_tree!=NULL)?(producer_tree->node_id):-1,\n\t\t\t\t\t\tpool_node, (pool_node!=NULL)?(pool_node->node_id):-1);\n#endif\n\n\t\tfree_pool_node(pool_node);\n\t}\n\telse\n\t{\n#ifdef TASKPOOL_DEBUG\n\t\t\tprintf(\"Succeeded setting next ptr of %p/%d to %p/%d\\n\",\n\t\t\t\t\t\tproducer_tree, (producer_tree!=NULL)?(producer_tree->node_id):-1,\n\t\t\t\t\t\tpool_node, (pool_node!=NULL)?(pool_node->node_id):-1);\n#endif\n\t}\n\n\treturn 0;\n}\n\nint put(WORD task, concurrent_pool* pool, unsigned int * seedptr)\n{\n\tconcurrent_pool_node_ptr producer_tree = NULL;\n\tint status = 0;\n#ifdef PRECALCULATE_TREE_LEVEL_SIZES\n\tint * precalculated_level_sizes = pool->level_sizes;\n#else\n\tint * precalculated_level_sizes = NULL;\n#endif\n\n\tproducer_tree = LOAD(pool->producer_tree);\n\n\twhile(1)\n\t{\n\t\tint put_index = put_in_tree(task, TREE_PTR(producer_tree), pool->degree, pool->tree_height, pool->k_no_trials, precalculated_level_sizes, seedptr);\n\n\t\tif(put_index >= 0)\n\t\t{\n#ifdef TASKPOOL_TRACE\n\t\t\tprintf(\"Successfully put task %ld in tree %d at index %d\\n\", (long) task, producer_tree->node_id, put_index);\n#endif\n\t\t\t// Put succeeded in current tree, but we may need to move back consumer pointer if it overshot us:\n\n\t\t\tconcurrent_pool_node_ptr_pair c_ptrs = LOAD(pool->consumer_trees);\n\n\t\t\tif(c_ptrs.crt->node_id > producer_tree->node_id)\n\t\t\t{\n\t\t\t\tmove_consumer_ptr_back(pool, producer_tree, c_ptrs);\n\t\t\t}\n\n\t\t\treturn 0;\n\t\t}\n\t\telse // current producer tree is \"full\"\n\t\t{\n#ifdef TASKPOOL_DEBUG\n\t\t\tprintf(\"put_in_tree() returned status %d when attempting to put task %ld in full tree %d. Next pointer is: %d\\n\", status, (long) task, producer_tree->node_id, (producer_tree->next != NULL)?(producer_tree->next->node_id):(-1));\n#endif\n\n\t\t\t// It might be that another producer already inserted a new tree, so first check for that:\n\n\t\t\tatomic_concurrent_pool_node_ptr producer_tree_next = LOAD(producer_tree->next);\n\n\t\t\tif(producer_tree_next == NULL)\n\t\t\t{\n\t\t\t\tstatus = insert_new_tree(pool, producer_tree);\n\n#ifdef TASKPOOL_DEBUG\n\t\t\t\tprintf(\"insert_new_tree() returned status %d when attempting to put task %ld in full tree %d. Next pointer is: %d\\n\", status, (long) task, producer_tree->node_id, producer_tree->next->node_id);\n#endif\n\n\t\t\t\t// Note the only failure condition is failure to allocate memory, otherwise inserts s'd always succeed:\n\n\t\t\t\tif(status != 0)\n\t\t\t\t\treturn status;\n\t\t\t}\n\n\t\t\t// At this point a new tree was successfully linked into the list (either by us or by a concurrent producer).\n\t\t\t// We next attempt to progress the producer pointer of the pool. If that CAS fails, it just means that\n\t\t\t// some other producer managed to progress it before us, which is OK: we just continue and attempt\n\t\t\t// to put our task in the current producer tree of the pool:\n\n\t\t\tstatus = CAS(&(pool->producer_tree), &producer_tree, LOAD(producer_tree->next));\n\n#ifdef TASKPOOL_DEBUG\n\t\t\tif(status != 1)\n\t\t\t\tprintf(\"CAS returned status %d when attempting to progress producer pointer (after put failed in full tree).\\n\", status);\n#endif\n\t\t}\n\t}\n}\n\nint get(WORD* task, concurrent_pool* pool, unsigned int * seedptr)\n{\n\tconcurrent_pool_node_ptr producer_tree = NULL;\n\tconcurrent_pool_node_ptr_pair consumer_ptrs = LOAD(pool->consumer_trees);\n\tint status;\n\n\twhile(1)\n\t{\n\t\t// First try the previous and current consumer pointers:\n\n\t\tif(consumer_ptrs.prev != NULL)\n\t\t{\n#ifdef TASKPOOL_TRACE\n\t\t\tprintf(\"get() attempting to find a task in prev tree %d\\n\", consumer_ptrs.prev->node_id);\n#endif\n\n\t\t\tif(get_from_tree(task, TREE_PTR(consumer_ptrs.prev), pool->degree, pool->tree_height, pool->level_sizes, seedptr)==0)\n\t\t\t{\n#ifdef TASKPOOL_TRACE\n\t\t\tprintf(\"get() found task %ld in prev tree %d\\n\", (long) *task, consumer_ptrs.prev->node_id);\n#endif\n\t\t\t\treturn 0;\n\t\t\t}\n\n\t\t}\n\n\t\tif(consumer_ptrs.crt != NULL)\n\t\t{\n#ifdef TASKPOOL_TRACE\n\t\t\tprintf(\"get() attempting to find a task in crt tree %d\\n\", consumer_ptrs.crt->node_id);\n#endif\n\n\t\t\tif(get_from_tree(task, TREE_PTR(consumer_ptrs.crt), pool->degree, pool->tree_height, pool->level_sizes, seedptr)==0)\n\t\t\t{\n#ifdef TASKPOOL_TRACE\n\t\t\t\tprintf(\"get() found task %ld in crt tree %d\\n\", (long) *task, consumer_ptrs.crt->node_id);\n#endif\n\t\t\t\treturn 0;\n\t\t\t}\n\t\t}\n\n\t\tproducer_tree = LOAD(pool->producer_tree);\n\n\t\tif(producer_tree->node_id <= consumer_ptrs.crt->node_id)\n\t\t{\n#ifdef TASKPOOL_TRACE\n\t\t\tprintf(\"get(): No new tasks exist (producer tree %d < consumer tree %d)\\n\", producer_tree->node_id, consumer_ptrs.crt->node_id);\n#endif\n\t\t\t*task = NULL; // No new tasks exist\n\t\t\treturn 1;\n\t\t}\n\n\t\tconcurrent_pool_node_ptr_pair new_cts = { .prev = consumer_ptrs.crt, .crt = consumer_ptrs.crt->next };\n\n\t\tif(LOAD(pool->old_producers) == 0)\n\t\t{\n\t\t\t// Whether my CAS to update consumer pointers succeeds or not, use the most recent value\n\t\t\t// of the (prev, crt) pointer pair to retry grabbing tasks from the new tree pointers:\n\n\t\t\tstatus = CAS(&(pool->consumer_trees), &consumer_ptrs, new_cts);\n\n#ifdef TASKPOOL_DEBUG\n\t\t\tprintf(\"%s setting consumer ptrs to (%p/%d,%p/%d)\\n\", (status>0)?\"Succeeded\":\"Failed\",\n\t\t\t\t\t\tnew_cts.prev, (new_cts.prev!=NULL)?(new_cts.prev->node_id):-1,\n\t\t\t\t\t\tnew_cts.crt, (new_cts.crt!=NULL)?(new_cts.crt->node_id):-1);\n#endif\n\t\t}\n\t\telse\n\t\t// If there are currently some producers attempting to move consumer pointer back, retry to read from\n\t\t// the (updated) consumer pointer again, but *do not* attempt to progress consumer pointer after that,\n\t\t// to avoid race condition:\n\t\t{\n\t\t\tconsumer_ptrs = new_cts;\n\n#ifdef TASKPOOL_DEBUG\n\t\t\tprintf(\"Locally setting consumer ptrs to (%p/%d,%p/%d)\\n\",\n\t\t\t\t\t\tnew_cts.prev, (new_cts.prev!=NULL)?(new_cts.prev->node_id):-1,\n\t\t\t\t\t\tnew_cts.crt, (new_cts.crt!=NULL)?(new_cts.crt->node_id):-1);\n#endif\n\t\t}\n\t}\n}\n\n\n"
  },
  {
    "path": "workspace/concurrent_taskpool/src/concurrent_task_pool_tree.c",
    "content": "/*\n * Copyright (C) 2019-2021 Deutsche Telekom AG\n *\n * Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:\n *\n * 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.\n *\n * 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.\n *\n * 3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission.\n *\n * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS \"AS IS\" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n */\n\n/*\n * A concurrent, scalable, wait-free task pool implementation that performs well under high CAS contention\n *\n * This file contains functions related to managing tree pools\n *\n *  Created on: 22 Jan 2019\n *      Author: aagapi\n */\n\n#include <stdio.h>\n#include <stdlib.h>\n#include <math.h>\n#include <stdatomic.h>\n#include <time.h>\n#include <string.h>\n#include \"concurrent_task_pool.h\"\n\nstatic inline int has_tasks_k(concurrent_tree_pool_node node, int degree)\n{\n\tif(node.data != NULL)\n\t\treturn 1;\n\n\tfor(int i=0;i< degree;i++)\n\t\tif(!IS_EMPTY_BYTE(node.child_has_tasks[i]))\n\t\t\treturn 1;\n\n\treturn 0;\n}\n\nstatic inline int random_in_level(int level, int degree, int * precomputed_level_sizes, unsigned int * seedptr)\n{\n\tunsigned int first_in_level, last_in_level, randno;\n\n\tif(level==0)\n\t\treturn 0;\n\n\tif(precomputed_level_sizes!=NULL)\n\t{\n\t\tfirst_in_level = precomputed_level_sizes[level-1];\n\t\tlast_in_level = precomputed_level_sizes[level] - 1;\n\t}\n\telse\n\t{\n\t\tfirst_in_level = CALCULATE_TREE_SIZE(level, degree);\n\t\tlast_in_level = CALCULATE_TREE_SIZE(level+1, degree) - 1;\n\t}\n\n\tFASTRAND(seedptr, randno);\n\n\treturn (randno % (last_in_level - first_in_level + 1)) + first_in_level;\n}\n\nstatic inline int update_father(int index, concurrent_tree_pool_node* pool, int degree, unsigned char value)\n{\n\tatomic_fetch_add(&(pool[index].pending), 1);\n\tint parent_index=PARENT_K(index, degree);\n\tint child_index = (index - 1) % degree;\n\tunsigned char old = 0, new = 0;\n\tint success = 0;\n\n\told = LOAD(pool[parent_index].child_has_tasks[child_index]);\n\tnew = (value)?(FULL_0_VERSION_BYTE):(EMPTY_0_VERSION_BYTE);\n\tnew = NEW_VERSION_BYTE(new, VERSION_BYTE(old) + 1);\n\n\tsuccess = CAS(&(pool[parent_index].child_has_tasks[child_index]), &old, new);\n\n#ifdef TASKPOOL_DEBUG\n\tprintf(\"update_father(): Updating parent index %d of index %d from (%u, %u, %u) to (%u, %u, %u) returned %d\\n\",\n\t\t\tparent_index, index,\n\t\t\told, IS_EMPTY_BYTE(old), VERSION_BYTE(old),\n\t\t\tnew, IS_EMPTY_BYTE(new), VERSION_BYTE(new),\n\t\t\tsuccess);\n#endif\n\n\tatomic_fetch_add(&(pool[index].pending), -1);\n\n\treturn success;\n}\n\nstatic inline void update_node_metadata(int index, concurrent_tree_pool_node* pool, int degree, unsigned char value)\n{\n\tint trials = 0, crt_index = index;\n\n#ifdef TASKPOOL_TRACE\n\tprintf(\"update_node_metadata(index=%d, value=%d)\\n\", index, value);\n#endif\n\n\twhile(HAS_PARENT(crt_index))\n\t{\n\t\tint have_tasks = has_tasks_k(pool[crt_index], degree);\n\n\t\tif(value != have_tasks)\n\t\t{\n#ifdef TASKPOOL_TRACE\n\t\t\tprintf(\"update_node_metadata(): Skipping because my operation has been eliminated: value=%d != has_tasks(%d)=%d\\n\", value, crt_index, have_tasks);\n#endif\n\t\t\treturn;\n\t\t}\n\n\t\tint parent_index=PARENT_K(crt_index, degree);\n\t\tconcurrent_tree_pool_node parent_node = pool[parent_index];\n\t\tint child_index = (crt_index - 1) % degree;\n\n\t\tif(IS_EMPTY_BYTE(pool[parent_index].child_has_tasks[child_index]) == have_tasks || pool[crt_index].pending > 0)\n\t\t{\n#ifdef TASKPOOL_TRACE\n\t\t\tprintf(\"update_node_metadata(index=%d, value=%d), updating parent index %d\\n\", index, value, parent_index);\n#endif\n\n\t\t\ttrials++;\n\n\t\t\tif(!update_father(crt_index, pool, degree, value))\n\t\t\t{\n#ifdef TASKPOOL_TRACE\n\t\t\t\tprintf(\"update_node_metadata(index=%d, value=%d), update_father() failed on parent index %d, trials=%d\\n\", index, value, parent_index, trials);\n#endif\n\t\t\t\tif(trials < 2)\n\t\t\t\t\tcontinue;\n\t\t\t}\n\t\t}\n\t\telse\n\t\t{\n#ifdef TASKPOOL_TRACE\n\t\t\tprintf(\"update_node_metadata(index=%d, value=%d), skipping update of parent index %d because pool[%d].pending=%d, child_index=%d, parent_empty_child=%d, has_tasks=%d\\n\",\n\t\t\t\t\tindex, value, parent_index,\n\t\t\t\t\tcrt_index, pool[crt_index].pending,\n\t\t\t\t\tchild_index, IS_EMPTY(pool[parent_index].child_has_tasks[child_index]),\n\t\t\t\t\thave_tasks);\n#endif\n\t\t\t}\n\n\t\tcrt_index = parent_index;\n\n\t\ttrials = 0;\n\t}\n}\n\nstatic inline int put_in_node_simple(int index, concurrent_tree_pool_node* pool, int degree, WORD task)\n{\n\tint crt_index = index;\n\n\tunsigned char old = LOAD(pool[crt_index].dirty);\n\n\tif(old == 0 && CAS(&pool[crt_index].dirty, &old, 1))\n\t{\n\t\tpool[crt_index].data = task;\n\n\t\treturn crt_index;\n\t}\n\telse\n\t{\n\t\treturn -1;\n\t}\n}\n\nstatic inline int put_in_node(int index, concurrent_tree_pool_node* pool, int degree, WORD task)\n{\n\tint crt_index = index;\n\n\twhile(HAS_PARENT(crt_index) && pool[PARENT_K(crt_index, degree)].data==NULL)\n\t\tcrt_index=PARENT_K(crt_index, degree);\n\n\tunsigned char old = LOAD(pool[crt_index].dirty);\n\n\tif(old == 0 && CAS(&pool[crt_index].dirty, &old, 1))\n\t{\n\t\tpool[crt_index].data = task;\n\n\t\treturn crt_index;\n\t}\n\telse\n\t{\n\t\treturn -1;\n\t}\n}\n\nstatic inline int find_node_for_put(WORD task, concurrent_tree_pool_node* pool, int tree_height, int degree, int k_no_trials, int * precomputed_level_sizes, unsigned int * seedptr)\n{\n\tint index;\n\n#ifdef FAST_PUT\n\tint total_nodes = 0;\n\n\tif(precomputed_level_sizes!=NULL)\n\t{\n\t\ttotal_nodes = precomputed_level_sizes[tree_height-1];\n\t}\n\telse\n\t{\n\t\ttotal_nodes = CALCULATE_TREE_SIZE(tree_height, degree);\n\t}\n\n\tunsigned int randno;\n\tFASTRAND(seedptr, randno);\n\n\tindex=put_in_node_simple(randno % total_nodes, pool, degree, task);\n\n\tif(index!=-1)\n\t\treturn index;\n#endif\n\n\tfor(int level=1;level<tree_height;level++)\n\t{\n\t\tint no_trials = ((level==tree_height-1)?k_no_trials:1);\n\n\t\tfor(int trials=0;trials<no_trials;trials++)\n\t\t{\n\t\t\tindex=put_in_node(random_in_level(level, degree, precomputed_level_sizes, seedptr), pool, degree, task);\n\t\t\tif(index!=-1)\n\t\t\t\treturn index;\n\t\t}\n\t}\n\n\treturn -1;\n}\n\nint put_in_tree(WORD task, concurrent_tree_pool_node* pool, int degree, int tree_height, int k_no_trials, int * precomputed_level_sizes, unsigned int * seedptr)\n{\n\t// Handle root insertions separately for higher speed:\n\n\tunsigned char old = LOAD(pool[0].dirty);\n\n\tif(old == 0)\n\t{\n\t\tif(CAS(&pool[0].dirty, &old, 1))\n\t\t{\n\t\t\tpool[0].data = task;\n\t\t\treturn 0;\n\t\t}\n\t}\n\n\tif(tree_height==1)\n\t{\n\t\treturn -1;\n\t}\n\n\tint index = find_node_for_put(task, pool, tree_height, degree, k_no_trials, precomputed_level_sizes, seedptr);\n\n\tif(index==-1)\n\t\treturn -1;\n\n\tupdate_node_metadata(index, pool, degree, 1);\n\n\treturn index;\n}\n\n// Returns either a node with an existing, non-grabbed task, or a node with empty children:\n\nstatic inline int find_node_for_get(concurrent_tree_pool_node* pool, int degree, int tree_height, int * index_p, int * precomputed_level_sizes, unsigned int * seedptr)\n{\n\tint index = 0;\n\n#ifdef FAST_GET\n\tint total_nodes = 0;\n\n\tif(precomputed_level_sizes!=NULL)\n\t{\n\t\ttotal_nodes = precomputed_level_sizes[tree_height-1];\n\t}\n\telse\n\t{\n\t\ttotal_nodes = CALCULATE_TREE_SIZE(tree_height, degree);\n\t}\n\n\tunsigned int randno;\n\tFASTRAND(seedptr, randno);\n\n\tindex=randno % total_nodes;\n\n\tif((pool[index].data != NULL))\n\t{\n\t\t*index_p = index;\n\t\treturn 0;\n\t}\n#endif\n\n\twhile(1)\n\t{\n#ifdef TASKPOOL_TRACE\n\t\tprintf(\"find_node_for_get: index=%d, data=%ld, grabbed=%d, dirty=%d, left_empty=(%d, %d, %d), right_empty=(%d, %d, %d)\\n\",\n\t\t\t\tindex, (long) pool[index].data, atomic_load(&pool[index].grabbed), atomic_load(&pool[index].dirty),\n\t\t\t\tpool[index].tasks_left, IS_EMPTY(pool[index].tasks_left), VERSION(pool[index].tasks_left),\n\t\t\t\tpool[index].tasks_right, IS_EMPTY(pool[index].tasks_right), VERSION(pool[index].tasks_right));\n#endif\n\n\t\t// Return this node's task if it exists:\n\n\t\tif((pool[index].data != NULL))\n\t\t{\n\t\t\t*index_p = index;\n\t\t\treturn 0;\n\t\t}\n\n#ifdef FAST_GET_PER_LEVEL\n\t\tunsigned int randno;\n\t\tFASTRAND(seedptr, randno);\n\t\tint rand_child = randno % degree;\n\n\t\tif(!IS_EMPTY_BYTE(pool[index].child_has_tasks[rand_child]))\n\t\t{\n\t\t\tindex = CHILD_K(index, rand_child, degree);\n\t\t\tcontinue;\n\t\t}\n#endif\n\n\t\tint full_children[MAX_DEGREE], no_full_children=0;\n\n\t\tfor(int i=0;i<degree;i++)\n\t\t{\n\t\t\tif(!IS_EMPTY_BYTE(pool[index].child_has_tasks[i]))\n\t\t\t{\n\t\t\t\tfull_children[no_full_children++] = i;\n\t\t\t}\n\t\t}\n\n\t\tif(no_full_children==0)\n\t\t{\n\t\t\t*index_p = index;\n\t\t\treturn -1;\n\t\t}\n\t\telse if(no_full_children==1)\n\t\t{\n\t\t\tindex = CHILD_K(index,full_children[0], degree);\n\t\t}\n\t\telse\n\t\t{\n\t\t\tunsigned int randno;\n\n\t\t\tFASTRAND(seedptr, randno);\n\n\t\t\tindex = CHILD_K(index,full_children[randno % no_full_children], degree);\n\t\t}\n\t}\n}\n\nint get_from_tree(WORD* task, concurrent_tree_pool_node* pool, int degree, int tree_height, int * precomputed_level_sizes, unsigned int * seedptr)\n{\n\twhile(1)\n\t{\n\t\t// Check if tree is empty:\n\n\t\tif(!has_tasks_k(pool[0], degree))\n\t\t{\n\t\t\treturn -1;\n\t\t}\n\n\t\t// Returns either a node with an existing, non-grabbed task, or a node with empty children:\n\n\t\tint index = -1;\n\t\tint status = find_node_for_get(pool, degree, tree_height, &index, precomputed_level_sizes, seedptr);\n\n\t\t// This is the case when find_node_for_get() returned a node with empty children.\n\t\t// Update its ancestor's metadata and keep trying to get a task from the current tree:\n\n\t\tif(status < 0)\n\t\t{\n#ifdef TASKPOOL_TRACE\n\t\t\tprintf(\"find_node_for_get() found no tasks (index=%d)\\n\", index);\n#endif\n\n\t\t\tupdate_node_metadata(index, pool, degree, 0);\n\n\t\t\tcontinue;\n\t\t}\n\n\t\t// We have a valid node index with a task. Attempt to grab it:\n\n\t\tunsigned char old = LOAD(pool[index].grabbed);\n\n#ifdef TASKPOOL_TRACE\n\t\tprintf(\"find_node_for_get() found a task at index=%d, task=%ld, grabbed=%d, dirty=%d\\n\", index, (long) pool[index].data, old, atomic_load(&pool[index].dirty));\n#endif\n\t\tif(old == 0 && CAS(&pool[index].grabbed, &old, 1))\n\t\t{\n\t\t\t*task = pool[index].data;\n\t\t\tpool[index].data=(WORD) NULL;\n\n\t\t\tif(index > 0)\n\t\t\t\tupdate_node_metadata(index, pool, degree, 0);\n\n\t\t\treturn 0;\n\t\t}\n\t\telse // Didn't manage to grab the task. Keep trying to get a task from the current tree:\n\t\t{\n\t\t\tcontinue;\n\t\t}\n\t}\n}\n\nconcurrent_tree_pool_node * allocate_tree_pool(int tree_height, int degree, int * precomputed_level_sizes)\n{\n\tint total_nodes, total_size;\n\n\tif(precomputed_level_sizes!=NULL)\n\t\ttotal_nodes = precomputed_level_sizes[tree_height-1];\n\telse\n\t\ttotal_nodes = CALCULATE_TREE_SIZE(tree_height, degree);\n\n\ttotal_size = total_nodes * sizeof(struct concurrent_tree_pool_node);\n\n\tconcurrent_tree_pool_node * tpn = (concurrent_tree_pool_node *) malloc(total_size);\n\n\tif(tpn)\n\t{\n\t\tmemset(tpn, 0, total_size);\n\n#ifdef TASKPOOL_DEBUG\n\t\tprintf(\"Allocated tree of size %d/%d\\n\", total_nodes, total_size);\n#endif\n\t}\n\telse\n\t{\n\t\tprintf(\"Failed to allocate tree of size %d/%d\\n\", total_nodes, total_size);\n\t}\n\n\treturn tpn;\n}\n\nvoid free_tree_pool(concurrent_tree_pool_node * p)\n{\n\tfree(p);\n}\n\n\n\n"
  },
  {
    "path": "workspace/concurrent_taskpool/src/fastrand.h",
    "content": "\n#ifndef FASTRAND_H_\n#define FASTRAND_H_\n\n#if( defined _POSIX_THREADS && _POSIX_TIMERS >= 0 && _POSIX_MONOTONIC_CLOCK >= 0 )\n#define GET_RANDSEED(seedptr, rand)\t\t\t\t\t\t\t                        \t\t\t\t\t\t\t\\\n{                                                                                     \t\t\t\t\t\t\\\n  struct timespec tp;                                                                 \t\t\t\t\t\t\\\n  clock_gettime( CLOCK_MONOTONIC_RAW, &tp );                                          \t\t\t\t\t\t\\\n  *(seedptr) = (unsigned int) ((tp.tv_nsec & 0xFFFFFFFF00000000) + (tp.tv_nsec & 0x00000000FFFFFFFF) + rand) ; \\\n}\n#else\n#define GET_RANDSEED(seedptr, rand)\t\t\t\t\t\t\t                        \t\t\t\t\t\t\t\\\n{                                                                                     \t\t\t\t\t\t\\\n  long now = time(NULL);                                                                 \t\t\t\t\t\t\\\n  *(seedptr) = (unsigned int) ((now & 0xFFFFFFFF00000000) + (now & 0x00000000FFFFFFFF) + rand) ; \\\n}\n#endif\n\n\n#define FASTRAND(seedptr, value)\t\t\t\t\\\n{\t*seedptr = (214013*(*seedptr)+2531011);\t\\\n\tvalue = ((*seedptr)>>16)&0x7FFF;\t\t\t\\\n}\n\nstatic unsigned int g_seed;\n\ninline static void fast_srand(int seed)\n{\n\tg_seed = seed;\n}\n\ninline static int fastrand()\n{\n\tg_seed = (214013*g_seed+2531011);\n\n\treturn (g_seed>>16)&0x7FFF;\n}\n\n\n#endif /* FASTRAND_H_ */\n"
  },
  {
    "path": "workspace/concurrent_taskpool/tests_and_benchmarks/Makefile",
    "content": "# jemalloc is faster so let's use it by default\nJEM_LIBS:=\nJEM_FLAGS:=\n\n# there's no pkg-config ??\nJEM_LIB?=$(wildcard /usr/lib/x86_64-linux-gnu/libjemalloc.a)\n\nifeq ($(JEM_LIB),)\n$(info ** Not using jemalloc)\nelse\n$(info Using jemalloc: $(JEM_LIB))\nJEM_FLAGS:=-DUSE_JEMALLOC\nJEM_LIBS:=$(JEM_LIB)\nendif\n\nLDFS_FLAGS:=-I ~/liblfds7.1.1/liblfds711/inc -L ~/liblfds7.1.1/liblfds711/bin\nLDFS_LIBS:=-llfds711\n\nCFLAGS:=$(JEM_FLAGS) $(LDFS_FLAGS)\nLIBS:=$(JEM_LIBS) $(LDFS_LIBS)\n\nall: concurrent_task_pool_test_multithreaded concurrent_task_pool_test_multithreaded_mixed\n\nconcurrent_task_pool_test_multithreaded: concurrent_task_pool_test_multithreaded.c\n\tcc -std=c11 concurrent_task_pool_test_multithreaded.c -O3 \\\n\t\t$(CFLAGS) -I ../src -L ../lib \\\n\t\t-ltaskpool -latomic -pthread -lm \\\n\t\t$(LIBS) \\\n\t\t-Wno-int-to-pointer-cast -Wno-pointer-to-int-cast \\\n\t\t-o concurrent_task_pool_test_multithreaded\n\nconcurrent_task_pool_test_multithreaded_mixed: concurrent_task_pool_test_multithreaded_mixed.c\n\tcc -std=c11 concurrent_task_pool_test_multithreaded_mixed.c -O3 \\\n\t\t$(CFLAGS) -I ../src -L ../lib \\\n\t\t-ltaskpool -latomic -pthread -lm \\\n\t\t$(LIBS) \\\n\t\t-Wno-int-to-pointer-cast -Wno-pointer-to-int-cast \\\n\t\t-o concurrent_task_pool_test_multithreaded_mixed\nclean:\n\trm -f concurrent_task_pool_test_multithreaded concurrent_task_pool_test_multithreaded_mixed\n"
  },
  {
    "path": "workspace/concurrent_taskpool/tests_and_benchmarks/benchmarking_scripts/compare_old_new",
    "content": "#!/bin/bash\n\n# e.g. 11 concurrent_task_pool_times_t_v11_k_ary_tree_static_vector_inline_list_fixed_degree_2.bare_iron.1.ammended.merged.txt concurrent_task_pool_times_t_v12_k_ary_tree_static_vector_inline_list_fixed_no_atomic_load_degree_2.bare_iron.1.txt\n\nfield=$1\noldfile=\"$2\"\nnewfile=\"$3\"\n\ncat $oldfile | cut -f $field -d ' ' | cut -f 2 -d = | sed -e 's/,//g' > old_times.txt\ncat $newfile | cut -f $field -d ' ' | cut -f 2 -d = | sed -e 's/,//g' > new_times.txt\n\nno_msmts=`wc -l new_times.txt | cut -f 1 -d ' '`\n\nfor msmt in `seq ${no_msmts}`\ndo\n\toldtime=`cat old_times.txt | head -$msmt | tail -1`\n\tnewtime=`cat new_times.txt | head -$msmt | tail -1`\n\n\techo `cat $newfile | head -$msmt | tail -1 | cut -f 3,4,5 -d ' '` time_diff=`echo $oldtime - $newtime | bc -l`\ndone | grep -vE \"tree_height=1, k_retries=4,\"\\|\"tree_height=1, k_retries=8,\"\\|\"tree_height=1, k_retries=10,\"\\|\"tree_height=2, k_retries=4,\"\\|\"tree_height=2, k_retries=8,\"\\|\"tree_height=2, k_retries=10,\"\\|\"tree_height=4, k_retries=8,\"\\|\"tree_height=4, k_retries=10,\"\n\n"
  },
  {
    "path": "workspace/concurrent_taskpool/tests_and_benchmarks/benchmarking_scripts/compare_settings",
    "content": "#!/bin/bash\n\n# e.g. 11_3_1 11_3_2 11 concurrent_task_pool_times_t_v15_fast_get_per_level_new_test_10M_no_keep_tasks_preallocated_more_threads3_all_degrees.bare_iron.7.txt\n\nold=$1\nnew=$2\nfield=$3\nfile=$4\n\nod=`echo $old | cut -f 1 -d '_'`\noh=`echo $old | cut -f 2 -d '_'`\nok=`echo $old | cut -f 3 -d '_'`\n\nnd=`echo $new | cut -f 1 -d '_'`\nnh=`echo $new | cut -f 2 -d '_'`\nnk=`echo $new | cut -f 3 -d '_'`\n\n./get_series $od $oh $ok \"$field\" $file l > series_${field}_${old}.txt\n./get_series $nd $nh $nk \"$field\" $file l > series_${field}_${new}.txt\n\noldseries=`cat series_${field}_${old}.txt | cut -f 2 -d ' '`\nnewseries=`cat series_${field}_${new}.txt | cut -f 2 -d ' '`\nnoentries=`echo $newseries | wc -w`\n\nfor entryno in `seq $noentries`\ndo\n\tnewentry=`echo $newseries | cut -f $entryno -d ' '`\n\toldentry=`echo $oldseries | cut -f $entryno -d ' ' | bc -l`\n\tx=`head -$entryno series_${field}_${old}.txt | tail -1 | cut -f 1 -d ' '` ; echo $x `echo $oldentry - $newentry | bc -l`\ndone\n\n\n"
  },
  {
    "path": "workspace/concurrent_taskpool/tests_and_benchmarks/benchmarking_scripts/get_series",
    "content": "#!/bin/bash\n\n# e.g. 10 4 1 \"11,13\" concurrent_task_pool_times_t_v11_k_ary_tree_static_vector_inline_list_fixed_all_degrees_1_32.txt [l]\n\nd=$1\nh=$2\nk=$3\nfields=\"$4\"\nfile=$5\n\nif [ $# -eq 5 ]\nthen\n\tcat $file | grep \"tree_degree=$d, tree_height=$h, k_retries=$k,\" | cut -f 3,$fields -d ' '\nelse\n\tcat $file | grep \"tree_degree=$d, tree_height=$h, k_retries=$k,\" | cut -f 3,$fields -d ' ' | sed -e 's/[^0-9 ]*=//g' -e 's/,//g'\nfi\n\n\n"
  },
  {
    "path": "workspace/concurrent_taskpool/tests_and_benchmarks/benchmarking_scripts/get_series_avg",
    "content": "#!/bin/bash\n\n# e.g. 11 3 2 \"11\" \"concurrent_task_pool_times_t_v15_fast_get_per_level_new_test_10M_no_keep_tasks_preallocated_more_threads_aligned_degree_11_h_3_k_2_t_1_32.bare_iron.*\" \n\ndegree=$1\nh=$2\nk=$3\nfield=$4\nfiles=`ls $5`\n\nnofiles=`echo $files | wc -w`\n\ni=0\n\nfor file in $files\ndo\n\ti=`expr $i + 1`\n\t./get_series ${degree} ${h} ${k} \"$field\" $file l | sort -n -k 1 -t ' ' | cut -f 2 -d ' ' > s${i}.txt\ndone\n\nnomsmts=`cat s1.txt | wc -l`\n\nfor msmt in `seq $nomsmts`\ndo\n\tavg=0\n\n\tfor fileindex in `seq $nofiles`\n\tdo\n\t\tnumber=`cat s${fileindex}.txt | head -$msmt | tail -1`\n\t\tavg=`echo $avg + $number | bc -l`\n\tdone\n\tavg=`echo \"scale=0; $avg / $nofiles\" | bc -l`\n\techo $avg\ndone\n\n"
  },
  {
    "path": "workspace/concurrent_taskpool/tests_and_benchmarks/benchmarking_scripts/get_series_q",
    "content": "#!/bin/bash\n\n# e.g. \"10,12\" concurrent_task_pool_times_r.bare_iron.txt\n\nfields=\"$1\"\nfile=$2\n\nif [ $# -eq 2 ]\nthen\n\tcat $file | cut -f 3,$fields -d ' '\nelse\n\tcat $file | cut -f 3,$fields -d ' ' | sed -e 's/[^0-9 ]*=//g' -e 's/,//g'\nfi\n\n\n"
  },
  {
    "path": "workspace/concurrent_taskpool/tests_and_benchmarks/benchmarking_scripts/get_series_r",
    "content": "#!/bin/bash\n\n# e.g. 50000 \"10,12\" concurrent_task_pool_times_r.bare_iron.txt\n\nr=$1\nfields=\"$2\"\nfile=$3\n\nif [ $# -eq 3 ]\nthen\n\tcat $file | grep ring_buffer_size=$r, | cut -f 3,$fields -d ' '\nelse\n\tcat $file | grep ring_buffer_size=$r, | cut -f 3,$fields -d ' ' | sed -e 's/[^0-9 ]*=//g' -e 's/,//g'\nfi\n\n\n"
  },
  {
    "path": "workspace/concurrent_taskpool/tests_and_benchmarks/benchmarking_scripts/get_series_r_avg",
    "content": "#!/bin/bash\n\n# e.g. 5000 \"11\" \"concurrent_task_pool_times_t_v15_fast_get_per_level_new_test_10M_no_keep_tasks_preallocated_more_threads_aligned_degree_11_h_3_k_2_t_1_32.bare_iron.*\" \n\nbuffsize=$1\nfield=$2\nfiles=`ls $3`\n\nnofiles=`echo $files | wc -w`\nfirstfile=`echo $files | cut -f 1 -d ' '`\nnomsmts=`cat $firstfile | wc -l`\n\ni=0\n\nfor file in $files\ndo\n\ti=`expr $i + 1`\n\t./get_series_r ${buffsize} \"$field\" $file l | sort -n -k 1 -t ' ' | cut -f 2 -d ' ' > s${i}.txt\ndone\n\nfor msmt in `seq $nomsmts`\ndo\n\tavg=0\n\n\tfor fileindex in `seq $nofiles`\n\tdo\n\t\tnumber=`cat s${fileindex}.txt | head -$msmt | tail -1`\n\t\tavg=`echo $avg + $number | bc -l`\n\tdone\n\tavg=`echo \"scale=0; $avg / $nofiles\" | bc -l`\n\techo $avg\ndone\n\n"
  },
  {
    "path": "workspace/concurrent_taskpool/tests_and_benchmarks/benchmarking_scripts/rank_param_settings",
    "content": "#!/bin/bash\n\n# e.g. concurrent_task_pool_times_t_v11_k_ary_tree_static_vector_inline_list_fixed_all_degrees_1_32.txt 13 1 32 5\n\nfile=\"$1\"\nfield=$2\nminthreads=$3\nmaxthreads=$4\ntop=$5\n\nfor threads in `seq $minthreads $maxthreads`\ndo\n\ttriples=`cat $file | grep no_threads=$threads, | cut -f 4,5,6,11 -d ' ' | sed -e 's/[ ]*[^0-9]*=/ /g' -e 's/,//g' -e 's/^ //g' | sort -g -k 4 -t ' ' | head -$top | cut -f 1-3 -d ' ' | sed -e 's/ /,/g'`\n\techo \"threads=$threads, \"`echo $triples | sed -e 's/ /) (/g' -e 's/^/(/g' -e 's/$/)/g'`\ndone\n\n\n"
  },
  {
    "path": "workspace/concurrent_taskpool/tests_and_benchmarks/benchmarking_scripts/rank_param_settings_d_h",
    "content": "#!/bin/bash\n\n# e.g. concurrent_task_pool_times_t_v11_k_ary_tree_static_vector_inline_list_fixed_all_degrees_1_32.txt 13 1 32 5\n\nfile=$1\nfield=$2\nminthreads=$3\nmaxthreads=$4\ntop=$5\n\nfor threads in `seq $minthreads $maxthreads`\ndo\n\ttuples=`cat $file | grep no_threads=$threads, | cut -f 4,5,11 -d ' ' | sed -e 's/[ ]*[^0-9]*=/ /g' -e 's/,//g' -e 's/^ //g' | sort -g -k 3 -t ' ' | head -$top | cut -f 1-2 -d ' ' | sed -e 's/ /,/g'`\n\techo \"threads=$threads, \"`echo $tuples | sed -e 's/ /) (/g' -e 's/^/(/g' -e 's/$/)/g'`\ndone\n\n\n"
  },
  {
    "path": "workspace/concurrent_taskpool/tests_and_benchmarks/benchmarking_scripts/rank_param_settings_freqs",
    "content": "#!/bin/bash\n\n# e.g. concurrent_task_pool_times_t_v11_k_ary_tree_static_vector_inline_list_fixed_all_degrees_1_32.txt 13 1 32 5\n\nfile=\"$1\"\nfield=$2\nminthreads=$3\nmaxthreads=$4\ntop=$5\n\nfor threads in `seq $minthreads $maxthreads`\ndo\n\tcat $file | grep no_threads=$threads, | cut -f 4,5,6,11 -d ' ' | sed -e 's/[ ]*[^0-9]*=/ /g' -e 's/,//g' -e 's/^ //g' | sort -g -k 4 -t ' ' | head -$top | cut -f 1-3 -d ' ' | sed -e 's/ /,/g'\ndone | sort | uniq -c | sort -n\n\n\n"
  },
  {
    "path": "workspace/concurrent_taskpool/tests_and_benchmarks/benchmarking_scripts/rank_param_settings_freqs_d_h",
    "content": "#!/bin/bash\n\n# e.g. concurrent_task_pool_times_t_v11_k_ary_tree_static_vector_inline_list_fixed_all_degrees_1_32.txt 13 1 32 5\n\nfile=$1\nfield=$2\nminthreads=$3\nmaxthreads=$4\ntop=$5\n\nfor threads in `seq $minthreads $maxthreads`\ndo\n\tcat $file | grep no_threads=$threads, | cut -f 4,5,11 -d ' ' | sed -e 's/[ ]*[^0-9]*=/ /g' -e 's/,//g' -e 's/^ //g' | sort -g -k 3 -t ' ' | head -$top | cut -f 1-2 -d ' ' | sed -e 's/ /,/g'\ndone | sort | uniq -c | sort -n\n\n\n"
  },
  {
    "path": "workspace/concurrent_taskpool/tests_and_benchmarks/concurrent_task_pool_test_multithreaded.c",
    "content": "/*\n * Copyright (C) 2019-2021 Deutsche Telekom AG\n *\n * Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:\n *\n * 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.\n *\n * 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.\n *\n * 3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission.\n *\n * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS \"AS IS\" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n */\n\n/*\n * A concurrent, scalable, wait-free task pool implementation that performs well under high CAS contention\n *\n * This file contains testing functions for pools\n *\n *  Created on: 22 Jan 2019\n *      Author: aagapi\n */\n\n#define _GNU_SOURCE\n\n#include <stdio.h>\n#include <stdlib.h>\n#include <math.h>\n#include <stdatomic.h>\n#include <time.h>\n#include <pthread.h>\n#include <unistd.h>\n#include <stdarg.h>\n#include <sched.h>\n#include <string.h>\n\n#include \"fastrand.h\"\n\n#include \"concurrent_task_pool.h\"\n\n// For comparative benchmarking:\n#include <liblfds711.h>\n\n#define NO_TASKS 10000\n#define NO_THREADS 1\n\n#define RING_BUFFER_SIZE 1000\n\n// #define VERBOSE\n\n// #define KEEP_TASKS_PUT\n// #define KEEP_TASKS_GET\n\n#define BENCHMARK_TASKPOOL 0\n#define BENCHMARK_LIBLFDS_QUEUE 1\n#define BENCHMARK_LIBLFDS_RINGBUFFER 2\n#define BENCHMARK_MUTEX 3\n#define BENCHMARK_SPINLOCK_ATOMIC_FLAG 4\n#define BENCHMARK_SPINLOCK_PTHREAD 5\n\nint no_tasks = NO_TASKS, no_threads = NO_THREADS, tree_height = DEFAULT_TREE_HEIGHT, k_retries = DEFAULT_K_NO_TRIALS;\nlong num_cpu, ring_buffer_size = RING_BUFFER_SIZE;\nint benchmark_target = BENCHMARK_TASKPOOL;\nint verbose = 0;\nlong * put_errs, * dequeued_elems;\n\n#define NUMBER_OF_NANOSECONDS_IN_ONE_SECOND         1000000000LLU\n\n#if( defined _POSIX_THREADS && _POSIX_TIMERS >= 0 && _POSIX_MONOTONIC_CLOCK >= 0 )\n  #define TIME_UNITS_PER_SECOND( pointer_to_time_units_per_second )  *(pointer_to_time_units_per_second) = NUMBER_OF_NANOSECONDS_IN_ONE_SECOND\n\n  #define GET_HIGHRES_TIME( pointer_to_time )                          \\\n  {                                                                                     \\\n    struct timespec tp;                                                                 \\\n    clock_gettime( CLOCK_MONOTONIC_RAW, &tp );                                          \\\n    *(pointer_to_time) = tp.tv_sec * NUMBER_OF_NANOSECONDS_IN_ONE_SECOND + tp.tv_nsec;  \\\n  }\n#else\n  #error Linux without high resolution timers.\n#endif\n\n\n// Taskpool-related global vars:\n\nconcurrent_pool * pool;\n\nWORD* tasks;\nstruct lfds711_queue_umm_element *qes;\n\nWORD* recovered_tasks;\nstruct lfds711_queue_umm_element *recovered_qes;\n\n\n// Liblfds queue-related global vars:\n\nstruct lfds711_queue_umm_state qs;\n\n// Liblfds ringbuffer-related global vars:\n\nstruct lfds711_ringbuffer_state rs;\nstruct lfds711_ringbuffer_element * re;\n\n// Mutex-related:\n\npthread_mutex_t queue_mutex;\n\n// Spinlock-related:\n\nvolatile atomic_flag queue_spinlock_af;\n\nvoid inline spinlock_lock(volatile atomic_flag *f) {\n    while (atomic_flag_test_and_set(f)) {\n        // spin until we could set the flag\n    }\n}\nvoid inline spinlock_unlock(volatile atomic_flag *f) {\n    atomic_flag_clear(f);\n}\n\n// Libpthread spinlock-related:\n\npthread_spinlock_t queue_spinlock_pthread;\n\n// Basic list structs for benchmarking mutexes & spinlocks:\n\ntypedef struct queue_entry\n{\n\tWORD data;\n\tstruct queue_entry * next;\n} queue_entry;\n\nqueue_entry * queue_head, * queue_tail;\nqueue_entry * simple_qes, * recovered_simple_qes;\n\nvoid *thread_main_put(void *arg)\n{\n    int thread_id = (int) arg, status=0;\n\tint long long unsigned start_put, end_put;\n\tstruct lfds711_queue_umm_element qe;\n\tstruct lfds711_ringbuffer_element elem;\n\tenum lfds711_misc_flag overwrite_occurred_flag;\n\tunsigned int seed;\n\n\tGET_RANDSEED(&seed, thread_id);\n\n\tLFDS711_MISC_MAKE_VALID_ON_CURRENT_LOGICAL_CORE_INITS_COMPLETED_BEFORE_NOW_ON_ANY_OTHER_LOGICAL_CORE;\n\n\tif(verbose)\n\t{\n\t\tGET_HIGHRES_TIME(&start_put);\n\n\t\tprintf(\"[thread %d put] start_time=%lld, no_tasks=%d\\n\", thread_id, start_put, no_tasks/no_threads);\n\t}\n\n\tint first_task_index = thread_id*(no_tasks/no_threads);\n\n\tfor(long i=first_task_index;i<first_task_index+no_tasks/no_threads;i++)\n\t{\n\t\tif(benchmark_target == BENCHMARK_TASKPOOL)\n\t\t{\n#ifdef KEEP_TASKS_PUT\n\t\t\ttasks[i]= (WORD) (i+1);\n\t\t\tstatus = put(tasks[i], pool, &seed);\n#else\n\t\t\tstatus = put((WORD) (i + 1), pool, &seed);\n#endif\n\t\t}\n\t\telse if(benchmark_target == BENCHMARK_LIBLFDS_QUEUE)\n\t\t{\n#ifdef KEEP_TASKS_PUT\n\t\t\tLFDS711_QUEUE_UMM_SET_VALUE_IN_ELEMENT(qes[i],(WORD) (i + 1));\n\t\t\tlfds711_queue_umm_enqueue(&qs, &qes[i]);\n#else\n\t\t\t// NOTE: Due to the way LFDS implements queue elements, this will not work correctly\n\t\t\t// (will corrupt next pointers and the list will end up with a single element).\n\t\t\t// Therefore, we use KEEP_TASKS_PUT when benchmarking the lfds711_queue:\n\t\t\tLFDS711_QUEUE_UMM_SET_VALUE_IN_ELEMENT(qe,(WORD) (i + 1));\n\t\t\tlfds711_queue_umm_enqueue(&qs, &qe);\n#endif\n\t\t}\n\t\telse if(benchmark_target == BENCHMARK_LIBLFDS_RINGBUFFER)\n\t\t{\n\t\t\tlfds711_ringbuffer_write(&rs, (void *) (lfds711_pal_uint_t) (i+1), NULL, &overwrite_occurred_flag, NULL, NULL);\n\n\t\t    if(overwrite_occurred_flag == LFDS711_MISC_FLAG_RAISED )\n\t\t    \t\tstatus=1;\n\t\t}\n\t\telse if(benchmark_target == BENCHMARK_MUTEX ||\n\t\t\t\tbenchmark_target == BENCHMARK_SPINLOCK_ATOMIC_FLAG ||\n\t\t\t\tbenchmark_target == BENCHMARK_SPINLOCK_PTHREAD)\n\t\t{\n\t\t\tif(benchmark_target == BENCHMARK_MUTEX)\n\t\t\t\tpthread_mutex_lock(&queue_mutex);\n\t\t\telse if(benchmark_target == BENCHMARK_SPINLOCK_ATOMIC_FLAG)\n\t\t\t    spinlock_lock(&queue_spinlock_af);\n\t\t\telse if(benchmark_target == BENCHMARK_SPINLOCK_PTHREAD)\n\t\t\t\tpthread_spin_lock(&queue_spinlock_pthread);\n\n#ifdef KEEP_TASKS_PUT\n\t\t\tsimple_qes[i].data = (WORD) (i + 1);\n\t\t\tsimple_qes[i].next = NULL;\n\n\t\t\tif(queue_tail != NULL)\n\t\t\t{\n\t\t\t\tqueue_tail->next = simple_qes + i;\n\t\t\t\tqueue_tail = simple_qes + i;\n\t\t\t}\n\t\t\telse\n\t\t\t{\n\t\t\t\tqueue_tail = simple_qes + i;\n\t\t\t\tqueue_head = simple_qes + i;\n\t\t\t}\n#endif\n\n\t\t\tif(benchmark_target == BENCHMARK_MUTEX)\n\t\t\t\tpthread_mutex_unlock(&queue_mutex);\n\t\t\telse if(benchmark_target == BENCHMARK_SPINLOCK_ATOMIC_FLAG)\n\t\t\t    spinlock_unlock(&queue_spinlock_af);\n\t\t\telse if(benchmark_target == BENCHMARK_SPINLOCK_PTHREAD)\n\t\t\t\tpthread_spin_unlock(&queue_spinlock_pthread);\n\t\t}\n\n\t\tif(status!=0)\n\t\t{\n\t\t\tput_errs[thread_id]++;\n\n\t\t\tif(verbose)\n\t\t\t\tprintf(\"ERROR (thread %d - put): put() attempt %ld failed!\\n\", thread_id, i+1);\n\t\t}\n\t}\n\n\tif(verbose)\n\t{\n\t\tGET_HIGHRES_TIME(&end_put);\n\n\t\tprintf(\"[thread %d put] no_tasks=%d, total_seconds_put=%f, put_tpt=%f, put_latency_ns=%lld\\n\",\n\t\t\t\tthread_id, no_tasks/no_threads,\n\t\t\t\t(end_put-start_put)/(double)NUMBER_OF_NANOSECONDS_IN_ONE_SECOND,\n\t\t\t\t(no_tasks/no_threads) / ((end_put-start_put)/(double)NUMBER_OF_NANOSECONDS_IN_ONE_SECOND),\n\t\t\t\t((end_put-start_put)) / (no_tasks/no_threads));\n\t}\n\n    return NULL;\n}\n\nvoid *thread_main_get(void *arg)\n{\n    int thread_id = (int) arg;\n    int status=0;\n\tint long long unsigned start_get, end_get;\n\tstruct lfds711_queue_umm_element * qep;\n\tvoid *buffer_read_element;\n\tint dequeued_elements = 0;\n\tWORD recovered_task;\n\tunsigned int seed;\n\n\tGET_RANDSEED(&seed, thread_id);\n\n\tLFDS711_MISC_MAKE_VALID_ON_CURRENT_LOGICAL_CORE_INITS_COMPLETED_BEFORE_NOW_ON_ANY_OTHER_LOGICAL_CORE;\n\n\tif(verbose)\n\t{\n\t\tGET_HIGHRES_TIME(&start_get);\n\n\t\tprintf(\"[thread %d get] start_time=%lld, no_tasks=%d\\n\", thread_id, start_get, no_tasks/no_threads);\n\t}\n\n\tdo\n\t{\n\t\tif(benchmark_target == BENCHMARK_TASKPOOL)\n\t\t{\n#ifdef KEEP_TASKS_GET\n\t\t\tstatus = get(recovered_tasks + thread_id*(no_tasks/no_threads) + dequeued_elements, pool, &seed);\n#else\n\t\t\tstatus = get(&recovered_task, pool, &seed);\n#endif\n\t\t}\n\t\telse if(benchmark_target == BENCHMARK_LIBLFDS_QUEUE)\n\t\t{\n#ifdef KEEP_TASKS_GET\n\t\t\tstatus = !lfds711_queue_umm_dequeue(&qs, &qep);\n\t\t\trecovered_tasks[thread_id*(no_tasks/no_threads) + dequeued_elements] = (WORD) LFDS711_QUEUE_UMM_GET_VALUE_FROM_ELEMENT(*qep);\n#else\n\t\t\tstatus = !lfds711_queue_umm_dequeue(&qs, &qep);\n\t\t\tLFDS711_QUEUE_UMM_GET_VALUE_FROM_ELEMENT(*qep);\n#endif\n\t\t}\n\t\telse if(benchmark_target == BENCHMARK_LIBLFDS_RINGBUFFER)\n\t\t{\n#ifdef KEEP_TASKS_GET\n\t\t\tstatus = !lfds711_ringbuffer_read(&rs, recovered_tasks + thread_id*(no_tasks/no_threads) + dequeued_elements, NULL);\n#else\n\t\t\tstatus = !lfds711_ringbuffer_read(&rs, &buffer_read_element, NULL);\n#endif\n\t\t}\n\t\telse if(benchmark_target == BENCHMARK_MUTEX ||\n\t\t\t\tbenchmark_target == BENCHMARK_SPINLOCK_ATOMIC_FLAG ||\n\t\t\t\tbenchmark_target == BENCHMARK_SPINLOCK_PTHREAD)\n\t\t{\n\t\t\tif(benchmark_target == BENCHMARK_MUTEX)\n\t\t\t\tpthread_mutex_lock(&queue_mutex);\n\t\t\telse if(benchmark_target == BENCHMARK_SPINLOCK_ATOMIC_FLAG)\n\t\t\t    spinlock_lock(&queue_spinlock_af);\n\t\t\telse if(benchmark_target == BENCHMARK_SPINLOCK_PTHREAD)\n\t\t\t\tpthread_spin_lock(&queue_spinlock_pthread);\n\n\t\t\tif(queue_head != NULL)\n\t\t\t{\n#ifdef KEEP_TASKS_GET\n\t\t\t\t*(recovered_simple_qes + thread_id*(no_tasks/no_threads) + dequeued_elements) = queue_head;\n#endif\n\t\t\t\tqueue_head = queue_head->next;\n\t\t\t\tif(queue_head == NULL)\n\t\t\t\t\tqueue_tail = NULL;\n\t\t\t}\n\t\t\telse\n\t\t\t{\n\t\t\t\tstatus = 1;\n\t\t\t}\n\n\t\t\tif(benchmark_target == BENCHMARK_MUTEX)\n\t\t\t\tpthread_mutex_unlock(&queue_mutex);\n\t\t\telse if(benchmark_target == BENCHMARK_SPINLOCK_ATOMIC_FLAG)\n\t\t\t    spinlock_unlock(&queue_spinlock_af);\n\t\t\telse if(benchmark_target == BENCHMARK_SPINLOCK_PTHREAD)\n\t\t\t\tpthread_spin_unlock(&queue_spinlock_pthread);\n\t\t}\n\n\t\tif(status==0)\n\t\t\tdequeued_elements++;\n\t\telse\n\t\t\tbreak;\n\n\t\tif(verbose)\n\t\t\tprintf(\"[thread %d get] got task %d\\n\",\n\t\t\t\t\tthread_id, (int) ((benchmark_target == BENCHMARK_TASKPOOL)?(recovered_task):(LFDS711_QUEUE_UMM_GET_VALUE_FROM_ELEMENT(*qep))));\n\t} while(1);\n\n\tdequeued_elems[thread_id]=dequeued_elements;\n\n\tif(verbose)\n\t{\n\t\tGET_HIGHRES_TIME(&end_get);\n\n\t\tprintf(\"[thread %d get] no_tasks=%d, total_seconds_get=%f, get_tpt=%f, get_latency_ns=%lld\\n\",\n\t\t\t\tthread_id, dequeued_elements,\n\t\t\t\t(end_get-start_get)/(double)NUMBER_OF_NANOSECONDS_IN_ONE_SECOND,\n\t\t\t\t(no_tasks/no_threads) / ((end_get-start_get)/(double)NUMBER_OF_NANOSECONDS_IN_ONE_SECOND),\n\t\t\t\t((end_get-start_get)) / (no_tasks/no_threads));\n\t}\n\n    return NULL;\n}\n\n\nint main(int argc, char **argv) {\n\n\tstruct lfds711_queue_umm_element qe_dummy;\n\n\tint status = 0, opt, n;\n\tlong total_put_errs = 0, total_get_errs = 0;\n\tint long long unsigned start_put, end_put, start_get, end_get;\n\n    while ((opt = getopt(argc, argv, \"t:h:k:T:B:R:v\")) != -1)\n    {\n        switch (opt) {\n            case 't':\n            {\n                n = atoi(optarg);\n                no_tasks = (n>0)?n:NO_TASKS;\n                break;\n            }\n            case 'h':\n            {\n                n = atoi(optarg);\n                tree_height = (n>0)?n:DEFAULT_TREE_HEIGHT;\n                break;\n            }\n            case 'k':\n            {\n                n = atoi(optarg);\n                k_retries = (n>0)?n:DEFAULT_K_NO_TRIALS;\n                break;\n            }\n            case 'T':\n            {\n                n = atoi(optarg);\n                no_threads = (n>0)?n:NO_THREADS;\n                break;\n            }\n            case 'B':\n            {\n                if(optarg[0] == 'T')\n                \t\tbenchmark_target = BENCHMARK_TASKPOOL;\n                else if(optarg[0] == 'Q')\n                \t\tbenchmark_target = BENCHMARK_LIBLFDS_QUEUE;\n                else if(optarg[0] == 'R')\n                \t\tbenchmark_target = BENCHMARK_LIBLFDS_RINGBUFFER;\n                else if(optarg[0] == 'M')\n                \t\tbenchmark_target = BENCHMARK_MUTEX;\n                else if(optarg[0] == 'A')\n                \t\tbenchmark_target = BENCHMARK_SPINLOCK_ATOMIC_FLAG;\n                else if(optarg[0] == 'S')\n                \t\tbenchmark_target = BENCHMARK_SPINLOCK_PTHREAD;\n\n                break;\n            }\n            case 'R':\n            {\n                n = atoi(optarg);\n                ring_buffer_size = (n>0)?n:RING_BUFFER_SIZE;\n                break;\n            }\n            case 'v':\n            {\n            \t\tverbose = 1;\n            \t\tbreak;\n            }\n        }\n    }\n\n    num_cpu = sysconf(_SC_NPROCESSORS_ONLN);\n\n// Detect if we have hyperthreading:\n\n    u_int32_t registers[4];\n\n    __asm__ __volatile__ (\"cpuid \" :\n                          \"=a\" (registers[0]),\n                          \"=b\" (registers[1]),\n                          \"=c\" (registers[2]),\n                          \"=d\" (registers[3])\n                          : \"a\" (1), \"c\" (0));\n\n    unsigned CPUFeatureSet = registers[3];\n    unsigned char hyperthreading = CPUFeatureSet & (1 << 28);\n\n    hyperthreading=0; // Assume no hyperthreading\n\n\tif(verbose)\n\t\tprintf(\"Detected num_cpu=%ld, hyperthreading=%d\\n\", num_cpu, hyperthreading);\n\n#ifdef KEEP_TASKS_PUT\n\tif(benchmark_target == BENCHMARK_TASKPOOL)\n\t{\n\t\ttasks = (WORD*) malloc(no_tasks * sizeof(WORD));\n\t}\n\telse if(benchmark_target == BENCHMARK_LIBLFDS_QUEUE)\n\t{\n\t\tqes = (struct lfds711_queue_umm_element *) malloc(no_tasks * sizeof(struct lfds711_queue_umm_element));\n\t}\n#endif\n\n#ifdef KEEP_TASKS_GET\n\tif(benchmark_target == BENCHMARK_TASKPOOL)\n\t{\n\t\trecovered_tasks = (WORD*) malloc(no_tasks * sizeof(WORD));\n\t}\n\telse if(benchmark_target == BENCHMARK_LIBLFDS_QUEUE)\n\t{\n\t\trecovered_qes = (struct lfds711_queue_umm_element *) malloc(no_tasks * sizeof(struct lfds711_queue_umm_element));\n\t}\n#endif\n\n\n\t// Taskpool init:\n\tif(benchmark_target == BENCHMARK_TASKPOOL)\n\t{\n\t\tpool = allocate_pool_with_tree_height(tree_height, no_tasks);\n\t\tset_no_trials(pool, k_retries);\n\t}\n\t// Liblfds queue init:\n\telse if(benchmark_target == BENCHMARK_LIBLFDS_QUEUE)\n\t{\n\t\tlfds711_queue_umm_init_valid_on_current_logical_core(&qs, &qe_dummy, NULL);\n\t}\n\telse if(benchmark_target == BENCHMARK_LIBLFDS_RINGBUFFER)\n\t{\n\t\tre = (struct lfds711_ringbuffer_element *) malloc(sizeof(struct lfds711_ringbuffer_element) * ((ring_buffer_size) + 1));\n\n\t\tlfds711_ringbuffer_init_valid_on_current_logical_core(&rs, re, (ring_buffer_size) + 1, NULL);\n\t}\n\telse if(benchmark_target == BENCHMARK_MUTEX ||\n\t\t\tbenchmark_target == BENCHMARK_SPINLOCK_ATOMIC_FLAG ||\n\t\t\tbenchmark_target == BENCHMARK_SPINLOCK_PTHREAD)\n\t{\n\t\tqueue_head=NULL;\n\t\tqueue_tail=NULL;\n\t\tif(benchmark_target == BENCHMARK_MUTEX)\n\t\t\tpthread_mutex_init(&queue_mutex, NULL);\n\t\telse if(benchmark_target == BENCHMARK_SPINLOCK_PTHREAD)\n\t\t\tpthread_spin_init(&queue_spinlock_pthread, PTHREAD_PROCESS_SHARED);\n\t}\n\n    pthread_t threads_put[no_threads];\n    pthread_t threads_get[no_threads];\n    pthread_attr_t attrs[no_threads];\n    cpu_set_t cpu_set[no_threads];\n    for(int th_id = 0; th_id < no_threads; ++th_id)\n    {\n        pthread_attr_init(&attrs[th_id]);\n        CPU_ZERO(&cpu_set[th_id]);\n\n        int core_id = (th_id % num_cpu) * (hyperthreading+1);\n\n        if(verbose)\n        \t\tprintf(\"Setting thread affinity of thread %d to core %d\\n\", th_id, core_id);\n\n        CPU_SET(core_id, &cpu_set[th_id]);\n#if defined(__linux__) || defined(__APPLE__) || defined(__FreeBSD__)\n        pthread_attr_setaffinity_np(&attrs[th_id], sizeof(cpu_set_t), &cpu_set[th_id]);\n#else\n        printf(\"\\x1b[41;1mSetting thread affinity is not implemented for your OS\\x1b[m\\n\");\n        // __unix__\n#endif\n    }\n\n    put_errs = (long *) malloc(no_threads * sizeof(long));\n    dequeued_elems = (long *) malloc(no_threads * sizeof(long));\n\n\tint last_block_start = (benchmark_target == BENCHMARK_TASKPOOL)?(get_last_block_id(pool)):-1;\n\n\tGET_HIGHRES_TIME(&start_put);\n\n    \tfor(int th_id = 0; th_id < no_threads; ++th_id)\n    {\n        pthread_create(&threads_put[th_id], &attrs[th_id], thread_main_put, (void *) th_id);\n    }\n\n    for(int th_id = 0; th_id < no_threads; ++th_id)\n    {\n        pthread_join(threads_put[th_id], NULL);\n\t\tif(verbose)\n\t\t\tprintf(\"[%d put] exited\\n\", th_id);\n    }\n\n    GET_HIGHRES_TIME(&end_put);\n\n\tstart_get = end_put ;\n\n\tfor(int th_id = 0; th_id < no_threads; ++th_id)\n\t{\n\t\tpthread_create(&threads_get[th_id], &attrs[th_id], thread_main_get, (void *) th_id);\n\t}\n\n\tfor(int th_id = 0; th_id < no_threads; ++th_id)\n\t{\n\t\tpthread_join(threads_get[th_id], NULL);\n\t\tif(verbose)\n\t\t\tprintf(\"[%d get] exited\\n\", th_id);\n\t}\n\n\tGET_HIGHRES_TIME(&end_get);\n\n\ttotal_get_errs = no_tasks;\n\n\tfor(int th_id = 0; th_id < no_threads; ++th_id)\n\t{\n\t\ttotal_put_errs += put_errs[th_id];\n\t\ttotal_get_errs -= dequeued_elems[th_id];\n\t}\n\n\tint tree_degree_pool =  (benchmark_target == BENCHMARK_TASKPOOL)?pool->degree:-1;\n\tint tree_height_pool =  (benchmark_target == BENCHMARK_TASKPOOL)?pool->tree_height:-1;\n\tint k_retries_pool =  (benchmark_target == BENCHMARK_TASKPOOL)?pool->k_no_trials:-1;\n\tint last_block_end = (benchmark_target == BENCHMARK_TASKPOOL)?get_last_block_id(pool):-1;\n\tint last_used_block = (benchmark_target == BENCHMARK_TASKPOOL)?pool->producer_tree->node_id:-1;\n\tint block_size = (benchmark_target == BENCHMARK_TASKPOOL)?(CALCULATE_TREE_SIZE(pool->tree_height, pool->degree)):-1;\n\tint block_fill = (benchmark_target == BENCHMARK_TASKPOOL)?(TREE_FILL_FACTOR(pool->tree_height, pool->degree, pool->k_no_trials)):-1;\n\n\tprintf(\"data_struct=%s, no_tasks=%d, no_threads=%d, tree_degree=%d, tree_height=%d, k_retries=%d, ring_buffer_size=%ld, total_seconds_put=%f, total_seconds_get=%f, put_tpt=%f, put_latency_ns=%lld, get_tpt=%f, get_latency_ns=%lld, put_errs=%ld, get_errs=%ld, prealloc_blocks=%d, dynamicalloc_blocks=%d, unused_blocks=%d, block_size=%d, block_fill=%d\\n\",\n\t\t\t(benchmark_target == BENCHMARK_TASKPOOL)?\"taskpool\":((benchmark_target == BENCHMARK_LIBLFDS_QUEUE)?\"lfds_queue\":\"lfds_ringbuffer\"),\n\t\t\tno_tasks, no_threads, tree_degree_pool, tree_height_pool, k_retries_pool, ring_buffer_size,\n\t\t\t(end_put-start_put)/(double)NUMBER_OF_NANOSECONDS_IN_ONE_SECOND,\n\t\t\t(end_get-start_get)/(double)NUMBER_OF_NANOSECONDS_IN_ONE_SECOND,\n\t\t\tno_tasks / ((end_put-start_put)/(double)NUMBER_OF_NANOSECONDS_IN_ONE_SECOND),\n\t\t\t(end_put-start_put) / no_tasks,\n\t\t\t(no_tasks-total_get_errs) / ((end_get-start_get)/(double)NUMBER_OF_NANOSECONDS_IN_ONE_SECOND),\n\t\t\t(end_get-start_get) / (no_tasks-total_get_errs),\n\t\t\ttotal_put_errs, total_get_errs,\n\t\t\tlast_block_start + 1, last_block_end - last_block_start, last_block_end - last_used_block,\n\t\t\tblock_size, block_fill);\n\n\tif(benchmark_target == BENCHMARK_TASKPOOL)\n\t\tfree_pool(pool);\n\telse if(benchmark_target == BENCHMARK_LIBLFDS_QUEUE)\n\t\tlfds711_queue_umm_cleanup(&qs, NULL);\n\telse if(benchmark_target == BENCHMARK_LIBLFDS_RINGBUFFER)\n\t\tlfds711_ringbuffer_cleanup(&rs, NULL);\n\n\tfree(put_errs);\n\tfree(dequeued_elems);\n\n#ifdef KEEP_TASKS_PUT\n\tif(benchmark_target == BENCHMARK_TASKPOOL)\n\t\tfree(tasks);\n\telse if(benchmark_target == BENCHMARK_LIBLFDS_QUEUE)\n\t\tfree(qes);\n\telse if(benchmark_target == BENCHMARK_MUTEX || benchmark_target == BENCHMARK_SPINLOCK_ATOMIC_FLAG || benchmark_target == BENCHMARK_SPINLOCK_PTHREAD)\n\t\tfree(simple_qes);\n#endif\n\n#ifdef KEEP_TASKS_GET\n\tif(benchmark_target == BENCHMARK_TASKPOOL)\n\t\tfree(recovered_tasks);\n\telse if(benchmark_target == BENCHMARK_LIBLFDS_QUEUE)\n\t\tfree(recovered_qes);\n\telse if(benchmark_target == BENCHMARK_MUTEX || benchmark_target == BENCHMARK_SPINLOCK_ATOMIC_FLAG || benchmark_target == BENCHMARK_SPINLOCK_PTHREAD)\n\t\tfree(recovered_simple_qes);\n#endif\n}\n\n\n"
  },
  {
    "path": "workspace/concurrent_taskpool/tests_and_benchmarks/concurrent_task_pool_test_multithreaded_mixed.c",
    "content": "/*\n * Copyright (C) 2019-2021 Deutsche Telekom AG\n *\n * Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:\n *\n * 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.\n *\n * 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.\n *\n * 3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission.\n *\n * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS \"AS IS\" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n */\n\n/*\n * A concurrent, scalable, wait-free task pool implementation that performs well under high CAS contention\n *\n * This file contains testing functions for pools\n *\n *  Created on: 22 Jan 2019\n *      Author: aagapi\n */\n\n#define _GNU_SOURCE\n\n#include <stdio.h>\n#include <stdlib.h>\n#include <math.h>\n#include <stdatomic.h>\n#include <time.h>\n#include <pthread.h>\n#include <unistd.h>\n#include <stdarg.h>\n#include <sched.h>\n#include <string.h>\n\n#include \"fastrand.h\"\n\n#include \"concurrent_task_pool.h\"\n\n// For comparative benchmarking:\n#include <liblfds711.h>\n\n#define NO_TASKS 10000\n#define NO_THREADS 1\n\n#define RING_BUFFER_SIZE 1000\n\n#define DEFAULT_MAX_BENCHMARK_DURATION_SECONDS 60\n\n// #define VERBOSE\n\n// #define KEEP_TASKS_PUT\n// #define KEEP_TASKS_GET\n\n#define BENCHMARK_TASKPOOL 0\n#define BENCHMARK_LIBLFDS_QUEUE 1\n#define BENCHMARK_LIBLFDS_RINGBUFFER 2\n#define BENCHMARK_MUTEX 3\n#define BENCHMARK_SPINLOCK_ATOMIC_FLAG 4\n#define BENCHMARK_SPINLOCK_PTHREAD 5\n\nint no_tasks = NO_TASKS, no_threads = NO_THREADS, tree_height = DEFAULT_TREE_HEIGHT, k_retries = DEFAULT_K_NO_TRIALS;\nlong num_cpu, ring_buffer_size = RING_BUFFER_SIZE;\nint benchmark_target = BENCHMARK_TASKPOOL;\nint verbose = 0;\nlong * put_errs, * dequeued_elems;\nint long long unsigned * last_dequeues;\nint benchmark_duration_seconds = DEFAULT_MAX_BENCHMARK_DURATION_SECONDS;\n\n#define NUMBER_OF_NANOSECONDS_IN_ONE_SECOND         1000000000LLU\n\n#if( defined _POSIX_THREADS && _POSIX_TIMERS >= 0 && _POSIX_MONOTONIC_CLOCK >= 0 )\n  #define TIME_UNITS_PER_SECOND( pointer_to_time_units_per_second )  *(pointer_to_time_units_per_second) = NUMBER_OF_NANOSECONDS_IN_ONE_SECOND\n\n  #define GET_HIGHRES_TIME( pointer_to_time )                          \\\n  {                                                                                     \\\n    struct timespec tp;                                                                 \\\n    clock_gettime( CLOCK_MONOTONIC_RAW, &tp );                                          \\\n    *(pointer_to_time) = tp.tv_sec * NUMBER_OF_NANOSECONDS_IN_ONE_SECOND + tp.tv_nsec;  \\\n  }\n\n#define GET_LOWRES_LOWOVERHEAD_TIME_SECONDS( pointer_to_time )                          \\\n{                                                                                     \\\n  struct timespec tp;                                                                 \\\n  clock_gettime( CLOCK_MONOTONIC_COARSE, &tp );                                          \\\n  *(pointer_to_time) = tp.tv_sec;  \\\n}\n#else\n  #error Linux without high resolution timers.\n#endif\n\n\n\n// Taskpool-related global vars:\n\nconcurrent_pool * pool;\n\nWORD* tasks;\nstruct lfds711_queue_umm_element *qes;\n\nWORD* recovered_tasks;\nstruct lfds711_queue_umm_element *recovered_qes;\n\n\n// Liblfds queue-related global vars:\n\nstruct lfds711_queue_umm_state qs;\n\n// Liblfds ringbuffer-related global vars:\n\nstruct lfds711_ringbuffer_state rs;\nstruct lfds711_ringbuffer_element * re;\n\n// Mutex-related:\n\npthread_mutex_t queue_mutex;\n\n// Spinlock-related:\n\nvolatile atomic_flag queue_spinlock_af;\n\nvoid inline spinlock_lock(volatile atomic_flag *f) {\n    while (atomic_flag_test_and_set(f)) {\n        // spin until we could set the flag\n    }\n}\nvoid inline spinlock_unlock(volatile atomic_flag *f) {\n    atomic_flag_clear(f);\n}\n\n// Libpthread spinlock-related:\n\npthread_spinlock_t queue_spinlock_pthread;\n\n// Basic list structs for benchmarking mutexes & spinlocks:\n\ntypedef struct queue_entry\n{\n\tWORD data;\n\tstruct queue_entry * next;\n} queue_entry;\n\nqueue_entry * queue_head, * queue_tail;\nqueue_entry * simple_qes, * recovered_simple_qes;\n\nvoid *thread_main_put(void *arg)\n{\n    int thread_id = (int) arg, status=0;\n\tint long long unsigned start_put, end_put;\n\tstruct lfds711_queue_umm_element qe;\n\tstruct lfds711_ringbuffer_element elem;\n\tenum lfds711_misc_flag overwrite_occurred_flag;\n\tunsigned int seed;\n\n\tGET_RANDSEED(&seed, thread_id);\n\n\tLFDS711_MISC_MAKE_VALID_ON_CURRENT_LOGICAL_CORE_INITS_COMPLETED_BEFORE_NOW_ON_ANY_OTHER_LOGICAL_CORE;\n\n\tif(verbose)\n\t{\n\t\tGET_HIGHRES_TIME(&start_put);\n\n\t\tprintf(\"[thread %d put] start_time=%lld, no_tasks=%d\\n\", thread_id, start_put, 2*no_tasks/no_threads);\n\t}\n\n\tint first_task_index = thread_id*(2*no_tasks/no_threads);\n\n\tfor(long i=first_task_index;i<first_task_index+2*no_tasks/no_threads;i++)\n\t{\n\t\tif(benchmark_target == BENCHMARK_TASKPOOL)\n\t\t{\n#ifdef KEEP_TASKS_PUT\n\t\t\ttasks[i]= (WORD) (i+1);\n\t\t\tstatus = put(tasks[i], pool, &seed);\n#else\n\t\t\tstatus = put((WORD) (i + 1), pool, &seed);\n#endif\n\t\t}\n\t\telse if(benchmark_target == BENCHMARK_LIBLFDS_QUEUE)\n\t\t{\n#ifdef KEEP_TASKS_PUT\n\t\t\tLFDS711_QUEUE_UMM_SET_VALUE_IN_ELEMENT(qes[i],(WORD) (i + 1));\n\t\t\tlfds711_queue_umm_enqueue(&qs, &qes[i]);\n#else\n\t\t\t// NOTE: Due to the way LFDS implements queue elements, this will not work correctly\n\t\t\t// (will corrupt next pointers and the list will end up with a single element).\n\t\t\t// Therefore, we use KEEP_TASKS_PUT when benchmarking the lfds711_queue:\n\t\t\tLFDS711_QUEUE_UMM_SET_VALUE_IN_ELEMENT(qe,(WORD) (i + 1));\n\t\t\tlfds711_queue_umm_enqueue(&qs, &qe);\n#endif\n\t\t}\n\t\telse if(benchmark_target == BENCHMARK_LIBLFDS_RINGBUFFER)\n\t\t{\n\t\t\tlfds711_ringbuffer_write(&rs, (void *) (lfds711_pal_uint_t) (i+1), NULL, &overwrite_occurred_flag, NULL, NULL);\n\n\t\t    if(overwrite_occurred_flag == LFDS711_MISC_FLAG_RAISED )\n\t\t    \t\tstatus=1;\n\t\t}\n\t\telse if(benchmark_target == BENCHMARK_MUTEX ||\n\t\t\t\tbenchmark_target == BENCHMARK_SPINLOCK_ATOMIC_FLAG ||\n\t\t\t\tbenchmark_target == BENCHMARK_SPINLOCK_PTHREAD)\n\t\t{\n\t\t\tif(benchmark_target == BENCHMARK_MUTEX)\n\t\t\t\tpthread_mutex_lock(&queue_mutex);\n\t\t\telse if(benchmark_target == BENCHMARK_SPINLOCK_ATOMIC_FLAG)\n\t\t\t    spinlock_lock(&queue_spinlock_af);\n\t\t\telse if(benchmark_target == BENCHMARK_SPINLOCK_PTHREAD)\n\t\t\t\tpthread_spin_lock(&queue_spinlock_pthread);\n\n#ifdef KEEP_TASKS_PUT\n\t\t\tsimple_qes[i].data = (WORD) (i + 1);\n\t\t\tsimple_qes[i].next = NULL;\n\n\t\t\tif(queue_tail != NULL)\n\t\t\t{\n\t\t\t\tqueue_tail->next = simple_qes + i;\n\t\t\t\tqueue_tail = simple_qes + i;\n\t\t\t}\n\t\t\telse\n\t\t\t{\n\t\t\t\tqueue_tail = simple_qes + i;\n\t\t\t\tqueue_head = simple_qes + i;\n\t\t\t}\n#endif\n\n\t\t\tif(benchmark_target == BENCHMARK_MUTEX)\n\t\t\t\tpthread_mutex_unlock(&queue_mutex);\n\t\t\telse if(benchmark_target == BENCHMARK_SPINLOCK_ATOMIC_FLAG)\n\t\t\t    spinlock_unlock(&queue_spinlock_af);\n\t\t\telse if(benchmark_target == BENCHMARK_SPINLOCK_PTHREAD)\n\t\t\t\tpthread_spin_unlock(&queue_spinlock_pthread);\n\t\t}\n\n\t\tif(status!=0)\n\t\t{\n\t\t\tput_errs[thread_id]++;\n\n\t\t\tif(verbose)\n\t\t\t\tprintf(\"ERROR (thread %d - put): put() attempt %ld failed!\\n\", thread_id, i+1);\n\t\t}\n\t}\n\n\tif(verbose)\n\t{\n\t\tGET_HIGHRES_TIME(&end_put);\n\n\t\tprintf(\"[thread %d put] no_tasks=%d, total_seconds_put=%f, put_tpt=%f, put_latency_ns=%lld\\n\",\n\t\t\t\tthread_id, 2*no_tasks/no_threads,\n\t\t\t\t(end_put-start_put)/(double)NUMBER_OF_NANOSECONDS_IN_ONE_SECOND,\n\t\t\t\t(2*no_tasks/no_threads) / ((end_put-start_put)/(double)NUMBER_OF_NANOSECONDS_IN_ONE_SECOND),\n\t\t\t\t((end_put-start_put)) / (2*no_tasks/no_threads));\n\t}\n\n    return NULL;\n}\n\nvoid *thread_main_get(void *arg)\n{\n    int thread_id = (int) arg;\n    int status=0, prev_status=1;\n\tint long long unsigned start_get, end_get, last_dequeue=0;\n\tstruct lfds711_queue_umm_element * qep;\n\tvoid *buffer_read_element;\n\tint dequeued_elements = 0;\n\tWORD recovered_task;\n\tqueue_entry recovered_simple_qe;\n\tunsigned int seed;\n\n\tGET_RANDSEED(&seed, thread_id);\n\n\tLFDS711_MISC_MAKE_VALID_ON_CURRENT_LOGICAL_CORE_INITS_COMPLETED_BEFORE_NOW_ON_ANY_OTHER_LOGICAL_CORE;\n\n\tGET_HIGHRES_TIME(&start_get);\n\n\tif(verbose)\n\t{\n\t\tprintf(\"[thread %d get] start_time=%lld, no_tasks=%d\\n\", thread_id, start_get, 2*no_tasks/no_threads);\n\t}\n\n\tdo\n\t{\n\t\tif(benchmark_target == BENCHMARK_TASKPOOL)\n\t\t{\n#ifdef KEEP_TASKS_GET\n\t\t\tstatus = get(recovered_tasks + thread_id*(no_tasks/no_threads) + dequeued_elements, pool, &seed);\n#else\n\t\t\tstatus = get(&recovered_task, pool, &seed);\n#endif\n\t\t}\n\t\telse if(benchmark_target == BENCHMARK_LIBLFDS_QUEUE)\n\t\t{\n#ifdef KEEP_TASKS_GET\n\t\t\tstatus = !lfds711_queue_umm_dequeue(&qs, &qep);\n\t\t\trecovered_tasks[thread_id*(no_tasks/no_threads) + dequeued_elements] = (WORD) LFDS711_QUEUE_UMM_GET_VALUE_FROM_ELEMENT(*qep);\n#else\n\t\t\tstatus = !lfds711_queue_umm_dequeue(&qs, &qep);\n\t\t\tLFDS711_QUEUE_UMM_GET_VALUE_FROM_ELEMENT(*qep);\n#endif\n\t\t}\n\t\telse if(benchmark_target == BENCHMARK_LIBLFDS_RINGBUFFER)\n\t\t{\n#ifdef KEEP_TASKS_GET\n\t\t\tstatus = !lfds711_ringbuffer_read(&rs, recovered_tasks + thread_id*(no_tasks/no_threads) + dequeued_elements, NULL);\n#else\n\t\t\tstatus = !lfds711_ringbuffer_read(&rs, &buffer_read_element, NULL);\n#endif\n\t\t}\n\t\telse if(benchmark_target == BENCHMARK_MUTEX ||\n\t\t\t\tbenchmark_target == BENCHMARK_SPINLOCK_ATOMIC_FLAG ||\n\t\t\t\tbenchmark_target == BENCHMARK_SPINLOCK_PTHREAD)\n\t\t{\n\t\t\tif(benchmark_target == BENCHMARK_MUTEX)\n\t\t\t\tpthread_mutex_lock(&queue_mutex);\n\t\t\telse if(benchmark_target == BENCHMARK_SPINLOCK_ATOMIC_FLAG)\n\t\t\t    spinlock_lock(&queue_spinlock_af);\n\t\t\telse if(benchmark_target == BENCHMARK_SPINLOCK_PTHREAD)\n\t\t\t\tpthread_spin_lock(&queue_spinlock_pthread);\n\n\t\t\tif(queue_head != NULL)\n\t\t\t{\n#ifdef KEEP_TASKS_GET\n\t\t\t\trecovered_simple_qes[thread_id*(no_tasks/no_threads) + dequeued_elements].data = queue_head->data;\n#else\n\t\t\t\trecovered_simple_qe.data=queue_head->data;\n#endif\n\t\t\t\tqueue_head = queue_head->next;\n\t\t\t\tif(queue_head == NULL)\n\t\t\t\t\tqueue_tail = NULL;\n\n\t\t\t\tstatus = 0;\n\t\t\t}\n\t\t\telse\n\t\t\t{\n\t\t\t\tstatus = 1;\n\t\t\t}\n\n\t\t\tif(benchmark_target == BENCHMARK_MUTEX)\n\t\t\t\tpthread_mutex_unlock(&queue_mutex);\n\t\t\telse if(benchmark_target == BENCHMARK_SPINLOCK_ATOMIC_FLAG)\n\t\t\t    spinlock_unlock(&queue_spinlock_af);\n\t\t\telse if(benchmark_target == BENCHMARK_SPINLOCK_PTHREAD)\n\t\t\t\tpthread_spin_unlock(&queue_spinlock_pthread);\n\t\t}\n\n\t\tif(status==0)\n\t\t{\n\t\t\tdequeued_elements++;\n\t\t}\n\t\telse\n\t\t{\n\t\t\tGET_HIGHRES_TIME(&end_get);\n\n\t\t\tif(prev_status==0)\n\t\t\t\tlast_dequeue=end_get;\n\n\t\t\tif(((end_get - start_get) / NUMBER_OF_NANOSECONDS_IN_ONE_SECOND) > benchmark_duration_seconds)\n\t\t\t\tbreak;\n\t\t}\n\n\t\tprev_status = status;\n\n\t\tif(verbose)\n\t\t{\n\t\t\tint value=-1;\n\n\t\t\tif(status==0)\n\t\t\t{\n\t\t\t\tswitch(benchmark_target)\n\t\t\t\t{\n\t\t\t\t\tcase BENCHMARK_TASKPOOL:\n\t\t\t\t\tcase BENCHMARK_LIBLFDS_QUEUE:\n\t\t\t\t\tcase BENCHMARK_LIBLFDS_RINGBUFFER:\n#ifdef KEEP_TASKS_GET\n\t\t\t\t\t\tvalue = (int) recovered_tasks[thread_id*(no_tasks/no_threads) + dequeued_elements];\n#else\n\t\t\t\t\t\tvalue = (int) recovered_task;\n#endif\n\t\t\t\t\t\tbreak;\n\t\t\t\t\tcase BENCHMARK_MUTEX:\n\t\t\t\t\tcase BENCHMARK_SPINLOCK_ATOMIC_FLAG:\n\t\t\t\t\tcase BENCHMARK_SPINLOCK_PTHREAD:\n#ifdef KEEP_TASKS_GET\n\t\t\t\t\t\tvalue = (int) recovered_simple_qes[thread_id*(no_tasks/no_threads) + dequeued_elements].data;\n#else\n\t\t\t\t\t\tvalue = (int) recovered_simple_qe.data;\n#endif\n\t\t\t\t\t\tbreak;\n\t\t\t\t}\n\n\t\t\t\tprintf(\"[thread %d get] got task %d\\n\", thread_id, value);\n\t\t\t}\n\t\t\telse\n\t\t\t{\n\t\t\t\tprintf(\"[thread %d get] failed to get task %f ago, last dequeue %f ago, start_get=%lld, end_get=%lld, last_dequeue=%lld, dequeued_elements=%d\\n\",\n\t\t\t\t\t\tthread_id,\n\t\t\t\t\t\t(end_get-start_get)/(double)NUMBER_OF_NANOSECONDS_IN_ONE_SECOND,\n\t\t\t\t\t\t(last_dequeue>0)?((last_dequeue-start_get)/(double)NUMBER_OF_NANOSECONDS_IN_ONE_SECOND):-1,\n\t\t\t\t\t\tstart_get, end_get, last_dequeue, dequeued_elements);\n\t\t\t}\n\t\t}\n\t} while(1);\n\n\tGET_HIGHRES_TIME(&end_get);\n\n\tdequeued_elems[thread_id]=dequeued_elements;\n\tlast_dequeues[thread_id]=last_dequeue;\n\n\tif(verbose)\n\t{\n\t\tprintf(\"[thread %d get] no_tasks=%d, total_seconds_get=%f, get_tpt=%f, get_latency_ns=%lld, quit_after=%f\\n\",\n\t\t\t\tthread_id, dequeued_elements,\n\t\t\t\t(dequeued_elements>0)?((last_dequeue-start_get)/(double)NUMBER_OF_NANOSECONDS_IN_ONE_SECOND):-1,\n\t\t\t\t(dequeued_elements>0)?((no_tasks/no_threads) / ((last_dequeue-start_get)/(double)NUMBER_OF_NANOSECONDS_IN_ONE_SECOND)):-1,\n\t\t\t\t(dequeued_elements>0)?(((last_dequeue-start_get)) / (no_tasks/no_threads)):-1,\n\t\t\t\t(end_get-start_get)/(double)NUMBER_OF_NANOSECONDS_IN_ONE_SECOND);\n\t}\n\n    return NULL;\n}\n\n\nint main(int argc, char **argv) {\n\n\tstruct lfds711_queue_umm_element qe_dummy;\n\n\tint status = 0, opt, n;\n\tlong total_put_errs = 0, total_get_errs = 0;\n\tint long long unsigned start_put, end_put, start_get, end_get, start_prealloc, end_prealloc;\n\tchar * struct_type = \"NA\";\n\tint alternate_prod_cons_placement = 0;\n\n    while ((opt = getopt(argc, argv, \"t:h:k:T:B:R:M:av\")) != -1)\n    {\n        switch (opt) {\n            case 't':\n            {\n                n = atoi(optarg);\n                no_tasks = (n>0)?n:NO_TASKS;\n                break;\n            }\n            case 'h':\n            {\n                n = atoi(optarg);\n                tree_height = (n>0)?n:DEFAULT_TREE_HEIGHT;\n                break;\n            }\n            case 'k':\n            {\n                n = atoi(optarg);\n                k_retries = (n>0)?n:DEFAULT_K_NO_TRIALS;\n                break;\n            }\n            case 'T':\n            {\n                n = atoi(optarg);\n                no_threads = (n>0)?n:NO_THREADS;\n                break;\n            }\n            case 'B':\n            {\n            \t\tswitch(optarg[0])\n            \t\t{\n\t\t\t\t\tcase 'Q':\n\t\t\t\t\t{\n\t\t\t\t\t\t\tbenchmark_target = BENCHMARK_LIBLFDS_QUEUE;\n\t\t\t\t\t\t\tstruct_type = \"lfds_queue\";\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\t\t\t\t\tcase 'R':\n\t\t\t\t\t{\n\t\t\t\t\t\t\tbenchmark_target = BENCHMARK_LIBLFDS_RINGBUFFER;\n\t\t\t\t\t\t\tstruct_type = \"lfds_ringbuffer\";\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\t\t\t\t\tcase 'M':\n\t\t\t\t\t{\n\t\t\t\t\t\t\tbenchmark_target = BENCHMARK_MUTEX;\n\t\t\t\t\t\t\tstruct_type = \"pthread_mutex\";\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\t\t\t\t\tcase 'A':\n\t\t\t\t\t{\n\t\t\t\t\t\t\tbenchmark_target = BENCHMARK_SPINLOCK_ATOMIC_FLAG;\n\t\t\t\t\t\t\tstruct_type = \"atomic_flag_spinlock\";\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\t\t\t\t\tcase 'S':\n\t\t\t\t\t{\n\t\t\t\t\t\t\tbenchmark_target = BENCHMARK_SPINLOCK_PTHREAD;\n\t\t\t\t\t\t\tstruct_type = \"pthread_spinlock\";\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\t\t\t\t\tcase 'T':\n\t\t\t\t\tdefault:\n\t\t\t\t\t{\n\t\t\t\t\t\t\tbenchmark_target = BENCHMARK_TASKPOOL;\n\t\t\t\t\t\t\tstruct_type = \"taskpool\";\n\t\t\t\t\t}\n            \t\t}\n\n                break;\n            }\n            case 'R':\n            {\n                n = atoi(optarg);\n                ring_buffer_size = (n>0)?n:RING_BUFFER_SIZE;\n                break;\n            }\n            case 'M':\n            {\n                n = atoi(optarg);\n                benchmark_duration_seconds = (n>0)?n:DEFAULT_MAX_BENCHMARK_DURATION_SECONDS;\n                break;\n            }\n            case 'a':\n            {\n            \t\talternate_prod_cons_placement = 1;\n            \t\tbreak;\n            }\n            case 'v':\n            {\n            \t\tverbose = 1;\n            \t\tbreak;\n            }\n        }\n    }\n\n    num_cpu = sysconf(_SC_NPROCESSORS_ONLN);\n\n// Detect if we have hyperthreading:\n\n    u_int32_t registers[4];\n\n    __asm__ __volatile__ (\"cpuid \" :\n                          \"=a\" (registers[0]),\n                          \"=b\" (registers[1]),\n                          \"=c\" (registers[2]),\n                          \"=d\" (registers[3])\n                          : \"a\" (1), \"c\" (0));\n\n    unsigned CPUFeatureSet = registers[3];\n    unsigned char hyperthreading = CPUFeatureSet & (1 << 28);\n\n    hyperthreading=0; // Assume no hyperthreading\n\n\tif(verbose)\n\t\tprintf(\"Detected num_cpu=%ld, hyperthreading=%d\\n\", num_cpu, hyperthreading);\n\n#ifdef KEEP_TASKS_PUT\n\tif(benchmark_target == BENCHMARK_TASKPOOL)\n\t{\n\t\ttasks = (WORD*) malloc(no_tasks * sizeof(WORD));\n\t}\n\telse if(benchmark_target == BENCHMARK_LIBLFDS_QUEUE)\n\t{\n\t\tqes = (struct lfds711_queue_umm_element *) malloc(no_tasks * sizeof(struct lfds711_queue_umm_element));\n\t}\n\telse if(benchmark_target == BENCHMARK_MUTEX || benchmark_target == BENCHMARK_SPINLOCK_ATOMIC_FLAG || benchmark_target == BENCHMARK_SPINLOCK_PTHREAD)\n\t{\n\t\tsimple_qes = (queue_entry *) malloc(no_tasks * sizeof(struct queue_entry));\n\t}\n#endif\n\n#ifdef KEEP_TASKS_GET\n\tif(benchmark_target == BENCHMARK_TASKPOOL)\n\t{\n\t\trecovered_tasks = (WORD*) malloc(no_tasks * sizeof(WORD));\n\t}\n\telse if(benchmark_target == BENCHMARK_LIBLFDS_QUEUE)\n\t{\n\t\trecovered_qes = (struct lfds711_queue_umm_element *) malloc(no_tasks * sizeof(struct lfds711_queue_umm_element));\n\t}\n\telse if(benchmark_target == BENCHMARK_MUTEX || benchmark_target == BENCHMARK_SPINLOCK_ATOMIC_FLAG || benchmark_target == BENCHMARK_SPINLOCK_PTHREAD)\n\t{\n\t\trecovered_simple_qes = (queue_entry *) malloc(no_tasks * sizeof(struct queue_entry));\n\t}\n#endif\n\n\tGET_HIGHRES_TIME(&start_prealloc);\n\n\t// Taskpool init:\n\tif(benchmark_target == BENCHMARK_TASKPOOL)\n\t{\n\t\tpool = allocate_pool_with_tree_height(tree_height, no_tasks);\n\t\tset_no_trials(pool, k_retries);\n\t}\n\t// Liblfds queue init:\n\telse if(benchmark_target == BENCHMARK_LIBLFDS_QUEUE)\n\t{\n\t\tlfds711_queue_umm_init_valid_on_current_logical_core(&qs, &qe_dummy, NULL);\n\t}\n\telse if(benchmark_target == BENCHMARK_LIBLFDS_RINGBUFFER)\n\t{\n\t\tre = (struct lfds711_ringbuffer_element *) malloc(sizeof(struct lfds711_ringbuffer_element) * ((ring_buffer_size) + 1));\n\n\t\tlfds711_ringbuffer_init_valid_on_current_logical_core(&rs, re, (ring_buffer_size) + 1, NULL);\n\t}\n\telse if(benchmark_target == BENCHMARK_MUTEX ||\n\t\t\tbenchmark_target == BENCHMARK_SPINLOCK_ATOMIC_FLAG ||\n\t\t\tbenchmark_target == BENCHMARK_SPINLOCK_PTHREAD)\n\t{\n\t\tqueue_head=NULL;\n\t\tqueue_tail=NULL;\n\t\tif(benchmark_target == BENCHMARK_MUTEX)\n\t\t\tpthread_mutex_init(&queue_mutex, NULL);\n\t\telse if(benchmark_target == BENCHMARK_SPINLOCK_PTHREAD)\n\t\t\tpthread_spin_init(&queue_spinlock_pthread, PTHREAD_PROCESS_SHARED);\n\t}\n\n\tGET_HIGHRES_TIME(&end_prealloc);\n\n    pthread_t threads_put[no_threads/2];\n    pthread_t threads_get[no_threads/2];\n    pthread_attr_t attrs[no_threads];\n    cpu_set_t cpu_set[no_threads];\n\n    for(int th_id = 0; th_id < no_threads; ++th_id)\n    {\n        pthread_attr_init(&attrs[th_id]);\n        CPU_ZERO(&cpu_set[th_id]);\n\n        int core_id;\n\n        if(alternate_prod_cons_placement)\n        {\n        \t\tif(th_id<no_threads/2)\n        \t\t\tcore_id = 2*th_id % num_cpu;\n        \t\telse\n        \t\t\tcore_id = (2*(th_id-no_threads/2)+1) % num_cpu;\n        }\n        else\n        {\n        \t\tcore_id = (th_id % num_cpu) * (hyperthreading+1);\n        }\n\n        if(verbose)\n        \t\tprintf(\"Setting thread affinity of thread %d (%s) to core %d\\n\",\n        \t\t\t\t\t\tth_id, (th_id<no_threads/2)?\"put\":\"get\", core_id);\n\n        CPU_SET(core_id, &cpu_set[th_id]);\n#if defined(__linux__) || defined(__APPLE__) || defined(__FreeBSD__)\n        pthread_attr_setaffinity_np(&attrs[th_id], sizeof(cpu_set_t), &cpu_set[th_id]);\n#else\n        printf(\"\\x1b[41;1mSetting thread affinity is not implemented for your OS\\x1b[m\\n\");\n        // __unix__\n#endif\n    }\n\n    put_errs = (long *) malloc(no_threads/2 * sizeof(long));\n    dequeued_elems = (long *) malloc(no_threads/2 * sizeof(long));\n    last_dequeues = (int long long unsigned *) malloc(no_threads/2 * sizeof(int long long unsigned));\n\n\tint last_block_start = (benchmark_target == BENCHMARK_TASKPOOL)?(get_last_block_id(pool)):-1;\n\n\tGET_HIGHRES_TIME(&start_put);\n\n    \tfor(int th_id = 0; th_id < no_threads/2; ++th_id)\n    {\n        pthread_create(&threads_put[th_id], &attrs[th_id], thread_main_put, (void *) th_id);\n    }\n\n    \tGET_HIGHRES_TIME(&start_get);\n\n    \tfor(int th_id = 0; th_id < no_threads/2; ++th_id)\n    \t{\n    \t\tpthread_create(&threads_get[th_id], &attrs[th_id+no_threads/2], thread_main_get, (void *) th_id);\n    \t}\n\n    for(int th_id = 0; th_id < no_threads/2; ++th_id)\n    {\n        pthread_join(threads_put[th_id], NULL);\n\t\tif(verbose)\n\t\t\tprintf(\"[%d put] exited\\n\", th_id);\n    }\n\n    GET_HIGHRES_TIME(&end_put);\n\n\tfor(int th_id = 0; th_id < no_threads/2; ++th_id)\n\t{\n\t\tpthread_join(threads_get[th_id], NULL);\n\t\tif(verbose)\n\t\t\tprintf(\"[%d get] exited\\n\", th_id);\n\t}\n\n\tend_get=0;\n\ttotal_get_errs = no_tasks;\n\n\tfor(int th_id = 0; th_id < no_threads/2; ++th_id)\n\t{\n\t\ttotal_put_errs += put_errs[th_id];\n\t\ttotal_get_errs -= dequeued_elems[th_id];\n\t\tif(last_dequeues[th_id] > end_get && dequeued_elems[th_id] > 0)\n\t\t\tend_get = last_dequeues[th_id];\n\t}\n\n\tint tree_degree_pool =  (benchmark_target == BENCHMARK_TASKPOOL)?pool->degree:-1;\n\tint tree_height_pool =  (benchmark_target == BENCHMARK_TASKPOOL)?pool->tree_height:-1;\n\tint k_retries_pool =  (benchmark_target == BENCHMARK_TASKPOOL)?pool->k_no_trials:-1;\n\tint last_block_end = (benchmark_target == BENCHMARK_TASKPOOL)?get_last_block_id(pool):-1;\n\tint last_used_block = (benchmark_target == BENCHMARK_TASKPOOL)?pool->producer_tree->node_id:-1;\n\tint block_size = (benchmark_target == BENCHMARK_TASKPOOL)?(CALCULATE_TREE_SIZE(pool->tree_height, pool->degree)):-1;\n\tint block_fill = (benchmark_target == BENCHMARK_TASKPOOL)?(TREE_FILL_FACTOR(pool->tree_height, pool->degree, pool->k_no_trials)):-1;\n\n\tprintf(\"data_struct=%s, no_tasks=%d, no_threads=%d, tree_degree=%d, tree_height=%d, k_retries=%d, ring_buffer_size=%ld, total_seconds_put=%f, total_seconds_get=%f, put_tpt=%f, put_latency_ns=%lld, get_tpt=%f, get_latency_ns=%lld, put_errs=%ld, get_errs=%ld, prealloc_blocks=%d, dynamicalloc_blocks=%d, unused_blocks=%d, block_size=%d, block_fill=%d, total_seconds_prealloc=%f\\n\",\n\t\t\tstruct_type, no_tasks, no_threads/2, tree_degree_pool, tree_height_pool, k_retries_pool, ring_buffer_size,\n\t\t\t(end_put-start_put)/(double)NUMBER_OF_NANOSECONDS_IN_ONE_SECOND,\n\t\t\t(end_get-start_get)/(double)NUMBER_OF_NANOSECONDS_IN_ONE_SECOND,\n\t\t\tno_tasks / ((end_put-start_put)/(double)NUMBER_OF_NANOSECONDS_IN_ONE_SECOND),\n\t\t\t(end_put-start_put) / no_tasks,\n\t\t\t(no_tasks-total_get_errs) / ((end_get-start_get)/(double)NUMBER_OF_NANOSECONDS_IN_ONE_SECOND),\n\t\t\t(no_tasks>total_get_errs)?((end_get-start_get) / (no_tasks-total_get_errs)):-1,\n\t\t\ttotal_put_errs, total_get_errs,\n\t\t\tlast_block_start + 1, last_block_end - last_block_start, last_block_end - last_used_block,\n\t\t\tblock_size, block_fill,\n\t\t\t(end_prealloc-start_prealloc)/(double)NUMBER_OF_NANOSECONDS_IN_ONE_SECOND);\n\n\tif(benchmark_target == BENCHMARK_TASKPOOL)\n\t\tfree_pool(pool);\n\telse if(benchmark_target == BENCHMARK_LIBLFDS_QUEUE)\n\t\tlfds711_queue_umm_cleanup(&qs, NULL);\n\telse if(benchmark_target == BENCHMARK_LIBLFDS_RINGBUFFER)\n\t\tlfds711_ringbuffer_cleanup(&rs, NULL);\n\n\tfree(put_errs);\n\tfree(dequeued_elems);\n\tfree(last_dequeues);\n\n#ifdef KEEP_TASKS_PUT\n\tif(benchmark_target == BENCHMARK_TASKPOOL)\n\t\tfree(tasks);\n\telse if(benchmark_target == BENCHMARK_LIBLFDS_QUEUE)\n\t\tfree(qes);\n\telse if(benchmark_target == BENCHMARK_MUTEX || benchmark_target == BENCHMARK_SPINLOCK_ATOMIC_FLAG || benchmark_target == BENCHMARK_SPINLOCK_PTHREAD)\n\t\tfree(simple_qes);\n#endif\n\n#ifdef KEEP_TASKS_GET\n\tif(benchmark_target == BENCHMARK_TASKPOOL)\n\t\tfree(recovered_tasks);\n\telse if(benchmark_target == BENCHMARK_LIBLFDS_QUEUE)\n\t\tfree(recovered_qes);\n\telse if(benchmark_target == BENCHMARK_MUTEX || benchmark_target == BENCHMARK_SPINLOCK_ATOMIC_FLAG || benchmark_target == BENCHMARK_SPINLOCK_PTHREAD)\n\t\tfree(recovered_simple_qes);\n#endif\n}\n\n\n"
  },
  {
    "path": "workspace/micke/Makefile",
    "content": "DEBUG ?= 0\n# jemalloc is faster so let's use it by default (if it's found)\nUSE_JEM ?= 1\n\nCC := cc\nCXX := c++\n\nCFLAGS := -std=c11 -Wall -Werror -pedantic -pedantic-errors\nCXXFLAGS := -std=c++11 -Wall -Werror -pedantic -pedantic-errors\nLDFLAGS :=\n\nifeq ($(DEBUG), 1)\n\tCFLAGS += -g -DDEBUG\n\tCXXFLAGS += -g -DDEBUG\nelse\n\tCFLAGS += -O3 -DNDEBUG\n\tCXXFLAGS += -O3 -DNDEBUG\nendif\n\nifeq ($(shell $(CC) -v 2>&1 | grep -c \"clang version\"), 1)\nLDFLAGS += -fuse-ld=bfd\nendif\n\n\n# there's no pkg-config ??\nJEM_LIB?=$(wildcard /usr/lib/x86_64-linux-gnu/libjemalloc.a)\n\nifeq ($(USE_JEM), 1)\nifeq ($(JEM_LIB),)\n$(error jemalloc library not in assumed location, use JEM_LIB=<file location>)\nendif\n$(info Using jemalloc: $(JEM_LIB))\nCFLAGS += -DUSE_JEMALLOC\nLDFLAGS += $(JEM_LIB)\nendif\n\n# for e.g. clock_gettime\nCFLAGS += -D_GNU_SOURCE -D_XOPEN_SOURCE=600\n\nPQUEUE_LIB := ../deps/libpqueue/libpqueue.a\n\nall: bvtest\n\n%.o: %.c\n\t$(CC) $(CFLAGS) -c -o $@ $^\n\nbvtest: bytesview_test.o bytesview.o\n\t$(CC) $(CFLAGS) $(LDFLAGS) -o $@ $^\n\n.PHONY: test\ntest:\n\t@make -C test\n\nclean:\n\trm -f *.a *.o\n\trm -f bvtest\n\n.PHONY: help\nhelp:\n\t@echo \"Targets:\"\n\t@echo \"  all         Same as `kernel`\"\n\t@echo \"  kernel      Build the kernel (test program)\"\n\t@echo \"  test_io     Testing program of IO polling\"\n\t@echo \"  clean       Do some cleaning\"\n\t@echo \"Options:\"\n\t@echo \"  USE_JEM=1   Use jemalloc (default: on)\"\n\t@echo \"              requires a jemalloc .so or .a file (use JEM_LIB=...)\"\n"
  },
  {
    "path": "workspace/micke/bytesview.c",
    "content": "/*\n * Copyright (C) 2019-2021 Data Ductus AB\n *\n * Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:\n *\n * 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.\n *\n * 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.\n *\n * 3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission.\n *\n * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS \"AS IS\" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n */\n\n/* bytesview.c */\n    \n#include <assert.h>\n#include <errno.h>\n#include <stdio.h>\n#include <stdlib.h>\n#include <string.h>\n\n#include \"bytesview.h\"\n\nbytesview_t const _empty = {\n    ._pre = NULL,\n    ._eof = 0,\n    .buf = { ._start = 0, ._end = 0, ._bytes = (uint8_t *) \"\"}\n};\n\n\nact_bv_method_table_t *_bv_meth;\n\n/* ### creation ### */\n\nbytesview_t const *act_bv_init (const uint8_t *b, size_t n, size_t start, const bytesview_t *pre, int closed)\n{\n    size_t len;\n    bytesview_t *bv = (bytesview_t *) malloc(sizeof(bytesview_t));\n\n    bv->_pre = (bytesview_t *) pre;              /* disable warning: discards const qualifier */\n    bv->_eof = closed;\n    if (start >= 0) {\n        bv->buf._start = start;\n    } else {\n        bv->buf._start = 0;\n    }\n    if (n >= 0) {\n        bv->buf._end = bv->buf._start+n;\n    } else {\n        len = strlen((char *) b);\n        bv->buf._end = len - bv->buf._start;\n    }\n    bv->buf._bytes = (uint8_t *) b;              /* disable warning: discards const qualifier */\n      \n    return bv;\n}\n\nbytesview_t const *act_bv_empty()\n{\n    return &_empty;\n}\n\nbytesview_t const *act_bv_fromstr (char const *s)\n{\n    return act_bv_init((uint8_t const *)s, strlen(s), 0, NULL, 0);\n}\n\nbytesview_t const *act_bv_frombuf(bytesview_data_buffer_t const *buf)\n{\n    bytesview_t *bv = (bytesview_t *) malloc(sizeof(bytesview_t));\n\n    bv->_pre = NULL;\n    bv->_eof = 0;\n    bv->buf._start = buf->_start;\n    bv->buf._end = buf->_end;\n    bv->buf._bytes = buf->_bytes;\n\n    return bv;\n}\n\n/* ### analysis ### */\n\nsize_t act_bv_n(bytesview_t const *self)\n{\n    size_t prelen;\n\n    if (self->_pre == NULL) {\n        prelen = 0;\n    } else {\n        prelen = act_bv_n(self->_pre);\n    }\n    return prelen + self->buf._end - self->buf._start;\n}\n\nstatic uint8_t *act_bv_cpybuf(bytesview_t const *self, uint8_t *p)\n{\n    /* copy all bytes to *p */\n\n    uint8_t *q;\n    size_t thislen;\n    \n    if (self->_pre != NULL) {\n        q = act_bv_cpybuf(self->_pre, p);\n    } else {\n        q = p;\n    }\n    thislen = self->buf._end - self->buf._start;\n    memcpy(q, self->buf._bytes+self->buf._start, thislen);\n    return q+thislen;\n}\n\nbytesview_data_buffer_t const *act_bv_tobuf(bytesview_t const *self)\n{\n    size_t n = act_bv_n(self);\n    bytesview_data_buffer_t *p;\n\n#if NDEBUG\n#else\n    uint8_t *q;\n#endif\n\n    if (self->buf._end - self->buf._start == n) {\n        /* no more than one buffer */\n        p = (bytesview_data_buffer_t *) &(self->buf);\n    } else {\n        /* several buffers, must concatenate */\n        p = (bytesview_data_buffer_t *) malloc(sizeof(bytesview_data_buffer_t));\n        p->_bytes = (uint8_t *) malloc (n);\n#if NDEBUG\n        act_bv_cpybuf(self, p->_bytes);\n#else\n        q  = act_bv_cpybuf(self, p->_bytes);\n        assert(q-p->_bytes == n);\n#endif\t\t      \n        p->_start = 0;\n        p->_end = n;\n    }\n    return p;\n}\n\nchar *act_bv_tostr(bytesview_t const *self)\n{\n    size_t n = act_bv_n(self);\n    uint8_t *p, *q;\n    \n    p = (uint8_t *) malloc(n+1);  /* room for NUL character at end */\n    q = act_bv_cpybuf(self, p);\n    assert(q-p == n);\n    *q = 0;    /* NUL character at end */\n    return (char *) p;\n}\n\n\nint act_bv_at_eof (const bytesview_t *self)\n{\n    return self->_eof;\n}\n\n/* ### de-lousing */\nvoid act_bv_showbuf(const bytesview_data_buffer_t *buf)\n{\n    size_t i;\n    size_t thislen;\n    uint8_t *p;\n\n    thislen = buf->_end - buf->_start;\n    p = buf->_bytes+buf->_start;\n    \n    printf(\"[%lu,%lu] b'\", buf->_start, buf->_end);\n    i = 0;\n    while (i++ < thislen) {\n        printf(\"%c\", *p++);\n    }\n    printf(\"'\\n\");\n}\n\nvoid act_bv_show(const bytesview_t *self)\n{\n    if (self == NULL) return;\n\n    act_bv_show(self->_pre);\n    printf(\"_eof=%d - buf= \", self->_eof);\n    act_bv_showbuf(&self->buf);\n}\n\nvoid raise_IncompleteReadError(char *msg)\n{\n    fprintf(stderr, \"IncompleteReadError: %s\\n\", msg);\n    // assert(0==1);\n}\n      \nvoid raise_IndexError(char *msg)\n{\n    fprintf(stderr, \"IndexError: %s\\n\", msg);\n    // assert(0==1);\n}\n\nvoid raise_ValueError(char *msg)\n{\n    fprintf(stderr, \"ValueError: %s\\n\", msg);\n    // assert(0==1);\n}\n\n/* ### consuming data */\n\nvoid act_bv__consume(bytesview_t const *self, int amount, bytesview_t const **prep, size_t *remainingp)\n{\n    bytesview_t const *pre;\n    bytesview_t const *newthis;\n    size_t remaining, newremaining;\n    size_t thislen;\n    \n    if (self->_pre != NULL) {\n        act_bv__consume(self->_pre, amount, &pre, &remaining);     \n    } else {\n        pre = NULL;\n        remaining = amount;\n    }\n    thislen = self->buf._end - self->buf._start;\n    if (remaining < thislen) {\n        newthis = act_bv_init(self->buf._bytes, thislen-remaining, self->buf._start+remaining, pre, self->_eof);\n        newremaining = 0;\n    } else {\n        newthis = pre;\n        newremaining = remaining - thislen;\n    }\n    *prep = newthis;\n    *remainingp = newremaining; \n    return;\n}\n\nbytesview_t const *act_bv_consume(bytesview_t const *self, size_t amount)\n{\n    bytesview_t const *newview;\n    size_t remaining;\n\n    act_bv__consume(self, amount, &newview, &remaining);\n    if (remaining > 0) {\n        raise_IndexError(\"Not enough data to consume\");\n        return NULL;\n    }\n\n    if (newview != NULL) {\n        return newview;\n    } else {\n        return act_bv_empty();\n    }\n}\n\n\nvoid act_bv__read(bytesview_t const *self, int n, int *remainingp, bytesview_t const **initialp)\n{\n    bytesview_t const *initial;\n    int remaining;\n    size_t thislen;\n\n    assert(n>=0);\n\n    if (self->_pre != NULL) {\n        act_bv__read(self->_pre, n, &remaining, &initial);\n    } else {\n        remaining = n;\n        initial = NULL;\n    }\n    thislen = self->buf._end-self->buf._start;\n    if (remaining == 0) {\n        *remainingp = remaining;\n        *initialp = initial;\n    } else if (remaining >= thislen) {\n        *remainingp = remaining-thislen;\n        *initialp = self;\n    } else {\n        /*  0 < remaining < thislen */\n        *remainingp = 0;\n        *initialp = act_bv_init(self->buf._bytes, remaining, self->buf._start, initial, 0);\n    }\n    return;\n}\n\nbytesview_t const *act_bv_read(bytesview_t const *self, size_t n)\n{\n    bytesview_t const *initial;\n    int remaining;\n    int thislen;\n      \n    if (n == -1) {\n        if (!self->_eof) {\n            raise_IncompleteReadError(\"read(-1) on non-closed Bytesview\");\n            return NULL;\n         } else {\n            return (bytesview_t *) self;\n         }\n    } else {\n         /* deliver n bytes, if there are n bytes.\n          * if not, deliver available bytes if closed, error if not closed\n          */\n        thislen = self->buf._end - self->buf._start;\n        if (self->_pre != NULL) {\n            act_bv__read(self->_pre, n, &remaining, &initial);\n        } else {\n            remaining = n;\n            initial = NULL;\n        }\n\n        if (remaining == 0) {\n            if (initial != NULL) {\n                return initial;\n            } else {\n                return act_bv_empty();\n            }\n        } else if (remaining < thislen) {\n            return act_bv_init(self->buf._bytes, remaining, self->buf._start, initial, 0);\n        } else if (remaining > thislen) {\n          if (self->_eof) return (bytesview_t *) self;\n            else raise_IncompleteReadError(\"read(n) on non-closed Bytesview with less than n bytes\");\n            return NULL;\n        } else {\n            /* remaining == thislen */\n          return (bytesview_t *) self;\n        }\n    } \n}\n\nbytesview_t const *act_bv_readline(bytesview_t const *self)\n{\n    return act_bv_readuntil(self, \"\\n\");\n}\n\nstatic void act_bv__readexactly(bytesview_t const *self, size_t n, bytesview_t const **initialp, size_t *remainsp)\n{\n    bytesview_t const *initial;\n    size_t remains, thislen;\n\n    thislen = self->buf._end - self->buf._start;\n    if (self->_pre != NULL) {\n        act_bv__readexactly(self->_pre, n, &initial, &remains);\n    } else {\n        initial = NULL;\n        remains = n;\n    }\n\n    if (remains == 0) {\n        *initialp = initial;\n        *remainsp = remains;\n    } else if (remains >= thislen) {\n        *initialp = (bytesview_t *) self;\n        *remainsp = remains - thislen;\n    } else {\n        /* remains < thislen */\n        *initialp = act_bv_init(self->buf._bytes, remains, self->buf._start, initial, 0);\n        *remainsp = 0;\n    }\n}\n\nbytesview_t const *act_bv_readexactly(const bytesview_t *self, size_t n) {\n    bytesview_t const *initial;\n    size_t remains;\n\n    act_bv__readexactly(self, n, &initial, &remains);\n    if (remains > 0) {\n        raise_IncompleteReadError(\"readexactly(): Too few bytes available\");\n        return NULL;\n    }\n\n    if (initial == NULL) {\n        initial = act_bv_empty();\n    }\n    \n    return initial;\n}\n\nstatic size_t act_bv_min(size_t a, size_t b)\n{\n    if (a <= b) return a;\n    else return b;\n}\n\nstatic int act_bv__readuntil(bytesview_t const *self, void const *separator, size_t seplen,\n    bytesview_data_buffer_t *last,\n    bytesview_t const ** initialp)\n{\n    bytesview_t const *initial;\n    int found;\n    uint8_t *m;\n    size_t idx, lastlen, cpylen, thislen, keeplen;\n\n    if (self->_pre != NULL) {\n        found = act_bv__readuntil(self->_pre, separator, seplen, last, &initial);\n    } else {\n        /* last initialized in act_bv_readuntil() */\n        initial = NULL;\n        found = 0;\n        //printf(\"-\");\t\n    }\n    // last is potential beginning of separator at end of previous buffer(s)\n\n    if (found) {\n        /* last made empty in recursive call */\n        *initialp = initial;\n        return found;\n    }\n    //printf(\"-\\n\");\n    \n    /* still looking - is separator straddling buffers? */\n    lastlen = last->_end - last->_start;\n    thislen = self->buf._end - self->buf._start;\n    cpylen = act_bv_min(seplen-1, thislen);\n    memcpy(last->_bytes+last->_end, self->buf._bytes+self->buf._start, cpylen);\n    lastlen = last->_end += cpylen;\n    /* now, last contains last part of previous plus first part of this */\n    //printf(\"lastlen = %ld, cpylen = %ld\\n\", lastlen, cpylen);\n    //printf(\"last: \");\n    //act_bv_showbuf(last);\n    if (lastlen >= seplen) {\n        // might be straddling, check!\n        m = (uint8_t *) strstr((const char *)last->_bytes+last->_start, separator);\n        if (m != NULL) {\n            found = 1;\n\t    idx = m - (last->_bytes+last->_start);\n            //printf(\"straddling! idx=%ld cpylen=%ld last: [%ld, %ld]\\n\", idx, cpylen, last->_start, last->_end);\n\t    // end of separator at idx + seplen - len(last)\n\t    *initialp = act_bv_init(self->buf._bytes, cpylen-(last->_end-(idx+seplen)), self->buf._start, self->_pre, 0); \n\t    // last->_start = last->_end = 0;\n\t    return found;\n\t}\n    }\n    \n    /* Nope, so search this buffer */\n    m = memmem(self->buf._bytes+self->buf._start, self->buf._end-self->buf._start, separator, seplen);\n    if (m != NULL) {\n\tfound = 1;\n\tidx = m - (self->buf._bytes + self->buf._start);\n        //printf(\"inbuf [%ld, %ld]: idx == %ld\\n\", self->buf._start, self->buf._end, idx);\n\t*initialp = act_bv_init(self->buf._bytes, idx+seplen, self->buf._start, self->_pre, 0);\n\treturn found;\n    }\n    \n    /* Nope, so return last part of this buffer in case separator is straddling */\n    found = 0;\n    if (thislen >= seplen-1) {\n\t/* discard old contents of last */\n\tlast->_start = 0;\n\tlast->_end = seplen-1;\n\tmemcpy(last->_bytes, self->buf._bytes+self->buf._end-(seplen-1), seplen-1);\n\t*(last->_bytes+last->_end) = 0;\n    } else {\n        /* entire this is in last, so just keep end of last */\n        keeplen = act_bv_min(seplen-1, lastlen);\n\tif (keeplen < lastlen) {\n\t    // move end of last up front  \n\t    memcpy(last->_bytes, last->_bytes+last->_end-keeplen, keeplen);\n\t    last->_start = 0;\n\t    last->_end = keeplen;\n \t    *(last->_bytes+last->_end) = 0;\n\t} else {\n\t    /* keep all of last */\n\t}\n    }\n    *initialp = self;\n    return found;\n}\n\nbytesview_t const *act_bv_readuntil(bytesview_t const *self, void const *separator)\n{\n    bytesview_data_buffer_t buf, *last;\n    size_t seplen;\n    bytesview_t const *initial;\n    int found;\n\n    seplen = strlen(separator);\n    last = &buf;\n    last->_start = 0;\n    last->_end = 0;\n    last->_bytes = (uint8_t *) malloc (seplen + seplen -1);   // room for (seplen-1)*2 bytes + nul byte\n    *(last->_bytes) = 0;\n    \n    found = act_bv__readuntil(self, separator, seplen, last, &initial);\n\n    if (found) {\n        if (initial != NULL) {\n            return initial;\n        } else {\n            return act_bv_empty();\n        }\n    } else {\n        if (self->_eof) {\n            raise_IncompleteReadError(\"Separator not found and Bytesview closed\");\n            return NULL;\n        } else {\n            raise_IncompleteReadError(\"Separator not found\");\n            return NULL;\n        }\n    }\n}\n\n/* ### feeding data & closing */\n\nbytesview_t const *act_bv_append(bytesview_t const *self, void const *b, size_t n)\n{\n    if (self->_eof) {\n        raise_ValueError(\"append() on closed Bytesview\");\n\treturn NULL;\n    }\n    if (self->buf._start < self->buf._end) {\n        return act_bv_init(b, n, 0, self, 0);\n    } else {\n        return act_bv_init(b, n, 0, NULL, 0);\n    }\n}\n\nbytesview_t const *act_bv_write(bytesview_t const *self, void const *b, size_t n)\n{\n    if (self->_eof) {\n        raise_ValueError(\"write() on closed Bytesview\");\n\treturn NULL;\n    } \n    return act_bv_append(self, b, n);\n}\n\nbytesview_t const *act_bv_writelines(bytesview_t const *self, void const **data)\n{\n    if (self->_eof) {\n        raise_ValueError(\"writelines() on closed Bytesview\");\n    }\n\n    /* XXX */\n    assert(0);\n    return act_bv_empty();\n}\n\nbytesview_t const *act_bv_close (bytesview_t const *self)\n{\n    if (self->_eof) return (bytesview_t *) self;             /* disable warning: discards const qualifier */\n    return act_bv_init(self->buf._bytes, self->buf._end-self->buf._start, self->buf._start, self->_pre, 1);\n}\n\n\n/* method table */\n\nact_bv_method_table_t _act_bv_method_table = {\n    .init = act_bv_init,\n    .empty = act_bv_empty\n};\n\nvoid act_bv_class_init() {\n    _bv_meth = & _act_bv_method_table;\n}\n\n"
  },
  {
    "path": "workspace/micke/bytesview.h",
    "content": "/* bytesview.h */\n\n/* C version of bytesview\n */\n\n#include <stdint.h>\n#include <sys/types.h>\n\n#define ACT_BV_DEFAULT_BUFFER_SIZE 8192\n\ntypedef struct {\n    size_t _start;\n    size_t _end;\n    uint8_t *_bytes;         /* will usually have size ACT_BV_DEFAULT_BUFFER_SIZE */\n} bytesview_data_buffer_t;\n\ntypedef struct bytesview_t {\n    struct bytesview_t *_pre;\n    int _eof;\n    bytesview_data_buffer_t buf;\n} bytesview_t;\n\nextern void act_bv_class_init();\n\n/* ### Creation ### */\n\nbytesview_t const *act_bv_init(uint8_t const *b, size_t n, size_t start, const bytesview_t *pre, int closed);\n\nbytesview_t const *act_bv_empty();\n\nbytesview_t const *act_bv_frombuf(bytesview_data_buffer_t const *buf);\n\nbytesview_t const *act_bv_fromstr(char const *s);\n\n/* ### Analysis ### */\n\nsize_t act_bv_n(bytesview_t const *self);\n\nbytesview_data_buffer_t const *act_bv_tobuf(bytesview_t const *self);   /* return value SHOULD NOT be mutated */\n\nchar *act_bv_tostr(bytesview_t const *self);   /* return value SHOULD NOT be mutated */\n\nint act_bv_at_eof (bytesview_t const *self);\n\n/* ### De-lousing ### */\n\nvoid act_bv_show(bytesview_t const *self);\n\nvoid act_bv_showbuf(bytesview_data_buffer_t const *buf);\n\nvoid raise_IncompleteReadError(char *msg);\n\nvoid raise_IndexError(char *msg);\n\nvoid raise_ValueError(char *msg);\n\n/* ### Consuming data ### */\n\nbytesview_t const *act_bv_consume(bytesview_t const *self, size_t amount);\n\nbytesview_t const *act_bv_read(bytesview_t const *self, size_t n);\n\nbytesview_t const *act_bv_readline(bytesview_t const *self);\n\nbytesview_t const *act_bv_readexactly(bytesview_t const *self, size_t n);\n\nbytesview_t const *act_bv_readuntil(bytesview_t const *self, void const *separator);\n\n/* ### Adding data ### */\n\nbytesview_t const *act_bv_append(bytesview_t const *self, void const *b, size_t n);\n\nbytesview_t const *act_bv_write(bytesview_t const *self, void const *b, size_t n);\n\nbytesview_t const *act_bv_writelines(bytesview_t const *self, void const **data);\n\nbytesview_t const *act_bv_close (bytesview_t const *self);\n\n\ntypedef int (*BV_INT_T)(int);\ntypedef bytesview_t const * (*BYTESVIEW_INIT_T)(const uint8_t *b, size_t n, size_t start, bytesview_t const *pre, int closed);\ntypedef bytesview_t const * (*BYTESVIEW_EMPTY_T)(bytesview_t const *self);\ntypedef bytesview_t const * (*BYTESVIEW_FROMBUF_T)(bytesview_data_buffer_t const *buf);\ntypedef bytesview_t const * (*BYTESVIEW_FROMSTR_T)(char const *s);\n\n\n\ntypedef struct {\n  BV_INT_T intfunc;\n  BYTESVIEW_INIT_T init;    \t\t/*  = act_bv_init; */\n  BYTESVIEW_EMPTY_T empty;    \t\t/*  = act_bv_empty; */\n  BYTESVIEW_FROMBUF_T frombuf;    \t/*  = act_bv_frombuf; */\n\n} act_bv_method_table_t;\n\n\n"
  },
  {
    "path": "workspace/micke/bytesview.py",
    "content": "# Copyright (C) 2019-2021 Data Ductus AB\n#\n# Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:\n#\n# 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.\n#\n# 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.\n#\n# 3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission.\n#\n# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS \"AS IS\" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n#\n\n# Python version of bytesview\n\n##################################################\n### Bytesview\n\nclass Bytesview():\n\n    _bytes : bytes = None\n    _pre = None\n    _start : int = 0\n    _end : int = 0\n    _eof : bool = False\n    \n    def __init__(self, b, n=None, start=None, pre=None, closed=False):\n        self._bytes = b\n        self._pre = pre \n        self._start = 0 if start is None else start\n        if n is not None:\n            self._end = self._start + n\n        else:\n            self._end = len(b)-self._start\n        self._eof = closed\n\n    ### analysis of Bytesview objects\n    \n    def n(self):\n        return self._end - self._start + (self._pre.n() if self._pre is not None else 0)\n\n    def to_bytes(self):\n        these = self._bytes[self._start:self._end]\n        if self._pre is None:\n            return these\n        else:\n            return self._pre.to_bytes() + these\n\n    ### de-lousing\n\n    def show(self):\n        if self._pre is not None:\n            self._pre.show()\n        print(self._bytes, \"[{}:{}]\".format(self._start,self._end))\n        if self._eof:\n            print(\"_eof = {}\".format(self._eof))\n            \n    ### consuming data\n\n    def _consume(self, amount):\n        if self._pre is not None:\n            (pre, remaining) = self._pre._consume(amount)\n        else:\n            pre = None\n            remaining = amount\n            \n        thislen = self._end - self._start\n        if remaining < thislen:\n            newthis = Bytesview(self._bytes, n=thislen-remaining, start=self._start+remaining, pre=pre)\n            newremaining = 0\n        else:\n            newthis = pre\n            newremaining = remaining - thislen\n        \n        return(newthis,newremaining)\n        \n    def consume(self, amount):\n        # assert(self.n()>=amount)\n        (newview, remaining) = self._consume(amount)\n        if remaining > 0:\n            # raise IndexError\n            return None\n\n        if newview is not None:\n            return newview\n        else:\n            return Bytesview(b'')\n\n#    def _initialbytes(self, amount=a, end=-1, endskip=0):\n#        \n#\n#    def initialbytes(self, end=-1, endskip=0):\n#        # remove data at end of bytesview.\n#        #\n#        # end == -1 implies trimming from eof (so error if -1 and not closed)\n#        # end >= 0 implies end-endskip is the index where returned bytesview object ends.\n#        # remove endskip bytes before end.\n#        if end == -1 and not self._eof:\n#            raise ValueError(\"Trim(end=-1) on non-closed Bytesview\")\n#\n#        if self._pre is None:\n#            \n#        thislen = self._end - self._start\n#        thislen -= \n#        if self._pre is None:\n#            newstartskip = startskip\n#            newend = end\n#            newenskip = endskip\n#            return Bytesview(self._bytes, start=self._start+ \n#        else:\n#            \n#        if start is None:\n#            if end is None or end == -1:\n#                these = self._bytes[self._start:self._end]\n#            else:\n#                these = self._bytes[self._start:self._start+end]\n#        else:\n#            if end is None or end == -1:\n#                these = self._bytes[self._start+start:self._end]\n#            else:\n#                these = self._bytes[self._start+start:self._start+end]\n#        if self._pre is None:\n#            return these\n#        else:\n#            return self._pre.to_bytes() + these\n\n    ### reading out data from a Bytesview object (creating a new)\n    ###\n    ### Raises IncompleteReadError if Bytesview object does not contain\n    ### enough data to fulfill request.\n\n    def _read(self, n):\n       # n is always >= 0\n       if self._pre is not None:\n           (remaining, initial) = self._pre._read(n)\n       else:\n           remaining = n\n           initial = None\n \n       thislen = self._end - self._start\n       if remaining == 0:\n           return (remaining,initial)\n       elif remaining >= thislen:\n           return (remaining-thislen, self)\n       else:  # 0 < remaining < thislen\n           return (0, Bytesview(self._bytes, start=self._start, n=remaining, pre=initial))\n                             \n\n    def read(self, n=-1):                  # (int) -> (bytes, Bytesview) \n       if n == -1:\n           if not self._eof:\n               raise IncompleteReadError(\"read(-1) on non-closed Bytesview\")\n               return None\n           else:\n               return self\n       else:\n           # deliver n bytes, if there are n bytes.\n           # if not, deliver available bytes if closed, error if not closed\n           thislen = self._end - self._start\n           if self._pre is not None:\n               (remaining, initial) = self._pre._read(n)\n           else:\n               remaining = n\n               initial = None\n\n           if remaining == 0:\n               return initial if initial is not None else Bytesview(b'')\n           elif remaining < thislen:\n               return Bytesview(self._bytes, n=remaining, start=self._start, pre=initial)\n           elif remaining > thislen:\n               if self._eof:\n                   return self\n               else:\n                   #raise IncompleteReadError(\"read(n) on non-closed Bytesview with less than n bytes\")\n                   return None\n           else:\n               # remaining == thislen\n               return self\n        \n    def readline(self):\n        return self.readuntil (separator=b'\\n')\n\n    def _readexactly(self, n):\n        thislen = self._end - self._start\n        if self._pre:\n            (initial, remains) = self._pre._readexactly(n)\n        else:\n            (initial, remains) = (None, n)\n\n        if remains == 0:\n            return (initial, remains)\n        elif remains >= thislen:\n            return (self, remains-thislen)\n        else:\n            # remains < thislen\n            return (Bytesview(self._bytes, start=self._start, n=remains, pre=initial), 0)\n        \n    def readexactly(self, n):\n        (initial, remains) = self._readexactly(n)\n        if remains > 0:\n            #raise IncompleteReadError(\"readexactly(): Too few bytes available\")\n            return None\n        if initial is None:\n            initial = Bytesview(b'')\n        return initial \n    \n    def _readuntil(self, separator, seplen):\n        # len(last) < len(separator)\n        if self._pre is not None:\n            (last, initial, found) = self._pre._readuntil(separator, seplen)\n        else:\n            (last, initial, found) = (b'', None, False)\n\n        # last is potential beginning of separator at end of previous Bytesview(s)\n\n        if found:\n            return (b'',initial, found)\n        else:\n            buf = last+self._bytes[self._start:self._start+seplen-1]\n            idx = buf.find(separator)\n            if idx >= 0:   # found it!\n                # end of separator at ix+seplen-len(last)\n                #print (buf, len(buf), last, len(last), sep, idx)\n                return (b'', Bytesview(self._bytes, n=idx+seplen-len(last),\n                                       start=self._start,\n                                       pre=self._pre), True)\n            idx = self._bytes.find(separator, self._start)\n            if idx >= 0:   # found it!\n                return (b'', Bytesview(self._bytes, n=idx-self._start+seplen, start=self._start, pre=self._pre), True)\n            thislen = self._end-self._start\n            if thislen >= seplen-1:\n                last = self._bytes[self._end-(seplen-1):self._end]\n            else:\n                last = last[thislen-(seplen-1):] + self._bytes[self._start:self._end]\n            return (last, self, False)\n                    \n    def readuntil(self, separator=b'\\n'):\n        seplen = len(separator)\n        (_, initial, found) = self._readuntil(separator, seplen)\n        if found:\n            return initial if initial is not None else Bytesview(b'')\n        else:\n            if self._eof:\n                #raise IncompleteReadError(\"Separator not found and Bytesview closed\")\n                return None\n            else:\n                #raise IncompleteReadError(\"Separator not found\")\n                return None\n    \n    def at_eof(self):\n        return self._eof and self._pre is None and self._start == self._end\n    \n    ### feeding data & closing\n    \n    def append(self, b, n=None):\n        if self._eof:\n            #raise ValueError(\"append() on closed Bytesview\")\n            return None\n        if self._start < self._end:\n            return Bytesview(b, n=n, pre=self)\n        else:\n            return Bytesview(b, n=n)\n\n    def write(self, b, n=None):  \t# same as append(self, b, n=None)\n        if self._eof:\n            #raise ValueError(\"write() on closed Bytesview\")\n            return None\n        return self.append(b, n)\n        \n    def writelines(self,data):\n        if self._eof:\n            #raise ValueError(\"writelines() on closed Bytesview\")\n            return None\n        for b in data:\n            self.append(b)\n        \n    def close(self):\n        if self._eof:\n            return self\n        return Bytesview(self._bytes, n=self._end-self._start, start=self._start, pre=self._pre, closed=True)\n\n##################################################\n### Unit tests\n\ndef report(bv, name):\n    print (name+\" = \", bv)\n    print (name+\".n() = \", bv.n())\n#    print (name+\"limits() = \", bv.limits())\n    print (name+\".to_bytes() = \", bv.to_bytes())\n    print (name+\".show():\")\n    bv.show()\n\nby = b'0123456789abcdef'\n\n#l = len(by)\n#print(\"by = \",by)\n#print(\"l = \", l)\n#\n#bv1 = Bytesview(by)\n#bv2 = Bytesview(by, n=16)\n#                 \n#report(bv1, \"bv1\")\n#report(bv2, \"bv2\")\n\nbv3 = bv2.append(by, n=16)\n#report(bv2, \"bv2\")\n#report(bv3, \"bv3\")\n\nbv4 = bv3.append(by)\n#report(bv4,\"bv4\")\n\n#bv = bv4\n#n=0\n#while True: \n#   res = bv.consume(n)\n#   print(\"\")\n#   res.show()\n#   #print(res.to_bytes())\n#   n += 1   \n\n###########\n### read()\n#\n#bv = bv4\n#n=0\n#while True: \n#   res = bv.read(n)\n#   print(\"\")\n#   res.show()\n#   #print(res.to_bytes())\n#   n += 1   \n\n#print(\"read() test\")\n\n#bv = bv4\n#n=0\n#while n < 60: \n#   res = bv.read(n)\n#   print(res.to_bytes())\n#   n += 1\n\n#bv = bv4.close()\n#print(\"bv length: \", bv.n())\n#\n#n=0\n#while n < 60: \n#   res = bv.read(n)\n#   print(res.to_bytes())\n#   n += 1\n\n#bv = bv4.close()\n#print(\"bv length: \", bv.n())\n#\n#n=0\n#while n < 60: \n#   res = bv.read(n)\n#   print(res.to_bytes())\n#   res.show()\n#   n += 1\n\n###########\n### readuntil()\n#\n\n#separators = by+b'x'+by+b'y'+by+b'z'+by+b'w'\n#bv = Bytesview(by+b'x').append(by+b'y').append(by+b'z').append(by)\n#bv.close()\n#print(\"bv length: \", bv.n())\n#\n#n=0\n#while n < 4*16+3+5:\n#    sep = separators[n:n+7]\n#    res = bv.readuntil(separator=sep)\n#    print(sep, \" \", res.to_bytes())\n#    res.show()\n#    n += 1\n\ndef bv_list(bv=None):\n    bvl = bv if bv is not None else Bytesview(b'')\n    n = 0\n    while n < 16:\n        bvl = bvl.append(by[n:n+1])\n        n += 1\n    return bvl\n\nbvl = bv_list().append(b'x')\nbvl = bv_list(bvl).append(b'y')\nbvl = bv_list(bvl).append(b'z')\nbvl = bv_list(bvl)\n\nprint (\"bvl: \", bvl.to_bytes())\nbvl.show()\n\n#bv.close()\nprint(\"bv length: \", bvl.n())\n\nseparators = by+b'x'+by+b'y'+by+b'z'+by+b'w'\nn=0\nwhile n < 4*16+3+5:\n    sep = separators[n:n+7]\n    res = bvl.readuntil(separator=sep)\n    print(sep, \" \", res.to_bytes())\n    res.show()\n    n += 1   \n\n###########\n### readexactly()\n#\n\n#bv = Bytesview(by+b'x').append(by+b'y').append(by+b'z').append(by)\n#bv.close()\n#print(\"bv length: \", bv.n())\n#\n#n=0\n#while n < 4*16+3+5:\n#    res = bv.readexactly(n)\n#    print(res.to_bytes())\n#    #res.show()\n#    n += 1\n#\n\n\n"
  },
  {
    "path": "workspace/micke/bytesview_test.c",
    "content": "/*\n * Copyright (C) 2019-2021 Data Ductus AB\n *\n * Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:\n *\n * 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.\n *\n * 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.\n *\n * 3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission.\n *\n * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS \"AS IS\" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n */\n\n/* bytesview_test.c */\n    \n#include <assert.h>\n#include <errno.h>\n#include <stdio.h>\n#include <stdlib.h>\n#include <string.h>\n\n#include \"bytesview.h\"\n\nvoid report(bytesview_t const *bv, char *name)\n{\n    \n    printf(\"%s.n() = %ld\\n\", name, act_bv_n(bv));\n    printf(\"%s.tostr() = %s\\n\", name, act_bv_tostr(bv));\n    printf(\"%s.show():\\n\", name);\n    act_bv_show(bv);\n    printf(\"\\n\");\n}\n\n\nvoid consumetest(bytesview_t const *bv, int additional, int show)\n{  \n    bytesview_t const *bvr;\n\n    size_t i, iterations;\n\n    printf(\"consume test (show=%d)\\n\", show);\n    printf(\"=====================\\n\");\n    printf(\"bv: b'%s'\\n\", act_bv_tostr(bv));\n    printf(\"additional: %d\\n\", additional);\n    printf(\"---\\n\");\n\n    iterations = act_bv_n(bv) + 2;\n    i = 0;\n    while (i < iterations) {\n        bvr = act_bv_consume(bv, i);\n\tif (additional>0 && bvr != NULL) bvr = act_bv_consume(bvr, additional);\n        if (show) {\n\t    if (bvr != NULL) report(bvr,\"bvr\");\n\t    else printf(\"NULL\\n\");\n        } else {\n\t    if (bvr != NULL) printf(\"bvr: b'%s'\\n\", act_bv_tostr(bvr));\n\t    else printf(\"NULL\\n\");\n\t}\n        i++;\n    }\n}\n\nvoid readtest(bytesview_t const *bv, int show)\n{  \n    bytesview_t const *bvr;\n\n    size_t i, iterations;\n\n    printf(\"read test (show = %d)\\n\", show);\n    printf(\"====================\\n\");\n    iterations = act_bv_n(bv) + 2;\n    // iterations = 3;\n    i = 0;\n    while (i < iterations) {\n        bvr = act_bv_read(bv, i);\n        if (show) {\n            if (bvr != NULL) report(bvr,\"bv\");\n            else printf(\"NULL\\n\");\n\t} else {\n\t    if (bvr != NULL) printf(\"b'%s'\\n\", act_bv_tostr(bvr));\n\t    else printf(\"NULL\\n\");\n\t}\t  \n        i++;\n    }\n}\n\nvoid readexactlytest(bytesview_t const *bv, int show)\n{  \n    bytesview_t const *bvr;\n\n    size_t i, iterations;\n\n    printf(\"readexactly test (show = %d)\\n\", show);\n    printf(\"===========================\\n\");\n    iterations = act_bv_n(bv) + 2;\n    // iterations = 3;\n    i = 0;\n    while (i < iterations) {\n        bvr = act_bv_readexactly(bv, i);\n        if (show) {\n            if (bvr != NULL) report(bvr,\"bv\");\n            else printf(\"NULL\\n\");\n\t} else {\n\t    if (bvr != NULL) printf(\"b'%s'\\n\", act_bv_tostr(bvr));\n\t    else printf(\"NULL\\n\");\n\t}\t  \n        i++;\n    }\n}\n\nvoid readuntiltest(bytesview_t const *bv, char *sep, int show)\n{  \n    bytesview_t const *bvr;\n    bytesview_t const *bvs;\n\n    size_t seplen = strlen(sep);\n\n    size_t i, iterations;\n\n    printf(\"readuntil test (show = %d)\\n\", show);\n    printf(\"=========================\\n\");\n    printf(\"data = '%s'\\n\", act_bv_tostr(bv));\n    printf(\"separator ='%s'\\n\", sep);\n    printf(\"seplen = %ld\\n\", seplen);\n    printf(\"---\\n\");\n    \n    iterations = act_bv_n(bv) + 2;\n\n    i = 0;\n    while (i < iterations) {\n        bvr = act_bv_consume(bv, i);\n        if (bvr != NULL) {\n\t    bvs = act_bv_readuntil(bvr, sep);\n\t    if (show) {\n\t\tif (bvr != NULL) printf(\"bvr: b'%s'\\n\", act_bv_tostr(bvr));\n\t\telse printf(\"bvr: NULL\\n\");\n\t\tif (bvs != NULL) report(bvs,\"bvs\");\n\t\telse printf(\"bvs: NULL\\n\");\n\t    } else {\n\t\tif (bvr != NULL) printf(\"b'%s'\\n\", act_bv_tostr(bvr));\n\t\telse printf(\"NULL\\n\");\n\t\tif (bvs != NULL) printf(\"b'%s'\\n\", act_bv_tostr(bvs));\n\t\telse printf(\"NULL\\n\");\t\t\n\t    }\n\t}\n        i++;\n    }\n}\n\nint main() {\n\n    char *by = \"0123456789abcdef\";\n\n    bytesview_data_buffer_t b = { ._start = 0, ._end = 16, ._bytes = (uint8_t *) by };\n\n    size_t l = strlen(by);\n    //int j;\n    \n    bytesview_t const *bv1;\n    bytesview_t const *bv2;\n    bytesview_t const *bv3;\n    bytesview_t const *bv4;\n    bytesview_t const *bv5;\n    \n    bv1 = act_bv_fromstr(by);\n    report(bv1, \"bv1\");\n\n    bv2 = act_bv_frombuf(&b);\n    report(bv2, \"bv2\");\n\n    bv3 = act_bv_append(bv2, by, l);\n    report(bv3, \"bv3\");\n    \n    bv4 = act_bv_append(bv1, \"x\", 1);\n    bv4 = act_bv_append(bv4, by, 16);\n    bv4 = act_bv_append(bv4, by, 16);\n    bv4 = act_bv_append(bv4, \"z\", 1);\n    bv4 = act_bv_append(bv4, by, 16);\n    bv4 = act_bv_append(bv4, \"w\", 1);\n    report(bv4, \"bv4\");\n\n    bv5 = act_bv_close(bv4);\n    report(bv5, \"bv5\");\n    \n    //consumetest(bv4, 20, 1);\n    \n    //consumetest(bv5);\n    \n    //readtest(bv4,1);\n    //readtest(bv4,0);\n\n    //readtest(bv5,1);\n    //readtest(bv5,0);\n\n    //readexactlytest(bv4,1);\n    //readexactlytest(bv4,0);\n\n    //readexactlytest(bv5,1);\n    //readexactlytest(bv5,0);\n\n    //    readuntiltest(bv4,\"0123456\",0);  // OK!\n    //    readuntiltest(bv4,\"x\",0);  // OK!\n    //    readuntiltest(bv4,\"fz\",0);  // OK!\n    //    readuntiltest(bv4,\"z0\",0);  // OK!\n    //    readuntiltest(bv4,\"fz0\",0);  // OK!\n    //    readuntiltest(bv4,\"efz\",0);  // OK!\n    //    readuntiltest(bv4,\"z01\",0);  //OK!\n    //    readuntiltest(bv4,\"9ab\",0);  //OK!\n    //readuntiltest(bv4,\"def012\",0);  //OK!\n    //readuntiltest(bv4,\"def012\",0);  //OK\n    readuntiltest(bv4,\"f0123\",0);  //OK!\n    readuntiltest(bv4,\"cdef0\",0);  //OK!\n\n    //readuntiltest(bv4,\"9\",1);\n    //readuntiltest(bv4,\"9a\",0);\n\n    //readuntiltest(bv5,,1);\n    //readuntiltest(bv5,bv4,0);\n\n    return 0;\n}\n \n"
  },
  {
    "path": "workspace/micke/flow.txt",
    "content": "# Definitions for interface between producing and consuming sides of\n# a data flow with simple flow control.\n#\n# Producer delivers data by calling deliver_data() of Consumer. \n\nstruct Consumer(Type, Error):\n    # methods that may be called by associated producer\n    \n    deliver_data: (Type) -> bool  # Delivery of data to be consumed.\n                                  # Always succeeds.\n    \t\t       \t  \t  # return True equivalent with encourage()\n\t\t\t\t  # return False equivalent with discourage()\n\n    is_closed: () -> bool\t  # True when any data delivered will be ignored\n\n    producer_closed: () -> None   # Producer promises it will never call\n                                  # deliver_data() again. Called exactly once.\n\n    producer_error: (Error) -> None # Error condition reported by Producer\n                                  \n\t\t\t\t  \nstruct Producer(Error):\n    # methods that may be called by associated consumer\n    \n    discourage: () -> None        # consumer asks producer to slow down\n    encourage: () -> None\t  # consumer asks producer to deliver\n    is_discouraged: () -> bool    # Am I delivering or am I slowed down?\n\n    close: (opt(bool)) -> None    # close(True) - Consumer wants all data\n                                  #    currently available, but\n\t\t\t\t  #    nothing more after that. Default.\n\t\t\t\t  # close(False) - Consumer wants no more data,\n\t\t\t\t  #    effective immediately\n\n    is_closed: () -> bool\t  # True iff producer will not deliver any more\n                                  #    data.\n\t\t\t\t  \n    consumer_error: (Error) -> None # Error condition reported by Consumer.\n\n\n# Flow control:\n#     Consumer buffers data delivered by deliver_data(data) as needed.\n#     No blocking.\n#     If Consumer deems it is busy or has buffered enough, it will\n#     return False and/or call discourage() to inform Producer.\n#     When at some later time the Consumer deems it is ready to accept more\n#     data, it informs producer by calling encourage().\n#     Calls to discourage() and deliver_data() returning False are idempotent.\n#     Calls to encourage() and deliver_data() returning True are idempotent.\n#\n#     A Consumer that represents an outgoing OS socket, SHOULD call\n#     discourage() or have deliver_data() return False whenever an OS send()\n#     operation would have blocked. It SHOULD call encourage() when it has sent\n#     all its buffered data and can send() without blocking.\n#\n#     A Producer that represents an incoming OS socket, SHOULD react to\n#     discourage() or deliver_data() returning False by no longer receiving\n#     data from the socket. It MUST NOT receive data from the socket only to\n#     buffer it. The intended sequence of events is that discourage() stops\n#     receiving from the socket, so that the receive buffer of the socket\n#     fills up, which will cause the flow-control mechanisms of TCP (assuming\n#     a TCP socket) to pace or stop the network peer sending to the socket.\n#     A Producer SHOULD react to encourage() by again receiving from the socket\n#     whenever there is data to receive, and delivering received data using the\n#     deliver_data() method of its associated consumer. \n"
  },
  {
    "path": "workspace/micke/processing.txt",
    "content": "Processing of an incoming NETCONF RPC\n=====================================\n\nIP + TCP + receive buf + sockets in OS kernel\n\n  |\n  | stream of bytes, delivered in chunks by OS recv() syscall \n  |\n  V\n\nSSH impl \n     processes an encrypted stream consisting of ssh packets.\n     After key exchange, the stream is decrypted and then deframed\n     and demultiplexed, producing sequences of ssh packet streams,\n     one per open ssh channel.\n\n  SSH decrypt + byte order + deframing + trimming of frames + demultiplexing\n  \n  |                             |   |   |  ...  |\n  | decrypted ssh packets       |   |   |  ...  |\n  |                             |   |   |  ...  |\n  V                             V   V   V       V\n\nNETCONF subsystem\n  One NETCONF session per SSH channel\n  processes stream of channel data chunks\n  produces sequence of NETCONF frames\n\n  NETCONF deframing + trimming of frames\n\n  |\n  | utf-8 encoded XML documents representing NETCONF RPC:s\n  |\n  V\n  \n  utf-8 decoding (bytes -> string)\n\n  |\n  | XML-encoded NETCONF RPC:s           \n  |                                     \n  V                                     \n\n  XML parsing                           \n                                        \n  |                             \n  | XML trees                   \n  |                             \n  V                             \n                                \n  XML Operations -> XML replies\n  \n                          |\n                          |  XML trees\n\t\t\t  |\n\t\t\t  V\n\n\t\t\t  XML printing\n\n\t\t\t  |\n\t\t\t  | XML-encoded NETCONF RPC-REPLIES\n\t\t\t  |\n\t\t\t  V\n \t\t\t  \n                          utf-8 encoding (string -> bytes)\n\n                          |\n                          | utf-8 encoded XML for NETCONF RPC-REPLIES\n                          |\n\t\t\t  V\n\n                          NETCONF framing (adding framing headers & trailers)\n\t\t\t  \n                          |                  |   |  . . .  |\n                          | NETCONF frames   |   |  . . .  |\n                          |                  |   |  . . .  |\n\t\t\t  V                  V   V         V\n\n                        SSH system\n\n                          multiplexing per-channel data into single SSH pipe\n\t\t\t  adding headers & trailers to data chunks\n                          byte ordering\n\n                          |\n                          |  plaintext SSH packets\n                          |\n\t\t\t  V\n\n                          SSH encryption\n\t\t\t  \n                          |\n                          |  stream of bytes (encrypted multiplexed SSH packets)\n                          |\n\t\t\t  V\n\n                        OS send() syscall\n\t\t\tOS sockets + send buf + TCP + IP\n"
  },
  {
    "path": "workspace/misc-examples/divtest.act",
    "content": "import numpy as np\nimport math\n\nactor main(env):\n  print(3/5)\n  print(3.2/1.6)\n  a = np.arange(1, 10)\n  b = np.full(a.shape,2)\n  print(a/b)\n  c = np.linspace(0,5,5)\n  d = np.array([2.5] * 5)\n  print(c/d)\n  env.exit(0)\n  "
  },
  {
    "path": "workspace/misc-examples/loess_smoother.act",
    "content": "import numpy\nimport math\n\ndef loess(x, y, xin, win):\n    win1 = win-1                                # to be compatible with Loess.py and Loess_with_np.py\n    xd = numpy.abs(xin[:,numpy.newaxis] - x)\n    q = xd/numpy.partition(xd,win1)[:,win1][:,numpy.newaxis]\n    w  = numpy.clip(q, 0.0, 1.0)\n    ws  = (1.0 - w ** 3.0) ** 3.0\n    a00 = numpy.sum(ws,1)\n    a01 = numpy.dot(ws, x)\n    a11 = numpy.dot(ws, x*x)\n    b0  = numpy.dot(ws, y)\n    b1  = numpy.dot(ws, x*y)\n    det = a00*a11-a01*a01\n    return ((a11*b0 - a01*b1) + (-a01*b0 + a00*b1)*xin)/det\n\ndef sample():\n    x = numpy.linspace(0.0, 10.0, 101)\n    y = numpy.unirandfloat(1.0, 3.0, 101) + math.sin(x)\n    z = loess(x, y, x, 40)\n    print(\"clear\\n$data <<EOD\");\n    for i in range(101):\n       print(x[i],y[i],z[i])\n    print(\"EOD\")\n    print(\"plot [0:10][0:5] \\'$data\\' using 1:2 with points title \\\"raw data\\\", \\\\\")\n    print(\"\\'$data\\' using 1:3 with lines title \\\"loess smoothed\\\"\")\n    after 4: sample()\n    \nactor main(env):\n    print (\"set terminal aqua title \\\"Loess smoothening\\\"\")\n    print(\"set multiplot\\nplot  [0:10][0:5] 0\")\n    sample()\n\n"
  },
  {
    "path": "workspace/misc-examples/loess_smoother3.act",
    "content": "import numpy\nimport math\n\n# run as follows:\n\n# script -q /dev/null examples/loess_smoother3 104 52 | gnuplot\n\n# first command line argument: nr of weeks shown in window.\n# second command line argument: nr of weeks in \"loess window\", i.e. nr of neighboring observtions used for each smoothed value.\n\ndef loess(x, y, xin, win):\n    xd = numpy.abs(xin[:,numpy.newaxis] - x)\n    q = xd/numpy.partition(xd,win)[:,win][:,numpy.newaxis]\n    w  = numpy.clip(q, 0.0, 1.0)\n    ws  = (1.0 - w ** 3.0) ** 3.0\n    a00 = numpy.sum(ws,1)\n    a01 = numpy.dot(ws, x)\n    a11 = numpy.dot(ws, x*x)\n    b0  = numpy.dot(ws, y)\n    b1  = numpy.dot(ws, x*y)\n    det = a00*a11-a01*a01\n    return ((a11*b0 - a01*b1) + (-a01*b0 + a00*b1)*xin)/det\n\nglobalnoise  = numpy.unirandfloat(-0.5, 0.5, 10000)\n      \ndef sample(t0, n, n0, w):\n    t1 = t0+float(n)/52.0\n    time         = numpy.linspace(t0,t1,n)\n    trend        = 2.0 + 0.1 * time\n    periodic     = 0.5 * math.sin (6.2832 * time)\n    noise        = globalnoise[n0:n0+n:1]\n    observation  = trend + periodic + noise\n\n    smooth = loess(time,observation,time,w)\n    print(\"clear\\n$data <<EOD\")\n    for i in range(n):\n       print(time[i],observation[i],smooth[i])\n    print(\"EOD\")\n    print(\"plot [\",t0,\":\",t1,\"][0:5] \\'$data\\' using 1:2 with lines title \\\"raw data\\\", \\\\\")\n    print(\"\\'$data\\' using 1:3 with lines title \\\"loess smoothed\\\"\")\n    after 4: sample(t0 + (t1-t0)/8,n,n0+n//8,w)\n    \nactor main(env):\n    print (\"set terminal aqua title \\\"Loess smoothening\\\"\")\n    print(\"set multiplot\\nplot  [0:1][0:5] 0\")\n    sample(0.0, int(env.argv[1]), 0, int(env.argv[2]))\n\n"
  },
  {
    "path": "workspace/misc-examples/loess_smoother4.act",
    "content": "import numpy\nimport math\n\n# run as follows:\n\n# script -q /dev/null examples/loess_smoother4 13 52 | gnuplot\n\n# first command line argument: nr of weeks shown in each sample. 8 consecutive samples are shown in window.\n# second command line argument: nr of weeks in \"loess window\", i.e. nr of neighboring observtions used for each smoothed value.\n\ndef loess(x, y, xin, win):\n    xd  = numpy.abs(xin[:,numpy.newaxis] - x)\n    q   = xd/numpy.partition(xd,win)[:,win][:,numpy.newaxis]\n    w   = numpy.clip(q, 0.0, 1.0)\n    ws  = (1.0 - w ** 3.0) ** 3.0\n    a00 = numpy.sum(ws,1)\n    a01 = numpy.dot(ws, x)\n    a11 = numpy.dot(ws, x*x)\n    b0  = numpy.dot(ws, y)\n    b1  = numpy.dot(ws, x*y)\n    det = a00*a11-a01*a01\n    return ((a11*b0 - a01*b1) + (-a01*b0 + a00*b1)*xin)/det\n\n          \nactor sampler(sample_size, report):\n    def sample(t0, n0):\n        t1           = t0+float(sample_size)/52.0\n        time         = numpy.linspace(t0,t1,sample_size)\n        trend        = 2.0 + 0.1 * time\n        periodic     = 0.5 * math.sin (6.2832 * time)\n        noise        = numpy.unirandfloat(-0.5, 0.5, sample_size);\n        observation  = trend + periodic + noise\n        report(time, observation)\n        after 4: sample(t1, n0+sample_size)\n\n    sample(0.0, 0)\n\n\nactor analyzer(sample_size, loess_win_size):\n    var xsamples = []\n    var ysamples = []\n\n    nullsample   = numpy.zeros(sample_size)\n    width        = float(sample_size)/52.0;\n\n    def add_sample(x, y):\n       xsamples.append(x)\n       ysamples.append(y)\n       del xsamples[0]\n       del ysamples[0]\n       time        = numpy.concatenate(xsamples)\n       observation = numpy.concatenate(ysamples)\n       smooth      = loess(time,observation,time,loess_win_size)\n       print(\"clear\\n$data <<EOD\")\n       for i in range(8*sample_size):\n           print(time[i],observation[i],smooth[i])\n       print(\"EOD\")\n       t0 = numpy.scalar(time[0])\n       t1 = t0 + 8*width\n       print(\"plot [\",t0,\":\",t1,\"][0:5] \\'$data\\' using 1:2 with lines title \\\"raw data\\\", \\\\\")\n       print(\"\\'$data\\' using 1:3 with lines title \\\"loess smoothed\\\"\")\n\n    for i in range(8,0,-1):\n       xsamples.append(numpy.linspace(-float(i)*width, -float(i-1)*width, sample_size))\n       ysamples.append(nullsample)\n       \n\nactor main(env):\n  sample_size = int(env.argv[1])\n  loess_win_size =  int(env.argv[2])\n  a = analyzer(sample_size, loess_win_size)\n  s = sampler(sample_size, a.add_sample)\n\n"
  },
  {
    "path": "workspace/misc-examples/loess_smoother5.act",
    "content": "import numpy\nimport math\nfrom numpy import ndarray\n\n# run as follows:\n\n# script -q /dev/null examples/loess_smoother5 312 104 | gnuplot\n\n# first command line argument:  nr of weeks shown in window. 1/8 of this number is size of the new sample introduced in each step.\n# second command line argument: nr of weeks to be used in \"loess window\" for long term trend. \n\ndef loess(x, y, xin, win):\n    xd  = numpy.abs(xin[:,numpy.newaxis] - x)\n    q   = xd/numpy.partition(xd,win)[:,win][:,numpy.newaxis]\n    w   = numpy.clip(q, 0, 1)\n    ws  = (1.0 - w ** 3.0) ** 3.0\n    a00 = numpy.sum(ws, 1)\n    a01 = numpy.dot(ws, x)\n    a11 = numpy.dot(ws, x*x)\n    b0  = numpy.dot(ws, y)\n    b1  = numpy.dot(ws, x*y)\n    det = a00*a11-a01*a01\n    return ((a11*b0 - a01*b1) + (-a01*b0 + a00*b1)*xin)/det\n\ndef decompose(observed, time, period, lo_window_frac): \n    n                = len(observed)\n    phase            = n % period\n    trend            = loess(time, observed, time, int(lo_window_frac * float(n)))\n    detrended        = observed - trend\n    detrended_smooth = loess(time, detrended, time, period//3)                                 # smoothen over small window to get nicer periodic\n    period_averages  = numpy.mean(detrended_smooth[:n - phase:].reshape([n//period,period]),0) # reshape to get one period per row, do mean over columns\n    period_averages  -= numpy.mean(period_averages,None)\n    seasonal         = numpy.tile(period_averages, n//period + 1)[:n:]\n    residual         = detrended - seasonal\n    \n    return (trend, seasonal, residual, period_averages, phase) \n          \nactor analyzer(window_size, loess_win_size):\n    var time        = numpy.linspace(-float(window_size)/52, 0, window_size)\n    var observation = numpy.zeros(window_size)\n\n    def add_sample(x, y):\n       time        = numpy.concatenate([time[len(x):],x])\n       observation = numpy.concatenate([observation[len(y):],y])\n       trend, seasonal, resid, periodic, phase = decompose(observation, time, 52, 0.6)\n       print(\"clear\\n$data <<EOD\")\n       for i in range(window_size):\n           print(time[i], observation[i], trend[i], seasonal[i], resid[i])\n       print(\"EOD\")\n       t0 = numpy.scalar(time[0])\n       t1 = t0 + float(window_size)/52\n       print(\"plot [\",t0,\":\",t1,\"][-1:5] \\'$data\\' using 1:2 with lines title \\\"observations\\\", \\\\\")\n       print(\"\\'$data\\' using 1:3 with lines title \\\"trend\\\", \\\\\")\n       print(\"\\'$data\\' using 1:4 with lines title \\\"periodic\\\", \\\\\")\n       print(\"\\'$data\\' using 1:5 with lines title \\\"residual\\\"\")\n\nactor sampler(sample_size, report):\n    var t0 = 0\n\n    def _sample():\n        t1           = t0+float(sample_size)/52\n        time         = numpy.linspace(t0, t1, sample_size)\n        trend        = 2.0 + 0.1 * time\n        periodic     = 0.5 * math.sin (6.2832 * time)\n        noise        = numpy.unirandfloat(-0.5, 0.5, sample_size)\n        observation  = trend + periodic + noise\n        t0           = t1\n        report(time, observation)\n        after 4: _sample()\n\n    _sample()\n\nactor main(env):\n    if len(env.argv) != 3:\n        print(\"usage: loess_smoother5 >weeks in graph> <weeks in loess_window>\")\n        env.exit(0)\n    win_width = int(env.argv[1])\n    loess_win_width = int(env.argv[2])\n    a = analyzer(win_width, loess_win_width)\n    s = sampler(win_width//8, a.add_sample)\n\n"
  },
  {
    "path": "workspace/misc-examples/numpyfns.act",
    "content": "import numpy\nimport math\n\nactor main(env):\n  a = numpy.arange(20)\n  b = numpy.tile(a,3)\n  print(b)\n  c = numpy.roll(a,-7)\n  print(c)\n  d = numpy.zeros(12)\n  print(d)\n  env.exit(0)\n  "
  },
  {
    "path": "workspace/misc-examples/timestest.act",
    "content": "actor main(env):\n   print([3,5] * 4)\n   print([3,5] * -3)\n   print(3 * 5)\n   print(7.5 * 2.5)\n   print(\"abc\" * 6)\n   print(\"abc\" * -1)\n   print(bytearray([65,67]) * 4)\n   \n\n   "
  },
  {
    "path": "workspace/upgrades/upgrade_v1.act",
    "content": "actor Counter(foo):\n    var a = 0\n    def get():\n        a += 1\n        return \"%s: %d\" % (foo, a)\n\nactor main(env):\n    var counter = Counter(\"banana\")\n    def _work():\n        msg = counter.get()\n        print(msg)\n        after 1: _work()\n    _work()\n"
  },
  {
    "path": "workspace/upgrades/upgrade_v2.act",
    "content": "actor Counter(foo):\n    var b = 0\n    def get():\n        b += 1\n        return \"%s: %d\" % (foo, b)\n\nactor main(env):\n    var counter = Counter(\"banana\")\n    def _work():\n        msg = counter.get()\n        print(msg)\n        after 1: _work()\n    _work()\n"
  }
]